A lot of template improvements and translation fixes

- Fixed agenda widget for special slide views (e.g. list of speakers, summary).
- Fixed back to motion(s) link
- Set icon for list of speakers widget.
- Fixed overlay widget layout of form elements.
- Added submenu with other config_pages to version.html.
- Updated completly DE translations, fixed EN strings.
- Coding style: Use correct ugettext and ugettext_lazy strings. Use "as _" for ugettext only.
Updated translation.
- Improved projector template (clock image, fixed facicon, added subtitle for list of speakers)
- Changed permission strings ('oneself'). Added check if group(pk=3) exists.
- Added event name and description to base template. Some minor template layout fixes.
- Use static subtile (no context var). Show last 2 old_speakers for projector.
- Cut old_speakers.
- Projektor template style changes (e.g. overlay list of speakers).
This commit is contained in:
Emanuel Schuetze 2013-04-22 19:59:05 +02:00
parent f581169e1e
commit abad75c129
60 changed files with 1807 additions and 1627 deletions

View File

@ -45,7 +45,6 @@ def get_personal_info_widget(request):
'submitted_motions': Motion.objects.filter(submitter=request.user), 'submitted_motions': Motion.objects.filter(submitter=request.user),
'config_motion_min_supporters': config['motion_min_supporters'], 'config_motion_min_supporters': config['motion_min_supporters'],
'supported_motions': Motion.objects.filter(supporter=request.user)}) 'supported_motions': Motion.objects.filter(supporter=request.user)})
try: try:
from openslides.assignment.models import Assignment from openslides.assignment.models import Assignment
except ImportError: except ImportError:

View File

@ -14,7 +14,7 @@ from datetime import datetime
from django.db import models from django.db import models
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _, ugettext_noop, ugettext from django.utils.translation import ugettext_lazy, ugettext_noop, ugettext as _
from mptt.models import MPTTModel, TreeForeignKey from mptt.models import MPTTModel, TreeForeignKey
@ -38,30 +38,30 @@ class Item(MPTTModel, SlideMixin):
ORGANIZATIONAL_ITEM = 2 ORGANIZATIONAL_ITEM = 2
ITEM_TYPE = ( ITEM_TYPE = (
(AGENDA_ITEM, _('Agenda item')), (AGENDA_ITEM, ugettext_lazy('Agenda item')),
(ORGANIZATIONAL_ITEM, _('Organizational item'))) (ORGANIZATIONAL_ITEM, ugettext_lazy('Organizational item')))
title = models.CharField(null=True, max_length=255, verbose_name=_("Title")) title = models.CharField(null=True, max_length=255, verbose_name=ugettext_lazy("Title"))
""" """
Title of the agenda item. Title of the agenda item.
""" """
text = models.TextField(null=True, blank=True, verbose_name=_("Text")) text = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Text"))
""" """
The optional text of the agenda item. The optional text of the agenda item.
""" """
comment = models.TextField(null=True, blank=True, verbose_name=_("Comment")) comment = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Comment"))
""" """
Optional comment to the agenda item. Will not be shoun to normal users. Optional comment to the agenda item. Will not be shoun to normal users.
""" """
closed = models.BooleanField(default=False, verbose_name=_("Closed")) closed = models.BooleanField(default=False, verbose_name=ugettext_lazy("Closed"))
""" """
Flag, if the item is finished. Flag, if the item is finished.
""" """
weight = models.IntegerField(default=0, verbose_name=_("Weight")) weight = models.IntegerField(default=0, verbose_name=ugettext_lazy("Weight"))
""" """
Weight to sort the item in the agenda. Weight to sort the item in the agenda.
""" """
@ -73,7 +73,7 @@ class Item(MPTTModel, SlideMixin):
""" """
type = models.IntegerField(max_length=1, choices=ITEM_TYPE, type = models.IntegerField(max_length=1, choices=ITEM_TYPE,
default=AGENDA_ITEM, verbose_name=_("Type")) default=AGENDA_ITEM, verbose_name=ugettext_lazy("Type"))
""" """
Type of the agenda item. Type of the agenda item.
@ -81,7 +81,7 @@ class Item(MPTTModel, SlideMixin):
""" """
duration = models.CharField(null=True, blank=True, max_length=5, duration = models.CharField(null=True, blank=True, max_length=5,
verbose_name=_("Duration (hh:mm)")) verbose_name=ugettext_lazy("Duration (hh:mm)"))
""" """
The intended duration for the topic. The intended duration for the topic.
""" """
@ -94,7 +94,7 @@ class Item(MPTTModel, SlideMixin):
""" """
speaker_list_closed = models.BooleanField( speaker_list_closed = models.BooleanField(
default=False, verbose_name=_("List of speakers is closed")) default=False, verbose_name=ugettext_lazy("List of speakers is closed"))
""" """
True, if the list of speakers is closed. True, if the list of speakers is closed.
""" """
@ -125,7 +125,7 @@ class Item(MPTTModel, SlideMixin):
For use in Template For use in Template
??Why does {% trans item.print_related_type|capfirst %} not work?? ??Why does {% trans item.print_related_type|capfirst %} not work??
""" """
return ugettext(self.get_related_type().capitalize()) return _(self.get_related_type().capitalize())
def get_title(self): def get_title(self):
""" """
@ -158,9 +158,12 @@ class Item(MPTTModel, SlideMixin):
} }
elif config['presentation_argument'] == 'show_list_of_speakers': elif config['presentation_argument'] == 'show_list_of_speakers':
speakers = Speaker.objects.filter(time=None, item=self.pk).order_by('weight') speakers = Speaker.objects.filter(time=None, item=self.pk).order_by('weight')
data = {'title': _('List of speakers for %s') % self.get_title(), old_speakers = Speaker.objects.filter(item=self.pk).exclude(time=None).order_by('time')
slice_items = max(0, old_speakers.count()-2)
data = {'title': self.get_title(),
'template': 'projector/agenda_list_of_speaker.html', 'template': 'projector/agenda_list_of_speaker.html',
'speakers': speakers} 'speakers': speakers,
'old_speakers': old_speakers[slice_items:]}
elif self.related_sid: elif self.related_sid:
data = self.get_related_slide().slide() data = self.get_related_slide().slide()
else: else:
@ -244,7 +247,7 @@ class Item(MPTTModel, SlideMixin):
class SpeakerManager(models.Manager): class SpeakerManager(models.Manager):
def add(self, person, item): def add(self, person, item):
if self.filter(person=person, item=item, time=None).exists(): if self.filter(person=person, item=item, time=None).exists():
raise OpenSlidesError(_('%s is already on the list of speakers of item %d.') % (person, item.id)) raise OpenSlidesError(_('%(person)s is already on the list of speakers of item %(id)s.') % {'person': person, 'id': item.id})
weight = (self.filter(item=item).aggregate( weight = (self.filter(item=item).aggregate(
models.Max('weight'))['weight__max'] or 0) models.Max('weight'))['weight__max'] or 0)
return self.create(item=item, person=person, weight=weight + 1) return self.create(item=item, person=person, weight=weight + 1)
@ -279,7 +282,7 @@ class Speaker(models.Model):
class Meta: class Meta:
permissions = ( permissions = (
('can_be_speaker', ugettext_noop('Can be speaker')), ('can_be_speaker', ugettext_noop('Can put oneself on the list of speakers')),
) )
def __unicode__(self): def __unicode__(self):

View File

