diff --git a/src/clients/Elsa.Api.Client/Contracts/IElsaClient.cs b/src/clients/Elsa.Api.Client/Contracts/IElsaClient.cs index 16f3a2506..e255ff9c6 100644 --- a/src/clients/Elsa.Api.Client/Contracts/IElsaClient.cs +++ b/src/clients/Elsa.Api.Client/Contracts/IElsaClient.cs @@ -1,4 +1,5 @@ -using Elsa.Api.Client.Resources.WorkflowDefinitions.Contracts; +using Elsa.Api.Client.Resources.ActivityDescriptors.Contracts; +using Elsa.Api.Client.Resources.WorkflowDefinitions.Contracts; using Elsa.Api.Client.Resources.WorkflowInstances.Contracts; namespace Elsa.Api.Client.Contracts; @@ -13,6 +14,11 @@ public interface IElsaClient /// IWorkflowDefinitionsApi WorkflowDefinitions { get; } + /// + /// Gets the activity descriptors API. + /// + IActivityDescriptorsApi ActivityDescriptors { get; } + /// /// Gets the workflow instances API. /// diff --git a/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs b/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs index 862de56f2..c63eb81a8 100644 --- a/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs +++ b/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs @@ -1,5 +1,6 @@ using Elsa.Api.Client.Contracts; using Elsa.Api.Client.Options; +using Elsa.Api.Client.Resources.ActivityDescriptors.Contracts; using Elsa.Api.Client.Resources.Identity.Contracts; using Elsa.Api.Client.Resources.WorkflowDefinitions.Contracts; using Elsa.Api.Client.Services; @@ -26,6 +27,7 @@ public static class DependencyInjectionExtensions var settings = new RefitSettings(); services.AddElsaApiClient(settings); + services.AddElsaApiClient(settings); services.AddElsaApiClient(settings); return services; } diff --git a/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Contracts/IWorkflowDefinitionsApi.cs b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Contracts/IWorkflowDefinitionsApi.cs new file mode 100644 index 000000000..f7dded57b --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Contracts/IWorkflowDefinitionsApi.cs @@ -0,0 +1,19 @@ +using Elsa.Api.Client.Resources.ActivityDescriptors.Models; +using Refit; + +namespace Elsa.Api.Client.Resources.ActivityDescriptors.Contracts; + +/// +/// Represents a client for the workflow definitions API. +/// +public interface IActivityDescriptorsApi +{ + /// + /// Lists activity descriptors. + /// + /// The request containing options for listing activity descriptors. + /// The cancellation token. + /// The response containing the activity descriptors. + [Get("/descriptors/activities")] + Task ListAsync([Query]ListActivityDescriptorsRequest request, CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ActivityDescriptor.cs b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ActivityDescriptor.cs new file mode 100644 index 000000000..adcb69983 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ActivityDescriptor.cs @@ -0,0 +1,77 @@ +namespace Elsa.Api.Client.Resources.ActivityDescriptors.Models; + +/// +/// A descriptor of an activity type. +/// +public record ActivityDescriptor +{ + /// + /// The fully qualified name of the activity type. + /// + public string TypeName { get; init; } = default!; + + /// + /// The namespace of the activity type. + /// + public string Namespace { get; init; } = default!; + + /// + /// The name of the activity type. + /// + public string Name { get; init; } = default!; + + /// + /// The version of the activity type. + /// + public int Version { get; init; } + + /// + /// The category of the activity type. + /// + public string Category { get; init; } = default!; + + /// + /// The display name of the activity type. + /// + public string? DisplayName { get; init; } + + /// + /// The description of the activity type. + /// + public string? Description { get; init; } + + /// + /// The input properties of the activity type. + /// + public ICollection Inputs { get; init; } = new List(); + + /// + /// The output properties of the activity type. + /// + public ICollection Outputs { get; init; } = new List(); + + /// + /// The kind of activity. + /// + public ActivityKind Kind { get; set; } = ActivityKind.Action; + + /// + /// The ports of the activity type. + /// + public ICollection Ports { get; init; } = new List(); + + /// + /// The custom properties of the activity type. + /// + public IDictionary CustomProperties { get; set; } = new Dictionary(); + + /// + /// A value indicating whether this activity is a container of child activities. + /// + public bool IsContainer { get; set; } + + /// + /// Whether this activity type is selectable from activity pickers. + /// + public bool IsBrowsable { get; set; } +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ActivityKind.cs b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ActivityKind.cs new file mode 100644 index 000000000..1049d01c3 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ActivityKind.cs @@ -0,0 +1,27 @@ +namespace Elsa.Api.Client.Resources.ActivityDescriptors.Models; + +/// +/// Represents the kind of an activity, which affects how it is executed. +/// +public enum ActivityKind +{ + /// + /// Always run synchronously. + /// + Action, + + /// + /// Can be used to trigger new workflows. + /// + Trigger, + + /// + /// Always run asynchronously. + /// + Job, + + /// + /// Run synchronously by default (like , but can be configured to run asynchronously (like ). + /// + Task +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/InputDescriptor.cs b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/InputDescriptor.cs new file mode 100644 index 000000000..1d784ec73 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/InputDescriptor.cs @@ -0,0 +1,57 @@ +using JetBrains.Annotations; + +namespace Elsa.Api.Client.Resources.ActivityDescriptors.Models; + +/// +/// A descriptor of an activity's input property. +/// +[PublicAPI] +public class InputDescriptor : PropertyDescriptor +{ + /// + public InputDescriptor() + { + } + + /// + /// True if the property is wrapped with an "Input{T}" type, false otherwise. + /// + public bool IsWrapped { get; set; } + + /// + /// A string value that hints at what UI control might be used to render in a UI tool. + /// + public string UIHint { get; set; } = default!; + + /// + /// An arbitrary options object that can be used by some UI tool. + /// + public object? Options { get; set; } + + /// + /// The category to whcih this input belongs. Can be used by UI to e.g. render different inputs in different tabs. + /// + public string? Category { get; set; } + + /// + /// The default value. + /// + public object? DefaultValue { get; set; } + + /// + /// The default syntax. + /// + public string? DefaultSyntax { get; set; } + //public ICollection SupportedSyntaxes { get; set; } = new List(); + + /// + /// True if the input is readonly, false otherwise. + /// + public bool? IsReadOnly { get; set; } + + /// + /// The storage driver type to use for persistence. + /// If no driver is specified, the referenced memory block will remain in memory for as long as the expression execution context exists. + /// + public string? StorageDriverType { get; set; } +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ListActivityDescriptorsRequest.cs b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ListActivityDescriptorsRequest.cs new file mode 100644 index 000000000..9ec5c43fc --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ListActivityDescriptorsRequest.cs @@ -0,0 +1,6 @@ +namespace Elsa.Api.Client.Resources.ActivityDescriptors.Models; + +/// +/// Represents a request to list activity descriptors. +/// +public record ListActivityDescriptorsRequest; \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ListActivityDescriptorsResponse.cs b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ListActivityDescriptorsResponse.cs new file mode 100644 index 000000000..cc9073541 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/ListActivityDescriptorsResponse.cs @@ -0,0 +1,8 @@ +namespace Elsa.Api.Client.Resources.ActivityDescriptors.Models; + +/// +/// Represents a response from listing activity descriptors. +/// +/// The activity descriptors. +/// The total number of activity descriptors. +public record ListActivityDescriptorsResponse(ICollection Items, int Count); \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/OutputDescriptor.cs b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/OutputDescriptor.cs new file mode 100644 index 000000000..390296870 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/OutputDescriptor.cs @@ -0,0 +1,11 @@ +using JetBrains.Annotations; + +namespace Elsa.Api.Client.Resources.ActivityDescriptors.Models; + +/// +/// A descriptor of an activity's output property. +/// +[PublicAPI] +public class OutputDescriptor : PropertyDescriptor +{ +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/Port.cs b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/Port.cs new file mode 100644 index 000000000..953df1d2d --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/Port.cs @@ -0,0 +1,27 @@ +namespace Elsa.Api.Client.Resources.ActivityDescriptors.Models; + +/// +/// Represents a port on an activity. +/// +public class Port +{ + /// + /// Gets or sets the name of the port. + /// + public string Name { get; set; } = default!; + + /// + /// Gets or sets the display name of the port. + /// + public string? DisplayName { get; set; } + + /// + /// Gets or sets the type of the port. + /// + public PortType Type { get; set; } + + /// + /// Gets or sets the visibility of the port. + /// + public bool IsBrowsable { get; set; } = true; +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/PortType.cs b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/PortType.cs new file mode 100644 index 000000000..673ede776 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/PortType.cs @@ -0,0 +1,17 @@ +namespace Elsa.Api.Client.Resources.ActivityDescriptors.Models; + +/// +/// The type of a port. +/// +public enum PortType +{ + /// + /// A port that is embedded in the activity. + /// + Embedded, + + /// + /// A flow port. + /// + Flow +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/PropertyDescriptor.cs b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/PropertyDescriptor.cs new file mode 100644 index 000000000..927f0eaa2 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/ActivityDescriptors/Models/PropertyDescriptor.cs @@ -0,0 +1,47 @@ +using System.Text.Json.Serialization; +using JetBrains.Annotations; + +namespace Elsa.Api.Client.Resources.ActivityDescriptors.Models; + +/// +/// A base type for and . +/// +[PublicAPI] +public abstract class PropertyDescriptor +{ + /// + /// The name. + /// + public string Name { get; set; } = default!; + + /// + /// The .NET type. + /// + [JsonPropertyName("typeName")] + public string TypeName { get; set; } = default!; + + /// + /// The user friendly name of the input. Used by UI tools. + /// + public string? DisplayName { get; set; } + + /// + /// The user friendly description of the input. Used by UI tools. + /// + public string? Description { get; set; } + + /// + /// The order in which this input should be displayed by UI tools. + /// + public float Order { get; set; } + + /// + /// True if this input should be displayed by UI tools, false otherwise. + /// + public bool? IsBrowsable { get; set; } + + /// + /// True if this input property is synthetic, which means it does not exist physically on the activity's .NET type. + /// + public bool IsSynthetic { get; set; } +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Services/ElsaClient.cs b/src/clients/Elsa.Api.Client/Services/ElsaClient.cs index b46974121..562f75ec9 100644 --- a/src/clients/Elsa.Api.Client/Services/ElsaClient.cs +++ b/src/clients/Elsa.Api.Client/Services/ElsaClient.cs @@ -1,4 +1,5 @@ using Elsa.Api.Client.Contracts; +using Elsa.Api.Client.Resources.ActivityDescriptors.Contracts; using Elsa.Api.Client.Resources.WorkflowDefinitions.Contracts; using Elsa.Api.Client.Resources.WorkflowInstances.Contracts; @@ -10,15 +11,19 @@ public class ElsaClient : IElsaClient /// /// Initializes a new instance of the class. /// - public ElsaClient(IWorkflowDefinitionsApi workflowDefinitions, IWorkflowInstancesApi workflowInstances) + public ElsaClient(IWorkflowDefinitionsApi workflowDefinitions, IWorkflowInstancesApi workflowInstances, IActivityDescriptorsApi activityDescriptors) { WorkflowDefinitions = workflowDefinitions; WorkflowInstances = workflowInstances; + ActivityDescriptors = activityDescriptors; } /// public IWorkflowDefinitionsApi WorkflowDefinitions { get; } + /// + public IActivityDescriptorsApi ActivityDescriptors { get; } + /// public IWorkflowInstancesApi WorkflowInstances { get; } } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List/Models.cs b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List/Models.cs index 0b5ebb1b4..2792d345a 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List/Models.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/ActivityDescriptors/List/Models.cs @@ -12,4 +12,5 @@ internal class Response } public ICollection Items { get; set; } + public int Count => Items.Count; } \ No newline at end of file