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