Added "table" and "tables" in the DSL

This commit is contained in:
2026-02-07 22:48:51 +01:00
parent 08c8c00e28
commit 6160e91665
18 changed files with 717 additions and 54 deletions

View File

@@ -78,6 +78,7 @@ class DatagridState(DbObject):
self.edition: DatagridEditionState = DatagridEditionState()
self.selection: DatagridSelectionState = DatagridSelectionState()
self.cell_formats: dict = {}
self.table_format: list = []
self.ne_df = None
self.ns_fast_access = None
@@ -274,7 +275,7 @@ class DataGrid(MultipleInstance):
def _get_filtered_df(self):
if self._df is None:
return DataFrame()
return None
df = self._df.copy()
df = self._apply_sort(df) # need to keep the real type to sort
@@ -396,6 +397,8 @@ class DataGrid(MultipleInstance):
1. Cell-level: self._state.cell_formats[cell_id]
2. Row-level: row_state.format (if row has specific state)
3. Column-level: col_def.format
4. Table-level: self._state.table_format
5. Tables-level (global): manager.all_tables_formats
Args:
col_pos: Column position index
@@ -419,7 +422,11 @@ class DataGrid(MultipleInstance):
if col_def.format:
return col_def.format
return None
if self._state.table_format:
return self._state.table_format
# Get global tables formatting from manager
return self._parent.all_tables_formats
def set_column_width(self, col_id: str, width: str):
"""Update column width after resize. Called via Command from JS."""
@@ -629,6 +636,9 @@ class DataGrid(MultipleInstance):
OPTIMIZED: Uses OptimizedDiv for rows instead of Div for faster rendering.
"""
df = self._get_filtered_df()
if df is None:
return []
start = page_index * DATAGRID_PAGE_SIZE
end = start + DATAGRID_PAGE_SIZE
if self._state.ns_total_rows > end:

View File

@@ -2,7 +2,8 @@ import logging
from collections import defaultdict
from myfasthtml.controls.DslEditor import DslEditor
from myfasthtml.core.formatting.dsl import parse_dsl, DSLSyntaxError, ColumnScope, RowScope, CellScope
from myfasthtml.core.formatting.dsl import parse_dsl, DSLSyntaxError, ColumnScope, RowScope, CellScope, TableScope, TablesScope
from myfasthtml.core.instances import InstancesManager
logger = logging.getLogger("DataGridFormattingEditor")
@@ -62,11 +63,13 @@ class DataGridFormattingEditor(DslEditor):
columns_rules = defaultdict(list) # key = column name
rows_rules = defaultdict(list) # key = row index
cells_rules = defaultdict(list) # key = cell_id
table_rules = [] # rules for this table
tables_rules = [] # global rules for all tables
for scoped_rule in scoped_rules:
scope = scoped_rule.scope
rule = scoped_rule.rule
if isinstance(scope, ColumnScope):
columns_rules[scope.column].append(rule)
elif isinstance(scope, RowScope):
@@ -75,6 +78,14 @@ class DataGridFormattingEditor(DslEditor):
cell_id = self._get_cell_id(scope)
if cell_id:
cells_rules[cell_id].append(rule)
elif isinstance(scope, TableScope):
# Validate table name matches current grid
if scope.table == self._parent._settings.name:
table_rules.append(rule)
else:
logger.warning(f"Table name '{scope.table}' does not match grid name '{self._parent._settings.name}', skipping rules")
elif isinstance(scope, TablesScope):
tables_rules.append(rule)
# Step 3: Copy state for atomic update
state = self._parent.get_state().copy()
@@ -85,6 +96,7 @@ class DataGridFormattingEditor(DslEditor):
for row in state.rows:
row.format = None
state.cell_formats.clear()
state.table_format = []
# Step 5: Apply grouped rules on the copy
for column_name, rules in columns_rules.items():
@@ -103,10 +115,21 @@ class DataGridFormattingEditor(DslEditor):
for cell_id, rules in cells_rules.items():
state.cell_formats[cell_id] = rules
# Apply table-level rules
if table_rules:
state.table_format = table_rules
# Apply global tables-level rules to manager
if tables_rules:
from myfasthtml.controls.DataGridsManager import DataGridsManager
manager = InstancesManager.get_by_type(self._session, DataGridsManager)
if manager:
manager.all_tables_formats = tables_rules
# Step 6: Update state atomically
self._parent.get_state().update(state)
# Step 7: Refresh the DataGrid
logger.debug(f"Formatting applied: {len(columns_rules)} columns, {len(rows_rules)} rows, {len(cells_rules)} cells")
logger.debug(f"Formatting applied: {len(columns_rules)} columns, {len(rows_rules)} rows, {len(cells_rules)} cells, table: {len(table_rules)}, tables: {len(tables_rules)}")
return self._parent.render_partial("body")

View File

@@ -84,12 +84,13 @@ class DataGridsManager(SingleInstance, DatagridMetadataProvider):
self._state = DataGridsState(self)
self._tree = self._mk_tree()
self._tree.bind_command("SelectNode", self.commands.show_document())
self._tabs_manager = InstancesManager.get_by_type(self._session, TabsManager)
self._tabs_manager = InstancesManager.get_by_type(self._session, TabsManager, None)
self._registry = DataGridsRegistry(parent)
# Global presets shared across all DataGrids
self.style_presets: dict = DEFAULT_STYLE_PRESETS.copy()
self.formatter_presets: dict = DEFAULT_FORMATTER_PRESETS.copy()
self.all_tables_formats: list = []
def upload_from_source(self):
file_upload = FileUpload(self)

View File

@@ -99,7 +99,7 @@ class DslEditor(MultipleInstance):
self._dsl = dsl
self.conf = conf or DslEditorConf()
self._state = DslEditorState(self, name=conf.name, save_state=save_state)
self._state = DslEditorState(self, name=self.conf.name, save_state=save_state)
self.commands = Commands(self)
logger.debug(f"DslEditor created with id={self._id}, dsl={dsl.name}")