Extract the tests and refactor some of the methods.

Extract some of the ACI Tree functionalities, and decouple it from the
main source. Also - create some abstractions from the repeated code
around the enable/disable the schema children object create/edit/delete
functionalities, and also created the dialog wrappers for backup and
restore dialogs.

Reviewed by: Khushboo and Ashesh
Refactored by: Ashesh
This commit is contained in:
Joao De Almeida Pereira
2018-06-05 16:06:19 +05:30
committed by Ashesh Vashi
parent 920934759f
commit 7dd6372eeb
75 changed files with 5186 additions and 1939 deletions

View File

@@ -0,0 +1,18 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
export const restoreSupportedNodes = [
'database',
'schema',
'table',
'function',
'trigger',
'index',
'partition',
];

View File

@@ -1,11 +1,13 @@
// Restore dialog
define('tools.restore', [
'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'backbone',
'underscore.string', 'pgadmin.alertifyjs', 'pgadmin.browser',
'pgadmin.backgrid', 'pgadmin.backform', 'sources/utils',
'tools/restore/static/js/menu_utils',
'sources/nodes/supported_database_node',
'tools/restore/static/js/restore_dialog',
], function(
gettext, url_for, $, _, Backbone, S, alertify, pgBrowser, Backgrid, Backform,
commonUtils
commonUtils, menuUtils, supportedNodes, restoreDialog
) {
// if module is already initialized, refer to that.
@@ -307,59 +309,6 @@ commonUtils
this.initialized = true;
// Define list of nodes on which restore context menu option appears
var restore_supported_nodes = [
'database', 'schema',
'table', 'function',
'trigger', 'index',
'partition',
];
/**
Enable/disable restore menu in tools based
on node selected
if selected node is present in supported_nodes,
menu will be enabled otherwise disabled.
Also, hide it for system view in catalogs
*/
var menu_enabled = function(itemData, item, data) {
var t = pgBrowser.tree,
i = item,
d = itemData;
var parent_item = t.hasParent(i) ? t.parent(i) : null,
parent_data = parent_item ? t.itemData(parent_item) : null;
if (!_.isUndefined(d) && !_.isNull(d) && !_.isNull(parent_data)) {
if (_.indexOf(restore_supported_nodes, d._type) !== -1 &&
is_parent_catalog(itemData, item, data)) {
if (d._type == 'database' && d.allowConn)
return true;
else if (d._type != 'database')
return true;
else
return false;
} else
return false;
} else
return false;
};
var is_parent_catalog = function(itemData, item) {
var t = pgBrowser.tree,
i = item,
d = itemData;
// To iterate over tree to check parent node
while (i) {
// If it is schema then allow user to restore
if (_.indexOf(['catalog'], d._type) > -1)
return false;
i = t.hasParent(i) ? t.parent(i) : null;
d = i ? t.itemData(i) : null;
}
// by default we do not want to allow create menu
return true;
};
// Define the nodes on which the menus to be appear
var menus = [{
name: 'restore_object',
@@ -369,20 +318,24 @@ commonUtils
priority: 13,
label: gettext('Restore...'),
icon: 'fa fa-upload',
enable: menu_enabled,
enable: supportedNodes.enabled.bind(
null, pgBrowser.treeMenu, menuUtils.restoreSupportedNodes
),
}];
for (var idx = 0; idx < restore_supported_nodes.length; idx++) {
for (var idx = 0; idx < menuUtils.restoreSupportedNodes.length; idx++) {
menus.push({
name: 'restore_' + restore_supported_nodes[idx],
node: restore_supported_nodes[idx],
name: 'restore_' + menuUtils.restoreSupportedNodes[idx],
node: menuUtils.restoreSupportedNodes[idx],
module: this,
applies: ['context'],
callback: 'restore_objects',
priority: 13,
label: gettext('Restore...'),
icon: 'fa fa-upload',
enable: menu_enabled,
enable: supportedNodes.enabled.bind(
null, pgBrowser.treeMenu, menuUtils.restoreSupportedNodes
),
});
}
@@ -391,318 +344,10 @@ commonUtils
},
// Callback to draw Backup Dialog for objects
restore_objects: function(action, treeItem) {
var i = treeItem || pgBrowser.tree.selected(),
server_data = null;
while (i) {
var node_data = pgBrowser.tree.itemData(i);
if (node_data._type == 'server') {
server_data = node_data;
break;
}
if (pgBrowser.tree.hasParent(i)) {
i = $(pgBrowser.tree.parent(i));
} else {
alertify.alert(
gettext('Restore Error'),
gettext('Please select server or child node from tree.')
);
break;
}
}
if (!server_data) {
return;
}
var module = 'paths',
preference_name = 'pg_bin_dir',
msg = gettext('Please configure the PostgreSQL Binary Path in the Preferences dialog.');
if ((server_data.type && server_data.type == 'ppas') ||
server_data.server_type == 'ppas') {
preference_name = 'ppas_bin_dir';
msg = gettext('Please configure the EDB Advanced Server Binary Path in the Preferences dialog.');
}
var preference = pgBrowser.get_preference(module, preference_name);
if (preference) {
if (!preference.value) {
alertify.alert(gettext('Configuration required'), msg);
return;
}
} else {
alertify.alert(
gettext('Restore Error'),
S(gettext('Failed to load preference %s of module %s')).sprintf(preference_name, module).value()
);
return;
}
var title = S(gettext('Restore (%s: %s)')),
tree = pgBrowser.tree,
item = treeItem || tree.selected(),
data = item && item.length == 1 && tree.itemData(item),
node = data && data._type && pgBrowser.Nodes[data._type];
if (!node)
return;
var treeInfo = node.getTreeNodeHierarchy.apply(node, [item]);
if (treeInfo.database._label.indexOf('=') >= 0) {
alertify.alert(
gettext('Restore error'),
gettext('Restore job creation failed. '+
'Databases with = symbols in the name cannot be restored using this utility.')
);
return;
}
title = title.sprintf(node.label, data.label).value();
if (!alertify.pg_restore) {
// Create Dialog title on the fly with node details
alertify.dialog('pg_restore', function factory() {
return {
main: function(title, item, data, node) {
this.set('title', title);
this.setting('pg_node', node);
this.setting('pg_item', item);
this.setting('pg_item_data', data);
},
build: function() {
alertify.pgDialogBuild.apply(this);
},
setup: function() {
return {
buttons: [{
text: '',
className: 'btn btn-default pull-left fa fa-lg fa-info',
attrs: {
name: 'object_help',
type: 'button',
url: 'backup.html',
label: gettext('Restore'),
},
}, {
text: '',
key: 112,
className: 'btn btn-default pull-left fa fa-lg fa-question',
attrs: {
name: 'dialog_help',
type: 'button',
label: gettext('Restore'),
url: url_for('help.static', {
'filename': 'restore_dialog.html',
}),
},
}, {
text: gettext('Restore'),
key: 13,
className: 'btn btn-primary fa fa-upload pg-alertify-button',
restore: true,
'data-btn-name': 'restore',
}, {
text: gettext('Cancel'),
key: 27,
className: 'btn btn-danger fa fa-lg fa-times pg-alertify-button',
restore: false,
'data-btn-name': 'cancel',
}],
// Set options for dialog
options: {
title: title,
//disable both padding and overflow control.
padding: !1,
overflow: !1,
model: 0,
resizable: true,
maximizable: true,
pinnable: false,
closableByDimmer: false,
modal: false,
},
};
},
hooks: {
// triggered when the dialog is closed
onclose: function() {
if (this.view) {
this.view.remove({
data: true,
internal: true,
silent: true,
});
}
},
},
settings: {
pg_node: null,
pg_item: null,
pg_item_data: null,
},
prepare: function() {
var self = this;
// Disable Backup button until user provides Filename
this.__internal.buttons[2].element.disabled = true;
var $container = $('<div class=\'restore_dialog\'></div>');
var t = pgBrowser.tree,
i = t.selected(),
d = i && i.length == 1 ? t.itemData(i) : undefined,
node = d && pgBrowser.Nodes[d._type];
if (!d)
return;
var treeInfo = node.getTreeNodeHierarchy.apply(node, [i]);
var newModel = new RestoreObjectModel({
node_data: node,
}, {
node_info: treeInfo,
}),
fields = Backform.generateViewSchema(
treeInfo, newModel, 'create', node, treeInfo.server, true
);
var view = this.view = new Backform.Dialog({
el: $container,
model: newModel,
schema: fields,
});
$(this.elements.body.childNodes[0]).addClass(
'alertify_tools_dialog_properties obj_properties'
);
view.render();
this.elements.content.appendChild($container.get(0));
view.$el.attr('tabindex', -1);
// var dialogTabNavigator = pgBrowser.keyboardNavigation.getDialogTabNavigator(view);
pgBrowser.keyboardNavigation.getDialogTabNavigator(view);
var container = view.$el.find('.tab-content:first > .tab-pane.active:first');
commonUtils.findAndSetFocus(container);
// Listen to model & if filename is provided then enable Backup button
this.view.model.on('change', function() {
if (!_.isUndefined(this.get('file')) && this.get('file') !== '') {
this.errorModel.clear();
self.__internal.buttons[2].element.disabled = false;
} else {
self.__internal.buttons[2].element.disabled = true;
this.errorModel.set('file', gettext('Please provide filename'));
}
});
},
// Callback functions when click on the buttons of the Alertify dialogs
callback: function(e) {
// Fetch current server id
var t = pgBrowser.tree,
i = this.settings['pg_item'] || t.selected(),
d = this.settings['pg_item_data'] || (
i && i.length == 1 ? t.itemData(i) : undefined
),
node = this.settings['pg_node'] || (
d && pgBrowser.Nodes[d._type]
);
if (e.button.element.name == 'dialog_help' || e.button.element.name == 'object_help') {
e.cancel = true;
pgBrowser.showHelp(e.button.element.name, e.button.element.getAttribute('url'),
node, i, e.button.element.getAttribute('label'));
return;
}
if (e.button['data-btn-name'] === 'restore') {
if (!d)
return;
var info = node.getTreeNodeHierarchy.apply(node, [i]),
m = this.view.model;
// Set current node info into model
m.set('database', info.database._label);
if (!m.get('custom')) {
switch (d._type) {
case 'schema':
m.set('schemas', [d._label]);
break;
case 'table':
m.set('schemas', [info.schema._label]);
m.set('tables', [d._label]);
break;
case 'function':
m.set('schemas', [info.schema._label]);
m.set('functions', [d._label]);
break;
case 'index':
m.set('schemas', [info.schema._label]);
m.set('indexes', [d._label]);
break;
case 'trigger':
m.set('schemas', [info.schema._label]);
m.set('triggers', [d._label]);
break;
case 'trigger_func':
m.set('schemas', [info.schema._label]);
m.set('trigger_funcs', [d._label]);
break;
}
} else {
// TODO::
// When we will implement the object selection in the
// import dialog, we will need to select the objects from
// the tree selection tab.
}
var self = this,
baseUrl = url_for('restore.create_job', {
'sid': info.server._id,
}),
args = this.view.model.toJSON();
$.ajax({
url: baseUrl,
method: 'POST',
data: {
'data': JSON.stringify(args),
},
success: function(res) {
if (res.success) {
alertify.success(
gettext('Restore job created.'), 5
);
pgBrowser.Events.trigger('pgadmin-bgprocess:created', self);
} else {
console.warn(res);
}
},
error: function(xhr) {
try {
var err = JSON.parse(xhr.responseText);
alertify.alert(
gettext('Restore failed.'),
err.errormsg
);
} catch (e) {
console.warn(e.stack || e);
}
},
});
}
},
};
});
}
alertify.pg_restore(title, item, data, node).resizeTo('65%', '60%');
let dialog = new restoreDialog.RestoreDialog(
pgBrowser, $, alertify, RestoreObjectModel
);
dialog.draw(action, treeItem);
},
};
return pgBrowser.Restore;

View File

@@ -0,0 +1,322 @@
diff a/web/pgadmin/tools/restore/static/js/restore.js b/web/pgadmin/tools/restore/static/js/restore.js (rejected hunks)
@@ -391,318 +344,8 @@ commonUtils
},
// Callback to draw Backup Dialog for objects
restore_objects: function(action, treeItem) {
-
- var i = treeItem || pgBrowser.tree.selected(),
- server_data = null;
-
- while (i) {
- var node_data = pgBrowser.tree.itemData(i);
- if (node_data._type == 'server') {
- server_data = node_data;
- break;
- }
-
- if (pgBrowser.tree.hasParent(i)) {
- i = $(pgBrowser.tree.parent(i));
- } else {
- alertify.alert(
- gettext('Restore Error'),
- gettext('Please select server or child node from tree.')
- );
- break;
- }
- }
-
- if (!server_data) {
- return;
- }
-
- var module = 'paths',
- preference_name = 'pg_bin_dir',
- msg = gettext('Please configure the PostgreSQL Binary Path in the Preferences dialog.');
-
- if ((server_data.type && server_data.type == 'ppas') ||
- server_data.server_type == 'ppas') {
- preference_name = 'ppas_bin_dir';
- msg = gettext('Please configure the EDB Advanced Server Binary Path in the Preferences dialog.');
- }
-
- var preference = pgBrowser.get_preference(module, preference_name);
-
- if (preference) {
- if (!preference.value) {
- alertify.alert(gettext('Configuration required'), msg);
- return;
- }
- } else {
- alertify.alert(
- gettext('Restore Error'),
- S(gettext('Failed to load preference %s of module %s')).sprintf(preference_name, module).value()
- );
- return;
- }
-
- var title = S(gettext('Restore (%s: %s)')),
- tree = pgBrowser.tree,
- item = treeItem || tree.selected(),
- data = item && item.length == 1 && tree.itemData(item),
- node = data && data._type && pgBrowser.Nodes[data._type];
-
- if (!node)
- return;
-
- var treeInfo = node.getTreeNodeHierarchy.apply(node, [item]);
-
- if (treeInfo.database._label.indexOf('=') >= 0) {
- alertify.alert(
- gettext('Restore error'),
- gettext('Restore job creation failed. '+
- 'Databases with = symbols in the name cannot be restored using this utility.')
- );
- return;
- }
-
- title = title.sprintf(node.label, data.label).value();
-
- if (!alertify.pg_restore) {
- // Create Dialog title on the fly with node details
- alertify.dialog('pg_restore', function factory() {
- return {
- main: function(title, item, data, node) {
- this.set('title', title);
- this.setting('pg_node', node);
- this.setting('pg_item', item);
- this.setting('pg_item_data', data);
- },
- build: function() {
- alertify.pgDialogBuild.apply(this);
- },
- setup: function() {
- return {
- buttons: [{
- text: '',
- className: 'btn btn-default pull-left fa fa-lg fa-info',
- attrs: {
- name: 'object_help',
- type: 'button',
- url: 'backup.html',
- label: gettext('Restore'),
- },
- }, {
- text: '',
- key: 112,
- className: 'btn btn-default pull-left fa fa-lg fa-question',
- attrs: {
- name: 'dialog_help',
- type: 'button',
- label: gettext('Restore'),
- url: url_for('help.static', {
- 'filename': 'restore_dialog.html',
- }),
- },
- }, {
- text: gettext('Restore'),
- key: 13,
- className: 'btn btn-primary fa fa-upload pg-alertify-button',
- restore: true,
- 'data-btn-name': 'restore',
- }, {
- text: gettext('Cancel'),
- key: 27,
- className: 'btn btn-danger fa fa-lg fa-times pg-alertify-button',
- restore: false,
- 'data-btn-name': 'cancel',
- }],
- // Set options for dialog
- options: {
- title: title,
- //disable both padding and overflow control.
- padding: !1,
- overflow: !1,
- model: 0,
- resizable: true,
- maximizable: true,
- pinnable: false,
- closableByDimmer: false,
- modal: false,
- },
- };
- },
- hooks: {
- // triggered when the dialog is closed
- onclose: function() {
- if (this.view) {
- this.view.remove({
- data: true,
- internal: true,
- silent: true,
- });
- }
- },
- },
- settings: {
- pg_node: null,
- pg_item: null,
- pg_item_data: null,
- },
- prepare: function() {
-
- var self = this;
- // Disable Backup button until user provides Filename
- this.__internal.buttons[2].element.disabled = true;
- var $container = $('<div class=\'restore_dialog\'></div>');
- var t = pgBrowser.tree,
- i = t.selected(),
- d = i && i.length == 1 ? t.itemData(i) : undefined,
- node = d && pgBrowser.Nodes[d._type];
-
- if (!d)
- return;
-
- var treeInfo = node.getTreeNodeHierarchy.apply(node, [i]);
-
- var newModel = new RestoreObjectModel({
- node_data: node,
- }, {
- node_info: treeInfo,
- }),
- fields = Backform.generateViewSchema(
- treeInfo, newModel, 'create', node, treeInfo.server, true
- );
-
- var view = this.view = new Backform.Dialog({
- el: $container,
- model: newModel,
- schema: fields,
- });
-
- $(this.elements.body.childNodes[0]).addClass(
- 'alertify_tools_dialog_properties obj_properties'
- );
-
- view.render();
-
- this.elements.content.appendChild($container.get(0));
-
- view.$el.attr('tabindex', -1);
- // var dialogTabNavigator = pgBrowser.keyboardNavigation.getDialogTabNavigator(view);
- pgBrowser.keyboardNavigation.getDialogTabNavigator(view);
- var container = view.$el.find('.tab-content:first > .tab-pane.active:first');
- commonUtils.findAndSetFocus(container);
-
- // Listen to model & if filename is provided then enable Backup button
- this.view.model.on('change', function() {
- if (!_.isUndefined(this.get('file')) && this.get('file') !== '') {
- this.errorModel.clear();
- self.__internal.buttons[2].element.disabled = false;
- } else {
- self.__internal.buttons[2].element.disabled = true;
- this.errorModel.set('file', gettext('Please provide filename'));
- }
- });
-
- },
- // Callback functions when click on the buttons of the Alertify dialogs
- callback: function(e) {
- // Fetch current server id
- var t = pgBrowser.tree,
- i = this.settings['pg_item'] || t.selected(),
- d = this.settings['pg_item_data'] || (
- i && i.length == 1 ? t.itemData(i) : undefined
- ),
- node = this.settings['pg_node'] || (
- d && pgBrowser.Nodes[d._type]
- );
-
- if (e.button.element.name == 'dialog_help' || e.button.element.name == 'object_help') {
- e.cancel = true;
- pgBrowser.showHelp(e.button.element.name, e.button.element.getAttribute('url'),
- node, i, e.button.element.getAttribute('label'));
- return;
- }
-
- if (e.button['data-btn-name'] === 'restore') {
- if (!d)
- return;
-
- var info = node.getTreeNodeHierarchy.apply(node, [i]),
- m = this.view.model;
- // Set current node info into model
- m.set('database', info.database._label);
- if (!m.get('custom')) {
- switch (d._type) {
- case 'schema':
- m.set('schemas', [d._label]);
- break;
- case 'table':
- m.set('schemas', [info.schema._label]);
- m.set('tables', [d._label]);
- break;
- case 'function':
- m.set('schemas', [info.schema._label]);
- m.set('functions', [d._label]);
- break;
- case 'index':
- m.set('schemas', [info.schema._label]);
- m.set('indexes', [d._label]);
- break;
- case 'trigger':
- m.set('schemas', [info.schema._label]);
- m.set('triggers', [d._label]);
- break;
- case 'trigger_func':
- m.set('schemas', [info.schema._label]);
- m.set('trigger_funcs', [d._label]);
- break;
- }
- } else {
- // TODO::
- // When we will implement the object selection in the
- // import dialog, we will need to select the objects from
- // the tree selection tab.
- }
-
- var self = this,
- baseUrl = url_for('restore.create_job', {
- 'sid': info.server._id,
- }),
- args = this.view.model.toJSON();
-
- $.ajax({
- url: baseUrl,
- method: 'POST',
- data: {
- 'data': JSON.stringify(args),
- },
- success: function(res) {
- if (res.success) {
- alertify.success(
- gettext('Restore job created.'), 5
- );
- pgBrowser.Events.trigger('pgadmin-bgprocess:created', self);
- } else {
- console.warn(res);
- }
- },
- error: function(xhr) {
- try {
- var err = $.parseJSON(xhr.responseText);
- alertify.alert(
- gettext('Restore failed.'),
- err.errormsg
- );
- } catch (e) {
- console.warn(e.stack || e);
- }
- },
- });
- }
- },
- };
- });
- }
-
- alertify.pg_restore(title, item, data, node).resizeTo('65%', '60%');
+ let dialog = new restoreDialog.RestoreDialog(pgBrowser, $, alertify, RestoreObjectModel);
+ dialog.draw(action, treeItem);
},
};
return pgBrowser.Restore;

