diff --git a/src/core/Elsa.Core/Activities/ControlFlow/Finish/Finish.cs b/src/core/Elsa.Core/Activities/ControlFlow/Finish/Finish.cs index 4b35606d6..88eed513c 100644 --- a/src/core/Elsa.Core/Activities/ControlFlow/Finish/Finish.cs +++ b/src/core/Elsa.Core/Activities/ControlFlow/Finish/Finish.cs @@ -3,6 +3,8 @@ using System.Linq; using System.Threading.Tasks; using Elsa.ActivityResults; using Elsa.Attributes; +using Elsa.Design; +using Elsa.Expressions; using Elsa.Models; using Elsa.Services; using Elsa.Services.Models; @@ -17,25 +19,30 @@ namespace Elsa.Activities.ControlFlow )] public class Finish : Activity { - [ActivityProperty(Hint = "The value to set as the workflow's output")] + [ActivityProperty(Hint = "The value to set as the workflow's output", SupportedSyntaxes = new[] { SyntaxNames.Literal, SyntaxNames.JavaScript, SyntaxNames.Liquid })] public object? OutputValue { get; set; } - [ActivityProperty(Hint = "The outcomes to set on the container activity")] + [ActivityProperty( + Hint = "The outcomes to set on the container activity", + UIHint = ActivityPropertyUIHints.MultiText, + DefaultValue = Elsa.OutcomeNames.Done, + DefaultSyntax = SyntaxNames.Json, + SupportedSyntaxes = new[] { SyntaxNames.Json, SyntaxNames.JavaScript, SyntaxNames.Liquid })] public IEnumerable OutcomeNames { get; set; } = new[] { Elsa.OutcomeNames.Done }; protected override async ValueTask OnExecuteAsync(ActivityExecutionContext context) { var parentBlueprint = context.ActivityBlueprint.Parent; - + // Remove any blocking activities within the scope of the composite activity. var blockingActivities = context.WorkflowExecutionContext.WorkflowInstance.BlockingActivities; var blockingActivityIds = blockingActivities.Select(x => x.ActivityId).ToList(); var containedBlockingActivityIds = parentBlueprint == null ? blockingActivityIds : parentBlueprint.Activities.Where(x => blockingActivityIds.Contains(x.Id)).Select(x => x.Id).ToList(); var containedBlockingActivities = blockingActivities.Where(x => containedBlockingActivityIds.Contains(x.ActivityId)); - - foreach (var blockingActivity in containedBlockingActivities) + + foreach (var blockingActivity in containedBlockingActivities) await context.WorkflowExecutionContext.RemoveBlockingActivityAsync(blockingActivity); - + // Evict & remove any scope activities within the scope of the composite activity. var scopes = context.WorkflowInstance.Scopes.Select(x => x).Reverse().ToList(); var scopeIds = scopes.Select(x => x.ActivityId).ToList(); @@ -47,9 +54,9 @@ namespace Elsa.Activities.ControlFlow await context.WorkflowExecutionContext.EvictScopeAsync(scopeActivity); scopes.RemoveAll(x => x.ActivityId == scopeId); } - + context.WorkflowInstance.Scopes = new SimpleStack(scopes.AsEnumerable().Reverse()); - + // Return output. var output = new FinishOutput(OutputValue, OutcomeNames); diff --git a/src/core/Elsa.Core/Activities/ControlFlow/For/For.cs b/src/core/Elsa.Core/Activities/ControlFlow/For/For.cs index 0d20f3d8f..1841cabba 100644 --- a/src/core/Elsa.Core/Activities/ControlFlow/For/For.cs +++ b/src/core/Elsa.Core/Activities/ControlFlow/For/For.cs @@ -1,6 +1,7 @@ using System; using Elsa.ActivityResults; using Elsa.Attributes; +using Elsa.Expressions; using Elsa.Services; using Elsa.Services.Models; @@ -14,16 +15,16 @@ namespace Elsa.Activities.ControlFlow )] public class For : Activity { - [ActivityProperty(Hint = "The starting number.")] + [ActivityProperty(Hint = "The starting number.", SupportedSyntaxes = new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid })] public long Start { get; set; } - [ActivityProperty(Hint = "The ending number.")] + [ActivityProperty(Hint = "The ending number.", SupportedSyntaxes = new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid })] public long End { get; set; } - [ActivityProperty(Hint = "An expression that evaluates to the incrementing number on each step.")] + [ActivityProperty(Hint = "An expression that evaluates to the incrementing number on each step.", SupportedSyntaxes = new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid })] public long Step { get; set; } = 1; - [ActivityProperty(Hint = "The operator to use when comparing the current value against the end value.")] + [ActivityProperty(Hint = "The operator to use when comparing the current value against the end value.", SupportedSyntaxes = new[] { SyntaxNames.Literal, SyntaxNames.JavaScript, SyntaxNames.Liquid })] public Operator Operator { get; set; } = Operator.LessThan; internal long? CurrentValue @@ -46,9 +47,9 @@ namespace Elsa.Activities.ControlFlow Break = false; return Done(); } - + var currentValue = CurrentValue ?? Start; - + var loop = Operator switch { Operator.LessThan => currentValue < End, @@ -62,7 +63,7 @@ namespace Elsa.Activities.ControlFlow { CurrentValue = currentValue + Step; var scope = context.CreateScope(); - + scope.Variables.Set(nameof(CurrentValue), currentValue); return Outcome(OutcomeNames.Iterate, currentValue); } diff --git a/src/core/Elsa.Core/Activities/ControlFlow/ForEach/ForEach.cs b/src/core/Elsa.Core/Activities/ControlFlow/ForEach/ForEach.cs index c4fe247ad..5d4e43863 100644 --- a/src/core/Elsa.Core/Activities/ControlFlow/ForEach/ForEach.cs +++ b/src/core/Elsa.Core/Activities/ControlFlow/ForEach/ForEach.cs @@ -3,6 +3,8 @@ using System.Collections.ObjectModel; using System.Linq; using Elsa.ActivityResults; using Elsa.Attributes; +using Elsa.Design; +using Elsa.Expressions; using Elsa.Services; using Elsa.Services.Models; @@ -16,21 +18,26 @@ namespace Elsa.Activities.ControlFlow )] public class ForEach : Activity { - [ActivityProperty(Hint = "A collection of items to iterate over.")] + [ActivityProperty( + Hint = "A collection of items to iterate over.", + UIHint = ActivityPropertyUIHints.MultiLine, + DefaultSyntax = SyntaxNames.Json, + SupportedSyntaxes = new[] { SyntaxNames.Json, SyntaxNames.JavaScript, SyntaxNames.Liquid } + )] public ICollection Items { get; set; } = new Collection(); - + private int? CurrentIndex { get => GetState(); set => SetState(value); } - + private bool Break { get => GetState(); set => SetState(value); } - + protected override IActivityExecutionResult OnExecute(ActivityExecutionContext context) { if (Break) @@ -39,7 +46,7 @@ namespace Elsa.Activities.ControlFlow Break = false; return Done(); } - + var collection = Items.ToList(); var currentIndex = CurrentIndex ?? 0; @@ -50,7 +57,7 @@ namespace Elsa.Activities.ControlFlow scope.Variables.Set("CurrentIndex", currentIndex); scope.Variables.Set("CurrentValue", currentValue); - + CurrentIndex = currentIndex + 1; return Combine(Outcome(OutcomeNames.Iterate, currentValue)); } diff --git a/src/core/Elsa.Core/Activities/ControlFlow/Fork/Fork.cs b/src/core/Elsa.Core/Activities/ControlFlow/Fork/Fork.cs index 54554a64d..0b066f785 100644 --- a/src/core/Elsa.Core/Activities/ControlFlow/Fork/Fork.cs +++ b/src/core/Elsa.Core/Activities/ControlFlow/Fork/Fork.cs @@ -6,6 +6,7 @@ using Elsa.ActivityResults; using Elsa.Attributes; using Elsa.Design; using Elsa.Events; +using Elsa.Expressions; using Elsa.Models; using Elsa.Services; using Elsa.Services.Models; @@ -19,8 +20,11 @@ namespace Elsa.Activities.ControlFlow public class Fork : Activity { [ActivityProperty( + Hint = "Enter one or more branch names.", UIHint = ActivityPropertyUIHints.MultiText, - Hint = "Enter one or more branch names.")] + DefaultSyntax = SyntaxNames.Json, + SupportedSyntaxes = new[] { SyntaxNames.Json } + )] public ISet Branches { get; set; } = new HashSet(); protected override IActivityExecutionResult OnExecute(ActivityExecutionContext context) => Outcomes(Branches); diff --git a/src/core/Elsa.Core/Activities/ControlFlow/If/If.cs b/src/core/Elsa.Core/Activities/ControlFlow/If/If.cs index 795e80725..aebc6a07c 100644 --- a/src/core/Elsa.Core/Activities/ControlFlow/If/If.cs +++ b/src/core/Elsa.Core/Activities/ControlFlow/If/If.cs @@ -4,6 +4,7 @@ using Elsa.ActivityResults; using Elsa.Attributes; using Elsa.Design; using Elsa.Events; +using Elsa.Expressions; using Elsa.Services; using Elsa.Services.Models; using MediatR; @@ -23,7 +24,7 @@ namespace Elsa.Activities.ControlFlow public const string True = "True"; public const string False = "False"; - [ActivityProperty(Hint = "The condition to evaluate.", UIHint = ActivityPropertyUIHints.SingleLine)] + [ActivityProperty(Hint = "The condition to evaluate.", UIHint = ActivityPropertyUIHints.SingleLine, SupportedSyntaxes = new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid })] public bool Condition { get; set; } public bool EnteredScope @@ -54,12 +55,12 @@ namespace Elsa.Activities.ControlFlow public Task Handle(ScopeEvicted notification, CancellationToken cancellationToken) { - if (notification.EvictedScope.Type != nameof(If)) + if (notification.EvictedScope.Type != nameof(If)) return Task.CompletedTask; - + var data = notification.WorkflowExecutionContext.WorkflowInstance.ActivityData.GetItem(notification.EvictedScope.Id, () => new JObject()); data.SetState(nameof(EnteredScope), false); - + return Task.CompletedTask; } } diff --git a/src/core/Elsa.Core/Activities/ControlFlow/Join/Join.cs b/src/core/Elsa.Core/Activities/ControlFlow/Join/Join.cs index ce81a78d3..1c5271f38 100644 --- a/src/core/Elsa.Core/Activities/ControlFlow/Join/Join.cs +++ b/src/core/Elsa.Core/Activities/ControlFlow/Join/Join.cs @@ -6,6 +6,7 @@ using Elsa.ActivityResults; using Elsa.Attributes; using Elsa.Design; using Elsa.Events; +using Elsa.Expressions; using Elsa.Models; using Elsa.Services; using Elsa.Services.Models; @@ -39,7 +40,8 @@ namespace Elsa.Activities.ControlFlow [ActivityProperty( UIHint = ActivityPropertyUIHints.Dropdown, Hint = "WaitAll: wait for all incoming activities to have executed. WaitAny: continue execution as soon as any of the incoming activity has executed.", - Options = new[] { "WaitAll", "WaitAny" } + Options = new[] { "WaitAll", "WaitAny" }, + SupportedSyntaxes = new[] { SyntaxNames.Literal, SyntaxNames.JavaScript, SyntaxNames.Liquid } )] public JoinMode Mode { get; set; } diff --git a/src/core/Elsa.Core/Activities/ControlFlow/ParallelForEach/ParallelForEach.cs b/src/core/Elsa.Core/Activities/ControlFlow/ParallelForEach/ParallelForEach.cs index 1efd12b51..78ffcb257 100644 --- a/src/core/Elsa.Core/Activities/ControlFlow/ParallelForEach/ParallelForEach.cs +++ b/src/core/Elsa.Core/Activities/ControlFlow/ParallelForEach/ParallelForEach.cs @@ -3,6 +3,8 @@ using System.Collections.ObjectModel; using System.Linq; using Elsa.ActivityResults; using Elsa.Attributes; +using Elsa.Design; +using Elsa.Expressions; using Elsa.Services; using Elsa.Services.Models; @@ -16,7 +18,12 @@ namespace Elsa.Activities.ControlFlow )] public class ParallelForEach : Activity { - [ActivityProperty(Hint = "A collection of items to iterate over.")] + [ActivityProperty( + Hint = "A collection of items to iterate over.", + UIHint = ActivityPropertyUIHints.MultiLine, + DefaultSyntax = SyntaxNames.Json, + SupportedSyntaxes = new[] { SyntaxNames.Json, SyntaxNames.JavaScript, SyntaxNames.Liquid } + )] public ICollection Items { get; set; } = new Collection(); protected override IActivityExecutionResult OnExecute(ActivityExecutionContext context) diff --git a/src/core/Elsa.Core/Activities/ControlFlow/Switch/Switch.cs b/src/core/Elsa.Core/Activities/ControlFlow/Switch/Switch.cs index bbdc4239d..795884c22 100644 --- a/src/core/Elsa.Core/Activities/ControlFlow/Switch/Switch.cs +++ b/src/core/Elsa.Core/Activities/ControlFlow/Switch/Switch.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Elsa.ActivityResults; using Elsa.Attributes; using Elsa.Events; +using Elsa.Expressions; using Elsa.Services; using Elsa.Services.Models; using MediatR; @@ -24,9 +25,13 @@ namespace Elsa.Activities.ControlFlow [ActivityProperty(Hint = "The conditions to evaluate.")] public ICollection Cases { get; set; } = new List(); - [ActivityProperty(Hint = "The conditions to evaluate.")] + [ActivityProperty( + Hint = "The switch mode determines whether the first match should be scheduled, or all matches.", + DefaultValue = SwitchMode.MatchFirst, + SupportedSyntaxes = new[] { SyntaxNames.Literal, SyntaxNames.JavaScript, SyntaxNames.Liquid } + )] public SwitchMode Mode { get; set; } = SwitchMode.MatchFirst; - + public bool EnteredScope { get => GetState(); @@ -48,23 +53,23 @@ namespace Elsa.Activities.ControlFlow return Done(); } } - + var matches = Cases.Where(x => x.Condition).Select(x => x.Name).ToList(); var results = Mode == SwitchMode.MatchFirst ? matches.Any() ? new[] { matches.First() } : new string[0] : matches.ToArray(); var outcomes = results; - + return Outcomes(outcomes); } Task INotificationHandler.Handle(ScopeEvicted notification, CancellationToken cancellationToken) { - if (notification.EvictedScope.Type != nameof(Switch)) + if (notification.EvictedScope.Type != nameof(Switch)) return Task.CompletedTask; - + var data = notification.WorkflowExecutionContext.WorkflowInstance.ActivityData.GetItem(notification.EvictedScope.Id, () => new JObject()); data.SetState(nameof(EnteredScope), false); data.SetState("Unwinding", false); - + return Task.CompletedTask; } } diff --git a/src/core/Elsa.Core/Activities/ControlFlow/While/While.cs b/src/core/Elsa.Core/Activities/ControlFlow/While/While.cs index 128c82ad2..246d8688e 100644 --- a/src/core/Elsa.Core/Activities/ControlFlow/While/While.cs +++ b/src/core/Elsa.Core/Activities/ControlFlow/While/While.cs @@ -1,6 +1,7 @@ using Elsa.ActivityResults; using Elsa.Attributes; using Elsa.Design; +using Elsa.Expressions; using Elsa.Services; using Elsa.Services.Models; @@ -14,9 +15,13 @@ namespace Elsa.Activities.ControlFlow )] public class While : Activity { - [ActivityProperty(Hint = "The condition to evaluate.", UIHint = ActivityPropertyUIHints.SingleLine)] + [ActivityProperty( + Hint = "The condition to evaluate.", + UIHint = ActivityPropertyUIHints.SingleLine, + SupportedSyntaxes = new[] { SyntaxNames.JavaScript, SyntaxNames.Liquid } + )] public bool Condition { get; set; } - + private bool Break { get => GetState(); @@ -30,12 +35,12 @@ namespace Elsa.Activities.ControlFlow Break = false; return Done(); } - + var loop = Condition; - if (!loop) + if (!loop) return Done(); - + context.CreateScope(); return Outcome(OutcomeNames.Iterate); }