PromucFlow_constructor/app/client/src/sagas/ActionSagas.ts
Rishabh Rathod bef48e8a79
chore: Config changes (#8564)
Change eslint config for console logging from error to warn
Add babel auto-import resolver to avoid using relative paths
2021-11-05 11:19:19 +05:30

995 lines
29 KiB
TypeScript

import {
EvaluationReduxAction,
ReduxAction,
ReduxActionErrorTypes,
ReduxActionTypes,
} from "constants/ReduxActionConstants";
import {
all,
call,
put,
race,
select,
take,
takeEvery,
takeLatest,
} from "redux-saga/effects";
import { Datasource } from "entities/Datasource";
import ActionAPI, { ActionCreateUpdateResponse } from "api/ActionAPI";
import { GenericApiResponse } from "api/ApiResponses";
import PageApi from "api/PageApi";
import { updateCanvasWithDSL } from "sagas/PageSagas";
import {
copyActionError,
copyActionSuccess,
createActionRequest,
createActionSuccess,
deleteActionSuccess,
fetchActionsForPage,
fetchActionsForPageSuccess,
FetchActionsPayload,
moveActionError,
moveActionSuccess,
SetActionPropertyPayload,
updateAction,
updateActionProperty,
updateActionSuccess,
} from "actions/pluginActionActions";
import {
DynamicPath,
isChildPropertyPath,
isDynamicValue,
removeBindingsFromActionObject,
} from "utils/DynamicBindingUtils";
import { validateResponse } from "./ErrorSagas";
import { transformRestAction } from "transformers/RestActionTransformer";
import {
getActionById,
getCurrentApplicationId,
getCurrentPageId,
} from "selectors/editorSelectors";
import AnalyticsUtil from "utils/AnalyticsUtil";
import {
Action,
ActionViewMode,
PluginType,
SlashCommand,
SlashCommandPayload,
} from "entities/Action";
import {
ActionData,
ActionDataState,
} from "reducers/entityReducers/actionsReducer";
import {
getAction,
getCurrentPageNameByActionId,
getEditorConfig,
getPageNameByPageId,
getPlugin,
getSettingConfig,
getDatasources,
getActions,
} from "selectors/entitiesSelector";
import history from "utils/history";
import {
API_EDITOR_ID_URL,
BUILDER_PAGE_URL,
INTEGRATION_EDITOR_URL,
INTEGRATION_TABS,
QUERIES_EDITOR_ID_URL,
} from "constants/routes";
import { Toaster } from "components/ads/Toast";
import { Variant } from "components/ads/common";
import PerformanceTracker, {
PerformanceTransactionName,
} from "utils/PerformanceTracker";
import {
ACTION_COPY_SUCCESS,
ACTION_MOVE_SUCCESS,
createMessage,
ERROR_ACTION_COPY_FAIL,
ERROR_ACTION_MOVE_FAIL,
ERROR_ACTION_RENAME_FAIL,
} from "constants/messages";
import _, { merge, get } from "lodash";
import { getConfigInitialValues } from "components/formControls/utils";
import AppsmithConsole from "utils/AppsmithConsole";
import { ENTITY_TYPE } from "entities/AppsmithConsole";
import { SAAS_EDITOR_API_ID_URL } from "pages/Editor/SaaSEditor/constants";
import LOG_TYPE from "entities/AppsmithConsole/logtype";
import { createNewApiAction } from "actions/apiPaneActions";
import {
createNewApiName,
createNewQueryName,
getQueryParams,
} from "utils/AppsmithUtils";
import { DEFAULT_API_ACTION_CONFIG } from "constants/ApiEditorConstants";
import {
toggleShowGlobalSearchModal,
setGlobalSearchFilterContext,
} from "actions/globalSearchActions";
import {
filterCategories,
SEARCH_CATEGORY_ID,
} from "components/editorComponents/GlobalSearch/utils";
import { getSelectedWidget, getWidgetById } from "./selectors";
import {
onApiEditor,
onQueryEditor,
} from "components/editorComponents/Debugger/helpers";
import { Plugin } from "api/PluginApi";
import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer";
import { SnippetAction } from "reducers/uiReducers/globalSearchReducer";
import * as log from "loglevel";
export function* createActionSaga(
actionPayload: ReduxAction<
Partial<Action> & { eventData: any; pluginId: string }
>,
) {
try {
let payload = actionPayload.payload;
if (actionPayload.payload.pluginId) {
const editorConfig = yield select(
getEditorConfig,
actionPayload.payload.pluginId,
);
const settingConfig = yield select(
getSettingConfig,
actionPayload.payload.pluginId,
);
let initialValues = yield call(getConfigInitialValues, editorConfig);
if (settingConfig) {
const settingInitialValues = yield call(
getConfigInitialValues,
settingConfig,
);
initialValues = merge(initialValues, settingInitialValues);
}
payload = merge(initialValues, actionPayload.payload);
}
const response: ActionCreateUpdateResponse = yield ActionAPI.createAction(
payload,
);
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
const pageName = yield select(
getCurrentPageNameByActionId,
response.data.id,
);
AnalyticsUtil.logEvent("CREATE_ACTION", {
id: response.data.id,
actionName: response.data.name,
pageName: pageName,
...actionPayload.payload.eventData,
});
AppsmithConsole.info({
text: `Action created`,
source: {
type: ENTITY_TYPE.ACTION,
id: response.data.id,
name: response.data.name,
},
});
const newAction = response.data;
yield put(createActionSuccess(newAction));
}
} catch (error) {
yield put({
type: ReduxActionErrorTypes.CREATE_ACTION_ERROR,
payload: actionPayload.payload,
});
}
}
export function* fetchActionsSaga(
action: EvaluationReduxAction<FetchActionsPayload>,
) {
const { applicationId } = action.payload;
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.FETCH_ACTIONS_API,
{ mode: "EDITOR", appId: applicationId },
);
try {
const response: GenericApiResponse<Action[]> = yield ActionAPI.fetchActions(
applicationId,
);
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
yield put({
type: ReduxActionTypes.FETCH_ACTIONS_SUCCESS,
payload: response.data,
postEvalActions: action.postEvalActions,
});
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_ACTIONS_API,
);
}
} catch (error) {
yield put({
type: ReduxActionErrorTypes.FETCH_ACTIONS_ERROR,
payload: { error },
});
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_ACTIONS_API,
{ failed: true },
);
}
}
export function* fetchActionsForViewModeSaga(
action: ReduxAction<FetchActionsPayload>,
) {
const { applicationId } = action.payload;
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.FETCH_ACTIONS_API,
{ mode: "VIEWER", appId: applicationId },
);
try {
const response: GenericApiResponse<ActionViewMode[]> = yield ActionAPI.fetchActionsForViewMode(
applicationId,
);
const correctFormatResponse = response.data.map((action) => {
return {
...action,
actionConfiguration: {
timeoutInMillisecond: action.timeoutInMillisecond,
},
};
});
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
yield put({
type: ReduxActionTypes.FETCH_ACTIONS_VIEW_MODE_SUCCESS,
payload: correctFormatResponse,
});
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_ACTIONS_API,
);
}
} catch (error) {
yield put({
type: ReduxActionErrorTypes.FETCH_ACTIONS_VIEW_MODE_ERROR,
payload: { error },
});
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_ACTIONS_API,
{ failed: true },
);
}
}
export function* fetchActionsForPageSaga(
action: EvaluationReduxAction<{ pageId: string }>,
) {
const { pageId } = action.payload;
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_ACTIONS_API,
{ pageId: pageId },
);
try {
const response: GenericApiResponse<Action[]> = yield call(
ActionAPI.fetchActionsByPageId,
pageId,
);
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
yield put(
fetchActionsForPageSuccess(response.data, action.postEvalActions),
);
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_ACTIONS_API,
);
}
} catch (error) {
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.FETCH_PAGE_ACTIONS_API,
{ failed: true },
);
yield put({
type: ReduxActionErrorTypes.FETCH_ACTIONS_FOR_PAGE_ERROR,
payload: { error },
});
}
}
export function* updateActionSaga(actionPayload: ReduxAction<{ id: string }>) {
try {
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.UPDATE_ACTION_API,
{ actionid: actionPayload.payload.id },
);
let action = yield select(getAction, actionPayload.payload.id);
if (!action) throw new Error("Could not find action to update");
const isApi = action.pluginType === PluginType.API;
if (isApi) {
action = transformRestAction(action);
}
const response: GenericApiResponse<Action> = yield ActionAPI.updateAction(
action,
);
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
const pageName = yield select(
getCurrentPageNameByActionId,
response.data.id,
);
if (action.pluginType === PluginType.DB) {
AnalyticsUtil.logEvent("SAVE_QUERY", {
queryName: action.name,
pageName,
});
} else if (action.pluginType === PluginType.API) {
AnalyticsUtil.logEvent("SAVE_API", {
apiId: response.data.id,
apiName: response.data.name,
pageName: pageName,
});
} else if (action.pluginType === PluginType.SAAS) {
AnalyticsUtil.logEvent("SAVE_SAAS", {
apiId: response.data.id,
apiName: response.data.name,
pageName: pageName,
});
}
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.UPDATE_ACTION_API,
);
yield put(updateActionSuccess({ data: response.data }));
}
} catch (error) {
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.UPDATE_ACTION_API,
{ failed: true },
);
yield put({
type: ReduxActionErrorTypes.UPDATE_ACTION_ERROR,
payload: { error, id: actionPayload.payload.id },
});
}
}
export function* deleteActionSaga(
actionPayload: ReduxAction<{
id: string;
name: string;
onSuccess?: () => void;
}>,
) {
try {
const id = actionPayload.payload.id;
const name = actionPayload.payload.name;
const action: Action | undefined = yield select(getAction, id);
if (!action) return;
const isApi = action.pluginType === PluginType.API;
const isQuery = action.pluginType === PluginType.DB;
const isSaas = action.pluginType === PluginType.SAAS;
const response: GenericApiResponse<Action> = yield ActionAPI.deleteAction(
id,
);
const isValidResponse = yield validateResponse(response);
if (!isValidResponse) {
return;
}
if (isApi) {
const pageName = yield select(getCurrentPageNameByActionId, id);
AnalyticsUtil.logEvent("DELETE_API", {
apiName: name,
pageName,
apiID: id,
});
}
if (isSaas) {
const pageName = yield select(getCurrentPageNameByActionId, id);
AnalyticsUtil.logEvent("DELETE_SAAS", {
apiName: name,
pageName,
apiID: id,
});
}
if (isQuery) {
AnalyticsUtil.logEvent("DELETE_QUERY", {
queryName: name,
});
}
if (!!actionPayload.payload.onSuccess) {
actionPayload.payload.onSuccess();
} else {
const pageId = yield select(getCurrentPageId);
const applicationId = yield select(getCurrentApplicationId);
history.push(
INTEGRATION_EDITOR_URL(applicationId, pageId, INTEGRATION_TABS.NEW),
);
}
AppsmithConsole.info({
logType: LOG_TYPE.ENTITY_DELETED,
text: "Action was deleted",
source: {
type: ENTITY_TYPE.ACTION,
name: response.data.name,
id: response.data.id,
},
analytics: {
pluginId: action.pluginId,
},
});
yield put(deleteActionSuccess({ id }));
} catch (error) {
yield put({
type: ReduxActionErrorTypes.DELETE_ACTION_ERROR,
payload: { error, id: actionPayload.payload.id },
});
}
}
function* moveActionSaga(
action: ReduxAction<{
id: string;
destinationPageId: string;
originalPageId: string;
name: string;
}>,
) {
const actionObject: Action = yield select(getAction, action.payload.id);
const withoutBindings = removeBindingsFromActionObject(actionObject);
try {
const response = yield ActionAPI.moveAction({
action: {
...withoutBindings,
pageId: action.payload.originalPageId,
name: action.payload.name,
},
destinationPageId: action.payload.destinationPageId,
});
const isValidResponse = yield validateResponse(response);
const pageName = yield select(getPageNameByPageId, response.data.pageId);
if (isValidResponse) {
Toaster.show({
text: createMessage(ACTION_MOVE_SUCCESS, response.data.name, pageName),
variant: Variant.success,
});
}
AnalyticsUtil.logEvent("MOVE_API", {
apiName: response.data.name,
pageName: pageName,
apiID: response.data.id,
});
yield put(moveActionSuccess(response.data));
} catch (e) {
Toaster.show({
text: createMessage(ERROR_ACTION_MOVE_FAIL, actionObject.name),
variant: Variant.danger,
});
yield put(
moveActionError({
id: action.payload.id,
originalPageId: action.payload.originalPageId,
}),
);
}
}
function* copyActionSaga(
action: ReduxAction<{ id: string; destinationPageId: string; name: string }>,
) {
let actionObject: Action = yield select(getAction, action.payload.id);
try {
if (!actionObject) throw new Error("Could not find action to copy");
if (action.payload.destinationPageId !== actionObject.pageId) {
actionObject = removeBindingsFromActionObject(actionObject);
}
const copyAction = Object.assign({}, actionObject, {
name: action.payload.name,
pageId: action.payload.destinationPageId,
}) as Partial<Action>;
delete copyAction.id;
const response = yield ActionAPI.createAction(copyAction);
const datasources = yield select(getDatasources);
const isValidResponse = yield validateResponse(response);
const pageName = yield select(getPageNameByPageId, response.data.pageId);
if (isValidResponse) {
Toaster.show({
text: createMessage(ACTION_COPY_SUCCESS, actionObject.name, pageName),
variant: Variant.success,
});
}
AnalyticsUtil.logEvent("DUPLICATE_API", {
apiName: response.data.name,
pageName: pageName,
apiID: response.data.id,
});
// checking if there is existing datasource to be added to the action payload
const existingDatasource = datasources.find(
(d: Datasource) => d.id === response.data.datasource.id,
);
let payload = response.data;
if (existingDatasource) {
payload = { ...payload, datasource: existingDatasource };
}
yield put(copyActionSuccess(payload));
} catch (e) {
const actionName = actionObject ? actionObject.name : "";
Toaster.show({
text: createMessage(ERROR_ACTION_COPY_FAIL, actionName),
variant: Variant.danger,
});
yield put(copyActionError(action.payload));
}
}
export function* refactorActionName(
id: string,
pageId: string,
oldName: string,
newName: string,
) {
// fetch page of the action
PerformanceTracker.startAsyncTracking(
PerformanceTransactionName.REFACTOR_ACTION_NAME,
{ actionId: id },
);
const pageResponse = yield call(PageApi.fetchPage, {
id: pageId,
});
// check if page request is successful
const isPageRequestSuccessful = yield validateResponse(pageResponse);
if (isPageRequestSuccessful) {
// get the layoutId from the page response
const layoutId = pageResponse.data.layouts[0].id;
// call to refactor action
const refactorResponse = yield ActionAPI.updateActionName({
layoutId,
actionId: id,
pageId: pageId,
oldName: oldName,
newName: newName,
});
const isRefactorSuccessful = yield validateResponse(refactorResponse);
const currentPageId = yield select(getCurrentPageId);
PerformanceTracker.stopAsyncTracking(
PerformanceTransactionName.REFACTOR_ACTION_NAME,
{ isSuccess: isRefactorSuccessful },
);
if (isRefactorSuccessful) {
yield put({
type: ReduxActionTypes.SAVE_ACTION_NAME_SUCCESS,
payload: {
actionId: id,
},
});
if (currentPageId === pageId) {
yield updateCanvasWithDSL(refactorResponse.data, pageId, layoutId);
} else {
yield put(fetchActionsForPage(pageId));
}
}
}
}
function* bindDataOnCanvasSaga(
action: ReduxAction<{
queryId: string;
applicationId: string;
pageId: string;
}>,
) {
const { pageId, queryId } = action.payload;
const applicationId = yield select(getCurrentApplicationId);
history.push(
BUILDER_PAGE_URL({
applicationId,
pageId,
params: {
isSnipingMode: "true",
bindTo: queryId,
},
}),
);
}
function* saveActionName(action: ReduxAction<{ id: string; name: string }>) {
// Takes from state, checks if the name isValid, saves
const apiId = action.payload.id;
const api = yield select((state) =>
state.entities.actions.find(
(action: ActionData) => action.config.id === apiId,
),
);
try {
yield refactorActionName(
api.config.id,
api.config.pageId,
api.config.name,
action.payload.name,
);
} catch (e) {
yield put({
type: ReduxActionErrorTypes.SAVE_ACTION_NAME_ERROR,
payload: {
actionId: action.payload.id,
oldName: api.config.name,
},
});
Toaster.show({
text: createMessage(ERROR_ACTION_RENAME_FAIL, action.payload.name),
variant: Variant.danger,
});
log.error(e);
}
}
function getDynamicBindingsChangesSaga(
action: Action,
value: unknown,
field: string,
) {
const bindingField = field.replace("actionConfiguration.", "");
let dynamicBindings: DynamicPath[] = action.dynamicBindingPathList || [];
if (typeof value === "object") {
dynamicBindings = dynamicBindings.filter((dynamicPath) => {
if (isChildPropertyPath(bindingField, dynamicPath.key)) {
const childPropertyValue = _.get(value, dynamicPath.key);
return isDynamicValue(childPropertyValue);
}
});
} else if (typeof value === "string") {
const fieldExists = _.some(dynamicBindings, { key: bindingField });
const isDynamic = isDynamicValue(value);
if (!isDynamic && fieldExists) {
dynamicBindings = dynamicBindings.filter((d) => d.key !== bindingField);
}
if (isDynamic && !fieldExists) {
dynamicBindings.push({ key: bindingField });
}
}
return dynamicBindings;
}
function* setActionPropertySaga(action: ReduxAction<SetActionPropertyPayload>) {
const { actionId, propertyName, value } = action.payload;
if (!actionId) return;
if (propertyName === "name") return;
const actionObj = yield select(getAction, actionId);
const fieldToBeUpdated = propertyName.replace(
"actionConfiguration",
"config",
);
AppsmithConsole.info({
logType: LOG_TYPE.ACTION_UPDATE,
text: "Configuration updated",
source: {
type: ENTITY_TYPE.ACTION,
name: actionObj.name,
id: actionId,
propertyPath: fieldToBeUpdated,
},
state: {
[fieldToBeUpdated]: value,
},
});
const effects: Record<string, any> = {};
// Value change effect
effects[propertyName] = value;
// Bindings change effect
effects.dynamicBindingPathList = getDynamicBindingsChangesSaga(
actionObj,
value,
propertyName,
);
yield all(
Object.keys(effects).map((field) =>
put(updateActionProperty({ id: actionId, field, value: effects[field] })),
),
);
if (propertyName === "executeOnLoad") {
yield put({
type: ReduxActionTypes.TOGGLE_ACTION_EXECUTE_ON_LOAD_INIT,
payload: {
actionId,
shouldExecute: value,
},
});
return;
}
yield put(updateAction({ id: actionId }));
}
function* toggleActionExecuteOnLoadSaga(
action: ReduxAction<{ actionId: string; shouldExecute: boolean }>,
) {
try {
const response = yield call(
ActionAPI.toggleActionExecuteOnLoad,
action.payload.actionId,
action.payload.shouldExecute,
);
const isValidResponse = yield validateResponse(response);
if (isValidResponse) {
yield put({
type: ReduxActionTypes.TOGGLE_ACTION_EXECUTE_ON_LOAD_SUCCESS,
});
}
} catch (error) {
yield put({
type: ReduxActionErrorTypes.TOGGLE_ACTION_EXECUTE_ON_LOAD_ERROR,
payload: error,
});
}
}
function* handleMoveOrCopySaga(actionPayload: ReduxAction<{ id: string }>) {
const { id } = actionPayload.payload;
const action: Action = yield select(getAction, id);
const isApi = action.pluginType === PluginType.API;
const isQuery = action.pluginType === PluginType.DB;
const isSaas = action.pluginType === PluginType.SAAS;
const applicationId = yield select(getCurrentApplicationId);
if (isApi) {
history.push(API_EDITOR_ID_URL(applicationId, action.pageId, action.id));
}
if (isQuery) {
history.push(
QUERIES_EDITOR_ID_URL(applicationId, action.pageId, action.id),
);
}
if (isSaas) {
const plugin = yield select(getPlugin, action.pluginId);
history.push(
SAAS_EDITOR_API_ID_URL(
applicationId,
action.pageId,
plugin.packageName,
action.id,
),
);
}
}
function* buildMetaForSnippets(
entityId: any,
entityType: string,
expectedType: string,
propertyPath: string,
) {
/*
Score is set to sort the snippets in the following order.
1. Field (10)
2. Entity + (All Queries / All Widgets) +Data Type (9)
3. Entity + Data Type (8)
4. Entity (5)
5. All Queries / All Widgets + Data Type (4)
6. All Queries / All Widgets 1
*/
/*
UNKNOWN is given priority over other non matching dataTypes.
Eg. If there are no snippets matching a dataType criteria, we are promote snippets of type UNKNOWN
*/
const refinements: any = {
entities: [entityType],
};
const fieldMeta: {
dataType: Array<string>;
fields?: Array<string>;
entities?: Array<string>;
} = {
dataType: [`${expectedType}<score=3>`, `UNKNOWN<score=1>`],
};
if (propertyPath) {
const relevantField = propertyPath
.split(".")
.slice(-1)
.pop();
fieldMeta.fields = [`${relevantField}<score=10>`];
}
if (entityType === ENTITY_TYPE.ACTION && entityId) {
const currentEntity: Action = yield select(getActionById, {
match: { params: { apiId: entityId } },
});
const plugin: Plugin = yield select(getPlugin, currentEntity.pluginId);
const type: string = plugin.packageName || "";
refinements.entities = [type, entityType];
fieldMeta.entities = [`${type}<score=5>`, `${entityType}<score=1>`];
}
if (entityType === ENTITY_TYPE.WIDGET && entityId) {
const currentEntity: FlattenedWidgetProps = yield select(
getWidgetById,
entityId,
);
const type: string = currentEntity.type || "";
refinements.entities = [type, entityType];
fieldMeta.entities = [`${type}<score=5>`, `${entityType}<score=1>`];
}
return { refinements, fieldMeta };
}
function* getCurrentEntity(pageId: string, params: Record<string, string>) {
let entityId = "",
entityType = "";
if (onApiEditor() || onQueryEditor()) {
const id = params.apiId || params.queryId;
const action: Action = yield select(getAction, id);
entityId = action?.id;
entityType = ENTITY_TYPE.ACTION;
} else {
const widget: FlattenedWidgetProps = yield select(getSelectedWidget);
entityId = widget?.widgetId;
entityType = ENTITY_TYPE.WIDGET;
}
return { entityId, entityType };
}
function* executeCommandSaga(actionPayload: ReduxAction<SlashCommandPayload>) {
const pageId: string = yield select(getCurrentPageId);
const applicationId = yield select(getCurrentApplicationId);
const callback = get(actionPayload, "payload.callback");
const params = getQueryParams();
switch (actionPayload.payload.actionType) {
case SlashCommand.NEW_SNIPPET:
let { entityId, entityType } = get(actionPayload, "payload.args", {});
const { expectedType, propertyPath } = get(
actionPayload,
"payload.args",
{},
);
// Entity is derived using the dataTreePath property.
// Fallback to find current entity when dataTreePath property value is empty (Eg. trigger fields)
if (!entityId) {
const currentEntity: {
entityId: string;
entityType: string;
} = yield getCurrentEntity(pageId, params);
entityId = currentEntity.entityId;
entityType = currentEntity.entityType;
}
const { fieldMeta, refinements } = yield buildMetaForSnippets(
entityId,
entityType,
expectedType,
propertyPath,
);
yield put(
setGlobalSearchFilterContext({
refinements,
fieldMeta,
}),
);
yield put(
toggleShowGlobalSearchModal(
filterCategories[SEARCH_CATEGORY_ID.SNIPPETS],
),
);
yield put(
setGlobalSearchFilterContext({
onEnter:
typeof callback === "function"
? SnippetAction.INSERT
: SnippetAction.COPY, //Set insertSnippet to true only if values
hideOuterBindings: entityType === ENTITY_TYPE.JSACTION,
}),
);
AnalyticsUtil.logEvent("SNIPPET_LOOKUP");
const effectRaceResult: { failure: any; success: any } = yield race({
failure: take(ReduxActionTypes.CANCEL_SNIPPET),
success: take(ReduxActionTypes.INSERT_SNIPPET),
});
if (effectRaceResult.failure) return;
if (callback) callback(effectRaceResult.success.payload);
break;
case SlashCommand.NEW_INTEGRATION:
history.push(
INTEGRATION_EDITOR_URL(applicationId, pageId, INTEGRATION_TABS.NEW),
);
break;
case SlashCommand.NEW_QUERY:
const datasource = get(actionPayload, "payload.args.datasource");
const pluginId = get(datasource, "pluginId");
const plugin: Plugin = yield select(getPlugin, pluginId);
const actions: ActionDataState = yield select(getActions);
const pageActions = actions.filter(
(a: ActionData) => a.config.pageId === pageId,
);
const newQueryName =
plugin.type === PluginType.DB
? createNewQueryName(actions, pageId)
: createNewApiName(pageActions, pageId);
const nextPayload: Partial<Action> = {
name: newQueryName,
pageId,
eventData: {
actionType: "Query",
from: "Quick-Commands",
dataSource: datasource.name,
},
pluginId: datasource.pluginId,
actionConfiguration: {},
};
if (plugin.type === "API") {
nextPayload.datasource = datasource;
nextPayload.actionConfiguration = DEFAULT_API_ACTION_CONFIG;
} else {
nextPayload.datasource = {
id: datasource.id,
};
}
yield put(createActionRequest(nextPayload));
const QUERY = yield take(ReduxActionTypes.CREATE_ACTION_SUCCESS);
if (callback) callback(`{{${QUERY.payload.name}.data}}`);
break;
case SlashCommand.NEW_API:
yield put(createNewApiAction(pageId, "QUICK_COMMANDS"));
const API = yield take(ReduxActionTypes.CREATE_ACTION_SUCCESS);
if (callback) callback(`{{${API.payload.name}.data}}`);
break;
}
}
export function* watchActionSagas() {
yield all([
takeEvery(ReduxActionTypes.SET_ACTION_PROPERTY, setActionPropertySaga),
takeEvery(ReduxActionTypes.FETCH_ACTIONS_INIT, fetchActionsSaga),
takeEvery(
ReduxActionTypes.FETCH_ACTIONS_VIEW_MODE_INIT,
fetchActionsForViewModeSaga,
),
takeEvery(ReduxActionTypes.CREATE_ACTION_INIT, createActionSaga),
takeLatest(ReduxActionTypes.UPDATE_ACTION_INIT, updateActionSaga),
takeLatest(ReduxActionTypes.DELETE_ACTION_INIT, deleteActionSaga),
takeLatest(ReduxActionTypes.BIND_DATA_ON_CANVAS, bindDataOnCanvasSaga),
takeLatest(ReduxActionTypes.SAVE_ACTION_NAME_INIT, saveActionName),
takeLatest(ReduxActionTypes.MOVE_ACTION_INIT, moveActionSaga),
takeLatest(ReduxActionTypes.COPY_ACTION_INIT, copyActionSaga),
takeLatest(
ReduxActionTypes.FETCH_ACTIONS_FOR_PAGE_INIT,
fetchActionsForPageSaga,
),
takeEvery(ReduxActionTypes.MOVE_ACTION_SUCCESS, handleMoveOrCopySaga),
takeEvery(ReduxActionTypes.COPY_ACTION_SUCCESS, handleMoveOrCopySaga),
takeEvery(ReduxActionErrorTypes.MOVE_ACTION_ERROR, handleMoveOrCopySaga),
takeEvery(ReduxActionErrorTypes.COPY_ACTION_ERROR, handleMoveOrCopySaga),
takeLatest(
ReduxActionTypes.TOGGLE_ACTION_EXECUTE_ON_LOAD_INIT,
toggleActionExecuteOnLoadSaga,
),
takeLatest(ReduxActionTypes.EXECUTE_COMMAND, executeCommandSaga),
]);
}