Implement activity property categorization

This commit is contained in:
Sipke Schoorstra 2021-03-19 14:13:26 +01:00
parent 8fb2091813
commit 37eeed2cd0
18 changed files with 143 additions and 76 deletions

View file

@ -57,7 +57,7 @@ namespace Elsa.Activities.Http
/// The <see cref="Type"/> to parse the received request content into if <seealso cref="ReadContent"/> is set to true.
/// If not set, the content will be parse into a default type, depending on the parser associated with the received content-type header.
/// </summary>
[ActivityProperty]
[ActivityProperty(Category = PropertyCategories.Advanced)]
public Type? TargetType { get; set; }
protected override async ValueTask<IActivityExecutionResult> OnExecuteAsync(ActivityExecutionContext context) => context.WorkflowExecutionContext.IsFirstPass ? await ExecuteInternalAsync(context.CancellationToken) : Suspend();

View file

@ -25,22 +25,22 @@ namespace Elsa.Activities.Telnyx.Activities
_telnyxClient = telnyxClient;
}
[ActivityProperty(Label = "Call Control ID", Hint = "Unique identifier and token for controlling the call")]
[ActivityProperty(Label = "Call Control ID", Hint = "Unique identifier and token for controlling the call", Category = PropertyCategories.Advanced)]
public string CallControlId { get; set; } = default!;
[ActivityProperty(Label = "Billing Group ID", Hint = "Use this field to set the Billing Group ID for the call. Must be a valid and existing Billing Group ID.")]
[ActivityProperty(Label = "Billing Group ID", Hint = "Use this field to set the Billing Group ID for the call. Must be a valid and existing Billing Group ID.", Category = PropertyCategories.Advanced)]
public string? BillingGroupId { 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.")]
[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 = "Command ID", Hint = "Use this field to avoid duplicate commands. Telnyx will ignore commands with the same Command ID.")]
[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 = "Webhook URL", Hint = "Use this field to override the URL for which Telnyx will send subsequent webhooks to for this call.")]
[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" })]
[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<IActivityExecutionResult> OnExecuteAsync(ActivityExecutionContext context)

View file

@ -5,6 +5,7 @@ using Elsa.Activities.Telnyx.Client.Models;
using Elsa.Activities.Telnyx.Client.Services;
using Elsa.ActivityResults;
using Elsa.Attributes;
using Elsa.Design;
using Elsa.Exceptions;
using Elsa.Services;
using Elsa.Services.Models;
@ -27,25 +28,25 @@ namespace Elsa.Activities.Telnyx.Activities
_telnyxClient = telnyxClient;
}
[ActivityProperty(Label = "Call Control ID", Hint = "Unique identifier and token for controlling the call")]
[ActivityProperty(Label = "Call Control ID", Hint = "Unique identifier and token for controlling the call", Category = PropertyCategories.Advanced)]
public string CallControlId { get; set; } = default!;
[ActivityProperty(Label = "Audio URL", Hint = "The URL of a file to be played back at the beginning of each prompt. The URL can point to either a WAV or MP3 file.")]
public Uri AudioUrl { get; set; } = default!;
[ActivityProperty(Label = "Client State", Hint = "Use this field to add state to every subsequent webhook. It must be a valid Base-64 encoded string.")]
[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 = "Command ID", Hint = "Use this field to avoid duplicate commands. Telnyx will ignore commands with the same Command ID.")]
[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 = "Inter Digit Timeout", Hint = "The number of milliseconds to wait for input between digits.")]
[ActivityProperty(Label = "Inter Digit Timeout", Hint = "The number of milliseconds to wait for input between digits.", Category = PropertyCategories.Advanced)]
public int? InterDigitTimeoutMillis { get; set; } = 5000;
[ActivityProperty(Label = "Invalid Audio Url", Hint = "The URL of a file to play when digits don't match the Valid Digits setting or the number of digits is not between Min and Max. The URL can point to either a WAV or MP3 file.")]
public Uri? InvalidAudioUrl { get; set; }
[ActivityProperty(Label = "Valid Digits", Hint = "A list of all digits accepted as valid.")]
[ActivityProperty(Label = "Valid Digits", Hint = "A list of all digits accepted as valid.", Category = PropertyCategories.Advanced)]
public string? ValidDigits { get; set; } = "0123456789#*";
[ActivityProperty(Label = "Minimum Digits", Hint = "The minimum number of digits to fetch. This parameter has a minimum value of 1.")]
@ -60,7 +61,7 @@ namespace Elsa.Activities.Telnyx.Activities
[ActivityProperty(Label = "Terminating Digit", Hint = "The digit used to terminate input if fewer than `maximum_digits` digits have been gathered.")]
public string? TerminatingDigit { get; set; } = "#";
[ActivityProperty(Label = "Timeout", Hint = "The number of milliseconds to wait for a DTMF response after file playback ends before a replaying the sound file.")]
[ActivityProperty(Label = "Timeout", Hint = "The number of milliseconds to wait for a DTMF response after file playback ends before a replaying the sound file.", Category = PropertyCategories.Advanced)]
public int? TimeoutMillis { get; set; } = 60000;
protected override async ValueTask<IActivityExecutionResult> OnExecuteAsync(ActivityExecutionContext context)

