mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
- Base font size changed from 0.815rem to 0.875rem, for navbar from 0.875rem to 0.925rem. - Dialog sizes made consistent throughout the application. Now there are 3 size options for width and height each - sm, md, lg. Combination of any of these to be used hereafter - Alignment fix for controls of Node properties dialogs which includes showing text and label in one line without dialog size change, checkbox alignment, switch control alignment at places and other minor improvements in other dialogs - Error message design change in dialogs validation - SQL Editor data grid editor popup design changes which were missed - Design change for dashboard server activity grid - Login page language dropdown color fix - Properties accordion collapse design fix - Help, Info icon fixed across all dialogs which were not working if clicked exactly on the text - Added missing icon with buttons at few places - Shadow behind the dialogs is increased to make it look clearly separated and depth. - Control Alignment fix in maintenance dialog - Min height of alertify dialogs set for better UX - File dialog design fix when no files found - Grant wizard fixes - Scroll bar visibility on first page, use full space for SQL generated on the last page - Browser toolbar buttons changed to sync with SQL editor toolbar buttons - Rounded corners for docker floating dialog (no properties) - Renaming file in file dialog should show original file name - SQL data grid text edit popup buttons behaviour was swapped. This is fixed. - Import/Export dialog changes as per new design.
607 lines
18 KiB
JavaScript
607 lines
18 KiB
JavaScript
// Backup dialog
|
|
define([
|
|
'sources/gettext', 'sources/url_for', 'jquery', 'underscore',
|
|
'underscore.string', '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, $, _, S, alertify, Backbone, Backgrid, Backform, pgBrowser,
|
|
commonUtils, menuUtils, globalBackupDialog, supportedNodes
|
|
) {
|
|
|
|
// if module is already initialized, refer to that.
|
|
if (pgBrowser.Backup) {
|
|
return pgBrowser.Backup;
|
|
}
|
|
|
|
/*
|
|
=====================
|
|
TODO LIST FOR BACKUP:
|
|
=====================
|
|
1) Add Object tree on object tab which allows user to select
|
|
objects which can be backed up
|
|
2) Allow user to select/deselect objects
|
|
3) If database is selected in browser
|
|
show all database children objects selected in Object tree
|
|
4) If schema is selected in browser
|
|
show all schema children objects selected in Object tree
|
|
5) If table is selected then show table/schema/database selected
|
|
in Object tree
|
|
6) if root objects like database/schema is not selected and their
|
|
children are selected then add them separately with in tables attribute
|
|
with schema.
|
|
*/
|
|
|
|
Backform.CustomSwitchControl = Backform.SwitchControl.extend({
|
|
template: _.template([
|
|
'<label class="<%=Backform.controlLabelClassName%> custom_switch_label_class"><%=label%></label>',
|
|
'<div class="<%=Backform.controlsClassName%> custom_switch_control_class">',
|
|
' <div class="checkbox">',
|
|
' <label>',
|
|
' <input type="checkbox" class="<%=extraClasses.join(\' \')%>"',
|
|
' name="<%=name%>" <%=value ? "checked=\'checked\'" : ""%>',
|
|
' <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> />',
|
|
' </label>',
|
|
' </div>',
|
|
'</div>',
|
|
'<% if (helpMessage && helpMessage.length) { %>',
|
|
' <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
|
|
'<% } %>',
|
|
].join('\n')),
|
|
className: 'pgadmin-control-group form-group pg-el-md-6 pg-el-12 row',
|
|
});
|
|
|
|
//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'),
|
|
schema: [{
|
|
id: 'verbose',
|
|
label: gettext('Verbose messages'),
|
|
control: Backform.CustomSwitchControl,
|
|
disabled: false,
|
|
group: gettext('Miscellaneous'),
|
|
}, {
|
|
id: 'dqoute',
|
|
label: gettext('Force double quote on identifiers'),
|
|
control: Backform.CustomSwitchControl,
|
|
disabled: false,
|
|
group: gettext('Miscellaneous'),
|
|
}],
|
|
}, {
|
|
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,
|
|
disabled: false,
|
|
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 && i.length == 1 ? t.itemData(i) : undefined;
|
|
return 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'),
|
|
control: Backform.CustomSwitchControl,
|
|
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'),
|
|
control: Backform.CustomSwitchControl,
|
|
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'),
|
|
control: Backform.CustomSwitchControl,
|
|
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'),
|
|
control: Backform.CustomSwitchControl,
|
|
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'),
|
|
control: Backform.CustomSwitchControl,
|
|
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'),
|
|
control: Backform.CustomSwitchControl,
|
|
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'),
|
|
control: Backform.CustomSwitchControl,
|
|
disabled: false,
|
|
group: gettext('Do not save'),
|
|
}, {
|
|
id: 'dns_privilege',
|
|
label: gettext('Privilege'),
|
|
control: Backform.CustomSwitchControl,
|
|
disabled: false,
|
|
group: gettext('Do not save'),
|
|
}, {
|
|
id: 'dns_tablespace',
|
|
label: gettext('Tablespace'),
|
|
control: Backform.CustomSwitchControl,
|
|
disabled: false,
|
|
group: gettext('Do not save'),
|
|
}, {
|
|
id: 'dns_unlogged_tbl_data',
|
|
label: gettext('Unlogged table data'),
|
|
control: Backform.CustomSwitchControl,
|
|
disabled: false,
|
|
group: gettext('Do not save'),
|
|
}, {
|
|
id: 'no_comments',
|
|
label: gettext('Comments'),
|
|
control: Backform.CustomSwitchControl,
|
|
disabled: false,
|
|
group: gettext('Do not save'),
|
|
visible: function() {
|
|
var t = pgBrowser.tree,
|
|
i = t.selected(),
|
|
d = i && i.length == 1 ? t.itemData(i) : undefined,
|
|
s = pgBrowser.Nodes[d._type].getTreeNodeHierarchy(i)['server'];
|
|
|
|
return 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'),
|
|
control: Backform.CustomSwitchControl,
|
|
disabled: false,
|
|
group: gettext('Queries'),
|
|
}, {
|
|
id: 'use_insert_commands',
|
|
label: gettext('Use Insert Commands'),
|
|
control: Backform.CustomSwitchControl,
|
|
disabled: false,
|
|
group: gettext('Queries'),
|
|
}, {
|
|
id: 'include_create_database',
|
|
label: gettext('Include CREATE DATABASE statement'),
|
|
control: Backform.CustomSwitchControl,
|
|
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'),
|
|
control: Backform.CustomSwitchControl,
|
|
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'),
|
|
control: Backform.CustomSwitchControl,
|
|
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(),
|
|
d = i && i.length == 1 ? t.itemData(i) : undefined,
|
|
s = pgBrowser.Nodes[d._type].getTreeNodeHierarchy(i)['server'];
|
|
|
|
return s.version >= 110000;
|
|
},
|
|
}],
|
|
}, {
|
|
type: 'nested',
|
|
control: 'fieldset',
|
|
label: gettext('Disable'),
|
|
group: gettext('Dump options'),
|
|
contentClass: 'row',
|
|
schema: [{
|
|
id: 'disable_trigger',
|
|
label: gettext('Trigger'),
|
|
control: Backform.CustomSwitchControl,
|
|
group: gettext('Disable'),
|
|
deps: ['only_data'],
|
|
disabled: function(m) {
|
|
return !(m.get('only_data'));
|
|
},
|
|
}, {
|
|
id: 'disable_quoting',
|
|
label: gettext('$ quoting'),
|
|
control: Backform.CustomSwitchControl,
|
|
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)'),
|
|
control: Backform.CustomSwitchControl,
|
|
deps: ['use_column_inserts', 'use_insert_commands'],
|
|
group: gettext('Miscellaneous'),
|
|
disabled: function(m) {
|
|
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'),
|
|
control: Backform.CustomSwitchControl,
|
|
disabled: false,
|
|
group: gettext('Miscellaneous'),
|
|
}, {
|
|
id: 'dqoute',
|
|
label: gettext('Force double quote on identifiers'),
|
|
control: Backform.CustomSwitchControl,
|
|
disabled: false,
|
|
group: gettext('Miscellaneous'),
|
|
}, {
|
|
id: 'use_set_session_auth',
|
|
label: gettext('Use SET SESSION AUTHORIZATION'),
|
|
control: Backform.CustomSwitchControl,
|
|
disabled: false,
|
|
group: gettext('Miscellaneous'),
|
|
}],
|
|
}],
|
|
validate: function() {
|
|
return null;
|
|
},
|
|
});
|
|
|
|
// Create an Object Backup of pgBrowser class
|
|
pgBrowser.Backup = {
|
|
init: function() {
|
|
if (this.initialized)
|
|
return;
|
|
|
|
this.initialized = true;
|
|
|
|
// Define the nodes on which the menus to be appear
|
|
var menus = [{
|
|
name: 'backup_global',
|
|
module: this,
|
|
applies: ['tools'],
|
|
callback: 'start_backup_global',
|
|
priority: 12,
|
|
label: gettext('Backup Globals...'),
|
|
icon: 'fa fa-floppy-o',
|
|
enable: menuUtils.menuEnabledServer,
|
|
}, {
|
|
name: 'backup_server',
|
|
module: this,
|
|
applies: ['tools'],
|
|
callback: 'start_backup_server',
|
|
priority: 12,
|
|
label: gettext('Backup Server...'),
|
|
icon: 'fa fa-floppy-o',
|
|
enable: menuUtils.menuEnabledServer,
|
|
}, {
|
|
name: 'backup_global_ctx',
|
|
module: this,
|
|
node: 'server',
|
|
applies: ['context'],
|
|
callback: 'start_backup_global',
|
|
priority: 12,
|
|
label: gettext('Backup Globals...'),
|
|
icon: 'fa fa-floppy-o',
|
|
enable: menuUtils.menuEnabledServer,
|
|
}, {
|
|
name: 'backup_server_ctx',
|
|
module: this,
|
|
node: 'server',
|
|
applies: ['context'],
|
|
callback: 'start_backup_server',
|
|
priority: 12,
|
|
label: gettext('Backup Server...'),
|
|
icon: 'fa fa-floppy-o',
|
|
enable: menuUtils.menuEnabledServer,
|
|
}, {
|
|
name: 'backup_object',
|
|
module: this,
|
|
applies: ['tools'],
|
|
callback: 'backup_objects',
|
|
priority: 11,
|
|
label: gettext('Backup...'),
|
|
icon: 'fa fa-floppy-o',
|
|
enable: supportedNodes.enabled.bind(
|
|
null, pgBrowser.treeMenu, menuUtils.backupSupportedNodes
|
|
),
|
|
}];
|
|
|
|
for (var idx = 0; idx < menuUtils.backupSupportedNodes.length; idx++) {
|
|
menus.push({
|
|
name: 'backup_' + menuUtils.backupSupportedNodes[idx],
|
|
node: menuUtils.backupSupportedNodes[idx],
|
|
module: this,
|
|
applies: ['context'],
|
|
callback: 'backup_objects',
|
|
priority: 11,
|
|
label: gettext('Backup...'),
|
|
icon: 'fa fa-floppy-o',
|
|
enable: supportedNodes.enabled.bind(
|
|
null, pgBrowser.treeMenu, menuUtils.backupSupportedNodes
|
|
),
|
|
});
|
|
}
|
|
|
|
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.md, pgBrowser.stdH.md);
|
|
},
|
|
start_backup_server: function(action, item) {
|
|
let dialog = new globalBackupDialog.BackupDialog(
|
|
pgBrowser,
|
|
$,
|
|
alertify,
|
|
BackupObjectModel
|
|
);
|
|
dialog.draw(action, item, {'server': true}, pgBrowser.stdW.md, pgBrowser.stdH.md);
|
|
},
|
|
// 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.md, pgBrowser.stdH.md);
|
|
},
|
|
};
|
|
return pgBrowser.Backup;
|
|
});
|