revert: removed changes done for cursor position jump fix (#9193)

This commit is contained in:
Abhi kumar 2025-09-25 19:27:05 +05:30 committed by GitHub
parent 96cdf21a92
commit 9a5bcb6b64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 11 additions and 80 deletions

View File

@ -97,7 +97,7 @@ function QuerySearch({
onRun?: (query: string) => void; onRun?: (query: string) => void;
}): JSX.Element { }): JSX.Element {
const isDarkMode = useIsDarkMode(); const isDarkMode = useIsDarkMode();
const [query, setQuery] = useState<string>(''); const [query, setQuery] = useState<string>(queryData.filter?.expression || '');
const [valueSuggestions, setValueSuggestions] = useState<any[]>([]); const [valueSuggestions, setValueSuggestions] = useState<any[]>([]);
const [activeKey, setActiveKey] = useState<string>(''); const [activeKey, setActiveKey] = useState<string>('');
const [isLoadingSuggestions, setIsLoadingSuggestions] = useState(false); const [isLoadingSuggestions, setIsLoadingSuggestions] = useState(false);
@ -108,10 +108,6 @@ function QuerySearch({
errors: [], errors: [],
}); });
const [cursorPos, setCursorPos] = useState({ line: 0, ch: 0 });
const [isFocused, setIsFocused] = useState(false);
const [hasInteractedWithQB, setHasInteractedWithQB] = useState(false);
const handleQueryValidation = (newQuery: string): void => { const handleQueryValidation = (newQuery: string): void => {
try { try {
const validationResponse = validateQuery(newQuery); const validationResponse = validateQuery(newQuery);
@ -131,28 +127,13 @@ function QuerySearch({
useEffect(() => { useEffect(() => {
const newQuery = queryData.filter?.expression || ''; const newQuery = queryData.filter?.expression || '';
// Only update query from external source when editor is not focused // Only mark as external change if the query actually changed from external source
// When focused, just update the lastExternalQuery to track changes
if (newQuery !== lastExternalQuery) { if (newQuery !== lastExternalQuery) {
setQuery(newQuery); setQuery(newQuery);
setIsExternalQueryChange(true); setIsExternalQueryChange(true);
setLastExternalQuery(newQuery); setLastExternalQuery(newQuery);
} }
// eslint-disable-next-line react-hooks/exhaustive-deps }, [queryData.filter?.expression, lastExternalQuery]);
}, [queryData.filter?.expression]);
useEffect(() => {
// Update the query when the editor is blurred and the query has changed
// Only call onChange if the editor has been focused before (not on initial mount)
if (
!isFocused &&
hasInteractedWithQB &&
query !== queryData.filter?.expression
) {
onChange(query);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isFocused]);
// Validate query when it changes externally (from queryData) // Validate query when it changes externally (from queryData)
useEffect(() => { useEffect(() => {
@ -168,6 +149,9 @@ function QuerySearch({
const [showExamples] = useState(false); const [showExamples] = useState(false);
const [cursorPos, setCursorPos] = useState({ line: 0, ch: 0 });
const [isFocused, setIsFocused] = useState(false);
const [ const [
isFetchingCompleteValuesList, isFetchingCompleteValuesList,
setIsFetchingCompleteValuesList, setIsFetchingCompleteValuesList,
@ -181,9 +165,6 @@ function QuerySearch({
const lastFetchedKeyRef = useRef<string>(''); const lastFetchedKeyRef = useRef<string>('');
const lastValueRef = useRef<string>(''); const lastValueRef = useRef<string>('');
const isMountedRef = useRef<boolean>(true); const isMountedRef = useRef<boolean>(true);
const [shouldRunQueryPostUpdate, setShouldRunQueryPostUpdate] = useState(
false,
);
const { handleRunQuery } = useQueryBuilder(); const { handleRunQuery } = useQueryBuilder();
@ -229,7 +210,6 @@ function QuerySearch({
return (): void => clearTimeout(timeoutId); return (): void => clearTimeout(timeoutId);
}, },
// eslint-disable-next-line react-hooks/exhaustive-deps
[isFocused], [isFocused],
); );
@ -575,6 +555,7 @@ function QuerySearch({
const handleChange = (value: string): void => { const handleChange = (value: string): void => {
setQuery(value); setQuery(value);
onChange(value);
// Mark as internal change to avoid triggering external validation // Mark as internal change to avoid triggering external validation
setIsExternalQueryChange(false); setIsExternalQueryChange(false);
// Update lastExternalQuery to prevent external validation trigger // Update lastExternalQuery to prevent external validation trigger
@ -1238,25 +1219,6 @@ function QuerySearch({
</div> </div>
); );
// Effect to handle query run after update
useEffect(
() => {
// Only run the query post updating the filter expression.
// This runs the query in the next update cycle of react, when it's guaranteed that the query is updated.
// Because both the things are sequential and react batches the updates so it was still taking the old query.
if (shouldRunQueryPostUpdate) {
if (onRun && typeof onRun === 'function') {
onRun(query);
} else {
handleRunQuery();
}
setShouldRunQueryPostUpdate(false);
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[shouldRunQueryPostUpdate, handleRunQuery, onRun],
);
return ( return (
<div className="code-mirror-where-clause"> <div className="code-mirror-where-clause">
{editingMode && ( {editingMode && (
@ -1331,7 +1293,6 @@ function QuerySearch({
theme={isDarkMode ? copilot : githubLight} theme={isDarkMode ? copilot : githubLight}
onChange={handleChange} onChange={handleChange}
onUpdate={handleUpdate} onUpdate={handleUpdate}
data-testid="query-where-clause-editor"
className={cx('query-where-clause-editor', { className={cx('query-where-clause-editor', {
isValid: validation.isValid === true, isValid: validation.isValid === true,
hasErrors: validation.errors.length > 0, hasErrors: validation.errors.length > 0,
@ -1368,14 +1329,11 @@ function QuerySearch({
// and instead run a custom action // and instead run a custom action
// Mod-Enter is usually Ctrl-Enter or Cmd-Enter based on OS // Mod-Enter is usually Ctrl-Enter or Cmd-Enter based on OS
run: (): boolean => { run: (): boolean => {
if ( if (onRun && typeof onRun === 'function') {
onChange && onRun(query);
typeof onChange === 'function' && } else {
query !== queryData.filter?.expression handleRunQuery();
) {
onChange(query);
} }
setShouldRunQueryPostUpdate(true);
return true; return true;
}, },
}, },
@ -1394,13 +1352,8 @@ function QuerySearch({
}} }}
onFocus={(): void => { onFocus={(): void => {
setIsFocused(true); setIsFocused(true);
setHasInteractedWithQB(true);
}} }}
onBlur={handleBlur} onBlur={handleBlur}
onCreateEditor={(view: EditorView): EditorView => {
editorRef.current = view;
return view;
}}
/> />
{query && validation.isValid === false && !isFocused && ( {query && validation.isValid === false && !isFocused && (

View File

@ -222,28 +222,6 @@ describe('QuerySearch', () => {
expect(screen.getByPlaceholderText(PLACEHOLDER_TEXT)).toBeInTheDocument(); expect(screen.getByPlaceholderText(PLACEHOLDER_TEXT)).toBeInTheDocument();
}); });
it('calls onChange on blur after user edits', async () => {
const handleChange = jest.fn() as jest.MockedFunction<(v: string) => void>;
const user = userEvent.setup({ pointerEventsCheck: 0 });
render(
<QuerySearch
onChange={handleChange}
queryData={initialQueriesMap.metrics.builder.queryData[0]}
dataSource={DataSource.METRICS}
/>,
);
const editor = screen.getByTestId(TESTID_EDITOR);
await user.click(editor);
await user.type(editor, SAMPLE_VALUE_TYPING_COMPLETE);
// Blur triggers validation + onChange (only if focused at least once and value changed)
editor.blur();
await waitFor(() => expect(handleChange).toHaveBeenCalledTimes(1));
expect(handleChange.mock.calls[0][0]).toContain("service.name = 'frontend'");
});
it('fetches key suggestions when typing a key (debounced)', async () => { it('fetches key suggestions when typing a key (debounced)', async () => {
jest.useFakeTimers(); jest.useFakeTimers();
const advance = (ms: number): void => { const advance = (ms: number): void => {