public inbox for [email protected]  
help / color / mirror / Atom feed
From: Murtuza Zabuawala <[email protected]>
To: Dave Page <[email protected]>
Cc: Ashesh Vashi <[email protected]>
Cc: Akshay Joshi <[email protected]>
Cc: Harshal Dhumal <[email protected]>
Cc: pgadmin-hackers <[email protected]>
Subject: Re: [PATCH] Tables node (pgAdmin4)
Date: Mon, 23 May 2016 18:35:59 +0530
Message-ID: <CAKKotZS9MbvFpSkYtRfcLZ8_2drrMpL8T-btH4QXf-BPL0cYzQ@mail.gmail.com> (raw)
In-Reply-To: <[email protected]>
References: <CAKKotZRCf07F_SGHi4KawBtLHPSeKz5Uvzwu6ddQ=bKc1FDRRw@mail.gmail.com>
	<CAFiP3vw61T0n--F4vYXALdtrkBKznBegBPq5Ds=6uZrg02vWXQ@mail.gmail.com>
	<CAFOhELea6nCtX_T78o_3mNKJC0_emirXKGm3nq8d6mvSZV57pg@mail.gmail.com>
	<CAFiP3vypf7KEmToKsBqn1--qf_PzMV+p-d9bsMj04eoYnj5_tQ@mail.gmail.com>
	<CAKKotZQumWW_cvhvgyFc7_1Lvs8npkPW57FgVN_+wPPSurBDOw@mail.gmail.com>
	<CAKKotZQMR5zsbDAiAhUEQ46yhNE51BONu0DYjEY1WFSJbBqK+w@mail.gmail.com>
	<CAFiP3vwBUX5Ez51Fk_s+t67hRW-uZ6ViMcuTg4e+oPf+k5KqTg@mail.gmail.com>
	<CAFOhELdg9-TB=fdpGDLNkjYve9vBxYttE_PzmahsrNMQv4nn4Q@mail.gmail.com>
	<CAFiP3vxO9tej3WXYeLjZk6MgQYR0C-hp9UUWmog1E7iDvvqFmQ@mail.gmail.com>
	<CAFOhELd=_vuqwR0eGLL=KhxGaQCP6n9mcXP1GijcWh1ecCpegw@mail.gmail.com>
	<CAFiP3vw5nx2Wdt9ci-MNRV+H+dO-x9KUSZtk16EZKjdox+KRxg@mail.gmail.com>
	<CAFiP3vz9=gtNuoGEt+oxt+UYfE=7=dTUQZpCxgGkVWUhS=Kafw@mail.gmail.com>
	<CA+yw=mPp8CY+jd3FUXeV-KSd+82dztXYWySJVLuL9eoE9hrbfQ@mail.gmail.com>
	<CAFiP3vw+yN2kYktjdmJEHL8Ug8R+k_HxhN+E+pozpC=d_zs1=Q@mail.gmail.com>
	<CAKKotZQKV3nkCz8ADOV1ExoSaKWHdH4rY17xW9K3B-4qLree3Q@mail.gmail.com>
	<CAKKotZTiR-cUVTbH21WnYbHW3EaQ3J_zESyYrkL+wO4sKNSSGg@mail.gmail.com>
	<CAKKotZQyTOK4tZYQ2kk4_G-4GknU+uDVu3PaU5FDeJuCe=ywDw@mail.gmail.com>
	<CAM5-9D9R6fT9LOhCBoSbcBvzKpWcjZvN23-wHRTJKsvQqNPECA@mail.gmail.com>
	<CAFiP3vwY_cAx9b-BoxteX5+7fcxVvu+LY4y5ooy28bxvz7D8AA@mail.gmail.com>
	<CAFiP3vwfO=udZvVPdXuEnem9A2LN7MBEQt02VW1AJLuCEsRL2w@mail.gmail.com>
	<CANxoLDcJ-Qum-BJXtDx52ij72EJVzLE+XYFE+_skJF4fXVJ9jA@mail.gmail.com>
	<CA+OCxowB=LJKts18wKx982gF4ZNJnOamND0xZEMp0CnTrjeruA@mail.gmail.com>
	<CAG7mmoyD5vJ3_FS6RO5kmer=CWyRW5Lgr723denYxLM-K00eow@mail.gmail.com>
	<[email protected]>
List-Unsubscribe:  <mailto:[email protected]?body=unsub%20pgadmin-hackers>

Hi,

PFA patch, which will fixes below mentioned issues,

- Fixed all the review comments given by Dave on tables & its child nodes.

*Additional enhancements*
- In Index node, We have updated the way columns were added,
  earlier it was using subnode control now we can insert/update
  values in-place using DepsCell functionality

- In Type node, We have updated the way Composite types were added,
  earlier it was using subnode control now we can insert/update
  values in-place using DepsCell functionality

- In Constraints nodes, Updated error messages handling earlier it was
  throwing error when we open create dialog and no input has been
  provided by user.


*Affected nodes by this patch:*


   1. Table
   2. Column
   3. Check constraint
   4. Exclusion constraint
   5. Foreign key
   6. Primary key
   7. Unique
   8. Index
   9. Trigger
   10. Type
   11. Materialized view




--
Regards,
Murtuza Zabuawala
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company

On Sat, May 21, 2016 at 2:45 PM, Dave Page <[email protected]> wrote:

> I think that makes sense, yes.
>
> Sent from my iPad
>
> On 21 May 2016, at 04:12, Ashesh Vashi <[email protected]>
> wrote:
>
>
> On Sat, May 21, 2016 at 12:01 AM, Dave Page <[email protected]> wrote:
>
>> Hi
>>
>> I just started to take a look at the table dialogue and friends. Here are
>> a few issues that we need to address - please take care of them:
>>
>> 1) Move columns to their own tab. Vertical scrolling is bad.
>>
> Should the 'inherit from table' part of columns tab?
>
>>
>> 2) Similarly, move constraints to their own tab.
>>
>> 3) Ensure all labels only have a capital letter on the first word, except
>> if following words are keywords or acronyms, e.g.
>>
>>   With default values?
>>   Has OIDs?
>>
>> 4) s/System tabel?/System table?
>>
>> 5) Error messages on fields should not be shown unless the field loses
>> focus and has an error (see Create Table)
>>
>> 6) The sections on the Properties view are not as they should be. As I've
>> pointed out before, the "General" section should have a limited subset of
>> information, e.g. name, oid, owner, tablespace, comment and "is system?"
>> Other properties should be in other appropriate sections.
>>
>> 7) Variables grids should not be on the Security tab (as also mentioned
>> previously).
>>
>> 8) Field labels that imply a question (e.g. usually those with a Yes/No
>> switch for input) should end in a ? - e.g. "Deferrable?"
>>
>> 9) On the Trigger dialogue, "Fires" and following controls should move to
>> a new tab.
>>
>> 10) On the MV dialogue, VACUUM settings should be on their own tab, as on
>> the Table dialogue.
>>
>> 11) Privileges controls on the Properties lists should be in a "Security"
>> group, not "General"
>>
>> I think there are a couple of basic principles to follow here:
>>
>> - Make properties lists and dialogues consistent with existing ones, from
>> control grouping right down to spelling and case of labels.
>>
>> - Dialogs should never need vertical scrolling by default (e.g. for a new
>> object with no columns/constraints/whatever yet defined). If you need to
>> scroll, then things should be moved to a new tab, grouped as appropriate.
>>
>> Thanks.
>>
>> On Fri, May 20, 2016 at 7:57 AM, Akshay Joshi <
>> [email protected]> wrote:
>>
>>> Thanks - Committed with minor changes.
>>>
>>> On Thu, May 19, 2016 at 10:47 PM, Harshal Dhumal <
>>> [email protected]> wrote:
>>>
>>>> Hi,
>>>>
>>>> PFA updated patch for table and all it's child nodes (Version 9). This
>>>> patch does not depend on any of existing table node patch.
>>>>
>>>> Major change in this patch: Unlike pgAdmin3 now in table create mode
>>>> any constraint(s) created (but not saved) will listen to table column
>>>> changes and adapt themselves accordingly.
>>>>
>>>> For e.g.
>>>> In table create mode user adds column definition with name "col1" then
>>>> adds constraint which includes column "col1". Now user changes column name
>>>> to "col2" then constraint will listen to this change and adapt the column
>>>> name from "col1" to "col2" in constraint definition. Also if column "col2"
>>>> is removed then constraint will also remove the column "col2" from it's
>>>> definition.
>>>>
>>>>
>>>> --
>>>> *Harshal Dhumal*
>>>> *Software Engineer *
>>>>
>>>>
>>>>
>>>> EenterpriseDB <http://www.enterprisedb.com;
>>>>
>>>>
>>>>
>>>> --
>>>> Sent via pgadmin-hackers mailing list ([email protected])
>>>> To make changes to your subscription:
>>>> http://www.postgresql.org/mailpref/pgadmin-hackers
>>>>
>>>>
>>>
>>>
>>> --
>>> *Akshay Joshi*
>>> *Principal Software Engineer *
>>>
>>>
>>>
>>> *Phone: +91 20-3058-9517 <%2B91%2020-3058-9517>Mobile: +91 976-788-8246*
>>>
>>
>>
>>
>> --
>> Dave Page
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>>
>> EnterpriseDB UK: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>
>


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


