Subject: New mechanism in backgrid to render different types of cells in same column [pgAdmin4]

From: Harshal Dhumal <[email-masked]>
Date: Tue, 19 Jan 2016 00:37:59 +0530

Hi,

This patch is replacement for our developed DynamicVariablecell.

Now we can pass cellFunction in column schema to get appropriate cell class.
User provided cellFunction must return valid cell class.
cellFunction will be called with context (this) as column and model as
argument.

eg.:

schema: [
  {id: 'name', label:'Name', type:'text', editable: false, cell: 'string'},
  {
    id: 'value', label:'Value', type: 'text', editable: true,
    cellFunction: function(model){

          if (isNaN(model.get(this.get('name')))) {
             return "string";
          } else {
              return Backgrid.NumberCell;
         }
      }
  },
  {id: 'database', label:'Database', type: 'text', editable: false},
  .
  .
  .

-- 
*Harshal Dhumal*
*Software Engineer *

EenterpriseDB <http://www.enterprisedb.com>
diff --git a/web/pgadmin/browser/server_groups/servers/static/js/variable.js b/web/pgadmin/browser/server_groups/servers/static/js/variable.js
index 2ead1a0..d0ba646 100644
--- a/web/pgadmin/browser/server_groups/servers/static/js/variable.js
+++ b/web/pgadmin/browser/server_groups/servers/static/js/variable.js
@@ -31,6 +31,46 @@
   }
 } (this, function(root, _, $, Backbone, Backform, Alertify, pgAdmin, pgNode) {
 
+  /*
+   * cellFunction for variable control.
+   * This function returns cell class depending on vartype.
+   */
+  var cellFunction = function(model) {
+    var self = this,
+      name = model.get("name"),
+      availVariables = self.get('availVariables'),
+      variable = availVariables[name];
+
+    switch(variable && variable.vartype) {
+      case "bool":
+        return Backgrid.Extension.SwitchCell;
+      break;
+      case "enum":
+        var options = [],
+            enumVals = variable.enumvals;
+
+        _.each(enumVals, function(enumVal) {
+          options.push([enumVal, enumVal]);
+        });
+        return Backgrid.Extension.Select2Cell.extend(
+            { optionValues: options }
+            );
+      break;
+      case "integer":
+        return Backgrid.IntegerCell;
+        break;
+      case "real":
+        return Backgrid.NumberCell.extend({ decimals: 0 });
+      break;
+      case "string":
+        return Backgrid.StringCell;
+      break;
+      default:
+        Backgrid.Cell;
+      break;
+    }
+  }
+
   /**
    *  VariableModel used to represent configuration parameters (variables tab)
    *  for database objects.
@@ -46,8 +86,8 @@
     schema: [
       {id: 'name', label:'Name', type:'text', editable: false, cellHeaderClasses: 'width_percent_30'},
       {
-        id: 'value', label:'Value', type: 'text', cell: 'dynamic-variable',
-        editable: true, cellHeaderClasses: 'width_percent_50'
+        id: 'value', label:'Value', type: 'text', editable: true,
+        cellFunction: cellFunction, cellHeaderClasses: 'width_percent_50'
       },
       {id: 'database', label:'Database', type: 'text', editable: false},
       {id: 'role', label:'Role', type: 'text', editable: false}
@@ -85,102 +125,6 @@
     }
   });
 
-  /*
-   * Dynamic Variable cell. Used for variable data type column in Variables tab.
-   * Behaviour of cell depends on variable data type.
-   */
-  var DynamicVariableCell = Backgrid.Extension.DynamicVariableCell = Backgrid.Cell.extend({
-    /*
-     * Mapping of postgres data type to backgrid cell type.
-     */
-    variableCellMapper: {
-      "bool":Backgrid.Extension.SwitchCell,
-      "enum":Backgrid.Extension.Select2Cell,
-      "string":Backgrid.Cell,
-      "integer":Backgrid.IntegerCell,
-      "real":Backgrid.NumberCell
-    },
-    initialize: function (opts) {
-
-      var self = this,
-          name = opts.model.get("name");
-      self.availVariables = opts.column.get('availVariables');
-
-      var variable = (self.availVariables[name]),
-          cell = self.variableCellMapper[variable && variable.vartype] || Backgrid.Cell;
-
-      /*
-       * Set properties for dynamic cell.
-       */
-      _.each(cell.prototype, function(v,k) {
-        self[k] = v;
-      });
-
-      DynamicVariableCell.__super__.initialize.apply(self, arguments);
-
-      switch(variable && variable.vartype) {
-        case "bool":
-          // There are no specific properties for BooleanCell.
-          break;
-
-        case "enum":
-          var options = [],
-              name = self.model.get("name"),
-              enumVals = variable.enumvals;
-
-          _.each(enumVals, function(enumVal) {
-            options.push([enumVal, enumVal]);
-          });
-
-          self.optionValues = options;
-          self.multiple = cell.prototype.multiple;
-          self.delimiter = cell.prototype.delimiter;
-
-          self.listenTo(
-              self.model, "backgrid:edit",
-              function (model, column, cell, editor) {
-                if (column.get("name") == self.column.get("name")) {
-                  editor.setOptionValues(self.optionValues);
-                  editor.setMultiple(self.multiple);
-                }
-              });
-          break;
-
-        case "integer":
-
-          self.decimals = 0;
-          self.decimalSeparator = cell.prototype.decimalSeparator;
-          self.orderSeparator = cell.prototype.orderSeparator;
-          var formatter = self.formatter;
-
-          formatter.decimals = self.decimals;
-          formatter.decimalSeparator = self.decimalSeparator;
-          formatter.orderSeparator = self.orderSeparator;
-
-          break;
-
-        case "real":
-
-          self.decimals = cell.prototype.decimals;
-          self.decimalSeparator = cell.prototype.decimalSeparator;
-          self.orderSeparator = cell.prototype.orderSeparator;
-
-          var formatter = self.formatter;
-
-          formatter.decimals = 0;
-          formatter.decimalSeparator = self.decimalSeparator;
-          formatter.orderSeparator = self.orderSeparator;
-
-          break;
-
-        case "string":
-        default:
-          // There are no specific properties for StringCell and Cell.
-          break;
-      }
-    }
-  });
-
   /**
    * Variable Tab Control to set/update configuration values for database object.
    *
@@ -198,13 +142,22 @@
     ),
 
     initialize: function(opts) {
-      var self = this;
+      var self = this,
+        uniqueCol = ['name'];
+
+      self.hasDatabase = opts.field.get('hasDatabase');
+      self.hasRole = opts.field.get('hasRole');
 
+      if (self.hasDatabase) {
+        uniqueCol.push('database')
+      } else if (self.hasRole) {
+        uniqueCol.push('role')
+      }
       // Overriding the uniqueCol in the field
       if (opts && opts.field) {
         if (opts.field instanceof Backform.Field) {
           opts.field.set({
-            uniqueCol: ['name', 'role', 'database'],
+            uniqueCol: uniqueCol || self.uniqueCol,
             model: pgNode.VariableModel
           },
           {
@@ -212,7 +165,7 @@
           });
         } else {
           opts.field.extend({
-            uniqueCol: ['name', 'role', 'database'],
+            uniqueCol: uniqueCol || self.uniqueCol,
             model: pgNode.VariableModel
           });
         }
@@ -222,8 +175,7 @@
           self, arguments
           );
 
-      self.hasDatabase = self.field.get('hasDatabase');
-      self.hasRole = self.field.get('hasRole');
+
       self.availVariables = {};
 
       var node = self.field.get('node').type,
@@ -566,7 +518,7 @@
         checkVars.push('database');
       }
 
-      if (self.role) {
+      if (self.hasRole) {
         checkVars.push('role');
       }
 
diff --git a/web/pgadmin/static/js/backgrid/backgrid.pgadmin.js b/web/pgadmin/static/js/backgrid/backgrid.pgadmin.js
index b9a3f81..43e194b 100644
--- a/web/pgadmin/static/js/backgrid/backgrid.pgadmin.js
+++ b/web/pgadmin/static/js/backgrid/backgrid.pgadmin.js
@@ -22,6 +22,49 @@
     factory(root, root._, (root.jQuery || root.Zepto || root.ender || root.$), root.Backbone, root.Backform);
   }
 } (this, function(root, _, $, Backbone, Backform, Alertify) {
+
+  /*
+   * Add mechanism in backgrid to render different types of cells in
+   * same column;
+   */
+
+  // Add new property cellFunction in Backgrid.Column.
+  _.extend(Backgrid.Column.prototype.defaults, { cellFunction: undefined });
+
+  _.extend(Backgrid.Row.prototype, {
+    makeCell: function (column) {
+      return new (this.getCell(column))({
+        column: column,
+        model: this.model
+      });
+    },
+    /*
+     * getCell function will check and execute user give cellFunction to get
+     * appropriate cell class for current cell being rendered.
+     * User provided cellFunction must return valid cell class.
+     * cellFunction will be called with context (this) as column and model as
+     * argument.
+     */
+    getCell: function (column) {
+      var cf = column.get("cellFunction");
+      if (_.isFunction(cf)){
+        var cell = cf.apply(column, [this.model]);
+        try {
+          return Backgrid.resolveNameToClass(cell, "Cell");
+        } catch (e) {
+          if (e instanceof ReferenceError) {
+            // Fallback to column cell.
+            return column.get("cell");
+          } else {
+            throw e; // Let other exceptions bubble up
+          }
+        }
+      } else {
+        return column.get("cell");
+      }
+    }
+  });
+
   var ObjectCellEditor = Backgrid.Extension.ObjectCellEditor = Backgrid.CellEditor.extend({
     modalTemplate: _.template([
       '<div class="subnode-dialog" tabindex="1">',

-- 
Sent via pgadmin-hackers mailing list ([email-masked])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers

---

From: Harshal Dhumal <[email-masked]>
Date: Tue, 19 Jan 2016 00:42:30 +0530

+
Also fixed some minor issues related to Unique column functionality in
Variable control in same patch.

-- 
*Harshal Dhumal*
*Software Engineer *

---

From: Ashesh Vashi <[email-masked]>
Date: Fri, 5 Feb 2016 14:39:58 +0530

On Fri, Feb 5, 2016 at 2:16 PM, Harshal Dhumal <
[email-masked]> wrote:

> Hi, Ashesh,
Hi Harshal,

[ Please do not forget to reply to All next time.. :-) ]

>
> Same patch which I send on 19 Jan with very minor change. i.e. properly
> initialize bool cell for dynamic variable cell.
>
Thanks - I've committed the patch.

--

Thanks & Regards,

Ashesh Vashi
EnterpriseDB INDIA: Enterprise PostgreSQL Company
<http://www.enterprisedb.com/>

*http://www.linkedin.com/in/asheshvashi*
<http://www.linkedin.com/in/asheshvashi>

> On Tue, Jan 19, 2016 at 12:42 AM, Harshal Dhumal <