From f3c047d624f68dff5975be82f4874c730d79cd5a Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Thu, 21 Nov 2024 12:52:48 +0100 Subject: [PATCH 01/25] Delete all Summary 2.0 components that has a reference to deleted component --- .../Controllers/AppDevelopmentController.cs | 27 ++++-- .../ComponentDeletedSummaryRefHandler.cs | 94 +++++++++++++++++++ .../Designer/Events/ComponentDeletedEvent.cs | 11 +++ .../Designer/Hubs/SyncHub/SyncErrorCodes.cs | 2 + 4 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedSummaryRefHandler.cs create mode 100644 backend/src/Designer/Events/ComponentDeletedEvent.cs diff --git a/backend/src/Designer/Controllers/AppDevelopmentController.cs b/backend/src/Designer/Controllers/AppDevelopmentController.cs index 37a2d40c08b..a499e1e7196 100644 --- a/backend/src/Designer/Controllers/AppDevelopmentController.cs +++ b/backend/src/Designer/Controllers/AppDevelopmentController.cs @@ -125,13 +125,28 @@ public async Task SaveFormLayout(string org, string app, [FromQuer { foreach (var componentIdChange in formLayoutPayload.ComponentIdsChange) { - await _mediator.Publish(new ComponentIdChangedEvent + if (componentIdChange.OldComponentId != componentIdChange.NewComponentId) { - OldComponentId = componentIdChange.OldComponentId, - NewComponentId = componentIdChange.NewComponentId, - LayoutSetName = layoutSetName, - EditingContext = editingContext - }, cancellationToken); + if (componentIdChange.NewComponentId == null) + { + await _mediator.Publish(new ComponentDeletedEvent + { + ComponentId = componentIdChange.OldComponentId, + LayoutSetName = layoutSetName, + EditingContext = editingContext + }, cancellationToken); + } + else + { + await _mediator.Publish(new ComponentIdChangedEvent + { + OldComponentId = componentIdChange.OldComponentId, + NewComponentId = componentIdChange.NewComponentId, + LayoutSetName = layoutSetName, + EditingContext = editingContext + }, cancellationToken); + } + } } } if (!formLayouts.ContainsKey(layoutName)) diff --git a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedSummaryRefHandler.cs b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedSummaryRefHandler.cs new file mode 100644 index 00000000000..6b2490b40f4 --- /dev/null +++ b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedSummaryRefHandler.cs @@ -0,0 +1,94 @@ +using System.Threading; +using System.Threading.Tasks; +using Altinn.Studio.Designer.Events; +using Altinn.Studio.Designer.Services.Interfaces; +using Altinn.Studio.Designer.Infrastructure.GitRepository; +using MediatR; +using System.Text.Json.Nodes; +using Altinn.App.Core.Helpers; +using Altinn.Studio.Designer.Hubs.SyncHub; +using Altinn.Studio.Designer.Models; +using System.Linq; + +namespace Altinn.Studio.Designer.EventHandlers.ComponentDeleted; + +public class ComponentDeletedSummaryRefHandler : INotificationHandler +{ + private readonly IAltinnGitRepositoryFactory _altinnGitRepositoryFactory; + private readonly IFileSyncHandlerExecutor _fileSyncHandlerExecutor; + + public ComponentDeletedSummaryRefHandler(IAltinnGitRepositoryFactory altinnGitRepositoryFactory, IFileSyncHandlerExecutor fileSyncHandlerExecutor) + { + _altinnGitRepositoryFactory = altinnGitRepositoryFactory; + _fileSyncHandlerExecutor = fileSyncHandlerExecutor; + } + + public async Task Handle(ComponentDeletedEvent notification, CancellationToken cancellationToken) + { + bool hasChanges = false; + await _fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( + notification.EditingContext, + SyncErrorCodes.ComponentDeletedSummaryRefSyncError, + "layouts", + async () => + { + AltinnAppGitRepository repository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository( + notification.EditingContext.Org, + notification.EditingContext.Repo, + notification.EditingContext.Developer); + + if (!repository.AppUsesLayoutSets()) + { + return hasChanges; + } + + return await DeleteSummaryComponents(repository, notification.LayoutSetName, notification.ComponentId, cancellationToken); + }); + + } + + private async Task DeleteSummaryComponents(AltinnAppGitRepository altinnAppGitRepository, string deletedComponentLayoutSetId, string deletedComponentId, CancellationToken cancellationToken) + { + bool hasChanged = false; + + LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile(cancellationToken); + + foreach (LayoutSetConfig layoutSetConfig in layoutSets.Sets) + { + string[] layoutNames = altinnAppGitRepository.GetLayoutNames(layoutSetConfig.Id); + foreach (string layoutName in layoutNames) + { + JsonNode layout = await altinnAppGitRepository.GetLayout(layoutSetConfig.Id, layoutName); + + if (layout?["data"]?["layout"] is not JsonArray layoutArray) + { + continue; + } + + int initialCount = layoutArray.Count; + layoutArray.RemoveAll(layoutObject => + { + if (layoutObject["type"]?.GetValue() != "Summary2" || layoutObject["target"] is not JsonObject targetObject) + { + return false; + } + + string summaryType = targetObject["type"]?.GetValue(); + string id = targetObject["id"]?.GetValue(); + string taskId = targetObject["taskId"]?.GetValue(); + string layouSetId = string.IsNullOrEmpty(taskId) ? layoutSetConfig.Id : layoutSets.Sets.FirstOrDefault(item => item.Tasks.Contains(taskId))?.Id; + + return summaryType == "component" && layouSetId == deletedComponentLayoutSetId && id == deletedComponentId; + }); + + if (layoutArray.Count != initialCount) + { + await altinnAppGitRepository.SaveLayout(layoutSetConfig.Id, layoutName, layout, cancellationToken); + hasChanged = true; + } + } + } + + return hasChanged; + } +} diff --git a/backend/src/Designer/Events/ComponentDeletedEvent.cs b/backend/src/Designer/Events/ComponentDeletedEvent.cs new file mode 100644 index 00000000000..de23fabd236 --- /dev/null +++ b/backend/src/Designer/Events/ComponentDeletedEvent.cs @@ -0,0 +1,11 @@ +using Altinn.Studio.Designer.Models; +using MediatR; + +namespace Altinn.Studio.Designer.Events; + +public class ComponentDeletedEvent : INotification +{ + public string ComponentId { get; set; } + public string LayoutSetName { get; set; } + public AltinnRepoEditingContext EditingContext { get; set; } +} diff --git a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs index 23556793c7b..df11ccb137d 100644 --- a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs +++ b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs @@ -13,4 +13,6 @@ public static class SyncErrorCodes public const string LayoutSetSubFormButtonSyncError = nameof(LayoutSetSubFormButtonSyncError); public const string SettingsComponentIdSyncError = nameof(SettingsComponentIdSyncError); public const string LayoutPageAddSyncError = nameof(LayoutPageAddSyncError); + public const string ComponentDeletedSummaryRefSyncError = nameof(ComponentDeletedSummaryRefSyncError); + } From c1e29228ab442290f6a507a7f50b25a9c67298e5 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Wed, 27 Nov 2024 13:42:34 +0100 Subject: [PATCH 02/25] dotnet format --- .../ComponentDeletedSummaryRefHandler.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedSummaryRefHandler.cs b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedSummaryRefHandler.cs index 6b2490b40f4..fd233233aea 100644 --- a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedSummaryRefHandler.cs +++ b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedSummaryRefHandler.cs @@ -1,14 +1,14 @@ +using System.Linq; +using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; -using Altinn.Studio.Designer.Events; -using Altinn.Studio.Designer.Services.Interfaces; -using Altinn.Studio.Designer.Infrastructure.GitRepository; -using MediatR; -using System.Text.Json.Nodes; using Altinn.App.Core.Helpers; +using Altinn.Studio.Designer.Events; using Altinn.Studio.Designer.Hubs.SyncHub; +using Altinn.Studio.Designer.Infrastructure.GitRepository; using Altinn.Studio.Designer.Models; -using System.Linq; +using Altinn.Studio.Designer.Services.Interfaces; +using MediatR; namespace Altinn.Studio.Designer.EventHandlers.ComponentDeleted; From dd249f7d0284d747b2a9f5fdff18a4eb630ab475 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Wed, 27 Nov 2024 15:13:54 +0100 Subject: [PATCH 03/25] Fix SaveFormLayout --- .../Controllers/AppDevelopmentController.cs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/backend/src/Designer/Controllers/AppDevelopmentController.cs b/backend/src/Designer/Controllers/AppDevelopmentController.cs index a499e1e7196..05aaade566d 100644 --- a/backend/src/Designer/Controllers/AppDevelopmentController.cs +++ b/backend/src/Designer/Controllers/AppDevelopmentController.cs @@ -136,16 +136,14 @@ await _mediator.Publish(new ComponentDeletedEvent EditingContext = editingContext }, cancellationToken); } - else + + await _mediator.Publish(new ComponentIdChangedEvent { - await _mediator.Publish(new ComponentIdChangedEvent - { - OldComponentId = componentIdChange.OldComponentId, - NewComponentId = componentIdChange.NewComponentId, - LayoutSetName = layoutSetName, - EditingContext = editingContext - }, cancellationToken); - } + OldComponentId = componentIdChange.OldComponentId, + NewComponentId = componentIdChange.NewComponentId, + LayoutSetName = layoutSetName, + EditingContext = editingContext + }, cancellationToken); } } } From 1920a7b714ed5930dbba99ce805eedd0d27137ba Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Fri, 29 Nov 2024 15:19:24 +0100 Subject: [PATCH 04/25] Add backend tests --- .../SaveFormLayoutTests.cs | 49 ++++++++++++++++++- .../ui/Activity_0z4cgvm/layouts/Side1.json | 13 +++++ .../ui/Activity_0z4cgvm/layouts/Side2.json | 13 +++++ .../ui/Activity_0z4cgvm/layouts/Side3.json | 31 ++++++++++++ .../App/ui/form/layouts/Side1.json | 21 ++++++++ .../App/ui/form/layouts/Side2.json | 13 +++++ .../App/ui/form/layouts/Side3.json | 31 ++++++++++++ .../ui/Activity_0z4cgvm/layouts/Side1.json | 22 +++++++++ .../ui/Activity_0z4cgvm/layouts/Side2.json | 22 +++++++++ .../ui/Activity_0z4cgvm/layouts/Side3.json | 31 ++++++++++++ .../App/ui/form/layouts/Side1.json | 37 ++++++++++++++ .../App/ui/form/layouts/Side2.json | 22 +++++++++ .../App/ui/form/layouts/Side3.json | 31 ++++++++++++ 13 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side3.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side3.json diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs index 496f39223fb..b007cf38ec6 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs @@ -1,4 +1,5 @@ -using System.Net; +using System.Linq; +using System.Net; using System.Net.Http; using System.Net.Mime; using System.Text; @@ -93,6 +94,52 @@ public async Task SaveFormLayoutWithComponentIdsChange_ReturnsOk(string org, str JsonUtils.DeepEquals(layout, savedLayout).Should().BeTrue(); } + [Theory] + [InlineData("ttd", "testUser", "Side1", "form")] + public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummaryComponents_ReturnsOk(string org, string developer, string layoutName, string layoutSetName) + { + string actualApp = "deleted-component-before-delete"; + string app = TestDataHelper.GenerateTestRepoName(); + await CopyRepositoryForTest(org, actualApp, developer, app); + + string layout = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{layoutSetName}/layouts/{layoutName}.json"); + JsonNode layoutWithDeletedComponent = JsonNode.Parse(layout); + JsonArray layoutArray = layoutWithDeletedComponent["data"]["layout"] as JsonArray; + layoutArray.RemoveAt(0); + + string url = $"{VersionPrefix(org, app)}/form-layout/{layoutName}?layoutSetName={layoutSetName}"; + var payload = new JsonObject + { + ["componentIdsChange"] = new JsonArray() { + new JsonObject + { + ["oldComponentId"] = "Input-XDDxRp", + } + }, + ["layout"] = layoutWithDeletedComponent + }; + HttpResponseMessage response = await SendHttpRequest(url, payload); + response.StatusCode.Should().Be(HttpStatusCode.OK); + + string expectedApp = "deleted-component-after-delete"; + + string[] layoutPaths = [ + "form/layouts/Side1.json", + "form/layouts/Side2.json", + "form/layouts/Side3.json", + "Activity_0z4cgvm/layouts/Side1.json", + "Activity_0z4cgvm/layouts/Side2.json", + "Activity_0z4cgvm/layouts/Side3.json" + ]; + + layoutPaths.ToList().ForEach(file => + { + string actual = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{file}"); + string expected = TestDataHelper.GetFileFromRepo(org, expectedApp, developer, $"App/ui/{file}"); + JsonUtils.DeepEquals(actual, expected).Should().BeTrue(); + }); + } + [Theory] [InlineData("ttd", "app-with-layoutsets", "testUser", "testLayout", "layoutSet1", "TestData/App/ui/layoutWithUnknownProperties.json")] public async Task SaveFormLayoutWithNewPageLanguageUpdate_ReturnsOk(string org, string app, string developer, string layoutName, string layoutSetName, string layoutPath) diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json new file mode 100644 index 00000000000..d23b7e0802a --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "id": "NavigationButtons-DfcNol", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json new file mode 100644 index 00000000000..e64197d78e5 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "id": "NavigationButtons-GAW8Dx", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json new file mode 100644 index 00000000000..cbcfcc70d95 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "component", + "id": "Input-1GAVAE", + "taskId": "Task_1" + }, + "id": "Summary2-PBrjWH", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "", + "taskId": "" + }, + "id": "Summary2-WokR5T", + "type": "Summary2" + }, + { + "id": "NavigationButtons-Knkbt3", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side1.json new file mode 100644 index 00000000000..099450bd77d --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side1.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "hidden": false, + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-1GAVAE", + "type": "Input" + }, + { + "id": "NavigationButtons-C2O3bE", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side2.json new file mode 100644 index 00000000000..69152361ed1 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side2.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "id": "NavigationButtons-TFHw9D", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side3.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side3.json new file mode 100644 index 00000000000..09e48f21de0 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side3.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "component", + "id": "Input-1GAVAE", + "taskId": "" + }, + "id": "Summary2-GcK8zp", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "", + "taskId": "" + }, + "id": "Summary2-3TdVTp", + "type": "Summary2" + }, + { + "id": "NavigationButtons-tIAlCU", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json new file mode 100644 index 00000000000..ef246f0cc61 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "component", + "id": "Input-XDDxRp", + "taskId": "Task_1" + }, + "id": "Summary2-QN78Y8", + "type": "Summary2" + }, + { + "id": "NavigationButtons-DfcNol", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json new file mode 100644 index 00000000000..36a45150d8d --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "component", + "id": "Input-XDDxRp", + "taskId": "Task_1" + }, + "id": "Summary2-9OFVzC", + "type": "Summary2" + }, + { + "id": "NavigationButtons-GAW8Dx", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json new file mode 100644 index 00000000000..cbcfcc70d95 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "component", + "id": "Input-1GAVAE", + "taskId": "Task_1" + }, + "id": "Summary2-PBrjWH", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "", + "taskId": "" + }, + "id": "Summary2-WokR5T", + "type": "Summary2" + }, + { + "id": "NavigationButtons-Knkbt3", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side1.json new file mode 100644 index 00000000000..f4fd400bbfe --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side1.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "hidden": false, + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-XDDxRp", + "type": "Input" + }, + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-1GAVAE", + "type": "Input" + }, + { + "target": { + "type": "component", + "id": "Input-XDDxRp", + "taskId": "" + }, + "id": "Summary2-qx7wBR", + "type": "Summary2" + }, + { + "id": "NavigationButtons-C2O3bE", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side2.json new file mode 100644 index 00000000000..308fdbb3a4d --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side2.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "component", + "id": "Input-XDDxRp", + "taskId": "" + }, + "id": "Summary2-sopfsr", + "type": "Summary2" + }, + { + "id": "NavigationButtons-TFHw9D", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side3.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side3.json new file mode 100644 index 00000000000..09e48f21de0 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side3.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "component", + "id": "Input-1GAVAE", + "taskId": "" + }, + "id": "Summary2-GcK8zp", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "", + "taskId": "" + }, + "id": "Summary2-3TdVTp", + "type": "Summary2" + }, + { + "id": "NavigationButtons-tIAlCU", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file From 8cbebb76204553aa8bd7019c8e71696ce19c7dd7 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Fri, 29 Nov 2024 16:48:35 +0100 Subject: [PATCH 05/25] Cleanup --- backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs index df11ccb137d..a906a9b1f4c 100644 --- a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs +++ b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs @@ -14,5 +14,4 @@ public static class SyncErrorCodes public const string SettingsComponentIdSyncError = nameof(SettingsComponentIdSyncError); public const string LayoutPageAddSyncError = nameof(LayoutPageAddSyncError); public const string ComponentDeletedSummaryRefSyncError = nameof(ComponentDeletedSummaryRefSyncError); - } From 7f950cb4383ff84892b6f239629c303a6cafae87 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Wed, 4 Dec 2024 18:47:03 +0100 Subject: [PATCH 06/25] Refactoring --- .../Controllers/AppDevelopmentController.cs | 18 +++- .../ComponentDeletedHandler.cs | 27 ++++++ .../ComponentDeletedSummaryRefHandler.cs | 94 ------------------- .../LayoutPageDeletedHandler.cs | 50 ++++++++++ .../LayoutSetDeletedComponentRefHandler.cs | 59 ++++-------- .../Designer/Events/ComponentDeletedEvent.cs | 4 +- .../Designer/Events/LayoutPageDeletedEvent.cs | 11 +++ .../Designer/Events/LayoutSetDeletedEvent.cs | 2 +- .../Designer/Hubs/SyncHub/SyncErrorCodes.cs | 3 +- backend/src/Designer/Models/Reference.cs | 15 +++ .../Implementation/AppDevelopmentService.cs | 73 ++++++++++++++ .../Interfaces/IAppDevelopmentService.cs | 9 ++ 12 files changed, 225 insertions(+), 140 deletions(-) create mode 100644 backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs delete mode 100644 backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedSummaryRefHandler.cs create mode 100644 backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs create mode 100644 backend/src/Designer/Events/LayoutPageDeletedEvent.cs create mode 100644 backend/src/Designer/Models/Reference.cs diff --git a/backend/src/Designer/Controllers/AppDevelopmentController.cs b/backend/src/Designer/Controllers/AppDevelopmentController.cs index 05aaade566d..d404696e300 100644 --- a/backend/src/Designer/Controllers/AppDevelopmentController.cs +++ b/backend/src/Designer/Controllers/AppDevelopmentController.cs @@ -172,16 +172,26 @@ await _mediator.Publish(new LayoutPageAddedEvent /// Application identifier which is unique within an organisation. /// The name of the layout set the specific layout belongs to /// The form layout to be deleted + /// A that observes if operation is cancelled. /// A success message if the save was successful [HttpDelete] [Route("form-layout/{layoutName}")] - public ActionResult DeleteFormLayout(string org, string app, [FromQuery] string layoutSetName, [FromRoute] string layoutName) + public async Task DeleteFormLayout(string org, string app, [FromQuery] string layoutSetName, [FromRoute] string layoutName, CancellationToken cancellationToken) { try { string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext); var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer); + + await _mediator.Publish(new LayoutPageDeletedEvent + { + EditingContext = editingContext, + LayoutSetName = layoutSetName, + LayoutName = layoutName, + }, cancellationToken); + _appDevelopmentService.DeleteFormLayout(editingContext, layoutSetName, layoutName); + return Ok(); } catch (FileNotFoundException exception) @@ -404,13 +414,15 @@ public async Task DeleteLayoutSet(string org, string app, [FromRou { string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext); var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer); - LayoutSets layoutSets = await _appDevelopmentService.DeleteLayoutSet(editingContext, layoutSetIdToUpdate, cancellationToken); await _mediator.Publish(new LayoutSetDeletedEvent { EditingContext = editingContext, - LayoutSetId = layoutSetIdToUpdate + LayoutSetName = layoutSetIdToUpdate }, cancellationToken); + + LayoutSets layoutSets = await _appDevelopmentService.DeleteLayoutSet(editingContext, layoutSetIdToUpdate, cancellationToken); + return Ok(layoutSets); } diff --git a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs new file mode 100644 index 00000000000..bddfcf8b8ed --- /dev/null +++ b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Altinn.Studio.Designer.Events; +using Altinn.Studio.Designer.Hubs.SyncHub; +using Altinn.Studio.Designer.Models; +using Altinn.Studio.Designer.Services.Interfaces; +using MediatR; + +namespace Altinn.Studio.Designer.EventHandlers.ComponentDeleted; + +public class ComponentDeletedHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler +{ + public async Task Handle(ComponentDeletedEvent notification, CancellationToken cancellationToken) + { + await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( + notification.EditingContext, + SyncErrorCodes.ComponentDeletedSyncError, + "layouts", + async () => + { + List deletedIds = [new Reference("component", notification.LayoutSetName, notification.ComponentId)]; + + return await appDevelopmentService.DeleteFromLayouts(notification.EditingContext, deletedIds, cancellationToken); + }); + } +} diff --git a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedSummaryRefHandler.cs b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedSummaryRefHandler.cs deleted file mode 100644 index fd233233aea..00000000000 --- a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedSummaryRefHandler.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System.Linq; -using System.Text.Json.Nodes; -using System.Threading; -using System.Threading.Tasks; -using Altinn.App.Core.Helpers; -using Altinn.Studio.Designer.Events; -using Altinn.Studio.Designer.Hubs.SyncHub; -using Altinn.Studio.Designer.Infrastructure.GitRepository; -using Altinn.Studio.Designer.Models; -using Altinn.Studio.Designer.Services.Interfaces; -using MediatR; - -namespace Altinn.Studio.Designer.EventHandlers.ComponentDeleted; - -public class ComponentDeletedSummaryRefHandler : INotificationHandler -{ - private readonly IAltinnGitRepositoryFactory _altinnGitRepositoryFactory; - private readonly IFileSyncHandlerExecutor _fileSyncHandlerExecutor; - - public ComponentDeletedSummaryRefHandler(IAltinnGitRepositoryFactory altinnGitRepositoryFactory, IFileSyncHandlerExecutor fileSyncHandlerExecutor) - { - _altinnGitRepositoryFactory = altinnGitRepositoryFactory; - _fileSyncHandlerExecutor = fileSyncHandlerExecutor; - } - - public async Task Handle(ComponentDeletedEvent notification, CancellationToken cancellationToken) - { - bool hasChanges = false; - await _fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( - notification.EditingContext, - SyncErrorCodes.ComponentDeletedSummaryRefSyncError, - "layouts", - async () => - { - AltinnAppGitRepository repository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository( - notification.EditingContext.Org, - notification.EditingContext.Repo, - notification.EditingContext.Developer); - - if (!repository.AppUsesLayoutSets()) - { - return hasChanges; - } - - return await DeleteSummaryComponents(repository, notification.LayoutSetName, notification.ComponentId, cancellationToken); - }); - - } - - private async Task DeleteSummaryComponents(AltinnAppGitRepository altinnAppGitRepository, string deletedComponentLayoutSetId, string deletedComponentId, CancellationToken cancellationToken) - { - bool hasChanged = false; - - LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile(cancellationToken); - - foreach (LayoutSetConfig layoutSetConfig in layoutSets.Sets) - { - string[] layoutNames = altinnAppGitRepository.GetLayoutNames(layoutSetConfig.Id); - foreach (string layoutName in layoutNames) - { - JsonNode layout = await altinnAppGitRepository.GetLayout(layoutSetConfig.Id, layoutName); - - if (layout?["data"]?["layout"] is not JsonArray layoutArray) - { - continue; - } - - int initialCount = layoutArray.Count; - layoutArray.RemoveAll(layoutObject => - { - if (layoutObject["type"]?.GetValue() != "Summary2" || layoutObject["target"] is not JsonObject targetObject) - { - return false; - } - - string summaryType = targetObject["type"]?.GetValue(); - string id = targetObject["id"]?.GetValue(); - string taskId = targetObject["taskId"]?.GetValue(); - string layouSetId = string.IsNullOrEmpty(taskId) ? layoutSetConfig.Id : layoutSets.Sets.FirstOrDefault(item => item.Tasks.Contains(taskId))?.Id; - - return summaryType == "component" && layouSetId == deletedComponentLayoutSetId && id == deletedComponentId; - }); - - if (layoutArray.Count != initialCount) - { - await altinnAppGitRepository.SaveLayout(layoutSetConfig.Id, layoutName, layout, cancellationToken); - hasChanged = true; - } - } - } - - return hasChanged; - } -} diff --git a/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs b/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs new file mode 100644 index 00000000000..9b2026805a2 --- /dev/null +++ b/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs @@ -0,0 +1,50 @@ + +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Altinn.Studio.Designer.Events; +using Altinn.Studio.Designer.Hubs.SyncHub; +using Altinn.Studio.Designer.Infrastructure.GitRepository; +using Altinn.Studio.Designer.Services.Interfaces; +using MediatR; +using System.Text.Json.Nodes; +using Altinn.Studio.Designer.Models; + +namespace Altinn.Studio.Designer.EventHandlers.LayoutPageDeleted; + +public class LayoutPageDeletedHandler( + IFileSyncHandlerExecutor fileSyncHandlerExecutor, + IAppDevelopmentService appDevelopmentService, + IAltinnGitRepositoryFactory altinnGitRepositoryFactory) : INotificationHandler +{ + public async Task Handle(LayoutPageDeletedEvent notification, CancellationToken cancellationToken) + { + await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( + notification.EditingContext, + SyncErrorCodes.LayoutPageDeletedSyncError, + "layouts", + async () => + { + AltinnAppGitRepository altinnAppGitRepository = altinnGitRepositoryFactory.GetAltinnAppGitRepository( + notification.EditingContext.Org, + notification.EditingContext.Repo, + notification.EditingContext.Developer); + + JsonNode deletedLayout = await altinnAppGitRepository.GetLayout(notification.LayoutSetName, notification.LayoutName, cancellationToken); + + List deletedIds = [new Reference("page", notification.LayoutSetName, notification.LayoutName)]; + if (deletedLayout["data"] is not JsonObject data || data["layout"] is not JsonArray layoutArray) + { + return false; + } + + foreach (JsonNode component in layoutArray) + { + string deletedId = component["id"]?.GetValue(); + deletedIds.Add(new Reference("component", notification.LayoutSetName, deletedId)); + } + + return await appDevelopmentService.DeleteFromLayouts(notification.EditingContext, deletedIds, cancellationToken); + }); + } +} diff --git a/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedComponentRefHandler.cs b/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedComponentRefHandler.cs index 95b38685a47..f0835ffed80 100644 --- a/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedComponentRefHandler.cs +++ b/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedComponentRefHandler.cs @@ -2,16 +2,16 @@ using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; -using Altinn.App.Core.Helpers; using Altinn.Studio.Designer.Events; using Altinn.Studio.Designer.Hubs.SyncHub; using Altinn.Studio.Designer.Infrastructure.GitRepository; +using Altinn.Studio.Designer.Models; using Altinn.Studio.Designer.Services.Interfaces; using MediatR; namespace Altinn.Studio.Designer.EventHandlers.LayoutSetDeleted; -public class LayoutSetDeletedComponentRefHandler(IAltinnGitRepositoryFactory altinnGitRepositoryFactory, IFileSyncHandlerExecutor fileSyncHandlerExecutor) : INotificationHandler +public class LayoutSetDeletedComponentRefHandler(IAltinnGitRepositoryFactory altinnGitRepositoryFactory, IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler { public async Task Handle(LayoutSetDeletedEvent notification, CancellationToken cancellationToken) { @@ -20,7 +20,7 @@ public async Task Handle(LayoutSetDeletedEvent notification, CancellationToken c notification.EditingContext.Repo, notification.EditingContext.Developer); - string[] layoutSetNames = altinnAppGitRepository.GetLayoutSetNames(); + LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile(cancellationToken); await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( notification.EditingContext, @@ -28,46 +28,27 @@ await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotifica "layouts", async () => { - bool hasChanges = false; - foreach (string layoutSetName in layoutSetNames) + Dictionary deletedLayouts = await altinnAppGitRepository.GetFormLayouts(notification.LayoutSetName, cancellationToken); + + List referencesToDelete = [new Reference("layoutSet", notification.LayoutSetName, notification.LayoutSetName)]; + + foreach (KeyValuePair deletedLayout in deletedLayouts) { - Dictionary formLayouts = await altinnAppGitRepository.GetFormLayouts(layoutSetName, cancellationToken); - foreach (var formLayout in formLayouts) + referencesToDelete.Add(new Reference("page", notification.LayoutSetName, deletedLayout.Key)); + + if (deletedLayout.Value["data"] is not JsonObject data || data["layout"] is not JsonArray layoutArray) { - hasChanges |= await RemoveComponentsReferencingLayoutSet( - notification, - altinnAppGitRepository, - layoutSetName, - formLayout, - cancellationToken); + continue; } - } - return hasChanges; - }); - } - private static async Task RemoveComponentsReferencingLayoutSet(LayoutSetDeletedEvent notification, AltinnAppGitRepository altinnAppGitRepository, string layoutSetName, KeyValuePair formLayout, CancellationToken cancellationToken) - { - if (formLayout.Value["data"] is not JsonObject data || data["layout"] is not JsonArray layoutArray) - { - return false; - } - - bool hasChanges = false; - layoutArray.RemoveAll(jsonNode => - { - if (jsonNode["layoutSet"]?.GetValue() == notification.LayoutSetId) - { - hasChanges = true; - return true; - } - return false; - }); + foreach (JsonNode component in layoutArray) + { + string deletedId = component["id"]?.GetValue(); + referencesToDelete.Add(new Reference("component", notification.LayoutSetName, deletedId)); + } + } - if (hasChanges) - { - await altinnAppGitRepository.SaveLayout(layoutSetName, $"{formLayout.Key}.json", formLayout.Value, cancellationToken); - } - return hasChanges; + return await appDevelopmentService.DeleteFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); + }); } } diff --git a/backend/src/Designer/Events/ComponentDeletedEvent.cs b/backend/src/Designer/Events/ComponentDeletedEvent.cs index de23fabd236..a6897eee55d 100644 --- a/backend/src/Designer/Events/ComponentDeletedEvent.cs +++ b/backend/src/Designer/Events/ComponentDeletedEvent.cs @@ -5,7 +5,7 @@ namespace Altinn.Studio.Designer.Events; public class ComponentDeletedEvent : INotification { - public string ComponentId { get; set; } - public string LayoutSetName { get; set; } public AltinnRepoEditingContext EditingContext { get; set; } + public string LayoutSetName { get; set; } + public string ComponentId { get; set; } } diff --git a/backend/src/Designer/Events/LayoutPageDeletedEvent.cs b/backend/src/Designer/Events/LayoutPageDeletedEvent.cs new file mode 100644 index 00000000000..8411d583169 --- /dev/null +++ b/backend/src/Designer/Events/LayoutPageDeletedEvent.cs @@ -0,0 +1,11 @@ +using Altinn.Studio.Designer.Models; +using MediatR; + +namespace Altinn.Studio.Designer.Events; + +public class LayoutPageDeletedEvent : INotification +{ + public AltinnRepoEditingContext EditingContext { get; set; } + public string LayoutSetName { get; set; } + public string LayoutName { get; set; } +} diff --git a/backend/src/Designer/Events/LayoutSetDeletedEvent.cs b/backend/src/Designer/Events/LayoutSetDeletedEvent.cs index aadbd44a4c0..00bf4a926cf 100644 --- a/backend/src/Designer/Events/LayoutSetDeletedEvent.cs +++ b/backend/src/Designer/Events/LayoutSetDeletedEvent.cs @@ -5,6 +5,6 @@ namespace Altinn.Studio.Designer.Events; public class LayoutSetDeletedEvent : INotification { - public string LayoutSetId { get; set; } public AltinnRepoEditingContext EditingContext { get; set; } + public string LayoutSetName { get; set; } } diff --git a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs index a906a9b1f4c..89cd0439eb4 100644 --- a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs +++ b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs @@ -13,5 +13,6 @@ public static class SyncErrorCodes public const string LayoutSetSubFormButtonSyncError = nameof(LayoutSetSubFormButtonSyncError); public const string SettingsComponentIdSyncError = nameof(SettingsComponentIdSyncError); public const string LayoutPageAddSyncError = nameof(LayoutPageAddSyncError); - public const string ComponentDeletedSummaryRefSyncError = nameof(ComponentDeletedSummaryRefSyncError); + public const string ComponentDeletedSyncError = nameof(ComponentDeletedSyncError); + public const string LayoutPageDeletedSyncError = nameof(LayoutPageDeletedSyncError); } diff --git a/backend/src/Designer/Models/Reference.cs b/backend/src/Designer/Models/Reference.cs new file mode 100644 index 00000000000..1cde4847945 --- /dev/null +++ b/backend/src/Designer/Models/Reference.cs @@ -0,0 +1,15 @@ +namespace Altinn.Studio.Designer.Models; + +public class Reference +{ + public string Type { get; } + public string LayoutSetName { get; } + public string Id { get; } + + public Reference(string type, string layoutSetName, string id) + { + Type = type; + LayoutSetName = layoutSetName; + Id = id; + } +} diff --git a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs index 204e87eb9d9..b7e396c66ee 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -16,6 +16,8 @@ using Microsoft.AspNetCore.Http; using NuGet.Versioning; using LayoutSets = Altinn.Studio.Designer.Models.LayoutSets; +using Altinn.App.Core.Helpers; +using Altinn.Studio.Designer.EventHandlers.ComponentDeleted; namespace Altinn.Studio.Designer.Services.Implementation { @@ -552,5 +554,76 @@ public async Task AddComponentToLayout( layoutArray.Add(component); await SaveFormLayout(editingContext, layoutSetName, layoutName, formLayout, cancellationToken); } + + public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContext, List referencesToDelete, CancellationToken cancellationToken) + { + AltinnAppGitRepository altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository( + editingContext.Org, + editingContext.Repo, + editingContext.Developer); + + bool hasChanges = false; + + LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile(cancellationToken); + + var deletedLayoutsSetIds = referencesToDelete.Where(item => item.Type == "layoutSet").Select(item => item.Id).ToList(); + var deletedLayouts = referencesToDelete.Where(item => item.Type == "page").ToList(); + var deletedComponents = referencesToDelete.Where(item => item.Type == "component").ToList(); + + var filteredLayoutSets = layoutSets.Sets.Where(item => !deletedLayoutsSetIds.Contains(item.Id)).ToList(); + foreach (LayoutSetConfig layoutSet in filteredLayoutSets) + { + Dictionary formLayouts = await altinnAppGitRepository.GetFormLayouts(layoutSet.Id, cancellationToken); + + var deletedLayoutIds = deletedLayouts.Where(item => item.Type == "page" && item.LayoutSetName == layoutSet.Id).Select(item => item.Id).ToList(); + var filteredLayouts = formLayouts.Where(item => !deletedLayoutIds.Contains(item.Key)).ToList(); + foreach (KeyValuePair formLayout in filteredLayouts) + { + if (formLayout.Value["data"] is not JsonObject data || data["layout"] is not JsonArray layoutArray) + { + return false; + } + + int initialCount = layoutArray.Count; + layoutArray.RemoveAll(jsonNode => + { + string componentType = jsonNode["type"]?.GetValue(); + switch (componentType) + { + case "Subform": + return deletedLayoutsSetIds.Contains(jsonNode["layoutSet"]?.GetValue()); + case "Summary2": + if (jsonNode["target"] is not JsonObject targetObject) + { + return false; + } + + string type = targetObject["type"]?.GetValue(); + string id = targetObject["id"]?.GetValue(); + string taskId = targetObject["taskId"]?.GetValue(); + string layouSetId = string.IsNullOrEmpty(taskId) ? layoutSet.Id : layoutSets.Sets?.FirstOrDefault(item => item.Tasks?.Contains(taskId) ?? false)?.Id; + + return type switch + { + "layoutSet" => deletedLayoutsSetIds.Contains(layouSetId), + "page" => deletedLayouts.Exists(item => item.LayoutSetName == layouSetId && item.Id == id), + "component" => deletedComponents.Exists(item => item.LayoutSetName == layouSetId && item.Id == id), + _ => false, + }; + } + + return false; + }); + + if (layoutArray.Count != initialCount) + { + await altinnAppGitRepository.SaveLayout(layoutSet.Id, $"{formLayout.Key}.json", formLayout.Value, cancellationToken); + hasChanges = true; + } + } + } + + return hasChanges; + } } } diff --git a/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs b/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs index 8080312fae7..4e7faca61fd 100644 --- a/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs +++ b/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs @@ -3,6 +3,7 @@ using System.Threading; using System.Threading.Tasks; using Altinn.Studio.DataModeling.Metamodel; +using Altinn.Studio.Designer.EventHandlers.ComponentDeleted; using Altinn.Studio.Designer.Models; using JetBrains.Annotations; @@ -205,5 +206,13 @@ public Task GetModelMetadata( /// The component to add. /// An that observes if operation is cancelled. public Task AddComponentToLayout(AltinnRepoEditingContext altinnRepoEditingContext, string layoutSetName, string layoutName, object component, CancellationToken cancellationToken = default); + + /// + /// Delete references from layouts + /// + /// An . + /// The references to delete. + /// An that observes if operation is cancelled. + public Task DeleteFromLayouts(AltinnRepoEditingContext altinnRepoEditingContext, List referencesToDelete, CancellationToken cancellationToken); } } From 4279b30c8e46c2a1d1f5606dab9e6b12897610a9 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Thu, 5 Dec 2024 09:11:45 +0100 Subject: [PATCH 07/25] Cleanup --- .../ComponentDeleted/ComponentDeletedHandler.cs | 4 ++-- .../LayoutPageDeleted/LayoutPageDeletedHandler.cs | 10 +++++----- .../Services/Implementation/AppDevelopmentService.cs | 3 +-- .../Services/Interfaces/IAppDevelopmentService.cs | 1 - 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs index bddfcf8b8ed..86fd9617ff5 100644 --- a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs +++ b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs @@ -19,9 +19,9 @@ await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotifica "layouts", async () => { - List deletedIds = [new Reference("component", notification.LayoutSetName, notification.ComponentId)]; + List referencesToDelete = [new Reference("component", notification.LayoutSetName, notification.ComponentId)]; - return await appDevelopmentService.DeleteFromLayouts(notification.EditingContext, deletedIds, cancellationToken); + return await appDevelopmentService.DeleteFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); }); } } diff --git a/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs b/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs index 9b2026805a2..109942ca2f5 100644 --- a/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs +++ b/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs @@ -1,14 +1,14 @@ using System.Collections.Generic; +using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; using Altinn.Studio.Designer.Events; using Altinn.Studio.Designer.Hubs.SyncHub; using Altinn.Studio.Designer.Infrastructure.GitRepository; +using Altinn.Studio.Designer.Models; using Altinn.Studio.Designer.Services.Interfaces; using MediatR; -using System.Text.Json.Nodes; -using Altinn.Studio.Designer.Models; namespace Altinn.Studio.Designer.EventHandlers.LayoutPageDeleted; @@ -32,7 +32,7 @@ await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotifica JsonNode deletedLayout = await altinnAppGitRepository.GetLayout(notification.LayoutSetName, notification.LayoutName, cancellationToken); - List deletedIds = [new Reference("page", notification.LayoutSetName, notification.LayoutName)]; + List referencesToDelete = [new Reference("page", notification.LayoutSetName, notification.LayoutName)]; if (deletedLayout["data"] is not JsonObject data || data["layout"] is not JsonArray layoutArray) { return false; @@ -41,10 +41,10 @@ await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotifica foreach (JsonNode component in layoutArray) { string deletedId = component["id"]?.GetValue(); - deletedIds.Add(new Reference("component", notification.LayoutSetName, deletedId)); + referencesToDelete.Add(new Reference("component", notification.LayoutSetName, deletedId)); } - return await appDevelopmentService.DeleteFromLayouts(notification.EditingContext, deletedIds, cancellationToken); + return await appDevelopmentService.DeleteFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); }); } } diff --git a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs index b7e396c66ee..72f77cf3caa 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -6,6 +6,7 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Altinn.App.Core.Helpers; using Altinn.App.Core.Models; using Altinn.Studio.DataModeling.Metamodel; using Altinn.Studio.Designer.Exceptions.AppDevelopment; @@ -16,8 +17,6 @@ using Microsoft.AspNetCore.Http; using NuGet.Versioning; using LayoutSets = Altinn.Studio.Designer.Models.LayoutSets; -using Altinn.App.Core.Helpers; -using Altinn.Studio.Designer.EventHandlers.ComponentDeleted; namespace Altinn.Studio.Designer.Services.Implementation { diff --git a/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs b/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs index 4e7faca61fd..e0cdf62c813 100644 --- a/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs +++ b/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs @@ -3,7 +3,6 @@ using System.Threading; using System.Threading.Tasks; using Altinn.Studio.DataModeling.Metamodel; -using Altinn.Studio.Designer.EventHandlers.ComponentDeleted; using Altinn.Studio.Designer.Models; using JetBrains.Annotations; From f058f90082486ad52c3031c24b918ce17ca4868b Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Fri, 6 Dec 2024 16:05:47 +0100 Subject: [PATCH 08/25] Fix tests --- .../AppDevelopmentController/SaveFormLayoutTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs index b007cf38ec6..9cae7047ad5 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using System.Net; using System.Net.Http; using System.Net.Mime; @@ -95,8 +95,8 @@ public async Task SaveFormLayoutWithComponentIdsChange_ReturnsOk(string org, str } [Theory] - [InlineData("ttd", "testUser", "Side1", "form")] - public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummaryComponents_ReturnsOk(string org, string developer, string layoutName, string layoutSetName) + [InlineData("ttd", "testUser", "form", "Side1")] + public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummaryComponents_ReturnsOk(string org, string developer, string layoutSetName, string layoutName) { string actualApp = "deleted-component-before-delete"; string app = TestDataHelper.GenerateTestRepoName(); From 4e204a46c061a253358305d1c6711f7f2ce0b56f Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Fri, 6 Dec 2024 17:50:15 +0100 Subject: [PATCH 09/25] Fix tests --- .../SaveFormLayoutTests.cs | 2 +- .../App/ui/layout-sets.json | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout-sets.json diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs index 9cae7047ad5..2b0b75f4781 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs @@ -102,7 +102,7 @@ public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummaryCom string app = TestDataHelper.GenerateTestRepoName(); await CopyRepositoryForTest(org, actualApp, developer, app); - string layout = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{layoutSetName}/layouts/{layoutName}.json"); + string layout = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{layoutSetName}/layouts/{layoutName}.json"); JsonNode layoutWithDeletedComponent = JsonNode.Parse(layout); JsonArray layoutArray = layoutWithDeletedComponent["data"]["layout"] as JsonArray; layoutArray.RemoveAt(0); diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout-sets.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout-sets.json new file mode 100644 index 00000000000..364af0f0d51 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout-sets.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout-sets.schema.v1.json", + "sets": [ + { + "id": "form", + "dataType": "model", + "tasks": [ + "Task_1" + ] + }, + { + "id": "Activity_0z4cgvm", + "tasks": [ + "Activity_0z4cgvm" + ] + } + ], + "uiSettings": {} + } From bda8b14f2253777e9bc1cd2f17bbc82b5bf9788e Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Fri, 6 Dec 2024 17:51:11 +0100 Subject: [PATCH 10/25] Fix SaveFormLayout --- .../Controllers/AppDevelopmentController.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/backend/src/Designer/Controllers/AppDevelopmentController.cs b/backend/src/Designer/Controllers/AppDevelopmentController.cs index d404696e300..8e816379254 100644 --- a/backend/src/Designer/Controllers/AppDevelopmentController.cs +++ b/backend/src/Designer/Controllers/AppDevelopmentController.cs @@ -136,14 +136,16 @@ await _mediator.Publish(new ComponentDeletedEvent EditingContext = editingContext }, cancellationToken); } - - await _mediator.Publish(new ComponentIdChangedEvent + else { - OldComponentId = componentIdChange.OldComponentId, - NewComponentId = componentIdChange.NewComponentId, - LayoutSetName = layoutSetName, - EditingContext = editingContext - }, cancellationToken); + await _mediator.Publish(new ComponentIdChangedEvent + { + OldComponentId = componentIdChange.OldComponentId, + NewComponentId = componentIdChange.NewComponentId, + LayoutSetName = layoutSetName, + EditingContext = editingContext + }, cancellationToken); + } } } } From c85740d7d5ece444d3cfeb5b4a2bde56140248fd Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Sun, 15 Dec 2024 18:28:22 +0100 Subject: [PATCH 11/25] Cleanup overrides --- .../Controllers/AppDevelopmentController.cs | 15 ++-- .../LayoutPageDeletedHandler.cs | 2 +- .../Implementation/AppDevelopmentService.cs | 84 +++++++++++++------ .../DeleteFormLayoutTests.cs | 33 ++++++++ .../DeleteLayoutSetTests.cs | 31 +++++++ .../SaveFormLayoutTests.cs | 16 ++-- .../ui/Activity_0z4cgvm/layouts/Side3.json | 31 ------- .../App/ui/component/Settings.json | 9 ++ .../App/ui/component/layouts/Side1.json | 49 +++++++++++ .../layouts/Side2.json} | 5 +- .../App/ui/component2/Settings.json | 9 ++ .../App/ui/component2/layouts/Side1.json | 56 +++++++++++++ .../App/ui/component2/layouts/Side2.json | 49 +++++++++++ .../App/ui/layout-sets.json | 36 ++++++++ .../App/ui/layout/Settings.json | 8 ++ .../App/ui/layout/layouts/Side1.json} | 14 ++-- .../App/ui/layout2/Settings.json | 9 ++ .../App/ui/layout2/layouts/Side1.json | 53 ++++++++++++ .../Side3.json => layout2/layouts/Side2.json} | 18 ++-- .../App/ui/layoutSet2/Settings.json | 9 ++ .../App/ui/layoutSet2/layouts/Side1.json | 54 ++++++++++++ .../layouts/Side2.json | 2 +- .../ui/Activity_0z4cgvm/layouts/Side1.json | 22 ----- .../ui/Activity_0z4cgvm/layouts/Side2.json | 22 ----- .../ui/Activity_0z4cgvm/layouts/Side3.json | 31 ------- .../App/ui/component/Settings.json | 9 ++ .../App/ui/component/layouts/Side1.json | 64 ++++++++++++++ .../layouts/Side2.json} | 16 +--- .../App/ui/component2/Settings.json | 9 ++ .../App/ui/component2/layouts/Side1.json | 56 +++++++++++++ .../App/ui/component2/layouts/Side2.json | 64 ++++++++++++++ .../App/ui/form/layouts/Side2.json | 22 ----- .../App/ui/layout-sets.json | 59 +++++++++---- .../App/ui/layout/Settings.json | 9 ++ .../App/ui/layout/layouts/Side1.json | 49 +++++++++++ .../App/ui/layout}/layouts/Side2.json | 9 +- .../App/ui/layout2/Settings.json | 9 ++ .../App/ui/layout2/layouts/Side1.json | 53 ++++++++++++ .../App/ui/layout2/layouts/Side2.json | 49 +++++++++++ .../App/ui/layoutSet/Settings.json | 9 ++ .../App/ui/layoutSet}/layouts/Side1.json | 2 +- .../App/ui/layoutSet/layouts/Side2.json | 20 +++++ .../App/ui/layoutSet2/Settings.json | 9 ++ .../App/ui/layoutSet2/layouts/Side1.json | 54 ++++++++++++ .../App/ui/layoutSet2/layouts/Side2.json | 49 +++++++++++ 45 files changed, 1061 insertions(+), 226 deletions(-) delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/layouts/Side1.json rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/{form/layouts/Side1.json => component/layouts/Side2.json} (80%) create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout-sets.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout/Settings.json rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete/App/ui/form/layouts/Side3.json => deleted-component-after-delete/App/ui/layout/layouts/Side1.json} (70%) create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/layouts/Side1.json rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/{form/layouts/Side3.json => layout2/layouts/Side2.json} (64%) create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/layouts/Side1.json rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/{Activity_0z4cgvm => layoutSet2}/layouts/Side2.json (86%) delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/layouts/Side1.json rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/{form/layouts/Side1.json => component/layouts/Side2.json} (61%) create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/layouts/Side2.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/layouts/Side1.json rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete/App/ui/form => deleted-component-before-delete/App/ui/layout}/layouts/Side2.json (59%) create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/Settings.json rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete/App/ui/Activity_0z4cgvm => deleted-component-before-delete/App/ui/layoutSet}/layouts/Side1.json (86%) create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/layouts/Side2.json diff --git a/backend/src/Designer/Controllers/AppDevelopmentController.cs b/backend/src/Designer/Controllers/AppDevelopmentController.cs index 8e816379254..1e11e86009e 100644 --- a/backend/src/Designer/Controllers/AppDevelopmentController.cs +++ b/backend/src/Designer/Controllers/AppDevelopmentController.cs @@ -136,16 +136,13 @@ await _mediator.Publish(new ComponentDeletedEvent EditingContext = editingContext }, cancellationToken); } - else + await _mediator.Publish(new ComponentIdChangedEvent { - await _mediator.Publish(new ComponentIdChangedEvent - { - OldComponentId = componentIdChange.OldComponentId, - NewComponentId = componentIdChange.NewComponentId, - LayoutSetName = layoutSetName, - EditingContext = editingContext - }, cancellationToken); - } + OldComponentId = componentIdChange.OldComponentId, + NewComponentId = componentIdChange.NewComponentId, + LayoutSetName = layoutSetName, + EditingContext = editingContext + }, cancellationToken); } } } diff --git a/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs b/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs index 109942ca2f5..0310f63757c 100644 --- a/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs +++ b/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs @@ -30,7 +30,7 @@ await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotifica notification.EditingContext.Repo, notification.EditingContext.Developer); - JsonNode deletedLayout = await altinnAppGitRepository.GetLayout(notification.LayoutSetName, notification.LayoutName, cancellationToken); + JsonNode deletedLayout = await altinnAppGitRepository.GetLayout(notification.LayoutSetName, $"{notification.LayoutName}.json", cancellationToken); List referencesToDelete = [new Reference("page", notification.LayoutSetName, notification.LayoutName)]; if (deletedLayout["data"] is not JsonObject data || data["layout"] is not JsonArray layoutArray) diff --git a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs index 72f77cf3caa..0c0b0505136 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -561,7 +561,7 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex editingContext.Repo, editingContext.Developer); - bool hasChanges = false; + bool hasLayoutSetChanges = false; LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile(cancellationToken); @@ -572,6 +572,8 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex var filteredLayoutSets = layoutSets.Sets.Where(item => !deletedLayoutsSetIds.Contains(item.Id)).ToList(); foreach (LayoutSetConfig layoutSet in filteredLayoutSets) { + bool hasLayoutChanges = false; + Dictionary formLayouts = await altinnAppGitRepository.GetFormLayouts(layoutSet.Id, cancellationToken); var deletedLayoutIds = deletedLayouts.Where(item => item.Type == "page" && item.LayoutSetName == layoutSet.Id).Select(item => item.Id).ToList(); @@ -583,46 +585,76 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex return false; } - int initialCount = layoutArray.Count; - layoutArray.RemoveAll(jsonNode => + for (int i = layoutArray.Count - 1; i >= 0; i--) { - string componentType = jsonNode["type"]?.GetValue(); + JsonNode jsonNode = layoutArray[i]; + if (jsonNode is not JsonObject jsonObject) + { + continue; + } + string componentType = jsonObject["type"]?.GetValue(); switch (componentType) { case "Subform": - return deletedLayoutsSetIds.Contains(jsonNode["layoutSet"]?.GetValue()); - case "Summary2": - if (jsonNode["target"] is not JsonObject targetObject) + if (deletedLayoutsSetIds.Contains(jsonObject["layoutSet"]?.GetValue())) { - return false; + layoutArray.RemoveAt(i); + hasLayoutChanges = true; } - - string type = targetObject["type"]?.GetValue(); - string id = targetObject["id"]?.GetValue(); - string taskId = targetObject["taskId"]?.GetValue(); - string layouSetId = string.IsNullOrEmpty(taskId) ? layoutSet.Id : layoutSets.Sets?.FirstOrDefault(item => item.Tasks?.Contains(taskId) ?? false)?.Id; - - return type switch + break; + case "Summary2": + if (jsonObject["target"] is JsonObject targetObject) { - "layoutSet" => deletedLayoutsSetIds.Contains(layouSetId), - "page" => deletedLayouts.Exists(item => item.LayoutSetName == layouSetId && item.Id == id), - "component" => deletedComponents.Exists(item => item.LayoutSetName == layouSetId && item.Id == id), - _ => false, - }; + string type = targetObject["type"]?.GetValue(); + string id = targetObject["id"]?.GetValue(); + string taskId = targetObject["taskId"]?.GetValue(); + string layouSetId = string.IsNullOrEmpty(taskId) ? layoutSet.Id : layoutSets.Sets?.FirstOrDefault(item => item.Tasks?.Contains(taskId) ?? false)?.Id; + + if (type switch + { + "layoutSet" => deletedLayoutsSetIds.Contains(layouSetId), + "page" => deletedLayouts.Exists(item => item.LayoutSetName == layouSetId && item.Id == id), + "component" => deletedComponents.Exists(item => item.LayoutSetName == layouSetId && item.Id == id), + _ => false + }) + { + layoutArray.RemoveAt(i); + hasLayoutChanges = true; + } + + if (jsonNode["overrides"] is JsonArray overridesArray) + { + overridesArray.RemoveAll(overrideObject => + { + string componentId = overrideObject["componentId"]?.GetValue(); + if (deletedComponents.Exists(item => item.LayoutSetName == layouSetId && item.Id == componentId)) + { + hasLayoutChanges = true; + return true; + } + + return false; + }); + + if (overridesArray.Count == 0) + { + jsonObject.Remove("overrides"); + } + } + } + break; } + } - return false; - }); - - if (layoutArray.Count != initialCount) + if (hasLayoutChanges) { await altinnAppGitRepository.SaveLayout(layoutSet.Id, $"{formLayout.Key}.json", formLayout.Value, cancellationToken); - hasChanges = true; + hasLayoutSetChanges = true; } } } - return hasChanges; + return hasLayoutSetChanges; } } } diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteFormLayoutTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteFormLayoutTests.cs index 07ad105e57f..f371c0a1f62 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteFormLayoutTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteFormLayoutTests.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Linq; using System.Net; using System.Net.Http; using System.Threading.Tasks; @@ -7,6 +8,7 @@ using FluentAssertions; using JetBrains.Annotations; using Microsoft.AspNetCore.Mvc.Testing; +using SharedResources.Tests; using Xunit; namespace Designer.Tests.Controllers.AppDevelopmentController @@ -55,5 +57,36 @@ public async Task DeleteFormLayout_NonExistingFile_Should_AndReturnNotFound(stri using var response = await HttpClient.SendAsync(httpRequestMessage); response.StatusCode.Should().Be(HttpStatusCode.NotFound); } + + [Theory] + [InlineData("ttd", "testUser", "layout", "Side2")] + public async Task DeleteFormLayout_DeletesAssociatedSummaryComponents_ReturnsOk(string org, string developer, string layoutSetName, string layoutName) + { + string actualApp = "deleted-component-before-delete"; + string app = TestDataHelper.GenerateTestRepoName(); + await CopyRepositoryForTest(org, actualApp, developer, app); + + string url = $"{VersionPrefix(org, app)}/form-layout/{layoutName}?layoutSetName={layoutSetName}"; + using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Delete, url); + + using var response = await HttpClient.SendAsync(httpRequestMessage); + response.StatusCode.Should().Be(HttpStatusCode.OK); + + string expectedApp = "deleted-component-after-delete"; + + string[] layoutPaths = [ + "layout/layouts/Side1.json", + "layout/layouts/Side2.json", + "layout2/layouts/Side1.json", + "layout2/layouts/Side2.json", + ]; + + layoutPaths.ToList().ForEach(file => + { + string actual = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{file}"); + string expected = TestDataHelper.GetFileFromRepo(org, expectedApp, developer, $"App/ui/{file}"); + JsonUtils.DeepEquals(actual, expected).Should().BeTrue(); + }); + } } } diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteLayoutSetTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteLayoutSetTests.cs index 8acf823a8a2..48d09965cec 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteLayoutSetTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteLayoutSetTests.cs @@ -160,6 +160,37 @@ public async Task DeleteLayoutSet_RemovesComponentsReferencingLayoutSet(string o $"No components should reference the deleted layout set {deletedComponentId}"); } + [Theory] + [InlineData("ttd", "testUser", "layoutSet")] + public async Task DeleteLayoutSet_DeletesAssociatedSummaryComponents_ReturnsOk(string org, string developer, string layoutSetName) + { + string actualApp = "deleted-component-before-delete"; + string app = TestDataHelper.GenerateTestRepoName(); + await CopyRepositoryForTest(org, actualApp, developer, app); + + string url = $"{VersionPrefix(org, app)}/layout-set/{layoutSetName}"; + using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Delete, url); + + using var response = await HttpClient.SendAsync(httpRequestMessage); + response.StatusCode.Should().Be(HttpStatusCode.OK, await response.Content.ReadAsStringAsync()); + + string expectedApp = "deleted-component-after-delete"; + + string[] layoutPaths = [ + "layoutSet/layouts/Side1.json", + "layoutSet/layouts/Side2.json", + "layoutSet2/layouts/Side1.json", + "layoutSet2/layouts/Side2.json" + ]; + + layoutPaths.ToList().ForEach(file => + { + string actual = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{file}"); + string expected = TestDataHelper.GetFileFromRepo(org, expectedApp, developer, $"App/ui/{file}"); + JsonUtils.DeepEquals(actual, expected).Should().BeTrue(); + }); + } + private async Task GetLayoutSetsFile(string org, string app, string developer) { AltinnGitRepositoryFactory altinnGitRepositoryFactory = diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs index 2b0b75f4781..79f8012d032 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs @@ -95,8 +95,8 @@ public async Task SaveFormLayoutWithComponentIdsChange_ReturnsOk(string org, str } [Theory] - [InlineData("ttd", "testUser", "form", "Side1")] - public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummaryComponents_ReturnsOk(string org, string developer, string layoutSetName, string layoutName) + [InlineData("ttd", "testUser", "component", "Side2", "Input-Om7N3y")] + public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummaryComponents_ReturnsOk(string org, string developer, string layoutSetName, string layoutName, string componentId) { string actualApp = "deleted-component-before-delete"; string app = TestDataHelper.GenerateTestRepoName(); @@ -113,7 +113,7 @@ public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummaryCom ["componentIdsChange"] = new JsonArray() { new JsonObject { - ["oldComponentId"] = "Input-XDDxRp", + ["oldComponentId"] = componentId, } }, ["layout"] = layoutWithDeletedComponent @@ -124,12 +124,10 @@ public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummaryCom string expectedApp = "deleted-component-after-delete"; string[] layoutPaths = [ - "form/layouts/Side1.json", - "form/layouts/Side2.json", - "form/layouts/Side3.json", - "Activity_0z4cgvm/layouts/Side1.json", - "Activity_0z4cgvm/layouts/Side2.json", - "Activity_0z4cgvm/layouts/Side3.json" + "component/layouts/Side1.json", + "component/layouts/Side2.json", + "component2/layouts/Side1.json", + "component2/layouts/Side2.json" ]; layoutPaths.ToList().ForEach(file => diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json deleted file mode 100644 index cbcfcc70d95..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "target": { - "type": "component", - "id": "Input-1GAVAE", - "taskId": "Task_1" - }, - "id": "Summary2-PBrjWH", - "type": "Summary2" - }, - { - "target": { - "type": "component", - "id": "", - "taskId": "" - }, - "id": "Summary2-WokR5T", - "type": "Summary2" - }, - { - "id": "NavigationButtons-Knkbt3", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/layouts/Side1.json new file mode 100644 index 00000000000..880092a7380 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/layouts/Side1.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "" + }, + "id": "Summary2-9iG1lB", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "" + }, + "id": "Summary2-R8HsuB", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-mL8NjJ", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-qWr0oa", + "taskId": "" + }, + "id": "Summary2-0BV88Q", + "type": "Summary2" + }, + { + "id": "NavigationButtons-DfcNol", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/layouts/Side2.json similarity index 80% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/layouts/Side2.json index 099450bd77d..1fc7b9c90e0 100644 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side1.json +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/layouts/Side2.json @@ -1,17 +1,16 @@ { "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", "data": { - "hidden": false, "layout": [ { "dataModelBindings": { "simpleBinding": "" }, - "id": "Input-1GAVAE", + "id": "Input-qWr0oa", "type": "Input" }, { - "id": "NavigationButtons-C2O3bE", + "id": "NavigationButtons-GAW8Dx", "showBackButton": true, "textResourceBindings": {}, "type": "NavigationButtons" diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/layouts/Side1.json new file mode 100644 index 00000000000..8489464261c --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/layouts/Side1.json @@ -0,0 +1,56 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-LCr3oK", + "type": "Input" + }, + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "" + }, + "id": "Summary2-eoT5QK", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "" + }, + "id": "Summary2-NJfE92", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-BGHvph", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-LCr3oK", + "taskId": "" + }, + "id": "Summary2-rb2ml2", + "type": "Summary2" + }, + { + "id": "NavigationButtons-t7UTGJ", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/layouts/Side2.json new file mode 100644 index 00000000000..5ebc0f7df8b --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/layouts/Side2.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "component" + }, + "id": "Summary2-2FSqcf", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "component" + }, + "id": "Summary2-eGrDpP", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "component" + }, + "id": "Summary2-uJDgMu", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-qWr0oa", + "taskId": "component" + }, + "id": "Summary2-2JiT3P", + "type": "Summary2" + }, + { + "id": "NavigationButtons-BYcvaT", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout-sets.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout-sets.json new file mode 100644 index 00000000000..f916f692bec --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout-sets.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout-sets.schema.v1.json", + "sets": [ + { + "id": "component", + "tasks": [ + "component" + ] + }, + { + "id": "layout", + "tasks": [ + "layout" + ] + }, + { + "id": "component2", + "tasks": [ + "component2" + ] + }, + { + "id": "layout2", + "tasks": [ + "layout2" + ] + }, + { + "id": "layoutSet2", + "tasks": [ + "layoutSet2" + ] + } + ], + "uiSettings": {} +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout/Settings.json new file mode 100644 index 00000000000..b40e33a3211 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout/Settings.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side3.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout/layouts/Side1.json similarity index 70% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side3.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout/layouts/Side1.json index 09e48f21de0..2f467af518a 100644 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side3.json +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout/layouts/Side1.json @@ -4,24 +4,24 @@ "layout": [ { "target": { - "type": "component", - "id": "Input-1GAVAE", + "type": "layoutSet", + "id": "", "taskId": "" }, - "id": "Summary2-GcK8zp", + "id": "Summary2-FEI1HC", "type": "Summary2" }, { "target": { - "type": "component", - "id": "", + "type": "page", + "id": "Side1", "taskId": "" }, - "id": "Summary2-3TdVTp", + "id": "Summary2-e2yYpk", "type": "Summary2" }, { - "id": "NavigationButtons-tIAlCU", + "id": "NavigationButtons-7g3XcW", "showBackButton": true, "textResourceBindings": {}, "type": "NavigationButtons" diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/layouts/Side1.json new file mode 100644 index 00000000000..2530921cc4e --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/layouts/Side1.json @@ -0,0 +1,53 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-QCSonu", + "type": "Input" + }, + { + "target": { + "type": "layoutSet", + "id": "" + }, + "id": "Summary2-18hFaH", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1" + }, + "id": "Summary2-iZJ80j", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-V55C6Q", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-QCSonu" + }, + "id": "Summary2-aI91Tv", + "type": "Summary2" + }, + { + "id": "NavigationButtons-2hGPi1", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side3.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/layouts/Side2.json similarity index 64% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side3.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/layouts/Side2.json index 09e48f21de0..edd72d878e9 100644 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side3.json +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/layouts/Side2.json @@ -4,24 +4,24 @@ "layout": [ { "target": { - "type": "component", - "id": "Input-1GAVAE", - "taskId": "" + "type": "layoutSet", + "id": "", + "taskId": "layout" }, - "id": "Summary2-GcK8zp", + "id": "Summary2-MfRiX8", "type": "Summary2" }, { "target": { - "type": "component", - "id": "", - "taskId": "" + "type": "page", + "id": "Side1", + "taskId": "layout" }, - "id": "Summary2-3TdVTp", + "id": "Summary2-66YavC", "type": "Summary2" }, { - "id": "NavigationButtons-tIAlCU", + "id": "NavigationButtons-h0g3Wt", "showBackButton": true, "textResourceBindings": {}, "type": "NavigationButtons" diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/layouts/Side1.json new file mode 100644 index 00000000000..60fc1029c15 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/layouts/Side1.json @@ -0,0 +1,54 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-wrspcN", + "type": "Input" + }, + { + "target": { + "type": "layoutSet", + "id": "" + }, + "id": "Summary2-00SFBO", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1" + }, + "id": "Summary2-4069IB", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-Orxmu1", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-wrspcN", + "taskId": "" + }, + "id": "Summary2-2YoJGY", + "type": "Summary2" + }, + { + "id": "NavigationButtons-KnXA9y", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/layouts/Side2.json similarity index 86% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/layouts/Side2.json index e64197d78e5..ba9b66dff54 100644 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/layouts/Side2.json @@ -3,7 +3,7 @@ "data": { "layout": [ { - "id": "NavigationButtons-GAW8Dx", + "id": "NavigationButtons-5ukC2N", "showBackButton": true, "textResourceBindings": {}, "type": "NavigationButtons" diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json deleted file mode 100644 index ef246f0cc61..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "target": { - "type": "component", - "id": "Input-XDDxRp", - "taskId": "Task_1" - }, - "id": "Summary2-QN78Y8", - "type": "Summary2" - }, - { - "id": "NavigationButtons-DfcNol", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json deleted file mode 100644 index 36a45150d8d..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side2.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "target": { - "type": "component", - "id": "Input-XDDxRp", - "taskId": "Task_1" - }, - "id": "Summary2-9OFVzC", - "type": "Summary2" - }, - { - "id": "NavigationButtons-GAW8Dx", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json deleted file mode 100644 index cbcfcc70d95..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/Activity_0z4cgvm/layouts/Side3.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "target": { - "type": "component", - "id": "Input-1GAVAE", - "taskId": "Task_1" - }, - "id": "Summary2-PBrjWH", - "type": "Summary2" - }, - { - "target": { - "type": "component", - "id": "", - "taskId": "" - }, - "id": "Summary2-WokR5T", - "type": "Summary2" - }, - { - "id": "NavigationButtons-Knkbt3", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/layouts/Side1.json new file mode 100644 index 00000000000..112caa4c318 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/layouts/Side1.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "" + }, + "id": "Summary2-9iG1lB", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "" + }, + "id": "Summary2-R8HsuB", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-mL8NjJ", + "type": "Summary2", + "overrides": [ + { + "componentId": "Input-Om7N3y", + "displayType": "string" + } + ] + }, + { + "target": { + "type": "component", + "id": "Input-qWr0oa", + "taskId": "" + }, + "id": "Summary2-0BV88Q", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-Om7N3y", + "taskId": "" + }, + "id": "Summary2-dTepe0", + "type": "Summary2" + }, + { + "id": "NavigationButtons-DfcNol", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/layouts/Side2.json similarity index 61% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/layouts/Side2.json index f4fd400bbfe..3989fafc6be 100644 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side1.json +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/layouts/Side2.json @@ -1,33 +1,23 @@ { "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", "data": { - "hidden": false, "layout": [ { "dataModelBindings": { "simpleBinding": "" }, - "id": "Input-XDDxRp", + "id": "Input-Om7N3y", "type": "Input" }, { "dataModelBindings": { "simpleBinding": "" }, - "id": "Input-1GAVAE", + "id": "Input-qWr0oa", "type": "Input" }, { - "target": { - "type": "component", - "id": "Input-XDDxRp", - "taskId": "" - }, - "id": "Summary2-qx7wBR", - "type": "Summary2" - }, - { - "id": "NavigationButtons-C2O3bE", + "id": "NavigationButtons-GAW8Dx", "showBackButton": true, "textResourceBindings": {}, "type": "NavigationButtons" diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/layouts/Side1.json new file mode 100644 index 00000000000..8489464261c --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/layouts/Side1.json @@ -0,0 +1,56 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-LCr3oK", + "type": "Input" + }, + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "" + }, + "id": "Summary2-eoT5QK", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "" + }, + "id": "Summary2-NJfE92", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-BGHvph", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-LCr3oK", + "taskId": "" + }, + "id": "Summary2-rb2ml2", + "type": "Summary2" + }, + { + "id": "NavigationButtons-t7UTGJ", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/layouts/Side2.json new file mode 100644 index 00000000000..b754c0caf49 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/layouts/Side2.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "component" + }, + "id": "Summary2-2FSqcf", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "component" + }, + "id": "Summary2-eGrDpP", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "component" + }, + "id": "Summary2-uJDgMu", + "type": "Summary2", + "overrides": [ + { + "componentId": "Input-Om7N3y", + "displayType": "string" + } + ] + }, + { + "target": { + "type": "component", + "id": "Input-qWr0oa", + "taskId": "component" + }, + "id": "Summary2-2JiT3P", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-Om7N3y", + "taskId": "component" + }, + "id": "Summary2-vIXkWO", + "type": "Summary2" + }, + { + "id": "NavigationButtons-BYcvaT", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side2.json deleted file mode 100644 index 308fdbb3a4d..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/form/layouts/Side2.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "target": { - "type": "component", - "id": "Input-XDDxRp", - "taskId": "" - }, - "id": "Summary2-sopfsr", - "type": "Summary2" - }, - { - "id": "NavigationButtons-TFHw9D", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout-sets.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout-sets.json index 364af0f0d51..536ae9da2c2 100644 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout-sets.json +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout-sets.json @@ -1,19 +1,42 @@ { - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout-sets.schema.v1.json", - "sets": [ - { - "id": "form", - "dataType": "model", - "tasks": [ - "Task_1" - ] - }, - { - "id": "Activity_0z4cgvm", - "tasks": [ - "Activity_0z4cgvm" - ] - } - ], - "uiSettings": {} - } + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout-sets.schema.v1.json", + "sets": [ + { + "id": "component", + "tasks": [ + "component" + ] + }, + { + "id": "layout", + "tasks": [ + "layout" + ] + }, + { + "id": "layoutSet", + "tasks": [ + "layoutSet" + ] + }, + { + "id": "component2", + "tasks": [ + "component2" + ] + }, + { + "id": "layout2", + "tasks": [ + "layout2" + ] + }, + { + "id": "layoutSet2", + "tasks": [ + "layoutSet2" + ] + } + ], + "uiSettings": {} +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/layouts/Side1.json new file mode 100644 index 00000000000..a7e9078479d --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/layouts/Side1.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "" + }, + "id": "Summary2-FEI1HC", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "" + }, + "id": "Summary2-e2yYpk", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-qOn2O1", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-AVRSNf", + "taskId": "" + }, + "id": "Summary2-da0Tq6", + "type": "Summary2" + }, + { + "id": "NavigationButtons-7g3XcW", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/layouts/Side2.json similarity index 59% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side2.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/layouts/Side2.json index 69152361ed1..8b8ea337e26 100644 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/form/layouts/Side2.json +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/layouts/Side2.json @@ -3,7 +3,14 @@ "data": { "layout": [ { - "id": "NavigationButtons-TFHw9D", + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-AVRSNf", + "type": "Input" + }, + { + "id": "NavigationButtons-wDmNQu", "showBackButton": true, "textResourceBindings": {}, "type": "NavigationButtons" diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/layouts/Side1.json new file mode 100644 index 00000000000..2530921cc4e --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/layouts/Side1.json @@ -0,0 +1,53 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-QCSonu", + "type": "Input" + }, + { + "target": { + "type": "layoutSet", + "id": "" + }, + "id": "Summary2-18hFaH", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1" + }, + "id": "Summary2-iZJ80j", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-V55C6Q", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-QCSonu" + }, + "id": "Summary2-aI91Tv", + "type": "Summary2" + }, + { + "id": "NavigationButtons-2hGPi1", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/layouts/Side2.json new file mode 100644 index 00000000000..6f3ad889e8f --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/layouts/Side2.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "layout" + }, + "id": "Summary2-MfRiX8", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "layout" + }, + "id": "Summary2-66YavC", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "layout" + }, + "id": "Summary2-bmqvUb", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-AVRSNf", + "taskId": "layout" + }, + "id": "Summary2-uuKXTD", + "type": "Summary2" + }, + { + "id": "NavigationButtons-h0g3Wt", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/layouts/Side1.json similarity index 86% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/layouts/Side1.json index d23b7e0802a..48f8a1f9cf7 100644 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/Activity_0z4cgvm/layouts/Side1.json +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/layouts/Side1.json @@ -3,7 +3,7 @@ "data": { "layout": [ { - "id": "NavigationButtons-DfcNol", + "id": "NavigationButtons-n2jUp6", "showBackButton": true, "textResourceBindings": {}, "type": "NavigationButtons" diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/layouts/Side2.json new file mode 100644 index 00000000000..6fa6e9455ff --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/layouts/Side2.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-hqcYqo", + "type": "Input" + }, + { + "id": "NavigationButtons-QzkEka", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/layouts/Side1.json new file mode 100644 index 00000000000..60fc1029c15 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/layouts/Side1.json @@ -0,0 +1,54 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-wrspcN", + "type": "Input" + }, + { + "target": { + "type": "layoutSet", + "id": "" + }, + "id": "Summary2-00SFBO", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1" + }, + "id": "Summary2-4069IB", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-Orxmu1", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-wrspcN", + "taskId": "" + }, + "id": "Summary2-2YoJGY", + "type": "Summary2" + }, + { + "id": "NavigationButtons-KnXA9y", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/layouts/Side2.json new file mode 100644 index 00000000000..c49447d2904 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/layouts/Side2.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "layoutSet" + }, + "id": "Summary2-6VQ3LC", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "layoutSet" + }, + "id": "Summary2-LZxPWb", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "layoutSet" + }, + "id": "Summary2-El9z2Y", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-hqcYqo", + "taskId": "layoutSet" + }, + "id": "Summary2-SMqpYV", + "type": "Summary2" + }, + { + "id": "NavigationButtons-5ukC2N", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file From dcaeb943ac3b7d11dec795d1a8b59d667b935cd8 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Mon, 16 Dec 2024 15:47:30 +0100 Subject: [PATCH 12/25] Recursive deletion --- .../ComponentDeletedHandler.cs | 1 - .../LayoutPageDeletedHandler.cs | 26 +-------- .../LayoutSetDeletedComponentRefHandler.cs | 30 +---------- .../Implementation/AppDevelopmentService.cs | 54 +++++++++++++++---- 4 files changed, 47 insertions(+), 64 deletions(-) diff --git a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs index 86fd9617ff5..235925d580b 100644 --- a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs +++ b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs @@ -20,7 +20,6 @@ await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotifica async () => { List referencesToDelete = [new Reference("component", notification.LayoutSetName, notification.ComponentId)]; - return await appDevelopmentService.DeleteFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); }); } diff --git a/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs b/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs index 0310f63757c..01da6286892 100644 --- a/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs +++ b/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs @@ -1,21 +1,15 @@ - using System.Collections.Generic; -using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; using Altinn.Studio.Designer.Events; using Altinn.Studio.Designer.Hubs.SyncHub; -using Altinn.Studio.Designer.Infrastructure.GitRepository; using Altinn.Studio.Designer.Models; using Altinn.Studio.Designer.Services.Interfaces; using MediatR; namespace Altinn.Studio.Designer.EventHandlers.LayoutPageDeleted; -public class LayoutPageDeletedHandler( - IFileSyncHandlerExecutor fileSyncHandlerExecutor, - IAppDevelopmentService appDevelopmentService, - IAltinnGitRepositoryFactory altinnGitRepositoryFactory) : INotificationHandler +public class LayoutPageDeletedHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler { public async Task Handle(LayoutPageDeletedEvent notification, CancellationToken cancellationToken) { @@ -25,25 +19,7 @@ await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotifica "layouts", async () => { - AltinnAppGitRepository altinnAppGitRepository = altinnGitRepositoryFactory.GetAltinnAppGitRepository( - notification.EditingContext.Org, - notification.EditingContext.Repo, - notification.EditingContext.Developer); - - JsonNode deletedLayout = await altinnAppGitRepository.GetLayout(notification.LayoutSetName, $"{notification.LayoutName}.json", cancellationToken); - List referencesToDelete = [new Reference("page", notification.LayoutSetName, notification.LayoutName)]; - if (deletedLayout["data"] is not JsonObject data || data["layout"] is not JsonArray layoutArray) - { - return false; - } - - foreach (JsonNode component in layoutArray) - { - string deletedId = component["id"]?.GetValue(); - referencesToDelete.Add(new Reference("component", notification.LayoutSetName, deletedId)); - } - return await appDevelopmentService.DeleteFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); }); } diff --git a/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedComponentRefHandler.cs b/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedComponentRefHandler.cs index f0835ffed80..b31de8808f9 100644 --- a/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedComponentRefHandler.cs +++ b/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedComponentRefHandler.cs @@ -1,53 +1,25 @@ using System.Collections.Generic; -using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; using Altinn.Studio.Designer.Events; using Altinn.Studio.Designer.Hubs.SyncHub; -using Altinn.Studio.Designer.Infrastructure.GitRepository; using Altinn.Studio.Designer.Models; using Altinn.Studio.Designer.Services.Interfaces; using MediatR; namespace Altinn.Studio.Designer.EventHandlers.LayoutSetDeleted; -public class LayoutSetDeletedComponentRefHandler(IAltinnGitRepositoryFactory altinnGitRepositoryFactory, IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler +public class LayoutSetDeletedComponentRefHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler { public async Task Handle(LayoutSetDeletedEvent notification, CancellationToken cancellationToken) { - AltinnAppGitRepository altinnAppGitRepository = altinnGitRepositoryFactory.GetAltinnAppGitRepository( - notification.EditingContext.Org, - notification.EditingContext.Repo, - notification.EditingContext.Developer); - - LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile(cancellationToken); - await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( notification.EditingContext, SyncErrorCodes.LayoutSetSubLayoutSyncError, "layouts", async () => { - Dictionary deletedLayouts = await altinnAppGitRepository.GetFormLayouts(notification.LayoutSetName, cancellationToken); - List referencesToDelete = [new Reference("layoutSet", notification.LayoutSetName, notification.LayoutSetName)]; - - foreach (KeyValuePair deletedLayout in deletedLayouts) - { - referencesToDelete.Add(new Reference("page", notification.LayoutSetName, deletedLayout.Key)); - - if (deletedLayout.Value["data"] is not JsonObject data || data["layout"] is not JsonArray layoutArray) - { - continue; - } - - foreach (JsonNode component in layoutArray) - { - string deletedId = component["id"]?.GetValue(); - referencesToDelete.Add(new Reference("component", notification.LayoutSetName, deletedId)); - } - } - return await appDevelopmentService.DeleteFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); }); } diff --git a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs index b9ee91e42ce..df65bffe6e0 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -602,7 +602,8 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex editingContext.Repo, editingContext.Developer); - bool hasLayoutSetChanges = false; + List newReferencesToDelete = []; + bool hasChanges = false; LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile(cancellationToken); @@ -610,22 +611,26 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex var deletedLayouts = referencesToDelete.Where(item => item.Type == "page").ToList(); var deletedComponents = referencesToDelete.Where(item => item.Type == "component").ToList(); - var filteredLayoutSets = layoutSets.Sets.Where(item => !deletedLayoutsSetIds.Contains(item.Id)).ToList(); - foreach (LayoutSetConfig layoutSet in filteredLayoutSets) + foreach (LayoutSetConfig layoutSet in layoutSets.Sets) { - bool hasLayoutChanges = false; + bool isLayoutSetDeleted = deletedLayoutsSetIds.Contains(layoutSet.Id); Dictionary formLayouts = await altinnAppGitRepository.GetFormLayouts(layoutSet.Id, cancellationToken); - var deletedLayoutIds = deletedLayouts.Where(item => item.Type == "page" && item.LayoutSetName == layoutSet.Id).Select(item => item.Id).ToList(); - var filteredLayouts = formLayouts.Where(item => !deletedLayoutIds.Contains(item.Key)).ToList(); - foreach (KeyValuePair formLayout in filteredLayouts) + var deletedLayoutIds = deletedLayouts.Where(item => item.LayoutSetName == layoutSet.Id).Select(item => item.Id).ToList(); + foreach (KeyValuePair formLayout in formLayouts) { + bool isLayoutDeleted = deletedLayoutIds.Contains(formLayout.Key); + bool hasLayoutChanges = false; + + var filteredLayouts = formLayouts.Where(item => !deletedLayoutIds.Contains(item.Key)).ToList(); + if (formLayout.Value["data"] is not JsonObject data || data["layout"] is not JsonArray layoutArray) { return false; } + var deletedLayoutComponentIds = deletedComponents.Where(item => item.LayoutSetName == layoutSet.Id).Select(item => item.Id).ToList(); for (int i = layoutArray.Count - 1; i >= 0; i--) { JsonNode jsonNode = layoutArray[i]; @@ -633,12 +638,27 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex { continue; } + + string componentId = jsonObject["id"]?.GetValue(); + bool isComponentDeleted = deletedLayoutComponentIds.Contains(componentId); + + if (isLayoutSetDeleted || isLayoutDeleted || isComponentDeleted) + { + if (!isComponentDeleted) + { + newReferencesToDelete.Add(new Reference("component", layoutSet.Id, componentId)); + } + + continue; + } + string componentType = jsonObject["type"]?.GetValue(); switch (componentType) { case "Subform": if (deletedLayoutsSetIds.Contains(jsonObject["layoutSet"]?.GetValue())) { + newReferencesToDelete.Add(new Reference("component", layoutSet.Id, componentId)); layoutArray.RemoveAt(i); hasLayoutChanges = true; } @@ -659,6 +679,7 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex _ => false }) { + newReferencesToDelete.Add(new Reference("component", layoutSet.Id, componentId)); layoutArray.RemoveAt(i); hasLayoutChanges = true; } @@ -687,15 +708,30 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex } } + if (isLayoutSetDeleted || isLayoutDeleted) + { + if (!isLayoutDeleted) + { + newReferencesToDelete.Add(new Reference("page", layoutSet.Id, formLayout.Key)); + } + + continue; + } + if (hasLayoutChanges) { await altinnAppGitRepository.SaveLayout(layoutSet.Id, $"{formLayout.Key}.json", formLayout.Value, cancellationToken); - hasLayoutSetChanges = true; + hasChanges = true; } } } - return hasLayoutSetChanges; + if (newReferencesToDelete.Count > 0) + { + hasChanges |= await DeleteFromLayouts(editingContext, newReferencesToDelete, cancellationToken); + } + + return hasChanges; } } } From 53663afcc813419651c52d9576c400a889b7e499 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Wed, 18 Dec 2024 15:32:31 +0100 Subject: [PATCH 13/25] Fix warnings --- .../Designer/Services/Implementation/AppDevelopmentService.cs | 4 +--- .../AppDevelopmentController/SaveFormLayoutTests.cs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs index df65bffe6e0..2e53c02eeee 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -611,7 +611,7 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex var deletedLayouts = referencesToDelete.Where(item => item.Type == "page").ToList(); var deletedComponents = referencesToDelete.Where(item => item.Type == "component").ToList(); - foreach (LayoutSetConfig layoutSet in layoutSets.Sets) + foreach (LayoutSetConfig layoutSet in layoutSets.Sets ?? [new() { Id = null }]) { bool isLayoutSetDeleted = deletedLayoutsSetIds.Contains(layoutSet.Id); @@ -623,8 +623,6 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex bool isLayoutDeleted = deletedLayoutIds.Contains(formLayout.Key); bool hasLayoutChanges = false; - var filteredLayouts = formLayouts.Where(item => !deletedLayoutIds.Contains(item.Key)).ToList(); - if (formLayout.Value["data"] is not JsonObject data || data["layout"] is not JsonArray layoutArray) { return false; diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs index 79f8012d032..fb54421a7ea 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs @@ -105,7 +105,7 @@ public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummaryCom string layout = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{layoutSetName}/layouts/{layoutName}.json"); JsonNode layoutWithDeletedComponent = JsonNode.Parse(layout); JsonArray layoutArray = layoutWithDeletedComponent["data"]["layout"] as JsonArray; - layoutArray.RemoveAt(0); + layoutArray?.RemoveAt(0); string url = $"{VersionPrefix(org, app)}/form-layout/{layoutName}?layoutSetName={layoutSetName}"; var payload = new JsonObject From 1739b58d2de3ff4ade369e9af2b0ca1c286bf4cf Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Thu, 19 Dec 2024 14:17:33 +0100 Subject: [PATCH 14/25] Clean up code --- ...r.cs => ComponentDeletedLayoutsHandler.cs} | 6 +- ....cs => LayoutPageDeletedLayoutsHandler.cs} | 6 +- ...r.cs => LayoutSetDeletedLayoutsHandler.cs} | 6 +- .../Designer/Hubs/SyncHub/SyncErrorCodes.cs | 6 +- .../Implementation/AppDevelopmentService.cs | 64 ++++++++++--------- .../Interfaces/IAppDevelopmentService.cs | 2 +- 6 files changed, 48 insertions(+), 42 deletions(-) rename backend/src/Designer/EventHandlers/ComponentDeleted/{ComponentDeletedHandler.cs => ComponentDeletedLayoutsHandler.cs} (67%) rename backend/src/Designer/EventHandlers/LayoutPageDeleted/{LayoutPageDeletedHandler.cs => LayoutPageDeletedLayoutsHandler.cs} (66%) rename backend/src/Designer/EventHandlers/LayoutSetDeleted/{LayoutSetDeletedComponentRefHandler.cs => LayoutSetDeletedLayoutsHandler.cs} (67%) diff --git a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedLayoutsHandler.cs similarity index 67% rename from backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs rename to backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedLayoutsHandler.cs index 235925d580b..e380d08c708 100644 --- a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedHandler.cs +++ b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedLayoutsHandler.cs @@ -9,18 +9,18 @@ namespace Altinn.Studio.Designer.EventHandlers.ComponentDeleted; -public class ComponentDeletedHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler +public class ComponentDeletedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler { public async Task Handle(ComponentDeletedEvent notification, CancellationToken cancellationToken) { await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( notification.EditingContext, - SyncErrorCodes.ComponentDeletedSyncError, + SyncErrorCodes.ComponentDeletedLayoutsSyncError, "layouts", async () => { List referencesToDelete = [new Reference("component", notification.LayoutSetName, notification.ComponentId)]; - return await appDevelopmentService.DeleteFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); + return await appDevelopmentService.DeleteReferencesFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); }); } } diff --git a/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs b/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedLayoutsHandler.cs similarity index 66% rename from backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs rename to backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedLayoutsHandler.cs index 01da6286892..5a79f1219d8 100644 --- a/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedHandler.cs +++ b/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedLayoutsHandler.cs @@ -9,18 +9,18 @@ namespace Altinn.Studio.Designer.EventHandlers.LayoutPageDeleted; -public class LayoutPageDeletedHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler +public class LayoutPageDeletedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler { public async Task Handle(LayoutPageDeletedEvent notification, CancellationToken cancellationToken) { await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( notification.EditingContext, - SyncErrorCodes.LayoutPageDeletedSyncError, + SyncErrorCodes.LayoutPageDeletedLayoutsSyncError, "layouts", async () => { List referencesToDelete = [new Reference("page", notification.LayoutSetName, notification.LayoutName)]; - return await appDevelopmentService.DeleteFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); + return await appDevelopmentService.DeleteReferencesFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); }); } } diff --git a/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedComponentRefHandler.cs b/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedLayoutsHandler.cs similarity index 67% rename from backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedComponentRefHandler.cs rename to backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedLayoutsHandler.cs index b31de8808f9..97ce3d164c6 100644 --- a/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedComponentRefHandler.cs +++ b/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedLayoutsHandler.cs @@ -9,18 +9,18 @@ namespace Altinn.Studio.Designer.EventHandlers.LayoutSetDeleted; -public class LayoutSetDeletedComponentRefHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler +public class LayoutSetDeletedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler { public async Task Handle(LayoutSetDeletedEvent notification, CancellationToken cancellationToken) { await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( notification.EditingContext, - SyncErrorCodes.LayoutSetSubLayoutSyncError, + SyncErrorCodes.LayoutSetDeletedLayoutsSyncError, "layouts", async () => { List referencesToDelete = [new Reference("layoutSet", notification.LayoutSetName, notification.LayoutSetName)]; - return await appDevelopmentService.DeleteFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); + return await appDevelopmentService.DeleteReferencesFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); }); } } diff --git a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs index 89cd0439eb4..04178d4eb7e 100644 --- a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs +++ b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs @@ -9,10 +9,10 @@ public static class SyncErrorCodes public const string ApplicationMetadataDataTypeSyncError = nameof(ApplicationMetadataDataTypeSyncError); public const string LayoutSetsDataTypeSyncError = nameof(LayoutSetsDataTypeSyncError); public const string LayoutSetComponentIdSyncError = nameof(LayoutSetComponentIdSyncError); - public const string LayoutSetSubLayoutSyncError = nameof(LayoutSetSubLayoutSyncError); + public const string LayoutSetDeletedLayoutsSyncError = nameof(LayoutSetDeletedLayoutsSyncError); public const string LayoutSetSubFormButtonSyncError = nameof(LayoutSetSubFormButtonSyncError); public const string SettingsComponentIdSyncError = nameof(SettingsComponentIdSyncError); public const string LayoutPageAddSyncError = nameof(LayoutPageAddSyncError); - public const string ComponentDeletedSyncError = nameof(ComponentDeletedSyncError); - public const string LayoutPageDeletedSyncError = nameof(LayoutPageDeletedSyncError); + public const string ComponentDeletedLayoutsSyncError = nameof(ComponentDeletedLayoutsSyncError); + public const string LayoutPageDeletedLayoutsSyncError = nameof(LayoutPageDeletedLayoutsSyncError); } diff --git a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs index 2e53c02eeee..a3091dd001d 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -595,49 +595,55 @@ public async Task AddComponentToLayout( await SaveFormLayout(editingContext, layoutSetName, layoutName, formLayout, cancellationToken); } - public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContext, List referencesToDelete, CancellationToken cancellationToken) + public async Task DeleteReferencesFromLayouts(AltinnRepoEditingContext editingContext, List referencesToDelete, CancellationToken cancellationToken) { AltinnAppGitRepository altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository( editingContext.Org, editingContext.Repo, editingContext.Developer); + LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile(cancellationToken); + + return await DeleteReferencesFromLayouts(altinnAppGitRepository, layoutSets.Sets, referencesToDelete, cancellationToken); + } + + private async Task DeleteReferencesFromLayouts(AltinnAppGitRepository altinnAppGitRepository, List layoutSets, List referencesToDelete, CancellationToken cancellationToken) + { List newReferencesToDelete = []; bool hasChanges = false; - LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile(cancellationToken); - var deletedLayoutsSetIds = referencesToDelete.Where(item => item.Type == "layoutSet").Select(item => item.Id).ToList(); var deletedLayouts = referencesToDelete.Where(item => item.Type == "page").ToList(); var deletedComponents = referencesToDelete.Where(item => item.Type == "component").ToList(); - foreach (LayoutSetConfig layoutSet in layoutSets.Sets ?? [new() { Id = null }]) + foreach (LayoutSetConfig layoutSet in layoutSets ?? [new() { Id = null }]) { bool isLayoutSetDeleted = deletedLayoutsSetIds.Contains(layoutSet.Id); - Dictionary formLayouts = await altinnAppGitRepository.GetFormLayouts(layoutSet.Id, cancellationToken); + Dictionary layouts = await altinnAppGitRepository.GetFormLayouts(layoutSet.Id, cancellationToken); var deletedLayoutIds = deletedLayouts.Where(item => item.LayoutSetName == layoutSet.Id).Select(item => item.Id).ToList(); - foreach (KeyValuePair formLayout in formLayouts) + foreach (KeyValuePair layout in layouts) { - bool isLayoutDeleted = deletedLayoutIds.Contains(formLayout.Key); + bool isLayoutDeleted = deletedLayoutIds.Contains(layout.Key); bool hasLayoutChanges = false; - if (formLayout.Value["data"] is not JsonObject data || data["layout"] is not JsonArray layoutArray) + // TODO : https://github.com/Altinn/altinn-studio/issues/14073 + if (layout.Value["data"] is not JsonObject data || data["layout"] is not JsonArray componentList) { return false; } var deletedLayoutComponentIds = deletedComponents.Where(item => item.LayoutSetName == layoutSet.Id).Select(item => item.Id).ToList(); - for (int i = layoutArray.Count - 1; i >= 0; i--) + for (int i = componentList.Count - 1; i >= 0; i--) { - JsonNode jsonNode = layoutArray[i]; - if (jsonNode is not JsonObject jsonObject) + JsonNode componentNode = componentList[i]; + if (componentNode is not JsonObject component) { continue; } - string componentId = jsonObject["id"]?.GetValue(); + string componentId = component["id"]?.GetValue(); bool isComponentDeleted = deletedLayoutComponentIds.Contains(componentId); if (isLayoutSetDeleted || isLayoutDeleted || isComponentDeleted) @@ -650,24 +656,24 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex continue; } - string componentType = jsonObject["type"]?.GetValue(); + string componentType = component["type"]?.GetValue(); switch (componentType) { case "Subform": - if (deletedLayoutsSetIds.Contains(jsonObject["layoutSet"]?.GetValue())) + if (deletedLayoutsSetIds.Contains(component["layoutSet"]?.GetValue())) { newReferencesToDelete.Add(new Reference("component", layoutSet.Id, componentId)); - layoutArray.RemoveAt(i); + componentList.RemoveAt(i); hasLayoutChanges = true; } break; case "Summary2": - if (jsonObject["target"] is JsonObject targetObject) + if (component["target"] is JsonObject target) { - string type = targetObject["type"]?.GetValue(); - string id = targetObject["id"]?.GetValue(); - string taskId = targetObject["taskId"]?.GetValue(); - string layouSetId = string.IsNullOrEmpty(taskId) ? layoutSet.Id : layoutSets.Sets?.FirstOrDefault(item => item.Tasks?.Contains(taskId) ?? false)?.Id; + string type = target["type"]?.GetValue(); + string id = target["id"]?.GetValue(); + string taskId = target["taskId"]?.GetValue(); + string layouSetId = string.IsNullOrEmpty(taskId) ? layoutSet.Id : layoutSets?.FirstOrDefault(item => item.Tasks?.Contains(taskId) ?? false)?.Id; if (type switch { @@ -678,15 +684,15 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex }) { newReferencesToDelete.Add(new Reference("component", layoutSet.Id, componentId)); - layoutArray.RemoveAt(i); + componentList.RemoveAt(i); hasLayoutChanges = true; } - if (jsonNode["overrides"] is JsonArray overridesArray) + if (component["overrides"] is JsonArray overrideList) { - overridesArray.RemoveAll(overrideObject => + overrideList.RemoveAll(overrideItem => { - string componentId = overrideObject["componentId"]?.GetValue(); + string componentId = overrideItem["componentId"]?.GetValue(); if (deletedComponents.Exists(item => item.LayoutSetName == layouSetId && item.Id == componentId)) { hasLayoutChanges = true; @@ -696,9 +702,9 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex return false; }); - if (overridesArray.Count == 0) + if (overrideList.Count == 0) { - jsonObject.Remove("overrides"); + component.Remove("overrides"); } } } @@ -710,7 +716,7 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex { if (!isLayoutDeleted) { - newReferencesToDelete.Add(new Reference("page", layoutSet.Id, formLayout.Key)); + newReferencesToDelete.Add(new Reference("page", layoutSet.Id, layout.Key)); } continue; @@ -718,7 +724,7 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex if (hasLayoutChanges) { - await altinnAppGitRepository.SaveLayout(layoutSet.Id, $"{formLayout.Key}.json", formLayout.Value, cancellationToken); + await altinnAppGitRepository.SaveLayout(layoutSet.Id, $"{layout.Key}.json", layout.Value, cancellationToken); hasChanges = true; } } @@ -726,7 +732,7 @@ public async Task DeleteFromLayouts(AltinnRepoEditingContext editingContex if (newReferencesToDelete.Count > 0) { - hasChanges |= await DeleteFromLayouts(editingContext, newReferencesToDelete, cancellationToken); + hasChanges |= await DeleteReferencesFromLayouts(altinnAppGitRepository, layoutSets, newReferencesToDelete, cancellationToken); } return hasChanges; diff --git a/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs b/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs index 697f9d6ebf3..b6161898b5d 100644 --- a/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs +++ b/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs @@ -220,6 +220,6 @@ public Task GetModelMetadata( /// An . /// The references to delete. /// An that observes if operation is cancelled. - public Task DeleteFromLayouts(AltinnRepoEditingContext altinnRepoEditingContext, List referencesToDelete, CancellationToken cancellationToken); + public Task DeleteReferencesFromLayouts(AltinnRepoEditingContext altinnRepoEditingContext, List referencesToDelete, CancellationToken cancellationToken); } } From f837897f669590d8b07066f8b3600825dcbf624b Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Fri, 20 Dec 2024 16:41:55 +0100 Subject: [PATCH 15/25] Update Summary2 and Subform when updating component id --- .../Controllers/AppDevelopmentController.cs | 16 +- .../ComponentDeletedLayoutsHandler.cs | 2 +- .../ComponentIdChangedLayoutsHandler.cs | 11 +- .../LayoutPageDeletedLayoutsHandler.cs | 2 +- .../LayoutPageIdChangedLayoutsHandler.cs | 26 +++ .../LayoutSetDeletedLayoutsHandler.cs | 2 +- .../LayoutSetIdChangedLayoutsHandler.cs | 26 +++ .../Events/LayoutPageIdChangedEvent.cs | 12 + .../Events/LayoutSetIdChangedEvent.cs | 11 + .../Designer/Hubs/SyncHub/SyncErrorCodes.cs | 2 + backend/src/Designer/Models/Reference.cs | 14 +- .../Implementation/AppDevelopmentService.cs | 217 ++++++++++++------ .../Interfaces/IAppDevelopmentService.cs | 4 +- 13 files changed, 259 insertions(+), 86 deletions(-) create mode 100644 backend/src/Designer/EventHandlers/LayoutPageIdChanged/LayoutPageIdChangedLayoutsHandler.cs create mode 100644 backend/src/Designer/EventHandlers/LayoutSetIdChanged/LayoutSetIdChangedLayoutsHandler.cs create mode 100644 backend/src/Designer/Events/LayoutPageIdChangedEvent.cs create mode 100644 backend/src/Designer/Events/LayoutSetIdChangedEvent.cs diff --git a/backend/src/Designer/Controllers/AppDevelopmentController.cs b/backend/src/Designer/Controllers/AppDevelopmentController.cs index 4ef29e4b3be..4b7d29b0d9f 100644 --- a/backend/src/Designer/Controllers/AppDevelopmentController.cs +++ b/backend/src/Designer/Controllers/AppDevelopmentController.cs @@ -207,16 +207,24 @@ await _mediator.Publish(new LayoutPageDeletedEvent /// Application identifier which is unique within an organisation. /// Name of the layout set the specific layout belongs to /// The current name of the form layout + /// An that observes if operation is cancelled. /// A success message if the save was successful [HttpPost] [Route("form-layout-name/{layoutName}")] - public ActionResult UpdateFormLayoutName(string org, string app, [FromQuery] string layoutSetName, [FromRoute] string layoutName, [FromBody] string newName) + public async Task UpdateFormLayoutName(string org, string app, [FromQuery] string layoutSetName, [FromRoute] string layoutName, [FromBody] string newName, CancellationToken cancellationToken) { try { string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext); var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer); _appDevelopmentService.UpdateFormLayoutName(editingContext, layoutSetName, layoutName, newName); + await _mediator.Publish(new LayoutPageIdChangedEvent + { + EditingContext = editingContext, + LayoutSetName = layoutSetName, + LayoutName = layoutName, + NewLayoutName = newName, + }, cancellationToken); return Ok(); } catch (FileNotFoundException exception) @@ -407,6 +415,12 @@ public async Task UpdateLayoutSetName(string org, string app, [Fro string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext); var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer); LayoutSets layoutSets = await _appDevelopmentService.UpdateLayoutSetName(editingContext, layoutSetIdToUpdate, newLayoutSetName, cancellationToken); + await _mediator.Publish(new LayoutSetIdChangedEvent + { + EditingContext = editingContext, + LayoutSetName = layoutSetIdToUpdate, + NewLayoutSetName = newLayoutSetName, + }, cancellationToken); return Ok(layoutSets); } diff --git a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedLayoutsHandler.cs index e380d08c708..93865d5c5b6 100644 --- a/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedLayoutsHandler.cs +++ b/backend/src/Designer/EventHandlers/ComponentDeleted/ComponentDeletedLayoutsHandler.cs @@ -20,7 +20,7 @@ await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotifica async () => { List referencesToDelete = [new Reference("component", notification.LayoutSetName, notification.ComponentId)]; - return await appDevelopmentService.DeleteReferencesFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); + return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToDelete, cancellationToken); }); } } diff --git a/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs index df9923093fa..d297547c9a9 100644 --- a/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs +++ b/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs @@ -1,9 +1,11 @@ +using System.Collections.Generic; using System.Linq; using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; using Altinn.Studio.Designer.Events; using Altinn.Studio.Designer.Hubs.SyncHub; +using Altinn.Studio.Designer.Models; using Altinn.Studio.Designer.Services.Interfaces; using MediatR; @@ -13,12 +15,15 @@ public class ComponentIdChangedLayoutsHandler : INotificationHandler referencesToUpdate = [new Reference("component", notification.LayoutSetName, notification.OldComponentId, notification.NewComponentId)]; + hasChanges = await _appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); + return hasChanges; }); } diff --git a/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedLayoutsHandler.cs index 5a79f1219d8..0bd0765027b 100644 --- a/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedLayoutsHandler.cs +++ b/backend/src/Designer/EventHandlers/LayoutPageDeleted/LayoutPageDeletedLayoutsHandler.cs @@ -20,7 +20,7 @@ await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotifica async () => { List referencesToDelete = [new Reference("page", notification.LayoutSetName, notification.LayoutName)]; - return await appDevelopmentService.DeleteReferencesFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); + return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToDelete, cancellationToken); }); } } diff --git a/backend/src/Designer/EventHandlers/LayoutPageIdChanged/LayoutPageIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/LayoutPageIdChanged/LayoutPageIdChangedLayoutsHandler.cs new file mode 100644 index 00000000000..7772a125cf1 --- /dev/null +++ b/backend/src/Designer/EventHandlers/LayoutPageIdChanged/LayoutPageIdChangedLayoutsHandler.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Altinn.Studio.Designer.Events; +using Altinn.Studio.Designer.Hubs.SyncHub; +using Altinn.Studio.Designer.Models; +using Altinn.Studio.Designer.Services.Interfaces; +using MediatR; + +namespace Altinn.Studio.Designer.EventHandlers.LayoutPageDeleted; + +public class LayoutPageIdChangedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler +{ + public async Task Handle(LayoutPageIdChangedEvent notification, CancellationToken cancellationToken) + { + await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( + notification.EditingContext, + SyncErrorCodes.LayoutPageIdChangedLayoutsSyncError, + "layouts", + async () => + { + List referencesToUpdate = [new Reference("page", notification.LayoutSetName, notification.LayoutName, notification.NewLayoutName)]; + return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); + }); + } +} diff --git a/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedLayoutsHandler.cs index 97ce3d164c6..8d97d60f53c 100644 --- a/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedLayoutsHandler.cs +++ b/backend/src/Designer/EventHandlers/LayoutSetDeleted/LayoutSetDeletedLayoutsHandler.cs @@ -20,7 +20,7 @@ await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotifica async () => { List referencesToDelete = [new Reference("layoutSet", notification.LayoutSetName, notification.LayoutSetName)]; - return await appDevelopmentService.DeleteReferencesFromLayouts(notification.EditingContext, referencesToDelete, cancellationToken); + return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToDelete, cancellationToken); }); } } diff --git a/backend/src/Designer/EventHandlers/LayoutSetIdChanged/LayoutSetIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/LayoutSetIdChanged/LayoutSetIdChangedLayoutsHandler.cs new file mode 100644 index 00000000000..6502bd03b6e --- /dev/null +++ b/backend/src/Designer/EventHandlers/LayoutSetIdChanged/LayoutSetIdChangedLayoutsHandler.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Altinn.Studio.Designer.Events; +using Altinn.Studio.Designer.Hubs.SyncHub; +using Altinn.Studio.Designer.Models; +using Altinn.Studio.Designer.Services.Interfaces; +using MediatR; + +namespace Altinn.Studio.Designer.EventHandlers.LayoutSetDeleted; + +public class LayoutSetIdChangedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler +{ + public async Task Handle(LayoutSetIdChangedEvent notification, CancellationToken cancellationToken) + { + await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( + notification.EditingContext, + SyncErrorCodes.LayoutSetIdChangedLayoutsSyncError, + "layouts", + async () => + { + List referencesToUpdate = [new Reference("layoutSet", notification.LayoutSetName, notification.LayoutSetName, notification.NewLayoutSetName)]; + return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); + }); + } +} diff --git a/backend/src/Designer/Events/LayoutPageIdChangedEvent.cs b/backend/src/Designer/Events/LayoutPageIdChangedEvent.cs new file mode 100644 index 00000000000..4059f3ab287 --- /dev/null +++ b/backend/src/Designer/Events/LayoutPageIdChangedEvent.cs @@ -0,0 +1,12 @@ +using Altinn.Studio.Designer.Models; +using MediatR; + +namespace Altinn.Studio.Designer.Events; + +public class LayoutPageIdChangedEvent : INotification +{ + public AltinnRepoEditingContext EditingContext { get; set; } + public string LayoutSetName { get; set; } + public string LayoutName { get; set; } + public string NewLayoutName { get; set; } +} diff --git a/backend/src/Designer/Events/LayoutSetIdChangedEvent.cs b/backend/src/Designer/Events/LayoutSetIdChangedEvent.cs new file mode 100644 index 00000000000..1f327277588 --- /dev/null +++ b/backend/src/Designer/Events/LayoutSetIdChangedEvent.cs @@ -0,0 +1,11 @@ +using Altinn.Studio.Designer.Models; +using MediatR; + +namespace Altinn.Studio.Designer.Events; + +public class LayoutSetIdChangedEvent : INotification +{ + public AltinnRepoEditingContext EditingContext { get; set; } + public string LayoutSetName { get; set; } + public string NewLayoutSetName { get; set; } +} diff --git a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs index 04178d4eb7e..d4811e1a898 100644 --- a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs +++ b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs @@ -10,9 +10,11 @@ public static class SyncErrorCodes public const string LayoutSetsDataTypeSyncError = nameof(LayoutSetsDataTypeSyncError); public const string LayoutSetComponentIdSyncError = nameof(LayoutSetComponentIdSyncError); public const string LayoutSetDeletedLayoutsSyncError = nameof(LayoutSetDeletedLayoutsSyncError); + public const string LayoutSetIdChangedLayoutsSyncError = nameof(LayoutSetIdChangedLayoutsSyncError); public const string LayoutSetSubFormButtonSyncError = nameof(LayoutSetSubFormButtonSyncError); public const string SettingsComponentIdSyncError = nameof(SettingsComponentIdSyncError); public const string LayoutPageAddSyncError = nameof(LayoutPageAddSyncError); public const string ComponentDeletedLayoutsSyncError = nameof(ComponentDeletedLayoutsSyncError); public const string LayoutPageDeletedLayoutsSyncError = nameof(LayoutPageDeletedLayoutsSyncError); + public const string LayoutPageIdChangedLayoutsSyncError = nameof(LayoutPageIdChangedLayoutsSyncError); } diff --git a/backend/src/Designer/Models/Reference.cs b/backend/src/Designer/Models/Reference.cs index 1cde4847945..ba16ffddb91 100644 --- a/backend/src/Designer/Models/Reference.cs +++ b/backend/src/Designer/Models/Reference.cs @@ -1,15 +1,3 @@ namespace Altinn.Studio.Designer.Models; -public class Reference -{ - public string Type { get; } - public string LayoutSetName { get; } - public string Id { get; } - - public Reference(string type, string layoutSetName, string id) - { - Type = type; - LayoutSetName = layoutSetName; - Id = id; - } -} +public record Reference(string Type, string LayoutSetName, string Id, string NewId = null); diff --git a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs index a3091dd001d..7abc59b6a37 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -2,11 +2,11 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text.Json; using System.Text.Json.Nodes; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using Altinn.App.Core.Helpers; using Altinn.App.Core.Internal.Process.Elements; using Altinn.App.Core.Models; using Altinn.Studio.DataModeling.Metamodel; @@ -595,7 +595,7 @@ public async Task AddComponentToLayout( await SaveFormLayout(editingContext, layoutSetName, layoutName, formLayout, cancellationToken); } - public async Task DeleteReferencesFromLayouts(AltinnRepoEditingContext editingContext, List referencesToDelete, CancellationToken cancellationToken) + public async Task UpdateLayoutReferences(AltinnRepoEditingContext editingContext, List referencesToUpdate, CancellationToken cancellationToken) { AltinnAppGitRepository altinnAppGitRepository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository( editingContext.Org, @@ -604,17 +604,24 @@ public async Task DeleteReferencesFromLayouts(AltinnRepoEditingContext edi LayoutSets layoutSets = await altinnAppGitRepository.GetLayoutSetsFile(cancellationToken); - return await DeleteReferencesFromLayouts(altinnAppGitRepository, layoutSets.Sets, referencesToDelete, cancellationToken); + return await UpdateLayoutReferences(altinnAppGitRepository, layoutSets.Sets, referencesToUpdate, cancellationToken); } - private async Task DeleteReferencesFromLayouts(AltinnAppGitRepository altinnAppGitRepository, List layoutSets, List referencesToDelete, CancellationToken cancellationToken) + private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnAppGitRepository, List layoutSets, List referencesToUpdate, CancellationToken cancellationToken) { - List newReferencesToDelete = []; + List referencesToDelete = []; bool hasChanges = false; - var deletedLayoutsSetIds = referencesToDelete.Where(item => item.Type == "layoutSet").Select(item => item.Id).ToList(); - var deletedLayouts = referencesToDelete.Where(item => item.Type == "page").ToList(); - var deletedComponents = referencesToDelete.Where(item => item.Type == "component").ToList(); + var deletedReferences = referencesToUpdate.Where(item => string.IsNullOrEmpty(item.NewId)).ToList(); + var updatedReferences = referencesToUpdate.Where(item => !string.IsNullOrEmpty(item.NewId)).ToList(); + + var deletedLayoutsSetIds = deletedReferences.Where(item => item.Type == "layoutSet").Select(item => item.Id).ToList(); + var deletedLayouts = deletedReferences.Where(item => item.Type == "page").ToList(); + var deletedComponents = deletedReferences.Where(item => item.Type == "component").ToList(); + + var updatedLayoutsSets = updatedReferences.Where(item => item.Type == "layoutSet").ToList(); + var updatedLayouts = updatedReferences.Where(item => item.Type == "page").ToList(); + var updatedComponents = updatedReferences.Where(item => item.Type == "component").ToList(); foreach (LayoutSetConfig layoutSet in layoutSets ?? [new() { Id = null }]) { @@ -622,93 +629,171 @@ private async Task DeleteReferencesFromLayouts(AltinnAppGitRepository alti Dictionary layouts = await altinnAppGitRepository.GetFormLayouts(layoutSet.Id, cancellationToken); - var deletedLayoutIds = deletedLayouts.Where(item => item.LayoutSetName == layoutSet.Id).Select(item => item.Id).ToList(); + var deletedLayoutIdsFromCurrentLayoutSet = deletedLayouts.Where(item => item.LayoutSetName == layoutSet.Id && string.IsNullOrEmpty(item.NewId)).Select(item => item.Id).ToList(); foreach (KeyValuePair layout in layouts) { - bool isLayoutDeleted = deletedLayoutIds.Contains(layout.Key); + bool isLayoutDeleted = deletedLayoutIdsFromCurrentLayoutSet.Contains(layout.Key); bool hasLayoutChanges = false; // TODO : https://github.com/Altinn/altinn-studio/issues/14073 - if (layout.Value["data"] is not JsonObject data || data["layout"] is not JsonArray componentList) + if (layout.Value["data"] is not JsonObject data) { - return false; + continue; } - var deletedLayoutComponentIds = deletedComponents.Where(item => item.LayoutSetName == layoutSet.Id).Select(item => item.Id).ToList(); - for (int i = componentList.Count - 1; i >= 0; i--) - { - JsonNode componentNode = componentList[i]; - if (componentNode is not JsonObject component) - { - continue; - } - - string componentId = component["id"]?.GetValue(); - bool isComponentDeleted = deletedLayoutComponentIds.Contains(componentId); + var deletedComponentIdsFromCurrentLayoutSet = deletedComponents.Where(item => item.LayoutSetName == layoutSet.Id && string.IsNullOrEmpty(item.NewId)).Select(item => item.Id).ToList(); + var updatedComponentsFromCurrentLayoutSet = updatedComponents.Where(item => item.LayoutSetName == layoutSet.Id && !string.IsNullOrEmpty(item.NewId)).ToList(); - if (isLayoutSetDeleted || isLayoutDeleted || isComponentDeleted) + if (data["layout"] is JsonArray componentList) + { + for (int i = componentList.Count - 1; i >= 0; i--) { - if (!isComponentDeleted) + JsonNode componentNode = componentList[i]; + if (componentNode is not JsonObject component) { - newReferencesToDelete.Add(new Reference("component", layoutSet.Id, componentId)); + continue; } - continue; - } + string componentId = component["id"]?.GetValue(); + bool isComponentDeleted = deletedComponentIdsFromCurrentLayoutSet.Contains(componentId); - string componentType = component["type"]?.GetValue(); - switch (componentType) - { - case "Subform": - if (deletedLayoutsSetIds.Contains(component["layoutSet"]?.GetValue())) + if (isComponentDeleted) + { + componentList.RemoveAt(i); + hasLayoutChanges = true; + } + else + { + Reference updatedReference = updatedComponentsFromCurrentLayoutSet.FirstOrDefault(item => item.Id == componentId); + if (updatedReference != null) { - newReferencesToDelete.Add(new Reference("component", layoutSet.Id, componentId)); - componentList.RemoveAt(i); + component["id"] = updatedReference.NewId; hasLayoutChanges = true; } - break; - case "Summary2": - if (component["target"] is JsonObject target) + } + + if (isLayoutSetDeleted || isLayoutDeleted || isComponentDeleted) + { + if (!isComponentDeleted) { - string type = target["type"]?.GetValue(); - string id = target["id"]?.GetValue(); - string taskId = target["taskId"]?.GetValue(); - string layouSetId = string.IsNullOrEmpty(taskId) ? layoutSet.Id : layoutSets?.FirstOrDefault(item => item.Tasks?.Contains(taskId) ?? false)?.Id; + referencesToDelete.Add(new Reference("component", layoutSet.Id, componentId)); + } - if (type switch - { - "layoutSet" => deletedLayoutsSetIds.Contains(layouSetId), - "page" => deletedLayouts.Exists(item => item.LayoutSetName == layouSetId && item.Id == id), - "component" => deletedComponents.Exists(item => item.LayoutSetName == layouSetId && item.Id == id), - _ => false - }) + continue; + } + + string componentType = component["type"]?.GetValue(); + switch (componentType) + { + case "Subform": + string subformLayoutSet = component["layoutSet"]?.GetValue(); + if (deletedLayoutsSetIds.Contains(subformLayoutSet)) { - newReferencesToDelete.Add(new Reference("component", layoutSet.Id, componentId)); + referencesToDelete.Add(new Reference("component", layoutSet.Id, componentId)); componentList.RemoveAt(i); hasLayoutChanges = true; } - - if (component["overrides"] is JsonArray overrideList) + else { - overrideList.RemoveAll(overrideItem => + Reference updatedReference = updatedLayoutsSets.FirstOrDefault(item => item.Id == subformLayoutSet); + if (updatedReference != null) { - string componentId = overrideItem["componentId"]?.GetValue(); - if (deletedComponents.Exists(item => item.LayoutSetName == layouSetId && item.Id == componentId)) + component["layoutSet"] = updatedReference.NewId; + hasLayoutChanges = true; + } + } + break; + case "Summary": + string componentRef = component["componentRef"]?.GetValue(); + if (deletedComponentIdsFromCurrentLayoutSet.Contains(componentRef)) + { + component["componentRef"] = ""; + hasLayoutChanges = true; + } + else + { + Reference updatedReference = updatedComponentsFromCurrentLayoutSet.FirstOrDefault(item => item.Id == componentRef); + if (updatedReference != null) + { + component["componentRef"] = updatedReference.NewId; + hasLayoutChanges = true; + } + } + break; + case "Summary2": + if (component["target"] is JsonObject target) + { + string type = target["type"]?.GetValue(); + string id = target["id"]?.GetValue(); + string taskId = target["taskId"]?.GetValue(); + string layoutSetId = string.IsNullOrEmpty(taskId) ? layoutSet.Id : layoutSets?.FirstOrDefault(item => item.Tasks?.Contains(taskId) ?? false)?.Id; + + if (type switch + { + "layoutSet" => deletedLayoutsSetIds.Contains(layoutSetId), + "page" => deletedLayouts.Exists(item => item.LayoutSetName == layoutSetId && item.Id == id), + "component" => deletedComponents.Exists(item => item.LayoutSetName == layoutSetId && item.Id == id), + _ => false + }) + { + referencesToDelete.Add(new Reference("component", layoutSet.Id, componentId)); + componentList.RemoveAt(i); + hasLayoutChanges = true; + } + else + { + Reference updatedReference = null; + + switch (type) { - hasLayoutChanges = true; - return true; + case "layoutSet": + updatedReference = updatedLayoutsSets.FirstOrDefault(item => item.Type == type && item.Id == layoutSetId); + break; + case "page": + updatedReference = updatedLayouts.FirstOrDefault(item => item.Type == type && item.LayoutSetName == layoutSetId && item.Id == id); + break; + case "component": + updatedReference = updatedComponents.FirstOrDefault(item => item.Type == type && item.LayoutSetName == layoutSetId && item.Id == id); + break; } - return false; - }); + if (updatedReference != null) + { + target["taskId"] = updatedReference.NewId; + hasLayoutChanges = true; + } + } - if (overrideList.Count == 0) + if (component["overrides"] is JsonArray overrideList) { - component.Remove("overrides"); + for (int j = overrideList.Count - 1; j >= 0; j--) + { + JsonNode overrideItem = overrideList[j]; + string overrideComponentId = overrideItem["componentId"]?.GetValue(); + if (deletedComponents.Exists(item => item.LayoutSetName == layoutSetId && item.Id == overrideComponentId)) + { + overrideList.RemoveAt(i); + hasLayoutChanges = true; + } + else + { + Reference updatedReference = updatedComponents.FirstOrDefault(item => item.LayoutSetName == layoutSetId && item.Id == overrideComponentId); + if (updatedReference != null) + { + overrideItem["componentId"] = updatedReference.NewId; + hasLayoutChanges = true; + } + } + + if (overrideList.Count == 0) + { + component.Remove("overrides"); + } + } } } - } - break; + break; + } } } @@ -716,7 +801,7 @@ private async Task DeleteReferencesFromLayouts(AltinnAppGitRepository alti { if (!isLayoutDeleted) { - newReferencesToDelete.Add(new Reference("page", layoutSet.Id, layout.Key)); + referencesToDelete.Add(new Reference("page", layoutSet.Id, layout.Key)); } continue; @@ -730,9 +815,9 @@ private async Task DeleteReferencesFromLayouts(AltinnAppGitRepository alti } } - if (newReferencesToDelete.Count > 0) + if (referencesToDelete.Count > 0) { - hasChanges |= await DeleteReferencesFromLayouts(altinnAppGitRepository, layoutSets, newReferencesToDelete, cancellationToken); + hasChanges |= await UpdateLayoutReferences(altinnAppGitRepository, layoutSets, referencesToDelete, cancellationToken); } return hasChanges; diff --git a/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs b/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs index b6161898b5d..de0541624ae 100644 --- a/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs +++ b/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs @@ -215,11 +215,11 @@ public Task GetModelMetadata( public Task AddComponentToLayout(AltinnRepoEditingContext altinnRepoEditingContext, string layoutSetName, string layoutName, object component, CancellationToken cancellationToken = default); /// - /// Delete references from layouts + /// Update layout references /// /// An . /// The references to delete. /// An that observes if operation is cancelled. - public Task DeleteReferencesFromLayouts(AltinnRepoEditingContext altinnRepoEditingContext, List referencesToDelete, CancellationToken cancellationToken); + public Task UpdateLayoutReferences(AltinnRepoEditingContext altinnRepoEditingContext, List referencesToDelete, CancellationToken cancellationToken); } } From 55c8500ba8cf30a27e1e13e844f4363ba52db8d8 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Mon, 6 Jan 2025 14:50:38 +0100 Subject: [PATCH 16/25] Cleanup code --- .../Implementation/AppDevelopmentService.cs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs index 7abc59b6a37..108170b0ca6 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Text.Json; using System.Text.Json.Nodes; using System.Text.RegularExpressions; using System.Threading; @@ -703,23 +702,6 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp } } break; - case "Summary": - string componentRef = component["componentRef"]?.GetValue(); - if (deletedComponentIdsFromCurrentLayoutSet.Contains(componentRef)) - { - component["componentRef"] = ""; - hasLayoutChanges = true; - } - else - { - Reference updatedReference = updatedComponentsFromCurrentLayoutSet.FirstOrDefault(item => item.Id == componentRef); - if (updatedReference != null) - { - component["componentRef"] = updatedReference.NewId; - hasLayoutChanges = true; - } - } - break; case "Summary2": if (component["target"] is JsonObject target) { From c5a64873df83caec0ce38ec51cc2bf1da2df09a1 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Mon, 6 Jan 2025 16:39:33 +0100 Subject: [PATCH 17/25] Fix code --- .../Services/Implementation/AppDevelopmentService.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs index 108170b0ca6..f14ad77ba66 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -714,8 +714,7 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp { "layoutSet" => deletedLayoutsSetIds.Contains(layoutSetId), "page" => deletedLayouts.Exists(item => item.LayoutSetName == layoutSetId && item.Id == id), - "component" => deletedComponents.Exists(item => item.LayoutSetName == layoutSetId && item.Id == id), - _ => false + "component" => deletedComponents.Exists(item => item.LayoutSetName == layoutSetId && item.Id == id) }) { referencesToDelete.Add(new Reference("component", layoutSet.Id, componentId)); @@ -754,7 +753,7 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp string overrideComponentId = overrideItem["componentId"]?.GetValue(); if (deletedComponents.Exists(item => item.LayoutSetName == layoutSetId && item.Id == overrideComponentId)) { - overrideList.RemoveAt(i); + overrideList.RemoveAt(j); hasLayoutChanges = true; } else From 73e2f93ddd8070e583cfc876720de172317ba2a6 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Mon, 6 Jan 2025 18:11:17 +0100 Subject: [PATCH 18/25] Cleanup --- .../ComponentIdChangedLayoutsHandler.cs | 2 +- .../Implementation/AppDevelopmentService.cs | 21 +++++++++++++------ .../DeleteFormLayoutTests.cs | 6 +++--- .../DeleteLayoutSetTests.cs | 6 +++--- .../SaveFormLayoutTests.cs | 6 +++--- .../App/ui/component/Settings.json | 0 .../App/ui/component/layouts/Side1.json | 0 .../App/ui/component/layouts/Side2.json | 0 .../App/ui/component2/Settings.json | 0 .../App/ui/component2/layouts/Side1.json | 0 .../App/ui/component2/layouts/Side2.json | 0 .../App/ui/layout-sets.json | 0 .../App/ui/layout/Settings.json | 0 .../App/ui/layout/layouts/Side1.json | 0 .../App/ui/layout2/Settings.json | 0 .../App/ui/layout2/layouts/Side1.json | 0 .../App/ui/layout2/layouts/Side2.json | 0 .../App/ui/layoutSet2/Settings.json | 0 .../App/ui/layoutSet2/layouts/Side1.json | 0 .../App/ui/layoutSet2/layouts/Side2.json | 0 .../App/ui/component/Settings.json | 0 .../App/ui/component/layouts/Side1.json | 0 .../App/ui/component/layouts/Side2.json | 0 .../App/ui/component2/Settings.json | 0 .../App/ui/component2/layouts/Side1.json | 0 .../App/ui/component2/layouts/Side2.json | 0 .../App/ui/layout-sets.json | 0 .../App/ui/layout/Settings.json | 0 .../App/ui/layout/layouts/Side1.json | 0 .../App/ui/layout/layouts/Side2.json | 0 .../App/ui/layout2/Settings.json | 0 .../App/ui/layout2/layouts/Side1.json | 0 .../App/ui/layout2/layouts/Side2.json | 0 .../App/ui/layoutSet/Settings.json | 0 .../App/ui/layoutSet/layouts/Side1.json | 0 .../App/ui/layoutSet/layouts/Side2.json | 0 .../App/ui/layoutSet2/Settings.json | 0 .../App/ui/layoutSet2/layouts/Side1.json | 0 .../App/ui/layoutSet2/layouts/Side2.json | 0 39 files changed, 25 insertions(+), 16 deletions(-) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/component/Settings.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/component/layouts/Side1.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/component/layouts/Side2.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/component2/Settings.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/component2/layouts/Side1.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/component2/layouts/Side2.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/layout-sets.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/layout/Settings.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/layout/layouts/Side1.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/layout2/Settings.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/layout2/layouts/Side1.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/layout2/layouts/Side2.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/layoutSet2/Settings.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/layoutSet2/layouts/Side1.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-after-delete => app-with-summary2-components-after-deleting-references}/App/ui/layoutSet2/layouts/Side2.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/component/Settings.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/component/layouts/Side1.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/component/layouts/Side2.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/component2/Settings.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/component2/layouts/Side1.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/component2/layouts/Side2.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/layout-sets.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/layout/Settings.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/layout/layouts/Side1.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/layout/layouts/Side2.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/layout2/Settings.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/layout2/layouts/Side1.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/layout2/layouts/Side2.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/layoutSet/Settings.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/layoutSet/layouts/Side1.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/layoutSet/layouts/Side2.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/layoutSet2/Settings.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/layoutSet2/layouts/Side1.json (100%) rename backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/{deleted-component-before-delete => app-with-summary2-components}/App/ui/layoutSet2/layouts/Side2.json (100%) diff --git a/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs index d297547c9a9..2de41203bef 100644 --- a/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs +++ b/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs @@ -52,7 +52,7 @@ await _fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotific } List referencesToUpdate = [new Reference("component", notification.LayoutSetName, notification.OldComponentId, notification.NewComponentId)]; - hasChanges = await _appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); + hasChanges |= await _appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); return hasChanges; }); diff --git a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs index f14ad77ba66..6b764a4f912 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -729,20 +729,29 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp { case "layoutSet": updatedReference = updatedLayoutsSets.FirstOrDefault(item => item.Type == type && item.Id == layoutSetId); + if (updatedReference != null) + { + target["taskId"] = updatedReference.NewId; + hasLayoutChanges = true; + } break; case "page": updatedReference = updatedLayouts.FirstOrDefault(item => item.Type == type && item.LayoutSetName == layoutSetId && item.Id == id); + if (updatedReference != null) + { + target["id"] = updatedReference.NewId; + hasLayoutChanges = true; + } break; case "component": updatedReference = updatedComponents.FirstOrDefault(item => item.Type == type && item.LayoutSetName == layoutSetId && item.Id == id); + if (updatedReference != null) + { + target["id"] = updatedReference.NewId; + hasLayoutChanges = true; + } break; } - - if (updatedReference != null) - { - target["taskId"] = updatedReference.NewId; - hasLayoutChanges = true; - } } if (component["overrides"] is JsonArray overrideList) diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteFormLayoutTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteFormLayoutTests.cs index f371c0a1f62..691575e6269 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteFormLayoutTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteFormLayoutTests.cs @@ -60,9 +60,9 @@ public async Task DeleteFormLayout_NonExistingFile_Should_AndReturnNotFound(stri [Theory] [InlineData("ttd", "testUser", "layout", "Side2")] - public async Task DeleteFormLayout_DeletesAssociatedSummaryComponents_ReturnsOk(string org, string developer, string layoutSetName, string layoutName) + public async Task DeleteFormLayout_DeletesAssociatedSummary2Components_ReturnsOk(string org, string developer, string layoutSetName, string layoutName) { - string actualApp = "deleted-component-before-delete"; + string actualApp = "app-with-summary2-components"; string app = TestDataHelper.GenerateTestRepoName(); await CopyRepositoryForTest(org, actualApp, developer, app); @@ -72,7 +72,7 @@ public async Task DeleteFormLayout_DeletesAssociatedSummaryComponents_ReturnsOk( using var response = await HttpClient.SendAsync(httpRequestMessage); response.StatusCode.Should().Be(HttpStatusCode.OK); - string expectedApp = "deleted-component-after-delete"; + string expectedApp = "app-with-summary2-components-after-deleting-references"; string[] layoutPaths = [ "layout/layouts/Side1.json", diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteLayoutSetTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteLayoutSetTests.cs index 48d09965cec..4178a0b31fc 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteLayoutSetTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/DeleteLayoutSetTests.cs @@ -162,9 +162,9 @@ public async Task DeleteLayoutSet_RemovesComponentsReferencingLayoutSet(string o [Theory] [InlineData("ttd", "testUser", "layoutSet")] - public async Task DeleteLayoutSet_DeletesAssociatedSummaryComponents_ReturnsOk(string org, string developer, string layoutSetName) + public async Task DeleteLayoutSet_DeletesAssociatedSummary2Components_ReturnsOk(string org, string developer, string layoutSetName) { - string actualApp = "deleted-component-before-delete"; + string actualApp = "app-with-summary2-components"; string app = TestDataHelper.GenerateTestRepoName(); await CopyRepositoryForTest(org, actualApp, developer, app); @@ -174,7 +174,7 @@ public async Task DeleteLayoutSet_DeletesAssociatedSummaryComponents_ReturnsOk(s using var response = await HttpClient.SendAsync(httpRequestMessage); response.StatusCode.Should().Be(HttpStatusCode.OK, await response.Content.ReadAsStringAsync()); - string expectedApp = "deleted-component-after-delete"; + string expectedApp = "app-with-summary2-components-after-deleting-references"; string[] layoutPaths = [ "layoutSet/layouts/Side1.json", diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs index fb54421a7ea..24dbd314057 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs @@ -96,9 +96,9 @@ public async Task SaveFormLayoutWithComponentIdsChange_ReturnsOk(string org, str [Theory] [InlineData("ttd", "testUser", "component", "Side2", "Input-Om7N3y")] - public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummaryComponents_ReturnsOk(string org, string developer, string layoutSetName, string layoutName, string componentId) + public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummary2Components_ReturnsOk(string org, string developer, string layoutSetName, string layoutName, string componentId) { - string actualApp = "deleted-component-before-delete"; + string actualApp = "app-with-summary2-components"; string app = TestDataHelper.GenerateTestRepoName(); await CopyRepositoryForTest(org, actualApp, developer, app); @@ -121,7 +121,7 @@ public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummaryCom HttpResponseMessage response = await SendHttpRequest(url, payload); response.StatusCode.Should().Be(HttpStatusCode.OK); - string expectedApp = "deleted-component-after-delete"; + string expectedApp = "app-with-summary2-components-after-deleting-references"; string[] layoutPaths = [ "component/layouts/Side1.json", diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/component/Settings.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/Settings.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/component/Settings.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/component/layouts/Side1.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/component/layouts/Side1.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/component/layouts/Side2.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component/layouts/Side2.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/component/layouts/Side2.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/component2/Settings.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/Settings.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/component2/Settings.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/component2/layouts/Side1.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/component2/layouts/Side1.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/component2/layouts/Side2.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/component2/layouts/Side2.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/component2/layouts/Side2.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout-sets.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layout-sets.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout-sets.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layout-sets.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layout/Settings.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout/Settings.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layout/Settings.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layout/layouts/Side1.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layout/layouts/Side1.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layout2/Settings.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/Settings.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layout2/Settings.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layout2/layouts/Side1.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layout2/layouts/Side1.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layout2/layouts/Side2.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layout2/layouts/Side2.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layout2/layouts/Side2.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layoutSet2/Settings.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/Settings.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layoutSet2/Settings.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layoutSet2/layouts/Side1.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layoutSet2/layouts/Side1.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layoutSet2/layouts/Side2.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-after-delete/App/ui/layoutSet2/layouts/Side2.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-deleting-references/App/ui/layoutSet2/layouts/Side2.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/component/Settings.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/Settings.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/component/Settings.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/component/layouts/Side1.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/component/layouts/Side1.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/component/layouts/Side2.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component/layouts/Side2.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/component/layouts/Side2.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/component2/Settings.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/Settings.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/component2/Settings.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/component2/layouts/Side1.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/component2/layouts/Side1.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/component2/layouts/Side2.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/component2/layouts/Side2.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/component2/layouts/Side2.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout-sets.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout-sets.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout-sets.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout-sets.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout/Settings.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/Settings.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout/Settings.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout/layouts/Side1.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout/layouts/Side1.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout/layouts/Side2.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout/layouts/Side2.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout/layouts/Side2.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout2/Settings.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/Settings.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout2/Settings.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout2/layouts/Side1.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout2/layouts/Side1.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout2/layouts/Side2.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layout2/layouts/Side2.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layout2/layouts/Side2.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layoutSet/Settings.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/Settings.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layoutSet/Settings.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layoutSet/layouts/Side1.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layoutSet/layouts/Side1.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layoutSet/layouts/Side2.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet/layouts/Side2.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layoutSet/layouts/Side2.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layoutSet2/Settings.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/Settings.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layoutSet2/Settings.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layoutSet2/layouts/Side1.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/layouts/Side1.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layoutSet2/layouts/Side1.json diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layoutSet2/layouts/Side2.json similarity index 100% rename from backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/deleted-component-before-delete/App/ui/layoutSet2/layouts/Side2.json rename to backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components/App/ui/layoutSet2/layouts/Side2.json From fd717a6a0fbd7296a8fc64566dd04faa1f1d0beb Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Tue, 7 Jan 2025 12:31:08 +0100 Subject: [PATCH 19/25] Add tests --- .../ProcessTaskIdChangedLayoutsHandler.cs | 92 +++---------------- .../Implementation/AppDevelopmentService.cs | 50 +++++----- .../SaveFormLayoutTests.cs | 44 +++++++++ .../UpdateFormLayoutNameTests.cs | 35 +++++++ .../App/ui/component/Settings.json | 9 ++ .../App/ui/component/layouts/Side1.json | 64 +++++++++++++ .../App/ui/component/layouts/Side2.json | 27 ++++++ .../App/ui/component2/Settings.json | 9 ++ .../App/ui/component2/layouts/Side1.json | 56 +++++++++++ .../App/ui/component2/layouts/Side2.json | 64 +++++++++++++ .../App/ui/layout-sets.json | 42 +++++++++ .../App/ui/layout/Settings.json | 9 ++ .../App/ui/layout/layouts/Side1.json | 49 ++++++++++ .../App/ui/layout/layouts/Side2-new.json | 20 ++++ .../App/ui/layout2/Settings.json | 9 ++ .../App/ui/layout2/layouts/Side1.json | 53 +++++++++++ .../App/ui/layout2/layouts/Side2.json | 49 ++++++++++ .../App/ui/layoutSet-new/Settings.json | 9 ++ .../App/ui/layoutSet-new/layouts/Side1.json | 13 +++ .../App/ui/layoutSet-new/layouts/Side2.json | 20 ++++ .../App/ui/layoutSet2/Settings.json | 9 ++ .../App/ui/layoutSet2/layouts/Side1.json | 54 +++++++++++ .../App/ui/layoutSet2/layouts/Side2.json | 49 ++++++++++ 23 files changed, 729 insertions(+), 106 deletions(-) create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout-sets.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side2-new.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side2.json diff --git a/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs index acee366380d..0b67fa7a885 100644 --- a/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs +++ b/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs @@ -1,10 +1,9 @@ -using System.IO; -using System.Linq; -using System.Text.Json.Nodes; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Altinn.Studio.Designer.Events; using Altinn.Studio.Designer.Hubs.SyncHub; +using Altinn.Studio.Designer.Models; using Altinn.Studio.Designer.Services.Interfaces; using MediatR; @@ -12,90 +11,25 @@ namespace Altinn.Studio.Designer.EventHandlers.ProcessTaskIdChanged; public class ProcessTaskIdChangedLayoutsHandler : INotificationHandler { - private readonly IAltinnGitRepositoryFactory _altinnGitRepositoryFactory; private readonly IFileSyncHandlerExecutor _fileSyncHandlerExecutor; + private readonly IAppDevelopmentService _appDevelopmentService; - public ProcessTaskIdChangedLayoutsHandler(IAltinnGitRepositoryFactory altinnGitRepositoryFactory, - IFileSyncHandlerExecutor fileSyncHandlerExecutor) + public ProcessTaskIdChangedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) { - _altinnGitRepositoryFactory = altinnGitRepositoryFactory; _fileSyncHandlerExecutor = fileSyncHandlerExecutor; + _appDevelopmentService = appDevelopmentService; } public async Task Handle(ProcessTaskIdChangedEvent notification, CancellationToken cancellationToken) { - var repository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository( - notification.EditingContext.Org, - notification.EditingContext.Repo, - notification.EditingContext.Developer); - - if (!repository.AppUsesLayoutSets()) - { - return; - } - - var layoutSetsFile = await repository.GetLayoutSetsFile(cancellationToken); - - foreach (string layoutSetName in layoutSetsFile.Sets.Select(layoutSet => layoutSet.Id)) - { - string[] layoutNames; - try - { - layoutNames = repository.GetLayoutNames(layoutSetName); - } - catch (FileNotFoundException) + await _fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( + notification.EditingContext, + SyncErrorCodes.LayoutTaskIdSyncError, + "layouts", + async () => { - continue; - } - - await _fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( - notification.EditingContext, - SyncErrorCodes.LayoutTaskIdSyncError, - $"App/ui/{layoutSetName}/layouts", - async () => - { - bool hasChanged = false; - - foreach (string layoutName in layoutNames) - { - var layout = await repository.GetLayout(layoutSetName, layoutName, cancellationToken); - if (TryChangeLayoutTaskIds(layout, notification.OldId, notification.NewId)) - { - await repository.SaveLayout(layoutSetName, layoutName, layout, cancellationToken); - hasChanged = true; - } - } - - return hasChanged; - }); - } - } - - private static bool TryChangeLayoutTaskIds(JsonNode node, string oldId, string newId) - { - bool hasChanged = false; - - if (node is JsonObject jsonObject) - { - foreach (var property in jsonObject.ToList()) - { - if (property.Key == "taskId" && property.Value?.ToString() == oldId) - { - jsonObject["taskId"] = newId; - hasChanged = true; - } - - hasChanged |= TryChangeLayoutTaskIds(property.Value, oldId, newId); - } - } - else if (node is JsonArray jsonArray) - { - foreach (var element in jsonArray) - { - hasChanged |= TryChangeLayoutTaskIds(element, oldId, newId); - } - } - - return hasChanged; + List referencesToUpdate = [new Reference("task", null, notification.OldId, notification.NewId)]; + return await _appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); + }); } } diff --git a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs index 6b764a4f912..169440d9287 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -618,6 +618,7 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp var deletedLayouts = deletedReferences.Where(item => item.Type == "page").ToList(); var deletedComponents = deletedReferences.Where(item => item.Type == "component").ToList(); + var updatedTasks = updatedReferences.Where(item => item.Type == "task").ToList(); var updatedLayoutsSets = updatedReferences.Where(item => item.Type == "layoutSet").ToList(); var updatedLayouts = updatedReferences.Where(item => item.Type == "page").ToList(); var updatedComponents = updatedReferences.Where(item => item.Type == "component").ToList(); @@ -710,12 +711,11 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp string taskId = target["taskId"]?.GetValue(); string layoutSetId = string.IsNullOrEmpty(taskId) ? layoutSet.Id : layoutSets?.FirstOrDefault(item => item.Tasks?.Contains(taskId) ?? false)?.Id; - if (type switch - { - "layoutSet" => deletedLayoutsSetIds.Contains(layoutSetId), - "page" => deletedLayouts.Exists(item => item.LayoutSetName == layoutSetId && item.Id == id), - "component" => deletedComponents.Exists(item => item.LayoutSetName == layoutSetId && item.Id == id) - }) + if ( + (type == "page" && deletedLayouts.Exists(item => item.LayoutSetName == layoutSetId && item.Id == id)) + || (type == "component" && deletedComponents.Exists(item => item.LayoutSetName == layoutSetId && item.Id == id)) + || deletedLayoutsSetIds.Contains(layoutSetId) + ) { referencesToDelete.Add(new Reference("component", layoutSet.Id, componentId)); componentList.RemoveAt(i); @@ -724,34 +724,30 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp else { Reference updatedReference = null; - switch (type) { - case "layoutSet": - updatedReference = updatedLayoutsSets.FirstOrDefault(item => item.Type == type && item.Id == layoutSetId); - if (updatedReference != null) - { - target["taskId"] = updatedReference.NewId; - hasLayoutChanges = true; - } - break; case "page": - updatedReference = updatedLayouts.FirstOrDefault(item => item.Type == type && item.LayoutSetName == layoutSetId && item.Id == id); - if (updatedReference != null) - { - target["id"] = updatedReference.NewId; - hasLayoutChanges = true; - } + updatedReference = updatedLayouts.FirstOrDefault(item => item.LayoutSetName == layoutSetId && item.Id == id); break; case "component": - updatedReference = updatedComponents.FirstOrDefault(item => item.Type == type && item.LayoutSetName == layoutSetId && item.Id == id); - if (updatedReference != null) - { - target["id"] = updatedReference.NewId; - hasLayoutChanges = true; - } + updatedReference = updatedComponents.FirstOrDefault(item => item.LayoutSetName == layoutSetId && item.Id == id); break; } + if (updatedReference != null) + { + target["id"] = updatedReference.NewId; + hasLayoutChanges = true; + } + + if (!string.IsNullOrEmpty(taskId)) + { + updatedReference = updatedTasks.FirstOrDefault(item => item.Id == taskId); + if (updatedReference != null) + { + target["taskId"] = updatedReference.NewId; + hasLayoutChanges = true; + } + } } if (component["overrides"] is JsonArray overrideList) diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs index 24dbd314057..0ad67ba963f 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using System.Net; using System.Net.Http; @@ -138,6 +139,49 @@ public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummary2Co }); } + [Theory] + [InlineData("ttd", "testUser", "component", "Side2", "Input-Om7N3y", "Input-Om7N3y-new")] + public async Task SaveFormLayoutWithUpdatedComponentName_UpdatesAssociatedSummary2Components_ReturnsOk(string org, string developer, string layoutSetName, string layoutName, string componentId, string newComponentId) + { + string actualApp = "app-with-summary2-components"; + string app = TestDataHelper.GenerateTestRepoName(); + await CopyRepositoryForTest(org, actualApp, developer, app); + + string layout = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{layoutSetName}/layouts/{layoutName}.json"); + JsonNode layoutWithUpdatedComponent = JsonNode.Parse(layout); + + string url = $"{VersionPrefix(org, app)}/form-layout/{layoutName}?layoutSetName={layoutSetName}"; + var payload = new JsonObject + { + ["componentIdsChange"] = new JsonArray() { + new JsonObject + { + ["oldComponentId"] = componentId, + ["newComponentId"] = newComponentId, + } + }, + ["layout"] = layoutWithUpdatedComponent + }; + HttpResponseMessage response = await SendHttpRequest(url, payload); + response.StatusCode.Should().Be(HttpStatusCode.OK); + + string expectedApp = "app-with-summary2-components-after-updating-references"; + + string[] layoutPaths = [ + "component/layouts/Side1.json", + "component/layouts/Side2.json", + "component2/layouts/Side1.json", + "component2/layouts/Side2.json" + ]; + + layoutPaths.ToList().ForEach(file => + { + string actual = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{file}"); + string expected = TestDataHelper.GetFileFromRepo(org, expectedApp, developer, $"App/ui/{file}"); + JsonUtils.DeepEquals(actual, expected).Should().BeTrue(); + }); + } + [Theory] [InlineData("ttd", "app-with-layoutsets", "testUser", "testLayout", "layoutSet1", "TestData/App/ui/layoutWithUnknownProperties.json")] public async Task SaveFormLayoutWithNewPageLanguageUpdate_ReturnsOk(string org, string app, string developer, string layoutName, string layoutSetName, string layoutPath) diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs index a14d0f12964..680bd69df28 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs @@ -9,6 +9,8 @@ using FluentAssertions; using Microsoft.AspNetCore.Mvc.Testing; using Xunit; +using System.Linq; +using SharedResources.Tests; namespace Designer.Tests.Controllers.AppDevelopmentController { @@ -69,5 +71,38 @@ public async Task UpdateFormLayoutName_NonExistingName_ShouldReturnNotFound(stri response.StatusCode.Should().Be(HttpStatusCode.NotFound); } + [Theory] + [InlineData("ttd", "testUser", "layout", "Side2", "Side2-new")] + public async Task UpdateFormLayoutName_UpdatesAssociatedSummary2Components_ReturnsOk(string org, string developer, string layoutSetName, string layoutName, string newLayoutName) + { + string actualApp = "app-with-summary2-components"; + string app = TestDataHelper.GenerateTestRepoName(); + await CopyRepositoryForTest(org, actualApp, developer, app); + + string url = $"{VersionPrefix(org, app)}/form-layout-name/{layoutName}?layoutSetName={layoutSetName}"; + using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url) + { + Content = new StringContent($"\"{newLayoutName}\"", Encoding.UTF8, MediaTypeNames.Application.Json) + }; + + using var response = await HttpClient.SendAsync(httpRequestMessage); + response.StatusCode.Should().Be(HttpStatusCode.OK); + + string expectedApp = "app-with-summary2-components-after-updating-references"; + + string[] layoutPaths = [ + "layout/layouts/Side1.json", + "layout/layouts/Side2.json", + "layout2/layouts/Side1.json", + "layout2/layouts/Side2.json", + ]; + + layoutPaths.ToList().ForEach(file => + { + string actual = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{file}"); + string expected = TestDataHelper.GetFileFromRepo(org, expectedApp, developer, $"App/ui/{file}"); + JsonUtils.DeepEquals(actual, expected).Should().BeTrue(); + }); + } } } diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side1.json new file mode 100644 index 00000000000..6345da9bdc3 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side1.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "" + }, + "id": "Summary2-9iG1lB", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "" + }, + "id": "Summary2-R8HsuB", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-mL8NjJ", + "type": "Summary2", + "overrides": [ + { + "componentId": "Input-Om7N3y-new", + "displayType": "string" + } + ] + }, + { + "target": { + "type": "component", + "id": "Input-qWr0oa", + "taskId": "" + }, + "id": "Summary2-0BV88Q", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-Om7N3y-new", + "taskId": "" + }, + "id": "Summary2-dTepe0", + "type": "Summary2" + }, + { + "id": "NavigationButtons-DfcNol", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side2.json new file mode 100644 index 00000000000..ec9bc398b4b --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side2.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-Om7N3y-new", + "type": "Input" + }, + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-qWr0oa", + "type": "Input" + }, + { + "id": "NavigationButtons-GAW8Dx", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side1.json new file mode 100644 index 00000000000..8489464261c --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side1.json @@ -0,0 +1,56 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-LCr3oK", + "type": "Input" + }, + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "" + }, + "id": "Summary2-eoT5QK", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "" + }, + "id": "Summary2-NJfE92", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-BGHvph", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-LCr3oK", + "taskId": "" + }, + "id": "Summary2-rb2ml2", + "type": "Summary2" + }, + { + "id": "NavigationButtons-t7UTGJ", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side2.json new file mode 100644 index 00000000000..6fc08c2ad27 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side2.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "component" + }, + "id": "Summary2-2FSqcf", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "component" + }, + "id": "Summary2-eGrDpP", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "component" + }, + "id": "Summary2-uJDgMu", + "type": "Summary2", + "overrides": [ + { + "componentId": "Input-Om7N3y-new", + "displayType": "string" + } + ] + }, + { + "target": { + "type": "component", + "id": "Input-qWr0oa", + "taskId": "component" + }, + "id": "Summary2-2JiT3P", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-Om7N3y-new", + "taskId": "component" + }, + "id": "Summary2-vIXkWO", + "type": "Summary2" + }, + { + "id": "NavigationButtons-BYcvaT", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout-sets.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout-sets.json new file mode 100644 index 00000000000..b28d6340c73 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout-sets.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout-sets.schema.v1.json", + "sets": [ + { + "id": "component", + "tasks": [ + "component" + ] + }, + { + "id": "layout", + "tasks": [ + "layout" + ] + }, + { + "id": "layoutSet-new", + "tasks": [ + "layoutSet-new" + ] + }, + { + "id": "component2", + "tasks": [ + "component2" + ] + }, + { + "id": "layout2", + "tasks": [ + "layout2" + ] + }, + { + "id": "layoutSet2", + "tasks": [ + "layoutSet2" + ] + } + ], + "uiSettings": {} +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/Settings.json new file mode 100644 index 00000000000..4668d52f882 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2-new" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side1.json new file mode 100644 index 00000000000..e9968cf6512 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side1.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "" + }, + "id": "Summary2-FEI1HC", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "" + }, + "id": "Summary2-e2yYpk", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2-new", + "taskId": "" + }, + "id": "Summary2-qOn2O1", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-AVRSNf", + "taskId": "" + }, + "id": "Summary2-da0Tq6", + "type": "Summary2" + }, + { + "id": "NavigationButtons-7g3XcW", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side2-new.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side2-new.json new file mode 100644 index 00000000000..8b8ea337e26 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side2-new.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-AVRSNf", + "type": "Input" + }, + { + "id": "NavigationButtons-wDmNQu", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side1.json new file mode 100644 index 00000000000..2530921cc4e --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side1.json @@ -0,0 +1,53 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-QCSonu", + "type": "Input" + }, + { + "target": { + "type": "layoutSet", + "id": "" + }, + "id": "Summary2-18hFaH", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1" + }, + "id": "Summary2-iZJ80j", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-V55C6Q", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-QCSonu" + }, + "id": "Summary2-aI91Tv", + "type": "Summary2" + }, + { + "id": "NavigationButtons-2hGPi1", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side2.json new file mode 100644 index 00000000000..223f8377420 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side2.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "layout" + }, + "id": "Summary2-MfRiX8", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "layout" + }, + "id": "Summary2-66YavC", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2-new", + "taskId": "layout" + }, + "id": "Summary2-bmqvUb", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-AVRSNf", + "taskId": "layout" + }, + "id": "Summary2-uuKXTD", + "type": "Summary2" + }, + { + "id": "NavigationButtons-h0g3Wt", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side1.json new file mode 100644 index 00000000000..48f8a1f9cf7 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side1.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "id": "NavigationButtons-n2jUp6", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side2.json new file mode 100644 index 00000000000..6fa6e9455ff --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side2.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-hqcYqo", + "type": "Input" + }, + { + "id": "NavigationButtons-QzkEka", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side1.json new file mode 100644 index 00000000000..60fc1029c15 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side1.json @@ -0,0 +1,54 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-wrspcN", + "type": "Input" + }, + { + "target": { + "type": "layoutSet", + "id": "" + }, + "id": "Summary2-00SFBO", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1" + }, + "id": "Summary2-4069IB", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-Orxmu1", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-wrspcN", + "taskId": "" + }, + "id": "Summary2-2YoJGY", + "type": "Summary2" + }, + { + "id": "NavigationButtons-KnXA9y", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side2.json new file mode 100644 index 00000000000..b6351845ad5 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side2.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "layoutSet-new" + }, + "id": "Summary2-6VQ3LC", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "layoutSet-new" + }, + "id": "Summary2-LZxPWb", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "layoutSet-new" + }, + "id": "Summary2-El9z2Y", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-hqcYqo", + "taskId": "layoutSet-new" + }, + "id": "Summary2-SMqpYV", + "type": "Summary2" + }, + { + "id": "NavigationButtons-5ukC2N", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file From 3d2a84f7e5b84cf0c8b476fbf9a84e31ad885210 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Tue, 7 Jan 2025 12:54:23 +0100 Subject: [PATCH 20/25] Cleanup --- .../AppDevelopmentController/UpdateFormLayoutNameTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs index 680bd69df28..f207d9da541 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Linq; using System.Net; using System.Net.Http; using System.Net.Mime; @@ -8,9 +9,8 @@ using Designer.Tests.Utils; using FluentAssertions; using Microsoft.AspNetCore.Mvc.Testing; -using Xunit; -using System.Linq; using SharedResources.Tests; +using Xunit; namespace Designer.Tests.Controllers.AppDevelopmentController { From f91bdbd348c3d12d011d28123b9a60d7b8592e9e Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Tue, 7 Jan 2025 14:47:39 +0100 Subject: [PATCH 21/25] Remove update changes --- .../Controllers/AppDevelopmentController.cs | 42 +++------ .../ComponentIdChangedLayoutsHandler.cs | 8 -- .../LayoutPageIdChangedLayoutsHandler.cs | 26 ------ .../LayoutSetIdChangedLayoutsHandler.cs | 26 ------ .../ProcessTaskIdChangedLayoutsHandler.cs | 92 ++++++++++++++++--- .../Events/LayoutPageIdChangedEvent.cs | 12 --- .../Events/LayoutSetIdChangedEvent.cs | 11 --- .../Designer/Hubs/SyncHub/SyncErrorCodes.cs | 2 - .../Implementation/AppDevelopmentService.cs | 62 ------------- .../Interfaces/IAppDevelopmentService.cs | 4 +- .../SaveFormLayoutTests.cs | 43 --------- .../UpdateFormLayoutNameTests.cs | 33 ------- .../App/ui/component/Settings.json | 9 -- .../App/ui/component/layouts/Side1.json | 64 ------------- .../App/ui/component/layouts/Side2.json | 27 ------ .../App/ui/component2/Settings.json | 9 -- .../App/ui/component2/layouts/Side1.json | 56 ----------- .../App/ui/component2/layouts/Side2.json | 64 ------------- .../App/ui/layout-sets.json | 42 --------- .../App/ui/layout/Settings.json | 9 -- .../App/ui/layout/layouts/Side1.json | 49 ---------- .../App/ui/layout/layouts/Side2-new.json | 20 ---- .../App/ui/layout2/Settings.json | 9 -- .../App/ui/layout2/layouts/Side1.json | 53 ----------- .../App/ui/layout2/layouts/Side2.json | 49 ---------- .../App/ui/layoutSet-new/Settings.json | 9 -- .../App/ui/layoutSet-new/layouts/Side1.json | 13 --- .../App/ui/layoutSet-new/layouts/Side2.json | 20 ---- .../App/ui/layoutSet2/Settings.json | 9 -- .../App/ui/layoutSet2/layouts/Side1.json | 54 ----------- .../App/ui/layoutSet2/layouts/Side2.json | 49 ---------- 31 files changed, 94 insertions(+), 881 deletions(-) delete mode 100644 backend/src/Designer/EventHandlers/LayoutPageIdChanged/LayoutPageIdChangedLayoutsHandler.cs delete mode 100644 backend/src/Designer/EventHandlers/LayoutSetIdChanged/LayoutSetIdChangedLayoutsHandler.cs delete mode 100644 backend/src/Designer/Events/LayoutPageIdChangedEvent.cs delete mode 100644 backend/src/Designer/Events/LayoutSetIdChangedEvent.cs delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/Settings.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side1.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side2.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/Settings.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side1.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side2.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout-sets.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/Settings.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side1.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side2-new.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/Settings.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side1.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side2.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/Settings.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side1.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side2.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/Settings.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side1.json delete mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side2.json diff --git a/backend/src/Designer/Controllers/AppDevelopmentController.cs b/backend/src/Designer/Controllers/AppDevelopmentController.cs index 4b7d29b0d9f..745fd9a2b4e 100644 --- a/backend/src/Designer/Controllers/AppDevelopmentController.cs +++ b/backend/src/Designer/Controllers/AppDevelopmentController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; @@ -123,27 +124,24 @@ public async Task SaveFormLayout(string org, string app, [FromQuer if (formLayoutPayload.ComponentIdsChange is not null && !string.IsNullOrEmpty(layoutSetName)) { - foreach (var componentIdChange in formLayoutPayload.ComponentIdsChange) + foreach (var componentIdChange in formLayoutPayload.ComponentIdsChange.Where((componentIdChange) => componentIdChange.OldComponentId != componentIdChange.NewComponentId)) { - if (componentIdChange.OldComponentId != componentIdChange.NewComponentId) + if (componentIdChange.NewComponentId == null) { - if (componentIdChange.NewComponentId == null) + await _mediator.Publish(new ComponentDeletedEvent { - await _mediator.Publish(new ComponentDeletedEvent - { - ComponentId = componentIdChange.OldComponentId, - LayoutSetName = layoutSetName, - EditingContext = editingContext - }, cancellationToken); - } - await _mediator.Publish(new ComponentIdChangedEvent - { - OldComponentId = componentIdChange.OldComponentId, - NewComponentId = componentIdChange.NewComponentId, + ComponentId = componentIdChange.OldComponentId, LayoutSetName = layoutSetName, EditingContext = editingContext }, cancellationToken); } + await _mediator.Publish(new ComponentIdChangedEvent + { + OldComponentId = componentIdChange.OldComponentId, + NewComponentId = componentIdChange.NewComponentId, + LayoutSetName = layoutSetName, + EditingContext = editingContext + }, cancellationToken); } } if (!formLayouts.ContainsKey(layoutName)) @@ -207,24 +205,16 @@ await _mediator.Publish(new LayoutPageDeletedEvent /// Application identifier which is unique within an organisation. /// Name of the layout set the specific layout belongs to /// The current name of the form layout - /// An that observes if operation is cancelled. /// A success message if the save was successful [HttpPost] [Route("form-layout-name/{layoutName}")] - public async Task UpdateFormLayoutName(string org, string app, [FromQuery] string layoutSetName, [FromRoute] string layoutName, [FromBody] string newName, CancellationToken cancellationToken) + public ActionResult UpdateFormLayoutName(string org, string app, [FromQuery] string layoutSetName, [FromRoute] string layoutName, [FromBody] string newName) { try { string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext); var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer); _appDevelopmentService.UpdateFormLayoutName(editingContext, layoutSetName, layoutName, newName); - await _mediator.Publish(new LayoutPageIdChangedEvent - { - EditingContext = editingContext, - LayoutSetName = layoutSetName, - LayoutName = layoutName, - NewLayoutName = newName, - }, cancellationToken); return Ok(); } catch (FileNotFoundException exception) @@ -415,12 +405,6 @@ public async Task UpdateLayoutSetName(string org, string app, [Fro string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext); var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer); LayoutSets layoutSets = await _appDevelopmentService.UpdateLayoutSetName(editingContext, layoutSetIdToUpdate, newLayoutSetName, cancellationToken); - await _mediator.Publish(new LayoutSetIdChangedEvent - { - EditingContext = editingContext, - LayoutSetName = layoutSetIdToUpdate, - NewLayoutSetName = newLayoutSetName, - }, cancellationToken); return Ok(layoutSets); } diff --git a/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs index 2de41203bef..ecbfcc46d1e 100644 --- a/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs +++ b/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs @@ -1,11 +1,9 @@ -using System.Collections.Generic; using System.Linq; using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; using Altinn.Studio.Designer.Events; using Altinn.Studio.Designer.Hubs.SyncHub; -using Altinn.Studio.Designer.Models; using Altinn.Studio.Designer.Services.Interfaces; using MediatR; @@ -15,7 +13,6 @@ public class ComponentIdChangedLayoutsHandler : INotificationHandler referencesToUpdate = [new Reference("component", notification.LayoutSetName, notification.OldComponentId, notification.NewComponentId)]; - hasChanges |= await _appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); - return hasChanges; }); } diff --git a/backend/src/Designer/EventHandlers/LayoutPageIdChanged/LayoutPageIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/LayoutPageIdChanged/LayoutPageIdChangedLayoutsHandler.cs deleted file mode 100644 index 7772a125cf1..00000000000 --- a/backend/src/Designer/EventHandlers/LayoutPageIdChanged/LayoutPageIdChangedLayoutsHandler.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Altinn.Studio.Designer.Events; -using Altinn.Studio.Designer.Hubs.SyncHub; -using Altinn.Studio.Designer.Models; -using Altinn.Studio.Designer.Services.Interfaces; -using MediatR; - -namespace Altinn.Studio.Designer.EventHandlers.LayoutPageDeleted; - -public class LayoutPageIdChangedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler -{ - public async Task Handle(LayoutPageIdChangedEvent notification, CancellationToken cancellationToken) - { - await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( - notification.EditingContext, - SyncErrorCodes.LayoutPageIdChangedLayoutsSyncError, - "layouts", - async () => - { - List referencesToUpdate = [new Reference("page", notification.LayoutSetName, notification.LayoutName, notification.NewLayoutName)]; - return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); - }); - } -} diff --git a/backend/src/Designer/EventHandlers/LayoutSetIdChanged/LayoutSetIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/LayoutSetIdChanged/LayoutSetIdChangedLayoutsHandler.cs deleted file mode 100644 index 6502bd03b6e..00000000000 --- a/backend/src/Designer/EventHandlers/LayoutSetIdChanged/LayoutSetIdChangedLayoutsHandler.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using Altinn.Studio.Designer.Events; -using Altinn.Studio.Designer.Hubs.SyncHub; -using Altinn.Studio.Designer.Models; -using Altinn.Studio.Designer.Services.Interfaces; -using MediatR; - -namespace Altinn.Studio.Designer.EventHandlers.LayoutSetDeleted; - -public class LayoutSetIdChangedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler -{ - public async Task Handle(LayoutSetIdChangedEvent notification, CancellationToken cancellationToken) - { - await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( - notification.EditingContext, - SyncErrorCodes.LayoutSetIdChangedLayoutsSyncError, - "layouts", - async () => - { - List referencesToUpdate = [new Reference("layoutSet", notification.LayoutSetName, notification.LayoutSetName, notification.NewLayoutSetName)]; - return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); - }); - } -} diff --git a/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs index 0b67fa7a885..acee366380d 100644 --- a/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs +++ b/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs @@ -1,9 +1,10 @@ -using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; using Altinn.Studio.Designer.Events; using Altinn.Studio.Designer.Hubs.SyncHub; -using Altinn.Studio.Designer.Models; using Altinn.Studio.Designer.Services.Interfaces; using MediatR; @@ -11,25 +12,90 @@ namespace Altinn.Studio.Designer.EventHandlers.ProcessTaskIdChanged; public class ProcessTaskIdChangedLayoutsHandler : INotificationHandler { + private readonly IAltinnGitRepositoryFactory _altinnGitRepositoryFactory; private readonly IFileSyncHandlerExecutor _fileSyncHandlerExecutor; - private readonly IAppDevelopmentService _appDevelopmentService; - public ProcessTaskIdChangedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) + public ProcessTaskIdChangedLayoutsHandler(IAltinnGitRepositoryFactory altinnGitRepositoryFactory, + IFileSyncHandlerExecutor fileSyncHandlerExecutor) { + _altinnGitRepositoryFactory = altinnGitRepositoryFactory; _fileSyncHandlerExecutor = fileSyncHandlerExecutor; - _appDevelopmentService = appDevelopmentService; } public async Task Handle(ProcessTaskIdChangedEvent notification, CancellationToken cancellationToken) { - await _fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( - notification.EditingContext, - SyncErrorCodes.LayoutTaskIdSyncError, - "layouts", - async () => + var repository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository( + notification.EditingContext.Org, + notification.EditingContext.Repo, + notification.EditingContext.Developer); + + if (!repository.AppUsesLayoutSets()) + { + return; + } + + var layoutSetsFile = await repository.GetLayoutSetsFile(cancellationToken); + + foreach (string layoutSetName in layoutSetsFile.Sets.Select(layoutSet => layoutSet.Id)) + { + string[] layoutNames; + try + { + layoutNames = repository.GetLayoutNames(layoutSetName); + } + catch (FileNotFoundException) { - List referencesToUpdate = [new Reference("task", null, notification.OldId, notification.NewId)]; - return await _appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); - }); + continue; + } + + await _fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( + notification.EditingContext, + SyncErrorCodes.LayoutTaskIdSyncError, + $"App/ui/{layoutSetName}/layouts", + async () => + { + bool hasChanged = false; + + foreach (string layoutName in layoutNames) + { + var layout = await repository.GetLayout(layoutSetName, layoutName, cancellationToken); + if (TryChangeLayoutTaskIds(layout, notification.OldId, notification.NewId)) + { + await repository.SaveLayout(layoutSetName, layoutName, layout, cancellationToken); + hasChanged = true; + } + } + + return hasChanged; + }); + } + } + + private static bool TryChangeLayoutTaskIds(JsonNode node, string oldId, string newId) + { + bool hasChanged = false; + + if (node is JsonObject jsonObject) + { + foreach (var property in jsonObject.ToList()) + { + if (property.Key == "taskId" && property.Value?.ToString() == oldId) + { + jsonObject["taskId"] = newId; + hasChanged = true; + } + + hasChanged |= TryChangeLayoutTaskIds(property.Value, oldId, newId); + } + } + else if (node is JsonArray jsonArray) + { + foreach (var element in jsonArray) + { + hasChanged |= TryChangeLayoutTaskIds(element, oldId, newId); + } + } + + return hasChanged; } } diff --git a/backend/src/Designer/Events/LayoutPageIdChangedEvent.cs b/backend/src/Designer/Events/LayoutPageIdChangedEvent.cs deleted file mode 100644 index 4059f3ab287..00000000000 --- a/backend/src/Designer/Events/LayoutPageIdChangedEvent.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Altinn.Studio.Designer.Models; -using MediatR; - -namespace Altinn.Studio.Designer.Events; - -public class LayoutPageIdChangedEvent : INotification -{ - public AltinnRepoEditingContext EditingContext { get; set; } - public string LayoutSetName { get; set; } - public string LayoutName { get; set; } - public string NewLayoutName { get; set; } -} diff --git a/backend/src/Designer/Events/LayoutSetIdChangedEvent.cs b/backend/src/Designer/Events/LayoutSetIdChangedEvent.cs deleted file mode 100644 index 1f327277588..00000000000 --- a/backend/src/Designer/Events/LayoutSetIdChangedEvent.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Altinn.Studio.Designer.Models; -using MediatR; - -namespace Altinn.Studio.Designer.Events; - -public class LayoutSetIdChangedEvent : INotification -{ - public AltinnRepoEditingContext EditingContext { get; set; } - public string LayoutSetName { get; set; } - public string NewLayoutSetName { get; set; } -} diff --git a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs index d4811e1a898..04178d4eb7e 100644 --- a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs +++ b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs @@ -10,11 +10,9 @@ public static class SyncErrorCodes public const string LayoutSetsDataTypeSyncError = nameof(LayoutSetsDataTypeSyncError); public const string LayoutSetComponentIdSyncError = nameof(LayoutSetComponentIdSyncError); public const string LayoutSetDeletedLayoutsSyncError = nameof(LayoutSetDeletedLayoutsSyncError); - public const string LayoutSetIdChangedLayoutsSyncError = nameof(LayoutSetIdChangedLayoutsSyncError); public const string LayoutSetSubFormButtonSyncError = nameof(LayoutSetSubFormButtonSyncError); public const string SettingsComponentIdSyncError = nameof(SettingsComponentIdSyncError); public const string LayoutPageAddSyncError = nameof(LayoutPageAddSyncError); public const string ComponentDeletedLayoutsSyncError = nameof(ComponentDeletedLayoutsSyncError); public const string LayoutPageDeletedLayoutsSyncError = nameof(LayoutPageDeletedLayoutsSyncError); - public const string LayoutPageIdChangedLayoutsSyncError = nameof(LayoutPageIdChangedLayoutsSyncError); } diff --git a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs index 169440d9287..6b7cb76324e 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -612,17 +612,11 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp bool hasChanges = false; var deletedReferences = referencesToUpdate.Where(item => string.IsNullOrEmpty(item.NewId)).ToList(); - var updatedReferences = referencesToUpdate.Where(item => !string.IsNullOrEmpty(item.NewId)).ToList(); var deletedLayoutsSetIds = deletedReferences.Where(item => item.Type == "layoutSet").Select(item => item.Id).ToList(); var deletedLayouts = deletedReferences.Where(item => item.Type == "page").ToList(); var deletedComponents = deletedReferences.Where(item => item.Type == "component").ToList(); - var updatedTasks = updatedReferences.Where(item => item.Type == "task").ToList(); - var updatedLayoutsSets = updatedReferences.Where(item => item.Type == "layoutSet").ToList(); - var updatedLayouts = updatedReferences.Where(item => item.Type == "page").ToList(); - var updatedComponents = updatedReferences.Where(item => item.Type == "component").ToList(); - foreach (LayoutSetConfig layoutSet in layoutSets ?? [new() { Id = null }]) { bool isLayoutSetDeleted = deletedLayoutsSetIds.Contains(layoutSet.Id); @@ -642,7 +636,6 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp } var deletedComponentIdsFromCurrentLayoutSet = deletedComponents.Where(item => item.LayoutSetName == layoutSet.Id && string.IsNullOrEmpty(item.NewId)).Select(item => item.Id).ToList(); - var updatedComponentsFromCurrentLayoutSet = updatedComponents.Where(item => item.LayoutSetName == layoutSet.Id && !string.IsNullOrEmpty(item.NewId)).ToList(); if (data["layout"] is JsonArray componentList) { @@ -662,15 +655,6 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp componentList.RemoveAt(i); hasLayoutChanges = true; } - else - { - Reference updatedReference = updatedComponentsFromCurrentLayoutSet.FirstOrDefault(item => item.Id == componentId); - if (updatedReference != null) - { - component["id"] = updatedReference.NewId; - hasLayoutChanges = true; - } - } if (isLayoutSetDeleted || isLayoutDeleted || isComponentDeleted) { @@ -693,15 +677,6 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp componentList.RemoveAt(i); hasLayoutChanges = true; } - else - { - Reference updatedReference = updatedLayoutsSets.FirstOrDefault(item => item.Id == subformLayoutSet); - if (updatedReference != null) - { - component["layoutSet"] = updatedReference.NewId; - hasLayoutChanges = true; - } - } break; case "Summary2": if (component["target"] is JsonObject target) @@ -721,34 +696,6 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp componentList.RemoveAt(i); hasLayoutChanges = true; } - else - { - Reference updatedReference = null; - switch (type) - { - case "page": - updatedReference = updatedLayouts.FirstOrDefault(item => item.LayoutSetName == layoutSetId && item.Id == id); - break; - case "component": - updatedReference = updatedComponents.FirstOrDefault(item => item.LayoutSetName == layoutSetId && item.Id == id); - break; - } - if (updatedReference != null) - { - target["id"] = updatedReference.NewId; - hasLayoutChanges = true; - } - - if (!string.IsNullOrEmpty(taskId)) - { - updatedReference = updatedTasks.FirstOrDefault(item => item.Id == taskId); - if (updatedReference != null) - { - target["taskId"] = updatedReference.NewId; - hasLayoutChanges = true; - } - } - } if (component["overrides"] is JsonArray overrideList) { @@ -761,15 +708,6 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp overrideList.RemoveAt(j); hasLayoutChanges = true; } - else - { - Reference updatedReference = updatedComponents.FirstOrDefault(item => item.LayoutSetName == layoutSetId && item.Id == overrideComponentId); - if (updatedReference != null) - { - overrideItem["componentId"] = updatedReference.NewId; - hasLayoutChanges = true; - } - } if (overrideList.Count == 0) { diff --git a/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs b/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs index de0541624ae..11e656b1ec0 100644 --- a/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs +++ b/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs @@ -218,8 +218,8 @@ public Task GetModelMetadata( /// Update layout references /// /// An . - /// The references to delete. + /// The references to update. /// An that observes if operation is cancelled. - public Task UpdateLayoutReferences(AltinnRepoEditingContext altinnRepoEditingContext, List referencesToDelete, CancellationToken cancellationToken); + public Task UpdateLayoutReferences(AltinnRepoEditingContext altinnRepoEditingContext, List referencesToUpdate, CancellationToken cancellationToken); } } diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs index 0ad67ba963f..9244a74ddd9 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs @@ -139,49 +139,6 @@ public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummary2Co }); } - [Theory] - [InlineData("ttd", "testUser", "component", "Side2", "Input-Om7N3y", "Input-Om7N3y-new")] - public async Task SaveFormLayoutWithUpdatedComponentName_UpdatesAssociatedSummary2Components_ReturnsOk(string org, string developer, string layoutSetName, string layoutName, string componentId, string newComponentId) - { - string actualApp = "app-with-summary2-components"; - string app = TestDataHelper.GenerateTestRepoName(); - await CopyRepositoryForTest(org, actualApp, developer, app); - - string layout = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{layoutSetName}/layouts/{layoutName}.json"); - JsonNode layoutWithUpdatedComponent = JsonNode.Parse(layout); - - string url = $"{VersionPrefix(org, app)}/form-layout/{layoutName}?layoutSetName={layoutSetName}"; - var payload = new JsonObject - { - ["componentIdsChange"] = new JsonArray() { - new JsonObject - { - ["oldComponentId"] = componentId, - ["newComponentId"] = newComponentId, - } - }, - ["layout"] = layoutWithUpdatedComponent - }; - HttpResponseMessage response = await SendHttpRequest(url, payload); - response.StatusCode.Should().Be(HttpStatusCode.OK); - - string expectedApp = "app-with-summary2-components-after-updating-references"; - - string[] layoutPaths = [ - "component/layouts/Side1.json", - "component/layouts/Side2.json", - "component2/layouts/Side1.json", - "component2/layouts/Side2.json" - ]; - - layoutPaths.ToList().ForEach(file => - { - string actual = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{file}"); - string expected = TestDataHelper.GetFileFromRepo(org, expectedApp, developer, $"App/ui/{file}"); - JsonUtils.DeepEquals(actual, expected).Should().BeTrue(); - }); - } - [Theory] [InlineData("ttd", "app-with-layoutsets", "testUser", "testLayout", "layoutSet1", "TestData/App/ui/layoutWithUnknownProperties.json")] public async Task SaveFormLayoutWithNewPageLanguageUpdate_ReturnsOk(string org, string app, string developer, string layoutName, string layoutSetName, string layoutPath) diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs index f207d9da541..4f5ebe84218 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs @@ -71,38 +71,5 @@ public async Task UpdateFormLayoutName_NonExistingName_ShouldReturnNotFound(stri response.StatusCode.Should().Be(HttpStatusCode.NotFound); } - [Theory] - [InlineData("ttd", "testUser", "layout", "Side2", "Side2-new")] - public async Task UpdateFormLayoutName_UpdatesAssociatedSummary2Components_ReturnsOk(string org, string developer, string layoutSetName, string layoutName, string newLayoutName) - { - string actualApp = "app-with-summary2-components"; - string app = TestDataHelper.GenerateTestRepoName(); - await CopyRepositoryForTest(org, actualApp, developer, app); - - string url = $"{VersionPrefix(org, app)}/form-layout-name/{layoutName}?layoutSetName={layoutSetName}"; - using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url) - { - Content = new StringContent($"\"{newLayoutName}\"", Encoding.UTF8, MediaTypeNames.Application.Json) - }; - - using var response = await HttpClient.SendAsync(httpRequestMessage); - response.StatusCode.Should().Be(HttpStatusCode.OK); - - string expectedApp = "app-with-summary2-components-after-updating-references"; - - string[] layoutPaths = [ - "layout/layouts/Side1.json", - "layout/layouts/Side2.json", - "layout2/layouts/Side1.json", - "layout2/layouts/Side2.json", - ]; - - layoutPaths.ToList().ForEach(file => - { - string actual = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{file}"); - string expected = TestDataHelper.GetFileFromRepo(org, expectedApp, developer, $"App/ui/{file}"); - JsonUtils.DeepEquals(actual, expected).Should().BeTrue(); - }); - } } } diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/Settings.json deleted file mode 100644 index 6bb44cf6db8..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/Settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", - "pages": { - "order": [ - "Side1", - "Side2" - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side1.json deleted file mode 100644 index 6345da9bdc3..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side1.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "target": { - "type": "layoutSet", - "id": "", - "taskId": "" - }, - "id": "Summary2-9iG1lB", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side1", - "taskId": "" - }, - "id": "Summary2-R8HsuB", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side2", - "taskId": "" - }, - "id": "Summary2-mL8NjJ", - "type": "Summary2", - "overrides": [ - { - "componentId": "Input-Om7N3y-new", - "displayType": "string" - } - ] - }, - { - "target": { - "type": "component", - "id": "Input-qWr0oa", - "taskId": "" - }, - "id": "Summary2-0BV88Q", - "type": "Summary2" - }, - { - "target": { - "type": "component", - "id": "Input-Om7N3y-new", - "taskId": "" - }, - "id": "Summary2-dTepe0", - "type": "Summary2" - }, - { - "id": "NavigationButtons-DfcNol", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side2.json deleted file mode 100644 index ec9bc398b4b..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side2.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "dataModelBindings": { - "simpleBinding": "" - }, - "id": "Input-Om7N3y-new", - "type": "Input" - }, - { - "dataModelBindings": { - "simpleBinding": "" - }, - "id": "Input-qWr0oa", - "type": "Input" - }, - { - "id": "NavigationButtons-GAW8Dx", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/Settings.json deleted file mode 100644 index 6bb44cf6db8..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/Settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", - "pages": { - "order": [ - "Side1", - "Side2" - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side1.json deleted file mode 100644 index 8489464261c..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side1.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "dataModelBindings": { - "simpleBinding": "" - }, - "id": "Input-LCr3oK", - "type": "Input" - }, - { - "target": { - "type": "layoutSet", - "id": "", - "taskId": "" - }, - "id": "Summary2-eoT5QK", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side1", - "taskId": "" - }, - "id": "Summary2-NJfE92", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side2", - "taskId": "" - }, - "id": "Summary2-BGHvph", - "type": "Summary2" - }, - { - "target": { - "type": "component", - "id": "Input-LCr3oK", - "taskId": "" - }, - "id": "Summary2-rb2ml2", - "type": "Summary2" - }, - { - "id": "NavigationButtons-t7UTGJ", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side2.json deleted file mode 100644 index 6fc08c2ad27..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side2.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "target": { - "type": "layoutSet", - "id": "", - "taskId": "component" - }, - "id": "Summary2-2FSqcf", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side1", - "taskId": "component" - }, - "id": "Summary2-eGrDpP", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side2", - "taskId": "component" - }, - "id": "Summary2-uJDgMu", - "type": "Summary2", - "overrides": [ - { - "componentId": "Input-Om7N3y-new", - "displayType": "string" - } - ] - }, - { - "target": { - "type": "component", - "id": "Input-qWr0oa", - "taskId": "component" - }, - "id": "Summary2-2JiT3P", - "type": "Summary2" - }, - { - "target": { - "type": "component", - "id": "Input-Om7N3y-new", - "taskId": "component" - }, - "id": "Summary2-vIXkWO", - "type": "Summary2" - }, - { - "id": "NavigationButtons-BYcvaT", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout-sets.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout-sets.json deleted file mode 100644 index b28d6340c73..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout-sets.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout-sets.schema.v1.json", - "sets": [ - { - "id": "component", - "tasks": [ - "component" - ] - }, - { - "id": "layout", - "tasks": [ - "layout" - ] - }, - { - "id": "layoutSet-new", - "tasks": [ - "layoutSet-new" - ] - }, - { - "id": "component2", - "tasks": [ - "component2" - ] - }, - { - "id": "layout2", - "tasks": [ - "layout2" - ] - }, - { - "id": "layoutSet2", - "tasks": [ - "layoutSet2" - ] - } - ], - "uiSettings": {} -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/Settings.json deleted file mode 100644 index 4668d52f882..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/Settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", - "pages": { - "order": [ - "Side1", - "Side2-new" - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side1.json deleted file mode 100644 index e9968cf6512..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side1.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "target": { - "type": "layoutSet", - "id": "", - "taskId": "" - }, - "id": "Summary2-FEI1HC", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side1", - "taskId": "" - }, - "id": "Summary2-e2yYpk", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side2-new", - "taskId": "" - }, - "id": "Summary2-qOn2O1", - "type": "Summary2" - }, - { - "target": { - "type": "component", - "id": "Input-AVRSNf", - "taskId": "" - }, - "id": "Summary2-da0Tq6", - "type": "Summary2" - }, - { - "id": "NavigationButtons-7g3XcW", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side2-new.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side2-new.json deleted file mode 100644 index 8b8ea337e26..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side2-new.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "dataModelBindings": { - "simpleBinding": "" - }, - "id": "Input-AVRSNf", - "type": "Input" - }, - { - "id": "NavigationButtons-wDmNQu", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/Settings.json deleted file mode 100644 index 6bb44cf6db8..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/Settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", - "pages": { - "order": [ - "Side1", - "Side2" - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side1.json deleted file mode 100644 index 2530921cc4e..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side1.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "dataModelBindings": { - "simpleBinding": "" - }, - "id": "Input-QCSonu", - "type": "Input" - }, - { - "target": { - "type": "layoutSet", - "id": "" - }, - "id": "Summary2-18hFaH", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side1" - }, - "id": "Summary2-iZJ80j", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side2", - "taskId": "" - }, - "id": "Summary2-V55C6Q", - "type": "Summary2" - }, - { - "target": { - "type": "component", - "id": "Input-QCSonu" - }, - "id": "Summary2-aI91Tv", - "type": "Summary2" - }, - { - "id": "NavigationButtons-2hGPi1", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side2.json deleted file mode 100644 index 223f8377420..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side2.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "target": { - "type": "layoutSet", - "id": "", - "taskId": "layout" - }, - "id": "Summary2-MfRiX8", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side1", - "taskId": "layout" - }, - "id": "Summary2-66YavC", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side2-new", - "taskId": "layout" - }, - "id": "Summary2-bmqvUb", - "type": "Summary2" - }, - { - "target": { - "type": "component", - "id": "Input-AVRSNf", - "taskId": "layout" - }, - "id": "Summary2-uuKXTD", - "type": "Summary2" - }, - { - "id": "NavigationButtons-h0g3Wt", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/Settings.json deleted file mode 100644 index 6bb44cf6db8..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/Settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", - "pages": { - "order": [ - "Side1", - "Side2" - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side1.json deleted file mode 100644 index 48f8a1f9cf7..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side1.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "id": "NavigationButtons-n2jUp6", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side2.json deleted file mode 100644 index 6fa6e9455ff..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side2.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "dataModelBindings": { - "simpleBinding": "" - }, - "id": "Input-hqcYqo", - "type": "Input" - }, - { - "id": "NavigationButtons-QzkEka", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/Settings.json deleted file mode 100644 index 6bb44cf6db8..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/Settings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", - "pages": { - "order": [ - "Side1", - "Side2" - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side1.json deleted file mode 100644 index 60fc1029c15..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side1.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "dataModelBindings": { - "simpleBinding": "" - }, - "id": "Input-wrspcN", - "type": "Input" - }, - { - "target": { - "type": "layoutSet", - "id": "" - }, - "id": "Summary2-00SFBO", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side1" - }, - "id": "Summary2-4069IB", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side2", - "taskId": "" - }, - "id": "Summary2-Orxmu1", - "type": "Summary2" - }, - { - "target": { - "type": "component", - "id": "Input-wrspcN", - "taskId": "" - }, - "id": "Summary2-2YoJGY", - "type": "Summary2" - }, - { - "id": "NavigationButtons-KnXA9y", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side2.json deleted file mode 100644 index b6351845ad5..00000000000 --- a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side2.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", - "data": { - "layout": [ - { - "target": { - "type": "layoutSet", - "id": "", - "taskId": "layoutSet-new" - }, - "id": "Summary2-6VQ3LC", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side1", - "taskId": "layoutSet-new" - }, - "id": "Summary2-LZxPWb", - "type": "Summary2" - }, - { - "target": { - "type": "page", - "id": "Side2", - "taskId": "layoutSet-new" - }, - "id": "Summary2-El9z2Y", - "type": "Summary2" - }, - { - "target": { - "type": "component", - "id": "Input-hqcYqo", - "taskId": "layoutSet-new" - }, - "id": "Summary2-SMqpYV", - "type": "Summary2" - }, - { - "id": "NavigationButtons-5ukC2N", - "showBackButton": true, - "textResourceBindings": {}, - "type": "NavigationButtons" - } - ] - } -} \ No newline at end of file From 8ba38b161311e0ad430a3f127c5dcb91a7df507f Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Tue, 7 Jan 2025 16:46:29 +0100 Subject: [PATCH 22/25] Revert "Remove update changes" This reverts commit f91bdbd348c3d12d011d28123b9a60d7b8592e9e. --- .../Controllers/AppDevelopmentController.cs | 42 ++++++--- .../ComponentIdChangedLayoutsHandler.cs | 8 ++ .../LayoutPageIdChangedLayoutsHandler.cs | 26 ++++++ .../LayoutSetIdChangedLayoutsHandler.cs | 26 ++++++ .../ProcessTaskIdChangedLayoutsHandler.cs | 92 +++---------------- .../Events/LayoutPageIdChangedEvent.cs | 12 +++ .../Events/LayoutSetIdChangedEvent.cs | 11 +++ .../Designer/Hubs/SyncHub/SyncErrorCodes.cs | 2 + .../Implementation/AppDevelopmentService.cs | 62 +++++++++++++ .../Interfaces/IAppDevelopmentService.cs | 4 +- .../SaveFormLayoutTests.cs | 43 +++++++++ .../UpdateFormLayoutNameTests.cs | 33 +++++++ .../App/ui/component/Settings.json | 9 ++ .../App/ui/component/layouts/Side1.json | 64 +++++++++++++ .../App/ui/component/layouts/Side2.json | 27 ++++++ .../App/ui/component2/Settings.json | 9 ++ .../App/ui/component2/layouts/Side1.json | 56 +++++++++++ .../App/ui/component2/layouts/Side2.json | 64 +++++++++++++ .../App/ui/layout-sets.json | 42 +++++++++ .../App/ui/layout/Settings.json | 9 ++ .../App/ui/layout/layouts/Side1.json | 49 ++++++++++ .../App/ui/layout/layouts/Side2-new.json | 20 ++++ .../App/ui/layout2/Settings.json | 9 ++ .../App/ui/layout2/layouts/Side1.json | 53 +++++++++++ .../App/ui/layout2/layouts/Side2.json | 49 ++++++++++ .../App/ui/layoutSet-new/Settings.json | 9 ++ .../App/ui/layoutSet-new/layouts/Side1.json | 13 +++ .../App/ui/layoutSet-new/layouts/Side2.json | 20 ++++ .../App/ui/layoutSet2/Settings.json | 9 ++ .../App/ui/layoutSet2/layouts/Side1.json | 54 +++++++++++ .../App/ui/layoutSet2/layouts/Side2.json | 49 ++++++++++ 31 files changed, 881 insertions(+), 94 deletions(-) create mode 100644 backend/src/Designer/EventHandlers/LayoutPageIdChanged/LayoutPageIdChangedLayoutsHandler.cs create mode 100644 backend/src/Designer/EventHandlers/LayoutSetIdChanged/LayoutSetIdChangedLayoutsHandler.cs create mode 100644 backend/src/Designer/Events/LayoutPageIdChangedEvent.cs create mode 100644 backend/src/Designer/Events/LayoutSetIdChangedEvent.cs create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout-sets.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side2-new.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side2.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/Settings.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side1.json create mode 100644 backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side2.json diff --git a/backend/src/Designer/Controllers/AppDevelopmentController.cs b/backend/src/Designer/Controllers/AppDevelopmentController.cs index 745fd9a2b4e..4b7d29b0d9f 100644 --- a/backend/src/Designer/Controllers/AppDevelopmentController.cs +++ b/backend/src/Designer/Controllers/AppDevelopmentController.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; @@ -124,24 +123,27 @@ public async Task SaveFormLayout(string org, string app, [FromQuer if (formLayoutPayload.ComponentIdsChange is not null && !string.IsNullOrEmpty(layoutSetName)) { - foreach (var componentIdChange in formLayoutPayload.ComponentIdsChange.Where((componentIdChange) => componentIdChange.OldComponentId != componentIdChange.NewComponentId)) + foreach (var componentIdChange in formLayoutPayload.ComponentIdsChange) { - if (componentIdChange.NewComponentId == null) + if (componentIdChange.OldComponentId != componentIdChange.NewComponentId) { - await _mediator.Publish(new ComponentDeletedEvent + if (componentIdChange.NewComponentId == null) { - ComponentId = componentIdChange.OldComponentId, + await _mediator.Publish(new ComponentDeletedEvent + { + ComponentId = componentIdChange.OldComponentId, + LayoutSetName = layoutSetName, + EditingContext = editingContext + }, cancellationToken); + } + await _mediator.Publish(new ComponentIdChangedEvent + { + OldComponentId = componentIdChange.OldComponentId, + NewComponentId = componentIdChange.NewComponentId, LayoutSetName = layoutSetName, EditingContext = editingContext }, cancellationToken); } - await _mediator.Publish(new ComponentIdChangedEvent - { - OldComponentId = componentIdChange.OldComponentId, - NewComponentId = componentIdChange.NewComponentId, - LayoutSetName = layoutSetName, - EditingContext = editingContext - }, cancellationToken); } } if (!formLayouts.ContainsKey(layoutName)) @@ -205,16 +207,24 @@ await _mediator.Publish(new LayoutPageDeletedEvent /// Application identifier which is unique within an organisation. /// Name of the layout set the specific layout belongs to /// The current name of the form layout + /// An that observes if operation is cancelled. /// A success message if the save was successful [HttpPost] [Route("form-layout-name/{layoutName}")] - public ActionResult UpdateFormLayoutName(string org, string app, [FromQuery] string layoutSetName, [FromRoute] string layoutName, [FromBody] string newName) + public async Task UpdateFormLayoutName(string org, string app, [FromQuery] string layoutSetName, [FromRoute] string layoutName, [FromBody] string newName, CancellationToken cancellationToken) { try { string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext); var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer); _appDevelopmentService.UpdateFormLayoutName(editingContext, layoutSetName, layoutName, newName); + await _mediator.Publish(new LayoutPageIdChangedEvent + { + EditingContext = editingContext, + LayoutSetName = layoutSetName, + LayoutName = layoutName, + NewLayoutName = newName, + }, cancellationToken); return Ok(); } catch (FileNotFoundException exception) @@ -405,6 +415,12 @@ public async Task UpdateLayoutSetName(string org, string app, [Fro string developer = AuthenticationHelper.GetDeveloperUserName(HttpContext); var editingContext = AltinnRepoEditingContext.FromOrgRepoDeveloper(org, app, developer); LayoutSets layoutSets = await _appDevelopmentService.UpdateLayoutSetName(editingContext, layoutSetIdToUpdate, newLayoutSetName, cancellationToken); + await _mediator.Publish(new LayoutSetIdChangedEvent + { + EditingContext = editingContext, + LayoutSetName = layoutSetIdToUpdate, + NewLayoutSetName = newLayoutSetName, + }, cancellationToken); return Ok(layoutSets); } diff --git a/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs index ecbfcc46d1e..2de41203bef 100644 --- a/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs +++ b/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs @@ -1,9 +1,11 @@ +using System.Collections.Generic; using System.Linq; using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; using Altinn.Studio.Designer.Events; using Altinn.Studio.Designer.Hubs.SyncHub; +using Altinn.Studio.Designer.Models; using Altinn.Studio.Designer.Services.Interfaces; using MediatR; @@ -13,6 +15,7 @@ public class ComponentIdChangedLayoutsHandler : INotificationHandler referencesToUpdate = [new Reference("component", notification.LayoutSetName, notification.OldComponentId, notification.NewComponentId)]; + hasChanges |= await _appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); + return hasChanges; }); } diff --git a/backend/src/Designer/EventHandlers/LayoutPageIdChanged/LayoutPageIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/LayoutPageIdChanged/LayoutPageIdChangedLayoutsHandler.cs new file mode 100644 index 00000000000..7772a125cf1 --- /dev/null +++ b/backend/src/Designer/EventHandlers/LayoutPageIdChanged/LayoutPageIdChangedLayoutsHandler.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Altinn.Studio.Designer.Events; +using Altinn.Studio.Designer.Hubs.SyncHub; +using Altinn.Studio.Designer.Models; +using Altinn.Studio.Designer.Services.Interfaces; +using MediatR; + +namespace Altinn.Studio.Designer.EventHandlers.LayoutPageDeleted; + +public class LayoutPageIdChangedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler +{ + public async Task Handle(LayoutPageIdChangedEvent notification, CancellationToken cancellationToken) + { + await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( + notification.EditingContext, + SyncErrorCodes.LayoutPageIdChangedLayoutsSyncError, + "layouts", + async () => + { + List referencesToUpdate = [new Reference("page", notification.LayoutSetName, notification.LayoutName, notification.NewLayoutName)]; + return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); + }); + } +} diff --git a/backend/src/Designer/EventHandlers/LayoutSetIdChanged/LayoutSetIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/LayoutSetIdChanged/LayoutSetIdChangedLayoutsHandler.cs new file mode 100644 index 00000000000..6502bd03b6e --- /dev/null +++ b/backend/src/Designer/EventHandlers/LayoutSetIdChanged/LayoutSetIdChangedLayoutsHandler.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Altinn.Studio.Designer.Events; +using Altinn.Studio.Designer.Hubs.SyncHub; +using Altinn.Studio.Designer.Models; +using Altinn.Studio.Designer.Services.Interfaces; +using MediatR; + +namespace Altinn.Studio.Designer.EventHandlers.LayoutSetDeleted; + +public class LayoutSetIdChangedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) : INotificationHandler +{ + public async Task Handle(LayoutSetIdChangedEvent notification, CancellationToken cancellationToken) + { + await fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( + notification.EditingContext, + SyncErrorCodes.LayoutSetIdChangedLayoutsSyncError, + "layouts", + async () => + { + List referencesToUpdate = [new Reference("layoutSet", notification.LayoutSetName, notification.LayoutSetName, notification.NewLayoutSetName)]; + return await appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); + }); + } +} diff --git a/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs index acee366380d..0b67fa7a885 100644 --- a/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs +++ b/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs @@ -1,10 +1,9 @@ -using System.IO; -using System.Linq; -using System.Text.Json.Nodes; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Altinn.Studio.Designer.Events; using Altinn.Studio.Designer.Hubs.SyncHub; +using Altinn.Studio.Designer.Models; using Altinn.Studio.Designer.Services.Interfaces; using MediatR; @@ -12,90 +11,25 @@ namespace Altinn.Studio.Designer.EventHandlers.ProcessTaskIdChanged; public class ProcessTaskIdChangedLayoutsHandler : INotificationHandler { - private readonly IAltinnGitRepositoryFactory _altinnGitRepositoryFactory; private readonly IFileSyncHandlerExecutor _fileSyncHandlerExecutor; + private readonly IAppDevelopmentService _appDevelopmentService; - public ProcessTaskIdChangedLayoutsHandler(IAltinnGitRepositoryFactory altinnGitRepositoryFactory, - IFileSyncHandlerExecutor fileSyncHandlerExecutor) + public ProcessTaskIdChangedLayoutsHandler(IFileSyncHandlerExecutor fileSyncHandlerExecutor, IAppDevelopmentService appDevelopmentService) { - _altinnGitRepositoryFactory = altinnGitRepositoryFactory; _fileSyncHandlerExecutor = fileSyncHandlerExecutor; + _appDevelopmentService = appDevelopmentService; } public async Task Handle(ProcessTaskIdChangedEvent notification, CancellationToken cancellationToken) { - var repository = _altinnGitRepositoryFactory.GetAltinnAppGitRepository( - notification.EditingContext.Org, - notification.EditingContext.Repo, - notification.EditingContext.Developer); - - if (!repository.AppUsesLayoutSets()) - { - return; - } - - var layoutSetsFile = await repository.GetLayoutSetsFile(cancellationToken); - - foreach (string layoutSetName in layoutSetsFile.Sets.Select(layoutSet => layoutSet.Id)) - { - string[] layoutNames; - try - { - layoutNames = repository.GetLayoutNames(layoutSetName); - } - catch (FileNotFoundException) + await _fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( + notification.EditingContext, + SyncErrorCodes.LayoutTaskIdSyncError, + "layouts", + async () => { - continue; - } - - await _fileSyncHandlerExecutor.ExecuteWithExceptionHandlingAndConditionalNotification( - notification.EditingContext, - SyncErrorCodes.LayoutTaskIdSyncError, - $"App/ui/{layoutSetName}/layouts", - async () => - { - bool hasChanged = false; - - foreach (string layoutName in layoutNames) - { - var layout = await repository.GetLayout(layoutSetName, layoutName, cancellationToken); - if (TryChangeLayoutTaskIds(layout, notification.OldId, notification.NewId)) - { - await repository.SaveLayout(layoutSetName, layoutName, layout, cancellationToken); - hasChanged = true; - } - } - - return hasChanged; - }); - } - } - - private static bool TryChangeLayoutTaskIds(JsonNode node, string oldId, string newId) - { - bool hasChanged = false; - - if (node is JsonObject jsonObject) - { - foreach (var property in jsonObject.ToList()) - { - if (property.Key == "taskId" && property.Value?.ToString() == oldId) - { - jsonObject["taskId"] = newId; - hasChanged = true; - } - - hasChanged |= TryChangeLayoutTaskIds(property.Value, oldId, newId); - } - } - else if (node is JsonArray jsonArray) - { - foreach (var element in jsonArray) - { - hasChanged |= TryChangeLayoutTaskIds(element, oldId, newId); - } - } - - return hasChanged; + List referencesToUpdate = [new Reference("task", null, notification.OldId, notification.NewId)]; + return await _appDevelopmentService.UpdateLayoutReferences(notification.EditingContext, referencesToUpdate, cancellationToken); + }); } } diff --git a/backend/src/Designer/Events/LayoutPageIdChangedEvent.cs b/backend/src/Designer/Events/LayoutPageIdChangedEvent.cs new file mode 100644 index 00000000000..4059f3ab287 --- /dev/null +++ b/backend/src/Designer/Events/LayoutPageIdChangedEvent.cs @@ -0,0 +1,12 @@ +using Altinn.Studio.Designer.Models; +using MediatR; + +namespace Altinn.Studio.Designer.Events; + +public class LayoutPageIdChangedEvent : INotification +{ + public AltinnRepoEditingContext EditingContext { get; set; } + public string LayoutSetName { get; set; } + public string LayoutName { get; set; } + public string NewLayoutName { get; set; } +} diff --git a/backend/src/Designer/Events/LayoutSetIdChangedEvent.cs b/backend/src/Designer/Events/LayoutSetIdChangedEvent.cs new file mode 100644 index 00000000000..1f327277588 --- /dev/null +++ b/backend/src/Designer/Events/LayoutSetIdChangedEvent.cs @@ -0,0 +1,11 @@ +using Altinn.Studio.Designer.Models; +using MediatR; + +namespace Altinn.Studio.Designer.Events; + +public class LayoutSetIdChangedEvent : INotification +{ + public AltinnRepoEditingContext EditingContext { get; set; } + public string LayoutSetName { get; set; } + public string NewLayoutSetName { get; set; } +} diff --git a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs index 04178d4eb7e..d4811e1a898 100644 --- a/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs +++ b/backend/src/Designer/Hubs/SyncHub/SyncErrorCodes.cs @@ -10,9 +10,11 @@ public static class SyncErrorCodes public const string LayoutSetsDataTypeSyncError = nameof(LayoutSetsDataTypeSyncError); public const string LayoutSetComponentIdSyncError = nameof(LayoutSetComponentIdSyncError); public const string LayoutSetDeletedLayoutsSyncError = nameof(LayoutSetDeletedLayoutsSyncError); + public const string LayoutSetIdChangedLayoutsSyncError = nameof(LayoutSetIdChangedLayoutsSyncError); public const string LayoutSetSubFormButtonSyncError = nameof(LayoutSetSubFormButtonSyncError); public const string SettingsComponentIdSyncError = nameof(SettingsComponentIdSyncError); public const string LayoutPageAddSyncError = nameof(LayoutPageAddSyncError); public const string ComponentDeletedLayoutsSyncError = nameof(ComponentDeletedLayoutsSyncError); public const string LayoutPageDeletedLayoutsSyncError = nameof(LayoutPageDeletedLayoutsSyncError); + public const string LayoutPageIdChangedLayoutsSyncError = nameof(LayoutPageIdChangedLayoutsSyncError); } diff --git a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs index 6b7cb76324e..169440d9287 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -612,11 +612,17 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp bool hasChanges = false; var deletedReferences = referencesToUpdate.Where(item => string.IsNullOrEmpty(item.NewId)).ToList(); + var updatedReferences = referencesToUpdate.Where(item => !string.IsNullOrEmpty(item.NewId)).ToList(); var deletedLayoutsSetIds = deletedReferences.Where(item => item.Type == "layoutSet").Select(item => item.Id).ToList(); var deletedLayouts = deletedReferences.Where(item => item.Type == "page").ToList(); var deletedComponents = deletedReferences.Where(item => item.Type == "component").ToList(); + var updatedTasks = updatedReferences.Where(item => item.Type == "task").ToList(); + var updatedLayoutsSets = updatedReferences.Where(item => item.Type == "layoutSet").ToList(); + var updatedLayouts = updatedReferences.Where(item => item.Type == "page").ToList(); + var updatedComponents = updatedReferences.Where(item => item.Type == "component").ToList(); + foreach (LayoutSetConfig layoutSet in layoutSets ?? [new() { Id = null }]) { bool isLayoutSetDeleted = deletedLayoutsSetIds.Contains(layoutSet.Id); @@ -636,6 +642,7 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp } var deletedComponentIdsFromCurrentLayoutSet = deletedComponents.Where(item => item.LayoutSetName == layoutSet.Id && string.IsNullOrEmpty(item.NewId)).Select(item => item.Id).ToList(); + var updatedComponentsFromCurrentLayoutSet = updatedComponents.Where(item => item.LayoutSetName == layoutSet.Id && !string.IsNullOrEmpty(item.NewId)).ToList(); if (data["layout"] is JsonArray componentList) { @@ -655,6 +662,15 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp componentList.RemoveAt(i); hasLayoutChanges = true; } + else + { + Reference updatedReference = updatedComponentsFromCurrentLayoutSet.FirstOrDefault(item => item.Id == componentId); + if (updatedReference != null) + { + component["id"] = updatedReference.NewId; + hasLayoutChanges = true; + } + } if (isLayoutSetDeleted || isLayoutDeleted || isComponentDeleted) { @@ -677,6 +693,15 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp componentList.RemoveAt(i); hasLayoutChanges = true; } + else + { + Reference updatedReference = updatedLayoutsSets.FirstOrDefault(item => item.Id == subformLayoutSet); + if (updatedReference != null) + { + component["layoutSet"] = updatedReference.NewId; + hasLayoutChanges = true; + } + } break; case "Summary2": if (component["target"] is JsonObject target) @@ -696,6 +721,34 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp componentList.RemoveAt(i); hasLayoutChanges = true; } + else + { + Reference updatedReference = null; + switch (type) + { + case "page": + updatedReference = updatedLayouts.FirstOrDefault(item => item.LayoutSetName == layoutSetId && item.Id == id); + break; + case "component": + updatedReference = updatedComponents.FirstOrDefault(item => item.LayoutSetName == layoutSetId && item.Id == id); + break; + } + if (updatedReference != null) + { + target["id"] = updatedReference.NewId; + hasLayoutChanges = true; + } + + if (!string.IsNullOrEmpty(taskId)) + { + updatedReference = updatedTasks.FirstOrDefault(item => item.Id == taskId); + if (updatedReference != null) + { + target["taskId"] = updatedReference.NewId; + hasLayoutChanges = true; + } + } + } if (component["overrides"] is JsonArray overrideList) { @@ -708,6 +761,15 @@ private async Task UpdateLayoutReferences(AltinnAppGitRepository altinnApp overrideList.RemoveAt(j); hasLayoutChanges = true; } + else + { + Reference updatedReference = updatedComponents.FirstOrDefault(item => item.LayoutSetName == layoutSetId && item.Id == overrideComponentId); + if (updatedReference != null) + { + overrideItem["componentId"] = updatedReference.NewId; + hasLayoutChanges = true; + } + } if (overrideList.Count == 0) { diff --git a/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs b/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs index 11e656b1ec0..de0541624ae 100644 --- a/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs +++ b/backend/src/Designer/Services/Interfaces/IAppDevelopmentService.cs @@ -218,8 +218,8 @@ public Task GetModelMetadata( /// Update layout references /// /// An . - /// The references to update. + /// The references to delete. /// An that observes if operation is cancelled. - public Task UpdateLayoutReferences(AltinnRepoEditingContext altinnRepoEditingContext, List referencesToUpdate, CancellationToken cancellationToken); + public Task UpdateLayoutReferences(AltinnRepoEditingContext altinnRepoEditingContext, List referencesToDelete, CancellationToken cancellationToken); } } diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs index 9244a74ddd9..0ad67ba963f 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs @@ -139,6 +139,49 @@ public async Task SaveFormLayoutWithDeletedComponent_DeletesAssociatedSummary2Co }); } + [Theory] + [InlineData("ttd", "testUser", "component", "Side2", "Input-Om7N3y", "Input-Om7N3y-new")] + public async Task SaveFormLayoutWithUpdatedComponentName_UpdatesAssociatedSummary2Components_ReturnsOk(string org, string developer, string layoutSetName, string layoutName, string componentId, string newComponentId) + { + string actualApp = "app-with-summary2-components"; + string app = TestDataHelper.GenerateTestRepoName(); + await CopyRepositoryForTest(org, actualApp, developer, app); + + string layout = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{layoutSetName}/layouts/{layoutName}.json"); + JsonNode layoutWithUpdatedComponent = JsonNode.Parse(layout); + + string url = $"{VersionPrefix(org, app)}/form-layout/{layoutName}?layoutSetName={layoutSetName}"; + var payload = new JsonObject + { + ["componentIdsChange"] = new JsonArray() { + new JsonObject + { + ["oldComponentId"] = componentId, + ["newComponentId"] = newComponentId, + } + }, + ["layout"] = layoutWithUpdatedComponent + }; + HttpResponseMessage response = await SendHttpRequest(url, payload); + response.StatusCode.Should().Be(HttpStatusCode.OK); + + string expectedApp = "app-with-summary2-components-after-updating-references"; + + string[] layoutPaths = [ + "component/layouts/Side1.json", + "component/layouts/Side2.json", + "component2/layouts/Side1.json", + "component2/layouts/Side2.json" + ]; + + layoutPaths.ToList().ForEach(file => + { + string actual = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{file}"); + string expected = TestDataHelper.GetFileFromRepo(org, expectedApp, developer, $"App/ui/{file}"); + JsonUtils.DeepEquals(actual, expected).Should().BeTrue(); + }); + } + [Theory] [InlineData("ttd", "app-with-layoutsets", "testUser", "testLayout", "layoutSet1", "TestData/App/ui/layoutWithUnknownProperties.json")] public async Task SaveFormLayoutWithNewPageLanguageUpdate_ReturnsOk(string org, string app, string developer, string layoutName, string layoutSetName, string layoutPath) diff --git a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs index 4f5ebe84218..f207d9da541 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/UpdateFormLayoutNameTests.cs @@ -71,5 +71,38 @@ public async Task UpdateFormLayoutName_NonExistingName_ShouldReturnNotFound(stri response.StatusCode.Should().Be(HttpStatusCode.NotFound); } + [Theory] + [InlineData("ttd", "testUser", "layout", "Side2", "Side2-new")] + public async Task UpdateFormLayoutName_UpdatesAssociatedSummary2Components_ReturnsOk(string org, string developer, string layoutSetName, string layoutName, string newLayoutName) + { + string actualApp = "app-with-summary2-components"; + string app = TestDataHelper.GenerateTestRepoName(); + await CopyRepositoryForTest(org, actualApp, developer, app); + + string url = $"{VersionPrefix(org, app)}/form-layout-name/{layoutName}?layoutSetName={layoutSetName}"; + using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, url) + { + Content = new StringContent($"\"{newLayoutName}\"", Encoding.UTF8, MediaTypeNames.Application.Json) + }; + + using var response = await HttpClient.SendAsync(httpRequestMessage); + response.StatusCode.Should().Be(HttpStatusCode.OK); + + string expectedApp = "app-with-summary2-components-after-updating-references"; + + string[] layoutPaths = [ + "layout/layouts/Side1.json", + "layout/layouts/Side2.json", + "layout2/layouts/Side1.json", + "layout2/layouts/Side2.json", + ]; + + layoutPaths.ToList().ForEach(file => + { + string actual = TestDataHelper.GetFileFromRepo(org, app, developer, $"App/ui/{file}"); + string expected = TestDataHelper.GetFileFromRepo(org, expectedApp, developer, $"App/ui/{file}"); + JsonUtils.DeepEquals(actual, expected).Should().BeTrue(); + }); + } } } diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side1.json new file mode 100644 index 00000000000..6345da9bdc3 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side1.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "" + }, + "id": "Summary2-9iG1lB", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "" + }, + "id": "Summary2-R8HsuB", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-mL8NjJ", + "type": "Summary2", + "overrides": [ + { + "componentId": "Input-Om7N3y-new", + "displayType": "string" + } + ] + }, + { + "target": { + "type": "component", + "id": "Input-qWr0oa", + "taskId": "" + }, + "id": "Summary2-0BV88Q", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-Om7N3y-new", + "taskId": "" + }, + "id": "Summary2-dTepe0", + "type": "Summary2" + }, + { + "id": "NavigationButtons-DfcNol", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side2.json new file mode 100644 index 00000000000..ec9bc398b4b --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component/layouts/Side2.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-Om7N3y-new", + "type": "Input" + }, + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-qWr0oa", + "type": "Input" + }, + { + "id": "NavigationButtons-GAW8Dx", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side1.json new file mode 100644 index 00000000000..8489464261c --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side1.json @@ -0,0 +1,56 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-LCr3oK", + "type": "Input" + }, + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "" + }, + "id": "Summary2-eoT5QK", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "" + }, + "id": "Summary2-NJfE92", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-BGHvph", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-LCr3oK", + "taskId": "" + }, + "id": "Summary2-rb2ml2", + "type": "Summary2" + }, + { + "id": "NavigationButtons-t7UTGJ", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side2.json new file mode 100644 index 00000000000..6fc08c2ad27 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/component2/layouts/Side2.json @@ -0,0 +1,64 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "component" + }, + "id": "Summary2-2FSqcf", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "component" + }, + "id": "Summary2-eGrDpP", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "component" + }, + "id": "Summary2-uJDgMu", + "type": "Summary2", + "overrides": [ + { + "componentId": "Input-Om7N3y-new", + "displayType": "string" + } + ] + }, + { + "target": { + "type": "component", + "id": "Input-qWr0oa", + "taskId": "component" + }, + "id": "Summary2-2JiT3P", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-Om7N3y-new", + "taskId": "component" + }, + "id": "Summary2-vIXkWO", + "type": "Summary2" + }, + { + "id": "NavigationButtons-BYcvaT", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout-sets.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout-sets.json new file mode 100644 index 00000000000..b28d6340c73 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout-sets.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout-sets.schema.v1.json", + "sets": [ + { + "id": "component", + "tasks": [ + "component" + ] + }, + { + "id": "layout", + "tasks": [ + "layout" + ] + }, + { + "id": "layoutSet-new", + "tasks": [ + "layoutSet-new" + ] + }, + { + "id": "component2", + "tasks": [ + "component2" + ] + }, + { + "id": "layout2", + "tasks": [ + "layout2" + ] + }, + { + "id": "layoutSet2", + "tasks": [ + "layoutSet2" + ] + } + ], + "uiSettings": {} +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/Settings.json new file mode 100644 index 00000000000..4668d52f882 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2-new" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side1.json new file mode 100644 index 00000000000..e9968cf6512 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side1.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "" + }, + "id": "Summary2-FEI1HC", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "" + }, + "id": "Summary2-e2yYpk", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2-new", + "taskId": "" + }, + "id": "Summary2-qOn2O1", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-AVRSNf", + "taskId": "" + }, + "id": "Summary2-da0Tq6", + "type": "Summary2" + }, + { + "id": "NavigationButtons-7g3XcW", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side2-new.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side2-new.json new file mode 100644 index 00000000000..8b8ea337e26 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout/layouts/Side2-new.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-AVRSNf", + "type": "Input" + }, + { + "id": "NavigationButtons-wDmNQu", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side1.json new file mode 100644 index 00000000000..2530921cc4e --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side1.json @@ -0,0 +1,53 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-QCSonu", + "type": "Input" + }, + { + "target": { + "type": "layoutSet", + "id": "" + }, + "id": "Summary2-18hFaH", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1" + }, + "id": "Summary2-iZJ80j", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-V55C6Q", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-QCSonu" + }, + "id": "Summary2-aI91Tv", + "type": "Summary2" + }, + { + "id": "NavigationButtons-2hGPi1", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side2.json new file mode 100644 index 00000000000..223f8377420 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layout2/layouts/Side2.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "layout" + }, + "id": "Summary2-MfRiX8", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "layout" + }, + "id": "Summary2-66YavC", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2-new", + "taskId": "layout" + }, + "id": "Summary2-bmqvUb", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-AVRSNf", + "taskId": "layout" + }, + "id": "Summary2-uuKXTD", + "type": "Summary2" + }, + { + "id": "NavigationButtons-h0g3Wt", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side1.json new file mode 100644 index 00000000000..48f8a1f9cf7 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side1.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "id": "NavigationButtons-n2jUp6", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side2.json new file mode 100644 index 00000000000..6fa6e9455ff --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet-new/layouts/Side2.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-hqcYqo", + "type": "Input" + }, + { + "id": "NavigationButtons-QzkEka", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/Settings.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/Settings.json new file mode 100644 index 00000000000..6bb44cf6db8 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/Settings.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://altinncdn.no/schemas/json/layout/layoutSettings.schema.v1.json", + "pages": { + "order": [ + "Side1", + "Side2" + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side1.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side1.json new file mode 100644 index 00000000000..60fc1029c15 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side1.json @@ -0,0 +1,54 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "dataModelBindings": { + "simpleBinding": "" + }, + "id": "Input-wrspcN", + "type": "Input" + }, + { + "target": { + "type": "layoutSet", + "id": "" + }, + "id": "Summary2-00SFBO", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1" + }, + "id": "Summary2-4069IB", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "" + }, + "id": "Summary2-Orxmu1", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-wrspcN", + "taskId": "" + }, + "id": "Summary2-2YoJGY", + "type": "Summary2" + }, + { + "id": "NavigationButtons-KnXA9y", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file diff --git a/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side2.json b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side2.json new file mode 100644 index 00000000000..b6351845ad5 --- /dev/null +++ b/backend/tests/Designer.Tests/_TestData/Repositories/testUser/ttd/app-with-summary2-components-after-updating-references/App/ui/layoutSet2/layouts/Side2.json @@ -0,0 +1,49 @@ +{ + "$schema": "https://altinncdn.no/toolkits/altinn-app-frontend/4/schemas/json/layout/layout.schema.v1.json", + "data": { + "layout": [ + { + "target": { + "type": "layoutSet", + "id": "", + "taskId": "layoutSet-new" + }, + "id": "Summary2-6VQ3LC", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side1", + "taskId": "layoutSet-new" + }, + "id": "Summary2-LZxPWb", + "type": "Summary2" + }, + { + "target": { + "type": "page", + "id": "Side2", + "taskId": "layoutSet-new" + }, + "id": "Summary2-El9z2Y", + "type": "Summary2" + }, + { + "target": { + "type": "component", + "id": "Input-hqcYqo", + "taskId": "layoutSet-new" + }, + "id": "Summary2-SMqpYV", + "type": "Summary2" + }, + { + "id": "NavigationButtons-5ukC2N", + "showBackButton": true, + "textResourceBindings": {}, + "type": "NavigationButtons" + } + ] + } +} \ No newline at end of file From 1dc9ccd970ae778047976e4fb53762747389c731 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Tue, 7 Jan 2025 17:00:54 +0100 Subject: [PATCH 23/25] Fix revert --- .../Controllers/AppDevelopmentController.cs | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/backend/src/Designer/Controllers/AppDevelopmentController.cs b/backend/src/Designer/Controllers/AppDevelopmentController.cs index 4b7d29b0d9f..71abc6d13f9 100644 --- a/backend/src/Designer/Controllers/AppDevelopmentController.cs +++ b/backend/src/Designer/Controllers/AppDevelopmentController.cs @@ -123,27 +123,24 @@ public async Task SaveFormLayout(string org, string app, [FromQuer if (formLayoutPayload.ComponentIdsChange is not null && !string.IsNullOrEmpty(layoutSetName)) { - foreach (var componentIdChange in formLayoutPayload.ComponentIdsChange) + foreach (var componentIdChange in formLayoutPayload.ComponentIdsChange.Where((componentIdChange) => componentIdChange.OldComponentId != componentIdChange.NewComponentId)) { - if (componentIdChange.OldComponentId != componentIdChange.NewComponentId) + if (componentIdChange.NewComponentId == null) { - if (componentIdChange.NewComponentId == null) + await _mediator.Publish(new ComponentDeletedEvent { - await _mediator.Publish(new ComponentDeletedEvent - { - ComponentId = componentIdChange.OldComponentId, - LayoutSetName = layoutSetName, - EditingContext = editingContext - }, cancellationToken); - } - await _mediator.Publish(new ComponentIdChangedEvent - { - OldComponentId = componentIdChange.OldComponentId, - NewComponentId = componentIdChange.NewComponentId, + ComponentId = componentIdChange.OldComponentId, LayoutSetName = layoutSetName, EditingContext = editingContext }, cancellationToken); } + await _mediator.Publish(new ComponentIdChangedEvent + { + OldComponentId = componentIdChange.OldComponentId, + NewComponentId = componentIdChange.NewComponentId, + LayoutSetName = layoutSetName, + EditingContext = editingContext + }, cancellationToken); } } if (!formLayouts.ContainsKey(layoutName)) From 6244138952a6c5b07c7121163897c32994cf2567 Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Tue, 7 Jan 2025 18:06:02 +0100 Subject: [PATCH 24/25] Add frontend warnings --- frontend/language/src/nb.json | 4 ++-- .../src/bpmnProviders/SupportedContextPadProvider.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/language/src/nb.json b/frontend/language/src/nb.json index 73a04014688..4efb041e37c 100644 --- a/frontend/language/src/nb.json +++ b/frontend/language/src/nb.json @@ -1177,7 +1177,7 @@ "ux_editor.component_category.select": "Flervalg", "ux_editor.component_category.text": "Tekst", "ux_editor.component_deletion_confirm": "Ja, slett komponenten", - "ux_editor.component_deletion_text": "Er du sikker på at du vil slette denne komponenten?", + "ux_editor.component_deletion_text": "Er du sikker på at du vil slette denne komponenten?\nAlle Summary2-komponenter knyttet til denne komponenten vil også bli slettet.", "ux_editor.component_dropdown_set_preselected": "Sett forhåndsvalgt verdi for nedtrekksliste", "ux_editor.component_group_deletion_text": "Er du sikker på at du vil slette denne gruppen?\nAlle komponenter i denne gruppen blir også slettet", "ux_editor.component_help_text.Accordion": "Med Trekkspilliste kan du presentere mye innhold på liten plass, i en eller flere rader. Brukerne kan klikke på hele raden for å vise eller skjule innholdet under.", @@ -1775,7 +1775,7 @@ "ux_editor.page_config_pdf_delete_existing_pdf": "Slett eksisterende PDF", "ux_editor.page_config_pdf_exclude_components_from_default_pdf": "Velg hvilke komponenter fra siden som skal skjules i standard PDF", "ux_editor.page_config_pdf_exclude_page_from_default_pdf": "Ekskluder siden fra standard PDF", - "ux_editor.page_delete_text": "Er du sikker på at du vil slette denne siden?\nAlt innholdet på siden vil bli fjernet.", + "ux_editor.page_delete_text": "Er du sikker på at du vil slette denne siden?\nAlt innholdet på siden vil bli fjernet.\nAlle Summary2-komponenter knyttet til denne siden vil også bli slettet.", "ux_editor.page_menu_down": "Flytt ned", "ux_editor.page_menu_edit": "Gi nytt navn", "ux_editor.page_menu_up": "Flytt opp", diff --git a/frontend/packages/process-editor/src/bpmnProviders/SupportedContextPadProvider.js b/frontend/packages/process-editor/src/bpmnProviders/SupportedContextPadProvider.js index 0971159f330..b124370dec0 100644 --- a/frontend/packages/process-editor/src/bpmnProviders/SupportedContextPadProvider.js +++ b/frontend/packages/process-editor/src/bpmnProviders/SupportedContextPadProvider.js @@ -16,7 +16,7 @@ class SupportedContextPadProvider { } const isConfirmed = confirm( - 'Prosess-steget du vil slette kan være knyttet til en sidegruppe. Den kan inneholde visningsoppsett eller skjema du har satt opp. Hvis du sletter steget, sletter du også hele sidegruppen og alt som hører til.', + 'Prosess-steget du vil slette kan være knyttet til en sidegruppe. Den kan inneholde visningsoppsett eller skjema du har satt opp. Hvis du sletter steget, sletter du også hele sidegruppen og alt som hører til.\nAlle Summary2-komponenter knyttet til dette prosess-steget vil også bli slettet.', ); if (isConfirmed) { From b15a35d6e0b04a0d8b5e95377183b3aebbe5afdd Mon Sep 17 00:00:00 2001 From: Michael Queyrichon Date: Tue, 7 Jan 2025 18:55:28 +0100 Subject: [PATCH 25/25] Fix error --- backend/src/Designer/Controllers/AppDevelopmentController.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/Designer/Controllers/AppDevelopmentController.cs b/backend/src/Designer/Controllers/AppDevelopmentController.cs index 71abc6d13f9..231c62540f6 100644 --- a/backend/src/Designer/Controllers/AppDevelopmentController.cs +++ b/backend/src/Designer/Controllers/AppDevelopmentController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks;