diff --git a/src/activities/Elsa.Activities.Telnyx/Activities/CallRingGroup.cs b/src/activities/Elsa.Activities.Telnyx/Activities/CallRingGroup.cs new file mode 100644 index 000000000..5282d1027 --- /dev/null +++ b/src/activities/Elsa.Activities.Telnyx/Activities/CallRingGroup.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using Elsa.Activities.ControlFlow; +using Elsa.Attributes; +using Elsa.Builders; +using Elsa.Design; +using Elsa.Metadata; +using Elsa.Services; +using NodaTime; + +namespace Elsa.Activities.Telnyx.Activities +{ + [Action( + Category = Constants.Category, + Description = "Call a ring group.", + Outcomes = new[] { "Connected", "NoResponse" }, + DisplayName = "Call Ring Group" + )] + public class CallRingGroup : CompositeActivity, IActivityPropertyDefaultValueProvider + { + [ActivityProperty(UIHint = ActivityPropertyUIHints.MultiText)] + public IList Extensions + { + get => GetState>(() => new List()); + set => SetState(value); + } + + [ActivityProperty] + public RingGroupStrategy Strategy + { + get => GetState(); + set => SetState(value); + } + + [ActivityProperty(Hint = + "The 'from' number to be used as the caller id presented to the destination ('To' number). The number should be in +E164 format. This attribute will default to the 'From' number of the original call if omitted.")] + public string? From + { + get => GetState(); + set => SetState(value); + } + + [ActivityProperty(Hint = + "The string to be used as the caller id name (SIP From Display Name) presented to the destination ('To' number). The string should have a maximum of 128 characters, containing only letters, numbers, spaces, and -_~!.+ special characters. If omitted, the display name will be the same as the number in the 'From' field.")] + public string? FromDisplayName + { + get => GetState(); + set => SetState(value); + } + + [ActivityProperty(DefaultValueProvider = typeof(CallRingGroup))] + public Duration RingTime + { + get => GetState(() => Duration.FromSeconds(20)); + set => SetState(value); + } + + public override void Build(ICompositeActivityBuilder builder) + { + builder.Switch(cases => + { + cases.Add(RingGroupStrategy.PrioritizedHunt.ToString(), () => Strategy == RingGroupStrategy.PrioritizedHunt, BuildSerialFlow); + cases.Add(RingGroupStrategy.RingAll.ToString(), () => Strategy == RingGroupStrategy.RingAll, BuildRingAllFlow); + }); + } + + private void BuildSerialFlow(IOutcomeBuilder builder) + { + builder + .ForEach(() => Extensions, DialExtension); + } + + private void BuildRingAllFlow(IOutcomeBuilder builder) + { + builder.Then(() => Console.Write("Let's do parallel")); + } + + private void DialExtension(IOutcomeBuilder builder) + { + builder + .Then(a => a.WithExtension(context => context.GetInput())) + .Then(a => a + .WithTo(context => context.GetInput()) + .WithFrom(() => From) + .WithFromDisplayName(() => FromDisplayName) + ) + .Then(); + } + + object IActivityPropertyDefaultValueProvider.GetDefaultValue(PropertyInfo property) => Duration.FromSeconds(20); + } +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Telnyx/Activities/Dial.cs b/src/activities/Elsa.Activities.Telnyx/Activities/Dial.cs new file mode 100644 index 000000000..aef5c35a6 --- /dev/null +++ b/src/activities/Elsa.Activities.Telnyx/Activities/Dial.cs @@ -0,0 +1,216 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Elsa.Activities.Telnyx.Client.Models; +using Elsa.Activities.Telnyx.Client.Services; +using Elsa.Activities.Telnyx.Options; +using Elsa.ActivityResults; +using Elsa.Attributes; +using Elsa.Builders; +using Elsa.Design; +using Elsa.Exceptions; +using Elsa.Services; +using Elsa.Services.Models; +using Refit; + +namespace Elsa.Activities.Telnyx.Activities +{ + [Action( + Category = Constants.Category, + Description = "Dial a number or SIP URI from a given connection.", + Outcomes = new[] { OutcomeNames.Done }, + DisplayName = "Dial" + )] + public class Dial : Activity + { + private readonly ITelnyxClient _telnyxClient; + private readonly TelnyxOptions _telnyxOptions; + + public Dial(ITelnyxClient telnyxClient, TelnyxOptions telnyxOptions) + { + _telnyxClient = telnyxClient; + _telnyxOptions = telnyxOptions; + } + + [ActivityProperty(Label = "Connection ID", Hint = "The ID of the Call Control App (formerly ID of the connection) to be used when dialing the destination.", Category = PropertyCategories.Advanced)] + public string CallControlAppId { get; set; } = default!; + + [ActivityProperty(Label = "To", Hint = "The DID or SIP URI to dial out and bridge to the given call.")] + public string To { get; set; } + + [ActivityProperty(Label = "From", + Hint = "The 'from' number to be used as the caller id presented to the destination ('To' number). The number should be in +E164 format. This attribute will default to the 'From' number of the original call if omitted.")] + public string? From { get; set; } + + [ActivityProperty(Label = "From Display Name", + Hint = + "The string to be used as the caller id name (SIP From Display Name) presented to the destination ('To' number). The string should have a maximum of 128 characters, containing only letters, numbers, spaces, and -_~!.+ special characters. If omitted, the display name will be the same as the number in the 'From' field.")] + public string? FromDisplayName { get; set; } + + [ActivityProperty(Label = "Answering Machine Detection", Hint = "Enables Answering Machine Detection.", UIHint = ActivityPropertyUIHints.Dropdown, + Options = new[] { "disabled", "detect", "detect_beep", "detect_words", "greeting_end" })] + public string? AnsweringMachineDetection { get; set; } + + [ActivityProperty(Label = "Answering Machine Detection Configuration", Hint = "Optional configuration parameters to modify answering machine detection performance.", Category = PropertyCategories.Advanced)] + public AnsweringMachineConfig? AnsweringMachineDetectionConfig { get; set; } + + [ActivityProperty(Label = "Command ID", Hint = "Use this field to avoid duplicate commands. Telnyx will ignore commands with the same Command ID.", Category = PropertyCategories.Advanced)] + public string? CommandId { get; set; } + + [ActivityProperty(Label = "Client State", Hint = "Use this field to add state to every subsequent webhook. It must be a valid Base-64 encoded string.", Category = PropertyCategories.Advanced)] + public string? ClientState { get; set; } + + [ActivityProperty(Label = "Custom Headers", Hint = "Custom headers to be added to the SIP INVITE.", Category = PropertyCategories.Advanced)] + public IList
? CustomHeaders { get; set; } + + [ActivityProperty(Label = "SIP Authentication Username", Hint = "SIP Authentication username used for SIP challenges.", Category = "SIP Authentication")] + public string? SipAuthUsername { get; set; } + + [ActivityProperty(Label = "SIP Authentication Password", Hint = "SIP Authentication password used for SIP challenges.", Category = "SIP Authentication")] + public string? SipAuthPassword { get; set; } + + [ActivityProperty(Label = "Time Limit", Hint = "Sets the maximum duration of a Call Control Leg in seconds.", Category = PropertyCategories.Advanced)] + public int? TimeLimitSecs { get; set; } + + [ActivityProperty(Label = "Timeout", Hint = "The number of seconds that Telnyx will wait for the call to be answered by the destination to which it is being transferred.", Category = PropertyCategories.Advanced)] + public int? TimeoutSecs { get; set; } + + [ActivityProperty(Label = "Webhook URL", Hint = "Use this field to override the URL for which Telnyx will send subsequent webhooks to for this call.", Category = PropertyCategories.Advanced)] + public string? WebhookUrl { get; set; } + + [ActivityProperty(Label = "Webhook URL Method", Hint = "HTTP request type used for Webhook URL", UIHint = ActivityPropertyUIHints.Dropdown, Options = new[] { "GET", "POST" }, Category = PropertyCategories.Advanced)] + public string? WebhookUrlMethod { get; set; } + + protected override async ValueTask OnExecuteAsync(ActivityExecutionContext context) + { + await DialAsync(context); + return Done(); + } + + private async ValueTask DialAsync(ActivityExecutionContext context) + { + var connectionId = CallControlAppId is not null and not "" ? CallControlAppId : _telnyxOptions.CallControlAppId ?? throw new Exception("No Call Control ID specified and no default value configured"); + + var request = new DialRequest( + connectionId, + To, + From, + FromDisplayName, + AnsweringMachineDetection, + AnsweringMachineDetectionConfig, + ClientState, + CommandId, + CustomHeaders, + SipAuthUsername, + SipAuthPassword, + TimeLimitSecs, + TimeoutSecs, + WebhookUrl, + WebhookUrlMethod + ); + + try + { + await _telnyxClient.Calls.DialAsync(request, context.CancellationToken); + } + catch (ApiException e) + { + throw new WorkflowException(e.Content ?? e.Message, e); + } + } + } + + public static class DialExtensions + { + public static ISetupActivity WithCallControlAppId(this ISetupActivity setup, Func> value) => setup.Set(x => x.CallControlAppId, value); + public static ISetupActivity WithCallControlAppId(this ISetupActivity setup, Func value) => setup.Set(x => x.CallControlAppId, value); + public static ISetupActivity WithCallControlAppId(this ISetupActivity setup, Func> value) => setup.Set(x => x.CallControlAppId, value); + public static ISetupActivity WithCallControlAppId(this ISetupActivity setup, Func value) => setup.Set(x => x.CallControlAppId, value); + public static ISetupActivity WithCallControlAppId(this ISetupActivity setup, string? value) => setup.Set(x => x.CallControlAppId, value); + + public static ISetupActivity WithTo(this ISetupActivity setup, Func> value) => setup.Set(x => x.To, value); + public static ISetupActivity WithTo(this ISetupActivity setup, Func value) => setup.Set(x => x.To, value); + public static ISetupActivity WithTo(this ISetupActivity setup, Func> value) => setup.Set(x => x.To, value); + public static ISetupActivity WithTo(this ISetupActivity setup, Func value) => setup.Set(x => x.To, value); + public static ISetupActivity WithTo(this ISetupActivity setup, string? value) => setup.Set(x => x.To, value); + + public static ISetupActivity WithFrom(this ISetupActivity setup, Func> value) => setup.Set(x => x.From, value); + public static ISetupActivity WithFrom(this ISetupActivity setup, Func value) => setup.Set(x => x.From, value); + public static ISetupActivity WithFrom(this ISetupActivity setup, Func> value) => setup.Set(x => x.From, value); + public static ISetupActivity WithFrom(this ISetupActivity setup, Func value) => setup.Set(x => x.From, value); + public static ISetupActivity WithFrom(this ISetupActivity setup, string? value) => setup.Set(x => x.From, value); + + public static ISetupActivity WithFromDisplayName(this ISetupActivity setup, Func> value) => setup.Set(x => x.FromDisplayName, value); + public static ISetupActivity WithFromDisplayName(this ISetupActivity setup, Func value) => setup.Set(x => x.FromDisplayName, value); + public static ISetupActivity WithFromDisplayName(this ISetupActivity setup, Func> value) => setup.Set(x => x.FromDisplayName, value); + public static ISetupActivity WithFromDisplayName(this ISetupActivity setup, Func value) => setup.Set(x => x.FromDisplayName, value); + public static ISetupActivity WithFromDisplayName(this ISetupActivity setup, string? value) => setup.Set(x => x.FromDisplayName, value); + + public static ISetupActivity WithAnsweringMachineDetection(this ISetupActivity setup, Func> value) => setup.Set(x => x.AnsweringMachineDetection, value); + public static ISetupActivity WithAnsweringMachineDetection(this ISetupActivity setup, Func value) => setup.Set(x => x.AnsweringMachineDetection, value); + public static ISetupActivity WithAnsweringMachineDetection(this ISetupActivity setup, Func> value) => setup.Set(x => x.AnsweringMachineDetection, value); + public static ISetupActivity WithAnsweringMachineDetection(this ISetupActivity setup, Func value) => setup.Set(x => x.AnsweringMachineDetection, value); + public static ISetupActivity WithAnsweringMachineDetection(this ISetupActivity setup, string? value) => setup.Set(x => x.AnsweringMachineDetection, value); + + public static ISetupActivity WithAnsweringMachineDetectionConfig(this ISetupActivity setup, Func> value) => setup.Set(x => x.AnsweringMachineDetectionConfig, value); + public static ISetupActivity WithAnsweringMachineDetectionConfig(this ISetupActivity setup, Func value) => setup.Set(x => x.AnsweringMachineDetectionConfig, value); + public static ISetupActivity WithAnsweringMachineDetectionConfig(this ISetupActivity setup, Func> value) => setup.Set(x => x.AnsweringMachineDetectionConfig, value); + public static ISetupActivity WithAnsweringMachineDetectionConfig(this ISetupActivity setup, Func value) => setup.Set(x => x.AnsweringMachineDetectionConfig, value); + public static ISetupActivity WithAnsweringMachineDetectionConfig(this ISetupActivity setup, AnsweringMachineConfig? value) => setup.Set(x => x.AnsweringMachineDetectionConfig, value); + + public static ISetupActivity WithCommandId(this ISetupActivity setup, Func> value) => setup.Set(x => x.CommandId, value); + public static ISetupActivity WithCommandId(this ISetupActivity setup, Func value) => setup.Set(x => x.CommandId, value); + public static ISetupActivity WithCommandId(this ISetupActivity setup, Func> value) => setup.Set(x => x.CommandId, value); + public static ISetupActivity WithCommandId(this ISetupActivity setup, Func value) => setup.Set(x => x.CommandId, value); + public static ISetupActivity WithCommandId(this ISetupActivity setup, string? value) => setup.Set(x => x.CommandId, value); + + public static ISetupActivity WithClientState(this ISetupActivity setup, Func> value) => setup.Set(x => x.ClientState, value); + public static ISetupActivity WithClientState(this ISetupActivity setup, Func value) => setup.Set(x => x.ClientState, value); + public static ISetupActivity WithClientState(this ISetupActivity setup, Func> value) => setup.Set(x => x.ClientState, value); + public static ISetupActivity WithClientState(this ISetupActivity setup, Func value) => setup.Set(x => x.ClientState, value); + public static ISetupActivity WithClientState(this ISetupActivity setup, string? value) => setup.Set(x => x.ClientState, value); + + public static ISetupActivity WithCustomHeaders(this ISetupActivity setup, Func?>> value) => setup.Set(x => x.CustomHeaders, value); + public static ISetupActivity WithCustomHeaders(this ISetupActivity setup, Func?> value) => setup.Set(x => x.CustomHeaders, value); + public static ISetupActivity WithCustomHeaders(this ISetupActivity setup, Func?>> value) => setup.Set(x => x.CustomHeaders, value); + public static ISetupActivity WithCustomHeaders(this ISetupActivity setup, Func?> value) => setup.Set(x => x.CustomHeaders, value); + public static ISetupActivity WithCustomHeaders(this ISetupActivity setup, IList
? value) => setup.Set(x => x.CustomHeaders, value); + + public static ISetupActivity WithSipAuthUsername(this ISetupActivity setup, Func> value) => setup.Set(x => x.SipAuthUsername, value); + public static ISetupActivity WithSipAuthUsername(this ISetupActivity setup, Func value) => setup.Set(x => x.SipAuthUsername, value); + public static ISetupActivity WithSipAuthUsername(this ISetupActivity setup, Func> value) => setup.Set(x => x.SipAuthUsername, value); + public static ISetupActivity WithSipAuthUsername(this ISetupActivity setup, Func value) => setup.Set(x => x.SipAuthUsername, value); + public static ISetupActivity WithSipAuthUsername(this ISetupActivity setup, string? value) => setup.Set(x => x.SipAuthUsername, value); + + public static ISetupActivity WithSipAuthPassword(this ISetupActivity setup, Func> value) => setup.Set(x => x.SipAuthPassword, value); + public static ISetupActivity WithSipAuthPassword(this ISetupActivity setup, Func value) => setup.Set(x => x.SipAuthPassword, value); + public static ISetupActivity WithSipAuthPassword(this ISetupActivity setup, Func> value) => setup.Set(x => x.SipAuthPassword, value); + public static ISetupActivity WithSipAuthPassword(this ISetupActivity setup, Func value) => setup.Set(x => x.SipAuthPassword, value); + public static ISetupActivity WithSipAuthPassword(this ISetupActivity setup, string? value) => setup.Set(x => x.SipAuthPassword, value); + + public static ISetupActivity WithTimeLimitSecs(this ISetupActivity setup, Func> value) => setup.Set(x => x.TimeLimitSecs, value); + public static ISetupActivity WithTimeLimitSecs(this ISetupActivity setup, Func value) => setup.Set(x => x.TimeLimitSecs, value); + public static ISetupActivity WithTimeLimitSecs(this ISetupActivity setup, Func> value) => setup.Set(x => x.TimeLimitSecs, value); + public static ISetupActivity WithTimeLimitSecs(this ISetupActivity setup, Func value) => setup.Set(x => x.TimeLimitSecs, value); + public static ISetupActivity WithTimeLimitSecs(this ISetupActivity setup, int? value) => setup.Set(x => x.TimeLimitSecs, value); + + public static ISetupActivity WithTimeoutSecs(this ISetupActivity setup, Func> value) => setup.Set(x => x.TimeoutSecs, value); + public static ISetupActivity WithTimeoutSecs(this ISetupActivity setup, Func value) => setup.Set(x => x.TimeoutSecs, value); + public static ISetupActivity WithTimeoutSecs(this ISetupActivity setup, Func> value) => setup.Set(x => x.TimeoutSecs, value); + public static ISetupActivity WithTimeoutSecs(this ISetupActivity setup, Func value) => setup.Set(x => x.TimeoutSecs, value); + public static ISetupActivity WithTimeoutSecs(this ISetupActivity setup, int? value) => setup.Set(x => x.TimeoutSecs, value); + + public static ISetupActivity WithWebhookUrl(this ISetupActivity setup, Func> value) => setup.Set(x => x.WebhookUrl, value); + public static ISetupActivity WithWebhookUrl(this ISetupActivity setup, Func value) => setup.Set(x => x.WebhookUrl, value); + public static ISetupActivity WithWebhookUrl(this ISetupActivity setup, Func> value) => setup.Set(x => x.WebhookUrl, value); + public static ISetupActivity WithWebhookUrl(this ISetupActivity setup, Func value) => setup.Set(x => x.WebhookUrl, value); + public static ISetupActivity WithWebhookUrl(this ISetupActivity setup, string? value) => setup.Set(x => x.WebhookUrl, value); + + public static ISetupActivity WithWebhookUrlMethod(this ISetupActivity setup, Func> value) => setup.Set(x => x.WebhookUrlMethod, value); + public static ISetupActivity WithWebhookUrlMethod(this ISetupActivity setup, Func value) => setup.Set(x => x.WebhookUrlMethod, value); + public static ISetupActivity WithWebhookUrlMethod(this ISetupActivity setup, Func> value) => setup.Set(x => x.WebhookUrlMethod, value); + public static ISetupActivity WithWebhookUrlMethod(this ISetupActivity setup, Func value) => setup.Set(x => x.WebhookUrlMethod, value); + public static ISetupActivity WithWebhookUrlMethod(this ISetupActivity setup, string? value) => setup.Set(x => x.WebhookUrlMethod, value); + } +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Telnyx/Activities/ResolveExtension.cs b/src/activities/Elsa.Activities.Telnyx/Activities/ResolveExtension.cs new file mode 100644 index 000000000..e8d92b51c --- /dev/null +++ b/src/activities/Elsa.Activities.Telnyx/Activities/ResolveExtension.cs @@ -0,0 +1,47 @@ +using System; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using Elsa.Activities.Telnyx.Services; +using Elsa.ActivityResults; +using Elsa.Attributes; +using Elsa.Builders; +using Elsa.Services; +using Elsa.Services.Models; + +namespace Elsa.Activities.Telnyx.Activities +{ + [Action( + Category = Constants.Category, + Description = "Resolve an extension number into a real number (DID or SIP url).", + Outcomes = new[] { OutcomeNames.Done, "Resolved", "Unresolved" }, + DisplayName = "Resolve Extension" + )] + public class ResolveExtension : Activity + { + private readonly IExtensionProvider _extensionProvider; + + public ResolveExtension(IExtensionProvider extensionProvider) + { + _extensionProvider = extensionProvider; + } + + [ActivityProperty(Hint = "The extension to resolve. If the extension could not be resolved, it is returned as-is.")] + public string Extension { get; set; } + + protected override async ValueTask OnExecuteAsync(ActivityExecutionContext context) + { + var resolvedNumber = await _extensionProvider.GetAsync(Extension, context.CancellationToken); + var result = resolvedNumber != null ? Outcome("Resolved", resolvedNumber) : Outcome("Unresolved", Extension); + return Combine(result, Done()); + } + } + + public static class ResolveExtensionExtensions + { + public static ISetupActivity WithExtension(this ISetupActivity setup, Func> value) => setup.Set(x => x.Extension, value); + public static ISetupActivity WithExtension(this ISetupActivity setup, Func value) => setup.Set(x => x.Extension, value); + public static ISetupActivity WithExtension(this ISetupActivity setup, Func> value) => setup.Set(x => x.Extension, value); + public static ISetupActivity WithExtension(this ISetupActivity setup, Func value) => setup.Set(x => x.Extension, value); + public static ISetupActivity WithExtension(this ISetupActivity setup, string? value) => setup.Set(x => x.Extension, value); + } +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Telnyx/Client/Models/Requests.cs b/src/activities/Elsa.Activities.Telnyx/Client/Models/Requests.cs index a388aea7a..435ddb54c 100644 --- a/src/activities/Elsa.Activities.Telnyx/Client/Models/Requests.cs +++ b/src/activities/Elsa.Activities.Telnyx/Client/Models/Requests.cs @@ -37,4 +37,22 @@ namespace Elsa.Activities.Telnyx.Client.Models string? WebhookUrl, string? WebhookUrlMethod ); + + public record DialRequest( + string ConnectionId, + string To, + string? From, + string? FromDisplayName, + string? AnsweringMachineDetection, + AnsweringMachineConfig? AnsweringMachineConfig, + string? ClientState, + string? CommandId, + IList
? CustomHeaders, + string? SipAuthUsername, + string? SipAuthPassword, + int? TimeLimitSecs, + int? TimeoutSecs, + string? WebhookUrl, + string? WebhookUrlMethod + ); } \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Telnyx/Client/Services/ICallsApi.cs b/src/activities/Elsa.Activities.Telnyx/Client/Services/ICallsApi.cs index b2ed518f5..6a1ac000c 100644 --- a/src/activities/Elsa.Activities.Telnyx/Client/Services/ICallsApi.cs +++ b/src/activities/Elsa.Activities.Telnyx/Client/Services/ICallsApi.cs @@ -7,6 +7,9 @@ namespace Elsa.Activities.Telnyx.Client.Services { public interface ICallsApi { + [Post("/v2/calls")] + Task DialAsync([Body]DialRequest request, CancellationToken cancellationToken = default); + [Post("/v2/calls/{callControlId}/actions/answer")] Task AnswerCallAsync(string callControlId, [Body]AnswerCallRequest request, CancellationToken cancellationToken = default); diff --git a/src/activities/Elsa.Activities.Telnyx/Extensions/SetupExtensions.cs b/src/activities/Elsa.Activities.Telnyx/Extensions/SetupExtensions.cs index d096ae9a9..b4482c0c9 100644 --- a/src/activities/Elsa.Activities.Telnyx/Extensions/SetupExtensions.cs +++ b/src/activities/Elsa.Activities.Telnyx/Extensions/SetupExtensions.cs @@ -9,6 +9,7 @@ using Elsa.Activities.Telnyx.ActivityTypes; using Elsa.Activities.Telnyx.Bookmarks; using Elsa.Activities.Telnyx.Client.Services; using Elsa.Activities.Telnyx.Options; +using Elsa.Activities.Telnyx.Services; using Elsa.Activities.Telnyx.Webhooks.Consumers; using Elsa.Activities.Telnyx.Webhooks.Events; using Elsa.Activities.Telnyx.Webhooks.Services; @@ -44,7 +45,8 @@ namespace Elsa.Activities.Telnyx.Extensions .AddActivityTypeProvider() .AddBookmarkProvider() .AddNotificationHandlers(typeof(TriggerWorkflows)) - .AddScoped(); + .AddScoped() + .AddScoped(telnyxOptions.ExtensionProviderFactory); // Telnyx API Client. var refitSettings = CreateRefitSettings(); diff --git a/src/activities/Elsa.Activities.Telnyx/Models/Extension.cs b/src/activities/Elsa.Activities.Telnyx/Models/Extension.cs new file mode 100644 index 000000000..8ff3ef092 --- /dev/null +++ b/src/activities/Elsa.Activities.Telnyx/Models/Extension.cs @@ -0,0 +1,22 @@ +using System; + +namespace Elsa.Activities.Telnyx.Models +{ + public record Extension + { + public string Number { get; init; } = default!; + + /// + /// The DID or SIP URL + /// + public string Destination { get; init; } + + /// + /// An URL to a sound wave to play as a voicemail message when the recipient doesn't pick up. + /// + public Uri? VoicemailRecordingUrl { get; set; } + + public string? FirstName { get; init; } + public string? LastName { get; init; } + } +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Telnyx/Models/RingGroupStrategy.cs b/src/activities/Elsa.Activities.Telnyx/Models/RingGroupStrategy.cs new file mode 100644 index 000000000..651e0d441 --- /dev/null +++ b/src/activities/Elsa.Activities.Telnyx/Models/RingGroupStrategy.cs @@ -0,0 +1,8 @@ +namespace Elsa.Activities.Telnyx.Activities +{ + public enum RingGroupStrategy + { + PrioritizedHunt, + RingAll + } +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Telnyx/Options/TelnyxOptions.cs b/src/activities/Elsa.Activities.Telnyx/Options/TelnyxOptions.cs index b575a4451..21f1c87f8 100644 --- a/src/activities/Elsa.Activities.Telnyx/Options/TelnyxOptions.cs +++ b/src/activities/Elsa.Activities.Telnyx/Options/TelnyxOptions.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; +using Elsa.Activities.Telnyx.Services; using Elsa.Activities.Telnyx.Webhooks.Payloads.Call; +using Microsoft.Extensions.DependencyInjection; namespace Elsa.Activities.Telnyx.Options { @@ -12,10 +14,14 @@ namespace Elsa.Activities.Telnyx.Options { typeof(CallInitiatedPayload) }; + + ExtensionProviderFactory = sp => ActivatorUtilities.CreateInstance(sp); } public IList PayloadTypes { get; set; } public Uri ApiUrl { get; set; } = new("https://api.telnyx.com"); public string ApiKey { get; set; } = default!; + public string? CallControlAppId { get; set; } + internal Func ExtensionProviderFactory { get; set; } } } \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Telnyx/Services/IExtensionProvider.cs b/src/activities/Elsa.Activities.Telnyx/Services/IExtensionProvider.cs new file mode 100644 index 000000000..409eb5227 --- /dev/null +++ b/src/activities/Elsa.Activities.Telnyx/Services/IExtensionProvider.cs @@ -0,0 +1,11 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Activities.Telnyx.Models; + +namespace Elsa.Activities.Telnyx.Services +{ + public interface IExtensionProvider + { + Task GetAsync(string extensionNumber, CancellationToken cancellationToken = default); + } +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Telnyx/Services/NullExtensionProvider.cs b/src/activities/Elsa.Activities.Telnyx/Services/NullExtensionProvider.cs new file mode 100644 index 000000000..eee9ff3d5 --- /dev/null +++ b/src/activities/Elsa.Activities.Telnyx/Services/NullExtensionProvider.cs @@ -0,0 +1,11 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Activities.Telnyx.Models; + +namespace Elsa.Activities.Telnyx.Services +{ + public class NullExtensionProvider : IExtensionProvider + { + public Task GetAsync(string extensionNumber, CancellationToken cancellationToken = default) => Task.FromResult(default); + } +} \ No newline at end of file diff --git a/src/core/Elsa.Abstractions/Attributes/ActivityPropertyAttribute.cs b/src/core/Elsa.Abstractions/Attributes/ActivityPropertyAttribute.cs index 53826b637..c2c707837 100644 --- a/src/core/Elsa.Abstractions/Attributes/ActivityPropertyAttribute.cs +++ b/src/core/Elsa.Abstractions/Attributes/ActivityPropertyAttribute.cs @@ -31,7 +31,7 @@ namespace Elsa.Attributes public object? Options { get; set; } /// - /// The name of a static method that provides options. + /// The type that provides options. /// public Type? OptionsProvider { get; set; } @@ -44,5 +44,10 @@ namespace Elsa.Attributes /// The default value to set. /// public object? DefaultValue { get; set; } + + /// + /// The type that provides a default value. + /// + public Type? DefaultValueProvider { get; set; } } } \ No newline at end of file diff --git a/src/core/Elsa.Abstractions/Builders/ICompositeActivityBuilder.cs b/src/core/Elsa.Abstractions/Builders/ICompositeActivityBuilder.cs index 717270d81..f8df71757 100644 --- a/src/core/Elsa.Abstractions/Builders/ICompositeActivityBuilder.cs +++ b/src/core/Elsa.Abstractions/Builders/ICompositeActivityBuilder.cs @@ -33,11 +33,13 @@ namespace Elsa.Builders IActivityBuilder Add( Action>? setup, Action? branch = default, + string? activityType = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity; IActivityBuilder Add( Action? branch = default, + string? activityType = default, IDictionary? propertyValueProviders = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) diff --git a/src/core/Elsa.Abstractions/Builders/ISetupActivity.cs b/src/core/Elsa.Abstractions/Builders/ISetupActivity.cs index 3c780f2b5..3fd687daf 100644 --- a/src/core/Elsa.Abstractions/Builders/ISetupActivity.cs +++ b/src/core/Elsa.Abstractions/Builders/ISetupActivity.cs @@ -17,11 +17,11 @@ namespace Elsa.Builders public static class SetupActivityExtensions { - public static ISetupActivity Set( - this ISetupActivity builder, - Expression> propertyAccessor, - Func> valueFactory) where T : IActivity => - builder.Set(propertyAccessor, async context => await valueFactory(context)); + // public static ISetupActivity Set( + // this ISetupActivity builder, + // Expression> propertyAccessor, + // Func> valueFactory) where T : IActivity => + // builder.Set(propertyAccessor, async context => await valueFactory(context)); public static ISetupActivity Set( this ISetupActivity builder, diff --git a/src/core/Elsa.Abstractions/Metadata/IActivityPropertyDefaultValueProvider.cs b/src/core/Elsa.Abstractions/Metadata/IActivityPropertyDefaultValueProvider.cs new file mode 100644 index 000000000..72acc59f9 --- /dev/null +++ b/src/core/Elsa.Abstractions/Metadata/IActivityPropertyDefaultValueProvider.cs @@ -0,0 +1,9 @@ +using System.Reflection; + +namespace Elsa.Metadata +{ + public interface IActivityPropertyDefaultValueProvider + { + object GetDefaultValue(PropertyInfo property); + } +} \ No newline at end of file diff --git a/src/core/Elsa.Abstractions/Metadata/IActivityPropertyDefaultValueResolver.cs b/src/core/Elsa.Abstractions/Metadata/IActivityPropertyDefaultValueResolver.cs new file mode 100644 index 000000000..7eac53711 --- /dev/null +++ b/src/core/Elsa.Abstractions/Metadata/IActivityPropertyDefaultValueResolver.cs @@ -0,0 +1,9 @@ +using System.Reflection; + +namespace Elsa.Metadata +{ + public interface IActivityPropertyDefaultValueResolver + { + object? GetDefaultValue(PropertyInfo activityPropertyInfo); + } +} \ No newline at end of file diff --git a/src/core/Elsa.Abstractions/Services/CompositeActivity.cs b/src/core/Elsa.Abstractions/Services/CompositeActivity.cs index 026250f32..0083161e8 100644 --- a/src/core/Elsa.Abstractions/Services/CompositeActivity.cs +++ b/src/core/Elsa.Abstractions/Services/CompositeActivity.cs @@ -14,7 +14,7 @@ namespace Elsa.Services { internal const string Enter = "Enter"; - public virtual void Build(ICompositeActivityBuilder activity) + public virtual void Build(ICompositeActivityBuilder builder) { } diff --git a/src/core/Elsa.Core/Activities/Workflows/Workflow/Workflow.cs b/src/core/Elsa.Core/Activities/Workflows/Workflow/Workflow.cs index 85a2d78d0..bcca339c8 100644 --- a/src/core/Elsa.Core/Activities/Workflows/Workflow/Workflow.cs +++ b/src/core/Elsa.Core/Activities/Workflows/Workflow/Workflow.cs @@ -7,7 +7,7 @@ namespace Elsa.Activities.Workflows.Workflow [Browsable(false)] public class Workflow : CompositeActivity { - public override void Build(ICompositeActivityBuilder activity) + public override void Build(ICompositeActivityBuilder builder) { } } diff --git a/src/core/Elsa.Core/Builders/ActivityBuilder.cs b/src/core/Elsa.Core/Builders/ActivityBuilder.cs index 2062505f8..d1fd4dc88 100644 --- a/src/core/Elsa.Core/Builders/ActivityBuilder.cs +++ b/src/core/Elsa.Core/Builders/ActivityBuilder.cs @@ -12,12 +12,14 @@ namespace Elsa.Builders { public ActivityBuilder( Type activityType, + string? activityTypeName, ICompositeActivityBuilder workflowBuilder, IDictionary? propertyValueProviders, int lineNumber, string? sourceFile) { ActivityType = activityType; + ActivityTypeName = activityTypeName ?? activityType.Name; WorkflowBuilder = workflowBuilder; PropertyValueProviders = propertyValueProviders; LineNumber = lineNumber; @@ -29,6 +31,7 @@ namespace Elsa.Builders } public Type ActivityType { get; protected set; } = default!; + public string ActivityTypeName { get; set; } = default!; public ICompositeActivityBuilder WorkflowBuilder { get; set; } = default!; public string ActivityId { get; set; } = default!; public string? Name { get; set; } @@ -45,22 +48,24 @@ namespace Elsa.Builders public IActivityBuilder Add( Action>? setup = default, + string? activityType = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity => - WorkflowBuilder.Add(setup, null, lineNumber, sourceFile); + WorkflowBuilder.Add(setup, null, activityType, lineNumber, sourceFile); public IOutcomeBuilder When(string outcome) => new OutcomeBuilder(WorkflowBuilder, this, outcome); public virtual IActivityBuilder Then( Action>? setup = null, Action? branch = null, + string? activityType = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity => - When(OutcomeNames.Done).Then(setup, branch, lineNumber, sourceFile); + When(OutcomeNames.Done).Then(setup, branch, act, lineNumber, sourceFile); - public virtual IActivityBuilder Then(Action? branch = null, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) + public virtual IActivityBuilder Then(Action? branch = null, string? activityTypeName = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity => When(OutcomeNames.Done).Then(branch, lineNumber, sourceFile); diff --git a/src/core/Elsa.Core/Builders/CompositeActivityBuilder.cs b/src/core/Elsa.Core/Builders/CompositeActivityBuilder.cs index 6b76b0444..ae98d5e00 100644 --- a/src/core/Elsa.Core/Builders/CompositeActivityBuilder.cs +++ b/src/core/Elsa.Core/Builders/CompositeActivityBuilder.cs @@ -38,21 +38,28 @@ namespace Elsa.Builders public IReadOnlyCollection Activities => ActivityBuilders.ToList().AsReadOnly(); - public IActivityBuilder New(Type activityType, IDictionary? propertyValueProviders = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) + public IActivityBuilder New( + Type activityType, + string? activityTypeName = default, + IDictionary? propertyValueProviders = default, + [CallerLineNumber] int lineNumber = default, + [CallerFilePath] string? sourceFile = default) { - var activityBuilder = new ActivityBuilder(activityType, this, propertyValueProviders, lineNumber, sourceFile); + var activityBuilder = new ActivityBuilder(activityType, activityTypeName, this, propertyValueProviders, lineNumber, sourceFile); return activityBuilder; } public IActivityBuilder New( + string? activityTypeName = default, IDictionary? propertyValueProviders = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity => - New(typeof(T), propertyValueProviders, lineNumber, sourceFile); + New(typeof(T), activityTypeName, propertyValueProviders, lineNumber, sourceFile); public IActivityBuilder New( Action>? setup = default, + string? activityTypeName = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity { @@ -61,61 +68,68 @@ namespace Elsa.Builders var valueProviders = propertyValuesBuilder.ValueProviders.ToDictionary( x => x.Key, - x => (IActivityPropertyValueProvider)new DelegateActivityPropertyValueProvider(x.Value)); + x => (IActivityPropertyValueProvider) new DelegateActivityPropertyValueProvider(x.Value)); - return New(valueProviders, lineNumber, sourceFile); + return New(activityTypeName, valueProviders, lineNumber, sourceFile); } public IActivityBuilder StartWith( Action>? setup = default, Action? branch = default, + string? activityTypeName = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity { - var activityBuilder = New(setup, lineNumber, sourceFile); + var activityBuilder = New(setup, activityTypeName, lineNumber, sourceFile); return Add(activityBuilder, branch); } - public IActivityBuilder StartWith(Action? branch = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) + public IActivityBuilder StartWith(Action? branch = default, string? activityTypeName = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity => - Add(branch, null, lineNumber, sourceFile); + Add(branch, activityTypeName, null, lineNumber, sourceFile); public IActivityBuilder Add( Action>? setup = default, Action? branch = default, + string? activityType = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity { - var activityBuilder = New(setup, lineNumber, sourceFile); + var activityBuilder = New(setup, activityType, lineNumber, sourceFile); return Add(activityBuilder, branch); } public IActivityBuilder Add( Action? branch = default, + string? activityType = default, IDictionary? propertyValueProviders = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity { - var activityBuilder = new ActivityBuilder(typeof(T), this, propertyValueProviders, lineNumber, sourceFile); + var activityBuilder = new ActivityBuilder(typeof(T), activityType, this, propertyValueProviders, lineNumber, sourceFile); return Add(activityBuilder, branch); } - public IActivityBuilder Add( - IActivityBuilder activityBuilder, - Action? branch = default) + public IActivityBuilder Add(IActivityBuilder activityBuilder, Action? branch = default) { branch?.Invoke(activityBuilder); ActivityBuilders.Add(activityBuilder); return activityBuilder; } - public override IActivityBuilder Then(Action>? setup = null, Action? branch = null, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) => - StartWith(setup, branch, lineNumber, sourceFile); + public override IActivityBuilder Then( + Action>? setup = null, + Action? branch = null, + string? activityTypeName = default, + [CallerLineNumber] int lineNumber = default, + [CallerFilePath] string? sourceFile = default) => + StartWith(setup, branch, activityTypeName, lineNumber, sourceFile); public override IActivityBuilder Then(IActivityBuilder targetActivity) => Add(targetActivity); - public override IActivityBuilder Then(Action? branch = null, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) => StartWith(branch, lineNumber, sourceFile); + public override IActivityBuilder Then(Action? branch = null, string? activityTypeName = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) + where T : class, IActivity => StartWith(branch, activityTypeName, lineNumber, sourceFile); public IConnectionBuilder Connect( IActivityBuilder source, @@ -184,7 +198,7 @@ namespace Elsa.Builders using var scope = ServiceProvider.CreateScope(); foreach (var activityBuilder in compositeActivityBuilders) { - var compositeActivity = (CompositeActivity)ActivatorUtilities.CreateInstance(scope.ServiceProvider, activityBuilder.ActivityType); + var compositeActivity = (CompositeActivity) ActivatorUtilities.CreateInstance(scope.ServiceProvider, activityBuilder.ActivityType); var compositeActivityBuilder = _compositeActivityBuilderFactory(); compositeActivityBuilder.ActivityId = activityBuilder.ActivityId; compositeActivity.Build(compositeActivityBuilder); diff --git a/src/core/Elsa.Core/Builders/OutcomeBuilder.cs b/src/core/Elsa.Core/Builders/OutcomeBuilder.cs index c420edb3f..557c658b9 100644 --- a/src/core/Elsa.Core/Builders/OutcomeBuilder.cs +++ b/src/core/Elsa.Core/Builders/OutcomeBuilder.cs @@ -23,10 +23,11 @@ namespace Elsa.Builders public IActivityBuilder Then( Action>? setup = default, Action? branch = default, + string? activityType = default, [CallerLineNumber] int lineNumber = default, [CallerFilePath] string? sourceFile = default) where T : class, IActivity { - var activityBuilder = WorkflowBuilder.Add(setup, null, lineNumber, sourceFile); + var activityBuilder = WorkflowBuilder.Add(setup, default, activityType, lineNumber, sourceFile); Then(activityBuilder, branch); return activityBuilder; } diff --git a/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs b/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs index 8be3dfde3..a719d769b 100644 --- a/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs +++ b/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs @@ -138,6 +138,7 @@ namespace Microsoft.Extensions.DependencyInjection services .AddSingleton() .AddSingleton() + .AddSingleton() .AddSingleton(); // Bookmarks. diff --git a/src/core/Elsa.Core/Metadata/ActivityPropertyDefaultValueResolver.cs b/src/core/Elsa.Core/Metadata/ActivityPropertyDefaultValueResolver.cs new file mode 100644 index 000000000..891a8b344 --- /dev/null +++ b/src/core/Elsa.Core/Metadata/ActivityPropertyDefaultValueResolver.cs @@ -0,0 +1,34 @@ +using System; +using System.Reflection; +using Elsa.Attributes; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Metadata +{ + public class ActivityPropertyDefaultValueResolver : IActivityPropertyDefaultValueResolver + { + private readonly IServiceProvider _serviceProvider; + + public ActivityPropertyDefaultValueResolver(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + + public object? GetDefaultValue(PropertyInfo activityPropertyInfo) + { + var activityPropertyAttribute = activityPropertyInfo.GetCustomAttribute(); + + if (activityPropertyAttribute == null) + return null; + + if (activityPropertyAttribute.DefaultValueProvider == null) + return activityPropertyAttribute.DefaultValue; + + var providerType = activityPropertyAttribute.DefaultValueProvider; + + using var scope = _serviceProvider.CreateScope(); + var provider = (IActivityPropertyDefaultValueProvider) ActivatorUtilities.GetServiceOrCreateInstance(scope.ServiceProvider, providerType); + return provider.GetDefaultValue(activityPropertyInfo); + } + } +} \ No newline at end of file diff --git a/src/core/Elsa.Core/Metadata/TypedActivityTypeDescriber.cs b/src/core/Elsa.Core/Metadata/TypedActivityTypeDescriber.cs index c612f00b1..f51f5a5f7 100644 --- a/src/core/Elsa.Core/Metadata/TypedActivityTypeDescriber.cs +++ b/src/core/Elsa.Core/Metadata/TypedActivityTypeDescriber.cs @@ -11,11 +11,13 @@ namespace Elsa.Metadata { private readonly IActivityPropertyOptionsResolver _optionsResolver; private readonly IActivityPropertyUIHintResolver _uiHintResolver; + private readonly IActivityPropertyDefaultValueResolver _defaultValueResolver; - public TypedActivityTypeDescriber(IActivityPropertyOptionsResolver optionsResolver, IActivityPropertyUIHintResolver uiHintResolver) + public TypedActivityTypeDescriber(IActivityPropertyOptionsResolver optionsResolver, IActivityPropertyUIHintResolver uiHintResolver, IActivityPropertyDefaultValueResolver defaultValueResolver) { _optionsResolver = optionsResolver; _uiHintResolver = uiHintResolver; + _defaultValueResolver = defaultValueResolver; } public ActivityDescriptor? Describe(Type activityType) @@ -60,7 +62,7 @@ namespace Elsa.Metadata activityPropertyAttribute.Hint, _optionsResolver.GetOptions(propertyInfo), activityPropertyAttribute.Category, - activityPropertyAttribute.DefaultValue + _defaultValueResolver.GetDefaultValue(propertyInfo) ); } } diff --git a/src/designer/elsa-workflows-studio/src/utils/jsplumb-helper.ts b/src/designer/elsa-workflows-studio/src/utils/jsplumb-helper.ts index 6f2e57a93..9245f519c 100644 --- a/src/designer/elsa-workflows-studio/src/utils/jsplumb-helper.ts +++ b/src/designer/elsa-workflows-studio/src/utils/jsplumb-helper.ts @@ -4,7 +4,6 @@ import {ConnectionModel} from "../models"; let jsPlumbInstance = null; function onConnectionCreated(e, callback) { - debugger; const connection: ConnectionModel = { sourceId: e.connection.getParameter('sourceActivityId'), targetId: e.connection.getParameter('targetActivityId'), diff --git a/src/samples/console/Elsa.Samples.ProgrammaticCompositeActivitiesConsole/Activities/CountdownActivity.cs b/src/samples/console/Elsa.Samples.ProgrammaticCompositeActivitiesConsole/Activities/CountdownActivity.cs index 21f276d1a..bb2b38fda 100644 --- a/src/samples/console/Elsa.Samples.ProgrammaticCompositeActivitiesConsole/Activities/CountdownActivity.cs +++ b/src/samples/console/Elsa.Samples.ProgrammaticCompositeActivitiesConsole/Activities/CountdownActivity.cs @@ -20,9 +20,9 @@ namespace Elsa.Samples.ProgrammaticCompositeActivitiesConsole.Activities set => SetState(value); } - public override void Build(ICompositeActivityBuilder activity) + public override void Build(ICompositeActivityBuilder builder) { - activity + builder .For(() => Start, () => 0, () => -1, iterate => { iterate.WriteLine(context => $"{context.ForScope().CurrentValue}..."); diff --git a/src/samples/console/Elsa.Samples.ProgrammaticCompositeActivitiesConsole/Activities/NavigateActivity.cs b/src/samples/console/Elsa.Samples.ProgrammaticCompositeActivitiesConsole/Activities/NavigateActivity.cs index 4ed46de5a..1b305594d 100644 --- a/src/samples/console/Elsa.Samples.ProgrammaticCompositeActivitiesConsole/Activities/NavigateActivity.cs +++ b/src/samples/console/Elsa.Samples.ProgrammaticCompositeActivitiesConsole/Activities/NavigateActivity.cs @@ -14,9 +14,9 @@ namespace Elsa.Samples.ProgrammaticCompositeActivitiesConsole.Activities [Action(Outcomes = new[] { "Left", "Right" })] public class NavigateActivity : CompositeActivity { - public override void Build(ICompositeActivityBuilder activity) + public override void Build(ICompositeActivityBuilder builder) { - activity + builder .StartWith(GetInstructions) .WriteLine(context => (string)context.Input) .ReadLine() diff --git a/src/samples/worker/Elsa.Samples.Timers.Quartz/Activities/MyContainer1.cs b/src/samples/worker/Elsa.Samples.Timers.Quartz/Activities/MyContainer1.cs index f592cd4f9..f8009f4ef 100644 --- a/src/samples/worker/Elsa.Samples.Timers.Quartz/Activities/MyContainer1.cs +++ b/src/samples/worker/Elsa.Samples.Timers.Quartz/Activities/MyContainer1.cs @@ -9,9 +9,9 @@ namespace Elsa.Samples.Temporal.Activities { public class MyContainer1 : CompositeActivity { - public override void Build(ICompositeActivityBuilder activity) + public override void Build(ICompositeActivityBuilder builder) { - activity + builder .StartWith(fork => fork.WithBranches("A", "B", "C"), fork => { fork diff --git a/src/samples/worker/Elsa.Samples.Timers.Quartz/Activities/MyContainer2.cs b/src/samples/worker/Elsa.Samples.Timers.Quartz/Activities/MyContainer2.cs index 42e33d4f1..dbf69d62b 100644 --- a/src/samples/worker/Elsa.Samples.Timers.Quartz/Activities/MyContainer2.cs +++ b/src/samples/worker/Elsa.Samples.Timers.Quartz/Activities/MyContainer2.cs @@ -9,9 +9,9 @@ namespace Elsa.Samples.Temporal.Activities { public class MyContainer2 : CompositeActivity { - public override void Build(ICompositeActivityBuilder activity) + public override void Build(ICompositeActivityBuilder builder) { - activity + builder .StartWith(fork => fork.WithBranches("D", "E"), fork => { fork diff --git a/src/samples/worker/Elsa.Samples.WhileLoopWorker/Activities/MakePhoneCall.cs b/src/samples/worker/Elsa.Samples.WhileLoopWorker/Activities/MakePhoneCall.cs index 7ad799d39..6b0470e7e 100644 --- a/src/samples/worker/Elsa.Samples.WhileLoopWorker/Activities/MakePhoneCall.cs +++ b/src/samples/worker/Elsa.Samples.WhileLoopWorker/Activities/MakePhoneCall.cs @@ -25,9 +25,9 @@ namespace Elsa.Samples.WhileLoopWorker.Activities _phoneCallService = phoneCallService; } - public override void Build(ICompositeActivityBuilder activity) + public override void Build(ICompositeActivityBuilder builder) { - activity + builder .While(() => _phoneCallService.CallStatus != PhoneCallStatus.Finished, @while => {