2019-10-21 15:12:45 +00:00
|
|
|
import {
|
|
|
|
|
ReduxAction,
|
|
|
|
|
ReduxActionErrorTypes,
|
|
|
|
|
ReduxActionTypes,
|
2019-11-25 05:07:27 +00:00
|
|
|
} from "constants/ReduxActionConstants";
|
2019-10-21 15:12:45 +00:00
|
|
|
import { Intent } from "@blueprintjs/core";
|
2019-10-25 05:35:20 +00:00
|
|
|
import {
|
|
|
|
|
all,
|
|
|
|
|
call,
|
|
|
|
|
select,
|
|
|
|
|
put,
|
|
|
|
|
takeEvery,
|
|
|
|
|
takeLatest,
|
|
|
|
|
} from "redux-saga/effects";
|
2019-11-28 03:56:44 +00:00
|
|
|
import {
|
|
|
|
|
ActionPayload,
|
|
|
|
|
PageAction,
|
|
|
|
|
ExecuteJSActionPayload,
|
|
|
|
|
} from "constants/ActionConstants";
|
2019-10-21 15:12:45 +00:00
|
|
|
import ActionAPI, {
|
2019-11-11 11:42:52 +00:00
|
|
|
ActionApiResponse,
|
2019-10-21 15:12:45 +00:00
|
|
|
ActionCreateUpdateResponse,
|
2019-11-12 09:43:13 +00:00
|
|
|
ActionResponse,
|
2019-10-21 15:12:45 +00:00
|
|
|
ExecuteActionRequest,
|
2019-11-20 10:57:05 +00:00
|
|
|
Property,
|
2019-10-21 15:12:45 +00:00
|
|
|
RestAction,
|
2019-11-25 05:07:27 +00:00
|
|
|
} from "api/ActionAPI";
|
|
|
|
|
import { AppState, DataTree } from "reducers";
|
2019-10-21 15:12:45 +00:00
|
|
|
import _ from "lodash";
|
2019-11-25 05:07:27 +00:00
|
|
|
import { mapToPropList } from "utils/AppsmithUtils";
|
|
|
|
|
import AppToaster from "components/editorComponents/ToastComponent";
|
|
|
|
|
import { GenericApiResponse } from "api/ApiResponses";
|
2019-10-25 05:35:20 +00:00
|
|
|
import {
|
2020-01-24 09:54:40 +00:00
|
|
|
copyActionError,
|
|
|
|
|
copyActionSuccess,
|
2019-10-25 05:35:20 +00:00
|
|
|
createActionSuccess,
|
|
|
|
|
deleteActionSuccess,
|
2019-12-11 15:24:27 +00:00
|
|
|
FetchActionsPayload,
|
2020-01-24 09:54:40 +00:00
|
|
|
moveActionError,
|
|
|
|
|
moveActionSuccess,
|
2020-01-02 13:46:36 +00:00
|
|
|
runApiAction,
|
2019-10-25 05:35:20 +00:00
|
|
|
updateActionSuccess,
|
2019-11-25 05:07:27 +00:00
|
|
|
} from "actions/actionActions";
|
2019-11-20 10:57:05 +00:00
|
|
|
import {
|
|
|
|
|
getDynamicBindings,
|
2020-01-03 13:40:31 +00:00
|
|
|
getDynamicValue,
|
2019-11-20 10:57:05 +00:00
|
|
|
isDynamicValue,
|
2020-01-27 13:53:33 +00:00
|
|
|
removeBindingsFromObject,
|
2019-11-25 05:07:27 +00:00
|
|
|
} from "utils/DynamicBindingUtils";
|
2019-11-13 07:34:59 +00:00
|
|
|
import { validateResponse } from "./ErrorSagas";
|
2019-11-25 05:07:27 +00:00
|
|
|
import { getDataTree } from "selectors/entitiesSelector";
|
2019-11-14 07:42:24 +00:00
|
|
|
import {
|
|
|
|
|
ERROR_MESSAGE_SELECT_ACTION,
|
|
|
|
|
ERROR_MESSAGE_SELECT_ACTION_TYPE,
|
|
|
|
|
} from "constants/messages";
|
2019-11-20 10:57:05 +00:00
|
|
|
import { getFormData } from "selectors/formSelectors";
|
2019-11-25 05:07:27 +00:00
|
|
|
import { API_EDITOR_FORM_NAME } from "constants/forms";
|
2019-12-11 15:24:27 +00:00
|
|
|
import { executeAction } from "actions/widgetActions";
|
2019-11-28 03:56:44 +00:00
|
|
|
import JSExecutionManagerSingleton from "jsExecution/JSExecutionManagerSingleton";
|
2020-01-17 09:28:26 +00:00
|
|
|
import { getParsedDataTree } from "selectors/nameBindingsWithDataSelector";
|
2019-12-23 12:12:58 +00:00
|
|
|
import { transformRestAction } from "transformers/RestActionTransformer";
|
2019-10-21 15:12:45 +00:00
|
|
|
|
2019-11-25 09:15:11 +00:00
|
|
|
export const getAction = (
|
2019-11-05 05:09:50 +00:00
|
|
|
state: AppState,
|
|
|
|
|
actionId: string,
|
|
|
|
|
): RestAction | undefined => {
|
|
|
|
|
return _.find(state.entities.actions.data, { id: actionId });
|
2019-10-21 15:12:45 +00:00
|
|
|
};
|
|
|
|
|
|
2019-11-12 09:43:13 +00:00
|
|
|
const createActionResponse = (response: ActionApiResponse): ActionResponse => ({
|
|
|
|
|
...response.data,
|
|
|
|
|
...response.clientMeta,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const createActionErrorResponse = (
|
|
|
|
|
response: ActionApiResponse,
|
|
|
|
|
): ActionResponse => ({
|
|
|
|
|
body: response.responseMeta.error || { error: "Error" },
|
|
|
|
|
statusCode: response.responseMeta.error
|
|
|
|
|
? response.responseMeta.error.code
|
|
|
|
|
: "Error",
|
|
|
|
|
headers: {},
|
|
|
|
|
duration: "0",
|
|
|
|
|
size: "0",
|
|
|
|
|
});
|
|
|
|
|
|
2019-12-02 09:50:25 +00:00
|
|
|
export function* evaluateDynamicBoundValueSaga(path: string): any {
|
2020-01-17 09:28:26 +00:00
|
|
|
const tree = yield select(getParsedDataTree);
|
|
|
|
|
return getDynamicValue(`{{${path}}}`, tree);
|
2019-10-21 15:12:45 +00:00
|
|
|
}
|
|
|
|
|
|
2019-11-20 10:57:05 +00:00
|
|
|
export function* getActionParams(jsonPathKeys: string[] | undefined) {
|
|
|
|
|
if (_.isNil(jsonPathKeys)) return [];
|
|
|
|
|
const values: any = _.flatten(
|
|
|
|
|
yield all(
|
|
|
|
|
jsonPathKeys.map((jsonPath: string) => {
|
2019-12-02 09:50:25 +00:00
|
|
|
return call(evaluateDynamicBoundValueSaga, jsonPath);
|
2019-11-20 10:57:05 +00:00
|
|
|
}),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
const dynamicBindings: Record<string, string> = {};
|
|
|
|
|
jsonPathKeys.forEach((key, i) => {
|
2020-01-03 13:40:31 +00:00
|
|
|
let value = values[i];
|
|
|
|
|
if (typeof value === "object") value = JSON.stringify(value);
|
|
|
|
|
dynamicBindings[key] = value;
|
2019-11-20 10:57:05 +00:00
|
|
|
});
|
|
|
|
|
return mapToPropList(dynamicBindings);
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-28 03:56:44 +00:00
|
|
|
function* executeJSActionSaga(jsAction: ExecuteJSActionPayload) {
|
2020-01-17 09:28:26 +00:00
|
|
|
const tree = yield select(getParsedDataTree);
|
2019-11-28 03:56:44 +00:00
|
|
|
const result = JSExecutionManagerSingleton.evaluateSync(
|
|
|
|
|
jsAction.jsFunction,
|
2020-01-17 09:28:26 +00:00
|
|
|
tree,
|
2019-11-28 03:56:44 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.SAVE_JS_EXECUTION_RECORD,
|
|
|
|
|
payload: {
|
|
|
|
|
[jsAction.jsFunctionId]: result,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-12 08:52:13 +00:00
|
|
|
export function* executeAPIQueryActionSaga(apiAction: ActionPayload) {
|
2019-11-13 07:34:59 +00:00
|
|
|
try {
|
|
|
|
|
const api: PageAction = yield select(getAction, apiAction.actionId);
|
|
|
|
|
if (!api) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.EXECUTE_ACTION_ERROR,
|
|
|
|
|
payload: "No action selected",
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-11-20 10:57:05 +00:00
|
|
|
const params: Property[] = yield call(getActionParams, api.jsonPathKeys);
|
2019-11-13 07:34:59 +00:00
|
|
|
const executeActionRequest: ExecuteActionRequest = {
|
2019-11-20 10:57:05 +00:00
|
|
|
action: { id: apiAction.actionId },
|
|
|
|
|
params,
|
2019-11-13 07:34:59 +00:00
|
|
|
};
|
2019-11-20 08:10:01 +00:00
|
|
|
const dataTree: DataTree = yield select(getDataTree);
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.WIDGETS_LOADING,
|
|
|
|
|
payload: {
|
|
|
|
|
widgetIds:
|
|
|
|
|
dataTree.actions.actionToWidgetIdMap[apiAction.actionId] || [],
|
|
|
|
|
areLoading: true,
|
|
|
|
|
},
|
|
|
|
|
});
|
2019-11-13 07:34:59 +00:00
|
|
|
const response: ActionApiResponse = yield ActionAPI.executeAction(
|
|
|
|
|
executeActionRequest,
|
2019-10-21 15:12:45 +00:00
|
|
|
);
|
2019-11-20 08:10:01 +00:00
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.WIDGETS_LOADING,
|
|
|
|
|
payload: {
|
|
|
|
|
widgetIds:
|
|
|
|
|
dataTree.actions.actionToWidgetIdMap[apiAction.actionId] || [],
|
|
|
|
|
areLoading: false,
|
|
|
|
|
},
|
|
|
|
|
});
|
2019-11-13 07:34:59 +00:00
|
|
|
let payload = createActionResponse(response);
|
|
|
|
|
if (response.responseMeta && response.responseMeta.error) {
|
|
|
|
|
payload = createActionErrorResponse(response);
|
|
|
|
|
if (apiAction.onError) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.EXECUTE_ACTION,
|
|
|
|
|
payload: apiAction.onError,
|
|
|
|
|
});
|
|
|
|
|
}
|
2019-11-12 07:57:12 +00:00
|
|
|
yield put({
|
2019-11-13 07:34:59 +00:00
|
|
|
type: ReduxActionTypes.EXECUTE_ACTION_ERROR,
|
|
|
|
|
payload: { [apiAction.actionId]: payload },
|
2019-11-12 07:57:12 +00:00
|
|
|
});
|
2019-11-13 07:34:59 +00:00
|
|
|
} else {
|
|
|
|
|
if (apiAction.onSuccess) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.EXECUTE_ACTION,
|
|
|
|
|
payload: apiAction.onSuccess,
|
|
|
|
|
});
|
|
|
|
|
}
|
2019-11-12 07:57:12 +00:00
|
|
|
yield put({
|
2019-11-13 07:34:59 +00:00
|
|
|
type: ReduxActionTypes.EXECUTE_ACTION_SUCCESS,
|
|
|
|
|
payload: { [apiAction.actionId]: payload },
|
2019-11-12 07:57:12 +00:00
|
|
|
});
|
2019-11-12 05:22:32 +00:00
|
|
|
}
|
2019-11-13 07:34:59 +00:00
|
|
|
return response;
|
|
|
|
|
} catch (error) {
|
2019-11-12 07:57:12 +00:00
|
|
|
yield put({
|
2019-11-13 07:34:59 +00:00
|
|
|
type: ReduxActionTypes.EXECUTE_ACTION_ERROR,
|
|
|
|
|
payload: { error },
|
2019-11-12 07:57:12 +00:00
|
|
|
});
|
2019-11-06 06:35:15 +00:00
|
|
|
}
|
2019-10-21 15:12:45 +00:00
|
|
|
}
|
|
|
|
|
|
2019-11-14 07:42:24 +00:00
|
|
|
function validateActionPayload(actionPayload: ActionPayload) {
|
|
|
|
|
const validation = {
|
|
|
|
|
isValid: true,
|
|
|
|
|
messages: [] as string[],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const noActionId = actionPayload.actionId === undefined;
|
|
|
|
|
validation.isValid = validation.isValid && !noActionId;
|
|
|
|
|
if (noActionId) {
|
|
|
|
|
validation.messages.push(ERROR_MESSAGE_SELECT_ACTION);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const noActionType = actionPayload.actionType === undefined;
|
|
|
|
|
validation.isValid = validation.isValid && !noActionType;
|
|
|
|
|
if (noActionType) {
|
|
|
|
|
validation.messages.push(ERROR_MESSAGE_SELECT_ACTION_TYPE);
|
|
|
|
|
}
|
|
|
|
|
return validation;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-12 05:22:32 +00:00
|
|
|
export function* executeActionSaga(actionPayloads: ActionPayload[]): any {
|
|
|
|
|
yield all(
|
|
|
|
|
_.map(actionPayloads, (actionPayload: ActionPayload) => {
|
2019-11-14 07:42:24 +00:00
|
|
|
const actionValidation = validateActionPayload(actionPayload);
|
|
|
|
|
if (!actionValidation.isValid) {
|
|
|
|
|
console.error(actionValidation.messages.join(", "));
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
|
2019-11-12 05:22:32 +00:00
|
|
|
switch (actionPayload.actionType) {
|
|
|
|
|
case "API":
|
|
|
|
|
return call(executeAPIQueryActionSaga, actionPayload);
|
|
|
|
|
case "QUERY":
|
|
|
|
|
return call(executeAPIQueryActionSaga, actionPayload);
|
2019-11-28 03:56:44 +00:00
|
|
|
case "JS_FUNCTION":
|
|
|
|
|
return call(
|
|
|
|
|
executeJSActionSaga,
|
|
|
|
|
actionPayload as ExecuteJSActionPayload,
|
|
|
|
|
);
|
2019-11-12 05:22:32 +00:00
|
|
|
default:
|
2019-11-14 07:42:24 +00:00
|
|
|
return undefined;
|
2019-11-12 05:22:32 +00:00
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function* executeReduxActionSaga(action: ReduxAction<ActionPayload[]>) {
|
2019-10-21 15:12:45 +00:00
|
|
|
if (!_.isNil(action.payload)) {
|
2019-11-12 05:22:32 +00:00
|
|
|
yield call(executeActionSaga, action.payload);
|
2019-11-13 07:34:59 +00:00
|
|
|
} else {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.EXECUTE_ACTION_ERROR,
|
|
|
|
|
payload: "No action payload",
|
|
|
|
|
});
|
2019-10-21 15:12:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function* createActionSaga(actionPayload: ReduxAction<RestAction>) {
|
2019-11-13 07:34:59 +00:00
|
|
|
try {
|
|
|
|
|
const response: ActionCreateUpdateResponse = yield ActionAPI.createAPI(
|
|
|
|
|
actionPayload.payload,
|
|
|
|
|
);
|
|
|
|
|
const isValidResponse = yield validateResponse(response);
|
|
|
|
|
if (isValidResponse) {
|
|
|
|
|
AppToaster.show({
|
|
|
|
|
message: `${actionPayload.payload.name} Action created`,
|
|
|
|
|
intent: Intent.SUCCESS,
|
|
|
|
|
});
|
|
|
|
|
yield put(createActionSuccess(response.data));
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.CREATE_ACTION_ERROR,
|
2020-01-24 09:54:40 +00:00
|
|
|
payload: actionPayload.payload,
|
2019-10-21 15:12:45 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-11 15:24:27 +00:00
|
|
|
export function* fetchActionsSaga(action: ReduxAction<FetchActionsPayload>) {
|
2019-11-13 07:34:59 +00:00
|
|
|
try {
|
2020-01-24 09:54:40 +00:00
|
|
|
const { applicationId } = action.payload;
|
2019-12-11 15:24:27 +00:00
|
|
|
const response: GenericApiResponse<RestAction[]> = yield ActionAPI.fetchActions(
|
2020-01-24 09:54:40 +00:00
|
|
|
applicationId,
|
2019-12-11 15:24:27 +00:00
|
|
|
);
|
2019-11-13 07:34:59 +00:00
|
|
|
const isValidResponse = yield validateResponse(response);
|
|
|
|
|
if (isValidResponse) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.FETCH_ACTIONS_SUCCESS,
|
|
|
|
|
payload: response.data,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
2019-10-21 15:12:45 +00:00
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.FETCH_ACTIONS_ERROR,
|
2019-11-13 07:34:59 +00:00
|
|
|
payload: { error },
|
2019-10-21 15:12:45 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function* updateActionSaga(
|
|
|
|
|
actionPayload: ReduxAction<{ data: RestAction }>,
|
|
|
|
|
) {
|
2019-11-13 07:34:59 +00:00
|
|
|
try {
|
2019-12-23 12:12:58 +00:00
|
|
|
const { data } = actionPayload.payload;
|
|
|
|
|
const action = transformRestAction(data);
|
2019-11-13 07:34:59 +00:00
|
|
|
const response: GenericApiResponse<RestAction> = yield ActionAPI.updateAPI(
|
2019-12-23 12:12:58 +00:00
|
|
|
action,
|
2019-11-13 07:34:59 +00:00
|
|
|
);
|
|
|
|
|
const isValidResponse = yield validateResponse(response);
|
|
|
|
|
if (isValidResponse) {
|
|
|
|
|
AppToaster.show({
|
|
|
|
|
message: `${actionPayload.payload.data.name} Action updated`,
|
|
|
|
|
intent: Intent.SUCCESS,
|
|
|
|
|
});
|
|
|
|
|
yield put(updateActionSuccess({ data: response.data }));
|
2020-01-02 13:46:36 +00:00
|
|
|
yield put(runApiAction(data.id));
|
2019-11-13 07:34:59 +00:00
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.UPDATE_ACTION_ERROR,
|
2019-12-11 15:14:38 +00:00
|
|
|
payload: { error, id: actionPayload.payload.data.id },
|
2019-10-21 15:12:45 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function* deleteActionSaga(actionPayload: ReduxAction<{ id: string }>) {
|
2019-11-13 07:34:59 +00:00
|
|
|
try {
|
|
|
|
|
const id = actionPayload.payload.id;
|
2019-11-22 14:02:55 +00:00
|
|
|
const response: GenericApiResponse<RestAction> = yield ActionAPI.deleteAction(
|
|
|
|
|
id,
|
|
|
|
|
);
|
2019-11-13 07:34:59 +00:00
|
|
|
const isValidResponse = yield validateResponse(response);
|
|
|
|
|
if (isValidResponse) {
|
|
|
|
|
AppToaster.show({
|
|
|
|
|
message: `${response.data.name} Action deleted`,
|
|
|
|
|
intent: Intent.SUCCESS,
|
|
|
|
|
});
|
|
|
|
|
yield put(deleteActionSuccess({ id }));
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.DELETE_ACTION_ERROR,
|
2019-12-11 15:14:38 +00:00
|
|
|
payload: { error, id: actionPayload.payload.id },
|
2019-10-21 15:12:45 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-23 12:12:58 +00:00
|
|
|
export function* runApiActionSaga(action: ReduxAction<string>) {
|
2019-11-20 10:57:05 +00:00
|
|
|
try {
|
|
|
|
|
const {
|
|
|
|
|
values,
|
|
|
|
|
dirty,
|
|
|
|
|
valid,
|
|
|
|
|
}: { values: RestAction; dirty: boolean; valid: boolean } = yield select(
|
|
|
|
|
getFormData,
|
|
|
|
|
API_EDITOR_FORM_NAME,
|
|
|
|
|
);
|
2020-01-03 13:40:31 +00:00
|
|
|
const actionObject: PageAction = yield select(getAction, values.id);
|
2019-11-20 10:57:05 +00:00
|
|
|
let action: ExecuteActionRequest["action"] = { id: values.id };
|
2020-01-03 13:40:31 +00:00
|
|
|
let jsonPathKeys = actionObject.jsonPathKeys;
|
2019-11-20 10:57:05 +00:00
|
|
|
if (!valid) {
|
|
|
|
|
console.error("Form error");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (dirty) {
|
2019-12-23 12:12:58 +00:00
|
|
|
action = _.omit(transformRestAction(values), "id");
|
2019-11-20 10:57:05 +00:00
|
|
|
const actionString = JSON.stringify(action);
|
|
|
|
|
if (isDynamicValue(actionString)) {
|
|
|
|
|
const { paths } = getDynamicBindings(actionString);
|
|
|
|
|
// Replace cause the existing keys could have been updated
|
2020-01-03 13:40:31 +00:00
|
|
|
jsonPathKeys = paths.filter(path => !!path);
|
2019-11-20 10:57:05 +00:00
|
|
|
} else {
|
|
|
|
|
jsonPathKeys = [];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const params = yield call(getActionParams, jsonPathKeys);
|
|
|
|
|
const response: ActionApiResponse = yield ActionAPI.executeAction({
|
|
|
|
|
action,
|
|
|
|
|
params,
|
|
|
|
|
});
|
|
|
|
|
let payload = createActionResponse(response);
|
|
|
|
|
if (response.responseMeta && response.responseMeta.error) {
|
|
|
|
|
payload = createActionErrorResponse(response);
|
|
|
|
|
}
|
|
|
|
|
const id = values.id || "DRY_RUN";
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.RUN_API_SUCCESS,
|
|
|
|
|
payload: { [id]: payload },
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.RUN_API_ERROR,
|
2019-12-23 12:12:58 +00:00
|
|
|
payload: { error, id: action.payload },
|
2019-11-20 10:57:05 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-11 15:24:27 +00:00
|
|
|
function* executePageLoadActionsSaga(action: ReduxAction<PageAction[]>) {
|
|
|
|
|
const pageActions = action.payload;
|
|
|
|
|
const apiResponses = yield select(
|
|
|
|
|
(state: AppState) => state.entities.apiData,
|
|
|
|
|
);
|
|
|
|
|
const actionPayloads: ActionPayload[] = pageActions
|
|
|
|
|
.filter(action => !(action.id in apiResponses))
|
|
|
|
|
.map(action => ({
|
|
|
|
|
actionId: action.id,
|
|
|
|
|
actionType: action.pluginType,
|
|
|
|
|
contextParams: {},
|
|
|
|
|
actionName: action.name,
|
|
|
|
|
}));
|
|
|
|
|
if (actionPayloads.length) {
|
|
|
|
|
yield put(executeAction(actionPayloads));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-24 09:54:40 +00:00
|
|
|
function* moveActionSaga(
|
|
|
|
|
action: ReduxAction<{
|
|
|
|
|
id: string;
|
|
|
|
|
destinationPageId: string;
|
|
|
|
|
originalPageId: string;
|
|
|
|
|
name: string;
|
|
|
|
|
}>,
|
|
|
|
|
) {
|
|
|
|
|
const drafts = yield select(state => state.ui.apiPane.drafts);
|
|
|
|
|
const dirty = action.payload.id in drafts;
|
|
|
|
|
const actionObject: RestAction = dirty
|
|
|
|
|
? drafts[action.payload.id]
|
|
|
|
|
: yield select(getAction, action.payload.id);
|
2020-01-27 13:53:33 +00:00
|
|
|
const withoutBindings = removeBindingsFromObject(actionObject);
|
2020-01-24 09:54:40 +00:00
|
|
|
try {
|
|
|
|
|
const response = yield ActionAPI.moveAction({
|
2020-01-27 13:53:33 +00:00
|
|
|
action: {
|
|
|
|
|
...withoutBindings,
|
|
|
|
|
name: action.payload.name,
|
|
|
|
|
},
|
2020-01-24 09:54:40 +00:00
|
|
|
destinationPageId: action.payload.destinationPageId,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const isValidResponse = yield validateResponse(response);
|
|
|
|
|
if (isValidResponse) {
|
|
|
|
|
AppToaster.show({
|
|
|
|
|
message: `${response.data.name} Action moved`,
|
|
|
|
|
intent: Intent.SUCCESS,
|
|
|
|
|
});
|
|
|
|
|
}
|
2020-01-27 13:53:33 +00:00
|
|
|
yield put(moveActionSuccess(response.data));
|
2020-01-24 09:54:40 +00:00
|
|
|
} catch (e) {
|
|
|
|
|
AppToaster.show({
|
|
|
|
|
message: `Error while moving action ${actionObject.name}`,
|
|
|
|
|
intent: Intent.DANGER,
|
|
|
|
|
});
|
|
|
|
|
yield put(
|
|
|
|
|
moveActionError({
|
|
|
|
|
id: action.payload.id,
|
|
|
|
|
originalPageId: action.payload.originalPageId,
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* copyActionSaga(
|
|
|
|
|
action: ReduxAction<{ id: string; destinationPageId: string; name: string }>,
|
|
|
|
|
) {
|
|
|
|
|
const drafts = yield select(state => state.ui.apiPane.drafts);
|
|
|
|
|
const dirty = action.payload.id in drafts;
|
2020-01-27 13:53:33 +00:00
|
|
|
let actionObject = dirty
|
2020-01-24 09:54:40 +00:00
|
|
|
? drafts[action.payload.id]
|
|
|
|
|
: yield select(getAction, action.payload.id);
|
2020-01-27 13:53:33 +00:00
|
|
|
if (action.payload.destinationPageId !== actionObject.pageId) {
|
|
|
|
|
actionObject = removeBindingsFromObject(actionObject);
|
|
|
|
|
}
|
2020-01-24 09:54:40 +00:00
|
|
|
try {
|
|
|
|
|
const copyAction = {
|
|
|
|
|
...(_.omit(actionObject, "id") as RestAction),
|
|
|
|
|
name: action.payload.name,
|
|
|
|
|
pageId: action.payload.destinationPageId,
|
|
|
|
|
};
|
|
|
|
|
const response = yield ActionAPI.createAPI(copyAction);
|
|
|
|
|
|
|
|
|
|
const isValidResponse = yield validateResponse(response);
|
|
|
|
|
if (isValidResponse) {
|
|
|
|
|
AppToaster.show({
|
|
|
|
|
message: `${actionObject.name} Action copied`,
|
|
|
|
|
intent: Intent.SUCCESS,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
yield put(copyActionSuccess(response.data));
|
|
|
|
|
} catch (e) {
|
|
|
|
|
AppToaster.show({
|
|
|
|
|
message: `Error while copying action ${actionObject.name}`,
|
|
|
|
|
intent: Intent.DANGER,
|
|
|
|
|
});
|
|
|
|
|
yield put(copyActionError(action.payload));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-21 15:12:45 +00:00
|
|
|
export function* watchActionSagas() {
|
|
|
|
|
yield all([
|
|
|
|
|
takeEvery(ReduxActionTypes.FETCH_ACTIONS_INIT, fetchActionsSaga),
|
2019-11-12 05:22:32 +00:00
|
|
|
takeLatest(ReduxActionTypes.EXECUTE_ACTION, executeReduxActionSaga),
|
2019-11-20 10:57:05 +00:00
|
|
|
takeLatest(ReduxActionTypes.RUN_API_REQUEST, runApiActionSaga),
|
2019-10-25 05:35:20 +00:00
|
|
|
takeLatest(ReduxActionTypes.CREATE_ACTION_INIT, createActionSaga),
|
|
|
|
|
takeLatest(ReduxActionTypes.UPDATE_ACTION_INIT, updateActionSaga),
|
|
|
|
|
takeLatest(ReduxActionTypes.DELETE_ACTION_INIT, deleteActionSaga),
|
2019-12-11 15:24:27 +00:00
|
|
|
takeLatest(
|
|
|
|
|
ReduxActionTypes.EXECUTE_PAGE_LOAD_ACTIONS,
|
|
|
|
|
executePageLoadActionsSaga,
|
|
|
|
|
),
|
2020-01-24 09:54:40 +00:00
|
|
|
takeLatest(ReduxActionTypes.MOVE_ACTION_INIT, moveActionSaga),
|
|
|
|
|
takeLatest(ReduxActionTypes.COPY_ACTION_INIT, copyActionSaga),
|
2019-10-21 15:12:45 +00:00
|
|
|
]);
|
|
|
|
|
}
|