Added an option to open the file in a new tab within the query tool. #1235

pull/8484/head
Yogesh Mahajan 2025-02-21 14:45:41 +05:30 committed by GitHub
parent b983b094a3
commit 636821f2ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 71 additions and 16 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -474,6 +474,9 @@ Use the fields on the *Options* panel to manage editor preferences.
editor will prompt the user to saved unsaved data when exiting the data editor will prompt the user to saved unsaved data when exiting the data
editor. editor.
* When the *Open the file in a new tab?* switch is set to *True*, the
editor will open the new file in new tab of the Query Tool.
* When the *Prompt to save unsaved query changes?* switch is set to *True*, the * When the *Prompt to save unsaved query changes?* switch is set to *True*, the
editor will prompt the user to saved unsaved query modifications when exiting editor will prompt the user to saved unsaved query modifications when exiting
the Query Tool. the Query Tool.

View File

@ -29,7 +29,8 @@ File Options
+----------------------+---------------------------------------------------------------------------------------------------+----------------+ +----------------------+---------------------------------------------------------------------------------------------------+----------------+
| Icon | Behavior | Shortcut | | Icon | Behavior | Shortcut |
+======================+===================================================================================================+================+ +======================+===================================================================================================+================+
| *Open File* | Click the *Open File* icon to display a previously saved query in the SQL Editor. | Cmd/Ctrl + O | | *Open File* | Click the *Open File* icon to display a previously saved query in the same tab of the SQL Editor. | |
| | To open the file in a new tab, select *Open in a new tab?* option from the dropdown. | Cmd/Ctrl + O |
+----------------------+---------------------------------------------------------------------------------------------------+----------------+ +----------------------+---------------------------------------------------------------------------------------------------+----------------+
| *Save File* | Click the *Save* icon to perform a quick-save of a previously saved query, or to access the | Cmd/Ctrl + S | | *Save File* | Click the *Save* icon to perform a quick-save of a previously saved query, or to access the | Cmd/Ctrl + S |
| | *Save* menu: | | | | *Save* menu: | |

View File

