Fix switch activity designer support
This commit is contained in:
parent
0a3070d861
commit
50f53bb52b
|
|
@ -4,18 +4,18 @@ import {Container} from "typedi";
|
|||
import {PanelPosition, PanelStateChangedArgs} from '../panel/models';
|
||||
import {
|
||||
Activity,
|
||||
ActivityDeletedArgs,
|
||||
ActivityDescriptor,
|
||||
ActivitySelectedArgs,
|
||||
ChildActivitySelectedArgs,
|
||||
Container as ContainerActivity,
|
||||
ContainerSelectedArgs,
|
||||
EditChildActivityArgs,
|
||||
GraphUpdatedArgs,
|
||||
WorkflowDefinition,
|
||||
Container as ContainerActivity,
|
||||
ActivityDeletedArgs
|
||||
WorkflowDefinition
|
||||
} from '../../../models';
|
||||
import {ActivityIdUpdatedArgs, ActivityUpdatedArgs, DeleteActivityRequestedArgs} from './activity-properties-editor';
|
||||
import {ActivityDriverRegistry, ActivityNameFormatter, ActivityNode, createActivityMap, createActivityNodeMap, EventBus, flatten, flattenList, PluginRegistry, walkActivities} from '../../../services';
|
||||
import {ActivityDriverRegistry, ActivityNameFormatter, ActivityNode, createActivityMap, createActivityNodeMap, EventBus, flatten, flattenList, PluginRegistry, PortProviderRegistry, walkActivities} from '../../../services';
|
||||
import {MonacoEditorSettings} from "../../../services/monaco-editor-settings";
|
||||
import {Flowchart} from "../../activities/flowchart/models";
|
||||
import {ActivityPropertyChangedEventArgs, WorkflowDefinitionPropsUpdatedArgs, WorkflowDefinitionUpdatedArgs, WorkflowEditorEventTypes} from "./models";
|
||||
|
|
@ -34,6 +34,7 @@ export class WorkflowDefinitionEditor {
|
|||
private readonly pluginRegistry: PluginRegistry;
|
||||
private readonly eventBus: EventBus;
|
||||
private readonly activityNameFormatter: ActivityNameFormatter;
|
||||
private readonly portProviderRegistry: PortProviderRegistry;
|
||||
private canvas: HTMLElsaCanvasElement;
|
||||
private container: HTMLDivElement;
|
||||
private toolbox: HTMLElsaWorkflowDefinitionEditorToolboxElement;
|
||||
|
|
@ -42,13 +43,16 @@ export class WorkflowDefinitionEditor {
|
|||
private applyActivityChanges: (activity: Activity) => void;
|
||||
private deleteActivity: (activity: Activity) => void;
|
||||
private readonly emitActivityChangedDebounced: (e: ActivityPropertyChangedEventArgs) => void;
|
||||
private readonly updateModelDebounced: () => void;
|
||||
private readonly saveChangesDebounced: () => void;
|
||||
|
||||
constructor() {
|
||||
this.eventBus = Container.get(EventBus);
|
||||
this.pluginRegistry = Container.get(PluginRegistry);
|
||||
this.activityNameFormatter = Container.get(ActivityNameFormatter);
|
||||
this.portProviderRegistry = Container.get(PortProviderRegistry);
|
||||
this.emitActivityChangedDebounced = debounce(this.emitActivityChanged, 100);
|
||||
this.updateModelDebounced = debounce(this.updateModel, 10);
|
||||
this.saveChangesDebounced = debounce(this.saveChanges, 1000);
|
||||
}
|
||||
|
||||
|
|
@ -110,6 +114,7 @@ export class WorkflowDefinitionEditor {
|
|||
|
||||
@Listen('graphUpdated')
|
||||
private async handleGraphUpdated(e: CustomEvent<GraphUpdatedArgs>) {
|
||||
this.updateModelDebounced();
|
||||
this.saveChangesDebounced();
|
||||
}
|
||||
|
||||
|
|
@ -119,16 +124,18 @@ export class WorkflowDefinitionEditor {
|
|||
const currentActivityId = this.currentWorkflowPath[this.currentWorkflowPath.length - 1].activityId;
|
||||
const currentActivity = this.nodeMap[currentActivityId];
|
||||
const parentActivity = this.nodeMap[parentActivityId];
|
||||
const indexInParent = currentActivity.activities.findIndex(x => x == parentActivity);
|
||||
const parentActivityDescriptor = descriptorsStore.activityDescriptors.find(x => x.activityType == parentActivity.typeName);
|
||||
const indexInParent = currentActivity.activities?.findIndex(x => x == parentActivity);
|
||||
const portName = e.detail.port.name;
|
||||
|
||||
const item: WorkflowNavigationItem = {
|
||||
activityId: parentActivityId,
|
||||
portName: e.detail.port.name,
|
||||
portName: portName,
|
||||
index: indexInParent
|
||||
};
|
||||
|
||||
const portName = camelCase(e.detail.port.name);
|
||||
const activityProperty = parentActivity[portName] as Activity | Array<Activity>;
|
||||
const portProvider = this.portProviderRegistry.get(parentActivity.typeName);
|
||||
const activityProperty = portProvider.resolvePort(portName, {activity: parentActivity, activityDescriptor: parentActivityDescriptor });
|
||||
const isContainer = Array.isArray(activityProperty);
|
||||
|
||||
if (!activityProperty) {
|
||||
|
|
@ -299,17 +306,17 @@ export class WorkflowDefinitionEditor {
|
|||
}
|
||||
|
||||
if (!!currentPortName) {
|
||||
const portName = camelCase(currentPortName);
|
||||
|
||||
if (currentActivityDescriptor.isContainer) {
|
||||
const parentNavigationItem = this.currentWorkflowPath[this.currentWorkflowPath.length - 2];
|
||||
const parentActivityId = parentNavigationItem.activityId;
|
||||
const parentActivity = this.nodeMap[parentActivityId] as ContainerActivity;
|
||||
const parentActivitiesProp = parentActivity[portName] as Array<Activity>;
|
||||
const parentActivityDescriptor = descriptorsStore.activityDescriptors.find(x => x.activityType == parentActivity.typeName);
|
||||
const portProvider = this.portProviderRegistry.get(parentActivity.typeName);
|
||||
const parentActivitiesProp = portProvider.resolvePort(currentPortName, {activity: parentActivity, activityDescriptor: parentActivityDescriptor}) as Array<Activity>;
|
||||
parentActivitiesProp[currentWorkflowNavigationItem.index] = activity;
|
||||
} else {
|
||||
debugger;
|
||||
currentActivity[portName] = activity;
|
||||
const portProvider = this.portProviderRegistry.get(currentActivity.typeName);
|
||||
portProvider.assignPort(currentPortName, activity, {activity: currentActivity, activityDescriptor: currentActivityDescriptor});
|
||||
}
|
||||
} else {
|
||||
workflowDefinition.root = activity;
|
||||
|
|
@ -323,9 +330,12 @@ export class WorkflowDefinitionEditor {
|
|||
await this.eventBus.emit(WorkflowEditorEventTypes.Activity.PropertyChanged, this, activity, propertyName, this);
|
||||
};
|
||||
|
||||
private saveChanges = async (): Promise<void> => {
|
||||
private updateModel = async (): Promise<void> => {
|
||||
const workflowDefinition = await this.getWorkflowDefinitionInternal();
|
||||
await this.updateWorkflowDefinition(workflowDefinition);
|
||||
};
|
||||
|
||||
private saveChanges = async (): Promise<void> => {
|
||||
this.workflowUpdated.emit({workflowDefinition: this.workflowDefinitionState});
|
||||
};
|
||||
|
||||
|
|
@ -365,7 +375,14 @@ export class WorkflowDefinitionEditor {
|
|||
if (!currentItem)
|
||||
return this.workflowDefinitionState.root;
|
||||
|
||||
return this.nodeMap[currentItem.activityId];
|
||||
const activity = this.nodeMap[currentItem.activityId];
|
||||
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.activityType == activity.typeName);
|
||||
|
||||
if(activityDescriptor.isContainer)
|
||||
return activity;
|
||||
|
||||
const portProvider = this.portProviderRegistry.get(activity.typeName);
|
||||
return portProvider.resolvePort(currentItem.portName, {activity, activityDescriptor}) as Activity;
|
||||
};
|
||||
|
||||
private createNodeMap = (workflowDefinition: WorkflowDefinition): void => {
|
||||
|
|
@ -395,8 +412,6 @@ export class WorkflowDefinitionEditor {
|
|||
});
|
||||
|
||||
this.nodeMap[newName] = activity;
|
||||
|
||||
requestAnimationFrame(() => {});
|
||||
};
|
||||
|
||||
private onZoomToFit = async () => await this.canvas.zoomToFit()
|
||||
|
|
@ -405,7 +420,7 @@ export class WorkflowDefinitionEditor {
|
|||
const updatedActivity = e.detail.activity;
|
||||
this.nodeMap[updatedActivity.id] = updatedActivity;
|
||||
|
||||
if(!!this.applyActivityChanges)
|
||||
if (!!this.applyActivityChanges)
|
||||
this.applyActivityChanges(updatedActivity);
|
||||
|
||||
this.emitActivityChangedDebounced({...e.detail, workflowEditor: this.el});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import {Component, FunctionalComponent, h, Prop, Event, EventEmitter} from "@stencil/core";
|
||||
import {Container} from "typedi";
|
||||
import {ActivityIconRegistry, ActivityNode, flatten, walkActivities} from "../../../services";
|
||||
import {ActivityIconRegistry, ActivityNode, flatten, PortProviderRegistry, walkActivities} from "../../../services";
|
||||
import {WorkflowNavigationItem} from "./models";
|
||||
import {Port, WorkflowDefinition} from "../../../models";
|
||||
import descriptorsStore from "../../../data/descriptors-store";
|
||||
|
|
@ -10,6 +10,13 @@ import descriptorsStore from "../../../data/descriptors-store";
|
|||
shadow: false
|
||||
})
|
||||
export class WorkflowNavigator {
|
||||
private readonly iconRegistry: ActivityIconRegistry;
|
||||
private readonly portProviderRegistry: PortProviderRegistry;
|
||||
|
||||
constructor() {
|
||||
this.iconRegistry = Container.get(ActivityIconRegistry);
|
||||
this.portProviderRegistry = Container.get(PortProviderRegistry);
|
||||
}
|
||||
|
||||
@Prop() items: Array<WorkflowNavigationItem> = [];
|
||||
@Prop() workflowDefinition: WorkflowDefinition;
|
||||
|
|
@ -37,11 +44,10 @@ export class WorkflowNavigator {
|
|||
}
|
||||
|
||||
private renderPathItem = (item: WorkflowNavigationItem, index: number, nodes: Array<ActivityNode>) => {
|
||||
const iconRegistry = Container.get(ActivityIconRegistry);
|
||||
const activityId = item.activityId;
|
||||
const activity = nodes.find(x => x.activity.id == activityId).activity;
|
||||
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.activityType == activity.typeName);
|
||||
const icon = iconRegistry.get(activity.typeName)();
|
||||
const icon = this.iconRegistry.get(activity.typeName)();
|
||||
const listElements = [];
|
||||
const isLastItem = index == this.items.length - 1;
|
||||
|
||||
|
|
@ -53,7 +59,8 @@ export class WorkflowNavigator {
|
|||
let port: Port = null;
|
||||
|
||||
if (!!item.portName) {
|
||||
const ports = activityDescriptor.ports;
|
||||
const portProvider = this.portProviderRegistry.get(activity.typeName);
|
||||
const ports = portProvider.getOutboundPorts({activity, activityDescriptor});
|
||||
|
||||
if (ports.length > 1)
|
||||
port = ports.find(x => x.name == item.portName);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'reflect-metadata';
|
||||
import {Service} from "typedi";
|
||||
import {camelCase} from 'lodash';
|
||||
import {Activity, Port, PortMode} from "../../models";
|
||||
import {SwitchActivity, SwitchCase} from "./models";
|
||||
import {PortProvider, PortProviderContext} from "../../services";
|
||||
|
|
@ -31,4 +32,15 @@ export class SwitchPortProvider implements PortProvider {
|
|||
|
||||
return caseItem.activity;
|
||||
}
|
||||
|
||||
assignPort(portName: string, activity: Activity, context: PortProviderContext) {
|
||||
const switchActivity = context.activity as SwitchActivity;
|
||||
const cases: Array<SwitchCase> = switchActivity.cases ?? [];
|
||||
const caseItem = cases.find(x => x.label == portName);
|
||||
|
||||
if(!caseItem)
|
||||
return null;
|
||||
|
||||
caseItem.activity = activity;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import {Activity, Port} from "../models";
|
|||
@Service()
|
||||
export class DefaultPortProvider implements PortProvider {
|
||||
getInboundPorts(context: PortProviderContext): Array<Port> {
|
||||
const {activityDescriptor} = context;
|
||||
return [];
|
||||
}
|
||||
|
||||
|
|
@ -20,10 +19,20 @@ export class DefaultPortProvider implements PortProvider {
|
|||
const propName = camelCase(portName);
|
||||
const activity = context.activity;
|
||||
|
||||
if(!activity)
|
||||
if (!activity)
|
||||
return null;
|
||||
|
||||
return activity[propName] as Activity | Array<Activity>;
|
||||
}
|
||||
|
||||
assignPort(portName: string, activity: Activity, context: PortProviderContext) {
|
||||
const propName = camelCase(portName);
|
||||
const container = context.activity;
|
||||
|
||||
if (!container)
|
||||
return null;
|
||||
|
||||
container[propName] = activity;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ export interface PortProvider {
|
|||
getOutboundPorts(context: PortProviderContext): Array<Port>;
|
||||
|
||||
resolvePort(portName: string, context: PortProviderContext): Activity | Array<Activity>;
|
||||
|
||||
assignPort(portName: string, activity: Activity, context: PortProviderContext);
|
||||
}
|
||||
|
||||
export interface PortProviderContext {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using System.Text.Json;
|
|||
using System.Text.Json.Serialization;
|
||||
using Dahomey.Json;
|
||||
using Dahomey.Json.Serialization.Conventions;
|
||||
using Dahomey.Json.Util;
|
||||
using Elsa.Expressions.Exceptions;
|
||||
using DahomeyJsonNode = System.Text.Json.JsonNode;
|
||||
|
||||
|
|
@ -55,7 +56,7 @@ public static class ObjectConverter
|
|||
var targetTypeConverter = TypeDescriptor.GetConverter(underlyingTargetType);
|
||||
|
||||
if (targetTypeConverter.CanConvertFrom(underlyingSourceType))
|
||||
return targetTypeConverter.ConvertFrom(value);
|
||||
return targetTypeConverter.IsValid(value) ? targetTypeConverter.ConvertFrom(value) : targetType.GetDefaultValue();
|
||||
|
||||
var sourceTypeConverter = TypeDescriptor.GetConverter(underlyingSourceType);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue