UI improvements

- item list: reorder buttons
- motion list:
  * move hover menu for edit/delete below submitters
  * limit submitters to one
- motion detail:
  * show ol flush left
  * use 2 or 3 columns in meta box
  * use small buttons for line numbering controls
  * group line number controls in grey tool bar.
  * Show motion comments div only if user is allowed.
- motion config:
  * Deativate comments by default.
  * Deactivate recommendations for motions by default.
- item detail: Show needed buttons only.
- assignment detail: Improve ballot tabs.
- general:
  * move pdf button to right
  * move 'back to overview' button to left
  * update label vor countdown option
This commit is contained in:
Emanuel Schuetze 2016-09-30 17:19:27 +02:00
parent 2a5bd6d94b
commit bc72089973
17 changed files with 339 additions and 224 deletions

View File

@ -337,9 +337,21 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda'])
$scope.defaultProjectorListOfSpeakersId = projectiondefaultListOfSpeakers.projector_id;
}
});
$scope.$watch(function () {
return Agenda.lastModified();
}, function () {
// all speakers
$scope.speakers = $filter('orderBy')(item.speakers, 'weight');
// next speakers
$scope.nextSpeakers = $filter('filter')($scope.speakers, {'begin_time': null});
// current speaker
$scope.currentSpeaker = $filter('filter')($scope.speakers, {'begin_time': '!!', 'end_time': null});
// last speakers
$scope.lastSpeakers = $filter('filter')($scope.speakers, {'end_time': '!!'});
});
$scope.speakerSelectBox = {};
$scope.alert = {};
$scope.speakers = $filter('orderBy')(item.speakers, 'weight');
$scope.$watch(function () {
return Agenda.lastModified();
@ -403,20 +415,31 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda'])
$scope.speakers = item.speakers;
};
// check if user is allowed to see 'add me' / 'remove me' button
// Return true if the requested user is allowed to do a specific action
// and see the corresponding button (e.g. 'add me' or 'remove me').
$scope.isAllowed = function (action) {
var nextUsers = [];
var nextSpeakers = $filter('filter')($scope.speakers, {'begin_time': null});
angular.forEach(nextSpeakers, function (speaker) {
angular.forEach($scope.nextSpeakers, function (speaker) {
nextUsers.push(speaker.user_id);
});
if (action == 'add') {
switch (action) {
case 'add':
return (operator.hasPerms('agenda.can_be_speaker') &&
!item.speaker_list_closed &&
$.inArray(operator.user.id, nextUsers) == -1);
}
if (action == 'remove') {
case 'remove':
return ($.inArray(operator.user.id, nextUsers) != -1);
case 'removeAll':
return (operator.hasPerms('agenda.can_manage') &&
$scope.speakers.length > 0);
case 'beginNextSpeech':
return (operator.hasPerms('agenda.can_manage') &&
$scope.nextSpeakers.length > 0);
case 'endCurrentSpeech':
return (operator.hasPerms('agenda.can_manage') &&
$scope.currentSpeaker.length > 0);
case 'showLastSpeakers':
return $scope.lastSpeakers.length > 0;
}
};

View File

@ -1,7 +1,19 @@
<div class="header">
<div class="title">
<div class="submenu">
<div class="form-inline">
<a ui-sref="agenda.item.list" class="btn btn-sm btn-default">
<i class="fa fa-angle-double-left fa-lg"></i>
<translate>Back to overview</translate>
</a>
<!-- manage list of speakers -->
<button os-perms="agenda.can_manage"
ng-click="goToListOfSpeakers()"
class="btn btn-sm btn-default">
<i class="fa fa-microphone"></i>
<translate>Manage list</translate>
</button>
<!-- project -->
<div class="form-inline button">
<div os-perms="core.can_manage_projector" class="btn-group" uib-dropdown
uib-tooltip="{{ 'Projector' | translate }} {{ isCurrentLoSProjected() }}"
tooltip-enable="isCurrentLoSProjected() > 0">
@ -27,12 +39,6 @@
</li>
</ul>
</div>
<button os-perms="agenda.can_manage"
ng-click="goToListOfSpeakers()"
class="btn btn-sm btn-default">
<i class="fa fa-microphone"></i>
<translate>Manage list</translate>
</button>
</div>
</div>
<h1 translate>Current list of speakers</h1>

View File

@ -51,10 +51,11 @@
</div>
</div>
<div ng-if="item" class="details listOfSpeakers">
<div ng-if="item" class="details">
<div class="speakers-toolbar">
<div class="pull-right">
<span os-perms="agenda.can_manage">
<button class="btn btn-danger"
<button ng-if="isAllowed('removeAll')" class="btn btn-sm btn-danger"
ng-bootbox-confirm="{{ 'Are you sure you want to remove all speakers from this list?'| translate }}"
ng-bootbox-confirm-action="removeAllSpeakers()">
<i class="fa fa-trash fa-lg"></i>
@ -74,32 +75,35 @@
</div>
<!-- Start/Stop controls -->
<div os-perms="agenda.can_manage">
<button ng-click="beginSpeech()"
class="btn btn-sm btn-primary">
<i class="fa fa-microphone"></i>
<translate>Begin next speech</translate>
</button>
<button ng-click="endSpeech()"
<button ng-if="isAllowed('endCurrentSpeech')" ng-click="endSpeech()"
class="btn btn-sm btn-default">
<i class="fa fa-microphone-slash"></i>
<i class="fa fa-stop"></i>
<translate>End current speech</translate>
</button>
<button ng-if="isAllowed('beginNextSpeech')" ng-click="beginSpeech()"
class="btn btn-sm btn-default">
<i class="fa fa-play"></i>
<translate>Begin next speech</translate>
</button>
</div>
<!-- text for empty list -->
<p ng-if="speakers.length == 0" translate>
The list of speakers is empty.
</p>
<template-hook hook-name="itemDetailListOfSpeakersButtons"></template-hook>
<!-- Last speakers -->
<div class="spacer">
<h3 translate>Last speakers</h3>
<button ng-click="showOldSpeakers = !showOldSpeakers"
class="btn btn-sm btn-default">
<translate ng-if="!showOldSpeakers">Show</translate>
<translate ng-if="showOldSpeakers">Hide</translate>
<div class="spacer-top-lg">
<button ng-if="isAllowed('showLastSpeakers')" ng-click="$parent.showOldSpeakers = !$parent.showOldSpeakers"
class="btn btn-xs btn-default">
<translate ng-if="!$parent.showOldSpeakers">Last speakers</translate>
<translate ng-if="$parent.showOldSpeakers">Hide</translate>
</button>
<div uib-collapse="!showOldSpeakers">
<ol class="indentation-lg">
<li ng-repeat="speaker in item.speakers | filter: {end_time: '!!'}">
<ol class="indentation">
<li ng-repeat="speaker in lastSpeakers">
{{ speaker.user.get_full_name() }}
<small class="grey">
{{ getDuration(speaker) | osSecondsToTime }} <translate>minutes</translate>
@ -115,9 +119,8 @@
</div>
<!-- Current speaker -->
<h3 translate class="">Current speaker</h3>
<strong class="indentation" ng-repeat="speaker in item.speakers |
filter: {end_time: null, begin_time: '!!'}">
<p ng-repeat="speaker in currentSpeaker" class="currentSpeaker spacer indentation">
<i class="fa fa-microphone fa-lg"></i>
{{ speaker.user.get_full_name() }}
<button os-perms="agenda.can_manage" ng-click="endSpeech()"
class="btn btn-default btn-sm" title="{{ 'End speech' | translate }}">
@ -127,17 +130,17 @@
class="btn btn-default btn-sm" title="{{ 'Remove' | translate }}">
<i class="fa fa-times"></i>
</button>
</strong>
</p>
<!-- Next speakers -->
<h3 translate>Next speakers</h3>
<div ng-show="speakers.length > 0">
<div ng-show="nextSpeakers.length > 0">
<div ui-tree="treeOptions">
<ol ui-tree-nodes="" ng-model="speakers">
<li ng-repeat="speaker in speakers | filter: {begin_time: null}" ui-tree-node>
<li ng-repeat="speaker in nextSpeakers | orderBy:'weight'" ui-tree-node>
<i os-perms="agenda.can_manage" ui-tree-handle="" class="fa fa-arrows-v"></i>
{{ $index + 1 }}.
{{ speaker.user.get_full_name() }}
&nbsp;
<button os-perms="agenda.can_manage" ng-click="beginSpeech(speaker.id)"
class="btn btn-default btn-sm" title="{{ 'Begin speech' | translate }}">
<i class="fa fa-microphone"></i> <translate>Start</translate>
@ -151,7 +154,7 @@
</div>
<!-- Select speakers form -->
<div class="form-group spacer">
<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>

View File

@ -1,55 +1,37 @@
<div class="header">
<div class="title">
<div class="submenu">
<a ng-click="newDialog()" os-perms="agenda.can_manage" class="btn btn-primary btn-sm">
<!-- new -->
<a ng-click="newDialog()" os-perms="agenda.can_manage"
class="btn btn-primary btn-sm">
<i class="fa fa-plus fa-lg"></i>
<translate>New</translate>
</a>
<a ui-sref="agenda.item.sort" os-perms="agenda.can_manage" class="btn btn-default btn-sm">
<i class="fa fa-sitemap fa-lg"></i>
<translate>Sort agenda</translate>
</a>
<a ui-sref="topics.topic.import" os-perms="agenda.can_manage" class="btn btn-default btn-sm">
<!-- import -->
<a ui-sref="topics.topic.import" os-perms="agenda.can_manage"
class="btn btn-default btn-sm">
<i class="fa fa-download fa-lg"></i>
<translate>Import</translate>
</a>
<a ui-sref="core.tag.list" os-perms="core.can_manage_tags" class="btn btn-default btn-sm">
<i class="fa fa-tags fa-lg"></i>
<translate>Tags</translate>
<!-- current list of speakers -->
<a ui-sref="agenda.current-list-of-speakers" os-perms="users.can_see_name"
class="btn btn-default btn-sm">
<i class="fa fa-microphone"></i>
<translate>Current list of speakers</translate>
</a>
<a ui-sref="agenda_pdf" target="_blank" class="btn btn-default btn-sm">
<i class="fa fa-file-pdf-o fa-lg"></i>
<translate>PDF</translate>
</a>
</div>
<h1 translate>Agenda</h1>
</div>
</div>
<div class="details">
<div class="row">
<div class="col-sm-7">
<div class="form-inline">
<!-- delete mode -->
<button os-perms="agenda.can_manage" class="btn"
ng-class="$parent.isDeleteMode ? 'btn-primary' : 'btn-default'"
ng-click="$parent.isDeleteMode = !$parent.isDeleteMode; uncheckAll()">
<i class="fa fa-check-square-o"></i>
<translate>Select ...</translate>
</button>
<!-- project agenda button -->
<div class="btn-group" uib-dropdown
<div class="btn-group button" uib-dropdown
uib-tooltip="{{ 'Projector' | translate }} {{ isAgendaProjected(mainListTree) }}"
tooltip-enable="isAgendaProjected(mainListTree) > 0"
os-perms="core.can_manage_projector">
<button type="button" class="btn btn-default"
<button type="button" class="btn btn-default btn-sm"
title="{{ 'Project agenda' | translate }}"
ng-click="projectAgenda(defaultProjectorId_all_items, mainListTree)"
ng-class="{ 'btn-primary': isAgendaProjected(mainListTree) > 0 && isAgendaProjected(mainListTree) == defaultProjectorId_all_items}">
<i class="fa fa-video-camera"></i>
<translate>Agenda</translate>
</button>
<button type="button" class="btn btn-default" uib-dropdown-toggle
<button type="button" class="btn btn-default btn-sm" uib-dropdown-toggle
ng-class="{ 'btn-primary': isAgendaProjected(mainListTree) > 0 && isAgendaProjected(mainListTree) != defaultProjectorId_all_items}">
<span class="caret"></span>
</button>
@ -71,18 +53,39 @@
</li>
</ul>
</div>
</div>
<h1 translate>Agenda</h1>
</div>
</div>
<div class="details">
<div class="row">
<div class="col-sm-7">
<div class="form-inline">
<!-- delete mode -->
<button os-perms="agenda.can_manage" class="btn btn-sm"
ng-class="$parent.isDeleteMode ? 'btn-primary' : 'btn-default'"
ng-click="$parent.isDeleteMode = !$parent.isDeleteMode; uncheckAll()">
<i class="fa fa-check-square-o"></i>
<translate>Select ...</translate>
</button>
<!-- sort button -->
<a ui-sref="agenda.item.sort" os-perms="agenda.can_manage" class="btn btn-default btn-sm">
<i class="fa fa-sitemap fa-lg"></i>
<translate>Sort ...</translate>
</a>
<!-- auto numbering button -->
<a os-perms="core.can_manage_projector"
class="btn btn-default"
class="btn btn-default btn-sm"
ng-click="autoNumbering()">
<i class="fa fa-sort-numeric-asc"></i>
<translate>Numbering</translate>
</a>
<!--current list of speakers button-->
<a os-perms="users.can_see_name" class="btn btn-default"
ui-sref="agenda.current-list-of-speakers">
<i class="fa fa-microphone"></i>
<translate>Current list of speakers</translate>
<!-- pdf -->
<a ui-sref="agenda_pdf" target="_blank" class="btn btn-default btn-sm">
<i class="fa fa-file-pdf-o fa-lg"></i>
<translate>PDF</translate>
</a>
</div>
</div>

View File

@ -367,6 +367,8 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
$scope.candidateSelectBox = {};
$scope.phases = phases;
$scope.alert = {};
$scope.activeTab = 0;
// open edit dialog
$scope.openDialog = function (assignment) {
ngDialog.open(AssignmentForm.getDialog(assignment));
@ -431,6 +433,7 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
};
// create new ballot
$scope.createBallot = function () {
$scope.activeTab = 0;
$http.post('/rest/assignments/assignment/' + assignment.id + '/create_poll/')
.success(function(data){
$scope.alert.show = false;
@ -465,10 +468,10 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
});
};
// publish ballot
$scope.publishBallot = function (poll, isPublished) {
$scope.togglePublishBallot = function (poll) {
poll.DSUpdate({
assignment_id: assignment.id,
published: isPublished,
published: !poll.published,
})
.then(function(success) {
$scope.alert.show = false;

View File

@ -3,11 +3,7 @@
<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>All elections</translate>
</a>
<a ui-sref="assignments_single_pdf({pk: assignment.id})" target="_blank" class="btn btn-default btn-sm">
<i class="fa fa-file-pdf-o fa-lg"></i>
<translate>PDF</translate>
<translate>Back to overview</translate>
</a>
<!-- List of speakers -->
<a ui-sref="agenda.item.detail({id: assignment.agenda_item_id})"
@ -24,6 +20,11 @@
title="{{ 'Edit' | translate}}">
<i class="fa fa-pencil"></i>
</a>
<!-- pdf -->
<a ui-sref="assignments_single_pdf({pk: assignment.id})" 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>
@ -117,76 +118,98 @@
</div>
<h3 translate>Election result</h3>
<button os-perms="assignments.can_manage" ng-click="createBallot()" class="btn btn-default btn-sm">
<button os-perms="assignments.can_manage" ng-show="assignment.polls.length == 0"
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 class="spacer">
<uib-tabset ng-if="assignment.polls.length > 0" class="spacer ballot-tabs" active="activeTab">
<uib-tab ng-repeat="poll in assignment.polls | orderBy:'-id'"
index="$index"
heading="{{ 'Ballot' | translate }} {{ assignment.polls.length - $index }}">
<div os-perms="assignments.can_manage" class="spacer">
<!-- action buttons -->
<div class="pull-right">
<!-- 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 ui-sref="assignmentpoll_pdf({poll_pk: poll.id})" target="_blank"
class="btn btn-default btn-sm">
<i class="fa fa-file-pdf-o"></i>
1. <translate>Print ballot paper</translate>
<translate>Print ballot paper</translate>
</a>
<i class="fa fa-arrow-right"></i>
<!-- Edit -->
<button ng-click="editPollDialog(poll, $index+1)"
class="btn btn-default btn-sm">
<i class="fa fa-pencil"></i>
2. <translate>Enter votes</translate>
<translate>Enter votes</translate>
</button>
<i class="fa fa-arrow-right"></i>
<button ng-if="!poll.published" ng-click="publishBallot(poll, true)"
class="btn btn-default btn-sm">
<i class="fa fa-toggle-off"></i>
3. <translate>Publish</translate>
<!-- 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>
<button ng-if="poll.published" ng-click="publishBallot(poll, false)"
class="btn btn-default btn-sm">
<i class="fa fa-toggle-on"></i>
3. <translate>Published</translate>
</button>
<i class="fa fa-arrow-right"></i>
<!-- Project -->
<projector-button model="assignment" default-projector-id="defaultProjectorId"
additional-id="poll.id" content="4. {{ 'Project' | translate }}">
additional-id="poll.id" content="{{ 'Project' | translate }}">
</projector-button>
<a class="btn btn-danger btn-sm"
ng-bootbox-confirm="{{ 'Are you sure you want to delete this ballot?' | translate }}"
ng-bootbox-confirm-action="deleteBallot(poll)">
<i class="fa fa-times"></i>
<translate>Delete</translate>
</a>
</div>
<!-- template hook for assignment poll small buttons -->
<template-hook hook-name="assignmentPollSmallButtons"></template-hook>
<div class="results spacer">
<table class="table table-bordered table-striped minimumTable">
<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">
<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>
<!-- election result of poll -->
<table ng-if="poll.has_votes" class="table table-bordered table-striped minimumTable">
<tr>
<th translate>Elected
<th translate>Candidates
<th ng-if="poll.has_votes" class="col-sm-6" translate>Votes</th>
<th translate>Votes</th>
<!-- candidates (poll options) -->
<tr ng-repeat="option in poll.options">
<!-- elected -->
<td class="minimum">
<button os-perms="assignments.can_manage"
ng-click="markElected(option.candidate_id, option.is_elected)" class="btn btn-default btn-xs">
<i ng-if="option.is_elected" class="fa fa-star" title="{{ 'is elected' | translate }}"></i>
<i ng-if="!option.is_elected" class="fa fa-star-o" title="{{ 'is not elected' | translate }}"></i>
</button>
<!-- 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>
&nbsp;
</span>
<a ui-sref="users.user.detail({id: option.candidate.id})">{{ option.candidate.get_full_name() }}</a>
<!-- votes -->
<td ng-if="poll.has_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>
@ -199,25 +222,30 @@
<!-- total votes (valid/invalid/casts) -->
<tr>
<td>
<td>
<translate>Valid ballots</translate>
<td ng-if="poll.has_votes" ng-init="vote = poll.getVote('votesvalid')">
<td ng-init="vote = poll.getVote('votesvalid')">
{{ vote.value }} {{ vote.percentStr }}
<tr>
<td>
<td>
<translate>Invalid ballots</translate>
<td ng-if="poll.has_votes" ng-init="vote = poll.getVote('votesinvalid')">
<td ng-init="vote = poll.getVote('votesinvalid')">
{{ vote.value }} {{ vote.percentStr }}
<tr class="total bg-info">
<td>
<td>
<translate>Casted ballots</translate>
<td ng-if="poll.has_votes" ng-init="vote = poll.getVote('votescast')">
<td ng-init="vote = poll.getVote('votescast')">
{{ vote.value }} {{ vote.percentStr }}
</table>
</div>
</uib-tab>
<!-- new ballot tab -->
<uib-tab select="createBallot()" index="assignment.polls.length">
<uib-tab-heading>
<i class="fa fa-plus"></i>
<translate>New ballot</translate>
</uib-tab-heading>
</uib-tab>
</uib-tabset>
</div>

View File

@ -153,7 +153,7 @@ def get_config_variables():
name='projector_default_countdown',
default_value=60,
input_type='integer',
label='Default countdown',
label='Predefined seconds of new countdowns',
weight=185,
group='Projector')

View File

@ -275,7 +275,10 @@ img {
float: left;
margin-left: 5px;
}
.col1 .header .submenu > div.button {
float: none;
margin-left: 0;
}
.col1 .meta .title {
width: 100%;
cursor: pointer;
@ -333,9 +336,23 @@ img {
max-width: 100%;
height: auto;
}
.col1 ul, .col1 ol {
margin-left: 20px;
.col1 ol {
margin-left: 15px;
}
.ballot-tabs ul {
margin-left: 0px;
}
.ballot-tabs li.active a {
background-color: #f5f5f5 !important;
}
.ballot-tabs .tab-content {
background-color: #f5f5f5;
border: 1px solid #ddd;
border-width: 0px 1px 1px 1px;
padding: 15px;
}
/* Toolbar to save motion in inline editing mode */
.motion-save-toolbar {
@ -689,14 +706,26 @@ img {
}
#motion-table .data-row > div {
padding: 12px 0;
padding: 10px 0;
}
#motion-table .header-row {
border-top: 1px solid #ddd;
background-color: #f5f5f5;
}
.linenumber-toolbar, .speakers-toolbar {
background-color: #f5f5f5;
border-bottom: 1px solid #ddd;
padding: 12px 0 10px 0;
height: 54px;
margin: -20px -5px 50px -5px;
}
.speakers-toolbar {
margin: -20px -20px 30px -20px;
padding: 12px 15px 10px 15px;
}
.header-row > div {
padding: 10px;
}
@ -733,7 +762,7 @@ img {
}
#motion-table .content > div > div {
margin-bottom: 5px;
margin-bottom: 3px;
}
#motion-table .content > div > div:last-child {
@ -948,16 +977,12 @@ img {
white-space: pre-line;
}
.slimlist {
padding-left: 20px;
}
.slimlabel.label {
padding: 0px 10px;
}
.indentation, .indentation20 {
margin-left: 20px;
margin-left: 20px !important;
}
.indentation-lg {
@ -972,10 +997,6 @@ img {
background-color: #f0ad4e;
}
.listOfSpeakers h3 {
padding-bottom: 0;
}
.smallhr {
margin-top: 5px;
margin-bottom: 5px;
@ -1062,12 +1083,13 @@ img {
.lastSpeakers {
color: #9a9898;
}
.lastSpeakers .indentation {
margin-left: 27px;
}
.currentSpeaker {
font-weight: bold;
margin-left: 0px;
}
.currentSpeaker i {
@ -1275,6 +1297,10 @@ tr.selected td {
h3 { font-size: 18px; padding-bottom: 10px; }
.col-md-4 {
float: left;
width: 50%;
}
}

View File

@ -1884,7 +1884,7 @@ angular.module('OpenSlidesApp.core.site', [
gettext('Background color of projector header and footer');
gettext('Font color of projector header and footer');
gettext('Font color of projector headline');
gettext('Default countdown');
gettext('Predefined seconds of new countdowns');
}
]);

View File

@ -1,14 +1,14 @@
<div class="header">
<div class="title">
<div class="submenu">
<a href="javascript:history.back()" class="btn btn-sm btn-default">
<i class="fa fa-angle-double-left fa-lg"></i>
<translate>Back to overview</translate>
</a>
<a ui-sref="core.tag.create" os-perms="core.can_manage_tags" class="btn btn-primary btn-sm">
<i class="fa fa-plus fa-lg"></i>
<translate>New</translate>
</a>
<a href="javascript:history.back()" class="btn btn-sm btn-default">
<i class="fa fa-angle-double-left fa-lg"></i>
<translate>Back</translate>
</a>
</div>
<h1 translate>Tags</h1>
</div>

View File

@ -100,7 +100,7 @@ def get_config_variables():
yield ConfigVariable(
name='motions_recommendations_by',
default_value='Recommendation committee',
default_value='',
label='Name of recommendation committee',
help_text='Use an empty value to disable the recommendation system.',
weight=332,
@ -161,7 +161,7 @@ def get_config_variables():
yield ConfigVariable(
name='motions_comments',
default_value=[{'name': 'Comment', 'public': True}],
default_value=[],
input_type='comments',
label='Comment fields for motions',
weight=353,

View File

@ -1185,6 +1185,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
.controller('MotionDetailCtrl', [
'$scope',
'$http',
'operator',
'ngDialog',
'MotionForm',
'Motion',
@ -1204,7 +1205,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
'Projector',
'HTMLValidizer',
'ProjectionDefault',
function($scope, $http, ngDialog, MotionForm, Motion, Category, Mediafile, Tag, User, Workflow, Config,
function($scope, $http, operator, ngDialog, MotionForm, Motion, Category, Mediafile, Tag, User, Workflow, Config,
motion, MotionContentProvider, PollContentProvider, PdfMakeConverter, PdfMakeDocumentProvider,
MotionInlineEditing, gettextCatalog, Projector, HTMLValidizer, ProjectionDefault) {
Motion.bindOne(motion.id, $scope, 'motion');
@ -1374,6 +1375,19 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions', 'OpenSlid
$scope.showVersion(motion.active_version);
});
};
// check if user is allowed to see at least one comment field
$scope.isAllowedToSeeCommentField = function () {
var isAllowed = false;
if ($scope.commentsFields.length > 0) {
isAllowed = operator.hasPerms('motions.can_see_and_manage_comments') || _.find(
$scope.commentsFields,
function(field) {
return field.public;
}
);
}
return Boolean(isAllowed);
};
// Inline editing functions
$scope.inlineEditing = MotionInlineEditing;

View File

@ -1,14 +1,14 @@
<div class="header">
<div class="title">
<div class="submenu">
<a ui-sref="motions.category.create" os-perms="motions.can_manage" class="btn btn-primary btn-sm">
<i class="fa fa-plus fa-lg"></i>
<translate>New</translate>
</a>
<a ui-sref="motions.motion.list" class="btn btn-sm btn-default">
<i class="fa fa-angle-double-left fa-lg"></i>
<translate>Back to overview</translate>
</a>
<a ui-sref="motions.category.create" os-perms="motions.can_manage" class="btn btn-primary btn-sm">
<i class="fa fa-plus fa-lg"></i>
<translate>New</translate>
</a>
</div>
<h1 translate>Categories</h1>
</div>

View File

@ -3,11 +3,7 @@
<div class="submenu">
<a ui-sref="motions.motion.list" class="btn btn-sm btn-default">
<i class="fa fa-angle-double-left fa-lg"></i>
<translate>All motions</translate>
</a>
<a ng-click="makePDF()" class="btn btn-default btn-sm">
<i class="fa fa-file-pdf-o fa-lg"></i>
<translate>PDF</translate>
<translate>Back to overview</translate>
</a>
<!-- List of speakers -->
<a ui-sref="agenda.item.detail({id: motion.agenda_item_id})"
@ -24,6 +20,11 @@
title="{{ 'Edit' | translate}}">
<i class="fa fa-pencil"></i>
</a>
<!-- pdf -->
<a ng-click="makePDF()" class="btn btn-default btn-sm">
<i class="fa fa-file-pdf-o fa-lg"></i>
<translate>PDF</translate>
</a>
</div>
<h1>{{ motion.agenda_item.getTitle() || motion.getTitle() }}</h1>
<h2>
@ -41,7 +42,7 @@
</div>
</div>
<div class="meta">
<div class="meta motion-detail">
<div class="title" ng-click="isMeta = !isMeta">
<div class="name">
<i class="fa fa-info-circle"></i>
@ -161,7 +162,7 @@
</div>
<div class="col-md-4">
<h3 ng-if="motion.polls.length > 0" translate>Voting result</h3>
<ol class="slimlist">
<ol>
<li ng-repeat="poll in motion.polls" class="spacer"
ng-if="poll.has_votes || operator.hasPerms('motions.can_manage')">
<strong translate-comment='ballot of a motion' translate>Vote</strong>
@ -264,64 +265,71 @@
<div class="details">
<div class="row">
<div class="linenumber-toolbar">
<!-- inline editing -->
<div class="pull-right inline-editing-activator"
ng-if="motion.isAllowed('update') && version == motion.getVersion(-1).id">
<button ng-if="!inlineEditing.active" ng-click="inlineEditing.enable()" class="btn btn-sm btn-default">
<i class="fa fa-toggle-off"></i>
<translate>Inline editing inactive</translate>
<i class="fa fa-pencil-square-o"></i>
<translate>Inline editing</translate>
</button>
<button ng-if="inlineEditing.active" ng-click="inlineEditing.disable()" class="btn btn-sm btn-default">
<i class="fa fa-toggle-on"></i>
<translate>Inline editing active</translate>
<i class="fa fa-times-circle"></i>
<translate>Inline editing</translate>
</button>
</div>
<!-- line number mode -->
<div class="line-number-setter {{ lineNumberMode }}">
<span class="btn-group" data-toggle="buttons">
<div class="btn btn-default disabled" title="{{ 'Line Numbering' | translate }}">
<div class="btn btn-sm btn-default disabled" title="{{ 'Line Numbering' | translate }}">
<i class="fa fa-list-ol" aria-hidden="true"></i>
</div>
<label class="btn btn-default" ng-class="{active: (lineNumberMode == 'none')}"
<label class="btn btn-sm btn-default" ng-class="{active: (lineNumberMode == 'none')}"
ng-click="lineNumberMode = 'none';">
<input type="radio" name="lineNumberMode" value="none" ng-model="lineNumberMode"
ng-checked="lineNumberMode == 'none'">
<translate>None</translate>
<translate>none</translate>
</label>
<label class="btn btn-default" ng-class="{active: (lineNumberMode == 'inline')}"
<label class="btn btn-sm btn-default" ng-class="{active: (lineNumberMode == 'inline')}"
ng-click="lineNumberMode = 'inline'">
<input type="radio" name="lineNumberMode" value="inline" ng-model="lineNumberMode"
ng-checked="lineNumberMode == 'inline'">
<translate>Inline</translate>
<translate>inline</translate>
</label>
<label class="btn btn-default" ng-class="{active: (lineNumberMode == 'outside')}"
<label class="btn btn-sm btn-default" ng-class="{active: (lineNumberMode == 'outside')}"
ng-click="lineNumberMode = 'outside'">
<input type="radio" name="lineNumberMode" value="outside" ng-model="lineNumberMode"
ng-checked="lineNumberMode == 'outside'">
<translate>Outside</translate>
<translate>outside</translate>
</label>
</span>
<!-- go to line number -->
<span>
<form class="input-group" style="max-width: 220px;" ng-if="lineNumberMode != 'none'" ng-submit="scrollToAndHighlight(gotoLinenumber)">
<input type="number" class="form-control" ng-model="gotoLinenumber" placeholder="{{ 'Line' | translate }}"></input>
<input type="number" class="form-control input-sm" ng-model="gotoLinenumber" placeholder="{{ 'Line' | translate }}"></input>
<span class="input-group-btn">
<button type="button" class="btn btn-default btn-slim" ng-show="gotoLinenumber"
<button type="button" class="btn btn-sm btn-default btn-slim" ng-show="gotoLinenumber"
ng-click="gotoLinenumber = ''; scrollToAndHighlight(0);">
<i class="fa fa-times text-danger"></i>
</button>
<button type="submit" class="btn btn-default">
<button type="submit" class="btn btn-sm btn-default">
<i class="fa fa-share"></i>
<translate>go</translate>
</button>
<button type="button" class="btn btn-default" os-perms="core.can_manage_projector"
<button type="button" class="btn btn-sm btn-default" os-perms="core.can_manage_projector"
ng-show="lineNumberMode != 'none' && motion.isProjected()" ng-click="toggleLinesForProjector()"
uib-tooltip="{{ 'Show highlighted line also on projector.' | translate }}">
<i class="fa" ng-class="linesForProjector ? 'fa-check-square-o' : 'fa-square-o'"></i>
<i class="fa" ng-class="linesForProjector ? 'fa-check-square-o' : 'fa-square-o'"></i>&nbsp;
<i class="fa fa-video-camera"></i>
</button>
</span>
</form>
</span>
</div>
</div>
<div ng-class="{'col-sm-8': (lineNumberMode != 'outside'), 'col-sm-12': (lineNumberMode == 'outside')}">
<div ng-if="motion.isAllowed('update') && version == motion.getVersion(-1).id">
@ -393,7 +401,7 @@
</div>
<!-- log -->
<button type="button" class="btn btn-default spacer" ng-click="isCollapsed = !isCollapsed" translate>
<button type="button" class="btn btn-sm btn-default spacer" ng-click="isCollapsed = !isCollapsed" translate>
Show history
</button>
<div uib-collapse="isCollapsed">
@ -410,7 +418,7 @@
</div>
</div>
<div class="details" ng-if="motion.comments">
<div class="details" ng-if="isAllowedToSeeCommentField()">
<h3>Motion Comments</h3>
<div ng-repeat="field in commentsFields">
<p ng-if="field.public || operator.hasPerms('motions.can_see_and_manage_comments')">

View File

@ -312,19 +312,6 @@
<div class="nobr" ng-show="motion.identifier">
{{ motion.identifier }}:
</div>
<!-- hover menu -->
<div ng-if="motion.isAllowed('update')" ng-class="{'hiddenDiv': !motion.hover}">
<span ng-if="motion.isAllowed('update')">
<a href="" ng-click="openDialog(motion)">
<i class="fa fa-pencil"></i></a>
</span>
<span ng-if="motion.isAllowed('delete')">
&nbsp;<a href="" ng-bootbox-confirm="{{ 'Are you sure you want to delete this entry?' | translate }}<br>
<b>{{ motion.getTitle() }}</b>"
ng-bootbox-confirm-action="delete(motion)">
<i class="fa fa-trash text-danger"></i></a>
</span>
</div>
</div>
<div class="title-col">
<!-- ID and title -->
@ -358,11 +345,25 @@
<div>
<small>
<span class="optional" translate>by</span>
<span class="optional" ng-repeat="submitter in motion.submitters | limitTo:3">
{{ submitter.get_full_name() }}<span ng-if="!$last">,</span></span><span ng-if="motion.submitters.length > 3">, ...</span>
<span class="optional" ng-repeat="submitter in motion.submitters | limitTo:1">
{{ submitter.get_full_name() }}<span ng-if="!$last">,</span></span><span ng-if="motion.submitters.length > 1">,
... [+{{ motion.submitters.length - 1 }}]</span>
<!-- sorry for merging them together, but otherwise there would be a whitespace because of the new line -->
</small>
</div>
<!-- hover menu -->
<div ng-if="motion.isAllowed('update')" ng-class="{'hiddenDiv': !motion.hover}">
<small>
<span ng-if="motion.isAllowed('update')">
<a href="" ng-click="openDialog(motion)" translate>Edit</a>
</span>
<span ng-if="motion.isAllowed('delete')"> &middot;
<a href="" class="text-danger"
ng-bootbox-confirm="{{ 'Are you sure you want to delete this entry?' | translate }}<br><b>{{ motion.getTitle() }}</b>"
ng-bootbox-confirm-action="delete(motion)" translate>Delete</a>
</span>
</small>
</div>
</div>
</div>

View File

@ -1,15 +1,15 @@
<div class="header">
<div class="title">
<div class="submenu">
<a ui-sref="users.user.list" class="btn btn-sm btn-default">
<i class="fa fa-angle-double-left fa-lg"></i>
<translate>Back to overview</translate>
</a>
<a os-perms="users.can_manage" class="btn btn-primary btn-sm"
ng-click="openDialog()" title="add new group">
<i class="fa fa-plus fa-lg"></i>
<translate>New</translate>
</a>
<a ui-sref="users.user.list" class="btn btn-sm btn-default">
<i class="fa fa-angle-double-left fa-lg"></i>
<translate>Back to overview</translate>
</a>
</div>
<h1 translate>Groups</h1>
</div>

View File

@ -2,7 +2,7 @@
<div class="title">
<div class="submenu">
<a ng-click="openDialog()" os-perms="users.can_manage" class="btn btn-primary btn-sm">
<i class="fa fa-user-plus fa-lg"></i>
<i class="fa fa-plus fa-lg"></i>
<translate>New</translate>
</a>
<a ui-sref="users.group.list" os-perms="users.can_manage" class="btn btn-default btn-sm">