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 026e2439f..d15ddae86 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
@@ -14,7 +14,6 @@ import ForeignServerSchema from './foreign_server.ui';
 define('pgadmin.node.foreign_server', [
   'sources/gettext', 'sources/url_for', 'sources/pgadmin',
   'pgadmin.browser', 'pgadmin.browser.collection',
-  'pgadmin.browser.server.privilege',
 ], function(gettext, url_for, pgAdmin, pgBrowser) {
 
   // Extend the browser's collection class for foreign server collection
diff --git a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mappings/static/js/user_mapping.js b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mappings/static/js/user_mapping.js
index 0c220a2bc..e20f36460 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mappings/static/js/user_mapping.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/foreign_data_wrappers/foreign_servers/user_mappings/static/js/user_mapping.js
@@ -14,8 +14,8 @@ import _ from 'lodash';
 define('pgadmin.node.user_mapping', [
   'sources/gettext', 'sources/url_for',
   'sources/pgadmin', 'pgadmin.browser',
-  'pgadmin.backform', 'pgadmin.browser.collection',
-], function(gettext, url_for, pgAdmin, pgBrowser, Backform) {
+  'pgadmin.browser.collection',
+], function(gettext, url_for, pgAdmin, pgBrowser) {
 
   // Extend the browser's collection class for user mapping collection
   if (!pgBrowser.Nodes['coll-user_mapping']) {
@@ -105,34 +105,6 @@ define('pgadmin.node.user_mapping', [
           }
           pgAdmin.Browser.Node.Model.prototype.initialize.apply(this, arguments);
         },
-
-        // Defining schema for the user mapping node
-        schema: [
-          {
-            id: 'name', label: gettext('User'), type: 'text',
-            control: Backform.NodeListByNameControl, node: 'role',
-            mode: ['edit', 'create', 'properties'], select2: { allowClear: false },
-            disabled: function(m) { return !m.isNew(); },
-            transform: function() {
-              let self = this,
-                node = self.field.get('schema_node');
-              let res =
-              Backform.NodeListByNameControl.prototype.defaults.transform.apply(
-                this, arguments
-              );
-              res.unshift({
-                label: 'CURRENT_USER', value: 'CURRENT_USER',
-                image: 'icon-' + node.type,
-              },{
-                label: 'PUBLIC', value: 'PUBLIC', image: 'icon-' + node.type,
-              });
-              return res;
-            },
-          }, {
-            id: 'oid', label: gettext('OID'), cell: 'string',
-            type: 'text', mode: ['properties'],
-          }
-        ],
       }),
     });
 
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 4dcfc72af..00cbe51ad 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
@@ -13,7 +13,7 @@ import ForeignDataWrapperSchema from './foreign_data_wrapper.ui';
 
 define('pgadmin.node.foreign_data_wrapper', [
   'sources/gettext', 'sources/url_for', 'pgadmin.browser',
-  'pgadmin.browser.collection', 'pgadmin.browser.server.privilege',
+  'pgadmin.browser.collection',
 ], function(gettext, url_for, pgBrowser) {
 
   // Extend the browser's collection class for foreign data wrapper collection
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 2ab91efb7..9378d6826 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
@@ -13,7 +13,7 @@ import { getNodePrivilegeRoleSchema } from '../../../../static/js/privilege.ui';
 
 define('pgadmin.node.language', [
   'sources/gettext', 'sources/url_for', 'pgadmin.browser',
-  'pgadmin.browser.collection', 'pgadmin.browser.server.privilege',
+  'pgadmin.browser.collection',
 ], function(gettext, url_for, pgBrowser) {
 
   // Extend the browser's collection class for languages collection
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 b77ad85e2..e3b7dd918 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,7 +12,7 @@ import PublicationSchema from './publication.ui';
 
 define('pgadmin.node.publication', [
   'sources/gettext', 'sources/url_for', 'pgadmin.browser',
-  'pgadmin.browser.collection', 'pgadmin.browser.server.privilege',
+  'pgadmin.browser.collection',
 ], function(gettext, url_for, pgBrowser) {
 
   // Extend the browser's collection class for publications collection
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 f730bd154..a216222e6 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
@@ -16,7 +16,7 @@ import { getNodeVariableSchema } from '../../../../../static/js/variable.ui';
 define('pgadmin.node.function', [
   'sources/gettext', 'sources/url_for', 'pgadmin.browser',
   'pgadmin.node.schema.dir/child', 'pgadmin.node.schema.dir/schema_child_tree_node',
-  'pgadmin.browser.collection', 'pgadmin.browser.server.privilege',
+  'pgadmin.browser.collection',
 ], function(
   gettext, url_for, pgBrowser, schemaChild, schemaChildTreeNode
 ) {
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 2b779aaa2..b09d680eb 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
@@ -17,7 +17,7 @@ define('pgadmin.node.procedure', [
   'sources/gettext', 'sources/url_for',
   'sources/pgadmin', 'pgadmin.browser', 'pgadmin.node.schema.dir/child',
   'pgadmin.node.schema.dir/schema_child_tree_node',
-  'pgadmin.browser.collection', 'pgadmin.browser.server.privilege',
+  'pgadmin.browser.collection',
 ], function(gettext, url_for, pgAdmin, pgBrowser, schemaChild, schemaChildTreeNode) {
 
   if (!pgBrowser.Nodes['coll-procedure']) {
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 313d4c87d..afc1a3f33 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
@@ -16,7 +16,7 @@ import _ from 'lodash';
 define('pgadmin.node.trigger_function', [
   'sources/gettext', 'sources/url_for', 'pgadmin.browser',
   'pgadmin.node.schema.dir/child', 'pgadmin.node.schema.dir/schema_child_tree_node',
-  'pgadmin.browser.collection', 'pgadmin.browser.server.privilege',
+  'pgadmin.browser.collection',
 ], function(
   gettext, url_for, pgBrowser, schemaChild, schemaChildTreeNode
 ) {
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/edbfuncs/static/js/edbfunc.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/edbfuncs/static/js/edbfunc.js
index 5bf697fe3..c9271ec7d 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/edbfuncs/static/js/edbfunc.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/edbfuncs/static/js/edbfunc.js
@@ -12,7 +12,7 @@ import EDBFuncSchema from './edbfunc.ui';
 /* Create and Register Function Collection and Node. */
 define('pgadmin.node.edbfunc', [
   'sources/gettext', 'sources/url_for', 'pgadmin.browser',
-  'pgadmin.browser.collection', 'pgadmin.browser.server.privilege',
+  'pgadmin.browser.collection',
 ], function(gettext, url_for, pgBrowser) {
 
   if (!pgBrowser.Nodes['coll-edbfunc']) {
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/edbfuncs/static/js/edbproc.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/edbfuncs/static/js/edbproc.js
index bf3c570a6..8ff5844a1 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/edbfuncs/static/js/edbproc.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/packages/edbfuncs/static/js/edbproc.js
@@ -15,7 +15,6 @@ define('pgadmin.node.edbproc', [
   'sources/gettext', 'sources/url_for',
   'sources/pgadmin', 'pgadmin.browser',
   'pgadmin.node.edbfunc', 'pgadmin.browser.collection',
-  'pgadmin.browser.server.privilege',
 ], function(
   gettext, url_for, pgAdmin, pgBrowser, EdbFunction
 ) {
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 490ad4a9c..ccfe4dba5 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
@@ -12,7 +12,7 @@ import EDBVarSchema from './edbvar.ui';
 /* Create and Register Function Collection and Node. */
 define('pgadmin.node.edbvar', [
   'sources/gettext', 'sources/url_for', 'pgadmin.browser',
-  'pgadmin.browser.collection', 'pgadmin.browser.server.privilege',
+  'pgadmin.browser.collection',
 ], function(gettext, url_for, pgBrowser) {
 
   if (!pgBrowser.Nodes['coll-edbvar']) {
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 0b4b588f8..5f8cfc4f4 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
@@ -10,297 +10,11 @@
 import PGSchema from './schema.ui';
 import { getNodePrivilegeRoleSchema } from '../../../../static/js/privilege.ui';
 import { getNodeListByName } from '../../../../../../static/js/node_ajax';
-import _ from 'lodash';
 
 define('pgadmin.node.schema', [
   'sources/gettext', 'sources/url_for', 'jquery',
-  'pgadmin.browser', 'pgadmin.backform', 'pgadmin.backgrid',
-  'pgadmin.browser.collection', 'pgadmin.browser.server.privilege',
-], function(gettext, url_for, $, pgBrowser, Backform, Backgrid) {
-
-  // VacuumSettings Collection to display all settings parameters as Grid
-  Backform.VacuumCollectionControl =
-    Backform.Control.extend({
-
-      grid_columns:undefined,
-
-      initialize: function() {
-        Backform.Control.prototype.initialize.apply(this, arguments);
-        let self = this,
-          m = this.model,
-          url = self.field.get('url');
-
-        if (url && m.isNew()) {
-          let node = self.field.get('node'),
-            node_data = self.field.get('node_data'),
-            node_info = self.field.get('node_info'),
-            full_url = node.generate_url.apply(
-              node, [
-                null, url, node_data, false, node_info,
-              ]),
-            data;
-          m.trigger('pgadmin-view:fetching', m, self.field);
-
-          // fetch default values for autovacuum fields
-          $.ajax({
-            async: false,
-            url: full_url,
-          })
-            .done(function (res) {
-              data = res;
-            })
-            .fail(function() {
-              m.trigger('pgadmin-view:fetch:error', m, self.field);
-            });
-          m.trigger('pgadmin-view:fetched', m, self.field);
-
-          // Add fetched models into collection
-          if (data && _.isArray(data)) {
-            m.get(self.field.get('name')).reset(data, {silent: true});
-          }
-        }
-      },
-      events : {
-        'keydown': 'keyDownHandler',
-      },
-
-      keyDownHandler : function(event){
-        // move the focus to editable input
-        let lastButton = $(this.$el).find('button:last');
-        let firstEditableCell = $(this.$el).find('td.editable:first');
-        if (event.keyCode== 9 && !event.shiftKey){
-          if ($(firstEditableCell).is(':visible')
-            && ($(event.target)).is($(lastButton))){
-            $(firstEditableCell).trigger('click');
-            event.preventDefault();
-            event.stopPropagation();
-          }
-        }
-      },
-
-      render: function() {
-        let self = this,
-          attributes = self.field.attributes;
-
-        // remove grid
-        if(self.grid) {
-          self.grid.remove();
-          delete self.grid;
-          self.grid = undefined;
-        }
-
-        self.$el.empty();
-
-        let gridHeader = _.template([
-            '<div class="subnode-header">',
-            '<% if (label && label != "") %> {',
-            '    <span class="control-label col-sm-4"><%-label%></span>',
-            '}',
-            '</div>'].join('\n')),
-          gridBody = $('<div class="pgadmin-control-group backgrid form-group col-12 object subnode"></div>').append(
-            gridHeader(attributes)
-          );
-
-        // Initialize a new Grid instance
-        let grid = self.grid = new Backgrid.Grid({
-          columns: self.grid_columns,
-          collection: self.model.get(self.field.get('name')),
-          className: 'backgrid table table-bordered table-noouter-border table-hover',
-        });
-
-        // render grid
-        self.$el.addClass('mb-0');
-        self.$el.append($(gridBody).append(grid.render().$el));
-
-        return self;
-      },
-    });
-
-  // We will use this function in VacuumSettings Control
-  // to convert data type on the fly
-  Backform.cellFunction = function(model) {
-    let vartype = model.get('column_type');
-
-    switch(vartype) {
-    case 'integer':
-      return Backgrid.IntegerCell;
-    case 'number':
-      return Backgrid.NumberCell.extend({
-        decimals: this.get('decimals') || Backgrid.NumberFormatter.prototype.defaults.decimals,
-      });
-    case 'string':
-      return Backgrid.StringCell;
-    default:
-      return Backgrid.Cell;
-    }
-  };
-
-  // Define Security Model with fields and validation for VacuumSettings Control
-  Backform.VacuumTableModel = pgBrowser.Node.Model.extend({
-    defaults: {
-      name: undefined,
-      setting: undefined,
-      label:undefined,
-      value: undefined,
-      column_type: undefined,
-    },
-
-    toJSON: function(){
-      let d = pgBrowser.Node.Model.prototype.toJSON.apply(this);
-      delete d.label;
-      delete d.setting;
-      delete d.column_type;
-      return d;
-    },
-  });
-
-  /* As Backform.VacuumSettingsSchema is commonly used in table & partition, so keeping it as it is for now.
-    this and other supporting model can be removed after their migration to react. */
-  // Extend the browser's collection class for VacuumSettingsModel
-  Backform.VacuumSettingsSchema = [{
-    id: 'spacer_ctrl', group: gettext('Table'), mode: ['edit', 'create'], type: 'spacer',
-  },{
-    id: 'autovacuum_custom', label: gettext('Custom auto-vacuum?'),
-    group: gettext('Table'), mode: ['edit', 'create'],
-    type: 'switch', controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12',
-    controlsClassName: 'pgadmin-controls pg-el-sm-8 pg-el-12',
-    disabled: function(m) {
-      // If table is partitioned table then disabled it.
-      if (m.top && m.top.get('is_partitioned')) {
-        // We also need to unset rest of all
-        setTimeout(function() {
-          m.set('autovacuum_custom', false);
-        }, 10);
-
-        return true;
-      }
-
-      return m.top.inSchema.apply(this, [m]);
-    },
-  },{
-    id: 'autovacuum_enabled', label: gettext('Autovacuum Enabled?'),
-    group: gettext('Table'), mode: ['edit', 'create'],
-    type: 'radioModern', controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12',
-    controlsClassName: 'pgadmin-controls pg-el-sm-8 pg-el-12',
-    options: [
-      {'label': gettext('Not set'), 'value': 'x'},
-      {'label': gettext('Yes'), 'value': 't'},
-      {'label': gettext('No'), 'value': 'f'},
-    ],
-    deps: ['autovacuum_custom'],
-    disabled: function(m) {
-      if(!m.top.inSchema.apply(this, [m]) && m.get('autovacuum_custom')) {
-        return false;
-      }
-
-      // We also need to unset rest of all
-      setTimeout(function() {
-        m.set('autovacuum_enabled', 'x');
-      }, 10);
-      return true;
-    },
-  },{
-    id: 'vacuum_table', label: '',
-    model: Backform.VacuumTableModel, editable: false, type: 'collection',
-    canEdit: true, group: gettext('Table'),
-    mode: ['edit', 'create'], url: 'get_table_vacuum',
-    control: Backform.VacuumCollectionControl.extend({
-      grid_columns :[
-        {
-          name: 'label', label: gettext('Label'),
-          headerCell: Backgrid.Extension.CustomHeaderCell,
-          cell: 'string', editable: false, cellHeaderClasses:'width_percent_40',
-        },
-        {
-          name: 'value', label: gettext('Value'),
-          cellHeaderClasses:'width_percent_30',
-          decimals: 5,
-          cellFunction: Backform.cellFunction, editable: function(m) {
-            return m.handler.get('autovacuum_custom');
-          }, headerCell: Backgrid.Extension.CustomHeaderCell,
-        },
-        {
-          name: 'setting', label: gettext('Default'),
-          cellHeaderClasses:'width_percent_30',
-          headerCell: Backgrid.Extension.CustomHeaderCell,
-          cellFunction: Backform.cellFunction, editable: false,
-        },
-      ],
-    }),
-    deps: ['autovacuum_custom'],
-  },{
-    id: 'spacer_ctrl', group: gettext('TOAST table'), mode: ['edit', 'create'], type: 'spacer',
-  },{
-    id: 'toast_autovacuum', label: gettext('Custom auto-vacuum?'),
-    group: gettext('TOAST table'), mode: ['edit', 'create'],
-    type: 'switch', controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12',
-    controlsClassName: 'pgadmin-controls pg-el-sm-8 pg-el-12',
-    disabled: function(m) {
-      // We need to check additional condition to toggle enable/disable
-      // for table auto-vacuum
-      return !(!m.top.inSchema.apply(this, [m]) &&
-        (m.isNew() || (m.get('toast_autovacuum_enabled') === true || m.top.get('hastoasttable') === true)));
-    },
-  },{
-    id: 'toast_autovacuum_enabled', label: gettext('Autovacuum Enabled?'),
-    group: gettext('TOAST table'), mode: ['edit', 'create'],
-    type: 'radioModern', controlLabelClassName: 'control-label pg-el-sm-4 pg-el-12',
-    controlsClassName: 'pgadmin-controls pg-el-sm-8 pg-el-12',
-    options: [
-      {'label': gettext('Not set'), 'value': 'x'},
-      {'label': gettext('Yes'), 'value': 't'},
-      {'label': gettext('No'), 'value': 'f'},
-    ],
-    deps:['toast_autovacuum'],
-    disabled: function(m) {
-      // If in schema & in create mode then enable it
-      if(!m.top.inSchema.apply(this, [m]) &&
-          m.get('toast_autovacuum') === true) {
-
-        return false;
-      }
-
-      if (m.isNew() || m.get('hastoasttable')) {
-        // we also need to unset rest of all
-        setTimeout(function() {
-          m.set('toast_autovacuum_enabled', 'x');
-        }, 10);
-      }
-      return true;
-    },
-  },{
-    id: 'vacuum_toast', label: '',
-    model: Backform.VacuumTableModel, type: 'collection', editable: function(m) {
-      return m.isNew();
-    },
-    canEdit: true, group: gettext('TOAST table'),
-    mode: ['properties', 'edit', 'create'], url: 'get_toast_table_vacuum',
-    control: Backform.VacuumCollectionControl.extend({
-      grid_columns :[
-        {
-          name: 'label', label: gettext('Label'),
-          headerCell: Backgrid.Extension.CustomHeaderCell,
-          cell: 'string', editable: false, cellHeaderClasses:'width_percent_40',
-        },
-        {
-          name: 'value', label: gettext('Value'),
-          cellHeaderClasses:'width_percent_30',
-          headerCell: Backgrid.Extension.CustomHeaderCell,
-          decimals: 5,
-          cellFunction: Backform.cellFunction, editable: function(m) {
-            return m.handler.get('toast_autovacuum');
-          },
-        },
-        {
-          name: 'setting', label: gettext('Default'),
-          cellHeaderClasses:'width_percent_30',
-          headerCell: Backgrid.Extension.CustomHeaderCell,
-          cellFunction: Backform.cellFunction, editable: false,
-        },
-      ],
-    }),
-    deps: ['toast_autovacuum'],
-  }];
+  'pgadmin.browser', 'pgadmin.browser.collection',
+], function(gettext, url_for, $, pgBrowser) {
 
   // Extend the browser's collection class for schema collection
   if (!pgBrowser.Nodes['coll-schema']) {
@@ -376,38 +90,5 @@ define('pgadmin.node.schema', [
     };
   }
 
-  /* As TableChildSwitchCell is commonly used in index, column & TableDialog, so keeping it as it is for now.
-    this and other supporting model can be removed after their migration to react. */
-  // Switch Cell with Deps (specifically for table children)
-  Backgrid.Extension.TableChildSwitchCell = Backgrid.Extension.SwitchCell.extend({
-    initialize: function() {
-      Backgrid.Extension.SwitchCell.prototype.initialize.apply(this, arguments);
-      Backgrid.Extension.DependentCell.prototype.initialize.apply(this, arguments);
-    },
-    dependentChanged: function () {
-      let model = this.model,
-        column = this.column,
-        editable = this.column.get('editable'),
-        input = this.$el.find('input[type=checkbox]').first(),
-        self_name = column.get('name'),
-        is_editable;
-
-      is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
-      if (is_editable) {
-        this.$el.addClass('editable');
-        input.bootstrapToggle('disabled',false);
-      } else {
-        this.$el.removeClass('editable');
-        input.bootstrapToggle('disabled',true);
-        // Set self value into model to false
-        setTimeout(function() { model.set(self_name, false); }, 10);
-      }
-
-      this.delegateEvents();
-      return this;
-    },
-    remove: Backgrid.Extension.DependentCell.prototype.remove,
-  });
-
   return pgBrowser.Nodes['schema'];
 });
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/primary_key.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/primary_key.js
index 006e70b9a..de4491be1 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/primary_key.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/static/js/primary_key.js
@@ -13,9 +13,9 @@ import _ from 'lodash';
 
 define('pgadmin.node.primary_key', [
   'sources/gettext', 'sources/url_for',
-  'sources/pgadmin', 'pgadmin.browser', 'pgadmin.backform', 'pgadmin.backgrid',
+  'sources/pgadmin', 'pgadmin.browser',
   'pgadmin.browser.collection',
-], function(gettext, url_for, pgAdmin, pgBrowser, Backform, Backgrid) {
+], function(gettext, url_for, pgAdmin, pgBrowser) {
 
   // Extend the browser's node class for index constraint node
   if (!pgBrowser.Nodes['primary_key']) {
@@ -166,447 +166,6 @@ define('pgadmin.node.primary_key', [
           // We can't update columns of existing index constraint.
           return !m.isNew();
         },
-        // Define the schema for the index constraint node
-        schema: [{
-          id: 'name', label: gettext('Name'), type: 'text',
-          mode: ['properties', 'create', 'edit'], editable:true,
-          cellHeaderClasses:'width_percent_40',
-        },{
-          id: 'oid', label: gettext('OID'), cell: 'string',
-          type: 'text' , mode: ['properties'], editable: false,
-          cellHeaderClasses:'width_percent_20',
-        },{
-          id: 'is_sys_obj', label: gettext('System primary key?'),
-          cell:'boolean', type: 'switch', mode: ['properties'],
-        },{
-          id: 'comment', label: gettext('Comment'), cell: 'string',
-          type: 'multiline', mode: ['properties', 'create', 'edit'],
-          deps:['name'], disabled:function(m) {
-            let name = m.get('name');
-            if (!(name && name != '')) {
-              setTimeout(function(){
-                if(m.get('comment') && m.get('comment') !== '') {
-                  m.set('comment', null);
-                }
-              },10);
-              return true;
-            } else {
-              return false;
-            }
-          },
-        },{
-          id: 'columns', label: gettext('Columns'),
-          type: 'collection', group: gettext('Definition'),
-          editable: false,
-          cell: Backgrid.StringCell.extend({
-            initialize: function() {
-              Backgrid.StringCell.prototype.initialize.apply(this, arguments);
-
-              let self = this,
-                collection = this.model.get('columns');
-
-              // Do not listen for any event(s) for existing constraint.
-              if (_.isUndefined(self.model.get('oid'))) {
-                let tableCols = self.model.top.get('columns');
-                self.listenTo(tableCols, 'remove' , self.removeColumn);
-                self.listenTo(tableCols, 'change:name', self.resetColOptions);
-              }
-
-              collection.on('pgadmin:multicolumn:updated', function() {
-                self.render.apply(self);
-              });
-              self.listenTo(collection, 'add', self.render);
-              self.listenTo(collection, 'remove', self.render);
-            },
-            removeColumn: function(m) {
-              let self = this,
-                removedCols = self.model.get('columns').where(
-                  {column: m.get('name')}
-                );
-
-              self.model.get('columns').remove(removedCols);
-              setTimeout(function () {
-                self.render();
-              }, 10);
-
-              let key = 'primary_key';
-              setTimeout(function () {
-                let constraints = self.model.top.get(key),
-                  removed = [];
-                constraints.each(function(constraint) {
-                  if (constraint.get('columns').length == 0) {
-                    removed.push(constraint);
-                  }
-                });
-                constraints.remove(removed);
-              },100);
-
-            },
-            resetColOptions : function(m) {
-              let self = this,
-                updatedCols = self.model.get('columns').where(
-                  {column: m.previous('name')}
-                );
-              if (updatedCols.length > 0) {
-                /*
-                 * Table column name has changed so update
-                 * column name in primary key as well.
-                 */
-                updatedCols[0].set(
-                  {'column': m.get('name')},
-                  {silent: true});
-              }
-
-              setTimeout(function () {
-                self.render();
-              }, 10);
-            },
-            formatter: {
-              fromRaw: function (rawValue) {
-                return rawValue.pluck('column').toString();
-              },
-              toRaw: function (val) { return val; },
-            },
-            render: function() {
-              return Backgrid.StringCell.prototype.render.apply(this, arguments);
-            },
-            remove: function() {
-              let tableCols = this.model.top.get('columns'),
-                primary_key_col = this.model.get('columns');
-
-              if (primary_key_col) {
-                primary_key_col.off('pgadmin:multicolumn:updated');
-              }
-
-              this.stopListening(tableCols, 'remove' , self.removeColumn);
-              this.stopListening(tableCols, 'change:name' , self.resetColOptions);
-
-              Backgrid.StringCell.prototype.remove.apply(this, arguments);
-            },
-          }),
-          canDelete: true, canAdd: true,
-          control: Backform.MultiSelectAjaxControl.extend({
-            defaults: _.extend(
-              {},
-              Backform.NodeListByNameControl.prototype.defaults,
-              {
-                select2: {
-                  multiple: true,
-                  allowClear: true,
-                  width: 'style',
-                  placeholder: gettext('Select the column(s)'),
-                },
-              }
-            ),
-            keyPathAccessor: function(obj, path) {
-              let res = obj;
-              if(_.isArray(res)) {
-                return _.map(res, function(o) { return o['column'];
-                });
-              }
-              path = path.split('.');
-              for (let path_val of path) {
-                if (_.isNull(res)) return null;
-                if (_.isEmpty(path_val)) continue;
-                if (!_.isUndefined(res[path_val])) res = res[path_val];
-              }
-              return _.isObject(res) && !_.isArray(res) ? null : res;
-            },
-            initialize: function() {
-              // Here we will decide if we need to call URL
-              // Or fetch the data from parent columns collection
-              let self = this;
-              if(this.model.handler) {
-                Backform.Select2Control.prototype.initialize.apply(this, arguments);
-                // Do not listen for any event(s) for existing constraint.
-                if (_.isUndefined(self.model.get('oid'))) {
-                  let tableCols = self.model.top.get('columns');
-                  self.listenTo(tableCols, 'remove' , self.resetColOptions);
-                  self.listenTo(tableCols, 'change:name', self.resetColOptions);
-                }
-
-                self.custom_options();
-              } else {
-                Backform.MultiSelectAjaxControl.prototype.initialize.apply(this, arguments);
-              }
-              self.model.get('columns').on('pgadmin:multicolumn:updated', function() {
-                self.render.apply(self);
-              });
-            },
-            resetColOptions: function() {
-              this.genResetColOptions();
-            },
-            custom_options: function() {
-              this.genCustomOptions();
-            },
-            onChange: function() {
-              let self = this,
-                model = this.model,
-                attrArr = this.field.get('name').split('.'),
-                name = attrArr.shift(),
-                vals = this.getValueFromDOM(),
-                collection = model.get(name),
-                removed = [];
-
-              this.stopListening(this.model, 'change:' + name, this.render);
-
-              /*
-                 * Iterate through all the values, and find out how many are already
-                 * present in the collection.
-                 */
-              collection.each(function(m) {
-                let column = m.get('column'),
-                  idx = _.indexOf(vals, column);
-
-                if (idx > -1) {
-                  vals.splice(idx, 1);
-                } else {
-                  removed.push(column);
-                }
-              });
-
-              /*
-                 * Adding new values
-                 */
-
-              _.each(vals, function(v) {
-                let m = new (self.field.get('model'))(
-                  {column: v}, { silent: true,
-                    top: self.model.top,
-                    collection: collection,
-                    handler: collection,
-                  });
-
-                collection.add(m);
-              });
-
-              /*
-                 * Removing unwanted!
-                 */
-              _.each(removed, function(v) {
-                collection.remove(collection.where({column: v}));
-              });
-
-              this.listenTo(this.model, 'change:' + name, this.render);
-            },
-            remove: function() {
-              if(this.model.handler) {
-                let self = this,
-                  tableCols = self.model.top.get('columns');
-                self.stopListening(tableCols, 'remove' , self.resetColOptions);
-                self.stopListening(tableCols, 'change:name' , self.resetColOptions);
-                self.model.get('columns').off('pgadmin:multicolumn:updated');
-
-                Backform.Select2Control.prototype.remove.apply(this, arguments);
-
-              } else {
-                Backform.MultiSelectAjaxControl.prototype.remove.apply(this, arguments);
-              }
-            },
-            render: function() {
-              let index = this.model.get('index');
-              if(!_.isUndefined(index) && index != '') {
-                let col = this.model.get('columns');
-                col.reset([], {silent: true});
-              }
-              return Backform.Select2Control.prototype.render.apply(this, arguments);
-            },
-          }),
-          deps: ['index'], node: 'column',
-          model: pgBrowser.Node.Model.extend({
-            defaults: {
-              column: undefined,
-            },
-            validate: function() {
-              return null;
-            },
-          }),
-          transform : function(data){
-            let res = [];
-            if (data && _.isArray(data)) {
-              _.each(data, function(d) {
-                res.push({label: d.label, value: d.label, image:'icon-column'});
-              });
-            }
-            return res;
-          },
-          select2:{allowClear:false},
-          readonly: function(m) {
-            return this.checkReadOnly(m);
-          },
-          disabled: function(m) {
-            // Disable if index is selected.
-            let index = m.get('index');
-            return !(_.isUndefined(index) || index == '');
-          },
-        },{
-          id: 'include', label: gettext('Include columns'),
-          type: 'array', group: gettext('Definition'),
-          editable: false,
-          canDelete: true, canAdd: true, mode: ['properties', 'create', 'edit'],
-          visible: function(m) {
-            /* In table properties, m.node_info is not available */
-            m = m.top;
-            return (!_.isUndefined(m.node_info) && !_.isUndefined(m.node_info.server)
-              && !_.isUndefined(m.node_info.server.version) &&
-              m.node_info.server.version >= 110000);
-          },
-          control: Backform.MultiSelectAjaxControl.extend({
-            defaults: _.extend(
-              {},
-              Backform.NodeListByNameControl.prototype.defaults,
-              {
-                select2: {
-                  allowClear: false,
-                  width: 'style',
-                  multiple: true,
-                  placeholder: gettext('Select the column(s)'),
-                },
-              }
-            ),
-            initialize: function() {
-              // Here we will decide if we need to call URL
-              // Or fetch the data from parent columns collection
-              let self = this;
-              if(this.model.handler) {
-                Backform.Select2Control.prototype.initialize.apply(this, arguments);
-                // Do not listen for any event(s) for existing constraint.
-                if (_.isUndefined(self.model.get('oid'))) {
-                  let tableCols = self.model.top.get('columns');
-                  self.listenTo(tableCols, 'remove' , self.resetColOptions);
-                  self.listenTo(tableCols, 'change:name', self.resetColOptions);
-                }
-
-                self.custom_options();
-              } else {
-                Backform.MultiSelectAjaxControl.prototype.initialize.apply(this, arguments);
-              }
-            },
-            resetColOptions: function() {
-              this.genResetColOptions();
-            },
-            custom_options: function() {
-              this.genCustomOptions();
-            },
-          }),
-          deps: ['index'], node: 'column',
-          readonly: function(m) {
-            return this.checkReadOnly(m);
-          },
-          disabled: function(m) {
-            // Disable if index is selected.
-            let index = m.get('index');
-            if(_.isUndefined(index) || index == '') {
-              return false;
-            } else {
-              setTimeout(function(){
-                m.set('include', []);
-              },10);
-              return true;
-            }
-          },
-        },{
-          id: 'spcname', label: gettext('Tablespace'),
-          type: 'text', group: gettext('Definition'),
-          control: 'node-list-by-name', node: 'tablespace',
-          deps: ['index'],
-          select2:{allowClear:false},
-          filter: function(m) {
-            // Don't show pg_global tablespace in selection.
-            return (m.label != 'pg_global');
-          },
-          disabled: function(m) {
-            // Disable if index is selected.
-            m = m.top || m;
-            let index = m.get('index');
-            if(_.isUndefined(index) || index == '') {
-              return false;
-            } else {
-              setTimeout(function(){
-                m.set('spcname', '');
-              },10);
-              return true;
-            }
-          },
-        },{
-          id: 'index', label: gettext('Index'),
-          mode: ['create'],
-          type: 'text', group: gettext('Definition'),
-          control: Backform.NodeListByNameControl.extend({
-            initialize:function() {
-              Backform.NodeListByNameControl.prototype.initialize.apply(this, arguments);
-            },
-          }),
-          select2:{allowClear:true}, node: 'index',
-          readonly: function(m) {
-            // If we are in table edit mode then disable it
-            if (_.has(m, 'top') && !_.isUndefined(m.top)
-              && !m.top.isNew()) {
-              return true;
-            }
-
-            // We can't update index of existing index constraint.
-            return !m.isNew();
-          },
-          // We will not show this field in Create Table mode
-          visible: function(m) {
-            return !_.isUndefined(m.top.node_info['table']);
-          },
-        },{
-          id: 'fillfactor', label: gettext('Fill factor'), deps: ['index'],
-          type: 'int', group: gettext('Definition'), allowNull: true,
-          disabled: function(m) {
-            // Disable if index is selected.
-            let index = m.get('index');
-            if(_.isUndefined(index) || index == '') {
-              return false;
-            } else {
-              setTimeout(function(){
-                m.set('fillfactor', null);
-              },10);
-              return true;
-            }
-          },
-        },{
-          id: 'condeferrable', label: gettext('Deferrable?'),
-          type: 'switch', group: gettext('Definition'), deps: ['index'],
-          readonly: function(m) {
-            return this.checkReadOnly(m);
-          },
-          disabled: function(m) {
-            // Disable if index is selected.
-            let index = m.get('index');
-            if(_.isUndefined(index) || index == '') {
-              return false;
-            } else {
-              setTimeout(function(){
-                if(m.get('condeferrable'))
-                  m.set('condeferrable', false);
-              },10);
-              return true;
-            }
-          },
-        },{
-          id: 'condeferred', label: gettext('Deferred?'),
-          type: 'switch', group: gettext('Definition'),
-          deps: ['condeferrable'],
-          readonly: function(m) {
-            return this.checkReadOnly(m);
-          },
-          disabled: function(m) {
-            // Disable if condeferred is false or unselected.
-            if(m.get('condeferrable')) {
-              return false;
-            } else {
-              setTimeout(function(){
-                if(m.get('condeferred'))
-                  m.set('condeferred', false);
-              },10);
-              return true;
-            }
-          },
-        },
-        ],
         validate: function() {
           this.errorModel.clear();
           // Clear parent's error as well
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 4bde610f7..7c2577949 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
@@ -19,7 +19,6 @@ define('pgadmin.node.mview', [
   'sources/pgadmin', 'pgadmin.browser',
   'pgadmin.node.schema.dir/child',
   'pgadmin.node.schema.dir/schema_child_tree_node', 'sources/utils',
-  'pgadmin.browser.server.privilege',
 ], function(
   gettext, url_for, $, pgAdmin, pgBrowser,
   schemaChild, schemaChildTreeNode, commonUtils
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 829ddca3b..aad666035 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
@@ -14,7 +14,7 @@ import ViewSchema from './view.ui';
 define('pgadmin.node.view', [
   'sources/gettext', 'sources/url_for', 'pgadmin.browser',
   'pgadmin.node.schema.dir/child', 'pgadmin.node.schema.dir/schema_child_tree_node',
-  'pgadmin.browser.server.privilege', 'pgadmin.node.rule',
+  'pgadmin.node.rule',
 ], function(
   gettext, url_for, pgBrowser, schemaChild, schemaChildTreeNode
 ) {
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 82b0bad47..34418bb2f 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
@@ -19,7 +19,6 @@ define('pgadmin.node.database', [
   'sources/gettext', 'sources/url_for', 'jquery',
   'sources/pgadmin', 'pgadmin.browser.utils',
   'pgadmin.authenticate.kerberos', 'pgadmin.browser.collection',
-  'pgadmin.browser.server.privilege', 'pgadmin.browser.server.variable',
 ], function(gettext, url_for, $, pgAdmin, pgBrowser, Kerberos) {
 
   if (!pgBrowser.Nodes['coll-database']) {
diff --git a/web/pgadmin/browser/server_groups/servers/pgagent/steps/static/js/pga_jobstep.js b/web/pgadmin/browser/server_groups/servers/pgagent/steps/static/js/pga_jobstep.js
index 341f979c5..676be3d98 100644
--- a/web/pgadmin/browser/server_groups/servers/pgagent/steps/static/js/pga_jobstep.js
+++ b/web/pgadmin/browser/server_groups/servers/pgagent/steps/static/js/pga_jobstep.js
@@ -11,9 +11,8 @@ import { getNodePgaJobStepSchema } from './pga_jobstep.ui';
 import _ from 'lodash';
 
 define('pgadmin.node.pga_jobstep', [
-  'sources/gettext', 'sources/url_for', 'pgadmin.browser', 'backform',
-  'backgrid', 'pgadmin.backform',
-], function(gettext, url_for, pgBrowser, Backform) {
+  'sources/gettext', 'sources/url_for', 'pgadmin.browser',
+], function(gettext, url_for, pgBrowser) {
 
   if (!pgBrowser.Nodes['coll-pga_jobstep']) {
     pgBrowser.Nodes['coll-pga_jobstep'] =
@@ -93,37 +92,6 @@ define('pgadmin.node.pga_jobstep', [
           }
         },
         idAttribute: 'jstid',
-        schema: [{
-          id: 'jstid', label: gettext('ID'), type: 'int',
-          cellHeaderClasses: 'width_percent_5', mode: ['properties'],
-        },{
-          id: 'jstname', label: gettext('Name'), type: 'text',
-          cellHeaderClasses: 'width_percent_60',
-        },{
-          id: 'jstenabled', label: gettext('Enabled?'),
-          type: 'switch',
-        },{
-          id: 'jstkind', label: gettext('Kind'), type: 'switch',
-          options: {
-            'onText': gettext('SQL'), 'offText': gettext('Batch'),
-            'onColor': 'primary', 'offColor': 'primary',
-          }, control: Backform.SwitchControl,
-        },{
-          id: 'jstconntype', label: gettext('Connection type'),
-          type: 'switch', deps: ['jstkind'], mode: ['properties'],
-          disabled: function(m) { return !m.get('jstkind'); },
-          options: {
-            'onText': gettext('Local'), 'offText': gettext('Remote'),
-            'onColor': 'primary', 'offColor': 'primary', width: '65',
-          },
-        },{
-          id: 'jstonerror', label: gettext('On error'), cell: 'select2',
-          control: 'select2', options: [
-            {'label': gettext('Fail'), 'value': 'f'},
-            {'label': gettext('Success'), 'value': 's'},
-            {'label': gettext('Ignore'), 'value': 'i'},
-          ], select2: {allowClear: false},
-        }],
       }),
     });
   }
diff --git a/web/pgadmin/browser/server_groups/servers/static/js/privilege.js b/web/pgadmin/browser/server_groups/servers/static/js/privilege.js
deleted file mode 100644
index 28ebdda59..000000000
--- a/web/pgadmin/browser/server_groups/servers/static/js/privilege.js
+++ /dev/null
@@ -1,765 +0,0 @@
-/////////////////////////////////////////////////////////////
-//
-// pgAdmin 4 - PostgreSQL Tools
-//
-// Copyright (C) 2013 - 2022, The pgAdmin Development Team
-// This software is released under the PostgreSQL Licence
-//
-//////////////////////////////////////////////////////////////
-
-import _ from 'lodash';
-
-define(['sources/gettext', 'jquery', 'backbone',
-  'backgrid', 'pgadmin.browser.node', 'sources/utils', 'pgadmin.browser.node.ui',
-], function(gettext, $, Backbone, Backgrid, pgNode, commonUtils) {
-  /**
-   * Each Privilege, supporeted by an database object, will be represented
-   * using this Model.
-   *
-   * Defaults:
-   *   privilege_type -> Name of the permission
-   *      i.e. CREATE, TEMPORARY, CONNECT, etc.
-   *   privilege      -> Has privilege? (true/false)
-   *   with_grant     -> Has privilege with grant option (true/false)
-   **/
-  let PrivilegeModel = pgNode.Model.extend({
-    idAttribute: 'privilege_type',
-    defaults: {
-      privilege_type: undefined,
-      privilege: false,
-      with_grant: false,
-    },
-    validate: function() {
-      return null;
-    },
-  });
-
-  /**
-   * A database object has privileges item list (aclitem[]).
-   *
-   * This model represents the individual privilege item (aclitem).
-   * It has basically three properties:
-   *  + grantee    - Role to which that privilege applies to.
-   *                Empty value represents to PUBLIC.
-   *  + grantor    - Grantor who has given this permission.
-   *  + privileges - Privileges for that role.
-   **/
-  let PrivilegeRoleModel = pgNode.PrivilegeRoleModel = pgNode.Model.extend({
-    idAttribute: 'grantee',
-    defaults: {
-      grantee: undefined,
-      grantor: undefined,
-      privileges: undefined,
-    },
-    keys: ['grantee', 'grantor'],
-    /*
-     * Each of the database object needs to extend this model, which should
-     * provide the type of privileges (it supports).
-     */
-    privileges:[],
-    schema: [{
-      id: 'grantee', label: gettext('Grantee'), type:'text', group: null,
-      editable: true, cellHeaderClasses: 'width_percent_40',
-      node: 'role', options_cached: false,
-      disabled : function(m) {
-        if (!(m instanceof Backbone.Model)) {
-          // This has been called during generating the header cell
-          return false;
-        }
-        return !(
-          m.top && m.top.node_info &&
-            m.top.node_info.server.user.name == m.get('grantor')
-        );
-      },
-      transform: function() {
-        let res =
-          Backgrid.Extension.NodeListByNameCell.prototype.defaults.transform.apply(
-            this, arguments
-          );
-        res.unshift({label: 'PUBLIC', value: 'PUBLIC'});
-        return res;
-      },
-      cell: Backgrid.Extension.NodeListByNameCell.extend({
-        initialize: function(opts) {
-          let self = this,
-            override_opts = true;
-
-          // We would like to override the original options, because - we
-          // should omit the existing role/user from the privilege cell.
-          // Because - the column is shared among all the cell, we can only
-          // override only once.
-          if (opts && opts.column &&
-            opts.column instanceof Backbone.Model &&
-              opts.column.get('options_cached')) {
-            override_opts = false;
-          }
-          Backgrid.Extension.NodeListByNameCell.prototype.initialize.apply(
-            self, arguments
-          );
-
-          // Let's override the options
-          if (override_opts) {
-            opts = self.column.get('options');
-            self.column.set(
-              'options', self.omit_selected_roles.bind(self, opts)
-            );
-          }
-
-          let rerender = function (m) {
-            let _self = this;
-            if ('grantee' in m.changed && this.model.cid != m.cid) {
-              setTimeout(
-                function() {
-                  _self.render();
-                }, 50
-              );
-            }
-          }.bind(this);
-
-          // We would like to rerender all the cells of this type for this
-          // collection, because - we need to omit the newly selected roles
-          // form the list. Also, the render will be automatically called for
-          // the model represented by this cell, we will not do that again.
-          this.listenTo(self.model.collection, 'change', rerender, this);
-          this.listenTo(self.model.collection, 'remove', rerender, this);
-        },
-        // Remove all the selected roles (though- not mine).
-        omit_selected_roles: function(opts, cell) {
-          let res = opts(cell),
-            selected = {},
-            model = cell.model,
-            cid = model.cid,
-            // We need to check node_info values in parent when object is nested.
-            // eg: column level privileges in table dialog
-            // In this case node_info will not be avilable to column node as
-            // it is not loaded yet
-            node_info = (_.has(model.top, 'node_info')
-              && !_.isUndefined(model.top.node_info)) ?
-              model.top.node_info :
-              model.handler.top.node_info,
-            curr_user = node_info.server.user.name;
-
-          model.collection.each(function(m) {
-            let grantee = m.get('grantee');
-
-            if (m.cid != cid && !_.isUndefined(grantee) &&
-              curr_user == m.get('grantor')) {
-              selected[grantee] = m.cid;
-            }
-          });
-
-          res = _.filter(res, function(o) {
-            return !(o.value in selected);
-          });
-
-          return res;
-        },
-      }),
-    },{
-      id: 'privileges', label: gettext('Privileges'),
-      type: 'collection', model: PrivilegeModel, group: null,
-      cell: 'privilege', control: 'text', cellHeaderClasses: 'width_percent_40',
-      disabled : function(column) {
-        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: gettext('Grantor'), type: 'text', readonly: true,
-      cell: 'node-list-by-name', node: 'role',
-    }],
-
-    /*
-     * Initialize the model, which will transform the privileges string to
-     * collection of Privilege Model.
-     */
-    initialize: function(attrs, opts) {
-
-      pgNode.Model.prototype.initialize.apply(this, arguments);
-
-      if (_.isNull(attrs)) {
-        this.set(
-          'grantor',
-          opts && opts.top && opts.top.node_info && opts.top.node_info.server.user.name,
-          {silent: true}
-        );
-      }
-
-      /*
-       * Define the collection of the privilege supported by this model
-       */
-      let self = this,
-        models = self.get('privileges'),
-        privileges = this.get('privileges') || {};
-
-      if (_.isArray(privileges)) {
-        privileges = new (pgNode.Collection)(
-          models, {
-            model: PrivilegeModel,
-            top: this.top || this,
-            handler: this,
-            silent: true,
-            parse: false,
-          });
-        this.set('privileges', privileges, {silent: true});
-      }
-
-      let privs = {};
-      _.each(self.privileges, function(p) {
-        privs[p] = {
-          'privilege_type': p, 'privilege': false, 'with_grant': false,
-        };
-      });
-
-      privileges.each(function(m) {
-        delete privs[m.get('privilege_type')];
-      });
-
-      _.each(privs, function(p) {
-        privileges.add(p, {silent: true});
-      });
-
-      self.on('change:grantee', self.granteeChanged);
-      privileges.on('change', function() {
-        self.trigger('change:privileges', self);
-      });
-
-      return self;
-    },
-
-    granteeChanged: function() {
-      let privileges = this.get('privileges'),
-        grantee = this.get('grantee');
-
-      // Reset all with grant options if grantee is public.
-      if (grantee == 'PUBLIC') {
-        privileges.each(function(m) {
-          m.set('with_grant', false, {silent: true});
-        });
-      }
-    },
-
-    toJSON: function() {
-
-      let privileges = [];
-
-      if (this.attributes &&
-        !this.attributes['privileges']) {
-        return null;
-      }
-
-      this.attributes['privileges'].each(
-        function(p) {
-          if (p.get('privilege')) {
-            privileges.push(p.toJSON());
-          }
-        });
-
-      return {
-        'grantee': this.get('grantee'),
-        'grantor': this.get('grantor'),
-        'privileges': privileges,
-      };
-    },
-
-    validate: function() {
-      let  errmsg = null,
-        msg;
-
-      if (_.isUndefined(this.get('grantee'))) {
-        msg = gettext('A grantee must be selected.');
-        this.errorModel.set('grantee', msg);
-        errmsg = msg;
-      } else {
-        this.errorModel.unset('grantee');
-      }
-
-      if (this.attributes &&
-        this.attributes['privileges']) {
-        let anyPrivSelected = false;
-        this.attributes['privileges'].each(
-          function(p) {
-            if (p.get('privilege')) {
-              anyPrivSelected = true;
-            }
-          });
-
-        if (!anyPrivSelected) {
-          msg = gettext('At least one privilege should be selected.');
-          this.errorModel.set('privileges', msg);
-          errmsg = errmsg || msg;
-        } else {
-          this.errorModel.unset('privileges');
-        }
-      }
-
-      return errmsg;
-    },
-  });
-
-  /**
-   Custom cell editor for editing privileges.
-   */
-  let PrivilegeCellEditor = Backgrid.Extension.PrivilegeCellEditor =
-    Backgrid.CellEditor.extend({
-      tagName: 'div',
-
-      // All available privileges in the PostgreSQL database server for
-      // generating the label for the specific Control
-      Labels: {
-        'C': 'CREATE',
-        'T': 'TEMPORARY',
-        'c': 'CONNECT',
-        'a': 'INSERT',
-        'r': 'SELECT',
-        'w': 'UPDATE',
-        'd': 'DELETE',
-        'D': 'TRUNCATE',
-        'x': 'REFERENCES',
-        't': 'TRIGGER',
-        'U': 'USAGE',
-        'X': 'EXECUTE',
-      },
-
-      template: _.template([
-        '<tr class="<%= header ? "header" : "" %>">',
-        ' <td class="renderable">',
-        '  <div class="custom-control custom-checkbox privilege-checkbox">',
-        '    <input tabindex="0" type="checkbox" class="custom-control-input" id="<%= checkbox_id %>" name="privilege" privilege="<%- privilege_type %>" target="<%- target %>" <%= privilege ? \'checked\' : "" %>/>',
-        '    <label class="custom-control-label" for="<%= checkbox_id %>">',
-        '      <%- privilege_label %>',
-        '    </label>',
-        '  </div>',
-        ' </td>',
-        ' <td class="renderable">',
-        '  <div class="custom-control custom-checkbox privilege-checkbox">',
-        '    <input tabindex="0" type="checkbox" class="custom-control-input" id="wgo_<%= checkbox_id %>" name="with_grant" privilege="<%- privilege_type %>" target="<%- target %>" <%= with_grant ? \'checked\' : "" %> <%= enable_with_grant ? "" : \'disabled\'%>/>',
-        '    <label class="custom-control-label" for="wgo_<%= checkbox_id %>">',
-        '      WITH GRANT OPTION',
-        '    </label>',
-        '  </div>',
-        ' </td>',
-        '</tr>'].join(' '), null, {variable: null}),
-
-      events: {
-        'change': 'privilegeChanged',
-        'blur': 'lostFocus',
-        'keydown': 'lostFocus',
-      },
-
-      render: function () {
-        this.$el.empty();
-        this.$el.attr('tabindex', '1');
-        this.$el.attr('target', this.elId);
-
-        let collection = this.model.get(this.column.get('name')),
-          tbl = $('<table aria-label='+this.column.get('label')+'></table>').appendTo(this.$el),
-          self = this,
-          privilege = true, with_grant = true;
-
-        // For each privilege generate html template.
-        // List down all the Privilege model.
-        let checkbox_id = _.uniqueId();
-        collection.each(function(m) {
-          let d = m.toJSON();
-
-          privilege = (privilege && d.privilege);
-          with_grant = (with_grant && privilege && d.with_grant);
-
-          _.extend(
-            d, {
-              'target': self.cid,
-              'header': false,
-              'privilege_label': self.Labels[d.privilege_type],
-              'with_grant': (self.model.get('grantee') != 'PUBLIC' && d.with_grant),
-              'enable_with_grant': (self.model.get('grantee') != 'PUBLIC' && d.privilege),
-              'checkbox_id': d.privilege_type + '' + checkbox_id,
-            });
-          privilege = (privilege && d.privilege);
-          with_grant = (with_grant && privilege && d.with_grant);
-          tbl.append(self.template(d));
-        });
-
-        if (collection.length > 1) {
-          // Preprend the ALL controls on that table
-          tbl.prepend(
-            self.template({
-              'target': self.cid,
-              'privilege_label': 'ALL',
-              'privilege_type': 'ALL',
-              'privilege': privilege,
-              'with_grant': (self.model.get('grantee') != 'PUBLIC' && with_grant),
-              'enable_with_grant': (self.model.get('grantee') != 'PUBLIC' && privilege),
-              'header': true,
-              'checkbox_id': 'all' + '' + checkbox_id,
-            }));
-        }
-        self.$el.find('input[type=checkbox]').first().trigger('focus');
-        // Since blur event does not bubble we need to explicitly call parent's blur event.
-        $(self.$el.find('input[type=checkbox]')).on('blur',function() {
-          self.$el.trigger('blur');
-        });
-
-        // Make row visible in when entering in edit mode.
-        $(self.$el).pgMakeVisible('backform-tab');
-
-        self.delegateEvents();
-
-        return this;
-      },
-
-      /*
-       * Listen to the checkbox value change and update the model accordingly.
-       */
-      privilegeChanged: function(ev) {
-
-        if (ev && ev.target) {
-          /*
-           * We're looking for checkboxes only.
-           */
-          let $el = $(ev.target),
-            privilege_type = $el.attr('privilege'),
-            type = $el.attr('name'),
-            checked = $el.prop('checked'),
-            $tr = $el.closest('tr'),
-            $tbl = $tr.closest('table'),
-            collection = this.model.get('privileges'),
-            grantee = this.model.get('grantee'), $allGrants,
-            $allPrivileges, $elGrant;
-
-          this.undelegateEvents();
-          /*
-           * If the checkbox selected/deselected is for 'ALL', we will select all
-           * the checkbox for each privilege.
-           */
-          if (privilege_type == 'ALL') {
-            let allPrivilege, allWithGrant;
-
-            $elGrant = $tr.find('input[name=with_grant]');
-            $allPrivileges = $tbl.find(
-              'input[name=privilege][privilege!=\'ALL\']'
-            );
-            $allGrants = $tbl.find(
-              'input[name=with_grant][privilege!=\'ALL\']'
-            );
-
-            if (type == 'privilege') {
-              /*
-               * We clicked the privilege checkbox, and not checkbox for with
-               * grant options.
-               */
-              allPrivilege = checked;
-              allWithGrant = false;
-
-              if (checked) {
-                $allPrivileges.prop('checked', true);
-
-                /*
-                 * We have clicked the ALL checkbox, we should be able to select
-                 * the grant options too.
-                 */
-                if (grantee == 'PUBLIC') {
-                  $allGrants.prop('disabled', true);
-                  $elGrant.prop('disabled', true);
-                } else {
-                  $allGrants.prop('disabled', false);
-                  $elGrant.prop('disabled', false);
-                }
-
-              } else {
-                /*
-                 * ALL checkbox has been deselected, hence - we need to make
-                 * sure.
-                 * 1. Deselect all the privileges checkboxes
-                 * 2. Deselect and disable all with grant privilege checkboxes.
-                 * 3. Deselect and disable the checkbox for ALL with grant privilege.
-                 */
-                $allPrivileges.prop('checked', false);
-                $elGrant.prop('checked', false);
-                $allGrants.prop('checked', false);
-                $elGrant.prop('disabled', true);
-                $allGrants.prop('disabled', true);
-              }
-            } else {
-              /*
-               * We were able to click the ALL with grant privilege checkbox,
-               * that means, privilege for Privileges are true.
-               *
-               * We need to select/deselect all the with grant options
-               * checkboxes, based on the current value of the ALL with grant
-               * privilege checkbox.
-               */
-              allPrivilege = true;
-              allWithGrant = checked;
-              $allGrants.prop('checked', checked);
-            }
-
-            /*
-             * Set the values for each Privilege Model.
-             */
-            collection.each(function(m) {
-              m.set(
-                {'privilege': allPrivilege, 'with_grant': allWithGrant}
-              );
-            });
-          } else {
-            /*
-             * Particular privilege has been selected/deselected, which can be
-             * identified using the privilege="X" attribute.
-             */
-            let attrs = {};
-
-            $tbl = $tr.closest('table');
-            $allPrivileges = $tbl.find(
-              'input[name=privilege][privilege=\'ALL\']'
-            );
-            $allGrants = $tbl.find(
-              'input[name=with_grant][privilege=\'ALL\']'
-            );
-
-            attrs[type] = checked;
-
-            if (type == 'privilege') {
-              $elGrant = ($el.closest('tr')).find('input[name=with_grant]');
-              if (!checked) {
-                attrs['with_grant'] = false;
-
-                $elGrant.prop('checked', false).prop('disabled', true);
-                $allPrivileges.prop('checked', false);
-                $allGrants.prop('disabled', true);
-                $allGrants.prop('checked', false);
-              } else if (grantee != 'PUBLIC') {
-                $elGrant.prop('disabled', false);
-              }
-            } else if (!checked) {
-              $allGrants.prop('checked', false);
-            }
-            collection.get(privilege_type).set(attrs);
-
-            if (checked) {
-              $allPrivileges = $tbl.find(
-                'input[name=privilege][privilege!=\'ALL\']:checked'
-              );
-
-              if ($allPrivileges.length > 1 &&
-                $allPrivileges.length == collection.models.length) {
-
-                $allPrivileges.prop('checked', true);
-
-                if (type == 'with_grant') {
-                  $allGrants = $tbl.find(
-                    'input[name=with_grant][privilege!=\'ALL\']:checked'
-                  );
-                  if ($allGrants.length == collection.models.length) {
-                    $allGrants.prop('disabled', false);
-                    $allGrants.prop('checked', true);
-                  }
-                } else if (grantee != 'PUBLIC') {
-                  $allGrants.prop('disabled', false);
-                }
-              }
-            }
-          }
-          this.model.trigger('change', this.model);
-
-          let anySelected = false,
-            msg = null;
-
-          collection.each(function(m) {
-            anySelected = anySelected || m.get('privilege');
-          });
-
-          if (anySelected) {
-            this.model.errorModel.unset('privileges');
-            if (this.model.errorModel.has('grantee')) {
-              msg = this.model.errorModel.get('grantee');
-            }
-          } else {
-            this.model.errorModel.set(
-              'privileges', gettext('At least one privilege should be selected.')
-            );
-            msg = gettext('At least one privilege should be selected.');
-          }
-          if (msg) {
-            this.model.collection.trigger(
-              'pgadmin-session:model:invalid', msg, this.model
-            );
-          } else {
-            this.model.collection.trigger(
-              'pgadmin-session:model:valid', this.model
-            );
-          }
-        }
-        this.delegateEvents();
-      },
-
-      lostFocus: function(ev) {
-        /*
-         * We lost the focus, it's time for us to exit the editor.
-         */
-        let self = this,
-          /*
-           * Function to determine whether one dom element is descendant of another
-           * dom element.
-           */
-          isDescendant = function (parent, child) {
-            let node = child.parentNode;
-            while (node != null) {
-              if (node == parent) {
-                return true;
-              }
-              node = node.parentNode;
-            }
-            return false;
-          },
-          model = this.model,
-          column = this.column,
-          command = new Backgrid.Command(ev),
-          coll = this.model.get(this.column.get('name'));
-
-        if (ev.key == 'Tab'){
-          commonUtils.handleKeyNavigation(event);
-        }
-
-        if (command.moveUp() || command.moveDown() || command.save() || command.cancel() ||
-          (command.moveLeft() && ev.target.name === 'privilege' && $(ev.target).attr('privilege') === 'ALL')) {
-          // undo
-          ev.stopPropagation();
-          model.trigger('backgrid:edited', model, column, command);
-          return;
-        } else if (command.moveRight()) {
-          // If we are at the last privilege then we should move to next cell
-          if (coll.last().get('privilege_type') === $(ev.target).attr('privilege')) {
-            if ((ev.target.name === 'privilege' && !ev.target.checked ) ||
-              $(ev.target).attr('name') === 'with_grant') {
-              ev.stopPropagation();
-              model.trigger('backgrid:edited', model, column, command);
-              return;
-            }
-          }
-        }
-
-        /*
-         * Between leaving the old element focus and entering the new element focus the
-         * active element is the document/body itself so add timeout to get the proper
-         * focused active element.
-         */
-        setTimeout(function() {
-          /*
-           * Do not close the control if user clicks outside dialog window,
-           * only close the row if user clicks on add button or on another row,
-           * if user clicks somewhere else then we will get tagName as 'BODY'
-           * or 'WINDOW'
-           */
-          let is_active_element = document.activeElement.tagName == 'DIV' ||
-            document.activeElement.tagName == 'BUTTON';
-
-          if (is_active_element && self.$el[0] != document.activeElement &&
-            !isDescendant(self.$el[0], document.activeElement)) {
-            let m = self.model;
-            m.trigger('backgrid:edited', m, self.column, new Backgrid.Command(ev));
-          }},10);
-      },
-    });
-
-  /*
-   * This will help us transform the privileges value in proper format to be
-   * displayed in the cell.
-   */
-  let PrivilegeCellFormatter = Backgrid.Extension.PrivilegeCellFormatter =
-    function () {/*This is intentional (SonarQube)*/};
-  _.extend(PrivilegeCellFormatter.prototype, {
-    notation: {
-      'CREATE' : 'C',
-      'TEMPORARY' : 'T',
-      'CONNECT' : 'c',
-      'INSERT' : 'a',
-      'SELECT' : 'r',
-      'UPDATE' : 'w',
-      'DELETE' : 'd',
-      'TRUNCATE' : 'D',
-      'REFERENCES' : 'x',
-      'TRIGGER' : 't',
-      'USAGE' : 'U',
-      'EXECUTE' : 'X',
-    },
-    /**
-     * Takes a raw value from a model and returns an optionally formatted
-     * string for display.
-     */
-    fromRaw: function (rawData) {
-      let res = '';
-
-      if (rawData instanceof Backbone.Collection) {
-        rawData.each(function(m) {
-          if (m.get('privilege')) {
-            res += m.get('privilege_type');
-            if (m.get('with_grant')) {
-              res += '*';
-            }
-          }
-        });
-      }
-      return res;
-    },
-  });
-
-  /*
-   *  PrivilegeCell for rendering and taking input for the privileges.
-   */
-  Backgrid.Extension.PrivilegeCell = Backgrid.Cell.extend({
-    className: 'edit-cell',
-    formatter: PrivilegeCellFormatter,
-    editor: PrivilegeCellEditor,
-
-    initialize: function () {
-      let self = this;
-      Backgrid.Cell.prototype.initialize.apply(this, arguments);
-
-      self.model.on('change:grantee', function() {
-        if (!self.$el.hasClass('editor')) {
-          /*
-           * Add time out before render; As we might want to wait till model
-           * is updated by PrivilegeRoleModel:granteeChanged.
-           */
-          setTimeout(function() {
-            self.render();
-          },10);
-        }
-      });
-    },
-
-    events: {
-      'click': 'enterEditMode',
-      'keydown': 'saveOrCancel',
-    },
-
-    saveOrCancel: function (e) {
-      let model = this.model;
-      let column = this.column;
-      let command = new Backgrid.Command(e);
-
-      if (command.moveUp() || command.moveDown() || command.moveLeft() || command.moveRight() ||
-        command.save()) {
-        e.preventDefault();
-        e.stopPropagation();
-        model.trigger('backgrid:edited', model, column, command);
-      }
-      // esc
-      else if (command.cancel()) {
-      // undo
-        e.stopPropagation();
-        model.trigger('backgrid:edited', model, column, command);
-      }
-    },
-  });
-
-  return PrivilegeRoleModel;
-
-});
diff --git a/web/pgadmin/browser/server_groups/servers/static/js/server.js b/web/pgadmin/browser/server_groups/servers/static/js/server.js
index c85f663a9..3b2370220 100644
--- a/web/pgadmin/browser/server_groups/servers/static/js/server.js
+++ b/web/pgadmin/browser/server_groups/servers/static/js/server.js
@@ -18,7 +18,6 @@ define('pgadmin.node.server', [
   'sources/pgadmin', 'pgadmin.browser',
   'pgadmin.user_management.current_user',
   'pgadmin.authenticate.kerberos',
-  'pgadmin.browser.server.privilege',
 ], function(
   gettext, url_for, $, pgAdmin, pgBrowser,
   current_user, Kerberos,
diff --git a/web/pgadmin/browser/server_groups/servers/static/js/variable.js b/web/pgadmin/browser/server_groups/servers/static/js/variable.js
deleted file mode 100644
index 30191e1db..000000000
--- a/web/pgadmin/browser/server_groups/servers/static/js/variable.js
+++ /dev/null
@@ -1,490 +0,0 @@
-/////////////////////////////////////////////////////////////
-//
-// pgAdmin 4 - PostgreSQL Tools
-//
-// Copyright (C) 2013 - 2022, The pgAdmin Development Team
-// This software is released under the PostgreSQL Licence
-//
-//////////////////////////////////////////////////////////////
-
-import _ from 'lodash';
-
-define([
-  'sources/gettext', 'jquery', 'backbone', 'backform', 'backgrid',
-  'pgadmin.browser.node', 'pgadmin.browser.node.ui',
-],
-function(gettext, $, Backbone, Backform, Backgrid, pgNode) {
-
-  /*
-     * cellFunction for variable control.
-     * This function returns cell class depending on vartype.
-     */
-  let cellFunction = function(model) {
-    let self = this,
-      name = model.get('name'),
-      availVariables = {};
-
-    self.collection.each(function(col) {
-      if (col.get('name') == 'name') {
-        availVariables = col.get('availVariables');
-      }
-    });
-
-    let variable = name ? availVariables[name]: undefined,
-      value = model.get('value');
-
-    switch(variable && variable.vartype) {
-    case 'bool':
-      /*
-           * bool cell and variable cannot be stateless (i.e undefined).
-           * It should be either true or false.
-           */
-
-      model.set('value', !!model.get('value'), {silent: true});
-
-      return Backgrid.Extension.SwitchCell;
-    case 'enum':
-      model.set({'value': value}, {silent:true});
-      var options = [],
-        enumVals = variable && variable.enumvals;
-
-      _.each(enumVals, function(enumVal) {
-        options.push([enumVal, enumVal]);
-      });
-
-      return Backgrid.Extension.Select2Cell.extend({optionValues: options});
-    case 'integer':
-      if (!_.isNaN(parseInt(value))) {
-        model.set({'value': parseInt(value)}, {silent:true});
-      } else {
-        model.set({'value': undefined}, {silent:true});
-      }
-      return Backgrid.IntegerCell;
-    case 'real':
-      if (!_.isNaN(parseFloat(value))) {
-        model.set({'value': parseFloat(value)}, {silent:true});
-      } else {
-        model.set({'value': undefined}, {silent:true});
-      }
-      return Backgrid.NumberCell.extend({decimals: 0});
-    case 'string':
-      return Backgrid.StringCell;
-    default:
-      model.set({'value': undefined}, {silent:true});
-      return Backgrid.Cell;
-    }
-  };
-
-  /*
-       * This row will define behaviour or value column cell depending upon
-       * variable name.
-       */
-  let VariableRow = Backgrid.Row.extend({
-    modelDuplicateClass: 'bg-model-duplicate',
-
-    initialize: function () {
-      Backgrid.Row.prototype.initialize.apply(this, arguments);
-      let self = this;
-      self.model.on('change:name', function() {
-        setTimeout(function() {
-          self.columns.each(function(col) {
-            if (col.get('name') == 'value') {
-              // Reset old value
-              self.model.set({'value': undefined}, {silent:true});
-              let idx = self.columns.indexOf(col),
-                cf = col.get('cellFunction'),
-                cell = new (cf.apply(col, [self.model]))({
-                  column: col,
-                  model: self.model,
-                }),
-                oldCell = self.cells[idx];
-              oldCell.remove();
-              self.cells[idx] = cell;
-              self.render();
-            }
-
-          });
-        }, 10);
-      });
-      self.listenTo(self.model, 'pgadmin-session:model:duplicate', self.modelDuplicate);
-      self.listenTo(self.model, 'pgadmin-session:model:unique', self.modelUnique);
-    },
-    modelDuplicate: function() {
-      $(this.el).removeClass('new');
-      $(this.el).addClass(this.modelDuplicateClass);
-    },
-    modelUnique: function() {
-      $(this.el).removeClass(this.modelDuplicateClass);
-    },
-
-  });
-  /**
-       *  VariableModel used to represent configuration parameters (variables tab)
-       *  for database objects.
-       **/
-  let VariableModel = pgNode.VariableModel = pgNode.Model.extend({
-    keys: ['name'],
-    defaults: {
-      name: undefined,
-      value: undefined,
-      role: null,
-      database: null,
-    },
-    schema: [
-      {
-        id: 'name', label: gettext('Name'), type:'text', cellHeaderClasses: 'width_percent_30',
-        editable: function(m) {
-          return (m instanceof Backbone.Collection) ? true : m.isNew();
-        },
-        cell: Backgrid.Extension.NodeAjaxOptionsCell.extend({
-          initialize: function() {
-            Backgrid.Extension.NodeAjaxOptionsCell.prototype.initialize.apply(this, arguments);
-
-            // Immediately process options as we need them before render.
-
-            let opVals = _.clone(this.optionValues ||
-                (_.isFunction(this.column.get('options')) ?
-                  (this.column.get('options'))(this) :
-                  this.column.get('options')));
-
-            this.column.set('options', opVals);
-          },
-        }),
-        url: 'vopts',
-        select2: { allowClear: false },
-        transform: function(vars, cell) {
-          let res = [],
-            availVariables = {};
-
-          _.each(vars, function(v) {
-            res.push({
-              'value': v.name,
-              'image': undefined,
-              'label': v.name,
-            });
-            availVariables[v.name] = v;
-          });
-
-          cell.column.set('availVariables', availVariables);
-          return res;
-        },
-      },
-      {
-        id: 'value', label: gettext('Value'), type: 'text', editable: true,
-        cellFunction: cellFunction, cellHeaderClasses: 'width_percent_40',
-      },
-      {id: 'database', label: gettext('Database'), type: 'text', editable: true,
-        node: 'database', cell: Backgrid.Extension.NodeListByNameCell,
-      },
-      {id: 'role', label: gettext('Role'), type: 'text', editable: true,
-        node: 'role', cell: Backgrid.Extension.NodeListByNameCell},
-    ],
-    toJSON: function() {
-      let d = Backbone.Model.prototype.toJSON.apply(this);
-
-      // Remove not defined values from model values.
-      // i.e.
-      // role, database
-      if (_.isUndefined(d.database) || _.isNull(d.database)) {
-        delete d.database;
-      }
-
-      if (_.isUndefined(d.role) || _.isNull(d.role)) {
-        delete d.role;
-      }
-
-      return d;
-    },
-    validate: function() {
-      let msg = null;
-      if (_.isUndefined(this.get('name')) ||
-          _.isNull(this.get('name')) ||
-            String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') {
-        msg = gettext('Please select a parameter name.');
-        this.errorModel.set('name', msg);
-      } else if (_.isUndefined(this.get('value')) ||
-              _.isNull(this.get('value')) ||
-                String(this.get('value')).replace(/^\s+|\s+$/g, '') == '') {
-        msg = gettext('Please enter a value for the parameter.');
-        this.errorModel.set('value', msg);
-        this.errorModel.unset('name');
-      } else {
-        this.errorModel.unset('name');
-        this.errorModel.unset('value');
-      }
-
-      return msg;
-    },
-  });
-
-  /**
-       * Variable Tab Control to set/update configuration values for database object.
-       *
-       **/
-  Backform.VariableCollectionControl =
-      Backform.UniqueColCollectionControl.extend({
-
-        hasDatabase: false,
-        hasRole: false,
-
-        initialize: function(opts) {
-          let self = this,
-            keys = ['name'];
-
-          /*
-             * Read from field schema whether user wants to use database and role
-             * fields in Variable control.
-             */
-          self.hasDatabase = opts.field.get('hasDatabase');
-          self.hasRole = opts.field.get('hasRole');
-
-          // Update unique coll field based on above flag status.
-          if (self.hasDatabase) {
-            keys.push('database');
-          } else if (self.hasRole) {
-            keys.push('role');
-          }
-          // Overriding the uniqueCol in the field
-          if (opts && opts.field) {
-            if (opts.field instanceof Backform.Field) {
-              opts.field.set({
-                model: pgNode.VariableModel.extend({keys:keys}),
-              },
-              {
-                silent: true,
-              });
-            } else {
-              opts.field.extend({
-                model: pgNode.VariableModel.extend({keys:keys}),
-              });
-            }
-          }
-
-          Backform.UniqueColCollectionControl.prototype.initialize.apply(
-            self, arguments
-          );
-
-          self.availVariables = {};
-
-          let gridCols = ['name', 'value'];
-
-          if (self.hasDatabase) {
-            gridCols.push('database');
-          }
-
-          if (self.hasRole) {
-            gridCols.push('role');
-          }
-
-          self.gridSchema = Backform.generateGridColumnsFromModel(
-            self.field.get('node_info'), VariableModel.extend({keys:keys}), 'edit', gridCols, self.field.get('schema_node')
-          );
-
-          // Make sure - we do have the data for variables
-          self.getVariables();
-        },
-        /*
-         * Get the variable data for this node.
-         */
-        getVariables: function() {
-          let self = this,
-            url = this.field.get('url'),
-            m = self.model;
-
-          if (!this.field.get('version_compatible'))
-            return;
-
-          if (url && !m.isNew()) {
-            let node = self.field.get('node'),
-              node_data = self.field.get('node_data'),
-              node_info = self.field.get('node_info'),
-              full_url = node.generate_url.apply(
-                node, [
-                  null, url, node_data, true, node_info,
-                ]),
-              data,
-              isTracking = self.collection.trackChanges;
-
-            if (isTracking) {
-              self.collection.stopSession();
-            }
-            m.trigger('pgadmin-view:fetching', m, self.field);
-
-            $.ajax({
-              async: false,
-              url: full_url,
-            })
-              .done(function (res) {
-                data = res.data;
-              })
-              .fail(function() {
-                m.trigger('pgadmin-view:fetch:error', m, self.field);
-              });
-            m.trigger('pgadmin-view:fetched', m, self.field);
-
-            if (data && _.isArray(data)) {
-              self.collection.reset(data, {silent: true});
-            }
-            /*
-               * Make sure - new data will be taken care by the session management
-               */
-            if (isTracking) {
-              self.collection.startNewSession();
-            }
-          }
-        },
-
-        showGridControl: function(data) {
-
-          let self = this,
-            titleTmpl = _.template([
-              '<div class=\'subnode-header\'>',
-              '<span class=\'control-label\'><%-label%></span>',
-              '<button class=\'btn btn-sm-sq btn-primary-icon add fa fa-plus\' title=\'' + gettext('Add new row') + '\' <%=canAdd ? \'\' : \'disabled="disabled"\'%>><span class="sr-only">' + gettext('Add new row') + '</span></button>',
-              '</div>'].join('\n')),
-            $gridBody =
-            $('<div class=\'pgadmin-control-group backgrid form-group col-12 object subnode\'></div>').append(
-              titleTmpl(data)
-            );
-
-          // Clean up existing grid if any (in case of re-render)
-          if (self.grid) {
-            self.grid.remove();
-          }
-
-          let gridSchema = _.clone(this.gridSchema);
-
-          _.each(gridSchema.columns, function(col) {
-            if (col.name == 'value') {
-              col.availVariables = self.availVariables;
-            }
-          });
-
-          // Insert Delete Cell into Grid
-          if (data.disabled && data.canDelete) {
-            gridSchema.columns.unshift({
-              name: 'pg-backform-delete width_percent_5', label: '',
-              cell: Backgrid.Extension.DeleteCell,
-              editable: false, cell_priority: -1,
-            });
-          }
-
-          // Change format of each of the data
-          // Because - data coming from the server is in string format
-          self.collection.each(function(model) {
-            let name = model.get('name'), val;
-
-            if (name in self.availVariables) {
-              switch(self.availVariables[name].vartype) {
-              case 'real':
-                val = parseFloat(model.get('value'));
-                model.set('value', (isNaN(val) ? undefined : val), {silent: true});
-
-                break;
-              case 'integer':
-                val = parseInt(model.get('value'));
-                model.set('value', (isNaN(val) ? undefined : val), {silent: true});
-
-                break;
-              default:
-                break;
-              }
-            }
-          });
-
-          // Initialize a new Grid instance
-          let grid = self.grid = new Backgrid.Grid({
-            columns: gridSchema.columns,
-            collection: self.collection,
-            row: VariableRow,
-            className: 'backgrid table presentation table-bordered table-noouter-border table-hover',
-          });
-          self.$grid = grid.render().$el;
-
-          $gridBody.append(self.$grid);
-
-          // Add button callback
-          if (!(data.disabled || !data.canAdd)) {
-            $gridBody.find('button.add').first().on('click',(e) => {
-              e.preventDefault();
-              let canAddRow = _.isFunction(data.canAddRow) ?
-                data.canAddRow.apply(self, [self.model]) : true;
-              if (canAddRow) {
-
-                let allowMultipleEmptyRows = !!self.field.get('allowMultipleEmptyRows');
-
-                // If allowMultipleEmptyRows is not set or is false then don't allow second new empty row.
-                // There should be only one empty row.
-                if (!allowMultipleEmptyRows && self.collection) {
-                  let isEmpty = false;
-                  self.collection.each(function(model) {
-                    let modelValues = [];
-                    _.each(model.attributes, function(val) {
-                      modelValues.push(val);
-                    });
-                    if(!_.some(modelValues, _.identity)) {
-                      isEmpty = true;
-                    }
-                  });
-                  if(isEmpty) {
-                    return false;
-                  }
-                }
-
-                $(grid.body.$el.find($('tr.new'))).removeClass('new');
-                let m = new (data.model) (null, {
-                  silent: true,
-                  handler: self.collection,
-                  top: self.model.top || self.model,
-                  collection: self.collection,
-                  node_info: self.model.node_info,
-                });
-                self.collection.add(m);
-
-                let idx = self.collection.indexOf(m),
-                  newRow = grid.body.rows[idx].$el;
-
-                newRow.addClass('new');
-                $(newRow).pgMakeVisible('backform-tab');
-
-                return false;
-              }
-            });
-          }
-
-          // Render node grid
-          return $gridBody;
-        },
-
-        addVariable: function(ev) {
-          ev.preventDefault();
-
-          let self = this,
-            m = new (self.field.get('model'))(
-              self.headerData.toJSON(), {
-                silent: true, top: self.collection.top,
-                handler: self.collection,
-              }),
-            coll = self.model.get(self.field.get('name'));
-
-          coll.add(m);
-
-          let idx = coll.indexOf(m);
-
-          // idx may not be always > -1 because our UniqueColCollection may
-          // remove 'm' if duplicate value found.
-          if (idx > -1) {
-            self.$grid.find('.new').removeClass('new');
-
-            let newRow = self.grid.body.rows[idx].$el;
-
-            newRow.addClass('new');
-            $(newRow).pgMakeVisible('backform-tab');
-          }
-
-          return false;
-        },
-      });
-
-  return VariableModel;
-});
diff --git a/web/pgadmin/browser/server_groups/servers/tablespaces/static/js/tablespace.js b/web/pgadmin/browser/server_groups/servers/tablespaces/static/js/tablespace.js
index 7a744ab46..2663c2812 100644
--- a/web/pgadmin/browser/server_groups/servers/tablespaces/static/js/tablespace.js
+++ b/web/pgadmin/browser/server_groups/servers/tablespaces/static/js/tablespace.js
@@ -15,8 +15,7 @@ import _ from 'lodash';
 
 define('pgadmin.node.tablespace', [
   'sources/gettext', 'sources/url_for',
-  'pgadmin.browser', 'pgadmin.browser.collection', 'pgadmin.browser.node.ui',
-  'pgadmin.browser.server.privilege',
+  'pgadmin.browser', 'pgadmin.browser.collection',
 ], function(
   gettext, url_for, pgBrowser
 ) {
diff --git a/web/pgadmin/browser/static/js/collection.js b/web/pgadmin/browser/static/js/collection.js
index 998260ee6..a66acb12e 100644
--- a/web/pgadmin/browser/static/js/collection.js
+++ b/web/pgadmin/browser/static/js/collection.js
@@ -12,8 +12,7 @@ import _ from 'lodash';
 define([
   'sources/gettext', 'sources/pgadmin',
   'sources/browser/generate_url',
-  'pgadmin.backform', 'pgadmin.backgrid',
-  'pgadmin.browser.node', 'backgrid.select.all',
+  'pgadmin.browser.node',
 ], function(gettext, pgAdmin, generateUrl) {
 
   let pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
diff --git a/web/pgadmin/browser/static/js/node.js b/web/pgadmin/browser/static/js/node.js
index 9b6635b92..1ae2218c1 100644
--- a/web/pgadmin/browser/static/js/node.js
+++ b/web/pgadmin/browser/static/js/node.js
@@ -10,17 +10,16 @@
 import {getNodeView, removeNodeView} from './node_view';
 import Notify from '../../../static/js/helpers/Notifier';
 import _ from 'lodash';
-import { pgHandleItemError } from '../../../static/js/utils';
 
 define('pgadmin.browser.node', [
   'sources/gettext', 'jquery', 'sources/pgadmin',
   'backbone', 'pgadmin.browser.datamodel',
-  'backform', 'sources/browser/generate_url', 'pgadmin.help', 'sources/utils',
-  'pgadmin.browser.utils', 'pgadmin.backform',
+  'sources/browser/generate_url', 'pgadmin.help', 'sources/utils',
+  'pgadmin.browser.utils',
 ], function(
   gettext, $, pgAdmin,
   Backbone, pgBrowser,
-  Backform, generateUrl, help,
+  generateUrl, help,
   commonUtils
 ) {
 
@@ -295,208 +294,10 @@ define('pgadmin.browser.node', [
       }
     },
     ///////
-    // Generate a Backform view using the node's model type
+    // Generate a view using the node's model type
     //
     // Used to generate view for the particular node properties, edit,
     // creation.
-    getView: function(item, type, el, node, formType, callback, ctx, cancelFunc) {
-      var that = this;
-
-      if (!this.type || this.type == '')
-        // We have no information, how to generate view for this type.
-        return null;
-
-      if (this.model) {
-        // This will be the URL, used for object manipulation.
-        // i.e. Create, Update in these cases
-        var urlBase = this.generate_url(item, type, node, false, null, that.url_jump_after_node);
-
-        if (!urlBase)
-          // Ashamed of myself, I don't know how to manipulate this
-          // node.
-          return null;
-
-        var attrs = {};
-
-        // In order to get the object data from the server, we must set
-        // object-id in the model (except in the create mode).
-        if (type !== 'create') {
-          attrs[this.model.idAttribute || this.model.prototype.idAttribute ||
-            'id'] = node._id;
-        }
-
-        // We know - which data model to be used for this object.
-        var info = pgBrowser.tree.getTreeNodeHierarchy(item),
-          newModel = new(this.model.extend({
-            urlRoot: urlBase,
-          }))(
-            attrs, {
-              node_info: info,
-            }
-          ),
-          fields = Backform.generateViewSchema(
-            info, newModel, type, this, node
-          );
-
-        if (type == 'create' || type == 'edit') {
-
-          if (callback && ctx) {
-            callback = callback.bind(ctx);
-          } else {
-            callback = function() {
-              console.warn(
-                'Broke something!!! Why we don\'t have the callback or the context???'
-              );
-            };
-          }
-
-          var onSessionInvalid = function(msg) {
-            var alertMessage = `
-            <div class="error-in-footer">
-              <div class="d-flex px-2 py-1">
-                <div class="pr-2">
-                  <i class="fa fa-exclamation-triangle text-danger" aria-hidden="true" role="img"></i>
-                </div>
-                <div role="alert" class="alert-text">${msg}</div>
-                <div class="ml-auto close-error-bar">
-                  <a class="close-error fa fa-times text-danger"></a>
-                </div>
-              </div>
-            </div>`;
-
-            if (!_.isUndefined(that.statusBar)) {
-              that.statusBar.html(alertMessage).css('visibility', 'visible');
-              that.statusBar.find('a.close-error').bind('click', function() {
-                this.empty().css('visibility', 'hidden');
-              }.bind(that.statusBar));
-            }
-
-            var sessHasChanged = false;
-            if(this.sessChanged && this.sessChanged()){
-              sessHasChanged = true;
-            }
-            callback(true, sessHasChanged);
-
-            return true;
-          };
-
-          var onSessionValidated = function(sessHasChanged) {
-
-            if (!_.isUndefined(that.statusBar)) {
-              that.statusBar.empty().css('visibility', 'hidden');
-            }
-
-            callback(false, sessHasChanged);
-          };
-
-          callback(false, false);
-
-          newModel.on('pgadmin-session:valid', onSessionValidated);
-          newModel.on('pgadmin-session:invalid', onSessionInvalid);
-        }
-        // 'schema' has the information about how to generate the form.
-        if (_.size(fields)) {
-          // This will contain the actual view
-          var view;
-
-          if (formType == 'fieldset') {
-            // It is used to show, edit, create the object in the
-            // properties tab.
-            view = new Backform.Accordian({
-              el: el,
-              model: newModel,
-              schema: fields,
-            });
-          } else {
-            // This generates a view to be used by the node dialog
-            // (for create/edit operation).
-            view = new Backform.Dialog({
-              el: el,
-              model: newModel,
-              schema: fields,
-            });
-          }
-
-          var setFocusOnEl = function() {
-            var container = $(el).find('.tab-content:first > .tab-pane.active:first');
-            commonUtils.findAndSetFocus(container);
-          };
-
-          if (!newModel.isNew()) {
-            // This is definetely not in create mode
-            var msgDiv = '<div role="status" class="pg-panel-message pg-panel-properties-message">' +
-              gettext('Retrieving data from the server...') + '</div>',
-              $msgDiv = $(msgDiv);
-            var timer = setTimeout(function(_ctx) {
-              // notify user if request is taking longer than 1 second
-
-              if (!_.isUndefined(_ctx)) {
-                $msgDiv.appendTo(_ctx);
-              }
-            }, 1000, ctx);
-
-
-            var fetchAjaxHook = function() {
-              newModel.fetch({
-                success: function() {
-                  // Clear timeout and remove message
-                  clearTimeout(timer);
-                  $msgDiv.addClass('d-none');
-
-                  // We got the latest attributes of the object. Render the view
-                  // now.
-                  view.render();
-                  setFocusOnEl();
-                  newModel.startNewSession();
-                },
-                error: function(model, xhr, options) {
-                  var _label = that && item ?
-                    pgBrowser.tree.getTreeNodeHierarchy(
-                      item
-                    )[that.type].label : '';
-                  pgBrowser.Events.trigger(
-                    'pgadmin:node:retrieval:error', 'properties',
-                    xhr, options.textStatus, options.errorThrown, item
-                  );
-                  if (!pgHandleItemError(xhr, {
-                    item: item,
-                    info: info,
-                  }
-                  )) {
-                    Notify.pgNotifier(
-                      options.textStatus, xhr,
-                      gettext('Error retrieving properties - %s', options.errorThrown || _label),
-                      function(msg) {
-                        if(msg === 'CRYPTKEY_SET') {
-                          fetchAjaxHook();
-                        } else {
-                          console.warn(arguments);
-                        }
-                      }
-                    );
-                  }
-                  // Close the panel (if could not fetch properties)
-                  if (cancelFunc) {
-                    cancelFunc();
-                  }
-                },
-              });
-            };
-
-            fetchAjaxHook();
-          } else {
-            // Yay - render the view now!
-            view.render();
-            setFocusOnEl();
-            newModel.startNewSession();
-          }
-        }
-
-        return view;
-      }
-
-      return null;
-    },
     addUtilityPanel: function(width, height, docker) {
       var body = window.document.body,
         el = document.createElement('div'),
@@ -1180,8 +981,6 @@ define('pgadmin.browser.node', [
         tree = pgAdmin.Browser.tree,
         j = panel.$container.find('.obj_properties').first(),
         view = j.data('obj-view'),
-        content = $('<div></div>')
-          .addClass('pg-prop-content col-12'),
         confirm_close = true;
 
       // Handle key press events for Cancel, save and help button
@@ -1218,70 +1017,11 @@ define('pgadmin.browser.node', [
         });
       }, 200); // wait for panel tab to render
 
-      // Template function to create the status bar
-      var createStatusBar = function(location) {
-          var statusBar = $('<div role="status"></div>').addClass(
-            'pg-prop-status-bar'
-          ).appendTo(j);
-          statusBar.css('visibility', 'hidden');
-          if (location == 'header') {
-            statusBar.appendTo(that.header);
-          } else {
-            statusBar.prependTo(that.footer);
-          }
-          that.statusBar = statusBar;
-          return statusBar;
-        }.bind(panel),
-        // Template function to create the button-group
-        createButtons = function(buttons, location, extraClasses) {
-          // Arguments must be non-zero length array of type
-          // object, which contains following attributes:
-          // label, type, extraClasses, register
-          if (buttons && _.isArray(buttons) && buttons.length > 0) {
-            // All buttons will be created within a single
-            // div area.
-            var btnGroup =
-              $('<div class="pg-prop-btn-group"></div>'),
-              // Template used for creating a button
-              tmpl = _.template([
-                '<button tabindex="0" type="<%= type %>" ',
-                'class="btn <%=extraClasses.join(\' \')%>"',
-                '<% if (disabled) { %> disabled="disabled"<% } %> title="<%-tooltip%>"',
-                '<% if (label != "") {} else { %> aria-label="<%-tooltip%>"<% } %> >',
-                '<span class="<%= icon %>"></span><% if (label != "") { %>&nbsp;<%-label%><% } %></button>',
-              ].join(' '));
-            if (location == 'header') {
-              btnGroup.appendTo(that.header);
-            } else {
-              btnGroup.appendTo(that.footer);
-            }
-            if (extraClasses) {
-              btnGroup.addClass(extraClasses);
-            }
-            _.each(buttons, 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),
-        // Callback to show object properties
-        properties = function() {
+      // Callback to show object properties
+      var properties = function() {
 
           // Avoid unnecessary reloads
           var i = tree.selected(),
-            d = i && tree.itemData(i),
             treeHierarchy = tree.getTreeNodeHierarchy(i);
 
           // Cache the current IDs for next time
@@ -1289,106 +1029,12 @@ define('pgadmin.browser.node', [
 
           /* Remove any dom rendered by getNodeView */
           removeNodeView(j[0]);
-          if(that.getSchema) {
-            let treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(item);
-            getNodeView(
-              that.type, treeNodeInfo, 'properties', data, 'tab', j[0], this, onEdit
-            );
-            return;
-          }
-
-          if (!content.hasClass('has-pg-prop-btn-group'))
-            content.addClass('has-pg-prop-btn-group');
-
-          // We need to release any existing view, before
-          // creating new view.
-          if (view) {
-            // Release the view
-            view.remove({
-              data: true,
-              internal: true,
-              silent: true,
-            });
-            // Deallocate the view
-            // delete view;
-            view = null;
-            // Reset the data object
-            j.data('obj-view', null);
-          }
-          // Make sure the HTML element is empty.
-          j.empty();
-          that.header = $('<div></div>').addClass(
-            'pg-prop-header'
-          ).appendTo(j);
-          that.footer = $('<div></div>').addClass(
-            'pg-prop-footer'
-          ).appendTo(j);
-
-          // Create a view to show the properties in fieldsets
-          view = that.getView(item, 'properties', content, data, 'fieldset', undefined, j);
-          if (view) {
-            // Save it for release it later
-            j.data('obj-view', view);
-
-            // Create proper buttons
-
-            var buttons = [];
-
-            buttons.push({
-              label: gettext('Edit'),
-              type: 'edit',
-              tooltip: gettext('Edit'),
-              extraClasses: ['btn', 'btn-primary', 'pull-right', 'm-1'],
-              icon: 'fa fa-sm fa-pencil-alt',
-              disabled: _.isFunction(that.canEdit) ? !that.canEdit.apply(that, [d, i]) : !that.canEdit,
-              register: function(btn) {
-                btn.on('click',() => {
-                  onEdit();
-                });
-              },
-            });
-
-            buttons.push({
-              label: '',
-              type: 'help',
-              tooltip: gettext('SQL help for this object type.'),
-              extraClasses: ['btn-primary-icon', 'btn-primary-icon', 'm-1'],
-              icon: 'fa fa-info',
-              disabled: (that.sqlAlterHelp == '' && that.sqlCreateHelp == '' && !that.epasHelp) ? true : false,
-              register: function(btn) {
-                btn.on('click',() => {
-                  onSqlHelp();
-                });
-              },
-            });
-            createButtons(buttons, 'header', 'pg-prop-btn-group-above');
-          }
-          j.append(content);
-        }.bind(panel),
-        onSqlHelp = function() {
-          // Construct the URL
-          var server = pgBrowser.tree.getTreeNodeHierarchy(item).server;
-
-          var url = pgBrowser.utils.pg_help_path;
-          var fullUrl = '';
-
-          if (server.server_type == 'ppas' && that.epasHelp) {
-            fullUrl = help.getEPASHelpUrl(server.version);
-          } else {
-            if (that.sqlCreateHelp == '' && that.sqlAlterHelp != '') {
-              fullUrl = help.getHelpUrl(url, that.sqlAlterHelp, server.version);
-            } else if (that.sqlCreateHelp != '' && that.sqlAlterHelp == '') {
-              fullUrl = help.getHelpUrl(url, that.sqlCreateHelp, server.version);
-            } else {
-              if (view.model.isNew()) {
-                fullUrl = help.getHelpUrl(url, that.sqlCreateHelp, server.version);
-              } else {
-                fullUrl = help.getHelpUrl(url, that.sqlAlterHelp, server.version);
-              }
-            }
-          }
+          let treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(item);
+          getNodeView(
+            that.type, treeNodeInfo, 'properties', data, 'tab', j[0], this, onEdit
+          );
+          return;
 
-          window.open(fullUrl, 'postgres_help');
         }.bind(panel),
 
         onDialogHelp = function() {
@@ -1425,52 +1071,6 @@ define('pgadmin.browser.node', [
           }
         }.bind(panel),
 
-        warnBeforeAttributeChange = function(yes_callback) {
-          var $props = this.$container.find('.obj_properties').first(),
-            objview = $props && $props.data('obj-view'),
-            self = this;
-
-          if (objview && objview.model && !_.isUndefined(objview.model.warn_text) && !_.isNull(objview.model.warn_text)) {
-            let warn_text;
-            warn_text = gettext(objview.model.warn_text);
-            if(objview.model.sessChanged()){
-              Notify.confirm(
-                gettext('Warning'),
-                warn_text,
-                function() {
-                  setTimeout(function(){
-                    yes_callback();
-                  }.bind(self), 50);
-                  return true;
-                },
-                function() {
-                  return true;
-                }
-              );
-            } else {
-              return true;
-            }
-          } else {
-            yes_callback();
-            return true;
-          }
-        }.bind(panel),
-
-        informBeforeAttributeChange = function(ok_callback) {
-          var $props = this.$container.find('.obj_properties').first(),
-            objview = $props && $props.data('obj-view');
-
-          if (objview && objview.model && !_.isUndefined(objview.model.inform_text) && !_.isNull(objview.model.inform_text)) {
-            Notify.alert(
-              gettext('Warning'),
-              gettext(objview.model.inform_text)
-            );
-
-          }
-          ok_callback();
-          return true;
-        }.bind(panel),
-
         onSave = function(_view, saveBtn) {
           var m = _view.model,
             d = m.toJSON(true),
@@ -1545,229 +1145,40 @@ define('pgadmin.browser.node', [
           /* Remove any dom rendered by getNodeView */
           removeNodeView(j[0]);
           /* getSchema is a schema for React. Get the react node view */
-          if(that.getSchema) {
-            let treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(item);
-            getNodeView(
-              that.type, treeNodeInfo, action, data, 'dialog', j[0], this, onEdit,
-              (nodeData)=>{
-                if(nodeData.node) {
-                  onSaveFunc(nodeData.node, treeNodeInfo);
-                  // Removing the node-prop property of panel
-                  // so that we show updated data on panel
-                  var pnlProperties = pgBrowser.docker.findPanels('properties')[0],
-                    pnlSql = pgBrowser.docker.findPanels('sql')[0],
-                    pnlStats = pgBrowser.docker.findPanels('statistics')[0],
-                    pnlDependencies = pgBrowser.docker.findPanels('dependencies')[0],
-                    pnlDependents = pgBrowser.docker.findPanels('dependents')[0];
-
-                  if (pnlProperties)
-                    $(pnlProperties).removeData('node-prop');
-                  if (pnlSql)
-                    $(pnlSql).removeData('node-prop');
-                  if (pnlStats)
-                    $(pnlStats).removeData('node-prop');
-                  if (pnlDependencies)
-                    $(pnlDependencies).removeData('node-prop');
-                  if (pnlDependents)
-                    $(pnlDependents).removeData('node-prop');
-
-                  if(nodeData.success === 0) {
-                    Notify.alert(gettext('Error'),
-                      gettext(nodeData.errormsg)
-                    );
-                  }
-                }
-              }
-            );
-            return;
-          }
-
-          // We need to release any existing view, before
-          // creating the new view.
-          if (view) {
-            // Release the view
-            view.remove({
-              data: true,
-              internal: true,
-              silent: true,
-            });
-            // Deallocate the view
-            view = null;
-            // Reset the data object
-            j.data('obj-view', null);
-          }
-          // Make sure the HTML element is empty.
-          j.empty();
-
-          that.header = $('<div></div>').addClass(
-            'pg-prop-header'
-          ).appendTo(j);
-          that.footer = $('<div></div>').addClass(
-            'pg-prop-footer'
-          ).appendTo(j);
-
-          var updateButtons = function(hasError, modified) {
-
-            var btnGroup = this.find('.pg-prop-btn-group'),
-              btnSave = btnGroup.find('button.btn-primary'),
-              btnReset = btnGroup.find('button.btn-secondary[type="reset"]');
-
-            if (hasError || !modified) {
-              btnSave.prop('disabled', true);
-              btnSave.attr('disabled', 'disabled');
-            } else {
-              btnSave.prop('disabled', false);
-              btnSave.removeAttr('disabled');
-            }
-
-            if (!modified) {
-              btnReset.prop('disabled', true);
-              btnReset.attr('disabled', 'disabled');
-            } else {
-              btnReset.prop('disabled', false);
-              btnReset.removeAttr('disabled');
-            }
-          };
-
-          // Create a view to edit/create the properties in fieldsets
-          view = that.getView(item, action, content, data, 'dialog', updateButtons, j, onCancelFunc);
-          if (view) {
-            // Save it to release it later
-            j.data('obj-view', view);
+          let treeNodeInfo = pgBrowser.tree.getTreeNodeHierarchy(item);
+          getNodeView(
+            that.type, treeNodeInfo, action, data, 'dialog', j[0], this, onEdit,
+            (nodeData)=>{
+              if(nodeData.node) {
+                onSaveFunc(nodeData.node, treeNodeInfo);
+                // Removing the node-prop property of panel
+                // so that we show updated data on panel
+                var pnlProperties = pgBrowser.docker.findPanels('properties')[0],
+                  pnlSql = pgBrowser.docker.findPanels('sql')[0],
+                  pnlStats = pgBrowser.docker.findPanels('statistics')[0],
+                  pnlDependencies = pgBrowser.docker.findPanels('dependencies')[0],
+                  pnlDependents = pgBrowser.docker.findPanels('dependents')[0];
 
-            self.icon(
-              _.isFunction(that['node_image']) ?
-                (that['node_image']).apply(that, [data, view.model]) :
-                (that['node_image'] || ('icon-' + that.type))
-            );
+                if (pnlProperties)
+                  $(pnlProperties).removeData('node-prop');
+                if (pnlSql)
+                  $(pnlSql).removeData('node-prop');
+                if (pnlStats)
+                  $(pnlStats).removeData('node-prop');
+                if (pnlDependencies)
+                  $(pnlDependencies).removeData('node-prop');
+                if (pnlDependents)
+                  $(pnlDependents).removeData('node-prop');
 
-            // Create proper buttons
-            let btn_grp = createButtons([{
-              label: '',
-              type: 'help',
-              tooltip: gettext('SQL help for this object type.'),
-              extraClasses: ['btn-primary-icon', 'pull-left', 'mx-1'],
-              icon: 'fa fa-info',
-              disabled: (that.sqlAlterHelp == '' && that.sqlCreateHelp == '' && !that.epasHelp) ? true : false,
-              register: function(btn) {
-                btn.on('click',() => {
-                  onSqlHelp();
-                });
-              },
-            }, {
-              label: '',
-              type: 'help',
-              tooltip: gettext('Help for this dialog.'),
-              extraClasses: ['btn-primary-icon', 'pull-left', 'mx-1'],
-              icon: 'fa fa-question',
-              disabled: (that.dialogHelp == '') ? true : false,
-              register: function(btn) {
-                btn.on('click',() => {
-                  onDialogHelp();
-                });
-              },
-            }, {
-              label: gettext('Cancel'),
-              type: 'cancel',
-              tooltip: gettext('Cancel changes to this object.'),
-              extraClasses: ['btn-secondary', 'mx-1'],
-              icon: 'fa fa-times',
-              disabled: false,
-              register: function(btn) {
-                btn.on('click',() => {
-                  // Removing the action-mode
-                  self.$container.removeAttr('action-mode');
-                  onCancelFunc.call(true);
-                });
-              },
-            }, {
-              label: gettext('Reset'),
-              type: 'reset',
-              tooltip: gettext('Reset the fields on this dialog.'),
-              extraClasses: ['btn-secondary', 'mx-1'],
-              icon: 'fa fa-recycle',
-              disabled: true,
-              register: function(btn) {
-                btn.on('click',() => {
-                  warnBeforeChangesLost.call(
-                    self,
-                    gettext('Changes will be lost. Are you sure you want to reset?'),
-                    function() {
-                      setTimeout(function() {
-                        editFunc.call();
-                      }, 0);
-                    }
-                  );
-                });
-              },
-            }, {
-              label: gettext('Save'),
-              type: 'save',
-              tooltip: gettext('Save this object.'),
-              extraClasses: ['btn-primary', 'mx-1'],
-              icon: 'fa fa-save',
-              disabled: true,
-              register: function(btn) {
-                // Save the changes
-                btn.on('click',() => {
-                  warnBeforeAttributeChange.call(
-                    self,
-                    function() {
-                      informBeforeAttributeChange.call(self, function(){
-                        setTimeout(function() {
-                          onSave.call(this, view, btn);
-                        }, 0);
-                      });
-                    }
+                if(nodeData.success === 0) {
+                  Notify.alert(gettext('Error'),
+                    gettext(nodeData.errormsg)
                   );
-                });
-              },
-            }], 'footer', 'pg-prop-btn-group-below');
-
-            btn_grp.on('keydown', 'button', function(event) {
-              if (!event.shiftKey && event.keyCode == 9 && $(this).nextAll('button:not([disabled])').length == 0) {
-                // set focus back to first focusable element on dialog
-                view.$el.closest('.wcFloating').find('[tabindex]:not([tabindex="-1"]').first().focus();
-                return false;
-              }
-              let btnGroup = $(self.$container.find('.pg-prop-btn-group'));
-              let el = $(btnGroup).find('button:first');
-              if (self.$container.find('.number-cell.editable:last').is(':visible')){
-                if (event.keyCode === 9 && event.shiftKey) {
-                  if ($(el).is($(event.target))){
-                    $(self.$container.find('td.editable:last').trigger('click'));
-                    event.preventDefault();
-                    event.stopPropagation();
-                  }
                 }
               }
-            });
-
-            setTimeout(function() {
-              pgBrowser.keyboardNavigation.getDialogTabNavigator(self.pgElContainer);
-            }, 200);
-          }
-
-          // Create status bar.
-          createStatusBar('footer');
-
-          // Add some space, so that - button group does not override the
-          // space
-          content.addClass('pg-prop-has-btn-group-below');
-
-          // Show contents before buttons
-          j.prepend(content);
-          // add required attributes to select2 input to resolve accessibility issue.
-          $('.select2-search__field').attr('aria-label', 'select2');
-          view.$el.closest('.wcFloating').find('.wcFrameButtonBar > .wcFrameButton[style!="display: none;"]').on('keydown', function(e) {
-
-            if(e.shiftKey && e.keyCode === 9) {
-              e.stopPropagation();
-              setTimeout(() => {
-                view.$el.closest('.wcFloating').find('[tabindex]:not([tabindex="-1"]):not([disabled])').last().focus();
-              }, 10);
             }
-          });
+          );
+          return;
         }.bind(panel),
         closePanel = function(confirm_close_flag) {
           if(!_.isUndefined(confirm_close_flag)) {
@@ -1830,7 +1241,6 @@ define('pgadmin.browser.node', [
             }]);
           }, 0);
         },
-        onCancelFunc = closePanel,
         onSaveFunc = updateTreeItem.bind(panel, that),
         onEdit = editFunc.bind(panel);
 
diff --git a/web/pgadmin/browser/static/js/node.ui.js b/web/pgadmin/browser/static/js/node.ui.js
deleted file mode 100644
index 48c56f0de..000000000
--- a/web/pgadmin/browser/static/js/node.ui.js
+++ /dev/null
@@ -1,564 +0,0 @@
-/////////////////////////////////////////////////////////////
-//
-// pgAdmin 4 - PostgreSQL Tools
-//
-// Copyright (C) 2013 - 2022, The pgAdmin Development Team
-// This software is released under the PostgreSQL Licence
-//
-//////////////////////////////////////////////////////////////
-import _ from 'lodash';
-
-define([
-  'sources/gettext', 'jquery', 'sources/pgadmin', 'backform',
-  'backgrid', 'select2', 'pgadmin.browser.node',
-], function(gettext, $, pgAdmin, Backform, Backgrid) {
-
-  /*
-   * Define the selectAll adapter for select2.
-   *
-   * Reference:
-   * https://github.com/select2/select2/issues/195#issuecomment-240130634
-   */
-  $.fn.select2.amd.define('select2/selectAllAdapter', [
-    'select2/utils',
-    'select2/dropdown',
-    'select2/dropdown/attachBody',
-  ], function(Utils, Dropdown, AttachBody) {
-
-    function SelectAll() {/*This is intentional (SonarQube)*/}
-    SelectAll.prototype.render = function(decorated) {
-      let self = this;
-      let $rendered = decorated.call(this);
-
-      let $selectAll = $([
-        '<button class="btn btn-secondary btn-sm" type="button"',
-        ' style="width: 49%;margin: 0 0.5%;">',
-        '<i class="fa fa-check-square" role="img"></i>',
-        '<span style="padding: 0px 5px;">',
-        gettext('Select All'),
-        '</span></button>',
-      ].join(''));
-
-      let $unselectAll = $([
-        '<button class="btn btn-secondary btn-sm" type="button"',
-        ' style="width: 49%;margin: 0 0.5%;">',
-        '<i class="fa fa-square"></i><span style="padding: 0px 5px;" role="img">',
-        gettext('Unselect All'),
-        '</span></button>',
-      ].join(''));
-
-      let $btnContainer = $(
-        '<div class="select2-select-all-adapter-container">'
-      ).append($selectAll).append($unselectAll);
-
-      if (!this.$element.prop('multiple')) {
-        // this isn't a multi-select -> don't add the buttons!
-        return $rendered;
-      }
-      $rendered.find('.select2-dropdown').prepend($btnContainer);
-      // Select All button click
-      $selectAll.on('click', function() {
-        $rendered.find('.select2-results__option[aria-selected=false]').each(
-          function() {
-            // Note: With latest version we do not get data in the data attribute of a element
-            // Hence as per new logic we will fetch the data from the cache created by Select2.
-            let data = Utils.GetData($(this)[0], 'data');
-            self.trigger('select', {
-              data: data,
-            });
-          }
-        );
-        self.trigger('close');
-      });
-      // Unselect All button click
-      $unselectAll.on('click', function() {
-        $rendered.find('.select2-results__option[aria-selected=true]').each(
-          function() {
-            let data = Utils.GetData($(this)[0], 'data');
-            self.trigger('unselect', {
-              data: data,
-            });
-          }
-        );
-        self.trigger('close');
-      });
-      return $rendered;
-    };
-
-    return Utils.Decorate(
-      Utils.Decorate(
-        Dropdown,
-        AttachBody
-      ),
-      SelectAll
-    );
-  });
-
-  /*
-   * NodeAjaxOptionsControl
-   *   This control will fetch the options required to render the select
-   *   control, 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.
-   */
-  let NodeAjaxOptionsControl = Backform.NodeAjaxOptionsControl =
-    Backform.Select2Control.extend({
-      defaults: _.extend(Backform.Select2Control.prototype.defaults, {
-        url: undefined,
-        transform: undefined,
-        url_with_id: false,
-        select2: {
-          allowClear: true,
-          placeholder: gettext('Select an item...'),
-          width: 'style',
-        },
-      }),
-      initialize: function() {
-        /*
-         * Initialization from the original control.
-         */
-        Backform.Select2Control.prototype.initialize.apply(this, arguments);
-
-        /*
-         * We're about to fetch the options required for this control.
-         */
-        let self = this,
-          url = self.field.get('url') || self.defaults.url,
-          m = self.model.top || self.model,
-          url_jump_after_node = self.field.get('url_jump_after_node') || null;
-
-        // Hmm - we found the url option.
-        // That means - we needs to fetch the options from that node.
-        if (url) {
-          let node = this.field.get('schema_node'),
-            node_info = this.field.get('node_info'),
-            with_id = this.field.get('url_with_id') || false,
-            full_url = node.generate_url.apply(
-              node, [
-                null, url, this.field.get('node_data'), with_id, node_info, url_jump_after_node,
-              ]),
-            cache_level,
-            cache_node = this.field.get('cache_node');
-
-          cache_node = (cache_node && pgAdmin.Browser.Nodes[cache_node]) || node;
-
-          if (this.field.has('cache_level')) {
-            cache_level = this.field.get('cache_level');
-          } else {
-            cache_level = cache_node.cache_level(node_info, with_id);
-          }
-
-          /*
-           * 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.
-           */
-          let data = cache_node.cache(node.type + '#' + url, node_info, cache_level);
-
-          if (this.field.get('version_compatible') &&
-            (_.isUndefined(data) || _.isNull(data))) {
-            m.trigger('pgadmin:view:fetching', m, self.field);
-            $.ajax({
-              async: false,
-              url: full_url,
-            })
-              .done(function(res) {
-              /*
-               * We will cache this data for short period of time for avoiding
-               * same calls.
-               */
-                data = cache_node.cache(node.type + '#' + 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) || [];
-
-          /*
-           * Transform the data
-           */
-          let transform = this.field.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.field.set('options', transform.bind(self, data));
-          } else {
-            self.field.set('options', data);
-          }
-        }
-      },
-    });
-
-  let formatNode = function(opt) {
-    if (!opt.id) {
-      return opt.text;
-    }
-
-    let optimage = $(opt.element).data('image');
-
-    if (!optimage) {
-      return opt.text;
-    } else {
-      return $('<span></span>').append(
-        $('<span></span>', {
-          class: 'wcTabIcon ' + optimage,
-        })
-      ).append($('<span></span>').text(opt.text));
-    }
-  };
-
-  let filterRows = function(self, filter, rows, node) {
-    let res = [];
-    _.each(rows, function(r) {
-      if (filter(r)) {
-        let 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;
-  };
-
-  let NodeListByIdControl = Backform.NodeListByIdControl = NodeAjaxOptionsControl.extend({
-    controlClassName: 'pgadmin-node-select form-control',
-    defaults: _.extend({}, NodeAjaxOptionsControl.prototype.defaults, {
-      url: 'nodes',
-      filter: undefined,
-      transform: function(rows) {
-        let self = this,
-          node = self.field.get('schema_node'),
-          filter = self.field.get('filter') || function() {
-            return true;
-          };
-
-        filter = filter.bind(self);
-        return filterRows(self, filter, rows, node);
-      },
-      select2: {
-        allowClear: true,
-        placeholder: gettext('Select an item...'),
-        width: 'style',
-        templateResult: formatNode,
-        templateSelection: formatNode,
-      },
-    }),
-  });
-
-  Backform.NodeListByNameControl = NodeListByIdControl.extend({
-    defaults: _.extend({}, NodeListByIdControl.prototype.defaults, {
-      transform: function(rows) {
-        let self = this,
-          node = self.field.get('schema_node'),
-          res = [],
-          filter = self.field.get('filter') || function() {
-            return true;
-          };
-
-        filter = filter.bind(self);
-
-        _.each(rows, function(r) {
-          if (filter(r)) {
-            let 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;
-      },
-    }),
-  });
-
-  /*
-   * Global function to make visible  particular dom element in it's parent
-   * with given class.
-   */
-  $.fn.pgMakeVisible = function(cls) {
-    return this.each(function() {
-      if (!this || !$(this.length))
-        return;
-      let top, p = $(this),
-        hasScrollbar = function(j) {
-          if (j && j.length > 0) {
-            return j.get(0).scrollHeight > j.height();
-          }
-          return false;
-        };
-
-      // check if p is not empty
-      while (p && p.length > 0) {
-        top = p.get(0).offsetTop + p.height();
-        p = p.parent();
-        if (hasScrollbar(p)) {
-          p.scrollTop(top);
-        }
-        if (p.hasClass(cls)) //'backform-tab'
-          return;
-      }
-    });
-  };
-
-  /*
-  * Global function to make visible backgrid new row
-  */
-  $.fn.pgMakeBackgridVisible = function(cls) {
-    return this.each(function() {
-      if (!this || !$(this.length))
-        return;
-
-      let elem = $(this),
-        backgridDiv = $(this).offsetParent().parent(), // Backgrid div.subnode
-        backgridDivTop = backgridDiv.offset().top,
-        backgridDivHeight = backgridDiv.height(),
-        backformTab = $(this).closest(cls), // Backform-tab
-        gridScroll = null;
-
-      if(backformTab.length == 0) {
-        return false;
-      }
-      gridScroll = backformTab[0].offsetHeight - backgridDivTop;
-
-      if (backgridDivHeight > gridScroll) {
-        let top = elem.get(0).offsetTop + elem.height();
-        backformTab.find('.tab-content').scrollTop(top);
-      }
-      return true;
-    });
-  };
-
-  /*
-   * 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.
-   */
-  let 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: gettext('Select an item...'),
-        width: 'style',
-      },
-      opt: {
-        label: null,
-        value: null,
-        image: null,
-        selected: false,
-      },
-    }),
-    template: _.template(
-      '<option <% if (image) { %> data-image=<%= image %> <% } %> value="<%- value %>" <%= selected ? \'selected="selected"\' : "" %>><%- label %></option>'
-    ),
-    initialize: function() {
-      Backgrid.Extension.Select2Cell.prototype.initialize.apply(this, arguments);
-
-      let url = this.column.get('url') || this.defaults.url,
-        is_options_cached = _.has(this.column.attributes, 'options_cached'),
-        options_cached = is_options_cached && this.column.get('options_cached');
-      // Hmm - we found the url option.
-      // That means - we needs to fetch the options from that node.
-      if (url && !options_cached) {
-
-        let self = this,
-          m = this.model,
-          column = this.column,
-          eventHandler = m.top || m,
-          node = column.get('schema_node'),
-          node_info = column.get('node_info'),
-          with_id = column.get('url_with_id') || false,
-          url_jump_after_node = this.column.get('url_jump_after_node') || null,
-          full_url = node.generate_url.apply(
-            node, [
-              null, url, column.get('node_data'), with_id, node_info, url_jump_after_node,
-            ]),
-          cache_level,
-          cache_node = column.get('cache_node');
-
-        cache_node = (cache_node && pgAdmin.Browser.Nodes[cache_node]) || node;
-
-        if (column.has('cache_level')) {
-          cache_level = column.get('cache_level');
-        } else {
-          cache_level = cache_node.cache_level(node_info, with_id);
-        }
-
-        /*
-         * 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.
-         */
-        let data = cache_node.cache(node.type + '#' + url, node_info, cache_level);
-
-        if (column.get('version_compatible') &&
-          (_.isUndefined(data) || _.isNull(data))) {
-          eventHandler.trigger('pgadmin:view:fetching', m, column);
-          $.ajax({
-            async: false,
-            url: full_url,
-          })
-            .done(function(res) {
-            /*
-             * We will cache this data for short period of time for avoiding
-             * same calls.
-             */
-              data = cache_node.cache(node.type + '#' + url, node_info, cache_level, res.data);
-            })
-            .fail(function() {
-              eventHandler.trigger('pgadmin:view:fetch:error', m, column);
-            });
-          eventHandler.trigger('pgadmin:view:fetched', m, 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
-         */
-        let transform = 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.
-          column.set('options', transform.bind(column, data));
-        } else {
-          column.set('options', data);
-        }
-
-        if (is_options_cached) {
-          column.set('options_cached', true);
-        }
-      }
-    },
-  });
-
-  let transformFunc = function(rows, control) {
-    let self = control || this,
-      node = self.column.get('schema_node'),
-      filter = self.column.get('filter') || function() {
-        return true;
-      };
-
-    filter = filter.bind(self);
-    return filterRows(self, filter, rows, node);
-  };
-
-  Backgrid.Extension.NodeListByIdCell = NodeAjaxOptionsCell.extend({
-    controlClassName: 'pgadmin-node-select backgrid-cell',
-    defaults: _.extend({}, NodeAjaxOptionsCell.prototype.defaults, {
-      url: 'nodes',
-      filter: undefined,
-      transform: transformFunc,
-      select2: {
-        placeholder: gettext('Select an item...'),
-        width: 'style',
-        templateResult: formatNode,
-        templateSelection: formatNode,
-      },
-    }),
-  });
-
-  Backgrid.Extension.NodeListByNameCell = NodeAjaxOptionsCell.extend({
-    controlClassName: 'pgadmin-node-select backgrid-cell',
-    defaults: _.extend({}, NodeAjaxOptionsCell.prototype.defaults, {
-      url: 'nodes',
-      filter: undefined,
-      transform: transformFunc,
-      select2: {
-        placeholder: gettext('Select an item...'),
-        width: 'style',
-        templateResult: formatNode,
-        templateSelection: formatNode,
-      },
-    }),
-  });
-
-  // Extend the browser's node model class to create a option/value pair
-  Backgrid.Extension.MultiSelectAjaxCell = Backgrid.Extension.NodeAjaxOptionsCell.extend({
-    defaults: _.extend({}, NodeAjaxOptionsCell.prototype.defaults, {
-      transform: undefined,
-      url_with_id: false,
-      select2: {
-        allowClear: true,
-        placeholder: gettext('Select an item...'),
-        width: 'style',
-        multiple: true,
-      },
-      opt: {
-        label: null,
-        value: null,
-        image: null,
-        selected: false,
-      },
-    }),
-    getValueFromDOM: function() {
-      let res = [];
-
-      this.$el.find('select').find(':selected').each(function() {
-        res.push($(this).attr('value'));
-      });
-
-      return res;
-    },
-  });
-
-  /*
-   * Control to select multiple columns.
-   */
-  Backform.MultiSelectAjaxControl = NodeAjaxOptionsControl.extend({
-    defaults: _.extend({}, NodeAjaxOptionsControl.prototype.defaults, {
-      select2: {
-        multiple: true,
-        allowClear: true,
-        width: 'style',
-      },
-    }),
-  });
-
-  return Backform;
-});
diff --git a/web/pgadmin/settings/static/js/settings.js b/web/pgadmin/settings/static/js/settings.js
index 6bfbc12d6..6beff2b9b 100644
--- a/web/pgadmin/settings/static/js/settings.js
+++ b/web/pgadmin/settings/static/js/settings.js
@@ -11,7 +11,7 @@ import Notify from '../../../static/js/helpers/Notifier';
 
 define('pgadmin.settings', [
   'jquery', 'sources/pgadmin',
-  'sources/gettext', 'sources/url_for', 'pgadmin.backform',
+  'sources/gettext', 'sources/url_for',
 ], function($, pgAdmin, gettext, url_for) {
 
   // This defines the Preference/Options Dialog for pgAdmin IV.
diff --git a/web/pgadmin/static/css/style.css b/web/pgadmin/static/css/style.css
index 62c52adac..983587c81 100644
--- a/web/pgadmin/static/css/style.css
+++ b/web/pgadmin/static/css/style.css
@@ -12,9 +12,6 @@
 @import 'node_modules/codemirror/addon/dialog/dialog.css';
 @import 'node_modules/codemirror/addon/scroll/simplescrollbars.css';
 
-@import '../vendor/backgrid/backgrid.css';
-@import '../vendor/backgrid/backgrid-select-all.css';
-
 @import 'node_modules/xterm/css/xterm.css';
 
 @import 'node_modules/jsoneditor/dist/jsoneditor.min.css';
diff --git a/web/pgadmin/static/js/backform.pgadmin.js b/web/pgadmin/static/js/backform.pgadmin.js
deleted file mode 100644
index df5019218..000000000
--- a/web/pgadmin/static/js/backform.pgadmin.js
+++ /dev/null
@@ -1,3558 +0,0 @@
-/////////////////////////////////////////////////////////////
-//
-// pgAdmin 4 - PostgreSQL Tools
-//
-// Copyright (C) 2013 - 2022, The pgAdmin Development Team
-// This software is released under the PostgreSQL Licence
-//
-//////////////////////////////////////////////////////////////
-
-import { calcFontSize } from './utils';
-
-define([
-  'sources/gettext', 'underscore', 'jquery',
-  'backbone', 'backform', 'backgrid', 'codemirror',
-  'sources/keyboard_shortcuts', 'sources/window', 'sources/select2/configure_show_on_scroll',
-  'color-picker', 'pgadmin.backgrid', 'select2', 'bootstrap.toggle',
-], function(gettext, _, $, Backbone, Backform, Backgrid, CodeMirror,
-  keyboardShortcuts, pgWindow, configure_show_on_scroll,
-  Pickr) {
-
-  let pgAdmin = (window.pgAdmin = window.pgAdmin || {}),
-    pgBrowser = pgAdmin.Browser;
-
-  pgAdmin.editableCell = function() {
-    if (this.attributes && !_.isUndefined(this.attributes.disabled) &&
-      !_.isNull(this.attributes.disabled)) {
-      if (_.isFunction(this.attributes.disabled)) {
-        return !(this.attributes.disabled.apply(this, arguments));
-      }
-      if (_.isBoolean(this.attributes.disabled)) {
-        return !this.attributes.disabled;
-      }
-    }
-  };
-
-  // HTML markup global class names. More can be added by individual controls
-  // using _.extend. Look at RadioControl as an example.
-  _.extend(Backform, {
-    controlLabelClassName: 'control-label pg-el-sm-3 pg-el-12',
-    controlsClassName: 'pgadmin-controls pg-el-sm-9 pg-el-12',
-    controlContainerClassName: 'pgadmin-controls pg-el-sm-9 pg-el-12',
-    groupClassName: 'pgadmin-control-group form-group row pg-el-12',
-    setGroupClassName: 'set-group pg-el-12',
-    tabClassName: 'backform-tab pg-el-12',
-    setGroupContentClassName: 'fieldset-content pg-el-12',
-    accordianGroupClassName: 'accordian-group pg-el-12',
-    accordianContentClassName: 'accordian-content pg-el-12',
-    hiddenClassName: 'd-none',
-    helpMessageClassName: 'form-text text-muted help-block',
-    helpBlockControlClass: 'pgadmin-controls offset-sm-3 pg-el-sm-9 pg-el-12',
-  });
-
-  Backform.controlMapper = {
-    'int': ['uneditable-input', 'numeric', 'integer'],
-    'text': ['uneditable-input', 'input', 'string'],
-    'numeric': ['uneditable-input', 'numeric', 'numeric'],
-    'date': 'datepicker',
-    'datetime': 'datetimepicker',
-    'boolean': 'boolean',
-    'options': ['readonly-option', 'select', Backgrid.Extension.PGSelectCell],
-    'multiline': ['textarea', 'textarea', 'string'],
-    'collection': ['sub-node-collection', 'sub-node-collection', 'string'],
-    'uniqueColCollection': ['unique-col-collection', 'unique-col-collection', 'string'],
-    'switch': 'switch',
-    'select2': 'select2',
-    'note': 'note',
-    'color': 'color',
-    'radioModern': 'radioModern',
-  };
-
-  Backform.getMappedControl = function(type, mode) {
-    if (type in Backform.controlMapper) {
-      let m = Backform.controlMapper[type];
-
-      if (!_.isArray(m)) {
-        return m;
-      }
-
-      let idx, len = _.size(m);
-
-      switch (mode) {
-      case 'properties':
-        idx = 0;
-        break;
-      case 'edit':
-      case 'create':
-      case 'control':
-        idx = 1;
-        break;
-      case 'cell':
-        idx = 2;
-        break;
-      default:
-        idx = 0;
-        break;
-      }
-
-      return m[idx > len ? 0 : idx];
-    }
-    return type;
-  };
-
-  /* Returns raw data as it is */
-  let RawFormatter = Backform.RawFormatter = function() {/*This is intentional (SonarQube)*/};
-  _.extend(RawFormatter.prototype, {
-    fromRaw: function(rawData) {
-      return rawData;
-    },
-    toRaw: function(formattedData) {
-      return formattedData;
-    },
-  });
-
-
-  let BackformControlInit = Backform.Control.prototype.initialize,
-    BackformControlRemove = Backform.Control.prototype.remove;
-
-  // Override the Backform.Control to allow to track changes in dependencies,
-  // and rerender the View element
-  _.extend(Backform.Control.prototype, {
-
-    defaults: _.extend(Backform.Control.prototype.defaults, {
-      helpMessage: null,
-    }),
-
-    initialize: function() {
-      BackformControlInit.apply(this, arguments);
-
-      // Listen to the dependent fields in the model for any change
-      let deps = this.field.get('deps');
-      let self = this;
-
-      if (deps && _.isArray(deps)) {
-        _.each(deps, function(d) {
-          let attrArr = d.split('.');
-          let name = attrArr.shift();
-          self.listenTo(self.model, 'change:' + name, self.render);
-        });
-      }
-    },
-
-    remove: function() {
-      // Remove the events for the dependent fields in the model
-      let self = this,
-        deps = self.field.get('deps');
-      let attrArr = this.field.get('name').split('.');
-      let name = attrArr.shift();
-
-      self.stopListening(self.model, 'change:' + name, self.render);
-      if (self.model.errorModel instanceof Backbone.Model) {
-        self.stopListening(
-          self.model.errorModel, 'change:' + name, self.updateInvalid
-        );
-      }
-
-      if (deps && _.isArray(deps)) {
-        _.each(deps, function(d) {
-
-          let attrArray = d.split('.');
-          let depname = attrArray.shift();
-
-          self.stopListening(self.model, 'change:' + depname, self.render);
-        });
-      }
-
-      if (this.cleanup) {
-        this.cleanup.apply(this);
-      }
-
-      if (BackformControlRemove) {
-        BackformControlRemove.apply(self, arguments);
-      } else {
-        Backbone.View.prototype.remove.apply(self, arguments);
-      }
-    },
-
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>" for="<%=cId%>"><%=label%></label>',
-      '<div class="<%=Backform.controlsClassName%>">',
-      '  <input id="<%=cId%>" class="<%=Backform.controlClassName%> uneditable-input" <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly aria-readonly=true" : ""%> id="<%=cId%>" value="<%-value%>" />',
-      '  <% if (helpMessage && helpMessage.length) { %>',
-      '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '  <% } %>',
-      '</div>',
-    ].join('\n')),
-
-    clearInvalid: function() {
-      this.$el.removeClass(Backform.errorClassName);
-      this.$el.find('.pgadmin-control-error-message').remove();
-      return this;
-    },
-
-    updateInvalid: function() {
-      let self = this,
-        errorModel = this.model.errorModel;
-
-      if (!(errorModel instanceof Backbone.Model)) return this;
-
-      this.clearInvalid();
-
-      /*
-       * Find input which have name attribute.
-       */
-      this.$el.find(':input[name]').not('button').each(function(ix, el) {
-        let error = self.keyPathAccessor(
-          errorModel.toJSON(), $(el).attr('name')
-        );
-
-        if (_.isEmpty(error)) return;
-        self.$el.addClass(Backform.errorClassName);
-      });
-    },
-
-    /*
-     * Overriding the render function of the control to allow us to eval the
-     * values properly.
-     */
-    render: function() {
-      let field = _.defaults(this.field.toJSON(), this.defaults),
-        attributes = this.model.toJSON(),
-        attrArr = field.name.split('.'),
-        name = attrArr.shift(),
-        path = attrArr.join('.'),
-        rawValue = this.keyPathAccessor(attributes[name], path),
-        data = _.extend(field, {
-          rawValue: rawValue,
-          value: this.formatter.fromRaw(rawValue, this.model),
-          attributes: attributes,
-          formatter: this.formatter,
-        }),
-        evalF = function(f, d, m) {
-          return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f);
-        };
-
-      // Evaluate the disabled, visible, and required option
-      _.extend(data, {
-        disabled: evalF(data.disabled, data, this.model),
-        readonly: evalF(data.readonly, data, this.model),
-        visible: evalF(data.visible, data, this.model),
-        required: evalF(data.required, data, this.model),
-      });
-
-      data.cId = data.cId || _.uniqueId('pgC_');
-      // Clean up first
-      this.$el.removeClass(Backform.hiddenClassName);
-
-      if (!data.visible)
-        this.$el.addClass(Backform.hiddenClassName);
-
-      this.$el.html(this.template(data)).addClass(field.name);
-      this.updateInvalid();
-
-      return this;
-    },
-  });
-
-  /*
-   * Override the input control events in order to reslove the issue related to
-   * not updating the value sometimes in the input control.
-   */
-  _.extend(
-    Backform.InputControl.prototype, {
-      defaults: _.extend(Backform.InputControl.prototype.defaults, {
-        controlLabelClassName: Backform.controlLabelClassName,
-        controlsClassName: Backform.controlsClassName,
-      }),
-      template: _.template([
-        '<label class="<%=controlLabelClassName%>" for="<%=cId%>"><%=label%></label>',
-        '<div class="<%=controlsClassName%>">',
-        '  <input type="<%=type%>" id="<%=cId%>" class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>" name="<%=name%>" maxlength="<%=maxlength%>" value="<%-value%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly aria-readonly=true" : ""%> <%=required ? "required" : ""%> />',
-        '  <% if (helpMessage && helpMessage.length) { %>',
-        '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-        '  <% } %>',
-        '</div>',
-      ].join('\n')),
-      events: {
-        'change input': 'onChange',
-        'blur input': 'onChange',
-        'keyup input': 'onKeyUp',
-        'focus input': 'clearInvalid',
-      },
-      onKeyUp: function(ev) {
-        if (this.key_timeout) {
-          clearTimeout(this.key_timeout);
-        }
-
-        this.keyup_timeout = setTimeout(function() {
-          this.onChange(ev);
-        }.bind(this), 400);
-      },
-    });
-
-  /*
-   * Override the textarea control events in order to resolve the issue related
-   * to not updating the value in model on certain browsers in few situations
-   * like copy/paste, deletion using backspace.
-   *
-   * Reference:
-   * http://stackoverflow.com/questions/11338592/how-can-i-bind-to-the-change-event-of-a-textarea-in-jquery
-   */
-  _.extend(
-    Backform.TextareaControl.prototype, {
-      defaults: _.extend(
-        Backform.TextareaControl.prototype.defaults, {
-          rows: 5,
-          helpMessage: null,
-          maxlength: null,
-        }
-      ),
-      events: {
-        'change textarea': 'onChange',
-        'keyup textarea': 'onKeyUp',
-        'paste textarea': 'onChange',
-        'selectionchange textarea': 'onChange',
-        'focus textarea': 'clearInvalid',
-      },
-      template: _.template([
-        '<label class="<%=Backform.controlLabelClassName%>" for="<%=cId%>"><%=label%></label>',
-        '<div class="<%=Backform.controlsClassName%>">',
-        '  <textarea id="<%=cId%>"',
-        '    class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>" name="<%=name%>" aria-label="<%=name%>"',
-        '  <% if (maxlength) { %>',
-        '    maxlength="<%=maxlength%>"',
-        '  <% } %>',
-        '    placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly aria-readonly=true" : ""%>',
-        '    rows=<%=rows ? rows : ""%>',
-        '    <%=required ? "required" : ""%>><%-value%></textarea>',
-        '  <% if (helpMessage && helpMessage.length) { %>',
-        '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-        '  <% } %>',
-        '</div>',
-      ].join('\n')),
-      onKeyUp: function(ev) {
-        if (this.key_timeout) {
-          clearTimeout(this.key_timeout);
-        }
-
-        this.keyup_timeout = setTimeout(function() {
-          this.onChange(ev);
-        }.bind(this), 400);
-      },
-    });
-
-  /*
-   * Overriding the render function of the select control to allow us to use
-   * options as function, which should return array in the format of
-   * (label, value) pair.
-   */
-  Backform.SelectControl.prototype.render = function() {
-    let field = _.defaults(this.field.toJSON(), this.defaults),
-      attributes = this.model.toJSON(),
-      attrArr = field.name.split('.'),
-      name = attrArr.shift(),
-      path = attrArr.join('.'),
-      rawValue = this.keyPathAccessor(attributes[name], path),
-      data = _.extend(field, {
-        rawValue: rawValue,
-        value: this.formatter.fromRaw(rawValue, this.model),
-        attributes: attributes,
-        formatter: this.formatter,
-      }),
-      evalF = function(f, d, m) {
-        return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f);
-      };
-
-    // Evaluate the disabled, visible, and required option
-    _.extend(data, {
-      disabled: evalF(data.disabled, data, this.model),
-      visible: evalF(data.visible, data, this.model),
-      required: evalF(data.required, data, this.model),
-    });
-    // Evaluation the options
-    if (_.isFunction(data.options)) {
-      try {
-        data.options = data.options(this);
-      } catch (e) {
-        // Do nothing
-        data.options = [];
-        this.model.trigger('pgadmin-view:transform:error', this.model, this.field, e);
-      }
-    }
-
-    data.cId = data.cId || _.uniqueId('pgC_');
-    // Clean up first
-    this.$el.removeClass(Backform.hiddenClassName);
-
-    if (!data.visible)
-      this.$el.addClass(Backform.hiddenClassName);
-
-    this.$el.html(this.template(data)).addClass(field.name);
-    this.updateInvalid();
-
-    return this;
-  };
-
-  Backform.SelectControl.prototype.template = _.template([
-    '<label class="<%=Backform.controlLabelClassName%>" for="<%=cId%>"><%=label%></label>',
-    '<div class="<%=Backform.controlContainerClassName%>">',
-    '  <select id="<%=cId%>" class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>" name="<%=name%>" value="<%-value%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "disabled" : ""%> <%=required ? "required" : ""%> >',
-    '    <% for (let i=0; i < options.length; i++) { %>',
-    '      <% let option = options[i]; %>',
-    '      <option value="<%-formatter.fromRaw(option.value)%>" <%=option.value === rawValue ? "selected=\'selected\'" : ""%> <%=option.disabled ? "disabled=\'disabled\'" : ""%>><%-option.label%></option>',
-    '    <% } %>',
-    '  </select>',
-    '</div>',
-  ].join('\n'));
-
-  _.extend(Backform.SelectControl.prototype.defaults, {
-    helpMessage: null,
-  });
-
-  Backform.ReadonlyOptionControl = Backform.SelectControl.extend({
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>" for="<%=cId%>"><%=label%></label>',
-      '<div class="<%=Backform.controlsClassName%>">',
-      '<% for (let i=0; i < options.length; i++) { %>',
-      ' <% let option = options[i]; %>',
-      ' <% if (option.value === rawValue) { %>',
-      ' <input id="<%=cId%>" class="<%=Backform.controlClassName%> uneditable-input" readonly value="<%-option.label%>"></span>',
-      ' <% } %>',
-      '<% } %>',
-      '<% if (helpMessage && helpMessage.length) { %>',
-      '  <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '<% } %>',
-      '</div>',
-    ].join('\n')),
-    events: {},
-    getValueFromDOM: function() {
-      return this.formatter.toRaw(this.$el.find('span').text(), this.model);
-    },
-  });
-
-  /*
-   * Override the function 'updateInvalid' of the radio control to resolve an
-   * issue, which will not render the error block multiple times for each
-   * options.
-   */
-  _.extend(
-    Backform.RadioControl.prototype, {
-      updateInvalid: function() {
-        let self = this,
-          errorModel = this.model.errorModel;
-
-        if (!(errorModel instanceof Backbone.Model)) return this;
-
-        this.clearInvalid();
-
-        /*
-         * Find input which have name attribute.
-         */
-        this.$el.find(':input[name]').not('button').each(function(ix, el) {
-          let error = self.keyPathAccessor(
-            errorModel.toJSON(), $(el).attr('name')
-          );
-
-          if (_.isEmpty(error)) return;
-
-          self.$el.addClass(Backform.errorClassName).find(
-            '[type="radio"]'
-          ).append(
-            $('<div></div>').addClass(
-              'pgadmin-control-error-message pg-el-offset-4 pg-el-8 pg-el-8 help-block'
-            ).text(error));
-        });
-      },
-    });
-
-
-  Backform.RadioModernControl = Backform.RadioControl.extend({
-    defaults: {
-      controlLabelClassName: Backform.controlLabelClassName,
-      controlsClassName: Backform.controlsClassName,
-      extraClasses: [],
-      helpMessage: '',
-      name: '',
-    },
-    events: _.extend({}, Backform.InputControl.prototype.events, {
-      'click label.btn': 'toggle',
-    }),
-    toggle: function(e) {
-      /* Toggle the other buttons to unchecked and current to checked */
-      let $curr = $(e.currentTarget),
-        $btn_group = $curr.closest('.btn-group');
-
-      $btn_group.find('.btn')
-        .removeClass('btn-primary')
-        .addClass('btn-secondary')
-        .find('.fa')
-        .addClass('visibility-hidden')
-        .siblings('input')
-        .prop('checked', false);
-
-      $curr.removeClass('btn-secondary')
-        .addClass('btn-primary')
-        .find('.fa')
-        .removeClass('visibility-hidden')
-        .siblings('input')
-        .prop('checked', true)
-        .trigger('change');
-
-      e.preventDefault();
-      e.stopPropagation();
-    },
-    template: _.template([
-      '<% if (label) { %>',
-      '<label class="<%=controlLabelClassName%>" id="<%=cId%>_grplabel"><%=label%></label>',
-      '<% } %>',
-      '<div class="<%=controlsClassName%> <%=extraClasses.join(\' \')%>">',
-      ' <div class="btn-group pgadmin-controls-radio-none<% if (disabled) {%> disabled <%}%>" role="radiogroup" <% if (label) {%> aria-labelledby="<%=cId%>_grplabel" <%}%>>',
-      '  <% for (let i=0; i < options.length; i++) { %>',
-      '  <% let option = options[i]; %>',
-      '  <label role="radio" class="btn btn-radiomodern <% if (option.value == value) { %> btn-primary <%} else {%> btn-secondary <%}%> <% if (!option.disabled && !disabled) { %>" tabindex="0"<% } else { %> disabled"<% } %>>',
-      '    <i class="fa fa-check  <% if (option.value != value) { %>visibility-hidden <%}%>" role="img"></i>',
-      '    <input type="radio" name="<%=name%>" autocomplete="off" value=<%-formatter.fromRaw(option.value)%> <% if (option.value == value) { %> checked<%}%> <% if (option.disabled || disabled) { %> disabled <%}%>> <%-option.label%>',
-      '  </label>',
-      '  <% } %>',
-      ' </div>',
-      ' <% if (helpMessage && helpMessage.length) { %>',
-      '  <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      ' <% } %>',
-      '</div>',
-    ].join('\n')),
-    formatter: RawFormatter,
-    getValueFromDOM: function() {
-      return this.formatter.toRaw(this.$el.find('input[type="radio"]:checked').attr('value'), this.model);
-    },
-    render: function() {
-      let field = _.defaults(this.field.toJSON(), this.defaults),
-        attributes = this.model.toJSON(),
-        attrArr = field.name.split('.'),
-        name = attrArr.shift(),
-        path = attrArr.join('.'),
-        rawValue = this.keyPathAccessor(attributes[name], path),
-        data = _.extend(field, {
-          rawValue: rawValue,
-          value: this.formatter.fromRaw(rawValue, this.model),
-          attributes: attributes,
-          formatter: this.formatter,
-        }),
-        // Evaluate the disabled, visible, and required option
-        evalF = function evalF(f, d, m) {
-          return _.isFunction(f) ? !!f.apply(d, [m]) : !!f;
-        };
-
-      _.extend(data, {
-        disabled: evalF(data.disabled, data, this.model),
-        visible: evalF(data.visible, data, this.model),
-        required: evalF(data.required, data, this.model),
-      }); // Clean up first
-
-      data.cId = data.cId || _.uniqueId('pgC_');
-      data.options = _.isFunction(data.options) ?
-        data.options.apply(data, [this.model]) : data.options;
-
-      this.$el.removeClass(Backform.hiddenClassName);
-      if (!data.visible) this.$el.addClass(Backform.hiddenClassName);
-      this.$el.html(this.template(data)).addClass(field.name);
-      this.updateInvalid();
-
-      this.$el.find('.btn').on('keyup', (e)=>{
-        /* Spacebar click */
-        if (e.keyCode == 32) {
-          $(e.currentTarget).trigger('click');
-        }
-      });
-      return this;
-    },
-  });
-
-  // Requires the Bootstrap Switch to work.
-  Backform.SwitchControl = Backform.InputControl.extend({
-    defaults: {
-      label: '',
-      options: {
-        onText: gettext('Yes'),
-        offText: gettext('No'),
-        onColor: 'success',
-        offColor: 'ternary',
-        size: 'mini',
-        width: null,
-        height: null,
-      },
-      controlLabelClassName: Backform.controlLabelClassName,
-      controlsClassName: Backform.controlsClassName,
-      extraClasses: [],
-      helpMessage: null,
-      extraToggleClasses: null,
-    },
-    template: _.template([
-      '<span class="<%=controlLabelClassName%>"><%=label%></span>',
-      '<div class="<%=controlsClassName%> <%=extraClasses.join(\' \')%>">',
-      '      <input tabindex="-1" type="checkbox" aria-hidden="true" aria-label="' + gettext('Toggle button') + '" data-style="quick" data-toggle="toggle"',
-      '      data-size="<%=options.size%>" data-height="<%=options.height%>"  ',
-      '      data-on="<%=options.onText%>" data-off="<%=options.offText%>" ',
-      '      data-onstyle="<%=options.onColor%>" data-offstyle="<%=options.offColor%>" data-width="<%=options.width%>" ',
-      '      name="<%=name%>" <%=value ? "checked=\'checked\'" : ""%> <%=disabled ? "disabled" : ""%> <%=readonly ? "disabled" : ""%> <%=required ? "required" : ""%> />',
-      '  <% if (helpMessage && helpMessage.length) { %>',
-      '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '  <% } %>',
-      '</div>',
-    ].join('\n')),
-    getValueFromDOM: function() {
-      return this.formatter.toRaw(
-        this.$input.prop('checked'),
-        this.model
-      );
-    },
-    events: {
-      'change input': 'onChange',
-      'keyup': 'toggleSwitch',
-    },
-    setSrValue: function() {
-      let {onText, offText} = _.defaults(this.field.get('options'), this.defaults.options);
-      let label = this.field.get('label');
-
-      if(this.$el.find('.toggle.btn').hasClass('off')) {
-        this.$el.find('.sr-value').text(`
-          ${label}, ${offText}, ` + gettext('Toggle') + `
-        `);
-      } else {
-        this.$el.find('.sr-value').text(`
-          ${label}, ${onText}, ` + gettext('Toggle') + `
-        `);
-      }
-    },
-    onChange: function() {
-      Backform.InputControl.prototype.onChange.apply(this, arguments);
-      this.setSrValue();
-    },
-    toggleSwitch: function(e) {
-      if (e.keyCode == 32) {
-        this.$el.find('input[type=checkbox]').bootstrapToggle('toggle');
-        e.preventDefault();
-        this.setSrValue();
-      }
-    },
-    render: function() {
-      let field = _.defaults(this.field.toJSON(), this.defaults),
-        attributes = this.model.toJSON(),
-        attrArr = field.name.split('.'),
-        name = attrArr.shift(),
-        path = attrArr.join('.'),
-        rawValue = this.keyPathAccessor(attributes[name], path),
-        data = _.extend(field, {
-          rawValue: rawValue,
-          value: this.formatter.fromRaw(rawValue, this.model),
-          attributes: attributes,
-          formatter: this.formatter,
-        }),
-        evalF = function(f, d, m) {
-          return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f);
-        };
-
-      // Evaluate the disabled, visible, and required option
-      _.extend(data, {
-        disabled: evalF(field.disabled, field, this.model),
-        readonly: evalF(field.readonly, field, this.model),
-        visible:  evalF(data.visible, field, this.model),
-        required: evalF(data.required, field, this.model),
-      });
-
-      data.cId = data.cId || _.uniqueId('pgC_');
-      // Clean up first
-      this.$el.removeClass(Backform.hiddenClassName);
-
-      if (!data.visible)
-        this.$el.addClass(Backform.hiddenClassName);
-
-      if(Backform.requiredInputClassName) {
-        this.$el.removeClass(Backform.requiredInputClassName);
-      }
-
-      if (data.required) {
-        this.$el.addClass(Backform.requiredInputClassName);
-      }
-
-      /* Set disabled for both disabled and readonly */
-      data.options = _.defaults({
-        disabled: data.disabled || data.readonly,
-      }, this.field.get('options'), this.defaults.options,
-      $.fn.bootstrapToggle.defaults);
-
-      this.$el.html(this.template(data)).addClass(field.name);
-
-      // Add Extra Toggle classes to render multiple toggles in a single row
-      if(!_.isNull(field.extraToggleClasses)) this.$el.addClass(field.extraToggleClasses);
-
-      this.$input = this.$el.find('input[type=checkbox]').first();
-      this.$input.bootstrapToggle();
-      // When disable then set tabindex value to -1
-      this.$el.find('.toggle.btn')
-        .attr('tabindex', data.disabled ? '-1' : '0')
-        .attr('id', data.cId);
-
-      this.$el.find('.toggle.btn .toggle-group .btn').attr('aria-hidden', true);
-      this.$el.find('div.toggle').append('<label class="sr-value sr-only" for="<%=cId%>"></label>');
-      this.setSrValue();
-
-      this.updateInvalid();
-
-      /* Bootstrap toggle does not have option for readonly
-       * If readonly, then let it focus.
-       */
-      if(data.readonly) {
-        this.$el.find('.select2-selection').attr('tabindex', 0);
-      }
-      return this;
-    },
-  });
-
-  // Backform Dialog view (in bootstrap tabbular form)
-  // A collection of field models.
-  Backform.Dialog = Backform.Form.extend({
-    /* Array of objects having attributes [label, fields] */
-    schema: undefined,
-    tagName: 'div',
-    legend: true,
-    className: function() {
-      return 'pg-el-sm-12 pg-el-md-12 pg-el-lg-12 pg-el-12';
-    },
-    tabPanelClassName: function() {
-      return Backform.tabClassName;
-    },
-    tabIndex: 0,
-    initialize: function(opts) {
-      let s = opts.schema;
-      if (s && _.isArray(s)) {
-        this.schema = _.each(s, function(o) {
-          if (o.fields && !(o.fields instanceof Backbone.Collection))
-            o.fields = new Backform.Fields(o.fields);
-          o.cId = o.cId || _.uniqueId('pgC_');
-          o.hId = o.hId || _.uniqueId('pgH_');
-          o.disabled = o.disabled || false;
-          o.legend = opts.legend;
-        });
-        if (opts.tabPanelClassName && _.isFunction(opts.tabPanelClassName)) {
-          this.tabPanelClassName = opts.tabPanelClassName;
-        }
-      }
-      this.model.errorModel = opts.errorModel || this.model.errorModel || new Backbone.Model();
-      this.controls = [];
-    },
-    template: {
-      'header': _.template([
-        '<li class="nav-item" <%=disabled ? "disabled" : ""%>>',
-        ' <a class="nav-link" data-toggle="tab" role="tab" tabindex="-1" data-tab-index="<%=tabIndex%>" href="#<%=cId%>"',
-        '  id="<%=hId%>" aria-controls="<%=cId%>">',
-        '<%=label%></a></li>',
-      ].join(' ')),
-      'panel': _.template(
-        '<div role="tabpanel" tabindex="-1" class="tab-pane <%=label%> <%=tabPanelCodeClass%> pg-el-sm-12 pg-el-md-12 pg-el-lg-12 pg-el-12 fade" id="<%=cId%>" aria-labelledby="<%=hId%>"></div>'
-      ),
-    },
-    render: function() {
-      this.cleanup();
-
-      let c = this.$el
-          .children().first().children('.active')
-          .first().attr('id'),
-        m = this.model,
-        controls = this.controls,
-        tmpls = this.template,
-        self = this,
-        idx = (this.tabIndex * 100),
-        evalF = function(f, d, model) {
-          return (_.isFunction(f) ? !!f.apply(d, [model]) : !!f);
-        };
-
-      this.$el
-        .empty()
-        .attr('role', 'tabpanel')
-        .attr('class', _.result(this, 'tabPanelClassName'));
-      m.panelEl = this.$el;
-
-      let tabHead = $('<ul class="nav nav-tabs" role="tablist"></ul>')
-        .appendTo(this.$el);
-      let tabContent = $('<div class="tab-content pg-el-sm-12 pg-el-md-12 pg-el-lg-12 pg-el-12"></div>')
-        .appendTo(this.$el);
-
-      _.each(this.schema, function(o) {
-        idx++;
-        if (!o.version_compatible || !evalF(o.visible, o, m)) {
-          return;
-        }
-        let el = $((tmpls['panel'])(_.extend(o, {
-          'tabIndex': idx,
-          'tabPanelCodeClass': o.tabPanelCodeClass ? o.tabPanelCodeClass : '',
-        })))
-          .appendTo(tabContent)
-          .removeClass('collapse').addClass('collapse');
-        $((tmpls['header'])(o)).appendTo(tabHead);
-
-        o.fields.each(function(f) {
-          let cntr = new(f.get('control'))({
-            field: f,
-            model: m,
-            dialog: self,
-            tabIndex: idx,
-          });
-          el.append(cntr.render().$el);
-          controls.push(cntr);
-        });
-
-        tabHead.find('a[data-toggle="tab"]').off(
-          'shown.bs.tab'
-        ).off('hidden.bs.tab').on(
-          'hidden.bs.tab',
-          function() {
-            self.hidden_tab = $(this).data('tabIndex');
-          }).on('shown.bs.tab', function() {
-          let ctx = this;
-          ctx.shown_tab = $(ctx).data('tabIndex');
-          m.trigger('pg-property-tab-changed', {
-            'model': m,
-            'shown': ctx.shown_tab,
-            'hidden': ctx.hidden_tab,
-            'tab': ctx,
-          });
-        });
-      });
-
-      let makeActive = tabHead.find('[id="' + c + '"]').first();
-      if (makeActive.length == 1) {
-        makeActive.addClass('active show');
-        tabContent.find('#' + makeActive.attr('aria-controls'))
-          .addClass('active show');
-      } else {
-        tabHead.find('.nav-link').first().addClass('active show');
-        tabContent.find('.tab-pane').first().addClass('active show');
-      }
-
-      return this;
-    },
-    remove: function(opts) {
-      if (opts && opts.data) {
-        if (this.model) {
-          if (this.model.reset) {
-            this.model.reset({
-              validate: false,
-              silent: true,
-              stop: true,
-            });
-          }
-          this.model.clear({
-            validate: false,
-            silent: true,
-            stop: true,
-          });
-          delete(this.model);
-        }
-        if (this.errorModel) {
-          this.errorModel.clear({
-            validate: false,
-            silent: true,
-            stop: true,
-          });
-          delete(this.errorModel);
-        }
-      }
-      this.cleanup();
-      Backform.Form.prototype.remove.apply(this, arguments);
-    },
-  });
-
-  Backform.Accordian   = Backform.Dialog.extend({
-    className: function() {
-      return 'set-group pg-el-12';
-    },
-    tabPanelClassName: function() {
-      return Backform.tabClassName;
-    },
-    legendClass: 'badge',
-    contentClass: Backform.accordianContentClassName + ' collapse show',
-    template: {
-      'header': _.template([
-        '<div class="<%=Backform.accordianGroupClassName%>" <%=disabled ? "disabled" : ""%>>',
-        ' <% if (legend != false) { %>',
-        '  <div class="<%=legendClass%>" <%=collapse ? "data-toggle=\'collapse\'" : ""%> data-target="#<%=cId%>" aria-controls="<%=cId%>" aria-level="3" role="heading"><%=collapse ? "<span class=\'caret\'></span>" : "" %><%=label%></legend>',
-        ' <% } %>',
-        '</div>',
-      ].join('\n')),
-      'content': _.template(
-        '  <div id="<%= cId %>" class="<%=contentClass%>"></div>'
-      ),
-    },
-    collapse: true,
-    render: function() {
-      this.cleanup();
-
-      let m = this.model,
-        $el = this.$el,
-        tmpl = this.template,
-        controls = this.controls,
-        data = {
-          'className': _.result(this, 'className'),
-          'legendClass': _.result(this, 'legendClass'),
-          'contentClass': _.result(this, 'contentClass'),
-          'collapse': _.result(this, 'collapse'),
-        },
-        idx = (this.tabIndex * 100),
-        evalF = function(f, d, model) {
-          return (_.isFunction(f) ? !!f.apply(d, [model]) : !!f);
-        };
-
-      this.$el.empty();
-
-      _.each(this.schema, function(o) {
-        idx++;
-        if (!o.version_compatible || !evalF(o.visible, o, m)) {
-          return;
-        }
-
-        if (!o.fields)
-          return;
-
-        let d = _.extend({}, data, o),
-          h = $((tmpl['header'])(d)).appendTo($el),
-          el = $((tmpl['content'])(d)).appendTo(h);
-
-        o.fields.each(function(f) {
-          let cntr = new(f.get('control'))({
-            field: f,
-            model: m,
-            tabIndex: idx,
-          });
-          el.append(cntr.render().$el);
-          controls.push(cntr);
-        });
-      });
-
-      return this;
-    },
-    getValueFromDOM: function() {
-      return '';
-    },
-    events: {},
-  });
-
-  Backform.Fieldset = Backform.Dialog.extend({
-    className: function() {
-      return 'set-group pg-el-12';
-    },
-    tabPanelClassName: function() {
-      return Backform.tabClassName;
-    },
-    fieldsetClass: Backform.setGroupClassName,
-    legendClass: 'badge',
-    contentClass: Backform.setGroupContentClassName + ' collapse show',
-    template: {
-      'header': _.template([
-        '<fieldset class="<%=fieldsetClass%>" <%=disabled ? "disabled" : ""%>>',
-        ' <% if (legend != false) { %>',
-        '  <legend class="<%=legendClass%>" <%=collapse ? "data-toggle=\'collapse\'" : ""%> data-target="#<%=cId%>"><%=collapse ? "<span class=\'caret\'></span>" : "" %><%=label%></legend>',
-        ' <% } %>',
-        '</fieldset>',
-      ].join('\n')),
-      'content': _.template(
-        '  <div id="<%= cId %>" class="<%=contentClass%>"></div>'
-      ),
-    },
-    collapse: true,
-    render: function() {
-      this.cleanup();
-
-      let m = this.model,
-        $el = this.$el,
-        tmpl = this.template,
-        controls = this.controls,
-        data = {
-          'className': _.result(this, 'className'),
-          'fieldsetClass': _.result(this, 'fieldsetClass'),
-          'legendClass': _.result(this, 'legendClass'),
-          'contentClass': _.result(this, 'contentClass'),
-          'collapse': _.result(this, 'collapse'),
-        },
-        idx = (this.tabIndex * 100),
-        evalF = function(f, d, model) {
-          return (_.isFunction(f) ? !!f.apply(d, [model]) : !!f);
-        };
-
-      this.$el.empty();
-
-      _.each(this.schema, function(o) {
-        idx++;
-        if (!o.version_compatible || !evalF(o.visible, o, m)) {
-          return;
-        }
-
-        if (!o.fields)
-          return;
-
-        let d = _.extend({}, data, o),
-          h = $((tmpl['header'])(d)).appendTo($el),
-          el = $((tmpl['content'])(d)).appendTo(h);
-
-        o.fields.each(function(f) {
-          let cntr = new(f.get('control'))({
-            field: f,
-            model: m,
-            tabIndex: idx,
-          });
-          el.append(cntr.render().$el);
-          controls.push(cntr);
-        });
-      });
-
-      return this;
-    },
-    getValueFromDOM: function() {
-      return '';
-    },
-    events: {},
-  });
-
-  Backform.generateGridColumnsFromModel =
-    function(node_info, m, type, cols, node) {
-      let groups = Backform.generateViewSchema(
-          node_info, m, type, node, true, true
-        ),
-        schema = [],
-        columns = [],
-        func,
-        idx = 0;
-
-      // Create another array if cols is of type object & store its keys in that array,
-      // If cols is object then chances that we have custom width class attached with in.
-      if (_.isNull(cols) || _.isUndefined(cols)) {
-        func = function(f) {
-          f.cell_priority = idx;
-          idx = idx + 1;
-
-          // We can also provide custom header cell class in schema itself,
-          // But we will give priority to extraClass attached in cols
-          // If headerCell property is already set by cols then skip extraClass property from schema
-          if (!(f.headerCell) && f.cellHeaderClasses) {
-            f.headerCell = Backgrid.Extension.CustomHeaderCell;
-          }
-        };
-      } else if (_.isArray(cols)) {
-        func = function(f) {
-          f.cell_priority = _.indexOf(cols, f.name);
-
-          // We can also provide custom header cell class in schema itself,
-          // But we will give priority to extraClass attached in cols
-          // If headerCell property is already set by cols then skip extraClass property from schema
-          if ((!f.headerCell) && f.cellHeaderClasses) {
-            f.headerCell = Backgrid.Extension.CustomHeaderCell;
-          }
-        };
-      } else if (_.isObject(cols)) {
-        let tblCols = Object.keys(cols);
-        func = function(f) {
-          let val = (f.name in cols) && cols[f.name],
-            i;
-
-          if (_.isNull(val) || _.isUndefined(val)) {
-            f.cell_priority = -1;
-            return;
-          }
-          if (_.isObject(val)) {
-            if ('index' in val) {
-              f.cell_priority = val['index'];
-              idx = (idx > val['index']) ? idx + 1 : val['index'];
-            } else {
-              i = _.indexOf(tblCols, f.name);
-              f.cell_priority = idx = ((i > idx) ? i : idx);
-              idx = idx + 1;
-            }
-
-            // We can also provide custom header cell class in schema itself,
-            // But we will give priority to extraClass attached in cols
-            // If headerCell property is already set by cols then skip extraClass property from schema
-            if (!f.headerCell) {
-              if (f.cellHeaderClasses) {
-                f.headerCell = Backgrid.Extension.CustomHeaderCell;
-              }
-              if ('class' in val && _.isString(val['class'])) {
-                f.headerCell = Backgrid.Extension.CustomHeaderCell;
-                f.cellHeaderClasses = (f.cellHeaderClasses || '') + ' ' + val['class'];
-              }
-            }
-          }
-          if (_.isString(val)) {
-            i = _.indexOf(tblCols, f.name);
-
-            f.cell_priority = idx = ((i > idx) ? i : idx);
-            idx = idx + 1;
-
-            if (!f.headerCell) {
-              f.headerCell = Backgrid.Extension.CustomHeaderCell;
-            }
-            f.cellHeaderClasses = (f.cellHeaderClasses || '') + ' ' + val;
-          }
-        };
-      }
-
-      // Prepare columns for backgrid
-      _.each(groups, function(group) {
-        _.each(group.fields, function(f) {
-          if (!f.cell) {
-            return;
-          }
-          // Check custom property in cols & if it is present then attach it to current cell
-          func(f);
-          if (f.cell_priority != -1) {
-            columns.push(f);
-          }
-        });
-        schema.push(group);
-      });
-      return {
-        'columns': _.sortBy(columns, function(c) {
-          return c.cell_priority;
-        }),
-        'schema': schema,
-      };
-    };
-
-  Backform.BinaryPathsGridControl = Backform.Control.extend({
-    initialize: function() {
-      Backform.Control.prototype.initialize.apply(this, arguments);
-
-      let BinaryPathModel = Backbone.Model.extend({
-        idAttribute: 'serverType',
-        defaults: {
-          serverType: undefined,
-          binaryPath: undefined,
-          isDefault: false
-        },
-      });
-
-      let placeholder = pgAdmin.enable_binary_path_browsing ? gettext('Select binary path...') : gettext('Enter binary path...'),
-        browse_btn_visible = pgAdmin.enable_binary_path_browsing ? true : false;
-
-      if (pgAdmin.server_mode === 'False') {
-        placeholder = gettext('Select binary path...');
-        browse_btn_visible = true;
-      }
-
-      this.gridColumns = [{
-        name: 'isDefault',
-        label: gettext('Set as default'),
-        sortable: false,
-        cell: Backgrid.RadioCell,
-        cellHeaderClasses: 'width_percent_10',
-        headerCell: Backgrid.Extension.CustomHeaderCell,
-        deps: ['binaryPath'],
-        editable: function(m) {
-          if (!_.isUndefined(m.get('binaryPath')) && !_.isNull(m.get('binaryPath')) && m.get('binaryPath') !== '') {
-            return true;
-          } else if (!_.isUndefined(m.get('isDefault')) && !_.isNull(m.get('isDefault'))){
-            setTimeout(function() {
-              m.set('isDefault', false);
-            }, 10);
-          }
-
-          return false;
-        }
-      }, {
-        name: 'serverType',
-        label: gettext('Database Server'),
-        editable: false,
-        cell: 'string',
-        cellHeaderClasses: 'width_percent_20',
-        headerCell: Backgrid.Extension.CustomHeaderCell,
-      }, {
-        name: 'binaryPath',
-        label: gettext('Binary Path'),
-        sortable: false,
-        cell: Backgrid.Extension.SelectFileCell,
-        dialog_type: 'select_folder',
-        dialog_title: gettext('Select Folder'),
-        placeholder: placeholder,
-        browse_btn_label: gettext('Select path'),
-        check_btn_label: gettext('Validate utilities'),
-        browse_btn_visible: browse_btn_visible
-      }];
-
-      let BinPathCollection = this.BinPathCollection =  new (Backbone.Collection.extend({
-        model: BinaryPathModel
-      }))(null);
-
-      let bin_value = JSON.parse(this.model.get(this.field.get('name')));
-      this.BinPathCollection.add(bin_value);
-      this.listenTo(BinPathCollection, 'change', this.binPathCollectionChanged);
-    },
-
-    render: function() {
-      let self = this,
-        gridHeader = ['<div class=\'subnode-header\'>',
-          '  <span class=\'control-label pg-el-sm-12\'>' + gettext(this.field.get('label')) + '</span>',
-          '</div>',
-        ].join('\n'),
-        gridBody = $('<div class=\'pgadmin-control-group backgrid form-group pg-el-12 object subnode\'></div>').append(gridHeader);
-
-      self.grid = new Backgrid.Grid({
-        columns: self.gridColumns,
-        collection: self.BinPathCollection,
-        className: 'backgrid table presentation table-bordered table-noouter-border table-hover',
-      });
-
-      this.$el.empty();
-      this.$el.append(gridBody.append(self.grid.render().$el));
-      this.$el.append(['<span class="pg-el-sm-12 form-text text-muted help-block">' +
-      gettext('Enter the directory in which the psql, pg_dump, pg_dumpall, and pg_restore' +
-      ' utilities can be found for the corresponding database server version.' +
-      ' The default path will be used for server versions that do not have a' +
-      ' path specified.') + '</span>'].join('\n'));
-
-      return this;
-    },
-    binPathCollectionChanged: function() {
-      let bin_value = JSON.stringify(this.BinPathCollection.toJSON());
-      this.model.set(this.field.get('name'), bin_value, {
-        silent: false
-      });
-    }
-  });
-
-  Backform.UniqueColCollectionControl = Backform.Control.extend({
-    initialize: function() {
-      Backform.Control.prototype.initialize.apply(this, arguments);
-
-      let uniqueCol = this.field.get('uniqueCol') || [],
-        m = this.field.get('model'),
-        schema = m.prototype.schema || m.__super__.schema,
-        columns = [],
-        self = this;
-
-      _.each(schema, function(s) {
-        columns.push(s.id);
-      });
-
-      // Check if unique columns provided are also in model attributes.
-      if (uniqueCol.length > _.intersection(columns, uniqueCol).length) {
-        throw new Error('Developer: Unique columns [ ' + _.difference(uniqueCol, columns) + ' ] not found in collection model [ ' + columns + ' ].');
-      }
-
-      let collection = self.collection = self.model.get(self.field.get('name'));
-
-      if (!collection) {
-        collection = self.collection = new(pgAdmin.Browser.Node.Collection)(
-          null, {
-            model: self.field.get('model'),
-            silent: true,
-            handler: self.model,
-            top: self.model.top || self.model,
-            attrName: self.field.get('name'),
-          });
-        self.model.set(self.field.get('name'), collection, {
-          silent: true,
-        });
-      }
-
-      if (this.field.get('version_compatible')) {
-        self.listenTo(collection, 'add', self.collectionChanged);
-        self.listenTo(collection, 'change', self.collectionChanged);
-      }
-    },
-    cleanup: function() {
-      this.stopListening(this.collection, 'change', this.collectionChanged);
-
-      if (this.field.get('version_compatible')) {
-        this.stopListening(self.collection, 'add', this.collectionChanged);
-        this.stopListening(self.collection, 'change', this.collectionChanged);
-      }
-      if (this.grid) {
-        this.grid.remove();
-        delete this.grid;
-      }
-      this.$el.empty();
-    },
-    collectionChanged: function(newModel, coll, op) {
-      let uniqueCol = this.field.get('uniqueCol') || [],
-        uniqueChangedAttr = [],
-        self = this;
-
-      // Check if changed model attributes are also in unique columns. And then only check for uniqueness.
-      if (newModel.attributes) {
-        _.each(uniqueCol, function(col) {
-          if (_.has(newModel.attributes, col)) {
-            uniqueChangedAttr.push(col);
-          }
-        });
-        if (uniqueChangedAttr.length == 0) {
-          return;
-        }
-      } else {
-        return;
-      }
-
-      let collection = this.model.get(this.field.get('name'));
-      this.stopListening(collection, 'change', this.collectionChanged);
-      // Check if changed attribute's value of new/updated model also exist for another model in collection.
-      // If duplicate value exists then set the attribute's value of new/updated model to its previous values.
-      let m = undefined,
-        oldModel = undefined;
-      collection.each(function(model) {
-        if (newModel != model) {
-          let duplicateAttrValues = [];
-          _.each(uniqueCol, function(attr) {
-            let attrValue = newModel.get(attr);
-            if (!_.isUndefined(attrValue) && attrValue == model.get(attr)) {
-              duplicateAttrValues.push(attrValue);
-            }
-          });
-          if (duplicateAttrValues.length == uniqueCol.length) {
-            m = newModel;
-            // Keep reference of model to make it visible in dialog.
-            oldModel = model;
-          }
-        }
-      });
-      if (m) {
-        if (op && op.add) {
-          // Remove duplicate model.
-          setTimeout(function() {
-            collection.remove(m);
-          }, 0);
-
-        } else {
-          /*
-           * Set model value to its previous value as its new value is
-           * conflicting with another model value.
-           */
-
-          m.set(uniqueChangedAttr[0], m.previous(uniqueChangedAttr[0]));
-        }
-        if (oldModel) {
-          let idx = collection.indexOf(oldModel);
-          if (idx > -1) {
-            let newRow = self.grid.body.rows[idx].$el;
-            newRow.addClass('new');
-            $(newRow).pgMakeVisible('backform-tab');
-            setTimeout(function() {
-              newRow.removeClass('new');
-            }, 3000);
-          }
-        }
-      }
-
-      this.listenTo(collection, 'change', this.collectionChanged);
-    },
-    render: function() {
-      // Clean up existing elements
-
-      this.undelegateEvents();
-      this.$el.empty();
-
-      let field = _.defaults(this.field.toJSON(), this.defaults),
-        attributes = this.model.toJSON(),
-        attrArr = field.name.split('.'),
-        name = attrArr.shift(),
-        path = attrArr.join('.'),
-        rawValue = this.keyPathAccessor(attributes[name], path),
-        data = _.extend(field, {
-          rawValue: rawValue,
-          value: this.formatter.fromRaw(rawValue, this.model),
-          attributes: attributes,
-          formatter: this.formatter,
-        }),
-        evalF = function(f, d, m) {
-          return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f);
-        };
-
-      // Evaluate the disabled, visible, required, canAdd, & canDelete option
-      _.extend(data, {
-        disabled: (field.version_compatible &&
-          evalF.apply(this.field, [data.disabled, data, this.model])
-        ),
-        visible: evalF.apply(this.field, [data.visible, data, this.model]),
-        required: evalF.apply(this.field, [data.required, data, this.model]),
-        canAdd: (field.version_compatible &&
-          evalF.apply(this.field, [data.canAdd, data, this.model])
-        ),
-        canAddRow: data.canAddRow,
-        canDelete: evalF.apply(this.field, [data.canDelete, data, this.model]),
-        canEdit: evalF.apply(this.field, [data.canEdit, data, this.model]),
-      });
-      _.extend(data, {
-        add_label: '',
-      });
-
-      // This control is not visible, we should remove it.
-      if (!data.visible) {
-        return this;
-      }
-
-      this.control_data = _.clone(data);
-
-      // Show Backgrid Control
-      let grid = this.showGridControl(data);
-
-      this.$el.html(grid).addClass(field.name);
-      this.updateInvalid();
-
-      this.delegateEvents();
-      return this;
-    },
-    showGridControl: function(data) {
-      data.cId = data.cId || _.uniqueId('pgC_');
-      let self = this,
-        gridHeader = _.template([
-          '<div class="subnode-header">',
-          '  <span  class="control-label pg-el-sm-10" id="<%=cId%>"><%-label%></span>',
-          '  <button aria-label="' + gettext('Add new row') + '" class="btn btn-sm-sq btn-primary-icon add fa fa-plus" <%=canAdd ? "" : "disabled=\'disabled\'"%> title="' + gettext('Add new row') + '"><%-add_label%></button>',
-          '</div>',
-        ].join('\n')),
-        gridBody = $('<div class="pgadmin-control-group backgrid form-group pg-el-12 object subnode "></div>').append(
-          gridHeader(data)
-        );
-
-      // Clean up existing grid if any (in case of re-render)
-      if (self.grid) {
-        self.grid.remove();
-      }
-
-      if (!(data.subnode)) {
-        return '';
-      }
-
-      let subnode = data.subnode.schema ? data.subnode : data.subnode.prototype,
-        gridSchema = Backform.generateGridColumnsFromModel(
-          data.node_info, subnode, this.field.get('mode'), data.columns
-        );
-
-      // Set visibility of Add button
-      if (data.mode == 'properties') {
-        $(gridBody).find('button.add').remove();
-      }
-
-      // Insert Delete Cell into Grid
-      if (!data.disabled && data.canDelete) {
-        gridSchema.columns.unshift({
-          name: 'pg-backform-delete',
-          label: '',
-          cell: Backgrid.Extension.DeleteCell,
-          editable: false,
-          cell_priority: -1,
-          canDeleteRow: data.canDeleteRow,
-        });
-      }
-
-      // Insert Edit Cell into Grid
-      if (!data.disabled && data.canEdit) {
-        let editCell = Backgrid.Extension.ObjectCell.extend({
-          schema: gridSchema.schema,
-        });
-
-        gridSchema.columns.unshift({
-          name: 'pg-backform-edit',
-          label: '',
-          cell: editCell,
-          cell_priority: -2,
-          canEditRow: data.canEditRow,
-        });
-      }
-
-      let collection = this.model.get(data.name);
-
-      let cellEditing = function(args) {
-        let that = this,
-          cell = args[0];
-        // Search for any other rows which are open.
-        this.each(function(m) {
-          // Check if row which we are about to close is not current row.
-          if (cell.model != m) {
-            let idx = that.indexOf(m);
-            if (idx > -1) {
-              let row = self.grid.body.rows[idx],
-                rowEditCell = row.$el.find('.subnode-edit-in-process').parent();
-              // Only close row if it's open.
-              if (rowEditCell.length > 0) {
-                let event = new Event('click');
-                rowEditCell[0].dispatchEvent(event);
-              }
-            }
-          }
-        });
-      };
-      // Listen for any row which is about to enter in edit mode.
-      collection.on('enteringEditMode', cellEditing, collection);
-
-      // Initialize a new Grid instance
-      self.grid = new Backgrid.Grid({
-        columns: gridSchema.columns,
-        collection: collection,
-        className: 'backgrid table presentation table-bordered table-noouter-border table-hover',
-        attr: {
-          'aria-labelledby': data.cId,
-        },
-      });
-
-      for(let i = 0; i < (collection.length); i++) {
-        collection.at(i).parentTr = self.grid.body.rows[i].$el;
-      }
-
-      // Render subNode grid
-      let subNodeGrid = self.grid.render().$el;
-
-      // Combine Edit and Delete Cell
-      if (data.canDelete && data.canEdit) {
-        $(subNodeGrid).find('th.pg-backform-delete').remove();
-        $(subNodeGrid).find('th.pg-backform-edit').attr('colspan', '2');
-      }
-
-      let $dialog = gridBody.append(subNodeGrid);
-
-      let tmp_browser = pgBrowser;
-      if (pgBrowser.preferences_cache.length == 0)
-        tmp_browser = pgWindow.default.pgAdmin.Browser;
-
-      let preferences = tmp_browser.get_preferences_for_module('browser');
-
-      if (preferences) {
-        let addBtn = $dialog.find('.add');
-        // Add title to the buttons
-        $(addBtn)
-          .attr('title',
-            keyboardShortcuts.shortcut_title(gettext('Add new row'),preferences.add_grid_row));
-      }
-
-      // Add button callback
-      if (!(data.disabled || !data.canAdd)) {
-        $dialog.find('button.add').first().on('click',(e) => {
-          e.preventDefault();
-          let canAddRow = _.isFunction(data.canAddRow) ?
-            data.canAddRow.apply(self, [self.model]) : true;
-          if (canAddRow) {
-            // Close any existing expanded row before adding new one.
-            _.each(self.grid.body.rows, function(row) {
-              let rowEditCell = row.$el.find('.subnode-edit-in-process').parent();
-              // Only close row if it's open.
-              if (rowEditCell.length > 0) {
-                let event = new Event('click');
-                rowEditCell[0].dispatchEvent(event);
-              }
-            });
-
-            let allowMultipleEmptyRows = !!self.field.get('allowMultipleEmptyRows');
-
-            // If allowMultipleEmptyRows is not set or is false then don't allow second new empty row.
-            // There should be only one empty row.
-            if (!allowMultipleEmptyRows && collection) {
-              let isEmpty = false;
-              collection.each(function(model) {
-                let modelValues = [];
-                _.each(model.attributes, function(val) {
-                  modelValues.push(val);
-                });
-                if (!_.some(modelValues, _.identity)) {
-                  isEmpty = true;
-                }
-              });
-              if (isEmpty) {
-                return false;
-              }
-            }
-
-            $(self.grid.body.$el.find($('tr.new'))).removeClass('new');
-            let m = new(data.model)(null, {
-              silent: true,
-              handler: collection,
-              top: self.model.top || self.model,
-              collection: collection,
-              node_info: self.model.node_info,
-            });
-
-            if(data.beforeAdd) {
-              m = data.beforeAdd.apply(self, [m]);
-            }
-            collection.add(m);
-
-            let idx = collection.indexOf(m),
-              newRow = self.grid.body.rows[idx].$el;
-
-            collection.get(m).parentTr = newRow;
-            m.parentTr = newRow;
-
-            newRow.addClass('new');
-            if(!$(newRow).pgMakeBackgridVisible('.backform-tab')){
-              // We can have subnode controls in Panels
-              $(newRow).pgMakeBackgridVisible('.set-group');
-            }
-            return false;
-          }
-        });
-      }
-
-      return $dialog;
-    },
-    clearInvalid: function() {
-      this.$el.removeClass('subnode-error');
-      this.$el.find('.pgadmin-control-error-message').remove();
-      return this;
-    },
-    updateInvalid: function() {
-      let self = this,
-        errorModel = self.model.errorModel;
-
-      if (!(errorModel instanceof Backbone.Model)) return this;
-
-      this.clearInvalid();
-    },
-  });
-
-  Backform.SubNodeCollectionControl = Backform.Control.extend({
-    row: Backgrid.Row,
-    render: function() {
-      let field = _.defaults(this.field.toJSON(), this.defaults),
-        attributes = this.model.toJSON(),
-        attrArr = field.name.split('.'),
-        name = attrArr.shift(),
-        path = attrArr.join('.'),
-        rawValue = this.keyPathAccessor(attributes[name], path),
-        data = _.extend(field, {
-          rawValue: rawValue,
-          value: this.formatter.fromRaw(rawValue, this.model),
-          attributes: attributes,
-          formatter: this.formatter,
-        }),
-        evalF = function(f, d, m) {
-          return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f);
-        };
-
-      // Evaluate the disabled, visible, required, canAdd, cannEdit & canDelete option
-      _.extend(data, {
-        disabled: evalF(data.disabled, data, this.model),
-        visible: evalF(data.visible, data, this.model),
-        required: evalF(data.required, data, this.model),
-        canAdd: evalF(data.canAdd, data, this.model),
-        canAddRow: data.canAddRow,
-        canEdit: evalF(data.canEdit, data, this.model),
-        canDelete: evalF(data.canDelete, data, this.model),
-        showError: data.showError || true,
-      });
-      // Show Backgrid Control
-      let grid = (data.subnode == undefined) ? '' : this.showGridControl(data);
-
-      // Clean up first
-      this.$el.removeClass(Backform.hiddenClassName);
-
-      if (!data.visible)
-        this.$el.addClass(Backform.hiddenClassName);
-
-      this.$el.html(grid).addClass(field.name);
-      this.updateInvalid();
-
-      return this;
-    },
-    updateInvalid: function() {
-      let self = this;
-      let errorModel = this.model.errorModel;
-      if (!(errorModel instanceof Backbone.Model)) return this;
-
-      this.clearInvalid();
-
-      let attrArr = self.field.get('name').split('.'),
-        path = attrArr.join('.'),
-        error = self.keyPathAccessor(errorModel.toJSON(), path);
-
-      if (_.isEmpty(error)) return;
-
-      if (self.field.get('showError')) {
-        self.$el.addClass('subnode-error').append(
-          $('<div></div>').addClass('pgadmin-control-error-message pg-el-offset-4 pg-el-8 help-block').text(error)
-        );
-      }
-    },
-    cleanup: function() {
-      // Clean up existing grid if any (in case of re-render)
-      if (this.grid) {
-        this.grid.remove();
-      }
-      if (this.collection) {
-        this.collection.off('enteringEditMode');
-      }
-    },
-    clearInvalid: function() {
-      if (this.field.get('showError')) {
-        this.$el.removeClass('subnode-error');
-        this.$el.find('.pgadmin-control-error-message').remove();
-      }
-      return this;
-    },
-    showGridControl: function(data) {
-      let self = this,
-        gridHeader = ['<div class=\'subnode-header\'>',
-          '  <span class=\'control-label pg-el-sm-10\'>' + data.label + '</span>',
-          '  <button aria-label="' + gettext('Add') + '" class=\'btn btn-sm-sq btn-primary-icon add fa fa-plus\' title=\'' + gettext('Add new row') + '\'></button>',
-          '</div>',
-        ].join('\n'),
-        gridBody = $('<div class=\'pgadmin-control-group backgrid form-group pg-el-12 object subnode\'></div>').append(gridHeader);
-
-      let subnode = data.subnode.schema ? data.subnode : data.subnode.prototype,
-        gridSchema = Backform.generateGridColumnsFromModel(
-          data.node_info, subnode, this.field.get('mode'), data.columns, data.schema_node
-        );
-
-      // Clean up existing grid if any (in case of re-render)
-      if (self.grid) {
-        self.grid.remove();
-      }
-
-      // Set visibility of Add button
-      if (data.disabled || !data.canAdd) {
-        $(gridBody).find('button.add').remove();
-      }
-
-      // Insert Delete Cell into Grid
-      if (!data.disabled && data.canDelete) {
-        gridSchema.columns.unshift({
-          name: 'pg-backform-delete',
-          label: '',
-          cell: Backgrid.Extension.DeleteCell,
-          editable: false,
-          cell_priority: -1,
-          canDeleteRow: data.canDeleteRow,
-          customDeleteMsg: data.customDeleteMsg,
-          customDeleteTitle: data.customDeleteTitle,
-        });
-      }
-
-      // Insert Edit Cell into Grid
-      if (!data.disabled && data.canEdit) {
-        let editCell = Backgrid.Extension.ObjectCell.extend({
-            schema: gridSchema.schema,
-          }),
-          canEdit = self.field.has('canEdit') &&
-          self.field.get('canEdit') || true;
-
-        gridSchema.columns.unshift({
-          name: 'pg-backform-edit',
-          label: '',
-          cell: editCell,
-          cell_priority: -2,
-          editable: canEdit,
-          canEditRow: data.canEditRow,
-        });
-      }
-
-      let collection = self.model.get(data.name);
-
-      if (!collection) {
-        collection = new(pgBrowser.Node.Collection)(null, {
-          handler: self.model.handler || self.model,
-          model: data.model,
-          top: self.model.top || self.model,
-          silent: true,
-        });
-        self.model.set(data.name, collection, {
-          silent: true,
-        });
-      }
-
-      let cellEditing = function(args) {
-        let ctx = this,
-          cell = args[0];
-        // Search for any other rows which are open.
-        this.each(function(m) {
-          // Check if row which we are about to close is not current row.
-          if (cell.model != m) {
-            let idx = ctx.indexOf(m);
-            if (idx > -1) {
-              let row = grid.body.rows[idx],
-                rowEditCell = row.$el.find('.subnode-edit-in-process').parent();
-              // Only close row if it's open.
-              if (rowEditCell.length > 0) {
-                let event = new Event('click');
-                rowEditCell[0].dispatchEvent(event);
-              }
-            }
-          }
-        });
-      };
-      // Listen for any row which is about to enter in edit mode.
-      collection.on('enteringEditMode', cellEditing, collection);
-
-      // Initialize a new Grid instance
-      let grid = self.grid = new Backgrid.Grid({
-        columns: gridSchema.columns,
-        collection: collection,
-        row: this.row,
-        className: 'backgrid table presentation table-bordered table-noouter-border table-hover',
-      });
-
-      // Render subNode grid
-      let subNodeGrid = grid.render().$el;
-
-      // Combine Edit and Delete Cell
-      if (data.canDelete && data.canEdit) {
-        $(subNodeGrid).find('th.pg-backform-delete').remove();
-        $(subNodeGrid).find('th.pg-backform-edit').attr('colspan', '2');
-      }
-
-      let $dialog = gridBody.append(subNodeGrid);
-
-      let tmp_browser = pgBrowser;
-      if (pgBrowser.preferences_cache.length == 0)
-        tmp_browser = pgWindow.default.pgAdmin.Browser;
-
-      let preferences = tmp_browser.get_preferences_for_module('browser');
-
-      if (preferences) {
-        let addBtn = $dialog.find('.add');
-        // Add title to the buttons
-        $(addBtn)
-          .attr('title',
-            keyboardShortcuts.shortcut_title(gettext('Add new row'),preferences.add_grid_row));
-      }
-
-
-      // Add button callback
-      $dialog.find('button.add').on('click',(e) => {
-        e.preventDefault();
-        let canAddRow = _.isFunction(data.canAddRow) ?
-          data.canAddRow.apply(self, [self.model]) : true;
-        if (canAddRow) {
-          // Close any existing expanded row before adding new one.
-          _.each(grid.body.rows, function(row) {
-            let rowEditCell = row.$el.find('.subnode-edit-in-process').parent();
-            // Only close row if it's open.
-            if (rowEditCell.length > 0) {
-              let event = new Event('click');
-              rowEditCell[0].dispatchEvent(event);
-            }
-          });
-
-          grid.insertRow({});
-
-          let newRow = $(grid.body.rows[collection.length - 1].$el);
-          newRow.attr('class', 'new').on('click',() => {
-            $(this).attr('class', 'editable');
-          });
-
-          if(!$(newRow).pgMakeBackgridVisible('.backform-tab')){
-            // We can have subnode controls in Panels
-            $(newRow).pgMakeBackgridVisible('.set-group');
-          }
-          return false;
-        }
-      });
-
-      return $dialog;
-    },
-  });
-
-  /*
-   * SQL Tab Control for showing the modified SQL for the node with the
-   * property 'hasSQL' is set to true.
-   *
-   * When the user clicks on the SQL tab, we will send the modified data to the
-   * server and fetch the SQL for it.
-   */
-  Backform.SqlTabControl = Backform.Control.extend({
-    defaults: {
-      label: '',
-      controlsClassName: 'pgadmin-controls pg-el-sm-12 SQL',
-      extraClasses: [],
-      helpMessage: null,
-    },
-    template: _.template([
-      '<label for="<%=cId%>" class="sr-only"><%=(label==""?"SQL":label)%></label>',
-      '<div class="<%=controlsClassName%>">',
-      '  <textarea id="<%=cId%>" class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>" name="<%=name%>" aria-label="<%=name%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly aria-readonly=true" : ""%> <%=required ? "required" : ""%>><%-value%></textarea>',
-      '  <% if (helpMessage && helpMessage.length) { %>',
-      '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '  <% } %>',
-      '</div>',
-    ].join('\n')),
-    /*
-     * Initialize the SQL Tab control properly
-     */
-    initialize: function(o) {
-      Backform.Control.prototype.initialize.apply(this, arguments);
-
-      // Save the required information for using it later.
-      this.dialog = o.dialog;
-      this.tabIndex = o.tabIndex;
-
-      _.bindAll(this, 'onTabChange', 'onPanelResized');
-    },
-    getValueFromDOM: function() {
-      return this.formatter.toRaw(this.$el.find('textarea').val(), this.model);
-    },
-
-    reflectPreferences: function() {
-      let self = this;
-      /* self.sqlCtrl is null when SQL tab is not active */
-      if(self.sqlCtrl) {
-        let sqlEditPreferences = pgAdmin.Browser.get_preferences_for_module('sqleditor');
-
-        $(self.sqlCtrl.getWrapperElement()).css(
-          'font-size', calcFontSize(sqlEditPreferences.sql_font_size)
-        );
-        self.sqlCtrl.setOption('tabSize', sqlEditPreferences.tab_size);
-        self.sqlCtrl.setOption('lineWrapping', sqlEditPreferences.wrap_code);
-        self.sqlCtrl.setOption('autoCloseBrackets', sqlEditPreferences.insert_pair_brackets);
-        self.sqlCtrl.setOption('matchBrackets', sqlEditPreferences.brace_matching);
-        self.sqlCtrl.refresh();
-      }
-    },
-    render: function() {
-      if (this.sqlCtrl) {
-        this.sqlCtrl.toTextArea();
-        delete this.sqlCtrl;
-        this.sqlCtrl = null;
-        this.$el.empty();
-        this.model.off('pg-property-tab-changed', this.onTabChange, this);
-        this.model.off('pg-browser-resized', this.onPanelResized, this);
-      }
-      // Use the Backform Control's render function
-      Backform.Control.prototype.render.apply(this, arguments);
-
-      this.sqlCtrl = CodeMirror.fromTextArea(
-        (this.$el.find('textarea')[0]), {
-          lineNumbers: true,
-          mode: 'text/x-pgsql',
-          readOnly: true,
-          extraKeys: pgAdmin.Browser.editor_shortcut_keys,
-          screenReaderLabel: 'SQL',
-        });
-
-      this.reflectPreferences();
-
-      /* Check for sql editor preference changes */
-      let self = this;
-      this.$el.find('textarea').attr('tabindex', -1);
-      pgBrowser.onPreferencesChange('sqleditor', function() {
-        self.reflectPreferences();
-      });
-
-      /*
-       * We will listen to the tab change event to check, if the SQL tab has
-       * been clicked or, not.
-       */
-      this.model.on('pg-property-tab-changed', this.onTabChange, this);
-      this.model.on('pg-browser-resized', this.onPanelResized, this);
-
-      return this;
-    },
-    onTabChange: function(obj) {
-
-      // Fetch the information only if the SQL tab is visible at the moment.
-      if (this.dialog && obj.shown == this.tabIndex) {
-
-        // We will send a request to the sever only if something has changed
-        // in a model and also it does not contain any error.
-        if (this.model.sessChanged()) {
-          if (_.size(this.model.errorModel.attributes) == 0) {
-            let self = this,
-              node = self.field.get('schema_node'),
-              msql_url = node.generate_url.apply(
-                node, [
-                  null, 'msql', this.field.get('node_data'), !self.model.isNew(),
-                  this.field.get('node_info'), node.url_jump_after_node,
-                ]);
-
-            // Fetching the modified SQL
-            self.model.trigger('pgadmin-view:msql:fetching', self.method, node);
-
-            $.ajax({
-              url: msql_url,
-              type: 'GET',
-              cache: false,
-              data: self.model.toJSON(true, 'GET'),
-              dataType: 'json',
-              contentType: 'application/json',
-            }).done(function(res) {
-              self.sqlCtrl.clearHistory();
-              self.sqlCtrl.setValue(res.data);
-            }).fail(function() {
-              self.model.trigger('pgadmin-view:msql:error', self.method, node, arguments);
-            }).always(function() {
-              self.model.trigger('pgadmin-view:msql:fetched', self.method, node, arguments);
-            });
-          } else {
-            this.sqlCtrl.clearHistory();
-            this.sqlCtrl.setValue('-- ' + gettext('Definition incomplete.'));
-          }
-        } else {
-          this.sqlCtrl.clearHistory();
-          this.sqlCtrl.setValue('-- ' + gettext('No updates.'));
-        }
-        this.sqlCtrl.refresh.apply(this.sqlCtrl);
-      }
-    },
-    onPanelResized: function(o) {
-      if (o && o.container) {
-        let $tabContent = o.container.find(
-            '.backform-tab > .tab-content'
-          ).first(),
-          $sqlPane = $tabContent.find(
-            'div[role=tabpanel].tab-pane.SQL'
-          );
-        if ($sqlPane.hasClass('active')) {
-          $sqlPane.find('.CodeMirror').css(
-            'cssText',
-            'height: ' + ($tabContent.height() + 8) + 'px !important;'
-          );
-        }
-      }
-    },
-    remove: function() {
-      if (this.sqlCtrl) {
-        this.sqlCtrl.toTextArea();
-        delete this.sqlCtrl;
-        this.sqlCtrl = null;
-
-        this.$el.empty();
-      }
-      this.model.off('pg-property-tab-changed', this.onTabChange, this);
-      this.model.off('pg-browser-resized', this.onPanelResized, this);
-
-      Backform.Control.__super__.remove.apply(this, arguments);
-    },
-  });
-  /*
-   * Numeric input Control functionality just like backgrid
-   */
-  Backform.NumericControl = Backform.InputControl.extend({
-    defaults: {
-      type: 'number',
-      label: '',
-      min: undefined,
-      max: undefined,
-      maxlength: 255,
-      extraClasses: [],
-      helpMessage: null,
-    },
-    template: _.template([
-      '<label for="<%=cId%>" class="<%=Backform.controlLabelClassName%> text-wrap"><%=label%></label>',
-      '<div class="<%=Backform.controlsClassName%>">',
-      '  <input type="<%=type%>" id="<%=cId%>" class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>" name="<%=name%>" min="<%=min%>" max="<%=max%>"maxlength="<%=maxlength%>" value="<%-value%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly aria-readonly=true" : ""%> <%=required ? "required" : ""%> />',
-      '  <% if (helpMessage && helpMessage.length) { %>',
-      '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '  <% } %>',
-      '</div>',
-    ].join('\n')),
-  });
-
-  ///////
-  // Generate a schema (as group members) based on the model's schema
-  //
-  // It will be used by the grid, properties, and dialog view generation
-  // functions.
-  Backform.generateViewSchema = function(
-    node_info, Model, mode, node, treeData, noSQL, subschema
-  ) {
-    let proto = (Model && Model.prototype) || Model,
-      schema = subschema || (proto && proto.schema),
-      fields = [],
-      groupInfo = {};
-
-    // 'schema' has the information about how to generate the form.
-    if (schema && _.isArray(schema)) {
-      let evalASFunc = evalASFunc = function(prop) {
-        return ((prop && proto[prop] &&
-          typeof proto[prop] == 'function') ? proto[prop] : prop);
-      };
-      let groups = {},
-        server_info = node_info && ('server' in node_info) &&
-        pgBrowser.serverInfo && pgBrowser.serverInfo[node_info.server._id],
-        in_catalog = node_info && ('catalog' in node_info),
-        ver_in_limit;
-
-      _.each(schema, function(s) {
-        // Do we understand - what control, we're creating
-        // here?
-        if (s.type == 'group') {
-          let visible = true;
-          if (_.isUndefined(server_info)) {
-            ver_in_limit = true;
-          } else {
-            ver_in_limit = ((_.isUndefined(s.server_type) ? true :
-              (server_info.type in s.server_type)) &&
-              (_.isUndefined(s.min_version) ? true :
-                (server_info.version >= s.min_version)) &&
-              (_.isUndefined(s.max_version) ? true :
-                (server_info.version <= s.max_version)));
-          }
-
-          if (s.mode && _.isObject(s.mode))
-            visible = (_.indexOf(s.mode, mode) > -1);
-          if (visible)
-            visible = evalASFunc(s.visible);
-
-          groupInfo[s.id] = {
-            label: s.label || s.id,
-            version_compatible: ver_in_limit,
-            visible: visible,
-            tabPanelCodeClass: '',
-          };
-          return;
-        }
-
-        if (!s.mode || (s && s.mode && _.isObject(s.mode) &&
-            _.indexOf(s.mode, mode) != -1)) {
-          // Each field is kept in specified group, or in
-          // 'General' category.
-          let group = s.group || gettext('General'),
-            control = s.control || Backform.getMappedControl(s.type, mode),
-            cell = s.cell || Backform.getMappedControl(s.type, 'cell');
-
-          if (control == null) {
-            return;
-          }
-
-          // Generate the empty group list (if not exists)
-          groups[group] = (groups[group] || []);
-          if (_.isUndefined(server_info)) {
-            ver_in_limit = true;
-          } else {
-            ver_in_limit = ((_.isUndefined(s.server_type) ? true :
-              (server_info.type in s.server_type)) &&
-              (_.isUndefined(s.min_version) ? true :
-                (server_info.version >= s.min_version)) &&
-              (_.isUndefined(s.max_version) ? true :
-                (server_info.version <= s.max_version)));
-          }
-
-          let disabled = (
-              !ver_in_limit || in_catalog
-            ),
-            readonly = (mode == 'properties'),
-            schema_node = (s.node && _.isString(s.node) &&
-              s.node in pgBrowser.Nodes && pgBrowser.Nodes[s.node]) || node;
-
-          let o = _.extend(_.clone(s), {
-            name: s.id,
-            // This can be disabled in some cases (if not hidden)
-
-            disabled: (disabled ? true : evalASFunc(s.disabled)),
-            readonly: (readonly ? true : evalASFunc(s.readonly)),
-            editable: _.isUndefined(s.editable) ?
-              pgAdmin.editableCell : evalASFunc(s.editable),
-            subnode: ((_.isString(s.model) && s.model in pgBrowser.Nodes) ?
-              pgBrowser.Nodes[s.model].model : s.model),
-            canAdd: (disabled || readonly) ? false : evalASFunc(s.canAdd),
-            canAddRow: (disabled || readonly) ? false : evalASFunc(s.canAddRow),
-            canEdit: (disabled || readonly) ? false : evalASFunc(s.canEdit),
-            canDelete: (disabled || readonly) ? false : evalASFunc(s.canDelete),
-            canEditRow: (disabled || readonly) ? false : evalASFunc(s.canEditRow),
-            canDeleteRow: (disabled || readonly) ? false : evalASFunc(s.canDeleteRow),
-            transform: evalASFunc(s.transform),
-            mode: mode,
-            control: control,
-            cell: cell,
-            node_info: node_info,
-            schema_node: schema_node,
-            // Do we need to show this control in this mode?
-            visible: evalASFunc(s.visible),
-            node: node,
-            node_data: treeData,
-            version_compatible: ver_in_limit,
-          });
-          delete o.id;
-
-          // Temporarily store in dictionary format for
-          // utilizing it later.
-          groups[group].push(o);
-
-          if (s.type == 'nested') {
-            delete o.name;
-            delete o.cell;
-
-            o.schema = Backform.generateViewSchema(
-              node_info, Model, mode, node, treeData, true, s.schema
-            );
-            o.control = o.control || 'tab';
-          }
-        }
-      });
-
-      // Do we have fields to genreate controls, which we
-      // understand?
-      if (_.isEmpty(groups)) {
-        return null;
-      }
-
-      if (!noSQL && node && node.hasSQL && (mode == 'create' || mode == 'edit')) {
-        groups[gettext('SQL')] = [{
-          name: 'sql',
-          visible: true,
-          disabled: false,
-          type: 'text',
-          control: 'sql-tab',
-          node_info: node_info,
-          schema_node: node,
-          node_data: treeData,
-        }];
-      }
-
-      // Create an array from the dictionary with proper required
-      // structure.
-      _.each(groups, function(val, key) {
-        let tabPanelCodeClass = _.pluck(val, 'tabPanelCodeClass');
-        if (tabPanelCodeClass) {
-          tabPanelCodeClass = tabPanelCodeClass.join(' ').trim();
-        }
-        fields.push(
-          _.extend(
-            _.defaults(
-              groupInfo[key] || {
-                label: key,
-                tabPanelCodeClass: tabPanelCodeClass,
-              }, {
-                version_compatible: true,
-                visible: true,
-              }
-            ), {
-              fields: val,
-            })
-        );
-      });
-    }
-
-    return fields;
-  };
-
-  let Select2Formatter = function() {/*This is intentional (SonarQube)*/};
-  _.extend(Select2Formatter.prototype, {
-    fromRaw: function(rawData) {
-      return encodeURIComponent(rawData);
-    },
-    toRaw: function(formattedData, model, opts) {
-      if (_.isArray(formattedData)) {
-        if (opts && opts.tags)
-          return formattedData;
-        return _.map(formattedData, decodeURIComponent);
-      } else {
-        if (!_.isNull(formattedData) && !_.isUndefined(formattedData)) {
-          return decodeURIComponent(formattedData);
-        } else {
-          return null;
-        }
-      }
-    },
-  });
-
-  /*
-   *  Backform Select2 control.
-   */
-  Backform.Select2Control = Backform.SelectControl.extend({
-    defaults: _.extend({}, Backform.SelectControl.prototype.defaults, {
-      select2: {
-        first_empty: true,
-        multiple: false,
-        emptyOptions: false,
-        preserveSelectionOrder: false,
-        isDropdownParent: false,
-      },
-      // To accept the label and conrol classes while extending control if
-      // required(e.g. if we want to show label and control in 50-50% or in
-      //different width of dialog/form) otherwise default classes will be added
-      controlLabelClassName: Backform.controlLabelClassName,
-      controlsClassName: Backform.controlsClassName,
-    }),
-
-    events: function() {
-      // Inherit all default events of InputControl
-      return _.extend({}, Backform.SelectControl.prototype.events, {
-        'select2:select': 'onSelect',
-      });
-    },
-
-    onSelect: function (evt) {
-      let sel2Options = this.field.get('select2');
-      if (!_.isUndefined(sel2Options) && !_.isNull(sel2Options) &&
-          sel2Options.multiple && sel2Options.preserveSelectionOrder) {
-        let element = evt.params.data.element;
-        let $element = $(element);
-
-        $element.detach();
-        $(this.$sel).append($element);
-        $(this.$sel).trigger('change');
-      }
-
-      let new_value = _.findWhere(this.field.get('options'), {value: evt.params.data.id});
-      if(new_value && !_.isUndefined(new_value.preview_src) && new_value.preview_src) {
-        this.$el.find('.preview-img img').attr('src', new_value.preview_src);
-      }
-    },
-
-    formatter: Select2Formatter,
-    template: _.template([
-      '<% if(label == false) {} else {%>',
-      '  <label class="<%=controlLabelClassName%>" for="<%=cId%>"><%=label%></label>',
-      '<% }%>',
-      '<div class="<%=controlsClassName%>">',
-      ' <select title="<%=name%>" id="<%=cId%>" class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>"',
-      '  name="<%=name%>" value="<%-value%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "disabled" : ""%>',
-      '  <%=required ? "required" : ""%><%= select2.multiple ? " multiple>" : ">" %>',
-      '  <%=select2.first_empty ? " <option></option>" : ""%>',
-      '  <% for (let i=0; i < options.length; i++) {%>',
-      '   <% let option = options[i]; %>',
-      '   <option ',
-      '    <% if (option.image) { %> data-image=<%=option.image%> <%}%>',
-      '    value=<%- formatter.fromRaw(option.value) %>',
-      '    <% if (option.selected) {%>selected="selected"<%} else {%>',
-      '    <% if (!select2.multiple && option.value === rawValue) {%>selected="selected"<%}%>',
-      '    <% if (select2.multiple && rawValue && rawValue.indexOf(option.value) != -1){%>selected="selected" data-index="rawValue.indexOf(option.value)"<%}%>',
-      '    <%}%>',
-      '    <%= disabled ? "disabled" : ""%> <%=readonly ? "disabled" : ""%>><%-option.label%></option>',
-      '  <%}%>',
-      ' </select>',
-      ' <% if (helpMessage && helpMessage.length) { %>',
-      ' <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      ' <% } %>',
-      ' <% for (let i=0; i < options.length; i++) {%>',
-      '   <% let option = options[i]; %>',
-      '     <% if (option.preview_src && option.value === rawValue) { %>',
-      '       <div class="preview-img mt-2">',
-      '         <img src="<%=option.preview_src%>" class="img-fluid mx-auto d-block w-50 border" alt="'+gettext('Preview not available...')+'">',
-      '       </div>',
-      '    <%}%>',
-      ' <%}%>',
-      '</div>',
-    ].join('\n')),
-    render: function() {
-      if (this.$sel && this.$sel.select2 &&
-        this.$sel.select2.hasOwnProperty('destroy')) {
-        this.$sel.select2('destroy');
-      }
-
-      let field = _.defaults(this.field.toJSON(), this.defaults),
-        attributes = this.model.toJSON(),
-        attrArr = field.name.split('.'),
-        name = attrArr.shift(),
-        path = attrArr.join('.'),
-        rawValue = this.keyPathAccessor(attributes[name], path),
-        data = _.extend(field, {
-          rawValue: rawValue,
-          value: this.formatter.fromRaw(rawValue, this.model),
-          attributes: attributes,
-          formatter: this.formatter,
-        }),
-        evalF = function(f, d, m) {
-          return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f);
-        };
-
-      data.select2 = data.select2 || {};
-      _.defaults(data.select2, this.defaults.select2, {
-        first_empty: true,
-        multiple: false,
-        emptyOptions: false,
-        preserveSelectionOrder: false,
-        isDropdownParent: false,
-        showOnScroll: true,
-      });
-
-      // Evaluate the disabled, visible, and required option
-      // disable for readonly also and later handle readonly programmatically.
-      _.extend(data, {
-        disabled: evalF(data.disabled, data, this.model),
-        readonly: evalF(data.readonly, data, this.model),
-        visible: evalF(data.visible, data, this.model),
-        required: evalF(data.required, data, this.model),
-      });
-
-      // Evaluation the options
-      if (_.isFunction(data.options)) {
-        try {
-          data.options = data.options(this);
-        } catch (e) {
-          // Do nothing
-          data.options = [];
-          this.model.trigger(
-            'pgadmin-view:transform:error', this.model, this.field, e
-          );
-        }
-      }
-
-      data.cId = data.cId || _.uniqueId('pgC_');
-      // Clean up first
-      this.$el.removeClass(Backform.hiddenClassName);
-
-      if (!data.visible)
-        this.$el.addClass(Backform.hiddenClassName);
-
-      this.$el.html(this.template(data)).addClass(field.name);
-
-      let select2Opts = _.extend({
-        disabled: data.disabled || data.readonly,
-      }, field.select2, {
-        options: (this.field.get('options') || this.defaults.options),
-      });
-
-      // Dropdown body can be render at user given location
-      // If isDropdownParent flag is set to true then, By default we will
-      // display it on the control itself.
-      if (data.select2.isDropdownParent) {
-        select2Opts.dropdownParent = data.select2.dropdownParent || this.$el;
-      }
-
-      // If disabled then no need to show placeholder
-      if (data.disabled || data.readonly) {
-        select2Opts['placeholder'] = '';
-      }
-
-      /*
-       * Add empty option as Select2 requires any empty '<option><option>' for
-       * some of its functionality to work and initialize select2 control.
-       */
-
-      if (data.select2.tags && data.select2.emptyOptions) {
-        select2Opts.data = data.rawValue;
-      }
-
-      /* Configure show on scroll if required */
-      select2Opts = configure_show_on_scroll.default(select2Opts);
-
-      this.$sel = this.$el.find('select').select2(select2Opts);
-
-      // Add or remove tags from select2 control
-      if (data.select2.tags && data.select2.emptyOptions) {
-        this.$sel.val(data.rawValue);
-        this.$sel.trigger('change.select2');
-        this.$sel.on('select2:unselect', function(evt) {
-
-          $(this).find('option[value="' + evt.params.data.text.replace('\'', '\\\'').replace('"', '\\"') + '"]').remove();
-          $(this).trigger('change.select2');
-          if ($(this).val() == null) {
-            $(this).empty();
-          }
-        });
-      }
-
-      // Select the highlighted item on Tab press.
-      if (this.$sel) {
-        this.$sel.data('select2').on('keypress', function(ev) {
-          let self = this;
-
-          // keycode 9 is for TAB key
-          if (ev.which === 9 && self.isOpen()) {
-            ev.preventDefault();
-            self.trigger('results:select', {});
-          }
-        });
-      }
-
-      /* Select2 does not have option for readonly
-       * If readonly, then let it focus.
-       */
-      if(data.readonly && !data.disabled) {
-        setTimeout(()=>{
-          this.$el.find('.select2-selection').attr('tabindex', 0);
-        }, 500);
-      }
-
-      this.updateInvalid();
-
-      return this;
-    },
-    getValueFromDOM: function() {
-      let select2Opts = _.extend({}, this.field.get('select2') || this.defaults.select2),
-        val = this.formatter.toRaw(this.$sel.val(), this.model, select2Opts);
-
-      if (select2Opts.multiple && val == null) {
-        return [];
-      }
-      return val;
-    },
-  });
-
-  Backform.FieldsetControl = Backform.Fieldset.extend({
-    initialize: function(opts) {
-      Backform.Control.prototype.initialize.apply(
-        this, arguments
-      );
-      Backform.Dialog.prototype.initialize.apply(
-        this, [{
-          schema: opts.field.get('schema'),
-        }]
-      );
-      this.dialog = opts.dialog;
-      this.tabIndex = opts.tabIndex;
-      this.contentClass = opts.field.get('contentClass')?opts.field.get('contentClass'):'';
-
-      // Listen to the dependent fields in the model for any change
-      let deps = this.field.get('deps');
-      let self = this;
-
-      if (deps && _.isArray(deps)) {
-        _.each(deps, function(d) {
-          let attrArr = d.split('.'),
-            name = attrArr.shift();
-          self.listenTo(self.model, 'change:' + name, self.render);
-        });
-      }
-    },
-    // Render using Backform.Fieldset (only if this control is visible)
-    orig_render: Backform.Fieldset.prototype.render,
-    render: function() {
-      let field = _.defaults(this.field.toJSON(), this.defaults),
-        evalF = function(f, d, m) {
-          return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f);
-        };
-
-      if (!field.version_compatible ||
-        !evalF(field.visible, field, this.model)) {
-        this.cleanup();
-        this.$el.empty();
-      } else {
-        this.orig_render.apply(this, arguments);
-      }
-      return this;
-    },
-    formatter: function() {/*This is intentional (SonarQube)*/},
-    cleanup: function() {
-      Backform.Fieldset.prototype.cleanup.apply(this);
-    },
-    remove: function() {
-      Backform.Control.prototype.remove.apply(this, arguments);
-      Backform.Dialog.prototype.remove.apply(this, arguments);
-    },
-    className: function() {
-      return 'set-group';
-    },
-    tabPanelClassName: function() {
-      return Backform.tabClassName;
-    },
-    fieldsetClass: 'inline-fieldset',
-    legendClass: '',
-    collapse: false,
-  });
-
-  // Backform Tab Control (in bootstrap tabbular)
-  // A collection of field models.
-  Backform.TabControl = Backform.FieldsetControl.extend({
-    tagName: 'div',
-    className: 'inline-tab-panel',
-    tabPanelClassName: 'inline-tab-panel',
-    tabPanelExtraClasses: '',
-    initialize: function(opts) {
-      Backform.FieldsetControl.prototype.initialize.apply(
-        this, arguments
-      );
-      this.tabIndex = (opts.tabIndex || parseInt(crypto.getRandomValues(new Uint8Array(1)))) + 1;
-      if(opts.field.get('tabPanelExtraClasses')) {
-        this.tabPanelExtraClasses = opts.field.get('tabPanelExtraClasses');
-      }
-      this.tabPanelClassName = this.tabPanelClassName + ' ' + this.tabPanelExtraClasses;
-    },
-    // Render using Backform.Dialog (tabular UI) (only if this control is
-    // visible).
-    orig_render: Backform.Dialog.prototype.render,
-    template: Backform.Dialog.prototype.template,
-  });
-
-  // Backform Tab Control (in bootstrap tabbular)
-  // A collection of field models.
-  Backform.PlainFieldsetControl = Backform.FieldsetControl.extend({
-    initialize: function() {
-      Backform.FieldsetControl.prototype.initialize.apply(this, arguments);
-    },
-    template: {
-      'header': _.template([
-        '<fieldset class="<%=fieldsetClass%>" <%=disabled ? "disabled" : ""%>>',
-        ' <% if (legend != false) { %>',
-        '  <div><legend class="<%=legendClass%>" <%=collapse ? "data-toggle=\'collapse\'" : ""%> data-target="#<%=cId%>"><%=collapse ? "<span class=\'caret\'></span>" : "" %></legend></div>',
-        ' <% } %>',
-        '</fieldset>',
-      ].join('\n')),
-      'content': _.template(
-        '  <div id="<%= cId %>" class="<%=contentClass%>"></div>'
-      ),
-    },
-    fieldsetClass: 'inline-fieldset-without-border',
-    legend: false,
-  });
-
-  /*
-   * Control For Code Mirror SQL text area.
-   */
-  Backform.SqlFieldControl = Backform.TextareaControl.extend({
-
-    defaults: {
-      label: '',
-      extraClasses: [], // Add default control height
-      helpMessage: null,
-      maxlength: 4096,
-      rows: undefined,
-    },
-
-    // Customize template to add new styles
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>" for="<%=cId%>"><%=label%></label>',
-      '<div class="<%=Backform.controlsClassName%> sql_field_layout <%=extraClasses.join(\' \')%>">',
-      '  <textarea id="<%=cId%>"',
-      '    class="<%=Backform.controlClassName%> " name="<%=name%>" aria-label="<%=name%>"',
-      '    maxlength="<%=maxlength%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly aria-readonly=true" : ""%>',
-      '    rows=<%=rows%>',
-      '    <%=required ? "required" : ""%>><%-value%></textarea>',
-      '  <% if (helpMessage && helpMessage.length) { %>',
-      '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '  <% } %>',
-      '</div>',
-    ].join('\n')),
-
-    /*
-     * Initialize the SQL Field control properly
-     */
-    initialize: function() {
-      Backform.TextareaControl.prototype.initialize.apply(this, arguments);
-      this.sqlCtrl = null;
-
-      _.bindAll(this, 'onFocus', 'onBlur', 'refreshTextArea');
-    },
-
-    getValueFromDOM: function() {
-      return this.sqlCtrl.getValue();
-    },
-
-    reflectPreferences: function() {
-      let self = this;
-      /* self.sqlCtrl is null when Definition tab is not active */
-      if(self.sqlCtrl) {
-
-        /* This control is used by filter dialog in query editor, so taking preferences from window
-         * SQL Editor can be in different tab
-         */
-        let browser = pgWindow.default.pgAdmin.Browser;
-
-        let sqlEditPreferences = browser.get_preferences_for_module('sqleditor');
-
-        $(self.sqlCtrl.getWrapperElement()).css(
-          'font-size', calcFontSize(sqlEditPreferences.sql_font_size)
-        );
-        self.sqlCtrl.setOption('indentWithTabs', !sqlEditPreferences.use_spaces);
-        self.sqlCtrl.setOption('indentUnit', sqlEditPreferences.tab_size);
-        self.sqlCtrl.setOption('tabSize', sqlEditPreferences.tab_size);
-        self.sqlCtrl.setOption('lineWrapping', sqlEditPreferences.wrap_code);
-        self.sqlCtrl.setOption('autoCloseBrackets', sqlEditPreferences.insert_pair_brackets);
-        self.sqlCtrl.setOption('matchBrackets', sqlEditPreferences.brace_matching);
-        setTimeout(function() {
-          if (self.sqlCtrl) self.sqlCtrl.refresh();
-        }, 500);
-      }
-    },
-
-    render: function() {
-      // Clean up the existing sql control
-      if (this.sqlCtrl) {
-        this.model.off('pg-property-tab-changed', this.refreshTextArea, this);
-        this.sqlCtrl.off('focus', this.onFocus);
-        this.sqlCtrl.off('blur', this.onBlur);
-
-        this.sqlCtrl.toTextArea();
-        delete this.sqlCtrl;
-        this.sqlCtrl = null;
-        this.$el.empty();
-      }
-
-      // Use the Backform TextareaControl's render function
-      Backform.TextareaControl.prototype.render.apply(this, arguments);
-
-      let field = _.defaults(this.field.toJSON(), this.defaults),
-        attributes = this.model.toJSON(),
-        attrArr = field.name.split('.'),
-        name = attrArr.shift(),
-        path = attrArr.join('.'),
-        rawValue = this.keyPathAccessor(attributes[name], path),
-        data = _.extend(field, {
-          rawValue: rawValue,
-          value: this.formatter.fromRaw(rawValue, this.model),
-          attributes: attributes,
-          formatter: this.formatter,
-        }),
-        evalF = function(f, d, m) {
-          return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f);
-        };
-
-      data.cId = data.cId || _.uniqueId('pgC_');
-      // Evaluate the disabled, visible option
-      let isDisabled = evalF(data.disabled, data, this.model),
-        isVisible = evalF(data.visible, data, this.model),
-        isReadonly = evalF(data.readonly, data, this.model),
-        self = this;
-
-      self.sqlCtrl = CodeMirror.fromTextArea(
-        (self.$el.find('textarea')[0]), {
-          lineNumbers: true,
-          mode: 'text/x-pgsql',
-          extraKeys: pgAdmin.Browser.editor_shortcut_keys,
-          screenReaderLabel: data.label,
-        });
-
-      self.reflectPreferences();
-      /* Check for sql editor preference changes */
-      pgBrowser.onPreferencesChange('sqleditor', function() {
-        self.reflectPreferences();
-      });
-
-      // Disable editor
-      if (isDisabled || isReadonly) {
-        // set read only mode to true instead of 'nocursor', and hide cursor using a class so that copying is enabled
-        self.sqlCtrl.setOption('readOnly', true);
-        self.sqlCtrl.setOption('extraKeys', {
-          Tab: false,
-          'Shift-Tab': false,
-        });
-        let cm = self.sqlCtrl.getWrapperElement();
-        if (cm) {
-          cm.className += ' cm_disabled hide-cursor-workaround';
-        }
-      }
-
-      if (!isVisible)
-        self.$el.addClass(Backform.hiddenClassName);
-
-      // There is an issue with the Code Mirror SQL.
-      //
-      // It does not initialize the code mirror object completely when the
-      // referenced textarea is hidden (not visible), hence - we need to
-      // refresh the code mirror object on 'pg-property-tab-changed' event to
-      // make it work properly.
-      self.model.on('pg-property-tab-changed', this.refreshTextArea, this);
-      this.sqlCtrl.setOption('dragDrop', true);
-      this.sqlCtrl.on('focus', this.onFocus);
-      this.sqlCtrl.on('blur', this.onBlur);
-      this.sqlCtrl.on('drop', this.onDrop);
-      // Refresh SQL Field to refresh the control lazily after it renders
-      setTimeout(function() {
-        self.refreshTextArea.apply(self);
-      }, 0);
-
-      return self;
-    },
-
-    onDrop: function(editor, e){
-      let dropDetails = null;
-      try {
-        dropDetails = JSON.parse(e.dataTransfer.getData('text'));
-
-        /* Stop firefox from redirecting */
-
-        if(e.preventDefault) {
-          e.preventDefault();
-        }
-        if (e.stopPropagation) {
-          e.stopPropagation();
-        }
-      } catch(error) {
-        /* if parsing fails, it must be the drag internal of codemirror text */
-        return;
-      }
-
-      let cursor = editor.coordsChar({
-        left: e.x,
-        top: e.y,
-      });
-      editor.replaceRange(dropDetails.text, cursor);
-      editor.focus();
-      editor.setSelection({
-        ...cursor,
-        ch: cursor.ch + dropDetails.cur.from,
-      },{
-        ...cursor,
-        ch: cursor.ch +dropDetails.cur.to,
-      });
-    },
-
-    onFocus: function() {
-      let $ctrl = this.$el.find('.pgadmin-controls').first();
-      if (!$ctrl.hasClass('focused'))
-        $ctrl.addClass('focused');
-    },
-
-    onBlur: function() {
-      this.$el.find('.pgadmin-controls').first().removeClass('focused');
-    },
-
-    refreshTextArea: function() {
-      if (this.sqlCtrl) {
-        this.sqlCtrl.refresh();
-      }
-    },
-
-    remove: function() {
-      // Clean up the sql control
-      if (this.sqlCtrl) {
-        this.sqlCtrl.off('focus', this.onFocus);
-        this.sqlCtrl.off('blur', this.onBlur);
-        delete this.sqlCtrl;
-        this.sqlCtrl = null;
-        this.$el.empty();
-      }
-
-      this.model.off('pg-property-tab-changed', this.refreshTextArea, this);
-
-      Backform.TextareaControl.prototype.remove.apply(this, arguments);
-    },
-  });
-
-  /*
-   * Control For Code Mirror with FULL text area.
-   */
-  Backform.SqlCodeControl = Backform.SqlFieldControl.extend({
-    // Customize template to add new styles
-    template: _.template([
-      '<label class="sr-only" for="<%=cId%>"><%=(label==""?"Code":label)%></label>',
-      '<div class="pgadmin-controls pg-el-12 <%=extraClasses.join(\' \')%>">',
-      '  <textarea id="<%=cId%>" ',
-      '    class="<%=Backform.controlClassName%> " name="<%=name%>" aria-label="<%=name%>"',
-      '    maxlength="<%=maxlength%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly aria-readonly=true" : ""%> ',
-      '    rows=<%=rows%>',
-      '    <%=required ? "required" : ""%>><%-value%></textarea>',
-      '  <% if (helpMessage && helpMessage.length) { %>',
-      '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '  <% } %>',
-      '</div>',
-    ].join('\n')),
-  });
-
-  // We will use this control just as a annotate in Backform
-  Backform.NoteControl = Backform.Control.extend({
-    defaults: {
-      label: gettext('Note'),
-      text: '',
-      extraClasses: ['pg-el-12', 'd-flex'],
-      noteClass: 'backform-note',
-      faIcon: 'fa-file-alt',
-      faExtraClass: 'fa-rotate-180 fa-flip-vertical',
-      iconWidthClass: 'col-0 pr-2',
-      textWidthClass: 'col-sm',
-    },
-    template: _.template([
-      '<div class="<%=noteClass%> <%=extraClasses.join(\' \')%>">',
-      '  <div class="icon <%=iconWidthClass%>">',
-      '    <i class="fa <%=faIcon%> <%=faExtraClass%>" aria-hidden="true"></i>',
-      '  </div>',
-      '  <div class="<%=textWidthClass%>">',
-      '    <span><%=text%></span>',
-      '  </div>',
-      '</div>',
-    ].join('\n')),
-  });
-
-  Backform.DatetimepickerControl =
-    Backform.InputControl.extend({
-      defaults: {
-        type: 'text',
-        label: '',
-        options: {
-          format: 'YYYY-MM-DD HH:mm:ss Z',
-          icons: {
-            time: 'fa fa-clock',
-            data: 'fa fa-calendar-alt',
-            today: 'fa fa-calendar-check',
-            clear: 'fa fa-trash-alt',
-          },
-          buttons: {
-            showToday: true,
-          },
-          toolbarPlacement: 'top',
-          widgetPositioning: {
-            horizontal: 'auto',
-            vertical: 'bottom',
-          },
-          keepOpen: false,
-        },
-        placeholder: 'YYYY-MM-DD HH:mm:ss Z',
-        extraClasses: [],
-        helpMessage: null,
-        setMinDate: true,
-      },
-      events: {
-        'blur input': 'onChange',
-        'change input': 'onChange',
-        'changeDate input': 'onChange',
-        'focus input': 'clearInvalid',
-        'focusout input': 'closePicker',
-        'change.datetimepicker': 'onChange',
-        'click .input-group': 'togglePicker',
-        'keydown .datetimepicker-input': 'keyboardEvent',
-      },
-      togglePicker: function() {
-        if (this.has_datepicker) {
-          this.$el.find('input').datetimepicker('toggle');
-        }
-      },
-      closePicker: function() {
-        if (this.has_datepicker) {
-          this.$el.find('input').datetimepicker('hide');
-        }
-      },
-      template: _.template([
-        '<label for="<%=cId%>" class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
-        '<div class="input-group  <%=Backform.controlsClassName%>">',
-        ' <input id="<%=cId%>" type="text" class="<%=Backform.controlClassName%> datetimepicker-input <%=extraClasses.join(\' \')%>" name="<%=name%>" value="<%-value%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly aria-readonly=true" : ""%> <%=required ? "required" : ""%> data-toggle="datetimepicker"/>',
-        ' <div class="input-group-append">',
-        '   <span class="input-group-text fa fa-calendar-alt"></span>',
-        ' </div>',
-        '</div>',
-        '<% if (helpMessage && helpMessage.length) { %>',
-        '<div class="<%=Backform.helpBlockControlClass%>">',
-        ' <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-        '</div>',
-        '<% } %>',
-      ].join('\n')),
-
-      keyboardEvent: function(event) {
-        let stopBubble = false;
-        if (!event.altKey && event.keyCode == 38) {
-          this.up();
-        }
-        if (!event.altKey && event.keyCode == 40) {
-          this.down();
-        }
-        if (event.keyCode == 37) {
-          this.left();
-        }
-        if (event.keyCode == 39) {
-          this.right();
-        }
-        if (event.keyCode == 27){
-          this.$el.find('input').datetimepicker('hide');
-          stopBubble = true;
-        }
-        if (event.keyCode == 13){
-          if ((this.$el.find('.datepicker').is(':visible')) || (this.$el.find('.timepicker').is(':visible'))){
-            this.$el.find('input').datetimepicker('hide');
-          }else{
-            this.$el.find('input').datetimepicker('show');
-          }
-        }
-        if (event.altKey && event.keyCode == 84) {
-          this.timePicker();
-        }
-        if(event.altKey && event.keyCode == 38){
-          this.controlUp();
-        }
-        if(event.altKey && event.keyCode == 40){
-          this.controlDown();
-        }
-
-        if(stopBubble) {
-          event.stopImmediatePropagation();
-        }
-      },
-
-      down: function() {
-        let $el = this.$el.find('.datetimepicker-input');
-        let currdate = $el.data('datetimepicker').date().clone();
-        if (this.$el.find('.datepicker').is(':visible')) {
-          $el.datetimepicker('date', currdate.add(7, 'd'));
-        } else {
-          $el.datetimepicker('date', currdate.subtract(1, 'm'));
-        }
-      },
-
-      up: function() {
-        let $el = this.$el.find('.datetimepicker-input');
-        let currdate = $el.data('datetimepicker').date().clone();
-
-        if (this.$el.find('.datepicker').is(':visible')) {
-          $el.datetimepicker('date', currdate.subtract(7, 'd'));
-        } else {
-          $el.datetimepicker('date', currdate.add(1, 'm'));
-        }
-      },
-
-      left: function() {
-        let $el = this.$el.find('.datetimepicker-input');
-        let currdate = $el.data('datetimepicker').date().clone();
-
-        if (this.$el.find('.datepicker').is(':visible')) {
-          $el.datetimepicker('date', currdate.subtract(1, 'd'));
-        }
-      },
-
-      right: function() {
-        let $el = this.$el.find('.datetimepicker-input');
-        let currdate = $el.data('datetimepicker').date().clone();
-
-        if (this.$el.find('.datepicker').is(':visible')) {
-          $el.datetimepicker('date', currdate.add(1, 'd'));
-        }
-      },
-
-      timePicker:function() {
-        if (this.$el.find('.timepicker').is(':visible')){
-          this.$el.find('.fa-calendar-alt').click();
-        }else{
-          this.$el.find('.fa-clock').click();
-        }
-      },
-
-      controlUp:function() {
-        this.$el.find('.fa-clock').click();
-        let $el = this.$el.find('.datetimepicker-input');
-        let currdate = $el.data('datetimepicker').date().clone();
-        $el.datetimepicker('date', currdate.add(1, 'h'));
-      },
-
-      controlDown:function() {
-        this.$el.find('.fa-clock').click();
-        let $el = this.$el.find('.datetimepicker-input');
-        let currdate = $el.data('datetimepicker').date().clone();
-        $el.datetimepicker('date', currdate.subtract(1, 'h'));
-      },
-
-      render: function() {
-        let field = _.defaults(this.field.toJSON(), this.defaults),
-          attributes = this.model.toJSON(),
-          attrArr = field.name.split('.'),
-          name = attrArr.shift(),
-          path = attrArr.join('.'),
-          rawValue = this.keyPathAccessor(attributes[name], path),
-          data = _.extend(field, {
-            rawValue: rawValue,
-            value: this.formatter.fromRaw(rawValue, this.model),
-            attributes: attributes,
-            formatter: this.formatter,
-          }),
-          evalF = function(f, m) {
-            return (_.isFunction(f) ? !!f(m) : !!f);
-          };
-
-        // disable when mode is properties.
-        if(data.mode == 'properties') {
-          data.disabled = true;
-        }
-
-        // Evaluate the disabled, visible, and required option
-        _.extend(data, {
-          disabled: evalF(data.disabled, this.model),
-          readonly: evalF(data.readonly, this.model),
-          visible: evalF(data.visible, this.model),
-          required: evalF(data.required, this.model),
-        });
-
-        data.cId = data.cId || _.uniqueId('pgC_');
-
-        if (!data.disabled && data.mode != 'properties') {
-          data.placeholder = data.placeholder || this.defaults.placeholder;
-        }
-
-        // Clean up first
-        if (this.has_datepicker)
-          this.$el.find('input').datetimepicker('destroy');
-        this.$el.empty();
-        this.$el.removeClass(Backform.hiddenClassName);
-
-
-        this.$el.html(this.template(data)).addClass(field.name);
-
-        if (!data.visible) {
-          this.has_datepicker = false;
-          this.$el.addClass(Backform.hiddenClassName);
-        } else {
-          this.has_datepicker = true;
-          let self = this;
-          if (!_.isUndefined(data.value) && !_.isNull(data.value)
-              && data.value.toLowerCase() === 'infinity') {
-            data.value = null;
-          }
-
-          let dateSettings = {};
-          if (!data.setMinDate) {
-            dateSettings = {
-              'date': data.value,
-            };
-          } else {
-            dateSettings = {
-              'date': data.value,
-              'minDate': data.value,
-            };
-          }
-
-          this.$el.find('input').first().datetimepicker(
-            _.extend({
-              keyBinds: {
-                enter: function(widget) {
-                  let picker = this;
-                  if (widget) {
-                    setTimeout(function() {
-                      picker.toggle();
-                      self.$el.find('input').first().trigger('blur');
-                    }, 10);
-                  } else {
-                    setTimeout(function() {
-                      picker.toggle();
-                    }, 10);
-                  }
-                },
-                tab: function(widget) {
-                  if (!widget) {
-                    // blur the input
-                    setTimeout(
-                      function() {
-                        self.$el.find('input').first().trigger('blur');
-                      }, 10
-                    );
-                  }
-                },
-                escape: function(widget) {
-                  if (widget) {
-                    let picker = this;
-                    setTimeout(function() {
-                      picker.toggle();
-                      self.$el.find('input').first().trigger('blur');
-                    }, 10);
-                  }
-                },
-              },
-            }, this.defaults.options, this.field.get('options'), dateSettings)
-          );
-        }
-        this.updateInvalid();
-        return this;
-      },
-      clearInvalid: function() {
-        Backform.InputControl.prototype.clearInvalid.apply(this, arguments);
-        this.$el.removeClass('pgadmin-datepicker-has-error');
-        return this;
-      },
-      updateInvalid: function() {
-        Backform.InputControl.prototype.updateInvalid.apply(this, arguments);
-        // Introduce a new class to fix the error icon placement on the control
-        this.$el.addClass('pgadmin-datepicker-has-error');
-      },
-      cleanup: function() {
-        if (this.has_datepicker)
-          this.$el.find('input').datetimepicker('destroy');
-        this.$el.empty();
-      },
-    });
-
-  // Color Picker control
-  Backform.ColorControl = Backform.InputControl.extend({
-    defaults: {
-      label: '',
-      extraClasses: [],
-      helpMessage: null,
-      showPalette: true,
-      allowEmpty: true,
-      colorFormat: 'HEX',
-      defaultColor: null,
-      position: 'right-middle',
-      clearText: gettext('No color'),
-    },
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>" for="<%=cId%>"><%=label%></label>',
-      '<div class="<%=Backform.controlsClassName%>">',
-      '  <input id="<%=cId%>" class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%> d-none" name="<%=name%>" value="<%-value%>" <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> />',
-      '  <p></p>',
-      '  <% if (helpMessage && helpMessage.length) { %>',
-      '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '  <% } %>',
-      '</div>',
-    ].join('\n')),
-    applyColor: function(name, instance, color) {
-      if(!color) {
-        this.model.set(name, '', {silent: true});
-      } else {
-        instance.applyColor(true);
-        this.model.set(name, instance.getSelectedColor().toHEXA().toString(), {silent: true});
-      }
-    },
-    render: function() {
-      // Clear first
-      if (this.picker) {
-        this.picker.destroyAndRemove();
-        this.picker = null;
-      }
-
-      let field = _.defaults(this.field.toJSON(), this.defaults),
-        attributes = this.model.toJSON(),
-        attrArr = field.name.split('.'),
-        name = attrArr.shift(),
-        path = attrArr.join('.'),
-        rawValue = this.keyPathAccessor(attributes[name], path),
-        data = _.extend(field, {
-          rawValue: rawValue,
-          value: this.formatter.fromRaw(rawValue, this.model),
-          attributes: attributes,
-          formatter: this.formatter,
-        }),
-        evalF = function(f, d, m) {
-          return (_.isFunction(f) ? !!f.apply(d, [m]) : !!f);
-        };
-
-      // Evaluate the disabled, visible, and required option
-      _.extend(data, {
-        disabled: evalF(data.disabled, data, this.model),
-        visible: evalF(data.visible, data, this.model),
-        required: evalF(data.required, data, this.model),
-      });
-
-      data.cId = data.cId || _.uniqueId('pgC_');
-      // Clean up first
-      this.$el.empty();
-
-      if (!data.visible)
-        this.$el.addClass(Backform.hiddenClassname);
-
-      this.$el.html(this.template(data)).addClass(field.name);
-
-      data.colorFormat = (data.colorFormat) ? data.colorFormat.toUpperCase() : 'HEX';
-      data.value = (!data.value || data.value == '') ?  data.defaultColor : data.value;
-      // Creating default Color picker
-      this.picker = new Pickr({
-        el: this.$el.find('p')[0],
-        theme: 'monolith',
-        swatches: [
-          '#000', '#666', '#ccc', '#fff', '#f90', '#ff0', '#0f0',
-          '#f0f', '#f4cccc', '#fce5cd', '#d0e0e3', '#cfe2f3', '#ead1dc', '#ea9999',
-          '#b6d7a8', '#a2c4c9', '#d5a6bd', '#e06666','#93c47d', '#76a5af', '#c27ba0',
-          '#f1c232', '#6aa84f', '#45818e', '#a64d79', '#bf9000', '#0c343d', '#4c1130',
-        ],
-        position: data.position,
-        strings: {
-          clear: data.clearText,
-        },
-        components: {
-          palette: data.showPalette,
-          preview: true,
-          hue: data.showPalette,
-          interaction: {
-            clear: data.allowEmpty,
-            defaultRepresentation: data.colorFormat,
-            disabled: data.disabled,
-          },
-        },
-      });
-
-      this.picker.on('init', instance => {
-        this.picker.setColor(data.value, true);
-        data.disabled && this.picker.disable();
-
-        const {lastColor} = instance.getRoot().preview;
-        const {clear} = instance.getRoot().interaction;
-
-        /* Cycle the keyboard navigation within the color picker */
-        clear.addEventListener('keydown', (e)=>{
-          if(e.keyCode === 9) {
-            e.preventDefault();
-            e.stopPropagation();
-            lastColor.focus();
-          }
-        });
-
-        lastColor.addEventListener('keydown', (e)=>{
-          if(e.keyCode === 9 && e.shiftKey) {
-            e.preventDefault();
-            e.stopPropagation();
-            clear.focus();
-          }
-        });
-      }).on('clear', (instance) => {
-        this.applyColor(name, instance, null);
-      }).on('change', (color, source, instance) => {
-        this.applyColor(name, instance, color);
-      }).on('show', (color, instance) => {
-        const {palette} = instance.getRoot().palette;
-        palette.focus();
-      }).on('hide', (instance) => {
-        const button = instance.getRoot().button;
-        button.focus();
-      });
-
-      this.updateInvalid();
-      return this;
-    },
-  });
-
-  let KeyCodeControlFormatter = Backform.KeyCodeControlFormatter = function() {/*This is intentional (SonarQube)*/};
-
-  _.extend(KeyCodeControlFormatter.prototype, {
-    fromRaw: function (rawData) {
-      return rawData['char'];
-    },
-    // we don't need toRaw
-    toRaw: undefined,
-  });
-
-  Backform.KeyCodeControl = Backform.InputControl.extend({
-    defaults: _.defaults({
-      escapeKeyCodes: [16, 17, 18, 27], // Shift, Ctrl, Alt/Option, Escape
-    }, Backform.InputControl.prototype.defaults),
-
-    events: {
-      'keydown input': 'onkeyDown',
-      'keyup input': 'preventEvent',
-      'focus select': 'clearInvalid',
-    },
-
-    formatter: KeyCodeControlFormatter,
-
-    preventEvent: function(e) {
-      let key_code = e.which || e.keyCode,
-        field = _.defaults(this.field.toJSON(), this.defaults);
-
-      if (field.escapeKeyCodes.indexOf(key_code) != -1) {
-        return;
-      }
-
-      e.preventDefault();
-      e.stopImmediatePropagation();
-      e.stopPropagation();
-    },
-
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%> keyboard-shortcut-label"><%=label%></label>',
-      '<div class="<%=Backform.controlsClassName%>">',
-      '  <input aria-label="<%=name%>" type="<%=type%>" class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>" name="<%=name%>" oncopy="return false; oncut="return false; onpaste="return false;" maxlength="<%=maxlength%>" value="<%-value%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> />',
-      '  <% if (helpMessage && helpMessage.length) { %>',
-      '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '  <% } %>',
-      '</div>',
-    ].join('\n')),
-    onkeyDown: function(e) {
-      let self = this,
-        model = this.model,
-        attrArr = this.field.get('name').split('.'),
-        name = attrArr.shift(),
-        changes = {},
-        key_code = e.which || e.keyCode,
-        key,
-        field = _.defaults(this.field.toJSON(), this.defaults);
-
-      if (field.escapeKeyCodes.indexOf(key_code) != -1) {
-        return;
-      }
-
-      if (this.model.errorModel instanceof Backbone.Model) {
-        this.model.errorModel.unset(name);
-      }
-      key = gettext(e.key);
-      if (key_code == 32) {
-        key = gettext('Space');
-      }
-      changes = {
-        'key_code': e.which || e.keyCode,
-        'char': key,
-      };
-
-      this.stopListening(this.model, 'change:' + name, this.render);
-      model.set(name, changes);
-      this.listenTo(this.model, 'change:' + name, this.render);
-      setTimeout(function() {
-        self.$el.find('input').val(key);
-      });
-      e.preventDefault();
-    },
-    keyPathAccessor: function(obj, path) {
-      let res = obj;
-      path = path.split('.');
-      for (let path_val of path) {
-        if (_.isNull(res)) return null;
-        if (_.isEmpty(path_val)) continue;
-        if (!_.isUndefined(res[path_val])) res = res[path_val];
-      }
-      return res;
-    },
-  });
-
-  Backform.KeyboardShortcutControl = Backform.Control.extend({
-
-    initialize: function() {
-
-      Backform.Control.prototype.initialize.apply(this, arguments);
-
-      let fields = this.field.get('fields');
-
-      if (!fields) {
-        throw new ReferenceError('"fields" not found in keyboard shortcut');
-      }
-
-      this.innerModel = new Backbone.Model();
-
-      this.controls = [];
-    },
-    cleanup: function() {
-
-      this.stopListening(this.innerModel, 'change', this.onInnerModelChange);
-
-      _.each(this.controls, function(c) {
-        c.remove();
-      });
-
-      this.controls.length = 0;
-    },
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
-      '<div class="<%=Backform.controlsClassName%> d-flex flex-row">',
-      '</div>',
-    ].join('\n')),
-
-    onInnerModelChange: function() {
-
-      let name = this.field.get('name'),
-        val = $.extend(true, {}, this.model.get(name));
-
-      this.stopListening(this.model, 'change:' + name, this.render);
-
-      this.model.set(name,
-        $.extend(true, val, this.innerModel.toJSON())
-      );
-
-      this.listenTo(this.model, 'change:' + name, this.render);
-    },
-
-    render: function() {
-      this.cleanup();
-      this.$el.empty();
-
-      let self = this,
-        initial_value = {},
-        field = _.defaults(this.field.toJSON(), this.defaults),
-        value = self.model.get(field['name']),
-        innerFields = field['fields'];
-
-      this.$el.html(self.template(field)).addClass(field.name);
-
-      let $container = $(self.$el.find('.pgadmin-controls'));
-
-      _.each(innerFields, function(inField) {
-        initial_value[inField['name']] = value[inField['name']];
-      });
-
-      self.innerModel.set(initial_value);
-
-      self.listenTo(self.innerModel, 'change', self.onInnerModelChange);
-
-      _.each(innerFields, function(fld) {
-
-        let f = new Backform.Field(
-            _.extend({}, {
-              id: fld['name'],
-              name: fld['name'],
-              control: fld['type'] == 'checkbox' ? 'checkboxWithBox' : fld['type'],
-              label: fld['label'],
-            })
-          ),
-          cntr = new (f.get('control')) ({
-            field: f,
-            model: self.innerModel,
-          });
-
-        cntr.render();
-
-        if(fld['type'] == 'checkbox') {
-          // Remove control label for keyboard shortcuts to
-          // align it properly.
-          let label = cntr.$el.find('label.control-label').text().trim();
-          if (label.length <= 0) {
-            cntr.$el.find('label.control-label').remove();
-          }
-
-          if (fld['name'] == 'alt') {
-            $container.append($('<div class="pg-el-sm-3 pg-el-12"></div>').append(cntr.$el));
-          } else {
-            $container.append($('<div class="pg-el-sm-2 pg-el-12"></div>').append(cntr.$el));
-          }
-        } else {
-          $container.append($('<div class="pg-el-sm-5 pg-el-12"></div>').append(cntr.$el));
-        }
-
-        // We will keep track of all the controls rendered at the
-        // moment.
-        self.controls.push(cntr);
-
-      });
-
-      return self;
-    },
-    remove: function() {
-      /* First do the clean up */
-      this.cleanup();
-      Backform.Control.prototype.remove.apply(this, arguments);
-    },
-  });
-
-  Backform.CheckboxWithBoxControl = Backform.CheckboxControl.extend({
-    events: _.extend({}, Backform.CheckboxControl.prototype.events, {
-      'click button': 'onButtonClick',
-    }),
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>"><%=controlLabel%></label>',
-      '<div class="<%=Backform.controlContainerClassName%>">',
-      '  <button class="btn btn-secondary btn-checkbox">',
-      '  <div class="custom-control custom-checkbox <%=extraClasses.join(\' \')%>">',
-      '    <input tabindex="-1" type="checkbox" class="custom-control-input" id="<%=cId%>" name="<%=name%>" <%=value ? "checked=\'checked\'" : ""%> <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> />',
-      '    <label class="custom-control-label" for="<%=cId%>" aria-label="<%=cId%>">',
-      '      <%=label%>',
-      '    </label>',
-      '  </div>',
-      '  </button>',
-      '</div>',
-    ].join('\n')),
-    onButtonClick: function(e) {
-      if (e.target.nodeName !== 'BUTTON')
-        return;
-      this.$el.find('input[type=checkbox]').trigger('click');
-    },
-  });
-
-  Backform.ThresholdControl = Backform.Control.extend({
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
-      '<div class="<%=Backform.controlContainerClassName%>">',
-      '  <span class="control-label pg-el-sm-2 pg-el-12"><%=warning_label%></span>',
-      '  <input type="text" id="warning_threshold" class="pg-el-sm-2" value="<%=warning_value%>" />',
-      '  <span class="control-label pg-el-sm-1 pg-el-12"><%=alert_label%></span>',
-      '  <input type="text" id="alert_threshold" class="pg-el-sm-2" value="<%=alert_value%>" />',
-      '  <span class="control-label pg-el-sm-3 pg-el-12"><%=unit%></span>',
-      '  <% if (helpMessage && helpMessage.length) { %>',
-      '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '  <% } %>',
-      '</div>',
-    ].join('\n')),
-
-    events: {
-      'change input#warning_threshold': 'onChange',
-      'change input#alert_threshold': 'onChange',
-    },
-    initialize: function() {
-      Backform.Control.prototype.initialize.apply(this, arguments);
-    },
-
-    render: function() {
-      let field = _.defaults(this.field.toJSON(), this.defaults),
-        attributes = this.model.toJSON(),
-        threshold_val = [];
-
-      if (!_.isUndefined(this.model.get('value')) && !_.isNull(this.model.get('value'))){
-        threshold_val = this.model.get('value').split('|');
-      }
-
-      let data = _.extend(field, {
-        attributes: attributes,
-        'warning_value': threshold_val.length > 0 ? threshold_val[0] : '',
-        'alert_value': threshold_val.length > 1 ? threshold_val[1] : ''
-      });
-
-      this.$el.html(this.template(data));
-
-      return this;
-    },
-
-    onChange: function() {
-      // Get the value from raw jquery and concat it using |
-      // and set the value
-      let warning_threshold = $('input#warning_threshold').val(),
-        alert_threshold = $('input#alert_threshold').val();
-
-      let threshold_val = warning_threshold + '|' + alert_threshold;
-      this.model.set(this.field.get('name'), threshold_val, {
-        silent: false
-      });
-    }
-  });
-
-  return Backform;
-});
diff --git a/web/pgadmin/static/js/backgrid.pgadmin.js b/web/pgadmin/static/js/backgrid.pgadmin.js
deleted file mode 100644
index 5fba5a041..000000000
--- a/web/pgadmin/static/js/backgrid.pgadmin.js
+++ /dev/null
@@ -1,2318 +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([
-  'sources/gettext', 'underscore', 'jquery', 'backbone', 'backform', 'backgrid',
-  'moment', 'bignumber', 'codemirror', 'sources/utils', 'sources/keyboard_shortcuts', 'sources/select2/configure_show_on_scroll',
-  'sources/window', 'bootstrap.datetimepicker', 'backgrid.filter', 'bootstrap.toggle',
-], function(
-  gettext, _, $, Backbone, Backform, Backgrid, moment, BigNumber, CodeMirror,
-  commonUtils, keyboardShortcuts, configure_show_on_scroll, pgWindow
-) {
-  /*
-   * Add mechanism in backgrid to render different types of cells in
-   * same column;
-   */
-  let pgAdmin = (window.pgAdmin = window.pgAdmin || {}),
-    pgBrowser = pgAdmin.Browser;
-
-  // Add new property cellFunction in Backgrid.Column.
-  _.extend(Backgrid.Column.prototype.defaults, {
-    cellFunction: undefined,
-  });
-
-  // Add tooltip to cell if cell content is larger than
-  // cell width
-  _.extend(Backgrid.Cell.prototype.events, {
-    'mouseover': function() {
-      var $el = $(this.el);
-      if ($el.text().length > 0 && !$el.attr('title') &&
-        ($el.innerWidth() + 1) < $el[0].scrollWidth
-      ) {
-        $el.attr('title', $.trim($el.text()));
-      }
-    },
-  });
-
-  // bind shortcut in cell edit mode
-  _.extend(Backgrid.InputCellEditor.prototype.events, {
-    'keydown': function(e) {
-      let preferences = pgWindow.default.pgAdmin.Browser.get_preferences_for_module('browser');
-      if(preferences && keyboardShortcuts.validateShortcutKeys(preferences.add_grid_row,e)) {
-        pgBrowser.keyboardNavigation.bindAddGridRow();
-      } else {
-        Backgrid.InputCellEditor.prototype.saveOrCancel.apply(this, arguments);
-      }
-    },
-  });
-
-  /* Overriding backgrid sort method.
-   * As we are getting numeric, integer values as string
-   * from server side, but on client side javascript truncates
-   * large numbers automatically due to which backgrid was unable
-   * to sort numeric values properly in the grid.
-   * To fix this issue, now we check if cell type is integer/number
-   * convert it into BigNumber object and make comparison to perform sorting.
-   */
-
-  _.extend(Backgrid.Body.prototype, {
-    sort: function(column, direction) {
-
-      if (!_.contains(['ascending', 'descending', null], direction)) {
-        throw new RangeError('direction must be one of "ascending", "descending" or `null`');
-      }
-
-      if (_.isString(column)) column = this.columns.findWhere({
-        name: column,
-      });
-
-      var collection = this.collection;
-
-      var order;
-      if (direction === 'ascending') order = -1;
-      else if (direction === 'descending') order = 1;
-      else order = null;
-
-      // Get column type and pass it to comparator.
-      var col_type = column.get('cell').prototype.className || 'string-cell',
-        comparator = this.makeComparator(column.get('name'), order,
-          order ?
-            column.sortValue() :
-            function(model) {
-              return model.cid.replace('c', '') * 1;
-            }, col_type);
-
-      if (Backbone.PageableCollection &&
-        collection instanceof Backbone.PageableCollection) {
-
-        collection.setSorting(order && column.get('name'), order, {
-          sortValue: column.sortValue(),
-        });
-
-        if (collection.fullCollection) {
-          // If order is null, pageable will remove the comparator on both sides,
-          // in this case the default insertion order comparator needs to be
-          // attached to get back to the order before sorting.
-          if (collection.fullCollection.comparator == null) {
-            collection.fullCollection.comparator = comparator;
-          }
-          collection.fullCollection.sort();
-          collection.trigger('backgrid:sorted', column, direction, collection);
-        } else collection.fetch({
-          reset: true,
-          success: function() {
-            collection.trigger('backgrid:sorted', column, direction, collection);
-          },
-        });
-      } else {
-        collection.comparator = comparator;
-        collection.sort();
-        collection.trigger('backgrid:sorted', column, direction, collection);
-      }
-
-      column.set('direction', direction);
-
-      return this;
-    },
-    makeComparator: function(attr, order, func, type) {
-
-      return function(left, right) {
-        // extract the values from the models
-
-        var l = func(left, attr),
-          r = func(right, attr),
-          t;
-        if (_.isUndefined(l) || _.isUndefined(r)) return;
-
-        var types = ['number-cell', 'integer-cell'];
-        if (_.include(types, type)) {
-          var _l, _r;
-          // NaN if invalid number
-          try {
-            _l = new BigNumber(l);
-          } catch (err) {
-            _l = NaN;
-          }
-
-          try {
-            _r = new BigNumber(r);
-          } catch (err) {
-            _r = NaN;
-          }
-
-          // if descending order, swap left and right
-          if (order === 1) {
-            t = _l;
-            _l = _r;
-            _r = t;
-          }
-
-          if (_l.eq(_r)) // If both are equals
-            return 0;
-          else if (_l.lt(_r)) // If left is less than right
-            return -1;
-          else
-            return 1;
-        } else {
-          // if descending order, swap left and right
-          if (order === 1) {
-            t = l;
-            l = r;
-            r = t;
-          }
-
-          // compare as usual
-          if (l === r) return 0;
-          else if (l === null && r != null) return -1;
-          else if (l != null && r === null) return 1;
-          else if (l < r) return -1;
-          return 1;
-        }
-      };
-    },
-    moveToNextCell: function (model, column, command) {
-      var i = this.collection.indexOf(model);
-      var j = this.columns.indexOf(column);
-      var cell, renderable, editable, m, n;
-
-      // return if model being edited in a different grid
-      if (j === -1) return this;
-
-      this.rows[i].cells[j].exitEditMode();
-
-      if (command.moveUp() || command.moveDown() || command.moveLeft() ||
-          command.moveRight() || command.save()) {
-        var l = this.columns.length;
-        var maxOffset = l * this.collection.length;
-
-        if (command.moveUp() || command.moveDown()) {
-          m = i + (command.moveUp() ? -1 : 1);
-          var row = this.rows[m];
-          if (row) {
-            cell = row.cells[j];
-            if (Backgrid.callByNeed(cell.column.editable(), cell.column, model)) {
-              cell.enterEditMode();
-              model.trigger('backgrid:next', m, j, false);
-            }
-          }
-          else model.trigger('backgrid:next', m, j, true);
-        }
-        else if (command.moveLeft() || command.moveRight()) {
-          var right = command.moveRight();
-          for (var offset = i * l + j + (right ? 1 : -1);
-            offset >= 0 && offset < maxOffset;
-            right ? offset++ : offset--) {
-            m = ~~(offset / l);
-            n = offset - m * l;
-            cell = this.rows[m].cells[n];
-            renderable = Backgrid.callByNeed(cell.column.renderable(), cell.column, cell.model);
-            editable = Backgrid.callByNeed(cell.column.editable(), cell.column, model);
-            if(cell && cell.$el.hasClass('edit-cell') &&
-              !cell.$el.hasClass('privileges') || cell.$el.hasClass('delete-cell')) {
-              model.trigger('backgrid:next', m, n, false);
-              if(cell.$el.hasClass('delete-cell')) {
-                setTimeout(function(){
-                  $(cell.$el).trigger('focus');
-                }, 50);
-              }
-              break;
-            } else if (renderable && editable) {
-              cell.enterEditMode();
-              model.trigger('backgrid:next', m, n, false);
-              break;
-            }
-          }
-
-          if (offset == maxOffset) {
-            model.trigger('backgrid:next', ~~(offset / l), offset - m * l, true);
-          }
-        }
-      }
-
-      return this;
-    },
-  });
-
-  _.extend(Backgrid.Row.prototype, {
-    makeCell: function(column) {
-      return new(this.getCell(column))({
-        column: column,
-        model: this.model,
-      });
-    },
-    /*
-     * getCell function will check and execute user given 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="0">',
-      '    <div class="subnode-body"></div>',
-      '</div>',
-    ].join('\n')),
-    stringTemplate: _.template([
-      '<div class="form-group">',
-      '  <label class="control-label col-sm-4"><%=label%></label>',
-      '  <div class="col-sm-8">',
-      '    <input type="text" class="form-control" name="<%=name%>" value="<%=value%>" placeholder="<%=placeholder%>" />',
-      '  </div>',
-      '</div>',
-    ].join('\n')),
-    extendWithOptions: function(options) {
-      _.extend(this, options);
-    },
-    render: function() {
-      return this;
-    },
-    postRender: function(model, column) {
-      var columns_length = this.columns_length,
-        // To render schema directly from Backgrid cell we use columns schema
-        // attribute.
-        schema = this.schema.length ? this.schema : this.column.get('schema');
-
-      if (column != null && column.get('name') != this.column.get('name'))
-        return false;
-
-      if (!_.isArray(schema)) throw new TypeError('schema must be an array');
-
-      // Create a Backbone model from our object if it does not exist
-      var $dialog = this.createDialog(columns_length);
-
-      // Add the Bootstrap form
-      var $form = $('<form class="form-dialog"></form>');
-      $dialog.find('div.subnode-body').append($form);
-
-      // Call Backform to prepare dialog
-      var back_el = $dialog.find('form.form-dialog');
-
-      this.objectView = new Backform.Dialog({
-        el: back_el,
-        model: this.model,
-        schema: schema,
-        tabPanelClassName: function() {
-          return 'sub-node-form col-sm-12';
-        },
-        events: {
-          'keydown': function (event) {
-            let preferences = pgWindow.default.pgAdmin.Browser.get_preferences_for_module('browser');
-            if(preferences && keyboardShortcuts.validateShortcutKeys(preferences.add_grid_row,event)) {
-              pgBrowser.keyboardNavigation.bindAddGridRow();
-            }
-          },
-        },
-      });
-
-      this.objectView.render();
-
-      return this;
-    },
-    createDialog: function(noofcol) {
-      noofcol = noofcol || 1;
-      var $dialog = this.$dialog = $(this.modalTemplate({
-          title: '',
-        })),
-        tr = $('<tr class="nohover editor-row">'),
-        td = $('<td>', {
-          class: 'editable sortable renderable',
-          style: 'height: auto',
-          colspan: noofcol + 2,
-        }).appendTo(tr);
-
-      this.tr = tr;
-
-      // Show the Bootstrap modal dialog
-      td.append($dialog.css('display', 'block'));
-      this.el.parent('tr').after(tr);
-
-      return $dialog;
-    },
-    save: function() {
-      // Retrieve values from the form, and store inside the object model
-      this.model.trigger('backgrid:edited', this.model, this.column, new Backgrid.Command({
-        keyCode: 13,
-      }));
-      if (this.tr) {
-        this.tr.remove();
-      }
-
-      return this;
-    },
-    remove: function() {
-      this.objectView.remove();
-      Backgrid.CellEditor.prototype.remove.apply(this, arguments);
-      if (this.tr) {
-        this.tr.remove();
-      }
-      return this;
-    },
-  });
-
-  Backgrid.Extension.PGSelectCell = Backgrid.SelectCell.extend({
-    // It's possible to render an option group or use a
-    // function to provide option values too.
-    optionValues: function() {
-      var res = [],
-        opts = _.result(this.column.attributes, 'options');
-      _.each(opts, function(o) {
-        res.push([o.label, o.value]);
-      });
-      return res;
-    },
-  });
-
-  Backgrid.Extension.ObjectCell = Backgrid.Cell.extend({
-    editorOptionDefaults: {
-      schema: [],
-    },
-    className: 'edit-cell',
-    editor: ObjectCellEditor,
-    initialize: function(options) {
-      Backgrid.Cell.prototype.initialize.apply(this, arguments);
-
-      // Pass on cell options to the editor
-      var cell = this,
-        editorOptions = {};
-      _.each(this.editorOptionDefaults, function(def, opt) {
-        if (!cell[opt]) cell[opt] = def;
-        if (options && options[opt]) cell[opt] = options[opt];
-        editorOptions[opt] = cell[opt];
-      });
-
-      editorOptions['el'] = $(this.el);
-      editorOptions['columns_length'] = this.column.collection.length;
-      editorOptions['el'].attr('tabindex', 0);
-
-      this.listenTo(this.model, 'backgrid:edit', function(model, column, sel_cell, editor) {
-        if (column.get('name') == this.column.get('name'))
-          editor.extendWithOptions(editorOptions);
-      });
-      // Listen for Tab key, open subnode dialog on space key
-      this.$el.on('keydown', function(e) {
-        if (e.keyCode == 32) {
-          $(this).click();
-        }
-      });
-    },
-    enterEditMode: function() {
-      // Notify that we are about to enter in edit mode for current cell.
-      // We will check if this row is editable first
-      var canEditRow = (!_.isUndefined(this.column.get('canEditRow')) &&
-          _.isFunction(this.column.get('canEditRow'))) ?
-        Backgrid.callByNeed(this.column.get('canEditRow'),
-          this.column, this.model) : true;
-      if (canEditRow) {
-        // 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(
-            '<i class=\'fa fa-pen-square subnode-edit-in-process\' title=\'' + gettext('Edit row') +  '\' aria-label=\'' + gettext('Edit row') +  '\'></i>'
-          );
-          let body = $(this.$el).parents()[1],
-            container = $(body).find('.tab-content:first > .tab-pane.active:first');
-          commonUtils.findAndSetFocus(container);
-          pgBrowser.keyboardNavigation.getDialogTabNavigator($(body).find('.subnode-dialog'));
-          this.model.trigger(
-            'pg-sub-node:opened', this.model, this
-          );
-        }
-      } else {
-        Notify.alert(gettext('Edit object'), gettext('This object is not user editable.'));
-      }
-    },
-    render: function() {
-      this.$el.empty();
-      this.$el.html('<i class=\'fa fa-edit\' title=\'' + gettext('Edit row') + '\' aria-label=\'' + gettext('Edit row') +  '\'></i>');
-      this.delegateEvents();
-      if (this.grabFocus)
-        this.$el.trigger('focus');
-      return this;
-    },
-    exitEditMode: function() {
-      if(!_.isUndefined(this.currentEditor) || !_.isEmpty(this.currentEditor)) {
-        var index = $(this.currentEditor.objectView.el)
-          .find('.nav-tabs > .active > a[data-toggle="tab"]').first()
-          .data('tabIndex');
-        Backgrid.Cell.prototype.exitEditMode.apply(this, arguments);
-        this.model.trigger(
-          'pg-sub-node:closed', this, index
-        );
-        this.grabFocus = true;
-      }
-    },
-    events: {
-      'click': function(e) {
-        if (this.$el.find('i').first().hasClass('subnode-edit-in-process')) {
-          // Need to redundantly undelegate events for Firefox
-          this.undelegateEvents();
-          this.currentEditor.save();
-        } else {
-          this.enterEditMode.call(this, []);
-        }
-        e.preventDefault();
-      },
-      'keydown': function(e) {
-        var model = this.model;
-        var column = this.column;
-        var command = new Backgrid.Command(e);
-
-        if (command.moveLeft()) {
-          setTimeout(function() {
-            model.trigger('backgrid:edited', model, column, command);
-          }, 20);
-        }
-      },
-    },
-  });
-
-  Backgrid.Extension.DeleteCell = Backgrid.Cell.extend({
-    defaults: _.defaults({
-      defaultDeleteMsg: gettext('Are you sure you wish to delete this row?'),
-      defaultDeleteTitle: gettext('Delete Row'),
-    }, Backgrid.Cell.prototype.defaults),
-
-    /** @property */
-    className: 'delete-cell',
-    events: {
-      'click': 'deleteRow',
-    },
-    deleteRow: function(e) {
-      e.preventDefault();
-      var that = this;
-      // We will check if row is deletable or not
-      var canDeleteRow = (!_.isUndefined(this.column.get('canDeleteRow')) &&
-          _.isFunction(this.column.get('canDeleteRow'))) ?
-        Backgrid.callByNeed(this.column.get('canDeleteRow'),
-          this.column, this.model) : true;
-      if (canDeleteRow) {
-        var delete_msg = !_.isUndefined(this.column.get('customDeleteMsg')) ?
-          this.column.get('customDeleteMsg') : that.defaults.defaultDeleteMsg;
-        var delete_title = !_.isUndefined(this.column.get('customDeleteTitle')) ?
-          this.column.get('customDeleteTitle') : that.defaults.defaultDeleteTitle;
-        Notify.confirm(
-          delete_title,
-          delete_msg,
-          function() {
-            let tbody = $(that.el).parents('tbody').eq(0);
-            that.model.collection.remove(that.model);
-            let row = $(tbody).find('tr');
-            if(row.length > 0) {
-              // set focus to first tr
-              row.first().children()[0].focus();
-            } else {
-              // set focus to add button
-              $(tbody).parents('.subnode').eq(0).find('.add').focus();
-            }
-          },
-          function() {
-            return true;
-          }
-        );
-      } else {
-        Notify.alert(gettext('Delete object'), gettext('This object cannot be deleted.'));
-      }
-    },
-    exitEditMode: function() {
-      this.$el.removeClass('editor');
-    },
-    initialize: function() {
-      Backgrid.Cell.prototype.initialize.apply(this, arguments);
-    },
-    render: function() {
-      var self = this;
-      this.$el.empty();
-      $(this.$el).attr('tabindex', 0);
-      this.$el.html('<i aria-label="' + gettext('Delete row') + '" class=\'fa fa-trash-alt\' title=\'' + gettext('Delete row') + '\'></i>');
-      // Listen for Tab/Shift-Tab key
-      this.$el.on('keydown', function(e) {
-        // with keyboard navigation on space key, mark row for deletion
-        if (e.keyCode == 32) {
-          self.$el.click();
-        }
-        var gotoCell;
-        if (e.keyCode == 9 || e.keyCode == 16) {
-          // go to Next Cell & if Shift is also pressed go to Previous Cell
-          gotoCell = e.shiftKey ? self.$el.prev() : self.$el.next();
-        }
-
-        if (gotoCell) {
-          let command = new Backgrid.Command({
-            key: 'Tab',
-            keyCode: 9,
-            which: 9,
-            shiftKey: e.shiftKey,
-          });
-          setTimeout(function() {
-            // When we have Editable Cell
-            if (gotoCell.hasClass('editable')) {
-              e.preventDefault();
-              e.stopPropagation();
-              self.model.trigger('backgrid:edited', self.model,
-                self.column, command);
-            }
-            else {
-              // When we have Non-Editable Cell
-              self.model.trigger('backgrid:edited', self.model,
-                self.column, command);
-            }
-          }, 20);
-        }
-      });
-
-
-      this.delegateEvents();
-      return this;
-    },
-  });
-
-
-  Backgrid.Extension.ClearCell = Backgrid.Cell.extend({
-    defaults: _.defaults({
-      defaultClearMsg: gettext('Are you sure you wish to clear this row?'),
-      defaultClearTitle: gettext('Clear Row'),
-    }, Backgrid.Cell.prototype.defaults),
-
-    /** @property */
-    className: 'clear-cell',
-    events: {
-      'click': 'clearRow',
-    },
-    clearRow: function(e) {
-      e.preventDefault();
-      if (_.isEmpty(e.currentTarget.innerHTML)) return false;
-      var that = this;
-      // We will check if row is deletable or not
-
-      var clear_msg = !_.isUndefined(this.column.get('customClearMsg')) ?
-        this.column.get('customClearMsg') : that.defaults.defaultClearMsg;
-      var clear_title = !_.isUndefined(this.column.get('customClearTitle')) ?
-        this.column.get('customClearTitle') : that.defaults.defaultClearTitle;
-      Notify.confirm(
-        clear_title,
-        clear_msg,
-        function() {
-          that.model.set('name', null);
-          that.model.set('sql', null);
-        },
-        function() {
-          return true;
-        }
-      );
-
-    },
-    exitEditMode: function() {
-      this.$el.removeClass('editor');
-    },
-    initialize: function() {
-      Backgrid.Cell.prototype.initialize.apply(this, arguments);
-    },
-    render: function() {
-      var self = this;
-      this.$el.empty();
-      $(this.$el).attr('tabindex', 0);
-      if (this.model.get('name') !== null && this.model.get('sql') !== null)
-        this.$el.html('<i aria-label="' + gettext('Clear row') + '" class=\'fa fa-eraser\' title=\'' + gettext('Clear row') + '\'></i>');
-      // Listen for Tab/Shift-Tab key
-      this.$el.on('keydown', function(e) {
-        // with keyboard navigation on space key, mark row for deletion
-        if (e.keyCode == 32) {
-          self.$el.click();
-        }
-        var gotoCell;
-        if (e.keyCode == 9 || e.keyCode == 16) {
-          // go to Next Cell & if Shift is also pressed go to Previous Cell
-          gotoCell = e.shiftKey ? self.$el.prev() : self.$el.next();
-        }
-
-        if (gotoCell) {
-          let command = new Backgrid.Command({
-            key: 'Tab',
-            keyCode: 9,
-            which: 9,
-            shiftKey: e.shiftKey,
-          });
-          setTimeout(function() {
-            // When we have Editable Cell
-            if (gotoCell.hasClass('editable')) {
-              e.preventDefault();
-              e.stopPropagation();
-              self.model.trigger('backgrid:edited', self.model,
-                self.column, command);
-            }
-            else {
-              // When we have Non-Editable Cell
-              self.model.trigger('backgrid:edited', self.model,
-                self.column, command);
-            }
-          }, 20);
-        }
-      });
-
-
-      this.delegateEvents();
-      return this;
-    },
-  });
-
-
-  Backgrid.Extension.CustomHeaderCell = Backgrid.HeaderCell.extend({
-    initialize: function() {
-      // Here, we will add custom classes to header cell
-      Backgrid.HeaderCell.prototype.initialize.apply(this, arguments);
-      var getClassName = this.column.get('cellHeaderClasses');
-      var getAriaLabel = this.column.get('cellAriaLabel');
-      if (getClassName) {
-        this.$el.addClass(getClassName);
-      }
-      if (getAriaLabel) {
-        this.$el.attr('aria-label', getAriaLabel);
-      }
-    },
-    render: function() {
-      Backgrid.HeaderCell.prototype.render.apply(this, arguments);
-      // If table header label is not present then screen reader will raise
-      // an error we will add span for screen reader only
-      if (this.column.get('label') == '' || !this.column.get('label')) {
-        let getAriaLabel = this.column.get('cellAriaLabel');
-        if (getAriaLabel)
-          this.$el.append(`<span class="sr-only">${getAriaLabel}</span>`);
-      }
-      return this;
-    },
-  });
-
-  /**
-    SwitchCell renders a Bootstrap Switch in backgrid cell
-  */
-  if (window.jQuery && window.jQuery.fn.bootstrapToggle)
-    $.fn.bootstrapToggle = window.jQuery.fn.bootstrapToggle;
-
-  Backgrid.Extension.SwitchCell = Backgrid.BooleanCell.extend({
-    defaults: {
-      options: _.defaults({
-        onText: gettext('Yes'),
-        offText: gettext('No'),
-        onColor: 'success',
-        offColor: 'ternary',
-        size: 'mini',
-        width: null,
-        height: null,
-      }, $.fn.bootstrapToggle.defaults),
-    },
-
-    className: 'switch-cell',
-
-    initialize: function() {
-      Backgrid.BooleanCell.prototype.initialize.apply(this, arguments);
-      this.onChange = this.onChange.bind(this);
-    },
-
-    enterEditMode: function() {
-      this.$el.addClass('editor');
-      $(this.$el.find('.toggle.btn')).trigger('focus');
-    },
-
-    exitEditMode: function() {
-      this.$el.removeClass('editor');
-    },
-
-    events: {
-      'change input': 'onChange',
-      'blur input': 'exitEditMode',
-      'keydown': 'onKeyDown',
-    },
-
-    onKeyDown: function(e) {
-      let preferences = pgWindow.default.pgAdmin.Browser.get_preferences_for_module('browser');
-      if(keyboardShortcuts.validateShortcutKeys(preferences.add_grid_row,e)) {
-        pgBrowser.keyboardNavigation.bindAddGridRow();
-      }
-    },
-
-    onChange: function() {
-      var model = this.model,
-        column = this.column,
-        val = this.formatter.toRaw(this.$input.prop('checked'), model);
-
-      this.enterEditMode();
-      // on bootstrap change we also need to change model's value
-      model.set(column.get('name'), val);
-      this.setSrValue();
-    },
-    setSrValue: function() {
-      let {onText, offText} = _.defaults({}, this.column.get('options'), this.defaults.options);
-      if(this.$el.find('.toggle.btn').hasClass('off')) {
-        this.$el.find('.sr-value').text(`
-          ${offText}, ${gettext('Toggle button')}
-        `);
-      } else {
-        this.$el.find('.sr-value').text(`
-          ${onText}, ${gettext('Toggle button')}
-        `);
-      }
-    },
-    render: function() {
-      var self = this,
-        col = _.defaults(this.column.toJSON(), this.defaults),
-        model = this.model,
-        column = this.column,
-        rawValue = this.formatter.fromRaw(
-          model.get(column.get('name')), model
-        ),
-        editable = Backgrid.callByNeed(col.editable, column, model),
-        options =  _.defaults({}, col.options, this.defaults.options),
-        cId = _.uniqueId('pgC_');
-
-      this.undelegateEvents();
-
-      this.$el.empty();
-      this.$el.append('<label class="sr-value sr-only" for="' + cId + '"></label>');
-      this.$el.append(
-        $('<input>', {
-          tabIndex: -1,
-          type: 'checkbox',
-          'aria-hidden': 'true',
-          'aria-label': column.get('name'),
-        }).prop('checked', rawValue).prop('disabled', !editable).attr('data-toggle', 'toggle')
-          .attr('data-size', options.size).attr('data-on', options.onText).attr('data-off', options.offText)
-          .attr('data-width', options.width).attr('data-height', options.height)
-          .attr('data-onstyle', options.onColor).attr('data-offstyle', options.offColor));
-
-      this.$input = this.$el.find('input[type=checkbox]').first();
-
-      // Override BooleanCell checkbox with Bootstraptoggle
-      this.$input.bootstrapToggle();
-
-      this.$el.find('.toggle.btn')
-        .attr('tabindex', !editable ? '-1' : '0')
-        .attr('id', cId)
-        .on('keydown', function(e) {
-          if (e.keyCode == 32) {
-            self.$el.find('input[type=checkbox]').bootstrapToggle('toggle');
-            e.preventDefault();
-            e.stopPropagation();
-            self.setSrValue();
-          }
-        });
-
-      this.$el.find('.toggle.btn .toggle-group .btn').attr('aria-hidden', true);
-      this.setSrValue();
-      // Listen for Tab key
-      this.$el.on('keydown', function(e) {
-        var gotoCell;
-        if (e.keyCode == 9) {
-          // go to Next Cell & if Shift is also pressed go to Previous Cell
-          gotoCell = e.shiftKey ? self.$el.prev() : self.$el.next();
-        }
-
-        if (gotoCell && gotoCell.length > 0) {
-          if(gotoCell.hasClass('editable')){
-            e.preventDefault();
-            e.stopPropagation();
-          }
-          let command = new Backgrid.Command({
-            key: 'Tab',
-            keyCode: 9,
-            which: 9,
-            shiftKey: e.shiftKey,
-          });
-          setTimeout(function() {
-            // When we have Editable Cell
-            if (gotoCell.hasClass('editable') && gotoCell.hasClass('edit-cell')) {
-              gotoCell.trigger('focus');
-            } else if (gotoCell.hasClass('editable')) {
-              setTimeout(function() {
-                self.model.trigger('backgrid:edited', self.model,
-                  self.column, command);
-              }, 10);
-              gotoCell.trigger('focus');
-            } else {
-              // When we have Non-Editable Cell
-              setTimeout(function() {
-                self.model.trigger('backgrid:edited', self.model,
-                  self.column, command);
-              }, 10);
-            }
-          }, 20);
-        }
-
-      });
-
-      this.delegateEvents();
-
-      return this;
-    },
-  });
-
-  /*
-   *  Select2Cell for backgrid.
-   */
-  Backgrid.Extension.Select2Cell = Backgrid.SelectCell.extend({
-    className: 'select2-cell',
-
-    /** @property */
-    editor: null,
-
-    defaults: _.defaults({
-      select2: {},
-      opt: {
-        label: null,
-        value: null,
-        selected: false,
-      },
-    }, Backgrid.SelectCell.prototype.defaults),
-
-    enterEditMode: function() {
-      if (!this.$el.hasClass('editor'))
-        this.$el.addClass('editor');
-      this.$select.select2('focus');
-      this.$select.select2('open');
-      this.$select.on('blur', this.exitEditMode);
-    },
-
-    exitEditMode: function() {
-      this.$select.off('blur', this.exitEditMode);
-      this.$select.select2('close');
-      this.$el.removeClass('editor');
-      this.$el.find('.select2-selection').trigger('focus');
-    },
-
-    saveOrCancel: function (e) {
-      var self = this;
-
-      var command = new Backgrid.Command(e);
-      var blurred = e.type === 'blur';
-
-      if (command.moveUp() || command.moveDown() || command.moveLeft() || command.moveRight() ||
-          command.save() || blurred) {
-
-        let gotoCell;
-        // go to Next Cell & if Shift is also pressed go to Previous Cell
-        if (e.keyCode == 9 || e.keyCode == 16) {
-          gotoCell = e.shiftKey ? self.$el.prev() : self.$el.next();
-          if (self.$el.next().length == 0){
-            setTimeout(function() {
-              self.$el.find('.select2-selection').blur();
-            }, 100);
-
-          }
-        }
-
-        if (gotoCell) {
-          let cmd = new Backgrid.Command({
-            key: 'Tab',
-            keyCode: 9,
-            which: 9,
-            shiftKey: e.shiftKey,
-          });
-          setTimeout(function() {
-            // When we have Editable Cell
-            if (gotoCell.hasClass('editable')) {
-              e.preventDefault();
-              e.stopPropagation();
-              self.model.trigger('backgrid:edited', self.model,
-                self.column, cmd);
-            }
-            else {
-              // When we have Non-Editable Cell
-              self.model.trigger('backgrid:edited', self.model,
-                self.column, cmd);
-            }
-          }, 20);
-        }
-      }
-    },
-    events: {
-      'select2:open': 'enterEditMode',
-      'select2:close': 'exitEditMode',
-      'change': 'onSave',
-      'select2:unselect': 'onSave',
-      'blur': 'saveOrCancel',
-      'keydown': 'saveOrCancel',
-    },
-    /** @property {function(Object, ?Object=): string} template */
-    template: _.template([
-      '<option value="<%- value %>" ',
-      '<%= selected ? \'selected="selected"\' : "" %>>',
-      '<%- label %></option>',
-    ].join(''),
-    null, {
-      variable: null,
-    }),
-
-    initialize: function() {
-      Backgrid.SelectCell.prototype.initialize.apply(this, arguments);
-      this.onSave = this.onSave.bind(this);
-      this.enterEditMode = this.enterEditMode.bind(this);
-      this.exitEditMode = this.exitEditMode.bind(this);
-    },
-
-    render: function() {
-      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'))(this) :
-            this.column.get('options')));
-
-      this.undelegateEvents();
-
-      if (this.$select) {
-        if (this.$select.data('select2')) {
-          this.$select.select2('destroy');
-        }
-        delete this.$select;
-        this.$select = null;
-      }
-
-      this.$el.empty();
-
-      if (!_.isArray(optionValues))
-        throw new TypeError('optionValues must be an array');
-
-      var optionText = null,
-        optionValue = null,
-        self = this,
-        selectedValues = model.get(this.column.get('name')),
-        select2_opts = _.extend({
-          openOnEnter: false,
-          multiple: false,
-          showOnScroll: true,
-          first_empty: true,
-        }, self.defaults.select2,
-        (col.select2 || {})
-        ),
-        selectTpl = _.template('<select <%=multiple ? "multiple" : "" %>></select>');
-
-      var $select = self.$select = $(selectTpl({
-        multiple: select2_opts.multiple,
-      })).appendTo(self.$el);
-
-      /*
-       * Add empty option as Select2 requires any empty '<option><option>' for
-       * some of its functionality to work.
-       */
-      if(select2_opts.first_empty) {
-        optionValues.unshift(this.defaults.opt);
-      }
-      for (let option_val of optionValues) {
-        var opt = option_val;
-
-        if (_.isArray(opt)) {
-
-          optionText = opt[0];
-          optionValue = opt[1];
-
-          $select.append(
-            self.template({
-              label: optionText,
-              value: optionValue,
-              selected: (selectedValues == optionValue) ||
-                (select2_opts.multiple && _.indexOf(selectedValues, optionValue) > -1),
-            }));
-        } else {
-          opt = _.defaults({}, opt, {
-            selected: ((selectedValues == opt.value) ||
-              (select2_opts.multiple && _.indexOf(selectedValues, opt.value) > -1)),
-          }, self.defaults.opt);
-          $select.append(self.template(opt));
-        }
-      }
-
-      if (col && _.has(col.disabled)) {
-        var evalF = function() {
-          var args = [];
-          Array.prototype.push.apply(args, arguments);
-          var f = args.shift();
-
-          if (typeof(f) === 'function') {
-            return f.apply(self, args);
-          }
-          return f;
-        };
-        _.extend(select2_opts, {
-          disabled: evalF(col.disabled, col, model),
-        });
-      } else {
-        _.extend(select2_opts, {
-          disabled: !editable,
-        });
-      }
-
-      this.delegateEvents();
-
-      // If disabled then no need to show placeholder
-      if (!editable || col.mode === 'properties') {
-        select2_opts['placeholder'] = '';
-      }
-
-      /* Configure show on scroll if required */
-      select2_opts = configure_show_on_scroll.default(select2_opts);
-
-      // Initialize select2 control.
-      this.$sel = this.$select.select2(select2_opts);
-
-      // Select the highlighted item on Tab press.
-      if (this.$sel) {
-        this.$sel.data('select2').on('keypress', function(ev) {
-          var ctx = this;
-
-          // keycode 9 is for TAB key
-          if (ev.which === 9 && ctx.isOpen()) {
-            ctx.trigger('results:select', {});
-            ev.preventDefault();
-          }
-        });
-      }
-
-      return this;
-    },
-
-    /**
-         Saves the value of the selected option to the model attribute.
-         */
-    onSave: function() {
-      var model = this.model;
-      var column = this.column;
-
-      model.set(column.get('name'), this.$select.val());
-    },
-
-    remove: function() {
-      this.$select.off('change', this.onSave);
-      if (this.$select.data('select2')) {
-        this.$select.select2('destroy');
-      }
-      this.$el.empty();
-      Backgrid.SelectCell.prototype.remove.apply(this, arguments);
-    },
-  });
-
-  /**
-    TextareaCellEditor the cell editor renders a textarea multi-line text input
-    box as its editor.
-
-    @class Backgrid.TextareaCellEditor
-    @extends Backgrid.InputCellEditor
-  */
-  var TextareaCellEditor = Backgrid.TextareaCellEditor = Backgrid.InputCellEditor.extend({
-    /** @property */
-    tagName: 'textarea',
-
-    events: {
-      'blur': 'saveOrCancel',
-      'keydown': '',
-    },
-  });
-
-  /**
-    TextareaCell displays multiline HTML strings.
-
-      @class Backgrid.Extension.TextareaCell
-      @extends Backgrid.Cell
-  */
-  Backgrid.Extension.TextareaCell = Backgrid.Cell.extend({
-    /** @property */
-    className: 'textarea-cell',
-
-    editor: TextareaCellEditor,
-  });
-
-
-  /**
-   * Custom header icon cell to add the icon in table header.
-   */
-  Backgrid.Extension.CustomHeaderIconCell = Backgrid.HeaderCell.extend({
-    /** @property */
-    className: 'header-icon-cell',
-    events: {
-      'click': 'addHeaderIcon',
-    },
-    addHeaderIcon: function(e) {
-      this.collection.add(
-        new(this.collection.model)
-      );
-      e.preventDefault();
-    },
-    render: function() {
-      this.$el.empty();
-      this.$el.html('<label><a><span style=\'font-weight:normal;\'>' + gettext('Array Values') + '</a></span></label> <button class=\'btn-sm btn-secondary add\'>' + gettext('Add') + '</button>');
-      this.delegateEvents();
-      return this;
-    },
-  });
-
-  var arrayCellModel = Backbone.Model.extend({
-    defaults: {
-      value: null,
-    },
-  });
-
-  /**
-     Custom InputArrayCellEditor for editing user input array for debugger.
-   */
-  var InputArrayCellEditor = Backgrid.Extension.InputArrayCellEditor =
-    Backgrid.CellEditor.extend({
-      tagName: 'div',
-
-      events: {
-        'blur': 'lostFocus',
-      },
-
-      render: function() {
-        var self = this,
-          arrayValuesCol = this.model.get(this.column.get('name')),
-          cell_type = 'string';
-
-        var data_type = this.model.get('type').replace('[]' ,'');
-        switch (data_type) {
-        case 'boolean':
-          cell_type = 'boolean';
-          break;
-        case 'integer':
-        case 'smallint':
-        case 'bigint':
-        case 'serial':
-        case 'smallserial':
-        case 'bigserial':
-        case 'oid':
-        case 'cid':
-        case 'xid':
-        case 'tid':
-          cell_type = 'integer';
-          break;
-        case 'real':
-        case 'numeric':
-        case 'double precision':
-        case 'decimal':
-          cell_type = 'number';
-          break;
-        case 'date':
-          cell_type = 'date';
-          break;
-        }
-
-        var gridCols = [{
-            name: 'value',
-            label: gettext('Array Values'),
-            type: 'text',
-            cell: cell_type,
-            headerCell: Backgrid.Extension.CustomHeaderIconCell,
-            cellHeaderClasses: 'width_percent_100',
-          }],
-          gridBody = $('<div class=\'pgadmin-control-group backgrid form-group col-12 object subnode\'></div>');
-
-        this.$el.attr('tabindex', '1');
-
-        gridCols.unshift({
-          name: 'pg-backform-delete',
-          label: '',
-          cell: Backgrid.Extension.DeleteCell,
-          //headerCell: Backgrid.Extension.CustomHeaderIconCell,
-          editable: false,
-          cell_priority: -1,
-        });
-
-        this.$el.empty();
-        var grid = self.grid = new Backgrid.Grid({
-          columns: gridCols,
-          collection: arrayValuesCol,
-        });
-
-        this.grid.listenTo(arrayValuesCol, 'backgrid:error',
-          (function(obj) {
-            return function(ev) {
-              obj.model.trigger('backgrid:error', obj.model, obj.column, new Backgrid.Command(ev));
-            };
-          })(this)
-        );
-
-        this.grid.listenTo(arrayValuesCol, 'backgrid:edited',
-          (function(obj) {
-            return function(ev) {
-              obj.model.trigger('backgrid:edited', obj.model, obj.column, new Backgrid.Command(ev));
-            };
-          })(this)
-        );
-
-        grid.render();
-
-        gridBody.append(grid.$el);
-
-        this.$el.html(gridBody);
-
-        $(self.$el).pgMakeVisible('backform-tab');
-        self.delegateEvents();
-
-        return this;
-      },
-
-      /*
-       * Call back function when the grid lost the focus
-       */
-      lostFocus: function(ev) {
-
-        var self = this,
-          /*
-           * Function to determine whether one dom element is descendant of another
-           * dom element.
-           */
-          isDescendant = function(parent, child) {
-            var node = child.parentNode;
-            while (node != null) {
-              if (node == parent) {
-                return true;
-              }
-              node = node.parentNode;
-            }
-            return false;
-          };
-        /*
-         * Between leaving the old element focus and entering the new element focus the
-         * active element is the document/body itself so add timeout to get the proper
-         * focused active element.
-         */
-        setTimeout(function() {
-          if (self.$el[0] != document.activeElement && !isDescendant(self.$el[0], document.activeElement)) {
-            var m = self.model,
-              column = self.column;
-            m.trigger('backgrid:edited', m, column, new Backgrid.Command(ev));
-
-            setTimeout(function() {
-              if (self.grid) {
-                self.grid.remove();
-                self.grid = null;
-              }
-            }, 10);
-          }
-        }, 10);
-      },
-    });
-
-  /*
-   * This will help us transform the user input string array values in proper format to be
-   * displayed in the cell.
-   */
-  var InputStringArrayCellFormatter = Backgrid.Extension.InputStringArrayCellFormatter =
-    function() {/*This is intentional (SonarQube)*/};
-  _.extend(InputStringArrayCellFormatter.prototype, {
-    /**
-     * Takes a raw value from a model and returns an optionally formatted
-     * string for display.
-     */
-    fromRaw: function(rawData) {
-      var values = [];
-      rawData.each(function(m) {
-        var val = m.get('value');
-        if (_.isUndefined(val)) {
-          values.push('null');
-        } else {
-          values.push(m.get('value'));
-        }
-      });
-      return values.toString();
-    },
-    toRaw: function(formattedData) {
-      return formattedData;
-    },
-  });
-
-  /*
-   * This will help us transform the user input integer array values in proper format to be
-   * displayed in the cell.
-   */
-  var InputIntegerArrayCellFormatter = Backgrid.Extension.InputIntegerArrayCellFormatter =
-    function() {/*This is intentional (SonarQube)*/};
-  _.extend(InputIntegerArrayCellFormatter.prototype, {
-    /**
-     * Takes a raw value from a model and returns an optionally formatted
-     * string for display.
-     */
-    fromRaw: function(rawData) {
-      var values = [];
-      rawData.each(function(m) {
-        var val = m.get('value');
-        if (_.isUndefined(val) || _.isNull(val)) {
-          values.push('NULL');
-        } else {
-          values.push(m.get('value'));
-        }
-      });
-      return values.toString();
-    },
-    toRaw: function(formattedData) {
-      formattedData.each(function(m) {
-        m.set('value', parseInt(m.get('value')), {
-          silent: true,
-        });
-      });
-
-      return formattedData;
-    },
-  });
-
-  /*
-   * This will help us transform the user input numeric array values in proper format to be
-   * displayed in the cell.
-   */
-  var InputNumberArrayCellFormatter= Backgrid.Extension.InputNumberArrayCellFormatter =
-    function() {/*This is intentional (SonarQube)*/};
-  _.extend(InputNumberArrayCellFormatter.prototype, {
-    /**
-     * Takes a raw value from a model and returns an optionally formatted
-     * string for display.
-     */
-    fromRaw: function(rawData) {
-      var values = [];
-      rawData.each(function(m) {
-        var val = m.get('value');
-        if (_.isUndefined(val) || _.isNull(val)) {
-          values.push('NULL');
-        } else {
-          values.push(m.get('value'));
-        }
-      });
-      return values.toString();
-    },
-    toRaw: function(formattedData) {
-      formattedData.each(function(m) {
-        m.set('value', parseFloat(m.get('value')), {
-          silent: true,
-        });
-      });
-
-      return formattedData;
-    },
-  });
-
-  /*
-   *  InputStringArrayCell for rendering and taking input for string array type in debugger
-   */
-  Backgrid.Extension.InputStringArrayCell = Backgrid.Cell.extend({
-    className: 'width_percent_25',
-    formatter: InputStringArrayCellFormatter,
-    editor: InputArrayCellEditor,
-
-    initialize: function() {
-      Backgrid.Cell.prototype.initialize.apply(this, arguments);
-      // set value to empty array.
-      var m = arguments[0].model;
-      if (_.isUndefined(this.collection)) {
-        this.collection = new(Backbone.Collection.extend({
-          model: arrayCellModel,
-        }))(m.get('value'));
-      }
-
-      this.model.set(this.column.get('name'), this.collection);
-      this.listenTo(this.collection, 'remove', this.render);
-    },
-  });
-
-  /*
-   *  InputIntegerArrayCell for rendering and taking input for integer array type in debugger
-   */
-  Backgrid.Extension.InputIntegerArrayCell = Backgrid.IntegerCell.extend({
-    className: 'width_percent_25',
-    formatter: InputIntegerArrayCellFormatter,
-    editor: InputArrayCellEditor,
-
-    initialize: function() {
-      Backgrid.IntegerCell.prototype.initialize.apply(this, arguments);
-      // set value to empty array.
-      var m = arguments[0].model;
-      _.each(m.get('value'), function(arrVal) {
-        if (arrVal.value === 'NULL') {
-          arrVal.value = null;
-        }
-      });
-
-      if (_.isUndefined(this.collection)) {
-        this.collection = new(Backbone.Collection.extend({
-          model: arrayCellModel,
-        }))(m.get('value'));
-      }
-
-      this.model.set(this.column.get('name'), this.collection);
-      this.listenTo(this.collection, 'remove', this.render);
-    },
-  });
-
-  /*
-   *  InputNumberArrayCell for rendering and taking input for numeric array type in debugger
-   */
-  Backgrid.Extension.InputNumberArrayCell = Backgrid.NumberCell.extend({
-    className: 'width_percent_25',
-    formatter: InputNumberArrayCellFormatter,
-    editor: InputArrayCellEditor,
-
-    initialize: function() {
-      Backgrid.NumberCell.prototype.initialize.apply(this, arguments);
-      // set value to empty array.
-      var m = arguments[0].model;
-      _.each(m.get('value'), function(arrVal) {
-        if (arrVal.value === 'NULL') {
-          arrVal.value = null;
-        }
-      });
-
-      if (_.isUndefined(this.collection)) {
-        this.collection = new(Backbone.Collection.extend({
-          model: arrayCellModel,
-        }))(m.get('value'));
-      }
-
-      this.model.set(this.column.get('name'), this.collection);
-      this.listenTo(this.collection, 'remove', this.render);
-    },
-  });
-
-  /*
-   *  InputBooleanArrayCell for rendering and taking input for boolean array type in debugger
-   */
-  Backgrid.Extension.InputBooleanArrayCell = Backgrid.BooleanCell.extend({
-    className: 'width_percent_25',
-    editor: InputArrayCellEditor,
-
-    initialize: function() {
-      Backgrid.BooleanCell.prototype.initialize.apply(this, arguments);
-      // set value to empty array.
-      var m = arguments[0].model;
-      if (_.isUndefined(this.collection)) {
-        this.collection = new(Backbone.Collection.extend({
-          model: arrayCellModel,
-        }))(m.get('value'));
-      }
-
-      this.model.set(this.column.get('name'), this.collection);
-      this.listenTo(this.collection, 'remove', this.render);
-    },
-  });
-
-  /**
-   * DependentCell functions can be used with the different cell type in order
-   * to setup the callback for the depedent attribute change in the model.
-   *
-   * Please implement the 'dependentChanged' as the callback in the used cell.
-   *
-   * @class Backgrid.Extension.DependentCell
-   **/
-  var DependentCell = Backgrid.Extension.DependentCell = function() {/*This is intentional (SonarQube)*/};
-
-  _.extend(
-    DependentCell.prototype, {
-      initialize: function() {
-        // Listen to the dependent fields in the model for any change
-        var deps = this.column.get('deps');
-        var self = this;
-
-        if (deps && _.isArray(deps)) {
-          _.each(deps, function(d) {
-            var attrArr = d.split('.'),
-              name = attrArr.shift();
-            self.listenTo(self.model, 'change:' + name, self.dependentChanged);
-          });
-        }
-      },
-      remove: function() {
-        // Remove the events for the dependent fields in the model
-        var self = this,
-          deps = self.column.get('deps');
-
-        if (deps && _.isArray(deps)) {
-          _.each(deps, function(d) {
-            var attrArr = d.split('.'),
-              name = attrArr.shift();
-
-            self.stopListening(self.model, 'change:' + name, self.dependentChanged);
-          });
-        }
-      },
-    });
-
-  /**
-   Formatter for PasswordCell.
-
-   @class Backgrid.PasswordFormatter
-   @extends Backgrid.CellFormatter
-   @constructor
-  */
-  var PasswordFormatter = Backgrid.PasswordFormatter = function() {/*This is intentional (SonarQube)*/};
-  PasswordFormatter.prototype = new Backgrid.CellFormatter();
-  _.extend(PasswordFormatter.prototype, {
-    fromRaw: function(rawValue) {
-
-      if (_.isUndefined(rawValue) || _.isNull(rawValue)) return '';
-
-      var pass = '';
-      rawValue.forEach(() => {
-        pass += '*';
-      });
-
-      return pass;
-    },
-  });
-
-  Backgrid.Extension.PasswordCell = Backgrid.StringCell.extend({
-
-    formatter: PasswordFormatter,
-
-    editor: Backgrid.InputCellEditor.extend({
-      attributes: {
-        type: 'password',
-        autocomplete: 'new-password',
-      },
-
-      render: function() {
-        var model = this.model;
-        this.$el.val(model.get(this.column.get('name')));
-        return this;
-      },
-    }),
-  });
-
-  /*
-   * Override NumberFormatter to support NaN, Infinity values.
-   * On client side, JSON do not directly support NaN & Infinity,
-   * we explicitly converted it into string format at server side
-   * and we need to parse it again in float at client side.
-   */
-  _.extend(Backgrid.NumberFormatter.prototype, {
-    fromRaw: function(number) {
-      if (_.isNull(number) || _.isUndefined(number)) return '';
-
-      number = parseFloat(number).toFixed(~~this.decimals);
-
-      var parts = number.split('.');
-      var integerPart = parts[0];
-      var decimalPart = parts[1] ? (this.decimalSeparator || '.') + parts[1] : '';
-
-      return integerPart.replace(this.HUMANIZED_NUM_RE, '$1' + this.orderSeparator) + decimalPart;
-    },
-  });
-
-  /*
-   *  JSONBCell Formatter.
-   */
-  var JSONBCellFormatter = Backgrid.Extension.JSONBCellFormatter =
-    function() {/*This is intentional (SonarQube)*/};
-  _.extend(JSONBCellFormatter.prototype, {
-    fromRaw: function(rawData) {
-      // json data
-      if (_.isArray(rawData)) {
-        var converted_data = '';
-        converted_data = _.map(rawData, function(data) {
-          return JSON.stringify(JSON.stringify(data));
-        });
-        return '{' + converted_data.join() + '}';
-      } else if (_.isObject(rawData)) {
-        return JSON.stringify(rawData);
-      } else {
-        return rawData;
-      }
-    },
-    toRaw: function(formattedData) {
-      return formattedData;
-    },
-  });
-
-  /*
-   *  JSONBCell for backgrid.
-   */
-  Backgrid.Extension.JSONBCell =
-    Backgrid.StringCell.extend({
-      className: 'jsonb-cell',
-      formatter: JSONBCellFormatter,
-    });
-
-  var DatepickerCellEditor = Backgrid.InputCellEditor.extend({
-    events: {},
-    initialize: function() {
-      Backgrid.InputCellEditor.prototype.initialize.apply(this, arguments);
-      var input = this;
-      $(this.el).prop('readonly', true);
-      $(this.el).datepicker({
-        onClose: function(newValue) {
-          var command = new Backgrid.Command({});
-          input.model.set(input.column.get('name'), newValue);
-          input.model.trigger(
-            'backgrid:edited', input.model, input.column, command
-          );
-          input = null;
-        },
-      });
-    },
-  });
-
-  Backgrid.Extension.DatepickerCell = Backgrid.Cell.extend({
-    editor: DatepickerCellEditor,
-  });
-
-  // Reference:
-  // https://github.com/wyuenho/backgrid-moment-cell/blob/master/backgrid-moment-cell.js
-  /**
-   MomentFormatter converts bi-directionally any datetime values in any format
-   supported by [moment()](http://momentjs.com/docs/#/parsing/) to any
-   datetime format
-   [moment.fn.format()](http://momentjs.com/docs/#/displaying/format/)
-   supports.
-   @class Backgrid.Extension.MomentFormatter
-   @extends Backgrid.CellFormatter
-   @constructor
-   */
-  var MomentFormatter = Backgrid.Extension.MomentFormatter = function(options) {
-    _.extend(this, this.defaults, options);
-  };
-
-  MomentFormatter.prototype = new Backgrid.CellFormatter;
-  _.extend(MomentFormatter.prototype, {
-    /**
-       @cfg {Object} options
-       @cfg {boolean} [options.modelInUnixOffset=false] Whether the model values
-       should be read/written as the number of milliseconds since UNIX Epoch.
-       @cfg {boolean} [options.modelInUnixTimestamp=false] Whether the model
-       values should be read/written as the number of seconds since UNIX Epoch.
-       @cfg {boolean} [options.modelInUTC=true] Whether the model values should
-       be read/written in UTC mode or local mode.
-       @cfg {string} [options.modelLang=moment.locale() moment>=2.8.0 |
-       moment.lang() moment<2.8.0] The locale the model values should be
-       read/written in.
-       @cfg {string} [options.modelFormat=moment.defaultFormat] The format this
-       moment formatter should use to read/write model values. Only meaningful if
-       the values are strings.
-       @cfg {boolean} [options.displayInUnixOffset=false] Whether the display
-       values should be read/written as the number of milliseconds since UNIX
-       Epoch.
-       @cfg {boolean} [options.displayInUnixTimestamp=false] Whether the display
-       values should be read/written as the number of seconds since UNIX Epoch.
-       @cfg {boolean} [options.displayInUTC=true] Whether the display values
-       should be read/written in UTC mode or local mode.
-       @cfg {string} [options.displayLang=moment.locale() moment>=2.8.0 |
-       moment.lang() moment<2.8.0] The locale the display values should be
-       read/written in.
-       @cfg {string} [options.displayFormat=moment.defaultFormat] The format
-       this moment formatter should use to read/write dislay values.
-       */
-    defaults: {
-      modelInUnixOffset: false,
-      modelInUnixTimestamp: false,
-      modelInUTC: true,
-      modelLang: moment.locale(),
-      modelFormat: moment.defaultFormat,
-      displayInUnixOffset: false,
-      displayInUnixTimestamp: false,
-      displayInUTC: true,
-      displayLang: moment.locale(),
-      displayFormat: moment.defaultFormat,
-      allowEmpty: false,
-    },
-
-    /**
-       Converts datetime values from the model for display.
-       @member Backgrid.Extension.MomentFormatter
-       @param {*} rawData
-       @return {string}
-       */
-    fromRaw: function(rawData) {
-      if (rawData == null) return '';
-      var m = null;
-      if (this.modelInUnixOffset) {
-        m = moment(rawData);
-      } else if (this.modelInUnixTimestamp) {
-        m = moment.unix(rawData);
-      } else if (this.modelInUTC) {
-        m = moment.utc(rawData, this.modelFormat, this.modelLang);
-      } else {
-        m = moment(rawData, this.modelFormat, this.modelLang);
-      }
-
-      if (this.displayInUnixOffset) return +m;
-
-      if (this.displayInUnixTimestamp) return m.unix();
-
-      if (this.displayLang) m.locale(this.displayLang);
-
-      if (this.displayInUTC) m.utc();
-      else m.local();
-
-      if (this.displayFormat != moment.defaultFormat) {
-        return m.format(this.displayFormat);
-      }
-
-      return m.format();
-    },
-
-    /**
-       Converts datetime values from user input to model values.
-       @member Backgrid.Extension.MomentFormatter
-       @param {string} formattedData
-       @return {string}
-       */
-    toRaw: function(formattedData) {
-      var m = null;
-      if (this.displayInUnixOffset) {
-        m = moment(+formattedData);
-      } else if (this.displayInUnixTimestamp) {
-        m = moment.unix(+formattedData);
-      } else if (this.displayInUTC) {
-        m = moment.utc(formattedData, this.displayFormat, this.displayLang);
-      } else {
-        m = moment(formattedData, this.displayFormat, this.displayLang);
-      }
-
-      if (!m || !m.isValid()) return (this.allowEmpty && formattedData === '') ? null : undefined;
-
-      if (this.modelInUnixOffset) return +m;
-
-      if (this.modelInUnixTimestamp) return m.unix();
-
-      if (this.modelLang) m.locale(this.modelLang);
-
-      if (this.modelInUTC) m.utc();
-      else m.local();
-
-      if (this.modelFormat != moment.defaultFormat) {
-        return m.format(this.modelFormat);
-      }
-
-      return m.format();
-    },
-  });
-
-  var MomentCell = Backgrid.Extension.MomentCell = Backgrid.Cell.extend({
-
-    editor: Backgrid.InputCellEditor,
-
-    /** @property */
-    className: 'datetime-cell',
-
-    /** @property {Backgrid.CellFormatter} [formatter=Backgrid.Extension.MomentFormatter] */
-    formatter: MomentFormatter,
-
-    /**
-       Initializer. Accept Backgrid.Extension.MomentFormatter.options and
-       Backgrid.Cell.initialize required parameters.
-     */
-    initialize: function(options) {
-
-      MomentCell.__super__.initialize.apply(this, arguments);
-
-      var formatterDefaults = MomentFormatter.prototype.defaults;
-      var formatterDefaultKeys = _.keys(formatterDefaults);
-      var classAttrs = _.pick(this, formatterDefaultKeys);
-      var formatterOptions = _.pick(options, formatterDefaultKeys);
-      var columnsAttrs = _.pick(this.column.toJSON(), formatterDefaultKeys);
-
-      // Priority of the options for the formatter, from highest to lowerest
-      // 1. MomentCell instance options
-      // 2. MomentCell class attributes
-      // 3. MomentFormatter defaults
-
-      // this.formatter will have been instantiated now
-      _.extend(this.formatter, formatterDefaults, classAttrs, formatterOptions, columnsAttrs);
-
-      this.editor = this.editor.extend({
-        attributes: _.extend({}, this.editor.prototype.attributes || this.editor.attributes || {}, {
-          placeholder: this.formatter.displayFormat,
-        }),
-        options: this.column.get('options'),
-      });
-    },
-  });
-
-  Backgrid.Extension.DatetimePickerEditor = Backgrid.InputCellEditor.extend({
-    postRender: function() {
-      var self = this,
-        evalF = function() {
-          var args = [];
-          Array.prototype.push.apply(args, arguments);
-          var f = args.shift();
-
-          if (typeof(f) === 'function') {
-            return f.apply(self, args);
-          }
-          return f;
-        },
-        options = _.extend({
-          format: 'YYYY-MM-DD HH:mm:ss Z',
-          icons: {
-            time: 'fa fa-clock',
-            data: 'fa fa-calendar-alt',
-            today: 'fa fa-calendar-check',
-            clear: 'fa fa-trash',
-          },
-          buttons: {
-            showToday: true,
-          },
-          toolbarPlacement: 'top',
-          widgetPositioning: {
-            horizontal: 'auto',
-            vertical: 'bottom',
-          },
-          keepOpen: false,
-        }, evalF(this.column.get('options')), {
-          keyBinds: {
-            'shift tab': function(widget) {
-              if (widget) {
-                // blur the input
-                setTimeout(
-                  function() {
-                    self.closeIt({
-                      keyCode: 9,
-                      shiftKey: true,
-                    });
-                  }, 10
-                );
-              }
-            },
-            tab: function(widget) {
-              if (widget) {
-                // blur the input
-                setTimeout(
-                  function() {
-                    self.closeIt({
-                      keyCode: 9,
-                    });
-                  }, 10
-                );
-              }
-            },
-          },
-        });
-      this.tabKeyPress = false;
-      this.$el.datetimepicker(options);
-      this.$el.datetimepicker('show');
-      this.picker = this.$el.data('datetimepicker');
-    },
-    events: {
-      'hide.datetimepicker': 'closeIt',
-      'focusout':'closeIt',
-      'keydown': 'keydownHandler',
-    },
-    keydownHandler: function(event) {
-      let stopBubble = false;
-      let self = this;
-      if (!event.altKey && event.keyCode == 38){
-        let currdate = self.$el.data('datetimepicker').date().clone();
-        if (self.$el.data('datetimepicker').widget.find('.datepicker').is(':visible')){
-          $(this.el).datetimepicker('date', currdate.subtract(7, 'd'));
-        }else{
-          $(this.el).datetimepicker('date', currdate.add(7, 'm'));
-        }
-      }else if (!event.altKey && event.keyCode == 40){
-        let currdate = self.$el.data('datetimepicker').date().clone();
-        if (self.$el.data('datetimepicker').widget.find('.datepicker').is(':visible')){
-          $(this.el).datetimepicker('date', currdate.add(7, 'd'));
-        }else{
-          $(this.el).datetimepicker('date', currdate.subtract(7, 'm'));
-        }
-      }else if (event.keyCode == 39){
-        let currdate = self.$el.data('datetimepicker').date().clone();
-        $(this.el).datetimepicker('date', currdate.add(1, 'd'));
-      }else if (event.keyCode == 37){
-        let currdate = self.$el.data('datetimepicker').date().clone();
-        $(this.el).datetimepicker('date', currdate.subtract(1, 'd'));
-      }
-
-      if (event.altKey && event.keyCode == 84){
-        if (self.$el.data('datetimepicker').widget.find('.timepicker').is(':visible')){
-          self.$el.data('datetimepicker').widget.find('.fa-calendar-alt').click();
-        }else{
-          self.$el.data('datetimepicker').widget.find('.fa-clock').click();
-        }
-      }
-
-      if(event.altKey && event.keyCode == 38){
-        let currdate = self.$el.data('datetimepicker').date().clone();
-        $(this.el).datetimepicker('date', currdate.add(1, 'h'));
-      }else if(event.altKey && event.keyCode == 40){
-        let currdate = self.$el.data('datetimepicker').date().clone();
-        $(this.el).datetimepicker('date', currdate.subtract(1, 'h'));
-      }
-
-      if (event.keyCode == 27){
-        this.$el.datetimepicker('hide');
-        stopBubble = true;
-      }
-
-      if(stopBubble) {
-        event.stopImmediatePropagation();
-      }
-      // If Tab key pressed from Cell and not from Datetime picker element
-      // then we should trigger edited event so that we can goto next cell
-      let tabKeyPressed = true;
-      if (event.keyCode === 9 && self.el === event.target) {
-        self.closeIt(event, tabKeyPressed);
-      }
-    },
-    closeIt: function(ev, isTabKeyPressed) {
-      if (this.is_closing || this.tabKeyPress)
-        return;
-
-      this.is_closing = true;
-      this.tabKeyPress = isTabKeyPressed;
-
-      var formatter = this.formatter,
-        model = this.model,
-        column = this.column,
-        val = this.$el.val(),
-        newValue = formatter.toRaw(val, model);
-
-      this.$el.datetimepicker('destroy');
-      this.is_closing = false;
-
-      /* set the model default value in case of empty or undefined */
-      if (_.isUndefined(newValue) ||
-        String(val).replace(/^\s+|\s+$/g, '') == '') {
-        newValue = null;
-      }
-
-      model.set(column.get('name'), newValue);
-      let command = new Backgrid.Command(ev);
-      model.trigger('backgrid:edited', model, column, command);
-    },
-  });
-
-  _.extend(MomentCell.prototype, MomentFormatter.prototype.defaults);
-
-
-  Backgrid.Extension.StringDepCell = Backgrid.StringCell.extend({
-    initialize: function() {
-      Backgrid.StringCell.prototype.initialize.apply(this, arguments);
-      Backgrid.Extension.DependentCell.prototype.initialize.apply(this, arguments);
-    },
-    dependentChanged: function() {
-      this.$el.empty();
-
-      var self = this,
-        model = this.model,
-        column = this.column,
-        editable = this.column.get('editable');
-
-      this.render();
-
-      var is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
-      setTimeout(function() {
-        self.$el.removeClass('editor');
-        if (is_editable) {
-          self.$el.addClass('editable');
-        } else {
-          self.$el.removeClass('editable');
-        }
-      }, 10);
-
-      this.delegateEvents();
-      return this;
-    },
-    remove: Backgrid.Extension.DependentCell.prototype.remove,
-  });
-
-  Backgrid.Extension.Select2DepCell = Backgrid.Extension.Select2Cell.extend({
-    initialize: function() {
-      Backgrid.Extension.Select2Cell.prototype.initialize.apply(this, arguments);
-      Backgrid.Extension.DependentCell.prototype.initialize.apply(this, arguments);
-    },
-
-    dependentChanged: function() {
-      var model = this.model,
-        column = this.column,
-        editable = this.column.get('editable');
-
-      this.render();
-
-      if (
-        _.isFunction(editable) ? !!editable.apply(column, [model]) :
-          !!editable
-      ) {
-        this.$el.addClass('editable');
-      } else {
-        this.$el.removeClass('editable');
-      }
-
-      this.delegateEvents();
-      return this;
-    },
-    remove: Backgrid.Extension.DependentCell.prototype.remove,
-  });
-
-  /* Custom search box was added to give user defined text box for search
-   * instead of backgrid rendered textbox
-   */
-  Backgrid.Extension.ClientSideFilter = Backgrid.Extension.ClientSideFilter.extend({
-    $customSearchBox: null,
-    template: function (data) {
-      return '<span class="search">&nbsp;</span><input type="search" ' + (data.placeholder ? 'aria-label= "' + data.placeholder + '"' : '')+' '+ (data.placeholder ? 'placeholder="' +
-      data.placeholder + '"' : '') + ' name="' + data.name + '" ' + (data.value ? 'value="' + data.value + '"' : '') + '/><a class="clear" data-backgrid-action="clear" href="#">&times;</a>';
-    },
-
-    searchBox: function() {
-      if(this.$customSearchBox) {
-        return this.$customSearchBox;
-      } else {
-        return this.$el.find('input[type=search]');
-      }
-    },
-
-    setCustomSearchBox: function($el) {
-      this.$customSearchBox = $el;
-      this.$customSearchBox.attr('type','search');
-      this.$customSearchBox.on('keydown', this.search.bind(this));
-      this.$customSearchBox.on('mousedown', this.search.bind(this));
-      return this;
-    },
-
-    unsetCustomSearchBox: function() {
-      this.$customSearchBox.off('keydown', this.search.bind(this));
-      this.$customSearchBox = null;
-      return this;
-    },
-  });
-
-  var BooleanCellFormatter = Backgrid.BooleanCellFormatter = function() {/*This is intentional (SonarQube)*/};
-  _.extend(BooleanCellFormatter.prototype, {
-    fromRaw: function (rawValue) {
-      if (_.isUndefined(rawValue) || _.isNull(rawValue)) {
-        return false;
-      } else if (rawValue === '1' || rawValue === 'True') {
-        return true;
-      } else if (rawValue === '0' || rawValue === 'False') {
-        return false;
-      }
-      return rawValue;
-    },
-    toRaw: function (formattedData) {
-      return formattedData;
-    },
-  });
-
-  Backgrid.BooleanCell = Backgrid.BooleanCell.extend({
-    className: 'boolean-cell',
-
-    enterEditMode: function() {
-      this.$el.addClass('editor');
-      $(this.$el.find('input[type=checkbox]')).trigger('focus');
-    },
-
-    exitEditMode: function() {
-      this.$el.removeClass('editor');
-    },
-
-    events: {
-      'change input': 'onChange',
-      'blur input': 'exitEditMode',
-      'keydown': 'onKeyDown',
-    },
-
-    onChange: function(e) {
-      var model = this.model,
-        column = this.column,
-        val = this.formatter.toRaw(this.$input.prop('checked'), model);
-
-      this.enterEditMode();
-      // on bootstrap change we also need to change model's value
-      model.set(column.get('name'), val);
-      model.trigger('backgrid:edited', model, column, new Backgrid.Command(e));
-    },
-
-    render: function () {
-      this.$el.empty();
-      var model = this.model, column = this.column;
-      var editable = Backgrid.callByNeed(column.editable(), column, model);
-      var align_center = column.get('align_center') || false;
-      let checked =  this.formatter.fromRaw(model.get(column.get('name')), model);
-      let id = `${column.get('name')}_${_.uniqueId()}`;
-
-      this.$el.empty();
-      this.$el.append(
-        $(`<div class="custom-control custom-checkbox custom-checkbox-no-label ${align_center?'text-center':''}">
-          <input tabindex="0" type="checkbox" class="custom-control-input" id="${id}" ${!editable?'disabled':''} ${checked?'checked':''}/>
-          <label class="custom-control-label" for="${id}">
-            <span class="sr-only">` + gettext('Select') + `<span>
-          </label>
-        </div>`)
-      );
-      this.$input = this.$el.find('input');
-      this.delegateEvents();
-      return this;
-    },
-  });
-
-  Backgrid.Extension.SqlCell = Backgrid.Extension.TextareaCell.extend({
-    className: 'sql-cell',
-    defaults: {
-      lineWrapping: true,
-    },
-    template: _.template([
-      '<div data-toggle="tooltip" data-placement="top" data-html="true" title="<%- val %>"><textarea aria-label="' + gettext('SQL') +'" + style="display: none;"><%- val %></textarea><div>',
-    ].join('\n')),
-
-    render: function() {
-      let self = this,
-        col = _.defaults(this.column.toJSON(), this.defaults),
-        model = this.model,
-        column = this.column,
-        columnName = this.column.get('name'),
-        editable = Backgrid.callByNeed(col.editable, column, model);
-
-      if (this.sqlCell) {
-        this.sqlCell.toTextArea();
-        delete this.sqlCell;
-        this.sqlCell = null;
-      }
-
-      this.$el.empty();
-      this.$el.append(this.template({
-        val:this.formatter.fromRaw(model.get(columnName), model),
-      })
-      );
-      this.$el.addClass(columnName);
-      this.updateStateClassesMaybe();
-      this.delegateEvents();
-
-      setTimeout(function() {
-        self.sqlCell = CodeMirror.fromTextArea(
-          (self.$el.find('textarea')[0]), {
-            mode: 'text/x-pgsql',
-            readOnly: !editable,
-            singleCursorHeightPerLine: true,
-            screenReaderLabel: columnName,
-          });
-      });
-
-      return this;
-    },
-    enterEditMode: function () {
-      if (!this.$el.hasClass('editor')) this.$el.addClass('editor');
-      this.sqlCell.focus();
-      this.sqlCell.on('blur', this.exitEditMode.bind(this));
-    },
-    exitEditMode: function () {
-      this.$el.removeClass('editor');
-      this.saveOrCancel.apply(this, arguments);
-    },
-    saveOrCancel: function() {
-      var model = this.model;
-      var column = this.column;
-      if (this.sqlCell) {
-        var val = this.sqlCell.getTextArea().value;
-        var newValue = this.sqlCell.getValue();
-        if (_.isUndefined(newValue)) {
-          model.trigger('backgrid:error', model, column, val);
-        }
-        else {
-          model.set(column.get('name'), newValue);
-        }
-      }
-    },
-    remove: function() {
-      if (this.sqlCell) {
-        $(this.$el.find('[data-toggle="tooltip"]')).tooltip('dispose');
-        this.sqlCell.toTextArea();
-        delete this.sqlCell;
-        this.sqlCell = null;
-      }
-      return Backgrid.Extension.TextareaCell.prototype.remove.apply(this, arguments);
-    },
-  });
-
-  Backgrid.RadioCell = Backgrid.BooleanCell.extend({
-    className: 'radio-cell',
-
-    initialize: function() {
-      Backgrid.BooleanCell.prototype.initialize.apply(this, arguments);
-      Backgrid.Extension.DependentCell.prototype.initialize.apply(this, arguments);
-    },
-
-    dependentChanged: function() {
-      return this.render();
-    },
-
-    enterEditMode: function() {
-      this.$el.addClass('editor');
-      $(this.$el.find('input[type=radio]')).trigger('focus');
-    },
-
-    exitEditMode: function() {
-      this.$el.removeClass('editor');
-    },
-
-    events: {
-      'change input': 'onChange',
-      'blur input': 'exitEditMode',
-    },
-
-    onChange: function(e) {
-      var model = this.model,
-        column = this.column,
-        val = this.formatter.toRaw(this.$input.prop('checked'), model);
-
-      this.enterEditMode();
-
-      _.each(this.model.collection.models, function(sub_model) {
-        sub_model.set(column.get('name'), false);
-        sub_model.trigger('backgrid:edited', sub_model, column, new Backgrid.Command(e));
-      });
-
-      // on bootstrap change we also need to change model's value
-      model.set(column.get('name'), val);
-      model.trigger('backgrid:edited', model, column, new Backgrid.Command(e));
-    },
-
-    render: function () {
-      this.$el.empty();
-      var model = this.model, column = this.column;
-      var editable = Backgrid.callByNeed(column.editable(), column, model);
-      let checked =  this.formatter.fromRaw(model.get(column.get('name')), model);
-      let id = `${column.get('name')}_${_.uniqueId()}`;
-
-      this.$el.empty();
-      this.$el.append(
-        $(`<div style="text-align: center">
-          <input tabindex="0" type="radio" id="${id}" ${!editable?'disabled':''} ${checked?'checked':''}/>
-        </div>`)
-      );
-      this.$input = this.$el.find('input');
-      this.delegateEvents();
-      return this;
-    },
-  });
-
-  return Backgrid;
-});
diff --git a/web/pgadmin/static/js/tree/tree_init.tsx b/web/pgadmin/static/js/tree/tree_init.tsx
index 0b80db060..7a71be2be 100644
--- a/web/pgadmin/static/js/tree/tree_init.tsx
+++ b/web/pgadmin/static/js/tree/tree_init.tsx
@@ -89,8 +89,8 @@ var initBrowserTree = async (pgBrowser) => {
   await treeModelX.root.ensureLoaded();
   var _height = undefined;
 
-  document.getElementsByClassName('wcLayoutPane').forEach((item, index) => {
-    if (index > 0 && $(item).find('#tree').length == 1) {
+  [...document.getElementsByClassName('wcLayoutPane')].forEach((item, index) => {
+    if ($(item).find('#tree').length == 1) {
       _height = item.clientHeight - 30;
     }
   });
diff --git a/web/pgadmin/static/scss/_backform.overrides.scss b/web/pgadmin/static/scss/_backform.overrides.scss
deleted file mode 100644
index 47ff027b6..000000000
--- a/web/pgadmin/static/scss/_backform.overrides.scss
+++ /dev/null
@@ -1,65 +0,0 @@
-.has-error {
-  .pgadmin-controls .form-control {
-    border-color: $color-danger-light;
-  }
-
-  .form-control {
-    border-color: $color-danger;
-  }
-
-  .control-label {
-    color: $color-danger;
-  }
-
-  .control-label::before {
-    font: normal normal normal 16px/1 $font-family-icon;
-    content: "\f071";
-    font-weight: 900;
-    text-decoration: inherit;
-    position: absolute;
-    color: $color-danger;
-    right: 0.5rem;
-    z-index: 1;
-    line-height: inherit;
-  }
-}
-
-.pgadmin-file-has-error {
-  .pgadmin-controls:before {
-    right: 40px !important;
-  }
-}
-
-.pgadmin-datepicker-has-error {
-  .pgadmin-controls:before {
-    right: 50px !important;
-    z-index: 3;
-  }
-}
-.backform-tab .tab-pane {
-	padding: 0.5rem;
-	&.SQL, &.sql-code-control {
-        height: 100%;
-        padding: 0px;
-
-        & .pgadmin-controls.SQL {
-          padding: 0px;
-        }
-	}
-}
-
-.backform-note {
-  border-radius: $border-radius;
-  padding: .25rem;
-  word-wrap: break-word;
-  background: $border-color;
-  color: $color-fg;
-}
-
-.subnode-header label {
-  max-width: 90% !important;
-}
-
-.set-group, .accordian-group {
-  margin-bottom: $form-group-margin-bottom;
-}
diff --git a/web/pgadmin/static/scss/_backgrid.overrides.scss b/web/pgadmin/static/scss/_backgrid.overrides.scss
deleted file mode 100644
index 8b7a90729..000000000
--- a/web/pgadmin/static/scss/_backgrid.overrides.scss
+++ /dev/null
@@ -1,397 +0,0 @@
-.backgrid th, .backgrid td {
-  text-align: left;
-  line-height: $line-height-base;
-}
-
-.backgrid td {
-  font-weight: normal!important;
-  &.editable {
-    & > .display-text {
-      overflow: hidden;
-      text-overflow: ellipsis;
-      @extend .form-control;
-    }
-  }
-}
-
-.backgrid.table th.sortable > button {
-  width: 100%;
-  text-align: left;
-  cursor: pointer;
-}
-
-.backgrid .ascending .sort-caret {
-    border-bottom-color: $color-fg;
-}
-
-.backgrid .descending .sort-caret {
-    border-top-color: $color-fg;
-}
-
-.backgrid.backgrid-striped tbody {
-  & tr:nth-child(even) {
-    background: $table-bg;
-
-    & td.editor {
-      background: $table-bg;
-      outline: none;
-    }
-  }
-  & tr:nth-child(odd) {
-    background: $table-bg;
-    & td.editor {
-      background: $table-bg;
-      outline: none;
-    }
-  }
-}
-.backgrid tbody tr.empty td {
-  display: table-cell;
-  font-style: normal;
-  color: $text-muted;
-}
-
-.backgrid .textarea-cell {
-    text-align: left;
-}
-
-.backgrid .textarea-cell.editor textarea {
-    width: 100%;
-    height: auto;
-}
-
-/* Override Backgrid's default z-index */
-.dashboard-tab-container .backgrid-filter .search {
-  z-index: 10 !important;
-}
-
-.dashboard-tab-container .backgrid-filter .clear {
-  z-index: 10 !important;
-}
-
-.backgrid td.editor {
-  & input[type=text], & input[type=password] {
-    @extend .form-control;
-  }
-}
-
-.backgrid .string-cell.editor input[type=password] {
-  text-align: left;
-}
-
-.backgrid > tbody > td.editor input[type=password] {
-  display: block;
-  width: 100%;
-  height: 100%;
-  padding: 0 5px;
-  margin: 0;
-  background-color: transparent;
-  border: 0;
-  outline: 0;
-  -webkit-box-shadow: none;
-     -moz-box-shadow: none;
-          box-shadow: none;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-  -webkit-appearance: none;
-     -moz-appearance: none;
-}
-
-.backgrid {
-  border-radius: inherit;
-}
-
-.backgrid thead td,
-.backgrid thead th{
-  background: $table-bg;
-  background-color: $table-bg !important;
-  text-align: left;
-}
-
-.backgrid:not(.presentation) td.renderable:not(.editable):not(.delete-cell) {
-    // if transparent border then setting color will help
-    border-bottom-color: $color-gray-lighter;
-}
-
-.backgrid tr.header td.renderable:not(.editable):not(.delete-cell) {
-    background-color: $color-gray-light;
-}
-
-.sql-editor-grid-container .backgrid > thead > th.renderable,
-.sql-editor-grid-container .backgrid > tbody > td.renderable {
-    white-space: pre-wrap;
-}
-
-.backgrid > thead > th.renderable {
-  font-weight: bold;
-}
-
-table.backgrid {
-  position: initial;
-  overflow: auto;
-}
-
-.backgrid td.editor input[type=password] {
-  display: block;
-  width: 100%;
-  height: 100%;
-  padding: 0 5px;
-  margin: 0;
-  background-color: transparent;
-  border: 0;
-  outline: 0;
-  -webkit-box-shadow: none;
-     -moz-box-shadow: none;
-          box-shadow: none;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-  -webkit-appearance: none;
-     -moz-appearance: none;
-}
-
-.backgrid td.editor input[type=password]::-ms-clear {
-  display: none;
-}
-
-.enable-selection, .form-control, .backgrid td, .ajs-content {
-  -webkit-user-select: text;
-  -moz-user-select: text;
-  -ms-user-select: text;
-  user-select: text;
-}
-
-/* Latest backgrid adds column name like `label` to td element, override color*/
-.backgrid td.label {
-  color: $color-fg;
-  font-size: $font-size-base;
-  font-weight: normal;
-}
-
-.backgrid tr:hover {
-  .label {
-    color: $grid-hover-fg-color;
-  }
-}
-
-.subnode {
-  border: $panel-border;
-  background: $color-bg;
-}
-
-.subnode-noouter-border {
-  border: none !important;
-}
-
-.subnode > table.backgrid > thead > tr > th:last-child {
-  border-right-color: $color-primary;
-}
-
-.subnode > table.backgrid {
-    width: 100%;
-    margin: 0px;
-    padding: 0;
-}
-
-.subnode-header button {
-  border-left: 1px solid $border-color;
-  border-bottom-width: 0px !important;
-  border-top-width: 0px !important;
-  border-right-width: 0px !important;
-  border-radius: 0px !important;
-  text-align: center !important;
-  padding: 8px 8px !important;
-  min-height: 31px !important;
-  margin: 0px !important;
-}
-
-.subnode-header .control-label {
-  min-height: 31px;
-  font-weight: bold;
-}
-
-.subnode-footer {
-  text-align: right;
-  border-color: $color-gray-light;
-  border-style: inset inset inset solid;
-  border-width: 2px 1px 0;
-  margin: 0px, 15px;
-  margin-top: -10px;
-  height: 38px;
-  min-height: 40px;
-  vertical-align: bottom;
-}
-.subnode-footer .ajs-button {
-  margin: 2px 2px 0;
-}
-
-
-/* Sub-Node */
-
-.edit-cell, .delete-cell {
-    text-align:center !important;
-    width:25px;
-    height:29px !important;
-}
-
-.subnode-header {
-    background-color: $header-bg;
-    color: $color-fg;
-    border-bottom: $panel-border;
-}
-
-.subnode-header > button.add {
-    float: right;
-    margin-right: 3px;
-    margin-bottom: 3px;
-    margin-top: 5px;
-}
-
-.subnode-dialog {
-    bottom: 0;
-    left: 0;
-    overflow-x: auto;
-    overflow-y: auto;
-    right: 0;
-    height: auto;
-    margin-top: 0px;
-}
-.subnode-body {
-    height: auto;
-    overflow: inherit;
-    background-color: $color-bg;
-    border: 1px solid $border-color;
-    border-radius: $panel-border-radius;
-
-    & .tab-pane {
-      padding: 0.5rem;
-    }
-
-    & .tab-content {
-      padding: 0px;
-    }
-
-    fieldset.inline-fieldset {
-      background: $color-bg;
-    }
-}
-
-.sub-node-form {
-    height: auto;
-    padding-left: 0rem !important;
-    padding-right: 0rem !important;
-}
-
-.sub-node-form > ul.tab-content{
-    background-color: $color-bg;
-    padding-left: 15px;
-    left: 1px;
-}
-
-.subnode-header-form {
-    background-color: $color-gray-lighter;
-    padding: 7px;
-    border-bottom: $panel-border;
-}
-
-.subnode-header-form button.add {
-    float: right;
-    margin-right: 0px;
-}
-
-.subnode-error .help-block {
-    color: $color-danger;
-}
-
-.backgrid tbody {
-  & td.edit-cell.editor {
-    background-color: $color-gray-light !important;
-    border-bottom-color: $color-gray-light !important;
-    outline: none !important;
-  }
-
-  & td.editor {
-    background-color: $color-bg !important;
-    color: $color-fg !important;
-
-    & input {
-        color: $color-fg !important;
-    }
-  }
-
-  & td.edit-cell.editor:focus {
-    outline: $input-focus-border-color auto 5px !important;
-  }
-
-  & td.select-cell.editor select{
-    outline: none !important;
-    height: 100% !important;
-    width: 100% !important;
-  }
-
-  tr.editor-row  {
-    background-color: $color-gray-light !important;
-    & > td {
-      padding: 15px !important;
-      background-color: $color-gray-light !important;
-      border-top: none !important;
-      border-bottom-color: $color-gray-light !important;
-    }
-  }
-
-  tr.warning {
-    background-color: $color-warning !important;
-  }
-
-  tr.alert {
-    background-color: $color-danger !important;
-  }
-}
-
-table tr th button {
-  font-weight: bold;
-}
-
-.custom-control.custom-checkbox.custom-checkbox-no-label {
-   padding-left: 0;
-
-   .custom-control-label {
-     // set same width/height as before and after
-     width: 1em;
-     height: 1em;
-
-     &::before,
-     &::after {
-       left: 0;
-     }
-   }
-}
-
-.backgrid .sql-cell .CodeMirror-scroll {
-  overflow: hidden !important;
-}
-
-.backgrid .sql-cell .cm-s-default {
-  height: 50px !important;
-}
-
-.backgrid .sql-cell .CodeMirror-hscrollbar > div {
-  width: 100% !important;
-}
-
-.backgrid .sql-cell .CodeMirror-hscrollbar {
-  overflow-x: hidden !important;
-}
-
-.backgrid .sql-cell .CodeMirror-vscrollbar {
-  overflow-y: hidden !important;
-}
-
-.backgrid .sql-cell .CodeMirror-sizer {
-  padding-bottom: 0 !important;
-}
-
-.backgrid .sql-cell .CodeMirror-scrollbar-filler {
-  display: none !important;
-}
diff --git a/web/pgadmin/static/scss/pgadmin.scss b/web/pgadmin/static/scss/pgadmin.scss
index e98c58344..4e6311a6c 100644
--- a/web/pgadmin/static/scss/pgadmin.scss
+++ b/web/pgadmin/static/scss/pgadmin.scss
@@ -20,12 +20,10 @@ $theme-colors: (
 @import "bootstrap/scss/bootstrap";
 @import 'webcabin.pgadmin';
 @import 'bootstrap.overrides';
-@import 'backgrid.overrides';
 @import 'tree.overrides';
 @import 'select2.overrides';
 @import 'codemirror.overrides';
 @import 'alert';
-@import 'backform.overrides';
 @import 'pgadmin.grid';
 @import 'pgadmin.style';
 @import 'bootstrap4-toggle.overrides';
diff --git a/web/pgadmin/static/vendor/backform/backform.js b/web/pgadmin/static/vendor/backform/backform.js
deleted file mode 100644
index a1b2316d0..000000000
--- a/web/pgadmin/static/vendor/backform/backform.js
+++ /dev/null
@@ -1,658 +0,0 @@
-/////////////////////////////////////////////////////////////
-//
-// pgAdmin 4 - PostgreSQL Tools
-//
-// Copyright (C) 2013 - 2022, The pgAdmin Development Team
-// This software is released under the PostgreSQL Licence
-//
-//////////////////////////////////////////////////////////////
-
-/*
-  Backform
-  http://github.com/amiliaapp/backform
-
-  Copyright (c) 2014 Amilia Inc.
-  Written by Martin Drapeau
-  Licensed under the MIT @license
- */
-(function(root, factory) {
-
-  // Set up Backform appropriately for the environment. Start with AMD.
-  if (typeof define === 'function' && define.amd) {
-    define(['underscore', 'jquery', 'backbone'], function(underscore, $, Backbone) {
-      // Export global even in AMD case in case this script is loaded with
-      // others that may still expect a global Backform.
-      return factory(root, underscore, $, Backbone);
-    });
-
-  // Next for Node.js or CommonJS. jQuery may not be needed as a module.
-  } else if (typeof exports !== 'undefined') {
-    var _ = require('underscore');
-    factory(root, _, (root.jQuery || root.$ || root.Zepto || root.ender), root.Backbone);
-
-  // Finally, as a browser global.
-  } else {
-    factory(root, root._, (root.jQuery || root.Zepto || root.ender || root.$), root.Backbone);
-  }
-} (this, function(root, _, $, Backbone) {
-
-  // Backform namespace and global options
-  Backform = root.Backform = {
-    // HTML markup global class names. More can be added by individual controls
-    // using _.extend. Look at RadioControl as an example.
-    formClassName: "backform form-inline",
-    groupClassName: "form-group row",
-    controlLabelClassName: "col-sm-2 col-form-label",
-    controlContainerClassName: "col-sm-10",
-    controlsClassName: "col-sm-8",
-    controlClassName: "form-control",
-    controlFormInlineClassName: "form-inline",
-    helpClassName: "form-text",
-    errorClassName: "has-error",
-    helpMessageClassName: "form-text text-muted",
-    hiddenClassName: "d-none",
-    requiredInputClassName: undefined,
-
-    // https://github.com/wyuenho/backgrid/blob/master/lib/backgrid.js
-    resolveNameToClass: function(name, suffix) {
-      if (_.isString(name)) {
-        var key = _.map(name.split('-'), function(e) {
-          return e.slice(0, 1).toUpperCase() + e.slice(1);
-        }).join('') + suffix;
-        var klass = Backform[key];
-        if (_.isUndefined(klass)) {
-          throw new ReferenceError("Class '" + key + "' not found");
-        }
-        return klass;
-      }
-      return name;
-    }
-  };
-
-  // Backform Form view
-  // A collection of field models.
-  Backform.Form = Backbone.View.extend({
-    fields: undefined,
-    errorModel: undefined,
-    tagName: "form",
-    className: function() {
-      return Backform.formClassName;
-    },
-    initialize: function(options) {
-      if (!(options.fields instanceof Backbone.Collection))
-        options.fields = new Fields(options.fields || this.fields);
-      this.fields = options.fields;
-      this.model.errorModel = options.errorModel || this.model.errorModel || new Backbone.Model();
-      this.controls = [];
-    },
-    cleanup: function() {
-      _.each(this.controls, function(c) {
-        c.remove();
-      });
-      this.controls.length = 0;
-    },
-    remove: function() {
-      /* First do the clean up */
-      this.cleanup();
-      Backbone.View.prototype.remove.apply(this, arguments);
-    },
-    render: function() {
-      this.cleanup();
-      this.$el.empty();
-
-      var $form = this.$el,
-          model = this.model,
-          controls = this.controls;
-
-      this.fields.each(function(field) {
-        var control = new (field.get("control"))({
-          field: field,
-          model: model
-        });
-        $form.append(control.render().$el);
-        controls.push(control);
-      });
-
-      return this;
-    }
-  });
-
-  // Converting data to/from Model/DOM.
-  // Stolen directly from Backgrid's CellFormatter.
-  // Source: http://backgridjs.com/ref/formatter.html
-  /**
-     Just a convenient class for interested parties to subclass.
-
-     The default Cell classes don't require the formatter to be a subclass of
-     Formatter as long as the fromRaw(rawData) and toRaw(formattedData) methods
-     are defined.
-
-     @abstract
-     @class Backform.ControlFormatter
-     @constructor
-  */
-  var ControlFormatter = Backform.ControlFormatter = function() {/*This is intentional (SonarQube)*/};
-  _.extend(ControlFormatter.prototype, {
-
-    /**
-       Takes a raw value from a model and returns an optionally formatted string
-       for display. The default implementation simply returns the supplied value
-       as is without any type conversion.
-
-       @member Backform.ControlFormatter
-       @param {*} rawData
-       @param {Backbone.Model} model Used for more complicated formatting
-       @return {*}
-    */
-    fromRaw: function (rawData, model) {
-      return rawData;
-    },
-
-    /**
-       Takes a formatted string, usually from user input, and returns a
-       appropriately typed value for persistence in the model.
-
-       If the user input is invalid or unable to be converted to a raw value
-       suitable for persistence in the model, toRaw must return `undefined`.
-
-       @member Backform.ControlFormatter
-       @param {string} formattedData
-       @param {Backbone.Model} model Used for more complicated formatting
-       @return {*|undefined}
-    */
-    toRaw: function (formattedData, model) {
-      return formattedData;
-    }
-
-  });
-
-  // Store value in DOM as stringified JSON.
-  var JSONFormatter = Backform.JSONFormatter = function() {/*This is intentional (SonarQube)*/};
-  _.extend(JSONFormatter.prototype, {
-    fromRaw: function(rawData, model) {
-      return JSON.stringify(rawData);
-    },
-    toRaw: function(formattedData, model) {
-      return JSON.parse(formattedData);
-    }
-  });
-
-  // Field model and collection
-  //
-  //   A field maps a model attriute to a control for rendering and capturing
-  //   user input.
-  var Field = Backform.Field = Backbone.Model.extend({
-    defaults: {
-      // Name of the model attribute
-      // - It accepts "." nested path (e.g. x.y.z)
-      name: "",
-      // Placeholder for the input
-      placeholder: "",
-      // Disable the input control
-      // (Optional - true/false/function returning boolean)
-      // (Default Value: false)
-      disabled: false,
-      // Make the input control readonly
-      // readonly control can receive focus whereas disabled cannot
-      // (Optional - true/false/function returning boolean)
-      // (Default Value: false)
-      readonly: false,
-      // Visible
-      // (Optional - true/false/function returning boolean)
-      // (Default Value: true)
-      visible: true,
-      // Value Required (validation)
-      // (Optional - true/false/function returning boolean)
-      // (Default Value: true)
-      required: false,
-      // Default value for the field
-      // (Optional)
-      value: undefined,
-      // Control or class name for the control representing this field
-      control: undefined,
-      formatter: undefined
-    },
-    initialize: function(attributes, options) {
-      var control = Backform.resolveNameToClass(this.get("control"), "Control");
-      this.set({control: control}, {silent: true});
-    }
-  });
-
-  var Fields = Backform.Fields = Backbone.Collection.extend({
-    model: Field
-  });
-
-  // Base Control class
-  var Control = Backform.Control = Backbone.View.extend({
-    // Additional field defaults
-    defaults: {},
-    className: function() {
-      return Backform.groupClassName;
-    },
-    events: {
-      'keydown :input': 'processTab'
-    },
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
-      '<div class="<%=Backform.controlContainerClassName%>">',
-      '  <span readonly class="<%=Backform.controlClassName%>" value="<%=value%>">',
-      '</div>'
-    ].join("\n")),
-    initialize: function(options) {
-      // Back-reference to the field
-      this.field = options.field;
-
-      var formatter = Backform.resolveNameToClass(this.field.get("formatter") || this.formatter, "Formatter");
-      if (!_.isFunction(formatter.fromRaw) && !_.isFunction(formatter.toRaw)) {
-        formatter = new formatter();
-      }
-      this.formatter = formatter;
-
-      var attrArr = this.field.get('name').split('.');
-      var name = attrArr.shift();
-
-      // Listen to the field in the model for any change
-      this.listenTo(this.model, "change:" + name, this.render);
-
-      // Listen for the field in the error model for any change
-      if (this.model.errorModel instanceof Backbone.Model)
-        this.listenTo(this.model.errorModel, "change:" + name, this.updateInvalid);
-    },
-    formatter: ControlFormatter,
-    getValueFromDOM: function() {
-      return this.formatter.toRaw(this.$el.find(".uneditable-input").text(), this.model);
-    },
-    onChange: function(e) {
-      var model = this.model,
-          attrArr = this.field.get("name").split('.'),
-          name = attrArr.shift(),
-          path = attrArr.join('.'),
-          value = this.getValueFromDOM(),
-          changes = {};
-
-      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);
-          }
-        }
-      }
-
-      changes[name] = _.isEmpty(path) ? value : _.clone(model.get(name)) || {};
-
-      if (!_.isEmpty(path)) this.keyPathSetter(changes[name], path, value);
-      this.stopListening(this.model, "change:" + name, this.render);
-      model.set(changes);
-      this.listenTo(this.model, "change:" + name, this.render);
-    },
-    render: function() {
-      var field = _.defaults(this.field.toJSON(), this.defaults),
-          attributes = this.model.toJSON(),
-          attrArr = field.name.split('.'),
-          name = attrArr.shift(),
-          path = attrArr.join('.'),
-          rawValue = this.keyPathAccessor(attributes[name], path),
-          data = _.extend(field, {
-            rawValue: rawValue,
-            value: this.formatter.fromRaw(rawValue, this.model),
-            attributes: attributes,
-            formatter: this.formatter
-          }),
-          evalF = function(f, m) {
-            return (_.isFunction(f) ? !!f(m) : !!f);
-          };
-
-      // Evaluate the disabled, visible, and required option
-      _.extend(data, {
-        disabled: evalF(data.disabled, this.model),
-        readonly: evalF(data.readonly, this.model),
-        visible:  evalF(data.visible, this.model),
-        required: evalF(data.required, this.model)
-      });
-
-      // Clean up first
-      this.$el.removeClass(Backform.hiddenClassName);
-
-      if (!data.visible)
-        this.$el.addClass(Backform.hiddenClassName);
-
-      if(Backform.requiredInputClassName) {
-        this.$el.removeClass(Backform.requiredInputClassName);
-      }
-
-      if (data.required) {
-        this.$el.addClass(Backform.requiredInputClassName);
-      }
-
-      this.$el.html(this.template(data)).addClass(field.name);
-      this.updateInvalid();
-
-      return this;
-    },
-    clearInvalid: function() {
-      this.$el.removeClass(Backform.errorClassName)
-        .find("." + Backform.helpClassName + ".error").remove();
-      return this;
-    },
-    updateInvalid: function() {
-      var self = this;
-      var errorModel = this.model.errorModel;
-      if (!(errorModel instanceof Backbone.Model)) return this;
-
-      this.clearInvalid();
-
-      this.$el.find(':input').not('button').each(function(ix, el) {
-        var error = self.keyPathAccessor(errorModel.toJSON(), $(el).attr('name'));
-
-        if (_.isEmpty(error)) return;
-
-        self.$el.addClass(Backform.errorClassName);
-        if (ix === 0) {
-          self.$el
-            .find("." + Backform.controlsClassName)
-            .append('<span class="' + Backform.helpClassName + ' error">' + (_.isArray(error) ? error.join(", ") : error) + '</span>');
-        }
-      });
-
-      return this;
-    },
-    keyPathAccessor: function(obj, path) {
-      var res = obj;
-      path = path.split('.');
-      for (let path_val of path) {
-        if (_.isNull(res)) return null;
-        if (_.isEmpty(path_val)) continue;
-        if (!_.isUndefined(res[path_val])) res = res[path_val];
-      }
-      return _.isObject(res) && !_.isArray(res) ? null : res;
-    },
-    keyPathSetter: function(obj, path, value) {
-      path = path.split('.');
-      while (path.length > 1) {
-        if (!obj[path[0]]) obj[path[0]] = {};
-        obj = obj[path.shift()];
-      }
-      return obj[path.shift()] = value;
-    },
-    processTab: function(e) {
-      if (e.which == 9) {
-        var $target = $(e.currentTarget);
-        setTimeout(function() {
-          var $nextFocus;
-          if (e.shiftKey) {
-            $nextFocus = !!$target.prevAll(':input:visible').length ?
-                         $target.prevAll(':input:visible').first() :
-                         $target.closest('.control-group:visible').prev('.control-group:visible').find(':input:visible');
-          } else {
-            $nextFocus = !!$target.nextAll(':input:visible').length ?
-                         $target.nextAll(':input:visible').first() :
-                         $target.closest('.control-group:visible').next('.control-group:visible').find(':input:visible');
-          }
-
-          if ($nextFocus.length) $nextFocus.first().focus();
-        }, 0);
-      }
-    }
-  });
-
-  // Built-in controls
-
-  Backform.UneditableInputControl = Control;
-
-  Backform.HelpControl = Control.extend({
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>">&nbsp;</label>',
-      '<div class="<%=Backform.controlsClassName%>">',
-      '  <span class="<%=Backform.helpMessageClassName%> help-block"><%=label%></span>',
-      '</div>'
-    ].join("\n"))
-  });
-
-  Backform.SpacerControl = Control.extend({
-    template: _.template([
-      '<div class="<%=Backform.controlsClassName%>"></div>'
-    ].join("\n"))
-  });
-
-  Backform.TextareaControl = Control.extend({
-    defaults: {
-      label: "",
-      maxlength: 4000,
-      extraClasses: [],
-      helpMessage: null
-    },
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
-      '<div class="<%=Backform.controlContainerClassName%>">',
-      '  <textarea class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>" name="<%=name%>" maxlength="<%=maxlength%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly" : ""%> <%=required ? "required" : ""%>><%-value%></textarea>',
-      '  <% if (helpMessage && helpMessage.length) { %>',
-      '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '  <% } %>',
-      '</div>'
-    ].join("\n")),
-    events: _.extend({}, Control.prototype.events, {
-      "change textarea": "onChange",
-      "focus textarea": "clearInvalid"
-    }),
-    getValueFromDOM: function() {
-      return this.formatter.toRaw(this.$el.find("textarea").val(), this.model);
-    }
-  });
-
-  var SelectControl = Backform.SelectControl = Control.extend({
-    defaults: {
-      label: "",
-      options: [], // List of options as [{label:<label>, value:<value>}, ...]
-      extraClasses: []
-    },
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
-      '<div class="<%=Backform.controlContainerClassName%>">',
-      '  <select class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>" name="<%=name%>" value="<%-value%>" <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> >',
-      '    <% for (var i=0; i < options.length; i++) { %>',
-      '      <% var option = options[i]; %>',
-      '      <option value="<%-formatter.fromRaw(option.value)%>" <%=option.value === rawValue ? "selected=\'selected\'" : ""%> <%=option.disabled ? "disabled=\'disabled\'" : ""%>><%-option.label%></option>',
-      '    <% } %>',
-      '  </select>',
-      '</div>'
-    ].join("\n")),
-    events: _.extend({}, Control.prototype.events, {
-      "change select": "onChange",
-      "focus select": "clearInvalid"
-    }),
-    formatter: JSONFormatter,
-    getValueFromDOM: function() {
-      return this.formatter.toRaw(this.$el.find("select").val(), this.model);
-    }
-  });
-
-  // Note: Value here is null or an array. Since jQuery val() returns either.
-  Backform.MultiSelectControl = SelectControl.extend({
-    defaults: {
-      label: "",
-      options: [], // List of options as [{label:<label>, value:<value>}, ...]
-      extraClasses: [],
-      height: '78px'
-    },
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
-      '<div class="<%=Backform.controlsClassName%>">',
-      '  <select multiple="multiple" class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>" name="<%=name%>" value="<%-JSON.stringify(value)%>" <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> style="height:<%=height%>">',
-      '    <% for (var i=0; i < options.length; i++) { %>',
-      '      <% var option = options[i]; %>',
-      '      <option value="<%-option.value%>" <%=value != null && _.indexOf(value, option.value) != -1 ? "selected=\'selected\'" : ""%> <%=option.disabled ? "disabled=\'disabled\'" : ""%>><%-option.label%></option>',
-      '    <% } %>',
-      '  </select>',
-      '</div>'
-    ].join("\n")),
-    events: _.extend({}, Control.prototype.events, {
-      "change select": "onChange",
-      "dblclick select": "onDoubleClick",
-      "focus select": "clearInvalid"
-    }),
-    formatter: {
-      fromRaw: function(rawData, model) {
-        return rawData;
-      },
-      toRaw: function(formattedData, model) {
-        return typeof formattedData == "object" ? formattedData : JSON.parse(formattedData);
-      }
-    },
-    onDoubleClick: function(e) {
-      this.model.trigger('doubleclick', e);
-    }
-  });
-
-  var InputControl = Backform.InputControl = Control.extend({
-    defaults: {
-      type: "text",
-      label: "",
-      maxlength: 255,
-      extraClasses: [],
-      helpMessage: null,
-    },
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
-      '<div class="<%=Backform.controlContainerClassName%>">',
-      '  <input type="<%=type%>" class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>" name="<%=name%>" maxlength="<%=maxlength%>" value="<%-value%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly aria-readonly=true" : ""%> <%=required ? "required" : ""%> />',
-      '  <% if (helpMessage && helpMessage.length) { %>',
-      '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '  <% } %>',
-      '</div>'
-    ].join("\n")),
-    events: _.extend({}, Control.prototype.events, {
-      "change input": "onChange",
-      "focus input": "clearInvalid"
-    }),
-    getValueFromDOM: function() {
-      return this.formatter.toRaw(this.$el.find("input").val(), this.model);
-    }
-  });
-
-  var BooleanControl = Backform.BooleanControl = InputControl.extend({
-    defaults: {
-      type: "checkbox",
-      label: "",
-      controlLabel: '&nbsp;',
-      extraClasses: [],
-      id: _.uniqueId('bf_')
-    },
-    template: _.template([
-      '<div class="<%=Backform.controlLabelClassName%>"><%=controlLabel%></div>',
-      '<div class="<%=Backform.controlContainerClassName%>">',
-      '  <div class="custom-control custom-checkbox <%= (label && label.length)?"":"custom-checkbox-no-label" %>">',
-      '    <input type="<%=type%>" id="<%=cId%>" class="custom-control-input <%=extraClasses.join(\' \')%>" name="<%=name%>" <%=value ? "checked=\'checked\'" : ""%> <%=disabled ? "disabled" : ""%> <%=readonly ? "readonly" : ""%> <%=required ? "required" : ""%> />',
-      '    <% if (label && label.length) { %>',
-      '       <label class="custom-control-label" for="<%=cId%>"><%=label%></label>',
-      '    <% } else { %>',
-      '       <label class="custom-control-label" for="<%=cId%>"><span class="sr-only"><%=controlLabel%></span></label>',
-      '    <% } %>',
-      '  </div>',
-      '</div>'
-    ].join("\n")),
-    getValueFromDOM: function() {
-      return this.formatter.toRaw(this.$el.find("input").is(":checked"), this.model);
-    }
-  });
-
-  Backform.CheckboxControl = BooleanControl;
-
-  Backform.RadioControl = InputControl.extend({
-    defaults: {
-      type: "radio",
-      label: "",
-      options: [],
-      extraClasses: [],
-      helpMessage: null
-    },
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>',
-      '<div class="<%=Backform.controlContainerClassName%> d-flex">',
-      '  <% for (var i=0; i < options.length; i++) { %>',
-      '    <% var option = options[i]; %>',
-      '    <% var id = _.uniqueId("bf_"); %>',
-      '  <div class="custom-control custom-radio">',
-      '    <input type="<%=type%>" class="custom-control-input <%=extraClasses.join(\' \')%>" id="<%=cId%><%=i%>" name="<%=name%>" value="<%-formatter.fromRaw(option.value)%>" <%=rawValue == option.value ? "checked=\'checked\'" : ""%> <%=disabled ? "disabled" : ""%> <%=readonly ? "disabled" : ""%> <%=required ? "required" : ""%> />',
-      '    <label class="custom-control-label" for="<%=cId%><%=i%>"><%-option.label%></label>',
-      '  </div>',
-      '  <% } %>',
-      '  <% if (helpMessage && helpMessage.length) { %>',
-      '    <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
-      '  <% } %>',
-      '</div>'
-    ].join("\n")),
-    formatter: JSONFormatter,
-    getValueFromDOM: function() {
-      return this.formatter.toRaw(this.$el.find("input:checked").val(), this.model);
-    },
-    bootstrap2: function() {
-      Backform.radioControlsClassName = "controls";
-      Backform.radioLabelClassName = "radio inline";
-    }
-  });
-  _.extend(Backform, {
-    radioControlsClassName: "checkbox",
-    radioLabelClassName: "checkbox-inline"
-  });
-
-  // Requires the Bootstrap Datepicker to work.
-  Backform.DatepickerControl = InputControl.extend({
-    defaults: {
-      type: "text",
-      label: "",
-      options: {},
-      extraClasses: [],
-      maxlength: 255,
-      helpMessage: null
-    },
-    events: _.extend({}, Control.prototype.events, {
-      "blur input": "onChange",
-      "change input": "onChange",
-      "changeDate input": "onChange",
-      "focus input": "clearInvalid"
-    }),
-    render: function() {
-      InputControl.prototype.render.apply(this, arguments);
-      this.$el.find("input").datepicker(this.field.get("options"));
-      return this;
-    }
-  });
-
-  Backform.ButtonControl = Control.extend({
-    defaults: {
-      type: "submit",
-      label: "Submit",
-      status: undefined, // error or success
-      message: undefined,
-      extraClasses: []
-    },
-    template: _.template([
-      '<label class="<%=Backform.controlLabelClassName%>">&nbsp;</label>',
-      '<div class="<%=Backform.controlsClassName%>">',
-      '  <button type="<%=type%>" name="<%=name%>" class="btn <%=extraClasses.join(\' \')%>" <%=disabled ? "disabled" : ""%> ><%=label%></button>',
-      '  <% var cls = ""; if (status == "error") cls = Backform.buttonStatusErrorClassName; if (status == "success") cls = Backform.buttonStatusSuccessClassname; %>',
-      '  <span class="status <%=cls%>"><%=message%></span>',
-      '</div>'
-    ].join("\n")),
-    initialize: function() {
-      Control.prototype.initialize.apply(this, arguments);
-      this.listenTo(this.field, "change:status", this.render);
-      this.listenTo(this.field, "change:message", this.render);
-    },
-    bootstrap2: function() {
-      Backform.buttonStatusErrorClassName = "text-error";
-      Backform.buttonStatusSuccessClassname = "text-success";
-    }
-  });
-  _.extend(Backform, {
-    buttonStatusErrorClassName: "text-danger",
-    buttonStatusSuccessClassname: "text-success"
-  });
-
-  return Backform;
-
-}));
diff --git a/web/pgadmin/static/vendor/backgrid/backgrid-select-all.css b/web/pgadmin/static/vendor/backgrid/backgrid-select-all.css
deleted file mode 100644
index 70bcc2d5b..000000000
--- a/web/pgadmin/static/vendor/backgrid/backgrid-select-all.css
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
-  backgrid-select-all
-  http://github.com/wyuenho/backgrid
-
-  Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
-  Licensed under the MIT @license.
-*/
-
-.backgrid .select-row-cell,
-.backgrid .select-all-header-cell {
-  text-align: center;
-}
\ No newline at end of file
diff --git a/web/pgadmin/static/vendor/backgrid/backgrid-select-all.js b/web/pgadmin/static/vendor/backgrid/backgrid-select-all.js
deleted file mode 100644
index 46cbbb029..000000000
--- a/web/pgadmin/static/vendor/backgrid/backgrid-select-all.js
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
-  backgrid-select-all
-  http://github.com/wyuenho/backgrid
-
-  Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
-  Licensed under the MIT @license.
-*/
-(function (root, factory) {
-  if (typeof define === 'function' && define.amd) {
-    // AMD. Register as an anonymous module.
-    define(["backbone", "backgrid", "underscore", "sources/gettext"], factory);
-  } else if (typeof exports == "object") {
-    // CommonJS
-    module.exports = factory(require("backbone"), require("backgrid"), require("underscore"));
-  }
-  // Browser
-  else factory(root.Backbone, root.Backgrid, root._);
-
-}(this, function (Backbone, Backgrid, _, gettext) {
-
-  "use strict";
-
-  /**
-     Renders a checkbox for row selection.
-
-     @class Backgrid.Extension.SelectRowCell
-     @extends Backbone.View
-  */
-  var SelectRowCell = Backgrid.Extension.SelectRowCell = Backbone.View.extend({
-
-    /** @property */
-    className: "select-row-cell",
-
-    /** @property */
-    tagName: "td",
-
-    /** @property */
-    events: {
-      "keydown input[type=checkbox]": "onKeydown",
-      "change input[type=checkbox]": "onChange",
-      "click input[type=checkbox]": "enterEditMode"
-    },
-
-    /**
-       Initializer. If the underlying model triggers a `select` event, this cell
-       will change its checked value according to the event's `selected` value.
-
-       @param {Object} options
-       @param {Backgrid.Column} options.column
-       @param {Backbone.Model} options.model
-    */
-    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");
-
-      this.listenTo(model, "backgrid:select", function (mod, selected) {
-        this.checkbox().prop("checked", selected).change();
-      });
-    },
-
-    /**
-       Returns the checkbox.
-     */
-    checkbox: function () {
-      return this.$el.find("input[type=checkbox]");
-    },
-
-    /**
-       Focuses the checkbox.
-    */
-    enterEditMode: function () {
-      this.checkbox().focus();
-    },
-
-    /**
-       Unfocuses the checkbox.
-    */
-    exitEditMode: function () {
-      this.checkbox().blur();
-    },
-
-    /**
-       Process keyboard navigation.
-    */
-    onKeydown: function (e) {
-      var command = new Backgrid.Command(e);
-      if (command.passThru()) return true; // skip ahead to `change`
-      else if (command.save() || command.moveLeft() || command.moveRight() ||
-               command.moveUp() || command.moveDown()) {
-
-        if(this.model) {
-          e.preventDefault();
-          e.stopPropagation();
-          this.model.trigger("backgrid:edited", this.model, this.column, command);
-        }
-      }
-    },
-
-    /**
-       When the checkbox's value changes, this method will trigger a Backbone
-       `backgrid:selected` event with a reference of the model and the
-       checkbox's `checked` value.
-    */
-    onChange: function () {
-      var checked = this.checkbox().prop("checked");
-      this.$el.parent().toggleClass("selected", checked);
-      this.model.trigger("backgrid:selected", this.model, checked);
-    },
-
-    /**
-       Renders a checkbox in a table cell.
-    */
-    render: function () {
-      var id = 'selectall-' + _.uniqueId(this.column.get('name'));
-      this.$el.empty().append([
-        '<div class="custom-control custom-checkbox custom-checkbox-no-label">',
-        '  <input tabindex="0" type="checkbox" class="custom-control-input" id="'+ id +'" />',
-        '  <label class="custom-control-label" for="'+ id +'">',
-        '    <span class="sr-only">' + gettext('Select All') + '<span>',
-        '  </label>',
-        '</div>'
-      ].join('\n'));
-      this.delegateEvents();
-      return this;
-    }
-
-  });
-
-  /**
-     Renders a checkbox to select all rows on the current page.
-
-     @class Backgrid.Extension.SelectAllHeaderCell
-     @extends Backgrid.Extension.SelectRowCell
-  */
-  var SelectAllHeaderCell = Backgrid.Extension.SelectAllHeaderCell = SelectRowCell.extend({
-
-    /** @property */
-    className: "select-all-header-cell",
-
-    /** @property */
-    tagName: "th",
-
-
-
-    /**
-       Initializer. When this cell's checkbox is checked, a Backbone
-       `backgrid:select` event will be triggered for each model for the current
-       page in the underlying collection. If a `SelectRowCell` instance exists
-       for the rows representing the models, they will check themselves. If any
-       of the SelectRowCell instances trigger a Backbone `backgrid:selected`
-       event with a `false` value, this cell will uncheck its checkbox. In the
-       event of a Backbone `backgrid:refresh` event, which is triggered when the
-       body refreshes its rows, which can happen under a number of conditions
-       such as paging or the columns were reset, this cell will still remember
-       the previously selected models and trigger a Backbone `backgrid:select`
-       event on them such that the SelectRowCells can recheck themselves upon
-       refreshing.
-
-       @param {Object} options
-       @param {Backgrid.Column} options.column
-       @param {Backbone.Collection} options.collection
-    */
-    initialize: function (options) {
-
-      this.column = options.column;
-      if (!(this.column instanceof Backgrid.Column)) {
-        this.column = new Backgrid.Column(this.column);
-      }
-
-      var collection = this.collection;
-      var selectedModels = this.selectedModels = {};
-      this.listenTo(collection.fullCollection || collection,
-                    "backgrid:selected", function (model, selected) {
-        if (selected) selectedModels[model.id || model.cid] = 1;
-        else {
-          delete selectedModels[model.id || model.cid];
-          this.checkbox().prop("checked", false);
-        }
-        if (_.keys(selectedModels).length === (collection.fullCollection|| collection).length) {
-          this.checkbox().prop("checked", true);
-        }
-      });
-
-      this.listenTo(collection.fullCollection || collection, "remove", function (model) {
-        delete selectedModels[model.id || model.cid];
-        if ((collection.fullCollection || collection).length === 0) {
-          this.checkbox().prop("checked", false);
-        }
-      });
-
-      this.listenTo(collection, "backgrid:refresh", function () {
-        if ((collection.fullCollection || collection).length === 0) {
-          this.checkbox().prop("checked", false);
-        }
-        else {
-          var checked = this.checkbox().prop("checked");
-          for (var i = 0; i < collection.length; i++) {
-            var model = collection.at(i);
-            if (checked || selectedModels[model.id || model.cid]) {
-              model.trigger("backgrid:select", model, true);
-            }
-          }
-        }
-      });
-
-      var column = this.column, $el = this.$el;
-      this.listenTo(column, "change:renderable", function (col, renderable) {
-        $el.toggleClass("renderable", renderable);
-      });
-
-      if (Backgrid.callByNeed(column.renderable(), column, collection)) $el.addClass("renderable");
-    },
-
-    /**
-       Propagates the checked value of this checkbox to all the models of the
-       underlying collection by triggering a Backbone `backgrid:select` event on
-       the models on the current page, passing each model and the current
-       `checked` value of the checkbox in each event.
-
-       A `backgrid:selected` event will also be triggered with the current
-       `checked` value on all the models regardless of whether they are on the
-       current page.
-
-       This method triggers a 'backgrid:select-all' event on the collection
-       afterwards.
-    */
-    onChange: function () {
-      var checked = this.checkbox().prop("checked");
-
-      var collection = this.collection;
-      collection.each(function (model) {
-        model.trigger("backgrid:select", model, checked);
-      });
-
-      if (collection.fullCollection) {
-        collection.fullCollection.each(function (model) {
-          if (!collection.get(model.cid)) {
-            model.trigger("backgrid:selected", model, checked);
-          }
-        });
-      }
-
-      this.collection.trigger("backgrid:select-all", this.collection, checked);
-    }
-
-  });
-
-  /**
-     Convenient method to retrieve a list of selected models. This method only
-     exists when the `SelectAll` extension has been included. Selected models
-     are retained across pagination.
-
-     @member Backgrid.Grid
-     @return {Array.<Backbone.Model>}
-  */
-  Backgrid.Grid.prototype.getSelectedModels = function () {
-    var selectAllHeaderCell;
-    var headerCells = this.header.row.cells;
-    for (var i = 0, l = headerCells.length; i < l; i++) {
-      var headerCell = headerCells[i];
-      if (headerCell instanceof SelectAllHeaderCell) {
-        selectAllHeaderCell = headerCell;
-        break;
-      }
-    }
-
-    var result = [];
-    if (selectAllHeaderCell) {
-      var selectedModels = selectAllHeaderCell.selectedModels;
-      var collection = this.collection.fullCollection || this.collection;
-      for (var modelId in selectedModels) {
-        result.push(collection.get(modelId));
-      }
-    }
-
-    return result;
-  };
-
-  /**
-     Convenient method to deselect the selected models. This method is only
-     available when the `SelectAll` extension has been included.
-
-     @member Backgrid.Grid
-   */
-  Backgrid.Grid.prototype.clearSelectedModels = function () {
-    var selectedModels = this.getSelectedModels();
-    for (var i = 0, l = selectedModels.length; i < l; i++) {
-      var model = selectedModels[i];
-      model.trigger("backgrid:select", model, false);
-    }
-  };
-
-}));
diff --git a/web/pgadmin/static/vendor/backgrid/backgrid.css b/web/pgadmin/static/vendor/backgrid/backgrid.css
deleted file mode 100644
index a8cef8c3d..000000000
--- a/web/pgadmin/static/vendor/backgrid/backgrid.css
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
-  backgrid
-  http://github.com/cloudflare/backgrid
-
-  Copyright (c) 2013-present Cloudflare, Inc. and contributors
-  Licensed under the MIT license.
-*/
-
-.backgrid-container {
-  position: relative;
-  display: block;
-  width: 100%;
-  height: 465px;
-  padding: 0;
-  overflow: auto;
-  border: 0;
-}
-
-.backgrid {
-  width: 100%;
-  max-width: 100%;
-  background-color: transparent;
-  border-collapse: collapse;
-  -webkit-border-radius: 4px;
-     -moz-border-radius: 4px;
-          border-radius: 4px;
-}
-
-.backgrid th,
-.backgrid td {
-  display: none;
-  height: 20px;
-  max-width: 250px;
-  padding: 4px 5px;
-  overflow: hidden;
-  line-height: 20px;
-  text-align: left;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  vertical-align: middle;
-  border-bottom: 1px solid #DDD;
-}
-
-.backgrid th.renderable,
-.backgrid td.renderable {
-  display: table-cell;
-}
-
-.backgrid th {
-  font-weight: bold;
-  text-align: center;
-}
-
-.backgrid th.sortable a {
-  text-decoration: none;
-  white-space: nowrap;
-  cursor: pointer;
-}
-
-.backgrid thead th {
-  vertical-align: bottom;
-  background-color: #f9f9f9;
-}
-
-.backgrid thead th a {
-  display: block;
-}
-
-.backgrid.backgrid-striped tbody tr:nth-child(even) {
-  background-color: #f9f9f9;
-}
-
-.backgrid tbody tr.empty {
-  font-style: italic;
-  color: gray;
-}
-
-.backgrid tbody tr.empty td {
-  display: inherit;
-  text-align: center;
-}
-
-.backgrid td.editor,
-.backgrid tbody tr:nth-child(odd) td.editor {
-  background-color: rgba(82, 168, 236, 0.1);
-  outline: 1px solid rgba(82, 168, 236, 0.8);
-  outline-offset: -1px;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-  -webkit-transition-duration: 200ms;
-     -moz-transition-duration: 200ms;
-       -o-transition-duration: 200ms;
-          transition-duration: 200ms;
-  -webkit-transition-property: width, outline, background-color;
-     -moz-transition-property: width, outline, background-color;
-       -o-transition-property: width, outline, background-color;
-          transition-property: width, outline, background-color;
-  -webkit-transition-timing-function: ease-in-out;
-     -moz-transition-timing-function: ease-in-out;
-       -o-transition-timing-function: ease-in-out;
-          transition-timing-function: ease-in-out;
-}
-
-.backgrid td.editor input[type=text] {
-  display: block;
-  width: 100%;
-  height: 100%;
-  padding: 0 5px;
-  margin: 0;
-  background-color: transparent;
-  border: 0;
-  outline: 0;
-  -webkit-box-shadow: none;
-     -moz-box-shadow: none;
-          box-shadow: none;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-  -webkit-appearance: none;
-     -moz-appearance: none;
-}
-
-.backgrid td.editor input[type=text]::-ms-clear {
-  display: none;
-}
-
-.backgrid td.error,
-.backgrid tbody tr:nth-child(odd) td.error {
-  background-color: rgba(255, 210, 77, 0.1);
-  outline: 1px solid #ffd24d;
-}
-
-.backgrid td.editor :focus,
-.backgrid th.editor :focus {
-  outline: 0;
-}
-
-.backgrid .sort-caret {
-  display: inline-block;
-  width: 0;
-  height: 0;
-  margin-left: 0.3em;
-  border: 0;
-  content: "";
-}
-
-.backgrid .ascending .sort-caret {
-  vertical-align: baseline;
-  border-top: none;
-  border-right: 4px solid transparent;
-  border-bottom: 4px solid #000000;
-  border-left: 4px solid transparent;
-}
-
-.backgrid .descending .sort-caret {
-  vertical-align: super;
-  border-top: 4px solid #000000;
-  border-right: 4px solid transparent;
-  border-bottom: none;
-  border-left: 4px solid transparent;
-}
-
-.backgrid .string-cell,
-.backgrid .uri-cell,
-.backgrid .email-cell,
-.backgrid .string-cell.editor input[type=text],
-.backgrid .uri-cell.editor input[type=text],
-.backgrid .email-cell.editor input[type=text] {
-  text-align: left;
-}
-
-.backgrid .date-cell,
-.backgrid .time-cell,
-.backgrid .datetime-cell,
-.backgrid .number-cell,
-.backgrid .integer-cell,
-.backgrid .percent-cell,
-.backgrid .date-cell.editor input[type=text],
-.backgrid .time-cell.editor input[type=text],
-.backgrid .datetime-cell.editor input[type=text],
-.backgrid .number-cell.editor input[type=text],
-.backgrid .integer-cell.editor input[type=text],
-.backgrid .percent-cell.editor input[type=text] {
-  text-align: right;
-}
-
-.backgrid .boolean-cell,
-.backgrid .boolean-cell.editor input[type=checkbox] {
-  text-align: center;
-}
-
-.backgrid .select-cell {
-  text-align: center;
-}
-
-.backgrid .select-cell.editor {
-  padding: 0;
-}
-
-.backgrid .select-cell.editor select {
-  display: block;
-  width: 100%;
-  height: 28px;
-  padding: 4px 5px;
-  margin: 0;
-  line-height: 28px;
-  vertical-align: middle;
-  background-color: white;
-  border: 0;
-  outline: 0;
-  -webkit-box-shadow: none;
-     -moz-box-shadow: none;
-          box-shadow: none;
-  -webkit-box-sizing: border-box;
-     -moz-box-sizing: border-box;
-          box-sizing: border-box;
-}
-
-.backgrid .select-cell.editor select[multiple] {
-  height: auto;
-}
-
-.backgrid .select-cell.editor :focus {
-  border: 0;
-  outline: 0;
-}
-
-.backgrid .select-cell.editor select::-moz-focus-inner,
-.backgrid .select-cell.editor optgroup::-moz-focus-inner,
-.backgrid .select-cell.editor option::-moz-focus-inner,
-.backgrid .select-cell.editor select::-o-focus-inner,
-.backgrid .select-cell.editor optgroup::-o-focus-inner,
-.backgrid .select-cell.editor option::-o-focus-inner {
-  border: 0;
-}
diff --git a/web/pgadmin/static/vendor/backgrid/backgrid.js b/web/pgadmin/static/vendor/backgrid/backgrid.js
deleted file mode 100644
index 2da4327d6..000000000
--- a/web/pgadmin/static/vendor/backgrid/backgrid.js
+++ /dev/null
@@ -1,3011 +0,0 @@
-/*!
-  backgrid 0.3.8
-  http://github.com/cloudflare/backgrid
-
-  Copyright (c) 2017 Cloudflare, Inc. and contributors <jwong@cloudflare.com>
-  Licensed under the MIT license.
-*/
-
-(function (root, factory) {
-
-  if (typeof define === "function" && define.amd) {
-    // AMD (+ global for extensions)
-    define(["underscore", "backbone"], function (_, Backbone) {
-      return (root.Backgrid = factory(_, Backbone));
-    });
-  } else if (typeof exports === "object") {
-    // CommonJS
-    module.exports = factory(require("underscore"), require("backbone"));
-  } else {
-    // Browser
-    root.Backgrid = factory(root._, root.Backbone);
-  }}(this, function (_, Backbone) {
-
-  "use strict";
-
-/*
-  backgrid
-  http://github.com/cloudflare/backgrid
-
-  Copyright (c) 2013-present Cloudflare, Inc. and contributors
-  Licensed under the MIT license.
-*/
-
-// Copyright 2009, 2010 Kristopher Michael Kowal
-// https://github.com/kriskowal/es5-shim
-// ES5 15.5.4.20
-// http://es5.github.com/#x15.5.4.20
-var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
-  "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
-  "\u2029\uFEFF";
-if (!String.prototype.trim || ws.trim()) {
-  // http://blog.stevenlevithan.com/archives/faster-trim-javascript
-  // http://perfectionkills.com/whitespace-deviations/
-  ws = "[" + ws + "]";
-  var trimBeginRegexp = new RegExp("^" + ws + ws + "*"),
-  trimEndRegexp = new RegExp(ws + ws + "*$");
-  String.prototype.trim = function trim() {
-    if (this === undefined || this === null) {
-      throw new TypeError("can't convert " + this + " to object");
-    }
-    return String(this)
-      .replace(trimBeginRegexp, "")
-      .replace(trimEndRegexp, "");
-  };
-}
-
-function lpad(str, length, padstr) {
-  var paddingLen = length - (str + '').length;
-  paddingLen =  paddingLen < 0 ? 0 : paddingLen;
-  var padding = '';
-  for (var i = 0; i < paddingLen; i++) {
-    padding = padding + padstr;
-  }
-  return padding + str;
-}
-
-var $ = Backbone.$;
-
-var Backgrid = {
-
-  Extension: {},
-
-  resolveNameToClass: function (name, suffix) {
-    if (_.isString(name)) {
-      var key = _.map(name.split('-'), function (e) {
-        return e.slice(0, 1).toUpperCase() + e.slice(1);
-      }).join('') + suffix;
-      var klass = Backgrid[key] || Backgrid.Extension[key];
-      if (_.isUndefined(klass)) {
-        throw new ReferenceError("Class '" + key + "' not found");
-      }
-      return klass;
-    }
-
-    return name;
-  },
-
-  callByNeed: function () {
-    var value = arguments[0];
-    if (!_.isFunction(value)) return value;
-
-    var context = arguments[1];
-    var args = [].slice.call(arguments, 2);
-    return value.apply(context, !!(args + '') ? args : []);
-  }
-
-};
-_.extend(Backgrid, Backbone.Events);
-
-/**
-   Command translates a DOM Event into commands that Backgrid
-   recognizes. Interested parties can listen on selected Backgrid events that
-   come with an instance of this class and act on the commands.
-
-   It is also possible to globally rebind the keyboard shortcuts by replacing
-   the methods in this class' prototype.
-
-   @class Backgrid.Command
-   @constructor
- */
-var Command = Backgrid.Command = function (evt) {
-  _.extend(this, {
-    altKey: !!evt.altKey,
-    "char": evt["char"],
-    charCode: evt.charCode,
-    ctrlKey: !!evt.ctrlKey,
-    key: evt.key,
-    keyCode: evt.keyCode,
-    locale: evt.locale,
-    location: evt.location,
-    metaKey: !!evt.metaKey,
-    repeat: !!evt.repeat,
-    shiftKey: !!evt.shiftKey,
-    which: evt.which
-  });
-};
-_.extend(Command.prototype, {
-  /**
-     Up Arrow
-
-     @member Backgrid.Command
-   */
-  moveUp: function () { return this.keyCode == 38; },
-  /**
-     Down Arrow
-
-     @member Backgrid.Command
-   */
-  moveDown: function () { return this.keyCode === 40; },
-  /**
-     Shift Tab
-
-     @member Backgrid.Command
-   */
-  moveLeft: function () { return this.shiftKey && this.keyCode === 9; },
-  /**
-     Tab
-
-     @member Backgrid.Command
-   */
-  moveRight: function () { return !this.shiftKey && this.keyCode === 9; },
-  /**
-     Enter
-
-     @member Backgrid.Command
-   */
-  save: function () { return this.keyCode === 13; },
-  /**
-     Esc
-
-     @member Backgrid.Command
-   */
-  cancel: function () { return this.keyCode === 27; },
-  /**
-     None of the above.
-
-     @member Backgrid.Command
-   */
-  passThru: function () {
-    return !(this.moveUp() || this.moveDown() || this.moveLeft() ||
-             this.moveRight() || this.save() || this.cancel());
-  }
-});
-
-/*
-  backgrid
-  http://github.com/cloudflare/backgrid
-
-  Copyright (c) 2013-present Cloudflare, Inc. and contributors
-  Licensed under the MIT license.
-*/
-
-/**
-   Just a convenient class for interested parties to subclass.
-
-   The default Cell classes don't require the formatter to be a subclass of
-   Formatter as long as the fromRaw(rawData) and toRaw(formattedData) methods
-   are defined.
-
-   @abstract
-   @class Backgrid.CellFormatter
-   @constructor
-*/
-var CellFormatter = Backgrid.CellFormatter = function () {/*This is intentional (SonarQube)*/};
-_.extend(CellFormatter.prototype, {
-
-  /**
-     Takes a raw value from a model and returns an optionally formatted string
-     for display. The default implementation simply returns the supplied value
-     as is without any type conversion.
-
-     @member Backgrid.CellFormatter
-     @param {*} rawData
-     @param {Backbone.Model} model Used for more complicated formatting
-     @return {*}
-  */
-  fromRaw: function (rawData, model) {
-    return rawData;
-  },
-
-  /**
-     Takes a formatted string, usually from user input, and returns a
-     appropriately typed value for persistence in the model.
-
-     If the user input is invalid or unable to be converted to a raw value
-     suitable for persistence in the model, toRaw must return `undefined`.
-
-     @member Backgrid.CellFormatter
-     @param {string} formattedData
-     @param {Backbone.Model} model Used for more complicated formatting
-     @return {*|undefined}
-  */
-  toRaw: function (formattedData, model) {
-    return formattedData;
-  }
-
-});
-
-/**
-   A floating point number formatter. Doesn't understand scientific notation at
-   the moment.
-
-   @class Backgrid.NumberFormatter
-   @extends Backgrid.CellFormatter
-   @constructor
-   @throws {RangeError} If decimals < 0 or > 20.
-*/
-var NumberFormatter = Backgrid.NumberFormatter = function (options) {
-  _.extend(this, this.defaults, options || {});
-
-  if (this.decimals < 0 || this.decimals > 20) {
-    throw new RangeError("decimals must be between 0 and 20");
-  }
-};
-NumberFormatter.prototype = new CellFormatter();
-_.extend(NumberFormatter.prototype, {
-
-  /**
-     @member Backgrid.NumberFormatter
-     @cfg {Object} options
-
-     @cfg {number} [options.decimals=2] Number of decimals to display. Must be an integer.
-
-     @cfg {string} [options.decimalSeparator='.'] The separator to use when
-     displaying decimals.
-
-     @cfg {string} [options.orderSeparator=','] The separator to use to
-     separator thousands. May be an empty string.
-   */
-  defaults: {
-    decimals: 2,
-    decimalSeparator: '.',
-    orderSeparator: ','
-  },
-
-  HUMANIZED_NUM_RE: /(\d)(?=(?:\d{3})+$)/g,
-
-  /**
-     Takes a floating point number and convert it to a formatted string where
-     every thousand is separated by `orderSeparator`, with a `decimal` number of
-     decimals separated by `decimalSeparator`. The number returned is rounded
-     the usual way.
-
-     @member Backgrid.NumberFormatter
-     @param {number} number
-     @param {Backbone.Model} model Used for more complicated formatting
-     @return {string}
-  */
-  fromRaw: function (number, model) {
-    if (_.isNull(number) || _.isUndefined(number)) return '';
-
-    number = parseFloat(number).toFixed(~~this.decimals);
-
-    var parts = number.split('.');
-    var integerPart = parts[0];
-    var decimalPart = parts[1] ? (this.decimalSeparator || '.') + parts[1] : '';
-
-    return integerPart.replace(this.HUMANIZED_NUM_RE, '$1' + this.orderSeparator) + decimalPart;
-  },
-
-  /**
-     Takes a string, possibly formatted with `orderSeparator` and/or
-     `decimalSeparator`, and convert it back to a number.
-
-     @member Backgrid.NumberFormatter
-     @param {string} formattedData
-     @param {Backbone.Model} model Used for more complicated formatting
-     @return {number|undefined} Undefined if the string cannot be converted to
-     a number.
-  */
-  toRaw: function (formattedData, model) {
-    formattedData = formattedData.trim();
-
-    if (formattedData === '') return null;
-
-    var rawData = '';
-
-    var thousands = formattedData.split(this.orderSeparator);
-    for (let thousand_val of thousands) {
-      rawData += thousand_val;
-    }
-
-    var decimalParts = rawData.split(this.decimalSeparator);
-    rawData = '';
-    for (let decimal_val of decimalParts) {
-      rawData = rawData + decimal_val + '.';
-    }
-
-    if (rawData[rawData.length - 1] === '.') {
-      rawData = rawData.slice(0, rawData.length - 1);
-    }
-
-    var result = (rawData * 1).toFixed(~~this.decimals) * 1;
-    if (_.isNumber(result) && !_.isNaN(result)) return result;
-  }
-
-});
-
-/**
-   A number formatter that converts a floating point number, optionally
-   multiplied by a multiplier, to a percentage string and vice versa.
-
-   @class Backgrid.PercentFormatter
-   @extends Backgrid.NumberFormatter
-   @constructor
-   @throws {RangeError} If decimals < 0 or > 20.
- */
-var PercentFormatter = Backgrid.PercentFormatter = function () {
-  Backgrid.NumberFormatter.apply(this, arguments);
-};
-
-PercentFormatter.prototype = new Backgrid.NumberFormatter();
-
-_.extend(PercentFormatter.prototype, {
-
-  /**
-     @member Backgrid.PercentFormatter
-     @cfg {Object} options
-
-     @cfg {number} [options.multiplier=1] The number used to multiply the model
-     value for display.
-
-     @cfg {string} [options.symbol='%'] The symbol to append to the percentage
-     string.
-   */
-  defaults: _.extend({}, NumberFormatter.prototype.defaults, {
-    multiplier: 1,
-    symbol: "%"
-  }),
-
-  /**
-     Takes a floating point number, where the number is first multiplied by
-     `multiplier`, then converted to a formatted string like
-     NumberFormatter#fromRaw, then finally append `symbol` to the end.
-
-     @member Backgrid.PercentFormatter
-     @param {number} rawValue
-     @param {Backbone.Model} model Used for more complicated formatting
-     @return {string}
-  */
-  fromRaw: function (number, model) {
-    var args = [].slice.call(arguments, 1);
-    args.unshift(number * this.multiplier);
-    return (NumberFormatter.prototype.fromRaw.apply(this, args) || "0") + this.symbol;
-  },
-
-  /**
-     Takes a string, possibly appended with `symbol` and/or `decimalSeparator`,
-     and convert it back to a number for the model like NumberFormatter#toRaw,
-     and then dividing it by `multiplier`.
-
-     @member Backgrid.PercentFormatter
-     @param {string} formattedData
-     @param {Backbone.Model} model Used for more complicated formatting
-     @return {number|undefined} Undefined if the string cannot be converted to
-     a number.
-  */
-  toRaw: function (formattedValue, model) {
-    var tokens = formattedValue.split(this.symbol);
-    if (tokens && tokens[0] && tokens[1] === "" || tokens[1] == null) {
-      var rawValue = NumberFormatter.prototype.toRaw.call(this, tokens[0]);
-      if (_.isUndefined(rawValue)) return rawValue;
-      return rawValue / this.multiplier;
-    }
-  }
-
-});
-
-/**
-   Formatter to converts between various datetime formats.
-
-   This class only understands ISO-8601 formatted datetime strings and UNIX
-   offset (number of milliseconds since UNIX Epoch). See
-   Backgrid.Extension.MomentFormatter if you need a much more flexible datetime
-   formatter.
-
-   @class Backgrid.DatetimeFormatter
-   @extends Backgrid.CellFormatter
-   @constructor
-   @throws {Error} If both `includeDate` and `includeTime` are false.
-*/
-var DatetimeFormatter = Backgrid.DatetimeFormatter = function (options) {
-  _.extend(this, this.defaults, options || {});
-
-  if (!this.includeDate && !this.includeTime) {
-    throw new Error("Either includeDate or includeTime must be true");
-  }
-};
-DatetimeFormatter.prototype = new CellFormatter();
-_.extend(DatetimeFormatter.prototype, {
-
-  /**
-     @member Backgrid.DatetimeFormatter
-
-     @cfg {Object} options
-
-     @cfg {boolean} [options.includeDate=true] Whether the values include the
-     date part.
-
-     @cfg {boolean} [options.includeTime=true] Whether the values include the
-     time part.
-
-     @cfg {boolean} [options.includeMilli=false] If `includeTime` is true,
-     whether to include the millisecond part, if it exists.
-   */
-  defaults: {
-    includeDate: true,
-    includeTime: true,
-    includeMilli: false
-  },
-
-  DATE_RE: /^([+\-]?\d{4})-(\d{2})-(\d{2})$/,
-  TIME_RE: /^(\d{2}):(\d{2}):(\d{2})(\.(\d{3}))?$/,
-  ISO_SPLITTER_RE: /T|Z| +/,
-
-  _convert: function (data, validate) {
-    if ((data + '').trim() === '') return null;
-
-    var date, time = null;
-    var jsDate = new Date(data);
-    if (_.isNumber(data)) {
-      date = lpad(jsDate.getUTCFullYear(), 4, 0) + '-' + lpad(jsDate.getUTCMonth() + 1, 2, 0) + '-' + lpad(jsDate.getUTCDate(), 2, 0);
-      time = lpad(jsDate.getUTCHours(), 2, 0) + ':' + lpad(jsDate.getUTCMinutes(), 2, 0) + ':' + lpad(jsDate.getUTCSeconds(), 2, 0);
-    }
-    else {
-      data = data.trim();
-      var parts = data.split(this.ISO_SPLITTER_RE) || [];
-      date = this.DATE_RE.test(parts[0]) ? parts[0] : '';
-      time = this.TIME_RE.test(parts[0]) ? parts[0] : '';
-      if (date && parts[1]) {
-        time = parts[1];
-      }
-    }
-
-    var YYYYMMDD = this.DATE_RE.exec(date) || [];
-    var HHmmssSSS = this.TIME_RE.exec(time) || [];
-
-    if (validate) {
-      if (this.includeDate && _.isUndefined(YYYYMMDD[0])) return;
-      if (this.includeTime && _.isUndefined(HHmmssSSS[0])) return;
-      if (!this.includeDate && date) return;
-      if (!this.includeTime && time) return;
-    }
-
-    jsDate = new Date(Date.UTC(YYYYMMDD[1] * 1 || 0,
-                                   YYYYMMDD[2] * 1 - 1 || 0,
-                                   YYYYMMDD[3] * 1 || 0,
-                                   HHmmssSSS[1] * 1 || null,
-                                   HHmmssSSS[2] * 1 || null,
-                                   HHmmssSSS[3] * 1 || null,
-                                   HHmmssSSS[5] * 1 || null));
-
-    var result = '';
-
-    if (this.includeDate) {
-      result = lpad(jsDate.getUTCFullYear(), 4, 0) + '-' + lpad(jsDate.getUTCMonth() + 1, 2, 0) + '-' + lpad(jsDate.getUTCDate(), 2, 0);
-    }
-
-    if (this.includeTime) {
-      result = result + (this.includeDate ? 'T' : '') + lpad(jsDate.getUTCHours(), 2, 0) + ':' + lpad(jsDate.getUTCMinutes(), 2, 0) + ':' + lpad(jsDate.getUTCSeconds(), 2, 0);
-
-      if (this.includeMilli) {
-        result = result + '.' + lpad(jsDate.getUTCMilliseconds(), 3, 0);
-      }
-    }
-
-    if (this.includeDate && this.includeTime) {
-      result += "Z";
-    }
-
-    return result;
-  },
-
-  /**
-     Converts an ISO-8601 formatted datetime string to a datetime string, date
-     string or a time string. The timezone is ignored if supplied.
-
-     @member Backgrid.DatetimeFormatter
-     @param {string} rawData
-     @param {Backbone.Model} model Used for more complicated formatting
-     @return {string|null|undefined} ISO-8601 string in UTC. Null and undefined
-     values are returned as is.
-  */
-  fromRaw: function (rawData, model) {
-    if (_.isNull(rawData) || _.isUndefined(rawData)) return '';
-    return this._convert(rawData);
-  },
-
-  /**
-     Converts an ISO-8601 formatted datetime string to a datetime string, date
-     string or a time string. The timezone is ignored if supplied. This method
-     parses the input values exactly the same way as
-     Backgrid.Extension.MomentFormatter#fromRaw(), in addition to doing some
-     sanity checks.
-
-     @member Backgrid.DatetimeFormatter
-     @param {string} formattedData
-     @param {Backbone.Model} model Used for more complicated formatting
-     @return {string|undefined} ISO-8601 string in UTC. Undefined if a date is
-     found when `includeDate` is false, or a time is found when `includeTime` is
-     false, or if `includeDate` is true and a date is not found, or if
-     `includeTime` is true and a time is not found.
-  */
-  toRaw: function (formattedData, model) {
-    return this._convert(formattedData, true);
-  }
-
-});
-
-/**
-   Formatter to convert any value to string.
-
-   @class Backgrid.StringFormatter
-   @extends Backgrid.CellFormatter
-   @constructor
- */
-var StringFormatter = Backgrid.StringFormatter = function () {/*This is intentional (SonarQube)*/};
-StringFormatter.prototype = new CellFormatter();
-_.extend(StringFormatter.prototype, {
-  /**
-     Converts any value to a string using Ecmascript's implicit type
-     conversion. If the given value is `null` or `undefined`, an empty string is
-     returned instead.
-
-     @member Backgrid.StringFormatter
-     @param {*} rawValue
-     @param {Backbone.Model} model Used for more complicated formatting
-     @return {string}
-   */
-  fromRaw: function (rawValue, model) {
-    if (_.isUndefined(rawValue) || _.isNull(rawValue)) return '';
-    return rawValue + '';
-  }
-});
-
-/**
-   Simple email validation formatter.
-
-   @class Backgrid.EmailFormatter
-   @extends Backgrid.CellFormatter
-   @constructor
- */
-var EmailFormatter = Backgrid.EmailFormatter = function () {/*This is intentional (SonarQube)*/};
-EmailFormatter.prototype = new CellFormatter();
-_.extend(EmailFormatter.prototype, {
-  /**
-     Return the input if it is a string that contains an '@' character and if
-     the strings before and after '@' are non-empty. If the input does not
-     validate, `undefined` is returned.
-
-     @member Backgrid.EmailFormatter
-     @param {*} formattedData
-     @param {Backbone.Model} model Used for more complicated formatting
-     @return {string|undefined}
-   */
-  toRaw: function (formattedData, model) {
-    var parts = formattedData.trim().split("@");
-    if (parts.length === 2 && _.all(parts)) {
-      return formattedData;
-    }
-  }
-});
-
-/**
-   Formatter for SelectCell.
-
-   If the type of a model value is not a string, it is expected that a subclass
-   of this formatter is provided to the SelectCell, with #toRaw overridden to
-   convert the string value returned from the DOM back to whatever value is
-   expected in the model.
-
-   @class Backgrid.SelectFormatter
-   @extends Backgrid.CellFormatter
-   @constructor
-*/
-var SelectFormatter = Backgrid.SelectFormatter = function () {/*This is intentional (SonarQube)*/};
-SelectFormatter.prototype = new CellFormatter();
-_.extend(SelectFormatter.prototype, {
-
-  /**
-     Normalizes raw scalar or array values to an array.
-
-     @member Backgrid.SelectFormatter
-     @param {*} rawValue
-     @param {Backbone.Model} model Used for more complicated formatting
-     @return {Array.<*>}
-  */
-  fromRaw: function (rawValue, model) {
-    if (_.isArray(rawValue)) {
-      return rawValue;
-    }
-    return rawValue != null ? [rawValue] : [];
-  }
-});
-
-/*
-  backgrid
-  http://github.com/cloudflare/backgrid
-
-  Copyright (c) 2013-present Cloudflare, Inc. and contributors
-  Licensed under the MIT license.
-*/
-
-/**
-   Generic cell editor base class. Only defines an initializer for a number of
-   required parameters.
-
-   @abstract
-   @class Backgrid.CellEditor
-   @extends Backbone.View
-*/
-var CellEditor = Backgrid.CellEditor = Backbone.View.extend({
-
-  /**
-     Initializer.
-
-     @param {Object} options
-     @param {Backgrid.CellFormatter} options.formatter
-     @param {Backgrid.Column} options.column
-     @param {Backbone.Model} options.model
-
-     @throws {TypeError} If `formatter` is not a formatter instance, or when
-     `model` or `column` are undefined.
-  */
-  initialize: function (options) {
-    this.formatter = options.formatter;
-    this.column = options.column;
-    if (!(this.column instanceof Column)) {
-      this.column = new Column(this.column);
-    }
-
-    this.listenTo(this.model, "backgrid:editing", this.postRender);
-  },
-
-  /**
-     Post-rendering setup and initialization. Focuses the cell editor's `el` in
-     this default implementation. **Should** be called by Cell classes after
-     calling Backgrid.CellEditor#render.
-  */
-  postRender: function (model, column) {
-    if (column == null || column.get("name") == this.column.get("name")) {
-      this.$el.focus();
-    }
-    return this;
-  }
-
-});
-
-/**
-   InputCellEditor the cell editor type used by most core cell types. This cell
-   editor renders a text input box as its editor. The input will render a
-   placeholder if the value is empty on supported browsers.
-
-   @class Backgrid.InputCellEditor
-   @extends Backgrid.CellEditor
-*/
-var InputCellEditor = Backgrid.InputCellEditor = CellEditor.extend({
-
-  /** @property */
-  tagName: "input",
-
-  /** @property */
-  attributes: {
-    type: "text"
-  },
-
-  /** @property */
-  events: {
-    "blur": "saveOrCancel",
-    "keydown": "saveOrCancel"
-  },
-
-  /**
-     Initializer. Removes this `el` from the DOM when a `done` event is
-     triggered.
-
-     @param {Object} options
-     @param {Backgrid.CellFormatter} options.formatter
-     @param {Backgrid.Column} options.column
-     @param {Backbone.Model} options.model
-     @param {string} [options.placeholder]
-  */
-  initialize: function (options) {
-    InputCellEditor.__super__.initialize.apply(this, arguments);
-
-    if (options.placeholder) {
-      this.$el.attr("placeholder", options.placeholder);
-    }
-  },
-
-  /**
-     Renders a text input with the cell value formatted for display, if it
-     exists.
-  */
-  render: function () {
-    var model = this.model;
-    this.$el.attr('aria-label', this.column.get("label"));
-    this.$el.val(this.formatter.fromRaw(model.get(this.column.get("name")), model));
-    return this;
-  },
-
-  /**
-     If the key pressed is `enter`, `tab`, `up`, or `down`, converts the value
-     in the editor to a raw value for saving into the model using the formatter.
-
-     If the key pressed is `esc` the changes are undone.
-
-     If the editor goes out of focus (`blur`) but the value is invalid, the
-     event is intercepted and cancelled so the cell remains in focus pending for
-     further action. The changes are saved otherwise.
-
-     Triggers a Backbone `backgrid:edited` event from the model when successful,
-     and `backgrid:error` if the value cannot be converted. Classes listening to
-     the `error` event, usually the Cell classes, should respond appropriately,
-     usually by rendering some kind of error feedback.
-
-     @param {Event} e
-  */
-  saveOrCancel: function (e) {
-
-    var formatter = this.formatter;
-    var model = this.model;
-    var column = this.column;
-
-    var command = new Command(e);
-    var blurred = e.type === "blur";
-
-    if (command.moveUp() || command.moveDown() || command.moveLeft() || command.moveRight() ||
-        command.save() || blurred) {
-
-      e.preventDefault();
-      e.stopPropagation();
-
-      var val = this.$el.val();
-      var newValue = formatter.toRaw(val, model);
-      if (_.isUndefined(newValue)) {
-        model.trigger("backgrid:error", model, column, val);
-      }
-      else {
-        model.set(column.get("name"), newValue);
-        model.trigger("backgrid:edited", model, column, command);
-      }
-    }
-    // esc
-    else if (command.cancel()) {
-      // undo
-      e.stopPropagation();
-      model.trigger("backgrid:edited", model, column, command);
-    }
-  },
-
-  postRender: function (model, column) {
-    if (column == null || column.get("name") == this.column.get("name")) {
-      // move the cursor to the end on firefox if text is right aligned
-      if (this.$el.css("text-align") === "right") {
-        var val = this.$el.val();
-        this.$el.focus().val(null).val(val);
-      }
-      else this.$el.focus();
-    }
-    return this;
-  }
-
-});
-
-/**
-   The super-class for all Cell types. By default, this class renders a plain
-   table cell with the model value converted to a string using the
-   formatter. The table cell is clickable, upon which the cell will go into
-   editor mode, which is rendered by a Backgrid.InputCellEditor instance by
-   default. Upon encountering any formatting errors, this class will add an
-   `error` CSS class to the table cell.
-
-   @abstract
-   @class Backgrid.Cell
-   @extends Backbone.View
-*/
-var Cell = Backgrid.Cell = Backbone.View.extend({
-
-  /** @property */
-  tagName: "td",
-
-  /**
-     @property {Backgrid.CellFormatter|Object|string} [formatter=CellFormatter]
-  */
-  formatter: CellFormatter,
-
-  /**
-     @property {Backgrid.CellEditor} [editor=Backgrid.InputCellEditor] The
-     default editor for all cell instances of this class. This value must be a
-     class, it will be automatically instantiated upon entering edit mode.
-
-     See Backgrid.CellEditor
-  */
-  editor: InputCellEditor,
-
-  /** @property */
-  events: {
-    "click": "enterEditMode"
-  },
-
-  /**
-     Initializer.
-
-     @param {Object} options
-     @param {Backbone.Model} options.model
-     @param {Backgrid.Column} options.column
-
-     @throws {ReferenceError} If formatter is a string but a formatter class of
-     said name cannot be found in the Backgrid module.
-  */
-  initialize: function (options) {
-    this.column = options.column;
-    if (!(this.column instanceof Column)) {
-      this.column = new Column(this.column);
-    }
-
-    var column = this.column, model = this.model, $el = this.$el;
-
-    var formatter = Backgrid.resolveNameToClass(column.get("formatter") ||
-                                                this.formatter, "Formatter");
-
-    if (!_.isFunction(formatter.fromRaw) && !_.isFunction(formatter.toRaw)) {
-      formatter = new formatter();
-    }
-
-    this.formatter = formatter;
-
-    this.editor = Backgrid.resolveNameToClass(this.editor, "CellEditor");
-
-    this.listenTo(model, "change:" + column.get("name"), function () {
-      if (!$el.hasClass("editor")) this.render();
-    });
-
-    this.listenTo(model, "backgrid:error", this.renderError);
-
-    this.listenTo(column, "change:editable change:sortable change:renderable",
-                  function (col) {
-                    var changed = col.changedAttributes();
-                    for (var key in changed) {
-                      if (changed.hasOwnProperty(key)) {
-                        $el.toggleClass(key, changed[key]);
-                      }
-                    }
-                  });
-
-    this.updateStateClassesMaybe();
-  },
-
-  updateStateClassesMaybe: function () {
-    var model = this.model;
-    var column = this.column;
-    var $el = this.$el;
-    $el.toggleClass("editable", Backgrid.callByNeed(column.editable(), column, model));
-    $el.toggleClass("sortable", Backgrid.callByNeed(column.sortable(), column, model));
-    $el.toggleClass("renderable", Backgrid.callByNeed(column.renderable(), column, model));
-  },
-
-  /**
-     Render a text string in a table cell. The text is converted from the
-     model's raw value for this cell's column.
-  */
-  render: function () {
-    var $el = this.$el;
-    $el.empty();
-    var model = this.model;
-    var columnName = this.column.get("name");
-    var value = _.escape(this.formatter.fromRaw(model.get(columnName), model));
-    $el.append($(`<span class="display-text" title="${value}">${value}</span>`));
-    $el.addClass(columnName);
-    this.updateStateClassesMaybe();
-    this.delegateEvents();
-    return this;
-  },
-
-  /**
-     If this column is editable, a new CellEditor instance is instantiated with
-     its required parameters. An `editor` CSS class is added to the cell upon
-     entering edit mode.
-
-     This method triggers a Backbone `backgrid:edit` event from the model when
-     the cell is entering edit mode and an editor instance has been constructed,
-     but before it is rendered and inserted into the DOM. The cell and the
-     constructed cell editor instance are sent as event parameters when this
-     event is triggered.
-
-     When this cell has finished switching to edit mode, a Backbone
-     `backgrid:editing` event is triggered from the model. The cell and the
-     constructed cell instance are also sent as parameters in the event.
-
-     When the model triggers a `backgrid:error` event, it means the editor is
-     unable to convert the current user input to an apprpriate value for the
-     model's column, and an `error` CSS class is added to the cell accordingly.
-  */
-  enterEditMode: function () {
-    var model = this.model;
-    var column = this.column;
-
-    var editable = Backgrid.callByNeed(column.editable(), column, model);
-    if (editable) {
-
-      this.currentEditor = new this.editor({
-        column: this.column,
-        model: this.model,
-        formatter: this.formatter
-      });
-
-      model.trigger("backgrid:edit", model, column, this, this.currentEditor);
-
-      // Need to redundantly undelegate events for Firefox
-      this.undelegateEvents();
-      var dispText = this.$el.find('.display-text');
-      var width = '100%';
-      if(dispText.length === 1) {
-        width = dispText.width();
-      }
-      this.$el.empty();
-      this.$el.append(this.currentEditor.$el);
-      this.currentEditor.render();
-      this.currentEditor.$el.css('min-width',width);
-      this.$el.addClass("editor");
-
-      model.trigger("backgrid:editing", model, column, this, this.currentEditor);
-    }
-  },
-
-  /**
-     Put an `error` CSS class on the table cell.
-  */
-  renderError: function (model, column) {
-    if (column == null || column.get("name") == this.column.get("name")) {
-      this.$el.addClass("error");
-    }
-  },
-
-  /**
-     Removes the editor and re-render in display mode.
-  */
-  exitEditMode: function () {
-    this.$el.removeClass("error");
-    this.currentEditor.remove();
-    this.stopListening(this.currentEditor);
-    delete this.currentEditor;
-    this.$el.removeClass("editor");
-    this.render();
-  },
-
-  /**
-     Clean up this cell.
-
-     @chainable
-  */
-  remove: function () {
-    if (this.currentEditor) {
-      this.currentEditor.remove.apply(this.currentEditor, arguments);
-      delete this.currentEditor;
-    }
-    return Cell.__super__.remove.apply(this, arguments);
-  }
-
-});
-
-/**
-   StringCell displays HTML escaped strings and accepts anything typed in.
-
-   @class Backgrid.StringCell
-   @extends Backgrid.Cell
-*/
-var StringCell = Backgrid.StringCell = Cell.extend({
-
-  /** @property */
-  className: "string-cell",
-  attributes: {
-    tabIndex: "0"
-  },
-
-  formatter: StringFormatter
-
-});
-
-/**
-   UriCell renders an HTML `<a>` anchor for the value and accepts URIs as user
-   input values. No type conversion or URL validation is done by the formatter
-   of this cell. Users who need URL validation are encourage to subclass UriCell
-   to take advantage of the parsing capabilities of the HTMLAnchorElement
-   available on HTML5-capable browsers or using a third-party library like
-   [URI.js](https://github.com/medialize/URI.js).
-
-   @class Backgrid.UriCell
-   @extends Backgrid.Cell
-*/
-var UriCell = Backgrid.UriCell = Cell.extend({
-
-  /** @property */
-  className: "uri-cell",
-
-  /**
-     @property {string} [title] The title attribute of the generated anchor. It
-     uses the display value formatted by the `formatter.fromRaw` by default.
-  */
-  title: null,
-
-  /**
-     @property {string} [target="_blank"] The target attribute of the generated
-     anchor.
-  */
-  target: "_blank",
-
-  initialize: function (options) {
-    UriCell.__super__.initialize.apply(this, arguments);
-    this.title = options.title || this.title;
-    this.target = options.target || this.target;
-  },
-
-  render: function () {
-    this.$el.empty();
-    var rawValue = this.model.get(this.column.get("name"));
-    var formattedValue = this.formatter.fromRaw(rawValue, this.model);
-    this.$el.append($("<a>", {
-      tabIndex: -1,
-      href: rawValue,
-      title: this.title || formattedValue,
-      target: this.target
-    }).text(formattedValue));
-    this.delegateEvents();
-    return this;
-  }
-
-});
-
-/**
-   Like Backgrid.UriCell, EmailCell renders an HTML `<a>` anchor for the
-   value. The `href` in the anchor is prefixed with `mailto:`. EmailCell will
-   complain if the user enters a string that doesn't contain the `@` sign.
-
-   @class Backgrid.EmailCell
-   @extends Backgrid.StringCell
-*/
-Backgrid.EmailCell = StringCell.extend({
-
-  /** @property */
-  className: "email-cell",
-
-  formatter: EmailFormatter,
-
-  render: function () {
-    this.$el.empty();
-    var model = this.model;
-    var formattedValue = this.formatter.fromRaw(model.get(this.column.get("name")), model);
-    this.$el.append($("<a>", {
-      tabIndex: -1,
-      href: "mailto:" + formattedValue,
-      title: formattedValue
-    }).text(formattedValue));
-    this.delegateEvents();
-    return this;
-  }
-
-});
-
-/**
-   NumberCell is a generic cell that renders all numbers. Numbers are formatted
-   using a Backgrid.NumberFormatter.
-
-   @class Backgrid.NumberCell
-   @extends Backgrid.Cell
-*/
-var NumberCell = Backgrid.NumberCell = Cell.extend({
-
-  /** @property */
-  className: "number-cell",
-
-  /**
-     @property {number} [decimals=2] Must be an integer.
-  */
-  decimals: NumberFormatter.prototype.defaults.decimals,
-
-  /** @property {string} [decimalSeparator='.'] */
-  decimalSeparator: NumberFormatter.prototype.defaults.decimalSeparator,
-
-  /** @property {string} [orderSeparator=','] */
-  orderSeparator: NumberFormatter.prototype.defaults.orderSeparator,
-
-  /** @property {Backgrid.CellFormatter} [formatter=Backgrid.NumberFormatter] */
-  formatter: NumberFormatter,
-
-  /**
-     Initializes this cell and the number formatter.
-
-     @param {Object} options
-     @param {Backbone.Model} options.model
-     @param {Backgrid.Column} options.column
-  */
-  initialize: function (options) {
-    NumberCell.__super__.initialize.apply(this, arguments);
-    var formatter = this.formatter;
-    formatter.decimals = this.decimals;
-    formatter.decimalSeparator = this.decimalSeparator;
-    formatter.orderSeparator = this.orderSeparator;
-  }
-
-});
-
-/**
-   An IntegerCell is just a Backgrid.NumberCell with 0 decimals. If a floating
-   point number is supplied, the number is simply rounded the usual way when
-   displayed.
-
-   @class Backgrid.IntegerCell
-   @extends Backgrid.NumberCell
-*/
-Backgrid.IntegerCell = NumberCell.extend({
-
-  /** @property */
-  className: "integer-cell",
-
-  /**
-     @property {number} decimals Must be an integer.
-  */
-  decimals: 0
-});
-
-/**
-   A PercentCell is another Backgrid.NumberCell that takes a floating number,
-   optionally multiplied by a multiplier and display it as a percentage.
-
-   @class Backgrid.PercentCell
-   @extends Backgrid.NumberCell
- */
-var PercentCell = Backgrid.PercentCell = NumberCell.extend({
-
-  /** @property */
-  className: "percent-cell",
-
-  /** @property {number} [multiplier=1] */
-  multiplier: PercentFormatter.prototype.defaults.multiplier,
-
-  /** @property {string} [symbol='%'] */
-  symbol: PercentFormatter.prototype.defaults.symbol,
-
-  /** @property {Backgrid.CellFormatter} [formatter=Backgrid.PercentFormatter] */
-  formatter: PercentFormatter,
-
-  /**
-     Initializes this cell and the percent formatter.
-
-     @param {Object} options
-     @param {Backbone.Model} options.model
-     @param {Backgrid.Column} options.column
-  */
-  initialize: function () {
-    PercentCell.__super__.initialize.apply(this, arguments);
-    var formatter = this.formatter;
-    formatter.multiplier = this.multiplier;
-    formatter.symbol = this.symbol;
-  }
-
-});
-
-/**
-   DatetimeCell is a basic cell that accepts datetime string values in RFC-2822
-   or W3C's subset of ISO-8601 and displays them in ISO-8601 format. For a much
-   more sophisticated date time cell with better datetime formatting, take a
-   look at the Backgrid.Extension.MomentCell extension.
-
-   @class Backgrid.DatetimeCell
-   @extends Backgrid.Cell
-
-   See:
-
-   - Backgrid.Extension.MomentCell
-   - Backgrid.DatetimeFormatter
-*/
-var DatetimeCell = Backgrid.DatetimeCell = Cell.extend({
-
-  /** @property */
-  className: "datetime-cell",
-
-  /**
-     @property {boolean} [includeDate=true]
-  */
-  includeDate: DatetimeFormatter.prototype.defaults.includeDate,
-
-  /**
-     @property {boolean} [includeTime=true]
-  */
-  includeTime: DatetimeFormatter.prototype.defaults.includeTime,
-
-  /**
-     @property {boolean} [includeMilli=false]
-  */
-  includeMilli: DatetimeFormatter.prototype.defaults.includeMilli,
-
-  /** @property {Backgrid.CellFormatter} [formatter=Backgrid.DatetimeFormatter] */
-  formatter: DatetimeFormatter,
-
-  /**
-     Initializes this cell and the datetime formatter.
-
-     @param {Object} options
-     @param {Backbone.Model} options.model
-     @param {Backgrid.Column} options.column
-  */
-  initialize: function (options) {
-    DatetimeCell.__super__.initialize.apply(this, arguments);
-    var formatter = this.formatter;
-    formatter.includeDate = this.includeDate;
-    formatter.includeTime = this.includeTime;
-    formatter.includeMilli = this.includeMilli;
-
-    var placeholder = this.includeDate ? "YYYY-MM-DD" : "";
-    placeholder += (this.includeDate && this.includeTime) ? "T" : "";
-    placeholder += this.includeTime ? "HH:mm:ss" : "";
-    placeholder += (this.includeTime && this.includeMilli) ? ".SSS" : "";
-
-    this.editor = this.editor.extend({
-      attributes: _.extend({}, this.editor.prototype.attributes, this.editor.attributes, {
-        placeholder: placeholder
-      })
-    });
-  }
-
-});
-
-/**
-   DateCell is a Backgrid.DatetimeCell without the time part.
-
-   @class Backgrid.DateCell
-   @extends Backgrid.DatetimeCell
-*/
-Backgrid.DateCell = DatetimeCell.extend({
-
-  /** @property */
-  className: "date-cell",
-
-  /** @property */
-  includeTime: false
-
-});
-
-/**
-   TimeCell is a Backgrid.DatetimeCell without the date part.
-
-   @class Backgrid.TimeCell
-   @extends Backgrid.DatetimeCell
-*/
-Backgrid.TimeCell = DatetimeCell.extend({
-
-  /** @property */
-  className: "time-cell",
-
-  /** @property */
-  includeDate: false
-
-});
-
-/**
-   BooleanCellEditor renders a checkbox as its editor.
-
-   @class Backgrid.BooleanCellEditor
-   @extends Backgrid.CellEditor
-*/
-var BooleanCellEditor = Backgrid.BooleanCellEditor = CellEditor.extend({
-
-  /** @property */
-  tagName: "input",
-
-  /** @property */
-  attributes: {
-    tabIndex: -1,
-    type: "checkbox"
-  },
-
-  /** @property */
-  events: {
-    "mousedown": function () {
-      this.mouseDown = true;
-    },
-    "blur": "enterOrExitEditMode",
-    "mouseup": function () {
-      this.mouseDown = false;
-    },
-    "change": "saveOrCancel",
-    "keydown": "saveOrCancel"
-  },
-
-  /**
-     Renders a checkbox and check it if the model value of this column is true,
-     uncheck otherwise.
-  */
-  render: function () {
-    var model = this.model;
-    var val = this.formatter.fromRaw(model.get(this.column.get("name")), model);
-    this.$el.prop("checked", val);
-    return this;
-  },
-
-  /**
-     Event handler. Hack to deal with the case where `blur` is fired before
-     `change` and `click` on a checkbox.
-  */
-  enterOrExitEditMode: function (e) {
-    if (!this.mouseDown) {
-      var model = this.model;
-      model.trigger("backgrid:edited", model, this.column, new Command(e));
-    }
-  },
-
-  /**
-     Event handler. Save the value into the model if the event is `change` or
-     one of the keyboard navigation key presses. Exit edit mode without saving
-     if `escape` was pressed.
-  */
-  saveOrCancel: function (e) {
-    var model = this.model;
-    var column = this.column;
-    var formatter = this.formatter;
-    var command = new Command(e);
-    // skip ahead to `change` when space is pressed
-    if (command.passThru() && e.type != "change") return true;
-    if (command.cancel()) {
-      e.stopPropagation();
-      model.trigger("backgrid:edited", model, column, command);
-    }
-
-    var $el = this.$el;
-    var val = null;
-    if (command.save() || command.moveLeft() || command.moveRight() || command.moveUp() ||
-        command.moveDown()) {
-      e.preventDefault();
-      e.stopPropagation();
-      val = formatter.toRaw($el.prop("checked"), model);
-      model.set(column.get("name"), val);
-      model.trigger("backgrid:edited", model, column, command);
-    }
-    else if (e.type == "change") {
-      val = formatter.toRaw($el.prop("checked"), model);
-      model.set(column.get("name"), val);
-      $el.focus();
-    }
-  }
-
-});
-
-/**
-   BooleanCell renders a checkbox both during display mode and edit mode. The
-   checkbox is checked if the model value is true, unchecked otherwise.
-
-   @class Backgrid.BooleanCell
-   @extends Backgrid.Cell
-*/
-Backgrid.BooleanCell = Cell.extend({
-
-  /** @property */
-  className: "boolean-cell",
-
-  /** @property */
-  editor: BooleanCellEditor,
-
-  /** @property */
-  events: {
-    "click": "enterEditMode"
-  },
-
-  /**
-     Renders a checkbox and check it if the model value of this column is true,
-     uncheck otherwise.
-  */
-  render: function () {
-    this.$el.empty();
-    var model = this.model, column = this.column;
-    var editable = Backgrid.callByNeed(column.editable(), column, model);
-    this.$el.append($("<input>", {
-      tabIndex: -1,
-      type: "checkbox",
-      checked: this.formatter.fromRaw(model.get(column.get("name")), model),
-      disabled: !editable
-    }));
-    this.delegateEvents();
-    return this;
-  }
-
-});
-
-/**
-   SelectCellEditor renders an HTML `<select>` fragment as the editor.
-
-   @class Backgrid.SelectCellEditor
-   @extends Backgrid.CellEditor
-*/
-var SelectCellEditor = Backgrid.SelectCellEditor = CellEditor.extend({
-
-  /** @property */
-  tagName: "select",
-
-  /** @property */
-  events: {
-    "change": "save",
-    "blur": "close",
-    "keydown": "close"
-  },
-
-  /** @property {function(Object, ?Object=): string} template */
-  template: _.template(
-    '<option value="<%- value %>" <%= selected ? \'selected="selected"\' : "" %>><%- text %></option>',
-    null,
-    {
-        variable    : null,
-        evaluate    : /<%([\s\S]+?)%>/g,
-        interpolate : /<%=([\s\S]+?)%>/g,
-        escape      : /<%-([\s\S]+?)%>/g
-    }),
-
-  setOptionValues: function (optionValues) {
-    this.optionValues = optionValues;
-    this.optionValues = _.result(this, "optionValues");
-  },
-
-  setMultiple: function (multiple) {
-    this.multiple = multiple;
-    this.$el.prop("multiple", multiple);
-  },
-
-  _renderOptions: function (nvps, selectedValues) {
-    var options = '';
-    for (let nvps_val of nvps) {
-      options = options + this.template({
-        text: nvps_val[0],
-        value: nvps_val[1],
-        selected: _.indexOf(selectedValues, nvps_val[1]) > -1
-      });
-    }
-    return options;
-  },
-
-  /**
-     Renders the options if `optionValues` is a list of name-value pairs. The
-     options are contained inside option groups if `optionValues` is a list of
-     object hashes. The name is rendered at the option text and the value is the
-     option value. If `optionValues` is a function, it is called without a
-     parameter.
-  */
-  render: function () {
-    this.$el.empty();
-
-    var optionValues = _.result(this, "optionValues");
-    var model = this.model;
-    var selectedValues = this.formatter.fromRaw(model.get(this.column.get("name")), model);
-
-    if (!_.isArray(optionValues)) throw new TypeError("optionValues must be an array");
-
-    var optionValue = null;
-    var optionText = null;
-    var optgroupName = null;
-    var optgroup = null;
-
-    for (let option_val of optionValues) {
-      optionValue = option_val;
-
-      if (_.isArray(optionValue)) {
-        optionText  = optionValue[0];
-        optionValue = optionValue[1];
-
-        this.$el.append(this.template({
-          text: optionText,
-          value: optionValue,
-          selected: _.indexOf(selectedValues, optionValue) > -1
-        }));
-      }
-      else if (_.isObject(optionValue)) {
-        optgroupName = optionValue.name;
-        optgroup = $("<optgroup></optgroup>", { label: optgroupName });
-        optgroup.append(this._renderOptions.call(this, optionValue.values, selectedValues));
-        this.$el.append(optgroup);
-      }
-      else {
-        throw new TypeError("optionValues elements must be a name-value pair or an object hash of { name: 'optgroup label', value: [option name-value pairs] }");
-      }
-    }
-
-    this.delegateEvents();
-
-    return this;
-  },
-
-  /**
-     Saves the value of the selected option to the model attribute.
-  */
-  save: function (e) {
-    var model = this.model;
-    var column = this.column;
-    model.set(column.get("name"), this.formatter.toRaw(this.$el.val(), model));
-  },
-
-  /**
-     Triggers a `backgrid:edited` event from the model so the body can close
-     this editor.
-  */
-  close: function (e) {
-    var model = this.model;
-    var column = this.column;
-    var command = new Command(e);
-    if (command.cancel()) {
-      e.stopPropagation();
-      model.trigger("backgrid:edited", model, column, new Command(e));
-    }
-    else if (command.save() || command.moveLeft() || command.moveRight() ||
-             command.moveUp() || command.moveDown() || e.type == "blur") {
-      e.preventDefault();
-      e.stopPropagation();
-      this.save(e);
-      model.trigger("backgrid:edited", model, column, new Command(e));
-    }
-  }
-
-});
-
-/**
-   SelectCell is also a different kind of cell in that upon going into edit mode
-   the cell renders a list of options to pick from, as opposed to an input box.
-
-   SelectCell cannot be referenced by its string name when used in a column
-   definition because it requires an `optionValues` class attribute to be
-   defined. `optionValues` can either be a list of name-value pairs, to be
-   rendered as options, or a list of object hashes which consist of a key *name*
-   which is the option group name, and a key *values* which is a list of
-   name-value pairs to be rendered as options under that option group.
-
-   In addition, `optionValues` can also be a parameter-less function that
-   returns one of the above. If the options are static, it is recommended the
-   returned values to be memoized. `_.memoize()` is a good function to help with
-   that.
-
-   During display mode, the default formatter will normalize the raw model value
-   to an array of values whether the raw model value is a scalar or an
-   array. Each value is compared with the `optionValues` values using
-   Ecmascript's implicit type conversion rules. When exiting edit mode, no type
-   conversion is performed when saving into the model. This behavior is not
-   always desirable when the value type is anything other than string. To
-   control type conversion on the client-side, you should subclass SelectCell to
-   provide a custom formatter or provide the formatter to your column
-   definition.
-
-   See:
-     [$.fn.val()](http://api.jquery.com/val/)
-
-   @class Backgrid.SelectCell
-   @extends Backgrid.Cell
-*/
-var SelectCell = Backgrid.SelectCell = Cell.extend({
-
-  /** @property */
-  className: "select-cell",
-
-  /** @property */
-  editor: SelectCellEditor,
-
-  /** @property */
-  multiple: false,
-
-  /** @property */
-  formatter: SelectFormatter,
-
-  /**
-     @property {Array.<Array>|Array.<{name: string, values: Array.<Array>}>} optionValues
-  */
-  optionValues: undefined,
-
-  /** @property */
-  delimiter: ', ',
-
-  /**
-     Initializer.
-
-     @param {Object} options
-     @param {Backbone.Model} options.model
-     @param {Backgrid.Column} options.column
-
-     @throws {TypeError} If `optionsValues` is undefined.
-  */
-  initialize: function (options) {
-    SelectCell.__super__.initialize.apply(this, arguments);
-    this.listenTo(this.model, "backgrid:edit", function (model, column, cell, editor) {
-      if (column.get("name") == this.column.get("name")) {
-        editor.setOptionValues(this.optionValues);
-        editor.setMultiple(this.multiple);
-      }
-    });
-  },
-
-  /**
-     Renders the label using the raw value as key to look up from `optionValues`.
-
-     @throws {TypeError} If `optionValues` is malformed.
-  */
-  render: function () {
-    this.$el.empty();
-
-    var optionValues = _.result(this, "optionValues");
-    var model = this.model;
-    var rawData = this.formatter.fromRaw(model.get(this.column.get("name")), model);
-
-    var selectedText = [];
-
-    try {
-      if (!_.isArray(optionValues) || _.isEmpty(optionValues)) throw new TypeError;
-
-      for (let raw_val of rawData) {
-        var rawDatum = raw_val;
-
-        for (let opt_val of optionValues) {
-          var optionValue = opt_val;
-
-          if (_.isArray(optionValue)) {
-            var optionText  = optionValue[0];
-            optionValue = optionValue[1];
-
-            if (optionValue == rawDatum) selectedText.push(optionText);
-          }
-          else if (_.isObject(optionValue)) {
-            var optionGroupValues = optionValue.values;
-
-            for (let opt_grp_val of optionGroupValues) {
-              var optionGroupValue = opt_grp_val;
-              if (optionGroupValue[1] == rawDatum) {
-                selectedText.push(optionGroupValue[0]);
-              }
-            }
-          }
-          else {
-            throw new TypeError;
-          }
-        }
-      }
-
-      this.$el.append(selectedText.join(this.delimiter));
-    }
-    catch (ex) {
-      if (ex instanceof TypeError) {
-        throw new TypeError("'optionValues' must be of type {Array.<Array>|Array.<{name: string, values: Array.<Array>}>}");
-      }
-      throw ex;
-    }
-
-    this.delegateEvents();
-
-    return this;
-  }
-
-});
-
-/*
-  backgrid
-  http://github.com/cloudflare/backgrid
-
-  Copyright (c) 2013-present Cloudflare, Inc. and contributors
-  Licensed under the MIT license.
-*/
-
-/**
-   A Column is a placeholder for column metadata.
-
-   You usually don't need to create an instance of this class yourself as a
-   collection of column instances will be created for you from a list of column
-   attributes in the Backgrid.js view class constructors.
-
-   @class Backgrid.Column
-   @extends Backbone.Model
-*/
-var Column = Backgrid.Column = Backbone.Model.extend({
-
-  /**
-     @cfg {Object} defaults Column defaults. To override any of these default
-     values, you can either change the prototype directly to override
-     Column.defaults globally or extend Column and supply the custom class to
-     Backgrid.Grid:
-
-         // Override Column defaults globally
-         Column.prototype.defaults.sortable = false;
-
-         // Override Column defaults locally
-         var MyColumn = Column.extend({
-           defaults: _.defaults({
-             editable: false
-           }, Column.prototype.defaults)
-         });
-
-         var grid = new Backgrid.Grid(columns: new Columns([{...}, {...}], {
-           model: MyColumn
-         }));
-
-     @cfg {string} [defaults.name] The default name of the model attribute.
-
-     @cfg {string} [defaults.label] The default label to show in the header.
-
-     @cfg {string|Backgrid.Cell} [defaults.cell] The default cell type. If this
-     is a string, the capitalized form will be used to look up a cell class in
-     Backbone, i.e.: string => StringCell. If a Cell subclass is supplied, it is
-     initialized with a hash of parameters. If a Cell instance is supplied, it
-     is used directly.
-
-     @cfg {string|Backgrid.HeaderCell} [defaults.headerCell] The default header
-     cell type.
-
-     @cfg {boolean|string|function(): boolean} [defaults.sortable=true] Whether
-     this column is sortable. If the value is a string, a method will the same
-     name will be looked up from the column instance to determine whether the
-     column should be sortable. The method's signature must be `function
-     (Backbone.Model): boolean`. The function's context is the column instance.
-
-     @cfg {boolean|string|function(): boolean} [defaults.editable=true] Whether
-     this column is editable. If the value is a string, a method will the same
-     name will be looked up from the column instance to determine whether the
-     column should be editable. The method's signature must be `function
-     (Backbone.Model): boolean`. The function's context is the column instance.
-
-     @cfg {boolean|string|function(): boolean} [defaults.renderable=true]
-     Whether this column is renderable. If the value is a string, a method will
-     the same name will be looked up from the column instance to determine
-     whether the column should be renderable. The method's signature must be
-     `function (Backbone.Model): boolean`. The function's context is the column
-     instance.
-
-     @cfg {Backgrid.CellFormatter | Object | string} [defaults.formatter] The
-     formatter to use to convert between raw model values and user input.
-
-     @cfg {"toggle"|"cycle"} [defaults.sortType="cycle"] Whether sorting will
-     toggle between ascending and descending order, or cycle between insertion
-     order, ascending and descending order.
-
-     @cfg {(function(Backbone.Model, string): *) | string} [defaults.sortValue]
-     The function to use to extract a value from the model for comparison during
-     sorting. If this value is a string, a method with the same name will be
-     looked up from the column instance.
-
-     @cfg {"ascending"|"descending"|null} [defaults.direction=null] The initial
-     sorting direction for this column. The default is ordered by
-     Backbone.Model.cid, which usually means the collection is ordered by
-     insertion order.
-  */
-  defaults: {
-    name: undefined,
-    label: undefined,
-    sortable: true,
-    editable: true,
-    renderable: true,
-    formatter: undefined,
-    sortType: "cycle",
-    sortValue: undefined,
-    direction: null,
-    cell: undefined,
-    headerCell: undefined
-  },
-
-  /**
-     Initializes this Column instance.
-
-     @param {Object} attrs
-
-     @param {string} attrs.name The model attribute this column is responsible
-     for.
-
-     @param {string|Backgrid.Cell} attrs.cell The cell type to use to render
-     this column.
-
-     @param {string} [attrs.label]
-
-     @param {string|Backgrid.HeaderCell} [attrs.headerCell]
-
-     @param {boolean|string|function(): boolean} [attrs.sortable=true]
-
-     @param {boolean|string|function(): boolean} [attrs.editable=true]
-
-     @param {boolean|string|function(): boolean} [attrs.renderable=true]
-
-     @param {Backgrid.CellFormatter | Object | string} [attrs.formatter]
-
-     @param {"toggle"|"cycle"}  [attrs.sortType="cycle"]
-
-     @param {(function(Backbone.Model, string): *) | string} [attrs.sortValue]
-
-     @throws {TypeError} If attrs.cell or attrs.options are not supplied.
-
-     @throws {ReferenceError} If formatter is a string but a formatter class of
-     said name cannot be found in the Backgrid module.
-
-     See:
-
-     - Backgrid.Column.defaults
-     - Backgrid.Cell
-     - Backgrid.CellFormatter
-   */
-  initialize: function () {
-    if (!this.has("label")) {
-      this.set({ label: this.get("name") }, { silent: true });
-    }
-
-    var headerCell = Backgrid.resolveNameToClass(this.get("headerCell"), "HeaderCell");
-
-    var cell = Backgrid.resolveNameToClass(this.get("cell"), "Cell");
-
-    this.set({cell: cell, headerCell: headerCell}, { silent: true });
-  },
-
-  /**
-     Returns an appropriate value extraction function from a model for sorting.
-
-     If the column model contains an attribute `sortValue`, if it is a string, a
-     method from the column instance identifified by the `sortValue` string is
-     returned. If it is a function, it it returned as is. If `sortValue` isn't
-     found from the column model's attributes, a default value extraction
-     function is returned which will compare according to the natural order of
-     the value's type.
-
-     @return {function(Backbone.Model, string): *}
-   */
-  sortValue: function () {
-    var sortValue = this.get("sortValue");
-    if (_.isString(sortValue)) return this[sortValue];
-    else if (_.isFunction(sortValue)) return sortValue;
-
-    return function (model, colName) {
-      return model.get(colName);
-    };
-  }
-
-  /**
-     If you cannot always determine whether a column should be sortable before
-     the grid get initialized, you can override this method.
-
-     @member Backgrid.Column
-     @protected
-     @method sortable
-     @return {function(Backbone.Model): boolean | boolean}
-  */
-
-  /**
-     If you cannot always determine whether a column should be editable before
-     the grid get initialized, you can override this method.
-
-     @member Backgrid.Column
-     @protected
-     @method editable
-     @return {function(Backbone.Model): boolean | boolean}
-  */
-
-  /**
-     If you cannot always determine whether a column should be renderable before
-     the grid get initialized, you can override this method.
-
-     @member Backgrid.Column
-     @protected
-     @method renderable
-     @return {function(Backbone.Model): boolean | boolean}
-  */
-});
-
-_.each(["sortable", "renderable", "editable"], function (key) {
-  Column.prototype[key] = function () {
-    var value = this.get(key);
-    if (_.isString(value)) return this[value];
-    else if (_.isFunction(value)) return value;
-
-    return !!value;
-  };
-});
-
-/**
-   A Backbone collection of Column instances.
-
-   @class Backgrid.Columns
-   @extends Backbone.Collection
- */
-var Columns = Backgrid.Columns = Backbone.Collection.extend({
-
-  /**
-     @property {Backgrid.Column} model
-   */
-  model: Column
-});
-
-/*
-  backgrid
-  http://github.com/cloudflare/backgrid
-
-  Copyright (c) 2013-present Cloudflare, Inc. and contributors
-  Licensed under the MIT license.
-*/
-
-/**
-   Row is a simple container view that takes a model instance and a list of
-   column metadata describing how each of the model's attribute is to be
-   rendered, and apply the appropriate cell to each attribute.
-
-   @class Backgrid.Row
-   @extends Backbone.View
-*/
-var Row = Backgrid.Row = Backbone.View.extend({
-
-  /** @property */
-  tagName: "tr",
-
-  /**
-     Initializes a row view instance.
-
-     @param {Object} options
-     @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns Column metadata.
-     @param {Backbone.Model} options.model The model instance to render.
-
-     @throws {TypeError} If options.columns or options.model is undefined.
-  */
-  initialize: function (options) {
-
-    var columns = this.columns = options.columns;
-    if (!(columns instanceof Backbone.Collection)) {
-      columns = this.columns = new Columns(columns);
-    }
-
-    var cells = this.cells = [];
-    for (var i = 0; i < columns.length; i++) {
-      cells.push(this.makeCell(columns.at(i), options));
-    }
-
-    this.listenTo(columns, "add", function (column, cols) {
-      var index = cols.indexOf(column);
-      var cell = this.makeCell(column, options);
-      cells.splice(index, 0, cell);
-
-      var $el = this.$el;
-      if (index === 0) {
-        $el.prepend(cell.render().$el);
-      }
-      else if (index === cols.length - 1) {
-        $el.append(cell.render().$el);
-      }
-      else {
-        $el.children().eq(index).before(cell.render().$el);
-      }
-    });
-
-    this.listenTo(columns, "remove", function (column, cols, opts) {
-      cells[opts.index].remove();
-      cells.splice(opts.index, 1);
-    });
-  },
-
-  /**
-     Factory method for making a cell. Used by #initialize internally. Override
-     this to provide an appropriate cell instance for a custom Row subclass.
-
-     @protected
-
-     @param {Backgrid.Column} column
-     @param {Object} options The options passed to #initialize.
-
-     @return {Backgrid.Cell}
-  */
-  makeCell: function (column) {
-    return new (column.get("cell"))({
-      column: column,
-      model: this.model
-    });
-  },
-
-  /**
-     Renders a row of cells for this row's model.
-  */
-  render: function () {
-    this.$el.empty();
-
-    var fragment = document.createDocumentFragment();
-    for (let cell_val of this.cells) {
-      fragment.appendChild(cell_val.render().el);
-    }
-
-    this.el.appendChild(fragment);
-
-    this.delegateEvents();
-
-    return this;
-  },
-
-  /**
-     Clean up this row and its cells.
-
-     @chainable
-  */
-  remove: function () {
-    for (let cell_val of this.cells) {
-      var cell = cell_val;
-      cell.remove.apply(cell, arguments);
-    }
-    return Backbone.View.prototype.remove.apply(this, arguments);
-  }
-
-});
-
-/**
-   EmptyRow is a simple container view that takes a list of column and render a
-   row with a single column.
-
-   @class Backgrid.EmptyRow
-   @extends Backbone.View
-*/
-var EmptyRow = Backgrid.EmptyRow = Backbone.View.extend({
-
-  /** @property */
-  tagName: "tr",
-
-  /** @property {string|function(): string} */
-  emptyText: null,
-
-  /**
-     Initializer.
-
-     @param {Object} options
-     @param {string|function(): string} options.emptyText
-     @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns Column metadata.
-   */
-  initialize: function (options) {
-    this.emptyText = options.emptyText;
-    this.columns =  options.columns;
-  },
-
-  /**
-     Renders an empty row.
-  */
-  render: function () {
-    this.$el.empty();
-
-    var td = document.createElement("td");
-    td.setAttribute("colspan", this.columns.length);
-    var span = document.createElement("span");
-    span.innerHTML = _.result(this, "emptyText");
-    td.appendChild(span);
-
-    this.el.className = "empty";
-    this.el.appendChild(td);
-
-    return this;
-  }
-});
-
-/*
-  backgrid
-  http://github.com/cloudflare/backgrid
-
-  Copyright (c) 2013-present Cloudflare, Inc. and contributors
-  Licensed under the MIT license.
-*/
-
-/**
-   HeaderCell is a special cell class that renders a column header cell. If the
-   column is sortable, a sorter is also rendered and will trigger a table
-   refresh after sorting.
-
-   @class Backgrid.HeaderCell
-   @extends Backbone.View
- */
-var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({
-
-  /** @property */
-  tagName: "th",
-
-  /** @property */
-  events: {
-    "click button": "onClick"
-  },
-
-  /**
-     Initializer.
-
-     @param {Object} options
-     @param {Backgrid.Column|Object} options.column
-
-     @throws {TypeError} If options.column or options.collection is undefined.
-   */
-  initialize: function (options) {
-    this.column = options.column;
-    if (!(this.column instanceof Column)) {
-      this.column = new Column(this.column);
-    }
-
-    var column = this.column, collection = this.collection, $el = this.$el;
-
-    this.listenTo(column, "change:editable change:sortable change:renderable",
-                  function (col) {
-                    var changed = col.changedAttributes();
-                    for (var key in changed) {
-                      if (changed.hasOwnProperty(key)) {
-                        $el.toggleClass(key, changed[key]);
-                      }
-                    }
-                  });
-    this.listenTo(column, "change:direction", this.setCellDirection);
-    this.listenTo(column, "change:name change:label", this.render);
-
-    if (Backgrid.callByNeed(column.editable(), column, collection)) $el.addClass("editable");
-    if (Backgrid.callByNeed(column.sortable(), column, collection)) $el.addClass("sortable");
-    if (Backgrid.callByNeed(column.renderable(), column, collection)) $el.addClass("renderable");
-
-    this.listenTo(collection.fullCollection || collection, "backgrid:sorted", this.removeCellDirection);
-  },
-
-  /**
-     Event handler for the collection's `backgrid:sorted` event. Removes
-     all the CSS direction classes.
-   */
-  removeCellDirection: function () {
-    this.$el.removeClass("ascending").removeClass("descending");
-    this.column.set("direction", null);
-  },
-
-  /**
-     Event handler for the column's `change:direction` event. If this
-     HeaderCell's column is being sorted on, it applies the direction given as a
-     CSS class to the header cell. Removes all the CSS direction classes
-     otherwise.
-   */
-  setCellDirection: function (column, direction) {
-    this.$el.removeClass("ascending").removeClass("descending");
-    if (column.cid == this.column.cid) this.$el.addClass(direction);
-  },
-
-  /**
-     Event handler for the `click` event on the cell's anchor. If the column is
-     sortable, clicking on the anchor will cycle through 3 sorting orderings -
-     `ascending`, `descending`, and default.
-   */
-  onClick: function (e) {
-    e.preventDefault();
-
-    var column = this.column;
-    var collection = this.collection;
-    var event = "backgrid:sort";
-
-    function cycleSort(header, col) {
-      if (column.get("direction") === "ascending") collection.trigger(event, col, "descending");
-      else if (column.get("direction") === "descending") collection.trigger(event, col, null);
-      else collection.trigger(event, col, "ascending");
-    }
-
-    function toggleSort(header, col) {
-      if (column.get("direction") === "ascending") collection.trigger(event, col, "descending");
-      else collection.trigger(event, col, "ascending");
-    }
-
-    var sortable = Backgrid.callByNeed(column.sortable(), column, this.collection);
-    if (sortable) {
-      var sortType = column.get("sortType");
-      if (sortType === "toggle") toggleSort(this, column);
-      else cycleSort(this, column);
-    }
-  },
-
-  /**
-     Renders a header cell with a sorter, a label, and a class name for this
-     column.
-   */
-  render: function () {
-    this.$el.empty();
-    var column = this.column;
-    var sortable = Backgrid.callByNeed(column.sortable(), column, this.collection);
-    var label;
-    if(sortable){
-      label = $("<button>").text(column.get("label")).append("<span class='sort-caret' aria-hidden='true'></span>");
-    } else {
-      label = document.createTextNode(column.get("label"));
-    }
-
-    this.$el.append(label);
-    this.$el.addClass(column.get("name"));
-    this.$el.addClass(column.get("direction"));
-    this.$el.attr("role", "columnheader");
-    this.delegateEvents();
-    return this;
-  }
-
-});
-
-/**
-   EmptyHeaderCell is a special cell class that renders a column header cell.
-   The text is empty here and it is not sortable.
-
-   @class Backgrid.EmptyHeaderCell
-   @extends Backbone.View
- */
-var EmptyHeaderCell = Backgrid.EmptyHeaderCell = Backbone.View.extend({
-
-  /** @property */
-  tagName: "td",
-
-  /**
-     Initializer.
-
-     @param {Object} options
-     @param {Backgrid.Column|Object} options.column
-   */
-  initialize: function (options) {
-    this.column = options.column;
-  },
-
-  /**
-     Renders a empty header cell with no events
-   */
-  render: function () {
-    this.$el.empty();
-    this.$el.addClass(this.column.get("name"));
-    this.$el.addClass("renderable");
-    return this;
-  }
-});
-
-/**
-   HeaderRow is a controller for a row of header cells.
-
-   @class Backgrid.HeaderRow
-   @extends Backgrid.Row
- */
-Backgrid.HeaderRow = Backgrid.Row.extend({
-
-  /**
-     Initializer.
-
-     @param {Object} options
-     @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns
-     @param {Backgrid.HeaderCell} [options.headerCell] Customized default
-     HeaderCell for all the columns. Supply a HeaderCell class or instance to a
-     the `headerCell` key in a column definition for column-specific header
-     rendering.
-
-     @throws {TypeError} If options.columns or options.collection is undefined.
-   */
-  initialize: function () {
-    Backgrid.Row.prototype.initialize.apply(this, arguments);
-  },
-
-  makeCell: function (column, options) {
-    var headerCell = null;
-    if(column.get("label") === "" || !column.get("label")) {
-      headerCell = column.get("headerCell") || options.headerCell || EmptyHeaderCell;
-    } else {
-      headerCell = column.get("headerCell") || options.headerCell || HeaderCell;
-    }
-
-    headerCell = new headerCell({
-      column: column,
-      collection: this.collection
-    });
-    return headerCell;
-  }
-
-});
-
-/**
-   Header is a special structural view class that renders a table head with a
-   single row of header cells.
-
-   @class Backgrid.Header
-   @extends Backbone.View
- */
-var Header = Backgrid.Header = Backbone.View.extend({
-
-  /** @property */
-  tagName: "thead",
-
-  /**
-     Initializer. Initializes this table head view to contain a single header
-     row view.
-
-     @param {Object} options
-     @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns Column metadata.
-     @param {Backbone.Model} options.model The model instance to render.
-
-     @throws {TypeError} If options.columns or options.model is undefined.
-   */
-  initialize: function (options) {
-    this.columns = options.columns;
-    if (!(this.columns instanceof Backbone.Collection)) {
-      this.columns = new Columns(this.columns);
-    }
-
-    this.row = new Backgrid.HeaderRow({
-      columns: this.columns,
-      collection: this.collection
-    });
-  },
-
-  /**
-     Renders this table head with a single row of header cells.
-   */
-  render: function () {
-    this.$el.append(this.row.render().$el);
-    this.delegateEvents();
-    return this;
-  },
-
-  /**
-     Clean up this header and its row.
-
-     @chainable
-   */
-  remove: function () {
-    this.row.remove.apply(this.row, arguments);
-    return Backbone.View.prototype.remove.apply(this, arguments);
-  }
-
-});
-
-/*
-  backgrid
-  http://github.com/cloudflare/backgrid
-
-  Copyright (c) 2013-present Cloudflare, Inc. and contributors
-  Licensed under the MIT license.
-*/
-
-/**
-   Body is the table body which contains the rows inside a table. Body is
-   responsible for refreshing the rows after sorting, insertion and removal.
-
-   @class Backgrid.Body
-   @extends Backbone.View
-*/
-var Body = Backgrid.Body = Backbone.View.extend({
-
-  /** @property */
-  tagName: "tbody",
-
-  /**
-     Initializer.
-
-     @param {Object} options
-     @param {Backbone.Collection} options.collection
-     @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns
-     Column metadata.
-     @param {Backgrid.Row} [options.row=Backgrid.Row] The Row class to use.
-     @param {string|function(): string} [options.emptyText] The text to display in the empty row.
-
-     @throws {TypeError} If options.columns or options.collection is undefined.
-
-     See Backgrid.Row.
-  */
-  initialize: function (options) {
-
-    this.columns = options.columns;
-    if (!(this.columns instanceof Backbone.Collection)) {
-      this.columns = new Columns(this.columns);
-    }
-
-    this.row = options.row || this.row || Row;
-    this.rows = this.collection.map(function (model) {
-      return new this.row({
-        columns: this.columns,
-        model: model
-      });
-    }, this);
-
-    this.emptyText = options.emptyText;
-    this._unshiftEmptyRowMayBe();
-
-    var collection = this.collection;
-    this.listenTo(collection, "add", this.insertRow);
-    this.listenTo(collection, "remove", this.removeRow);
-    this.listenTo(collection, "sort", this.refresh);
-    this.listenTo(collection, "reset", this.refresh);
-    this.listenTo(collection, "backgrid:sort", this.sort);
-    this.listenTo(collection, "backgrid:edited", this.moveToNextCell);
-
-    this.listenTo(this.columns, "add remove", this.updateEmptyRow);
-  },
-
-  _unshiftEmptyRowMayBe: function () {
-    if (this.rows.length === 0 && this.emptyText != null) {
-      this.emptyRow = new EmptyRow({
-        emptyText: this.emptyText,
-        columns: this.columns
-      });
-
-      this.rows.unshift(this.emptyRow);
-      return true
-    }
-  },
-
-  /**
-     This method can be called either directly or as a callback to a
-     [Backbone.Collecton#add](http://backbonejs.org/#Collection-add) event.
-
-     When called directly, it accepts a model or an array of models and an
-     option hash just like
-     [Backbone.Collection#add](http://backbonejs.org/#Collection-add) and
-     delegates to it. Once the model is added, a new row is inserted into the
-     body and automatically rendered.
-
-     When called as a callback of an `add` event, splices a new row into the
-     body and renders it.
-
-     @param {Backbone.Model} model The model to render as a row.
-     @param {Backbone.Collection} collection When called directly, this
-     parameter is actually the options to
-     [Backbone.Collection#add](http://backbonejs.org/#Collection-add).
-     @param {Object} options When called directly, this must be null.
-
-     See:
-
-     - [Backbone.Collection#add](http://backbonejs.org/#Collection-add)
-  */
-  insertRow: function (model, collection, options) {
-
-    if (this.rows[0] instanceof EmptyRow) this.rows.pop().remove();
-
-    // insertRow() is called directly
-    if (!(collection instanceof Backbone.Collection) && !options) {
-      this.collection.add(model, (options = collection));
-      return;
-    }
-
-    var row = new this.row({
-      columns: this.columns,
-      model: model
-    });
-
-    var index = collection.indexOf(model);
-    this.rows.splice(index, 0, row);
-
-    var $el = this.$el;
-    var $children = $el.children();
-    var $rowEl = row.render().$el;
-
-    if (index >= $children.length) {
-      $el.append($rowEl);
-    }
-    else {
-      $children.eq(index).before($rowEl);
-    }
-
-    return this;
-  },
-
-  /**
-     The method can be called either directly or as a callback to a
-     [Backbone.Collection#remove](http://backbonejs.org/#Collection-remove)
-     event.
-
-     When called directly, it accepts a model or an array of models and an
-     option hash just like
-     [Backbone.Collection#remove](http://backbonejs.org/#Collection-remove) and
-     delegates to it. Once the model is removed, a corresponding row is removed
-     from the body.
-
-     When called as a callback of a `remove` event, splices into the rows and
-     removes the row responsible for rendering the model.
-
-     @param {Backbone.Model} model The model to remove from the body.
-     @param {Backbone.Collection} collection When called directly, this
-     parameter is actually the options to
-     [Backbone.Collection#remove](http://backbonejs.org/#Collection-remove).
-     @param {Object} options When called directly, this must be null.
-
-     See:
-
-     - [Backbone.Collection#remove](http://backbonejs.org/#Collection-remove)
-  */
-  removeRow: function (model, collection, options) {
-
-    // removeRow() is called directly
-    if (!options) {
-      this.collection.remove(model, (options = collection));
-      if (this._unshiftEmptyRowMayBe()) {
-        this.render();
-      }
-      return;
-    }
-
-    if (_.isUndefined(options.render) || options.render) {
-      this.rows[options.index].remove();
-    }
-
-    this.rows.splice(options.index, 1);
-    if (this._unshiftEmptyRowMayBe()) {
-      this.render();
-    }
-
-    return this;
-  },
-
-  /**
-     Rerender the EmptyRow which empties the DOM element, creates the td with the
-     updated colspan, and appends it back into the DOM
-  */
-
-  updateEmptyRow: function () {
-    if (this.emptyRow != null) {
-      this.emptyRow.render();
-    }
-  },
-
-  /**
-     Reinitialize all the rows inside the body and re-render them. Triggers a
-     Backbone `backgrid:refresh` event from the collection along with the body
-     instance as its sole parameter when done.
-  */
-  refresh: function () {
-    for (let row_val of this.rows) {
-      row_val.remove();
-    }
-
-    this.rows = this.collection.map(function (model) {
-      return new this.row({
-        columns: this.columns,
-        model: model
-      });
-    }, this);
-    this._unshiftEmptyRowMayBe();
-
-    this.render();
-
-    this.collection.trigger("backgrid:refresh", this);
-
-    return this;
-  },
-
-  /**
-     Renders all the rows inside this body. If the collection is empty and
-     `options.emptyText` is defined and not null in the constructor, an empty
-     row is rendered, otherwise no row is rendered.
-  */
-  render: function () {
-    this.$el.empty();
-
-    var fragment = document.createDocumentFragment();
-    for (let row_val of this.rows) {
-      var row = row_val;
-      fragment.appendChild(row.render().el);
-    }
-
-    this.el.appendChild(fragment);
-
-    this.delegateEvents();
-
-    return this;
-  },
-
-  /**
-     Clean up this body and it's rows.
-
-     @chainable
-  */
-  remove: function () {
-    for (let row_val of this.rows) {
-      var row = row_val;
-      row.remove.apply(row, arguments);
-    }
-    return Backbone.View.prototype.remove.apply(this, arguments);
-  },
-
-  /**
-     If the underlying collection is a Backbone.PageableCollection in
-     server-mode or infinite-mode, a page of models is fetched after sorting is
-     done on the server.
-
-     If the underlying collection is a Backbone.PageableCollection in
-     client-mode, or any
-     [Backbone.Collection](http://backbonejs.org/#Collection) instance, sorting
-     is done on the client side. If the collection is an instance of a
-     Backbone.PageableCollection, sorting will be done globally on all the pages
-     and the current page will then be returned.
-
-     Triggers a Backbone `backgrid:sorted` event from the collection when done
-     with the column, direction and a reference to the collection.
-
-     @param {Backgrid.Column|string} column
-     @param {null|"ascending"|"descending"} direction
-
-     See [Backbone.Collection#comparator](http://backbonejs.org/#Collection-comparator)
-  */
-  sort: function (column, direction) {
-
-    if (!_.contains(["ascending", "descending", null], direction)) {
-      throw new RangeError('direction must be one of "ascending", "descending" or `null`');
-    }
-
-    if (_.isString(column)) column = this.columns.findWhere({name: column});
-
-    var collection = this.collection;
-
-    var order;
-    if (direction === "ascending") order = -1;
-    else if (direction === "descending") order = 1;
-    else order = null;
-
-    var comparator = this.makeComparator(column.get("name"), order,
-                                         order ?
-                                         column.sortValue() :
-                                         function (model) {
-                                           return model.cid.replace('c', '') * 1;
-                                         });
-
-    if (Backbone.PageableCollection &&
-        collection instanceof Backbone.PageableCollection) {
-
-      collection.setSorting(order && column.get("name"), order,
-                            {sortValue: column.sortValue()});
-
-      if (collection.fullCollection) {
-        // If order is null, pageable will remove the comparator on both sides,
-        // in this case the default insertion order comparator needs to be
-        // attached to get back to the order before sorting.
-        if (collection.fullCollection.comparator == null) {
-          collection.fullCollection.comparator = comparator;
-        }
-        collection.fullCollection.sort();
-        collection.trigger("backgrid:sorted", column, direction, collection);
-        column.set("direction", direction);
-      }
-      else collection.fetch({reset: true, success: function () {
-        collection.trigger("backgrid:sorted", column, direction, collection);
-        column.set("direction", direction);
-      }});
-    }
-    else {
-      collection.comparator = comparator;
-      collection.sort();
-      collection.trigger("backgrid:sorted", column, direction, collection);
-      column.set("direction", direction);
-    }
-
-    return this;
-  },
-
-  makeComparator: function (attr, order, func) {
-
-    return function (left, right) {
-      // extract the values from the models
-      var l = func(left, attr), r = func(right, attr), t;
-
-      // if descending order, swap left and right
-      if (order === 1) {
-        t = l;
-        l = r;
-        r = t;
-      }
-
-      // compare as usual
-      if (l === r) return 0;
-      else if (l < r) return -1;
-      return 1;
-    };
-  },
-
-  /**
-     Moves focus to the next renderable and editable cell and return the
-     currently editing cell to display mode.
-
-     Triggers a `backgrid:next` event on the model with the indices of the row
-     and column the user *intended* to move to, and whether the intended move
-     was going to go out of bounds. Note that *out of bound* always means an
-     attempt to go past the end of the last row.
-
-     @param {Backbone.Model} model The originating model
-     @param {Backgrid.Column} column The originating model column
-     @param {Backgrid.Command} command The Command object constructed from a DOM
-     event
-  */
-  moveToNextCell: function (model, column, command) {
-    var i = this.collection.indexOf(model);
-    var j = this.columns.indexOf(column);
-    var cell, renderable, editable, m, n;
-
-    // return if model being edited in a different grid
-    if (j === -1) return this;
-
-    this.rows[i].cells[j].exitEditMode();
-
-    if (command.moveUp() || command.moveDown() || command.moveLeft() ||
-        command.moveRight() || command.save()) {
-      var l = this.columns.length;
-      var maxOffset = l * this.collection.length;
-
-      if (command.moveUp() || command.moveDown()) {
-        m = i + (command.moveUp() ? -1 : 1);
-        var row = this.rows[m];
-        if (row) {
-          cell = row.cells[j];
-          if (Backgrid.callByNeed(cell.column.editable(), cell.column, model)) {
-            cell.enterEditMode();
-            model.trigger("backgrid:next", m, j, false);
-          }
-        }
-        else model.trigger("backgrid:next", m, j, true);
-      }
-      else if (command.moveLeft() || command.moveRight()) {
-        var right = command.moveRight();
-        for (var offset = i * l + j + (right ? 1 : -1);
-             offset >= 0 && offset < maxOffset;
-             right ? offset++ : offset--) {
-          m = ~~(offset / l);
-          n = offset - m * l;
-          cell = this.rows[m].cells[n];
-          renderable = Backgrid.callByNeed(cell.column.renderable(), cell.column, cell.model);
-          editable = Backgrid.callByNeed(cell.column.editable(), cell.column, model);
-          if (renderable && editable) {
-            cell.enterEditMode();
-            model.trigger("backgrid:next", m, n, false);
-            break;
-          }
-        }
-
-        if (offset == maxOffset) {
-          model.trigger("backgrid:next", ~~(offset / l), offset - m * l, true);
-        }
-      }
-    }
-
-    return this;
-  }
-});
-
-/*
-  backgrid
-  http://github.com/cloudflare/backgrid
-
-  Copyright (c) 2013-present Cloudflare, Inc. and contributors
-  Licensed under the MIT license.
-*/
-
-/**
-   A Footer is a generic class that only defines a default tag `tfoot` and
-   number of required parameters in the initializer.
-
-   @abstract
-   @class Backgrid.Footer
-   @extends Backbone.View
- */
-Backgrid.Footer = Backbone.View.extend({
-
-  /** @property */
-  tagName: "tfoot",
-
-  /**
-     Initializer.
-
-     @param {Object} options
-     @param {Backbone.Collection.<Backgrid.Column>|Array.<Backgrid.Column>|Array.<Object>} options.columns
-     Column metadata.
-     @param {Backbone.Collection} options.collection
-
-     @throws {TypeError} If options.columns or options.collection is undefined.
-  */
-  initialize: function (options) {
-    this.columns = options.columns;
-    if (!(this.columns instanceof Backbone.Collection)) {
-      this.columns = new Backgrid.Columns(this.columns);
-    }
-  }
-
-});
-
-/*
-  backgrid
-  http://github.com/cloudflare/backgrid
-
-  Copyright (c) 2013-present Cloudflare, Inc. and contributors
-  Licensed under the MIT license.
-*/
-
-/**
-   Grid represents a data grid that has a header, body and an optional footer.
-
-   By default, a Grid treats each model in a collection as a row, and each
-   attribute in a model as a column. To render a grid you must provide a list of
-   column metadata and a collection to the Grid constructor. Just like any
-   Backbone.View class, the grid is rendered as a DOM node fragment when you
-   call render().
-
-       var grid = Backgrid.Grid({
-         columns: [{ name: "id", label: "ID", type: "string" },
-          // ...
-         ],
-         collections: books
-       });
-
-       $("#table-container").append(grid.render().el);
-
-   Optionally, if you want to customize the rendering of the grid's header and
-   footer, you may choose to extend Backgrid.Header and Backgrid.Footer, and
-   then supply that class or an instance of that class to the Grid constructor.
-   See the documentation for Header and Footer for further details.
-
-       var grid = Backgrid.Grid({
-         columns: [{ name: "id", label: "ID", type: "string" }],
-         collections: books,
-         header: Backgrid.Header.extend({
-              //...
-         }),
-         footer: Backgrid.Paginator
-       });
-
-   Finally, if you want to override how the rows are rendered in the table body,
-   you can supply a Body subclass as the `body` attribute that uses a different
-   Row class.
-
-   @class Backgrid.Grid
-   @extends Backbone.View
-
-   See:
-
-   - Backgrid.Column
-   - Backgrid.Header
-   - Backgrid.Body
-   - Backgrid.Row
-   - Backgrid.Footer
-*/
-Backgrid.Grid = Backbone.View.extend({
-
-  /** @property */
-  tagName: "table",
-
-  /** @property */
-  className: "backgrid",
-
-  /** @property */
-  header: Header,
-
-  /** @property */
-  body: Body,
-
-  /** @property */
-  footer: null,
-
-  /** @property */
-  attr: null,
-
-  /**
-     Initializes a Grid instance.
-
-     @param {Object} options
-     @param {Backbone.Collection.<Backgrid.Columns>|Array.<Backgrid.Column>|Array.<Object>} options.columns Column metadata.
-     @param {Backbone.Collection} options.collection The collection of tabular model data to display.
-     @param {string} [options.caption=string] An optional caption to be added to the table.
-     @param {Backgrid.Header} [options.header=Backgrid.Header] An optional Header class to override the default.
-     @param {Backgrid.Body} [options.body=Backgrid.Body] An optional Body class to override the default.
-     @param {Backgrid.Row} [options.row=Backgrid.Row] An optional Row class to override the default.
-     @param {Backgrid.Footer} [options.footer=Backgrid.Footer] An optional Footer class.
-
-   */
-  initialize: function (options) {
-    // Convert the list of column objects here first so the subviews don't have
-    // to.
-    if (!(options.columns instanceof Backbone.Collection)) {
-      options.columns = new Columns(options.columns || this.columns);
-    }
-    this.columns = options.columns;
-
-    this.caption = options.caption;
-
-    var filteredOptions = _.omit(options, ["el", "id", "attributes",
-                                           "className", "tagName", "events"]);
-
-    // must construct body first so it listens to backgrid:sort first
-    this.body = options.body || this.body;
-    this.body = new this.body(filteredOptions);
-
-    this.header = options.header || this.header;
-    if (this.header) {
-      this.header = new this.header(filteredOptions);
-    }
-
-    this.footer = options.footer || this.footer;
-    if (this.footer) {
-      this.footer = new this.footer(filteredOptions);
-    }
-
-    this.attr = options.attr || {};
-
-    this.listenTo(this.columns, "reset", function () {
-      if (this.header) {
-        this.header = new (this.header.remove().constructor)(filteredOptions);
-      }
-      this.body = new (this.body.remove().constructor)(filteredOptions);
-      if (this.footer) {
-        this.footer = new (this.footer.remove().constructor)(filteredOptions);
-      }
-      this.render();
-    });
-  },
-
-  /**
-     Delegates to Backgrid.Body#insertRow.
-   */
-  insertRow: function () {
-    this.body.insertRow.apply(this.body, arguments);
-    return this;
-  },
-
-  /**
-     Delegates to Backgrid.Body#removeRow.
-   */
-  removeRow: function () {
-    this.body.removeRow.apply(this.body, arguments);
-    return this;
-  },
-
-  /**
-     Delegates to Backgrid.Columns#add for adding a column. Subviews can listen
-     to the `add` event from their internal `columns` if rerendering needs to
-     happen.
-
-     @param {Object} [options] Options for `Backgrid.Columns#add`.
-   */
-  insertColumn: function () {
-    this.columns.add.apply(this.columns, arguments);
-    return this;
-  },
-
-  /**
-     Delegates to Backgrid.Columns#remove for removing a column. Subviews can
-     listen to the `remove` event from the internal `columns` if rerendering
-     needs to happen.
-
-     @param {Object} [options] Options for `Backgrid.Columns#remove`.
-   */
-  removeColumn: function () {
-    this.columns.remove.apply(this.columns, arguments);
-    return this;
-  },
-
-  /**
-     Delegates to Backgrid.Body#sort.
-   */
-  sort: function () {
-    this.body.sort.apply(this.body, arguments);
-    return this;
-  },
-
-  /**
-     Renders the grid's caption, then header, then footer, then finally the body. Triggers a
-     Backbone `backgrid:rendered` event along with a reference to the grid when
-     the it has successfully been rendered.
-   */
-  render: function () {
-    this.$el.empty();
-
-    if (this.caption) {
-      this.$el.append($("<caption>").text(this.caption));
-    }
-
-    if (this.header) {
-      this.$el.append(this.header.render().$el);
-    }
-
-    if (this.footer) {
-      this.$el.append(this.footer.render().$el);
-    }
-
-    this.$el.append(this.body.render().$el);
-    this.$el.attr("role", "table");
-    this.$el.attr(this.attr);
-
-    this.delegateEvents();
-
-    this.trigger("backgrid:rendered", this);
-
-    return this;
-  },
-
-  /**
-     Clean up this grid and its subviews.
-
-     @chainable
-   */
-  remove: function () {
-    this.header && this.header.remove.apply(this.header, arguments);
-    this.body.remove.apply(this.body, arguments);
-    this.footer && this.footer.remove.apply(this.footer, arguments);
-    return Backbone.View.prototype.remove.apply(this, arguments);
-  }
-
-});
-  return Backgrid;
-}));
diff --git a/web/regression/javascript/backform_controls/keyboardshortcut_spec.js b/web/regression/javascript/backform_controls/keyboardshortcut_spec.js
deleted file mode 100644
index 8dbcf5851..000000000
--- a/web/regression/javascript/backform_controls/keyboardshortcut_spec.js
+++ /dev/null
@@ -1,434 +0,0 @@
-//////////////////////////////////////////////////////////////////////////
-//
-// pgAdmin 4 - PostgreSQL Tools
-//
-// Copyright (C) 2013 - 2022, The pgAdmin Development Team
-// This software is released under the PostgreSQL Licence
-//
-//////////////////////////////////////////////////////////////////////////
-define([
-  'jquery',
-  'backbone',
-  'pgadmin.backform',
-], function ($, Backbone, Backform) {
-  describe('KeyboardshortcutControl', function () {
-    let field, innerFields, control, model;
-
-    beforeEach(() => {
-
-      innerFields = [
-        {'name': 'key', 'type': 'keyCode', 'label': 'Key'},
-        {'name': 'alt_option', 'type': 'checkbox',
-          'label': 'Alt/Option'},
-        {'name': 'control', 'type': 'checkbox',
-          'label': 'Ctrl'},
-        {'name': 'shift', 'type': 'checkbox', 'label': 'Shift'},
-      ];
-
-      model = new Backbone.Model({
-        'shortcut': {
-          'control': true,
-          'shift': false,
-          'alt_option': true,
-          'key': {
-            'key_code': 73,
-            'char': 'I',
-          },
-        },
-      });
-
-      field = new Backform.Field({
-        id: 'shortcut',
-        name: 'shortcut',
-        control: 'keyboardShortcut',
-        label: 'Keyboard shortcut',
-        fields: innerFields,
-      });
-
-      control = new (field.get('control')) ({
-        field: field,
-        model: model,
-      });
-
-      control.render();
-
-    });
-
-    describe('keyboardShortcut UI setup', function () {
-
-      it('keyboard shortcut control should be rendered with inner fields', function () {
-
-        expect(control.$el.find('input:text[name="key"]')[0].value).toEqual('I');
-
-        expect(control.$el.find('input:checkbox[name="alt_option"]')[0].checked).toBeTruthy();
-
-        expect(control.$el.find('input:checkbox[name="control"]')[0].checked).toBeTruthy();
-
-        expect(control.$el.find('input:checkbox[name="shift"]')[0].checked).toBeFalsy();
-
-      });
-    });
-
-    describe('onModelChange', function () {
-      beforeEach((done) => {
-
-        done();
-
-      });
-
-      it('when model "key" value changes UI and innerModel should update new "key" value', function (done) {
-
-        expect(control.$el.find('input:text[name="key"]')[0].value).toEqual('I');
-        expect(control.innerModel.get('key')).toEqual({
-          'key_code': 73,
-          'char': 'I',
-        });
-
-        let val = $.extend(true, {}, model.get(field.get('name')));
-
-        model.set(field.get('name'),
-          $.extend(true, val, {
-            'key': {
-              'key_code': 65,
-              'char': 'A',
-            },
-          })
-        );
-
-        // wait until UI updates.
-        setTimeout(function() {
-          // this should change
-          expect(control.$el.find('input:text[name="key"]')[0].value).toEqual('A');
-          expect(control.innerModel.get('key')).toEqual({
-            'key_code': 65,
-            'char': 'A',
-          });
-
-          // below three should not change.
-          expect(control.$el.find('input:checkbox[name="alt_option"]')[0].checked).toBeTruthy();
-          expect(control.innerModel.get('alt_option')).toBeTruthy();
-
-          expect(control.$el.find('input:checkbox[name="control"]')[0].checked).toBeTruthy();
-          expect(control.innerModel.get('control')).toBeTruthy();
-
-          expect(control.$el.find('input:checkbox[name="shift"]')[0].checked).toBeFalsy();
-          expect(control.innerModel.get('shift')).toBeFalsy();
-
-          done();
-        }, 100);
-
-      });
-
-      it('when model "control" value changes UI and innerModel should update new "control" value', function (done) {
-
-        expect(control.$el.find('input:checkbox[name="control"]')[0].checked).toBeTruthy();
-        expect(control.innerModel.get('control')).toBeTruthy();
-
-        let val = $.extend(true, {}, model.get(field.get('name')));
-
-        model.set(field.get('name'),
-          $.extend(true, val, {
-            'control': false,
-          })
-        );
-
-        // wait until UI updates.
-        setTimeout(function() {
-          // this should change
-          expect(control.$el.find('input:checkbox[name="control"]')[0].checked).toBeFalsy();
-          expect(control.innerModel.get('control')).toBeFalsy();
-
-          // below three should not change.
-          expect(control.$el.find('input:checkbox[name="alt_option"]')[0].checked).toBeTruthy();
-          expect(control.innerModel.get('alt_option')).toBeTruthy();
-
-          expect(control.$el.find('input:text[name="key"]')[0].value).toEqual('I');
-          expect(control.innerModel.get('key')).toEqual({
-            'key_code': 73,
-            'char': 'I',
-          });
-
-          expect(control.$el.find('input:checkbox[name="shift"]')[0].checked).toBeFalsy();
-          expect(control.innerModel.get('shift')).toBeFalsy();
-
-          done();
-        }, 100);
-
-      });
-
-      it('when model "shift" value changes UI and innerModel should update new "shift" value', function (done) {
-
-        expect(control.$el.find('input:checkbox[name="shift"]')[0].checked).toBeFalsy();
-        expect(control.innerModel.get('shift')).toBeFalsy();
-
-        let val = $.extend(true, {}, model.get(field.get('name')));
-
-        model.set(field.get('name'),
-          $.extend(true, val, {
-            'shift': true,
-          })
-        );
-
-        // wait until UI updates.
-        setTimeout(function() {
-          // this should change
-          expect(control.$el.find('input:checkbox[name="shift"]')[0].checked).toBeTruthy();
-          expect(control.innerModel.get('shift')).toBeTruthy();
-
-          // below three should not change.
-          expect(control.$el.find('input:checkbox[name="alt_option"]')[0].checked).toBeTruthy();
-          expect(control.innerModel.get('alt_option')).toBeTruthy();
-
-          expect(control.$el.find('input:text[name="key"]')[0].value).toEqual('I');
-          expect(control.innerModel.get('key')).toEqual({
-            'key_code': 73,
-            'char': 'I',
-          });
-
-          expect(control.$el.find('input:checkbox[name="control"]')[0].checked).toBeTruthy();
-          expect(control.innerModel.get('control')).toBeTruthy();
-
-          done();
-        }, 100);
-
-      });
-
-      it('when model "alt_option" value changes UI and innerModel should update new "alt_option" value', function (done) {
-
-        expect(control.$el.find('input:checkbox[name="alt_option"]')[0].checked).toBeTruthy();
-        expect(control.innerModel.get('alt_option')).toBeTruthy();
-
-        let val = $.extend(true, {}, model.get(field.get('name')));
-
-        model.set(field.get('name'),
-          $.extend(true, val, {
-            'alt_option': false,
-          })
-        );
-
-        // wait until UI updates.
-        setTimeout(function() {
-          // this should change
-          expect(control.$el.find('input:checkbox[name="alt_option"]')[0].checked).toBeFalsy();
-          expect(control.innerModel.get('alt_option')).toBeFalsy();
-
-          // below three should not change.
-          expect(control.$el.find('input:checkbox[name="shift"]')[0].checked).toBeFalsy();
-          expect(control.innerModel.get('shift')).toBeFalsy();
-
-          expect(control.$el.find('input:text[name="key"]')[0].value).toEqual('I');
-          expect(control.innerModel.get('key')).toEqual({
-            'key_code': 73,
-            'char': 'I',
-          });
-
-          expect(control.$el.find('input:checkbox[name="control"]')[0].checked).toBeTruthy();
-          expect(control.innerModel.get('control')).toBeTruthy();
-
-          done();
-        }, 100);
-
-      });
-
-    });
-
-    describe('onInnerModelChange', function () {
-      beforeEach((done) => {
-
-        done();
-
-      });
-
-      it('when innerModel "key" value changes UI and model should update new "key" value', function (done) {
-
-        expect(control.$el.find('input:text[name="key"]')[0].value).toEqual('I');
-        expect(model.get(field.get('name'))).toEqual({
-          'control': true,
-          'shift': false,
-          'alt_option': true,
-          'key': {
-            'key_code': 73,
-            'char': 'I',
-          },
-        });
-
-        control.innerModel.set('key',
-          {
-            'key_code': 65,
-            'char': 'A',
-          }
-        );
-
-        // wait until UI updates.
-        setTimeout(function() {
-          // this should change
-          expect(control.$el.find('input:text[name="key"]')[0].value).toEqual('A');
-          expect(model.get(field.get('name'))).toEqual({
-            'control': true,
-            'shift': false,
-            'alt_option': true,
-            'key': {
-              'key_code': 65,
-              'char': 'A',
-            },
-          });
-
-          // below three should not change.
-          expect(control.$el.find('input:checkbox[name="alt_option"]')[0].checked).toBeTruthy();
-
-          expect(control.$el.find('input:checkbox[name="control"]')[0].checked).toBeTruthy();
-
-          expect(control.$el.find('input:checkbox[name="shift"]')[0].checked).toBeFalsy();
-
-          done();
-        }, 100);
-
-      });
-
-      it('when innerModel "control" value changes UI and model should update new "control" value', function (done) {
-
-        expect(control.$el.find('input:checkbox[name="control"]')[0].checked).toBeTruthy();
-        expect(model.get(field.get('name'))).toEqual({
-          'control': true,
-          'shift': false,
-          'alt_option': true,
-          'key': {
-            'key_code': 73,
-            'char': 'I',
-          },
-        });
-
-        control.innerModel.set('control', false);
-
-        // wait until UI updates.
-        setTimeout(function() {
-          // this should change
-          expect(control.$el.find('input:checkbox[name="control"]')[0].checked).toBeFalsy();
-          expect(model.get(field.get('name'))).toEqual({
-            'control': false,
-            'shift': false,
-            'alt_option': true,
-            'key': {
-              'key_code': 73,
-              'char': 'I',
-            },
-          });
-
-          // below three should not change.
-          expect(control.$el.find('input:checkbox[name="alt_option"]')[0].checked).toBeTruthy();
-
-          expect(control.$el.find('input:text[name="key"]')[0].value).toEqual('I');
-
-          expect(control.$el.find('input:checkbox[name="shift"]')[0].checked).toBeFalsy();
-
-          done();
-        }, 100);
-
-      });
-
-      it('when innerModel "shift" value changes UI and model should update new "shift" value', function (done) {
-
-        expect(control.$el.find('input:checkbox[name="shift"]')[0].checked).toBeFalsy();
-        expect(model.get(field.get('name'))).toEqual({
-          'control': true,
-          'shift': false,
-          'alt_option': true,
-          'key': {
-            'key_code': 73,
-            'char': 'I',
-          },
-        });
-
-        control.innerModel.set('shift', true);
-
-        // wait until UI updates.
-        setTimeout(function() {
-          // this should change
-          expect(control.$el.find('input:checkbox[name="shift"]')[0].checked).toBeTruthy();
-          expect(model.get(field.get('name'))).toEqual({
-            'control': true,
-            'shift': true,
-            'alt_option': true,
-            'key': {
-              'key_code': 73,
-              'char': 'I',
-            },
-          });
-
-          // below three should not change.
-          expect(control.$el.find('input:checkbox[name="alt_option"]')[0].checked).toBeTruthy();
-
-          expect(control.$el.find('input:text[name="key"]')[0].value).toEqual('I');
-
-          expect(control.$el.find('input:checkbox[name="control"]')[0].checked).toBeTruthy();
-
-          done();
-        }, 100);
-
-      });
-
-      it('when innerModel "alt_option" value changes UI and model should update new "alt_option" value', function (done) {
-
-        expect(control.$el.find('input:checkbox[name="alt_option"]')[0].checked).toBeTruthy();
-        expect(model.get(field.get('name'))).toEqual({
-          'control': true,
-          'shift': false,
-          'alt_option': true,
-          'key': {
-            'key_code': 73,
-            'char': 'I',
-          },
-        });
-
-        control.innerModel.set('alt_option', false);
-
-        // wait until UI updates.
-        setTimeout(function() {
-          // this should change
-          expect(control.$el.find('input:checkbox[name="alt_option"]')[0].checked).toBeFalsy();
-          expect(model.get(field.get('name'))).toEqual({
-            'control': true,
-            'shift': false,
-            'alt_option': false,
-            'key': {
-              'key_code': 73,
-              'char': 'I',
-            },
-          });
-
-          // below three should not change.
-          expect(control.$el.find('input:checkbox[name="shift"]')[0].checked).toBeFalsy();
-
-          expect(control.$el.find('input:text[name="key"]')[0].value).toEqual('I');
-
-          expect(control.$el.find('input:checkbox[name="control"]')[0].checked).toBeTruthy();
-
-          done();
-        }, 100);
-
-      });
-
-    });
-
-    describe('remove keyboardShortcut control', function () {
-
-      beforeEach(function() {
-
-        spyOn(control, 'cleanup').and.callThrough();
-
-      });
-
-      it('when removed it should remove all of it\' controls', function () {
-
-        control.remove();
-
-        expect(control.cleanup).toHaveBeenCalled();
-
-        expect(control.controls.length).toEqual(0);
-
-      });
-
-    });
-
-  });
-});
diff --git a/web/regression/javascript/backform_controls/keycode_spec.js b/web/regression/javascript/backform_controls/keycode_spec.js
deleted file mode 100644
index e45baf8a8..000000000
--- a/web/regression/javascript/backform_controls/keycode_spec.js
+++ /dev/null
@@ -1,199 +0,0 @@
-//////////////////////////////////////////////////////////////////////////
-//
-// pgAdmin 4 - PostgreSQL Tools
-//
-// Copyright (C) 2013 - 2022, The pgAdmin Development Team
-// This software is released under the PostgreSQL Licence
-//
-//////////////////////////////////////////////////////////////////////////
-define([
-  'backbone',
-  'pgadmin.backform',
-], function (Backbone, Backform) {
-  describe('keyCodeControl', function () {
-    let field, control, model, event;
-
-    beforeEach(() => {
-      model = new Backbone.Model({
-        'key': {
-          'key_code': 65,
-          'char': 'A',
-        },
-      });
-
-      field = new Backform.Field({
-        id: 'key',
-        name: 'key',
-        control: 'keyCode',
-        label: 'Key',
-      });
-
-      control = new (field.get('control')) ({
-        field: field,
-        model: model,
-      });
-
-      control.render();
-
-      event = {
-        which: -1,
-        keyCode: -1,
-        key: '',
-        preventDefault: jasmine.createSpy('preventDefault'),
-      };
-
-    });
-
-    describe('onkeyDown', function () {
-
-      beforeEach((done) => {
-
-        spyOn(model, 'set').and.callThrough();
-
-        spyOn(control, 'onkeyDown').and.callThrough();
-
-        done();
-      });
-
-      it('when key with escapeKeyCode is pressed model should not update', function (done) {
-        event.which = 16;
-        event.keyCode = 16;
-        event.key = 'Shift';
-
-        control.onkeyDown(event);
-
-        expect(control.onkeyDown).toHaveBeenCalled();
-
-        expect(model.set).not.toHaveBeenCalled();
-
-        expect(event.preventDefault).not.toHaveBeenCalled();
-
-        expect(model.get('key')).toEqual({
-          'key_code': 65,
-          'char': 'A',
-        });
-
-        // wait until UI updates.
-        setTimeout(function() {
-          expect(control.$el.find('input')[0].value).toEqual('A');
-          done();
-        }, 100);
-
-      });
-
-      it('when key other than escapeKeyCode is pressed model should update', function (done) {
-        event.which = 66;
-        event.keyCode = 66;
-        event.key = 'B';
-
-        control.onkeyDown(event);
-
-        expect(control.onkeyDown).toHaveBeenCalled();
-
-        expect(model.set).toHaveBeenCalled();
-
-        expect(event.preventDefault).toHaveBeenCalled();
-
-        expect(model.get('key')).toEqual({
-          'key_code': 66,
-          'char': 'B',
-        });
-
-        // wait until UI updates.
-        setTimeout(function() {
-          expect(control.$el.find('input')[0].value).toEqual('B');
-          done();
-        }, 100);
-
-      });
-
-    });
-
-    describe('onkeyUp', function () {
-
-      beforeEach((done) => {
-        spyOn(control, 'preventEvent').and.callThrough();
-
-        event.stopPropagation = jasmine.createSpy('stopPropagation');
-
-        event.stopImmediatePropagation = jasmine.createSpy('stopImmediatePropagation');
-
-        done();
-
-      });
-
-      it('when key with escapeKeyCode is pressed and released event should be propagated', function (done) {
-        event.which = 17;
-        event.keyCode = 17;
-        event.key = 'Ctrl';
-
-        control.preventEvent(event);
-
-        expect(control.preventEvent).toHaveBeenCalled();
-
-        expect(event.preventDefault).not.toHaveBeenCalled();
-
-        expect(event.stopPropagation).not.toHaveBeenCalled();
-
-        expect(event.stopImmediatePropagation).not.toHaveBeenCalled();
-
-        // wait until UI updates.
-        setTimeout(function() {
-          expect(control.$el.find('input')[0].value).toEqual('A');
-          done();
-        }, 100);
-
-      });
-
-      it('when key other than escapeKeyCode is pressed and released event should not be propagated', function (done) {
-        event.which = 66;
-        event.keyCode = 66;
-        event.key = 'B';
-
-        control.preventEvent(event);
-
-        expect(control.preventEvent).toHaveBeenCalled();
-
-        expect(event.preventDefault).toHaveBeenCalled();
-
-        expect(event.stopPropagation).toHaveBeenCalled();
-
-        expect(event.stopImmediatePropagation).toHaveBeenCalled();
-
-        // wait until UI updates.
-        setTimeout(function() {
-          expect(control.$el.find('input')[0].value).toEqual('A');
-          done();
-        }, 100);
-
-      });
-    });
-
-    describe('onModelChange', function () {
-      beforeEach((done) => {
-
-        done();
-
-      });
-
-      it('when model changes UI should update', function (done) {
-
-        expect(control.$el.find('input')[0].value).toEqual('A');
-
-        model.set('key', {
-          'key_code': 67,
-          'char': 'C',
-        });
-
-        // wait until UI updates.
-        setTimeout(function() {
-          expect(control.$el.find('input')[0].value).toEqual('C');
-          done();
-        }, 100);
-
-      });
-
-    });
-
-  });
-});
diff --git a/web/webpack.shim.js b/web/webpack.shim.js
index 793afd856..d01d6203e 100644
--- a/web/webpack.shim.js
+++ b/web/webpack.shim.js
@@ -48,26 +48,6 @@ let webpackShimConfig = {
         'jquery:$', // Provide jquery as dependency with name $
       ],
     },
-    'backgrid': {
-      'deps': ['backform'],
-      'exports': 'Backgrid',
-    },
-    'pgadmin.backform': {
-      'deps': ['backform', 'pgadmin.backgrid', 'select2', 'bootstrap.toggle'],
-    },
-    'pgadmin.backgrid': {
-      'deps': ['backgrid', 'bootstrap.datetimepicker', 'bootstrap.toggle'],
-    },
-
-    'backgrid.select.all': {
-      'deps': ['backgrid'],
-    },
-    'backgrid.paginator': {
-      'deps': ['backgrid', 'backbone.paginator'],
-    },
-    'backgrid.filter': {
-      'deps': ['backgrid'],
-    },
     'jquery.event.drag': {
       'deps': ['jquery'], 'exports': 'jQuery.fn.drag',
     },
@@ -149,15 +129,9 @@ let webpackShimConfig = {
     // Backbone and Backgrid
     'backbone': path.join(__dirname, './node_modules/backbone/backbone'),
     'backbone.undo': path.join(__dirname, './node_modules/backbone-undo/Backbone.Undo'),
-    'backform': path.join(__dirname, './pgadmin/static/vendor/backform/backform'),
-    'backgrid': path.join(__dirname, './pgadmin/static/vendor/backgrid/backgrid'),
     'bootstrap.datetimepicker': path.join(__dirname, './node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min'),
     'bootstrap.toggle': path.join(__dirname, './node_modules/bootstrap4-toggle/js/bootstrap4-toggle.min'),
     'select2': path.join(__dirname, './node_modules/select2/dist/js/select2.full'),
-    'backgrid.filter': path.join(__dirname, './node_modules/backgrid-filter/backgrid-filter'),
-    'backgrid.select.all': path.join(__dirname, './pgadmin/static/vendor/backgrid/backgrid-select-all'),
-    'pgadmin.backform': path.join(__dirname, './pgadmin/static/js/backform.pgadmin'),
-    'pgadmin.backgrid': path.join(__dirname, './pgadmin/static/js/backgrid.pgadmin'),
 
     'pgadmin.about': path.join(__dirname, './pgadmin/about/static/js/about'),
     'pgadmin.authenticate.kerberos': path.join(__dirname, './pgadmin/authenticate/static/js/kerberos'),
@@ -178,11 +152,8 @@ let webpackShimConfig = {
     'pgadmin.browser.quick_search': path.join(__dirname, './pgadmin/browser/static/js/quick_search'),
     'pgadmin.browser.messages': '/browser/js/messages',
     '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.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.dashboard': path.join(__dirname, './pgadmin/dashboard/static/js/Dashboard'),
     'pgadmin.help': path.join(__dirname, './pgadmin/help/static/js/help'),
@@ -282,10 +253,10 @@ let webpackShimConfig = {
   // Define list of pgAdmin common libraries to bundle them separately
   // into commons JS from app.bundle.js
   pgLibs: [
-    'pgadmin.browser.error', 'pgadmin.browser.server.privilege',
-    'pgadmin.browser.server.variable', 'pgadmin.browser.collection', 'pgadmin.browser.node.ui',
+    'pgadmin.browser.error',
+    'pgadmin.browser.collection',
     'pgadmin.browser.datamodel', 'pgadmin.browser.menu', 'pgadmin.browser.panel', 'pgadmin',
-    'pgadmin.browser.frame', 'pgadmin.backform', 'pgadmin.backgrid', 'pgadmin.browser',
+    'pgadmin.browser.frame', 'pgadmin.browser',
     'pgadmin.browser.node',
     'pgadmin.settings', 'pgadmin.preferences', 'pgadmin.sqlfoldcode',
   ],
diff --git a/web/webpack.test.config.js b/web/webpack.test.config.js
index 40ef92477..92c67000a 100644
--- a/web/webpack.test.config.js
+++ b/web/webpack.test.config.js
@@ -122,9 +122,6 @@ module.exports = {
       'bootstrap.datetimepicker': path.join(__dirname, './node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min'),
       'bootstrap.toggle': path.join(__dirname, './node_modules/bootstrap4-toggle/js/bootstrap4-toggle.min'),
       'backbone': path.join(__dirname, './node_modules/backbone/backbone'),
-      'backform': path.join(__dirname, './node_modules/backform/src/backform'),
-      'backgrid': path.join(__dirname, './pgadmin/static/vendor/backgrid/backgrid'),
-      'backgrid.filter': path.join(__dirname, './node_modules/backgrid-filter/backgrid-filter'),
       'react': path.join(__dirname, 'node_modules/react'),
       'react-dom': path.join(__dirname, 'node_modules/react-dom'),
       'sources': sourcesDir + '/js',
@@ -137,8 +134,6 @@ module.exports = {
       'browser': path.resolve(__dirname, 'pgadmin/browser/static/js'),
       'pgadmin': sourcesDir + '/js/pgadmin',
       'pgadmin.sqlfoldcode': sourcesDir + '/js/codemirror/addon/fold/pgadmin-sqlfoldcode',
-      'pgadmin.backgrid': sourcesDir + '/js/backgrid.pgadmin',
-      'pgadmin.backform': sourcesDir + '/js/backform.pgadmin',
       'pgadmin4-tree': path.join(__dirname, 'node_modules/pgadmin4-tree'),
       'pgbrowser': path.resolve(__dirname, 'regression/javascript/fake_browser'),
       'pgadmin.schema.dir': path.resolve(__dirname, 'pgadmin/browser/server_groups/servers/databases/schemas/static/js'),