@ -12,7 +12,7 @@
from django.dispatch import receiver from django.dispatch import receiver
from django import forms from django import forms
from django.utils.translation import ugettext_lazy, ugettext_noop, ugettext as _ from django.utils.translation import ugettext_lazy, ugettext_noop
from django.template.loader import render_to_string from django.template.loader import render_to_string
from openslides.config.signals import config_signal from openslides.config.signals import config_signal
@ -41,7 +41,7 @@ def setup_agenda_config_page(sender, **kwargs):
widget=forms.DateTimeInput(format='%d.%m.%Y %H:%M'), widget=forms.DateTimeInput(format='%d.%m.%Y %H:%M'),
required=False, required=False,
label=ugettext_lazy('Begin of event'), label=ugettext_lazy('Begin of event'),
help_text=_('Input format: DD.MM.YYYY HH:MM'))) help_text=ugettext_lazy('Input format: DD.MM.YYYY HH:MM')))
extra_stylefiles = ['styles/timepicker.css', 'styles/jquery-ui/jquery-ui.custom.min.css'] extra_stylefiles = ['styles/timepicker.css', 'styles/jquery-ui/jquery-ui.custom.min.css']
extra_javascript = ['javascript/jquery-ui.custom.min.js', extra_javascript = ['javascript/jquery-ui.custom.min.js',

View File

@ -10,7 +10,7 @@
:license: GNU GPL, see LICENSE for more details. :license: GNU GPL, see LICENSE for more details.
""" """
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy, ugettext as _
from openslides.projector.api import register_slidemodel, register_slidefunc from openslides.projector.api import register_slidemodel, register_slidefunc
@ -26,4 +26,4 @@ def agenda_show():
return data return data
register_slidemodel(Item, control_template='agenda/control_item.html') register_slidemodel(Item, control_template='agenda/control_item.html')
register_slidefunc('agenda', agenda_show, weight=-1, name=_('Agenda')) register_slidefunc('agenda', agenda_show, weight=-1, name=ugettext_lazy('Agenda'))

View File

@ -1,23 +1,8 @@
{% load i18n %} {% load i18n %}
<style type="text/css"> <div id="overlay_list_of_speaker_box">
#overlay_speaker_inner {
position: fixed;
bottom: 0;
right: 0;
border-radius: 0.2em;
background-color: #cccccc;
opacity: 0.6;
padding: 0.2em 0;
margin: 1em;
z-index:2;
padding: 3px;
}
</style>
<div id="overlay_speaker_inner">
{% if speakers %} {% if speakers %}
<header>{% trans "List of speakers:" %}</header> <h3>{% trans "List of speakers" %}:</h3>
<ol> <ol>
{% for speaker in speakers %} {% for speaker in speakers %}
<li>{{ speaker }}</li> <li>{{ speaker }}</li>

View File

@ -2,5 +2,5 @@
{% load tags %} {% load tags %}
<div> <div>
<a href="{% url 'agenda_current_list_of_speakers' %}">{% trans 'Put me on the current list of speakers' %}</a> <a href="{% url 'agenda_current_list_of_speakers' %}" class="btn">{% trans 'Put me on the current list of speakers' %}</a>
</div> </div>

View File

@ -79,12 +79,14 @@
{% if old_speakers %} {% if old_speakers %}
<div class="well"> <div class="well">
<b>{% trans "Last speakers:" %}</b> <b>{% trans "Last speakers" %}:</b>
<div class="btn-group" data-toggle="buttons-checkbox"> {% if old_speakers|length > 1 %}
<button type="button" class="btn btn-mini" data-toggle="collapse" data-target="#all_speakers"> <div class="btn-group" data-toggle="buttons-checkbox">
{% trans "Show all speakers" %} <button type="button" class="btn btn-mini" data-toggle="collapse" data-target="#all_speakers">
</button> {% trans "Show all speakers" %}
</div> </button>
</div>
{% endif %}
<br> <br>
<div id="all_speakers" class="collapse out"> <div id="all_speakers" class="collapse out">
{% for speaker in old_speakers %} {% for speaker in old_speakers %}
@ -139,7 +141,7 @@
<span>{{ forloop.counter }}.</span> <span>{{ forloop.counter }}.</span>
<a href="{% model_url speaker %}">{{ speaker }}</a> <a href="{% model_url speaker %}">{{ speaker }}</a>
{% if perms.agenda.can_manage_agenda %} {% if perms.agenda.can_manage_agenda %}
<a href="{% url 'agenda_speaker_speak' item.pk speaker.person.person_id %}" class="btn btn-mini"><i class="icon-bell"></i> Finished speech</a> <a href="{% url 'agenda_speaker_speak' item.pk speaker.person.person_id %}" class="btn btn-mini"><i class="icon-bell"></i> {% trans "Next speaker" %}</a>
<a href="{% model_url speaker 'delete' %}" title="{% trans 'Delete' %}" class="btn btn-mini"> <a href="{% model_url speaker 'delete' %}" title="{% trans 'Delete' %}" class="btn btn-mini">
<i class="icon-remove"></i> <i class="icon-remove"></i>
</a> </a>

View File

@ -3,7 +3,9 @@
<ul style="line-height: 180%"> <ul style="line-height: 180%">
<li class="{% if agenda.active %}activeline{% endif %}"> <li class="{% if agenda.active %}activeline{% endif %}">
<a href="{% url 'projector_activate_slide' agenda.key %}" class="activate_link btn {% if agenda.active %}btn-primary{% endif %} btn-mini" title="{% trans 'Show' %}"> <a href="{% url 'projector_activate_slide' agenda.key %}"
class="activate_link btn {% if agenda.active %}btn-primary{% endif %} btn-mini"
rel="tooltip" data-original-title="{% trans 'Show' %}">
<i class="icon-facetime-video {% if agenda.active %}icon-white{% endif %}"></i> <i class="icon-facetime-video {% if agenda.active %}icon-white{% endif %}"></i>
</a>&nbsp; </a>&nbsp;
<a href="{% url 'projctor_preview_slide' agenda.key %}" title="{% trans 'Preview' %}" class="icon preview right"> <a href="{% url 'projctor_preview_slide' agenda.key %}" title="{% trans 'Preview' %}" class="icon preview right">
@ -16,8 +18,10 @@
<ul style="line-height: 180%"> <ul style="line-height: 180%">
{% for item in items %} {% for item in items %}
<li class="{% if item.active %}activeline{% endif %}"> <li class="{% if item.active %}activeline{% endif %}">
<a href="{% url 'projector_activate_slide' item.sid %}" class="activate_link btn {% if item.active %}btn-primary{% endif %} btn-mini" title="{% trans 'Show' %}"> <a href="{% url 'projector_activate_slide' item.sid %}"
<i class="icon-facetime-video {% if item.active %}icon-white{% endif %}"></i> class="activate_link btn {% if item.active and not summary and not speakers %}btn-primary{% endif %} btn-mini"
rel="tooltip" data-original-title="{% trans 'Show' %}">
<i class="icon-facetime-video {% if item.active and not summary and not speakers %}icon-white{% endif %}"></i>
</a>&nbsp; </a>&nbsp;
<a href="{% model_url item 'edit' %}" title="{% trans 'Edit' %}" class="btn btn-mini right"> <a href="{% model_url item 'edit' %}" title="{% trans 'Edit' %}" class="btn btn-mini right">
<i class="icon-pencil"></i> <i class="icon-pencil"></i>
@ -25,9 +29,16 @@
<a href="{% url 'projctor_preview_slide' item.sid %}" title="{% trans 'Preview' %}" class="btn btn-mini right"> <a href="{% url 'projctor_preview_slide' item.sid %}" title="{% trans 'Preview' %}" class="btn btn-mini right">
<i class="icon-search"></i> <i class="icon-search"></i>
</a> </a>
<a href="{% url 'projector_activate_slide' item.sid 'show_list_of_speakers' %}"
class="activate_link btn btn-mini right {% if item.active and speakers %}btn-primary{% endif %}"
rel="tooltip" data-original-title="{% trans 'Show list of speakers' %}">
<i class="icon icon-bell {% if item.active and speakers %}icon-white{% endif %}"></i>
</a>
{% if not item.is_leaf_node %} {% if not item.is_leaf_node %}
<a class="activate_link btn btn-mini {% if item.active %}btn-primary{% endif %} right" href="{% url 'projector_activate_slide' item.sid 'summary' %}" title="{% trans 'Show summary for this item' %}"> <a href="{% url 'projector_activate_slide' item.sid 'summary' %}"
<i class="icon-summary {% if item.active %}icon-white{% endif %}"></i> class="activate_link btn btn-mini {% if item.active and summary %}btn-primary{% endif %} right"
rel="tooltip" data-original-title="{% trans 'Show summary for this item' %}">
<i class="icon-summary {% if item.active and summary %}icon-white{% endif %}"></i>
</a> </a>
{% endif %} {% endif %}
{% for p in item.get_ancestors %} {% for p in item.get_ancestors %}

View File

@ -4,28 +4,27 @@
{% block title %}{{ block.super }} - {{ item }}{% endblock %} {% block title %}{{ block.super }} - {{ item }}{% endblock %}
{% block header %}
<style type="text/css">
#list_of_speakers li
{
font-size: 130%;
line-height: 160%;
}
</style>
{% endblock %}
{% block content %} {% block content %}
<h1>{{ title }}</h1> <h1>{{ title }}</h1>
<h2 style="margin-top: -15px;">{% trans 'List of speakers' %}</h2>
{% endblock %} {% endblock %}
{% block scrollcontent %} {% block scrollcontent %}
{% if old_speakers|length > 0 %}
<ul class="list_of_speakers last_speakers">
{% for speaker in old_speakers %}
<li>{{ speaker }}</li>
{% endfor %}
</ul>
{% endif %}
{% if speakers %} {% if speakers %}
<ol id="list_of_speakers"> <ol class="list_of_speakers">
{% for speaker in speakers %} {% for speaker in speakers %}
<li>{{ speaker }}</li> <li>{{ speaker }}</li>
{% endfor %} {% endfor %}
</ol> </ol>
{% else %} {% else %}
{% trans 'The list of speakers is empty' %} <p><i>{% trans 'The list of speakers is empty.' %}</i></p>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View File

@ -266,7 +266,7 @@ class SpeakerAppendView(SingleObjectMixin, RedirectView):
def pre_redirect(self, request, *args, **kwargs): def pre_redirect(self, request, *args, **kwargs):
self.object = self.get_object() self.object = self.get_object()
if self.object.speaker_list_closed: if self.object.speaker_list_closed:
messages.error(request, _('List of speakers is closed.')) messages.error(request, _('The list of speakers is closed.'))
else: else:
try: try:
Speaker.objects.add(item=self.object, person=request.user) Speaker.objects.add(item=self.object, person=request.user)
@ -337,8 +337,10 @@ class SpeakerSpeakView(SingleObjectMixin, RedirectView):
item=self.object.pk).exclude( item=self.object.pk).exclude(
weight=None).get() weight=None).get()
except Speaker.DoesNotExist: except Speaker.DoesNotExist:
messages.error(self.request, _('Person %s is not on the list of item %s.' messages.error(
% (kwargs['person_id'], self.object))) self.request,
_('%(person)s is not on the list of %(item)s.')
% {'person': kwargs['person_id'], 'item': self.object})
else: else:
speaker.speak() speaker.speak()
@ -439,7 +441,7 @@ class CurrentListOfSpeakersView(RedirectView):
if item is None: if item is None:
messages.error(request, _( messages.error(request, _(
'There is no list of speakers for the current slide. ' 'There is no list of speakers for the current slide. '
'Please choose your agenda item manually from the agenda.')) 'Please choose the agenda item manually from the agenda.'))
return reverse('dashboard') return reverse('dashboard')
if self.request.user.has_perm('agenda.can_be_speaker'): if self.request.user.has_perm('agenda.can_be_speaker'):
@ -483,7 +485,9 @@ def get_widgets(request):
template='agenda/widget.html', template='agenda/widget.html',
context={ context={
'agenda': SLIDE['agenda'], 'agenda': SLIDE['agenda'],
'items': Item.objects.all()}, 'items': Item.objects.all(),
'summary': config['presentation_argument'] == 'summary',
'speakers': config['presentation_argument'] == 'show_list_of_speakers'},
permission_required='projector.can_manage_projector'), permission_required='projector.can_manage_projector'),
Widget( Widget(

View File

@ -11,7 +11,7 @@
""" """
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy
from openslides.utils.forms import CssClassMixin from openslides.utils.forms import CssClassMixin
from openslides.utils.person import PersonFormField from openslides.utils.person import PersonFormField
@ -21,7 +21,7 @@ from openslides.assignment.models import Assignment
class AssignmentForm(forms.ModelForm, CssClassMixin): class AssignmentForm(forms.ModelForm, CssClassMixin):
posts = forms.IntegerField( posts = forms.IntegerField(
min_value=1, initial=1, label=_("Number of available posts")) min_value=1, initial=1, label=ugettext_lazy("Number of available posts"))
class Meta: class Meta:
model = Assignment model = Assignment
@ -31,5 +31,5 @@ class AssignmentForm(forms.ModelForm, CssClassMixin):
class AssignmentRunForm(forms.Form, CssClassMixin): class AssignmentRunForm(forms.Form, CssClassMixin):
candidate = PersonFormField( candidate = PersonFormField(
widget=forms.Select(attrs={'class': 'medium-input'}), widget=forms.Select(attrs={'class': 'medium-input'}),
label=_("Nominate a participant"), label=ugettext_lazy("Nominate a participant"),
) )

View File

@ -12,7 +12,7 @@
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _, ugettext_noop # TODO Change this in the code from django.utils.translation import ugettext as _, ugettext_lazy, ugettext_noop
from openslides.utils.person import PersonField from openslides.utils.person import PersonField
from openslides.config.api import config from openslides.config.api import config
@ -39,17 +39,17 @@ class AssignmentCandidate(models.Model):
class Assignment(models.Model, SlideMixin): class Assignment(models.Model, SlideMixin):
prefix = 'assignment' prefix = 'assignment'
STATUS = ( STATUS = (
('sea', _('Searching for candidates')), ('sea', ugettext_lazy('Searching for candidates')),
('vot', _('Voting')), ('vot', ugettext_lazy('Voting')),
('fin', _('Finished')), ('fin', ugettext_lazy('Finished')),
) )
name = models.CharField(max_length=100, verbose_name=_("Name")) name = models.CharField(max_length=100, verbose_name=ugettext_lazy("Name"))
description = models.TextField(null=True, blank=True, verbose_name=_("Description")) description = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Description"))
posts = models.PositiveSmallIntegerField(verbose_name=_("Number of available posts")) posts = models.PositiveSmallIntegerField(verbose_name=ugettext_lazy("Number of available posts"))
polldescription = models.CharField( polldescription = models.CharField(
max_length=100, null=True, blank=True, max_length=100, null=True, blank=True,
verbose_name=_("Comment on the ballot paper")) verbose_name=ugettext_lazy("Comment on the ballot paper"))
status = models.CharField(max_length=3, choices=STATUS, default='sea') status = models.CharField(max_length=3, choices=STATUS, default='sea')
def set_status(self, status): def set_status(self, status):
@ -240,9 +240,8 @@ class Assignment(models.Model, SlideMixin):
class Meta: class Meta:
permissions = ( permissions = (
('can_see_assignment', ugettext_noop("Can see assignment")), ('can_see_assignment', ugettext_noop("Can see assignment")),
('can_nominate_other', ('can_nominate_other', ugettext_noop("Can nominate another person")),
ugettext_noop("Can nominate another person")), ('can_nominate_self', ugettext_noop("Can nominate oneself")),
('can_nominate_self', ugettext_noop("Can nominate themselves")),
('can_manage_assignment', ugettext_noop("Can manage assignment")), ('can_manage_assignment', ugettext_noop("Can manage assignment")),
) )
ordering = ('name',) ordering = ('name',)

View File

@ -12,7 +12,7 @@
from django.dispatch import receiver from django.dispatch import receiver
from django import forms from django import forms
from django.utils.translation import ugettext_lazy, ugettext_noop, ugettext as _ from django.utils.translation import ugettext as _, ugettext_lazy, ugettext_noop
from openslides.config.signals import config_signal from openslides.config.signals import config_signal
from openslides.config.api import ConfigVariable, ConfigPage from openslides.config.api import ConfigVariable, ConfigPage
@ -28,19 +28,19 @@ def setup_assignment_config_page(sender, **kwargs):
default_value=False, default_value=False,
form_field=forms.BooleanField( form_field=forms.BooleanField(
required=False, required=False,
label=_('Only publish voting results for selected winners ' label=ugettext_lazy('Only publish voting results for selected '
'(Projector view only)'))) 'winners (Projector view only)')))
assignment_pdf_ballot_papers_selection = ConfigVariable( assignment_pdf_ballot_papers_selection = ConfigVariable(
name='assignment_pdf_ballot_papers_selection', name='assignment_pdf_ballot_papers_selection',
default_value='CUSTOM_NUMBER', default_value='CUSTOM_NUMBER',
form_field=forms.ChoiceField( form_field=forms.ChoiceField(
widget=forms.Select(), widget=forms.Select(),
required=False, required=False,
label=_('Number of ballot papers (selection)'), label=ugettext_lazy('Number of ballot papers (selection)'),
choices=( choices=(
('NUMBER_OF_DELEGATES', _('Number of all delegates')), ('NUMBER_OF_DELEGATES', ugettext_lazy('Number of all delegates')),
('NUMBER_OF_ALL_PARTICIPANTS', _('Number of all participants')), ('NUMBER_OF_ALL_PARTICIPANTS', ugettext_lazy('Number of all participants')),
('CUSTOM_NUMBER', _('Use the following custom number'))))) ('CUSTOM_NUMBER', ugettext_lazy('Use the following custom number')))))
assignment_pdf_ballot_papers_number = ConfigVariable( assignment_pdf_ballot_papers_number = ConfigVariable(
name='assignment_pdf_ballot_papers_number', name='assignment_pdf_ballot_papers_number',
default_value=8, default_value=8,
@ -48,32 +48,32 @@ def setup_assignment_config_page(sender, **kwargs):
widget=forms.TextInput(attrs={'class': 'small-input'}), widget=forms.TextInput(attrs={'class': 'small-input'}),
required=False, required=False,
min_value=1, min_value=1,
label=_('Custom number of ballot papers'))) label=ugettext_lazy('Custom number of ballot papers')))
assignment_pdf_title = ConfigVariable( assignment_pdf_title = ConfigVariable(
name='assignment_pdf_title', name='assignment_pdf_title',
default_value=_('Elections'), default_value=_('Elections'),
form_field=forms.CharField( form_field=forms.CharField(
widget=forms.TextInput(), widget=forms.TextInput(),
required=False, required=False,
label=_('Title for PDF document (all elections)'))) label=ugettext_lazy('Title for PDF document (all elections)')))
assignment_pdf_preamble = ConfigVariable( assignment_pdf_preamble = ConfigVariable(
name='assignment_pdf_preamble', name='assignment_pdf_preamble',
default_value='', default_value='',
form_field=forms.CharField( form_field=forms.CharField(
widget=forms.Textarea(), widget=forms.Textarea(),
required=False, required=False,
label=_('Preamble text for PDF document (all elections)'))) label=ugettext_lazy('Preamble text for PDF document (all elections)')))
assignment_poll_vote_values = ConfigVariable( assignment_poll_vote_values = ConfigVariable(
name='assignment_poll_vote_values', name='assignment_poll_vote_values',
default_value='auto', default_value='auto',
form_field=forms.ChoiceField( form_field=forms.ChoiceField(
widget=forms.Select(), widget=forms.Select(),
required=False, required=False,
label=_('Election method'), label=ugettext_lazy('Election method'),
choices=( choices=(
('auto', _('Automatic assign of method.')), ('auto', ugettext_lazy('Automatic assign of method')),
('votes', _('Always one option per candidate.')), ('votes', ugettext_lazy('Always one option per candidate')),
('yesnoabstain', _('Always Yes-No-Abstain per candidate.'))))) ('yesnoabstain', ugettext_lazy('Always Yes-No-Abstain per candidate')))))
return ConfigPage(title=ugettext_noop('Elections'), return ConfigPage(title=ugettext_noop('Elections'),
url='assignment', url='assignment',

View File

@ -31,7 +31,7 @@ from openslides.utils.utils import (
from openslides.utils.views import FormView, DeleteView, PDFView, RedirectView from openslides.utils.views import FormView, DeleteView, PDFView, RedirectView
from openslides.utils.person import get_person from openslides.utils.person import get_person
from openslides.config.api import config from openslides.config.api import config
from openslides.participant.models import User from openslides.participant.models import User, Group
from openslides.projector.projector import Widget from openslides.projector.projector import Widget
from openslides.poll.views import PollFormView from openslides.poll.views import PollFormView
from openslides.agenda.models import Item from openslides.agenda.models import Item
@ -564,7 +564,12 @@ class AssignmentPollPDF(PDFView):
# set number of ballot papers # set number of ballot papers
if ballot_papers_selection == "NUMBER_OF_DELEGATES": if ballot_papers_selection == "NUMBER_OF_DELEGATES":
number = User.objects.filter(type__iexact="delegate").count() try:
if Group.objects.get(pk=3):
number = User.objects.filter(groups__pk=3).count()
except Group.DoesNotExist:
number = 0
elif ballot_papers_selection == "NUMBER_OF_ALL_PARTICIPANTS": elif ballot_papers_selection == "NUMBER_OF_ALL_PARTICIPANTS":
number = int(User.objects.count()) number = int(User.objects.count())
else: # ballot_papers_selection == "CUSTOM_NUMBER" else: # ballot_papers_selection == "CUSTOM_NUMBER"

View File

@ -1,7 +1,6 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load i18n %} {% load i18n %}
{% load staticfiles %} {% load staticfiles %}
{% block content %} {% block content %}
@ -12,7 +11,7 @@
<div class="btn-toolbar"> <div class="btn-toolbar">
<div class="btn-group"> <div class="btn-group">
{% for config_page_dict in config_pages_list %} {% for config_page_dict in config_pages_list %}
<a href="/config/{{ config_page_dict.config_page.url }}/" class="btn btn-mini {% if config_page_dict.active %}active{% endif %}">{{ config_page_dict.config_page.title }}</a> <a href="/config/{{ config_page_dict.config_page.url }}/" class="btn btn-mini {% if config_page_dict.active %}active{% endif %}">{% trans config_page_dict.config_page.title %}</a>
{% endfor %} {% endfor %}
<a href="{% url 'core_version' %}" class="btn btn-mini">{% trans 'Version' %}</a> <a href="{% url 'core_version' %}" class="btn btn-mini">{% trans 'Version' %}</a>
</div> </div>

View File

@ -13,7 +13,7 @@
from django import forms from django import forms
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.contrib import messages from django.contrib import messages
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _, ugettext_lazy
from openslides.utils.views import FormView from openslides.utils.views import FormView
from openslides.utils.template import Tab from openslides.utils.template import Tab
@ -115,7 +115,7 @@ class ConfigView(FormView):
""" """
for key in form.cleaned_data: for key in form.cleaned_data:
config[key] = form.cleaned_data[key] config[key] = form.cleaned_data[key]
messages.success(self.request, _('%s settings successfully saved.' % self.config_page.title)) messages.success(self.request, _('%s settings successfully saved.') % _(self.config_page.title))
return super(ConfigView, self).form_valid(form) return super(ConfigView, self).form_valid(form)

View File

@ -12,7 +12,7 @@
from django.dispatch import Signal, receiver from django.dispatch import Signal, receiver
from django import forms from django import forms
from django.utils.translation import ugettext_lazy, ugettext_noop, ugettext as _ from django.utils.translation import ugettext as _, ugettext_lazy, ugettext_noop
from openslides.config.signals import config_signal from openslides.config.signals import config_signal
from openslides.config.api import ConfigVariable, ConfigGroup, ConfigGroupedPage from openslides.config.api import ConfigVariable, ConfigGroup, ConfigGroupedPage

View File

@ -5,7 +5,20 @@
{% block title %}{{ block.super }} {% trans 'Version' %}{% endblock %} {% block title %}{{ block.super }} {% trans 'Version' %}{% endblock %}
{% block content %} {% block content %}
<h1>{% trans 'Versions' %}</h1> <h1>
{% trans 'Version' %}
<small>{% trans active_config_page.title %}</small>
<small class="pull-right">
<div class="btn-toolbar">
<div class="btn-group">
{% for config_page_dict in config_pages_list %}
<a href="/config/{{ config_page_dict.config_page.url }}/" class="btn btn-mini">{% trans config_page_dict.config_page.title %}</a>
{% endfor %}
<a href="{% url 'core_version' %}" class="btn btn-mini active">{% trans 'Version' %}</a>
</div>
</div>
</small>
</h1>
{% for version in versions %} {% for version in versions %}
<p>{{ version.0 }} {% trans "Version" %}: {{ version.1 }}</p> <p>{{ version.0 }} {% trans "Version" %}: {{ version.1 }}</p>
{% endfor %} {% endfor %}

View File

@ -15,6 +15,7 @@ from django.utils.importlib import import_module
from openslides import get_version, get_git_commit_id, RELEASE from openslides import get_version, get_git_commit_id, RELEASE
from openslides.utils.views import TemplateView from openslides.utils.views import TemplateView
from .signals import config_signal
class VersionView(TemplateView): class VersionView(TemplateView):
@ -35,6 +36,13 @@ class VersionView(TemplateView):
openslides_version_string += ' Commit: %s' % get_git_commit_id() openslides_version_string += ' Commit: %s' % get_git_commit_id()
context['versions'] = [('OpenSlides', openslides_version_string)] context['versions'] = [('OpenSlides', openslides_version_string)]
# collect other config pages
config_pages_list = []
for receiver, config_page in config_signal.send(sender=self):
if config_page.is_shown():
config_pages_list.append({'config_page': config_page})
context['config_pages_list'] = sorted(config_pages_list, key=lambda config_page_dict: config_page_dict['config_page'].weight)
# Versions of plugins. # Versions of plugins.
for plugin in settings.INSTALLED_PLUGINS: for plugin in settings.INSTALLED_PLUGINS:
try: try:

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,210 @@
# SOME DESCRIPTIVE TITLE. # German translations for JavaScript file in OpenSlides package.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # Copyright (C) 2011-2013 by OpenSlides team, see AUTHORS.
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the OpenSlides package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # Emanuel Schütze <emanuel@intevation.de>, 2013.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: OpenSlides 1.3\n" "Project-Id-Version: OpenSlides 1.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-12 21:29+0100\n" "POT-Creation-Date: 2013-04-23 16:17+0200\n"
"PO-Revision-Date: 2012-07-28 11:07+0200\n" "PO-Revision-Date: 2012-07-28 11:07+0200\n"
"Last-Translator: Oskar Hahn <mail@oshahn.de>\n" "Last-Translator: Emanuel Schütze <emanuel@intevation.de>\n"
"Language: de\n" "Language: de\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: agenda/static/javascript/agenda-config-datepicker.js:9
#: agenda/static/javascript/agenda-config-datepicker.js:39
msgid "en"
msgstr "en"
#: agenda/static/javascript/agenda-config-datepicker.js:10
msgid "previous month"
msgstr "vorheriger Monat"
#: agenda/static/javascript/agenda-config-datepicker.js:11
msgid "next month"
msgstr "nächster Monat"
#: agenda/static/javascript/agenda-config-datepicker.js:13
msgid "January"
msgstr "Januar"
#: agenda/static/javascript/agenda-config-datepicker.js:13
msgid "February"
msgstr "Februar"
#: agenda/static/javascript/agenda-config-datepicker.js:13
msgid "March"
msgstr "März"
#: agenda/static/javascript/agenda-config-datepicker.js:14
msgid "April"
msgstr "April"
#: agenda/static/javascript/agenda-config-datepicker.js:14
#: agenda/static/javascript/agenda-config-datepicker.js:20
msgid "May"
msgstr "Mai"
#: agenda/static/javascript/agenda-config-datepicker.js:14
msgid "June"
msgstr "Juni"
#: agenda/static/javascript/agenda-config-datepicker.js:15
msgid "July"
msgstr "Juli"
#: agenda/static/javascript/agenda-config-datepicker.js:15
msgid "August"
msgstr "August"
#: agenda/static/javascript/agenda-config-datepicker.js:15
msgid "September"
msgstr "September"
#: agenda/static/javascript/agenda-config-datepicker.js:16
msgid "October"
msgstr "Oktober"
#: agenda/static/javascript/agenda-config-datepicker.js:16
msgid "November"
msgstr "November"
#: agenda/static/javascript/agenda-config-datepicker.js:16
msgid "December"
msgstr "Dezember"
#: agenda/static/javascript/agenda-config-datepicker.js:19
msgid "Jan"
msgstr "Jan"
#: agenda/static/javascript/agenda-config-datepicker.js:19
msgid "Feb"
msgstr "Feb"
#: agenda/static/javascript/agenda-config-datepicker.js:19
msgid "Mar"
msgstr "Mär"
#: agenda/static/javascript/agenda-config-datepicker.js:20
msgid "Apr"
msgstr "Apr"
#: agenda/static/javascript/agenda-config-datepicker.js:20
msgid "Jun"
msgstr "Jun"
#: agenda/static/javascript/agenda-config-datepicker.js:21
msgid "Jul"
msgstr "Jul"
#: agenda/static/javascript/agenda-config-datepicker.js:21
msgid "Aug"
msgstr "Aug"
#: agenda/static/javascript/agenda-config-datepicker.js:21
msgid "Sep"
msgstr "Sep"
#: agenda/static/javascript/agenda-config-datepicker.js:22
msgid "Oct"
msgstr "Okt"
#: agenda/static/javascript/agenda-config-datepicker.js:22
msgid "Nov"
msgstr "Nov"
#: agenda/static/javascript/agenda-config-datepicker.js:22
msgid "Dec"
msgstr "Dez"
#: agenda/static/javascript/agenda-config-datepicker.js:25
msgid "Sunday"
msgstr "Sonntag"
#: agenda/static/javascript/agenda-config-datepicker.js:25
msgid "Monday"
msgstr "Montag"
#: agenda/static/javascript/agenda-config-datepicker.js:25
msgid "Tuesdey"
msgstr "Dienstag"
#: agenda/static/javascript/agenda-config-datepicker.js:25
msgid "Wednesday"
msgstr "Mittwoch"
#: agenda/static/javascript/agenda-config-datepicker.js:26
msgid "Thursday"
msgstr "Donnerstag"
#: agenda/static/javascript/agenda-config-datepicker.js:26
msgid "Friday"
msgstr "Freitag"
#: agenda/static/javascript/agenda-config-datepicker.js:26
msgid "Saturday"
msgstr "Samstag"
#: agenda/static/javascript/agenda-config-datepicker.js:29
#: agenda/static/javascript/agenda-config-datepicker.js:33
msgid "Su"
msgstr "So"
#: agenda/static/javascript/agenda-config-datepicker.js:29
#: agenda/static/javascript/agenda-config-datepicker.js:33
msgid "Mo"
msgstr "Mo"
#: agenda/static/javascript/agenda-config-datepicker.js:29
#: agenda/static/javascript/agenda-config-datepicker.js:33
msgid "Tu"
msgstr "Di"
#: agenda/static/javascript/agenda-config-datepicker.js:29
#: agenda/static/javascript/agenda-config-datepicker.js:33
msgid "We"
msgstr "Mi"
#: agenda/static/javascript/agenda-config-datepicker.js:30
#: agenda/static/javascript/agenda-config-datepicker.js:34
msgid "Th"
msgstr "Do"
#: agenda/static/javascript/agenda-config-datepicker.js:30
#: agenda/static/javascript/agenda-config-datepicker.js:34
msgid "Fr"
msgstr "Fr"
#: agenda/static/javascript/agenda-config-datepicker.js:30
#: agenda/static/javascript/agenda-config-datepicker.js:34
msgid "Sa"
msgstr "Sa"
#: agenda/static/javascript/agenda-config-datepicker.js:45
msgid "Time"
msgstr "Zeit"
#: agenda/static/javascript/agenda-config-datepicker.js:46
msgid "Hour"
msgstr "Stunde"
#: agenda/static/javascript/agenda-config-datepicker.js:47
msgid "Minute"
msgstr "Minute"
#: agenda/static/javascript/agenda-config-datepicker.js:48
msgid "Current time"
msgstr "Aktuelle Zeit"
#: agenda/static/javascript/agenda-config-datepicker.js:49
msgid "Close"
msgstr "Schließen"
#: agenda/static/javascript/agenda.js:27 #: agenda/static/javascript/agenda.js:27
#, c-format #, c-format
msgid ", of which %s are hidden." msgid ", of which %s are hidden."

View File

@ -13,7 +13,7 @@
import mimetypes import mimetypes
from django.db import models from django.db import models
from django.utils.translation import ugettext_noop from django.utils.translation import ugettext_lazy, ugettext_noop
from openslides.utils.person.models import PersonField from openslides.utils.person.models import PersonField
@ -23,16 +23,16 @@ class Mediafile(models.Model):
Class for uploaded files which can be delivered under a certain url. Class for uploaded files which can be delivered under a certain url.
""" """
mediafile = models.FileField(upload_to='file') mediafile = models.FileField(upload_to='file', verbose_name=ugettext_lazy("File"))
""" """
See https://docs.djangoproject.com/en/dev/ref/models/fields/#filefield See https://docs.djangoproject.com/en/dev/ref/models/fields/#filefield
for more information. for more information.
""" """
title = models.CharField(max_length=255, unique=True) title = models.CharField(max_length=255, unique=True, verbose_name=ugettext_lazy("Title"))
"""A string representing the title of the file.""" """A string representing the title of the file."""
uploader = PersonField(blank=True) uploader = PersonField(blank=True, verbose_name=ugettext_lazy("Uploaded by"))
"""A person the uploader of a file.""" """A person the uploader of a file."""
timestamp = models.DateTimeField(auto_now_add=True) timestamp = models.DateTimeField(auto_now_add=True)

View File

@ -8,5 +8,9 @@
/** Navigation icons (mapping to glyphicons-halflings) **/ /** Navigation icons (mapping to glyphicons-halflings) **/
.icon-mediafile { .icon-mediafile {
background-position: -96px -24px; background-image: url("../img/glyphicons_062_paperclip.png");
background-position: 0;
}
.leftmenu ul li.active a span.ico i.icon-mediafile {
background-image: url("../img/glyphicons_062_paperclip_white.png");
} }

View File

@ -19,7 +19,7 @@
<th>{% trans 'Type' %}</th> <th>{% trans 'Type' %}</th>
<th>{% trans 'Size' %}</th> <th>{% trans 'Size' %}</th>
<th>{% trans 'Upload time' %}</th> <th>{% trans 'Upload time' %}</th>
<th>{% trans 'Uploader' %}</th> <th>{% trans 'Uploaded by' %}</th>
{% if perms.mediafile.can_manage %} {% if perms.mediafile.can_manage %}
<th class="mini_width">{% trans "Actions" %}</th> <th class="mini_width">{% trans "Actions" %}</th>
{% endif %} {% endif %}

View File

@ -11,7 +11,7 @@
""" """
from django import forms from django import forms
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _, ugettext_lazy
from openslides.utils.forms import CssClassMixin from openslides.utils.forms import CssClassMixin
from openslides.utils.forms import CleanHtmlFormMixin from openslides.utils.forms import CleanHtmlFormMixin
@ -30,18 +30,18 @@ class BaseMotionForm(CleanHtmlFormMixin, CssClassMixin, forms.ModelForm):
""" """
clean_html_fields = ('text', 'reason') clean_html_fields = ('text', 'reason')
title = forms.CharField(widget=forms.TextInput(), label=_("Title")) title = forms.CharField(widget=forms.TextInput(), label=ugettext_lazy("Title"))
""" """
Title of the motion. Will be saved in a MotionVersion object. Title of the motion. Will be saved in a MotionVersion object.
""" """
text = forms.CharField(widget=forms.Textarea(), label=_("Text")) text = forms.CharField(widget=forms.Textarea(), label=ugettext_lazy("Text"))
""" """
Text of the motion. Will be saved in a MotionVersion object. Text of the motion. Will be saved in a MotionVersion object.
""" """
reason = forms.CharField( reason = forms.CharField(
widget=forms.Textarea(), required=False, label=_("Reason")) widget=forms.Textarea(), required=False, label=ugettext_lazy("Reason"))
""" """
Reason of the motion. will be saved in a MotionVersion object. Reason of the motion. will be saved in a MotionVersion object.
""" """
@ -64,7 +64,7 @@ class BaseMotionForm(CleanHtmlFormMixin, CssClassMixin, forms.ModelForm):
class MotionSubmitterMixin(forms.ModelForm): class MotionSubmitterMixin(forms.ModelForm):
"""Mixin to append the submitter field to a MotionForm.""" """Mixin to append the submitter field to a MotionForm."""
submitter = MultiplePersonFormField(label=_("Submitter")) submitter = MultiplePersonFormField(label=ugettext_lazy("Submitter"))
"""Submitter of the motion. Can be one or more persons.""" """Submitter of the motion. Can be one or more persons."""
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -78,7 +78,7 @@ class MotionSubmitterMixin(forms.ModelForm):
class MotionSupporterMixin(forms.ModelForm): class MotionSupporterMixin(forms.ModelForm):
"""Mixin to append the supporter field to a Motionform.""" """Mixin to append the supporter field to a Motionform."""
supporter = MultiplePersonFormField(required=False, label=_("Supporters")) supporter = MultiplePersonFormField(required=False, label=ugettext_lazy("Supporters"))
"""Supporter of the motion. Can be one or more persons.""" """Supporter of the motion. Can be one or more persons."""
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -93,8 +93,8 @@ class MotionDisableVersioningMixin(forms.ModelForm):
"""Mixin to add the option to the form to choose to disable versioning.""" """Mixin to add the option to the form to choose to disable versioning."""
disable_versioning = forms.BooleanField( disable_versioning = forms.BooleanField(
required=False, label=_("Don't create a new version"), required=False, label=ugettext_lazy("Don't create a new version"),
help_text=_("Don't create a new version. Useful e. g. for trivial changes.")) help_text=ugettext_lazy("Don't create a new version. Useful e.g. for trivial changes."))
"""BooleanField to decide, if a new version will be created, or the """BooleanField to decide, if a new version will be created, or the
last_version will be used.""" last_version will be used."""
@ -102,10 +102,10 @@ class MotionDisableVersioningMixin(forms.ModelForm):
class MotionCategoryMixin(forms.ModelForm): class MotionCategoryMixin(forms.ModelForm):
"""Mixin to let the user choose the category for the motion.""" """Mixin to let the user choose the category for the motion."""
category = forms.ModelChoiceField(queryset=Category.objects.all(), required=False) category = forms.ModelChoiceField(queryset=Category.objects.all(), required=False, label=ugettext_lazy("Category"))
class MotionIdentifierMixin(forms.ModelForm): class MotionIdentifierMixin(forms.ModelForm):
"""Mixin to let the user choose the identifier for the motion.""" """Mixin to let the user choose the identifier for the motion."""
identifier = forms.CharField(required=False) identifier = forms.CharField(required=False, label=ugettext_lazy("Identifier"))

View File

@ -21,7 +21,7 @@ from django.db.models import Max
from django.dispatch import receiver from django.dispatch import receiver
from django.utils import formats from django.utils import formats
from django.utils.translation import pgettext from django.utils.translation import pgettext
from django.utils.translation import ugettext_lazy, ugettext_noop, ugettext as _ from django.utils.translation import ugettext as _, ugettext_lazy, ugettext_noop
from openslides.utils.person import PersonField from openslides.utils.person import PersonField
from openslides.config.api import config from openslides.config.api import config
@ -565,7 +565,7 @@ class MotionVersion(models.Model):
title = models.CharField(max_length=255, verbose_name=ugettext_lazy("Title")) title = models.CharField(max_length=255, verbose_name=ugettext_lazy("Title"))
"""The title of a motion.""" """The title of a motion."""
text = models.TextField(verbose_name=_("Text")) text = models.TextField(verbose_name=ugettext_lazy("Text"))
"""The text of a motion.""" """The text of a motion."""
reason = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Reason")) reason = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Reason"))
@ -585,7 +585,7 @@ class MotionVersion(models.Model):
def __unicode__(self): def __unicode__(self):
"""Return a string, representing this object.""" """Return a string, representing this object."""
counter = self.version_number or _('new') counter = self.version_number or ugettext_lazy('new')
return "%s Version %s" % (self.motion, counter) # TODO: Should this really be self.motion or the title of the specific version? return "%s Version %s" % (self.motion, counter) # TODO: Should this really be self.motion or the title of the specific version?
def get_absolute_url(self, link='detail'): def get_absolute_url(self, link='detail'):

