diff --git a/src/api/Synapse.Api.Application/Synapse.Api.Application.csproj b/src/api/Synapse.Api.Application/Synapse.Api.Application.csproj
index 8f4fbadcc..559ef2c7c 100644
--- a/src/api/Synapse.Api.Application/Synapse.Api.Application.csproj
+++ b/src/api/Synapse.Api.Application/Synapse.Api.Application.csproj
@@ -7,7 +7,7 @@
en
True
1.0.0
- alpha5
+ alpha5.1
$(VersionPrefix)
$(VersionPrefix)
The Synapse Authors
diff --git a/src/api/Synapse.Api.Client.Core/Synapse.Api.Client.Core.csproj b/src/api/Synapse.Api.Client.Core/Synapse.Api.Client.Core.csproj
index 485ea739a..0ff59e430 100644
--- a/src/api/Synapse.Api.Client.Core/Synapse.Api.Client.Core.csproj
+++ b/src/api/Synapse.Api.Client.Core/Synapse.Api.Client.Core.csproj
@@ -7,7 +7,7 @@
en
True
1.0.0
- alpha5
+ alpha5.1
$(VersionPrefix)
$(VersionPrefix)
The Synapse Authors
diff --git a/src/api/Synapse.Api.Client.Http/Synapse.Api.Client.Http.csproj b/src/api/Synapse.Api.Client.Http/Synapse.Api.Client.Http.csproj
index 4fabc3bea..2282c9d6d 100644
--- a/src/api/Synapse.Api.Client.Http/Synapse.Api.Client.Http.csproj
+++ b/src/api/Synapse.Api.Client.Http/Synapse.Api.Client.Http.csproj
@@ -7,7 +7,7 @@
en
True
1.0.0
- alpha5
+ alpha5.1
$(VersionPrefix)
$(VersionPrefix)
The Synapse Authors
diff --git a/src/api/Synapse.Api.Http/Synapse.Api.Http.csproj b/src/api/Synapse.Api.Http/Synapse.Api.Http.csproj
index 06f850c6a..06e7b3221 100644
--- a/src/api/Synapse.Api.Http/Synapse.Api.Http.csproj
+++ b/src/api/Synapse.Api.Http/Synapse.Api.Http.csproj
@@ -8,7 +8,7 @@
Library
True
1.0.0
- alpha5
+ alpha5.1
$(VersionPrefix)
$(VersionPrefix)
The Synapse Authors
diff --git a/src/api/Synapse.Api.Server/Synapse.Api.Server.csproj b/src/api/Synapse.Api.Server/Synapse.Api.Server.csproj
index d4fd6f08f..91debeaf9 100644
--- a/src/api/Synapse.Api.Server/Synapse.Api.Server.csproj
+++ b/src/api/Synapse.Api.Server/Synapse.Api.Server.csproj
@@ -7,7 +7,7 @@
en
True
1.0.0
- alpha5
+ alpha5.1
$(VersionPrefix)
$(VersionPrefix)
The Synapse Authors
diff --git a/src/cli/Synapse.Cli/Synapse.Cli.csproj b/src/cli/Synapse.Cli/Synapse.Cli.csproj
index a49ae597f..fafc6e667 100644
--- a/src/cli/Synapse.Cli/Synapse.Cli.csproj
+++ b/src/cli/Synapse.Cli/Synapse.Cli.csproj
@@ -8,7 +8,7 @@
en
True
1.0.0
- alpha5
+ alpha5.1
$(VersionPrefix)
$(VersionPrefix)
The Synapse Authors
diff --git a/src/core/Synapse.Core.Infrastructure.Containers.Docker/Synapse.Core.Infrastructure.Containers.Docker.csproj b/src/core/Synapse.Core.Infrastructure.Containers.Docker/Synapse.Core.Infrastructure.Containers.Docker.csproj
index a527a1ec3..b86f9e08c 100644
--- a/src/core/Synapse.Core.Infrastructure.Containers.Docker/Synapse.Core.Infrastructure.Containers.Docker.csproj
+++ b/src/core/Synapse.Core.Infrastructure.Containers.Docker/Synapse.Core.Infrastructure.Containers.Docker.csproj
@@ -7,7 +7,7 @@
en
True
1.0.0
- alpha5
+ alpha5.1
$(VersionPrefix)
$(VersionPrefix)
The Synapse Authors
diff --git a/src/core/Synapse.Core.Infrastructure.Containers.Kubernetes/Synapse.Core.Infrastructure.Containers.Kubernetes.csproj b/src/core/Synapse.Core.Infrastructure.Containers.Kubernetes/Synapse.Core.Infrastructure.Containers.Kubernetes.csproj
index 58747907c..980efb526 100644
--- a/src/core/Synapse.Core.Infrastructure.Containers.Kubernetes/Synapse.Core.Infrastructure.Containers.Kubernetes.csproj
+++ b/src/core/Synapse.Core.Infrastructure.Containers.Kubernetes/Synapse.Core.Infrastructure.Containers.Kubernetes.csproj
@@ -7,7 +7,7 @@
en
True
1.0.0
- alpha5
+ alpha5.1
$(VersionPrefix)
$(VersionPrefix)
The Synapse Authors
diff --git a/src/core/Synapse.Core.Infrastructure/Synapse.Core.Infrastructure.csproj b/src/core/Synapse.Core.Infrastructure/Synapse.Core.Infrastructure.csproj
index 5d4d4e5b7..b5048f7e0 100644
--- a/src/core/Synapse.Core.Infrastructure/Synapse.Core.Infrastructure.csproj
+++ b/src/core/Synapse.Core.Infrastructure/Synapse.Core.Infrastructure.csproj
@@ -7,7 +7,7 @@
en
True
1.0.0
- alpha5
+ alpha5.1
$(VersionPrefix)
$(VersionPrefix)
The Synapse Authors
diff --git a/src/core/Synapse.Core/Synapse.Core.csproj b/src/core/Synapse.Core/Synapse.Core.csproj
index 537f04d4c..fb8f03500 100644
--- a/src/core/Synapse.Core/Synapse.Core.csproj
+++ b/src/core/Synapse.Core/Synapse.Core.csproj
@@ -7,7 +7,7 @@
en
True
1.0.0
- alpha5
+ alpha5.1
$(VersionPrefix)
$(VersionPrefix)
The Synapse Authors
diff --git a/src/correlator/Synapse.Correlator/Synapse.Correlator.csproj b/src/correlator/Synapse.Correlator/Synapse.Correlator.csproj
index 5c2f612f7..b3eaf33d9 100644
--- a/src/correlator/Synapse.Correlator/Synapse.Correlator.csproj
+++ b/src/correlator/Synapse.Correlator/Synapse.Correlator.csproj
@@ -8,7 +8,7 @@
en
True
1.0.0
- alpha5
+ alpha5.1
$(VersionPrefix)
$(VersionPrefix)
The Synapse Authors
diff --git a/src/dashboard/Synapse.Dashboard/Components/WorkflowInstancesList/WorkflowInstancesList.razor b/src/dashboard/Synapse.Dashboard/Components/WorkflowInstancesList/WorkflowInstancesList.razor
index 361353a1e..13597314d 100644
--- a/src/dashboard/Synapse.Dashboard/Components/WorkflowInstancesList/WorkflowInstancesList.razor
+++ b/src/dashboard/Synapse.Dashboard/Components/WorkflowInstancesList/WorkflowInstancesList.razor
@@ -58,7 +58,10 @@
await OnShowClickedAsync(instance)" class="cursor-pointer @(ActiveRow == instance.GetName() ? "table-active" : "")">
@foreach (var column in knownColumns)
{
- if ((Columns.Count() == 0 && column != "Delete") || Columns.Contains(column))
+ if ((Columns.Count() == 0 && !DirectActions.Contains(column)) || Columns.Contains(column))
{
@switch(column)
@@ -144,16 +147,44 @@
break;
+ case "Resume":
+ @if (instance.Status?.Phase == WorkflowInstanceStatusPhase.Running)
+ {
+
+ }
+ @if (instance.Status?.Phase == WorkflowInstanceStatusPhase.Suspended)
+ {
+
+ }
+ break;
+ case "Cancel":
+ @if (instance.IsOperative)
+ {
+
+ }
+ break;
case "Replay":
-
+
break;
case "Delete":
-
+
break;
default:
break;
@@ -208,9 +239,21 @@
[Parameter] public EventCallback OnToggleSelected { get; set; }
[Parameter] public EventCallback OnDelete { get; set; }
[Parameter] public EventCallback OnReplay { get; set; }
+ [Parameter] public EventCallback OnSuspend { get; set; }
+ [Parameter] public EventCallback OnResume { get; set; }
+ [Parameter] public EventCallback OnCancel { get; set; }
[Parameter] public EventCallback OnDeleteSelected { get; set; }
+ [Parameter] public EventCallback OnSuspendSelected { get; set; }
+ [Parameter] public EventCallback OnResumeSelected { get; set; }
+ [Parameter] public EventCallback OnCancelSelected { get; set; }
- IEnumerable knownColumns = [
+ public static IEnumerable DirectActions = [
+ "Resume",
+ "Cancel",
+ "Replay",
+ "Delete"
+ ];
+ static IEnumerable knownColumns = [
"Name",
"Namespace",
"Definition",
@@ -221,8 +264,7 @@
"Duration",
"Operator",
"Actions",
- "Replay",
- "Delete"
+ ..DirectActions
];
ElementReference checkboxAll = default!;
@@ -324,11 +366,14 @@
///
string GetColumnAlignment(string column)
{
- return column == "Name" || column == "Namespace"
- ? "start"
- : column == "Action"
- ? "end"
- : "center";
+ return (
+ column == "Name" || column == "Namespace"
+ ? "start"
+ : column == "Action"
+ ? "end"
+ : "center"
+ )
+ + (DirectActions.Contains(column) ? " p-0": "");
}
///
@@ -385,7 +430,7 @@
///
/// Handles the click on the show button
///
- ///
+ /// The instance to show
///
protected async Task OnShowClickedAsync(WorkflowInstance instance)
{
@@ -398,7 +443,7 @@
///
/// Handles the click on the delete button
///
- ///
+ /// The instance to delete
///
protected async Task OnDeleteClickedAsync(WorkflowInstance instance)
{
@@ -411,7 +456,7 @@
///
/// Handles the click on the replay button
///
- ///
+ /// The instance to replay
///
protected async Task OnReplayClickedAsync(WorkflowInstance instance)
{
@@ -420,4 +465,94 @@
await this.OnReplay.InvokeAsync(instance);
}
}
+
+ ///
+ /// Handles the click on the suspend button
+ ///
+ /// The instance to suspend
+ ///
+ protected async Task OnSuspendClickedAsync(WorkflowInstance instance)
+ {
+ if (this.OnSuspend.HasDelegate)
+ {
+ await this.OnSuspend.InvokeAsync(instance);
+ }
+ }
+
+ ///
+ /// Handles the click on the resume button
+ ///
+ /// The instance to resume
+ ///
+ protected async Task OnResumeClickedAsync(WorkflowInstance instance)
+ {
+ if (this.OnResume.HasDelegate)
+ {
+ await this.OnResume.InvokeAsync(instance);
+ }
+ }
+
+ ///
+ /// Handles the click on the cancel button
+ ///
+ /// The instance to cancel
+ ///
+ protected async Task OnCancelClickedAsync(WorkflowInstance instance)
+ {
+ if (this.OnCancel.HasDelegate)
+ {
+ await this.OnCancel.InvokeAsync(instance);
+ }
+ }
+
+ protected async Task OnSuspendSelectedClickedAsync()
+ {
+ var selected = selectedInstanceNames.ToList();
+ var nonRuningInstances = (WorkflowInstances??[]).Where(instance => selected.Contains(instance.GetName()) && instance.Status?.Phase != WorkflowInstanceStatusPhase.Running);
+ foreach(var instance in nonRuningInstances)
+ {
+ if (this.OnToggleSelected.HasDelegate)
+ {
+ await OnToggleSelected.InvokeAsync(instance.GetName());
+ }
+ }
+ if (this.OnSuspendSelected.HasDelegate)
+ {
+ await OnSuspendSelected.InvokeAsync();
+ }
+ }
+
+ protected async Task OnResumeSelectedClickedAsync()
+ {
+ var selected = selectedInstanceNames.ToList();
+ var nonSuspendedInstances = (WorkflowInstances ?? []).Where(instance => selected.Contains(instance.GetName()) && instance.Status?.Phase != WorkflowInstanceStatusPhase.Suspended);
+ foreach (var instance in nonSuspendedInstances)
+ {
+ if (this.OnToggleSelected.HasDelegate)
+ {
+ await OnToggleSelected.InvokeAsync(instance.GetName());
+ }
+ }
+ if (this.OnResumeSelected.HasDelegate)
+ {
+ await OnResumeSelected.InvokeAsync();
+ }
+ }
+
+ protected async Task OnCancelSelectedClickedAsync()
+ {
+ var selected = selectedInstanceNames.ToList();
+ var nonOperativeInstances = (WorkflowInstances ?? []).Where(instance => selected.Contains(instance.GetName()) && !instance.IsOperative);
+ foreach (var instance in nonOperativeInstances)
+ {
+ if (this.OnToggleSelected.HasDelegate)
+ {
+ await OnToggleSelected.InvokeAsync(instance.GetName());
+ }
+ }
+ if (this.OnCancelSelected.HasDelegate)
+ {
+ await OnCancelSelected.InvokeAsync();
+ }
+ }
}
\ No newline at end of file
diff --git a/src/dashboard/Synapse.Dashboard/Extensions/StatusExtensions.cs b/src/dashboard/Synapse.Dashboard/Extensions/StatusExtensions.cs
index 5ac8ccb70..3100b332e 100644
--- a/src/dashboard/Synapse.Dashboard/Extensions/StatusExtensions.cs
+++ b/src/dashboard/Synapse.Dashboard/Extensions/StatusExtensions.cs
@@ -43,6 +43,7 @@ public static class StatusExtensions
//CorrelationContextStatus.Completed => "success",
WorkflowInstanceStatusPhase.Waiting => "cinereous",
TaskInstanceStatus.Suspended => "icterine",
+ //WorkflowInstanceStatusPhase.Suspended => "icterine",
TaskInstanceStatus.Skipped => "cinereous",
WorkflowInstanceStatusPhase.Pending => "mute",
//TaskInstanceStatus.Pending => "mute",
diff --git a/src/dashboard/Synapse.Dashboard/Pages/Workflows/Details/Store.cs b/src/dashboard/Synapse.Dashboard/Pages/Workflows/Details/Store.cs
index 8bff87e2a..46e7b08ec 100644
--- a/src/dashboard/Synapse.Dashboard/Pages/Workflows/Details/Store.cs
+++ b/src/dashboard/Synapse.Dashboard/Pages/Workflows/Details/Store.cs
@@ -12,6 +12,7 @@
// limitations under the License.
using Neuroglia.Blazor.Dagre.Models;
+using Neuroglia.Data.Infrastructure.ResourceOriented;
using ServerlessWorkflow.Sdk.Models;
using Synapse.Api.Client.Services;
using Synapse.Dashboard.Components.DocumentDetailsStateManagement;
@@ -318,9 +319,12 @@ public async Task OnCopyToClipboard()
}
}
+
///
/// Displays the modal used to provide the new workflow input
///
+ /// The definition to start a new instance of
+ /// A default input payload, if any
/// A awaitable task
public async Task OnShowCreateInstanceAsync(WorkflowDefinition workflowDefinition, EquatableDictionary? input = null)
{
@@ -336,6 +340,90 @@ public async Task OnShowCreateInstanceAsync(WorkflowDefinition workflowDefinitio
}
}
+ ///
+ /// Suspends the provided instance
+ ///
+ /// The instance to suspend
+ /// A awaitable task
+ public async Task SuspendInstanceAsync(WorkflowInstance workflowInstance)
+ {
+ await this.ApiClient.WorkflowInstances.SuspendAsync(workflowInstance.GetName(), workflowInstance.GetNamespace()!).ConfigureAwait(false);
+ }
+
+ ///
+ /// Resumes the provided instance
+ ///
+ /// The instance to resume
+ /// A awaitable task
+ public async Task ResumeInstanceAsync(WorkflowInstance workflowInstance)
+ {
+ await this.ApiClient.WorkflowInstances.ResumeAsync(workflowInstance.GetName(), workflowInstance.GetNamespace()!).ConfigureAwait(false);
+ }
+
+ ///
+ /// Cancels the provided instance
+ ///
+ /// The instance to resume
+ /// A awaitable task
+ public async Task CancelInstanceAsync(WorkflowInstance workflowInstance)
+ {
+ await this.ApiClient.WorkflowInstances.CancelAsync(workflowInstance.GetName(), workflowInstance.GetNamespace()!).ConfigureAwait(false);
+ }
+
+ ///
+ /// Suspends selected instances
+ ///
+ /// A awaitable task
+ public async Task OnSuspendSelectedInstancesAsync()
+ {
+ var selectedResourcesNames = this.Get(state => state.SelectedResourceNames);
+ var resources = (this.Get(state => state.Resources) ?? []).Where(resource => selectedResourcesNames.Contains(resource.GetName()));
+ foreach (var resource in resources)
+ {
+ await this.SuspendInstanceAsync(resource);
+ }
+ this.Reduce(state => state with
+ {
+ SelectedResourceNames = []
+ });
+ }
+
+ ///
+ /// Resumes selected instances
+ ///
+ /// A awaitable task
+ public async Task OnResumeSelectedInstancesAsync()
+ {
+ var selectedResourcesNames = this.Get(state => state.SelectedResourceNames);
+ var resources = (this.Get(state => state.Resources) ?? []).Where(resource => selectedResourcesNames.Contains(resource.GetName()));
+ foreach (var resource in resources)
+ {
+ await this.ResumeInstanceAsync(resource);
+ }
+ this.Reduce(state => state with
+ {
+ SelectedResourceNames = []
+ });
+ }
+
+ ///
+ /// Cancels selected instances
+ ///
+ /// A awaitable task
+ public async Task OnCancelSelectedInstancesAsync()
+ {
+ var selectedResourcesNames = this.Get(state => state.SelectedResourceNames);
+ var resources = (this.Get(state => state.Resources) ?? []).Where(resource => selectedResourcesNames.Contains(resource.GetName()));
+ foreach (var resource in resources)
+ {
+ await this.CancelInstanceAsync(resource);
+ }
+ this.Reduce(state => state with
+ {
+ SelectedResourceNames = []
+ });
+ }
+
///
/// Creates a new instance of the workflow
///
diff --git a/src/dashboard/Synapse.Dashboard/Pages/Workflows/Details/View.razor b/src/dashboard/Synapse.Dashboard/Pages/Workflows/Details/View.razor
index 90d274868..401e2a733 100644
--- a/src/dashboard/Synapse.Dashboard/Pages/Workflows/Details/View.razor
+++ b/src/dashboard/Synapse.Dashboard/Pages/Workflows/Details/View.razor
@@ -36,9 +36,15 @@
Columns="@columns"
OnSearchInput="Store.SetSearchTerm"
OnShowDetails="OnShowInstanceDetails"
+ OnSuspend="async (instance) => await Store.SuspendInstanceAsync(instance)"
+ OnResume="async (instance) => await Store.ResumeInstanceAsync(instance)"
+ OnCancel="async (instance) => await Store.CancelInstanceAsync(instance)"
+ OnReplay="async (instance) => await Store.OnShowCreateInstanceAsync(workflowDefinition, instance.Spec?.Input)"
OnDelete="OnDeleteWorkflowInstanceAsync"
- OnReplay="async instance => await Store.OnShowCreateInstanceAsync(workflowDefinition, instance.Spec?.Input)"
OnToggleSelected="Store.ToggleResourceSelection"
+ OnSuspendSelected="async () => await Store.OnSuspendSelectedInstancesAsync()"
+ OnResumeSelected="async () => await Store.OnResumeSelectedInstancesAsync()"
+ OnCancelSelected="async () => await Store.OnCancelSelectedInstancesAsync()"
OnDeleteSelected="OnDeleteSelectedResourcesAsync" />
|