Motion template fixes
- Add has_votes to motion serializer and add poll.has_votes check in motion detail view. - Fix motion meta box 3 column layout. - Added missing intents - Show motionPoll edit form in dialog. Moved into new template. - Clean up assignmentpoll form (like motionPoll)
This commit is contained in:
parent
440a38b387
commit
694ed6f1cc
@ -136,40 +136,6 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
// Provide generic assignmentpoll form fields for create and update view
|
|
||||||
.factory('AssignmentPollFormFieldFactory', [
|
|
||||||
'gettextCatalog',
|
|
||||||
function (gettextCatalog) {
|
|
||||||
return {
|
|
||||||
getFormFields: function () {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
key: 'description',
|
|
||||||
type: 'input',
|
|
||||||
templateOptions: {
|
|
||||||
label: gettextCatalog.getString('Comment on the ballot paper')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'yes',
|
|
||||||
type: 'input',
|
|
||||||
templateOptions: {
|
|
||||||
label: gettextCatalog.getString('Yes'),
|
|
||||||
type: 'number',
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'poll_description_default',
|
|
||||||
type: 'input',
|
|
||||||
templateOptions: {
|
|
||||||
label: gettextCatalog.getString('Default comment on the ballot paper')
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
])
|
|
||||||
.controller('AssignmentListCtrl', [
|
.controller('AssignmentListCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'ngDialog',
|
'ngDialog',
|
||||||
@ -340,6 +306,8 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
|
|||||||
template: 'static/templates/assignments/assignmentpoll-form.html',
|
template: 'static/templates/assignments/assignmentpoll-form.html',
|
||||||
controller: 'AssignmentPollUpdateCtrl',
|
controller: 'AssignmentPollUpdateCtrl',
|
||||||
className: 'ngdialog-theme-default',
|
className: 'ngdialog-theme-default',
|
||||||
|
closeByEscape: false,
|
||||||
|
closeByDocument: false,
|
||||||
resolve: {
|
resolve: {
|
||||||
assignmentpoll: function (AssignmentPoll) {
|
assignmentpoll: function (AssignmentPoll) {
|
||||||
return AssignmentPoll.find(poll.id);
|
return AssignmentPoll.find(poll.id);
|
||||||
@ -443,6 +411,8 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
|
|||||||
$scope.model = assignmentpoll;
|
$scope.model = assignmentpoll;
|
||||||
$scope.ballot = ballot;
|
$scope.ballot = ballot;
|
||||||
$scope.formFields = [];
|
$scope.formFields = [];
|
||||||
|
$scope.alert = {};
|
||||||
|
|
||||||
// add dynamic form fields
|
// add dynamic form fields
|
||||||
assignmentpoll.options.forEach(function(option) {
|
assignmentpoll.options.forEach(function(option) {
|
||||||
if (assignmentpoll.yesnoabstain) {
|
if (assignmentpoll.yesnoabstain) {
|
||||||
@ -528,9 +498,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// save assignmentpoll
|
||||||
|
|
||||||
// save assignment
|
|
||||||
$scope.save = function (poll) {
|
$scope.save = function (poll) {
|
||||||
var votes = [];
|
var votes = [];
|
||||||
if (assignmentpoll.yesnoabstain) {
|
if (assignmentpoll.yesnoabstain) {
|
||||||
@ -556,8 +524,16 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
|
|||||||
votescast: poll.votescast
|
votescast: poll.votescast
|
||||||
})
|
})
|
||||||
.then(function(success) {
|
.then(function(success) {
|
||||||
|
$scope.alert.show = false;
|
||||||
$scope.closeThisDialog();
|
$scope.closeThisDialog();
|
||||||
})
|
})
|
||||||
|
.catch(function(error) {
|
||||||
|
var message = '';
|
||||||
|
for (var e in error.data) {
|
||||||
|
message += e + ': ' + error.data[e] + ' ';
|
||||||
|
}
|
||||||
|
$scope.alert = { type: 'danger', msg: message, show: true };
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -1,8 +1,17 @@
|
|||||||
<h1><translate>Ballot</translate> {{ ballot }}</h1>
|
<h1><translate>Ballot</translate> {{ ballot }}</h1>
|
||||||
|
|
||||||
<form name="assignmentpollForm" ng-submit="save(model)">
|
<alert ng-show="alert.show" type="{{ alert.type }}" ng-click="alert={}" close="alert={}">
|
||||||
|
{{ alert.msg }}
|
||||||
|
</alert>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<translate>Special values</translate>:
|
||||||
|
<span class="badge badge-success">-1</span> = <translate>majority</translate>
|
||||||
|
<span class="badge">-2</span> = <translate>undocumented</translate>
|
||||||
|
|
||||||
|
<form name="assignmentPollForm" ng-submit="save(model)">
|
||||||
<formly-form model="model" fields="formFields">
|
<formly-form model="model" fields="formFields">
|
||||||
<button type="submit" ng-disabled="assignmentForm.$invalid" class="btn btn-primary" translate>
|
<button type="submit" ng-disabled="assignmentPollForm.$invalid" class="btn btn-primary" translate>
|
||||||
Save
|
Save
|
||||||
</button>
|
</button>
|
||||||
<button ng-click="closeThisDialog()" class="btn btn-default" translate>
|
<button ng-click="closeThisDialog()" class="btn btn-default" translate>
|
||||||
|
@ -100,6 +100,7 @@ class MotionPollSerializer(ModelSerializer):
|
|||||||
votes = DictField(
|
votes = DictField(
|
||||||
child=IntegerField(min_value=-2, allow_null=True),
|
child=IntegerField(min_value=-2, allow_null=True),
|
||||||
write_only=True)
|
write_only=True)
|
||||||
|
has_votes = SerializerMethodField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = MotionPoll
|
model = MotionPoll
|
||||||
@ -112,7 +113,8 @@ class MotionPollSerializer(ModelSerializer):
|
|||||||
'votesvalid',
|
'votesvalid',
|
||||||
'votesinvalid',
|
'votesinvalid',
|
||||||
'votescast',
|
'votescast',
|
||||||
'votes',)
|
'votes',
|
||||||
|
'has_votes')
|
||||||
|
|
||||||
def to_representation(self, obj):
|
def to_representation(self, obj):
|
||||||
"""
|
"""
|
||||||
@ -150,6 +152,12 @@ class MotionPollSerializer(ModelSerializer):
|
|||||||
result = None
|
result = None
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def get_has_votes(self, obj):
|
||||||
|
"""
|
||||||
|
Returns True if this poll has some votes.
|
||||||
|
"""
|
||||||
|
return obj.has_votes()
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def update(self, instance, validated_data):
|
def update(self, instance, validated_data):
|
||||||
"""
|
"""
|
||||||
|
@ -295,6 +295,69 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
// Provide generic motionpoll form fields for poll update view
|
||||||
|
.factory('MotionPollForm', [
|
||||||
|
'gettextCatalog',
|
||||||
|
function (gettextCatalog) {
|
||||||
|
return {
|
||||||
|
getFormFields: function () {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
key: 'yes',
|
||||||
|
type: 'input',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Yes'),
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'no',
|
||||||
|
type: 'input',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('No'),
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'abstain',
|
||||||
|
type: 'input',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Abstain'),
|
||||||
|
type: 'number',
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'votesvalid',
|
||||||
|
type: 'input',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Valid votes'),
|
||||||
|
type: 'number'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'votesinvalid',
|
||||||
|
type: 'input',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Invalid votes'),
|
||||||
|
type: 'number'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'votescast',
|
||||||
|
type: 'input',
|
||||||
|
templateOptions: {
|
||||||
|
label: gettextCatalog.getString('Votes cast'),
|
||||||
|
type: 'number'
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
.controller('MotionListCtrl', [
|
.controller('MotionListCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'$state',
|
'$state',
|
||||||
@ -430,58 +493,54 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
|
|||||||
Workflow.bindAll({}, $scope, 'workflows');
|
Workflow.bindAll({}, $scope, 'workflows');
|
||||||
Motion.loadRelations(motion, 'agenda_item');
|
Motion.loadRelations(motion, 'agenda_item');
|
||||||
|
|
||||||
$scope.alert = {};
|
|
||||||
$scope.isCollapsed = true;
|
$scope.isCollapsed = true;
|
||||||
|
|
||||||
// open edit dialog
|
// open edit dialog
|
||||||
$scope.openDialog = function (motion) {
|
$scope.openDialog = function (motion) {
|
||||||
ngDialog.open(MotionForm.getDialog(motion));
|
ngDialog.open(MotionForm.getDialog(motion));
|
||||||
};
|
};
|
||||||
|
// support
|
||||||
$scope.support = function () {
|
$scope.support = function () {
|
||||||
$http.post('/rest/motions/motion/' + motion.id + '/support/');
|
$http.post('/rest/motions/motion/' + motion.id + '/support/');
|
||||||
}
|
}
|
||||||
|
// unsupport
|
||||||
$scope.unsupport = function () {
|
$scope.unsupport = function () {
|
||||||
$http.delete('/rest/motions/motion/' + motion.id + '/support/');
|
$http.delete('/rest/motions/motion/' + motion.id + '/support/');
|
||||||
}
|
}
|
||||||
|
// update state
|
||||||
$scope.updateState = function (state_id) {
|
$scope.updateState = function (state_id) {
|
||||||
$http.put('/rest/motions/motion/' + motion.id + '/set_state/', {'state': state_id});
|
$http.put('/rest/motions/motion/' + motion.id + '/set_state/', {'state': state_id});
|
||||||
}
|
}
|
||||||
|
// reset state
|
||||||
$scope.reset_state = function (state_id) {
|
$scope.reset_state = function (state_id) {
|
||||||
$http.put('/rest/motions/motion/' + motion.id + '/set_state/', {});
|
$http.put('/rest/motions/motion/' + motion.id + '/set_state/', {});
|
||||||
}
|
}
|
||||||
|
// create poll
|
||||||
$scope.create_poll = function () {
|
$scope.create_poll = function () {
|
||||||
$http.post('/rest/motions/motion/' + motion.id + '/create_poll/', {})
|
$http.post('/rest/motions/motion/' + motion.id + '/create_poll/', {});
|
||||||
.success(function(data){
|
|
||||||
$scope.alert.show = false;
|
|
||||||
})
|
|
||||||
.error(function(data){
|
|
||||||
$scope.alert = { type: 'danger', msg: data.detail, show: true };
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
// open poll update dialog
|
||||||
|
$scope.openPollDialog = function (poll, voteNumber) {
|
||||||
|
ngDialog.open({
|
||||||
|
template: 'static/templates/motions/motionpoll-form.html',
|
||||||
|
controller: 'MotionPollUpdateCtrl',
|
||||||
|
className: 'ngdialog-theme-default',
|
||||||
|
closeByEscape: false,
|
||||||
|
closeByDocument: false,
|
||||||
|
resolve: {
|
||||||
|
motionpoll: function (MotionPoll) {
|
||||||
|
return MotionPoll.find(poll.id);
|
||||||
|
},
|
||||||
|
voteNumber: function () {
|
||||||
|
return voteNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// delete poll
|
||||||
$scope.delete_poll = function (poll) {
|
$scope.delete_poll = function (poll) {
|
||||||
poll.DSDestroy();
|
poll.DSDestroy();
|
||||||
}
|
}
|
||||||
$scope.update_poll = function (poll) {
|
|
||||||
poll.DSUpdate({
|
|
||||||
motion_id: motion.id,
|
|
||||||
votes: {"Yes": poll.yes, "No": poll.no, "Abstain": poll.abstain},
|
|
||||||
votesvalid: poll.votesvalid,
|
|
||||||
votesinvalid: poll.votesinvalid,
|
|
||||||
votescast: poll.votescast
|
|
||||||
})
|
|
||||||
.then(function(success) {
|
|
||||||
$scope.alert.show = false;
|
|
||||||
poll.isEditMode = false;
|
|
||||||
})
|
|
||||||
.catch(function(error) {
|
|
||||||
var message = '';
|
|
||||||
for (var e in error.data) {
|
|
||||||
message += e + ': ' + error.data[e] + ' ';
|
|
||||||
}
|
|
||||||
$scope.alert = { type: 'danger', msg: message, show: true };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -587,6 +646,45 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
.controller('MotionPollUpdateCtrl', [
|
||||||
|
'$scope',
|
||||||
|
'$state',
|
||||||
|
'gettextCatalog',
|
||||||
|
'MotionPoll',
|
||||||
|
'MotionPollForm',
|
||||||
|
'motionpoll',
|
||||||
|
'voteNumber',
|
||||||
|
function($scope, $state, gettextCatalog, MotionPoll, MotionPollForm, motionpoll, voteNumber) {
|
||||||
|
// set initial values for form model
|
||||||
|
$scope.model = motionpoll;
|
||||||
|
$scope.voteNumber = voteNumber;
|
||||||
|
$scope.formFields = MotionPollForm.getFormFields();
|
||||||
|
$scope.alert = {};
|
||||||
|
|
||||||
|
// save motionpoll
|
||||||
|
$scope.save = function (poll) {
|
||||||
|
poll.DSUpdate({
|
||||||
|
motion_id: poll.motion_id,
|
||||||
|
votes: {"Yes": poll.yes, "No": poll.no, "Abstain": poll.abstain},
|
||||||
|
votesvalid: poll.votesvalid,
|
||||||
|
votesinvalid: poll.votesinvalid,
|
||||||
|
votescast: poll.votescast
|
||||||
|
})
|
||||||
|
.then(function(success) {
|
||||||
|
$scope.alert.show = false;
|
||||||
|
$scope.closeThisDialog();
|
||||||
|
})
|
||||||
|
.catch(function(error) {
|
||||||
|
var message = '';
|
||||||
|
for (var e in error.data) {
|
||||||
|
message += e + ': ' + error.data[e] + ' ';
|
||||||
|
}
|
||||||
|
$scope.alert = { type: 'danger', msg: message, show: true };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
.controller('MotionImportCtrl', [
|
.controller('MotionImportCtrl', [
|
||||||
'$scope',
|
'$scope',
|
||||||
'gettext',
|
'gettext',
|
||||||
@ -759,6 +857,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
.controller('CategoryListCtrl', function($scope, Category) {
|
.controller('CategoryListCtrl', function($scope, Category) {
|
||||||
Category.bindAll({}, $scope, 'categories');
|
Category.bindAll({}, $scope, 'categories');
|
||||||
|
|
||||||
|
@ -51,187 +51,142 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail" uib-collapse="isMeta">
|
<div class="detail" uib-collapse="isMeta">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4">
|
<div class="col-md-4">
|
||||||
<!-- submitters -->
|
<!-- submitters -->
|
||||||
<h3 translate>Submitters</h3>
|
<h3 translate>Submitters</h3>
|
||||||
<div ng-repeat="submitter in motion.submitters">
|
<div ng-repeat="submitter in motion.submitters">
|
||||||
{{ submitter.get_full_name() }}<br>
|
{{ submitter.get_full_name() }}<br>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- supporters -->
|
<!-- supporters -->
|
||||||
<div ng-if="config('motions_min_supporters') > 0">
|
<div ng-if="config('motions_min_supporters') > 0">
|
||||||
<h3 translate>Supporters</h3>
|
<h3 translate>Supporters</h3>
|
||||||
<ol>
|
<ol>
|
||||||
<li ng-repeat="supporters in motion.supporters">
|
<li ng-repeat="supporters in motion.supporters">
|
||||||
{{ supporters.get_full_name() }}
|
{{ supporters.get_full_name() }}
|
||||||
|
</ol>
|
||||||
|
<!-- support button -->
|
||||||
|
<button ng-if="motion.isAllowed('support')" ng-click="support()" class="btn btn-default btn-sm">
|
||||||
|
<i class="fa fa-heart"></i>
|
||||||
|
<translate>Support motion</translate>
|
||||||
|
</button>
|
||||||
|
<!-- unsupport button -->
|
||||||
|
<button ng-if="motion.isAllowed('unsupport')" ng-click="unsupport()" class="btn btn-default btn-sm">
|
||||||
|
<i class="fa fa-heart-o"></i>
|
||||||
|
<translate>Unsupport motion</translate>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<!-- Category -->
|
||||||
|
<h3 ng-if="motion.category" translate>Category</h3>
|
||||||
|
{{ motion.category.name }}
|
||||||
|
|
||||||
|
<!-- Tags -->
|
||||||
|
<h3 ng-if="motion.tags.length > 0" translate>Tags</h3>
|
||||||
|
<span ng-repeat="tag in motion.tags">
|
||||||
|
{{ tag.name }}{{$last ? '' : ', '}}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- State -->
|
||||||
|
<h3 translate>State</h3>
|
||||||
|
<span class="label" ng-class="'label-'+motion.state.css_class">
|
||||||
|
{{ motion.state.name | translate }}
|
||||||
|
</span>
|
||||||
|
<div ng-if="motion.isAllowed('change_state')" class="spacer">
|
||||||
|
<select ng-if="motion.state.getNextStates().length > 0" ng-model="stateSelect" class="form-control" ng-change="updateState(stateSelect)">
|
||||||
|
<option value="" translate>--- Set next state ---</option>
|
||||||
|
<option ng-repeat="state in motion.state.getNextStates()" value="{{ state.id }}">{{ state.action_word }}</option>
|
||||||
|
</select>
|
||||||
|
<button ng-if="motion.isAllowed('reset_state')" ng-click="reset_state()"
|
||||||
|
class="btn btn-danger btn-xs spacer">
|
||||||
|
<i class="fa fa-exclamation-triangle"></i>
|
||||||
|
<translate>Reset state</translate>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<h3 ng-if="motion.polls.length > 0" translate>Voting result</h3>
|
||||||
|
<ol class="slimlist">
|
||||||
|
<li ng-repeat="poll in motion.polls" class="spacer"
|
||||||
|
ng-if="poll.has_votes || operator.hasPerms('motions.can_manage')">
|
||||||
|
<strong><translate translate-context="ballot">Vote</translate></strong>
|
||||||
|
<!-- Edit poll -->
|
||||||
|
<button os-perms="motions.can_manage" ng-click="openPollDialog(poll, $index+1)"
|
||||||
|
class="btn btn-default btn-xs" title="{{ 'Edit' | translate }}">
|
||||||
|
<i class="fa fa-pencil"></i>
|
||||||
|
</button>
|
||||||
|
<!-- Delete poll -->
|
||||||
|
<button os-perms="motions.can_manage" class="btn btn-default btn-xs"
|
||||||
|
ng-bootbox-confirm="{{ 'Are you sure you want to delete this poll?' | translate }}"
|
||||||
|
ng-bootbox-confirm-action="delete_poll(poll)"
|
||||||
|
title="{{ 'Delete' | translate }}">
|
||||||
|
<i class="fa fa-times"></i>
|
||||||
|
</button>
|
||||||
|
<!-- Poll results -->
|
||||||
|
<div ng-show="poll.has_votes" class="pollresults">
|
||||||
|
<table class="table">
|
||||||
|
<!-- yes -->
|
||||||
|
<tr>
|
||||||
|
<td class="icon">
|
||||||
|
<i class="fa fa-thumbs-up fa-2x"></i>
|
||||||
|
<td>
|
||||||
|
<span class="result_label"><translate>Yes</translate>:</span>
|
||||||
|
<span class="result_value">{{ poll.yes }} {{ poll.getYesPercent() }}</span>
|
||||||
|
<div ng-if="poll.getYesPercent(true)">
|
||||||
|
<uib-progressbar value="poll.getYesPercent(true)" type="success"></uib-progressbar>
|
||||||
|
</div>
|
||||||
|
<!-- no -->
|
||||||
|
<tr>
|
||||||
|
<td class="icon">
|
||||||
|
<i class="fa fa-thumbs-down fa-2x"></i>
|
||||||
|
<td>
|
||||||
|
<span class="result_label"><translate>No</translate>:</span>
|
||||||
|
<span class="result_value">{{ poll.no }} {{ poll.getNoPercent() }}</span>
|
||||||
|
<div ng-if="poll.getNoPercent(true)">
|
||||||
|
<uib-progressbar value="poll.getNoPercent(true)" type="danger"></uib-progressbar>
|
||||||
|
</div>
|
||||||
|
<!-- abstain -->
|
||||||
|
<tr>
|
||||||
|
<td class="icon">
|
||||||
|
<strong style="font-size: 26px">∅</strong>
|
||||||
|
<td>
|
||||||
|
<span class="result_label"><translate>Abstain</translate>:</span>
|
||||||
|
<span class="result_value">{{ poll.abstain }} {{ poll.getAbstainPercent() }}</span>
|
||||||
|
<div ng-if="poll.getAbstainPercent(true)">
|
||||||
|
<uib-progressbar value="poll.getAbstainPercent(true)" type="warning"></uib-progressbar>
|
||||||
|
</div>
|
||||||
|
<!-- valid votes -->
|
||||||
|
<tr>
|
||||||
|
<td class="icon">
|
||||||
|
<i class="fa fa-check fa-lg"></i>
|
||||||
|
<td>
|
||||||
|
<span class="result_label"><translate>Valid votes</translate>:</span>
|
||||||
|
<span class="result_value">{{ poll.votesvalid }} {{ poll.getVotesValidPercent() }}</span>
|
||||||
|
<!-- invalid votes -->
|
||||||
|
<tr>
|
||||||
|
<td class="icon">
|
||||||
|
<i class="fa fa-ban fa-lg"></i>
|
||||||
|
<td>
|
||||||
|
<span class="result_label"><translate>Invalid votes</translate>:</span>
|
||||||
|
<span class="result_value">{{ poll.votesinvalid }} {{ poll.getVotesInvalidPercent() }}</span>
|
||||||
|
<!-- votes cast -->
|
||||||
|
<tr class="total">
|
||||||
|
<td class="icon">
|
||||||
|
<strong style="font-size: 16px">∑</strong>
|
||||||
|
<td>
|
||||||
|
<span class="result_label"><translate>Votes cast</translate>:</span>
|
||||||
|
<span class="result_value">{{ poll.votescast }} {{ poll.getVotesCastPercent() }}</span>
|
||||||
|
</table>
|
||||||
</ol>
|
</ol>
|
||||||
<!-- support button -->
|
<button ng-if="motion.isAllowed('create_poll')" ng-click="create_poll()" class="btn btn-default btn-sm">
|
||||||
<button ng-if="motion.isAllowed('support')" ng-click="support()" class="btn btn-default btn-sm">
|
<i class="fa fa-bar-chart fa-lg"></i>
|
||||||
<i class="fa fa-heart"></i>
|
<translate>New vote</translate>
|
||||||
<translate>Support motion</translate>
|
|
||||||
</button>
|
</button>
|
||||||
<!-- unsupport button -->
|
</div>
|
||||||
<button ng-if="motion.isAllowed('unsupport')" ng-click="unsupport()" class="btn btn-default btn-sm">
|
<div class="col-sm-1"></div>
|
||||||
<i class="fa fa-heart-o"></i>
|
|
||||||
<translate>Unsupport motion</translate>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4">
|
|
||||||
<!-- Category -->
|
|
||||||
<h3 ng-if="motion.category" translate>Category</h3>
|
|
||||||
{{ motion.category.name }}
|
|
||||||
|
|
||||||
<!-- Tags -->
|
|
||||||
<h3 ng-if="motion.tags.length > 0" translate>Tags</h3>
|
|
||||||
<span ng-repeat="tag in motion.tags">
|
|
||||||
{{ tag.name }}{{$last ? '' : ', '}}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<!-- State -->
|
|
||||||
<h3 translate>State</h3>
|
|
||||||
<span class="label" ng-class="'label-'+motion.state.css_class">
|
|
||||||
{{ motion.state.name | translate }}
|
|
||||||
</span>
|
|
||||||
<div ng-if="motion.isAllowed('change_state')" class="spacer">
|
|
||||||
<select ng-if="motion.state.getNextStates().length > 0" ng-model="stateSelect" class="form-control" ng-change="updateState(stateSelect)">
|
|
||||||
<option value="" translate>--- Set next state ---</option>
|
|
||||||
<option ng-repeat="state in motion.state.getNextStates()" value="{{ state.id }}">{{ state.action_word }}</option>
|
|
||||||
</select>
|
|
||||||
<button ng-if="motion.isAllowed('reset_state')" ng-click="reset_state()"
|
|
||||||
class="btn btn-danger btn-xs spacer">
|
|
||||||
<i class="fa fa-exclamation-triangle"></i>
|
|
||||||
<translate>Reset state</translate>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-3">
|
|
||||||
<h3 ng-if="motion.polls.length > 0" translate>Voting result</h3>
|
|
||||||
<ol class="slimlist">
|
|
||||||
<li ng-repeat="poll in motion.polls" class="spacer">
|
|
||||||
<translate translate-context="ballot">Vote</translate>
|
|
||||||
<button os-perms="motions.can_manage" ng-click="$parent.poll.isEditMode=true;"
|
|
||||||
class="btn btn-default btn-xs">
|
|
||||||
<i class="fa fa-pencil"></i>
|
|
||||||
</button>
|
|
||||||
<button os-perms="motions.can_manage" ng-click="delete_poll(poll)"
|
|
||||||
class="btn btn-default btn-xs">
|
|
||||||
<i class="fa fa-times"></i>
|
|
||||||
</button>
|
|
||||||
<div ng-show="poll.isEditMode" class="spacer">
|
|
||||||
<form>
|
|
||||||
<p>
|
|
||||||
<translate>Special values</translate>:<br>
|
|
||||||
<span class="badge badge-success">-1</span> = <translate>majority</translate><br>
|
|
||||||
<span class="badge">-2</span> = <translate>undocumented</translate>
|
|
||||||
</p>
|
|
||||||
<alert ng-show="alert.show" type="{{ alert.type }}" ng-click="alert={}" close="alert={}">
|
|
||||||
{{alert.msg}}
|
|
||||||
</alert>
|
|
||||||
<!-- yes -->
|
|
||||||
<div class="input-group col-sm-8 spacer">
|
|
||||||
<div class="input-group-addon" title="{{ 'Yes' | translate }}"><i class="fa fa-thumbs-up"></i></div>
|
|
||||||
<input type="number" ng-model="poll.yes" class="form-control input-sm" placeholder="{{ 'Yes' | translate }}">
|
|
||||||
</div>
|
|
||||||
<!-- no -->
|
|
||||||
<div class="input-group col-sm-8">
|
|
||||||
<div class="input-group-addon" title="{{ 'No' | translate }}"><i class="fa fa-thumbs-down"></i></div>
|
|
||||||
<input type="number" ng-model="poll.no" class="form-control input-sm" placeholder="{{ 'No' | translate }}">
|
|
||||||
</div>
|
|
||||||
<!-- abstain -->
|
|
||||||
<div class="input-group col-sm-8">
|
|
||||||
<div class="input-group-addon" title="{{ 'Abstain' | translate }}"><b>∅</b></div>
|
|
||||||
<input type="number" ng-model="poll.abstain" class="form-control input-sm" placeholder="{{ 'Abstain' | translate }}">
|
|
||||||
</div>
|
|
||||||
<!-- valid votes -->
|
|
||||||
<div class="input-group col-sm-8 spacer">
|
|
||||||
<div class="input-group-addon" title="{{ 'Valid votes' | translate }}"><i class="fa fa-check"></i></div>
|
|
||||||
<input type="number" ng-model="poll.votesvalid" class="form-control input-sm" placeholder="{{ 'Valid votes' | translate }}">
|
|
||||||
</div>
|
|
||||||
<!-- invalid votes -->
|
|
||||||
<div class="input-group col-sm-8">
|
|
||||||
<div class="input-group-addon" title="{{ 'Invalid votes' | translate }}"><i class="fa fa-ban"></i></div>
|
|
||||||
<input type="number" ng-model="poll.votesinvalid" class="form-control input-sm" placeholder="{{ 'Invalid votes' | translate }}">
|
|
||||||
</div>
|
|
||||||
<!-- votes cast -->
|
|
||||||
<div class="input-group col-sm-8 spacer">
|
|
||||||
<div class="input-group-addon" title="{{ 'Votes cast' | translate }}"><b>∑</b></div>
|
|
||||||
<input type="number" ng-model="poll.votescast" class="form-control input-sm" placeholder="{{ 'Votes cast' | translate }}">
|
|
||||||
</div>
|
|
||||||
<!-- buttons -->
|
|
||||||
<div class="spacer">
|
|
||||||
<button type="submit" ng-click="update_poll(poll)" class="btn btn-primary" translate>
|
|
||||||
Save
|
|
||||||
</button>
|
|
||||||
<button ng-click="poll.isEditMode=false;" class="btn btn-default" translate>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div ng-show="!poll.isEditMode" class="pollresults">
|
|
||||||
<table class="table">
|
|
||||||
<!-- yes -->
|
|
||||||
<tr>
|
|
||||||
<td class="icon">
|
|
||||||
<i class="fa fa-thumbs-up fa-2x"></i>
|
|
||||||
<td>
|
|
||||||
<span class="result_label"><translate>Yes</translate>:</span>
|
|
||||||
<span class="result_value">{{ poll.yes }} {{ poll.getYesPercent() }}</span>
|
|
||||||
<div ng-if="poll.getYesPercent(true)">
|
|
||||||
<uib-progressbar value="poll.getYesPercent(true)" type="success"></uib-progressbar>
|
|
||||||
</div>
|
|
||||||
<!-- no -->
|
|
||||||
<tr>
|
|
||||||
<td class="icon">
|
|
||||||
<i class="fa fa-thumbs-down fa-2x"></i>
|
|
||||||
<td>
|
|
||||||
<span class="result_label"><translate>No</translate>:</span>
|
|
||||||
<span class="result_value">{{ poll.no }} {{ poll.getNoPercent() }}</span>
|
|
||||||
<div ng-if="poll.getNoPercent(true)">
|
|
||||||
<uib-progressbar value="poll.getNoPercent(true)" type="danger"></uib-progressbar>
|
|
||||||
</div>
|
|
||||||
<!-- abstain -->
|
|
||||||
<tr>
|
|
||||||
<td class="icon">
|
|
||||||
<strong style="font-size: 26px">∅</strong>
|
|
||||||
<td>
|
|
||||||
<span class="result_label"><translate>Abstain</translate>:</span>
|
|
||||||
<span class="result_value">{{ poll.abstain }} {{ poll.getAbstainPercent() }}</span>
|
|
||||||
<div ng-if="poll.getAbstainPercent(true)">
|
|
||||||
<uib-progressbar value="poll.getAbstainPercent(true)" type="warning"></uib-progressbar>
|
|
||||||
</div>
|
|
||||||
<!-- valid votes -->
|
|
||||||
<tr>
|
|
||||||
<td class="icon">
|
|
||||||
<i class="fa fa-check fa-lg"></i>
|
|
||||||
<td>
|
|
||||||
<span class="result_label"><translate>Valid votes</translate>:</span>
|
|
||||||
<span class="result_value">{{ poll.votesvalid }} {{ poll.getVotesValidPercent() }}</span>
|
|
||||||
<!-- invalid votes -->
|
|
||||||
<tr>
|
|
||||||
<td class="icon">
|
|
||||||
<i class="fa fa-ban fa-lg"></i>
|
|
||||||
<td>
|
|
||||||
<span class="result_label"><translate>Invalid votes</translate>:</span>
|
|
||||||
<span class="result_value">{{ poll.votesinvalid }} {{ poll.getVotesInvalidPercent() }}</span>
|
|
||||||
<!-- votes cast -->
|
|
||||||
<tr class="total">
|
|
||||||
<td class="icon">
|
|
||||||
<strong style="font-size: 16px">∑</strong>
|
|
||||||
<td>
|
|
||||||
<span class="result_label"><translate>Votes cast</translate>:</span>
|
|
||||||
<span class="result_value">{{ poll.votescast }} {{ poll.getVotesCastPercent() }}</span>
|
|
||||||
</table>
|
|
||||||
</ol>
|
|
||||||
<button ng-if="motion.isAllowed('create_poll')" ng-click="create_poll()" class="btn btn-default btn-sm">
|
|
||||||
<i class="fa fa-bar-chart fa-lg"></i>
|
|
||||||
<translate>New vote</translate>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-1"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user