Working version of DataGridColumnsManager.py where columns can be updated

This commit is contained in:
2026-01-25 21:40:32 +01:00
parent e31d9026ce
commit 05d4e5cd89
7 changed files with 702 additions and 34 deletions

View File

@@ -178,6 +178,7 @@ class DataGrid(MultipleInstance):
# add columns manager
self._columns_manager = DataGridColumnsManager(self)
self._columns_manager.bind_command("ToggleColumn", self.commands.on_column_changed())
self._columns_manager.bind_command("UpdateColumn", self.commands.on_column_changed())
# other definitions
self._mouse_support = {

View File

@@ -7,8 +7,9 @@ from myfasthtml.controls.Search import Search
from myfasthtml.controls.datagrid_objects import DataGridColumnState
from myfasthtml.controls.helpers import icons, mk
from myfasthtml.core.commands import Command
from myfasthtml.core.constants import ColumnType
from myfasthtml.core.instances import MultipleInstance
from myfasthtml.icons.fluent_p1 import chevron_right20_regular
from myfasthtml.icons.fluent_p1 import chevron_right20_regular, chevron_left20_regular
logger = logging.getLogger("DataGridColumnsManager")
@@ -20,6 +21,27 @@ class Commands(BaseCommands):
self._owner,
self._owner.toggle_column,
kwargs={"col_id": col_id}).htmx(swap="outerHTML", target=f"#tcolman_{self._id}-{col_id}")
def show_column_details(self, col_id):
return Command(f"ShowColumnDetails",
f"Show column details {col_id}",
self._owner,
self._owner.show_column_details,
kwargs={"col_id": col_id}).htmx(target=f"#{self._id}", swap="innerHTML")
def show_all_columns(self):
return Command(f"ShowAllColumns",
f"Show all columns",
self._owner,
self._owner.show_all_columns).htmx(target=f"#{self._id}", swap="innerHTML")
def update_column(self, col_id):
return Command(f"UpdateColumn",
f"Update column {col_id}",
self._owner,
self._owner.update_column,
kwargs={"col_id": col_id}
).htmx(target=f"#{self._id}", swap="innerHTML")
class DataGridColumnsManager(MultipleInstance):
@@ -31,41 +53,138 @@ class DataGridColumnsManager(MultipleInstance):
def columns(self):
return self._parent.get_state().columns
def toggle_column(self, col_id):
logger.debug(f"toggle_column {col_id=}")
def _get_col_def_from_col_id(self, col_id):
cols_defs = [c for c in self.columns if c.col_id == col_id]
if not cols_defs:
return None
else:
return cols_defs[0]
def toggle_column(self, col_id):
logger.debug(f"toggle_column {col_id=}")
col_def = self._get_col_def_from_col_id(col_id)
if col_def is None:
logger.debug(f" column '{col_id}' is not found.")
return Div(f"Column '{col_id}' not found")
col_def = cols_defs[0]
col_def.visible = not col_def.visible
self._parent.save_state()
return self.mk_column(col_def)
return self.mk_column_label(col_def)
def mk_column(self, col_def: DataGridColumnState):
def show_column_details(self, col_id):
logger.debug(f"show_column_details {col_id=}")
col_def = self._get_col_def_from_col_id(col_id)
if col_def is None:
logger.debug(f" column '{col_id}' is not found.")
return Div(f"Column '{col_id}' not found")
return self.mk_column_details(col_def)
def show_all_columns(self):
return self.mk_all_columns()
def update_column(self, col_id, client_response):
logger.debug(f"update_column {col_id=}, {client_response=}")
col_def = self._get_col_def_from_col_id(col_id)
if col_def is None:
logger.debug(f" column '{col_id}' is not found.")
else:
for k, v in client_response.items():
if not hasattr(col_def, k):
continue
if k == "visible":
col_def.visible = v == "on"
elif k == "type":
col_def.type = ColumnType(v)
elif k == "width":
col_def.width = int(v)
else:
setattr(col_def, k, v)
# save the new values
self._parent.save_state()
return self.mk_all_columns()
def mk_column_label(self, col_def: DataGridColumnState):
return Div(
mk.mk(
Input(type="checkbox", cls="checkbox checkbox-sm", checked=col_def.visible),
command=self.commands.toggle_column(col_def.col_id)
),
Div(
Div(mk.label(col_def.col_id, icon=icons.get(col_def.type, None), cls="ml-2")),
Div(mk.icon(chevron_right20_regular), cls="mr-2"),
cls="dt2-column-manager-label"
mk.mk(
Div(
Div(mk.label(col_def.col_id, icon=icons.get(col_def.type, None), cls="ml-2")),
Div(mk.icon(chevron_right20_regular), cls="mr-2"),
cls="dt2-column-manager-label"
),
command=self.commands.show_column_details(col_def.col_id)
),
cls="flex mb-1 items-center",
id=f"tcolman_{self._id}-{col_def.col_id}"
)
def render(self):
def mk_column_details(self, col_def: DataGridColumnState):
size = "sm"
return Div(
mk.label("Back", icon=chevron_left20_regular, command=self.commands.show_all_columns()),
Form(
Fieldset(
Label("Column Id"),
Input(name="col_id",
cls=f"input input-{size}",
value=col_def.col_id,
readonly=True),
Label("Title"),
Input(name="title",
cls=f"input input-{size}",
value=col_def.title),
Label("Visible"),
Input(name="visible",
type="checkbox",
cls=f"checkbox checkbox-{size}",
checked="true" if col_def.visible else None),
Label("type"),
Select(
*[Option(option.value, value=option.value, selected=option == col_def.type) for option in ColumnType],
name="type",
cls=f"select select-{size}",
value=col_def.title,
),
Label("Width"),
Input(name="width",
type="number",
cls=f"input input-{size}",
value=col_def.width),
legend="Column details",
cls="fieldset border-base-300 rounded-box"
),
mk.dialog_buttons(on_ok=self.commands.update_column(col_def.col_id),
on_cancel=self.commands.show_all_columns()),
cls="mb-1",
),
)
def mk_all_columns(self):
return Search(self,
items_names="Columns",
items=self.columns,
get_attr=lambda x: x.col_id,
template=self.mk_column,
template=self.mk_column_label,
max_height=None
)
def render(self):
return Div(
self.mk_all_columns(),
id=self._id,
)
def __ft__(self):
return self.render()

View File

@@ -1,4 +1,3 @@
from fastcore.xml import FT
from fasthtml.components import *
from myfasthtml.core.bindings import Binding
@@ -104,7 +103,7 @@ class mk:
command: Command | CommandTemplate = None,
binding: Binding = None,
**kwargs):
merged_cls = merge_classes("flex truncate items-center", cls, kwargs)
merged_cls = merge_classes("flex truncate items-center", "mf-button" if command else None, cls, kwargs)
icon_part = Span(icon, cls=f"mf-icon-{mk.convert_size(size)} mr-1") if icon else None
text_part = Span(text, cls=f"text-{size}")
return mk.mk(Label(icon_part, text_part, cls=merged_cls, **kwargs), command=command, binding=binding)