From 1c47d4b80dd2b5dcbe0cb72e1e41bd91d3cf000a Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Tue, 15 Mar 2022 13:01:10 +0100 Subject: [PATCH] Remove & merge Node base type --- .../Elsa.Core/Activities/ControlFlow/Join.cs | 2 +- .../OutboundActivityNodeResolver.cs | 4 +-- .../Models/WorkflowExecutionContext.cs | 4 +-- .../Models/WorkflowExecutionLogEntry.cs | 2 +- .../Services/IdentityGraphService.cs | 10 +++--- .../Services/WorkflowStateSerializer.cs | 14 ++++---- .../Models/ActivityDescriptor.cs | 9 ++++- .../Elsa.Management/Models/NodeDescriptor.cs | 11 ------ .../Models/TriggerDescriptor.cs | 12 ------- .../Converters/ActivityJsonConverter.cs | 2 +- .../Converters/FlowchartJsonConverter.cs | 10 +++--- .../Services/ActivityDescriber.cs | 5 +-- .../Services/ActivityRegistry.cs | 4 +-- .../src/components.d.ts | 34 +++++++++---------- .../activities/flowchart/activity-walker.ts | 4 +-- .../flowchart/default-node-handler.ts | 2 +- .../activities/flowchart/flowchart.tsx | 12 +++---- .../activities/flowchart/node-factory.ts | 2 +- .../components/activities/flowchart/shapes.ts | 2 +- .../activity-properties-editor.tsx | 30 ++++++++-------- .../designer/toolbox/toolbox-activities.tsx | 8 ++--- .../src/components/inputs/check-list.tsx | 4 +-- .../src/components/inputs/code-editor.tsx | 4 +-- .../src/components/inputs/dropdown.tsx | 4 +-- .../src/components/inputs/multi-line.tsx | 4 +-- .../src/components/inputs/multi-text.tsx | 4 +-- .../src/components/inputs/radio-list.tsx | 4 +-- .../src/components/inputs/single-line.tsx | 4 +-- .../activity/default-activity-driver.tsx | 4 +-- .../drivers/input/default-input-driver.tsx | 6 ++-- .../elsa-workflows-designer/src/models/api.ts | 13 +++---- .../src/models/core.ts | 7 ++-- .../elsa-workflows-designer/src/models/ui.ts | 18 +++++----- .../src/plugins/switch/switch-editor.tsx | 4 +-- .../src/services/input-driver-registry.ts | 4 +-- .../src/services/node-input-driver.ts | 12 +++---- .../src/utils/utils.ts | 6 ++-- .../Services/WorkflowBookmarkScheduler.cs | 5 ++- .../Services/WorkflowTriggerScheduler.cs | 2 +- .../Elsa.Modules.Scheduling/Triggers/Timer.cs | 18 ++++++++++ .../PersistWorkflowExecutionLogMiddleware.cs | 4 +-- .../aspnet/Elsa.Samples.Web1/Program.cs | 3 +- .../Workflows/HeartbeatWorkflow.cs | 26 ++++++++++++++ 43 files changed, 183 insertions(+), 160 deletions(-) delete mode 100644 src/core/Elsa.Management/Models/NodeDescriptor.cs delete mode 100644 src/core/Elsa.Management/Models/TriggerDescriptor.cs create mode 100644 src/samples/aspnet/Elsa.Samples.Web1/Workflows/HeartbeatWorkflow.cs diff --git a/src/core/Elsa.Core/Activities/ControlFlow/Join.cs b/src/core/Elsa.Core/Activities/ControlFlow/Join.cs index cccbfcb82..6df8bb274 100644 --- a/src/core/Elsa.Core/Activities/ControlFlow/Join.cs +++ b/src/core/Elsa.Core/Activities/ControlFlow/Join.cs @@ -35,7 +35,7 @@ public class Join : Activity var workflowExecutionContext = context.WorkflowExecutionContext; // Record last executed activity ID. - var lastActivityId = context.WorkflowExecutionContext.ExecutionLog.LastOrDefault(x => x.EventName == WorkflowExecutionLogEventNames.Executed)?.NodeId; + var lastActivityId = context.WorkflowExecutionContext.ExecutionLog.LastOrDefault(x => x.EventName == WorkflowExecutionLogEventNames.Executed)?.ActivityId; if (lastActivityId != null) { diff --git a/src/core/Elsa.Core/ActivityNodeResolvers/OutboundActivityNodeResolver.cs b/src/core/Elsa.Core/ActivityNodeResolvers/OutboundActivityNodeResolver.cs index 98513de5c..c083d1b8f 100644 --- a/src/core/Elsa.Core/ActivityNodeResolvers/OutboundActivityNodeResolver.cs +++ b/src/core/Elsa.Core/ActivityNodeResolvers/OutboundActivityNodeResolver.cs @@ -18,10 +18,10 @@ public class OutboundActivityNodeResolver : IActivityNodeResolver private static IEnumerable GetSinglePorts(IActivity activity) { - var nodeType = activity.GetType(); + var activityType = activity.GetType(); var ports = - from prop in nodeType.GetProperties(BindingFlags.Public | BindingFlags.Instance) + from prop in activityType.GetProperties(BindingFlags.Public | BindingFlags.Instance) where typeof(IActivity).IsAssignableFrom(prop.PropertyType) || typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) let portAttr = prop.GetCustomAttribute() let nodeAttr = prop.GetCustomAttribute() diff --git a/src/core/Elsa.Core/Models/WorkflowExecutionContext.cs b/src/core/Elsa.Core/Models/WorkflowExecutionContext.cs index 0ce6ae4c7..effca62c9 100644 --- a/src/core/Elsa.Core/Models/WorkflowExecutionContext.cs +++ b/src/core/Elsa.Core/Models/WorkflowExecutionContext.cs @@ -104,9 +104,9 @@ public class WorkflowExecutionContext public void RemoveCompletionCallback(ActivityCompletionCallbackEntry entry) => _completionCallbackEntries.Remove(entry); - public ActivityNode FindNodeById(string nodeId) => NodeIdLookup[nodeId]; + public ActivityNode FindActivityNodeById(string nodeId) => NodeIdLookup[nodeId]; public ActivityNode FindNodeByActivity(IActivity activity) => NodeActivityLookup[activity]; - public IActivity FindActivityById(string activityId) => FindNodeById(activityId).Activity; + public IActivity FindActivityById(string activityId) => FindActivityNodeById(activityId).Activity; public T? GetProperty(string key) => Properties.TryGetValue(key, out var value) ? (T?)value : default(T); public void SetProperty(string key, T value) => Properties[key] = value; diff --git a/src/core/Elsa.Core/Models/WorkflowExecutionLogEntry.cs b/src/core/Elsa.Core/Models/WorkflowExecutionLogEntry.cs index 2f96a5b5a..97bbb94c6 100644 --- a/src/core/Elsa.Core/Models/WorkflowExecutionLogEntry.cs +++ b/src/core/Elsa.Core/Models/WorkflowExecutionLogEntry.cs @@ -1,3 +1,3 @@ namespace Elsa.Models; -public record WorkflowExecutionLogEntry(string NodeId, string NodeType, DateTimeOffset Timestamp, string? EventName, string? Message, string? Source, object? Payload); \ No newline at end of file +public record WorkflowExecutionLogEntry(string ActivityId, string ActivityType, DateTimeOffset Timestamp, string? EventName, string? Message, string? Source, object? Payload); \ No newline at end of file diff --git a/src/core/Elsa.Core/Services/IdentityGraphService.cs b/src/core/Elsa.Core/Services/IdentityGraphService.cs index a61528c61..0d68daae8 100644 --- a/src/core/Elsa.Core/Services/IdentityGraphService.cs +++ b/src/core/Elsa.Core/Services/IdentityGraphService.cs @@ -78,16 +78,16 @@ public class IdentityGraphService : IIdentityGraphService return name; } - private int GetNextIndexFor(string nodeType, IDictionary identityCounters) + private int GetNextIndexFor(string activityType, IDictionary identityCounters) { - if (!identityCounters.TryGetValue(nodeType, out var index)) + if (!identityCounters.TryGetValue(activityType, out var index)) { - identityCounters[nodeType] = index; + identityCounters[activityType] = index; } else { - index = identityCounters[nodeType] + 1; - identityCounters[nodeType] = index; + index = identityCounters[activityType] + 1; + identityCounters[activityType] = index; } return index; diff --git a/src/core/Elsa.Core/Services/WorkflowStateSerializer.cs b/src/core/Elsa.Core/Services/WorkflowStateSerializer.cs index 9e9bfa3cd..369096c26 100644 --- a/src/core/Elsa.Core/Services/WorkflowStateSerializer.cs +++ b/src/core/Elsa.Core/Services/WorkflowStateSerializer.cs @@ -66,17 +66,17 @@ public class WorkflowStateSerializer : IWorkflowStateSerializer private void SetOutput(WorkflowState state, WorkflowExecutionContext workflowExecutionContext) { - foreach (var nodeEntry in state.ActivityOutput) + foreach (var entry in state.ActivityOutput) { - var nodeId = nodeEntry.Key; - var node = workflowExecutionContext.FindNodeById(nodeId); - var nodeType = node.GetType(); + var activityId = entry.Key; + var node = workflowExecutionContext.FindActivityNodeById(activityId); + var activityType = node.Activity.GetType(); - foreach (var outputEntry in nodeEntry.Value) + foreach (var outputEntry in entry.Value) { var propertyName = outputEntry.Key; var propertyValue = outputEntry.Value; - var propertyInfo = nodeType.GetProperty(propertyName, BindingFlags.Public)!; + var propertyInfo = activityType.GetProperty(propertyName, BindingFlags.Public)!; propertyInfo.SetValue(node, propertyValue); } } @@ -87,7 +87,7 @@ public class WorkflowStateSerializer : IWorkflowStateSerializer foreach (var completionCallbackEntry in state.CompletionCallbacks) { var owner = workflowExecutionContext.ActivityExecutionContexts.First(x => x.Id == completionCallbackEntry.OwnerId); - var child = workflowExecutionContext.FindNodeById(completionCallbackEntry.ChildId).Activity; + var child = workflowExecutionContext.FindActivityNodeById(completionCallbackEntry.ChildId).Activity; var callbackName = completionCallbackEntry.MethodName; var callbackDelegate = owner.Activity.GetActivityCompletionCallback(callbackName); workflowExecutionContext.AddCompletionCallback(owner, child, callbackDelegate); diff --git a/src/core/Elsa.Management/Models/ActivityDescriptor.cs b/src/core/Elsa.Management/Models/ActivityDescriptor.cs index 16d2cd08f..19eda03ae 100644 --- a/src/core/Elsa.Management/Models/ActivityDescriptor.cs +++ b/src/core/Elsa.Management/Models/ActivityDescriptor.cs @@ -4,8 +4,15 @@ using Elsa.Contracts; namespace Elsa.Management.Models; -public class ActivityDescriptor : NodeDescriptor +public class ActivityDescriptor { + public string ActivityType { get; init; } = default!; + public string Category { get; init; } = default!; + public string? DisplayName { get; init; } + public string? Description { get; init; } + public ICollection InputProperties { get; init; } = new List(); + public ICollection OutputProperties { get; init; } = new List(); + [JsonIgnore] public Func Constructor { get; init; } = default!; public ActivityTraits Traits { get; set; } = ActivityTraits.Action; public ICollection InPorts { get; init; } = new List(); diff --git a/src/core/Elsa.Management/Models/NodeDescriptor.cs b/src/core/Elsa.Management/Models/NodeDescriptor.cs deleted file mode 100644 index b1372f4dd..000000000 --- a/src/core/Elsa.Management/Models/NodeDescriptor.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Elsa.Management.Models; - -public abstract class NodeDescriptor -{ - public string NodeType { get; init; } = default!; - public string Category { get; init; } = default!; - public string? DisplayName { get; init; } - public string? Description { get; init; } - public ICollection InputProperties { get; init; } = new List(); - public ICollection OutputProperties { get; init; } = new List(); -} \ No newline at end of file diff --git a/src/core/Elsa.Management/Models/TriggerDescriptor.cs b/src/core/Elsa.Management/Models/TriggerDescriptor.cs deleted file mode 100644 index dd2c52ac3..000000000 --- a/src/core/Elsa.Management/Models/TriggerDescriptor.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; -using Elsa.Contracts; - -namespace Elsa.Management.Models; - -public class TriggerDescriptor : NodeDescriptor -{ - [JsonIgnore] public Func Constructor { get; init; } = default!; -} - -public record TriggerConstructorContext(JsonElement Element, JsonSerializerOptions SerializerOptions); \ No newline at end of file diff --git a/src/core/Elsa.Management/Serialization/Converters/ActivityJsonConverter.cs b/src/core/Elsa.Management/Serialization/Converters/ActivityJsonConverter.cs index 0d2423f9f..9db55acdb 100644 --- a/src/core/Elsa.Management/Serialization/Converters/ActivityJsonConverter.cs +++ b/src/core/Elsa.Management/Serialization/Converters/ActivityJsonConverter.cs @@ -25,7 +25,7 @@ public class ActivityJsonConverter : JsonConverter if (!JsonDocument.TryParseValue(ref reader, out var doc)) throw new JsonException("Failed to parse JsonDocument"); - if (!doc.RootElement.TryGetProperty("nodeType", out var activityTypeNameElement)) + if (!doc.RootElement.TryGetProperty("typeName", out var activityTypeNameElement)) throw new JsonException("Failed to extract activity type property"); var activityTypeName = activityTypeNameElement.GetString()!; diff --git a/src/core/Elsa.Management/Serialization/Converters/FlowchartJsonConverter.cs b/src/core/Elsa.Management/Serialization/Converters/FlowchartJsonConverter.cs index aeb14b3c7..59daed67d 100644 --- a/src/core/Elsa.Management/Serialization/Converters/FlowchartJsonConverter.cs +++ b/src/core/Elsa.Management/Serialization/Converters/FlowchartJsonConverter.cs @@ -54,12 +54,12 @@ public class FlowchartJsonConverter : JsonConverter var model = new { - NodeType = value.TypeName, - Id = value.Id, - Metadata = value.Metadata, + value.TypeName, + value.Id, + value.Metadata, Start = value.Start?.Id, - Activities = value.Activities, - Connections = value.Connections + value.Activities, + value.Connections }; JsonSerializer.Serialize(writer, model, connectionSerializerOptions); diff --git a/src/core/Elsa.Management/Services/ActivityDescriber.cs b/src/core/Elsa.Management/Services/ActivityDescriber.cs index c5add7090..8fbb96bc2 100644 --- a/src/core/Elsa.Management/Services/ActivityDescriber.cs +++ b/src/core/Elsa.Management/Services/ActivityDescriber.cs @@ -57,7 +57,7 @@ public class ActivityDescriber : IActivityDescriber { Category = category, Description = description, - NodeType = fullTypeName, + ActivityType = fullTypeName, DisplayName = displayName, Traits = isTrigger ? ActivityTraits.Trigger : ActivityTraits.Action, OutPorts = outboundPorts.ToList(), @@ -106,7 +106,8 @@ public class ActivityDescriber : IActivityDescriber foreach (var propertyInfo in properties) { var activityPropertyAttribute = propertyInfo.GetCustomAttribute(); - var wrappedPropertyType = propertyInfo.PropertyType.GenericTypeArguments[0]; + var typeArgs = propertyInfo.PropertyType.GenericTypeArguments; + var wrappedPropertyType = typeArgs.Any() ? typeArgs[0] : typeof(object); yield return new OutputDescriptor ( diff --git a/src/core/Elsa.Management/Services/ActivityRegistry.cs b/src/core/Elsa.Management/Services/ActivityRegistry.cs index 3ce53ba3d..56915417e 100644 --- a/src/core/Elsa.Management/Services/ActivityRegistry.cs +++ b/src/core/Elsa.Management/Services/ActivityRegistry.cs @@ -29,7 +29,7 @@ public class ActivityRegistry : IActivityRegistry var descriptors = ListByProvider(provider).ToList(); foreach (var descriptor in descriptors) - _activityDescriptors.Remove(descriptor.NodeType); + _activityDescriptors.Remove(descriptor.ActivityType); _providedActivityDescriptors.Remove(provider); } @@ -41,7 +41,7 @@ public class ActivityRegistry : IActivityRegistry private void Add(ActivityDescriptor descriptor, ICollection target) { - _activityDescriptors.Add(descriptor.NodeType, descriptor); + _activityDescriptors.Add(descriptor.ActivityType, descriptor); target.Add(descriptor); } diff --git a/src/designer/elsa-workflows-designer/src/components.d.ts b/src/designer/elsa-workflows-designer/src/components.d.ts index b207e6b0b..5910d9df7 100644 --- a/src/designer/elsa-workflows-designer/src/components.d.ts +++ b/src/designer/elsa-workflows-designer/src/components.d.ts @@ -9,7 +9,7 @@ import { ActionDefinition, ActionInvokedArgs, Activity, ActivityDescriptor, Acti import { ActivityUpdatedArgs, DeleteActivityRequestedArgs } from "./components/designer/activity-properties-editor/activity-properties-editor"; import { ContainerActivityComponent } from "./components/activities/container-activity-component"; import { AddActivityArgs } from "./components/designer/canvas/canvas"; -import { NodeInputContext } from "./services/node-input-driver"; +import { ActivityInputContext } from "./services/node-input-driver"; import { MenuItem } from "./components/shared/context-menu/models"; import { DropdownButtonItem, DropdownButtonOrigin } from "./components/shared/dropdown-button/models"; import { Graph } from "@antv/x6"; @@ -38,10 +38,10 @@ export namespace Components { "updateLayout": () => Promise; } interface ElsaCheckListInput { - "inputContext": NodeInputContext; + "inputContext": ActivityInputContext; } interface ElsaCodeEditorInput { - "inputContext": NodeInputContext; + "inputContext": ActivityInputContext; } interface ElsaContextMenu { "menuItems": Array; @@ -53,7 +53,7 @@ export namespace Components { "text": string; } interface ElsaDropdownInput { - "inputContext": NodeInputContext; + "inputContext": ActivityInputContext; } interface ElsaFlowchart { "activityDescriptors": Array; @@ -112,10 +112,10 @@ export namespace Components { "value": string; } interface ElsaMultiLineInput { - "inputContext": NodeInputContext; + "inputContext": ActivityInputContext; } interface ElsaMultiTextInput { - "inputContext": NodeInputContext; + "inputContext": ActivityInputContext; } interface ElsaPager { "page": number; @@ -126,10 +126,10 @@ export namespace Components { "position": PanelPosition; } interface ElsaRadioListInput { - "inputContext": NodeInputContext; + "inputContext": ActivityInputContext; } interface ElsaSingleLineInput { - "inputContext": NodeInputContext; + "inputContext": ActivityInputContext; } interface ElsaSlideOverPanel { "actions": Array; @@ -145,7 +145,7 @@ export namespace Components { "serverUrl": string; } interface ElsaSwitchEditor { - "inputContext": NodeInputContext; + "inputContext": ActivityInputContext; } interface ElsaToolbox { "graph": Graph; @@ -423,10 +423,10 @@ declare namespace LocalJSX { "interactiveMode"?: boolean; } interface ElsaCheckListInput { - "inputContext"?: NodeInputContext; + "inputContext"?: ActivityInputContext; } interface ElsaCodeEditorInput { - "inputContext"?: NodeInputContext; + "inputContext"?: ActivityInputContext; } interface ElsaContextMenu { "menuItems"?: Array; @@ -439,7 +439,7 @@ declare namespace LocalJSX { "text"?: string; } interface ElsaDropdownInput { - "inputContext"?: NodeInputContext; + "inputContext"?: ActivityInputContext; } interface ElsaFlowchart { "activityDescriptors"?: Array; @@ -504,10 +504,10 @@ declare namespace LocalJSX { "value"?: string; } interface ElsaMultiLineInput { - "inputContext"?: NodeInputContext; + "inputContext"?: ActivityInputContext; } interface ElsaMultiTextInput { - "inputContext"?: NodeInputContext; + "inputContext"?: ActivityInputContext; } interface ElsaPager { "onPaginated"?: (event: CustomEvent) => void; @@ -520,10 +520,10 @@ declare namespace LocalJSX { "position"?: PanelPosition; } interface ElsaRadioListInput { - "inputContext"?: NodeInputContext; + "inputContext"?: ActivityInputContext; } interface ElsaSingleLineInput { - "inputContext"?: NodeInputContext; + "inputContext"?: ActivityInputContext; } interface ElsaSlideOverPanel { "actions"?: Array; @@ -539,7 +539,7 @@ declare namespace LocalJSX { "serverUrl"?: string; } interface ElsaSwitchEditor { - "inputContext"?: NodeInputContext; + "inputContext"?: ActivityInputContext; } interface ElsaToolbox { "graph"?: Graph; diff --git a/src/designer/elsa-workflows-designer/src/components/activities/flowchart/activity-walker.ts b/src/designer/elsa-workflows-designer/src/components/activities/flowchart/activity-walker.ts index a2b94b7e3..7876d2557 100644 --- a/src/designer/elsa-workflows-designer/src/components/activities/flowchart/activity-walker.ts +++ b/src/designer/elsa-workflows-designer/src/components/activities/flowchart/activity-walker.ts @@ -62,9 +62,9 @@ function walkRecursive(node: ActivityNode, activity: Activity, collectedActiviti function getPorts(node: ActivityNode, activity: Activity, descriptors: Array): Array { const portProviderRegistry = Container.get(PortProviderRegistry); const transposeHandlerRegistry = Container.get(TransposeHandlerRegistry); - const transposeHandler = transposeHandlerRegistry.get(activity.nodeType); + const transposeHandler = transposeHandlerRegistry.get(activity.typeName); const portProvider = portProviderRegistry.get(activity.nodeType); - const activityDescriptor = descriptors.find(x => x.nodeType == activity.nodeType); + const activityDescriptor = descriptors.find(x => x.activityType == activity.typeName); const untransposedConnections = transposeHandler.untranspose({activity, activityDescriptor}); return untransposedConnections.map(x => ({activity: x.target, port: x.sourcePort})); } diff --git a/src/designer/elsa-workflows-designer/src/components/activities/flowchart/default-node-handler.ts b/src/designer/elsa-workflows-designer/src/components/activities/flowchart/default-node-handler.ts index 085d75d7c..a98b01959 100644 --- a/src/designer/elsa-workflows-designer/src/components/activities/flowchart/default-node-handler.ts +++ b/src/designer/elsa-workflows-designer/src/components/activities/flowchart/default-node-handler.ts @@ -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.nodeType); + const provider = this.portProviderRegistry.get(activityDescriptor.activityType); const providerContext: PortProviderContext = {activityDescriptor, activity}; let inPorts = provider.getInboundPorts(providerContext); let outPorts = provider.getOutboundPorts(providerContext); 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 0420d8cbf..c0ae35d98 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 @@ -68,7 +68,7 @@ export class FlowchartComponent implements ContainerActivityComponent { const activity: Activity = { id: uuid(), - nodeType: descriptor.nodeType, + typeName: descriptor.activityType, metadata: { designer: { position: { @@ -161,9 +161,9 @@ export class FlowchartComponent implements ContainerActivityComponent { for (const connection of connections) { const source = activities.find(x => x.id == connection.source); const target = activities.find(x => x.id == connection.target); - const sourceDescriptor = activityDescriptors.find(x => x.nodeType == source.nodeType); - const targetDescriptor = activityDescriptors.find(x => x.nodeType == target.nodeType); - const transposeHandler = transposeHandlerRegistry.get(source.nodeType); + const sourceDescriptor = activityDescriptors.find(x => x.activityType == source.typeName); + const targetDescriptor = activityDescriptors.find(x => x.activityType == target.typeName); + const transposeHandler = transposeHandlerRegistry.get(source.typeName); if (transposeHandler.transpose({source, target, connection, sourceDescriptor, targetDescriptor})) { // Remove the target activity from the list. @@ -175,7 +175,7 @@ export class FlowchartComponent implements ContainerActivityComponent { } return { - nodeType: 'Workflows.Flowchart', + typeName: 'Workflows.Flowchart', activities: remainingActivities, connections: remainingConnections, id: this.rootId, @@ -207,7 +207,7 @@ export class FlowchartComponent implements ContainerActivityComponent { const activity = activityNode.activity; const position = activity.metadata.designer?.position || {x: 100, y: 100}; const {x, y} = position; - const descriptor = descriptors.find(x => x.nodeType == activity.nodeType) + const descriptor = descriptors.find(x => x.activityType == activity.typeName) return this.nodeFactory.createNode(descriptor, activity, x, y); }); diff --git a/src/designer/elsa-workflows-designer/src/components/activities/flowchart/node-factory.ts b/src/designer/elsa-workflows-designer/src/components/activities/flowchart/node-factory.ts index 83c2bc780..4526bb9a9 100644 --- a/src/designer/elsa-workflows-designer/src/components/activities/flowchart/node-factory.ts +++ b/src/designer/elsa-workflows-designer/src/components/activities/flowchart/node-factory.ts @@ -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.nodeType); + const handler = this.handlerRegistry.createHandler(activityDescriptor.activityType); return handler.createDesignerNode({activityDescriptor, activity, x, y}); } } diff --git a/src/designer/elsa-workflows-designer/src/components/activities/flowchart/shapes.ts b/src/designer/elsa-workflows-designer/src/components/activities/flowchart/shapes.ts index 333a1c843..4cb0f13bf 100644 --- a/src/designer/elsa-workflows-designer/src/components/activities/flowchart/shapes.ts +++ b/src/designer/elsa-workflows-designer/src/components/activities/flowchart/shapes.ts @@ -71,7 +71,7 @@ export class ActivityNode extends Shape.HTML { createHtml() { const activityDescriptor = this.activityDescriptor as ActivityDescriptor; const activity = this.activity as Activity; - const activityType = activityDescriptor.nodeType; + const activityType = activityDescriptor.activityType; const driverRegistry = Container.get(ActivityDriverRegistry); const driver = driverRegistry.createDriver(activityType); diff --git a/src/designer/elsa-workflows-designer/src/components/designer/activity-properties-editor/activity-properties-editor.tsx b/src/designer/elsa-workflows-designer/src/components/designer/activity-properties-editor/activity-properties-editor.tsx index 03658a40f..6577f12c6 100644 --- a/src/designer/elsa-workflows-designer/src/components/designer/activity-properties-editor/activity-properties-editor.tsx +++ b/src/designer/elsa-workflows-designer/src/components/designer/activity-properties-editor/activity-properties-editor.tsx @@ -5,14 +5,14 @@ import { Activity, ActivityDescriptor, DefaultActions, InputDescriptor, - RenderNodePropContext, - RenderNodePropsContext, + RenderActivityPropContext, + RenderActivityPropsContext, TabChangedArgs, TabDefinition } from '../../../models'; import {InputDriverRegistry} from "../../../services"; import {Container} from "typedi"; -import {NodeInputContext} from "../../../services/node-input-driver"; +import {ActivityInputContext} from "../../../services/node-input-driver"; import {FormEntry} from "../../shared/forms/form-entry"; export interface ActivityUpdatedArgs { @@ -31,7 +31,7 @@ export interface DeleteActivityRequestedArgs { }) export class ActivityPropertiesEditor { private slideOverPanel: HTMLElsaSlideOverPanelElement; - private renderContext: RenderNodePropsContext; + private renderContext: RenderActivityPropsContext; private readonly inputDriverRegistry: InputDriverRegistry; constructor() { @@ -58,11 +58,11 @@ export class ActivityPropertiesEditor { public componentWillRender() { const activity = this.activity; const activityDescriptor = this.findActivityDescriptor(); - const title = activityDescriptor?.displayName ?? activityDescriptor?.nodeType ?? 'Unknown Activity'; + const title = activityDescriptor?.displayName ?? activityDescriptor?.activityType ?? 'Unknown Activity'; const driverRegistry = this.inputDriverRegistry; - const renderPropertyContexts: Array = activityDescriptor.inputProperties.map(inputDescriptor => { - const renderInputContext: NodeInputContext = { + const renderPropertyContexts: Array = activityDescriptor.inputProperties.map(inputDescriptor => { + const renderInputContext: ActivityInputContext = { node: activity, nodeDescriptor: activityDescriptor, inputDescriptor, @@ -80,15 +80,15 @@ export class ActivityPropertiesEditor { }); this.renderContext = { - node: activity, - nodeDescriptor: activityDescriptor, + activity, + activityDescriptor, title, properties: renderPropertyContexts } } public render() { - const {nodeDescriptor, title} = this.renderContext; + const {activityDescriptor, title} = this.renderContext; const propertiesTab: TabDefinition = { displayText: 'Properties', @@ -100,7 +100,7 @@ export class ActivityPropertiesEditor { content: () => this.renderCommonTab() }; - const tabs = !!nodeDescriptor ? [propertiesTab, commonTab] : []; + const tabs = !!activityDescriptor ? [propertiesTab, commonTab] : []; const actions = [DefaultActions.Delete(this.onDeleteActivity)]; return ( @@ -111,7 +111,7 @@ export class ActivityPropertiesEditor { ); } - private findActivityDescriptor = (): ActivityDescriptor => !!this.activity ? this.activityDescriptors.find(x => x.nodeType == this.activity.nodeType) : null; + private findActivityDescriptor = (): ActivityDescriptor => !!this.activity ? this.activityDescriptors.find(x => x.activityType == this.activity.typeName) : null; private onSelectedTabIndexChanged = (e: CustomEvent) => this.selectedTabIndex = e.detail.selectedTabIndex private onActivityIdChanged = (e: any) => { @@ -148,8 +148,8 @@ export class ActivityPropertiesEditor { private onDeleteActivity = () => this.deleteActivityRequested.emit({activity: this.activity}); private renderPropertiesTab = () => { - const {node, properties} = this.renderContext; - const activityId = node.id; + const {activity, properties} = this.renderContext; + const activityId = activity.id; return
@@ -157,7 +157,7 @@ export class ActivityPropertiesEditor { {properties.filter(x => !!x.inputControl).map(propertyContext => { - const key = `${node.id}-${propertyContext.inputContext.inputDescriptor.name}`; + const key = `${activity.id}-${propertyContext.inputContext.inputDescriptor.name}`; return
{propertyContext.inputControl}
; diff --git a/src/designer/elsa-workflows-designer/src/components/designer/toolbox/toolbox-activities.tsx b/src/designer/elsa-workflows-designer/src/components/designer/toolbox/toolbox-activities.tsx index 0eca17d92..5254e24e4 100644 --- a/src/designer/elsa-workflows-designer/src/components/designer/toolbox/toolbox-activities.tsx +++ b/src/designer/elsa-workflows-designer/src/components/designer/toolbox/toolbox-activities.tsx @@ -56,11 +56,11 @@ export class ToolboxActivities { const activityDriverRegistry = Container.get(ActivityDriverRegistry); for (const activityDescriptor of value) { - const nodeType = activityDescriptor.nodeType; - const driver = activityDriverRegistry.createDriver(nodeType); + const activityType = activityDescriptor.activityType; + const driver = activityDriverRegistry.createDriver(activityType); const html = driver.display({displayType: 'picker', activityDescriptor: activityDescriptor}); - renderedActivities.set(nodeType, html); + renderedActivities.set(activityType, html); } this.renderedActivities = renderedActivities; @@ -108,7 +108,7 @@ export class ToolboxActivities {
{activityDescriptors.map(activityDescriptor => { - const activityHtml = renderedActivities.get(activityDescriptor.nodeType); + const activityHtml = renderedActivities.get(activityDescriptor.activityType); return (
= []; @State() private selectedValue?: number; diff --git a/src/designer/elsa-workflows-designer/src/components/inputs/code-editor.tsx b/src/designer/elsa-workflows-designer/src/components/inputs/code-editor.tsx index 6bf879233..e22f3d523 100644 --- a/src/designer/elsa-workflows-designer/src/components/inputs/code-editor.tsx +++ b/src/designer/elsa-workflows-designer/src/components/inputs/code-editor.tsx @@ -1,6 +1,6 @@ import {Component, h, Prop} from '@stencil/core'; import {EditorHeight, LiteralExpression, SyntaxNames} from "../../models"; -import {NodeInputContext} from "../../services/node-input-driver"; +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"; @@ -16,7 +16,7 @@ interface CodeEditorOptions { shadow: false }) export class CodeEditorInput { - @Prop() public inputContext: NodeInputContext; + @Prop() public inputContext: ActivityInputContext; public render() { const inputContext = this.inputContext; diff --git a/src/designer/elsa-workflows-designer/src/components/inputs/dropdown.tsx b/src/designer/elsa-workflows-designer/src/components/inputs/dropdown.tsx index 52ce8e9b8..7746304db 100644 --- a/src/designer/elsa-workflows-designer/src/components/inputs/dropdown.tsx +++ b/src/designer/elsa-workflows-designer/src/components/inputs/dropdown.tsx @@ -1,6 +1,6 @@ import {Component, Prop, h} from '@stencil/core'; import {LiteralExpression, SelectList, SyntaxNames} from "../../models"; -import {NodeInputContext} from "../../services/node-input-driver"; +import {ActivityInputContext} from "../../services/node-input-driver"; import {getInputPropertyValue, getSelectListItems} from "../../utils"; import {ExpressionChangedArs} from "../designer/input-control-switch/input-control-switch"; @@ -9,7 +9,7 @@ import {ExpressionChangedArs} from "../designer/input-control-switch/input-contr shadow: false }) export class SingleLineInput { - @Prop() public inputContext: NodeInputContext; + @Prop() public inputContext: ActivityInputContext; private selectList: SelectList = {items: [], isFlagsEnum: false}; diff --git a/src/designer/elsa-workflows-designer/src/components/inputs/multi-line.tsx b/src/designer/elsa-workflows-designer/src/components/inputs/multi-line.tsx index 538d7a8ec..07935c7db 100644 --- a/src/designer/elsa-workflows-designer/src/components/inputs/multi-line.tsx +++ b/src/designer/elsa-workflows-designer/src/components/inputs/multi-line.tsx @@ -1,6 +1,6 @@ import {Component, Prop, h} from '@stencil/core'; import {LiteralExpression, SyntaxNames} from "../../models"; -import {NodeInputContext} from "../../services/node-input-driver"; +import {ActivityInputContext} from "../../services/node-input-driver"; import {getInputPropertyValue} from "../../utils"; import {ExpressionChangedArs} from "../designer/input-control-switch/input-control-switch"; @@ -9,7 +9,7 @@ import {ExpressionChangedArs} from "../designer/input-control-switch/input-contr shadow: false }) export class MultiLineInput { - @Prop() inputContext: NodeInputContext; + @Prop() inputContext: ActivityInputContext; public render() { const inputContext = this.inputContext; diff --git a/src/designer/elsa-workflows-designer/src/components/inputs/multi-text.tsx b/src/designer/elsa-workflows-designer/src/components/inputs/multi-text.tsx index 52a293e64..dd969e568 100644 --- a/src/designer/elsa-workflows-designer/src/components/inputs/multi-text.tsx +++ b/src/designer/elsa-workflows-designer/src/components/inputs/multi-text.tsx @@ -1,6 +1,6 @@ import {Component, Prop, h} from '@stencil/core'; import {JsonExpression, LiteralExpression, SyntaxNames} from "../../models"; -import {NodeInputContext} from "../../services/node-input-driver"; +import {ActivityInputContext} from "../../services/node-input-driver"; import {getInputPropertyValue, parseJson} from "../../utils"; import {ExpressionChangedArs} from "../designer/input-control-switch/input-control-switch"; @@ -9,7 +9,7 @@ import {ExpressionChangedArs} from "../designer/input-control-switch/input-contr shadow: false }) export class MultiTextInput { - @Prop() inputContext: NodeInputContext; + @Prop() inputContext: ActivityInputContext; public render() { const inputContext = this.inputContext; diff --git a/src/designer/elsa-workflows-designer/src/components/inputs/radio-list.tsx b/src/designer/elsa-workflows-designer/src/components/inputs/radio-list.tsx index 39e247484..f60b7b122 100644 --- a/src/designer/elsa-workflows-designer/src/components/inputs/radio-list.tsx +++ b/src/designer/elsa-workflows-designer/src/components/inputs/radio-list.tsx @@ -1,6 +1,6 @@ import {Component, h, Prop, State} from '@stencil/core'; import {LiteralExpression, SelectList, SyntaxNames} from "../../models"; -import {NodeInputContext} from "../../services/node-input-driver"; +import {ActivityInputContext} from "../../services/node-input-driver"; import {getSelectListItems, getInputPropertyValue} from "../../utils"; import {ExpressionChangedArs} from "../designer/input-control-switch/input-control-switch"; @@ -11,7 +11,7 @@ import {ExpressionChangedArs} from "../designer/input-control-switch/input-contr export class RadioList { private selectList: SelectList = {items: [], isFlagsEnum: false}; - @Prop() public inputContext: NodeInputContext; + @Prop() public inputContext: ActivityInputContext; @State() private selectedValue?: string; public async componentWillLoad() { diff --git a/src/designer/elsa-workflows-designer/src/components/inputs/single-line.tsx b/src/designer/elsa-workflows-designer/src/components/inputs/single-line.tsx index 4b5fc612a..46c6ed769 100644 --- a/src/designer/elsa-workflows-designer/src/components/inputs/single-line.tsx +++ b/src/designer/elsa-workflows-designer/src/components/inputs/single-line.tsx @@ -1,6 +1,6 @@ import {Component, h, Prop} from '@stencil/core'; import {LiteralExpression, SyntaxNames} from "../../models"; -import {NodeInputContext} from "../../services/node-input-driver"; +import {ActivityInputContext} from "../../services/node-input-driver"; import {getInputPropertyValue} from "../../utils"; import {ExpressionChangedArs} from "../designer/input-control-switch/input-control-switch"; @@ -9,7 +9,7 @@ import {ExpressionChangedArs} from "../designer/input-control-switch/input-contr shadow: false }) export class SingleLineInput { - @Prop() public inputContext: NodeInputContext; + @Prop() public inputContext: ActivityInputContext; public render() { const inputContext = this.inputContext; diff --git a/src/designer/elsa-workflows-designer/src/drivers/activity/default-activity-driver.tsx b/src/designer/elsa-workflows-designer/src/drivers/activity/default-activity-driver.tsx index bb40279c2..27a56d07c 100644 --- a/src/designer/elsa-workflows-designer/src/drivers/activity/default-activity-driver.tsx +++ b/src/designer/elsa-workflows-designer/src/drivers/activity/default-activity-driver.tsx @@ -15,13 +15,13 @@ export class DefaultActivityDriver implements ActivityDriver { display(context: ActivityDisplayContext): any { const iconRegistry = this.iconRegistry; const activityDescriptor = context.activityDescriptor; - const nodeType = activityDescriptor.nodeType; + const activityType = activityDescriptor.activityType; const text = activityDescriptor?.displayName; const isTrigger = (activityDescriptor?.traits & ActivityTraits.Trigger) == ActivityTraits.Trigger; const borderColor = isTrigger ? 'border-green-600' : 'border-blue-600'; const backgroundColor = isTrigger ? 'bg-green-400' : 'bg-blue-400'; const iconBackgroundColor = isTrigger ? 'bg-green-500' : 'bg-blue-500'; - const icon = iconRegistry.has(nodeType) ? iconRegistry.get(nodeType) : null; + const icon = iconRegistry.has(activityType) ? iconRegistry.get(activityType) : null; return (`
diff --git a/src/designer/elsa-workflows-designer/src/drivers/input/default-input-driver.tsx b/src/designer/elsa-workflows-designer/src/drivers/input/default-input-driver.tsx index 60c73c294..b139bcbd8 100644 --- a/src/designer/elsa-workflows-designer/src/drivers/input/default-input-driver.tsx +++ b/src/designer/elsa-workflows-designer/src/drivers/input/default-input-driver.tsx @@ -1,4 +1,4 @@ -import {NodeInputDriver, NodeInputContext} from "../../services/node-input-driver"; +import {NodeInputDriver, ActivityInputContext} from "../../services/node-input-driver"; import {Container} from "typedi"; import {InputControlRegistry} from "../../services/input-control-registry"; import {h} from "@stencil/core"; @@ -16,14 +16,14 @@ export class DefaultInputDriver implements NodeInputDriver { return -1; } - renderInput(context: NodeInputContext): any { + renderInput(context: ActivityInputContext): any { const inputDescriptor = context.inputDescriptor; const uiHint = inputDescriptor.uiHint; const inputControl = this.inputControlRegistry.get(uiHint); return inputControl(context); } - supportsInput(context: NodeInputContext): boolean { + supportsInput(context: ActivityInputContext): boolean { const uiHint = context.inputDescriptor.uiHint; return this.inputControlRegistry.has(uiHint); } diff --git a/src/designer/elsa-workflows-designer/src/models/api.ts b/src/designer/elsa-workflows-designer/src/models/api.ts index 34915bc28..f81c5d3e2 100644 --- a/src/designer/elsa-workflows-designer/src/models/api.ts +++ b/src/designer/elsa-workflows-designer/src/models/api.ts @@ -5,14 +5,11 @@ export interface ActivityDescriptorResponse { activityDescriptors: Array; } -export interface NodeDescriptor { - nodeType: string; +export interface ActivityDescriptor { + activityType: string; displayName: string; category: string; inputProperties: Array -} - -export interface ActivityDescriptor extends NodeDescriptor { traits: ActivityTraits; inPorts: Array; outPorts: Array; @@ -23,7 +20,7 @@ export enum ActivityTraits { Trigger = 2 } -export interface NodePropertyDescriptor { +export interface PropertyDescriptor { name: string; type: Type; displayName?: string; @@ -32,7 +29,7 @@ export interface NodePropertyDescriptor { isBrowsable?: boolean; } -export interface InputDescriptor extends NodePropertyDescriptor { +export interface InputDescriptor extends PropertyDescriptor { uiHint?: string; options?: any; category?: string; @@ -42,7 +39,7 @@ export interface InputDescriptor extends NodePropertyDescriptor { isReadOnly?: boolean; } -export interface OutputDescriptor extends NodePropertyDescriptor { +export interface OutputDescriptor extends PropertyDescriptor { } export interface Port { diff --git a/src/designer/elsa-workflows-designer/src/models/core.ts b/src/designer/elsa-workflows-designer/src/models/core.ts index 329814d75..77a65d33e 100644 --- a/src/designer/elsa-workflows-designer/src/models/core.ts +++ b/src/designer/elsa-workflows-designer/src/models/core.ts @@ -2,17 +2,14 @@ import {Type} from "./shared"; import {Expression} from "./expressions"; import {VersionOptions} from "./api"; -export interface Node { +export interface Activity { id: string; - nodeType: string; + typeName: string; metadata: any; [name: string]: any; } -export interface Activity extends Node { -} - export interface Trigger extends Activity { } diff --git a/src/designer/elsa-workflows-designer/src/models/ui.ts b/src/designer/elsa-workflows-designer/src/models/ui.ts index 3d23f918e..3a5edcba7 100644 --- a/src/designer/elsa-workflows-designer/src/models/ui.ts +++ b/src/designer/elsa-workflows-designer/src/models/ui.ts @@ -1,6 +1,6 @@ -import {Activity, Node} from "./core"; -import {ActivityDescriptor, InputDescriptor, NodeDescriptor} from "./api"; -import {NodeInputContext} from "../services/node-input-driver"; +import {ActivityInputContext} from "../services/node-input-driver"; +import {Activity} from "./core"; +import {ActivityDescriptor} from "./api"; export interface TabDefinition { displayText: string; @@ -66,15 +66,15 @@ export class DefaultActions { }); } -export interface RenderNodePropsContext { - node: Node; - nodeDescriptor: NodeDescriptor; +export interface RenderActivityPropsContext { + activity: Activity; + activityDescriptor: ActivityDescriptor; title: string; - properties: Array; + properties: Array; } -export interface RenderNodePropContext { - inputContext: NodeInputContext +export interface RenderActivityPropContext { + inputContext: ActivityInputContext inputControl?: any; } diff --git a/src/designer/elsa-workflows-designer/src/plugins/switch/switch-editor.tsx b/src/designer/elsa-workflows-designer/src/plugins/switch/switch-editor.tsx index f38475f17..010ad6e74 100644 --- a/src/designer/elsa-workflows-designer/src/plugins/switch/switch-editor.tsx +++ b/src/designer/elsa-workflows-designer/src/plugins/switch/switch-editor.tsx @@ -1,6 +1,6 @@ import {Component, h, Prop, State} from "@stencil/core"; import {camelCase} from 'lodash'; -import {NodeInputContext} from "../../services/node-input-driver"; +import {ActivityInputContext} from "../../services/node-input-driver"; import {mapSyntaxToLanguage} from "../../utils"; import {SyntaxNames} from "../../models"; import {SwitchCase} from "./models"; @@ -14,7 +14,7 @@ import {FormEntry} from "../../components/shared/forms/form-entry"; shadow: false }) export class SwitchEditor { - @Prop() public inputContext: NodeInputContext; + @Prop() public inputContext: ActivityInputContext; @State() private cases: Array = []; private supportedSyntaxes: Array = [SyntaxNames.JavaScript, SyntaxNames.Literal]; diff --git a/src/designer/elsa-workflows-designer/src/services/input-driver-registry.ts b/src/designer/elsa-workflows-designer/src/services/input-driver-registry.ts index 5ebfe7a1c..0f4393a65 100644 --- a/src/designer/elsa-workflows-designer/src/services/input-driver-registry.ts +++ b/src/designer/elsa-workflows-designer/src/services/input-driver-registry.ts @@ -1,6 +1,6 @@ import _ from 'lodash'; import {Service} from 'typedi'; -import {NodeInputDriver, NodeInputContext} from './node-input-driver'; +import {NodeInputDriver, ActivityInputContext} from './node-input-driver'; import {DefaultInputDriver} from "../drivers/input/default-input-driver"; @Service() @@ -12,7 +12,7 @@ export class InputDriverRegistry { this.drivers = _.orderBy(drivers, x => x.priority, 'desc'); } - public get(context: NodeInputContext): NodeInputDriver { + public get(context: ActivityInputContext): NodeInputDriver { return this.drivers.find(x => x.supportsInput(context)); } } diff --git a/src/designer/elsa-workflows-designer/src/services/node-input-driver.ts b/src/designer/elsa-workflows-designer/src/services/node-input-driver.ts index bd5ee4658..a41a3880a 100644 --- a/src/designer/elsa-workflows-designer/src/services/node-input-driver.ts +++ b/src/designer/elsa-workflows-designer/src/services/node-input-driver.ts @@ -1,17 +1,17 @@ -import {InputDescriptor, NodeDescriptor, Node} from "../models"; +import {Activity, ActivityDescriptor, InputDescriptor} from "../models"; -export interface NodeInputContext { - node: Node; - nodeDescriptor: NodeDescriptor; +export interface ActivityInputContext { + node: Activity; + nodeDescriptor: ActivityDescriptor; inputDescriptor: InputDescriptor; notifyInputChanged: () => void; inputChanged: (value: any, syntax: string) => void; } export interface NodeInputDriver { - supportsInput(context: NodeInputContext): boolean; + supportsInput(context: ActivityInputContext): boolean; get priority(): number; - renderInput(context: NodeInputContext): any; + renderInput(context: ActivityInputContext): any; } diff --git a/src/designer/elsa-workflows-designer/src/utils/utils.ts b/src/designer/elsa-workflows-designer/src/utils/utils.ts index ee0266400..0737f560e 100644 --- a/src/designer/elsa-workflows-designer/src/utils/utils.ts +++ b/src/designer/elsa-workflows-designer/src/utils/utils.ts @@ -1,7 +1,7 @@ import moment from 'moment'; import {camelCase} from 'lodash'; import {ActivityInput, VersionOptions} from '../models'; -import {NodeInputContext} from '../services/node-input-driver'; +import {ActivityInputContext} from '../services/node-input-driver'; export function formatTimestamp(timestamp?: Date, defaultText?: string): string { return !!timestamp ? moment(timestamp).format('DD-MM-YYYY HH:mm:ss') : defaultText; @@ -50,13 +50,13 @@ export const mapSyntaxToLanguage = (syntax: string): string => { } }; -export const getInputPropertyName = (inputContext: NodeInputContext) => { +export const getInputPropertyName = (inputContext: ActivityInputContext) => { const inputProperty = inputContext.inputDescriptor; const propertyName = inputProperty.name; return camelCase(propertyName); } -export const getInputPropertyValue = (inputContext: NodeInputContext): ActivityInput => { +export const getInputPropertyValue = (inputContext: ActivityInputContext): ActivityInput => { const propName = getInputPropertyName(inputContext); return inputContext.node[propName] as ActivityInput; }; diff --git a/src/modules/Elsa.Modules.Scheduling/Services/WorkflowBookmarkScheduler.cs b/src/modules/Elsa.Modules.Scheduling/Services/WorkflowBookmarkScheduler.cs index d173b9921..f99367e75 100644 --- a/src/modules/Elsa.Modules.Scheduling/Services/WorkflowBookmarkScheduler.cs +++ b/src/modules/Elsa.Modules.Scheduling/Services/WorkflowBookmarkScheduler.cs @@ -39,7 +39,7 @@ public class WorkflowBookmarkScheduler : IWorkflowBookmarkScheduler var resumeAt = payload.ResumeAt; var job = new ResumeWorkflowJob(workflowInstanceId, bookmark.ToBookmark()); var schedule = new SpecificInstantSchedule(resumeAt); - await _jobScheduler.ScheduleAsync(job, schedule, groupKeys, cancellationToken); + await _jobScheduler.ScheduleAsync(job, bookmark.Id, schedule, groupKeys, cancellationToken); } } @@ -50,8 +50,7 @@ public class WorkflowBookmarkScheduler : IWorkflowBookmarkScheduler foreach (var bookmark in delayBookmarks) { - var job = new ResumeWorkflowJob(workflowInstanceId, bookmark.ToBookmark()); - await _jobScheduler.UnscheduleAsync(job, cancellationToken); + await _jobScheduler.UnscheduleAsync(bookmark.Id, cancellationToken); } } } \ No newline at end of file diff --git a/src/modules/Elsa.Modules.Scheduling/Services/WorkflowTriggerScheduler.cs b/src/modules/Elsa.Modules.Scheduling/Services/WorkflowTriggerScheduler.cs index fbbfa1e32..7f586d2a6 100644 --- a/src/modules/Elsa.Modules.Scheduling/Services/WorkflowTriggerScheduler.cs +++ b/src/modules/Elsa.Modules.Scheduling/Services/WorkflowTriggerScheduler.cs @@ -36,7 +36,7 @@ public class WorkflowTriggerScheduler : IWorkflowTriggerScheduler // Schedule trigger. var (dateTime, timeSpan) = JsonSerializer.Deserialize(trigger.Data!)!; var groupKeys = new[] { RootGroupKey, trigger.WorkflowDefinitionId }; - await _jobScheduler.ScheduleAsync(new RunWorkflowJob(trigger.WorkflowDefinitionId), new RecurringSchedule(dateTime, timeSpan), groupKeys, cancellationToken); + await _jobScheduler.ScheduleAsync(new RunWorkflowJob(trigger.WorkflowDefinitionId), trigger.WorkflowDefinitionId, new RecurringSchedule(dateTime, timeSpan), groupKeys, cancellationToken); } } diff --git a/src/modules/Elsa.Modules.Scheduling/Triggers/Timer.cs b/src/modules/Elsa.Modules.Scheduling/Triggers/Timer.cs index bed3720a3..06f3c1a5f 100644 --- a/src/modules/Elsa.Modules.Scheduling/Triggers/Timer.cs +++ b/src/modules/Elsa.Modules.Scheduling/Triggers/Timer.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Text.Json.Serialization; using Elsa.Attributes; using Elsa.Contracts; using Elsa.Models; @@ -11,6 +12,20 @@ namespace Elsa.Modules.Scheduling.Triggers; /// public class Timer : EventGenerator { + [JsonConstructor] + public Timer() + { + } + + public Timer(TimeSpan interval) : this(new Input(interval)) + { + } + + public Timer(Input interval) + { + Interval = interval; + } + [Input] public Input Interval { get; set; } = default!; protected override IEnumerable GetTriggerData(TriggerIndexingContext context) @@ -20,6 +35,9 @@ public class Timer : EventGenerator var executeAt = clock.UtcNow.Add(interval); yield return new TimerPayload(executeAt, interval); } + + public static Timer FromTimeSpan(TimeSpan value) => new(value); + public static Timer FromSeconds(double value) => FromTimeSpan(TimeSpan.FromSeconds(value)); } public record TimerPayload(DateTimeOffset StartAt, TimeSpan Interval); \ No newline at end of file diff --git a/src/runtime/Elsa.Runtime/Middleware/PersistWorkflowExecutionLogMiddleware.cs b/src/runtime/Elsa.Runtime/Middleware/PersistWorkflowExecutionLogMiddleware.cs index a2bc34424..a643a581c 100644 --- a/src/runtime/Elsa.Runtime/Middleware/PersistWorkflowExecutionLogMiddleware.cs +++ b/src/runtime/Elsa.Runtime/Middleware/PersistWorkflowExecutionLogMiddleware.cs @@ -31,8 +31,8 @@ public class PersistWorkflowExecutionLogMiddleware : WorkflowExecutionMiddleware var entries = context.ExecutionLog.Select(x => new WorkflowExecutionLogRecord { Id = _identityGenerator.GenerateId(), - ActivityId = x.NodeId, - ActivityType = x.NodeType, + ActivityId = x.ActivityId, + ActivityType = x.ActivityType, Message = x.Message, EventName = x.EventName, WorkflowInstanceId = context.Id, diff --git a/src/samples/aspnet/Elsa.Samples.Web1/Program.cs b/src/samples/aspnet/Elsa.Samples.Web1/Program.cs index 1601e0489..26e62fa73 100644 --- a/src/samples/aspnet/Elsa.Samples.Web1/Program.cs +++ b/src/samples/aspnet/Elsa.Samples.Web1/Program.cs @@ -45,7 +45,7 @@ services .AddProtoActorWorkflowHost() .IndexWorkflowTriggers() .AddElsaManagement() - .AddJobs(new QuartzJobSchedulerProvider(), new HangfireJobQueueProvider()) + .AddJobServices(new QuartzJobSchedulerProvider(), new HangfireJobQueueProvider()) .AddHttpActivityServices() .AddJobServices() .AddAzureServiceBusServices(options => configuration.GetSection("AzureServiceBus").Bind(options)) @@ -53,6 +53,7 @@ services { // Register workflows. options.Workflows.Add(nameof(HelloWorldWorkflow), new HelloWorldWorkflow()); + options.Workflows.Add(nameof(HeartbeatWorkflow), new HeartbeatWorkflow()); options.Workflows.Add(nameof(HttpWorkflow), new HttpWorkflow()); options.Workflows.Add(nameof(ForkedHttpWorkflow), new ForkedHttpWorkflow()); options.Workflows.Add(nameof(CompositeActivitiesWorkflow), new CompositeActivitiesWorkflow()); diff --git a/src/samples/aspnet/Elsa.Samples.Web1/Workflows/HeartbeatWorkflow.cs b/src/samples/aspnet/Elsa.Samples.Web1/Workflows/HeartbeatWorkflow.cs new file mode 100644 index 000000000..255b768cc --- /dev/null +++ b/src/samples/aspnet/Elsa.Samples.Web1/Workflows/HeartbeatWorkflow.cs @@ -0,0 +1,26 @@ +using System; +using Elsa.Activities.Console; +using Elsa.Activities.Workflows; +using Elsa.Contracts; +using Elsa.Modules.Scheduling.Triggers; +using Elsa.Runtime.Contracts; + +namespace Elsa.Samples.Web1.Workflows; + +public class HeartbeatWorkflow : IWorkflow +{ + public void Build(IWorkflowDefinitionBuilder workflow) + { + workflow.WithRoot(new Sequence + { + Activities = + { + new Timer(TimeSpan.FromSeconds(10)) + { + CanStartWorkflow = true + }, + new WriteLine(context => $"Heartbeat at {context.GetRequiredService().UtcNow}") + } + }); + } +} \ No newline at end of file