fix: Correcting the execution of query with the latest values when run shortcut is pressed (#9363)

* fix(run-hot-key): added update init action with debounced on change function

* fix(run-hot-key): Adding new action for updating store for isSaving query true

* fix(run-hot-key): updating the action name to preparing_update_action

* fix(run-hot-key): added descriptive comments

* fix(run-hot-key): updated the action name and moved condition to action file

* fix(run-hot-key): updated the action to entity started at global app

* fix(run-hot-key): added entity saving status to show loader

* fix(run-hot-key): fixed cypress test to type in the query rather using set method of code editor
This commit is contained in:
Aman Agarwal 2021-12-24 19:29:02 +05:30 committed by GitHub
parent b82ea06aa3
commit 4d73536ea8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 83 additions and 5 deletions

View File

@ -139,7 +139,11 @@ describe("Entity explorer datasource structure", function() {
cy.get(".CodeMirror") cy.get(".CodeMirror")
.first() .first()
.then((editor) => { .then((editor) => {
editor[0].CodeMirror.setValue(`DROP TABLE ${tableName}`); editor[0].CodeMirror.setValue("");
cy.wrap(editor)
.find("textarea")
.focus()
.type(`DROP TABLE ${tableName};`);
cy.WaitAutoSave(); cy.WaitAutoSave();
cy.runQuery(); cy.runQuery();
cy.get(queryEditor.queryMoreAction).click(); cy.get(queryEditor.queryMoreAction).click();

View File

@ -31,3 +31,12 @@ export const updateCanvasLayoutAction = (
}, },
}; };
}; };
/**
* This action when executed updates the status of saving entity to true
* This function was created to add a sync to the entity update and shortcut command being fired to execute any command.
*/
export const startingEntityUpdation = () => ({
type: ReduxActionTypes.ENTITY_UPDATE_STARTED,
});

View File

@ -82,9 +82,11 @@ import { AutocompleteDataType } from "utils/autocomplete/TernServer";
import { Placement } from "@blueprintjs/popover2"; import { Placement } from "@blueprintjs/popover2";
import { getLintAnnotations } from "./lintHelpers"; import { getLintAnnotations } from "./lintHelpers";
import { executeCommandAction } from "actions/apiPaneActions"; import { executeCommandAction } from "actions/apiPaneActions";
import { startingEntityUpdation } from "actions/editorActions";
import { SlashCommandPayload } from "entities/Action"; import { SlashCommandPayload } from "entities/Action";
import { Indices } from "constants/Layers"; import { Indices } from "constants/Layers";
import { replayHighlightClass } from "globalStyles/portals"; import { replayHighlightClass } from "globalStyles/portals";
interface ReduxStateProps { interface ReduxStateProps {
dynamicData: DataTree; dynamicData: DataTree;
datasources: any; datasources: any;
@ -94,6 +96,7 @@ interface ReduxStateProps {
interface ReduxDispatchProps { interface ReduxDispatchProps {
executeCommand: (payload: any) => void; executeCommand: (payload: any) => void;
startingEntityUpdation: () => void;
} }
export type CodeEditorExpected = { export type CodeEditorExpected = {
@ -239,7 +242,7 @@ class CodeEditor extends Component<Props, State> {
// //
editor.on("beforeChange", this.handleBeforeChange); editor.on("beforeChange", this.handleBeforeChange);
editor.on("change", _.debounce(this.handleChange, 600)); editor.on("change", this.startChange);
editor.on("keyup", this.handleAutocompleteKeyup); editor.on("keyup", this.handleAutocompleteKeyup);
editor.on("focus", this.handleEditorFocus); editor.on("focus", this.handleEditorFocus);
editor.on("cursorActivity", this.handleCursorMovement); editor.on("cursorActivity", this.handleCursorMovement);
@ -304,7 +307,7 @@ class CodeEditor extends Component<Props, State> {
if (!this.editor) return; if (!this.editor) return;
this.editor.off("beforeChange", this.handleBeforeChange); this.editor.off("beforeChange", this.handleBeforeChange);
this.editor.off("change", _.debounce(this.handleChange, 600)); this.editor.off("change", this.startChange);
this.editor.off("keyup", this.handleAutocompleteKeyup); this.editor.off("keyup", this.handleAutocompleteKeyup);
this.editor.off("focus", this.handleEditorFocus); this.editor.off("focus", this.handleEditorFocus);
this.editor.off("cursorActivity", this.handleCursorMovement); this.editor.off("cursorActivity", this.handleCursorMovement);
@ -397,6 +400,18 @@ class CodeEditor extends Component<Props, State> {
CodeEditor.updateMarkings(this.editor, this.props.marking); CodeEditor.updateMarkings(this.editor, this.props.marking);
}; };
handleDebouncedChange = _.debounce(this.handleChange, 600);
startChange = (instance?: any, changeObj?: any) => {
/* This action updates the status of the savingEntity to true so that any
shortcut commands do not execute before updating the entity in the store */
const entity = this.getEntityInformation();
if (entity.entityId) {
this.props.startingEntityUpdation();
}
this.handleDebouncedChange(instance, changeObj);
};
getEntityInformation = (): FieldEntityInformation => { getEntityInformation = (): FieldEntityInformation => {
const { dataTreePath, dynamicData, expected } = this.props; const { dataTreePath, dynamicData, expected } = this.props;
const entityInformation: FieldEntityInformation = { const entityInformation: FieldEntityInformation = {
@ -716,6 +731,7 @@ const mapStateToProps = (state: AppState): ReduxStateProps => ({
const mapDispatchToProps = (dispatch: any): ReduxDispatchProps => ({ const mapDispatchToProps = (dispatch: any): ReduxDispatchProps => ({
executeCommand: (payload: SlashCommandPayload) => executeCommand: (payload: SlashCommandPayload) =>
dispatch(executeCommandAction(payload)), dispatch(executeCommandAction(payload)),
startingEntityUpdation: () => dispatch(startingEntityUpdation()),
}); });
export default Sentry.withProfiler( export default Sentry.withProfiler(

View File

@ -646,6 +646,9 @@ export const ReduxActionTypes = {
DELETE_ORG_SUCCESS: "DELETE_ORG_SUCCESS", DELETE_ORG_SUCCESS: "DELETE_ORG_SUCCESS",
SET_USER_CURRENT_GEO_LOCATION: "SET_USER_CURRENT_GEO_LOCATION", SET_USER_CURRENT_GEO_LOCATION: "SET_USER_CURRENT_GEO_LOCATION",
SET_DISCONNECTING_GIT_APPLICATION: "SET_DISCONNECTING_GIT_APPLICATION", SET_DISCONNECTING_GIT_APPLICATION: "SET_DISCONNECTING_GIT_APPLICATION",
/* This action constants is for identifying the status of the updates of the entities */
ENTITY_UPDATE_STARTED: "ENTITY_UPDATE_STARTED",
ENTITY_UPDATE_SUCCESS: "ENTITY_UPDATE_SUCCESS",
}; };
export type ReduxActionType = typeof ReduxActionTypes[keyof typeof ReduxActionTypes]; export type ReduxActionType = typeof ReduxActionTypes[keyof typeof ReduxActionTypes];

View File

@ -15,6 +15,7 @@ const initialState: EditorReduxState = {
publishingError: false, publishingError: false,
saving: false, saving: false,
savingError: false, savingError: false,
savingEntity: false,
loading: false, loading: false,
loadingError: false, loadingError: false,
pageSwitchingError: false, pageSwitchingError: false,
@ -193,6 +194,21 @@ const editorReducer = createReducer(initialState, {
isPreviewMode: action.payload, isPreviewMode: action.payload,
}; };
}, },
/* This action updates the status of the savingEntity for any entity of the application in the store */
[ReduxActionTypes.ENTITY_UPDATE_STARTED]: (state: EditorReduxState) => ({
...state,
loadingStates: {
...state.loadingStates,
savingEntity: true,
},
}),
[ReduxActionTypes.ENTITY_UPDATE_SUCCESS]: (state: EditorReduxState) => ({
...state,
loadingStates: {
...state.loadingStates,
savingEntity: false,
},
}),
}); });
export interface EditorReduxState { export interface EditorReduxState {
@ -209,6 +225,7 @@ export interface EditorReduxState {
loadingStates: { loadingStates: {
saving: boolean; saving: boolean;
savingError: boolean; savingError: boolean;
savingEntity: boolean;
publishing: boolean; publishing: boolean;
published?: string; published?: string;
publishingError: boolean; publishingError: boolean;

View File

@ -60,6 +60,7 @@ import {
} from "constants/AppsmithActionConstants/ActionConstants"; } from "constants/AppsmithActionConstants/ActionConstants";
import { import {
getCurrentPageId, getCurrentPageId,
getIsSavingEntity,
getLayoutOnLoadActions, getLayoutOnLoadActions,
} from "selectors/editorSelectors"; } from "selectors/editorSelectors";
import PerformanceTracker, { import PerformanceTracker, {
@ -407,7 +408,8 @@ function* runActionSaga(
const actionId = reduxAction.payload.id; const actionId = reduxAction.payload.id;
const isSaving = yield select(isActionSaving(actionId)); const isSaving = yield select(isActionSaving(actionId));
const isDirty = yield select(isActionDirty(actionId)); const isDirty = yield select(isActionDirty(actionId));
if (isSaving || isDirty) { const isSavingEntity = yield select(getIsSavingEntity);
if (isSaving || isDirty || isSavingEntity) {
if (isDirty && !isSaving) { if (isDirty && !isSaving) {
yield put(updateAction({ id: actionId })); yield put(updateAction({ id: actionId }));
} }

View File

@ -930,6 +930,17 @@ function* executeCommandSaga(actionPayload: ReduxAction<SlashCommandPayload>) {
} }
} }
function* updateEntitySavingStatus() {
yield race([
take(ReduxActionTypes.UPDATE_ACTION_SUCCESS),
take(ReduxActionTypes.SAVE_PAGE_SUCCESS),
]);
yield put({
type: ReduxActionTypes.ENTITY_UPDATE_SUCCESS,
});
}
export function* watchActionSagas() { export function* watchActionSagas() {
yield all([ yield all([
takeEvery(ReduxActionTypes.SET_ACTION_PROPERTY, setActionPropertySaga), takeEvery(ReduxActionTypes.SET_ACTION_PROPERTY, setActionPropertySaga),
@ -958,5 +969,9 @@ export function* watchActionSagas() {
toggleActionExecuteOnLoadSaga, toggleActionExecuteOnLoadSaga,
), ),
takeLatest(ReduxActionTypes.EXECUTE_COMMAND, executeCommandSaga), takeLatest(ReduxActionTypes.EXECUTE_COMMAND, executeCommandSaga),
takeLatest(
ReduxActionTypes.ENTITY_UPDATE_STARTED,
updateEntitySavingStatus,
),
]); ]);
} }

View File

@ -69,7 +69,10 @@ export const getIsPageSaving = (state: AppState) => {
}); });
return ( return (
state.ui.editor.loadingStates.saving || areApisSaving || areJsObjectsSaving state.ui.editor.loadingStates.saving ||
areApisSaving ||
areJsObjectsSaving ||
state.ui.editor.loadingStates.savingEntity
); );
}; };
@ -392,3 +395,12 @@ export const previewModeSelector = (state: AppState) => {
export const getZoomLevel = (state: AppState) => { export const getZoomLevel = (state: AppState) => {
return state.ui.editor.zoomLevel; return state.ui.editor.zoomLevel;
}; };
/**
* returns the `state.ui.editor.savingEntity`
*
* @param state AppState
* @returns boolean
*/
export const getIsSavingEntity = (state: AppState) =>
state.ui.editor.loadingStates.savingEntity;