Merge pull request #3740 from FinnStutzenstein/voting-plugin

Changes for the voting plugin and usability improvements
This commit is contained in:
Emanuel Schütze 2018-05-29 15:02:37 +02:00 committed by GitHub
commit 407b640f80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 50 additions and 19 deletions

View File

@ -40,11 +40,16 @@ class AssignmentAccessPermissions(BaseAccessPermissions):
if has_perm(user, 'assignments.can_see') and has_perm(user, 'assignments.can_manage'):
data = full_data
elif has_perm(user, 'assignments.can_see'):
# Exclude unpublished polls.
# Exclude unpublished poll votes.
data = []
for full in full_data:
full_copy = full.copy()
full_copy['polls'] = [poll for poll in full['polls'] if poll['published']]
polls = full_copy['polls']
for poll in polls:
if not poll['published']:
for option in poll['options']:
option['votes'] = [] # clear votes for not published polls
poll['has_votes'] = False # A user should see, if there are votes.
data.append(full_copy)
else:
data = []

View File

@ -337,9 +337,12 @@ angular.module('OpenSlidesApp.assignments', [])
getResourceName: function () {
return name;
},
getAgendaTitle: function () {
getTitle: function () {
return this.title;
},
getAgendaTitle: function () {
return this.getTitle();
},
// link name which is shown in search result
getSearchResultName: function () {
return this.getAgendaTitle();

View File

@ -716,14 +716,12 @@ angular.module('OpenSlidesApp.assignments.site', [
defaultValue[vote.value.toLowerCase()] = vote.weight;
});
$scope.formFields.push(
{
noFormControl: true,
template: '<strong>' + option.candidate.get_full_name() + '</strong>'
},
var columnClass = (assignmentpoll.pollmethod === 'yna') ? 'col-xs-4' : 'col-xs-6';
var columns = [
{
key: 'yes_' + option.candidate_id,
type: 'input',
className: columnClass + ' no-padding-left',
templateOptions: {
label: gettextCatalog.getString('Yes'),
type: 'number',
@ -735,6 +733,8 @@ angular.module('OpenSlidesApp.assignments.site', [
{
key: 'no_' + option.candidate_id,
type: 'input',
className: columnClass + ' no-padding-left' +
(assignmentpoll.pollmethod === 'yn' ? ' no-padding-right' : ''),
templateOptions: {
label: gettextCatalog.getString('No'),
type: 'number',
@ -743,12 +743,12 @@ angular.module('OpenSlidesApp.assignments.site', [
},
defaultValue: defaultValue.no
}
);
];
if (assignmentpoll.pollmethod == 'yna'){
$scope.formFields.push(
{
columns.push({
key:'abstain_' + option.candidate_id,
type: 'input',
className: columnClass + ' no-padding-left no-padding-right',
templateOptions: {
label: gettextCatalog.getString('Abstain'),
type: 'number',
@ -758,6 +758,14 @@ angular.module('OpenSlidesApp.assignments.site', [
defaultValue: defaultValue.abstain
});
}
$scope.formFields.push({
noFormControl: true,
template: '<strong>' + option.candidate.get_full_name() + '</strong>'
},
{
className: 'row',
fieldGroup: columns,
});
} else { // votes method
if (option.votes.length) {
defaultValue = option.votes[0].weight;

View File

@ -191,8 +191,10 @@ class AssignmentViewSet(ModelViewSet):
if not assignment.candidates.exists():
raise ValidationError({'detail': _('Can not create ballot because there are no candidates.')})
with transaction.atomic():
assignment.create_poll()
return Response({'detail': _('Ballot created successfully.')})
poll = assignment.create_poll()
return Response({
'detail': _('Ballot created successfully.'),
'createdPollId': poll.pk})
@detail_route(methods=['post'])
def sort_related_users(self, request, pk=None):

View File

@ -155,6 +155,7 @@ angular.module('OpenSlidesApp.core', [
'User',
'Group',
function (User, Group) {
var setUserCallbacks = [];
var operator = {
user: null,
perms: [],
@ -167,6 +168,10 @@ angular.module('OpenSlidesApp.core', [
} else {
operator.user = null;
}
operator.reloadPerms();
_.forEach(setUserCallbacks, function (cb) {
cb(operator.user);
});
},
// Returns true if the operator has at least one perm of the perms-list.
hasPerms: function(perms) {
@ -191,6 +196,9 @@ angular.module('OpenSlidesApp.core', [
}
return _.indexOf(groups, group.id) > -1;
},
registerSetUserCallback: function (cb) {
setUserCallbacks.push(cb);
},
};
return operator;
}
@ -715,6 +723,7 @@ angular.module('OpenSlidesApp.core', [
});
}
scope.content = '';
if (attributes.content) {
attributes.$observe('content', function (content) {
scope.content = content;
@ -816,8 +825,9 @@ angular.module('OpenSlidesApp.core', [
* provide also html markup for the messages. There are 4 types: 'info',
* 'success', 'warning', 'error'. The timeout is for autodeleting the message.
* Args that could be provided:
* - timeout: Milliseconds until autoclose the message
* - noClose: Whether to show the close button*/
* - timeout: Milliseconds until autoclose the message (default: not set, no auto close)
* - noClose: Whether to show the close button (default: false)
*/
.factory('Messaging', [
'$timeout',
function($timeout) {

View File

@ -6,7 +6,7 @@
ng-click="model.project(defaultProjectorId, arg)"
ng-class="{ 'btn-primary': inArray(model.isProjected(arg), defaultProjectorId) }">
<i class="fa fa-video-camera"></i>
{{ content }}
{{ content | translate }}
</button>
<button type="button" class="btn btn-default btn-sm slimDropDown"
ng-class="{ 'btn-primary': (model.isProjected(arg).length && !inArray(model.isProjected(arg), defaultProjectorId)) }"

View File

@ -346,6 +346,7 @@
</div>
<div class="col-sm-4">
<h3 ng-if="motion.polls.length > 0" translate>Voting result</h3>
<template-hook hook-name="motionPollVotingHeader"></template-hook>
<ol>
<li ng-controller="MotionPollDetailCtrl" ng-repeat="poll in motion.polls" class="spacer"
ng-if="poll.has_votes || operator.hasPerms('motions.can_manage')">

View File

@ -115,7 +115,7 @@ angular.module('OpenSlidesApp.users.pdf', ['OpenSlidesApp.core.pdf'])
var createInstance = function(userList) {
var creadeUserHeadLine = function(user) {
var createUserHeadLine = function(user) {
var titleLine = [];
titleLine.push({
text: user.get_short_name(),
@ -260,7 +260,7 @@ angular.module('OpenSlidesApp.users.pdf', ['OpenSlidesApp.core.pdf'])
var getContent = function() {
var content = [];
angular.forEach(userList, function (user, index) {
content.push(creadeUserHeadLine(user));
content.push(createUserHeadLine(user));
content.push(createAccessDataContent(user));
content.push(createWelcomeText());
// No pagebreak after the last user

View File

@ -355,7 +355,9 @@
<div os-perms="users.can_manage" ng-class="{'hiddenDiv': !user.hover}">
<small>
<template-hook hook-name="userListEditButton">
<span>
<a href="" ng-click="openDialog(user)" translate>Edit</a> &middot;
</span>
</template-hook>
<a ui-sref="users.user.change-password({id: user.id})" translate>Change password</a> &middot;
<a href="" class="text-danger"