View File

@@ -0,0 +1,57 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import gettext from '../../../../static/js/gettext';
import {sprintf} from 'sprintf-js';
import Backform from '../../../../static/js/backform.pgadmin';
import {Dialog} from '../../../../static/js/alertify/dialog';
export class RestoreDialog extends Dialog {
constructor(pgBrowser, $, alertify, RestoreModel, backform = Backform) {
super('Restore Error',
'<div class=\'restore_dialog\'></div>',
pgBrowser, $, alertify, RestoreModel, backform);
}
draw(action, aciTreeItem) {
const serverInformation = this.retrieveAncestorOfTypeServer(aciTreeItem);
if (!serverInformation) {
return;
}
if (!this.hasBinariesConfiguration(serverInformation)) {
return;
}
if (!this.canExecuteOnCurrentDatabase(aciTreeItem)) {
return;
}
let aciTreeItem1 = aciTreeItem || this.pgBrowser.treeMenu.selected();
let item = this.pgBrowser.treeMenu.findNodeByDomElement(aciTreeItem1);
const data = item.getData();
const node = this.pgBrowser.Nodes[data._type];
if (!node)
return;
let title = sprintf(gettext('Restore (%s: %s)'), node.label, data.label);
this.createOrGetDialog(title, 'restore');
this.alertify.pg_restore(title, aciTreeItem1, data, node).resizeTo('65%', '60%');
}
dialogName() {
return 'pg_restore';
}
}

