import { createImmerReducer } from "utils/ReducerUtils"; import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants"; import { ReduxActionTypes, ReduxActionErrorTypes, } from "@appsmith/constants/ReduxActionConstants"; import type { ActionResponse } from "api/ActionAPI"; import type { ExecuteErrorPayload } from "constants/AppsmithActionConstants/ActionConstants"; import _ from "lodash"; import type { Action } from "entities/Action"; import type { UpdateActionPropertyActionPayload } from "actions/pluginActionActions"; export interface ActionData { isLoading: boolean; config: Action; data?: ActionResponse; } export interface ActionDataWithMeta extends ActionData { responseMeta: { headers?: unknown; isExecutionSuccess: boolean; statusCode?: string; }; } export type ActionDataState = ActionData[]; export interface PartialActionData { isLoading: boolean; config: { id: string }; data?: ActionResponse; } const initialState: ActionDataState = []; const actionsReducer = createImmerReducer(initialState, { [ReduxActionTypes.FETCH_ACTIONS_SUCCESS]: ( draftMetaState: ActionDataState, action: ReduxAction, ) => { return action.payload.map((action) => { const foundAction = draftMetaState.find((currentAction) => { return currentAction.config.id === action.id; }); return { isLoading: false, config: action, data: foundAction?.data, }; }); }, [ReduxActionTypes.FETCH_ACTIONS_VIEW_MODE_SUCCESS]: ( _: ActionDataState, action: ReduxAction, ) => { return action.payload.map((a) => ({ isLoading: false, config: a, })); }, [ReduxActionTypes.FETCH_ACTIONS_FOR_PAGE_SUCCESS]: ( draftMetaState: ActionDataState, action: ReduxAction, ) => { if (action.payload.length > 0) { const stateActionMap = _.keyBy(draftMetaState, "config.id"); const result: ActionDataState = []; action.payload.forEach((actionPayload: Action) => { const stateAction = stateActionMap[actionPayload.id]; if (stateAction) { result.push({ data: stateAction.data, isLoading: false, config: actionPayload, }); delete stateActionMap[actionPayload.id]; } else { result.push({ isLoading: false, config: actionPayload, }); } }); Object.keys(stateActionMap).forEach((stateActionKey) => { result.push(stateActionMap[stateActionKey]); }); return result; } }, [ReduxActionTypes.SUBMIT_CURL_FORM_SUCCESS]: ( draftMetaState: ActionDataState, action: ReduxAction, ) => { return draftMetaState.concat([ { config: action.payload, isLoading: false }, ]); }, [ReduxActionErrorTypes.FETCH_ACTIONS_ERROR]: () => initialState, [ReduxActionErrorTypes.FETCH_ACTIONS_VIEW_MODE_ERROR]: () => initialState, [ReduxActionTypes.CREATE_ACTION_INIT]: ( draftMetaState: ActionDataState, action: ReduxAction, ) => { return draftMetaState.concat([ { config: { ...action.payload, id: action.payload.name }, isLoading: false, }, ]); }, [ReduxActionTypes.CREATE_ACTION_SUCCESS]: ( draftMetaState: ActionDataState, action: ReduxAction, ) => { draftMetaState.forEach((a) => { if ( a.config.pageId === action.payload.pageId && a.config.id === action.payload.name ) { a.config = action.payload; } }); }, [ReduxActionErrorTypes.CREATE_ACTION_ERROR]: ( draftMetaState: ActionDataState, action: ReduxAction, ) => { return draftMetaState.filter( (a) => a.config.name !== action.payload.name && a.config.id !== action.payload.name, ); }, [ReduxActionTypes.UPDATE_ACTION_SUCCESS]: ( draftMetaState: ActionDataState, action: ReduxAction<{ data: Action }>, ) => { draftMetaState.forEach((a) => { if (a.config.id === action.payload.data.id) { a.config = action.payload.data; } }); }, [ReduxActionTypes.UPDATE_ACTION_PROPERTY]: ( draftMetaState: ActionDataState, action: ReduxAction, ) => { draftMetaState.forEach((a) => { if (a.config.id === action.payload.id) { return _.set(a, `config.${action.payload.field}`, action.payload.value); } }); }, [ReduxActionTypes.DELETE_ACTION_SUCCESS]: ( draftMetaState: ActionDataState, action: ReduxAction<{ id: string }>, ) => { return draftMetaState.filter((a) => a.config.id !== action.payload.id); }, [ReduxActionTypes.EXECUTE_PLUGIN_ACTION_REQUEST]: ( draftMetaState: ActionDataState, action: ReduxAction<{ id: string }>, ) => { draftMetaState.forEach((a) => { if (a.config.id === action.payload.id) { a.isLoading = true; } }); }, [ReduxActionTypes.EXECUTE_PLUGIN_ACTION_SUCCESS]: ( draftMetaState: Array, action: ReduxAction<{ id: string; response: ActionResponse }>, ) => { const foundAction = draftMetaState.find((stateAction) => { return stateAction.config.id === action.payload.id; }); if (foundAction) { foundAction.isLoading = false; if (foundAction.data) _.assign(foundAction.data, action.payload.response); else foundAction.data = action.payload.response; } else { const partialAction: PartialActionData = { isLoading: false, config: { id: action.payload.id }, data: action.payload.response, }; draftMetaState.push(partialAction); } }, [ReduxActionTypes.SET_ACTION_RESPONSE_DISPLAY_FORMAT]: ( draftMetaState: ActionDataState, action: ReduxAction, ) => { draftMetaState.forEach((a) => { if (a.config.id === action.payload.id) { return _.set(a, `data.${action.payload.field}`, action.payload.value); } }); }, [ReduxActionTypes.CLEAR_ACTION_RESPONSE]: ( draftMetaState: ActionDataState, action: ReduxAction<{ actionId: string }>, ) => { draftMetaState.forEach((stateAction) => { if (stateAction.config.id === action.payload.actionId) { stateAction.data = undefined; } }); }, [ReduxActionErrorTypes.EXECUTE_PLUGIN_ACTION_ERROR]: ( draftMetaState: ActionDataState, action: ReduxAction, ) => { draftMetaState.forEach((a) => { if (a.config.id === action.payload.actionId) { a.isLoading = false; a.data = action.payload.data; } }); }, [ReduxActionTypes.RUN_ACTION_REQUEST]: ( draftMetaState: ActionDataState, action: ReduxAction<{ id: string }>, ) => { draftMetaState.forEach((a) => { if (action.payload.id === a.config.id) { a.isLoading = true; } }); }, [ReduxActionTypes.RUN_ACTION_SUCCESS]: ( draftMetaState: ActionDataState, action: ReduxAction<{ [id: string]: ActionResponse }>, ) => { const actionId = Object.keys(action.payload)[0]; draftMetaState.forEach((a) => { if (a.config.id === actionId) { a.isLoading = false; if (a.data) _.assign(a.data, action.payload[actionId]); else a.data = action.payload[actionId]; } }); }, [ReduxActionErrorTypes.RUN_ACTION_ERROR]: ( draftMetaState: ActionDataState, action: ReduxAction<{ id: string }>, ) => { draftMetaState.forEach((a) => { if (a.config.id === action.payload.id) { a.isLoading = false; } }); }, [ReduxActionTypes.RUN_ACTION_CANCELLED]: ( draftMetaState: ActionDataState, action: ReduxAction<{ id: string }>, ) => { draftMetaState.forEach((a) => { if (a.config.id === action.payload.id) { a.isLoading = false; } }); }, [ReduxActionTypes.MOVE_ACTION_INIT]: ( draftMetaState: ActionDataState, action: ReduxAction<{ id: string; destinationPageId: string; name: string; }>, ) => { draftMetaState.forEach((a) => { if (a.config.id === action.payload.id) { a.config.name = action.payload.name; a.config.pageId = action.payload.destinationPageId; } }); }, [ReduxActionTypes.MOVE_ACTION_SUCCESS]: ( draftMetaState: ActionDataState, action: ReduxAction, ) => { draftMetaState.forEach((a) => { if (a.config.id === action.payload.id) { a.config = action.payload; } }); }, [ReduxActionErrorTypes.MOVE_ACTION_ERROR]: ( draftMetaState: ActionDataState, action: ReduxAction<{ id: string; originalPageId: string }>, ) => { draftMetaState.forEach((a) => { if (a.config.id === action.payload.id) { a.config.pageId = action.payload.originalPageId; } }); }, [ReduxActionTypes.COPY_ACTION_INIT]: ( draftMetaState: ActionDataState, action: ReduxAction<{ id: string; destinationPageId: string; name: string; }>, ) => { return draftMetaState.concat( draftMetaState .filter((a) => a.config.id === action.payload.id) .map((a) => ({ ...a, data: undefined, config: { ...a.config, id: "TEMP_COPY_ID", name: action.payload.name, pageId: action.payload.destinationPageId, }, })), ); }, [ReduxActionTypes.COPY_ACTION_SUCCESS]: ( draftMetaState: ActionDataState, action: ReduxAction, ) => { draftMetaState.forEach((a) => { if ( a.config.pageId === action.payload.pageId && a.config.name === action.payload.name ) { a.config = action.payload; } }); }, [ReduxActionErrorTypes.COPY_ACTION_ERROR]: ( draftMetaState: ActionDataState, action: ReduxAction<{ id: string; destinationPageId: string; name: string; }>, ) => { return draftMetaState.filter((a) => { if (a.config.pageId === action.payload.destinationPageId) { if ( a.config.id === action.payload.id || a.config.id === "TEMP_COPY_ID" ) { return a.config.name !== action.payload.name; } return true; } return true; }); }, [ReduxActionTypes.SET_ACTION_TO_EXECUTE_ON_PAGELOAD]: ( draftMetaState: ActionDataState, action: ReduxAction< Array<{ executeOnLoad: boolean; id: string; name: string; }> >, ) => { const actionUpdateSearch = _.keyBy(action.payload, "id"); draftMetaState.forEach((action) => { if (action.config.id in actionUpdateSearch) { action.config.executeOnLoad = actionUpdateSearch[action.config.id].executeOnLoad; } }); }, [ReduxActionTypes.SWITCH_CURRENT_PAGE_ID]: ( draftMetaState: ActionDataState, ) => { draftMetaState.forEach((a) => { a.data = undefined; }); }, }); export default actionsReducer;