More CodeMirror fixes. #7268

Fix query tool autocomplete results when cursor is in between the SQL query. #7299
Fix an issue in query tool where custom keyboard shortcuts are not working for some. #7305
This commit is contained in:
Aditya Toshniwal 2024-03-23 18:22:06 +05:30
parent 25074e46b4
commit cc1ce09b73
12 changed files with 76 additions and 37 deletions

View File

@ -37,3 +37,5 @@ Bug fixes
| `Issue #7268 <https://github.com/pgadmin-org/pgadmin4/issues/7268>`_ - Fix an issue in editor where Format SQL shortcut and multiline selection are not working.
| `Issue #7269 <https://github.com/pgadmin-org/pgadmin4/issues/7269>`_ - Fix an issue in editor where "Use Spaces?" Preference of Editor is not working.
| `Issue #7277 <https://github.com/pgadmin-org/pgadmin4/issues/7277>`_ - Fix an issue in query tool where toggle case of selected text loses selection.
| `Issue #7299 <https://github.com/pgadmin-org/pgadmin4/issues/7299>`_ - Fix query tool autocomplete results when cursor is in between the SQL query.
| `Issue #7305 <https://github.com/pgadmin-org/pgadmin4/issues/7305>`_ - Fix an issue in query tool where custom keyboard shortcuts are not working for some.

View File

