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),
'config_motion_min_supporters': config['motion_min_supporters'],
'supported_motions': Motion.objects.filter(supporter=request.user)})
try:
from openslides.assignment.models import Assignment
except ImportError:

View File

@ -14,7 +14,7 @@ from datetime import datetime
from django.db import models
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
@ -38,30 +38,30 @@ class Item(MPTTModel, SlideMixin):
ORGANIZATIONAL_ITEM = 2
ITEM_TYPE = (
(AGENDA_ITEM, _('Agenda item')),
(ORGANIZATIONAL_ITEM, _('Organizational item')))
(AGENDA_ITEM, ugettext_lazy('Agenda 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.
"""
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.
"""
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.
"""
closed = models.BooleanField(default=False, verbose_name=_("Closed"))
closed = models.BooleanField(default=False, verbose_name=ugettext_lazy("Closed"))
"""
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.
"""
@ -73,7 +73,7 @@ class Item(MPTTModel, SlideMixin):
"""
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.
@ -81,7 +81,7 @@ class Item(MPTTModel, SlideMixin):
"""
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.
"""
@ -94,7 +94,7 @@ class Item(MPTTModel, SlideMixin):
"""
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.
"""
@ -125,7 +125,7 @@ class Item(MPTTModel, SlideMixin):
For use in Template
??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):
"""
@ -158,9 +158,12 @@ class Item(MPTTModel, SlideMixin):
}
elif config['presentation_argument'] == 'show_list_of_speakers':
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',
'speakers': speakers}
'speakers': speakers,
'old_speakers': old_speakers[slice_items:]}
elif self.related_sid:
data = self.get_related_slide().slide()
else:
@ -244,7 +247,7 @@ class Item(MPTTModel, SlideMixin):
class SpeakerManager(models.Manager):
def add(self, person, item):
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(
models.Max('weight'))['weight__max'] or 0)
return self.create(item=item, person=person, weight=weight + 1)
@ -279,7 +282,7 @@ class Speaker(models.Model):
class Meta:
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):

View File

@ -12,7 +12,7 @@
from django.dispatch import receiver
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 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'),
required=False,
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_javascript = ['javascript/jquery-ui.custom.min.js',

View File

@ -10,7 +10,7 @@
: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
@ -26,4 +26,4 @@ def agenda_show():
return data
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 %}
<style type="text/css">
#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">
<div id="overlay_list_of_speaker_box">
{% if speakers %}
<header>{% trans "List of speakers:" %}</header>
<h3>{% trans "List of speakers" %}:</h3>
<ol>
{% for speaker in speakers %}
<li>{{ speaker }}</li>

View File

@ -2,5 +2,5 @@
{% load tags %}
<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>

View File

@ -79,12 +79,14 @@
{% if old_speakers %}
<div class="well">
<b>{% trans "Last speakers:" %}</b>
<div class="btn-group" data-toggle="buttons-checkbox">
<button type="button" class="btn btn-mini" data-toggle="collapse" data-target="#all_speakers">
{% trans "Show all speakers" %}
</button>
</div>
<b>{% trans "Last speakers" %}:</b>
{% if old_speakers|length > 1 %}
<div class="btn-group" data-toggle="buttons-checkbox">
<button type="button" class="btn btn-mini" data-toggle="collapse" data-target="#all_speakers">
{% trans "Show all speakers" %}
</button>
</div>
{% endif %}
<br>
<div id="all_speakers" class="collapse out">
{% for speaker in old_speakers %}
@ -139,7 +141,7 @@
<span>{{ forloop.counter }}.</span>
<a href="{% model_url speaker %}">{{ speaker }}</a>
{% 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">
<i class="icon-remove"></i>
</a>

View File

@ -3,7 +3,9 @@
<ul style="line-height: 180%">
<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>
</a>&nbsp;
<a href="{% url 'projctor_preview_slide' agenda.key %}" title="{% trans 'Preview' %}" class="icon preview right">
@ -16,8 +18,10 @@
<ul style="line-height: 180%">
{% for item in items %}
<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' %}">
<i class="icon-facetime-video {% if item.active %}icon-white{% endif %}"></i>
<a href="{% url 'projector_activate_slide' item.sid %}"
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 href="{% model_url item 'edit' %}" title="{% trans 'Edit' %}" class="btn btn-mini right">
<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">
<i class="icon-search"></i>
</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 %}
<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' %}">
<i class="icon-summary {% if item.active %}icon-white{% endif %}"></i>
<a href="{% url 'projector_activate_slide' item.sid 'summary' %}"
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>
{% endif %}
{% for p in item.get_ancestors %}

View File

@ -4,28 +4,27 @@
{% 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 %}
<h1>{{ title }}</h1>
<h2 style="margin-top: -15px;">{% trans 'List of speakers' %}</h2>
{% endblock %}
{% 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 %}
<ol id="list_of_speakers">
<ol class="list_of_speakers">
{% for speaker in speakers %}
<li>{{ speaker }}</li>
{% endfor %}
</ol>
{% else %}
{% trans 'The list of speakers is empty' %}
<p><i>{% trans 'The list of speakers is empty.' %}</i></p>
{% endif %}
{% endblock %}

View File

@ -266,7 +266,7 @@ class SpeakerAppendView(SingleObjectMixin, RedirectView):
def pre_redirect(self, request, *args, **kwargs):
self.object = self.get_object()
if self.object.speaker_list_closed:
messages.error(request, _('List of speakers is closed.'))
messages.error(request, _('The list of speakers is closed.'))
else:
try:
Speaker.objects.add(item=self.object, person=request.user)
@ -337,8 +337,10 @@ class SpeakerSpeakView(SingleObjectMixin, RedirectView):
item=self.object.pk).exclude(
weight=None).get()
except Speaker.DoesNotExist:
messages.error(self.request, _('Person %s is not on the list of item %s.'
% (kwargs['person_id'], self.object)))
messages.error(
self.request,
_('%(person)s is not on the list of %(item)s.')
% {'person': kwargs['person_id'], 'item': self.object})
else:
speaker.speak()
@ -439,7 +441,7 @@ class CurrentListOfSpeakersView(RedirectView):
if item is None:
messages.error(request, _(
'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')
if self.request.user.has_perm('agenda.can_be_speaker'):
@ -483,7 +485,9 @@ def get_widgets(request):
template='agenda/widget.html',
context={
'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'),
Widget(

View File

@ -11,7 +11,7 @@
"""
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.person import PersonFormField
@ -21,7 +21,7 @@ from openslides.assignment.models import Assignment
class AssignmentForm(forms.ModelForm, CssClassMixin):
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:
model = Assignment
@ -31,5 +31,5 @@ class AssignmentForm(forms.ModelForm, CssClassMixin):
class AssignmentRunForm(forms.Form, CssClassMixin):
candidate = PersonFormField(
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.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.config.api import config
@ -39,17 +39,17 @@ class AssignmentCandidate(models.Model):
class Assignment(models.Model, SlideMixin):
prefix = 'assignment'
STATUS = (
('sea', _('Searching for candidates')),
('vot', _('Voting')),
('fin', _('Finished')),
('sea', ugettext_lazy('Searching for candidates')),
('vot', ugettext_lazy('Voting')),
('fin', ugettext_lazy('Finished')),
)
name = models.CharField(max_length=100, verbose_name=_("Name"))
description = models.TextField(null=True, blank=True, verbose_name=_("Description"))
posts = models.PositiveSmallIntegerField(verbose_name=_("Number of available posts"))
name = models.CharField(max_length=100, verbose_name=ugettext_lazy("Name"))
description = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Description"))
posts = models.PositiveSmallIntegerField(verbose_name=ugettext_lazy("Number of available posts"))
polldescription = models.CharField(
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')
def set_status(self, status):
@ -240,9 +240,8 @@ class Assignment(models.Model, SlideMixin):
class Meta:
permissions = (
('can_see_assignment', ugettext_noop("Can see assignment")),
('can_nominate_other',
ugettext_noop("Can nominate another person")),
('can_nominate_self', ugettext_noop("Can nominate themselves")),
('can_nominate_other', ugettext_noop("Can nominate another person")),
('can_nominate_self', ugettext_noop("Can nominate oneself")),
('can_manage_assignment', ugettext_noop("Can manage assignment")),
)
ordering = ('name',)

View File

@ -12,7 +12,7 @@
from django.dispatch import receiver
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.api import ConfigVariable, ConfigPage
@ -28,19 +28,19 @@ def setup_assignment_config_page(sender, **kwargs):
default_value=False,
form_field=forms.BooleanField(
required=False,
label=_('Only publish voting results for selected winners '
'(Projector view only)')))
label=ugettext_lazy('Only publish voting results for selected '
'winners (Projector view only)')))
assignment_pdf_ballot_papers_selection = ConfigVariable(
name='assignment_pdf_ballot_papers_selection',
default_value='CUSTOM_NUMBER',
form_field=forms.ChoiceField(
widget=forms.Select(),
required=False,
label=_('Number of ballot papers (selection)'),
label=ugettext_lazy('Number of ballot papers (selection)'),
choices=(
('NUMBER_OF_DELEGATES', _('Number of all delegates')),
('NUMBER_OF_ALL_PARTICIPANTS', _('Number of all participants')),
('CUSTOM_NUMBER', _('Use the following custom number')))))
('NUMBER_OF_DELEGATES', ugettext_lazy('Number of all delegates')),
('NUMBER_OF_ALL_PARTICIPANTS', ugettext_lazy('Number of all participants')),
('CUSTOM_NUMBER', ugettext_lazy('Use the following custom number')))))
assignment_pdf_ballot_papers_number = ConfigVariable(
name='assignment_pdf_ballot_papers_number',
default_value=8,
@ -48,32 +48,32 @@ def setup_assignment_config_page(sender, **kwargs):
widget=forms.TextInput(attrs={'class': 'small-input'}),
required=False,
min_value=1,
label=_('Custom number of ballot papers')))
label=ugettext_lazy('Custom number of ballot papers')))
assignment_pdf_title = ConfigVariable(
name='assignment_pdf_title',
default_value=_('Elections'),
form_field=forms.CharField(
widget=forms.TextInput(),
required=False,
label=_('Title for PDF document (all elections)')))
label=ugettext_lazy('Title for PDF document (all elections)')))
assignment_pdf_preamble = ConfigVariable(
name='assignment_pdf_preamble',
default_value='',
form_field=forms.CharField(
widget=forms.Textarea(),
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(
name='assignment_poll_vote_values',
default_value='auto',
form_field=forms.ChoiceField(
widget=forms.Select(),
required=False,
label=_('Election method'),
label=ugettext_lazy('Election method'),
choices=(
('auto', _('Automatic assign of method.')),
('votes', _('Always one option per candidate.')),
('yesnoabstain', _('Always Yes-No-Abstain per candidate.')))))
('auto', ugettext_lazy('Automatic assign of method')),
('votes', ugettext_lazy('Always one option per candidate')),
('yesnoabstain', ugettext_lazy('Always Yes-No-Abstain per candidate')))))
return ConfigPage(title=ugettext_noop('Elections'),
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.person import get_person
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.poll.views import PollFormView
from openslides.agenda.models import Item
@ -564,7 +564,12 @@ class AssignmentPollPDF(PDFView):
# set number of ballot papers
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":
number = int(User.objects.count())
else: # ballot_papers_selection == "CUSTOM_NUMBER"

View File

@ -1,7 +1,6 @@
{% extends 'base.html' %}
{% load i18n %}
{% load staticfiles %}
{% block content %}
@ -12,7 +11,7 @@
<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 {% 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 %}
<a href="{% url 'core_version' %}" class="btn btn-mini">{% trans 'Version' %}</a>
</div>

View File

@ -13,7 +13,7 @@
from django import forms
from django.core.urlresolvers import reverse
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.template import Tab
@ -115,7 +115,7 @@ class ConfigView(FormView):
"""
for key in form.cleaned_data:
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)

View File

@ -12,7 +12,7 @@
from django.dispatch import Signal, receiver
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.api import ConfigVariable, ConfigGroup, ConfigGroupedPage

View File

@ -5,7 +5,20 @@
{% block title %}{{ block.super }} {% trans 'Version' %}{% endblock %}
{% 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 %}
<p>{{ version.0 }} {% trans "Version" %}: {{ version.1 }}</p>
{% 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.utils.views import TemplateView
from .signals import config_signal
class VersionView(TemplateView):
@ -35,6 +36,13 @@ class VersionView(TemplateView):
openslides_version_string += ' Commit: %s' % get_git_commit_id()
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.
for plugin in settings.INSTALLED_PLUGINS:
try:

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,210 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# German translations for JavaScript file in OpenSlides package.
# Copyright (C) 2011-2013 by OpenSlides team, see AUTHORS.
# This file is distributed under the same license as the OpenSlides package.
# Emanuel Schütze <emanuel@intevation.de>, 2013.
#
msgid ""
msgstr ""
"Project-Id-Version: OpenSlides 1.3\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"
"Last-Translator: Oskar Hahn <mail@oshahn.de>\n"
"Last-Translator: Emanuel Schütze <emanuel@intevation.de>\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\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
#, c-format
msgid ", of which %s are hidden."

View File

@ -13,7 +13,7 @@
import mimetypes
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
@ -23,16 +23,16 @@ class Mediafile(models.Model):
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
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."""
uploader = PersonField(blank=True)
uploader = PersonField(blank=True, verbose_name=ugettext_lazy("Uploaded by"))
"""A person the uploader of a file."""
timestamp = models.DateTimeField(auto_now_add=True)

View File

@ -8,5 +8,9 @@
/** Navigation icons (mapping to glyphicons-halflings) **/
.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 'Size' %}</th>
<th>{% trans 'Upload time' %}</th>
<th>{% trans 'Uploader' %}</th>
<th>{% trans 'Uploaded by' %}</th>
{% if perms.mediafile.can_manage %}
<th class="mini_width">{% trans "Actions" %}</th>
{% endif %}

