diff --git a/openslides/assignments/static/js/assignments/base.js b/openslides/assignments/static/js/assignments/base.js index da843f9a8..35d595d02 100644 --- a/openslides/assignments/static/js/assignments/base.js +++ b/openslides/assignments/static/js/assignments/base.js @@ -6,9 +6,55 @@ angular.module('OpenSlidesApp.assignments', []) .factory('AssignmentPollOption', [ 'DS', - function (DS) { + 'jsDataModel', + 'gettextCatalog', + 'Config', + function (DS, jsDataModel, gettextCatalog, Config) { return DS.defineResource({ name: 'assignments/polloption', + useClass: jsDataModel, + methods: { + getVotes: function () { + if (!this.poll.has_votes) { + return; + } + var poll = this.poll; + var votes = []; + var config = Config.get('assignments_poll_100_percent_base').value; + angular.forEach(this.votes, function(vote) { + // check for special value + var value; + switch (vote.weight) { + case -1: + value = gettextCatalog.getString('majority'); + break; + case -2: + value = gettextCatalog.getString('undocumented'); + break; + default: + value = vote.weight; + break; + } + // calculate percent value + var percentStr, percentNumber; + if (config == "WITHOUT_INVALID" && poll.votesvalid > 0 && vote.weight >= 0) { + percentNumber = Math.round(vote.weight * 100 / poll.votesvalid * 10) / 10; + } else if (config == "WITH_INVALID" && poll.votescast > 0 && vote.weight >= 0) { + percentNumber = Math.round(vote.weight * 100 / (poll.votescast) * 10) / 10; + } + if (percentNumber) { + percentStr = "(" + percentNumber + "%)"; + } + votes.push({ + 'label': gettextCatalog.getString(vote.value), + 'value': value, + 'percentStr': percentStr, + 'percentNumber': percentNumber + }); + }); + return votes; + } + }, relations: { belongsTo: { 'assignments/poll': { @@ -27,10 +73,43 @@ angular.module('OpenSlidesApp.assignments', []) .factory('AssignmentPoll', [ 'DS', + 'gettextCatalog', 'AssignmentPollOption', - function (DS, AssignmentPollOption) { + 'Config', + function (DS, gettextCatalog, AssignmentPollOption, Config) { return DS.defineResource({ name: 'assignments/poll', + methods: { + // returns object with value and percent (for votes valid/invalid/cast only) + getVote: function (vote) { + if (!this.has_votes || !vote) { + return; + } + var value = ''; + switch (vote) { + case -1: + value = gettextCatalog.getString('majority'); + break; + case -2: + value = gettextCatalog.getString('undocumented'); + break; + default: + value = vote; + break; + } + // calculate percent value + var config = Config.get('assignments_poll_100_percent_base').value; + var percent; + if ((config == "WITHOUT_INVALID" && vote == this.votesvalid && vote >= 0) || + (config == "WITH_INVALID" && vote == this.votescast && vote >= 0)) { + percent = '(100%)'; + } + return { + 'value': value, + 'percent': percent + }; + }, + }, relations: { belongsTo: { 'assignments/assignment': { diff --git a/openslides/assignments/static/js/assignments/site.js b/openslides/assignments/static/js/assignments/site.js index 28358bab1..4f2c9bdda 100644 --- a/openslides/assignments/static/js/assignments/site.js +++ b/openslides/assignments/static/js/assignments/site.js @@ -254,6 +254,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) .controller('AssignmentDetailCtrl', [ '$scope', '$http', + 'filterFilter', 'gettext', 'ngDialog', 'AssignmentForm', @@ -262,7 +263,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) 'User', 'assignment', 'phases', - function($scope, $http, gettext, ngDialog, AssignmentForm, operator, Assignment, User, assignment, phases) { + function($scope, $http, filterFilter, gettext, ngDialog, AssignmentForm, operator, Assignment, User, assignment, phases) { User.bindAll({}, $scope, 'users'); Assignment.bindOne(assignment.id, $scope, 'assignment'); Assignment.loadRelations(assignment, 'agenda_item'); @@ -337,6 +338,9 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) $http.post('/rest/assignments/assignment/' + assignment.id + '/create_poll/') .success(function(data){ $scope.alert.show = false; + if (assignment.phase == 0) { + $scope.updatePhase(1); + } }) .error(function(data){ $scope.alert = { type: 'danger', msg: data.detail, show: true }; @@ -390,6 +394,15 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) data: JSON.stringify({user: user})}) } else { $http.post('/rest/assignments/assignment/' + assignment.id + '/mark_elected/', {'user': user}) + .then(function(success) { + var elected = filterFilter(assignment.assignment_related_users,{elected: true}); + // Set phase to 'finished' if there are enough (= number of open posts) elected users. + // Note: The array 'elected' does NOT contains the candidate who is just marked as elected. + // So add 1 to length to get the real number of all elected users. + if (elected.length + 1 == assignment.open_posts ) { + $scope.updatePhase(2); + } + }); } }; @@ -490,8 +503,9 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) 'assignmentpoll', 'ballot', function($scope, gettextCatalog, AssignmentPoll, assignmentpoll, ballot) { - // set initial values for form model - $scope.model = assignmentpoll; + // set initial values for form model by create deep copy of assignmentpoll object + // so detail view is not updated while editing poll + $scope.model = angular.copy(assignmentpoll); $scope.ballot = ballot; $scope.formFields = []; $scope.alert = {}; @@ -499,6 +513,16 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) // add dynamic form fields assignmentpoll.options.forEach(function(option) { if (assignmentpoll.yesnoabstain) { + var defaultValue = { + 'yes': '', + 'no': '', + 'abstain': '' + }; + if (option.votes.length) { + defaultValue.yes = option.votes[0].weight; + defaultValue.no = option.votes[1].weight; + defaultValue.abstain = option.votes[2].weight; + } $scope.formFields.push( { noFormControl: true, @@ -511,7 +535,8 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) label: gettextCatalog.getString('Yes'), type: 'number', required: true - } + }, + defaultValue: defaultValue.yes }, { key: 'no_' + option.candidate_id, @@ -520,7 +545,8 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) label: gettextCatalog.getString('No'), type: 'number', required: true - } + }, + defaultValue: defaultValue.no }, { key:'abstain_' + option.candidate_id, @@ -529,9 +555,14 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) label: gettextCatalog.getString('Abstain'), type: 'number', required: true - } + }, + defaultValue: defaultValue.abstain }); } else { + var defaultValue; + if (option.votes.length) { + defaultValue = option.votes[0].weight; + } $scope.formFields.push( { key: 'vote_' + option.candidate_id, @@ -540,7 +571,8 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) label: option.candidate.get_full_name(), type: 'number', required: true - } + }, + defaultValue: defaultValue }); } }); @@ -599,6 +631,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments']) }); }); } + // save change poll object on server poll.DSUpdate({ assignment_id: poll.assignment_id, votes: votes, diff --git a/openslides/assignments/static/templates/assignments/assignment-detail.html b/openslides/assignments/static/templates/assignments/assignment-detail.html index 2d4e1ef26..ff669c535 100644 --- a/openslides/assignments/static/templates/assignments/assignment-detail.html +++ b/openslides/assignments/static/templates/assignments/assignment-detail.html @@ -150,7 +150,9 @@ Published - + Delete @@ -160,43 +162,54 @@ Elected Candidates - Votes + Votes + + + + + + {{ option.candidate.get_full_name() }} + + - - {{ option.votes[0].value | translate }}: {{ option.votes[0].weight }}
- {{ option.votes[1].value | translate }}: {{ option.votes[1].weight }}
- {{ option.votes[2].value | translate }}: {{ option.votes[2].weight }} -
- - {{ option.votes[0].weight}} - +
+
+ {{ vote.label }}: + {{ vote.value }} {{ vote.percentStr }} +
+ +
+
+
+ + Valid votes - - {{ poll.votesvalid }} + + {{ vote.value }} {{ vote.percent }} Invalid votes - - {{ poll.votesinvalid }} + + {{ vote.value }} Votes cast - - {{ poll.votescast }} + + {{ vote.value }} {{ vote.percent }}