View file

@ -4,6 +4,7 @@ using Elsa.Activities.Telnyx.Client.Models;
using Elsa.Activities.Telnyx.Client.Services;
using Elsa.ActivityResults;
using Elsa.Attributes;
using Elsa.Design;
using Elsa.Exceptions;
using Elsa.Services;
using Elsa.Services.Models;
@ -26,13 +27,13 @@ namespace Elsa.Activities.Telnyx.Activities
_telnyxClient = telnyxClient;
}
[ActivityProperty(Label = "Call Control ID", Hint = "Unique identifier and token for controlling the call")]
[ActivityProperty(Label = "Call Control ID", Hint = "Unique identifier and token for controlling the call", Category = PropertyCategories.Advanced)]
public string CallControlId { get; set; } = default!;
[ActivityProperty(Label = "Client State", Hint = "Use this field to add state to every subsequent webhook. It must be a valid Base-64 encoded string.")]
[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 = "Command ID", Hint = "Use this field to avoid duplicate commands. Telnyx will ignore commands with the same Command ID.")]
[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; }
protected override async ValueTask<IActivityExecutionResult> OnExecuteAsync(ActivityExecutionContext context)

View file

@ -29,7 +29,7 @@ namespace Elsa.Activities.Telnyx.Activities
_telnyxClient = telnyxClient;
}
[ActivityProperty(Label = "Call Control ID", Hint = "Unique identifier and token for controlling the call.")]
[ActivityProperty(Label = "Call Control ID", Hint = "Unique identifier and token for controlling the call.", Category = PropertyCategories.Advanced)]
public string CallControlId { get; set; } = default!;
[ActivityProperty(Label = "To", Hint = "The DID or SIP URI to dial out and bridge to the given call.")]
@ -48,40 +48,40 @@ namespace Elsa.Activities.Telnyx.Activities
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.")]
[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.")]
[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 = "Audio URL", Hint = "Audio URL to be played back when the transfer destination answers before bridging the call. The URL can point to either a WAV or MP3 file.")]
public Uri? AudioUrl { 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.")]
[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 = "Target Leg Client State", Hint = "Use this field to add state to every subsequent webhook for the new leg. It must be a valid Base-64 encoded string.")]
[ActivityProperty(Label = "Target Leg Client State", Hint = "Use this field to add state to every subsequent webhook for the new leg. It must be a valid Base-64 encoded string.", Category = PropertyCategories.Advanced)]
public string? TargetLegClientState { get; set; }
[ActivityProperty(Label = "Custom Headers", Hint = "Custom headers to be added to the SIP INVITE.")]
[ActivityProperty(Label = "Custom Headers", Hint = "Custom headers to be added to the SIP INVITE.", Category = PropertyCategories.Advanced)]
public IList<Header>? CustomHeaders { get; set; }
[ActivityProperty(Label = "SIP Authentication Username", Hint = "SIP Authentication username used for SIP challenges.")]
[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.")]
[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.")]
[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.")]
[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.")]
[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" })]
[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<IActivityExecutionResult> OnExecuteAsync(ActivityExecutionContext context)

View file

@ -11,5 +11,6 @@ namespace Elsa.Client.Models
[DataMember(Order = 3)] public string? Label { get; set; }
[DataMember(Order = 4)] public string? Hint { get; set; }
[DataMember(Order = 5)] public JToken? Options { get; set; }
[DataMember(Order = 6)] public string? Category { get; set; }
}
}

View file

@ -34,5 +34,10 @@ namespace Elsa.Attributes
/// The name of a static method that provides options.
/// </summary>
public Type? OptionsProvider { get; set; }
/// <summary>
/// A category to group this property with.
/// </summary>
public string? Category { get; set; }
}
}

View file

@ -0,0 +1,7 @@
namespace Elsa.Design
{
public static class PropertyCategories
{
public const string Advanced = "Advanced";
}
}

View file

@ -6,13 +6,14 @@ namespace Elsa.Metadata
{
}
public ActivityPropertyDescriptor(string name, string uiHint, string label, string? hint, object? options)
public ActivityPropertyDescriptor(string name, string uiHint, string label, string? hint, object? options, string category)
{
Name = name;
UIHint = uiHint;
Label = label;
Hint = hint;
Options = options;
Category = category;
}
public string Name { get; set; } = default!;
@ -20,5 +21,6 @@ namespace Elsa.Metadata
public string Label { get; set; } = default!;
public string? Hint { get; set; }
public object? Options { get; set; }
public string? Category { get; set; }
}
}

