Use native browser APIs and Luxon instead of Moment (#612)
This commit is contained in:
parent
9f47286899
commit
2a4b1f8b73
48 changed files with 1514 additions and 817 deletions
|
@ -4,7 +4,7 @@ import { inject as service } from '@ember/service';
|
|||
import Component from '@ember/component';
|
||||
import { isArray } from '@ember/array';
|
||||
import { isPresent } from '@ember/utils';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from "luxon";
|
||||
|
||||
@classic
|
||||
export default class CreateOptionsDates extends Component {
|
||||
|
@ -16,56 +16,60 @@ export default class CreateOptionsDates extends Component {
|
|||
return this.options
|
||||
// should be unique
|
||||
.uniqBy('day')
|
||||
// raw dates
|
||||
.map(({ date }) => date)
|
||||
// filter out invalid
|
||||
.filter(moment.isMoment)
|
||||
.filter(({ isDate }) => isDate)
|
||||
// raw dates
|
||||
.map(({ datetime }) => datetime)
|
||||
.toArray();
|
||||
}
|
||||
|
||||
@computed('calendarCenter')
|
||||
get calendarCenterNext() {
|
||||
return moment(this.calendarCenter).add(1, 'months');
|
||||
return this.calendarCenter.plus({ months: 1 });
|
||||
}
|
||||
|
||||
@action
|
||||
daysSelected({ moment: newMoments }) {
|
||||
daysSelected({ datetime: newDatesAsLuxonDateTime }) {
|
||||
let { options } = this;
|
||||
|
||||
if (!isArray(newMoments)) {
|
||||
if (!isArray(newDatesAsLuxonDateTime)) {
|
||||
// special case: all options are unselected
|
||||
options.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// array of options that represent days missing in updated selection
|
||||
let removedOptions = options.filter((option) => {
|
||||
return !newMoments.find((newMoment) => newMoment.format('YYYY-MM-DD') === option.day);
|
||||
const newDates = newDatesAsLuxonDateTime.map((dateAsLuxonDateTime) => {
|
||||
return dateAsLuxonDateTime.toISODate();
|
||||
});
|
||||
|
||||
// array of moments that aren't represented yet by an option
|
||||
let addedMoments = newMoments.filter((moment) => {
|
||||
return !options.find((option) => moment.format('YYYY-MM-DD') === option.day);
|
||||
// array of options that represent days missing in updated selection
|
||||
let removedOptions = options.filter((option) => {
|
||||
return !newDates.find((newDate) => newDate === option.day);
|
||||
});
|
||||
|
||||
// array of dates that aren't represented yet by an option
|
||||
let addedDates = newDates.filter((newDate) => {
|
||||
return !options.find((option) => newDate === option.day);
|
||||
});
|
||||
|
||||
// remove options that represent deselected days
|
||||
options.removeObjects(removedOptions);
|
||||
|
||||
// add options for newly selected days
|
||||
let newOptions = addedMoments.map((moment) => {
|
||||
let newOptions = addedDates.map((newDate) => {
|
||||
return this.store.createFragment('option', {
|
||||
title: moment.format('YYYY-MM-DD'),
|
||||
title: newDate,
|
||||
})
|
||||
});
|
||||
newOptions.forEach((newOption) => {
|
||||
// options must be insert into options array at correct position
|
||||
let insertBefore = options.find(({ date }) => {
|
||||
if (!moment.isMoment(date)) {
|
||||
let insertBefore = options.find((option) => {
|
||||
if (!option.isDate) {
|
||||
// ignore options that do not represent a valid date
|
||||
return false;
|
||||
}
|
||||
|
||||
return date.isAfter(newOption.date);
|
||||
return option.title > newOption.title;
|
||||
});
|
||||
let position = isPresent(insertBefore) ? options.indexOf(insertBefore) : options.length;
|
||||
options.insertAt(position, newOption);
|
||||
|
@ -82,6 +86,6 @@ export default class CreateOptionsDates extends Component {
|
|||
super.init(arguments);
|
||||
|
||||
let { selectedDays } = this;
|
||||
this.set('calendarCenter', selectedDays.length >= 1 ? selectedDays[0] : moment());
|
||||
this.set('calendarCenter', selectedDays.length >= 1 ? selectedDays[0] : DateTime.local());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ export default class CreateOptionsDatetime extends Component.extend(modelValidat
|
|||
items.slice(1)
|
||||
);
|
||||
// set title as date without time
|
||||
remainingOption.set('title', remainingOption.get('date').format('YYYY-MM-DD'));
|
||||
remainingOption.set('title', remainingOption.day);
|
||||
} else {
|
||||
// adopt times of first day
|
||||
if (timesForFirstDay.get('length') < items.length) {
|
||||
|
@ -102,9 +102,9 @@ export default class CreateOptionsDatetime extends Component.extend(modelValidat
|
|||
timesForFirstDay.forEach((timeOfFirstDate, index) => {
|
||||
const target = items[index];
|
||||
if (target === undefined) {
|
||||
const basisDate = get(items[0], 'date').clone();
|
||||
let [hour, minute] = timeOfFirstDate.split(':');
|
||||
let dateString = basisDate.hour(hour).minute(minute).toISOString();
|
||||
const basisDate = get(items[0], 'datetime');
|
||||
let [hours, minutes] = timeOfFirstDate.split(':');
|
||||
let dateString = basisDate.set({ hours, minutes }).toISO();
|
||||
let fragment = this.store.createFragment('option', {
|
||||
title: dateString
|
||||
});
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import classic from 'ember-classic-decorator';
|
||||
import { classNames, tagName } from '@ember-decorators/component';
|
||||
import { computed } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { readOnly } from '@ember/object/computed';
|
||||
import Component from '@ember/component';
|
||||
import localesMeta from 'croodle/locales/meta';
|
||||
|
||||
|
@ -13,33 +11,21 @@ export default class LanguageSelect extends Component {
|
|||
@service
|
||||
intl;
|
||||
|
||||
@service
|
||||
moment;
|
||||
|
||||
@service
|
||||
powerCalendar;
|
||||
|
||||
@readOnly('intl.primaryLocale')
|
||||
current;
|
||||
|
||||
@computed('intl.locales')
|
||||
get locales() {
|
||||
let currentLocale = this.intl.primaryLocale;
|
||||
|
||||
return Object.keys(localesMeta).map(function(locale) {
|
||||
return {
|
||||
id: locale,
|
||||
selected: locale === currentLocale,
|
||||
text: localesMeta[locale]
|
||||
};
|
||||
});
|
||||
get currentLocale() {
|
||||
return this.intl.primaryLocale;
|
||||
}
|
||||
|
||||
change() {
|
||||
let locale = this.element.options[this.element.selectedIndex].value;
|
||||
get locales() {
|
||||
return localesMeta;
|
||||
}
|
||||
|
||||
change(event) {
|
||||
const locale = event.target.value;
|
||||
|
||||
this.intl.set('locale', locale.includes('-') ? [locale, locale.split('-')[0]] : [locale]);
|
||||
this.moment.changeLocale(locale);
|
||||
this.powerCalendar.set('locale', locale);
|
||||
|
||||
if (window.localStorage) {
|
||||
|
|
|
@ -2,7 +2,7 @@ import classic from 'ember-classic-decorator';
|
|||
import { classNames } from '@ember-decorators/component';
|
||||
import { computed } from '@ember/object';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { readOnly, max, mapBy, gt } from '@ember/object/computed';
|
||||
import { readOnly, gt } from '@ember/object/computed';
|
||||
import Component from '@ember/component';
|
||||
import { copy } from '@ember/object/internals';
|
||||
import { isEmpty } from '@ember/utils';
|
||||
|
@ -13,7 +13,7 @@ export default class PollEvaluationSummary extends Component {
|
|||
@service
|
||||
intl;
|
||||
|
||||
@computed('users.[]')
|
||||
@computed('poll.{answers,isFreeText,options}', 'users.[]')
|
||||
get bestOptions() {
|
||||
// can not evaluate answer type free text
|
||||
if (this.get('poll.isFreeText')) {
|
||||
|
@ -82,11 +82,17 @@ export default class PollEvaluationSummary extends Component {
|
|||
@gt('bestOptions.length', 1)
|
||||
multipleBestOptions;
|
||||
|
||||
@max('participationDates')
|
||||
lastParticipationAt;
|
||||
get lastParticipationAt() {
|
||||
let lastParticipationAt = null;
|
||||
|
||||
@mapBy('users', 'creationDate')
|
||||
participationDates;
|
||||
for (const { creationDate } of this.users.toArray()) {
|
||||
if (creationDate >= lastParticipationAt) {
|
||||
lastParticipationAt = creationDate;
|
||||
}
|
||||
}
|
||||
|
||||
return lastParticipationAt;
|
||||
}
|
||||
|
||||
@readOnly('users.length')
|
||||
participantsCount;
|
||||
|
|
|
@ -2,7 +2,6 @@ import classic from 'ember-classic-decorator';
|
|||
import { action } from '@ember/object';
|
||||
import { alias } from '@ember/object/computed';
|
||||
import Controller from '@ember/controller';
|
||||
import moment from 'moment';
|
||||
|
||||
@classic
|
||||
export default class CreateOptionsDatetimeController extends Controller {
|
||||
|
@ -24,10 +23,10 @@ export default class CreateOptionsDatetimeController extends Controller {
|
|||
// remove all days from options which haven't a time but there is atleast
|
||||
// one option with time for that day
|
||||
const daysWithTime = options.map((option) => {
|
||||
if (moment(option.get('title'), 'YYYY-MM-DD', true).isValid()) {
|
||||
if (!option.hasTime) {
|
||||
return null;
|
||||
} else {
|
||||
return moment(option.get('title')).format('YYYY-MM-DD');
|
||||
return option.day;
|
||||
}
|
||||
}).uniq().filter((option) => option !== null);
|
||||
const removeObjects = options.filter((option) => {
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
validator, buildValidations
|
||||
}
|
||||
from 'ember-cp-validations';
|
||||
import moment from 'moment';
|
||||
import { DateTime, Duration } from 'luxon';
|
||||
|
||||
const Validations = buildValidations({
|
||||
anonymousUser: validator('presence', {
|
||||
|
@ -58,9 +58,8 @@ export default class CreateSettings extends Controller.extend(Validations) {
|
|||
set expirationDuration(value) {
|
||||
this.set(
|
||||
'model.expirationDate',
|
||||
isPresent(value) ? moment().add(moment.duration(value)).toISOString(): ''
|
||||
isPresent(value) ? DateTime.local().plus(Duration.fromISO(value)).toISO() : ''
|
||||
);
|
||||
return value;
|
||||
}
|
||||
|
||||
@computed
|
||||
|
@ -100,11 +99,11 @@ export default class CreateSettings extends Controller.extend(Validations) {
|
|||
// set timezone if there is atleast one option with time
|
||||
if (
|
||||
poll.isFindADate &&
|
||||
poll.options.any(({ title }) => {
|
||||
return !moment(title, 'YYYY-MM-DD', true).isValid();
|
||||
poll.options.any((option) => {
|
||||
return option.hasTime;
|
||||
})
|
||||
) {
|
||||
this.set('model.timezone', moment.tz.guess());
|
||||
this.set('model.timezone', Intl.DateTimeFormat().resolvedOptions().timeZone);
|
||||
}
|
||||
|
||||
// save poll
|
||||
|
|
|
@ -4,7 +4,7 @@ import Controller from '@ember/controller';
|
|||
import { isPresent, isEmpty } from '@ember/utils';
|
||||
import { action, computed } from '@ember/object';
|
||||
import { observes } from '@ember-decorators/object';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
export default class PollController extends Controller {
|
||||
@service
|
||||
|
@ -28,16 +28,6 @@ export default class PollController extends Controller {
|
|||
@readOnly('intl.primaryLocale')
|
||||
currentLocale;
|
||||
|
||||
@computed('currentLocale')
|
||||
get momentLongDayFormat() {
|
||||
let currentLocale = this.currentLocale;
|
||||
return moment.localeData(currentLocale)
|
||||
.longDateFormat('LLLL')
|
||||
.replace(
|
||||
moment.localeData(currentLocale).longDateFormat('LT'), '')
|
||||
.trim();
|
||||
}
|
||||
|
||||
@readOnly('model')
|
||||
poll;
|
||||
|
||||
|
@ -52,7 +42,7 @@ export default class PollController extends Controller {
|
|||
if (isEmpty(expirationDate)) {
|
||||
return false;
|
||||
}
|
||||
return moment().add(2, 'weeks').isAfter(moment(expirationDate));
|
||||
return DateTime.local().plus({ weeks: 2 }) >= DateTime.fromISO(expirationDate);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -61,7 +51,7 @@ export default class PollController extends Controller {
|
|||
@computed('poll.timezone')
|
||||
get timezoneDiffers() {
|
||||
let modelTimezone = this.poll.timezone;
|
||||
return isPresent(modelTimezone) && moment.tz.guess() !== modelTimezone;
|
||||
return isPresent(modelTimezone) && Intl.DateTimeFormat().resolvedOptions().timeZone !== modelTimezone;
|
||||
}
|
||||
|
||||
@computed('timezoneDiffers', 'timezoneChoosen')
|
||||
|
@ -69,7 +59,7 @@ export default class PollController extends Controller {
|
|||
return this.timezoneDiffers && !this.timezoneChoosen;
|
||||
}
|
||||
|
||||
@computed('useLocalTimezone')
|
||||
@computed('poll.timezone', 'useLocalTimezone')
|
||||
get timezone() {
|
||||
return this.useLocalTimezone ? undefined : this.poll.timezone;
|
||||
}
|
||||
|
|
|
@ -15,9 +15,6 @@ export default class PollEvaluationController extends Controller {
|
|||
@service
|
||||
intl;
|
||||
|
||||
@readOnly('pollController.momentLongDayFormat')
|
||||
momentLongDayFormat;
|
||||
|
||||
@readOnly('model')
|
||||
poll;
|
||||
|
||||
|
@ -34,7 +31,7 @@ export default class PollEvaluationController extends Controller {
|
|||
* evaluates poll data
|
||||
* if free text answers are allowed evaluation is disabled
|
||||
*/
|
||||
@computed('users.[]')
|
||||
@computed('isEvaluable', 'poll.{answers,forceAnswer,options,users}', 'users.[]')
|
||||
get evaluation() {
|
||||
if (!this.isEvaluable) {
|
||||
return [];
|
||||
|
|
|
@ -3,13 +3,12 @@ import { inject as service } from '@ember/service';
|
|||
import { not, readOnly } from '@ember/object/computed';
|
||||
import Controller, { inject as controller } from '@ember/controller';
|
||||
import { getOwner } from '@ember/application';
|
||||
import { isPresent, isEmpty } from '@ember/utils';
|
||||
import { isEmpty } from '@ember/utils';
|
||||
import EmberObject, { computed } from '@ember/object';
|
||||
import {
|
||||
validator, buildValidations
|
||||
}
|
||||
from 'ember-cp-validations';
|
||||
import moment from 'moment';
|
||||
import config from 'croodle/config/environment';
|
||||
|
||||
const validCollection = function(collection) {
|
||||
|
@ -156,8 +155,6 @@ export default Controller.extend(Validations, {
|
|||
isFreeText: readOnly('poll.isFreeText'),
|
||||
isFindADate: readOnly('poll.isFindADate'),
|
||||
|
||||
momentLongDayFormat: readOnly('pollController.momentLongDayFormat'),
|
||||
|
||||
name: '',
|
||||
|
||||
options: readOnly('poll.options'),
|
||||
|
@ -165,7 +162,7 @@ export default Controller.extend(Validations, {
|
|||
poll: readOnly('model'),
|
||||
pollController: controller('poll'),
|
||||
|
||||
possibleAnswers: computed('poll.answers', function() {
|
||||
possibleAnswers: computed('labelTranslation', 'poll.answers', function() {
|
||||
return this.get('poll.answers').map((answer) => {
|
||||
const owner = getOwner(this);
|
||||
|
||||
|
@ -177,7 +174,7 @@ export default Controller.extend(Validations, {
|
|||
if (!isEmpty(answer.get('labelTranslation'))) {
|
||||
return AnswerObject.extend({
|
||||
intl: service(),
|
||||
label: computed('intl.locale', function() {
|
||||
label: computed('intl.locale', 'labelTranslation', function() {
|
||||
return this.intl.t(this.labelTranslation);
|
||||
}),
|
||||
labelTranslation: answer.get('labelTranslation'),
|
||||
|
@ -192,41 +189,28 @@ export default Controller.extend(Validations, {
|
|||
|
||||
savingFailed: false,
|
||||
|
||||
selections: computed('options', 'pollController.dates', function() {
|
||||
selections: computed('forceAnswer', 'isFindADate', 'isFreeText', 'options', 'pollController.dates', 'timezone', function() {
|
||||
let options = this.options;
|
||||
let isFindADate = this.isFindADate;
|
||||
let lastDate;
|
||||
let lastOption;
|
||||
|
||||
return options.map((option) => {
|
||||
let labelValue;
|
||||
let momentFormat;
|
||||
let value = option.get('title');
|
||||
const labelString = option.title;
|
||||
const labelValue = option.isDate ? option.jsDate : option.title;
|
||||
const showDate = isFindADate && (!lastOption || option.get('day') !== lastOption.get('day'));
|
||||
const showTime = isFindADate && option.get('hasTime');
|
||||
|
||||
// format label
|
||||
if (isFindADate) {
|
||||
let hasTime = value.length > 10; // 'YYYY-MM-DD'.length === 10
|
||||
let timezone = this.timezone;
|
||||
let date = isPresent(timezone) ? moment.tz(value, timezone) : moment(value);
|
||||
if (hasTime && lastDate && date.format('YYYY-MM-DD') === lastDate.format('YYYY-MM-DD')) {
|
||||
labelValue = value;
|
||||
// do not repeat dates for different times
|
||||
momentFormat = 'LT';
|
||||
} else {
|
||||
labelValue = value;
|
||||
momentFormat = hasTime ? 'LLLL' : 'day';
|
||||
lastDate = date;
|
||||
}
|
||||
} else {
|
||||
labelValue = value;
|
||||
}
|
||||
lastOption = option;
|
||||
|
||||
// https://github.com/offirgolan/ember-cp-validations#basic-usage---objects
|
||||
// To lookup validators, container access is required which can cause an issue with Object creation
|
||||
// if the object is statically imported. The current fix for this is as follows.
|
||||
let owner = getOwner(this);
|
||||
return SelectionObject.create(owner.ownerInjection(), {
|
||||
labelString,
|
||||
labelValue,
|
||||
momentFormat,
|
||||
showDate,
|
||||
showTime,
|
||||
|
||||
// forceAnswer and isFreeText must be included in model
|
||||
// cause otherwise validations can't depend on it
|
||||
|
|
19
app/helpers/format-date-relative.js
Normal file
19
app/helpers/format-date-relative.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
import Helper from '@ember/component/helper';
|
||||
import { DateTime } from 'luxon';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
|
||||
export default class FormatDateRelativeHelper extends Helper {
|
||||
@service intl;
|
||||
|
||||
compute([date]) {
|
||||
if (date instanceof Date) {
|
||||
date = date.toISOString();
|
||||
}
|
||||
|
||||
return DateTime.fromISO(date).toRelative({
|
||||
locale: this.intl.primaryLocale,
|
||||
padding: 1000,
|
||||
});
|
||||
}
|
||||
}
|
|
@ -5,14 +5,12 @@ export default {
|
|||
name: 'i18n',
|
||||
initialize(appInstance) {
|
||||
let intl = appInstance.lookup('service:intl');
|
||||
let moment = appInstance.lookup('service:moment');
|
||||
let powerCalendar = appInstance.lookup('service:power-calendar');
|
||||
|
||||
let availableLocales = Object.keys(localesMeta);
|
||||
let locale = getLocale(availableLocales);
|
||||
|
||||
intl.set('locale', locale.includes('-') ? [locale, locale.split('-')[0]] : [locale]);
|
||||
moment.changeLocale(locale);
|
||||
powerCalendar.set('local', locale);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,7 +5,7 @@ import { readOnly } from '@ember/object/computed';
|
|||
import { attr } from '@ember-data/model';
|
||||
import { assert } from '@ember/debug';
|
||||
import { isEmpty } from '@ember/utils';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
import Fragment from 'ember-data-model-fragments/fragment';
|
||||
import { fragmentOwner } from 'ember-data-model-fragments/attributes';
|
||||
import {
|
||||
|
@ -20,12 +20,6 @@ const Validations = buildValidations({
|
|||
title: [
|
||||
validator('iso8601', {
|
||||
active: readOnly('model.poll.isFindADate'),
|
||||
validFormats: [
|
||||
'YYYY-MM-DD',
|
||||
'YYYY-MM-DDTHH:mmZ',
|
||||
'YYYY-MM-DDTHH:mm:ssZ',
|
||||
'YYYY-MM-DDTHH:mm:ss.SSSZ'
|
||||
],
|
||||
}),
|
||||
validator('presence', {
|
||||
presence: true,
|
||||
|
@ -73,103 +67,62 @@ export default class Option extends Fragment.extend(Validations) {
|
|||
// working based on a property of the model.
|
||||
isPartiallyFilled = false;
|
||||
|
||||
@computed('title')
|
||||
get date() {
|
||||
const allowedFormats = [
|
||||
'YYYY-MM-DD',
|
||||
'YYYY-MM-DDTHH:mm:ss.SSSZ'
|
||||
];
|
||||
const value = this.title;
|
||||
if (isEmpty(value)) {
|
||||
get datetime() {
|
||||
const { title } = this;
|
||||
|
||||
if (isEmpty(title)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const format = allowedFormats.find((f) => {
|
||||
// if format length does not match value length
|
||||
// string can't be in this format
|
||||
return f.length === value.length && moment(value, f, true).isValid();
|
||||
});
|
||||
if (isEmpty(format)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return moment(value, format, true);
|
||||
return DateTime.fromISO(title);
|
||||
}
|
||||
|
||||
get isDate() {
|
||||
const { datetime } = this;
|
||||
return datetime !== null && datetime.isValid;
|
||||
}
|
||||
|
||||
@computed('date')
|
||||
get day() {
|
||||
const date = this.date;
|
||||
if (!moment.isMoment(date)) {
|
||||
return null;
|
||||
}
|
||||
return date.format('YYYY-MM-DD');
|
||||
}
|
||||
|
||||
@computed('date', 'intl.primaryLocale')
|
||||
get dayFormatted() {
|
||||
let date = this.date;
|
||||
if (!moment.isMoment(date)) {
|
||||
if (!this.isDate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const locale = this.get('intl.primaryLocale');
|
||||
const format = moment.localeData(locale)
|
||||
.longDateFormat('LLLL')
|
||||
.replace(
|
||||
moment.localeData(locale).longDateFormat('LT'), '')
|
||||
.trim();
|
||||
|
||||
// momentjs object caches the locale on creation
|
||||
if (date.locale() !== locale) {
|
||||
// we clone the date to allow adjusting timezone without changing the object
|
||||
date = date.clone();
|
||||
date.locale(locale);
|
||||
}
|
||||
|
||||
return date.format(format);
|
||||
return this.datetime.toISODate();
|
||||
}
|
||||
|
||||
get jsDate() {
|
||||
return this.datetime.toJSDate();
|
||||
}
|
||||
|
||||
@computed('title')
|
||||
get hasTime() {
|
||||
return moment.isMoment(this.date) &&
|
||||
this.title.length === 'YYYY-MM-DDTHH:mm:ss.SSSZ'.length;
|
||||
return this.isDate &&
|
||||
this.title.length >= 'YYYY-MM-DDTHH:mm'.length;
|
||||
}
|
||||
|
||||
@computed('date')
|
||||
get time() {
|
||||
const date = this.date;
|
||||
if (!moment.isMoment(date)) {
|
||||
return null;
|
||||
}
|
||||
// verify that value is an ISO 8601 date string containg time
|
||||
// testing length is faster than parsing with moment
|
||||
const value = this.title;
|
||||
if (value.length !== 'YYYY-MM-DDTHH:mm:ss.SSSZ'.length) {
|
||||
if (!this.isDate || !this.hasTime) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return date.format('HH:mm');
|
||||
return this.datetime.toISOTime().substring(0, 5);
|
||||
}
|
||||
set time(value) {
|
||||
let date = this.date;
|
||||
assert(
|
||||
'can not set a time if current value is not a valid date',
|
||||
moment.isMoment(date)
|
||||
this.isDate
|
||||
);
|
||||
|
||||
// set time to undefined if value is false
|
||||
if (isEmpty(value)) {
|
||||
this.set('title', date.format('YYYY-MM-DD'));
|
||||
return value;
|
||||
this.set('title', this.day);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!moment(value, 'HH:mm', true).isValid()) {
|
||||
return value;
|
||||
const datetime = DateTime.fromISO(value);
|
||||
if (!datetime.isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [ hour, minute ] = value.split(':');
|
||||
this.set('title', date.hour(hour).minute(minute).toISOString());
|
||||
return value;
|
||||
this.set('title', this.datetime.set({ hours: datetime.hour, minutes: datetime.minute }).toISO());
|
||||
}
|
||||
|
||||
init() {
|
||||
|
|
|
@ -72,7 +72,7 @@ export default class Poll extends Model {
|
|||
/*
|
||||
* computed properties
|
||||
*/
|
||||
@computed('options.[]')
|
||||
@computed('isMakeAPoll', 'options.[]')
|
||||
get hasTimes() {
|
||||
if (this.isMakeAPoll) {
|
||||
return false;
|
||||
|
|
|
@ -3,7 +3,7 @@ import { inject as service } from '@ember/service';
|
|||
import Route from '@ember/routing/route';
|
||||
import config from 'croodle/config/environment';
|
||||
import answersForAnswerType from 'croodle/utils/answers-for-answer-type';
|
||||
/* global moment */
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
@classic
|
||||
export default class CreateRoute extends Route {
|
||||
|
@ -30,7 +30,7 @@ export default class CreateRoute extends Route {
|
|||
anonymousUser: false,
|
||||
pollType: 'FindADate',
|
||||
timezone: null,
|
||||
expirationDate: moment().add(3, 'month').toISOString(),
|
||||
expirationDate: DateTime.local().plus({ months: 3 }).toISO(),
|
||||
version: config.APP.version,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,20 +6,20 @@
|
|||
as |el|
|
||||
>
|
||||
<div
|
||||
class="
|
||||
form-control
|
||||
cr-h-auto
|
||||
cr-pr-validation
|
||||
{{if (eq el.validation "error") "is-invalid"}}
|
||||
{{if (eq el.validation "success") "is-valid"}}
|
||||
"
|
||||
class="form-control cr-h-auto cr-pr-validation
|
||||
{{if (eq el.validation 'error') 'is-invalid'}}
|
||||
{{if (eq el.validation 'success') 'is-valid'}}
|
||||
"
|
||||
>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6">
|
||||
<InlineDatepicker
|
||||
@center={{this.calendarCenter}}
|
||||
@selectedDays={{this.selectedDays}}
|
||||
@onCenterChange={{action (mut this.calendarCenter) value="moment"}}
|
||||
@onCenterChange={{action
|
||||
(mut this.calendarCenter)
|
||||
value="datetime"
|
||||
}}
|
||||
@onSelect={{action "daysSelected"}}
|
||||
/>
|
||||
</div>
|
||||
|
@ -27,7 +27,10 @@
|
|||
<InlineDatepicker
|
||||
@center={{this.calendarCenterNext}}
|
||||
@selectedDays={{this.selectedDays}}
|
||||
@onCenterChange={{action (mut this.calendarCenter) value="moment"}}
|
||||
@onCenterChange={{action
|
||||
(mut this.calendarCenter)
|
||||
value="datetime"
|
||||
}}
|
||||
@onSelect={{action "daysSelected"}}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -27,7 +27,16 @@
|
|||
data-test-day={{date.day}}
|
||||
>
|
||||
<form.element
|
||||
@label={{date.dayFormatted}}
|
||||
{{!
|
||||
TODO: Simplify to dateStyle="full" after upgrading to Ember Intl v6
|
||||
}}
|
||||
@label={{format-date
|
||||
date.jsDate
|
||||
weekday="long"
|
||||
day="numeric"
|
||||
month="long"
|
||||
year="numeric"
|
||||
}}
|
||||
{{!
|
||||
show label only if it differ from label before
|
||||
Nested-helpers are called first and object-at requires a positive integer
|
||||
|
@ -35,7 +44,12 @@
|
|||
Therefore we pass in array length if index is null. Cause index starting
|
||||
by zero there can't be any element with an index === array.length.
|
||||
}}
|
||||
@invisibleLabel={{eq date.dayFormatted (get (object-at (if index (sub index 1) @dates.length) @dates) "dayFormatted")}}
|
||||
@invisibleLabel={{eq
|
||||
date.day
|
||||
(get
|
||||
(object-at (if index (sub index 1) @dates.length) @dates) "day"
|
||||
)
|
||||
}}
|
||||
@model={{date}}
|
||||
@property="time"
|
||||
class="option"
|
||||
|
@ -47,14 +61,11 @@
|
|||
@placeholder="00:00"
|
||||
@type="time"
|
||||
@value={{el.value}}
|
||||
|
||||
{{! focus input if it's the first one }}
|
||||
{{autofocus enabled=(eq index 0)}}
|
||||
|
||||
{{! run validation for partially filled input on focusout event }}
|
||||
{{on "focusout" (fn this.validateInput date)}}
|
||||
|
||||
{{!--
|
||||
{{!
|
||||
Validation for partially input field must be reset if input is cleared.
|
||||
But `@onChange` is not called and `focusout` event not triggered in that
|
||||
scenario. Need to listen to additional events to ensure that partially
|
||||
|
@ -67,10 +78,9 @@
|
|||
Firefox does not consider partially time input as invalid, Edge prevents
|
||||
partially filling in first place and Desktop Safari as well as IE 11
|
||||
do not support `<input type="time">`.
|
||||
--}}
|
||||
}}
|
||||
{{on "focusin" (fn this.updateInputValidation date)}}
|
||||
{{on "keyup" (fn this.updateInputValidation date)}}
|
||||
|
||||
id={{el.id}}
|
||||
/>
|
||||
<div class="input-group-append">
|
||||
|
@ -81,8 +91,14 @@
|
|||
{{! disable delete button if there is only one option }}
|
||||
disabled={{lte @dates.length 1}}
|
||||
>
|
||||
<span class="oi oi-trash" title={{t "create.options.button.delete.label"}} aria-hidden="true"></span>
|
||||
<span class="sr-only">{{t "create.options.button.delete.label"}}</span>
|
||||
<span
|
||||
class="oi oi-trash"
|
||||
title={{t "create.options.button.delete.label"}}
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
<span class="sr-only">{{t
|
||||
"create.options.button.delete.label"
|
||||
}}</span>
|
||||
</BsButton>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -93,8 +109,14 @@
|
|||
@size="sm"
|
||||
class="add cr-option-menu__button cr-option-menu__add-button float-left"
|
||||
>
|
||||
<span class="oi oi-plus" title={{t "create.options.button.add.label"}} aria-hidden="true"></span>
|
||||
<span class="sr-only">{{t "create.options.button.add.label"}}</span>
|
||||
<span
|
||||
class="oi oi-plus"
|
||||
title={{t "create.options.button.add.label"}}
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
<span class="sr-only">{{t
|
||||
"create.options.button.add.label"
|
||||
}}</span>
|
||||
</BsButton>
|
||||
</form.element>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
@center={{@center}}
|
||||
@selected={{@selectedDays}}
|
||||
@onCenterChange={{@onCenterChange}}
|
||||
@onSelect={{@onSelect}} as |calendar|
|
||||
@onSelect={{@onSelect}}
|
||||
as |calendar|
|
||||
>
|
||||
<nav class="ember-power-calendar-nav">
|
||||
<button
|
||||
|
@ -13,7 +14,7 @@
|
|||
«
|
||||
</button>
|
||||
<div class="ember-power-calendar-nav-title">
|
||||
{{moment-format calendar.center "MMMM YYYY"}}
|
||||
{{format-date calendar.center month="long" year="numeric"}}
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{{#each this.locales as |locale|}}
|
||||
<option value={{locale.id}} selected={{locale.selected}}>
|
||||
{{locale.text}}
|
||||
{{#each-in this.locales as |localeKey localeName|}}
|
||||
<option value={{localeKey}} selected={{eq localeKey this.currentLocale}}>
|
||||
{{localeName}}
|
||||
</option>
|
||||
{{/each}}
|
||||
{{/each-in}}
|
|
@ -1,17 +1,23 @@
|
|||
<div class="participants-table">
|
||||
<table
|
||||
class="table"
|
||||
data-test-table-of="participants"
|
||||
>
|
||||
<table class="table" data-test-table-of="participants">
|
||||
<thead>
|
||||
{{#if this.hasTimes}}
|
||||
<tr>
|
||||
<th>
|
||||
{{!-- column for name --}}
|
||||
{{! column for name }}
|
||||
</th>
|
||||
{{#each this.optionsGroupedByDays as |optionGroup|}}
|
||||
<th colspan={{optionGroup.items.length}}>
|
||||
{{moment-format optionGroup.value @momentLongDayFormat}}
|
||||
{{!
|
||||
TODO: Simplify to dateStyle="full" after upgrading to Ember Intl v6
|
||||
}}
|
||||
{{format-date
|
||||
optionGroup.value
|
||||
weekday="long"
|
||||
day="numeric"
|
||||
month="long"
|
||||
year="numeric"
|
||||
}}
|
||||
</th>
|
||||
{{/each}}
|
||||
</tr>
|
||||
|
@ -19,16 +25,28 @@
|
|||
|
||||
<tr>
|
||||
<th>
|
||||
{{!-- column for name --}}
|
||||
{{! column for name }}
|
||||
</th>
|
||||
{{#each this.options as |option|}}
|
||||
<th>
|
||||
{{#if (and this.isFindADate this.hasTimes)}}
|
||||
{{#if option.hasTime}}
|
||||
{{moment-format option.date "LT"}}
|
||||
{{!
|
||||
TODO: Simplify to timeStyle="short" after upgrading to Ember Intl v6
|
||||
}}
|
||||
{{format-date option.date hour="numeric" minute="numeric"}}
|
||||
{{/if}}
|
||||
{{else if this.isFindADate}}
|
||||
{{moment-format option.date @momentLongDayFormat}}
|
||||
{{!
|
||||
TODO: Simplify to dateStyle="full" after upgrading to Ember Intl v6
|
||||
}}
|
||||
{{format-date
|
||||
option.jsDate
|
||||
weekday="long"
|
||||
day="numeric"
|
||||
month="long"
|
||||
year="numeric"
|
||||
}}
|
||||
{{else}}
|
||||
{{option.title}}
|
||||
{{/if}}
|
||||
|
@ -40,9 +58,7 @@
|
|||
<tbody>
|
||||
{{#each this.usersSorted as |user|}}
|
||||
<tr data-test-participant={{user.id}}>
|
||||
<td
|
||||
data-test-value-for="name"
|
||||
>
|
||||
<td data-test-value-for="name">
|
||||
{{user.name}}
|
||||
</td>
|
||||
{{#each this.options as |option index|}}
|
||||
|
|
|
@ -1,23 +1,32 @@
|
|||
{{!--
|
||||
{{!
|
||||
There must not be a line break between option text and "</strong>." cause otherwise
|
||||
we will see a space between option string and following dot.
|
||||
--}}
|
||||
}}
|
||||
{{#if @isFindADate}}
|
||||
{{! Need to disable block indentation rule cause there shouldn't be a space between date and dot }}
|
||||
{{! template-lint-disable block-indentation }}
|
||||
<strong class="best-option-value">
|
||||
{{moment-format
|
||||
@evaluationBestOption.option.title
|
||||
(if @evaluationBestOption.option.hasTime "LLLL" @momentLongDayFormat)
|
||||
locale=@currentLocale
|
||||
timeZone=@timezone
|
||||
{{!
|
||||
TODO: Simplify to dateStyle="full" and timeStyle="short" after upgrading to Ember Intl v6
|
||||
}}
|
||||
{{format-date
|
||||
@evaluationBestOption.option.jsDate
|
||||
weekday="long"
|
||||
day="numeric"
|
||||
month="long"
|
||||
year="numeric"
|
||||
hour=(if @evaluationBestOption.option.hasTime "numeric" undefined)
|
||||
minute=(if @evaluationBestOption.option.hasTime "numeric" undefined)
|
||||
timeZone=(if @timeZone @timeZone undefined)
|
||||
}}</strong>.
|
||||
{{! template-lint-enable block-indentation }}
|
||||
{{else}}
|
||||
<strong class="best-option-value">{{@evaluationBestOption.option.title}}</strong>.
|
||||
<strong
|
||||
class="best-option-value"
|
||||
>{{@evaluationBestOption.option.title}}</strong>.
|
||||
{{/if}}
|
||||
|
||||
<br>
|
||||
<br />
|
||||
|
||||
{{#if @isFindADate}}
|
||||
{{#if @evaluationBestOption.answers.yes}}
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
@currentLocale={{this.currentLocale}}
|
||||
@evaluationBestOption={{evaluationBestOption}}
|
||||
@isFindADate={{@poll.isFindADate}}
|
||||
@momentLongDayFormat={{@momentLongDayFormat}}
|
||||
@timezone={{@timezone}}
|
||||
@timeZone={{@timeZone}}
|
||||
/>
|
||||
</li>
|
||||
{{/each}}
|
||||
|
@ -38,8 +37,7 @@
|
|||
@currentLocale={{this.currentLocale}}
|
||||
@evaluationBestOption={{this.bestOptions.firstObject}}
|
||||
@isFindADate={{@poll.isFindADate}}
|
||||
@momentLongDayFormat={{@momentLongDayFormat}}
|
||||
@timezone={{@timezone}}
|
||||
@timeZone={{@timeZone}}
|
||||
/>
|
||||
{{/if}}
|
||||
</p>
|
||||
|
@ -47,6 +45,6 @@
|
|||
<p class="last-participation">
|
||||
{{t
|
||||
"poll.evaluation.lastParticipation"
|
||||
ago=(moment-from-now this.lastParticipationAt locale=this.currentLocale timezone=@timezone)
|
||||
ago=(format-date-relative this.lastParticipationAt)
|
||||
}}
|
||||
</p>
|
|
@ -9,17 +9,39 @@
|
|||
<p class="description">{{poll.description}}</p>
|
||||
<p class="dates">
|
||||
<span class="creationDate">
|
||||
{{!
|
||||
TODO: Simplify to dateStyle="full" and timeStyle="short" after upgrading to Ember Intl v6
|
||||
}}
|
||||
{{t
|
||||
"poll.created-date"
|
||||
date=(moment-format poll.creationDate "LLLL" locale=this.currentLocale)
|
||||
date=(format-date
|
||||
poll.creationDate
|
||||
weekday="long"
|
||||
day="numeric"
|
||||
month="long"
|
||||
year="numeric"
|
||||
hour="numeric"
|
||||
minute="numeric"
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
{{#if poll.expirationDate}}
|
||||
<br>
|
||||
<br />
|
||||
<span class="expirationDate">
|
||||
{{!
|
||||
TODO: Simplify to dateStyle="full" and timeStyle="short" after upgrading to Ember Intl v6
|
||||
}}
|
||||
{{t
|
||||
"poll.expiration-date"
|
||||
date=(moment-format poll.expirationDate "LLLL" locale=this.currentLocale)
|
||||
date=(format-date
|
||||
poll.expirationDate
|
||||
weekday="long"
|
||||
day="numeric"
|
||||
month="long"
|
||||
year="numeric"
|
||||
hour="numeric"
|
||||
minute="numeric"
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
{{/if}}
|
||||
|
@ -40,7 +62,11 @@
|
|||
class="btn btn-secondary cr-poll-link__copy-btn btn-sm"
|
||||
>
|
||||
{{t "poll.link.copy-label"}}
|
||||
<span class="oi oi-clipboard" title={{t "poll.link.copy-label"}} aria-hidden="true"></span>
|
||||
<span
|
||||
class="oi oi-clipboard"
|
||||
title={{t "poll.link.copy-label"}}
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
</CopyButton>
|
||||
</p>
|
||||
<small class="text-muted">
|
||||
|
@ -56,7 +82,7 @@
|
|||
<BsAlert @type="warning" class="expiration-warning">
|
||||
{{t
|
||||
"poll.expiration-date-warning"
|
||||
timeToNow=(moment-from-now poll.expirationDate locale=this.currentLocale)
|
||||
timeToNow=(format-date-relative poll.expirationDate)
|
||||
}}
|
||||
</BsAlert>
|
||||
</div>
|
||||
|
@ -65,12 +91,24 @@
|
|||
|
||||
<div class="box">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<LinkTo @route="poll.participation" @model={{poll}} @tagName="li" @activeClass="active" class="participation nav-item">
|
||||
<LinkTo
|
||||
@route="poll.participation"
|
||||
@model={{poll}}
|
||||
@tagName="li"
|
||||
@activeClass="active"
|
||||
class="participation nav-item"
|
||||
>
|
||||
<LinkTo @route="poll.participation" @model={{poll}} class="nav-link">
|
||||
{{t "poll.tab-title.participation"}}
|
||||
</LinkTo>
|
||||
</LinkTo>
|
||||
<LinkTo @route="poll.evaluation" @model={{poll}} @tagName="li" @activeClass="active" class="evaluation nav-item">
|
||||
<LinkTo
|
||||
@route="poll.evaluation"
|
||||
@model={{poll}}
|
||||
@tagName="li"
|
||||
@activeClass="active"
|
||||
class="evaluation nav-item"
|
||||
>
|
||||
<LinkTo @route="poll.evaluation" @model={{poll}} class="nav-link">
|
||||
{{t "poll.tab-title.evaluation"}}
|
||||
</LinkTo>
|
||||
|
|
|
@ -1,16 +1,8 @@
|
|||
{{#let @model as |poll|}}
|
||||
{{#if this.isEvaluable}}
|
||||
<PollEvaluationSummary
|
||||
@momentLongDayFormat={{this.momentLongDayFormat}}
|
||||
@poll={{poll}}
|
||||
@timezone={{this.timezone}}
|
||||
/>
|
||||
<PollEvaluationSummary @poll={{poll}} @timeZone={{this.timezone}} />
|
||||
{{/if}}
|
||||
|
||||
<h3>{{t "poll.evaluation.participantTable"}}</h3>
|
||||
<PollEvaluationParticipantsTable
|
||||
@momentLongDayFormat={{this.momentLongDayFormat}}
|
||||
@poll={{poll}}
|
||||
@timezone={{this.timezone}}
|
||||
/>
|
||||
<PollEvaluationParticipantsTable @poll={{poll}} @timeZone={{this.timezone}} />
|
||||
{{/let}}
|
|
@ -25,12 +25,20 @@
|
|||
{{#if this.isFreeText}}
|
||||
<form.element
|
||||
@controlType="text"
|
||||
@label={{if this.isFindADate
|
||||
(moment-format
|
||||
{{!
|
||||
TODO: Simplify date formating to dateStyle="full" and timeStyle="short" after upgrading to Ember Intl v6
|
||||
}}
|
||||
@label={{if
|
||||
this.isFindADate
|
||||
(format-date
|
||||
selection.labelValue
|
||||
(if (eq selection.momentFormat "day") this.momentLongDayFormat selection.momentFormat)
|
||||
locale=this.currentLocale
|
||||
timeZone=this.timezone
|
||||
weekday=(if selection.showDate "long" undefined)
|
||||
day=(if selection.showDate "numeric" undefined)
|
||||
month=(if selection.showDate "long" undefined)
|
||||
year=(if selection.showDate "numeric" undefined)
|
||||
hour=(if selection.showTime "numeric" undefined)
|
||||
minute=(if selection.showTime "numeric" undefined)
|
||||
timeZone=(if this.timezone this.timezone undefined)
|
||||
)
|
||||
selection.labelValue
|
||||
}}
|
||||
|
@ -39,12 +47,20 @@
|
|||
/>
|
||||
{{else}}
|
||||
<form.element
|
||||
@label={{if this.isFindADate
|
||||
(moment-format
|
||||
{{!
|
||||
TODO: Simplify date formating to dateStyle="full" and timeStyle="short" after upgrading to Ember Intl v6
|
||||
}}
|
||||
@label={{if
|
||||
this.isFindADate
|
||||
(format-date
|
||||
selection.labelValue
|
||||
(if (eq selection.momentFormat "day") this.momentLongDayFormat selection.momentFormat)
|
||||
locale=this.currentLocale
|
||||
timeZone=this.timezone
|
||||
weekday=(if selection.showDate "long" undefined)
|
||||
day=(if selection.showDate "numeric" undefined)
|
||||
month=(if selection.showDate "long" undefined)
|
||||
year=(if selection.showDate "numeric" undefined)
|
||||
hour=(if selection.showTime "numeric" undefined)
|
||||
minute=(if selection.showTime "numeric" undefined)
|
||||
timeZone=(if this.timezone this.timezone undefined)
|
||||
)
|
||||
selection.labelValue
|
||||
}}
|
||||
|
@ -52,24 +68,30 @@
|
|||
@property="value"
|
||||
@showValidationOn="change"
|
||||
@useIcons={{false}}
|
||||
data-test-form-element={{concat "option-" selection.labelValue}}
|
||||
data-test-form-element={{concat "option-" selection.labelString}}
|
||||
as |el|
|
||||
>
|
||||
{{#each this.possibleAnswers as |possibleAnswer|}}
|
||||
<div class="radio custom-control custom-radio custom-control-inline {{possibleAnswer.type}}">
|
||||
<div
|
||||
class="radio custom-control custom-radio custom-control-inline
|
||||
{{possibleAnswer.type}}"
|
||||
>
|
||||
<input
|
||||
class="custom-control-input
|
||||
{{if (eq el.validation "success") "is-valid"}}
|
||||
{{if (eq el.validation "error") "is-invalid"}}
|
||||
"
|
||||
{{if (eq el.validation 'success') 'is-valid'}}
|
||||
{{if (eq el.validation 'error') 'is-invalid'}}
|
||||
"
|
||||
type="radio"
|
||||
value={{possibleAnswer.type}}
|
||||
checked={{eq possibleAnswer.type el.value}}
|
||||
onchange={{action (mut el.value) possibleAnswer.type}}
|
||||
id={{concat el.id "_" possibleAnswer.type}}
|
||||
name={{selection.labelValue}}
|
||||
/>
|
||||
<label
|
||||
class="custom-control-label"
|
||||
for={{concat el.id "_" possibleAnswer.type}}
|
||||
>
|
||||
<label class="custom-control-label" for={{concat el.id "_" possibleAnswer.type}}>
|
||||
{{possibleAnswer.label}}
|
||||
</label>
|
||||
</div>
|
||||
|
@ -81,7 +103,10 @@
|
|||
|
||||
<div class="row cr-steps-bottom-nav">
|
||||
<div class="col-md-8 offset-md-4">
|
||||
<SaveButton @isPending={{form.isSubmitting}} data-test-button="submit" />
|
||||
<SaveButton
|
||||
@isPending={{form.isSubmitting}}
|
||||
data-test-button="submit"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</BsForm>
|
||||
|
@ -94,17 +119,12 @@
|
|||
data-test-modal="saving-failed"
|
||||
as |modal|
|
||||
>
|
||||
<modal.header
|
||||
@closeButton={{false}}
|
||||
@title={{t "modal.save-retry.title"}}
|
||||
/>
|
||||
<modal.header @closeButton={{false}} @title={{t "modal.save-retry.title"}} />
|
||||
<modal.body>
|
||||
<p>{{t "modal.save-retry.text"}}</p>
|
||||
</modal.body>
|
||||
<modal.footer>
|
||||
<BsButton
|
||||
@onClick={{action modal.close}}
|
||||
>
|
||||
<BsButton @onClick={{action modal.close}}>
|
||||
{{t "action.abort"}}
|
||||
</BsButton>
|
||||
<BsButton
|
||||
|
|
|
@ -1,21 +1,10 @@
|
|||
import classic from 'ember-classic-decorator';
|
||||
import { isArray } from '@ember/array';
|
||||
import { isEmpty } from '@ember/utils';
|
||||
import { assert } from '@ember/debug';
|
||||
import BaseValidator from 'ember-cp-validations/validators/base';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
@classic
|
||||
export default class Iso8601Validator extends BaseValidator {
|
||||
validate(value, options = {}) {
|
||||
assert(
|
||||
'options.validFormats must not be set or an array of momentJS format strings',
|
||||
isEmpty(options.validFormats) || isArray(options.validFormats)
|
||||
);
|
||||
|
||||
let valid;
|
||||
const validFormats = isEmpty(options.validFormats) ? ['YYYY-MM-DDTHH:mm:ss.SSSZ'] : options.validFormats;
|
||||
|
||||
if (
|
||||
options.active === false ||
|
||||
(typeof options.active === 'function' && options.active() === false)
|
||||
|
@ -25,9 +14,7 @@ export default class Iso8601Validator extends BaseValidator {
|
|||
|
||||
options.value = value;
|
||||
|
||||
valid = validFormats.any((validFormat) => {
|
||||
return moment(value, validFormat, true).isValid();
|
||||
});
|
||||
const valid = DateTime.fromISO(value).isValid;
|
||||
|
||||
if (valid) {
|
||||
return true;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import classic from 'ember-classic-decorator';
|
||||
import { isEmpty } from '@ember/utils';
|
||||
import BaseValidator from 'ember-cp-validations/validators/base';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
@classic
|
||||
export default class TimeValidator extends BaseValidator {
|
||||
|
@ -14,15 +14,15 @@ export default class TimeValidator extends BaseValidator {
|
|||
|
||||
options.value = value;
|
||||
|
||||
if (options.allowEmpty && isEmpty(value)) {
|
||||
return true;
|
||||
if (isEmpty(value)) {
|
||||
return options.allowEmpty === true ? true : this.createErrorMessage('time', value, options);
|
||||
}
|
||||
|
||||
if (!isEmpty(value) && typeof value.trim === 'function') {
|
||||
if (typeof value.trim === 'function') {
|
||||
value = value.trim();
|
||||
}
|
||||
|
||||
valid = moment(value, 'H:mm', true).isValid();
|
||||
valid = DateTime.fromFormat(value, 'H:mm').isValid;
|
||||
|
||||
if (valid && value !== '24:00') {
|
||||
return true;
|
||||
|
|
|
@ -34,11 +34,6 @@ module.exports = function(environment) {
|
|||
'media-src': "'none'",
|
||||
},
|
||||
contentSecurityPolicyMeta: true,
|
||||
|
||||
moment: {
|
||||
includeLocales: ['ca', 'de', 'en-gb', 'es', 'fr', 'it', 'nb'],
|
||||
includeTimezone: 'subset'
|
||||
},
|
||||
};
|
||||
|
||||
if (environment === 'development') {
|
||||
|
|
11
package.json
11
package.json
|
@ -29,7 +29,7 @@
|
|||
"babel-eslint": "^10.1.0",
|
||||
"bootstrap": "^4.3.1",
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"ember-auto-import": "^1.6.0",
|
||||
"ember-auto-import": "^2.0.0",
|
||||
"ember-awesome-macros": "^6.0.0",
|
||||
"ember-bootstrap": "^3.0.0",
|
||||
"ember-bootstrap-cp-validations": "^2.0.0",
|
||||
|
@ -39,7 +39,7 @@
|
|||
"ember-cli-app-version": "^4.0.0",
|
||||
"ember-cli-babel": "^7.21.0",
|
||||
"ember-cli-browser-navigation-button-test-helper": "^0.3.0",
|
||||
"ember-cli-browserstack": "^1.0.0",
|
||||
"ember-cli-browserstack": "^2.0.0",
|
||||
"ember-cli-bundlesize": "^0.3.0",
|
||||
"ember-cli-clipboard": "^0.16.0",
|
||||
"ember-cli-content-security-policy": "^1.0.0",
|
||||
|
@ -49,7 +49,6 @@
|
|||
"ember-cli-htmlbars": "^5.2.0",
|
||||
"ember-cli-inject-live-reload": "^2.0.2",
|
||||
"ember-cli-mirage": "^2.0.0",
|
||||
"ember-cli-moment-shim": "jelhan/ember-cli-moment-shim#6eabccf0bee2a3840c3024c5d526bc9c349fa13f",
|
||||
"ember-cli-page-object": "^1.11.0",
|
||||
"ember-cli-sass": "^10.0.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
|
@ -66,10 +65,9 @@
|
|||
"ember-math-helpers": "^2.8.1",
|
||||
"ember-maybe-import-regenerator": "^0.1.6",
|
||||
"ember-modifier": "^2.1.1",
|
||||
"ember-moment": "^8.0.0",
|
||||
"ember-page-title": "^6.0.0",
|
||||
"ember-power-calendar": "^0.19.0",
|
||||
"ember-power-calendar-moment": "^0.1.4",
|
||||
"ember-power-calendar-luxon": "^0.4.0",
|
||||
"ember-qunit": "^4.6.0",
|
||||
"ember-resolver": "^8.0.0",
|
||||
"ember-source": "~3.20.2",
|
||||
|
@ -89,7 +87,8 @@
|
|||
"release-it": "^16.0.0",
|
||||
"release-it-lerna-changelog": "^5.0.0",
|
||||
"sass": "^1.19.0",
|
||||
"sjcl": "^1.0.8"
|
||||
"sjcl": "^1.0.8",
|
||||
"webpack": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "16.* || >=18"
|
||||
|
|
|
@ -58,7 +58,7 @@ module.exports = {
|
|||
'--os',
|
||||
'OS X',
|
||||
'--osv',
|
||||
'Mojave',
|
||||
'Ventura',
|
||||
'--b',
|
||||
'safari',
|
||||
'--bv',
|
||||
|
@ -76,7 +76,7 @@ module.exports = {
|
|||
'--os',
|
||||
'OS X',
|
||||
'--osv',
|
||||
'Catalina',
|
||||
'Ventura',
|
||||
'--b',
|
||||
'safari',
|
||||
'--bv',
|
||||
|
|
|
@ -4,7 +4,7 @@ import { setupApplicationTest } from 'ember-qunit';
|
|||
import { setupMirage } from 'ember-cli-mirage/test-support';
|
||||
import { setupIntl, t } from 'ember-intl/test-support';
|
||||
import { setupBrowserNavigationButtons, backButton } from 'ember-cli-browser-navigation-button-test-helper/test-support';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
import pageCreateIndex from 'croodle/tests/pages/create/index';
|
||||
import pageCreateMeta from 'croodle/tests/pages/create/meta';
|
||||
import pageCreateOptions from 'croodle/tests/pages/create/options';
|
||||
|
@ -28,8 +28,8 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
|
||||
test('create a default poll', async function(assert) {
|
||||
const dates = [
|
||||
moment().add(1, 'day'),
|
||||
moment().add(1, 'week')
|
||||
DateTime.now().plus({ days: 1 }),
|
||||
DateTime.now().plus({ weeks: 1 }),
|
||||
];
|
||||
|
||||
await pageCreateIndex.visit();
|
||||
|
@ -174,13 +174,9 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
'',
|
||||
'poll description is correct'
|
||||
);
|
||||
const dayFormat = moment.localeData().longDateFormat('LLLL')
|
||||
.replace(
|
||||
moment.localeData().longDateFormat('LT'), '')
|
||||
.trim();
|
||||
assert.deepEqual(
|
||||
pagePollParticipation.options().labels,
|
||||
dates.map((date) => date.format(dayFormat)),
|
||||
dates.map((date) => Intl.DateTimeFormat('en-US', { dateStyle: "full" }).format(date)),
|
||||
'options are correctly labeled'
|
||||
);
|
||||
assert.deepEqual(
|
||||
|
@ -338,14 +334,10 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
});
|
||||
|
||||
test('create a poll with times and description', async function(assert) {
|
||||
let days = [
|
||||
moment().add(1, 'day'),
|
||||
moment().add(1, 'week')
|
||||
const days = [
|
||||
DateTime.now().plus({ days: 1 }),
|
||||
DateTime.now().plus({ weeks: 1 }),
|
||||
];
|
||||
const dayFormat = moment.localeData().longDateFormat('LLLL')
|
||||
.replace(
|
||||
moment.localeData().longDateFormat('LT'), '')
|
||||
.trim();
|
||||
|
||||
await pageCreateIndex.visit();
|
||||
await pageCreateIndex.next();
|
||||
|
@ -362,7 +354,7 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
assert.equal(currentRouteName(), 'create.options-datetime');
|
||||
assert.deepEqual(
|
||||
pageCreateOptionsDatetime.days().labels,
|
||||
days.map((day) => moment(day).format(dayFormat)),
|
||||
days.map((day) => Intl.DateTimeFormat('en-US', { dateStyle: "full" }).format(day)),
|
||||
'time inputs having days as label'
|
||||
);
|
||||
|
||||
|
@ -392,20 +384,16 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
assert.deepEqual(
|
||||
pagePollParticipation.options().labels,
|
||||
[
|
||||
days[0].hour(10).minute(0).format('LLLL'),
|
||||
days[0].hour(18).minute(0).format('LT'),
|
||||
days[1].hour(12).minute(0).format('LLLL')
|
||||
Intl.DateTimeFormat('en-US', { dateStyle: "full", timeStyle: "short" }).format(days[0].set({ hour: 10, minutes: 0 })),
|
||||
Intl.DateTimeFormat('en-US', { timeStyle: "short" }).format(days[0].set({ hours: 18, minutes: 0 })),
|
||||
Intl.DateTimeFormat('en-US', { dateStyle: "full", timeStyle: "short" }).format(days[1].set({ hour: 12, minutes: 0 })),
|
||||
],
|
||||
'options are correctly labeled'
|
||||
);
|
||||
});
|
||||
|
||||
test('create a poll with only one day and multiple times', async function(assert) {
|
||||
let day = moment().add(1, 'day');
|
||||
const dayFormat = moment.localeData().longDateFormat('LLLL')
|
||||
.replace(
|
||||
moment.localeData().longDateFormat('LT'), '')
|
||||
.trim();
|
||||
const day = DateTime.now().plus({ days: 1 });
|
||||
|
||||
await pageCreateIndex.visit();
|
||||
await pageCreateIndex.next();
|
||||
|
@ -422,7 +410,7 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
assert.equal(currentRouteName(), 'create.options-datetime');
|
||||
assert.deepEqual(
|
||||
pageCreateOptionsDatetime.days().labels,
|
||||
[ day.format(dayFormat) ],
|
||||
[ Intl.DateTimeFormat('en-US', { dateStyle: "full" }).format(day) ],
|
||||
'time inputs having days as label'
|
||||
);
|
||||
|
||||
|
@ -451,19 +439,15 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
assert.deepEqual(
|
||||
pagePollParticipation.options().labels,
|
||||
[
|
||||
day.hour(10).minute(0).format('LLLL'),
|
||||
day.hour(18).minute(0).format('LT')
|
||||
Intl.DateTimeFormat('en-US', { dateStyle: "full", timeStyle: "short" }).format(day.set({ hours: 10, minutes: 0 })),
|
||||
Intl.DateTimeFormat('en-US', { timeStyle: "short" }).format(day.set({ hours: 18, minutes: 0 })),
|
||||
],
|
||||
'options are correctly labeled'
|
||||
);
|
||||
});
|
||||
|
||||
test('create a poll with only one day (without time)', async function(assert) {
|
||||
let day = moment().add(1, 'day');
|
||||
const dayFormat = moment.localeData().longDateFormat('LLLL')
|
||||
.replace(
|
||||
moment.localeData().longDateFormat('LT'), '')
|
||||
.trim();
|
||||
const day = DateTime.now().plus({ days: 1 });
|
||||
|
||||
await pageCreateIndex.visit();
|
||||
await pageCreateIndex.next();
|
||||
|
@ -480,7 +464,7 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
assert.equal(currentRouteName(), 'create.options-datetime');
|
||||
assert.deepEqual(
|
||||
pageCreateOptionsDatetime.days().labels,
|
||||
[ day.format(dayFormat) ],
|
||||
[ Intl.DateTimeFormat('en-US', { dateStyle: "full" }).format(day) ],
|
||||
'time inputs having days as label'
|
||||
);
|
||||
|
||||
|
@ -506,18 +490,14 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
assert.deepEqual(
|
||||
pagePollParticipation.options().labels,
|
||||
[
|
||||
day.format(dayFormat)
|
||||
Intl.DateTimeFormat('en-US', { dateStyle: "full" }).format(day)
|
||||
],
|
||||
'options are correctly labeled'
|
||||
);
|
||||
});
|
||||
|
||||
test('create a poll with only one day (with time)', async function(assert) {
|
||||
let day = moment().add(1, 'day');
|
||||
const dayFormat = moment.localeData().longDateFormat('LLLL')
|
||||
.replace(
|
||||
moment.localeData().longDateFormat('LT'), '')
|
||||
.trim();
|
||||
const day = DateTime.now().plus({ days: 1 });
|
||||
|
||||
await pageCreateIndex.visit();
|
||||
await pageCreateIndex.next();
|
||||
|
@ -534,7 +514,7 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
assert.equal(currentRouteName(), 'create.options-datetime');
|
||||
assert.deepEqual(
|
||||
pageCreateOptionsDatetime.days().labels,
|
||||
[ day.format(dayFormat) ],
|
||||
[ Intl.DateTimeFormat('en-US', { dateStyle: "full" }).format(day) ],
|
||||
'time inputs having days as label'
|
||||
);
|
||||
|
||||
|
@ -561,7 +541,7 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
assert.deepEqual(
|
||||
pagePollParticipation.options().labels,
|
||||
[
|
||||
day.hour(22).minute(30).format('LLLL')
|
||||
Intl.DateTimeFormat('en-US', { dateStyle: "full", timeStyle: "short" }).format(day.set({ hours: 22, minutes: 30 })),
|
||||
],
|
||||
'options are correctly labeled'
|
||||
);
|
||||
|
@ -621,13 +601,9 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
|
||||
test('create a poll and using back button (find a date)', async function(assert) {
|
||||
let days = [
|
||||
moment('2016-01-02'),
|
||||
moment('2016-01-13'),
|
||||
DateTime.fromISO('2016-01-02'),
|
||||
DateTime.fromISO('2016-01-13'),
|
||||
];
|
||||
const dayFormat = moment.localeData().longDateFormat('LLLL')
|
||||
.replace(
|
||||
moment.localeData().longDateFormat('LT'), '')
|
||||
.trim();
|
||||
|
||||
setupBrowserNavigationButtons();
|
||||
|
||||
|
@ -641,14 +617,12 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
.next();
|
||||
assert.equal(currentRouteName(), 'create.options');
|
||||
|
||||
await pageCreateOptions.selectDates(
|
||||
days.map((_) => _.toDate())
|
||||
);
|
||||
await pageCreateOptions.selectDates(days);
|
||||
await pageCreateOptions.next();
|
||||
assert.equal(currentRouteName(), 'create.options-datetime');
|
||||
assert.deepEqual(
|
||||
pageCreateOptionsDatetime.days().labels,
|
||||
days.map((_) => _.format(dayFormat)),
|
||||
days.map((day) => Intl.DateTimeFormat('en-US', { dateStyle: "full" }).format(day)),
|
||||
'time inputs having days as label'
|
||||
);
|
||||
|
||||
|
@ -657,7 +631,7 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
assert.equal(currentRouteName(), 'create.options');
|
||||
assert.deepEqual(
|
||||
findAll('.ember-power-calendar-day--selected').map((el) => el.dataset.date),
|
||||
days.map((_) => _.format('YYYY-MM-DD')),
|
||||
days.map((day) => day.toISODate()),
|
||||
'days are still present after back button is used'
|
||||
);
|
||||
|
||||
|
@ -686,8 +660,8 @@ module('Acceptance | create a poll', function(hooks) {
|
|||
assert.deepEqual(
|
||||
pagePollParticipation.options().labels,
|
||||
[
|
||||
days[0].format(dayFormat),
|
||||
days[1].clone().hour(10).minute(0).format('LLLL')
|
||||
Intl.DateTimeFormat('en-US', { dateStyle: "full" }).format(days[0]),
|
||||
Intl.DateTimeFormat('en-US', { dateStyle: "full", timeStyle: "short" }).format(days[1].set({ hours: 10, minutes: 0 })),
|
||||
],
|
||||
'options are correctly labeled'
|
||||
);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { find, visit } from '@ember/test-helpers';
|
||||
import { fillIn, find, visit } from '@ember/test-helpers';
|
||||
import { module, test } from 'qunit';
|
||||
import { setupApplicationTest } from 'ember-qunit';
|
||||
import pageIndex from 'croodle/tests/pages/index';
|
||||
|
||||
module('Acceptance | i18n', function(hooks) {
|
||||
hooks.beforeEach(function() {
|
||||
|
@ -14,7 +13,7 @@ module('Acceptance | i18n', function(hooks) {
|
|||
await visit('/');
|
||||
assert.equal(find('.language-select').value, 'de', 'picks up locale in locale storage');
|
||||
|
||||
await pageIndex.locale('en');
|
||||
await fillIn('.language-select', 'en');
|
||||
assert.equal(find('.language-select').value, 'en');
|
||||
assert.equal(
|
||||
window.localStorage.getItem('locale'), 'en',
|
||||
|
|
|
@ -5,7 +5,6 @@ import { setupMirage } from 'ember-cli-mirage/test-support';
|
|||
import { setupIntl, t } from 'ember-intl/test-support';
|
||||
import switchTab from 'croodle/tests/helpers/switch-tab';
|
||||
import pollParticipate from 'croodle/tests/helpers/poll-participate';
|
||||
import moment from 'moment';
|
||||
import PollParticipationPage from 'croodle/tests/pages/poll/participation';
|
||||
import PollEvaluationPage from 'croodle/tests/pages/poll/evaluation';
|
||||
|
||||
|
@ -57,9 +56,9 @@ module('Acceptance | legacy support', function(hooks) {
|
|||
assert.deepEqual(
|
||||
PollParticipationPage.options().labels,
|
||||
[
|
||||
moment('2015-12-24T17:00:00.000Z').format('LLLL'),
|
||||
moment('2015-12-24T19:00:00.000Z').format('LT'),
|
||||
moment('2015-12-31T22:59:00.000Z').format('LLLL')
|
||||
Intl.DateTimeFormat('en-US', { dateStyle: "full", timeStyle: "short" }).format(new Date('2015-12-24T17:00:00.000Z')),
|
||||
Intl.DateTimeFormat('en-US', { timeStyle: "short" }).format(new Date('2015-12-24T19:00:00.000Z')),
|
||||
Intl.DateTimeFormat('en-US', { dateStyle: "full", timeStyle: "short" }).format(new Date('2015-12-31T22:59:00.000Z')),
|
||||
]
|
||||
);
|
||||
assert.deepEqual(
|
||||
|
|
|
@ -3,9 +3,9 @@ import { module, test } from 'qunit';
|
|||
import { setupApplicationTest } from 'ember-qunit';
|
||||
import { setupMirage } from 'ember-cli-mirage/test-support';
|
||||
import { setupIntl, t } from 'ember-intl/test-support';import switchTab from 'croodle/tests/helpers/switch-tab';
|
||||
import moment from 'moment';
|
||||
import PollEvaluationPage from 'croodle/tests/pages/poll/evaluation';
|
||||
import { assign } from '@ember/polyfills';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
module('Acceptance | view evaluation', function(hooks) {
|
||||
hooks.beforeEach(function() {
|
||||
|
@ -32,7 +32,7 @@ module('Acceptance | view evaluation', function(hooks) {
|
|||
test('evaluation is correct for FindADate', async function(assert) {
|
||||
let encryptionKey = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let user1 = this.server.create('user', {
|
||||
creationDate: '2015-01-01T00:00:00.000Z',
|
||||
creationDate: DateTime.local().minus({ months: 8, weeks: 3 }).toISO(),
|
||||
encryptionKey,
|
||||
name: 'Maximilian',
|
||||
selections: [
|
||||
|
@ -51,7 +51,7 @@ module('Acceptance | view evaluation', function(hooks) {
|
|||
]
|
||||
});
|
||||
let user2 = this.server.create('user', {
|
||||
creationDate: '2015-08-01T00:00:00.000Z',
|
||||
creationDate: DateTime.local().minus({ months: 3, weeks: 2 }).toISO(),
|
||||
encryptionKey,
|
||||
name: 'Peter',
|
||||
selections: [
|
||||
|
@ -108,7 +108,7 @@ module('Acceptance | view evaluation', function(hooks) {
|
|||
assert.equal(
|
||||
find('.last-participation').textContent.trim(),
|
||||
t('poll.evaluation.lastParticipation', {
|
||||
ago: moment('2015-08-01T00:00:00.000Z').from()
|
||||
ago: '3 months ago'
|
||||
}).toString(),
|
||||
'last participation is evaluated correctly'
|
||||
);
|
||||
|
@ -118,7 +118,7 @@ module('Acceptance | view evaluation', function(hooks) {
|
|||
let encryptionKey = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let usersData = [
|
||||
{
|
||||
creationDate: '2015-01-01T00:00:00.000Z',
|
||||
creationDate: DateTime.local().minus({ weeks: 5 }).toISO(),
|
||||
encryptionKey,
|
||||
name: 'Maximilian',
|
||||
selections: [
|
||||
|
@ -137,7 +137,7 @@ module('Acceptance | view evaluation', function(hooks) {
|
|||
]
|
||||
},
|
||||
{
|
||||
creationDate: '2015-08-01T00:00:00.000Z',
|
||||
creationDate: DateTime.local().minus({ days: 3 }).toISO(),
|
||||
encryptionKey,
|
||||
name: 'Peter',
|
||||
selections: [
|
||||
|
@ -215,7 +215,7 @@ module('Acceptance | view evaluation', function(hooks) {
|
|||
assert.equal(
|
||||
find('.last-participation').textContent.trim(),
|
||||
t('poll.evaluation.lastParticipation', {
|
||||
ago: moment('2015-08-01T00:00:00.000Z').from()
|
||||
ago: '3 days ago'
|
||||
}).toString(),
|
||||
'last participation is evaluated correctly'
|
||||
);
|
||||
|
|
|
@ -5,7 +5,7 @@ import { setupMirage } from 'ember-cli-mirage/test-support';
|
|||
import switchTab from 'croodle/tests/helpers/switch-tab';
|
||||
import pageParticipation from 'croodle/tests/pages/poll/participation';
|
||||
import pageEvaluation from 'croodle/tests/pages/poll/evaluation';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
import { triggerCopySuccess } from 'ember-cli-clipboard/test-support';
|
||||
|
||||
module('Acceptance | view poll', function(hooks) {
|
||||
|
@ -42,7 +42,7 @@ module('Acceptance | view poll', function(hooks) {
|
|||
let encryptionKey = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let poll = this.server.create('poll', {
|
||||
encryptionKey,
|
||||
expirationDate: moment().add(1, 'week')
|
||||
expirationDate: DateTime.local().plus({ weeks: 1 }).toISO(),
|
||||
});
|
||||
|
||||
await visit(`/poll/${poll.id}?encryptionKey=${encryptionKey}`);
|
||||
|
@ -73,18 +73,18 @@ module('Acceptance | view poll', function(hooks) {
|
|||
|
||||
test('view a poll with dates and times', async function(assert) {
|
||||
let encryptionKey = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let timezone = moment.tz.guess();
|
||||
let timezone = Intl.DateTimeFormat().resolvedOptions().timeZone ;
|
||||
let poll = this.server.create('poll', {
|
||||
encryptionKey,
|
||||
expirationDate: moment().add(1, 'year'),
|
||||
expirationDate: DateTime.local().plus({ years: 1 }).toISO(),
|
||||
isDateTime: true,
|
||||
options: [
|
||||
// need to parse the date with moment cause Safari's Date.parse()
|
||||
// need to parse the date with luxon cause Safari's Date.parse()
|
||||
// implementation treats a data-time string without explicit
|
||||
// time zone as UTC rather than local time
|
||||
{ title: moment('2015-12-12T11:11:00').toISOString() },
|
||||
{ title: moment('2015-12-12T13:13:00').toISOString() },
|
||||
{ title: moment('2016-01-01T11:11:00').toISOString() }
|
||||
{ title: DateTime.fromISO('2015-12-12T11:11:00').toISO() },
|
||||
{ title: DateTime.fromISO('2015-12-12T13:13:00').toISO() },
|
||||
{ title: DateTime.fromISO('2016-01-01T11:11:00').toISO() }
|
||||
],
|
||||
timezone
|
||||
});
|
||||
|
@ -94,11 +94,11 @@ module('Acceptance | view poll', function(hooks) {
|
|||
pageParticipation.options().labels,
|
||||
[
|
||||
// full date
|
||||
'Saturday, December 12, 2015 11:11 AM',
|
||||
'Saturday, December 12, 2015 at 11:11 AM',
|
||||
// only time cause day is repeated
|
||||
'1:13 PM',
|
||||
// full date cause day changed
|
||||
'Friday, January 1, 2016 11:11 AM',
|
||||
'Friday, January 1, 2016 at 11:11 AM',
|
||||
]
|
||||
);
|
||||
assert.notOk(
|
||||
|
@ -109,7 +109,7 @@ module('Acceptance | view poll', function(hooks) {
|
|||
|
||||
test('view a poll while timezone differs from the one poll got created in and choose local timezone', async function(assert) {
|
||||
let encryptionKey = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let timezoneUser = moment.tz.guess();
|
||||
let timezoneUser = Intl.DateTimeFormat().resolvedOptions().timeZone ;
|
||||
let timezonePoll = timezoneUser !== 'America/Caracas' ? 'America/Caracas' : 'Europe/Moscow';
|
||||
let poll = this.server.create('poll', {
|
||||
encryptionKey,
|
||||
|
@ -148,8 +148,8 @@ module('Acceptance | view poll', function(hooks) {
|
|||
assert.deepEqual(
|
||||
pageParticipation.options().labels,
|
||||
[
|
||||
moment.tz('2015-12-12T11:11:00.000Z', timezoneUser).locale('en').format('LLLL'),
|
||||
moment.tz('2016-01-01T11:11:00.000Z', timezoneUser).locale('en').format('LLLL')
|
||||
Intl.DateTimeFormat('en-US', { dateStyle: "full", timeStyle: "short" }).format(new Date('2015-12-12T11:11:00.000Z')),
|
||||
Intl.DateTimeFormat('en-US', { dateStyle: "full", timeStyle: "short" }).format(new Date('2016-01-01T11:11:00.000Z')),
|
||||
]
|
||||
);
|
||||
assert.dom('[data-test-modal="choose-timezone"]').doesNotExist('modal is closed');
|
||||
|
@ -157,13 +157,13 @@ module('Acceptance | view poll', function(hooks) {
|
|||
await switchTab('evaluation');
|
||||
assert.deepEqual(
|
||||
pageEvaluation.preferedOptions,
|
||||
[moment.tz('2015-12-12T11:11:00.000Z', timezoneUser).locale('en').format('LLLL')]
|
||||
[Intl.DateTimeFormat('en-US', { dateStyle: "full", timeStyle: "short" }).format(new Date('2015-12-12T11:11:00.000Z'))]
|
||||
);
|
||||
});
|
||||
|
||||
test('view a poll while timezone differs from the one poll got created in and choose poll timezone', async function(assert) {
|
||||
let encryptionKey = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let timezoneUser = moment.tz.guess();
|
||||
let timezoneUser = Intl.DateTimeFormat().resolvedOptions().timeZone ;
|
||||
let timezonePoll = timezoneUser !== 'America/Caracas' ? 'America/Caracas' : 'Europe/Moscow';
|
||||
let poll = this.server.create('poll', {
|
||||
encryptionKey,
|
||||
|
@ -202,8 +202,8 @@ module('Acceptance | view poll', function(hooks) {
|
|||
assert.deepEqual(
|
||||
pageParticipation.options().labels,
|
||||
[
|
||||
moment.tz('2015-12-12T11:11:00.000Z', timezonePoll).locale('en').format('LLLL'),
|
||||
moment.tz('2016-01-01T11:11:00.000Z', timezonePoll).locale('en').format('LLLL')
|
||||
Intl.DateTimeFormat('en-US', { timeZone: timezonePoll, dateStyle: "full", timeStyle: "short" }).format(new Date('2015-12-12T11:11:00.000Z')),
|
||||
Intl.DateTimeFormat('en-US', { timeZone: timezonePoll, dateStyle: "full", timeStyle: "short" }).format(new Date('2016-01-01T11:11:00.000Z')),
|
||||
]
|
||||
);
|
||||
assert.dom('[data-test-modal="choose-timezone"]').doesNotExist('modal is closed');
|
||||
|
@ -211,7 +211,7 @@ module('Acceptance | view poll', function(hooks) {
|
|||
await switchTab('evaluation');
|
||||
assert.deepEqual(
|
||||
pageEvaluation.preferedOptions,
|
||||
[moment.tz('2015-12-12T11:11:00.000Z', timezonePoll).locale('en').format('LLLL')]
|
||||
[Intl.DateTimeFormat('en-US', { timeZone: timezonePoll, dateStyle: "full", timeStyle: "short" }).format(new Date('2015-12-12T11:11:00.000Z')),]
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ module('Integration | Component | create options dates', function(hooks) {
|
|||
await calendarSelect('[data-test-form-element-for="days"]', new Date(2015, 0, 1));
|
||||
await calendarSelect('[data-test-form-element-for="days"]', new Date(2015, 0, 2));
|
||||
assert.deepEqual(
|
||||
this.get('options').map((option) => option.title),
|
||||
this.options.map((option) => option.title),
|
||||
['2015-01-01', '2015-01-02'],
|
||||
'dates are correct'
|
||||
);
|
||||
|
@ -43,7 +43,7 @@ module('Integration | Component | create options dates', function(hooks) {
|
|||
await calendarSelect('[data-test-form-element-for="days"]', new Date(2016, 11, 31));
|
||||
await calendarSelect('[data-test-form-element-for="days"]', new Date(2016, 0, 1));
|
||||
assert.deepEqual(
|
||||
this.get('options').map((option) => option.title),
|
||||
this.options.map((option) => option.title),
|
||||
['2015-01-01', '2015-01-02', '2016-01-01', '2016-12-31'],
|
||||
'dates are sorted'
|
||||
);
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
triggerEvent
|
||||
} from '@ember/test-helpers';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
module('Integration | Component | create options datetime', function(hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
@ -78,7 +78,7 @@ module('Integration | Component | create options datetime', function(hooks) {
|
|||
);
|
||||
assert.equal(
|
||||
find('.days .form-group input').value,
|
||||
moment('2015-01-01T11:11:00.000Z').format('HH:mm'),
|
||||
DateTime.fromISO('2015-01-01T11:11:00.000Z').toFormat('HH:mm'),
|
||||
'it has time in option as value'
|
||||
);
|
||||
});
|
||||
|
@ -93,8 +93,8 @@ module('Integration | Component | create options datetime', function(hooks) {
|
|||
isFindADate: true,
|
||||
isMakeAPoll: false,
|
||||
options: [
|
||||
{ title: moment('2015-01-01T10:11').toISOString() },
|
||||
{ title: moment('2015-01-01T22:22').toISOString() },
|
||||
{ title: DateTime.fromISO('2015-01-01T10:11').toISO() },
|
||||
{ title: DateTime.fromISO('2015-01-01T22:22').toISO() },
|
||||
{ title: '2015-02-02' }
|
||||
]
|
||||
}));
|
||||
|
@ -173,8 +173,8 @@ module('Integration | Component | create options datetime', function(hooks) {
|
|||
isFindADate: true,
|
||||
isMakeAPoll: false,
|
||||
options: [
|
||||
{ title: moment('2015-01-01T11:11').toISOString() },
|
||||
{ title: moment('2015-01-01T22:22').toISOString() }
|
||||
{ title: DateTime.fromISO('2015-01-01T11:11').toISO() },
|
||||
{ title: DateTime.fromISO('2015-01-01T22:22').toISO() }
|
||||
]
|
||||
}));
|
||||
});
|
||||
|
@ -208,7 +208,7 @@ module('Integration | Component | create options datetime', function(hooks) {
|
|||
);
|
||||
assert.equal(
|
||||
this.get('poll.options.firstObject.title'),
|
||||
moment('2015-01-01T22:22').toISOString(),
|
||||
DateTime.fromISO('2015-01-01T22:22').toISO(),
|
||||
'correct option is deleted'
|
||||
);
|
||||
});
|
||||
|
@ -221,7 +221,7 @@ module('Integration | Component | create options datetime', function(hooks) {
|
|||
run(() => {
|
||||
this.set('poll', this.store.createRecord('poll', {
|
||||
options: [
|
||||
{ title: moment().hour(10).minute(0).toISOString() },
|
||||
{ title: DateTime.local().set({ hours: 10, minutes: 0 }).toISO() },
|
||||
{ title: '2015-02-02' },
|
||||
{ title: '2015-03-03' }
|
||||
]
|
||||
|
@ -254,8 +254,8 @@ module('Integration | Component | create options datetime', function(hooks) {
|
|||
run(() => {
|
||||
this.set('poll', this.store.createRecord('poll', {
|
||||
options: [
|
||||
{ title: moment().hour(10).minute(0).toISOString() },
|
||||
{ title: moment().hour(22).minute(0).toISOString() },
|
||||
{ title: DateTime.local().set({ hours: 10, minutes: 0 }).toISO() },
|
||||
{ title: DateTime.local().set({ hours: 22, minutes: 0 }).toISO() },
|
||||
{ title: '2015-02-02' },
|
||||
{ title: '2015-03-03' }
|
||||
]
|
||||
|
@ -280,9 +280,9 @@ module('Integration | Component | create options datetime', function(hooks) {
|
|||
isFindADate: true,
|
||||
isMakeAPoll: false,
|
||||
options: [
|
||||
{ title: moment().hour(10).minute(0).toISOString() },
|
||||
{ title: moment().add(1, 'day').hour(10).minute(0).toISOString() },
|
||||
{ title: moment().add(1, 'day').hour(22).minute(0).toISOString() }
|
||||
{ title: DateTime.local().set({ hours: 10, minutes: 0 }).toISO() },
|
||||
{ title: DateTime.local().plus({ days: 1 }).set({ hours: 10, minutes: 0 }).toISO() },
|
||||
{ title: DateTime.local().plus({ days: 1 }).set({ hours: 22, minutes: 0 }).toISO() }
|
||||
]
|
||||
}));
|
||||
});
|
||||
|
|
|
@ -54,9 +54,9 @@ module('Integration | Component | create options', function(hooks) {
|
|||
let poll;
|
||||
run(() => {
|
||||
poll = this.store.createRecord('poll', {
|
||||
isFindADate: this.get('isFindADate'),
|
||||
isDateTime: this.get('isDateTime'),
|
||||
isMakeAPoll: this.get('isMakeAPoll')
|
||||
isFindADate: this.isFindADate,
|
||||
isDateTime: this.isDateTime,
|
||||
isMakeAPoll: this.isMakeAPoll
|
||||
});
|
||||
});
|
||||
this.set('options', poll.get('options'));
|
||||
|
@ -96,9 +96,9 @@ module('Integration | Component | create options', function(hooks) {
|
|||
let poll;
|
||||
run(() => {
|
||||
poll = this.store.createRecord('poll', {
|
||||
isFindADate: this.get('isFindADate'),
|
||||
isDateTime: this.get('isDateTime'),
|
||||
isMakeAPoll: this.get('isMakeAPoll')
|
||||
isFindADate: this.isFindADate,
|
||||
isDateTime: this.isDateTime,
|
||||
isMakeAPoll: this.isMakeAPoll
|
||||
});
|
||||
});
|
||||
this.set('options', poll.get('options'));
|
||||
|
|
|
@ -53,7 +53,7 @@ module('Integration | Component | create options text', function(hooks) {
|
|||
);
|
||||
|
||||
run(() => {
|
||||
this.get('options').pushObject(
|
||||
this.options.pushObject(
|
||||
EmberObject.create({ title: 'baz' })
|
||||
);
|
||||
});
|
||||
|
@ -79,7 +79,7 @@ module('Integration | Component | create options text', function(hooks) {
|
|||
|
||||
await fillIn(findAll('input')[0], 'baz');
|
||||
assert.equal(
|
||||
this.get('options')[0].get('title'),
|
||||
this.options[0].get('title'),
|
||||
'baz',
|
||||
'option was updated'
|
||||
);
|
||||
|
@ -93,9 +93,9 @@ module('Integration | Component | create options text', function(hooks) {
|
|||
let poll;
|
||||
run(() => {
|
||||
poll = this.store.createRecord('poll', {
|
||||
isFindADate: this.get('isFindADate'),
|
||||
isDateTime: this.get('isDateTime'),
|
||||
isMakeAPoll: this.get('isMakeAPoll'),
|
||||
isFindADate: this.isFindADate,
|
||||
isDateTime: this.isDateTime,
|
||||
isMakeAPoll: this.isMakeAPoll,
|
||||
options: [
|
||||
{ title: 'foo' },
|
||||
{ title: 'bar' }
|
||||
|
@ -125,7 +125,7 @@ module('Integration | Component | create options text', function(hooks) {
|
|||
|
||||
await fillIn(findAll('.form-group input')[1], 'baz')
|
||||
assert.equal(
|
||||
this.get('options').objectAt(1).get('title'),
|
||||
this.options.objectAt(1).get('title'),
|
||||
'baz',
|
||||
'options are observed for new input field'
|
||||
);
|
||||
|
@ -161,7 +161,7 @@ module('Integration | Component | create options text', function(hooks) {
|
|||
'correct input field is deleted'
|
||||
);
|
||||
assert.deepEqual(
|
||||
this.get('options').map((option) => option.get('title')),
|
||||
this.options.map((option) => option.get('title')),
|
||||
['foo', 'baz'],
|
||||
'option is updated'
|
||||
);
|
||||
|
|
65
tests/integration/helpers/format-date-relative-test.js
Normal file
65
tests/integration/helpers/format-date-relative-test.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render } from '@ember/test-helpers';
|
||||
import { hbs } from 'ember-cli-htmlbars';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
module('Integration | Helper | format-date-relative', function(hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test('it formats an ISO date to relative duration from now', async function(assert) {
|
||||
this.set('date', DateTime.local().plus({ hours: 6 }));
|
||||
|
||||
await render(hbs`{{format-date-relative this.date}}`);
|
||||
assert.dom(this.element).hasText('in 6 hours');
|
||||
|
||||
this.set('date', DateTime.local().plus({ weeks: 1 }));
|
||||
assert.dom(this.element).hasText('in 7 days');
|
||||
|
||||
this.set('date', DateTime.local().plus({ weeks: 2 }));
|
||||
assert.dom(this.element).hasText('in 14 days');
|
||||
|
||||
this.set('date', DateTime.local().plus({ weeks: 3 }));
|
||||
assert.dom(this.element).hasText('in 21 days');
|
||||
|
||||
this.set('date', DateTime.local().plus({ months: 1 }));
|
||||
assert.dom(this.element).hasText('in 1 month');
|
||||
|
||||
this.set('date', DateTime.local().plus({ months: 3 }));
|
||||
assert.dom(this.element).hasText('in 3 months');
|
||||
|
||||
this.set('date', DateTime.local().plus({ months: 6 }));
|
||||
assert.dom(this.element).hasText('in 6 months');
|
||||
|
||||
this.set('date', DateTime.local().plus({ years: 1 }));
|
||||
assert.dom(this.element).hasText('in 1 year');
|
||||
});
|
||||
|
||||
test('it formats an ISO date to relative duration to now', async function(assert) {
|
||||
this.set('date', DateTime.local().minus({ hours: 6 }));
|
||||
|
||||
await render(hbs`{{format-date-relative this.date}}`);
|
||||
assert.dom(this.element).hasText('6 hours ago');
|
||||
|
||||
this.set('date', DateTime.local().minus({ weeks: 1 }));
|
||||
assert.dom(this.element).hasText('7 days ago');
|
||||
|
||||
this.set('date', DateTime.local().minus({ weeks: 2 }));
|
||||
assert.dom(this.element).hasText('14 days ago');
|
||||
|
||||
this.set('date', DateTime.local().minus({ weeks: 3 }));
|
||||
assert.dom(this.element).hasText('21 days ago');
|
||||
|
||||
this.set('date', DateTime.local().minus({ months: 1 }));
|
||||
assert.dom(this.element).hasText('1 month ago');
|
||||
|
||||
this.set('date', DateTime.local().minus({ months: 3 }));
|
||||
assert.dom(this.element).hasText('3 months ago');
|
||||
|
||||
this.set('date', DateTime.local().minus({ months: 6 }));
|
||||
assert.dom(this.element).hasText('6 months ago');
|
||||
|
||||
this.set('date', DateTime.local().minus({ years: 1 }));
|
||||
assert.dom(this.element).hasText('1 year ago');
|
||||
});
|
||||
});
|
|
@ -13,20 +13,20 @@ import { calendarSelect } from 'ember-power-calendar/test-support';
|
|||
import { assign } from '@ember/polyfills';
|
||||
import { isArray } from '@ember/array';
|
||||
import { assert } from '@ember/debug';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
function selectDates(selector) {
|
||||
return {
|
||||
isDescriptor: true,
|
||||
async value(dateOrMoments) {
|
||||
async value(dateOrDateTimes) {
|
||||
assert(
|
||||
'selectDates expects an array of date or moment objects as frist argument',
|
||||
isArray(dateOrMoments) && dateOrMoments.every((dateOrMoment) => dateOrMoment instanceof Date || moment.isMoment(dateOrMoment))
|
||||
'selectDates expects an array of date or DateTime (luxon) objects as frist argument',
|
||||
isArray(dateOrDateTimes) && dateOrDateTimes.every((dateOrDateTime) => dateOrDateTime instanceof Date || DateTime.isDateTime(dateOrDateTime))
|
||||
)
|
||||
|
||||
for (let i = 0; i < dateOrMoments.length; i++) {
|
||||
let dateOrMoment = dateOrMoments[i];
|
||||
let date = moment.isMoment(dateOrMoment) ? dateOrMoment.toDate() : dateOrMoment;
|
||||
for (let i = 0; i < dateOrDateTimes.length; i++) {
|
||||
let dateOrDateTime = dateOrDateTimes[i];
|
||||
let date = DateTime.isDateTime(dateOrDateTime) ? dateOrDateTime.toJSDate() : dateOrDateTime;
|
||||
await calendarSelect(selector, date);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { isArray } from '@ember/array';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
module('Unit | Component | create options dates', function(hooks) {
|
||||
setupTest(hooks);
|
||||
|
@ -31,13 +31,11 @@ module('Unit | Component | create options dates', function(hooks) {
|
|||
'array length is correct'
|
||||
);
|
||||
assert.ok(
|
||||
component.selectedDays.every((el) => {
|
||||
return moment.isMoment(el);
|
||||
}),
|
||||
'array elements are moment objects'
|
||||
component.selectedDays.every(DateTime.isDateTime),
|
||||
'array elements are luxon DateTime objects'
|
||||
);
|
||||
assert.deepEqual(
|
||||
component.selectedDays.map((el) => el.format('YYYY-MM-DD')),
|
||||
component.selectedDays.map((day) => day.toISODate()),
|
||||
values.slice(0, 2),
|
||||
'values are correct'
|
||||
);
|
||||
|
@ -45,9 +43,9 @@ module('Unit | Component | create options dates', function(hooks) {
|
|||
|
||||
test('#selectedDays: options representing days with times are mapped correctly', function(assert) {
|
||||
let values = [
|
||||
moment('2014-01-01T12:00').toISOString(),
|
||||
moment('2015-02-02T15:00').toISOString(),
|
||||
moment('2015-02-02T15:00').toISOString(),
|
||||
DateTime.fromISO('2014-01-01T12:00').toISO(),
|
||||
DateTime.fromISO('2015-02-02T15:00').toISO(),
|
||||
DateTime.fromISO('2015-02-02T15:00').toISO(),
|
||||
'2016-03-03',
|
||||
];
|
||||
|
||||
|
@ -65,11 +63,11 @@ module('Unit | Component | create options dates', function(hooks) {
|
|||
'array length is correct'
|
||||
);
|
||||
assert.ok(
|
||||
component.selectedDays.every(moment.isMoment),
|
||||
'array elements are moment objects'
|
||||
component.selectedDays.every(DateTime.isDateTime),
|
||||
'array elements are Luxon DateTime objects'
|
||||
);
|
||||
assert.deepEqual(
|
||||
component.selectedDays.map((day) => day.format('YYYY-MM-DD')),
|
||||
component.selectedDays.map((day) => day.toISODate()),
|
||||
['2014-01-01', '2015-02-02', '2016-03-03'],
|
||||
'dates are correct'
|
||||
);
|
||||
|
@ -82,7 +80,7 @@ module('Unit | Component | create options dates', function(hooks) {
|
|||
|
||||
let component = this.owner.factoryFor('component:create-options-dates').create({ options });
|
||||
component.actions.daysSelected.bind(component)({
|
||||
moment: values.map((_) => moment(_)),
|
||||
datetime: values.map((_) => DateTime.fromISO(_)),
|
||||
});
|
||||
|
||||
assert.ok(isArray(options), 'options is still an array');
|
||||
|
@ -91,21 +89,18 @@ module('Unit | Component | create options dates', function(hooks) {
|
|||
options.every(({ title }) => typeof title === 'string'),
|
||||
'title property of options are strings'
|
||||
);
|
||||
assert.ok(
|
||||
options.every(({ title }) => moment(title, 'YYYY-MM-DD', true).isValid()),
|
||||
'title property of options are ISO-8601 date string without time'
|
||||
);
|
||||
assert.deepEqual(
|
||||
options.map(({ title }) => title), values.sort(),
|
||||
options.map(({ title }) => title),
|
||||
['1917-10-25', '1918-11-09'],
|
||||
'options having correct value and are sorted'
|
||||
);
|
||||
});
|
||||
|
||||
test('action #daysSelected: existing times are preserved if new day is selected', function(assert) {
|
||||
let existing = [
|
||||
moment('2015-01-01T11:11').toISOString(),
|
||||
moment('2015-01-01T22:22').toISOString(),
|
||||
moment('2015-06-06T08:08').toISOString(),
|
||||
DateTime.fromISO('2015-01-01T11:11').toISO(),
|
||||
DateTime.fromISO('2015-01-01T22:22').toISO(),
|
||||
DateTime.fromISO('2015-06-06T08:08').toISO(),
|
||||
'2016-01-01'
|
||||
];
|
||||
let additional = '2016-06-06';
|
||||
|
@ -118,7 +113,7 @@ module('Unit | Component | create options dates', function(hooks) {
|
|||
});
|
||||
|
||||
component.actions.daysSelected.bind(component)({
|
||||
moment: merged.map((_) => moment(_)),
|
||||
datetime: merged.map((_) => DateTime.fromISO(_)),
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
|
@ -130,9 +125,9 @@ module('Unit | Component | create options dates', function(hooks) {
|
|||
|
||||
test('action #daysSelected: existing times are preserved if day gets unselected', function(assert) {
|
||||
let existing = [
|
||||
moment('2015-01-01T11:11').toISOString(),
|
||||
moment('2015-01-01T22:22').toISOString(),
|
||||
moment('2015-06-06T08:08').toISOString(),
|
||||
DateTime.fromISO('2015-01-01T11:11').toISO(),
|
||||
DateTime.fromISO('2015-01-01T22:22').toISO(),
|
||||
DateTime.fromISO('2015-06-06T08:08').toISO(),
|
||||
'2016-01-01'
|
||||
];
|
||||
let reduced = existing.slice();
|
||||
|
@ -144,7 +139,7 @@ module('Unit | Component | create options dates', function(hooks) {
|
|||
});
|
||||
|
||||
component.actions.daysSelected.bind(component)({
|
||||
moment: reduced.map((_) => moment(_)),
|
||||
datetime: reduced.map((_) => DateTime.fromISO(_)),
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { run } from '@ember/runloop';
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
import { settled } from '@ember/test-helpers';
|
||||
|
||||
module('Unit | Component | create options datetime', function(hooks) {
|
||||
|
@ -15,9 +15,9 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
let component = this.owner.factoryFor('component:create-options-datetime').create();
|
||||
let a, b, c, d, e;
|
||||
run(() => {
|
||||
a = this.store.createFragment('option', { title: moment('2015-01-01T01:01:00.000').toISOString() });
|
||||
b = this.store.createFragment('option', { title: moment('2015-01-01T11:11:00.000').toISOString() });
|
||||
c = this.store.createFragment('option', { title: moment('2015-02-02T11:11:00.000').toISOString() });
|
||||
a = this.store.createFragment('option', { title: DateTime.fromISO('2015-01-01T01:01:00.000').toISO() });
|
||||
b = this.store.createFragment('option', { title: DateTime.fromISO('2015-01-01T11:11:00.000').toISO() });
|
||||
c = this.store.createFragment('option', { title: DateTime.fromISO('2015-02-02T11:11:00.000').toISO() });
|
||||
d = this.store.createFragment('option', { title: '2015-02-02' });
|
||||
e = this.store.createFragment('option', { title: '2015-02-03' });
|
||||
component.set('dates', [a, b, c, d, e]);
|
||||
|
@ -26,8 +26,8 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
assert.deepEqual(
|
||||
component.get('dates').map((date) => date.get('title')),
|
||||
[
|
||||
moment('2015-01-01T01:01:00.000').toISOString(),
|
||||
moment('2015-02-02T11:11:00.000').toISOString(),
|
||||
DateTime.fromISO('2015-01-01T01:01:00.000').toISO(),
|
||||
DateTime.fromISO('2015-02-02T11:11:00.000').toISO(),
|
||||
'2015-02-02',
|
||||
'2015-02-03'
|
||||
],
|
||||
|
@ -37,8 +37,8 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
assert.deepEqual(
|
||||
component.get('dates').map((date) => date.get('title')),
|
||||
[
|
||||
moment('2015-01-01T01:01:00.000').toISOString(),
|
||||
moment('2015-02-02T11:11:00.000').toISOString(),
|
||||
DateTime.fromISO('2015-01-01T01:01:00.000').toISO(),
|
||||
DateTime.fromISO('2015-02-02T11:11:00.000').toISO(),
|
||||
'2015-02-03'
|
||||
],
|
||||
'date get deleted if there is another date with same day (date does not have a time)'
|
||||
|
@ -49,7 +49,7 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
assert.deepEqual(
|
||||
component.get('dates').map((date) => date.get('title')),
|
||||
[
|
||||
moment('2015-01-01T01:01:00.000').toISOString(),
|
||||
DateTime.fromISO('2015-01-01T01:01:00.000').toISO(),
|
||||
'2015-02-02',
|
||||
'2015-02-03'
|
||||
],
|
||||
|
@ -59,7 +59,7 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
assert.deepEqual(
|
||||
component.get('dates').map((date) => date.get('title')),
|
||||
[
|
||||
moment('2015-01-01T01:01:00.000').toISOString(),
|
||||
DateTime.fromISO('2015-01-01T01:01:00.000').toISO(),
|
||||
'2015-02-02',
|
||||
'2015-02-03'
|
||||
],
|
||||
|
@ -73,9 +73,9 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
// have to set dates in local time and than convert to ISO 8601 strings
|
||||
// because otherwise test could fail caused by timezone
|
||||
run(() => {
|
||||
a = this.store.createFragment('option', { title: moment('2015-01-01T01:01:00').toISOString() });
|
||||
b = this.store.createFragment('option', { title: moment('2015-01-01T11:11:00').toISOString() });
|
||||
c = this.store.createFragment('option', { title: moment('2015-02-02T01:01:00').toISOString() });
|
||||
a = this.store.createFragment('option', { title: DateTime.fromISO('2015-01-01T01:01:00').toISO() });
|
||||
b = this.store.createFragment('option', { title: DateTime.fromISO('2015-01-01T11:11:00').toISO() });
|
||||
c = this.store.createFragment('option', { title: DateTime.fromISO('2015-02-02T01:01:00').toISO() });
|
||||
component.set('dates', [a, b, c]);
|
||||
});
|
||||
assert.equal(
|
||||
|
@ -85,13 +85,13 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
);
|
||||
assert.deepEqual(
|
||||
component.get('groupedDates.firstObject.items').map((item) => {
|
||||
return item.get('date').toISOString();
|
||||
return item.get('title');
|
||||
}),
|
||||
[a.get('title'), b.get('title')],
|
||||
'first dates having same day are grouped together'
|
||||
);
|
||||
assert.equal(
|
||||
component.get('groupedDates.lastObject.items.firstObject.date').toISOString(),
|
||||
component.get('groupedDates.lastObject.items.firstObject.title'),
|
||||
[c.get('title')],
|
||||
'last date having another day is in a separate group'
|
||||
);
|
||||
|
@ -99,16 +99,16 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
|
||||
test('bindings are working on grouped datetimes', function(assert) {
|
||||
let component = this.owner.factoryFor('component:create-options-datetime').create();
|
||||
let baseDate = moment('2015-01-01T11:11');
|
||||
let baseDate = DateTime.fromISO('2015-01-01T11:11');
|
||||
|
||||
component.set('dates', [
|
||||
this.store.createFragment('option', {
|
||||
title: baseDate.toISOString()
|
||||
title: baseDate.toISO()
|
||||
})
|
||||
]);
|
||||
assert.equal(
|
||||
component.get('groupedDates.firstObject.items.firstObject.time'),
|
||||
baseDate.format('HH:mm'),
|
||||
baseDate.toISOTime('HH:mm').substr(0, 5),
|
||||
'time is correct before'
|
||||
);
|
||||
|
||||
|
@ -118,13 +118,13 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
);
|
||||
assert.equal(
|
||||
component.get('dates.firstObject.title'),
|
||||
moment(baseDate).hour(0).minute(0).toISOString(),
|
||||
baseDate.set({ hours: 0, minutes: 0 }).toISO(),
|
||||
'option is updated after time changed on grouped datetimes'
|
||||
);
|
||||
|
||||
component.get('dates').pushObject(
|
||||
this.store.createFragment('option', {
|
||||
title: baseDate.add(1, 'hour').add(1, 'minute').toISOString(),
|
||||
title: baseDate.plus({ hours: 1, minutes: 1 }).toISO(),
|
||||
})
|
||||
);
|
||||
assert.equal(
|
||||
|
@ -139,7 +139,7 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
);
|
||||
|
||||
component.get('dates').pushObject(
|
||||
this.store.createFragment('option', { title: moment('2015-02-02T01:01').toISOString() })
|
||||
this.store.createFragment('option', { title: DateTime.fromISO('2015-02-02T01:01').toISO() })
|
||||
);
|
||||
assert.equal(
|
||||
component.get('groupedDates.length'),
|
||||
|
@ -156,10 +156,10 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
test('adopt times of first day - simple', async function(assert) {
|
||||
let poll = this.store.createRecord('poll', {
|
||||
options: [
|
||||
{ title: moment('2015-01-01T11:11:00.000').toISOString() },
|
||||
{ title: moment('2015-01-01T22:22:00.000').toISOString() },
|
||||
{ title: moment('2015-01-02').toISOString() },
|
||||
{ title: moment('2015-01-03').toISOString() }
|
||||
{ title: DateTime.fromISO('2015-01-01T11:11:00.000').toISO() },
|
||||
{ title: DateTime.fromISO('2015-01-01T22:22:00.000').toISO() },
|
||||
{ title: DateTime.fromISO('2015-01-02').toISO() },
|
||||
{ title: DateTime.fromISO('2015-01-03').toISO() }
|
||||
]
|
||||
});
|
||||
let component = this.owner.factoryFor('component:create-options-datetime').create({
|
||||
|
@ -171,12 +171,12 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
assert.deepEqual(
|
||||
component.get('dates').map((option) => option.get('title')),
|
||||
[
|
||||
moment('2015-01-01T11:11:00.000').toISOString(),
|
||||
moment('2015-01-01T22:22:00.000').toISOString(),
|
||||
moment('2015-01-02T11:11:00.000').toISOString(),
|
||||
moment('2015-01-02T22:22:00.000').toISOString(),
|
||||
moment('2015-01-03T11:11:00.000').toISOString(),
|
||||
moment('2015-01-03T22:22:00.000').toISOString()
|
||||
DateTime.fromISO('2015-01-01T11:11:00.000').toISO(),
|
||||
DateTime.fromISO('2015-01-01T22:22:00.000').toISO(),
|
||||
DateTime.fromISO('2015-01-02T11:11:00.000').toISO(),
|
||||
DateTime.fromISO('2015-01-02T22:22:00.000').toISO(),
|
||||
DateTime.fromISO('2015-01-03T11:11:00.000').toISO(),
|
||||
DateTime.fromISO('2015-01-03T22:22:00.000').toISO()
|
||||
],
|
||||
'times adopted correctly'
|
||||
);
|
||||
|
@ -185,14 +185,14 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
test('adopt times of first day - having times on the other days', async function(assert) {
|
||||
let poll = this.store.createRecord('poll', {
|
||||
options: [
|
||||
{ title: moment('2015-01-01T11:11:00.000').toISOString() },
|
||||
{ title: moment('2015-01-01T22:22:00.000').toISOString() },
|
||||
{ title: moment('2015-01-02T09:11:00.000').toISOString() },
|
||||
{ title: moment('2015-01-03T01:11:00.000').toISOString() },
|
||||
{ title: moment('2015-01-03T11:11:00.000').toISOString() },
|
||||
{ title: moment('2015-01-04T02:11:00.000').toISOString() },
|
||||
{ title: moment('2015-01-04T05:11:00.000').toISOString() },
|
||||
{ title: moment('2015-01-04T12:11:00.000').toISOString() }
|
||||
{ title: DateTime.fromISO('2015-01-01T11:11:00.000').toISO() },
|
||||
{ title: DateTime.fromISO('2015-01-01T22:22:00.000').toISO() },
|
||||
{ title: DateTime.fromISO('2015-01-02T09:11:00.000').toISO() },
|
||||
{ title: DateTime.fromISO('2015-01-03T01:11:00.000').toISO() },
|
||||
{ title: DateTime.fromISO('2015-01-03T11:11:00.000').toISO() },
|
||||
{ title: DateTime.fromISO('2015-01-04T02:11:00.000').toISO() },
|
||||
{ title: DateTime.fromISO('2015-01-04T05:11:00.000').toISO() },
|
||||
{ title: DateTime.fromISO('2015-01-04T12:11:00.000').toISO() }
|
||||
]
|
||||
});
|
||||
let component = this.owner.factoryFor('component:create-options-datetime').create({
|
||||
|
@ -204,14 +204,14 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
assert.deepEqual(
|
||||
component.get('dates').map((option) => option.get('title')),
|
||||
[
|
||||
moment('2015-01-01T11:11:00.000').toISOString(),
|
||||
moment('2015-01-01T22:22:00.000').toISOString(),
|
||||
moment('2015-01-02T11:11:00.000').toISOString(),
|
||||
moment('2015-01-02T22:22:00.000').toISOString(),
|
||||
moment('2015-01-03T11:11:00.000').toISOString(),
|
||||
moment('2015-01-03T22:22:00.000').toISOString(),
|
||||
moment('2015-01-04T11:11:00.000').toISOString(),
|
||||
moment('2015-01-04T22:22:00.000').toISOString()
|
||||
DateTime.fromISO('2015-01-01T11:11:00.000').toISO(),
|
||||
DateTime.fromISO('2015-01-01T22:22:00.000').toISO(),
|
||||
DateTime.fromISO('2015-01-02T11:11:00.000').toISO(),
|
||||
DateTime.fromISO('2015-01-02T22:22:00.000').toISO(),
|
||||
DateTime.fromISO('2015-01-03T11:11:00.000').toISO(),
|
||||
DateTime.fromISO('2015-01-03T22:22:00.000').toISO(),
|
||||
DateTime.fromISO('2015-01-04T11:11:00.000').toISO(),
|
||||
DateTime.fromISO('2015-01-04T22:22:00.000').toISO()
|
||||
],
|
||||
'times adopted correctly'
|
||||
);
|
||||
|
@ -222,8 +222,8 @@ module('Unit | Component | create options datetime', function(hooks) {
|
|||
options: [
|
||||
{ title: '2015-01-01' },
|
||||
{ title: '2015-01-02' },
|
||||
{ title: moment('2015-01-03T11:00').toISOString() },
|
||||
{ title: moment('2015-01-03T15:00').toISOString() }
|
||||
{ title: DateTime.fromISO('2015-01-03T11:00').toISO() },
|
||||
{ title: DateTime.fromISO('2015-01-03T15:00').toISO() }
|
||||
]
|
||||
});
|
||||
let component = this.owner.factoryFor('component:create-options-datetime').create({
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { run } from '@ember/runloop';
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
module('Unit | Component | create options', function(hooks) {
|
||||
setupTest(hooks);
|
||||
|
@ -157,7 +157,7 @@ module('Unit | Component | create options', function(hooks) {
|
|||
);
|
||||
run(() => {
|
||||
let option = this.store.createFragment('option', {
|
||||
title: moment().add('1', 'day').format('YYYY-MM-DD')
|
||||
title: DateTime.local().plus({ days: 1 }).toISODate(),
|
||||
});
|
||||
poll.get('options').pushObject(option);
|
||||
component.get('options').pushObject(option);
|
||||
|
@ -166,18 +166,5 @@ module('Unit | Component | create options', function(hooks) {
|
|||
component.get('validations.isValid'),
|
||||
'valid if there is atleast one valid date'
|
||||
);
|
||||
/*
|
||||
Ember.run(() => {
|
||||
let option = this.store.createFragment('option', {
|
||||
title: moment().add('1', 'day').hour(22).minute(30).seconds(0).milliseconds(0).toISOString()
|
||||
});
|
||||
poll.get('options').pushObject(option);
|
||||
component.get('options').pushObject(option);
|
||||
});
|
||||
assert.notOk(
|
||||
component.get('validations.isValid'),
|
||||
'invalid if there is a option without time for a day with has another option with time specified'
|
||||
);
|
||||
*/
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,21 +1,22 @@
|
|||
import { run } from '@ember/runloop';
|
||||
import EmberObject from '@ember/object';
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
module('Unit | Controller | create/options datetime', function(hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('normalize options - remove days without time if there is another option with a time for that day', function(assert) {
|
||||
const dirtyOption = EmberObject.create({ title: '2015-01-01' });
|
||||
test('normalize options - remove days without time if there is another option with a time for that day', function (assert) {
|
||||
const StoreService = this.owner.lookup('service:store');
|
||||
|
||||
const dirtyOption = StoreService.createRecord('option', { title: '2015-01-01' });
|
||||
let controller = this.owner.factoryFor('controller:create/options-datetime').create({
|
||||
model: {
|
||||
options: [
|
||||
EmberObject.create({ title: moment('2015-01-01T12:00').toISOString() }),
|
||||
StoreService.createRecord('option', { title: DateTime.fromISO('2015-01-01T12:00').toISO() }),
|
||||
dirtyOption,
|
||||
EmberObject.create({ title: '2017-11-11' }),
|
||||
EmberObject.create({ title: moment('2018-04-04T11:11').toISOString() })
|
||||
StoreService.createRecord('option', { title: '2017-11-11' }),
|
||||
StoreService.createRecord('option', { title: DateTime.fromISO('2018-04-04T11:11').toISO() })
|
||||
]
|
||||
}
|
||||
});
|
||||
|
@ -31,18 +32,20 @@ module('Unit | Controller | create/options datetime', function(hooks) {
|
|||
);
|
||||
});
|
||||
|
||||
test('normalize options - sort them', function(assert) {
|
||||
const dateA = moment().hour(5).toISOString();
|
||||
const dateB = moment().hour(10).toISOString();
|
||||
const dateC = moment().hour(22).toISOString();
|
||||
const dateD = moment().add(1, 'day').toISOString();
|
||||
test('normalize options - sort them', function (assert) {
|
||||
const StoreService = this.owner.lookup('service:store');
|
||||
|
||||
const dateA = DateTime.local().set({ hours: 5 }).toISO();
|
||||
const dateB = DateTime.local().set({ hours: 10 }).toISO();
|
||||
const dateC = DateTime.local().set({ hours: 22 }).toISO();
|
||||
const dateD = DateTime.local().plus({ days: 1 }).toISO();
|
||||
let controller = this.owner.factoryFor('controller:create/options-datetime').create({
|
||||
model: {
|
||||
options: [
|
||||
EmberObject.create({ title: dateB }),
|
||||
EmberObject.create({ title: dateA }),
|
||||
EmberObject.create({ title: dateC }),
|
||||
EmberObject.create({ title: dateD })
|
||||
StoreService.createRecord('option', { title: dateB }),
|
||||
StoreService.createRecord('option', { title: dateA }),
|
||||
StoreService.createRecord('option', { title: dateC }),
|
||||
StoreService.createRecord('option', { title: dateD })
|
||||
]
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
module('Unit | Controller | poll', function(hooks) {
|
||||
setupTest(hooks);
|
||||
|
@ -16,13 +16,13 @@ module('Unit | Controller | poll', function(hooks) {
|
|||
'is false if expirationDate is undefined'
|
||||
);
|
||||
|
||||
controller.set('model.expirationDate', moment().add(1, 'week').toISOString());
|
||||
controller.set('model.expirationDate', DateTime.local().plus({ weeks: 1 }).toISO());
|
||||
assert.ok(
|
||||
controller.get('showExpirationWarning'),
|
||||
'is true if expirationDate is less than 2 weeks in future'
|
||||
);
|
||||
|
||||
controller.set('model.expirationDate', moment().add(1, 'month').toISOString());
|
||||
controller.set('model.expirationDate', DateTime.local().plus({ months: 1 }).toISO());
|
||||
assert.notOk(
|
||||
controller.get('showExpirationWarning'),
|
||||
'is false if expirationDate is more than 2 weeks in future'
|
||||
|
|
|
@ -2,89 +2,12 @@ import { run } from '@ember/runloop';
|
|||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
import { setupIntl } from 'ember-intl/test-support';
|
||||
import moment from 'moment';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
module('Unit | Model | option', function(hooks) {
|
||||
setupTest(hooks);
|
||||
setupIntl(hooks, 'en');
|
||||
|
||||
hooks.beforeEach(function() {
|
||||
moment.locale('en');
|
||||
});
|
||||
|
||||
test('date property (get)', function(assert) {
|
||||
let option = run(() => this.owner.lookup('service:store').createRecord('option', {
|
||||
title: '2015-01-01'
|
||||
}));
|
||||
assert.ok(
|
||||
moment.isMoment(option.get('date')),
|
||||
'returns a moment instance if title is an ISO 8601 day string'
|
||||
);
|
||||
assert.equal(
|
||||
option.get('date').format('YYYY-MM-DD HH:mm:ss.SSS'),
|
||||
'2015-01-01 00:00:00.000',
|
||||
'string to date conversion is correct for ISO 8601 day string'
|
||||
);
|
||||
|
||||
run(() => {
|
||||
option.set('title', '2015-01-01T11:11:00.000Z');
|
||||
});
|
||||
assert.ok(
|
||||
moment.isMoment(option.get('date')),
|
||||
'returns a moment instance if title is an ISO 8601 datetime string'
|
||||
);
|
||||
assert.equal(
|
||||
option.get('date').toISOString(),
|
||||
'2015-01-01T11:11:00.000Z',
|
||||
'string to date conversion is correct for ISO 8601 datetime string'
|
||||
);
|
||||
|
||||
run(() => {
|
||||
option.set('title', null);
|
||||
});
|
||||
assert.equal(
|
||||
option.get('date'),
|
||||
undefined,
|
||||
'returns undefined if title is empty'
|
||||
);
|
||||
|
||||
run(() => {
|
||||
option.set('title', 'abc');
|
||||
});
|
||||
assert.equal(
|
||||
option.get('date'),
|
||||
undefined,
|
||||
'returns undefined if title is not a valid ISO 8601 date string'
|
||||
);
|
||||
|
||||
run(() => {
|
||||
option.set('title', '2015');
|
||||
});
|
||||
assert.equal(
|
||||
option.get('date'),
|
||||
undefined,
|
||||
'returns undefined if title ISO 8601 string only contains a year'
|
||||
);
|
||||
|
||||
run(() => {
|
||||
option.set('title', '2015-01');
|
||||
});
|
||||
assert.equal(
|
||||
option.get('date'),
|
||||
undefined,
|
||||
'returns undefined if title ISO 8601 string only contains a year and a month'
|
||||
);
|
||||
|
||||
run(() => {
|
||||
option.set('title', '2013W06');
|
||||
});
|
||||
assert.equal(
|
||||
option.get('date'),
|
||||
undefined,
|
||||
'returns undefined if title ISO 8601 string only contains a year and a week'
|
||||
);
|
||||
});
|
||||
|
||||
test('day property (get)', function(assert) {
|
||||
let option = run(() => this.owner.lookup('service:store').createRecord('option', {
|
||||
title: '2015-01-01'
|
||||
|
@ -100,7 +23,7 @@ module('Unit | Model | option', function(hooks) {
|
|||
});
|
||||
assert.equal(
|
||||
option.get('day'),
|
||||
moment('2015-01-01T11:11:00.000Z').format('YYYY-MM-DD'),
|
||||
DateTime.fromISO('2015-01-01T11:11:00.000Z').toISODate(),
|
||||
'returns ISO 8601 day string if title is ISO 8601 datetime string'
|
||||
);
|
||||
|
||||
|
@ -123,44 +46,6 @@ module('Unit | Model | option', function(hooks) {
|
|||
);
|
||||
});
|
||||
|
||||
test('dayFormatted property (get)', function(assert) {
|
||||
let option = run(() => this.owner.lookup('service:store').createRecord('option', {
|
||||
title: '2015-01-01'
|
||||
}));
|
||||
assert.equal(
|
||||
option.get('dayFormatted'),
|
||||
'Thursday, January 1, 2015',
|
||||
'returns formatted date if title is ISO 8601 day string'
|
||||
);
|
||||
|
||||
run(() => {
|
||||
option.set('title', moment('2015-01-01').toISOString());
|
||||
});
|
||||
assert.equal(
|
||||
option.get('dayFormatted'),
|
||||
'Thursday, January 1, 2015',
|
||||
'returns formatted date if title is ISO 8601 datetime string'
|
||||
);
|
||||
|
||||
run(() => {
|
||||
option.set('intl.locale', 'de');
|
||||
});
|
||||
assert.equal(
|
||||
option.get('dayFormatted'),
|
||||
'Donnerstag, 1. Januar 2015',
|
||||
'observes locale changes'
|
||||
);
|
||||
|
||||
run(() => {
|
||||
option.set('title', 'abc');
|
||||
});
|
||||
assert.equal(
|
||||
option.get('dayFormatted'),
|
||||
undefined,
|
||||
'returns undfined if title is not a valid ISO 8601 string'
|
||||
);
|
||||
});
|
||||
|
||||
test('hasTime property', function(assert) {
|
||||
let option = run(() => this.owner.lookup('service:store').createRecord('option', {
|
||||
title: '2015-01-01T11:11:00.000Z'
|
||||
|
@ -182,7 +67,7 @@ module('Unit | Model | option', function(hooks) {
|
|||
}));
|
||||
assert.equal(
|
||||
option.get('time'),
|
||||
moment('2015-01-01T11:11:00.000Z').format('HH:mm'),
|
||||
DateTime.fromISO('2015-01-01T11:11:00.000Z').toFormat('HH:mm'),
|
||||
'returns time if title is ISO 8601 datetime string'
|
||||
);
|
||||
|
||||
|
@ -215,7 +100,7 @@ module('Unit | Model | option', function(hooks) {
|
|||
});
|
||||
assert.equal(
|
||||
option.get('title'),
|
||||
moment('2015-01-01T11:00').toISOString(),
|
||||
DateTime.fromISO('2015-01-01T11:00').toISO(),
|
||||
'sets title according to time'
|
||||
);
|
||||
|
||||
|
|
|
@ -57,42 +57,22 @@ module('Unit | Validator | iso8601', function(hooks) {
|
|||
);
|
||||
});
|
||||
|
||||
test('valid iso8601 string formats could be defined by options.validFormats', function(assert) {
|
||||
test('other iso8601 strings', function(assert) {
|
||||
let validator = this.owner.lookup('validator:iso8601');
|
||||
const buildOptions = validator.buildOptions({
|
||||
validFormats: [
|
||||
'YYYY-MM-DD',
|
||||
'YYYY-MM-DDTHH:mmZ',
|
||||
'YYYY-MM-DDTHH:mm:ssZ'
|
||||
]
|
||||
}, {});
|
||||
assert.notOk(
|
||||
validator.validate('1945-05-08') === true,
|
||||
'iso 8601 date string is invalid by default'
|
||||
);
|
||||
assert.equal(
|
||||
validator.validate('1945-05-08', buildOptions),
|
||||
assert.strictEqual(
|
||||
validator.validate('1945-05-08'),
|
||||
true,
|
||||
'iso 8601 date string is valid if it\'s in validFormats options'
|
||||
'iso 8601 date string is valid'
|
||||
);
|
||||
assert.notOk(
|
||||
validator.validate('1945-05-08T23:01Z') === true,
|
||||
'iso 8601 datetime string in UTC is invalid by default'
|
||||
);
|
||||
assert.equal(
|
||||
validator.validate('1945-05-08T23:01Z', buildOptions),
|
||||
assert.strictEqual(
|
||||
validator.validate('1945-05-08T23:01Z'),
|
||||
true,
|
||||
'iso 8601 datetime string in UTC is valid if it\'s in validFormats options'
|
||||
'iso 8601 datetime string in UTC is valid'
|
||||
);
|
||||
assert.notOk(
|
||||
validator.validate('1945-05-08T23:01:00Z') === true,
|
||||
assert.strictEqual(
|
||||
validator.validate('1945-05-08T23:01:00Z'),
|
||||
true,
|
||||
'iso 8601 datetime string with seconds in UTC is invalid by default'
|
||||
);
|
||||
assert.equal(
|
||||
validator.validate('1945-05-08T23:01:00Z', buildOptions),
|
||||
true,
|
||||
'iso 8601 datetime string with seconds in UTC is valid if it\'s in validFormats options'
|
||||
'iso 8601 datetime string with seconds in UTC is valid'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue