diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/FlowDecision.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/FlowDecision.cs index b38ef9f9a..f51d6b23b 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/FlowDecision.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/FlowDecision.cs @@ -7,7 +7,7 @@ using Elsa.Workflows.Core.Models; namespace Elsa.Workflows.Core.Activities.Flowchart.Activities; [FlowNode("True", "False")] -[Activity("Elsa", "Flow", "Continues on either the True or False branch, depending on the result of a specified condition")] +[Activity("Elsa", "Flow", "Evaluate a Boolean condition to determine which path to execute next.")] public class FlowDecision : ActivityBase { /// diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/FlowSwitch.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/FlowSwitch.cs new file mode 100644 index 000000000..a67f0a905 --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/FlowSwitch.cs @@ -0,0 +1,79 @@ +using System.Text.Json.Serialization; +using Elsa.Expressions; +using Elsa.Expressions.Models; +using Elsa.Expressions.Services; +using Elsa.Workflows.Core.Activities.Flowchart.Attributes; +using Elsa.Workflows.Core.Attributes; +using Elsa.Workflows.Core.Models; + +namespace Elsa.Workflows.Core.Activities.Flowchart.Activities; + +[FlowNode("Default")] +[Activity("Elsa", "Flow", "Evaluate a set of case conditions and schedule the activity for a matching case.")] +public class FlowSwitch : ActivityBase +{ + [Input(UIHint = "flow-switch-editor")] public ICollection Cases { get; set; } = new List(); + + protected override async ValueTask ExecuteAsync(ActivityExecutionContext context) + { + var matchingCase = await FindMatchingCaseAsync(context.ExpressionExecutionContext); + var outcome = matchingCase?.Label ?? "Default"; + + await context.CompleteActivityAsync(outcome); + } + + private async Task FindMatchingCaseAsync(ExpressionExecutionContext context) + { + var expressionEvaluator = context.GetRequiredService(); + + foreach (var switchCase in Cases) + { + var result = await expressionEvaluator.EvaluateAsync(switchCase.Condition, context); + + if (result == true) + return switchCase; + } + + return null; + } +} + +/// +/// Represents an individual case of the activity. +/// +public class FlowSwitchCase +{ + [JsonConstructor] + public FlowSwitchCase() + { + } + + public FlowSwitchCase(string label, IExpression condition) + { + Label = label; + Condition = condition; + } + + public FlowSwitchCase(string label, DelegateBlockReference condition) : this(label, new DelegateExpression(condition)) + { + } + + public FlowSwitchCase(string label, Func> condition) : this(label, new DelegateBlockReference(condition)) + { + } + + public FlowSwitchCase(string label, Func> condition) : this(label, new DelegateBlockReference(condition)) + { + } + + public FlowSwitchCase(string label, Func condition) : this(label, new DelegateBlockReference(condition)) + { + } + + public FlowSwitchCase(string label, Func condition) : this(label, new DelegateBlockReference(condition)) + { + } + + public string Label { get; set; } = default!; + public IExpression Condition { get; set; } = new LiteralExpression(false); +} \ No newline at end of file