fix: code editor changes (#40239)
## Description We've encountered a bug in the REST API plugin where rapidly changing the URL input causes the save status to get stuck in the loading state. This happens because the evaluation is debounced, and by the time it's ready to run, the inputs may have changed in a way that prevents the evaluation from being triggered. However, we still initiate a saga that tracks the terminal state and controls the loading status. Since the evaluation never actually occurs, the terminal state is never reached, causing the loading status to remain stuck. Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.JS" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/15493848736> > Commit: f993e21dd7a3bc0414d5c2cb35e96f3831b625bc > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=15493848736&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.JS` > Spec: > <hr>Fri, 06 Jun 2025 16:05:30 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit - **Refactor** - Streamlined change handling in the code editor for more consistent updates using a standardized debounce timer. - **Bug Fixes** - Improved auto-save reliability by adding a delay before save status checks to prevent premature assertions. - **New Features** - Introduced a configurable save delay constant to unify save operation timing across the editor. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: “sneha122” <“sneha@appsmith.com”>
This commit is contained in:
parent
fde8d013aa
commit
99db0a1fae
|
|
@ -8,6 +8,9 @@ import EditorNavigator from "./EditorNavigation";
|
|||
import { EntityType } from "./EditorNavigation";
|
||||
import ClickOptions = Cypress.ClickOptions;
|
||||
import { DEBOUNCE_WAIT_TIME_ON_INPUT_CHANGE } from "../../../src/constants/WidgetConstants";
|
||||
const {
|
||||
SAVE_TRIGGER_DELAY_MS,
|
||||
} = require("../../../src/components/editorComponents/CodeEditor/debounceConstants");
|
||||
|
||||
type ElementType = string | JQuery<HTMLElement>;
|
||||
|
||||
|
|
@ -296,6 +299,11 @@ export class AggregateHelper {
|
|||
}
|
||||
|
||||
public AssertAutoSave() {
|
||||
// After fix made in https://github.com/appsmithorg/appsmith/pull/40239 to make save state and nw call in sync
|
||||
// We will need to wait for the debounced time before we make any assertions on save state, otherwise
|
||||
// we might run into situation where absence of save is asserted but save actually hasn't happened
|
||||
// Additional 100ms added to avoid flaky issues that might be caused by race condition.
|
||||
this.Sleep(SAVE_TRIGGER_DELAY_MS + 100);
|
||||
let saveStatus = this.CheckForPageSaveError();
|
||||
// wait for save query to trigger & n/w call to finish occuring
|
||||
if (!saveStatus)
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
export const SAVE_TRIGGER_DELAY_MS = 600;
|
||||
|
|
@ -161,6 +161,7 @@ import { getEachEntityInformation } from "ee/utils/autocomplete/EntityDefinition
|
|||
import { getCurrentPageId } from "selectors/editorSelectors";
|
||||
import { executeCommandAction } from "actions/pluginActionActions";
|
||||
import { PEEK_OVERLAY_DELAY } from "./PeekOverlayPopup/constants";
|
||||
import { SAVE_TRIGGER_DELAY_MS } from "./debounceConstants";
|
||||
|
||||
type ReduxStateProps = ReturnType<typeof mapStateToProps>;
|
||||
type ReduxDispatchProps = ReturnType<typeof mapDispatchToProps>;
|
||||
|
|
@ -269,8 +270,6 @@ interface State {
|
|||
isOpened: boolean;
|
||||
autoCompleteVisible: boolean;
|
||||
hinterOpen: boolean;
|
||||
// Flag for determining whether the entity change has been started or not so that even if the initial and final value remains the same, the status should be changed to not loading
|
||||
changeStarted: boolean;
|
||||
ctrlPressed: boolean;
|
||||
peekOverlayProps:
|
||||
| (PeekOverlayStateProps & {
|
||||
|
|
@ -314,7 +313,6 @@ class CodeEditor extends Component<Props, State> {
|
|||
isOpened: false,
|
||||
autoCompleteVisible: false,
|
||||
hinterOpen: false,
|
||||
changeStarted: false,
|
||||
ctrlPressed: false,
|
||||
peekOverlayProps: undefined,
|
||||
showAIWindow: false,
|
||||
|
|
@ -1309,17 +1307,17 @@ class CodeEditor extends Component<Props, State> {
|
|||
instance?: CodeMirror.Editor,
|
||||
changeObj?: CodeMirror.EditorChangeLinkedList,
|
||||
) => {
|
||||
const value = this.editor?.getValue() || "";
|
||||
const value = this.editor.getValue() || "";
|
||||
const inputValue = this.props.input.value || "";
|
||||
|
||||
if (
|
||||
this.props.input.onChange &&
|
||||
((value !== inputValue && this.state.isFocused) ||
|
||||
this.state.changeStarted)
|
||||
value !== inputValue &&
|
||||
this.state.isFocused
|
||||
) {
|
||||
this.setState({
|
||||
changeStarted: false,
|
||||
});
|
||||
/* 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 */
|
||||
this.props.startingEntityUpdate();
|
||||
this.props.input.onChange(value);
|
||||
}
|
||||
|
||||
|
|
@ -1364,29 +1362,12 @@ class CodeEditor extends Component<Props, State> {
|
|||
}
|
||||
};
|
||||
|
||||
handleDebouncedChange = _.debounce(this.handleChange, 600);
|
||||
handleDebouncedChange = _.debounce(this.handleChange, SAVE_TRIGGER_DELAY_MS);
|
||||
|
||||
startChange = (
|
||||
instance: CodeMirror.Editor,
|
||||
changeObj: CodeMirror.EditorChangeLinkedList,
|
||||
) => {
|
||||
/* 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 value = this.editor.getValue() || "";
|
||||
const inputValue = this.props.input.value || "";
|
||||
|
||||
if (
|
||||
this.props.input.onChange &&
|
||||
value !== inputValue &&
|
||||
this.state.isFocused &&
|
||||
!this.state.changeStarted
|
||||
) {
|
||||
this.setState({
|
||||
changeStarted: true,
|
||||
});
|
||||
this.props.startingEntityUpdate();
|
||||
}
|
||||
|
||||
this.hidePeekOverlay();
|
||||
this.handleDebouncedChange(instance, changeObj);
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user