Files
MyFastHtml/src/myfasthtml/controls/Menu.py

71 lines
2.0 KiB
Python

import inspect
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(attr := getattr(commands_obj, name))
and len(inspect.signature(attr).parameters) == 0
]
return {
c.name: c for c in [getattr(commands_obj, name)() for name in callables]
}
def _mk_menu(self, command_name):
if not isinstance(command_name, str):
return 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 mb-1"
),
id=self._id
)
def __ft__(self):
return self.render()