View File

@ -11,7 +11,7 @@
"""
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 CleanHtmlFormMixin
@ -30,18 +30,18 @@ class BaseMotionForm(CleanHtmlFormMixin, CssClassMixin, forms.ModelForm):
"""
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.
"""
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.
"""
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.
"""
@ -64,7 +64,7 @@ class BaseMotionForm(CleanHtmlFormMixin, CssClassMixin, forms.ModelForm):
class MotionSubmitterMixin(forms.ModelForm):
"""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."""
def __init__(self, *args, **kwargs):
@ -78,7 +78,7 @@ class MotionSubmitterMixin(forms.ModelForm):
class MotionSupporterMixin(forms.ModelForm):
"""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."""
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."""
disable_versioning = forms.BooleanField(
required=False, label=_("Don't create a new version"),
help_text=_("Don't create a new version. Useful e. g. for trivial changes."))
required=False, label=ugettext_lazy("Don't create a new version"),
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
last_version will be used."""
@ -102,10 +102,10 @@ class MotionDisableVersioningMixin(forms.ModelForm):
class MotionCategoryMixin(forms.ModelForm):
"""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):
"""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.utils import formats
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.config.api import config
@ -565,7 +565,7 @@ class MotionVersion(models.Model):
title = models.CharField(max_length=255, verbose_name=ugettext_lazy("Title"))
"""The title of a motion."""
text = models.TextField(verbose_name=_("Text"))
text = models.TextField(verbose_name=ugettext_lazy("Text"))
"""The text of a motion."""
reason = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Reason"))
@ -585,7 +585,7 @@ class MotionVersion(models.Model):
def __unicode__(self):
"""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?
def get_absolute_url(self, link='detail'):