View File

@ -167,7 +167,7 @@ def motion_to_pdf(pdf, motion):
# motion reason # motion reason
if motion.reason: if motion.reason:
pdf.append(Paragraph(_("Reason:"), stylesheet['Heading3'])) pdf.append(Paragraph(_("Reason")+":", stylesheet['Heading3']))
convert_html_to_reportlab(pdf, motion.reason) convert_html_to_reportlab(pdf, motion.reason)
return pdf return pdf

View File

@ -30,36 +30,36 @@ def setup_motion_config_page(sender, **kwargs):
name='motion_stop_submitting', name='motion_stop_submitting',
default_value=False, default_value=False,
form_field=forms.BooleanField( form_field=forms.BooleanField(
label=_('Stop submitting new motions by non-staff users'), label=ugettext_lazy('Stop submitting new motions by non-staff users'),
required=False)) required=False))
motion_min_supporters = ConfigVariable( motion_min_supporters = ConfigVariable(
name='motion_min_supporters', name='motion_min_supporters',
default_value=0, default_value=0,
form_field=forms.IntegerField( form_field=forms.IntegerField(
widget=forms.TextInput(attrs={'class': 'small-input'}), widget=forms.TextInput(attrs={'class': 'small-input'}),
label=_('Number of (minimum) required supporters for a motion'), label=ugettext_lazy('Number of (minimum) required supporters for a motion'),
initial=4, initial=4,
min_value=0, min_value=0,
max_value=8, max_value=8,
help_text=_('Choose 0 to disable the supporting system'))) help_text=ugettext_lazy('Choose 0 to disable the supporting system')))
motion_preamble = ConfigVariable( motion_preamble = ConfigVariable(
name='motion_preamble', name='motion_preamble',
default_value=_('The assembly may decide,'), default_value=_('The assembly may decide,'),
form_field=forms.CharField( form_field=forms.CharField(
widget=forms.TextInput(), widget=forms.TextInput(),
required=False, required=False,
label=_('Motion preamble'))) label=ugettext_lazy('Motion preamble')))
motion_pdf_ballot_papers_selection = ConfigVariable( motion_pdf_ballot_papers_selection = ConfigVariable(
name='motion_pdf_ballot_papers_selection', name='motion_pdf_ballot_papers_selection',
default_value='CUSTOM_NUMBER', default_value='CUSTOM_NUMBER',
form_field=forms.ChoiceField( form_field=forms.ChoiceField(
widget=forms.Select(), widget=forms.Select(),
required=False, required=False,
label=_('Number of ballot papers (selection)'), label=ugettext_lazy('Number of ballot papers (selection)'),
choices=[ choices=[
('NUMBER_OF_DELEGATES', _('Number of all delegates')), ('NUMBER_OF_DELEGATES', ugettext_lazy('Number of all delegates')),
('NUMBER_OF_ALL_PARTICIPANTS', _('Number of all participants')), ('NUMBER_OF_ALL_PARTICIPANTS', ugettext_lazy('Number of all participants')),
('CUSTOM_NUMBER', _("Use the following custom number"))])) ('CUSTOM_NUMBER', ugettext_lazy("Use the following custom number"))]))
motion_pdf_ballot_papers_number = ConfigVariable( motion_pdf_ballot_papers_number = ConfigVariable(
name='motion_pdf_ballot_papers_number', name='motion_pdf_ballot_papers_number',
default_value=8, default_value=8,
@ -67,46 +67,46 @@ def setup_motion_config_page(sender, **kwargs):
widget=forms.TextInput(attrs={'class': 'small-input'}), widget=forms.TextInput(attrs={'class': 'small-input'}),
required=False, required=False,
min_value=1, min_value=1,
label=_('Custom number of ballot papers'))) label=ugettext_lazy('Custom number of ballot papers')))
motion_pdf_title = ConfigVariable( motion_pdf_title = ConfigVariable(
name='motion_pdf_title', name='motion_pdf_title',
default_value=_('Motions'), default_value=_('Motions'),
form_field=forms.CharField( form_field=forms.CharField(
widget=forms.TextInput(), widget=forms.TextInput(),
required=False, required=False,
label=_('Title for PDF document (all motions)'))) label=ugettext_lazy('Title for PDF document (all motions)')))
motion_pdf_preamble = ConfigVariable( motion_pdf_preamble = ConfigVariable(
name='motion_pdf_preamble', name='motion_pdf_preamble',
default_value='', default_value='',
form_field=forms.CharField( form_field=forms.CharField(
widget=forms.Textarea(), widget=forms.Textarea(),
required=False, required=False,
label=_('Preamble text for PDF document (all motions)'))) label=ugettext_lazy('Preamble text for PDF document (all motions)')))
motion_allow_disable_versioning = ConfigVariable( motion_allow_disable_versioning = ConfigVariable(
name='motion_allow_disable_versioning', name='motion_allow_disable_versioning',
default_value=False, default_value=False,
form_field=forms.BooleanField( form_field=forms.BooleanField(
label=_('Allow to disable versioning'), label=ugettext_lazy('Allow to disable versioning'),
required=False)) required=False))
motion_workflow = ConfigVariable( motion_workflow = ConfigVariable(
name='motion_workflow', name='motion_workflow',
default_value=1, default_value=1,
form_field=forms.ChoiceField( form_field=forms.ChoiceField(
widget=forms.Select(), widget=forms.Select(),
label=_('Workflow of new motions'), label=ugettext_lazy('Workflow of new motions'),
required=True, required=True,
choices=[(workflow.pk, workflow.name) for workflow in Workflow.objects.all()])) choices=[(workflow.pk, ugettext_lazy(workflow.name)) for workflow in Workflow.objects.all()]))
motion_identifier = ConfigVariable( motion_identifier = ConfigVariable(
name='motion_identifier', name='motion_identifier',
default_value='manually', default_value='manually',
form_field=forms.ChoiceField( form_field=forms.ChoiceField(
widget=forms.Select(), widget=forms.Select(),
required=False, required=False,
label=_('Identifier'), label=ugettext_lazy('Identifier'),
choices=[ choices=[
('manually', _('Set it manually')), ('manually', ugettext_lazy('Set it manually')),
('per_category', _('Numbered per category')), ('per_category', ugettext_lazy('Numbered per category')),
('serially_numbered', _('Serially numbered'))])) ('serially_numbered', ugettext_lazy('Serially numbered'))]))
return ConfigPage(title=ugettext_noop('Motion'), return ConfigPage(title=ugettext_noop('Motion'),
url='motion', url='motion',

View File

@ -10,7 +10,7 @@
{% trans "Categories" %} {% trans "Categories" %}
<small class="pull-right"> <small class="pull-right">
{% if perms.motion.can_manage_motion %} {% if perms.motion.can_manage_motion %}
<a href="{% url 'motion_category_create' %}" class="btn btn-mini btn-primary" rel="tooltip" data-original-title="{% trans 'New motion' %}"><i class="icon-plus icon-white"></i> {% trans 'New' %}</a> <a href="{% url 'motion_category_create' %}" class="btn btn-mini btn-primary" rel="tooltip" data-original-title="{% trans 'New category' %}"><i class="icon-plus icon-white"></i> {% trans 'New' %}</a>
{% endif %} {% endif %}
<a href="{% url 'motion_list' %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to overview" %}</a> <a href="{% url 'motion_list' %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to overview" %}</a>
</small> </small>

