chore: refactor to use layout service for onPageLoad actions calculations in blocks API (#34269)
## Description Refactor the consolidated API for importing blocks Fixes ## Automation /ok-to-test tags="@tag.Templates" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/9690978421> > Commit: ce3884a3db7b99cd36b0d600b43120d8eafb61fb > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=9690978421&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Templates` <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Refactor** - Improved code structure by extending interface and class compatibility for `ConsolidatedAPIService` and `ConsolidatedAPIServiceImpl`. - **New Features** - Enhanced layout management by importing `UpdateLayoutService` and updating related logic to improve page load actions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Abhijeet <41686026+abhvsn@users.noreply.github.com>
This commit is contained in:
parent
2f12030a9a
commit
c3047e8e57
|
|
@ -1,10 +1,9 @@
|
|||
package com.appsmith.server.dtos;
|
||||
|
||||
import com.appsmith.external.dtos.DslExecutableDTO;
|
||||
import com.appsmith.external.models.ActionDTO;
|
||||
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 lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
|
@ -16,10 +15,7 @@ public class BuildingBlockResponseDTO {
|
|||
List<DslExecutableDTO> onPageLoadActions;
|
||||
|
||||
// New actions created in the current flow
|
||||
List<NewAction> newActionList;
|
||||
|
||||
// New actionCollection created in the current flow
|
||||
List<ActionCollection> actionCollectionList;
|
||||
List<ActionDTO> newActionList;
|
||||
|
||||
// All datasource in the workspace
|
||||
List<Datasource> datasourceList;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.appsmith.server.imports.internal.partial;
|
|||
|
||||
import com.appsmith.external.constants.AnalyticsEvents;
|
||||
import com.appsmith.external.helpers.Stopwatch;
|
||||
import com.appsmith.external.models.ActionDTO;
|
||||
import com.appsmith.external.models.CreatorContextType;
|
||||
import com.appsmith.external.models.Datasource;
|
||||
import com.appsmith.server.acl.AclPermission;
|
||||
|
|
@ -30,6 +31,7 @@ import com.appsmith.server.helpers.ImportArtifactPermissionProvider;
|
|||
import com.appsmith.server.imports.importable.ImportableService;
|
||||
import com.appsmith.server.imports.internal.ImportService;
|
||||
import com.appsmith.server.jslibs.base.CustomJSLibService;
|
||||
import com.appsmith.server.layouts.UpdateLayoutService;
|
||||
import com.appsmith.server.newactions.base.NewActionService;
|
||||
import com.appsmith.server.newpages.base.NewPageService;
|
||||
import com.appsmith.server.refactors.applications.RefactoringService;
|
||||
|
|
@ -50,6 +52,8 @@ import lombok.RequiredArgsConstructor;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.codec.multipart.Part;
|
||||
import org.springframework.transaction.reactive.TransactionalOperator;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
|
|
@ -58,10 +62,11 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.appsmith.server.constants.ce.FieldNameCE.WORKSPACE_ID;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class PartialImportServiceCEImpl implements PartialImportServiceCE {
|
||||
|
|
@ -93,6 +98,7 @@ public class PartialImportServiceCEImpl implements PartialImportServiceCE {
|
|||
private final ActionCollectionService actionCollectionService;
|
||||
private final DatasourceService datasourceService;
|
||||
private final CustomJSLibService customJSLibService;
|
||||
private final UpdateLayoutService updateLayoutService;
|
||||
|
||||
@Override
|
||||
public Mono<Application> importResourceInPage(
|
||||
|
|
@ -422,6 +428,9 @@ public class PartialImportServiceCEImpl implements PartialImportServiceCE {
|
|||
Mono<ApplicationJson> applicationJsonMono =
|
||||
applicationTemplateService.getApplicationJsonFromTemplate(buildingBlockDTO.getTemplateId());
|
||||
|
||||
Mono<String> branchedPageIdMono =
|
||||
newPageService.findBranchedPageId(branchName, buildingBlockDTO.getPageId(), AclPermission.MANAGE_PAGES);
|
||||
|
||||
Stopwatch processStopwatch = new Stopwatch("Download Content from Cloud service");
|
||||
return applicationJsonMono.flatMap(applicationJson -> {
|
||||
processStopwatch.stopAndLogTimeInMillis();
|
||||
|
|
@ -432,7 +441,10 @@ public class PartialImportServiceCEImpl implements PartialImportServiceCE {
|
|||
buildingBlockDTO.getPageId(),
|
||||
branchName,
|
||||
applicationJson)
|
||||
.flatMap(buildingBlockImportDTO -> {
|
||||
.zipWith(branchedPageIdMono)
|
||||
.flatMap(tuple -> {
|
||||
BuildingBlockImportDTO buildingBlockImportDTO = tuple.getT1();
|
||||
String branchedPageId = tuple.getT2();
|
||||
processStopwatch1.stopAndLogTimeInMillis();
|
||||
// Fetch layout and get new onPageLoadActions
|
||||
// This data is not present in a client, since these are created
|
||||
|
|
@ -441,117 +453,77 @@ public class PartialImportServiceCEImpl implements PartialImportServiceCE {
|
|||
buildingBlockResponseDTO.setWidgetDsl(buildingBlockImportDTO.getWidgetDsl());
|
||||
buildingBlockResponseDTO.setOnPageLoadActions(new ArrayList<>());
|
||||
|
||||
Set<String> newOnPageLoadActionNames = new HashSet<>();
|
||||
applicationJson
|
||||
.getPageList()
|
||||
.get(0)
|
||||
.getPublishedPage()
|
||||
.getLayouts()
|
||||
.get(0)
|
||||
.getLayoutOnLoadActions()
|
||||
.forEach(dslExecutableDTOS -> {
|
||||
dslExecutableDTOS.forEach(dslExecutableDTO -> {
|
||||
if (dslExecutableDTO.getName() != null) {
|
||||
// Use the refactored names to get the correct ids
|
||||
if (buildingBlockImportDTO
|
||||
.getRefactoredEntityNameMap()
|
||||
.get(dslExecutableDTO.getName())
|
||||
!= null) {
|
||||
dslExecutableDTO.setName(buildingBlockImportDTO
|
||||
.getRefactoredEntityNameMap()
|
||||
.get(dslExecutableDTO.getName()));
|
||||
}
|
||||
newOnPageLoadActionNames.add(
|
||||
dslExecutableDTO.getName().contains(".")
|
||||
? dslExecutableDTO.getName()
|
||||
.split("\\.")[0]
|
||||
: dslExecutableDTO.getName());
|
||||
buildingBlockResponseDTO
|
||||
.getOnPageLoadActions()
|
||||
.add(dslExecutableDTO);
|
||||
}
|
||||
});
|
||||
});
|
||||
// Fetch the datasource and customJsLibs
|
||||
Mono<List<Datasource>> datasourceList = datasourceService
|
||||
.getAllByWorkspaceIdWithStorages(
|
||||
buildingBlockDTO.getWorkspaceId(), AclPermission.MANAGE_DATASOURCES)
|
||||
.collectList();
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add(WORKSPACE_ID, buildingBlockDTO.getWorkspaceId());
|
||||
Mono<List<Datasource>> datasourceList =
|
||||
datasourceService.getAllWithStorages(params).collectList();
|
||||
|
||||
Mono<List<CustomJSLib>> customJSLibs = customJSLibService.getAllJSLibsInContext(
|
||||
buildingBlockDTO.getApplicationId(), CreatorContextType.APPLICATION, branchName, false);
|
||||
|
||||
// Fetch all actions and action collections and update the onPageLoadActions with correct ids
|
||||
return Mono.zip(
|
||||
actionCollectionService
|
||||
.findByPageId(buildingBlockDTO.getPageId())
|
||||
.collectList(),
|
||||
newActionService
|
||||
.findByPageId(buildingBlockDTO.getPageId())
|
||||
.collectList(),
|
||||
datasourceList,
|
||||
customJSLibs)
|
||||
.flatMap(tuple -> {
|
||||
List<ActionCollection> actionCollections = tuple.getT1();
|
||||
List<NewAction> newActions = tuple.getT2();
|
||||
Mono<List<ActionDTO>> actionList = newActionService
|
||||
.getUnpublishedActionsByPageId(branchedPageId, AclPermission.MANAGE_ACTIONS)
|
||||
.collectList();
|
||||
|
||||
buildingBlockResponseDTO.setDatasourceList(tuple.getT3());
|
||||
buildingBlockResponseDTO.setCustomJSLibList(tuple.getT4());
|
||||
// Filter the newly created actions and actionCollection
|
||||
buildingBlockResponseDTO.setNewActionList(newActions.stream()
|
||||
.filter(newAction -> buildingBlockImportDTO
|
||||
.getRefactoredEntityNameMap()
|
||||
.containsValue(newAction
|
||||
.getUnpublishedAction()
|
||||
.getName()))
|
||||
.toList());
|
||||
buildingBlockResponseDTO.setActionCollectionList(actionCollections.stream()
|
||||
.filter(actionCollection -> buildingBlockImportDTO
|
||||
.getRefactoredEntityNameMap()
|
||||
.containsValue(actionCollection
|
||||
.getUnpublishedCollection()
|
||||
.getName()))
|
||||
.toList());
|
||||
MultiValueMap<String, String> params1 = new LinkedMultiValueMap<>();
|
||||
params1.add(FieldName.PAGE_ID, branchedPageId);
|
||||
newActionService.getUnpublishedActions(params1, branchName);
|
||||
|
||||
actionCollections.forEach(actionCollection -> {
|
||||
if (newOnPageLoadActionNames.contains(actionCollection
|
||||
.getUnpublishedCollection()
|
||||
.getName())) {
|
||||
buildingBlockResponseDTO
|
||||
.getOnPageLoadActions()
|
||||
.forEach(dslExecutableDTO -> {
|
||||
if (dslExecutableDTO.getCollectionId() != null) {
|
||||
String name = dslExecutableDTO.getCollectionId()
|
||||
.split("_")[1];
|
||||
if (name.equals(actionCollection
|
||||
.getUnpublishedCollection()
|
||||
.getName())) {
|
||||
dslExecutableDTO.setId(actionCollection.getId());
|
||||
dslExecutableDTO.setCollectionId(
|
||||
actionCollection.getId());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
List<String> newActionNames = applicationJson.getActionList().stream()
|
||||
.map(newAction ->
|
||||
newAction.getUnpublishedAction().getName())
|
||||
.toList();
|
||||
|
||||
newActions.forEach(newAction -> {
|
||||
if (newOnPageLoadActionNames.contains(
|
||||
newAction.getUnpublishedAction().getName())) {
|
||||
buildingBlockResponseDTO
|
||||
.getOnPageLoadActions()
|
||||
.forEach(dslExecutableDTO -> {
|
||||
if (dslExecutableDTO
|
||||
.getName()
|
||||
.equals(newAction
|
||||
.getUnpublishedAction()
|
||||
.getName())) {
|
||||
dslExecutableDTO.setId(newAction.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return newPageService
|
||||
.findByBranchNameAndDefaultPageId(
|
||||
branchName, buildingBlockDTO.getPageId(), AclPermission.MANAGE_PAGES)
|
||||
.flatMap(newPage -> {
|
||||
String layoutId = newPage.getUnpublishedPage()
|
||||
.getLayouts()
|
||||
.get(0)
|
||||
.getId();
|
||||
Layout layout = applicationJson
|
||||
.getPageList()
|
||||
.get(0)
|
||||
.getUnpublishedPage()
|
||||
.getLayouts()
|
||||
.get(0);
|
||||
layout.setDsl(widgetRefactorUtil.convertDslStringToJSONObject(
|
||||
buildingBlockImportDTO.getWidgetDsl()));
|
||||
// fetch the layout and get the onPageLoadActions
|
||||
return updateLayoutService
|
||||
.getOnPageLoadActions(
|
||||
buildingBlockDTO.getPageId(),
|
||||
layoutId,
|
||||
layout,
|
||||
buildingBlockImportDTO
|
||||
.getApplication()
|
||||
.getEvaluationVersion(),
|
||||
CreatorContextType.PAGE)
|
||||
.flatMap(layoutDTO -> {
|
||||
layoutDTO.forEach(actionSet -> {
|
||||
buildingBlockResponseDTO
|
||||
.getOnPageLoadActions()
|
||||
.addAll(actionSet.stream()
|
||||
.toList());
|
||||
});
|
||||
|
||||
return Mono.just(buildingBlockResponseDTO);
|
||||
return Mono.zip(datasourceList, customJSLibs, actionList);
|
||||
})
|
||||
.map(tuple3 -> {
|
||||
buildingBlockResponseDTO.setDatasourceList(tuple3.getT1());
|
||||
buildingBlockResponseDTO.setCustomJSLibList(tuple3.getT2());
|
||||
buildingBlockResponseDTO.setNewActionList(tuple3.getT3());
|
||||
return buildingBlockResponseDTO;
|
||||
});
|
||||
})
|
||||
// Remove the existing actions in the page from the newActions list
|
||||
.flatMap(buildingBlockResponseDTO1 -> {
|
||||
buildingBlockResponseDTO1
|
||||
.getNewActionList()
|
||||
.removeIf(actionDTO -> !newActionNames.contains(actionDTO.getName()));
|
||||
return Mono.just(buildingBlockResponseDTO1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.appsmith.server.domains.Plugin;
|
|||
import com.appsmith.server.imports.importable.ImportableService;
|
||||
import com.appsmith.server.imports.internal.ImportService;
|
||||
import com.appsmith.server.jslibs.base.CustomJSLibService;
|
||||
import com.appsmith.server.layouts.UpdateLayoutService;
|
||||
import com.appsmith.server.newactions.base.NewActionService;
|
||||
import com.appsmith.server.newpages.base.NewPageService;
|
||||
import com.appsmith.server.refactors.applications.RefactoringService;
|
||||
|
|
@ -64,7 +65,8 @@ public class PartialImportServiceImpl extends PartialImportServiceCEImpl impleme
|
|||
NewActionService newActionService,
|
||||
ActionCollectionService actionCollectionService,
|
||||
DatasourceService datasourceService,
|
||||
CustomJSLibService customJSLibService) {
|
||||
CustomJSLibService customJSLibService,
|
||||
UpdateLayoutService updateLayoutService) {
|
||||
super(
|
||||
importService,
|
||||
workspaceService,
|
||||
|
|
@ -92,6 +94,7 @@ public class PartialImportServiceImpl extends PartialImportServiceCEImpl impleme
|
|||
newActionService,
|
||||
actionCollectionService,
|
||||
datasourceService,
|
||||
customJSLibService);
|
||||
customJSLibService,
|
||||
updateLayoutService);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,16 @@
|
|||
package com.appsmith.server.layouts;
|
||||
|
||||
import com.appsmith.external.dtos.DslExecutableDTO;
|
||||
import com.appsmith.external.models.CreatorContextType;
|
||||
import com.appsmith.server.domains.Layout;
|
||||
import com.appsmith.server.dtos.LayoutDTO;
|
||||
import com.appsmith.server.dtos.UpdateMultiplePageLayoutDTO;
|
||||
import net.minidev.json.JSONObject;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public interface UpdateLayoutServiceCE {
|
||||
Mono<LayoutDTO> updateLayout(String pageId, String applicationId, String layoutId, Layout layout);
|
||||
|
||||
|
|
@ -18,4 +23,7 @@ public interface UpdateLayoutServiceCE {
|
|||
JSONObject unescapeMongoSpecialCharacters(Layout layout);
|
||||
|
||||
Mono<String> updatePageLayoutsByPageId(String pageId);
|
||||
|
||||
Mono<List<Set<DslExecutableDTO>>> getOnPageLoadActions(
|
||||
String creatorId, String layoutId, Layout layout, Integer evaluatedVersion, CreatorContextType creatorType);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -304,6 +304,67 @@ public class UpdateLayoutServiceCEImpl implements UpdateLayoutServiceCE {
|
|||
.then(Mono.just(pageId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<List<Set<DslExecutableDTO>>> getOnPageLoadActions(
|
||||
String creatorId,
|
||||
String layoutId,
|
||||
Layout layout,
|
||||
Integer evaluatedVersion,
|
||||
CreatorContextType creatorType) {
|
||||
JSONObject dsl = layout.getDsl();
|
||||
if (dsl == null) {
|
||||
// There is no DSL here. No need to process anything. Return as is.
|
||||
return Mono.just(new ArrayList<>());
|
||||
}
|
||||
|
||||
Set<String> widgetNames = new HashSet<>();
|
||||
Map<String, Set<String>> widgetDynamicBindingsMap = new HashMap<>();
|
||||
Set<String> escapedWidgetNames = new HashSet<>();
|
||||
try {
|
||||
dsl = extractAllWidgetNamesAndDynamicBindingsFromDSL(
|
||||
dsl, widgetNames, widgetDynamicBindingsMap, creatorId, layoutId, escapedWidgetNames, creatorType);
|
||||
} catch (Throwable t) {
|
||||
return sendUpdateLayoutAnalyticsEvent(creatorId, layoutId, dsl, false, t, creatorType)
|
||||
.then(Mono.error(t));
|
||||
}
|
||||
|
||||
layout.setWidgetNames(widgetNames);
|
||||
|
||||
if (!escapedWidgetNames.isEmpty()) {
|
||||
layout.setMongoEscapedWidgetNames(escapedWidgetNames);
|
||||
}
|
||||
Set<ExecutableDependencyEdge> edges = new HashSet<>();
|
||||
Set<String> executablesUsedInDSL = new HashSet<>();
|
||||
List<Executable> flatmapOnLoadExecutables = new ArrayList<>();
|
||||
|
||||
AtomicReference<Boolean> validOnLoadExecutables = new AtomicReference<>(Boolean.TRUE);
|
||||
|
||||
// setting the layoutOnLoadActionActionErrors to empty to remove the existing errors before new DAG calculation.
|
||||
layout.setLayoutOnLoadActionErrors(new ArrayList<>());
|
||||
|
||||
return onLoadExecutablesUtil
|
||||
.findAllOnLoadExecutables(
|
||||
creatorId,
|
||||
evaluatedVersion,
|
||||
widgetNames,
|
||||
edges,
|
||||
widgetDynamicBindingsMap,
|
||||
flatmapOnLoadExecutables,
|
||||
executablesUsedInDSL,
|
||||
creatorType)
|
||||
.onErrorResume(AppsmithException.class, error -> {
|
||||
log.info(error.getMessage());
|
||||
validOnLoadExecutables.set(FALSE);
|
||||
layout.setLayoutOnLoadActionErrors(List.of(new ErrorDTO(
|
||||
error.getAppErrorCode(),
|
||||
error.getErrorType(),
|
||||
layoutOnLoadActionErrorToastMessage,
|
||||
error.getMessage(),
|
||||
error.getTitle())));
|
||||
return Mono.just(new ArrayList<>());
|
||||
});
|
||||
}
|
||||
|
||||
private JSONObject unEscapeDslKeys(JSONObject dsl, Set<String> escapedWidgetNames) {
|
||||
|
||||
String widgetName = (String) dsl.get(FieldName.WIDGET_NAME);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package com.appsmith.server.widgets.refactors;
|
|||
|
||||
import com.appsmith.external.models.MustacheBindingToken;
|
||||
import com.appsmith.server.constants.FieldName;
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
import com.appsmith.server.exceptions.AppsmithException;
|
||||
import com.appsmith.server.helpers.DslUtils;
|
||||
import com.appsmith.server.services.AstService;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
|
@ -10,7 +12,10 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
|
|||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.fasterxml.jackson.databind.node.TextNode;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.minidev.json.JSONObject;
|
||||
import net.minidev.json.parser.JSONParser;
|
||||
import net.minidev.json.parser.ParseException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
|
@ -24,6 +29,7 @@ import java.util.regex.Pattern;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class WidgetRefactorUtil {
|
||||
|
|
@ -197,4 +203,14 @@ public class WidgetRefactorUtil {
|
|||
public JsonNode convertDslStringToJsonNode(JSONObject dsl) {
|
||||
return objectMapper.convertValue(dsl, JsonNode.class);
|
||||
}
|
||||
|
||||
public JSONObject convertDslStringToJSONObject(String dsl) {
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
try {
|
||||
return (JSONObject) jsonParser.parse(dsl);
|
||||
} catch (ParseException exception) {
|
||||
log.error("Error parsing the page dsl for page: {}", exception.getMessage());
|
||||
throw new AppsmithException(AppsmithError.JSON_PROCESSING_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user