@ -76,7 +76,7 @@
"dependencies": {
"@babel/plugin-proposal-class-properties": "^7.10.4",
"@babel/preset-react": "^7.12.13",
"@codemirror/lang-sql": "^6.5.5",
"@codemirror/lang-sql": "^6.6.2",
"@date-io/core": "^1.3.6",
"@date-io/date-fns": "1.x",
"@emotion/sheet": "^1.0.1",

View File

@ -102,9 +102,11 @@ export default function cmOverride(theme) {
}
},
'.cm-tooltip': {
...theme.mixins.fontSourceCode,
backgroundColor: theme.palette.background.default + '!important',
color: theme.palette.text.primary + '!important',
border: `1px solid ${theme.otherVars.borderColor} !important`,
fontSize: '0.9em',
'& li[aria-selected="true"]': {
backgroundColor: theme.otherVars.treeBgSelected + '!important',

View File

@ -27,7 +27,10 @@ export default class CustomEditorView extends EditorView {
this._cleanDoc = this.state.doc;
}
getValue() {
getValue(tillCursor=false) {
if(tillCursor) {
return this.state.sliceDoc(0, this.state.selection.main.head);
}
return this.state.doc.toString();
}

View File

@ -1,5 +1,6 @@
import {useRef, useEffect, useState, useCallback, useLayoutEffect} from 'react';
import moment from 'moment';
import { isMac } from './keyboard_shortcuts';
/* React hook for setInterval */
export function useInterval(callback, delay) {
@ -150,9 +151,11 @@ export function useKeyboardShortcuts(shortcuts, eleRef) {
const matchFound = (shortcut, e)=>{
if(!shortcut) return false;
let keyCode = e.which || e.keyCode;
const ctrlKey = (isMac() && shortcut.ctrl_is_meta) ? e.metaKey : e.ctrlKey;
return Boolean(shortcut.alt) == e.altKey &&
Boolean(shortcut.shift) == e.shiftKey &&
Boolean(shortcut.control) == e.ctrlKey &&
Boolean(shortcut.control) == ctrlKey &&
shortcut.key.key_code == keyCode;
};
useEffect(()=>{

View File

@ -46,7 +46,7 @@ export function toCodeMirrorKey(obj) {
if (obj.shift) { shortcut += 'Shift-'; }
if (obj.control) {
if(isMac() && obj.ctrl_is_meta) {
shortcut += 'Mod-';
shortcut += 'Meta-';
} else {
shortcut += 'Ctrl-';
}

View File

@ -26,7 +26,7 @@ import DebuggerComponent from './components/DebuggerComponent';
import Theme from '../../../../static/js/Theme';
import { BROWSER_PANELS } from '../../../../browser/static/js/constants';
import { NotifierProvider } from '../../../../static/js/helpers/Notifier';
import usePreferences from '../../../../preferences/static/js/store';
import usePreferences, { listenPreferenceBroadcast } from '../../../../preferences/static/js/store';
import pgAdmin from 'sources/pgadmin';
import { PgAdminContext } from '../../../../static/js/BrowserComponent';
@ -565,7 +565,7 @@ export default class DebuggerModule {
}
/* We should get the transaction id from the server during initialization here */
load(container, trans_id, debug_type, function_name_with_arguments, layout) {
async load(container, trans_id, debug_type, function_name_with_arguments, layout) {
this.trans_id = trans_id;
this.debug_type = debug_type;
this.first_time_indirect_debug = false;
@ -576,11 +576,11 @@ export default class DebuggerModule {
this.is_polling_required = true; // Flag to stop unwanted ajax calls
this.function_name_with_arguments = function_name_with_arguments;
this.layout = layout;
this.preferences = usePreferences.getState().getPreferencesForModule('debugger');
let selectedNodeInfo = pgWindow.pgAdmin.Browser.tree.getTreeNodeHierarchy(
pgWindow.pgAdmin.Browser.tree.selected()
);
await listenPreferenceBroadcast();
ReactDOM.render(
<Theme>

View File

@ -23,7 +23,7 @@ import pgAdmin from 'sources/pgadmin';
import Loader from 'sources/components/Loader';
import SchemaView from '../../../../../static/js/SchemaView';
import getApiInstance from '../../../../../static/js/api_instance';
import getApiInstance, { parseApiError } from '../../../../../static/js/api_instance';
import { DefaultButton, PrimaryButton } from '../../../../../static/js/components/Buttons';
import { getAppropriateLabel, getDebuggerTitle } from '../debugger_utils';
import { DebuggerArgumentSchema } from './DebuggerArgs.ui';
@ -737,7 +737,7 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
setLoaderText('');
pgAdmin.Browser.notifier.alert(
gettext('Error occured: '),
gettext(error.response.data)
parseApiError(error)
);
});
/* Close the debugger modal dialog */
@ -748,7 +748,7 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
setLoaderText('');
pgAdmin.Browser.notifier.alert(
gettext('Debugger Target Initialization Error'),
gettext(error.response.data)
parseApiError(error)
);
});
@ -769,7 +769,7 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
props.closeModal();
pgAdmin.Browser.notifier.alert(
gettext('Debugger Listener Startup Error'),
gettext(error.response.data)
parseApiError(error)
);
});
setLoaderText('');
@ -793,7 +793,7 @@ export default function DebuggerArgumentComponent({ debuggerInfo, restartDebug,
setLoaderText('');
pgAdmin.Browser.notifier.alert(
gettext('Debugger Listener Startup Set Arguments Error'),
gettext(error.response.data)
parseApiError(error)
);
});
}

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import { Box } from '@material-ui/core';
import React, { useEffect, useRef } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import gettext from 'sources/gettext';
@ -45,13 +45,11 @@ export default function DebuggerComponent({ pgAdmin, selectedNodeInfo, panelId,
const editor = useRef(null);
const preferencesStore = usePreferences();
let timeOut = null;
const qtState = {
is_new_tab: window.location == window.parent?.location,
params: {
...params,
node_name: retrieveNodeName(selectedNodeInfo),
}
};
const [preferences, setPreferences] = useState({
browser: preferencesStore.getPreferencesForModule('browser'),
debugger: preferencesStore.getPreferencesForModule('debugger'),
});
const disableToolbarButtons = () => {
eventBus.current.fireEvent(DEBUGGER_EVENTS.DISABLE_MENU);
@ -1066,16 +1064,26 @@ export default function DebuggerComponent({ pgAdmin, selectedNodeInfo, panelId,
});
}, []);
useEffect(() => usePreferences.subscribe(
state => {
setPreferences({
browser: state.getPreferencesForModule('browser'),
debugger: state.getPreferencesForModule('debugger'),
});
}
), []);
const DebuggerContextValue = React.useMemo(() => ({
docker: docker.current,
api: api,
modal: modal,
params: qtState.params,
preferences: {
browser: preferencesStore.getPreferencesForModule('browser'),
debugger: preferencesStore.getPreferencesForModule('debugger'),
params: {
...params,
node_name: retrieveNodeName(selectedNodeInfo),
},
}), [qtState.params, preferencesStore]);
preferences: preferences,
}), [preferences]);
// Define the debugger layout components such as DebuggerEditor to show queries and
let defaultLayout = {

View File

@ -318,6 +318,8 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros}) {
);
};
const executeCmd = (cmd)=>eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_EXEC_CMD, cmd);
useEffect(()=>{
if(queryToolPref) {
/* Get the prefs first time */
@ -370,9 +372,21 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros}) {
}
},
{
shortcut: queryToolPref.format_sql,
shortcut: queryToolPref.indent,
options: {
callback: ()=>{formatSQL();}
callback: ()=>{executeCmd('indentMore');}
}
},
{
shortcut: queryToolPref.unindent,
options: {
callback: ()=>{executeCmd('indentLess');}
}
},
{
shortcut: queryToolPref.comment,
options: {
callback: ()=>{executeCmd('toggleComment');}
}
},
{
@ -387,6 +401,12 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros}) {
callback: ()=>{clearQuery();}
}
},
{
shortcut: queryToolPref.format_sql,
options: {
callback: ()=>{formatSQL();}
}
},
], containerRef);
/* Macro shortcuts */
@ -520,14 +540,14 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros}) {
<PgMenuItem shortcut={queryToolPref.replace}
onClick={()=>{eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_FIND_REPLACE, true);}}>{gettext('Replace')}</PgMenuItem>
<PgMenuItem shortcut={queryToolPref.gotolinecol}
onClick={()=>{eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_EXEC_CMD, 'gotoLineCol');}}>{gettext('Go to Line/Column')}</PgMenuItem>
onClick={()=>{executeCmd('gotoLineCol');}}>{gettext('Go to Line/Column')}</PgMenuItem>
<PgMenuDivider />
<PgMenuItem shortcut={queryToolPref.indent}
onClick={()=>{eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_EXEC_CMD, 'indentMore');}}>{gettext('Indent Selection')}</PgMenuItem>
onClick={()=>{executeCmd('indentMore');}}>{gettext('Indent Selection')}</PgMenuItem>
<PgMenuItem shortcut={queryToolPref.unindent}
onClick={()=>{eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_EXEC_CMD, 'indentLess');}}>{gettext('Unindent Selection')}</PgMenuItem>
onClick={()=>{executeCmd('indentLess');}}>{gettext('Unindent Selection')}</PgMenuItem>
<PgMenuItem shortcut={queryToolPref.comment}
onClick={()=>{eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_EXEC_CMD, 'toggleComment');}}>{gettext('Toggle Comment')}</PgMenuItem>
onClick={()=>{executeCmd('toggleComment');}}>{gettext('Toggle Comment')}</PgMenuItem>
<PgMenuItem shortcut={queryToolPref.toggle_case}
onClick={toggleCase}>{gettext('Toggle Case Of Selected Text')}</PgMenuItem>
<PgMenuItem shortcut={queryToolPref.clear_query}