View file

@ -58,7 +58,8 @@ namespace Elsa.Metadata
_uiHintResolver.GetUIHint(propertyInfo),
activityPropertyAttribute.Label ?? propertyInfo.Name.Humanize(LetterCasing.Title),
activityPropertyAttribute.Hint,
_optionsResolver.GetOptions(propertyInfo)
_optionsResolver.GetOptions(propertyInfo),
activityPropertyAttribute.Category
);
}
}

View file

@ -1,8 +1,6 @@
using Elsa.Client.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NodaTime;
using NodaTime.Serialization.JsonNet;
using ProtoBuf;
namespace ElsaDashboard.Shared.Surrogates
@ -10,17 +8,6 @@ namespace ElsaDashboard.Shared.Surrogates
[ProtoContract(IgnoreListHandling = true)]
public class ActivityPropertyDescriptorSurrogate
{
private static readonly JsonSerializerSettings SerializerSettings;
static ActivityPropertyDescriptorSurrogate()
{
SerializerSettings = new JsonSerializerSettings().ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
}
public ActivityPropertyDescriptorSurrogate()
{
}
public ActivityPropertyDescriptorSurrogate(ActivityPropertyDescriptor value)
{
Name = value.Name;
@ -28,6 +15,7 @@ namespace ElsaDashboard.Shared.Surrogates
Label = value.Label;
Hint = value.Hint;
Options = value.Options?.ToString(Formatting.None);
Category = value.Category;
}
[ProtoMember(1)] public string? Name { get; }
@ -35,6 +23,7 @@ namespace ElsaDashboard.Shared.Surrogates
[ProtoMember(3)] public string? Label { get; }
[ProtoMember(4)] public string? Hint { get; }
[ProtoMember(5)] public string? Options { get; }
[ProtoMember(6)] public string? Category { get; }
public static implicit operator ActivityPropertyDescriptor?(ActivityPropertyDescriptorSurrogate? surrogate) =>
surrogate != null
@ -44,7 +33,8 @@ namespace ElsaDashboard.Shared.Surrogates
UIHint = surrogate.Type!,
Hint = surrogate.Hint,
Label = surrogate.Label,
Options = surrogate.Options is null or "" ? default : JToken.Parse(surrogate.Options)
Options = surrogate.Options is null or "" ? default : JToken.Parse(surrogate.Options),
Category = surrogate.Category
}
: default;

View file

