Working on Datagrid interaction
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
from typing import Optional
|
||||
|
||||
from fastcore.basics import NotStr
|
||||
from fasthtml.components import Div
|
||||
|
||||
from myfasthtml.controls.BaseCommands import BaseCommands
|
||||
from myfasthtml.controls.datagrid_objects import DataGridColumnState, DataGridRowState, DataGridFooterConf, \
|
||||
from myfasthtml.controls.datagrid_objects import DataGridColumnState, DataGridRowState, \
|
||||
DatagridSelectionState, DataGridHeaderFooterConf, DatagridEditionState
|
||||
from myfasthtml.core.dbmanager import DbObject
|
||||
from myfasthtml.core.instances import MultipleInstance
|
||||
@@ -24,6 +25,7 @@ class DatagridState(DbObject):
|
||||
self.filtered: dict = {}
|
||||
self.edition: DatagridEditionState = DatagridEditionState()
|
||||
self.selection: DatagridSelectionState = DatagridSelectionState()
|
||||
self.html = None
|
||||
|
||||
|
||||
class DatagridSettings(DbObject):
|
||||
@@ -46,13 +48,17 @@ class Commands(BaseCommands):
|
||||
class DataGrid(MultipleInstance):
|
||||
def __init__(self, parent, settings=None, _id=None):
|
||||
super().__init__(parent, _id=_id)
|
||||
self._settings = DatagridSettings(self).update(settings)
|
||||
self._settings = DatagridSettings(self)
|
||||
self._state = DatagridState(self)
|
||||
self.commands = Commands(self)
|
||||
|
||||
def set_html(self, html):
|
||||
self._state.html = html
|
||||
|
||||
def render(self):
|
||||
return Div(
|
||||
self._id
|
||||
NotStr(self._state.html),
|
||||
id=self._id
|
||||
)
|
||||
|
||||
def __ft__(self):
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
import pandas as pd
|
||||
from fastcore.basics import NotStr
|
||||
from fasthtml.components import Div
|
||||
|
||||
from myfasthtml.controls.BaseCommands import BaseCommands
|
||||
from myfasthtml.controls.DataGrid import DataGrid
|
||||
from myfasthtml.controls.FileUpload import FileUpload
|
||||
from myfasthtml.controls.Panel import Panel
|
||||
from myfasthtml.controls.TabsManager import TabsManager
|
||||
from myfasthtml.controls.TreeView import TreeView, TreeNode
|
||||
from myfasthtml.controls.helpers import mk
|
||||
@@ -76,8 +77,10 @@ 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)
|
||||
content = df.to_html(index=False)
|
||||
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)
|
||||
document = DocumentDefinition(
|
||||
namespace=file_upload.get_file_basename(),
|
||||
name=file_upload.get_sheet_name(),
|
||||
@@ -89,7 +92,7 @@ class DataGridsManager(MultipleInstance):
|
||||
parent_id = self._tree.ensure_path(document.namespace)
|
||||
tree_node = TreeNode(label=document.name, type="excel", parent=parent_id)
|
||||
self._tree.add_node(tree_node, parent_id=parent_id)
|
||||
return self._mk_tree(), self._tabs_manager.change_tab_content(tab_id, document.name, NotStr(content))
|
||||
return self._mk_tree(), self._tabs_manager.change_tab_content(tab_id, document.name, Panel(self).set_main(dg))
|
||||
|
||||
def clear_tree(self):
|
||||
self._state.elements = []
|
||||
|
||||
@@ -111,10 +111,10 @@ class TabsManager(MultipleInstance):
|
||||
if tab_id not in self._state.tabs:
|
||||
return Div("Tab not found.")
|
||||
tab_config = self._state.tabs[tab_id]
|
||||
if tab_config["component_type"] is None:
|
||||
if tab_config["component"] is None:
|
||||
return Div("Tab content does not support serialization.")
|
||||
try:
|
||||
return InstancesManager.get(self._session, tab_config["component_id"])
|
||||
return InstancesManager.get(self._session, tab_config["component"][1])
|
||||
except Exception as e:
|
||||
logger.error(f"Error while retrieving tab content: {e}")
|
||||
return Div("Failed to retrieve tab content.")
|
||||
@@ -384,8 +384,7 @@ class TabsManager(MultipleInstance):
|
||||
|
||||
if component_id is not None:
|
||||
for tab_id, tab_data in self._state.tabs.items():
|
||||
if (tab_data.get('component_type') == component_type and
|
||||
tab_data.get('component_id') == component_id and
|
||||
if (tab_data.get('component') == (component_type, component_id) and
|
||||
tab_data.get('label') == label):
|
||||
return tab_id
|
||||
|
||||
@@ -399,16 +398,21 @@ class TabsManager(MultipleInstance):
|
||||
|
||||
# Extract component ID if the component has a get_id() method
|
||||
component_type, component_id = None, None
|
||||
parent_type, parent_id = None, None
|
||||
if isinstance(component, BaseInstance):
|
||||
component_type = component.get_prefix()
|
||||
component_id = component.get_id()
|
||||
parent = component.get_parent()
|
||||
if parent:
|
||||
parent_type = parent.get_prefix()
|
||||
parent_id = parent.get_id()
|
||||
|
||||
# Add tab metadata to state
|
||||
state.tabs[tab_id] = {
|
||||
'id': tab_id,
|
||||
'label': label,
|
||||
'component_type': component_type,
|
||||
'component_id': component_id
|
||||
'component': (component_type, component_id) if component_type else None,
|
||||
'component_parent': (parent_type, parent_id) if parent_type else None
|
||||
}
|
||||
|
||||
# Add tab to order list
|
||||
|
||||
@@ -37,6 +37,7 @@ class TreeNode:
|
||||
type: str = "default"
|
||||
parent: Optional[str] = None
|
||||
children: list[str] = field(default_factory=list)
|
||||
bag: Optional[dict] = None # to keep extra info
|
||||
|
||||
|
||||
class TreeViewState(DbObject):
|
||||
|
||||
@@ -98,6 +98,8 @@ class DbObject:
|
||||
properties = {}
|
||||
if args:
|
||||
arg = args[0]
|
||||
if arg is None:
|
||||
return self
|
||||
if not isinstance(arg, (dict, SimpleNamespace)):
|
||||
raise ValueError("Only dict or Expando are allowed as argument")
|
||||
properties |= vars(arg) if isinstance(arg, SimpleNamespace) else arg
|
||||
|
||||
@@ -51,8 +51,8 @@ class TestTabsManagerBehaviour:
|
||||
assert tab_id in tabs_manager.get_state().tabs
|
||||
assert tabs_manager.get_state().tabs[tab_id]["label"] == "Tab1"
|
||||
assert tabs_manager.get_state().tabs[tab_id]["id"] == tab_id
|
||||
assert tabs_manager.get_state().tabs[tab_id]["component_type"] is None
|
||||
assert tabs_manager.get_state().tabs[tab_id]["component_id"] is None
|
||||
assert tabs_manager.get_state().tabs[tab_id]["component"] is None
|
||||
assert tabs_manager.get_state().tabs[tab_id]["component_parent"] is None
|
||||
assert tabs_manager.get_state().tabs_order == [tab_id]
|
||||
assert tabs_manager.get_state().active_tab == tab_id
|
||||
|
||||
@@ -61,9 +61,12 @@ class TestTabsManagerBehaviour:
|
||||
vis_network = VisNetwork(tabs_manager, nodes=[], edges=[])
|
||||
tab_id = tabs_manager.create_tab("Network", vis_network)
|
||||
|
||||
component_type, component_id = vis_network.get_prefix(), vis_network.get_id()
|
||||
parent_type, parent_id = tabs_manager.get_prefix(), tabs_manager.get_id()
|
||||
|
||||
assert tab_id is not None
|
||||
assert tabs_manager.get_state().tabs[tab_id]["component_type"] == vis_network.get_prefix()
|
||||
assert tabs_manager.get_state().tabs[tab_id]["component_id"] == vis_network.get_id()
|
||||
assert tabs_manager.get_state().tabs[tab_id]["component"] == (component_type, component_id)
|
||||
assert tabs_manager.get_state().tabs[tab_id]["component_parent"] == (parent_type, parent_id)
|
||||
|
||||
def test_i_can_create_multiple_tabs(self, tabs_manager):
|
||||
"""Test creating multiple tabs maintains correct order and activation."""
|
||||
|
||||
Reference in New Issue
Block a user