Improved command management to reduce the number of instances

This commit is contained in:
2025-12-21 11:14:02 +01:00
parent 9f69a6bc5b
commit 2f808ed226
8 changed files with 100 additions and 19 deletions

View File

@@ -57,7 +57,7 @@ class DataGrid(MultipleInstance):
def render(self):
return Div(
NotStr(self._state.html),
NotStr(self._state.html) if self._state.html else "Content lost !",
id=self._id
)

View File

@@ -1,3 +1,4 @@
import uuid
from dataclasses import dataclass
import pandas as pd
@@ -10,7 +11,7 @@ from myfasthtml.controls.Panel import Panel
from myfasthtml.controls.TabsManager import TabsManager
from myfasthtml.controls.TreeView import TreeView, TreeNode
from myfasthtml.controls.helpers import mk
from myfasthtml.core.commands import Command, LambdaCommand
from myfasthtml.core.commands import Command
from myfasthtml.core.dbmanager import DbObject
from myfasthtml.core.instances import MultipleInstance, InstancesManager
from myfasthtml.icons.fluent_p1 import table_add20_regular
@@ -19,6 +20,7 @@ from myfasthtml.icons.fluent_p3 import folder_open20_regular
@dataclass
class DocumentDefinition:
document_id: str
namespace: str
name: str
type: str
@@ -30,7 +32,7 @@ class DataGridsState(DbObject):
def __init__(self, owner, name=None):
super().__init__(owner, name=name)
with self.initializing():
self.elements: list = []
self.elements: list = [DocumentDefinition]
class Commands(BaseCommands):
@@ -61,7 +63,11 @@ class Commands(BaseCommands):
self._owner.clear_tree).htmx(target=f"#{self._owner._tree.get_id()}")
def show_document(self):
return LambdaCommand(self._owner, lambda: print("show_document"))
return Command("ShowDocument",
"Show document",
self._owner,
self._owner.select_document,
key="SelectNode")
class DataGridsManager(MultipleInstance):
@@ -89,18 +95,29 @@ class DataGridsManager(MultipleInstance):
dg = DataGrid(self._tabs_manager)
dg.set_html(html)
document = DocumentDefinition(
document_id=str(uuid.uuid4()),
namespace=file_upload.get_file_basename(),
name=file_upload.get_sheet_name(),
type="excel",
tab_id=tab_id,
datagrid_id=dg.get_id()
)
self._state.elements = self._state.elements + [document]
self._state.elements = self._state.elements + [document] # do not use append() other it won't be saved
parent_id = self._tree.ensure_path(document.namespace)
tree_node = TreeNode(label=document.name, type="excel", parent=parent_id)
self._tree.add_node(tree_node, parent_id=parent_id)
return self._mk_tree(), self._tabs_manager.change_tab_content(tab_id, document.name, Panel(self).set_main(dg))
def select_document(self, node_id):
document_id = self._tree.get_bag(node_id)
try:
document = next(filter(lambda x: x.document_id == document_id, self._state.elements))
dg = DataGrid(self._tabs_manager, _id=document.datagrid_id)
return self._tabs_manager.show_or_create_tab(document.tab_id, document.name, dg)
except StopIteration:
# the selected node is not a document (it's a folder)
return None
def clear_tree(self):
self._state.elements = []
self._tree.clear()
@@ -117,7 +134,11 @@ class DataGridsManager(MultipleInstance):
tree = TreeView(self, _id="-treeview")
for element in self._state.elements:
parent_id = tree.ensure_path(element.namespace)
tree.add_node(TreeNode(label=element.name, type=element.type, parent=parent_id, id=element.datagrid_id))
tree.add_node(TreeNode(id=element.document_id,
label=element.name,
type=element.type,
parent=parent_id,
bag=element.document_id))
return tree
def render(self):

View File

@@ -40,7 +40,7 @@ class PanelIds:
@dataclass
class PanelConf:
left: bool = True
left: bool = False
right: bool = True

View File

@@ -58,29 +58,34 @@ class TabsManagerState(DbObject):
class Commands(BaseCommands):
def show_tab(self, tab_id):
return Command(f"{self._prefix}ShowTab",
return Command(f"ShowTab",
"Activate or show a specific tab",
self._owner,
self._owner.show_tab,
args=[tab_id,
True,
False]).htmx(target=f"#{self._id}-controller", swap="outerHTML")
False],
key=f"{self._owner.get_full_id()}-ShowTab-{tab_id}",
).htmx(target=f"#{self._id}-controller", swap="outerHTML")
def close_tab(self, tab_id):
return Command(f"{self._prefix}CloseTab",
return Command(f"CloseTab",
"Close a specific tab",
self._owner,
self._owner.close_tab,
args=[tab_id]).htmx(target=f"#{self._id}-controller", swap="outerHTML")
kwargs={"tab_id": tab_id},
).htmx(target=f"#{self._id}-controller", swap="outerHTML")
def add_tab(self, label: str, component: Any, auto_increment=False):
return Command(f"{self._prefix}AddTab",
return Command(f"AddTab",
"Add a new tab",
self._owner,
self._owner.on_new_tab,
args=[label,
component,
auto_increment]).htmx(target=f"#{self._id}-controller", swap="outerHTML")
auto_increment],
key="#{id-name-args}",
).htmx(target=f"#{self._id}-controller", swap="outerHTML")
class TabsManager(MultipleInstance):
@@ -148,6 +153,13 @@ class TabsManager(MultipleInstance):
tab_id = self.create_tab(label, component)
return self.show_tab(tab_id, oob=False)
def show_or_create_tab(self, tab_id, label, component, activate=True):
logger.debug(f"show_or_create_tab {tab_id=}, {label=}, {component=}, {activate=}")
if tab_id not in self._state.tabs:
self._add_or_update_tab(tab_id, label, component, activate)
return self.show_tab(tab_id, activate=activate, oob=True)
def create_tab(self, label: str, component: Any, activate: bool = True) -> str:
"""
Add a new tab or update an existing one with the same component type, ID and label.

View File

@@ -267,6 +267,12 @@ class TreeView(MultipleInstance):
self._state.update(state)
return self
def get_bag(self, node_id: str):
try:
return self._state.items[node_id].bag
except KeyError:
return None
def _toggle_node(self, node_id: str):
"""Toggle expand/collapse state of a node."""
if node_id in self._state.opened: