routable tabs in poll view for participation and evaluation
This commit is contained in:
parent
6bcf2fb088
commit
858b75e543
18 changed files with 892 additions and 723 deletions
|
@ -1,111 +1,11 @@
|
||||||
import Ember from "ember";
|
import Ember from "ember";
|
||||||
import EmberValidations from 'ember-validations';
|
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
/* global jstz */
|
/* global jstz */
|
||||||
|
|
||||||
export default Ember.Controller.extend(EmberValidations.Mixin, {
|
export default Ember.Controller.extend({
|
||||||
encryption: Ember.inject.service(),
|
encryption: Ember.inject.service(),
|
||||||
encryptionKey: '',
|
encryptionKey: '',
|
||||||
newUserName: '',
|
|
||||||
queryParams: ['encryptionKey'],
|
queryParams: ['encryptionKey'],
|
||||||
usersSorting: ['creationDate'],
|
|
||||||
sortedUsers: Ember.computed.sort('model.users', 'usersSorting'),
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
addNewUser: function(){
|
|
||||||
var newUser = {
|
|
||||||
name: this.get('newUserName'),
|
|
||||||
selections: []
|
|
||||||
};
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
// work-a-round cause value is not retrived otherwise
|
|
||||||
this.get('newUserSelections').forEach(function(selection) {
|
|
||||||
if(typeof selection.get('value') === 'string') {
|
|
||||||
newUser.selections.pushObject(
|
|
||||||
self.store.createFragment('selection', {
|
|
||||||
label: selection.get('value')
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newUser.selections.pushObject(
|
|
||||||
self.store.createFragment('selection', {
|
|
||||||
type: selection.get('value.type'),
|
|
||||||
label: selection.get('value.label'),
|
|
||||||
labelTranslation: selection.get('value.labelTranslation'),
|
|
||||||
icon: selection.get('value.icon')
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// send new user to controller for saving
|
|
||||||
this.send('saveNewUser', newUser);
|
|
||||||
|
|
||||||
// clear input fields
|
|
||||||
this.set('newUserName', '');
|
|
||||||
this.get('newUserSelections').forEach(function(selection){
|
|
||||||
selection.set('value', '');
|
|
||||||
});
|
|
||||||
|
|
||||||
// reset validation erros
|
|
||||||
this.set('errors.newUserName', '');
|
|
||||||
this.set('errors.everyOptionIsAnswered', '');
|
|
||||||
|
|
||||||
Ember.run.scheduleOnce('afterRender', this, function(){
|
|
||||||
// recalculate fixedHeaders
|
|
||||||
Ember.$('.user-selections-table').floatThead('reflow');
|
|
||||||
});
|
|
||||||
|
|
||||||
Ember.run.scheduleOnce('afterRender', this, function(){
|
|
||||||
// resize top scrollbars
|
|
||||||
Ember.$('.top-scrollbar div').css('width', Ember.$('.user-selections-table').width() );
|
|
||||||
Ember.$('.top-scrollbar-floatThead').css('width', Ember.$('.table-scroll').outerWidth() );
|
|
||||||
Ember.$('.top-scrollbar-floatThead div').css('width', Ember.$('.user-selections-table').width() );
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/*
|
|
||||||
* save a new user
|
|
||||||
*/
|
|
||||||
saveNewUser: function(user){
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
// create new user record in store
|
|
||||||
var newUser = this.store.createRecord('user', {
|
|
||||||
name: user.name,
|
|
||||||
creationDate: new Date(),
|
|
||||||
poll: this.get('model'),
|
|
||||||
selections: user.selections,
|
|
||||||
version: this.buildInfo.semver
|
|
||||||
});
|
|
||||||
|
|
||||||
// save new user
|
|
||||||
newUser.save().catch(function(){
|
|
||||||
// error: new user is not saved
|
|
||||||
self.send('openModal', {
|
|
||||||
template: 'save-retry',
|
|
||||||
model: {
|
|
||||||
record: newUser
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
submitNewUser: function(){
|
|
||||||
var self = this;
|
|
||||||
this.validate().then(function() {
|
|
||||||
self.send('addNewUser');
|
|
||||||
}).catch(function(){
|
|
||||||
Ember.$.each(Ember.View.views, function(id, view) {
|
|
||||||
if(view.isEasyForm) {
|
|
||||||
view.focusOut();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
dateGroups: function() {
|
dateGroups: function() {
|
||||||
// group dates only for find a date with times
|
// group dates only for find a date with times
|
||||||
|
@ -189,242 +89,10 @@ export default Ember.Controller.extend(EmberValidations.Mixin, {
|
||||||
return dates;
|
return dates;
|
||||||
}.property('model.options.@each', 'useLocalTimezone'),
|
}.property('model.options.@each', 'useLocalTimezone'),
|
||||||
|
|
||||||
/*
|
|
||||||
* evaluates poll data
|
|
||||||
* if free text answers are allowed evaluation is disabled
|
|
||||||
*/
|
|
||||||
evaluation: function() {
|
|
||||||
// disable evaluation if answer type is free text
|
|
||||||
if (this.get('model.answerType') === 'FreeText') {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
var evaluation = [],
|
|
||||||
options = [],
|
|
||||||
lookup = [];
|
|
||||||
|
|
||||||
// init options array
|
|
||||||
this.get('model.options').forEach(function(option, index){
|
|
||||||
options[index] = 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
// init array of evalutation objects
|
|
||||||
// create object for every possible answer
|
|
||||||
this.get('model.answers').forEach(function(answer){
|
|
||||||
evaluation.push({
|
|
||||||
id: answer.label,
|
|
||||||
label: answer.label,
|
|
||||||
options: Ember.$.extend([], options)
|
|
||||||
});
|
|
||||||
});
|
|
||||||
// create object for no answer if answers are not forced
|
|
||||||
if (!this.get('model.forceAnswer')){
|
|
||||||
evaluation.push({
|
|
||||||
id: null,
|
|
||||||
label: 'no answer',
|
|
||||||
options: Ember.$.extend([], options)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// create lookup array
|
|
||||||
evaluation.forEach(function(value, index){
|
|
||||||
lookup[value.id] = index;
|
|
||||||
});
|
|
||||||
|
|
||||||
// loop over all users
|
|
||||||
this.get('model.users').forEach(function(user){
|
|
||||||
// loop over all selections of the user
|
|
||||||
user.get('selections').forEach(function(selection, optionindex){
|
|
||||||
var answerindex;
|
|
||||||
|
|
||||||
// get answer index by lookup array
|
|
||||||
if (typeof lookup[selection.value.label] === 'undefined') {
|
|
||||||
answerindex = lookup[null];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
answerindex = lookup[selection.value.label];
|
|
||||||
}
|
|
||||||
|
|
||||||
// increment counter
|
|
||||||
try {
|
|
||||||
evaluation[answerindex]['options'][optionindex] = evaluation[answerindex]['options'][optionindex] + 1;
|
|
||||||
} catch (e) {
|
|
||||||
// ToDo: Throw an error
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return evaluation;
|
|
||||||
}.property('model.users.@each'),
|
|
||||||
|
|
||||||
evaluationBestOptions: function() {
|
|
||||||
var options = [],
|
|
||||||
bestOptions = [],
|
|
||||||
self = this;
|
|
||||||
// can not evaluate answer type free text
|
|
||||||
if(this.get('model.isFreeText')) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.get('model.users').forEach(function(user){
|
|
||||||
user.get('selections').forEach(function(selection, i){
|
|
||||||
if(options.length - 1 < i) {
|
|
||||||
options.push({
|
|
||||||
answers: [],
|
|
||||||
key: i,
|
|
||||||
score: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if(typeof options[i].answers[selection.get('type')] === 'undefined') {
|
|
||||||
options[i].answers[selection.get('type')] = 0;
|
|
||||||
}
|
|
||||||
options[i].answers[selection.get('type')]++;
|
|
||||||
|
|
||||||
switch (selection.get('type')) {
|
|
||||||
case 'yes':
|
|
||||||
options[i].score += 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'maybe':
|
|
||||||
options[i].score += 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'no':
|
|
||||||
options[i].score -= 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
options.sort(function(a, b) {
|
|
||||||
return a.score < b.score;
|
|
||||||
});
|
|
||||||
|
|
||||||
bestOptions.push(
|
|
||||||
options[0]
|
|
||||||
);
|
|
||||||
var i = 1;
|
|
||||||
while(true) {
|
|
||||||
if (
|
|
||||||
typeof options[i] !== 'undefined' &&
|
|
||||||
bestOptions[0].score === options[i].score
|
|
||||||
) {
|
|
||||||
bestOptions.push(
|
|
||||||
options[i]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
bestOptions.forEach(function(bestOption, i){
|
|
||||||
if (self.get('model.isFindADate')) {
|
|
||||||
bestOptions[i].title = self.get('dates')[bestOption.key].title;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bestOptions[i].title = self.get('model.options')[bestOption.key].title;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return bestOptions;
|
|
||||||
}.property('model.users.@each'),
|
|
||||||
|
|
||||||
evaluationBestOptionsMultiple: function(){
|
|
||||||
if (this.get('evaluationBestOptions.length') > 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}.property('evaluationBestOptions'),
|
|
||||||
|
|
||||||
evaluationLastParticipation: function(){
|
|
||||||
return this.get('sortedUsers.lastObject.creationDate');
|
|
||||||
}.property('sortedUsers.@each'),
|
|
||||||
|
|
||||||
evaluationParticipants: function(){
|
|
||||||
return this.get('model.users.length');
|
|
||||||
}.property('model.users.@each'),
|
|
||||||
|
|
||||||
/*
|
|
||||||
* returns true if user has selected an answer for every option provided
|
|
||||||
*/
|
|
||||||
everyOptionIsAnswered: function(){
|
|
||||||
try {
|
|
||||||
var newUserSelections = this.get('newUserSelections'),
|
|
||||||
allAnswered = true;
|
|
||||||
|
|
||||||
if (typeof newUserSelections === 'undefined') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
newUserSelections.forEach(function(item){
|
|
||||||
if (Ember.isEmpty(item.value)) {
|
|
||||||
allAnswered = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return allAnswered;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}.property('newUserSelections.@each.value'),
|
|
||||||
|
|
||||||
/*
|
|
||||||
* calculate colspan for a row which should use all columns in table
|
|
||||||
* used by evaluation row
|
|
||||||
*/
|
|
||||||
fullRowColspan: function(){
|
|
||||||
return this.get('model.options.length') + 2;
|
|
||||||
}.property('model.options.@each'),
|
|
||||||
|
|
||||||
isEvaluable: function() {
|
|
||||||
if(
|
|
||||||
!this.get('model.isFreeText') &&
|
|
||||||
this.get('model.users.length') > 0
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}.property('model.users.@each', 'model.isFreeText'),
|
|
||||||
|
|
||||||
/*
|
|
||||||
* switch isValid state
|
|
||||||
* is needed for disable submit button
|
|
||||||
*/
|
|
||||||
isNotValid: function(){
|
|
||||||
return !this.get('isValid');
|
|
||||||
}.property('isValid'),
|
|
||||||
|
|
||||||
// array to store selections of new user
|
|
||||||
newUserSelections: function(){
|
|
||||||
var newUserSelections = Ember.A(),
|
|
||||||
options = this.get('model.options');
|
|
||||||
|
|
||||||
options.forEach(function(){
|
|
||||||
var newSelection = Ember.Object.create({value: ''});
|
|
||||||
newUserSelections.pushObject(newSelection);
|
|
||||||
});
|
|
||||||
|
|
||||||
return newUserSelections;
|
|
||||||
}.property('model.options'),
|
|
||||||
|
|
||||||
optionCount: function() {
|
|
||||||
return this.get('model.options.length');
|
|
||||||
}.property('model.options'),
|
|
||||||
|
|
||||||
pollUrl: function() {
|
pollUrl: function() {
|
||||||
return window.location.href;
|
return window.location.href;
|
||||||
}.property('currentPath', 'encryptionKey'),
|
}.property('currentPath', 'encryptionKey'),
|
||||||
|
|
||||||
|
|
||||||
preventEncryptionKeyChanges: function() {
|
preventEncryptionKeyChanges: function() {
|
||||||
if (
|
if (
|
||||||
!Ember.isEmpty(this.get('encryption.key')) &&
|
!Ember.isEmpty(this.get('encryption.key')) &&
|
||||||
|
@ -446,40 +114,5 @@ export default Ember.Controller.extend(EmberValidations.Mixin, {
|
||||||
|
|
||||||
useLocalTimezone: function() {
|
useLocalTimezone: function() {
|
||||||
return false;
|
return false;
|
||||||
}.property(),
|
}.property()
|
||||||
|
|
||||||
validations: {
|
|
||||||
everyOptionIsAnswered: {
|
|
||||||
/*
|
|
||||||
* validate if every option is answered
|
|
||||||
* if it's forced by poll settings (forceAnswer === true)
|
|
||||||
*
|
|
||||||
* using a computed property therefore which returns true / false
|
|
||||||
* in combinatoin with acceptance validator
|
|
||||||
*
|
|
||||||
* ToDo: Show validation errors
|
|
||||||
*/
|
|
||||||
acceptance: {
|
|
||||||
if: function(object){
|
|
||||||
return object.get('model.forceAnswer');
|
|
||||||
},
|
|
||||||
message: Ember.I18n.t('poll.error.newUser.everyOptionIsAnswered')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
newUserName: {
|
|
||||||
presence: {
|
|
||||||
message: Ember.I18n.t('poll.error.newUserName'),
|
|
||||||
|
|
||||||
/*
|
|
||||||
* validate if a user name is given
|
|
||||||
* if it's forced by poll settings (anonymousUser === false)
|
|
||||||
*/
|
|
||||||
unless: function(object){
|
|
||||||
/* have in mind that anonymousUser is undefined on init */
|
|
||||||
return object.get('model.anonymousUser');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
194
app/controllers/poll/evaluation.js
Normal file
194
app/controllers/poll/evaluation.js
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
import Ember from "ember";
|
||||||
|
|
||||||
|
export default Ember.Controller.extend({
|
||||||
|
usersSorting: ['creationDate'],
|
||||||
|
sortedUsers: Ember.computed.sort('pollController.model.users', 'usersSorting'),
|
||||||
|
pollController: Ember.inject.controller('poll'),
|
||||||
|
dates: Ember.computed.reads('pollController.dates'),
|
||||||
|
dateGroups: Ember.computed.reads('pollController.dateGroups'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* evaluates poll data
|
||||||
|
* if free text answers are allowed evaluation is disabled
|
||||||
|
*/
|
||||||
|
evaluation: function() {
|
||||||
|
// disable evaluation if answer type is free text
|
||||||
|
if (this.get('model.answerType') === 'FreeText') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var evaluation = [],
|
||||||
|
options = [],
|
||||||
|
lookup = [];
|
||||||
|
|
||||||
|
// init options array
|
||||||
|
this.get('model.options').forEach(function(option, index){
|
||||||
|
options[index] = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
// init array of evalutation objects
|
||||||
|
// create object for every possible answer
|
||||||
|
this.get('model.answers').forEach(function(answer){
|
||||||
|
evaluation.push({
|
||||||
|
id: answer.label,
|
||||||
|
label: answer.label,
|
||||||
|
options: Ember.$.extend([], options)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// create object for no answer if answers are not forced
|
||||||
|
if (!this.get('model.forceAnswer')){
|
||||||
|
evaluation.push({
|
||||||
|
id: null,
|
||||||
|
label: 'no answer',
|
||||||
|
options: Ember.$.extend([], options)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// create lookup array
|
||||||
|
evaluation.forEach(function(value, index){
|
||||||
|
lookup[value.id] = index;
|
||||||
|
});
|
||||||
|
|
||||||
|
// loop over all users
|
||||||
|
this.get('model.users').forEach(function(user){
|
||||||
|
// loop over all selections of the user
|
||||||
|
user.get('selections').forEach(function(selection, optionindex){
|
||||||
|
var answerindex;
|
||||||
|
|
||||||
|
// get answer index by lookup array
|
||||||
|
if (typeof lookup[selection.value.label] === 'undefined') {
|
||||||
|
answerindex = lookup[null];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
answerindex = lookup[selection.value.label];
|
||||||
|
}
|
||||||
|
|
||||||
|
// increment counter
|
||||||
|
try {
|
||||||
|
evaluation[answerindex]['options'][optionindex] = evaluation[answerindex]['options'][optionindex] + 1;
|
||||||
|
} catch (e) {
|
||||||
|
// ToDo: Throw an error
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return evaluation;
|
||||||
|
}.property('model.users.@each'),
|
||||||
|
|
||||||
|
evaluationBestOptions: function() {
|
||||||
|
var options = [],
|
||||||
|
bestOptions = [],
|
||||||
|
self = this;
|
||||||
|
// can not evaluate answer type free text
|
||||||
|
if(this.get('model.isFreeText')) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.get('model.users').forEach(function(user){
|
||||||
|
user.get('selections').forEach(function(selection, i){
|
||||||
|
if(options.length - 1 < i) {
|
||||||
|
options.push({
|
||||||
|
answers: [],
|
||||||
|
key: i,
|
||||||
|
score: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof options[i].answers[selection.get('type')] === 'undefined') {
|
||||||
|
options[i].answers[selection.get('type')] = 0;
|
||||||
|
}
|
||||||
|
options[i].answers[selection.get('type')]++;
|
||||||
|
|
||||||
|
switch (selection.get('type')) {
|
||||||
|
case 'yes':
|
||||||
|
options[i].score += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'maybe':
|
||||||
|
options[i].score += 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'no':
|
||||||
|
options[i].score -= 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
options.sort(function(a, b) {
|
||||||
|
return a.score < b.score;
|
||||||
|
});
|
||||||
|
|
||||||
|
bestOptions.push(
|
||||||
|
options[0]
|
||||||
|
);
|
||||||
|
var i = 1;
|
||||||
|
while(true) {
|
||||||
|
if (
|
||||||
|
typeof options[i] !== 'undefined' &&
|
||||||
|
bestOptions[0].score === options[i].score
|
||||||
|
) {
|
||||||
|
bestOptions.push(
|
||||||
|
options[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bestOptions.forEach(function(bestOption, i){
|
||||||
|
if (self.get('model.isFindADate')) {
|
||||||
|
bestOptions[i].title = self.get('dates')[bestOption.key].title;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bestOptions[i].title = self.get('model.options')[bestOption.key].title;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return bestOptions;
|
||||||
|
}.property('model.users.@each'),
|
||||||
|
|
||||||
|
evaluationBestOptionsMultiple: function(){
|
||||||
|
if (this.get('evaluationBestOptions.length') > 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}.property('evaluationBestOptions'),
|
||||||
|
|
||||||
|
evaluationLastParticipation: function(){
|
||||||
|
return this.get('sortedUsers.lastObject.creationDate');
|
||||||
|
}.property('sortedUsers.@each'),
|
||||||
|
|
||||||
|
evaluationParticipants: function(){
|
||||||
|
return this.get('model.users.length');
|
||||||
|
}.property('model.users.@each'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* calculate colspan for a row which should use all columns in table
|
||||||
|
* used by evaluation row
|
||||||
|
*/
|
||||||
|
fullRowColspan: function(){
|
||||||
|
return this.get('model.options.length') + 2;
|
||||||
|
}.property('model.options.@each'),
|
||||||
|
|
||||||
|
isEvaluable: function() {
|
||||||
|
if(
|
||||||
|
!this.get('model.isFreeText') &&
|
||||||
|
this.get('model.users.length') > 0
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}.property('model.users.@each', 'model.isFreeText'),
|
||||||
|
|
||||||
|
optionCount: function() {
|
||||||
|
return this.get('model.options.length');
|
||||||
|
}.property('model.options')
|
||||||
|
});
|
197
app/controllers/poll/participation.js
Normal file
197
app/controllers/poll/participation.js
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
import Ember from "ember";
|
||||||
|
import EmberValidations from 'ember-validations';
|
||||||
|
|
||||||
|
export default Ember.Controller.extend(EmberValidations.Mixin, {
|
||||||
|
dates: Ember.computed.reads('pollController.dates'),
|
||||||
|
dateGroups: Ember.computed.reads('pollController.dateGroups'),
|
||||||
|
encryption: Ember.inject.service(),
|
||||||
|
newUserName: '',
|
||||||
|
pollController: Ember.inject.controller('poll'),
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
addNewUser: function(){
|
||||||
|
var newUser = {
|
||||||
|
name: this.get('newUserName'),
|
||||||
|
selections: []
|
||||||
|
};
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
// work-a-round cause value is not retrived otherwise
|
||||||
|
this.get('newUserSelections').forEach(function(selection) {
|
||||||
|
if(typeof selection.get('value') === 'string') {
|
||||||
|
newUser.selections.pushObject(
|
||||||
|
self.store.createFragment('selection', {
|
||||||
|
label: selection.get('value')
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newUser.selections.pushObject(
|
||||||
|
self.store.createFragment('selection', {
|
||||||
|
type: selection.get('value.type'),
|
||||||
|
label: selection.get('value.label'),
|
||||||
|
labelTranslation: selection.get('value.labelTranslation'),
|
||||||
|
icon: selection.get('value.icon')
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// send new user to controller for saving
|
||||||
|
this.send('saveNewUser', newUser);
|
||||||
|
|
||||||
|
// clear input fields
|
||||||
|
this.set('newUserName', '');
|
||||||
|
this.get('newUserSelections').forEach(function(selection){
|
||||||
|
selection.set('value', '');
|
||||||
|
});
|
||||||
|
|
||||||
|
// reset validation erros
|
||||||
|
this.set('errors.newUserName', '');
|
||||||
|
this.set('errors.everyOptionIsAnswered', '');
|
||||||
|
|
||||||
|
Ember.run.scheduleOnce('afterRender', this, function(){
|
||||||
|
// recalculate fixedHeaders
|
||||||
|
Ember.$('.user-selections-table').floatThead('reflow');
|
||||||
|
});
|
||||||
|
|
||||||
|
Ember.run.scheduleOnce('afterRender', this, function(){
|
||||||
|
// resize top scrollbars
|
||||||
|
Ember.$('.top-scrollbar div').css('width', Ember.$('.user-selections-table').width() );
|
||||||
|
Ember.$('.top-scrollbar-floatThead').css('width', Ember.$('.table-scroll').outerWidth() );
|
||||||
|
Ember.$('.top-scrollbar-floatThead div').css('width', Ember.$('.user-selections-table').width() );
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save a new user
|
||||||
|
*/
|
||||||
|
saveNewUser: function(user){
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
// create new user record in store
|
||||||
|
var newUser = this.store.createRecord('user', {
|
||||||
|
name: user.name,
|
||||||
|
creationDate: new Date(),
|
||||||
|
poll: this.get('model'),
|
||||||
|
selections: user.selections,
|
||||||
|
version: this.buildInfo.semver
|
||||||
|
});
|
||||||
|
|
||||||
|
// save new user
|
||||||
|
newUser.save()
|
||||||
|
.then(() => {
|
||||||
|
this.transitionTo('poll.evaluation', this.get('model'), {
|
||||||
|
queryParams: { encryptionKey: this.get('encryption.key') }
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(function(){
|
||||||
|
// error: new user is not saved
|
||||||
|
self.send('openModal', {
|
||||||
|
template: 'save-retry',
|
||||||
|
model: {
|
||||||
|
record: newUser
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
submitNewUser: function(){
|
||||||
|
var self = this;
|
||||||
|
this.validate().then(function() {
|
||||||
|
self.send('addNewUser');
|
||||||
|
}).catch(function(){
|
||||||
|
Ember.$.each(Ember.View.views, function(id, view) {
|
||||||
|
if(view.isEasyForm) {
|
||||||
|
view.focusOut();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
* returns true if user has selected an answer for every option provided
|
||||||
|
*/
|
||||||
|
everyOptionIsAnswered: function(){
|
||||||
|
try {
|
||||||
|
var newUserSelections = this.get('newUserSelections'),
|
||||||
|
allAnswered = true;
|
||||||
|
|
||||||
|
if (typeof newUserSelections === 'undefined') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
newUserSelections.forEach(function(item){
|
||||||
|
if (Ember.isEmpty(item.value)) {
|
||||||
|
allAnswered = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return allAnswered;
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}.property('newUserSelections.@each.value'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* switch isValid state
|
||||||
|
* is needed for disable submit button
|
||||||
|
*/
|
||||||
|
isNotValid: function(){
|
||||||
|
return !this.get('isValid');
|
||||||
|
}.property('isValid'),
|
||||||
|
|
||||||
|
// array to store selections of new user
|
||||||
|
newUserSelections: function(){
|
||||||
|
var newUserSelections = Ember.A(),
|
||||||
|
options = this.get('model.options');
|
||||||
|
|
||||||
|
options.forEach(function(){
|
||||||
|
var newSelection = Ember.Object.create({value: ''});
|
||||||
|
newUserSelections.pushObject(newSelection);
|
||||||
|
});
|
||||||
|
|
||||||
|
return newUserSelections;
|
||||||
|
}.property('model.options'),
|
||||||
|
|
||||||
|
optionCount: function() {
|
||||||
|
return this.get('model.options.length');
|
||||||
|
}.property('model.options'),
|
||||||
|
|
||||||
|
validations: {
|
||||||
|
everyOptionIsAnswered: {
|
||||||
|
/*
|
||||||
|
* validate if every option is answered
|
||||||
|
* if it's forced by poll settings (forceAnswer === true)
|
||||||
|
*
|
||||||
|
* using a computed property therefore which returns true / false
|
||||||
|
* in combinatoin with acceptance validator
|
||||||
|
*
|
||||||
|
* ToDo: Show validation errors
|
||||||
|
*/
|
||||||
|
acceptance: {
|
||||||
|
if: function(object){
|
||||||
|
return object.get('model.forceAnswer');
|
||||||
|
},
|
||||||
|
message: Ember.I18n.t('poll.error.newUser.everyOptionIsAnswered')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
newUserName: {
|
||||||
|
presence: {
|
||||||
|
message: Ember.I18n.t('poll.error.newUserName'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* validate if a user name is given
|
||||||
|
* if it's forced by poll settings (anonymousUser === false)
|
||||||
|
*/
|
||||||
|
unless: function(object){
|
||||||
|
/* have in mind that anonymousUser is undefined on init */
|
||||||
|
return object.get('model.anonymousUser');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -6,7 +6,10 @@ var Router = Ember.Router.extend({
|
||||||
});
|
});
|
||||||
|
|
||||||
Router.map(function(){
|
Router.map(function(){
|
||||||
this.route('poll', { path: '/poll/:poll_id' });
|
this.resource('poll', { path: '/poll/:poll_id' }, function(){
|
||||||
|
this.route('participation');
|
||||||
|
this.route('evaluation');
|
||||||
|
});
|
||||||
this.resource('create', function(){
|
this.resource('create', function(){
|
||||||
this.route('meta');
|
this.route('meta');
|
||||||
this.route('options');
|
this.route('options');
|
||||||
|
|
|
@ -11,6 +11,10 @@ export default Ember.Route.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
afterModel(poll) {
|
||||||
|
this.transitionTo('poll.participation', poll, {queryParams: {encryptionKey: this.get('encryption.key')}});
|
||||||
|
},
|
||||||
|
|
||||||
encryption: Ember.inject.service(),
|
encryption: Ember.inject.service(),
|
||||||
|
|
||||||
model: function(params) {
|
model: function(params) {
|
||||||
|
|
|
@ -18,216 +18,26 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="box">
|
<div class="box container-fluid">
|
||||||
<div class="table-scroll">
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
<table class="user-selections-table table table-striped table-condensed">
|
{{#link-to "poll.participation" model tagName='li' activeClass='active' class='participation'}}
|
||||||
<thead>
|
{{#link-to "poll.participation" model}}
|
||||||
{{#if model.isDateTime}}
|
participation
|
||||||
<tr class="dateGroups">
|
{{/link-to}}
|
||||||
<th> </th>
|
{{/link-to}}
|
||||||
{{#each dateGroup in dateGroups}}
|
{{#link-to "poll.evaluation" model tagName='li' activeClass='active' class='evaluation'}}
|
||||||
<th {{bind-attr colspan="dateGroup.colspan"}}>
|
{{#link-to "poll.evaluation" model}}
|
||||||
{{formattedDate dateGroup.value}}
|
evaluation
|
||||||
</th>
|
{{/link-to}}
|
||||||
{{/each}}
|
{{/link-to}}
|
||||||
<th> </th>
|
</ul>
|
||||||
</tr>
|
|
||||||
{{/if}}
|
|
||||||
<tr>
|
|
||||||
<th> </th>
|
|
||||||
{{#if model.isFindADate}}
|
|
||||||
{{#each date in dates}}
|
|
||||||
<th>
|
|
||||||
{{#if model.isDateTime}}
|
|
||||||
{{formattedDate date.title format="LT" times=true}}
|
|
||||||
{{else}}
|
|
||||||
{{formattedDate date.title}}
|
|
||||||
{{/if}}
|
|
||||||
</th>
|
|
||||||
{{/each}}
|
|
||||||
{{else}}
|
|
||||||
{{#each option in model.options}}
|
|
||||||
<th>
|
|
||||||
{{option.title}}
|
|
||||||
</th>
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<th> </th>
|
<div class="tab-content">
|
||||||
</tr>
|
<div role="tabpanel" class="tab-pane active">
|
||||||
</thead>
|
{{outlet}}
|
||||||
|
</div>
|
||||||
<tbody>
|
|
||||||
<tr class='newUser'>
|
|
||||||
<td>
|
|
||||||
{{#form-wrapper}}
|
|
||||||
{{#input newUserName}}
|
|
||||||
{{input-field newUserName
|
|
||||||
placeholderTranslation="poll.input.newUserName.placeholder"
|
|
||||||
}}
|
|
||||||
{{#if view.showError}}
|
|
||||||
{{error-field newUserName}}
|
|
||||||
{{/if}}
|
|
||||||
{{/input}}
|
|
||||||
{{/form-wrapper}}
|
|
||||||
</td>
|
|
||||||
{{#each newUserSelection in newUserSelections}}
|
|
||||||
<td class="newUserSelection">
|
|
||||||
{{#form-wrapper}}
|
|
||||||
{{#if model.isFreeText}}
|
|
||||||
{{#input newUserSelection.value}}
|
|
||||||
{{input-field newUserSelection.value}}
|
|
||||||
{{/input}}
|
|
||||||
{{else}}
|
|
||||||
{{#each answer in model.answers}}
|
|
||||||
<div class="radio">
|
|
||||||
{{#radio-button value=answer groupValue=newUserSelection.value}}
|
|
||||||
<span {{bind-attr class="answer.type"}}>
|
|
||||||
<span {{bind-attr class="answer.icon"}}></span>
|
|
||||||
{{#if answer.labelTranslation}}
|
|
||||||
{{t answer.labelTranslation}}
|
|
||||||
{{else}}
|
|
||||||
{{answer.label}}
|
|
||||||
{{/if}}
|
|
||||||
</span>
|
|
||||||
{{/radio-button}}
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
{{/form-wrapper}}
|
|
||||||
</td>
|
|
||||||
{{/each}}
|
|
||||||
<td>
|
|
||||||
<button {{action "submitNewUser"}} class="btn btn-default btn-primary">
|
|
||||||
{{t "poll.save"}}
|
|
||||||
</button>
|
|
||||||
<span style="white-space: normal;">
|
|
||||||
{{#input everyOptionIsAnswered}}
|
|
||||||
{{#if view.showError}}
|
|
||||||
{{error-field everyOptionIsAnswered}}
|
|
||||||
{{/if}}
|
|
||||||
{{/input}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
{{#each user in sortedUsers}}
|
|
||||||
<tr class="user">
|
|
||||||
<td>{{user.name}}</td>
|
|
||||||
{{#each selection in user.selections}}
|
|
||||||
<td>
|
|
||||||
{{#if selection.label}}
|
|
||||||
{{#if model.isFreeText}}
|
|
||||||
{{selection.label}}
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
{{#if selection.labelTranslation}}
|
|
||||||
{{#unless model.isFreeText}}
|
|
||||||
<span {{bind-attr class="selection.type"}}>
|
|
||||||
<span {{bind-attr class="selection.icon"}}></span>
|
|
||||||
{{t selection.labelTranslation}}
|
|
||||||
</span>
|
|
||||||
{{/unless}}
|
|
||||||
{{/if}}
|
|
||||||
</td>
|
|
||||||
{{/each}}
|
|
||||||
<td> </td>
|
|
||||||
</tr>
|
|
||||||
{{/each}}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if isEvaluable}}
|
|
||||||
<div class="box evaluation">
|
|
||||||
<h2>
|
|
||||||
{{t "poll.evaluation.label"}}
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<p class="participants">
|
|
||||||
{{t "poll.evaluation.participants" count=evaluationParticipants}}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p class="best-options">
|
|
||||||
{{#if model.isFindADate}}
|
|
||||||
{{t "poll.evaluation.bestOption.label.findADate" count=evaluationBestOptions.length}}
|
|
||||||
{{else}}
|
|
||||||
{{t "poll.evaluation.bestOption.label.makeAPoll" count=evaluationBestOptions.length}}
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if evaluationBestOptionsMultiple}}
|
|
||||||
<ul>
|
|
||||||
{{#each evaluationBestOption in evaluationBestOptions}}
|
|
||||||
<li>
|
|
||||||
{{#if model.isFindADate}}
|
|
||||||
<strong>{{formattedDate evaluationBestOption.title times=model.isDateTime}}</strong>.
|
|
||||||
{{else}}
|
|
||||||
<strong>{{evaluationBestOption.title}}</strong>.
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
{{#if model.isFindADate}}
|
|
||||||
{{#if evaluationBestOption.answers.yes}}
|
|
||||||
{{t "poll.evaluation.bestOptionParticipants.findADate.yes" count=evaluationBestOption.answers.yes}}
|
|
||||||
{{/if}}
|
|
||||||
{{#if evaluationBestOption.answers.maybe}}
|
|
||||||
{{t "poll.evaluation.bestOptionParticipants.findADate.maybe" count=evaluationBestOption.answers.maybe}}
|
|
||||||
{{/if}}
|
|
||||||
{{#if evaluationBestOption.answers.no}}
|
|
||||||
{{t "poll.evaluation.bestOptionParticipants.findADate.no" count=evaluationBestOption.answers.no}}
|
|
||||||
{{/if}}
|
|
||||||
{{else}}
|
|
||||||
{{#if evaluationBestOption.answers.yes}}
|
|
||||||
{{t "poll.evaluation.bestOptionParticipants.makeAPoll.yes" count=evaluationBestOption.answers.yes}}
|
|
||||||
{{/if}}
|
|
||||||
{{#if evaluationBestOption.answers.maybe}}
|
|
||||||
{{t "poll.evaluation.bestOptionParticipants.makeAPoll.maybe" count=evaluationBestOption.answers.maybe}}
|
|
||||||
{{/if}}
|
|
||||||
{{#if evaluationBestOption.answers.no}}
|
|
||||||
{{t "poll.evaluation.bestOptionParticipants.makeAPoll.no" count=evaluationBestOption.answers.no}}
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
</li>
|
|
||||||
{{/each}}
|
|
||||||
</ul>
|
|
||||||
{{else}}
|
|
||||||
{{#if model.isFindADate}}
|
|
||||||
<strong>{{formattedDate evaluationBestOptions.[0].title times=model.isDateTime}}</strong>.
|
|
||||||
{{else}}
|
|
||||||
<strong>{{evaluationBestOptions.[0].title}}</strong>.
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if model.isFindADate}}
|
|
||||||
{{#if evaluationBestOptions.[0].answers.yes}}
|
|
||||||
{{t "poll.evaluation.bestOptionParticipants.findADate.yes" count=evaluationBestOptions.[0].answers.yes}}
|
|
||||||
{{/if}}
|
|
||||||
{{#if evaluationBestOptions.[0].answers.maybe}}
|
|
||||||
{{t "poll.evaluation.bestOptionParticipants.findADate.maybe" count=evaluationBestOptions.[0].answers.maybe}}
|
|
||||||
{{/if}}
|
|
||||||
{{#if evaluationBestOptions.[0].answers.no}}
|
|
||||||
{{t "poll.evaluation.bestOptionParticipants.findADate.no" count=evaluationBestOptions.[0].answers.no}}
|
|
||||||
{{/if}}
|
|
||||||
{{else}}
|
|
||||||
{{#if evaluationBestOptions.[0].answers.yes}}
|
|
||||||
{{t "poll.evaluation.bestOptionParticipants.makeAPoll.yes" count=evaluationBestOptions.[0].answers.yes}}
|
|
||||||
{{/if}}
|
|
||||||
{{#if evaluationBestOptions.[0].answers.maybe}}
|
|
||||||
{{t "poll.evaluation.bestOptionParticipants.makeAPoll.maybe" count=evaluationBestOptions.[0].answers.maybe}}
|
|
||||||
{{/if}}
|
|
||||||
{{#if evaluationBestOptions.[0].answers.no}}
|
|
||||||
{{t "poll.evaluation.bestOptionParticipants.makeAPoll.no" count=evaluationBestOptions.[0].answers.no}}
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p class="last-participation">
|
|
||||||
{{t "poll.evaluation.lastParticipation" ago=(moment-from-now evaluationLastParticipation)}}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal fade" id="timezoneDiffers">
|
<div class="modal fade" id="timezoneDiffers">
|
||||||
|
|
155
app/templates/poll/evaluation.hbs
Normal file
155
app/templates/poll/evaluation.hbs
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
<div class="table-scroll">
|
||||||
|
<table class="user-selections-table table table-striped table-condensed">
|
||||||
|
<thead>
|
||||||
|
{{#if model.isDateTime}}
|
||||||
|
<tr class="dateGroups">
|
||||||
|
<th> </th>
|
||||||
|
{{#each dateGroup in dateGroups}}
|
||||||
|
<th {{bind-attr colspan="dateGroup.colspan"}}>
|
||||||
|
{{formattedDate dateGroup.value}}
|
||||||
|
</th>
|
||||||
|
{{/each}}
|
||||||
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
{{/if}}
|
||||||
|
<tr>
|
||||||
|
<th> </th>
|
||||||
|
{{#if model.isFindADate}}
|
||||||
|
{{#each date in dates}}
|
||||||
|
<th>
|
||||||
|
{{#if model.isDateTime}}
|
||||||
|
{{formattedDate date.title format="LT" times=true}}
|
||||||
|
{{else}}
|
||||||
|
{{formattedDate date.title}}
|
||||||
|
{{/if}}
|
||||||
|
</th>
|
||||||
|
{{/each}}
|
||||||
|
{{else}}
|
||||||
|
{{#each option in model.options}}
|
||||||
|
<th>
|
||||||
|
{{option.title}}
|
||||||
|
</th>
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{{#each user in sortedUsers}}
|
||||||
|
<tr class="user">
|
||||||
|
<td>{{user.name}}</td>
|
||||||
|
{{#each selection in user.selections}}
|
||||||
|
<td>
|
||||||
|
{{#if selection.label}}
|
||||||
|
{{#if model.isFreeText}}
|
||||||
|
{{selection.label}}
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if selection.labelTranslation}}
|
||||||
|
{{#unless model.isFreeText}}
|
||||||
|
<span {{bind-attr class="selection.type"}}>
|
||||||
|
<span {{bind-attr class="selection.icon"}}></span>
|
||||||
|
{{t selection.labelTranslation}}
|
||||||
|
</span>
|
||||||
|
{{/unless}}
|
||||||
|
{{/if}}
|
||||||
|
</td>
|
||||||
|
{{/each}}
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if isEvaluable}}
|
||||||
|
<div class="box evaluation">
|
||||||
|
<h2>
|
||||||
|
{{t "poll.evaluation.label"}}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p class="participants">
|
||||||
|
{{t "poll.evaluation.participants" count=evaluationParticipants}}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="best-options">
|
||||||
|
{{#if model.isFindADate}}
|
||||||
|
{{t "poll.evaluation.bestOption.label.findADate" count=evaluationBestOptions.length}}
|
||||||
|
{{else}}
|
||||||
|
{{t "poll.evaluation.bestOption.label.makeAPoll" count=evaluationBestOptions.length}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if evaluationBestOptionsMultiple}}
|
||||||
|
<ul>
|
||||||
|
{{#each evaluationBestOption in evaluationBestOptions}}
|
||||||
|
<li>
|
||||||
|
{{#if model.isFindADate}}
|
||||||
|
<strong>{{formattedDate evaluationBestOption.title times=model.isDateTime}}</strong>.
|
||||||
|
{{else}}
|
||||||
|
<strong>{{evaluationBestOption.title}}</strong>.
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
{{#if model.isFindADate}}
|
||||||
|
{{#if evaluationBestOption.answers.yes}}
|
||||||
|
{{t "poll.evaluation.bestOptionParticipants.findADate.yes" count=evaluationBestOption.answers.yes}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if evaluationBestOption.answers.maybe}}
|
||||||
|
{{t "poll.evaluation.bestOptionParticipants.findADate.maybe" count=evaluationBestOption.answers.maybe}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if evaluationBestOption.answers.no}}
|
||||||
|
{{t "poll.evaluation.bestOptionParticipants.findADate.no" count=evaluationBestOption.answers.no}}
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
{{#if evaluationBestOption.answers.yes}}
|
||||||
|
{{t "poll.evaluation.bestOptionParticipants.makeAPoll.yes" count=evaluationBestOption.answers.yes}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if evaluationBestOption.answers.maybe}}
|
||||||
|
{{t "poll.evaluation.bestOptionParticipants.makeAPoll.maybe" count=evaluationBestOption.answers.maybe}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if evaluationBestOption.answers.no}}
|
||||||
|
{{t "poll.evaluation.bestOptionParticipants.makeAPoll.no" count=evaluationBestOption.answers.no}}
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
{{else}}
|
||||||
|
{{#if model.isFindADate}}
|
||||||
|
<strong>{{formattedDate evaluationBestOptions.[0].title times=model.isDateTime}}</strong>.
|
||||||
|
{{else}}
|
||||||
|
<strong>{{evaluationBestOptions.[0].title}}</strong>.
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if model.isFindADate}}
|
||||||
|
{{#if evaluationBestOptions.[0].answers.yes}}
|
||||||
|
{{t "poll.evaluation.bestOptionParticipants.findADate.yes" count=evaluationBestOptions.[0].answers.yes}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if evaluationBestOptions.[0].answers.maybe}}
|
||||||
|
{{t "poll.evaluation.bestOptionParticipants.findADate.maybe" count=evaluationBestOptions.[0].answers.maybe}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if evaluationBestOptions.[0].answers.no}}
|
||||||
|
{{t "poll.evaluation.bestOptionParticipants.findADate.no" count=evaluationBestOptions.[0].answers.no}}
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
{{#if evaluationBestOptions.[0].answers.yes}}
|
||||||
|
{{t "poll.evaluation.bestOptionParticipants.makeAPoll.yes" count=evaluationBestOptions.[0].answers.yes}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if evaluationBestOptions.[0].answers.maybe}}
|
||||||
|
{{t "poll.evaluation.bestOptionParticipants.makeAPoll.maybe" count=evaluationBestOptions.[0].answers.maybe}}
|
||||||
|
{{/if}}
|
||||||
|
{{#if evaluationBestOptions.[0].answers.no}}
|
||||||
|
{{t "poll.evaluation.bestOptionParticipants.makeAPoll.no" count=evaluationBestOptions.[0].answers.no}}
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="last-participation">
|
||||||
|
{{t "poll.evaluation.lastParticipation" ago=(moment-from-now evaluationLastParticipation)}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
94
app/templates/poll/participation.hbs
Normal file
94
app/templates/poll/participation.hbs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
<div class="table-scroll">
|
||||||
|
<table class="user-selections-table table table-striped table-condensed">
|
||||||
|
<thead>
|
||||||
|
{{#if model.isDateTime}}
|
||||||
|
<tr class="dateGroups">
|
||||||
|
<th> </th>
|
||||||
|
{{#each dateGroup in dateGroups}}
|
||||||
|
<th {{bind-attr colspan="dateGroup.colspan"}}>
|
||||||
|
{{formattedDate dateGroup.value}}
|
||||||
|
</th>
|
||||||
|
{{/each}}
|
||||||
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
{{/if}}
|
||||||
|
<tr>
|
||||||
|
<th> </th>
|
||||||
|
{{#if model.isFindADate}}
|
||||||
|
{{#each date in dates}}
|
||||||
|
<th>
|
||||||
|
{{#if model.isDateTime}}
|
||||||
|
{{formattedDate date.title format="LT" times=true}}
|
||||||
|
{{else}}
|
||||||
|
{{formattedDate date.title}}
|
||||||
|
{{/if}}
|
||||||
|
</th>
|
||||||
|
{{/each}}
|
||||||
|
{{else}}
|
||||||
|
{{#each option in model.options}}
|
||||||
|
<th>
|
||||||
|
{{option.title}}
|
||||||
|
</th>
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<th> </th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
<tr class='newUser'>
|
||||||
|
<td>
|
||||||
|
{{#form-wrapper}}
|
||||||
|
{{#input newUserName}}
|
||||||
|
{{input-field newUserName
|
||||||
|
placeholderTranslation="poll.input.newUserName.placeholder"
|
||||||
|
}}
|
||||||
|
{{#if view.showError}}
|
||||||
|
{{error-field newUserName}}
|
||||||
|
{{/if}}
|
||||||
|
{{/input}}
|
||||||
|
{{/form-wrapper}}
|
||||||
|
</td>
|
||||||
|
{{#each newUserSelection in newUserSelections}}
|
||||||
|
<td class="newUserSelection">
|
||||||
|
{{#form-wrapper}}
|
||||||
|
{{#if model.isFreeText}}
|
||||||
|
{{#input newUserSelection.value}}
|
||||||
|
{{input-field newUserSelection.value}}
|
||||||
|
{{/input}}
|
||||||
|
{{else}}
|
||||||
|
{{#each answer in model.answers}}
|
||||||
|
<div class="radio">
|
||||||
|
{{#radio-button value=answer groupValue=newUserSelection.value}}
|
||||||
|
<span {{bind-attr class="answer.type"}}>
|
||||||
|
<span {{bind-attr class="answer.icon"}}></span>
|
||||||
|
{{#if answer.labelTranslation}}
|
||||||
|
{{t answer.labelTranslation}}
|
||||||
|
{{else}}
|
||||||
|
{{answer.label}}
|
||||||
|
{{/if}}
|
||||||
|
</span>
|
||||||
|
{{/radio-button}}
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
{{/form-wrapper}}
|
||||||
|
</td>
|
||||||
|
{{/each}}
|
||||||
|
<td>
|
||||||
|
<button {{action "submitNewUser"}} class="btn btn-default btn-primary">
|
||||||
|
{{t "poll.save"}}
|
||||||
|
</button>
|
||||||
|
<span style="white-space: normal;">
|
||||||
|
{{#input everyOptionIsAnswered}}
|
||||||
|
{{#if view.showError}}
|
||||||
|
{{error-field everyOptionIsAnswered}}
|
||||||
|
{{/if}}
|
||||||
|
{{/input}}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
|
@ -30,7 +30,8 @@
|
||||||
"pollHasOptionsDates",
|
"pollHasOptionsDates",
|
||||||
"pollHasOptionsTimes",
|
"pollHasOptionsTimes",
|
||||||
"pollHasAnswers",
|
"pollHasAnswers",
|
||||||
"pollParticipate"
|
"pollParticipate",
|
||||||
|
"switchTab"
|
||||||
],
|
],
|
||||||
"node": false,
|
"node": false,
|
||||||
"browser": false,
|
"browser": false,
|
||||||
|
|
|
@ -69,7 +69,7 @@ test("create a default poll", function(assert) {
|
||||||
click('.button-next');
|
click('.button-next');
|
||||||
|
|
||||||
andThen(function(){
|
andThen(function(){
|
||||||
assert.equal(currentPath(), 'poll');
|
assert.equal(currentPath(), 'poll.participation');
|
||||||
|
|
||||||
pollTitleEqual(assert, 'default poll');
|
pollTitleEqual(assert, 'default poll');
|
||||||
pollDescriptionEqual(assert, '');
|
pollDescriptionEqual(assert, '');
|
||||||
|
@ -133,7 +133,7 @@ test("create a poll for answering a question", function(assert) {
|
||||||
click('.button-next');
|
click('.button-next');
|
||||||
|
|
||||||
andThen(function(){
|
andThen(function(){
|
||||||
assert.equal(currentPath(), 'poll');
|
assert.equal(currentPath(), 'poll.participation');
|
||||||
|
|
||||||
pollTitleEqual(assert, 'default poll');
|
pollTitleEqual(assert, 'default poll');
|
||||||
pollDescriptionEqual(assert, '');
|
pollDescriptionEqual(assert, '');
|
||||||
|
@ -174,7 +174,7 @@ test("create a poll with description", function(assert) {
|
||||||
click('.button-next');
|
click('.button-next');
|
||||||
|
|
||||||
andThen(function(){
|
andThen(function(){
|
||||||
assert.equal(currentPath(), 'poll');
|
assert.equal(currentPath(), 'poll.participation');
|
||||||
|
|
||||||
pollTitleEqual(assert, 'default poll');
|
pollTitleEqual(assert, 'default poll');
|
||||||
pollDescriptionEqual(assert, 'a sample description');
|
pollDescriptionEqual(assert, 'a sample description');
|
||||||
|
|
|
@ -40,11 +40,12 @@ test("participate in a default poll", function(assert) {
|
||||||
);
|
);
|
||||||
|
|
||||||
visit('/poll/' + id + '?encryptionKey=' + encryptionKey).then(function() {
|
visit('/poll/' + id + '?encryptionKey=' + encryptionKey).then(function() {
|
||||||
|
assert.equal(currentPath(), 'poll.participation');
|
||||||
pollParticipate('Max Meiner', ['yes', 'no']);
|
pollParticipate('Max Meiner', ['yes', 'no']);
|
||||||
|
|
||||||
assert.equal(Ember.$('.has-error').length, 0, "there is no validation error");
|
assert.equal(Ember.$('.has-error').length, 0, "there is no validation error");
|
||||||
|
|
||||||
andThen(function(){
|
andThen(function(){
|
||||||
|
assert.equal(currentPath(), 'poll.evaluation');
|
||||||
pollHasUsersCount(assert, 1, "user is added to user selections table");
|
pollHasUsersCount(assert, 1, "user is added to user selections table");
|
||||||
pollHasUser(assert, 'Max Meiner', [Ember.I18n.t('answerTypes.yes.label'), Ember.I18n.t('answerTypes.no.label')]);
|
pollHasUser(assert, 'Max Meiner', [Ember.I18n.t('answerTypes.yes.label'), Ember.I18n.t('answerTypes.no.label')]);
|
||||||
});
|
});
|
||||||
|
@ -73,11 +74,12 @@ test("participate in a poll using freetext", function(assert) {
|
||||||
);
|
);
|
||||||
|
|
||||||
visit('/poll/' + id + '?encryptionKey=' + encryptionKey).then(function() {
|
visit('/poll/' + id + '?encryptionKey=' + encryptionKey).then(function() {
|
||||||
|
assert.equal(currentPath(), 'poll.participation');
|
||||||
pollParticipate('Max Manus', ['answer 1', 'answer 2']);
|
pollParticipate('Max Manus', ['answer 1', 'answer 2']);
|
||||||
|
|
||||||
assert.equal(find('.has-error').length, 0, "there is no validation error");
|
assert.equal(find('.has-error').length, 0, "there is no validation error");
|
||||||
|
|
||||||
andThen(function(){
|
andThen(function(){
|
||||||
|
assert.equal(currentPath(), 'poll.evaluation');
|
||||||
pollHasUsersCount(assert, 1, "user is added to user selections table");
|
pollHasUsersCount(assert, 1, "user is added to user selections table");
|
||||||
pollHasUser(assert, 'Max Manus', ['answer 1', 'answer 2']);
|
pollHasUser(assert, 'Max Manus', ['answer 1', 'answer 2']);
|
||||||
});
|
});
|
||||||
|
@ -105,11 +107,12 @@ test("participate in a poll which doesn't force an answer to all options", funct
|
||||||
);
|
);
|
||||||
|
|
||||||
visit('/poll/' + id + '?encryptionKey=' + encryptionKey).then(function() {
|
visit('/poll/' + id + '?encryptionKey=' + encryptionKey).then(function() {
|
||||||
|
assert.equal(currentPath(), 'poll.participation');
|
||||||
pollParticipate('Karl Käfer', ['yes', null]);
|
pollParticipate('Karl Käfer', ['yes', null]);
|
||||||
|
|
||||||
assert.equal(Ember.$('.has-error').length, 0, "there is no validation error");
|
assert.equal(Ember.$('.has-error').length, 0, "there is no validation error");
|
||||||
|
|
||||||
andThen(function(){
|
andThen(function(){
|
||||||
|
assert.equal(currentPath(), 'poll.evaluation');
|
||||||
pollHasUsersCount(assert, 1, "user is added to user selections table");
|
pollHasUsersCount(assert, 1, "user is added to user selections table");
|
||||||
pollHasUser(assert, "Karl Käfer", [Ember.I18n.t("answerTypes.yes.label"), ""]);
|
pollHasUser(assert, "Karl Käfer", [Ember.I18n.t("answerTypes.yes.label"), ""]);
|
||||||
});
|
});
|
||||||
|
@ -137,11 +140,12 @@ test("participate in a poll which allows anonymous participation", function(asse
|
||||||
);
|
);
|
||||||
|
|
||||||
visit('/poll/' + id + '?encryptionKey=' + encryptionKey).then(function() {
|
visit('/poll/' + id + '?encryptionKey=' + encryptionKey).then(function() {
|
||||||
|
assert.equal(currentPath(), 'poll.participation');
|
||||||
pollParticipate(null, ['yes', 'no']);
|
pollParticipate(null, ['yes', 'no']);
|
||||||
|
|
||||||
assert.equal(Ember.$('.has-error').length, 0, "there is no validation error");
|
assert.equal(Ember.$('.has-error').length, 0, "there is no validation error");
|
||||||
|
|
||||||
andThen(function(){
|
andThen(function(){
|
||||||
|
assert.equal(currentPath(), 'poll.evaluation');
|
||||||
pollHasUsersCount(assert, 1, "user is added to user selections table");
|
pollHasUsersCount(assert, 1, "user is added to user selections table");
|
||||||
pollHasUser(assert, "", [Ember.I18n.t("answerTypes.yes.label"), Ember.I18n.t("answerTypes.no.label")]);
|
pollHasUser(assert, "", [Ember.I18n.t("answerTypes.yes.label"), Ember.I18n.t("answerTypes.no.label")]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -39,7 +39,12 @@ test('evaluation is not present for poll without participants', function(assert)
|
||||||
visit('/poll/' + id + '?encryptionKey=' + encryptionKey);
|
visit('/poll/' + id + '?encryptionKey=' + encryptionKey);
|
||||||
|
|
||||||
andThen(function() {
|
andThen(function() {
|
||||||
assert.equal(find('.evaluation').length, 0);
|
assert.equal(currentPath(), 'poll.participation');
|
||||||
|
switchTab('evaluation');
|
||||||
|
|
||||||
|
andThen(function() {
|
||||||
|
assert.equal(find('.tab-content .evaluation').length, 0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -116,19 +121,25 @@ test('evaluation is correct', function(assert) {
|
||||||
visit('/poll/' + id + '?encryptionKey=' + encryptionKey);
|
visit('/poll/' + id + '?encryptionKey=' + encryptionKey);
|
||||||
|
|
||||||
andThen(function() {
|
andThen(function() {
|
||||||
assert.equal(find('.evaluation').length, 1, 'evaluation is present');
|
assert.equal(currentPath(), 'poll.participation');
|
||||||
assert.notEqual(
|
switchTab('evaluation');
|
||||||
find('.participants').text().indexOf(' 2 '),
|
|
||||||
-1,
|
andThen(function() {
|
||||||
'participants are counted correctly'
|
assert.equal(currentPath(), 'poll.evaluation');
|
||||||
);
|
assert.equal(find('.tab-content .evaluation').length, 1, 'evaluation is present');
|
||||||
assert.equal(find('.best-options strong').text().trim(), formattedDateHelper('2015-12-12'), 'options are evaluated correctly');
|
assert.notEqual(
|
||||||
assert.notEqual(
|
find('.participants').text().indexOf(' 2 '),
|
||||||
find('.last-participation').text().indexOf(
|
-1,
|
||||||
moment('2015-08-01T00:00:00.000Z').from()
|
'participants are counted correctly'
|
||||||
),
|
);
|
||||||
-1,
|
assert.equal(find('.best-options strong').text().trim(), formattedDateHelper('2015-12-12'), 'options are evaluated correctly');
|
||||||
'last participation is evaluated correctly'
|
assert.notEqual(
|
||||||
);
|
find('.last-participation').text().indexOf(
|
||||||
|
moment('2015-08-01T00:00:00.000Z').from()
|
||||||
|
),
|
||||||
|
-1,
|
||||||
|
'last participation is evaluated correctly'
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,6 +22,24 @@ module('Acceptance | view poll', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('view poll url', function(assert) {
|
||||||
|
var id = 'test',
|
||||||
|
encryptionKey = 'abcdefghijklmnopqrstuvwxyz012345789';
|
||||||
|
|
||||||
|
server.get('/polls/' + id, function() {
|
||||||
|
return serverGetPolls({ id: id }, encryptionKey);
|
||||||
|
});
|
||||||
|
|
||||||
|
visit('/poll/' + id + '?encryptionKey=' + encryptionKey);
|
||||||
|
andThen(function() {
|
||||||
|
assert.equal(
|
||||||
|
find('.share-link .link a').text(),
|
||||||
|
window.location.href,
|
||||||
|
'share link is shown'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('view a poll with dates', function(assert) {
|
test('view a poll with dates', function(assert) {
|
||||||
var id = 'test',
|
var id = 'test',
|
||||||
encryptionKey = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
encryptionKey = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
||||||
|
|
|
@ -8,6 +8,7 @@ import './poll-has-users';
|
||||||
import './poll-has-options';
|
import './poll-has-options';
|
||||||
import './poll-has-answers';
|
import './poll-has-answers';
|
||||||
import './poll-participate';
|
import './poll-participate';
|
||||||
|
import './switch-tab';
|
||||||
|
|
||||||
export default function startApp(attrs) {
|
export default function startApp(attrs) {
|
||||||
var application;
|
var application;
|
||||||
|
|
5
tests/helpers/switch-tab.js
Normal file
5
tests/helpers/switch-tab.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
export default Ember.Test.registerAsyncHelper('switchTab', function(app, tab) {
|
||||||
|
click('.nav-tabs .' + tab + ' a');
|
||||||
|
});
|
|
@ -42,7 +42,7 @@ test("create a default poll and participate", function(assert) {
|
||||||
click('.button-next');
|
click('.button-next');
|
||||||
|
|
||||||
andThen(function(){
|
andThen(function(){
|
||||||
assert.equal(currentPath(), 'poll');
|
assert.equal(currentPath(), 'poll.participation');
|
||||||
|
|
||||||
pollTitleEqual(assert, 'default poll');
|
pollTitleEqual(assert, 'default poll');
|
||||||
pollDescriptionEqual(assert, '');
|
pollDescriptionEqual(assert, '');
|
||||||
|
@ -62,6 +62,7 @@ test("create a default poll and participate", function(assert) {
|
||||||
pollHasUsersCount(assert, 0);
|
pollHasUsersCount(assert, 0);
|
||||||
pollParticipate('Max Hoelz', ['no', 'no']);
|
pollParticipate('Max Hoelz', ['no', 'no']);
|
||||||
andThen(function(){
|
andThen(function(){
|
||||||
|
assert.equal(currentPath(), 'poll.evaluation');
|
||||||
pollHasUsersCount(assert, 1);
|
pollHasUsersCount(assert, 1);
|
||||||
pollHasUser(assert, 'Max Hoelz', [Ember.I18n.t('answerTypes.no.label'), Ember.I18n.t('answerTypes.no.label')]);
|
pollHasUser(assert, 'Max Hoelz', [Ember.I18n.t('answerTypes.no.label'), Ember.I18n.t('answerTypes.no.label')]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -53,33 +53,47 @@ test('show a default poll created with v0.3.0', function(assert) {
|
||||||
Ember.I18n.t('answerTypes.no.label')
|
Ember.I18n.t('answerTypes.no.label')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
pollHasUser(assert,
|
switchTab('evaluation');
|
||||||
'Fritz Bauer',
|
|
||||||
[
|
|
||||||
Ember.I18n.t('answerTypes.yes.label'),
|
|
||||||
Ember.I18n.t('answerTypes.no.label'),
|
|
||||||
Ember.I18n.t('answerTypes.no.label')
|
|
||||||
]
|
|
||||||
);
|
|
||||||
pollHasUser(assert,
|
|
||||||
'Lothar Hermann',
|
|
||||||
[
|
|
||||||
Ember.I18n.t('answerTypes.maybe.label'),
|
|
||||||
Ember.I18n.t('answerTypes.yes.label'),
|
|
||||||
Ember.I18n.t('answerTypes.no.label')
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
pollParticipate('Hermann Langbein', ['yes', 'maybe', 'yes']);
|
|
||||||
andThen(function() {
|
andThen(function() {
|
||||||
|
assert.equal(currentPath(), 'poll.evaluation');
|
||||||
|
|
||||||
pollHasUser(assert,
|
pollHasUser(assert,
|
||||||
'Hermann Langbein',
|
'Fritz Bauer',
|
||||||
[
|
[
|
||||||
Ember.I18n.t('answerTypes.yes.label'),
|
Ember.I18n.t('answerTypes.yes.label'),
|
||||||
Ember.I18n.t('answerTypes.maybe.label'),
|
Ember.I18n.t('answerTypes.no.label'),
|
||||||
Ember.I18n.t('answerTypes.yes.label')
|
Ember.I18n.t('answerTypes.no.label')
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
pollHasUser(assert,
|
||||||
|
'Lothar Hermann',
|
||||||
|
[
|
||||||
|
Ember.I18n.t('answerTypes.maybe.label'),
|
||||||
|
Ember.I18n.t('answerTypes.yes.label'),
|
||||||
|
Ember.I18n.t('answerTypes.no.label')
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
switchTab('participation');
|
||||||
|
|
||||||
|
andThen(function() {
|
||||||
|
assert.equal(currentPath(), 'poll.participation');
|
||||||
|
|
||||||
|
pollParticipate('Hermann Langbein', ['yes', 'maybe', 'yes']);
|
||||||
|
|
||||||
|
andThen(function() {
|
||||||
|
assert.equal(currentPath(), 'poll.evaluation');
|
||||||
|
pollHasUser(assert,
|
||||||
|
'Hermann Langbein',
|
||||||
|
[
|
||||||
|
Ember.I18n.t('answerTypes.yes.label'),
|
||||||
|
Ember.I18n.t('answerTypes.maybe.label'),
|
||||||
|
Ember.I18n.t('answerTypes.yes.label')
|
||||||
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -100,25 +114,37 @@ test('find a poll using free text created with v0.3.0', function(assert) {
|
||||||
'plum pie'
|
'plum pie'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
pollHasUser(assert,
|
switchTab('evaluation');
|
||||||
'Paul Levi',
|
|
||||||
[
|
|
||||||
'would be great!',
|
|
||||||
'no way',
|
|
||||||
'if I had to'
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
pollParticipate('Hermann Langbein', ["I don't care", 'would be awesome', "can't imagine anything better"]);
|
|
||||||
andThen(function() {
|
andThen(function() {
|
||||||
|
assert.equal(currentPath(), 'poll.evaluation');
|
||||||
pollHasUser(assert,
|
pollHasUser(assert,
|
||||||
'Hermann Langbein',
|
'Paul Levi',
|
||||||
[
|
[
|
||||||
"I don't care",
|
'would be great!',
|
||||||
'would be awesome',
|
'no way',
|
||||||
"can't imagine anything better"
|
'if I had to'
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
switchTab('participation');
|
||||||
|
|
||||||
|
andThen(function() {
|
||||||
|
assert.equal(currentPath(), 'poll.participation');
|
||||||
|
pollParticipate('Hermann Langbein', ["I don't care", 'would be awesome', "can't imagine anything better"]);
|
||||||
|
|
||||||
|
andThen(function() {
|
||||||
|
assert.equal(currentPath(), 'poll.evaluation');
|
||||||
|
pollHasUser(assert,
|
||||||
|
'Hermann Langbein',
|
||||||
|
[
|
||||||
|
"I don't care",
|
||||||
|
'would be awesome',
|
||||||
|
"can't imagine anything better"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
12
tests/unit/controllers/poll/participation-test.js
Normal file
12
tests/unit/controllers/poll/participation-test.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { moduleFor, test } from 'ember-qunit';
|
||||||
|
|
||||||
|
moduleFor('controller:poll/participation', {
|
||||||
|
// Specify the other units that are required for this test.
|
||||||
|
// needs: ['controller:foo']
|
||||||
|
});
|
||||||
|
|
||||||
|
// Replace this with your real tests.
|
||||||
|
test('it exists', function(assert) {
|
||||||
|
var controller = this.subject();
|
||||||
|
assert.ok(controller);
|
||||||
|
});
|
Loading…
Reference in a new issue