Attachments:

  [application/octet-stream] fixed_review_comments.patch (77.9K, 3-fixed_review_comments.patch)
  download | inline diff:
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/templates/column/js/column.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/templates/column/js/column.js
index 5f8edc6..8a12f32 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/templates/column/js/column.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/column/templates/column/js/column.js
@@ -84,6 +84,8 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
       type: 'column',
       label: '{{ _('Column') }}',
       hasSQL:  true,
+      sqlAlterHelp: 'sql-altertable.html',
+      sqlCreateHelp: 'sql-altertable.html',
       canDrop: function(itemData, item, data){
         if (pgBrowser.Nodes['schema'].canChildDrop.apply(this, [itemData, item, data])) {
           var t = pgBrowser.tree, i = item, d = itemData, parents = [];
@@ -294,7 +296,9 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
               });
 
               flag && setTimeout(function() {
-                  m.set('attlen', null);
+                  if(m.get('attlen')) {
+                    m.set('attlen', null);
+                  }
                 },10);
 
               return flag;
@@ -317,8 +321,10 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
               });
 
               flag && setTimeout(function() {
+                if(m.get('attprecision')) {
                   m.set('attprecision', null);
-                },10);
+                }
+              },10);
               return flag;
            }
          },{
@@ -338,7 +344,9 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
               });
               if (flag) {
                 setTimeout(function(){
-                  m.set('collspcname', "");
+                  if(m.get('collspcname') && m.get('collspcname') !== '') {
+                    m.set('collspcname', "");
+                  }
                 }, 10);
               }
               return flag;
