diff --git a/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ActivityDescriptor.cs b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ActivityDescriptor.cs index 8ba4079c82..4f6b68a1de 100644 --- a/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ActivityDescriptor.cs +++ b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ActivityDescriptor.cs @@ -82,6 +82,11 @@ public record ActivityDescriptor /// public bool IsBrowsable { get; set; } + /// + /// Whether this activity type is a start activity. + /// + public bool IsStart { get; set; } + /// /// Whether this activity type is a terminal activity. /// diff --git a/src/modules/Elsa.Workflows.Core/Activities/Start.cs b/src/modules/Elsa.Workflows.Core/Activities/Start.cs index 5dcfcbefad..f8f001d611 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Start.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Start.cs @@ -1,5 +1,6 @@ using System.Runtime.CompilerServices; using Elsa.Workflows.Attributes; +using Elsa.Workflows.Contracts; using JetBrains.Annotations; namespace Elsa.Workflows.Activities; @@ -9,7 +10,7 @@ namespace Elsa.Workflows.Activities; /// [Activity("Elsa", "Flow", "A milestone activity that marks the start of a flowchart.", Kind = ActivityKind.Action)] [PublicAPI] -public class Start : CodeActivity +public class Start : CodeActivity, IStartNode { /// public Start([CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : base(source, line) diff --git a/src/modules/Elsa.Workflows.Core/Contracts/IStartNode.cs b/src/modules/Elsa.Workflows.Core/Contracts/IStartNode.cs new file mode 100644 index 0000000000..1f0311c41b --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Contracts/IStartNode.cs @@ -0,0 +1,8 @@ +namespace Elsa.Workflows.Contracts; + +/// +/// Marks an activity as a terminal activity. +/// +public interface IStartNode +{ +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Models/ActivityDescriptor.cs b/src/modules/Elsa.Workflows.Core/Models/ActivityDescriptor.cs index a14e589ff1..cd09df6bd1 100644 --- a/src/modules/Elsa.Workflows.Core/Models/ActivityDescriptor.cs +++ b/src/modules/Elsa.Workflows.Core/Models/ActivityDescriptor.cs @@ -97,6 +97,11 @@ public class ActivityDescriptor /// public bool IsBrowsable { get; set; } = true; + /// + /// Whether this activity type is a start activity. + /// + public bool IsStart { get; set; } + /// /// Whether this activity type is a terminal activity. /// diff --git a/src/modules/Elsa.Workflows.Core/Services/ActivityDescriber.cs b/src/modules/Elsa.Workflows.Core/Services/ActivityDescriber.cs index 805fdd4cc4..365f4c5c86 100644 --- a/src/modules/Elsa.Workflows.Core/Services/ActivityDescriber.cs +++ b/src/modules/Elsa.Workflows.Core/Services/ActivityDescriber.cs @@ -74,6 +74,7 @@ where typeof(IActivity).IsAssignableFrom(prop.PropertyType) var isTrigger = activityType.IsAssignableTo(typeof(ITrigger)); var browsableAttr = activityType.GetCustomAttribute(); var isTerminal = activityType.FindInterfaces((type, criteria) => type == typeof(ITerminalNode), null).Any(); + var isStart = activityType.FindInterfaces((type, criteria) => type == typeof(IStartNode), null).Any(); var attributes = activityType.GetCustomAttributes(true).Cast().ToList(); var outputAttribute = attributes.OfType().FirstOrDefault(); @@ -92,6 +93,7 @@ where typeof(IActivity).IsAssignableFrom(prop.PropertyType) Outputs = (await DescribeOutputPropertiesAsync(outputProperties, cancellationToken)).ToList(), IsContainer = typeof(IContainer).IsAssignableFrom(activityType), IsBrowsable = browsableAttr == null || browsableAttr.Browsable, + IsStart = isStart, IsTerminal = isTerminal, Attributes = attributes, Constructor = context =>