decide.nolog.cz/app/controllers/poll/participation.js

241 lines
6.6 KiB
JavaScript
Raw Normal View History

import classic from 'ember-classic-decorator';
2018-12-29 01:27:37 +01:00
import { inject as service } from '@ember/service';
import { not, readOnly } from '@ember/object/computed';
2018-12-29 01:27:37 +01:00
import Controller, { inject as controller } from '@ember/controller';
import { getOwner } from '@ember/application';
import { isPresent, 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';
2016-01-28 23:48:14 +01:00
const validCollection = function(collection) {
// return false if any object in collection is inValid
return !collection.any((object) => {
return object.get('validations.isInvalid');
});
};
2016-01-28 23:48:14 +01:00
const Validations = buildValidations({
name: [
validator('presence', {
presence: true,
2018-12-29 01:27:37 +01:00
disabled: readOnly('model.anonymousUser'),
dependentKeys: ['model.intl.locale']
}),
validator('unique', {
parent: 'poll',
attributeInParent: 'users',
dependentKeys: ['model.poll.users.[]', 'model.poll.users.@each.name', 'model.intl.locale'],
2018-12-29 01:27:37 +01:00
disable: readOnly('model.anonymousUser'),
messageKey: 'errors.uniqueName',
ignoreNewRecords: true,
})
],
selections: [
validator('collection', true),
// all selection objects must be valid
// if forceAnswer is true in poll settings
validator(validCollection, {
dependentKeys: ['model.forceAnswer', 'model.selections.[]', 'model.selections.@each.value', 'model.intl.locale']
})
]
});
2016-01-28 23:48:14 +01:00
const SelectionValidations = buildValidations({
value: validator('presence', {
presence: true,
2018-12-29 01:27:37 +01:00
disabled: not('model.forceAnswer'),
messageKey: computed('model.isFreeText', function() {
return this.get('model.isFreeText') ? 'errors.present' : 'errors.answerRequired';
}),
dependentKeys: ['model.intl.locale']
})
});
@classic
class SelectionObject extends EmberObject.extend(SelectionValidations) {
@service intl;
value = null;
init() {
super.init(...arguments);
// current locale needs to be consumed in order to be observeable
// for localization of validation messages
this.intl.locale;
}
}
export default Controller.extend(Validations, {
actions: {
async submit() {
if (!this.get('validations.isValid')) {
return;
}
let poll = this.poll;
let selections = this.selections.map(({ value }) => {
if (value === null) {
return {};
}
if (this.isFreeText) {
return {
label: value,
};
}
// map selection to answer if it's not freetext
let answer = poll.answers.findBy('type', value);
let { icon, label, labelTranslation, type } = answer;
return {
icon,
label,
labelTranslation,
type,
};
});
let user = this.store.createRecord('user', {
creationDate: new Date(),
name: this.name,
poll,
selections,
version: config.APP.version,
});
this.set('newUserRecord', user);
await this.actions.save.bind(this)();
},
async save() {
let user = this.newUserRecord;
try {
await user.save();
this.set('savingFailed', false);
} catch (error) {
// couldn't save user model
this.set('savingFailed', true);
return;
}
// reset form
this.set('name', '');
this.selections.forEach((selection) => {
selection.set('value', null);
});
this.transitionToRoute('poll.evaluation', this.model, {
queryParams: { encryptionKey: this.encryption.key }
});
}
},
anonymousUser: readOnly('poll.anonymousUser'),
currentLocale: readOnly('intl.locale'),
2018-12-29 01:27:37 +01:00
encryption: service(),
forceAnswer: readOnly('poll.forceAnswer'),
intl: service(),
init() {
2018-12-29 01:27:37 +01:00
this._super(...arguments);
// current locale needs to be consumed in order to be observeable
// for localization of validation messages
this.intl.locale;
},
isFreeText: readOnly('poll.isFreeText'),
isFindADate: readOnly('poll.isFindADate'),
2018-12-29 01:27:37 +01:00
momentLongDayFormat: readOnly('pollController.momentLongDayFormat'),
name: '',
options: readOnly('poll.options'),
poll: readOnly('model'),
2018-12-29 01:27:37 +01:00
pollController: controller('poll'),
possibleAnswers: computed('poll.answers', function() {
return this.get('poll.answers').map((answer) => {
const owner = getOwner(this);
2015-11-24 00:53:03 +01:00
const AnswerObject = EmberObject.extend({
2015-11-24 00:53:03 +01:00
icon: answer.get('icon'),
type: answer.get('type')
});
if (!isEmpty(answer.get('labelTranslation'))) {
return AnswerObject.extend({
intl: service(),
label: computed('intl.locale', function() {
return this.intl.t(this.labelTranslation);
2015-11-24 00:53:03 +01:00
}),
labelTranslation: answer.get('labelTranslation'),
}).create(owner.ownerInjection());
} else {
2015-11-24 00:53:03 +01:00
return AnswerObject.extend({
label: answer.get('label')
});
}
});
}),
savingFailed: false,
selections: computed('options', 'pollController.dates', function() {
2018-12-29 20:35:04 +01:00
let options = this.options;
let isFindADate = this.isFindADate;
2016-01-28 23:48:14 +01:00
let lastDate;
return options.map((option) => {
2016-01-28 23:48:14 +01:00
let labelValue;
let momentFormat;
let value = option.get('title');
// format label
if (isFindADate) {
let hasTime = value.length > 10; // 'YYYY-MM-DD'.length === 10
2018-12-29 20:35:04 +01:00
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;
}
2016-01-28 23:48:14 +01:00
} else {
labelValue = value;
}
// 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(), {
2016-01-28 23:48:14 +01:00
labelValue,
momentFormat,
// forceAnswer and isFreeText must be included in model
// cause otherwise validations can't depend on it
forceAnswer: this.forceAnswer,
isFreeText: this.isFreeText,
});
});
}),
2018-12-29 01:27:37 +01:00
timezone: readOnly('pollController.timezone')
});