@@ -371,16 +379,20 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
            ]
         },{
           id: 'is_pk', label:'{{ _('Primary key?') }}',
-          type: 'switch', disabled: true, mode: ['properties']
+          type: 'switch', disabled: true, mode: ['properties'],
+          group: '{{ _('Definition') }}'
         },{
           id: 'is_fk', label:'{{ _('Foreign key?') }}',
-          type: 'switch', disabled: true, mode: ['properties']
+          type: 'switch', disabled: true, mode: ['properties'],
+          group: '{{ _('Definition') }}'
         },{
           id: 'is_inherited', label:'{{ _('Inherited?') }}',
-          type: 'switch', disabled: true, mode: ['properties']
+          type: 'switch', disabled: true, mode: ['properties'],
+          group: '{{ _('Definition') }}'
         },{
           id: 'tbls_inherited', label:'{{ _('Inherited from table(s)') }}',
           type: 'text', disabled: true, mode: ['properties'], deps: ['is_inherited'],
+          group: '{{ _('Definition') }}',
           visible: function(m) {
               if (!_.isUndefined(m.get('is_inherited')) && m.get('is_inherited')) {
                 return true;
@@ -389,13 +401,19 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
               }
           }
         },{
-          id: 'is_sys_column', label:'{{ _('System Column?') }}', cell: 'string',
+          id: 'is_sys_column', label:'{{ _('System column?') }}', cell: 'string',
           type: 'switch', disabled: true, mode: ['properties']
         },{
           id: 'description', label:'{{ _('Comment') }}', cell: 'string',
           type: 'multiline', mode: ['properties', 'create', 'edit'],
           disabled: 'inSchema'
         },{
+          id: 'attoptions', label: 'Variables', type: 'collection',
+          group: '{{ _('Variables') }}', control: 'unique-col-collection',
+          model: VariablesModel, uniqueCol : ['name'],
+          mode: ['edit', 'create'], canAdd: true, canEdit: false,
+          canDelete: true
+        },{
           id: 'attacl', label: 'Privileges', type: 'collection',
           group: '{{ _('Security') }}', control: 'unique-col-collection',
           model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend({
@@ -403,12 +421,6 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
           mode: ['edit'], canAdd: true, canDelete: true,
           uniqueCol : ['grantee']
         },{
-          id: 'attoptions', label: 'Variables', type: 'collection',
-          group: '{{ _('Security') }}', control: 'unique-col-collection',
-          model: VariablesModel, uniqueCol : ['name'],
-          mode: ['edit', 'create'], canAdd: true, canEdit: false,
-          canDelete: true
-        },{
           id: 'seclabels', label: '{{ _('Security Labels') }}',
           model: pgAdmin.Browser.SecurityModel,
           editable: false, type: 'collection',
@@ -506,7 +518,7 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
           var node_info = this.node_info || m.node_info || m.top.node_info;
 
           // disable all fields if column is listed under view or mview
-          if ('view' in node_info || 'mview' in node_info) {
+          if (node_info && ('view' in node_info || 'mview' in node_info)) {
             if (this && _.has(this, 'name') && (this.name != 'defval')) {
               return true;
             }
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/templates/check_constraint/js/check_constraint.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/templates/check_constraint/js/check_constraint.js
index afc5ba9..ebb1711 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/templates/check_constraint/js/check_constraint.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/check_constraint/templates/check_constraint/js/check_constraint.js
@@ -111,7 +111,8 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
             var name = m.get('name');
             if (!(name && name != '')) {
               setTimeout(function(){
-                m.set('comment', null);
+                if(m.get('comment') && m.get('comment') !== '')
+                  m.set('comment', null);
               },10);
               return true;
             } else {
@@ -127,7 +128,7 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
               !_.isUndefined(m.get('oid'))) || (_.isFunction(m.isNew) && !m.isNew()));
           }, editable: false
         },{
-          id: 'connoinherit', label: '{{ _('No Inherit') }}', type:
+          id: 'connoinherit', label: '{{ _('No Inherit?') }}', type:
           'switch', cell: 'boolean', group: '{{ _('Definition') }}', mode:
           ['properties', 'create', 'edit'], min_version: 90200,
           disabled: function(m) {
@@ -136,7 +137,7 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
               !_.isUndefined(m.get('oid'))) || (_.isFunction(m.isNew) && !m.isNew()));
           }
         },{
-          id: 'convalidated', label: "{{ _("Don't validate") }}", type: 'switch', cell:
+          id: 'convalidated', label: "{{ _("Don't validate?") }}", type: 'switch', cell:
           'boolean', group: '{{ _('Definition') }}', min_version: 90200,
           disabled: function(m) {
             if ((_.isFunction(m.isNew) && !m.isNew()) ||
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/templates/exclusion_constraint/js/exclusion_constraint.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/templates/exclusion_constraint/js/exclusion_constraint.js
index 6cfa7c3..7baf1af 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/templates/exclusion_constraint/js/exclusion_constraint.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/exclusion_constraint/templates/exclusion_constraint/js/exclusion_constraint.js
@@ -653,7 +653,8 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
             var name = m.get('name');
             if (!(name && name != '')) {
               setTimeout(function(){
-                m.set('comment', null);
+              if(m.get('comment') && m.get('comment') !== '')
+                 m.set('comment', null);
               },10);
               return true;
             } else {
@@ -713,7 +714,7 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
           id: 'fillfactor', label: '{{ _('Fill factor') }}',
           type: 'int', group: '{{ _('Definition') }}', allowNull: true
         },{
-          id: 'condeferrable', label: '{{ _('Deferrable') }}',
+          id: 'condeferrable', label: '{{ _('Deferrable?') }}',
           type: 'switch', group: '{{ _('Definition') }}', deps: ['index'],
           disabled: function(m) {
             return ((_.has(m, 'handler') &&
@@ -721,7 +722,7 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
               !_.isUndefined(m.get('oid'))) || (_.isFunction(m.isNew) && !m.isNew()));
           }
         },{
-          id: 'condeferred', label: '{{ _('Deferred') }}',
+          id: 'condeferred', label: '{{ _('Deferred?') }}',
           type: 'switch', group: '{{ _('Definition') }}',
           deps: ['condeferrable'],
           disabled: function(m) {
@@ -736,7 +737,8 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
               return false;
             } else {
               setTimeout(function(){
-                m.set('condeferred', false);
+                if(m.get('condeferred'))
+                  m.set('condeferred', false);
               },10);
               return true;
             }
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/templates/foreign_key/js/foreign_key.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/templates/foreign_key/js/foreign_key.js
index 7da458a..6ef7d8c 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/templates/foreign_key/js/foreign_key.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/foreign_key/templates/foreign_key/js/foreign_key.js
@@ -21,9 +21,6 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
       headerSelectControlTemplate =  _.template([
                               '<div class="<%=Backform.controlsClassName%> <%=extraClasses.join(\' \')%>">',
                               '  <select class="pgadmin-node-select form-control" name="<%=name%>" style="width:100%;" value="<%-value%>" <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> >',
-                              '    <% if (first_empty) { %>',
-                              '    <option value="" <%="" === rawValue ? "selected" : "" %>><%- empty_value %></option>',
-                              '    <% } %>',
                               '    <% for (var i=0; i < options.length; i++) { %>',
                               '    <% var option = options[i]; %>',
                               '    <option <% if (option.image) { %> data-image=<%= option.image %> <% } %> value=<%= formatter.fromRaw(option.value) %> <%=option.value === rawValue ? "selected=\'selected\'" : "" %>><%-option.label%></option>',
@@ -702,7 +699,8 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
             var name = m.get('name');
             if (!(name && name != '')) {
               setTimeout(function(){
-                m.set('comment', null);
+              if(m.get('comment') && m.get('comment') !== '')
+                 m.set('comment', null);
               },10);
               return true;
             } else {
@@ -710,7 +708,7 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
             }
           }
         },{
-          id: 'condeferrable', label: '{{ _('Deferrable') }}',
+          id: 'condeferrable', label: '{{ _('Deferrable?') }}',
           type: 'switch', group: '{{ _('Definition') }}',
           disabled: function(m) {
             // If we are in table edit mode then
@@ -723,7 +721,7 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
             return !m.isNew();
           }
         },{
-          id: 'condeferred', label: '{{ _('Deferred') }}',
+          id: 'condeferred', label: '{{ _('Deferred?') }}',
           type: 'switch', group: '{{ _('Definition') }}',
           deps: ['condeferrable'],
           disabled: function(m) {
@@ -740,7 +738,8 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
               return false;
             } else {
               setTimeout(function(){
-                m.set('condeferred', false);
+                if(m.get('condeferred'))
+                  m.set('condeferred', false);
               },10);
               return true;
             }
@@ -778,7 +777,7 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
             return !(m.isNew() || m.get("convalidated"));
           }
         },{
-          id: 'autoindex', label: '{{ _('Auto FK index') }}',
+          id: 'autoindex', label: '{{ _('Auto FK index?') }}',
           type: 'switch', group: '{{ _('Definition') }}',
           deps: ['name', 'hasindex'],
           options: {
@@ -809,7 +808,8 @@ function($, _, S, pgAdmin, pgBrowser, Alertify) {
                 // new constraint which should allowed for Unique
                 if(_.isUndefined(m.get('oid')) && _.isUndefined(m.handler.get('oid'))) {
                   setTimeout(function () {
-                    m.set('autoindex', false);
+                    if(m.get('autoindex'))
+                      m.set('autoindex', false);
                   }, 10);
                   return true;
                 } else {
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/templates/index_constraint/js/index_constraint.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/templates/index_constraint/js/index_constraint.js
index b19d90f..6f709c4 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/templates/index_constraint/js/index_constraint.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/constraints/index_constraint/templates/index_constraint/js/index_constraint.js
@@ -101,7 +101,9 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
             var name = m.get('name');
             if (!(name && name != '')) {
               setTimeout(function(){
-                m.set('comment', null);
+               if(m.get('comment') && m.get('comment') !== '') {
+                 m.set('comment', null);
+               }
               },10);
               return true;
             } else {
@@ -207,17 +209,6 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
           }),
           canDelete: true, canAdd: true,
           control: Backform.MultiSelectAjaxControl.extend({
-            formatter: {
-              fromRaw: function (rawData, model) {
-                var res = _.isObject(rawData) ?
-                      rawData : JSON.parse(rawData);
-
-                return _.pluck(res, 'column');
-              },
-              toRaw: function (formattedData, model) {
-                return formattedData;
-              }
-            },
             defaults: _.extend(
               {},
               Backform.NodeListByNameControl.prototype.defaults,
@@ -454,7 +445,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
               }
             }
         },{
-          id: 'condeferrable', label: '{{ _('Deferrable') }}',
+          id: 'condeferrable', label: '{{ _('Deferrable?') }}',
           type: 'switch', group: '{{ _('Definition') }}', deps: ['index'],
           disabled: function(m) {
             // If we are in table edit mode then
@@ -475,13 +466,14 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
               return false;
             } else {
               setTimeout(function(){
-                m.set('condeferrable', false);
+                if(m.get('condeferrable'))
+                  m.set('condeferrable', false);
               },10);
               return true;
             }
           }
         },{
-          id: 'condeferred', label: '{{ _('Deferred') }}',
+          id: 'condeferred', label: '{{ _('Deferred?') }}',
           type: 'switch', group: '{{ _('Definition') }}',
           deps: ['condeferrable'],
           disabled: function(m) {
@@ -502,7 +494,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
               return false;
             } else {
               setTimeout(function(){
-                m.set('condeferred', false);
+               if(m.get('condeferred'))
+                  m.set('condeferred', false);
               },10);
               return true;
             }
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/templates/index/js/index.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/templates/index/js/index.js
index b49492a..7859112 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/templates/index/js/index.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/indexes/templates/index/js/index.js
@@ -15,6 +15,62 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
       });
   };
 
+  // Switch Cell with Deps
+  var SwitchDepCell = Backgrid.Extension.SwitchCell.extend({
+      initialize: function() {
+        Backgrid.Extension.SwitchCell.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"),
+          input = this.$el.find('input[type=checkbox]').first();
+
+        is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
+        if (is_editable) {
+           this.$el.addClass("editable");
+           input.prop('disabled', false);
+         } else {
+           this.$el.removeClass("editable");
+           input.prop('disabled', true);
+         }
+
+        this.delegateEvents();
+        return this;
+      },
+      remove: Backgrid.Extension.DependentCell.prototype.remove
+    });
+
+
+  // Node-Ajax-Cell with Deps
+  var NodeAjaxOptionsDepsCell = Backgrid.Extension.NodeAjaxOptionsCell.extend({
+      initialize: function() {
+        Backgrid.Extension.NodeAjaxOptionsCell.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"),
+          input = this.$el.find('select').first();
+
+        is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
+        if (is_editable) {
+           this.$el.addClass("editable");
+           input.prop('disabled', false);
+         } else {
+           this.$el.removeClass("editable");
+           input.prop('disabled', true);
+         }
+
+        this.delegateEvents();
+        return this;
+      },
+      remove: Backgrid.Extension.DependentCell.prototype.remove
+    });
+
+
     // Model to create column collection control
     var ColumnModel = pgAdmin.Browser.Node.Model.extend({
         defaults: {
@@ -26,23 +82,38 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
         },
         schema: [
           {
-            id: 'colname', label:'{{ _('Column') }}', cell: 'string',
-            type: 'text', disabled: 'inSchema', editable: false,
+            id: 'colname', label:'{{ _('Column') }}', cell: 'node-list-by-name',
+            type: 'text', disabled: 'inSchema', editable: true,
             control: 'node-list-by-name', node: 'column'
           },{
-            id: 'collspcname', label:'{{ _('Collation') }}', cell: 'string',
-            type: 'text', disabled: 'inSchema', editable: false,
+            id: 'collspcname', label:'{{ _('Collation') }}',
+            cell: NodeAjaxOptionsDepsCell,
+            type: 'text', disabled: 'inSchema', editable: function(m) {
+                // Header cell then skip
+                if (m instanceof Backbone.Collection) {
+                    return false;
+                }
+                return !(m.inSchema.apply(this, arguments));
+            },
             control: 'node-ajax-options', url: 'get_collations', node: 'index'
           },{
-            id: 'op_class', label:'{{ _('Operator class') }}', cell: 'string',
-            type: 'text', disabled: 'checkAccessMethod', editable: false,
+            id: 'op_class', label:'{{ _('Operator class') }}',
+            cell: NodeAjaxOptionsDepsCell,
+            type: 'text', disabled: 'checkAccessMethod',
+            editable: function(m) {
+                // Header cell then skip
+                if (m instanceof Backbone.Collection) {
+                    return false;
+                }
+                return !(m.checkAccessMethod.apply(this, arguments));
+            },
             control: 'node-ajax-options', url: 'get_op_class', node: 'index',
-            deps: ['amname'], transform: function(data) {
+            deps: ['amname'], transform: function(data, control) {
              /* We need to extract data from collection according
               * to access method selected by user if not selected
               * send btree related op_class options
               */
-             var amname = this.model.handler.get('amname'),
+             var amname = control.model.top.get('amname'),
                  options = data['btree'];
 
              if(_.isUndefined(amname))
@@ -56,21 +127,35 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
              return options;
             }
           },{
-            id: 'sort_order', label:'{{ _('Sort order') }}', cell: 'switch',
-            type: 'switch', disabled: 'checkAccessMethod', editable: false,
+            id: 'sort_order', label:'{{ _('Sort order') }}', cell: SwitchDepCell,
+            type: 'switch', disabled: 'checkAccessMethod',
+            editable: function(m) {
+                // Header cell then skip
+                if (m instanceof Backbone.Collection) {
+                    return false;
+                }
+                return !(m.checkAccessMethod.apply(this, arguments));
+            },
             deps: ['amname'],
             options: {
              'onText': 'DESC', 'offText': 'ASC',
-             'onColor': 'success', 'offColor': 'default',
+             'onColor': 'success', 'offColor': 'primary',
              'size': 'small'
             }
           },{
-            id: 'nulls', label:'{{ _('NULLs') }}', cell: 'switch',
-            type: 'switch', disabled: 'checkAccessMethod', editable: false,
+            id: 'nulls', label:'{{ _('NULLs') }}', cell: SwitchDepCell,
+            type: 'switch', disabled: 'checkAccessMethod',
+            editable: function(m) {
+                // Header cell then skip
+                if (m instanceof Backbone.Collection) {
+                    return true;
+                }
+                return !(m.checkAccessMethod.apply(this, arguments));
+            },
             deps: ['amname', 'sort_order'],
             options: {
              'onText': 'FIRST', 'offText': 'LAST',
-             'onColor': 'success', 'offColor': 'default',
+             'onColor': 'success', 'offColor': 'primary',
              'size': 'small'
             }
           }
@@ -107,7 +192,7 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
         // We will check if we are under schema node and added condition
         checkAccessMethod: function(m) {
         //Access method is empty or btree then do not disable field
-          var parent_model = m.handler;
+          var parent_model = m.top;
           if(!m.inSchema.apply(this, [m]) &&
               (_.isUndefined(parent_model.get('amname')) ||
                _.isNull(parent_model.get('amname')) ||
@@ -115,10 +200,8 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
                parent_model.get('amname') === 'btree')) {
             // We need to set nulls to true if sort_order is set to desc
             // nulls first is default for desc
-            if(m.get('sort_order') == true) {
+            if(m.get('sort_order') == true && m.previous('sort_order') ==  false) {
                setTimeout(function() { m.set('nulls', true) }, 10);
-            } else {
-               setTimeout(function() { m.set('nulls', false) }, 10);
             }
             return false;
           }
@@ -130,6 +213,8 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
     pgAdmin.Browser.Nodes['index'] = pgAdmin.Browser.Node.extend({
       parent_type: ['table', 'view', 'mview'],
       collection_type: ['coll-table', 'coll-view'],
+      sqlAlterHelp: 'sql-alterindex.html',
+      sqlCreateHelp: 'sql-createindex.html',
       type: 'index',
       label: '{{ _('Index') }}',
       hasSQL:  true,
@@ -228,7 +313,8 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
           })
         },{
           id: 'cols', label:'{{ _('Columns') }}', cell: 'string',
-          type: 'text', disabled: 'inSchema', mode: ['properties']
+          type: 'text', disabled: 'inSchema', mode: ['properties'],
+          group: '{{ _('Definition') }}'
         },{
           id: 'fillfactor', label:'{{ _('Fill factor') }}', cell: 'string',
           type: 'int', disabled: 'inSchema', mode: ['create', 'edit', 'properties'],
@@ -244,15 +330,14 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
         },{
           id: 'indisvalid', label:'{{ _('Valid?') }}', cell: 'string',
           type: 'switch', disabled: true, mode: ['properties'],
-
+          group: '{{ _('Definition') }}'
         },{
           id: 'indisprimary', label:'{{ _('Primary?') }}', cell: 'string',
           type: 'switch', disabled: true, mode: ['properties'],
-
+          group: '{{ _('Definition') }}'
         },{
           id: 'is_sys_idx', label:'{{ _('System index?') }}', cell: 'string',
-          type: 'switch', disabled: true, mode: ['properties'],
-
+          type: 'switch', disabled: true, mode: ['properties']
         },{
           id: 'isconcurrent', label:'{{ _('Concurrent build?') }}', cell: 'string',
           type: 'switch', disabled: 'inSchemaWithModelCheck',
@@ -262,7 +347,7 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
           type: 'text', disabled: 'inSchemaWithModelCheck', mode: ['create', 'edit'],
           control: 'sql-field', visible: true, group: '{{ _('Definition') }}'
         },{
-          id: 'columns', label: 'Columns', type: 'collection',
+          id: 'columns', label: 'Columns', type: 'collection', deps: ['amname'],
           group: '{{ _('Definition') }}', model: ColumnModel, mode: ['edit', 'create'],
           canAdd: function(m) {
             // We will disable it if it's in 'edit' mode
@@ -272,14 +357,7 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
               return false;
             }
           },
-          canEdit: function(m) {
-            // We will disable it if it's in 'edit' mode
-            if (m.isNew()) {
-              return true;
-            } else {
-              return false;
-            }
-          },
+          canEdit: false,
           canDelete: function(m) {
             // We will disable it if it's in 'edit' mode
             if (m.isNew()) {
@@ -288,7 +366,8 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
               return false;
             }
           },
-          control: 'unique-col-collection', uniqueCol : ['colname']
+          control: 'unique-col-collection', uniqueCol : ['colname'],
+          columns: ['colname', 'op_class', 'sort_order', 'nulls', 'collspcname']
         },{
           id: 'description', label:'{{ _('Comment') }}', cell: 'string',
           type: 'multiline', mode: ['properties', 'create', 'edit'],
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/js/table.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/js/table.js
index 19798a4..3c3da63 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/js/table.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/templates/table/js/table.js
@@ -385,29 +385,30 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
           disabled: 'inSchemaWithModelCheck',
           group: '{{ _('Advanced') }}'
         },{
-          id: 'conname', label:'{{ _('Primary Key') }}', cell: 'string',
-          type: 'text', mode: ['properties'],
+          id: 'conname', label:'{{ _('Primary key') }}', cell: 'string',
+          type: 'text', mode: ['properties'], group: '{{ _('Advanced') }}',
           disabled: 'inSchema'
         },{
           id: 'reltuples', label:'{{ _('Rows (estimated)') }}', cell: 'string',
-          type: 'text', mode: ['properties'],
+          type: 'text', mode: ['properties'], group: '{{ _('Advanced') }}',
           disabled: 'inSchema'
         },{
           id: 'rows_cnt', label:'{{ _('Rows (counted)') }}', cell: 'string',
-          type: 'text', mode: ['properties'],
+          type: 'text', mode: ['properties'], group: '{{ _('Advanced') }}',
           disabled: 'inSchema'
         },{
           id: 'relhassubclass', label:'{{ _('Inherits tables?') }}', cell: 'switch',
-          type: 'switch', mode: ['properties'],
+          type: 'switch', mode: ['properties'], group: '{{ _('Advanced') }}',
           disabled: 'inSchema'
         },{
-          id: 'is_sys_table', label:'{{ _('System tabel?') }}', cell: 'switch',
+          id: 'is_sys_table', label:'{{ _('System table?') }}', cell: 'switch',
           type: 'switch', mode: ['properties'],
           disabled: 'inSchema'
         },{
           id: 'coll_inherits', label: '{{ _('Inherited from table(s)') }}',
-          url: 'get_inherits', type: 'array',
+          url: 'get_inherits', type: 'array', group: '{{ _('Columns') }}',
           disabled: 'checkInheritance', deps: ['typname'],
+          mode: ['create', 'edit'],
           select2: { multiple: true, allowClear: true,
           placeholder: '{{ _('Select to inherit from...') }}'},
           transform: function(data, cell) {
@@ -490,193 +491,192 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
               }
             })
         },{
+          id: 'coll_inherits', label: '{{ _('Inherited from table(s)') }}',
+          url: 'get_inherits', type: 'text', group: '{{ _('Advanced') }}',
+          disabled: 'checkInheritance',
+          mode: ['properties'],
+        },{
           id: 'inherited_tables_cnt', label:'{{ _('Inherited tables count') }}', cell: 'string',
-          type: 'text', mode: ['properties'],
+          type: 'text', mode: ['properties'], group: '{{ _('Advanced') }}',
           disabled: 'inSchema'
         },{
-          type: 'nested', control: 'fieldset', mode: ['edit', 'create'],
-          schema:[{
-            // Here we will create tab control for columns
-              id: 'columns', label:'{{ _('Columns') }}', type: 'collection',
-              group: '{{ _('Columns') }}',
-              model: pgBrowser.Nodes['column'].model,
-              subnode: pgBrowser.Nodes['column'].model,
-              mode: ['create', 'edit'],
-              disabled: 'inSchema',
-              canAdd: 'check_grid_add_condition',
-              canEdit: true, canDelete: true,
-              // For each row edit/delete button enable/disable
-              canEditRow: 'check_grid_row_edit_delete',
-              canDeleteRow: 'check_grid_row_edit_delete',
-              uniqueCol : ['name'],
-              columns : ['name' , 'cltype', 'is_primary_key', 'inheritedfrom'],
-              control: Backform.UniqueColCollectionControl.extend({
-                initialize: function() {
-                  Backform.UniqueColCollectionControl.prototype.initialize.apply(this, arguments);
-                  var self = this,
-                      collection = self.model.get(self.field.get('name'));
-
-                  collection.on("change:is_primary_key", function(m) {
-                    var primary_key_coll = self.model.get('primary_key'),
-                        column_name = m.get('name'),
-                        primary_key;
-
-                    if(m.get('is_primary_key')) {
-                    // Add column to primary key.
-                      if (primary_key_coll.length < 1) {
-                        primary_key = new (primary_key_coll.model)({}, {
+        // Here we will create tab control for columns
+          id: 'columns', label:'{{ _('Columns') }}', type: 'collection',
+          group: '{{ _('Columns') }}',
+          model: pgBrowser.Nodes['column'].model,
+          subnode: pgBrowser.Nodes['column'].model,
+          mode: ['create', 'edit'],
+          disabled: 'inSchema',
+          canAdd: 'check_grid_add_condition',
+          canEdit: true, canDelete: true,
+          // For each row edit/delete button enable/disable
+          canEditRow: 'check_grid_row_edit_delete',
+          canDeleteRow: 'check_grid_row_edit_delete',
+          uniqueCol : ['name'],
+          columns : ['name' , 'cltype', 'is_primary_key', 'inheritedfrom'],
+          control: Backform.UniqueColCollectionControl.extend({
+            initialize: function() {
+              Backform.UniqueColCollectionControl.prototype.initialize.apply(this, arguments);
+              var self = this,
+                  collection = self.model.get(self.field.get('name'));
+
+              collection.on("change:is_primary_key", function(m) {
+                var primary_key_coll = self.model.get('primary_key'),
+                    column_name = m.get('name'),
+                    primary_key;
+
+                if(m.get('is_primary_key')) {
+                // Add column to primary key.
+                  if (primary_key_coll.length < 1) {
+                    primary_key = new (primary_key_coll.model)({}, {
+                      top: self.model,
+                      collection: primary_key_coll,
+                      handler: primary_key_coll
+                    });
+                    primary_key_coll.add(primary_key);
+                  } else {
+                    primary_key = primary_key_coll.first();
+                  }
+                  // Do not alter existing primary key columns.
+                  if (_.isUndefined(primary_key.get('oid'))) {
+                    var primary_key_column_coll = primary_key.get('columns'),
+                      primary_key_column_exist = primary_key_column_coll.where({column:column_name});
+
+                    if (primary_key_column_exist.length == 0) {
+                      var primary_key_column = new (primary_key_column_coll.model)(
+                          {column: column_name}, { silent: true,
                           top: self.model,
                           collection: primary_key_coll,
                           handler: primary_key_coll
                         });
-                        primary_key_coll.add(primary_key);
-                      } else {
-                        primary_key = primary_key_coll.first();
-                      }
-                      // Do not alter existing primary key columns.
-                      if (_.isUndefined(primary_key.get('oid'))) {
-                        var primary_key_column_coll = primary_key.get('columns'),
-                          primary_key_column_exist = primary_key_column_coll.where({column:column_name});
-
-                        if (primary_key_column_exist.length == 0) {
-                          var primary_key_column = new (primary_key_column_coll.model)(
-                              {column: column_name}, { silent: true,
-                              top: self.model,
-                              collection: primary_key_coll,
-                              handler: primary_key_coll
-                            });
-
-                          primary_key_column_coll.add(primary_key_column);
-                        }
-
-                        primary_key_column_coll.trigger('pgadmin:multicolumn:updated', primary_key_column_coll);
-                      }
 
-                    } else {
-                    // remove column from primary key.
-                      if (primary_key_coll.length > 0) {
-                        var primary_key = primary_key_coll.first();
-                        // Do not alter existing primary key columns.
-                        if (!_.isUndefined(primary_key.get('oid'))) {
-                          return;
-                        }
-
-                        var  primary_key_column_coll = primary_key.get('columns'),
-                            removedCols = primary_key_column_coll.where({column:column_name});
-                        if (removedCols.length > 0) {
-                          primary_key_column_coll.remove(removedCols);
-                          _.each(removedCols, function(m) {
-                            m.destroy();
-                          })
-                          if (primary_key_column_coll.length == 0) {
-                            setTimeout(function () {
-                              // There will be only on primary key so remove the first one.
-                              primary_key_coll.remove(primary_key_coll.first());
-                              /* Ideally above line of code should be "primary_key_coll.reset()".
-                               * But our custom DataCollection (extended from Backbone collection in datamodel.js)
-                               * does not respond to reset event, it only supports add, remove, change events.
-                               * And hence no custom event listeners/validators get called for reset event.
-                               */
-                            }, 10);
-                          }
-                        }
-                        primary_key_column_coll.trigger('pgadmin:multicolumn:updated', primary_key_column_coll);
-                      }
+                      primary_key_column_coll.add(primary_key_column);
                     }
-                  })
-                },
-                remove: function() {
-                  var collection = this.model.get(this.field.get('name'));
-                  if (collection) {
-                    collection.off("change:is_primary_key");
+
+                    primary_key_column_coll.trigger('pgadmin:multicolumn:updated', primary_key_column_coll);
                   }
 
-                  Backform.UniqueColCollectionControl.prototype.remove.apply(this, arguments);
+                } else {
+                // remove column from primary key.
+                  if (primary_key_coll.length > 0) {
+                    var primary_key = primary_key_coll.first();
+                    // Do not alter existing primary key columns.
+                    if (!_.isUndefined(primary_key.get('oid'))) {
+                      return;
+                    }
+
+                    var  primary_key_column_coll = primary_key.get('columns'),
+                        removedCols = primary_key_column_coll.where({column:column_name});
+                    if (removedCols.length > 0) {
+                      primary_key_column_coll.remove(removedCols);
+                      _.each(removedCols, function(m) {
+                        m.destroy();
+                      })
+                      if (primary_key_column_coll.length == 0) {
+                        setTimeout(function () {
+                          // There will be only on primary key so remove the first one.
+                          primary_key_coll.remove(primary_key_coll.first());
+                          /* Ideally above line of code should be "primary_key_coll.reset()".
+                           * But our custom DataCollection (extended from Backbone collection in datamodel.js)
+                           * does not respond to reset event, it only supports add, remove, change events.
+                           * And hence no custom event listeners/validators get called for reset event.
+                           */
+                        }, 10);
+                      }
+                    }
+                    primary_key_column_coll.trigger('pgadmin:multicolumn:updated', primary_key_column_coll);
+                  }
                 }
-              }),
-              allowMultipleEmptyRow: false
-          }]
+              })
+            },
+            remove: function() {
+              var collection = this.model.get(this.field.get('name'));
+              if (collection) {
+                collection.off("change:is_primary_key");
+              }
+
+              Backform.UniqueColCollectionControl.prototype.remove.apply(this, arguments);
+            }
+          }),
+          allowMultipleEmptyRow: false
         },{
-          type: 'nested', control: 'fieldset',
-          schema:[{
-              // Here we will create tab control for constraints
-              type: 'nested', control: 'tab', group: '{{ _('Constraints') }}',
-              mode: ['edit', 'create'],
-              schema: [{
-                  id: 'primary_key', label: '{{ _('Primary Key') }}',
-                  model: pgBrowser.Nodes['primary_key'].model,
-                  subnode: pgBrowser.Nodes['primary_key'].model,
-                  editable: false, type: 'collection',
-                  group: '{{ _('Primary Key') }}', mode: ['edit', 'create'],
-                  canEdit: true, canDelete: true,
-                  control: 'unique-col-collection',
-                  columns : ['name', 'columns'],
-                  canAdd: true,
-                  canAddRow: function(m) {
-                   // User can only add one primary key
-                   var columns = m.get('columns');
-
-                   return (m.get('primary_key') &&
-                            m.get('primary_key').length < 1 &&
-                            _.some(columns.pluck('name')));
-                  }
-                },{
-                  id: 'foreign_key', label: '{{ _('Foreign Key') }}',
-                  model: pgBrowser.Nodes['foreign_key'].model,
-                  subnode: pgBrowser.Nodes['foreign_key'].model,
-                  editable: false, type: 'collection',
-                  group: '{{ _('Foreign Key') }}', mode: ['edit', 'create'],
-                  canEdit: true, canDelete: true,
-                  control: 'unique-col-collection',
-                  canAdd: true,
-                  columns : ['name', 'columns'],
-                  canAddRow: function(m) {
-                   // User can only add if there is at least one column with name.
-                   var columns = m.get('columns');
-                   return _.some(columns.pluck('name'));
-                  }
-                },{
-                  id: 'check_constraint', label: '{{ _('Check Constraint') }}',
-                  model: pgBrowser.Nodes['check_constraints'].model,
-                  subnode: pgBrowser.Nodes['check_constraints'].model,
-                  editable: false, type: 'collection',
-                  group: '{{ _('Check') }}', mode: ['edit', 'create'],
-                  canEdit: true, canDelete: true,
-                  control: 'unique-col-collection',
-                  canAdd: true,
-                  columns : ['name', 'consrc']
-                },{
-                  id: 'unique_constraint', label: '{{ _('Unique Constraint') }}',
-                  model: pgBrowser.Nodes['unique_constraint'].model,
-                  subnode: pgBrowser.Nodes['unique_constraint'].model,
-                  editable: false, type: 'collection',
-                  group: '{{ _('Unique') }}', mode: ['edit', 'create'],
-                  canEdit: true, canDelete: true,
-                  control: 'unique-col-collection',
-                  columns : ['name', 'columns'],
-                  canAdd: true,
-                  canAddRow: function(m) {
-                   // User can only add if there is at least one column with name.
-                   var columns = m.get('columns');
-                   return _.some(columns.pluck('name'));
-                  }
-                },{
-                  id: 'exclude_constraint', label: '{{ _('Exclude Constraint') }}',
-                  model: pgBrowser.Nodes['exclusion_constraint'].model,
-                  subnode: pgBrowser.Nodes['exclusion_constraint'].model,
-                  editable: false, type: 'collection',
-                  group: '{{ _('Exclude') }}', mode: ['edit', 'create'],
-                  canEdit: true, canDelete: true,
-                  control: 'unique-col-collection',
-                  columns : ['name', 'columns', 'constraint'],
-                  canAdd: true,
-                  canAddRow: function(m) {
-                   // User can only add if there is at least one column with name.
-                   var columns = m.get('columns');
-                   return _.some(columns.pluck('name'));
-                  }
-            }]
-          }]
+          // Here we will create tab control for constraints
+          type: 'nested', control: 'tab', group: '{{ _('Constraints') }}',
+          mode: ['edit', 'create'],
+          schema: [{
+              id: 'primary_key', label: '{{ _('Primary key') }}',
+              model: pgBrowser.Nodes['primary_key'].model,
+              subnode: pgBrowser.Nodes['primary_key'].model,
+              editable: false, type: 'collection',
+              group: '{{ _('Primary Key') }}', mode: ['edit', 'create'],
+              canEdit: true, canDelete: true,
+              control: 'unique-col-collection',
+              columns : ['name', 'columns'],
+              canAdd: true,
+              canAddRow: function(m) {
+               // User can only add one primary key
+               var columns = m.get('columns');
+
+               return (m.get('primary_key') &&
+                        m.get('primary_key').length < 1 &&
+                        _.some(columns.pluck('name')));
+              }
+            },{
+              id: 'foreign_key', label: '{{ _('Foreign key') }}',
+              model: pgBrowser.Nodes['foreign_key'].model,
+              subnode: pgBrowser.Nodes['foreign_key'].model,
+              editable: false, type: 'collection',
+              group: '{{ _('Foreign Key') }}', mode: ['edit', 'create'],
+              canEdit: true, canDelete: true,
+              control: 'unique-col-collection',
+              canAdd: true,
+              columns : ['name', 'columns'],
+              canAddRow: function(m) {
+               // User can only add if there is at least one column with name.
+               var columns = m.get('columns');
+               return _.some(columns.pluck('name'));
+              }
+            },{
+              id: 'check_constraint', label: '{{ _('Check constraint') }}',
+              model: pgBrowser.Nodes['check_constraints'].model,
+              subnode: pgBrowser.Nodes['check_constraints'].model,
+              editable: false, type: 'collection',
+              group: '{{ _('Check') }}', mode: ['edit', 'create'],
+              canEdit: true, canDelete: true,
+              control: 'unique-col-collection',
+              canAdd: true,
+              columns : ['name', 'consrc']
+            },{
+              id: 'unique_constraint', label: '{{ _('Unique constraint') }}',
+              model: pgBrowser.Nodes['unique_constraint'].model,
+              subnode: pgBrowser.Nodes['unique_constraint'].model,
+              editable: false, type: 'collection',
+              group: '{{ _('Unique') }}', mode: ['edit', 'create'],
+              canEdit: true, canDelete: true,
+              control: 'unique-col-collection',
+              columns : ['name', 'columns'],
+              canAdd: true,
+              canAddRow: function(m) {
+               // User can only add if there is at least one column with name.
+               var columns = m.get('columns');
+               return _.some(columns.pluck('name'));
+              }
+            },{
+              id: 'exclude_constraint', label: '{{ _('Exclude constraint') }}',
+              model: pgBrowser.Nodes['exclusion_constraint'].model,
+              subnode: pgBrowser.Nodes['exclusion_constraint'].model,
+              editable: false, type: 'collection',
+              group: '{{ _('Exclude') }}', mode: ['edit', 'create'],
+              canEdit: true, canDelete: true,
+              control: 'unique-col-collection',
+              columns : ['name', 'columns', 'constraint'],
+              canAdd: true,
+              canAddRow: function(m) {
+               // User can only add if there is at least one column with name.
+               var columns = m.get('columns');
+               return _.some(columns.pluck('name'));
+              }
+        }]
         },{
           type: 'nested', control: 'fieldset', label: '{{ _('Like') }}',
           group: '{{ _('Advanced') }}',
@@ -686,23 +686,23 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
             control: 'node-ajax-options', url: 'get_relations',
             disabled: 'inSchemaWithModelCheck', group: '{{ _('Like') }}'
           },{
-            id: 'like_default_value', label:'{{ _('With Default values?') }}', cell: 'switch',
+            id: 'like_default_value', label:'{{ _('With default values?') }}', cell: 'switch',
             type: 'switch', mode: ['create', 'edit'],
             disabled: 'inSchemaWithModelCheck', group: '{{ _('Like') }}'
           },{
-            id: 'like_constraints', label:'{{ _('With Constraints?') }}', cell: 'switch',
+            id: 'like_constraints', label:'{{ _('With constraints?') }}', cell: 'switch',
             type: 'switch', mode: ['create', 'edit'],
             disabled: 'inSchemaWithModelCheck', group: '{{ _('Like') }}'
           },{
-            id: 'like_indexes', label:'{{ _('With Indexes?') }}', cell: 'switch',
+            id: 'like_indexes', label:'{{ _('With indexes?') }}', cell: 'switch',
             type: 'switch', mode: ['create', 'edit'],
             disabled: 'inSchemaWithModelCheck', group: '{{ _('Like') }}'
           },{
-            id: 'like_storage', label:'{{ _('With Storage?') }}', cell: 'switch',
+            id: 'like_storage', label:'{{ _('With storage?') }}', cell: 'switch',
             type: 'switch', mode: ['create', 'edit'],
             disabled: 'inSchemaWithModelCheck', group: '{{ _('Like') }}'
           },{
-            id: 'like_comments', label:'{{ _('With Comments?') }}', cell: 'switch',
+            id: 'like_comments', label:'{{ _('With comments?') }}', cell: 'switch',
             type: 'switch', mode: ['create', 'edit'],
             disabled: 'inSchemaWithModelCheck', group: '{{ _('Like') }}'
           }]
@@ -723,17 +723,17 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
           mode: ['edit', 'create'], canAdd: true, canDelete: true,
           uniqueCol : ['grantee']
         },{
-          id: 'seclabels', label: '{{ _('Security Labels') }}',
+          id: 'seclabels', label: '{{ _('Security labels') }}',
           model: pgAdmin.Browser.SecurityModel, editable: false, type: 'collection',
           group: '{{ _('Security') }}', mode: ['edit', 'create'],
           min_version: 90100, canAdd: true,
           canEdit: false, canDelete: true, control: 'unique-col-collection'
         },{
-          id: 'vacuum_settings_str', label: '{{ _('Storage Settings') }}',
+          id: 'vacuum_settings_str', label: '{{ _('Storage settings') }}',
           type: 'multiline', group: '{{ _('Advanced') }}', mode: ['properties']
         }
         ],
-        validate: function() {
+        validate: function(keys) {
           var err = {},
               changedAttrs = this.changed,
               msg = undefined,
@@ -743,6 +743,14 @@ function($, _, S, pgAdmin, pgBrowser, alertify) {
 
           this.errorModel.clear();
 
+          // If nothing to validate or VacuumSetting keys then
+          // return from here
+          if ( keys && (keys.length == 0
+                        || _.indexOf(keys, 'autovacuum_enabled') != -1
+                        || _.indexOf(keys, 'toast_autovacuum_enabled') != -1) ) {
+            return null;
+          }
+
           if (_.isUndefined(name) || _.isNull(name) ||
             String(name).replace(/^\s+|\s+$/g, '') == '') {
             msg = '{{ _('Table name can not be empty.') }}';
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py
index 634483a..37b1391 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/__init__.py
@@ -113,7 +113,7 @@ class TriggerModule(CollectionNodeModule):
         """
         Load the module node as a leaf node
         """
-        return True
+        return False
 
     @property
     def csssnippets(self):
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/templates/trigger/js/trigger.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/templates/trigger/js/trigger.js
index bd22795..3b20527 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/templates/trigger/js/trigger.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/tables/triggers/templates/trigger/js/trigger.js
@@ -3,6 +3,26 @@ define(
         'backform', 'alertify', 'pgadmin.browser.collection'],
 function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
 
+
+  var CustomSwitchControl = Backform.CustomSwitchControl = Backform.SwitchControl.extend({
+    template: _.template([
+      '<label class="<%=Backform.controlLabelClassName%> custom_switch_label_class"><%=label%></label>',
+      '<div class="<%=Backform.controlsClassName%> custom_switch_control_class">',
+      '  <div class="checkbox">',
+      '    <label>',
+      '      <input type="checkbox" class="<%=extraClasses.join(\' \')%>"',
+      '        name="<%=name%>" <%=value ? "checked=\'checked\'" : ""%>',
+      '        <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> />',
+      '    </label>',
+      '  </div>',
+      '</div>',
+      '<% if (helpMessage && helpMessage.length) { %>',
+      '  <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
+      '<% } %>'
+    ].join("\n")),
+    className: 'pgadmin-control-group form-group col-xs-6'
+  });
+
   if (!pgBrowser.Nodes['coll-trigger']) {
     var triggers = pgAdmin.Browser.Nodes['coll-trigger'] =
       pgAdmin.Browser.Collection.extend({
@@ -162,7 +182,8 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
       model: pgAdmin.Browser.Node.Model.extend({
         defaults: {
           name: undefined,
-					is_row_trigger: true
+          is_row_trigger: true,
+          fires: 'BEFORE'
         },
         schema: [{
           id: 'name', label: '{{ _('Name') }}', cell: 'string',
@@ -172,14 +193,15 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
           type: 'int', disabled: true, mode: ['properties']
         },{
           id: 'is_enable_trigger', label:'{{ _('Enable trigger?') }}',
-          type: 'switch', disabled: 'inSchema', mode: ['properties']
+          type: 'switch', disabled: 'inSchema', mode: ['properties'],
+          group: '{{ _('Definition') }}'
         },{
-          id: 'is_row_trigger', label:'{{ _('Row trigger') }}',
+          id: 'is_row_trigger', label:'{{ _('Row trigger?') }}',
           type: 'switch', group: '{{ _('Definition') }}',
           mode: ['create','edit', 'properties'],
           deps: ['is_constraint_trigger'],
           disabled: function(m) {
-            // If contraint trigger is set to True then row trigger will
+            // If constraint trigger is set to True then row trigger will
             // automatically set to True and becomes disable
             var is_constraint_trigger = m.get('is_constraint_trigger');
             if(!m.inSchemaWithModelCheck.apply(this, [m])) {
@@ -192,54 +214,61 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
                     return false;
                 }
             } else {
-                // Disbale it
+                // Disable it
                 return true;
             }
           }
         },{
-          id: 'is_constraint_trigger', label:'{{ _('Constraint trigger') }}',
+          id: 'is_constraint_trigger', label:'{{ _('Constraint trigger?') }}',
           type: 'switch', disabled: 'inSchemaWithModelCheck',
           mode: ['create','edit', 'properties'],
           group: '{{ _('Definition') }}'
         },{
-          id: 'tgdeferrable', label:'{{ _('Deferrable') }}',
+          id: 'tgdeferrable', label:'{{ _('Deferrable?') }}',
           type: 'switch', group: '{{ _('Definition') }}',
           mode: ['create','edit', 'properties'],
           deps: ['is_constraint_trigger'],
           disabled: function(m) {
-            // If contraint trigger is set to True then only enable it
+            // If constraint trigger is set to True then only enable it
             var is_constraint_trigger = m.get('is_constraint_trigger');
             if(!m.inSchemaWithModelCheck.apply(this, [m])) {
                 if(!_.isUndefined(is_constraint_trigger) &&
                 is_constraint_trigger === true) {
                     return false;
                 } else {
-                    setTimeout(function() { m.set('tgdeferrable', false) }, 10);
+                    // If value is already set then reset it to false
+                    if(m.get('tgdeferrable')) {
+                      setTimeout(function() { m.set('tgdeferrable', false) }, 10);
+                    }
                     return true;
                 }
             } else {
-                // Disbale it
+                // Disable it
                 return true;
             }
           }
         },{
-          id: 'tginitdeferred', label:'{{ _('Deferred') }}',
+          id: 'tginitdeferred', label:'{{ _('Deferred?') }}',
           type: 'switch', group: '{{ _('Definition') }}',
           mode: ['create','edit', 'properties'],
-          deps: ['tgdeferrable'],
+          deps: ['tgdeferrable', 'is_constraint_trigger'],
           disabled: function(m) {
-            // If contraint trigger is set to True then only enable it
-            var is_constraint_trigger = m.get('tgdeferrable');
+            // If Deferrable is set to True then only enable it
+            var tgdeferrable = m.get('tgdeferrable');
             if(!m.inSchemaWithModelCheck.apply(this, [m])) {
-                if(!_.isUndefined(is_constraint_trigger) &&
-                is_constraint_trigger === true) {
+                if(!_.isUndefined(tgdeferrable) &&
+                tgdeferrable) {
                     return false;
                 } else {
-                    setTimeout(function() { m.set('tginitdeferred', false) }, 10);
-                    return true;
+                    // If value is already set then reset it to false
+                    if(m.get('tginitdeferred')) {
+                      setTimeout(function() { m.set('tginitdeferred', false) }, 10);
+                    }
+                    // If constraint trigger is set then do not disable
+                    return m.get('is_constraint_trigger') ? false : true;
                 }
             } else {
-                // Disbale it
+                // Disable it
                 return true;
             }
           }
@@ -261,20 +290,20 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
                 if(server_type === 'ppas' &&
                     !_.isUndefined(tfunction) &&
                 tfunction === 'Inline EDB-SPL') {
-                    // Disbale and clear its value
+                    // Disable and clear its value
                     m.set('tgargs', undefined)
                     return true;
                 } else {
                     return false;
                 }
             } else {
-                // Disbale it
+                // Disable it
                 return true;
             }
           }
         },{
         id: 'fires', label:'{{ _('Fires') }}', deps: ['is_constraint_trigger'],
-        mode: ['create','edit', 'properties'], group: '{{ _('Definition') }}',
+        mode: ['create','edit', 'properties'], group: '{{ _('Events') }}',
         options: function(control) {
             var table_options = [
                 {label: "BEFORE", value: "BEFORE"},
@@ -291,18 +320,7 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
             }
         },
         // If create mode then by default open composite type
-        control: Backform.Select2Control.extend({
-            render: function(){
-                // Initialize parent's render method
-                Backform.Select2Control.prototype.render.apply(this, arguments);
-                if(this.model.isNew() &&
-                        this.model.get('is_constraint_trigger') !== true ) {
-                    this.model.set({'fires': 'BEFORE'}, {silent: true});
-                }
-                return this;
-            }
-        }),
-        select2: { allowClear: false, width: "100%" },
+        control: 'select2', select2: { allowClear: false, width: "100%" },
         disabled: function(m) {
         // If contraint trigger is set to True then only enable it
         var is_constraint_trigger = m.get('is_constraint_trigger');
@@ -315,17 +333,18 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
                 return false;
             }
         } else {
-            // Disbale it
+            // Disable it
             return true;
         }
        }
       },{
         type: 'nested', control: 'fieldset', mode: ['create','edit', 'properties'],
-        label: '{{ _('Events') }}', group: '{{ _('Definition') }}',
+        label: '{{ _('Events') }}', group: '{{ _('Events') }}',
         schema:[{
             id: 'evnt_insert', label:'{{ _('INSERT') }}',
             type: 'switch', mode: ['create','edit', 'properties'],
             group: '{{ _('Events') }}',
+            control: Backform.CustomSwitchControl,
             disabled: function(m) {
                 return m.inSchemaWithModelCheck.apply(this, [m]);
             }
@@ -333,6 +352,7 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
             id: 'evnt_update', label:'{{ _('UPDATE') }}',
             type: 'switch', mode: ['create','edit', 'properties'],
             group: '{{ _('Events') }}',
+            control: Backform.CustomSwitchControl,
             disabled: function(m) {
                 return m.inSchemaWithModelCheck.apply(this, [m]);
             }
@@ -340,12 +360,14 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
             id: 'evnt_delete', label:'{{ _('DELETE') }}',
             type: 'switch', mode: ['create','edit', 'properties'],
             group: '{{ _('Events') }}',
+            control: Backform.CustomSwitchControl,
             disabled: function(m) {
                 return m.inSchemaWithModelCheck.apply(this, [m]);
             }
         },{
             id: 'evnt_turncate', label:'{{ _('TRUNCATE') }}',
             type: 'switch', group: '{{ _('Events') }}',
+            control: Backform.CustomSwitchControl,
             disabled: function(m) {
             var is_constraint_trigger = m.get('is_constraint_trigger'),
                 is_row_trigger = m.get('is_row_trigger'),
@@ -363,7 +385,7 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
                     return true;
                 }
             } else {
-                // Disbale it
+                // Disable it
                 return true;
             }
         }
@@ -372,11 +394,11 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
             id: 'whenclause', label:'{{ _('When') }}',
             type: 'text', disabled: 'inSchemaWithModelCheck',
             mode: ['create', 'edit', 'properties'],
-            control: 'sql-field', visible: true, group: '{{ _('Definition') }}'
+            control: 'sql-field', visible: true, group: '{{ _('Events') }}'
         },{
             id: 'columns', label: '{{ _('Columns') }}', url: 'nodes',
             type: 'collection', control: 'multi-select-ajax',
-            deps: ['evnt_update'], node: 'column', group: '{{ _('Definition') }}',
+            deps: ['evnt_update'], node: 'column', group: '{{ _('Events') }}',
             model: pgBrowser.Node.Model.extend({
                 keys: ['column'], defaults: { column: undefined }
             }),
@@ -384,7 +406,7 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
                 if(this.node_info &&  'catalog' in this.node_info) {
                     return true;
                 }
-                //Disbale in edit mode
+                //Disable in edit mode
                 if (!m.isNew()) {
                     return true;
                 }
@@ -414,7 +436,7 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
                         return true;
                     }
                 } else {
-                    // Disbale it
+                    // Disable it
                       return true;
                 }
             }
@@ -423,17 +445,23 @@ function($, _, S, pgAdmin, pgBrowser, Backform, alertify) {
           type: 'switch', disabled: 'inSchemaWithModelCheck', mode: ['properties']
         },{
           id: 'is_constarint', label:'{{ _('Constraint?') }}', cell: 'string',
-          type: 'switch', disabled: 'inSchemaWithModelCheck', mode: ['properties']
+          type: 'switch', disabled: 'inSchemaWithModelCheck', mode: ['properties'],
+          group: '{{ _('Definition') }}'
         },{
           id: 'description', label:'{{ _('Comment') }}', cell: 'string',
           type: 'multiline', mode: ['properties', 'create', 'edit'],
           disabled: 'inSchema'
     }],
-        validate: function() {
+        validate: function(keys) {
           var err = {},
               msg = undefined;
           this.errorModel.clear();
 
+          // If nothing to validate
+          if (keys && keys.length == 0) {
+            return null;
+          }
+
           if(_.isUndefined(this.get('name'))
               || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') {
             msg = '{{ _('Name can not be empty.') }}';
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/__init__.py
index 498781e..33c3a6d 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/__init__.py
@@ -552,7 +552,8 @@ class TypeView(PGChildNodeView, DataTypeReader):
                 res.append(
                             {'label': row['typname'], 'value': row['typname'],
                              'typval': typeval, 'precision': precision,
-                             'length': length, 'min_val': min_val, 'max_val': max_val
+                             'length': length, 'min_val': min_val, 'max_val': max_val,
+                             'is_collatable': row['is_collatable']
                              }
                         )
 
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/type/js/type.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/type/js/type.js
index 5222741..c91bdf5 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/type/js/type.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/type/js/type.js
@@ -14,6 +14,55 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Backgrid) {
       });
   };
 
+  // Integer Cell for Columns Length and Precision
+  var IntegerDepCell = Backgrid.IntegerCell.extend({
+      initialize: function() {
+        Backgrid.NumberCell.prototype.initialize.apply(this, arguments);
+        Backgrid.Extension.DependentCell.prototype.initialize.apply(this, arguments);
+      },
+      dependentChanged: function () {
+        this.$el.empty();
+        var model = this.model;
+        var column = this.column;
+        editable = this.column.get("editable");
+
+        is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
+        if (is_editable){ this.$el.addClass("editable"); }
+        else { this.$el.removeClass("editable"); }
+
+        this.delegateEvents();
+        return this;
+      },
+      remove: Backgrid.Extension.DependentCell.prototype.remove
+    });
+
+  // Node-Ajax-Cell with Deps
+  var NodeAjaxOptionsDepsCell = Backgrid.Extension.NodeAjaxOptionsCell.extend({
+      initialize: function() {
+        Backgrid.Extension.NodeAjaxOptionsCell.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"),
+          input = this.$el.find('select').first();
+
+        is_editable = _.isFunction(editable) ? !!editable.apply(column, [model]) : !!editable;
+        if (is_editable) {
+           this.$el.addClass("editable");
+           input.prop('disabled', false);
+         } else {
+           this.$el.removeClass("editable");
+           input.prop('disabled', true);
+         }
+
+        this.delegateEvents();
+        return this;
+      },
+      remove: Backgrid.Extension.DependentCell.prototype.remove
+    });
+
   // Security label model declaration
   var SecurityModel = Backform.SecurityModel = pgAdmin.Browser.Node.Model.extend({
     defaults: {
@@ -64,13 +113,14 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Backgrid) {
     subtypes: undefined,
     schema: [{
       id: 'member_name', label: '{{ _('Member Name') }}',
-      type: 'text',  disabled: false, editable: false
+      type: 'text',  disabled: false, editable: true
     },{
       id: 'type', label: '{{ _('Type') }}', control: 'node-ajax-options',
       type: 'text', url: 'get_types', disabled: false, node: 'type',
-      editable: false,
-      transform: function(d){
-        this.model.type_options =  d;
+      cell: 'node-ajax-options',
+      editable: true,
+      transform: function(d, control){
+        control.model.type_options =  d;
         return d;
       }
     },{
@@ -78,8 +128,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Backgrid) {
       // precision and scale. In the UI, we try to follow the docs as
       // closely as possible, therefore we use Length/Precision and Scale
       id: 'tlength', label: '{{ _('Length/precision') }}', deps: ['type'], type: 'text',
-      editable: false,
-      disabled: function(m) {
+      disabled: false, cell: IntegerDepCell,
+      editable: function(m) {
         // We will store type from selected from combobox
         var of_type = m.get('type');
         if(m.type_options) {
@@ -98,15 +148,15 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Backgrid) {
             }
           });
         }
-        return !m.get('is_tlength');
+        return m.get('is_tlength');
       }
     },{
       // Note: There are ambiguities in the PG catalogs and docs between
       // precision and scale. In the UI, we try to follow the docs as
       // closely as possible, therefore we use Length/Precision and Scale
       id: 'precision', label: '{{ _('Scale') }}', deps: ['type'],
-      type: 'text', editable: false,
-      disabled: function(m) {
+      type: 'text', disabled: false, cell: IntegerDepCell,
+      editable: function(m) {
         // We will store type from selected from combobox
         var of_type = m.get('type');
         if(m.type_options) {
@@ -125,11 +175,32 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Backgrid) {
             }
           });
         }
-        return !m.get('is_precision');
+        return m.get('is_precision');
       }
     },{
       id: 'collation', label: '{{ _('Collation') }}',
-      control: 'node-ajax-options', editable: false,
+      cell: NodeAjaxOptionsDepsCell, deps: ['type'],
+      control: 'node-ajax-options', editable: function(m) {
+         var of_type = m.get('type'),
+           flag = false;
+         if(m.type_options) {
+          _.each(m.type_options, function(o) {
+            if ( of_type == o.value ) {
+                if(o.is_collatable)
+                {
+                  flag = true;
+                }
+            }
+          });
+         }
+
+         if (flag) {
+           setTimeout(function(){
+             m.set('collspcname', "");
+           }, 10);
+         }
+         return flag;
+      },
       type: 'text', disabled: false, url: 'get_collations', node: 'type'
     }],
     validate: function() {
@@ -323,7 +394,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Backgrid) {
           model: CompositeModel, editable: true, type: 'collection',
           group: '{{ _('Definition') }}', mode: ['edit', 'create'],
           control: 'unique-col-collection', uniqueCol : ['member_name'],
-          canAdd: true, canEdit: true, canDelete: true, disabled: 'inSchema',
+          canAdd: true, canEdit: false, canDelete: true, disabled: 'inSchema',
           deps: ['typtype'], deps: ['typtype'],
           visible: function(m) {
            return m.get('typtype') === 'c';
@@ -358,8 +429,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Backgrid) {
             select2: { allowClear: true, placeholder: "", width: "100%" },
             url: 'get_stypes', type: 'text', mode: ['properties', 'create', 'edit'],
             group: '{{ _('Range Type') }}', disabled: 'inSchemaWithModelCheck',
-            transform: function(d){
-              this.model.subtypes =  d;
+            transform: function(d, self){
+              self.model.subtypes =  d;
               return d;
             }
           },{
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/type/sql/9.1_plus/get_types.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/type/sql/9.1_plus/get_types.sql
index 2a7d3d8..1055ac6 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/type/sql/9.1_plus/get_types.sql
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/types/templates/type/sql/9.1_plus/get_types.sql
@@ -2,7 +2,8 @@ SELECT * FROM
     (SELECT format_type(t.oid,NULL) AS typname,
     CASE WHEN typelem > 0 THEN typelem ELSE t.oid END AS elemoid,
     typlen, typtype, t.oid, nspname,
-    (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup
+    (SELECT COUNT(1) FROM pg_type t2 WHERE t2.typname = t.typname) > 1 AS isdup,
+    CASE WHEN t.typcollation != 0 THEN TRUE ELSE FALSE END AS is_collatable
 FROM pg_type t
    JOIN pg_namespace nsp ON typnamespace=nsp.oid
 WHERE (NOT (typname = 'unknown' AND nspname = 'pg_catalog')) AND typisdefined AND typtype IN ('b', 'c', 'd', 'e', 'r') AND NOT EXISTS (select 1 from pg_class where relnamespace=typnamespace and relname = typname and relkind != 'c') AND (typname not like '_%' OR NOT EXISTS (select 1 from pg_class where relnamespace=typnamespace and relname = substring(typname from 2)::name and relkind != 'c'))  AND nsp.nspname != 'information_schema'
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/js/mview.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/js/mview.js
index 1772ca3..83ea88c 100644
--- a/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/js/mview.js
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/views/templates/mview/js/mview.js
@@ -148,24 +148,6 @@ function($, _, S, pgAdmin, alertify, pgBrowser, CodeMirror) {
           type: 'text', mode: ['create', 'edit'], group: 'Definition',
           control: Backform.SqlFieldControl, extraClasses:['sql_field_width_full']
         },
-        // Add Privilege Control
-        {
-          id: 'datacl', label: '{{ _("Privileges") }}',
-          model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend(
-            {privileges: ['a', 'r', 'w', 'd', 'D', 'x', 't']}), uniqueCol : ['grantee'],
-          editable: false, type: 'collection', group: '{{ _("Security") }}',
-          mode: ['edit', 'create'], canAdd: true, canDelete: true,
-          control: 'unique-col-collection', priority: 3
-        },
-
-        // Add Security Labels Control
-        {
-          id: 'seclabels', label: '{{ _("Security Labels") }}',
-          model: Backform.SecurityModel, editable: false, type: 'collection',
-          canEdit: false, group: '{{ _("Security") }}', canDelete: true,
-          mode: ['edit', 'create'], canAdd: true,
-          control: 'unique-col-collection', uniqueCol : ['provider']
-        },
         {
           id: 'with_data', label: '{{ _("With Data") }}',
           group: '{{ _("Storage") }}', mode: ['edit', 'create'],
@@ -187,10 +169,28 @@ function($, _, S, pgAdmin, alertify, pgBrowser, CodeMirror) {
         },
         {
           type: 'nested', control: 'tab', id: 'materialization',
-          label: '{{ _("Materialization") }}', mode: ['edit', 'create'],
-          group: '{{ _("Storage") }}',
+          label: '{{ _("Auto vacuum") }}', mode: ['edit', 'create'],
+          group: '{{ _("Auto vacuum") }}',
           schema: Backform.VacuumSettingsSchema
         },
+        // Add Privilege Control
+        {
+          id: 'datacl', label: '{{ _("Privileges") }}',
+          model: pgAdmin.Browser.Node.PrivilegeRoleModel.extend(
+            {privileges: ['a', 'r', 'w', 'd', 'D', 'x', 't']}), uniqueCol : ['grantee'],
+          editable: false, type: 'collection', group: '{{ _("Security") }}',
+          mode: ['edit', 'create'], canAdd: true, canDelete: true,
+          control: 'unique-col-collection', priority: 3
+        },
+
+        // Add Security Labels Control
+        {
+          id: 'seclabels', label: '{{ _("Security Labels") }}',
+          model: Backform.SecurityModel, editable: false, type: 'collection',
+          canEdit: false, group: '{{ _("Security") }}', canDelete: true,
+          mode: ['edit', 'create'], canAdd: true,
+          control: 'unique-col-collection', uniqueCol : ['provider']
+        }
         ],
         validate: function(keys) {
 


view thread (49+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected], [email protected]
  Subject: Re: [PATCH] Tables node (pgAdmin4)
  In-Reply-To: <CAKKotZS9MbvFpSkYtRfcLZ8_2drrMpL8T-btH4QXf-BPL0cYzQ@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox