CE equivalent for removing js obj action id map (#32917)

This commit is contained in:
Nidhi 2024-04-24 19:10:53 +05:30 committed by GitHub
parent b867f9c643
commit 58671d6e8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 503 additions and 1150 deletions

View File

@ -29,7 +29,6 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
@ -46,11 +45,9 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import static com.appsmith.external.helpers.AppsmithBeanUtils.copyNewFieldValuesIntoOldObject;
import static java.lang.Boolean.TRUE;
import static java.util.stream.Collectors.toMap;
@Slf4j
public class ActionCollectionServiceCEImpl extends BaseService<ActionCollectionRepository, ActionCollection, String>
@ -171,17 +168,12 @@ public class ActionCollectionServiceCEImpl extends BaseService<ActionCollectionR
@Override
public Mono<ActionCollectionDTO> populateActionCollectionByViewMode(
ActionCollectionDTO actionCollectionDTO1, Boolean viewMode) {
return Mono.just(actionCollectionDTO1).flatMap(actionCollectionDTO -> Flux.fromIterable(
actionCollectionDTO.getDefaultToBranchedActionIdsMap().values())
.mergeWith(Flux.fromIterable(actionCollectionDTO
.getDefaultToBranchedArchivedActionIdsMap()
.values()))
.flatMap(actionId -> {
return newActionService.findActionDTObyIdAndViewMode(
actionId, viewMode, actionPermission.getReadPermission());
})
return newActionService
.findByCollectionIdAndViewMode(
actionCollectionDTO1.getId(), viewMode, actionPermission.getReadPermission())
.map(action -> newActionService.generateActionByViewMode(action, false))
.collectList()
.flatMap(actionsList -> splitValidActionsByViewMode(actionCollectionDTO, actionsList, viewMode)));
.flatMap(actionsList -> splitValidActionsByViewMode(actionCollectionDTO1, actionsList, viewMode));
}
/**
@ -191,28 +183,17 @@ public class ActionCollectionServiceCEImpl extends BaseService<ActionCollectionR
public Mono<ActionCollectionDTO> splitValidActionsByViewMode(
ActionCollectionDTO actionCollectionDTO, List<ActionDTO> actionsList, Boolean viewMode) {
return Mono.just(actionCollectionDTO).map(actionCollectionDTO1 -> {
List<ActionDTO> archivedActionList = new ArrayList<>();
List<ActionDTO> validActionList = new ArrayList<>();
final List<String> collect = actionsList.stream()
.parallel()
.map(ActionDTO::getPluginId)
.distinct()
.collect(Collectors.toList());
.toList();
if (collect.size() == 1) {
actionCollectionDTO.setPluginId(collect.get(0));
actionCollectionDTO.setPluginType(actionsList.get(0).getPluginType());
}
actionsList.forEach(action -> {
if (action.getDeletedAt() == null) {
validActionList.add(action);
} else {
archivedActionList.add(action);
}
});
List<ActionDTO> validActionList = new ArrayList<>(actionsList);
actionCollectionDTO.setActions(validActionList);
if (Boolean.FALSE.equals(viewMode)) {
actionCollectionDTO.setArchivedActions(archivedActionList);
}
return actionCollectionDTO;
});
}
@ -273,9 +254,9 @@ public class ActionCollectionServiceCEImpl extends BaseService<ActionCollectionR
defaults.setPageId(actionCollection.getPublishedCollection().getPageId());
}
actionCollectionViewDTO.setDefaultResources(defaults);
return Flux.fromIterable(
actionCollectionDTO.getDefaultToBranchedActionIdsMap().values())
.flatMap(actionId -> newActionService.findActionDTObyIdAndViewMode(actionId, viewMode, aclPermission))
return newActionService
.findByCollectionIdAndViewMode(actionCollection.getId(), viewMode, aclPermission)
.map(action -> newActionService.generateActionByViewMode(action, false))
.collectList()
.map(actionDTOList -> {
actionCollectionViewDTO.setActions(actionDTOList);
@ -395,16 +376,15 @@ public class ActionCollectionServiceCEImpl extends BaseService<ActionCollectionR
if (toDelete.getPublishedCollection() != null
&& toDelete.getPublishedCollection().getName() != null) {
toDelete.getUnpublishedCollection().setDeletedAt(Instant.now());
modifiedActionCollectionMono = Flux.fromIterable(toDelete.getUnpublishedCollection()
.getDefaultToBranchedActionIdsMap()
.values())
.flatMap(actionId -> newActionService
.deleteUnpublishedActionWithOptionalPermission(actionId, deleteActionPermission)
modifiedActionCollectionMono = newActionService
.findByCollectionIdAndViewMode(id, false, deleteActionPermission.orElse(null))
.flatMap(newAction -> newActionService
.deleteGivenNewAction(newAction)
// return an empty action so that the filter can remove it from the list
.onErrorResume(throwable -> {
log.debug(
"Failed to delete action with id {} for collection: {}",
actionId,
newAction.getId(),
toDelete.getUnpublishedCollection()
.getName());
log.error(throwable.getMessage());
@ -482,28 +462,7 @@ public class ActionCollectionServiceCEImpl extends BaseService<ActionCollectionR
String applicationId, AclPermission permission) {
return repository
.findByApplicationId(applicationId, permission, null)
.flatMap(actionCollection -> {
Set<String> actionIds = new HashSet<>();
actionIds.addAll(actionCollection
.getUnpublishedCollection()
.getDefaultToBranchedActionIdsMap()
.values());
if (actionCollection.getPublishedCollection() != null
&& !CollectionUtils.isEmpty(
actionCollection.getPublishedCollection().getDefaultToBranchedActionIdsMap())) {
actionIds.addAll(actionCollection
.getPublishedCollection()
.getDefaultToBranchedActionIdsMap()
.values());
}
return Flux.fromIterable(actionIds)
.flatMap(newActionService::archiveById)
.onErrorResume(throwable -> {
log.error(throwable.getMessage());
return Mono.empty();
})
.then(repository.archive(actionCollection));
})
.flatMap(this::archiveGivenActionCollection)
.collectList();
}
@ -539,43 +498,29 @@ public class ActionCollectionServiceCEImpl extends BaseService<ActionCollectionR
.switchIfEmpty(Mono.error(
new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.ACTION_COLLECTION, id)))
.cache();
return actionCollectionMono
.map(actionCollection -> {
final ActionCollectionDTO unpublishedCollection = actionCollection.getUnpublishedCollection();
final ActionCollectionDTO publishedCollection = actionCollection.getPublishedCollection();
final Set<String> actionIds = new HashSet<>();
if (unpublishedCollection != null) {
actionIds.addAll(unpublishedCollection
.getDefaultToBranchedActionIdsMap()
.values());
actionIds.addAll(unpublishedCollection
.getDefaultToBranchedArchivedActionIdsMap()
.values());
}
if (publishedCollection != null
&& !CollectionUtils.isEmpty(publishedCollection.getDefaultToBranchedActionIdsMap())) {
actionIds.addAll(publishedCollection
.getDefaultToBranchedActionIdsMap()
.values());
actionIds.addAll(publishedCollection
.getDefaultToBranchedArchivedActionIdsMap()
.values());
}
return actionIds;
})
.flatMapMany(Flux::fromIterable)
.flatMap(actionId -> newActionService
.archiveById(actionId)
return actionCollectionMono.flatMap(this::archiveGivenActionCollection);
}
protected Mono<ActionCollection> archiveGivenActionCollection(ActionCollection actionCollection) {
Flux<NewAction> unpublishedJsActionsFlux = newActionService.findByCollectionIdAndViewMode(
actionCollection.getId(), false, actionPermission.getDeletePermission());
Flux<NewAction> publishedJsActionsFlux = newActionService.findByCollectionIdAndViewMode(
actionCollection.getId(), true, actionPermission.getDeletePermission());
return unpublishedJsActionsFlux
.mergeWith(publishedJsActionsFlux)
.flatMap(toArchive -> newActionService
.archiveGivenNewAction(toArchive)
// return an empty action so that the filter can remove it from the list
.onErrorResume(throwable -> {
log.debug("Failed to delete action with id {} for collection with id: {}", actionId, id);
log.debug(
"Failed to delete action with id {} for collection with id: {}",
toArchive.getId(),
actionCollection.getId());
log.error(throwable.getMessage());
return Mono.empty();
}))
.collectList()
.flatMap(actionList -> actionCollectionMono)
.flatMap(
actionCollection -> repository.archive(actionCollection).thenReturn(actionCollection))
.then(repository.archive(actionCollection).thenReturn(actionCollection))
.flatMap(deletedActionCollection -> analyticsService.sendDeleteEvent(
deletedActionCollection, getAnalyticsProperties(deletedActionCollection)));
}
@ -856,10 +801,6 @@ public class ActionCollectionServiceCEImpl extends BaseService<ActionCollectionR
defaults.setApplicationId(actionCollection.getApplicationId());
}
actionCollection.setDefaultResources(defaults);
final Map<String, String> actionIds = actions.stream()
.collect(toMap(actionDTO -> actionDTO.getDefaultResources().getActionId(), ActionDTO::getId));
collectionDTO.setDefaultToBranchedActionIdsMap(actionIds);
}
@Override

View File

@ -6,15 +6,12 @@ import com.appsmith.server.clonepage.ClonePageServiceCE;
import com.appsmith.server.domains.ActionCollection;
import com.appsmith.server.dtos.ActionCollectionDTO;
import com.appsmith.server.dtos.ClonePageMetaDTO;
import com.appsmith.server.newactions.base.NewActionService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import static com.appsmith.external.helpers.AppsmithBeanUtils.copyNestedNonNullProperties;
@ -23,7 +20,6 @@ import static com.appsmith.external.helpers.AppsmithBeanUtils.copyNestedNonNullP
@RequiredArgsConstructor
public class ActionCollectionClonePageServiceCEImpl implements ClonePageServiceCE<ActionCollection> {
private final ActionCollectionService actionCollectionService;
private final NewActionService newActionService;
@Override
public Mono<Void> cloneEntities(ClonePageMetaDTO clonePageMetaDTO) {
@ -49,54 +45,6 @@ public class ActionCollectionClonePageServiceCEImpl implements ClonePageServiceC
defaultResourcesForDTO.setPageId(clonedPageDefaultResources.getPageId());
toBeClonedActionCollection.getUnpublishedCollection().setDefaultResources(defaultResourcesForDTO);
// Replace all action Ids from map
Map<String, String> updatedDefaultToBranchedActionId = new HashMap<>();
// Check if the application is connected with git and update
// defaultActionIds accordingly
//
// 1. If the app is connected with git keep the actionDefaultId as it is and
// update branchedActionId only
//
// 2. If app is not connected then both default and branchedActionId will be
// same as newly created action Id
if (StringUtils.isEmpty(clonedPageDefaultResources.getBranchName())) {
unpublishedCollection.getDefaultToBranchedActionIdsMap().forEach((defaultId, oldActionId) -> {
// Filter out the actionIds for which the reference is not
// present in cloned actions, this happens when we have
// deleted action in unpublished mode
if (StringUtils.hasLength(oldActionId)
&& StringUtils.hasLength(clonePageMetaDTO
.getOldToNewActionIdMap()
.get(oldActionId))) {
updatedDefaultToBranchedActionId.put(
clonePageMetaDTO
.getOldToNewActionIdMap()
.get(oldActionId),
clonePageMetaDTO
.getOldToNewActionIdMap()
.get(oldActionId));
}
});
} else {
unpublishedCollection.getDefaultToBranchedActionIdsMap().forEach((defaultId, oldActionId) -> {
// Filter out the actionIds for which the reference is not
// present in cloned actions, this happens when we have
// deleted action in unpublished mode
if (StringUtils.hasLength(defaultId)
&& StringUtils.hasLength(clonePageMetaDTO
.getOldToNewActionIdMap()
.get(oldActionId))) {
updatedDefaultToBranchedActionId.put(
defaultId,
clonePageMetaDTO
.getOldToNewActionIdMap()
.get(oldActionId));
}
});
}
unpublishedCollection.setDefaultToBranchedActionIdsMap(updatedDefaultToBranchedActionId);
// Set id as null, otherwise create (which is using under the hood save)
// will try to overwrite same resource instead of creating a new resource
toBeClonedActionCollection.setId(null);
@ -110,7 +58,9 @@ public class ActionCollectionClonePageServiceCEImpl implements ClonePageServiceC
return actionCollectionService
.create(toBeClonedActionCollection)
.flatMap(clonedActionCollection -> {
clonePageMetaDTO.getClonedActionCollections().add(clonedActionCollection);
clonePageMetaDTO
.getOldToNewCollectionIds()
.put(sourceActionCollection.getId(), clonedActionCollection.getId());
if (!StringUtils.hasLength(clonedActionCollection
.getDefaultResources()
.getCollectionId())) {
@ -127,32 +77,6 @@ public class ActionCollectionClonePageServiceCEImpl implements ClonePageServiceC
.then();
}
@Override
public Mono<Void> updateClonedEntities(ClonePageMetaDTO clonePageMetaDTO) {
return Flux.fromIterable(clonePageMetaDTO.getClonedActionCollections())
.flatMap(clonedActionCollection -> {
return Flux.fromIterable(clonedActionCollection
.getUnpublishedCollection()
.getDefaultToBranchedActionIdsMap()
.values())
.flatMap(newActionService::findById)
.flatMap(newlyCreatedAction -> {
newlyCreatedAction
.getUnpublishedAction()
.setCollectionId(clonedActionCollection.getId());
newlyCreatedAction
.getUnpublishedAction()
.getDefaultResources()
.setCollectionId(clonedActionCollection
.getDefaultResources()
.getCollectionId());
return newActionService.update(newlyCreatedAction.getId(), newlyCreatedAction);
});
})
.collectList()
.then();
}
protected Flux<ActionCollection> getCloneableActionCollections(String pageId) {
return actionCollectionService.findByPageId(pageId);
}

View File

@ -3,14 +3,12 @@ package com.appsmith.server.actioncollections.clonepage;
import com.appsmith.server.actioncollections.base.ActionCollectionService;
import com.appsmith.server.clonepage.ClonePageService;
import com.appsmith.server.domains.ActionCollection;
import com.appsmith.server.newactions.base.NewActionService;
import org.springframework.stereotype.Service;
@Service
public class ActionCollectionClonePageServiceImpl extends ActionCollectionClonePageServiceCEImpl
implements ClonePageService<ActionCollection> {
public ActionCollectionClonePageServiceImpl(
ActionCollectionService actionCollectionService, NewActionService newActionService) {
super(actionCollectionService, newActionService);
public ActionCollectionClonePageServiceImpl(ActionCollectionService actionCollectionService) {
super(actionCollectionService);
}
}

View File

@ -279,10 +279,6 @@ public class ActionCollectionImportableServiceCEImpl implements ImportableServic
final String fallbackDefaultContextId = unpublishedCollection.calculateContextId();
if (unpublishedCollection.getName() != null) {
unpublishedCollection.setDefaultToBranchedActionIdsMap(mappedImportableResourcesDTO
.getActionResultDTO()
.getUnpublishedCollectionIdToActionIdsMap()
.get(idFromJsonFile));
unpublishedCollection.setPluginId(
mappedImportableResourcesDTO.getPluginMap().get(unpublishedCollection.getPluginId()));
@ -291,10 +287,6 @@ public class ActionCollectionImportableServiceCEImpl implements ImportableServic
}
if (publishedCollection != null && publishedCollection.getName() != null) {
publishedCollection.setDefaultToBranchedActionIdsMap(mappedImportableResourcesDTO
.getActionResultDTO()
.getPublishedCollectionIdToActionIdsMap()
.get(idFromJsonFile));
publishedCollection.setPluginId(
mappedImportableResourcesDTO.getPluginMap().get(publishedCollection.getPluginId()));

View File

@ -21,7 +21,6 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
@ -119,17 +118,10 @@ public class ActionCollectionRefactoringServiceCEImpl implements EntityRefactori
return branchedActionCollectionDTOMono
.flatMap(branchedActionCollection -> {
final HashMap<String, String> actionIds = new HashMap<>();
if (branchedActionCollection.getDefaultToBranchedActionIdsMap() != null) {
actionIds.putAll(branchedActionCollection.getDefaultToBranchedActionIdsMap());
}
if (branchedActionCollection.getDefaultToBranchedArchivedActionIdsMap() != null) {
actionIds.putAll(branchedActionCollection.getDefaultToBranchedArchivedActionIdsMap());
}
Flux<ActionDTO> actionUpdatesFlux = Flux.fromIterable(actionIds.values())
.flatMap(actionId -> newActionService.findActionDTObyIdAndViewMode(
actionId, false, actionPermission.getEditPermission()))
Flux<ActionDTO> actionUpdatesFlux = newActionService
.findByCollectionIdAndViewMode(
branchedActionCollection.getId(), false, actionPermission.getEditPermission())
.map(action -> newActionService.generateActionByViewMode(action, false))
.flatMap(actionDTO -> {
actionDTO.setFullyQualifiedName(newName + "." + actionDTO.getName());
return newActionService

View File

@ -6,6 +6,4 @@ import reactor.core.publisher.Mono;
public interface ClonePageServiceCE<T extends BaseDomain> {
Mono<Void> cloneEntities(ClonePageMetaDTO clonePageMetaDTO);
Mono<Void> updateClonedEntities(ClonePageMetaDTO clonePageMetaDTO);
}

View File

@ -78,8 +78,15 @@ public class NewActionCE extends BranchAwareDomain {
public static final String unpublishedAction_actionConfiguration_httpMethod =
dotted(unpublishedAction, ActionDTO.Fields.actionConfiguration, ActionConfiguration.Fields.httpMethod);
public static final String publishedAction_datasource_id =
dotted(publishedAction, ActionDTO.Fields.datasource, Datasource.Fields.id);
public static final String publishedAction_name = dotted(publishedAction, ActionDTO.Fields.name);
public static final String publishedAction_pageId = dotted(publishedAction, ActionDTO.Fields.pageId);
public static final String publishedAction_contextType = dotted(publishedAction, ActionDTO.Fields.contextType);
public static final String unpublishedAction_collectionId =
dotted(unpublishedAction, ActionDTO.Fields.collectionId);
public static final String publishedAction_collectionId =
dotted(publishedAction, ActionDTO.Fields.collectionId);
}
}

View File

@ -1,14 +1,11 @@
package com.appsmith.server.dtos;
import com.appsmith.server.domains.ActionCollection;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Data
@ -19,6 +16,5 @@ public class ClonePageMetaDTO {
String branchedSourcePageId;
PageDTO clonedPageDTO;
String branchName;
Map<String, String> oldToNewActionIdMap = new HashMap<>();
List<ActionCollection> clonedActionCollections = new ArrayList<>();
Map<String, String> oldToNewCollectionIds = new HashMap<>();
}

View File

@ -24,7 +24,6 @@ import org.springframework.data.annotation.Transient;
import java.time.Instant;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static com.appsmith.external.helpers.AppsmithBeanUtils.copyNewFieldValuesIntoOldObject;
@ -74,32 +73,12 @@ public class ActionCollectionCE_DTO {
@JsonView(Views.Public.class)
Instant deletedAt;
// This property is not shared with the client since the reference is only useful to server
// Map<defaultActionId, branchedActionId>
@JsonView(Views.Internal.class)
Map<String, String> defaultToBranchedActionIdsMap = Map.of();
@Deprecated
@JsonView(Views.Public.class)
Set<String> actionIds = Set.of();
// This property is not shared with the client since the reference is only useful to server
// Archived actions represent actions that have been removed from a js object but may be subject to re-use by the
// user
// Map<defaultActionId, branchedActionId>
@JsonView(Views.Internal.class)
Map<String, String> defaultToBranchedArchivedActionIdsMap = Map.of();
@Deprecated
@JsonView(Views.Public.class)
Set<String> archivedActionIds = Set.of();
// Instead of storing the entire action object, we only populate this field while interacting with the client side
@Transient
@JsonView(Views.Public.class)
List<ActionDTO> actions = List.of();
// Instead of storing the entire action object, we only populate this field while interacting with the client side
// TODO : Remove after clean up, this is only kept as of now because removing it will show up as a diff on git
@Transient
@JsonView(Views.Public.class)
List<ActionDTO> archivedActions = List.of();
@ -152,10 +131,6 @@ public class ActionCollectionCE_DTO {
public void sanitiseForExport() {
this.resetTransientFields();
this.setDefaultResources(null);
this.setDefaultToBranchedActionIdsMap(null);
this.setDefaultToBranchedArchivedActionIdsMap(null);
this.setActionIds(null);
this.setArchivedActionIds(null);
this.setUserPermissions(Set.of());
}
@ -170,7 +145,6 @@ public class ActionCollectionCE_DTO {
this.setApplicationId(null);
this.setErrorReports(null);
this.setActions(List.of());
this.setArchivedActions(List.of());
}
public String calculateContextId() {

View File

@ -2,7 +2,6 @@ package com.appsmith.server.fork.internal;
import com.appsmith.external.constants.ActionCreationSourceTypeEnum;
import com.appsmith.external.constants.AnalyticsEvents;
import com.appsmith.external.dtos.DslExecutableDTO;
import com.appsmith.external.helpers.AppsmithEventContext;
import com.appsmith.external.helpers.AppsmithEventContextType;
import com.appsmith.external.models.ActionDTO;
@ -33,6 +32,7 @@ import com.appsmith.server.fork.forkable.ForkableService;
import com.appsmith.server.helpers.ResponseUtils;
import com.appsmith.server.helpers.UserPermissionUtils;
import com.appsmith.server.imports.internal.ImportService;
import com.appsmith.server.layouts.UpdateLayoutService;
import com.appsmith.server.newactions.base.NewActionService;
import com.appsmith.server.repositories.ActionCollectionRepository;
import com.appsmith.server.repositories.NewActionRepository;
@ -55,6 +55,7 @@ import org.apache.commons.lang.StringUtils;
import org.bson.types.ObjectId;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.function.Tuple2;
import java.util.ArrayList;
import java.util.HashMap;
@ -90,6 +91,7 @@ public class ApplicationForkingServiceCEImpl implements ApplicationForkingServic
private final NewActionRepository newActionRepository;
private final WorkspaceRepository workspaceRepository;
private final ForkableService<Datasource> datasourceForkableService;
private final UpdateLayoutService updateLayoutService;
/**
* Clone all applications (except deleted ones), including its pages and actions from one workspace into
* another. Also clones all datasources (not just the ones used by any applications) provided in the parameter list.
@ -178,219 +180,174 @@ public class ApplicationForkingServiceCEImpl implements ApplicationForkingServic
.forkWithConfiguration(forkWithConfig)
.build();
return applicationPageService
Mono<NewPage> createForkedPageMono = applicationPageService
.createPage(page)
.flatMap(savedPage -> isDefault
? applicationPageService
.makePageDefault(savedPage)
.thenReturn(savedPage)
: Mono.just(savedPage))
.flatMap(savedPage -> newPageRepository.findById(savedPage.getId()))
.flatMap(savedPage -> {
clonedPages.add(savedPage);
Flux<NewAction> sourceActionFlux = newActionService
.findByPageId(templatePageId)
.cache();
.flatMap(savedPage -> newPageRepository.findById(savedPage.getId()));
forkingSourceToForkableActionsFluxMap.put(sourceMetaForPage, sourceActionFlux);
return createForkedPageMono.flatMap(savedPage -> {
clonedPages.add(savedPage);
Flux<NewAction> sourceActionFlux = newActionService
.findByPageIdsForExport(List.of(templatePageId), Optional.empty())
.cache();
ForkingMetaDTO targetMetaForPage = targetMeta.toBuilder()
.applicationId(newPage.getApplicationId())
.pageId(newPage.getId())
.forkWithConfiguration(forkWithConfig)
.build();
forkingSourceToForkableActionsFluxMap.put(sourceMetaForPage, sourceActionFlux);
Flux<Datasource> forkableDatasourceFlux = datasourceForkableService
.getForkableEntitiesFromSource(sourceMetaForPage, sourceActionFlux)
.map(forkableDatasource -> {
if (!clonedDatasourceMonos.containsKey(forkableDatasource.getId())) {
Mono<Datasource> datasourceMono = datasourceForkableService
.createForkedEntity(
forkableDatasource,
sourceMetaForPage,
targetMetaForPage,
existingDatasourcesMono)
.cache();
clonedDatasourceMonos.put(forkableDatasource.getId(), datasourceMono);
}
return forkableDatasource;
});
ForkingMetaDTO targetMetaForPage = targetMeta.toBuilder()
.applicationId(newPage.getApplicationId())
.pageId(newPage.getId())
.forkWithConfiguration(forkWithConfig)
.build();
return forkableDatasourceFlux
.thenMany(sourceActionFlux)
.map(newAction -> {
ActionDTO action = newAction.getUnpublishedAction();
log.info(
"Preparing action for cloning {} {}.",
action.getName(),
newAction.getId());
action.setPageId(savedPage.getId());
action.setDefaultResources(null);
return newAction;
})
.flatMap(newAction -> {
final String originalActionId = newAction.getId();
log.info("Creating clone of action {}", originalActionId);
newAction.makePristine();
newAction.setWorkspaceId(toWorkspaceId);
ActionDTO action = newAction.getUnpublishedAction();
action.setCollectionId(null);
Flux<Datasource> forkableDatasourceFlux = datasourceForkableService
.getForkableEntitiesFromSource(sourceMetaForPage, sourceActionFlux)
.map(forkableDatasource -> {
if (!clonedDatasourceMonos.containsKey(forkableDatasource.getId())) {
Mono<Datasource> datasourceMono = datasourceForkableService
.createForkedEntity(
forkableDatasource,
sourceMetaForPage,
targetMetaForPage,
existingDatasourcesMono)
.cache();
clonedDatasourceMonos.put(forkableDatasource.getId(), datasourceMono);
}
return forkableDatasource;
});
Mono<ActionDTO> actionMono = Mono.just(action);
final Datasource datasourceInsideAction = action.getDatasource();
if (datasourceInsideAction != null) {
if (datasourceInsideAction.getId() != null) {
final String datasourceId = datasourceInsideAction.getId();
actionMono = clonedDatasourceMonos
.get(datasourceId)
.map(newDatasource -> {
action.setDatasource(newDatasource);
return action;
});
} else {
// If this is an embedded datasource, the config will get forked
// along with the action
datasourceInsideAction.setWorkspaceId(toWorkspaceId);
Mono<HashMap<String, String>> forkedCollectionsMono = actionCollectionService
.findByPageId(templatePageId)
.flatMap(actionCollection -> {
// Keep a record of the original collection id
final String originalCollectionId = actionCollection.getId();
log.info("Creating clone of action collection {}", originalCollectionId);
// Sanitize them
actionCollection.makePristine();
actionCollection.setPublishedCollection(null);
final ActionCollectionDTO unpublishedCollection =
actionCollection.getUnpublishedCollection();
unpublishedCollection.setPageId(savedPage.getId());
DefaultResources defaultResources = new DefaultResources();
defaultResources.setPageId(savedPage.getId());
unpublishedCollection.setDefaultResources(defaultResources);
actionCollection.setWorkspaceId(toWorkspaceId);
actionCollection.setApplicationId(savedPage.getApplicationId());
DefaultResources defaultResources1 = new DefaultResources();
defaultResources1.setApplicationId(savedPage.getApplicationId());
actionCollection.setDefaultResources(defaultResources1);
actionCollectionService.generateAndSetPolicies(savedPage, actionCollection);
return actionCollectionService
.create(actionCollection)
.flatMap(clonedActionCollection -> {
Mono<Tuple2<String, String>> tuple2Mono = Mono.zip(
Mono.just(clonedActionCollection.getId()),
Mono.just(originalCollectionId));
if (org.springframework.util.StringUtils.isEmpty(clonedActionCollection
.getDefaultResources()
.getCollectionId())) {
ActionCollection updates = new ActionCollection();
DefaultResources defaultResources2 =
clonedActionCollection.getDefaultResources();
defaultResources2.setCollectionId(clonedActionCollection.getId());
updates.setDefaultResources(defaultResources2);
return actionCollectionService
.update(clonedActionCollection.getId(), updates)
.then(tuple2Mono);
}
}
return Mono.zip(
actionMono
.flatMap(actionDTO -> {
// Indicates that source of action creation is fork
// application
actionDTO.setSource(
ActionCreationSourceTypeEnum.FORK_APPLICATION);
return layoutActionService.createAction(
actionDTO,
new AppsmithEventContext(
AppsmithEventContextType.CLONE_PAGE),
Boolean.FALSE);
})
.map(ActionDTO::getId),
Mono.justOrEmpty(originalActionId));
})
// This call to `collectMap` will wait for all actions in all pages to have been
// processed, and so the
// `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)
.flatMap(actionCollection -> {
// Keep a record of the original collection id
final String originalCollectionId = actionCollection.getId();
log.info(
"Creating clone of action collection {}",
originalCollectionId);
// Sanitize them
actionCollection.makePristine();
actionCollection.setPublishedCollection(null);
final ActionCollectionDTO unpublishedCollection =
actionCollection.getUnpublishedCollection();
unpublishedCollection.setPageId(savedPage.getId());
return tuple2Mono;
});
})
.collect(
HashMap<String, String>::new,
(map, tuple2) -> map.put(tuple2.getT2(), tuple2.getT1()))
.cache();
DefaultResources defaultResources = new DefaultResources();
defaultResources.setPageId(savedPage.getId());
unpublishedCollection.setDefaultResources(defaultResources);
Mono<HashMap<String, String>> forkedActionsMono =
forkedCollectionsMono.flatMap(collectionIdMap -> {
return sourceActionFlux
.map(newAction -> {
ActionDTO action = newAction.getUnpublishedAction();
log.info(
"Preparing action for cloning {} {}.",
action.getName(),
newAction.getId());
action.setPageId(savedPage.getId());
action.setDefaultResources(null);
return newAction;
})
.flatMap(newAction -> {
final String originalActionId = newAction.getId();
String originalCollectionId = newAction
.getUnpublishedAction()
.getCollectionId();
String forkedCollectionId = collectionIdMap.get(originalCollectionId);
log.info("Creating clone of action {}", originalActionId);
newAction.makePristine();
newAction.setWorkspaceId(toWorkspaceId);
ActionDTO action = newAction.getUnpublishedAction();
action.setCollectionId(forkedCollectionId);
actionCollection.setWorkspaceId(toWorkspaceId);
actionCollection.setApplicationId(savedPage.getApplicationId());
DefaultResources defaultResources1 = new DefaultResources();
defaultResources1.setApplicationId(
savedPage.getApplicationId());
actionCollection.setDefaultResources(defaultResources1);
actionCollectionService.generateAndSetPolicies(
savedPage, actionCollection);
// Replace all action Ids from map and replace with newly
// created actionIds
final Map<String, String> newActionIds = new HashMap<>();
unpublishedCollection
.getDefaultToBranchedActionIdsMap()
.forEach((defaultActionId, oldActionId) -> {
if (org.springframework.util.StringUtils.hasLength(
oldActionId)
&& org.springframework.util.StringUtils
.hasLength(actionIdsMap.get(
oldActionId))) {
// As this is a new application and not
// connected
// through git branch, the default and newly
// created actionId will be same
newActionIds.put(
actionIdsMap.get(oldActionId),
actionIdsMap.get(oldActionId));
} else {
log.debug(
"Unable to find action {} while forking inside ID map: {}",
oldActionId,
actionIdsMap);
}
Mono<ActionDTO> actionMono = Mono.just(action);
final Datasource datasourceInsideAction = action.getDatasource();
if (datasourceInsideAction != null) {
if (datasourceInsideAction.getId() != null) {
final String datasourceId = datasourceInsideAction.getId();
actionMono = clonedDatasourceMonos
.get(datasourceId)
.map(newDatasource -> {
action.setDatasource(newDatasource);
return action;
});
unpublishedCollection.setDefaultToBranchedActionIdsMap(
newActionIds);
return actionCollectionService
.create(actionCollection)
.flatMap(clonedActionCollection -> {
if (org.springframework.util.StringUtils.isEmpty(
clonedActionCollection
.getDefaultResources()
.getCollectionId())) {
ActionCollection updates =
new ActionCollection();
DefaultResources defaultResources2 =
clonedActionCollection
.getDefaultResources();
defaultResources2.setCollectionId(
clonedActionCollection.getId());
updates.setDefaultResources(defaultResources2);
return actionCollectionService.update(
clonedActionCollection.getId(),
updates);
}
return Mono.just(clonedActionCollection);
} else {
// If this is an embedded datasource, the config will get forked
// along with the action
datasourceInsideAction.setWorkspaceId(toWorkspaceId);
}
}
return Mono.zip(
actionMono
.flatMap(actionDTO -> {
actionDTO.setId(null);
// Indicates that source of action creation is fork
// application
actionDTO.setSource(
ActionCreationSourceTypeEnum
.FORK_APPLICATION);
return layoutActionService.createAction(
actionDTO,
new AppsmithEventContext(
AppsmithEventContextType
.CLONE_PAGE),
Boolean.FALSE);
})
.flatMap(clonedActionCollection -> {
collectionIdsMap.put(
originalCollectionId,
clonedActionCollection.getId());
return Flux.fromIterable(newActionIds.values())
.flatMap(newActionService::findById)
.flatMap(newlyCreatedAction -> {
ActionDTO unpublishedAction =
newlyCreatedAction
.getUnpublishedAction();
unpublishedAction.setCollectionId(
clonedActionCollection.getId());
unpublishedAction
.getDefaultResources()
.setCollectionId(
clonedActionCollection
.getId());
return newActionService.update(
newlyCreatedAction.getId(),
newlyCreatedAction);
})
.collectList();
});
})
.collectList()
.then(Mono.zip(
Mono.just(actionIdsMap), Mono.just(collectionIdsMap)));
});
});
.map(ActionDTO::getId),
Mono.justOrEmpty(originalActionId));
})
// This call to `collectMap` will wait for all actions in all pages to have
// been processed,
// and so the `clonedPages` list will also contain all pages cloned.
.collect(
HashMap::new,
(map, tuple2) -> map.put(tuple2.getT2(), tuple2.getT1()));
});
return forkableDatasourceFlux
.then(forkedCollectionsMono)
.zipWhen(forkedCollectionsMap -> forkedActionsMono);
});
})
.flatMap(tuple -> updateActionAndCollectionsIdsInForkedPages(clonedPages, tuple.getT1(), tuple.getT2()))
.flatMapIterable(tuple2 -> clonedPages)
.flatMap(clonedPage -> updateLayoutService.updatePageLayoutsByPageId(clonedPage.getId()))
// 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))
@ -399,63 +356,6 @@ public class ApplicationForkingServiceCEImpl implements ApplicationForkingServic
.collectList();
}
private Flux<NewPage> updateActionAndCollectionsIdsInForkedPages(
List<NewPage> clonedPages, Map<String, String> actionIdsMap, Map<String, String> actionCollectionIdsMap) {
final List<Mono<NewPage>> pageSaveMonos = new ArrayList<>();
for (final NewPage page : clonedPages) {
// If there are no unpublished layouts, there would be no published layouts either.
// Move on to the next page.
if (page.getUnpublishedPage().getLayouts() == null) {
continue;
}
boolean shouldSave = false;
for (final Layout layout : page.getUnpublishedPage().getLayouts()) {
if (layout.getLayoutOnLoadActions() != null) {
shouldSave = updateOnLoadActionsWithNewActionAndCollectionIds(
actionIdsMap, actionCollectionIdsMap, page.getId(), shouldSave, layout);
}
}
if (shouldSave) {
pageSaveMonos.add(newPageRepository.save(page));
}
}
return Flux.concat(pageSaveMonos);
}
private boolean updateOnLoadActionsWithNewActionAndCollectionIds(
Map<String, String> actionIdsMap,
Map<String, String> collectionIdsMap,
String pageId,
boolean shouldSave,
Layout layout) {
for (final Set<DslExecutableDTO> actionSet : layout.getLayoutOnLoadActions()) {
for (final DslExecutableDTO 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 (org.springframework.util.StringUtils.hasLength(srcCollectionId)) {
actionDTO.setDefaultCollectionId(collectionIdsMap.get(actionDTO.getCollectionId()));
actionDTO.setCollectionId(collectionIdsMap.get(actionDTO.getCollectionId()));
}
shouldSave = true;
} else {
log.error(
"Couldn't find cloned action ID for publishedLayoutOnLoadAction {} in page {}",
actionDTO.getId(),
pageId);
}
}
}
return shouldSave;
}
/**
* This function simply creates a clone of the Application object without cloning its children (page and actions)
* Once the new application object is created, it adds the new application's id into the list applicationIds

View File

@ -6,6 +6,7 @@ import com.appsmith.server.applications.base.ApplicationService;
import com.appsmith.server.fork.forkable.ForkableService;
import com.appsmith.server.helpers.ResponseUtils;
import com.appsmith.server.imports.internal.ImportService;
import com.appsmith.server.layouts.UpdateLayoutService;
import com.appsmith.server.newactions.base.NewActionService;
import com.appsmith.server.repositories.ActionCollectionRepository;
import com.appsmith.server.repositories.NewActionRepository;
@ -51,7 +52,8 @@ public class ApplicationForkingServiceImpl extends ApplicationForkingServiceCEIm
ActionCollectionRepository actionCollectionRepository,
NewActionRepository newActionRepository,
WorkspaceRepository workspaceRepository,
ForkableService<Datasource> datasourceForkableService) {
ForkableService<Datasource> datasourceForkableService,
UpdateLayoutService updateLayoutService) {
super(
applicationService,
workspaceService,
@ -73,6 +75,7 @@ public class ApplicationForkingServiceImpl extends ApplicationForkingServiceCEIm
actionCollectionRepository,
newActionRepository,
workspaceRepository,
datasourceForkableService);
datasourceForkableService,
updateLayoutService);
}
}

View File

@ -10,8 +10,6 @@ import com.appsmith.server.dtos.ActionCollectionDTO;
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;
@ -134,16 +132,6 @@ public class DefaultResourcesUtils {
collectionDTODefaultResources.setBranchName(null);
collectionDTODefaultResources.setCollectionId(null);
if (updateActionIds) {
Map<String, String> updatedActionIds = new HashMap<>();
if (!CollectionUtils.isNullOrEmpty(collectionDTO.getDefaultToBranchedActionIdsMap())) {
collectionDTO
.getDefaultToBranchedActionIdsMap()
.values()
.forEach(val -> updatedActionIds.put(val, val));
collectionDTO.setDefaultToBranchedActionIdsMap(updatedActionIds);
}
}
collectionDTO.setDefaultResources(collectionDTODefaultResources);
}
return resource;

View File

@ -265,10 +265,6 @@ public class ResponseUtilsCE {
actionDto.setCollectionId(defaultResourceIds.getCollectionId());
this.updateActionDTOWithDefaultResources(actionDto);
});
collection.getArchivedActions().forEach(actionDto -> {
actionDto.setCollectionId(defaultResourceIds.getCollectionId());
this.updateActionDTOWithDefaultResources(actionDto);
});
return collection;
}

View File

@ -96,6 +96,8 @@ public interface NewActionServiceCE extends CrudService<NewAction, String> {
Flux<ActionDTO> getUnpublishedActions(MultiValueMap<String, String> params, String branchName);
Mono<ActionDTO> deleteGivenNewAction(NewAction toDelete);
Mono<ActionDTO> populateHintMessages(ActionDTO action);
Mono<NewAction> save(NewAction action);
@ -104,6 +106,8 @@ public interface NewActionServiceCE extends CrudService<NewAction, String> {
Flux<NewAction> findByPageId(String pageId);
Mono<NewAction> archiveGivenNewAction(NewAction toDelete);
Mono<NewAction> archive(NewAction newAction);
Mono<NewAction> archiveById(String id);
@ -160,4 +164,6 @@ public interface NewActionServiceCE extends CrudService<NewAction, String> {
void updateDefaultResourcesInAction(NewAction newAction);
Mono<Void> saveLastEditInformationInParent(ActionDTO actionDTO);
Flux<NewAction> findByCollectionIdAndViewMode(String collectionId, boolean viewMode, AclPermission aclPermission);
}

View File

@ -858,80 +858,49 @@ public class NewActionServiceCEImpl extends BaseService<NewActionRepository, New
.findById(id, newActionDeletePermission)
.switchIfEmpty(
Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.ACTION, id)));
return actionMono
.flatMap(toDelete -> {
Mono<NewAction> newActionMono;
return actionMono.flatMap(this::deleteGivenNewAction);
}
// Using the name field to determine if the action was ever published. In case of never published
// action, publishedAction would exist with empty datasource and default fields.
if (toDelete.getPublishedAction() != null
&& toDelete.getPublishedAction().getName() != null) {
toDelete.getUnpublishedAction().setDeletedAt(Instant.now());
newActionMono = repository
.save(toDelete)
.zipWith(Mono.defer(() -> {
final ActionDTO action = toDelete.getUnpublishedAction();
if (action.getDatasource() != null
&& action.getDatasource().getId() != null) {
return datasourceService.findById(
action.getDatasource().getId());
} else {
return Mono.justOrEmpty(action.getDatasource());
}
}))
.flatMap(zippedActions -> {
final Datasource datasource = zippedActions.getT2();
final NewAction newAction1 = zippedActions.getT1();
final Map<String, Object> data =
this.getAnalyticsProperties(newAction1, datasource);
final Map<String, Object> eventData = Map.of(
FieldName.APP_MODE,
ApplicationMode.EDIT.toString(),
FieldName.ACTION,
newAction1);
data.put(FieldName.EVENT_DATA, eventData);
@Override
public Mono<ActionDTO> deleteGivenNewAction(NewAction toDelete) {
Mono<NewAction> newActionMono;
return analyticsService
.sendArchiveEvent(newAction1, data)
.thenReturn(zippedActions.getT1());
})
.thenReturn(toDelete);
} else {
// This action was never published. This document can be safely archived
newActionMono = repository
.archive(toDelete)
.zipWith(Mono.defer(() -> {
final ActionDTO action = toDelete.getUnpublishedAction();
if (action.getDatasource() != null
&& action.getDatasource().getId() != null) {
return datasourceService.findById(
action.getDatasource().getId());
} else {
return Mono.justOrEmpty(action.getDatasource());
}
}))
.flatMap(zippedActions -> {
final Datasource datasource = zippedActions.getT2();
final NewAction newAction1 = zippedActions.getT1();
final Map<String, Object> data =
this.getAnalyticsProperties(newAction1, datasource);
final Map<String, Object> eventData = Map.of(
FieldName.APP_MODE,
ApplicationMode.EDIT.toString(),
FieldName.ACTION,
newAction1);
data.put(FieldName.EVENT_DATA, eventData);
// Using the name field to determine if the action was ever published. In case of never published
// action, publishedAction would exist with empty datasource and default fields.
if (toDelete.getPublishedAction() != null
&& toDelete.getPublishedAction().getName() != null) {
toDelete.getUnpublishedAction().setDeletedAt(Instant.now());
newActionMono = repository
.save(toDelete)
.zipWith(Mono.defer(() -> {
final ActionDTO action = toDelete.getUnpublishedAction();
if (action.getDatasource() != null
&& action.getDatasource().getId() != null) {
return datasourceService.findById(
action.getDatasource().getId());
} else {
return Mono.justOrEmpty(action.getDatasource());
}
}))
.flatMap(zippedActions -> {
final Datasource datasource = zippedActions.getT2();
final NewAction newAction1 = zippedActions.getT1();
final Map<String, Object> data = this.getAnalyticsProperties(newAction1, datasource);
final Map<String, Object> eventData = Map.of(
FieldName.APP_MODE, ApplicationMode.EDIT.toString(), FieldName.ACTION, newAction1);
data.put(FieldName.EVENT_DATA, eventData);
return analyticsService
.sendDeleteEvent(newAction1, data)
.thenReturn(zippedActions.getT1());
})
.thenReturn(toDelete);
}
return analyticsService
.sendArchiveEvent(newAction1, data)
.thenReturn(zippedActions.getT1());
})
.thenReturn(toDelete);
} else {
// This action was never published. This document can be safely archived
newActionMono = archiveGivenNewAction(toDelete);
}
return newActionMono;
})
.map(updatedAction -> generateActionByViewMode(updatedAction, false));
return newActionMono.map(updatedAction -> generateActionByViewMode(updatedAction, false));
}
/*
@ -1459,7 +1428,12 @@ public class NewActionServiceCEImpl extends BaseService<NewActionRepository, New
.findById(id)
.switchIfEmpty(
Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.ACTION, id)));
return actionMono.flatMap(toDelete -> repository
return actionMono.flatMap(this::archiveGivenNewAction);
}
@Override
public Mono<NewAction> archiveGivenNewAction(NewAction toDelete) {
return repository
.archive(toDelete)
.zipWith(Mono.defer(() -> {
final ActionDTO action = toDelete.getUnpublishedAction();
@ -1479,7 +1453,7 @@ public class NewActionServiceCEImpl extends BaseService<NewActionRepository, New
return analyticsService.sendDeleteEvent(newAction1, data).thenReturn(zippedActions.getT1());
})
.thenReturn(toDelete));
.thenReturn(toDelete);
}
@Override
@ -1832,4 +1806,10 @@ public class NewActionServiceCEImpl extends BaseService<NewActionRepository, New
// Do nothing as this is already taken care for actions in the context of page
return Mono.empty().then();
}
@Override
public Flux<NewAction> findByCollectionIdAndViewMode(
String collectionId, boolean viewMode, AclPermission aclPermission) {
return repository.findAllByCollectionIds(List.of(collectionId), viewMode, aclPermission);
}
}

View File

@ -8,8 +8,6 @@ import com.appsmith.external.models.DefaultResources;
import com.appsmith.server.clonepage.ClonePageServiceCE;
import com.appsmith.server.domains.NewAction;
import com.appsmith.server.dtos.ClonePageMetaDTO;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.newactions.base.NewActionService;
import com.appsmith.server.services.LayoutActionService;
import com.appsmith.server.solutions.ActionPermission;
@ -18,8 +16,6 @@ import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import static com.appsmith.external.helpers.AppsmithBeanUtils.copyNestedNonNullProperties;
@Service
@ -33,13 +29,23 @@ public class ActionClonePageServiceCEImpl implements ClonePageServiceCE<NewActio
public Mono<Void> cloneEntities(ClonePageMetaDTO clonePageMetaDTO) {
return getCloneableActions(clonePageMetaDTO.getBranchedSourcePageId())
.flatMap(action -> {
String originalActionId = action.getId();
// Set new page id in the actionDTO
final DefaultResources clonedPageDefaultResources =
clonePageMetaDTO.getClonedPageDTO().getDefaultResources();
action.getUnpublishedAction()
.setPageId(clonePageMetaDTO.getClonedPageDTO().getId());
action.getUnpublishedAction().setDefaultResources(clonedPageDefaultResources);
ActionDTO actionDTO = action.getUnpublishedAction();
DefaultResources defaultResources = new DefaultResources();
defaultResources.setPageId(clonedPageDefaultResources.getPageId());
defaultResources.setBranchName(clonedPageDefaultResources.getBranchName());
defaultResources.setApplicationId(clonedPageDefaultResources.getApplicationId());
actionDTO.setDefaultResources(defaultResources);
actionDTO.setPageId(clonePageMetaDTO.getClonedPageDTO().getId());
if (actionDTO.getCollectionId() != null) {
String clonedActionCollectionId =
clonePageMetaDTO.getOldToNewCollectionIds().get(actionDTO.getCollectionId());
actionDTO.setCollectionId(clonedActionCollectionId);
actionDTO.getDefaultResources().setCollectionId(clonedActionCollectionId);
}
/*
* - Now create the new action from the template of the source action.
* - Use CLONE_PAGE context to make sure that page / application clone quirks are
@ -51,42 +57,16 @@ public class ActionClonePageServiceCEImpl implements ClonePageServiceCE<NewActio
// Indicates that source of action creation is clone page action
cloneActionDTO.setSource(ActionCreationSourceTypeEnum.CLONE_PAGE);
copyNestedNonNullProperties(action.getUnpublishedAction(), cloneActionDTO);
return Mono.zip(
layoutActionService
.createAction(cloneActionDTO, eventContext, Boolean.FALSE)
.map(clonedAction -> {
clonePageMetaDTO
.getOldToNewActionIdMap()
.put(action.getId(), clonedAction.getId());
return clonedAction.getId();
}),
Mono.justOrEmpty(originalActionId));
copyNestedNonNullProperties(actionDTO, cloneActionDTO);
return layoutActionService.createAction(cloneActionDTO, eventContext, Boolean.FALSE);
})
.collect(HashMap<String, String>::new, (map, tuple2) -> map.put(tuple2.getT2(), tuple2.getT1()))
.flatMap(oldToClonedActionIdMap -> {
clonePageMetaDTO.setOldToNewActionIdMap(oldToClonedActionIdMap);
return Mono.empty().then();
});
}
@Override
public Mono<Void> updateClonedEntities(ClonePageMetaDTO clonePageMetaDTO) {
return Mono.error(new AppsmithException(AppsmithError.UNSUPPORTED_OPERATION));
.then();
}
protected Flux<NewAction> getCloneableActions(String pageId) {
Flux<NewAction> sourceActionFlux = newActionService
return newActionService
.findByPageId(pageId, actionPermission.getEditPermission())
// Set collection reference in actions to null to reset to the new application's collections later
.map(newAction -> {
if (newAction.getUnpublishedAction() != null) {
newAction.getUnpublishedAction().setCollectionId(null);
}
return newAction;
})
// In case there are no actions in the page being cloned, return empty
.switchIfEmpty(Flux.empty());
return sourceActionFlux;
}
}

View File

@ -84,10 +84,6 @@ public class JsActionRefactoringServiceCEImpl implements EntityRefactoringServic
actionCollectionDTO.setName(
dbActionCollection.getUnpublishedCollection().getName());
actionCollectionDTO.setDefaultToBranchedActionIdsMap(
dbActionCollection.getUnpublishedCollection().getDefaultToBranchedActionIdsMap());
actionCollectionDTO.setDefaultToBranchedArchivedActionIdsMap(
dbActionCollection.getUnpublishedCollection().getDefaultToBranchedArchivedActionIdsMap());
copyNewFieldValuesIntoOldObject(actionCollectionDTO, dbActionCollection.getUnpublishedCollection());
// First perform refactor of the action itself

View File

@ -67,6 +67,8 @@ public interface CustomNewActionRepositoryCE extends AppsmithRepository<NewActio
Flux<NewAction> findAllByApplicationIdsWithoutPermission(List<String> applicationIds, List<String> includeFields);
Flux<NewAction> findAllByCollectionIds(List<String> collectionIds, boolean viewMode, AclPermission aclPermission);
Flux<NewAction> findAllUnpublishedActionsByContextIdAndContextType(
String contextId, CreatorContextType contextType, AclPermission permission, boolean includeJs);

View File

@ -404,6 +404,19 @@ public class CustomNewActionRepositoryCEImpl extends BaseAppsmithRepositoryImpl<
.all();
}
@Override
public Flux<NewAction> findAllByCollectionIds(
List<String> collectionIds, boolean viewMode, AclPermission aclPermission) {
String collectionIdPath;
if (viewMode) {
collectionIdPath = NewAction.Fields.publishedAction_collectionId;
} else {
collectionIdPath = NewAction.Fields.unpublishedAction_collectionId;
}
BridgeQuery<NewAction> q = Bridge.in(collectionIdPath, collectionIds);
return queryBuilder().criteria(q).permission(aclPermission).all();
}
@Override
public Flux<NewAction> findAllUnpublishedActionsByContextIdAndContextType(
String contextId, CreatorContextType contextType, AclPermission permission, boolean includeJs) {

View File

@ -641,10 +641,6 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
return page;
}));
final Flux<ActionCollection> sourceActionCollectionsFlux = getCloneableActionCollections(pageId);
Flux<NewAction> sourceActionFlux = getCloneableActions(pageId);
return sourcePageMono
.flatMap(page -> {
clonePageMetaDTO.setBranchedSourcePageId(page.getId());
@ -703,10 +699,9 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
}
protected Mono<Void> clonePageDependentEntities(ClonePageMetaDTO clonePageMetaDTO) {
return actionClonePageService
return actionCollectionClonePageService
.cloneEntities(clonePageMetaDTO)
.then(Mono.defer(() -> actionCollectionClonePageService.cloneEntities(clonePageMetaDTO)))
.then(Mono.defer(() -> actionCollectionClonePageService.updateClonedEntities(clonePageMetaDTO)));
.then(Mono.defer(() -> actionClonePageService.cloneEntities(clonePageMetaDTO)));
}
protected Mono<PageDTO> updateClonedPageLayout(PageDTO savedPage) {
@ -1527,8 +1522,9 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
private Mono<Boolean> validateDatasourcesForCreatePermission(Mono<Application> applicationMono) {
Flux<BaseDomain> datasourceFlux = applicationMono
.flatMapMany(application ->
newActionRepository.findIdAndDatasourceIdByApplicationIdIn(List.of(application.getId())))
.flatMapMany(application -> newActionRepository.findAllByApplicationIdsWithoutPermission(
List.of(application.getId()),
List.of(NewAction.Fields.id, NewAction.Fields.unpublishedAction_datasource_id)))
.collectList()
.map(actions -> {
return actions.stream()

View File

@ -30,8 +30,6 @@ import org.apache.commons.lang3.StringUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.Instant;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -201,17 +199,11 @@ public class LayoutCollectionServiceCEImpl implements LayoutCollectionServiceCE
.flatMap(tuple -> {
NewPage destinationPage = tuple.getT1();
ActionCollectionDTO actionCollectionDTO = tuple.getT2();
final Map<String, String> actionIds = new HashMap<>();
if (actionCollectionDTO.getDefaultToBranchedActionIdsMap() != null) {
actionIds.putAll(actionCollectionDTO.getDefaultToBranchedActionIdsMap());
}
if (actionCollectionDTO.getDefaultToBranchedArchivedActionIdsMap() != null) {
actionIds.putAll(actionCollectionDTO.getDefaultToBranchedArchivedActionIdsMap());
}
final Flux<ActionDTO> actionUpdatesFlux = Flux.fromIterable(actionIds.values())
.flatMap(actionId -> newActionService.findActionDTObyIdAndViewMode(
actionId, false, actionPermission.getEditPermission()))
final Flux<ActionDTO> actionUpdatesFlux = newActionService
.findByCollectionIdAndViewMode(
actionCollectionDTO.getId(), false, actionPermission.getEditPermission())
.map(newAction -> newActionService.generateActionByViewMode(newAction, false))
.flatMap(actionDTO -> {
actionDTO.setPageId(destinationPageId);
// Update default page ID in actions as per destination page object
@ -336,13 +328,8 @@ public class LayoutCollectionServiceCEImpl implements LayoutCollectionServiceCE
.map(ActionDTO::getId)
.filter(Objects::nonNull)
.collect(Collectors.toUnmodifiableSet());
final Set<String> archivedDefaultActionIds = actionCollectionDTO.getArchivedActions().stream()
.map(ActionDTO::getId)
.filter(Objects::nonNull)
.collect(Collectors.toUnmodifiableSet());
final Set<String> defaultActionIds = new HashSet<>();
defaultActionIds.addAll(validDefaultActionIds);
defaultActionIds.addAll(archivedDefaultActionIds);
final Mono<Map<String, String>> newValidActionIdsMono = branchedActionCollectionMono.flatMap(
branchedActionCollection -> Flux.fromIterable(actionCollectionDTO.getActions())
@ -393,102 +380,28 @@ public class LayoutCollectionServiceCEImpl implements LayoutCollectionServiceCE
.collect(toMap(
actionDTO -> actionDTO.getDefaultResources().getActionId(), ActionDTO::getId)));
final Mono<Map<String, String>> newArchivedActionIdsMono = branchedActionCollectionMono.flatMap(
branchedActionCollection -> Flux.fromIterable(actionCollectionDTO.getArchivedActions())
.flatMap(actionDTO -> {
actionDTO.setCollectionId(branchedActionCollection.getId());
actionDTO.setDeletedAt(Instant.now());
setContextId(branchedActionCollection, actionDTO);
if (actionDTO.getId() == null) {
actionDTO.getDatasource().setWorkspaceId(actionCollectionDTO.getWorkspaceId());
actionDTO.getDatasource().setPluginId(actionCollectionDTO.getPluginId());
actionDTO.getDatasource().setName(FieldName.UNUSED_DATASOURCE);
actionDTO.setFullyQualifiedName(
actionCollectionDTO.getName() + "." + actionDTO.getName());
actionDTO.setDefaultResources(branchedActionCollection.getDefaultResources());
actionDTO.getDefaultResources().setBranchName(branchName);
final String defaultPageId = branchedActionCollection
.getUnpublishedCollection()
.getDefaultResources()
.getPageId();
actionDTO.getDefaultResources().setPageId(defaultPageId);
// actionCollectionService is a new action, we need to create one
return layoutActionService
.createSingleAction(actionDTO, Boolean.TRUE)
// return an empty action so that the filter can remove it from the list
.onErrorResume(throwable -> {
log.debug(
"Failed to create action with name {} for collection: {}",
actionDTO.getName(),
actionCollectionDTO.getName());
log.error(throwable.getMessage());
return Mono.empty();
});
} else {
// Client only knows about the default action ID, fetch branched action id to update the
// action
Mono<String> branchedActionIdMono = StringUtils.isEmpty(branchName)
? Mono.just(actionDTO.getId())
: newActionService
.findByBranchNameAndDefaultActionId(
branchName,
actionDTO.getId(),
false,
actionPermission.getEditPermission())
.map(NewAction::getId);
actionDTO.setId(null);
return branchedActionIdMono.flatMap(
actionId -> layoutActionService.updateSingleAction(actionId, actionDTO));
}
})
.collect(toMap(
actionDTO -> actionDTO.getDefaultResources().getActionId(), ActionDTO::getId)));
// First collect all valid action ids from before, and diff against incoming action ids
return branchedActionCollectionMono
.map(branchedActionCollection -> {
// From the existing collection, if an action id is not referenced at all anymore,
// this means the action has been somehow deleted
final Set<String> oldDefaultActionIds = new HashSet<>();
if (branchedActionCollection.getUnpublishedCollection().getDefaultToBranchedActionIdsMap()
!= null) {
oldDefaultActionIds.addAll(branchedActionCollection
.getUnpublishedCollection()
.getDefaultToBranchedActionIdsMap()
.keySet());
}
if (branchedActionCollection.getUnpublishedCollection().getDefaultToBranchedArchivedActionIdsMap()
!= null) {
oldDefaultActionIds.addAll(branchedActionCollection
.getUnpublishedCollection()
.getDefaultToBranchedArchivedActionIdsMap()
.keySet());
}
return oldDefaultActionIds.stream()
.filter(Objects::nonNull)
.filter(x -> !defaultActionIds.contains(x))
.collect(Collectors.toUnmodifiableSet());
})
.flatMapMany(Flux::fromIterable)
.flatMap(defaultActionId -> newActionService
.findBranchedIdByBranchNameAndDefaultActionId(
branchName, defaultActionId, actionPermission.getEditPermission())
.flatMap(newActionService::deleteUnpublishedAction)
Mono<List<ActionDTO>> deleteNonExistingActionMono = newActionService
.findByCollectionIdAndViewMode(actionCollectionDTO.getId(), false, actionPermission.getEditPermission())
.filter(newAction -> !defaultActionIds.contains(
newAction.getDefaultResources().getActionId()))
.flatMap(x -> newActionService
.deleteGivenNewAction(x)
// return an empty action so that the filter can remove it from the list
.onErrorResume(throwable -> {
log.debug(
"Failed to delete action with id {}, branch {} for collection: {}",
defaultActionId,
x.getDefaultResources().getActionId(),
branchName,
actionCollectionDTO.getName());
log.error(throwable.getMessage());
return Mono.empty();
}))
.then(Mono.zip(newValidActionIdsMono, newArchivedActionIdsMono))
.collectList();
return deleteNonExistingActionMono
.then(newValidActionIdsMono)
.flatMap(tuple -> {
actionCollectionDTO.setDefaultToBranchedActionIdsMap(tuple.getT1());
actionCollectionDTO.setDefaultToBranchedArchivedActionIdsMap(tuple.getT2());
return branchedActionCollectionMono.map(dbActionCollection -> {
actionCollectionDTO.setId(null);
resetContextId(actionCollectionDTO);

View File

@ -1,4 +1,4 @@
package com.appsmith.server.services.ce;
package com.appsmith.server.git;
import com.appsmith.external.dtos.GitBranchDTO;
import com.appsmith.external.dtos.GitStatusDTO;
@ -63,6 +63,7 @@ import com.appsmith.server.services.LayoutCollectionService;
import com.appsmith.server.services.SessionUserService;
import com.appsmith.server.services.UserService;
import com.appsmith.server.services.WorkspaceService;
import com.appsmith.server.services.ce.GitServiceCE;
import com.appsmith.server.solutions.ApplicationPermission;
import com.appsmith.server.solutions.EnvironmentPermission;
import com.appsmith.server.themes.base.ThemeService;
@ -1241,7 +1242,6 @@ public class GitServiceCETest {
actionCollectionDTO.setActions(List.of(action1));
actionCollectionDTO.setPluginType(PluginType.JS);
actionCollectionDTO.setDefaultResources(branchedResources);
actionCollectionDTO.setDefaultToBranchedActionIdsMap(Map.of("branchedId", "collectionId"));
return Mono.zip(
layoutActionService
@ -1329,16 +1329,6 @@ public class GitServiceCETest {
ActionCollectionDTO unpublishedCollection = actionCollection.getUnpublishedCollection();
assertThat(unpublishedCollection.getDefaultToBranchedActionIdsMap())
.hasSize(1);
unpublishedCollection
.getDefaultToBranchedActionIdsMap()
.keySet()
.forEach(key -> assertThat(key)
.isEqualTo(unpublishedCollection
.getDefaultToBranchedActionIdsMap()
.get(key)));
assertThat(unpublishedCollection.getDefaultResources()).isNotNull();
assertThat(unpublishedCollection.getDefaultResources().getPageId())
.isEqualTo(application.getPages().get(0).getId());
@ -2682,11 +2672,6 @@ public class GitServiceCETest {
ActionCollectionDTO unpublishedCollection = actionCollection.getUnpublishedCollection();
assertThat(unpublishedCollection.getDefaultToBranchedActionIdsMap())
.hasSize(1);
unpublishedCollection.getDefaultToBranchedActionIdsMap().forEach((key, value) -> assertThat(key)
.isNotEqualTo(value));
assertThat(unpublishedCollection.getDefaultResources()).isNotNull();
assertThat(unpublishedCollection.getDefaultResources().getPageId())
.isEqualTo(parentApplication.getPages().get(0).getId());

View File

@ -46,7 +46,6 @@ import reactor.test.StepVerifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static com.appsmith.server.services.ce.ApplicationPageServiceCEImpl.EVALUATION_VERSION;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -270,7 +269,6 @@ class RefactoringServiceCEImplTest {
oldActionCollection.setId("testCollectionId");
oldUnpublishedCollection.setPageId("testPageId");
oldUnpublishedCollection.setName("oldName");
oldUnpublishedCollection.setDefaultToBranchedActionIdsMap(Map.of("defaultTestActionId", "testActionId"));
oldActionCollection.setUnpublishedCollection(oldUnpublishedCollection);
oldActionCollection.setDefaultResources(setDefaultResources(oldActionCollection));
oldUnpublishedCollection.setDefaultResources(setDefaultResources(oldUnpublishedCollection));

View File

@ -813,11 +813,9 @@ class RefactoringServiceCETest {
assert createdActionCollectionDTO1 != null;
final Mono<ActionCollection> actionCollectionMono =
actionCollectionService.getById(createdActionCollectionDTO1.getId());
final Optional<String> optional =
createdActionCollectionDTO1.getDefaultToBranchedActionIdsMap().values().stream()
.findFirst();
assert optional.isPresent();
final Mono<NewAction> actionMono = newActionService.findById(optional.get());
final Mono<NewAction> actionMono = newActionService
.findByCollectionIdAndViewMode(createdActionCollectionDTO1.getId(), false, null)
.next();
StepVerifier.create(Mono.zip(actionCollectionMono, actionMono))
.assertNext(tuple -> {

View File

@ -12,23 +12,17 @@ import com.appsmith.server.applications.base.ApplicationService;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.defaultresources.DefaultResourcesService;
import com.appsmith.server.domains.ActionCollection;
import com.appsmith.server.domains.Layout;
import com.appsmith.server.domains.NewAction;
import com.appsmith.server.domains.NewPage;
import com.appsmith.server.dtos.ActionCollectionDTO;
import com.appsmith.server.dtos.ActionCollectionMoveDTO;
import com.appsmith.server.dtos.LayoutDTO;
import com.appsmith.server.dtos.PageDTO;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.helpers.ObjectMapperUtils;
import com.appsmith.server.helpers.ResponseUtils;
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;
import com.appsmith.server.repositories.ActionCollectionRepository;
import com.appsmith.server.repositories.ce.params.QueryAllParams;
import com.appsmith.server.solutions.ActionPermission;
import com.appsmith.server.solutions.ActionPermissionImpl;
import com.appsmith.server.solutions.ApplicationPermission;
@ -39,7 +33,6 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.validation.Validator;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONObject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -54,18 +47,14 @@ import reactor.test.StepVerifier;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.doReturn;
@ExtendWith(SpringExtension.class)
@Slf4j
@ -477,6 +466,10 @@ public class ActionCollectionServiceImplTest {
Mockito.when(newPageService.findById(Mockito.any(), Mockito.<AclPermission>any()))
.thenReturn(Mono.just(newPage));
Mockito.when(newActionService.findByCollectionIdAndViewMode(
Mockito.anyString(), Mockito.anyBoolean(), Mockito.any()))
.thenReturn(Flux.empty());
final Mono<ActionCollectionDTO> actionCollectionDTOMono =
layoutCollectionService.updateUnpublishedActionCollection("testId", actionCollectionDTO, null);
@ -489,113 +482,6 @@ public class ActionCollectionServiceImplTest {
.verify();
}
@Test
public void testUpdateUnpublishedActionCollection_withModifiedCollection_returnsValidCollection()
throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
ObjectMapperUtils objectMapperUtils = new ObjectMapperUtils(objectMapper);
final JsonNode jsonNode = objectMapperUtils.readFromFile(mockObjects, Views.Public.class, JsonNode.class);
String actionCollectionString =
objectMapperUtils.writeAsString(jsonNode.get("actionCollectionWithAction"), Views.Public.class);
final ActionCollection actionCollection =
objectMapperUtils.readFromString(actionCollectionString, Views.Public.class, ActionCollection.class);
String actionCollectionDTOWithModifiedActionsString = objectMapperUtils.writeAsString(
jsonNode.get("actionCollectionDTOWithModifiedActions"), Views.Public.class);
final ActionCollectionDTO modifiedActionCollectionDTO = objectMapperUtils.readFromString(
actionCollectionDTOWithModifiedActionsString, Views.Public.class, ActionCollectionDTO.class);
String actionCollectionAfterModifiedActionsString = objectMapperUtils.writeAsString(
jsonNode.get("actionCollectionAfterModifiedActions"), Views.Public.class);
final ActionCollection modifiedActionCollection = objectMapperUtils.readFromString(
actionCollectionAfterModifiedActionsString, Views.Public.class, ActionCollection.class);
final ActionCollectionDTO unpublishedCollection = modifiedActionCollection.getUnpublishedCollection();
unpublishedCollection.setDefaultToBranchedActionIdsMap(
Map.of("defaultTestActionId1", "testActionId1", "defaultTestActionId3", "testActionId3"));
unpublishedCollection.setDefaultToBranchedArchivedActionIdsMap(Map.of("defaultTestActionId2", "testActionId2"));
actionCollection.setDefaultResources(setDefaultResources(actionCollection));
modifiedActionCollection.setDefaultResources(actionCollection.getDefaultResources());
modifiedActionCollectionDTO.setDefaultResources(setDefaultResources(modifiedActionCollectionDTO));
unpublishedCollection.setDefaultResources(setDefaultResources(unpublishedCollection));
final Instant archivedAfter = Instant.now();
Map<String, ActionDTO> updatedActions = new HashMap<>();
Mockito.when(layoutActionService.updateSingleAction(Mockito.any(), Mockito.any()))
.thenAnswer(invocation -> {
final ActionDTO argument = (ActionDTO) invocation.getArguments()[1];
DefaultResources defaultResources = new DefaultResources();
defaultResources.setActionId((String) invocation.getArguments()[0]);
argument.setDefaultResources(defaultResources);
argument.setId(defaultResources.getActionId());
updatedActions.put(argument.getId(), argument);
return Mono.just(argument);
});
Mockito.when(newActionService.deleteUnpublishedAction(Mockito.any())).thenAnswer(invocation -> {
final ActionDTO argument = (ActionDTO) invocation.getArguments()[1];
return Mono.just(argument);
});
final QueryAllParams<ActionCollection> params = Mockito.spy(new QueryAllParams<>(null));
doReturn(Mono.just(1)).when(params).updateFirst(Mockito.<ActionCollection>any());
Mockito.when(actionCollectionRepository.queryBuilder()).thenReturn(params);
Mockito.when(actionCollectionRepository.findById(Mockito.anyString(), Mockito.<AclPermission>any()))
.thenReturn(Mono.just(actionCollection));
Mockito.when(actionCollectionRepository.findById(Mockito.anyString()))
.thenReturn(Mono.just(modifiedActionCollection));
Mockito.when(newActionService.findActionDTObyIdAndViewMode(Mockito.any(), Mockito.any(), Mockito.any()))
.thenAnswer(invocation -> {
String id = (String) invocation.getArguments()[0];
return Mono.just(updatedActions.get(id));
});
Mockito.when(responseUtils.updateCollectionDTOWithDefaultResources(Mockito.any()))
.thenReturn(modifiedActionCollectionDTO);
final NewPage newPage = objectMapper.convertValue(jsonNode.get("newPage"), NewPage.class);
Mockito.when(newPageService.findByBranchNameAndDefaultPageId(Mockito.any(), Mockito.any(), Mockito.any()))
.thenReturn(Mono.just(newPage));
Mockito.when(newPageService.findById(Mockito.any(), Mockito.<AclPermission>any()))
.thenReturn(Mono.just(newPage));
Mockito.when(actionCollectionRepository.setUserPermissionsInObject(Mockito.any()))
.thenReturn(Mono.just(modifiedActionCollection));
Mockito.when(updateLayoutService.updatePageLayoutsByPageId(Mockito.anyString()))
.thenAnswer(invocationOnMock -> {
return Mono.just(actionCollection.getUnpublishedCollection().getPageId());
});
final Mono<ActionCollectionDTO> actionCollectionDTOMono =
layoutCollectionService.updateUnpublishedActionCollection(
"testCollectionId", modifiedActionCollectionDTO, null);
StepVerifier.create(actionCollectionDTOMono)
.assertNext(actionCollectionDTO1 -> {
assertEquals(2, actionCollectionDTO1.getActions().size());
assertEquals(1, actionCollectionDTO1.getArchivedActions().size());
assertTrue(actionCollectionDTO1.getActions().stream()
.map(ActionDTO::getId)
.collect(Collectors.toSet())
.containsAll(Set.of("testActionId1", "testActionId3")));
assertEquals(
"testActionId2",
actionCollectionDTO1.getArchivedActions().get(0).getId());
assertTrue(archivedAfter.isBefore(
actionCollectionDTO1.getArchivedActions().get(0).getDeletedAt()));
})
.verifyComplete();
}
@Test
public void testDeleteUnpublishedActionCollection_withInvalidId_throwsError() {
Mockito.when(actionCollectionRepository.findById(Mockito.any(), Mockito.<Optional<AclPermission>>any()))
@ -631,6 +517,10 @@ public class ActionCollectionServiceImplTest {
Mockito.when(actionCollectionRepository.findById(Mockito.any(), Mockito.<Optional<AclPermission>>any()))
.thenReturn(Mono.just(actionCollection));
Mockito.when(newActionService.findByCollectionIdAndViewMode(
Mockito.anyString(), Mockito.anyBoolean(), Mockito.any()))
.thenReturn(Flux.empty());
Mockito.when(actionCollectionRepository.save(Mockito.any())).thenAnswer(invocation -> {
final ActionCollection argument = (ActionCollection) invocation.getArguments()[0];
return Mono.just(argument);
@ -662,8 +552,6 @@ public class ActionCollectionServiceImplTest {
.writeValueAsString(jsonNode.get("actionCollectionWithAction")),
ActionCollection.class);
ActionCollectionDTO unpublishedCollection = actionCollection.getUnpublishedCollection();
unpublishedCollection.setDefaultToBranchedActionIdsMap(
Map.of("defaultTestActionId1", "testActionId1", "defaultTestActionId2", "testActionId2"));
actionCollection.setDefaultResources(setDefaultResources(actionCollection));
unpublishedCollection.setDefaultResources(setDefaultResources(unpublishedCollection));
Instant deletedAt = Instant.now();
@ -671,9 +559,15 @@ public class ActionCollectionServiceImplTest {
Mockito.when(actionCollectionRepository.findById(Mockito.any(), Mockito.<Optional<AclPermission>>any()))
.thenReturn(Mono.just(actionCollection));
Mockito.when(newActionService.deleteUnpublishedActionWithOptionalPermission(Mockito.any(), Mockito.any()))
.thenReturn(Mono.just(
actionCollection.getUnpublishedCollection().getActions().get(0)));
ActionDTO actionDTO =
actionCollection.getUnpublishedCollection().getActions().get(0);
NewAction newAction = new NewAction();
newAction.setUnpublishedAction(actionDTO);
Mockito.when(newActionService.findByCollectionIdAndViewMode(
Mockito.anyString(), Mockito.anyBoolean(), Mockito.any()))
.thenReturn(Flux.just(newAction));
Mockito.when(newActionService.deleteGivenNewAction(Mockito.any())).thenReturn(Mono.just(actionDTO));
Mockito.when(actionCollectionRepository.save(Mockito.any())).thenAnswer(invocation -> {
final ActionCollection argument = (ActionCollection) invocation.getArguments()[0];
@ -716,6 +610,16 @@ public class ActionCollectionServiceImplTest {
Mockito.when(actionCollectionRepository.findById(Mockito.any(), Mockito.<Optional<AclPermission>>any()))
.thenReturn(Mono.just(actionCollection));
ActionDTO actionDTO =
actionCollection.getUnpublishedCollection().getActions().get(0);
NewAction newAction = new NewAction();
newAction.setUnpublishedAction(actionDTO);
Mockito.when(newActionService.findByCollectionIdAndViewMode(
Mockito.anyString(), Mockito.anyBoolean(), Mockito.any()))
.thenReturn(Flux.just(newAction));
Mockito.when(newActionService.archiveGivenNewAction(Mockito.any())).thenReturn(Mono.just(newAction));
Mockito.when(actionCollectionRepository.findById(Mockito.anyString())).thenReturn(Mono.just(actionCollection));
Mockito.when(actionCollectionRepository.archive(Mockito.any())).thenReturn(Mono.empty());
@ -742,10 +646,6 @@ public class ActionCollectionServiceImplTest {
.writerWithView(Views.Public.class)
.writeValueAsString(jsonNode.get("actionCollectionWithAction")),
ActionCollection.class);
actionCollection
.getUnpublishedCollection()
.setDefaultToBranchedActionIdsMap(
Map.of("defaultTestActionId1", "testActionId1", "defaultTestActionId2", "testActionId2"));
actionCollection.setPublishedCollection(null);
DefaultResources resources = new DefaultResources();
resources.setApplicationId("testApplicationId");
@ -758,6 +658,16 @@ public class ActionCollectionServiceImplTest {
Mockito.when(actionCollectionRepository.findById(Mockito.any(), Mockito.<Optional<AclPermission>>any()))
.thenReturn(Mono.just(actionCollection));
ActionDTO actionDTO =
actionCollection.getUnpublishedCollection().getActions().get(0);
NewAction newAction = new NewAction();
newAction.setUnpublishedAction(actionDTO);
Mockito.when(newActionService.findByCollectionIdAndViewMode(
Mockito.anyString(), Mockito.anyBoolean(), Mockito.any()))
.thenReturn(Flux.just(newAction));
Mockito.when(newActionService.archiveGivenNewAction(Mockito.any())).thenReturn(Mono.just(newAction));
Mockito.when(actionCollectionRepository.findById(Mockito.anyString())).thenReturn(Mono.just(actionCollection));
Mockito.when(newActionService.archiveById(Mockito.any())).thenReturn(Mono.just(new NewAction()));
@ -772,90 +682,6 @@ public class ActionCollectionServiceImplTest {
.verifyComplete();
}
@Test
public void testMoveCollection_toValidPage_returnsCollection() throws IOException {
final ActionCollectionMoveDTO actionCollectionMoveDTO = new ActionCollectionMoveDTO();
actionCollectionMoveDTO.setCollectionId("testCollectionId");
actionCollectionMoveDTO.setDestinationPageId("newPageId");
final ActionCollection actionCollection = new ActionCollection();
final ActionCollectionDTO unpublishedCollection = new ActionCollectionDTO();
unpublishedCollection.setPageId("oldPageId");
unpublishedCollection.setName("collectionName");
unpublishedCollection.setDefaultResources(setDefaultResources(unpublishedCollection));
unpublishedCollection.setDefaultToBranchedActionIdsMap(Map.of("defaultTestActionId", "testActionId"));
actionCollection.setUnpublishedCollection(unpublishedCollection);
actionCollection.setDefaultResources(setDefaultResources(actionCollection));
unpublishedCollection.setDefaultResources(setDefaultResources(unpublishedCollection));
ActionDTO action = new ActionDTO();
action.setName("testAction");
DefaultResources actionResources = new DefaultResources();
actionResources.setActionId("testAction");
actionResources.setPageId("newPageId");
action.setDefaultResources(actionResources);
Mockito.when(actionCollectionRepository.findById(Mockito.any(), Mockito.<AclPermission>any()))
.thenReturn(Mono.just(actionCollection));
Mockito.when(newActionService.findActionDTObyIdAndViewMode(Mockito.any(), Mockito.anyBoolean(), Mockito.any()))
.thenReturn(Mono.just(action));
Mockito.when(newActionService.updateUnpublishedAction(Mockito.any(), Mockito.any()))
.thenReturn(Mono.just(new ActionDTO()));
Mockito.when(actionCollectionRepository.findById(Mockito.anyString())).thenReturn(Mono.just(actionCollection));
final QueryAllParams<ActionCollection> params = Mockito.spy(new QueryAllParams<>(null));
doReturn(Mono.just(1)).when(params).updateFirst(Mockito.<ActionCollection>any());
Mockito.when(actionCollectionRepository.queryBuilder()).thenReturn(params);
PageDTO oldPageDTO = new PageDTO();
oldPageDTO.setId("oldPageId");
oldPageDTO.setLayouts(List.of(new Layout()));
PageDTO newPageDTO = new PageDTO();
newPageDTO.setId("newPageId");
newPageDTO.setLayouts(List.of(new Layout()));
ObjectMapper objectMapper = new ObjectMapper();
final JsonNode jsonNode = objectMapper.readValue(mockObjects, JsonNode.class);
final NewPage newPage = objectMapper.convertValue(jsonNode.get("newPage"), NewPage.class);
DefaultResources pageDefaultResources = new DefaultResources();
pageDefaultResources.setPageId(newPage.getId());
newPage.setDefaultResources(pageDefaultResources);
Mockito.when(newPageService.findPageById(Mockito.any(), Mockito.any(), Mockito.anyBoolean()))
.thenReturn(Mono.just(oldPageDTO))
.thenReturn(Mono.just(newPageDTO));
Mockito.when(newPageService.findById(Mockito.any(), Mockito.<AclPermission>any()))
.thenReturn(Mono.just(newPage));
LayoutDTO layout = new LayoutDTO();
final JSONObject jsonObject = new JSONObject();
jsonObject.put("key", "value");
layout.setDsl(jsonObject);
Mockito.when(updateLayoutService.unescapeMongoSpecialCharacters(Mockito.any()))
.thenReturn(jsonObject);
Mockito.when(updateLayoutService.updateLayout(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any()))
.thenReturn(Mono.just(layout));
Mockito.when(actionCollectionRepository.setUserPermissionsInObject(Mockito.any()))
.thenReturn(Mono.just(actionCollection));
final Mono<ActionCollectionDTO> actionCollectionDTOMono =
layoutCollectionService.moveCollection(actionCollectionMoveDTO);
StepVerifier.create(actionCollectionDTOMono)
.assertNext(actionCollectionDTO -> {
assertEquals("newPageId", actionCollectionDTO.getPageId());
})
.verifyComplete();
}
@Test
public void testGenerateActionCollectionByViewModeTestTransientFields() {
ActionCollection actionCollection = new ActionCollection();

View File

@ -18,6 +18,7 @@ import com.appsmith.server.domains.Plugin;
import com.appsmith.server.domains.User;
import com.appsmith.server.domains.Workspace;
import com.appsmith.server.dtos.ActionCollectionDTO;
import com.appsmith.server.dtos.ActionCollectionMoveDTO;
import com.appsmith.server.dtos.ActionCollectionViewDTO;
import com.appsmith.server.dtos.EntityType;
import com.appsmith.server.dtos.LayoutDTO;
@ -277,6 +278,52 @@ public class ActionCollectionServiceTest {
.verifyComplete();
}
@Test
@WithUserDetails(value = "api_user")
public void testMoveActionCollection_whenMovedAcrossPages_thenContainsNewPageId() {
Application application = new Application();
application.setName(UUID.randomUUID().toString());
Application createdApplication = applicationPageService
.createApplication(application, workspaceId)
.block();
PageDTO newPageDTO = new PageDTO();
newPageDTO.setName("newPage");
newPageDTO.setApplicationId(createdApplication.getId());
newPageDTO.setLayouts(List.of(new Layout()));
PageDTO newPageRes = applicationPageService.createPage(newPageDTO).block();
assert createdApplication != null;
final String pageId = createdApplication.getPages().get(0).getId();
ActionCollectionDTO actionCollectionDTO = new ActionCollectionDTO();
actionCollectionDTO.setName("testActionCollectionSoftDeleted");
actionCollectionDTO.setApplicationId(createdApplication.getId());
actionCollectionDTO.setWorkspaceId(createdApplication.getWorkspaceId());
actionCollectionDTO.setPageId(pageId);
actionCollectionDTO.setPluginId(datasource.getPluginId());
actionCollectionDTO.setPluginType(PluginType.JS);
actionCollectionDTO.setDeletedAt(Instant.now());
layoutCollectionService.createCollection(actionCollectionDTO, null).block();
ActionCollection createdActionCollection = actionCollectionRepository
.findByApplicationId(createdApplication.getId(), READ_ACTIONS, null)
.blockFirst();
final ActionCollectionMoveDTO actionCollectionMoveDTO = new ActionCollectionMoveDTO();
actionCollectionMoveDTO.setCollectionId(createdActionCollection.getId());
actionCollectionMoveDTO.setDestinationPageId(newPageRes.getId());
final Mono<ActionCollectionDTO> actionCollectionDTOMono =
layoutCollectionService.moveCollection(actionCollectionMoveDTO);
StepVerifier.create(actionCollectionDTOMono)
.assertNext(res -> {
assertThat(res.getPageId()).isEqualTo(newPageRes.getId());
})
.verifyComplete();
}
@Test
@WithUserDetails(value = "api_user")
public void createValidActionCollectionAndCheckPermissions() {

View File

@ -38,6 +38,7 @@ import com.appsmith.server.dtos.ApplicationAccessDTO;
import com.appsmith.server.dtos.ApplicationJson;
import com.appsmith.server.dtos.ApplicationPagesDTO;
import com.appsmith.server.dtos.InviteUsersDTO;
import com.appsmith.server.dtos.LayoutDTO;
import com.appsmith.server.dtos.PageDTO;
import com.appsmith.server.dtos.RecentlyUsedEntityDTO;
import com.appsmith.server.exceptions.AppsmithError;
@ -115,7 +116,7 @@ import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuple3;
import reactor.util.function.Tuple4;
import java.time.Duration;
import java.util.ArrayList;
@ -607,7 +608,7 @@ public class ApplicationServiceCETest {
assertThat(page.getPolicies().stream()
.map(Policy::getPermission)
.collect(Collectors.toSet()))
.containsExactlyInAnyOrder(
.contains(
MANAGE_PAGES.getValue(),
READ_PAGES.getValue(),
PAGE_CREATE_PAGE_ACTIONS.getValue(),
@ -2167,9 +2168,9 @@ public class ApplicationServiceCETest {
.isEqualTo(application.getId());
newPage.getUnpublishedPage().getLayouts().forEach(layout -> {
assertThat(layout.getLayoutOnLoadActions()).hasSize(2);
assertThat(layout.getLayoutOnLoadActions()).hasSize(1);
layout.getLayoutOnLoadActions().forEach(dslActionDTOS -> {
assertThat(dslActionDTOS).hasSize(1);
assertThat(dslActionDTOS).hasSize(2);
dslActionDTOS.forEach(actionDTO -> {
assertThat(actionDTO.getId()).isEqualTo(actionDTO.getDefaultActionId());
if (StringUtils.hasLength(actionDTO.getCollectionId())) {
@ -2193,7 +2194,7 @@ public class ApplicationServiceCETest {
assertThat(action.getDefaultResources()).isNotNull();
assertThat(action.getDefaultResources().getPageId())
.isEqualTo(application.getPages().get(0).getId());
if (!StringUtils.isEmpty(action.getDefaultResources().getCollectionId())) {
if (StringUtils.hasLength(action.getDefaultResources().getCollectionId())) {
assertThat(action.getDefaultResources().getCollectionId())
.isEqualTo(action.getCollectionId());
}
@ -2209,16 +2210,6 @@ public class ApplicationServiceCETest {
ActionCollectionDTO unpublishedCollection = actionCollection.getUnpublishedCollection();
assertThat(unpublishedCollection.getDefaultToBranchedActionIdsMap())
.hasSize(2);
unpublishedCollection
.getDefaultToBranchedActionIdsMap()
.keySet()
.forEach(key -> assertThat(key)
.isEqualTo(unpublishedCollection
.getDefaultToBranchedActionIdsMap()
.get(key)));
assertThat(unpublishedCollection.getDefaultResources()).isNotNull();
assertThat(unpublishedCollection.getDefaultResources().getPageId())
.isEqualTo(application.getPages().get(0).getId());
@ -2325,7 +2316,7 @@ public class ApplicationServiceCETest {
.collectList();
Map<String, List<String>> originalResourceIds = new HashMap<>();
Mono<Application> resultMono = originalApplicationMono
Tuple4<ActionCollectionDTO, ActionDTO, LayoutDTO, Application> tuple4 = originalApplicationMono
.zipWhen(application -> newPageService.findPageById(
application.getPages().get(0).getId(), READ_PAGES, false))
.flatMap(tuple -> {
@ -2429,53 +2420,51 @@ public class ApplicationServiceCETest {
testPage.getId(), testPage.getApplicationId(), layout.getId(), layout),
Mono.just(tuple.getT3()));
})
.flatMap(tuple -> {
List<String> pageIds = new ArrayList<>(), collectionIds = new ArrayList<>();
ActionCollectionDTO collectionDTO = tuple.getT1();
collectionIds.add(collectionDTO.getId());
tuple.getT4().getPages().forEach(page -> pageIds.add(page.getId()));
.block();
originalResourceIds.put("pageIds", pageIds);
originalResourceIds.put("collectionIds", collectionIds);
List<String> pageIds = new ArrayList<>(), collectionIds = new ArrayList<>();
ActionCollectionDTO collectionDTO = tuple4.getT1();
collectionIds.add(collectionDTO.getId());
tuple4.getT4().getPages().forEach(page -> pageIds.add(page.getId()));
String deletedActionIdWithinActionCollection =
String.valueOf(collectionDTO.getDefaultToBranchedActionIdsMap().values().stream()
.findAny()
.orElse(null));
originalResourceIds.put("pageIds", pageIds);
originalResourceIds.put("collectionIds", collectionIds);
return newActionService
.deleteUnpublishedAction(deletedActionIdWithinActionCollection)
.thenMany(newActionService.findAllByApplicationIdAndViewMode(
tuple.getT4().getId(), false, READ_ACTIONS, null))
.collectList()
.flatMap(actionList -> {
List<String> actionIds = actionList.stream()
.map(BaseDomain::getId)
.collect(Collectors.toList());
originalResourceIds.put("actionIds", actionIds);
return applicationPageService.cloneApplication(
tuple.getT4().getId(), null);
});
String deletedActionIdWithinActionCollection = newActionService
.findByCollectionIdAndViewMode(collectionDTO.getId(), false, null)
.blockFirst()
.getId();
Application application1 = newActionService
.deleteUnpublishedAction(deletedActionIdWithinActionCollection)
.thenMany(newActionService.findAllByApplicationIdAndViewMode(
tuple4.getT4().getId(), false, READ_ACTIONS, null))
.collectList()
.flatMap(actionList -> {
List<String> actionIds =
actionList.stream().map(BaseDomain::getId).collect(Collectors.toList());
originalResourceIds.put("actionIds", actionIds);
return applicationPageService.cloneApplication(
tuple4.getT4().getId(), null);
})
.cache();
.block();
StepVerifier.create(resultMono.zipWhen(application -> Mono.zip(
StepVerifier.create(Mono.zip(
newActionService
.findAllByApplicationIdAndViewMode(application.getId(), false, READ_ACTIONS, null)
.findAllByApplicationIdAndViewMode(application1.getId(), false, READ_ACTIONS, null)
.collectList(),
actionCollectionService
.findAllByApplicationIdAndViewMode(application.getId(), false, READ_ACTIONS, null)
.findAllByApplicationIdAndViewMode(application1.getId(), false, READ_ACTIONS, null)
.collectList(),
newPageService
.findNewPagesByApplicationId(application.getId(), READ_PAGES)
.findNewPagesByApplicationId(application1.getId(), READ_PAGES)
.collectList(),
defaultPermissionGroupsMono)))
defaultPermissionGroupsMono))
.assertNext(tuple -> {
Application application = tuple.getT1(); // cloned application
List<NewAction> actionList = tuple.getT2().getT1();
List<ActionCollection> actionCollectionList = tuple.getT2().getT2();
List<NewPage> pageList = tuple.getT2().getT3();
List<PermissionGroup> permissionGroups = tuple.getT2().getT4();
List<NewAction> actionList = tuple.getT1();
List<ActionCollection> actionCollectionList = tuple.getT2();
List<NewPage> pageList = tuple.getT3();
List<PermissionGroup> permissionGroups = tuple.getT4();
PermissionGroup adminPermissionGroup = permissionGroups.stream()
.filter(permissionGroup -> permissionGroup.getName().startsWith(ADMINISTRATOR))
@ -2517,17 +2506,17 @@ public class ApplicationServiceCETest {
viewerPermissionGroup.getId()))
.build();
assertThat(application).isNotNull();
assertThat(application.isAppIsExample()).isFalse();
assertThat(application.getId()).isNotNull();
assertThat(application.getName())
assertThat(application1).isNotNull();
assertThat(application1.isAppIsExample()).isFalse();
assertThat(application1.getId()).isNotNull();
assertThat(application1.getName())
.isEqualTo(
"ApplicationServiceTest-clone-application-deleted-action-within-collection Copy");
assertThat(application.getPolicies()).containsAll(Set.of(manageAppPolicy, readAppPolicy));
assertThat(application.getWorkspaceId()).isEqualTo(workspaceId);
assertThat(application.getModifiedBy()).isEqualTo("api_user");
assertThat(application.getUpdatedAt()).isNotNull();
List<ApplicationPage> pages = application.getPages();
assertThat(application1.getPolicies()).containsAll(Set.of(manageAppPolicy, readAppPolicy));
assertThat(application1.getWorkspaceId()).isEqualTo(workspaceId);
assertThat(application1.getModifiedBy()).isEqualTo("api_user");
assertThat(application1.getUpdatedAt()).isNotNull();
List<ApplicationPage> pages = application1.getPages();
Set<String> pageIdsFromApplication =
pages.stream().map(ApplicationPage::getId).collect(Collectors.toSet());
Set<String> pageIdsFromDb =
@ -2538,7 +2527,7 @@ public class ApplicationServiceCETest {
assertThat(pageList).isNotEmpty();
for (NewPage page : pageList) {
assertThat(page.getPolicies()).containsAll(Set.of(managePagePolicy, readPagePolicy));
assertThat(page.getApplicationId()).isEqualTo(application.getId());
assertThat(page.getApplicationId()).isEqualTo(application1.getId());
}
assertThat(pageList).isNotEmpty();
@ -2546,12 +2535,12 @@ public class ApplicationServiceCETest {
assertThat(newPage.getDefaultResources()).isNotNull();
assertThat(newPage.getDefaultResources().getPageId()).isEqualTo(newPage.getId());
assertThat(newPage.getDefaultResources().getApplicationId())
.isEqualTo(application.getId());
.isEqualTo(application1.getId());
newPage.getUnpublishedPage().getLayouts().forEach(layout -> {
assertThat(layout.getLayoutOnLoadActions()).hasSize(2);
assertThat(layout.getLayoutOnLoadActions()).hasSize(1);
layout.getLayoutOnLoadActions().forEach(dslActionDTOS -> {
assertThat(dslActionDTOS).hasSize(1);
assertThat(dslActionDTOS).hasSize(2);
dslActionDTOS.forEach(actionDTO -> {
assertThat(actionDTO.getId()).isEqualTo(actionDTO.getDefaultActionId());
if (StringUtils.hasLength(actionDTO.getCollectionId())) {
@ -2569,13 +2558,13 @@ public class ApplicationServiceCETest {
assertThat(newAction.getDefaultResources().getActionId())
.isEqualTo(newAction.getId());
assertThat(newAction.getDefaultResources().getApplicationId())
.isEqualTo(application.getId());
.isEqualTo(application1.getId());
ActionDTO action = newAction.getUnpublishedAction();
assertThat(action.getDefaultResources()).isNotNull();
assertThat(action.getDefaultResources().getPageId())
.isEqualTo(application.getPages().get(0).getId());
if (!StringUtils.isEmpty(action.getDefaultResources().getCollectionId())) {
.isEqualTo(application1.getPages().get(0).getId());
if (StringUtils.hasLength(action.getDefaultResources().getCollectionId())) {
assertThat(action.getDefaultResources().getCollectionId())
.isEqualTo(action.getCollectionId());
}
@ -2587,24 +2576,13 @@ public class ApplicationServiceCETest {
assertThat(actionCollection.getDefaultResources().getCollectionId())
.isEqualTo(actionCollection.getId());
assertThat(actionCollection.getDefaultResources().getApplicationId())
.isEqualTo(application.getId());
.isEqualTo(application1.getId());
ActionCollectionDTO unpublishedCollection = actionCollection.getUnpublishedCollection();
// We should have single entry as other action is deleted from the parent application
assertThat(unpublishedCollection.getDefaultToBranchedActionIdsMap())
.hasSize(1);
unpublishedCollection
.getDefaultToBranchedActionIdsMap()
.keySet()
.forEach(key -> assertThat(key)
.isEqualTo(unpublishedCollection
.getDefaultToBranchedActionIdsMap()
.get(key)));
assertThat(unpublishedCollection.getDefaultResources()).isNotNull();
assertThat(unpublishedCollection.getDefaultResources().getPageId())
.isEqualTo(application.getPages().get(0).getId());
.isEqualTo(application1.getPages().get(0).getId());
});
})
.verifyComplete();
@ -2775,7 +2753,7 @@ public class ApplicationServiceCETest {
Application.NavigationSetting appNavigationSetting = new Application.NavigationSetting();
appNavigationSetting.setOrientation("top");
testApplication.getUnpublishedApplicationDetail().setNavigationSetting(appNavigationSetting);
Mono<Tuple3<NewAction, ActionCollection, NewPage>> resultMono = applicationPageService
Mono<Tuple4<NewAction, ActionCollection, NewPage, NewAction>> resultMono = applicationPageService
.createApplication(testApplication, workspaceId)
.flatMap(application -> {
PageDTO page = new PageDTO();
@ -2827,6 +2805,10 @@ public class ApplicationServiceCETest {
.flatMap(tuple1 -> {
ActionDTO savedAction = tuple1.getT1();
ActionCollectionDTO savedActionCollection = tuple1.getT2();
String actionId = savedActionCollection
.getActions()
.get(0)
.getId();
return applicationPageService
.publish(testApplication.getId(), true)
.then(applicationPageService.deleteUnpublishedPage(page.getId()))
@ -2836,24 +2818,18 @@ public class ApplicationServiceCETest {
this.getArchivedResource(savedAction.getId(), NewAction.class),
(Mono<ActionCollection>) this.getArchivedResource(
savedActionCollection.getId(), ActionCollection.class),
(Mono<NewPage>) this.getArchivedResource(page.getId(), NewPage.class)));
(Mono<NewPage>) this.getArchivedResource(page.getId(), NewPage.class),
(Mono<NewAction>) this.getArchivedResource(actionId, NewAction.class)));
});
})
.cache();
Mono<NewAction> archivedActionFromActionCollectionMono = resultMono.flatMap(tuple -> {
final Optional<String> actionId =
tuple.getT2().getUnpublishedCollection().getDefaultToBranchedActionIdsMap().values().stream()
.findFirst();
return (Mono<NewAction>) this.getArchivedResource(actionId.get(), NewAction.class);
});
StepVerifier.create(resultMono.zipWith(archivedActionFromActionCollectionMono))
StepVerifier.create(resultMono)
.assertNext(tuple -> {
NewAction archivedAction = tuple.getT1().getT1();
ActionCollection archivedActionCollection = tuple.getT1().getT2();
NewPage archivedPage = tuple.getT1().getT3();
NewAction archivedActionFromActionCollection = tuple.getT2();
NewAction archivedAction = tuple.getT1();
ActionCollection archivedActionCollection = tuple.getT2();
NewPage archivedPage = tuple.getT3();
NewAction archivedActionFromActionCollection = tuple.getT4();
assertThat(archivedAction.getDeletedAt()).isNotNull();
@ -3747,7 +3723,7 @@ public class ApplicationServiceCETest {
String appName = "deleteApplicationWithPagesAndActions";
testApplication.setName(appName);
Mono<Tuple3<NewAction, ActionCollection, NewPage>> resultMono = applicationPageService
Mono<Tuple4<NewAction, ActionCollection, NewPage, NewAction>> resultMono = applicationPageService
.createApplication(testApplication, workspaceId)
.flatMap(application -> {
PageDTO page = new PageDTO();
@ -3804,29 +3780,31 @@ public class ApplicationServiceCETest {
.findById(page.getApplicationId(), MANAGE_APPLICATIONS)
.flatMap(application ->
applicationPageService.deleteApplication(application.getId()))
.flatMap(ignored -> Mono.zip(
(Mono<NewAction>)
this.getArchivedResource(savedAction.getId(), NewAction.class),
(Mono<ActionCollection>) this.getArchivedResource(
savedActionCollection.getId(), ActionCollection.class),
(Mono<NewPage>) this.getArchivedResource(page.getId(), NewPage.class)));
.flatMap(ignored -> {
final String actionId = savedActionCollection
.getActions()
.get(0)
.getId();
return Mono.zip(
(Mono<NewAction>) this.getArchivedResource(
savedAction.getId(), NewAction.class),
(Mono<ActionCollection>) this.getArchivedResource(
savedActionCollection.getId(), ActionCollection.class),
(Mono<NewPage>)
this.getArchivedResource(page.getId(), NewPage.class),
(Mono<NewAction>)
this.getArchivedResource(actionId, NewAction.class));
});
});
})
.cache();
Mono<NewAction> archivedActionFromActionCollectionMono = resultMono.flatMap(tuple -> {
final Optional<String> actionId =
tuple.getT2().getUnpublishedCollection().getDefaultToBranchedActionIdsMap().values().stream()
.findFirst();
return (Mono<NewAction>) this.getArchivedResource(actionId.get(), NewAction.class);
});
StepVerifier.create(resultMono.zipWith(archivedActionFromActionCollectionMono))
StepVerifier.create(resultMono)
.assertNext(tuple -> {
NewAction archivedAction = tuple.getT1().getT1();
ActionCollection archivedActionCollection = tuple.getT1().getT2();
NewPage archivedPage = tuple.getT1().getT3();
NewAction archivedActionFromActionCollection = tuple.getT2();
NewAction archivedAction = tuple.getT1();
ActionCollection archivedActionCollection = tuple.getT2();
NewPage archivedPage = tuple.getT3();
NewAction archivedActionFromActionCollection = tuple.getT4();
assertThat(archivedAction.getDeletedAt()).isNotNull();

View File

@ -441,16 +441,6 @@ public class ApplicationForkingServiceTests {
ActionCollectionDTO unpublishedCollection = actionCollection.getUnpublishedCollection();
assertThat(unpublishedCollection.getDefaultToBranchedActionIdsMap())
.hasSize(1);
unpublishedCollection
.getDefaultToBranchedActionIdsMap()
.keySet()
.forEach(key -> assertThat(key)
.isEqualTo(unpublishedCollection
.getDefaultToBranchedActionIdsMap()
.get(key)));
assertThat(unpublishedCollection.getDefaultResources()).isNotNull();
assertThat(unpublishedCollection.getDefaultResources().getPageId())
.isEqualTo(application.getPages().get(0).getId());
@ -623,16 +613,6 @@ public class ApplicationForkingServiceTests {
ActionCollectionDTO unpublishedCollection = actionCollection.getUnpublishedCollection();
assertThat(unpublishedCollection.getDefaultToBranchedActionIdsMap())
.hasSize(1);
unpublishedCollection
.getDefaultToBranchedActionIdsMap()
.keySet()
.forEach(key -> assertThat(key)
.isEqualTo(unpublishedCollection
.getDefaultToBranchedActionIdsMap()
.get(key)));
assertThat(unpublishedCollection.getDefaultResources()).isNotNull();
assertThat(unpublishedCollection.getDefaultResources().getPageId())
.isEqualTo(application.getPages().get(0).getId());

View File

@ -51,14 +51,6 @@
"name": "testCollection",
"pageId": "testPageId",
"pluginId": "testPluginId",
"defaultToBranchedActionIdsMap": [
{
"defaultTestActionId1": "testActionId1"
},
{
"defaultTestActionId2": "testActionId2"
}
],
"actions": [
{
"id": "testActionId1"
@ -71,12 +63,7 @@
"publishedCollection": {
"name": "testCollection",
"pageId": "testPageId",
"pluginId": "testPluginId",
"defaultToBranchedActionIdsMap": [
{
"defaultTestActionId1": "testActionId1"
}
]
"pluginId": "testPluginId"
}
},
"actionCollectionDTOWithModifiedActions": {
@ -86,19 +73,6 @@
"name": "testCollection",
"pageId": "testPageId",
"pluginId": "testPluginId",
"defaultToBranchedActionIdsMap": [
{
"defaultTestActionId1": "testActionId1"
},
{
"defaultTestActionId3": "testActionId3"
}
],
"defaultToBranchedArchivedActionIdsMap": [
{
"defaultTestActionId2": "testActionId2"
}
],
"actions": [
{
"id": "testActionId1"
@ -106,11 +80,6 @@
{
"id": "testActionId3"
}
],
"archivedActions": [
{
"id": "testActionId2"
}
]
},
"actionCollectionAfterModifiedActions": {
@ -123,19 +92,6 @@
"name": "testCollection",
"pageId": "testPageId",
"pluginId": "testPluginId",
"defaultToBranchedActionIdsMap": [
{
"defaultTestActionId1": "testActionId1"
},
{
"defaultTestActionId3": "testActionId3"
}
],
"defaultToBranchedArchivedActionIdsMap": [
{
"defaultTestActionId2": "testActionId2"
}
],
"actions": [
{
"id": "testActionId1"
@ -143,22 +99,12 @@
{
"id": "testActionId3"
}
],
"archivedActions": [
{
"id": "testActionId2"
}
]
},
"publishedCollection": {
"name": "testCollection",
"pageId": "testPageId",
"pluginId": "testPluginId",
"defaultToBranchedActionIdsMap": [
{
"defaultTestActionId1": "testActionId1"
}
]
"pluginId": "testPluginId"
}
}
}