fix: Map correct collection ids for onPageLoad actions during import application (#11328)

* Introduce defaultCollectionId for onLayoutLoadAction

* Added TC for clone application

* ImportExportSpec & Dropdown resetSpec flaky fix

* Fix test failures

Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
This commit is contained in:
Abhijeet 2022-02-24 12:42:28 +05:30 committed by GitHub
parent 2ad121a092
commit 86c7c09982
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 240 additions and 391 deletions

View File

@ -20,274 +20,6 @@
"dynamicBindingPathList": [],
"leftColumn": 0,
"children": [
{
"widgetName": "Table1",
"defaultPageSize": 0,
"columnOrder": [
"id",
"gender",
"latitude",
"longitude",
"dob",
"phone",
"email",
"image",
"country",
"name"
],
"isVisibleDownload": true,
"dynamicPropertyPathList": [
{
"key": "tableData"
}
],
"displayName": "Table",
"iconSVG": "/static/media/icon.db8a9cbd.svg",
"topRow": 45,
"bottomRow": 86,
"isSortable": true,
"parentRowSpace": 10,
"type": "TABLE_WIDGET",
"defaultSelectedRow": "0",
"hideCard": false,
"animateLoading": true,
"parentColumnSpace": 33.375,
"dynamicTriggerPathList": [],
"dynamicBindingPathList": [
{
"key": "tableData"
},
{
"key": "primaryColumns.id.computedValue"
},
{
"key": "primaryColumns.gender.computedValue"
},
{
"key": "primaryColumns.latitude.computedValue"
},
{
"key": "primaryColumns.longitude.computedValue"
},
{
"key": "primaryColumns.dob.computedValue"
},
{
"key": "primaryColumns.phone.computedValue"
},
{
"key": "primaryColumns.email.computedValue"
},
{
"key": "primaryColumns.image.computedValue"
},
{
"key": "primaryColumns.country.computedValue"
},
{
"key": "primaryColumns.name.computedValue"
}
],
"leftColumn": 6,
"primaryColumns": {
"id": {
"index": 0,
"width": 150,
"id": "id",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellVisible": true,
"isDerived": false,
"label": "id",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.id))}}"
},
"gender": {
"index": 1,
"width": 150,
"id": "gender",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellVisible": true,
"isDerived": false,
"label": "gender",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.gender))}}"
},
"latitude": {
"index": 2,
"width": 150,
"id": "latitude",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellVisible": true,
"isDerived": false,
"label": "latitude",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.latitude))}}"
},
"longitude": {
"index": 3,
"width": 150,
"id": "longitude",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellVisible": true,
"isDerived": false,
"label": "longitude",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.longitude))}}"
},
"dob": {
"index": 4,
"width": 150,
"id": "dob",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellVisible": true,
"isDerived": false,
"label": "dob",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.dob))}}"
},
"phone": {
"index": 5,
"width": 150,
"id": "phone",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellVisible": true,
"isDerived": false,
"label": "phone",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.phone))}}"
},
"email": {
"index": 6,
"width": 150,
"id": "email",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellVisible": true,
"isDerived": false,
"label": "email",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.email))}}"
},
"image": {
"index": 7,
"width": 150,
"id": "image",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellVisible": true,
"isDerived": false,
"label": "image",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.image))}}"
},
"country": {
"index": 8,
"width": 150,
"id": "country",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellVisible": true,
"isDerived": false,
"label": "country",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.country))}}"
},
"name": {
"index": 9,
"width": 150,
"id": "name",
"horizontalAlignment": "LEFT",
"verticalAlignment": "CENTER",
"columnType": "text",
"textSize": "PARAGRAPH",
"enableFilter": true,
"enableSort": true,
"isVisible": true,
"isDisabled": false,
"isCellVisible": true,
"isDerived": false,
"label": "name",
"computedValue": "{{Table1.sanitizedTableData.map((currentRow) => ( currentRow.name))}}"
}
},
"delimiter": ",",
"key": "zwrlfvfuz3",
"derivedColumns": {},
"rightColumn": 46,
"textSize": "PARAGRAPH",
"widgetId": "52lm2cgbcq",
"isVisibleFilters": true,
"tableData": "{{GetAllUsers.data}}",
"isVisible": true,
"label": "Data",
"searchKey": "",
"enableClientSideSearch": true,
"version": 3,
"totalRecordsCount": 0,
"parentId": "0",
"renderMode": "CANVAS",
"isLoading": false,
"horizontalAlignment": "LEFT",
"isVisibleSearch": true,
"isVisiblePagination": true,
"verticalAlignment": "CENTER",
"columnSizeMap": {
"task": 245,
"step": 62,
"status": 75
}
},
{
"widgetName": "Select2",
"isFilterable": false,

View File

@ -1,3 +1,5 @@
/// <reference types="Cypress" />
const homePage = require("../../../locators/HomePage.json");
//const dsl = require("../../../fixtures/forkedApp.json");
@ -6,7 +8,7 @@ describe("Import, Export and Fork application and validate data binding", functi
let appid;
let newOrganizationName;
it("Import application and validate data on pageload", function() {
it("1. Import application and validate data on pageload", function() {
// import application
cy.get(homePage.homeIcon).click();
cy.get(homePage.optionsIcon)
@ -14,13 +16,19 @@ describe("Import, Export and Fork application and validate data binding", functi
.click();
cy.get(homePage.orgImportAppOption).click({ force: true });
cy.get(homePage.orgImportAppModal).should("be.visible");
cy.xpath(homePage.uploadLogo).attachFile("forkedApp.json");
cy.get(homePage.orgImportAppButton).click({ force: true });
cy.xpath(homePage.uploadLogo)
.attachFile("forkedApp.json")
.wait(500);
cy.get(homePage.orgImportAppButton)
.trigger("click")
.wait(500);
cy.get(homePage.orgImportAppModal).should("not.exist");
cy.wait("@importNewApplication").then((interception) => {
//let appId = interception.response.body.data.id;
// let defaultPage = interception.response.body.data.pages.find(
// (eachPage) => !!eachPage.isDefault,
// );
let appId = interception.response.body.data.id;
let defaultPage = interception.response.body.data.pages.find(
(eachPage) => !!eachPage.isDefault,
);
cy.get(homePage.toastMessage).should(
"contain",
@ -43,7 +51,7 @@ describe("Import, Export and Fork application and validate data binding", functi
});
});
it("Fork application and validate data binding for the widgets", function() {
it("2. Fork application and validate data binding for the widgets", function() {
// fork application
cy.get(homePage.homeIcon).click();
cy.get(homePage.searchInput).type(`${this.appname}`);
@ -69,7 +77,7 @@ describe("Import, Export and Fork application and validate data binding", functi
cy.xpath("//div[text()='Recusan']").should("be.visible");
});
it("Export and import application and validate data binding for the widgets", function() {
it("3. Export and import application and validate data binding for the widgets", function() {
cy.NavigateToHome();
cy.get(homePage.searchInput)
.clear()

View File

@ -8,6 +8,7 @@ describe("Dropdown Widget Check value does not reset on navigation", function()
it("check if the dropdown value does not change on navigation", function() {
//Change the value of drop down;
cy.wait(4000); //settling time for dsl into layout
cy.get(".t--draggable-selectwidget .bp3-popover-target")
.first()
.click();

View File

@ -19,6 +19,8 @@ public class DslActionDTO {
String id;
@JsonIgnore
String defaultActionId;
@JsonIgnore
String defaultCollectionId;
String name;
String collectionId;
Boolean clientSideExecution;

View File

@ -6,11 +6,14 @@ import com.appsmith.server.domains.NewAction;
import com.appsmith.server.domains.NewPage;
import com.appsmith.server.dtos.ActionCollectionDTO;
import com.appsmith.server.dtos.ActionDTO;
import com.appsmith.server.dtos.DslActionDTO;
import com.appsmith.server.dtos.PageDTO;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
public class DefaultResourcesUtils {
public static <T> T createDefaultIdsOrUpdateWithGivenResourceIds(T resource, String branchName) {
@ -61,10 +64,10 @@ public class DefaultResourcesUtils {
} else if (resource instanceof NewPage) {
NewPage page = (NewPage) resource;
DefaultResources pageDefaultResources = page.getDefaultResources();
boolean updateOnLoadActionTemp = false;
boolean updateOnLoadAction = false;
if (Optional.ofNullable(pageDefaultResources).isEmpty()) {
pageDefaultResources = new DefaultResources();
updateOnLoadActionTemp = true;
updateOnLoadAction = true;
}
final String defaultApplicationId = StringUtils.isEmpty(pageDefaultResources.getApplicationId())
@ -79,37 +82,10 @@ public class DefaultResourcesUtils {
pageDefaultResources.setBranchName(branchName);
// Copy layoutOnLoadAction Ids to defaultPageId
final boolean updateOnLoadAction = updateOnLoadActionTemp;
page.getUnpublishedPage()
.getLayouts()
.forEach(layout -> {
if (!CollectionUtils.isNullOrEmpty(layout.getLayoutOnLoadActions())) {
layout.getLayoutOnLoadActions()
.forEach(dslActionDTOS -> dslActionDTOS
.forEach(actionDTO -> {
if (updateOnLoadAction || StringUtils.isEmpty(actionDTO.getDefaultActionId())) {
actionDTO.setDefaultActionId(actionDTO.getId());
}
})
);
}
});
updateOnLoadActionAndCollectionIds(page.getUnpublishedPage(), updateOnLoadAction);
if (page.getPublishedPage() != null && !CollectionUtils.isNullOrEmpty(page.getPublishedPage().getLayouts())) {
page.getPublishedPage()
.getLayouts()
.forEach(layout -> {
if (!CollectionUtils.isNullOrEmpty(layout.getLayoutOnLoadActions())) {
layout.getLayoutOnLoadActions()
.forEach(dslActionDTOS -> dslActionDTOS
.forEach(actionDTO -> {
if (updateOnLoadAction || StringUtils.isEmpty(actionDTO.getDefaultActionId())) {
actionDTO.setDefaultActionId(actionDTO.getId());
}
})
);
}
});
updateOnLoadActionAndCollectionIds(page.getPublishedPage(), updateOnLoadAction);
}
page.setDefaultResources(pageDefaultResources);
} else if (resource instanceof ActionCollection) {
@ -165,4 +141,20 @@ public class DefaultResourcesUtils {
}
return resource;
}
static void updateOnLoadActionAndCollectionIds(PageDTO page, boolean shouldUpdate) {
page.getLayouts()
.forEach(layout -> {
if (!CollectionUtils.isNullOrEmpty(layout.getLayoutOnLoadActions())) {
for (Set<DslActionDTO> layoutOnLoadAction : layout.getLayoutOnLoadActions()) {
for (DslActionDTO dslActionDTO : layoutOnLoadAction) {
if (shouldUpdate || StringUtils.isEmpty(dslActionDTO.getDefaultActionId())) {
dslActionDTO.setDefaultActionId(dslActionDTO.getId());
dslActionDTO.setDefaultCollectionId(dslActionDTO.getCollectionId());
}
}
}
}
});
}
}

View File

@ -313,7 +313,10 @@ public class GitFileUtils {
TreeSet<DslActionDTO> sortedActions = new TreeSet<>(new CompareDslActionDTO());
sortedActions.addAll(layoutOnLoadActions.get(dslActionIndex));
sortedActions
.forEach(actionDTO -> actionDTO.setDefaultActionId(null));
.forEach(actionDTO -> {
actionDTO.setDefaultActionId(null);
actionDTO.setDefaultCollectionId(null);
});
layoutOnLoadActions.set(dslActionIndex, sortedActions);
}
}

View File

@ -50,15 +50,9 @@ public class ResponseUtils {
page.setId(defaultResourceIds.getPageId());
page.getLayouts()
.stream().filter(layout -> !CollectionUtils.isEmpty(layout.getLayoutOnLoadActions()))
.forEach(layout -> layout.getLayoutOnLoadActions()
.forEach(dslActionDTOS -> dslActionDTOS
.forEach(actionDTO -> {
if (!StringUtils.isEmpty(actionDTO.getDefaultActionId())) {
actionDTO.setId(actionDTO.getDefaultActionId());
}
}))
);
.stream()
.filter(layout -> !CollectionUtils.isEmpty(layout.getLayoutOnLoadActions()))
.forEach(layout -> this.updateLayoutWithDefaultResources(layout));
return page;
}
@ -151,6 +145,9 @@ public class ResponseUtils {
if (!StringUtils.isEmpty(onLoadAction.getDefaultActionId())) {
onLoadAction.setId(onLoadAction.getDefaultActionId());
}
if (!StringUtils.isEmpty(onLoadAction.getDefaultCollectionId())) {
onLoadAction.setCollectionId(onLoadAction.getDefaultCollectionId());
}
})
);
}
@ -164,6 +161,9 @@ public class ResponseUtils {
if (!StringUtils.isEmpty(onLoadAction.getDefaultActionId())) {
onLoadAction.setId(onLoadAction.getDefaultActionId());
}
if (!StringUtils.isEmpty(onLoadAction.getDefaultCollectionId())) {
onLoadAction.setCollectionId(onLoadAction.getDefaultCollectionId());
}
}));
}
return layout;

View File

@ -281,6 +281,8 @@ public class ExamplesOrganizationClonerCEImpl implements ExamplesOrganizationClo
// `clonedPages` list will also contain all pages cloned.
.collect(HashMap<String, String>::new, (map, tuple2) -> map.put(tuple2.getT2(), tuple2.getT1()))
.flatMap(actionIdsMap -> {
// Map of <originalCollectionId, clonedActionCollectionIds>
HashMap<String, String> collectionIdsMap = new HashMap<>();
// Pick all action collections
return actionCollectionService
.findByPageId(templatePageId)
@ -326,34 +328,35 @@ public class ExamplesOrganizationClonerCEImpl implements ExamplesOrganizationClo
unpublishedCollection.setDefaultToBranchedActionIdsMap(newActionIds);
return actionCollectionService.create(actionCollection)
.flatMap(newActionCollection -> {
if (StringUtils.isEmpty(newActionCollection.getDefaultResources().getCollectionId())) {
.flatMap(clonedActionCollection -> {
if (StringUtils.isEmpty(clonedActionCollection.getDefaultResources().getCollectionId())) {
ActionCollection updates = new ActionCollection();
DefaultResources defaultResources2 = newActionCollection.getDefaultResources();
defaultResources2.setCollectionId(newActionCollection.getId());
DefaultResources defaultResources2 = clonedActionCollection.getDefaultResources();
defaultResources2.setCollectionId(clonedActionCollection.getId());
updates.setDefaultResources(defaultResources2);
return actionCollectionService.update(newActionCollection.getId(), updates);
return actionCollectionService.update(clonedActionCollection.getId(), updates);
}
return Mono.just(newActionCollection);
return Mono.just(clonedActionCollection);
})
.flatMap(newlyCreatedActionCollection -> {
.flatMap(clonedActionCollection -> {
collectionIdsMap.put(originalCollectionId, clonedActionCollection.getId());
return Flux.fromIterable(newActionIds.values())
.flatMap(newActionService::findById)
.flatMap(newlyCreatedAction -> {
ActionDTO unpublishedAction = newlyCreatedAction.getUnpublishedAction();
unpublishedAction.setCollectionId(newlyCreatedActionCollection.getId());
unpublishedAction.getDefaultResources().setCollectionId(newlyCreatedActionCollection.getId());
unpublishedAction.setCollectionId(clonedActionCollection.getId());
unpublishedAction.getDefaultResources().setCollectionId(clonedActionCollection.getId());
return newActionService.update(newlyCreatedAction.getId(), newlyCreatedAction);
})
.collectList();
});
})
.collectList()
.thenReturn(actionIdsMap);
.then(Mono.zip(Mono.just(actionIdsMap), Mono.just(collectionIdsMap)));
});
});
})
.flatMap(actionIdsMap -> updateActionIdsInClonedPages(clonedPages, actionIdsMap))
.flatMap(tuple -> updateActionAndCollectionsIdsInClonedPages(clonedPages, tuple.getT1(), tuple.getT2()))
// Now publish all the example applications which have been cloned to ensure that there is a
// view mode for the newly created user.
.then(Mono.just(newApplicationIds))
@ -362,7 +365,9 @@ public class ExamplesOrganizationClonerCEImpl implements ExamplesOrganizationClo
.collectList();
}
private Flux<NewPage> updateActionIdsInClonedPages(List<NewPage> clonedPages, Map<String, String> actionIdsMap) {
private Flux<NewPage> updateActionAndCollectionsIdsInClonedPages(List<NewPage> clonedPages,
Map<String, String> actionIdsMap,
Map<String, String> actionCollectionIdsMap) {
final List<Mono<NewPage>> pageSaveMonos = new ArrayList<>();
for (final NewPage page : clonedPages) {
@ -376,7 +381,7 @@ public class ExamplesOrganizationClonerCEImpl implements ExamplesOrganizationClo
for (final Layout layout : page.getUnpublishedPage().getLayouts()) {
if (layout.getLayoutOnLoadActions() != null) {
shouldSave = updateOnLoadActionsWithNewActionIds(actionIdsMap, page.getId(), shouldSave, layout);
shouldSave = updateOnLoadActionsWithNewActionAndCollectionIds(actionIdsMap, actionCollectionIdsMap, page.getId(), shouldSave, layout);
}
}
@ -388,13 +393,22 @@ public class ExamplesOrganizationClonerCEImpl implements ExamplesOrganizationClo
return Flux.concat(pageSaveMonos);
}
private boolean updateOnLoadActionsWithNewActionIds(Map<String, String> actionIdsMap, String pageId, boolean shouldSave, Layout layout) {
private boolean updateOnLoadActionsWithNewActionAndCollectionIds(Map<String, String> actionIdsMap,
Map<String, String> collectionIdsMap,
String pageId,
boolean shouldSave,
Layout layout) {
for (final Set<DslActionDTO> actionSet : layout.getLayoutOnLoadActions()) {
for (final DslActionDTO actionDTO : actionSet) {
if (actionIdsMap.containsKey(actionDTO.getId())) {
final String srcActionId = actionDTO.getId();
final String srcCollectionId = actionDTO.getCollectionId();
actionDTO.setId(actionIdsMap.get(srcActionId));
actionDTO.setDefaultActionId(actionIdsMap.get(srcActionId));
if (StringUtils.hasLength(srcCollectionId)) {
actionDTO.setDefaultCollectionId(collectionIdsMap.get(actionDTO.getCollectionId()));
actionDTO.setCollectionId(collectionIdsMap.get(actionDTO.getCollectionId()));
}
shouldSave = true;
} else {
log.error(

View File

@ -545,10 +545,13 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
Map<String, String> datasourceMap = new HashMap<>();
Map<String, NewPage> pageNameMap = new HashMap<>();
Map<String, String> actionIdMap = new HashMap<>();
Map<String, Map<String, String>> unpublishedActionCollectionIdMap = new HashMap<>();
Map<String, Map<String, String>> publishedActionCollectionIdMap = new HashMap<>();
Map<String, String> unpublishedActionIdToCollectionIdMap = new HashMap<>();
Map<String, String> publishedActionIdToCollectionIdMap = new HashMap<>();
// Datastructures to create a link between collectionId to embedded action ids
Map<String, Map<String, String>> unpublishedCollectionIdToActionIdsMap = new HashMap<>();
Map<String, Map<String, String>> publishedCollectionIdToActionIdsMap = new HashMap<>();
// Datastructures to create a link between actionIds to collectionIds
// <actionId, [collectionId, defaultCollectionId]>
Map<String, List<String>> unpublishedActionIdToCollectionIdMap = new HashMap<>();
Map<String, List<String>> publishedActionIdToCollectionIdMap = new HashMap<>();
Application importedApplication = importedDoc.getExportedApplication();
List<Datasource> importedDatasourceList = importedDoc.getDatasourceList();
@ -911,8 +914,8 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
);
if (unpublishedAction.getCollectionId() != null) {
unpublishedActionCollectionIdMap.putIfAbsent(unpublishedAction.getCollectionId(), new HashMap<>());
final Map<String, String> actionIds = unpublishedActionCollectionIdMap.get(unpublishedAction.getCollectionId());
unpublishedCollectionIdToActionIdsMap.putIfAbsent(unpublishedAction.getCollectionId(), new HashMap<>());
final Map<String, String> actionIds = unpublishedCollectionIdToActionIdsMap.get(unpublishedAction.getCollectionId());
actionIds.put(newAction.getDefaultResources().getActionId(), newAction.getId());
}
}
@ -924,8 +927,8 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
);
if (publishedAction.getCollectionId() != null) {
publishedActionCollectionIdMap.putIfAbsent(publishedAction.getCollectionId(), new HashMap<>());
final Map<String, String> actionIds = publishedActionCollectionIdMap.get(publishedAction.getCollectionId());
publishedCollectionIdToActionIdsMap.putIfAbsent(publishedAction.getCollectionId(), new HashMap<>());
final Map<String, String> actionIds = publishedCollectionIdToActionIdsMap.get(publishedAction.getCollectionId());
actionIds.put(newAction.getDefaultResources().getActionId(), newAction.getId());
}
}
@ -957,13 +960,13 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
final String fallbackParentPageId = unpublishedCollection.getPageId();
if (unpublishedCollection.getName() != null) {
unpublishedCollection.setDefaultToBranchedActionIdsMap(unpublishedActionCollectionIdMap.get(importedActionCollectionId));
unpublishedCollection.setDefaultToBranchedActionIdsMap(unpublishedCollectionIdToActionIdsMap.get(importedActionCollectionId));
unpublishedCollection.setPluginId(pluginMap.get(unpublishedCollection.getPluginId()));
parentPage = updatePageInActionCollection(unpublishedCollection, pageNameMap);
}
if (publishedCollection != null && publishedCollection.getName() != null) {
publishedCollection.setDefaultToBranchedActionIdsMap(publishedActionCollectionIdMap.get(importedActionCollectionId));
publishedCollection.setDefaultToBranchedActionIdsMap(publishedCollectionIdToActionIdsMap.get(importedActionCollectionId));
publishedCollection.setPluginId(pluginMap.get(publishedCollection.getPluginId()));
if (StringUtils.isEmpty(publishedCollection.getPageId())) {
publishedCollection.setPageId(fallbackParentPageId);
@ -1036,15 +1039,17 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
.flatMap(tuple -> {
final String importedActionCollectionId = tuple.getT1();
final String savedActionCollectionId = tuple.getT2().getId();
unpublishedActionCollectionIdMap
final String defaultCollectionId = tuple.getT2().getDefaultResources().getCollectionId();
List<String> collectionIds = List.of(savedActionCollectionId, defaultCollectionId);
unpublishedCollectionIdToActionIdsMap
.getOrDefault(importedActionCollectionId, Map.of())
.forEach((defaultActionId, actionId) -> {
unpublishedActionIdToCollectionIdMap.put(actionId, savedActionCollectionId);
unpublishedActionIdToCollectionIdMap.putIfAbsent(actionId, collectionIds);
});
publishedActionCollectionIdMap
publishedCollectionIdToActionIdsMap
.getOrDefault(importedActionCollectionId, Map.of())
.forEach((defaultActionId, actionId) -> {
publishedActionIdToCollectionIdMap.put(actionId, savedActionCollectionId);
publishedActionIdToCollectionIdMap.putIfAbsent(actionId, collectionIds);
});
final HashSet<String> actionIds = new HashSet<>();
actionIds.addAll(unpublishedActionIdToCollectionIdMap.keySet());
@ -1053,10 +1058,34 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
})
.flatMap(actionId -> newActionRepository.findById(actionId, MANAGE_ACTIONS))
.map(newAction -> {
newAction.getUnpublishedAction().setCollectionId(
unpublishedActionIdToCollectionIdMap.getOrDefault(newAction.getId(), null));
newAction.getPublishedAction().setCollectionId(
publishedActionIdToCollectionIdMap.getOrDefault(newAction.getId(), null));
// Update collectionId and defaultCollectionIds in actionDTOs
ActionDTO unpublishedAction = newAction.getUnpublishedAction();
ActionDTO publishedAction = newAction.getPublishedAction();
if (!CollectionUtils.sizeIsEmpty(unpublishedActionIdToCollectionIdMap)
&& !CollectionUtils.isEmpty(unpublishedActionIdToCollectionIdMap.get(newAction.getId()))) {
unpublishedAction.setCollectionId(
unpublishedActionIdToCollectionIdMap.get(newAction.getId()).get(0)
);
if (unpublishedAction.getDefaultResources() != null
&& StringUtils.isEmpty(unpublishedAction.getDefaultResources().getCollectionId())) {
unpublishedAction.getDefaultResources().setCollectionId(
unpublishedActionIdToCollectionIdMap.get(newAction.getId()).get(1)
);
}
}
if (!CollectionUtils.sizeIsEmpty(publishedActionIdToCollectionIdMap)
&& !CollectionUtils.isEmpty(publishedActionIdToCollectionIdMap.get(newAction.getId()))) {
publishedAction.setCollectionId(
publishedActionIdToCollectionIdMap.get(newAction.getId()).get(0)
);
if (publishedAction.getDefaultResources() != null
&& StringUtils.isEmpty(publishedAction.getDefaultResources().getCollectionId())) {
publishedAction.getDefaultResources().setCollectionId(
publishedActionIdToCollectionIdMap.get(newAction.getId()).get(1));
}
}
return newAction;
})
.flatMap(newAction -> newActionService.update(newAction.getId(), newAction))
@ -1072,7 +1101,7 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
if (newPage.getDefaultResources() != null) {
newPage.getDefaultResources().setBranchName(branchName);
}
return mapActionIdWithPageLayout(newPage, actionIdMap)
return mapActionAndCollectionIdWithPageLayout(newPage, actionIdMap, unpublishedActionIdToCollectionIdMap, publishedActionIdToCollectionIdMap)
.flatMap(newPageService::save);
})
.then(applicationService.update(importedApplication.getId(), importedApplication))
@ -1312,7 +1341,10 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
}
// This method will update the action id in saved page for layoutOnLoadAction
private Mono<NewPage> mapActionIdWithPageLayout(NewPage page, Map<String, String> actionIdMap) {
private Mono<NewPage> mapActionAndCollectionIdWithPageLayout(NewPage page,
Map<String, String> actionIdMap,
Map<String, List<String>> unpublishedActionIdToCollectionIdsMap,
Map<String, List<String>> publishedActionIdToCollectionIdsMap) {
Set<String> layoutOnLoadActions = new HashSet<>();
if (page.getUnpublishedPage().getLayouts() != null) {
@ -1322,6 +1354,10 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
layout.getLayoutOnLoadActions().forEach(onLoadAction -> onLoadAction
.forEach(actionDTO -> {
actionDTO.setId(actionIdMap.get(actionDTO.getId()));
if (!CollectionUtils.sizeIsEmpty(unpublishedActionIdToCollectionIdsMap)
&& !CollectionUtils.isEmpty(unpublishedActionIdToCollectionIdsMap.get(actionDTO.getId()))) {
actionDTO.setCollectionId(unpublishedActionIdToCollectionIdsMap.get(actionDTO.getId()).get(0));
}
layoutOnLoadActions.add(actionDTO.getId());
}));
}
@ -1335,6 +1371,10 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
layout.getLayoutOnLoadActions().forEach(onLoadAction -> onLoadAction
.forEach(actionDTO -> {
actionDTO.setId(actionIdMap.get(actionDTO.getId()));
if (!CollectionUtils.sizeIsEmpty(publishedActionIdToCollectionIdsMap)
&& !CollectionUtils.isEmpty(publishedActionIdToCollectionIdsMap.get(actionDTO.getId()))) {
actionDTO.setCollectionId(publishedActionIdToCollectionIdsMap.get(actionDTO.getId()).get(0));
}
layoutOnLoadActions.add(actionDTO.getId());
}));
}
@ -1347,25 +1387,38 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
.map(newAction -> {
final String defaultActionId = newAction.getDefaultResources().getActionId();
if (page.getUnpublishedPage().getLayouts() != null) {
final String defaultCollectionId = newAction.getUnpublishedAction().getDefaultResources().getCollectionId();
page.getUnpublishedPage().getLayouts().forEach(layout -> {
if (layout.getLayoutOnLoadActions() != null) {
layout.getLayoutOnLoadActions().forEach(onLoadAction -> onLoadAction
.stream()
.filter(actionDTO -> StringUtils.equals(actionDTO.getId(), newAction.getId()))
.forEach(actionDTO -> actionDTO.setDefaultActionId(defaultActionId)));
layout.getLayoutOnLoadActions()
.forEach(onLoadAction -> onLoadAction
.stream()
.filter(actionDTO -> StringUtils.equals(actionDTO.getId(), newAction.getId()))
.forEach(actionDTO -> {
actionDTO.setDefaultActionId(defaultActionId);
actionDTO.setDefaultCollectionId(defaultCollectionId);
})
);
}
});
}
if (page.getPublishedPage() != null && page.getPublishedPage().getLayouts() != null) {
page.getPublishedPage().getLayouts().forEach(layout -> {
if (layout.getLayoutOnLoadActions() != null) {
layout.getLayoutOnLoadActions().forEach(onLoadAction -> onLoadAction
.stream()
.filter(actionDTO -> StringUtils.equals(actionDTO.getId(), newAction.getId()))
.forEach(actionDTO -> actionDTO.setDefaultActionId(defaultActionId)));
.forEach(actionDTO -> {
actionDTO.setDefaultActionId(defaultActionId);
if (newAction.getPublishedAction() != null
&& newAction.getPublishedAction().getDefaultResources() != null) {
actionDTO.setDefaultCollectionId(
newAction.getPublishedAction().getDefaultResources().getCollectionId()
);
}
})
);
}
});
}

View File

@ -518,7 +518,6 @@ public class PageLoadActionsUtilCEImpl implements PageLoadActionsUtilCE {
* Breadth First level by level traversal is used to compute each set of such independent actions.
*
* @param dag : The DAG graph containing all the edges representing dependencies between appsmith entities in the page.
* @param pageLoadActionSet
* @param onPageLoadActionSet
* @param actionNames : All the action names for the page
* @return
@ -995,6 +994,7 @@ public class PageLoadActionsUtilCEImpl implements PageLoadActionsUtilCE {
dslActionDTO.setClientSideExecution(actionDTO.getClientSideExecution());
if (actionDTO.getDefaultResources() != null) {
dslActionDTO.setDefaultActionId(actionDTO.getDefaultResources().getActionId());
dslActionDTO.setDefaultCollectionId(actionDTO.getDefaultResources().getCollectionId());
}
if (actionDTO.getActionConfiguration() != null) {

View File

@ -1207,6 +1207,14 @@ public class ApplicationServiceTest {
testWidget.put("testField", "{{ cloneActionTest.data }}");
children.add(testWidget);
JSONObject secondWidget = new JSONObject();
secondWidget.put("widgetName", "secondWidget");
temp = new JSONArray();
temp.addAll(List.of(new JSONObject(Map.of("key", "testField1"))));
secondWidget.put("dynamicBindingPathList", temp);
secondWidget.put("testField1", "{{ testCollection1.cloneActionCollection1.data }}");
children.add(secondWidget);
Layout layout = testPage.getLayouts().get(0);
layout.setDsl(parentDsl);
@ -1218,11 +1226,20 @@ public class ApplicationServiceTest {
actionCollectionDTO.setOrganizationId(application.getOrganizationId());
actionCollectionDTO.setPluginId(testPlugin.getId());
actionCollectionDTO.setVariables(List.of(new JSValue("test", "String", "test", true)));
actionCollectionDTO.setBody("collectionBody");
actionCollectionDTO.setBody("export default {\n" +
"\tgetData: async () => {\n" +
"\t\tconst data = await cloneActionTest.run();\n" +
"\t\treturn data;\n" +
"\t}\n" +
"}");
ActionDTO action1 = new ActionDTO();
action1.setName("cloneActionCollection1");
action1.setActionConfiguration(new ActionConfiguration());
action1.getActionConfiguration().setBody("mockBody");
action1.getActionConfiguration().setBody(
"async () => {\n" +
"\t\tconst data = await cloneActionTest.run();\n" +
"\t\treturn data;\n" +
"\t}");
actionCollectionDTO.setActions(List.of(action1));
actionCollectionDTO.setPluginType(PluginType.JS);
@ -1304,13 +1321,18 @@ public class ApplicationServiceTest {
newPage.getUnpublishedPage()
.getLayouts()
.forEach(layout ->
layout.getLayoutOnLoadActions().forEach(dslActionDTOS -> {
dslActionDTOS.forEach(actionDTO -> {
assertThat(actionDTO.getId()).isEqualTo(actionDTO.getDefaultActionId());
});
})
);
.forEach(layout -> {
assertThat(layout.getLayoutOnLoadActions()).hasSize(1);
layout.getLayoutOnLoadActions().forEach(dslActionDTOS -> {
assertThat(dslActionDTOS).hasSize(2);
dslActionDTOS.forEach(actionDTO -> {
assertThat(actionDTO.getId()).isEqualTo(actionDTO.getDefaultActionId());
if (StringUtils.hasLength(actionDTO.getCollectionId())) {
assertThat(actionDTO.getDefaultCollectionId()).isEqualTo(actionDTO.getCollectionId());
}
});
});
});
});
assertThat(actionList).hasSize(2);

View File

@ -195,23 +195,6 @@ public class ApplicationForkingServiceTests {
layoutActionService.createSingleAction(action).block();
ObjectMapper objectMapper = new ObjectMapper();
JSONObject parentDsl = new JSONObject(objectMapper.readValue(DEFAULT_PAGE_LAYOUT, new TypeReference<HashMap<String, Object>>() {
}));
ArrayList children = (ArrayList) parentDsl.get("children");
JSONObject testWidget = new JSONObject();
testWidget.put("widgetName", "firstWidget");
JSONArray temp = new JSONArray();
temp.addAll(List.of(new JSONObject(Map.of("key", "testField"))));
testWidget.put("dynamicBindingPathList", temp);
testWidget.put("testField", "{{ forkActionTest.data }}");
children.add(testWidget);
Layout layout = testPage.getLayouts().get(0);
layout.setDsl(parentDsl);
layoutActionService.updateLayout(testPage.getId(), layout.getId(), layout).block();
// Save actionCollection
ActionCollectionDTO actionCollectionDTO = new ActionCollectionDTO();
@ -221,16 +204,49 @@ public class ApplicationForkingServiceTests {
actionCollectionDTO.setOrganizationId(sourceOrganization.getId());
actionCollectionDTO.setPluginId(datasource.getPluginId());
actionCollectionDTO.setVariables(List.of(new JSValue("test", "String", "test", true)));
actionCollectionDTO.setBody("collectionBody");
actionCollectionDTO.setBody("export default {\n" +
"\tgetData: async () => {\n" +
"\t\tconst data = await forkActionTest.run();\n" +
"\t\treturn data;\n" +
"\t}\n" +
"}");
ActionDTO action1 = new ActionDTO();
action1.setName("forkTestAction1");
action1.setName("getData");
action1.setActionConfiguration(new ActionConfiguration());
action1.getActionConfiguration().setBody("mockBody");
action1.getActionConfiguration().setBody(
"async () => {\n" +
"\t\tconst data = await forkActionTest.run();\n" +
"\t\treturn data;\n" +
"\t}");
actionCollectionDTO.setActions(List.of(action1));
actionCollectionDTO.setPluginType(PluginType.JS);
layoutCollectionService.createCollection(actionCollectionDTO).block();
ObjectMapper objectMapper = new ObjectMapper();
JSONObject parentDsl = new JSONObject(objectMapper.readValue(DEFAULT_PAGE_LAYOUT, new TypeReference<HashMap<String, Object>>() {
}));
ArrayList children = (ArrayList) parentDsl.get("children");
JSONObject testWidget = new JSONObject();
testWidget.put("widgetName", "firstWidget");
JSONArray temp = new JSONArray();
temp.addAll(List.of(new JSONObject(Map.of("key", "testField", "key1", "testField1"))));
testWidget.put("dynamicBindingPathList", temp);
testWidget.put("testField", "{{ forkActionTest.data }}");
children.add(testWidget);
JSONObject secondWidget = new JSONObject();
secondWidget.put("widgetName", "secondWidget");
temp = new JSONArray();
temp.addAll(List.of(new JSONObject(Map.of("key", "testField1"))));
secondWidget.put("dynamicBindingPathList", temp);
secondWidget.put("testField1", "{{ testCollection1.getData.data }}");
children.add(secondWidget);
Layout layout = testPage.getLayouts().get(0);
layout.setDsl(parentDsl);
layoutActionService.updateLayout(testPage.getId(), layout.getId(), layout).block();
// Invite "usertest@usertest.com" with VIEW access, api_user will be the admin of sourceOrganization and we are
// controlling this with @FixMethodOrder(MethodSorters.NAME_ASCENDING) to run the TCs in a sequence.
// Running TC in a sequence is a bad practice for unit TCs but here we are testing the invite user and then fork
@ -312,12 +328,18 @@ public class ApplicationForkingServiceTests {
newPage.getUnpublishedPage()
.getLayouts()
.forEach(layout ->
.forEach(layout -> {
assertThat(layout.getLayoutOnLoadActions()).hasSize(1);
layout.getLayoutOnLoadActions().forEach(dslActionDTOS -> {
assertThat(dslActionDTOS).hasSize(2);
dslActionDTOS.forEach(actionDTO -> {
assertThat(actionDTO.getId()).isEqualTo(actionDTO.getDefaultActionId());
if (!StringUtils.isEmpty(actionDTO.getCollectionId())) {
assertThat(actionDTO.getCollectionId()).isEqualTo(actionDTO.getDefaultCollectionId());
}
});
})
});
}
);
});