diff --git a/src/myfasthtml/controls/DataGrid.py b/src/myfasthtml/controls/DataGrid.py
index 909e7ea..53aba86 100644
--- a/src/myfasthtml/controls/DataGrid.py
+++ b/src/myfasthtml/controls/DataGrid.py
@@ -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):
diff --git a/src/myfasthtml/controls/DataGridsManager.py b/src/myfasthtml/controls/DataGridsManager.py
index aada9f5..2f065e2 100644
--- a/src/myfasthtml/controls/DataGridsManager.py
+++ b/src/myfasthtml/controls/DataGridsManager.py
@@ -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 = []
diff --git a/src/myfasthtml/controls/TabsManager.py b/src/myfasthtml/controls/TabsManager.py
index f7825d8..07a12f0 100644
--- a/src/myfasthtml/controls/TabsManager.py
+++ b/src/myfasthtml/controls/TabsManager.py
@@ -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
diff --git a/src/myfasthtml/controls/TreeView.py b/src/myfasthtml/controls/TreeView.py
index fd93536..30f8926 100644
--- a/src/myfasthtml/controls/TreeView.py
+++ b/src/myfasthtml/controls/TreeView.py
@@ -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):
diff --git a/src/myfasthtml/core/dbmanager.py b/src/myfasthtml/core/dbmanager.py
index 97dd8ed..c4bdb00 100644
--- a/src/myfasthtml/core/dbmanager.py
+++ b/src/myfasthtml/core/dbmanager.py
@@ -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
diff --git a/tests/controls/test_tabsmanager.py b/tests/controls/test_tabsmanager.py
index c3599bc..0ec7cdc 100644
--- a/tests/controls/test_tabsmanager.py
+++ b/tests/controls/test_tabsmanager.py
@@ -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."""