Properties Details correctly reacts on user interaction
This commit is contained in:
@@ -16,6 +16,7 @@ using `_id={WORKFLOW_DESIGNER_INSTANCE_ID}{session['user_id']}{get_unique_id()}`
|
|||||||
| Properties Properties drag top | `ppt_{self._id}` |
|
| Properties Properties drag top | `ppt_{self._id}` |
|
||||||
| Properties Properties drag left | `ppl_{self._id}` |
|
| Properties Properties drag left | `ppl_{self._id}` |
|
||||||
| Properties Properties drag right | `ppr_{self._id}` |
|
| Properties Properties drag right | `ppr_{self._id}` |
|
||||||
|
| Properties Properties content | `ppc_{self._id}` |
|
||||||
| Spliter | `s_{self._id}` |
|
| Spliter | `s_{self._id}` |
|
||||||
| Top element | `t_{self._id}` |
|
| Top element | `t_{self._id}` |
|
||||||
| Form for properties | `f_{self._id}_{component_id}` |
|
| Form for properties | `f_{self._id}_{component_id}` |
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ function bindWorkflowDesignerToolbox(elementId) {
|
|||||||
// Also trigger server-side selection
|
// Also trigger server-side selection
|
||||||
utils.makeRequest('/workflows/select-component', {
|
utils.makeRequest('/workflows/select-component', {
|
||||||
component_id: designer.selectedComponent
|
component_id: designer.selectedComponent
|
||||||
}, `#p_${elementId}`, "outerHTML");
|
}, `#ppc_${elementId}`, "outerHTML");
|
||||||
},
|
},
|
||||||
|
|
||||||
// Deselect all components
|
// Deselect all components
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class WorkflowDesignerCommandManager(BaseCommandManager):
|
|||||||
def select_processor(self, component_id: str):
|
def select_processor(self, component_id: str):
|
||||||
return {
|
return {
|
||||||
"hx_post": f"{ROUTE_ROOT}{Routes.SelectProcessor}",
|
"hx_post": f"{ROUTE_ROOT}{Routes.SelectProcessor}",
|
||||||
"hx-target": f"#p_{self._id}",
|
"hx-target": f"#ppc_{self._id}",
|
||||||
"hx-swap": "outerHTML",
|
"hx-swap": "outerHTML",
|
||||||
"hx-trigger": "change",
|
"hx-trigger": "change",
|
||||||
"hx-vals": f'js:{{"_id": "{self._id}", "component_id": "{component_id}"}}',
|
"hx-vals": f'js:{{"_id": "{self._id}", "component_id": "{component_id}"}}',
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ from utils.DbManagementHelper import DbManagementHelper
|
|||||||
logger = logging.getLogger("WorkflowDesigner")
|
logger = logging.getLogger("WorkflowDesigner")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WorkflowDesigner(BaseComponent):
|
class WorkflowDesigner(BaseComponent):
|
||||||
def __init__(self, session,
|
def __init__(self, session,
|
||||||
_id=None,
|
_id=None,
|
||||||
@@ -121,7 +120,7 @@ class WorkflowDesigner(BaseComponent):
|
|||||||
undo_redo_attrs = UndoRedoAttrs(f"Move Component '{component.title}'", on_undo=self.refresh_state)
|
undo_redo_attrs = UndoRedoAttrs(f"Move Component '{component.title}'", on_undo=self.refresh_state)
|
||||||
self._db.save_state(self._key, self._state, undo_redo_attrs) # update db
|
self._db.save_state(self._key, self._state, undo_redo_attrs) # update db
|
||||||
|
|
||||||
return self.refresh_designer(), self.properties.refresh(), self._undo_redo.refresh()
|
return self.refresh_designer(), self.properties.refresh(mode="form", oob=True), self._undo_redo.refresh()
|
||||||
|
|
||||||
def delete_component(self, component_id):
|
def delete_component(self, component_id):
|
||||||
# Remove component
|
# Remove component
|
||||||
@@ -191,7 +190,7 @@ class WorkflowDesigner(BaseComponent):
|
|||||||
undo_redo_attrs = UndoRedoAttrs(f"Select Component {component.title}", on_undo=self.refresh_state)
|
undo_redo_attrs = UndoRedoAttrs(f"Select Component {component.title}", on_undo=self.refresh_state)
|
||||||
self._db.save_state(self._key, self._state, undo_redo_attrs)
|
self._db.save_state(self._key, self._state, undo_redo_attrs)
|
||||||
|
|
||||||
return self.properties.refresh(), self._undo_redo.refresh()
|
return self.properties.refresh(mode="form"), self._undo_redo.refresh()
|
||||||
|
|
||||||
def save_properties(self, component_id: str, details: dict):
|
def save_properties(self, component_id: str, details: dict):
|
||||||
if component_id in self._state.components:
|
if component_id in self._state.components:
|
||||||
@@ -217,7 +216,7 @@ class WorkflowDesigner(BaseComponent):
|
|||||||
|
|
||||||
undo_redo_attrs = UndoRedoAttrs(f"Set Processor for {component.title}", on_undo=self.refresh_state)
|
undo_redo_attrs = UndoRedoAttrs(f"Set Processor for {component.title}", on_undo=self.refresh_state)
|
||||||
self._db.save_state(self._key, self._state, undo_redo_attrs)
|
self._db.save_state(self._key, self._state, undo_redo_attrs)
|
||||||
return self.refresh_properties(), self._undo_redo.refresh()
|
return self.properties.refresh(mode="form"), self._undo_redo.refresh()
|
||||||
|
|
||||||
def play_workflow(self, boundaries: dict):
|
def play_workflow(self, boundaries: dict):
|
||||||
self._error_message = None
|
self._error_message = None
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from fasthtml.common import *
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from components.BaseComponent import BaseComponent
|
from components.BaseComponent import BaseComponent
|
||||||
from components.workflows.constants import COMPONENT_TYPES
|
from components.workflows.constants import COMPONENT_TYPES, PROCESSOR_TYPES
|
||||||
from components_helpers import mk_dialog_buttons
|
from components_helpers import mk_dialog_buttons
|
||||||
from core.utils import merge_classes
|
from core.utils import merge_classes
|
||||||
|
|
||||||
@@ -44,12 +44,25 @@ class WorkflowDesignerProperties(BaseComponent):
|
|||||||
def update_component(self, component_id):
|
def update_component(self, component_id):
|
||||||
if component_id is None or component_id not in self._owner.get_state().components:
|
if component_id is None or component_id not in self._owner.get_state().components:
|
||||||
self._component = None
|
self._component = None
|
||||||
self._component = self._owner.get_state().components[component_id]
|
else:
|
||||||
|
self._component = self._owner.get_state().components[component_id]
|
||||||
|
|
||||||
def refresh(self, oob=True):
|
def refresh(self, mode="all", oob=False):
|
||||||
self.update_component(self._owner.get_state().selected_component_id)
|
self.update_component(self._owner.get_state().selected_component_id)
|
||||||
|
if mode == "form":
|
||||||
|
return self._mk_content(oob=oob)
|
||||||
|
|
||||||
return self.__ft__(oob=oob)
|
return self.__ft__(oob=oob)
|
||||||
|
|
||||||
|
def _mk_layout(self):
|
||||||
|
return Div(
|
||||||
|
self._mk_input(),
|
||||||
|
self._mk_properties(),
|
||||||
|
self._mk_output(),
|
||||||
|
cls="flex",
|
||||||
|
style="height: 100%; width: 100%; flex: 1;"
|
||||||
|
)
|
||||||
|
|
||||||
def _mk_input(self):
|
def _mk_input(self):
|
||||||
return Div(
|
return Div(
|
||||||
"Input",
|
"Input",
|
||||||
@@ -66,30 +79,6 @@ class WorkflowDesignerProperties(BaseComponent):
|
|||||||
cls="wkf-properties-output"
|
cls="wkf-properties-output"
|
||||||
)
|
)
|
||||||
|
|
||||||
def _mk_header(self, cls=None):
|
|
||||||
if self._component is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
icon = COMPONENT_TYPES[self._component.type]["icon"]
|
|
||||||
color = COMPONENT_TYPES[self._component.type]["color"]
|
|
||||||
return Div(
|
|
||||||
Div(
|
|
||||||
Span(icon),
|
|
||||||
H4(self._component.title, cls="font-semibold text-xs"),
|
|
||||||
cls=f"rounded-lg border-2 {color} flex text-center px-2"
|
|
||||||
),
|
|
||||||
H1(self._component.id, cls="ml-4"),
|
|
||||||
cls=merge_classes("flex mb-2", cls)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _mk_form(self, cls=None):
|
|
||||||
if self._component is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return Div(
|
|
||||||
cls=merge_classes(cls)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _mk_properties(self):
|
def _mk_properties(self):
|
||||||
return Div(
|
return Div(
|
||||||
# Drag handle (20px height)
|
# Drag handle (20px height)
|
||||||
@@ -100,9 +89,9 @@ class WorkflowDesignerProperties(BaseComponent):
|
|||||||
),
|
),
|
||||||
|
|
||||||
# Properties content
|
# Properties content
|
||||||
|
self._mk_content(cls="flex-1 overflow-y-auto"),
|
||||||
|
|
||||||
self._mk_header(cls="flex-none"),
|
# Dialog buttons
|
||||||
self._mk_form(cls="flex-1 overflow-y-auto"),
|
|
||||||
mk_dialog_buttons(cls="flex-none mt-auto pb-2"),
|
mk_dialog_buttons(cls="flex-none mt-auto pb-2"),
|
||||||
|
|
||||||
# Left resize handle
|
# Left resize handle
|
||||||
@@ -122,22 +111,67 @@ class WorkflowDesignerProperties(BaseComponent):
|
|||||||
cls="wkf-properties-properties flex flex-col",
|
cls="wkf-properties-properties flex flex-col",
|
||||||
)
|
)
|
||||||
|
|
||||||
def _mk_layout(self):
|
def _mk_content(self, cls=None, oob=False):
|
||||||
|
|
||||||
return Div(
|
return Div(
|
||||||
self._mk_input(),
|
self._header(),
|
||||||
self._mk_properties(),
|
self._form(),
|
||||||
self._mk_output(),
|
cls=merge_classes(cls),
|
||||||
cls="flex",
|
id=f"ppc_{self._id}",
|
||||||
style="height: 100%; width: 100%; flex: 1;"
|
hx_swap_oob=f'true' if oob else None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _header(self):
|
||||||
|
if self._component is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
icon = COMPONENT_TYPES[self._component.type]["icon"]
|
||||||
|
color = COMPONENT_TYPES[self._component.type]["color"]
|
||||||
|
return Div(
|
||||||
|
Div(
|
||||||
|
Span(icon),
|
||||||
|
H4(self._component.title, cls="font-semibold text-xs"),
|
||||||
|
cls=f"rounded-lg border-2 {color} flex text-center px-2"
|
||||||
|
),
|
||||||
|
cls=merge_classes("flex"),
|
||||||
|
)
|
||||||
|
|
||||||
|
def _form(self):
|
||||||
|
if self._component is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return Form(
|
||||||
|
self._mk_select_processor(),
|
||||||
|
self._content_details(),
|
||||||
|
)
|
||||||
|
|
||||||
|
def _mk_select_processor(self):
|
||||||
|
selected_processor_name = self._component.properties["processor_name"]
|
||||||
|
return Select(
|
||||||
|
*[Option(processor_name, selected="selected" if processor_name == selected_processor_name else None)
|
||||||
|
for processor_name in PROCESSOR_TYPES[self._component.type]],
|
||||||
|
cls="select select-sm m-2",
|
||||||
|
id="processor_name",
|
||||||
|
name="processor_name",
|
||||||
|
**self._commands.select_processor(self._component.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
def _content_details(self):
|
||||||
|
component_type = self._component.type
|
||||||
|
processor_name = self._component.properties.get("processor_name", None)
|
||||||
|
key = f"_mk_details_{component_type}_{processor_name}"
|
||||||
|
if hasattr(self, key):
|
||||||
|
return getattr(self, key)()
|
||||||
|
else:
|
||||||
|
return Div(f"Component '{key}' not found")
|
||||||
|
|
||||||
def __ft__(self, oob=False):
|
def __ft__(self, oob=False):
|
||||||
# return self.render()
|
# return self.render()
|
||||||
return Div(
|
return Div(
|
||||||
self._mk_layout(),
|
self._mk_layout(),
|
||||||
style=f"height: {self._get_height()}px;",
|
style=f"height: {self._get_height()}px;",
|
||||||
id=f"p_{self._id}",
|
id=f"p_{self._id}",
|
||||||
hx_swap_oob='true' if oob else None,
|
hx_swap_oob=f'innerHTML' if oob else None,
|
||||||
cls="wkf-properties"
|
cls="wkf-properties"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user