From cb052f1988e001fd0756b2eff170945c7a5ece60 Mon Sep 17 00:00:00 2001 From: Pradip Parkale Date: Wed, 30 Mar 2022 12:06:59 +0530 Subject: [PATCH] 1) Port Properties panel for collection node, Dashboard, and SQL panel in React. Fixes #7132 2) Added transaction start time to Server activity sessions view. Fixes #7215 --- docs/en_US/release_notes_6_8.rst | 2 + web/package.json | 9 + .../servers/databases/casts/static/js/cast.js | 19 - .../event_triggers/static/js/event_trigger.js | 131 +- .../extensions/static/js/extension.js | 108 +- .../static/js/foreign_server.js | 43 +- .../static/js/foreign_data_wrapper.js | 44 +- .../databases/languages/static/js/language.js | 36 +- .../publications/static/js/publication.js | 81 +- .../publications/static/js/publication.ui.js | 2 +- .../publications/sql/default/get_tables.sql | 5 +- .../schemas/aggregates/static/js/aggregate.js | 31 - .../static/js/catalog_object_column.js | 26 - .../static/js/catalog_object.js | 25 - .../schemas/collations/static/js/collation.js | 36 - .../static/js/domain_constraints.js | 37 - .../schemas/domains/static/js/domain.js | 32 - .../foreign_tables/static/js/foreign_table.js | 620 +-------- .../static/js/fts_configuration.js | 26 - .../static/js/fts_dictionary.js | 25 - .../fts_parsers/static/js/fts_parser.js | 102 -- .../fts_templates/static/js/fts_template.js | 59 - .../schemas/functions/static/js/function.js | 38 - .../schemas/functions/static/js/procedure.js | 121 -- .../functions/static/js/trigger_function.js | 145 -- .../schemas/operators/static/js/operator.js | 31 - .../packages/edbvars/static/js/edbvar.js | 10 - .../schemas/packages/static/js/package.js | 35 - .../schemas/sequences/static/js/sequence.js | 35 - .../databases/schemas/static/js/catalog.js | 19 - .../databases/schemas/static/js/schema.js | 30 - .../schemas/synonyms/static/js/synonym.js | 48 - .../tables/columns/static/js/column.js | 30 - .../static/js/compound_trigger.js | 10 - .../constraints/static/js/constraints.js | 18 - .../schemas/tables/indexes/static/js/index.js | 23 - .../tables/partitions/static/js/partition.js | 43 - .../static/js/row_security_policy.js | 58 - .../schemas/tables/rules/static/js/rule.js | 48 - .../tables/triggers/static/js/trigger.js | 462 ------- .../databases/schemas/types/static/js/type.js | 42 - .../schemas/views/static/js/mview.js | 87 -- .../databases/schemas/views/static/js/view.js | 157 --- .../servers/databases/static/js/database.js | 39 - .../databases/static/js/database.ui.js | 6 +- .../subscriptions/static/js/subscription.js | 101 +- .../static/js/subscription.ui.js | 2 +- .../subscriptions/sql/default/properties.sql | 1 + .../servers/roles/static/js/role.js | 146 -- web/pgadmin/browser/static/js/collection.js | 402 +----- web/pgadmin/browser/static/js/node.js | 16 +- web/pgadmin/browser/static/js/node_ajax.js | 3 +- web/pgadmin/browser/static/js/node_view.jsx | 1 - web/pgadmin/browser/static/js/panel.js | 59 +- web/pgadmin/browser/static/js/panel_view.jsx | 62 +- .../dashboard/static/js/ActiveQuery.ui.js | 67 + web/pgadmin/dashboard/static/js/Dashboard.jsx | 907 +++++++++++++ web/pgadmin/dashboard/static/js/Graphs.jsx | 2 +- .../dashboard/static/js/PgAdminLogo.jsx | 219 +++ .../dashboard/static/js/WelcomeDashboard.jsx | 249 ++++ web/pgadmin/dashboard/static/js/dashboard.js | 1209 ----------------- .../static/js/dashboard_components.jsx | 74 - .../dashboard/database_dashboard.html | 59 - .../templates/dashboard/server_dashboard.html | 67 - .../dashboard/sql/10_plus/activity.sql | 1 + .../dashboard/sql/9.6_plus/activity.sql | 1 + .../dashboard/sql/default/activity.sql | 1 + .../dashboard/welcome_dashboard.html | 135 -- .../dependencies/static/js/Dependencies.jsx | 21 +- .../misc/dependents/static/js/Dependents.jsx | 21 +- .../properties/CollectionNodeProperties.jsx | 331 +++++ web/pgadmin/misc/sql/static/js/SQL.jsx | 114 ++ web/pgadmin/misc/sql/static/js/sql.js | 207 --- .../misc/statistics/static/js/Statistics.jsx | 37 +- web/pgadmin/static/js/Theme/dark.js | 3 +- web/pgadmin/static/js/Theme/high_contrast.js | 3 +- web/pgadmin/static/js/Theme/standard.js | 2 + web/pgadmin/static/js/components/PgTable.jsx | 343 +++-- web/pgadmin/static/js/nodes/dashboard.js | 37 - .../grant_wizard/static/js/GrantWizard.jsx | 15 +- web/webpack.config.js | 2 - web/webpack.shim.js | 3 +- 82 files changed, 2352 insertions(+), 5605 deletions(-) create mode 100644 web/pgadmin/dashboard/static/js/ActiveQuery.ui.js create mode 100644 web/pgadmin/dashboard/static/js/Dashboard.jsx create mode 100644 web/pgadmin/dashboard/static/js/PgAdminLogo.jsx create mode 100644 web/pgadmin/dashboard/static/js/WelcomeDashboard.jsx delete mode 100644 web/pgadmin/dashboard/static/js/dashboard.js delete mode 100644 web/pgadmin/dashboard/static/js/dashboard_components.jsx delete mode 100644 web/pgadmin/dashboard/templates/dashboard/database_dashboard.html delete mode 100644 web/pgadmin/dashboard/templates/dashboard/server_dashboard.html delete mode 100644 web/pgadmin/dashboard/templates/dashboard/welcome_dashboard.html create mode 100644 web/pgadmin/misc/properties/CollectionNodeProperties.jsx create mode 100644 web/pgadmin/misc/sql/static/js/SQL.jsx delete mode 100644 web/pgadmin/misc/sql/static/js/sql.js delete mode 100644 web/pgadmin/static/js/nodes/dashboard.js diff --git a/docs/en_US/release_notes_6_8.rst b/docs/en_US/release_notes_6_8.rst index 0b98c7b76..5974c202f 100644 --- a/docs/en_US/release_notes_6_8.rst +++ b/docs/en_US/release_notes_6_8.rst @@ -9,12 +9,14 @@ This release contains a number of bug fixes and new features since the release o New features ************ + | `Issue #7215 `_ - Added transaction start time to Server activity sessions view. | `Issue #7249 `_ - Added support for unique keys in ERD. | `Issue #7257 `_ - Support running the container under OpenShift with alternate UIDs. Housekeeping ************ + | `Issue #7132 `_ - Port Properties panel for collection node, Dashboard, and SQL panel in React. | `Issue #7149 `_ - Port preferences dialog to React. Bug fixes diff --git a/web/package.json b/web/package.json index 4200b1f82..2379e9188 100644 --- a/web/package.json +++ b/web/package.json @@ -83,10 +83,16 @@ "@date-io/date-fns": "1.x", "@emotion/sheet": "^1.0.1", "@fortawesome/fontawesome-free": "^5.14.0", + "@fortawesome/fontawesome-svg-core": "^6.1.0", + "@fortawesome/free-regular-svg-icons": "^6.1.0", + "@fortawesome/free-solid-svg-icons": "^6.1.0", + "@fortawesome/react-fontawesome": "^0.1.18", "@material-ui/core": "4.11.0", "@material-ui/icons": "^4.11.2", "@material-ui/lab": "4.0.0-alpha.58", "@material-ui/pickers": "^3.2.10", + "@mui/icons-material": "^5.4.2", + "@mui/material": "^5.4.3", "@projectstorm/react-diagrams": "^6.6.1", "@simonwep/pickr": "^1.5.1", "@szhsin/react-menu": "^2.2.0", @@ -122,6 +128,7 @@ "date-fns": "^2.24.0", "diff-arrays-of-objects": "^1.1.8", "dropzone": "^5.9.3", + "html-loader": "^3.1.0", "html2canvas": "^1.0.0-rc.7", "immutability-helper": "^3.0.0", "imports-loader": "^2.0.0", @@ -155,6 +162,8 @@ "react-dom": "^17.0.1", "react-draggable": "^4.4.4", "react-rnd": "^10.3.5", + "react-fontawesome": "^1.7.1", + "react-router-dom": "^6.2.2", "react-select": "^4.2.1", "react-table": "^7.6.3", "react-timer-hook": "^3.0.5", diff --git a/web/pgadmin/browser/server_groups/servers/databases/casts/static/js/cast.js b/web/pgadmin/browser/server_groups/servers/databases/casts/static/js/cast.js index dd9874976..d1ee8b3b3 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/casts/static/js/cast.js +++ b/web/pgadmin/browser/server_groups/servers/databases/casts/static/js/cast.js @@ -68,25 +68,6 @@ define('pgadmin.node.cast', [ }, - // Define the backform model for cast node - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - - // Define the schema for cast - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - editable: false, type: 'text', readonly: true, cellHeaderClasses: 'width_percent_50', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - editable: false, type: 'text', mode: ['properties'], - }, - { - id: 'description', label: gettext('Comment'), - type: 'multiline', cellHeaderClasses: 'width_percent_50', - }, - ], - }), - getSchema: function(treeNodeInfo, itemNodeData){ return new CastSchema({ getTypeOptions: ()=>getNodeAjaxOptions('get_type', this, treeNodeInfo, itemNodeData), diff --git a/web/pgadmin/browser/server_groups/servers/databases/event_triggers/static/js/event_trigger.js b/web/pgadmin/browser/server_groups/servers/databases/event_triggers/static/js/event_trigger.js index c6d7a7e51..5e830af87 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/event_triggers/static/js/event_trigger.js +++ b/web/pgadmin/browser/server_groups/servers/databases/event_triggers/static/js/event_trigger.js @@ -12,9 +12,8 @@ import { getNodeListByName, getNodeAjaxOptions } from '../../../../../../static/ define('pgadmin.node.event_trigger', [ 'sources/gettext', 'sources/url_for', 'jquery', 'underscore', - 'sources/pgadmin', 'pgadmin.browser', - 'pgadmin.backform', 'pgadmin.browser.collection', -], function(gettext, url_for, $, _, pgAdmin, pgBrowser, Backform) { + 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.browser.collection', +], function(gettext, url_for, $, _, pgAdmin, pgBrowser) { // Extend the browser's collection class for event trigger collection if (!pgBrowser.Nodes['coll-event_trigger']) { @@ -80,132 +79,6 @@ define('pgadmin.node.event_trigger', [ } ); }, - // Define the model for event trigger node - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - defaults: { - oid: undefined, - name: undefined, - eventowner: undefined, - is_sys_obj: undefined, - comment: undefined, - enabled: 'O', - eventfuncoid: undefined, - eventfunname: undefined, - eventname: 'DDL_COMMAND_START', - when: undefined, - xmin: undefined, - source: undefined, - language: undefined, - }, - - // Default values! - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - - this.set({'eventowner': userInfo.name}, {silent: true}); - } - pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments); - }, - - // Define the schema for the event trigger node - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text', mode: ['properties'], - },{ - id: 'eventowner', label: gettext('Owner'), cell: 'string', - type: 'text', mode: ['properties', 'edit','create'], node: 'role', - control: Backform.NodeListByNameControl, - },{ - id: 'is_sys_obj', label: gettext('System event trigger?'), - cell:'boolean', type: 'switch', - mode: ['properties'], - },{ - id: 'comment', label: gettext('Comment'), type: 'multiline', - },{ - id: 'enabled', label: gettext('Trigger enabled?'), - group: gettext('Definition'), mode: ['properties', 'edit','create'], - options: [ - {label: gettext('Enable'), value: 'O'}, - {label: gettext('Disable'), value: 'D'}, - {label: gettext('Replica'), value: 'R'}, - {label: gettext('Always'), value: 'A'}, - ], - control: 'select2', select2: { allowClear: false, width: '100%' }, - },{ - id: 'eventfunname', label: gettext('Trigger function'), - type: 'text', control: 'node-ajax-options', group: gettext('Definition'), - url:'fopts', cache_node: 'trigger_function', - },{ - id: 'eventname', label: gettext('Event'), - group: gettext('Definition'), cell: 'string', - options: [ - {label: gettext('DDL COMMAND START'), value: 'DDL_COMMAND_START'}, - {label: gettext('DDL COMMAND END'), value: 'DDL_COMMAND_END'}, - {label: gettext('SQL DROP'), value: 'SQL_DROP'}, - ], - control: 'select2', select2: { allowClear: false, width: '100%' }, - },{ - id: 'when', label: gettext('When TAG in'), cell: 'string', - type: 'text', group: gettext('Definition'), - control: Backform.SqlFieldControl, - extraClasses:['custom_height_css_class'], - },{ - id: 'seclabels', label: gettext('Security labels'), - model: pgBrowser.SecLabelModel, editable: false, type: 'collection', - group: gettext('Security'), mode: ['edit', 'create'], - min_version: 90200, canAdd: true, - canEdit: false, canDelete: true, control: 'unique-col-collection', - }, - ], - // event trigger model data validation. - validate: function() { - var msg = undefined; - // Clear any existing error msg. - this.errorModel.clear(); - - if (_.isUndefined(this.get('name')) - || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Event trigger name cannot be empty.'); - this.errorModel.set('name', msg); - return msg; - } - - if (_.isUndefined(this.get('eventowner')) - || String(this.get('eventowner')).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Event trigger owner cannot be empty.'); - this.errorModel.set('eventowner', msg); - return msg; - } - - if (_.isUndefined(this.get('enabled'))) { - msg = gettext('Event trigger enabled status cannot be empty.'); - this.errorModel.set('enabled', msg); - return msg; - } - - if (_.isUndefined(this.get('eventfunname')) - || String(this.get('eventfunname')).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Event trigger function cannot be empty.'); - this.errorModel.set('eventfunname', msg); - return msg; - } - - if (_.isUndefined(this.get('eventname'))) { - msg = gettext('Event trigger event cannot be empty.'); - this.errorModel.set('eventname', msg); - return msg; - } - - return null; - }, - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.js b/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.js index 6045b0c75..82001e107 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.js +++ b/web/pgadmin/browser/server_groups/servers/databases/extensions/static/js/extension.js @@ -13,9 +13,8 @@ import ExtensionsSchema from './extension.ui'; define('pgadmin.node.extension', [ 'sources/gettext', 'sources/url_for', 'jquery', 'underscore', - 'sources/pgadmin', 'pgadmin.browser', - 'pgadmin.backform', 'pgadmin.browser.collection', -], function(gettext, url_for, $, _, pgAdmin, pgBrowser, Backform) { + 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.browser.collection', +], function(gettext, url_for, $, _, pgAdmin, pgBrowser) { /* * Create and Add an Extension Collection into nodes @@ -96,109 +95,6 @@ define('pgadmin.node.extension', [ * Define model for the Node and specify the properties * of the model in schema. */ - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - schema: [ - { - id: 'name', label: gettext('Name'), first_empty: true, - type: 'text', mode: ['properties', 'create', 'edit'], - visible: true, url:'avails', readonly: function(m) { - return !m.isNew(); - }, - transform: function(data, cell) { - var res = [], - control = cell || this, - label = control.model.get('name'); - - if (!control.model.isNew()) { - res.push({label: label, value: label}); - } - else { - if (data && _.isArray(data)) { - _.each(data, function(d) { - if (d.installed_version === null) - - /* - * d contains json data and sets into - * select's option control - * - * We need to stringify data because formatter will - * convert Array Object as [Object] string - */ - res.push({label: d.name, value: JSON.stringify(d)}); - }); - } - } - return res; - }, - - /* - * extends NodeAjaxOptionsControl to override the properties - * getValueFromDOM which takes stringified data from option of - * select control and parse it. And `onChange` takes the stringified - * data from select's option, thus convert it to json format and set the - * data into Model which is used to enable/disable the schema field. - */ - control: Backform.NodeAjaxOptionsControl.extend({ - getValueFromDOM: function() { - var data = this.formatter.toRaw( - _.unescape(this.$el.find('select').val()), this.model); - /* - * return null if data is empty to prevent it from - * throwing parsing error. Adds check as name can be empty - */ - if (data === '') { - return null; - } - else if (typeof(data) === 'string') { - data=JSON.parse(data); - } - return data.name; - }, - - /* - * When name is changed, extract value from its select option and - * set attributes values into the model - */ - onChange: function() { - Backform.NodeAjaxOptionsControl.prototype.onChange.apply( - this, arguments - ); - var selectedValue = this.$el.find('select').val(); - if (selectedValue.trim() != '') { - var d = this.formatter.toRaw(selectedValue, this.model); - if(typeof(d) === 'string') - d=JSON.parse(d); - this.model.set({ - 'version' : '', - 'relocatable': ( - (!_.isNull(d.relocatable[0]) && - !_.isUndefined(d.relocatable[0])) ? d.relocatable[0]: '' - ), - }); - } else { - this.model.set({ - 'version': '', 'relocatable': true, 'schema': '', - }); - } - }, - }), - }, - { - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text', mode: ['properties'], - }, - { - id: 'owner', label: gettext('Owner'), control: 'node-list-by-name', - mode: ['properties'], node: 'role', cell: 'string', - cache_level: 'server', - }, - { - id: 'comment', label: gettext('Comment'), cell: 'string', - type: 'multiline', readonly: true, - }, - ], - }), getSchema: (treeNodeInfo, itemNodeData)=>{ let nodeObj = pgAdmin.Browser.Nodes['extension']; return new ExtensionsSchema( diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/static/js/foreign_server.js b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/static/js/foreign_server.js index 8f0ed95ef..4dc85aae0 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/static/js/foreign_server.js +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/static/js/foreign_server.js @@ -13,9 +13,9 @@ import ForeignServerSchema from './foreign_server.ui'; define('pgadmin.node.foreign_server', [ 'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'sources/pgadmin', - 'pgadmin.browser', 'pgadmin.backform', 'pgadmin.browser.collection', + 'pgadmin.browser', 'pgadmin.browser.collection', 'pgadmin.browser.server.privilege', -], function(gettext, url_for, $, _, pgAdmin, pgBrowser, Backform) { +], function(gettext, url_for, $, _, pgAdmin, pgBrowser) { // Extend the browser's collection class for foreign server collection if (!pgBrowser.Nodes['coll-foreign_server']) { @@ -82,45 +82,6 @@ define('pgadmin.node.foreign_server', [ } ); }, - - // Defining model for foreign server node - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - - // Default values! - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - - this.set({'fsrvowner': userInfo.name}, {silent: true}); - } - pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments); - }, - - // Defining schema for the foreign server node - schema: [ - { - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', disabled: function() { - return ( - this.mode == 'edit' && this.node_info.server.version < 90200 - ); - }, - }, { - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text', mode: ['properties'], - }, { - id: 'fsrvowner', label: gettext('Owner'), type: 'text', - control: Backform.NodeListByNameControl, node: 'role', - mode: ['edit', 'create', 'properties'], select2: { allowClear: false }, - }, { - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', - }, - ], - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/static/js/foreign_data_wrapper.js b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/static/js/foreign_data_wrapper.js index 5c5be3c85..b45be8187 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/static/js/foreign_data_wrapper.js +++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/static/js/foreign_data_wrapper.js @@ -12,10 +12,10 @@ import { getNodePrivilegeRoleSchema } from '../../../../static/js/privilege.ui'; import ForeignDataWrapperSchema from './foreign_data_wrapper.ui'; define('pgadmin.node.foreign_data_wrapper', [ - 'sources/gettext', 'sources/url_for', 'jquery', 'underscore', - 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.backform', + 'sources/gettext', 'sources/url_for', 'jquery', + 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.browser.collection', 'pgadmin.browser.server.privilege', -], function(gettext, url_for, $, _, pgAdmin, pgBrowser, Backform) { +], function(gettext, url_for, $, pgAdmin, pgBrowser) { // Extend the browser's collection class for foreign data wrapper collection if (!pgBrowser.Nodes['coll-foreign_data_wrapper']) { @@ -87,44 +87,6 @@ define('pgadmin.node.foreign_data_wrapper', [ } ); }, - - // Defining model for foreign data wrapper node - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - - // Default values! - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - - this.set({'fdwowner': userInfo.name}, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - - // Defining schema for the foreign data wrapper node - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', readonly: function() { - // name field will be disabled only if edit mode - return ( - this.mode == 'edit' - ); - }, - }, { - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text', mode: ['properties'], - }, { - id: 'fdwowner', label: gettext('Owner'), type: 'text', - control: Backform.NodeListByNameControl, node: 'role', - mode: ['edit', 'create', 'properties'], select2: { allowClear: false }, - }, { - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', - }], - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/languages/static/js/language.js b/web/pgadmin/browser/server_groups/servers/databases/languages/static/js/language.js index aaabe734d..56dc670a1 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/languages/static/js/language.js +++ b/web/pgadmin/browser/server_groups/servers/databases/languages/static/js/language.js @@ -10,13 +10,12 @@ import { getNodeAjaxOptions, getNodeListByName } from '../../../../../../static/js/node_ajax'; import LanguageSchema from './language.ui'; import { getNodePrivilegeRoleSchema } from '../../../../static/js/privilege.ui'; -import _ from 'lodash'; define('pgadmin.node.language', [ 'sources/gettext', 'sources/url_for', 'jquery', - 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.backform', + 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.browser.collection', 'pgadmin.browser.server.privilege', -], function(gettext, url_for, $, pgAdmin, pgBrowser, Backform) { +], function(gettext, url_for, $, pgAdmin, pgBrowser) { // Extend the browser's collection class for languages collection if (!pgBrowser.Nodes['coll-language']) { @@ -71,37 +70,6 @@ define('pgadmin.node.language', [ }]); }, - // Define the model for language node - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - - this.set({'lanowner': userInfo.name}, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - - // Define the schema for the language node - schema: [{ - id: 'name', label: gettext('Name'), type: 'text', - mode: ['properties'], - },{ - id: 'oid', label: gettext('OID'), cell: 'string', mode: ['properties'], - type: 'text', - },{ - id: 'lanowner', label: gettext('Owner'), type: 'text', - control: Backform.NodeListByNameControl, node: 'role', - mode: ['edit', 'properties', 'create'], select2: { allowClear: false }, - }, - { - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', - }, - ], - }), getSchema: function(treeNodeInfo, itemNodeData){ return new LanguageSchema( diff --git a/web/pgadmin/browser/server_groups/servers/databases/publications/static/js/publication.js b/web/pgadmin/browser/server_groups/servers/databases/publications/static/js/publication.js index b767057cd..697ddf265 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/publications/static/js/publication.js +++ b/web/pgadmin/browser/server_groups/servers/databases/publications/static/js/publication.js @@ -12,9 +12,9 @@ import PublicationSchema from './publication.ui'; define('pgadmin.node.publication', [ 'sources/gettext', 'sources/url_for', 'jquery', 'underscore', - 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.backform', + 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.browser.collection', 'pgadmin.browser.server.privilege', -], function(gettext, url_for, $, _, pgAdmin, pgBrowser, Backform) { +], function(gettext, url_for, $, _, pgAdmin, pgBrowser) { // Extend the browser's collection class for publications collection if (!pgBrowser.Nodes['coll-publication']) { @@ -23,7 +23,7 @@ define('pgadmin.node.publication', [ node: 'publication', label: gettext('Publications'), type: 'coll-publication', - columns: ['name', 'pubowner', 'pubtable', 'all_table'], + columns: ['name', 'pubowner', 'proptable', 'all_table'], }); } @@ -70,82 +70,7 @@ define('pgadmin.node.publication', [ icon: 'wcTabIcon icon-publication', data: {action: 'create'}, }]); }, - // Define the model for publication node - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - // Default values! - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - - this.set({'pubowner': userInfo.name}, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - - // Define the schema for the publication node - schema: [{ - id: 'name', label: gettext('Name'), type: 'text', - mode: ['properties', 'create', 'edit'], - visible: function() { - if(!_.isUndefined(this.node_info) && !_.isUndefined(this.node_info.server) - && !_.isUndefined(this.node_info.server.version) && - this.node_info.server.version >= 100000) { - return true; - } - return false; - }, - },{ - id: 'oid', label: gettext('OID'), cell: 'string', mode: ['properties'], - type: 'text', - },{ - id: 'pubowner', label: gettext('Owner'), type: 'text', - control: Backform.NodeListByNameControl, node: 'role', - disabled: function(m){ - if(m.isNew()) - return true; - return false; - }, - mode: ['edit', 'properties', 'create'], select2: { allowClear: false}, - },{ - id: 'all_table', label: gettext('All tables?'), type: 'switch', - group: gettext('Definition'), mode: ['edit', 'properties', 'create'], deps: ['name'], - readonly: function(m) {return !m.isNew();}, - }, - { - id: 'pubtable', label: gettext('Tables'), type: 'text', group: gettext('Definition'), - mode: ['properties'], - }, - ], - - - /* validate function is used to validate the input given by - * the user. In case of error, message will be displayed on - * the GUI for the respective control. - */ - - sessChanged: function() { - if (this.sessAttrs['pubtable'] == '' && this.origSessAttrs['pubtable'] == '') - return false; - return pgBrowser.DataModel.prototype.sessChanged.apply(this); - }, - - canCreate: function(itemData, item) { - - var treeData = pgBrowser.tree.getTreeNodeHierarchy(item), - server = treeData['server']; - - // If server is less than 10 then do not allow 'create' menu - if (server && server.version < 100000) - return false; - - // by default we want to allow create menu - return true; - }, - - }), getSchema: function(treeNodeInfo, itemNodeData){ return new PublicationSchema( diff --git a/web/pgadmin/browser/server_groups/servers/databases/publications/static/js/publication.ui.js b/web/pgadmin/browser/server_groups/servers/databases/publications/static/js/publication.ui.js index 46cfb0e87..55736d4b0 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/publications/static/js/publication.ui.js +++ b/web/pgadmin/browser/server_groups/servers/databases/publications/static/js/publication.ui.js @@ -147,7 +147,7 @@ export default class PublicationSchema extends BaseUISchema { group: gettext('Definition'), mode: ['edit', 'create'], deps: ['all_table'], disabled: obj.isAllTable, },{ - id: 'pubtable', label: gettext('Tables'), type: 'text', group: gettext('Definition'), + id: 'proptable', label: gettext('Tables'), type: 'text', group: gettext('Definition'), mode: ['properties'], },{ type: 'nested-fieldset', mode: ['create','edit', 'properties'], diff --git a/web/pgadmin/browser/server_groups/servers/databases/publications/templates/publications/sql/default/get_tables.sql b/web/pgadmin/browser/server_groups/servers/databases/publications/templates/publications/sql/default/get_tables.sql index 58eac45a8..668b4eba5 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/publications/templates/publications/sql/default/get_tables.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/publications/templates/publications/sql/default/get_tables.sql @@ -1,3 +1,6 @@ SELECT pg_catalog.quote_ident(pgb_table.schemaname)||'.'||pg_catalog.quote_ident(pgb_table.tablename) -AS pubtable FROM pg_catalog.pg_publication_tables pgb_table WHERE pubname = '{{ pname }}' +AS pubtable, +pg_catalog.quote_ident(pgb_table.schemaname)||'.'||pg_catalog.quote_ident(pgb_table.tablename) +AS proptable + FROM pg_catalog.pg_publication_tables pgb_table WHERE pubname = '{{ pname }}' AND pgb_table.schemaname NOT LIKE 'pgagent'; diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/aggregates/static/js/aggregate.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/aggregates/static/js/aggregate.js index 25c0f04fc..df8d9b4f9 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/aggregates/static/js/aggregate.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/aggregates/static/js/aggregate.js @@ -45,37 +45,6 @@ define('pgadmin.node.aggregate', [ this.initialized = true; }, - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - - // Default values! - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - var schemaInfo = args.node_info.schema; - - this.set({'owner': userInfo.name}, {silent: true}); - this.set({'schema': schemaInfo._label}, {silent: true}); - } - pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments); - }, - - schema: [{ - id: 'name', label: gettext('Aggregate'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - },{ - id: 'owner', label: gettext('Owner'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - control: 'node-list-by-name', - node: 'role', - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', mode: ['properties', 'create', 'edit'], - } - ], - }), getSchema: ()=>{ return new AggregateSchema(); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/columns/static/js/catalog_object_column.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/columns/static/js/catalog_object_column.js index 8785d147a..e1152eb22 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/columns/static/js/catalog_object_column.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/columns/static/js/catalog_object_column.js @@ -45,32 +45,6 @@ define('pgadmin.node.catalog_object_column', [ getSchema: function() { return new CatalogObjectColumnSchema(); }, - model: pgAdmin.Browser.Node.Model.extend({ - defaults: { - attname: undefined, - attowner: undefined, - atttypid: undefined, - attnum: undefined, - cltype: undefined, - collspcname: undefined, - attacl: undefined, - is_sys_obj: undefined, - description: undefined, - }, - schema: [{ - id: 'attname', label: gettext('Column'), cell: 'string', - type: 'text', readonly: true, - },{ - id: 'attnum', label: gettext('Position'), cell: 'string', - type: 'text', readonly: true, - },{ - id: 'cltype', label: gettext('Data type'), cell: 'string', - group: gettext('Definition'), type: 'text', readonly: true, - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', readonly: true, - }], - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/static/js/catalog_object.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/static/js/catalog_object.js index 06753a427..dac46721a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/static/js/catalog_object.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/catalog_objects/static/js/catalog_object.js @@ -43,31 +43,6 @@ define('pgadmin.node.catalog_object', [ }, getSchema: ()=>new CatalogObjectSchema(), - /* Few fields are kept since the properties tab for collection is not - yet migrated to new react schema. Once the properties for collection - is removed, remove this model */ - model: pgAdmin.Browser.Node.Model.extend({ - defaults: { - name: undefined, - namespaceowner: undefined, - nspacl: undefined, - description: undefined, - }, - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', readonly: true, - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text', - },{ - id: 'owner', label: gettext('Owner'), cell: 'string', - type: 'text', readonly: true, - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline' , readonly: true, - }, - ], - }), }); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/static/js/collation.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/static/js/collation.js index 586f410bc..4d3dff132 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/static/js/collation.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/collations/static/js/collation.js @@ -69,42 +69,6 @@ define('pgadmin.node.collation', [ ]); }, - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - - // Default values! - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - var schemaInfo = args.node_info.schema; - - this.set({'owner': userInfo.name}, {silent: true}); - this.set({'schema': schemaInfo._label}, {silent: true}); - } - pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments); - }, - - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - disabled: 'inSchema', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text' , mode: ['properties'], - },{ - id: 'owner', label: gettext('Owner'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - disabled: 'inSchema', control: 'node-list-by-name', - node: 'role', - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', mode: ['properties', 'create', 'edit'], - disabled: 'inSchema', - } - ], - }), getSchema: (treeNodeInfo, itemNodeData)=>{ let nodeObj = pgAdmin.Browser.Nodes['collation']; return new CollationSchema( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain_constraints/static/js/domain_constraints.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain_constraints/static/js/domain_constraints.js index 67f23e5ca..4c6594ddb 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain_constraints/static/js/domain_constraints.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/domain_constraints/static/js/domain_constraints.js @@ -75,43 +75,6 @@ define('pgadmin.node.domain_constraints', [ getSchema: function() { return new DomainConstraintSchema(); }, - - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - // Domain Constraint Schema - schema: [{ - id: 'name', label: gettext('Name'), type:'text', cell:'string', - },{ - id: 'description', label: gettext('Comment'), type: 'multiline', cell: - 'string', mode: ['properties', 'create', 'edit'], min_version: 90500, - }], - // Client Side Validation - validate: function() { - var err = {}, - errmsg; - - if (_.isUndefined(this.get('name')) || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') { - err['name'] = gettext('Name cannot be empty.'); - errmsg = err['name']; - } - - if (_.isUndefined(this.get('consrc')) || String(this.get('consrc')).replace(/^\s+|\s+$/g, '') == '') { - err['consrc'] = gettext('Check cannot be empty.'); - errmsg = errmsg || err['consrc']; - - } - - this.errorModel.clear().set(err); - - if (_.size(err)) { - this.trigger('on-status', {msg: errmsg}); - return errmsg; - } - - return null; - - }, - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/static/js/domain.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/static/js/domain.js index a14fbf395..8b2b361f9 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/static/js/domain.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/domains/static/js/domain.js @@ -98,38 +98,6 @@ define('pgadmin.node.domain', [ } ); }, - - // Domain Node Model - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - if (isNew) { - // Set Selected Schema - var schema = args.node_info.schema.label; - this.set({'basensp': schema}, {silent: true}); - - // Set Current User - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - this.set({'owner': userInfo.name}, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - // Domain Schema - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text' , mode: ['properties'], - },{ - id: 'owner', label: gettext('Owner'), cell: 'string', control: Backform.NodeListByNameControl, - node: 'role', type: 'text', mode: ['edit', 'create', 'properties'], - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', - }], - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/static/js/foreign_table.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/static/js/foreign_table.js index 8e6059486..3affdeefb 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/static/js/foreign_table.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/static/js/foreign_table.js @@ -10,15 +10,16 @@ import { getNodeListByName, getNodeAjaxOptions } from '../../../../../../../stat import { getNodeVariableSchema } from '../../../../../static/js/variable.ui'; import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui'; import ForeignTableSchema from './foreign_table.ui'; +import _ from 'lodash'; /* Create and Register Foreign Table Collection and Node. */ define('pgadmin.node.foreign_table', [ - 'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'backbone', - 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.backform', 'pgadmin.backgrid', + 'sources/gettext', 'sources/url_for', 'jquery', 'backbone', + 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.backgrid', 'pgadmin.node.schema.dir/child', 'pgadmin.node.schema.dir/schema_child_tree_node', 'pgadmin.browser.collection', ], function( - gettext, url_for, $, _, Backbone, pgAdmin, pgBrowser, Backform, Backgrid, + gettext, url_for, $, Backbone, pgAdmin, pgBrowser, Backgrid, schemaChild, schemaChildTreeNode ) { @@ -34,465 +35,6 @@ define('pgadmin.node.foreign_table', [ }); } - // Options Model - var ColumnOptionsModel = pgBrowser.Node.Model.extend({ - idAttribute: 'option', - defaults: { - option: undefined, - value: undefined, - }, - schema: [ - {id: 'option', label: gettext('Option'), type:'text', editable: true, cellHeaderClasses: 'width_percent_30'}, - { - id: 'value', label: gettext('Value'), type: 'text', editable: true, cellHeaderClasses: 'width_percent_50', - }, - ], - validate: function() { - if (_.isUndefined(this.get('value')) || - _.isNull(this.get('value')) || - String(this.get('value')).replace(/^\s+|\s+$/g, '') == '') { - var msg = 'Please enter a value.'; - - this.errorModel.set('value', msg); - - return msg; - } else { - this.errorModel.unset('value'); - } - - return null; - }, - }); - - // Columns Model - var ColumnsModel = pgBrowser.Node.Model.extend({ - idAttribute: 'attnum', - defaults: { - attname: undefined, - datatype: undefined, - typlen: undefined, - precision: undefined, - typdefault: undefined, - attnotnull: undefined, - collname: undefined, - attnum: undefined, - inheritedfrom: undefined, - inheritedid: undefined, - attstattarget: undefined, - coloptions: [], - }, - type_options: undefined, - schema: [{ - id: 'attname', label: gettext('Name'), cell: 'string', type: 'text', - editable: 'is_editable_column', cellHeaderClasses: 'width_percent_40', - },{ - id: 'datatype', label: gettext('Data type'), cell: 'node-ajax-options', - control: 'node-ajax-options', type: 'text', url: 'get_types', - editable: 'is_editable_column', cellHeaderClasses: 'width_percent_0', - group: gettext('Definition'), - transform: function(d, self){ - self.model.type_options = d; - return d; - }, - }, - { - id: 'typlen', label: gettext('Length'), - cell: 'string', group: gettext('Definition'), - type: 'int', deps: ['datatype'], - disabled: function(m) { - var val = m.get('typlen'); - // We will store type from selected from combobox - if(!(_.isUndefined(m.get('inheritedid')) - || _.isNull(m.get('inheritedid')) - || _.isUndefined(m.get('inheritedfrom')) - || _.isNull(m.get('inheritedfrom')))) { - - if (!_.isUndefined(val)) { - setTimeout(function() { - m.set('typlen', undefined); - }, 10); - } - return true; - } - - var of_type = m.get('datatype'), - has_length = false; - if(m.type_options) { - m.set('is_tlength', false, {silent: true}); - - // iterating over all the types - _.each(m.type_options, function(o) { - // if type from selected from combobox matches in options - if ( of_type == o.value ) { - // if length is allowed for selected type - if(o.length) - { - // set the values in model - has_length = true; - m.set('is_tlength', true, {silent: true}); - m.set('min_val', o.min_val, {silent: true}); - m.set('max_val', o.max_val, {silent: true}); - } - } - }); - - if (!has_length && !_.isUndefined(val)) { - setTimeout(function() { - m.set('typlen', undefined); - }, 10); - } - - return !(m.get('is_tlength')); - } - if (!has_length && !_.isUndefined(val)) { - setTimeout(function() { - m.set('typlen', undefined); - }, 10); - } - return true; - }, - cellHeaderClasses: 'width_percent_10', - }, - { - id: 'precision', label: gettext('Precision'), - type: 'int', deps: ['datatype'], - cell: 'string', group: gettext('Definition'), - disabled: function(m) { - var val = m.get('precision'); - if(!(_.isUndefined(m.get('inheritedid')) - || _.isNull(m.get('inheritedid')) - || _.isUndefined(m.get('inheritedfrom')) - || _.isNull(m.get('inheritedfrom')))) { - - if (!_.isUndefined(val)) { - setTimeout(function() { - m.set('precision', undefined); - }, 10); - } - return true; - } - - var of_type = m.get('datatype'), - has_precision = false; - - if(m.type_options) { - m.set('is_precision', false, {silent: true}); - // iterating over all the types - _.each(m.type_options, function(o) { - // if type from selected from combobox matches in options - if ( of_type == o.value ) { - // if precession is allowed for selected type - if(o.precision) - { - has_precision = true; - // set the values in model - m.set('is_precision', true, {silent: true}); - m.set('min_val', o.min_val, {silent: true}); - m.set('max_val', o.max_val, {silent: true}); - } - } - }); - if (!has_precision && !_.isUndefined(val)) { - setTimeout(function() { - m.set('precision', undefined); - }, 10); - } - return !(m.get('is_precision')); - } - if (!has_precision && !_.isUndefined(val)) { - setTimeout(function() { - m.set('precision', undefined); - }, 10); - } - return true; - }, cellHeaderClasses: 'width_percent_10', - }, - { - id: 'typdefault', label: gettext('Default'), type: 'text', - cell: 'string', min_version: 90300, group: gettext('Definition'), - placeholder: gettext('Enter an expression or a value.'), - cellHeaderClasses: 'width_percent_10', - editable: function(m) { - if(!(_.isUndefined(m.get('inheritedid')) - || _.isNull(m.get('inheritedid')) - || _.isUndefined(m.get('inheritedfrom')) - || _.isNull(m.get('inheritedfrom')))) { return false; } - if (this.get('node_info').server.version < 90300){ - return false; - } - return true; - }, - }, - { - id: 'attnotnull', label: gettext('Not NULL?'), - cell: 'boolean',type: 'switch', editable: 'is_editable_column', - cellHeaderClasses: 'width_percent_10', group: gettext('Definition'), - }, - { - id: 'attstattarget', label: gettext('Statistics'), min_version: 90200, - cell: 'integer', type: 'int', group: gettext('Definition'), - editable: function(m) { - if (_.isUndefined(m.isNew) || m.isNew()) { return false; } - if (this.get('node_info').server.version < 90200){ - return false; - } - return (_.isUndefined(m.get('inheritedid')) || _.isNull(m.get('inheritedid')) - || _.isUndefined(m.get('inheritedfrom')) || _.isNull(m.get('inheritedfrom'))) ? true : false; - }, cellHeaderClasses: 'width_percent_10', - }, - { - id: 'collname', label: gettext('Collation'), cell: 'node-ajax-options', - control: 'node-ajax-options', type: 'text', url: 'get_collations', - min_version: 90300, editable: function(m) { - if (!(_.isUndefined(m.isNew)) && !m.isNew()) { return false; } - return (_.isUndefined(m.get('inheritedid')) || _.isNull(m.get('inheritedid')) - || _.isUndefined(m.get('inheritedfrom')) || _.isNull(m.get('inheritedfrom'))) ? true : false; - }, - cellHeaderClasses: 'width_percent_20', group: gettext('Definition'), - }, - { - id: 'attnum', cell: 'string',type: 'text', visible: false, - }, - { - id: 'inheritedfrom', label: gettext('Inherited From'), cell: 'string', - type: 'text', visible: false, mode: ['properties', 'edit'], - cellHeaderClasses: 'width_percent_10', - }, - { - id: 'coloptions', label: gettext('Options'), cell: 'string', - type: 'collection', group: gettext('Options'), mode: ['edit', 'create'], - model: ColumnOptionsModel, canAdd: true, canDelete: true, canEdit: false, - control: Backform.UniqueColCollectionControl, uniqueCol : ['option'], - min_version: 90200, - }], - validate: function() { - var errmsg = null; - - if (_.isUndefined(this.get('attname')) || String(this.get('attname')).replace(/^\s+|\s+$/g, '') == '') { - errmsg = gettext('Column Name cannot be empty.'); - this.errorModel.set('attname', errmsg); - } else { - this.errorModel.unset('attname'); - } - - if (_.isUndefined(this.get('datatype')) || String(this.get('datatype')) - .replace(/^\s+|\s+$/g, '') == '') { - errmsg = gettext('Column Datatype cannot be empty.'); - this.errorModel.set('datatype', errmsg); - } else { - this.errorModel.unset('datatype'); - } - - return errmsg; - }, - is_editable_column: function(m) { - return (_.isUndefined(m.get('inheritedid')) || _.isNull(m.get('inheritedid')) - || _.isUndefined(m.get('inheritedfrom')) || _.isNull(m.get('inheritedfrom'))) ? true : false; - }, - toJSON: Backbone.Model.prototype.toJSON, - }); - - - /* NodeAjaxOptionsMultipleControl is for multiple selection of Combobox. - * This control is used to select Multiple Parent Tables to be inherited. - * It also populates/vacates Columns on selection/deselection of the option (i.e. table name). - * To populates the column, it calls the server and fetch the columns data - * for the selected table. - */ - var NodeAjaxOptionsMultipleControl = Backform.NodeAjaxOptionsControl.extend({ - onChange: function() { - var model = this.model, - attrArr = this.field.get('name').split('.'), - name = attrArr.shift(), - path = attrArr.join('.'), - value = this.getValueFromDOM(), - changes = {}, - columns = model.get('columns'), - inherits = model.get(name); - - if (this.model.errorModel instanceof Backbone.Model) { - if (_.isEmpty(path)) { - this.model.errorModel.unset(name); - } else { - var nestedError = this.model.errorModel.get(name); - if (nestedError) { - this.keyPathSetter(nestedError, path, null); - this.model.errorModel.set(name, nestedError); - } - } - } - - var self = this; - - if (typeof(inherits) == 'string'){ inherits = JSON.parse(inherits); } - - // Remove Columns if inherit option is deselected from the combobox - if(_.size(value) < _.size(inherits)) { - var dif = _.difference(inherits, value); - var rmv_columns = columns.where({inheritedid: parseInt(dif[0])}); - columns.remove(rmv_columns); - } - else - { - _.each(value, function(i) { - // Fetch Columns from server - var fnd_columns = columns.where({inheritedid: parseInt(i)}); - if (fnd_columns && fnd_columns.length <= 0) { - var inhted_columns = self.fetchColumns(i); - columns.add(inhted_columns); - } - }); - } - - changes[name] = _.isEmpty(path) ? value : _.clone(model.get(name)) || {}; - this.stopListening(this.model, 'change:' + name, this.render); - model.set(changes); - this.listenTo(this.model, 'change:' + name, this.render); - }, - fetchColumns: function(table_id){ - var self = this, - url = 'get_columns', - m = self.model.top || self.model; - - var node = this.field.get('schema_node'), - node_info = this.field.get('node_info'), - full_url = node.generate_url.apply( - node, [ - null, url, this.field.get('node_data'), - this.field.get('url_with_id') || false, node_info, - ]), - cache_level = this.field.get('cache_level') || node.type, - cache_node = this.field.get('cache_node'); - - cache_node = (cache_node && pgBrowser.Nodes['cache_node']) || node; - - m.trigger('pgadmin:view:fetching', m, self.field); - var data = {attrelid: table_id}; - - // Fetching Columns data for the selected table. - $.ajax({ - async: false, - url: full_url, - data: data, - }) - .done(function(res) { - /* - * We will cache this data for short period of time for avoiding - * same calls. - */ - data = cache_node.cache(url, node_info, cache_level, res.data); - - }) - .fail(function() { - m.trigger('pgadmin:view:fetch:error', m, self.field); - }); - m.trigger('pgadmin:view:fetched', m, self.field); - - // To fetch only options from cache, we do not need time from 'at' - // attribute but only options. - // - // It is feasible that the data may not have been fetched. - data = (data && data.data) || []; - return data; - - }, - }); - - - // Constraints Model - var ConstraintModel = pgBrowser.Node.Model.extend({ - idAttribute: 'conoid', - initialize: function(attrs) { - var isNew = (_.size(attrs) === 0); - if (!isNew) { - this.convalidated_default = this.get('convalidated'); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - defaults: { - conoid: undefined, - conname: undefined, - consrc: undefined, - connoinherit: undefined, - convalidated: true, - conislocal: undefined, - }, - convalidated_default: true, - schema: [{ - id: 'conoid', type: 'text', cell: 'string', visible: false, - },{ - id: 'conname', label: gettext('Name'), type: 'text', cell: 'string', - editable: 'is_editable', cellHeaderClasses: 'width_percent_30', - },{ - id: 'consrc', label: gettext('Check'), type: 'multiline', - editable: 'is_editable', cell: Backgrid.Extension.TextareaCell, - cellHeaderClasses: 'width_percent_30', - },{ - id: 'connoinherit', label: gettext('No inherit?'), type: 'switch', - cell: 'boolean', editable: 'is_editable', - cellHeaderClasses: 'width_percent_20', - },{ - id: 'convalidated', label: gettext('Validate?'), type: 'switch', - cell: 'boolean', cellHeaderClasses: 'width_percent_20', - editable: function(m) { - if (_.isUndefined(m.isNew)) { return true; } - if (!m.isNew()) { - if(m.get('convalidated') && m.convalidated_default) { - return false; - } - return true; - } - return true; - }, - }, - ], - validate: function() { - var err = {}, - errmsg; - - if (_.isUndefined(this.get('conname')) || String(this.get('conname')).replace(/^\s+|\s+$/g, '') == '') { - err['conname'] = gettext('Constraint Name cannot be empty.'); - errmsg = err['conname']; - } - - if (_.isUndefined(this.get('consrc')) || String(this.get('consrc')) - .replace(/^\s+|\s+$/g, '') == '') { - err['consrc'] = gettext('Constraint Check cannot be empty.'); - errmsg = errmsg || err['consrc']; - } - - this.errorModel.clear().set(err); - - return errmsg; - }, - is_editable: function(m) { - return _.isUndefined(m.isNew) ? true : m.isNew(); - }, - toJSON: Backbone.Model.prototype.toJSON, - }); - - - // Options Model - var OptionsModel = pgBrowser.Node.Model.extend({ - defaults: { - option: undefined, - value: undefined, - }, - schema: [{ - id: 'option', label: gettext('Option'), cell: 'string', type: 'text', - editable: true, cellHeaderClasses:'width_percent_50', - },{ - id: 'value', label: gettext('Value'), cell: 'string',type: 'text', - editable: true, cellHeaderClasses:'width_percent_50', - }, - ], - validate: function() { - // TODO: Add validation here - }, - toJSON: Backbone.Model.prototype.toJSON, - }); - - if (!pgBrowser.Nodes['foreign_table']) { pgBrowser.Nodes['foreign_table'] = schemaChild.SchemaChildNode.extend({ type: 'foreign_table', @@ -561,160 +103,6 @@ define('pgadmin.node.foreign_table', [ } ); }, - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - if (isNew) { - var schema = args.node_info.schema._label, - userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - - // Set Selected Schema and Current User - this.set({ - 'basensp': schema, 'owner': userInfo.name, - }, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - defaults: { - name: undefined, - oid: undefined, - owner: undefined, - basensp: undefined, - is_sys_obj: undefined, - description: undefined, - ftsrvname: undefined, - strftoptions: undefined, - inherits: [], - columns: [], - constraints: [], - ftoptions: [], - relacl: [], - stracl: [], - seclabels: [], - }, - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text' , mode: ['properties'], - },{ - id: 'owner', label: gettext('Owner'), cell: 'string', - control: Backform.NodeListByNameControl, - node: 'role', type: 'text', select2: { allowClear: false }, - },{ - id: 'basensp', label: gettext('Schema'), cell: 'node-list-by-name', - control: 'node-list-by-name', cache_level: 'database', type: 'text', - node: 'schema', mode:['create', 'edit'], - },{ - id: 'is_sys_obj', label: gettext('System foreign table?'), - cell:'boolean', type: 'switch', mode: ['properties'], - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', - },{ - id: 'ftsrvname', label: gettext('Foreign server'), cell: 'string', control: 'node-ajax-options', - type: 'text', group: gettext('Definition'), url: 'get_foreign_servers', - readonly: function(m) { return !m.isNew(); }, cache_node: 'database', - },{ - id: 'inherits', label: gettext('Inherits'), group: gettext('Definition'), - type: 'array', min_version: 90500, control: NodeAjaxOptionsMultipleControl, - url: 'get_tables', select2: {multiple: true}, - 'cache_level': 'database', - transform: function(d) { - if (this.field.get('mode') == 'edit') { - var oid = this.model.get('oid'); - var s = _.findWhere(d, {'id': oid}); - if (s) { - d = _.reject(d, s); - } - } - return d; - }, - },{ - id: 'columns', label: gettext('Columns'), cell: 'string', - type: 'collection', group: gettext('Columns'), mode: ['edit', 'create'], - model: ColumnsModel, canAdd: true, canDelete: true, canEdit: true, - columns: ['attname', 'datatype', 'inheritedfrom'], - canDeleteRow: function(m) { - return (_.isUndefined(m.get('inheritedid')) || _.isNull(m.get('inheritedid')) - || _.isUndefined(m.get('inheritedfrom')) || _.isNull(m.get('inheritedfrom'))) ? true : false; - }, - canEditRow: function(m) { - return (_.isUndefined(m.get('inheritedid')) || _.isNull(m.get('inheritedid')) - || _.isUndefined(m.get('inheritedfrom')) || _.isNull(m.get('inheritedfrom'))) ? true : false; - }, - }, - { - id: 'constraints', label: gettext('Constraints'), cell: 'string', - type: 'collection', group: gettext('Constraints'), mode: ['edit', 'create'], - model: ConstraintModel, canAdd: true, canDelete: true, columns: ['conname','consrc', 'connoinherit', 'convalidated'], - canEdit: function(o) { - if (o instanceof Backbone.Model) { - if (o instanceof ConstraintModel) { - return o.isNew(); - } - } - return true; - }, min_version: 90500, canDeleteRow: function(m) { - return (m.get('conislocal') == true || _.isUndefined(m.get('conislocal'))) ? true : false; - }, - },{ - id: 'strftoptions', label: gettext('Options'), cell: 'string', - type: 'text', group: gettext('Definition'), mode: ['properties'], - },{ - id: 'ftoptions', label: gettext('Options'), cell: 'string', - type: 'collection', group: gettext('Options'), mode: ['edit', 'create'], - model: OptionsModel, canAdd: true, canDelete: true, canEdit: false, - control: 'unique-col-collection', uniqueCol : ['option'], - },{ - id: 'relacl', label: gettext('Privileges'), cell: 'string', - type: 'text', group: gettext('Security'), - mode: ['properties'], min_version: 90200, - }, pgBrowser.SecurityGroupSchema, { - id: 'acl', label: gettext('Privileges'), model: pgAdmin - .Browser.Node.PrivilegeRoleModel.extend( - {privileges: ['a','r','w','x']}), uniqueCol : ['grantee', 'grantor'], - editable: false, type: 'collection', group: 'security', - mode: ['edit', 'create'], - canAdd: true, canDelete: true, control: 'unique-col-collection', - min_version: 90200, - },{ - id: 'seclabels', label: gettext('Security labels'), - model: pgBrowser.SecLabelModel, type: 'collection', - group: 'security', mode: ['edit', 'create'], - min_version: 90100, canAdd: true, - canEdit: false, canDelete: true, - control: 'unique-col-collection', uniqueCol : ['provider'], - }, - ], - validate: function() - { - var err = {}, - errmsg = null; - - if (_.isUndefined(this.get('name')) || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') { - err['name'] = gettext('Name cannot be empty.'); - errmsg = err['name']; - } - - if (_.isUndefined(this.get('basensp')) || String(this.get('basensp')) - .replace(/^\s+|\s+$/g, '') == '') { - err['basensp'] = gettext('Schema cannot be empty.'); - errmsg = errmsg || err['basensp']; - } - - if (_.isUndefined(this.get('ftsrvname')) || String(this.get('ftsrvname')).replace(/^\s+|\s+$/g, '') == '') { - err['ftsrvname'] = gettext('Foreign server cannot be empty.'); - errmsg = errmsg || err['ftsrvname']; - } - - this.errorModel.clear().set(err); - - return errmsg; - }, - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/static/js/fts_configuration.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/static/js/fts_configuration.js index 0049de5bd..073dd4acc 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/static/js/fts_configuration.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_configurations/static/js/fts_configuration.js @@ -93,32 +93,6 @@ define('pgadmin.node.fts_configuration', [ } ); }, - - // Defining model for FTS Configuration node - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - - initialize: function(attrs, opts) { - var isNew = (_.size(attrs) === 0); - pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments); - - if (isNew) { - var user = pgBrowser.serverInfo[opts.node_info.server._id].user; - this.set({ - 'owner': user.name, - 'schema': opts.node_info.schema._id, - }, {silent: true}); - } - }, - // Defining schema for FTS Configuration - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', cellHeaderClasses: 'width_percent_50', - }, { - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', cellHeaderClasses: 'width_percent_50', - }], - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/static/js/fts_dictionary.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/static/js/fts_dictionary.js index 5d5bd3a8f..0ea741034 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/static/js/fts_dictionary.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_dictionaries/static/js/fts_dictionary.js @@ -88,31 +88,6 @@ define('pgadmin.node.fts_dictionary', [ } ); }, - - // Defining backform model for FTS Dictionary node - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments); - - if (isNew) { - var user = pgBrowser.serverInfo[args.node_info.server._id].user; - this.set({ - 'owner': user.name, - 'schema': args.node_info.schema._id, - }, {silent: true}); - } - }, - // Defining schema for fts dictionary - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', cellHeaderClasses: 'width_percent_50', - }, { - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', cellHeaderClasses: 'width_percent_50', - }], - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/static/js/fts_parser.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/static/js/fts_parser.js index 27a4ce87f..ad5579d0d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/static/js/fts_parser.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_parsers/static/js/fts_parser.js @@ -70,108 +70,6 @@ define('pgadmin.node.fts_parser', [ }, - // Defining backform model for fts parser node - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - defaults: { - name: undefined, // Fts parser name - is_sys_obj: undefined, // Is system object - description: undefined, // Comment on parser - }, - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - pgAdmin.Browser.Node.Model.prototype.initialize.apply( - this, arguments - ); - if (isNew) { - this.set('schema', args.node_info.schema._id); - } - }, - // Defining schema for fts parser - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', cellHeaderClasses: 'width_percent_50', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - editable: false, type: 'text', mode:['properties'], - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', cellHeaderClasses: 'width_percent_50', - }], - - /* - * Triggers control specific error messages for parser name, - * start, token, end, lextype functions and schema, if any one of them is not specified - * while creating new fts parser - */ - validate: function() { - var name = this.get('name'), - start = this.get('prsstart'), - token = this.get('prstoken'), - end = this.get('prsend'), - lextype = this.get('prslextype'), - schema = this.get('schema'), - msg; - - // Validate fts parser name - if (_.isUndefined(name) || - _.isNull(name) || - String(name).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Name must be specified.'); - this.errorModel.set('name', msg); - return msg; - } - - // Validate start function control - else if (_.isUndefined(start) || - _.isNull(start) || - String(start).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Start function must be selected.'); - this.errorModel.set('prsstart', msg); - return msg; - } - - // Validate gettoken function control - else if (_.isUndefined(token) || - _.isNull(token) || - String(token).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Get next token function must be selected.'); - this.errorModel.set('prstoken', msg); - return msg; - } - - // Validate end function control - else if (_.isUndefined(end) || - _.isNull(end) || - String(end).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('End function must be selected.'); - this.errorModel.set('prsend', msg); - return msg; - } - - // Validate lextype function control - else if (_.isUndefined(lextype) || - _.isNull(lextype) || - String(lextype).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Lextype function must be selected.'); - this.errorModel.set('prslextype', msg); - return msg; - } - - // Validate schema for fts parser - else if (_.isUndefined(schema) || - _.isNull(schema) || - String(schema).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Schema must be selected.'); - this.errorModel.set('schema', msg); - return msg; - } - else this.errorModel.clear(); - - this.trigger('on-status-clear'); - return null; - }, - }), getSchema: (treeNodeInfo, itemNodeData) => { let nodeObj = pgAdmin.Browser.Nodes['fts_parser']; return new FTSParserSchema( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/static/js/fts_template.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/static/js/fts_template.js index 791adb2f9..5320246f3 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/static/js/fts_template.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/static/js/fts_template.js @@ -70,65 +70,6 @@ define('pgadmin.node.fts_template', [ }, - // Defining backform model for fts template node - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments); - if (isNew) { - this.set('schema', args.node_info.schema._id); - } - }, - // Defining schema for fts template - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', cellHeaderClasses: 'width_percent_50', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - editable: false, type: 'text', mode:['properties'], - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', cellHeaderClasses: 'width_percent_50', - }], - - /* - * Triggers control specific error messages for template name, - * lexize function and schema, if any one of them is not specified - * while creating new fts template - */ - validate: function() { - var name = this.get('name'), - lexize = this.get('tmpllexize'), - schema = this.get('schema'), - msg; - - // Validate fts template name - if (_.isUndefined(name) || _.isNull(name) || String(name).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Name must be specified.'); - this.errorModel.set('name', msg); - return msg; - } - - // Validate lexize function control - else if (_.isUndefined(lexize) || _.isNull(lexize) || String(lexize).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Lexize function must be selected.'); - this.errorModel.set('tmpllexize', msg); - return msg; - } - - // Validate schema for fts template - else if (_.isUndefined(schema) || _.isNull(schema) || String(schema).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Schema must be selected.'); - this.errorModel.set('schema', msg); - return msg; - } - else this.errorModel.clear(); - - this.trigger('on-status-clear'); - return null; - }, - }), getSchema: (treeNodeInfo, itemNodeData) => { let nodeObj = pgAdmin.Browser.Nodes['fts_template']; return new FTSTemplateSchema( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/function.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/function.js index 41171c62a..b9107d98f 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/function.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/function.js @@ -11,7 +11,6 @@ import { getNodeAjaxOptions, getNodeListByName, getNodeListById} from '../../../ import FunctionSchema from './function.ui'; import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui'; import { getNodeVariableSchema } from '../../../../../static/js/variable.ui'; -import _ from 'lodash'; /* Create and Register Function Collection and Node. */ define('pgadmin.node.function', [ @@ -109,44 +108,7 @@ define('pgadmin.node.function', [ } ); }, - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - if (isNew) { - // Set Selected Schema - var schema_id = args.node_info.schema._id; - this.set({'pronamespace': schema_id}, {silent: true}); - - // Set Current User - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - this.set({'funcowner': userInfo.name}, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - disabled: 'isDisabled', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text' , mode: ['properties'], - },{ - id: 'funcowner', label: gettext('Owner'), cell: 'string', - control: Backform.NodeListByNameControl, node: 'role', type: - 'text', disabled: 'isDisabled', - },{ - id: 'pronamespace', label: gettext('Schema'), cell: 'string', - control: 'node-list-by-id', type: 'text', cache_level: 'database', - node: 'schema', disabled: 'isDisabled', mode: ['create', 'edit'], - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', disabled: 'isDisabled', - }], - }), }); - } - return pgBrowser.Nodes['function']; }); diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/procedure.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/procedure.js index 1b6b61863..7cbcdc907 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/procedure.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/procedure.js @@ -11,7 +11,6 @@ import { getNodeAjaxOptions, getNodeListByName, getNodeListById} from '../../../ import FunctionSchema from './function.ui'; import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.ui'; import { getNodeVariableSchema } from '../../../../../static/js/variable.ui'; -import _ from 'lodash'; /* Create and Register Procedure Collection and Node. */ define('pgadmin.node.procedure', [ @@ -126,126 +125,6 @@ define('pgadmin.node.procedure', [ ); }, - model: Function.model.extend({ - defaults: _.extend({}, - Function.model.prototype.defaults, - { - lanname: 'edbspl', - } - ), - canVarAdd: function() { - var server = this.node_info.server; - return server.version >= 90500; - }, - isVisible: function() { - if (this.name == 'sysfunc') { return false; } - else if (this.name == 'sysproc') { return true; } - return false; - }, - isDisabled: function(m) { - if(this.node_info && 'catalog' in this.node_info) { - return true; - } - switch(this.name){ - case 'provolatile': - case 'proisstrict': - case 'procost': - case 'proleakproof': - if(this.node_info.server.version < 90500 || - this.node_info.server.server_type != 'ppas' || - m.get('lanname') != 'edbspl') { - - setTimeout(function() { - m.set('provolatile', null); - m.set('proisstrict', false); - m.set('procost', null); - m.set('proleakproof', false); - }, 10); - return true; - } - else{ - return false; - } - case 'variables': - case 'prosecdef': - return this.node_info.server.version < 90500; - case 'prorows': - var server = this.node_info.server; - return !(server.version >= 90500 && m.get('proretset') == true); - case 'proparallel': - if (this.node_info.server.version < 90600 || - this.node_info.server.server_type != 'ppas' || - m.get('lanname') != 'edbspl') { - setTimeout(function() { - m.set('proparallel', null); - }, 10); - return true; - } - else{ - return false; - } - case 'lanname': - return this.node_info.server.version < 110000; - default: - return false; - } - }, - validate: function() - { - var err = {}, - errmsg, - seclabels = this.get('seclabels'); - - if (_.isUndefined(this.get('name')) || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') { - err['name'] = gettext('Name cannot be empty.'); - errmsg = err['name']; - } - - if (_.isUndefined(this.get('pronamespace')) || String(this.get('pronamespace')).replace(/^\s+|\s+$/g, '') == '') { - err['pronamespace'] = gettext('Schema cannot be empty.'); - errmsg = errmsg || err['pronamespace']; - } - - if (_.isUndefined(this.get('lanname')) || String(this.get('lanname')).replace(/^\s+|\s+$/g, '') == '') { - err['lanname'] = gettext('Language cannot be empty.'); - errmsg = errmsg || err['lanname']; - } - - if (String(this.get('lanname')) == 'c') { - if (_.isUndefined(this.get('probin')) || String(this.get('probin')) - .replace(/^\s+|\s+$/g, '') == '') { - err['probin'] = gettext('Object File cannot be empty.'); - errmsg = errmsg || err['probin']; - } - - if (_.isUndefined(this.get('prosrc_c')) || String(this.get('prosrc_c')).replace(/^\s+|\s+$/g, '') == '') { - err['prosrc_c'] = gettext('Link Symbol cannot be empty.'); - errmsg = errmsg || err['prosrc_c']; - } - } - else { - if (_.isUndefined(this.get('prosrc')) || String(this.get('prosrc')).replace(/^\s+|\s+$/g, '') == '') { - err['prosrc'] = gettext('Code cannot be empty.'); - errmsg = errmsg || err['prosrc']; - } - } - - if (seclabels) { - var secLabelsErr; - for (var i = 0; i < seclabels.models.length && !secLabelsErr; i++) { - secLabelsErr = (seclabels.models[i]).validate.apply(seclabels.models[i]); - if (secLabelsErr) { - err['seclabels'] = secLabelsErr; - errmsg = errmsg || secLabelsErr; - } - } - } - - this.errorModel.clear().set(err); - - return null; - }, - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js index ec0b9f2c5..1eed8e8bf 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/functions/static/js/trigger_function.js @@ -107,151 +107,6 @@ define('pgadmin.node.trigger_function', [ } ); }, - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - if (isNew) { - // Set Selected Schema - var schema_id = args.node_info.schema._id; - this.set({'pronamespace': schema_id}, {silent: true}); - - // Set Current User - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - this.set({'funcowner': userInfo.name}, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - defaults: { - name: undefined, - oid: undefined, - funcowner: undefined, - description: undefined, - }, - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - disabled: 'isDisabled', readonly: 'isReadonly', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text' , mode: ['properties'], - },{ - id: 'funcowner', label: gettext('Owner'), cell: 'string', - control: Backform.NodeListByNameControl, node: 'role', type: - 'text', disabled: 'isDisabled', readonly: 'isReadonly', - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', disabled: 'isDisabled', readonly: 'isReadonly', - }], - validate: function(keys) - { - var err = {}, - errmsg, - seclabels = this.get('seclabels'); - - // Nothing to validate - if(keys && keys.length == 0) { - this.errorModel.clear(); - return null; - } - - if (_.isUndefined(this.get('name')) || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') { - err['name'] = gettext('Name cannot be empty.'); - errmsg = err['name']; - } - - if (_.isUndefined(this.get('funcowner')) || String(this.get('funcowner')).replace(/^\s+|\s+$/g, '') == '') { - err['funcowner'] = gettext('Owner cannot be empty.'); - errmsg = errmsg || err['funcowner']; - } - - if (_.isUndefined(this.get('pronamespace')) || String(this.get('pronamespace')).replace(/^\s+|\s+$/g, '') == '') { - err['pronamespace'] = gettext('Schema cannot be empty.'); - errmsg = errmsg || err['pronamespace']; - } - - if (_.isUndefined(this.get('prorettypename')) || String(this.get('prorettypename')).replace(/^\s+|\s+$/g, '') == '') { - err['prorettypename'] = gettext('Return type cannot be empty.'); - errmsg = errmsg || err['prorettypename']; - } - - if (_.isUndefined(this.get('lanname')) || String(this.get('lanname')).replace(/^\s+|\s+$/g, '') == '') { - err['lanname'] = gettext('Language cannot be empty.'); - errmsg = errmsg || err['lanname']; - } - - if (String(this.get('lanname')) == 'c') { - if (_.isUndefined(this.get('probin')) || String(this.get('probin')) - .replace(/^\s+|\s+$/g, '') == '') { - err['probin'] = gettext('Object File cannot be empty.'); - errmsg = errmsg || err['probin']; - } - - if (_.isUndefined(this.get('prosrc_c')) || String(this.get('prosrc_c')).replace(/^\s+|\s+$/g, '') == '') { - err['prosrc_c'] = gettext('Link Symbol cannot be empty.'); - errmsg = errmsg || err['prosrc_c']; - } - } - else { - if (_.isUndefined(this.get('prosrc')) || String(this.get('prosrc')).replace(/^\s+|\s+$/g, '') == '') { - err['prosrc'] = gettext('Code cannot be empty.'); - errmsg = errmsg || err['prosrc']; - } - } - - if (seclabels) { - var secLabelsErr; - for (var i = 0; i < seclabels.models.length && !secLabelsErr; i++) { - secLabelsErr = (seclabels.models[i]).validate.apply(seclabels.models[i]); - if (secLabelsErr) { - err['seclabels'] = secLabelsErr; - errmsg = errmsg || secLabelsErr; - } - } - } - - this.errorModel.clear().set(err); - - if (_.size(err)) { - this.trigger('on-status', {msg: errmsg}); - return errmsg; - } - - return null; - }, - isVisible: function() { - if (this.name == 'sysproc') { return false; } - return true; - }, - isReadonly: function(m) { - switch(this.name){ - case 'proargs': - case 'proargtypenames': - case 'prorettypename': - case 'proretset': - case 'proiswindow': - return !m.isNew(); - default: - return false; - } - }, - isDisabled: function(m) { - if(this.node_info && 'catalog' in this.node_info) { - return true; - } - if (this.name === 'prorows'){ - if(m.get('proretset') == true) { - return false; - } - return true; - } else { - return false; - } - }, - canVarAdd: function() { - return !(this.node_info && 'catalog' in this.node_info); - }, - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/static/js/operator.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/static/js/operator.js index 98fff6bab..3a2bb65a8 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/static/js/operator.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/operators/static/js/operator.js @@ -45,37 +45,6 @@ define('pgadmin.node.operator', [ this.initialized = true; }, - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - - // Default values! - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - var schemaInfo = args.node_info.schema; - - this.set({'owner': userInfo.name}, {silent: true}); - this.set({'schema': schemaInfo._label}, {silent: true}); - } - pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments); - }, - - schema: [{ - id: 'name', label: gettext('Operator'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - },{ - id: 'owner', label: gettext('Owner'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - control: 'node-list-by-name', - node: 'role', - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', mode: ['properties', 'create', 'edit'], - } - ], - }), getSchema: ()=>{ return new OperatorSchema(); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/edbvars/static/js/edbvar.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/edbvars/static/js/edbvar.js index a3c340407..d9ebb9d3d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/edbvars/static/js/edbvar.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/edbvars/static/js/edbvar.js @@ -48,16 +48,6 @@ define('pgadmin.node.edbvar', [ }, 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'], - }] - }), getSchema: () => { return new EDBVarSchema(); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/static/js/package.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/static/js/package.js index a2ce63fc3..003f379bd 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/static/js/package.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/static/js/package.js @@ -92,41 +92,6 @@ define('pgadmin.node.package', [ // by default we want to allow create menu return true; }, - // Define the model for package node. - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - initialize: function(attrs, args) { - if (_.size(attrs) === 0) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - var schemaInfo = args.node_info.schema; - - this.set({ - 'owner': userInfo.name, 'schema': schemaInfo._label, - }, {silent: true}); - } - pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments); - }, - // Define the schema for package node. - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - readonly: function(m) { - return !m.isNew(); - }, - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text', mode: ['properties'], - },{ - id: 'owner', label: gettext('Owner'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - readonly: true, editable: false, visible: function(m) { - return !m.isNew(); - }, - },{ - id: 'description', label: gettext('Comment'), type: 'multiline', - mode: ['properties', 'create', 'edit'], - }] - }), getSchema: (treeNodeInfo, itemNodeData) => { var nodeObj = pgBrowser.Nodes['package']; return new PackageSchema( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/static/js/sequence.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/static/js/sequence.js index 6c358fd58..0e336682a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/static/js/sequence.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/static/js/sequence.js @@ -106,41 +106,6 @@ define('pgadmin.node.sequence', [ } ); }, - - // Define the model for sequence node. - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - - // Default values! - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - var schemaInfo = args.node_info.schema; - - this.set({'seqowner': userInfo.name}, {silent: true}); - this.set({'schema': schemaInfo._label}, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - - // Define the schema for sequence node. - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text', mode: ['properties'], - },{ - id: 'seqowner', label: gettext('Owner'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], node: 'role', - control: Backform.NodeListByNameControl, - },{ - id: 'comment', label: gettext('Comment'), type: 'multiline', - mode: ['properties', 'create', 'edit'], - }], - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/catalog.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/catalog.js index c41cbd5d2..42d182c48 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/catalog.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/catalog.js @@ -42,25 +42,6 @@ define('pgadmin.node.catalog', [ this.initialized = true; }, - model: pgBrowser.Node.Model.extend({ - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - - this.set({'namespaceowner': userInfo.name}, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', readonly: true, - },{ - id: 'oid', label: gettext('OID'), cell: 'string', mode: ['properties'], - type: 'text', - }] - }), getSchema: function(treeNodeInfo) { return new CatalogSchema( { diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js index ee384f629..4822c204d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/static/js/schema.js @@ -361,36 +361,6 @@ define('pgadmin.node.schema', [ can_create_schema: function(node) { return pgBrowser.Nodes['database'].is_conn_allow.call(this, node); }, - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - - this.set({'namespaceowner': userInfo.name}, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text', mode: ['properties'], - },{ - id: 'namespaceowner', label: gettext('Owner'), cell: 'string', - type: 'text', control: 'node-list-by-name', node: 'role', - select2: { allowClear: false }, - },{ - id: 'is_sys_obj', label: gettext('System schema?'), - cell: 'switch', type: 'switch', mode: ['properties'], - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline' - }] - }), getSchema: function(treeNodeInfo, itemNodeData) { var schemaObj = pgBrowser.Nodes['schema']; return new PGSchema( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/synonyms/static/js/synonym.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/synonyms/static/js/synonym.js index 8181fdc94..104324cb3 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/synonyms/static/js/synonym.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/synonyms/static/js/synonym.js @@ -100,54 +100,6 @@ define('pgadmin.node.synonym', [ } ); }, - - model: pgAdmin.Browser.Node.Model.extend({ - isNew: function() { - return !this.fetchFromServer; - }, - idAttribute: 'oid', - // Default values! - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - var schemaInfo = args.node_info.schema; - this.set({ - 'owner': userInfo.name, - 'synobjschema': schemaInfo._label, - 'schema': schemaInfo._label, - 'targettype': 'r', - }, {silent: true}); - } else { - this.fetchFromServer = true; - } - pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments); - - }, - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - disabled: 'inSchema', readonly: function(m) { return !m.isNew(); }, - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text', mode: ['properties'], - },{ - id: 'owner', label: gettext('Owner'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - readonly: true , control: 'node-list-by-name', - node: 'role', visible: false, - }], - - // We will disable everything if we are under catalog node - inSchema: function() { - if(this.node_info && 'catalog' in this.node_info) - { - return true; - } - return false; - }, - }), canCreate: function(itemData, item, data) { //If check is false then , we will allow create menu if (data && data.check == false) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.js index 5e12f159a..4df6c7ae7 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/columns/static/js/column.js @@ -98,36 +98,6 @@ define('pgadmin.node.column', [ getSchema: function(treeNodeInfo, itemNodeData) { return getNodeColumnSchema(treeNodeInfo, itemNodeData, pgBrowser); }, - model: pgBrowser.Node.Model.extend({ - idAttribute: 'attnum', - - defaults: { - name: undefined, - attnum: undefined, - description: undefined, - }, - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', disabled: 'inSchemaWithColumnCheck', - cellHeaderClasses:'width_percent_30', - editable: 'editable_check_for_table', - },{ - id: 'attnum', label: gettext('Position'), cell: 'string', - type: 'text', disabled: 'notInSchema', mode: ['properties'], - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', mode: ['properties', 'create', 'edit'], - disabled: 'notInSchema', - }], - // We will check if we are under schema node & in 'create' mode - notInSchema: function() { - if(this.node_info && 'catalog' in this.node_info) - { - return true; - } - return false; - }, - }), // Below function will enable right click menu for creating column canCreate: function(itemData, item, data) { // If check is false then , we will allow create menu diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js index 433828373..06b41026a 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/compound_triggers/static/js/compound_trigger.js @@ -189,16 +189,6 @@ define('pgadmin.node.compound_trigger', [ ); }, - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', - }, { - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', mode: ['properties', 'create', 'edit'], - }], - }), canCreate: function(itemData, item, data) { //If check is false then , we will allow create menu if (data && data.check == false) diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/static/js/constraints.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/static/js/constraints.js index d135deae5..df5f0e4cb 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/static/js/constraints.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/static/js/constraints.js @@ -43,24 +43,6 @@ define('pgadmin.node.constraints', [ pgBrowser.add_menus([]); }, - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - defaults: { - name: undefined, - oid: undefined, - comment: undefined, - }, - schema: [{ - id: 'name', label: gettext('Name'), type: 'text', - mode: ['properties', 'create', 'edit'], - },{ - id: 'oid', label: gettext('Oid'), cell: 'string', - type: 'text' , mode: ['properties'], - },{ - id: 'comment', label: gettext('Comment'), cell: 'string', - type: 'multiline', mode: ['properties', 'create', 'edit'], - }], - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js index 3fb8a6c17..cb1749c08 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/static/js/index.js @@ -92,29 +92,6 @@ define('pgadmin.node.index', [ }, canDrop: SchemaChildTreeNode.isTreeItemOfChildOfSchema, canDropCascade: SchemaChildTreeNode.isTreeItemOfChildOfSchema, - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - - defaults: { - name: undefined, - oid: undefined, - nspname: undefined, - tabname: undefined, - spcname: undefined, - amname: 'btree', - }, - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', disabled: 'inSchema', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'int', readonly: true, mode: ['properties'], - }, { - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', mode: ['properties', 'create', 'edit'], - disabled: 'inSchema', - }], - }), // Below function will enable right click menu for creating column canCreate: function(itemData, item, data) { // If check is false then , we will allow create menu diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js index 7b8b144b9..b360c6b8d 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/partitions/static/js/partition.js @@ -305,49 +305,6 @@ function( getSchema: function(treeNodeInfo, itemNodeData) { return getNodePartitionTableSchema(treeNodeInfo, itemNodeData, pgBrowser); }, - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - defaults: { - name: undefined, - oid: undefined, - description: undefined, - is_partitioned: false, - partition_value: undefined, - }, - // Default values! - initialize: function(attrs, args) { - if (_.size(attrs) === 0) { - var userInfo = pgBrowser.serverInfo[ - args.node_info.server._id - ].user, - schemaInfo = args.node_info.schema; - - this.set({ - 'relowner': userInfo.name, 'schema': schemaInfo._label, - }, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - - }, - schema: [{ - id: 'name', label: gettext('Name'), type: 'text', - mode: ['properties', 'create', 'edit'], - },{ - id: 'oid', label: gettext('OID'), type: 'text', mode: ['properties'], - },{ - id: 'schema', label: gettext('Schema'), type: 'text', node: 'schema', - mode: ['create', 'edit', 'properties'], - },{ - id: 'is_partitioned', label:gettext('Partitioned table?'), cell: 'switch', - type: 'switch', mode: ['properties', 'create', 'edit'], - },{ - id: 'partition_value', label:gettext('Partition Scheme'), - type: 'text', visible: false, - },{ - id: 'description', label: gettext('Comment'), type: 'multiline', - mode: ['properties', 'create', 'edit'], - }], - }), canCreate: SchemaChildTreeNode.isTreeItemOfChildOfSchema, // Check to whether table has disable trigger(s) canCreate_with_trigger_enable: function(itemData, item, data) { diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/row_security_policies/static/js/row_security_policy.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/row_security_policies/static/js/row_security_policy.js index acc285e99..d1908a6eb 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/row_security_policies/static/js/row_security_policy.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/row_security_policies/static/js/row_security_policy.js @@ -88,64 +88,6 @@ define('pgadmin.node.row_security_policy', [ } ); }, - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - defaults: { - name: undefined, - }, - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', readonly: true, cellHeaderClasses: 'width_percent_50', - mode: ['properties'] - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - editable: false, type: 'text', mode: ['properties'], - }], - validate: function(keys) { - var msg; - this.errorModel.clear(); - // If nothing to validate - if (keys && keys.length == 0) { - return null; - } - - if(_.isUndefined(this.get('name')) - || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Name cannot be empty.'); - this.errorModel.set('name', msg); - return msg; - } - if (!this.isNew() && !_.isNull(this.get('using_orig')) && this.get('using_orig') != '' && String(this.get('using')).replace(/^\s+|\s+$/g, '') == ''){ - msg = gettext('"USING" can not be empty once the value is set'); - this.errorModel.set('using', msg); - return msg; - } - if (!this.isNew() && !_.isNull(this.get('withcheck_orig')) && this.get('withcheck_orig') != '' && String(this.get('withcheck')).replace(/^\s+|\s+$/g, '') == ''){ - msg = gettext('"Withcheck" can not be empty once the value is set'); - this.errorModel.set('withcheck', msg); - return msg; - } - return null; - }, - disableWithCheck: function(m){ - var event = m.get('event'); - if ((event == 'SELECT') || (event == 'DELETE')){ - m.set('withcheck', ''); - return true; - } - return false; - }, - - disableUsing: function(m){ - var event = m.get('event'); - - if (event == 'INSERT'){ - return true; - } - return false; - }, - - }), canCreate: function(itemData, item) { var treeData = pgBrowser.tree.getTreeNodeHierarchy(item), diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/js/rule.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/js/rule.js index cde25009b..73ebd4183 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/js/rule.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/rules/static/js/rule.js @@ -207,54 +207,6 @@ define('pgadmin.node.rule', [ } ); }, - /** - Define model for the rule node and specify the node - properties of the model in schema. - */ - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - schema: [{ - id: 'name', label: gettext('Name'), - type: 'text', disabled: function(m) { - // disable name field it it is system rule - if (m && m.get('name') == '_RETURN') { - return true; - } - if (m.isNew && m.isNew() || m.node_info && m.node_info.server.version >= 90400) { - return false; - } - return true; - }, - }, - { - id: 'oid', label: gettext('OID'), - type: 'text', mode: ['properties'], - }, - { - id: 'comment', label: gettext('Comment'), cell: 'string', type: 'multiline', - }, - ], - validate: function() { - - // Triggers specific error messages for fields - var err = {}, - errmsg, - field_name = this.get('name'); - if (_.isUndefined(field_name) || _.isNull(field_name) || - String(field_name).replace(/^\s+|\s+$/g, '') === '') - { - err['name'] = gettext('Please specify name.'); - errmsg = err['name']; - this.errorModel.set('name', errmsg); - return errmsg; - } - else - { - this.errorModel.unset('name'); - } - return null; - }, - }), // Show or hide create rule menu option on parent node canCreate: function(itemData, item, data) { diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js index 1e4ecba89..c60ecbc5c 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/static/js/trigger.js @@ -187,468 +187,6 @@ define('pgadmin.node.trigger', [ }, ); }, - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - defaults: { - name: undefined, - is_row_trigger: true, - fires: 'BEFORE', - }, - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', disabled: 'inSchema', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'int', mode: ['properties'], - },{ - id: 'is_enable_trigger', label: gettext('Trigger enabled?'), - mode: ['edit', 'properties'], group: gettext('Definition'), - disabled: function() { - if(this.node_info && ('catalog' in this.node_info || 'view' in this.node_info)) { - return true; - } - return false; - }, - options: [ - {label: gettext('Enable'), value: 'O'}, - {label: gettext('Enable Replica'), value: 'R'}, - {label: gettext('Enable Always'), value: 'A'}, - {label: gettext('Disable'), value: 'D'}, - ], - control: 'select2', select2: { allowClear: false, width: '100%' }, - },{ - id: 'is_row_trigger', label: gettext('Row trigger?'), - type: 'switch', group: gettext('Definition'), - mode: ['create','edit', 'properties'], - deps: ['is_constraint_trigger'], - disabled: function(m) { - // Disabled if table is a partitioned table. - if (!m.isNew()) - return true; - - if (_.has(m, 'node_info') && _.has(m.node_info, 'table') && - _.has(m.node_info.table, 'is_partitioned') && - m.node_info.table.is_partitioned && m.node_info.server.version < 110000 - ) - { - setTimeout(function(){ - m.set('is_row_trigger', false); - },10); - - return true; - } - - // If constraint trigger is set to True then row trigger will - // automatically set to True and becomes disable - var is_constraint_trigger = m.get('is_constraint_trigger'); - if(!m.inSchemaWithModelCheck.apply(this, [m])) { - if(!_.isUndefined(is_constraint_trigger) && - is_constraint_trigger === true) { - // change it's model value - setTimeout(function() { m.set('is_row_trigger', true); }, 10); - return true; - } else { - return false; - } - } else { - // Check if it is row trigger then enabled it. - var is_row_trigger = m.get('is_row_trigger'); - if (!_.isUndefined(is_row_trigger) && m.node_info['server']['server_type'] == 'ppas') { - return false; - } - // Disable it - return true; - } - }, - },{ - id: 'is_constraint_trigger', label: gettext('Constraint trigger?'), - type: 'switch', - mode: ['create','edit', 'properties'], - group: gettext('Definition'), - deps: ['tfunction'], - disabled: function(m) { - // Disabled if table is a partitioned table. - var tfunction = m.get('tfunction'); - if ((_.has(m, 'node_info') && _.has(m.node_info, 'table') && - _.has(m.node_info.table, 'is_partitioned') && - m.node_info.table.is_partitioned) || - _.indexOf(Object.keys(m.node_info), 'view') != -1 || - (m.node_info.server.server_type === 'ppas' && - !_.isUndefined(tfunction) && - tfunction === 'Inline EDB-SPL')) { - setTimeout(function(){ - m.set('is_constraint_trigger', false); - },10); - - return true; - } - - return m.inSchemaWithModelCheck.apply(this, [m]); - }, - },{ - id: 'tgdeferrable', label: gettext('Deferrable?'), - type: 'switch', group: gettext('Definition'), - mode: ['create','edit', 'properties'], - deps: ['is_constraint_trigger'], - disabled: function(m) { - // If constraint trigger is set to True then only enable it - var is_constraint_trigger = m.get('is_constraint_trigger'); - if(!m.inSchemaWithModelCheck.apply(this, [m])) { - if(!_.isUndefined(is_constraint_trigger) && - is_constraint_trigger === true) { - return false; - } else { - // If value is already set then reset it to false - if(m.get('tgdeferrable')) { - setTimeout(function() { m.set('tgdeferrable', false); }, 10); - } - return true; - } - } else { - // Disable it - return true; - } - }, - },{ - id: 'tginitdeferred', label: gettext('Deferred?'), - type: 'switch', group: gettext('Definition'), - mode: ['create','edit', 'properties'], - deps: ['tgdeferrable', 'is_constraint_trigger'], - disabled: function(m) { - // If Deferrable is set to True then only enable it - var tgdeferrable = m.get('tgdeferrable'); - if(!m.inSchemaWithModelCheck.apply(this, [m])) { - if(!_.isUndefined(tgdeferrable) && - tgdeferrable) { - return false; - } else { - // If value is already set then reset it to false - if(m.get('tginitdeferred')) { - setTimeout(function() { m.set('tginitdeferred', false); }, 10); - } - // If constraint trigger is set then do not disable - return m.get('is_constraint_trigger') ? false : true; - } - } else { - // Disable it - return true; - } - }, - },{ - id: 'tfunction', label: gettext('Trigger function'), - type: 'text', disabled: 'inSchemaWithModelCheck', - mode: ['create','edit', 'properties'], group: gettext('Definition'), - control: 'node-ajax-options', url: 'get_triggerfunctions', url_jump_after_node: 'schema', - cache_node: 'trigger_function', - },{ - id: 'tgargs', label: gettext('Arguments'), cell: 'string', - group: gettext('Definition'), - type: 'text',mode: ['create','edit', 'properties'], deps: ['tfunction'], - disabled: function(m) { - // We will disable it when EDB PPAS and trigger function is - // set to Inline EDB-SPL - var tfunction = m.get('tfunction'), - server_type = m.node_info['server']['server_type']; - if(!m.inSchemaWithModelCheck.apply(this, [m])) { - if(server_type === 'ppas' && - !_.isUndefined(tfunction) && - tfunction === 'Inline EDB-SPL') { - // Disable and clear its value - m.set('tgargs', undefined); - return true; - } else { - return false; - } - } else { - // Disable it - return true; - } - }, - },{ - id: 'fires', label: gettext('Fires'), deps: ['is_constraint_trigger'], - mode: ['create','edit', 'properties'], group: gettext('Events'), - options: function(control) { - var table_options = [ - {label: 'BEFORE', value: 'BEFORE'}, - {label: 'AFTER', value: 'AFTER'}], - view_options = [ - {label: 'BEFORE', value: 'BEFORE'}, - {label: 'AFTER', value: 'AFTER'}, - {label: 'INSTEAD OF', value: 'INSTEAD OF'}]; - // If we are under table then show table specific options - if(_.indexOf(Object.keys(control.model.node_info), 'table') != -1) { - return table_options; - } else { - return view_options; - } - }, - control: 'select2', select2: { allowClear: false, width: '100%' }, - disabled: function(m) { - if (!m.isNew()) - return true; - // If contraint trigger is set to True then only enable it - var is_constraint_trigger = m.get('is_constraint_trigger'); - if(!m.inSchemaWithModelCheck.apply(this, [m])) { - if(!_.isUndefined(is_constraint_trigger) && - is_constraint_trigger === true) { - setTimeout(function() { m.set('fires', 'AFTER'); }, 10); - return true; - } else { - return false; - } - } else { - // Check if it is row trigger then enabled it. - var fires_ = m.get('fires'); - if (!_.isUndefined(fires_) && m.node_info['server']['server_type'] == 'ppas') { - return false; - } - // Disable it - return true; - } - }, - },{ - type: 'nested', control: 'fieldset', mode: ['create','edit', 'properties'], - label: gettext('Events'), group: gettext('Events'), contentClass: 'row', - schema:[{ - id: 'evnt_insert', label: gettext('INSERT'), - type: 'switch', mode: ['create','edit', 'properties'], - group: gettext('Events'), - extraToggleClasses: 'pg-el-sm-6', - controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12', - controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12', - disabled: function(m) { - var evn_insert = m.get('evnt_insert'); - if (!_.isUndefined(evn_insert) && m.node_info['server']['server_type'] == 'ppas' && m.isNew()) - return false; - return m.inSchemaWithModelCheck.apply(this, [m]); - }, - },{ - id: 'evnt_update', label: gettext('UPDATE'), - type: 'switch', mode: ['create','edit', 'properties'], - group: gettext('Events'), - extraToggleClasses: 'pg-el-sm-6', - controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12', - controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12', - disabled: function(m) { - var evn_update = m.get('evnt_update'); - if (!_.isUndefined(evn_update) && m.node_info['server']['server_type'] == 'ppas' && m.isNew()) - return false; - return m.inSchemaWithModelCheck.apply(this, [m]); - }, - },{ - id: 'evnt_delete', label: gettext('DELETE'), - type: 'switch', mode: ['create','edit', 'properties'], - group: gettext('Events'), - extraToggleClasses: 'pg-el-sm-6', - controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12', - controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12', - disabled: function(m) { - var evn_delete = m.get('evnt_delete'); - if (!_.isUndefined(evn_delete) && m.node_info['server']['server_type'] == 'ppas' && m.isNew()) - return false; - return m.inSchemaWithModelCheck.apply(this, [m]); - }, - },{ - id: 'evnt_truncate', label: gettext('TRUNCATE'), - type: 'switch', group: gettext('Events'),deps: ['is_row_trigger', 'is_constraint_trigger'], - extraToggleClasses: 'pg-el-sm-6', - controlLabelClassName: 'control-label pg-el-sm-5 pg-el-12', - controlsClassName: 'pgadmin-controls pg-el-sm-7 pg-el-12', - disabled: function(m) { - var is_constraint_trigger = m.get('is_constraint_trigger'), - is_row_trigger = m.get('is_row_trigger'), - server_type = m.node_info['server']['server_type']; - if (is_row_trigger == true){ - setTimeout(function(){ - m.set('evnt_truncate', false); - },10); - return true; - } - - if (server_type === 'ppas' && - !_.isUndefined(is_constraint_trigger) && - !_.isUndefined(is_row_trigger) && - is_constraint_trigger === false && m.isNew()) - return false; - return m.inSchemaWithModelCheck.apply(this, [m]); - }, - }], - },{ - id: 'whenclause', label: gettext('When'), - type: 'text', disabled: 'inSchemaWithModelCheck', - mode: ['create', 'edit', 'properties'], - control: 'sql-field', visible: true, group: gettext('Events'), - },{ - id: 'columns', label: gettext('Columns'), url: 'nodes', - control: 'node-list-by-name', cache_node: 'column', type: 'array', - select2: {'multiple': true}, - deps: ['evnt_update'], node: 'column', group: gettext('Events'), - disabled: function(m) { - if(this.node_info && 'catalog' in this.node_info) { - return true; - } - //Disable in edit mode - if (!m.isNew()) { - return true; - } - // Enable column only if update event is set true - var isUpdate = m.get('evnt_update'); - if(!_.isUndefined(isUpdate) && isUpdate) { - return false; - } - return true; - }, - },{ - id: 'tgoldtable', label: gettext('Old table'), - type: 'text', group: gettext('Transition'), - cell: 'string', mode: ['create', 'edit', 'properties'], - deps: ['fires', 'is_constraint_trigger', 'evnt_insert', 'evnt_update', 'evnt_delete', 'columns'], - disabled: 'disableTransition', - },{ - id: 'tgnewtable', label: gettext('New table'), - type: 'text', group: gettext('Transition'), - cell: 'string', mode: ['create', 'edit', 'properties'], - deps: ['fires', 'is_constraint_trigger', 'evnt_insert', 'evnt_update', 'evnt_delete', 'columns'], - disabled: 'disableTransition', - },{ - id: 'prosrc', label: gettext('Code'), group: gettext('Code'), - type: 'text', mode: ['create', 'edit'], deps: ['tfunction'], - tabPanelCodeClass: 'sql-code-control', - control: Backform.SqlCodeControl, - visible: true, - disabled: function(m) { - // We will enable it only when EDB PPAS and trigger function is - // set to Inline EDB-SPL - var tfunction = m.get('tfunction'), - server_type = m.node_info['server']['server_type']; - - return (server_type !== 'ppas' || - _.isUndefined(tfunction) || - tfunction !== 'Inline EDB-SPL'); - }, - },{ - id: 'is_sys_trigger', label: gettext('System trigger?'), cell: 'string', - type: 'switch', disabled: 'inSchemaWithModelCheck', mode: ['properties'], - },{ - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', mode: ['properties', 'create', 'edit'], - disabled: 'inSchema', - }], - validate: function(keys) { - var msg; - this.errorModel.clear(); - - // If nothing to validate - if (keys && keys.length == 0) { - return null; - } - - if(_.isUndefined(this.get('name')) - || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Name cannot be empty.'); - this.errorModel.set('name', msg); - return msg; - } - if(_.isUndefined(this.get('tfunction')) - || String(this.get('tfunction')).replace(/^\s+|\s+$/g, '') == '') { - msg = gettext('Trigger function cannot be empty.'); - this.errorModel.set('tfunction', msg); - return msg; - } - - if(!this.get('evnt_truncate') && !this.get('evnt_delete') && - !this.get('evnt_update') && !this.get('evnt_insert')) { - msg = gettext('Specify at least one event.'); - this.errorModel.set('evnt_truncate', ' '); - this.errorModel.set('evnt_delete', ' '); - this.errorModel.set('evnt_update', ' '); - this.errorModel.set('evnt_insert', msg); - return msg; - } - - if(!_.isUndefined(this.get('tfunction')) && - this.get('tfunction') === 'Inline EDB-SPL' && - (_.isUndefined(this.get('prosrc')) - || String(this.get('prosrc')).replace(/^\s+|\s+$/g, '') == '')) - { - msg = gettext('Trigger code cannot be empty.'); - this.errorModel.set('prosrc', msg); - return msg; - } - return null; - }, - // We will check if we are under schema node & in 'create' mode - inSchema: function() { - if(this.node_info && 'catalog' in this.node_info) { - return true; - } - return false; - }, - // We will check if we are under schema node & in 'create' mode - inSchemaWithModelCheck: function(m) { - if(this.node_info && 'schema' in this.node_info) { - // We will disable control if it's in 'edit' mode - return !m.isNew(); - } - return true; - }, - // Checks weather to enable/disable control - inSchemaWithColumnCheck: function(m) { - if(this.node_info && 'schema' in this.node_info) { - // We will disable control if it's system columns - // ie: it's position is less then 1 - if (m.isNew()) { - return false; - } else { - // if we are in edit mode - return (_.isUndefined(m.get('attnum')) || m.get('attnum') < 1 ); - } - } - return true; - }, - // Disable/Enable Transition tables - disableTransition: function(m) { - if (!m.isNew()) - return true; - var flag = false, - evnt = null, - name = this.name, - evnt_count = 0; - - // Disable transition tables for view trigger and PG version < 100000 - if(_.indexOf(Object.keys(m.node_info), 'table') == -1 || - m.node_info.server.version < 100000) return true; - - if (name == 'tgoldtable') evnt = 'evnt_delete'; - else if (name == 'tgnewtable') evnt = 'evnt_insert'; - - if(m.get('evnt_insert')) evnt_count++; - if(m.get('evnt_update')) evnt_count++; - if(m.get('evnt_delete')) evnt_count++; - - - // Disable transition tables if - // - It is a constraint trigger - // - Fires other than AFTER - // - More than one events enabled - // - Update event with the column list - - // Disable Old transition table if both UPDATE and DELETE events are disabled - // Disable New transition table if both UPDATE and INSERT events are disabled - if(!m.get('is_constraint_trigger') && m.get('fires') == 'AFTER' && - (m.get('evnt_update') || m.get(evnt)) && evnt_count == 1) { - flag = (m.get('evnt_update') && (_.size(m.get('columns')) >= 1 && m.get('columns')[0] != '')); - } - - flag && setTimeout(function() { - if(m.get(name)) { - m.set(name, null); - } - },10); - - return flag; - }, - }), canCreate: SchemaChildTreeNode.isTreeItemOfChildOfSchema, // Check to whether trigger is disable ? canCreate_with_trigger_enable: function(itemData, item, data) { diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.js index f0ec287f0..56ef198e1 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/static/js/type.js @@ -74,48 +74,6 @@ define('pgadmin.node.type', [ }, ext_funcs: undefined, - /* Few fields are kept since the properties tab for collection is not - yet migrated to new react schema. Once the properties for collection - is removed, remove this model */ - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - defaults: { - name: undefined, - is_sys_type: false, - typtype: undefined, - }, - - // Default values! - initialize: function(attrs, args) { - if (_.size(attrs) === 0) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user, - schemaInfo = args.node_info.schema; - - this.set({ - 'typeowner': userInfo.name, 'schema': schemaInfo._label, - }, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', mode: ['properties', 'create', 'edit'], - disabled: 'schemaCheck', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text' , mode: ['properties'], - },{ - id: 'typeowner', label: gettext('Owner'), cell: 'string', - control: 'node-list-by-name', - type: 'text', mode: ['properties', 'create', 'edit'], node: 'role', - disabled: 'inSchema', select2: {allowClear: false}, - }, { - id: 'description', label: gettext('Comment'), cell: 'string', - type: 'multiline', mode: ['properties', 'create', 'edit'], - disabled: 'inSchema', - }] - }), getSchema: (treeNodeInfo, itemNodeData) => { let nodeObj = pgAdmin.Browser.Nodes['type']; return new TypeSchema( diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js index 393707c9b..cbfd68667 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/mview.js @@ -146,93 +146,6 @@ define('pgadmin.node.mview', [ } ); }, - /** - Define model for the view node and specify the - properties of the model in schema. - */ - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - initialize: function(attrs, args) { - if (_.size(attrs) === 0) { - // Set Selected Schema and Current User - var schemaLabel = args.node_info.schema._label || 'public', - userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - this.set({ - 'schema': schemaLabel, 'owner': userInfo.name, - }, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - defaults: { - spcname: undefined, - }, - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', disabled: 'inSchema', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text', mode: ['properties'], - },{ - id: 'owner', label: gettext('Owner'), cell: 'string', - control: 'node-list-by-name', select2: { allowClear: false }, - node: 'role', disabled: 'inSchema', - },{ - id: 'comment', label: gettext('Comment'), cell: 'string', - type: 'multiline', - }], - 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); - }, - validate: function(keys) { - - // Triggers specific error messages for fields - var err = {}, - errmsg, - field_name = this.get('name'), - field_def = this.get('definition'); - - if(_.indexOf(keys, 'autovacuum_custom')) - if (_.indexOf(keys, 'autovacuum_enabled') != -1 || - _.indexOf(keys, 'toast_autovacuum_enabled') != -1 ) - return null; - - if (_.isUndefined(field_name) || _.isNull(field_name) || - String(field_name).replace(/^\s+|\s+$/g, '') == '') { - err['name'] = gettext('Please specify name.'); - errmsg = err['name']; - this.errorModel.set('name', errmsg); - return errmsg; - }else{ - this.errorModel.unset('name'); - } - if (_.isUndefined(field_def) || _.isNull(field_def) || - String(field_def).replace(/^\s+|\s+$/g, '') == '') { - err['definition'] = gettext('Please enter view definition.'); - errmsg = err['definition']; - this.errorModel.set('definition', errmsg); - return errmsg; - }else{ - this.errorModel.unset('definition'); - } - return null; - }, - // We will disable everything if we are under catalog node - inSchema: function() { - if(this.node_info && 'catalog' in this.node_info) - { - return true; - } - return false; - }, - - }), refresh_mview: function(args) { var input = args || {}, diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.js index b98ea6c6c..0ba952954 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/static/js/view.js @@ -108,163 +108,6 @@ define('pgadmin.node.view', [ } ); }, - /** - Define model for the view node and specify the - properties of the model in schema. - */ - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - initialize: function(attrs, args) { - if (_.size(attrs) === 0) { - // Set Selected Schema and, Current User - var schemaLabel = args.node_info.schema._label || 'public', - userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - this.set({ - 'schema': schemaLabel, 'owner': userInfo.name, - }, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - schema: [{ - id: 'name', label: gettext('Name'), cell: 'string', - type: 'text', disabled: 'notInSchema', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', - type: 'text', mode: ['properties'], - },{ - id: 'owner', label: gettext('Owner'), cell: 'string', control: 'node-list-by-name', - node: 'role', disabled: 'notInSchema', select2: { allowClear: false }, - },{ - id: 'schema', label: gettext('Schema'), cell: 'string', first_empty: false, - control: 'node-list-by-name', type: 'text', cache_level: 'database', - node: 'schema', disabled: 'notInSchema', mode: ['create', 'edit'], - select2: { allowClear: false }, cache_node: 'database', - },{ - id: 'system_view', label: gettext('System view?'), cell: 'string', - type: 'switch', mode: ['properties'], - },{ - id: 'acl', label: gettext('Privileges'), - mode: ['properties'], type: 'text', group: gettext('Security'), - },{ - id: 'comment', label: gettext('Comment'), cell: 'string', - type: 'multiline', disabled: 'notInSchema', - },{ - id: 'security_barrier', label: gettext('Security barrier?'), - type: 'switch', min_version: '90200', group: gettext('Definition'), - disabled: 'notInSchema', - },{ - id: 'check_option', label: gettext('Check options'), - control: 'select2', group: gettext('Definition'), type: 'text', - min_version: '90400', mode:['properties', 'create', 'edit'], - select2: { - // Set select2 option width to 100% - allowClear: false, - }, disabled: 'notInSchema', - options:[{ - label: gettext('No'), value: 'no', - },{ - label: gettext('Local'), value: 'local', - },{ - label: gettext('Cascaded'), value: 'cascaded', - }], - },{ - id: 'definition', label: gettext('Code'), cell: 'string', - type: 'text', mode: ['create', 'edit'], group: gettext('Code'), - tabPanelCodeClass: 'sql-code-control', - disabled: 'notInSchema', - control: Backform.SqlCodeControl.extend({ - onChange: function() { - Backform.SqlCodeControl.prototype.onChange.apply(this, arguments); - - if (!this.model || !( - this.model.changed && - this.model.node_info.server.server_type == 'pg' && - // No need to check this when creating a view - this.model.get('oid') !== undefined - ) || !( - this.model.origSessAttrs && - this.model.changed.definition != this.model.origSessAttrs.definition - )) { - this.model.warn_text = undefined; - return; - } - - let old_def = this.model.origSessAttrs.definition && - this.model.origSessAttrs.definition.replace( - /\s/gi, '' - ).split('FROM'), - new_def = []; - - if (this.model.changed.definition !== undefined) { - new_def = this.model.changed.definition.replace( - /\s/gi, '' - ).split('FROM'); - } - - if ((old_def.length != new_def.length) || ( - old_def.length > 1 && ( - old_def[0] != new_def[0] - ) - )) { - this.model.warn_text = gettext( - 'Changing the columns in a view requires dropping and re-creating the view. This may fail if other objects are dependent upon this view, or may cause procedural functions to fail if they are not modified to take account of the changes.' - ) + '

