diff --git a/app/components/create-options-datetime.js b/app/components/create-options-datetime.js index e1d5c5325..772d88d24 100644 --- a/app/components/create-options-datetime.js +++ b/app/components/create-options-datetime.js @@ -2,7 +2,7 @@ import { inject as service } from '@ember/service'; import { readOnly, mapBy, filter } from '@ember/object/computed'; import Component from '@ember/component'; import { isPresent, isEmpty } from '@ember/utils'; -import { observer, get } from '@ember/object'; +import { action, observer, get } from '@ember/object'; import { validator, buildValidations } @@ -128,7 +128,7 @@ export default Component.extend(modelValidations, { } else { this.set('shouldShowErrors', true); } - } + }, }, // dates are sorted datesForFirstDay: readOnly('groupedDates.firstObject.items'), @@ -148,4 +148,20 @@ export default Component.extend(modelValidations, { groupedDates: groupBy('dates', raw('day')), store: service(), + + inputChanged: action(function(date, value) { + // reset partially filled state + date.set('isPartiallyFilled', false); + + date.set('time', value); + }), + + validateInput: action(function(date, event) { + let element = event.target; + + if (!element.checkValidity()) { + // partially filled time input + date.set('isPartiallyFilled', true); + } + }), }); diff --git a/app/locales/ca/translations.js b/app/locales/ca/translations.js index 57fccd430..3b5ef1863 100644 --- a/app/locales/ca/translations.js +++ b/app/locales/ca/translations.js @@ -148,6 +148,7 @@ export default { phone: '{{description}} ha de ser un número de telèfon vàlid', url: '{{description}} ha de ser un URL vàlid ', time: '{{description}} ha de ser un orari vàlid (p. ex. 10:45)', + 'time.notPartially': 'Partially times are not supported', unique: '{{description}} ha de ser explícita', 'unique.name': 'Aquest nom ja s\'ha usat' } diff --git a/app/locales/de/translations.js b/app/locales/de/translations.js index 15743c2f3..9043a532b 100644 --- a/app/locales/de/translations.js +++ b/app/locales/de/translations.js @@ -148,6 +148,7 @@ export default { phone: '{{description}} muss eine gültige Telefonnummer sein', url: '{{description}} muss eine gültige URL sein', time: '{{description}} muss eine gültige Zeit sein (z.B. 10:45)', + 'time.notPartially': 'Zeiten müssen vollständig sein', unique: '{{description}} müssen eindeutig sein', 'unique.name': 'Dieser Name wurde bereits genutzt' } diff --git a/app/locales/en/translations.js b/app/locales/en/translations.js index cb2600b8d..ca26cd01a 100644 --- a/app/locales/en/translations.js +++ b/app/locales/en/translations.js @@ -148,6 +148,7 @@ export default { phone: '{{description}} must be a valid phone number', url: '{{description}} must be a valid URL ', time: '{{description}} must be a valid time (e.g. 10:45)', + 'time.notPartially': 'Partially times are not supported', unique: '{{description}} must be explicit', 'unique.name': 'This name has already been used' } diff --git a/app/locales/es/translations.js b/app/locales/es/translations.js index 188328a84..034702a29 100644 --- a/app/locales/es/translations.js +++ b/app/locales/es/translations.js @@ -148,6 +148,7 @@ export default { phone: '{{description}} debe de ser un número de teléfono valido', url: '{{description}} debe de ser una URL valida', time: '{{description}} debe de ser un horario valido (p.ej. 10:45)', + 'time.notPartially': 'Partially times are not supported', unique: '{{description}} debe de ser único', 'unique.name': 'Este nombre ya está usado' } diff --git a/app/locales/it/translations.js b/app/locales/it/translations.js index 29f924bc0..ccf322d82 100644 --- a/app/locales/it/translations.js +++ b/app/locales/it/translations.js @@ -148,6 +148,7 @@ export default { phone: '{{description}} deve essere un numero di telefono valido.', url: '{{description}} deve essere un URL valido ', time: '{{description}} deve essere un orario valido (ad es. 10:45)', + 'time.notPartially': 'Partially times are not supported', unique: '{{description}} deve essere esplicito', 'unique.name': 'Questo nome è già stato usato' } diff --git a/app/models/option.js b/app/models/option.js index cc4fe91bf..169fee931 100644 --- a/app/models/option.js +++ b/app/models/option.js @@ -15,6 +15,10 @@ from 'ember-cp-validations'; const { attr } = DS; const Validations = buildValidations({ + isPartiallyFilled: validator('falsy', { + messageKey: 'errors.time.notPartially', + dependentKeys: ['model.i18n.locale'], + }), title: [ validator('iso8601', { active: readOnly('model.poll.isFindADate'), @@ -48,7 +52,11 @@ const Validations = buildValidations({ validator('alias', { alias: 'title', firstMessageOnly: true - }) + }), + // alias is partially filled validation as that's part of time validation + validator('alias', { + alias: 'isPartiallyFilled', + }), ] }); @@ -114,6 +122,12 @@ export default Fragment.extend(Validations, { this.title.length === 'YYYY-MM-DDTHH:mm:ss.SSSZ'.length; }), + // isPartiallyFilled should be set only for times on creation if input is filled + // partially (e.g. "11:--"). It's required cause ember-cp-validations does not + // provide any method to push a validation error into validations. It's only + // working based on a property of the model. + isPartiallyFilled: false, + time: computed('date', { get() { const date = this.date; @@ -130,7 +144,7 @@ export default Fragment.extend(Validations, { return date.format('HH:mm'); }, set(key, value) { - const date = this.date; + let date = this.date; assert( 'can not set a time if current value is not a valid date', moment.isMoment(date) diff --git a/app/templates/components/create-options-datetime.hbs b/app/templates/components/create-options-datetime.hbs index 2c1b7f28c..615a3a805 100644 --- a/app/templates/components/create-options-datetime.hbs +++ b/app/templates/components/create-options-datetime.hbs @@ -43,10 +43,13 @@
diff --git a/app/validators/falsy.js b/app/validators/falsy.js new file mode 100644 index 000000000..f25946fd7 --- /dev/null +++ b/app/validators/falsy.js @@ -0,0 +1,9 @@ +import BaseValidator from 'ember-cp-validations/validators/base'; + +const Truthy = BaseValidator.extend({ + validate(value, options) { + return value ? this.createErrorMessage('iso8601', value, options) : true; + } +}); + +export default Truthy; diff --git a/tests/integration/components/create-options-datetime-test.js b/tests/integration/components/create-options-datetime-test.js index c10979668..35aa6a9bd 100644 --- a/tests/integration/components/create-options-datetime-test.js +++ b/tests/integration/components/create-options-datetime-test.js @@ -27,7 +27,7 @@ module('Integration | Component | create options datetime', function(hooks) { * that ones could be identifed by class 'ws-inputreplace' */ - test('it generates inpute field for options iso 8601 date string (without time)', async function(assert) { + test('it generates input field for options iso 8601 date string (without time)', async function(assert) { // validation is based on validation of every option fragment // which validates according to poll model it belongs to // therefore each option needs to be pushed to poll model to have it as @@ -55,7 +55,7 @@ module('Integration | Component | create options datetime', function(hooks) { ); }); - test('it generates inpute field for options iso 8601 datetime string (with time)', async function(assert) { + test('it generates input field for options iso 8601 datetime string (with time)', async function(assert) { // validation is based on validation of every option fragment // which validates according to poll model it belongs to // therefore each option needs to be pushed to poll model to have it as diff --git a/tests/unit/validators/falsy-test.js b/tests/unit/validators/falsy-test.js new file mode 100644 index 000000000..418eea263 --- /dev/null +++ b/tests/unit/validators/falsy-test.js @@ -0,0 +1,16 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Validator | falsy', function(hooks) { + setupTest(hooks); + + test('`false` passes validation', function(assert) { + let validator = this.owner.lookup('validator:falsy'); + assert.ok(validator.validate(false) === true); + }); + + test('`true` fails validation', function(assert) { + let validator = this.owner.lookup('validator:falsy'); + assert.ok(typeof validator.validate(true) === 'string'); + }); +});