Skip to content

Commit

Permalink
Implement types API endpoint (#3479)
Browse files Browse the repository at this point in the history
  • Loading branch information
sfmskywalker authored Nov 26, 2022
1 parent 2ed1e14 commit b5a2e95
Show file tree
Hide file tree
Showing 51 changed files with 363 additions and 162 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {SyntaxSelectorIcon} from "../../icons/tooling/syntax-selector";
import {MonacoValueChangedArgs} from "../../shared/monaco-editor/monaco-editor";
import {Hint} from "../../shared/forms/hint";
import {mapSyntaxToLanguage} from "../../../utils";
import descriptorsStore from "../../../data/descriptors-store";

export interface ExpressionChangedArs {
expression: string;
Expand Down Expand Up @@ -137,10 +138,15 @@ export class InputControlSwitch {
const showMonaco = !!selectedSyntax && selectedSyntax != 'Literal' && !!this.supportedSyntaxes.find(x => x === selectedSyntax);
const expressionEditorClass = showMonaco ? 'block' : 'hidden';
const defaultEditorClass = showMonaco ? 'hidden' : 'block';
const propertyType = "Object";
const typeDescriptor = descriptorsStore.variableDescriptors.find(x => x.typeName == propertyType);
const propertyTypeName = typeDescriptor?.displayName ?? propertyType;

return (
<div>
<div class="relative">

<div class={expressionEditorClass}>

<elsa-monaco-editor
value={value}
language={monacoLanguage}
Expand All @@ -153,6 +159,9 @@ export class InputControlSwitch {
<slot/>
</div>
<Hint text={this.hint}/>
<div class="pointer-events-none absolute inset-y-0 right-0 top-0 flex items-center pr-10">
<span class="text-gray-500 sm:text-sm">{propertyTypeName}</span>
</div>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {Component, h, Prop, Event, EventEmitter, Method} from "@stencil/core";
import {_, groupBy} from 'lodash';
import {StorageDriverDescriptor, Variable} from "../../../models";
import {FormEntry} from "../../shared/forms/form-entry";
import {isNullOrWhitespace} from "../../../utils";
import descriptorsStore from '../../../data/descriptors-store';
import {VariableDescriptor} from "../../../services/api-client/variable-descriptors-api";

@Component({
tag: 'elsa-variable-editor-dialog-content',
Expand All @@ -22,7 +24,8 @@ export class VariableEditorDialogContent {
render() {
const variable: Variable = this.variable ?? {name: '', typeName: 'Object'};
const variableTypeName = variable.typeName;
const availableTypeNames: Array<string> = ['Object', 'String', 'Boolean', 'Int32', 'Int64', 'Single', 'Double']; // TODO: Fetch these from backend.
const availableTypes: Array<VariableDescriptor> = descriptorsStore.variableDescriptors;
const groupedVariableTypes = _.groupBy(availableTypes, x => x.category);
const storageDrivers: Array<StorageDriverDescriptor> = [{id: null, displayName: '-'}, ...descriptorsStore.storageDrivers];

return (
Expand All @@ -38,7 +41,12 @@ export class VariableEditorDialogContent {

<FormEntry fieldId="variableTypeName" label="Type" hint="The type of the variable.">
<select id="variableTypeName" name="variableTypeName">
{availableTypeNames.map(typeName => <option value={typeName} selected={typeName == variableTypeName}>{typeName}</option>)}
{Object.keys(groupedVariableTypes).map(category => {
const variableTypes = groupedVariableTypes[category] as Array<VariableDescriptor>;
return (<optgroup label={category}>
{variableTypes.map(descriptor => <option value={descriptor.typeName} selected={descriptor.typeName == variableTypeName}>{descriptor.displayName}</option>)}
</optgroup>);
})}
</select>
</FormEntry>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,13 @@ export class VariablesEditor {
{variables.map(variable => {
const storage = storageDrivers.find(x => x.id == variable.storageDriverId);
const storageName = storage?.displayName ?? '-';
const descriptor = descriptorsStore.variableDescriptors.find(x => x.typeName == variable.typeName);
const typeDisplayName = descriptor?.displayName ?? variable.typeName;

return (
<tr>
<td class="whitespace-nowrap">{variable.name}</td>
<td class="whitespace-nowrap">{variable.typeName}</td>
<td class="whitespace-nowrap">{typeDisplayName}</td>
<td>{variable.value}</td>
<td>{storageName}</td>
<td class="pr-6">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {ActivityInputContext} from "../../services/node-input-driver";
import {getInputPropertyValue} from "../../utils";
import {MonacoValueChangedArgs} from "../shared/monaco-editor/monaco-editor";
import {ExpressionChangedArs} from "../designer/input-control-switch/input-control-switch";
import descriptorsStore from "../../data/descriptors-store";

interface CodeEditorOptions {
editorHeight?: EditorHeight;
Expand Down Expand Up @@ -33,7 +34,7 @@ export class CodeEditorInput {

return (
<elsa-input-control-switch label={displayName} hint={hint} syntax={syntax} expression={value} onExpressionChanged={this.onExpressionChanged}>
<elsa-monaco-editor value={value} {...options} onValueChanged={this.onChange}/>
<elsa-monaco-editor value={value} {...options} onValueChanged={this.onChange}/>
</elsa-input-control-switch>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {LiteralExpression, SyntaxNames} from "../../models";
import {ActivityInputContext} from "../../services/node-input-driver";
import {getInputPropertyValue} from "../../utils";
import {ExpressionChangedArs} from "../designer/input-control-switch/input-control-switch";
import descriptorsStore from "../../data/descriptors-store";

@Component({
tag: 'elsa-single-line-input',
Expand All @@ -21,10 +22,13 @@ export class SingleLineInput {
const input = getInputPropertyValue(inputContext);
const value = (input?.expression as LiteralExpression)?.value; // TODO: The "value" field is currently hardcoded, but we should be able to be more flexible and potentially have different fields for a given syntax.
const syntax = input?.expression?.type ?? inputDescriptor.defaultSyntax;
const propertyType = inputDescriptor.typeName;
const typeDescriptor = descriptorsStore.variableDescriptors.find(x => x.typeName == propertyType);
const propertyTypeName = typeDescriptor?.displayName ?? propertyType;

return (
<elsa-input-control-switch label={displayName} hint={hint} syntax={syntax} expression={value} onExpressionChanged={this.onExpressionChanged}>
<input type="text" name={fieldName} id={fieldId} value={value} onChange={this.onPropertyEditorChanged}/>
<input type="text" name={fieldName} id={fieldId} value={value} onChange={this.onPropertyEditorChanged}/>
</elsa-input-control-switch>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { createStore } from '@stencil/store';
import {ActivityDescriptor} from "../models";
import {VariableDescriptor} from "../services/api-client/variable-descriptors-api";

export interface DescriptorsStore {
activityDescriptors: Array<ActivityDescriptor>;
storageDrivers: Array<any>;
variableDescriptors: Array<VariableDescriptor>;
}

const { state, onChange } = createStore({
activityDescriptors: [],
storageDrivers: []
storageDrivers: [],
variableDescriptors: []
} as DescriptorsStore);

export default state;
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ export class DefaultActivityDriver implements ActivityDriver {

display(context: ActivityDisplayContext): any {
const activityDescriptor = context.activityDescriptor;
const type = activityDescriptor.type;
const typeName = activityDescriptor.typeName;
const version = activityDescriptor.version;
const activity = context.activity;
const activityId = activity?.id;
const displayType = context.displayType;

return (`<elsa-default-activity-template activity-type="${type}" activity-type-version="${version}" activity-id="${activityId}" display-type="${displayType}" />`);
return (`<elsa-default-activity-template activity-type="${typeName}" activity-type-version="${version}" activity-id="${activityId}" display-type="${displayType}" />`);
}
}
8 changes: 4 additions & 4 deletions src/designer/elsa-workflows-designer/src/models/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ export interface Variable {
}

export interface ActivityInput {
type: Type;
typeName: Type;
expression: Expression;
}

export interface ActivityOutput {
type: Type;
typeName: Type;
memoryReference: MemoryReference;
}

Expand All @@ -68,7 +68,7 @@ export interface WorkflowState {
}

export interface ActivityDescriptor {
type: string;
typeName: string;
version: number;
displayName: string;
category: string;
Expand All @@ -83,7 +83,7 @@ export interface ActivityDescriptor {

export interface PropertyDescriptor {
name: string;
type: Type;
typeName: Type;
displayName?: string;
description?: string;
order?: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class ActivityDefinitionsPlugin implements Plugin {
const newName = await this.generateUniqueActivityName(flowchartDescriptor);

const flowchart = {
type: flowchartDescriptor.type,
type: flowchartDescriptor.typeName,
version: 1,
activities: [],
connections: [],
Expand All @@ -92,7 +92,7 @@ export class ActivityDefinitionsPlugin implements Plugin {
};

private getFlowchartDescriptor = () => this.getActivityDescriptor(FlowchartTypeName);
private getActivityDescriptor = (typeName: string): ActivityDescriptor => descriptorsStore.activityDescriptors.find(x => x.type == typeName)
private getActivityDescriptor = (typeName: string): ActivityDescriptor => descriptorsStore.activityDescriptors.find(x => x.typeName == typeName)
private generateUniqueActivityName = async (activityDescriptor: ActivityDescriptor): Promise<string> => await generateUniqueActivityName([], activityDescriptor);

private saveActivityDefinition = async (definition: ActivityDefinition, publish: boolean): Promise<ActivityDefinition> => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class DefaultActivityTemplate {
const iconRegistry = this.iconRegistry;
const activityType = this.activityType;
const activityTypeVersion = this.activityTypeVersion ?? 0;
this.activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.type == activityType && x.version == activityTypeVersion);
this.activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.typeName == activityType && x.version == activityTypeVersion);
this.icon = iconRegistry.has(activityType) ? iconRegistry.get(activityType) : null;
}

Expand Down Expand Up @@ -109,7 +109,7 @@ export class DefaultActivityTemplate {
return;

const activityDescriptor = this.activityDescriptor;
const portProvider = this.portProviderRegistry.get(activityDescriptor.type);
const portProvider = this.portProviderRegistry.get(activityDescriptor.typeName);
const ports = portProvider.getOutboundPorts({ activityDescriptor, activity });
const embeddedPorts = ports.filter(x => x.mode == PortMode.Embedded);

Expand All @@ -128,9 +128,9 @@ export class DefaultActivityTemplate {
const textColor = canStartWorkflow ? 'text-white' : 'text-gray-700';
const borderColor = port.name == this.selectedPortName ? 'border-blue-600' : 'border-gray-300';
const activityDescriptor = this.activityDescriptor;
const portProvider = this.portProviderRegistry.get(activityDescriptor.type);
const portProvider = this.portProviderRegistry.get(activityDescriptor.typeName);
const activityProperty = portProvider.resolvePort(port.name, { activity, activityDescriptor }) as Activity;
const childActivityDescriptor: ActivityDescriptor = activityProperty != null ? descriptorsStore.activityDescriptors.find(x => x.type == activityProperty.type) : null;
const childActivityDescriptor: ActivityDescriptor = activityProperty != null ? descriptorsStore.activityDescriptors.find(x => x.typeName == activityProperty.type) : null;
let childActivityDisplayText = activityProperty?.metadata?.displayText;

if (isNullOrWhitespace(childActivityDisplayText))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class DefaultNodeHandler implements ActivityNodeHandler {

createDesignerNode(context: CreateUINodeContext): Node.Metadata {
const {activityDescriptor, activity, x, y} = context;
const provider = this.portProviderRegistry.get(activityDescriptor.type);
const provider = this.portProviderRegistry.get(activityDescriptor.typeName);
const providerContext: PortProviderContext = {activityDescriptor, activity};
const inPorts = [{name: 'In', displayName: null, mode: PortMode.Port}];
let outPorts = provider.getOutboundPorts(providerContext).filter(x => x.mode == PortMode.Port);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class FlowchartComponent implements ContainerActivityComponent {
const newName = await this.generateUniqueActivityName(flowchartDescriptor);

const flowchart = {
type: flowchartDescriptor.type,
type: flowchartDescriptor.typeName,
version: 1,
activities: [],
connections: [],
Expand Down Expand Up @@ -176,7 +176,7 @@ export class FlowchartComponent implements ContainerActivityComponent {

const activity: Activity = {
id: id,
type: descriptor.type,
type: descriptor.typeName,
version: descriptor.version,
applicationProperties: {},
metadata: {
Expand Down Expand Up @@ -275,7 +275,7 @@ export class FlowchartComponent implements ContainerActivityComponent {
const currentActivityId = this.currentPath[this.currentPath.length - 1].activityId;
const currentActivity = this.activityLookup[currentActivityId];
const parentActivity = this.activityLookup[parentActivityId] as Flowchart;
const parentActivityDescriptor = descriptorsStore.activityDescriptors.find(x => x.type == parentActivity.type);
const parentActivityDescriptor = descriptorsStore.activityDescriptors.find(x => x.typeName == parentActivity.type);
const indexInParent = currentActivity.activities?.findIndex(x => x == parentActivity);
const portName = e.detail.port.name;

Expand Down Expand Up @@ -311,7 +311,7 @@ export class FlowchartComponent implements ContainerActivityComponent {
const activityId = await this.generateUniqueActivityName(descriptor);

return {
type: descriptor.type,
type: descriptor.typeName,
version: descriptor.version,
id: activityId,
start: null,
Expand Down Expand Up @@ -417,7 +417,7 @@ export class FlowchartComponent implements ContainerActivityComponent {
await this.setupGraph(flowchart);
};

private getActivityDescriptor = (typeName: string): ActivityDescriptor => descriptorsStore.activityDescriptors.find(x => x.type == typeName)
private getActivityDescriptor = (typeName: string): ActivityDescriptor => descriptorsStore.activityDescriptors.find(x => x.typeName == typeName)

private setupGraph = async (flowchart: Flowchart) => {
const activities = flowchart.activities;
Expand Down Expand Up @@ -506,7 +506,7 @@ export class FlowchartComponent implements ContainerActivityComponent {
return this.activity;

const activity = this.activityLookup[currentItem.activityId] as Flowchart;
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.type == activity.type);
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.typeName == activity.type);

if (activityDescriptor.isContainer)
return activity;
Expand Down Expand Up @@ -709,7 +709,7 @@ export class FlowchartComponent implements ContainerActivityComponent {
const item = e.detail;
const activityId = item.activityId;
let activity = this.activityLookup[activityId];
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.type == activity.type);
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.typeName == activity.type);
const path = this.currentPath;
const index = path.indexOf(item);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ export function createGraph(
for (const cell of activityCells) {
const activity = {...cell.data} as Activity;
const activityTypeName = activity.type;
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.type == activityTypeName);
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.typeName == activityTypeName);
const currentId = activity.id;
const idExists = allActivities.find(x => x.id == currentId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class NodeFactory {
}

public createNode(activityDescriptor: ActivityDescriptor, activity: Activity, x: number, y: number): Node.Metadata {
const handler = this.handlerRegistry.createHandler(activityDescriptor.type);
const handler = this.handlerRegistry.createHandler(activityDescriptor.typeName);
return handler.createDesignerNode({activityDescriptor, activity, x, y});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class ActivityNodeShape extends Shape.HTML {
createHtml() {
const activityDescriptor = this.activityDescriptor as ActivityDescriptor;
const activity = this.activity as Activity;
const activityType = activityDescriptor.type;
const activityType = activityDescriptor.typeName;
const driverRegistry = Container.get(ActivityDriverRegistry);
const driver = driverRegistry.createDriver(activityType);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class WorkflowNavigator {
private renderPathItem = (item: FlowchartNavigationItem, index: number, nodes: Array<ActivityNode>) => {
const activityId = item.activityId;
const activity = nodes.find(x => x.activity.id == activityId).activity;
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.type == activity.type);
const activityDescriptor = descriptorsStore.activityDescriptors.find(x => x.typeName == activity.type);
const icon = this.iconRegistry.getOrDefault(activity.type)();
const listElements = [];
const isLastItem = index == this.items.length - 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ export class LoginPlugin implements Plugin {

const activityDescriptors = await this.elsaClient.descriptors.activities.list();
const storageDrivers = await this.elsaClient.descriptors.storageDrivers.list();
const variableDescriptors = await this.elsaClient.descriptors.variables.list();

descriptorsStore.activityDescriptors = activityDescriptors;
descriptorsStore.storageDrivers = storageDrivers;
descriptorsStore.variableDescriptors = variableDescriptors;
}
}

Expand Down
Loading

0 comments on commit b5a2e95

Please sign in to comment.