Remove all traces of Backbone, Underscore. #5493
parent
5dca51637c
commit
8d74de09cc
|
@ -200,6 +200,7 @@ babel-plugin-styled-components 1.13.3
|
|||
babel-plugin-syntax-jsx 6.18.0 MIT https://github.com/babel/babel/tree/master/packages/babel-plugin-syntax-jsx
|
||||
babelify 10.0.0 MIT https://github.com/babel/babelify.git
|
||||
backbone 1.4.0 MIT https://github.com/jashkenas/backbone.git
|
||||
backo2 1.0.2 MIT https://github.com/mokesmokes/backo.git
|
||||
balanced-match 1.0.2 MIT git://github.com/juliangruber/balanced-match.git
|
||||
base64-arraybuffer 0.2.0 MIT https://github.com/niklasvh/base64-arraybuffer
|
||||
base64-arraybuffer 1.0.1 MIT https://github.com/niklasvh/base64-arraybuffer
|
||||
|
@ -516,7 +517,6 @@ to-fast-properties 2.0.0
|
|||
to-regex-range 5.0.1 MIT https://github.com/micromatch/to-regex-range.git
|
||||
trim-newlines 4.0.2 MIT https://github.com/sindresorhus/trim-newlines.git
|
||||
unc-path-regex 0.1.2 MIT https://github.com/regexhq/unc-path-regex.git
|
||||
underscore 1.13.1 MIT git://github.com/jashkenas/underscore.git
|
||||
uniqs 2.0.0 MIT git://github.com/fgnass/uniqs.git
|
||||
url-loader 1.1.2 MIT https://github.com/webpack-contrib/url-loader.git
|
||||
util-deprecate 1.0.2 MIT git://github.com/TooTallNate/util-deprecate.git
|
||||
|
|
|
@ -207,8 +207,8 @@ Front End
|
|||
|
||||
pgAdmin uses javascript extensively for the front-end implementation. It uses
|
||||
require.js to allow the lazy loading (or, say load only when required),
|
||||
bootstrap for UI look and feel, Backbone for data manipulation of a node,
|
||||
React for generating properties/create dialog for selected node. We have
|
||||
bootstrap and MaterialUI for UI look and feel, React for generating
|
||||
properties/create dialog for selected node. We have
|
||||
divided each module in small chunks as much as possible. Not all javascript
|
||||
modules are required to be loaded (i.e. loading a javascript module for
|
||||
database will make sense only when a server node is loaded completely.) Please
|
||||
|
|
|
@ -80,9 +80,12 @@ following options (in alphabetical order):
|
|||
+-----------------------------+--------------------------------------------------------------------------------------------------------------------------+
|
||||
| *View Data* | Click to access a context menu that provides several options for viewing data (see below). |
|
||||
+-----------------------------+--------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Generate ERD* | Click to open the ERD tool with automatically generated diagram for the database selected. |
|
||||
| *ERD For Database* | Click to open the ERD tool with automatically generated diagram for the database selected. |
|
||||
| | This option is available only when a database is selected. Options are displayed on the flyout menu. |
|
||||
+-----------------------------+--------------------------------------------------------------------------------------------------------------------------+
|
||||
| *ERD For Table* | Click to open the ERD tool with automatically generated diagram for the table selected. |
|
||||
| | This option is available only when a table is selected. Options are displayed on the flyout menu. |
|
||||
+-----------------------------+--------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
The Tools Menu
|
||||
**************
|
||||
|
|
|
@ -101,7 +101,6 @@
|
|||
"aspen-decorations": "^1.0.2",
|
||||
"axios": "^0.21.1",
|
||||
"babelify": "~10.0.0",
|
||||
"backbone": "1.4.0",
|
||||
"bignumber.js": "^9.0.1",
|
||||
"bootstrap": "^4.3.1",
|
||||
"bootstrap-datepicker": "^1.8.0",
|
||||
|
@ -169,7 +168,6 @@
|
|||
"styled-components": "^5.2.1",
|
||||
"tempusdominus-bootstrap-4": "^5.1.2",
|
||||
"tempusdominus-core": "^5.19.3",
|
||||
"underscore": "^1.13.1",
|
||||
"valid-filename": "^2.0.1",
|
||||
"webcabin-docker": "git+https://github.com/EnterpriseDB/wcDocker/#3df8aac825ee2892f4d824de273b779cc6dbcad8",
|
||||
"wkx": "^0.5.0",
|
||||
|
|
|
@ -92,10 +92,6 @@ define('pgadmin.node.extension', [
|
|||
]);
|
||||
},
|
||||
|
||||
/*
|
||||
* Define model for the Node and specify the properties
|
||||
* of the model in schema.
|
||||
*/
|
||||
getSchema: (treeNodeInfo, itemNodeData)=>{
|
||||
let nodeObj = pgAdmin.Browser.Nodes['extension'];
|
||||
return new ExtensionsSchema(
|
||||
|
|
|
@ -48,19 +48,6 @@ define('pgadmin.node.edbfunc', [
|
|||
},
|
||||
canDrop: false,
|
||||
canDropCascade: false,
|
||||
model: pgBrowser.Node.Model.extend({
|
||||
idAttribute: 'oid',
|
||||
schema: [{
|
||||
id: 'name', label: gettext('Name'), cell: 'string',
|
||||
type: 'text', mode: ['properties'],
|
||||
},{
|
||||
id: 'oid', label: gettext('OID'), cell: 'string',
|
||||
type: 'text' , mode: ['properties'],
|
||||
},{
|
||||
id: 'funcowner', label: gettext('Owner'), cell: 'string',
|
||||
type: 'text', readonly: true,
|
||||
}]
|
||||
}),
|
||||
getSchema: () => {
|
||||
return new EDBFuncSchema(
|
||||
{}, {
|
||||
|
|
|
@ -8,15 +8,14 @@
|
|||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import EDBFuncSchema from './edbfunc.ui';
|
||||
import _ from 'lodash';
|
||||
|
||||
/* Create and Register Procedure Collection and Node. */
|
||||
define('pgadmin.node.edbproc', [
|
||||
'sources/gettext', 'sources/url_for',
|
||||
'sources/pgadmin', 'pgadmin.browser',
|
||||
'pgadmin.node.edbfunc', 'pgadmin.browser.collection',
|
||||
'pgadmin.browser.collection',
|
||||
], function(
|
||||
gettext, url_for, pgAdmin, pgBrowser, EdbFunction
|
||||
gettext, url_for, pgAdmin, pgBrowser
|
||||
) {
|
||||
|
||||
if (!pgBrowser.Nodes['coll-edbproc']) {
|
||||
|
@ -54,24 +53,6 @@ define('pgadmin.node.edbproc', [
|
|||
},
|
||||
canDrop: false,
|
||||
canDropCascade: false,
|
||||
model: EdbFunction.model.extend({
|
||||
defaults: _.extend({},
|
||||
EdbFunction.model.prototype.defaults,
|
||||
{
|
||||
lanname: 'edbspl',
|
||||
}
|
||||
),
|
||||
isVisible: function() {
|
||||
if (this.name == 'sysfunc') { return false; }
|
||||
else if (this.name == 'sysproc') { return true; }
|
||||
return false;
|
||||
},
|
||||
validate: function()
|
||||
{
|
||||
return null;
|
||||
},
|
||||
}
|
||||
),
|
||||
getSchema: () => {
|
||||
return new EDBFuncSchema(
|
||||
{}, {
|
||||
|
|
|
@ -128,15 +128,15 @@ define('pgadmin.node.table', [
|
|||
}
|
||||
]);
|
||||
pgBrowser.Events.on(
|
||||
'pgadmin:browser:node:table:updated', this.onTableUpdated, this
|
||||
'pgadmin:browser:node:table:updated', this.onTableUpdated.bind(this)
|
||||
);
|
||||
pgBrowser.Events.on(
|
||||
'pgadmin:browser:node:type:cache_cleared',
|
||||
this.handle_cache, this
|
||||
this.handle_cache.bind(this)
|
||||
);
|
||||
pgBrowser.Events.on(
|
||||
'pgadmin:browser:node:domain:cache_cleared',
|
||||
this.handle_cache, this
|
||||
this.handle_cache.bind(this)
|
||||
);
|
||||
},
|
||||
callbacks: {
|
||||
|
@ -305,50 +305,6 @@ define('pgadmin.node.table', [
|
|||
getSchema: function(treeNodeInfo, itemNodeData) {
|
||||
return getNodeTableSchema(treeNodeInfo, itemNodeData, pgBrowser);
|
||||
},
|
||||
model: pgBrowser.Node.Model.extend({
|
||||
idAttribute: 'oid',
|
||||
defaults: {
|
||||
name: undefined,
|
||||
oid: undefined,
|
||||
relowner: undefined,
|
||||
description: undefined,
|
||||
is_partitioned: false,
|
||||
},
|
||||
schema: [{
|
||||
id: 'name', label: gettext('Name'), type: 'text',
|
||||
mode: ['properties', 'create', 'edit'], disabled: 'inSchema',
|
||||
},{
|
||||
id: 'oid', label: gettext('OID'), type: 'text', mode: ['properties'],
|
||||
},{
|
||||
id: 'relowner', label: gettext('Owner'), type: 'text', node: 'role',
|
||||
mode: ['properties', 'create', 'edit'], select2: {allowClear: false},
|
||||
disabled: 'inSchema', control: 'node-list-by-name',
|
||||
},{
|
||||
id: 'is_partitioned', label:gettext('Partitioned table?'), cell: 'switch',
|
||||
type: 'switch', mode: ['properties', 'create', 'edit'],
|
||||
visible: 'isVersionGreaterThan96',
|
||||
readonly: function(m) {
|
||||
return !m.isNew();
|
||||
},
|
||||
},{
|
||||
id: 'description', label: gettext('Comment'), type: 'multiline',
|
||||
mode: ['properties', 'create', 'edit'], disabled: 'inSchema',
|
||||
}],
|
||||
sessChanged: function() {
|
||||
/* If only custom autovacuum option is enabled the check if the options table is also changed. */
|
||||
if(_.size(this.sessAttrs) == 2 && this.sessAttrs['autovacuum_custom'] && this.sessAttrs['toast_autovacuum']) {
|
||||
return this.get('vacuum_table').sessChanged() || this.get('vacuum_toast').sessChanged();
|
||||
}
|
||||
if(_.size(this.sessAttrs) == 1 && (this.sessAttrs['autovacuum_custom'] || this.sessAttrs['toast_autovacuum'])) {
|
||||
return this.get('vacuum_table').sessChanged() || this.get('vacuum_toast').sessChanged();
|
||||
}
|
||||
return pgBrowser.DataModel.prototype.sessChanged.apply(this);
|
||||
},
|
||||
// We will disable everything if we are under catalog node
|
||||
inSchema: function() {
|
||||
return this.node_info && 'catalog' in this.node_info;
|
||||
},
|
||||
}),
|
||||
// Check to whether table has disable trigger(s)
|
||||
canCreate_with_trigger_enable: function(itemData, item, data) {
|
||||
return itemData.tigger_count > 0 &&
|
||||
|
|
|
@ -442,7 +442,7 @@ define('pgadmin.node.database', [
|
|||
} else {
|
||||
Notify.success(res.info);
|
||||
}
|
||||
obj.trigger('connected', obj, _item, _data);
|
||||
// obj.trigger('connected', obj, _item, _data);
|
||||
pgBrowser.Events.trigger(
|
||||
'pgadmin:database:connected', _item, _data
|
||||
);
|
||||
|
|
|
@ -66,22 +66,6 @@ define('pgadmin.node.pga_schedule', [
|
|||
getSchema: function() {
|
||||
return new PgaJobScheduleSchema();
|
||||
},
|
||||
|
||||
model: pgBrowser.Node.Model.extend({
|
||||
idAttribute: 'jscid',
|
||||
schema: [{
|
||||
id: 'jscid', label: gettext('ID'), type: 'int',
|
||||
cellHeaderClasses: 'width_percent_5', mode: ['properties'],
|
||||
},{
|
||||
id: 'jscname', label: gettext('Name'), type: 'text',
|
||||
cellHeaderClasses: 'width_percent_45',
|
||||
disabled: function() { return false; },
|
||||
},{
|
||||
id: 'jscenabled', label: gettext('Enabled?'), type: 'switch',
|
||||
disabled: function() { return false; },
|
||||
cellHeaderClasses: 'width_percent_5',
|
||||
}],
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -83,31 +83,6 @@ define('pgadmin.node.pga_job', [
|
|||
);
|
||||
},
|
||||
|
||||
model: pgBrowser.Node.Model.extend({
|
||||
idAttribute: 'jobid',
|
||||
schema: [{
|
||||
id: 'jobname', label: gettext('Name'), type: 'text',
|
||||
cellHeaderClasses: 'width_percent_30',
|
||||
},{
|
||||
id: 'jobid', label: gettext('ID'), mode: ['properties'],
|
||||
type: 'int',
|
||||
},{
|
||||
id: 'jobenabled', label: gettext('Enabled?'), type: 'switch',
|
||||
cellHeaderClasses: 'width_percent_5',
|
||||
},{
|
||||
id: 'jobnextrun', type: 'text', mode: ['properties'],
|
||||
label: gettext('Next run'), cellHeaderClasses: 'width_percent_20',
|
||||
},{
|
||||
id: 'joblastrun', type: 'text', mode: ['properties'],
|
||||
label: gettext('Last run'), cellHeaderClasses: 'width_percent_20',
|
||||
},{
|
||||
id: 'jlgstatus', type: 'text', label: gettext('Last result'),
|
||||
cellHeaderClasses: 'width_percent_5', mode: ['properties'],
|
||||
},{
|
||||
id: 'jobdesc', label: gettext('Comment'), type: 'multiline',
|
||||
cellHeaderClasses: 'width_percent_15',
|
||||
}],
|
||||
}),
|
||||
/* Run pgagent job now */
|
||||
run_pga_job_now: function(args) {
|
||||
let input = args || {},
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import { getNodePgaJobStepSchema } from './pga_jobstep.ui';
|
||||
import _ from 'lodash';
|
||||
|
||||
define('pgadmin.node.pga_jobstep', [
|
||||
'sources/gettext', 'sources/url_for', 'pgadmin.browser',
|
||||
|
@ -74,25 +73,6 @@ define('pgadmin.node.pga_jobstep', [
|
|||
return getNodePgaJobStepSchema(treeNodeInfo, itemNodeData);
|
||||
},
|
||||
|
||||
model: pgBrowser.Node.Model.extend({
|
||||
initialize: function() {
|
||||
pgBrowser.Node.Model.prototype.initialize.apply(this, arguments);
|
||||
if (this.isNew() && this.get('jstconntype')) {
|
||||
let args = arguments.length > 1 && arguments[1];
|
||||
|
||||
if (args) {
|
||||
if (!_.isUndefined(args['node_info']) ||
|
||||
!_.isUndefined(args.collection.top['node_info'])) {
|
||||
this.set(
|
||||
'jstdbname',
|
||||
(args['node_info'] || args.collection.top['node_info'])['server']['db']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
idAttribute: 'jstid',
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -81,22 +81,6 @@ define('pgadmin.node.resource_group', [
|
|||
getSchema: ()=>{
|
||||
return new ResourceGroupSchema();
|
||||
},
|
||||
|
||||
// Defining model for resource group node
|
||||
model: pgBrowser.Node.Model.extend({
|
||||
idAttribute: 'oid',
|
||||
// Defining schema for the resource group node
|
||||
schema: [{
|
||||
id: 'name', label: gettext('Name'), cell: 'string',
|
||||
type: 'text',
|
||||
}, {
|
||||
id: 'cpu_rate_limit', label: gettext('CPU rate limit (percentage)'), cell: 'string',
|
||||
type: 'numeric', min:0, max:16777216,
|
||||
}, {
|
||||
id: 'dirty_rate_limit', label: gettext('Dirty rate limit (KB)'), cell: 'string',
|
||||
type: 'numeric', min:0, max:16777216,
|
||||
}],
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -682,7 +682,7 @@ define('pgadmin.node.server', [
|
|||
// Check the database server against supported version.
|
||||
checkSupportedVersion(_data.version, res.info);
|
||||
|
||||
obj.trigger('connected', obj, _item, _data);
|
||||
// obj.trigger('connected', obj, _item, _data);
|
||||
|
||||
// Generate the event that server is connected
|
||||
pgBrowser.Events.trigger(
|
||||
|
|
|
@ -11,7 +11,6 @@ import { getNodeListByName } from '../../../../../static/js/node_ajax';
|
|||
import { getNodePrivilegeRoleSchema } from '../../../static/js/privilege.ui';
|
||||
import { getNodeVariableSchema } from '../../../static/js/variable.ui';
|
||||
import TablespaceSchema from './tablespace.ui';
|
||||
import _ from 'lodash';
|
||||
|
||||
define('pgadmin.node.tablespace', [
|
||||
'sources/gettext', 'sources/url_for',
|
||||
|
@ -96,35 +95,6 @@ define('pgadmin.node.tablespace', [
|
|||
}
|
||||
);
|
||||
},
|
||||
|
||||
model: pgBrowser.Node.Model.extend({
|
||||
idAttribute: 'oid',
|
||||
|
||||
// Default values!
|
||||
initialize: function(attrs, args) {
|
||||
let isNew = (_.size(attrs) === 0);
|
||||
|
||||
if (isNew) {
|
||||
let userInfo = pgBrowser.serverInfo[args.node_info.server._id].user;
|
||||
this.set({'spcuser': userInfo.name}, {silent: true});
|
||||
}
|
||||
pgBrowser.Node.Model.prototype.initialize.apply(this, arguments);
|
||||
},
|
||||
|
||||
schema: [
|
||||
{
|
||||
id: 'name', label: gettext('Name'), cell: 'string',
|
||||
type: 'text',
|
||||
}, {
|
||||
id: 'spcuser', label: gettext('Owner'), cell: 'string',
|
||||
type: 'text', control: 'node-list-by-name', node: 'role',
|
||||
select2: {allowClear: false},
|
||||
}, {
|
||||
id: 'description', label: gettext('Comment'), cell: 'string',
|
||||
type: 'multiline',
|
||||
},
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -554,11 +554,11 @@ define('pgadmin.browser', [
|
|||
|
||||
obj.set_master_password('');
|
||||
obj.check_corrupted_db_file();
|
||||
obj.Events.on('pgadmin:browser:tree:add', obj.onAddTreeNode, obj);
|
||||
obj.Events.on('pgadmin:browser:tree:update', obj.onUpdateTreeNode, obj);
|
||||
obj.Events.on('pgadmin:browser:tree:refresh', obj.onRefreshTreeNodeReact, obj);
|
||||
obj.Events.on('pgadmin-browser:tree:loadfail', obj.onLoadFailNode, obj);
|
||||
obj.Events.on('pgadmin-browser:panel-browser:' + wcDocker.EVENT.RESIZE_ENDED, obj.onResizeEnded, obj);
|
||||
obj.Events.on('pgadmin:browser:tree:add', obj.onAddTreeNode.bind(obj));
|
||||
obj.Events.on('pgadmin:browser:tree:update', obj.onUpdateTreeNode.bind(obj));
|
||||
obj.Events.on('pgadmin:browser:tree:refresh', obj.onRefreshTreeNodeReact.bind(obj));
|
||||
obj.Events.on('pgadmin-browser:tree:loadfail', obj.onLoadFailNode.bind(obj));
|
||||
obj.Events.on('pgadmin-browser:panel-browser:' + wcDocker.EVENT.RESIZE_ENDED, obj.onResizeEnded.bind(obj));
|
||||
obj.bind_beforeunload();
|
||||
|
||||
/* User UI activity */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,15 @@
|
|||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import EventBus from '../../../static/js/helpers/EventBus';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
|
||||
const pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
|
||||
pgBrowser.Events = new EventBus();
|
||||
|
||||
export default pgBrowser;
|
|
@ -13,22 +13,15 @@ import _ from 'lodash';
|
|||
|
||||
define('pgadmin.browser.node', [
|
||||
'sources/gettext', 'jquery', 'sources/pgadmin',
|
||||
'backbone', 'pgadmin.browser.datamodel',
|
||||
'sources/browser/generate_url', 'pgadmin.help', 'sources/utils',
|
||||
'pgadmin.browser.utils',
|
||||
'sources/browser/generate_url', 'sources/utils',
|
||||
'pgadmin.browser.utils', 'pgadmin.browser.events',
|
||||
], function(
|
||||
gettext, $, pgAdmin,
|
||||
Backbone, pgBrowser,
|
||||
generateUrl, help,
|
||||
commonUtils
|
||||
gettext, $, pgAdmin, generateUrl, commonUtils
|
||||
) {
|
||||
|
||||
let wcDocker = window.wcDocker,
|
||||
keyCode = {
|
||||
ENTER: 13,
|
||||
ESCAPE: 27,
|
||||
F1: 112,
|
||||
};
|
||||
let wcDocker = window.wcDocker;
|
||||
|
||||
const pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
|
||||
|
||||
// It has already been defined.
|
||||
// Avoid running this script again.
|
||||
|
@ -45,7 +38,6 @@ define('pgadmin.browser.node', [
|
|||
// Uses a hash of class properties to be extended.
|
||||
//
|
||||
// It is unlikely - we will instantiate an object for this class.
|
||||
// (Inspired by Backbone.extend function)
|
||||
pgBrowser.Node.extend = function(props, initialize) {
|
||||
let parent = this;
|
||||
let child;
|
||||
|
@ -83,7 +75,7 @@ define('pgadmin.browser.node', [
|
|||
return child;
|
||||
};
|
||||
|
||||
_.extend(pgAdmin.Browser.Node, Backbone.Events, {
|
||||
_.extend(pgAdmin.Browser.Node, {
|
||||
// Node type
|
||||
type: undefined,
|
||||
// Label
|
||||
|
@ -332,20 +324,6 @@ define('pgadmin.browser.node', [
|
|||
return new_panel;
|
||||
},
|
||||
|
||||
onEventResizeEnded: function() {
|
||||
let $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,
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
registerDockerPanel: function(docker, name, params) {
|
||||
let w = docker || pgBrowser.docker,
|
||||
p = w.findPanels(name);
|
||||
|
@ -373,7 +351,6 @@ define('pgadmin.browser.node', [
|
|||
return;
|
||||
|
||||
let events = {};
|
||||
events[wcDocker.EVENT.RESIZE_ENDED] = this.onEventResizeEnded;
|
||||
|
||||
p = new pgBrowser.Panel({
|
||||
name: 'utility_props',
|
||||
|
@ -399,7 +376,6 @@ define('pgadmin.browser.node', [
|
|||
return;
|
||||
|
||||
let events = {};
|
||||
events[wcDocker.EVENT.RESIZE_ENDED] = this.onEventResizeEnded;
|
||||
|
||||
p = new pgBrowser.Panel({
|
||||
name: 'node_props',
|
||||
|
@ -974,55 +950,10 @@ define('pgadmin.browser.node', [
|
|||
**/
|
||||
showProperties: function(item, data, panel, action) {
|
||||
let that = this,
|
||||
tree = pgAdmin.Browser.tree,
|
||||
j = panel.$container.find('.obj_properties').first(),
|
||||
view = j.data('obj-view'),
|
||||
confirm_close = true;
|
||||
|
||||
// Handle key press events for Cancel, save and help button
|
||||
let handleKeyDown = function(event, context) {
|
||||
// If called on panel other than node_props, return
|
||||
if (panel && panel['_type'] !== 'node_props') return;
|
||||
|
||||
switch (event.which) {
|
||||
case keyCode.ESCAPE:
|
||||
closePanel(true);
|
||||
break;
|
||||
case keyCode.ENTER:
|
||||
// Return if event is fired from child element
|
||||
if (event.target !== context) return;
|
||||
if (view && view.model && view.model.sessChanged()) {
|
||||
let btn = $(event.target).closest('.obj_properties')
|
||||
.find('.pg-prop-btn-group')
|
||||
.find('button.btn-primary');
|
||||
onSave.call(this, view, btn);
|
||||
}
|
||||
break;
|
||||
case keyCode.F1:
|
||||
onDialogHelp();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}.bind(panel);
|
||||
|
||||
setTimeout(function() {
|
||||
// Register key press events with panel element
|
||||
panel.$container.find('.backform-tab').on('keydown', function(event) {
|
||||
handleKeyDown(event, this);
|
||||
});
|
||||
}, 200); // wait for panel tab to render
|
||||
j = panel.$container.find('.obj_properties').first();
|
||||
|
||||
// Callback to show object properties
|
||||
let properties = function() {
|
||||
|
||||
// Avoid unnecessary reloads
|
||||
let i = tree.selected(),
|
||||
treeHierarchy = tree.getTreeNodeHierarchy(i);
|
||||
|
||||
// Cache the current IDs for next time
|
||||
$(this).data('node-prop', treeHierarchy);
|
||||
|
||||
let properties = function() {
|
||||
/* Remove any dom rendered by getNodeView */
|
||||
removeNodeView(j[0]);
|
||||
let treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(item);
|
||||
|
@ -1032,99 +963,6 @@ define('pgadmin.browser.node', [
|
|||
return;
|
||||
}.bind(panel),
|
||||
|
||||
onDialogHelp = function() {
|
||||
window.open(that.dialogHelp, 'pgadmin_help');
|
||||
}.bind(panel),
|
||||
|
||||
warnBeforeChangesLost = function(warn_text, yes_callback) {
|
||||
let $props = this.$container.find('.obj_properties').first(),
|
||||
objview = $props && $props.data('obj-view'),
|
||||
self = this;
|
||||
|
||||
let confirm_on_properties_close = pgBrowser.get_preferences_for_module('browser').confirm_on_properties_close;
|
||||
if (confirm_on_properties_close && confirm_close && objview && objview.model) {
|
||||
if(objview.model.sessChanged()){
|
||||
Notify.confirm(
|
||||
gettext('Warning'),
|
||||
warn_text,
|
||||
function() {
|
||||
setTimeout(function(){
|
||||
yes_callback();
|
||||
}.bind(self), 50);
|
||||
return true;
|
||||
},
|
||||
function() {
|
||||
return true;
|
||||
}
|
||||
);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
yes_callback();
|
||||
return true;
|
||||
}
|
||||
}.bind(panel),
|
||||
|
||||
onSave = function(_view, saveBtn) {
|
||||
let m = _view.model,
|
||||
d = m.toJSON(true),
|
||||
// Generate a timer for the request
|
||||
timer = setTimeout(function() {
|
||||
$('.obj_properties').addClass('show_progress');
|
||||
}, 1000);
|
||||
|
||||
// Prevent subsequent save operation by disabling Save button
|
||||
if (saveBtn)
|
||||
$(saveBtn).prop('disabled', true);
|
||||
|
||||
if (d && !_.isEmpty(d)) {
|
||||
m.save({}, {
|
||||
attrs: d,
|
||||
validate: false,
|
||||
cache: false,
|
||||
wait: true,
|
||||
success: function() {
|
||||
onSaveFunc.call();
|
||||
// Hide progress cursor
|
||||
$('.obj_properties').removeClass('show_progress');
|
||||
clearTimeout(timer);
|
||||
|
||||
// Removing the node-prop property of panel
|
||||
// so that we show updated data on panel
|
||||
let pnlProperties = pgBrowser.docker.findPanels('properties')[0],
|
||||
pnlSql = pgBrowser.docker.findPanels('sql')[0],
|
||||
pnlStats = pgBrowser.docker.findPanels('statistics')[0],
|
||||
pnlDependencies = pgBrowser.docker.findPanels('dependencies')[0],
|
||||
pnlDependents = pgBrowser.docker.findPanels('dependents')[0];
|
||||
|
||||
if (pnlProperties)
|
||||
$(pnlProperties).removeData('node-prop');
|
||||
if (pnlSql)
|
||||
$(pnlSql).removeData('node-prop');
|
||||
if (pnlStats)
|
||||
$(pnlStats).removeData('node-prop');
|
||||
if (pnlDependencies)
|
||||
$(pnlDependencies).removeData('node-prop');
|
||||
if (pnlDependents)
|
||||
$(pnlDependents).removeData('node-prop');
|
||||
},
|
||||
error: function(_m, jqxhr) {
|
||||
Notify.pgNotifier(
|
||||
'error', jqxhr,
|
||||
gettext('Error saving properties')
|
||||
);
|
||||
|
||||
// Hide progress cursor
|
||||
$('.obj_properties').removeClass('show_progress');
|
||||
clearTimeout(timer);
|
||||
if (saveBtn)
|
||||
$(saveBtn).prop('disabled', false);
|
||||
},
|
||||
});
|
||||
}
|
||||
}.bind(panel),
|
||||
|
||||
editFunc = function() {
|
||||
let self = this;
|
||||
if (action && action == 'properties') {
|
||||
|
@ -1146,25 +984,6 @@ define('pgadmin.browser.node', [
|
|||
(nodeData)=>{
|
||||
if(nodeData.node) {
|
||||
onSaveFunc(nodeData.node, treeNodeInfo);
|
||||
// Removing the node-prop property of panel
|
||||
// so that we show updated data on panel
|
||||
let pnlProperties = pgBrowser.docker.findPanels('properties')[0],
|
||||
pnlSql = pgBrowser.docker.findPanels('sql')[0],
|
||||
pnlStats = pgBrowser.docker.findPanels('statistics')[0],
|
||||
pnlDependencies = pgBrowser.docker.findPanels('dependencies')[0],
|
||||
pnlDependents = pgBrowser.docker.findPanels('dependents')[0];
|
||||
|
||||
if (pnlProperties)
|
||||
$(pnlProperties).removeData('node-prop');
|
||||
if (pnlSql)
|
||||
$(pnlSql).removeData('node-prop');
|
||||
if (pnlStats)
|
||||
$(pnlStats).removeData('node-prop');
|
||||
if (pnlDependencies)
|
||||
$(pnlDependencies).removeData('node-prop');
|
||||
if (pnlDependents)
|
||||
$(pnlDependents).removeData('node-prop');
|
||||
|
||||
if(nodeData.success === 0) {
|
||||
Notify.alert(gettext('Error'),
|
||||
gettext(nodeData.errormsg)
|
||||
|
@ -1176,17 +995,11 @@ define('pgadmin.browser.node', [
|
|||
return;
|
||||
|
||||
}.bind(panel),
|
||||
closePanel = function(confirm_close_flag) {
|
||||
if(!_.isUndefined(confirm_close_flag)) {
|
||||
confirm_close = confirm_close_flag;
|
||||
}
|
||||
// Closing this panel
|
||||
this.close();
|
||||
}.bind(panel),
|
||||
|
||||
updateTreeItem = function(obj, tnode, node_info) {
|
||||
let _old = data,
|
||||
_new = tnode || _.clone(view.model.tnode),
|
||||
info = node_info || _.clone(view.model.node_info);
|
||||
_new = tnode,
|
||||
info = node_info;
|
||||
|
||||
// Clear the cache for this node now.
|
||||
setTimeout(function() {
|
||||
|
@ -1208,25 +1021,22 @@ define('pgadmin.browser.node', [
|
|||
},
|
||||
}
|
||||
);
|
||||
closePanel(false);
|
||||
this.close();
|
||||
},
|
||||
saveNewNode = function(obj, tnode, node_info) {
|
||||
let $props = this.$container.find('.obj_properties').first(),
|
||||
objview = $props.data('obj-view');
|
||||
|
||||
// Clear the cache for this node now.
|
||||
setTimeout(function() {
|
||||
obj.clear_cache.apply(obj, item);
|
||||
}, 0);
|
||||
try {
|
||||
pgBrowser.Events.trigger(
|
||||
'pgadmin:browser:tree:add', _.clone(tnode || objview.model.tnode),
|
||||
_.clone(node_info || objview.model.node_info)
|
||||
'pgadmin:browser:tree:add', _.clone(tnode),
|
||||
_.clone(node_info)
|
||||
);
|
||||
} catch (e) {
|
||||
console.warn(e.stack || e);
|
||||
}
|
||||
closePanel(false);
|
||||
this.close();
|
||||
}.bind(panel, that),
|
||||
editInNewPanel = function() {
|
||||
// Open edit in separate panel
|
||||
|
@ -1255,30 +1065,6 @@ define('pgadmin.browser.node', [
|
|||
onEdit = editInNewPanel.bind(panel);
|
||||
properties();
|
||||
}
|
||||
if (panel.closeable() && !that.getSchema) {
|
||||
panel.on(wcDocker.EVENT.CLOSING, warnBeforeChangesLost.bind(
|
||||
panel,
|
||||
gettext('Changes will be lost. Are you sure you want to close the dialog?'),
|
||||
function() {
|
||||
panel.off(wcDocker.EVENT.CLOSING);
|
||||
panel.close();
|
||||
}
|
||||
));
|
||||
|
||||
let onCloseFunc = function() {
|
||||
let $props = this.$container.find('.obj_properties').first(),
|
||||
objview = $props && $props.data('obj-view');
|
||||
|
||||
if (objview) {
|
||||
objview.remove({
|
||||
data: true,
|
||||
internal: true,
|
||||
silent: true,
|
||||
});
|
||||
}
|
||||
}.bind(panel);
|
||||
panel.on(wcDocker.EVENT.CLOSED, onCloseFunc);
|
||||
}
|
||||
},
|
||||
_find_parent_node: function(t, i, d) {
|
||||
if (this.parent_type) {
|
||||
|
@ -1368,10 +1154,6 @@ define('pgadmin.browser.node', [
|
|||
|
||||
return generateUrl.generate_url(pgBrowser.URL, treeInfo, actionType, self.type, nodePickFunction, itemID);
|
||||
},
|
||||
// Base class for Node Data Collection
|
||||
Collection: pgBrowser.DataCollection,
|
||||
// Base class for Node Data Model
|
||||
Model: pgBrowser.DataModel,
|
||||
cache: function(url, node_info, level, data) {
|
||||
let cached = this.cached = this.cached || {},
|
||||
hash = url,
|
||||
|
|
|
@ -49,7 +49,7 @@ _.extend(pgBrowser, {
|
|||
get_preference: function(module, preference){
|
||||
const self = this;
|
||||
|
||||
return _.findWhere(
|
||||
return _.find(
|
||||
self.preferences_cache, {'module': module, 'name': preference}
|
||||
);
|
||||
},
|
||||
|
@ -58,8 +58,8 @@ _.extend(pgBrowser, {
|
|||
get_preferences_for_module: function(module) {
|
||||
let self = this;
|
||||
let preferences = {};
|
||||
_.each(
|
||||
_.where(self.preferences_cache, {'module': module}),
|
||||
_.forEach(
|
||||
_.filter(self.preferences_cache, {'module': module}),
|
||||
(preference) => {
|
||||
preferences[preference.name] = preference.value;
|
||||
}
|
||||
|
@ -72,8 +72,8 @@ _.extend(pgBrowser, {
|
|||
/* Get preference of an id, id is numeric */
|
||||
get_preference_for_id : function(id) {
|
||||
let self = this;
|
||||
/* findWhere returns undefined if not found */
|
||||
return _.findWhere(self.preferences_cache, {'id': id});
|
||||
/* find returns undefined if not found */
|
||||
return _.find(self.preferences_cache, {'id': id});
|
||||
},
|
||||
|
||||
// Get and cache the preferences
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import $ from 'jquery';
|
||||
import Backbone from 'backbone';
|
||||
import axios from 'axios';
|
||||
|
||||
export function setPGCSRFToken(header, token) {
|
||||
|
@ -17,28 +16,6 @@ export function setPGCSRFToken(header, token) {
|
|||
throw new Error('csrf-token meta tag has not been set');
|
||||
}
|
||||
|
||||
// Configure Backbone.sync to set CSRF-Token-header request header for
|
||||
// every requests except GET.
|
||||
let origBackboneSync = Backbone.sync;
|
||||
Backbone.sync = function(method, model, options) {
|
||||
options.beforeSend = function(xhr) {
|
||||
xhr.setRequestHeader(header, token);
|
||||
};
|
||||
|
||||
return origBackboneSync(method, model, options);
|
||||
};
|
||||
|
||||
// Configure Backbone.get to set 'X-CSRFToken' request header for
|
||||
// GET requests.
|
||||
let origBackboneGet = Backbone.get;
|
||||
Backbone.get = function(method, model, options) {
|
||||
options.beforeSend = function(xhr) {
|
||||
xhr.setRequestHeader(header, token);
|
||||
};
|
||||
|
||||
return origBackboneGet(method, model, options);
|
||||
};
|
||||
|
||||
// Configure jquery.ajax to set 'X-CSRFToken' request header for
|
||||
// every requests.
|
||||
$.ajaxSetup({
|
||||
|
|
|
@ -14,6 +14,10 @@ export default class EventBus {
|
|||
});
|
||||
}
|
||||
|
||||
on(...args) {
|
||||
this.registerListener(...args);
|
||||
}
|
||||
|
||||
deregisterListener(event, callback) {
|
||||
if(callback) {
|
||||
this._eventListeners = this._eventListeners.filter((e)=>{
|
||||
|
@ -27,6 +31,10 @@ export default class EventBus {
|
|||
}
|
||||
}
|
||||
|
||||
off(...args) {
|
||||
this.deregisterListener(...args);
|
||||
}
|
||||
|
||||
fireEvent(event, ...args) {
|
||||
let self = this;
|
||||
Promise.resolve(0).then(()=>{
|
||||
|
@ -43,4 +51,8 @@ export default class EventBus {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
trigger(...args) {
|
||||
this.fireEvent(...args);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
import 'select2';
|
||||
import $ from 'jquery';
|
||||
import _ from 'underscore';
|
||||
|
||||
export default function (options) {
|
||||
if(options.showOnScroll) {
|
||||
let Utils = $.fn.select2.amd.require('select2/utils');
|
||||
|
||||
/* Define on scroll showing of dropdown items.
|
||||
* This also requires ajax option of select2 to be set.
|
||||
* The trick is, ajax: {} will also work even if you're actually not
|
||||
* using ajax.
|
||||
*/
|
||||
let ScrollDataAdapter = function ($element, dropdownOptions) {
|
||||
this.$element = $element;
|
||||
this.options = dropdownOptions;
|
||||
this._dataToConvert = dropdownOptions.get('data') || [];
|
||||
};
|
||||
|
||||
let BaseAdapter = null;
|
||||
if(options.data != null) {
|
||||
BaseAdapter = $.fn.select2.amd.require('select2/data/array');
|
||||
} else {
|
||||
BaseAdapter = $.fn.select2.amd.require('select2/data/select');
|
||||
}
|
||||
Utils.Extend(ScrollDataAdapter, BaseAdapter);
|
||||
|
||||
ScrollDataAdapter.prototype.query = function (params, callback) {
|
||||
let data = [];
|
||||
let self = this;
|
||||
if (!params.page) {
|
||||
params.page = 1;
|
||||
}
|
||||
let pageSize = 20;
|
||||
|
||||
let $options = this.$element.children();
|
||||
$options.each(function () {
|
||||
let $option = $(this);
|
||||
|
||||
if (!$option.is('option') && !$option.is('optgroup')) {
|
||||
return;
|
||||
}
|
||||
|
||||
let option = self.item($option);
|
||||
|
||||
let matches = self.matches(params, option);
|
||||
|
||||
if (matches !== null) {
|
||||
data.push(matches);
|
||||
}
|
||||
});
|
||||
|
||||
callback({
|
||||
results: data.slice((params.page - 1) * pageSize, params.page * pageSize),
|
||||
pagination: {
|
||||
more: data.length >= params.page * pageSize,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
if (options.minimumInputLength > 0) {
|
||||
ScrollDataAdapter = Utils.Decorate(
|
||||
ScrollDataAdapter,
|
||||
$.fn.select2.amd.require('select2/data/minimumInputLength')
|
||||
);
|
||||
}
|
||||
|
||||
if (options.maximumInputLength > 0) {
|
||||
ScrollDataAdapter = Utils.Decorate(
|
||||
ScrollDataAdapter,
|
||||
$.fn.select2.amd.require('select2/data/maximumInputLength')
|
||||
);
|
||||
}
|
||||
|
||||
if (options.maximumSelectionLength > 0) {
|
||||
ScrollDataAdapter = Utils.Decorate(
|
||||
ScrollDataAdapter,
|
||||
$.fn.select2.amd.require('select2/data/maximumSelectionLength')
|
||||
);
|
||||
}
|
||||
|
||||
if (options.tags) {
|
||||
ScrollDataAdapter = Utils.Decorate(ScrollDataAdapter, $.fn.select2.amd.require('select2/data/tags'));
|
||||
}
|
||||
|
||||
if (options.tokenSeparators != null || options.tokenizer != null) {
|
||||
ScrollDataAdapter = Utils.Decorate(
|
||||
ScrollDataAdapter,
|
||||
$.fn.select2.amd.require('select2/data/tokenizer')
|
||||
);
|
||||
}
|
||||
|
||||
options.dataAdapter = ScrollDataAdapter;
|
||||
|
||||
/* Setting empty ajax option will enable infinite scrolling. */
|
||||
if(_.isUndefined(options.ajax)) {
|
||||
options.ajax = {};
|
||||
}
|
||||
}
|
||||
return options;
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import Notify from '../helpers/Notifier';
|
||||
|
||||
define(['sources/gettext'], function (gettext) {
|
||||
return {
|
||||
copyTextToClipboard: function (text) {
|
||||
let textArea = document.createElement('textarea');
|
||||
|
||||
//
|
||||
// *** This styling is an extra step which is likely not required. ***
|
||||
//
|
||||
// Why is it here? To ensure:
|
||||
// 1. the element is able to have focus and selection.
|
||||
// 2. if element was to flash render it has minimal visual impact.
|
||||
// 3. less flakyness with selection and copying which **might** occur if
|
||||
// the textarea element is not visible.
|
||||
//
|
||||
// The likelihood is the element won't even render, not even a flash,
|
||||
// so some of these are just precautions. However in IE the element
|
||||
// is visible whilst the popup box asking the user for permission for
|
||||
// the web page to copy to the clipboard.
|
||||
//
|
||||
|
||||
// Place in top-left corner of screen regardless of scroll position.
|
||||
textArea.style.position = 'fixed';
|
||||
textArea.style.top = 0;
|
||||
textArea.style.left = 0;
|
||||
|
||||
// Ensure it has a small width and height. Setting to 1px / 1em
|
||||
// doesn't work as this gives a negative w/h on some browsers.
|
||||
textArea.style.width = '2em';
|
||||
textArea.style.height = '2em';
|
||||
|
||||
// We don't need padding, reducing the size if it does flash render.
|
||||
textArea.style.padding = 0;
|
||||
|
||||
// Clean up any borders.
|
||||
textArea.style.border = 'none';
|
||||
textArea.style.outline = 'none';
|
||||
textArea.style.boxShadow = 'none';
|
||||
|
||||
// Avoid flash of white box if rendered for any reason.
|
||||
textArea.style.background = 'transparent';
|
||||
|
||||
document.body.appendChild(textArea);
|
||||
textArea.textContent = text;
|
||||
textArea.select();
|
||||
|
||||
let copyTextToClipboardHandler = function(e) {
|
||||
/* Remove oncopy event listener from document as we add listener for
|
||||
* oncopy event on each copy operation.
|
||||
* Also we don't want this listener to be persistent; Otherwise it'll get
|
||||
* called for each copy operation performed on any input/textarea from
|
||||
* this document.
|
||||
*/
|
||||
document.removeEventListener('copy', copyTextToClipboardHandler);
|
||||
let clipboardData = e.clipboardData || window.clipboardData;
|
||||
|
||||
if (clipboardData) {
|
||||
clipboardData.setData('text', text);
|
||||
// As there no uniform way to read data from clipboard
|
||||
// storing copied data into main window object, so it is accessible from anywhere in the application
|
||||
window.parent.window.clipboardData = text;
|
||||
// We want our data, not data from any selection, to be written to the clipboard
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('copy', copyTextToClipboardHandler);
|
||||
|
||||
try {
|
||||
// just perform copy on empty textarea so that copy event will be
|
||||
// triggered on document and then we can set clipboardData.
|
||||
document.execCommand('copy');
|
||||
} catch (err) {
|
||||
Notify.alert(
|
||||
gettext('Error'),
|
||||
gettext('Oops, unable to copy to clipboard'));
|
||||
}
|
||||
|
||||
document.body.removeChild(textArea);
|
||||
},
|
||||
getTextFromClipboard: function() {
|
||||
return window.parent.window.clipboardData || '';
|
||||
},
|
||||
};
|
||||
});
|
|
@ -1,170 +0,0 @@
|
|||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
define(['sources/selection/range_selection_helper', 'json-bignumber'],
|
||||
function (RangeSelectionHelper, JSONBigNumber) {
|
||||
return {
|
||||
getUnion: function (allRanges) {
|
||||
if (_.isEmpty(allRanges)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
allRanges.sort(firstElementNumberComparator);
|
||||
let unionedRanges = [allRanges[0]];
|
||||
|
||||
allRanges.forEach(function (range) {
|
||||
let maxBeginningOfRange = _.last(unionedRanges);
|
||||
if (isStartInsideRange(range, maxBeginningOfRange)) {
|
||||
if (!isEndInsideRange(range, maxBeginningOfRange)) {
|
||||
maxBeginningOfRange[1] = range[1];
|
||||
}
|
||||
} else {
|
||||
unionedRanges.push(range);
|
||||
}
|
||||
});
|
||||
|
||||
return unionedRanges;
|
||||
|
||||
function firstElementNumberComparator(a, b) {
|
||||
return a[0] - b[0];
|
||||
}
|
||||
|
||||
function isStartInsideRange(range, surroundingRange) {
|
||||
return range[0] <= surroundingRange[1] + 1;
|
||||
}
|
||||
|
||||
function isEndInsideRange(range, surroundingRange) {
|
||||
return range[1] <= surroundingRange[1];
|
||||
}
|
||||
},
|
||||
|
||||
mapDimensionBoundaryUnion: function (unionedDimensionBoundaries, iteratee) {
|
||||
let mapResult = [];
|
||||
unionedDimensionBoundaries.forEach(function (subrange) {
|
||||
for (let index = subrange[0]; index <= subrange[1]; index += 1) {
|
||||
mapResult.push(iteratee(index));
|
||||
}
|
||||
});
|
||||
return mapResult;
|
||||
},
|
||||
|
||||
mapOver2DArray: function (rowRangeBounds, colRangeBounds, processCell, rowCollector) {
|
||||
let unionedRowRanges = this.getUnion(rowRangeBounds);
|
||||
let unionedColRanges = this.getUnion(colRangeBounds);
|
||||
|
||||
return this.mapDimensionBoundaryUnion(unionedRowRanges, function (rowId) {
|
||||
let rowData = this.mapDimensionBoundaryUnion(unionedColRanges, function (colId) {
|
||||
return processCell(rowId, colId);
|
||||
});
|
||||
return rowCollector(rowData);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
getHeaderData: function (columnDefinitions, CSVOptions) {
|
||||
let headerData = [],
|
||||
field_separator = CSVOptions.field_separator || '\t',
|
||||
quote_char = CSVOptions.quote_char || '"';
|
||||
|
||||
_.each(columnDefinitions, function(col) {
|
||||
if(col.display_name && col.selected) {
|
||||
headerData.push(quote_char + col.display_name + quote_char);
|
||||
}
|
||||
});
|
||||
|
||||
return headerData.join(field_separator);
|
||||
},
|
||||
|
||||
rangesToCsv: function (data, columnDefinitions, selectedRanges, CSVOptions, copyWithHeader) {
|
||||
|
||||
let rowRangeBounds = selectedRanges.map(function (range) {
|
||||
return [range.fromRow, range.toRow];
|
||||
});
|
||||
let colRangeBounds = selectedRanges.map(function (range) {
|
||||
return [range.fromCell, range.toCell];
|
||||
});
|
||||
|
||||
if (!RangeSelectionHelper.isFirstColumnData(columnDefinitions)) {
|
||||
colRangeBounds = this.removeFirstColumn(colRangeBounds);
|
||||
}
|
||||
|
||||
let csvRows = this.mapOver2DArray(rowRangeBounds, colRangeBounds, this.csvCell.bind(this, data, columnDefinitions, CSVOptions), function (rowData) {
|
||||
let field_separator = CSVOptions.field_separator || '\t';
|
||||
return rowData.join(field_separator);
|
||||
});
|
||||
|
||||
if (copyWithHeader) {
|
||||
let headerData = '';
|
||||
headerData = this.getHeaderData(columnDefinitions, CSVOptions);
|
||||
|
||||
return headerData + '\n' + csvRows.join('\n');
|
||||
}
|
||||
|
||||
return csvRows.join('\n');
|
||||
},
|
||||
|
||||
removeFirstColumn: function (colRangeBounds) {
|
||||
let unionedColRanges = this.getUnion(colRangeBounds);
|
||||
|
||||
if(unionedColRanges.length == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let firstSubrangeStartsAt0 = function () {
|
||||
return unionedColRanges[0][0] == 0;
|
||||
};
|
||||
|
||||
function firstSubrangeIsJustFirstColumn() {
|
||||
return unionedColRanges[0][1] == 0;
|
||||
}
|
||||
|
||||
if (firstSubrangeStartsAt0()) {
|
||||
if (firstSubrangeIsJustFirstColumn()) {
|
||||
unionedColRanges.shift();
|
||||
} else {
|
||||
unionedColRanges[0][0] = 1;
|
||||
}
|
||||
}
|
||||
return unionedColRanges;
|
||||
},
|
||||
|
||||
csvCell: function (data, columnDefinitions, CSVOptions, rowId, colId) {
|
||||
let val = data[rowId][columnDefinitions[colId].field],
|
||||
cell_type = columnDefinitions[colId].cell || '',
|
||||
quoting = CSVOptions.quoting || 'strings',
|
||||
quote_char = CSVOptions.quote_char || '"';
|
||||
|
||||
const escape = (iStr) => {
|
||||
return (quote_char == '"') ?
|
||||
iStr.replace(/\"/g, '""') : iStr.replace(/\'/g, '\'\'');
|
||||
};
|
||||
|
||||
if (quoting == 'all') {
|
||||
if (val && _.isObject(val)) {
|
||||
val = quote_char + JSONBigNumber.stringify(val) + quote_char;
|
||||
} else if (val) {
|
||||
val = quote_char + escape(val.toString()) + quote_char;
|
||||
} else if (_.isNull(val) || _.isUndefined(val)) {
|
||||
val = '';
|
||||
}
|
||||
}
|
||||
else if(quoting == 'strings') {
|
||||
if (val && _.isObject(val)) {
|
||||
val = quote_char + JSONBigNumber.stringify(val) + quote_char;
|
||||
} else if (val && cell_type != 'number' && cell_type != 'boolean') {
|
||||
val = quote_char + escape(val.toString()) + quote_char;
|
||||
} else if (cell_type == 'string' && _.isNull(val)){
|
||||
val = null;
|
||||
} else if (_.isNull(val) || _.isUndefined(val)) {
|
||||
val = '';
|
||||
}
|
||||
}
|
||||
return val;
|
||||
},
|
||||
};
|
||||
});
|
|
@ -1,106 +0,0 @@
|
|||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
define(
|
||||
[
|
||||
'jquery',
|
||||
'underscore',
|
||||
'sources/selection/range_selection_helper',
|
||||
],
|
||||
function ($, _, RangeSelectionHelper) {
|
||||
function disableButton(selector) {
|
||||
$(selector).prop('disabled', true);
|
||||
}
|
||||
|
||||
function enableButton(selector) {
|
||||
$(selector).prop('disabled', false);
|
||||
}
|
||||
|
||||
function getRowPrimaryKeyValuesToStage(selectedRows, primaryKeys, dataView, client_primary_key) {
|
||||
return _.reduce(selectedRows, function (primaryKeyValuesToStage, dataGridRowIndex) {
|
||||
let gridRow = dataView.getItem(dataGridRowIndex);
|
||||
if (isRowMissingPrimaryKeys(gridRow, primaryKeys)) {
|
||||
return primaryKeyValuesToStage;
|
||||
}
|
||||
let tempPK = gridRow[client_primary_key];
|
||||
primaryKeyValuesToStage[tempPK] = getSingleRowPrimaryKeyValueToStage(primaryKeys, gridRow);
|
||||
return primaryKeyValuesToStage;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function isRowMissingPrimaryKeys(gridRow, primaryKeys) {
|
||||
if (_.isUndefined(gridRow)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !_.isUndefined(
|
||||
_.find(primaryKeys , function (pk) {
|
||||
return _.isUndefined(gridRow[pk]);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function getSingleRowPrimaryKeyValueToStage(primaryKeys, gridRow) {
|
||||
let rowToStage = {};
|
||||
if (primaryKeys && primaryKeys.length) {
|
||||
_.each(_.keys(gridRow), function (columnNames) {
|
||||
if (_.contains(primaryKeys, columnNames))
|
||||
rowToStage[columnNames] = gridRow[columnNames];
|
||||
});
|
||||
}
|
||||
return rowToStage;
|
||||
}
|
||||
|
||||
function getPrimaryKeysForSelectedRows(self, selectedRows) {
|
||||
let dataView = self.grid.getData();
|
||||
return getRowPrimaryKeyValuesToStage(selectedRows, _.keys(self.keys), dataView, self.client_primary_key);
|
||||
}
|
||||
|
||||
return function () {
|
||||
let self = this;
|
||||
|
||||
function setStagedRows(rowsToStage) {
|
||||
self.editor.handler.data_store.staged_rows = rowsToStage;
|
||||
}
|
||||
|
||||
function isEditMode() {
|
||||
return self.editor.handler.can_edit;
|
||||
}
|
||||
|
||||
disableButton('#btn-delete-row');
|
||||
disableButton('#btn-copy-row');
|
||||
|
||||
function areAllSelectionsEntireRows() {
|
||||
return RangeSelectionHelper.areAllRangesCompleteRows(self.grid,
|
||||
self.selection.getSelectedRanges());
|
||||
}
|
||||
|
||||
let selectedRanges = this.selection.getSelectedRanges();
|
||||
|
||||
if (selectedRanges.length > 0) {
|
||||
enableButton('#btn-copy-row');
|
||||
}
|
||||
|
||||
if (areAllSelectionsEntireRows()) {
|
||||
let selectedRows = RangeSelectionHelper.getIndexesOfCompleteRows(this.grid, this.selection.getSelectedRanges());
|
||||
let stagedRows = getPrimaryKeysForSelectedRows(self, selectedRows);
|
||||
setStagedRows(stagedRows);
|
||||
if (_.isEmpty(stagedRows)) {
|
||||
this.selection.setSelectedRows([]);
|
||||
}
|
||||
|
||||
if (isEditMode() && !_.isEmpty(stagedRows)) {
|
||||
enableButton('#btn-delete-row');
|
||||
}
|
||||
} else {
|
||||
setStagedRows({});
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
|
@ -66,11 +66,11 @@ _.extend(pgBrowser.browserTreeState, {
|
|||
this.fetch_state.apply(this);
|
||||
|
||||
pgBrowser.Events.on('pgadmin:browser:tree:expand-from-previous-tree-state',
|
||||
this.expand_from_previous_state, this);
|
||||
this.expand_from_previous_state.bind(this));
|
||||
pgBrowser.Events.on('pgadmin:browser:tree:remove-from-tree-state',
|
||||
this.remove_from_cache, this);
|
||||
this.remove_from_cache.bind(this));
|
||||
pgBrowser.Events.on('pgadmin:browser:tree:update-tree-state',
|
||||
this.update_cache, this);
|
||||
this.update_cache.bind(this));
|
||||
} else if (!_.isUndefined(save_tree_state_period)) {
|
||||
$.ajax({
|
||||
url: url_for('settings.reset_tree_state'),
|
||||
|
|
|
@ -54,9 +54,6 @@ function manageTreeEvents(event, eventName, item) {
|
|||
|
||||
/* Raise tree events for the nodes */
|
||||
try {
|
||||
node.trigger(
|
||||
'browser-node.' + eventName, node, item, d
|
||||
);
|
||||
obj.Events.trigger(
|
||||
'pgadmin-browser:tree:' + eventName, item, d, node
|
||||
);
|
||||
|
|
|
@ -80,7 +80,7 @@ def make_json_response(
|
|||
|
||||
|
||||
def make_response(response=None, status=200):
|
||||
"""Create a JSON response handled by the backbone models."""
|
||||
"""Create a JSON response"""
|
||||
return Response(
|
||||
response=json.dumps(
|
||||
response, cls=DataTypeJSONEncoder, separators=(',', ':')),
|
||||
|
|
|
@ -41,8 +41,7 @@ const providePlugin = new webpack.ProvidePlugin({
|
|||
$: 'jquery',
|
||||
jQuery: 'jquery',
|
||||
'window.jQuery': 'jquery',
|
||||
_: 'underscore',
|
||||
Backbone: 'backbone',
|
||||
_: 'lodash',
|
||||
pgAdmin: 'pgadmin',
|
||||
'moment': 'moment',
|
||||
'window.moment':'moment',
|
||||
|
@ -599,7 +598,7 @@ module.exports = [{
|
|||
minChunks: 2,
|
||||
enforce: true,
|
||||
test(module) {
|
||||
return webpackShimConfig.matchModules(module, ['wcdocker', 'backbone', 'jquery', 'bootstrap', 'popper']);
|
||||
return webpackShimConfig.matchModules(module, ['wcdocker', 'jquery', 'bootstrap', 'popper']);
|
||||
},
|
||||
},
|
||||
vendor_others: {
|
||||
|
|
|
@ -16,9 +16,6 @@ let webpackShimConfig = {
|
|||
'moment': {
|
||||
exports: 'moment',
|
||||
},
|
||||
'underscore': {
|
||||
exports: '_',
|
||||
},
|
||||
'jquery': {
|
||||
'exports': '$',
|
||||
},
|
||||
|
@ -41,13 +38,6 @@ let webpackShimConfig = {
|
|||
deps: ['jquery', 'bootstrap'],
|
||||
'exports': '$.fn.bootstrapToggle',
|
||||
},
|
||||
'backbone': {
|
||||
exports: 'Backbone', // Once loaded, use the global 'Backbone' as the module value.
|
||||
deps: [
|
||||
'underscore', // just make sure that underscore is loaded before (uses it's global value)
|
||||
'jquery:$', // Provide jquery as dependency with name $
|
||||
],
|
||||
},
|
||||
'jquery.event.drag': {
|
||||
'deps': ['jquery'], 'exports': 'jQuery.fn.drag',
|
||||
},
|
||||
|
@ -75,9 +65,6 @@ let webpackShimConfig = {
|
|||
'wcdocker': {
|
||||
'deps': ['jquery.contextmenu'],
|
||||
},
|
||||
'pgadmin.browser.messages': {
|
||||
'deps': ['pgadmin.browser.datamodel'],
|
||||
},
|
||||
},
|
||||
|
||||
// Map module id to file path used in 'define(['baseurl', 'misc']). It is
|
||||
|
@ -126,9 +113,6 @@ let webpackShimConfig = {
|
|||
//socket
|
||||
'socketio': path.join(__dirname, './node_modules/socket.io-client/dist/socket.io.js'),
|
||||
|
||||
// Backbone
|
||||
'backbone': path.join(__dirname, './node_modules/backbone/backbone'),
|
||||
'backbone.undo': path.join(__dirname, './node_modules/backbone-undo/Backbone.Undo'),
|
||||
'bootstrap.datetimepicker': path.join(__dirname, './node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min'),
|
||||
'bootstrap.toggle': path.join(__dirname, './node_modules/bootstrap4-toggle/js/bootstrap4-toggle.min'),
|
||||
'select2': path.join(__dirname, './node_modules/select2/dist/js/select2.full'),
|
||||
|
@ -138,7 +122,7 @@ let webpackShimConfig = {
|
|||
'pgadmin.browser': path.join(__dirname, './pgadmin/browser/static/js/browser'),
|
||||
'pgadmin.browser.bgprocessmanager': path.join(__dirname, './pgadmin/misc/bgprocess/static/js'),
|
||||
'pgadmin.browser.collection': path.join(__dirname, './pgadmin/browser/static/js/collection'),
|
||||
'pgadmin.browser.datamodel': path.join(__dirname, './pgadmin/browser/static/js/datamodel'),
|
||||
'pgadmin.browser.events': path.join(__dirname, './pgadmin/browser/static/js/events'),
|
||||
'pgadmin.browser.endpoints': '/browser/js/endpoints',
|
||||
'pgadmin.browser.constants': '/browser/js/constants',
|
||||
'pgadmin.browser.error': path.join(__dirname, './pgadmin/browser/static/js/error'),
|
||||
|
@ -255,7 +239,7 @@ let webpackShimConfig = {
|
|||
pgLibs: [
|
||||
'pgadmin.browser.error',
|
||||
'pgadmin.browser.collection',
|
||||
'pgadmin.browser.datamodel', 'pgadmin.browser.menu', 'pgadmin.browser.panel', 'pgadmin',
|
||||
'pgadmin.browser.events', 'pgadmin.browser.menu', 'pgadmin.browser.panel', 'pgadmin',
|
||||
'pgadmin.browser.frame', 'pgadmin.browser',
|
||||
'pgadmin.browser.node',
|
||||
'pgadmin.settings', 'pgadmin.preferences', 'pgadmin.sqlfoldcode',
|
||||
|
|
|
@ -21,7 +21,7 @@ module.exports = {
|
|||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
jQuery: 'jquery',
|
||||
_: 'underscore',
|
||||
_: 'lodash',
|
||||
'window.jQuery': 'jquery',
|
||||
'moment': 'moment',
|
||||
'window.moment':'moment',
|
||||
|
@ -126,7 +126,6 @@ module.exports = {
|
|||
'bignumber': path.join(__dirname, './node_modules/bignumber.js/bignumber'),
|
||||
'bootstrap.datetimepicker': path.join(__dirname, './node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min'),
|
||||
'bootstrap.toggle': path.join(__dirname, './node_modules/bootstrap4-toggle/js/bootstrap4-toggle.min'),
|
||||
'backbone': path.join(__dirname, './node_modules/backbone/backbone'),
|
||||
'react': path.join(__dirname, 'node_modules/react'),
|
||||
'react-dom': path.join(__dirname, 'node_modules/react-dom'),
|
||||
'socketio': path.join(__dirname, './node_modules/socket.io-client/dist/socket.io.js'),
|
||||
|
|
|
@ -3448,13 +3448,6 @@ babylon@^6.18.0:
|
|||
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
|
||||
integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
|
||||
|
||||
backbone@1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/backbone/-/backbone-1.4.0.tgz#54db4de9df7c3811c3f032f34749a4cd27f3bd12"
|
||||
integrity sha512-RLmDrRXkVdouTg38jcgHhyQ/2zjg7a8E6sz2zxfz21Hh17xDJYUHBZimVIt5fUyS8vbfpeSmTL3gUjTEvUV3qQ==
|
||||
dependencies:
|
||||
underscore ">=1.8.3"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
|
@ -11237,7 +11230,7 @@ undeclared-identifiers@^1.1.2:
|
|||
simple-concat "^1.0.0"
|
||||
xtend "^4.0.1"
|
||||
|
||||
underscore@>=1.8.3, underscore@^1.13.1, underscore@^1.9.1:
|
||||
underscore@^1.9.1:
|
||||
version "1.13.1"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.1.tgz#0c1c6bd2df54b6b69f2314066d65b6cde6fcf9d1"
|
||||
integrity sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g==
|
||||
|
|
Loading…
Reference in New Issue