View File

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

View File

@ -30,36 +30,36 @@ def setup_motion_config_page(sender, **kwargs):
name='motion_stop_submitting',
default_value=False,
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))
motion_min_supporters = ConfigVariable(
name='motion_min_supporters',
default_value=0,
form_field=forms.IntegerField(
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,
min_value=0,
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(
name='motion_preamble',
default_value=_('The assembly may decide,'),
form_field=forms.CharField(
widget=forms.TextInput(),
required=False,
label=_('Motion preamble')))
label=ugettext_lazy('Motion preamble')))
motion_pdf_ballot_papers_selection = ConfigVariable(
name='motion_pdf_ballot_papers_selection',
default_value='CUSTOM_NUMBER',
form_field=forms.ChoiceField(
widget=forms.Select(),
required=False,
label=_('Number of ballot papers (selection)'),
label=ugettext_lazy('Number of ballot papers (selection)'),
choices=[
('NUMBER_OF_DELEGATES', _('Number of all delegates')),
('NUMBER_OF_ALL_PARTICIPANTS', _('Number of all participants')),
('CUSTOM_NUMBER', _("Use the following custom number"))]))
('NUMBER_OF_DELEGATES', ugettext_lazy('Number of all delegates')),
('NUMBER_OF_ALL_PARTICIPANTS', ugettext_lazy('Number of all participants')),
('CUSTOM_NUMBER', ugettext_lazy("Use the following custom number"))]))
motion_pdf_ballot_papers_number = ConfigVariable(
name='motion_pdf_ballot_papers_number',
default_value=8,
@ -67,46 +67,46 @@ def setup_motion_config_page(sender, **kwargs):
widget=forms.TextInput(attrs={'class': 'small-input'}),
required=False,
min_value=1,
label=_('Custom number of ballot papers')))
label=ugettext_lazy('Custom number of ballot papers')))
motion_pdf_title = ConfigVariable(
name='motion_pdf_title',
default_value=_('Motions'),
form_field=forms.CharField(
widget=forms.TextInput(),
required=False,
label=_('Title for PDF document (all motions)')))
label=ugettext_lazy('Title for PDF document (all motions)')))
motion_pdf_preamble = ConfigVariable(
name='motion_pdf_preamble',
default_value='',
form_field=forms.CharField(
widget=forms.Textarea(),
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(
name='motion_allow_disable_versioning',
default_value=False,
form_field=forms.BooleanField(
label=_('Allow to disable versioning'),
label=ugettext_lazy('Allow to disable versioning'),
required=False))
motion_workflow = ConfigVariable(
name='motion_workflow',
default_value=1,
form_field=forms.ChoiceField(
widget=forms.Select(),
label=_('Workflow of new motions'),
label=ugettext_lazy('Workflow of new motions'),
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(
name='motion_identifier',
default_value='manually',
form_field=forms.ChoiceField(
widget=forms.Select(),
required=False,
label=_('Identifier'),
label=ugettext_lazy('Identifier'),
choices=[
('manually', _('Set it manually')),
('per_category', _('Numbered per category')),
('serially_numbered', _('Serially numbered'))]))
('manually', ugettext_lazy('Set it manually')),
('per_category', ugettext_lazy('Numbered per category')),
('serially_numbered', ugettext_lazy('Serially numbered'))]))
return ConfigPage(title=ugettext_noop('Motion'),
url='motion',

View File

@ -10,7 +10,7 @@
{% trans "Categories" %}
<small class="pull-right">
{% 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 %}
<a href="{% url 'motion_list' %}" class="btn btn-mini"><i class="icon-chevron-left"></i> {% trans "Back to overview" %}</a>
</small>

View File

@ -126,11 +126,11 @@
<input type="radio" value="{{ version.version_number }}" name="rev2">
</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>
</a>
{# 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>
</a>
</td>

View File

@ -34,11 +34,11 @@
<table class="table table-striped table-bordered">
<tr>
<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>
</td>
<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>
</td>
</tr>

View File

@ -31,7 +31,11 @@
{% trans "New motion" %}
{% endif %}
<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>
</h1>
<form action="" method="post">{% csrf_token %}

View File

@ -15,7 +15,7 @@
{% endif %}
{% endif %}
{% 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>#}
{% 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>

View File

@ -291,7 +291,7 @@ class VersionDiffView(DetailView):
diff_text = htmldiff(version_rev1.text, version_rev2.text)
diff_reason = htmldiff(version_rev1.reason, version_rev2.reason)
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_rev2 = None
diff_text = None
@ -556,7 +556,7 @@ class MotionSetStateView(SingleObjectMixin, RedirectView):
else:
self.object.save()
# 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)
messages.success(request, _('Motion status was set to: %s.'
% html_strong(self.object.state)))
@ -583,7 +583,7 @@ class CreateAgendaItemView(SingleObjectMixin, RedirectView):
def pre_redirect(self, request, *args, **kwargs):
"""Create the agenda item."""
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()
@ -595,7 +595,7 @@ class MotionPDFView(SingleObjectMixin, PDFView):
If self.print_all_motions is False, the view returns a PDF with only one
motion."""
permission_required = 'motion.can_manage_motion'
permission_required = 'motion.can_see_motion'
model = Motion
top_space = 0
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))
continue
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
user.reset_password()
count_success += 1

View File

@ -117,11 +117,11 @@ class GroupForm(forms.ModelForm, CssClassMixin):
# Editing the anonymous-user
if self.instance.name.lower() != data.lower():
raise forms.ValidationError(
ugettext_lazy('You can not edit the name for this group.'))
_('You can not edit the name for this group.'))
else:
if data.lower() in ['anonymous', 'registered']:
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
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.models import signals
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.signals import receive_persons
@ -27,32 +27,32 @@ class User(PersonMixin, Person, SlideMixin, DjangoUser):
prefix = 'user' # This is for the slides
person_prefix = 'user'
GENDER_CHOICES = (
('male', _('Male')),
('female', _('Female')),
('male', ugettext_lazy('Male')),
('female', ugettext_lazy('Female')),
)
django_user = models.OneToOneField(DjangoUser, editable=False, parent_link=True)
structure_level = models.CharField(
max_length=255, blank=True, default='', verbose_name=_("Structure level"),
help_text=_('Will be shown after the name.'))
max_length=255, blank=True, default='', verbose_name=ugettext_lazy("Structure level"),
help_text=ugettext_lazy('Will be shown after the name.'))
title = models.CharField(
max_length=50, blank=True, default='', verbose_name=_("Titel"),
help_text=_('Will be shown before the name.'))
max_length=50, blank=True, default='', verbose_name=ugettext_lazy("Title"),
help_text=ugettext_lazy('Will be shown before the name.'))
gender = models.CharField(
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(
max_length=255, blank=True, default='', verbose_name=_("Committee"),
help_text=_('Only for filtering the participant list.'))
max_length=255, blank=True, default='', verbose_name=ugettext_lazy("Committee"),
help_text=ugettext_lazy('Only for filtering the participant list.'))
about_me = models.TextField(
blank=True, default='', verbose_name=_('About me'),
help_text=_('Your profile text'))
blank=True, default='', verbose_name=ugettext_lazy('About me'),
help_text=ugettext_lazy('Your profile text'))
comment = models.TextField(
blank=True, default='', verbose_name=_('Comment'),
help_text=_('Only for notes.'))
blank=True, default='', verbose_name=ugettext_lazy('Comment'),
help_text=ugettext_lazy('Only for notes.'))
default_password = models.CharField(
max_length=100, blank=True, default='',
verbose_name=_("Default password"))
verbose_name=ugettext_lazy("Default password"))
@property
def clean_name(self):
@ -134,9 +134,9 @@ class Group(PersonMixin, Person, SlideMixin, DjangoGroup):
django_group = models.OneToOneField(DjangoGroup, editable=False, parent_link=True)
group_as_person = models.BooleanField(
default=False, verbose_name=_("Use this group as participant"),
help_text=_('For example as submitter of a motion.'))
description = models.TextField(blank=True, verbose_name=_("Description"))
default=False, verbose_name=ugettext_lazy("Use this group as participant"),
help_text=ugettext_lazy('For example as submitter of a motion.'))
description = models.TextField(blank=True, verbose_name=ugettext_lazy("Description"))
@models.permalink
def get_absolute_url(self, link='view'):

View File

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

View File

@ -3,11 +3,11 @@
{% load i18n %}
{% load tags %}
{% block title %}{{ block.super }} {{ group }}{% endblock %}
{% block title %}{{ block.super }} {% trans group.name %}{% endblock %}
{% block content %}
<h1>{{ group }}
<h1>{% trans group.name %}
<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>
</small>

View File

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

View File

@ -14,43 +14,44 @@
</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>
<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>
<legend>{% trans "Event data" %}</legend>
<label>{% trans "Structure level" %}</label>
{{ shown_user.structure_level }}
<label>{% trans "Committee" %}</label>
{{ shown_user.committee }}
<label>{% trans "Groups" %}</label>
{% if shown_user.groups.all %}
{{ shown_user.groups.all|join:", " }}
{% else %}
{% trans "The participant is not member of any group." %}
{% endif %}
</fieldset>
<fieldset>
<legend>{% trans "Event data" %}</legend>
<label>{% trans "Structure level" %}</label>
{{ shown_user.structure_level }}
<label>{% trans "Committee" %}</label>
{{ shown_user.committee }}
<label>{% trans "Groups" %}</label>
{% if shown_user.groups.all %}
{{ shown_user.groups.all|join:", " }}
{% else %}
{% trans "The participant is not member of any group." %}
{% if perms.participant.can_manage_participant %}
<fieldset>
<legend>{% trans "Administrative data" %}</legend>
<label>{% trans "Username" %}</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 %}
</fieldset>
{% 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 %}
</div>
{% endblock %}

View File

@ -12,7 +12,7 @@
from django.db import models
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.projector import SlideMixin
@ -24,9 +24,9 @@ class ProjectorSlide(models.Model, SlideMixin):
"""
prefix = 'ProjectorSlide'
title = models.CharField(max_length=256, verbose_name=_("Title"))
text = models.TextField(null=True, blank=True, verbose_name=_("Text"))
weight = models.IntegerField(default=0, verbose_name=_("Weight"))
title = models.CharField(max_length=256, verbose_name=ugettext_lazy("Title"))
text = models.TextField(null=True, blank=True, verbose_name=ugettext_lazy("Text"))
weight = models.IntegerField(default=0, verbose_name=ugettext_lazy("Weight"))
def slide(self):
return {

View File

@ -13,7 +13,6 @@ from time import time
from django.dispatch import Signal, receiver
from django import forms
from django.utils.translation import ugettext_lazy, ugettext as _
from django.template.loader import render_to_string
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;
}
.overlay_list .form-inline {
margin: 5px 0 0 31px;
.overlay_list .overlayblock {
margin: 0 0 0 31px;
}
#countdown_time {

View File

@ -58,7 +58,7 @@ body{
top:110px;
right:40px;
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 {
@ -73,6 +73,19 @@ body{
width: 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 ***/
#contentwrapper {
@ -146,6 +159,14 @@ body{
color: #9FA9B7;
list-style-type: none;
}
.list_of_speakers li {
font-size: 130%;
line-height: 160%;
}
.last_speakers li {
color: #9FA9B7;
list-style: none;
}
/* Table */
table {

View File

@ -7,7 +7,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<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/projector.js' %}"></script>
<title>{% block title %} {% get_config 'event_name' %} {% endblock %}</title>

View File

@ -3,14 +3,14 @@
<span>
{% trans "Countdown for speaking time" %}:
<div>
<div class="input-append">
<div class="overlayblock">
<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 }}">
<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>
<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' %}">
<i class="icon-fast-backward"></i>
</a>

View File

@ -4,7 +4,7 @@
<span>
{% trans "Message" %}:
<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' %}">
<button type="submit" class="btn btn-primary" name="message" title="{% trans 'Apply' %}" style="width: 16px;">
<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.shortcuts import redirect
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.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
$('.leftmenu').tooltip({
selector: "a[rel=tooltip]",
placement: 'right'
});
$(this).tooltip({
selector: "a[rel=tooltip]",
placement: 'bottom'
});
$('h1').tooltip({
selector: "a[rel=tooltip]",
placement: 'bottom'
});
$('body').tooltip({
selector: '.tooltip'
});
$('.tooltip-left').tooltip({
placement: 'left'
});

View File

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

View File

@ -10,7 +10,6 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}{% get_config 'event_name' %}{% endblock %}</title>
<!-- styles -->
<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" />
@ -28,7 +27,7 @@
<div class="span12">
<div id="header">
<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 %}
<div class="btn-group pull-right">
{% if user.is_authenticated %}
@ -65,7 +64,7 @@
{% for tab in tabs %}
{% if tab.permission %}
<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="text">{{ tab.title }}</span>
</a>

View File

@ -2,7 +2,7 @@ import json
from django.db import models
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.util import ValidationError as FormValidationError

View File

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

View File

@ -114,7 +114,7 @@ class TestSpeakerAppendView(SpeakerViewTestCase):
response = self.check_url('/agenda/1/speaker/', self.speaker1_client, 302)
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):
@ -155,7 +155,7 @@ class TestSpeakerSpeakView(SpeakerViewTestCase):
def test_get(self):
url = '/agenda/1/speaker/%s/speak/' % self.speaker1.person_id
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)
response = self.check_url(url, self.admin_client, 302)