Added menu management
This commit is contained in:
@@ -7,10 +7,12 @@ from fasthtml.components import Div
|
|||||||
from fasthtml.xtend import Script
|
from fasthtml.xtend import Script
|
||||||
|
|
||||||
from myfasthtml.controls.BaseCommands import BaseCommands
|
from myfasthtml.controls.BaseCommands import BaseCommands
|
||||||
|
from myfasthtml.controls.Menu import Menu, MenuConf
|
||||||
from myfasthtml.controls.Query import Query, QueryConf
|
from myfasthtml.controls.Query import Query, QueryConf
|
||||||
from myfasthtml.core.commands import Command
|
from myfasthtml.core.commands import Command
|
||||||
from myfasthtml.core.dbmanager import DbObject
|
from myfasthtml.core.dbmanager import DbObject
|
||||||
from myfasthtml.core.instances import MultipleInstance
|
from myfasthtml.core.instances import MultipleInstance
|
||||||
|
from myfasthtml.icons.fluent import arrow_reset20_regular
|
||||||
|
|
||||||
logger = logging.getLogger("HierarchicalCanvasGraph")
|
logger = logging.getLogger("HierarchicalCanvasGraph")
|
||||||
|
|
||||||
@@ -91,10 +93,11 @@ class Commands(BaseCommands):
|
|||||||
This command can be used to fix stuck/frozen canvas by resetting zoom/pan state.
|
This command can be used to fix stuck/frozen canvas by resetting zoom/pan state.
|
||||||
"""
|
"""
|
||||||
return Command(
|
return Command(
|
||||||
"ResetTransform",
|
"ResetView",
|
||||||
"Reset view transform",
|
"Reset view transform",
|
||||||
self._owner,
|
self._owner,
|
||||||
self._owner.handle_reset_view
|
self._owner.handle_reset_view,
|
||||||
|
icon=arrow_reset20_regular
|
||||||
).htmx(target=f"#{self._id}")
|
).htmx(target=f"#{self._id}")
|
||||||
|
|
||||||
|
|
||||||
@@ -136,6 +139,9 @@ class HierarchicalCanvasGraph(MultipleInstance):
|
|||||||
self._query.bind_command("QueryChanged", self.commands.apply_filter())
|
self._query.bind_command("QueryChanged", self.commands.apply_filter())
|
||||||
self._query.bind_command("CancelQuery", self.commands.apply_filter())
|
self._query.bind_command("CancelQuery", self.commands.apply_filter())
|
||||||
|
|
||||||
|
# Add Menu
|
||||||
|
self._menu = Menu(self, conf=MenuConf(["ResetView"]))
|
||||||
|
|
||||||
logger.debug(f"HierarchicalCanvasGraph created with id={self._id}, "
|
logger.debug(f"HierarchicalCanvasGraph created with id={self._id}, "
|
||||||
f"nodes={len(conf.nodes)}, edges={len(conf.edges)}")
|
f"nodes={len(conf.nodes)}, edges={len(conf.edges)}")
|
||||||
|
|
||||||
@@ -341,8 +347,11 @@ class HierarchicalCanvasGraph(MultipleInstance):
|
|||||||
options_json = json.dumps(options, indent=2)
|
options_json = json.dumps(options, indent=2)
|
||||||
|
|
||||||
return Div(
|
return Div(
|
||||||
# Query filter bar
|
Div(
|
||||||
self._query,
|
self._query,
|
||||||
|
self._menu,
|
||||||
|
cls="flex justify-between m-2"
|
||||||
|
),
|
||||||
|
|
||||||
# Canvas element (sized by JS to fill container)
|
# Canvas element (sized by JS to fill container)
|
||||||
Div(
|
Div(
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ default_icons = {
|
|||||||
False: checkbox_unchecked20_regular,
|
False: checkbox_unchecked20_regular,
|
||||||
|
|
||||||
"Brain": brain_circuit20_regular,
|
"Brain": brain_circuit20_regular,
|
||||||
|
"QuestionMark" : question20_regular,
|
||||||
|
|
||||||
# TreeView icons
|
# TreeView icons
|
||||||
"TreeViewFolder": folder20_regular,
|
"TreeViewFolder": folder20_regular,
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from fasthtml.components import Div, Button
|
from fasthtml.components import Div
|
||||||
|
|
||||||
from myfasthtml.controls.HierarchicalCanvasGraph import HierarchicalCanvasGraph, HierarchicalCanvasGraphConf
|
from myfasthtml.controls.HierarchicalCanvasGraph import HierarchicalCanvasGraph, HierarchicalCanvasGraphConf
|
||||||
from myfasthtml.controls.Panel import Panel
|
from myfasthtml.controls.Panel import Panel
|
||||||
from myfasthtml.controls.Properties import Properties
|
from myfasthtml.controls.Properties import Properties
|
||||||
from myfasthtml.controls.helpers import mk
|
|
||||||
from myfasthtml.core.commands import Command
|
from myfasthtml.core.commands import Command
|
||||||
from myfasthtml.core.instances import SingleInstance, UniqueInstance, MultipleInstance, InstancesManager
|
from myfasthtml.core.instances import SingleInstance, UniqueInstance, MultipleInstance, InstancesManager
|
||||||
|
|
||||||
@@ -44,15 +43,7 @@ class InstancesDebugger(SingleInstance):
|
|||||||
)
|
)
|
||||||
self._canvas_graph = HierarchicalCanvasGraph(self, conf=graph_conf, _id="-canvas-graph")
|
self._canvas_graph = HierarchicalCanvasGraph(self, conf=graph_conf, _id="-canvas-graph")
|
||||||
|
|
||||||
# Debug button to reset transform
|
|
||||||
reset_btn = mk.button(
|
|
||||||
"🔄 Reset View",
|
|
||||||
command=self._canvas_graph.commands.reset_view(),
|
|
||||||
cls="btn btn-sm btn-ghost"
|
|
||||||
)
|
|
||||||
|
|
||||||
main_content = Div(
|
main_content = Div(
|
||||||
Div(reset_btn, cls="p-2 flex justify-end bg-base-200"),
|
|
||||||
self._canvas_graph,
|
self._canvas_graph,
|
||||||
cls="flex flex-col h-full"
|
cls="flex flex-col h-full"
|
||||||
)
|
)
|
||||||
|
|||||||
65
src/myfasthtml/controls/Menu.py
Normal file
65
src/myfasthtml/controls/Menu.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from fasthtml.components import Div
|
||||||
|
|
||||||
|
from myfasthtml.controls.IconsHelper import IconsHelper
|
||||||
|
from myfasthtml.controls.helpers import mk
|
||||||
|
from myfasthtml.core.dbmanager import DbObject
|
||||||
|
from myfasthtml.core.instances import MultipleInstance
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MenuConf:
|
||||||
|
fixed_items: list = field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
|
class MenuState(DbObject):
|
||||||
|
def __init__(self, owner, save_state):
|
||||||
|
with self.initializing():
|
||||||
|
super().__init__(owner, save_state=save_state)
|
||||||
|
self.last_used: Optional[list] = None
|
||||||
|
|
||||||
|
|
||||||
|
class Menu(MultipleInstance):
|
||||||
|
def __init__(self, parent, conf=None, save_state=True, _id=None):
|
||||||
|
super().__init__(parent, _id=_id)
|
||||||
|
self.conf = conf or MenuConf()
|
||||||
|
self._state = MenuState(self, save_state=save_state)
|
||||||
|
self.usable_commands = self._get_parent_commands()
|
||||||
|
|
||||||
|
def _get_parent_commands(self):
|
||||||
|
commands_obj = self._parent.commands
|
||||||
|
|
||||||
|
callables = [
|
||||||
|
name
|
||||||
|
for name in dir(commands_obj)
|
||||||
|
if not name.startswith("_")
|
||||||
|
and callable(getattr(commands_obj, name))
|
||||||
|
]
|
||||||
|
|
||||||
|
return {
|
||||||
|
c.name: c for c in [getattr(commands_obj, name)() for name in callables]
|
||||||
|
}
|
||||||
|
|
||||||
|
def _mk_menu(self, command_name):
|
||||||
|
command = self.usable_commands.get(command_name)
|
||||||
|
return mk.icon(command.icon or IconsHelper.get("QuestionMark"),
|
||||||
|
command=command,
|
||||||
|
tooltip=command.description)
|
||||||
|
|
||||||
|
def render(self):
|
||||||
|
return Div(
|
||||||
|
Div(
|
||||||
|
*[self._mk_menu(command_name) for command_name in self.conf.fixed_items],
|
||||||
|
*(
|
||||||
|
Div("|"),
|
||||||
|
*[self._mk_menu(command_name) for command_name in self._state.last_used[:3]]
|
||||||
|
) if self._state.last_used else [],
|
||||||
|
cls="flex"
|
||||||
|
),
|
||||||
|
id=self._id
|
||||||
|
)
|
||||||
|
|
||||||
|
def __ft__(self):
|
||||||
|
return self.render()
|
||||||
@@ -85,10 +85,12 @@ class Command:
|
|||||||
args: list = None,
|
args: list = None,
|
||||||
kwargs: dict = None,
|
kwargs: dict = None,
|
||||||
key=None,
|
key=None,
|
||||||
|
icon=None,
|
||||||
auto_register=True):
|
auto_register=True):
|
||||||
self.id = uuid.uuid4()
|
self.id = uuid.uuid4()
|
||||||
self.name = name
|
self.name = name
|
||||||
self.description = description
|
self.description = description
|
||||||
|
self.icon = icon
|
||||||
self.owner = owner
|
self.owner = owner
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
self.default_args = args or []
|
self.default_args = args or []
|
||||||
|
|||||||
Reference in New Issue
Block a user