diff --git a/src/app.py b/src/app.py index 45637ac..13b8860 100644 --- a/src/app.py +++ b/src/app.py @@ -3,11 +3,12 @@ import logging.config import yaml from fasthtml import serve +from myfasthtml.controls.InstancesDebugger import InstancesDebugger from myfasthtml.controls.Layout import Layout from myfasthtml.controls.TabsManager import TabsManager from myfasthtml.controls.helpers import Ids, mk -from myfasthtml.core.commands import Command from myfasthtml.core.instances import InstancesManager, RootInstance +from myfasthtml.icons.carbon import volume_object_storage from myfasthtml.myfastapp import create_app with open('logging.yaml', 'r') as f: @@ -31,14 +32,17 @@ def index(session): layout.set_footer("Goodbye World") tabs_manager = TabsManager(layout, _id=f"{Ids.TabsManager}-main") - + instances_debugger = InstancesManager.get(session, Ids.InstancesDebugger, InstancesDebugger, layout) btn_show_right_drawer = mk.button("show", - command=Command("ShowRightDrawer", - "Show Right Drawer", - layout.toggle_drawer, "right"), + command=layout.commands.toggle_drawer("right"), id="btn_show_right_drawer_id") + + btn_show_instances_debugger = mk.icon(volume_object_storage, + command=tabs_manager.commands.add_tab("Instances", instances_debugger), + id=instances_debugger.get_id()) layout.header_left.add(tabs_manager.add_tab_btn()) layout.header_right.add(btn_show_right_drawer) + layout.left_drawer.add(btn_show_instances_debugger) layout.set_main(tabs_manager) return layout diff --git a/src/myfasthtml/controls/InstancesDebugger.py b/src/myfasthtml/controls/InstancesDebugger.py new file mode 100644 index 0000000..a467b3c --- /dev/null +++ b/src/myfasthtml/controls/InstancesDebugger.py @@ -0,0 +1,26 @@ +from myfasthtml.controls.VisNetwork import VisNetwork +from myfasthtml.controls.helpers import Ids +from myfasthtml.core.instances import SingleInstance, InstancesManager +from myfasthtml.core.network_utils import from_parent_child_list + + +class InstancesDebugger(SingleInstance): + def __init__(self, session, parent, _id=None): + super().__init__(session, Ids.InstancesDebugger, parent) + + def render(self): + instances = self._get_instances() + nodes, edges = from_parent_child_list(instances, + id_getter=lambda x: x.get_id(), + label_getter=lambda x: x.get_prefix(), + parent_getter=lambda x: x.get_parent().get_id() if x.get_parent() else None + ) + + vis_network = VisNetwork(self, nodes=nodes, edges=edges) + return vis_network + + def _get_instances(self): + return list(InstancesManager.instances.values()) + + def __ft__(self): + return self.render() diff --git a/src/myfasthtml/controls/Layout.py b/src/myfasthtml/controls/Layout.py index 4488711..209407b 100644 --- a/src/myfasthtml/controls/Layout.py +++ b/src/myfasthtml/controls/Layout.py @@ -35,7 +35,7 @@ class LayoutState(DbObject): class Commands(BaseCommands): def toggle_drawer(self, side: Literal["left", "right"]): - return Command("ToggleDrawer", "Toggle main layout drawer", self._owner.toggle_drawer, side) + return Command("ToggleDrawer", f"Toggle {side} layout drawer", self._owner.toggle_drawer, side) def update_drawer_width(self, side: Literal["left", "right"]): """ diff --git a/src/myfasthtml/controls/TabsManager.py b/src/myfasthtml/controls/TabsManager.py index 696c70c..88d13de 100644 --- a/src/myfasthtml/controls/TabsManager.py +++ b/src/myfasthtml/controls/TabsManager.py @@ -115,6 +115,11 @@ class TabsManager(MultipleInstance): if auto_increment: label = f"{label}_{self._get_tab_count()}" component = component or VisNetwork(self, nodes=vis_nodes, edges=vis_edges) + + tab_id = self._tab_already_exists(label, component) + if tab_id: + return self.show_tab(tab_id) + tab_id = self.add_tab(label, component) return ( self._mk_tabs_controller(), @@ -145,14 +150,7 @@ class TabsManager(MultipleInstance): component_id = component.get_id() # Check if a tab with the same component_type, component_id AND label already exists - existing_tab_id = None - if component_id is not None: - for tab_id, tab_data in state.tabs.items(): - if (tab_data.get('component_type') == component_type and - tab_data.get('component_id') == component_id and - tab_data.get('label') == label): - existing_tab_id = tab_id - break + existing_tab_id = self._tab_already_exists(label, component) if existing_tab_id: # Update existing tab (only the component instance in memory) @@ -365,6 +363,22 @@ class TabsManager(MultipleInstance): hx_swap_oob=f"beforeend:#{self._id}-content-wrapper", ) + def _tab_already_exists(self, label, component): + if not isinstance(component, BaseInstance): + return None + + component_type = component.get_prefix() if isinstance(component, BaseInstance) else type(component).__name__ + component_id = component.get_id() + + if component_id is not None: + for tab_id, tab_data in self._state.tabs.items(): + if (tab_data.get('component_type') == component_type and + tab_data.get('component_id') == component_id and + tab_data.get('label') == label): + return tab_id + + return None + def _get_tab_list(self): return [self._state.tabs[tab_id] for tab_id in self._state.tabs_order if tab_id in self._state.tabs] diff --git a/src/myfasthtml/controls/VisNetwork.py b/src/myfasthtml/controls/VisNetwork.py index d565469..d7fa9f3 100644 --- a/src/myfasthtml/controls/VisNetwork.py +++ b/src/myfasthtml/controls/VisNetwork.py @@ -50,7 +50,7 @@ class VisNetwork(MultipleInstance): state.options = options self._state.update(state) - + def render(self): # Serialize nodes and edges to JSON diff --git a/src/myfasthtml/controls/helpers.py b/src/myfasthtml/controls/helpers.py index f0919d7..7a94d00 100644 --- a/src/myfasthtml/controls/helpers.py +++ b/src/myfasthtml/controls/helpers.py @@ -10,6 +10,7 @@ class Ids: AuthProxy = "mf-auth-proxy" Boundaries = "mf-boundaries" DbManager = "mf-dbmanager" + InstancesDebugger = "mf-instances-debugger" Layout = "mf-layout" Root = "mf-root" Search = "mf-search" diff --git a/src/myfasthtml/core/instances.py b/src/myfasthtml/core/instances.py index f022c7c..e12cf24 100644 --- a/src/myfasthtml/core/instances.py +++ b/src/myfasthtml/core/instances.py @@ -34,7 +34,9 @@ class BaseInstance: def get_prefix(self): return self._prefix - + + def get_parent(self): + return self._parent class SingleInstance(BaseInstance): """ diff --git a/src/myfasthtml/icons/carbon.py b/src/myfasthtml/icons/carbon.py index f2bff75..744e878 100644 --- a/src/myfasthtml/icons/carbon.py +++ b/src/myfasthtml/icons/carbon.py @@ -385,7 +385,7 @@ down_to_bottom = NotStr('''''') thunderstorm_scattered_night = NotStr(''' ''') letter_uu = NotStr(''' ''') -continue = NotStr(''' ''') +continue_ = NotStr(''' ''') login = NotStr(''' ''') favorite = NotStr('''''') cd_archive = NotStr(''' ''')