From fa3da6267d65a233c8e999e91c2384535d027a62 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 29 Jun 2022 10:48:44 +0200 Subject: [PATCH] Designer improvements --- .../src/components.d.ts | 3 +- .../activities/flowchart/flowchart.tsx | 35 ++++++++++++++++--- .../activity-properties-editor.tsx | 2 +- .../workflow-definition-editor.tsx | 32 ++++++++++++++--- .../src/models/event-args.ts | 6 ++++ 5 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/designer/elsa-workflows-designer/src/components.d.ts b/src/designer/elsa-workflows-designer/src/components.d.ts index f91d61451..11f273308 100644 --- a/src/designer/elsa-workflows-designer/src/components.d.ts +++ b/src/designer/elsa-workflows-designer/src/components.d.ts @@ -5,7 +5,7 @@ * It contains typing information for all components that exist in this project. */ import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; -import { ActionDefinition, ActionInvokedArgs, Activity, ActivitySelectedArgs, ChildActivitySelectedArgs, ContainerSelectedArgs, EditChildActivityArgs, GraphUpdatedArgs, IntellisenseContext, SelectListItem, TabChangedArgs, TabDefinition, Variable, WorkflowDefinition, WorkflowDefinitionSummary, WorkflowInstance, WorkflowInstanceSummary } from "./models"; +import { ActionDefinition, ActionInvokedArgs, Activity, ActivityDeletedArgs, ActivitySelectedArgs, ChildActivitySelectedArgs, ContainerSelectedArgs, EditChildActivityArgs, GraphUpdatedArgs, IntellisenseContext, SelectListItem, TabChangedArgs, TabDefinition, Variable, WorkflowDefinition, WorkflowDefinitionSummary, WorkflowInstance, WorkflowInstanceSummary } from "./models"; import { ActivityIdUpdatedArgs, ActivityUpdatedArgs, DeleteActivityRequestedArgs } from "./components/designer/workflow-definition-editor/activity-properties-editor"; import { Button } from "./components/shared/button-group/models"; import { ContainerActivityComponent } from "./components/activities/container-activity-component"; @@ -684,6 +684,7 @@ declare namespace LocalJSX { } interface ElsaFlowchart { "interactiveMode"?: boolean; + "onActivityDeleted"?: (event: CustomEvent) => void; "onActivitySelected"?: (event: CustomEvent) => void; "onContainerSelected"?: (event: CustomEvent) => void; "onGraphUpdated"?: (event: CustomEvent) => void; diff --git a/src/designer/elsa-workflows-designer/src/components/activities/flowchart/flowchart.tsx b/src/designer/elsa-workflows-designer/src/components/activities/flowchart/flowchart.tsx index 7766229c0..46a19da08 100644 --- a/src/designer/elsa-workflows-designer/src/components/activities/flowchart/flowchart.tsx +++ b/src/designer/elsa-workflows-designer/src/components/activities/flowchart/flowchart.tsx @@ -8,7 +8,7 @@ import './ports'; import {ActivityNode as ActivityNodeShape} from './shapes'; import {ContainerActivityComponent} from '../container-activity-component'; import {AddActivityArgs, UpdateActivityArgs} from '../../designer/canvas/canvas'; -import {Activity, ActivitySelectedArgs, ContainerSelectedArgs, GraphUpdatedArgs} from '../../../models'; +import {Activity, ActivityDeletedArgs, ActivitySelectedArgs, ContainerSelectedArgs, GraphUpdatedArgs} from '../../../models'; import {createGraph} from './graph-factory'; import {Connection, Flowchart} from './models'; import {NodeFactory} from "./node-factory"; @@ -45,6 +45,7 @@ export class FlowchartComponent implements ContainerActivityComponent { target: Node; @Event() activitySelected: EventEmitter; + @Event() activityDeleted: EventEmitter; @Event() containerSelected: EventEmitter; @Event() graphUpdated: EventEmitter; @@ -112,6 +113,9 @@ export class FlowchartComponent implements ContainerActivityComponent { const activity = args.activity; const node = this.graph.getNodes().find(x => x.id == nodeId) as any; + if (!node) + return; + // Update the node's data with the activity. node.data = activity; @@ -188,6 +192,7 @@ export class FlowchartComponent implements ContainerActivityComponent { graph.on('node:change:*', this.onGraphChanged); graph.on('node:added', this.onGraphChanged); + graph.on('node:removed', this.onNodeRemoved); graph.on('node:removed', this.onGraphChanged); graph.on('edge:added', this.onGraphChanged); graph.on('edge:removed', this.onGraphChanged); @@ -297,7 +302,15 @@ export class FlowchartComponent implements ContainerActivityComponent { } } - onGraphClick = async (e: PositionEventArgs) => this.containerSelected.emit({}); + onGraphClick = async (e: PositionEventArgs) => { + const activityId = this.activity.id; + + const args: ContainerSelectedArgs = { + activity: this.activity, + applyChanges: async a => await this.updateActivity({id: activityId, activity: a}), + }; + return this.containerSelected.emit(args); + }; onNodeClick = async (e: PositionEventArgs) => { const node = e.node as ActivityNodeShape; @@ -351,9 +364,6 @@ export class FlowchartComponent implements ContainerActivityComponent { } onNodeMoved = (e: PositionEventArgs) => { - - console.debug("Node moved..."); - const node = e.node as ActivityNodeShape; const activity = node.data as Activity; const nodePosition = node.position({relative: false}); @@ -408,6 +418,11 @@ export class FlowchartComponent implements ContainerActivityComponent { this.graphUpdated.emit({exportGraph: this.exportInternal}); } + private onNodeRemoved = (e: any) => { + const activity = e.node.data as Activity; + this.activityDeleted.emit({activity}); + }; + onToggleCanStartWorkflowClicked = (node: ActivityNodeShape) => { const activity = node.data as Activity; activity.canStartWorkflow = !activity.canStartWorkflow; @@ -423,6 +438,11 @@ export class FlowchartComponent implements ContainerActivityComponent { cells = [node]; this.graph.removeCells(cells); + + for (const cell of cells) { + const activity = node.data as Activity; + this.activityDeleted.emit({activity: activity}); + } }; onCopyActivityClicked = (node: ActivityNodeShape) => { @@ -441,5 +461,10 @@ export class FlowchartComponent implements ContainerActivityComponent { cells = [node]; this.graph.cut(cells); + + for (const cell of cells) { + const activity = node.data as Activity; + this.activityDeleted.emit({activity: activity}); + } }; } diff --git a/src/designer/elsa-workflows-designer/src/components/designer/workflow-definition-editor/activity-properties-editor.tsx b/src/designer/elsa-workflows-designer/src/components/designer/workflow-definition-editor/activity-properties-editor.tsx index 436b86241..d0f99c261 100644 --- a/src/designer/elsa-workflows-designer/src/components/designer/workflow-definition-editor/activity-properties-editor.tsx +++ b/src/designer/elsa-workflows-designer/src/components/designer/workflow-definition-editor/activity-properties-editor.tsx @@ -163,8 +163,8 @@ export class ActivityPropertiesEditor { activity.id = newId; - this.activityUpdated.emit({activity, activityDescriptor, propertyName: 'id', propertyDescriptor: inputDescriptor}); this.activityIdUpdated.emit({ activity, activityDescriptor, originalId, newId: activity.id }); + this.activityUpdated.emit({activity, activityDescriptor, propertyName: 'id', propertyDescriptor: inputDescriptor}); } private onActivityDisplayTextChanged(e: any) { diff --git a/src/designer/elsa-workflows-designer/src/components/designer/workflow-definition-editor/workflow-definition-editor.tsx b/src/designer/elsa-workflows-designer/src/components/designer/workflow-definition-editor/workflow-definition-editor.tsx index a4c188159..7c1ca9c81 100644 --- a/src/designer/elsa-workflows-designer/src/components/designer/workflow-definition-editor/workflow-definition-editor.tsx +++ b/src/designer/elsa-workflows-designer/src/components/designer/workflow-definition-editor/workflow-definition-editor.tsx @@ -2,7 +2,18 @@ import {Component, Element, Event, EventEmitter, h, Listen, Method, Prop, State, import {camelCase, debounce} from 'lodash'; import {Container} from "typedi"; import {PanelPosition, PanelStateChangedArgs} from '../panel/models'; -import {Activity, ActivityDescriptor, ActivitySelectedArgs, ChildActivitySelectedArgs, ContainerSelectedArgs, EditChildActivityArgs, GraphUpdatedArgs, WorkflowDefinition, Container as ContainerActivity} from '../../../models'; +import { + Activity, + ActivityDescriptor, + ActivitySelectedArgs, + ChildActivitySelectedArgs, + ContainerSelectedArgs, + EditChildActivityArgs, + GraphUpdatedArgs, + WorkflowDefinition, + Container as ContainerActivity, + ActivityDeletedArgs +} from '../../../models'; import {ActivityIdUpdatedArgs, ActivityUpdatedArgs, DeleteActivityRequestedArgs} from './activity-properties-editor'; import {ActivityDriverRegistry, ActivityNameFormatter, ActivityNode, createActivityMap, createActivityNodeMap, EventBus, flatten, flattenList, PluginRegistry, walkActivities} from '../../../services'; import {MonacoEditorSettings} from "../../../services/monaco-editor-settings"; @@ -67,6 +78,7 @@ export class WorkflowDefinitionEditor { @Listen('containerSelected') private async handleContainerSelected(e: CustomEvent) { this.selectedActivity = this.getCurrentContainer(); + this.applyActivityChanges = e.detail.applyChanges; } @Listen('activitySelected') @@ -91,10 +103,13 @@ export class WorkflowDefinitionEditor { }; } + @Listen('activityDeleted') + private async handleActivityDeleted(e: CustomEvent) { + this.selectedActivity = this.getCurrentContainer(); + } + @Listen('graphUpdated') private async handleGraphUpdated(e: CustomEvent) { - const workflowDefinition = await this.getWorkflowDefinitionInternal(); - await this.updateWorkflowDefinition(workflowDefinition); this.saveChangesDebounced(); } @@ -299,6 +314,7 @@ export class WorkflowDefinitionEditor { workflowDefinition.root = activity; } + this.createNodeMap(workflowDefinition); return workflowDefinition; }; @@ -307,6 +323,8 @@ export class WorkflowDefinitionEditor { }; private saveChanges = async (): Promise => { + const workflowDefinition = await this.getWorkflowDefinitionInternal(); + await this.updateWorkflowDefinition(workflowDefinition); this.workflowUpdated.emit({workflowDefinition: this.workflowDefinitionState}); }; @@ -389,7 +407,10 @@ export class WorkflowDefinitionEditor { private onActivityUpdated = (e: CustomEvent) => { const updatedActivity = e.detail.activity; this.nodeMap[updatedActivity.id] = updatedActivity; - this.applyActivityChanges(updatedActivity); + + if(!!this.applyActivityChanges) + this.applyActivityChanges(updatedActivity); + this.emitActivityChangedDebounced({...e.detail, workflowEditor: this.el}); this.saveChangesDebounced(); } @@ -405,6 +426,7 @@ export class WorkflowDefinitionEditor { item.activityId = newId; this.currentWorkflowPath = [...workflowPath]; + this.createNodeMap(this.workflowDefinition); } private onWorkflowPropsUpdated = (e: CustomEvent) => this.saveChangesDebounced() @@ -425,7 +447,6 @@ export class WorkflowDefinitionEditor { this.currentWorkflowPath = path.slice(0, index + 1); if (!!item.portName) { - debugger; if (!activityDescriptor.isContainer) { const portName = camelCase(item.portName); activity = activity[portName] as Activity; @@ -433,5 +454,6 @@ export class WorkflowDefinitionEditor { } await this.canvas.importGraph(activity); + this.selectedActivity = this.getCurrentContainer(); } } diff --git a/src/designer/elsa-workflows-designer/src/models/event-args.ts b/src/designer/elsa-workflows-designer/src/models/event-args.ts index 357360bed..94b8e73d6 100644 --- a/src/designer/elsa-workflows-designer/src/models/event-args.ts +++ b/src/designer/elsa-workflows-designer/src/models/event-args.ts @@ -6,7 +6,13 @@ export interface ActivitySelectedArgs { deleteActivity: (activity: Activity) => void; } +export interface ActivityDeletedArgs { + activity: Activity; +} + export interface ContainerSelectedArgs { + activity: Activity; + applyChanges: (activity: Activity) => void; } export interface GraphUpdatedArgs {