Hi,
Please find the attached path for Privilege control with select2cell for
user role section
TODO: Need to add current database logged in user in Granter filed in
privilege grid control.
--
*Harshal Dhumal*
*Software Engineer *
EenterpriseDB <http://www.enterprisedb.com>
diff --git a/web/pgadmin/browser/server_groups/servers/__init__.py b/web/pgadmin/browser/server_groups/servers/__init__.py
index c38265d..04156ee 100644
--- a/web/pgadmin/browser/server_groups/servers/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/__init__.py
@@ -115,7 +115,8 @@ class ServerModule(sg.ServerGroupPluginModule):
{
'name': 'pgadmin.browser.server.privilege',
'path': url_for('browser.index') + 'server/static/js/privilege',
- 'when': self.node_type
+ 'when': self.node_type,
+ 'deps': ['pgadmin.browser.node.ui']
},
{
'name': 'pgadmin.browser.server.variable',
diff --git a/web/pgadmin/browser/server_groups/servers/static/js/privilege.js b/web/pgadmin/browser/server_groups/servers/static/js/privilege.js
index 2f6f052..651f837 100644
--- a/web/pgadmin/browser/server_groups/servers/static/js/privilege.js
+++ b/web/pgadmin/browser/server_groups/servers/static/js/privilege.js
@@ -5,7 +5,7 @@
function(_, $, Backbone, Backform, Backgrid, Alertify, pgNode) {
// Export global even in AMD case in case this script is loaded with
// others that may still expect a global Backform.
- return factory(root, _, $, Backbone, Backform, Alertify, pgNode);
+ return factory(root, _, $, Backbone, Backform, Backgrid, Alertify, pgNode);
});
// Next for Node.js or CommonJS. jQuery may not be needed as a module.
@@ -14,15 +14,16 @@
$ = root.jQuery || root.$ || root.Zepto || root.ender,
Backbone = require('backbone') || root.Backbone,
Backform = require('backform') || root.Backform;
+ Backgrid = require('backgrid') || root.Backgrid;
Alertify = require('alertify') || root.Alertify;
pgAdmin = require('pgadmin.browser.node') || root.pgAdmin.Browser.Node;
factory(root, _, $, Backbone, Backform, Alertify, pgNode);
// Finally, as a browser global.
} else {
- factory(root, root._, (root.jQuery || root.Zepto || root.ender || root.$), root.Backbone, root.Backform, root.pgAdmin.Browser.Node);
+ factory(root, root._, (root.jQuery || root.Zepto || root.ender || root.$), root.Backbone, root.Backform, root.Backgrid, root.alertify, root.pgAdmin.Browser.Node);
}
-} (this, function(root, _, $, Backbone, Backform, Alertify, pgNode) {
+} (this, function(root, _, $, Backbone, Backform, Backgrid, Alertify, pgNode) {
/**
* Each Privilege, supporeted by an database object, will be represented
@@ -66,15 +67,39 @@
privileges:[],
schema: [{
- id: 'grantee', label:'Grantee', type:'text', group: null, cell: 'string',
- disabled: true, cellHeaderClasses: 'width_percent_40'
+ id: 'grantee', label:'Grantee', type:'text', group: null,
+ editable: true, cellHeaderClasses: 'width_percent_40',
+ cell: 'node-list-by-name', node: 'role',
+ disabled : function(column, collection) {
+ if (column instanceof Backbone.Collection) {
+ // This has been called during generating the header cell
+ return false;
+ }
+ return !(this.node_info && this.node_info.server.user.name == column.get('grantor'));
+ },
+ transform: function(data) {
+ var res =
+ Backgrid.Extension.NodeListByNameCell.prototype.defaults.transform.apply(
+ this, arguments
+ );
+ res.unshift({label: 'public', value: 'public'});
+ return res;
+ }
}, {
id: 'privileges', label:'Privileges',
type: 'collection', model: PrivilegeModel, group: null,
- disabled: false, cell: 'privilege', control: 'text',
- cellHeaderClasses: 'width_percent_40'
+ cell: 'privilege', control: 'text', cellHeaderClasses: 'width_percent_40',
+ disabled : function(column, collection) {
+ if (column instanceof Backbone.Collection) {
+ // This has been called during generating the header cell
+ return false;
+ }
+ return !(this.node_info && this.node_info.server.user.name == column.get('grantor') ||
+ this.attributes.node_info.server.user.name == column.get('grantor'));
+ }
},{
- id: 'grantor', label: 'Granter', type: 'text', disabled: true
+ id: 'grantor', label: 'Granter', type: 'text', disabled: true,
+ cell: 'node-list-by-name', node: 'role'
}],
/*
diff --git a/web/pgadmin/browser/static/js/node.ui.js b/web/pgadmin/browser/static/js/node.ui.js
index 7642a47..e38adcb 100644
--- a/web/pgadmin/browser/static/js/node.ui.js
+++ b/web/pgadmin/browser/static/js/node.ui.js
@@ -4,7 +4,6 @@ function($, _, pgAdmin, Backbone, Backform, Alertify, Node) {
var pgBrowser = pgAdmin.Browser;
-
// Store value in DOM as stringified JSON.
var StringOrJSONFormatter = function() {};
_.extend(StringOrJSONFormatter.prototype, {
@@ -183,7 +182,7 @@ function($, _, pgAdmin, Backbone, Backform, Alertify, Node) {
var NodeListByIdControl = Backform.NodeListByIdControl = NodeAjaxOptionsControl.extend({
controlClassName: 'pgadmin-node-select form-control',
- defaults: _.extend(NodeAjaxOptionsControl.prototype.defaults, {
+ defaults: _.extend({}, NodeAjaxOptionsControl.prototype.defaults, {
first_empty: true,
empty_value: '-- None --',
url: 'nodes',
@@ -229,7 +228,7 @@ function($, _, pgAdmin, Backbone, Backform, Alertify, Node) {
var NodeListByNameControl = Backform.NodeListByNameControl = NodeListByIdControl.extend({
- defaults: _.extend(NodeListByIdControl.prototype.defaults, {
+ defaults: _.extend({}, NodeListByIdControl.prototype.defaults, {
transform: function(rows) {
var self = this,
node = self.field.get('schema_node'),
@@ -288,5 +287,273 @@ function($, _, pgAdmin, Backbone, Backform, Alertify, Node) {
});
};
+
+ /*
+ * NodeAjaxOptionsCell
+ * This cell will fetch the options required to render the select
+ * cell, from the url specific to the pgAdmin.Browser node object.
+ *
+ * In order to use this properly, schema require to set the 'url' property,
+ * which exposes the data for this node.
+ *
+ * In case the url is not providing the data in proper format, we can
+ * specify the 'transform' function too, which will convert the fetched
+ * data to proper 'label', 'value' format.
+ */
+ var NodeAjaxOptionsCell = Backgrid.Extension.NodeAjaxOptionsCell = Backgrid.Extension.Select2Cell.extend({
+ defaults: _.extend({}, Backgrid.Extension.Select2Cell.prototype.defaults, {
+ url: undefined,
+ transform: undefined,
+ url_with_id: false,
+ select2: {
+ allowClear: true,
+ placeholder: 'Select from the list',
+ width: 'style'
+ }
+ }),
+ template: _.template(
+ '<option <% if (image) { %> data-image=<%= image %> <% } %> value="<%- value %>" <%= selected ? \'selected="selected"\' : "" %>><%- text %></option>'
+ ),
+ initialize: function () {
+ Backgrid.Extension.Select2Cell.prototype.initialize.apply(this, arguments);
+
+ var col = _.defaults(this.column.toJSON(), this.defaults),
+ model = this.model, column = this.column,
+ editable = Backgrid.callByNeed(col.editable, column, model),
+ optionValues = _.clone(this.optionValues || this.column.get('options'));
+
+
+ var self = this,
+ url = self.column.get('url') || self.defaults.url,
+ m = self.model.handler || self.model;
+
+ // Hmm - we found the url option.
+ // That means - we needs to fetch the options from that node.
+ if (url) {
+ var node = this.column.get('schema_node'),
+ node_info = this.column.get('node_info'),
+ full_url = node.generate_url.apply(
+ node, [
+ null, url, this.column.get('node_data'),
+ this.column.get('url_with_id') || false, node_info
+ ]),
+ cache_level = this.column.get('cache_level') || node.type,
+ cache_node = this.column.get('cache_node');
+
+ cache_node = (cache_node && pgAdmin.Browser.Nodes['cache_node']) || node;
+
+ /*
+ * We needs to check, if we have already cached data for this url.
+ * If yes - use that, and do not bother about fetching it again,
+ * and use it.
+ */
+ var data = cache_node.cache(url, node_info, cache_level);
+
+ if (this.column.get('version_compitible') &&
+ (_.isUndefined(data) || _.isNull(data))) {
+ m.trigger('pgadmin:view:fetching', m, self.column);
+ $.ajax({
+ async: false,
+ url: full_url,
+ success: 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);
+ },
+ error: function() {
+ m.trigger('pgadmin:view:fetch:error', m, self.column);
+ }
+ });
+ m.trigger('pgadmin:view:fetched', m, self.column);
+ }
+ // 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) || [];
+
+ /*
+ * Transform the data
+ */
+ transform = this.column.get('transform') || self.defaults.transform;
+ if (transform && _.isFunction(transform)) {
+ // We will transform the data later, when rendering.
+ // It will allow us to generate different data based on the
+ // dependencies.
+ self.column.set('options', transform.bind(self, data));
+ } else {
+ self.column.set('options', data);
+ }
+ }
+ },
+ render: function() {
+ /*
+ * Let SelectCell render it, we will do our magic on the
+ * select control in it.
+ */
+
+ var col = _.defaults(this.column.toJSON(), this.defaults),
+ model = this.model, column = this.column,
+ editable = Backgrid.callByNeed(col.editable, column, model),
+ optionValues = _.clone(this.optionValues ||
+ _.isFunction(this.column.get('options')) ?
+ this.column.get('options').apply(this) :
+ this.column.get(' options')),
+ select2_opts = _.defaults({}, col.select2, this.defaults.select2),
+ evalF = function(f, col, m) {
+ return (_.isFunction(f) ? !!f.apply(col, [m]) : !!f);
+ };
+
+ this.$el.empty();
+
+ if (!_.isArray(optionValues)) throw new TypeError("optionValues must be an array");
+
+ /*
+ * Add empty option as Select2 requires any empty '<option><option>' for
+ * some of its functionality to work.
+ */
+ optionValues.unshift({'label':null, 'value':null, 'image':null});
+
+ var optionText = null,
+ optionValue = null,
+ model = this.model,
+ selectedValues = model.get(this.column.get("name"));
+
+ delete this.$select;
+
+ this.$select = $("<select>", {tabIndex: -1}).appendTo(this.$el);
+
+ for (var i = 0; i < optionValues.length; i++) {
+ var op = optionValues[i];
+
+ optionText = op['label'];
+ optionValue = op['value'];
+ optionImage = op['image'];
+
+ this.$select.append(
+ this.template({
+ text: optionText,
+ value: optionValue,
+ image: optionImage,
+ selected: (selectedValues == optionValue) ||
+ (_.indexOf(selectedValues, optionValue) > -1)
+ }));
+ }
+ // Initialize select2 control.
+ this.$select.select2(
+ _.defaults(
+ {'disabled': !editable},
+ col.select2,
+ this.defaults.select2
+ ));
+
+ /*
+ * If select2 options do not have any disabled property on this cell
+ * and schema has disabled property then we need to apply it
+ */
+ if(!_.has(select2_opts, 'disabled') && (col && col.disabled)) {
+ _.extend(select2_opts, {
+ disabled: evalF(col.disabled, col, this.model)
+ });
+ }
+
+ this.$el.find("select").select2(select2_opts);
+
+ this.delegateEvents();
+
+ return this;
+ }
+ });
+
+ var NodeListByIdCell = Backgrid.Extension.NodeListByIdCell = NodeAjaxOptionsCell.extend({
+ controlClassName: 'pgadmin-node-select backgrid-cell',
+ defaults: _.extend({}, NodeAjaxOptionsCell.prototype.defaults, {
+ url: 'nodes',
+ filter: undefined,
+ transform: function(rows) {
+ var self = this,
+ node = self.column.get('schema_node'),
+ res = [],
+ filter = self.column.get('filter') || function() { return true; };
+
+ filter = filter.bind(self);
+
+ _.each(rows, function(r) {
+ if (filter(r)) {
+ var l = (_.isFunction(node['node_label']) ?
+ (node['node_label']).apply(node, [r, self.model, self]) :
+ r.label),
+ image= (_.isFunction(node['node_image']) ?
+ (node['node_image']).apply(
+ node, [r, self.model, self]
+ ) :
+ (node['node_image'] || ('icon-' + node.type)));
+
+ res.push({
+ 'value': r._id,
+ 'image': image,
+ 'label': l
+ });
+ }
+ });
+
+ return res;
+ },
+ select2: {
+ placeholder: 'Select from the list',
+ width: 'style',
+ templateResult: formatNode,
+ templateSelection: formatNode
+ }
+ })
+ });
+
+
+ var NodeListByNameCell = Backgrid.Extension.NodeListByNameCell = NodeAjaxOptionsCell.extend({
+ controlClassName: 'pgadmin-node-select backgrid-cell',
+ defaults: _.extend({}, NodeAjaxOptionsCell.prototype.defaults, {
+ url: 'nodes',
+ filter: undefined,
+ transform: function(rows) {
+ var self = this,
+ node = self.column.get('schema_node'),
+ res = [],
+ filter = self.column.get('filter') || function() { return true; };
+
+ filter = filter.bind(self);
+
+ _.each(rows, function(r) {
+ if (filter(r)) {
+ var l = (_.isFunction(node['node_label']) ?
+ (node['node_label']).apply(node, [r, self.model, self]) :
+ r.label),
+ image= (_.isFunction(node['node_image']) ?
+ (node['node_image']).apply(
+ node, [r, self.model, self]
+ ) :
+ (node['node_image'] || ('icon-' + node.type)));
+
+ res.push({
+ 'value': r.label,
+ 'image': image,
+ 'label': l
+ });
+ }
+ });
+
+ return res;
+ },
+ select2: {
+ placeholder: 'Select from the list',
+ width: 'style',
+ templateResult: formatNode,
+ templateSelection: formatNode
+ }
+ })
+ });
+
+
return Backform;
});
diff --git a/web/pgadmin/browser/templates/browser/js/node.js b/web/pgadmin/browser/templates/browser/js/node.js
index fe999bb..622e9e1 100644
--- a/web/pgadmin/browser/templates/browser/js/node.js
+++ b/web/pgadmin/browser/templates/browser/js/node.js
@@ -1289,7 +1289,7 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, Backform) {
}
idx = _.indexOf(self.sessAttrs['changed'], obj);
if (!'sessChanged' in obj) {
- if (idx > 0) {
+ if (idx >= 0) {
return true;
}
self.sessAttrs['changed'].push(obj);
@@ -1301,7 +1301,7 @@ function($, _, S, pgAdmin, Menu, Backbone, Alertify, Backform) {
return true;
}
- if (idx > 0) {
+ if (idx >= 0) {
(self || self.handler).trigger(
'pgadmin-session:changed',
diff --git a/web/pgadmin/static/js/backform.pgadmin.js b/web/pgadmin/static/js/backform.pgadmin.js
index 42aaa55..e99c96e 100644
--- a/web/pgadmin/static/js/backform.pgadmin.js
+++ b/web/pgadmin/static/js/backform.pgadmin.js
@@ -76,6 +76,7 @@
'uniqueColCollection': ['unique-col-collection', 'unique-col-collection', 'string'],
'switch' : 'switch',
'select2': 'select2',
+ 'radio' : 'radio'
};
var getMappedControl = Backform.getMappedControl = function(type, mode) {
@@ -724,7 +725,7 @@
* conflicting with another model value.
*/
- m.set(uniqueChangedAttr[0], m.previous(uniqueChangedAttr[0]), {silent: true});
+ m.set(uniqueChangedAttr[0], m.previous(uniqueChangedAttr[0]));
}
if (oldModel) {
var idx = collection.indexOf(oldModel);
@@ -1204,7 +1205,7 @@
);
}
- // After validation we need to set that value into model (only if all falgs are true)
+ // After validation we need to set that value into model (only if all flags are true)
if (isValid) {
this.stopListening(this.model, "change:" + name, this.render);
this.model.set(name, value);
diff --git a/web/pgadmin/static/js/backgrid/backgrid.pgadmin.js b/web/pgadmin/static/js/backgrid/backgrid.pgadmin.js
index 85f99a6..b9a3f81 100644
--- a/web/pgadmin/static/js/backgrid/backgrid.pgadmin.js
+++ b/web/pgadmin/static/js/backgrid/backgrid.pgadmin.js
@@ -367,7 +367,7 @@
onSave: function (e) {
var model = this.model;
var column = this.column;
- model.set(column.get("name"), this.$select.val(),{silent:true});
+ model.set(column.get("name"), this.$select.val());
}
});
return Backgrid;
--
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers