diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/AnalyticsEvents.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/AnalyticsEvents.java index 07e64f3a67..744496623c 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/AnalyticsEvents.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/constants/AnalyticsEvents.java @@ -84,7 +84,9 @@ public enum AnalyticsEvents { DS_TEST_EVENT_FAILED("Test_Datasource_Failed"), GIT_STALE_FILE_LOCK_DELETED, - SERVER_SETUP_COMPLETE("server_setup_complete"); + SERVER_SETUP_COMPLETE("server_setup_complete"), + + PARTIAL_IMPORT; private final String eventName; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ApplicationController.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ApplicationController.java index dea331d246..869f43d058 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ApplicationController.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ApplicationController.java @@ -6,6 +6,7 @@ import com.appsmith.server.exports.internal.ExportApplicationService; import com.appsmith.server.exports.internal.PartialExportService; import com.appsmith.server.fork.internal.ApplicationForkingService; import com.appsmith.server.imports.internal.ImportApplicationService; +import com.appsmith.server.imports.internal.PartialImportService; import com.appsmith.server.services.ApplicationPageService; import com.appsmith.server.services.ApplicationService; import com.appsmith.server.services.ApplicationSnapshotService; @@ -27,7 +28,8 @@ public class ApplicationController extends ApplicationControllerCE { ExportApplicationService exportApplicationService, ThemeService themeService, ApplicationSnapshotService applicationSnapshotService, - PartialExportService partialExportService) { + PartialExportService partialExportService, + PartialImportService partialImportService) { super( service, applicationPageService, @@ -37,6 +39,7 @@ public class ApplicationController extends ApplicationControllerCE { exportApplicationService, themeService, applicationSnapshotService, - partialExportService); + partialExportService, + partialImportService); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationControllerCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationControllerCE.java index 9d737b49c2..40706829c7 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationControllerCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/ApplicationControllerCE.java @@ -12,6 +12,7 @@ import com.appsmith.server.dtos.ApplicationAccessDTO; import com.appsmith.server.dtos.ApplicationImportDTO; import com.appsmith.server.dtos.ApplicationPagesDTO; import com.appsmith.server.dtos.GitAuthDTO; +import com.appsmith.server.dtos.PartialExportFileDTO; import com.appsmith.server.dtos.ReleaseItemsDTO; import com.appsmith.server.dtos.ResponseDTO; import com.appsmith.server.dtos.UserHomepageDTO; @@ -21,6 +22,7 @@ import com.appsmith.server.exports.internal.ExportApplicationService; import com.appsmith.server.exports.internal.PartialExportService; import com.appsmith.server.fork.internal.ApplicationForkingService; import com.appsmith.server.imports.internal.ImportApplicationService; +import com.appsmith.server.imports.internal.PartialImportService; import com.appsmith.server.services.ApplicationPageService; import com.appsmith.server.services.ApplicationService; import com.appsmith.server.services.ApplicationSnapshotService; @@ -64,8 +66,8 @@ public class ApplicationControllerCE extends BaseController> exportApplicationPartially( @PathVariable String applicationId, @PathVariable String pageId, @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName, - @RequestBody MultiValueMap params, - @RequestBody String widgets) { + @Valid @RequestBody PartialExportFileDTO fileDTO) { // params - contains ids of jsLib, actions and datasourceIds to be exported return partialExportService - .getPartialExportResources(applicationId, pageId, branchName, params, widgets) + .getPartialExportResources(applicationId, pageId, branchName, fileDTO) .map(fetchedResource -> { HttpHeaders responseHeaders = fetchedResource.getHttpHeaders(); Object applicationResource = fetchedResource.getApplicationResource(); return new ResponseEntity<>(applicationResource, responseHeaders, HttpStatus.OK); }); } + + @JsonView(Views.Public.class) + @PostMapping( + value = "/import/partial/{workspaceId}/{applicationId}", + consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public Mono> importApplicationPartially( + @RequestPart("file") Mono fileMono, + @PathVariable String workspaceId, + @PathVariable String applicationId, + @RequestParam String pageId, + @RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) { + return fileMono.flatMap(fileData -> partialImportService.importResourceInPage( + workspaceId, applicationId, pageId, branchName, fileData)) + .map(fetchedResource -> new ResponseDTO<>(HttpStatus.OK.value(), fetchedResource, null)); + } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PartialExportFileDTO.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PartialExportFileDTO.java new file mode 100644 index 0000000000..c5f8997298 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/dtos/PartialExportFileDTO.java @@ -0,0 +1,20 @@ +package com.appsmith.server.dtos; + +import lombok.Data; + +import java.util.ArrayList; +import java.util.List; + +@Data +public class PartialExportFileDTO { + + List actionList = new ArrayList<>(); + + List actionCollectionList = new ArrayList<>(); + + List customJsLib = new ArrayList<>(); + + List datasourceList = new ArrayList<>(); + + String widget = ""; +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/exports/internal/PartialExportServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/exports/internal/PartialExportServiceCE.java index 44c109f231..8e521d7fdc 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/exports/internal/PartialExportServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/exports/internal/PartialExportServiceCE.java @@ -1,14 +1,10 @@ package com.appsmith.server.exports.internal; import com.appsmith.server.dtos.ExportFileDTO; -import org.springframework.util.MultiValueMap; +import com.appsmith.server.dtos.PartialExportFileDTO; import reactor.core.publisher.Mono; public interface PartialExportServiceCE { Mono getPartialExportResources( - String applicationId, - String pageId, - String branchName, - MultiValueMap params, - String widgets); + String applicationId, String pageId, String branchName, PartialExportFileDTO partialExportFileDTO); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/exports/internal/PartialExportServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/exports/internal/PartialExportServiceCEImpl.java index 640dba8e36..4db0321608 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/exports/internal/PartialExportServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/exports/internal/PartialExportServiceCEImpl.java @@ -15,6 +15,7 @@ import com.appsmith.server.dtos.ApplicationJson; import com.appsmith.server.dtos.ExportFileDTO; import com.appsmith.server.dtos.ExportingMetaDTO; import com.appsmith.server.dtos.MappedExportableResourcesDTO; +import com.appsmith.server.dtos.PartialExportFileDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.exports.exportable.ExportableService; @@ -31,12 +32,10 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.http.ContentDisposition; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; -import org.springframework.util.MultiValueMap; import reactor.core.publisher.Mono; import java.nio.charset.StandardCharsets; import java.util.List; -import java.util.Set; import java.util.stream.Collectors; import static com.appsmith.server.constants.ResourceModes.EDIT; @@ -60,11 +59,7 @@ public class PartialExportServiceCEImpl implements PartialExportServiceCE { @Override public Mono getPartialExportResources( - String applicationId, - String pageId, - String branchName, - MultiValueMap params, - String widgets) { + String applicationId, String pageId, String branchName, PartialExportFileDTO partialExportFileDTO) { /* * Params has ids for actions, customJsLibs and datasource * Export the resources based on the value of these entities @@ -96,21 +91,25 @@ public class PartialExportServiceCEImpl implements PartialExportServiceCE { return applicationMono .flatMap(application -> { applicationJson.setExportedApplication(application); - return pluginExportableService.getExportableEntities( - exportingMetaDTO, mappedResourcesDTO, applicationMono, applicationJson); + return pluginExportableService + .getExportableEntities( + exportingMetaDTO, mappedResourcesDTO, applicationMono, applicationJson) + .thenReturn(applicationJson); }) .flatMap(pluginList -> { - if (params.containsKey(FieldName.DATASOURCE_LIST)) { - return datasourceExportableService.getExportableEntities( - exportingMetaDTO, mappedResourcesDTO, applicationMono, applicationJson); + if (partialExportFileDTO.getDatasourceList().size() > 0) { + return datasourceExportableService + .getExportableEntities( + exportingMetaDTO, mappedResourcesDTO, applicationMono, applicationJson) + .thenReturn(applicationJson); } return Mono.just(applicationJson); }) .flatMap(appJson -> { - if (params.containsKey(FieldName.CUSTOM_JS_LIB_LIST)) { + if (partialExportFileDTO.getCustomJsLib().size() > 0) { return exportFilteredCustomJSLib( applicationId, - Set.copyOf(params.get(FieldName.CUSTOM_JS_LIB_LIST)), + partialExportFileDTO.getCustomJsLib(), applicationJson, branchName) .flatMap(jsLibList -> { @@ -129,33 +128,34 @@ public class PartialExportServiceCEImpl implements PartialExportServiceCE { // update page name in meta and exportable DTO for resource to name mapping .flatMap(branchedPageId -> updatePageNameInResourceMapDTO(branchedPageId, mappedResourcesDTO)) // export actions + // export js objects .flatMap(branchedPageId -> { - if (params.containsKey(FieldName.ACTION_LIST) - || params.containsKey(FieldName.ACTION_COLLECTION_LIST)) { - return exportActions( + if (partialExportFileDTO.getActionCollectionList().size() > 0) { + return exportActionCollections( branchedPageId, - Set.copyOf(params.get(FieldName.ACTION_LIST)), + partialExportFileDTO.getActionCollectionList(), applicationJson, mappedResourcesDTO) .then(Mono.just(branchedPageId)); } return Mono.just(branchedPageId); }) - // export js objects .flatMap(branchedPageId -> { - if (params.containsKey(FieldName.ACTION_COLLECTION_LIST)) { - return exportActionCollections( - branchedPageId, - Set.copyOf(params.get(FieldName.ACTION_COLLECTION_LIST)), - applicationJson, - mappedResourcesDTO); + if (partialExportFileDTO.getActionCollectionList().size() > 0 + || partialExportFileDTO.getActionList().size() > 0) { + return exportActions( + branchedPageId, + partialExportFileDTO.getActionList(), + applicationJson, + mappedResourcesDTO) + .then(Mono.just(branchedPageId)); } - return Mono.just(applicationJson); + return Mono.just(branchedPageId); }) .flatMap(appJson -> { // Remove the datasources not in use - if (params.containsKey(FieldName.DATASOURCE_LIST)) { - exportDatasource(Set.copyOf(params.get(FieldName.DATASOURCE_LIST)), applicationJson); + if (partialExportFileDTO.getDatasourceList().size() > 0) { + exportDatasource(partialExportFileDTO.getDatasourceList(), applicationJson); // Sanitise the datasource datasourceExportableService.sanitizeEntities( exportingMetaDTO, @@ -168,7 +168,7 @@ public class PartialExportServiceCEImpl implements PartialExportServiceCE { .map(exportedJson -> { String applicationName = applicationJson.getExportedApplication().getName(); - applicationJson.setWidgets(widgets); + applicationJson.setWidgets(partialExportFileDTO.getWidget()); applicationJson.setExportedApplication(null); String stringifiedFile = gson.toJson(exportedJson); Object jsonObject = gson.fromJson(stringifiedFile, Object.class); @@ -186,7 +186,7 @@ public class PartialExportServiceCEImpl implements PartialExportServiceCE { }); } - private void exportDatasource(Set validDatasource, ApplicationJson applicationJson) { + private void exportDatasource(List validDatasource, ApplicationJson applicationJson) { List datasourceList = applicationJson.getDatasourceList().stream() .filter(datasourceStorage -> validDatasource.contains(datasourceStorage.getDatasourceId())) .toList(); @@ -194,7 +194,7 @@ public class PartialExportServiceCEImpl implements PartialExportServiceCE { } private Mono exportFilteredCustomJSLib( - String applicationId, Set customJSLibSet, ApplicationJson applicationJson, String branchName) { + String applicationId, List customJSLibSet, ApplicationJson applicationJson, String branchName) { return customJSLibService .getAllJSLibsInApplication(applicationId, branchName, false) .flatMap(customJSLibs -> { @@ -209,7 +209,7 @@ public class PartialExportServiceCEImpl implements PartialExportServiceCE { private Mono exportActions( String pageId, - Set validActions, + List validActions, ApplicationJson applicationJson, MappedExportableResourcesDTO mappedResourcesDTO) { return newActionService.findByPageId(pageId).collectList().flatMap(actions -> { @@ -229,7 +229,7 @@ public class PartialExportServiceCEImpl implements PartialExportServiceCE { private Mono exportActionCollections( String pageId, - Set validActions, + List validActions, ApplicationJson applicationJson, MappedExportableResourcesDTO mappedResourcesDTO) { return actionCollectionService.findByPageId(pageId).collectList().flatMap(actionCollections -> { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/PartialImportService.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/PartialImportService.java new file mode 100644 index 0000000000..f328e50968 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/PartialImportService.java @@ -0,0 +1,3 @@ +package com.appsmith.server.imports.internal; + +public interface PartialImportService extends PartialImportServiceCE {} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/PartialImportServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/PartialImportServiceCE.java new file mode 100644 index 0000000000..3fffce596f --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/PartialImportServiceCE.java @@ -0,0 +1,11 @@ +package com.appsmith.server.imports.internal; + +import com.appsmith.server.domains.Application; +import org.springframework.http.codec.multipart.Part; +import reactor.core.publisher.Mono; + +public interface PartialImportServiceCE { + + Mono importResourceInPage( + String workspaceId, String applicationId, String pageId, String branchName, Part file); +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/PartialImportServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/PartialImportServiceCEImpl.java new file mode 100644 index 0000000000..63af9fb0dc --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/PartialImportServiceCEImpl.java @@ -0,0 +1,280 @@ +package com.appsmith.server.imports.internal; + +import com.appsmith.external.constants.AnalyticsEvents; +import com.appsmith.external.models.Datasource; +import com.appsmith.server.acl.AclPermission; +import com.appsmith.server.constants.FieldName; +import com.appsmith.server.domains.ActionCollection; +import com.appsmith.server.domains.Application; +import com.appsmith.server.domains.CustomJSLib; +import com.appsmith.server.domains.NewAction; +import com.appsmith.server.domains.NewPage; +import com.appsmith.server.domains.Plugin; +import com.appsmith.server.domains.Workspace; +import com.appsmith.server.dtos.ApplicationJson; +import com.appsmith.server.dtos.ImportingMetaDTO; +import com.appsmith.server.dtos.MappedImportableResourcesDTO; +import com.appsmith.server.exceptions.AppsmithError; +import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.helpers.ce.ImportApplicationPermissionProvider; +import com.appsmith.server.imports.importable.ImportableService; +import com.appsmith.server.newpages.base.NewPageService; +import com.appsmith.server.repositories.PermissionGroupRepository; +import com.appsmith.server.services.AnalyticsService; +import com.appsmith.server.services.ApplicationService; +import com.appsmith.server.services.WorkspaceService; +import com.appsmith.server.solutions.ActionPermission; +import com.appsmith.server.solutions.ApplicationPermission; +import com.appsmith.server.solutions.DatasourcePermission; +import com.appsmith.server.solutions.PagePermission; +import com.appsmith.server.solutions.WorkspacePermission; +import com.google.gson.Gson; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.codec.multipart.Part; +import org.springframework.transaction.reactive.TransactionalOperator; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@RequiredArgsConstructor +@Slf4j +public class PartialImportServiceCEImpl implements PartialImportServiceCE { + + private final ImportApplicationService importApplicationService; + private final WorkspaceService workspaceService; + private final ApplicationService applicationService; + private final AnalyticsService analyticsService; + private final DatasourcePermission datasourcePermission; + private final WorkspacePermission workspacePermission; + private final ApplicationPermission applicationPermission; + private final PagePermission pagePermission; + private final ActionPermission actionPermission; + private final Gson gson; + private final TransactionalOperator transactionalOperator; + private final PermissionGroupRepository permissionGroupRepository; + private final ImportableService pluginImportableService; + private final ImportableService newPageImportableService; + private final ImportableService customJSLibImportableService; + private final ImportableService datasourceImportableService; + private final ImportableService newActionImportableService; + private final ImportableService actionCollectionImportableService; + private final NewPageService newPageService; + + @Override + public Mono importResourceInPage( + String workspaceId, String applicationId, String pageId, String branchName, Part file) { + /* + 1. Get branchedPageId from pageId and branchName + 2. Get Application Mono + 3. Prepare the Meta DTO's + 4. Get plugin data + 5. Import datasources + 6. Import customJsLib + 7. Import actions + 8. Import actionCollection + */ + + MappedImportableResourcesDTO mappedImportableResourcesDTO = new MappedImportableResourcesDTO(); + + Mono branchedPageIdMono = + newPageService.findBranchedPageId(branchName, pageId, AclPermission.MANAGE_PAGES); + + // Extract file and get App Json + Mono partiallyImportedAppMono = importApplicationService + .extractApplicationJson(file) + .zipWith(getImportApplicationPermissions()) + .flatMap(tuple -> { + ApplicationJson applicationJson = tuple.getT1(); + ImportApplicationPermissionProvider permissionProvider = tuple.getT2(); + // Set Application in App JSON, remove the pages other than the one to be imported in + // Set the current page in the JSON to be imported + // Debug and get the value from getImportApplicationMono method if any difference + // Modify the Application set in JSON to be imported + + Mono workspaceMono = workspaceService + .findById(workspaceId, permissionProvider.getRequiredPermissionOnTargetWorkspace()) + .switchIfEmpty(Mono.defer(() -> { + log.error( + "No workspace found with id: {} and permission: {}", + workspaceId, + permissionProvider.getRequiredPermissionOnTargetWorkspace()); + return Mono.error(new AppsmithException( + AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.WORKSPACE, workspaceId)); + })) + .cache(); + + ImportingMetaDTO importingMetaDTO = + new ImportingMetaDTO(workspaceId, applicationId, branchName, false, permissionProvider); + + // Get the Application from DB + Mono importedApplicationMono = applicationService + .findByBranchNameAndDefaultApplicationId( + branchName, + applicationId, + permissionProvider.getRequiredPermissionOnTargetApplication()) + .cache(); + + return importedApplicationMono + .flatMap(application -> { + applicationJson.setExportedApplication(application); + return Mono.just(applicationJson); + }) + // Import Custom Js Lib and Datasource + .then(getApplicationImportableEntities( + importingMetaDTO, + mappedImportableResourcesDTO, + workspaceMono, + importedApplicationMono, + applicationJson)) + .thenReturn("done") + // Update the pageName map for actions and action collection + .then(paneNameMapForActionAndActionCollectionInAppJson( + branchedPageIdMono, applicationJson, mappedImportableResourcesDTO)) + .thenReturn("done") + // Import Actions and action collection + .then(getActionAndActionCollectionImport( + importingMetaDTO, + mappedImportableResourcesDTO, + workspaceMono, + importedApplicationMono, + applicationJson)) + .thenReturn("done") + .then(Mono.defer(() -> { + Application application = applicationJson.getExportedApplication(); + return newActionImportableService + .updateImportedEntities( + application, importingMetaDTO, mappedImportableResourcesDTO) + .then(newPageImportableService.updateImportedEntities( + application, importingMetaDTO, mappedImportableResourcesDTO)) + .flatMap( + newPage -> applicationService.update(application.getId(), application)); + })); + }) + .as(transactionalOperator::transactional); + + // Send Analytics event + return partiallyImportedAppMono.flatMap(application -> { + final Map eventData = Map.of(FieldName.APPLICATION, application); + + final Map data = Map.of( + FieldName.APPLICATION_ID, application.getId(), + FieldName.WORKSPACE_ID, application.getWorkspaceId(), + FieldName.EVENT_DATA, eventData); + + return analyticsService.sendObjectEvent(AnalyticsEvents.PARTIAL_IMPORT, application, data); + }); + } + + private Mono getImportApplicationPermissions() { + return permissionGroupRepository.getCurrentUserPermissionGroups().flatMap(userPermissionGroups -> { + ImportApplicationPermissionProvider permissionProvider = ImportApplicationPermissionProvider.builder( + applicationPermission, + pagePermission, + actionPermission, + datasourcePermission, + workspacePermission) + .requiredPermissionOnTargetWorkspace(workspacePermission.getReadPermission()) + .requiredPermissionOnTargetApplication(applicationPermission.getEditPermission()) + .permissionRequiredToCreateDatasource(true) + .permissionRequiredToEditDatasource(true) + .currentUserPermissionGroups(userPermissionGroups) + .build(); + return Mono.just(permissionProvider); + }); + } + + private Mono getApplicationImportableEntities( + ImportingMetaDTO importingMetaDTO, + MappedImportableResourcesDTO mappedImportableResourcesDTO, + Mono workspaceMono, + Mono importedApplicationMono, + ApplicationJson applicationJson) { + Mono customJSLibMono = pluginImportableService.importEntities( + importingMetaDTO, + mappedImportableResourcesDTO, + workspaceMono, + importedApplicationMono, + applicationJson); + + Mono datasourceMono = datasourceImportableService.importEntities( + importingMetaDTO, + mappedImportableResourcesDTO, + workspaceMono, + importedApplicationMono, + applicationJson); + + Mono customJsLibMono = customJSLibImportableService.importEntities( + importingMetaDTO, mappedImportableResourcesDTO, null, null, applicationJson); + + return Flux.merge(List.of(customJsLibMono, datasourceMono, customJSLibMono)) + .then(); + } + + private Mono getActionAndActionCollectionImport( + ImportingMetaDTO importingMetaDTO, + MappedImportableResourcesDTO mappedImportableResourcesDTO, + Mono workspaceMono, + Mono importedApplicationMono, + ApplicationJson applicationJson) { + Mono actionMono = newActionImportableService.importEntities( + importingMetaDTO, + mappedImportableResourcesDTO, + workspaceMono, + importedApplicationMono, + applicationJson); + + Mono actionCollectionMono = actionCollectionImportableService.importEntities( + importingMetaDTO, + mappedImportableResourcesDTO, + workspaceMono, + importedApplicationMono, + applicationJson); + + return Flux.merge(List.of(actionMono, actionCollectionMono)).then(); + } + + private Mono paneNameMapForActionAndActionCollectionInAppJson( + Mono branchedPageIdMono, + ApplicationJson applicationJson, + MappedImportableResourcesDTO mappedImportableResourcesDTO) { + return branchedPageIdMono.flatMap( + pageId -> newPageService.findById(pageId, Optional.empty()).flatMap(newPage -> { + String pageName = newPage.getUnpublishedPage().getName(); + // update page name reference with newPage + Map pageNameMap = new HashMap<>(); + pageNameMap.put(pageName, newPage); + mappedImportableResourcesDTO.setPageNameMap(pageNameMap); + + applicationJson.getActionList().forEach(action -> { + action.getPublishedAction().setPageId(pageName); + action.getUnpublishedAction().setPageId(pageName); + if (action.getPublishedAction().getCollectionId() != null) { + String collectionName = action.getPublishedAction() + .getCollectionId() + .split("_")[1]; + action.getPublishedAction().setCollectionId(pageName + "_" + collectionName); + action.getUnpublishedAction().setCollectionId(pageName + "_" + collectionName); + } + + String actionName = action.getId().split("_")[1]; + action.setId(pageName + "_" + actionName); + action.setGitSyncId(null); + }); + + applicationJson.getActionCollectionList().forEach(actionCollection -> { + actionCollection.getPublishedCollection().setPageId(pageName); + actionCollection.getUnpublishedCollection().setPageId(pageName); + + String collectionName = actionCollection.getId().split("_")[1]; + actionCollection.setId(pageName + "_" + collectionName); + actionCollection.setGitSyncId(null); + }); + return Mono.just(pageName); + })); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/PartialImportServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/PartialImportServiceImpl.java new file mode 100644 index 0000000000..1db60b46d2 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/PartialImportServiceImpl.java @@ -0,0 +1,72 @@ +package com.appsmith.server.imports.internal; + +import com.appsmith.external.models.Datasource; +import com.appsmith.server.domains.ActionCollection; +import com.appsmith.server.domains.CustomJSLib; +import com.appsmith.server.domains.NewAction; +import com.appsmith.server.domains.NewPage; +import com.appsmith.server.domains.Plugin; +import com.appsmith.server.imports.importable.ImportableService; +import com.appsmith.server.newpages.base.NewPageService; +import com.appsmith.server.repositories.PermissionGroupRepository; +import com.appsmith.server.services.AnalyticsService; +import com.appsmith.server.services.ApplicationService; +import com.appsmith.server.services.WorkspaceService; +import com.appsmith.server.solutions.ActionPermission; +import com.appsmith.server.solutions.ApplicationPermission; +import com.appsmith.server.solutions.DatasourcePermission; +import com.appsmith.server.solutions.PagePermission; +import com.appsmith.server.solutions.WorkspacePermission; +import com.google.gson.Gson; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; +import org.springframework.transaction.reactive.TransactionalOperator; + +@Slf4j +@Service +@Primary +public class PartialImportServiceImpl extends PartialImportServiceCEImpl implements PartialImportService { + + public PartialImportServiceImpl( + ImportApplicationService importApplicationService, + WorkspaceService workspaceService, + ApplicationService applicationService, + AnalyticsService analyticsService, + DatasourcePermission datasourcePermission, + WorkspacePermission workspacePermission, + ApplicationPermission applicationPermission, + PagePermission pagePermission, + ActionPermission actionPermission, + Gson gson, + TransactionalOperator transactionalOperator, + PermissionGroupRepository permissionGroupRepository, + ImportableService pluginImportableService, + ImportableService newPageImportableService, + ImportableService customJSLibImportableService, + ImportableService datasourceImportableService, + ImportableService newActionImportableService, + ImportableService actionCollectionImportableService, + NewPageService newPageService) { + super( + importApplicationService, + workspaceService, + applicationService, + analyticsService, + datasourcePermission, + workspacePermission, + applicationPermission, + pagePermission, + actionPermission, + gson, + transactionalOperator, + permissionGroupRepository, + pluginImportableService, + newPageImportableService, + customJSLibImportableService, + datasourceImportableService, + newActionImportableService, + actionCollectionImportableService, + newPageService); + } +} diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java index 520169f829..1f2f8c965d 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/controllers/ApplicationControllerTest.java @@ -11,6 +11,7 @@ import com.appsmith.server.fork.internal.ApplicationForkingService; import com.appsmith.server.helpers.GitFileUtils; import com.appsmith.server.helpers.RedisUtils; import com.appsmith.server.imports.internal.ImportApplicationService; +import com.appsmith.server.imports.internal.PartialImportService; import com.appsmith.server.services.AnalyticsService; import com.appsmith.server.services.ApplicationPageService; import com.appsmith.server.services.ApplicationService; @@ -83,6 +84,9 @@ public class ApplicationControllerTest { @MockBean PartialExportService partialExportService; + @MockBean + PartialImportService partialImportService; + private String getFileName(int length) { StringBuilder fileName = new StringBuilder(); for (int count = 0; count < length; count++) {