@ -380,6 +380,12 @@ class Filemanager():
True, True,
gettext("Select Folder") gettext("Select Folder")
), ),
'open_file': (
['open_file'],
True,
False,
gettext("Select File")
),
'create_file': ( 'create_file': (
['select_file', 'rename', 'create'], ['select_file', 'rename', 'create'],
True, True,

View File

@ -61,7 +61,9 @@ export default class FileManagerModule {
if(!title) { if(!title) {
if(params.dialog_type == 'create_file') { if(params.dialog_type == 'create_file') {
title = gettext('Save File'); title = gettext('Save File');
} else if(params.dialog_type == 'select_file') { } else if(params.dialog_type == 'open_file'){
title = gettext('Open File');
}else if(params.dialog_type == 'select_file') {
title = gettext('Select File'); title = gettext('Select File');
} else { } else {
title = gettext('Storage Manager'); title = gettext('Storage Manager');

View File

@ -645,7 +645,8 @@ export default function FileManager({params, closeModal, onOK, onCancel, sharedS
} else if(selectedRowIdx.current >= 0 && row) { } else if(selectedRowIdx.current >= 0 && row) {
let selectedfileType = row?.file_type; let selectedfileType = row?.file_type;
if(((selectedfileType == 'dir' || selectedfileType == 'drive') && fmUtilsObj.hasCapability('select_folder')) if(((selectedfileType == 'dir' || selectedfileType == 'drive') && fmUtilsObj.hasCapability('select_folder'))
|| (selectedfileType != 'dir' && selectedfileType != 'drive' && fmUtilsObj.hasCapability('select_file'))) { || (selectedfileType != 'dir' && selectedfileType != 'drive' && fmUtilsObj.hasCapability('select_file'))
|| (selectedfileType != 'dir' && selectedfileType != 'drive' && fmUtilsObj.hasCapability('open_file'))) {
disabled = false; disabled = false;
} }
} }
@ -695,6 +696,8 @@ export default function FileManager({params, closeModal, onOK, onCancel, sharedS
okBtnText = gettext('Select'); okBtnText = gettext('Select');
if(params.dialog_type == 'create_file' || params.dialog_type == 'create_folder') { if(params.dialog_type == 'create_file' || params.dialog_type == 'create_folder') {
okBtnText = gettext('Create'); okBtnText = gettext('Create');
}else if(params.dialog_type == 'open_file'){
okBtnText = gettext('Open');
} }
} }
@ -862,4 +865,4 @@ FileManager.propTypes = {
onCancel: PropTypes.func, onCancel: PropTypes.func,
sharedStorages: PropTypes.array, sharedStorages: PropTypes.array,
restrictedSharedStorage: PropTypes.array, restrictedSharedStorage: PropTypes.array,
}; };

View File

@ -117,4 +117,4 @@ export const MSAzureIcon = ({style})=><ExternalIcon Icon={MsAzure} style={{heigh
MSAzureIcon.propTypes = {style: PropTypes.object}; MSAzureIcon.propTypes = {style: PropTypes.object};
export const SchemaDiffIcon = ({style})=><ExternalIcon Icon={SchemaDiffSvg} style={{height: '2rem', ...style}} data-label="SchemaDiffIcon" />; export const SchemaDiffIcon = ({style})=><ExternalIcon Icon={SchemaDiffSvg} style={{height: '2rem', ...style}} data-label="SchemaDiffIcon" />;
SchemaDiffIcon.propTypes = {style: PropTypes.object}; SchemaDiffIcon.propTypes = {style: PropTypes.object};

View File

@ -261,6 +261,7 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
} }
}, pollTime); }, pollTime);
let defaultLayout = { let defaultLayout = {
dockbox: { dockbox: {
mode: 'vertical', mode: 'vertical',
@ -378,6 +379,10 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
let msg = `${selectedConn['server_name']}/${selectedConn['database_name']} - Database connected`; let msg = `${selectedConn['server_name']}/${selectedConn['database_name']} - Database connected`;
pgAdmin.Browser.notifier.success(_.escape(msg)); pgAdmin.Browser.notifier.success(_.escape(msg));
} }
// Open the file if filename passed on the parameters.
if(qtState.params.fileName){
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.LOAD_FILE, params.fileName, params.storage);
}
}).catch((error)=>{ }).catch((error)=>{
if(error.response?.request?.responseText?.search('Ticket expired') !== -1) { if(error.response?.request?.responseText?.search('Ticket expired') !== -1) {
Kerberos.fetch_ticket() Kerberos.fetch_ticket()
@ -577,14 +582,20 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.EDITOR_LAST_FOCUS); eventBus.current.fireEvent(QUERY_TOOL_EVENTS.EDITOR_LAST_FOCUS);
}; };
const events = [ const events = [
[QUERY_TOOL_EVENTS.TRIGGER_LOAD_FILE, ()=>{ [QUERY_TOOL_EVENTS.TRIGGER_LOAD_FILE, (openInNewTab=false)=>{
let fileParams = { let fileParams = {
'supported_types': ['sql', '*'], // file types allowed 'supported_types': ['sql', '*'], // file types allowed
'dialog_type': 'select_file', // open select file dialog 'dialog_type': 'open_file', // open select file dialog
}; };
pgAdmin.Tools.FileManager.show(fileParams, (fileName, storage)=>{ if(openInNewTab){
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.LOAD_FILE, fileName, storage); pgAdmin.Tools.FileManager.show(fileParams, (fileName, storage)=>{
}, null, modal); onNewQueryToolClick(null, fileName, storage);
}, null, modal, openInNewTab);
}else{
pgAdmin.Tools.FileManager.show(fileParams,(fileName, storage)=>{
eventBus.current.fireEvent(QUERY_TOOL_EVENTS.LOAD_FILE, fileName, storage);
}, null, modal);
}
}], }],
[QUERY_TOOL_EVENTS.TRIGGER_SAVE_FILE, (isSaveAs=false)=>{ [QUERY_TOOL_EVENTS.TRIGGER_SAVE_FILE, (isSaveAs=false)=>{
if(!isSaveAs && qtState.current_file) { if(!isSaveAs && qtState.current_file) {
@ -783,8 +794,7 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
}); });
}, [qtState.preferences.browser, qtState.connection_list, qtState.params]); }, [qtState.preferences.browser, qtState.connection_list, qtState.params]);
const onNewQueryToolClick = (event, fileName, storage)=>{
const onNewQueryToolClick = ()=>{
const transId = commonUtils.getRandomInt(1, 9999999); const transId = commonUtils.getRandomInt(1, 9999999);
let selectedConn = _.find(qtState.connection_list, (c)=>c.is_selected); let selectedConn = _.find(qtState.connection_list, (c)=>c.is_selected);
let parentData = { let parentData = {
@ -807,6 +817,8 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
showQueryTool.launchQueryTool(pgWindow.pgAdmin.Tools.SQLEditor, transId, gridUrl, title, { showQueryTool.launchQueryTool(pgWindow.pgAdmin.Tools.SQLEditor, transId, gridUrl, title, {
user: selectedConn.user, user: selectedConn.user,
role: selectedConn.role, role: selectedConn.role,
fileName: fileName,
storage: storage
}); });
}; };
@ -982,6 +994,8 @@ QueryToolComponent.propTypes = {
server_name: PropTypes.string, server_name: PropTypes.string,
database_name: PropTypes.string, database_name: PropTypes.string,
layout: PropTypes.string, layout: PropTypes.string,
fileName: PropTypes.string,
storage: PropTypes.string,
}), }),
pgWindow: PropTypes.object.isRequired, pgWindow: PropTypes.object.isRequired,
pgAdmin: PropTypes.object.isRequired, pgAdmin: PropTypes.object.isRequired,

