Ensure that modal dialogs are not triggered more than once to avoid duplicates. #8316
parent
f25cde8c5f
commit
b2669930f5
|
|
@ -31,6 +31,9 @@ let startPageUrl = null;
|
|||
let serverCheckUrl = null;
|
||||
let pgAdminMainScreen = null;
|
||||
|
||||
let configureWindow = null,
|
||||
viewLogWindow = null;
|
||||
|
||||
let serverPort = 5050;
|
||||
let appStartTime = (new Date()).getTime();
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
|
@ -77,7 +80,8 @@ contextMenu({
|
|||
Menu.setApplicationMenu(null);
|
||||
|
||||
function openConfigure() {
|
||||
const win = new BrowserWindow({
|
||||
if (configureWindow === null){
|
||||
configureWindow = new BrowserWindow({
|
||||
show: false,
|
||||
width: 600,
|
||||
height: 580,
|
||||
|
|
@ -88,11 +92,12 @@ function openConfigure() {
|
|||
preload: path.join(__dirname, 'other_preload.js'),
|
||||
},
|
||||
});
|
||||
win.loadFile('./src/html/configure.html');
|
||||
win.once('ready-to-show', ()=>{
|
||||
win.show();
|
||||
configureWindow.loadFile('./src/html/configure.html');
|
||||
configureWindow.once('ready-to-show', ()=>{
|
||||
configureWindow.show();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showErrorDialog(intervalID) {
|
||||
if(!splashWindow.isVisible()) {
|
||||
|
|
@ -304,21 +309,23 @@ function launchPgAdminWindow() {
|
|||
|
||||
setupMenu(pgAdminMainScreen, {
|
||||
'view_logs': ()=>{
|
||||
const win = new BrowserWindow({
|
||||
show: false,
|
||||
width: 800,
|
||||
height: 460,
|
||||
position: 'center',
|
||||
resizable: false,
|
||||
icon: '../../assets/pgAdmin4.png',
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'other_preload.js'),
|
||||
},
|
||||
});
|
||||
win.loadFile('./src/html/view_log.html');
|
||||
win.once('ready-to-show', ()=>{
|
||||
win.show();
|
||||
});
|
||||
if(viewLogWindow === null){
|
||||
viewLogWindow = new BrowserWindow({
|
||||
show: false,
|
||||
width: 800,
|
||||
height: 460,
|
||||
position: 'center',
|
||||
resizable: false,
|
||||
icon: '../../assets/pgAdmin4.png',
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'other_preload.js'),
|
||||
},
|
||||
});
|
||||
viewLogWindow.loadFile('./src/html/view_log.html');
|
||||
viewLogWindow.once('ready-to-show', ()=>{
|
||||
viewLogWindow.show();
|
||||
});
|
||||
}
|
||||
},
|
||||
'configure': openConfigure,
|
||||
'reloadApp': reloadApp,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class About {
|
|||
pgAdmin.Browser.notifier.showModal(gettext('About %s', pgAdmin.Browser.utils.app_name), () => {
|
||||
return <AboutComponent />;
|
||||
}, { isFullScreen: false, isResizeable: true, showFullScreen: true,
|
||||
isFullWidth: true, dialogWidth: dlgWidth, dialogHeight: dlgHeight, minHeight: dlgHeight
|
||||
isFullWidth: true, dialogWidth: dlgWidth, dialogHeight: dlgHeight, minHeight: dlgHeight, id:'id-about'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ export const BROWSER_PANELS = {
|
|||
WELCOME_PSQL_TOOL: 'id-welcome-psql'
|
||||
};
|
||||
|
||||
|
||||
export const WORKSPACES = {
|
||||
DEFAULT: 'default_workspace',
|
||||
QUERY_TOOL: 'query_tool_workspace',
|
||||
|
|
|
|||
|
|
@ -689,7 +689,6 @@ export default function PreferencesComponent({ ...props }) {
|
|||
const text = `${gettext('All preferences will be reset to their default values.')}<br><br>${gettext('Do you want to proceed?')}<br><br>
|
||||
${gettext('Note:')}<br> <ul style="padding-left:20px"><li style="list-style-type:disc">${gettext('The object explorer tree will be refreshed automatically to reflect the changes.')}</li>
|
||||
<li style="list-style-type:disc">${gettext('If the application language changes, a reload of the application will be required. You can choose to reload later at your convenience.')}</li></ul>`;
|
||||
|
||||
pgAdmin.Browser.notifier.showModal(
|
||||
gettext('Reset all preferences'),
|
||||
(closeModal)=>{
|
||||
|
|
@ -710,7 +709,7 @@ ${gettext('Note:')}<br> <ul style="padding-left:20px"><li style="list-style-type
|
|||
</StyledBox>
|
||||
);
|
||||
},
|
||||
{ isFullScreen: false, isResizeable: false, showFullScreen: false, isFullWidth: false, showTitle: true},
|
||||
{ isFullScreen: false, isResizeable: false, showFullScreen: false, isFullWidth: false, showTitle: true, id: 'id-reset-preferences'},
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,6 @@ export default class Preferences {
|
|||
|
||||
// This is a callback function to show preferences.
|
||||
show() {
|
||||
|
||||
// Render Preferences component
|
||||
pgAdmin.Browser.notifier.showModal(gettext('Preferences'), (closeModal) => {
|
||||
return <PreferencesComponent
|
||||
|
|
@ -56,6 +55,6 @@ export default class Preferences {
|
|||
// Render preferences tree component
|
||||
return <PreferencesTree pgBrowser={this.pgBrowser} data={prefTreeData} />;
|
||||
}} closeModal={closeModal} />;
|
||||
}, { isFullScreen: false, isResizeable: true, showFullScreen: true, isFullWidth: true, dialogWidth: 900, dialogHeight: 550 });
|
||||
}, { isFullScreen: false, isResizeable: true, showFullScreen: true, isFullWidth: true, dialogWidth: 900, dialogHeight: 550, id: 'id-preferences' });
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,7 +151,6 @@ export default function BrowserComponent({pgAdmin}) {
|
|||
let { name: browser } = useMemo(()=>getBrowser(), []);
|
||||
const [uiReady, setUiReady] = useState(false);
|
||||
const confirmOnClose = getPreferencesForModule('browser').confirm_on_refresh_close;
|
||||
|
||||
useBeforeUnload({
|
||||
enabled: confirmOnClose,
|
||||
beforeClose: (forceClose)=>{
|
||||
|
|
@ -159,7 +158,11 @@ export default function BrowserComponent({pgAdmin}) {
|
|||
gettext('Quit pgAdmin 4'),
|
||||
gettext('Are you sure you want to quit the application?'),
|
||||
function() { forceClose(); },
|
||||
function() { return true;},
|
||||
function() { return true; },
|
||||
gettext('Yes'),
|
||||
gettext('No'),
|
||||
'default',
|
||||
'id-app-quit'
|
||||
);
|
||||
},
|
||||
isNewTab: true,
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ export function showServerPassword() {
|
|||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}, {id: 'id-connect-server'});
|
||||
}
|
||||
|
||||
function masterPassCallbacks(masterpass_callback_queue) {
|
||||
|
|
@ -176,7 +176,7 @@ export function showMasterPassword(isPWDPresent, errmsg, masterpass_callback_que
|
|||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
}, {id: 'id-master-password'});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -275,7 +275,7 @@ export function showChangeUserPassword(url) {
|
|||
/>;
|
||||
},
|
||||
{ isFullScreen: false, isResizeable: true, showFullScreen: false, isFullWidth: true,
|
||||
dialogWidth: pgAdmin.Browser.stdW.md, dialogHeight: pgAdmin.Browser.stdH.md});
|
||||
dialogWidth: pgAdmin.Browser.stdW.md, dialogHeight: pgAdmin.Browser.stdH.md, id: 'id-change-password'});
|
||||
}
|
||||
|
||||
export function showNamedRestorePoint() {
|
||||
|
|
@ -351,7 +351,7 @@ export function showChangeOwnership() {
|
|||
/>;
|
||||
},
|
||||
{ isFullScreen: false, isResizeable: true, showFullScreen: true, isFullWidth: true,
|
||||
dialogWidth: pgAdmin.Browser.stdW.md, dialogHeight: pgAdmin.Browser.stdH.md});
|
||||
dialogWidth: pgAdmin.Browser.stdW.md, dialogHeight: pgAdmin.Browser.stdH.md, id: 'id-change-owner' });
|
||||
}
|
||||
|
||||
export function showUrlDialog() {
|
||||
|
|
@ -388,6 +388,6 @@ export function showQuickSearch() {
|
|||
pgAdmin.Browser.notifier.showModal(gettext('Quick Search'), (closeModal) => {
|
||||
return <QuickSearch closeModal={closeModal}/>;
|
||||
},
|
||||
{ isFullScreen: false, isResizeable: false, showFullScreen: false, isFullWidth: false, showTitle: false}
|
||||
{ isFullScreen: false, isResizeable: false, showFullScreen: false, isFullWidth: false, showTitle: false, id: 'id-quick-search'}
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ function alert(title, text, onOkClick, okLabel = gettext('OK')) {
|
|||
});
|
||||
}
|
||||
|
||||
function confirm(title, text, onOkClick, onCancelClick, okLabel = gettext('Yes'), cancelLabel = gettext('No'), okIcon = 'default') {
|
||||
function confirm(title, text, onOkClick, onCancelClick, okLabel = gettext('Yes'), cancelLabel = gettext('No'), okIcon = 'default', modalId=null) {
|
||||
// bind the modal provider before calling
|
||||
this.showModal(title, (closeModal) => {
|
||||
const onCancelClickClose = () => {
|
||||
|
|
@ -98,7 +98,7 @@ function confirm(title, text, onOkClick, onCancelClick, okLabel = gettext('Yes')
|
|||
return (
|
||||
<AlertContent text={text} confirm onOkClick={onOkClickClose} onCancelClick={onCancelClickClose} okLabel={okLabel} cancelLabel={cancelLabel} okIcon={okIcon}/>
|
||||
);
|
||||
});
|
||||
}, {modalId: modalId});
|
||||
}
|
||||
|
||||
function confirmDelete(title, text, onDeleteClick, onCancelClick, deleteLabel = gettext('Delete'), cancelLabel = gettext('Cancel')) {
|
||||
|
|
@ -127,16 +127,23 @@ function confirmDelete(title, text, onDeleteClick, onCancelClick, deleteLabel =
|
|||
|
||||
export default function ModalProvider({ children }) {
|
||||
const [modals, setModals] = React.useState([]);
|
||||
|
||||
const showModal = (title, content, modalOptions) => {
|
||||
let id = getEpoch().toString() + crypto.getRandomValues(new Uint8Array(4));
|
||||
setModals((prev) => [...prev, {
|
||||
id: id,
|
||||
title: title,
|
||||
content: content,
|
||||
...modalOptions,
|
||||
}]);
|
||||
if(modalOptions?.id){
|
||||
id = modalOptions.id;
|
||||
}
|
||||
setModals((prev) => {
|
||||
if(prev?.find(modal=> modal.id === modalOptions?.id)){
|
||||
return prev;
|
||||
}
|
||||
return [...prev, {
|
||||
id: id,
|
||||
title: title,
|
||||
content: content,
|
||||
...modalOptions,
|
||||
}];});
|
||||
};
|
||||
|
||||
const closeModal = (id) => {
|
||||
setModals((prev) => {
|
||||
return prev.filter((o) => o.id != id);
|
||||
|
|
|
|||
|
|
@ -175,10 +175,10 @@ class Notifier {
|
|||
this.modal.alert(title, text, onOkClick, okLabel);
|
||||
}
|
||||
|
||||
confirm(title, text, onOkClick, onCancelClick, okLabel=gettext('Yes'), cancelLabel=gettext('No'), okIcon='default') {
|
||||
confirm(title, text, onOkClick, onCancelClick, okLabel=gettext('Yes'), cancelLabel=gettext('No'), okIcon='default', modalId=null) {
|
||||
/* Use this if you want to use pgAdmin global notifier.
|
||||
Or else, if you want to use modal inside iframe only then use ModalProvider eg- query tool */
|
||||
this.modal.confirm(title, text, onOkClick, onCancelClick, okLabel, cancelLabel, okIcon);
|
||||
this.modal.confirm(title, text, onOkClick, onCancelClick, okLabel, cancelLabel, okIcon, modalId);
|
||||
}
|
||||
|
||||
confirmDelete(title, text, onDeleteClick, onCancelClick, okLabel = gettext('Delete'), cancelLabel = gettext('Cancel')){
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import React from 'react';
|
|||
|
||||
import gettext from 'sources/gettext';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
|
||||
import DebuggerArgumentComponent from './components/DebuggerArgumentComponent';
|
||||
|
||||
export default class FunctionArguments {
|
||||
|
|
@ -28,6 +27,6 @@ export default class FunctionArguments {
|
|||
// Render Debugger argument component
|
||||
pgAdmin.Browser.notifier.showModal(gettext('Debugger'), (closeModal) => {
|
||||
return <DebuggerArgumentComponent closeModal={closeModal} debuggerInfo={debugInfo} restartDebug={restartDebug} isEdbProc={isEdbProc} transId={transId} pgTreeInfo={treeInfo} pgData={d}></DebuggerArgumentComponent>;
|
||||
}, { isFullScreen: false, isResizeable: true, showFullScreen: true, isFullWidth: true, dialogWidth: pgAdmin.Browser.stdW.md, dialogHeight: pgAdmin.Browser.stdH.md });
|
||||
}, { isFullScreen: false, isResizeable: true, showFullScreen: true, isFullWidth: true, dialogWidth: pgAdmin.Browser.stdW.md, dialogHeight: pgAdmin.Browser.stdH.md, id:'id-debugger'});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -378,7 +378,7 @@ export default class ERDTool extends React.Component {
|
|||
bodyObj.onSaveDiagram(false, true);
|
||||
}}
|
||||
/>
|
||||
));
|
||||
), {id: 'id-erd-close-confirmation'});
|
||||
return false;
|
||||
} else {
|
||||
this.forceClose();
|
||||
|
|
|
|||
|
|
@ -100,6 +100,10 @@ export const CONNECTION_STATUS_MESSAGE = {
|
|||
[CONNECTION_STATUS.TRANSACTION_STATUS_UNKNOWN]: gettext('The connection with the server is bad.')
|
||||
};
|
||||
|
||||
export const MODAL_DIALOGS = {
|
||||
QT_CONFIRMATIONS: 'id-qt-close-confirmation',
|
||||
};
|
||||
|
||||
export const PANELS = {
|
||||
QUERY: 'id-query',
|
||||
MESSAGES: 'id-messages',
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import CustomPropTypes from '../../../../../../static/js/custom_prop_types';
|
|||
import ConfirmTransactionContent from '../dialogs/ConfirmTransactionContent';
|
||||
import { LayoutDocker } from '../../../../../../static/js/helpers/Layout';
|
||||
import CloseRunningDialog from '../dialogs/CloseRunningDialog';
|
||||
import { MODAL_DIALOGS } from '../QueryToolConstants';
|
||||
|
||||
const StyledBox = styled(Box)(({theme}) => ({
|
||||
padding: '2px 4px',
|
||||
|
|
@ -56,6 +57,7 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros, onAddT
|
|||
const eventBus = useContext(QueryToolEventsContext);
|
||||
const queryToolCtx = useContext(QueryToolContext);
|
||||
const queryToolConnCtx = useContext(QueryToolConnectionContext);
|
||||
const modalId = MODAL_DIALOGS.QT_CONFIRMATIONS;
|
||||
|
||||
const [highlightFilter, setHighlightFilter] = useState(false);
|
||||
const [limit, setLimit] = useState('-1');
|
||||
|
|
@ -237,7 +239,7 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros, onAddT
|
|||
eventBus.fireEvent(QUERY_TOOL_EVENTS.FORCE_CLOSE_PANEL);
|
||||
}}
|
||||
/>
|
||||
));
|
||||
), {id: modalId});
|
||||
return;
|
||||
} else {
|
||||
eventBus.fireEvent(QUERY_TOOL_EVENTS.FORCE_CLOSE_PANEL);
|
||||
|
|
@ -258,7 +260,7 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros, onAddT
|
|||
onCommitClick();
|
||||
}}
|
||||
/>
|
||||
));
|
||||
), {id: modalId});
|
||||
};
|
||||
useEffect(()=>{
|
||||
if(isInTxn()) {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import ConfirmExecuteQueryContent from '../dialogs/ConfirmExecuteQueryContent';
|
|||
import usePreferences from '../../../../../../preferences/static/js/store';
|
||||
import { getTitle } from '../../sqleditor_title';
|
||||
import PropTypes from 'prop-types';
|
||||
import { MODAL_DIALOGS } from '../QueryToolConstants';
|
||||
|
||||
|
||||
async function registerAutocomplete(editor, api, transId) {
|
||||
|
|
@ -65,6 +66,7 @@ export default function Query({onTextSelect, setQtStatePartial}) {
|
|||
const pgAdmin = usePgAdmin();
|
||||
const preferencesStore = usePreferences();
|
||||
const queryToolPref = queryToolCtx.preferences.sqleditor;
|
||||
const modalId = MODAL_DIALOGS.QT_CONFIRMATIONS;
|
||||
const highlightError = (cmObj, {errormsg: result, data}, executeCursor)=>{
|
||||
let errorLineNo = 0,
|
||||
startMarker = 0,
|
||||
|
|
@ -343,7 +345,7 @@ export default function Query({onTextSelect, setQtStatePartial}) {
|
|||
eventBus.fireEvent(QUERY_TOOL_EVENTS.TRIGGER_SAVE_FILE);
|
||||
}}
|
||||
/>
|
||||
));
|
||||
), {id:modalId});
|
||||
};
|
||||
|
||||
const formatSQL = ()=>{
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import { GraphVisualiser } from './GraphVisualiser';
|
|||
import { usePgAdmin } from '../../../../../../static/js/PgAdminProvider';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
import ConnectServerContent from '../../../../../../static/js/Dialogs/ConnectServerContent';
|
||||
import { MODAL_DIALOGS } from '../QueryToolConstants';
|
||||
|
||||
const StyledBox = styled(Box)(({theme}) => ({
|
||||
display: 'flex',
|
||||
|
|
@ -832,6 +833,7 @@ export function ResultSet() {
|
|||
const [selectedColumns, setSelectedColumns] = useState(new Set());
|
||||
// NONE - no select, PAGE - show select all, ALL - select all.
|
||||
const [allRowsSelect, setAllRowsSelect] = useState('NONE');
|
||||
const modalId = MODAL_DIALOGS.QT_CONFIRMATIONS;
|
||||
|
||||
// We'll use this track if any changes were saved.
|
||||
// It will help to decide whether results refresh is required or not on page change.
|
||||
|
|
@ -1145,7 +1147,7 @@ export function ResultSet() {
|
|||
eventBus.fireEvent(QUERY_TOOL_EVENTS.WARN_SAVE_TEXT_CLOSE);
|
||||
}}
|
||||
/>
|
||||
));
|
||||
), {modalId:modalId});
|
||||
};
|
||||
useEffect(()=>{
|
||||
let isDirty = _.size(dataChangeStore.updated) || _.size(dataChangeStore.added) || _.size(dataChangeStore.deleted);
|
||||
|
|
|
|||
|
|
@ -457,12 +457,11 @@ UserManagementDialog.propTypes = {
|
|||
|
||||
export function showUserManagement() {
|
||||
const title = gettext('User Management');
|
||||
|
||||
pgAdmin.Browser.notifier.showModal(title, (onClose) => {
|
||||
return <UserManagementDialog
|
||||
onClose={()=>{onClose();}}
|
||||
/>;
|
||||
},
|
||||
{ isFullScreen: false, isResizeable: true, showFullScreen: false, isFullWidth: true,
|
||||
dialogWidth: pgAdmin.Browser.stdW.lg, dialogHeight: pgAdmin.Browser.stdH.md});
|
||||
dialogWidth: pgAdmin.Browser.stdW.lg, dialogHeight: pgAdmin.Browser.stdH.md, id: 'id-user-management'});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue