Dialog box at the bottom. Property layout fully operationnel

This commit is contained in:
2025-08-04 10:34:11 +02:00
parent 4ac3eb2dfa
commit badc2e28b0
4 changed files with 101 additions and 54 deletions

View File

@@ -59,6 +59,7 @@
box-sizing: border-box;
font-family: Arial, sans-serif;
background-color: var(--color-base-100); /* bg-base-100 */
overflow: auto;
}
@@ -79,10 +80,10 @@
}
.wkf-properties-properties {
display: inline-block;
vertical-align: top;
position: relative;
box-sizing: border-box;
overflow: auto;
}
.wkf-properties-handle-left {
@@ -105,6 +106,28 @@
background-color: transparent;
}
.wkf-properties-top {
display: flex;
justify-content: center;
align-items: center;
cursor: move;
padding: 4px;
}
.wkf-properties-handle-top {
background-image: radial-gradient(var(--color-splitter) 40%, transparent 0);
background-repeat: repeat;
background-size: 4px 4px;
cursor: move;
display: flex;
justify-content: center;
align-items: center;
height: 8px;
width: 20px;
position: relative;
top: 1px;
}
.wkf-canvas {
position: relative;
box-sizing: border-box;

View File

@@ -11,7 +11,8 @@ from components.workflows.assets.icons import icon_play, icon_pause, icon_stop,
from components.workflows.commands import WorkflowDesignerCommandManager
from components.workflows.components.WorkflowDesignerProperties import WorkflowDesignerProperties
from components.workflows.components.WorkflowPlayer import WorkflowPlayer
from components.workflows.constants import WORKFLOW_DESIGNER_INSTANCE_ID, ProcessorTypes
from components.workflows.constants import WORKFLOW_DESIGNER_INSTANCE_ID, ProcessorTypes, COMPONENT_TYPES, \
PROCESSOR_TYPES
from components.workflows.db_management import WorkflowsDesignerSettings, WorkflowComponent, \
Connection, WorkflowsDesignerDbManager, ComponentState, WorkflowsDesignerState
from components_helpers import apply_boundaries, mk_tooltip, mk_dialog_buttons, mk_icon
@@ -23,32 +24,6 @@ from utils.DbManagementHelper import DbManagementHelper
logger = logging.getLogger("WorkflowDesigner")
# Component templates
COMPONENT_TYPES = {
ProcessorTypes.Producer: {
"title": "Data Producer",
"description": "Generates or loads data",
"icon": "📊",
"color": "bg-green-100 border-green-300 text-neutral"
},
ProcessorTypes.Filter: {
"title": "Data Filter",
"description": "Filters and transforms data",
"icon": "🔍",
"color": "bg-blue-100 border-blue-300 text-neutral"
},
ProcessorTypes.Presenter: {
"title": "Data Presenter",
"description": "Displays or exports data",
"icon": "📋",
"color": "bg-purple-100 border-purple-300 text-neutral"
}
}
PROCESSOR_TYPES = {
ProcessorTypes.Producer: ["Repository", "Jira"],
ProcessorTypes.Filter: ["Default"],
ProcessorTypes.Presenter: ["Default"]}
class WorkflowDesigner(BaseComponent):
@@ -216,7 +191,7 @@ class WorkflowDesigner(BaseComponent):
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)
return self.refresh_properties(), self._undo_redo.refresh()
return self.properties.refresh(), self._undo_redo.refresh()
def save_properties(self, component_id: str, details: dict):
if component_id in self._state.components:

View File

