feat: Migrate executeOnLoad to runBehavior enum

This commit is contained in:
Ankita Kinger 2025-04-22 20:09:08 +05:30
parent d7d59c63e4
commit a9803cfa55
6 changed files with 169 additions and 0 deletions

View File

@ -0,0 +1,9 @@
package com.appsmith.external.models;
/**
* Enum to define the behavior for running actions
*/
public enum RunBehaviorEnum {
MANUAL, // Action will only run when manually triggered
ON_PAGE_LOAD // Action will run when the page loads
}

View File

@ -15,6 +15,7 @@ import com.appsmith.external.models.Executable;
import com.appsmith.external.models.PluginType;
import com.appsmith.external.models.Policy;
import com.appsmith.external.models.Property;
import com.appsmith.external.models.RunBehaviorEnum;
import com.appsmith.external.views.FromRequest;
import com.appsmith.external.views.Git;
import com.appsmith.external.views.Views;
@ -100,9 +101,17 @@ public class ActionCE_DTO implements Identifiable, Executable {
@JsonView(Views.Public.class)
List<ErrorDTO> errorReports;
/**
* @deprecated This field is deprecated and will be removed in a future release.
* Use runBehavior instead.
*/
@Deprecated
@JsonView({Views.Public.class, FromRequest.class, Git.class})
Boolean executeOnLoad;
@JsonView({Views.Public.class, FromRequest.class, Git.class})
RunBehaviorEnum runBehavior = RunBehaviorEnum.MANUAL;
@JsonView({Views.Public.class, FromRequest.class, Git.class})
Boolean clientSideExecution;

View File

@ -2,6 +2,7 @@ package com.appsmith.server.controllers.ce;
import com.appsmith.external.models.ActionDTO;
import com.appsmith.external.models.ActionExecutionResult;
import com.appsmith.external.models.RunBehaviorEnum;
import com.appsmith.external.views.FromRequest;
import com.appsmith.external.views.Views;
import com.appsmith.server.constants.FieldName;
@ -115,6 +116,20 @@ public class ActionControllerCE {
.map(actions -> new ResponseDTO<>(HttpStatus.OK, actions));
}
@JsonView(Views.Public.class)
@PutMapping("/runBehavior/{branchedActionId}")
public Mono<ResponseDTO<ActionDTO>> setRunBehavior(
@PathVariable String branchedActionId, @RequestParam RunBehaviorEnum behavior) {
log.debug("Going to set run behavior for action id {} to {}", branchedActionId, behavior);
return layoutActionService
.setRunBehavior(branchedActionId, behavior)
.map(action -> new ResponseDTO<>(HttpStatus.OK, action));
}
/**
* @deprecated This endpoint is deprecated. Use /runBehavior/{branchedActionId} instead.
*/
@Deprecated
@JsonView(Views.Public.class)
@PutMapping("/executeOnLoad/{branchedActionId}")
public Mono<ResponseDTO<ActionDTO>> setExecuteOnLoad(

View File

@ -1,6 +1,7 @@
package com.appsmith.server.services.ce;
import com.appsmith.external.models.ActionDTO;
import com.appsmith.external.models.RunBehaviorEnum;
import com.appsmith.server.dtos.ActionMoveDTO;
import com.appsmith.server.dtos.CreateActionMetaDTO;
import reactor.core.publisher.Mono;
@ -17,6 +18,8 @@ public interface LayoutActionServiceCE {
Mono<ActionDTO> setExecuteOnLoad(String id, Boolean isExecuteOnLoad);
Mono<ActionDTO> setRunBehavior(String id, RunBehaviorEnum behavior);
Mono<ActionDTO> createAction(ActionDTO actionDTO);
Mono<ActionDTO> createSingleAction(ActionDTO actionDTO);

View File

@ -6,6 +6,7 @@ import com.appsmith.external.models.ActionDTO;
import com.appsmith.external.models.CreatorContextType;
import com.appsmith.external.models.Datasource;
import com.appsmith.external.models.PluginType;
import com.appsmith.external.models.RunBehaviorEnum;
import com.appsmith.server.acl.AclPermission;
import com.appsmith.server.constants.FieldName;
import com.appsmith.server.datasources.base.DatasourceService;
@ -300,6 +301,42 @@ public class LayoutActionServiceCEImpl implements LayoutActionServiceCE {
action.setUserSetOnLoad(true);
action.setExecuteOnLoad(isExecuteOnLoad);
// Update runBehavior based on executeOnLoad for forward compatibility
if (Boolean.TRUE.equals(isExecuteOnLoad)) {
action.setRunBehavior(RunBehaviorEnum.ON_PAGE_LOAD);
} else {
action.setRunBehavior(RunBehaviorEnum.MANUAL);
}
newAction.setUnpublishedAction(action);
return newActionService.save(newAction).flatMap(savedAction -> updateLayoutService
.updatePageLayoutsByPageId(
savedAction.getUnpublishedAction().getPageId())
.name(UPDATE_PAGE_LAYOUT_BY_PAGE_ID)
.tap(Micrometer.observation(observationRegistry))
.thenReturn(newActionService.generateActionByViewMode(savedAction, false)));
});
}
@Override
public Mono<ActionDTO> setRunBehavior(String id, RunBehaviorEnum behavior) {
return newActionService
.findById(id, actionPermission.getEditPermission())
.switchIfEmpty(Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.ACTION, id)))
.flatMap(newAction -> {
ActionDTO action = newAction.getUnpublishedAction();
action.setUserSetOnLoad(true);
action.setRunBehavior(behavior);
// Update executeOnLoad based on RunBehaviorEnum for backward compatibility
if (RunBehaviorEnum.ON_PAGE_LOAD.equals(behavior)) {
action.setExecuteOnLoad(true);
} else {
action.setExecuteOnLoad(false);
}
newAction.setUnpublishedAction(action);
return newActionService.save(newAction).flatMap(savedAction -> updateLayoutService
@ -386,6 +423,15 @@ public class LayoutActionServiceCEImpl implements LayoutActionServiceCE {
// page or application clone event.
if (!AppsmithEventContextType.CLONE_PAGE.equals(eventContext.getAppsmithEventContextType())) {
actionDTO.setExecuteOnLoad(false);
actionDTO.setRunBehavior(RunBehaviorEnum.MANUAL);
} else {
// For cloned pages, if executeOnLoad is true, set runBehavior to ON_PAGE_LOAD
if (Boolean.TRUE.equals(actionDTO.getExecuteOnLoad())) {
actionDTO.setRunBehavior(RunBehaviorEnum.ON_PAGE_LOAD);
} else {
actionDTO.setRunBehavior(RunBehaviorEnum.MANUAL);
}
}
newAction.setUnpublishedAction(actionDTO);

View File

@ -8,6 +8,7 @@ import com.appsmith.external.models.Datasource;
import com.appsmith.external.models.DatasourceConfiguration;
import com.appsmith.external.models.PluginType;
import com.appsmith.external.models.Property;
import com.appsmith.external.models.RunBehaviorEnum;
import com.appsmith.server.actioncollections.base.ActionCollectionService;
import com.appsmith.server.applications.base.ApplicationService;
import com.appsmith.server.constants.ArtifactType;
@ -1352,4 +1353,90 @@ class LayoutActionServiceTest {
parentDsl.put("children", children);
return parentDsl;
}
@Test
@WithUserDetails(value = "api_user")
void testSetRunBehavior_WhenRunBehaviorChanged_ValuesUpdatedCorrectly() {
Mockito.when(pluginExecutorHelper.getPluginExecutor(Mockito.any()))
.thenReturn(Mono.just(new MockPluginExecutor()));
// Create a new action
ActionDTO action = new ActionDTO();
action.setName("testRunBehaviorAction");
action.setPageId(testPage.getId());
ActionConfiguration actionConfiguration = new ActionConfiguration();
actionConfiguration.setHttpMethod(HttpMethod.GET);
action.setActionConfiguration(actionConfiguration);
action.setDatasource(datasource);
// Create the action and validate default values
ActionDTO createdAction =
layoutActionService.createSingleAction(action, Boolean.FALSE).block();
assertNotNull(createdAction);
assertEquals(RunBehaviorEnum.MANUAL, createdAction.getRunBehavior());
assertEquals(Boolean.FALSE, createdAction.getExecuteOnLoad());
// Test setting runBehavior to ON_PAGE_LOAD
ActionDTO updatedAction = layoutActionService
.setRunBehavior(createdAction.getId(), RunBehaviorEnum.ON_PAGE_LOAD)
.block();
assertNotNull(updatedAction);
assertEquals(RunBehaviorEnum.ON_PAGE_LOAD, updatedAction.getRunBehavior());
assertEquals(Boolean.TRUE, updatedAction.getExecuteOnLoad());
assertEquals(Boolean.TRUE, updatedAction.getUserSetOnLoad());
// Test setting runBehavior back to MANUAL
updatedAction = layoutActionService
.setRunBehavior(createdAction.getId(), RunBehaviorEnum.MANUAL)
.block();
assertNotNull(updatedAction);
assertEquals(RunBehaviorEnum.MANUAL, updatedAction.getRunBehavior());
assertEquals(Boolean.FALSE, updatedAction.getExecuteOnLoad());
assertEquals(Boolean.TRUE, updatedAction.getUserSetOnLoad());
// Ensure the changes were persisted by getting the action again
NewAction savedAction = actionRepository.findById(createdAction.getId()).block();
assertNotNull(savedAction);
assertEquals(RunBehaviorEnum.MANUAL, savedAction.getUnpublishedAction().getRunBehavior());
assertEquals(Boolean.FALSE, savedAction.getUnpublishedAction().getExecuteOnLoad());
}
@Test
@WithUserDetails(value = "api_user")
void testSetExecuteOnLoad_AlsoUpdatesRunBehavior() {
Mockito.when(pluginExecutorHelper.getPluginExecutor(Mockito.any()))
.thenReturn(Mono.just(new MockPluginExecutor()));
// Create a new action
ActionDTO action = new ActionDTO();
action.setName("testExecuteLoadRunBehaviorAction");
action.setPageId(testPage.getId());
ActionConfiguration actionConfiguration = new ActionConfiguration();
actionConfiguration.setHttpMethod(HttpMethod.GET);
action.setActionConfiguration(actionConfiguration);
action.setDatasource(datasource);
// Create the action and validate default values
ActionDTO createdAction =
layoutActionService.createSingleAction(action, Boolean.FALSE).block();
assertNotNull(createdAction);
assertEquals(RunBehaviorEnum.MANUAL, createdAction.getRunBehavior());
assertEquals(Boolean.FALSE, createdAction.getExecuteOnLoad());
// Test setting executeOnLoad to TRUE
ActionDTO updatedAction = layoutActionService
.setExecuteOnLoad(createdAction.getId(), Boolean.TRUE)
.block();
assertNotNull(updatedAction);
assertEquals(RunBehaviorEnum.ON_PAGE_LOAD, updatedAction.getRunBehavior());
assertEquals(Boolean.TRUE, updatedAction.getExecuteOnLoad());
// Test setting executeOnLoad to FALSE
updatedAction = layoutActionService
.setExecuteOnLoad(createdAction.getId(), Boolean.FALSE)
.block();
assertNotNull(updatedAction);
assertEquals(RunBehaviorEnum.MANUAL, updatedAction.getRunBehavior());
assertEquals(Boolean.FALSE, updatedAction.getExecuteOnLoad());
}
}