Incremental work on API + client
This commit is contained in:
parent
def637b4ca
commit
cb99b26151
|
|
@ -10,6 +10,7 @@
|
|||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Configurer/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=localizer/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Materializer/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Noda/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Persister/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=persisters/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Elsa.Client
|
||||
{
|
||||
public class Class1
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using System.Collections.Generic;
|
||||
using Elsa.Client.Models;
|
||||
|
||||
namespace Elsa.Client.Comparers
|
||||
{
|
||||
public class BlockingActivityEqualityComparer : IEqualityComparer<BlockingActivity>
|
||||
{
|
||||
public static BlockingActivityEqualityComparer Instance { get; } = new BlockingActivityEqualityComparer();
|
||||
|
||||
public bool Equals(BlockingActivity x, BlockingActivity y) => x.ActivityId.Equals(y.ActivityId);
|
||||
public int GetHashCode(BlockingActivity obj) => obj.ActivityId.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,26 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.0</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<PackageVersion>1.0.0</PackageVersion>
|
||||
<Authors>Elsa Contributors</Authors>
|
||||
<Description>
|
||||
Elsa is a set of workflow libraries and tools that enable lean and mean workflowing capabilities in any .NET Core application.
|
||||
This package provides a client using Refit for Elsa's REST API endpoints.
|
||||
</Description>
|
||||
<Copyright>2020</Copyright>
|
||||
<PackageProjectUrl>https://github.com/elsa-workflows/elsa-core</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/elsa-workflows/elsa-core</RepositoryUrl>
|
||||
<RepositoryType>GitHub</RepositoryType>
|
||||
<PackageTags>elsa, workflows, rest, api, client</PackageTags>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="NodaTime" Version="3.0.3" />
|
||||
<PackageReference Include="Refit" Version="5.2.1" />
|
||||
<PackageReference Include="Refit.HttpClientFactory" Version="5.2.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
14
src/clients/Elsa.Client/ElsaClient.cs
Normal file
14
src/clients/Elsa.Client/ElsaClient.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
using Elsa.Client.Services;
|
||||
|
||||
namespace Elsa.Client
|
||||
{
|
||||
internal class ElsaClient : IElsaClient
|
||||
{
|
||||
public ElsaClient(IWorkflowDefinitionsApi workflowDefinitionsApi)
|
||||
{
|
||||
WorkflowDefinitions = workflowDefinitionsApi;
|
||||
}
|
||||
|
||||
public IWorkflowDefinitionsApi WorkflowDefinitions { get; }
|
||||
}
|
||||
}
|
||||
9
src/clients/Elsa.Client/IElsaClient.cs
Normal file
9
src/clients/Elsa.Client/IElsaClient.cs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
using Elsa.Client.Services;
|
||||
|
||||
namespace Elsa.Client
|
||||
{
|
||||
public interface IElsaClient
|
||||
{
|
||||
IWorkflowDefinitionsApi WorkflowDefinitions { get; }
|
||||
}
|
||||
}
|
||||
17
src/clients/Elsa.Client/Models/ActivityDefinition.cs
Normal file
17
src/clients/Elsa.Client/Models/ActivityDefinition.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class ActivityDefinition
|
||||
{
|
||||
public string ActivityId { get; set; } = default!;
|
||||
public string Type { get; set; } = default!;
|
||||
public string? Name { get; set; }
|
||||
public string? DisplayName { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public int? Left { get; set; }
|
||||
public int? Top { get; set; }
|
||||
public bool PersistWorkflow { get; set; }
|
||||
public bool LoadWorkflowContext { get; set; }
|
||||
public bool SaveWorkflowContext { get; set; }
|
||||
public ActivityDefinitionProperties Properties { get; set; } = new ActivityDefinitionProperties();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class ActivityDefinitionProperties : Dictionary<string, ActivityDefinitionPropertyValue>
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
|
||||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class ActivityDefinitionPropertyValue
|
||||
{
|
||||
public static ActivityDefinitionPropertyValue Literal<T>(T value) => new ActivityDefinitionPropertyValue(value!.ToString(), "Literal", typeof(T));
|
||||
public static ActivityDefinitionPropertyValue Liquid<T>(string expression) => new ActivityDefinitionPropertyValue(expression, "Liquid", typeof(T));
|
||||
public static ActivityDefinitionPropertyValue JavaScript<T>(string expression) => new ActivityDefinitionPropertyValue(expression, "JavaScript", typeof(T));
|
||||
|
||||
public ActivityDefinitionPropertyValue()
|
||||
{
|
||||
}
|
||||
|
||||
public ActivityDefinitionPropertyValue(string expression, string syntax, Type type)
|
||||
{
|
||||
Expression = expression;
|
||||
Syntax = syntax;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public Type Type { get; set; } = default!;
|
||||
public string Syntax { get; set; } = default!;
|
||||
public string Expression { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
24
src/clients/Elsa.Client/Models/ActivityInstance.cs
Normal file
24
src/clients/Elsa.Client/Models/ActivityInstance.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class ActivityInstance
|
||||
{
|
||||
public ActivityInstance()
|
||||
{
|
||||
}
|
||||
|
||||
public ActivityInstance(string id, string type, object? output, JObject data)
|
||||
{
|
||||
Id = id;
|
||||
Type = type;
|
||||
Data = data;
|
||||
Output = output;
|
||||
}
|
||||
|
||||
public string? Id { get; set; }
|
||||
public string? Type { get; set; }
|
||||
public JObject Data { get; set; } = new JObject();
|
||||
public object? Output { get; set; }
|
||||
}
|
||||
}
|
||||
19
src/clients/Elsa.Client/Models/BlockingActivity.cs
Normal file
19
src/clients/Elsa.Client/Models/BlockingActivity.cs
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class BlockingActivity
|
||||
{
|
||||
public BlockingActivity()
|
||||
{
|
||||
}
|
||||
|
||||
public BlockingActivity(string activityId, string activityType)
|
||||
{
|
||||
ActivityId = activityId;
|
||||
ActivityType = activityType;
|
||||
}
|
||||
|
||||
public string ActivityId { get; set; } = default!;
|
||||
public string ActivityType { get; set; }= default!;
|
||||
public string? Tag { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class CompositeActivityDefinition : ActivityDefinition
|
||||
{
|
||||
public CompositeActivityDefinition()
|
||||
{
|
||||
Activities = new List<ActivityDefinition>();
|
||||
Connections = new List<ConnectionDefinition>();
|
||||
Type = "CompositeActivity";
|
||||
}
|
||||
|
||||
public ICollection<ActivityDefinition> Activities { get; set; }
|
||||
public ICollection<ConnectionDefinition> Connections { get; set; }
|
||||
}
|
||||
}
|
||||
20
src/clients/Elsa.Client/Models/ConnectionDefinition.cs
Normal file
20
src/clients/Elsa.Client/Models/ConnectionDefinition.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class ConnectionDefinition
|
||||
{
|
||||
public ConnectionDefinition()
|
||||
{
|
||||
}
|
||||
|
||||
public ConnectionDefinition(string sourceActivityId, string targetActivityId, string outcome)
|
||||
{
|
||||
SourceActivityId = sourceActivityId;
|
||||
TargetActivityId = targetActivityId;
|
||||
Outcome = outcome;
|
||||
}
|
||||
|
||||
public string? SourceActivityId { get; set; }
|
||||
public string? TargetActivityId { get; set; }
|
||||
public string? Outcome { get; set; }
|
||||
}
|
||||
}
|
||||
20
src/clients/Elsa.Client/Models/ExecutionLogEntry.cs
Normal file
20
src/clients/Elsa.Client/Models/ExecutionLogEntry.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using NodaTime;
|
||||
|
||||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class ExecutionLogEntry
|
||||
{
|
||||
public ExecutionLogEntry()
|
||||
{
|
||||
}
|
||||
|
||||
public ExecutionLogEntry(string activityId, Instant timestamp)
|
||||
{
|
||||
ActivityId = activityId;
|
||||
Timestamp = timestamp;
|
||||
}
|
||||
|
||||
public string ActivityId { get; set; } = default!;
|
||||
public Instant Timestamp { get; set; }
|
||||
}
|
||||
}
|
||||
18
src/clients/Elsa.Client/Models/ScheduledActivity.cs
Normal file
18
src/clients/Elsa.Client/Models/ScheduledActivity.cs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class ScheduledActivity
|
||||
{
|
||||
public ScheduledActivity()
|
||||
{
|
||||
}
|
||||
|
||||
public ScheduledActivity(string activityId, object? input = default)
|
||||
{
|
||||
ActivityId = activityId;
|
||||
Input = input;
|
||||
}
|
||||
|
||||
public string ActivityId { get; set; } = default!;
|
||||
public object? Input { get; set; }
|
||||
}
|
||||
}
|
||||
21
src/clients/Elsa.Client/Models/Scheduler.cs
Normal file
21
src/clients/Elsa.Client/Models/Scheduler.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class Scheduler
|
||||
{
|
||||
private readonly Stack<ScheduledActivity> _stack = new Stack<ScheduledActivity>();
|
||||
|
||||
public bool HasScheduledActivities => _stack.Any();
|
||||
|
||||
public ScheduledActivity Schedule(string activityId, object? input = null)
|
||||
{
|
||||
var scheduledActivity = new ScheduledActivity(activityId, input);
|
||||
_stack.Push(scheduledActivity);
|
||||
return scheduledActivity;
|
||||
}
|
||||
|
||||
public ScheduledActivity Next() => _stack.Pop();
|
||||
}
|
||||
}
|
||||
46
src/clients/Elsa.Client/Models/Variables.cs
Normal file
46
src/clients/Elsa.Client/Models/Variables.cs
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class Variables
|
||||
{
|
||||
public Variables()
|
||||
{
|
||||
Data = new Dictionary<string, object?>();
|
||||
}
|
||||
|
||||
public Variables(Variables other) : this(other.Data)
|
||||
{
|
||||
}
|
||||
|
||||
public Variables(IDictionary<string, object?> data)
|
||||
{
|
||||
Data = data;
|
||||
}
|
||||
|
||||
public IDictionary<string, object?> Data { get; set; }
|
||||
|
||||
public object? Get(string name) => Has(name) ? Data[name] : default;
|
||||
|
||||
public T Get<T>(string name)
|
||||
{
|
||||
if (!Has(name))
|
||||
return default!;
|
||||
|
||||
var value = Get(name);
|
||||
|
||||
if (value == null)
|
||||
return default!;
|
||||
|
||||
return (T)value!;
|
||||
}
|
||||
|
||||
public Variables Set(string name, object? value)
|
||||
{
|
||||
Data[name] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public bool Has(string name) => Data.ContainsKey(name);
|
||||
}
|
||||
}
|
||||
42
src/clients/Elsa.Client/Models/VersionOptions.cs
Normal file
42
src/clients/Elsa.Client/Models/VersionOptions.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
namespace Elsa.Client.Models
|
||||
{
|
||||
public struct VersionOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the latest version.
|
||||
/// </summary>
|
||||
public static readonly VersionOptions Latest = new VersionOptions { IsLatest = true };
|
||||
|
||||
/// <summary>
|
||||
/// Gets the published version.
|
||||
/// </summary>
|
||||
public static readonly VersionOptions Published = new VersionOptions { IsPublished = true };
|
||||
|
||||
/// <summary>
|
||||
/// Gets the latest or published version.
|
||||
/// </summary>
|
||||
public static readonly VersionOptions LatestOrPublished = new VersionOptions { IsLatestOrPublished = true };
|
||||
|
||||
/// <summary>
|
||||
/// Gets the draft version.
|
||||
/// </summary>
|
||||
public static readonly VersionOptions Draft = new VersionOptions { IsDraft = true };
|
||||
|
||||
/// <summary>
|
||||
/// Gets all versions.
|
||||
/// </summary>
|
||||
public static readonly VersionOptions All = new VersionOptions { AllVersions = true };
|
||||
|
||||
/// <summary>
|
||||
/// Gets a specific version.
|
||||
/// </summary>
|
||||
public static VersionOptions SpecificVersion(int version) => new VersionOptions { Version = version };
|
||||
|
||||
public bool IsLatest { get; private set; }
|
||||
public bool IsLatestOrPublished { get; private set; }
|
||||
public bool IsPublished { get; private set; }
|
||||
public bool IsDraft { get; private set; }
|
||||
public bool AllVersions { get; private set; }
|
||||
public int Version { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
namespace Elsa.Services.Models
|
||||
namespace Elsa.Client.Models
|
||||
{
|
||||
public enum WorkflowContextFidelity
|
||||
{
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
|
||||
namespace Elsa.Services.Models
|
||||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class WorkflowContextOptions
|
||||
{
|
||||
24
src/clients/Elsa.Client/Models/WorkflowDefinition.cs
Normal file
24
src/clients/Elsa.Client/Models/WorkflowDefinition.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class WorkflowDefinition : CompositeActivityDefinition
|
||||
{
|
||||
public WorkflowDefinition()
|
||||
{
|
||||
Variables = new Variables();
|
||||
Type = "Workflow";
|
||||
}
|
||||
|
||||
public int Id { get; set; }
|
||||
public string WorkflowDefinitionId { get; set; } = default!;
|
||||
public string WorkflowDefinitionVersionId { get; set; } = default!;
|
||||
public int Version { get; set; }
|
||||
public Variables? Variables { get; set; }
|
||||
public WorkflowContextOptions? ContextOptions { get; set; }
|
||||
public bool IsSingleton { get; set; }
|
||||
public WorkflowPersistenceBehavior PersistenceBehavior { get; set; }
|
||||
public bool DeleteCompletedInstances { get; set; }
|
||||
public bool IsEnabled { get; set; }
|
||||
public bool IsPublished { get; set; }
|
||||
public bool IsLatest { get; set; }
|
||||
}
|
||||
}
|
||||
17
src/clients/Elsa.Client/Models/WorkflowExecutionScope.cs
Normal file
17
src/clients/Elsa.Client/Models/WorkflowExecutionScope.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class WorkflowExecutionScope
|
||||
{
|
||||
public WorkflowExecutionScope()
|
||||
{
|
||||
Variables = new Variables();
|
||||
}
|
||||
|
||||
public WorkflowExecutionScope(Variables variables)
|
||||
{
|
||||
Variables = variables;
|
||||
}
|
||||
|
||||
public Variables Variables { get; }
|
||||
}
|
||||
}
|
||||
8
src/clients/Elsa.Client/Models/WorkflowFault.cs
Normal file
8
src/clients/Elsa.Client/Models/WorkflowFault.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class WorkflowFault
|
||||
{
|
||||
public string? FaultedActivityId { get; set; }
|
||||
public string? Message { get; set; }
|
||||
}
|
||||
}
|
||||
43
src/clients/Elsa.Client/Models/WorkflowInstance.cs
Normal file
43
src/clients/Elsa.Client/Models/WorkflowInstance.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
using System.Collections.Generic;
|
||||
using Elsa.Client.Comparers;
|
||||
using NodaTime;
|
||||
|
||||
namespace Elsa.Client.Models
|
||||
{
|
||||
public class WorkflowInstance
|
||||
{
|
||||
private HashSet<BlockingActivity> _blockingActivities = new HashSet<BlockingActivity>(BlockingActivityEqualityComparer.Instance);
|
||||
|
||||
public WorkflowInstance()
|
||||
{
|
||||
Variables = new Variables();
|
||||
Activities = new List<ActivityInstance>();
|
||||
ExecutionLog = new List<ExecutionLogEntry>();
|
||||
ScheduledActivities = new Stack<ScheduledActivity>();
|
||||
PostScheduledActivities = new Stack<ScheduledActivity>();
|
||||
}
|
||||
|
||||
public int Id { get; set; }
|
||||
public string WorkflowInstanceId { get; set; } = default!;
|
||||
public string WorkflowDefinitionId { get; set; } = default!;
|
||||
public int Version { get; set; }
|
||||
public WorkflowStatus Status { get; set; }
|
||||
public string? CorrelationId { get; set; }
|
||||
public string? ContextId { get; set; }
|
||||
public Instant CreatedAt { get; set; }
|
||||
public Variables Variables { get; set; }
|
||||
public object? Output { get; set; }
|
||||
public ICollection<ActivityInstance> Activities { get; set; }
|
||||
|
||||
public HashSet<BlockingActivity> BlockingActivities
|
||||
{
|
||||
get => _blockingActivities;
|
||||
set => _blockingActivities = new HashSet<BlockingActivity>(value, BlockingActivityEqualityComparer.Instance);
|
||||
}
|
||||
|
||||
public ICollection<ExecutionLogEntry> ExecutionLog { get; set; }
|
||||
public WorkflowFault? Fault { get; set; }
|
||||
public Stack<ScheduledActivity> ScheduledActivities { get; set; }
|
||||
public Stack<ScheduledActivity> PostScheduledActivities { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
namespace Elsa.Client.Models
|
||||
{
|
||||
public enum WorkflowPersistenceBehavior
|
||||
{
|
||||
/// <summary>
|
||||
/// Workflow instances are persisted only when being suspended.
|
||||
/// </summary>
|
||||
Suspended,
|
||||
|
||||
/// <summary>
|
||||
/// Workflow instances are persisted after the workflow executed scheduled activities.
|
||||
/// </summary>
|
||||
WorkflowPassCompleted,
|
||||
|
||||
/// <summary>
|
||||
/// Workflow instances are persisted after each activity that executed.
|
||||
/// </summary>
|
||||
ActivityExecuted
|
||||
}
|
||||
}
|
||||
12
src/clients/Elsa.Client/Models/WorkflowStatus.cs
Normal file
12
src/clients/Elsa.Client/Models/WorkflowStatus.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
namespace Elsa.Client.Models
|
||||
{
|
||||
public enum WorkflowStatus
|
||||
{
|
||||
Idle,
|
||||
Running,
|
||||
Finished,
|
||||
Suspended,
|
||||
Faulted,
|
||||
Cancelled
|
||||
}
|
||||
}
|
||||
16
src/clients/Elsa.Client/Services/IWorkflowDefinitionsApi.cs
Normal file
16
src/clients/Elsa.Client/Services/IWorkflowDefinitionsApi.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Elsa.Client.Models;
|
||||
using Refit;
|
||||
|
||||
namespace Elsa.Client.Services
|
||||
{
|
||||
public interface IWorkflowDefinitionsApi
|
||||
{
|
||||
[Get("/v1/workflow-definitions/{id}/latest")]
|
||||
Task<WorkflowDefinition> GetLatestAsync([AliasAs("id")] string workflowDefinitionId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Get("/v1/workflow-definitions/{id}/published")]
|
||||
Task<WorkflowDefinition> GetPublishedAsync([AliasAs("id")] string workflowDefinitionId, CancellationToken cancellationToken = default);
|
||||
}
|
||||
}
|
||||
|
|
@ -42,19 +42,16 @@ namespace Elsa
|
|||
}
|
||||
|
||||
public static T GetActivityState<TActivity, T>(
|
||||
this IWorkflowBlueprint workflowBlueprint,
|
||||
string activityId,
|
||||
this IWorkflowBlueprint workflowBlueprint,
|
||||
Expression<Func<TActivity, T>> propertyExpression,
|
||||
ActivityExecutionContext activityExecutionContext) where TActivity : IActivity
|
||||
{
|
||||
var expression = (MemberExpression)propertyExpression.Body;
|
||||
string propertyName = expression.Member.Name;
|
||||
return GetActivityState<T>(workflowBlueprint, activityId, propertyName, activityExecutionContext);
|
||||
return GetActivityState<T>(propertyName, activityExecutionContext);
|
||||
}
|
||||
|
||||
public static T GetActivityState<T>(
|
||||
this IWorkflowBlueprint workflowBlueprint,
|
||||
string activityId,
|
||||
string propertyName,
|
||||
ActivityExecutionContext activityExecutionContext)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using Elsa.Converters;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Elsa.Models
|
||||
{
|
||||
|
|
@ -19,7 +21,7 @@ namespace Elsa.Models
|
|||
Type = type;
|
||||
}
|
||||
|
||||
public Type Type { get; set; } = default!;
|
||||
[JsonConverter(typeof(TypeConverter))] public Type Type { get; set; } = default!;
|
||||
public string Syntax { get; set; } = default!;
|
||||
public string Expression { get; set; } = default!;
|
||||
}
|
||||
|
|
|
|||
15
src/core/Elsa.Abstractions/Models/WorkflowContextFidelity.cs
Normal file
15
src/core/Elsa.Abstractions/Models/WorkflowContextFidelity.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
namespace Elsa.Models
|
||||
{
|
||||
public enum WorkflowContextFidelity
|
||||
{
|
||||
/// <summary>
|
||||
/// The workflow context is loaded only once per burst of execution.
|
||||
/// </summary>
|
||||
Burst,
|
||||
|
||||
/// <summary>
|
||||
/// The workflow context is loaded before executing an activity.
|
||||
/// </summary>
|
||||
Activity
|
||||
}
|
||||
}
|
||||
11
src/core/Elsa.Abstractions/Models/WorkflowContextOptions.cs
Normal file
11
src/core/Elsa.Abstractions/Models/WorkflowContextOptions.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using Elsa.Services.Models;
|
||||
|
||||
namespace Elsa.Models
|
||||
{
|
||||
public class WorkflowContextOptions
|
||||
{
|
||||
public Type ContextType { get; set; } = default!;
|
||||
public WorkflowContextFidelity ContextFidelity { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -11,9 +11,10 @@ namespace Elsa.Services
|
|||
{
|
||||
public interface IWorkflowDefinitionManager
|
||||
{
|
||||
ValueTask SaveAsync(WorkflowDefinition workflowDefinition, CancellationToken cancellationToken = default);
|
||||
ValueTask DeleteAsync(WorkflowDefinition workflowDefinition, CancellationToken cancellationToken = default);
|
||||
ValueTask<IEnumerable<WorkflowDefinition>> ListAsync(CancellationToken cancellationToken = default);
|
||||
Task SaveAsync(WorkflowDefinition workflowDefinition, CancellationToken cancellationToken = default);
|
||||
Task DeleteAsync(WorkflowDefinition workflowDefinition, CancellationToken cancellationToken = default);
|
||||
Task<int> CountAsync(VersionOptions? version = default, CancellationToken cancellationToken = default);
|
||||
Task<IEnumerable<WorkflowDefinition>> ListAsync(int? skip = default, int? take = default, VersionOptions? version = default, CancellationToken cancellationToken = default);
|
||||
IQuery<WorkflowDefinition> Query();
|
||||
IQuery<WorkflowDefinition, TIndex> Query<TIndex>() where TIndex : class, IIndex;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@ namespace Elsa.Triggers
|
|||
public T GetState<T>(Expression<Func<TActivity, T>> propertyExpression)
|
||||
{
|
||||
var workflowBlueprint = _activityExecutionContext.WorkflowExecutionContext.WorkflowBlueprint;
|
||||
var activityId = _activityExecutionContext.ActivityBlueprint.Id;
|
||||
return workflowBlueprint.GetActivityState(activityId, propertyExpression, _activityExecutionContext);
|
||||
return workflowBlueprint.GetActivityState(propertyExpression, _activityExecutionContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ using System.Linq.Expressions;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Elsa.Data;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Models;
|
||||
using YesSql;
|
||||
using YesSql.Indexes;
|
||||
|
|
@ -19,19 +20,36 @@ namespace Elsa.Services
|
|||
_session = session;
|
||||
}
|
||||
|
||||
public ValueTask SaveAsync(WorkflowDefinition workflowDefinition, CancellationToken cancellationToken = default)
|
||||
public Task SaveAsync(WorkflowDefinition workflowDefinition, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_session.Save(workflowDefinition, CollectionNames.WorkflowDefinitions);
|
||||
return new ValueTask();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public ValueTask DeleteAsync(WorkflowDefinition workflowDefinition, CancellationToken cancellationToken = default)
|
||||
public Task DeleteAsync(WorkflowDefinition workflowDefinition, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_session.Delete(workflowDefinition, CollectionNames.WorkflowDefinitions);
|
||||
return new ValueTask();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async Task<int> CountAsync(VersionOptions? version = default, CancellationToken cancellationToken = default) =>
|
||||
await Query()
|
||||
.WithVersion(version ?? VersionOptions.Published)
|
||||
.CountAsync();
|
||||
|
||||
public async Task<IEnumerable<WorkflowDefinition>> ListAsync(int? skip = default, int? take = default, VersionOptions? version = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var query = Query().WithVersion(version ?? VersionOptions.Published);
|
||||
|
||||
if (skip != null)
|
||||
query = query.Skip(skip.Value);
|
||||
|
||||
if (take != null)
|
||||
query = query.Take(take.Value);
|
||||
|
||||
return await query.ListAsync();
|
||||
}
|
||||
|
||||
public async ValueTask<IEnumerable<WorkflowDefinition>> ListAsync(CancellationToken cancellationToken = default) => await Query().ListAsync();
|
||||
public IQuery<WorkflowDefinition> Query() => _session.Query<WorkflowDefinition>(CollectionNames.WorkflowDefinitions);
|
||||
public IQuery<WorkflowDefinition, TIndex> Query<TIndex>() where TIndex : class, IIndex => _session.Query<WorkflowDefinition, TIndex>(CollectionNames.WorkflowDefinitions);
|
||||
public IQuery<WorkflowDefinition, TIndex> Query<TIndex>(Expression<Func<TIndex, bool>> predicate) where TIndex : class, IIndex => _session.Query<WorkflowDefinition, TIndex>(predicate, CollectionNames.WorkflowDefinitions);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace Elsa.WorkflowProviders
|
|||
|
||||
protected override async ValueTask<IEnumerable<IWorkflowBlueprint>> OnGetWorkflowsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var workflowDefinitions = await _workflowDefinitionManager.ListAsync(cancellationToken);
|
||||
var workflowDefinitions = await _workflowDefinitionManager.ListAsync(cancellationToken: cancellationToken);
|
||||
return workflowDefinitions.Select(_workflowBlueprintMaterializer.CreateWorkflowBlueprint);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="4.2.0" />
|
||||
<PackageReference Include="NodaTime.Serialization.SystemTextJson" Version="1.0.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="6.0.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.6.3" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,32 +1,41 @@
|
|||
using System.Threading;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.Models;
|
||||
using Elsa.Serialization;
|
||||
using Elsa.Server.Api.Swagger;
|
||||
using Elsa.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using Swashbuckle.AspNetCore.Filters;
|
||||
|
||||
namespace Elsa.Server.Api.Endpoints.WorkflowDefinitions
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1")]
|
||||
[Route("v{version:apiVersion}/workflow-definitions/{id}")]
|
||||
[Route("v{version:apiVersion}/workflow-definitions/{id:int}")]
|
||||
[Produces("application/json")]
|
||||
public class Get : Controller
|
||||
{
|
||||
private readonly IWorkflowDefinitionManager _workflowDefinitionManager;
|
||||
private readonly IContentSerializer _serializer;
|
||||
|
||||
public Get(IWorkflowDefinitionManager workflowDefinitionManager, IContentSerializer serializer)
|
||||
protected Get(IWorkflowDefinitionManager workflowDefinitionManager, IContentSerializer serializer)
|
||||
{
|
||||
_serializer = serializer;
|
||||
_workflowDefinitionManager = workflowDefinitionManager;
|
||||
_serializer = serializer;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Handle([FromRoute(Name = "id")] string workflowDefinitionId, CancellationToken cancellationToken)
|
||||
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(WorkflowDefinition))]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[SwaggerResponseExample(StatusCodes.Status200OK, typeof(WorkflowDefinitionExample))]
|
||||
public async Task<IActionResult> Handle(string workflowDefinitionId, VersionOptions? version = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var workflowDefinition = await _workflowDefinitionManager.GetAsync(workflowDefinitionId, VersionOptions.Latest, cancellationToken);
|
||||
return workflowDefinition == null ? (IActionResult)NotFound() : Json(workflowDefinition, _serializer.GetSettings());
|
||||
var workflowDefinition = await _workflowDefinitionManager.GetAsync(workflowDefinitionId, version ?? VersionOptions.Latest, cancellationToken);
|
||||
return workflowDefinition == null ? (IActionResult) NotFound() : Json(workflowDefinition, _serializer.GetSettings());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Elsa.Models;
|
||||
using Elsa.Serialization;
|
||||
using Elsa.Server.Api.Models;
|
||||
using Elsa.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Elsa.Server.Api.Endpoints.WorkflowDefinitions
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1")]
|
||||
[Route("v{version:apiVersion}/workflow-definitions")]
|
||||
[Produces("application/json")]
|
||||
public class List : Controller
|
||||
{
|
||||
private readonly IWorkflowDefinitionManager _workflowDefinitionManager;
|
||||
private readonly IContentSerializer _serializer;
|
||||
|
||||
public List(IWorkflowDefinitionManager workflowDefinitionManager, IContentSerializer serializer)
|
||||
{
|
||||
_workflowDefinitionManager = workflowDefinitionManager;
|
||||
_serializer = serializer;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<PagedList<WorkflowDefinition>>> Handle(int page = 0, int pageSize = 50, VersionOptions? version = default, CancellationToken cancellationToken = default)
|
||||
{
|
||||
version ??= VersionOptions.Latest;
|
||||
var totalCount = await _workflowDefinitionManager.CountAsync(version, cancellationToken);
|
||||
var items = await _workflowDefinitionManager.ListAsync(page, pageSize, version, cancellationToken);
|
||||
var pagedList = new PagedList<WorkflowDefinition>(items, page, pageSize, totalCount);
|
||||
|
||||
return Json(pagedList, _serializer.GetSettings());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,18 +2,18 @@
|
|||
using System.Threading.Tasks;
|
||||
using Elsa.Services;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using YesSql;
|
||||
|
||||
namespace Elsa.Server.Api.Endpoints.WorkflowDefinitions
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1")]
|
||||
[Route("v{version:apiVersion}/workflow-definitions")]
|
||||
[Produces("application/json")]
|
||||
public class Post : ControllerBase
|
||||
{
|
||||
private readonly IWorkflowPublisher _workflowPublisher;
|
||||
|
||||
public Post(IWorkflowDefinitionManager workflowDefinitionManager, IWorkflowPublisher workflowPublisher, ISession session)
|
||||
public Post(IWorkflowPublisher workflowPublisher)
|
||||
{
|
||||
_workflowPublisher = workflowPublisher;
|
||||
}
|
||||
|
|
|
|||
21
src/server/Elsa.Server.Api/Models/PagedList.cs
Normal file
21
src/server/Elsa.Server.Api/Models/PagedList.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Elsa.Server.Api.Models
|
||||
{
|
||||
public class PagedList<T>
|
||||
{
|
||||
public PagedList(IEnumerable<T> items, int page, int pageSize, int totalCount)
|
||||
{
|
||||
Page = page;
|
||||
PageSize = pageSize;
|
||||
TotalCount = totalCount;
|
||||
Items = items.ToList();
|
||||
}
|
||||
|
||||
public ICollection<T> Items { get; }
|
||||
public int Page { get; }
|
||||
public int PageSize { get; }
|
||||
public int TotalCount { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
using System.Collections.Generic;
|
||||
using Elsa.Models;
|
||||
using Swashbuckle.AspNetCore.Filters;
|
||||
|
||||
namespace Elsa.Server.Api.Swagger
|
||||
{
|
||||
public class WorkflowDefinitionExample : IExamplesProvider<WorkflowDefinition>
|
||||
{
|
||||
public WorkflowDefinition GetExamples()
|
||||
{
|
||||
return new WorkflowDefinition
|
||||
{
|
||||
Id = 1,
|
||||
Name = "ProcessOrderWorkflow",
|
||||
DisplayName = "Process Order Workflow",
|
||||
Description = "Process new orders",
|
||||
Version = 1,
|
||||
IsPublished = true,
|
||||
WorkflowDefinitionId = "26bd1dca39954c8f93364a18c2a35528",
|
||||
WorkflowDefinitionVersionId = "c8c57402e68949598a45411c74e463e1",
|
||||
Type = "Workflow",
|
||||
ContextOptions = new WorkflowContextOptions
|
||||
{
|
||||
ContextFidelity = WorkflowContextFidelity.Burst,
|
||||
ContextType = typeof(Order)
|
||||
},
|
||||
Activities = new[]
|
||||
{
|
||||
new ActivityDefinition
|
||||
{
|
||||
ActivityId = "activity-1",
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class Order
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1,26 +1,13 @@
|
|||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:11000"
|
||||
"profiles": {
|
||||
"Elsa.Server.Host": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "http://localhost:11000",
|
||||
"launchUrl": "http://localhost:11000/swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": false,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"Elsa.Server.Host": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "http://localhost:11000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Elsa.Runtime;
|
||||
using Elsa.Server.Api.Swagger;
|
||||
using Elsa.StartupTasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
|
@ -6,6 +7,7 @@ using Microsoft.Extensions.Configuration;
|
|||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.Filters;
|
||||
using YesSql.Provider.Sqlite;
|
||||
|
||||
namespace Elsa.Server.Host
|
||||
|
|
@ -31,8 +33,12 @@ namespace Elsa.Server.Host
|
|||
elsa => elsa
|
||||
.UsePersistence(config => config.UseSqLite(connectionString)));
|
||||
|
||||
services.AddSingleton<WorkflowDefinitionExample>();
|
||||
services
|
||||
.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo {Title = "Elsa", Version = "v1"}); })
|
||||
.AddSwaggerGen(c =>
|
||||
{
|
||||
c.SwaggerDoc("v1", new OpenApiInfo {Title = "Elsa", Version = "v1"});
|
||||
})
|
||||
.AddElsaApiEndpoints()
|
||||
.AddCors(
|
||||
options => options.AddDefaultPolicy(
|
||||
|
|
|
|||
Loading…
Reference in a new issue