summaryrefslogtreecommitdiffstats
path: root/install/ui/src
diff options
context:
space:
mode:
Diffstat (limited to 'install/ui/src')
-rw-r--r--install/ui/src/dojo.profile.js1
-rw-r--r--install/ui/src/freeipa/datetime.js217
-rw-r--r--install/ui/src/freeipa/field.js116
-rw-r--r--install/ui/src/freeipa/host.js25
-rw-r--r--install/ui/src/freeipa/ipa.js39
-rw-r--r--install/ui/src/freeipa/user.js2
-rw-r--r--install/ui/src/freeipa/widget.js18
-rw-r--r--install/ui/src/webui.profile.js1
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"
]