View File

@@ -0,0 +1,255 @@
import {getTreeNodeHierarchyFromElement} from '../../../../static/js/tree/pgadmin_tree_node';
import axios from 'axios/index';
import _ from 'underscore';
import gettext from '../../../../static/js/gettext';
import url_for from '../../../../static/js/url_for';
import {DialogWrapper} from '../../../../static/js/alertify/dialog_wrapper';
export class RestoreDialogWrapper extends DialogWrapper {
constructor(dialogContainerSelector, dialogTitle, typeOfDialog,
jquery, pgBrowser, alertify, dialogModel, backform) {
super(dialogContainerSelector, dialogTitle, jquery,
pgBrowser, alertify, dialogModel, backform);
}
main(title, item, data, node) {
this.set('title', title);
this.setting('pg_node', node);
this.setting('pg_item', item);
this.setting('pg_item_data', data);
}
setup() {
return {
buttons: [{
text: '',
className: 'btn btn-default pull-left fa fa-lg fa-info',
attrs: {
name: 'object_help',
type: 'button',
url: 'backup.html',
label: gettext('Restore'),
},
}, {
text: '',
key: 112,
className: 'btn btn-default pull-left fa fa-lg fa-question',
attrs: {
name: 'dialog_help',
type: 'button',
label: gettext('Restore'),
url: url_for('help.static', {
'filename': 'restore_dialog.html',
}),
},
}, {
text: gettext('Restore'),
key: 13,
className: 'btn btn-primary fa fa-upload pg-alertify-button',
restore: true,
'data-btn-name': 'restore',
}, {
text: gettext('Cancel'),
key: 27,
className: 'btn btn-danger fa fa-lg fa-times pg-alertify-button',
restore: false,
'data-btn-name': 'cancel',
}],
// 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.disableRestoreButton();
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];
const treeInfo = getTreeNodeHierarchyFromElement(this.pgBrowser, selectedTreeNode);
const dialog = this.createDialog(node, treeInfo, $container);
this.addAlertifyClassToRestoreNodeChildNodes();
dialog.render();
this.elements.content.appendChild($container.get(0));
this.focusOnDialog(dialog);
this.setListenersForFilenameChanges();
}
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,
event.button.element.getAttribute('label')
);
return;
}
if (this.wasRestoreButtonPressed(event)) {
if (!selectedTreeNodeData)
return;
const serverIdentifier = this.retrieveServerIdentifier(node, selectedTreeNode);
const dialogWrapper = this;
let urlShortcut = 'restore.create_job';
const baseUrl = url_for(urlShortcut, {
'sid': serverIdentifier,
});
const treeInfo = getTreeNodeHierarchyFromElement(
this.pgBrowser,
selectedTreeNode
);
this.setExtraParameters(selectedTreeNode, treeInfo);
let service = axios.create({});
service.post(
baseUrl,
this.view.model.toJSON()
).then(function () {
dialogWrapper.alertify.success(gettext('Restore job created.'), 5);
dialogWrapper.pgBrowser.Events.trigger('pgadmin-bgprocess:created', dialogWrapper);
}).catch(function (error) {
try {
const err = error.response.data;
dialogWrapper.alertify.alert(
gettext('Restore job failed.'),
err.errormsg
);
} catch (e) {
console.warn(e.stack || e);
}
});
}
}
addAlertifyClassToRestoreNodeChildNodes() {
this.jquery(this.elements.body.childNodes[0]).addClass(
'alertify_tools_dialog_properties obj_properties'
);
}
getSelectedNode() {
const tree = this.pgBrowser.treeMenu;
const selectedNode = tree.selected();
if (selectedNode) {
return tree.findNodeByDomElement(selectedNode);
} else {
return undefined;
}
}
disableRestoreButton() {
this.__internal.buttons[2].element.disabled = true;
}
enableRestoreButton() {
this.__internal.buttons[2].element.disabled = false;
}
createDialog(node, treeInfo, $container) {
const newModel = new this.dialogModel({
node_data: node,
}, {
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 = getTreeNodeHierarchyFromElement(
this.pgBrowser,
selectedTreeNode
);
return treeInfo.server._id;
}
setListenersForFilenameChanges() {
const self = this;
this.view.model.on('change', function () {
if (!_.isUndefined(this.get('file')) && this.get('file') !== '') {
this.errorModel.clear();
self.enableRestoreButton();
} else {
self.disableRestoreButton();
this.errorModel.set('file', gettext('Please provide a filename'));
}
});
}
setExtraParameters(selectedTreeNode, treeInfo) {
this.view.model.set('database', treeInfo.database._label);
if (!this.view.model.get('custom')) {
const nodeData = selectedTreeNode.getData();
switch (nodeData._type) {
case 'schema':
this.view.model.set('schemas', [nodeData._label]);
break;
case 'table':
this.view.model.set('schemas', [treeInfo.schema._label]);
this.view.model.set('tables', [nodeData._label]);
break;
case 'function':
this.view.model.set('schemas', [treeInfo.schema._label]);
this.view.model.set('functions', [nodeData._label]);
break;
case 'index':
this.view.model.set('schemas', [treeInfo.schema._label]);
this.view.model.set('indexes', [nodeData._label]);
break;
case 'trigger':
this.view.model.set('schemas', [treeInfo.schema._label]);
this.view.model.set('triggers', [nodeData._label]);
break;
case 'trigger_func':
this.view.model.set('schemas', [treeInfo.schema._label]);
this.view.model.set('trigger_funcs', [nodeData._label]);
break;
}
}
}
wasRestoreButtonPressed(event) {
return event.button['data-btn-name'] === 'restore';
}
}