From d38cac9dedbb0c4ed43d688fa4913286acc359ba Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Tue, 27 Apr 2021 22:14:59 +0200 Subject: [PATCH] Fix (workaround) re-render of tree --- .../elsa-designer-tree/elsa-designer-tree.tsx | 136 +++++++++--------- 1 file changed, 70 insertions(+), 66 deletions(-) diff --git a/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.tsx b/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.tsx index 1c54f7af2..106488ce8 100644 --- a/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.tsx +++ b/src/designer/elsa-workflows-studio/src/components/designers/tree/elsa-designer-tree/elsa-designer-tree.tsx @@ -1,5 +1,5 @@ -import { Component, Host, h, Prop, State, Event, EventEmitter, Watch } from '@stencil/core'; -import { Map, addConnection, findActivity, getChildActivities, getInboundConnections, getOutboundConnections, removeActivity } from '../../../../utils/utils'; +import {Component, Host, h, Prop, State, Event, EventEmitter, Watch} from '@stencil/core'; +import {Map, addConnection, findActivity, getChildActivities, getInboundConnections, getOutboundConnections, removeActivity} from '../../../../utils/utils'; import { ActivityDescriptor, ActivityDesignDisplayContext, @@ -10,14 +10,14 @@ import { WorkflowModel, WorkflowPersistenceBehavior, } from '../../../../models'; -import { eventBus } from '../../../../services/event-bus'; +import {eventBus} from '../../../../services/event-bus'; import jsPlumb from 'jsplumb'; import * as d3 from 'd3'; import dagreD3 from 'dagre-d3'; -import { registerClickOutside } from 'stencil-click-outside'; +import {registerClickOutside} from 'stencil-click-outside'; import state from '../../../../utils/store'; import uuid = jsPlumb.jsPlumbUtil.uuid; -import { ActivityIcon } from '../../../icons/activity-icon'; +import {ActivityIcon} from '../../../icons/activity-icon'; @Component({ tag: 'elsa-designer-tree', @@ -26,8 +26,8 @@ import { ActivityIcon } from '../../../icons/activity-icon'; shadow: false, }) export class ElsaWorkflowDesigner { - @Prop() model: WorkflowModel = { activities: [], connections: [], persistenceBehavior: WorkflowPersistenceBehavior.WorkflowBurst }; - @Event({ eventName: 'workflow-changed', bubbles: true, composed: true, cancelable: true }) workflowChanged: EventEmitter; + @Prop() model: WorkflowModel = {activities: [], connections: [], persistenceBehavior: WorkflowPersistenceBehavior.WorkflowBurst}; + @Event({eventName: 'workflow-changed', bubbles: true, composed: true, cancelable: true}) workflowChanged: EventEmitter; @State() workflowModel: WorkflowModel; el: HTMLElement; @@ -35,7 +35,7 @@ export class ElsaWorkflowDesigner { inner: SVGElement; svgD3Selected: d3.Selection; innerD3Selected: d3.Selection; - zoomParams: { x: number; y: number; scale: number } = { x: 0, y: 0, scale: 1 }; + zoomParams: { x: number; y: number; scale: number } = {x: 0, y: 0, scale: 1}; dagreD3Renderer: dagreD3.Render = new dagreD3.render(); graph: dagreD3.graphlib.Graph = new dagreD3.graphlib.Graph().setGraph({}); @@ -122,7 +122,7 @@ export class ElsaWorkflowDesigner { }; } - const workflowModel = { ...this.workflowModel, activities: [...this.workflowModel.activities, activity] }; + const workflowModel = {...this.workflowModel, activities: [...this.workflowModel.activities, activity]}; if (targetActivityId) { const existingConnection = workflowModel.connections.find(x => x.targetId == targetActivityId && x.outcome == outcome); @@ -137,7 +137,7 @@ export class ElsaWorkflowDesigner { workflowModel.connections.push(replacementConnection); } else { - workflowModel.connections.push({ sourceId: activity.activityId, targetId: targetActivityId, outcome: outcome }); + workflowModel.connections.push({sourceId: activity.activityId, targetId: targetActivityId, outcome: outcome}); } } @@ -153,10 +153,10 @@ export class ElsaWorkflowDesigner { }; workflowModel.connections.push(replacementConnection); - const connection: ConnectionModel = { sourceId: activity.activityId, targetId: existingConnection.targetId, outcome }; + const connection: ConnectionModel = {sourceId: activity.activityId, targetId: existingConnection.targetId, outcome}; workflowModel.connections.push(connection); } else { - const connection: ConnectionModel = { sourceId: sourceActivityId, targetId: activity.activityId, outcome: outcome }; + const connection: ConnectionModel = {sourceId: sourceActivityId, targetId: activity.activityId, outcome: outcome}; workflowModel.connections.push(connection); } } @@ -172,8 +172,8 @@ export class ElsaWorkflowDesigner { } addConnection(sourceActivityId: string, targetActivityId: string, outcome: string) { - const workflowModel = { ...this.workflowModel }; - const connection: ConnectionModel = { sourceId: sourceActivityId, targetId: targetActivityId, outcome: outcome }; + const workflowModel = {...this.workflowModel}; + const connection: ConnectionModel = {sourceId: sourceActivityId, targetId: targetActivityId, outcome: outcome}; workflowModel.connections.push(connection); this.updateWorkflowModel(workflowModel); this.parentActivityId = null; @@ -181,11 +181,11 @@ export class ElsaWorkflowDesigner { } updateActivity(activity: ActivityModel) { - let workflowModel = { ...this.workflowModel }; + let workflowModel = {...this.workflowModel}; const activities = [...workflowModel.activities]; const index = activities.findIndex(x => x.activityId === activity.activityId); activities[index] = activity; - this.updateWorkflowModel({ ...workflowModel, activities: activities }); + this.updateWorkflowModel({...workflowModel, activities: activities}); } componentWillLoad() { @@ -196,8 +196,9 @@ export class ElsaWorkflowDesigner { this.svgD3Selected = d3.select(this.svg); this.innerD3Selected = d3.select(this.inner); this.applyZoom(); - this.setEnities(); - this.renderNodes(); + this.setEntities(); + + setTimeout(() => this.renderNodes(), 50); } componentWillRender() { @@ -214,7 +215,7 @@ export class ElsaWorkflowDesigner { const displayContext: ActivityDesignDisplayContext = { activityModel: model, - activityIcon: , + activityIcon: , bodyDisplay: bodyDisplay, outcomes: [...model.outcomes], }; @@ -222,10 +223,12 @@ export class ElsaWorkflowDesigner { eventBus.emit(EventTypes.ActivityDesignDisplaying, this, displayContext); displayContexts[model.activityId] = displayContext; } + this.activityDisplayContexts = displayContexts; } - componentDidRender() {} + componentDidRender() { + } showActivityPicker() { eventBus.emit(EventTypes.ShowActivityPicker); @@ -236,7 +239,7 @@ export class ElsaWorkflowDesigner { } removeActivity(activity: ActivityModel) { - let workflowModel = { ...this.workflowModel }; + let workflowModel = {...this.workflowModel}; const incomingConnections = getInboundConnections(workflowModel, activity.activityId); const outgoingConnections = getOutboundConnections(workflowModel, activity.activityId); @@ -255,7 +258,7 @@ export class ElsaWorkflowDesigner { applyZoom() { this.zoom = d3.zoom().on('zoom', event => { - const { transform } = event; + const {transform} = event; this.innerD3Selected.attr('transform', transform); this.zoomParams = { x: transform.x, @@ -266,7 +269,7 @@ export class ElsaWorkflowDesigner { this.svgD3Selected.call(this.zoom); } - setEnities() { + setEntities() { this.graph = new dagreD3.graphlib.Graph().setGraph({}); const rootActivities = this.getRootActivities(); @@ -284,15 +287,17 @@ export class ElsaWorkflowDesigner { this.graph.setEdge('start', `${activity.activityId}/start`, { arrowhead: 'undirected', }); - this.graph.setNode(`${activity.activityId}/start`, { shape: 'rect', activity, label: this.renderOutcomeButton(), labelType: 'html', class: 'add' }); - this.graph.setEdge(`${activity.activityId}/start`, activity.activityId, { arrowhead: 'undirected' }); + this.graph.setNode(`${activity.activityId}/start`, {shape: 'rect', activity, label: this.renderOutcomeButton(), labelType: 'html', class: 'add'}); + this.graph.setEdge(`${activity.activityId}/start`, activity.activityId, {arrowhead: 'undirected'}); }); this.workflowModel.activities.forEach(activity => { this.graph.setNode(activity.activityId, this.createActivityOptions(activity)); + const displayContext = this.activityDisplayContexts[activity.activityId] || undefined; + const outcomes = !!displayContext ? displayContext.outcomes : activity.outcomes || []; - activity.outcomes.forEach(outcome => { - this.graph.setNode(`${activity.activityId}/${outcome}`, { shape: 'rect', outcome, activity, label: this.renderOutcomeButton(), labelType: 'html', class: 'add' }); + outcomes.forEach(outcome => { + this.graph.setNode(`${activity.activityId}/${outcome}`, {shape: 'rect', outcome, activity, label: this.renderOutcomeButton(), labelType: 'html', class: 'add'}); this.graph.setEdge(activity.activityId, `${activity.activityId}/${outcome}`, { label: `

${outcome}

`, labelpos: 'c', @@ -302,8 +307,8 @@ export class ElsaWorkflowDesigner { }); }); - this.workflowModel.connections.forEach(({ sourceId, targetId, outcome }) => { - this.graph.setEdge(`${sourceId}/${outcome}`, targetId, { arrowhead: 'undirected' }); + this.workflowModel.connections.forEach(({sourceId, targetId, outcome}) => { + this.graph.setEdge(`${sourceId}/${outcome}`, targetId, {arrowhead: 'undirected'}); }); } @@ -357,17 +362,17 @@ export class ElsaWorkflowDesigner { } }); d3.select(node.elem) - .select('button') - .on('click', evt => { - evt.stopPropagation(); - this.handleContextMenuChange(evt.clientX, evt.clientY, true, node.activity); - }); + .select('button') + .on('click', evt => { + evt.stopPropagation(); + this.handleContextMenuChange(evt.clientX, evt.clientY, true, node.activity); + }); }); } rerenderTree() { this.applyZoom(); - this.setEnities(); + this.setEntities(); this.renderNodes(); } @@ -384,7 +389,7 @@ export class ElsaWorkflowDesigner { } createOutcomeActivityOptions() { - return { shape: 'circle', label: this.renderOutcomeButton(), labelType: 'html', class: 'add', width: 32, height: 32 }; + return {shape: 'circle', label: this.renderOutcomeButton(), labelType: 'html', class: 'add', width: 32, height: 32}; } renderOutcomeButton() { @@ -397,30 +402,30 @@ export class ElsaWorkflowDesigner { const displayContext = this.activityDisplayContexts[activity.activityId] || undefined; return `
-
-
-
- ${displayContext?.activityIcon || ''} -
-
-

${activity.displayName}

-
-
- -
-
-
-${this.renderActivityBody(activity.description)} -
`; +
+
+
+ ${displayContext?.activityIcon || ''} +
+
+

${activity.displayName}

+
+
+ +
+
+
+ ${this.renderActivityBody(activity.description)} + `; } renderActivityBody(description: string | null) { @@ -441,8 +446,8 @@ ${this.renderActivityBody(activity.description)} render() { return ( (this.el = el)}> - (this.svg = el)} id="svg" style={{ height: '100vh', width: '100vw', pointerEvents: this.contextMenu.shown ? 'none' : '' }}> - (this.inner = el)} /> + (this.svg = el)} id="svg" style={{height: '100vh', width: '100vw', pointerEvents: this.contextMenu.shown ? 'none' : ''}}> + (this.inner = el)}/>
registerClickOutside(this, el, () => { this.handleContextMenuChange(0, 0, false, null); @@ -470,7 +475,7 @@ ${this.renderActivityBody(activity.description)} Edit
- -
} /> ); }