Fixed transform issue and added reset
This commit is contained in:
@@ -69,7 +69,7 @@ class Commands(BaseCommands):
|
||||
"UpdateViewState",
|
||||
"Update view transform and layout mode",
|
||||
self._owner,
|
||||
self._owner._handle_update_view_state
|
||||
self._owner.handle_update_view_state
|
||||
).htmx(target=f"#{self._id}", swap='none')
|
||||
|
||||
def apply_filter(self):
|
||||
@@ -81,9 +81,21 @@ class Commands(BaseCommands):
|
||||
"ApplyFilter",
|
||||
"Apply filter to graph",
|
||||
self._owner,
|
||||
self._owner._handle_apply_filter,
|
||||
self._owner.handle_apply_filter,
|
||||
key="#{id}-apply-filter",
|
||||
).htmx(target=f"#{self._id}")
|
||||
|
||||
def reset_view(self):
|
||||
"""Reset the view transform to default values.
|
||||
|
||||
This command can be used to fix stuck/frozen canvas by resetting zoom/pan state.
|
||||
"""
|
||||
return Command(
|
||||
"ResetTransform",
|
||||
"Reset view transform",
|
||||
self._owner,
|
||||
self._owner.handle_reset_view
|
||||
).htmx(target=f"#{self._id}")
|
||||
|
||||
|
||||
class HierarchicalCanvasGraph(MultipleInstance):
|
||||
@@ -135,64 +147,81 @@ class HierarchicalCanvasGraph(MultipleInstance):
|
||||
"""
|
||||
return self._state
|
||||
|
||||
def get_selected_id(self) -> Optional[str]:
|
||||
"""Get the currently selected node ID.
|
||||
|
||||
Returns:
|
||||
str or None: The selected node ID, or None if no selection
|
||||
"""
|
||||
return self._state.ns_selected_id
|
||||
# def get_selected_id(self) -> Optional[str]:
|
||||
# """Get the currently selected node ID.
|
||||
#
|
||||
# Returns:
|
||||
# str or None: The selected node ID, or None if no selection
|
||||
# """
|
||||
# return self._state.ns_selected_id
|
||||
#
|
||||
# def set_collapsed(self, node_ids: set):
|
||||
# """Set the collapsed state of nodes.
|
||||
#
|
||||
# Args:
|
||||
# node_ids: Set of node IDs to mark as collapsed
|
||||
# """
|
||||
# self._state.collapsed = list(node_ids)
|
||||
# logger.debug(f"set_collapsed: {len(node_ids)} nodes collapsed")
|
||||
#
|
||||
# def toggle_node(self, node_id: str):
|
||||
# """Toggle the collapsed state of a node.
|
||||
#
|
||||
# Args:
|
||||
# node_id: The ID of the node to toggle
|
||||
#
|
||||
# Returns:
|
||||
# self: For chaining
|
||||
# """
|
||||
# collapsed_set = set(self._state.collapsed)
|
||||
# if node_id in collapsed_set:
|
||||
# collapsed_set.remove(node_id)
|
||||
# logger.debug(f"toggle_node: expanded {node_id}")
|
||||
# else:
|
||||
# collapsed_set.add(node_id)
|
||||
# logger.debug(f"toggle_node: collapsed {node_id}")
|
||||
#
|
||||
# self._state.collapsed = list(collapsed_set)
|
||||
# return self
|
||||
|
||||
def set_collapsed(self, node_ids: set):
|
||||
"""Set the collapsed state of nodes.
|
||||
|
||||
Args:
|
||||
node_ids: Set of node IDs to mark as collapsed
|
||||
"""
|
||||
self._state.collapsed = list(node_ids)
|
||||
logger.debug(f"set_collapsed: {len(node_ids)} nodes collapsed")
|
||||
|
||||
def toggle_node(self, node_id: str):
|
||||
"""Toggle the collapsed state of a node.
|
||||
|
||||
Args:
|
||||
node_id: The ID of the node to toggle
|
||||
|
||||
Returns:
|
||||
self: For chaining
|
||||
"""
|
||||
collapsed_set = set(self._state.collapsed)
|
||||
if node_id in collapsed_set:
|
||||
collapsed_set.remove(node_id)
|
||||
logger.debug(f"toggle_node: expanded {node_id}")
|
||||
else:
|
||||
collapsed_set.add(node_id)
|
||||
logger.debug(f"toggle_node: collapsed {node_id}")
|
||||
|
||||
self._state.collapsed = list(collapsed_set)
|
||||
return self
|
||||
|
||||
def _handle_update_view_state(self, transform=None, layout_mode=None):
|
||||
def handle_update_view_state(self, transform: Optional[dict] = None, layout_mode: Optional[str] = None):
|
||||
"""Internal handler to update view state from client.
|
||||
|
||||
Args:
|
||||
transform: Optional dict with zoom/pan transform state
|
||||
transform: Optional dict with zoom/pan transform state (received as JSON string)
|
||||
layout_mode: Optional string with layout orientation
|
||||
|
||||
Returns:
|
||||
str: Empty string (no UI update needed)
|
||||
"""
|
||||
if transform is not None:
|
||||
# Parse JSON string to dict (sent as JSON.stringify() from JS)
|
||||
if isinstance(transform, str):
|
||||
try:
|
||||
transform = json.loads(transform)
|
||||
except (json.JSONDecodeError, TypeError) as e:
|
||||
logger.error(f"Failed to parse transform JSON: {e}")
|
||||
return ""
|
||||
|
||||
self._state.transform = transform
|
||||
logger.debug(f"Transform updated: {self._state.transform}")
|
||||
|
||||
if layout_mode is not None:
|
||||
self._state.layout_mode = layout_mode
|
||||
logger.debug(f"Layout mode updated: {self._state.layout_mode}")
|
||||
|
||||
return ""
|
||||
|
||||
def _handle_apply_filter(self, query_param="text", value=None):
|
||||
def handle_reset_view(self):
|
||||
"""Internal handler to reset view transform to default values.
|
||||
|
||||
Returns:
|
||||
self: For HTMX to render the updated graph with reset transform
|
||||
"""
|
||||
self._state.transform = {"x": 0, "y": 0, "scale": 1}
|
||||
self._state.collapsed = []
|
||||
logger.debug("Transform and collapsed state reset to defaults")
|
||||
return self
|
||||
|
||||
def handle_apply_filter(self, query_param="text", value=None):
|
||||
"""Internal handler to apply filter and re-render the graph.
|
||||
|
||||
Args:
|
||||
|
||||
Reference in New Issue
Block a user