Hi, Here is updated patch for RM2421.
Now I have moved all Numeric control level validations to datamodel. As existing implementation was causing issues with error messages in create/edit dialog when schema contains two or more Numeric controls. This is generic issue and not related to resource group. Also I have updated all other nodes which uses Numeric controls -- *Harshal Dhumal* *Sr. Software Engineer* EnterpriseDB India: http://www.enterprisedb.com The Enterprise PostgreSQL Company On Fri, May 19, 2017 at 12:22 PM, Harshal Dhumal < harshal.dhu...@enterprisedb.com> wrote: > Hi, > > On Thu, May 18, 2017 at 7:57 PM, Joao Pedro De Almeida Pereira < > jdealmeidapere...@pivotal.io> wrote: > >> Hello Harshal, >> >> We review the patch and have some questions: >> 1) Is there any particular reason to initialize variables and functions >> in the same place? We believe that it would be more readable there were no >> chaining of variable creation, specially if those variables are functions. >> Check line: >> > That function is only going to be used in checkNumeric function (in case > of Number control) and checkInt function (in case of Integer control) so > declared them locally. > Anyway I'm going to refactor both the controls as Number and Integer > shares some common properties. > > +++ b/web/pgadmin/static/js/backform.pgadmin.js >> @@ -1528,7 +1528,18 @@ >> max_value = field.max, >> isValid = true, >> intPattern = new RegExp("^-?[0-9]*$"), >> - isMatched = intPattern.test(value); >> + isMatched = intPattern.test(value), >> + trigger_invalid_event = function(msg) { >> >> >> 2) The functions added in both places look very similar, can they be >> merged and extracted? We are talking about the trigger_invalid_event >> function. >> > Yes they can be merged. As of now both NumericControl and IntegerControl > are derived from InputControl. Ideally > only NumericControl should be derived from InputControl and IntegerControl > should be derive from NumericControl. > > > >> 3) The following change is very similar to the trigger_invalid_event, >> was there a reason not to use it? >> > Below code triggers "model valid" event; opposite to "model invalid" event > (trigger_invalid_event) > >> +++ b/web/pgadmin/static/js/backform.pgadmin.js >> @@ -1573,25 +1584,23 @@ >> this.model.errorModel.unset(name); >> this.model.set(name, value); >> this.listenTo(this.model, "change:" + name, this.render); >> - if (this.model.collection || this.model.handler) { >> - (this.model.collection || this.model.handler).trigger( >> - 'pgadmin-session:model:valid', this.model, >> (this.model.collection || this.model.handler) >> - ); >> + // Check if other fields of same model are valid before >> + // triggering 'session:valid' event >> + if(_.size(this.model.errorModel.attributes) == 0) { >> + if (this.model.collection || this.model.handler) { >> + (this.model.collection || this.model.handler).trigger( >> + 'pgadmin-session:model:valid', this.model, >> (this.model.collection || this.model.handler) >> + ); >> + } else { >> + (this.model).trigger( >> + 'pgadmin-session:valid', this.model.sessChanged(), this.model >> + ); >> + } >> >> >> 4) We also noticed that the following change sets look very similiar. Is >> there any reason to have this code duplicated? If not this could be a good >> time to refactor it. >> > As said earlier in response of point 2 code duplication is because the way > controls are derived. > > >> +++ b/web/pgadmin/static/js/backform.pgadmin.js >> @@ -1528,7 +1528,18 @@ >> >> @@ -1573,25 +1584,23 @@ >> >> @@ -1631,7 +1640,18 @@ >> >> @@ -1676,25 +1696,23 @@ >> >> >> >> Thanks >> Joao & Shruti >> >> On Thu, May 18, 2017 at 6:01 AM, Harshal Dhumal < >> harshal.dhu...@enterprisedb.com> wrote: >> >>> Hi, >>> >>> Please find attached patch for RM2421 >>> >>> Issue fixed: 1. Integer/numeric Validation is not working properly. >>> 2. Wrong CPU rate unit >>> -- >>> *Harshal Dhumal* >>> *Sr. Software Engineer* >>> >>> EnterpriseDB India: http://www.enterprisedb.com >>> The Enterprise PostgreSQL Company >>> >>> >>> -- >>> Sent via pgadmin-hackers mailing list (pgadmin-hackers@postgresql.org) >>> To make changes to your subscription: >>> http://www.postgresql.org/mailpref/pgadmin-hackers >>> >>> >> >
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/templates/foreign_tables/js/foreign_tables.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/templates/foreign_tables/js/foreign_tables.js index 5f3dc69..b7df585 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/templates/foreign_tables/js/foreign_tables.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/foreign_tables/templates/foreign_tables/js/foreign_tables.js @@ -101,34 +101,56 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { cell: 'string', group: '{{ _('Definition') }}', type: 'int', deps: ['datatype'], disabled: function(m) { - // We will store type from selected from combobox + var val = m.get('typlen'); + // We will store type from selected from combobox if(!(_.isUndefined(m.get('inheritedid')) || _.isNull(m.get('inheritedid')) || _.isUndefined(m.get('inheritedfrom')) - || _.isNull(m.get('inheritedfrom')))) { return true; } + || _.isNull(m.get('inheritedfrom')))) { - var of_type = m.get('datatype'); - if(m.type_options) { - m.set('is_tlength', false, {silent: true}); + if (!_.isUndefined(val)) { + setTimeout(function() { + m.set('typlen', undefined); + }, 10); + } + return true; + } + + var of_type = m.get('datatype'), + has_length = false; + if(m.type_options) { + m.set('is_tlength', false, {silent: true}); - // iterating over all the types - _.each(m.type_options, function(o) { - // if type from selected from combobox matches in options - if ( of_type == o.value ) { - m.set('typlen', undefined); + // iterating over all the types + _.each(m.type_options, function(o) { + // if type from selected from combobox matches in options + if ( of_type == o.value ) { // if length is allowed for selected type if(o.length) { // set the values in model + has_length = true; m.set('is_tlength', true, {silent: true}); m.set('min_val', o.min_val, {silent: true}); m.set('max_val', o.max_val, {silent: true}); } + } + }); + + if (!has_length && !_.isUndefined(val)) { + setTimeout(function() { + m.set('typlen', undefined); + }, 10); } - }); - return !(m.get('is_tlength')); - } - return true; + + return !(m.get('is_tlength')); + } + if (!has_length && !_.isUndefined(val)) { + setTimeout(function() { + m.set('typlen', undefined); + }, 10); + } + return true; }, cellHeaderClasses: 'width_percent_10' },{ @@ -136,33 +158,54 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { type: 'int', deps: ['datatype'], cell: 'string', group: '{{ _('Definition') }}', disabled: function(m) { + var val = m.get('precision'); if(!(_.isUndefined(m.get('inheritedid')) || _.isNull(m.get('inheritedid')) || _.isUndefined(m.get('inheritedfrom')) - || _.isNull(m.get('inheritedfrom')))) { return true; } + || _.isNull(m.get('inheritedfrom')))) { + + if (!_.isUndefined(val)) { + setTimeout(function() { + m.set('precision', undefined); + }, 10); + } + return true; + } + + var of_type = m.get('datatype'), + has_precision = false; - var of_type = m.get('datatype'); if(m.type_options) { m.set('is_precision', false, {silent: true}); // iterating over all the types _.each(m.type_options, function(o) { // if type from selected from combobox matches in options if ( of_type == o.value ) { - m.set('precision', undefined); // if precession is allowed for selected type if(o.precision) { + has_precision = true; // set the values in model m.set('is_precision', true, {silent: true}); m.set('min_val', o.min_val, {silent: true}); m.set('max_val', o.max_val, {silent: true}); } + } + }); + if (!has_precision && !_.isUndefined(val)) { + setTimeout(function() { + m.set('precision', undefined); + }, 10); } - }); - return !(m.get('is_precision')); - } - return true; - }, cellHeaderClasses: 'width_percent_10' + return !(m.get('is_precision')); + } + if (!has_precision && !_.isUndefined(val)) { + setTimeout(function() { + m.set('precision', undefined); + }, 10); + } + return true; + }, cellHeaderClasses: 'width_percent_10' },{ id: 'typdefault', label:'{{ _('Default') }}', type: 'text', cell: 'string', min_version: 90300, group: '{{ _('Definition') }}', @@ -216,22 +259,23 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { min_version: 90200 }], validate: function() { - var err = {}, - errmsg; + var errmsg = null; if (_.isUndefined(this.get('attname')) || String(this.get('attname')).replace(/^\s+|\s+$/g, '') == '') { - err['name'] = '{{ _('Column Name cannot be empty!') }}'; - errmsg = errmsg || err['attname']; + errmsg = '{{ _('Column Name cannot be empty!') }}'; + this.errorModel.set('attname', errmsg); + } else { + this.errorModel.unset('attname'); } if (_.isUndefined(this.get('datatype')) || String(this.get('datatype')) .replace(/^\s+|\s+$/g, '') == '') { - err['basensp'] = '{{ _('Column Datatype cannot be empty!') }}'; - errmsg = errmsg || err['datatype']; + errmsg = '{{ _('Column Datatype cannot be empty!') }}'; + this.errorModel.set('datatype', errmsg); + } else { + this.errorModel.unset('datatype'); } - this.errorModel.clear().set(err); - return errmsg; }, is_editable_column: function(m) { diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/js/sequence.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/js/sequence.js index 2fb7ae5..1b9db50 100644 --- a/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/js/sequence.js +++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/sequences/templates/sequence/js/sequence.js @@ -153,7 +153,10 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { min: 1 },{ id: 'start', label: '{{ _('Start') }}', type: 'int', - mode: ['properties', 'create'], group: '{{ _('Definition') }}' + mode: ['properties', 'create', 'edit'], group: '{{ _('Definition') }}', + disabled: function(m) { + return !m.isNew(); + } },{ id: 'minimum', label: '{{ _('Minimum') }}', type: 'int', mode: ['properties', 'create', 'edit'], group: '{{ _('Definition') }}' @@ -199,14 +202,14 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { minimum = this.get('minimum'), maximum = this.get('maximum'); start = this.get('start'); - // Clear any existing error msg. - this.errorModel.clear(); if (_.isUndefined(this.get('name')) || String(this.get('name')).replace(/^\s+|\s+$/g, '') == '') { msg = '{{ _('Name cannot be empty.') }}'; this.errorModel.set('name', msg); return msg; + } else { + this.errorModel.unset('name'); } if (_.isUndefined(this.get('seqowner')) @@ -214,6 +217,8 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { msg = '{{ _('Owner cannot be empty.') }}'; this.errorModel.set('seqowner', msg); return msg; + } else { + this.errorModel.unset('seqowner'); } if (_.isUndefined(this.get('schema')) @@ -221,26 +226,81 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { msg = '{{ _('Schema cannot be empty.') }}'; this.errorModel.set('schema', msg); return msg; + } else { + this.errorModel.unset('schema'); + } + + if (!this.isNew()) { + if (_.isUndefined(this.get('current_value')) + || String(this.get('current_value')).replace(/^\s+|\s+$/g, '') == '') { + msg = '{{ _('Current value cannot be empty.') }}'; + this.errorModel.set('current_value', msg); + return msg; + } else { + this.errorModel.unset('current_value'); + } + + if (_.isUndefined(this.get('increment')) + || String(this.get('increment')).replace(/^\s+|\s+$/g, '') == '') { + msg = '{{ _('Increment value cannot be empty.') }}'; + this.errorModel.set('increment', msg); + return msg; + } else { + this.errorModel.unset('increment'); + } + + if (_.isUndefined(this.get('minimum')) + || String(this.get('minimum')).replace(/^\s+|\s+$/g, '') == '') { + msg = '{{ _('Minimum value cannot be empty.') }}'; + this.errorModel.set('minimum', msg); + return msg; + } else { + this.errorModel.unset('minimum'); + } + + if (_.isUndefined(this.get('maximum')) + || String(this.get('maximum')).replace(/^\s+|\s+$/g, '') == '') { + msg = '{{ _('Maximum value cannot be empty.') }}'; + this.errorModel.set('maximum', msg); + return msg; + } else { + this.errorModel.unset('maximum'); + } + + if (_.isUndefined(this.get('cache')) + || String(this.get('cache')).replace(/^\s+|\s+$/g, '') == '') { + msg = '{{ _('Cache value cannot be empty.') }}'; + this.errorModel.set('cache', msg); + return msg; + } else { + this.errorModel.unset('cache'); + } } var min_lt = '{{ _('Minimum value must be less than maximum value.') }}', start_lt = '{{ _('Start value cannot be less than minimum value.') }}', start_gt = '{{ _('Start value cannot be greater than maximum value.') }}'; + if ((minimum == 0 && maximum == 0) || (parseInt(minimum, 10) >= parseInt(maximum, 10))) { - msg = min_lt - this.errorModel.set('minimum', msg); - return msg; + this.errorModel.set('minimum', min_lt); + return min_lt; + } else { + this.errorModel.unset('minimum'); } - else if (start < minimum) { - msg = start_lt - this.errorModel.set('start', msg); - return msg; + + if (start && minimum && parseInt(start) < parseInt(minimum)) { + this.errorModel.set('start', start_lt); + return start_lt; + } else { + this.errorModel.unset('start'); } - else if (start > maximum) { - msg = start_gt - this.errorModel.set('start', msg); - return msg; + + if (start && maximum && parseInt(start) > parseInt(maximum)) { + this.errorModel.set('start', start_gt); + return start_gt; + } else { + this.errorModel.unset('start'); } return null; } diff --git a/web/pgadmin/browser/server_groups/servers/resource_groups/templates/resource_groups/js/resource_groups.js b/web/pgadmin/browser/server_groups/servers/resource_groups/templates/resource_groups/js/resource_groups.js index 3cc822e..26e63bf 100644 --- a/web/pgadmin/browser/server_groups/servers/resource_groups/templates/resource_groups/js/resource_groups.js +++ b/web/pgadmin/browser/server_groups/servers/resource_groups/templates/resource_groups/js/resource_groups.js @@ -85,54 +85,35 @@ define( */ validate: function(keys) { - /* Check whether 'name' is present in 'keys', if it is present - * it means there is a change in that field from the GUI, so we - * need to validate it. - */ - if (_.indexOf(keys, 'name') >= 0) { - var name = this.get('name'); - if (_.isUndefined(name) || _.isNull(name) || - String(name).replace(/^\s+|\s+$/g, '') == '') { - var msg = '{{ _('Name cannot be empty.') }}'; - this.errorModel.set('name', msg); - return msg; - } else { - this.errorModel.unset('name'); - } + var name = this.get('name'); + if (_.isUndefined(name) || _.isNull(name) || + String(name).replace(/^\s+|\s+$/g, '') == '') { + var msg = '{{ _('Name cannot be empty.') }}'; + this.errorModel.set('name', msg); + return msg; + } else { + this.errorModel.unset('name'); } - /* Check whether 'cpu_rate_limit' is present in 'keys', if it is present - * it means there is a change in that field from the GUI, so we - * need to validate it. - */ - if (_.indexOf(keys, 'cpu_rate_limit') >= 0) { - var cpu_rate_limit = this.get('cpu_rate_limit'); - if (_.isUndefined(cpu_rate_limit) || _.isNull(cpu_rate_limit) || - String(cpu_rate_limit).replace(/^\s+|\s+$/g, '') == '') { - var msg = '{{ _('CPU rate limit cannot be empty.') }}'; - this.errorModel.set('cpu_rate_limit', msg); - return msg; - } else { - this.errorModel.unset('cpu_rate_limit'); - } + var cpu_rate_limit = this.get('cpu_rate_limit'); + if (_.isUndefined(cpu_rate_limit) || _.isNull(cpu_rate_limit) || + String(cpu_rate_limit).replace(/^\s+|\s+$/g, '') == '') { + var msg = '{{ _('CPU rate limit cannot be empty.') }}'; + this.errorModel.set('cpu_rate_limit', msg); + return msg; + } else { + this.errorModel.unset('cpu_rate_limit'); } - /* Check whether 'dirty_rate_limit' is present in 'keys', if it is present - * it means there is a change in that field from the GUI, so we - * need to validate it. - */ - if (_.indexOf(keys, 'dirty_rate_limit') >= 0) { - var dirty_rate_limit = this.get('dirty_rate_limit'); - if (_.isUndefined(dirty_rate_limit) || _.isNull(dirty_rate_limit) || - String(dirty_rate_limit).replace(/^\s+|\s+$/g, '') == '') { - var msg = '{{ _('Dirty rate limit cannot be empty.') }}'; - this.errorModel.set('dirty_rate_limit', msg); - return msg; - } else { - this.errorModel.unset('dirty_rate_limit'); - } + var dirty_rate_limit = this.get('dirty_rate_limit'); + if (_.isUndefined(dirty_rate_limit) || _.isNull(dirty_rate_limit) || + String(dirty_rate_limit).replace(/^\s+|\s+$/g, '') == '') { + var msg = '{{ _('Dirty rate limit cannot be empty.') }}'; + this.errorModel.set('dirty_rate_limit', msg); + return msg; + } else { + this.errorModel.unset('dirty_rate_limit'); } - return null; } }) diff --git a/web/pgadmin/browser/server_groups/servers/roles/templates/role/js/role.js b/web/pgadmin/browser/server_groups/servers/roles/templates/role/js/role.js index a85416c..c74cd59 100644 --- a/web/pgadmin/browser/server_groups/servers/roles/templates/role/js/role.js +++ b/web/pgadmin/browser/server_groups/servers/roles/templates/role/js/role.js @@ -427,7 +427,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Backform) { deps: ['rolcanlogin'], options: {format: 'YYYY-MM-DD HH:mm:ss Z'} },{ id: 'rolconnlimit', type: 'int', group: '{{ _('Definition') }}', - label: '{{ _('Connection limit') }}', cell: 'number', + label: '{{ _('Connection limit') }}', cell: 'number', min : -1, mode: ['properties', 'edit', 'create'], disabled: 'readonly' },{ id: 'rolcanlogin', label:'{{ _('Can login?') }}', type: 'switch', diff --git a/web/pgadmin/browser/server_groups/servers/templates/servers/servers.js b/web/pgadmin/browser/server_groups/servers/templates/servers/servers.js index 9eb82b8..bf28474 100644 --- a/web/pgadmin/browser/server_groups/servers/templates/servers/servers.js +++ b/web/pgadmin/browser/server_groups/servers/templates/servers/servers.js @@ -727,6 +727,9 @@ function($, _, S, pgAdmin, pgBrowser, alertify) { check_for_empty( 'username', '{{ _('Username must be specified.') }}' ); + check_for_empty( + 'port', '{{ _('Port must be specified.') }}' + ); this.errorModel.set(err); if (_.size(err)) { diff --git a/web/pgadmin/browser/static/js/datamodel.js b/web/pgadmin/browser/static/js/datamodel.js index 5b1c3a7..c3b5fac 100644 --- a/web/pgadmin/browser/static/js/datamodel.js +++ b/web/pgadmin/browser/static/js/datamodel.js @@ -1,6 +1,6 @@ define( - ['underscore', 'pgadmin', 'jquery', 'backbone'], -function(_, pgAdmin, $, Backbone) { + ['underscore', 'underscore.string', 'pgadmin', 'jquery', 'backbone'], +function(_, S, pgAdmin, $, Backbone) { var pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {}; pgBrowser.DataModel = Backbone.Model.extend({ @@ -136,6 +136,7 @@ function(_, pgAdmin, $, Backbone) { } self.sessAttrs = {}; + self.fieldData = {}; self.origSessAttrs = {}; self.objects = []; self.arrays = []; @@ -153,6 +154,23 @@ function(_, pgAdmin, $, Backbone) { _.each(schema, function(s) { switch(s.type) { + case 'int': + case 'numeric': + self.fieldData[s.id] = { + label: s.id, + type: s.type, + min: s.min || undefined, + max: s.max || undefined + } + break; + default: + self.fieldData[s.id] = { + label: s.id, + type: s.type + } + } + + switch(s.type) { case 'array': self.arrays.push(s.id); @@ -280,6 +298,12 @@ function(_, pgAdmin, $, Backbone) { }, sessValid: function() { var self = this; + // Perform default validations. + if ('default_validate' in self && typeof(self.default_validate) == 'function' && + _.isString(self.default_validate())) { + return false; + } + if ('validate' in self && _.isFunction(self.validate) && _.isString(self.validate.apply(self))) { return false; @@ -301,8 +325,9 @@ function(_, pgAdmin, $, Backbone) { } if (key != null && res) { - var attrs = {}; - var self = this; + var attrs = {}, + self = this, + msg; attrChanged = function(v, k) { if (k in self.objects) { @@ -327,9 +352,18 @@ function(_, pgAdmin, $, Backbone) { if (!options || !options.silent) { self.trigger('change', self, options); } + + // Perform default validations. + + if ('default_validate' in self && typeof(self.default_validate) == 'function') { + msg = self.default_validate(); + } + if ('validate' in self && typeof(self['validate']) === 'function') { - var msg = self.validate(_.keys(attrs)); + if (!msg) { + msg = self.validate(_.keys(attrs)); + } /* * If any parent present, we will need to inform the parent - that @@ -562,6 +596,13 @@ function(_, pgAdmin, $, Backbone) { var msg = null, validate = function(m, attrs) { + if ('default_validate' in m && typeof(m.default_validate) == 'function') { + msg = m.default_validate(); + if (_.isString(msg)) { + return msg; + } + } + if ('validate' in m && typeof(m.validate) == 'function') { msg = m.validate(attrs); @@ -655,6 +696,79 @@ function(_, pgAdmin, $, Backbone) { }); self.trigger('pgadmin-session:stop'); + }, + default_validate: function() { + var msg, field, value, type; + + for (var i = 0, keys = _.keys(this.attributes), l = keys.length; + i<l; + i++) { + + value = this.attributes[keys[i]]; + field = this.fieldData[keys[i]] + msg = null; + + if (!(_.isUndefined(value) || _.isNull(value) || + String(value).replace(/^\s+|\s+$/g, '') == '')) { + + if (!field) { + continue; + } + + type = field.type || undefined; + if (!type) { + continue; + } + + switch(type) { + case 'int': + msg = this.integer_validate(value, field); + break; + case 'numeric': + msg = this.number_validate(value, field); + break; + } + + if (msg) { + this.errorModel.set(field.label, msg); + return msg; + } else { + this.errorModel.unset(field.label); + } + } else { + if (field) { + this.errorModel.unset(field.label); + } + } + } + return null; + }, + + check_min_max: function (value, field) { + var label = field.label, + min_value = field.min, + max_value = field.max; + + if (min_value && value < min_value) { + return S(pgAdmin.Browser.messages.MUST_GR_EQ).sprintf(label, min_value).value(); + } else if (max_value && value > max_value) { + return S(pgAdmin.Browser.messages.MUST_LESS_EQ).sprintf(label, max_value).value(); + } + return null; + }, + number_validate: function (value, field) { + var pattern = new RegExp("^-?[0-9]+(\.?[0-9]*)?$"); + if (!pattern.test(value)) { + return S(pgAdmin.Browser.messages.MUST_BE_NUM).sprintf(field.label).value() + } + return this.check_min_max(value, field) + }, + integer_validate: function(value, field) { + var pattern = new RegExp("^-?[0-9]*$"); + if (!pattern.test(value)) { + return S(pgAdmin.Browser.messages.MUST_BE_INT).sprintf(field.label).value() + } + return this.check_min_max(value, field) } }); @@ -696,7 +810,8 @@ function(_, pgAdmin, $, Backbone) { return self; }, startNewSession: function() { - var self = this; + var self = this, + msg; if (self.trackChanges) { // We're stopping the existing session. @@ -718,8 +833,15 @@ function(_, pgAdmin, $, Backbone) { if ('startNewSession' in m && _.isFunction(m.startNewSession)) { m.startNewSession(); } - if ('validate' in m && typeof(m.validate) === 'function') { - var msg = m.validate(); + + if ('default_validate' in m && typeof(m.default_validate) == 'function') { + msg = m.default_validate(); + } + + if (_.isString(msg)) { + self.sessAttrs['invalid'][m.cid] = msg; + } else if ('validate' in m && typeof(m.validate) === 'function') { + msg = m.validate(); if (msg) { self.sessAttrs['invalid'][m.cid] = msg; @@ -900,7 +1022,14 @@ function(_, pgAdmin, $, Backbone) { (self.handler || self).trigger('pgadmin-session:added', self, obj); - if ('validate' in obj && typeof(obj.validate) === 'function') { + + if ('default_validate' in obj && typeof(obj.default_validate) == 'function') { + msg = obj.default_validate(); + } + + if (_.isString(msg)) { + (self.sessAttrs['invalid'])[obj.cid] = msg; + } else if ('validate' in obj && typeof(obj.validate) === 'function') { msg = obj.validate(); if (msg) { @@ -908,7 +1037,14 @@ function(_, pgAdmin, $, Backbone) { } } } else { - if ('validate' in obj && typeof(obj.validate) === 'function') { + + if ('default_validate' in obj && typeof(obj.default_validate) == 'function') { + msg = obj.default_validate(); + } + + if (_.isString(msg)) { + (self.sessAttrs['invalid'])[obj.cid] = msg; + } else if ('validate' in obj && typeof(obj.validate) === 'function') { msg = obj.validate(); if (msg) { diff --git a/web/pgadmin/static/js/backform.pgadmin.js b/web/pgadmin/static/js/backform.pgadmin.js index 553676e..cf41297 100644 --- a/web/pgadmin/static/js/backform.pgadmin.js +++ b/web/pgadmin/static/js/backform.pgadmin.js @@ -1491,115 +1491,13 @@ Backform.Control.__super__.remove.apply(this, arguments); } -}); - - /* - * Integer input Control functionality just like backgrid - */ - var IntegerControl = Backform.IntegerControl = Backform.InputControl.extend({ - defaults: { - type: "number", - label: "", - min: undefined, - max: undefined, - maxlength: 255, - extraClasses: [], - helpMessage: null - }, - template: _.template([ - '<label class="<%=Backform.controlLabelClassName%>"><%=label%></label>', - '<div class="<%=Backform.controlsClassName%>">', - ' <input type="<%=type%>" class="<%=Backform.controlClassName%> <%=extraClasses.join(\' \')%>" name="<%=name%>" min="<%=min%>" max="<%=max%>"maxlength="<%=maxlength%>" value="<%-value%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%> <%=required ? "required" : ""%> />', - ' <% if (helpMessage && helpMessage.length) { %>', - ' <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>', - ' <% } %>', - '</div>' - ].join("\n")), - events: { - "change input": "checkInt", - "focus input": "clearInvalid" - }, - checkInt: function(e) { - var field = _.defaults(this.field.toJSON(), this.defaults), - attrArr = this.field.get("name").split('.'), - name = attrArr.shift(), - value = this.getValueFromDOM(), - min_value = field.min, - max_value = field.max, - isValid = true, - intPattern = new RegExp("^-?[0-9]*$"), - isMatched = intPattern.test(value); - - // Below logic will validate input - if (!isMatched) { - isValid = false; - this.model.errorModel.unset(name); - this.model.errorModel.set( - name, - S(pgAdmin.Browser.messages.MUST_BE_INT).sprintf( - field.label - ).value() - ); - } - - // Below will check if entered value is in-between min & max range - if (isValid && (!_.isUndefined(min_value) && value < min_value)) { - isValid = false; - this.model.errorModel.unset(name); - this.model.errorModel.set( - name, - S(pgAdmin.Browser.messages.MUST_GR_EQ).sprintf( - field.label, - min_value - ).value() - ); - } - - if (isValid && (!_.isUndefined(max_value) && value > max_value)) { - isValid = false; - this.model.errorModel.unset(name); - this.model.errorModel.set( - name, - S(pgAdmin.Browser.messages.MUST_LESS_EQ).sprintf( - field.label, - max_value - ).value() - ); - } - - // After validation we need to set that value into model (only if all flags are true) - if (isValid) { - this.stopListening(this.model, "change:" + name, this.render); - this.model.errorModel.unset(name); - this.model.set(name, value); - this.listenTo(this.model, "change:" + name, this.render); - if (this.model.collection || this.model.handler) { - (this.model.collection || this.model.handler).trigger( - 'pgadmin-session:model:valid', this.model, (this.model.collection || this.model.handler) - ); - } else { - (this.model).trigger( - 'pgadmin-session:valid', this.model.sessChanged(), this.model - ); - } - } else { - if (this.model.collection || this.model.handler) { - (this.model.collection || this.model.handler).trigger( - 'pgadmin-session:model:invalid', this.model.errorModel.get(name), this.model - ); - } else { - (this.model).trigger( - 'pgadmin-session:invalid', this.model.errorModel.get(name), this.model - ); - } - } - } }); /* * Numeric input Control functionality just like backgrid */ var NumericControl = Backform.NumericControl = Backform.InputControl.extend({ + defaults: { type: "number", label: "", @@ -1617,86 +1515,7 @@ ' <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>', ' <% } %>', '</div>' - ].join("\n")), - events: { - "change input": "checkNumeric", - "focus input": "clearInvalid" - }, - checkNumeric: function(e) { - var field = _.defaults(this.field.toJSON(), this.defaults), - attrArr = this.field.get("name").split('.'), - name = attrArr.shift(), - value = this.getValueFromDOM(), - min_value = field.min, - max_value = field.max, - isValid = true, - intPattern = new RegExp("^-?[0-9]+(\.?[0-9]*)?$"), - isMatched = intPattern.test(value); - - // Below logic will validate input - if (!isMatched) { - isValid = false; - this.model.errorModel.unset(name); - this.model.errorModel.set( - name, - S(pgAdmin.Browser.messages.MUST_BE_NUM).sprintf( - field.label - ).value() - ); - } - - // Below will check if entered value is in-between min & max range - if (isValid && (!_.isUndefined(min_value) && value < min_value)) { - isValid = false; - this.model.errorModel.unset(name); - this.model.errorModel.set( - name, - S(pgAdmin.Browser.messages.MUST_GR_EQ).sprintf( - field.label, - min_value - ).value() - ); - } - - if (isValid && (!_.isUndefined(max_value) && value > max_value)) { - isValid = false; - this.model.errorModel.unset(name); - this.model.errorModel.set( - name, - S(pgAdmin.Browser.messages.MUST_LESS_EQ).sprintf( - field.label, - max_value - ).value() - ); - } - - // After validation we need to set that value into model (only if all flags are true) - if (isValid) { - this.stopListening(this.model, "change:" + name, this.render); - this.model.errorModel.unset(name); - this.model.set(name, value); - this.listenTo(this.model, "change:" + name, this.render); - if (this.model.collection || this.model.handler) { - (this.model.collection || this.model.handler).trigger( - 'pgadmin-session:model:valid', this.model, (this.model.collection || this.model.handler) - ); - } else { - (this.model).trigger( - 'pgadmin-session:valid', this.model.sessChanged(), this.model - ); - } - } else { - if (this.model.collection || this.model.handler) { - (this.model.collection || this.model.handler).trigger( - 'pgadmin-session:model:invalid', this.model.errorModel.get(name), this.model - ); - } else { - (this.model).trigger( - 'pgadmin-session:invalid', this.model.errorModel.get(name), this.model - ); - } - } - } + ].join("\n")) }); ///////
-- Sent via pgadmin-hackers mailing list (pgadmin-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgadmin-hackers