diff --git a/requirements.txt b/requirements.txt index a735de4..98a359d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -37,17 +37,20 @@ markdown-it-py==4.0.0 mdurl==0.1.2 more-itertools==10.8.0 myauth==0.2.1 -mydbengine==0.1.0 -myutils==0.5.0 +mydbengine==0.2.1 +-e git+ssh://git@sheerka.synology.me:1010/kodjo/MyFastHtml.git@2f808ed226e98738a1cf476e1f1dda8a1d9118b0#egg=myfasthtml +myutils==0.5.1 nh3==0.3.1 numpy==2.3.5 oauthlib==3.3.1 openpyxl==3.1.5 packaging==25.0 pandas==2.3.3 +pandas-stubs==2.3.3.251201 passlib==1.7.4 pipdeptree==2.29.0 pluggy==1.6.0 +pyarrow==22.0.0 pyasn1==0.6.1 pycparser==2.23 pydantic==2.12.3 diff --git a/src/app.py b/src/app.py index b4c59ee..3d12ffa 100644 --- a/src/app.py +++ b/src/app.py @@ -1,6 +1,9 @@ +import json import logging.config +import pandas as pd import yaml +from dbengine.handlers import BaseRefHandler, handlers from fasthtml import serve from fasthtml.components import Div @@ -35,6 +38,23 @@ app, rt = create_app(protect_routes=True, base_url="http://localhost:5003") +class DataFrameHandler(BaseRefHandler): + def is_eligible_for(self, obj): + return isinstance(obj, pd.DataFrame) + + def tag(self): + return "DataFrame" + + def serialize_to_bytes(self, df) -> bytes: + from io import BytesIO + import pickle + return pickle.dumps(df) + + def deserialize_from_bytes(self, data: bytes): + import pickle + return pickle.loads(data) + + def create_sample_treeview(parent): """ Create a sample TreeView with a file structure for testing. @@ -83,7 +103,9 @@ def create_sample_treeview(parent): @rt("/") def index(session): - session_instance = UniqueInstance(session=session, _id=Ids.UserSession) + session_instance = UniqueInstance(session=session, + _id=Ids.UserSession, + on_init=lambda: handlers.register_handler(DataFrameHandler())) layout = Layout(session_instance, "Testing Layout") layout.footer_left.add("Goodbye World") diff --git a/src/myfasthtml/controls/DataGrid.py b/src/myfasthtml/controls/DataGrid.py index 478ab04..71b2cf3 100644 --- a/src/myfasthtml/controls/DataGrid.py +++ b/src/myfasthtml/controls/DataGrid.py @@ -12,7 +12,7 @@ from myfasthtml.core.instances import MultipleInstance class DatagridState(DbObject): def __init__(self, owner): - super().__init__(owner) + super().__init__(owner, name=f"{owner.get_full_id()}-state") with self.initializing(): self.sidebar_visible: bool = False self.selected_view: str = None @@ -25,12 +25,12 @@ class DatagridState(DbObject): self.filtered: dict = {} self.edition: DatagridEditionState = DatagridEditionState() self.selection: DatagridSelectionState = DatagridSelectionState() - self.html = None + self.ne_data = None class DatagridSettings(DbObject): def __init__(self, owner): - super().__init__(owner) + super().__init__(owner, name=f"{owner.get_full_id()}-settings") with self.initializing(): self.file_name: Optional[str] = None self.selected_sheet_name: Optional[str] = None @@ -52,12 +52,13 @@ class DataGrid(MultipleInstance): self._state = DatagridState(self) self.commands = Commands(self) - def set_html(self, html): - self._state.html = html + def init_from_dataframe(self, df): + self._state.ne_data = df def render(self): + html = self._state.ne_data.to_html(index=False) if self._state.ne_data is not None else "Content lost !" return Div( - NotStr(self._state.html) if self._state.html else "Content lost !", + NotStr(html), id=self._id ) diff --git a/src/myfasthtml/controls/DataGridsManager.py b/src/myfasthtml/controls/DataGridsManager.py index 29ce8c5..9633fee 100644 --- a/src/myfasthtml/controls/DataGridsManager.py +++ b/src/myfasthtml/controls/DataGridsManager.py @@ -23,7 +23,7 @@ class DocumentDefinition: document_id: str namespace: str name: str - type: str + type: str # table, card, tab_id: str datagrid_id: str @@ -32,7 +32,7 @@ class DataGridsState(DbObject): def __init__(self, owner, name=None): super().__init__(owner, name=name) with self.initializing(): - self.elements: list = [DocumentDefinition] + self.elements: list[DocumentDefinition] = [] class Commands(BaseCommands): @@ -91,9 +91,8 @@ class DataGridsManager(MultipleInstance): def open_from_excel(self, tab_id, file_upload: FileUpload): excel_content = file_upload.get_content() df = pd.read_excel(excel_content, file_upload.get_sheet_name()) - html = df.to_html(index=False) dg = DataGrid(self._tabs_manager) - dg.set_html(html) + dg.init_from_dataframe(df) document = DocumentDefinition( document_id=str(uuid.uuid4()), namespace=file_upload.get_file_basename(), diff --git a/src/myfasthtml/core/dbmanager.py b/src/myfasthtml/core/dbmanager.py index c4bdb00..6c656f4 100644 --- a/src/myfasthtml/core/dbmanager.py +++ b/src/myfasthtml/core/dbmanager.py @@ -55,13 +55,14 @@ class DbObject: self._initializing = old_state def __setattr__(self, name: str, value: str): - if name.startswith("_") or name.startswith("ns") or getattr(self, "_initializing", False): + if name.startswith("_") or name.startswith("ns_") or getattr(self, "_initializing", False): super().__setattr__(name, value) return - old_value = getattr(self, name, None) - if old_value == value: - return + if not name.startswith("ne_"): + old_value = getattr(self, name, None) + if old_value == value: + return super().__setattr__(name, value) self._save_self() diff --git a/src/myfasthtml/core/instances.py b/src/myfasthtml/core/instances.py index 05fd3a1..0bc550c 100644 --- a/src/myfasthtml/core/instances.py +++ b/src/myfasthtml/core/instances.py @@ -144,8 +144,11 @@ class UniqueInstance(BaseInstance): parent: Optional[BaseInstance] = None, session: Optional[dict] = None, _id: Optional[str] = None, - auto_register: bool = True): + auto_register: bool = True, + on_init=None): super().__init__(parent, session, _id, auto_register) + if on_init is not None: + on_init() class MultipleInstance(BaseInstance):