Add project files.

This commit is contained in:
2025-08-20 11:07:36 +03:30
parent 3863c74931
commit 1a308a4069
899 changed files with 85379 additions and 0 deletions
@@ -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);