I can save and load Datagrid content
This commit is contained in:
@@ -37,17 +37,20 @@ markdown-it-py==4.0.0
|
|||||||
mdurl==0.1.2
|
mdurl==0.1.2
|
||||||
more-itertools==10.8.0
|
more-itertools==10.8.0
|
||||||
myauth==0.2.1
|
myauth==0.2.1
|
||||||
mydbengine==0.1.0
|
mydbengine==0.2.1
|
||||||
myutils==0.5.0
|
-e git+ssh://git@sheerka.synology.me:1010/kodjo/MyFastHtml.git@2f808ed226e98738a1cf476e1f1dda8a1d9118b0#egg=myfasthtml
|
||||||
|
myutils==0.5.1
|
||||||
nh3==0.3.1
|
nh3==0.3.1
|
||||||
numpy==2.3.5
|
numpy==2.3.5
|
||||||
oauthlib==3.3.1
|
oauthlib==3.3.1
|
||||||
openpyxl==3.1.5
|
openpyxl==3.1.5
|
||||||
packaging==25.0
|
packaging==25.0
|
||||||
pandas==2.3.3
|
pandas==2.3.3
|
||||||
|
pandas-stubs==2.3.3.251201
|
||||||
passlib==1.7.4
|
passlib==1.7.4
|
||||||
pipdeptree==2.29.0
|
pipdeptree==2.29.0
|
||||||
pluggy==1.6.0
|
pluggy==1.6.0
|
||||||
|
pyarrow==22.0.0
|
||||||
pyasn1==0.6.1
|
pyasn1==0.6.1
|
||||||
pycparser==2.23
|
pycparser==2.23
|
||||||
pydantic==2.12.3
|
pydantic==2.12.3
|
||||||
|
|||||||
24
src/app.py
24
src/app.py
@@ -1,6 +1,9 @@
|
|||||||
|
import json
|
||||||
import logging.config
|
import logging.config
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
import yaml
|
import yaml
|
||||||
|
from dbengine.handlers import BaseRefHandler, handlers
|
||||||
from fasthtml import serve
|
from fasthtml import serve
|
||||||
from fasthtml.components import Div
|
from fasthtml.components import Div
|
||||||
|
|
||||||
@@ -35,6 +38,23 @@ app, rt = create_app(protect_routes=True,
|
|||||||
base_url="http://localhost:5003")
|
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):
|
def create_sample_treeview(parent):
|
||||||
"""
|
"""
|
||||||
Create a sample TreeView with a file structure for testing.
|
Create a sample TreeView with a file structure for testing.
|
||||||
@@ -83,7 +103,9 @@ def create_sample_treeview(parent):
|
|||||||
|
|
||||||
@rt("/")
|
@rt("/")
|
||||||
def index(session):
|
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 = Layout(session_instance, "Testing Layout")
|
||||||
layout.footer_left.add("Goodbye World")
|
layout.footer_left.add("Goodbye World")
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from myfasthtml.core.instances import MultipleInstance
|
|||||||
|
|
||||||
class DatagridState(DbObject):
|
class DatagridState(DbObject):
|
||||||
def __init__(self, owner):
|
def __init__(self, owner):
|
||||||
super().__init__(owner)
|
super().__init__(owner, name=f"{owner.get_full_id()}-state")
|
||||||
with self.initializing():
|
with self.initializing():
|
||||||
self.sidebar_visible: bool = False
|
self.sidebar_visible: bool = False
|
||||||
self.selected_view: str = None
|
self.selected_view: str = None
|
||||||
@@ -25,12 +25,12 @@ class DatagridState(DbObject):
|
|||||||
self.filtered: dict = {}
|
self.filtered: dict = {}
|
||||||
self.edition: DatagridEditionState = DatagridEditionState()
|
self.edition: DatagridEditionState = DatagridEditionState()
|
||||||
self.selection: DatagridSelectionState = DatagridSelectionState()
|
self.selection: DatagridSelectionState = DatagridSelectionState()
|
||||||
self.html = None
|
self.ne_data = None
|
||||||
|
|
||||||
|
|
||||||
class DatagridSettings(DbObject):
|
class DatagridSettings(DbObject):
|
||||||
def __init__(self, owner):
|
def __init__(self, owner):
|
||||||
super().__init__(owner)
|
super().__init__(owner, name=f"{owner.get_full_id()}-settings")
|
||||||
with self.initializing():
|
with self.initializing():
|
||||||
self.file_name: Optional[str] = None
|
self.file_name: Optional[str] = None
|
||||||
self.selected_sheet_name: Optional[str] = None
|
self.selected_sheet_name: Optional[str] = None
|
||||||
@@ -52,12 +52,13 @@ class DataGrid(MultipleInstance):
|
|||||||
self._state = DatagridState(self)
|
self._state = DatagridState(self)
|
||||||
self.commands = Commands(self)
|
self.commands = Commands(self)
|
||||||
|
|
||||||
def set_html(self, html):
|
def init_from_dataframe(self, df):
|
||||||
self._state.html = html
|
self._state.ne_data = df
|
||||||
|
|
||||||
def render(self):
|
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(
|
return Div(
|
||||||
NotStr(self._state.html) if self._state.html else "Content lost !",
|
NotStr(html),
|
||||||
id=self._id
|
id=self._id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class DocumentDefinition:
|
|||||||
document_id: str
|
document_id: str
|
||||||
namespace: str
|
namespace: str
|
||||||
name: str
|
name: str
|
||||||
type: str
|
type: str # table, card,
|
||||||
tab_id: str
|
tab_id: str
|
||||||
datagrid_id: str
|
datagrid_id: str
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ class DataGridsState(DbObject):
|
|||||||
def __init__(self, owner, name=None):
|
def __init__(self, owner, name=None):
|
||||||
super().__init__(owner, name=name)
|
super().__init__(owner, name=name)
|
||||||
with self.initializing():
|
with self.initializing():
|
||||||
self.elements: list = [DocumentDefinition]
|
self.elements: list[DocumentDefinition] = []
|
||||||
|
|
||||||
|
|
||||||
class Commands(BaseCommands):
|
class Commands(BaseCommands):
|
||||||
@@ -91,9 +91,8 @@ class DataGridsManager(MultipleInstance):
|
|||||||
def open_from_excel(self, tab_id, file_upload: FileUpload):
|
def open_from_excel(self, tab_id, file_upload: FileUpload):
|
||||||
excel_content = file_upload.get_content()
|
excel_content = file_upload.get_content()
|
||||||
df = pd.read_excel(excel_content, file_upload.get_sheet_name())
|
df = pd.read_excel(excel_content, file_upload.get_sheet_name())
|
||||||
html = df.to_html(index=False)
|
|
||||||
dg = DataGrid(self._tabs_manager)
|
dg = DataGrid(self._tabs_manager)
|
||||||
dg.set_html(html)
|
dg.init_from_dataframe(df)
|
||||||
document = DocumentDefinition(
|
document = DocumentDefinition(
|
||||||
document_id=str(uuid.uuid4()),
|
document_id=str(uuid.uuid4()),
|
||||||
namespace=file_upload.get_file_basename(),
|
namespace=file_upload.get_file_basename(),
|
||||||
|
|||||||
@@ -55,10 +55,11 @@ class DbObject:
|
|||||||
self._initializing = old_state
|
self._initializing = old_state
|
||||||
|
|
||||||
def __setattr__(self, name: str, value: str):
|
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)
|
super().__setattr__(name, value)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not name.startswith("ne_"):
|
||||||
old_value = getattr(self, name, None)
|
old_value = getattr(self, name, None)
|
||||||
if old_value == value:
|
if old_value == value:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -144,8 +144,11 @@ class UniqueInstance(BaseInstance):
|
|||||||
parent: Optional[BaseInstance] = None,
|
parent: Optional[BaseInstance] = None,
|
||||||
session: Optional[dict] = None,
|
session: Optional[dict] = None,
|
||||||
_id: Optional[str] = None,
|
_id: Optional[str] = None,
|
||||||
auto_register: bool = True):
|
auto_register: bool = True,
|
||||||
|
on_init=None):
|
||||||
super().__init__(parent, session, _id, auto_register)
|
super().__init__(parent, session, _id, auto_register)
|
||||||
|
if on_init is not None:
|
||||||
|
on_init()
|
||||||
|
|
||||||
|
|
||||||
class MultipleInstance(BaseInstance):
|
class MultipleInstance(BaseInstance):
|
||||||
|
|||||||
Reference in New Issue
Block a user