From cc1ce09b739b8835a39825d9221863729b06510c Mon Sep 17 00:00:00 2001 From: Aditya Toshniwal Date: Sat, 23 Mar 2024 18:22:06 +0530 Subject: [PATCH] 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 --- docs/en_US/release_notes_8_5.rst | 2 ++ web/package.json | 2 +- .../js/Theme/overrides/codemirror.override.js | 2 ++ .../ReactCodeMirror/CustomEditorView.js | 5 ++- web/pgadmin/static/js/custom_hooks.js | 5 ++- web/pgadmin/static/js/utils.js | 2 +- .../debugger/static/js/DebuggerModule.js | 6 ++-- .../components/DebuggerArgumentComponent.jsx | 10 +++--- .../js/components/DebuggerComponent.jsx | 34 ++++++++++++------- .../js/components/sections/MainToolBar.jsx | 32 +++++++++++++---- .../static/js/components/sections/Query.jsx | 3 +- web/yarn.lock | 10 +++--- 12 files changed, 76 insertions(+), 37 deletions(-) diff --git a/docs/en_US/release_notes_8_5.rst b/docs/en_US/release_notes_8_5.rst index 08c60e16b..4e5c7c3a6 100644 --- a/docs/en_US/release_notes_8_5.rst +++ b/docs/en_US/release_notes_8_5.rst @@ -37,3 +37,5 @@ Bug fixes | `Issue #7268 `_ - Fix an issue in editor where Format SQL shortcut and multiline selection are not working. | `Issue #7269 `_ - Fix an issue in editor where "Use Spaces?" Preference of Editor is not working. | `Issue #7277 `_ - Fix an issue in query tool where toggle case of selected text loses selection. + | `Issue #7299 `_ - Fix query tool autocomplete results when cursor is in between the SQL query. + | `Issue #7305 `_ - Fix an issue in query tool where custom keyboard shortcuts are not working for some. diff --git a/web/package.json b/web/package.json index 789236aaa..3e462d94b 100644 --- a/web/package.json +++ b/web/package.json @@ -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", diff --git a/web/pgadmin/static/js/Theme/overrides/codemirror.override.js b/web/pgadmin/static/js/Theme/overrides/codemirror.override.js index a3212dc33..5aa6f5430 100644 --- a/web/pgadmin/static/js/Theme/overrides/codemirror.override.js +++ b/web/pgadmin/static/js/Theme/overrides/codemirror.override.js @@ -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', diff --git a/web/pgadmin/static/js/components/ReactCodeMirror/CustomEditorView.js b/web/pgadmin/static/js/components/ReactCodeMirror/CustomEditorView.js index d622342d0..fd12371b0 100644 --- a/web/pgadmin/static/js/components/ReactCodeMirror/CustomEditorView.js +++ b/web/pgadmin/static/js/components/ReactCodeMirror/CustomEditorView.js @@ -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(); } diff --git a/web/pgadmin/static/js/custom_hooks.js b/web/pgadmin/static/js/custom_hooks.js index 62d095925..c87a339ae 100644 --- a/web/pgadmin/static/js/custom_hooks.js +++ b/web/pgadmin/static/js/custom_hooks.js @@ -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(()=>{ diff --git a/web/pgadmin/static/js/utils.js b/web/pgadmin/static/js/utils.js index 230b2a403..a56eae8f4 100644 --- a/web/pgadmin/static/js/utils.js +++ b/web/pgadmin/static/js/utils.js @@ -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-'; } diff --git a/web/pgadmin/tools/debugger/static/js/DebuggerModule.js b/web/pgadmin/tools/debugger/static/js/DebuggerModule.js index 329f23a10..59391be93 100644 --- a/web/pgadmin/tools/debugger/static/js/DebuggerModule.js +++ b/web/pgadmin/tools/debugger/static/js/DebuggerModule.js @@ -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( diff --git a/web/pgadmin/tools/debugger/static/js/components/DebuggerArgumentComponent.jsx b/web/pgadmin/tools/debugger/static/js/components/DebuggerArgumentComponent.jsx index 211ce7a70..6bd1c2dbb 100644 --- a/web/pgadmin/tools/debugger/static/js/components/DebuggerArgumentComponent.jsx +++ b/web/pgadmin/tools/debugger/static/js/components/DebuggerArgumentComponent.jsx @@ -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) ); }); } diff --git a/web/pgadmin/tools/debugger/static/js/components/DebuggerComponent.jsx b/web/pgadmin/tools/debugger/static/js/components/DebuggerComponent.jsx index b62dfd013..7c511c1ae 100644 --- a/web/pgadmin/tools/debugger/static/js/components/DebuggerComponent.jsx +++ b/web/pgadmin/tools/debugger/static/js/components/DebuggerComponent.jsx @@ -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 = { diff --git a/web/pgadmin/tools/sqleditor/static/js/components/sections/MainToolBar.jsx b/web/pgadmin/tools/sqleditor/static/js/components/sections/MainToolBar.jsx index f77c45671..4e928e286 100644 --- a/web/pgadmin/tools/sqleditor/static/js/components/sections/MainToolBar.jsx +++ b/web/pgadmin/tools/sqleditor/static/js/components/sections/MainToolBar.jsx @@ -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}) { {eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_FIND_REPLACE, true);}}>{gettext('Replace')} {eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_EXEC_CMD, 'gotoLineCol');}}>{gettext('Go to Line/Column')} + onClick={()=>{executeCmd('gotoLineCol');}}>{gettext('Go to Line/Column')} {eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_EXEC_CMD, 'indentMore');}}>{gettext('Indent Selection')} + onClick={()=>{executeCmd('indentMore');}}>{gettext('Indent Selection')} {eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_EXEC_CMD, 'indentLess');}}>{gettext('Unindent Selection')} + onClick={()=>{executeCmd('indentLess');}}>{gettext('Unindent Selection')} {eventBus.fireEvent(QUERY_TOOL_EVENTS.EDITOR_EXEC_CMD, 'toggleComment');}}>{gettext('Toggle Comment')} + onClick={()=>{executeCmd('toggleComment');}}>{gettext('Toggle Comment')} {gettext('Toggle Case Of Selected Text')} { onAvailable(); resolve({ diff --git a/web/yarn.lock b/web/yarn.lock index e829646e4..15fdbd116 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -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