hunk.code_window:     ],
       openDirection: Directions.DOWN,
       trigger: {
         content: (
           <DropdownTrigger className={props.className}>
             <AutoToolTipComponentWrapper title={selectedValue}>
               {selectedValue}
             </AutoToolTipComponentWrapper>
             <Icon color={Colors.SLATE_GRAY} icon="caret-down" iconSize={16} />
           </DropdownTrigger>
         ),
  
hunk.labels: keep keep keep keep keep replace keep keep keep keep keep
hunk.after_edit:           <AutoToolTipComponentWrapper isCellVisible title={selectedValue}>
  
hunk.file_path: app/client/src/components/designSystems/appsmith/TableComponent/CascadeFields.tsx
hunk.type: replace
file: import {
    ApplicationPayload,
    Page,
    ReduxAction,
    ReduxActionErrorTypes,
    ReduxActionTypes,
  } from "constants/ReduxActionConstants";
  import {
    EventType,
    ExecuteActionPayload,
    ExecuteActionPayloadEvent,
    PageAction,
    RESP_HEADER_DATATYPE,
  } from "constants/AppsmithActionConstants/ActionConstants";
  import * as log from "loglevel";
  import {
    all,
    call,
    put,
    race,
    select,
    take,
    takeEvery,
    takeLatest,
  } from "redux-saga/effects";
  import {
    ActionDescription,
    RunActionPayload,
  } from "entities/DataTree/dataTreeFactory";
  import { executeAction, executeActionError } from "actions/widgetActions";
  import {
    getCurrentApplicationId,
    getCurrentPageId,
    getLayoutOnLoadActions,
    getPageList,
  } from "selectors/editorSelectors";
  import _, { get, isString } from "lodash";
  import AnalyticsUtil, { EventName } from "utils/AnalyticsUtil";
  import history from "utils/history";
  import {
    API_EDITOR_ID_URL,
    API_EDITOR_URL,
    API_EDITOR_URL_WITH_SELECTED_PAGE_ID,
    BUILDER_PAGE_URL,
    convertToQueryParams,
    getApplicationViewerPageURL,
    QUERIES_EDITOR_ID_URL,
    QUERIES_EDITOR_URL,
    INTEGRATION_EDITOR_URL,
  } from "constants/routes";
  import { SAAS_EDITOR_API_ID_URL } from "pages/Editor/SaaSEditor/constants";
  import {
    executeApiActionRequest,
    executeApiActionSuccess,
    executePageLoadActionsComplete,
    showRunActionConfirmModal,
    updateAction,
  } from "actions/actionActions";
  import { Action, PluginType } from "entities/Action";
  import ActionAPI, {
    ActionExecutionResponse,
    ActionResponse,
    ExecuteActionRequest,
    PaginationField,
    Property,
  } from "api/ActionAPI";
  import {
    getAction,
    getAppStoreData,
    getCurrentPageNameByActionId,
    isActionDirty,
    isActionSaving,
  } from "selectors/entitiesSelector";
  import { AppState } from "reducers";
  import { mapToPropList } from "utils/AppsmithUtils";
  import { validateResponse } from "sagas/ErrorSagas";
  import { TypeOptions } from "react-toastify";
  import { DEFAULT_EXECUTE_ACTION_TIMEOUT_MS } from "constants/ApiConstants";
  import {
    updateAppPersistentStore,
    updateAppTransientStore,
  } from "actions/pageActions";
  import { getAppStoreName } from "constants/AppConstants";
  import downloadjs from "downloadjs";
  import Axios from "axios";
  import { getType, isURL, Types } from "utils/TypeHelpers";
  import { Toaster } from "components/ads/Toast";
  import { Variant } from "components/ads/common";
  import PerformanceTracker, {
    PerformanceTransactionName,
  } from "utils/PerformanceTracker";
  import { APP_MODE } from "entities/App";
  import {
    getAppMode,
    getCurrentApplication,
  } from "selectors/applicationSelectors";
  import {
    evaluateDynamicTrigger,
    evaluateActionBindings,
  } from "./EvaluationsSaga";
  import copy from "copy-to-clipboard";
  import {
    createMessage,
    ERROR_ACTION_EXECUTE_FAIL,
    ERROR_API_EXECUTE,
    ERROR_FAIL_ON_PAGE_LOAD_ACTIONS,
    ERROR_WIDGET_DOWNLOAD,
  } from "constants/messages";
  import { EMPTY_RESPONSE } from "components/editorComponents/ApiResponseView";
  
  import localStorage from "utils/localStorage";
  import { getWidgetByName } from "./selectors";
  import {
    resetChildrenMetaProperty,
    resetWidgetMetaProperty,
  } from "actions/metaActions";
  import AppsmithConsole from "utils/AppsmithConsole";
  import { ENTITY_TYPE, PLATFORM_ERROR } from "entities/AppsmithConsole";
  import LOG_TYPE from "entities/AppsmithConsole/logtype";
  import { matchPath } from "react-router";
  import { setDataUrl } from "./PageSagas";
  
  enum ActionResponseDataTypes {
    BINARY = "BINARY",
  }
  
  export enum NavigationTargetType {
    SAME_WINDOW = "SAME_WINDOW",
    NEW_WINDOW = "NEW_WINDOW",
  }
  
  const isValidUrlScheme = (url: string): boolean => {
    return (
      // Standard http call
      url.startsWith("http://") ||
      // Secure http call
      url.startsWith("https://") ||
      // Mail url to directly open email app prefilled
      url.startsWith("mailto:") ||
      // Tel url to directly open phone app prefilled
      url.startsWith("tel:")
    );
  };
  
  function* navigateActionSaga(
    action: {
      pageNameOrUrl: string;
      params: Record<string, string>;
      target?: NavigationTargetType;
    },
    event: ExecuteActionPayloadEvent,
  ) {
    const pageList = yield select(getPageList);
    const applicationId = yield select(getCurrentApplicationId);
    const {
      pageNameOrUrl,
      params,
      target = NavigationTargetType.SAME_WINDOW,
    } = action;
    const page = _.find(
      pageList,
      (page: Page) => page.pageName === pageNameOrUrl,
    );
    if (page) {
      const currentPageId = yield select(getCurrentPageId);
      AnalyticsUtil.logEvent("NAVIGATE", {
        pageName: pageNameOrUrl,
        pageParams: params,
      });
      const appMode = yield select(getAppMode);
      const path =
        appMode === APP_MODE.EDIT
          ? BUILDER_PAGE_URL(applicationId, page.pageId, params)
          : getApplicationViewerPageURL(applicationId, page.pageId, params);
      if (target === NavigationTargetType.SAME_WINDOW) {
        history.push(path);
        if (currentPageId === page.pageId) {
          yield call(setDataUrl);
        }
      } else if (target === NavigationTargetType.NEW_WINDOW) {
        window.open(path, "_blank");
      }
  
      AppsmithConsole.info({
        text: `navigateTo('${page.pageName}') was triggered`,
        state: {
          params,
        },
      });
      if (event.callback) event.callback({ success: true });
    } else {
      AnalyticsUtil.logEvent("NAVIGATE", {
        navUrl: pageNameOrUrl,
      });
      let url = pageNameOrUrl + convertToQueryParams(params);
      // Add a default protocol if it doesn't exist.
      if (!isValidUrlScheme(url)) {
        url = "https://" + url;
      }
      if (target === NavigationTargetType.SAME_WINDOW) {
        window.location.assign(url);
      } else if (target === NavigationTargetType.NEW_WINDOW) {
        window.open(url, "_blank");
      }
      if (event.callback) event.callback({ success: true });
    }
  }
  
  function* storeValueLocally(
    action: { key: string; value: string; persist: boolean },
    event: ExecuteActionPayloadEvent,
  ) {
    try {
      if (action.persist) {
        const appId = yield select(getCurrentApplicationId);
        const appStoreName = getAppStoreName(appId);
        const existingStore = localStorage.getItem(appStoreName) || "{}";
        const parsedStore = JSON.parse(existingStore);
        parsedStore[action.key] = action.value;
        const storeString = JSON.stringify(parsedStore);
        localStorage.setItem(appStoreName, storeString);
        yield put(updateAppPersistentStore(parsedStore));
        AppsmithConsole.info({
          text: `store('${action.key}', '${action.value}', true)`,
        });
      } else {
        const existingStore = yield select(getAppStoreData);
        const newTransientStore = {
          ...existingStore.transient,
          [action.key]: action.value,
        };
        yield put(updateAppTransientStore(newTransientStore));
        AppsmithConsole.info({
          text: `store('${action.key}', '${action.value}', false)`,
        });
      }
      // Wait for an evaluation before completing this trigger effect
      // This makes this trigger work in sync and not trigger
      // another effect till the values are reflected in
      // the dataTree
      yield take(ReduxActionTypes.SET_EVALUATED_TREE);
      if (event.callback) event.callback({ success: true });
    } catch (err) {
      if (event.callback) event.callback({ success: false });
    }
  }
  
  async function downloadSaga(
    action: { data: any; name: string; type: string },
    event: ExecuteActionPayloadEvent,
  ) {
    const displayWidgetDownloadError = (message: any) => {
      return Toaster.show({
        text: createMessage(ERROR_WIDGET_DOWNLOAD, message),
        variant: Variant.danger,
      });
    };
  
    try {
      const { data, name, type } = action;
  
      if (!name) {
        displayWidgetDownloadError("File name was not provided");
        if (event.callback) event.callback({ success: false });
        return;
      }
      const dataType = getType(data);
  
      if (dataType === Types.ARRAY || dataType === Types.OBJECT) {
        const jsonString = JSON.stringify(data, null, 2);
        downloadjs(jsonString, name, type);
        AppsmithConsole.info({
          text: `download('${jsonString}', '${name}', '${type}') was triggered`,
        });
      } else if (dataType === Types.STRING && isURL(data)) {
        // In the event that a url string is supplied, we need to fetch the image with the response type arraybuffer.
        // This also covers the case where the file to be downloaded is Binary.
  
        Axios.get(data, { responseType: "arraybuffer" }).then((res) => {
          downloadjs(res.data, name, type);
          AppsmithConsole.info({
            text: `download('${data}', '${name}', '${type}') was triggered`,
          });
        });
      } else {
        downloadjs(data, name, type);
        AppsmithConsole.info({
          text: `download('${data}', '${name}', '${type}') was triggered`,
        });
      }
  
      if (event.callback) event.callback({ success: true });
    } catch (err) {
      log.error(err);
      displayWidgetDownloadError(err);
      if (event.callback) event.callback({ success: false });
    }
  }
  
  function* copySaga(
    payload: {
      data: string;
      options: { debug: boolean; format: string };
    },
    event: ExecuteActionPayloadEvent,
  ) {
    const result = copy(payload.data, payload.options);
    if (event.callback) {
      if (result) {
        AppsmithConsole.info({
          text: `copyToClipboard('${payload.data}') was triggered`,
        });
  
        event.callback({ success: result });
      }
    }
  }
  
  function* resetWidgetMetaByNameRecursiveSaga(
    payload: { widgetName: string; resetChildren: boolean },
    event: ExecuteActionPayloadEvent,
  ) {
    const fail = (msg: string) => {
      console.error(msg);
      if (event.callback) event.callback({ success: false });
    };
    if (typeof payload.widgetName !== "string") {
      return fail("widgetName needs to be a string");
    }
  
    const widget = yield select(getWidgetByName, payload.widgetName);
    if (!widget) {
      return fail(`widget ${payload.widgetName} not found`);
    }
  
    yield put(resetWidgetMetaProperty(widget.widgetId));
    if (payload.resetChildren) {
      yield put(resetChildrenMetaProperty(widget.widgetId));
    }
  
    AppsmithConsole.info({
      text: `resetWidget('${payload.widgetName}', ${payload.resetChildren}) was triggered`,
    });
  
    if (event.callback) event.callback({ success: true });
  }
  
  function* showAlertSaga(
    payload: { message: string; style?: TypeOptions },
    event: ExecuteActionPayloadEvent,
  ) {
    if (typeof payload.message !== "string") {
      console.error("Toast message needs to be a string");
      if (event.callback) event.callback({ success: false });
      return;
    }
    let variant;
    switch (payload.style) {
      case "info":
        variant = Variant.info;
        break;
      case "success":
        variant = Variant.success;
        break;
      case "warning":
        variant = Variant.warning;
        break;
      case "error":
        variant = Variant.danger;
        break;
    }
    if (payload.style && !variant) {
      console.error(
        "Toast type needs to be a one of " + Object.values(Variant).join(", "),
      );
      if (event.callback) event.callback({ success: false });
      return;
    }
    Toaster.show({
      text: payload.message,
      variant: variant,
    });
    AppsmithConsole.info({
      text: payload.style
        ? `showAlert('${payload.message}', '${payload.style}') was triggered`
        : `showAlert('${payload.message}') was triggered`,
    });
    if (event.callback) event.callback({ success: true });
  }
  
  export const getActionTimeout = (
    state: AppState,
    actionId: string,
  ): number | undefined => {
    const action = _.find(
      state.entities.actions,
      (a) => a.config.id === actionId,
    );
    if (action) {
      const timeout = _.get(
        action,
        "config.actionConfiguration.timeoutInMillisecond",
        DEFAULT_EXECUTE_ACTION_TIMEOUT_MS,
      );
      if (timeout) {
        // Extra timeout padding to account for network calls
        return timeout + 5000;
      }
      return undefined;
    }
    return undefined;
  };
  const createActionExecutionResponse = (
    response: ActionExecutionResponse,
  ): ActionResponse => {
    const payload = response.data;
    if (payload.statusCode === "200 OK" && payload.hasOwnProperty("headers")) {
      const respHeaders = payload.headers;
      if (
        respHeaders.hasOwnProperty(RESP_HEADER_DATATYPE) &&
        respHeaders[RESP_HEADER_DATATYPE].length > 0 &&
        respHeaders[RESP_HEADER_DATATYPE][0] === ActionResponseDataTypes.BINARY &&
        getType(payload.body) === Types.STRING
      ) {
        // Decoding from base64 to handle the binary files because direct
        // conversion of binary files to string causes corruption in the final output
        // this is to only handle the download of binary files
        payload.body = atob(payload.body as string);
      }
    }
    return {
      ...payload,
      ...response.clientMeta,
    };
  };
  const isErrorResponse = (response: ActionExecutionResponse) => {
    return !response.data.isExecutionSuccess;
  };
  
  /**
   * Api1
   * URL: https://example.com/{{Text1.text}}
   * Body: {
   *     "name": "{{this.params.name}}",
   *     "age": {{this.params.age}},
   *     "gender": {{Dropdown1.selectedOptionValue}}
   * }
   *
   * If you call
   * Api1.run(undefined, undefined, { name: "Hetu", age: Input1.text });
   *
   * executionParams is { name: "Hetu", age: Input1.text }
   * bindings is [
   *   "Text1.text",
   *   "Dropdown1.selectedOptionValue",
   *   "this.params.name",
   *   "this.params.age",
   * ]
   *
   * Return will be [
   *   { key: "Text1.text", value: "updateUser" },
   *   { key: "Dropdown1.selectedOptionValue", value: "M" },
   *   { key: "this.params.name", value: "Hetu" },
   *   { key: "this.params.age", value: 26 },
   * ]
   * @param bindings
   * @param executionParams
   */
  export function* evaluateActionParams(
    bindings: string[] | undefined,
    executionParams?: Record<string, any> | string,
  ) {
    if (_.isNil(bindings) || bindings.length === 0) return [];
  
    // Evaluated all bindings of the actions. Pass executionParams if any
    const values: any = yield call(
      evaluateActionBindings,
      bindings,
      executionParams,
    );
  
    // Convert to object and transform non string values
    const actionParams: Record<string, string> = {};
    bindings.forEach((key, i) => {
      let value = values[i];
      if (typeof value === "object") value = JSON.stringify(value);
      actionParams[key] = value;
    });
    return mapToPropList(actionParams);
  }
  
  export function* executeActionSaga(
    apiAction: RunActionPayload,
    event: ExecuteActionPayloadEvent,
  ) {
    const { actionId, onError, onSuccess, params } = apiAction;
    PerformanceTracker.startAsyncTracking(
      PerformanceTransactionName.EXECUTE_ACTION,
      {
        actionId: actionId,
      },
      actionId,
    );
    const appMode = yield select(getAppMode);
    try {
      const api: Action = yield select(getAction, actionId);
      const currentApp: ApplicationPayload = yield select(getCurrentApplication);
      AnalyticsUtil.logEvent("EXECUTE_ACTION", {
        type: api.pluginType,
        name: api.name,
        pageId: api.pageId,
        appId: currentApp.id,
        appMode: appMode,
        appName: currentApp.name,
        isExampleApp: currentApp.appIsExample,
      });
      if (api.confirmBeforeExecute) {
        const confirmed = yield call(confirmRunActionSaga);
        if (!confirmed) {
          if (event.callback) {
            event.callback({ success: false });
          }
          return;
        }
      }
  
      yield put(executeApiActionRequest({ id: apiAction.actionId }));
      const actionParams: Property[] = yield call(
        evaluateActionParams,
        api.jsonPathKeys,
        params,
      );
      const pagination =
        event.type === EventType.ON_NEXT_PAGE
          ? "NEXT"
          : event.type === EventType.ON_PREV_PAGE
          ? "PREV"
          : undefined;
  
      const executeActionRequest: ExecuteActionRequest = {
        actionId: actionId,
        params: actionParams,
        paginationField: pagination,
        viewMode: appMode === APP_MODE.PUBLISHED,
      };
      AppsmithConsole.info({
        text: "Execution started from widget request",
        source: {
          type: ENTITY_TYPE.ACTION,
          name: api.name,
          id: actionId,
        },
        state: api.actionConfiguration,
      });
      const timeout = yield select(getActionTimeout, actionId);
      const response: ActionExecutionResponse = yield ActionAPI.executeAction(
        executeActionRequest,
        timeout,
      );
      const payload = createActionExecutionResponse(response);
      yield put(
        executeApiActionSuccess({
          id: actionId,
          response: payload,
        }),
      );
      if (isErrorResponse(response)) {
        AppsmithConsole.addError({
          id: actionId,
          logType: LOG_TYPE.ACTION_EXECUTION_ERROR,
          text: `Execution failed with status ${response.data.statusCode}`,
          source: {
            type: ENTITY_TYPE.ACTION,
            name: api.name,
            id: actionId,
          },
          state: response.data?.request ?? null,
          messages: [
            {
              message: payload.body as string,
              type: PLATFORM_ERROR.PLUGIN_EXECUTION,
            },
          ],
        });
        PerformanceTracker.stopAsyncTracking(
          PerformanceTransactionName.EXECUTE_ACTION,
          { failed: true },
          actionId,
        );
        if (onError) {
          yield put(
            executeAction({
              dynamicString: onError,
              event: {
                ...event,
                type: EventType.ON_ERROR,
              },
              responseData: [payload.body, params],
            }),
          );
        } else {
          if (event.callback) {
            event.callback({ success: false });
          }
        }
        Toaster.show({
          text: createMessage(ERROR_API_EXECUTE, api.name),
          variant: Variant.danger,
          showDebugButton: true,
        });
      } else {
        PerformanceTracker.stopAsyncTracking(
          PerformanceTransactionName.EXECUTE_ACTION,
          undefined,
          actionId,
        );
        AppsmithConsole.info({
          logType: LOG_TYPE.ACTION_EXECUTION_SUCCESS,
          text: "Executed successfully from widget request",
          timeTaken: response.clientMeta.duration,
          source: {
            type: ENTITY_TYPE.ACTION,
            name: api.name,
            id: actionId,
          },
          state: {
            response: payload.body,
            request: response.data.request,
          },
        });
        if (onSuccess) {
          yield put(
            executeAction({
              dynamicString: onSuccess,
              event: {
                ...event,
                type: EventType.ON_SUCCESS,
              },
              responseData: [payload.body, params],
            }),
          );
        } else {
          if (event.callback) {
            event.callback({ success: true });
          }
        }
      }
      return response;
    } catch (error) {
      const api: Action = yield select(getAction, actionId);
      yield put(
        executeActionError({
          actionId: actionId,
          error,
          data: {
            ...EMPTY_RESPONSE,
            body: "There was an error executing this action",
          },
        }),
      );
      Toaster.show({
        text: createMessage(ERROR_API_EXECUTE, api.name),
        variant: Variant.danger,
        showDebugButton: true,
      });
      if (onError) {
        yield put(
          executeAction({
            dynamicString: `{{${onError}}}`,
            event: {
              ...event,
              type: EventType.ON_ERROR,
            },
            responseData: [],
          }),
        );
      } else {
        if (event.callback) {
          event.callback({ success: false });
        }
      }
    }
  }
  
  function* executeActionTriggers(
    trigger: ActionDescription<any>,
    event: ExecuteActionPayloadEvent,
  ) {
    try {
      switch (trigger.type) {
        case "RUN_ACTION":
          yield call(executeActionSaga, trigger.payload, event);
          break;
        case "NAVIGATE_TO":
          yield call(navigateActionSaga, trigger.payload, event);
          break;
        case "SHOW_ALERT":
          yield call(showAlertSaga, trigger.payload, event);
          break;
        case "SHOW_MODAL_BY_NAME":
          yield put(trigger);
          if (event.callback) event.callback({ success: true });
          break;
        case "CLOSE_MODAL":
          yield put(trigger);
          AppsmithConsole.info({
            text: `closeModal(${trigger.payload.modalName}) was triggered`,
          });
          if (event.callback) event.callback({ success: true });
          break;
        case "STORE_VALUE":
          yield call(storeValueLocally, trigger.payload, event);
          break;
        case "DOWNLOAD":
          yield call(downloadSaga, trigger.payload, event);
          break;
        case "COPY_TO_CLIPBOARD":
          yield call(copySaga, trigger.payload, event);
          break;
        case "RESET_WIDGET_META_RECURSIVE_BY_NAME":
          yield call(resetWidgetMetaByNameRecursiveSaga, trigger.payload, event);
          break;
        default:
          log.error("Trigger type unknown", trigger.type);
      }
    } catch (e) {
      if (event.callback) event.callback({ success: false });
    }
  }
  
  function* executeAppAction(action: ReduxAction<ExecuteActionPayload>) {
    const { dynamicString, event, responseData } = action.payload;
    log.debug({ dynamicString, responseData });
  
    if (dynamicString === undefined) {
      if (event.callback) event.callback({ success: false });
      log.error("Executing undefined action", event);
      return;
    }
  
    const triggers = yield call(
      evaluateDynamicTrigger,
      dynamicString,
      responseData,
    );
  
    log.debug({ triggers });
    if (triggers && triggers.length) {
      yield all(
        triggers.map((trigger: ActionDescription<any>) =>
          call(executeActionTriggers, trigger, event),
        ),
      );
    } else {
      if (event.callback) event.callback({ success: true });
    }
  }
  
  function* runActionShortcutSaga() {
    const location = window.location.pathname;
    const match: any = matchPath(location, {
      path: [
        API_EDITOR_URL(),
        API_EDITOR_ID_URL(),
        QUERIES_EDITOR_URL(),
        QUERIES_EDITOR_ID_URL(),
        API_EDITOR_URL_WITH_SELECTED_PAGE_ID(),
        INTEGRATION_EDITOR_URL(),
        SAAS_EDITOR_API_ID_URL(),
      ],
      exact: true,
      strict: false,
    });
    if (!match || !match.params) return;
    const { apiId, pageId, queryId } = match.params;
    const actionId = apiId || queryId;
    if (!actionId) return;
    const trackerId = apiId
      ? PerformanceTransactionName.RUN_API_SHORTCUT
      : PerformanceTransactionName.RUN_QUERY_SHORTCUT;
    PerformanceTracker.startTracking(trackerId, {
      actionId,
      pageId,
    });
    AnalyticsUtil.logEvent(trackerId as EventName, {
      actionId,
    });
    yield put({
      type: ReduxActionTypes.RUN_ACTION_INIT,
      payload: {
        id: actionId,
      },
    });
  }
  
  function* runActionInitSaga(
    reduxAction: ReduxAction<{
      id: string;
      paginationField: PaginationField;
    }>,
  ) {
    const action = yield select(getAction, reduxAction.payload.id);
  
    if (action.confirmBeforeExecute) {
      const confirmed = yield call(confirmRunActionSaga);
      if (!confirmed) return;
    }
  
    yield put({
      type: ReduxActionTypes.RUN_ACTION_REQUEST,
      payload: reduxAction.payload,
    });
  }
  
  function* runActionSaga(
    reduxAction: ReduxAction<{
      id: string;
      paginationField: PaginationField;
    }>,
  ) {
    try {
      const actionId = reduxAction.payload.id;
      const isSaving = yield select(isActionSaving(actionId));
      const isDirty = yield select(isActionDirty(actionId));
      if (isSaving || isDirty) {
        if (isDirty && !isSaving) {
          yield put(updateAction({ id: actionId }));
        }
        yield take(ReduxActionTypes.UPDATE_ACTION_SUCCESS);
      }
      const actionObject = yield select(getAction, actionId);
      const jsonPathKeys = actionObject.jsonPathKeys;
  
      const { paginationField } = reduxAction.payload;
  
      const params = yield call(evaluateActionParams, jsonPathKeys);
      const timeout = yield select(getActionTimeout, actionId);
      const appMode = yield select(getAppMode);
      const viewMode = appMode === APP_MODE.PUBLISHED;
  
      const datasourceUrl = get(
        actionObject,
        "datasource.datasourceConfiguration.url",
      );
      AppsmithConsole.info({
        text: "Execution started from user request",
        source: {
          type: ENTITY_TYPE.ACTION,
          name: actionObject.name,
          id: actionId,
        },
        state: {
          ...actionObject.actionConfiguration,
          ...(datasourceUrl && {
            url: datasourceUrl,
          }),
        },
      });
  
      const response: ActionExecutionResponse = yield ActionAPI.executeAction(
        {
          actionId,
          params,
          paginationField,
          viewMode,
        },
        timeout,
      );
      const isValidResponse = yield validateResponse(response);
  
      if (isValidResponse) {
        const payload = createActionExecutionResponse(response);
  
        const pageName = yield select(getCurrentPageNameByActionId, actionId);
        let eventName: EventName = "RUN_API";
        if (actionObject.pluginType === PluginType.DB) {
          eventName = "RUN_QUERY";
        }
        if (actionObject.pluginType === PluginType.SAAS) {
          eventName = "RUN_SAAS_API";
        }
  
        AnalyticsUtil.logEvent(eventName, {
          actionId,
          actionName: actionObject.name,
          pageName: pageName,
          responseTime: response.clientMeta.duration,
          apiType: "INTERNAL",
        });
  
        yield put({
          type: ReduxActionTypes.RUN_ACTION_SUCCESS,
          payload: { [actionId]: payload },
        });
        if (payload.isExecutionSuccess) {
          AppsmithConsole.info({
            logType: LOG_TYPE.ACTION_EXECUTION_SUCCESS,
            text: "Executed successfully from user request",
            timeTaken: response.clientMeta.duration,
            source: {
              type: ENTITY_TYPE.ACTION,
              name: actionObject.name,
              id: actionId,
            },
            state: {
              response: payload.body,
              request: response.data.request,
            },
          });
        } else {
          AppsmithConsole.addError({
            id: actionId,
            logType: LOG_TYPE.ACTION_EXECUTION_ERROR,
            text: `Execution failed with status ${response.data.statusCode}`,
            source: {
              type: ENTITY_TYPE.ACTION,
              name: actionObject.name,
              id: actionId,
            },
            messages: [
              {
                message: !isString(payload.body)
                  ? JSON.stringify(payload.body)
                  : payload.body,
                type: PLATFORM_ERROR.PLUGIN_EXECUTION,
              },
            ],
            state: response.data?.request ?? null,
          });
  
          Toaster.show({
            text: createMessage(ERROR_ACTION_EXECUTE_FAIL, actionObject.name),
            variant: Variant.danger,
          });
        }
      } else {
        let error = "An unexpected error occurred";
        if (response.data.body) {
          error = response.data.body.toString();
        }
  
        AppsmithConsole.addError({
          id: actionId,
          logType: LOG_TYPE.ACTION_EXECUTION_ERROR,
          text: `Execution failed with status ${response.data.statusCode} `,
          source: {
            type: ENTITY_TYPE.ACTION,
            name: actionObject.name,
            id: actionId,
          },
          state: response.data?.request ?? null,
        });
  
        yield put({
          type: ReduxActionErrorTypes.RUN_ACTION_ERROR,
          payload: { error, id: reduxAction.payload.id },
        });
      }
    } catch (error) {
      console.error(error);
      yield put({
        type: ReduxActionErrorTypes.RUN_ACTION_ERROR,
        payload: { error, id: reduxAction.payload.id },
      });
    }
  }
  
  function* confirmRunActionSaga() {
    yield put(showRunActionConfirmModal(true));
  
    const { accept } = yield race({
      cancel: take(ReduxActionTypes.CANCEL_RUN_ACTION_CONFIRM_MODAL),
      accept: take(ReduxActionTypes.ACCEPT_RUN_ACTION_CONFIRM_MODAL),
    });
  
    return !!accept;
  }
  
  function* executePageLoadAction(pageAction: PageAction) {
    try {
      PerformanceTracker.startAsyncTracking(
        PerformanceTransactionName.EXECUTE_ACTION,
        {
          actionId: pageAction.id,
        },
        pageAction.id,
        PerformanceTransactionName.EXECUTE_PAGE_LOAD_ACTIONS,
      );
      const pageId = yield select(getCurrentPageId);
      let currentApp: ApplicationPayload = yield select(getCurrentApplication);
      currentApp = currentApp || {};
      yield put(executeApiActionRequest({ id: pageAction.id }));
      const params: Property[] = yield call(
        evaluateActionParams,
        pageAction.jsonPathKeys,
      );
      const appMode = yield select(getAppMode);
      const viewMode = appMode === APP_MODE.PUBLISHED;
      const executeActionRequest: ExecuteActionRequest = {
        actionId: pageAction.id,
        params,
        viewMode,
      };
      AnalyticsUtil.logEvent("EXECUTE_ACTION", {
        type: pageAction.pluginType,
        name: pageAction.name,
        pageId: pageId,
        appMode: appMode,
        appId: currentApp.id,
        onPageLoad: true,
        appName: currentApp.name,
        isExampleApp: currentApp.appIsExample,
      });
      const response: ActionExecutionResponse = yield ActionAPI.executeAction(
        executeActionRequest,
        pageAction.timeoutInMillisecond,
      );
      if (isErrorResponse(response)) {
        let body = _.get(response, "data.body");
        let message = `The action "${pageAction.name}" has failed.`;
        if (body) {
          if (_.isObject(body)) {
            body = JSON.stringify(body);
          }
          message += `\nERROR: "${body}"`;
        }
  
        AppsmithConsole.addError({
          id: pageAction.id,
          logType: LOG_TYPE.ACTION_EXECUTION_ERROR,
          text: `Execution failed with status ${response.data.statusCode}`,
          source: {
            type: ENTITY_TYPE.ACTION,
            name: pageAction.name,
            id: pageAction.id,
          },
          state: response.data?.request ?? null,
          messages: [
            {
              message: JSON.stringify(body),
              type: PLATFORM_ERROR.PLUGIN_EXECUTION,
            },
          ],
        });
  
        yield put(
          executeActionError({
            actionId: pageAction.id,
            isPageLoad: true,
            error: _.get(response, "responseMeta.error", {
              message,
            }),
            data: createActionExecutionResponse(response),
          }),
        );
        PerformanceTracker.stopAsyncTracking(
          PerformanceTransactionName.EXECUTE_ACTION,
          {
            failed: true,
          },
          pageAction.id,
        );
      } else {
        const payload = createActionExecutionResponse(response);
        PerformanceTracker.stopAsyncTracking(
          PerformanceTransactionName.EXECUTE_ACTION,
          undefined,
          pageAction.id,
        );
        yield put(
          executeApiActionSuccess({
            id: pageAction.id,
            response: payload,
            isPageLoad: true,
          }),
        );
        yield take(ReduxActionTypes.SET_EVALUATED_TREE);
      }
    } catch (e) {
      yield put(
        executeActionError({
          actionId: pageAction.id,
          isPageLoad: true,
          error: {
            message: `The action "${pageAction.name}" has failed.`,
          },
          data: {
            ...EMPTY_RESPONSE,
            body: "There was an error executing this action",
          },
        }),
      );
    }
  }
  
  function* executePageLoadActionsSaga() {
    try {
      const pageActions: PageAction[][] = yield select(getLayoutOnLoadActions);
      const actionCount = _.flatten(pageActions).length;
      PerformanceTracker.startAsyncTracking(
        PerformanceTransactionName.EXECUTE_PAGE_LOAD_ACTIONS,
        { numActions: actionCount },
      );
      for (const actionSet of pageActions) {
        // Load all sets in parallel
        yield* yield all(
          actionSet.map((apiAction) => call(executePageLoadAction, apiAction)),
        );
      }
      PerformanceTracker.stopAsyncTracking(
        PerformanceTransactionName.EXECUTE_PAGE_LOAD_ACTIONS,
      );
  
      yield put(executePageLoadActionsComplete());
    } catch (e) {
      log.error(e);
  
      Toaster.show({
        text: createMessage(ERROR_FAIL_ON_PAGE_LOAD_ACTIONS),
        variant: Variant.danger,
      });
    }
  }
  
  export function* watchActionExecutionSagas() {
    yield all([
      takeEvery(ReduxActionTypes.EXECUTE_ACTION, executeAppAction),
      takeLatest(ReduxActionTypes.RUN_ACTION_REQUEST, runActionSaga),
      takeLatest(ReduxActionTypes.RUN_ACTION_INIT, runActionInitSaga),
      takeLatest(
        ReduxActionTypes.RUN_ACTION_SHORTCUT_REQUEST,
        runActionShortcutSaga,
      ),
      takeLatest(
        ReduxActionTypes.EXECUTE_PAGE_LOAD_ACTIONS,
        executePageLoadActionsSaga,
      ),
    ]);
  }
  