diff options
Diffstat (limited to 'install/ui/src')
-rw-r--r-- | install/ui/src/dojo.profile.js | 1 | ||||
-rw-r--r-- | install/ui/src/freeipa/datetime.js | 217 | ||||
-rw-r--r-- | install/ui/src/freeipa/field.js | 116 | ||||
-rw-r--r-- | install/ui/src/freeipa/host.js | 25 | ||||
-rw-r--r-- | install/ui/src/freeipa/ipa.js | 39 | ||||
-rw-r--r-- | install/ui/src/freeipa/user.js | 2 | ||||
-rw-r--r-- | install/ui/src/freeipa/widget.js | 18 | ||||
-rw-r--r-- | install/ui/src/webui.profile.js | 1 |
8 files changed, 353 insertions, 66 deletions
diff --git a/install/ui/src/dojo.profile.js b/install/ui/src/dojo.profile.js index b93ac2480..2aeef9690 100644 --- a/install/ui/src/dojo.profile.js +++ b/install/ui/src/dojo.profile.js @@ -69,6 +69,7 @@ var profile = (function(){ // ^ core is about 20KB "dojo/_base/lang", "dojo/_base/array", + "dojo/string", // ^ adds 10KB "dojo/dom", "dojo/dom-construct", diff --git a/install/ui/src/freeipa/datetime.js b/install/ui/src/freeipa/datetime.js new file mode 100644 index 000000000..5802b972d --- /dev/null +++ b/install/ui/src/freeipa/datetime.js @@ -0,0 +1,217 @@ +/* Authors: + * Petr Vobornik <pvoborni@redhat.com> + * + * Copyright (C) 2014 Red Hat + * see file 'COPYING' for use and warranty information + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + + +define([ + 'dojo/string' + ], function(string) { + + var templates = { + human: '${YYYY}-${MM}-${DD} ${HH}:${mm}:${ss}Z', + generalized: '${YYYY}${MM}${DD}${HH}${mm}${ss}Z' + }; + + var dates = [ + ['YYYY-MM-DD', /^(\d{4})-(\d{2})-(\d{2})$/], + ['YYYYMMDD',/^(\d{4})(\d{2})(\d{2})$/] + ]; + + var times = [ + ['HH:mm:ss', /^(\d\d):(\d\d):(\d\d)$/], + ['HH:mm', /^(\d\d):(\d\d)$/] + ]; + + var generalized_regex = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z$/; + var datetime_regex = /^((?:\d{8})|(?:\d{4}-\d{2}-\d{2}))(?:(T| )(\d\d:\d\d(?::\d\d)?)(Z?))?$/; + + function parse(value) { + + var Y=0, M=0, D=0, H=0, m=0, s=0; + var i, l, dateStr, timeStr, utc; + + var dt_match = datetime_regex.exec(value); + var gt_match = generalized_regex.exec(value); + if (dt_match) { + dateStr = dt_match[1]; + timeStr = dt_match[3]; + utc = dt_match[4] || !timeStr; + + // error out if local time not supported + if (!this.allow_local && !utc) return null; + + for (i = 0, l = dates.length; i < l; i++) { + var dm = dates[i][1].exec(dateStr); + if (dm) { + Y = dm[1]; + M = dm[2]; + D = dm[3]; + break; + } + } + + if (timeStr) { + for (i = 0, l = times.length; i < l; i++) { + var tm = times[i][1].exec(timeStr); + if (tm) { + H = tm[1]; + m = tm[2] || 0; + s = tm[3] || 0; + break; + } + } + } + } else if (gt_match) { + Y = gt_match[1]; + M = gt_match[2]; + D = gt_match[3]; + H = gt_match[4]; + m = gt_match[5]; + s = gt_match[6]; + utc = true; + } else { + return null; + } + + var date = new Date(); + + if (utc || !timeStr) { + date.setUTCFullYear(Y, M-1, D); + date.setUTCHours(H, m, s, 0); + } else { + date.setFullYear(Y, M-1, D); + date.setHours(H, m, s, 0); + } + return date; + } + + function formatDate(date, format, local) { + + var fmt = format || templates.human; + var str; + + function pad(value) { + return string.pad(value, 2, '0'); + } + + if (local) { + str = string.substitute(fmt, { + YYYY: date.getFullYear(), + MM: pad(date.getMonth()+1), + DD: pad(date.getDate()), + HH: pad(date.getHours()), + mm: pad(date.getMinutes()), + ss: pad(date.getSeconds()) + }); + } else { + str = string.substitute(fmt, { + YYYY: date.getUTCFullYear(), + MM: pad(date.getUTCMonth()+1), + DD: pad(date.getUTCDate()), + HH: pad(date.getUTCHours()), + mm: pad(date.getUTCMinutes()), + ss: pad(date.getUTCSeconds()) + }); + } + return str; + } + + /** + * Utility module to parse strings in ISO 8601-ish format into Date object + * and vice versa + * + * @class datetime + * @singleton + */ + var datetime = { + /** + * Parse string, return date or null on error. + * + * Supported date formats: + * + * - `YYYY-MM-DD` + * - `YYYYMMDD` + * + * Supported time formats: + * + * - `HH:mm:ss` + * - `HH:mm` + * + * Supported formats: + * + * - `$dateT$timeZ` + * - `$date $timeZ` + * - `$date` + * - `YYYYMMDDHHmmssZ` + * + * Where Z indicates UTC date. Parsing of local dates is by default + * disabled. It can be enabled by setting `datetime.allow_local` to + * `true`. + * + * @param {string} value + * @returns {Date|null} parsed date + */ + parse: parse, + + /** + * Convert date to string + * + * - `${YYYY}` - year + * - `${MM}` - month + * - `${DD}` - day + * - `${HH}` - hours + * - `${mm}` - minutes + * - `${ss}` - seconds + * + * Default format string: `${YYYY}-${MM}-${DD} ${HH}:${mm}:${ss}` + * + * @param {Date} date + * @param {string} [format] format string + * @param {boolean} [local] use local time + */ + format: formatDate, + + /** + * Local time input method support + * @property {boolean} + */ + allow_local: false, + + /** + * Convert date value to generalized time string + * @param {Date} date + * @returns {string} + */ + to_generalized_time: function(date) { + return this.format(date, templates.generalized); + }, + + /** + * Dictionary of common format strings + * + * - `human` - default format string of `format` method + * - `generalized` - generalized time (LDAP) format + * + * @property {Object} + */ + templates: templates + }; + + return datetime; +});
\ No newline at end of file diff --git a/install/ui/src/freeipa/field.js b/install/ui/src/freeipa/field.js index f054ecc0e..ef50ebf2a 100644 --- a/install/ui/src/freeipa/field.js +++ b/install/ui/src/freeipa/field.js @@ -27,13 +27,15 @@ define([ 'dojo/_base/lang', './metadata', './builder', + './datetime', './ipa', './jquery', './navigation', './phases', './reg', './text'], - function(array, lang, metadata_provider, builder, IPA, $, navigation, phases, reg, text) { + function(array, lang, metadata_provider, builder, datetime, IPA, $, + navigation, phases, reg, text) { /** * Field module @@ -116,12 +118,21 @@ IPA.field = function(spec) { * Formatter * * - transforms field value to widget value - * - only for read-only fields + * - use corresponding output_formatter if field is not read-only and + * backend can't handle the different format * @property {IPA.formatter} */ that.formatter = builder.build('formatter', spec.formatter); /** + * Output formatter + * + * - transforms widget value into value for backend + * @property {IPA.formatter} + */ + that.output_formatter = builder.build('formatter', spec.output_formatter); + + /** * Widget * @property {IPA.input_widget} */ @@ -297,7 +308,7 @@ IPA.field = function(spec) { if (!that.enabled) return that.valid; - var values = that.save(); + var values = that.get_widget_values(); if (IPA.is_empty(values)) { return that.valid; @@ -424,9 +435,8 @@ IPA.field = function(spec) { var formatted_values; - // The formatter is currently only used on read-only fields only - // because it cannot parse formatted values back to internal values. - if (that.formatter && that.read_only) { + // Change loaded value to human readable value + if (that.formatter) { formatted_values = []; for (var i=0; that.values && i<that.values.length; i++) { var value = that.values[i]; @@ -468,13 +478,14 @@ IPA.field = function(spec) { var values = that.values; - if(!that.enabled) return ['']; + if (!that.enabled) return ['']; - if(that.widget) { - values = that.widget.save(); + if (that.widget) { + values = that.get_widget_values(); + values = that.format_output(values); } - if(record) { + if (record) { record[that.param] = values; } @@ -482,6 +493,41 @@ IPA.field = function(spec) { }; /** + * Gets widget values + * @returns {Array} + */ + that.get_widget_values = function() { + + var values = ['']; + + if (that.widget) { + values = that.widget.save(); + } + + return values; + }; + + /** + * Use output formatter to transform value entered into UI to + * value used by backend + * + * @param {Array} values + * @return {Array} formatted values + */ + that.format_output = function(values) { + + if (that.output_formatter) { + var formatted_values = []; + for (var i=0; values && i<values.length; i++) { + var formatted_value = that.output_formatter.format(values[i]); + formatted_values.push(formatted_value); + } + return formatted_values; + } + return values; + }; + + /** * This function compares the original values and the * values entered in the UI. If the values have changed * it will return true. @@ -853,6 +899,54 @@ IPA.same_password_validator = function(spec) { }; /** + * Check if input value is a valid datetime + * + * @class IPA.datetime_validator + * @extends IPA.validator + */ +IPA.datetime_validator = function(spec) { + + spec = spec || {}; + + var that = IPA.validator(spec); + + that.message = text.get(spec.message || '@i18n:widget.validation.datetime'); + + /** + * @inheritDoc + */ + that.validate = function(value, context) { + + var valid = datetime.parse(value) !== null; + if (!valid) return that.false_result(); + + return that.true_result(); + }; + + return that; +}; + +/** + * Used along with checkbox widget + * + * @class IPA.checkbox_field + * @extends IPA.field + */ +IPA.datetime_field = function(spec) { + + spec = spec || {}; + spec.validators = spec.validators || ['datetime']; + spec.output_formatter = spec.output_formatter || { + $type: 'datetime', + template: datetime.templates.generalized + }; + spec.formatter = spec.formatter || 'datetime'; + + var that = IPA.field(spec); + return that; +}; + +/** * Used along with checkbox widget * * @class IPA.checkbox_field @@ -1461,6 +1555,7 @@ exp.register = function() { f.register('checkbox', IPA.checkbox_field); f.register('checkboxes', IPA.checkboxes_field); f.register('combobox', IPA.field); + f.register('datetime', IPA.datetime_field); f.register('enable', IPA.enable_field); f.register('entity_select', IPA.field); f.register('field', IPA.field); @@ -1477,6 +1572,7 @@ exp.register = function() { v.register('metadata', IPA.metadata_validator); v.register('unsupported', IPA.unsupported_validator); v.register('same_password', IPA.same_password_validator); + v.register('datetime', IPA.datetime_validator); }; phases.on('registration', exp.register); diff --git a/install/ui/src/freeipa/host.js b/install/ui/src/freeipa/host.js index 923c82c65..8b6692282 100644 --- a/install/ui/src/freeipa/host.js +++ b/install/ui/src/freeipa/host.js @@ -357,6 +357,19 @@ IPA.host_fqdn_widget = function(spec) { }); }; + that.save = function() { + + var hw = that.widgets.get_widget('hostname'); + var dw = that.widgets.get_widget('dnszone'); + + var hostname = hw.save()[0]; + var dnszone = dw.save()[0]; + + var fqdn = hostname && dnszone ? [ hostname+'.'+dnszone ] : []; + return fqdn; + + }; + return that; }; @@ -400,18 +413,6 @@ IPA.host_fqdn_field = function(spec) { } }; - that.save = function(record) { - - if(!record) record = {}; - - var hostname = that.hostname_widget.save()[0]; - var dnszone = that.dns_zone_widget.save()[0]; - - record.fqdn = hostname && dnszone ? [ hostname+'.'+dnszone ] : []; - - return record.fqdn; - }; - that.reset = function() { that.hostname_widget.update([]); diff --git a/install/ui/src/freeipa/ipa.js b/install/ui/src/freeipa/ipa.js index e6f10d8a2..1d58712de 100644 --- a/install/ui/src/freeipa/ipa.js +++ b/install/ui/src/freeipa/ipa.js @@ -27,11 +27,12 @@ define([ './jquery', './json2', './_base/i18n', + './datetime', './metadata', './builder', './reg', './text'], - function(keys, $, JSON, i18n, metadata_provider, builder, reg, text) { + function(keys, $, JSON, i18n, datetime, metadata_provider, builder, reg, text) { /** * @class @@ -573,7 +574,7 @@ IPA.update_password_expiration = function() { var now, expires, notify_days, diff, message, container; expires = IPA.whoami.krbpasswordexpiration; - expires = expires ? IPA.parse_utc_date(expires[0]) : null; + expires = expires ? datetime.parse(expires[0]) : null; notify_days = IPA.server_config.ipapwdexpadvnotify; notify_days = notify_days ? notify_days[0] : 0; @@ -621,40 +622,6 @@ IPA.password_selfservice = function() { }; /** - * Parse value as UTC date - * @member IPA - * @return Data - */ -IPA.parse_utc_date = function(value) { - - if (!value) return null; - - // verify length - if (value.length != 'YYYYmmddHHMMSSZ'.length) { - return null; - } - - // We only handle GMT - if (value.charAt(value.length -1) !== 'Z') { - return null; - } - - var date = new Date(); - - date.setUTCFullYear( - value.substring(0, 4), // YYYY - value.substring(4, 6)-1, // mm (0-11) - value.substring(6, 8)); // dd (1-31) - - date.setUTCHours( - value.substring(8, 10), // HH (0-23) - value.substring(10, 12), // MM (0-59) - value.substring(12, 14)); // SS (0-59) - - return date; -}; - -/** * Call an IPA command over JSON-RPC. * * @class IPA.command diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js index e0d6cd435..6c5fbac4d 100644 --- a/install/ui/src/freeipa/user.js +++ b/install/ui/src/freeipa/user.js @@ -135,7 +135,7 @@ return { name: 'krbpasswordexpiration', label: '@i18n:objects.user.krbpasswordexpiration', read_only: true, - formatter: 'utc_date' + formatter: 'datetime' }, 'uidnumber', 'gidnumber', diff --git a/install/ui/src/freeipa/widget.js b/install/ui/src/freeipa/widget.js index b642cee02..6ee61c658 100644 --- a/install/ui/src/freeipa/widget.js +++ b/install/ui/src/freeipa/widget.js @@ -29,13 +29,15 @@ define(['dojo/_base/array', 'dojo/keys', 'dojo/on', './builder', + './datetime', './ipa', './jquery', './phases', './reg', './text' ], - function(array, lang, Evented, has, keys, on, builder, IPA, $, phases, reg, text) { + function(array, lang, Evented, has, keys, on, builder, datetime, IPA, $, + phases, reg, text) { /** * Widget module @@ -1934,24 +1936,25 @@ IPA.boolean_status_formatter = function(spec) { }; /** - * Take an LDAP format date in UTC and format it + * Take supported ISO 8601 or LDAP format date and format it * @class * @extends IPA.formatter */ -IPA.utc_date_formatter = function(spec) { +IPA.datetime_formatter = function(spec) { spec = spec || {}; var that = IPA.formatter(spec); + that.template = spec.template; that.format = function(value) { if (!value) return ''; - var date = IPA.parse_utc_date(value); + var date = datetime.parse(value); if (!date) return value; - return date.toString(); + var str = datetime.format(date, that.template); + return str; }; - return that; }; @@ -5155,6 +5158,7 @@ exp.register = function() { w.register('details_section', IPA.details_section); w.register('details_table_section', IPA.details_table_section); w.register('details_table_section_nc', IPA.details_section); + w.register('datetime', IPA.text_widget); w.register('multiple_choice_section', IPA.multiple_choice_section); w.register('enable', IPA.enable_widget); w.register('entity_select', IPA.entity_select_widget); @@ -5172,7 +5176,7 @@ exp.register = function() { f.register('boolean', IPA.boolean_formatter); f.register('boolean_status', IPA.boolean_status_formatter); - f.register('utc_date', IPA.utc_date_formatter); + f.register('datetime', IPA.datetime_formatter); }; phases.on('registration', exp.register); diff --git a/install/ui/src/webui.profile.js b/install/ui/src/webui.profile.js index 93585e39a..4176ed826 100644 --- a/install/ui/src/webui.profile.js +++ b/install/ui/src/webui.profile.js @@ -106,6 +106,7 @@ var profile = (function(){ 'dojo/when', 'dojo/domReady!', //added with '!' as a loader plugin "dojo/query", + "dojo/string", "dojo/NodeList-dom", "dojo/promise/all" ] |