View File

@ -126,11 +126,11 @@
<input type="radio" value="{{ version.version_number }}" name="rev2"> <input type="radio" value="{{ version.version_number }}" name="rev2">
</td> </td>
<td> <td>
<a href="{% model_url version %}" title="{% trans 'Show version number' %} {{ version.version_number }}" class="btn btn-mini"> <a href="{% model_url version %}" title="{% trans 'Show' %}" class="btn btn-mini">
<i class="icon-search"></i> <i class="icon-search"></i>
</a> </a>
{# TODO: add delete version function #} {# TODO: add delete version function #}
<a href="{% model_url version 'delete' %}" title="{% trans 'Delete version number' %} {{ version.version_number }}" class="btn btn-mini"> <a href="{% model_url version 'delete' %}" title="{% trans 'Delete' %}" class="btn btn-mini">
<i class="icon-remove"></i> <i class="icon-remove"></i>
</a> </a>
</td> </td>

View File

@ -34,11 +34,11 @@
<table class="table table-striped table-bordered"> <table class="table table-striped table-bordered">
<tr> <tr>
<td><b>{% trans "Version" %} {{ version_rev1.version_number }}</b><br> <td><b>{% trans "Version" %} {{ version_rev1.version_number }}</b><br>
{% trans "created: " %} {{ version_rev1.creation_time }}<br> {% trans "created" %}: {{ version_rev1.creation_time }}<br>
<h4>{{ version_rev1.title }}</h4> <h4>{{ version_rev1.title }}</h4>
</td> </td>
<td><b>{% trans "Version" %} {{ version_rev2.version_number }}</b><br> <td><b>{% trans "Version" %} {{ version_rev2.version_number }}</b><br>
{% trans "created: " %} {{ version_rev1.creation_time }}<br> {% trans "created" %}: {{ version_rev1.creation_time }}<br>
<h4>{{ version_rev2.title }}</h4> <h4>{{ version_rev2.title }}</h4>
</td> </td>
</tr> </tr>

View File

@ -31,7 +31,11 @@
{% trans "New motion" %} {% trans "New motion" %}
{% endif %} {% endif %}
<small class="pull-right"> <small class="pull-right">
<a href="{% url 'motion_list' %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to overview" %}</a> {% if motion %}
<a href="{% model_url motion 'view' %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to motion" %}</a>
{% else %}
<a href="{% url 'motion_list' %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to overview" %}</a>
{% endif %}
</small> </small>
</h1> </h1>
<form action="" method="post">{% csrf_token %} <form action="" method="post">{% csrf_token %}

