From 1d6c38b8f002cc135b69d6cbe77262b6fb58c9c2 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bianchi Date: Tue, 22 Jul 2025 12:55:11 +0200 Subject: [PATCH 01/23] feat(Dashboard): add the posiblity to specify a target operator when creating a workflow/workflow instance. Closes #517 Signed-off-by: Jean-Baptiste Bianchi --- .../CreateWorkflowInstanceDialog.razor | 33 ++- .../CreateWorkflowInstanceParameters.cs | 30 ++ .../Pages/Workflows/Create/State.cs | 11 + .../Pages/Workflows/Create/Store.cs | 268 ++++++++++------- .../Pages/Workflows/Create/View.razor | 21 +- .../Pages/Workflows/Details/State.cs | 10 + .../Pages/Workflows/Details/Store.cs | 274 +++++++++++------- .../Pages/Workflows/Details/View.razor | 71 +++-- .../Pages/Workflows/List/Store.cs | 17 +- .../Pages/Workflows/List/View.razor | 12 +- .../Synapse.Dashboard.csproj | 2 +- 11 files changed, 481 insertions(+), 268 deletions(-) create mode 100644 src/dashboard/Synapse.Dashboard/Components/CreateWorkflowInstanceDialog/CreateWorkflowInstanceParameters.cs diff --git a/src/dashboard/Synapse.Dashboard/Components/CreateWorkflowInstanceDialog/CreateWorkflowInstanceDialog.razor b/src/dashboard/Synapse.Dashboard/Components/CreateWorkflowInstanceDialog/CreateWorkflowInstanceDialog.razor index eab859dd1..eda273fb9 100644 --- a/src/dashboard/Synapse.Dashboard/Components/CreateWorkflowInstanceDialog/CreateWorkflowInstanceDialog.razor +++ b/src/dashboard/Synapse.Dashboard/Components/CreateWorkflowInstanceDialog/CreateWorkflowInstanceDialog.razor @@ -47,6 +47,20 @@ +
+ @if (Operators != null && Operators.Count() > 0) + { + + } +
+
} + +
+ @if (operators != null && operators.Count() > 0) + { + + } +
+ @@ -63,9 +68,9 @@ else { } @@ -158,11 +163,13 @@ readonly IEnumerable columns = [ "Name", - "Status", - "Start Time", - "End Time", - ..WorkflowInstancesList.DirectActions + "Status", + "Start Time", + "End Time", + ..WorkflowInstancesList.DirectActions ]; + protected EquatableList? operators { get; set; } + protected string? operatorName { get; set; } [Parameter] public string? Version { get; set; } [Parameter] public string? InstanceName { get; set; } @@ -174,6 +181,8 @@ UpdateBreadcrumb(); Store.WorkflowInstanceName.Subscribe(value => OnStateChanged(_ => instanceName = value), token: CancellationTokenSource.Token); Store.WorkflowDefinition.Where(value => value != null).Subscribe(value => OnStateChanged(_ => workflowDefinition = value!), token: CancellationTokenSource.Token); + Store.Operators.Subscribe(value => OnStateChanged(_ => operators = value), token: CancellationTokenSource.Token); + Store.Operator.Subscribe(value => OnStateChanged(_ => operatorName = value), token: CancellationTokenSource.Token); Store.WorkflowDefinitionVersion.Where(value => !string.IsNullOrWhiteSpace(value)).Subscribe(value => { OnStateChanged(_ => version = value!); @@ -255,8 +264,8 @@ /// The to delete protected async Task OnDeleteWorkflowInstanceAsync(WorkflowInstance instance) { - if (this.Dialog == null) return; - var confirmation = await this.Dialog.ShowAsync( + if (Dialog == null) return; + var confirmation = await Dialog.ShowAsync( title: $"Are you sure you want to delete '{instance.Metadata.Name}'?", message1: $"The workflow instance will be permanently deleted. Are you sure you want to proceed ?", confirmDialogOptions: new ConfirmDialogOptions() @@ -268,10 +277,10 @@ } ); if (!confirmation) return; - await this.Store.DeleteWorkflowInstanceAsync(instance); + await Store.DeleteWorkflowInstanceAsync(instance); } - void OnCreateWorkflowVersion() => this.NavigationManager.NavigateTo($"/workflows/new/{@namespace}/{Name}"); + void OnCreateWorkflowVersion() => NavigationManager.NavigateTo($"/workflows/new/{@namespace}/{Name}"); void OnShowInstanceDetails(WorkflowInstance instance) => NavigationManager.NavigateTo($"/workflows/details/{@namespace}/{Name}/{version}/{instance.GetName()}"); @@ -286,7 +295,7 @@ void OnDismissProblemDetails() { - this.Store.SetProblemDetails(null); + Store.SetProblemDetails(null); } } diff --git a/src/dashboard/Synapse.Dashboard/Pages/Workflows/List/Store.cs b/src/dashboard/Synapse.Dashboard/Pages/Workflows/List/Store.cs index c98b8e5e3..e834aaa55 100644 --- a/src/dashboard/Synapse.Dashboard/Pages/Workflows/List/Store.cs +++ b/src/dashboard/Synapse.Dashboard/Pages/Workflows/List/Store.cs @@ -12,7 +12,6 @@ // limitations under the License. using Synapse.Api.Client.Services; -using Synapse.Dashboard.Components.DocumentDetailsStateManagement; using Synapse.Resources; namespace Synapse.Dashboard.Pages.Workflows.List; @@ -43,8 +42,8 @@ public class WorkflowListComponentStore(ILogger logg /// A new awaitable public async Task ListOperatorsAsync() { - var operatorList = new EquatableList(await (await this.ApiClient.Operators.ListAsync().ConfigureAwait(false)).OrderBy(ns => ns.GetQualifiedName()).ToListAsync().ConfigureAwait(false)); - this.Reduce(s => s with + var operatorList = new EquatableList(await (await ApiClient.Operators.ListAsync().ConfigureAwait(false)).OrderBy(ns => ns.GetQualifiedName()).ToListAsync().ConfigureAwait(false)); + Reduce(s => s with { Operators = operatorList }); @@ -56,7 +55,7 @@ public async Task ListOperatorsAsync() /// The new value public void SetOperator(string? operatorName) { - this.Reduce(state => state with + Reduce(state => state with { Operator = operatorName }); @@ -66,16 +65,16 @@ public void SetOperator(string? operatorName) public override async Task InitializeAsync() { await base.InitializeAsync(); - await this.ListOperatorsAsync().ConfigureAwait(false); - this.Operator.Subscribe(operatorName => { + await ListOperatorsAsync().ConfigureAwait(false); + Operator.Subscribe(operatorName => { if (string.IsNullOrWhiteSpace(operatorName)) { - this.RemoveLabelSelector(SynapseDefaults.Resources.Labels.Operator); + RemoveLabelSelector(SynapseDefaults.Resources.Labels.Operator); } else { - this.AddLabelSelector(new(SynapseDefaults.Resources.Labels.Operator, LabelSelectionOperator.Equals, operatorName)); + AddLabelSelector(new(SynapseDefaults.Resources.Labels.Operator, LabelSelectionOperator.Equals, operatorName)); } - }, token: this.CancellationTokenSource.Token); + }, token: CancellationTokenSource.Token); } } diff --git a/src/dashboard/Synapse.Dashboard/Pages/Workflows/List/View.razor b/src/dashboard/Synapse.Dashboard/Pages/Workflows/List/View.razor index 6bb425c0c..75cb7fea8 100644 --- a/src/dashboard/Synapse.Dashboard/Pages/Workflows/List/View.razor +++ b/src/dashboard/Synapse.Dashboard/Pages/Workflows/List/View.razor @@ -163,9 +163,9 @@ protected override void OnInitialized() { base.OnInitialized(); - this.BreadcrumbManager.Use(Breadcrumbs.Workflows); - this.Store.Operators.Subscribe(value => this.OnStateChanged(_ => Operators = value), token: this.CancellationTokenSource.Token); - this.Store.Operator.Subscribe(value => this.OnStateChanged(_ => Operator = value), token: this.CancellationTokenSource.Token); + BreadcrumbManager.Use(Breadcrumbs.Workflows); + Store.Operators.Subscribe(value => OnStateChanged(_ => Operators = value), token: CancellationTokenSource.Token); + Store.Operator.Subscribe(value => OnStateChanged(_ => Operator = value), token: CancellationTokenSource.Token); } string GetScheduleType(Workflow workflow) @@ -179,10 +179,10 @@ else throw new NotSupportedException("The specified schedule type is not supported"); } - void OnViewWorkflow(Workflow workflow) => this.NavigationManager.NavigateTo($"workflows/details/{workflow.GetNamespace()}/{workflow.GetName()}/{workflow.Spec.Versions.GetLatest().Document.Version}"); + void OnViewWorkflow(Workflow workflow) => NavigationManager.NavigateTo($"workflows/details/{workflow.GetNamespace()}/{workflow.GetName()}/{workflow.Spec.Versions.GetLatest().Document.Version}"); - void OnCreateWorkflow() => this.NavigationManager.NavigateTo("/workflows/new"); + void OnCreateWorkflow() => NavigationManager.NavigateTo("/workflows/new"); - void OnCreateWorkflowVersion(string ns, string name) => this.NavigationManager.NavigateTo($"/workflows/new/{ns}/{name}"); + void OnCreateWorkflowVersion(string ns, string name) => NavigationManager.NavigateTo($"/workflows/new/{ns}/{name}"); } \ No newline at end of file diff --git a/src/dashboard/Synapse.Dashboard/Synapse.Dashboard.csproj b/src/dashboard/Synapse.Dashboard/Synapse.Dashboard.csproj index f6a2a55eb..4a67ce794 100644 --- a/src/dashboard/Synapse.Dashboard/Synapse.Dashboard.csproj +++ b/src/dashboard/Synapse.Dashboard/Synapse.Dashboard.csproj @@ -10,7 +10,7 @@ - + From 4ef1aaa2ad5edac5e2e4ae7f916e87ab6bf945d0 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bianchi Date: Tue, 22 Jul 2025 13:07:46 +0200 Subject: [PATCH 02/23] refactor(Dashboard): split long expression for readability in workflow details view Signed-off-by: Jean-Baptiste Bianchi --- .../Synapse.Dashboard/Pages/Workflows/Details/View.razor | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/dashboard/Synapse.Dashboard/Pages/Workflows/Details/View.razor b/src/dashboard/Synapse.Dashboard/Pages/Workflows/Details/View.razor index 41aa930c0..ed2308461 100644 --- a/src/dashboard/Synapse.Dashboard/Pages/Workflows/Details/View.razor +++ b/src/dashboard/Synapse.Dashboard/Pages/Workflows/Details/View.razor @@ -43,7 +43,11 @@ 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, operators ?? [], instance.Spec?.Input, instance.Metadata.Labels?.Get(SynapseDefaults.Resources.Labels.Operator) ?? operatorName)" + OnReplay="async (instance) => await Store.OnShowCreateInstanceAsync( + workflowDefinition, operators ?? [], + instance.Spec?.Input, + instance.Metadata.Labels?.Get(SynapseDefaults.Resources.Labels.Operator) ?? operatorName + )" OnDelete="OnDeleteWorkflowInstanceAsync" OnToggleSelected="Store.ToggleResourceSelection" OnSuspendSelected="async () => await Store.OnSuspendSelectedInstancesAsync()" From fbaa891fd7a95d2c55b816147766d138c5e7c36b Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bianchi Date: Tue, 22 Jul 2025 13:16:32 +0200 Subject: [PATCH 03/23] refactor(Dashboard): replace EquatableList with IEnumerable in views properties Signed-off-by: Jean-Baptiste Bianchi --- .../CreateWorkflowInstanceDialog.razor | 2 +- .../Synapse.Dashboard/Pages/Workflows/Create/View.razor | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dashboard/Synapse.Dashboard/Components/CreateWorkflowInstanceDialog/CreateWorkflowInstanceDialog.razor b/src/dashboard/Synapse.Dashboard/Components/CreateWorkflowInstanceDialog/CreateWorkflowInstanceDialog.razor index eda273fb9..7de0e0771 100644 --- a/src/dashboard/Synapse.Dashboard/Components/CreateWorkflowInstanceDialog/CreateWorkflowInstanceDialog.razor +++ b/src/dashboard/Synapse.Dashboard/Components/CreateWorkflowInstanceDialog/CreateWorkflowInstanceDialog.razor @@ -78,7 +78,7 @@ string? operatorName; [Parameter] public WorkflowDefinition? WorkflowDefinition { get; set; } - [Parameter] public EquatableList Operators { get; set; } = []; + [Parameter] public IEnumerable Operators { get; set; } = []; [Parameter] public string? OperatorName { get; set; } = null; [Parameter] public EquatableDictionary? Input { get; set; } [Parameter] public EventCallback OnCreate { get; set; } diff --git a/src/dashboard/Synapse.Dashboard/Pages/Workflows/Create/View.razor b/src/dashboard/Synapse.Dashboard/Pages/Workflows/Create/View.razor index e40c659f0..1f11bb59e 100644 --- a/src/dashboard/Synapse.Dashboard/Pages/Workflows/Create/View.razor +++ b/src/dashboard/Synapse.Dashboard/Pages/Workflows/Create/View.razor @@ -98,7 +98,7 @@ else bool loading = true; bool saving; private ProblemDetails? problemDetails = null; - protected EquatableList? operators { get; set; } + protected IEnumerable? operators { get; set; } protected string? operatorName { get; set; } [Parameter] public string? Namespace { get; set; } From f498e5505a8e6c7748149cffbdf3e794655052fd Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Bianchi Date: Tue, 22 Jul 2025 20:28:32 +0200 Subject: [PATCH 04/23] style(Dashboard): improve operator selection display Signed-off-by: Jean-Baptiste Bianchi --- .../CreateWorkflowInstanceDialog.razor | 27 +++++++++------- .../Pages/Workflows/Create/View.razor | 31 +++++++++++-------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/dashboard/Synapse.Dashboard/Components/CreateWorkflowInstanceDialog/CreateWorkflowInstanceDialog.razor b/src/dashboard/Synapse.Dashboard/Components/CreateWorkflowInstanceDialog/CreateWorkflowInstanceDialog.razor index 7de0e0771..825af1115 100644 --- a/src/dashboard/Synapse.Dashboard/Components/CreateWorkflowInstanceDialog/CreateWorkflowInstanceDialog.razor +++ b/src/dashboard/Synapse.Dashboard/Components/CreateWorkflowInstanceDialog/CreateWorkflowInstanceDialog.razor @@ -47,19 +47,24 @@ -
- @if (Operators != null && Operators.Count() > 0) - { - + + @foreach (var op in Operators) + { + var name = op.GetName() + "." + op.GetNamespace(); + + } + } - - } -
+ + +
} -
- @if (operators != null && operators.Count() > 0) - { - - } -
+ + + + @if (operators != null && operators.Count() > 0) + { + + + } + + +