@@ -2,6 +2,9 @@ from fasthtml.common import *
from dataclasses import dataclass
from components.BaseComponent import BaseComponent
from components.workflows.constants import COMPONENT_TYPES
from components_helpers import mk_dialog_buttons
from core.utils import merge_classes
@dataclass
@@ -17,12 +20,12 @@ class WorkflowDesignerProperties(BaseComponent):
self._owner = owner
self._boundaries = self._owner.get_boundaries()
self._commands = self._owner.commands
self.layout = self.compute_layout()
self.layout = None
self._component = None
self.update_layout()
self.update_component(self._owner.get_state().selected_component_id)
def update_layout(self):
self.layout = self.compute_layout()
def compute_layout(self) -> DesignerLayout:
if self._owner.get_state().properties_input_width is None:
input_width = self._boundaries["width"] // 3
properties_width = self._boundaries["width"] // 3
@@ -32,13 +35,19 @@ class WorkflowDesignerProperties(BaseComponent):
properties_width = self._owner.get_state().properties_properties_width
output_width = self._owner.get_state().properties_output_width
return DesignerLayout(
self.layout = DesignerLayout(
input_width=input_width,
properties_width=properties_width,
output_width=output_width
)
def update_component(self, component_id):
if component_id is None or component_id not in self._owner.get_state().components:
self._component = None
self._component = self._owner.get_state().components[component_id]
def refresh(self, oob=True):
self.update_component(self._owner.get_state().selected_component_id)
return self.__ft__(oob=oob)
def _mk_input(self):
@@ -57,30 +66,44 @@ class WorkflowDesignerProperties(BaseComponent):
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):
return Div(
# Drag handle (20px height)
Div(
"Properties",
A(cls="wkf-properties-handle-top"),
cls="wkf-properties-top",
id=f"ppt_{self._id}",
style="height: 20px; background-color: #ddd; cursor: move; text-align: center; line-height: 20px; font-weight: bold; font-size: 12px; border-bottom: 1px solid #bbb;"
),
# Properties content
Div(
Input(placeholder="output name", style="width: 100%; margin-bottom: 10px;"),
Select(
Option("Repository", value="repository"),
Option("Jira", value="jira"),
style="width: 100%; margin-bottom: 10px;"
),
Div(
Button("Save", **self._commands.on_save(), style="margin-right: 5px; padding: 5px 10px;"),
Button("Cancel", **self._commands.on_cancel(), style="padding: 5px 10px;"),
style="text-align: center;"
),
style=f"padding: 10px; box-sizing: border-box;"
),
self._mk_header(cls="flex-none"),
self._mk_form(cls="flex-1 overflow-y-auto"),
mk_dialog_buttons(cls="flex-none mt-auto pb-2"),
# Left resize handle
Div(
@@ -95,9 +118,8 @@ class WorkflowDesignerProperties(BaseComponent):
),
id=f"pp_{self._id}",
style=f"width: {self.layout.properties_width}px;",
cls="wkf-properties-properties"
style=f"width: {self.layout.properties_width}px; height: 100%;",
cls="wkf-properties-properties flex flex-col",
)
def _mk_layout(self):

View File

@@ -6,11 +6,39 @@ WORKFLOW_DESIGNER_DB_ENTRY = "WorkflowDesigner"
WORKFLOW_DESIGNER_DB_SETTINGS_ENTRY = "Settings"
WORKFLOW_DESIGNER_DB_STATE_ENTRY = "State"
class ProcessorTypes:
Producer = "producer"
Filter = "filter"
Presenter = "presenter"
COMPONENT_TYPES = {
ProcessorTypes.Producer: {
"title": "Data Producer",
"description": "Generates or loads data",
"icon": "📊",
"color": "bg-green-100 border-green-300 text-neutral"
},
ProcessorTypes.Filter: {
"title": "Data Filter",
"description": "Filters and transforms data",
"icon": "🔍",
"color": "bg-blue-100 border-blue-300 text-neutral"
},
ProcessorTypes.Presenter: {
"title": "Data Presenter",
"description": "Displays or exports data",
"icon": "📋",
"color": "bg-purple-100 border-purple-300 text-neutral"
}
}
PROCESSOR_TYPES = {
ProcessorTypes.Producer: ["Repository", "Jira"],
ProcessorTypes.Filter: ["Default"],
ProcessorTypes.Presenter: ["Default"]}
ROUTE_ROOT = "/workflows"
@@ -34,4 +62,3 @@ class Routes:
PauseWorkflow = "/pause-workflow"
StopWorkflow = "/stop-workflow"
Refresh = "/refresh"