I can validate formatting in editor
This commit is contained in:
@@ -13,8 +13,9 @@ from pandas import DataFrame
|
||||
from myfasthtml.controls.BaseCommands import BaseCommands
|
||||
from myfasthtml.controls.CycleStateControl import CycleStateControl
|
||||
from myfasthtml.controls.DataGridColumnsManager import DataGridColumnsManager
|
||||
from myfasthtml.controls.DataGridFormattingEditor import DataGridFormattingEditor
|
||||
from myfasthtml.controls.DataGridQuery import DataGridQuery, DG_QUERY_FILTER
|
||||
from myfasthtml.controls.DslEditor import DslEditor
|
||||
from myfasthtml.controls.DslEditor import DslEditorConf
|
||||
from myfasthtml.controls.Mouse import Mouse
|
||||
from myfasthtml.controls.Panel import Panel, PanelConf
|
||||
from myfasthtml.controls.datagrid_objects import DataGridColumnState, DataGridRowState, \
|
||||
@@ -180,7 +181,7 @@ class DataGrid(MultipleInstance):
|
||||
self.init_from_dataframe(self._state.ne_df, init_state=False) # state comes from DatagridState
|
||||
|
||||
# add Panel
|
||||
self._panel = Panel(self, conf=PanelConf(show_display_right=False), _id="-panel")
|
||||
self._panel = Panel(self, conf=PanelConf(show_display_right=False), _id="#panel")
|
||||
self._panel.set_side_visible("right", False) # the right Panel always starts closed
|
||||
self.bind_command("ToggleColumnsManager", self._panel.commands.toggle_side("right"))
|
||||
self.bind_command("ToggleFormattingEditor", self._panel.commands.toggle_side("right"))
|
||||
@@ -206,7 +207,12 @@ class DataGrid(MultipleInstance):
|
||||
self._columns_manager.bind_command("ToggleColumn", self.commands.on_column_changed())
|
||||
self._columns_manager.bind_command("UpdateColumn", self.commands.on_column_changed())
|
||||
|
||||
self._formatting_editor = DslEditor(self, dsl=FormattingDSL())
|
||||
editor_conf = DslEditorConf()
|
||||
self._formatting_editor = DataGridFormattingEditor(self,
|
||||
conf=editor_conf,
|
||||
dsl=FormattingDSL(),
|
||||
save_state=self._settings.save_state,
|
||||
_id="#formatting_editor")
|
||||
|
||||
# other definitions
|
||||
self._mouse_support = {
|
||||
|
||||
7
src/myfasthtml/controls/DataGridFormattingEditor.py
Normal file
7
src/myfasthtml/controls/DataGridFormattingEditor.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from myfasthtml.controls.DslEditor import DslEditor
|
||||
|
||||
|
||||
class DataGridFormattingEditor(DslEditor):
|
||||
|
||||
def on_dsl_change(self, dsl):
|
||||
pass
|
||||
@@ -14,6 +14,11 @@ from myfasthtml.controls.helpers import mk
|
||||
from myfasthtml.core.DataGridsRegistry import DataGridsRegistry
|
||||
from myfasthtml.core.commands import Command
|
||||
from myfasthtml.core.dbmanager import DbObject
|
||||
from myfasthtml.core.dsls import DslsManager
|
||||
from myfasthtml.core.formatting.dsl.completion.engine import FormattingCompletionEngine
|
||||
from myfasthtml.core.formatting.dsl.completion.provider import DatagridMetadataProvider
|
||||
from myfasthtml.core.formatting.dsl.definition import FormattingDSL
|
||||
from myfasthtml.core.formatting.dsl.parser import DSLParser
|
||||
from myfasthtml.core.formatting.presets import DEFAULT_STYLE_PRESETS, DEFAULT_FORMATTER_PRESETS
|
||||
from myfasthtml.core.instances import InstancesManager, SingleInstance
|
||||
from myfasthtml.icons.fluent_p1 import table_add20_regular
|
||||
@@ -72,7 +77,7 @@ class Commands(BaseCommands):
|
||||
key="SelectNode")
|
||||
|
||||
|
||||
class DataGridsManager(SingleInstance):
|
||||
class DataGridsManager(SingleInstance, DatagridMetadataProvider):
|
||||
|
||||
def __init__(self, parent, _id=None):
|
||||
if not getattr(self, "_is_new_instance", False):
|
||||
@@ -89,6 +94,11 @@ class DataGridsManager(SingleInstance):
|
||||
# Global presets shared across all DataGrids
|
||||
self.style_presets: dict = DEFAULT_STYLE_PRESETS.copy()
|
||||
self.formatter_presets: dict = DEFAULT_FORMATTER_PRESETS.copy()
|
||||
|
||||
# register the auto-completion for the formatter DSL
|
||||
DslsManager.register(FormattingDSL().get_id(),
|
||||
FormattingCompletionEngine(self),
|
||||
DSLParser())
|
||||
|
||||
def upload_from_source(self):
|
||||
file_upload = FileUpload(self)
|
||||
@@ -104,6 +114,7 @@ class DataGridsManager(SingleInstance):
|
||||
dg_conf = DatagridConf(namespace=namespace, name=name)
|
||||
dg = DataGrid(self._tabs_manager, conf=dg_conf, save_state=True) # first time the Datagrid is created
|
||||
dg.init_from_dataframe(df)
|
||||
self._registry.put(namespace, name, dg.get_id())
|
||||
document = DocumentDefinition(
|
||||
document_id=str(uuid.uuid4()),
|
||||
namespace=namespace,
|
||||
@@ -154,6 +165,26 @@ class DataGridsManager(SingleInstance):
|
||||
self._tree.clear()
|
||||
return self._tree
|
||||
|
||||
# === DatagridMetadataProvider ===
|
||||
|
||||
def list_tables(self):
|
||||
return self._registry.get_all_tables()
|
||||
|
||||
def list_columns(self, table_name):
|
||||
return self._registry.get_columns(table_name)
|
||||
|
||||
def list_column_values(self, table_name, column_name):
|
||||
return self._registry.get_column_values(table_name, column_name)
|
||||
|
||||
def get_row_count(self, table_name):
|
||||
return self._registry.get_row_count(table_name)
|
||||
|
||||
def list_style_presets(self) -> list[str]:
|
||||
return list(self.style_presets.keys())
|
||||
|
||||
def list_format_presets(self) -> list[str]:
|
||||
return list(self.formatter_presets.keys())
|
||||
|
||||
# === Presets Management ===
|
||||
|
||||
def get_style_presets(self) -> dict:
|
||||
@@ -194,6 +225,8 @@ class DataGridsManager(SingleInstance):
|
||||
if name in self.formatter_presets:
|
||||
del self.formatter_presets[name]
|
||||
|
||||
# === UI ===
|
||||
|
||||
def mk_main_icons(self):
|
||||
return Div(
|
||||
mk.icon(folder_open20_regular, tooltip="Upload from source", command=self.commands.upload_from_source()),
|
||||
|
||||
@@ -16,6 +16,7 @@ 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.dsl.base import DSLDefinition
|
||||
from myfasthtml.core.instances import MultipleInstance
|
||||
|
||||
@@ -25,19 +26,22 @@ logger = logging.getLogger("DslEditor")
|
||||
@dataclass
|
||||
class DslEditorConf:
|
||||
"""Configuration for DslEditor."""
|
||||
|
||||
name: str = None
|
||||
line_numbers: bool = True
|
||||
autocompletion: bool = True
|
||||
linting: bool = True
|
||||
placeholder: str = ""
|
||||
readonly: bool = False
|
||||
|
||||
|
||||
class DslEditorState:
|
||||
class DslEditorState(DbObject):
|
||||
"""Non-persisted state for DslEditor."""
|
||||
|
||||
def __init__(self):
|
||||
self.content: str = ""
|
||||
self.auto_save: bool = True
|
||||
def __init__(self, owner, name, save_state):
|
||||
with self.initializing():
|
||||
super().__init__(owner, name=name, save_state=save_state)
|
||||
self.content: str = ""
|
||||
self.auto_save: bool = True
|
||||
|
||||
|
||||
class Commands(BaseCommands):
|
||||
@@ -87,13 +91,14 @@ class DslEditor(MultipleInstance):
|
||||
parent,
|
||||
dsl: DSLDefinition,
|
||||
conf: Optional[DslEditorConf] = None,
|
||||
save_state: bool = True,
|
||||
_id: Optional[str] = None,
|
||||
):
|
||||
super().__init__(parent, _id=_id)
|
||||
|
||||
self._dsl = dsl
|
||||
self.conf = conf or DslEditorConf()
|
||||
self._state = DslEditorState()
|
||||
self._state = DslEditorState(self, name=conf.name, save_state=save_state)
|
||||
self.commands = Commands(self)
|
||||
|
||||
logger.debug(f"DslEditor created with id={self._id}, dsl={dsl.name}")
|
||||
@@ -114,9 +119,9 @@ class DslEditor(MultipleInstance):
|
||||
self.on_content_changed()
|
||||
logger.debug(f"Content updated: {len(content)} chars")
|
||||
|
||||
def toggle_auto_save(self) -> None:
|
||||
def toggle_auto_save(self):
|
||||
self._state.auto_save = not self._state.auto_save
|
||||
self._mk_auto_save()
|
||||
return self._mk_auto_save()
|
||||
|
||||
def on_content_changed(self) -> None:
|
||||
pass
|
||||
@@ -128,9 +133,11 @@ class DslEditor(MultipleInstance):
|
||||
"textareaId": f"ta_{self._id}",
|
||||
"lineNumbers": self.conf.line_numbers,
|
||||
"autocompletion": self.conf.autocompletion,
|
||||
"linting": self.conf.linting,
|
||||
"placeholder": self.conf.placeholder,
|
||||
"readonly": self.conf.readonly,
|
||||
"updateCommandId": str(self.commands.update_content().id),
|
||||
"dslId": self._dsl.get_id(),
|
||||
"dsl": {
|
||||
"name": self._dsl.name,
|
||||
"completions": self._dsl.completions,
|
||||
|
||||
@@ -159,31 +159,31 @@ class Panel(MultipleInstance):
|
||||
enabled = self.conf.left if side == "left" else self.conf.right
|
||||
if not enabled:
|
||||
return None
|
||||
|
||||
|
||||
visible = self._state.left_visible if side == "left" else self._state.right_visible
|
||||
content = self._right if side == "right" else self._left
|
||||
show_title = self.conf.show_left_title if side == "left" else self.conf.show_right_title
|
||||
title = self.conf.left_title if side == "left" else self.conf.right_title
|
||||
|
||||
|
||||
resizer = Div(
|
||||
cls=f"mf-resizer mf-resizer-{side}",
|
||||
data_command_id=self.commands.update_side_width(side).id,
|
||||
data_side=side
|
||||
)
|
||||
|
||||
|
||||
hide_icon = mk.icon(
|
||||
subtract20_regular,
|
||||
size=20,
|
||||
command=self.commands.set_side_visible(side, False),
|
||||
cls="mf-panel-hide-icon"
|
||||
)
|
||||
|
||||
|
||||
panel_cls = f"mf-panel-{side}"
|
||||
if not visible:
|
||||
panel_cls += " mf-hidden"
|
||||
if show_title:
|
||||
panel_cls += " mf-panel-with-title"
|
||||
|
||||
|
||||
# Left panel: content then resizer (resizer on the right)
|
||||
# Right panel: resizer then content (resizer on the left)
|
||||
if show_title:
|
||||
@@ -202,6 +202,7 @@ class Panel(MultipleInstance):
|
||||
body,
|
||||
resizer,
|
||||
cls=panel_cls,
|
||||
style=f"width: {self._state.left_width}px;",
|
||||
id=self._ids.panel(side)
|
||||
)
|
||||
else:
|
||||
@@ -209,6 +210,7 @@ class Panel(MultipleInstance):
|
||||
resizer,
|
||||
body,
|
||||
cls=panel_cls,
|
||||
style=f"width: {self._state.right_width}px;",
|
||||
id=self._ids.panel(side)
|
||||
)
|
||||
else:
|
||||
@@ -218,6 +220,7 @@ class Panel(MultipleInstance):
|
||||
Div(content, id=self._ids.content(side)),
|
||||
resizer,
|
||||
cls=panel_cls,
|
||||
style=f"width: {self._state.left_width}px;",
|
||||
id=self._ids.panel(side)
|
||||
)
|
||||
else:
|
||||
@@ -226,6 +229,7 @@ class Panel(MultipleInstance):
|
||||
hide_icon,
|
||||
Div(content, id=self._ids.content(side)),
|
||||
cls=panel_cls,
|
||||
style=f"width: {self._state.left_width}px;",
|
||||
id=self._ids.panel(side)
|
||||
)
|
||||
|
||||
@@ -250,14 +254,14 @@ class Panel(MultipleInstance):
|
||||
enabled = self.conf.left if side == "left" else self.conf.right
|
||||
if not enabled:
|
||||
return None
|
||||
|
||||
|
||||
show_display = self.conf.show_display_left if side == "left" else self.conf.show_display_right
|
||||
if not show_display:
|
||||
return None
|
||||
|
||||
|
||||
is_visible = self._state.left_visible if side == "left" else self._state.right_visible
|
||||
icon_cls = "hidden" if is_visible else f"mf-panel-show-icon mf-panel-show-icon-{side}"
|
||||
|
||||
|
||||
return mk.icon(
|
||||
more_horizontal20_regular,
|
||||
command=self.commands.set_side_visible(side, True),
|
||||
|
||||
Reference in New Issue
Block a user