@ -71,10 +71,15 @@ export class ElsaWorkflowDesigner {
const displayContexts: Map<ActivityDesignDisplayContext> = {};
for (const model of activityModels) {
const description = model.description;
const bodyText = description && description.length > 0 ? description : undefined;
const bodyDisplay = bodyText ? <p>{bodyText}</p> : undefined;
const displayContext: ActivityDesignDisplayContext = {
activityModel: model,
activityIcon: <ActivityIcon/>,
bodyDisplay: null,
bodyDisplay: bodyDisplay,
outcomes: [...model.outcomes]
};

View file

@ -45,7 +45,6 @@ export class ElsaMonaco {
filePath: libUri
}]);
//debugger;
const oldModel = monaco.editor.getModel(libUri);
if (oldModel)
@ -90,6 +89,7 @@ export class ElsaMonaco {
minimap: {
enabled: false
},
automaticLayout: true,
lineNumbers: "on",
theme: "vs",
roundedSelection: true,

View file

@ -18,12 +18,14 @@ export class ElsaActivityPickerModal {
dialog: HTMLElsaModalDialogElement;
form: HTMLFormElement;
formContext: FormContext;
renderProps: any;
componentDidLoad() {
eventBus.on(EventTypes.ShowActivityEditor, async (activity: ActivityModel, animate: boolean) => {
this.activityModel = {...activity, properties: activity.properties || []};
this.activityDescriptor = state.activityDescriptors.find(x => x.type == activity.type);
this.formContext = new FormContext(this.activityModel, newValue => this.activityModel = newValue);
this.selectedTab = 'Properties';
await this.dialog.show(animate);
});
}
@ -55,13 +57,45 @@ export class ElsaActivityPickerModal {
this.selectedTab = tab;
}
componentWillRender(){
const activityDescriptor = this.activityDescriptor || {displayName: '', type: '', outcomes: [], category: '', traits: 0, browsable: false, properties: [], description: ''};
const propertyCategories = activityDescriptor.properties.filter(x => x.category).map(x => x.category).distinct();
const defaultProperties = activityDescriptor.properties.filter(x => !x.category || x.category.length == 0);
let tabs: Array<string> = [];
if(defaultProperties.length > 0) {
tabs.push('Properties');
}
tabs.push('Common');
tabs.push('Behaviors');
tabs = [...tabs, ...propertyCategories];
let selectedTab = this.selectedTab;
if(tabs.findIndex(x => x === selectedTab) < 0)
selectedTab = tabs[0];
const activityModel: ActivityModel = this.activityModel || {type: '', activityId: '', outcomes: [], properties: []};
this.renderProps = {
activityDescriptor,
propertyCategories,
defaultProperties,
tabs,
selectedTab,
activityModel
}
}
render() {
const tabs = ['Properties', 'Common', 'Behaviors'];
const selectedTab = this.selectedTab;
const renderProps = this.renderProps;
const activityDescriptor = renderProps.activityDescriptor;
const propertyCategories = renderProps.propertyCategories;
const tabs = renderProps.tabs;
const selectedTab = renderProps.selectedTab;
const activityModel: ActivityModel = renderProps.activityModel;
const inactiveClass = 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300';
const selectedClass = 'border-blue-500 text-blue-600';
const activityModel: ActivityModel = this.activityModel || {type: '', activityId: '', outcomes: [], properties: []};
const activityDescriptor = this.activityDescriptor || {displayName: '', type: '', outcomes: [], category: '', traits: 0, browsable: false, properties: [], description: ''};
return (
<Host>
@ -91,7 +125,7 @@ export class ElsaActivityPickerModal {
</div>
<div class="mt-8">
{this.renderSelectedTab(activityModel, activityDescriptor)}
{this.renderSelectedTab(activityModel, activityDescriptor, propertyCategories)}
</div>
</div>
@ -119,11 +153,12 @@ export class ElsaActivityPickerModal {
);
}
renderSelectedTab(activityModel: ActivityModel, activityDescriptor: ActivityDescriptor) {
renderSelectedTab(activityModel: ActivityModel, activityDescriptor: ActivityDescriptor, categories: Array<string>) {
return [
this.renderWorkflowContextTab(activityModel),
this.renderCommonTab(activityModel),
this.renderPropertiesTab(activityModel, activityDescriptor)
this.renderPropertiesTab(activityModel, activityDescriptor),
this.renderCategoryTabs(activityModel, activityDescriptor, categories)
];
}
@ -157,7 +192,11 @@ export class ElsaActivityPickerModal {
}
renderPropertiesTab(activityModel: ActivityModel, activityDescriptor: ActivityDescriptor) {
const propertyDescriptors: Array<ActivityPropertyDescriptor> = activityDescriptor.properties;
const propertyDescriptors: Array<ActivityPropertyDescriptor> = this.renderProps.defaultProperties;
if(propertyDescriptors.length == 0)
return undefined;
const key = `activity-settings:${activityModel.activityId}`;
return (
@ -167,11 +206,25 @@ export class ElsaActivityPickerModal {
);
}
renderCategoryTabs(activityModel: ActivityModel, activityDescriptor: ActivityDescriptor, categories: Array<string>) {
const propertyDescriptors: Array<ActivityPropertyDescriptor> = activityDescriptor.properties;
return (
categories.map(category => {
const descriptors = propertyDescriptors.filter(x => x.category == category);
const key = `activity-settings:${activityModel.activityId}:${category}`;
return <div key={key} class={`grid grid-cols-1 gap-y-6 gap-x-4 sm:grid-cols-6 ${this.getHiddenClass(category)}`}>
{descriptors.map(property => this.renderPropertyEditor(activityModel, property))}
</div>
})
);
}
renderPropertyEditor(activity: ActivityModel, property: ActivityPropertyDescriptor) {
return propertyDisplayManager.display(activity, property);
}
getHiddenClass(tab: string) {
return this.selectedTab == tab ? '' : 'hidden';
return this.renderProps.selectedTab == tab ? '' : 'hidden';
}
}

View file

@ -14,7 +14,7 @@
</head>
<body class="h-screen" style="background-size: 30px 30px; background-image: url(/build/assets/tile.png); background-color: #FBFBFB;">
<elsa-workflow-editor id="workflowEditor" server-url="http://localhost:5000/" workflow-definition-id="7eed1333c2674370a1e9b300aa94fda2" monaco-lib-path="build/assets/js"></elsa-workflow-editor>
<elsa-workflow-editor id="workflowEditor" server-url="https://localhost:11000/" workflow-definition-id="7eed1333c2674370a1e9b300aa94fda2" monaco-lib-path="build/assets/js"></elsa-workflow-editor>
</body>
</html>

View file

@ -1,23 +1,23 @@
import {Map} from '../utils/utils';
export interface WorkflowDefinition {
id?: string,
definitionId?: string,
tenantId?: string,
name?: string,
displayName?: string,
description?: string,
version: number,
variables?: Variables,
customAttributes?: Variables,
contextOptions?: WorkflowContextOptions,
isSingleton?: boolean,
persistenceBehavior?: WorkflowPersistenceBehavior,
deleteCompletedInstances?: boolean,
isPublished?: boolean,
isLatest?: boolean,
activities: Array<ActivityDefinition>,
connections: Array<ConnectionDefinition>
id?: string;
definitionId?: string;
tenantId?: string;
name?: string;
displayName?: string;
description?: string;
version: number;
variables?: Variables;
customAttributes?: Variables;
contextOptions?: WorkflowContextOptions;
isSingleton?: boolean;
persistenceBehavior?: WorkflowPersistenceBehavior;
deleteCompletedInstances?: boolean;
isPublished?: boolean;
isLatest?: boolean;
activities: Array<ActivityDefinition>;
connections: Array<ConnectionDefinition>;
}
export interface ActivityDefinition {
@ -106,6 +106,7 @@ export interface ActivityPropertyDescriptor {
label?: string;
hint?: string;
options?: any;
category?: string;
}
export enum ActivityTraits {

View file

@ -17,6 +17,8 @@ export class IfPlugin implements ElsaPlugin {
const props = activityModel.properties || [];
const condition = props.find(x => x.name == 'Condition') || { expression: '' };
const expression = condition.expression || '';
context.bodyDisplay = <p>{expression}</p>;
const description = activityModel.description;
const bodyText = description && description.length > 0 ? description : expression;
context.bodyDisplay = <p>{bodyText}</p>;
}
}

View file

@ -22,7 +22,5 @@ export class RunJavascriptPlugin implements ElsaPlugin {
if(context.outcomes.length == 0)
context.outcomes = ['Done'];
context.bodyDisplay = undefined;
}
}