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('''''')