281 lines
13 KiB
HTML
281 lines
13 KiB
HTML
<div class="header">
|
|
<div class="title">
|
|
<div class="submenu">
|
|
<a ui-sref="assignments.assignment.list" class="btn btn-sm btn-default">
|
|
<i class="fa fa-angle-double-left fa-lg"></i>
|
|
<translate>Back to overview</translate>
|
|
</a>
|
|
<!-- List of speakers -->
|
|
<a ui-sref="agenda.item.detail({id: assignment.agenda_item_id})"
|
|
os-perms="agenda.can_see" class="btn btn-sm btn-default">
|
|
<i class="fa fa-microphone fa-lg"></i>
|
|
<translate>List of speakers</translate>
|
|
</a>
|
|
<!-- project -->
|
|
<projector-button model="assignment", default-projector-id="defaultProjectorId">
|
|
</projector-button>
|
|
<!-- edit -->
|
|
<a os-perms="assignments.can_manage" ng-click="openDialog()"
|
|
class="btn btn-default btn-sm"
|
|
title="{{ 'Edit' | translate}}">
|
|
<i class="fa fa-pencil"></i>
|
|
</a>
|
|
<!-- pdf -->
|
|
<a ng-click="pdfExport()" target="_blank" class="btn btn-default btn-sm">
|
|
<i class="fa fa-file-pdf-o fa-lg"></i>
|
|
<translate>PDF</translate>
|
|
</a>
|
|
</div>
|
|
<h1>{{ assignment.agenda_item.getTitle() || assignment.title }}</h1>
|
|
<h2>
|
|
<translate>Election</translate>
|
|
</h2>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="meta">
|
|
<div class="title" ng-click="isMeta = !isMeta">
|
|
<div class="name">
|
|
<i class="fa fa-info-circle"></i>
|
|
<translate>Meta information</translate>
|
|
</div>
|
|
<div class="icon">
|
|
<i class="fa fa-lg" ng-class="isMeta ? 'fa-angle-down' : 'fa-angle-up'"></i>
|
|
</div>
|
|
</div>
|
|
<div class="detail" uib-collapse="isMeta">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<!-- posts -->
|
|
<h3 translate>Number of persons to be elected</h3>
|
|
{{ assignment.open_posts }}<br>
|
|
<!-- Tags -->
|
|
<h3 ng-if="assignment.tags.length > 0" translate>Tags</h3>
|
|
<span ng-repeat="tag in assignment.tags">
|
|
{{ tag.name }}{{$last ? '' : ', '}}
|
|
</span>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<!-- phase -->
|
|
<h3 translate>Phase</h3>
|
|
<span class="label" ng-class="{'label-primary': assignment.phase == 0,
|
|
'label-warning': assignment.phase == 1,
|
|
'label-success': assignment.phase == 2 }">
|
|
{{ phases[assignment.phase].display_name | translate }}
|
|
</span>
|
|
<div os-perms="assignments.can_manage" class="spacer">
|
|
<select ng-model="phaseSelect" class="form-control" ng-change="updatePhase(phaseSelect)">
|
|
<option value="" translate>--- Set phase ---</option>
|
|
<option ng-repeat="phase in phases" value="{{ phase.value }}">{{ phase.display_name | translate }}</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="details">
|
|
<div ng-if="assignment.description">
|
|
<h3 translate>Description</h3>
|
|
<div class="white-space-pre-line">{{ assignment.description }}</div>
|
|
</div>
|
|
|
|
<div ng-if="assignment.phase !== 2">
|
|
<h3 translate>Candidates</h3>
|
|
<div ui-tree="treeOptions" ng-if="assignment.assignment_related_users.length"
|
|
data-empty-placeholder-enabled="false">
|
|
<ol ui-tree-nodes="" ng-model="relatedUsersSorted">
|
|
<li ui-tree-node ng-repeat="related_user in assignment.assignment_related_users | orderBy:'weight'">
|
|
<i ui-tree-handle="" class="fa fa-arrows-v spacer-right" os-perms="assignments.can_manage"></i>
|
|
<a class="spacer-right" ui-sref="users.user.detail({id: related_user.user_id})">
|
|
{{ related_user.user.get_full_name() }}
|
|
</a>
|
|
<i ng-if="related_user.elected" class="fa fa-star" title="{{ 'is elected' | translate }}"></i>
|
|
<a href os-perms="assignments.can_manage" ng-click="removeCandidate(related_user.user_id)" class="btn btn-default btn-xs">
|
|
<i class="fa fa-times"></i>
|
|
</a>
|
|
</ol>
|
|
</div>
|
|
|
|
<div class="form-group spacer-top-lg">
|
|
<div uib-alert ng-show="alert.show" ng-class="'alert-' + (alert.type || 'warning')" ng-click="alert={}" close="alert={}">
|
|
{{ alert.msg }}
|
|
</div>
|
|
<div os-perms="assignments.can_nominate_other">
|
|
<select chosen ng-model="candidateSelectBox.selected" ng-change="addCandidate(candidateSelectBox.selected)"
|
|
ng-options="user.id as user.get_full_name() for user in users"
|
|
search-contains="true"
|
|
placeholder-text-single="'Select or search a participant ...' | translate"
|
|
no-results-text="'No results available ...' | translate"
|
|
class="form-control">
|
|
<select>
|
|
</div>
|
|
<p os-perms="assignments.can_nominate_self" class="spacer">
|
|
<button ng-if="!isCandidate()" ng-click="addMe()" class="btn btn-default btn-sm">
|
|
<i class="fa fa-plus"></i>
|
|
<translate>Add me</translate>
|
|
</button>
|
|
<button ng-if="isCandidate()" ng-click="removeMe()" class="btn btn-default btn-sm">
|
|
<i class="fa fa-minus"></i>
|
|
<translate>Remove me</translate>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<h3 translate>Election result</h3>
|
|
<button os-perms="assignments.can_manage" ng-show="assignment.phase !== 2" ng-click="createBallot()"
|
|
class="btn btn-default btn-sm">
|
|
<i class="fa fa-bar-chart fa-lg"></i>
|
|
<translate>New ballot</translate>
|
|
</button>
|
|
<uib-tabset ng-if="assignment.polls.length > 0" class="spacer ballot-tabs" active="$parent.activeTab">
|
|
<uib-tab ng-repeat="poll in assignment.polls | orderBy:'id'"
|
|
index="$index" heading="{{ 'Ballot' | translate }} {{ $index + 1 }}">
|
|
<div ng-controller="AssignmentPollDetailCtrl">
|
|
<!-- action buttons -->
|
|
<div class="pull-right" os-perms="assignments.can_manage" ng-show="assignment.phase !== 2">
|
|
<span class="spacer-right" editable-text="poll.description" onaftersave="saveDescriptionChange(poll)"
|
|
uib-tooltip="{{ 'Hint on the ballot paper.' | translate }}">
|
|
<span ng-if="!poll.description" translate>Set hint for ballot paper ...</span>
|
|
<span ng-if="poll.description">{{ poll.description }}</span>
|
|
<i class="fa fa-pencil"></i>
|
|
</span>
|
|
<!-- delete -->
|
|
<a class="btn btn-danger btn-xs"
|
|
ng-bootbox-confirm="{{ 'Are you sure you want to delete this ballot?' | translate }}"
|
|
ng-bootbox-confirm-action="deleteBallot(poll)">
|
|
<i class="fa fa-trash"></i>
|
|
<translate>Delete</translate>
|
|
</a>
|
|
</div>
|
|
<div os-perms="assignments.can_manage" class="spacer" role="group">
|
|
<!-- angular requires to open the link in new tab with "target='_blank'".
|
|
Otherwise the pdf url can't be open in same window; angular redirects to "/". -->
|
|
<!-- PDF -->
|
|
<a ng-click="ballotpaperExport(poll.id)" target="_blank" class="btn btn-default btn-sm">
|
|
<i class="fa fa-file-pdf-o"></i>
|
|
<translate>Print ballot paper</translate>
|
|
</a>
|
|
<!-- Edit -->
|
|
<button ng-click="assignment.phase !== 2 && editPollDialog(poll, $index+1)"
|
|
ng-class="{ 'disabled': assignment.phase === 2 }"
|
|
class="btn btn-default btn-sm">
|
|
<i class="fa fa-pencil"></i>
|
|
<translate>Enter votes</translate>
|
|
</button>
|
|
<!-- Publish -->
|
|
<button ng-click="togglePublishBallot(poll)"
|
|
ng-class="poll.published ? 'btn-primary' : 'btn-default'"
|
|
class="btn btn-sm">
|
|
<i class="fa fa-eye"></i>
|
|
<translate>Publish</translate>
|
|
</button>
|
|
<!-- Project -->
|
|
<projector-button model="assignment" default-projector-id="defaultProjectorId"
|
|
arg="poll.id" content="{{ 'Project' | translate }}">
|
|
</projector-button>
|
|
</div>
|
|
|
|
<!-- template hook for assignment poll small buttons -->
|
|
<template-hook hook-name="assignmentPollSmallButtons"></template-hook>
|
|
|
|
<div class="results spacer-top-lg">
|
|
|
|
<!-- list of candidates of selected poll (without election result) -->
|
|
<div ng-if="!poll.has_votes">
|
|
<strong translate>Candidates</strong>
|
|
<ul class="list-unstyled">
|
|
<li ng-repeat="option in poll.options | orderBy:'weight'">
|
|
<a ui-sref="users.user.detail({id: option.candidate.id})">
|
|
{{ option.candidate.get_full_name() }}
|
|
</a>
|
|
</ul>
|
|
<strong translate>Election method</strong><br>
|
|
<span ng-if="poll.pollmethod == 'votes'" translate>One vote per candidate</span>
|
|
<span ng-if="poll.pollmethod == 'yna'" translate>Yes/No/Abstain per candidate</span>
|
|
<span ng-if="poll.pollmethod == 'yn'" translate>Yes/No per candidate</span>
|
|
</div>
|
|
|
|
<!-- Settings for majority calculations -->
|
|
<div os-perms="assignments.can_manage" ng-show="poll.has_votes" ng-cloak>
|
|
<div class="input-group">
|
|
<span><translate>Required majority</translate>: </span>
|
|
<select ng-model="method"
|
|
ng-change="recalculateMajorities(method)"
|
|
ng-options="option.value as option.display_name | translate for option in methodChoices" />
|
|
</div>
|
|
</div>
|
|
<!-- election result of poll -->
|
|
<table ng-if="poll.has_votes" class="table table-bordered table-striped minimumTable spacer">
|
|
<tr>
|
|
<th translate>Candidates
|
|
<th translate>Votes
|
|
<th translate ng-hide="method === 'disabled'">Quorum
|
|
</th>
|
|
<!-- candidates (poll options) -->
|
|
<tr ng-repeat="option in poll.options | orderBy:'weight'">
|
|
<!-- candidate name -->
|
|
<td>
|
|
<span os-perms="assignments.can_manage">
|
|
<i ng-if="option.is_elected" class="fa fa-check-square-o"
|
|
ng-click="markElected(option.candidate_id, option.is_elected)"
|
|
title="{{ 'is elected' | translate }}"></i>
|
|
<i ng-if="!option.is_elected" class="fa fa-square-o"
|
|
ng-click="markElected(option.candidate_id, option.is_elected)"
|
|
title="{{ 'is not elected' | translate }}"></i>
|
|
|
|
</span>
|
|
<a ui-sref="users.user.detail({id: option.candidate.id})">{{ option.candidate.get_full_name() }}</a>
|
|
|
|
<!-- votes -->
|
|
<td>
|
|
<div ng-init="votes = option.getVotes()">
|
|
<div ng-repeat="vote in votes">
|
|
<span ng-if="poll.pollmethod == 'yna' || poll.pollmethod == 'yn'">{{ vote.label }}:</span>
|
|
{{ vote.value }} {{ vote.percentStr }}
|
|
<div ng-if="vote.percentNumber >= 0">
|
|
<uib-progressbar ng-if="$index == 0" value="vote.percentNumber" type="success"></uib-progressbar>
|
|
<uib-progressbar ng-if="$index == 1" value="vote.percentNumber" type="danger"></uib-progressbar>
|
|
<uib-progressbar ng-if="$index == 2" value="vote.percentNumber" type="warning"></uib-progressbar>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<td ng-hide="method === 'disabled'">
|
|
<span ng-if="option.majorityReached >= 0" class="text-success" translate>
|
|
Quorum ({{ option.getVoteYes() - option.majorityReached }}) reached.
|
|
</span>
|
|
<span ng-if="option.majorityReached < 0" class="text-danger" translate>
|
|
Quorum ({{ option.getVoteYes() - option.majorityReached }}) not reached.
|
|
</span>
|
|
|
|
<!-- total votes (valid/invalid/casts) -->
|
|
<tr>
|
|
<td>
|
|
<translate>Valid ballots</translate>
|
|
<td>
|
|
{{ poll.getVote('votesvalid').value }}
|
|
{{ poll.getVote('votesvalid').percentStr }}
|
|
<tr>
|
|
<td>
|
|
<translate>Invalid ballots</translate>
|
|
<td>
|
|
{{ poll.getVote('votesinvalid').value }}
|
|
{{ poll.getVote('votesinvalid').percentStr }}
|
|
<tr class="total bg-info">
|
|
<td>
|
|
<translate>Casted ballots</translate>
|
|
<td>
|
|
{{ poll.getVote('votescast').value }}
|
|
{{ poll.getVote('votescast').percentStr }}
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</uib-tab>
|
|
</uib-tabset>
|
|
|
|
<!-- Workaround to prevent page scrolling up after autoupdate. -->
|
|
<div style="height: 700px"><div>
|
|
</div>
|
|
|
|
<template-hook hook-name="assignmentDetailViewDetailContainer"></template-hook>
|