Added feature to restore preferences to their default values. #1900
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 121 KiB |
Before Width: | Height: | Size: 184 KiB After Width: | Height: | Size: 191 KiB |
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 190 KiB |
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 217 KiB After Width: | Height: | Size: 214 KiB |
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 128 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 142 KiB |
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 166 KiB |
Before Width: | Height: | Size: 171 KiB After Width: | Height: | Size: 178 KiB |
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 188 KiB |
Before Width: | Height: | Size: 132 KiB After Width: | Height: | Size: 140 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 236 KiB After Width: | Height: | Size: 245 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 162 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 121 KiB |
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 131 KiB |
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 193 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 181 KiB After Width: | Height: | Size: 186 KiB |
Before Width: | Height: | Size: 169 KiB After Width: | Height: | Size: 182 KiB |
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 186 KiB |
Before Width: | Height: | Size: 190 KiB After Width: | Height: | Size: 183 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 94 KiB |
@ -11,9 +11,7 @@ The left pane of the *Preferences* dialog displays a tree control; each node of
|
||||
the tree control provides access to options that are related to the node under
|
||||
which they are displayed.
|
||||
|
||||
* Use the plus sign (+) to the left of a node name to expand a segment of the
|
||||
tree control.
|
||||
* Use the minus sign (-) to the left of a node name to close that node.
|
||||
* Click the *Reset all preferences* button to restore all preferences to their default values.
|
||||
|
||||
The Browser Node
|
||||
****************
|
||||
|
@ -320,3 +320,17 @@ def update():
|
||||
data={'data': 'Success'},
|
||||
status=200
|
||||
)
|
||||
|
||||
|
||||
@blueprint.route("/", methods=['DELETE'], endpoint="reset_prefs")
|
||||
@pga_login_required
|
||||
def reset():
|
||||
"""
|
||||
Reset preferences to default
|
||||
"""
|
||||
res, msg = Preferences.reset()
|
||||
|
||||
if not res:
|
||||
return internal_server_error(errormsg=msg)
|
||||
|
||||
return success_return()
|
||||
|
@ -20,6 +20,7 @@ import getApiInstance from '../../../../static/js/api_instance';
|
||||
import CloseSharpIcon from '@mui/icons-material/CloseSharp';
|
||||
import HelpIcon from '@mui/icons-material/HelpRounded';
|
||||
import SaveSharpIcon from '@mui/icons-material/SaveSharp';
|
||||
import SettingsBackupRestoreIcon from'@mui/icons-material/SettingsBackupRestore';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
import { DefaultButton, PgIconButton, PrimaryButton } from '../../../../static/js/components/Buttons';
|
||||
import BaseUISchema from 'sources/SchemaView/base_schema.ui';
|
||||
@ -589,6 +590,64 @@ export default function PreferencesComponent({ ...props }) {
|
||||
window.open(url_for('help.static', { 'filename': 'preferences.html' }), 'pgadmin_help');
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
pgAdmin.Browser.notifier.confirm(
|
||||
gettext('Reset all preferences'),
|
||||
`${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>`,
|
||||
function () {},
|
||||
function () {},
|
||||
'',
|
||||
'Cancel',
|
||||
function (closeModal) {
|
||||
return [
|
||||
{
|
||||
type: 'default',
|
||||
icon: <SaveSharpIcon />,
|
||||
label: gettext('Save & Reload'),
|
||||
onclick: () => {
|
||||
resetPrefsToDefault(true);
|
||||
closeModal();
|
||||
}
|
||||
}, {
|
||||
type: 'primary',
|
||||
icon: <SaveSharpIcon />,
|
||||
label: gettext('Save & Reload Later'),
|
||||
onclick: () => {
|
||||
resetPrefsToDefault(false);
|
||||
closeModal();
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const resetPrefsToDefault = (refresh = false) => {
|
||||
api({
|
||||
url: url_for('preferences.index'),
|
||||
method: 'DELETE'
|
||||
}).then(()=>{
|
||||
if (refresh){
|
||||
location.reload();
|
||||
return true;
|
||||
}
|
||||
preferencesStore.cache();
|
||||
pgAdmin.Browser.tree.destroy().then(
|
||||
() => {
|
||||
pgAdmin.Browser.Events.trigger(
|
||||
'pgadmin-browser:tree:destroyed', undefined, undefined
|
||||
);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
props.closeModal();
|
||||
}).catch((err) => {
|
||||
pgAdmin.Browser.notifier.alert(err.response.data);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledBox height={'100%'}>
|
||||
<Box className='PreferencesComponent-root'>
|
||||
@ -615,6 +674,9 @@ export default function PreferencesComponent({ ...props }) {
|
||||
<PgIconButton data-test="dialog-help" onClick={onDialogHelp} icon={<HelpIcon />} title={gettext('Help for this dialog.')} />
|
||||
</Box>
|
||||
<Box className='PreferencesComponent-actionBtn' marginLeft="auto">
|
||||
<DefaultButton className='PreferencesComponent-buttonMargin' onClick={reset} startIcon={<SettingsBackupRestoreIcon />}>
|
||||
{gettext('Reset all preferences')}
|
||||
</DefaultButton>
|
||||
<DefaultButton className='PreferencesComponent-buttonMargin' onClick={() => { props.closeModal();}} startIcon={<CloseSharpIcon onClick={() => { props.closeModal();}} />}>
|
||||
{gettext('Cancel')}
|
||||
</DefaultButton>
|
||||
|
@ -41,7 +41,18 @@ export function useModal() {
|
||||
return React.useContext(ModalContext);
|
||||
}
|
||||
|
||||
function AlertContent({ text, confirm, okLabel = gettext('OK'), cancelLabel = gettext('Cancel'), onOkClick, onCancelClick }) {
|
||||
function renderExtraButtons(button) {
|
||||
switch(button.type) {
|
||||
case 'primary':
|
||||
return <PrimaryButton className='Alert-margin' startIcon={button.icon} onClick={button.onclick}>{button.label}</PrimaryButton>;
|
||||
case 'default':
|
||||
return <DefaultButton className='Alert-margin' startIcon={button.icon} onClick={button.onclick}>{button.label}</DefaultButton>;
|
||||
default:
|
||||
return <DefaultButton className='Alert-margin' startIcon={button.icon} onClick={button.onclick}>{button.label}</DefaultButton>;
|
||||
};
|
||||
}
|
||||
|
||||
function AlertContent({ text, confirm, okLabel = gettext('OK'), cancelLabel = gettext('Cancel'), onOkClick, onCancelClick, extraButtons }) {
|
||||
return (
|
||||
<StyledBox display="flex" flexDirection="column" height="100%">
|
||||
<Box flexGrow="1" p={2}>{typeof (text) == 'string' ? HTMLReactParser(text) : text}</Box>
|
||||
@ -49,7 +60,12 @@ function AlertContent({ text, confirm, okLabel = gettext('OK'), cancelLabel = ge
|
||||
{confirm &&
|
||||
<DefaultButton startIcon={<CloseIcon />} onClick={onCancelClick} >{cancelLabel}</DefaultButton>
|
||||
}
|
||||
<PrimaryButton className='Alert-margin' startIcon={<CheckRoundedIcon />} onClick={onOkClick} autoFocus={true} >{okLabel}</PrimaryButton>
|
||||
{
|
||||
extraButtons?.length ?
|
||||
extraButtons.map(button=>renderExtraButtons(button))
|
||||
:
|
||||
<PrimaryButton className='Alert-margin' startIcon={<CheckRoundedIcon />} onClick={onOkClick} autoFocus={true} >{okLabel}</PrimaryButton>
|
||||
}
|
||||
</Box>
|
||||
</StyledBox>
|
||||
);
|
||||
@ -61,6 +77,7 @@ AlertContent.propTypes = {
|
||||
onCancelClick: PropTypes.func,
|
||||
okLabel: PropTypes.string,
|
||||
cancelLabel: PropTypes.string,
|
||||
extraButtons: PropTypes.array
|
||||
};
|
||||
|
||||
function alert(title, text, onOkClick, okLabel = gettext('OK')) {
|
||||
@ -76,7 +93,7 @@ function alert(title, text, onOkClick, okLabel = gettext('OK')) {
|
||||
});
|
||||
}
|
||||
|
||||
function confirm(title, text, onOkClick, onCancelClick, okLabel = gettext('Yes'), cancelLabel = gettext('No')) {
|
||||
function confirm(title, text, onOkClick, onCancelClick, okLabel = gettext('Yes'), cancelLabel = gettext('No'), extras = null) {
|
||||
// bind the modal provider before calling
|
||||
this.showModal(title, (closeModal) => {
|
||||
const onCancelClickClose = () => {
|
||||
@ -87,8 +104,9 @@ function confirm(title, text, onOkClick, onCancelClick, okLabel = gettext('Yes')
|
||||
onOkClick?.();
|
||||
closeModal();
|
||||
};
|
||||
const extraButtons = extras?.(closeModal);
|
||||
return (
|
||||
<AlertContent text={text} confirm onOkClick={onOkClickClose} onCancelClick={onCancelClickClose} okLabel={okLabel} cancelLabel={cancelLabel} />
|
||||
<AlertContent text={text} confirm onOkClick={onOkClickClose} onCancelClick={onCancelClickClose} okLabel={okLabel} cancelLabel={cancelLabel} extraButtons={extraButtons} />
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -175,10 +175,10 @@ class Notifier {
|
||||
this.modal.alert(title, text, onOkClick, okLabel);
|
||||
}
|
||||
|
||||
confirm(title, text, onOkClick, onCancelClick, okLabel=gettext('Yes'), cancelLabel=gettext('No')) {
|
||||
confirm(title, text, onOkClick, onCancelClick, okLabel=gettext('Yes'), cancelLabel=gettext('No'), extras=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);
|
||||
this.modal.confirm(title, text, onOkClick, onCancelClick, okLabel, cancelLabel, extras);
|
||||
}
|
||||
|
||||
showModal(title, content, modalOptions) {
|
||||
|
@ -694,3 +694,20 @@ class Preferences():
|
||||
pref.value = converter_func(pref.value)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
@classmethod
|
||||
def reset(cls):
|
||||
"""
|
||||
reset
|
||||
Reset the preferences for the current user in the configuration table.
|
||||
"""
|
||||
try:
|
||||
db.session.query(UserPrefTable).filter(
|
||||
UserPrefTable.uid == current_user.id).delete()
|
||||
db.session.commit()
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
current_app.logger.exception(e)
|
||||
return False, str(e)
|
||||
|
||||
return True, None
|
||||
|