Working on DatagridFilter

This commit is contained in:
2026-01-21 22:33:17 +01:00
parent ca40333742
commit 872d110f07
3 changed files with 105 additions and 23 deletions

View File

@@ -72,6 +72,7 @@ class DatagridSettings(DbObject):
self.views_visible: bool = True
self.open_file_visible: bool = True
self.open_settings_visible: bool = True
self.text_size: str = "sm"
class Commands(BaseCommands):
@@ -255,21 +256,21 @@ class DataGrid(MultipleInstance):
if not filter_keyword_lower:
# OPTIMIZATION: Return plain HTML string instead of Label object
# Include "truncate text-sm" to match mk.label() behavior (ellipsis + font size)
return NotStr(f'<span class="{css_class} truncate text-sm">{value_str}</span>')
return NotStr(f'<span class="{css_class} truncate">{value_str}</span>')
index = value_str.lower().find(filter_keyword_lower)
if index < 0:
return NotStr(f'<span class="{css_class} truncate text-sm">{value_str}</span>')
return NotStr(f'<span class="{css_class} truncate">{value_str}</span>')
# Has highlighting - need to use Span objects
# Add "truncate text-sm" to match mk.label() behavior
len_keyword = len(filter_keyword_lower)
res = []
if index > 0:
res.append(Span(value_str[:index], cls=f"{css_class} text-sm"))
res.append(Span(value_str[index:index + len_keyword], cls=f"{css_class} text-sm dt2-highlight-1"))
res.append(Span(value_str[:index], cls=f"{css_class}"))
res.append(Span(value_str[index:index + len_keyword], cls=f"{css_class} dt2-highlight-1"))
if index + len_keyword < len(value_str):
res.append(Span(value_str[index + len_keyword:], cls=f"{css_class} text-sm"))
res.append(Span(value_str[index + len_keyword:], cls=f"{css_class}"))
return Span(*res, cls=f"{css_class} truncate") if len(res) > 1 else res[0]
column_type = col_def.type
@@ -281,7 +282,7 @@ class DataGrid(MultipleInstance):
# RowIndex - simplest case, just return the number as plain HTML
if column_type == ColumnType.RowIndex:
return NotStr(f'<span class="dt2-cell-content-number truncate text-sm">{row_index}</span>')
return NotStr(f'<span class="dt2-cell-content-number truncate">{row_index}</span>')
# Convert value to string
value_str = str(value)
@@ -346,7 +347,7 @@ class DataGrid(MultipleInstance):
def mk_body(self):
return Div(
*self.mk_body_content_page(0),
cls="dt2-body"
cls=f"dt2-body text-{self._settings.text_size}",
)
def mk_footers(self):
@@ -469,7 +470,9 @@ class DataGrid(MultipleInstance):
if self._state.ne_df is None:
return Div("No data to display !")
from myfasthtml.controls.DataGridFilter import DataGridFilter
return Div(
Div(DataGridFilter(self), cls="mb-2"),
self.mk_table(),
Script(f"initDataGrid('{self._id}');"),
id=self._id,

View File

@@ -0,0 +1,76 @@
import logging
from fasthtml.components import *
from myfasthtml.controls.BaseCommands import BaseCommands
from myfasthtml.controls.helpers import mk
from myfasthtml.core.commands import Command
from myfasthtml.core.dbmanager import DbObject
from myfasthtml.core.instances import MultipleInstance
from myfasthtml.icons.fluent import brain_circuit20_regular
from myfasthtml.icons.fluent_p1 import filter20_regular, search20_regular
from myfasthtml.icons.fluent_p2 import dismiss_circle20_regular
logger = logging.getLogger("DataGridFilter")
filter_type = {
"filter": filter20_regular,
"search": search20_regular,
"ai": brain_circuit20_regular
}
class DataGridFilterState(DbObject):
def __init__(self, owner):
with self.initializing():
super().__init__(owner)
self.filter_type: str = "filter"
class Commands(BaseCommands):
def change_filter_type(self):
return Command("ChangeFilterType",
"Change filter type",
self._owner,
self._owner.change_filter_type).htmx(target=f"#{self._id}")
def on_filter_changed(self):
return Command("FilterChanged",
"Filter changed",
self._owner,
self._owner.filter_changed).htmx(target=None)
class DataGridFilter(MultipleInstance):
def __init__(self, parent, _id=None):
super().__init__(parent, _id=_id or "-filter")
self.commands = Commands(self)
self._state = DataGridFilterState(self)
def change_filter_type(self):
keys = list(filter_type.keys()) # ["filter", "search", "ai"]
current_idx = keys.index(self._state.filter_type)
self._state.filter_type = keys[(current_idx + 1) % len(keys)]
return self
def filter_changed(self, f):
logger.debug(f"filter_changed {f=}")
return self
def render(self):
return Div(
mk.label(
Input(name="f",
placeholder="Search...",
**self.commands.on_filter_changed().get_htmx_params(escaped=True)),
icon=mk.icon(filter_type[self._state.filter_type], command=self.commands.change_filter_type()),
cls="input input-sm flex gap-2"
),
mk.icon(dismiss_circle20_regular, size=24),
# Keyboard(self, _id="-keyboard").add("enter", self.commands.on_filter_changed()),
cls="flex",
id=self._id
)
def __ft__(self):
return self.render()