Fix: shortcut can be used throughtout the editor and added custom hook in codeeditor for query panel shortcuts.

This commit is contained in:
devanshu052000 2025-03-07 15:34:31 +05:30
parent 191348efdc
commit f234384f25
5 changed files with 103 additions and 31 deletions

View file

@ -21,6 +21,7 @@ import useStore from '@/AppBuilder/_stores/store';
import { shallow } from 'zustand/shallow';
import { search, searchKeymap, searchPanelOpen } from '@codemirror/search';
import { handleSearchPanel, SearchBtn } from './SearchBox';
import { useQueryPanelKeyHooks } from './useQueryPanelKeyHooks';
const langSupport = Object.freeze({
javascript: javascript(),
@ -64,6 +65,8 @@ const MultiLineCodeEditor = (props) => {
const [editorView, setEditorView] = React.useState(null);
const { queryPanelKeybindings } = useQueryPanelKeyHooks(onChange, currentValueRef, 'multiline');
const handleOnBlur = () => {
if (!delayOnChange) return onChange(currentValueRef.current);
setTimeout(() => {
@ -85,6 +88,7 @@ const MultiLineCodeEditor = (props) => {
highlightActiveLine: false,
autocompletion: hideSuggestion ?? true,
highlightActiveLineGutter: false,
defaultKeymap: false,
completionKeymap: true,
searchKeymap: false,
};
@ -187,7 +191,12 @@ const MultiLineCodeEditor = (props) => {
};
}
const customKeyMaps = [...defaultKeymap, ...completionKeymap, ...searchKeymap];
const customKeyMaps = [
...defaultKeymap.filter((keyBinding) => keyBinding.key !== 'Mod-Enter'), // Remove default keybinding for Mod-Enter
...completionKeymap,
...searchKeymap,
];
const customTabKeymap = keymap.of([
{
key: 'Tab',
@ -208,6 +217,7 @@ const MultiLineCodeEditor = (props) => {
return true;
},
},
...queryPanelKeybindings,
]);
// eslint-disable-next-line react-hooks/exhaustive-deps

View file

@ -22,6 +22,7 @@ import CodeHinter from './CodeHinter';
import { removeNestedDoubleCurlyBraces } from '@/_helpers/utils';
import useStore from '@/AppBuilder/_stores/store';
import { shallow } from 'zustand/shallow';
import { useQueryPanelKeyHooks } from './useQueryPanelKeyHooks';
const SingleLineCodeEditor = ({ componentName, fieldMeta = {}, componentId, ...restProps }) => {
const { initialValue, onChange, enablePreview = true, portalProps } = restProps;
@ -170,6 +171,8 @@ const EditorInput = ({
onInputChange,
}) => {
const getSuggestions = useStore((state) => state.getSuggestions, shallow);
const { queryPanelKeybindings } = useQueryPanelKeyHooks(onBlurUpdate, currentValue, 'singleline');
function autoCompleteExtensionConfig(context) {
const hints = getSuggestions();
let word = context.matchBefore(/\w*/);
@ -229,7 +232,10 @@ const EditorInput = ({
maxRenderedOptions: 10,
});
const customKeyMaps = [...defaultKeymap, ...completionKeymap];
const customKeyMaps = [
...defaultKeymap.filter((keyBinding) => keyBinding.key !== 'Mod-Enter'), // Remove default keybinding for Mod-Enter
...completionKeymap,
];
const customTabKeymap = keymap.of([
{
key: 'Tab',
@ -251,6 +257,7 @@ const EditorInput = ({
}
},
},
...queryPanelKeybindings,
]);
const handleOnChange = React.useCallback((val) => {
@ -395,6 +402,7 @@ const EditorInput = ({
foldGutter: false,
highlightActiveLine: false,
autocompletion: true,
defaultKeymap: false,
completionKeymap: true,
searchKeymap: false,
}}

View file

@ -0,0 +1,58 @@
import { useModuleId } from '@/AppBuilder/_contexts/ModuleContext';
import useStore from '@/AppBuilder/_stores/store';
import { useCallback, useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
export const useQueryPanelKeyHooks = (onChange, value, type) => {
const queryPanelHeight = useStore((state) => state.queryPanel.queryPanelHeight);
const runQueryOnShortcut = useStore((state) => state.queryPanel.runQueryOnShortcut);
const previewQueryOnShortcut = useStore((state) => state.queryPanel.previewQueryOnShortcut);
const moduleId = useModuleId();
const location = useLocation();
const { pathname } = location;
const [queryPanelKeybindings, setQueryPanelKeybindings] = useState([]);
const handleRunQuery = useCallback(
(view) => {
const isEditor = pathname.includes('/apps/');
if (queryPanelHeight !== 0 && isEditor) {
onChange(type === 'multiline' ? value.current : value);
runQueryOnShortcut();
}
return true;
},
[queryPanelHeight, onChange, runQueryOnShortcut, value]
);
const handlePreviewQuery = useCallback(
(view) => {
const isEditor = pathname.includes('/apps/');
if (queryPanelHeight !== 0 && isEditor) {
onChange(type === 'multiline' ? value.current : value);
previewQueryOnShortcut(moduleId);
}
return true;
},
[queryPanelHeight, moduleId, onChange, previewQueryOnShortcut, value]
);
useEffect(() => {
setQueryPanelKeybindings([
{
key: 'Mod-Enter',
preventDefault: true,
run: handleRunQuery,
},
{
key: 'Mod-Shift-Enter',
preventDefault: true,
run: handlePreviewQuery,
},
]);
}, [handleRunQuery, handlePreviewQuery]);
return {
queryPanelKeybindings,
};
};

View file

@ -4,45 +4,23 @@ import { useHotkeys } from 'react-hotkeys-hook';
import { useModuleId } from '@/AppBuilder/_contexts/ModuleContext';
const QueryKeyHooks = ({ children, isExpanded }) => {
const runQuery = useStore((state) => state.queryPanel.runQuery);
const selectedQuery = useStore((state) => state.queryPanel.selectedQuery);
const runQueryOnShortcut = useStore((state) => state.queryPanel.runQueryOnShortcut);
const previewQueryOnShortcut = useStore((state) => state.queryPanel.previewQueryOnShortcut);
const moduleId = useModuleId();
const previewQuery = useStore((state) => state.queryPanel.previewQuery);
const selectedDataSource = useStore((state) => state.queryPanel.selectedDataSource);
const queryName = selectedQuery?.name ?? '';
const previewButtonOnClick = () => {
const _options = { ...selectedQuery.options };
const query = {
data_source_id: selectedDataSource.id === 'null' ? null : selectedDataSource.id,
pluginId: selectedDataSource.pluginId,
options: _options,
kind: selectedDataSource.kind,
name: queryName,
id: selectedQuery?.id,
};
previewQuery(query, false, undefined, moduleId).catch(({ error, data }) => {
console.log(error, data);
});
};
const shortcutRef = useHotkeys(
useHotkeys(
['mod+enter', 'mod+shift+enter'],
(event, handler) => {
if (handler.mod && handler.keys[0] === 'enter') {
if (handler.shift) {
previewButtonOnClick();
} else runQuery(selectedQuery?.id, selectedQuery?.name, undefined, 'edit', {}, true);
previewQueryOnShortcut(moduleId);
} else runQueryOnShortcut();
}
},
{ enabled: isExpanded }
{ enabled: isExpanded, enableOnFormTags: ['input'] }
);
return (
<div ref={shortcutRef} tabIndex={-1} className="row main-row">
{children}
</div>
);
return <div className="row main-row">{children}</div>;
};
export default QueryKeyHooks;

View file

@ -1028,5 +1028,23 @@ export const createQueryPanelSlice = (set, get) => ({
isQuerySelected: (queryId) => {
return get().queryPanel.selectedQuery?.id === queryId;
},
runQueryOnShortcut: () => {
const { queryPanel } = get();
const { runQuery, selectedQuery } = queryPanel;
runQuery(selectedQuery?.id, selectedQuery?.name, undefined, 'edit', {}, true);
},
previewQueryOnShortcut: (moduleId = 'canvas') => {
const { queryPanel } = get();
const { previewQuery, selectedQuery, selectedDataSource } = queryPanel;
const query = {
data_source_id: selectedDataSource.id === 'null' ? null : selectedDataSource.id,
pluginId: selectedDataSource.pluginId,
options: { ...selectedQuery?.options },
kind: selectedDataSource.kind,
name: selectedQuery?.name ?? '',
id: selectedQuery?.id,
};
previewQuery(query, false, undefined, moduleId);
},
},
});