|
12 | 12 | // limitations under the License. |
13 | 13 |
|
14 | 14 | using JsonCons.Utilities; |
15 | | -using Neuroglia.Collections; |
16 | 15 | using Neuroglia.Data; |
17 | 16 | using Semver; |
18 | 17 | using ServerlessWorkflow.Sdk.Models; |
19 | 18 | using ServerlessWorkflow.Sdk.Validation; |
20 | 19 | using Synapse.Api.Client.Services; |
21 | 20 | using Synapse.Resources; |
22 | 21 | using System.Text.RegularExpressions; |
| 22 | +using System.Xml.Linq; |
23 | 23 |
|
24 | 24 | namespace Synapse.Dashboard.Pages.Workflows.Create; |
25 | 25 |
|
@@ -102,7 +102,7 @@ IWorkflowDefinitionValidator workflowDefinitionValidator |
102 | 102 | protected MonacoInterop MonacoInterop { get; } = monacoInterop; |
103 | 103 |
|
104 | 104 | /// <summary> |
105 | | - /// Gets the service to to validate workflow defintions |
| 105 | + /// Gets the service to to validate workflow definitions |
106 | 106 | /// </summary> |
107 | 107 | protected IWorkflowDefinitionValidator WorkflowDefinitionValidator { get; } = workflowDefinitionValidator; |
108 | 108 |
|
@@ -218,6 +218,18 @@ public void SetName(string? name) |
218 | 218 | }); |
219 | 219 | } |
220 | 220 |
|
| 221 | + /// <summary> |
| 222 | + /// Sets the state's <see cref="CreateWorkflowViewState.IsNew"/> |
| 223 | + /// </summary> |
| 224 | + /// <param name="isNew">The new <see cref="CreateWorkflowViewState.IsNew"/> value</param> |
| 225 | + public void SetIsNew(bool isNew) |
| 226 | + { |
| 227 | + this.Reduce(state => state with |
| 228 | + { |
| 229 | + IsNew = isNew |
| 230 | + }); |
| 231 | + } |
| 232 | + |
221 | 233 | /// <summary> |
222 | 234 | /// Sets the state's <see cref="CreateWorkflowViewState" /> <see cref="ProblemDetails"/>'s related data |
223 | 235 | /// </summary> |
@@ -415,57 +427,56 @@ public async Task SaveWorkflowDefinitionAsync() |
415 | 427 | var @namespace = workflowDefinition!.Document.Namespace; |
416 | 428 | var name = workflowDefinition.Document.Name; |
417 | 429 | var version = workflowDefinition.Document.Version; |
| 430 | + var isNew = this.Get(state => state.IsNew); |
418 | 431 | this.Reduce(s => s with |
419 | 432 | { |
420 | 433 | Saving = true |
421 | 434 | }); |
422 | 435 | Workflow? workflow = null; |
423 | | - try |
424 | | - { |
425 | | - workflow = await this.Api.Workflows.GetAsync(name, @namespace); |
426 | | - } |
427 | | - catch |
| 436 | + if (isNew) |
428 | 437 | { |
429 | | - // Assume 404, might need actual handling |
430 | | - } |
431 | | - if (workflow == null) |
432 | | - { |
433 | | - workflow = await this.Api.Workflows.CreateAsync(new() |
434 | | - { |
435 | | - Metadata = new() |
436 | | - { |
437 | | - Namespace = workflowDefinition!.Document.Namespace, |
438 | | - Name = workflowDefinition.Document.Name |
439 | | - }, |
440 | | - Spec = new() |
| 438 | + try { |
| 439 | + workflow = await this.Api.Workflows.CreateAsync(new() |
441 | 440 | { |
442 | | - Versions = [workflowDefinition] |
443 | | - } |
444 | | - }); |
445 | | - } |
446 | | - else |
447 | | - { |
448 | | - var updatedResource = workflow.Clone()!; |
449 | | - var documentVersion = SemVersion.Parse(version, SemVersionStyles.Strict)!; |
450 | | - var latestVersion = SemVersion.Parse(updatedResource.Spec.Versions.GetLatest().Document.Version, SemVersionStyles.Strict)!; |
451 | | - if (updatedResource.Spec.Versions.Any(v => SemVersion.Parse(v.Document.Version, SemVersionStyles.Strict).CompareSortOrderTo(documentVersion) >= 0)) |
452 | | - { |
453 | | - this.Reduce(state => state with |
454 | | - { |
455 | | - ProblemTitle = "Invalid version", |
456 | | - ProblemDetail = $"The specified version '{documentVersion}' must be strictly superior to the latest version '{latestVersion}'." |
| 441 | + Metadata = new() |
| 442 | + { |
| 443 | + Namespace = workflowDefinition!.Document.Namespace, |
| 444 | + Name = workflowDefinition.Document.Name |
| 445 | + }, |
| 446 | + Spec = new() |
| 447 | + { |
| 448 | + Versions = [workflowDefinition] |
| 449 | + } |
457 | 450 | }); |
| 451 | + this.NavigationManager.NavigateTo($"/workflows/details/{@namespace}/{name}/{version}"); |
458 | 452 | return; |
459 | 453 | } |
460 | | - updatedResource.Spec.Versions.Add(workflowDefinition!); |
461 | | - var jsonPatch = JsonPatch.FromDiff(this.JsonSerializer.SerializeToElement(workflow)!.Value, this.JsonSerializer.SerializeToElement(updatedResource)!.Value); |
462 | | - var patch = this.JsonSerializer.Deserialize<Json.Patch.JsonPatch>(jsonPatch.RootElement); |
463 | | - if (patch != null) |
| 454 | + catch (ProblemDetailsException ex) when (ex.Problem.Title == "Conflict" && ex.Problem.Detail != null && ex.Problem.Detail.EndsWith("already exists")) |
464 | 455 | { |
465 | | - var resourcePatch = new Patch(PatchType.JsonPatch, jsonPatch); |
466 | | - await this.Api.ManageNamespaced<Workflow>().PatchAsync(name, @namespace, resourcePatch, null, this.CancellationTokenSource.Token); |
| 456 | + // the workflow exists, try to update it instead |
467 | 457 | } |
468 | 458 | } |
| 459 | + workflow = await this.Api.Workflows.GetAsync(name, @namespace); |
| 460 | + var updatedResource = workflow.Clone()!; |
| 461 | + var documentVersion = SemVersion.Parse(version, SemVersionStyles.Strict)!; |
| 462 | + var latestVersion = SemVersion.Parse(updatedResource.Spec.Versions.GetLatest().Document.Version, SemVersionStyles.Strict)!; |
| 463 | + if (updatedResource.Spec.Versions.Any(v => SemVersion.Parse(v.Document.Version, SemVersionStyles.Strict).CompareSortOrderTo(documentVersion) >= 0)) |
| 464 | + { |
| 465 | + this.Reduce(state => state with |
| 466 | + { |
| 467 | + ProblemTitle = "Invalid version", |
| 468 | + ProblemDetail = $"The specified version '{documentVersion}' must be strictly superior to the latest version '{latestVersion}'." |
| 469 | + }); |
| 470 | + return; |
| 471 | + } |
| 472 | + updatedResource.Spec.Versions.Add(workflowDefinition!); |
| 473 | + var jsonPatch = JsonPatch.FromDiff(this.JsonSerializer.SerializeToElement(workflow)!.Value, this.JsonSerializer.SerializeToElement(updatedResource)!.Value); |
| 474 | + var patch = this.JsonSerializer.Deserialize<Json.Patch.JsonPatch>(jsonPatch.RootElement); |
| 475 | + if (patch != null) |
| 476 | + { |
| 477 | + var resourcePatch = new Patch(PatchType.JsonPatch, jsonPatch); |
| 478 | + await this.Api.ManageNamespaced<Workflow>().PatchAsync(name, @namespace, resourcePatch, null, this.CancellationTokenSource.Token); |
| 479 | + } |
469 | 480 | this.NavigationManager.NavigateTo($"/workflows/details/{@namespace}/{name}/{version}"); |
470 | 481 | } |
471 | 482 | catch (ProblemDetailsException ex) |
|
0 commit comments