View File

@ -15,7 +15,7 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if perms.motion.can_manage_motion %} {% if perms.motion.can_manage_motion %}
<a href="{% url 'motion_category_list' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'New motion' %}"><i class="icon-th-large"></i> {% trans 'Category' %}</a> <a href="{% url 'motion_category_list' %}" class="btn btn-mini"><i class="icon-th-large"></i> {% trans 'Categories' %}</a>
{# <a href="{% url 'motion_import' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Import motions' %}"><i class="icon-import"></i> {% trans 'Import' %}</a>#} {# <a href="{% url 'motion_import' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Import motions' %}"><i class="icon-import"></i> {% trans 'Import' %}</a>#}
{% endif %} {% endif %}
<a href="{% url 'motion_list_pdf' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Print all motions as PDF' %}"><i class="icon-print"></i> PDF</a> <a href="{% url 'motion_list_pdf' %}" class="btn btn-mini" rel="tooltip" data-original-title="{% trans 'Print all motions as PDF' %}"><i class="icon-print"></i> PDF</a>

View File

@ -291,7 +291,7 @@ class VersionDiffView(DetailView):
diff_text = htmldiff(version_rev1.text, version_rev2.text) diff_text = htmldiff(version_rev1.text, version_rev2.text)
diff_reason = htmldiff(version_rev1.reason, version_rev2.reason) diff_reason = htmldiff(version_rev1.reason, version_rev2.reason)
except (KeyError, ValueError, MotionVersion.DoesNotExist): except (KeyError, ValueError, MotionVersion.DoesNotExist):
messages.error(self.request, _('At least one version number was not valid.')) messages.error(self.request, _('At least one version number is not valid.'))
version_rev1 = None version_rev1 = None
version_rev2 = None version_rev2 = None
diff_text = None diff_text = None
@ -556,7 +556,7 @@ class MotionSetStateView(SingleObjectMixin, RedirectView):
else: else:
self.object.save() self.object.save()
# TODO: the state is not translated # TODO: the state is not translated
self.object.write_log(ugettext_noop('Changed state to %s') % self.object.write_log(ugettext_noop('State changed to %s') %
self.object.state.name, self.request.user) self.object.state.name, self.request.user)
messages.success(request, _('Motion status was set to: %s.' messages.success(request, _('Motion status was set to: %s.'
% html_strong(self.object.state))) % html_strong(self.object.state)))
@ -583,7 +583,7 @@ class CreateAgendaItemView(SingleObjectMixin, RedirectView):
def pre_redirect(self, request, *args, **kwargs): def pre_redirect(self, request, *args, **kwargs):
"""Create the agenda item.""" """Create the agenda item."""
self.item = Item.objects.create(related_sid=self.object.sid) self.item = Item.objects.create(related_sid=self.object.sid)
self.object.write_log(ugettext_noop('Created Agenda Item'), self.request.user) self.object.write_log(ugettext_noop('Agenda item created'), self.request.user)
create_agenda_item = CreateAgendaItemView.as_view() create_agenda_item = CreateAgendaItemView.as_view()
@ -595,7 +595,7 @@ class MotionPDFView(SingleObjectMixin, PDFView):
If self.print_all_motions is False, the view returns a PDF with only one If self.print_all_motions is False, the view returns a PDF with only one
motion.""" motion."""
permission_required = 'motion.can_manage_motion' permission_required = 'motion.can_see_motion'
model = Motion model = Motion
top_space = 0 top_space = 0
print_all_motions = False print_all_motions = False

View File

@ -97,7 +97,7 @@ def import_users(csv_file):
error_messages.append(_('Ignoring malformed group id in line %d.') % (line_no + 1)) error_messages.append(_('Ignoring malformed group id in line %d.') % (line_no + 1))
continue continue
except Group.DoesNotExist: except Group.DoesNotExist:
error_messages.append(_('Group id %s does not exists (line %d).') % (groupid, line_no + 1)) error_messages.append(_('Group id %(id)s does not exists (line %(line)d).') % {'id': groupid, 'line': line_no + 1})
continue continue
user.reset_password() user.reset_password()
count_success += 1 count_success += 1

View File

@ -117,11 +117,11 @@ class GroupForm(forms.ModelForm, CssClassMixin):
# Editing the anonymous-user # Editing the anonymous-user
if self.instance.name.lower() != data.lower(): if self.instance.name.lower() != data.lower():
raise forms.ValidationError( raise forms.ValidationError(
ugettext_lazy('You can not edit the name for this group.')) _('You can not edit the name for this group.'))
else: else:
if data.lower() in ['anonymous', 'registered']: if data.lower() in ['anonymous', 'registered']:
raise forms.ValidationError( raise forms.ValidationError(
ugettext_lazy('Group name "%s" is reserved for internal use.') % data) _('Group name "%s" is reserved for internal use.') % data)
return data return data
class Meta: class Meta:

View File

@ -14,7 +14,7 @@ from django.contrib.auth.models import User as DjangoUser, Group as DjangoGroup
from django.db import models from django.db import models
from django.db.models import signals from django.db.models import signals
from django.dispatch import receiver from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _, ugettext_noop # TODO: Change this in the code from django.utils.translation import ugettext_lazy, ugettext_noop
from openslides.utils.person import PersonMixin, Person from openslides.utils.person import PersonMixin, Person
from openslides.utils.person.signals import receive_persons from openslides.utils.person.signals import receive_persons
@ -27,32 +27,32 @@ class User(PersonMixin, Person, SlideMixin, DjangoUser):
prefix = 'user' # This is for the slides prefix = 'user' # This is for the slides
person_prefix = 'user' person_prefix = 'user'
GENDER_CHOICES = ( GENDER_CHOICES = (
('male', _('Male')), ('male', ugettext_lazy('Male')),
('female', _('Female')), ('female', ugettext_lazy('Female')),
) )
django_user = models.OneToOneField(DjangoUser, editable=False, parent_link=True) django_user = models.OneToOneField(DjangoUser, editable=False, parent_link=True)
structure_level = models.CharField( structure_level = models.CharField(
max_length=255, blank=True, default='', verbose_name=_("Structure level"), max_length=255, blank=True, default='', verbose_name=ugettext_lazy("Structure level"),
help_text=_('Will be shown after the name.')) help_text=ugettext_lazy('Will be shown after the name.'))
title = models.CharField( title = models.CharField(
max_length=50, blank=True, default='', verbose_name=_("Titel"), max_length=50, blank=True, default='', verbose_name=ugettext_lazy("Title"),
help_text=_('Will be shown before the name.')) help_text=ugettext_lazy('Will be shown before the name.'))
gender = models.CharField( gender = models.CharField(
max_length=50, choices=GENDER_CHOICES, blank=True, max_length=50, choices=GENDER_CHOICES, blank=True,
verbose_name=_("Gender"), help_text=_('Only for filtering the participant list.')) verbose_name=ugettext_lazy("Gender"), help_text=ugettext_lazy('Only for filtering the participant list.'))
committee = models.CharField( committee = models.CharField(
max_length=255, blank=True, default='', verbose_name=_("Committee"), max_length=255, blank=True, default='', verbose_name=ugettext_lazy("Committee"),
help_text=_('Only for filtering the participant list.')) help_text=ugettext_lazy('Only for filtering the participant list.'))
about_me = models.TextField( about_me = models.TextField(
blank=True, default='', verbose_name=_('About me'), blank=True, default='', verbose_name=ugettext_lazy('About me'),
help_text=_('Your profile text')) help_text=ugettext_lazy('Your profile text'))
comment = models.TextField( comment = models.TextField(
blank=True, default='', verbose_name=_('Comment'), blank=True, default='', verbose_name=ugettext_lazy('Comment'),
help_text=_('Only for notes.')) help_text=ugettext_lazy('Only for notes.'))
default_password = models.CharField( default_password = models.CharField(
max_length=100, blank=True, default='', max_length=100, blank=True, default='',
verbose_name=_("Default password")) verbose_name=ugettext_lazy("Default password"))
@property @property
def clean_name(self): def clean_name(self):
@ -134,9 +134,9 @@ class Group(PersonMixin, Person, SlideMixin, DjangoGroup):
django_group = models.OneToOneField(DjangoGroup, editable=False, parent_link=True) django_group = models.OneToOneField(DjangoGroup, editable=False, parent_link=True)
group_as_person = models.BooleanField( group_as_person = models.BooleanField(
default=False, verbose_name=_("Use this group as participant"), default=False, verbose_name=ugettext_lazy("Use this group as participant"),
help_text=_('For example as submitter of a motion.')) help_text=ugettext_lazy('For example as submitter of a motion.'))
description = models.TextField(blank=True, verbose_name=_("Description")) description = models.TextField(blank=True, verbose_name=ugettext_lazy("Description"))
@models.permalink @models.permalink
def get_absolute_url(self, link='view'): def get_absolute_url(self, link='view'):

View File

@ -12,7 +12,7 @@
from django.dispatch import receiver from django.dispatch import receiver
from django import forms from django import forms
from django.utils.translation import ugettext_noop, ugettext_lazy, ugettext as _ from django.utils.translation import ugettext as _, ugettext_lazy, ugettext_noop
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
@ -35,23 +35,23 @@ def setup_participant_config_page(sender, **kwargs):
form_field=forms.CharField( form_field=forms.CharField(
widget=forms.TextInput(), widget=forms.TextInput(),
required=False, required=False,
label=_('System URL'), label=ugettext_lazy('System URL'),
help_text=_('Printed in PDF of first time passwords only.'))) help_text=ugettext_lazy('Printed in PDF of first time passwords only.')))
participant_pdf_welcometext = ConfigVariable( participant_pdf_welcometext = ConfigVariable(
name='participant_pdf_welcometext', name='participant_pdf_welcometext',
default_value=_('Welcome to OpenSlides!'), default_value=_('Welcome to OpenSlides!'),
form_field=forms.CharField( form_field=forms.CharField(
widget=forms.Textarea(), widget=forms.Textarea(),
required=False, required=False,
label=_('Welcome text'), label=ugettext_lazy('Welcome text'),
help_text=_('Printed in PDF of first time passwords only.'))) help_text=ugettext_lazy('Printed in PDF of first time passwords only.')))
participant_sort_users_by_first_name = ConfigVariable( participant_sort_users_by_first_name = ConfigVariable(
name='participant_sort_users_by_first_name', name='participant_sort_users_by_first_name',
default_value=False, default_value=False,
form_field=forms.BooleanField( form_field=forms.BooleanField(
required=False, required=False,
label=_('Sort participants by first name'), label=ugettext_lazy('Sort participants by first name'),
help_text=_('Disable for sorting by last name'))) help_text=ugettext_lazy('Disable for sorting by last name')))
return ConfigPage(title=ugettext_noop('Participant'), return ConfigPage(title=ugettext_noop('Participant'),
url='participant', url='participant',

View File

@ -3,11 +3,11 @@
{% load i18n %} {% load i18n %}
{% load tags %} {% load tags %}
{% block title %}{{ block.super }} {{ group }}{% endblock %} {% block title %}{{ block.super }} {% trans group.name %}{% endblock %}
{% block content %} {% block content %}
<h1>{{ group }} <h1>{% trans group.name %}
<small class="pull-right"> <small class="pull-right">
<a href="{% url 'user_group_overview' %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to overview" %}</a> <a href="{% url 'user_group_overview' %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to overview" %}</a>
</small> </small>

