From 3de9aff15c84530c71dedb539225384c9a8d553f Mon Sep 17 00:00:00 2001 From: Kodjo Sossouvi Date: Sun, 16 Nov 2025 23:06:00 +0100 Subject: [PATCH] Added CommandsDebugger --- src/app.py | 10 +++++- src/myfasthtml/controls/CommandsDebugger.py | 40 +++++++++++++++++++++ src/myfasthtml/controls/helpers.py | 1 + src/myfasthtml/core/commands.py | 5 +++ src/myfasthtml/core/instances_helper.py | 4 +++ 5 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/myfasthtml/controls/CommandsDebugger.py diff --git a/src/app.py b/src/app.py index fde56f7..04aebd5 100644 --- a/src/app.py +++ b/src/app.py @@ -3,6 +3,7 @@ import logging.config import yaml from fasthtml import serve +from myfasthtml.controls.CommandsDebugger import CommandsDebugger from myfasthtml.controls.InstancesDebugger import InstancesDebugger from myfasthtml.controls.Layout import Layout from myfasthtml.controls.TabsManager import TabsManager @@ -32,19 +33,26 @@ 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=layout.commands.toggle_drawer("right"), id="btn_show_right_drawer_id") + instances_debugger = InstancesManager.get(session, Ids.InstancesDebugger, InstancesDebugger, layout) btn_show_instances_debugger = mk.label("Instances", icon=volume_object_storage, command=tabs_manager.commands.add_tab("Instances", instances_debugger), id=instances_debugger.get_id()) + commands_debugger = InstancesManager.get(session, Ids.CommandsDebugger, CommandsDebugger, layout) + btn_show_commands_debugger = mk.label("Commands", + icon=None, + command=tabs_manager.commands.add_tab("Commands", commands_debugger), + id=commands_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.left_drawer.add(btn_show_commands_debugger) layout.set_main(tabs_manager) return layout diff --git a/src/myfasthtml/controls/CommandsDebugger.py b/src/myfasthtml/controls/CommandsDebugger.py new file mode 100644 index 0000000..5ffa77d --- /dev/null +++ b/src/myfasthtml/controls/CommandsDebugger.py @@ -0,0 +1,40 @@ +from myfasthtml.controls.VisNetwork import VisNetwork +from myfasthtml.controls.helpers import Ids +from myfasthtml.core.commands import CommandsManager +from myfasthtml.core.instances import SingleInstance +from myfasthtml.core.network_utils import from_parent_child_list + + +class CommandsDebugger(SingleInstance): + def __init__(self, session, parent, _id=None): + super().__init__(session, Ids.CommandsDebugger, parent) + + def render(self): + commands = self._get_commands() + nodes, edges = from_parent_child_list(commands, + id_getter=lambda x: str(x.id), + label_getter=lambda x: x.name, + parent_getter=lambda x: str(self.get_command_parent(x)) + ) + + vis_network = VisNetwork(self, nodes=nodes, edges=edges) + return vis_network + + @staticmethod + def get_command_parent(command): + if (ft := command.get_ft()) is None: + return None + if hasattr(ft, "get_id") and callable(ft.get_id): + return ft.get_id() + if hasattr(ft, "get_prefix") and callable(ft.get_prefix): + return ft.get_prefix() + if hasattr(ft, "attrs"): + return ft.attrs.get("id", None) + + return None + + def _get_commands(self): + return list(CommandsManager.commands.values()) + + def __ft__(self): + return self.render() diff --git a/src/myfasthtml/controls/helpers.py b/src/myfasthtml/controls/helpers.py index 0d90568..bfd7c4b 100644 --- a/src/myfasthtml/controls/helpers.py +++ b/src/myfasthtml/controls/helpers.py @@ -9,6 +9,7 @@ class Ids: # Please keep the alphabetical order AuthProxy = "mf-auth-proxy" Boundaries = "mf-boundaries" + CommandsDebugger = "mf-commands-debugger" DbManager = "mf-dbmanager" InstancesDebugger = "mf-instances-debugger" Layout = "mf-layout" diff --git a/src/myfasthtml/core/commands.py b/src/myfasthtml/core/commands.py index ed0e60e..ca18ad9 100644 --- a/src/myfasthtml/core/commands.py +++ b/src/myfasthtml/core/commands.py @@ -30,6 +30,7 @@ class BaseCommand: self.description = description self._htmx_extra = {} self._bindings = [] + self._ft = None # register the command CommandsManager.register(self) @@ -68,6 +69,7 @@ class BaseCommand: :param ft: :return: """ + self._ft = ft htmx = self.get_htmx_params() ft.attrs |= htmx return ft @@ -95,6 +97,9 @@ class BaseCommand: def url(self): return f"{ROUTE_ROOT}{Routes.Commands}?c_id={self.id}" + def get_ft(self): + return self._ft + def __str__(self): return f"Command({self.name})" diff --git a/src/myfasthtml/core/instances_helper.py b/src/myfasthtml/core/instances_helper.py index 916381b..d7d34a3 100644 --- a/src/myfasthtml/core/instances_helper.py +++ b/src/myfasthtml/core/instances_helper.py @@ -1,5 +1,6 @@ import logging +from myfasthtml.controls.CommandsDebugger import CommandsDebugger from myfasthtml.controls.InstancesDebugger import InstancesDebugger from myfasthtml.controls.VisNetwork import VisNetwork from myfasthtml.controls.helpers import Ids @@ -17,6 +18,9 @@ class InstancesHelper: elif component_type == Ids.InstancesDebugger: return InstancesManager.get(parent.get_session(), instance_id, InstancesDebugger, parent.get_session(), parent, instance_id) + elif component_type == Ids.CommandsDebugger: + return InstancesManager.get(parent.get_session(), instance_id, + CommandsDebugger, parent.get_session(), parent, instance_id) logger.warning(f"Unknown component type: {component_type}") return None