diff options
| author | Michael Mattiello (mcm) <mcm@odoo.com> | 2020-08-03 12:17:25 +0000 |
|---|---|---|
| committer | Michael Mattiello (mcm) <mcm@odoo.com> | 2020-08-11 14:15:43 +0000 |
| commit | a5cca2cda3b5dc9468961fe7bebeb1257d67ecdd (patch) | |
| tree | 1d2aa2b4c2ffeff4c6981f9abcb725a337ab0550 /addons/web/static | |
| parent | 6184070923b618a6923822a2b2c37c7d9835825f (diff) | |
[IMP] web: add smart date input on date field
This commit adds smart date inputs for date and datetime fields.
The goal of smart date input is to provide the user some shortcuts
when setting dates.
The rule is [+-]\d+[dwmy]?
So we can enter inputs like:
+3 to have today + 3 days
-2w to have today - 2 weeks
+1y to have today + 1 year
+5m to have today + 5 months
-4d to have today - 4 days
closes odoo/odoo#55602
Task: 2270347
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Diffstat (limited to 'addons/web/static')
| -rw-r--r-- | addons/web/static/src/js/fields/basic_fields.js | 19 | ||||
| -rw-r--r-- | addons/web/static/src/js/fields/field_utils.js | 66 | ||||
| -rw-r--r-- | addons/web/static/tests/fields/basic_fields_tests.js | 30 | ||||
| -rw-r--r-- | addons/web/static/tests/fields/field_utils_tests.js | 18 |
4 files changed, 123 insertions, 10 deletions
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 8657e44c49b..252ef70894e 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -863,6 +863,25 @@ var FieldDate = InputField.extend({ this.datewidget.setValue(this.value); this.$input = this.datewidget.$input; }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * Confirm the value on hit enter and re-render + * + * @private + * @override + * @param {KeyboardEvent} ev + */ + async _onKeydown(ev) { + this._super(...arguments); + if (ev.which === $.ui.keyCode.ENTER) { + await this._setValue(this.$input.val()); + this._render(); + } + }, }); var FieldDateTime = FieldDate.extend({ diff --git a/addons/web/static/src/js/fields/field_utils.js b/addons/web/static/src/js/fields/field_utils.js index 8f8b9bbb2ab..4ffceb93408 100644 --- a/addons/web/static/src/js/fields/field_utils.js +++ b/addons/web/static/src/js/fields/field_utils.js @@ -414,6 +414,42 @@ function formatSelection(value, field, options) { //////////////////////////////////////////////////////////////////////////////// /** + * Smart date inputs are shortcuts to write dates quicker. + * These shortcuts should respect the format ^[+-]\d+[dmwy]?$ + * + * e.g. + * "+1d" or "+1" will return now + 1 day + * "-2w" will return now - 2 weeks + * "+3m" will return now + 3 months + * "-4y" will return now + 4 years + * + * @param {string} value + * @returns {Moment|false} Moment date object + */ +function parseSmartDateInput(value) { + const units = { + d: 'days', + m: 'months', + w: 'weeks', + y: 'years', + }; + const re = new RegExp(`^([+-])(\\d+)([${Object.keys(units).join('')}]?)$`); + const match = re.exec(value); + if (match) { + let date = moment(); + const offset = parseInt(match[2], 10); + const unit = units[match[3] || 'd']; + if (match[1] === '+') { + date.add(offset, unit); + } else { + date.subtract(offset, unit); + } + return date; + } + return false; +} + +/** * Create an Date object * The method toJSON return the formated value to send value server side * @@ -433,11 +469,16 @@ function parseDate(value, field, options) { var datePattern = time.getLangDateFormat(); var datePatternWoZero = datePattern.replace('MM', 'M').replace('DD', 'D'); var date; - if (options && options.isUTC) { - value = value.padStart(10, "0"); // server may send "932-10-10" for "0932-10-10" on some OS - date = moment.utc(value); + const smartDate = parseSmartDateInput(value); + if (smartDate) { + date = smartDate; } else { - date = moment.utc(value, [datePattern, datePatternWoZero, moment.ISO_8601]); + if (options && options.isUTC) { + value = value.padStart(10, "0"); // server may send "932-10-10" for "0932-10-10" on some OS + date = moment.utc(value); + } else { + date = moment.utc(value, [datePattern, datePatternWoZero, moment.ISO_8601]); + } } if (date.isValid()) { if (date.year() === 0) { @@ -475,13 +516,18 @@ function parseDateTime(value, field, options) { var pattern1 = datePattern + ' ' + timePattern; var pattern2 = datePatternWoZero + ' ' + timePatternWoZero; var datetime; - if (options && options.isUTC) { - // phatomjs crash if we don't use this format - datetime = moment.utc(value.replace(' ', 'T') + 'Z'); + const smartDate = parseSmartDateInput(value); + if (smartDate) { + datetime = smartDate; } else { - datetime = moment.utc(value, [pattern1, pattern2, moment.ISO_8601]); - if (options && options.timezone) { - datetime.add(-session.getTZOffset(datetime), 'minutes'); + if (options && options.isUTC) { + // phatomjs crash if we don't use this format + datetime = moment.utc(value.replace(' ', 'T') + 'Z'); + } else { + datetime = moment.utc(value, [pattern1, pattern2, moment.ISO_8601]); + if (options && options.timezone) { + datetime.add(-session.getTZOffset(datetime), 'minutes'); + } } } if (datetime.isValid()) { diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 504d69dff69..965a98e973b 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -3891,6 +3891,36 @@ QUnit.module('basic_fields', { form.destroy(); }); + QUnit.test('date field: hit enter should update value', async function (assert) { + assert.expect(2); + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch:'<form string="Partners"><field name="date"/></form>', + res_id: 1, + translateParameters: { // Avoid issues due to localization formats + date_format: '%m/%d/%Y', + }, + viewOptions: { + mode: 'edit', + }, + }); + + const year = (new Date()).getFullYear(); + + await testUtils.fields.editInput(form.el.querySelector('input[name="date"]'), '01/08'); + await testUtils.fields.triggerKeydown(form.el.querySelector('input[name="date"]'), 'enter'); + assert.strictEqual(form.el.querySelector('input[name="date"]').value, '01/08/' + year); + + await testUtils.fields.editInput(form.el.querySelector('input[name="date"]'), '08/01'); + await testUtils.fields.triggerKeydown(form.el.querySelector('input[name="date"]'), 'enter'); + assert.strictEqual(form.el.querySelector('input[name="date"]').value, '08/01/' + year); + + form.destroy(); + }); + QUnit.module('FieldDatetime'); QUnit.test('datetime field in form view', async function (assert) { diff --git a/addons/web/static/tests/fields/field_utils_tests.js b/addons/web/static/tests/fields/field_utils_tests.js index f3ab43260ae..567390e336d 100644 --- a/addons/web/static/tests/fields/field_utils_tests.js +++ b/addons/web/static/tests/fields/field_utils_tests.js @@ -413,4 +413,22 @@ QUnit.test('parse datetime without separator', function (assert) { core._t.database.parameters = originalParameters; }); }); + +QUnit.test('parse smart date input', function (assert) { + assert.expect(10); + + const format = "DD MM YYYY"; + assert.strictEqual(fieldUtils.parse.date("+1d").format(format), moment().add(1, 'days').format(format)); + assert.strictEqual(fieldUtils.parse.datetime("+2w").format(format), moment().add(2, 'weeks').format(format)); + assert.strictEqual(fieldUtils.parse.date("+3m").format(format), moment().add(3, 'months').format(format)); + assert.strictEqual(fieldUtils.parse.datetime("+4y").format(format), moment().add(4, 'years').format(format)); + + assert.strictEqual(fieldUtils.parse.date("+5").format(format), moment().add(5, 'days').format(format)); + assert.strictEqual(fieldUtils.parse.datetime("-5").format(format), moment().subtract(5, 'days').format(format)); + + assert.strictEqual(fieldUtils.parse.date("-4y").format(format), moment().subtract(4, 'years').format(format)); + assert.strictEqual(fieldUtils.parse.datetime("-3m").format(format), moment().subtract(3, 'months').format(format)); + assert.strictEqual(fieldUtils.parse.date("-2w").format(format), moment().subtract(2, 'weeks').format(format)); + assert.strictEqual(fieldUtils.parse.datetime("-1d").format(format), moment().subtract(1, 'days').format(format)); +}); }); |