View File

@ -21,7 +21,7 @@
{% for group in groups %} {% for group in groups %}
<tr class="{% if group.active %}activeline{% endif %}"> <tr class="{% if group.active %}activeline{% endif %}">
<td> <td>
<a href="{% model_url group 'view' %}">{{ group.name }}</a> <a href="{% model_url group 'view' %}">{% trans group.name %}</a>
</td> </td>
<td> <td>
<span style="width: 1px; white-space: nowrap;"> <span style="width: 1px; white-space: nowrap;">

View File

@ -14,43 +14,44 @@
</h1> </h1>
<div class="user_details">
<fieldset>
<legend>{% trans "Personal data" %}</legend>
<label>{% trans "Gender" %}</label>
{{ shown_user.get_gender_display }}
<label>{% trans "Email" %}</label>
{{ shown_user.email }}
<label>{% trans "About me" %}</label>
{{ shown_user.about_me|linebreaks }}
</fieldset>
<fieldset> <fieldset>
<legend>{% trans "Personal data" %}</legend> <legend>{% trans "Event data" %}</legend>
<label>{% trans "Gender" %}</label> <label>{% trans "Structure level" %}</label>
{{ shown_user.get_gender_display }} {{ shown_user.structure_level }}
<label>{% trans "Email" %}</label> <label>{% trans "Committee" %}</label>
{{ shown_user.email }} {{ shown_user.committee }}
<label>{% trans "About me" %}</label> <label>{% trans "Groups" %}</label>
{{ shown_user.about_me|linebreaks }} {% if shown_user.groups.all %}
</fieldset> {{ shown_user.groups.all|join:", " }}
{% else %}
{% trans "The participant is not member of any group." %}
{% endif %}
</fieldset>
<fieldset> {% if perms.participant.can_manage_participant %}
<legend>{% trans "Event data" %}</legend> <fieldset>
<label>{% trans "Structure level" %}</label> <legend>{% trans "Administrative data" %}</legend>
{{ shown_user.structure_level }} <label>{% trans "Username" %}</label>
<label>{% trans "Committee" %}</label> {{ shown_user.username }}
{{ shown_user.committee }} <label>{% trans "Comment" %}</label>
<label>{% trans "Groups" %}</label> {{ shown_user.comment|linebreaks }}
{% if shown_user.groups.all %} <label>{% trans "Last Login" %}</label>
{{ shown_user.groups.all|join:", " }} {% if shown_user.last_login > shown_user.date_joined %}
{% else %} {{ shown_user.last_login }}
{% trans "The participant is not member of any group." %} {% else %}
{% trans "The participant has not logged in yet." %}
{% endif %}
{% endif %} {% endif %}
</fieldset> </div>
{% if perms.participant.can_manage_participant %}
<fieldset>
<legend>{% trans "Administrative data" %}</legend>
<label>{% trans "User name" %}</label>
{{ shown_user.username }}
<label>{% trans "Comment" %}</label>
{{ shown_user.comment|linebreaks }}
<label>{% trans "Last Login" %}</label>
{% if shown_user.last_login > shown_user.date_joined %}
{{ shown_user.last_login }}
{% else %}
{% trans "The participant has not logged in yet." %}
{% endif %}
{% endif %}
{% endblock %} {% endblock %}

