Skip to content

Commit

Permalink
chore: Action execution changes for modules (#29357)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rishabh Rathod authored Dec 6, 2023
1 parent f8c5b7c commit 6580c60
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 124 deletions.
6 changes: 2 additions & 4 deletions app/client/src/actions/jsPaneActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,8 @@ export const refactorJSCollectionAction = (payload: {
};

export const executeJSFunctionInit = (payload: {
collectionName: string;
collection: JSCollection;
action: JSAction;
collectionId: string;
}) => {
return {
type: ReduxActionTypes.EXECUTE_JS_FUNCTION_INIT,
Expand All @@ -71,9 +70,8 @@ export const executeJSFunctionInit = (payload: {
};

export const startExecutingJSFunction = (payload: {
collectionName: string;
action: JSAction;
collectionId: string;
collection: JSCollection;
from: EventLocation;
}) => {
return {
Expand Down
20 changes: 16 additions & 4 deletions app/client/src/ce/selectors/entitiesSelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import type {
DefaultPlugin,
GenerateCRUDEnabledPluginMap,
} from "api/PluginApi";
import type { JSAction, JSCollection } from "entities/JSCollection";
import type { JSAction } from "entities/JSCollection";
import { APP_MODE } from "entities/App";
import type { ExplorerFileEntity } from "@appsmith/pages/Editor/Explorer/helpers";
import type { ActionValidationConfigMap } from "constants/PropertyControlConstants";
Expand Down Expand Up @@ -673,15 +673,27 @@ export const getActionData = (
return action ? action.data : undefined;
};

export const getJSCollection = (
export const getJSCollection = (state: AppState, actionId: string) => {
const jsaction = find(
state.entities.jsActions,
(a) => a.config.id === actionId,
);
return jsaction && jsaction.config;
};

/**
*
* getJSCollectionFromAllEntities is used to get the js collection from all jsAction entities (including module instance entities) )
*/
export const getJSCollectionFromAllEntities = (
state: AppState,
actionId: string,
): JSCollection | undefined => {
) => {
const jsaction = find(
state.entities.jsActions,
(a) => a.config.id === actionId,
);
return jsaction ? jsaction.config : undefined;
return jsaction && jsaction.config;
};

export function getCurrentPageNameByActionId(
Expand Down
17 changes: 17 additions & 0 deletions app/client/src/ce/utils/actionExecutionUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Action } from "entities/Action";
import type { JSAction, JSCollection } from "entities/JSCollection";

export function getPluginActionNameToDisplay(action: Action) {
return action.name;
}

export function getJSActionPathNameToDisplay(
action: JSAction,
collection: JSCollection,
) {
return collection.name + "." + action.name;
}

export function getJSActionNameToDisplay(action: JSAction) {
return action.name;
}
1 change: 1 addition & 0 deletions app/client/src/ee/utils/actionExecutionUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "ce/utils/actionExecutionUtils";
3 changes: 1 addition & 2 deletions app/client/src/pages/Editor/JSEditor/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,8 @@ function JSEditorForm({
);
dispatch(
startExecutingJSFunction({
collectionName: currentJSCollection.name || "",
action: jsAction,
collectionId: currentJSCollection.id || "",
collection: currentJSCollection,
from: from,
}),
);
Expand Down
5 changes: 2 additions & 3 deletions app/client/src/reducers/entityReducers/jsActionsReducer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -290,13 +290,12 @@ const jsActionsReducer = createReducer(initialState, {
[ReduxActionTypes.EXECUTE_JS_FUNCTION_INIT]: (
state: JSCollectionDataState,
action: ReduxAction<{
collectionName: string;
collectionId: string;
collection: JSCollection;
action: JSAction;
}>,
): JSCollectionDataState =>
state.map((a) => {
if (a.config.id === action.payload.collectionId) {
if (a.config.id === action.payload.collection.id) {
const newData = { ...a.data };
const newIsDirty = { ...a.isDirty };
unset(newData, action.payload.action.id);
Expand Down
129 changes: 68 additions & 61 deletions app/client/src/sagas/ActionExecution/PluginActionSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ import {
getPlugin,
isActionDirty,
isActionSaving,
getJSCollection,
getDatasource,
getJSCollectionFromAllEntities,
} from "@appsmith/selectors/entitiesSelector";
import { getIsGitSyncModalOpen } from "selectors/gitSyncSelectors";
import {
Expand Down Expand Up @@ -130,7 +130,6 @@ import {
UserCancelledActionExecutionError,
} from "sagas/ActionExecution/errorUtils";
import { shouldBeDefined, trimQueryString } from "utils/helpers";
import type { JSCollection } from "entities/JSCollection";
import { requestModalConfirmationSaga } from "sagas/UtilSagas";
import { ModalType } from "reducers/uiReducers/modalActionReducer";
import { getFormNames, getFormValues } from "redux-form";
Expand Down Expand Up @@ -169,6 +168,10 @@ import {
setAttributesToSpan,
startRootSpan,
} from "UITelemetry/generateTraces";
import {
getJSActionPathNameToDisplay,
getPluginActionNameToDisplay,
} from "@appsmith/utils/actionExecutionUtils";

enum ActionResponseDataTypes {
BINARY = "BINARY",
Expand Down Expand Up @@ -1023,71 +1026,74 @@ function* executeOnPageLoadJSAction(pageAction: PageAction) {
const collectionId = pageAction.collectionId;
const pageId: string | undefined = yield select(getCurrentPageId);

if (collectionId) {
const collection: JSCollection = yield select(
getJSCollection,
collectionId,
);
if (!collectionId) return;

if (!collection) {
Sentry.captureException(
new Error(
"Collection present in layoutOnLoadActions but no collection exists ",
),
{
extra: {
collectionId,
actionId: pageAction.id,
pageId,
},
const collection: ReturnType<typeof getJSCollectionFromAllEntities> =
yield select(getJSCollectionFromAllEntities, collectionId);

if (!collection) {
Sentry.captureException(
new Error(
"Collection present in layoutOnLoadActions but no collection exists ",
),
{
extra: {
collectionId,
actionId: pageAction.id,
pageId,
},
);
},
);
return;
}

return;
}
const jsAction = collection.actions.find(
(action) => action.id === pageAction.id,
);
if (!!jsAction) {
if (jsAction.confirmBeforeExecute) {
const jsActionPathNameToDisplay = getJSActionPathNameToDisplay(
jsAction,
collection,
);
const modalPayload = {
name: jsActionPathNameToDisplay,
modalOpen: true,
modalType: ModalType.RUN_ACTION,
};

const jsAction = collection.actions.find(
(action) => action.id === pageAction.id,
);
if (!!jsAction) {
if (jsAction.confirmBeforeExecute) {
const modalPayload = {
name: pageAction.name,
modalOpen: true,
modalType: ModalType.RUN_ACTION,
};
const confirmed: boolean = yield call(
requestModalConfirmationSaga,
modalPayload,
);
if (!confirmed) {
yield put({
type: ReduxActionTypes.RUN_ACTION_CANCELLED,
payload: { id: pageAction.id },
});

const jsActionPathNameToDisplay = getJSActionPathNameToDisplay(
jsAction,
collection,
);

const confirmed: unknown = yield call(
requestModalConfirmationSaga,
modalPayload,
toast.show(
createMessage(ACTION_EXECUTION_CANCELLED, jsActionPathNameToDisplay),
{
kind: "error",
},
);
if (!confirmed) {
yield put({
type: ReduxActionTypes.RUN_ACTION_CANCELLED,
payload: { id: pageAction.id },
});
toast.show(
createMessage(
ACTION_EXECUTION_CANCELLED,
`${collection.name}.${jsAction.name}`,
),
{
kind: "error",
},
);
// Don't proceed to executing the js function
return;
}
// Don't proceed to executing the js function
return;
}
const data = {
collectionName: collection.name,
action: jsAction,
collectionId: collectionId,
isExecuteJSFunc: true,
};

yield call(handleExecuteJSFunctionSaga, data);
}
const data = {
action: jsAction,
collection,
isExecuteJSFunc: true,
};

yield call(handleExecuteJSFunctionSaga, data);
}
}

Expand Down Expand Up @@ -1331,14 +1337,15 @@ function* executePluginActionSaga(
parentSpan?: OtlpSpan,
) {
const actionId = pluginAction.id;
const pluginActionNameToDisplay = getPluginActionNameToDisplay(pluginAction);
parentSpan &&
setAttributesToSpan(parentSpan, {
actionId,
pluginName: pluginAction?.name,
pluginName: pluginActionNameToDisplay,
});
if (pluginAction.confirmBeforeExecute) {
const modalPayload = {
name: pluginAction.name,
name: pluginActionNameToDisplay,
modalOpen: true,
modalType: ModalType.RUN_ACTION,
};
Expand Down
25 changes: 6 additions & 19 deletions app/client/src/sagas/EvaluationsSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ import {
postEvalActionDispatcher,
updateTernDefinitions,
} from "./PostEvaluationSagas";
import type { JSAction } from "entities/JSCollection";
import type { JSAction, JSCollection } from "entities/JSCollection";
import { getAppMode } from "@appsmith/selectors/applicationSelectors";
import { APP_MODE } from "entities/App";
import { get, isEmpty } from "lodash";
Expand Down Expand Up @@ -397,11 +397,8 @@ interface JSFunctionExecutionResponse {
logs?: LogObject[];
}

function* executeAsyncJSFunction(
collectionName: string,
action: JSAction,
collectionId: string,
) {
function* executeAsyncJSFunction(action: JSAction, collection: JSCollection) {
const { id: collectionId, name: collectionName } = collection;
const functionCall = `${collectionName}.${action.name}()`;
const triggerMeta = {
source: {
Expand All @@ -422,27 +419,17 @@ function* executeAsyncJSFunction(
return response;
}

export function* executeJSFunction(
collectionName: string,
action: JSAction,
collectionId: string,
) {
export function* executeJSFunction(action: JSAction, collection: JSCollection) {
const response: {
errors: unknown[];
result: unknown;
logs?: LogObject[];
} = yield call(executeAsyncJSFunction, collectionName, action, collectionId);
} = yield call(executeAsyncJSFunction, action, collection);
const { errors, result } = response;
const isDirty = !!errors.length;

// After every function execution, log execution errors if present
yield call(
handleJSFunctionExecutionErrorLog,
collectionId,
collectionName,
action,
errors,
);
yield call(handleJSFunctionExecutionErrorLog, action, collection, errors);
return { result, isDirty };
}

Expand Down
Loading

0 comments on commit 6580c60

Please sign in to comment.