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 (pgadmin-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers

Reply via email to