Incremental work on dynamic ports

This commit is contained in:
Sipke Schoorstra 2022-01-28 21:25:01 +01:00
parent 2a1ff4c392
commit 50fd5f85ed
8 changed files with 126 additions and 79 deletions

View file

@ -1,26 +1,24 @@
import 'reflect-metadata';
import {Node} from "@antv/x6";
import {Service} from "typedi"
import {Container, Service} from "typedi"
import {ActivityNodeHandler, CreateUINodeContext} from "./activity-node-handler";
import {Port} from "../../../models";
import {PortProviderRegistry} from "./port-provider-registry";
import {PortProviderContext} from "./port-provider";
@Service()
export class DefaultNodeHandler implements ActivityNodeHandler {
private readonly portProviderRegistry: PortProviderRegistry;
constructor() {
this.portProviderRegistry = Container.get(PortProviderRegistry);
}
createDesignerNode(context: CreateUINodeContext): Node.Metadata {
const {activityDescriptor, activity, x, y} = context;
let inPorts: Array<Port> = [...activityDescriptor.inPorts];
let outPorts: Array<Port> = [...activityDescriptor.outPorts];
if (inPorts.length == 0)
inPorts = [{name: 'In', displayName: 'In'}];
if (inPorts.length == 1)
inPorts[0].displayName = null;
outPorts = [...outPorts, {name: 'Done', displayName: 'Done'}];
if (outPorts.length == 1)
outPorts[0].displayName = null;
const provider = this.portProviderRegistry.get(activityDescriptor.nodeType);
const providerContext: PortProviderContext = { activityDescriptor, activity };
let inPorts = provider.getInboundPorts(providerContext);
let outPorts = provider.getOutboundPorts(providerContext);
const inPortModels = inPorts.map(x => ({
id: x.name,

View file

@ -0,0 +1,33 @@
import 'reflect-metadata';
import {Service} from "typedi"
import {Port} from "../../../models";
import {PortProvider, PortProviderContext} from "./port-provider";
@Service()
export class DefaultPortProvider implements PortProvider {
getInboundPorts(context: PortProviderContext): Array<Port> {
const {activityDescriptor} = context;
let inPorts: Array<Port> = [...activityDescriptor.inPorts];
if (inPorts.length == 0)
inPorts = [{name: 'In', displayName: 'In'}];
if (inPorts.length == 1)
inPorts[0].displayName = null;
return inPorts;
}
getOutboundPorts(context: PortProviderContext): Array<Port> {
const {activityDescriptor} = context;
let outPorts: Array<Port> = [...activityDescriptor.outPorts];
outPorts = [...outPorts, {name: 'Done', displayName: 'Done'}];
if (outPorts.length == 1)
outPorts[0].displayName = null;
return outPorts;
}
}

View file

@ -0,0 +1,21 @@
import 'reflect-metadata';
import {Container, Service} from "typedi";
import {PortProvider} from "./port-provider";
import {DefaultPortProvider} from "./default-port-provider";
export type PortProviderFactory = () => PortProvider;
@Service()
export class PortProviderRegistry {
private map: Map<string, PortProviderFactory> = new Map<string, PortProviderFactory>();
private defaultProviderFactory: PortProviderFactory = () => Container.get(DefaultPortProvider);
public register(activityType: string, defaultProviderFactory: PortProviderFactory) {
this.map.set(activityType, defaultProviderFactory);
}
public get(activityType: string): PortProvider {
const factory = this.map.get(activityType) ?? this.defaultProviderFactory;
return factory();
}
}

View file

@ -0,0 +1,11 @@
import {Activity, ActivityDescriptor, Port} from "../../../models";
export interface PortProvider {
getInboundPorts(context: PortProviderContext): Array<Port>;
getOutboundPorts(context: PortProviderContext): Array<Port>;
}
export interface PortProviderContext {
activityDescriptor: ActivityDescriptor;
activity: Activity;
}

View file

@ -0,0 +1,28 @@
import 'reflect-metadata';
import {h} from "@stencil/core";
import {Container, Service} from "typedi";
import {ActivityTraits} from '../../models';
import {ActivityDisplayContext, ActivityDriver, ActivityIcon, ActivityIconRegistry} from '../../services';
@Service()
export class SwitchActivityDriver implements ActivityDriver {
display(context: ActivityDisplayContext): any {
const activityDescriptor = context.activityDescriptor;
const text = activityDescriptor?.displayName;
return (`
<div>
<div class="activity-wrapper border border-sky-600 bg-sky-400 rounded text-white overflow-hidden">
<div class="activity-content-wrapper flex flex-row">
<div class="flex items-center">
<div class="px-4 py-4">
${text}
</div>
</div>
</div>
</div>
</div>
`);
}
}

View file

@ -1,58 +0,0 @@
import 'reflect-metadata';
import {Node} from '@antv/x6';
import {Service} from 'typedi';
import {ActivityNodeHandler} from "../../components/activities/flowchart/activity-node-handler";
import {Port} from "../../models";
@Service()
export class SwitchNodeHandler implements ActivityNodeHandler {
createDesignerNode(context): Node.Metadata {
const {activityDescriptor, activity, x, y} = context;
let inPorts: Array<Port> = [...activityDescriptor.inPorts];
let outPorts: Array<Port> = [...activityDescriptor.outPorts];
if (inPorts.length == 0)
inPorts = [{name: 'In', displayName: 'In'}];
if (inPorts.length == 1)
inPorts[0].displayName = null;
outPorts = [...outPorts, {name: 'Done', displayName: 'Done'}];
if (outPorts.length == 1)
outPorts[0].displayName = null;
const inPortModels = inPorts.map(x => ({
id: x.name,
group: 'in',
attrs: !!x.displayName ? {
text: {
text: x.displayName
}
} : null
}));
const outPortModels = outPorts.map(x => ({
id: x.name,
group: 'out',
attrs: {
text: {
text: x.displayName
}
}
}));
const portModels = [...inPortModels, ...outPortModels];
return {
id: activity.id,
shape: 'activity',
activity: activity,
activityDescriptor: activityDescriptor,
x: x,
y: y,
data: activity,
ports: portModels
} as Node.Metadata;
}
}

View file

@ -1,20 +1,21 @@
import 'reflect-metadata';
import {h} from '@stencil/core';
import {Container, Service} from "typedi";
import {InputControlRegistry} from "../../services";
import {ActivityDriverRegistry, InputControlRegistry} from "../../services";
import {Plugin} from "../../models";
import {NodeHandlerRegistry} from "../../components/activities/flowchart/node-handler-registry";
import {SwitchNodeHandler} from "./switch-node-handler";
import {SwitchActivityDriver} from "./switch-activity-driver";
@Service()
export class SwitchPlugin implements Plugin {
private static readonly ActivityTypeName: string = 'ControlFlow.Switch';
constructor() {
const activityTypeName = SwitchPlugin.ActivityTypeName;
const driverRegistry = Container.get(ActivityDriverRegistry);
const inputControlRegistry = Container.get(InputControlRegistry);
const nodeHandlerRegistry = Container.get(NodeHandlerRegistry);
inputControlRegistry.add('switch-editor', c => <elsa-switch-editor inputContext={c} />)
nodeHandlerRegistry.add('ControlFlow.Switch', () => Container.get(SwitchNodeHandler));
driverRegistry.add(activityTypeName, () => Container.get(SwitchActivityDriver));
inputControlRegistry.add('switch-editor', c => <elsa-switch-editor inputContext={c}/>);
}
}

View file

@ -0,0 +1,13 @@
import {PortProvider, PortProviderContext} from "../../components/activities/flowchart/port-provider";
import {Port} from "../../models";
export class SwitchPortProvider implements PortProvider {
getInboundPorts(context: PortProviderContext): Array<Port> {
return undefined;
}
getOutboundPorts(context: PortProviderContext): Array<Port> {
return undefined;
}
}