View File

@ -74,6 +74,7 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros, onAddT
const [checkedMenuItems, setCheckedMenuItems] = React.useState({}); const [checkedMenuItems, setCheckedMenuItems] = React.useState({});
/* Menu button refs */ /* Menu button refs */
const saveAsMenuRef = React.useRef(null); const saveAsMenuRef = React.useRef(null);
const openInNewTabMenuRef = React.useRef(null);
const editMenuRef = React.useRef(null); const editMenuRef = React.useRef(null);
const autoCommitMenuRef = React.useRef(null); const autoCommitMenuRef = React.useRef(null);
const explainMenuRef = React.useRef(null); const explainMenuRef = React.useRef(null);
@ -138,9 +139,9 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros, onAddT
const openFile = useCallback(()=>{ const openFile = useCallback(()=>{
confirmDiscard(()=>{ confirmDiscard(()=>{
eventBus.fireEvent(QUERY_TOOL_EVENTS.TRIGGER_LOAD_FILE); eventBus.fireEvent(QUERY_TOOL_EVENTS.TRIGGER_LOAD_FILE, Boolean(checkedMenuItems['open_in_new_tab']));
}, true); }, true);
}, [buttonsDisabled['save']]); }, [buttonsDisabled['save'], checkedMenuItems]);
const saveFile = useCallback((saveAs=false)=>{ const saveFile = useCallback((saveAs=false)=>{
eventBus.fireEvent(QUERY_TOOL_EVENTS.TRIGGER_SAVE_FILE, saveAs); eventBus.fireEvent(QUERY_TOOL_EVENTS.TRIGGER_SAVE_FILE, saveAs);
@ -337,6 +338,7 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros, onAddT
explain_summary: queryToolPref.explain_summary, explain_summary: queryToolPref.explain_summary,
explain_settings: queryToolPref.explain_settings, explain_settings: queryToolPref.explain_settings,
explain_wal: queryToolPref.explain_wal, explain_wal: queryToolPref.explain_wal,
open_in_new_tab: queryToolPref.open_in_new_tab,
}); });
} }
} }
@ -501,6 +503,11 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros, onAddT
<PgButtonGroup size="small"> <PgButtonGroup size="small">
<PgIconButton title={gettext('Open File')} icon={<FolderRoundedIcon />} disabled={!queryToolCtx.params.is_query_tool} <PgIconButton title={gettext('Open File')} icon={<FolderRoundedIcon />} disabled={!queryToolCtx.params.is_query_tool}
shortcut={queryToolPref.btn_open_file} onClick={openFile} /> shortcut={queryToolPref.btn_open_file} onClick={openFile} />
<PgIconButton title={gettext('Open in a new tab')} icon={<KeyboardArrowDownIcon />} splitButton disabled={!queryToolCtx.params.is_query_tool}
name="menu-openfileintab" ref={openInNewTabMenuRef} onClick={toggleMenu}
/>
</PgButtonGroup>
<PgButtonGroup size="small">
<PgIconButton title={gettext('Save File')} icon={<SaveRoundedIcon />} <PgIconButton title={gettext('Save File')} icon={<SaveRoundedIcon />}
shortcut={queryToolPref.btn_save_file} disabled={buttonsDisabled['save'] || !queryToolCtx.params.is_query_tool} shortcut={queryToolPref.btn_save_file} disabled={buttonsDisabled['save'] || !queryToolCtx.params.is_query_tool}
onClick={()=>{saveFile(false);}} /> onClick={()=>{saveFile(false);}} />
@ -562,13 +569,22 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros, onAddT
<PgIconButton title={gettext('Help')} icon={<HelpIcon />} onClick={onHelpClick} /> <PgIconButton title={gettext('Help')} icon={<HelpIcon />} onClick={onHelpClick} />
</PgButtonGroup> </PgButtonGroup>
</StyledBox> </StyledBox>
<PgMenu
anchorRef={openInNewTabMenuRef}
open={openMenuName=='menu-openfileintab'}
onClose={onMenuClose}
label={gettext('Open file Menu')}
>
<PgMenuItem hasCheck value="open_in_new_tab" checked={checkedMenuItems['open_in_new_tab']}
onClick={checkMenuClick}>{gettext('Open in a new tab?')}</PgMenuItem>
</PgMenu>
<PgMenu <PgMenu
anchorRef={saveAsMenuRef} anchorRef={saveAsMenuRef}
open={openMenuName=='menu-saveas'} open={openMenuName=='menu-saveas'}
onClose={onMenuClose} onClose={onMenuClose}
label={gettext('File Menu')} label={gettext('Save As')}
> >
<PgMenuItem onClick={()=>{saveFile(true);}}>{gettext('Save as')}</PgMenuItem> <PgMenuItem onClick={()=>{saveFile(true);}}>{gettext('Save As')}</PgMenuItem>
</PgMenu> </PgMenu>
<PgMenu <PgMenu
anchorRef={editMenuRef} anchorRef={editMenuRef}

View File

@ -133,6 +133,16 @@ def register_query_tool_preferences(self):
) )
) )
self.open_file_in_new_tab = self.preference.register(
'Options', 'open_in_new_tab',
gettext("Open the file in a new tab?"), 'boolean',
True,
category_label=PREF_LABEL_OPTIONS,
help_str=gettext(
'Specifies whether or not to open the file in a new tab.'
)
)
self.view_edit_promotion_warning = self.preference.register( self.view_edit_promotion_warning = self.preference.register(
'Options', 'view_edit_promotion_warning', 'Options', 'view_edit_promotion_warning',
gettext("Show View/Edit Data Promotion Warning?"), gettext("Show View/Edit Data Promotion Warning?"),