Port Backup Global, Backup Server, and Backup object dialog in React. Fixes #6984
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 47 KiB |
@ -13,6 +13,7 @@ New features
|
||||
Housekeeping
|
||||
************
|
||||
|
||||
| `Issue #6984 <https://redmine.postgresql.org/issues/6984>`_ - Port Backup Global, Backup Server, and Backup object dialog in React.
|
||||
|
||||
Bug fixes
|
||||
*********
|
||||
|
@ -537,7 +537,7 @@ class DatabaseView(PGChildNodeView):
|
||||
"""
|
||||
This function to return list of avialable encodings
|
||||
"""
|
||||
res = [{'label': '', 'value': ''}]
|
||||
res = []
|
||||
SQL = render_template(
|
||||
"/".join([self.template_path, 'get_encodings.sql'])
|
||||
)
|
||||
|
@ -497,6 +497,72 @@ define('pgadmin.browser.node', [
|
||||
|
||||
return null;
|
||||
},
|
||||
addUtilityPanel: function() {
|
||||
var body = window.document.body,
|
||||
el = document.createElement('div');
|
||||
|
||||
body.insertBefore(el, body.firstChild);
|
||||
|
||||
var new_panel = pgBrowser.docker.addPanel(
|
||||
'utility_props', window.wcDocker.DOCK.FLOAT, undefined, {
|
||||
w: (screen.width < 700 ?
|
||||
screen.width * 0.95 : screen.width * 0.5),
|
||||
h: (screen.height < 500 ?
|
||||
screen.height * 0.95 : screen.height * 0.5),
|
||||
x: (screen.width < 700 ? '2%' : '25%'),
|
||||
y: (screen.height < 500 ? '2%' : '25%'),
|
||||
}
|
||||
);
|
||||
/*set movable false to prevent dialog from docking,
|
||||
by setting this we can able to move the dialog but can't dock it
|
||||
in to the frame. e.g: can't dock it in to properties and other tabs. */
|
||||
setTimeout(function() {
|
||||
new_panel.moveable(false);
|
||||
}, 0);
|
||||
|
||||
body.removeChild(el);
|
||||
|
||||
return new_panel;
|
||||
},
|
||||
registerUtilityPanel: function() {
|
||||
var w = pgBrowser.docker,
|
||||
p = w.findPanels('utility_props');
|
||||
|
||||
if (p && p.length == 1)
|
||||
return;
|
||||
|
||||
var events = {};
|
||||
events[wcDocker.EVENT.RESIZE_ENDED] = function() {
|
||||
var $container = this.$container.find('.obj_properties').first(),
|
||||
v = $container.data('obj-view');
|
||||
|
||||
if (v && v.model && v.model) {
|
||||
v.model.trigger(
|
||||
'pg-browser-resized', {
|
||||
'view': v,
|
||||
'panel': this,
|
||||
'container': $container,
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
p = new pgBrowser.Panel({
|
||||
name: 'utility_props',
|
||||
showTitle: true,
|
||||
isCloseable: true,
|
||||
isPrivate: true,
|
||||
isLayoutMember: false,
|
||||
canMaximise: true,
|
||||
elContainer: true,
|
||||
content: '<div class="obj_properties container-fluid h-100"><div role="status" class="pg-panel-message">' + gettext('Please wait while we fetch information ...') + '</div></div>',
|
||||
onCreate: function(myPanel, $container) {
|
||||
$container.addClass('pg-no-overflow');
|
||||
},
|
||||
events: events,
|
||||
});
|
||||
p.load(pgBrowser.docker);
|
||||
},
|
||||
register_node_panel: function() {
|
||||
var w = pgBrowser.docker,
|
||||
p = w.findPanels('node_props');
|
||||
|
108
web/pgadmin/browser/static/js/utility_view.jsx
Normal file
@ -0,0 +1,108 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
import getApiInstance from 'sources/api_instance';
|
||||
import {getHelpUrl, getEPASHelpUrl} from 'pgadmin.help';
|
||||
import SchemaView from 'sources/SchemaView';
|
||||
import 'wcdocker';
|
||||
|
||||
/* The entry point for rendering React based view in properties, called in node.js */
|
||||
export function getUtilityView(schema, treeNodeInfo, actionType, formType, container, containerPanel, onSave, extraData, saveBtnName, urlBase, sqlHelpUrl, helpUrl) {
|
||||
let serverInfo = treeNodeInfo && ('server' in treeNodeInfo) &&
|
||||
pgAdmin.Browser.serverInfo && pgAdmin.Browser.serverInfo[treeNodeInfo.server._id];
|
||||
let inCatalog = treeNodeInfo && ('catalog' in treeNodeInfo);
|
||||
const api = getApiInstance();
|
||||
const url = ()=>{
|
||||
return urlBase;
|
||||
};
|
||||
const confirmOnReset = pgAdmin.Browser.get_preferences_for_module('browser').confirm_on_properties_close;
|
||||
|
||||
/* on save button callback, promise required */
|
||||
const onSaveClick = (isNew, data)=>new Promise((resolve, reject)=>{
|
||||
return api({
|
||||
url: url(),
|
||||
method: isNew ? 'POST' : 'PUT',
|
||||
data: Object.assign({}, data, extraData),
|
||||
}).then((res)=>{
|
||||
/* Don't warn the user before closing dialog */
|
||||
resolve(res.data);
|
||||
onSave && onSave(res.data, containerPanel);
|
||||
containerPanel.close();
|
||||
}).catch((err)=>{
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
|
||||
/* Callback for help button */
|
||||
const onHelp = (isSqlHelp=false, isNew=false)=>{
|
||||
if(isSqlHelp) {
|
||||
let server = treeNodeInfo.server;
|
||||
let url = pgAdmin.Browser.utils.pg_help_path;
|
||||
let fullUrl = '';
|
||||
|
||||
if (server.server_type == 'ppas') {
|
||||
fullUrl = getEPASHelpUrl(server.version);
|
||||
} else {
|
||||
if (sqlHelpUrl == '') {
|
||||
fullUrl = getHelpUrl(url, sqlHelpUrl, server.version);
|
||||
} else if (sqlHelpUrl != '') {
|
||||
fullUrl = getHelpUrl(url, sqlHelpUrl, server.version);
|
||||
} else {
|
||||
if (isNew) {
|
||||
fullUrl = getHelpUrl(url, sqlHelpUrl, server.version);
|
||||
} else {
|
||||
fullUrl = getHelpUrl(url, sqlHelpUrl, server.version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.open(fullUrl, 'postgres_help');
|
||||
} else {
|
||||
window.open(helpUrl, 'pgadmin_help');
|
||||
}
|
||||
};
|
||||
|
||||
/* All other useful details can go with this object */
|
||||
const viewHelperProps = {
|
||||
mode: actionType,
|
||||
serverInfo: serverInfo ? {
|
||||
type: serverInfo.server_type,
|
||||
version: serverInfo.version,
|
||||
}: undefined,
|
||||
inCatalog: inCatalog,
|
||||
};
|
||||
|
||||
let _schema = schema;
|
||||
|
||||
/* Fire at will, mount the DOM */
|
||||
ReactDOM.render(
|
||||
<SchemaView
|
||||
formType={formType}
|
||||
schema={_schema}
|
||||
viewHelperProps={viewHelperProps}
|
||||
customSaveBtnName={saveBtnName}
|
||||
onSave={onSaveClick}
|
||||
onClose={()=>containerPanel.close()}
|
||||
onHelp={onHelp}
|
||||
onDataChange={()=>{
|
||||
}}
|
||||
confirmOnCloseReset={confirmOnReset}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={sqlHelpUrl == undefined || sqlHelpUrl == ''}
|
||||
disableDialogHelp={helpUrl == undefined || helpUrl == ''}
|
||||
/>, container);
|
||||
}
|
||||
|
||||
/* When switching from normal node to collection node, clean up the React mounted DOM */
|
||||
export function removeNodeView(container) {
|
||||
ReactDOM.unmountComponentAtNode(container);
|
||||
}
|
@ -706,7 +706,7 @@ function SchemaDialogView({
|
||||
{gettext('Reset')}
|
||||
</DefaultButton>
|
||||
<PrimaryButton data-test="Save" onClick={onSaveClick} startIcon={<SaveIcon />} disabled={!dirty || saving || Boolean(formErr.name) || !formReady}>
|
||||
{gettext('Save')}
|
||||
{props.customSaveBtnName ? gettext(props.customSaveBtnName) : gettext('Save')}
|
||||
</PrimaryButton>
|
||||
</Box>
|
||||
</Box>}
|
||||
@ -739,6 +739,7 @@ SchemaDialogView.propTypes = {
|
||||
disableDialogHelp: PropTypes.bool,
|
||||
showFooter: PropTypes.bool,
|
||||
resetKey: PropTypes.any,
|
||||
customSaveBtnName: PropTypes.string,
|
||||
};
|
||||
|
||||
const usePropsStyles = makeStyles((theme)=>({
|
||||
|
@ -7,7 +7,6 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import * as BackupDialog from '../../../tools/backup/static/js/backup_dialog_wrapper';
|
||||
import {RestoreDialogWrapper} from '../../../tools/restore/static/js/restore_dialog_wrapper';
|
||||
import SearchObjectsDialogWrapper from '../../../tools/search_objects/static/js/search_objects_dialog_wrapper';
|
||||
|
||||
@ -28,8 +27,6 @@ export class DialogFactory {
|
||||
return this.createRestoreDialog(dialogTitle, typeOfDialog);
|
||||
} else if (typeOfDialog === 'search_objects') {
|
||||
return this.createSearchObjectsDialog(dialogTitle, typeOfDialog);
|
||||
} else {
|
||||
return this.createBackupDialog(dialogTitle, typeOfDialog);
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,16 +40,6 @@ export class DialogFactory {
|
||||
this.backform);
|
||||
}
|
||||
|
||||
createBackupDialog(dialogTitle, typeOfDialog) {
|
||||
return new BackupDialog.BackupDialogWrapper(
|
||||
this.dialogContainerSelector, dialogTitle, typeOfDialog,
|
||||
this.jquery,
|
||||
this.pgBrowser,
|
||||
this.alertify,
|
||||
this.dialogModel,
|
||||
this.backform);
|
||||
}
|
||||
|
||||
createSearchObjectsDialog(dialogTitle, typeOfDialog) {
|
||||
return new SearchObjectsDialogWrapper(
|
||||
this.dialogContainerSelector, dialogTitle, typeOfDialog,
|
||||
|
@ -6,18 +6,20 @@
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import {getUtilityView, removeNodeView} from '../../../../browser/static/js/utility_view';
|
||||
import { getNodeListByName, getNodeAjaxOptions } from '../../../../browser/static/js/node_ajax';
|
||||
import BackupSchema, {getSectionSchema, getTypeObjSchema, getSaveOptSchema, getQueryOptionSchema, getDisabledOptionSchema, getMiscellaneousSchema} from './backup.ui';
|
||||
import BackupGlobalSchema, {getMiscellaneousSchema as getMiscellaneousGlobalSchema} from './backupGlobal.ui';
|
||||
// Backup dialog
|
||||
define([
|
||||
'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
|
||||
'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'sources/pgadmin',
|
||||
'pgadmin.alertifyjs', 'backbone', 'pgadmin.backgrid',
|
||||
'pgadmin.backform', 'pgadmin.browser', 'sources/utils',
|
||||
'tools/backup/static/js/menu_utils',
|
||||
'tools/backup/static/js/backup_dialog',
|
||||
'sources/nodes/supported_database_node',
|
||||
], function(
|
||||
gettext, url_for, $, _, alertify, Backbone, Backgrid, Backform, pgBrowser,
|
||||
commonUtils, menuUtils, globalBackupDialog, supportedNodes
|
||||
gettext, url_for, $, _, pgAdmin, alertify, Backbone, Backgrid, Backform, pgBrowser,
|
||||
commonUtils, menuUtils, supportedNodes
|
||||
) {
|
||||
|
||||
// if module is already initialized, refer to that.
|
||||
@ -43,524 +45,6 @@ define([
|
||||
with schema.
|
||||
*/
|
||||
|
||||
//Backup Model (Server Node)
|
||||
var BackupModel = Backbone.Model.extend({
|
||||
idAttribute: 'id',
|
||||
defaults: {
|
||||
file: undefined,
|
||||
role: undefined,
|
||||
dqoute: false,
|
||||
verbose: true,
|
||||
type: undefined,
|
||||
/* global */
|
||||
},
|
||||
schema: [{
|
||||
id: 'file',
|
||||
label: gettext('Filename'),
|
||||
type: 'text',
|
||||
disabled: false,
|
||||
control: Backform.FileControl,
|
||||
dialog_type: 'create_file',
|
||||
supp_types: ['*', 'sql', 'backup'],
|
||||
}, {
|
||||
id: 'role',
|
||||
label: gettext('Role name'),
|
||||
control: 'node-list-by-name',
|
||||
node: 'role',
|
||||
select2: {
|
||||
allowClear: false,
|
||||
},
|
||||
}, {
|
||||
type: 'nested',
|
||||
control: 'fieldset',
|
||||
label: gettext('Miscellaneous'),
|
||||
contentClass: 'row',
|
||||
schema: [{
|
||||
id: 'verbose',
|
||||
label: gettext('Verbose messages'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Miscellaneous'),
|
||||
}, {
|
||||
id: 'dqoute',
|
||||
label: gettext('Force double quote on identifiers'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Miscellaneous'),
|
||||
controlLabelClassName: 'control-label pg-el-sm-6 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-6 pg-el-12',
|
||||
}],
|
||||
}, {
|
||||
id: 'globals_note',
|
||||
label: gettext('Note'),
|
||||
text: gettext('Only objects global to the entire database will be backed up, in PLAIN format'),
|
||||
type: 'note',
|
||||
}, {}],
|
||||
validate: function() {
|
||||
// TODO: HOW TO VALIDATE ???
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
||||
//Backup Model (Objects like Database/Schema/Table)
|
||||
var BackupObjectModel = Backbone.Model.extend({
|
||||
idAttribute: 'id',
|
||||
defaults: {
|
||||
file: undefined,
|
||||
role: undefined,
|
||||
format: 'custom',
|
||||
verbose: true,
|
||||
blobs: true,
|
||||
encoding: undefined,
|
||||
schemas: [],
|
||||
tables: [],
|
||||
database: undefined,
|
||||
},
|
||||
schema: [{
|
||||
id: 'file',
|
||||
label: gettext('Filename'),
|
||||
type: 'text',
|
||||
disabled: false,
|
||||
control: Backform.FileControl.extend({
|
||||
render: function() {
|
||||
var attributes = this.model.toJSON();
|
||||
if (attributes.format == 'directory') {
|
||||
this.field.attributes.dialog_type = 'select_folder';
|
||||
}
|
||||
else {
|
||||
this.field.attributes.dialog_type = 'create_file';
|
||||
}
|
||||
|
||||
Backform.InputControl.prototype.render.apply(this, arguments);
|
||||
return this;
|
||||
},
|
||||
}),
|
||||
dialog_type: 'create_file',
|
||||
supp_types: ['*', 'sql', 'backup'],
|
||||
deps: ['format'],
|
||||
}, {
|
||||
id: 'format',
|
||||
label: gettext('Format'),
|
||||
type: 'text',
|
||||
disabled: false,
|
||||
control: 'select2',
|
||||
select2: {
|
||||
allowClear: false,
|
||||
width: '100%',
|
||||
},
|
||||
options: [{
|
||||
label: gettext('Custom'),
|
||||
value: 'custom',
|
||||
},
|
||||
{
|
||||
label: gettext('Tar'),
|
||||
value: 'tar',
|
||||
},
|
||||
{
|
||||
label: gettext('Plain'),
|
||||
value: 'plain',
|
||||
},
|
||||
{
|
||||
label: gettext('Directory'),
|
||||
value: 'directory',
|
||||
},
|
||||
],
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server') {
|
||||
setTimeout(function() { m.set('format', 'plain'); }, 10);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'ratio',
|
||||
label: gettext('Compression ratio'),
|
||||
type: 'int',
|
||||
min: 0,
|
||||
max: 9,
|
||||
deps: ['format'],
|
||||
disabled: function(m) {
|
||||
return (m.get('format') === 'tar');
|
||||
},
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server')
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'encoding',
|
||||
label: gettext('Encoding'),
|
||||
type: 'text',
|
||||
disabled: false,
|
||||
node: 'database',
|
||||
control: 'node-ajax-options',
|
||||
url: 'get_encodings',
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server') {
|
||||
var t = pgBrowser.tree,
|
||||
i = t.selected(),
|
||||
d = i ? t.itemData(i) : undefined;
|
||||
return _.isUndefined(d) ? false : d.version >= 110000;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'no_of_jobs',
|
||||
label: gettext('Number of jobs'),
|
||||
type: 'int',
|
||||
deps: ['format'],
|
||||
disabled: function(m) {
|
||||
return (m.get('format') !== 'directory');
|
||||
},
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server')
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'role',
|
||||
label: gettext('Role name'),
|
||||
control: 'node-list-by-name',
|
||||
node: 'role',
|
||||
select2: {
|
||||
allowClear: false,
|
||||
},
|
||||
}, {
|
||||
id: 'server_note',
|
||||
label: gettext('Note'),
|
||||
text: gettext('The backup format will be PLAIN'),
|
||||
type: 'note',
|
||||
visible: function(m) {
|
||||
return m.get('type') === 'server';
|
||||
},
|
||||
}, {
|
||||
type: 'nested',
|
||||
control: 'fieldset',
|
||||
label: gettext('Sections'),
|
||||
group: gettext('Dump options'),
|
||||
contentClass: 'row',
|
||||
schema: [{
|
||||
id: 'pre_data',
|
||||
label: gettext('Pre-data'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
group: gettext('Sections'),
|
||||
deps: ['only_data', 'only_schema'],
|
||||
disabled: function(m) {
|
||||
return m.get('only_data') ||
|
||||
m.get('only_schema');
|
||||
},
|
||||
}, {
|
||||
id: 'data',
|
||||
label: gettext('Data'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
group: gettext('Sections'),
|
||||
deps: ['only_data', 'only_schema'],
|
||||
disabled: function(m) {
|
||||
return m.get('only_data') ||
|
||||
m.get('only_schema');
|
||||
},
|
||||
}, {
|
||||
id: 'post_data',
|
||||
label: gettext('Post-data'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
group: gettext('Sections'),
|
||||
deps: ['only_data', 'only_schema'],
|
||||
disabled: function(m) {
|
||||
return m.get('only_data') ||
|
||||
m.get('only_schema');
|
||||
},
|
||||
}],
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server')
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
type: 'nested',
|
||||
control: 'fieldset',
|
||||
label: gettext('Type of objects'),
|
||||
group: gettext('Dump options'),
|
||||
contentClass: 'row',
|
||||
schema: [{
|
||||
id: 'only_data',
|
||||
label: gettext('Only data'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
group: gettext('Type of objects'),
|
||||
deps: ['pre_data', 'data', 'post_data', 'only_schema'],
|
||||
disabled: function(m) {
|
||||
return m.get('pre_data') ||
|
||||
m.get('data') ||
|
||||
m.get('post_data') ||
|
||||
m.get('only_schema');
|
||||
},
|
||||
}, {
|
||||
id: 'only_schema',
|
||||
label: gettext('Only schema'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
group: gettext('Type of objects'),
|
||||
deps: ['pre_data', 'data', 'post_data', 'only_data'],
|
||||
disabled: function(m) {
|
||||
return m.get('pre_data') ||
|
||||
m.get('data') ||
|
||||
m.get('post_data') ||
|
||||
m.get('only_data');
|
||||
},
|
||||
}, {
|
||||
id: 'blobs',
|
||||
label: gettext('Blobs'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Type of objects'),
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server') {
|
||||
setTimeout(function() { m.set('blobs', false); }, 10);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
}],
|
||||
}, {
|
||||
type: 'nested',
|
||||
control: 'fieldset',
|
||||
label: gettext('Do not save'),
|
||||
group: gettext('Dump options'),
|
||||
contentClass: 'row',
|
||||
schema: [{
|
||||
id: 'dns_owner',
|
||||
label: gettext('Owner'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
}, {
|
||||
id: 'dns_privilege',
|
||||
label: gettext('Privilege'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
}, {
|
||||
id: 'dns_tablespace',
|
||||
label: gettext('Tablespace'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
}, {
|
||||
id: 'dns_unlogged_tbl_data',
|
||||
label: gettext('Unlogged table data'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
}, {
|
||||
id: 'no_comments',
|
||||
label: gettext('Comments'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
visible: function() {
|
||||
var t = pgBrowser.tree,
|
||||
i = t.selected(),
|
||||
s = _.isUndefined(i) ? undefined : t.getTreeNodeHierarchy(i)['server'];
|
||||
|
||||
return _.isUndefined(s) ? false : s.version >= 110000;
|
||||
},
|
||||
}],
|
||||
}, {
|
||||
type: 'nested',
|
||||
control: 'fieldset',
|
||||
label: gettext('Queries'),
|
||||
group: gettext('Dump options'),
|
||||
contentClass: 'row',
|
||||
schema: [{
|
||||
id: 'use_column_inserts',
|
||||
label: gettext('Use Column Inserts'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Queries'),
|
||||
}, {
|
||||
id: 'use_insert_commands',
|
||||
label: gettext('Use Insert Commands'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Queries'),
|
||||
}, {
|
||||
id: 'include_create_database',
|
||||
label: gettext('Include CREATE DATABASE statement'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Queries'),
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server')
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'include_drop_database',
|
||||
label: gettext('Include DROP DATABASE statement'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
group: gettext('Queries'),
|
||||
deps: ['only_data'],
|
||||
disabled: function(m) {
|
||||
if (m.get('only_data')) {
|
||||
setTimeout(function() { m.set('include_drop_database', false); }, 10);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}, {
|
||||
id: 'load_via_partition_root',
|
||||
label: gettext('Load Via Partition Root'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Queries'),
|
||||
visible: function(m) {
|
||||
if (!_.isUndefined(m.get('type')) && m.get('type') === 'server')
|
||||
return false;
|
||||
|
||||
var t = pgBrowser.tree,
|
||||
i = t.selected(),
|
||||
s = _.isUndefined(i) ? undefined : t.getTreeNodeHierarchy(i)['server'];
|
||||
|
||||
return _.isUndefined(s) ? false : s.version >= 110000;
|
||||
},
|
||||
}],
|
||||
}, {
|
||||
type: 'nested',
|
||||
control: 'fieldset',
|
||||
label: gettext('Disable'),
|
||||
group: gettext('Dump options'),
|
||||
contentClass: 'row',
|
||||
schema: [{
|
||||
id: 'disable_trigger',
|
||||
label: gettext('Trigger'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
group: gettext('Disable'),
|
||||
deps: ['only_data'],
|
||||
disabled: function(m) {
|
||||
return !(m.get('only_data'));
|
||||
},
|
||||
}, {
|
||||
id: 'disable_quoting',
|
||||
label: gettext('$ quoting'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Disable'),
|
||||
}],
|
||||
}, {
|
||||
type: 'nested',
|
||||
control: 'fieldset',
|
||||
label: gettext('Miscellaneous'),
|
||||
group: gettext('Dump options'),
|
||||
contentClass: 'row',
|
||||
schema: [{
|
||||
id: 'with_oids',
|
||||
label: gettext('With OID(s)'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
deps: ['use_column_inserts', 'use_insert_commands'],
|
||||
group: gettext('Miscellaneous'),
|
||||
disabled: function(m) {
|
||||
var t = pgBrowser.tree,
|
||||
i = t.selected(),
|
||||
s = _.isUndefined(i) ? undefined : t.getTreeNodeHierarchy(i)['server'];
|
||||
|
||||
if (!_.isUndefined(s) && s.version >= 120000)
|
||||
return true;
|
||||
|
||||
if (m.get('use_column_inserts') || m.get('use_insert_commands')) {
|
||||
setTimeout(function() { m.set('with_oids', false); }, 10);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}, {
|
||||
id: 'verbose',
|
||||
label: gettext('Verbose messages'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Miscellaneous'),
|
||||
}, {
|
||||
id: 'dqoute',
|
||||
label: gettext('Force double quote on identifiers'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Miscellaneous'),
|
||||
}, {
|
||||
id: 'use_set_session_auth',
|
||||
label: gettext('Use SET SESSION AUTHORIZATION'),
|
||||
type: 'switch',
|
||||
extraToggleClasses: 'pg-el-sm-6',
|
||||
controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12',
|
||||
controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12',
|
||||
disabled: false,
|
||||
group: gettext('Miscellaneous'),
|
||||
}],
|
||||
}],
|
||||
validate: function() {
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
||||
// Create an Object Backup of pgBrowser class
|
||||
pgBrowser.Backup = {
|
||||
init: function() {
|
||||
@ -574,7 +58,7 @@ define([
|
||||
name: 'backup_global',
|
||||
module: this,
|
||||
applies: ['tools'],
|
||||
callback: 'start_backup_global',
|
||||
callback: 'startBackupGlobal',
|
||||
priority: 12,
|
||||
label: gettext('Backup Globals...'),
|
||||
icon: 'fa fa-save',
|
||||
@ -586,7 +70,7 @@ define([
|
||||
name: 'backup_server',
|
||||
module: this,
|
||||
applies: ['tools'],
|
||||
callback: 'start_backup_server',
|
||||
callback: 'startBackupServer',
|
||||
priority: 12,
|
||||
label: gettext('Backup Server...'),
|
||||
icon: 'fa fa-save',
|
||||
@ -599,7 +83,7 @@ define([
|
||||
module: this,
|
||||
node: 'server',
|
||||
applies: ['context'],
|
||||
callback: 'start_backup_global',
|
||||
callback: 'startBackupGlobal',
|
||||
priority: 12,
|
||||
label: gettext('Backup Globals...'),
|
||||
icon: 'fa fa-save',
|
||||
@ -612,7 +96,7 @@ define([
|
||||
module: this,
|
||||
node: 'server',
|
||||
applies: ['context'],
|
||||
callback: 'start_backup_server',
|
||||
callback: 'startBackupServer',
|
||||
priority: 12,
|
||||
label: gettext('Backup Server...'),
|
||||
icon: 'fa fa-save',
|
||||
@ -624,7 +108,7 @@ define([
|
||||
name: 'backup_object',
|
||||
module: this,
|
||||
applies: ['tools'],
|
||||
callback: 'backup_objects',
|
||||
callback: 'backupObjects',
|
||||
priority: 11,
|
||||
label: gettext('Backup...'),
|
||||
icon: 'fa fa-save',
|
||||
@ -642,7 +126,7 @@ define([
|
||||
node: menuUtils.backupSupportedNodes[idx],
|
||||
module: this,
|
||||
applies: ['context'],
|
||||
callback: 'backup_objects',
|
||||
callback: 'backupObjects',
|
||||
priority: 11,
|
||||
label: gettext('Backup...'),
|
||||
icon: 'fa fa-save',
|
||||
@ -655,34 +139,161 @@ define([
|
||||
pgBrowser.add_menus(menus);
|
||||
return this;
|
||||
},
|
||||
start_backup_global: function(action, item) {
|
||||
let dialog = new globalBackupDialog.BackupDialog(
|
||||
pgBrowser,
|
||||
$,
|
||||
alertify,
|
||||
BackupModel
|
||||
);
|
||||
dialog.draw(action, item, {'globals': true}, pgBrowser.stdW.calc(pgBrowser.stdW.md), pgBrowser.stdH.calc(pgBrowser.stdH.md));
|
||||
startBackupGlobal: function(action, treeItem) {
|
||||
pgBrowser.Node.registerUtilityPanel();
|
||||
var panel = pgBrowser.Node.addUtilityPanel();
|
||||
var tree = pgBrowser.tree,
|
||||
i = treeItem || tree.selected(),
|
||||
data = i ? tree.itemData(i) : undefined,
|
||||
j = panel.$container.find('.obj_properties').first();
|
||||
|
||||
var schema = this.getGlobalUISchema(treeItem);
|
||||
panel.title('Backup Globals');
|
||||
panel.focus();
|
||||
var typeOfDialog = 'globals';
|
||||
var serverIdentifier = this.retrieveServerIdentifier();
|
||||
|
||||
var extraData = this.setExtraParameters(typeOfDialog);
|
||||
this.showBackupDialog(schema, treeItem, j, data, panel, typeOfDialog, serverIdentifier, extraData);
|
||||
},
|
||||
start_backup_server: function(action, item) {
|
||||
let dialog = new globalBackupDialog.BackupDialog(
|
||||
pgBrowser,
|
||||
$,
|
||||
alertify,
|
||||
BackupObjectModel
|
||||
);
|
||||
dialog.draw(action, item, {'server': true}, pgBrowser.stdW.calc(pgBrowser.stdW.md), pgBrowser.stdH.calc(pgBrowser.stdH.md));
|
||||
startBackupServer: function(action, treeItem) {
|
||||
pgBrowser.Node.registerUtilityPanel();
|
||||
var panel = pgBrowser.Node.addUtilityPanel();
|
||||
var tree = pgBrowser.tree,
|
||||
i = treeItem || tree.selected(),
|
||||
data = i ? tree.itemData(i) : undefined,
|
||||
j = panel.$container.find('.obj_properties').first();
|
||||
|
||||
var schema = this.getUISchema(treeItem, 'server');
|
||||
panel.title(gettext('Backup Server'));
|
||||
panel.focus();
|
||||
var typeOfDialog = 'server';
|
||||
var serverIdentifier = this.retrieveServerIdentifier();
|
||||
|
||||
var extraData = this.setExtraParameters(typeOfDialog);
|
||||
this.showBackupDialog(schema, treeItem, j, data, panel, typeOfDialog, serverIdentifier, extraData);
|
||||
},
|
||||
saveCallBack: function(data, dialog) {
|
||||
pgBrowser.Events.trigger('pgadmin-bgprocess:created', dialog);
|
||||
},
|
||||
showBackupDialog: function(schema, item, j, data, panel, typeOfDialog, serverIdentifier, extraData) {
|
||||
if(schema) {
|
||||
let treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(item);
|
||||
removeNodeView(j[0]);
|
||||
|
||||
let urlShortcut = 'backup.create_server_job';
|
||||
if (typeOfDialog === 'backup_objects') {
|
||||
urlShortcut = 'backup.create_object_job';
|
||||
}
|
||||
const baseUrl = url_for(urlShortcut, {
|
||||
'sid': serverIdentifier,
|
||||
});
|
||||
var sqlHelpUrl = 'backup.html';
|
||||
var helpUrl = url_for('help.static', {
|
||||
'filename': this.getHelpFile(typeOfDialog),
|
||||
});
|
||||
getUtilityView(
|
||||
schema, treeNodeInfo, 'create', 'dialog', j[0], panel, this.saveCallBack, extraData, 'Backup', baseUrl, sqlHelpUrl, helpUrl);
|
||||
}
|
||||
},
|
||||
// Callback to draw Backup Dialog for objects
|
||||
backup_objects: function(action, treeItem) {
|
||||
let dialog = new globalBackupDialog.BackupDialog(
|
||||
pgBrowser,
|
||||
$,
|
||||
alertify,
|
||||
BackupObjectModel
|
||||
);
|
||||
dialog.draw(action, treeItem, null, pgBrowser.stdW.calc(pgBrowser.stdW.md), pgBrowser.stdH.calc(pgBrowser.stdH.md));
|
||||
backupObjects: function(action, treeItem) {
|
||||
pgBrowser.Node.registerUtilityPanel();
|
||||
var panel = pgBrowser.Node.addUtilityPanel();
|
||||
var tree = pgBrowser.tree,
|
||||
i = treeItem || tree.selected(),
|
||||
data = i ? tree.itemData(i) : undefined,
|
||||
j = panel.$container.find('.obj_properties').first();
|
||||
|
||||
var schema = this.getUISchema(treeItem, 'backup_objects');
|
||||
panel.title(`Backup (${pgBrowser.Nodes[data._type].label}: ${data.label})`);
|
||||
panel.focus();
|
||||
|
||||
var typeOfDialog = 'backup_objects';
|
||||
var serverIdentifier = this.retrieveServerIdentifier();
|
||||
|
||||
var extraData = this.setExtraParameters(typeOfDialog);
|
||||
this.showBackupDialog(schema, treeItem, j, data, panel, typeOfDialog, serverIdentifier, extraData);
|
||||
|
||||
},
|
||||
getUISchema: function(treeItem, backupType) {
|
||||
let treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(treeItem);
|
||||
const selectedNode = pgBrowser.tree.selected();
|
||||
let itemNodeData = pgBrowser.tree.findNodeByDomElement(selectedNode).getData();
|
||||
return new BackupSchema(
|
||||
()=> getSectionSchema(),
|
||||
()=> getTypeObjSchema({backupType: backupType}),
|
||||
()=> getSaveOptSchema({nodeInfo: treeNodeInfo}),
|
||||
()=> getQueryOptionSchema({nodeInfo: treeNodeInfo, backupType: backupType}),
|
||||
()=> getDisabledOptionSchema({nodeInfo: treeNodeInfo}),
|
||||
()=> getMiscellaneousSchema({nodeInfo: treeNodeInfo}),
|
||||
{
|
||||
role: ()=>getNodeListByName('role', treeNodeInfo, itemNodeData),
|
||||
encoding: ()=>getNodeAjaxOptions('get_encodings', pgBrowser.Nodes['database'], treeNodeInfo, itemNodeData, {
|
||||
cacheNode: 'database',
|
||||
cacheLevel: 'server',
|
||||
}),
|
||||
},
|
||||
treeNodeInfo,
|
||||
pgBrowser,
|
||||
backupType
|
||||
);
|
||||
},
|
||||
getGlobalUISchema: function(treeItem) {
|
||||
let treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(treeItem);
|
||||
const selectedNode = pgBrowser.tree.selected();
|
||||
let itemNodeData = pgBrowser.tree.findNodeByDomElement(selectedNode).getData();
|
||||
return new BackupGlobalSchema(
|
||||
()=> getMiscellaneousGlobalSchema(),
|
||||
{
|
||||
role: ()=>getNodeListByName('role', treeNodeInfo, itemNodeData),
|
||||
}
|
||||
);
|
||||
},
|
||||
retrieveServerIdentifier() {
|
||||
const selectedNode = pgBrowser.tree.selected();
|
||||
|
||||
var node = pgBrowser.tree.findNodeByDomElement(selectedNode);
|
||||
const treeInfo = pgBrowser.tree.getTreeNodeHierarchy(node);
|
||||
return treeInfo.server._id;
|
||||
},
|
||||
setExtraParameters(typeOfDialog) {
|
||||
var extraData = {};
|
||||
const selectedNode = pgBrowser.tree.selected();
|
||||
var selectedTreeNode = pgBrowser.tree.findNodeByDomElement(selectedNode);
|
||||
const treeInfo = pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode);
|
||||
if (typeOfDialog === 'backup_objects') {
|
||||
|
||||
extraData['database'] = treeInfo.database._label;
|
||||
|
||||
const nodeData = selectedTreeNode.getData();
|
||||
if (nodeData._type === 'schema') {
|
||||
extraData['schemas'] = [nodeData._label];
|
||||
}
|
||||
|
||||
if (nodeData._type === 'table' || nodeData._type === 'partition') {
|
||||
extraData['tables'] = [[treeInfo.schema._label, nodeData._label]];
|
||||
}
|
||||
|
||||
/*(if (_.isEmpty(this.view.model.get('ratio'))) {
|
||||
this.view.model.unset('ratio');
|
||||
}*/
|
||||
} else if(typeOfDialog === 'server') {
|
||||
extraData['type'] = 'server';
|
||||
} else if(typeOfDialog === 'globals') {
|
||||
extraData['type'] = 'globals';
|
||||
}
|
||||
|
||||
return extraData;
|
||||
},
|
||||
getHelpFile: function (dialog_type) {
|
||||
if (dialog_type == 'globals') {
|
||||
return 'backup_globals_dialog.html';
|
||||
} else if (dialog_type == 'server') {
|
||||
return 'backup_server_dialog.html';
|
||||
}
|
||||
return 'backup_dialog.html';
|
||||
}
|
||||
};
|
||||
return pgBrowser.Backup;
|
||||
});
|
||||
|
560
web/pgadmin/tools/backup/static/js/backup.ui.js
Normal file
@ -0,0 +1,560 @@
|
||||
import gettext from 'sources/gettext';
|
||||
import BaseUISchema from 'sources/SchemaView/base_schema.ui';
|
||||
import { isEmptyString } from 'sources/validators';
|
||||
|
||||
export class SectionSchema extends BaseUISchema {
|
||||
constructor(fieldOptions={}, initValues) {
|
||||
super({
|
||||
...initValues,
|
||||
});
|
||||
|
||||
this.fieldOptions = {
|
||||
...fieldOptions,
|
||||
};
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'id';
|
||||
}
|
||||
|
||||
|
||||
get baseFields() {
|
||||
return [
|
||||
{
|
||||
id: 'pre_data',
|
||||
label: gettext('Pre-data'),
|
||||
type: 'switch',
|
||||
group: gettext('Sections'),
|
||||
deps: ['only_data', 'only_schema'],
|
||||
disabled: function(state) {
|
||||
return state.only_data ||
|
||||
state.only_schema;
|
||||
},
|
||||
}, {
|
||||
id: 'data',
|
||||
label: gettext('Data'),
|
||||
type: 'switch',
|
||||
group: gettext('Sections'),
|
||||
deps: ['only_data', 'only_schema'],
|
||||
disabled: function(state) {
|
||||
return state.only_data ||
|
||||
state.only_schema;
|
||||
},
|
||||
}, {
|
||||
id: 'post_data',
|
||||
label: gettext('Post-data'),
|
||||
type: 'switch',
|
||||
group: gettext('Sections'),
|
||||
deps: ['only_data', 'only_schema'],
|
||||
disabled: function(state) {
|
||||
return state.only_data ||
|
||||
state.only_schema;
|
||||
},
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
export function getSectionSchema() {
|
||||
return new SectionSchema();
|
||||
}
|
||||
|
||||
export class TypeObjSchema extends BaseUISchema {
|
||||
constructor(fieldOptions={}) {
|
||||
super();
|
||||
|
||||
this.fieldOptions = {
|
||||
backupType: null,
|
||||
...fieldOptions,
|
||||
};
|
||||
|
||||
this.backupType = this.fieldOptions.backupType;
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'id';
|
||||
}
|
||||
|
||||
|
||||
get baseFields() {
|
||||
let obj = this;
|
||||
return [{
|
||||
id: 'only_data',
|
||||
label: gettext('Only data'),
|
||||
type: 'switch',
|
||||
group: gettext('Type of objects'),
|
||||
deps: ['pre_data', 'data', 'post_data', 'only_schema'],
|
||||
disabled: function(state) {
|
||||
return state.pre_data ||
|
||||
state.data ||
|
||||
state.post_data ||
|
||||
state.only_schema;
|
||||
},
|
||||
}, {
|
||||
id: 'only_schema',
|
||||
label: gettext('Only schema'),
|
||||
type: 'switch',
|
||||
group: gettext('Type of objects'),
|
||||
deps: ['pre_data', 'data', 'post_data', 'only_data'],
|
||||
disabled: function(state) {
|
||||
return state.pre_data ||
|
||||
state.data ||
|
||||
state.post_data ||
|
||||
state.only_data;
|
||||
},
|
||||
}, {
|
||||
id: 'blobs',
|
||||
label: gettext('Blobs'),
|
||||
type: 'switch',
|
||||
group: gettext('Type of objects'),
|
||||
visible: function(state) {
|
||||
if (!_.isUndefined(obj.backupType) && obj.backupType === 'server') {
|
||||
state.blobs = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
export function getTypeObjSchema(fieldOptions) {
|
||||
return new TypeObjSchema(fieldOptions);
|
||||
}
|
||||
|
||||
export class SaveOptSchema extends BaseUISchema {
|
||||
constructor(fieldOptions={}, initValues) {
|
||||
super({
|
||||
id: null,
|
||||
...initValues,
|
||||
});
|
||||
|
||||
this.fieldOptions = {
|
||||
nodeInfo: null,
|
||||
...fieldOptions,
|
||||
};
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'id';
|
||||
}
|
||||
|
||||
|
||||
get baseFields() {
|
||||
let obj = this;
|
||||
return [{
|
||||
id: 'dns_owner',
|
||||
label: gettext('Owner'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
}, {
|
||||
id: 'dns_privilege',
|
||||
label: gettext('Privilege'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
}, {
|
||||
id: 'dns_tablespace',
|
||||
label: gettext('Tablespace'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
}, {
|
||||
id: 'dns_unlogged_tbl_data',
|
||||
label: gettext('Unlogged table data'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
}, {
|
||||
id: 'no_comments',
|
||||
label: gettext('Comments'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Do not save'),
|
||||
visible: function() {
|
||||
var serverInfo = _.isUndefined(obj.fieldOptions.nodeInfo) ? undefined : obj.fieldOptions.nodeInfo.server;
|
||||
|
||||
return _.isUndefined(serverInfo) ? false : serverInfo.version >= 110000;
|
||||
},
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
export function getSaveOptSchema(fieldOptions) {
|
||||
return new SaveOptSchema(fieldOptions);
|
||||
}
|
||||
|
||||
export class QueryOptionSchema extends BaseUISchema {
|
||||
constructor(fieldOptions={}, initValues) {
|
||||
super({
|
||||
id: null,
|
||||
...initValues,
|
||||
});
|
||||
|
||||
this.fieldOptions = {
|
||||
nodeInfo: null,
|
||||
backupType: null,
|
||||
...fieldOptions,
|
||||
};
|
||||
this.backupType = fieldOptions.backupType;
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'id';
|
||||
}
|
||||
|
||||
|
||||
get baseFields() {
|
||||
let obj = this;
|
||||
return [{
|
||||
id: 'use_column_inserts',
|
||||
label: gettext('Use Column Inserts'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Queries'),
|
||||
}, {
|
||||
id: 'use_insert_commands',
|
||||
label: gettext('Use Insert Commands'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Queries'),
|
||||
}, {
|
||||
id: 'include_create_database',
|
||||
label: gettext('Include CREATE DATABASE statement'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Queries'),
|
||||
visible: function() {
|
||||
if (!_.isUndefined(obj.backupType) && obj.backupType === 'server')
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'include_drop_database',
|
||||
label: gettext('Include DROP DATABASE statement'),
|
||||
type: 'switch',
|
||||
group: gettext('Queries'),
|
||||
deps: ['only_data'],
|
||||
disabled: function(state) {
|
||||
if (state.only_data) {
|
||||
state.include_drop_database = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}, {
|
||||
id: 'load_via_partition_root',
|
||||
label: gettext('Load Via Partition Root'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Queries'),
|
||||
visible: function() {
|
||||
if (!_.isUndefined(obj.backupType) && obj.backupType === 'server')
|
||||
return false;
|
||||
|
||||
var serverInfo = _.isUndefined(obj.fieldOptions.nodeInfo) ? undefined : obj.fieldOptions.nodeInfo.server;
|
||||
|
||||
return _.isUndefined(serverInfo) ? false : serverInfo.version >= 110000;
|
||||
},
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
export function getQueryOptionSchema(fieldOptions) {
|
||||
return new QueryOptionSchema(fieldOptions);
|
||||
}
|
||||
|
||||
export class DisabledOptionSchema extends BaseUISchema {
|
||||
constructor(fieldOptions={}, initValues) {
|
||||
super({
|
||||
id: null,
|
||||
...initValues,
|
||||
});
|
||||
|
||||
this.fieldOptions = {
|
||||
nodeInfo: null,
|
||||
...fieldOptions,
|
||||
};
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'id';
|
||||
}
|
||||
|
||||
|
||||
get baseFields() {
|
||||
return [{
|
||||
id: 'disable_trigger',
|
||||
label: gettext('Trigger'),
|
||||
type: 'switch',
|
||||
group: gettext('Disable'),
|
||||
deps: ['only_data'],
|
||||
disabled: function(state) {
|
||||
return !(state.only_data);
|
||||
},
|
||||
}, {
|
||||
id: 'disable_quoting',
|
||||
label: gettext('$ quoting'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Disable'),
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
export function getDisabledOptionSchema(fieldOptions) {
|
||||
return new DisabledOptionSchema(fieldOptions);
|
||||
}
|
||||
|
||||
export class MiscellaneousSchema extends BaseUISchema {
|
||||
constructor(fieldOptions={}, initValues) {
|
||||
super({
|
||||
id: null,
|
||||
verbose: true,
|
||||
...initValues,
|
||||
});
|
||||
|
||||
this.fieldOptions = {
|
||||
nodeInfo: null,
|
||||
...fieldOptions,
|
||||
};
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'id';
|
||||
}
|
||||
|
||||
|
||||
get baseFields() {
|
||||
let obj = this;
|
||||
return [{
|
||||
id: 'with_oids',
|
||||
label: gettext('With OID(s)'),
|
||||
type: 'switch',
|
||||
deps: ['use_column_inserts', 'use_insert_commands'],
|
||||
group: gettext('Miscellaneous'),
|
||||
disabled: function(state) {
|
||||
var serverInfo = _.isUndefined(obj.fieldOptions.nodeInfo) ? undefined : obj.fieldOptions.nodeInfo.server;
|
||||
|
||||
if (!_.isUndefined(serverInfo) && serverInfo.version >= 120000)
|
||||
return true;
|
||||
|
||||
if (state.use_column_inserts || state.use_insert_commands) {
|
||||
state.with_oids = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}, {
|
||||
id: 'verbose',
|
||||
label: gettext('Verbose messages'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Miscellaneous'),
|
||||
}, {
|
||||
id: 'dqoute',
|
||||
label: gettext('Force double quote on identifiers'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Miscellaneous'),
|
||||
}, {
|
||||
id: 'use_set_session_auth',
|
||||
label: gettext('Use SET SESSION AUTHORIZATION'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Miscellaneous'),
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
export function getMiscellaneousSchema(fieldOptions) {
|
||||
return new MiscellaneousSchema(fieldOptions);
|
||||
}
|
||||
|
||||
export default class BackupSchema extends BaseUISchema {
|
||||
constructor(getSectionSchema, getTypeObjSchema, getSaveOptSchema, getQueryOptionSchema, getDisabledOptionSchema, getMiscellaneousSchema, fieldOptions = {}, treeNodeInfo, pgBrowser, backupType) {
|
||||
super({
|
||||
file: undefined,
|
||||
format: 'custom',
|
||||
id: null,
|
||||
blobs: true,
|
||||
verbose: true,
|
||||
});
|
||||
|
||||
this.fieldOptions = {
|
||||
encoding: null,
|
||||
role: null,
|
||||
...fieldOptions,
|
||||
};
|
||||
|
||||
this.treeNodeInfo = treeNodeInfo;
|
||||
this.pgBrowser = pgBrowser;
|
||||
this.backupType = backupType;
|
||||
this.getSectionSchema = getSectionSchema;
|
||||
this.getTypeObjSchema = getTypeObjSchema;
|
||||
this.getSaveOptSchema = getSaveOptSchema;
|
||||
this.getQueryOptionSchema = getQueryOptionSchema;
|
||||
this.getDisabledOptionSchema = getDisabledOptionSchema;
|
||||
this.getMiscellaneousSchema = getMiscellaneousSchema;
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'id';
|
||||
}
|
||||
|
||||
get baseFields() {
|
||||
var obj = this;
|
||||
return [{
|
||||
id: 'file',
|
||||
label: gettext('Filename'),
|
||||
type: 'file',
|
||||
disabled: false,
|
||||
controlProps: {
|
||||
dialogType: 'create_file',
|
||||
supportedTypes: ['*', 'sql', 'backup'],
|
||||
dialogTitle: 'Select file',
|
||||
},
|
||||
deps: ['format'],
|
||||
}, {
|
||||
id: 'format',
|
||||
label: gettext('Format'),
|
||||
type: 'select',
|
||||
disabled: false,
|
||||
controlProps: { allowClear: false, width: '100%' },
|
||||
options: [
|
||||
{
|
||||
label: gettext('Custom'),
|
||||
value: 'custom',
|
||||
},
|
||||
{
|
||||
label: gettext('Tar'),
|
||||
value: 'tar',
|
||||
},
|
||||
{
|
||||
label: gettext('Plain'),
|
||||
value: 'plain',
|
||||
},
|
||||
{
|
||||
label: gettext('Directory'),
|
||||
value: 'directory',
|
||||
},
|
||||
],
|
||||
visible: function(state) {
|
||||
if (!_.isUndefined(obj.backupType) && obj.backupType === 'server') {
|
||||
state.format = 'plain';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'ratio',
|
||||
label: gettext('Compression ratio'),
|
||||
type: 'int',
|
||||
min: 0,
|
||||
max: 9,
|
||||
deps: ['format'],
|
||||
disabled: function(state) {
|
||||
return (state.format === 'tar');
|
||||
},
|
||||
visible: function() {
|
||||
if (!_.isUndefined(obj.backupType) && obj.backupType === 'server')
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'encoding',
|
||||
label: gettext('Encoding'),
|
||||
type: 'select',
|
||||
disabled: false,
|
||||
options: obj.fieldOptions.encoding,
|
||||
visible: function() {
|
||||
if (!_.isUndefined(obj.backupType) && obj.backupType === 'server') {
|
||||
var dbNode = obj.pgBrowser.serverInfo[obj.treeNodeInfo.server._id];
|
||||
return _.isUndefined(dbNode) ? false : dbNode.version >= 110000;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'no_of_jobs',
|
||||
label: gettext('Number of jobs'),
|
||||
type: 'int',
|
||||
deps: ['format'],
|
||||
disabled: function(state) {
|
||||
return (state.format !== 'directory');
|
||||
},
|
||||
visible: function() {
|
||||
if (!_.isUndefined(obj.backupType) && obj.backupType === 'server')
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
id: 'role',
|
||||
label: gettext('Role name'),
|
||||
type: 'select',
|
||||
options: obj.fieldOptions.role,
|
||||
controlProps: {
|
||||
allowClear: false,
|
||||
},
|
||||
}, {
|
||||
id: 'server_note',
|
||||
label: gettext('Note'),
|
||||
text: gettext('The backup format will be PLAIN'),
|
||||
type: 'note',
|
||||
visible: function() {
|
||||
return obj.backupType === 'server';
|
||||
},
|
||||
}, {
|
||||
type: 'nested-fieldset',
|
||||
label: gettext('Sections'),
|
||||
group: gettext('Dump options'),
|
||||
schema:new getSectionSchema(),
|
||||
visible: function() {
|
||||
if (!_.isUndefined(obj.backupType) && obj.backupType === 'server')
|
||||
return false;
|
||||
return true;
|
||||
},
|
||||
}, {
|
||||
type: 'nested-fieldset',
|
||||
label: gettext('Type of objects'),
|
||||
group: gettext('Dump options'),
|
||||
schema: obj.getTypeObjSchema()
|
||||
}, {
|
||||
type: 'nested-fieldset',
|
||||
label: gettext('Do not save'),
|
||||
group: gettext('Dump options'),
|
||||
schema: obj.getSaveOptSchema(),
|
||||
}, {
|
||||
type: 'nested-fieldset',
|
||||
label: gettext('Queries'),
|
||||
group: gettext('Dump options'),
|
||||
schema: obj.getQueryOptionSchema(),
|
||||
}, {
|
||||
type: 'nested-fieldset',
|
||||
label: gettext('Disable'),
|
||||
group: gettext('Dump options'),
|
||||
schema: obj.getDisabledOptionSchema(),
|
||||
}, {
|
||||
type: 'nested-fieldset',
|
||||
label: gettext('Miscellaneous'),
|
||||
group: gettext('Dump options'),
|
||||
schema: obj.getMiscellaneousSchema(),
|
||||
}];
|
||||
}
|
||||
|
||||
validate(state, setError) {
|
||||
if (isEmptyString(state.service)) {
|
||||
let errmsg = null;
|
||||
/* events validation*/
|
||||
if (!state.file) {
|
||||
errmsg = gettext('Please provide a filename.');
|
||||
setError('file', errmsg);
|
||||
return true;
|
||||
} else {
|
||||
errmsg = null;
|
||||
setError('file', errmsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
108
web/pgadmin/tools/backup/static/js/backupGlobal.ui.js
Normal file
@ -0,0 +1,108 @@
|
||||
import gettext from 'sources/gettext';
|
||||
import BaseUISchema from 'sources/SchemaView/base_schema.ui';
|
||||
import { isEmptyString } from 'sources/validators';
|
||||
|
||||
export class MiscellaneousSchema extends BaseUISchema {
|
||||
constructor(fieldOptions={}) {
|
||||
super();
|
||||
|
||||
this.fieldOptions = {
|
||||
...fieldOptions,
|
||||
};
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'id';
|
||||
}
|
||||
|
||||
|
||||
get baseFields() {
|
||||
return [{
|
||||
id: 'verbose',
|
||||
label: gettext('Verbose messages'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Miscellaneous'),
|
||||
}, {
|
||||
id: 'dqoute',
|
||||
label: gettext('Force double quote on identifiers'),
|
||||
type: 'switch',
|
||||
disabled: false,
|
||||
group: gettext('Miscellaneous')
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
export function getMiscellaneousSchema() {
|
||||
return new MiscellaneousSchema();
|
||||
}
|
||||
|
||||
export default class BackupGlobalSchema extends BaseUISchema {
|
||||
constructor(getMiscellaneousSchema, fieldOptions = {}) {
|
||||
super({
|
||||
id: null,
|
||||
verbose: true,
|
||||
});
|
||||
|
||||
this.fieldOptions = {
|
||||
role: null,
|
||||
...fieldOptions,
|
||||
};
|
||||
|
||||
this.getMiscellaneousSchema = getMiscellaneousSchema;
|
||||
}
|
||||
|
||||
get idAttribute() {
|
||||
return 'id';
|
||||
}
|
||||
|
||||
get baseFields() {
|
||||
var obj = this;
|
||||
return [{
|
||||
id: 'file',
|
||||
label: gettext('Filename'),
|
||||
type: 'file',
|
||||
disabled: false,
|
||||
controlProps: {
|
||||
dialogType: 'create_file',
|
||||
supportedTypes: ['*', 'sql', 'backup'],
|
||||
dialogTitle: 'Select file',
|
||||
},
|
||||
dialog_title: 'Select file',
|
||||
}, {
|
||||
id: 'role',
|
||||
label: gettext('Role name'),
|
||||
type: 'select',
|
||||
options: obj.fieldOptions.role,
|
||||
controlProps: {
|
||||
allowClear: false,
|
||||
},
|
||||
}, {
|
||||
type: 'nested-fieldset',
|
||||
label: gettext('Miscellaneous'),
|
||||
contentClass: 'row',
|
||||
schema: obj.getMiscellaneousSchema(),
|
||||
}, {
|
||||
id: 'globals_note',
|
||||
label: gettext('Note'),
|
||||
text: gettext('Only objects global to the entire database will be backed up, in PLAIN format'),
|
||||
type: 'note',
|
||||
}];
|
||||
}
|
||||
|
||||
validate(state, setError) {
|
||||
if (isEmptyString(state.service)) {
|
||||
let errmsg = null;
|
||||
/* validation */
|
||||
if (!state.file) {
|
||||
errmsg = gettext('Please provide a filename.');
|
||||
setError('file', errmsg);
|
||||
return true;
|
||||
} else {
|
||||
errmsg = null;
|
||||
setError('file', errmsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import gettext from '../../../../static/js/gettext';
|
||||
import Backform from '../../../../static/js/backform.pgadmin';
|
||||
import {Dialog} from '../../../../static/js/alertify/dialog';
|
||||
import url_for from 'sources/url_for';
|
||||
import axios from 'axios/index';
|
||||
import {retrieveAncestorOfTypeServer} from 'sources/tree/tree_utils';
|
||||
import {hasBinariesConfiguration} from 'sources/utils';
|
||||
|
||||
export class BackupDialog extends Dialog {
|
||||
constructor(pgBrowser, $, alertify, BackupModel, backform = Backform) {
|
||||
super(gettext('Backup Error'),
|
||||
'<div class=\'backup_dialog\'></div>',
|
||||
pgBrowser, $, alertify, BackupModel, backform
|
||||
);
|
||||
}
|
||||
|
||||
url_for_utility_exists(id, params){
|
||||
return url_for('backup.utility_exists', {
|
||||
'sid': id,
|
||||
'backup_obj_type': params == null ? 'objects' : 'servers',
|
||||
});
|
||||
}
|
||||
|
||||
draw(action, aciTreeItem, params, width=0, height=0) {
|
||||
const serverInformation = retrieveAncestorOfTypeServer(this.pgBrowser, aciTreeItem, gettext('Backup Error'), this.alertify);
|
||||
|
||||
if (!serverInformation) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasBinariesConfiguration(this.pgBrowser, serverInformation, this.alertify)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var sid = serverInformation._type == 'database' ? serverInformation._pid : serverInformation._id;
|
||||
const baseUrl = this.url_for_utility_exists(sid, params);
|
||||
// Check pg_dump or pg_dumpall utility exists or not.
|
||||
let that = this;
|
||||
axios.get(
|
||||
baseUrl
|
||||
).then(function(res) {
|
||||
if (!res.data.success) {
|
||||
that.alertify.alert(
|
||||
gettext('Utility not found'),
|
||||
res.data.errormsg
|
||||
);
|
||||
return;
|
||||
}
|
||||
const typeOfDialog = BackupDialog.typeOfDialog(params);
|
||||
|
||||
if (!that.canExecuteOnCurrentDatabase(aciTreeItem)) {
|
||||
return;
|
||||
}
|
||||
const dialog = that.createOrGetDialog(
|
||||
BackupDialog.dialogTitle(typeOfDialog),
|
||||
typeOfDialog
|
||||
);
|
||||
dialog(true).resizeTo(width, height);
|
||||
}).catch(function() {
|
||||
that.alertify.alert(
|
||||
gettext('Utility not found'),
|
||||
gettext('Failed to fetch Utility information')
|
||||
);
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
static typeOfDialog(params) {
|
||||
if (params === null) {
|
||||
return 'backup_objects';
|
||||
}
|
||||
let typeOfDialog = 'server';
|
||||
if (!_.isUndefined(params['globals']) && params['globals']) {
|
||||
typeOfDialog = 'globals';
|
||||
}
|
||||
return typeOfDialog;
|
||||
}
|
||||
|
||||
static dialogTitle(typeOfDialog) {
|
||||
if (typeOfDialog === 'backup_objects') {
|
||||
return null;
|
||||
}
|
||||
return ((typeOfDialog === 'globals') ?
|
||||
gettext('Backup Globals...') :
|
||||
gettext('Backup Server...'));
|
||||
}
|
||||
|
||||
dialogName(typeOfDialog) {
|
||||
if (typeOfDialog === 'backup_objects') {
|
||||
return typeOfDialog;
|
||||
}
|
||||
return 'BackupDialog_' + typeOfDialog;
|
||||
}
|
||||
}
|
@ -1,317 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import axios from 'axios/index';
|
||||
import gettext from '../../../../static/js/gettext';
|
||||
import url_for from '../../../../static/js/url_for';
|
||||
import _ from 'underscore';
|
||||
import {DialogWrapper} from '../../../../static/js/alertify/dialog_wrapper';
|
||||
import {fetch_ticket_lifetime} from '../../../../authenticate/static/js/kerberos';
|
||||
import userInfo from 'pgadmin.user_management.current_user';
|
||||
import pgConst from 'pgadmin.browser.constants';
|
||||
|
||||
export class BackupDialogWrapper extends DialogWrapper {
|
||||
constructor(dialogContainerSelector, dialogTitle, typeOfDialog,
|
||||
jquery, pgBrowser, alertify, dialogModel, backform) {
|
||||
super(dialogContainerSelector, dialogTitle, jquery,
|
||||
pgBrowser, alertify, dialogModel, backform);
|
||||
this.typeOfDialog = typeOfDialog;
|
||||
}
|
||||
|
||||
main(title) {
|
||||
this.set('title', title);
|
||||
}
|
||||
|
||||
setup() {
|
||||
let get_help_file = function (dialog_type) {
|
||||
if (dialog_type == 'globals') {
|
||||
return 'backup_globals_dialog.html';
|
||||
} else if (dialog_type == 'server') {
|
||||
return 'backup_server_dialog.html';
|
||||
}
|
||||
return 'backup_dialog.html';
|
||||
};
|
||||
return {
|
||||
buttons: [{
|
||||
text: '',
|
||||
className: 'btn btn-primary-icon pull-left fa fa-info pg-alertify-icon-button',
|
||||
attrs: {
|
||||
name: 'object_help',
|
||||
type: 'button',
|
||||
url: 'backup.html',
|
||||
label: gettext('Backup'),
|
||||
'aria-label': gettext('Backup'),
|
||||
},
|
||||
}, {
|
||||
text: '',
|
||||
key: 112,
|
||||
className: 'btn btn-primary-icon pull-left fa fa-question pg-alertify-icon-button',
|
||||
attrs: {
|
||||
name: 'dialog_help',
|
||||
type: 'button',
|
||||
label: gettext('Help'),
|
||||
'aria-label': gettext('Help'),
|
||||
url: url_for('help.static', {
|
||||
'filename': get_help_file(this.typeOfDialog),
|
||||
}),
|
||||
},
|
||||
}, {
|
||||
text: gettext('Cancel'),
|
||||
key: 27,
|
||||
className: 'btn btn-secondary fa fa-lg fa-times pg-alertify-button',
|
||||
'data-btn-name': 'cancel',
|
||||
}, {
|
||||
text: gettext('Backup'),
|
||||
key: 13,
|
||||
className: 'btn btn-primary fa fa-lg fa-save pg-alertify-button',
|
||||
'data-btn-name': 'backup',
|
||||
}],
|
||||
// Set options for dialog
|
||||
options: {
|
||||
title: this.dialogTitle,
|
||||
//disable both padding and overflow control.
|
||||
padding: !1,
|
||||
overflow: !1,
|
||||
model: 0,
|
||||
resizable: true,
|
||||
maximizable: true,
|
||||
pinnable: false,
|
||||
closableByDimmer: false,
|
||||
modal: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
prepare() {
|
||||
this.disableBackupButton();
|
||||
|
||||
const $container = this.jquery(this.dialogContainerSelector);
|
||||
const selectedTreeNode = this.getSelectedNode();
|
||||
const selectedTreeNodeData = this.getSelectedNodeData(selectedTreeNode);
|
||||
if (!selectedTreeNodeData) {
|
||||
return;
|
||||
}
|
||||
|
||||
const node = this.pgBrowser.Nodes[selectedTreeNodeData._type];
|
||||
if (this.dialogTitle === null) {
|
||||
let title = gettext('Backup (%s: %s)', node.label, selectedTreeNodeData.label);
|
||||
this.main(title);
|
||||
}
|
||||
|
||||
const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode);
|
||||
const dialog = this.createDialog(node, treeInfo, this.typeOfDialog, $container);
|
||||
this.addAlertifyClassToBackupNodeChildNodes();
|
||||
dialog.render();
|
||||
const statusBar = this.jquery(
|
||||
'<div class=\'pg-prop-status-bar pg-prop-status-bar-absolute pg-el-xs-12 d-none\'>' +
|
||||
' <div class="error-in-footer"> ' +
|
||||
' <div class="d-flex px-2 py-1"> ' +
|
||||
' <div class="pr-2"> ' +
|
||||
' <i class="fa fa-exclamation-triangle text-danger" aria-hidden="true"></i> ' +
|
||||
' </div> ' +
|
||||
' <div class="alert-text" role="alert"></div> ' +
|
||||
' <div class="ml-auto close-error-bar"> ' +
|
||||
' <a aria-label="' + gettext('Close error bar') + '" class="close-error fa fa-times text-danger"></a> ' +
|
||||
' </div> ' +
|
||||
' </div> ' +
|
||||
' </div> ' +
|
||||
'</div>').appendTo($container);
|
||||
|
||||
this.elements.content.appendChild($container.get(0));
|
||||
|
||||
this.focusOnDialog(this);
|
||||
this.setListenersForFilenameChanges(statusBar);
|
||||
}
|
||||
|
||||
callback(event) {
|
||||
const selectedTreeNode = this.getSelectedNode();
|
||||
const selectedTreeNodeData = this.getSelectedNodeData(selectedTreeNode);
|
||||
const node = selectedTreeNodeData && this.pgBrowser.Nodes[selectedTreeNodeData._type];
|
||||
|
||||
if (this.wasHelpButtonPressed(event)) {
|
||||
event.cancel = true;
|
||||
this.pgBrowser.showHelp(
|
||||
event.button.element.name,
|
||||
event.button.element.getAttribute('url'),
|
||||
node,
|
||||
selectedTreeNode.getHtmlIdentifier()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.wasBackupButtonPressed(event)) {
|
||||
|
||||
if (!selectedTreeNodeData)
|
||||
return;
|
||||
|
||||
const serverIdentifier = this.retrieveServerIdentifier(node, selectedTreeNode);
|
||||
|
||||
const dialog = this;
|
||||
let urlShortcut = 'backup.create_server_job';
|
||||
if (this.typeOfDialog === 'backup_objects') {
|
||||
urlShortcut = 'backup.create_object_job';
|
||||
}
|
||||
const baseUrl = url_for(urlShortcut, {
|
||||
'sid': serverIdentifier,
|
||||
});
|
||||
|
||||
const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode);
|
||||
|
||||
this.setExtraParameters(selectedTreeNode, treeInfo);
|
||||
let backupDate = this.view.model.toJSON();
|
||||
|
||||
if(userInfo['current_auth_source'] == pgConst['KERBEROS'] && treeInfo.server.gss_authenticated && (backupDate.type == 'globals' || backupDate.type == 'server')) {
|
||||
let newPromise = fetch_ticket_lifetime();
|
||||
newPromise.then(
|
||||
function(lifetime) {
|
||||
if (lifetime < 1800 && lifetime > 0) {
|
||||
dialog.alertify.warning(
|
||||
'You have '+ (Math.round(parseInt(lifetime)/60)).toString() +' minutes left on your ticket - if the dump takes longer than that, it may fail."'
|
||||
);
|
||||
}
|
||||
},
|
||||
function() {
|
||||
dialog.alertify.warning(
|
||||
gettext('Please renew your kerberos ticket, it has been expired.')
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
axios.post(
|
||||
baseUrl,
|
||||
backupDate
|
||||
).then(function (res) {
|
||||
if (res.data.success) {
|
||||
dialog.alertify.success(gettext('Backup job created.'), 5);
|
||||
dialog.pgBrowser.Events.trigger('pgadmin-bgprocess:created', dialog);
|
||||
} else {
|
||||
dialog.alertify.alert(
|
||||
gettext('Backup job creation failed.'),
|
||||
res.data.errormsg
|
||||
);
|
||||
}
|
||||
}).catch(function (error) {
|
||||
try {
|
||||
const err = error.response.data;
|
||||
dialog.alertify.alert(
|
||||
gettext('Backup job failed.'),
|
||||
err.errormsg
|
||||
);
|
||||
} catch (e) {
|
||||
console.warn(e.stack || e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
addAlertifyClassToBackupNodeChildNodes() {
|
||||
this.jquery(this.elements.body.childNodes[0]).addClass(
|
||||
'alertify_tools_dialog_properties obj_properties'
|
||||
);
|
||||
}
|
||||
|
||||
getSelectedNode() {
|
||||
const tree = this.pgBrowser.tree;
|
||||
const selectedNode = tree.selected();
|
||||
if (selectedNode) {
|
||||
return tree.findNodeByDomElement(selectedNode);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
disableBackupButton() {
|
||||
this.__internal.buttons[3].element.disabled = true;
|
||||
}
|
||||
|
||||
enableBackupButton() {
|
||||
this.__internal.buttons[3].element.disabled = false;
|
||||
}
|
||||
|
||||
createDialog(node, treeInfo, typeOfDialog, $container) {
|
||||
let attributes = {};
|
||||
if (typeOfDialog !== 'backup_objects') {
|
||||
attributes['type'] = typeOfDialog;
|
||||
}
|
||||
// Instance of backbone model
|
||||
const newModel = new this.dialogModel(attributes, {
|
||||
node_info: treeInfo,
|
||||
});
|
||||
const fields = this.backform.generateViewSchema(
|
||||
treeInfo, newModel, 'create', node, treeInfo.server, true
|
||||
);
|
||||
|
||||
return this.view = new this.backform.Dialog({
|
||||
el: $container,
|
||||
model: newModel,
|
||||
schema: fields,
|
||||
});
|
||||
}
|
||||
|
||||
retrieveServerIdentifier(node, selectedTreeNode) {
|
||||
const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(selectedTreeNode);
|
||||
return treeInfo.server._id;
|
||||
}
|
||||
|
||||
setListenersForFilenameChanges(statusBar) {
|
||||
const self = this;
|
||||
|
||||
this.view.model.on('change', function () {
|
||||
const ctx = this;
|
||||
var errmsg;
|
||||
|
||||
const showError = function(errorField, errormsg) {
|
||||
ctx.errorModel.set(errorField, errormsg);
|
||||
statusBar.removeClass('d-none');
|
||||
statusBar.find('.alert-text').html(errormsg);
|
||||
self.elements.dialog.querySelector('.close-error').addEventListener('click', ()=>{
|
||||
statusBar.addClass('d-none');
|
||||
ctx.errorModel.set(errorField, errormsg);
|
||||
});
|
||||
};
|
||||
|
||||
if (!_.isUndefined(this.get('file')) && this.get('file') !== '') {
|
||||
this.errorModel.clear();
|
||||
statusBar.addClass('d-none');
|
||||
self.enableBackupButton();
|
||||
} else {
|
||||
self.disableBackupButton();
|
||||
errmsg = gettext('Please provide a filename');
|
||||
showError('file', errmsg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setExtraParameters(selectedTreeNode, treeInfo) {
|
||||
if (this.typeOfDialog === 'backup_objects') {
|
||||
|
||||
this.view.model.set('database', treeInfo.database._label);
|
||||
|
||||
const nodeData = selectedTreeNode.getData();
|
||||
if (nodeData._type === 'schema') {
|
||||
this.view.model.set('schemas', [nodeData._label]);
|
||||
}
|
||||
|
||||
if (nodeData._type === 'table' || nodeData._type === 'partition') {
|
||||
this.view.model.set('tables', [
|
||||
[treeInfo.schema._label, nodeData._label],
|
||||
]);
|
||||
}
|
||||
|
||||
if (_.isEmpty(this.view.model.get('ratio'))) {
|
||||
this.view.model.unset('ratio');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wasBackupButtonPressed(event) {
|
||||
return event.button['data-btn-name'] === 'backup';
|
||||
}
|
||||
}
|
@ -1,303 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import {BackupDialog} from '../../../pgadmin/tools/backup/static/js/backup_dialog';
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import axios from 'axios/index';
|
||||
|
||||
const context = describe;
|
||||
|
||||
describe('BackupDialog', () => {
|
||||
let backupDialog;
|
||||
let pgBrowser;
|
||||
let jquerySpy;
|
||||
let alertifySpy;
|
||||
let backupModelSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
pgBrowser = {
|
||||
Nodes: {
|
||||
server: {
|
||||
hasId: true,
|
||||
label: 'server',
|
||||
getTreeNodeHierarchy: jasmine.createSpy('server.getTreeNodeHierarchy'),
|
||||
},
|
||||
database: {
|
||||
hasId: true,
|
||||
label: 'database',
|
||||
getTreeNodeHierarchy: jasmine.createSpy('db.getTreeNodeHierarchy'),
|
||||
},
|
||||
schema: {
|
||||
hasId: true,
|
||||
label: 'schema',
|
||||
getTreeNodeHierarchy: jasmine.createSpy('db.getTreeNodeHierarchy'),
|
||||
},
|
||||
},
|
||||
stdW: {
|
||||
sm: 500,
|
||||
md: 700,
|
||||
lg: 900,
|
||||
default: 500,
|
||||
},
|
||||
stdH: {
|
||||
sm: 200,
|
||||
md: 400,
|
||||
lg: 550,
|
||||
default: 550,
|
||||
},
|
||||
};
|
||||
pgBrowser.tree = new TreeFake(pgBrowser);
|
||||
pgBrowser.Nodes.server.hasId = true;
|
||||
pgBrowser.Nodes.database.hasId = true;
|
||||
jquerySpy = jasmine.createSpy('jquerySpy');
|
||||
backupModelSpy = jasmine.createSpy('backupModelSpy');
|
||||
|
||||
const hierarchy = {
|
||||
children: [
|
||||
{
|
||||
id: 'root',
|
||||
children: [
|
||||
{
|
||||
id: 'serverTreeNode',
|
||||
data: {
|
||||
_id: 10,
|
||||
_type: 'server',
|
||||
label: 'some-tree-label',
|
||||
server_type: 'pg',
|
||||
version: 100000,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
id: 'some_database',
|
||||
data: {
|
||||
_type: 'database',
|
||||
_id: 11,
|
||||
label: 'some_database',
|
||||
_label: 'some_database_label',
|
||||
},
|
||||
}, {
|
||||
id: 'database_with_equal_in_name',
|
||||
data: {
|
||||
_type: 'database',
|
||||
label: 'some_database',
|
||||
_label: '=some_database_label',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'serverTreeNodeWrongPath',
|
||||
data: {
|
||||
_id: 12,
|
||||
_type: 'server',
|
||||
label: 'some-tree-label',
|
||||
server_type: 'pg',
|
||||
version: 90600,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'ppasServer',
|
||||
data: {
|
||||
_id: 13,
|
||||
_type: 'server',
|
||||
label: 'some-tree-label',
|
||||
server_type: 'ppas',
|
||||
version: 130000,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'ppasServerTreeNodeWrongPath',
|
||||
data: {
|
||||
_id: 14,
|
||||
_type: 'server',
|
||||
label: 'some-tree-label',
|
||||
server_type: 'ppas',
|
||||
version: 90600,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
pgBrowser.tree = TreeFake.build(hierarchy, pgBrowser);
|
||||
});
|
||||
|
||||
describe('#draw', () => {
|
||||
let networkMock;
|
||||
beforeEach(() => {
|
||||
networkMock = new MockAdapter(axios);
|
||||
alertifySpy = jasmine.createSpyObj('alertify', ['alert', 'dialog']);
|
||||
alertifySpy['backup_objects'] = jasmine.createSpy('backup_objects');
|
||||
backupDialog = new BackupDialog(
|
||||
pgBrowser,
|
||||
jquerySpy,
|
||||
alertifySpy,
|
||||
backupModelSpy
|
||||
);
|
||||
|
||||
pgBrowser.get_preference = jasmine.createSpy('get_preferences');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
networkMock.restore();
|
||||
});
|
||||
|
||||
context('there are no ancestors of the type server', () => {
|
||||
it('does not create a dialog', () => {
|
||||
pgBrowser.tree.selectNode([{id: 'root'}]);
|
||||
backupDialog.draw(null, null, null);
|
||||
expect(alertifySpy['backup_objects']).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('display an alert with a Backup Error', () => {
|
||||
backupDialog.draw(null, [{id: 'root'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Backup Error',
|
||||
'Please select server or child node from the browser tree.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('there is an ancestor of the type server', () => {
|
||||
context('no preference can be found', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.get_preference.and.returnValue(undefined);
|
||||
});
|
||||
|
||||
context('server is a PostgreSQL server', () => {
|
||||
it('display an alert with "Preferences Error"', () => {
|
||||
backupDialog.draw(null, [{id: 'serverTreeNode'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Preferences Error',
|
||||
'Failed to load preference pg_bin_dir of module paths'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('server is a EPAS server', () => {
|
||||
it('display an alert with "Preferences Error"', () => {
|
||||
backupDialog.draw(null, [{id: 'ppasServer'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Preferences Error',
|
||||
'Failed to load preference ppas_bin_dir of module paths'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('preference can be found for PostgreSQL Server', () => {
|
||||
context('binary folder is not configured', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.get_preference.and.returnValue({value: '[{\"serverType\":\"PostgreSQL 9.6\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"90600\",\"next_major_version\":\"100000\"},{\"serverType\":\"PostgreSQL 10\",\"binaryPath\":\"/Library/PostgreSQL/10/bin\",\"isDefault\":false,\"version\":\"100000\",\"next_major_version\":\"110000\"},{\"serverType\":\"PostgreSQL 11\",\"binaryPath\":\"/Library/PostgreSQL/11/bin\",\"isDefault\":false,\"version\":\"110000\",\"next_major_version\":\"120000\"},{\"serverType\":\"PostgreSQL 12\",\"binaryPath\":\"/Library/PostgreSQL/12/bin\",\"isDefault\":false,\"version\":\"120000\",\"next_major_version\":\"130000\"},{\"serverType\":\"PostgreSQL 13\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"130000\",\"next_major_version\":\"140000\"}]'});
|
||||
});
|
||||
|
||||
context('server is a PostgreSQL server', () => {
|
||||
it('display an alert with "Configuration required"', () => {
|
||||
backupDialog.draw(null, [{id: 'serverTreeNodeWrongPath'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Configuration required',
|
||||
'Please configure the PostgreSQL Binary Path in the Preferences dialog.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('binary folder is configured', () => {
|
||||
let backupDialogResizeToSpy;
|
||||
beforeEach(() => {
|
||||
backupDialogResizeToSpy = jasmine.createSpyObj('backupDialogResizeToSpy', ['resizeTo']);
|
||||
alertifySpy['backup_objects'].and
|
||||
.returnValue(backupDialogResizeToSpy);
|
||||
pgBrowser.get_preference.and.returnValue({value: '[{\"serverType\":\"PostgreSQL 9.6\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"90600\",\"next_major_version\":\"100000\"},{\"serverType\":\"PostgreSQL 10\",\"binaryPath\":\"/Library/PostgreSQL/10/bin\",\"isDefault\":true,\"version\":\"100000\",\"next_major_version\":\"110000\"},{\"serverType\":\"PostgreSQL 11\",\"binaryPath\":\"/Library/PostgreSQL/11/bin\",\"isDefault\":false,\"version\":\"110000\",\"next_major_version\":\"120000\"},{\"serverType\":\"PostgreSQL 12\",\"binaryPath\":\"/Library/PostgreSQL/12/bin\",\"isDefault\":false,\"version\":\"120000\",\"next_major_version\":\"130000\"},{\"serverType\":\"PostgreSQL 13\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"130000\",\"next_major_version\":\"140000\"}]'});
|
||||
spyOn(backupDialog, 'url_for_utility_exists').and.returnValue('/backup/utility_exists/10/objects');
|
||||
networkMock.onGet('/backup/utility_exists/10/objects').reply(200, {'success': 1});
|
||||
});
|
||||
|
||||
it('displays the dialog when binary path is for correct server version', (done) => {
|
||||
backupDialog.draw(null, [{id: 'serverTreeNode'}], null, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy['backup_objects']).toHaveBeenCalledWith(true);
|
||||
expect(backupDialogResizeToSpy.resizeTo).toHaveBeenCalledWith(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('displays the dialog when default binary path is specified', (done) => {
|
||||
backupDialog.draw(null, [{id: 'serverTreeNodeWrongPath'}], null, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy['backup_objects']).toHaveBeenCalledWith(true);
|
||||
expect(backupDialogResizeToSpy.resizeTo).toHaveBeenCalledWith(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
context('database label contain "="', () => {
|
||||
it('should create alert dialog with backup error', (done) => {
|
||||
backupDialog.draw(null, [{id: 'database_with_equal_in_name'}], null);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith('Backup Error',
|
||||
'Databases with = symbols in the name cannot be backed up or restored using this utility.');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('preference can be found for EPAS server', () => {
|
||||
context('binary folder is not configured', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.get_preference.and.returnValue({value: '[{\"serverType\":\"EDB Advanced Server 9.6\",\"binaryPath\":\"\",\"isDefault\":false,\"version\":\"90600\",\"next_major_version\":\"100000\"},{\"serverType\":\"EDB Advanced Server 10\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"100000\",\"next_major_version\":\"110000\"},{\"serverType\":\"EDB Advanced Server 11\",\"binaryPath\":\"/Library/EPAS/11/bin/\",\"isDefault\":false,\"version\":\"110000\",\"next_major_version\":\"120000\"},{\"serverType\":\"EDB Advanced Server 12\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"120000\",\"next_major_version\":\"130000\"},{\"serverType\":\"EDB Advanced Server 13\",\"binaryPath\":\"/Library/EPAS/13/bin/\",\"isDefault\":false,\"version\":\"130000\",\"next_major_version\":\"140000\"}]'});
|
||||
});
|
||||
|
||||
context('server is a EPAS server', () => {
|
||||
it('display an alert with "Configuration required"', () => {
|
||||
backupDialog.draw(null, [{id: 'ppasServerTreeNodeWrongPath'}], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Configuration required',
|
||||
'Please configure the EDB Advanced Server Binary Path in the Preferences dialog.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('binary folder is configured', () => {
|
||||
let backupDialogResizeToSpy;
|
||||
beforeEach(() => {
|
||||
backupDialogResizeToSpy = jasmine.createSpyObj('backupDialogResizeToSpy', ['resizeTo']);
|
||||
alertifySpy['backup_objects'].and
|
||||
.returnValue(backupDialogResizeToSpy);
|
||||
pgBrowser.get_preference.and.returnValue({value: '[{\"serverType\":\"EDB Advanced Server 9.6\",\"binaryPath\":\"\",\"isDefault\":false,\"version\":\"90600\",\"next_major_version\":\"100000\"},{\"serverType\":\"EDB Advanced Server 10\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"100000\",\"next_major_version\":\"110000\"},{\"serverType\":\"EDB Advanced Server 11\",\"binaryPath\":\"/Library/EPAS/11/bin/\",\"isDefault\":false,\"version\":\"110000\",\"next_major_version\":\"120000\"},{\"serverType\":\"EDB Advanced Server 12\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"120000\",\"next_major_version\":\"130000\"},{\"serverType\":\"EDB Advanced Server 13\",\"binaryPath\":\"/Library/EPAS/13/bin/\",\"isDefault\":true,\"version\":\"130000\",\"next_major_version\":\"140000\"}]'});
|
||||
spyOn(backupDialog, 'url_for_utility_exists').and.returnValue('/backup/utility_exists/10/objects');
|
||||
networkMock.onGet('/backup/utility_exists/10/objects').reply(200, {'success': 1});
|
||||
});
|
||||
|
||||
it('displays the dialog when binary path is for correct server version', (done) => {
|
||||
backupDialog.draw(null, [{id: 'ppasServer'}], null, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy['backup_objects']).toHaveBeenCalledWith(true);
|
||||
expect(backupDialogResizeToSpy.resizeTo).toHaveBeenCalledWith(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('displays the dialog when default binary path is specified', (done) => {
|
||||
backupDialog.draw(null, [{id: 'ppasServerTreeNodeWrongPath'}], null, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy['backup_objects']).toHaveBeenCalledWith(true);
|
||||
expect(backupDialogResizeToSpy.resizeTo).toHaveBeenCalledWith(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1,682 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
import {BackupDialogWrapper} from '../../../pgadmin/tools/backup/static/js/backup_dialog_wrapper';
|
||||
import axios from 'axios/index';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import {FakeModel} from '../fake_model';
|
||||
import {TreeNode} from '../../../pgadmin/static/js/tree/tree_nodes';
|
||||
|
||||
let context = describe;
|
||||
|
||||
describe('BackupDialogWrapper', () => {
|
||||
let jquerySpy;
|
||||
let pgBrowser;
|
||||
let alertifySpy;
|
||||
let dialogModelKlassSpy;
|
||||
let backform;
|
||||
let generatedBackupModel;
|
||||
let backupDialogWrapper;
|
||||
let noDataNode;
|
||||
let serverTreeNode;
|
||||
let databaseTreeNode;
|
||||
let viewSchema;
|
||||
let backupJQueryContainerSpy;
|
||||
let backupNodeChildNodeSpy;
|
||||
let backupNode;
|
||||
|
||||
beforeEach(() => {
|
||||
pgBrowser = {
|
||||
Nodes: {
|
||||
server: {
|
||||
hasId: true,
|
||||
getTreeNodeHierarchy: jasmine.createSpy('getTreeNodeHierarchy'),
|
||||
},
|
||||
database: {
|
||||
hasId: true,
|
||||
},
|
||||
},
|
||||
keyboardNavigation: jasmine.createSpyObj('keyboardNavigation', ['getDialogTabNavigator']),
|
||||
};
|
||||
|
||||
pgBrowser.tree = new TreeFake(pgBrowser);
|
||||
|
||||
noDataNode = pgBrowser.tree.addNewNode('level1.1', undefined, [{id: 'level1'}]);
|
||||
serverTreeNode = pgBrowser.tree.addNewNode('level2.1', {
|
||||
_type: 'server',
|
||||
_id: 10,
|
||||
label: 'some-tree-label',
|
||||
}, [{id: 'level2.1'}]);
|
||||
databaseTreeNode = new TreeNode('database-tree-node', {
|
||||
_type: 'database',
|
||||
_label: 'some-database-label',
|
||||
}, [{id: 'database-tree-node'}]);
|
||||
pgBrowser.tree.addChild(serverTreeNode, databaseTreeNode);
|
||||
|
||||
jquerySpy = jasmine.createSpy('jquerySpy');
|
||||
backupNode = {
|
||||
__internal: {
|
||||
buttons: [{}, {}, {}, {
|
||||
element: {
|
||||
disabled: false,
|
||||
},
|
||||
}],
|
||||
},
|
||||
elements: {
|
||||
body: {
|
||||
childNodes: [
|
||||
{},
|
||||
],
|
||||
},
|
||||
content: jasmine.createSpyObj('content', ['appendChild', 'attr']),
|
||||
},
|
||||
};
|
||||
|
||||
backupJQueryContainerSpy = jasmine.createSpyObj('backupJQueryContainer', ['get', 'attr']);
|
||||
backupJQueryContainerSpy.get.and.returnValue(backupJQueryContainerSpy);
|
||||
|
||||
generatedBackupModel = {};
|
||||
dialogModelKlassSpy = jasmine.createSpy('dialogModelKlass');
|
||||
dialogModelKlassSpy.and.returnValue(generatedBackupModel);
|
||||
|
||||
viewSchema = {};
|
||||
backform = jasmine.createSpyObj('backform', ['generateViewSchema', 'Dialog']);
|
||||
backform.generateViewSchema.and.returnValue(viewSchema);
|
||||
|
||||
backupNodeChildNodeSpy = jasmine.createSpyObj('something', ['addClass']);
|
||||
jquerySpy.and.callFake((selector) => {
|
||||
if (selector === '<div class=\'backup_dialog\'></div>') {
|
||||
return backupJQueryContainerSpy;
|
||||
} else if (selector === backupNode.elements.body.childNodes[0]) {
|
||||
return backupNodeChildNodeSpy;
|
||||
} else {
|
||||
return jasmine.createSpyObj('obj', ['appendTo']);
|
||||
}
|
||||
});
|
||||
alertifySpy = jasmine.createSpyObj('alertify', ['alert', 'dialog']);
|
||||
|
||||
});
|
||||
|
||||
describe('#prepare', () => {
|
||||
beforeEach(() => {
|
||||
backupDialogWrapper = new BackupDialogWrapper(
|
||||
'<div class=\'backup_dialog\'></div>',
|
||||
'backupDialogTitle',
|
||||
'backup',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
backupDialogWrapper = Object.assign(backupDialogWrapper, backupNode);
|
||||
});
|
||||
|
||||
context('no tree element is selected', () => {
|
||||
it('does not create a backform dialog', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backform.Dialog).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('disables the button "submit button" until a filename is selected', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backupDialogWrapper.__internal.buttons[3].element.disabled).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
context('selected tree node has no data', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.tree.selectNode(noDataNode.domNode);
|
||||
});
|
||||
|
||||
it('does not create a backform dialog', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backform.Dialog).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('disables the button "submit button" until a filename is selected', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backupDialogWrapper.__internal.buttons[3].element.disabled).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
context('tree element is selected', () => {
|
||||
let treeHierarchyInformation;
|
||||
let dialogSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
treeHierarchyInformation = {
|
||||
server: {
|
||||
_type: 'server',
|
||||
_id: 10,
|
||||
priority: 0,
|
||||
label: 'some-tree-label',
|
||||
},
|
||||
};
|
||||
pgBrowser.tree.selectNode(serverTreeNode.domNode);
|
||||
pgBrowser.Nodes['server'].getTreeNodeHierarchy.and
|
||||
.returnValue(treeHierarchyInformation);
|
||||
dialogSpy = jasmine.createSpyObj('newView', ['render']);
|
||||
dialogSpy.$el = jasmine.createSpyObj('$el', ['find', 'attr']);
|
||||
dialogSpy.model = jasmine.createSpyObj('model', ['on']);
|
||||
dialogSpy.$el.find.and.returnValue([]);
|
||||
|
||||
backform.Dialog.and.returnValue(dialogSpy);
|
||||
});
|
||||
|
||||
it('creates a backform dialog and displays it', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backform.Dialog).toHaveBeenCalledWith({
|
||||
el: backupJQueryContainerSpy,
|
||||
model: generatedBackupModel,
|
||||
schema: viewSchema,
|
||||
});
|
||||
|
||||
expect(dialogSpy.render).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('add alertify classes to restore node childnode', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backupNodeChildNodeSpy.addClass)
|
||||
.toHaveBeenCalledWith('alertify_tools_dialog_properties obj_properties');
|
||||
});
|
||||
|
||||
it('disables the button submit button until a filename is selected', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backupNode.__internal.buttons[3].element.disabled).toBe(true);
|
||||
});
|
||||
|
||||
it('generates a new backup model', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(dialogModelKlassSpy).toHaveBeenCalledWith(
|
||||
{type: 'backup'},
|
||||
{node_info: treeHierarchyInformation}
|
||||
);
|
||||
});
|
||||
|
||||
it('add the new dialog to the backup node HTML', () => {
|
||||
backupDialogWrapper.prepare();
|
||||
expect(backupNode.elements.content.appendChild).toHaveBeenCalledWith(backupJQueryContainerSpy);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('onButtonClicked', () => {
|
||||
let networkMock;
|
||||
beforeEach(() => {
|
||||
networkMock = new MockAdapter(axios);
|
||||
backupDialogWrapper = new BackupDialogWrapper(
|
||||
'<div class=\'backup_dialog\'></div>',
|
||||
'backupDialogTitle',
|
||||
'backup',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
|
||||
backupDialogWrapper = Object.assign(backupDialogWrapper, backupNode);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
networkMock.restore();
|
||||
});
|
||||
|
||||
context('dialog help button was pressed', () => {
|
||||
let networkCalled;
|
||||
beforeEach(() => {
|
||||
networkCalled = false;
|
||||
networkMock.onAny(/.*/).reply(() => {
|
||||
networkCalled = true;
|
||||
return [200, {}];
|
||||
});
|
||||
pgBrowser.tree.selectNode(serverTreeNode.domNode);
|
||||
pgBrowser.showHelp = jasmine.createSpy('showHelp');
|
||||
|
||||
const event = {
|
||||
button: {
|
||||
element: {
|
||||
name: 'dialog_help',
|
||||
getAttribute: (attributeName) => {
|
||||
if (attributeName === 'url') {
|
||||
return 'http://someurl';
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
backupDialogWrapper.callback(event);
|
||||
});
|
||||
|
||||
it('displays help for dialog', () => {
|
||||
expect(pgBrowser.showHelp).toHaveBeenCalledWith(
|
||||
'dialog_help',
|
||||
'http://someurl',
|
||||
pgBrowser.Nodes['server'],
|
||||
serverTreeNode.getHtmlIdentifier()
|
||||
);
|
||||
});
|
||||
|
||||
it('does not start the backup', () => {
|
||||
expect(networkCalled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('object help button was pressed', () => {
|
||||
let networkCalled;
|
||||
beforeEach(() => {
|
||||
networkCalled = false;
|
||||
networkMock.onAny(/.*/).reply(() => {
|
||||
networkCalled = true;
|
||||
return [200, {}];
|
||||
});
|
||||
pgBrowser.tree.selectNode(serverTreeNode.domNode);
|
||||
pgBrowser.showHelp = jasmine.createSpy('showHelp');
|
||||
|
||||
const event = {
|
||||
button: {
|
||||
element: {
|
||||
name: 'object_help',
|
||||
getAttribute: (attributeName) => {
|
||||
if (attributeName === 'url') {
|
||||
return 'http://someurl';
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
backupDialogWrapper.callback(event);
|
||||
});
|
||||
|
||||
it('displays help for dialog', () => {
|
||||
expect(pgBrowser.showHelp).toHaveBeenCalledWith(
|
||||
'object_help',
|
||||
'http://someurl',
|
||||
pgBrowser.Nodes['server'],
|
||||
serverTreeNode.getHtmlIdentifier()
|
||||
);
|
||||
});
|
||||
|
||||
it('does not start the backup', () => {
|
||||
expect(networkCalled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('backup button was pressed', () => {
|
||||
context('no tree node is selected', () => {
|
||||
it('does not start the backup', () => {
|
||||
let networkCalled = false;
|
||||
networkMock.onAny(/.*/).reply(() => {
|
||||
networkCalled = true;
|
||||
return [200, {}];
|
||||
});
|
||||
|
||||
let event = {
|
||||
button: {
|
||||
'data-btn-name': 'backup',
|
||||
element: {
|
||||
getAttribute: () => {
|
||||
return 'http://someurl';
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
backupDialogWrapper.callback(event);
|
||||
expect(networkCalled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('tree node has no data', () => {
|
||||
it('does not start the backup', () => {
|
||||
pgBrowser.tree.selectNode(noDataNode.domNode);
|
||||
|
||||
let networkCalled = false;
|
||||
networkMock.onAny(/.*/).reply(() => {
|
||||
networkCalled = true;
|
||||
return [200, {}];
|
||||
});
|
||||
|
||||
let event = {
|
||||
button: {
|
||||
'data-btn-name': 'backup',
|
||||
element: {
|
||||
getAttribute: () => {
|
||||
return 'http://someurl';
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
backupDialogWrapper.callback(event);
|
||||
expect(networkCalled).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
context('tree node has data', () => {
|
||||
context('when dialog type is global', () => {
|
||||
let event;
|
||||
beforeEach(() => {
|
||||
pgBrowser.tree.selectNode(serverTreeNode.domNode);
|
||||
|
||||
backupDialogWrapper.view = {
|
||||
model: new FakeModel(),
|
||||
};
|
||||
|
||||
event = {
|
||||
button: {
|
||||
'data-btn-name': 'backup',
|
||||
element: {
|
||||
getAttribute: () => {
|
||||
return 'http://someurl';
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
context('when the backup job is created successfully', () => {
|
||||
let dataSentToServer;
|
||||
beforeEach(() => {
|
||||
pgBrowser.Events = jasmine.createSpyObj('Events', ['trigger']);
|
||||
alertifySpy.success = jasmine.createSpy('success');
|
||||
networkMock.onPost('/backup/job/10').reply((request) => {
|
||||
dataSentToServer = request.data;
|
||||
return [200, {'success': 1}];
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('creates a success alert box', (done) => {
|
||||
backupDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy.success).toHaveBeenCalledWith(
|
||||
'Backup job created.',
|
||||
5
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('trigger an event to background process', (done) => {
|
||||
backupDialogWrapper.callback(event);
|
||||
|
||||
setTimeout(() => {
|
||||
expect(pgBrowser.Events.trigger).toHaveBeenCalledWith(
|
||||
'pgadmin-bgprocess:created',
|
||||
backupDialogWrapper
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('send the correct paramenters to the backend', (done) => {
|
||||
backupDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(JSON.parse(dataSentToServer)).toEqual(
|
||||
{}
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
context('when creating backup job fails', () => {
|
||||
it('creates an alert box', (done) => {
|
||||
alertifySpy.alert = jasmine.createSpy('alert');
|
||||
networkMock.onPost('/backup/job/10').reply(() => {
|
||||
return [400, {
|
||||
errormsg: 'some-error-message',
|
||||
}];
|
||||
});
|
||||
|
||||
backupDialogWrapper.callback(event);
|
||||
setTimeout( () => {
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Backup job failed.',
|
||||
'some-error-message'
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('when dialog type is object', () => {
|
||||
let event;
|
||||
beforeEach(() => {
|
||||
backupDialogWrapper = new BackupDialogWrapper(
|
||||
'<div class=\'backup_dialog\'></div>',
|
||||
'backupDialogTitle',
|
||||
'backup_objects',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
|
||||
pgBrowser.tree.selectNode(databaseTreeNode.domNode);
|
||||
|
||||
backupDialogWrapper.view = {
|
||||
model: new FakeModel(),
|
||||
};
|
||||
|
||||
event = {
|
||||
button: {
|
||||
'data-btn-name': 'backup',
|
||||
element: {
|
||||
getAttribute: () => {
|
||||
return 'http://someurl';
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
context('when the backup job is created successfully', () => {
|
||||
let dataSentToServer;
|
||||
beforeEach(() => {
|
||||
pgBrowser.Events = jasmine.createSpyObj('Events', ['trigger']);
|
||||
alertifySpy.success = jasmine.createSpy('success');
|
||||
|
||||
networkMock.onPost('/backup/job/10/object').reply((request) => {
|
||||
dataSentToServer = request.data;
|
||||
return [200, {'success': 1}];
|
||||
});
|
||||
});
|
||||
|
||||
it('creates a success alert box', (done) => {
|
||||
backupDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy.success).toHaveBeenCalledWith(
|
||||
'Backup job created.',
|
||||
5
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('trigger an event to background process', (done) => {
|
||||
backupDialogWrapper.callback(event);
|
||||
|
||||
setTimeout(() => {
|
||||
expect(pgBrowser.Events.trigger).toHaveBeenCalledWith(
|
||||
'pgadmin-bgprocess:created',
|
||||
backupDialogWrapper
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('send the correct parameters to the backend', (done) => {
|
||||
backupDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(JSON.parse(dataSentToServer)).toEqual(
|
||||
{database: 'some-database-label'}
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
context('when creating backup job fails', () => {
|
||||
it('creates an alert box', (done) => {
|
||||
alertifySpy.alert = jasmine.createSpy('alert');
|
||||
networkMock.onPost('/backup/job/10/object').reply(() => {
|
||||
return [400, {
|
||||
errormsg: 'some-error-message',
|
||||
}];
|
||||
});
|
||||
|
||||
backupDialogWrapper.callback(event);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Backup job failed.',
|
||||
'some-error-message'
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
xdescribe('#setExtraParameters', () => {
|
||||
let selectedTreeNode;
|
||||
let treeInfo;
|
||||
let model;
|
||||
|
||||
context('when dialog type is global', () => {
|
||||
beforeEach(() => {
|
||||
backupDialogWrapper = new BackupDialogWrapper(
|
||||
'<div class=\'backup_dialog\'></div>',
|
||||
'backupDialogTitle',
|
||||
'backup',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
|
||||
treeInfo = {};
|
||||
model = new FakeModel();
|
||||
backupDialogWrapper.view = {
|
||||
model: model,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
it('sets nothing on the view model', () => {
|
||||
backupDialogWrapper.setExtraParameters(selectedTreeNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
context('when dialog type is object', () => {
|
||||
beforeEach(() => {
|
||||
backupDialogWrapper = new BackupDialogWrapper(
|
||||
'<div class=\'backup_dialog\'></div>',
|
||||
'backupDialogTitle',
|
||||
'backup_objects',
|
||||
jquerySpy,
|
||||
pgBrowser,
|
||||
alertifySpy,
|
||||
dialogModelKlassSpy,
|
||||
backform
|
||||
);
|
||||
|
||||
treeInfo = {
|
||||
database: {
|
||||
_label: 'some-database-label',
|
||||
},
|
||||
schema: {
|
||||
_label: 'some-treeinfo-label',
|
||||
},
|
||||
};
|
||||
|
||||
model = new FakeModel();
|
||||
selectedTreeNode = new TreeNode('some-selected-node',
|
||||
{_type: 'some-type', _label: 'some-selected-label'},
|
||||
[]);
|
||||
backupDialogWrapper.view = {
|
||||
model: model,
|
||||
};
|
||||
});
|
||||
|
||||
it('sets the database label on the model', () => {
|
||||
backupDialogWrapper.setExtraParameters(selectedTreeNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({
|
||||
'database': 'some-database-label',
|
||||
});
|
||||
});
|
||||
|
||||
context('when the selected is a schema type', () => {
|
||||
beforeEach(() => {
|
||||
selectedTreeNode = new TreeNode('some-selected-node',
|
||||
{_type: 'schema', _label: 'some-schema-label'},
|
||||
[]);
|
||||
});
|
||||
|
||||
it('sets the schema label on the model', () => {
|
||||
backupDialogWrapper.setExtraParameters(selectedTreeNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({
|
||||
'database': 'some-database-label',
|
||||
'schemas': ['some-schema-label'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('when the selected is a table type', () => {
|
||||
beforeEach(() => {
|
||||
selectedTreeNode = new TreeNode('some-selected-node',
|
||||
{_type: 'table', _label: 'some-table-label'},
|
||||
[]);
|
||||
});
|
||||
|
||||
it('sets the schema label on the model', () => {
|
||||
backupDialogWrapper.setExtraParameters(selectedTreeNode, treeInfo);
|
||||
expect(model.toJSON()).toEqual({
|
||||
'database': 'some-database-label',
|
||||
'tables': [['some-treeinfo-label', 'some-table-label']],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('when the model has no ratio value', () => {
|
||||
beforeEach(() => {
|
||||
model.set('ratio', '');
|
||||
});
|
||||
|
||||
it('sets clears the ratio value', () => {
|
||||
backupDialogWrapper.setExtraParameters(selectedTreeNode, treeInfo);
|
||||
expect(model.get('ratio')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
context('when the model has a valid ratio value', () => {
|
||||
beforeEach(() => {
|
||||
model.set('ratio', '0.25');
|
||||
});
|
||||
|
||||
it('sets clears the ratio value', () => {
|
||||
backupDialogWrapper.setExtraParameters(selectedTreeNode, treeInfo);
|
||||
expect(model.get('ratio')).toEqual('0.25');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1,298 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import {BackupDialog} from '../../../pgadmin/tools/backup/static/js/backup_dialog';
|
||||
import {TreeFake} from '../tree/tree_fake';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import axios from 'axios/index';
|
||||
|
||||
const context = describe;
|
||||
|
||||
describe('GlobalServerBackupDialog', () => {
|
||||
let backupDialog;
|
||||
let pgBrowser;
|
||||
let jquerySpy;
|
||||
let alertifySpy;
|
||||
let backupModelSpy;
|
||||
|
||||
let rootNode;
|
||||
let serverTreeNode, serverTreeNodeWrongPath;
|
||||
let ppasServerTreeNode, ppasServerTreeNodeWrongPath;
|
||||
|
||||
beforeEach(() => {
|
||||
pgBrowser = {
|
||||
Nodes: {
|
||||
server: jasmine.createSpyObj('Node[server]', ['getTreeNodeHierarchy']),
|
||||
},
|
||||
stdW: {
|
||||
sm: 500,
|
||||
md: 700,
|
||||
lg: 900,
|
||||
default: 500,
|
||||
},
|
||||
stdH: {
|
||||
sm: 200,
|
||||
md: 400,
|
||||
lg: 550,
|
||||
default: 550,
|
||||
},
|
||||
};
|
||||
pgBrowser.tree = new TreeFake(pgBrowser);
|
||||
pgBrowser.Nodes.server.hasId = true;
|
||||
jquerySpy = jasmine.createSpy('jquerySpy');
|
||||
backupModelSpy = jasmine.createSpy('backupModelSpy');
|
||||
|
||||
rootNode = pgBrowser.tree.addNewNode('level1', {}, undefined, []);
|
||||
serverTreeNode = pgBrowser.tree.addNewNode('level1.1', {
|
||||
_type: 'server',
|
||||
_id: 10,
|
||||
server_type: 'pg',
|
||||
version: 100000,
|
||||
}, undefined, ['level1']);
|
||||
serverTreeNodeWrongPath = pgBrowser.tree.addNewNode('level1.2', {
|
||||
_type: 'server',
|
||||
_id: 11,
|
||||
server_type: 'pg',
|
||||
version: 90600,
|
||||
}, undefined, ['level1']);
|
||||
ppasServerTreeNode = pgBrowser.tree.addNewNode('level1.3', {
|
||||
_type: 'server',
|
||||
server_type: 'ppas',
|
||||
version: 130000,
|
||||
}, undefined, ['level1']);
|
||||
ppasServerTreeNodeWrongPath = pgBrowser.tree.addNewNode('level1.4', {
|
||||
_type: 'server',
|
||||
server_type: 'ppas',
|
||||
version: 90600,
|
||||
}, undefined, ['level1']);
|
||||
pgBrowser.tree.addNewNode('level3', {}, undefined, ['level1', 'level1.2', 'level1.3', 'level1.4']);
|
||||
pgBrowser.tree.addNewNode('level3.1', undefined, undefined, ['level1', 'level1.2', 'level3']);
|
||||
});
|
||||
|
||||
describe('#draw', () => {
|
||||
let networkMock;
|
||||
beforeEach(() => {
|
||||
networkMock = new MockAdapter(axios);
|
||||
alertifySpy = jasmine.createSpyObj('alertify', ['alert', 'dialog']);
|
||||
alertifySpy['BackupDialog_globals'] = jasmine.createSpy('BackupDialog_globals');
|
||||
alertifySpy['BackupDialog_server'] = jasmine.createSpy('BackupDialog_server');
|
||||
backupDialog = new BackupDialog(
|
||||
pgBrowser,
|
||||
jquerySpy,
|
||||
alertifySpy,
|
||||
backupModelSpy
|
||||
);
|
||||
|
||||
pgBrowser.get_preference = jasmine.createSpy('get_preferences');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
networkMock.restore();
|
||||
});
|
||||
|
||||
context('there are no ancestors of the type server', () => {
|
||||
it('does not create a dialog', () => {
|
||||
pgBrowser.tree.selectNode([{id: 'level1'}]);
|
||||
backupDialog.draw(null, null, null);
|
||||
expect(alertifySpy['BackupDialog_globals']).not.toHaveBeenCalled();
|
||||
expect(alertifySpy['BackupDialog_server']).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('display an alert with a Backup Error', () => {
|
||||
backupDialog.draw(null, [rootNode], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Backup Error',
|
||||
'Please select server or child node from the browser tree.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('there is an ancestor of the type server', () => {
|
||||
context('no preference can be found', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.get_preference.and.returnValue(undefined);
|
||||
});
|
||||
|
||||
context('server is a PostgreSQL server', () => {
|
||||
it('display an alert with "Preferences Error"', () => {
|
||||
backupDialog.draw(null, [serverTreeNode], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Preferences Error',
|
||||
'Failed to load preference pg_bin_dir of module paths'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
context('server is a EPAS server', () => {
|
||||
it('display an alert with "Preferences Error"', () => {
|
||||
backupDialog.draw(null, [ppasServerTreeNode], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Preferences Error',
|
||||
'Failed to load preference ppas_bin_dir of module paths'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('preference can be found for PostgreSQL Server', () => {
|
||||
context('binary folder is not configured', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.get_preference.and.returnValue({value: '[{\"serverType\":\"PostgreSQL 9.6\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"90600\",\"next_major_version\":\"100000\"},{\"serverType\":\"PostgreSQL 10\",\"binaryPath\":\"/Library/PostgreSQL/10/bin\",\"isDefault\":false,\"version\":\"100000\",\"next_major_version\":\"110000\"},{\"serverType\":\"PostgreSQL 11\",\"binaryPath\":\"/Library/PostgreSQL/11/bin\",\"isDefault\":false,\"version\":\"110000\",\"next_major_version\":\"120000\"},{\"serverType\":\"PostgreSQL 12\",\"binaryPath\":\"/Library/PostgreSQL/12/bin\",\"isDefault\":false,\"version\":\"120000\",\"next_major_version\":\"130000\"},{\"serverType\":\"PostgreSQL 13\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"130000\",\"next_major_version\":\"140000\"}]'});
|
||||
});
|
||||
|
||||
context('server is a PostgreSQL server', () => {
|
||||
it('display an alert with "Configuration required"', () => {
|
||||
backupDialog.draw(null, [serverTreeNodeWrongPath], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Configuration required',
|
||||
'Please configure the PostgreSQL Binary Path in the Preferences dialog.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('binary folder is configured', () => {
|
||||
let globalResizeToSpy;
|
||||
let serverResizeToSpy;
|
||||
beforeEach(() => {
|
||||
globalResizeToSpy = jasmine.createSpyObj('globals', ['resizeTo']);
|
||||
alertifySpy['BackupDialog_globals'].and
|
||||
.returnValue(globalResizeToSpy);
|
||||
serverResizeToSpy = jasmine.createSpyObj('server', ['resizeTo']);
|
||||
alertifySpy['BackupDialog_server'].and
|
||||
.returnValue(serverResizeToSpy);
|
||||
pgBrowser.get_preference.and.returnValue({value: '[{\"serverType\":\"PostgreSQL 9.6\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"90600\",\"next_major_version\":\"100000\"},{\"serverType\":\"PostgreSQL 10\",\"binaryPath\":\"/Library/PostgreSQL/10/bin\",\"isDefault\":true,\"version\":\"100000\",\"next_major_version\":\"110000\"},{\"serverType\":\"PostgreSQL 11\",\"binaryPath\":\"/Library/PostgreSQL/11/bin\",\"isDefault\":false,\"version\":\"110000\",\"next_major_version\":\"120000\"},{\"serverType\":\"PostgreSQL 12\",\"binaryPath\":\"/Library/PostgreSQL/12/bin\",\"isDefault\":false,\"version\":\"120000\",\"next_major_version\":\"130000\"},{\"serverType\":\"PostgreSQL 13\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"130000\",\"next_major_version\":\"140000\"}]'});
|
||||
spyOn(backupDialog, 'url_for_utility_exists').and.returnValue('/backup/utility_exists/10/servers');
|
||||
networkMock.onGet('/backup/utility_exists/10/servers').reply(200, {'success': 1});
|
||||
});
|
||||
|
||||
context('dialog for global backup ', () => {
|
||||
it('displays the dialog when binary path is for correct server version', (done) => {
|
||||
backupDialog.draw(null, [serverTreeNode], {globals: true}, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy['BackupDialog_globals']).toHaveBeenCalledWith(true);
|
||||
expect(globalResizeToSpy.resizeTo).toHaveBeenCalledWith(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
context('dialog for server backup', () => {
|
||||
it('displays the dialog when binary path is for correct server version', (done) => {
|
||||
backupDialog.draw(null, [serverTreeNode], {server: true}, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy['BackupDialog_server']).toHaveBeenCalledWith(true);
|
||||
expect(serverResizeToSpy.resizeTo).toHaveBeenCalledWith(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
context('dialog for global backup ', () => {
|
||||
it('displays the dialog when default binary path is specified', (done) => {
|
||||
backupDialog.draw(null, [serverTreeNodeWrongPath], {globals: true}, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy['BackupDialog_globals']).toHaveBeenCalledWith(true);
|
||||
expect(globalResizeToSpy.resizeTo).toHaveBeenCalledWith(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
context('dialog for server backup', () => {
|
||||
it('displays the dialog when default binary path is specified', (done) => {
|
||||
backupDialog.draw(null, [serverTreeNodeWrongPath], {server: true}, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy['BackupDialog_server']).toHaveBeenCalledWith(true);
|
||||
expect(serverResizeToSpy.resizeTo).toHaveBeenCalledWith(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
context('preference can be found for EPAS Server', () => {
|
||||
context('binary folder is not configured', () => {
|
||||
beforeEach(() => {
|
||||
pgBrowser.get_preference.and.returnValue({value: '[{\"serverType\":\"EDB Advanced Server 9.6\",\"binaryPath\":\"\",\"isDefault\":false,\"version\":\"90600\",\"next_major_version\":\"100000\"},{\"serverType\":\"EDB Advanced Server 10\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"100000\",\"next_major_version\":\"110000\"},{\"serverType\":\"EDB Advanced Server 11\",\"binaryPath\":\"/Library/EPAS/11/bin/\",\"isDefault\":false,\"version\":\"110000\",\"next_major_version\":\"120000\"},{\"serverType\":\"EDB Advanced Server 12\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"120000\",\"next_major_version\":\"130000\"},{\"serverType\":\"EDB Advanced Server 13\",\"binaryPath\":\"/Library/EPAS/13/bin/\",\"isDefault\":false,\"version\":\"130000\",\"next_major_version\":\"140000\"}]'});
|
||||
});
|
||||
|
||||
context('server is a EPAS server', () => {
|
||||
it('display an alert with "Configuration required"', () => {
|
||||
backupDialog.draw(null, [ppasServerTreeNodeWrongPath], null);
|
||||
expect(alertifySpy.alert).toHaveBeenCalledWith(
|
||||
'Configuration required',
|
||||
'Please configure the EDB Advanced Server Binary Path in the Preferences dialog.'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('binary folder is configured', () => {
|
||||
let globalResizeToSpy;
|
||||
let serverResizeToSpy;
|
||||
beforeEach(() => {
|
||||
globalResizeToSpy = jasmine.createSpyObj('globals', ['resizeTo']);
|
||||
alertifySpy['BackupDialog_globals'].and
|
||||
.returnValue(globalResizeToSpy);
|
||||
serverResizeToSpy = jasmine.createSpyObj('server', ['resizeTo']);
|
||||
alertifySpy['BackupDialog_server'].and
|
||||
.returnValue(serverResizeToSpy);
|
||||
pgBrowser.get_preference.and.returnValue({value: '[{\"serverType\":\"EDB Advanced Server 9.6\",\"binaryPath\":\"\",\"isDefault\":false,\"version\":\"90600\",\"next_major_version\":\"100000\"},{\"serverType\":\"EDB Advanced Server 10\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"100000\",\"next_major_version\":\"110000\"},{\"serverType\":\"EDB Advanced Server 11\",\"binaryPath\":\"/Library/EPAS/11/bin/\",\"isDefault\":false,\"version\":\"110000\",\"next_major_version\":\"120000\"},{\"serverType\":\"EDB Advanced Server 12\",\"binaryPath\":null,\"isDefault\":false,\"version\":\"120000\",\"next_major_version\":\"130000\"},{\"serverType\":\"EDB Advanced Server 13\",\"binaryPath\":\"/Library/EPAS/13/bin/\",\"isDefault\":true,\"version\":\"130000\",\"next_major_version\":\"140000\"}]'});
|
||||
spyOn(backupDialog, 'url_for_utility_exists').and.returnValue('/backup/utility_exists/10/servers');
|
||||
networkMock.onGet('/backup/utility_exists/10/servers').reply(200, {'success': 1});
|
||||
});
|
||||
|
||||
context('dialog for global backup ', () => {
|
||||
it('displays the dialog when binary path is for correct server version', (done) => {
|
||||
backupDialog.draw(null, [ppasServerTreeNode], {globals: true}, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy['BackupDialog_globals']).toHaveBeenCalledWith(true);
|
||||
expect(globalResizeToSpy.resizeTo).toHaveBeenCalledWith(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
context('dialog for server backup', () => {
|
||||
it('displays the dialog when binary path is for correct server version', (done) => {
|
||||
backupDialog.draw(null, [ppasServerTreeNode], {server: true}, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy['BackupDialog_server']).toHaveBeenCalledWith(true);
|
||||
expect(serverResizeToSpy.resizeTo).toHaveBeenCalledWith(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
context('dialog for global backup ', () => {
|
||||
it('displays the dialog when default binary path is specified', (done) => {
|
||||
backupDialog.draw(null, [ppasServerTreeNodeWrongPath], {globals: true}, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy['BackupDialog_globals']).toHaveBeenCalledWith(true);
|
||||
expect(globalResizeToSpy.resizeTo).toHaveBeenCalledWith(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
context('dialog for server backup', () => {
|
||||
it('displays the dialog when default binary path is specified', (done) => {
|
||||
backupDialog.draw(null, [ppasServerTreeNodeWrongPath], {server: true}, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
setTimeout(() => {
|
||||
expect(alertifySpy['BackupDialog_server']).toHaveBeenCalledWith(true);
|
||||
expect(serverResizeToSpy.resizeTo).toHaveBeenCalledWith(pgBrowser.stdW.md, pgBrowser.stdH.md);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
96
web/regression/javascript/schema_ui_files/backup.ui.spec.js
Normal file
@ -0,0 +1,96 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import React from 'react';
|
||||
import '../helper/enzyme.helper';
|
||||
import { createMount } from '@material-ui/core/test-utils';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
import SchemaView from '../../../pgadmin/static/js/SchemaView';
|
||||
import BackupSchema, {getSectionSchema, getTypeObjSchema, getSaveOptSchema, getQueryOptionSchema, getDisabledOptionSchema, getMiscellaneousSchema} from '../../../pgadmin/tools/backup/static/js/backup.ui';
|
||||
|
||||
|
||||
describe('BackupSchema', ()=>{
|
||||
let mount;
|
||||
beforeAll(()=>{
|
||||
mount = createMount();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mount.cleanUp();
|
||||
});
|
||||
let backupSchemaObj = new BackupSchema(
|
||||
()=> getSectionSchema(),
|
||||
()=> getTypeObjSchema(),
|
||||
()=> getSaveOptSchema({nodeInfo: {server: {version: 11000}}}),
|
||||
()=> getQueryOptionSchema({nodeInfo: {server: {version: 11000}}}),
|
||||
()=> getDisabledOptionSchema({nodeInfo: {server: {version: 11000}}}),
|
||||
()=> getMiscellaneousSchema({nodeInfo: {server: {version: 11000}}}),
|
||||
{
|
||||
role: ()=>[],
|
||||
encoding: ()=>[],
|
||||
},
|
||||
{server: {version: 11000}},
|
||||
pgAdmin.pgBrowser,
|
||||
'backup_objects'
|
||||
);
|
||||
|
||||
it('create object backup', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={backupSchemaObj}
|
||||
viewHelperProps={{
|
||||
mode: 'create',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
disableDialogHelp={false}
|
||||
/>);
|
||||
});
|
||||
|
||||
|
||||
let backupServerSchemaObj = new BackupSchema(
|
||||
()=> getSectionSchema(),
|
||||
()=> getTypeObjSchema(),
|
||||
()=> getSaveOptSchema({nodeInfo: {server: {version: 11000}}}),
|
||||
()=> getQueryOptionSchema({nodeInfo: {server: {version: 11000}}}),
|
||||
()=> getDisabledOptionSchema({nodeInfo: {server: {version: 11000}}}),
|
||||
()=> getMiscellaneousSchema({nodeInfo: {server: {version: 11000}}}),
|
||||
{
|
||||
role: ()=>[],
|
||||
encoding: ()=>[],
|
||||
},
|
||||
{server: {version: 11000}},
|
||||
{serverInfo: {}},
|
||||
'server'
|
||||
);
|
||||
|
||||
it('create server backup', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={backupServerSchemaObj}
|
||||
viewHelperProps={{
|
||||
mode: 'create',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
disableDialogHelp={false}
|
||||
/>);
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,51 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import React from 'react';
|
||||
import '../helper/enzyme.helper';
|
||||
import { createMount } from '@material-ui/core/test-utils';
|
||||
import SchemaView from '../../../pgadmin/static/js/SchemaView';
|
||||
import BackupGlobalSchema, {getMiscellaneousSchema} from '../../../pgadmin/tools/backup/static/js/backupGlobal.ui';
|
||||
|
||||
|
||||
describe('BackupGlobalSchema', ()=>{
|
||||
let mount;
|
||||
beforeAll(()=>{
|
||||
mount = createMount();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
mount.cleanUp();
|
||||
});
|
||||
let backupGlobalSchemaObj = new BackupGlobalSchema(
|
||||
()=> getMiscellaneousSchema(),
|
||||
{
|
||||
role: ()=>[],
|
||||
}
|
||||
);
|
||||
|
||||
it('create', ()=>{
|
||||
mount(<SchemaView
|
||||
formType='dialog'
|
||||
schema={backupGlobalSchemaObj}
|
||||
viewHelperProps={{
|
||||
mode: 'create',
|
||||
}}
|
||||
onSave={()=>{}}
|
||||
onClose={()=>{}}
|
||||
onHelp={()=>{}}
|
||||
onDataChange={()=>{}}
|
||||
confirmOnCloseReset={false}
|
||||
hasSQL={false}
|
||||
disableSqlHelp={false}
|
||||
disableDialogHelp={false}
|
||||
/>);
|
||||
});
|
||||
});
|
||||
|