View File

@ -39,7 +39,8 @@ async function registerAutocomplete(editor, api, transId) {
});
const word = context.matchBefore(/\w*/);
const fullSql = context.state.doc.toString();
api.post(url, JSON.stringify([fullSql, fullSql]))
const sqlTillCur = context.state.sliceDoc(0, context.state.selection.main.head);
api.post(url, JSON.stringify([fullSql, sqlTillCur]))
.then((res) => {
onAvailable();
resolve({

View File

@ -2383,9 +2383,9 @@ __metadata:
languageName: node
linkType: hard
"@codemirror/lang-sql@npm:^6.5.5":
version: 6.5.5
resolution: "@codemirror/lang-sql@npm:6.5.5"
"@codemirror/lang-sql@npm:^6.6.2":
version: 6.6.2
resolution: "@codemirror/lang-sql@npm:6.6.2"
dependencies:
"@codemirror/autocomplete": ^6.0.0
"@codemirror/language": ^6.0.0
@ -2393,7 +2393,7 @@ __metadata:
"@lezer/common": ^1.2.0
"@lezer/highlight": ^1.0.0
"@lezer/lr": ^1.0.0
checksum: 404003ae73b986bd7a00f6924db78b7ffb28fdc38d689fdc11416aaafe2d5c6dc37cc18972530f82e940acb61e18ac74a1cf7712beef448c145344ff93970dc3
checksum: 664b20c65a8fa142f76baec7fe3c7c419e12ee89481fef0083917cc8640256af4945a9c82712ae67c6e96a5f2a46007e1dda8b3ce3d38d61d13da0ed116bcae9
languageName: node
linkType: hard
@ -14946,7 +14946,7 @@ __metadata:
"@babel/preset-env": ^7.10.2
"@babel/preset-react": ^7.12.13
"@babel/preset-typescript": ^7.22.5
"@codemirror/lang-sql": ^6.5.5
"@codemirror/lang-sql": ^6.6.2
"@date-io/core": ^1.3.6
"@date-io/date-fns": 1.x
"@emotion/core": ^10.0.14