diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ApplicationJson.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ApplicationJson.java index ad9987295ac..c08a97522ce 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ApplicationJson.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/ApplicationJson.java @@ -35,6 +35,10 @@ public class ApplicationJson { List pageList; + List pageOrder; + + List publishedPageOrder; + String publishedDefaultPageName; String unpublishedDefaultPageName; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ImportExportApplicationServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ImportExportApplicationServiceCEImpl.java index 0c65d00ad34..f0ccaa378af 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ImportExportApplicationServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ImportExportApplicationServiceCEImpl.java @@ -77,6 +77,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -233,6 +234,7 @@ public Mono exportApplicationById(String applicationId, Seriali // Refactor application to remove the ids final String organizationId = application.getOrganizationId(); List pageOrderList = application.getPages().stream().map(applicationPage -> applicationPage.getId()).collect(Collectors.toList()); + List publishedPageOrderList = application.getPublishedPages().stream().map(applicationPage -> applicationPage.getId()).collect(Collectors.toList()); removeUnwantedFieldsFromApplicationDuringExport(application); examplesOrganizationCloner.makePristine(application); applicationJson.setExportedApplication(application); @@ -244,9 +246,24 @@ public Mono exportApplicationById(String applicationId, Seriali return pageFlux .collectList() - // Maintain the page order while exporting the application + // Save the page order to json while exporting the application .flatMap(newPages -> { Collections.sort(newPages, Comparator.comparing(newPage -> pageOrderList.indexOf(newPage.getId()))); + List pageOrder = new ArrayList<>(); + for (NewPage page: newPages) { + pageOrder.add(page.getUnpublishedPage().getName()); + } + applicationJson.setPageOrder(pageOrder); + + List newPageList = newPages; + // When there is difference in number of pages between edit and view mode + newPageList = newPageList.stream().filter(newPage -> !Optional.ofNullable(newPage.getPublishedPage()).isEmpty()).collect(Collectors.toList()); + Collections.sort(newPageList, Comparator.comparing(newPage -> publishedPageOrderList.indexOf(newPage.getId()))); + pageOrder = new ArrayList<>(); + for (NewPage page: newPageList) { + pageOrder.add(page.getPublishedPage().getName()); + } + applicationJson.setPublishedPageOrder(pageOrder); return Mono.just(newPages); }) .flatMap(newPageList -> { @@ -306,7 +323,7 @@ public Mono exportApplicationById(String applicationId, Seriali Flux datasourceFlux = Boolean.TRUE.equals(application.getExportWithConfiguration()) ? datasourceRepository.findAllByOrganizationId(organizationId, AclPermission.READ_DATASOURCES) - : datasourceRepository.findAllByOrganizationId(organizationId, AclPermission.MANAGE_DATASOURCES); + : datasourceRepository.findAllByOrganizationId(organizationId, MANAGE_DATASOURCES); return datasourceFlux.collectList(); }) @@ -854,15 +871,17 @@ public Mono importApplicationInOrganization(String organizationId, existingPagesMono ).collectList() .map(newPageList -> { - // Check if the pages order match with json file - List pageOrderList = importedNewPageList.stream().map(newPage -> newPage.getUnpublishedPage().getName()).collect(Collectors.toList()); + // Sort the unPublished pages based on the json file order only + List pageOrderList; + if(Optional.ofNullable(applicationJson.getPageOrder()).isEmpty()) { + pageOrderList = importedNewPageList.stream().map(newPage -> newPage.getUnpublishedPage().getName()).collect(Collectors.toList()); + } else { + pageOrderList = applicationJson.getPageOrder(); + } Collections.sort(newPageList, Comparator.comparing(newPage -> pageOrderList.indexOf(newPage.getUnpublishedPage().getName()))); for (NewPage newPage : newPageList) { - ApplicationPage unpublishedAppPage = new ApplicationPage(); - ApplicationPage publishedAppPage = new ApplicationPage(); - if (newPage.getUnpublishedPage() != null && newPage.getUnpublishedPage().getName() != null) { unpublishedAppPage.setIsDefault( StringUtils.equals( @@ -875,6 +894,27 @@ public Mono importApplicationInOrganization(String organizationId, } pageNameMap.put(newPage.getUnpublishedPage().getName(), newPage); } + if (unpublishedAppPage.getId() != null && newPage.getUnpublishedPage().getDeletedAt() == null) { + applicationPages.get(PublishType.UNPUBLISHED).add(unpublishedAppPage); + } + } + + // Sort the published pages based on the json file order only + List publishedPageOrderList; + if(Optional.ofNullable(applicationJson.getPublishedPageOrder()).isEmpty()) { + publishedPageOrderList = importedNewPageList.stream() + .filter(newPage -> !Optional.ofNullable(newPage.getPublishedPage()).isEmpty()) + .map(newPage -> newPage.getPublishedPage().getName()).collect(Collectors.toList()); + } else { + publishedPageOrderList = applicationJson.getPublishedPageOrder(); + } + + // When there is difference in number of pages between edit and view mode + newPageList = newPageList.stream().filter(newPage -> !Optional.ofNullable(newPage.getPublishedPage()).isEmpty()).collect(Collectors.toList()); + Collections.sort(newPageList, + Comparator.comparing(newPage -> publishedPageOrderList.indexOf(newPage.getPublishedPage().getName()))); + for (NewPage newPage : newPageList) { + ApplicationPage publishedAppPage = new ApplicationPage(); if (newPage.getPublishedPage() != null && newPage.getPublishedPage().getName() != null) { publishedAppPage.setIsDefault( @@ -888,9 +928,7 @@ public Mono importApplicationInOrganization(String organizationId, } pageNameMap.put(newPage.getPublishedPage().getName(), newPage); } - if (unpublishedAppPage.getId() != null && newPage.getUnpublishedPage().getDeletedAt() == null) { - applicationPages.get(PublishType.UNPUBLISHED).add(unpublishedAppPage); - } + if (publishedAppPage.getId() != null && newPage.getPublishedPage().getDeletedAt() == null) { applicationPages.get(PublishType.PUBLISHED).add(publishedAppPage); } @@ -929,6 +967,7 @@ public Mono importApplicationInOrganization(String organizationId, }); }) .flatMap(applicationPageMap -> { + // set it based on the order for published and unublished pages importedApplication.setPages(applicationPageMap.get(PublishType.UNPUBLISHED)); importedApplication.setPublishedPages(applicationPageMap.get(PublishType.PUBLISHED)); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ImportExportApplicationServiceTests.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ImportExportApplicationServiceTests.java index 8f4362ce20d..0f720b5f205 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ImportExportApplicationServiceTests.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ImportExportApplicationServiceTests.java @@ -2336,12 +2336,12 @@ public void importApplication_datasourceWithSameNameAndPlugin_importedWithValidA @Test @WithUserDetails(value = "api_user") - public void exportAndImportApplication_withMultiplePages_PagesOrderIsMaintained() { + public void exportAndImportApplication_withMultiplePagesOrderSameInDeployAndEditMode_PagesOrderIsMaintainedInEditAndViewMode() { Organization newOrganization = new Organization(); newOrganization.setName("template-org-with-ds"); Application testApplication = new Application(); - testApplication.setName("exportApplication_withMultiplePages_PagesOrderIsMaintainedINExportedAppJson"); + testApplication.setName("exportAndImportApplication_withMultiplePagesOrderSameInDeployAndEditMode_PagesOrderIsMaintainedInEditAndViewMode"); testApplication.setExportWithConfiguration(true); testApplication = applicationPageService.createApplication(testApplication, orgId).block(); assert testApplication != null; @@ -2359,22 +2359,30 @@ public void exportAndImportApplication_withMultiplePages_PagesOrderIsMaintained( // Set order for the newly created pages applicationPageService.reorderPage(testApplication.getId(), page1.getId(), 0, null).block(); applicationPageService.reorderPage(testApplication.getId(), page2.getId(), 1, null).block(); + // Deploy the current application + applicationPageService.publish(testApplication.getId(), true).block(); Mono applicationJsonMono = importExportApplicationService.exportApplicationById(testApplication.getId(), ""); StepVerifier .create(applicationJsonMono) .assertNext(applicationJson -> { - List pageList = applicationJson.getPageList(); - assertThat(pageList.get(0).getUnpublishedPage().getName()).isEqualTo("123"); - assertThat(pageList.get(1).getUnpublishedPage().getName()).isEqualTo("abc"); - assertThat(pageList.get(2).getUnpublishedPage().getName()).isEqualTo("Page1"); + List pageList = applicationJson.getPageOrder(); + assertThat(pageList.get(0)).isEqualTo("123"); + assertThat(pageList.get(1)).isEqualTo("abc"); + assertThat(pageList.get(2)).isEqualTo("Page1"); + + List publishedPageList = applicationJson.getPublishedPageOrder(); + assertThat(publishedPageList.get(0)).isEqualTo("123"); + assertThat(publishedPageList.get(1)).isEqualTo("abc"); + assertThat(publishedPageList.get(2)).isEqualTo("Page1"); }) .verifyComplete(); ApplicationJson applicationJson = importExportApplicationService.exportApplicationById(testApplication.getId(), "").block(); Application application = importExportApplicationService.importApplicationInOrganization(orgId, applicationJson).block(); + // Get the unpublished pages and verify the order List pageDTOS = application.getPages(); Mono newPageMono1 = newPageService.findById(pageDTOS.get(0).getId(), MANAGE_PAGES); Mono newPageMono2 = newPageService.findById(pageDTOS.get(1).getId(), MANAGE_PAGES); @@ -2396,6 +2404,124 @@ public void exportAndImportApplication_withMultiplePages_PagesOrderIsMaintained( }) .verifyComplete(); + // Get the published pages + List publishedPageDTOs = application.getPublishedPages(); + Mono newPublishedPageMono1 = newPageService.findById(publishedPageDTOs.get(0).getId(), MANAGE_PAGES); + Mono newPublishedPageMono2 = newPageService.findById(publishedPageDTOs.get(1).getId(), MANAGE_PAGES); + Mono newPublishedPageMono3 = newPageService.findById(publishedPageDTOs.get(2).getId(), MANAGE_PAGES); + + StepVerifier + .create(Mono.zip(newPublishedPageMono1, newPublishedPageMono2, newPublishedPageMono3)) + .assertNext(objects -> { + NewPage newPage1 = objects.getT1(); + NewPage newPage2 = objects.getT2(); + NewPage newPage3 = objects.getT3(); + assertThat(newPage1.getPublishedPage().getName()).isEqualTo("123"); + assertThat(newPage2.getPublishedPage().getName()).isEqualTo("abc"); + assertThat(newPage3.getPublishedPage().getName()).isEqualTo("Page1"); + + assertThat(newPage1.getId()).isEqualTo(publishedPageDTOs.get(0).getId()); + assertThat(newPage2.getId()).isEqualTo(publishedPageDTOs.get(1).getId()); + assertThat(newPage3.getId()).isEqualTo(publishedPageDTOs.get(2).getId()); + }) + .verifyComplete(); + + } + + + @Test + @WithUserDetails(value = "api_user") + public void exportAndImportApplication_withMultiplePagesOrderDifferentInDeployAndEditMode_PagesOrderIsMaintainedInEditAndViewMode() { + Organization newOrganization = new Organization(); + newOrganization.setName("template-org-with-ds"); + + Application testApplication = new Application(); + testApplication.setName("exportAndImportApplication_withMultiplePagesOrderDifferentInDeployAndEditMode_PagesOrderIsMaintainedInEditAndViewMode"); + testApplication.setExportWithConfiguration(true); + testApplication = applicationPageService.createApplication(testApplication, orgId).block(); + assert testApplication != null; + + PageDTO testPage = new PageDTO(); + testPage.setName("123"); + testPage.setApplicationId(testApplication.getId()); + PageDTO page1 = applicationPageService.createPage(testPage).block(); + + testPage = new PageDTO(); + testPage.setName("abc"); + testPage.setApplicationId(testApplication.getId()); + PageDTO page2 = applicationPageService.createPage(testPage).block(); + + // Deploy the current application so that edit and view mode will have different page order + applicationPageService.publish(testApplication.getId(), true).block(); + + // Set order for the newly created pages + applicationPageService.reorderPage(testApplication.getId(), page1.getId(), 0, null).block(); + applicationPageService.reorderPage(testApplication.getId(), page2.getId(), 1, null).block(); + + Mono applicationJsonMono = importExportApplicationService.exportApplicationById(testApplication.getId(), ""); + + StepVerifier + .create(applicationJsonMono) + .assertNext(applicationJson -> { + List pageList = applicationJson.getPageOrder(); + assertThat(pageList.get(0)).isEqualTo("123"); + assertThat(pageList.get(1)).isEqualTo("abc"); + assertThat(pageList.get(2)).isEqualTo("Page1"); + + List publishedPageOrder = applicationJson.getPageOrder(); + assertThat(publishedPageOrder.get(0)).isEqualTo("123"); + assertThat(publishedPageOrder.get(1)).isEqualTo("abc"); + assertThat(publishedPageOrder.get(2)).isEqualTo("Page1"); + }) + .verifyComplete(); + + ApplicationJson applicationJson = importExportApplicationService.exportApplicationById(testApplication.getId(), "").block(); + Application application = importExportApplicationService.importApplicationInOrganization(orgId, applicationJson).block(); + + // Get the unpublished pages and verify the order + List pageDTOS = application.getPages(); + Mono newPageMono1 = newPageService.findById(pageDTOS.get(0).getId(), MANAGE_PAGES); + Mono newPageMono2 = newPageService.findById(pageDTOS.get(1).getId(), MANAGE_PAGES); + Mono newPageMono3 = newPageService.findById(pageDTOS.get(2).getId(), MANAGE_PAGES); + + StepVerifier + .create(Mono.zip(newPageMono1, newPageMono2, newPageMono3)) + .assertNext(objects -> { + NewPage newPage1 = objects.getT1(); + NewPage newPage2 = objects.getT2(); + NewPage newPage3 = objects.getT3(); + assertThat(newPage1.getUnpublishedPage().getName()).isEqualTo("123"); + assertThat(newPage2.getUnpublishedPage().getName()).isEqualTo("abc"); + assertThat(newPage3.getUnpublishedPage().getName()).isEqualTo("Page1"); + + assertThat(newPage1.getId()).isEqualTo(pageDTOS.get(0).getId()); + assertThat(newPage2.getId()).isEqualTo(pageDTOS.get(1).getId()); + assertThat(newPage3.getId()).isEqualTo(pageDTOS.get(2).getId()); + }) + .verifyComplete(); + + // Get the published pages + List publishedPageDTOs = application.getPublishedPages(); + Mono newPublishedPageMono1 = newPageService.findById(publishedPageDTOs.get(0).getId(), MANAGE_PAGES); + Mono newPublishedPageMono2 = newPageService.findById(publishedPageDTOs.get(1).getId(), MANAGE_PAGES); + Mono newPublishedPageMono3 = newPageService.findById(publishedPageDTOs.get(2).getId(), MANAGE_PAGES); + + StepVerifier + .create(Mono.zip(newPublishedPageMono1, newPublishedPageMono2, newPublishedPageMono3)) + .assertNext(objects -> { + NewPage newPage1 = objects.getT1(); + NewPage newPage2 = objects.getT2(); + NewPage newPage3 = objects.getT3(); + assertThat(newPage1.getPublishedPage().getName()).isEqualTo("Page1"); + assertThat(newPage2.getPublishedPage().getName()).isEqualTo("123"); + assertThat(newPage3.getPublishedPage().getName()).isEqualTo("abc"); + + assertThat(newPage1.getId()).isEqualTo(publishedPageDTOs.get(0).getId()); + assertThat(newPage2.getId()).isEqualTo(publishedPageDTOs.get(1).getId()); + assertThat(newPage3.getId()).isEqualTo(publishedPageDTOs.get(2).getId()); + }) + .verifyComplete(); + } } diff --git a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/invalid-application-without-pageId-action-collection.json b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/invalid-application-without-pageId-action-collection.json index 358adbad517..5b4e5d99090 100644 --- a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/invalid-application-without-pageId-action-collection.json +++ b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/invalid-application-without-pageId-action-collection.json @@ -380,6 +380,10 @@ "new": true } ], + "pageOrder": [ + "Page1", + "Page2" + ], "actionList": [ { "id": "60aca092136c4b7178f6790a", diff --git a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-custom-themes.json b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-custom-themes.json index 092bc8846e4..82793f2fcb1 100644 --- a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-custom-themes.json +++ b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-custom-themes.json @@ -421,6 +421,10 @@ "new": true } ], + "pageOrder": [ + "Page1", + "Page2" + ], "actionList": [ { "id": "60aca092136c4b7178f6790a", diff --git a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-page-added.json b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-page-added.json index 5cfdc8aa667..fc9e101e938 100644 --- a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-page-added.json +++ b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-page-added.json @@ -541,6 +541,11 @@ "new": true } ], + "pageOrder": [ + "Page1", + "Page2", + "Page3" + ], "publishedDefaultPageName": "Page1", "unpublishedDefaultPageName": "Page1", "actionList": [ diff --git a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-page-removed.json b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-page-removed.json index 35911046365..a7f76d16ab6 100644 --- a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-page-removed.json +++ b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-page-removed.json @@ -253,6 +253,9 @@ "new": true } ], + "pageOrder": [ + "importedPage" + ], "publishedDefaultPageName": "importedPage", "unpublishedDefaultPageName": "importedPage", "actionList": [], diff --git a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-un-configured-datasource.json b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-un-configured-datasource.json index ac8f1c1e1f9..22b4d4f04df 100644 --- a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-un-configured-datasource.json +++ b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-with-un-configured-datasource.json @@ -280,6 +280,9 @@ "new": true } ], + "pageOrder": [ + "Page1" + ], "publishedDefaultPageName": "Page1", "unpublishedDefaultPageName": "Page1", "actionList": [ diff --git a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-without-action-collection.json b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-without-action-collection.json index 7b9f5fe6621..df53c8f2ba7 100644 --- a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-without-action-collection.json +++ b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-without-action-collection.json @@ -421,6 +421,10 @@ "new": true } ], + "pageOrder": [ + "Page1", + "Page2" + ], "actionList": [ { "id": "60aca092136c4b7178f6790a", diff --git a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-without-theme.json b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-without-theme.json index 42705c64e83..d36510772b7 100644 --- a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-without-theme.json +++ b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application-without-theme.json @@ -421,6 +421,10 @@ "new": true } ], + "pageOrder": [ + "Page1", + "Page2" + ], "actionList": [ { "id": "60aca092136c4b7178f6790a", diff --git a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application.json b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application.json index fbfe7109a41..92bb277ccae 100644 --- a/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application.json +++ b/app/server/appsmith-server/src/test/resources/test_assets/ImportExportServiceTest/valid-application.json @@ -421,6 +421,10 @@ "new": true } ], + "pageOrder": [ + "Page1", + "Page2" + ], "actionList": [ { "id": "60aca092136c4b7178f6790a",