diff --git a/backend/src/Designer/Controllers/AppDevelopmentController.cs b/backend/src/Designer/Controllers/AppDevelopmentController.cs index 5f8d9e884ca..f64e8bd0fa6 100644 --- a/backend/src/Designer/Controllers/AppDevelopmentController.cs +++ b/backend/src/Designer/Controllers/AppDevelopmentController.cs @@ -201,16 +201,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) @@ -401,6 +409,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/Enums/ReferenceType.cs b/backend/src/Designer/Enums/ReferenceType.cs index e53ab497980..7541125cd9c 100644 --- a/backend/src/Designer/Enums/ReferenceType.cs +++ b/backend/src/Designer/Enums/ReferenceType.cs @@ -2,6 +2,7 @@ namespace Altinn.Studio.Designer.Enums { public enum ReferenceType { + Task, LayoutSet, Layout, Component diff --git a/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs b/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs index df9923093fa..ced8819ee79 100644 --- a/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs +++ b/backend/src/Designer/EventHandlers/ComponentIdChanged/ComponentIdChangedLayoutsHandler.cs @@ -1,9 +1,12 @@ +using System.Collections.Generic; using System.Linq; using System.Text.Json.Nodes; using System.Threading; using System.Threading.Tasks; +using Altinn.Studio.Designer.Enums; 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 +16,15 @@ public class ComponentIdChangedLayoutsHandler : INotificationHandler referencesToUpdate = [new Reference(ReferenceType.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..df70615909f --- /dev/null +++ b/backend/src/Designer/EventHandlers/LayoutPageIdChanged/LayoutPageIdChangedLayoutsHandler.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Altinn.Studio.Designer.Enums; +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.LayoutPageIdChanged; + +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(ReferenceType.Layout, 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..6b97f2f09c5 --- /dev/null +++ b/backend/src/Designer/EventHandlers/LayoutSetIdChanged/LayoutSetIdChangedLayoutsHandler.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Altinn.Studio.Designer.Enums; +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.LayoutSetIdChanged; + +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(ReferenceType.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..5df931634b8 100644 --- a/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs +++ b/backend/src/Designer/EventHandlers/ProcessTaskIdChanged/ProcessTaskIdChangedLayoutsHandler.cs @@ -1,10 +1,10 @@ -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.Enums; 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 +12,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(ReferenceType.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 4d0bd99c357..065d53c7978 100644 --- a/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs +++ b/backend/src/Designer/Services/Implementation/AppDevelopmentService.cs @@ -613,11 +613,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 == ReferenceType.LayoutSet).Select(item => item.Id).ToList(); var deletedLayouts = deletedReferences.Where(item => item.Type == ReferenceType.Layout).ToList(); var deletedComponents = deletedReferences.Where(item => item.Type == ReferenceType.Component).ToList(); + var updatedTasks = updatedReferences.Where(item => item.Type == ReferenceType.Task).ToList(); + var updatedLayoutsSets = updatedReferences.Where(item => item.Type == ReferenceType.LayoutSet).ToList(); + var updatedLayouts = updatedReferences.Where(item => item.Type == ReferenceType.Layout).ToList(); + var updatedComponents = updatedReferences.Where(item => item.Type == ReferenceType.Component).ToList(); + foreach (LayoutSetConfig layoutSet in layoutSets ?? [new() { Id = null }]) { bool isLayoutSetDeleted = deletedLayoutsSetIds.Contains(layoutSet.Id); @@ -637,6 +643,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) { @@ -661,6 +668,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) { @@ -683,6 +699,16 @@ 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) @@ -702,6 +728,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) { @@ -714,6 +768,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/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs index ae9ee078025..48bfbc7e934 100644 --- a/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs +++ b/backend/tests/Designer.Tests/Controllers/AppDevelopmentController/SaveFormLayoutTests.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using System.Net; using System.Net.Http; @@ -138,6 +137,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); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + 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}"); + Assert.True(JsonUtils.DeepEquals(actual, expected)); + }); + } + [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 b9bee6abc81..bf97ad9f7e9 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; @@ -7,6 +8,7 @@ using Designer.Tests.Controllers.ApiTests; using Designer.Tests.Utils; using Microsoft.AspNetCore.Mvc.Testing; +using SharedResources.Tests; using Xunit; namespace Designer.Tests.Controllers.AppDevelopmentController @@ -68,5 +70,38 @@ public async Task UpdateFormLayoutName_NonExistingName_ShouldReturnNotFound(stri Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } + [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); + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + + 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}"); + Assert.True(JsonUtils.DeepEquals(actual, expected)); + }); + } } } 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