Assignment improvements

- Use ckeditor for assignment description field (e.g. for candidatures
  using html).
- Use 2 decimal places for percentage of voting results (motions/assignments)
- Allow css style attributes 'float' and 'padding'.
- Remove progress bar in election result slide to get more space (height)
  for candidate rows.
This commit is contained in:
Emanuel Schütze 2017-11-20 16:40:39 +01:00
parent 8da08d9b36
commit 3d264683ff
9 changed files with 40 additions and 36 deletions

View File

@ -12,6 +12,7 @@ from openslides.utils.rest_api import (
ValidationError,
)
from ..utils.validate import validate_html
from .models import (
Assignment,
AssignmentOption,
@ -209,6 +210,11 @@ class AssignmentFullSerializer(ModelSerializer):
'tags',)
validators = (posts_validator,)
def validate(self, data):
if 'description' in data:
data['description'] = validate_html(data['description'])
return data
class AssignmentShortSerializer(AssignmentFullSerializer):
"""
@ -231,3 +237,8 @@ class AssignmentShortSerializer(AssignmentFullSerializer):
'agenda_item_id',
'tags',)
validators = (posts_validator,)
def validate(self, data):
if 'description' in data:
data['description'] = validate_html(data['description'])
return data

View File

@ -71,7 +71,7 @@ angular.module('OpenSlidesApp.assignments', [])
var skipPercents = config === 'YES_NO' && vote.value === 'Abstain';
if (base && !skipPercents) {
percentNumber = Math.round(vote.weight * 100 / base * 10) / 10;
percentNumber = Math.round(vote.weight * 100 / base * 100) / 100;
percentStr = "(" + percentNumber + "%)";
}
votes.push({

View File

@ -96,11 +96,13 @@ angular.module('OpenSlidesApp.assignments.site', [
.factory('AssignmentForm', [
'gettextCatalog',
'operator',
'Editor',
'Mediafile',
'Tag',
'Assignment',
'Agenda',
'AgendaTree',
function (gettextCatalog, operator, Tag, Assignment, Agenda, AgendaTree) {
function (gettextCatalog, operator, Editor, Mediafile, Tag, Assignment, Agenda, AgendaTree) {
return {
// ngDialog for assignment form
getDialog: function (assignment) {
@ -117,6 +119,7 @@ angular.module('OpenSlidesApp.assignments.site', [
},
// angular-formly fields for assignment form
getFormFields: function (isCreateForm) {
var images = Mediafile.getAllImages();
var formFields = [
{
key: 'title',
@ -128,9 +131,12 @@ angular.module('OpenSlidesApp.assignments.site', [
},
{
key: 'description',
type: 'textarea',
type: 'editor',
templateOptions: {
label: gettextCatalog.getString('Description')
},
data: {
ckeditorOptions: Editor.getOptions(images)
}
},
{

View File

@ -77,10 +77,10 @@
<div class="details">
<div ng-if="assignment.description">
<h3 translate>Description</h3>
<div class="white-space-pre-line">{{ assignment.description }}</div>
<div ng-bind-html="assignment.description | trusted"></div>
</div>
<div ng-if="assignment.phase !== 2">
<div ng-if="assignment.phase !== 2" class="clearfix">
<h3 translate>Candidates</h3>
<div ui-tree="treeOptions" ng-if="assignment.assignment_related_users.length"
data-empty-placeholder-enabled="false">

View File

@ -9,12 +9,13 @@
</div>
<!-- Description -->
<div ng-if="!showResult && assignment.description !== ''" class="white-space-pre-line zoomcontent">
{{ assignment.description }}
<div ng-if="!showResult && assignment.description !== ''"
ng-bind-html="assignment.description | trusted"
class="zoomcontent">
</div>
<!-- Candidates -->
<div class="zoomcontent" ng-if="!showResult">
<div class="zoomcontent" ng-if="!showResult" class="clearfix">
<h3 translate>Candidates</h3>
<ul>
<li ng-repeat="related_user in assignment.assignment_related_users | orderBy:'weight'">
@ -33,45 +34,31 @@
<table class="table table-bordered table-striped minimumTable">
<tr>
<th translate>Candidates
<th ng-if="poll.has_votes" class="col-sm-6" translate>Votes</th>
<th ng-if="poll.has_votes" class="col-sm-5" translate>Votes</th>
<!-- candidates (poll options) -->
<tr ng-repeat="option in poll.options | orderBy:'weight'">
<!-- candidate name -->
<td>
<td class="bold">
<i ng-if="option.is_elected" class="fa fa-star" title="{{ 'is elected' | translate }}"></i>
<strong>{{ option.candidate.get_full_name() }}</strong>
{{ option.candidate.get_full_name() }}
<!-- votes -->
<td ng-if="poll.has_votes">
<td ng-if="poll.has_votes" class="bold">
<div ng-init="votes = option.getVotes()">
<div ng-show="poll.pollmethod == 'yna' || poll.pollmethod == 'yn'">
<span ng-show="poll.pollmethod == 'yna'">
{{ votes[0].label | translate }}: {{ votes[0].value }} ·
{{ votes[1].label | translate }}: {{ votes[1].value }} ·
{{ votes[2].label | translate }}: {{ votes[2].value }} </span>
{{ votes[0].label | translate }}: {{ votes[0].value }} {{ votes[0].percentStr }}<br>
{{ votes[1].label | translate }}: {{ votes[1].value }} {{ votes[1].percentStr }}<br>
{{ votes[2].label | translate }}: {{ votes[2].value }} {{ votes[2].percentStr }}</span>
<span ng-show="poll.pollmethod == 'yn'">
{{ votes[0].label | translate }}: {{ votes[0].value }} ·
{{ votes[1].label | translate }}: {{ votes[1].value }}</span>
<uib-progress ng-if="votes[0].percentNumber>=0">
<uib-bar value="votes[0].percentNumber" type="success">
<span ng-hide="votes[0].percentNumber < 5">{{votes[0].percentNumber}} %</span>
</uib-bar>
<uib-bar value="votes[1].percentNumber" type="danger">
<span ng-hide="votes[1].percentNumber < 5">{{votes[1].percentNumber}} %</span>
</uib-bar>
<uib-bar value="votes[2].percentNumber" type="warning">
<span ng-hide="votes[2].percentNumber < 5">{{votes[2].percentNumber}} %</span>
</uib-bar>
</uib-progress>
{{ votes[0].label | translate }}: {{ votes[0].value }} {{ votes[0].percentStr }}<br>
{{ votes[1].label | translate }}: {{ votes[1].value }} {{ votes[1].percentStr }}</span>
</div>
<div ng-show="poll.pollmethod == 'votes'">
<div ng-repeat="vote in votes">
{{ vote.value }} {{ vote.percentStr }}
<div ng-if="vote.percentNumber >= 0">
<uib-progressbar value="vote.percentNumber" type="success"></uib-progressbar>
</div>
</div>
</div>
</div>

View File

@ -273,7 +273,7 @@ li {
font-size: 120%;
line-height: 40px;
}
.result .bold {
.result .bold, .electionresults .bold {
font-weight: bold;
}
.electionresults table {

View File

@ -1030,9 +1030,9 @@ angular.module('OpenSlidesApp.core', [
allowedContent:
'h1 h2 h3 b i u strike sup sub strong em;' +
'blockquote p pre table' +
'(text-align-left,text-align-center,text-align-right,text-align-justify,os-split-before,os-split-after){text-align};' +
'(text-align-left,text-align-center,text-align-right,text-align-justify,os-split-before,os-split-after){text-align, float, padding};' +
'a[!href];' +
'img[!src,alt]{width,height,float};' +
'img[!src,alt]{width,height,float, padding};' +
'tr th td caption;' +
'li(os-split-before,os-split-after); ol(os-split-before,os-split-after)[start]{list-style-type};' +
'ul(os-split-before,os-split-after){list-style};' +

View File

@ -155,7 +155,7 @@ angular.module('OpenSlidesApp.motions', [
// Calculate percent value
var base = this.getPercentBase(config, type);
if (base) {
percentNumber = Math.round(vote * 100 / (base) * 10) / 10;
percentNumber = Math.round(vote * 100 / (base) * 100) / 100;
percentStr = '(' + percentNumber + ' %)';
}
return {

View File

@ -16,7 +16,7 @@ allowed_attributes = {
'ol': ['start'],
}
allowed_styles = [
'color', 'background-color', 'height', 'width', 'text-align'
'color', 'background-color', 'height', 'width', 'text-align', 'float', 'padding'
]