PromucFlow_constructor/app/client/src/sagas/ActionExecution/PluginActionSaga.ts

1017 lines
30 KiB
TypeScript
Raw Normal View History

import { all, call, put, select, take, takeLatest } from "redux-saga/effects";
import {
executePluginActionError,
executePluginActionRequest,
executePluginActionSuccess,
runAction,
updateAction,
} from "actions/pluginActionActions";
import {
ApplicationPayload,
ReduxAction,
ReduxActionErrorTypes,
ReduxActionTypes,
} from "@appsmith/constants/ReduxActionConstants";
import ActionAPI, {
ActionExecutionResponse,
ActionResponse,
ExecuteActionRequest,
PaginationField,
} from "api/ActionAPI";
import {
getAction,
getCurrentPageNameByActionId,
getPlugin,
isActionDirty,
isActionSaving,
feat: Settings js editor (#9984) * POC * Closing channels * WIP * v1 * get working with JS editor * autocomplete * added comments * try removing an import * different way of import * dependency map added to body * triggers can be part of js editor functions hence * removed unwanted lines * new flow chnages * Resolve conflicts * small css changes for empty state * Fix prettier * Fixes * flow changes part 2 * Mock web worker for testing * Throw errors during evaluation * Action execution should be non blocking on the main thread to evaluation of further actions * WIP * Fix build issue * Fix warnings * Rename * Refactor and add tests for worker util * Fix response flow post refactor * added settings icon for js editor * WIP * WIP * WIP * Tests for promises * settings for each function of js object added * Error handling * Error handing action validation * Update test * Passing callback data in the eval trigger flow * log triggers to be executed * WIP * confirm before execution * Remove debugging * Fix backwards compatibility * Avoid passing trigger meta around * fix button loading * handle error callbacks * fix tests * tests * fix console error when checking for async * Fix async function check * Fix async function check again * fix bad commit * Add some comments * added clientSideExecution flag for js functions * css changes for settings icon * unsued code removed * on page load PART 1 * onPageLoad rest iof changes * corrected async badge * removed duplicate test cases * added confirm modal for js functions * removed unused code * small chnage * dependency was not getting created * Fix confirmation modal * unused code removed * replaced new confirmsaga * confirmaton box changes * Fixing JSEditor Run butn locator * corrected property * dependency map was failing * changed key for confirmation box Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-03-17 12:05:17 +00:00
getJSCollection,
} from "selectors/entitiesSelector";
import { getIsGitSyncModalOpen } from "selectors/gitSyncSelectors";
import {
getAppMode,
getCurrentApplication,
} from "selectors/applicationSelectors";
import { get, isArray, isString, set, find, isNil, flatten } from "lodash";
import AppsmithConsole from "utils/AppsmithConsole";
import { ENTITY_TYPE, PLATFORM_ERROR } from "entities/AppsmithConsole";
import { validateResponse } from "sagas/ErrorSagas";
import AnalyticsUtil, { EventName } from "utils/AnalyticsUtil";
import { Action, PluginType } from "entities/Action";
import LOG_TYPE from "entities/AppsmithConsole/logtype";
chore: migrate toast (#17208) * Refactor toast to be passed the dispatch hook externally * Add comments explaining dilemma * use store.dispatch instead of a hook * use alpha version * Change imports * Refactor DebugButton out * update release * fix issue with incorrectly merged package.lock * fix syntax of alpha version * bump ds vesion * copy lock from release * update lock to have alpha * make changes * delete Toast * DS package version updated * import change from release * use new alpha version * update ds version * update ds version * chore: migrate editable text and friends (#17285) * Delete empty components * use alpha for ds * Deleted EditableTextSubComponent, import changes * Delete EditableText, import changes * use ds alpha 10 * Delete EditableTextWrapper.tsx * update ds to use next minor version * use new alpha * fix issue with merge Co-authored-by: Albin <albin@appsmith.com> * chore: migrate file picker v2 (#17308) * use alpha ds * Delete FilePickerV2, import changes * Delete FilePicker, change imports * update alpha version * chore: move copy url form into setting components (#17322) * move CopyUrlForm to src/pages/settings/formgroup * update ds version to use next minor release * feat: Migrate table component to design system (#17329) * feat: Migrate table component to design system * removed commented code in ads index file * fix: table no data hover effect removed Co-authored-by: Tanvi Bhakta <tanvibhakta@gmail.com> * feat: Banner message component migrated to design system (#17327) * feat: Banner image component migrated to design system * Version update for design system package * design system version updated Co-authored-by: Tanvi Bhakta <tanvibhakta@gmail.com> * feat: Tabs component migrated to design system (#17321) * feat: Tabs component migrated to design system * design system package version updated * Update app/client/src/components/editorComponents/form/FormDialogComponent.tsx * Update app/client/src/pages/Editor/PropertyPane/PropertyPaneTab.tsx * Tab component expand issue fix Co-authored-by: Tanvi Bhakta <tanvibhakta@gmail.com> Co-authored-by: Albin <albin@appsmith.com> Co-authored-by: albinAppsmith <87797149+albinAppsmith@users.noreply.github.com>
2022-10-13 20:13:44 +00:00
import { Toaster } from "design-system";
import {
createMessage,
ERROR_ACTION_EXECUTE_FAIL,
ERROR_FAIL_ON_PAGE_LOAD_ACTIONS,
ERROR_PLUGIN_ACTION_EXECUTE,
ACTION_EXECUTION_CANCELLED,
ACTION_EXECUTION_FAILED,
refactor: admin settings (#9906) * refactor admin settings feature * separated save-restart bar to separate component * created new CE dir to facilitate code split * created separate ee dir and exporting everything we have in ce file. * little mod * minor fix * splitting settings types config * using object literals for category types instead of enums * CE: support use of component for each category * minor style fix * authentication page UI changes implemented * github signup doc url added back * removed comments * routing updates * made subcategories listing in left pane optional * added muted saml to auth listing * added breadcrumbs and enabled button * created separate component for auth page and auth config * added callout and disconnect components * updated breadcrumbs component * minor updates to common components * updated warning callout and added icon * ce: test cases fixed * updated test file name * warning banner callout added on auth page * updated callout banner for form login * CE: Split config files * CE: moved the window declaration in EE file as its dependency will be updated in EE * CE: Splitting ApiConstants and SocialLogin constants * CE: split login page * CE: moved getSocialLoginButtonProps func to EE file as it's dependencies will be updated in EE * added key icon * CE: created a factory class to share social auths list * Minor style fix for social btns * Updated the third party auth styles * Small fixes to styling * ce: splitting forms constants * breadcrumbs implemented for all pages in admin settings * Settings breadcrumbs separated * splitted settings breadcrumbs between ce and ee * renamed default import * minor style fix * added login form config. * updated login/signup pages to use form login disabled config * removed common functionality outside * implemented breadcrumb component from scratch without using blueprint * removed unwanted code * Small style update * updated breadcrumb categories file name and breadcrumb icon * added cypress tests for admin settings auth page * added comments * update locator for upgrade button * added link for intercom on upgrade button * removed unnecessary file * minor style fix * style fix for auth option cards * split messages constant * fixed imports for message constants splitting. * added message constants * updated unit test cases * fixed messages import in cypress index * fixed messages import again, cypress fails to read re-exported objs. * added OIDC auth method on authentication page * updated import statements from ee to @appsmith * removed dead code * updated read more link UI * PR comments fixes * some UI fixes * used color and fonts from theme * fixed some imports * fixed some imports * removed warning imports * updated OIDC logo and auth method desc copies * css changes * css changes * css changes * updated cypress test for breadcrumb * moved callout component to ads as calloutv2 * UI changes for form fields * updated css for spacing between form fields * added sub-text on auth pages * added active class for breadcrumb item * added config for disable signup toggle and fixed UI issues of restart banner * fixed admin settings page bugs * assigned true as default state for signup * fixed messages import statements * updated code for PR comments related suggestions * reverted file path change in cypress support * updated cypress test * updated cypress test Co-authored-by: Ankita Kinger <ankita@appsmith.com>
2022-02-11 18:08:46 +00:00
} from "@appsmith/constants/messages";
import { Variant } from "components/ads/common";
import {
EventType,
LayoutOnLoadActionErrors,
PageAction,
RESP_HEADER_DATATYPE,
} from "constants/AppsmithActionConstants/ActionConstants";
import {
getCurrentPageId,
getIsSavingEntity,
getLayoutOnLoadActions,
getLayoutOnLoadIssues,
} from "selectors/editorSelectors";
import PerformanceTracker, {
PerformanceTransactionName,
} from "utils/PerformanceTracker";
import * as log from "loglevel";
import { EMPTY_RESPONSE } from "components/editorComponents/ApiResponseView";
import { AppState } from "@appsmith/reducers";
import { DEFAULT_EXECUTE_ACTION_TIMEOUT_MS } from "@appsmith/constants/ApiConstants";
import { evaluateActionBindings } from "sagas/EvaluationsSaga";
import { isBlobUrl, parseBlobUrl } from "utils/AppsmithUtils";
import { getType, Types } from "utils/TypeHelpers";
import { matchPath } from "react-router";
import {
feat: adding slug names in urls (#10957) * Init commit clean urls * Changes to builder route * Refactored URLs * Remove default params from url builder functions. * Fixed more urls * Changed selector name * Minor url correction * Type fixes * Jest fixes * Fixed routing for old published apps * Fixed url slug replace * page-1 -> page1 as default page slug name * Remove application id from init editor calls * Use default page slug * Added comments and placeholder values for slug names * variable rename * Removed redirection and added back the old routes * Prevent page slug name recompute * Fixed home page load in view mode * Added null checks * Fixed jest test * Fixed jest test * Update URL slugs when app/page name changes * Added unit tests and updates types * Removed unused code * * Removed duplication fetch page call. * Fixes #11354 * Fixed sign up flow * Refactored initializeEditorSaga * Fixed warnings * Fixed integrations screen URL bugs * Cypress fixes * Fixed slug names in copy/move operations and pages screen * Minor refactor * Fixed page highlight bug in published apps * Added new url factory and middleware to store url params * Changed store to default export and fix unit tests * Fixed slugs unit test * Minor fixes * Fixes #11379 * Fixed set as home page feature * Updated types * app id adjustments for cypress * Fixed bad merge * Refactored routes to functional component * * Fixed EE active entity highlight. * Remove unused code in editor router. * jest fix * Mock history to prevent security errors * constant rename * Removed console logs * Fixed page id regex * Do not check for /pages in url * Fixed missing pageId on quick edit/deploy clicks * Missed files from previous commit * Fixed warnings * Fixed jest test * New api integration * feat: Add applicationVersion property to Application (#11626) Added a new property to Application object - applicationVersion. This property can be used to identity when there is a breaking change and can not be solved with migration. FE will use this property to detect such conditions. Another API is added to migrate the applicationVersion to latest version when user migrates the breaking changes. * Added manual upgrade modal. * Test fix * Fixed jest test * function rename * Fix deploy error * Added null check * Changes to persist URL search params when redirecting * Added updates tooltip * More unit test cases * Fixed git url redirection * Fix warning * Fixed evaluation on upgrade * Fixed warnings * File rename * Added cypress for clean urls * Fixed import/export/fork cypress * Cypress api server fixes * Fixed mongo spec * Fixed replay spec * Fixed comments spec * More cypress fixes * Fixed tooltip in update btn * Text size changes * Minor fixes * Jest test fix * Fixed type error * Fixed warnings * Fixed todo comments * Moved description to constants file * Fixed cypress CI run crash * Fixes git cypress failures * Import/Export cypress test fixes * Import export fork cypress fixes * Explorer test fix * Switch branch test fix * Added applicationVersion in export app json * Calls plugin forms in parallel * Fixed warnings * Fixed warning * Import export CI fixes * Reverts previous changes * Fixes import export * Fixed import export cypress URL verification * Pass applicationVersion when duplicating application * Cypress fix * Dummy commit Co-authored-by: Nayan <nayan@appsmith.com>
2022-03-25 10:43:26 +00:00
API_EDITOR_BASE_PATH,
API_EDITOR_ID_PATH,
API_EDITOR_PATH_WITH_SELECTED_PAGE_ID,
INTEGRATION_EDITOR_PATH,
QUERIES_EDITOR_BASE_PATH,
QUERIES_EDITOR_ID_PATH,
CURL_IMPORT_PAGE_PATH,
} from "constants/routes";
feat: adding slug names in urls (#10957) * Init commit clean urls * Changes to builder route * Refactored URLs * Remove default params from url builder functions. * Fixed more urls * Changed selector name * Minor url correction * Type fixes * Jest fixes * Fixed routing for old published apps * Fixed url slug replace * page-1 -> page1 as default page slug name * Remove application id from init editor calls * Use default page slug * Added comments and placeholder values for slug names * variable rename * Removed redirection and added back the old routes * Prevent page slug name recompute * Fixed home page load in view mode * Added null checks * Fixed jest test * Fixed jest test * Update URL slugs when app/page name changes * Added unit tests and updates types * Removed unused code * * Removed duplication fetch page call. * Fixes #11354 * Fixed sign up flow * Refactored initializeEditorSaga * Fixed warnings * Fixed integrations screen URL bugs * Cypress fixes * Fixed slug names in copy/move operations and pages screen * Minor refactor * Fixed page highlight bug in published apps * Added new url factory and middleware to store url params * Changed store to default export and fix unit tests * Fixed slugs unit test * Minor fixes * Fixes #11379 * Fixed set as home page feature * Updated types * app id adjustments for cypress * Fixed bad merge * Refactored routes to functional component * * Fixed EE active entity highlight. * Remove unused code in editor router. * jest fix * Mock history to prevent security errors * constant rename * Removed console logs * Fixed page id regex * Do not check for /pages in url * Fixed missing pageId on quick edit/deploy clicks * Missed files from previous commit * Fixed warnings * Fixed jest test * New api integration * feat: Add applicationVersion property to Application (#11626) Added a new property to Application object - applicationVersion. This property can be used to identity when there is a breaking change and can not be solved with migration. FE will use this property to detect such conditions. Another API is added to migrate the applicationVersion to latest version when user migrates the breaking changes. * Added manual upgrade modal. * Test fix * Fixed jest test * function rename * Fix deploy error * Added null check * Changes to persist URL search params when redirecting * Added updates tooltip * More unit test cases * Fixed git url redirection * Fix warning * Fixed evaluation on upgrade * Fixed warnings * File rename * Added cypress for clean urls * Fixed import/export/fork cypress * Cypress api server fixes * Fixed mongo spec * Fixed replay spec * Fixed comments spec * More cypress fixes * Fixed tooltip in update btn * Text size changes * Minor fixes * Jest test fix * Fixed type error * Fixed warnings * Fixed todo comments * Moved description to constants file * Fixed cypress CI run crash * Fixes git cypress failures * Import/Export cypress test fixes * Import export fork cypress fixes * Explorer test fix * Switch branch test fix * Added applicationVersion in export app json * Calls plugin forms in parallel * Fixed warnings * Fixed warning * Import export CI fixes * Reverts previous changes * Fixes import export * Fixed import export cypress URL verification * Pass applicationVersion when duplicating application * Cypress fix * Dummy commit Co-authored-by: Nayan <nayan@appsmith.com>
2022-03-25 10:43:26 +00:00
import { SAAS_EDITOR_API_ID_PATH } from "pages/Editor/SaaSEditor/constants";
import {
ActionTriggerType,
RunPluginActionDescription,
} from "entities/DataTree/actionTriggers";
import { APP_MODE } from "entities/App";
import { FileDataTypes } from "widgets/constants";
import { hideDebuggerErrors } from "actions/debuggerActions";
import {
ActionValidationError,
getErrorAsString,
PluginActionExecutionError,
PluginTriggerFailureError,
UserCancelledActionExecutionError,
} from "sagas/ActionExecution/errorUtils";
import { shouldBeDefined, trimQueryString } from "utils/helpers";
feat: Settings js editor (#9984) * POC * Closing channels * WIP * v1 * get working with JS editor * autocomplete * added comments * try removing an import * different way of import * dependency map added to body * triggers can be part of js editor functions hence * removed unwanted lines * new flow chnages * Resolve conflicts * small css changes for empty state * Fix prettier * Fixes * flow changes part 2 * Mock web worker for testing * Throw errors during evaluation * Action execution should be non blocking on the main thread to evaluation of further actions * WIP * Fix build issue * Fix warnings * Rename * Refactor and add tests for worker util * Fix response flow post refactor * added settings icon for js editor * WIP * WIP * WIP * Tests for promises * settings for each function of js object added * Error handling * Error handing action validation * Update test * Passing callback data in the eval trigger flow * log triggers to be executed * WIP * confirm before execution * Remove debugging * Fix backwards compatibility * Avoid passing trigger meta around * fix button loading * handle error callbacks * fix tests * tests * fix console error when checking for async * Fix async function check * Fix async function check again * fix bad commit * Add some comments * added clientSideExecution flag for js functions * css changes for settings icon * unsued code removed * on page load PART 1 * onPageLoad rest iof changes * corrected async badge * removed duplicate test cases * added confirm modal for js functions * removed unused code * small chnage * dependency was not getting created * Fix confirmation modal * unused code removed * replaced new confirmsaga * confirmaton box changes * Fixing JSEditor Run butn locator * corrected property * dependency map was failing * changed key for confirmation box Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-03-17 12:05:17 +00:00
import { JSCollection } from "entities/JSCollection";
import {
executeAppAction,
TriggerMeta,
} from "sagas/ActionExecution/ActionExecutionSagas";
import { requestModalConfirmationSaga } from "sagas/UtilSagas";
import { ModalType } from "reducers/uiReducers/modalActionReducer";
import { getFormNames, getFormValues } from "redux-form";
import { CURL_IMPORT_FORM } from "@appsmith/constants/forms";
import { submitCurlImportForm } from "actions/importActions";
import { curlImportFormValues } from "pages/Editor/APIEditor/helpers";
import { matchBasePath } from "pages/Editor/Explorer/helpers";
import { isTrueObject, findDatatype } from "workers/evaluationUtils";
import { handleExecuteJSFunctionSaga } from "sagas/JSPaneSagas";
import { Plugin } from "api/PluginApi";
import { setDefaultActionDisplayFormat } from "./PluginActionSagaUtils";
import { checkAndLogErrorsIfCyclicDependency } from "sagas/helper";
enum ActionResponseDataTypes {
BINARY = "BINARY",
}
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;
};
/**
*
* @param blobUrl string A blob url with type added a query param
* @returns promise that resolves to file content
*/
function* readBlob(blobUrl: string): any {
const [url, fileType] = parseBlobUrl(blobUrl);
const file = yield fetch(url).then((r) => r.blob());
return yield new Promise((resolve) => {
const reader = new FileReader();
if (fileType === FileDataTypes.Base64) {
reader.readAsDataURL(file);
} else if (fileType === FileDataTypes.Binary) {
reader.readAsBinaryString(file);
} else {
reader.readAsText(file);
}
reader.onloadend = () => {
resolve(reader.result);
};
});
}
/**
* This function resolves :
* - individual objects containing blob urls
* - blob urls directly
* - else returns the value unchanged
* - finds datatype of evaluated value
* - binds dataype to payload
*
* @param value
*/
function* resolvingBlobUrls(
value: any,
executeActionRequest: ExecuteActionRequest,
index: number,
isArray?: boolean,
arrDatatype?: string[],
) {
//Get datatypes of evaluated value.
const dataType: string = findDatatype(value);
//If array elements then dont push datatypes to payload.
isArray
? arrDatatype?.push(dataType)
: (executeActionRequest.paramProperties[`k${index}`] = dataType);
if (isTrueObject(value)) {
const blobUrlPaths: string[] = [];
Object.keys(value).forEach((propertyName) => {
if (isBlobUrl(value[propertyName])) {
blobUrlPaths.push(propertyName);
}
});
for (const blobUrlPath of blobUrlPaths) {
const blobUrl = value[blobUrlPath] as string;
const resolvedBlobValue: unknown = yield call(readBlob, blobUrl);
set(value, blobUrlPath, resolvedBlobValue);
}
} else if (isBlobUrl(value)) {
// @ts-expect-error: Values can take many types
value = yield call(readBlob, value);
}
return value;
}
/**
* 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
*/
function* evaluateActionParams(
bindings: string[] | undefined,
formData: FormData,
executeActionRequest: ExecuteActionRequest,
executionParams?: Record<string, any> | string,
) {
if (isNil(bindings) || bindings.length === 0) {
formData.append("executeActionDTO", JSON.stringify(executeActionRequest));
return [];
}
// Evaluated all bindings of the actions. Pass executionParams if any
// @ts-expect-error: Values can take many types
const values = yield call(evaluateActionBindings, bindings, executionParams);
const bindingsMap: Record<string, string> = {};
const bindingBlob = [];
// Add keys values to formData for the multipart submission
for (let i = 0; i < bindings.length; i++) {
const key = bindings[i];
let value = values[i];
if (isArray(value)) {
const tempArr = [];
const arrDatatype: string[] = [];
// array of objects containing blob urls that is loops and individual object is checked for resolution of blob urls.
for (const val of value) {
const newVal: unknown = yield call(
resolvingBlobUrls,
val,
executeActionRequest,
i,
true,
arrDatatype,
);
tempArr.push(newVal);
}
//Adding array datatype along with the datatype of first element of the array
executeActionRequest.paramProperties[`k${i}`] = {
array: [arrDatatype[0]],
};
value = tempArr;
} else {
// @ts-expect-error: Values can take many types
value = yield call(resolvingBlobUrls, value, executeActionRequest, i);
}
if (typeof value === "object") {
value = JSON.stringify(value);
}
value = new Blob([value], { type: "text/plain" });
bindingsMap[key] = `k${i}`;
bindingBlob.push({ name: `k${i}`, value: value });
}
formData.append("executeActionDTO", JSON.stringify(executeActionRequest));
formData.append("parameterMap", JSON.stringify(bindingsMap));
bindingBlob?.forEach((item) => formData.append(item.name, item.value));
}
export default function* executePluginActionTriggerSaga(
pluginAction: RunPluginActionDescription["payload"],
eventType: EventType,
triggerMeta: TriggerMeta,
) {
const { actionId, onError, onSuccess, params } = pluginAction;
if (getType(params) !== Types.OBJECT) {
throw new ActionValidationError(
ActionTriggerType.RUN_PLUGIN_ACTION,
"params",
Types.OBJECT,
getType(params),
);
}
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.EXECUTE_ACTION,
{
actionId: actionId,
},
actionId,
);
const appMode: APP_MODE | undefined = yield select(getAppMode);
const action = shouldBeDefined<Action>(
yield select(getAction, actionId),
`Action not found for id - ${actionId}`,
);
const currentApp: ApplicationPayload = yield select(getCurrentApplication);
AnalyticsUtil.logEvent("EXECUTE_ACTION", {
type: action?.pluginType,
name: action?.name,
pageId: action?.pageId,
appId: currentApp.id,
appMode: appMode,
appName: currentApp.name,
isExampleApp: currentApp.appIsExample,
});
const pagination =
eventType === EventType.ON_NEXT_PAGE
? "NEXT"
: eventType === EventType.ON_PREV_PAGE
? "PREV"
: undefined;
AppsmithConsole.info({
text: "Execution started from widget request",
source: {
type: ENTITY_TYPE.ACTION,
name: action.name,
id: actionId,
},
state: action.actionConfiguration,
});
const executePluginActionResponse: ExecutePluginActionResponse = yield call(
executePluginActionSaga,
action.id,
pagination,
params,
);
const { isError, payload } = executePluginActionResponse;
if (isError) {
AppsmithConsole.addError({
id: actionId,
logType: LOG_TYPE.ACTION_EXECUTION_ERROR,
text: `Execution failed with status ${payload.statusCode}`,
source: {
type: ENTITY_TYPE.ACTION,
name: action.name,
id: actionId,
},
state: payload.request,
messages: [
{
// Need to stringify cause this gets rendered directly
// and rendering objects can crash the app
message: !isString(payload.body)
? JSON.stringify(payload.body)
: payload.body,
type: PLATFORM_ERROR.PLUGIN_EXECUTION,
subType: payload.errorType,
},
],
});
if (onError) {
yield call(executeAppAction, {
event: { type: eventType },
dynamicString: onError,
callbackData: [payload.body, params],
...triggerMeta,
});
throw new PluginTriggerFailureError(
createMessage(ERROR_ACTION_EXECUTE_FAIL, action.name),
[payload.body, params],
);
} else {
throw new PluginTriggerFailureError(
createMessage(ERROR_PLUGIN_ACTION_EXECUTE, action.name),
[payload.body, params],
);
}
} else {
AppsmithConsole.info({
logType: LOG_TYPE.ACTION_EXECUTION_SUCCESS,
text: "Executed successfully from widget request",
timeTaken: payload.duration,
source: {
type: ENTITY_TYPE.ACTION,
name: action.name,
id: actionId,
},
state: {
response: payload.body,
request: payload.request,
},
});
if (onSuccess) {
yield call(executeAppAction, {
event: { type: eventType },
dynamicString: onSuccess,
callbackData: [payload.body, params],
...triggerMeta,
});
}
}
return [payload.body, params];
}
function* runActionShortcutSaga() {
const pathname = window.location.pathname;
const baseMatch = matchBasePath(pathname);
if (!baseMatch) return;
// get gitSyncModal status
const isGitSyncModalOpen: boolean = yield select(getIsGitSyncModalOpen);
// if git sync modal is open, prevent action from being executed via shortcut keys.
if (isGitSyncModalOpen) return;
const { path } = baseMatch;
const match: any = matchPath(pathname, {
path: [
trimQueryString(`${path}${API_EDITOR_BASE_PATH}`),
trimQueryString(`${path}${API_EDITOR_ID_PATH}`),
trimQueryString(`${path}${QUERIES_EDITOR_BASE_PATH}`),
trimQueryString(`${path}${QUERIES_EDITOR_ID_PATH}`),
trimQueryString(`${path}${API_EDITOR_PATH_WITH_SELECTED_PAGE_ID}`),
trimQueryString(`${path}${INTEGRATION_EDITOR_PATH}`),
trimQueryString(`${path}${SAAS_EDITOR_API_ID_PATH}`),
`${path}${CURL_IMPORT_PAGE_PATH}`,
],
exact: true,
strict: false,
});
// get the current form name
const currentFormNames: string[] = yield select(getFormNames());
if (!match || !match.params) return;
const { apiId, pageId, queryId } = match.params;
const actionId = apiId || queryId;
if (actionId) {
const trackerId = apiId
? PerformanceTransactionName.RUN_API_SHORTCUT
: PerformanceTransactionName.RUN_QUERY_SHORTCUT;
PerformanceTracker.startTracking(trackerId, {
actionId,
pageId,
});
AnalyticsUtil.logEvent(trackerId as EventName, {
actionId,
});
yield put(runAction(actionId));
} else if (
!!currentFormNames &&
currentFormNames.includes(CURL_IMPORT_FORM) &&
!actionId
) {
// if the current form names include the curl form and there are no actionIds i.e. its not an api or query
// get the form values and call the submit curl import form function with its data
const formValues: curlImportFormValues = yield select(
getFormValues(CURL_IMPORT_FORM),
);
// if the user has not edited the curl input field, assign an empty string to it, so it doesnt throw an error.
if (!formValues?.curl) formValues["curl"] = "";
yield put(submitCurlImportForm(formValues));
} else {
return;
}
}
function* runActionSaga(
reduxAction: ReduxAction<{
id: string;
paginationField: PaginationField;
}>,
) {
const actionId = reduxAction.payload.id;
const isSaving: boolean = yield select(isActionSaving(actionId));
const isDirty: boolean = yield select(isActionDirty(actionId));
const isSavingEntity: boolean = yield select(getIsSavingEntity);
if (isSaving || isDirty || isSavingEntity) {
if (isDirty && !isSaving) {
yield put(updateAction({ id: actionId }));
}
yield take(ReduxActionTypes.UPDATE_ACTION_SUCCESS);
}
const actionObject = shouldBeDefined<Action>(
yield select(getAction, actionId),
`action not found for id - ${actionId}`,
);
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 { id, paginationField } = reduxAction.payload;
let payload = EMPTY_RESPONSE;
let isError = true;
let error = "";
try {
const executePluginActionResponse: ExecutePluginActionResponse = yield call(
executePluginActionSaga,
id,
paginationField,
);
payload = executePluginActionResponse.payload;
isError = executePluginActionResponse.isError;
} catch (e) {
// When running from the pane, we just want to end the saga if the user has
// cancelled the call. No need to log any errors
if (e instanceof UserCancelledActionExecutionError) {
// cancel action but do not throw any error.
yield put({
type: ReduxActionErrorTypes.RUN_ACTION_ERROR,
payload: {
error: e.name,
id: reduxAction.payload.id,
show: false,
},
});
Toaster.show({
text: createMessage(ACTION_EXECUTION_CANCELLED, actionObject.name),
variant: Variant.danger,
});
return;
}
log.error(e);
error = (e as Error).message;
}
// Error should be readable error if present.
// Otherwise, payload's body.
// Default to "An unexpected error occurred" if none is available
const readableError = payload.readableError
? getErrorAsString(payload.readableError)
: undefined;
const payloadBodyError = payload.body
? getErrorAsString(payload.body)
: undefined;
const defaultError = "An unexpected error occurred";
if (isError) {
error = readableError || payloadBodyError || defaultError;
// In case of debugger, both the current error message
// and the readableError needs to be present,
// since the readableError may be malformed for certain errors.
const appsmithConsoleErrorMessageList = [
{
message: error,
type: PLATFORM_ERROR.PLUGIN_EXECUTION,
subType: payload.errorType,
},
];
if (error === readableError && !!payloadBodyError) {
appsmithConsoleErrorMessageList.push({
message: payloadBodyError,
type: PLATFORM_ERROR.PLUGIN_EXECUTION,
subType: payload.errorType,
});
}
AppsmithConsole.addError({
id: actionId,
logType: LOG_TYPE.ACTION_EXECUTION_ERROR,
text: `Execution failed${
payload.statusCode ? ` with status ${payload.statusCode}` : ""
}`,
source: {
type: ENTITY_TYPE.ACTION,
name: actionObject.name,
id: actionId,
},
messages: appsmithConsoleErrorMessageList,
state: payload.request,
});
Toaster.show({
text: createMessage(ERROR_ACTION_EXECUTE_FAIL, actionObject.name),
variant: Variant.danger,
});
yield put({
type: ReduxActionErrorTypes.RUN_ACTION_ERROR,
payload: {
error: appsmithConsoleErrorMessageList[0],
id: reduxAction.payload.id,
},
});
return;
}
const pageName: string = 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: payload.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: payload.duration,
source: {
type: ENTITY_TYPE.ACTION,
name: actionObject.name,
id: actionId,
},
state: {
response: payload.body,
request: payload.request,
},
});
}
}
feat: Settings js editor (#9984) * POC * Closing channels * WIP * v1 * get working with JS editor * autocomplete * added comments * try removing an import * different way of import * dependency map added to body * triggers can be part of js editor functions hence * removed unwanted lines * new flow chnages * Resolve conflicts * small css changes for empty state * Fix prettier * Fixes * flow changes part 2 * Mock web worker for testing * Throw errors during evaluation * Action execution should be non blocking on the main thread to evaluation of further actions * WIP * Fix build issue * Fix warnings * Rename * Refactor and add tests for worker util * Fix response flow post refactor * added settings icon for js editor * WIP * WIP * WIP * Tests for promises * settings for each function of js object added * Error handling * Error handing action validation * Update test * Passing callback data in the eval trigger flow * log triggers to be executed * WIP * confirm before execution * Remove debugging * Fix backwards compatibility * Avoid passing trigger meta around * fix button loading * handle error callbacks * fix tests * tests * fix console error when checking for async * Fix async function check * Fix async function check again * fix bad commit * Add some comments * added clientSideExecution flag for js functions * css changes for settings icon * unsued code removed * on page load PART 1 * onPageLoad rest iof changes * corrected async badge * removed duplicate test cases * added confirm modal for js functions * removed unused code * small chnage * dependency was not getting created * Fix confirmation modal * unused code removed * replaced new confirmsaga * confirmaton box changes * Fixing JSEditor Run butn locator * corrected property * dependency map was failing * changed key for confirmation box Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-03-17 12:05:17 +00:00
function* executeOnPageLoadJSAction(pageAction: PageAction) {
const collectionId = pageAction.collectionId;
if (collectionId) {
const collection: JSCollection = yield select(
getJSCollection,
collectionId,
);
const jsAction = collection.actions.find(
(action) => action.id === pageAction.id,
);
feat: Settings js editor (#9984) * POC * Closing channels * WIP * v1 * get working with JS editor * autocomplete * added comments * try removing an import * different way of import * dependency map added to body * triggers can be part of js editor functions hence * removed unwanted lines * new flow chnages * Resolve conflicts * small css changes for empty state * Fix prettier * Fixes * flow changes part 2 * Mock web worker for testing * Throw errors during evaluation * Action execution should be non blocking on the main thread to evaluation of further actions * WIP * Fix build issue * Fix warnings * Rename * Refactor and add tests for worker util * Fix response flow post refactor * added settings icon for js editor * WIP * WIP * WIP * Tests for promises * settings for each function of js object added * Error handling * Error handing action validation * Update test * Passing callback data in the eval trigger flow * log triggers to be executed * WIP * confirm before execution * Remove debugging * Fix backwards compatibility * Avoid passing trigger meta around * fix button loading * handle error callbacks * fix tests * tests * fix console error when checking for async * Fix async function check * Fix async function check again * fix bad commit * Add some comments * added clientSideExecution flag for js functions * css changes for settings icon * unsued code removed * on page load PART 1 * onPageLoad rest iof changes * corrected async badge * removed duplicate test cases * added confirm modal for js functions * removed unused code * small chnage * dependency was not getting created * Fix confirmation modal * unused code removed * replaced new confirmsaga * confirmaton box changes * Fixing JSEditor Run butn locator * corrected property * dependency map was failing * changed key for confirmation box Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-03-17 12:05:17 +00:00
if (!!jsAction) {
if (jsAction.confirmBeforeExecute) {
const modalPayload = {
name: pageAction.name,
modalOpen: true,
modalType: ModalType.RUN_ACTION,
};
const confirmed: unknown = yield call(
requestModalConfirmationSaga,
modalPayload,
);
if (!confirmed) {
yield put({
type: ReduxActionTypes.RUN_ACTION_CANCELLED,
payload: { id: pageAction.id },
});
Toaster.show({
text: createMessage(
ACTION_EXECUTION_CANCELLED,
`${collection.name}.${jsAction.name}`,
),
variant: Variant.danger,
});
// Don't proceed to executing the js function
return;
}
}
const data = {
collectionName: collection.name,
action: jsAction,
collectionId: collectionId,
};
yield call(handleExecuteJSFunctionSaga, data);
feat: Settings js editor (#9984) * POC * Closing channels * WIP * v1 * get working with JS editor * autocomplete * added comments * try removing an import * different way of import * dependency map added to body * triggers can be part of js editor functions hence * removed unwanted lines * new flow chnages * Resolve conflicts * small css changes for empty state * Fix prettier * Fixes * flow changes part 2 * Mock web worker for testing * Throw errors during evaluation * Action execution should be non blocking on the main thread to evaluation of further actions * WIP * Fix build issue * Fix warnings * Rename * Refactor and add tests for worker util * Fix response flow post refactor * added settings icon for js editor * WIP * WIP * WIP * Tests for promises * settings for each function of js object added * Error handling * Error handing action validation * Update test * Passing callback data in the eval trigger flow * log triggers to be executed * WIP * confirm before execution * Remove debugging * Fix backwards compatibility * Avoid passing trigger meta around * fix button loading * handle error callbacks * fix tests * tests * fix console error when checking for async * Fix async function check * Fix async function check again * fix bad commit * Add some comments * added clientSideExecution flag for js functions * css changes for settings icon * unsued code removed * on page load PART 1 * onPageLoad rest iof changes * corrected async badge * removed duplicate test cases * added confirm modal for js functions * removed unused code * small chnage * dependency was not getting created * Fix confirmation modal * unused code removed * replaced new confirmsaga * confirmaton box changes * Fixing JSEditor Run butn locator * corrected property * dependency map was failing * changed key for confirmation box Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-03-17 12:05:17 +00:00
}
}
feat: Settings js editor (#9984) * POC * Closing channels * WIP * v1 * get working with JS editor * autocomplete * added comments * try removing an import * different way of import * dependency map added to body * triggers can be part of js editor functions hence * removed unwanted lines * new flow chnages * Resolve conflicts * small css changes for empty state * Fix prettier * Fixes * flow changes part 2 * Mock web worker for testing * Throw errors during evaluation * Action execution should be non blocking on the main thread to evaluation of further actions * WIP * Fix build issue * Fix warnings * Rename * Refactor and add tests for worker util * Fix response flow post refactor * added settings icon for js editor * WIP * WIP * WIP * Tests for promises * settings for each function of js object added * Error handling * Error handing action validation * Update test * Passing callback data in the eval trigger flow * log triggers to be executed * WIP * confirm before execution * Remove debugging * Fix backwards compatibility * Avoid passing trigger meta around * fix button loading * handle error callbacks * fix tests * tests * fix console error when checking for async * Fix async function check * Fix async function check again * fix bad commit * Add some comments * added clientSideExecution flag for js functions * css changes for settings icon * unsued code removed * on page load PART 1 * onPageLoad rest iof changes * corrected async badge * removed duplicate test cases * added confirm modal for js functions * removed unused code * small chnage * dependency was not getting created * Fix confirmation modal * unused code removed * replaced new confirmsaga * confirmaton box changes * Fixing JSEditor Run butn locator * corrected property * dependency map was failing * changed key for confirmation box Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-03-17 12:05:17 +00:00
}
feat: Settings js editor (#9984) * POC * Closing channels * WIP * v1 * get working with JS editor * autocomplete * added comments * try removing an import * different way of import * dependency map added to body * triggers can be part of js editor functions hence * removed unwanted lines * new flow chnages * Resolve conflicts * small css changes for empty state * Fix prettier * Fixes * flow changes part 2 * Mock web worker for testing * Throw errors during evaluation * Action execution should be non blocking on the main thread to evaluation of further actions * WIP * Fix build issue * Fix warnings * Rename * Refactor and add tests for worker util * Fix response flow post refactor * added settings icon for js editor * WIP * WIP * WIP * Tests for promises * settings for each function of js object added * Error handling * Error handing action validation * Update test * Passing callback data in the eval trigger flow * log triggers to be executed * WIP * confirm before execution * Remove debugging * Fix backwards compatibility * Avoid passing trigger meta around * fix button loading * handle error callbacks * fix tests * tests * fix console error when checking for async * Fix async function check * Fix async function check again * fix bad commit * Add some comments * added clientSideExecution flag for js functions * css changes for settings icon * unsued code removed * on page load PART 1 * onPageLoad rest iof changes * corrected async badge * removed duplicate test cases * added confirm modal for js functions * removed unused code * small chnage * dependency was not getting created * Fix confirmation modal * unused code removed * replaced new confirmsaga * confirmaton box changes * Fixing JSEditor Run butn locator * corrected property * dependency map was failing * changed key for confirmation box Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-03-17 12:05:17 +00:00
function* executePageLoadAction(pageAction: PageAction) {
if (pageAction.hasOwnProperty("collectionId")) {
yield call(executeOnPageLoadJSAction, pageAction);
} else {
const pageId: string | undefined = yield select(getCurrentPageId);
feat: Settings js editor (#9984) * POC * Closing channels * WIP * v1 * get working with JS editor * autocomplete * added comments * try removing an import * different way of import * dependency map added to body * triggers can be part of js editor functions hence * removed unwanted lines * new flow chnages * Resolve conflicts * small css changes for empty state * Fix prettier * Fixes * flow changes part 2 * Mock web worker for testing * Throw errors during evaluation * Action execution should be non blocking on the main thread to evaluation of further actions * WIP * Fix build issue * Fix warnings * Rename * Refactor and add tests for worker util * Fix response flow post refactor * added settings icon for js editor * WIP * WIP * WIP * Tests for promises * settings for each function of js object added * Error handling * Error handing action validation * Update test * Passing callback data in the eval trigger flow * log triggers to be executed * WIP * confirm before execution * Remove debugging * Fix backwards compatibility * Avoid passing trigger meta around * fix button loading * handle error callbacks * fix tests * tests * fix console error when checking for async * Fix async function check * Fix async function check again * fix bad commit * Add some comments * added clientSideExecution flag for js functions * css changes for settings icon * unsued code removed * on page load PART 1 * onPageLoad rest iof changes * corrected async badge * removed duplicate test cases * added confirm modal for js functions * removed unused code * small chnage * dependency was not getting created * Fix confirmation modal * unused code removed * replaced new confirmsaga * confirmaton box changes * Fixing JSEditor Run butn locator * corrected property * dependency map was failing * changed key for confirmation box Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-03-17 12:05:17 +00:00
let currentApp: ApplicationPayload = yield select(getCurrentApplication);
currentApp = currentApp || {};
const appMode: APP_MODE | undefined = yield select(getAppMode);
feat: Settings js editor (#9984) * POC * Closing channels * WIP * v1 * get working with JS editor * autocomplete * added comments * try removing an import * different way of import * dependency map added to body * triggers can be part of js editor functions hence * removed unwanted lines * new flow chnages * Resolve conflicts * small css changes for empty state * Fix prettier * Fixes * flow changes part 2 * Mock web worker for testing * Throw errors during evaluation * Action execution should be non blocking on the main thread to evaluation of further actions * WIP * Fix build issue * Fix warnings * Rename * Refactor and add tests for worker util * Fix response flow post refactor * added settings icon for js editor * WIP * WIP * WIP * Tests for promises * settings for each function of js object added * Error handling * Error handing action validation * Update test * Passing callback data in the eval trigger flow * log triggers to be executed * WIP * confirm before execution * Remove debugging * Fix backwards compatibility * Avoid passing trigger meta around * fix button loading * handle error callbacks * fix tests * tests * fix console error when checking for async * Fix async function check * Fix async function check again * fix bad commit * Add some comments * added clientSideExecution flag for js functions * css changes for settings icon * unsued code removed * on page load PART 1 * onPageLoad rest iof changes * corrected async badge * removed duplicate test cases * added confirm modal for js functions * removed unused code * small chnage * dependency was not getting created * Fix confirmation modal * unused code removed * replaced new confirmsaga * confirmaton box changes * Fixing JSEditor Run butn locator * corrected property * dependency map was failing * changed key for confirmation box Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-03-17 12:05:17 +00:00
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,
});
feat: Settings js editor (#9984) * POC * Closing channels * WIP * v1 * get working with JS editor * autocomplete * added comments * try removing an import * different way of import * dependency map added to body * triggers can be part of js editor functions hence * removed unwanted lines * new flow chnages * Resolve conflicts * small css changes for empty state * Fix prettier * Fixes * flow changes part 2 * Mock web worker for testing * Throw errors during evaluation * Action execution should be non blocking on the main thread to evaluation of further actions * WIP * Fix build issue * Fix warnings * Rename * Refactor and add tests for worker util * Fix response flow post refactor * added settings icon for js editor * WIP * WIP * WIP * Tests for promises * settings for each function of js object added * Error handling * Error handing action validation * Update test * Passing callback data in the eval trigger flow * log triggers to be executed * WIP * confirm before execution * Remove debugging * Fix backwards compatibility * Avoid passing trigger meta around * fix button loading * handle error callbacks * fix tests * tests * fix console error when checking for async * Fix async function check * Fix async function check again * fix bad commit * Add some comments * added clientSideExecution flag for js functions * css changes for settings icon * unsued code removed * on page load PART 1 * onPageLoad rest iof changes * corrected async badge * removed duplicate test cases * added confirm modal for js functions * removed unused code * small chnage * dependency was not getting created * Fix confirmation modal * unused code removed * replaced new confirmsaga * confirmaton box changes * Fixing JSEditor Run butn locator * corrected property * dependency map was failing * changed key for confirmation box Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-03-17 12:05:17 +00:00
let payload = EMPTY_RESPONSE;
let isError = true;
let error = createMessage(ACTION_EXECUTION_FAILED, pageAction.name);
feat: Settings js editor (#9984) * POC * Closing channels * WIP * v1 * get working with JS editor * autocomplete * added comments * try removing an import * different way of import * dependency map added to body * triggers can be part of js editor functions hence * removed unwanted lines * new flow chnages * Resolve conflicts * small css changes for empty state * Fix prettier * Fixes * flow changes part 2 * Mock web worker for testing * Throw errors during evaluation * Action execution should be non blocking on the main thread to evaluation of further actions * WIP * Fix build issue * Fix warnings * Rename * Refactor and add tests for worker util * Fix response flow post refactor * added settings icon for js editor * WIP * WIP * WIP * Tests for promises * settings for each function of js object added * Error handling * Error handing action validation * Update test * Passing callback data in the eval trigger flow * log triggers to be executed * WIP * confirm before execution * Remove debugging * Fix backwards compatibility * Avoid passing trigger meta around * fix button loading * handle error callbacks * fix tests * tests * fix console error when checking for async * Fix async function check * Fix async function check again * fix bad commit * Add some comments * added clientSideExecution flag for js functions * css changes for settings icon * unsued code removed * on page load PART 1 * onPageLoad rest iof changes * corrected async badge * removed duplicate test cases * added confirm modal for js functions * removed unused code * small chnage * dependency was not getting created * Fix confirmation modal * unused code removed * replaced new confirmsaga * confirmaton box changes * Fixing JSEditor Run butn locator * corrected property * dependency map was failing * changed key for confirmation box Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-03-17 12:05:17 +00:00
try {
const executePluginActionResponse: ExecutePluginActionResponse = yield call(
executePluginActionSaga,
pageAction,
);
payload = executePluginActionResponse.payload;
isError = executePluginActionResponse.isError;
} catch (e) {
log.error(e);
if (e instanceof UserCancelledActionExecutionError) {
error = createMessage(ACTION_EXECUTION_CANCELLED, pageAction.name);
}
feat: Settings js editor (#9984) * POC * Closing channels * WIP * v1 * get working with JS editor * autocomplete * added comments * try removing an import * different way of import * dependency map added to body * triggers can be part of js editor functions hence * removed unwanted lines * new flow chnages * Resolve conflicts * small css changes for empty state * Fix prettier * Fixes * flow changes part 2 * Mock web worker for testing * Throw errors during evaluation * Action execution should be non blocking on the main thread to evaluation of further actions * WIP * Fix build issue * Fix warnings * Rename * Refactor and add tests for worker util * Fix response flow post refactor * added settings icon for js editor * WIP * WIP * WIP * Tests for promises * settings for each function of js object added * Error handling * Error handing action validation * Update test * Passing callback data in the eval trigger flow * log triggers to be executed * WIP * confirm before execution * Remove debugging * Fix backwards compatibility * Avoid passing trigger meta around * fix button loading * handle error callbacks * fix tests * tests * fix console error when checking for async * Fix async function check * Fix async function check again * fix bad commit * Add some comments * added clientSideExecution flag for js functions * css changes for settings icon * unsued code removed * on page load PART 1 * onPageLoad rest iof changes * corrected async badge * removed duplicate test cases * added confirm modal for js functions * removed unused code * small chnage * dependency was not getting created * Fix confirmation modal * unused code removed * replaced new confirmsaga * confirmaton box changes * Fixing JSEditor Run butn locator * corrected property * dependency map was failing * changed key for confirmation box Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-03-17 12:05:17 +00:00
}
if (isError) {
AppsmithConsole.addError({
id: pageAction.id,
feat: Settings js editor (#9984) * POC * Closing channels * WIP * v1 * get working with JS editor * autocomplete * added comments * try removing an import * different way of import * dependency map added to body * triggers can be part of js editor functions hence * removed unwanted lines * new flow chnages * Resolve conflicts * small css changes for empty state * Fix prettier * Fixes * flow changes part 2 * Mock web worker for testing * Throw errors during evaluation * Action execution should be non blocking on the main thread to evaluation of further actions * WIP * Fix build issue * Fix warnings * Rename * Refactor and add tests for worker util * Fix response flow post refactor * added settings icon for js editor * WIP * WIP * WIP * Tests for promises * settings for each function of js object added * Error handling * Error handing action validation * Update test * Passing callback data in the eval trigger flow * log triggers to be executed * WIP * confirm before execution * Remove debugging * Fix backwards compatibility * Avoid passing trigger meta around * fix button loading * handle error callbacks * fix tests * tests * fix console error when checking for async * Fix async function check * Fix async function check again * fix bad commit * Add some comments * added clientSideExecution flag for js functions * css changes for settings icon * unsued code removed * on page load PART 1 * onPageLoad rest iof changes * corrected async badge * removed duplicate test cases * added confirm modal for js functions * removed unused code * small chnage * dependency was not getting created * Fix confirmation modal * unused code removed * replaced new confirmsaga * confirmaton box changes * Fixing JSEditor Run butn locator * corrected property * dependency map was failing * changed key for confirmation box Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: Arpit Mohan <arpit@appsmith.com> Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-03-17 12:05:17 +00:00
logType: LOG_TYPE.ACTION_EXECUTION_ERROR,
text: `Execution failed with status ${payload.statusCode}`,
source: {
type: ENTITY_TYPE.ACTION,
name: pageAction.name,
id: pageAction.id,
},
state: payload.request,
messages: [
{
message: error,
type: PLATFORM_ERROR.PLUGIN_EXECUTION,
subType: payload.errorType,
},
],
});
yield put(
executePluginActionError({
actionId: pageAction.id,
isPageLoad: true,
error: { message: error },
data: payload,
}),
);
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.EXECUTE_ACTION,
{
failed: true,
},
pageAction.id,
);
} else {
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.EXECUTE_ACTION,
undefined,
pageAction.id,
);
yield put(
executePluginActionSuccess({
id: pageAction.id,
response: payload,
isPageLoad: true,
}),
);
yield take(ReduxActionTypes.SET_EVALUATED_TREE);
}
}
}
function* executePageLoadActionsSaga() {
try {
const pageActions: PageAction[][] = yield select(getLayoutOnLoadActions);
const layoutOnLoadActionErrors: LayoutOnLoadActionErrors[] = yield select(
getLayoutOnLoadIssues,
);
const actionCount = flatten(pageActions).length;
// when cyclical depedency issue is there,
// none of the page load actions would be executed
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.EXECUTE_PAGE_LOAD_ACTIONS,
{ numActions: actionCount },
);
for (const actionSet of pageActions) {
// Load all sets in parallel
// @ts-expect-error: no idea how to type this
yield* yield all(
actionSet.map((apiAction) => call(executePageLoadAction, apiAction)),
);
}
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.EXECUTE_PAGE_LOAD_ACTIONS,
);
// We show errors in the debugger once onPageLoad actions
// are executed
yield put(hideDebuggerErrors(false));
checkAndLogErrorsIfCyclicDependency(layoutOnLoadActionErrors);
} catch (e) {
log.error(e);
Toaster.show({
text: createMessage(ERROR_FAIL_ON_PAGE_LOAD_ACTIONS),
variant: Variant.danger,
});
}
}
type ExecutePluginActionResponse = {
payload: ActionResponse;
isError: boolean;
};
/*
* This saga handles the complete plugin action execution flow. It will respond with a
* payload and isError property which indicates if the response is of an error type.
* In case of the execution was not completed, it will throw errors of type
* PluginActionExecutionError which needs to be handled by any saga that calls this.
* */
function* executePluginActionSaga(
actionOrActionId: PageAction | string,
paginationField?: PaginationField,
params?: Record<string, unknown>,
) {
let pluginAction;
let actionId;
if (isString(actionOrActionId)) {
// @ts-expect-error: plugin Action can take many types
pluginAction = yield select(getAction, actionOrActionId);
actionId = actionOrActionId;
} else {
pluginAction = shouldBeDefined<Action>(
yield select(getAction, actionOrActionId.id),
`Action not found for id -> ${actionOrActionId.id}`,
);
actionId = actionOrActionId.id;
}
if (pluginAction.confirmBeforeExecute) {
const modalPayload = {
name: pluginAction.name,
modalOpen: true,
modalType: ModalType.RUN_ACTION,
};
const confirmed: unknown = yield call(
requestModalConfirmationSaga,
modalPayload,
);
if (!confirmed) {
yield put({
type: ReduxActionTypes.RUN_ACTION_CANCELLED,
payload: { id: actionId },
});
throw new UserCancelledActionExecutionError();
}
}
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.EXECUTE_ACTION,
{
actionId: actionId,
},
actionId,
);
yield put(executePluginActionRequest({ id: actionId }));
const appMode: APP_MODE | undefined = yield select(getAppMode);
const timeout: number | undefined = yield select(getActionTimeout, actionId);
const executeActionRequest: ExecuteActionRequest = {
actionId: actionId,
viewMode: appMode === APP_MODE.PUBLISHED,
paramProperties: {},
};
if (paginationField) {
executeActionRequest.paginationField = paginationField;
}
const formData = new FormData();
yield call(
evaluateActionParams,
pluginAction.jsonPathKeys,
formData,
executeActionRequest,
params,
);
try {
const response: ActionExecutionResponse = yield ActionAPI.executeAction(
formData,
timeout,
);
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.EXECUTE_ACTION,
);
yield validateResponse(response);
const payload = createActionExecutionResponse(response);
yield put(
executePluginActionSuccess({
id: actionId,
response: payload,
}),
);
let plugin: Plugin | undefined;
if (!!pluginAction.pluginId) {
plugin = shouldBeDefined<Plugin>(
yield select(getPlugin, pluginAction.pluginId),
`Plugin not found for id - ${pluginAction.pluginId}`,
);
}
// sets the default display format for action response e.g Raw, Json or Table
yield setDefaultActionDisplayFormat(actionId, plugin, payload);
return {
payload,
isError: isErrorResponse(response),
};
} catch (e) {
yield put(
executePluginActionSuccess({
id: actionId,
response: EMPTY_RESPONSE,
}),
);
if (e instanceof UserCancelledActionExecutionError) {
throw new UserCancelledActionExecutionError();
}
throw new PluginActionExecutionError("Response not valid", false);
}
}
export function* watchPluginActionExecutionSagas() {
yield all([
takeLatest(ReduxActionTypes.RUN_ACTION_REQUEST, runActionSaga),
takeLatest(
ReduxActionTypes.RUN_ACTION_SHORTCUT_REQUEST,
runActionShortcutSaga,
),
takeLatest(
ReduxActionTypes.EXECUTE_PAGE_LOAD_ACTIONS,
executePageLoadActionsSaga,
),
]);
}