From c0d203638b8092bc7468020822c881b1f86dc7bb Mon Sep 17 00:00:00 2001 From: Diljit VJ Date: Fri, 17 May 2024 13:17:15 +0530 Subject: [PATCH 1/8] fix: Show loading state of application until all jsobject update calls are complete --- app/client/src/actions/jsPaneActions.ts | 18 +- .../src/ce/constants/ReduxActionConstants.tsx | 2 +- .../src/ce/selectors/entitiesSelector.ts | 3 +- .../src/reducers/uiReducers/jsPaneReducer.ts | 27 +- app/client/src/sagas/ActionSagas.ts | 2 +- app/client/src/sagas/JSPaneSagas.ts | 293 +++++++++--------- app/client/src/selectors/editorSelectors.tsx | 64 ++-- app/client/src/store.ts | 7 +- app/client/src/utils/JSPaneUtils.tsx | 17 +- 9 files changed, 226 insertions(+), 207 deletions(-) diff --git a/app/client/src/actions/jsPaneActions.ts b/app/client/src/actions/jsPaneActions.ts index 2eab41195988..6b93c02172c3 100644 --- a/app/client/src/actions/jsPaneActions.ts +++ b/app/client/src/actions/jsPaneActions.ts @@ -1,10 +1,7 @@ import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants"; import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; import type { JSCollection, JSAction } from "entities/JSCollection"; -import type { - RefactorAction, - SetFunctionPropertyPayload, -} from "@appsmith/api/JSActionAPI"; +import type { SetFunctionPropertyPayload } from "@appsmith/api/JSActionAPI"; import type { EventLocation } from "@appsmith/utils/analyticsUtilTypes"; import type { JSEditorTab, @@ -48,21 +45,18 @@ export const updateJSCollectionSuccess = (payload: { data: JSCollection }) => { }; }; -export const updateJSCollectionBodySuccess = (payload: { - data: JSCollection; -}) => { +export const jsSaveActionComplete = (payload: { data: JSCollection }) => { return { - type: ReduxActionTypes.UPDATE_JS_ACTION_BODY_SUCCESS, + type: ReduxActionTypes.JS_ACTION_SAVE_COMPLETE, payload, }; }; -export const refactorJSCollectionAction = (payload: { - refactorAction: RefactorAction; - actionCollection: JSCollection; +export const updateJSCollectionBodySuccess = (payload: { + data: JSCollection; }) => { return { - type: ReduxActionTypes.REFACTOR_JS_ACTION_NAME, + type: ReduxActionTypes.UPDATE_JS_ACTION_BODY_SUCCESS, payload, }; }; diff --git a/app/client/src/ce/constants/ReduxActionConstants.tsx b/app/client/src/ce/constants/ReduxActionConstants.tsx index 6d8aaf340ae7..60ade700ac4c 100644 --- a/app/client/src/ce/constants/ReduxActionConstants.tsx +++ b/app/client/src/ce/constants/ReduxActionConstants.tsx @@ -594,6 +594,7 @@ const ActionTypes = { PARSE_UPDATE_JS_ACTION: "PARSE_UPDATE_JS_ACTION", UPDATE_JS_ACTION_INIT: "UPDATE_JS_ACTION_INIT", UPDATE_JS_ACTION_SUCCESS: "UPDATE_JS_ACTION_SUCCESS", + JS_ACTION_SAVE_COMPLETE: "JS_ACTION_SAVE_COMPLETE", EXECUTE_COMMAND: "EXECUTE_COMMAND", SAVE_JS_COLLECTION_NAME_INIT: "SAVE_JS_COLLECTION_NAME_INIT", FETCH_JS_ACTIONS_FOR_PAGE_INIT: "FETCH_JS_ACTIONS_FOR_PAGE_INIT", @@ -618,7 +619,6 @@ const ActionTypes = { GENERATE_SSH_KEY_PAIR_INIT: "GENERATE_SSH_KEY_PAIR_INIT", SET_REMOTE_URL_INPUT_VALUE: "SET_REMOTE_URL_INPUT_VALUE", GENERATE_SSH_KEY_PAIR_SUCCESS: "GENERATE_SSH_KEY_PAIR_SUCCESS", - REFACTOR_JS_ACTION_NAME: "REFACTOR_JS_ACTION_NAME", REFACTOR_JS_ACTION_NAME_SUCCESS: "REFACTOR_JS_ACTION_NAME_SUCCESS", SET_HEADER_META: "SET_HEADER_META", TOGGLE_ONBOARDING_WIDGET_SELECTION: "TOGGLE_ONBOARDING_WIDGET_SELECTION", diff --git a/app/client/src/ce/selectors/entitiesSelector.ts b/app/client/src/ce/selectors/entitiesSelector.ts index d827a61899c7..a42257098b0f 100644 --- a/app/client/src/ce/selectors/entitiesSelector.ts +++ b/app/client/src/ce/selectors/entitiesSelector.ts @@ -796,7 +796,8 @@ export function getPageNameByPageId(state: AppState, pageId: string): string { } const getQueryPaneSavingMap = (state: AppState) => state.ui.queryPane.isSaving; -const getApiPaneSavingMap = (state: AppState) => state.ui.apiPane.isSaving; +export const getApiPaneSavingMap = (state: AppState) => + state.ui.apiPane.isSaving; const getActionDirtyState = (state: AppState) => state.ui.apiPane.isDirty; export const isActionSaving = (id: string) => diff --git a/app/client/src/reducers/uiReducers/jsPaneReducer.ts b/app/client/src/reducers/uiReducers/jsPaneReducer.ts index 0403411d87b6..124423c3bf9a 100644 --- a/app/client/src/reducers/uiReducers/jsPaneReducer.ts +++ b/app/client/src/reducers/uiReducers/jsPaneReducer.ts @@ -92,7 +92,7 @@ const jsPaneReducer = createReducer(initialState, { [action.payload.id]: true, }, }), - [ReduxActionTypes.UPDATE_JS_ACTION_SUCCESS]: ( + [ReduxActionTypes.JS_ACTION_SAVE_COMPLETE]: ( state: JsPaneReduxState, action: ReduxAction<{ data: JSCollection }>, ) => ({ @@ -106,16 +106,6 @@ const jsPaneReducer = createReducer(initialState, { [action.payload.data.id]: false, }, }), - [ReduxActionTypes.UPDATE_JS_ACTION_BODY_SUCCESS]: ( - state: JsPaneReduxState, - action: ReduxAction<{ data: JSCollection }>, - ) => ({ - ...state, - isSaving: { - ...state.isSaving, - [action.payload.data.id]: false, - }, - }), [ReduxActionErrorTypes.UPDATE_JS_ACTION_BODY_ERROR]: ( state: JsPaneReduxState, action: ReduxAction<{ data: JSCollection }>, @@ -126,21 +116,6 @@ const jsPaneReducer = createReducer(initialState, { [action.payload.data.id]: false, }, }), - [ReduxActionTypes.REFACTOR_JS_ACTION_NAME_SUCCESS]: ( - state: JsPaneReduxState, - action: ReduxAction<{ collectionId: string }>, - ) => ({ - ...state, - isSaving: { - ...state.isSaving, - [action.payload.collectionId]: false, - }, - isDirty: { - ...state.isDirty, - [action.payload.collectionId]: false, - }, - }), - [ReduxActionErrorTypes.UPDATE_JS_ACTION_ERROR]: ( state: JsPaneReduxState, action: ReduxAction<{ data: JSCollection }>, diff --git a/app/client/src/sagas/ActionSagas.ts b/app/client/src/sagas/ActionSagas.ts index 48aa5cfc2e37..f9e65f6f47d1 100644 --- a/app/client/src/sagas/ActionSagas.ts +++ b/app/client/src/sagas/ActionSagas.ts @@ -1121,7 +1121,7 @@ function* updateEntitySavingStatus() { yield race([ take(ReduxActionTypes.UPDATE_ACTION_SUCCESS), take(ReduxActionTypes.SAVE_PAGE_SUCCESS), - take(ReduxActionTypes.UPDATE_JS_ACTION_BODY_SUCCESS), + take(ReduxActionTypes.JS_ACTION_SAVE_COMPLETE), ]); yield put({ diff --git a/app/client/src/sagas/JSPaneSagas.ts b/app/client/src/sagas/JSPaneSagas.ts index c157024a1c7a..98e56576207c 100644 --- a/app/client/src/sagas/JSPaneSagas.ts +++ b/app/client/src/sagas/JSPaneSagas.ts @@ -15,6 +15,7 @@ import { } from "@appsmith/constants/ReduxActionConstants"; import { getCurrentApplicationId, + getCurrentLayoutId, getCurrentPageId, getIsSavingEntity, } from "selectors/editorSelectors"; @@ -33,7 +34,11 @@ import { createJSCollectionRequest } from "actions/jsActionActions"; import history from "utils/history"; import { executeJSFunction } from "./EvaluationsSaga"; import { getJSCollectionIdFromURL } from "@appsmith/pages/Editor/Explorer/helpers"; -import type { JSUpdate } from "utils/JSPaneUtils"; +import type { + JSCollectionDifference, + JSUpdate, + ParsedBody, +} from "utils/JSPaneUtils"; import { getDifferenceInJSCollection, pushLogsForObjectUpdate, @@ -50,12 +55,12 @@ import JSActionAPI from "@appsmith/api/JSActionAPI"; import ActionAPI from "api/ActionAPI"; import { updateJSCollectionSuccess, - refactorJSCollectionAction, updateJSCollectionBodySuccess, updateJSFunction, executeJSFunctionInit, setJsPaneDebuggerState, createNewJSCollection, + jsSaveActionComplete, } from "actions/jsPaneActions"; import { getCurrentWorkspaceId } from "@appsmith/selectors/selectedWorkspaceSelectors"; import { getPluginIdOfPackageName } from "sagas/selectors"; @@ -75,8 +80,6 @@ import { PLATFORM_ERROR, } from "@appsmith/entities/AppsmithConsole/utils"; import LOG_TYPE from "entities/AppsmithConsole/logtype"; -import type { FetchPageRequest, FetchPageResponse } from "api/PageApi"; -import PageApi from "api/PageApi"; import { updateCanvasWithDSL } from "@appsmith/sagas/PageSagas"; import { set } from "lodash"; import { updateReplayEntity } from "actions/pageActions"; @@ -196,96 +199,125 @@ function* handleJSCollectionCreatedSaga( ); } -function* handleEachUpdateJSCollection(update: JSUpdate) { - const jsActionId = update.id; - const workspaceId: string = yield select(getCurrentWorkspaceId); - if (jsActionId) { - const jsAction: JSCollection = yield select(getJSCollection, jsActionId); - const parsedBody = update.parsedBody; - if (parsedBody && !!jsAction) { - const jsActionTobeUpdated = JSON.parse(JSON.stringify(jsAction)); - // jsActionTobeUpdated.body = jsAction.body; - const data = getDifferenceInJSCollection(parsedBody, jsAction); - if (data.nameChangedActions.length) { - for (let i = 0; i < data.nameChangedActions.length; i++) { - yield put( - refactorJSCollectionAction({ - refactorAction: { - actionId: data.nameChangedActions[i].id, - collectionName: jsAction.name, - pageId: data.nameChangedActions[i].pageId, - moduleId: data.nameChangedActions[i].moduleId, - oldName: data.nameChangedActions[i].oldName, - newName: data.nameChangedActions[i].newName, - }, - actionCollection: jsActionTobeUpdated, - }), - ); - } - } else { - let newActions: Partial[] = []; - let updateActions: JSAction[] = []; - let deletedActions: JSAction[] = []; - let updateCollection = false; - const changedVariables = data.changedVariables; - if (changedVariables.length) { - jsActionTobeUpdated.variables = parsedBody.variables; - updateCollection = true; - } - if (data.newActions.length) { - newActions = data.newActions; - for (let i = 0; i < data.newActions.length; i++) { - jsActionTobeUpdated.actions.push({ - ...data.newActions[i], - workspaceId: workspaceId, - }); - } - updateCollection = true; - } - if (data.updateActions.length > 0) { - updateActions = data.updateActions; - let changedActions = []; - for (let i = 0; i < data.updateActions.length; i++) { - changedActions = jsActionTobeUpdated.actions.map( - (js: JSAction) => - data.updateActions.find( - (update: JSAction) => update.id === js.id, - ) || js, - ); - } - updateCollection = true; - jsActionTobeUpdated.actions = changedActions; - } - if (data.deletedActions.length > 0) { - deletedActions = data.deletedActions; - const nonDeletedActions = jsActionTobeUpdated.actions.filter( - (js: JSAction) => { - return !data.deletedActions.find((deleted) => { - return deleted.id === js.id; - }); - }, - ); - updateCollection = true; - jsActionTobeUpdated.actions = nonDeletedActions; - } +function getJSCollectionUpdateType(difference: JSCollectionDifference) { + if (difference.nameChangedActions.length) { + return "REFACTOR"; + } - if (updateCollection) { - newActions.forEach((action) => { - AnalyticsUtil.logEvent("JS_OBJECT_FUNCTION_ADDED", { - name: action.name, - jsObjectName: jsAction.name, - }); - }); - yield call(updateJSCollection, { - jsCollection: jsActionTobeUpdated, - newActions: newActions, - updatedActions: updateActions, - deletedActions: deletedActions, - }); - } - } + if ( + difference.newActions.length || + difference.updateActions.length || + difference.deletedActions.length + ) { + return "UPDATE"; + } + + return "NO_CHANGE"; +} + +function* handleRefactorJSCollection( + difference: JSCollectionDifference, + actionCollection: JSCollection, +) { + yield all( + difference.nameChangedActions.map((action) => + call( + handleRefactorJSActionNameSaga, + { + actionId: action.id, + collectionName: actionCollection.name, + pageId: action.pageId, + moduleId: action.moduleId, + oldName: action.oldName, + newName: action.newName, + }, + actionCollection, + ), + ), + ); +} + +function* handleUpdateCollection( + difference: JSCollectionDifference, + actionCollection: JSCollection, + parsedBody: ParsedBody, +) { + const workspaceId: string = yield select(getCurrentWorkspaceId); + let newActions: JSAction[] = []; + let updateActions: JSAction[] = []; + let deletedActions: JSAction[] = []; + const changedVariables = difference.changedVariables; + if (changedVariables.length) { + actionCollection.variables = parsedBody.variables; + } + if (difference.newActions.length) { + newActions = difference.newActions as JSAction[]; + difference.newActions.forEach((action) => { + actionCollection.actions.push({ + ...(action as JSAction), + workspaceId: workspaceId, + }); + }); + } + if (difference.updateActions.length > 0) { + updateActions = difference.updateActions; + let changedActions: JSAction[] = []; + for (let i = 0; i < difference.updateActions.length; i++) { + changedActions = actionCollection.actions.map( + (js: JSAction) => + difference.updateActions.find( + (update: JSAction) => update.id === js.id, + ) || js, + ); } + actionCollection.actions = changedActions; } + if (difference.deletedActions.length > 0) { + deletedActions = difference.deletedActions; + const nonDeletedActions = actionCollection.actions.filter( + (js: JSAction) => { + return !difference.deletedActions.find((deleted) => { + return deleted.id === js.id; + }); + }, + ); + actionCollection.actions = nonDeletedActions; + } + + newActions.forEach((action) => { + AnalyticsUtil.logEvent("JS_OBJECT_FUNCTION_ADDED", { + name: action.name, + jsObjectName: actionCollection.name, + }); + }); + + yield call(updateJSCollection, { + jsCollection: actionCollection, + newActions: newActions, + updatedActions: updateActions, + deletedActions: deletedActions, + }); +} + +function* handleEachUpdateJSCollection(update: JSUpdate) { + const { id, parsedBody } = update; + if (!id || !parsedBody) return; + + const jsAction: JSCollection = yield select(getJSCollection, id); + if (!jsAction) return; + + const data = getDifferenceInJSCollection(parsedBody, jsAction); + const updateType = getJSCollectionUpdateType(data); + + if (updateType === "REFACTOR") { + yield handleRefactorJSCollection(data, jsAction); + } + + if (updateType === "UPDATE") { + yield handleUpdateCollection(data, jsAction, parsedBody); + } + + yield put(jsSaveActionComplete({ data: jsAction })); } export function* makeUpdateJSCollection( @@ -626,60 +658,49 @@ function* handleUpdateJSCollectionBody( } function* handleRefactorJSActionNameSaga( - data: ReduxAction<{ - refactorAction: RefactorAction; - actionCollection: JSCollection; - }>, + refactorAction: RefactorAction, + actionCollection: JSCollection, ) { - const { pageId } = data.payload.refactorAction; - if (!pageId) { + const { pageId } = refactorAction; + const layoutId: string | undefined = yield select(getCurrentLayoutId); + if (!pageId || !layoutId) { return; } - const params: FetchPageRequest = { - id: data.payload.refactorAction.pageId || "", - migrateDSL: true, + const requestData = { + ...refactorAction, + layoutId, + actionCollection: actionCollection, }; - const pageResponse: FetchPageResponse = yield call(PageApi.fetchPage, params); - const isPageRequestSuccessful: boolean = yield validateResponse(pageResponse); - if (isPageRequestSuccessful) { - // get the layoutId from the page response - const layoutId = pageResponse.data.layouts[0].id; - const requestData = { - ...data.payload.refactorAction, - layoutId: layoutId, - actionCollection: data.payload.actionCollection, - }; - // call to refactor action - try { - const refactorResponse: ApiResponse = - yield JSActionAPI.updateJSCollectionActionRefactor(requestData); + // call to refactor action + try { + const refactorResponse: ApiResponse = + yield JSActionAPI.updateJSCollectionActionRefactor(requestData); - const isRefactorSuccessful: boolean = - yield validateResponse(refactorResponse); + const isRefactorSuccessful: boolean = + yield validateResponse(refactorResponse); - const currentPageId: string | undefined = yield select(getCurrentPageId); + const currentPageId: string | undefined = yield select(getCurrentPageId); - if (isRefactorSuccessful) { - yield put({ - type: ReduxActionTypes.REFACTOR_JS_ACTION_NAME_SUCCESS, - payload: { collectionId: data.payload.actionCollection.id }, - }); - if (currentPageId === data.payload.refactorAction.pageId) { - yield updateCanvasWithDSL( - // @ts-expect-error: response is of type unknown - refactorResponse.data, - data.payload.refactorAction.pageId, - layoutId, - ); - } - } - } catch (error) { + if (isRefactorSuccessful) { yield put({ - type: ReduxActionErrorTypes.REFACTOR_JS_ACTION_NAME_ERROR, - payload: { collectionId: data.payload.actionCollection.id }, + type: ReduxActionTypes.REFACTOR_JS_ACTION_NAME_SUCCESS, + payload: { collectionId: actionCollection.id }, }); + if (currentPageId === refactorAction.pageId) { + yield updateCanvasWithDSL( + // @ts-expect-error: response is of type unknown + refactorResponse.data, + refactorAction.pageId, + layoutId, + ); + } } + } catch (error) { + yield put({ + type: ReduxActionErrorTypes.REFACTOR_JS_ACTION_NAME_ERROR, + payload: { collectionId: actionCollection.id }, + }); } } @@ -825,10 +846,6 @@ export default function* root() { ReduxActionTypes.START_EXECUTE_JS_FUNCTION, handleStartExecuteJSFunctionSaga, ), - takeEvery( - ReduxActionTypes.REFACTOR_JS_ACTION_NAME, - handleRefactorJSActionNameSaga, - ), debounce( 100, ReduxActionTypes.UPDATE_JS_ACTION_BODY_INIT, diff --git a/app/client/src/selectors/editorSelectors.tsx b/app/client/src/selectors/editorSelectors.tsx index ec497749cf32..f9a42f34c91e 100644 --- a/app/client/src/selectors/editorSelectors.tsx +++ b/app/client/src/selectors/editorSelectors.tsx @@ -30,6 +30,7 @@ import type { MainCanvasReduxState } from "reducers/uiReducers/mainCanvasReducer import { getActions, + getApiPaneSavingMap, getCanvasWidgets, getJSCollections, } from "@appsmith/selectors/entitiesSelector"; @@ -73,33 +74,44 @@ export const getIsFetchingPage = (state: AppState) => export const getLoadingError = (state: AppState) => state.ui.editor.loadingStates.loadingError; -export const getIsPageSaving = (state: AppState) => { - let areApisSaving = false; - let areJsObjectsSaving = false; - - const savingApis = state.ui.apiPane.isSaving; - const savingJSObjects = state.ui.jsPane.isSaving; - const isSavingAppTheme = state.ui.appTheming.isSaving; - const isSavingNavigationSetting = - state.ui.applications.isSavingNavigationSetting; - - Object.keys(savingApis).forEach((apiId) => { - areApisSaving = savingApis[apiId] || areApisSaving; - }); +export const getIsPageSaving = createSelector( + [ + getApiPaneSavingMap, + (state: AppState) => state.ui.jsPane.isSaving, + (state: AppState) => state.ui.appTheming.isSaving, + (state: AppState) => state.ui.applications.isSavingNavigationSetting, + (state: AppState) => state.ui.editor.loadingStates.savingEntity, + (state: AppState) => state.ui.editor.loadingStates.saving, + ], + ( + savingApis, + savingJSObjects, + isSavingAppTheme, + isSavingNavigationSetting, + editorLoadingStatesSavingEntity, + editorLoadingStates, + ) => { + let areApisSaving = false; + let areJsObjectsSaving = false; + + Object.keys(savingApis).forEach((apiId) => { + areApisSaving = savingApis[apiId] || areApisSaving; + }); - Object.keys(savingJSObjects).forEach((collectionId) => { - areJsObjectsSaving = savingJSObjects[collectionId] || areJsObjectsSaving; - }); + Object.keys(savingJSObjects).forEach((collectionId) => { + areJsObjectsSaving = savingJSObjects[collectionId] || areJsObjectsSaving; + }); - return ( - state.ui.editor.loadingStates.saving || - areApisSaving || - areJsObjectsSaving || - isSavingAppTheme || - state.ui.editor.loadingStates.savingEntity || - isSavingNavigationSetting - ); -}; + return ( + editorLoadingStates || + areApisSaving || + areJsObjectsSaving || + isSavingAppTheme || + editorLoadingStatesSavingEntity || + isSavingNavigationSetting + ); + }, +); export const snipingModeSelector = (state: AppState) => state.ui.editor.isSnipingMode; @@ -124,7 +136,7 @@ export const getIsPublishingApplication = (state: AppState) => export const getPublishingError = (state: AppState) => state.ui.editor.loadingStates.publishingError; -export const getCurrentLayoutId = (state: AppState) => +export const getCurrentLayoutId = (state: AppState): string | undefined => state.ui.editor.currentLayoutId; export const getPageList = (state: AppState) => state.entities.pageList.pages; diff --git a/app/client/src/store.ts b/app/client/src/store.ts index 7ec2f3b4b6e9..06ed991e952e 100644 --- a/app/client/src/store.ts +++ b/app/client/src/store.ts @@ -25,9 +25,14 @@ const sentryReduxEnhancer = Sentry.createReduxEnhancer({ }, }); +const composeEnhancers = composeWithDevTools({ + maxAge: 500, // Increase as needed + trace: true, +}); + export default createStore( appReducer, - composeWithDevTools( + composeEnhancers( reduxBatch, applyMiddleware(sagaMiddleware, routeParamsMiddleware), reduxBatch, diff --git a/app/client/src/utils/JSPaneUtils.tsx b/app/client/src/utils/JSPaneUtils.tsx index b745afa87ecf..0b359f0c60ab 100644 --- a/app/client/src/utils/JSPaneUtils.tsx +++ b/app/client/src/utils/JSPaneUtils.tsx @@ -20,10 +20,25 @@ export interface JSUpdate { parsedBody: ParsedBody | undefined; } +export interface JSCollectionDifference { + newActions: Partial[]; + updateActions: JSAction[]; + deletedActions: JSAction[]; + nameChangedActions: Array<{ + id: string; + collectionId?: string; + oldName: string; + newName: string; + pageId: string; + moduleId?: string; + }>; + changedVariables: Variable[]; +} + export const getDifferenceInJSCollection = ( parsedBody: ParsedBody, jsAction: JSCollection, -) => { +): JSCollectionDifference => { const newActions: ParsedJSSubAction[] = []; const toBearchivedActions: JSAction[] = []; const toBeUpdatedActions: JSAction[] = []; From 2379d2b74ea20665f46d30e1735a0c6b5530db74 Mon Sep 17 00:00:00 2001 From: Diljit VJ Date: Fri, 17 May 2024 13:28:52 +0530 Subject: [PATCH 2/8] Refactor code --- app/client/src/selectors/editorSelectors.tsx | 24 ++++++++------------ 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/app/client/src/selectors/editorSelectors.tsx b/app/client/src/selectors/editorSelectors.tsx index f9a42f34c91e..1456b89c007f 100644 --- a/app/client/src/selectors/editorSelectors.tsx +++ b/app/client/src/selectors/editorSelectors.tsx @@ -88,26 +88,22 @@ export const getIsPageSaving = createSelector( savingJSObjects, isSavingAppTheme, isSavingNavigationSetting, - editorLoadingStatesSavingEntity, - editorLoadingStates, + isEditorSavingEntity, + isEditorSaving, ) => { - let areApisSaving = false; - let areJsObjectsSaving = false; - - Object.keys(savingApis).forEach((apiId) => { - areApisSaving = savingApis[apiId] || areApisSaving; - }); - - Object.keys(savingJSObjects).forEach((collectionId) => { - areJsObjectsSaving = savingJSObjects[collectionId] || areJsObjectsSaving; - }); + const areApisSaving = Object.keys(savingApis).some( + (apiId) => savingApis[apiId], + ); + const areJsObjectsSaving = Object.keys(savingJSObjects).some( + (collectionId) => savingJSObjects[collectionId], + ); return ( - editorLoadingStates || + isEditorSavingEntity || areApisSaving || areJsObjectsSaving || isSavingAppTheme || - editorLoadingStatesSavingEntity || + isEditorSaving || isSavingNavigationSetting ); }, From 983bbab985dc2021567f2acd8ddc21d2f10c3ea7 Mon Sep 17 00:00:00 2001 From: Diljit VJ Date: Tue, 21 May 2024 07:44:20 +0530 Subject: [PATCH 3/8] Change the trigger for flipping entity save to false --- app/client/src/actions/jsPaneActions.ts | 17 ++++++++--------- .../src/ce/constants/ReduxActionConstants.tsx | 2 +- .../src/reducers/uiReducers/jsPaneReducer.ts | 18 ++++-------------- app/client/src/sagas/ActionSagas.ts | 2 +- app/client/src/sagas/JSPaneSagas.ts | 15 +++++++++++++-- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/app/client/src/actions/jsPaneActions.ts b/app/client/src/actions/jsPaneActions.ts index 6b93c02172c3..a18d7bc06952 100644 --- a/app/client/src/actions/jsPaneActions.ts +++ b/app/client/src/actions/jsPaneActions.ts @@ -21,14 +21,6 @@ export const createNewJSCollection = ( payload: { pageId, from, functionName }, }); -export const updateJSCollection = ( - body: string, - id: string, -): ReduxAction<{ body: string; id: string }> => ({ - type: ReduxActionTypes.UPDATE_JS_ACTION_INIT, - payload: { body, id }, -}); - export const updateJSCollectionBody = ( body: string, id: string, @@ -45,7 +37,14 @@ export const updateJSCollectionSuccess = (payload: { data: JSCollection }) => { }; }; -export const jsSaveActionComplete = (payload: { data: JSCollection }) => { +export const jsSaveActionStart = (payload: { id: string }) => { + return { + type: ReduxActionTypes.JS_ACTION_SAVE_START, + payload, + }; +}; + +export const jsSaveActionComplete = (payload: { id: string }) => { return { type: ReduxActionTypes.JS_ACTION_SAVE_COMPLETE, payload, diff --git a/app/client/src/ce/constants/ReduxActionConstants.tsx b/app/client/src/ce/constants/ReduxActionConstants.tsx index 60ade700ac4c..61faff4fc2e2 100644 --- a/app/client/src/ce/constants/ReduxActionConstants.tsx +++ b/app/client/src/ce/constants/ReduxActionConstants.tsx @@ -592,8 +592,8 @@ const ActionTypes = { DELETE_JS_ACTION_INIT: "DELETE_JS_ACTION_INIT", DELETE_JS_ACTION_SUCCESS: "DELETE_JS_ACTION_SUCCESS", PARSE_UPDATE_JS_ACTION: "PARSE_UPDATE_JS_ACTION", - UPDATE_JS_ACTION_INIT: "UPDATE_JS_ACTION_INIT", UPDATE_JS_ACTION_SUCCESS: "UPDATE_JS_ACTION_SUCCESS", + JS_ACTION_SAVE_START: "JS_ACTION_SAVE_START", JS_ACTION_SAVE_COMPLETE: "JS_ACTION_SAVE_COMPLETE", EXECUTE_COMMAND: "EXECUTE_COMMAND", SAVE_JS_COLLECTION_NAME_INIT: "SAVE_JS_COLLECTION_NAME_INIT", diff --git a/app/client/src/reducers/uiReducers/jsPaneReducer.ts b/app/client/src/reducers/uiReducers/jsPaneReducer.ts index 124423c3bf9a..b6cae9c6bda2 100644 --- a/app/client/src/reducers/uiReducers/jsPaneReducer.ts +++ b/app/client/src/reducers/uiReducers/jsPaneReducer.ts @@ -72,17 +72,7 @@ const jsPaneReducer = createReducer(initialState, { ...state, isCreating: false, }), - [ReduxActionTypes.UPDATE_JS_ACTION_INIT]: ( - state: JsPaneReduxState, - action: ReduxAction<{ id: string }>, - ) => ({ - ...state, - isSaving: { - ...state.isSaving, - [action.payload.id]: true, - }, - }), - [ReduxActionTypes.UPDATE_JS_ACTION_BODY_INIT]: ( + [ReduxActionTypes.JS_ACTION_SAVE_START]: ( state: JsPaneReduxState, action: ReduxAction<{ id: string }>, ) => ({ @@ -94,16 +84,16 @@ const jsPaneReducer = createReducer(initialState, { }), [ReduxActionTypes.JS_ACTION_SAVE_COMPLETE]: ( state: JsPaneReduxState, - action: ReduxAction<{ data: JSCollection }>, + action: ReduxAction<{ id: string }>, ) => ({ ...state, isSaving: { ...state.isSaving, - [action.payload.data.id]: false, + [action.payload.id]: false, }, isDirty: { ...state.isDirty, - [action.payload.data.id]: false, + [action.payload.id]: false, }, }), [ReduxActionErrorTypes.UPDATE_JS_ACTION_BODY_ERROR]: ( diff --git a/app/client/src/sagas/ActionSagas.ts b/app/client/src/sagas/ActionSagas.ts index f9e65f6f47d1..23b41bef42be 100644 --- a/app/client/src/sagas/ActionSagas.ts +++ b/app/client/src/sagas/ActionSagas.ts @@ -1121,7 +1121,7 @@ function* updateEntitySavingStatus() { yield race([ take(ReduxActionTypes.UPDATE_ACTION_SUCCESS), take(ReduxActionTypes.SAVE_PAGE_SUCCESS), - take(ReduxActionTypes.JS_ACTION_SAVE_COMPLETE), + take(ReduxActionTypes.EXECUTE_JS_UPDATES), ]); yield put({ diff --git a/app/client/src/sagas/JSPaneSagas.ts b/app/client/src/sagas/JSPaneSagas.ts index 98e56576207c..efa9cf1d3094 100644 --- a/app/client/src/sagas/JSPaneSagas.ts +++ b/app/client/src/sagas/JSPaneSagas.ts @@ -61,6 +61,7 @@ import { setJsPaneDebuggerState, createNewJSCollection, jsSaveActionComplete, + jsSaveActionStart, } from "actions/jsPaneActions"; import { getCurrentWorkspaceId } from "@appsmith/selectors/selectedWorkspaceSelectors"; import { getPluginIdOfPackageName } from "sagas/selectors"; @@ -316,8 +317,6 @@ function* handleEachUpdateJSCollection(update: JSUpdate) { if (updateType === "UPDATE") { yield handleUpdateCollection(data, jsAction, parsedBody); } - - yield put(jsSaveActionComplete({ data: jsAction })); } export function* makeUpdateJSCollection( @@ -325,11 +324,23 @@ export function* makeUpdateJSCollection( ) { const jsUpdates: Record = action.payload || {}; + yield all( + Object.keys(jsUpdates).map((key) => + put(jsSaveActionStart({ id: jsUpdates[key].id })), + ), + ); + yield all( Object.keys(jsUpdates).map((key) => call(handleEachUpdateJSCollection, jsUpdates[key]), ), ); + + yield all( + Object.keys(jsUpdates).map((key) => + put(jsSaveActionComplete({ id: jsUpdates[key].id })), + ), + ); } function* updateJSCollection(data: { From 6f6f2a94935a1ae9b65c59599599c3514bc954d4 Mon Sep 17 00:00:00 2001 From: Diljit VJ Date: Tue, 21 May 2024 07:53:27 +0530 Subject: [PATCH 4/8] Revert unintended deletion --- app/client/src/actions/jsPaneActions.ts | 15 ++++++++++++++- .../src/ce/constants/ReduxActionConstants.tsx | 1 + 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/client/src/actions/jsPaneActions.ts b/app/client/src/actions/jsPaneActions.ts index a18d7bc06952..c830c89e007e 100644 --- a/app/client/src/actions/jsPaneActions.ts +++ b/app/client/src/actions/jsPaneActions.ts @@ -1,7 +1,10 @@ import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants"; import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; import type { JSCollection, JSAction } from "entities/JSCollection"; -import type { SetFunctionPropertyPayload } from "@appsmith/api/JSActionAPI"; +import type { + RefactorAction, + SetFunctionPropertyPayload, +} from "@appsmith/api/JSActionAPI"; import type { EventLocation } from "@appsmith/utils/analyticsUtilTypes"; import type { JSEditorTab, @@ -44,6 +47,16 @@ export const jsSaveActionStart = (payload: { id: string }) => { }; }; +export const refactorJSCollectionAction = (payload: { + refactorAction: RefactorAction; + actionCollection: JSCollection; +}) => { + return { + type: ReduxActionTypes.REFACTOR_JS_ACTION_NAME, + payload, + }; +}; + export const jsSaveActionComplete = (payload: { id: string }) => { return { type: ReduxActionTypes.JS_ACTION_SAVE_COMPLETE, diff --git a/app/client/src/ce/constants/ReduxActionConstants.tsx b/app/client/src/ce/constants/ReduxActionConstants.tsx index 61faff4fc2e2..8b9b26f49580 100644 --- a/app/client/src/ce/constants/ReduxActionConstants.tsx +++ b/app/client/src/ce/constants/ReduxActionConstants.tsx @@ -619,6 +619,7 @@ const ActionTypes = { GENERATE_SSH_KEY_PAIR_INIT: "GENERATE_SSH_KEY_PAIR_INIT", SET_REMOTE_URL_INPUT_VALUE: "SET_REMOTE_URL_INPUT_VALUE", GENERATE_SSH_KEY_PAIR_SUCCESS: "GENERATE_SSH_KEY_PAIR_SUCCESS", + REFACTOR_JS_ACTION_NAME: "REFACTOR_JS_ACTION_NAME", REFACTOR_JS_ACTION_NAME_SUCCESS: "REFACTOR_JS_ACTION_NAME_SUCCESS", SET_HEADER_META: "SET_HEADER_META", TOGGLE_ONBOARDING_WIDGET_SELECTION: "TOGGLE_ONBOARDING_WIDGET_SELECTION", From 46eaceb989284459b692063f65a975a1a8546cab Mon Sep 17 00:00:00 2001 From: Diljit VJ Date: Tue, 21 May 2024 07:55:06 +0530 Subject: [PATCH 5/8] reorder --- app/client/src/actions/jsPaneActions.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/app/client/src/actions/jsPaneActions.ts b/app/client/src/actions/jsPaneActions.ts index c830c89e007e..fc35a64edeb3 100644 --- a/app/client/src/actions/jsPaneActions.ts +++ b/app/client/src/actions/jsPaneActions.ts @@ -40,6 +40,15 @@ export const updateJSCollectionSuccess = (payload: { data: JSCollection }) => { }; }; +export const updateJSCollectionBodySuccess = (payload: { + data: JSCollection; +}) => { + return { + type: ReduxActionTypes.UPDATE_JS_ACTION_BODY_SUCCESS, + payload, + }; +}; + export const jsSaveActionStart = (payload: { id: string }) => { return { type: ReduxActionTypes.JS_ACTION_SAVE_START, @@ -64,15 +73,6 @@ export const jsSaveActionComplete = (payload: { id: string }) => { }; }; -export const updateJSCollectionBodySuccess = (payload: { - data: JSCollection; -}) => { - return { - type: ReduxActionTypes.UPDATE_JS_ACTION_BODY_SUCCESS, - payload, - }; -}; - export const executeJSFunctionInit = (payload: { collection: JSCollection; action: JSAction; From f811743f1db628bb30a7838e2c11a6520f26f2f1 Mon Sep 17 00:00:00 2001 From: Diljit VJ Date: Wed, 22 May 2024 15:08:49 +0530 Subject: [PATCH 6/8] Revert code refactor --- app/client/src/sagas/JSPaneSagas.ts | 205 ++++++++++++---------------- 1 file changed, 86 insertions(+), 119 deletions(-) diff --git a/app/client/src/sagas/JSPaneSagas.ts b/app/client/src/sagas/JSPaneSagas.ts index efa9cf1d3094..e936b60edc93 100644 --- a/app/client/src/sagas/JSPaneSagas.ts +++ b/app/client/src/sagas/JSPaneSagas.ts @@ -34,11 +34,7 @@ import { createJSCollectionRequest } from "actions/jsActionActions"; import history from "utils/history"; import { executeJSFunction } from "./EvaluationsSaga"; import { getJSCollectionIdFromURL } from "@appsmith/pages/Editor/Explorer/helpers"; -import type { - JSCollectionDifference, - JSUpdate, - ParsedBody, -} from "utils/JSPaneUtils"; +import type { JSUpdate } from "utils/JSPaneUtils"; import { getDifferenceInJSCollection, pushLogsForObjectUpdate, @@ -200,122 +196,93 @@ function* handleJSCollectionCreatedSaga( ); } -function getJSCollectionUpdateType(difference: JSCollectionDifference) { - if (difference.nameChangedActions.length) { - return "REFACTOR"; - } - - if ( - difference.newActions.length || - difference.updateActions.length || - difference.deletedActions.length - ) { - return "UPDATE"; - } - - return "NO_CHANGE"; -} - -function* handleRefactorJSCollection( - difference: JSCollectionDifference, - actionCollection: JSCollection, -) { - yield all( - difference.nameChangedActions.map((action) => - call( - handleRefactorJSActionNameSaga, - { - actionId: action.id, - collectionName: actionCollection.name, - pageId: action.pageId, - moduleId: action.moduleId, - oldName: action.oldName, - newName: action.newName, - }, - actionCollection, - ), - ), - ); -} - -function* handleUpdateCollection( - difference: JSCollectionDifference, - actionCollection: JSCollection, - parsedBody: ParsedBody, -) { +function* handleEachUpdateJSCollection(update: JSUpdate) { + const jsActionId = update.id; const workspaceId: string = yield select(getCurrentWorkspaceId); - let newActions: JSAction[] = []; - let updateActions: JSAction[] = []; - let deletedActions: JSAction[] = []; - const changedVariables = difference.changedVariables; - if (changedVariables.length) { - actionCollection.variables = parsedBody.variables; - } - if (difference.newActions.length) { - newActions = difference.newActions as JSAction[]; - difference.newActions.forEach((action) => { - actionCollection.actions.push({ - ...(action as JSAction), - workspaceId: workspaceId, - }); - }); - } - if (difference.updateActions.length > 0) { - updateActions = difference.updateActions; - let changedActions: JSAction[] = []; - for (let i = 0; i < difference.updateActions.length; i++) { - changedActions = actionCollection.actions.map( - (js: JSAction) => - difference.updateActions.find( - (update: JSAction) => update.id === js.id, - ) || js, - ); + if (jsActionId) { + const jsAction: JSCollection = yield select(getJSCollection, jsActionId); + const parsedBody = update.parsedBody; + if (parsedBody && !!jsAction) { + const jsActionTobeUpdated = JSON.parse(JSON.stringify(jsAction)); + // jsActionTobeUpdated.body = jsAction.body; + const data = getDifferenceInJSCollection(parsedBody, jsAction); + if (data.nameChangedActions.length) { + for (let i = 0; i < data.nameChangedActions.length; i++) { + yield call( + handleRefactorJSActionNameSaga, + { + actionId: data.nameChangedActions[i].id, + collectionName: jsAction.name, + pageId: data.nameChangedActions[i].pageId, + moduleId: data.nameChangedActions[i].moduleId, + oldName: data.nameChangedActions[i].oldName, + newName: data.nameChangedActions[i].newName, + }, + jsActionTobeUpdated, + ); + } + } else { + let newActions: Partial[] = []; + let updateActions: JSAction[] = []; + let deletedActions: JSAction[] = []; + let updateCollection = false; + const changedVariables = data.changedVariables; + if (changedVariables.length) { + jsActionTobeUpdated.variables = parsedBody.variables; + updateCollection = true; + } + if (data.newActions.length) { + newActions = data.newActions; + for (let i = 0; i < data.newActions.length; i++) { + jsActionTobeUpdated.actions.push({ + ...data.newActions[i], + workspaceId: workspaceId, + }); + } + updateCollection = true; + } + if (data.updateActions.length > 0) { + updateActions = data.updateActions; + let changedActions = []; + for (let i = 0; i < data.updateActions.length; i++) { + changedActions = jsActionTobeUpdated.actions.map( + (js: JSAction) => + data.updateActions.find( + (update: JSAction) => update.id === js.id, + ) || js, + ); + } + updateCollection = true; + jsActionTobeUpdated.actions = changedActions; + } + if (data.deletedActions.length > 0) { + deletedActions = data.deletedActions; + const nonDeletedActions = jsActionTobeUpdated.actions.filter( + (js: JSAction) => { + return !data.deletedActions.find((deleted) => { + return deleted.id === js.id; + }); + }, + ); + updateCollection = true; + jsActionTobeUpdated.actions = nonDeletedActions; + } + if (updateCollection) { + newActions.forEach((action) => { + AnalyticsUtil.logEvent("JS_OBJECT_FUNCTION_ADDED", { + name: action.name, + jsObjectName: jsAction.name, + }); + }); + yield call(updateJSCollection, { + jsCollection: jsActionTobeUpdated, + newActions: newActions, + updatedActions: updateActions, + deletedActions: deletedActions, + }); + } + } } - actionCollection.actions = changedActions; - } - if (difference.deletedActions.length > 0) { - deletedActions = difference.deletedActions; - const nonDeletedActions = actionCollection.actions.filter( - (js: JSAction) => { - return !difference.deletedActions.find((deleted) => { - return deleted.id === js.id; - }); - }, - ); - actionCollection.actions = nonDeletedActions; - } - - newActions.forEach((action) => { - AnalyticsUtil.logEvent("JS_OBJECT_FUNCTION_ADDED", { - name: action.name, - jsObjectName: actionCollection.name, - }); - }); - - yield call(updateJSCollection, { - jsCollection: actionCollection, - newActions: newActions, - updatedActions: updateActions, - deletedActions: deletedActions, - }); -} - -function* handleEachUpdateJSCollection(update: JSUpdate) { - const { id, parsedBody } = update; - if (!id || !parsedBody) return; - - const jsAction: JSCollection = yield select(getJSCollection, id); - if (!jsAction) return; - - const data = getDifferenceInJSCollection(parsedBody, jsAction); - const updateType = getJSCollectionUpdateType(data); - - if (updateType === "REFACTOR") { - yield handleRefactorJSCollection(data, jsAction); - } - - if (updateType === "UPDATE") { - yield handleUpdateCollection(data, jsAction, parsedBody); } } From bede8eb2686ba2d87744d5e4a1f39e64aa991320 Mon Sep 17 00:00:00 2001 From: Diljit VJ Date: Wed, 22 May 2024 15:09:57 +0530 Subject: [PATCH 7/8] Revert line deletion --- app/client/src/sagas/JSPaneSagas.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/app/client/src/sagas/JSPaneSagas.ts b/app/client/src/sagas/JSPaneSagas.ts index e936b60edc93..f8fb06a013d6 100644 --- a/app/client/src/sagas/JSPaneSagas.ts +++ b/app/client/src/sagas/JSPaneSagas.ts @@ -267,6 +267,7 @@ function* handleEachUpdateJSCollection(update: JSUpdate) { updateCollection = true; jsActionTobeUpdated.actions = nonDeletedActions; } + if (updateCollection) { newActions.forEach((action) => { AnalyticsUtil.logEvent("JS_OBJECT_FUNCTION_ADDED", { From 4abfec0069893c0a8f99aa84e7af38e55b39558d Mon Sep 17 00:00:00 2001 From: Diljit VJ Date: Wed, 22 May 2024 15:12:00 +0530 Subject: [PATCH 8/8] Revert change in store dev tool setting --- app/client/src/store.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/client/src/store.ts b/app/client/src/store.ts index 06ed991e952e..7ec2f3b4b6e9 100644 --- a/app/client/src/store.ts +++ b/app/client/src/store.ts @@ -25,14 +25,9 @@ const sentryReduxEnhancer = Sentry.createReduxEnhancer({ }, }); -const composeEnhancers = composeWithDevTools({ - maxAge: 500, // Increase as needed - trace: true, -}); - export default createStore( appReducer, - composeEnhancers( + composeWithDevTools( reduxBatch, applyMiddleware(sagaMiddleware, routeParamsMiddleware), reduxBatch,