Fixed tab recreation logic and improved error handling
This commit is contained in:
@@ -116,7 +116,30 @@ class DataGridsManager(MultipleInstance):
|
|||||||
except StopIteration:
|
except StopIteration:
|
||||||
# the selected node is not a document (it's a folder)
|
# the selected node is not a document (it's a folder)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def create_tab_content(self, tab_id):
|
||||||
|
"""
|
||||||
|
Recreate the content for a tab managed by this DataGridsManager.
|
||||||
|
Called by TabsManager when the content is not in cache (e.g., after restart).
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tab_id: ID of the tab to recreate content for
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The recreated component (Panel with DataGrid)
|
||||||
|
"""
|
||||||
|
# Find the document associated with this tab
|
||||||
|
document = next((d for d in self._state.elements if d.tab_id == tab_id), None)
|
||||||
|
|
||||||
|
if document is None:
|
||||||
|
raise ValueError(f"No document found for tab {tab_id}")
|
||||||
|
|
||||||
|
# Recreate the DataGrid with its saved state
|
||||||
|
dg = DataGrid(self._tabs_manager, _id=document.datagrid_id)
|
||||||
|
|
||||||
|
# Wrap in Panel
|
||||||
|
return Panel(self).set_main(dg)
|
||||||
|
|
||||||
def clear_tree(self):
|
def clear_tree(self):
|
||||||
self._state.elements = []
|
self._state.elements = []
|
||||||
self._tree.clear()
|
self._tree.clear()
|
||||||
|
|||||||
@@ -120,15 +120,36 @@ class TabsManager(MultipleInstance):
|
|||||||
if tab_config["component"] is None:
|
if tab_config["component"] is None:
|
||||||
return Div("Tab content does not support serialization.")
|
return Div("Tab content does not support serialization.")
|
||||||
|
|
||||||
res = InstancesManager.get(self._session, tab_config["component"][1], None)
|
# 1. Try to get existing component instance
|
||||||
|
res = InstancesManager.get(self._session, tab_config["component"][1], None)
|
||||||
if res is not None:
|
if res is not None:
|
||||||
|
logger.debug(f"Component {tab_config['component'][1]} already exists")
|
||||||
return res
|
return res
|
||||||
|
|
||||||
try:
|
# 2. Get or create parent
|
||||||
logger.debug(f"Component not created yet. Need to manually create it.")
|
if tab_config["component_parent"] is None:
|
||||||
return InstancesManager.dynamic_get(self._session, tab_config["component_parent"], tab_config["component"])
|
logger.error(f"No parent defined for tab {tab_id}")
|
||||||
except Exception as e:
|
return Div("Failed to retrieve tab content.")
|
||||||
logger.error(f"Error while retrieving tab content: {e}")
|
|
||||||
|
parent = InstancesManager.get(self._session, tab_config["component_parent"][1], None)
|
||||||
|
if parent is None:
|
||||||
|
logger.error(f"Parent {tab_config['component_parent'][1]} not found for tab {tab_id}")
|
||||||
|
return Div("Parent component not available")
|
||||||
|
|
||||||
|
# 3. If parent supports create_tab_content, use it
|
||||||
|
if hasattr(parent, 'create_tab_content'):
|
||||||
|
try:
|
||||||
|
logger.debug(f"Asking parent {tab_config['component_parent'][1]} to create tab content for {tab_id}")
|
||||||
|
content = parent.create_tab_content(tab_id)
|
||||||
|
# Store in cache
|
||||||
|
self._state.ns_tabs_content[tab_id] = content
|
||||||
|
return content
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error while parent creating tab content: {e}")
|
||||||
|
return Div("Failed to retrieve tab content.")
|
||||||
|
else:
|
||||||
|
# Parent doesn't support create_tab_content, fallback to error
|
||||||
|
logger.error(f"Parent {tab_config['component_parent'][1]} doesn't support create_tab_content")
|
||||||
return Div("Failed to retrieve tab content.")
|
return Div("Failed to retrieve tab content.")
|
||||||
|
|
||||||
def _get_or_create_tab_content(self, tab_id):
|
def _get_or_create_tab_content(self, tab_id):
|
||||||
|
|||||||
@@ -210,15 +210,24 @@ class InstancesManager:
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def dynamic_get(session, component_parent: tuple, component: tuple):
|
def dynamic_get(session, component_parent: tuple, component: tuple):
|
||||||
parent_type, parent_id = component_parent
|
|
||||||
component_type, component_id = component
|
component_type, component_id = component
|
||||||
|
|
||||||
|
# 1. Check if component already exists
|
||||||
|
existing = InstancesManager.get(session, component_id, None)
|
||||||
|
if existing is not None:
|
||||||
|
logger.debug(f"Component {component_id} already exists, returning existing instance")
|
||||||
|
return existing
|
||||||
|
|
||||||
|
# 2. Component doesn't exist, create it
|
||||||
|
parent_type, parent_id = component_parent
|
||||||
|
|
||||||
# parent should always exist
|
# parent should always exist
|
||||||
parent = InstancesManager.get(session, parent_id)
|
parent = InstancesManager.get(session, parent_id)
|
||||||
|
|
||||||
real_component_type = snake_to_pascal(component_type.removeprefix("mf-"))
|
real_component_type = snake_to_pascal(component_type.removeprefix("mf-"))
|
||||||
component_full_type = f"myfasthtml.controls.{real_component_type}.{real_component_type}"
|
component_full_type = f"myfasthtml.controls.{real_component_type}.{real_component_type}"
|
||||||
cls = get_class(component_full_type)
|
cls = get_class(component_full_type)
|
||||||
|
logger.debug(f"Creating new component {component_id} of type {real_component_type}")
|
||||||
return cls(parent, _id=component_id)
|
return cls(parent, _id=component_id)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
Reference in New Issue
Block a user