Update Dial activity and fix Switch (#3753)

* Add GetCallStatus activity

* Update Dial activity

* Update Switch activity

* Fix missing ports
This commit is contained in:
Sipke Schoorstra 2023-03-02 10:37:16 +01:00 committed by GitHub
parent 280b905092
commit 67efc51ebb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 75 additions and 18 deletions

View file

@ -52,7 +52,7 @@ export class DefaultActivityTemplate {
{({nodeMap}) => {
const activity: Activity = nodeMap[activityId];
const ports = portProvider.getOutboundPorts({activityDescriptor, activity});
const embeddedPorts = ports.filter(x => x.mode == PortMode.Embedded && x.isBrowsable);
const embeddedPorts = ports.filter(x => x.mode == PortMode.Embedded && x.isBrowsable !== false);
const canStartWorkflow = activity?.canStartWorkflow;
const icon = this.icon;
const hasIcon = !!icon;

View file

@ -15,7 +15,9 @@ export class SwitchPortProvider implements PortProvider {
return [];
const cases = activity.cases ?? [];
return cases.map(x => ({name: x.label, displayName: x.label, mode: PortMode.Embedded}));
const ports = cases.map(x => ({name: x.label, displayName: x.label, mode: PortMode.Embedded}));
const defaultPort = {name: 'default', displayName: 'Default', mode: PortMode.Embedded};
return [...ports, defaultPort];
}
resolvePort(portName: string, context: PortProviderContext): Activity | Array<Activity> {

View file

@ -52,7 +52,7 @@ export class ToolboxActivities {
buildModel = (): any => {
const browsableDescriptors = uniqBy(descriptorsStore.activityDescriptors
.filter(x => x.isBrowsable)
.filter(x => x.isBrowsable !== false)
.sort((a, b) => a.version > b.version ? 1 : -1), x => `${x.typeName}:${x.version}`);
const categorizedActivitiesLookup = groupBy(browsableDescriptors, x => x.category);

View file

@ -81,10 +81,12 @@ function walkRecursive(node: ActivityNode, activity: Activity, collectedActiviti
}
if (childNode !== node) {
childNode.parents.push(node);
node.children.push(childNode);
collectedActivities.add(port.activity);
walkRecursive(childNode, port.activity, collectedActivities, collectedNodes, descriptors);
if(!!childNode.activity) {
childNode.parents.push(node);
node.children.push(childNode);
collectedActivities.add(port.activity)
walkRecursive(childNode, port.activity, collectedActivities, collectedNodes, descriptors);
}
}
}
}
@ -104,9 +106,6 @@ function getPorts(node: ActivityNode, activity: Activity, descriptors: Array<Act
for (const port of ports) {
const value = portProvider.resolvePort(port.name, portProviderContext);
if (!value)
continue;
if (Array.isArray(value)) {
const activities = value as Array<Activity>;
activityPorts = [...activityPorts, ...activities.map(x => ({port: port.name, activity: x}))];

View file

@ -23,7 +23,7 @@ public class Dial : CodeActivity<DialResponse>
public Dial(string? source = default, int? line = default) : base(source, line)
{
}
/// <summary>
/// The DID or SIP URI to dial out and bridge to the given call.
/// </summary>
@ -52,20 +52,31 @@ public class Dial : CodeActivity<DialResponse>
Options = new[] { "disabled", "detect", "detect_beep", "detect_words", "greeting_end", "premium" },
DefaultValue = "disabled")]
public Input<string?> AnsweringMachineDetection { get; set; } = new("disabled");
/// <summary>
/// Enables answering machine detection.
/// </summary>
[Input(Description = "Start recording automatically after an event. Disabled by default.")]
public Input<bool> Record { get; set; } = default!;
/// <summary>
/// Defines the format of the recording ('wav' or 'mp3') when `record` is specified.
/// </summary>
[Input(
Description = "Defines the format of the recording ('wav' or 'mp3') when `record` is specified.",
UIHint = InputUIHints.Dropdown,
Options = new[] { "wav", "mp3" },
DefaultValue = "mp3"
)]
public Input<string> RecordFormat { get; set; } = new("mp3");
/// <inheritdoc />
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
{
var response = await DialAsync(context);
Result.Set(context, response);
}
private async Task<DialResponse> DialAsync(ActivityExecutionContext context)
{
var telnyxOptions = context.GetRequiredService<IOptions<TelnyxOptions>>().Value;
@ -84,6 +95,7 @@ public class Dial : CodeActivity<DialResponse>
FromDisplayName.TryGet(context).SanitizeCallerName(),
AnsweringMachineDetection.TryGet(context),
Record: Record.TryGet(context) == true ? "record-from-answer" : default,
RecordFormat: RecordFormat.TryGet(context) ?? "mp3",
ClientState: clientState
);

View file

@ -0,0 +1,45 @@
using System.Runtime.CompilerServices;
using System.Text.Json.Serialization;
using Elsa.Extensions;
using Elsa.Telnyx.Client.Services;
using Elsa.Workflows.Core.Activities.Flowchart.Attributes;
using Elsa.Workflows.Core.Attributes;
using Elsa.Workflows.Core.Models;
namespace Elsa.Telnyx.Activities;
/// <inheritdoc />
[FlowNode("Alive", "Dead", "Done")]
[Activity(Constants.Namespace, "Get the status of a call.", Kind = ActivityKind.Task)]
public class GetCallStatus : CodeActivity<bool>
{
/// <inheritdoc />
[JsonConstructor]
public GetCallStatus([CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : base(source, line)
{
}
/// <summary>
/// Unique identifier and token for controlling the call.
/// </summary>
[Input(
DisplayName = "Call Control ID",
Description = "Unique identifier and token for controlling the call.",
Category = "Advanced"
)]
public Input<string> CallControlId { get; set; } = default!;
/// <inheritdoc />
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
{
var client = context.GetRequiredService<ITelnyxClient>();
var callControlId = CallControlId.Get(context);
var response = await client.Calls.GetStatusAsync(callControlId, context.CancellationToken);
var isAlive = response.Data.IsAlive;
var outcome = isAlive ? "Alive" : "Dead";
Result.Set(context, isAlive);
await context.CompleteActivityWithOutcomesAsync(outcome, "Done");
}
}

View file

@ -67,6 +67,7 @@ public record DialRequest(
string? AnsweringMachineDetection = default,
AnsweringMachineConfig? AnsweringMachineConfig = default,
string? Record = default,
string? RecordFormat = default,
string? ClientState = default,
string? CommandId = default,
IList<Header>? CustomHeaders = default,

View file

@ -34,7 +34,7 @@ public class Switch : Activity
public Output<object>? Output { get; set; }
[Input(UIHint = "switch-editor")] public ICollection<SwitchCase> Cases { get; set; } = new List<SwitchCase>();
public IActivity? Default { get; set; }
[Port]public IActivity? Default { get; set; }
/// <inheritdoc />
protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
@ -44,13 +44,11 @@ public class Switch : Activity
if (matchingCase != null)
{
if (matchingCase.Activity != null)
await context.ScheduleActivityAsync(matchingCase.Activity, OnChildActivityCompletedAsync);
await context.ScheduleActivityAsync(matchingCase.Activity, OnChildActivityCompletedAsync);
return;
}
if (Default != null)
await context.ScheduleActivityAsync(Default, OnChildActivityCompletedAsync);
await context.ScheduleActivityAsync(Default, OnChildActivityCompletedAsync);
}
private async Task<SwitchCase?> FindMatchingCaseAsync(ExpressionExecutionContext context)