' + gettext('Do you wish to continue?') + - ''; - } else { - this.model.warn_text = undefined; - } - }, - }), - }, pgBrowser.SecurityGroupSchema, { - // Add Privilege Control - id: 'datacl', label: gettext('Privileges'), type: 'collection', - model: pgBrowser.Node.PrivilegeRoleModel.extend({ - privileges: ['a', 'r', 'w', 'd', 'D', 'x', 't'], - }), uniqueCol : ['grantee'], editable: false, group: 'security', - mode: ['edit', 'create'], canAdd: true, canDelete: true, - control: 'unique-col-collection', disabled: 'notInSchema', - },{ - // Add Security Labels Control - id: 'seclabels', label: gettext('Security labels'), - model: pgBrowser.SecLabelModel, editable: false, type: 'collection', - canEdit: false, group: 'security', canDelete: true, - mode: ['edit', 'create'], canAdd: true, disabled: 'notInSchema', - control: 'unique-col-collection', uniqueCol : ['provider'], - }], - validate: function() { - // Triggers specific error messages for fields - var err = {}, - errmsg, - field_name = this.get('name'), - field_def = this.get('definition'); - if (_.isUndefined(field_name) || _.isNull(field_name) || - String(field_name).replace(/^\s+|\s+$/g, '') == '') { - err['name'] = gettext('Please specify name.'); - errmsg = err['name']; - this.errorModel.set('name', errmsg); - return errmsg; - }else{ - this.errorModel.unset('name'); - } - if (_.isUndefined(field_def) || _.isNull(field_def) || - String(field_def).replace(/^\s+|\s+$/g, '') == '') { - err['definition'] = gettext('Please enter view code.'); - errmsg = err['definition']; - this.errorModel.set('definition', errmsg); - return errmsg; - }else{ - this.errorModel.unset('definition'); - } - return null; - }, - // We will disable everything if we are under catalog node - notInSchema: function() { - if(this.node_info && 'catalog' in this.node_info) { - return true; - } - return false; - }, - }), }); } diff --git a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js index 344abcac5..a60fc26d9 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js +++ b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.js @@ -351,45 +351,6 @@ define('pgadmin.node.database', [ } ); }, - /* Few fields are kept since the properties tab for collection is not - yet migrated to new react schema. Once the properties for collection - is removed, remove this model */ - model: pgBrowser.Node.Model.extend({ - idAttribute: 'did', - defaults: { - name: undefined, - owner: undefined, - comment: undefined, - }, - - // Default values! - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - this.set({'datowner': userInfo.name}, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - - schema: [ - { - id: 'name', label: gettext('Database'), cell: 'string', - editable: false, type: 'text', - },{ - id: 'did', label: gettext('OID'), cell: 'string', mode: ['properties'], - editable: false, type: 'text', - },{ - id: 'datowner', label: gettext('Owner'), - editable: false, type: 'text', node: 'role', - control: Backform.NodeListByNameControl, select2: { allowClear: false }, - },{ - id: 'comments', label: gettext('Comment'), - editable: false, type: 'multiline', - }, - ], - }), }); pgBrowser.SecurityGroupSchema = { diff --git a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.ui.js b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.ui.js index 0715ea1b7..5b02716d3 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/static/js/database.ui.js +++ b/web/pgadmin/browser/server_groups/servers/databases/static/js/database.ui.js @@ -95,20 +95,20 @@ export default class DatabaseSchema extends BaseUISchema { return [ { id: 'name', label: gettext('Database'), cell: 'text', - editable: false, type: 'text', noEmpty: true, + editable: false, type: 'text', noEmpty: true, isCollectionProperty: true, },{ id: 'did', label: gettext('OID'), cell: 'text', mode: ['properties'], editable: false, type: 'text', },{ id: 'datowner', label: gettext('Owner'), editable: false, type: 'select', options: this.fieldOptions.role, - controlProps: { allowClear: false }, + controlProps: { allowClear: false }, isCollectionProperty: true, },{ id: 'is_sys_obj', label: gettext('System database?'), cell: 'switch', type: 'switch', mode: ['properties'], },{ id: 'comments', label: gettext('Comment'), - editable: false, type: 'multiline', + editable: false, type: 'multiline', isCollectionProperty: true, },{ id: 'encoding', label: gettext('Encoding'), editable: false, type: 'select', group: gettext('Definition'), diff --git a/web/pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription.js b/web/pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription.js index 1a145b4d6..f5f596188 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription.js +++ b/web/pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription.js @@ -14,8 +14,8 @@ import Notify from '../../../../../../../static/js/helpers/Notifier'; define('pgadmin.node.subscription', [ 'sources/gettext', 'sources/url_for', 'jquery', - 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.backform', 'pgadmin.browser.collection', -], function(gettext, url_for, $, pgAdmin, pgBrowser, Backform) { + 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.browser.collection', +], function(gettext, url_for, $, pgAdmin, pgBrowser) { // Extend the browser's collection class for subscriptions collection if (!pgBrowser.Nodes['coll-subscription']) { @@ -24,7 +24,7 @@ define('pgadmin.node.subscription', [ node: 'subscription', label: gettext('Subscriptions'), type: 'coll-subscription', - columns: ['name', 'subowner', 'pub', 'enabled'], + columns: ['name', 'subowner', 'proppub', 'enabled'], hasStatistics: true, }); } @@ -74,101 +74,6 @@ define('pgadmin.node.subscription', [ enable: 'canCreate', }]); }, - // Define the model for subscription node - model: pgBrowser.Node.Model.extend({ - idAttribute: 'oid', - defaults: { - name: undefined, - subowner: undefined, - pubtable: undefined, - connect_timeout: 10, - pub:[], - enabled:true, - create_slot: true, - copy_data:true, - connect:true, - copy_data_after_refresh:false, - sync:'off', - refresh_pub: false, - password: '', - sslmode: 'prefer', - sslcompression: false, - sslcert: '', - sslkey: '', - sslrootcert: '', - sslcrl: '', - host: '', - hostaddr: '', - port: 5432, - db: 'postgres', - }, - - // Default values! - initialize: function(attrs, args) { - var isNew = (_.size(attrs) === 0); - if (isNew) { - var userInfo = pgBrowser.serverInfo[args.node_info.server._id].user; - - this.set({'subowner': userInfo.name}, {silent: true}); - } - pgBrowser.Node.Model.prototype.initialize.apply(this, arguments); - }, - - // Define the schema for the subscription node - schema: [{ - id: 'name', label: gettext('Name'), type: 'text', - mode: ['properties', 'create', 'edit'], - visible: function() { - if(!_.isUndefined(this.node_info) && !_.isUndefined(this.node_info.server) - && !_.isUndefined(this.node_info.server.version) && - this.node_info.server.version >= 100000) { - return true; - } - return false; - }, - },{ - id: 'oid', label: gettext('OID'), cell: 'string', mode: ['properties'], - type: 'text', - }, - { - id: 'subowner', label: gettext('Owner'), type: 'text', - control: Backform.NodeListByNameControl, node: 'role', - mode: ['edit', 'properties', 'create'], select2: { allowClear: false}, - disabled: function(m){ - if(m.isNew()) - return true; - return false; - }, - }, - { - id: 'enabled', label: gettext('Enabled?'), - type: 'switch', mode: ['properties'], - group: gettext('With'), - readonly: 'isConnect', deps :['connect'], - helpMessage: gettext('Specifies whether the subscription should be actively replicating, or whether it should be just setup but not started yet.'), - }, - { - id: 'pub', label: gettext('Publication'), type: 'text', group: gettext('Connection'), - mode: ['properties'], - }, - ], - sessChanged: function() { - if (!this.isNew() && _.isUndefined(this.attributes['refresh_pub'])) - return false; - return pgBrowser.DataModel.prototype.sessChanged.apply(this); - }, - canCreate: function(itemData, item) { - var treeData = pgBrowser.tree.getTreeNodeHierarchy(item), - server = treeData['server']; - - // If server is less than 10 then do not allow 'create' menu - if (server && server.version < 100000) - return false; - - // by default we want to allow create menu - return true; - }, - }), getSchema: function(treeNodeInfo, itemNodeData){ return new SubscriptionSchema( { diff --git a/web/pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription.ui.js b/web/pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription.ui.js index bb6b418c6..771e3c03b 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription.ui.js +++ b/web/pgadmin/browser/server_groups/servers/databases/subscriptions/static/js/subscription.ui.js @@ -176,7 +176,7 @@ export default class SubscriptionSchema extends BaseUISchema{ mode: ['properties', 'edit', 'create'], }, { - id: 'pub', label: gettext('Publication'), type: 'text', group: gettext('Connection'), + id: 'proppub', label: gettext('Publication'), type: 'text', group: gettext('Connection'), mode: ['properties'], }, { diff --git a/web/pgadmin/browser/server_groups/servers/databases/subscriptions/templates/subscriptions/sql/default/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/subscriptions/templates/subscriptions/sql/default/properties.sql index f7a6baf3b..a416821da 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/subscriptions/templates/subscriptions/sql/default/properties.sql +++ b/web/pgadmin/browser/server_groups/servers/databases/subscriptions/templates/subscriptions/sql/default/properties.sql @@ -1,6 +1,7 @@ SELECT sub.oid as oid, subname as name, subpublications as pub, + subpublications as proppub, sub.subsynccommit as sync, pga.rolname as subowner, subslotname as slot_name, diff --git a/web/pgadmin/browser/server_groups/servers/roles/static/js/role.js b/web/pgadmin/browser/server_groups/servers/roles/static/js/role.js index 1147e352c..0b037813c 100644 --- a/web/pgadmin/browser/server_groups/servers/roles/static/js/role.js +++ b/web/pgadmin/browser/server_groups/servers/roles/static/js/role.js @@ -582,152 +582,6 @@ define('pgadmin.node.role', [ }, ); }, - model: pgAdmin.Browser.Node.Model.extend({ - idAttribute: 'oid', - defaults: { - oid: null, - rolname: undefined, - rolcanlogin: false, - rolconnlimit: -1, - rolsuper: false, - rolcreaterole: false, - rolcreatedb: false, - rolinherit: true, - rolcatupdate: false, - rolreplication: false, - rolvaliduntil: null, - }, - schema: [{ - id: 'rolname', label: gettext('Name'), type: 'text', - readonly: 'readonly', - },{ - id: 'oid', label: gettext('OID'), cell: 'string', mode: ['properties'], - editable: false, type: 'text', visible: true, - },{ - id: 'rolvaliduntil', readonly: 'readonly', type: 'text', - group: gettext('Definition'), label: gettext('Account expires'), - mode: ['properties', 'edit', 'create'], control: 'datetimepicker', - deps: ['rolcanlogin'], - placeholder: gettext('No Expiry'), - helpMessage: gettext('Please note that if you leave this field blank, then password will never expire.'), - setMinDate: false, - },{ - id: 'rolconnlimit', type: 'int', group: gettext('Definition'), - label: gettext('Connection limit'), cell: 'integer', min : -1, - mode: ['properties', 'edit', 'create'], readonly: 'readonly', - },{ - id: 'rolcanlogin', label: gettext('Can login?'), - type: 'switch', - controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12', - controlsClassName: 'pgadmin-controls pg-el-sm-8 pg-el-12', - group: gettext('Privileges'), - readonly: 'readonly', - },{ - id: 'rolsuper', label: gettext('Superuser?'), - type: 'switch', - controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12', - controlsClassName: 'pgadmin-controls pg-el-sm-8 pg-el-12', - group: gettext('Privileges'), - control: Backform.SwitchControl.extend({ - onChange: function() { - Backform.SwitchControl.prototype.onChange.apply(this, arguments); - - this.model.set('rolcatupdate', this.model.get('rolsuper')); - this.model.set('rolcreaterole', this.model.get('rolsuper')); - this.model.set('rolcreatedb', this.model.get('rolsuper')); - }, - }), - readonly: 'readonly', - },{ - id: 'rolcreaterole', label: gettext('Create roles?'), - group: gettext('Privileges'), - type: 'switch', - controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12', - controlsClassName: 'pgadmin-controls pg-el-sm-8 pg-el-12', - readonly: 'readonly', - },{ - id: 'is_sys_obj', label: gettext('System role?'), - cell:'boolean', type: 'switch', mode: ['properties'], - },{ - id: 'description', label: gettext('Comments'), type: 'multiline', - group: null, mode: ['properties', 'edit', 'create'], - readonly: 'readonly', - },{ - id: 'rolcreatedb', label: gettext('Create databases?'), - group: gettext('Privileges'), - type: 'switch', - controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12', - controlsClassName: 'pgadmin-controls pg-el-sm-8 pg-el-12', - readonly: 'readonly', - },{ - id: 'rolcatupdate', label: gettext('Update catalog?'), - type: 'switch', - controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12', - controlsClassName: 'pgadmin-controls pg-el-sm-8 pg-el-12', - max_version: 90400, - group: gettext('Privileges'), readonly: function(m) { - return m.get('read_only'); - }, - disabled: function(m) { - return !m.get('rolsuper'); - }, - },{ - id: 'rolinherit', group: gettext('Privileges'), - label: gettext('Inherit rights from the parent roles?'), - type: 'switch', - controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12', - controlsClassName: 'pgadmin-controls pg-el-sm-8 pg-el-12', - readonly: 'readonly', - },{ - id: 'rolreplication', group: gettext('Privileges'), - label: gettext('Can initiate streaming replication and backups?'), - type: 'switch', - controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12', - controlsClassName: 'pgadmin-controls pg-el-sm-8 pg-el-12', - min_version: 90100, - readonly: 'readonly', - }], - readonly: function(m) { - if (!m.has('read_only')) { - var user = this.node_info.server.user; - - m.set('read_only', !(user.is_superuser || user.can_create_role)); - } - - return m.get('read_only'); - }, - validate: function() - { - var err = {}, - errmsg, - seclabels = this.get('seclabels'); - - if (_.isUndefined(this.get('rolname')) || String(this.get('rolname')).replace(/^\s+|\s+$/g, '') == '') { - err['name'] = gettext('Name cannot be empty.'); - errmsg = err['name']; - } - - if (seclabels) { - var secLabelsErr; - for (var i = 0; i < seclabels.models.length && !secLabelsErr; i++) { - secLabelsErr = (seclabels.models[i]).validate.apply(seclabels.models[i]); - if (secLabelsErr) { - err['seclabels'] = secLabelsErr; - errmsg = errmsg || secLabelsErr; - } - } - } - - this.errorModel.clear().set(err); - - if (_.size(err)) { - this.trigger('on-status', {msg: errmsg}); - return errmsg; - } - - return null; - }, - }), }); } diff --git a/web/pgadmin/browser/static/js/collection.js b/web/pgadmin/browser/static/js/collection.js index 9f944ff19..240665432 100644 --- a/web/pgadmin/browser/static/js/collection.js +++ b/web/pgadmin/browser/static/js/collection.js @@ -7,8 +7,9 @@ // ////////////////////////////////////////////////////////////// -import {removeNodeView} from './node_view'; -import Notify from '../../../static/js/helpers/Notifier'; +// import {removeNodeView} from './node_view'; +// import Notify from '../../../static/js/helpers/Notifier'; +import {getPanelView} from './panel_view'; define([ 'sources/gettext', 'jquery', 'underscore', 'sources/pgadmin', @@ -91,399 +92,14 @@ define([ canDropCascade: true, selectParentNodeOnDelete: false, showProperties: function(item, data, panel) { - var that = this, - j = panel.$container.find('.obj_properties').first(), - view = j.data('obj-view'), - content = $('
') - .addClass('pg-prop-content col-12 has-pg-prop-btn-group'), - node = pgBrowser.Nodes[that.node], - $msgContainer = '', - // This will be the URL, used for object manipulation. - urlBase = this.generate_url(item, 'properties', data), - info = pgBrowser.tree.getTreeNodeHierarchy(item), - gridSchema = Backform.generateGridColumnsFromModel( - info, node.model, 'properties', that.columns - ), - createButtons = function(buttonsList, location, extraClasses) { - // Arguments must be non-zero length array of type - // object, which contains following attributes: - // label, type, extraClasses, register - if (buttonsList && _.isArray(buttonsList) && buttonsList.length > 0) { - // All buttons will be created within a single - // div area. - var btnGroup = - $('
'), - // Template used for creating a button - tmpl = _.template([ - '', - ].join(' ')); - if (location == 'header') { - btnGroup.appendTo(that.header); - } else { - btnGroup.appendTo(that.footer); - } - if (extraClasses) { - btnGroup.addClass(extraClasses); - } - _.each(buttonsList, function(btn) { - // Create the actual button, and append to - // the group div - // icon may not present for this button - if (!btn.icon) { - btn.icon = ''; - } - var b = $(tmpl(btn)); - btnGroup.append(b); - // Register is a callback to set callback - // for certain operation for this button. - btn.register(b); - }); - return btnGroup; - } - return null; - }.bind(panel); - - that.collection = new (node.Collection.extend({ - url: urlBase, - model: node.model, - }))(); - // Add the new column for the multi-select menus - if((_.isFunction(that.canDrop) ? - that.canDrop.apply(that, [data, item]) : that.canDrop) || - (_.isFunction(that.canDropCascade) ? - that.canDropCascade.apply(that, [data, item]) : that.canDropCascade)) { - gridSchema.columns.unshift({ - name: 'oid', - cell: Backgrid.Extension.SelectRowCell.extend({ - initialize: function (options) { - this.column = options.column; - if (!(this.column instanceof Backgrid.Column)) { - this.column = new Backgrid.Column(this.column); - } - - var column = this.column, model = this.model, $el = this.$el; - this.listenTo(column, 'change:renderable', function (col, renderable) { - $el.toggleClass('renderable', renderable); - }); - - if (Backgrid.callByNeed(column.renderable(), column, model)) $el.addClass('renderable width_percent_3'); - - this.listenTo(model, 'backgrid:select', this.toggleCheckbox); - }, - toggleCheckbox: function(model, selected) { - if (this.checkbox().prop('disabled') === false) { - this.checkbox().prop('checked', selected).change(); - } - }, - render: function() { - let model = this.model.toJSON(); - // canDrop can be set to false for individual row from the server side to disable the checkbox - let disabled = ('canDrop' in model && model.canDrop === false); - let id = `row-${_.uniqueId(model.oid || model.name)}`; - - this.$el.empty().append(` -
- - -
- `); - this.delegateEvents(); - return this; - }, - }), - headerCell: Backgrid.Extension.SelectAllHeaderCell, - }); - } - /* Columns should be always non-editable */ - gridSchema.columns.forEach((col)=>{ - col.disabled = true; - }); - - // Get the list of selected models, before initializing the grid - // again. - var selectedModels = []; - if(!_.isUndefined(that.grid) && 'collection' in that.grid){ - selectedModels = that.grid.getSelectedModels(); - } - - // Initialize a new Grid instance - that.grid = new Backgrid.Grid({ - emptyText: gettext('No data found'), - columns: gridSchema.columns, - collection: that.collection, - className: 'backgrid table presentation table-bordered table-noouter-border table-hover', - }); - - var gridView = { - 'remove': function() { - if (this.grid) { - if (this.grid.collection) { - this.grid.collection.reset([], {silent: true}); - delete (this.grid.collection); - } - delete (this.grid); - this.grid = null; - } - }, - grid: that.grid, - }; - - if (view) { - // Cache the current IDs for next time - $(panel).data('node-prop', urlBase); - - // Reset the data object - j.data('obj-view', null); - } - - /* Remove any dom rendered by getNodeView */ - removeNodeView(j[0]); - // Make sure the HTML element is empty. - j.empty(); - j.data('obj-view', gridView); - - $msgContainer = '
' + - gettext('Retrieving data from the server...') + '
'; - - $msgContainer = $($msgContainer).appendTo(j); - - that.header = $('
').addClass( - 'pg-prop-header' + let container = panel.$container[0]; + getPanelView( + pgBrowser.tree, + container, + pgBrowser, + panel._type ); - - // Render the buttons - var buttons = []; - - buttons.push({ - label: '', - type: 'delete', - tooltip: gettext('Delete/Drop'), - extraClasses: ['btn-primary-icon m-1', 'delete_multiple'], - icon: 'fa fa-trash-alt', - disabled: (_.isFunction(that.canDrop)) ? !(that.canDrop.apply(self, [data, item])) : (!that.canDrop), - register: function(btn) { - btn.on('click',() => { - onDrop('drop'); - }); - }, - }); - - buttons.push({ - label: '', - type: 'delete', - tooltip: gettext('Drop Cascade'), - extraClasses: ['btn-primary-icon m-1', 'delete_multiple_cascade'], - icon: 'pg-font-icon icon-drop_cascade', - disabled: (_.isFunction(that.canDropCascade)) ? !(that.canDropCascade.apply(self, [data, item])) : (!that.canDropCascade), - register: function(btn) { - btn.on('click',() => { - onDrop('dropCascade'); - }); - }, - }); - - createButtons(buttons, 'header', 'pg-prop-btn-group-above'); - - // Render subNode grid - content.append('
'); - content.find('.pg-prop-coll-container').append(that.grid.render().$el); - - var timer; - var getAjaxHook = function() { - $.ajax({ - url: urlBase, - type: 'GET', - beforeSend: function(xhr) { - xhr.setRequestHeader(pgAdmin.csrf_token_header, pgAdmin.csrf_token); - // Generate a timer for the request - timer = setTimeout(function() { - // notify user if request is taking longer than 1 second - - if (!$msgContainer.text()== 'Failed to retrieve data from the server.') - $msgContainer.text(gettext('Retrieving data from the server...')); - $msgContainer.removeClass('d-none'); - if (self.grid) { - self.grid.remove(); - } - }, 1000); - }, - }).done(function(res) { - clearTimeout(timer); - - if (_.isUndefined(that.grid) || _.isNull(that.grid)) return; - - that.data = res; - - if (that.data.length > 0) { - - if (!$msgContainer.hasClass('d-none')) { - $msgContainer.addClass('d-none'); - } - that.header.appendTo(j); - j.append(content); - - // Listen scroll event to load more rows - $('.pg-prop-content').on('scroll', that.__loadMoreRows.bind(that)); - - that.collection.reset(that.data.splice(0, 50)); - - // Listen to select all checkbox event - that.collection.on('backgrid:select-all', that.__loadAllRows.bind(that)); - - // Trigger the backgrid:select event for already selected items - // as we have created a new grid instance. - if(selectedModels.length > 0) { - that.collection.each(function (model) { - for(let model_val of selectedModels){ - if (model_val.id == model.id){ - model.trigger('backgrid:select', model, true); - } - } - }); - } - } else { - // Do not listen the scroll event - $('.pg-prop-content').off('scroll', that.__loadMoreRows); - - $msgContainer.text(gettext('No properties are available for the selected object.')); - - } - selectedModels = []; - }).fail(function(xhr, error) { - pgBrowser.Events.trigger( - 'pgadmin:node:retrieval:error', 'properties', xhr, error.message, item, that - ); - if (!Alertify.pgHandleItemError(xhr, error.message, { - item: item, - info: info, - })) { - Notify.pgNotifier( - error, xhr, gettext('Error retrieving properties - %s', error.message || that.label), - function(msg) { - if(msg === 'CRYPTKEY_SET') { - getAjaxHook(); - } else { - console.warn(arguments); - } - } - ); - } - // show failed message. - $msgContainer.text(gettext('Failed to retrieve data from the server.')); - }); - }; - getAjaxHook(); - - var onDrop = function(type, confirm=true) { - let sel_row_models = this.grid.getSelectedModels(), - sel_rows = [], - sel_item = pgBrowser.tree.selected(), - d = sel_item ? pgBrowser.tree.itemData(sel_item) : null, - sel_node = d && pgBrowser.Nodes[d._type], - url = undefined, - msg = undefined, - title = undefined; - - if (sel_node && sel_node.type && sel_node.type == 'coll-constraints') { - // In order to identify the constraint type, the type should be passed to the server - sel_rows = sel_row_models.map(row => ({id: row.get('oid'), _type: row.get('_type')})); - } - else { - sel_rows = sel_row_models.map(row => row.id); - } - - if (sel_rows.length === 0) { - Notify.alert(gettext('Drop Multiple'), - gettext('Please select at least one object to delete.') - ); - return; - } - - if (!sel_node) - return; - - if (type === 'dropCascade') { - url = sel_node.generate_url(sel_item, 'delete'); - msg = gettext('Are you sure you want to drop all the selected objects and all the objects that depend on them?'); - title = gettext('DROP CASCADE multiple objects?'); - } else { - url = sel_node.generate_url(sel_item, 'drop'); - msg = gettext('Are you sure you want to drop all the selected objects?'); - title = gettext('DROP multiple objects?'); - } - - let dropAjaxHook = function() { - $.ajax({ - url: url, - type: 'DELETE', - data: JSON.stringify({'ids': sel_rows}), - contentType: 'application/json; charset=utf-8', - }).done(function(res) { - if (res.success == 0) { - pgBrowser.report_error(res.errormsg, res.info); - } else { - $(pgBrowser.panels['properties'].panel).removeData('node-prop'); - pgBrowser.Events.trigger( - 'pgadmin:browser:tree:refresh', sel_item || pgBrowser.tree.selected(), { - success: function() { - setTimeout(function() { - pgBrowser.tree.select(sel_item); - sel_node.callbacks.selected.apply(sel_node, [sel_item]); - }, 100); - }, - }); - } - return true; - }).fail(function(xhr, error) { - Notify.pgNotifier( - error, xhr, - gettext('Error dropping %s', d._label.toLowerCase()), - function(alertMsg) { - if (alertMsg == 'CRYPTKEY_SET') { - onDrop(type, false); - } else { - $(pgBrowser.panels['properties'].panel).removeData('node-prop'); - pgBrowser.Events.trigger( - 'pgadmin:browser:tree:refresh', sel_item || pgBrowser.tree.selected(), { - success: function() { - sel_node.callbacks.selected.apply(sel_node, [sel_item]); - }, - } - ); - } - } - ); - }); - }; - - if(confirm) { - Notify.confirm(title, msg, dropAjaxHook, null); - } else { - dropAjaxHook(); - } - }.bind(that); - }, - __loadMoreRows: function(e) { - let elem = e.currentTarget; - if ((elem.scrollHeight - 10) < elem.scrollTop + elem.offsetHeight) { - if (this.data.length > 0) { - this.collection.add(this.data.splice(0, 50)); - } - } - }, - __loadAllRows: function(tmp, checked) { - if (this.data.length > 0) { - this.collection.add(this.data); - this.collection.each(function (model) { - model.trigger('backgrid:select', model, checked); - }); - } }, generate_url: function(item, type) { /* diff --git a/web/pgadmin/browser/static/js/node.js b/web/pgadmin/browser/static/js/node.js index 9e6d3d543..21ae4c06d 100644 --- a/web/pgadmin/browser/static/js/node.js +++ b/web/pgadmin/browser/static/js/node.js @@ -1082,8 +1082,6 @@ define('pgadmin.browser.node', [ b.panels['properties'] && b.panels['properties'].panel && b.panels['properties'].panel.isVisible()) { - // Show object properties (only when the 'properties' tab - // is active). this.showProperties(item, d, b.panels['properties'].panel); } } @@ -1259,20 +1257,20 @@ define('pgadmin.browser.node', [ d = i && tree.itemData(i), treeHierarchy = tree.getTreeNodeHierarchy(i); - if (_.isEqual($(this).data('node-prop'), treeHierarchy)) { - return; - } - // Cache the current IDs for next time $(this).data('node-prop', treeHierarchy); /* Remove any dom rendered by getNodeView */ - removeNodeView(j[0]); - /* getSchema is a schema for React. Get the react node view */ + removeNodeView(pgBrowser.panels['properties'].panel.$container[0]); + + var containerProperties = pgBrowser.panels['properties'].panel.$container; + containerProperties.addClass('pg-panel-content pg-no-overflow pg-el-container'); + + if(that.getSchema) { let treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(item); getNodeView( - that.type, treeNodeInfo, 'properties', data, 'tab', j[0], this, onEdit + that.type, treeNodeInfo, 'properties', data, 'tab', containerProperties[0], this, onEdit ); return; } diff --git a/web/pgadmin/browser/static/js/node_ajax.js b/web/pgadmin/browser/static/js/node_ajax.js index 14a9afa3c..19ac76562 100644 --- a/web/pgadmin/browser/static/js/node_ajax.js +++ b/web/pgadmin/browser/static/js/node_ajax.js @@ -25,8 +25,9 @@ export function generateCollectionURL(item, type) { }; var treeInfo = pgAdmin.Browser.tree.getTreeNodeHierarchy(item); var actionType = type in opURL ? opURL[type] : type; + var nodeType = type === 'properties' ? nodeObj.type : nodeObj.node; return generate_url( - pgAdmin.Browser.URL, treeInfo, actionType, nodeObj.node, + pgAdmin.Browser.URL, treeInfo, actionType, nodeType, collectionPickFunction ); } diff --git a/web/pgadmin/browser/static/js/node_view.jsx b/web/pgadmin/browser/static/js/node_view.jsx index b9ec79e90..453f20c95 100644 --- a/web/pgadmin/browser/static/js/node_view.jsx +++ b/web/pgadmin/browser/static/js/node_view.jsx @@ -16,7 +16,6 @@ import {getHelpUrl, getEPASHelpUrl} from 'pgadmin.help'; import SchemaView from 'sources/SchemaView'; import { generateNodeUrl } from './node_ajax'; import Notify from '../../../static/js/helpers/Notifier'; - import gettext from 'sources/gettext'; import 'wcdocker'; diff --git a/web/pgadmin/browser/static/js/panel.js b/web/pgadmin/browser/static/js/panel.js index fbbc56bd5..c0bd9178f 100644 --- a/web/pgadmin/browser/static/js/panel.js +++ b/web/pgadmin/browser/static/js/panel.js @@ -122,14 +122,32 @@ define( that.resizedContainer.apply(myPanel); } - // Bind events only if they are configurable - if (that.canHide) { - _.each([wcDocker.EVENT.CLOSED, wcDocker.EVENT.VISIBILITY_CHANGED], - function(ev) { - myPanel.on(ev, that.handleVisibility.bind(myPanel, ev)); - }); + + + if (myPanel._type == 'dashboard') { + getPanelView( + pgBrowser.tree, + $container[0], + pgBrowser, + myPanel._type + ); } + // Rerender the dashboard panel when preference value 'show graph' gets changed. + pgBrowser.onPreferencesChange('dashboards', function() { + getPanelView( + pgBrowser.tree, + $container[0], + pgBrowser, + myPanel._type + ); + }); + + _.each([wcDocker.EVENT.CLOSED, wcDocker.EVENT.VISIBILITY_CHANGED], + function(ev) { + myPanel.on(ev, that.handleVisibility.bind(myPanel, ev)); + }); + pgBrowser.Events.on('pgadmin-browser:tree:selected', () => { if(myPanel.isVisible()) { @@ -141,6 +159,18 @@ define( ); } }); + + pgBrowser.Events.on('pgadmin-browser:tree:refreshing', () => { + + if(myPanel.isVisible()) { + getPanelView( + pgBrowser.tree, + $container[0], + pgBrowser, + myPanel._type + ); + } + }); }, }); } @@ -205,11 +235,6 @@ define( } }, handleVisibility: function(eventName) { - // Supported modules - let type_module = { - dashboard: pgAdmin.Dashboard, - }; - let module = type_module[this._type]; if (_.isNull(pgBrowser.tree)) return; let selectedPanel = pgBrowser.docker.findPanels(this._type)[0]; @@ -219,18 +244,6 @@ define( .scene() .find('.pg-panel-content'); - if (this._type === 'dashboard') { - if (eventName == 'panelClosed') { - module.toggleVisibility.call(module, false, true); - } else if (eventName == 'panelVisibilityChanged') { - module.toggleVisibility.call( - module, - pgBrowser.docker.findPanels(this._type)[0].isVisible(), - false - ); - } - } - if (isPanelVisible) { if (eventName == 'panelClosed') { removePanelView($container[0]); diff --git a/web/pgadmin/browser/static/js/panel_view.jsx b/web/pgadmin/browser/static/js/panel_view.jsx index cf0a5a07e..39122755d 100644 --- a/web/pgadmin/browser/static/js/panel_view.jsx +++ b/web/pgadmin/browser/static/js/panel_view.jsx @@ -13,6 +13,11 @@ import Theme from 'sources/Theme'; import Dependencies from '../../../misc/dependencies/static/js/Dependencies'; import Dependents from '../../../misc/dependents/static/js/Dependents'; import Statistics from '../../../misc/statistics/static/js/Statistics'; +import SQL from '../../../misc/sql/static/js/SQL'; +import Dashboard from '../../../dashboard/static/js/Dashboard'; +import _ from 'lodash'; +import { CollectionNodeView } from '../../../misc/properties/CollectionNodeProperties'; + /* The entry point for rendering React based view in properties, called in node.js */ export function getPanelView( @@ -21,10 +26,33 @@ export function getPanelView( pgBrowser, panelType ) { - let item = tree.selected(), - nodeData = item && tree.itemData(item), - node = item && nodeData && pgBrowser.Nodes[nodeData._type], + let item = !_.isNull(tree)? tree.selected(): null, + + nodeData, node, treeNodeInfo, preferences; + if (item){ + nodeData = tree.itemData(item); + node = nodeData && pgBrowser.Nodes[nodeData._type]; treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(item); + preferences = pgBrowser.get_preferences_for_module('dashboards'); + } + if (panelType == 'dashboard') { + ReactDOM.render( + + + , + container + ); + } if (panelType == 'statistics') { @@ -41,6 +69,20 @@ export function getPanelView( container ); } + if (panelType == 'properties') { + ReactDOM.render( + + + , + container + ); + } if (panelType == 'dependencies') { ReactDOM.render( @@ -69,6 +111,20 @@ export function getPanelView( container ); } + if (panelType == 'sql') { + ReactDOM.render( + + + , + container + ); + } } /* When switching from normal node to collection node, clean up the React mounted DOM */ diff --git a/web/pgadmin/dashboard/static/js/ActiveQuery.ui.js b/web/pgadmin/dashboard/static/js/ActiveQuery.ui.js new file mode 100644 index 000000000..69080e47d --- /dev/null +++ b/web/pgadmin/dashboard/static/js/ActiveQuery.ui.js @@ -0,0 +1,67 @@ +///////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2022, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +////////////////////////////////////////////////////////////// + +import gettext from 'sources/gettext'; +import BaseUISchema from 'sources/SchemaView/base_schema.ui'; + +export default class ActiveQuery extends BaseUISchema { + constructor(initValues) { + super({ + ...initValues, + }); + + } + + get baseFields() { + return [ + + { + id: 'backend_type', + label: gettext('Backend type'), + type: 'text', + editable: true, + noEmpty: true, + readonly: true, + mode: ['properties'], + group: gettext('Details'), + disabled: true + }, + { + id: 'query_start', + label: gettext('Query started at'), + type: 'text', + editable: false, + readonly: true, + group: gettext('Details'), + disabled: true + + }, + { + id: 'state_change', + label: gettext('Last state changed at'), + type: 'text', + editable: false, + readonly: true, + group: gettext('Details'), + disabled: true + }, + { + id: 'query', + label: gettext('SQL'), + cell: 'string', + editable: false, + readonly: true, + type: 'sql', + group: gettext('Details'), + }, + ]; + + } + +} diff --git a/web/pgadmin/dashboard/static/js/Dashboard.jsx b/web/pgadmin/dashboard/static/js/Dashboard.jsx new file mode 100644 index 000000000..9c008b3cb --- /dev/null +++ b/web/pgadmin/dashboard/static/js/Dashboard.jsx @@ -0,0 +1,907 @@ +///////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2022, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +////////////////////////////////////////////////////////////// +// eslint-disable-next-line react/display-name +import React, { useEffect, useState } from 'react'; +import gettext from 'sources/gettext'; +import PropTypes from 'prop-types'; +import getApiInstance from 'sources/api_instance'; +import PgTable from 'sources/components/PgTable'; +import { makeStyles } from '@material-ui/core/styles'; +import url_for from 'sources/url_for'; +import Graphs from './Graphs'; +import Notify from '../../../static/js/helpers/Notifier'; +import { Box, Tab, Tabs } from '@material-ui/core'; +import { PgIconButton } from '../../../static/js/components/Buttons'; +import CancelIcon from '@mui/icons-material/Cancel'; +import SquareIcon from '@mui/icons-material/Square'; +import ArrowRightOutlinedIcon from '@mui/icons-material/ArrowRightOutlined'; +import ArrowDropDownOutlinedIcon from '@mui/icons-material/ArrowDropDownOutlined'; +import WelcomeDashboard from './WelcomeDashboard'; +import ActiveQuery from './ActiveQuery.ui'; +import _ from 'lodash'; + +function parseData(data) { + var res = []; + + data.forEach((row) => { + res.push({ ...row, icon: '' }); + }); + return res; +} + +const useStyles = makeStyles((theme) => ({ + emptyPanel: { + height: '100%', + background: theme.palette.grey[400], + overflow: 'auto', + padding: '8px', + display: 'flex', + flexDirection: 'column', + flexGrow: 1, + }, + fixedSizeList: { + overflowX: 'hidden !important', + overflow: 'overlay !important', + height: 'auto !important', + }, + dashboardPanel: { + height: '100%', + background: theme.palette.grey[400], + }, + cardHeader: { + padding: '0.25rem 0.5rem', + fontWeight: 'bold', + backgroundColor: theme.otherVars.tableBg, + borderBottom: '1px solid', + borderBottomColor: theme.otherVars.borderColor, + }, + searchPadding: { + display: 'flex', + flex: 2.5, + }, + component: { + padding: '8px', + }, + searchInput: { + flex: 1, + }, + panelIcon: { + width: '80%', + margin: '0 auto', + marginTop: '25px !important', + position: 'relative', + textAlign: 'center', + }, + panelMessage: { + marginLeft: '0.5rem', + fontSize: '0.875rem', + }, + panelContent: { + ...theme.mixins.panelBorder, + flexDirection: 'column', + overflow: 'hidden !important', + flexGrow: 1 + }, + terminateButton: { + color: theme.palette.error.main + }, + buttonClick: { + backgroundColor: theme.palette.grey[400] + } +})); + +/* eslint-disable react/display-name */ +export default function Dashboard({ + nodeData, + node, + item, + pgBrowser, + preferences, + sid, + did, + treeNodeInfo, + ...props +}) { + const classes = useStyles(); + let tab = ['Sessions', 'Locks', 'Prepared Transactions']; + const [dashData, setdashData] = useState([]); + const [msg, setMsg] = useState(''); + const[infoMsg, setInfo] = useState(''); + const [val, setVal] = useState(0); + const [schemaDict, setSchemaDict] = React.useState({}); + + if (!did) { + tab.push('Configuration'); + } + val == 3 && did && setVal(0); + const tabChanged = (e, tabVal) => { + setVal(tabVal); + }; + + const serverConfigColumns = [ + { + accessor: 'name', + Header: gettext('Name'), + sortble: true, + resizable: true, + disableGlobalFilter: false, + minWidth: 50, + maxWidth: 110, + }, + { + accessor: 'category', + Header: gettext('Category'), + sortble: true, + resizable: true, + disableGlobalFilter: false, + minWidth: 50, + maxWidth: 150, + }, + { + accessor: 'setting', + Header: gettext('Setting'), + sortble: true, + resizable: true, + disableGlobalFilter: false, + minWidth: 50, + maxWidth: 50, + }, + { + accessor: 'unit', + Header: gettext('Unit'), + sortble: true, + resizable: true, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 30, + }, + { + accessor: 'short_desc', + Header: gettext('Description'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + }, + ]; + + const activityColumns = [ + { + accessor: 'terminate_query', + Header: () => null, + sortble: true, + resizable: true, + disableGlobalFilter: false, + minWidth: 16, + maxWidth: 30, + id: 'btn-terminate', + // eslint-disable-next-line react/display-name + Cell: ({ row }) => { + var terminate_session_url = + url_for('dashboard.index') + 'terminate_session' + '/' + sid, + title = gettext('Terminate Session?'), + txtConfirm = gettext( + 'Are you sure you wish to terminate the session?' + ), + txtSuccess = gettext('Session terminated successfully.'), + txtError = gettext( + 'An error occurred whilst terminating the active query.' + ); + const action_url = did + ? terminate_session_url + '/' + did + : terminate_session_url; + + const api = getApiInstance(); + + return ( + } + className={classes.terminateButton} + onClick={() => { + if ( + !canTakeAction(row, 'terminate') + ) + return; + let url = action_url + '/' + row.values.pid; + Notify.confirm( + title, + txtConfirm, + function () { + api + .delete(url) + .then(function (res) { + if (res.data == gettext('Success')) { + setInfo(txtSuccess); + Notify.success(txtSuccess); + } else { + setInfo(txtError); + Notify.error(txtError); + } + }) + .catch(function (error) { + Notify.alert( + gettext('Failed to retrieve data from the server.'), + gettext(error.message) + ); + }); + }, + function () { + return true; + } + ); + }} + color="default" + aria-label="Terminate Session?" + title={gettext('Terminate Session?')} + > + ); + }, + }, + { + accessor: 'cancel_Query', + Header: () => null, + sortble: true, + resizable: true, + disableGlobalFilter: false, + minWidth: 16, + maxWidth: 30, + id: 'btn-cancel', + Cell: ({ row }) => { + var cancel_query_url = + url_for('dashboard.index') + 'cancel_query' + '/' + sid, + title = gettext('Cancel Active Query?'), + txtConfirm = gettext( + 'Are you sure you wish to cancel the active query?' + ), + txtSuccess = gettext('Active query cancelled successfully.'), + txtError = gettext( + 'An error occurred whilst cancelling the active query.' + ); + + const action_url = did ? cancel_query_url + '/' + did : cancel_query_url; + + const api = getApiInstance(); + + return ( + } + onClick={() => { + if (!canTakeAction(row, 'cancel')) + return; + let url = action_url + '/' + row.values.pid; + Notify.confirm( + title, + txtConfirm, + function () { + api + .delete(url) + .then(function (res) { + if (res.data == gettext('Success')) { + setInfo(txtSuccess); + Notify.success(txtSuccess); + } else { + setInfo(txtError); + Notify.error(txtError); + } + }) + .catch(function (error) { + Notify.alert( + gettext('Failed to retrieve data from the server.'), + gettext(error.message) + ); + }); + }, + function () { + return true; + } + ); + }} + color="default" + aria-label="Cancel the query" + title={gettext('Cancel the active query')} + > + ); + }, + }, + { + accessor: 'view_active_query', + Header: () => null, + sortble: true, + resizable: true, + disableGlobalFilter: false, + minWidth: 16, + maxWidth: 30, + id: 'btn-edit', + Cell: ({ row }) => { + let canEditRow = true; + return ( + + ) : ( + + ) + } + size="xs" + noBorder + onClick={(e) => { + e.preventDefault(); + row.toggleRowExpanded(!row.isExpanded); + if(!(row.id in schemaDict)){ + let schema = new ActiveQuery({ + query: row.original.query, + backend_type: row.original.backend_type, + state_change: row.original.state_change, + query_start: row.original.query_start, + }); + setSchemaDict(prevState => ({ + ...prevState, + [row.id]: schema + })); + } + }} + disabled={!canEditRow} + aria-label="View the active session details" + title={gettext('View the active session details')} + /> + ); + }, + }, + { + accessor: 'pid', + Header: gettext('PID'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 60, + }, + { + accessor: 'datname', + Header: gettext('Database'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 80, + isVisible: !did ? true: false + }, + { + accessor: 'usename', + Header: gettext('User'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 80, + }, + { + accessor: 'application_name', + Header: gettext('Application'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 150, + }, + { + accessor: 'client_addr', + Header: gettext('Client'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 60, + }, + { + accessor: 'backend_start', + Header: gettext('Backend start'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 150, + }, + { + accessor: 'xact_start', + Header: gettext('Transaction start'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 150, + }, + { + accessor: 'state', + Header: gettext('State'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 60, + }, + + { + accessor: 'waiting', + Header: gettext('Waiting'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + isVisible: treeNodeInfo?.server?.version < 90600 + }, + { + accessor: 'wait_event', + Header: gettext('Wait event'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + }, + { + accessor: 'blocking_pids', + Header: gettext('Blocking PIDs'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + }, + ]; + + const databaseLocksColumns = [ + { + accessor: 'pid', + Header: gettext('PID'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 50, + }, + { + accessor: 'datname', + Header: gettext('Database'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 80, + isVisible: !did ? true: false + }, + { + accessor: 'locktype', + Header: gettext('Lock type'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 60, + }, + { + accessor: 'relation', + Header: gettext('Target relation'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + }, + { + accessor: 'page', + Header: gettext('Page'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 50, + }, + { + accessor: 'tuple', + Header: gettext('Tuple'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 50, + }, + { + accessor: 'virtualxid', + Header: gettext('vXID (target)'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 100, + maxWidth: 100, + }, + { + accessor: 'transactionid', + Header: gettext('XID (target)'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 50, + maxWidth: 100, + }, + { + accessor: 'classid', + Header: gettext('Class'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 50, + }, + { + accessor: 'objid', + Header: gettext('Object ID'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 50, + maxWidth: 100, + }, + { + accessor: 'virtualtransaction', + Header: gettext('vXID (owner)'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 50, + maxWidth: 80, + }, + { + accessor: 'mode', + Header: gettext('Mode'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + }, + { + id: 'granted', + accessor: 'granted', + Header: gettext('Granted?'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 50, + maxWidth: 80, + Cell: ({ value }) => String(value) + }, + ]; + + const databasePreparedColumns = [ + { + accessor: 'git', + Header: gettext('Name'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + }, + { + accessor: 'datname', + Header: gettext('Database'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + minWidth: 26, + maxWidth: 80, + isVisible: !did ? true: false + }, + { + accessor: 'Owner', + Header: gettext('Owner'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + }, + { + accessor: 'transaction', + Header: gettext('XID'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + }, + { + accessor: 'prepared', + Header: gettext('Prepared at'), + sortble: true, + resizable: false, + disableGlobalFilter: false, + }, + ]; + + const canTakeAction = (row, cellAction) => { + // We will validate if user is allowed to cancel the active query + // If there is only one active session means it probably our main + // connection session + cellAction = cellAction || null; + var pg_version = treeNodeInfo.server.version || null, + is_cancel_session = cellAction === 'cancel', + txtMessage, + maintenance_database = treeNodeInfo.server.db, + is_super_user, + current_user; + + var can_signal_backend = + treeNodeInfo.server && treeNodeInfo.server.user + ? treeNodeInfo.server.user.can_signal_backend + : false; + + if ( + treeNodeInfo.server && + treeNodeInfo.server.user && + treeNodeInfo.server.user.is_superuser + ) { + is_super_user = true; + } else { + is_super_user = false; + current_user = + treeNodeInfo.server && treeNodeInfo.server.user + ? treeNodeInfo.server.user.name + : null; + } + + // With PG10, We have background process showing on dashboard + // We will not allow user to cancel them as they will fail with error + // anyway, so better usability we will throw our on notification + + // Background processes do not have database field populated + if (pg_version && pg_version >= 100000 && !row.original.datname) { + if (is_cancel_session) { + txtMessage = gettext('You cannot cancel background worker processes.'); + } else { + txtMessage = gettext( + 'You cannot terminate background worker processes.' + ); + } + Notify.info(txtMessage); + return false; + // If it is the last active connection on maintenance db then error out + } else if ( + maintenance_database == row.original.datname && + row.original.state == 'active' + ) { + if (is_cancel_session) { + txtMessage = gettext( + 'You are not allowed to cancel the main active session.' + ); + } else { + txtMessage = gettext( + 'You are not allowed to terminate the main active session.' + ); + } + Notify.error(txtMessage); + return false; + } else if (is_cancel_session && row.original.state == 'idle') { + // If this session is already idle then do nothing + Notify.info(gettext('The session is already in idle state.')); + return false; + } else if (can_signal_backend) { + // user with membership of 'pg_signal_backend' can terminate the session of non admin user. + return true; + } else if (is_super_user) { + // Super user can do anything + return true; + } else if (current_user && current_user == treeNodeInfo.server.user) { + // Non-super user can cancel only their active queries + return true; + } else { + // Do not allow to cancel someone else session to non-super user + if (is_cancel_session) { + txtMessage = gettext( + 'Superuser privileges are required to cancel another users query.' + ); + } else { + txtMessage = gettext( + 'Superuser privileges are required to terminate another users query.' + ); + } + Notify.error(txtMessage); + return false; + } + }; + + useEffect(() => { + let url, + message = gettext( + 'Please connect to the selected server to view the dashboard.' + ); + + if (sid && props.serverConnected) { + + if (val === 0) { + url = url_for('dashboard.activity'); + } else if (val === 1) { + url = url_for('dashboard.locks'); + } else if (val === 2) { + url = url_for('dashboard.prepared'); + } else { + url = url_for('dashboard.config'); + } + + message = gettext('Loading dashboard...'); + if (did) url += sid + '/' + did; + else url += sid; + + const api = getApiInstance(); + if (node) { + api({ + url: url, + type: 'GET', + }) + .then((res) => { + setdashData(parseData(res.data)); + }) + .catch((e) => { + Notify.alert( + gettext('Failed to retrieve data from the server.'), + gettext(e.message) + ); + // show failed message. + setMsg(gettext('Failed to retrieve data from the server.')); + }); + } else { + setMsg(message); + } + } + if (message != '') { + setMsg(message); + } + }, [nodeData, val, did, preferences, infoMsg]); + + return ( + <> + {sid && props.serverConnected ? ( + + + {!_.isUndefined(preferences) && preferences.show_graphs && ( + + )} + + + {gettext('Server activity')}{' '} + + + {tab.map((tabValue, i) => { + return ; + })} + + + + + + + ) : sid && !props.serverConnected ? ( + +
+
+ + {gettext(msg)} +
+
+
+ ) : ( + + )} + + ); +} + +Dashboard.propTypes = { + node: PropTypes.func, + itemData: PropTypes.object, + nodeData: PropTypes.object, + treeNodeInfo: PropTypes.object, + item: PropTypes.object, + pgBrowser: PropTypes.object, + preferences: PropTypes.object, + sid: PropTypes.string, + did: PropTypes.oneOfType([PropTypes.bool, PropTypes.number]), + row: PropTypes.object, + serverConnected: PropTypes.bool, +}; + +export function ChartContainer(props) { + return ( +
+
+
+
{props.title}
+
+
+
+
+
+ {props.children} +
+ +
+
+ ); +} + +ChartContainer.propTypes = { + id: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + legendRef: PropTypes.oneOfType([ + PropTypes.func, + PropTypes.shape({ current: PropTypes.any }), + ]).isRequired, + children: PropTypes.node.isRequired, + errorMsg: PropTypes.string, +}; + +export function ChartError(props) { + if (props.message === null) { + return <>; + } + return ( +
+ {props.message} +
+ ); +} + +ChartError.propTypes = { + message: PropTypes.string, +}; + +export function DashboardRow({ children }) { + return
{children}
; +} +DashboardRow.propTypes = { + children: PropTypes.node.isRequired, +}; + +export function DashboardRowCol({ breakpoint, parts, children }) { + return
{children}
; +} + +DashboardRowCol.propTypes = { + breakpoint: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']).isRequired, + parts: PropTypes.number.isRequired, + children: PropTypes.node.isRequired, +}; diff --git a/web/pgadmin/dashboard/static/js/Graphs.jsx b/web/pgadmin/dashboard/static/js/Graphs.jsx index cd8fa65a3..69a9af4fc 100644 --- a/web/pgadmin/dashboard/static/js/Graphs.jsx +++ b/web/pgadmin/dashboard/static/js/Graphs.jsx @@ -8,7 +8,7 @@ ////////////////////////////////////////////////////////////// import React, { useEffect, useRef, useState, useReducer, useCallback, useMemo } from 'react'; import {LineChart} from 'sources/chartjs'; -import {ChartContainer, DashboardRowCol, DashboardRow} from './dashboard_components'; +import {ChartContainer, DashboardRowCol, DashboardRow} from './Dashboard'; import url_for from 'sources/url_for'; import axios from 'axios'; import gettext from 'sources/gettext'; diff --git a/web/pgadmin/dashboard/static/js/PgAdminLogo.jsx b/web/pgadmin/dashboard/static/js/PgAdminLogo.jsx new file mode 100644 index 000000000..ecfe6e9e1 --- /dev/null +++ b/web/pgadmin/dashboard/static/js/PgAdminLogo.jsx @@ -0,0 +1,219 @@ +///////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2022, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +////////////////////////////////////////////////////////////// +import React from 'react'; + +export default function PgAdminLogo() { + + return ( + ); + + +} diff --git a/web/pgadmin/dashboard/static/js/WelcomeDashboard.jsx b/web/pgadmin/dashboard/static/js/WelcomeDashboard.jsx new file mode 100644 index 000000000..ea4b58003 --- /dev/null +++ b/web/pgadmin/dashboard/static/js/WelcomeDashboard.jsx @@ -0,0 +1,249 @@ +///////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2022, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +////////////////////////////////////////////////////////////// + +import React from 'react'; +import gettext from 'sources/gettext'; +import _ from 'lodash'; +import { Link, BrowserRouter } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import { makeStyles } from '@material-ui/core/styles'; +import pgAdmin from 'sources/pgadmin'; +import PgAdminLogo from './PgAdminLogo'; + +const useStyles = makeStyles((theme) => ({ + emptyPanel: { + background: theme.palette.grey[400], + overflow: 'hidden', + padding: '8px', + display: 'flex', + flexDirection: 'column', + flexGrow: 1, + height: '100%' + + }, + dashboardContainer: { + paddingBottom: '8px', + minHeight: '100%' + }, + card: { + position: 'relative', + minWidth: 0, + wordWrap: 'break-word', + backgroundColor: theme.otherVars.tableBg, + backgroundClip: 'border-box', + border: '1px solid' + theme.otherVars.borderColor, + borderRadius: theme.shape.borderRadius, + marginTop: 8 + }, + row: { + marginRight: '-8px', + marginLeft: '-8px' + }, + rowContent: { + display: 'flex', + flexWrap: 'wrap', + marginRight: '-7.5px', + marginLeft: '-7.5px' + }, + cardHeader: { + padding: '0.25rem 0.5rem', + fontWeight: 'bold', + backgroundColor: theme.otherVars.tableBg, + borderBottom: '1px solid', + borderBottomColor: theme.otherVars.borderColor, + }, + dashboardLink: { + color: theme.otherVars.colorFg + '!important', + flex: '0 0 50%', + maxWidth: '50%', + textAlign: 'center', + cursor: 'pointer' + }, + gettingStartedLink: { + flex: '0 0 25%', + maxWidth: '50%', + textAlign: 'center', + cursor: 'pointer' + }, + link: { + color: theme.otherVars.colorFg + '!important', + }, + cardColumn: { + flex: '0 0 100%', + maxWidth: '100%', + margin: '8px' + }, + cardBody: { + flex: '1 1 auto', + minHeight: '1px', + padding: '0.5rem !important', + } +})); + + +function AddNewServer(pgBrowser) { + if (pgBrowser && pgBrowser.tree) { + var i = _.isUndefined(pgBrowser.tree.selected()) ? + pgBrowser.tree.first(null, false) : + pgBrowser.tree.selected(), + serverModule = pgAdmin.Browser.Nodes.server, + itemData = pgBrowser.tree.itemData(i); + + while (itemData && itemData._type != 'server_group') { + i = pgBrowser.tree.next(i); + itemData = pgBrowser.tree.itemData(i); + } + + if (!itemData) { + return; + } + + if (serverModule) { + serverModule.callbacks.show_obj_properties.apply( + serverModule, [{ + action: 'create', + }, i] + ); + } + } +} + +export default function WelcomeDashboard({ pgBrowser }) { + + const classes = useStyles(); + + return ( + +
+
+
+
+
+
{gettext('Welcome')}
+
+ +

+ {gettext('Feature rich')} | {gettext('Maximises PostgreSQL')}{' '} + | {gettext('Open Source')}{' '} +

+

+ {gettext( + 'pgAdmin is an Open Source administration and management tool for the PostgreSQL database. It includes a graphical administration interface, an SQL query tool, a procedural code debugger and much more. The tool is designed to answer the needs of developers, DBAs and system administrators alike.' + )} +

+
+
+
+
+
+
+
+
{gettext('Quick Links')}
+
+
+
+ { AddNewServer(pgBrowser); }} className={classes.link}> + +
+ {gettext('Add New Server')} + +
+
+ pgAdmin.Preferences.show()} className={classes.link}> + +
+ {gettext('Configure pgAdmin')} + +
+
+
+
+
+
+ +
+
+
+ ); +} + + +WelcomeDashboard.propTypes = { + pgBrowser: PropTypes.object.isRequired +}; + diff --git a/web/pgadmin/dashboard/static/js/dashboard.js b/web/pgadmin/dashboard/static/js/dashboard.js deleted file mode 100644 index 258071da4..000000000 --- a/web/pgadmin/dashboard/static/js/dashboard.js +++ /dev/null @@ -1,1209 +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 '../../../static/js/helpers/Notifier'; - -define('pgadmin.dashboard', [ - 'sources/url_for', 'sources/gettext', 'require', 'jquery', 'underscore', - 'sources/pgadmin', 'backbone', 'backgrid', - 'pgadmin.alertifyjs', 'pgadmin.backform', 'sources/nodes/dashboard', - 'sources/window', './ChartsDOM', 'pgadmin.browser', 'bootstrap', 'wcdocker', -], function( - url_for, gettext, r, $, _, pgAdmin, Backbone, Backgrid, - Alertify, Backform, NodesDashboard, pgWindow, ChartsDOM -) { - - pgAdmin.Browser = pgAdmin.Browser || {}; - var pgBrowser = pgAdmin.Browser; - - /* Return back, this has been called more than once */ - if (pgAdmin.Dashboard) - return; - - var dashboardVisible = true, - cancel_query_url = '', - terminate_session_url = '', - is_super_user = false, - current_user, maintenance_database, - is_server_dashboard = false, - is_database_dashboard = false, - can_signal_backend = false; - - // Custom BackGrid cell, Responsible for cancelling active sessions - var customDashboardActionCell = Backgrid.Extension.DeleteCell.extend({ - render: function() { - this.$el.empty(); - var self = this, - cell_action = self.column.get('cell_action'); - // if cancel query button then - if (cell_action === 'cancel') { - this.$el.html( - '' - ); - } else { - this.$el.html( - '' - ); - } - this.$el.attr('tabindex', 0); - this.$el.on('keydown', function(e) { - // terminating session or cancel the active query. - if (e.keyCode == 32) { - self.$el.click(); - } - }); - this.delegateEvents(); - return this; - }, - deleteRow: function(e) { - var self = this, - title, txtConfirm, txtSuccess, txtError, action_url, - cell_action = self.column.get('cell_action'); - - e.preventDefault(); - - var canDeleteRow = Backgrid.callByNeed( - self.column.get('canDeleteRow'), self.column, self.model - ); - // If we are not allowed to cancel the query, return from here - if (!canDeleteRow) - return; - - // This will refresh the grid - let refresh_grid = () => { - $('#btn_refresh').trigger('click'); - }; - - if (cell_action === 'cancel') { - title = gettext('Cancel Active Query?'); - txtConfirm = gettext('Are you sure you wish to cancel the active query?'); - txtSuccess = gettext('Active query cancelled successfully.'); - txtError = gettext('An error occurred whilst cancelling the active query.'); - action_url = cancel_query_url + self.model.get('pid'); - } else { - title = gettext('Terminate Session?'); - txtConfirm = gettext('Are you sure you wish to terminate the session?'); - txtSuccess = gettext('Session terminated successfully.'); - txtError = gettext('An error occurred whilst terminating the active query.'); - action_url = terminate_session_url + self.model.get('pid'); - } - - Notify.confirm( - title, txtConfirm, - function() { - $.ajax({ - url: action_url, - type: 'DELETE', - }) - .done(function(res) { - if (res == gettext('Success')) { - Notify.success(txtSuccess); - refresh_grid(); - } else { - Notify.error(txtError); - } - }) - .fail(function(xhr, status, error) { - Notify.pgRespErrorNotify(xhr, error); - }); - }, - function() { - return true; - } - ); - }, - }); - - - // Subnode Cell, which will display subnode control - var SessionDetailsCell = Backgrid.Extension.ObjectCell.extend({ - enterEditMode: function() { - // Notify that we are about to enter in edit mode for current cell. - this.model.trigger('enteringEditMode', [this]); - - Backgrid.Cell.prototype.enterEditMode.apply(this, arguments); - /* Make sure - we listen to the click event */ - this.delegateEvents(); - var editable = Backgrid.callByNeed(this.column.editable(), this.column, this.model); - - if (editable) { - this.$el.html( - '' - ); - this.model.trigger( - 'pg-sub-node:opened', this.model, this - ); - } - }, - render: function() { - this.$el.empty(); - this.$el.html( - '' - ); - this.delegateEvents(); - if (this.grabFocus) - this.$el.trigger('focus'); - return this; - }, - }); - - // Subnode Model - var ActiveQueryDetailsModel = Backbone.Model.extend({ - defaults: { - version: null, - /* Postgres version */ - }, - schema: [{ - id: 'backend_type', - label: gettext('Backend type'), - type: 'text', - editable: true, - readonly: true, - group: gettext('Details'), - visible: function() { - return this.version >= 100000; - }, - }, { - id: 'query_start', - label: gettext('Query started at'), - type: 'text', - editable: false, - readonly: true, - group: gettext('Details'), - }, { - id: 'state_change', - label: gettext('Last state changed at'), - type: 'text', - editable: true, - readonly: true, - group: gettext('Details'), - }, { - id: 'query', - label: gettext('SQL'), - type: 'text', - editable: true, - readonly: true, - control: Backform.SqlFieldControl, - group: gettext('Details'), - }], - }); - - pgAdmin.Dashboard = { - init: function() { - if (this.initialized) - return; - - this.initialized = true; - this.chartsDomObj = null; - - this.sid = this.did = -1; - this.version = -1; - - - // Bind the Dashboard object with the 'object_selected' function - var selected = this.object_selected.bind(this); - var disconnected = this.object_disconnected.bind(this); - - // Listen for selection of any of object - pgBrowser.Events.on('pgadmin-browser:tree:selected', selected); - - // Listen for server disconnected event - pgBrowser.Events.on('pgadmin:server:disconnect', disconnected); - - // Load the default welcome dashboard - var url = url_for('dashboard.index'); - - var dashboardPanel = pgBrowser.panels['dashboard'].panel; - if (dashboardPanel) { - var div = dashboardPanel.layout().scene().find('.pg-panel-content'); - if (div) { - var ajaxHook = function() { - $.ajax({ - url: url, - type: 'GET', - dataType: 'html', - }) - .done(function(data) { - $(div).html(data); - }) - .fail(function(xhr, error) { - self.onFail(xhr, error, div, ajaxHook); - }); - }; - $(div).html( - '' - ); - ajaxHook(); - - // Cache the current IDs for next time - $(dashboardPanel).data('sid', -1); - $(dashboardPanel).data('did', -1); - } - } - }, - - onFail: function(xhr, error, div, ajaxHook) { - Notify.pgNotifier( - error, xhr, - gettext('An error occurred whilst loading the dashboard.'), - function(msg) { - if(msg === 'CRYPTKEY_SET') { - ajaxHook(); - } else { - $(div).html( - '' - ); - } - } - ); - }, - - // Handle Server Disconnect - object_disconnected: function() { - let item = pgBrowser.tree.selected(), - itemData = item && pgBrowser.tree.itemData(item); - - // The server connected may not be the same one, which was selected, and - // we do care out the current selected one only. - if (item.length != 0) { - this.object_selected(item, itemData); - } - }, - - // Handle treeview clicks - object_selected: function(item, itemData) { - let self = this; - - if (itemData && itemData._type) { - var treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item), - url = NodesDashboard.url(itemData, item, treeHierarchy); - - if (url === null) { - url = url_for('dashboard.index'); - self.version = (treeHierarchy.server && treeHierarchy.server.version) || 0; - - cancel_query_url = url + 'cancel_query/'; - terminate_session_url = url + 'terminate_session/'; - - // Check if user is super user - var server = treeHierarchy['server']; - maintenance_database = (server && server.db) || null; - can_signal_backend = (server && server.user) ? server.user.can_signal_backend : false; - - if (server && server.user && server.user.is_superuser) { - is_super_user = true; - } else { - is_super_user = false; - // Set current user - current_user = (server && server.user) ? server.user.name : null; - } - - if ('database' in treeHierarchy) { - self.sid = treeHierarchy.server._id; - self.did = treeHierarchy.database._id; - is_server_dashboard = false; - is_database_dashboard = true; - url += self.sid + '/' + self.did; - cancel_query_url += self.sid + '/' + self.did + '/'; - terminate_session_url += self.sid + '/' + self.did + '/'; - } else if ('server' in treeHierarchy) { - self.sid = treeHierarchy.server._id; - self.did = -1; - is_server_dashboard = true; - is_database_dashboard = false; - url += self.sid; - cancel_query_url += self.sid + '/'; - terminate_session_url += self.sid + '/'; - } else { - is_server_dashboard = is_database_dashboard = false; - } - } else { - is_server_dashboard = is_database_dashboard = false; - } - - var dashboardPanel = pgBrowser.panels['dashboard'].panel; - if (dashboardPanel) { - var div = dashboardPanel.layout().scene().find( - '.pg-panel-content' - ); - - if (div) { - if (itemData.connected || _.isUndefined(itemData.connected)) { - // Avoid unnecessary reloads - if ( - url !== $(dashboardPanel).data('dashboard_url') || ( - url === $(dashboardPanel).data('dashboard_url') && - $(dashboardPanel).data('server_status') == false - ) - ) { - this.chartsDomObj && this.chartsDomObj.unmount(); - $(div).empty(); - - let ajaxHook = function() { - $.ajax({ - url: url, - type: 'GET', - dataType: 'html', - }) - .done(function(data) { - $(div).html(data); - self.init_dashboard(); - }) - .fail(function(xhr, error) { - self.onFail(xhr, error, div, ajaxHook); - }); - }; - $(div).html( - '' - ); - ajaxHook(); - $(dashboardPanel).data('server_status', true); - } - } else { - this.chartsDomObj && this.chartsDomObj.unmount(); - $(div).html( - '' - ); - $(dashboardPanel).data('server_status', false); - } - // Cache the current IDs for next time - $(dashboardPanel).data('dashboard_url', url); - } - } - } - }, - - // Handler function to support the "Add Server" link - add_new_server: function() { - if (pgBrowser && pgBrowser.tree) { - var i = _.isUndefined(pgBrowser.tree.selected()) ? - pgBrowser.tree.first(null, false): - pgBrowser.tree.selected(), - serverModule = require('pgadmin.node.server'), - itemData = pgBrowser.tree.itemData(i); - - while (itemData && itemData._type != 'server_group') { - i = pgBrowser.tree.next(i); - itemData = pgBrowser.tree.itemData(i); - } - - if (!itemData) { - return; - } - - if (serverModule) { - serverModule.callbacks.show_obj_properties.apply( - serverModule, [{ - action: 'create', - }, i] - ); - } - } - }, - - // Render a grid - render_grid: function(container, url, columns) { - var Datum = Backbone.Model.extend({}), - self = this; - - var path = url + self.sid; - if (self.did != -1) { - path += '/' + self.did; - } - - var Data = Backbone.Collection.extend({ - model: Datum, - url: path, - mode: 'client', - }); - - var data = new Data(); - - var HighlightedRow = Backgrid.Row.extend({ - render: function() { - Backgrid.Row.prototype.render.call(this); - var row_type = this.model.get('row_type'); - - if (_.isUndefined(row_type) || _.isNull(row_type)) { - this.$el.removeClass('alert'); - this.$el.removeClass('warning'); - } else if (row_type === 'warning') { - this.$el.addClass('warning'); - } else if (row_type === 'alert') { - this.$el.addClass('alert'); - } - - return this; - } - }); - - // Set up the grid - var grid = new Backgrid.Grid({ - emptyText: gettext('No data found'), - columns: columns, - collection: data, - className: 'backgrid presentation table table-bordered table-noouter-border table-hover', - row: HighlightedRow - }); - - // Render the grid - $(container).empty(); - $(container).append(grid.render().el); - - // Initialize a client-side filter to filter on the client - // mode pageable collection's cache. - var filter = new Backgrid.Extension.ClientSideFilter({ - collection: data, - }); - - filter.setCustomSearchBox($('#txtGridSearch')); - // Stash objects for future use - $(container).data('data', data); - $(container).data('grid', grid); - $(container).data('filter', filter); - }, - __loadMoreRows: function(e) { - let elem = e.currentTarget; - if ((elem.scrollHeight - 10) < elem.scrollTop + elem.offsetHeight) { - if (this.data.length > 0) { - this.local_grid.collection.add(this.data.splice(0, 50)); - } - } - }, - // Render the data in a grid - render_grid_data: function(container) { - var that = this; - var data = $(container).data('data'), - grid = $(container).data('grid'), - filter = $(container).data('filter'); - - if (_.isUndefined(data)) { - return null; - } - - data.fetch({ - reset: true, - success: function(res) { - that.data = res.models; - that.local_grid = grid; - grid.collection.reset(that.data.splice(0,50)); - - // If we're showing an error, remove it, and replace the grid & filter - if ($(container).hasClass('grid-error')) { - $(container).removeClass('grid-error'); - $(container).html(grid.render().el); - $(filter.el).show(); - } - - if(that.data.length > 50) { - // Listen scroll event to load more rows - $('.wcScrollableY').on('scroll', that.__loadMoreRows.bind(that)); - } else { - // Listen scroll event to load more rows - $('.wcScrollableY').off('scroll', that.__loadMoreRows); - } - - // Re-apply search criteria - filter.search(); - }, - error: function(model, xhr) { - let err = ''; - let msg = ''; - let cls = 'info'; - - if (xhr.readyState === 0) { - msg = gettext('Not connected to the server or the connection to the server has been closed.'); - } else { - err = JSON.parse(xhr.responseText); - msg = err.errormsg; - - // If we get a 428, it means the server isn't connected - if (xhr.status === 428) { - if (_.isUndefined(msg) || _.isNull(msg)) { - msg = gettext('Please connect to the selected server to view the table.'); - } - } else { - msg = gettext('An error occurred whilst rendering the table.'); - cls = 'error'; - } - } - - // Replace the content with the error, if not already present. Always update the message - if (!$(container).hasClass('grid-error')) { - $(filter.el).hide(); - $(container).addClass('grid-error'); - } - - $(container).html( - '' - ); - - // Try again - setTimeout(function() { - pgAdmin.Dashboard.render_grid_data(container, data); - }, 5000); - }, - }); - }, - - // Rock n' roll on the dashboard - init_dashboard: function() { - let self = this; - - this.chartsDomObj = new ChartsDOM.default( - document.getElementById('dashboard-graphs'), - self.preferences, - self.sid, - self.did, - $('.dashboard-container')[0].clientHeight <=0 ? false : true - ); - - /* Cache may take time to load for the first time - * Keep trying till available - */ - let cacheIntervalId = setInterval(function() { - try { - if(pgWindow.default.pgAdmin.Browser.preference_version() > 0) { - clearInterval(cacheIntervalId); - self.reflectPreferences(); - } - } - catch(err) { - clearInterval(cacheIntervalId); - throw err; - } - },0); - - /* Register for preference changed event broadcasted */ - pgBrowser.onPreferencesChange('dashboards', function() { - self.reflectPreferences(); - }); - }, - - reflectPreferences: function() { - var self = this; - self.preferences = pgWindow.default.pgAdmin.Browser.get_preferences_for_module('dashboards'); - this.chartsDomObj.reflectPreferences(self.preferences); - - if(is_server_dashboard || is_database_dashboard) { - if (self.preferences.show_activity && $('#dashboard-activity').hasClass('dashboard-hidden')) { - $('#dashboard-activity').removeClass('dashboard-hidden'); - } - else if(!self.preferences.show_activity) { - $('#dashboard-activity').addClass('dashboard-hidden'); - } - - if (self.preferences.show_activity && $('#dashboard-activity').hasClass('dashboard-hidden')) { - $('#dashboard-activity').removeClass('dashboard-hidden'); - } - else if(!self.preferences.show_activity) { - $('#dashboard-activity').addClass('dashboard-hidden'); - } - - /* Dashboard specific preferences can be updated in the - * appropriate functions - */ - if(is_server_dashboard) { - self.reflectPreferencesServer(); - } - else if(is_database_dashboard) { - self.reflectPreferencesDatabase(); - } - } - }, - - renderTab: function(e, tab_grid_map) { - let prevGrid = tab_grid_map[$(e.relatedTarget).attr('aria-controls')]; - $(prevGrid).data('filtertext', $('#txtGridSearch').val()); - - let currGrid = tab_grid_map[$(e.target).attr('aria-controls')]; - $('#txtGridSearch').val($(currGrid).data('filtertext')); - pgAdmin.Dashboard.render_grid_data(currGrid); - }, - - reflectPreferencesServer: function() { - var self = this; - var $dashboardContainer = $('.dashboard-container'); - var div_server_activity = $dashboardContainer.find('#server_activity').get(0); - var div_server_locks = $dashboardContainer.find('#server_locks').get(0); - var div_server_prepared = $dashboardContainer.find('#server_prepared').get(0); - var div_server_config = $dashboardContainer.find('#server_config').get(0); - - var tab_grid_map = { - 'tab_server_activity': div_server_activity, - 'tab_server_locks': div_server_locks, - 'tab_server_prepared': div_server_prepared, - 'tab_server_config': div_server_config, - }; - - // Display server activity - if (self.preferences.show_activity) { - var server_activity_columns = [{ - name: 'pid', - label: gettext('PID'), - editable: false, - cell: 'string', - }, { - name: 'datname', - label: gettext('Database'), - editable: false, - cell: 'string', - }, { - name: 'usename', - label: gettext('User'), - editable: false, - cell: 'string', - }, { - name: 'application_name', - label: gettext('Application'), - editable: false, - cell: 'string', - }, { - name: 'client_addr', - label: gettext('Client'), - editable: false, - cell: 'string', - }, { - name: 'backend_start', - label: gettext('Backend start'), - editable: false, - cell: 'string', - }, { - name: 'state', - label: gettext('State'), - editable: false, - cell: 'string', - }]; - - if (self.version < 90600) { - server_activity_columns = server_activity_columns.concat( - [{ - name: 'waiting', - label: gettext('Waiting?'), - editable: false, - cell: 'string', - }]); - } else { - server_activity_columns = server_activity_columns.concat( - [{ - name: 'wait_event', - label: gettext('Wait event'), - editable: false, - cell: 'string', - }, { - name: 'blocking_pids', - label: gettext('Blocking PIDs'), - editable: false, - cell: 'string', - }]); - } - - var newActiveQueryDetailsModel = new ActiveQueryDetailsModel(); - - var subNodeFieldsModel = Backform.generateViewSchema( - null, newActiveQueryDetailsModel, 'create', null, null, true - ); - - // Add version to each field - _.each(subNodeFieldsModel[0].fields, function(obj) { - obj['version'] = self.version; - }); - - // Add cancel active query button - server_activity_columns.unshift({ - name: 'pg-backform-expand', - label: '', - cell: SessionDetailsCell, - cell_priority: -1, - postgres_version: self.version, - schema: subNodeFieldsModel, - }); - - // Add cancel active query button - server_activity_columns.unshift({ - name: 'pg-backform-delete', - label: '', - cell: customDashboardActionCell, - cell_action: 'cancel', - editable: false, - cell_priority: -1, - canDeleteRow: pgAdmin.Dashboard.can_take_action, - postgres_version: self.version, - }); - - server_activity_columns.unshift({ - name: 'pg-backform-delete', - label: '', - cell: customDashboardActionCell, - cell_action: 'terminate', - editable: false, - cell_priority: -1, - canDeleteRow: pgAdmin.Dashboard.can_take_action, - postgres_version: self.version, - }); - - var server_locks_columns = [{ - name: 'pid', - label: gettext('PID'), - editable: false, - cell: 'string', - }, { - name: 'datname', - label: gettext('Database'), - editable: false, - cell: 'string', - }, { - name: 'locktype', - label: gettext('Lock type'), - editable: false, - cell: 'string', - }, { - name: 'relation', - label: gettext('Target relation'), - editable: false, - cell: 'string', - }, { - name: 'page', - label: gettext('Page'), - editable: false, - cell: 'string', - }, { - name: 'tuple', - label: gettext('Tuple'), - editable: false, - cell: 'string', - }, { - name: 'virtualxid', - label: gettext('vXID (target)'), - editable: false, - cell: 'string', - }, { - name: 'transactionid', - label: gettext('XID (target)'), - editable: false, - cell: 'string', - }, { - name: 'classid', - label: gettext('Class'), - editable: false, - cell: 'string', - }, { - name: 'objid', - label: gettext('Object ID'), - editable: false, - cell: 'string', - }, { - name: 'virtualtransaction', - label: gettext('vXID (owner)'), - editable: false, - cell: 'string', - }, { - name: 'mode', - label: gettext('Mode'), - editable: false, - cell: 'string', - }, { - name: 'granted', - label: gettext('Granted?'), - editable: false, - cell: 'string', - }]; - - var server_prepared_columns = [{ - name: 'git', - label: gettext('Name'), - editable: false, - cell: 'string', - }, { - name: 'database', - label: gettext('Database'), - editable: false, - cell: 'string', - }, { - name: 'Owner', - label: gettext('Owner'), - editable: false, - cell: 'string', - }, { - name: 'transaction', - label: gettext('XID'), - editable: false, - cell: 'string', - }, { - name: 'prepared', - label: gettext('Prepared at'), - editable: false, - cell: 'string', - }]; - - var server_config_columns = [{ - name: 'name', - label: gettext('Name'), - editable: false, - cell: 'string', - }, { - name: 'category', - label: gettext('Category'), - editable: false, - cell: 'string', - }, { - name: 'setting', - label: gettext('Setting'), - editable: false, - cell: 'string', - }, { - name: 'unit', - label: gettext('Unit'), - editable: false, - cell: 'string', - }, { - name: 'short_desc', - label: gettext('Description'), - editable: false, - cell: 'string', - }]; - - // To align subnode controls properly - $(div_server_activity).addClass('pg-el-container'); - $(div_server_activity).attr('el', 'sm'); - - // Render the tabs, but only get data for the activity tab for now - pgAdmin.Dashboard.render_grid( - div_server_activity, url_for('dashboard.activity'), server_activity_columns - ); - pgAdmin.Dashboard.render_grid( - div_server_locks, url_for('dashboard.locks'), server_locks_columns - ); - pgAdmin.Dashboard.render_grid( - div_server_prepared, url_for('dashboard.prepared'), server_prepared_columns - ); - pgAdmin.Dashboard.render_grid( - div_server_config, url_for('dashboard.config'), server_config_columns - ); - - pgAdmin.Dashboard.render_grid_data(div_server_activity); - - // (Re)render the appropriate tab - $('a[data-toggle="tab"]').on('shown.bs.tab', function(e) { - self.renderTab(e, tab_grid_map); - }); - - $('#btn_refresh').off('click').on('click', () => { - let currGrid = tab_grid_map[$('#dashboard-activity .nav-tabs .active').attr('aria-controls')]; - pgAdmin.Dashboard.render_grid_data(currGrid); - }); - } - }, - reflectPreferencesDatabase: function() { - var self = this; - var div_database_activity = document.getElementById('database_activity'); - var div_database_locks = document.getElementById('database_locks'); - var div_database_prepared = document.getElementById('database_prepared'); - - var tab_grid_map = { - 'tab_database_activity': div_database_activity, - 'tab_database_locks': div_database_locks, - 'tab_database_prepared': div_database_prepared, - }; - - // Display server activity - if (self.preferences.show_activity) { - var database_activity_columns = [{ - name: 'pid', - label: gettext('PID'), - editable: false, - cell: 'string', - }, { - name: 'usename', - label: gettext('User'), - editable: false, - cell: 'string', - }, { - name: 'application_name', - label: gettext('Application'), - editable: false, - cell: 'string', - }, { - name: 'client_addr', - label: gettext('Client'), - editable: false, - cell: 'string', - }, { - name: 'backend_start', - label: gettext('Backend start'), - editable: false, - cell: 'string', - }, { - name: 'state', - label: gettext('State'), - editable: false, - cell: 'string', - }]; - - if (self.version < 90600) { - database_activity_columns = database_activity_columns.concat( - [{ - name: 'waiting', - label: gettext('Waiting?'), - editable: false, - cell: 'string', - }]); - } else { - database_activity_columns = database_activity_columns.concat( - [{ - name: 'wait_event', - label: gettext('Wait event'), - editable: false, - cell: 'string', - }, { - name: 'blocking_pids', - label: gettext('Blocking PIDs'), - editable: false, - cell: 'string', - }]); - } - - var newActiveQueryDetailsModel = new ActiveQueryDetailsModel(); - - var subNodeFieldsModel = Backform.generateViewSchema( - null, newActiveQueryDetailsModel, 'create', null, null, true - ); - - // Add version to each field - _.each(subNodeFieldsModel[0].fields, function(obj) { - obj['version'] = self.version; - }); - - // Add cancel active query button - database_activity_columns.unshift({ - name: 'pg-backform-expand', - label: '', - cell: SessionDetailsCell, - cell_priority: -1, - postgres_version: self.version, - schema: subNodeFieldsModel, - }); - - database_activity_columns.unshift({ - name: 'pg-backform-delete', - label: '', - cell: customDashboardActionCell, - cell_action: 'cancel', - editable: false, - cell_priority: -1, - canDeleteRow: pgAdmin.Dashboard.can_take_action, - postgres_version: self.version, - }); - database_activity_columns.unshift({ - name: 'pg-backform-delete', - label: '', - cell: customDashboardActionCell, - cell_action: 'terminate', - editable: false, - cell_priority: -1, - canDeleteRow: pgAdmin.Dashboard.can_take_action, - postgres_version: self.version, - }); - - var database_locks_columns = [{ - name: 'pid', - label: gettext('PID'), - editable: false, - cell: 'string', - }, { - name: 'locktype', - label: gettext('Lock type'), - editable: false, - cell: 'string', - }, { - name: 'relation', - label: gettext('Target relation'), - editable: false, - cell: 'string', - }, { - name: 'page', - label: gettext('Page'), - editable: false, - cell: 'string', - }, { - name: 'tuple', - label: gettext('Tuple'), - editable: false, - cell: 'string', - }, { - name: 'virtualxid', - label: gettext('vXID (target)'), - editable: false, - cell: 'string', - }, { - name: 'transactionid', - label: gettext('XID (target)'), - editable: false, - cell: 'string', - }, { - name: 'classid', - label: gettext('Class'), - editable: false, - cell: 'string', - }, { - name: 'objid', - label: gettext('Object ID'), - editable: false, - cell: 'string', - }, { - name: 'virtualtransaction', - label: gettext('vXID (owner)'), - editable: false, - cell: 'string', - }, { - name: 'mode', - label: gettext('Mode'), - editable: false, - cell: 'string', - }, { - name: 'granted', - label: gettext('Granted?'), - editable: false, - cell: 'string', - }]; - - var database_prepared_columns = [{ - name: 'git', - label: gettext('Name'), - editable: false, - cell: 'string', - }, { - name: 'Owner', - label: gettext('Owner'), - editable: false, - cell: 'string', - }, { - name: 'transaction', - label: gettext('XID'), - editable: false, - cell: 'string', - }, { - name: 'prepared', - label: gettext('Prepared at'), - editable: false, - cell: 'string', - }]; - - // To align subnode controls properly - $(div_database_activity).addClass('pg-el-container'); - $(div_database_activity).attr('el', 'sm'); - - // Render the tabs, but only get data for the activity tab for now - pgAdmin.Dashboard.render_grid( - div_database_activity, url_for('dashboard.activity'), database_activity_columns - ); - pgAdmin.Dashboard.render_grid( - div_database_locks, url_for('dashboard.locks'), database_locks_columns - ); - pgAdmin.Dashboard.render_grid( - div_database_prepared, url_for('dashboard.prepared'), database_prepared_columns - ); - - pgAdmin.Dashboard.render_grid_data(div_database_activity); - - // (Re)render the appropriate tab - $('a[data-toggle="tab"]').on('shown.bs.tab', function(e) { - self.renderTab(e, tab_grid_map); - }); - - $('#btn_refresh').off('click').on('click', () => { - let currGrid = tab_grid_map[$('#dashboard-activity .nav-tabs .active').attr('aria-controls')]; - pgAdmin.Dashboard.render_grid_data(currGrid); - }); - } - }, - toggleVisibility: function(visible, closed=false) { - dashboardVisible = visible; - if(closed) { - this.chartsDomObj && this.chartsDomObj.unmount(); - } else { - var t = pgBrowser.tree, - i = t ? t.selected() : 0, - d = i && t.itemData(i); - - this.chartsDomObj && this.chartsDomObj.setPageVisible(dashboardVisible); - this.object_selected(i, d); - } - }, - can_take_action: function(m) { - // We will validate if user is allowed to cancel the active query - // If there is only one active session means it probably our main - // connection session - var active_sessions = m.collection.where({ - 'state': 'active', - }), - pg_version = this.get('postgres_version') || null, - cell_action = this.get('cell_action') || null, - is_cancel_session = cell_action === 'cancel', - txtMessage; - - // With PG10, We have background process showing on dashboard - // We will not allow user to cancel them as they will fail with error - // anyway, so better usability we will throw our on notification - - // Background processes do not have database field populated - if (pg_version && pg_version >= 100000 && !m.get('datname')) { - if (is_cancel_session) { - txtMessage = gettext('You cannot cancel background worker processes.'); - } else { - txtMessage = gettext('You cannot terminate background worker processes.'); - } - Notify.info(txtMessage); - return false; - // If it is the last active connection on maintenance db then error out - } else if (maintenance_database == m.get('datname') && - m.get('state') == 'active' && active_sessions.length == 1) { - if (is_cancel_session) { - txtMessage = gettext('You are not allowed to cancel the main active session.'); - } else { - txtMessage = gettext('You are not allowed to terminate the main active session.'); - } - Notify.error(txtMessage); - return false; - } else if (is_cancel_session && m.get('state') == 'idle') { - // If this session is already idle then do nothing - Notify.info( - gettext('The session is already in idle state.') - ); - return false; - } else if (can_signal_backend) { - // user with membership of 'pg_signal_backend' can terminate the session of non admin user. - return true; - } else if (is_super_user) { - // Super user can do anything - return true; - } else if (current_user && current_user == m.get('usename')) { - // Non-super user can cancel only their active queries - return true; - } else { - // Do not allow to cancel someone else session to non-super user - if (is_cancel_session) { - txtMessage = gettext('Superuser privileges are required to cancel another users query.'); - } else { - txtMessage = gettext('Superuser privileges are required to terminate another users query.'); - } - Notify.error(txtMessage); - return false; - } - }, - }; - - return pgAdmin.Dashboard; -}); diff --git a/web/pgadmin/dashboard/static/js/dashboard_components.jsx b/web/pgadmin/dashboard/static/js/dashboard_components.jsx deleted file mode 100644 index a723dd242..000000000 --- a/web/pgadmin/dashboard/static/js/dashboard_components.jsx +++ /dev/null @@ -1,74 +0,0 @@ -///////////////////////////////////////////////////////////// -// -// pgAdmin 4 - PostgreSQL Tools -// -// Copyright (C) 2013 - 2022, The pgAdmin Development Team -// This software is released under the PostgreSQL Licence -// -////////////////////////////////////////////////////////////// -import React from 'react'; -import PropTypes from 'prop-types'; - -export function ChartContainer(props) { - return ( -
-
-
-
{props.title}
-
-
-
-
-
- {props.children} -
- -
-
- ); -} - -ChartContainer.propTypes = { - id: PropTypes.string.isRequired, - title: PropTypes.string.isRequired, - legendRef: PropTypes.oneOfType([ - PropTypes.func, - PropTypes.shape({ current: PropTypes.any }), - ]).isRequired, - children: PropTypes.node.isRequired, - errorMsg: PropTypes.string, -}; - -export function ChartError(props) { - if(props.message === null) { - return <>; - } - return ( -
{props.message}
- ); -} - -ChartError.propTypes = { - message: PropTypes.string, -}; - -export function DashboardRow({children}) { - return ( -
{children}
- ); -} -DashboardRow.propTypes = { - children: PropTypes.node.isRequired, -}; - -export function DashboardRowCol({breakpoint, parts, children}) { - return ( -
{children}
- ); -} - -DashboardRowCol.propTypes = { - breakpoint: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']).isRequired, - parts: PropTypes.number.isRequired, - children: PropTypes.node.isRequired, -}; diff --git a/web/pgadmin/dashboard/templates/dashboard/database_dashboard.html b/web/pgadmin/dashboard/templates/dashboard/database_dashboard.html deleted file mode 100644 index 148ce96ab..000000000 --- a/web/pgadmin/dashboard/templates/dashboard/database_dashboard.html +++ /dev/null @@ -1,59 +0,0 @@ -
-
-
-
- {{ _('Server activity') }} -
-
-
- -
- -
-
- - - - -
-
-
-
-
-
-
-
-
-
-
-
-
- -
diff --git a/web/pgadmin/dashboard/templates/dashboard/server_dashboard.html b/web/pgadmin/dashboard/templates/dashboard/server_dashboard.html deleted file mode 100644 index 874a1e206..000000000 --- a/web/pgadmin/dashboard/templates/dashboard/server_dashboard.html +++ /dev/null @@ -1,67 +0,0 @@ -
-
-
-
-
- {{ _('Server activity') }} -
-
-
- -
- -
-
- - - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
diff --git a/web/pgadmin/dashboard/templates/dashboard/sql/10_plus/activity.sql b/web/pgadmin/dashboard/templates/dashboard/sql/10_plus/activity.sql index a9379f67b..d02d071fc 100644 --- a/web/pgadmin/dashboard/templates/dashboard/sql/10_plus/activity.sql +++ b/web/pgadmin/dashboard/templates/dashboard/sql/10_plus/activity.sql @@ -12,6 +12,7 @@ SELECT query, pg_catalog.to_char(state_change, 'YYYY-MM-DD HH24:MI:SS TZ') AS state_change, pg_catalog.to_char(query_start, 'YYYY-MM-DD HH24:MI:SS TZ') AS query_start, + pg_catalog.to_char(xact_start, 'YYYY-MM-DD HH24:MI:SS TZ') AS xact_start, backend_type, CASE WHEN state = 'active' THEN ROUND((extract(epoch from now() - query_start) / 60)::numeric, 2) ELSE 0 END AS active_since FROM diff --git a/web/pgadmin/dashboard/templates/dashboard/sql/9.6_plus/activity.sql b/web/pgadmin/dashboard/templates/dashboard/sql/9.6_plus/activity.sql index b0a9c5847..67cb4588f 100644 --- a/web/pgadmin/dashboard/templates/dashboard/sql/9.6_plus/activity.sql +++ b/web/pgadmin/dashboard/templates/dashboard/sql/9.6_plus/activity.sql @@ -11,6 +11,7 @@ SELECT pg_catalog.pg_blocking_pids(pid) AS blocking_pids, query, pg_catalog.to_char(state_change, 'YYYY-MM-DD HH24:MI:SS TZ') AS state_change, + pg_catalog.to_char(xact_start, 'YYYY-MM-DD HH24:MI:SS TZ') AS xact_start, pg_catalog.to_char(query_start, 'YYYY-MM-DD HH24:MI:SS TZ') AS query_start, CASE WHEN state = 'active' THEN ROUND((extract(epoch from now() - query_start) / 60)::numeric, 2) ELSE 0 END AS active_since FROM diff --git a/web/pgadmin/dashboard/templates/dashboard/sql/default/activity.sql b/web/pgadmin/dashboard/templates/dashboard/sql/default/activity.sql index 494b5adbb..3e6cf81b0 100644 --- a/web/pgadmin/dashboard/templates/dashboard/sql/default/activity.sql +++ b/web/pgadmin/dashboard/templates/dashboard/sql/default/activity.sql @@ -10,6 +10,7 @@ SELECT CASE WHEN waiting THEN '{{ _('yes') }}' ELSE '{{ _('no') }}' END AS waiting, query, pg_catalog.to_char(state_change, 'YYYY-MM-DD HH24:MI:SS TZ') AS state_change, + pg_catalog.to_char(xact_start, 'YYYY-MM-DD HH24:MI:SS TZ') AS xact_start, pg_catalog.to_char(query_start, 'YYYY-MM-DD HH24:MI:SS TZ') AS query_start, CASE WHEN state = 'active' THEN ROUND((extract(epoch from now() - query_start) / 60)::numeric, 2) ELSE 0 END AS active_since FROM diff --git a/web/pgadmin/dashboard/templates/dashboard/welcome_dashboard.html b/web/pgadmin/dashboard/templates/dashboard/welcome_dashboard.html deleted file mode 100644 index fc798ab19..000000000 --- a/web/pgadmin/dashboard/templates/dashboard/welcome_dashboard.html +++ /dev/null @@ -1,135 +0,0 @@ -
-
-
-
-
-
{{ _('Welcome') }}
-
- -

{{ _('Feature rich') }} | {{ _('Maximises PostgreSQL') }} | {{ _('Open Source') }}

-

- {{ _('pgAdmin is an Open Source administration and management tool for the PostgreSQL database. It includes a graphical administration interface, an SQL query tool, a procedural code debugger and much more. The tool is designed to answer the needs of developers, DBAs and system administrators alike.') }} -

-
-
-
-
-
-
-
-
{{ _('Quick Links') }}
- -
-
-
- -
-
diff --git a/web/pgadmin/misc/dependencies/static/js/Dependencies.jsx b/web/pgadmin/misc/dependencies/static/js/Dependencies.jsx index ee7ea6e46..ccb605d67 100644 --- a/web/pgadmin/misc/dependencies/static/js/Dependencies.jsx +++ b/web/pgadmin/misc/dependencies/static/js/Dependencies.jsx @@ -16,6 +16,7 @@ import Notify from '../../../../static/js/helpers/Notifier'; import getApiInstance from 'sources/api_instance'; import { makeStyles } from '@material-ui/core/styles'; import { getURL } from '../../../static/utils/utils'; +import Loader from 'sources/components/Loader'; const useStyles = makeStyles((theme) => ({ emptyPanel: { @@ -71,7 +72,7 @@ function parseData(data, node) { export default function Dependencies({ nodeData, item, node, ...props }) { const classes = useStyles(); const [tableData, setTableData] = React.useState([]); - + const [loaderText, setLoaderText] = React.useState(''); const [msg, setMsg] = React.useState(''); var columns = [ { @@ -79,14 +80,14 @@ export default function Dependencies({ nodeData, item, node, ...props }) { accessor: 'type', sortble: true, resizable: false, - disableGlobalFilter: true, + disableGlobalFilter: false, }, { Header: 'Name', accessor: 'name', sortble: true, resizable: false, - disableGlobalFilter: true, + disableGlobalFilter: false, }, { Header: 'Restriction', @@ -114,7 +115,7 @@ export default function Dependencies({ nodeData, item, node, ...props }) { ); if (node.hasDepends) { const api = getApiInstance(); - + setLoaderText('Loading...'); api({ url: url, type: 'GET', @@ -123,8 +124,10 @@ export default function Dependencies({ nodeData, item, node, ...props }) { if (res.data.length > 0) { let data = parseData(res.data, node); setTableData(data); + setLoaderText(''); } else { setMsg(message); + setLoaderText(''); } }) .catch((e) => { @@ -157,10 +160,12 @@ export default function Dependencies({ nodeData, item, node, ...props }) { > ) : (
-
- - {gettext(msg)} -
+ {loaderText ? () : +
+ + {gettext(msg)} +
+ }
)} diff --git a/web/pgadmin/misc/dependents/static/js/Dependents.jsx b/web/pgadmin/misc/dependents/static/js/Dependents.jsx index 487e2d29b..867368b97 100644 --- a/web/pgadmin/misc/dependents/static/js/Dependents.jsx +++ b/web/pgadmin/misc/dependents/static/js/Dependents.jsx @@ -16,6 +16,7 @@ import Notify from '../../../../static/js/helpers/Notifier'; import getApiInstance from 'sources/api_instance'; import { makeStyles } from '@material-ui/core/styles'; import { getURL } from '../../../static/utils/utils'; +import Loader from 'sources/components/Loader'; const useStyles = makeStyles((theme) => ({ emptyPanel: { @@ -71,7 +72,7 @@ function parseData(data, node) { export default function Dependents({ nodeData, item, node, ...props }) { const classes = useStyles(); const [tableData, setTableData] = React.useState([]); - + const [loaderText, setLoaderText] = React.useState(''); const [msg, setMsg] = React.useState(''); var columns = [ @@ -80,14 +81,14 @@ export default function Dependents({ nodeData, item, node, ...props }) { accessor: 'type', sortble: true, resizable: false, - disableGlobalFilter: true, + disableGlobalFilter: false, }, { Header: 'Name', accessor: 'name', sortble: true, resizable: false, - disableGlobalFilter: true, + disableGlobalFilter: false, }, { Header: 'Restriction', @@ -115,6 +116,7 @@ export default function Dependents({ nodeData, item, node, ...props }) { ); if (node.hasDepends && !nodeData.is_collection) { const api = getApiInstance(); + setLoaderText('Loading...'); api({ url: url, type: 'GET', @@ -125,6 +127,7 @@ export default function Dependents({ nodeData, item, node, ...props }) { setTableData(data); } else { setMsg(message); + setLoaderText(''); } }) .catch((e) => { @@ -158,11 +161,15 @@ export default function Dependents({ nodeData, item, node, ...props }) { > ) : (
-
- - {gettext(msg)} -
+ {loaderText ? () : + +
+ + {gettext(msg)} +
+ }
+ )} ); diff --git a/web/pgadmin/misc/properties/CollectionNodeProperties.jsx b/web/pgadmin/misc/properties/CollectionNodeProperties.jsx new file mode 100644 index 000000000..db20331a9 --- /dev/null +++ b/web/pgadmin/misc/properties/CollectionNodeProperties.jsx @@ -0,0 +1,331 @@ +///////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2022, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +////////////////////////////////////////////////////////////// +import React from 'react'; +import pgAdmin from 'sources/pgadmin'; +import getApiInstance from 'sources/api_instance'; +import { makeStyles } from '@material-ui/core/styles'; +import { Box, Switch } from '@material-ui/core'; +import { generateCollectionURL } from '../../browser/static/js/node_ajax'; +import Notify from '../../static/js/helpers/Notifier'; +import gettext from 'sources/gettext'; +import 'wcdocker'; +import PgTable from 'sources/components/PgTable'; +import Theme from 'sources/Theme'; +import PropTypes from 'prop-types'; +import { PgIconButton } from '../../static/js/components/Buttons'; + +const useStyles = makeStyles((theme) => ({ + emptyPanel: { + minHeight: '100%', + minWidth: '100%', + background: theme.palette.grey[400], + overflow: 'auto', + padding: '7.5px', + }, + panelIcon: { + width: '80%', + margin: '0 auto', + marginTop: '25px !important', + position: 'relative', + textAlign: 'center', + }, + panelMessage: { + marginLeft: '0.5rem', + fontSize: '0.875rem', + }, + searchPadding: { + flex: 2.5 + }, + searchInput: { + flex: 1, + margin: '4 0 4 0', + borderLeft: 'none', + paddingLeft: 5 + }, + propertiesPanel: { + height: '100%' + }, + autoResizer: { + height: '100% !important', + width: '100% !important', + background: theme.palette.grey[400], + padding: '8px', + }, + dropButton: { + marginRight: '5px !important' + }, + readOnlySwitch: { + opacity: 0.75, + '& .MuiSwitch-track': { + opacity: theme.palette.action.disabledOpacity, + } + } +})); + +export function CollectionNodeView({ + node, + treeNodeInfo, + itemNodeData, + item, + pgBrowser +}) { + const classes = useStyles(); + + const [data, setData] = React.useState([]); + const [infoMsg, setInfoMsg] = React.useState('Please select an object in the tree view.'); + const [selectedObject, setSelectedObject] = React.useState([]); + const [reload, setReload] = React.useState(); + + const [pgTableColumns, setPgTableColumns] = React.useState([ + { + Header: 'properties', + accessor: 'Properties', + sortble: true, + resizable: false, + disableGlobalFilter: false, + }, + { + Header: 'value', + accessor: 'value', + sortble: true, + resizable: false, + disableGlobalFilter: false, + }, + ]); + + const getTableSelectedRows = (selRows) => { + setSelectedObject(selRows); + }; + + const onDrop = (type) => { + let selRowModels = selectedObject, + selRows = [], + selItem = pgBrowser.tree.selected(), + selectedItemData = selItem ? pgBrowser.tree.itemData(selItem) : null, + selNode = selectedItemData && pgBrowser.Nodes[selectedItemData._type], + url = undefined, + msg = undefined, + title = undefined; + + if (selNode && selNode.type && selNode.type == 'coll-constraints') { + // In order to identify the constraint type, the type should be passed to the server + selRows = selRowModels.map((row) => ({ + id: row.get('oid'), + _type: row.get('_type'), + })); + } else { + selRows = selRowModels.map((row) => row.original.oid); + } + + if (selRows.length === 0) { + Notify.alert( + gettext('Drop Multiple'), + gettext('Please select at least one object to delete.') + ); + return; + } + + if (!selNode) return; + + if (type === 'dropCascade') { + url = selNode.generate_url(selItem, 'delete'); + msg = gettext( + 'Are you sure you want to drop all the selected objects and all the objects that depend on them?' + ); + title = gettext('DROP CASCADE multiple objects?'); + } else { + url = selNode.generate_url(selItem, 'drop'); + msg = gettext('Are you sure you want to drop all the selected objects?'); + title = gettext('DROP multiple objects?'); + } + + const api = getApiInstance(); + let dropNodeProperties = function () { + api + .delete(url, { + data: JSON.stringify({ ids: selRows }), + contentType: 'application/json; charset=utf-8', + }) + .then(function (res) { + if (res.success == 0) { + pgBrowser.report_error(res.errormsg, res.info); + } else { + pgBrowser.Events.trigger( + 'pgadmin:browser:tree:refresh', + selItem || pgBrowser.tree.selected(), + { + success: function () { + pgBrowser.tree.select(selItem); + selNode.callbacks.selected.apply(selNode, [selItem]); + }, + } + ); + } + setReload(true); + }) + .catch(function (error) { + Notify.error( + gettext('Error dropping %s', selectedItemData._label.toLowerCase()), + error.message + ); + }); + }; + + if (confirm) { + Notify.confirm(title, msg, dropNodeProperties, null); + } else { + dropNodeProperties(); + } + }; + + React.useEffect(() => { + if (node){ + + let nodeObj = + pgAdmin.Browser.Nodes[itemNodeData?._type.replace('coll-', '')]; + + let schema = nodeObj.getSchema.call(nodeObj, treeNodeInfo, itemNodeData); + let url = generateCollectionURL.call(nodeObj, item, 'properties'); + + const api = getApiInstance(); + + let tableColumns = []; + var column = {}; + + if (itemNodeData._type.indexOf('coll-') > -1) { + schema.fields.forEach((field) => { + if (node.columns.indexOf(field.id) > -1) { + if (field.label.indexOf('?') > -1) { + column = { + Header: field.label, + accessor: field.id, + sortble: true, + resizable: false, + disableGlobalFilter: false, + // eslint-disable-next-line react/display-name + Cell: ({ value }) => { + return (); + } + }; + } else { + column = { + Header: field.label, + accessor: field.id, + sortble: true, + resizable: false, + disableGlobalFilter: false, + }; + } + tableColumns.push(column); + } + }); + api({ + url: url, + type: 'GET', + }) + .then((res) => { + res.data.forEach((element) => { + element['icon'] = ''; + }); + setPgTableColumns(tableColumns); + setData(res.data); + setInfoMsg('No properties are available for the selected object.'); + }) + .catch((err) => { + Notify.alert( + gettext('Failed to retrieve data from the server.'), + gettext(err.message) + ); + }); + } + } + }, [itemNodeData, node, item, reload]); + + const customHeader = () => { + return ( + + + + ); + }; + + return ( + + + {data.length > 0 ? + ( + + ) + : + ( +
+
+ + {gettext(infoMsg)} +
+
+ + ) + } +
+
+ ); +} + +CollectionNodeView.propTypes = { + node: PropTypes.func, + itemData: PropTypes.object, + itemNodeData: PropTypes.object, + treeNodeInfo: PropTypes.object, + item: PropTypes.object, + pgBrowser: PropTypes.object, + preferences: PropTypes.object, + sid: PropTypes.number, + did: PropTypes.number, + row: PropTypes.object, + serverConnected: PropTypes.bool, + value: PropTypes.bool, +}; diff --git a/web/pgadmin/misc/sql/static/js/SQL.jsx b/web/pgadmin/misc/sql/static/js/SQL.jsx new file mode 100644 index 000000000..5eec57e8d --- /dev/null +++ b/web/pgadmin/misc/sql/static/js/SQL.jsx @@ -0,0 +1,114 @@ +///////////////////////////////////////////////////////////// +// +// pgAdmin 4 - PostgreSQL Tools +// +// Copyright (C) 2013 - 2022, The pgAdmin Development Team +// This software is released under the PostgreSQL Licence +// +////////////////////////////////////////////////////////////// + +import React, { useEffect } from 'react'; +import { generateNodeUrl } from '../../../../browser/static/js/node_ajax'; +import gettext from 'sources/gettext'; +import PropTypes from 'prop-types'; +import Notify from '../../../../static/js/helpers/Notifier'; +import getApiInstance from 'sources/api_instance'; +import { makeStyles } from '@material-ui/core/styles'; +import CodeMirror from '../../../../static/js/components/CodeMirror'; + +const useStyles = makeStyles((theme) => ({ + textArea: { + height: '100% !important', + width: '100% !important', + background: theme.palette.grey[400], + overflow: 'auto !important', + minHeight: '100%', + minWidth: '100%', + }, +})); + +export default function SQL({ nodeData, node, ...props }) { + const classes = useStyles(); + const [nodeSQL, setNodeSQL] = React.useState(''); + + const [msg, setMsg] = React.useState(''); + + useEffect(() => { + var sql = '-- ' + gettext('Please select an object in the tree view.'); + if (node) { + let url = generateNodeUrl.call( + node, + props.treeNodeInfo, + 'sql', + nodeData, + true, + node.url_jump_after_node + ); + sql = + '-- ' + gettext('No SQL could be generated for the selected object.'); + + if (node.hasSQL) { + const api = getApiInstance(); + + api({ + url: url, + type: 'GET', + }) + .then((res) => { + if (res.data.length > 0) { + setNodeSQL(res.data); + } else { + setMsg(sql); + } + }) + .catch((e) => { + Notify.alert( + gettext('Failed to retrieve data from the server.'), + gettext(e.message) + ); + // show failed message. + setMsg(gettext('Failed to retrieve data from the server.')); + }); + } + } + if (sql != '') { + setMsg(sql); + } + return () => { + setNodeSQL([]); + }; + }, [nodeData]); + + return ( + <> + {nodeSQL.length > 0 ? ( + + ) : ( + + )} + + ); +} + +SQL.propTypes = { + res: PropTypes.array, + nodeData: PropTypes.object, + treeNodeInfo: PropTypes.object, + node: PropTypes.func, +}; diff --git a/web/pgadmin/misc/sql/static/js/sql.js b/web/pgadmin/misc/sql/static/js/sql.js deleted file mode 100644 index 57ee3129a..000000000 --- a/web/pgadmin/misc/sql/static/js/sql.js +++ /dev/null @@ -1,207 +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 '../../../../static/js/helpers/Notifier'; - -define('misc.sql', [ - 'sources/gettext', 'underscore', 'jquery', - 'sources/pgadmin', 'pgadmin.browser', 'pgadmin.alertifyjs', -], function(gettext, _, $, pgAdmin, pgBrowser, Alertify) { - - pgBrowser.ShowNodeSQL = pgBrowser.ShowNodeSQL || {}; - - if (pgBrowser.ShowNodeSQL.initialized) { - return pgBrowser.ShowNodeSQL; - } - var wcDocker = window.wcDocker; - - _.extend(pgBrowser.ShowNodeSQL, { - init: function() { - if (this.initialized) { - return; - } - this.initialized = true; - _.bindAll(this, 'showSQL', 'sqlPanelVisibilityChanged'); - - var sqlPanels; - this.sqlPanels = sqlPanels = pgBrowser.docker.findPanels('sql'); - - // We will listend to the visibility change of the SQL panel - pgBrowser.Events.on( - 'pgadmin-browser:panel-sql:' + wcDocker.EVENT.VISIBILITY_CHANGED, - this.sqlPanelVisibilityChanged - ); - - pgBrowser.Events.on( - 'pgadmin:browser:node:updated', - function() { - if (this.sqlPanels && this.sqlPanels.length) { - $(this.sqlPanels[0]).data('node-prop', ''); - this.sqlPanelVisibilityChanged(this.sqlPanels[0]); - } - }, this - ); - - // Hmm.. Did we find the SQL panel, and is it visible (opened)? - // If that is the case - we need to listen the browser tree selection - // events. - if (sqlPanels.length == 0) { - pgBrowser.Events.on( - 'pgadmin-browser:panel-sql:' + wcDocker.EVENT.INIT, - function() { - if ((sqlPanels[0].isVisible()) || sqlPanels.length != 1) { - pgBrowser.Events.on( - 'pgadmin-browser:tree:selected', this.showSQL - ); - pgBrowser.Events.on( - 'pgadmin-browser:tree:reactSelected', this.reactShowSQL - ); - pgBrowser.Events.on( - 'pgadmin-browser:tree:refreshing', this.refreshSQL, this - ); - } - }.bind(this) - ); - } else { - if ((sqlPanels[0].isVisible()) || sqlPanels.length != 1) { - pgBrowser.Events.on('pgadmin-browser:tree:selected', this.showSQL); - pgBrowser.Events.on('pgadmin-browser:tree:reactSelected', this.reactShowSQL); - pgBrowser.Events.on( - 'pgadmin-browser:tree:refreshing', this.refreshSQL, this - ); - } - } - }, - refreshSQL: function(item, data, node) { - var that = this, - cache_flag = { - node_type: data._type, - url: node.generate_url(item, 'sql', data, true), - }; - - if (_.isEqual($(that.sqlPanels[0]).data('node-prop'), cache_flag)) { - // Reset the current item selection - $(that.sqlPanels[0]).data('node-prop', ''); - that.showSQL(item, data, node); - } - }, - showSQL: function(item, data, node) { - /** - * We can't start fetching the SQL immediately, it is possible - the user - * is just using keyboards to select the node, and just traversing - * through. We will wait for some time before fetching the Reversed - * Engineering SQL. - **/ - - this.timeout && clearTimeout(this.timeout); - - var that = this; - this.timeout = setTimeout( - function() { - var sql = '-- ' + gettext('Please select an object in the tree view.'); - if (node) { - sql = '-- ' + gettext('No SQL could be generated for the selected object.'); - var n_type = data._type, - url = node.generate_url(item, 'sql', data, true), - treeHierarchy = pgBrowser.tree.getTreeNodeHierarchy(item), - cache_flag = { - node_type: n_type, - url: url, - }; - - // Avoid unnecessary reloads - if (_.isEqual($(that.sqlPanels[0]).data('node-prop'), cache_flag)) { - return; - } - // Cache the current IDs for next time - $(that.sqlPanels[0]).data('node-prop', cache_flag); - - if (node.hasSQL) { - - sql = ''; - var timer; - var ajaxHook = function() { - $.ajax({ - url: url, - type: 'GET', - beforeSend: function(xhr) { - xhr.setRequestHeader( - pgAdmin.csrf_token_header, pgAdmin.csrf_token - ); - // Generate a timer for the request - timer = setTimeout(function() { - // Notify user if request is taking longer than 1 second - pgAdmin.Browser.editor.setValue( - gettext('Retrieving data from the server...') - ); - }, 1000); - }, - }).done(function(res) { - if (pgAdmin.Browser.editor.getValue() != res) { - pgAdmin.Browser.editor.setValue(res); - } - clearTimeout(timer); - }).fail(function(xhr, error, message) { - var _label = treeHierarchy[n_type].label; - pgBrowser.Events.trigger( - 'pgadmin:node:retrieval:error', 'sql', xhr, error, message, item - ); - if (!Alertify.pgHandleItemError(xhr, error, message, { - item: item, - info: treeHierarchy, - })) { - Notify.pgNotifier( - error, xhr, - gettext('Error retrieving the information - %s', message || _label), - function(msg) { - if(msg === 'CRYPTKEY_SET') { - ajaxHook(); - } else { - console.warn(arguments); - } - } - ); - } - }); - }; - ajaxHook(); - } - } - - if (sql != '') { - pgAdmin.Browser.editor.setValue(sql); - } - }, 400); - }, - sqlPanelVisibilityChanged: function(panel) { - if (panel.isVisible()) { - var t = pgBrowser.tree, - i = t.selected(), - d = i && t.itemData(i), - n = i && d && pgBrowser.Nodes[d._type]; - - pgBrowser.ShowNodeSQL.showSQL.apply(pgBrowser.ShowNodeSQL, [i, d, n]); - - // We will start listening the tree selection event. - pgBrowser.Events.on('pgadmin-browser:tree:selected', pgBrowser.ShowNodeSQL.showSQL); - pgBrowser.Events.on( - 'pgadmin-browser:tree:refreshing', pgBrowser.ShowNodeSQL.refreshSQL, this - ); - } else { - // We don't need to listen the tree item selection event. - pgBrowser.Events.off('pgadmin-browser:tree:selected', pgBrowser.ShowNodeSQL.showSQL); - pgBrowser.Events.off( - 'pgadmin-browser:tree:refreshing', pgBrowser.ShowNodeSQL.refreshSQL, this - ); - } - }, - }); - - return pgBrowser.ShowNodeSQL; -}); diff --git a/web/pgadmin/misc/statistics/static/js/Statistics.jsx b/web/pgadmin/misc/statistics/static/js/Statistics.jsx index caf635351..305262680 100644 --- a/web/pgadmin/misc/statistics/static/js/Statistics.jsx +++ b/web/pgadmin/misc/statistics/static/js/Statistics.jsx @@ -17,7 +17,7 @@ import getApiInstance from 'sources/api_instance'; import { makeStyles } from '@material-ui/core/styles'; import sizePrettify from 'sources/size_prettify'; import { getURL } from '../../../static/utils/utils'; - +import Loader from 'sources/components/Loader'; const useStyles = makeStyles((theme) => ({ emptyPanel: { minHeight: '100%', @@ -37,12 +37,18 @@ const useStyles = makeStyles((theme) => ({ marginLeft: '0.5rem', fontSize: '0.875rem', }, + loading: { + marginLeft: '0.5rem', + fontSize: '0.875rem', + colour: theme.palette.grey[400] + }, autoResizer: { height: '100% !important', width: '100% !important', background: theme.palette.grey[400], padding: '7.5px', - overflow: 'auto !important', + overflowX: 'auto !important', + overflowY: 'hidden !important', minHeight: '100%', minWidth: '100%', }, @@ -58,7 +64,7 @@ function getColumn(data, singleLineStatistics) { accessor: row.name, sortble: true, resizable: false, - disableGlobalFilter: true, + disableGlobalFilter: false, }; columns.push(column); }); @@ -71,14 +77,14 @@ function getColumn(data, singleLineStatistics) { accessor: 'name', sortble: true, resizable: false, - disableGlobalFilter: true, + disableGlobalFilter: false, }, { Header: 'Value', accessor: 'value', sortble: true, resizable: false, - disableGlobalFilter: true, + disableGlobalFilter: false, }, ]; } @@ -142,20 +148,21 @@ export default function Statistics({ nodeData, item, node, ...props }) { const [tableData, setTableData] = React.useState([]); const [msg, setMsg] = React.useState(''); + const [loaderText, setLoaderText] = React.useState(''); const [columns, setColumns] = React.useState([ { Header: 'Statictics', accessor: 'name', sortble: true, resizable: false, - disableGlobalFilter: true, + disableGlobalFilter: false, }, { Header: 'Value', accessor: 'value', sortble: true, resizable: false, - disableGlobalFilter: true, + disableGlobalFilter: false, }, ]); @@ -170,6 +177,7 @@ export default function Statistics({ nodeData, item, node, ...props }) { const api = getApiInstance(); if (node.hasStatistics) { + setLoaderText('Loading...'); api({ url: url, type: 'GET', @@ -180,6 +188,7 @@ export default function Statistics({ nodeData, item, node, ...props }) { if (!_.isUndefined(colData)) { setColumns(colData); } + setLoaderText(''); }) .catch((e) => { Notify.alert( @@ -187,10 +196,12 @@ export default function Statistics({ nodeData, item, node, ...props }) { gettext(e.message) ); // show failed message. + setLoaderText(''); setMsg(gettext('Failed to retrieve data from the server.')); }); } else { - setMsg(message); + setLoaderText(''); + setMsg('No statistics are available for the selected object.'); } } if (message != '') { @@ -213,10 +224,12 @@ export default function Statistics({ nodeData, item, node, ...props }) { > ) : (
-
- - {gettext(msg)} -
+ {loaderText ? () : +
+ + {gettext(msg)} +
+ }
)} diff --git a/web/pgadmin/static/js/Theme/dark.js b/web/pgadmin/static/js/Theme/dark.js index 0fd5cc5a4..cafaaae3e 100644 --- a/web/pgadmin/static/js/Theme/dark.js +++ b/web/pgadmin/static/js/Theme/dark.js @@ -92,7 +92,8 @@ export default function(basicSettings) { activeStepFg: '#FFFFFF', stepBg: '#FFFFFF', stepFg: '#000', - toggleBtnBg: '#000' + toggleBtnBg: '#000', + colorFg: '#FFFFFF', } }); } diff --git a/web/pgadmin/static/js/Theme/high_contrast.js b/web/pgadmin/static/js/Theme/high_contrast.js index b567ca23e..a9c172ac7 100644 --- a/web/pgadmin/static/js/Theme/high_contrast.js +++ b/web/pgadmin/static/js/Theme/high_contrast.js @@ -90,7 +90,8 @@ export default function(basicSettings) { activeStepFg: '#010b15', stepBg: '#FFFFFF', stepFg: '#000', - toggleBtnBg: '#6B6B6B' + toggleBtnBg: '#6B6B6B', + colorFg: '#FFFFFF', } }); } diff --git a/web/pgadmin/static/js/Theme/standard.js b/web/pgadmin/static/js/Theme/standard.js index ddc9cd735..8cf463a71 100644 --- a/web/pgadmin/static/js/Theme/standard.js +++ b/web/pgadmin/static/js/Theme/standard.js @@ -85,6 +85,7 @@ export default function(basicSettings) { padding: '5px 8px', }, borderColor: '#dde0e6', + colorFg: '#222222', loader: { backgroundColor: fade('#000', 0.65), color: '#fff', @@ -102,6 +103,7 @@ export default function(basicSettings) { toggleBtnBg: '#000', editorToolbarBg: '#ebeef3', datagridBg: '#fff', + } }); } diff --git a/web/pgadmin/static/js/components/PgTable.jsx b/web/pgadmin/static/js/components/PgTable.jsx index 1b5179ac0..b6f9d12cb 100644 --- a/web/pgadmin/static/js/components/PgTable.jsx +++ b/web/pgadmin/static/js/components/PgTable.jsx @@ -8,13 +8,26 @@ ////////////////////////////////////////////////////////////// import React from 'react'; -import { useTable, useRowSelect, useSortBy, useResizeColumns, useFlexLayout, useGlobalFilter } from 'react-table'; -import { FixedSizeList } from 'react-window'; +import { + useTable, + useRowSelect, + useSortBy, + useResizeColumns, + useFlexLayout, + useGlobalFilter, + useExpanded, +} from 'react-table'; +import { VariableSizeList } from 'react-window'; import { makeStyles } from '@material-ui/core/styles'; import clsx from 'clsx'; import PropTypes from 'prop-types'; import AutoSizer from 'react-virtualized-auto-sizer'; -import { Checkbox } from '@material-ui/core'; +import { Checkbox, Box } from '@material-ui/core'; +import { InputText } from './FormComponents'; +import FormView from 'sources/SchemaView'; +import _ from 'lodash'; +import gettext from 'sources/gettext'; + /* eslint-disable react/display-name */ const useStyles = makeStyles((theme) => ({ root: { @@ -29,22 +42,56 @@ const useStyles = makeStyles((theme) => ({ width: '100% !important', }, fixedSizeList: { - // position: 'relative', direction: 'ltr', overflowX: 'hidden !important', - overflow: 'overlay !important' + overflow: 'overlay !important', + }, + customHeader:{ + marginTop: '12px', + marginLeft: '4px' + }, + searchBox: { + marginBottom: '5px', + display: 'flex', + background: theme.palette.background.default + }, + tableContentWidth: { + width: 'calc(100% - 3px)', + }, + searchPadding: { + flex: 2.5 + }, + searchInput: { + flex: 1, + marginTop: 8, + borderLeft: 'none', + paddingLeft: 5, + marginRight: 8, + marginBottom: 8, + }, table: { - flexGrow:1, - minHeight:0, + flexGrow: 1, + minHeight: 0, borderSpacing: 0, width: '100%', overflow: 'hidden', borderRadius: theme.shape.borderRadius, + border: '1px solid'+ theme.palette.grey[400] }, - extraTable:{ - backgroundColor: theme.palette.grey[400], - flexGrow:1, + pgTableHeadar: { + display: 'flex', + flexGrow: 1, + overflow: 'hidden !important', + height: '100% !important', + flexDirection: 'column' + }, + + expandedForm: { + ...theme.mixins.panelBorder, + margin: '8px', + paddingBottom: '12px', + marginRight: '15px', }, tableCell: { @@ -54,15 +101,14 @@ const useStyles = makeStyles((theme) => ({ ...theme.mixins.panelBorder.right, position: 'relative', overflow: 'hidden', + height: '35px', textOverflow: 'ellipsis', whiteSpace: 'nowrap', backgroundColor: theme.otherVars.tableBg, - // ...theme.mixins.panelBorder.top, - ...theme.mixins.panelBorder.left, - }, selectCell: { - textAlign: 'center' + textAlign: 'center', + minWidth: '25px' }, tableCellHeader: { fontWeight: theme.typography.fontWeightBold, @@ -93,13 +139,57 @@ const useStyles = makeStyles((theme) => ({ paddingTop: '0.35em', height: 35, backgroundPosition: '1%', - } -}), -); + }, + emptyPanel: { + minHeight: '100%', + minWidth: '100%', + background: theme.palette.background.default, + overflow: 'auto', + padding: '7.5px', + }, + panelIcon: { + width: '80%', + margin: '0 auto', + marginTop: '25px !important', + position: 'relative', + textAlign: 'center', + }, + panelMessage: { + marginLeft: '0.5rem', + fontSize: '0.875rem', + }, + expandedIconCell: { + backgroundColor: theme.palette.grey[400], + ...theme.mixins.panelBorder.top, + borderBottom: 'none', + }, + btnCell: { + padding: theme.spacing(0.5, 0), + textAlign: 'center', + }, +})); -export default function PgTable({ columns, data, isSelectRow, ...props }) { +export default function PgTable({ columns, data, isSelectRow, offset=105, ...props }) { // Use the state and functions returned from useTable to build your UI const classes = useStyles(); + const [searchVal, setSearchVal] = React.useState(''); + const tableRef = React.useRef(); + const rowHeights = React.useRef({}); + const rowRef = React.useRef({}); + + function getRowHeight(index, size) { + return rowHeights.current[index] + size || 35; + } + + const setRowHeight = React.useCallback((index, size) => { + if(tableRef.current) { + tableRef.current.resetAfterIndex(index); + if (!(rowHeights.current.hasOwnProperty(index))){ + rowHeights.current = { ...rowHeights.current, [index]: size }; + } + } + }, []); + const defaultColumn = React.useMemo( () => ({ minWidth: 150, @@ -119,7 +209,8 @@ export default function PgTable({ columns, data, isSelectRow, ...props }) { <> + ref={resolvedRef} {...rest} + /> ); }, @@ -141,9 +232,9 @@ export default function PgTable({ columns, data, isSelectRow, ...props }) { rows, prepareRow, selectedFlatRows, - state: { selectedRowIds }, + state: { selectedRowIds, expanded }, setGlobalFilter, - setHiddenColumns + setHiddenColumns, } = useTable( { columns, @@ -153,11 +244,12 @@ export default function PgTable({ columns, data, isSelectRow, ...props }) { }, useGlobalFilter, useSortBy, + useExpanded, useRowSelect, useResizeColumns, useFlexLayout, - hooks => { - hooks.visibleColumns.push(CLOUMNS => { + (hooks) => { + hooks.visibleColumns.push((CLOUMNS) => { if (isSelectRow) { return [ // Let's make a column for selection @@ -178,7 +270,7 @@ export default function PgTable({ columns, data, isSelectRow, ...props }) { ), sortble: false, - width: 50, + width: 30, minWidth: 0, }, ...CLOUMNS, @@ -195,11 +287,16 @@ export default function PgTable({ columns, data, isSelectRow, ...props }) { } ); + React.useEffect(()=>{ + tableRef.current?.resetAfterIndex(0); + },[expanded]); + + React.useEffect(() => { setHiddenColumns( columns .filter((column) => { - if (column.isVisible === undefined || columns.isVisible === true) { + if (column.isVisible === undefined || column.isVisible === true) { return false; } return true; @@ -222,28 +319,44 @@ export default function PgTable({ columns, data, isSelectRow, ...props }) { }, [selectedRowIds]); React.useEffect(() => { - setGlobalFilter(props.searchText || undefined); - }, [props.searchText]); - + setGlobalFilter(searchVal || undefined); + }, [searchVal]); const RenderRow = React.useCallback( ({ index, style }) => { const row = rows[index]; prepareRow(row); return ( -
- {row.cells.map((cell) => { - return ( -
- {cell.render('Cell')} -
- ); - })} +
+
+ {row.cells.map((cell) => { + let classNames = [classes.tableCell]; + if(typeof(cell.column.id) == 'string' && cell.column.id.startsWith('btn-')) { + classNames.push(classes.btnCell); + } + if(cell.column.id == 'btn-edit' && row.isExpanded) { + classNames.push(classes.expandedIconCell); + } + return ( +
+ {cell.render('Cell')} +
+ ); + })} +
+ {!_.isUndefined(row) && row.isExpanded && ( + + { + /*This is intentional (SonarQube)*/ + }} + viewHelperProps={{ mode: 'properties' }} + schema={props.schema[row.id]} + showFooter={false} + onDataChange={() => { }} + /> + + )}
); }, @@ -251,70 +364,108 @@ export default function PgTable({ columns, data, isSelectRow, ...props }) { ); // Render the UI for your table return ( - - {({ height}) => ( -
-
- {headerGroups.map((headerGroup) => ( -
- {headerGroup.headers.map((column) => ( -
+ + + {props.customHeader && ( )} + + { + setSearchVal(val); + }} + /> + + + {({ height }) => ( +
+
+ {headerGroups.map((headerGroup) => ( +
+ {headerGroup.headers.map((column) => (
- {column.render('Header')} - - {column.isSorted - ? column.isSortedDesc - ? ' 🔽' - : ' 🔼' - : ''} - - {column.resizable && ( -
- )} +
+ {column.render('Header')} + + {column.isSorted + ? column.isSortedDesc + ? ' 🔽' + : ' 🔼' + : ''} + + {column.resizable && ( +
+ )} +
-
- ))} - {/* */} -
- ))} -
+ ))} +
+ ))} +
-
- - {RenderRow} - + { + data.length > 0 ? ( +
+ { + if (_.isUndefined(rows[i].isExpanded)) { + rows[i].isExpanded = false; + } + if (rowRef.current && rows[i].isExpanded) { + setRowHeight(i, rowRef.current.offsetHeight + 35); + } + return rows[i].isExpanded ? getRowHeight(i, 35) : 35; + }} + sorted={props?.sortOptions} + > + {RenderRow} + + +
+ ) : ( + +
+
+ + {gettext('No record found')} +
+ +
+ )}
-
- )} - + )} + + ); } PgTable.propTypes = { stepId: PropTypes.number, height: PropTypes.number, + offset: PropTypes.number, + customHeader: PropTypes.func, className: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), - children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]), + fixedSizeList: PropTypes.oneOfType([PropTypes.string, PropTypes.object]), + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node, + ]), getToggleAllRowsSelectedProps: PropTypes.func, columns: PropTypes.array, data: PropTypes.array, @@ -324,8 +475,6 @@ PgTable.propTypes = { getSelectedRows: PropTypes.func, searchText: PropTypes.string, type: PropTypes.string, - sortOptions: PropTypes.array, - + sortOptions: PropTypes.array, + schema: PropTypes.object }; - - diff --git a/web/pgadmin/static/js/nodes/dashboard.js b/web/pgadmin/static/js/nodes/dashboard.js deleted file mode 100644 index 83b87bf99..000000000 --- a/web/pgadmin/static/js/nodes/dashboard.js +++ /dev/null @@ -1,37 +0,0 @@ -///////////////////////////////////////////////////////////// -// -// pgAdmin 4 - PostgreSQL Tools -// -// Copyright (C) 2013 - 2022, The pgAdmin Development Team -// This software is released under the PostgreSQL Licence -// -////////////////////////////////////////////////////////////// - -import {isString, isFunction} from 'sources/utils'; -import pgBrowser from 'pgadmin.browser'; - - -export function url(itemData, item, treeHierarchy) { - let treeNode = pgBrowser.tree.findNodeByDomElement(item); - let return_url = null; - - if (treeNode) { - treeNode.anyFamilyMember( - (node) => { - let nodeData = node.getData(); - let browserNode = pgBrowser.Nodes[nodeData._type]; - let dashboardURL = browserNode && browserNode.dashboard; - - if (isFunction(dashboardURL)) { - dashboardURL = dashboardURL.apply( - browserNode, [node, nodeData, treeHierarchy] - ); - } - return_url = isString(dashboardURL) ? dashboardURL : null; - - return (return_url !== null); - }); - } - - return return_url; -} diff --git a/web/pgadmin/tools/grant_wizard/static/js/GrantWizard.jsx b/web/pgadmin/tools/grant_wizard/static/js/GrantWizard.jsx index a0f38ea2f..015c3939d 100644 --- a/web/pgadmin/tools/grant_wizard/static/js/GrantWizard.jsx +++ b/web/pgadmin/tools/grant_wizard/static/js/GrantWizard.jsx @@ -17,7 +17,7 @@ import Wizard from '../../../../static/js/helpers/wizard/Wizard'; import WizardStep from '../../../../static/js/helpers/wizard/WizardStep'; import PgTable from 'sources/components/PgTable'; import { getNodePrivilegeRoleSchema } from '../../../../../pgadmin/browser/server_groups/servers/static/js/privilege.ui.js'; -import { InputSQL, InputText, FormFooterMessage, MESSAGE_TYPE } from '../../../../static/js/components/FormComponents'; +import { InputSQL, FormFooterMessage, MESSAGE_TYPE } from '../../../../static/js/components/FormComponents'; import getApiInstance from '../../../../static/js/api_instance'; import SchemaView from '../../../../static/js/SchemaView'; import clsx from 'clsx'; @@ -117,7 +117,6 @@ export default function GrantWizard({ sid, did, nodeInfo, nodeData }) { const [selectedObject, setSelectedObject] = React.useState([]); const [selectedAcl, setSelectedAcl] = React.useState({}); const [msqlData, setSQL] = React.useState(''); - const [searchVal, setSearchVal] = React.useState(''); const [loaderText, setLoaderText] = React.useState(''); const [tablebData, setTableData] = React.useState([]); const [privOptions, setPrivOptions] = React.useState({}); @@ -314,17 +313,6 @@ export default function GrantWizard({ sid, did, nodeInfo, nodeData }) { loaderText={loaderText} > - - - { - setSearchVal(val);} - }> - - diff --git a/web/webpack.config.js b/web/webpack.config.js index 3f9c5f8f4..ed9ad4472 100644 --- a/web/webpack.config.js +++ b/web/webpack.config.js @@ -469,10 +469,8 @@ module.exports = [{ options: { type: 'commonjs', imports: [ - 'pure|pgadmin.dashboard', 'pure|pgadmin.browser.quick_search', 'pure|pgadmin.tools.user_management', - 'pure|pgadmin.browser.object_sql', 'pure|pgadmin.browser.bgprocess', 'pure|pgadmin.node.server_group', 'pure|pgadmin.node.server', diff --git a/web/webpack.shim.js b/web/webpack.shim.js index a2e8f28e7..f9af1531f 100644 --- a/web/webpack.shim.js +++ b/web/webpack.shim.js @@ -208,14 +208,13 @@ var webpackShimConfig = { 'pgadmin.browser.dialog': path.join(__dirname, './pgadmin/browser/static/js/dialog'), 'pgadmin.browser.node': path.join(__dirname, './pgadmin/browser/static/js/node'), 'pgadmin.browser.node.ui': path.join(__dirname, './pgadmin/browser/static/js/node.ui'), - 'pgadmin.browser.object_sql': path.join(__dirname, './pgadmin/misc/sql/static/js/sql'), 'pgadmin.browser.panel': path.join(__dirname, './pgadmin/browser/static/js/panel'), 'pgadmin.browser.toolbar': path.join(__dirname, './pgadmin/browser/static/js/toolbar'), 'pgadmin.browser.server.privilege': path.join(__dirname, './pgadmin/browser/server_groups/servers/static/js/privilege'), 'pgadmin.browser.server.variable': path.join(__dirname, './pgadmin/browser/server_groups/servers/static/js/variable'), 'pgadmin.browser.utils': '/browser/js/utils', 'pgadmin.browser.wizard': path.join(__dirname, './pgadmin/browser/static/js/wizard'), - 'pgadmin.dashboard': path.join(__dirname, './pgadmin/dashboard/static/js/dashboard'), + 'pgadmin.dashboard': path.join(__dirname, './pgadmin/dashboard/static/js/Dashboard'), 'pgadmin.datagrid': path.join(__dirname, './pgadmin/tools/datagrid/static/js/datagrid'), 'pgadmin.file_manager': path.join(__dirname, './pgadmin/misc/file_manager/static/js/file_manager'), 'pgadmin.file_utility': path.join(__dirname, './pgadmin/misc/file_manager/static/js/utility'),