diff --git a/src/modules/Elsa.Workflows.Core/Activities/Composite.cs b/src/modules/Elsa.Workflows.Core/Activities/Composite.cs index 1c6db7127..6c9f047ec 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Composite.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Composite.cs @@ -1,7 +1,9 @@ +using System.ComponentModel; using Elsa.Expressions.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; @@ -15,6 +17,7 @@ public class Composite : ActivityBase /// The activity to schedule when this activity executes. /// [Port] + [Browsable(false)] public IActivity Root { get; set; } = new Sequence(); /// @@ -62,10 +65,16 @@ public class Composite : ActivityBase /// public class Composite : ActivityBase { + public Composite() + { + OnSignalReceived(OnCompleteCompositeSignal); + } + /// /// The activity to schedule when this activity executes. /// [Port] + [Browsable(false)] public IActivity Root { get; protected set; } = new Sequence(); protected override void Execute(ActivityExecutionContext context) @@ -105,4 +114,10 @@ public class Composite : ActivityBase protected static Inline From(Func> activity, MemoryBlockReference? output = default) => new(activity, output); protected static Inline From(Func activity, MemoryBlockReference? output = default) => new(activity, output); protected static Inline From(Func activity, MemoryBlockReference? output = default) => new(activity, output); + + private async ValueTask OnCompleteCompositeSignal(CompleteCompositeSignal signal, SignalContext context) + { + await context.ReceiverActivityExecutionContext.CompleteActivityAsync(signal.Result); + context.StopPropagation(); + } } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Core/Signals/CompleteCompositeSignal.cs b/src/modules/Elsa.Workflows.Core/Signals/CompleteCompositeSignal.cs new file mode 100644 index 000000000..6bc0f6835 --- /dev/null +++ b/src/modules/Elsa.Workflows.Core/Signals/CompleteCompositeSignal.cs @@ -0,0 +1,6 @@ +namespace Elsa.Workflows.Core.Signals; + +/// +/// Sent by child activities to notify their composite root that it should complete. +/// +public record CompleteCompositeSignal(object? Result = default); \ 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 a3773dd9a..cc0945f89 100644 --- a/src/modules/Elsa.Workflows.Management/Implementations/ActivityDescriber.cs +++ b/src/modules/Elsa.Workflows.Management/Implementations/ActivityDescriber.cs @@ -46,7 +46,8 @@ public class ActivityDescriber : IActivityDescriber 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 + let portBrowsableAttr = prop.GetCustomAttribute() + where portAttr != null && (portBrowsableAttr == null || portBrowsableAttr.Browsable) select new Port { Name = portAttr.Name ?? prop.Name, @@ -62,25 +63,6 @@ public class ActivityDescriber : IActivityDescriber DisplayName = x }).ToDictionary(x => x.Name) ?? new Dictionary(); - if (flowNodeAttr != null) - { - var portProperties = activityType.GetProperties().Where(p => typeof(IActivity).IsAssignableFrom(p.PropertyType) && p.GetCustomAttribute() != null).ToList(); - - foreach (var portProperty in portProperties) - { - var portAttr = portProperty.GetCustomAttribute(); - - var port = new Port - { - Mode = PortMode.Port, - Name = portAttr?.Name ?? portProperty.Name, - DisplayName = portAttr?.DisplayName ?? portProperty.Name - }; - - flowPorts[port.Name] = port; - } - } - var allPorts = embeddedPorts.Concat(flowPorts.Values); var properties = activityType.GetProperties(); var inputProperties = properties.Where(x => typeof(Input).IsAssignableFrom(x.PropertyType) || x.GetCustomAttribute() != null).ToList(); diff --git a/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/GetAge.cs b/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/GetAge.cs new file mode 100644 index 000000000..734f40785 --- /dev/null +++ b/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/GetAge.cs @@ -0,0 +1,22 @@ +using Elsa.Workflows.Core; +using Elsa.Workflows.Core.Activities; +using Elsa.Workflows.Core.Activities.Flowchart.Attributes; +using Elsa.Workflows.Core.Activities.Flowchart.Models; +using Elsa.Workflows.Core.Signals; + +namespace Elsa.Samples.TelnyxIntegration; + +[FlowNode("Over 18", "Under 18")] +public class GetAge : Composite +{ + public GetAge() + { + Root = new Inline(async context => + { + var random = new Random(); + var n = random.Next(2); + var outcome = n == 0 ? "Under 18" : "Over 18"; + await context.SendSignalAsync(new CompleteCompositeSignal(new Outcomes(outcome))); + }); + } +} \ No newline at end of file diff --git a/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/Program.cs b/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/Program.cs index bfc6b7344..6c9ed1342 100644 --- a/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/Program.cs +++ b/src/samples/aspnet/Elsa.Samples.TelnyxIntegration/Program.cs @@ -58,6 +58,7 @@ services .AddActivity() .AddActivity() .AddActivity() + .AddActivitiesFrom() ) .Use(identity => {