View File

@ -12,7 +12,7 @@
from django.db import models from django.db import models
from django.dispatch import receiver from django.dispatch import receiver
from django.utils.translation import ugettext_lazy as _, ugettext_noop from django.utils.translation import ugettext_lazy, ugettext_noop
from openslides.projector.api import register_slidemodel from openslides.projector.api import register_slidemodel
from openslides.projector.projector import SlideMixin from openslides.projector.projector import SlideMixin
@ -24,9 +24,9 @@ class ProjectorSlide(models.Model, SlideMixin):
""" """
prefix = 'ProjectorSlide' prefix = 'ProjectorSlide'
title = models.CharField(max_length=256, verbose_name=_("Title")) title = models.CharField(max_length=256, verbose_name=ugettext_lazy("Title"))
text = models.TextField(null=True, blank=True, verbose_name=_("Text")) text = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Text"))
weight = models.IntegerField(default=0, verbose_name=_("Weight")) weight = models.IntegerField(default=0, verbose_name=ugettext_lazy("Weight"))
def slide(self): def slide(self):
return { return {

View File

@ -13,7 +13,6 @@ from time import time
from django.dispatch import Signal, receiver from django.dispatch import Signal, receiver
from django import forms from django import forms
from django.utils.translation import ugettext_lazy, ugettext as _
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.core.context_processors import csrf from django.core.context_processors import csrf

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -77,8 +77,8 @@
visibility: hidden; visibility: hidden;
} }
.overlay_list .form-inline { .overlay_list .overlayblock {
margin: 5px 0 0 31px; margin: 0 0 0 31px;
} }
#countdown_time { #countdown_time {

View File

