diff --git a/src/bundles/Elsa.AllInOne.Web/Program.cs b/src/bundles/Elsa.AllInOne.Web/Program.cs index a8f8ed3b7..abd4083ce 100644 --- a/src/bundles/Elsa.AllInOne.Web/Program.cs +++ b/src/bundles/Elsa.AllInOne.Web/Program.cs @@ -15,6 +15,7 @@ using Elsa.Scheduling.Extensions; using Elsa.Liquid.Extensions; using Elsa.Workflows.Core; using Elsa.Workflows.Core.Activities; +using Elsa.Workflows.Core.Activities.Flowchart.Activities; using Elsa.Workflows.Core.Serialization; using Elsa.Workflows.Core.Services; using Elsa.Workflows.Management.Extensions; diff --git a/src/bundles/Elsa.WorkflowServer.Web/Program.cs b/src/bundles/Elsa.WorkflowServer.Web/Program.cs index 19b7d5f35..a86854c2a 100644 --- a/src/bundles/Elsa.WorkflowServer.Web/Program.cs +++ b/src/bundles/Elsa.WorkflowServer.Web/Program.cs @@ -17,6 +17,7 @@ using Elsa.Scheduling.Extensions; using Elsa.WorkflowContexts.Extensions; using Elsa.Workflows.Api.Extensions; using Elsa.Workflows.Core.Activities; +using Elsa.Workflows.Core.Activities.Flowchart.Activities; using Elsa.Workflows.Core.Pipelines.WorkflowExecution.Components; using Elsa.Workflows.Core.Serialization; using Elsa.Workflows.Core.Services; diff --git a/src/bundles/Elsa/Features/ElsaFeature.cs b/src/bundles/Elsa/Features/ElsaFeature.cs index c6b7a61aa..1061b6127 100644 --- a/src/bundles/Elsa/Features/ElsaFeature.cs +++ b/src/bundles/Elsa/Features/ElsaFeature.cs @@ -11,6 +11,7 @@ namespace Elsa.Features; [DependsOn(typeof(MediatorFeature))] [DependsOn(typeof(WorkflowsFeature))] +[DependsOn(typeof(FlowchartFeature))] [DependsOn(typeof(WorkflowPersistenceFeature))] [DependsOn(typeof(WorkflowRuntimeFeature))] [DependsOn(typeof(WorkflowManagementFeature))] 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 5b856782b..c16e5dcf3 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 @@ -63,7 +63,7 @@ function getPorts(node: ActivityNode, activity: Activity, descriptors: Array x.activityType == activity.typeName); const activityCopy: Activity = {...activity}; const untransposedConnections = transposeHandler.untranspose({activity: activityCopy, activityDescriptor}); 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 95054ae2c..722099d27 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 @@ -175,27 +175,27 @@ export class FlowchartComponent implements ContainerActivityComponent { const graphModel = graph.toJSON(); const activities = graphModel.cells.filter(x => x.shape == 'activity').map(x => x.data as Activity); const connections = graphModel.cells.filter(x => x.shape == 'elsa-edge' && !!x.data).map(x => x.data as Connection); - const remainingConnections: Array = []; // The connections remaining after transposition. - let remainingActivities: Array = [...activities]; // The activities remaining after transposition. - const activityDescriptors = descriptorsStore.activityDescriptors; - const transposeHandlerRegistry = Container.get(TransposeHandlerRegistry); + //const remainingConnections: Array = []; // The connections remaining after transposition. + //let remainingActivities: Array = [...activities]; // The activities remaining after transposition. + //const activityDescriptors = descriptorsStore.activityDescriptors; + //const transposeHandlerRegistry = Container.get(TransposeHandlerRegistry); - // Transpose connections to activity outbound port properties. - 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.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. - remainingActivities = remainingActivities.filter(x => x != target); - } else { - // Keep this connection. - remainingConnections.push(connection); - } - } + // // Transpose connections to activity outbound port properties. + // 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.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. + // remainingActivities = remainingActivities.filter(x => x != target); + // } else { + // // Keep this connection. + // remainingConnections.push(connection); + // } + // } let rootActivities = activities.filter(activity => { const hasInboundConnections = connections.find(c => c.target == activity.id) != null; @@ -206,8 +206,8 @@ export class FlowchartComponent implements ContainerActivityComponent { return { typeName: 'Elsa.Flowchart', - activities: remainingActivities, - connections: remainingConnections, + activities: activities, + connections: connections, id: this.rootId, start: rootActivity?.id, metadata: {}, @@ -220,12 +220,14 @@ export class FlowchartComponent implements ContainerActivityComponent { this.rootId = root.id; const descriptors = descriptorsStore.activityDescriptors; const flowchart = root as Flowchart; - const flowchartGraph = walkActivities(flowchart, descriptorsStore.activityDescriptors); - const flowchartNodes = flattenList(flowchartGraph.children); - const transposeHandlerRegistry = Container.get(TransposeHandlerRegistry); + const activities = flowchart.activities; + const connections = flowchart.connections; + //const flowchartGraph = walkActivities(flowchart, descriptorsStore.activityDescriptors); + //const flowchartNodes = flattenList(flowchartGraph.children); + //const transposeHandlerRegistry = Container.get(TransposeHandlerRegistry); // Clear inbound port for start activity. - const startActivityNode = flowchartNodes.find(x => x.activity.id === flowchart.start); + const startActivityNode = activities.find(x => x.activity.id === flowchart.start); if (startActivityNode?.port) delete startActivityNode.port; @@ -233,8 +235,7 @@ export class FlowchartComponent implements ContainerActivityComponent { let edges: Array = []; // Create an X6 node for each activity. - const nodes: Array = flowchartNodes.map(activityNode => { - const activity = activityNode.activity; + const nodes: Array = activities.map(activity => { const position = activity.metadata.designer?.position || {x: 100, y: 100}; const {x, y} = position; const descriptor = descriptors.find(x => x.activityType == activity.typeName) @@ -242,9 +243,9 @@ export class FlowchartComponent implements ContainerActivityComponent { }); // Create X6 edges for each child activity. - for (const rootNodes of flowchartNodes) { - const childEdges = this.createEdges(rootNodes); - edges = [...edges, ...childEdges]; + for (const connection of connections) { + const edge = this.createEdge(connection); + edges = [...edges, edge]; } // Create X6 edges for each connection in the flowchart. @@ -261,23 +262,6 @@ export class FlowchartComponent implements ContainerActivityComponent { this.graph.unfreeze(); }; - private createEdges = (activityNode: ActivityNode): Array => { - let edges: Array = []; - - for (const childNode of activityNode.children) { - const edge = this.createEdge({ - source: activityNode.activity.id, - sourcePort: childNode.port, - target: childNode.activity.id, - targetPort: 'In' - }); - - edges.push(edge); - } - - return edges; - } - createEdge = (connection: Connection): Edge.Metadata => { return { shape: 'elsa-edge', diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List.cs b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List.cs index 44c90ea35..2704ca0cc 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List.cs @@ -5,6 +5,7 @@ using System.Text.Json.Serialization; using Elsa.AspNetCore; using Elsa.AspNetCore.Attributes; using Elsa.AspNetCore.Models; +using Elsa.Workflows.Core.Models; using Elsa.Workflows.Core.Serialization.Converters; using Elsa.Workflows.Core.Services; using Elsa.Workflows.Management.Models; diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.cs similarity index 91% rename from src/modules/Elsa.Workflows.Core/Activities/Flowchart.cs rename to src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.cs index 704b54eb3..6bb78a13a 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Flowchart.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.cs @@ -1,11 +1,10 @@ +using Elsa.Workflows.Core.Activities.Flowchart.Models; using Elsa.Workflows.Core.Attributes; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Core.Services; using Elsa.Workflows.Core.Signals; -namespace Elsa.Workflows.Core.Activities; - -public record Connection(IActivity Source, IActivity Target, string? SourcePort, string TargetPort); +namespace Elsa.Workflows.Core.Activities.Flowchart.Activities; [Activity("Elsa", "Workflows", "A flowchart is a collection of activities and connections between them.")] public class Flowchart : Container diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Handlers/DefaultTransposeHandler.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Handlers/DefaultTransposeHandler.cs new file mode 100644 index 000000000..39c85d37e --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Handlers/DefaultTransposeHandler.cs @@ -0,0 +1,22 @@ +using Elsa.Workflows.Core.Activities.Flowchart.Models; +using Elsa.Workflows.Core.Activities.Flowchart.Transposition.Services; + +namespace Elsa.Workflows.Core.Activities.Flowchart.Handlers; + +public class DefaultTransposeHandler : ITransposeHandler +{ + public bool Transpose(TransposeContext context) + { + var (connection, sourceDescriptor, _) = context; + var (source, target) = connection; + var matchingTargetPort = sourceDescriptor.OutPorts.FirstOrDefault(x => x.Name == connection.SourcePort); + + if (matchingTargetPort == null) + return false; + + // Assign the target activity directly to the outbound port of the source activity. + source.SetPropertyValue(connection.SourcePort!, target); + + return true; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Implementations/ActivityNodeDescriber.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Implementations/ActivityNodeDescriber.cs new file mode 100644 index 000000000..cba49daf1 --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Implementations/ActivityNodeDescriber.cs @@ -0,0 +1,30 @@ +using System.Reflection; +using Elsa.Workflows.Core.Activities.Flowchart.Models; +using Elsa.Workflows.Core.Activities.Flowchart.Services; +using Elsa.Workflows.Core.Attributes; +using Elsa.Workflows.Core.Helpers; +using Elsa.Workflows.Core.Models; +using Elsa.Workflows.Core.Services; + +namespace Elsa.Workflows.Core.Activities.Flowchart.Implementations; + +public class ActivityNodeDescriber : IActivityNodeDescriber +{ + public ActivityNodeDescriptor DescribeActivity(Type activityType) + { + var fullTypeName = ActivityTypeNameHelper.GenerateTypeName(activityType); + + var outboundPorts = + from prop in activityType.GetProperties(BindingFlags.Public | BindingFlags.Instance) + where typeof(IActivity).IsAssignableFrom(prop.PropertyType) || typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) + let portAttr = prop.GetCustomAttribute() + where portAttr != null + select new Port + { + Name = portAttr.Name ?? prop.Name, + DisplayName = portAttr.DisplayName ?? portAttr.Name ?? prop.Name + }; + + return new ActivityNodeDescriptor(activityType, fullTypeName, outboundPorts.ToList()); + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Implementations/TransposeHandlerRegistry.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Implementations/TransposeHandlerRegistry.cs new file mode 100644 index 000000000..792e00e54 --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Implementations/TransposeHandlerRegistry.cs @@ -0,0 +1,13 @@ +using Elsa.Workflows.Core.Activities.Flowchart.Handlers; +using Elsa.Workflows.Core.Activities.Flowchart.Services; +using Elsa.Workflows.Core.Activities.Flowchart.Transposition.Services; + +namespace Elsa.Workflows.Core.Activities.Flowchart.Implementations; + +public class TransposeHandlerRegistry : ITransposeHandlerRegistry +{ + private readonly IDictionary> _dictionary = new Dictionary>(); + public void Add(string activityType, Func handlerFactory) => _dictionary[activityType] = handlerFactory; + public bool TryGet(string activityType, out Func handler) => _dictionary.TryGetValue(activityType, out handler!); + public ITransposeHandler Create(string activityType) => TryGet(activityType, out var h) ? h() : new DefaultTransposeHandler(); +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Models/ActivityNodeDescriptor.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Models/ActivityNodeDescriptor.cs new file mode 100644 index 000000000..b2734bd26 --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Models/ActivityNodeDescriptor.cs @@ -0,0 +1,5 @@ +using Elsa.Workflows.Core.Models; + +namespace Elsa.Workflows.Core.Activities.Flowchart.Models; + +public record ActivityNodeDescriptor(Type ActivityRuntimeType, string ActivityTypeName, ICollection OutPorts); \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Models/Connection.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Models/Connection.cs new file mode 100644 index 000000000..a3b203776 --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Models/Connection.cs @@ -0,0 +1,12 @@ +using Elsa.Workflows.Core.Services; + +namespace Elsa.Workflows.Core.Activities.Flowchart.Models; + +public record Connection(IActivity Source, IActivity Target, string? SourcePort, string TargetPort) +{ + public void Deconstruct(out IActivity source, out IActivity target) + { + source = Source; + target = Target; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Models/TransposeContext.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Models/TransposeContext.cs new file mode 100644 index 000000000..d029a46db --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Models/TransposeContext.cs @@ -0,0 +1,6 @@ +using Elsa.Workflows.Core.Models; +using Elsa.Workflows.Core.Services; + +namespace Elsa.Workflows.Core.Activities.Flowchart.Models; + +public record TransposeContext(Connection Connection, ActivityNodeDescriptor SourceDescriptor, ActivityNodeDescriptor TargetDescriptor); \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ConnectionJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/ConnectionJsonConverter.cs similarity index 85% rename from src/modules/Elsa.Workflows.Core/Serialization/Converters/ConnectionJsonConverter.cs rename to src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/ConnectionJsonConverter.cs index 92cb1eea8..d51dc12d3 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/ConnectionJsonConverter.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/ConnectionJsonConverter.cs @@ -1,9 +1,9 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Elsa.Workflows.Core.Activities; +using Elsa.Workflows.Core.Activities.Flowchart.Models; using Elsa.Workflows.Core.Services; -namespace Elsa.Workflows.Core.Serialization.Converters; +namespace Elsa.Workflows.Core.Activities.Flowchart.Serialization; public class ConnectionJsonConverter : JsonConverter { @@ -14,7 +14,7 @@ public class ConnectionJsonConverter : JsonConverter _activities = activities; } - public override Connection? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override Connection Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (!JsonDocument.TryParseValue(ref reader, out var doc)) throw new JsonException("Failed to parse JsonDocument"); diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartJsonConverter.cs new file mode 100644 index 000000000..9fa9c4a77 --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartJsonConverter.cs @@ -0,0 +1,93 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Elsa.Workflows.Core.Activities.Flowchart.Models; +using Elsa.Workflows.Core.Activities.Flowchart.Services; +using Elsa.Workflows.Core.Activities.Flowchart.Transposition.Services; +using Elsa.Workflows.Core.Serialization.Converters; +using Elsa.Workflows.Core.Services; + +namespace Elsa.Workflows.Core.Activities.Flowchart.Serialization; + +public class FlowchartJsonConverter : JsonConverter +{ + private readonly IActivityWalker _activityWalker; + private readonly IActivityNodeDescriber _activityNodeDescriber; + + public FlowchartJsonConverter(IActivityWalker activityWalker, IActivityNodeDescriber activityNodeDescriber) + { + _activityWalker = activityWalker; + _activityNodeDescriber = activityNodeDescriber; + } + + public override Activities.Flowchart? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (!JsonDocument.TryParseValue(ref reader, out var doc)) + throw new JsonException("Failed to parse JsonDocument"); + + var connectionsElement = doc.RootElement.GetProperty("connections"); + var metadataElement = doc.RootElement.GetProperty("metadata"); + var activitiesElement = doc.RootElement.GetProperty("activities"); + var id = doc.RootElement.GetProperty("id").GetString()!; + var startId = doc.RootElement.TryGetProperty("start", out var startElement) ? startElement.GetString() : default; + var activities = activitiesElement.Deserialize>(options) ?? new List(); + var activityTypes = activities.Select(x => x.GetType()).Distinct().ToList(); + var activityNodeDescriptors = activityTypes.Select(_activityNodeDescriber.DescribeActivity).ToDictionary(x => x.ActivityRuntimeType); + var metadata = metadataElement.Deserialize>(options) ?? new Dictionary(); + var start = activities.FirstOrDefault(x => x.Id == startId) ?? activities.FirstOrDefault(); + var connectionSerializerOptions = new JsonSerializerOptions(options); + var activityDictionary = activities.ToDictionary(x => x.Id); + connectionSerializerOptions.Converters.Add(new ConnectionJsonConverter(activityDictionary)); + + var connections = connectionsElement.Deserialize>(connectionSerializerOptions) ?? new List(); + var transposedStart = Transpose(start, activityDictionary, connections, activityNodeDescriptors); + + return new Activities.Flowchart + { + Id = id, + Metadata = metadata, + Activities = activities, + Connections = connections, + Start = start, + }; + } + + public override void Write(Utf8JsonWriter writer, Activities.Flowchart value, JsonSerializerOptions options) + { + var activities = value.Activities; + var connectionSerializerOptions = new JsonSerializerOptions(options); + var activityDictionary = activities.ToDictionary(x => x.Id); + connectionSerializerOptions.Converters.Add(new ConnectionJsonConverter(activityDictionary)); + + var model = new + { + value.TypeName, + value.Id, + value.Metadata, + value.ApplicationProperties, + Start = value.Start?.Id, + value.Activities, + value.Connections + }; + + JsonSerializer.Serialize(writer, model, connectionSerializerOptions); + } + + /// + /// Starting from the root, find each outbound connection and transpose each connection by constructing a sub-flow in case the source port is an actual outbound property on the source activity. + /// For example, the activity has a outbound activity property. + /// We follow the outbound connection, take the target activity, and assign it to the Body property. + /// + private IActivity? Transpose(IActivity? start, IDictionary activities, ICollection connections, IDictionary descriptors) + { + if (start == null) + return null; + + var outboundConnections = connections.Where(x => x.Source == start).ToList(); + + + foreach (var connection in outboundConnections) + { + var transposeContext = new TransposeContext(connection,) + } + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartSerializationOptionConfigurator.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartSerializationOptionConfigurator.cs new file mode 100644 index 000000000..62212e185 --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Serialization/FlowchartSerializationOptionConfigurator.cs @@ -0,0 +1,18 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Elsa.Workflows.Core.Serialization.Converters; +using Elsa.Workflows.Core.Services; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Workflows.Core.Activities.Flowchart.Serialization; + +/// +/// Add additional objects. +/// +public class FlowchartSerializationOptionConfigurator : ISerializationOptionsConfigurator +{ + private readonly IServiceProvider _serviceProvider; + public FlowchartSerializationOptionConfigurator(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider; + public void Configure(JsonSerializerOptions options) => options.Converters.Add(Create()); + private T Create() => ActivatorUtilities.CreateInstance(_serviceProvider); +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Services/IActivityNodeDescriber.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Services/IActivityNodeDescriber.cs new file mode 100644 index 000000000..6fdfd0694 --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Services/IActivityNodeDescriber.cs @@ -0,0 +1,8 @@ +using Elsa.Workflows.Core.Activities.Flowchart.Models; + +namespace Elsa.Workflows.Core.Activities.Flowchart.Services; + +public interface IActivityNodeDescriber +{ + ActivityNodeDescriptor DescribeActivity(Type activityType); +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Services/ITransposeHandler.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Services/ITransposeHandler.cs new file mode 100644 index 000000000..51d656a7d --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Services/ITransposeHandler.cs @@ -0,0 +1,9 @@ +using Elsa.Workflows.Core.Activities.Flowchart.Activities; +using Elsa.Workflows.Core.Activities.Flowchart.Models; + +namespace Elsa.Workflows.Core.Activities.Flowchart.Transposition.Services; + +public interface ITransposeHandler +{ + bool Transpose(TransposeContext context); +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Services/ITransposeHandlerRegistry.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Services/ITransposeHandlerRegistry.cs new file mode 100644 index 000000000..d39a5175b --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Services/ITransposeHandlerRegistry.cs @@ -0,0 +1,10 @@ +using Elsa.Workflows.Core.Activities.Flowchart.Transposition.Services; + +namespace Elsa.Workflows.Core.Activities.Flowchart.Services; + +public interface ITransposeHandlerRegistry +{ + void Add(string activityType, Func handlerFactory); + bool TryGet(string activityType, out Func? handler); + ITransposeHandler Create(string activityType); +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/ActivityNodeResolvers/OutboundActivityNodeResolver.cs b/src/modules/Elsa.Workflows.Core/ActivityNodeResolvers/OutboundActivityPortResolver.cs similarity index 71% rename from src/modules/Elsa.Workflows.Core/ActivityNodeResolvers/OutboundActivityNodeResolver.cs rename to src/modules/Elsa.Workflows.Core/ActivityNodeResolvers/OutboundActivityPortResolver.cs index 23dfe97d2..650a0fd77 100644 --- a/src/modules/Elsa.Workflows.Core/ActivityNodeResolvers/OutboundActivityNodeResolver.cs +++ b/src/modules/Elsa.Workflows.Core/ActivityNodeResolvers/OutboundActivityPortResolver.cs @@ -5,7 +5,7 @@ using Elsa.Workflows.Core.Services; namespace Elsa.Workflows.Core.ActivityNodeResolvers; -public class OutboundActivityNodeResolver : IActivityNodeResolver +public class OutboundActivityPortResolver : IActivityPortResolver { public int Priority => -1; public bool GetSupportsActivity(IActivity activity) => activity is Activity; @@ -16,6 +16,18 @@ public class OutboundActivityNodeResolver : IActivityNodeResolver .Select(x => x!) .ToHashSet(); + public IEnumerable GetPorts(Type activityType) + { + var outboundPortProperties = + from prop in activityType.GetProperties(BindingFlags.Public | BindingFlags.Instance) + where typeof(IActivity).IsAssignableFrom(prop.PropertyType) || typeof(IEnumerable).IsAssignableFrom(prop.PropertyType) + let portAttr = prop.GetCustomAttribute() + where portAttr != null + select prop; + + return outboundPortProperties; + } + private static IEnumerable GetSinglePorts(IActivity activity) { var activityType = activity.GetType(); diff --git a/src/modules/Elsa.Workflows.Core/ActivityNodeResolvers/SwitchActivityNodeResolver.cs b/src/modules/Elsa.Workflows.Core/ActivityNodeResolvers/SwitchActivityPortResolver.cs similarity index 76% rename from src/modules/Elsa.Workflows.Core/ActivityNodeResolvers/SwitchActivityNodeResolver.cs rename to src/modules/Elsa.Workflows.Core/ActivityNodeResolvers/SwitchActivityPortResolver.cs index 7dd0cc9c0..4906eafbf 100644 --- a/src/modules/Elsa.Workflows.Core/ActivityNodeResolvers/SwitchActivityNodeResolver.cs +++ b/src/modules/Elsa.Workflows.Core/ActivityNodeResolvers/SwitchActivityPortResolver.cs @@ -1,3 +1,4 @@ +using System.Reflection; using Elsa.Workflows.Core.Activities; using Elsa.Workflows.Core.Services; @@ -6,7 +7,7 @@ namespace Elsa.Workflows.Core.ActivityNodeResolvers; /// /// Returns a list of outbound activities for a given activity's branches. /// -public class SwitchActivityNodeResolver : IActivityNodeResolver +public class SwitchActivityPortResolver : IActivityPortResolver { public int Priority => 0; public bool GetSupportsActivity(IActivity activity) => activity is Switch; @@ -22,4 +23,9 @@ public class SwitchActivityNodeResolver : IActivityNodeResolver if (@switch.Default != null) yield return @switch.Default; } + + public IEnumerable GetPorts(Type activityType) + { + throw new NotImplementedException(); + } } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Extensions/PropertyAccessorExtensions.cs b/src/modules/Elsa.Workflows.Core/Extensions/PropertyAccessorExtensions.cs index a4a9f9413..818a9463f 100644 --- a/src/modules/Elsa.Workflows.Core/Extensions/PropertyAccessorExtensions.cs +++ b/src/modules/Elsa.Workflows.Core/Extensions/PropertyAccessorExtensions.cs @@ -1,10 +1,17 @@ using System.Linq.Expressions; using System.Reflection; +using System.Windows.Markup; namespace Elsa.Workflows.Core { public static class PropertyAccessorExtensions { + public static void SetPropertyValue(this object target, string propertyName, object? value) + { + var property = target.GetType().GetProperty(propertyName)!; + property.SetValue(target, value); + } + public static void SetPropertyValue(this T target, Expression> expression, TProperty value) { var property = expression.GetProperty(); diff --git a/src/modules/Elsa.Workflows.Core/Features/FlowchartFeature.cs b/src/modules/Elsa.Workflows.Core/Features/FlowchartFeature.cs new file mode 100644 index 000000000..b90079579 --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Features/FlowchartFeature.cs @@ -0,0 +1,28 @@ +using Elsa.Features.Abstractions; +using Elsa.Features.Services; +using Elsa.Workflows.Core.Activities.Flowchart.Handlers; +using Elsa.Workflows.Core.Activities.Flowchart.Implementations; +using Elsa.Workflows.Core.Activities.Flowchart.Serialization; +using Elsa.Workflows.Core.Activities.Flowchart.Services; +using Elsa.Workflows.Core.Activities.Flowchart.Transposition.Services; +using Elsa.Workflows.Core.Services; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Workflows.Core.Features; + +public class FlowchartFeature : FeatureBase +{ + public FlowchartFeature(IModule module) : base(module) + { + } + + public override void Apply() + { + Services + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + ; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs b/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs index 9cf2212da..1bebeb764 100644 --- a/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs +++ b/src/modules/Elsa.Workflows.Core/Features/WorkflowsFeature.cs @@ -72,8 +72,8 @@ public class WorkflowsFeature : FeatureBase .AddSingleton() // Built-in activity services. - .AddSingleton() - .AddSingleton() + .AddSingleton() + .AddSingleton() .AddSingleton() // Stream providers. diff --git a/src/modules/Elsa.Workflows.Core/Implementations/ActivityWalker.cs b/src/modules/Elsa.Workflows.Core/Implementations/ActivityWalker.cs index 78241ea8c..71d5c7685 100644 --- a/src/modules/Elsa.Workflows.Core/Implementations/ActivityWalker.cs +++ b/src/modules/Elsa.Workflows.Core/Implementations/ActivityWalker.cs @@ -5,9 +5,9 @@ namespace Elsa.Workflows.Core.Implementations; public class ActivityWalker : IActivityWalker { - private readonly IEnumerable _portResolvers; + private readonly IEnumerable _portResolvers; - public ActivityWalker(IEnumerable portResolvers) + public ActivityWalker(IEnumerable portResolvers) { _portResolvers = portResolvers.OrderByDescending(x => x.Priority).ToList(); } diff --git a/src/modules/Elsa.Workflows.Management/Models/ActivityDescriptor.cs b/src/modules/Elsa.Workflows.Core/Models/ActivityDescriptor.cs similarity index 95% rename from src/modules/Elsa.Workflows.Management/Models/ActivityDescriptor.cs rename to src/modules/Elsa.Workflows.Core/Models/ActivityDescriptor.cs index 01efad156..5185caa6b 100644 --- a/src/modules/Elsa.Workflows.Management/Models/ActivityDescriptor.cs +++ b/src/modules/Elsa.Workflows.Core/Models/ActivityDescriptor.cs @@ -2,7 +2,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using Elsa.Workflows.Core.Services; -namespace Elsa.Workflows.Management.Models; +namespace Elsa.Workflows.Core.Models; public class ActivityDescriptor { diff --git a/src/modules/Elsa.Workflows.Management/Models/ActivityKind.cs b/src/modules/Elsa.Workflows.Core/Models/ActivityKind.cs similarity index 54% rename from src/modules/Elsa.Workflows.Management/Models/ActivityKind.cs rename to src/modules/Elsa.Workflows.Core/Models/ActivityKind.cs index 9315c9b6f..f155ba983 100644 --- a/src/modules/Elsa.Workflows.Management/Models/ActivityKind.cs +++ b/src/modules/Elsa.Workflows.Core/Models/ActivityKind.cs @@ -1,4 +1,4 @@ -namespace Elsa.Workflows.Management.Models; +namespace Elsa.Workflows.Core.Models; public enum ActivityKind { diff --git a/src/modules/Elsa.Workflows.Management/Models/InputDescriptor.cs b/src/modules/Elsa.Workflows.Core/Models/InputDescriptor.cs similarity index 96% rename from src/modules/Elsa.Workflows.Management/Models/InputDescriptor.cs rename to src/modules/Elsa.Workflows.Core/Models/InputDescriptor.cs index 233b8b0a3..375bc8cfd 100644 --- a/src/modules/Elsa.Workflows.Management/Models/InputDescriptor.cs +++ b/src/modules/Elsa.Workflows.Core/Models/InputDescriptor.cs @@ -1,4 +1,4 @@ -namespace Elsa.Workflows.Management.Models; +namespace Elsa.Workflows.Core.Models; public class InputDescriptor : PropertyDescriptor { diff --git a/src/modules/Elsa.Workflows.Management/Models/OutputDescriptor.cs b/src/modules/Elsa.Workflows.Core/Models/OutputDescriptor.cs similarity index 90% rename from src/modules/Elsa.Workflows.Management/Models/OutputDescriptor.cs rename to src/modules/Elsa.Workflows.Core/Models/OutputDescriptor.cs index e7fc2501c..7a30894a9 100644 --- a/src/modules/Elsa.Workflows.Management/Models/OutputDescriptor.cs +++ b/src/modules/Elsa.Workflows.Core/Models/OutputDescriptor.cs @@ -1,4 +1,4 @@ -namespace Elsa.Workflows.Management.Models; +namespace Elsa.Workflows.Core.Models; public class OutputDescriptor : PropertyDescriptor { diff --git a/src/modules/Elsa.Workflows.Management/Models/Port.cs b/src/modules/Elsa.Workflows.Core/Models/Port.cs similarity index 72% rename from src/modules/Elsa.Workflows.Management/Models/Port.cs rename to src/modules/Elsa.Workflows.Core/Models/Port.cs index d06732bf7..ca4625290 100644 --- a/src/modules/Elsa.Workflows.Management/Models/Port.cs +++ b/src/modules/Elsa.Workflows.Core/Models/Port.cs @@ -1,4 +1,4 @@ -namespace Elsa.Workflows.Management.Models; +namespace Elsa.Workflows.Core.Models; public class Port { diff --git a/src/modules/Elsa.Workflows.Management/Models/PropertyDescriptor.cs b/src/modules/Elsa.Workflows.Core/Models/PropertyDescriptor.cs similarity index 87% rename from src/modules/Elsa.Workflows.Management/Models/PropertyDescriptor.cs rename to src/modules/Elsa.Workflows.Core/Models/PropertyDescriptor.cs index 74a6ceb44..af9c48b0d 100644 --- a/src/modules/Elsa.Workflows.Management/Models/PropertyDescriptor.cs +++ b/src/modules/Elsa.Workflows.Core/Models/PropertyDescriptor.cs @@ -1,4 +1,4 @@ -namespace Elsa.Workflows.Management.Models; +namespace Elsa.Workflows.Core.Models; public abstract class PropertyDescriptor { diff --git a/src/modules/Elsa.Workflows.Core/Serialization/Converters/FlowchartJsonConverter.cs b/src/modules/Elsa.Workflows.Core/Serialization/Converters/FlowchartJsonConverter.cs deleted file mode 100644 index 92c2d9962..000000000 --- a/src/modules/Elsa.Workflows.Core/Serialization/Converters/FlowchartJsonConverter.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Text.Json; -using System.Text.Json.Serialization; -using Elsa.Workflows.Core.Activities; -using Elsa.Workflows.Core.Services; - -namespace Elsa.Workflows.Core.Serialization.Converters; - -public class FlowchartJsonConverter : JsonConverter -{ - private readonly IActivityWalker _activityWalker; - - public FlowchartJsonConverter(IActivityWalker activityWalker) - { - _activityWalker = activityWalker; - } - - public override Flowchart? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (!JsonDocument.TryParseValue(ref reader, out var doc)) - throw new JsonException("Failed to parse JsonDocument"); - - var connectionsElement = doc.RootElement.GetProperty("connections"); - var metadataElement = doc.RootElement.GetProperty("metadata"); - var activitiesElement = doc.RootElement.GetProperty("activities"); - var id = doc.RootElement.GetProperty("id").GetString()!; - var startId = doc.RootElement.TryGetProperty("start", out var startElement) ? startElement.GetString() : default; - var rootActivities = activitiesElement.Deserialize>(options) ?? new List(); - var metadata = metadataElement.Deserialize>(options) ?? new Dictionary(); - var start = rootActivities.FirstOrDefault(x => x.Id == startId) ?? rootActivities.FirstOrDefault(); - var connectionSerializerOptions = new JsonSerializerOptions(options); - var activities = WalkActivityTree(rootActivities).ToList(); - var activityDictionary = activities.ToDictionary(x => x.Id); - connectionSerializerOptions.Converters.Add(new ConnectionJsonConverter(activityDictionary)); - - var connections = connectionsElement.Deserialize>(connectionSerializerOptions) ?? new List(); - - return new Flowchart - { - Id = id, - Metadata = metadata, - Activities = rootActivities, - Connections = connections, - Start = start, - }; - } - - public override void Write(Utf8JsonWriter writer, Flowchart value, JsonSerializerOptions options) - { - var activities = value.Activities; - var connectionSerializerOptions = new JsonSerializerOptions(options); - var activityDictionary = activities.ToDictionary(x => x.Id); - connectionSerializerOptions.Converters.Add(new ConnectionJsonConverter(activityDictionary)); - - var model = new - { - value.TypeName, - value.Id, - value.Metadata, - value.ApplicationProperties, - Start = value.Start?.Id, - value.Activities, - value.Connections - }; - - JsonSerializer.Serialize(writer, model, connectionSerializerOptions); - } - - private IEnumerable WalkActivityTree(IEnumerable rootActivities) => rootActivities - .Select(rootActivity => _activityWalker.Walk(rootActivity)) - .SelectMany(node => node.Flatten().Select(x => x.Activity)); -} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Serialization/CustomSerializationOptionConfigurator.cs b/src/modules/Elsa.Workflows.Core/Serialization/CustomSerializationOptionConfigurator.cs index b51fd77f3..7a85696d0 100644 --- a/src/modules/Elsa.Workflows.Core/Serialization/CustomSerializationOptionConfigurator.cs +++ b/src/modules/Elsa.Workflows.Core/Serialization/CustomSerializationOptionConfigurator.cs @@ -21,7 +21,6 @@ public class CustomSerializationOptionConfigurator : ISerializationOptionsConfig public void Configure(JsonSerializerOptions options) { options.Converters.Add(Create()); - options.Converters.Add(Create()); } private T Create() => ActivatorUtilities.CreateInstance(_serviceProvider); diff --git a/src/modules/Elsa.Workflows.Core/Services/IActivityNodeResolver.cs b/src/modules/Elsa.Workflows.Core/Services/IActivityPortResolver.cs similarity index 78% rename from src/modules/Elsa.Workflows.Core/Services/IActivityNodeResolver.cs rename to src/modules/Elsa.Workflows.Core/Services/IActivityPortResolver.cs index b878a597a..4d23dfa69 100644 --- a/src/modules/Elsa.Workflows.Core/Services/IActivityNodeResolver.cs +++ b/src/modules/Elsa.Workflows.Core/Services/IActivityPortResolver.cs @@ -1,12 +1,15 @@ +using System.Reflection; + namespace Elsa.Workflows.Core.Services; /// /// A node resolver inspects a given activity and returns its outbound "ports". A port is an activity that this activity connects to. /// Node resolvers are used to inspect a workflow structure and build a graph of nodes from it for easy node traversal. /// -public interface IActivityNodeResolver +public interface IActivityPortResolver { int Priority { get; } bool GetSupportsActivity(IActivity activity); IEnumerable GetPorts(IActivity activity); + IEnumerable GetPorts(Type activityType); } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Services/IActivityWalker.cs b/src/modules/Elsa.Workflows.Core/Services/IActivityWalker.cs index 122f3372d..49c7a17d5 100644 --- a/src/modules/Elsa.Workflows.Core/Services/IActivityWalker.cs +++ b/src/modules/Elsa.Workflows.Core/Services/IActivityWalker.cs @@ -8,4 +8,5 @@ namespace Elsa.Workflows.Core.Services; public interface IActivityWalker { ActivityNode Walk(IActivity activity); + } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Management/Implementations/ActivityDescriber.cs b/src/modules/Elsa.Workflows.Management/Implementations/ActivityDescriber.cs index b8bd51e0e..f86ab213b 100644 --- a/src/modules/Elsa.Workflows.Management/Implementations/ActivityDescriber.cs +++ b/src/modules/Elsa.Workflows.Management/Implementations/ActivityDescriber.cs @@ -30,7 +30,7 @@ public class ActivityDescriber : IActivityDescriber var activityAttr = activityType.GetCustomAttribute(); var ns = activityAttr?.Namespace ?? ActivityTypeNameHelper.GenerateNamespace(activityType); var typeName = activityAttr?.TypeName ?? activityType.Name; - var fullTypeName = $"{ns}.{typeName}"; + var fullTypeName = ActivityTypeNameHelper.GenerateTypeName(activityType); var displayNameAttr = activityType.GetCustomAttribute(); var displayName = displayNameAttr?.DisplayName ?? activityAttr?.DisplayName ?? typeName.Humanize(LetterCasing.Title); var categoryAttr = activityType.GetCustomAttribute(); diff --git a/src/modules/Elsa.Workflows.Management/Implementations/ActivityFactory.cs b/src/modules/Elsa.Workflows.Management/Implementations/ActivityFactory.cs index 2d6df82e9..303c70df9 100644 --- a/src/modules/Elsa.Workflows.Management/Implementations/ActivityFactory.cs +++ b/src/modules/Elsa.Workflows.Management/Implementations/ActivityFactory.cs @@ -1,4 +1,5 @@ using System.Text.Json; +using Elsa.Workflows.Core.Models; using Elsa.Workflows.Core.Services; using Elsa.Workflows.Management.Models; using Elsa.Workflows.Management.Services; diff --git a/src/modules/Elsa.Workflows.Management/Implementations/ActivityRegistry.cs b/src/modules/Elsa.Workflows.Management/Implementations/ActivityRegistry.cs index d8da842dd..d2809bfe0 100644 --- a/src/modules/Elsa.Workflows.Management/Implementations/ActivityRegistry.cs +++ b/src/modules/Elsa.Workflows.Management/Implementations/ActivityRegistry.cs @@ -1,3 +1,4 @@ +using Elsa.Workflows.Core.Models; using Elsa.Workflows.Management.Models; using Elsa.Workflows.Management.Services; diff --git a/src/modules/Elsa.Workflows.Management/Providers/TypedActivityProvider.cs b/src/modules/Elsa.Workflows.Management/Providers/TypedActivityProvider.cs index fee61e174..bba21552f 100644 --- a/src/modules/Elsa.Workflows.Management/Providers/TypedActivityProvider.cs +++ b/src/modules/Elsa.Workflows.Management/Providers/TypedActivityProvider.cs @@ -1,4 +1,5 @@ using System.Runtime.CompilerServices; +using Elsa.Workflows.Core.Models; using Elsa.Workflows.Management.Models; using Elsa.Workflows.Management.Options; using Elsa.Workflows.Management.Services; @@ -23,8 +24,8 @@ public class TypedActivityProvider : IActivityProvider var descriptors = await DescribeActivityTypesAsync(activityTypes, cancellationToken).ToListAsync(cancellationToken); return descriptors; } - - public async IAsyncEnumerable DescribeActivityTypesAsync(IEnumerable activityTypes, [EnumeratorCancellation] CancellationToken cancellationToken) + + private async IAsyncEnumerable DescribeActivityTypesAsync(IEnumerable activityTypes, [EnumeratorCancellation] CancellationToken cancellationToken) { foreach (var activityType in activityTypes) { diff --git a/src/modules/Elsa.Workflows.Management/Serialization/Converters/ActivityJsonConverter.cs b/src/modules/Elsa.Workflows.Management/Serialization/Converters/ActivityJsonConverter.cs index f1160a37a..d577cd271 100644 --- a/src/modules/Elsa.Workflows.Management/Serialization/Converters/ActivityJsonConverter.cs +++ b/src/modules/Elsa.Workflows.Management/Serialization/Converters/ActivityJsonConverter.cs @@ -1,5 +1,6 @@ using System.Text.Json; using System.Text.Json.Serialization; +using Elsa.Workflows.Core.Models; using Elsa.Workflows.Core.Services; using Elsa.Workflows.Management.Models; using Elsa.Workflows.Management.Services; diff --git a/src/modules/Elsa.Workflows.Management/Services/IActivityDescriber.cs b/src/modules/Elsa.Workflows.Management/Services/IActivityDescriber.cs index c73f92b31..7f90357f1 100644 --- a/src/modules/Elsa.Workflows.Management/Services/IActivityDescriber.cs +++ b/src/modules/Elsa.Workflows.Management/Services/IActivityDescriber.cs @@ -1,3 +1,4 @@ +using Elsa.Workflows.Core.Models; using Elsa.Workflows.Management.Models; namespace Elsa.Workflows.Management.Services; diff --git a/src/modules/Elsa.Workflows.Management/Services/IActivityFactory.cs b/src/modules/Elsa.Workflows.Management/Services/IActivityFactory.cs index 10a9faa8a..99cc08898 100644 --- a/src/modules/Elsa.Workflows.Management/Services/IActivityFactory.cs +++ b/src/modules/Elsa.Workflows.Management/Services/IActivityFactory.cs @@ -1,3 +1,4 @@ +using Elsa.Workflows.Core.Models; using Elsa.Workflows.Core.Services; using Elsa.Workflows.Management.Models; diff --git a/src/modules/Elsa.Workflows.Management/Services/IActivityProvider.cs b/src/modules/Elsa.Workflows.Management/Services/IActivityProvider.cs index 7acb9b84d..f64eb3c22 100644 --- a/src/modules/Elsa.Workflows.Management/Services/IActivityProvider.cs +++ b/src/modules/Elsa.Workflows.Management/Services/IActivityProvider.cs @@ -1,3 +1,4 @@ +using Elsa.Workflows.Core.Models; using Elsa.Workflows.Management.Models; namespace Elsa.Workflows.Management.Services; diff --git a/src/modules/Elsa.Workflows.Management/Services/IActivityRegistry.cs b/src/modules/Elsa.Workflows.Management/Services/IActivityRegistry.cs index 4e67fe20f..d6c87a92d 100644 --- a/src/modules/Elsa.Workflows.Management/Services/IActivityRegistry.cs +++ b/src/modules/Elsa.Workflows.Management/Services/IActivityRegistry.cs @@ -1,3 +1,4 @@ +using Elsa.Workflows.Core.Models; using Elsa.Workflows.Management.Models; namespace Elsa.Workflows.Management.Services; diff --git a/src/samples/aspnet/Elsa.Samples.Web2/Program.cs b/src/samples/aspnet/Elsa.Samples.Web2/Program.cs index 7e98bcbf4..072ad7847 100644 --- a/src/samples/aspnet/Elsa.Samples.Web2/Program.cs +++ b/src/samples/aspnet/Elsa.Samples.Web2/Program.cs @@ -14,6 +14,7 @@ using Elsa.Scheduling.Extensions; using Elsa.Workflows.Api.Extensions; using Elsa.Workflows.Core; using Elsa.Workflows.Core.Activities; +using Elsa.Workflows.Core.Activities.Flowchart.Activities; using Elsa.Workflows.Core.Pipelines.WorkflowExecution.Components; using Elsa.Workflows.Core.Serialization; using Elsa.Workflows.Core.Services; diff --git a/src/samples/aspnet/Elsa.Samples.Web3/Program.cs b/src/samples/aspnet/Elsa.Samples.Web3/Program.cs index 137002cce..1912eeb40 100644 --- a/src/samples/aspnet/Elsa.Samples.Web3/Program.cs +++ b/src/samples/aspnet/Elsa.Samples.Web3/Program.cs @@ -10,6 +10,7 @@ using Elsa.Scheduling.Activities; using Elsa.Scheduling.Extensions; using Elsa.Workflows.Api.Extensions; using Elsa.Workflows.Core.Activities; +using Elsa.Workflows.Core.Activities.Flowchart.Activities; using Elsa.Workflows.Management.Extensions; var builder = WebApplication.CreateBuilder(args); diff --git a/src/samples/console/Elsa.Samples.Console1/Workflows/FlowchartWorkflow.cs b/src/samples/console/Elsa.Samples.Console1/Workflows/FlowchartWorkflow.cs index 6ba315cb0..eb989fb0b 100644 --- a/src/samples/console/Elsa.Samples.Console1/Workflows/FlowchartWorkflow.cs +++ b/src/samples/console/Elsa.Samples.Console1/Workflows/FlowchartWorkflow.cs @@ -1,4 +1,6 @@ using Elsa.Workflows.Core.Activities; +using Elsa.Workflows.Core.Activities.Flowchart.Activities; +using Elsa.Workflows.Core.Activities.Flowchart.Models; using Elsa.Workflows.Core.Models; using Elsa.Workflows.Core.Services;