Add project files.
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
using Elsa.Api.Client.Options;
|
||||
using Elsa.Studio.Options;
|
||||
|
||||
namespace Elsa.Studio.Models;
|
||||
|
||||
public class BackendApiConfig
|
||||
{
|
||||
public Action<ElsaClientBuilderOptions>? ConfigureHttpClientBuilder { get; set; }
|
||||
public Action<BackendOptions>? ConfigureBackendOptions { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Elsa.Studio.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Contains information about the client.
|
||||
/// </summary>
|
||||
/// <param name="PackageVersion">The installed package version of Elsa Studio.</param>
|
||||
public record ClientInformation(string PackageVersion);
|
||||
@@ -0,0 +1,198 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using Elsa.Api.Client.Extensions;
|
||||
using Elsa.Api.Client.Resources.ActivityDescriptors.Models;
|
||||
using Elsa.Api.Client.Resources.Scripting.Models;
|
||||
using Elsa.Api.Client.Resources.WorkflowDefinitions.Models;
|
||||
using Elsa.Api.Client.Shared.Models;
|
||||
using Elsa.Studio.Contracts;
|
||||
|
||||
namespace Elsa.Studio.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Provides contextual information to the input editor.
|
||||
/// </summary>
|
||||
public class DisplayInputEditorContext
|
||||
{
|
||||
/// <summary>
|
||||
/// The workflow definition.
|
||||
/// </summary>
|
||||
public WorkflowDefinition WorkflowDefinition { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The activity.
|
||||
/// </summary>
|
||||
public JsonObject Activity { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The activity descriptor.
|
||||
/// </summary>
|
||||
public ActivityDescriptor ActivityDescriptor { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The input descriptor.
|
||||
/// </summary>
|
||||
public InputDescriptor InputDescriptor { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The input value.
|
||||
/// </summary>
|
||||
public object? Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The UI hint handler.
|
||||
/// </summary>
|
||||
public IUIHintHandler UIHintHandler { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The syntax provider.
|
||||
/// </summary>
|
||||
public ExpressionDescriptor? SelectedExpressionDescriptor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A delegate that is invoked when the input value changes.
|
||||
/// </summary>
|
||||
public Func<object?, Task> OnValueChanged { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// A value indicating whether the input is read-only.
|
||||
/// </summary>
|
||||
public bool IsReadOnly { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the input value or the default value if the input value is null.
|
||||
/// </summary>
|
||||
public T? GetValueOrDefault<T>()
|
||||
{
|
||||
return (Value ?? InputDescriptor.DefaultValue).ConvertTo<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the wrapped input literal value.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetLiteralValueOrDefault()
|
||||
{
|
||||
if (!InputDescriptor.IsWrapped)
|
||||
return Value?.ToString() ?? InputDescriptor.DefaultValue?.ToString() ?? string.Empty;
|
||||
|
||||
var wrappedInput = Value as WrappedInput;
|
||||
var expression = wrappedInput?.Expression;
|
||||
|
||||
if (expression?.Type != "Literal")
|
||||
return InputDescriptor.DefaultValue?.ToString() ?? string.Empty;
|
||||
|
||||
var value = expression.Value;
|
||||
return value?.ToString() ?? InputDescriptor.DefaultValue?.ToString() ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the wrapped input object value.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetObjectValueOrDefault()
|
||||
{
|
||||
if (!InputDescriptor.IsWrapped)
|
||||
return Serialize(Value ?? InputDescriptor.DefaultValue);
|
||||
|
||||
var wrappedInput = Value as WrappedInput;
|
||||
var expression = wrappedInput?.Expression;
|
||||
|
||||
if (expression?.Type != "Object")
|
||||
return Serialize(InputDescriptor.DefaultValue);
|
||||
|
||||
var value = expression.Value;
|
||||
return value?.ToString() ?? InputDescriptor.DefaultValue?.ToString() ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the input expression value if this is a wrapped input (i.e. Input{T}) or naked value otherwise. If either value is null, the default value is returned.
|
||||
/// </summary>
|
||||
public string GetExpressionValueOrDefault()
|
||||
{
|
||||
if (!InputDescriptor.IsWrapped)
|
||||
return Value?.ToString() ?? InputDescriptor.DefaultValue?.ToString() ?? string.Empty;
|
||||
|
||||
var wrappedInput = Value as WrappedInput;
|
||||
var expression = wrappedInput?.Expression;
|
||||
var value = expression?.ToString();
|
||||
return value ?? InputDescriptor.DefaultValue?.ToString() ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the naked input value.
|
||||
/// </summary>
|
||||
public async Task UpdateValueAsync(object? value)
|
||||
{
|
||||
await OnValueChanged(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the wrapped input expression.
|
||||
/// </summary>
|
||||
/// <param name="expression"></param>
|
||||
public async Task UpdateExpressionAsync(Expression expression)
|
||||
{
|
||||
var wrappedInput = Value as WrappedInput;
|
||||
|
||||
// Update input.
|
||||
wrappedInput ??= new();
|
||||
wrappedInput.Expression = expression;
|
||||
|
||||
Value = wrappedInput;
|
||||
|
||||
// Notify that the input has changed.
|
||||
await OnValueChanged(wrappedInput);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the input value or sets it as a literal expression,
|
||||
/// depending on the wrapping configuration of the <see cref="InputDescriptor"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The new value to be set, either directly or wrapped as a literal expression.</param>
|
||||
public Task UpdateValueOrLiteralExpressionAsync(string value)
|
||||
{
|
||||
return UpdateValueOrExpressionAsync(value, _ => value, "Literal");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the input value or sets it as an object expression,
|
||||
/// depending on the wrapping configuration of the <see cref="InputDescriptor"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The new value to be set, either directly or wrapped as an object expression.</param>
|
||||
public Task UpdateValueOrObjectExpressionAsync(object value)
|
||||
{
|
||||
return UpdateValueOrExpressionAsync(value, Serialize, "Object");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the input value or sets it as an expression,
|
||||
/// depending on the wrapping configuration of the <see cref="InputDescriptor"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The new value to be set, either directly or wrapped as an expression.</param>
|
||||
/// <param name="toString">A delegate to a function that stringifies the value for storing inside an <see cref="Expression"/> object.</param>
|
||||
/// <param name="expressionType">The expression type</param>
|
||||
public async Task UpdateValueOrExpressionAsync(object? value, Func<object?, string?> toString, string expressionType)
|
||||
{
|
||||
if (InputDescriptor.IsWrapped)
|
||||
{
|
||||
var stringValue = toString(value);
|
||||
var expression = new Expression(expressionType, stringValue);
|
||||
|
||||
await UpdateExpressionAsync(expression);
|
||||
return;
|
||||
}
|
||||
|
||||
await UpdateValueAsync(value);
|
||||
}
|
||||
|
||||
private static string Serialize(object? value)
|
||||
{
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
};
|
||||
|
||||
return value != null ? JsonSerializer.Serialize(value, options) : string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
|
||||
namespace Elsa.Studio.Models;
|
||||
|
||||
/// <summary>
|
||||
/// A menu item.
|
||||
/// </summary>
|
||||
public class MenuItem
|
||||
{
|
||||
/// <summary>
|
||||
/// The icon to use in SVG format.
|
||||
/// </summary>
|
||||
public string? Icon { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The path to navigate to.
|
||||
/// </summary>
|
||||
public string Href { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="NavLinkMatch"/> to use.
|
||||
/// </summary>
|
||||
public NavLinkMatch Match { get; set; } = NavLinkMatch.Prefix;
|
||||
|
||||
/// <summary>
|
||||
/// The text to display.
|
||||
/// </summary>
|
||||
public string Text { get; set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// The order of the menu item.
|
||||
/// </summary>
|
||||
public float Order { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A list of sub menu items.
|
||||
/// </summary>
|
||||
public ICollection<MenuItem> SubMenuItems { get; set; } = new List<MenuItem>();
|
||||
|
||||
/// <summary>
|
||||
/// The name of the group this menu item belongs to.
|
||||
/// </summary>
|
||||
public string GroupName { get; set; } = "General";
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace Elsa.Studio.Models;
|
||||
|
||||
/// A menu item group.
|
||||
public record MenuItemGroup(string Name, string Text, float Order = 0f);
|
||||
@@ -0,0 +1,21 @@
|
||||
namespace Elsa.Studio.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Represent a remote backend.
|
||||
/// </summary>
|
||||
public class RemoteBackend
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RemoteBackend"/> class.
|
||||
/// </summary>
|
||||
/// <param name="url">The URL of the backend.</param>
|
||||
public RemoteBackend(Uri url)
|
||||
{
|
||||
Url = url;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The URL of the backend.
|
||||
/// </summary>
|
||||
public Uri Url { get; }
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
namespace Elsa.Studio.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a result that is either successful or failed.
|
||||
/// </summary>
|
||||
/// <typeparam name="TSuccess">The type of the success value.</typeparam>
|
||||
/// <typeparam name="TFailure">The type of the failure value.</typeparam>
|
||||
public class Result<TSuccess, TFailure>
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new successful result.
|
||||
/// </summary>
|
||||
public Result(TSuccess success)
|
||||
{
|
||||
Success = success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new failed result.
|
||||
/// </summary>
|
||||
/// <param name="failure"></param>
|
||||
public Result(TFailure failure)
|
||||
{
|
||||
Failure = failure;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The success value.
|
||||
/// </summary>
|
||||
public TSuccess? Success { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The failure value.
|
||||
/// </summary>
|
||||
public TFailure? Failure { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the result is successful.
|
||||
/// </summary>
|
||||
public bool IsSuccess => Success is not null;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the result is failed.
|
||||
/// </summary>
|
||||
public bool IsFailed => Failure is not null;
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified handler if the result is successful.
|
||||
/// </summary>
|
||||
/// <returns>The success result.</returns>
|
||||
public async Task<TSuccess> OnSuccessAsync(Func<TSuccess, Task> handler)
|
||||
{
|
||||
if (!IsSuccess) return default!;
|
||||
await handler(Success!);
|
||||
return Success!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified handler if the result is successful.
|
||||
/// </summary>
|
||||
/// <returns>The success result.</returns>
|
||||
public TSuccess OnSuccess(Action<TSuccess> handler)
|
||||
{
|
||||
if (!IsSuccess) return default!;
|
||||
handler(Success!);
|
||||
return Success!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified handler if the result is failed.
|
||||
/// </summary>
|
||||
/// <returns>The failed result.</returns>
|
||||
public async Task<TFailure> OnFailedAsync(Func<TFailure, Task> handler)
|
||||
{
|
||||
if (!IsFailed) return default!;
|
||||
await handler(Failure!);
|
||||
return Failure!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified handler if the result is failed.
|
||||
/// </summary>
|
||||
/// <returns>The failed result.</returns>
|
||||
public TFailure OnFailed(Action<TFailure> handler)
|
||||
{
|
||||
if (!IsFailed) return default!;
|
||||
handler(Failure!);
|
||||
return Failure!;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Elsa.Studio.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Contains information about the server.
|
||||
/// </summary>
|
||||
/// <param name="PackageVersion">The installed package version of Elsa.</param>
|
||||
public record ServerInformation(string PackageVersion);
|
||||
Reference in New Issue
Block a user