Port change ownership dialog to React. Fixes #7590
parent
060d7ba46b
commit
53887c32bf
Binary file not shown.
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 42 KiB |
|
@ -15,6 +15,7 @@ Housekeeping
|
|||
************
|
||||
|
||||
| `Issue #7567 <https://redmine.postgresql.org/issues/7567>`_ - Port About dialog to React.
|
||||
| `Issue #7590 <https://redmine.postgresql.org/issues/7590>`_ - Port change ownership dialog to React.
|
||||
| `Issue #7595 <https://redmine.postgresql.org/issues/7595>`_ - Update the container base image to Alpine 3.16 (with Python 3.10.5).
|
||||
|
||||
Bug fixes
|
||||
|
|
|
@ -967,7 +967,7 @@ class ServerNode(PGChildNodeView):
|
|||
'shared': server.shared if config.SERVER_MODE else None,
|
||||
'username': server.username,
|
||||
'gid': str(server.servergroup_id),
|
||||
'group-name': sg.name,
|
||||
'group-name': sg.name if (sg and sg.name) else gettext('Servers'),
|
||||
'comment': server.comment,
|
||||
'role': server.role,
|
||||
'connected': connected,
|
||||
|
|
|
@ -12,7 +12,7 @@ import { getNodePrivilegeRoleSchema } from '../../../static/js/privilege.ui';
|
|||
import { getNodeVariableSchema } from '../../../static/js/variable.ui';
|
||||
import DatabaseSchema from './database.ui';
|
||||
import Notify from '../../../../../../static/js/helpers/Notifier';
|
||||
import { showServerPassword } from '../../../../../static/js/password_dialogs';
|
||||
import { showServerPassword } from '../../../../../../static/js/Dialogs/index';
|
||||
|
||||
define('pgadmin.node.database', [
|
||||
'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
import { getNodeListById } from '../../../../static/js/node_ajax';
|
||||
import ServerSchema from './server.ui';
|
||||
import Notify from '../../../../../static/js/helpers/Notifier';
|
||||
import { showServerPassword, showChangeServerPassword, showNamedRestorePoint } from '../../../../static/js/password_dialogs';
|
||||
import { showServerPassword, showChangeServerPassword, showNamedRestorePoint } from '../../../../../static/js/Dialogs/index';
|
||||
|
||||
define('pgadmin.node.server', [
|
||||
'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
import { generateNodeUrl } from './node_ajax';
|
||||
import Notify, {initializeModalProvider, initializeNotifier} from '../../../static/js/helpers/Notifier';
|
||||
import { checkMasterPassword } from './password_dialogs';
|
||||
import { checkMasterPassword } from '../../../static/js/Dialogs/index';
|
||||
|
||||
define('pgadmin.browser', [
|
||||
'sources/gettext', 'sources/url_for', 'require', 'jquery', 'underscore',
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import { makeStyles } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import gettext from 'sources/gettext';
|
||||
import BaseUISchema from '../SchemaView/base_schema.ui';
|
||||
import SchemaView from '../SchemaView';
|
||||
import { isEmptyString } from 'sources/validators';
|
||||
|
||||
class ChangeOwnershipSchema extends BaseUISchema {
|
||||
constructor(deletedUser, adminUserList, noOfSharedServers) {
|
||||
super({
|
||||
newUser: '',
|
||||
});
|
||||
this.deletedUser = deletedUser;
|
||||
this.adminUserList = adminUserList;
|
||||
this.noOfSharedServers = noOfSharedServers;
|
||||
}
|
||||
|
||||
get baseFields() {
|
||||
let self = this;
|
||||
return [
|
||||
{
|
||||
id: 'note', type: 'note',
|
||||
text: gettext('Select the user that will take ownership of the shared servers created by <b>' + self.deletedUser + '</b>. <b>' + self.noOfSharedServers + '</b> shared servers are currently owned by this user.'),
|
||||
}, {
|
||||
id: 'newUser', label: gettext('User'),
|
||||
type: 'select', controlProps: {allowClear: true},
|
||||
options: self.adminUserList,
|
||||
helpMessage: gettext('Note: If no user is selected, the shared servers will be deleted.')
|
||||
}
|
||||
];
|
||||
}
|
||||
validate(state) {
|
||||
let obj = this;
|
||||
|
||||
/* mview definition validation*/
|
||||
if (isEmptyString(state.newUser)) {
|
||||
obj.warningText = gettext('The shared servers owned by <b>'+ obj.deletedUser +'</b> will be deleted. Do you wish to continue?');
|
||||
} else {
|
||||
obj.warningText = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme)=>({
|
||||
root: {
|
||||
...theme.mixins.tabPanel,
|
||||
},
|
||||
}));
|
||||
|
||||
export default function ChangeOwnershipContent({onSave, onClose, deletedUser, userList, noOfSharedServers}) {
|
||||
const classes = useStyles();
|
||||
const objChangeOwnership = new ChangeOwnershipSchema(deletedUser, userList, noOfSharedServers);
|
||||
|
||||
return<SchemaView
|
||||
formType={'dialog'}
|
||||
getInitData={() => { /*This is intentional (SonarQube)*/ }}
|
||||
schema={objChangeOwnership}
|
||||
viewHelperProps={{
|
||||
mode: 'create',
|
||||
}}
|
||||
customSaveBtnName={'Change'}
|
||||
onSave={onSave}
|
||||
onClose={onClose}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={true}
|
||||
disableDialogHelp={true}
|
||||
isTabView={false}
|
||||
formClassName={classes.root}
|
||||
/>;
|
||||
}
|
||||
ChangeOwnershipContent.propTypes = {
|
||||
onSave: PropTypes.func,
|
||||
onClose: PropTypes.func,
|
||||
currentUser: PropTypes.string,
|
||||
userList: PropTypes.array,
|
||||
noOfSharedServers: PropTypes.number,
|
||||
deletedUser: PropTypes.string
|
||||
};
|
|
@ -11,8 +11,8 @@ import { makeStyles } from '@material-ui/core';
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import gettext from 'sources/gettext';
|
||||
import BaseUISchema from '../../../static/js/SchemaView/base_schema.ui';
|
||||
import SchemaView from '../../../static/js/SchemaView';
|
||||
import BaseUISchema from '../SchemaView/base_schema.ui';
|
||||
import SchemaView from '../SchemaView';
|
||||
|
||||
class ChangePasswordSchema extends BaseUISchema {
|
||||
constructor(user, isPgpassFileUsed) {
|
||||
|
@ -82,6 +82,7 @@ export default function ChangePasswordContent({onSave, onClose, userName, isPgpa
|
|||
viewHelperProps={{
|
||||
mode: 'create',
|
||||
}}
|
||||
customSaveBtnName={'Change'}
|
||||
onSave={onSave}
|
||||
onClose={onClose}
|
||||
hasSQL={false}
|
|
@ -10,12 +10,12 @@
|
|||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import gettext from 'sources/gettext';
|
||||
import { Box } from '@material-ui/core';
|
||||
import { DefaultButton, PrimaryButton } from '../../../static/js/components/Buttons';
|
||||
import { DefaultButton, PrimaryButton } from '../components/Buttons';
|
||||
import CloseIcon from '@material-ui/icons/CloseRounded';
|
||||
import CheckRoundedIcon from '@material-ui/icons/CheckRounded';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useModalStyles } from '../../../static/js/helpers/ModalProvider';
|
||||
import { FormFooterMessage, InputCheckbox, InputText, MESSAGE_TYPE } from '../../../static/js/components/FormComponents';
|
||||
import { useModalStyles } from '../helpers/ModalProvider';
|
||||
import { FormFooterMessage, InputCheckbox, InputText, MESSAGE_TYPE } from '../components/FormComponents';
|
||||
|
||||
export default function ConnectServerContent({closeModal, data, onOK, setHeight}) {
|
||||
const classes = useModalStyles();
|
|
@ -18,9 +18,9 @@ import DeleteForeverIcon from '@material-ui/icons/DeleteForever';
|
|||
import CheckRoundedIcon from '@material-ui/icons/CheckRounded';
|
||||
import HelpIcon from '@material-ui/icons/Help';
|
||||
|
||||
import { DefaultButton, PrimaryButton, PgIconButton } from '../../../static/js/components/Buttons';
|
||||
import { useModalStyles } from '../../../static/js/helpers/ModalProvider';
|
||||
import { FormFooterMessage, InputText, MESSAGE_TYPE } from '../../../static/js/components/FormComponents';
|
||||
import { DefaultButton, PrimaryButton, PgIconButton } from '../components/Buttons';
|
||||
import { useModalStyles } from '../helpers/ModalProvider';
|
||||
import { FormFooterMessage, InputText, MESSAGE_TYPE } from '../components/FormComponents';
|
||||
|
||||
export default function MasterPasswordContent({ closeModal, onResetPassowrd, onOK, onCancel, setHeight, isPWDPresent, data}) {
|
||||
const classes = useModalStyles();
|
|
@ -10,12 +10,12 @@
|
|||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import gettext from 'sources/gettext';
|
||||
import { Box } from '@material-ui/core';
|
||||
import { DefaultButton, PrimaryButton } from '../../../static/js/components/Buttons';
|
||||
import { DefaultButton, PrimaryButton } from '../components/Buttons';
|
||||
import CloseIcon from '@material-ui/icons/CloseRounded';
|
||||
import CheckRoundedIcon from '@material-ui/icons/CheckRounded';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useModalStyles } from '../../../static/js/helpers/ModalProvider';
|
||||
import { InputText } from '../../../static/js/components/FormComponents';
|
||||
import { useModalStyles } from '../helpers/ModalProvider';
|
||||
import { InputText } from '../components/FormComponents';
|
||||
import { isEmptyString } from '../../../static/js/validators';
|
||||
|
||||
export default function NamedRestoreContent({closeModal, onOK, setHeight}) {
|
|
@ -15,29 +15,51 @@ import Theme from 'sources/Theme';
|
|||
import url_for from 'sources/url_for';
|
||||
import gettext from 'sources/gettext';
|
||||
|
||||
import getApiInstance from '../../../static/js/api_instance';
|
||||
import getApiInstance from '../api_instance';
|
||||
import Notify from '../helpers/Notifier';
|
||||
import MasterPasswordContent from './MasterPassowrdContent';
|
||||
import ChangePasswordContent from './ChangePassowrdContent';
|
||||
import NamedRestoreContent from './NamedRestoreContent';
|
||||
import Notify from '../../../static/js/helpers/Notifier';
|
||||
import ChangeOwnershipContent from './ChangeOwnershipContent';
|
||||
|
||||
function setNewSize(panel, width, height) {
|
||||
// Add height of the header
|
||||
let newHeight = height + 31;
|
||||
// Set min and max size of the panel
|
||||
panel.minSize(width, newHeight);
|
||||
panel.maxSize(width, newHeight);
|
||||
panel.maximisable(false);
|
||||
/* No other way to update size, below is the only way */
|
||||
panel._parent._size.x = width;
|
||||
panel._parent._size.y = newHeight;
|
||||
panel._parent.__update();
|
||||
function mountDialog(title, getDialogContent, docker=undefined) {
|
||||
// Register dialog panel
|
||||
var panel;
|
||||
if (docker) {
|
||||
pgAdmin.Browser.Node.registerUtilityPanel(docker);
|
||||
panel = pgAdmin.Browser.Node.addUtilityPanel(pgAdmin.Browser.stdW.md, undefined, docker);
|
||||
} else {
|
||||
pgAdmin.Browser.Node.registerUtilityPanel();
|
||||
panel = pgAdmin.Browser.Node.addUtilityPanel(pgAdmin.Browser.stdW.md);
|
||||
}
|
||||
|
||||
var j = panel.$container.find('.obj_properties').first();
|
||||
panel.title(title);
|
||||
|
||||
const onClose = ()=> {
|
||||
ReactDOM.unmountComponentAtNode(j[0]);
|
||||
panel.close();
|
||||
};
|
||||
|
||||
const setNewSize = (width, height)=> {
|
||||
// Add height of the header
|
||||
let newHeight = height + 31;
|
||||
// Set min and max size of the panel
|
||||
panel.minSize(width, newHeight);
|
||||
panel.maxSize(width, newHeight);
|
||||
panel.maximisable(false);
|
||||
/* No other way to update size, below is the only way */
|
||||
panel._parent._size.x = width;
|
||||
panel._parent._size.y = newHeight;
|
||||
panel._parent.__update();
|
||||
};
|
||||
|
||||
ReactDOM.render(getDialogContent(onClose, setNewSize), j[0]);
|
||||
}
|
||||
|
||||
// This functions is used to show the connect server password dialog.
|
||||
export function showServerPassword() {
|
||||
var pgBrowser = pgAdmin.Browser,
|
||||
title = arguments[0],
|
||||
var title = arguments[0],
|
||||
formJson = arguments[1],
|
||||
nodeObj = arguments[2],
|
||||
nodeData = arguments[3],
|
||||
|
@ -47,20 +69,14 @@ export function showServerPassword() {
|
|||
onSuccess = arguments[7],
|
||||
onFailure = arguments[8];
|
||||
|
||||
// Register dialog panel
|
||||
pgBrowser.Node.registerUtilityPanel();
|
||||
var panel = pgBrowser.Node.addUtilityPanel(pgBrowser.stdW.md),
|
||||
j = panel.$container.find('.obj_properties').first();
|
||||
panel.title(title);
|
||||
|
||||
ReactDOM.render(
|
||||
<Theme>
|
||||
mountDialog(title, (onClose, setNewSize)=> {
|
||||
return <Theme>
|
||||
<ConnectServerContent
|
||||
setHeight={(containerHeight)=>{
|
||||
setNewSize(panel, pgBrowser.stdW.md, containerHeight);
|
||||
setNewSize(pgAdmin.Browser.stdW.md, containerHeight);
|
||||
}}
|
||||
closeModal={()=>{
|
||||
panel.close();
|
||||
onClose();
|
||||
}}
|
||||
data={formJson}
|
||||
onOK={(formData)=>{
|
||||
|
@ -74,7 +90,7 @@ export function showServerPassword() {
|
|||
|
||||
api.post(_url, formData)
|
||||
.then(res=>{
|
||||
panel.close();
|
||||
onClose();
|
||||
return onSuccess(
|
||||
res.data, nodeObj, nodeData, treeNodeInfo, itemNodeData, status
|
||||
);
|
||||
|
@ -87,14 +103,14 @@ export function showServerPassword() {
|
|||
});
|
||||
}}
|
||||
/>
|
||||
</Theme>, j[0]);
|
||||
</Theme>;
|
||||
});
|
||||
}
|
||||
|
||||
// This functions is used to show the connect server password dialog when
|
||||
// launch from Schema Diff tool.
|
||||
export function showSchemaDiffServerPassword() {
|
||||
var pgBrowser = pgAdmin.Browser,
|
||||
docker = arguments[0],
|
||||
var docker = arguments[0],
|
||||
title = arguments[1],
|
||||
formJson = arguments[2],
|
||||
serverID = arguments[3],
|
||||
|
@ -102,20 +118,14 @@ export function showSchemaDiffServerPassword() {
|
|||
onSuccess = arguments[5],
|
||||
onFailure = arguments[6];
|
||||
|
||||
// Register dialog panel
|
||||
pgBrowser.Node.registerUtilityPanel(docker);
|
||||
var panel = pgBrowser.Node.addUtilityPanel(pgBrowser.stdW.md, undefined, docker),
|
||||
j = panel.$container.find('.obj_properties').first();
|
||||
panel.title(title);
|
||||
|
||||
ReactDOM.render(
|
||||
<Theme>
|
||||
mountDialog(title, (onClose, setNewSize)=> {
|
||||
return <Theme>
|
||||
<ConnectServerContent
|
||||
setHeight={(containerHeight)=>{
|
||||
setNewSize(panel, pgBrowser.stdW.md, containerHeight);
|
||||
setNewSize(pgAdmin.Browser.stdW.md, containerHeight);
|
||||
}}
|
||||
closeModal={()=>{
|
||||
panel.close();
|
||||
onClose();
|
||||
}}
|
||||
data={formJson}
|
||||
onOK={(formData)=>{
|
||||
|
@ -124,7 +134,7 @@ export function showSchemaDiffServerPassword() {
|
|||
|
||||
api.post(_url, formData)
|
||||
.then(res=>{
|
||||
panel.close();
|
||||
onClose();
|
||||
return onSuccess(res.data, successCallback);
|
||||
})
|
||||
.catch((err)=>{
|
||||
|
@ -134,7 +144,8 @@ export function showSchemaDiffServerPassword() {
|
|||
});
|
||||
}}
|
||||
/>
|
||||
</Theme>, j[0]);
|
||||
</Theme>;
|
||||
}, docker);
|
||||
}
|
||||
|
||||
function masterPassCallbacks(masterpass_callback_queue) {
|
||||
|
@ -160,26 +171,18 @@ export function checkMasterPassword(data, masterpass_callback_queue, cancel_call
|
|||
// This functions is used to show the master password dialog.
|
||||
export function showMasterPassword(isPWDPresent, errmsg=null, masterpass_callback_queue, cancel_callback) {
|
||||
const api = getApiInstance();
|
||||
var pgBrowser = pgAdmin.Browser;
|
||||
|
||||
// Register dialog panel
|
||||
pgBrowser.Node.registerUtilityPanel();
|
||||
var panel = pgBrowser.Node.addUtilityPanel(pgBrowser.stdW.md),
|
||||
j = panel.$container.find('.obj_properties').first();
|
||||
|
||||
let title = isPWDPresent ? gettext('Unlock Saved Passwords') : gettext('Set Master Password');
|
||||
panel.title(title);
|
||||
|
||||
ReactDOM.render(
|
||||
<Theme>
|
||||
mountDialog(title, (onClose, setNewSize)=> {
|
||||
return <Theme>
|
||||
<MasterPasswordContent
|
||||
isPWDPresent= {isPWDPresent}
|
||||
data={{'errmsg': errmsg}}
|
||||
setHeight={(containerHeight) => {
|
||||
setNewSize(panel, pgBrowser.stdW.md, containerHeight);
|
||||
setNewSize(pgAdmin.Browser.stdW.md, containerHeight);
|
||||
}}
|
||||
closeModal={() => {
|
||||
panel.close();
|
||||
onClose();
|
||||
}}
|
||||
onResetPassowrd={()=>{
|
||||
Notify.confirm(gettext('Reset Master Password'),
|
||||
|
@ -190,7 +193,7 @@ export function showMasterPassword(isPWDPresent, errmsg=null, masterpass_callbac
|
|||
|
||||
api.delete(_url)
|
||||
.then(() => {
|
||||
panel.close();
|
||||
onClose();
|
||||
showMasterPassword(false, null, masterpass_callback_queue, cancel_callback);
|
||||
})
|
||||
.catch((err) => {
|
||||
|
@ -205,32 +208,26 @@ export function showMasterPassword(isPWDPresent, errmsg=null, masterpass_callbac
|
|||
cancel_callback?.();
|
||||
}}
|
||||
onOK={(formData) => {
|
||||
panel.close();
|
||||
onClose();
|
||||
checkMasterPassword(formData, masterpass_callback_queue, cancel_callback);
|
||||
}}
|
||||
/>
|
||||
</Theme>, j[0]);
|
||||
</Theme>;
|
||||
});
|
||||
}
|
||||
|
||||
export function showChangeServerPassword() {
|
||||
var pgBrowser = pgAdmin.Browser,
|
||||
title = arguments[0],
|
||||
var title = arguments[0],
|
||||
nodeData = arguments[1],
|
||||
nodeObj = arguments[2],
|
||||
itemNodeData = arguments[3],
|
||||
isPgPassFileUsed = arguments[4];
|
||||
|
||||
// Register dialog panel
|
||||
pgBrowser.Node.registerUtilityPanel();
|
||||
var panel = pgBrowser.Node.addUtilityPanel(pgBrowser.stdW.md),
|
||||
j = panel.$container.find('.obj_properties').first();
|
||||
panel.title(title);
|
||||
|
||||
ReactDOM.render(
|
||||
<Theme>
|
||||
mountDialog(title, (onClose)=> {
|
||||
return <Theme>
|
||||
<ChangePasswordContent
|
||||
onClose={()=>{
|
||||
panel.close();
|
||||
onClose();
|
||||
}}
|
||||
onSave={(isNew, data)=>{
|
||||
return new Promise((resolve, reject)=>{
|
||||
|
@ -251,7 +248,7 @@ export function showChangeServerPassword() {
|
|||
}
|
||||
|
||||
resolve(respData.data);
|
||||
panel.close();
|
||||
onClose();
|
||||
})
|
||||
.catch((error)=>{
|
||||
reject(error);
|
||||
|
@ -261,30 +258,24 @@ export function showChangeServerPassword() {
|
|||
userName={nodeData.user.name}
|
||||
isPgpassFileUsed={isPgPassFileUsed}
|
||||
/>
|
||||
</Theme>, j[0]);
|
||||
</Theme>;
|
||||
});
|
||||
}
|
||||
|
||||
export function showNamedRestorePoint() {
|
||||
var pgBrowser = pgAdmin.Browser,
|
||||
title = arguments[0],
|
||||
var title = arguments[0],
|
||||
nodeData = arguments[1],
|
||||
nodeObj = arguments[2],
|
||||
itemNodeData = arguments[3];
|
||||
|
||||
// Register dialog panel
|
||||
pgBrowser.Node.registerUtilityPanel();
|
||||
var panel = pgBrowser.Node.addUtilityPanel(pgBrowser.stdW.md),
|
||||
j = panel.$container.find('.obj_properties').first();
|
||||
panel.title(title);
|
||||
|
||||
ReactDOM.render(
|
||||
<Theme>
|
||||
mountDialog(title, (onClose, setNewSize)=> {
|
||||
return <Theme>
|
||||
<NamedRestoreContent
|
||||
setHeight={(containerHeight)=>{
|
||||
setNewSize(panel, pgBrowser.stdW.md, containerHeight);
|
||||
setNewSize(pgAdmin.Browser.stdW.md, containerHeight);
|
||||
}}
|
||||
closeModal={()=>{
|
||||
panel.close();
|
||||
onClose();
|
||||
}}
|
||||
onOK={(formData)=>{
|
||||
const api = getApiInstance();
|
||||
|
@ -292,7 +283,7 @@ export function showNamedRestorePoint() {
|
|||
|
||||
api.post(_url, formData)
|
||||
.then(res=>{
|
||||
panel.close();
|
||||
onClose();
|
||||
Notify.success(res.data.data.result);
|
||||
})
|
||||
.catch(function(xhr, status, error) {
|
||||
|
@ -300,5 +291,59 @@ export function showNamedRestorePoint() {
|
|||
});
|
||||
}}
|
||||
/>
|
||||
</Theme>, j[0]);
|
||||
</Theme>;
|
||||
});
|
||||
}
|
||||
|
||||
export function showChangeOwnership() {
|
||||
var title = arguments[0],
|
||||
userList = arguments[1],
|
||||
noOfSharedServers = arguments[2],
|
||||
deletedUser = arguments[3],
|
||||
destroyUserManagement = arguments[4];
|
||||
|
||||
// Render Preferences component
|
||||
Notify.showModal(title, (onClose) => {
|
||||
return <ChangeOwnershipContent
|
||||
onClose={()=>{
|
||||
onClose();
|
||||
}}
|
||||
onSave={(isNew, data)=>{
|
||||
const api = getApiInstance();
|
||||
|
||||
return new Promise((resolve, reject)=>{
|
||||
if (data.newUser == '') {
|
||||
api.delete(url_for('user_management.user', {uid: deletedUser['uid']}))
|
||||
.then(() => {
|
||||
Notify.success(gettext('User deleted.'));
|
||||
onClose();
|
||||
destroyUserManagement();
|
||||
resolve();
|
||||
})
|
||||
.catch((err)=>{
|
||||
Notify.error(err);
|
||||
reject(err);
|
||||
});
|
||||
} else {
|
||||
let newData = {'new_owner': `${data.newUser}`, 'old_owner': `${deletedUser['uid']}`};
|
||||
api.post(url_for('user_management.change_owner'), newData)
|
||||
.then(({data: respData})=>{
|
||||
Notify.success(gettext(respData.info));
|
||||
onClose();
|
||||
destroyUserManagement();
|
||||
resolve(respData.data);
|
||||
})
|
||||
.catch((err)=>{
|
||||
reject(err);
|
||||
});
|
||||
}
|
||||
});
|
||||
}}
|
||||
userList = {userList}
|
||||
noOfSharedServers = {noOfSharedServers}
|
||||
deletedUser = {deletedUser['name']}
|
||||
/>;
|
||||
},
|
||||
{ isFullScreen: false, isResizeable: true, showFullScreen: true, isFullWidth: true,
|
||||
dialogWidth: pgAdmin.Browser.stdW.md, dialogHeight: pgAdmin.Browser.stdH.md});
|
||||
}
|
|
@ -8,7 +8,7 @@
|
|||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import { Box, Dialog, DialogContent, DialogTitle, makeStyles, Paper } from '@material-ui/core';
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { getEpoch } from 'sources/utils';
|
||||
import { DefaultButton, PgIconButton, PrimaryButton } from '../components/Buttons';
|
||||
|
@ -296,7 +296,7 @@ function ModalContainer({ id, title, content, dialogHeight, dialogWidth, onClose
|
|||
</Box>
|
||||
</DialogTitle>
|
||||
<DialogContent height="100%">
|
||||
{content(closeModal)}
|
||||
{useMemo(()=>{ return content(closeModal); }, [])}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
|
|
|
@ -19,7 +19,7 @@ import 'pgadmin.tools.sqleditor';
|
|||
import pgWindow from 'sources/window';
|
||||
import _ from 'underscore';
|
||||
import Notify from '../../../../static/js/helpers/Notifier';
|
||||
import { showSchemaDiffServerPassword } from '../../../../browser/static/js/password_dialogs';
|
||||
import { showSchemaDiffServerPassword } from '../../../../static/js/Dialogs/index';
|
||||
|
||||
|
||||
import { SchemaDiffSelect2Control, SchemaDiffHeaderView,
|
||||
|
|
|
@ -37,7 +37,7 @@ import PropTypes from 'prop-types';
|
|||
import { retrieveNodeName } from '../show_view_data';
|
||||
import 'wcdocker';
|
||||
import { useModal } from '../../../../../static/js/helpers/ModalProvider';
|
||||
import ConnectServerContent from '../../../../../browser/static/js/ConnectServerContent';
|
||||
import ConnectServerContent from '../../../../../static/js/Dialogs/ConnectServerContent';
|
||||
|
||||
export const QueryToolContext = React.createContext();
|
||||
export const QueryToolConnectionContext = React.createContext();
|
||||
|
@ -362,10 +362,6 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
|
|||
|
||||
|
||||
const handleApiError = (error, handleParams)=>{
|
||||
if(error.response && pgAdmin.Browser?.UserManagement?.isPgaLoginRequired(error.response)) {
|
||||
return pgAdmin.Browser.UserManagement.pgaLogin();
|
||||
}
|
||||
|
||||
if(error.response?.status == 503 && error.response.data?.info == 'CONNECTION_LOST') {
|
||||
// We will display re-connect dialog, no need to display error message again
|
||||
modal.confirm(
|
||||
|
|
|
@ -16,7 +16,7 @@ import url_for from 'sources/url_for';
|
|||
import _ from 'lodash';
|
||||
import { flattenSelectOptions } from '../../../../../../static/js/components/FormComponents';
|
||||
import PropTypes from 'prop-types';
|
||||
import ConnectServerContent from '../../../../../../browser/static/js/ConnectServerContent';
|
||||
import ConnectServerContent from '../../../../../../static/js/Dialogs/ConnectServerContent';
|
||||
|
||||
class NewConnectionSchema extends BaseUISchema {
|
||||
constructor(api, params, connectServer) {
|
||||
|
|
|
@ -496,9 +496,6 @@ def get_shared_servers(uid):
|
|||
return internal_server_error(errormsg=str(e))
|
||||
|
||||
|
||||
# @blueprint.route(
|
||||
# '/admin_users', methods=['GET'], endpoint='admin_users'
|
||||
# )
|
||||
@blueprint.route(
|
||||
'/admin_users/<int:uid>', methods=['GET'], endpoint='admin_users'
|
||||
)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import Notify from '../../../../static/js/helpers/Notifier';
|
||||
import { showChangeOwnership } from '../../../../static/js/Dialogs/index';
|
||||
|
||||
define([
|
||||
'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'pgadmin.alertifyjs',
|
||||
|
@ -94,104 +95,6 @@ define([
|
|||
);
|
||||
},
|
||||
|
||||
isPgaLoginRequired(xhr) {
|
||||
/* If responseJSON is undefined then it could be object of
|
||||
* axios(Promise HTTP) response, so we should check accordingly.
|
||||
*/
|
||||
if (xhr.responseJSON === undefined && xhr.data !== undefined) {
|
||||
return xhr.status === 401 && xhr.data &&
|
||||
xhr.data.info &&
|
||||
xhr.data.info === 'PGADMIN_LOGIN_REQUIRED';
|
||||
}
|
||||
|
||||
return xhr.status === 401 && xhr.responseJSON &&
|
||||
xhr.responseJSON.info &&
|
||||
xhr.responseJSON.info === 'PGADMIN_LOGIN_REQUIRED';
|
||||
},
|
||||
|
||||
// Callback to draw pgAdmin4 login dialog.
|
||||
pgaLogin: function(url) {
|
||||
var title = gettext('pgAdmin 4 login');
|
||||
url = url || url_for('security.login');
|
||||
if(!alertify.PgaLogin) {
|
||||
alertify.dialog('PgaLogin' ,function factory() {
|
||||
return {
|
||||
main: function(alertTitle, alertUrl) {
|
||||
this.set({
|
||||
'title': alertTitle,
|
||||
'url': alertUrl,
|
||||
});
|
||||
},
|
||||
build: function() {
|
||||
alertify.pgDialogBuild.apply(this);
|
||||
},
|
||||
settings:{
|
||||
url: undefined,
|
||||
},
|
||||
setup:function() {
|
||||
return {
|
||||
buttons: [{
|
||||
text: gettext('Close'), key: 27,
|
||||
className: 'btn btn-secondary fa fa-lg fa-times pg-alertify-button',
|
||||
attrs:{name:'close', type:'button'},
|
||||
}],
|
||||
// Set options for dialog
|
||||
options: {
|
||||
//disable both padding and overflow control.
|
||||
padding : !1,
|
||||
overflow: !1,
|
||||
modal: true,
|
||||
resizable: true,
|
||||
maximizable: true,
|
||||
pinnable: false,
|
||||
closableByDimmer: false,
|
||||
closable: false,
|
||||
},
|
||||
};
|
||||
},
|
||||
hooks: {
|
||||
// Triggered when the dialog is closed
|
||||
onclose: function() {
|
||||
// Clear the view
|
||||
return setTimeout((function() {
|
||||
return alertify.PgaLogin().destroy();
|
||||
}));
|
||||
},
|
||||
},
|
||||
prepare: function() {
|
||||
// create the iframe element
|
||||
var self = this,
|
||||
iframe = document.createElement('iframe'),
|
||||
frameUrl = this.setting('url');
|
||||
|
||||
iframe.onload = function() {
|
||||
var doc = this.contentDocument || this.contentWindow.document;
|
||||
if (doc.location.href.indexOf(frameUrl) == -1) {
|
||||
// login successful.
|
||||
|
||||
this.contentWindow.stop();
|
||||
this.onload = null;
|
||||
|
||||
// close the dialog.
|
||||
self.close();
|
||||
pgBrowser.Events.trigger('pgadmin:user:logged-in');
|
||||
}
|
||||
};
|
||||
|
||||
iframe.frameBorder = 'no';
|
||||
iframe.width = '100%';
|
||||
iframe.height = '100%';
|
||||
iframe.src = frameUrl;
|
||||
// add it to the dialog
|
||||
self.elements.content.appendChild(iframe);
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
alertify.PgaLogin(title, url).resizeTo(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
},
|
||||
|
||||
is_editable: function(m) {
|
||||
if (m instanceof Backbone.Collection) {
|
||||
return true;
|
||||
|
@ -551,191 +454,34 @@ define([
|
|||
},
|
||||
|
||||
changeOwnership: function(res, uid) {
|
||||
let self = this;
|
||||
let self = this,
|
||||
url = url_for('user_management.admin_users', {'uid': uid});
|
||||
|
||||
let ownershipSelect2Control = Backform.Select2Control.extend({
|
||||
fetchData: function(){
|
||||
let that = this;
|
||||
let url = that.field.get('url');
|
||||
const destroyUserManagement = ()=>{
|
||||
alertify.UserManagement().destroy();
|
||||
};
|
||||
|
||||
url = url_for(url, {'uid': uid});
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
headers: {
|
||||
'Cache-Control' : 'no-cache',
|
||||
},
|
||||
}).done(function (res_data) {
|
||||
var transform = that.field.get('transform');
|
||||
if(res_data.data.status){
|
||||
let data = res_data.data.result.data;
|
||||
|
||||
if (transform && _.isFunction(transform)) {
|
||||
that.field.set('options', transform.bind(that, data));
|
||||
} else {
|
||||
that.field.set('options', data);
|
||||
}
|
||||
} else {
|
||||
if (transform && _.isFunction(transform)) {
|
||||
that.field.set('options', transform.bind(that, []));
|
||||
} else {
|
||||
that.field.set('options', []);
|
||||
}
|
||||
}
|
||||
Backform.Select2Control.prototype.render.apply(that, arguments);
|
||||
}).fail(function(e){
|
||||
let msg = '';
|
||||
if(e.status == 404) {
|
||||
msg = 'Unable to find url.';
|
||||
} else {
|
||||
msg = e.responseJSON.errormsg;
|
||||
}
|
||||
Notify.error(msg);
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
this.fetchData();
|
||||
return Backform.Select2Control.prototype.render.apply(this, arguments);
|
||||
},
|
||||
onChange: function() {
|
||||
Backform.Select2Control.prototype.onChange.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
let ownershipModel = pgBrowser.DataModel.extend({
|
||||
schema: [
|
||||
{
|
||||
id: 'note_text_ch_owner',
|
||||
control: Backform.NoteControl,
|
||||
text: 'Select the user that will take ownership of the shared servers created by <b>' + self.model.get('username') + '</b>. <b>' + res['data'].shared_servers + '</b> shared servers are currently owned by this user.',
|
||||
group: gettext('General'),
|
||||
},
|
||||
{
|
||||
id: 'user',
|
||||
name: 'user',
|
||||
label: gettext('User'),
|
||||
type: 'text',
|
||||
editable: true,
|
||||
select2: {
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
first_empty: true,
|
||||
},
|
||||
control: ownershipSelect2Control,
|
||||
url: 'user_management.admin_users',
|
||||
helpMessage: gettext('Note: If no user is selected, the shared servers will be deleted.'),
|
||||
}],
|
||||
});
|
||||
// Change shared server ownership before deleting the admin user
|
||||
if (!alertify.changeOwnershipDialog) {
|
||||
alertify.dialog('changeOwnershipDialog', function factory() {
|
||||
let $container = $('<div class=\'change-ownership\'></div>');
|
||||
return {
|
||||
main: function(message) {
|
||||
this.msg = message;
|
||||
},
|
||||
build: function() {
|
||||
this.elements.content.appendChild($container.get(0));
|
||||
alertify.pgDialogBuild.apply(this);
|
||||
},
|
||||
setup: function(){
|
||||
return {
|
||||
buttons: [
|
||||
{
|
||||
text: gettext('Cancel'),
|
||||
key: 27,
|
||||
className: 'btn btn-secondary fa fa-times pg-alertify-button',
|
||||
'data-btn-name': 'cancel',
|
||||
}, {
|
||||
text: gettext('OK'),
|
||||
key: 13,
|
||||
className: 'btn btn-primary fa fa-check pg-alertify-button',
|
||||
'data-btn-name': 'ok',
|
||||
},
|
||||
],
|
||||
// Set options for dialog
|
||||
options: {
|
||||
title: 'Change ownership',
|
||||
//disable both padding and overflow control.
|
||||
padding: !1,
|
||||
overflow: !1,
|
||||
model: 0,
|
||||
resizable: true,
|
||||
maximizable: false,
|
||||
pinnable: false,
|
||||
closableByDimmer: false,
|
||||
modal: false,
|
||||
autoReset: false,
|
||||
closable: true,
|
||||
},
|
||||
};
|
||||
},
|
||||
prepare: function() {
|
||||
let that = this;
|
||||
$container.html('');
|
||||
|
||||
that.ownershipModel = new ownershipModel();
|
||||
let fields = pgBackform.generateViewSchema(null, that.ownershipModel, 'create', null, null, true, null);
|
||||
|
||||
let view = this.view = new pgBackform.Dialog({
|
||||
el: '<div></div>',
|
||||
model: that.ownershipModel,
|
||||
schema: fields,
|
||||
});
|
||||
//Render change ownership dialog.
|
||||
$container.append(view.render().$el[0]);
|
||||
},
|
||||
callback: function(e) {
|
||||
if(e.button['data-btn-name'] === 'ok') {
|
||||
e.cancel = true; // Do not close dialog
|
||||
let newOwnershipModel = this.ownershipModel.toJSON();
|
||||
if (newOwnershipModel.user == '' || newOwnershipModel.user == undefined) {
|
||||
Notify.confirm(
|
||||
gettext('Delete user?'),
|
||||
gettext('The shared servers owned by <b>'+ self.model.get('username') +'</b> will be deleted. Do you wish to continue?'),
|
||||
function() {
|
||||
|
||||
self.model.destroy({
|
||||
wait: true,
|
||||
success: function() {
|
||||
Notify.success(gettext('User deleted.'));
|
||||
alertify.changeOwnershipDialog().destroy();
|
||||
alertify.UserManagement().destroy();
|
||||
},
|
||||
error: self.raiseError,
|
||||
});
|
||||
alertify.changeOwnershipDialog().destroy();
|
||||
},
|
||||
function() {
|
||||
return true;
|
||||
}
|
||||
);
|
||||
} else {
|
||||
self.changeOwner(newOwnershipModel.user, uid);
|
||||
}
|
||||
} else {
|
||||
alertify.changeOwnershipDialog().destroy();
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
alertify.changeOwnershipDialog('Change ownership').resizeTo(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
},
|
||||
changeOwner: function(user_id, old_user) {
|
||||
$.ajax({
|
||||
url: url_for('user_management.change_owner'),
|
||||
method: 'POST',
|
||||
data:{'new_owner': user_id, 'old_owner': old_user},
|
||||
})
|
||||
.done(function(res) {
|
||||
alertify.changeOwnershipDialog().destroy();
|
||||
alertify.UserManagement().destroy();
|
||||
Notify.success(gettext(res.info));
|
||||
})
|
||||
.fail(function() {
|
||||
Notify.error(gettext('Unable to change owner.'));
|
||||
});
|
||||
url: url,
|
||||
headers: {
|
||||
'Cache-Control' : 'no-cache',
|
||||
},
|
||||
}).done(function (result) {
|
||||
showChangeOwnership(gettext('Change ownership'),
|
||||
result.data.result.data,
|
||||
res['data'].shared_servers,
|
||||
{uid: uid, name: self.model.get('username')},
|
||||
destroyUserManagement
|
||||
);
|
||||
}).fail(function(e) {
|
||||
let msg = '';
|
||||
if(e.status == 404) {
|
||||
msg = 'Unable to find url.';
|
||||
} else {
|
||||
msg = e.responseJSON.errormsg;
|
||||
}
|
||||
Notify.error(msg);
|
||||
});
|
||||
},
|
||||
deleteUser: function() {
|
||||
let self = this;
|
||||
|
|
Loading…
Reference in New Issue