diff --git a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js index 7b80a118b..b74483268 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js +++ b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js @@ -270,6 +270,8 @@ define('pgadmin.node.database', [ t.deselect(item); }, function() { return true;}, + gettext('Disconnect'), + gettext('Cancel') ); } @@ -557,11 +559,13 @@ define('pgadmin.node.database', [ if (notify) { pgAdmin.Browser.notifier.confirm( gettext('Disconnect from database'), - gettext('Are you sure you want to disconnect from database - %s?', d.label), + gettext('Are you sure you want to disconnect from the database - %s?', d.label), function() { disconnect(); }, - function() { return true; } + function() { return true; }, + gettext('Disconnect'), + gettext('Cancel') ); } else { disconnect(); diff --git a/web/pgadmin/browser/server_groups/servers/static/js/server.js b/web/pgadmin/browser/server_groups/servers/static/js/server.js index 891b95865..405308969 100644 --- a/web/pgadmin/browser/server_groups/servers/static/js/server.js +++ b/web/pgadmin/browser/server_groups/servers/static/js/server.js @@ -259,6 +259,8 @@ define('pgadmin.node.server', [ }, 100); }, function() { return true;}, + gettext('Disconnect'), + gettext('Cancel'), ); } return false; @@ -862,9 +864,11 @@ define('pgadmin.node.server', [ if (notify) { pgAdmin.Browser.notifier.confirm( gettext('Disconnect from server'), - gettext('Are you sure you want to disconnect from the server %s?', label), + gettext('Are you sure you want to disconnect from the server %s?', label), function() { disconnect(); }, function() { return true;}, + gettext('Disconnect'), + gettext('Cancel') ); } else { disconnect(); diff --git a/web/pgadmin/browser/static/js/node.js b/web/pgadmin/browser/static/js/node.js index 41ce77089..a438dd6a0 100644 --- a/web/pgadmin/browser/static/js/node.js +++ b/web/pgadmin/browser/static/js/node.js @@ -525,7 +525,7 @@ define('pgadmin.browser.node', [ title = gettext('Delete FORCE %s?', obj.label); } else if (input.url == 'delete') { - msg = gettext('Are you sure you want to delete %s "%s" and all the objects that depend on it?', + msg = gettext('Are you sure you want to delete the %s "%s" and all the objects that depend on it?', obj.label.toLowerCase(), d.label); title = gettext('Delete CASCADE %s?', obj.label); @@ -539,10 +539,10 @@ define('pgadmin.browser.node', [ } } else { if (obj.dropAsRemove) { - msg = gettext('Are you sure you want to remove %s "%s"?', obj.label.toLowerCase(), d.label); + msg = gettext('Are you sure you want to remove the %s "%s"?', obj.label.toLowerCase(), d.label); title = gettext('Remove %s?', obj.label); } else { - msg = gettext('Are you sure you want to delete %s "%s"?', obj.label.toLowerCase(), d.label); + msg = gettext('Are you sure you want to delete the %s "%s"?', obj.label.toLowerCase(), d.label); title = gettext('Delete %s?', obj.label); } @@ -555,7 +555,7 @@ define('pgadmin.browser.node', [ return; } } - pgAdmin.Browser.notifier.confirm(title, msg, + pgAdmin.Browser.notifier.confirmDelete(title, msg, function() { getApiInstance().delete( obj.generate_url(i, input.url, d, true), @@ -592,7 +592,10 @@ define('pgadmin.browser.node', [ } pgAdmin.Browser.notifier.alert(gettext('Error dropping/removing %s: "%s"', obj.label, objName), errmsg); }); - } + }, + () => {}, + gettext('Delete'), + gettext('Cancel'), ); }, // Callback for creating script(s) & opening them in Query editor diff --git a/web/pgadmin/misc/properties/CollectionNodeProperties.jsx b/web/pgadmin/misc/properties/CollectionNodeProperties.jsx index 862d36b20..5adfecb06 100644 --- a/web/pgadmin/misc/properties/CollectionNodeProperties.jsx +++ b/web/pgadmin/misc/properties/CollectionNodeProperties.jsx @@ -197,7 +197,7 @@ export default function CollectionNodeProperties({ }; if (confirm) { - pgAdmin.Browser.notifier.confirm(title, msg, dropNodeProperties, null); + pgAdmin.Browser.notifier.confirmDelete(title, msg, dropNodeProperties, null, gettext('Delete'), gettext('Cancel')); } else { dropNodeProperties(); } diff --git a/web/pgadmin/static/js/Theme/dark.js b/web/pgadmin/static/js/Theme/dark.js index b13adbde7..d6d2085e3 100644 --- a/web/pgadmin/static/js/Theme/dark.js +++ b/web/pgadmin/static/js/Theme/dark.js @@ -44,6 +44,8 @@ export default function(basicSettings) { light: '#1e1e1e', contrastText: '#fff', lighter: '#1e1e1e', + hoverMain: darken('#da6758', 0.25), + hoverBorderColor: darken('#da6758', 0.25), }, warning: { main: '#eea236', diff --git a/web/pgadmin/static/js/Theme/high_contrast.js b/web/pgadmin/static/js/Theme/high_contrast.js index c35932d9d..9577c3bf6 100644 --- a/web/pgadmin/static/js/Theme/high_contrast.js +++ b/web/pgadmin/static/js/Theme/high_contrast.js @@ -42,6 +42,8 @@ export default function(basicSettings) { main: '#EE7A55', light: '#010B15', contrastText: '#010B15', + hoverMain: '#fff', + hoverBorderColor: '#fff', }, warning: { main: '#F4D35E', diff --git a/web/pgadmin/static/js/Theme/light.js b/web/pgadmin/static/js/Theme/light.js index fcd0db3a8..d1f57ffda 100644 --- a/web/pgadmin/static/js/Theme/light.js +++ b/web/pgadmin/static/js/Theme/light.js @@ -42,6 +42,8 @@ export default function(basicSettings) { main: '#CC0000', light: '#FAECEC', contrastText: '#fff', + hoverMain: darken('#CC0000', 0.25), + hoverBorderColor: darken('#CC0000', 0.25), }, warning: { main: '#eea236', diff --git a/web/pgadmin/static/js/components/Buttons.jsx b/web/pgadmin/static/js/components/Buttons.jsx index 2b3bec24f..fbd5441b8 100644 --- a/web/pgadmin/static/js/components/Buttons.jsx +++ b/web/pgadmin/static/js/components/Buttons.jsx @@ -15,7 +15,7 @@ import ShortcutTitle from './ShortcutTitle'; import { styled } from '@mui/material/styles'; -const StyledButton = styled(Button)(({theme}) => ({ +const StyledButton = styled(Button)(({theme, color}) => ({ '&.Buttons-primaryButton': { border: '1px solid '+theme.palette.primary.main, '&.Mui-disabled': { @@ -37,18 +37,19 @@ const StyledButton = styled(Button)(({theme}) => ({ } }, '&.Buttons-defaultButton': { - backgroundColor: theme.palette.default.main, - color: theme.palette.default.contrastText, - border: '1px solid '+theme.palette.default.borderColor, + // Use the color prop to determine the background color and text color. + backgroundColor: theme.palette[color]?.main ?? theme.palette.default.main, + border: '1px solid '+ theme.palette.default.borderColor, + color: theme.palette[color]?.contrastText ?? theme.palette.default.contrastText, whiteSpace: 'nowrap', '&.Mui-disabled': { color: [theme.palette.default.disabledContrastText, '!important'], borderColor: theme.palette.default.disabledBorderColor }, '&:hover': { - backgroundColor: theme.palette.default.hoverMain, - color: theme.palette.default.hoverContrastText, - borderColor: theme.palette.default.hoverBorderColor, + backgroundColor: theme.palette[color]?.hoverMain ?? theme.palette.default.hoverMain, + color: theme.palette[color]?.contrastText ?? theme.palette.default.hoverContrastText, + borderColor: theme.palette[color]?.hoverBorderColor ?? theme.palette.default.hoverBorderColor, }, '&.Buttons-noBorder': { border: 0, @@ -143,16 +144,19 @@ PrimaryButton.propTypes = { /* pgAdmin default button */ export const DefaultButton = forwardRef((props, ref)=>{ - let {children, className, size, noBorder, ...otherProps} = props; + let {children, className, size, noBorder, color, ...otherProps} = props; + let variant = 'outlined'; let allClassName = ['Buttons-defaultButton', className]; if(size == 'xs') { size = undefined; allClassName.push('Buttons-xsButton'); + } else if(color !== 'default'){ + variant='contained'; } noBorder && allClassName.push('Buttons-noBorder'); const dataLabel = typeof(children) == 'string' ? children : undefined; return ( - {children} + {children} ); }); DefaultButton.displayName = 'DefaultButton'; @@ -161,6 +165,7 @@ DefaultButton.propTypes = { noBorder: PropTypes.bool, children: CustomPropTypes.children, className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), + color: PropTypes.string, }; diff --git a/web/pgadmin/static/js/helpers/ModalProvider.jsx b/web/pgadmin/static/js/helpers/ModalProvider.jsx index eff6eb733..09c41a308 100644 --- a/web/pgadmin/static/js/helpers/ModalProvider.jsx +++ b/web/pgadmin/static/js/helpers/ModalProvider.jsx @@ -44,11 +44,11 @@ export function useModal() { function renderExtraButtons(button) { switch(button.type) { case 'primary': - return {button.label}; + return {button.label}; case 'default': - return {button.label}; + return {button.label}; default: - return {button.label}; + return {button.label}; }; } @@ -58,13 +58,13 @@ function AlertContent({ text, confirm, okLabel = gettext('OK'), cancelLabel = ge {typeof (text) == 'string' ? HTMLReactParser(text) : text} {confirm && - } onClick={onCancelClick} >{cancelLabel} + } onClick={onCancelClick} autoFocus={true}>{cancelLabel} } { extraButtons?.length ? extraButtons.map(button=>renderExtraButtons(button)) : - } onClick={onOkClick} autoFocus={true} >{okLabel} + } onClick={onOkClick}>{okLabel} } @@ -100,17 +100,17 @@ function confirm(title, text, onOkClick, onCancelClick, okLabel = gettext('Yes') onCancelClick?.(); closeModal(); }; + const onOkClickClose = () => { onOkClick?.(); closeModal(); }; - const extraButtons = extras?.(closeModal); + const extraButtons = extras?.(closeModal); return ( ); }); } - export default function ModalProvider({ children }) { const [modals, setModals] = React.useState([]); diff --git a/web/pgadmin/static/js/helpers/Notifier.jsx b/web/pgadmin/static/js/helpers/Notifier.jsx index 0839708be..9c7a83031 100644 --- a/web/pgadmin/static/js/helpers/Notifier.jsx +++ b/web/pgadmin/static/js/helpers/Notifier.jsx @@ -181,6 +181,25 @@ class Notifier { this.modal.confirm(title, text, onOkClick, onCancelClick, okLabel, cancelLabel, extras); } + confirmDelete(title, text, onOkClick, onCancelClick,okLabel = gettext('Yes'), cancelLabel = gettext('No')){ + + const extraButtons = (closeModal) => { + return [ + { + type: 'default', + icon: , + label: okLabel, + onClick: ()=>{ + onOkClick(); + closeModal(); + }, + color: 'error', + }, + ]; + }; + this.modal.confirm(title, text, onOkClick, onCancelClick, okLabel, cancelLabel, extraButtons); + } + showModal(title, content, modalOptions) { this.modal.showModal(title, content, modalOptions); } diff --git a/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx b/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx index c0b40a4ce..f2e3b7ba7 100644 --- a/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx +++ b/web/pgadmin/tools/erd/static/js/erd_tool/components/ERDTool.jsx @@ -499,7 +499,7 @@ export default class ERDTool extends React.Component { } onDeleteNode() { - pgAdmin.Browser.notifier.confirm( + pgAdmin.Browser.notifier.confirmDelete( gettext('Delete ?'), gettext('You have selected %s tables and %s links.', this.diagram.getSelectedNodes().length, this.diagram.getSelectedLinks().length) + '
' + gettext('Are you sure you want to delete ?'), @@ -516,7 +516,9 @@ export default class ERDTool extends React.Component { } this.diagram.repaint(); }, - () => {/*This is intentional (SonarQube)*/} + () => {/*This is intentional (SonarQube)*/}, + gettext('Delete'), + gettext('Cancel'), ); } diff --git a/web/regression/feature_utils/pgadmin_page.py b/web/regression/feature_utils/pgadmin_page.py index 8f8a37610..6e746a363 100644 --- a/web/regression/feature_utils/pgadmin_page.py +++ b/web/regression/feature_utils/pgadmin_page.py @@ -354,7 +354,7 @@ class PgadminPage: self.click_element(self.find_by_css_selector( "li[data-label='Remove Server']")) self.driver.switch_to.default_content() - self.click_modal('Yes') + self.click_modal('Delete') time.sleep(1) else: print(server_config['name'] + " server is not removed", diff --git a/web/regression/javascript/components/Buttons.spec.js b/web/regression/javascript/components/Buttons.spec.js index 645519da8..4e12af42a 100644 --- a/web/regression/javascript/components/Buttons.spec.js +++ b/web/regression/javascript/components/Buttons.spec.js @@ -28,7 +28,7 @@ describe('components Buttons', ()=>{ let ThemedBtn = withTheme(DefaultButton); render(Test); const btn = screen.getByRole('button'); - expect(btn.classList.contains('MuiButton-outlined')).toBe(true); + expect(btn.classList.contains('MuiButton-outlined')).toBe(false); expect(btn.classList.contains('testClass')).toBe(true); });