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")
.first()
.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.runQuery();
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 { getLintAnnotations } from "./lintHelpers";
import { executeCommandAction } from "actions/apiPaneActions";
import { startingEntityUpdation } from "actions/editorActions";
import { SlashCommandPayload } from "entities/Action";
import { Indices } from "constants/Layers";
import { replayHighlightClass } from "globalStyles/portals";
interface ReduxStateProps {
dynamicData: DataTree;
datasources: any;
@ -94,6 +96,7 @@ interface ReduxStateProps {
interface ReduxDispatchProps {
executeCommand: (payload: any) => void;
startingEntityUpdation: () => void;
}
export type CodeEditorExpected = {
@ -239,7 +242,7 @@ class CodeEditor extends Component<Props, State> {
//
editor.on("beforeChange", this.handleBeforeChange);
editor.on("change", _.debounce(this.handleChange, 600));
editor.on("change", this.startChange);
editor.on("keyup", this.handleAutocompleteKeyup);
editor.on("focus", this.handleEditorFocus);
editor.on("cursorActivity", this.handleCursorMovement);
@ -304,7 +307,7 @@ class CodeEditor extends Component<Props, State> {
if (!this.editor) return;
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("focus", this.handleEditorFocus);
this.editor.off("cursorActivity", this.handleCursorMovement);
@ -397,6 +400,18 @@ class CodeEditor extends Component<Props, State> {
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 => {
const { dataTreePath, dynamicData, expected } = this.props;
const entityInformation: FieldEntityInformation = {
@ -716,6 +731,7 @@ const mapStateToProps = (state: AppState): ReduxStateProps => ({
const mapDispatchToProps = (dispatch: any): ReduxDispatchProps => ({
executeCommand: (payload: SlashCommandPayload) =>
dispatch(executeCommandAction(payload)),
startingEntityUpdation: () => dispatch(startingEntityUpdation()),
});
export default Sentry.withProfiler(

View File

@ -646,6 +646,9 @@ export const ReduxActionTypes = {
DELETE_ORG_SUCCESS: "DELETE_ORG_SUCCESS",
SET_USER_CURRENT_GEO_LOCATION: "SET_USER_CURRENT_GEO_LOCATION",
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];

View File

@ -15,6 +15,7 @@ const initialState: EditorReduxState = {
publishingError: false,
saving: false,
savingError: false,
savingEntity: false,
loading: false,
loadingError: false,
pageSwitchingError: false,
@ -193,6 +194,21 @@ const editorReducer = createReducer(initialState, {
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 {
@ -209,6 +225,7 @@ export interface EditorReduxState {
loadingStates: {
saving: boolean;
savingError: boolean;
savingEntity: boolean;
publishing: boolean;
published?: string;
publishingError: boolean;

View File

@ -60,6 +60,7 @@ import {
} from "constants/AppsmithActionConstants/ActionConstants";
import {
getCurrentPageId,
getIsSavingEntity,
getLayoutOnLoadActions,
} from "selectors/editorSelectors";
import PerformanceTracker, {
@ -407,7 +408,8 @@ function* runActionSaga(
const actionId = reduxAction.payload.id;
const isSaving = yield select(isActionSaving(actionId));
const isDirty = yield select(isActionDirty(actionId));
if (isSaving || isDirty) {
const isSavingEntity = yield select(getIsSavingEntity);
if (isSaving || isDirty || isSavingEntity) {
if (isDirty && !isSaving) {
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() {
yield all([
takeEvery(ReduxActionTypes.SET_ACTION_PROPERTY, setActionPropertySaga),
@ -958,5 +969,9 @@ export function* watchActionSagas() {
toggleActionExecuteOnLoadSaga,
),
takeLatest(ReduxActionTypes.EXECUTE_COMMAND, executeCommandSaga),
takeLatest(
ReduxActionTypes.ENTITY_UPDATE_STARTED,
updateEntitySavingStatus,
),
]);
}

View File

@ -69,7 +69,10 @@ export const getIsPageSaving = (state: AppState) => {
});
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) => {
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;