@ -58,7 +58,7 @@ body{
top:110px; top:110px;
right:40px; right:40px;
padding-left:30px; padding-left:30px;
background: url(../img/glyphicons_054_clock.png) no-repeat scroll 0px 4px; background: url(../img/glyphicons_054_clock_big.png) no-repeat scroll 0px 4px;
} }
#currentTime.ajax_error { #currentTime.ajax_error {
@ -73,6 +73,19 @@ body{
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
#overlay_list_of_speaker_box {
position: fixed;
bottom: 0;
right: 0;
border-radius: 0.4em;
border: 0.1em solid #777777;
background-color: #cccccc;
opacity: 0.9;
padding: 0 1em;
margin: 1em;
z-index: 2;
width: 50%;
}
/*** CONTENT ***/ /*** CONTENT ***/
#contentwrapper { #contentwrapper {
@ -146,6 +159,14 @@ body{
color: #9FA9B7; color: #9FA9B7;
list-style-type: none; list-style-type: none;
} }
.list_of_speakers li {
font-size: 130%;
line-height: 160%;
}
.last_speakers li {
color: #9FA9B7;
list-style: none;
}
/* Table */ /* Table */
table { table {

View File

@ -7,7 +7,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head> <head>
<link type="text/css" rel="stylesheet" href="{% static 'styles/projector.css' %}"> <link type="text/css" rel="stylesheet" href="{% static 'styles/projector.css' %}">
<link rel="shortcut icon" href="{% static 'images/favicon.png' %}" type="image/png" /> <link rel="shortcut icon" href="{% static 'img/favicon.png' %}" type="image/png" />
<script type="text/javascript" src="{% static 'javascript/jquery.min.js' %}"></script> <script type="text/javascript" src="{% static 'javascript/jquery.min.js' %}"></script>
<script type="text/javascript" src="{% static 'javascript/projector.js' %}"></script> <script type="text/javascript" src="{% static 'javascript/projector.js' %}"></script>
<title>{% block title %} {% get_config 'event_name' %} {% endblock %}</title> <title>{% block title %} {% get_config 'event_name' %} {% endblock %}</title>

View File

@ -3,14 +3,14 @@
<span> <span>
{% trans "Countdown for speaking time" %}: {% trans "Countdown for speaking time" %}:
<div> <div class="overlayblock">
<div class="input-append"> <div class="input-append" style="margin-bottom:0;">
<input class="projector_countdown_spinval" id="countdown_time" name="countdown_time" type="number" min="0" value="{{ countdown_time }}"> <input class="projector_countdown_spinval" id="countdown_time" name="countdown_time" type="number" min="0" value="{{ countdown_time }}">
<span class="add-on">{% trans "s" context "seconds" %}</span> <span class="add-on">{% trans "s" context "seconds" %}</span>
<button id="countdown_set" class="countdown_control btn" href="{% url 'countdown_set_default' %}" title="{% trans 'Save time as default' %}" style="width: 16px;">
<i class="icon-refresh"></i>
</button>
</div> </div>
<a id="countdown_set" class="countdown_control btn btn-mini" href="{% url 'countdown_set_default' %}" title="{% trans 'Save time as default' %}">
<i class="icon-refresh"></i>
</a>
<a id="countdown_reset" class="countdown_control btn" href="{% url 'countdown_reset' %}" title="{% trans 'Reset countdown' %}"> <a id="countdown_reset" class="countdown_control btn" href="{% url 'countdown_reset' %}" title="{% trans 'Reset countdown' %}">
<i class="icon-fast-backward"></i> <i class="icon-fast-backward"></i>
</a> </a>

View File

@ -4,7 +4,7 @@
<span> <span>
{% trans "Message" %}: {% trans "Message" %}:
<form class="form-inline" id="overlay_message" action="{% url 'projector_overlay_message' %}" method="post">{% csrf_token %} <form class="form-inline" id="overlay_message" action="{% url 'projector_overlay_message' %}" method="post">{% csrf_token %}
<div class="input-append" style="width: 85%;"> <div class="input-append overlayblock" style="width: 77%;">
<input class="input-block-level" id="overlay_message_text" name='message_text' type='text' value="{% get_config 'projector_message' %}"> <input class="input-block-level" id="overlay_message_text" name='message_text' type='text' value="{% get_config 'projector_message' %}">
<button type="submit" class="btn btn-primary" name="message" title="{% trans 'Apply' %}" style="width: 16px;"> <button type="submit" class="btn btn-primary" name="message" title="{% trans 'Apply' %}" style="width: 16px;">
<i class="icon-ok icon-white"></i> <i class="icon-ok icon-white"></i>

View File

@ -21,7 +21,7 @@ from django.db import transaction
from django.db.models import Q from django.db.models import Q
from django.shortcuts import redirect from django.shortcuts import redirect
from django.template import RequestContext from django.template import RequestContext
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext as _
from openslides.utils.template import render_block_to_string, Tab from openslides.utils.template import render_block_to_string, Tab
from openslides.utils.views import ( from openslides.utils.views import (

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -124,22 +124,14 @@ $(document).ready(function(){
} }
}); });
// Tooltips // Tooltips
$('.leftmenu').tooltip({
selector: "a[rel=tooltip]",
placement: 'right'
});
$(this).tooltip({ $(this).tooltip({
selector: "a[rel=tooltip]", selector: "a[rel=tooltip]",
placement: 'bottom' placement: 'bottom'
}); });
$('h1').tooltip({ $('h1').tooltip({
selector: "a[rel=tooltip]", selector: "a[rel=tooltip]",
placement: 'bottom' placement: 'bottom'
}); });
$('body').tooltip({
selector: '.tooltip'
});
$('.tooltip-left').tooltip({ $('.tooltip-left').tooltip({
placement: 'left' placement: 'left'
}); });

View File

@ -29,8 +29,10 @@ body {
padding-left: 3px; padding-left: 3px;
} }
#header .title { #header .title {
font-size: 20px; font-size: 16px;
color: #999999; color: #999999;
position: absolute;
margin: 8px 0 0 50px;
} }
footer { footer {
margin-bottom: 20px; margin-bottom: 20px;
@ -117,17 +119,17 @@ tr.total td {
.optional { .optional {
display: auto; display: auto;
} }
fieldset { .user_details fieldset {
margin-bottom: 10px; margin-bottom: 10px;
} }
fieldset legend { .user_details legend {
margin-bottom: 5px; margin-bottom: 5px;
} }
fieldset label { .user_details label {
font-weight: bold; font-weight: bold;
margin: 10px 0 0 0; margin: 10px 0 0 0;
} }
fieldset label:after { .user_details label:after {
content: ":"; content: ":";
} }
@ -164,17 +166,27 @@ legend + .control-group {
height: 110px; height: 110px;
width: auto; width: auto;
} }
#dataTableParticipants_filter input {
width: auto;
}
#dataTableParticipants {
clear: none;
}
#dataTableParticipants_wrapper .row-fluid:after {
clear: none;
}
/** Left sitebar navigation **/ /** Left sitebar navigation **/
.leftmenu ul { .leftmenu ul {
margin: 0; margin: 0;
list-style: none; list-style: none;
} }
.leftmenu ul ul { .leftmenu ul ul {
display: none; display: none;
margin-left: 35px; margin-left: 35px;
margin-top: -1px; margin-top: -1px;
box-shadow: 0 1px 2px rgba(0,0,0,0.1); box-shadow: 0 1px 2px rgba(0,0,0,0.1);
} }
.leftmenu ul li { .leftmenu ul li {
display: block; display: block;
@ -188,12 +200,11 @@ legend + .control-group {
display: block; display: block;
font-weight: bold; font-weight: bold;
background-color: #ffffff; background-color: #ffffff;
padding: 0; padding: 0;
} }
.leftmenu ul li:first-child a { .leftmenu ul li:first-child a {
border-top: 1px solid #DDDDDD; border-top: 1px solid #DDDDDD;
} }
.leftmenu ul li a span.ico { .leftmenu ul li a span.ico {
display: inline-block; display: inline-block;
background: #f9f9f9; background: #f9f9f9;
@ -230,7 +241,6 @@ legend + .control-group {
margin-top: 5px; margin-top: 5px;
height: 20px; height: 20px;
} }
.leftmenu.lefticon > ul { .leftmenu.lefticon > ul {
width: 37px !important; width: 37px !important;
} }
@ -254,7 +264,6 @@ legend + .control-group {
background-position: 0 -24px; background-position: 0 -24px;
} }
.icon-agenda { .icon-agenda {
/* background-position: -264px 0;*/
background-position: 0; background-position: 0;
background-image: url("../img/glyphicons_045_calendar.png"); background-image: url("../img/glyphicons_045_calendar.png");
} }
@ -292,6 +301,9 @@ legend + .control-group {
.icon-personal_info { .icon-personal_info {
background-position: -312px -24px; background-position: -312px -24px;
} }
.icon-append_to_list_of_speakers {
background-position: -48px -144px;
}
/** More glyphicons free icons **/ /** More glyphicons free icons **/
.status_link .icon-on, .icon-checked-new { .status_link .icon-on, .icon-checked-new {
@ -347,9 +359,11 @@ legend + .control-group {
} }
.row-fluid .leftmenu { .row-fluid .leftmenu {
float: left; float: left;
width: auto;
} }
#content { #content {
margin: 0 5px 0 45px; margin: 0 5px 0 45px;
width: auto;
} }
/* hide optional column */ /* hide optional column */
.optional { .optional {

View File

@ -10,7 +10,6 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{% get_config 'event_name' %}{% endblock %}</title> <title>{% block title %}{% get_config 'event_name' %}{% endblock %}</title>
<!-- styles --> <!-- styles -->
<link href="{% static 'styles/bootstrap.min.css' %}" type="text/css" rel="stylesheet" /> <link href="{% static 'styles/bootstrap.min.css' %}" type="text/css" rel="stylesheet" />
<link href="{% static 'styles/bootstrap-responsive.min.css' %}" type="text/css" rel="stylesheet" /> <link href="{% static 'styles/bootstrap-responsive.min.css' %}" type="text/css" rel="stylesheet" />
@ -28,7 +27,7 @@
<div class="span12"> <div class="span12">
<div id="header"> <div id="header">
<a href="/" class="logo" title="{% trans 'Home' %}"><img src="{% static 'img/logo.png' %}" /></a> <a href="/" class="logo" title="{% trans 'Home' %}"><img src="{% static 'img/logo.png' %}" /></a>
<!--<a class="title" href="#">{% get_config 'event_name' %}</a>--> <span class="title optional">{% get_config 'event_name' %} - {% get_config 'event_description' %}</span>
{% block loginbutton %} {% block loginbutton %}
<div class="btn-group pull-right"> <div class="btn-group pull-right">
{% if user.is_authenticated %} {% if user.is_authenticated %}
@ -65,7 +64,7 @@
{% for tab in tabs %} {% for tab in tabs %}
{% if tab.permission %} {% if tab.permission %}
<li{% if tab.selected %} class="active"{% endif %}> <li{% if tab.selected %} class="active"{% endif %}>
<a href="{{ tab.url }}"> <a href="{{ tab.url }}" class="tooltip-right">
<span class="ico"><i class="icon-{{ tab.app }}"></i></span> <span class="ico"><i class="icon-{{ tab.app }}"></i></span>
<span class="text">{{ tab.title }}</span> <span class="text">{{ tab.title }}</span>
</a> </a>

View File

@ -2,7 +2,7 @@ import json
from django.db import models from django.db import models
from django.core.serializers.json import DjangoJSONEncoder from django.core.serializers.json import DjangoJSONEncoder
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext as _
from django.forms.fields import Field from django.forms.fields import Field
from django.forms.util import ValidationError as FormValidationError from django.forms.util import ValidationError as FormValidationError

View File

@ -48,6 +48,7 @@ class PersonField(models.fields.Field):
elif isinstance(value, basestring): elif isinstance(value, basestring):
# The object is already a a person_id # The object is already a a person_id
return value return value
elif hasattr(value, 'person_id'): elif hasattr(value, 'person_id'):
# The object is a person # The object is a person
return value.person_id return value.person_id

View File

@ -114,7 +114,7 @@ class TestSpeakerAppendView(SpeakerViewTestCase):
response = self.check_url('/agenda/1/speaker/', self.speaker1_client, 302) response = self.check_url('/agenda/1/speaker/', self.speaker1_client, 302)
self.assertEqual(Speaker.objects.filter(item=self.item1).count(), 0) self.assertEqual(Speaker.objects.filter(item=self.item1).count(), 0)
self.assertMessage(response, 'List of speakers is closed.') self.assertMessage(response, 'The list of speakers is closed.')
class TestAgendaItemView(SpeakerViewTestCase): class TestAgendaItemView(SpeakerViewTestCase):
@ -155,7 +155,7 @@ class TestSpeakerSpeakView(SpeakerViewTestCase):
def test_get(self): def test_get(self):
url = '/agenda/1/speaker/%s/speak/' % self.speaker1.person_id url = '/agenda/1/speaker/%s/speak/' % self.speaker1.person_id
response = self.check_url(url, self.admin_client, 302) response = self.check_url(url, self.admin_client, 302)
self.assertMessage(response, 'Person user:2 is not on the list of item item1.') self.assertMessage(response, 'user:2 is not on the list of item1.')
speaker = Speaker.objects.add(self.speaker1, self.item1) speaker = Speaker.objects.add(self.speaker1, self.item1)
response = self.check_url(url, self.admin_client, 302) response = self.check_url(url, self.admin_client, 302)