From 55073494fc20ea7937bed12d7b3d92b8ffe0a078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Wed, 5 Sep 2012 21:54:34 +0200 Subject: [PATCH 001/222] Insert weight field in custom slides and order custom slides in the widget --- openslides/projector/models.py | 1 + openslides/projector/views.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openslides/projector/models.py b/openslides/projector/models.py index e6e51716a..299b41afb 100644 --- a/openslides/projector/models.py +++ b/openslides/projector/models.py @@ -31,6 +31,7 @@ class ProjectorSlide(models.Model, SlideMixin): 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")) def slide(self): return { diff --git a/openslides/projector/views.py b/openslides/projector/views.py index 96af29ed6..59b660e2b 100644 --- a/openslides/projector/views.py +++ b/openslides/projector/views.py @@ -409,11 +409,11 @@ def get_widgets(request): # Custom slide widget context = { - 'slides': ProjectorSlide.objects.all(), + 'slides': ProjectorSlide.objects.all().order_by('weight'), 'welcomepage_is_active': not bool(config["presentation"])} widgets.append(Widget( name='custom_slide', - display_name=_('Custom Slide'), + display_name=_('Custom Slides'), template='projector/custom_slide_widget.html', context=context, permission_required='projector.can_manage_projector', From d84a8d2bddbb36b67f48a08757b9951a2db013c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Wed, 5 Sep 2012 22:19:53 +0200 Subject: [PATCH 002/222] Sorting assignments by name in the widget --- openslides/assignment/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py index 7bffaa18e..1e76e0999 100644 --- a/openslides/assignment/views.py +++ b/openslides/assignment/views.py @@ -660,5 +660,5 @@ def get_widgets(request): Widget( name=_('Assignments'), template='assignment/widget.html', - context={'assignments': Assignment.objects.all()}, + context={'assignments': Assignment.objects.all().order_by('name')}, permission_required='assignment.can_manage_assignment')] From 2ecd552d2b93aca8c6e62e38d5a71a3ea137f93a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Wed, 5 Sep 2012 22:38:40 +0200 Subject: [PATCH 003/222] Default Sorting of applications by number --- openslides/application/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openslides/application/views.py b/openslides/application/views.py index 37a0e08b4..c09b6a4a9 100644 --- a/openslides/application/views.py +++ b/openslides/application/views.py @@ -99,10 +99,11 @@ def overview(request): else: sort = sortfilter['sort'] query = query.order_by(sort) - if sort.startswith('aversion_'): # limit result to last version of an application query = query.filter(aversion__id__in=[x.last_version.id for x in Application.objects.all()]) + else: + query = query.order_by('number') if 'reverse' in sortfilter: query = query.reverse() From d1c12ea0e59396e75caa52091893bb1243250ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Wed, 5 Sep 2012 22:42:44 +0200 Subject: [PATCH 004/222] Sorting applications in the widget by number --- openslides/application/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openslides/application/views.py b/openslides/application/views.py index c09b6a4a9..f702eb53b 100644 --- a/openslides/application/views.py +++ b/openslides/application/views.py @@ -921,5 +921,5 @@ def get_widgets(request): Widget( name='applications', template='application/widget.html', - context={'applications': Application.objects.all()}, + context={'applications': Application.objects.all().order_by('number')}, permission_required='application.can_manage_application')] From 75eb59654799233ee63527cd9871261654ae4279 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 6 Sep 2012 15:57:42 +0200 Subject: [PATCH 005/222] block a user to be a candidate from a assignment, if he delete his candidation by him self --- openslides/assignment/models.py | 35 +++++++++++++++++++++++++-------- openslides/assignment/views.py | 9 ++++++--- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/openslides/assignment/models.py b/openslides/assignment/models.py index bf288cd8e..accfc2105 100644 --- a/openslides/assignment/models.py +++ b/openslides/assignment/models.py @@ -33,6 +33,7 @@ class AssignmentCandidate(models.Model): assignment = models.ForeignKey("Assignment") person = PersonField(db_index=True) elected = models.BooleanField(default=False) + blocked = models.BooleanField(default=False) def __unicode__(self): return unicode(self.person) @@ -72,6 +73,8 @@ class Assignment(models.Model, SlideMixin): def run(self, candidate, person=None): """ run for a vote + candidate: The user who will be a candidate + person: The user who chooses the candidate """ # TODO: don't make any permission checks here. # Use other Exceptions @@ -79,23 +82,39 @@ class Assignment(models.Model, SlideMixin): raise NameError(_('%s is already a candidate.') % candidate) if not person.has_perm("assignment.can_manage_assignment") and self.status != 'sea': raise NameError(_('The candidate list is already closed.')) - AssignmentCandidate(assignment=self, person=candidate, elected=False).save() + candidation = self.assignment_candidats.filter(person=candidate) + if candidation and candidate != person: + # if the candidation is blocked and anotherone tries to run the + # candidate + raise NameError( + _('The %s does not want to be a candidate.') % candidate) + elif candidation and candidate == person: + candidation[0].blocked = False + candidation[0].save() + else: + AssignmentCandidate(assignment=self, person=candidate).save() - def delrun(self, candidate): + def delrun(self, candidate, blocked=True): """ stop running for a vote """ if self.is_candidate(candidate): - self.assignment_candidats.get(person=candidate).delete() + candidation = self.assignment_candidats.get(person=candidate) + if blocked: + candidation.blocked = True + candidation.save() + else: + candidation.delete() else: # TODO: Use an OpenSlides Error raise Exception(_('%s is no candidate') % candidate) def is_candidate(self, person): - if self.assignment_candidats.filter(person=person).exists(): - return True - else: - return False + """ + return True, if person is a candidate. + """ + return self.assignment_candidats.filter(person=person) \ + .exclude(blocked=True).exists() @property def assignment_candidats(self): @@ -110,7 +129,7 @@ class Assignment(models.Model, SlideMixin): return self.get_participants(only_elected=True) def get_participants(self, only_elected=False, only_candidate=False): - candidates = self.assignment_candidats + candidates = self.assignment_candidats.exclude(blocked=True) if only_elected and only_candidate: # TODO: Use right Exception diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py index 7bffaa18e..bda689102 100644 --- a/openslides/assignment/views.py +++ b/openslides/assignment/views.py @@ -81,9 +81,12 @@ def view(request, assignment_id=None): user = form.cleaned_data['candidate'] try: assignment.run(user, request.user) - messages.success(request, _("Candidate %s was nominated successfully.") % (user)) except NameError, e: messages.error(request, e) + else: + messages.success(request, _( + "Candidate %s was nominated successfully.") + % user) else: if request.user.has_perm('assignment.can_nominate_other'): form = AssignmentRunForm() @@ -184,7 +187,7 @@ def delrun(request, assignment_id): assignment = Assignment.objects.get(pk=assignment_id) try: if assignment.status == 'sea' or user.has_perm("assignment.can_manage_assignment"): - assignment.delrun(request.user) + assignment.delrun(request.user, blocked=True) else: messages.error(request, _('The candidate list is already closed.')) except Exception, e: @@ -201,7 +204,7 @@ def delother(request, assignment_id, user_id): if request.method == 'POST': try: - assignment.delrun(person) + assignment.delrun(person, blocked=False) except Exception, e: messages.error(request, e) else: From 38d53bbb92075a4a810019618cc78bdb101504a5 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Tue, 11 Sep 2012 19:30:12 +0200 Subject: [PATCH 006/222] fixed first-time-pdf --- openslides/participant/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openslides/participant/views.py b/openslides/participant/views.py index a2575d138..f4bbb8448 100644 --- a/openslides/participant/views.py +++ b/openslides/participant/views.py @@ -269,7 +269,7 @@ class ParticipantsPasswordsPDF(PDFView): cell.append( Paragraph( _("Password: %s") - % (user.firstpassword), stylesheet['Monotype'])) + % (user.default_password), stylesheet['Monotype'])) cell.append(Spacer(0, 0.5 * cm)) cell.append( Paragraph( @@ -321,7 +321,7 @@ class UserImportView(FormView): class ResetPasswordView(RedirectView, SingleObjectMixin, QuestionMixin): """ - Set the Passwort for a user to his firstpassword. + Set the Passwort for a user to his default password. """ permission_required = 'participant.can_manage_participant' model = User From 7376b7a692d3014cb7d6998031d1c6a1b05dfd3c Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 11 Sep 2012 20:50:53 +0200 Subject: [PATCH 007/222] Updated translations. --- openslides/assignment/models.py | 2 +- openslides/locale/de/LC_MESSAGES/django.mo | Bin 35724 -> 32992 bytes openslides/locale/de/LC_MESSAGES/django.po | 620 +++++++++------------ openslides/projector/views.py | 2 +- 4 files changed, 263 insertions(+), 361 deletions(-) diff --git a/openslides/assignment/models.py b/openslides/assignment/models.py index accfc2105..32b511f89 100644 --- a/openslides/assignment/models.py +++ b/openslides/assignment/models.py @@ -87,7 +87,7 @@ class Assignment(models.Model, SlideMixin): # if the candidation is blocked and anotherone tries to run the # candidate raise NameError( - _('The %s does not want to be a candidate.') % candidate) + _('%s does not want to be a candidate.') % candidate) elif candidation and candidate == person: candidation[0].blocked = False candidation[0].save() diff --git a/openslides/locale/de/LC_MESSAGES/django.mo b/openslides/locale/de/LC_MESSAGES/django.mo index 328c8ebc10e2d5a9823b7ac1ff85cc1391d91aa8..8bb0c86f06684bbaef7a6dc8ba7d7421f7d5bc6e 100644 GIT binary patch delta 10811 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 delta 12969 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 f=GlBl{95WqUL9cwcA\n" "Language-Team: Deutsch \n" @@ -17,11 +17,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: openslides_settings.py:48 +#: openslides_global_settings.py:36 msgid "German" msgstr "Deutsch" -#: openslides_settings.py:49 +#: openslides_global_settings.py:37 msgid "English" msgstr "Englisch" @@ -51,6 +51,7 @@ msgid "Closed" msgstr "Abgeschlossen" #: agenda/models.py:46 agenda/templates/agenda/overview.html:71 +#: projector/models.py:34 msgid "Weight" msgstr "Gewichtung" @@ -118,28 +119,22 @@ msgstr "Neuer Eintrag" msgid "Agenda as PDF" msgstr "Tagesordnung als PDF" -#: agenda/templates/agenda/base_agenda.html:19 -#: projector/templates/projector/base_projector.html:20 -#: templates/front_page.html:25 -msgid "Projector view" -msgstr "Projektor-Ansicht" - -#: agenda/templates/agenda/base_agenda.html:31 +#: agenda/templates/agenda/base_agenda.html:26 msgid "View item" msgstr "Eintrag anzeigen" -#: agenda/templates/agenda/base_agenda.html:36 +#: agenda/templates/agenda/base_agenda.html:31 #: agenda/templates/agenda/edit.html:8 agenda/templates/agenda/edit.html:16 #: agenda/templates/agenda/item_row.html:40 msgid "Edit item" msgstr "Eintrag bearbeiten" -#: agenda/templates/agenda/base_agenda.html:38 +#: agenda/templates/agenda/base_agenda.html:33 #: agenda/templates/agenda/item_row.html:41 msgid "Delete item" msgstr "Eintrag löschen" -#: agenda/templates/agenda/base_agenda.html:43 +#: agenda/templates/agenda/base_agenda.html:38 msgid "Show item" msgstr "Eintrag projizieren" @@ -161,6 +156,7 @@ msgstr "Tagesordnungs-Einstellungen" #: participant/templates/participant/password_change.html:22 #: participant/templates/participant/settings.html:22 #: projector/templates/projector/new.html:13 +#: projector/templates/projector/select_widgets.html:22 msgid "Save" msgstr "Speichern" @@ -191,7 +187,7 @@ msgstr "Abbrechen" #: assignment/templates/assignment/view.html:83 #: participant/templates/participant/edit.html:34 #: participant/templates/participant/group_edit.html:28 -#: projector/templates/projector/control_overlay_message.html:7 +#: projector/templates/projector/control_overlay_message.html:8 #: projector/templates/projector/new.html:16 msgid "Apply" msgstr "Übernehmen" @@ -229,10 +225,10 @@ msgid "Do you want to save the changed order of agenda items?" msgstr "Möchten Sie die geänderte Reihenfolge der Einträge speichern?" #: agenda/templates/agenda/overview.html:46 application/models.py:574 -#: application/views.py:486 application/views.py:798 application/views.py:849 +#: application/views.py:487 application/views.py:799 application/views.py:850 #: application/templates/application/view.html:82 #: application/templates/projector/Application.html:37 -#: assignment/models.py:260 assignment/views.py:561 +#: assignment/models.py:279 assignment/views.py:564 #: assignment/templates/assignment/view.html:156 #: assignment/templates/assignment/view.html:160 #: assignment/templates/projector/Assignment.html:78 @@ -242,10 +238,10 @@ msgid "Yes" msgstr "Ja" #: agenda/templates/agenda/overview.html:47 application/models.py:574 -#: application/views.py:486 application/views.py:798 application/views.py:850 +#: application/views.py:487 application/views.py:799 application/views.py:851 #: application/templates/application/view.html:83 #: application/templates/projector/Application.html:38 -#: assignment/models.py:260 assignment/views.py:562 +#: assignment/models.py:279 assignment/views.py:565 #: assignment/templates/assignment/view.html:157 #: assignment/templates/projector/Assignment.html:79 utils/utils.py:53 #: utils/views.py:111 @@ -287,7 +283,7 @@ msgstr "Aktionen" #: agenda/templates/agenda/overview.html:102 #: agenda/templates/agenda/widget.html:46 -#: projector/templates/projector/widget.html:36 +#: projector/templates/projector/custom_slide_widget.html:36 msgid "No items available." msgstr "Keine Einträge vorhanden." @@ -295,8 +291,8 @@ msgstr "Keine Einträge vorhanden." #: agenda/templates/agenda/widget.html:29 #: application/templates/application/widget.html:17 #: assignment/templates/assignment/widget.html:17 -#: projector/templates/projector/widget.html:11 -#: projector/templates/projector/widget.html:30 +#: projector/templates/projector/custom_slide_widget.html:11 +#: projector/templates/projector/custom_slide_widget.html:30 msgid "Preview" msgstr "Vorschau" @@ -304,7 +300,7 @@ msgstr "Vorschau" #: application/templates/application/widget.html:11 #: assignment/templates/assignment/view.html:120 #: assignment/templates/assignment/widget.html:11 -#: projector/templates/projector/widget.html:24 +#: projector/templates/projector/custom_slide_widget.html:24 msgid "Delete" msgstr "Löschen" @@ -312,11 +308,11 @@ msgstr "Löschen" #: application/templates/application/widget.html:14 #: assignment/templates/assignment/view.html:119 #: assignment/templates/assignment/widget.html:14 -#: projector/templates/projector/widget.html:27 +#: projector/templates/projector/custom_slide_widget.html:27 msgid "Edit" msgstr "Bearbeiten" -#: application/forms.py:25 application/models.py:542 application/views.py:817 +#: application/forms.py:25 application/models.py:542 application/views.py:818 #: application/templates/application/view.html:232 #: application/templates/application/view.html:252 #: application/templates/projector/Application.html:77 @@ -331,12 +327,12 @@ msgstr "Triviale Änderung" msgid "Trivial changes don't create a new version." msgstr "Triviale Änderungen erzeugen keine neue Version." -#: application/forms.py:44 application/views.py:748 +#: application/forms.py:44 application/views.py:749 #: application/templates/application/view.html:25 msgid "Supporters" msgstr "Unterstützer/innen" -#: application/forms.py:50 participant/forms.py:116 +#: application/forms.py:50 participant/forms.py:102 msgid "CSV File" msgstr "CSV-Datei" @@ -441,7 +437,7 @@ msgstr "Verworfen (nicht zulässig)" msgid "Needs Review" msgstr "Benötigt Review" -#: application/models.py:66 application/views.py:732 +#: application/models.py:66 application/views.py:733 #: application/templates/application/overview.html:41 #: application/templates/application/view.html:18 #: application/templates/projector/Application.html:55 @@ -453,12 +449,6 @@ msgstr "Antragsteller/in" msgid "Version %d authorized" msgstr "Version %d zugelassen" -#: application/models.py:110 -#, python-format -msgctxt "Rejected means not authorized" -msgid "Version %d rejected" -msgstr "Version %d verworfen" - #: application/models.py:139 msgid "Searching for supporters." msgstr "Auf Unterstützersuche." @@ -518,7 +508,7 @@ msgstr "Version %s zugelassen" msgid "Version %s not authorized" msgstr "Version %s nicht zugelassen" -#: application/models.py:336 assignment/models.py:65 +#: application/models.py:336 assignment/models.py:66 #, python-format msgid "%s is not a valid status." msgstr "%s ist kein gültiger Status." @@ -577,7 +567,7 @@ msgstr "Darf Anträge unterstützen" msgid "Can manage motions" msgstr "Darf Anträge verwalten" -#: application/models.py:575 assignment/models.py:261 +#: application/models.py:575 assignment/models.py:280 msgid "Abstain" msgstr "Enthaltung" @@ -592,32 +582,32 @@ msgstr "Die Versammlung möge beschließen," msgid "Motions" msgstr "Anträge" -#: application/views.py:180 +#: application/views.py:181 msgid "You have not the necessary rights to create or edit motions." msgstr "" "Sie haben nicht die nötigen Rechte, um Anträge zu erstellen oder zu " "bearbeiten." -#: application/views.py:185 +#: application/views.py:186 msgid "You can not edit this motion. You are not the submitter." msgstr "" "Sie dürfen diesen Antrag nicht bearbeiten. Sie sind nicht der Antragsteller" -#: application/views.py:248 +#: application/views.py:249 msgid "New motion was successfully created." msgstr "Neuer Antrag wurde erfolgreich angelegt." -#: application/views.py:250 +#: application/views.py:251 msgid "Motion was successfully modified." msgstr "Antrag wurde erfolgreich geändert." -#: application/views.py:257 application/views.py:656 assignment/views.py:133 -#: participant/views.py:458 participant/views.py:481 utils/views.py:210 +#: application/views.py:258 application/views.py:657 assignment/views.py:136 +#: participant/views.py:459 participant/views.py:482 utils/views.py:210 #: utils/views.py:228 utils/views.py:252 msgid "Please check the form for errors." msgstr "Bitte kontrollieren Sie das Formular nach Fehlern." -#: application/views.py:264 +#: application/views.py:265 msgid "" "Attention: Do you really want to edit this motion? The supporters will " "not be removed automatically because you can manage motions. Please " @@ -627,7 +617,7 @@ msgstr "" "werden nicht automatisch entfernt, da Sie Anträge verwalten dürfen. " "Prüfen Sie, ob die Unterstützungen noch gültig sind." -#: application/views.py:266 +#: application/views.py:267 #, python-format msgid "" "Attention: Do you really want to edit this motion? All %s supporters " @@ -636,141 +626,141 @@ msgstr "" "Wollen Sie den Antrag wirklich ändern? Alle %s Unterstützer/innen " "werden dann automatisch entfernt. Versuchen Sie diese erneut zu gewinnen." -#: application/views.py:298 +#: application/views.py:299 msgid "Motion number was successfully set." msgstr "Antragsnummer wurde erfolgreich gesetzt." -#: application/views.py:314 +#: application/views.py:315 msgid "Motion was successfully authorized." msgstr "Antrag wurde erfolgreich zugelassen." -#: application/views.py:329 +#: application/views.py:330 msgid "Motion was successfully rejected." msgstr "Antrag wurde erfolgreich verworfen." -#: application/views.py:345 +#: application/views.py:346 #, python-format msgid "Motion status was set to: %s." msgstr "Antragsstatus wurde gesetzt auf: %s." -#: application/views.py:361 +#: application/views.py:362 msgid "Motion status was reset." msgstr "Antragsstatus wurde zurückgesetzt." -#: application/views.py:375 +#: application/views.py:376 msgid "You have support the motion successfully." msgstr "Sie haben den Antrag erfolgreich unterstützt." -#: application/views.py:389 +#: application/views.py:390 msgid "You have unsupport the motion successfully." msgstr "Sie haben dem Antrag erfolgreich Ihre Unterstützung entzogen." -#: application/views.py:403 +#: application/views.py:404 msgid "New vote was successfully created." msgstr "Neue Abstimmung erfolgreich angelegt." -#: application/views.py:419 +#: application/views.py:420 msgid "Poll deleted" msgstr "Abstimmung gelöscht" -#: application/views.py:420 +#: application/views.py:421 msgid "Poll was successfully deleted." msgstr "Abstimmung wurde erfolgreich gelöscht." -#: application/views.py:422 +#: application/views.py:423 #, python-format msgid "the %s. poll" msgstr "die %s. Abstimmung" -#: application/views.py:460 application/views.py:469 +#: application/views.py:461 application/views.py:470 #, python-format msgid "You can not delete motion %s." msgstr "Sie können Antrag %s nicht löschen." -#: application/views.py:465 application/views.py:473 +#: application/views.py:466 application/views.py:474 #, python-format msgid "Motion %s was successfully deleted." msgstr "Antrag %s wurde erfolgreich gelöscht." -#: application/views.py:475 +#: application/views.py:476 msgid "Invalid request" msgstr "Ungültige Anfrage" -#: application/views.py:494 +#: application/views.py:495 msgid "Do you really want to delete multiple motions?" msgstr "Wollen Sie wirklich mehrere Anträge löschen?" -#: application/views.py:496 +#: application/views.py:497 #, python-format msgid "Do you really want to delete %s?" msgstr "Soll %s wirklich gelöscht werden?" -#: application/views.py:520 +#: application/views.py:521 msgid "Poll was updated" msgstr "Abstimmung wurde aktualisiert" -#: application/views.py:537 +#: application/views.py:538 #, python-format msgid "Version %s accepted." msgstr "Version %s akzeptiert." -#: application/views.py:539 +#: application/views.py:540 #, python-format msgid "Do you really want to authorize version %s?" msgstr "Soll Version %s wirklich zugelassen werden?" -#: application/views.py:549 +#: application/views.py:550 #, python-format msgid "Version %s rejected." msgstr "Version %s zurückgewiesen." -#: application/views.py:551 +#: application/views.py:552 msgid "ERROR by rejecting the version." msgstr "FEHLER beim Zurückweisen der Version." -#: application/views.py:553 +#: application/views.py:554 #, python-format msgid "Do you really want to reject version %s?" msgstr "Soll Version %s wirklich zurückgewiesen werden?" -#: application/views.py:583 application/views.py:587 application/views.py:593 -#: application/views.py:596 participant/api.py:77 +#: application/views.py:584 application/views.py:588 application/views.py:594 +#: application/views.py:597 participant/api.py:77 #, python-format msgid "Ignoring malformed line %d in import file." msgstr "Fehlerhafte Zeile %d der Quelldatei wurde ignoriert." -#: application/views.py:642 +#: application/views.py:643 #, python-format msgid "%d motion was successfully imported." msgid_plural "%d motions were successfully imported." msgstr[0] "%d Antrag wurde erfolgreich importiert." msgstr[1] "%d Anträge wurden erfolgreich importiert." -#: application/views.py:645 +#: application/views.py:646 #, python-format msgid "%d motion was successfully modified." msgid_plural "%d motions were successfully modified." msgstr[0] "%d Antrag wurde erfolgreich geändert." msgstr[1] "%d Anträge wurden erfolgreich geändert." -#: application/views.py:648 +#: application/views.py:649 #, python-format msgid "%d new user was added." msgid_plural "%d new users were added." msgstr[0] "%d neuer Nutzer wurde erstellt." msgstr[1] "%d neue Nutzer wurden erstellt." -#: application/views.py:652 participant/api.py:93 +#: application/views.py:653 participant/api.py:93 msgid "Import aborted because of severe errors in the input file." msgstr "Import auf Grund von schweren Fehlern in der Quelldatei abgebrochen." -#: application/views.py:654 participant/api.py:95 +#: application/views.py:655 participant/api.py:95 msgid "Import file has wrong character encoding, only UTF-8 is supported!" msgstr "" "Die Quelldatei benutzt eine ungültige Zeichenkodierung, es wird nur UTF-8 " "wird unterstützt!" -#: application/views.py:658 +#: application/views.py:659 msgid "" "Attention: Existing motions will be modified if you import new motions with " "the same number." @@ -778,7 +768,7 @@ msgstr "" "Achtung: Existierende Anträge werden geändert wenn Sie neue Anträge mit " "identischer Nummer importieren." -#: application/views.py:659 +#: application/views.py:660 msgid "" "Attention: Importing an motions without a number multiple times will create " "duplicates." @@ -786,25 +776,25 @@ msgstr "" "Achtung: Bei mehrfachem Import eines Antrags ohne Nummer können Duplikate " "entstehen." -#: application/views.py:685 application/views.py:911 +#: application/views.py:686 application/views.py:912 msgid "Applications" msgstr "Anträge" -#: application/views.py:692 application/views.py:831 +#: application/views.py:693 application/views.py:832 msgid "Application" msgstr "Antrag" -#: application/views.py:706 application/templates/application/overview.html:84 +#: application/views.py:707 application/templates/application/overview.html:84 msgid "No motions available." msgstr "Keine Anträge vorhanden." -#: application/views.py:711 application/views.py:713 application/views.py:725 -#: application/views.py:727 +#: application/views.py:712 application/views.py:714 application/views.py:726 +#: application/views.py:728 #: application/templates/projector/Application.html:63 msgid "Motion No." msgstr "Antrag Nr." -#: application/views.py:762 application/templates/application/overview.html:20 +#: application/views.py:763 application/templates/application/overview.html:20 #: application/templates/application/overview.html:40 #: application/templates/application/view.html:37 #: application/templates/projector/Application.html:11 @@ -816,7 +806,7 @@ msgstr "Antrag Nr." msgid "Status" msgstr "Status" -#: application/views.py:781 application/templates/application/view.html:217 +#: application/views.py:782 application/templates/application/view.html:217 #: application/templates/application/view.html:247 config/models.py:131 #: config/templates/config/version.html:5 #: config/templates/config/version.html:8 @@ -824,12 +814,12 @@ msgstr "Status" msgid "Version" msgstr "Version" -#: application/views.py:791 application/templates/application/view.html:47 -#: assignment/views.py:395 +#: application/views.py:792 application/templates/application/view.html:47 +#: assignment/views.py:398 msgid "Vote results" msgstr "Abstimmungsergebnis" -#: application/views.py:797 +#: application/views.py:798 #: application/templates/application/base_application.html:55 #: application/templates/application/poll_view.html:8 #: application/templates/application/poll_view.html:13 @@ -839,25 +829,25 @@ msgstr "Abstimmungsergebnis" msgid "Vote" msgstr "Abstimmung" -#: application/views.py:798 application/views.py:851 +#: application/views.py:799 application/views.py:852 #: application/templates/application/view.html:84 -#: application/templates/projector/Application.html:39 assignment/views.py:562 +#: application/templates/projector/Application.html:39 assignment/views.py:565 #: assignment/templates/assignment/view.html:158 #: assignment/templates/projector/Assignment.html:80 msgid "Abstention" msgstr "Enthaltung" -#: application/views.py:798 application/templates/application/view.html:85 +#: application/views.py:799 application/templates/application/view.html:85 #: application/templates/projector/Application.html:40 #: assignment/templates/assignment/view.html:180 #: assignment/templates/projector/Assignment.html:101 msgid "Invalid" msgstr "Ungültig" -#: application/views.py:798 +#: application/views.py:799 #: application/templates/application/poll_view.html:35 #: application/templates/application/view.html:87 -#: application/templates/projector/Application.html:42 assignment/views.py:446 +#: application/templates/projector/Application.html:42 assignment/views.py:449 #: assignment/templates/assignment/poll_view.html:45 #: assignment/templates/assignment/view.html:192 #: assignment/templates/assignment/view.html:197 @@ -866,21 +856,21 @@ msgstr "Ungültig" msgid "Votes cast" msgstr "Abgegebene Stimmen" -#: application/views.py:831 +#: application/views.py:832 msgid "Poll" msgstr "Abstimmung" -#: application/views.py:845 +#: application/views.py:846 #, python-format msgid "Application No. %s" msgstr "Antrag Nr. %s" -#: application/views.py:847 +#: application/views.py:848 #, python-format msgid "%d. Vote" msgstr "%d. Abstimmung" -#: application/views.py:904 +#: application/views.py:905 msgid "Motion settings successfully saved." msgstr "Antrags-Einstellungen wurden erfolgreich gespeichert." @@ -1043,11 +1033,11 @@ msgid "Option" msgstr "Wahlmöglichkeit" #: application/templates/application/poll_view.html:22 -#: assignment/models.py:263 +#: assignment/models.py:282 msgid "Votes" msgstr "Stimmen" -#: application/templates/application/poll_view.html:31 assignment/views.py:439 +#: application/templates/application/poll_view.html:31 assignment/views.py:442 #: assignment/templates/assignment/poll_view.html:35 #: assignment/templates/assignment/view.html:175 #: assignment/templates/projector/Assignment.html:97 @@ -1199,7 +1189,7 @@ msgstr "Abstimmungsergebnis" msgid "No poll results available." msgstr "Keine Abstimmungen vorhanden." -#: assignment/forms.py:24 assignment/models.py:53 assignment/views.py:368 +#: assignment/forms.py:24 assignment/models.py:54 assignment/views.py:371 #: assignment/templates/assignment/view.html:13 #: assignment/templates/projector/Assignment.html:21 msgid "Number of available posts" @@ -1238,165 +1228,170 @@ msgstr "Eine Stimme pro Kandidat/in." msgid "Always Yes-No-Abstain per candidate." msgstr "Ja, Nein, Enthaltung pro Kandidat/in." -#: assignment/models.py:44 assignment/templates/assignment/overview.html:15 +#: assignment/models.py:45 assignment/templates/assignment/overview.html:15 #: assignment/templates/assignment/view.html:23 msgid "Searching for candidates" msgstr "Auf Kandidatensuche" -#: assignment/models.py:45 assignment/templates/assignment/overview.html:16 +#: assignment/models.py:46 assignment/templates/assignment/overview.html:16 #: assignment/templates/assignment/view.html:25 msgid "Voting" msgstr "Im Wahlvorgang" -#: assignment/models.py:46 assignment/templates/assignment/overview.html:17 +#: assignment/models.py:47 assignment/templates/assignment/overview.html:17 #: assignment/templates/assignment/view.html:27 msgid "Finished" msgstr "Abgeschlossen" -#: assignment/models.py:49 +#: assignment/models.py:50 msgid "Name" msgstr "Name" -#: assignment/models.py:51 +#: assignment/models.py:52 msgid "Description" msgstr "Beschreibung" -#: assignment/models.py:55 +#: assignment/models.py:56 msgid "Comment on the ballot paper" msgstr "Kommentar für den Stimmzettel" -#: assignment/models.py:67 +#: assignment/models.py:68 #, python-format msgid "The assignment status is already %s." msgstr "Der Wahlstatus ist bereits %s." -#: assignment/models.py:79 +#: assignment/models.py:82 #, python-format msgid "%s is already a candidate." msgstr "%s ist bereits ein/e Kandidat/in." -#: assignment/models.py:81 assignment/views.py:189 +#: assignment/models.py:84 assignment/views.py:192 msgid "The candidate list is already closed." msgstr "Die Kandidatenliste ist bereits geschlossen." -#: assignment/models.py:92 +#: assignment/models.py:90 +#, python-format +msgid "%s does not want to be a candidate." +msgstr "%s möchte nicht kandidieren." + +#: assignment/models.py:110 #, python-format msgid "%s is no candidate" msgstr "%s ist kein/e Kandidat/in" -#: assignment/models.py:214 +#: assignment/models.py:233 msgid "Can see assignment" msgstr "Darf Wahlen sehen" -#: assignment/models.py:216 +#: assignment/models.py:235 msgid "Can nominate another person" msgstr "Darf andere Personen für Wahlen vorschlagen" -#: assignment/models.py:217 +#: assignment/models.py:236 msgid "Can nominate themselves" msgstr "Darf selbst für Wahlen kandidieren" -#: assignment/models.py:218 +#: assignment/models.py:237 msgid "Can manage assignment" msgstr "Darf Wahlen verwalten" -#: assignment/models.py:280 +#: assignment/models.py:299 #, python-format msgid "Ballot %d" msgstr "Wahlgang %d" -#: assignment/models.py:289 assignment/views.py:325 assignment/views.py:648 +#: assignment/models.py:308 assignment/views.py:328 assignment/views.py:651 #: assignment/templates/assignment/base_assignment.html:14 #: assignment/templates/assignment/overview.html:6 #: assignment/templates/assignment/overview.html:9 msgid "Elections" msgstr "Wahlen" -#: assignment/views.py:84 +#: assignment/views.py:88 #, python-format msgid "Candidate %s was nominated successfully." msgstr "Kandidat/in %s wurde erfolgreich vorgeschlagen." -#: assignment/views.py:125 +#: assignment/views.py:128 msgid "New election was successfully created." msgstr "Neue Wahl wurde erfolgreich angelegt." -#: assignment/views.py:127 +#: assignment/views.py:130 msgid "Election was successfully modified." msgstr "Wahl wurde erfolgreich geändert." -#: assignment/views.py:152 +#: assignment/views.py:155 #, python-format msgid "Election %s was successfully deleted." msgstr "Wahl %s wurde erfolgreich gelöscht." -#: assignment/views.py:165 +#: assignment/views.py:168 #, python-format msgid "Election status was set to: %s." msgstr "Wahlstatus wurde gesetzt auf: %s." -#: assignment/views.py:176 +#: assignment/views.py:179 msgid "You have set your candidature successfully." msgstr "Sie haben Ihre Kandidatur erfolgreich gesetzt." -#: assignment/views.py:193 +#: assignment/views.py:196 msgid "You have withdrawn your candidature successfully." msgstr "Sie haben Ihre Kandidatur erfolgreich zurückgezogen." -#: assignment/views.py:208 +#: assignment/views.py:211 #, python-format msgid "Candidate %s was withdrawn successfully." msgstr "Die Kandidatur von %s wurde erfolgreich zurückgezogen." -#: assignment/views.py:211 +#: assignment/views.py:214 #, python-format msgid "Do you really want to withdraw %s from the election?" msgstr "Soll %s wirklich von der Wahl zurückgezogen werden?" -#: assignment/views.py:226 +#: assignment/views.py:229 msgid "New ballot was successfully created." msgstr "Neuer Wahlgang erfolgreich angelegt." -#: assignment/views.py:258 +#: assignment/views.py:261 #, python-format msgid "Ballot ID %d does not exist." msgstr "Wahlgang-ID %d existiert nicht." -#: assignment/views.py:265 +#: assignment/views.py:268 msgid "Ballot successfully published." msgstr "Wahlgang wurde erfolgreich veröffentlicht." -#: assignment/views.py:267 +#: assignment/views.py:270 msgid "Ballot successfully unpublished." msgstr "Wahlgang wurde erfolgreich unveröffentlicht." -#: assignment/views.py:280 +#: assignment/views.py:283 msgid "not elected" msgstr "nicht gewählt" -#: assignment/views.py:283 assignment/views.py:466 +#: assignment/views.py:286 assignment/views.py:469 msgid "elected" msgstr "gewählt" -#: assignment/views.py:311 +#: assignment/views.py:314 msgid "Ballot was successfully deleted." msgstr "Abstimmung wurde erfolgreich gelöscht." -#: assignment/views.py:322 +#: assignment/views.py:325 msgid "Assignment" msgstr "Wahl" -#: assignment/views.py:343 assignment/templates/assignment/overview.html:53 +#: assignment/views.py:346 assignment/templates/assignment/overview.html:53 #: assignment/templates/assignment/widget.html:23 msgid "No assignments available." msgstr "Keine Wahlen vorhanden." -#: assignment/views.py:362 +#: assignment/views.py:365 #, python-format msgid "Election: %s" msgstr "Wahlen: %s" -#: assignment/views.py:374 assignment/views.py:407 +#: assignment/views.py:377 assignment/views.py:410 #: assignment/templates/assignment/overview.html:26 #: assignment/templates/assignment/poll_view.html:18 #: assignment/templates/assignment/view.html:36 @@ -1406,7 +1401,7 @@ msgstr "Wahlen: %s" msgid "Candidates" msgstr "Kandidaten/innen" -#: assignment/views.py:399 +#: assignment/views.py:402 #: assignment/templates/assignment/base_assignment.html:71 #: assignment/templates/assignment/poll_view.html:5 #: assignment/templates/assignment/poll_view.html:8 @@ -1416,11 +1411,11 @@ msgstr "Kandidaten/innen" msgid "ballot" msgstr "Wahlgang" -#: assignment/views.py:402 +#: assignment/views.py:405 msgid "ballots" msgstr "Wahlgänge" -#: assignment/views.py:428 +#: assignment/views.py:431 #, python-format msgid "" "Y: %(YES)s\n" @@ -1431,7 +1426,7 @@ msgstr "" "N: %(NO)s\n" "E: %(ABSTAIN)s" -#: assignment/views.py:505 assignment/views.py:521 +#: assignment/views.py:508 assignment/views.py:524 #: assignment/templates/assignment/overview.html:25 #: assignment/templates/assignment/poll_view.html:5 #: assignment/templates/assignment/view.html:6 @@ -1439,28 +1434,28 @@ msgstr "" msgid "Election" msgstr "Wahl" -#: assignment/views.py:527 +#: assignment/views.py:530 #, python-format msgid "%d. ballot" msgstr "%d. Wahlgang" -#: assignment/views.py:528 +#: assignment/views.py:531 #, python-format msgid "%d candidate" msgid_plural "%d candidates" msgstr[0] "%d Kandidat/in" msgstr[1] "%d Kandidaten/innen" -#: assignment/views.py:530 +#: assignment/views.py:533 #, python-format msgid "%d available posts" msgstr "%d verfügbare Posten" -#: assignment/views.py:641 +#: assignment/views.py:644 msgid "Election settings successfully saved." msgstr "Wahl-Einstellungen wurden erfolgreich gespeichert." -#: assignment/views.py:660 +#: assignment/views.py:664 msgid "Assignments" msgstr "Wahlen" @@ -1600,7 +1595,7 @@ msgstr "Veranstalter" msgid "Allow access for anonymous guest users" msgstr "Erlaube Zugriff für anonyme Gast-Nutzer" -#: config/forms.py:67 participant/forms.py:128 +#: config/forms.py:67 participant/forms.py:114 msgid "Welcome text" msgstr "Willkommenstext" @@ -1666,50 +1661,34 @@ msgstr "System" msgid "Participant" msgstr "Teilnehmer" -#: participant/forms.py:26 participant/forms.py:40 +#: participant/forms.py:26 #: participant/templates/participant/group_overview.html:6 #: participant/templates/participant/group_overview.html:9 msgid "User groups" msgstr "Benutzerrollen" -#: participant/forms.py:27 participant/forms.py:41 -#: participant/templates/participant/overview.html:53 projector/models.py:65 -msgid "Active" -msgstr "Aktiv" - -#: participant/forms.py:37 -msgid "First name" -msgstr "Vorname" - -#: participant/forms.py:38 -msgid "Last name" -msgstr "Nachname" - -#: participant/forms.py:59 +#: participant/forms.py:44 msgid "Persmissions" msgstr "Rechte" -#: participant/forms.py:62 -#, fuzzy +#: participant/forms.py:47 msgid "Users" -msgstr "Nutzername: %s" +msgstr "Benutzer" -#: participant/forms.py:98 -#, fuzzy +#: participant/forms.py:83 msgid "You can not edit the name for the anonymous user" -msgstr "" -"Sie dürfen diesen Antrag nicht bearbeiten. Sie sind nicht der Antragsteller" +msgstr "Sie dürfen den Namen für Anonymous nicht bearbeiten." -#: participant/forms.py:102 +#: participant/forms.py:87 #, python-format msgid "Group name \"%s\" is reserved for internal use." msgstr "Der Gruppenname \"%s\" ist für interne Verwendung reserviert." -#: participant/forms.py:123 +#: participant/forms.py:109 msgid "System URL" msgstr "System URL" -#: participant/forms.py:124 participant/forms.py:129 +#: participant/forms.py:110 participant/forms.py:115 msgid "Printed in PDF of first time passwords only." msgstr "Erscheint nur im PDF der Erst-Passwörter" @@ -1740,12 +1719,11 @@ msgstr "Gast" #: participant/models.py:40 participant/templates/participant/overview.html:30 #: participant/templates/participant/overview.html:68 msgid "Category" -msgstr "" +msgstr "Kategorie" #: participant/models.py:41 -#, fuzzy msgid "Will be shown behind the name." -msgstr "Hinter dem Namen angezeigt." +msgstr "Wird nach dem Namen angezeigt." #: participant/models.py:44 participant/templates/participant/overview.html:24 msgid "Gender" @@ -1759,7 +1737,7 @@ msgstr "Nur zum Filtern der Benutzerliste." msgid "Typ" msgstr "Typ" -#: participant/models.py:49 participant/views.py:215 +#: participant/models.py:49 participant/views.py:216 #: participant/templates/participant/overview.html:45 #: participant/templates/participant/overview.html:70 msgid "Committee" @@ -1770,9 +1748,8 @@ msgid "Only for notes." msgstr "Nur für Notizen." #: participant/models.py:56 -#, fuzzy msgid "Default password" -msgstr "Erst-Passwort" +msgstr "Vorgegebenes Passwort" #: participant/models.py:98 msgid "Can see participant" @@ -1782,100 +1759,99 @@ msgstr "Darf die Teilnehmer/inen sehen" msgid "Can manage participant" msgstr "Darf die Teilnehmer/inen verwalten" -#: participant/views.py:210 +#: participant/views.py:211 msgid "Participant-list" msgstr "Teilnehmerliste" -#: participant/views.py:211 +#: participant/views.py:212 msgid "List of Participants" msgstr "Teilnehmerliste" -#: participant/views.py:214 participant/templates/participant/overview.html:67 +#: participant/views.py:215 participant/templates/participant/overview.html:67 msgid "Last Name" msgstr "Nachname" -#: participant/views.py:214 participant/templates/participant/overview.html:66 +#: participant/views.py:215 participant/templates/participant/overview.html:66 msgid "First Name" msgstr "Vorname" -#: participant/views.py:214 +#: participant/views.py:215 msgid "Group" msgstr "Gruppe" -#: participant/views.py:214 participant/templates/participant/overview.html:37 +#: participant/views.py:215 participant/templates/participant/overview.html:37 #: participant/templates/participant/overview.html:69 msgid "Type" msgstr "Typ" -#: participant/views.py:243 +#: participant/views.py:244 msgid "Participant-passwords" msgstr "Teilnehmer-Passwoerter" -#: participant/views.py:261 +#: participant/views.py:262 msgid "Account for OpenSlides" msgstr "Zugang für OpenSlides" -#: participant/views.py:263 +#: participant/views.py:264 #, python-format msgid "for %s" msgstr "für %s" -#: participant/views.py:266 +#: participant/views.py:267 #, python-format msgid "User: %s" msgstr "Nutzername: %s" -#: participant/views.py:270 +#: participant/views.py:271 #, python-format msgid "Password: %s" msgstr "Passwort: %s" -#: participant/views.py:275 +#: participant/views.py:276 #, python-format msgid "URL: %s" msgstr "URL: %s" -#: participant/views.py:317 +#: participant/views.py:318 #, python-format msgid "%d new participants were successfully imported." msgstr "%d neue Teilnehmer/innen wurden erfolgreich importiert." -#: participant/views.py:328 -#, fuzzy +#: participant/views.py:329 msgid "Do you really want to reset the password?" -msgstr "Soll das Passwort für %s wirklich zurückgesetzt werden?" +msgstr "Soll das Passwort wirklich zurückgesetzt werden?" -#: participant/views.py:344 -#, fuzzy, python-format +#: participant/views.py:345 +#, python-format msgid "The Password for %s was successfully reset." -msgstr "Das Passwort für %s wurde erfolgreich zurückgesetzt." +msgstr "Das Passwort für %s wurde erfolgreich zurückgesetzt." -#: participant/views.py:423 +#: participant/views.py:424 msgid "Participants settings successfully saved." msgstr "Teilnehmer/innen-Einstellungen wurden erfolgreich gespeichert." -#: participant/views.py:433 -#, fuzzy, python-format +#: participant/views.py:434 +#, python-format msgid "" "Installation was successfully! Use %(user)s (password: %(password)s) for " "first login.
Important: Please change the password after " "first login! Otherwise this message still appears for everyone and could be " "a security risk." msgstr "" -"Die Installation war erfolgreich! Verwende %(user)s (passwort: %(password)s) " -"für die erste Anmeldung.
Wichtig: Ändere das Passwort " -"nach der ersten Anmeldung! Anderenfalls erscheint diese Meldung weiterhin " -"für jeden und ist ein Sicherheitsrisiko." +"Die Installation war erfolgreich! Verwenden Sie %(user)s (Passwort: " +"%(password)s) für die erste Anmeldung.
Wichtig: Ändern " +"Sie das Passwort nach der ersten Anmeldung! Anderenfalls erscheint diese " +"Meldung weiterhin für alle und ist ein Sicherheitsrisiko." -#: participant/views.py:456 +#: participant/views.py:457 msgid "User settings successfully saved." msgstr "Nutzereinstellungen wurden erfolgreich gespeichert." -#: participant/views.py:478 +#: participant/views.py:479 msgid "Password successfully changed." msgstr "Password wurde erfolgreich geändert." -#: participant/views.py:496 +#: participant/views.py:497 #: participant/templates/participant/base_participant.html:12 #: participant/templates/participant/overview.html:7 #: participant/templates/participant/overview.html:18 @@ -1992,6 +1968,10 @@ msgstr "Weiter als Gast" msgid "Not specified" msgstr "Nicht angegeben" +#: participant/templates/participant/overview.html:53 projector/models.py:67 +msgid "Active" +msgstr "Aktiv" + #: participant/templates/participant/overview.html:54 msgid "Inactive" msgstr "Inaktiv" @@ -2015,14 +1995,12 @@ msgid "Delete participant" msgstr "Teilnehmer/in löschen" #: participant/templates/participant/overview.html:99 -#, fuzzy msgid "Change status to inactive" -msgstr "Status ändern (aktiv/inaktiv)" +msgstr "Status ändern auf inaktiv" #: participant/templates/participant/overview.html:102 -#, fuzzy msgid "Change status to active" -msgstr "Status ändern (aktiv/inaktiv)" +msgstr "Status ändern auf aktiv" #: participant/templates/participant/overview.html:111 msgid "No participants available." @@ -2033,7 +2011,7 @@ msgstr "Keine Teilnehmer/innen vorhanden." #: participant/templates/participant/password_change.html:16 #: participant/templates/participant/settings.html:11 msgid "Password Settings" -msgstr "Passwort Einstellungen" +msgstr "Passwort-Einstellungen" #: participant/templates/participant/password_change.html:8 #: participant/templates/participant/settings.html:8 templates/base.html:29 @@ -2055,17 +2033,40 @@ msgstr "Ungültige Stimmen" msgid "votes" msgstr "Stimmen" -#: projector/models.py:52 +#: projector/models.py:53 msgid "Can manage the projector" msgstr "Darf den Projektor steuern" -#: projector/models.py:53 -msgid "Can see projector" +#: projector/models.py:54 +msgid "Can see the projector" msgstr "Darf den Projektor sehen" -#: projector/views.py:342 projector/templates/projector/base_projector.html:7 -#: projector/templates/projector/base_projector.html:11 -#: projector/templates/projector/control.html:17 +#: projector/models.py:55 +msgid "Can see the dashboard" +msgstr "Darf das Dashboard sehen" + +#: projector/views.py:184 +msgid "Errors in the form" +msgstr "Fehler im Formular" + +#: projector/views.py:360 projector/templates/projector/dashboard.html:17 +msgid "Dashboard" +msgstr "Dashboard" + +#: projector/views.py:377 +msgid "Projector live view" +msgstr "Projektor-Live-Ansicht" + +#: projector/views.py:403 +msgid "Overlays" +msgstr "Einblendungen" + +#: projector/views.py:416 +msgid "Custom Slides" +msgstr "Benutzerdefinierte Folien" + +#: projector/templates/projector/base_projector.html:7 +#: projector/templates/projector/base_projector.html:12 msgid "Projector" msgstr "Projektor" @@ -2073,48 +2074,18 @@ msgstr "Projektor" msgid "Overview" msgstr "Übersicht" -#: projector/templates/projector/control.html:20 -msgid "Adjust projector view" -msgstr "Projektor-Ansicht anpassen" +#: projector/templates/projector/base_projector.html:18 +#: projector/templates/projector/select_widgets.html:5 +#: projector/templates/projector/select_widgets.html:8 +msgid "Select widgets" +msgstr "Widgets auswählen" -#: projector/templates/projector/control.html:21 -msgid "Zoom in" -msgstr "Vergrößern" - -#: projector/templates/projector/control.html:23 -msgid "Zoom out" -msgstr "Verkleinern" - -#: projector/templates/projector/control.html:25 -msgid "Scroll text up" -msgstr "Text nach oben scrollen" - -#: projector/templates/projector/control.html:27 -msgid "Scroll text down" -msgstr "Text nach unten scrollen" - -#: projector/templates/projector/control.html:29 -msgid "Reset projector view" -msgstr "Projektor-Ansicht zurücksetzen" - -#: projector/templates/projector/control.html:50 -msgid "Projector Live View" -msgstr "Projektor-Live-Ansicht" - -#: projector/templates/projector/control.html:53 -msgid "Open Projector view" -msgstr "Projektor-Ansicht öffnen" - -#: projector/templates/projector/control.html:64 -msgid "Overlays" -msgstr "Einblendungen" - -#: projector/templates/projector/control.html:94 -msgid "Custom slides" -msgstr "Benutzerdefinierte Folien" +#: projector/templates/projector/base_projector.html:22 +#: templates/front_page.html:25 +msgid "Projector view" +msgstr "Projektor-Ansicht" #: projector/templates/projector/control_countdown.html:6 -msgctxt "seconds" msgid "s" msgstr "s" @@ -2135,22 +2106,50 @@ msgstr "Countdown starten" msgid "Stop countdown" msgstr "Countdown stoppen" -#: projector/templates/projector/control_overlay_message.html:10 +#: projector/templates/projector/control_overlay_message.html:11 msgid "Clean message" msgstr "Message leeren" +#: projector/templates/projector/custom_slide_widget.html:14 +msgid "Welcome Page" +msgstr "Willkommensseite" + +#: projector/templates/projector/custom_slide_widget.html:41 +msgid "New slide" +msgstr "Neue Folie" + +#: projector/templates/projector/dashboard.html:21 +msgid "Adjust projector view" +msgstr "Projektor-Ansicht anpassen" + +#: projector/templates/projector/dashboard.html:22 +msgid "Zoom in" +msgstr "Vergrößern" + +#: projector/templates/projector/dashboard.html:25 +msgid "Zoom out" +msgstr "Verkleinern" + +#: projector/templates/projector/dashboard.html:28 +msgid "Scroll text up" +msgstr "Text nach oben scrollen" + +#: projector/templates/projector/dashboard.html:31 +msgid "Scroll text down" +msgstr "Text nach unten scrollen" + +#: projector/templates/projector/dashboard.html:34 +msgid "Reset projector view" +msgstr "Projektor-Ansicht zurücksetzen" + #: projector/templates/projector/new.html:6 #: projector/templates/projector/new.html:9 msgid "Custom slide" msgstr "Benutzerdefinierte Folie" -#: projector/templates/projector/widget.html:14 -msgid "Welcome Page" -msgstr "Willkommensseite" - -#: projector/templates/projector/widget.html:41 -msgid "New slide" -msgstr "Neue Folie" +#: projector/templates/projector/select_widgets.html:17 +msgid "No widgets available" +msgstr "Keine Widgets vorhanden." #: templates/404.html:7 msgid "Page not found." @@ -2198,11 +2197,11 @@ msgstr "Bedaure, Sie haben keine Berechtigung diese Seite zu sehen." #: utils/views.py:109 msgid "Are you sure?" -msgstr "" +msgstr "Sind Sie sicher?" #: utils/views.py:110 msgid "Thank you for your answer" -msgstr "" +msgstr "Danke für Ihre Antwort" #: utils/views.py:232 #, python-format @@ -2226,100 +2225,3 @@ msgstr "undefinierter-dateiname" #: utils/jsonfield/fields.py:21 msgid "Enter valid JSON" msgstr "Gebe valides JSON ein" - -#~ msgid "" -#~ "The import function is available for the admin (without user profile) " -#~ "only." -#~ msgstr "" -#~ "Die Importfunktion ist nur für den superuser (ohne Nutzerprofil) " -#~ "verfügbar." - -#~ msgid "You can't candidate. Your user account is only for administration." -#~ msgstr "" -#~ "Sie können nicht kandidieren. Ihr Nutzerkonto ist nur zur Administration." - -#~ msgid "Keep motions, try to reassign submitter" -#~ msgstr "Anträge beibehalten, versuchen Antragssteller erneut zuzuweisen" - -#~ msgid "Keep motions, set status to \"needs review\"" -#~ msgstr "Anträge beibehalten, Status auf \"Benötigt Review\" setzen" - -#~ msgid "Discard motions" -#~ msgstr "Alle Anträge löschen" - -#~ msgid "For existing motions" -#~ msgstr "Bei existierenden Anträgen" - -#~ msgid "New participant was successfully created." -#~ msgstr "Neue/r Teilnehmer/in wurde erfolgreich angelegt." - -#~ msgid "Participant was successfully modified." -#~ msgstr "Teilnehmer/in wurde erfolgreich geändert." - -#~ msgid "Participant %s was successfully deleted." -#~ msgstr "Teilnehmer/in %s wurde erfolgreich gelöscht." - -#~ msgid "Participant ID %d does not exist." -#~ msgstr "Teilnehmer/in ID %d existiert nicht." - -#~ msgid "%s is now present." -#~ msgstr "%s is jetzt anwesend." - -#~ msgid "%s is now absent." -#~ msgstr "%s ist jetzt abwesend." - -#~ msgid "New group was successfully created." -#~ msgstr "Neue Gruppe wurde erfolgreich angelegt." - -#~ msgid "Group was successfully modified." -#~ msgstr "Gruppe wurde erfolgreich geändert." - -#~ msgid "Group %s was successfully deleted." -#~ msgstr "Gruppe %s wurde erfolgreich gelöscht." - -#~ msgid "Supporters removed after user import." -#~ msgstr "Unterstützer/innen nach Benutzerimport zurückgesetzt." - -#~ msgid "Reassigned to \"%s\" after (re)importing users." -#~ msgstr "Nach Benutzerimport erneut \"%s\" zugeordnet." - -#~ msgid "Could not reassing motion %d - object not found!" -#~ msgstr "" -#~ "Antrag %d konnte nicht neu zugewiesen werden - Das Objekt wurde nicht " -#~ "gefunden!" - -#~ msgid "%d motion could not be reassigned and needs a review!" -#~ msgid_plural "%d motions could not be reassigned and need a review!" -#~ msgstr[0] "" -#~ "%d Antrag konnte nicht neu zugewiesen werden and benötigt ein Review!" -#~ msgstr[1] "" -#~ "%d Anträge konnten nicht neu zugewiesen werden und benötigen ein Review!" - -#~ msgid "%d motion was successfully reassigned." -#~ msgid_plural "%d motions were successfully reassigned." -#~ msgstr[0] "%d Antrag wurde erfolgreich neu zugewiesen." -#~ msgstr[1] "%d Anträge wurden erfolgreich neu zugewiesen." - -#~ msgid "%d motion was discarded." -#~ msgid_plural "%d motions were discarded." -#~ msgstr[0] "%d Antrag wurde verworfen." -#~ msgstr[1] "%d Anträge wurden verworfen." - -#~ msgid "" -#~ "Attention: All existing participants will be removed if you import new " -#~ "participants." -#~ msgstr "" -#~ "Achtung: Alle existierenden Teilnehmer/innen werden gelöscht, wenn Sie " -#~ "neue Teilnehmer/innen importieren." - -#~ msgid "Attention: Supporters from all existing motions will be removed." -#~ msgstr "" -#~ "Achtung: Alle Unterstützer/innen werden von existiernden Anträgen " -#~ "gelöscht." - -#~ msgid "" -#~ "Attention: Motions which can't be mapped to new users will be set to " -#~ "'Needs Review'." -#~ msgstr "" -#~ "Achtung: Anträge welche keinem Nutzer zugeordnet werden können bekommen " -#~ "automatisch den Status \"Benötigt Review\"." diff --git a/openslides/projector/views.py b/openslides/projector/views.py index 59b660e2b..862044b97 100644 --- a/openslides/projector/views.py +++ b/openslides/projector/views.py @@ -400,7 +400,7 @@ def get_widgets(request): context.update(csrf(request)) widgets.append(Widget( name='overlays', - display_name=_('Manage Overlays'), + display_name=_('Overlays'), template='projector/overlay_widget.html', permission_required='projector.can_manage_projector', default_column=2, From 760f8e042eff2b9f99a56574e7b2b989b79a6d6d Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Wed, 12 Sep 2012 10:17:51 +0200 Subject: [PATCH 008/222] some fixes --- openslides/application/models.py | 6 +++--- openslides/application/views.py | 6 +++--- openslides/assignment/models.py | 9 +++++---- openslides/assignment/views.py | 8 ++++---- openslides/participant/forms.py | 2 +- .../participant/templates/participant/overview.html | 2 +- openslides/poll/models.py | 2 +- 7 files changed, 18 insertions(+), 17 deletions(-) diff --git a/openslides/application/models.py b/openslides/application/models.py index 4c06b55a6..3a4e901be 100644 --- a/openslides/application/models.py +++ b/openslides/application/models.py @@ -264,7 +264,7 @@ class Application(models.Model, SlideMixin): ApplicationSupporter(application=self, person=person).save() self.writelog(_("Supporter: +%s") % (person)) - def unsupport(self, user): + def unsupport(self, person): """ remove a supporter from the list of supporters of the application """ @@ -272,11 +272,11 @@ class Application(models.Model, SlideMixin): # TODO: Use own Exception raise NameError('This application is already permitted.') try: - object = self.applicationsupporter_set.get(user=user).delete() + object = self.applicationsupporter_set.get(person=person).delete() except ApplicationSupporter.DoesNotExist: pass else: - self.writelog(_("Supporter: -%s") % (user)) + self.writelog(_("Supporter: -%s") % (person)) def set_number(self, number=None, user=None): """ diff --git a/openslides/application/views.py b/openslides/application/views.py index f702eb53b..e8a019875 100644 --- a/openslides/application/views.py +++ b/openslides/application/views.py @@ -264,7 +264,7 @@ def edit(request, application_id=None): if request.user.has_perm('application.can_manage_application'): messages.warning(request, _("Attention: Do you really want to edit this motion? The supporters will not be removed automatically because you can manage motions. Please check if the supports are valid after your changing!")) else: - messages.warning(request, _("Attention: Do you really want to edit this motion? All %s supporters will be removed! Try to convince the supporters again.") % application.supporter.count() ) + messages.warning(request, _("Attention: Do you really want to edit this motion? All %s supporters will be removed! Try to convince the supporters again.") % application.count_supporters() ) initial = {'title': application.title, 'text': application.text, 'reason': application.reason} @@ -372,7 +372,7 @@ def support(request, application_id): support an application. """ try: - Application.objects.get(pk=application_id).support(user=request.user) + Application.objects.get(pk=application_id).support(person=request.user) messages.success(request, _("You have support the motion successfully.") ) except Application.DoesNotExist: pass @@ -386,7 +386,7 @@ def unsupport(request, application_id): unsupport an application. """ try: - Application.objects.get(pk=application_id).unsupport(user=request.user) + Application.objects.get(pk=application_id).unsupport(person=request.user) messages.success(request, _("You have unsupport the motion successfully.") ) except Application.DoesNotExist: pass diff --git a/openslides/assignment/models.py b/openslides/assignment/models.py index accfc2105..7b7064ef1 100644 --- a/openslides/assignment/models.py +++ b/openslides/assignment/models.py @@ -131,9 +131,7 @@ class Assignment(models.Model, SlideMixin): def get_participants(self, only_elected=False, only_candidate=False): candidates = self.assignment_candidats.exclude(blocked=True) - if only_elected and only_candidate: - # TODO: Use right Exception - raise Exception("only_elected and only_candidate can not both be Treu") + assert not (only_elected and only_candidate) if only_elected: candidates = candidates.filter(elected=True) @@ -141,8 +139,11 @@ class Assignment(models.Model, SlideMixin): if only_candidate: candidates = candidates.filter(elected=False) + participants = [] for candidate in candidates.all(): - yield candidate.person + participants.append(candidate.person) + return participants + #return candidates.values_list('person', flat=True) def set_elected(self, person, value=True): diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py index 83b5e04c5..5271750c4 100644 --- a/openslides/assignment/views.py +++ b/openslides/assignment/views.py @@ -421,8 +421,8 @@ class AssignmentPDF(PDFView): candidate_string = candidate.user.get_full_name() if candidate in elected_candidates: candidate_string = "* " + candidate_string - if candidate.group: - candidate_string += "\n(%s)" % candidate.group + if candidate.category: + candidate_string += "\n(%s)" % candidate.category row.append(candidate_string) for vote in poll_list: if vote == None: @@ -581,8 +581,8 @@ class AssignmentPollPDF(PDFView): candidate = option.candidate cell.append(Paragraph(circle + candidate.user.get_full_name(), stylesheet['Ballot_option_name'])) - if candidate.group: - cell.append(Paragraph("(%s)" % candidate.group, + if candidate.category: + cell.append(Paragraph("(%s)" % candidate.category, stylesheet['Ballot_option_group_right'])) else: cell.append(Paragraph(" ", diff --git a/openslides/participant/forms.py b/openslides/participant/forms.py index 4fb13a570..aedff5126 100644 --- a/openslides/participant/forms.py +++ b/openslides/participant/forms.py @@ -94,7 +94,7 @@ class GroupForm(forms.ModelForm, CssClassMixin): class UsersettingsForm(forms.ModelForm, CssClassMixin): class Meta: model = User - fields = ('username', 'first_name', 'last_name', 'email') + fields = ('username', 'first_name', 'last_name', 'email', 'gender') class UserImportForm(forms.Form, CssClassMixin): diff --git a/openslides/participant/templates/participant/overview.html b/openslides/participant/templates/participant/overview.html index 3e2762a37..452bdcb53 100644 --- a/openslides/participant/templates/participant/overview.html +++ b/openslides/participant/templates/participant/overview.html @@ -65,7 +65,7 @@ {% trans "First Name" %} {% trans "Last Name" %} - {% trans "Category" %} + {% trans "Category" %} {% trans "Type" %} {% trans "Committee" %} {% if perms.participant.can_manage_participant %} diff --git a/openslides/poll/models.py b/openslides/poll/models.py index add325b66..a38514619 100644 --- a/openslides/poll/models.py +++ b/openslides/poll/models.py @@ -236,7 +236,7 @@ def print_value(value, percent_base=0): elif value == -2: return unicode(_('undocumented')) elif value is None: - return u'' + return unicode(_('undocumented')) if not percent_base: return u'%s' % value From 63835e74439b89cce31aaa581def58815417f1a1 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 13 Sep 2012 11:43:11 +0200 Subject: [PATCH 009/222] fixed application deletion --- openslides/application/views.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/openslides/application/views.py b/openslides/application/views.py index e8a019875..34f47b201 100644 --- a/openslides/application/views.py +++ b/openslides/application/views.py @@ -475,27 +475,6 @@ class ApplicationDelete(DeleteView): else: messages.error(request, _("Invalid request")) - def gen_confirm_form(self, request, message, url): - formbase = '%s
' % (message, url, csrf(request)['csrf_token']) - - if len(self.applications): - for application in self.applications: - formbase += '' % application.id - elif self.object: - formbase += '' % self.object.id - - formbase +='
' % (_("Yes"), _("No")) - messages.warning(request, formbase) - - - def confirm_form(self, request, object, item=None): - self.object = self.get_object() - - if len(self.applications): - self.gen_confirm_form(request, _('Do you really want to delete multiple motions?') % self.object.get_absolute_url('delete')) - else: - self.gen_confirm_form(request, _('Do you really want to delete %s?') % self.object, self.object.get_absolute_url('delete')) - class ViewPoll(PollFormView): permission_required = 'application.can_manage_application' From bcfceccb093df08579b370552b6ae422b57d548a Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 13 Sep 2012 11:50:06 +0200 Subject: [PATCH 010/222] dont use simular passwords in gen_password (no Il10oO) --- openslides/participant/api.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openslides/participant/api.py b/openslides/participant/api.py index 6728016cd..05b5c8bf4 100644 --- a/openslides/participant/api.py +++ b/openslides/participant/api.py @@ -29,11 +29,10 @@ def gen_password(): """ generates a random passwort. """ - chars = string.letters + string.digits - newpassword = '' - for i in range(8): - newpassword += choice(chars) - return newpassword + chars = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789" + size = 8 + + return ''.join([choice(chars) for i in range(size)]) def gen_username(first_name, last_name): From b15d70d13dadf8915338875d4518e8b888457aec Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 13 Sep 2012 11:52:04 +0200 Subject: [PATCH 011/222] typo --- openslides/application/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openslides/application/models.py b/openslides/application/models.py index 3a4e901be..b11eb074b 100644 --- a/openslides/application/models.py +++ b/openslides/application/models.py @@ -598,7 +598,7 @@ class ApplicationPoll(BasePoll, CountInvalid, CountVotesCast): def default_config(sender, key, **kwargs): return { 'application_min_supporters': 0, - 'application_preamble': _('The Assembly may decide,'), + 'application_preamble': _('The assembly may decide,'), 'application_pdf_ballot_papers_selection': 'CUSTOM_NUMBER', 'application_pdf_ballot_papers_number': '8', 'application_pdf_title': _('Motions'), From 48a992119afa44d7f03a926393eb6acd99d3c10a Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 13 Sep 2012 12:09:17 +0200 Subject: [PATCH 012/222] Fixted permissions for editing an application The suppmitter could edit an application after it was finished by manipulating the url --- openslides/application/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openslides/application/views.py b/openslides/application/views.py index 34f47b201..18bef8a1b 100644 --- a/openslides/application/views.py +++ b/openslides/application/views.py @@ -182,8 +182,8 @@ def edit(request, application_id=None): return redirect(reverse('application_overview')) if application_id is not None: application = Application.objects.get(id=application_id) - if not request.user == application.submitter and not is_manager: - messages.error(request, _("You can not edit this motion. You are not the submitter.")) + if not 'edit' in application.get_allowed_actions(request.user): + messages.error(request, _("You can not edit this motion.")) return redirect(reverse('application_view', args=[application.id])) actions = application.get_allowed_actions(user=request.user) else: From 07250033774343177cb16eb9faeac797733374c2 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 13 Sep 2012 12:16:46 +0200 Subject: [PATCH 013/222] clarify the submitter name in the application pdf It was not clear, that the submitter should sign the formular --- openslides/application/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openslides/application/views.py b/openslides/application/views.py index 18bef8a1b..5588f2cee 100644 --- a/openslides/application/views.py +++ b/openslides/application/views.py @@ -715,7 +715,7 @@ class ApplicationPDF(PDFView): if application.status == "pub": cell1b.append(Paragraph("__________________________________________",stylesheet['Signaturefield'])) cell1b.append(Spacer(0,0.1*cm)) - cell1b.append(Paragraph("       "+unicode(application.submitter), stylesheet['Small'])) + cell1b.append(Paragraph(_("Signature: %s") % application.submitter, stylesheet['Small'])) cell1b.append(Spacer(0,0.2*cm)) else: cell1b.append(Paragraph(unicode(application.submitter), stylesheet['Normal'])) From e64f4f5efc96baeb328f7d7c5d8c05a955b1c60c Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 13 Sep 2012 14:59:14 +0200 Subject: [PATCH 014/222] show blocked candidates of an assignment --- openslides/assignment/models.py | 26 +++++++++++++++---- .../assignment/templates/assignment/view.html | 14 ++++++++-- openslides/assignment/views.py | 6 +++-- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/openslides/assignment/models.py b/openslides/assignment/models.py index 7b7064ef1..805913d4e 100644 --- a/openslides/assignment/models.py +++ b/openslides/assignment/models.py @@ -38,6 +38,9 @@ class AssignmentCandidate(models.Model): def __unicode__(self): return unicode(self.person) + class Meta: + unique_together = ("assignment", "person") + class Assignment(models.Model, SlideMixin): prefix = 'assignment' @@ -83,12 +86,13 @@ class Assignment(models.Model, SlideMixin): if not person.has_perm("assignment.can_manage_assignment") and self.status != 'sea': raise NameError(_('The candidate list is already closed.')) candidation = self.assignment_candidats.filter(person=candidate) - if candidation and candidate != person: + if candidation and candidate != person and \ + not person.has_perm("assignment.can_manage_assignment"): # if the candidation is blocked and anotherone tries to run the # candidate raise NameError( _('The %s does not want to be a candidate.') % candidate) - elif candidation and candidate == person: + elif candidation: candidation[0].blocked = False candidation[0].save() else: @@ -98,16 +102,21 @@ class Assignment(models.Model, SlideMixin): """ stop running for a vote """ - if self.is_candidate(candidate): + try: candidation = self.assignment_candidats.get(person=candidate) + except AssignmentCandidate.DoesNotExist: + # TODO: Use an OpenSlides Error + raise Exception(_('%s is no candidate') % candidate) + + if not candidation.blocked: if blocked: candidation.blocked = True candidation.save() else: candidation.delete() else: - # TODO: Use an OpenSlides Error - raise Exception(_('%s is no candidate') % candidate) + candidation.delete() + def is_candidate(self, person): """ @@ -116,6 +125,13 @@ class Assignment(models.Model, SlideMixin): return self.assignment_candidats.filter(person=person) \ .exclude(blocked=True).exists() + def is_blocked(self, person): + """ + return True, if the person is blockt for candidation. + """ + return self.assignment_candidats.filter(person=person) \ + .filter(blocked=True).exists() + @property def assignment_candidats(self): return AssignmentCandidate.objects.filter(assignment=self) diff --git a/openslides/assignment/templates/assignment/view.html b/openslides/assignment/templates/assignment/view.html index fc4feb615..d3414f2a0 100644 --- a/openslides/assignment/templates/assignment/view.html +++ b/openslides/assignment/templates/assignment/view.html @@ -88,8 +88,18 @@ {% endif %} {% endif %} - -


+{% if perms.assignment.can_manage_assignments %} +

{% trans "Blocked Candidates" %}

+
    + {% for candidate in blocked_candidates %} +
  • + {{ candidate }} +
  • + {% empty %} +
  • {% trans "There are no blocked candidates." %}
  • + {% endfor %} +
+{% endif %}

{% trans "Election results" %}

{% if polls.exists %} diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py index 5271750c4..fdd727eda 100644 --- a/openslides/assignment/views.py +++ b/openslides/assignment/views.py @@ -100,13 +100,15 @@ def view(request, assignment_id=None): polls = assignment.poll_set.all() vote_results = assignment.vote_results(only_published=False) + blocked_candidates = [candidate.person for candidate in \ + assignment.assignment_candidats.filter(blocked=True)] return { 'assignment': assignment, + 'blocked_candidates': blocked_candidates, 'form': form, 'vote_results': vote_results, 'polls': polls, - 'user_is_candidate': assignment.is_candidate(request.user) - } + 'user_is_candidate': assignment.is_candidate(request.user)} @permission_required('assignment.can_manage_assignment') From 20ac817d49679d1313f923f39dd49f485cb8d771 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 13 Sep 2012 15:07:24 +0200 Subject: [PATCH 015/222] Fixed error message when delrun after the list is closed --- openslides/assignment/views.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py index fdd727eda..4413a1c05 100644 --- a/openslides/assignment/views.py +++ b/openslides/assignment/views.py @@ -187,15 +187,16 @@ def run(request, assignment_id): @login_required def delrun(request, assignment_id): assignment = Assignment.objects.get(pk=assignment_id) - try: - if assignment.status == 'sea' or user.has_perm("assignment.can_manage_assignment"): + if assignment.status == 'sea' or request.user.has_perm("assignment.can_manage_assignment"): + try: assignment.delrun(request.user, blocked=True) + except Exception, e: + messages.error(request, e) else: - messages.error(request, _('The candidate list is already closed.')) - except Exception, e: - messages.error(request, e) + messages.success(request, _("You have withdrawn your candidature successfully.") ) else: - messages.success(request, _("You have withdrawn your candidature successfully.") ) + messages.error(request, _('The candidate list is already closed.')) + return redirect(reverse('assignment_view', args=[assignment_id])) From ef7deb90c97e23100442c71c0581190f410d0d1a Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 13 Sep 2012 15:19:10 +0200 Subject: [PATCH 016/222] translate agenda hidden filter in js --- openslides/agenda/static/javascript/agenda.js | 2 +- openslides/locale/README.txt | 2 ++ openslides/locale/de/LC_MESSAGES/djangojs.mo | Bin 0 -> 457 bytes openslides/locale/de/LC_MESSAGES/djangojs.po | 23 ++++++++++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 openslides/locale/de/LC_MESSAGES/djangojs.mo create mode 100644 openslides/locale/de/LC_MESSAGES/djangojs.po diff --git a/openslides/agenda/static/javascript/agenda.js b/openslides/agenda/static/javascript/agenda.js index 0b6603c39..b2fe8f14f 100644 --- a/openslides/agenda/static/javascript/agenda.js +++ b/openslides/agenda/static/javascript/agenda.js @@ -24,7 +24,7 @@ function hideClosedSlides(hide) { hideLine($(this)); }); hidden = $('#menu-overview tr:hidden').size(); - $('#hiddencount').text(', davon ' + hidden + ' verborgen.'); + $('#hiddencount').text(interpolate(gettext(', therefrom %s hidden.'), [hidden])); } else { $('#menu-overview tr').show(); $('#hidelink').attr('title','hide'); diff --git a/openslides/locale/README.txt b/openslides/locale/README.txt index 2fc227be8..a54166107 100644 --- a/openslides/locale/README.txt +++ b/openslides/locale/README.txt @@ -6,8 +6,10 @@ Instruction to update translation for OpenSlides: 2. Update the German po file (locale/de/LC_MESSAGES/django.po): $ django-admin.py makemessages -l de + $ django-admin.py makemessages -l de -d djangojs 3. Edit the German po file: locale/de/LC_MESSAGES/django.po + Don't forget the js-file: locale/de/LC_MESSAGES/djangojs.po (Search for "fuzzy" and empty msgstr entries.) 4. Update the German mo file (locale/de/LC_MESSAGES/django.mo): diff --git a/openslides/locale/de/LC_MESSAGES/djangojs.mo b/openslides/locale/de/LC_MESSAGES/djangojs.mo new file mode 100644 index 0000000000000000000000000000000000000000..f25c076679cbc22fe612c25a914c95963639a89f GIT binary patch literal 457 zcmY+A%}xR_5XV=empz*3$-{Us(MWN-nt%%!BVxorKt%6_4!hN*-L!?^gZL!AkI&*P z9Eg+oWoDB9d}MwP_PztMUE-Li5c@=vC~Zg_5ii8^P7q`i4~ZYj$=7`pwpIb3p~aas zb2xR7DJfA`gP}DaIQ6V6**jXNj80%spnlDjLsjBWO0xS!>e$#M5Do`p z*0v}-^{@xwF@ZSZF^lSqUje^K`1M5;M-d6x2$!my{ZCh8aUD2MqS{8+6V9`-724&( z8%uY%PhsInWEz@tq4GQ9GAgPPZ^NF@=|ZHmRASig_B-42c{K{#MtjsW?yDe)$CbY< za-nnsrkSt~ed}%f$m&~Nxpsz@b@bForPBoJ6XnBUzOW)^kH*ej0=ih2t`#?6leW$@ ZoV0+SH^QI-QY?)wzq>>`F*Yq9{0F~+d;b6c literal 0 HcmV?d00001 diff --git a/openslides/locale/de/LC_MESSAGES/djangojs.po b/openslides/locale/de/LC_MESSAGES/djangojs.po new file mode 100644 index 000000000..5b308102e --- /dev/null +++ b/openslides/locale/de/LC_MESSAGES/djangojs.po @@ -0,0 +1,23 @@ +# 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 , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: OpenSlides 1.x\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-08-13 19:14+0200\n" +"PO-Revision-Date: 2012-07-28 11:07+0200\n" +"Last-Translator: Oskar Hahn \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.js:27 +#, c-format +msgid ", therefrom %s hidden." +msgstr ", davon %s verborgen." From d8136045bb7db7214169b35056302392c15b1e52 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 13 Sep 2012 21:33:57 +0200 Subject: [PATCH 017/222] update application pdf --- openslides/application/models.py | 6 +- openslides/application/views.py | 105 +++++++++++++++---------------- 2 files changed, 55 insertions(+), 56 deletions(-) diff --git a/openslides/application/models.py b/openslides/application/models.py index b11eb074b..06ad330bc 100644 --- a/openslides/application/models.py +++ b/openslides/application/models.py @@ -136,11 +136,11 @@ class Application(models.Model, SlideMixin): """ note = [] if self.status == "pub" and not self.enough_supporters: - note.append(_("Searching for supporters.")) + note.append(ugettext("Searching for supporters.")) if self.status == "pub" and self.permitted is None: - note.append(_("Not yet authorized.")) + note.append(ugettext("Not yet authorized.")) elif self.unpermitted_changes and self.permitted: - note.append(_("Not yet authorized changes.")) + note.append(ugettext("Not yet authorized changes.")) return note @property diff --git a/openslides/application/views.py b/openslides/application/views.py index 5588f2cee..35ff3345a 100644 --- a/openslides/application/views.py +++ b/openslides/application/views.py @@ -700,6 +700,9 @@ class ApplicationPDF(PDFView): story = self.get_application(application, story) def get_application(self, application, story): + # Preparing Table + data = [] + # application number if application.number: story.append(Paragraph(_("Motion No.")+" %s" % application.number, stylesheet['Heading1'])) @@ -708,85 +711,81 @@ class ApplicationPDF(PDFView): # submitter cell1a = [] - cell1a.append(Spacer(0,0.2*cm)) + cell1a.append(Spacer(0, 0.2 * cm)) cell1a.append(Paragraph("%s:" % _("Submitter"), stylesheet['Heading4'])) cell1b = [] - cell1b.append(Spacer(0,0.2*cm)) + cell1b.append(Spacer(0, 0.2 * cm)) + cell1b.append(Paragraph("%s" % application.submitter, stylesheet['Normal'])) + data.append([cell1a, cell1b]) + if application.status == "pub": - cell1b.append(Paragraph("__________________________________________",stylesheet['Signaturefield'])) - cell1b.append(Spacer(0,0.1*cm)) - cell1b.append(Paragraph(_("Signature: %s") % application.submitter, stylesheet['Small'])) - cell1b.append(Spacer(0,0.2*cm)) - else: - cell1b.append(Paragraph(unicode(application.submitter), stylesheet['Normal'])) + # Cell for the signature + cell2a = [] + cell2b = [] + cell2a.append(Paragraph("%s:" % _("Signature"), stylesheet['Heading4'])) + cell2b.append(Paragraph("__________________________________________", stylesheet['Signaturefield'])) + cell2b.append(Spacer(0, 0.1 * cm)) + cell2b.append(Spacer(0,0.2*cm)) + data.append([cell2a, cell2b]) # supporters - cell2a = [] - cell2b = [] if config['application_min_supporters']: - - cell2a.append(Paragraph("%s:" % _("Supporters"), stylesheet['Heading4'])) - + cell3a = [] + cell3b = [] + cell3a.append(Paragraph("%s:" % _("Supporters"), stylesheet['Heading4'])) for supporter in application.supporters: - cell2b.append(Paragraph(".  %s" % unicode(supporter), stylesheet['Signaturefield'])) + cell3b.append(Paragraph(".  %s" % supporter, stylesheet['Signaturefield'])) if application.status == "pub": - for x in range(0,application.missing_supporters): - cell2b.append(Paragraph(".  __________________________________________",stylesheet['Signaturefield'])) - cell2b.append(Spacer(0,0.2*cm)) + for x in range(application.missing_supporters): + cell3b.append(Paragraph(".  __________________________________________",stylesheet['Signaturefield'])) + cell3b.append(Spacer(0, 0.2 * cm)) + data.append([cell3a, cell3b]) # status - note = "" - for n in application.notes: - note += "%s " % unicode(n) - cell3a = [] - cell3a.append(Paragraph("%s:" % _("Status"), stylesheet['Heading4'])) - cell3b = [] + cell4a = [] + cell4b = [] + note = " ".join(application.notes) + cell4a.append(Paragraph("%s:" % _("Status"), stylesheet['Heading4'])) if note != "": if application.status == "pub": - cell3b.append(Paragraph(note, stylesheet['Normal'])) + cell4b.append(Paragraph(note, stylesheet['Normal'])) else: - cell3b.append(Paragraph("%s | %s" % (application.get_status_display(), note), stylesheet['Normal'])) + cell4b.append(Paragraph("%s | %s" % (application.get_status_display(), note), stylesheet['Normal'])) else: - cell3b.append(Paragraph("%s" % application.get_status_display(), stylesheet['Normal'])) - - # table - data = [] - data.append([cell1a,cell1b]) - data.append([cell2a,cell2b]) - data.append([cell3a,cell3b]) + cell4b.append(Paragraph("%s" % application.get_status_display(), stylesheet['Normal'])) + data.append([cell4a, cell4b]) # Version number (aid) if application.public_version.aid > 1: - cell4a = [] - cell4a.append(Paragraph("%s:" % _("Version"), stylesheet['Heading4'])) - cell4b = [] - cell4b.append(Paragraph("%s" % application.public_version.aid, stylesheet['Normal'])) - data.append([cell4a,cell4b]) - - poll_results = application.get_poll_results() + cell5a = [] + cell5b = [] + cell5a.append(Paragraph("%s:" % _("Version"), stylesheet['Heading4'])) + cell5b.append(Paragraph("%s" % application.public_version.aid, stylesheet['Normal'])) + data.append([cell5a, cell5b]) # voting results + poll_results = application.get_poll_results() if poll_results: - cell5a = [] - cell5a.append(Paragraph("%s:" % _("Vote results"), stylesheet['Heading4'])) - cell5b = [] + cell6a = [] + cell6a.append(Paragraph("%s:" % _("Vote results"), stylesheet['Heading4'])) + cell6b = [] ballotcounter = 0 for result in poll_results: ballotcounter += 1 if len(poll_results) > 1: - cell5b.append(Paragraph("%s. %s" % (ballotcounter, _("Vote")), stylesheet['Bold'])) - cell5b.append(Paragraph("%s: %s
%s: %s
%s: %s
%s: %s
%s: %s" % (_("Yes"), result[0], _("No"), result[1], _("Abstention"), result[2], _("Invalid"), result[3], _("Votes cast"), result[4]), stylesheet['Normal'])) - cell5b.append(Spacer(0,0.2*cm)) - data.append([cell5a,cell5b]) + cell6b.append(Paragraph("%s. %s" % (ballotcounter, _("Vote")), stylesheet['Bold'])) + cell6b.append(Paragraph("%s: %s
%s: %s
%s: %s
%s: %s
%s: %s" % (_("Yes"), result[0], _("No"), result[1], _("Abstention"), result[2], _("Invalid"), result[3], _("Votes cast"), result[4]), stylesheet['Normal'])) + cell6b.append(Spacer(0, 0.2*cm)) + data.append([cell6a, cell6b]) - t=Table(data) - t._argW[0]=4.5*cm - t._argW[1]=11*cm - t.setStyle(TableStyle([ ('BOX', (0,0), (-1,-1), 1, colors.black), - ('VALIGN', (0,0), (-1,-1), 'TOP'), - ])) + # Creating Table + t = Table(data) + t._argW[0] = 4.5 * cm + t._argW[1] = 11 * cm + t.setStyle(TableStyle([('BOX', (0, 0), (-1, -1), 1, colors.black), + ('VALIGN', (0,0), (-1,-1), 'TOP')])) story.append(t) - story.append(Spacer(0,1*cm)) + story.append(Spacer(0, 1 * cm)) # title story.append(Paragraph(application.public_version.title, stylesheet['Heading3'])) From f0f14861e8b7414c24e6d2e316f9fe9ef3deaf75 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 13 Sep 2012 21:51:50 +0200 Subject: [PATCH 018/222] fixed message for unblocking users --- openslides/assignment/views.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py index 4413a1c05..26a7a0bf5 100644 --- a/openslides/assignment/views.py +++ b/openslides/assignment/views.py @@ -193,7 +193,9 @@ def delrun(request, assignment_id): except Exception, e: messages.error(request, e) else: - messages.success(request, _("You have withdrawn your candidature successfully.") ) + messages.success(request, + _("You have withdrawn your candidature successfully. " + "You can not be nominated by other participants anymore.")) else: messages.error(request, _('The candidate list is already closed.')) @@ -204,6 +206,7 @@ def delrun(request, assignment_id): def delother(request, assignment_id, user_id): assignment = Assignment.objects.get(pk=assignment_id) person = get_person(user_id) + is_blocked = assignment.is_blocked(person) if request.method == 'POST': try: @@ -211,11 +214,17 @@ def delother(request, assignment_id, user_id): except Exception, e: messages.error(request, e) else: - messages.success(request, _("Candidate %s was withdrawn successfully.") % (person)) + if not is_blocked: + message = _("Candidate %s was withdrawn successfully.") % person + else: + message = _("%s was unblocked successfully.") % person + messages.success(request, message) else: - gen_confirm_form(request, - _("Do you really want to withdraw %s from the election?") \ - % person, reverse('assignment_delother', args=[assignment_id, user_id])) + if not is_blocked: + message = _("Do you really want to withdraw %s from the election?") % person + else: + message = _("Do you really want to unblock %s from the election?") % person + gen_confirm_form(request, message, reverse('assignment_delother', args=[assignment_id, user_id])) return redirect(reverse('assignment_view', args=[assignment_id])) From 56e3fe7a37eecd0e6383c990e78bc3e5312fa4c7 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 13 Sep 2012 21:56:50 +0200 Subject: [PATCH 019/222] fix translation --- openslides/agenda/static/javascript/agenda.js | 2 +- openslides/locale/de/LC_MESSAGES/django.mo | Bin 32992 -> 32992 bytes openslides/locale/de/LC_MESSAGES/djangojs.mo | Bin 457 -> 456 bytes openslides/locale/de/LC_MESSAGES/djangojs.po | 4 ++-- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openslides/agenda/static/javascript/agenda.js b/openslides/agenda/static/javascript/agenda.js index b2fe8f14f..538193219 100644 --- a/openslides/agenda/static/javascript/agenda.js +++ b/openslides/agenda/static/javascript/agenda.js @@ -24,7 +24,7 @@ function hideClosedSlides(hide) { hideLine($(this)); }); hidden = $('#menu-overview tr:hidden').size(); - $('#hiddencount').text(interpolate(gettext(', therefrom %s hidden.'), [hidden])); + $('#hiddencount').text(interpolate(gettext(', of which %s hidden.'), [hidden])); } else { $('#menu-overview tr').show(); $('#hidelink').attr('title','hide'); diff --git a/openslides/locale/de/LC_MESSAGES/django.mo b/openslides/locale/de/LC_MESSAGES/django.mo index 8bb0c86f06684bbaef7a6dc8ba7d7421f7d5bc6e..c4e9fae76280e9f976ab620238004b8d575a9d7a 100644 GIT binary patch delta 17 YcmaFR$n>C*X~Q)?CKHRzH~ct^07r!f8~^|S delta 17 YcmaFR$n>C*X~Q)?CS$|RH~ct^07p~@6aWAK diff --git a/openslides/locale/de/LC_MESSAGES/djangojs.mo b/openslides/locale/de/LC_MESSAGES/djangojs.mo index f25c076679cbc22fe612c25a914c95963639a89f..71802e3d7030d139cf602f5cde1b789983a2197c 100644 GIT binary patch delta 80 zcmX@fe1ds`in%BQ14AGXdoeOFqyuRXe-n@mL}0)KrNNYrLVlV;c}8Y(#>AL-E=yfQ PV+A8aD^s(LM_CvFuP6+C delta 81 zcmX@Xe3E&BiiH>h14AGXdoeOFWB_SVAl?jQ0}%rg5TgJcg_4ZaqSUma{M?Dr@mv\n" "Language: de\n" @@ -19,5 +19,5 @@ msgstr "" #: agenda/static/javascript/agenda.js:27 #, c-format -msgid ", therefrom %s hidden." +msgid ", of which %s hidden." msgstr ", davon %s verborgen." From eac23ecd9973b72b6c5d8bdb5bf7244f979026f3 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 13 Sep 2012 22:02:42 +0200 Subject: [PATCH 020/222] remove confusing image --- openslides/application/templates/application/view.html | 3 --- 1 file changed, 3 deletions(-) diff --git a/openslides/application/templates/application/view.html b/openslides/application/templates/application/view.html index d902777b1..bce03af57 100644 --- a/openslides/application/templates/application/view.html +++ b/openslides/application/templates/application/view.html @@ -17,9 +17,6 @@

{% trans "Submitter" %}:

{{ application.submitter }} - {% if user == application.submitter.user %} - - {% endif %} {% if min_supporters > 0 %}

{% trans "Supporters" %}: *

From 77ae543ff201c314e93b96435e758bfd3a52f87d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Fri, 14 Sep 2012 00:21:59 +0200 Subject: [PATCH 021/222] Using Meta Class for ordering assignments by name --- openslides/assignment/models.py | 1 + openslides/assignment/views.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/openslides/assignment/models.py b/openslides/assignment/models.py index 2a15f271f..dcd8a6e15 100644 --- a/openslides/assignment/models.py +++ b/openslides/assignment/models.py @@ -253,6 +253,7 @@ class Assignment(models.Model, SlideMixin): ('can_nominate_self', ugettext_noop("Can nominate themselves")), ('can_manage_assignment', ugettext_noop("Can manage assignment")), ) + ordering = ('name',) register_slidemodel(Assignment) diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py index 26a7a0bf5..2b7ff4a71 100644 --- a/openslides/assignment/views.py +++ b/openslides/assignment/views.py @@ -59,7 +59,7 @@ def get_overview(request): if sort in ['name','status']: query = query.order_by(sort) except KeyError: - query = query.order_by('name') + pass if 'reverse' in request.GET: query = query.reverse() @@ -353,7 +353,7 @@ class AssignmentPDF(PDFView): story.append(Paragraph("%s" % preamble.replace('\r\n', '
'), stylesheet['Paragraph'])) story.append(Spacer(0, 0.75 * cm)) - assignments = Assignment.objects.order_by('name') + assignments = Assignment.objects.all() if not assignments: # No assignments existing story.append(Paragraph(_("No assignments available."), stylesheet['Heading3'])) @@ -675,5 +675,5 @@ def get_widgets(request): Widget( name=_('Assignments'), template='assignment/widget.html', - context={'assignments': Assignment.objects.all().order_by('name')}, + context={'assignments': Assignment.objects.all()}, permission_required='assignment.can_manage_assignment')] From cb3b26c45de218ec75fbfb0432827ab3651ced84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Fri, 14 Sep 2012 01:14:25 +0200 Subject: [PATCH 022/222] Default sorting of applications using Meta Class --- openslides/application/models.py | 1 + openslides/application/views.py | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/openslides/application/models.py b/openslides/application/models.py index 06ad330bc..df1d8195f 100644 --- a/openslides/application/models.py +++ b/openslides/application/models.py @@ -534,6 +534,7 @@ class Application(models.Model, SlideMixin): ('can_support_application', ugettext_noop("Can support motions")), ('can_manage_application', ugettext_noop("Can manage motions")), ) + ordering = ('number',) class AVersion(models.Model): diff --git a/openslides/application/views.py b/openslides/application/views.py index 35ff3345a..ba073bb51 100644 --- a/openslides/application/views.py +++ b/openslides/application/views.py @@ -103,7 +103,7 @@ def overview(request): # limit result to last version of an application query = query.filter(aversion__id__in=[x.last_version.id for x in Application.objects.all()]) else: - query = query.order_by('number') + pass if 'reverse' in sortfilter: query = query.reverse() @@ -681,7 +681,7 @@ class ApplicationPDF(PDFView): if preamble: story.append(Paragraph("%s" % preamble.replace('\r\n','
'), stylesheet['Paragraph'])) story.append(Spacer(0,0.75*cm)) - applications = Application.objects.order_by('number') + applications = Application.objects.all() if not applications: # No applications existing story.append(Paragraph(_("No motions available."), stylesheet['Heading3'])) else: # Print all Applications @@ -899,5 +899,5 @@ def get_widgets(request): Widget( name='applications', template='application/widget.html', - context={'applications': Application.objects.all().order_by('number')}, + context={'applications': Application.objects.all()}, permission_required='application.can_manage_application')] From 811b780fb9ddc3c1a971e6ebd4aad0526235c9bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Fri, 14 Sep 2012 01:52:20 +0200 Subject: [PATCH 023/222] Fix typo TYPE_CHOICE to TYPE_CHOICES --- openslides/participant/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openslides/participant/models.py b/openslides/participant/models.py index b97ed119c..2e2c21ebc 100644 --- a/openslides/participant/models.py +++ b/openslides/participant/models.py @@ -28,7 +28,7 @@ class User(DjangoUser, PersonMixin): ('male', _('Male')), ('female', _('Female')), ) - TYPE_CHOICE = ( + TYPE_CHOICES = ( ('delegate', _('Delegate')), ('observer', _('Observer')), ('staff', _('Staff')), @@ -43,7 +43,7 @@ class User(DjangoUser, PersonMixin): max_length=50, choices=GENDER_CHOICES, blank=True, verbose_name=_("Gender"), help_text=_('Only for filter the userlist.')) type = models.CharField( - max_length=100, choices=TYPE_CHOICE, blank=True, + max_length=100, choices=TYPE_CHOICES, blank=True, verbose_name=_("Typ"), help_text=_('Only for filter the userlist.')) committee = models.CharField( max_length=100, null=True, blank=True, verbose_name=_("Committee"), From f8d3390c78219b280b89325478dc646ed4f29101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Fri, 14 Sep 2012 02:24:02 +0200 Subject: [PATCH 024/222] Docstrings and sorting of Users and Groups in the UsersAndGroupsToPersons class object (was: UsersConnector) --- openslides/participant/models.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/openslides/participant/models.py b/openslides/participant/models.py index 2e2c21ebc..f0b420f05 100644 --- a/openslides/participant/models.py +++ b/openslides/participant/models.py @@ -126,12 +126,16 @@ class Group(DjangoGroup, PersonMixin): return unicode(self.name) -class UsersConnector(object): +class UsersAndGroupsToPersons(object): + """ + Object to send all Users and Groups or a special User or Group to + the Person-API via receice_persons() + """ def __init__(self, person_prefix_filter=None, id_filter=None): self.person_prefix_filter = person_prefix_filter self.id_filter = id_filter - self.users = User.objects.all() - self.groups = Group.objects.filter(group_as_person=True) + self.users = User.objects.all().order_by('last_name') + self.groups = Group.objects.filter(group_as_person=True).order_by('name') def __iter__(self): if (not self.person_prefix_filter or @@ -150,13 +154,17 @@ class UsersConnector(object): for group in self.groups: yield group + # Are the following two lines superfluous? They only return Users not Groups. def __getitem__(self, key): return User.objects.get(pk=key) @receiver(receive_persons, dispatch_uid="participant") def receive_persons(sender, **kwargs): - return UsersConnector(person_prefix_filter=kwargs['person_prefix_filter'], + """ + Answers to the Person-API + """ + return UsersAndGroupsToPersons(person_prefix_filter=kwargs['person_prefix_filter'], id_filter=kwargs['id_filter']) From f41fe87656e09f99c6b8c5aa3531d516f9d9fb85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Fri, 14 Sep 2012 02:40:40 +0200 Subject: [PATCH 025/222] Insert new config var for sorting Users by first_name --- openslides/participant/forms.py | 3 +++ openslides/participant/models.py | 1 + openslides/participant/views.py | 5 ++++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/openslides/participant/forms.py b/openslides/participant/forms.py index aedff5126..4687432fe 100644 --- a/openslides/participant/forms.py +++ b/openslides/participant/forms.py @@ -113,3 +113,6 @@ class ConfigForm(forms.Form, CssClassMixin): required=False, label=_("Welcome text"), help_text=_("Printed in PDF of first time passwords only.")) + participant_sort_users_by_first_name = forms.BooleanField( + required=False, + label=_("Sort users by first name")) diff --git a/openslides/participant/models.py b/openslides/participant/models.py index f0b420f05..99581cd37 100644 --- a/openslides/participant/models.py +++ b/openslides/participant/models.py @@ -177,6 +177,7 @@ def default_config(sender, key, **kwargs): return { 'participant_pdf_system_url': 'http://example.com:8000', 'participant_pdf_welcometext': _('Welcome to OpenSlides!'), + 'participant_sort_users_by_first_name': False, }.get(key) diff --git a/openslides/participant/views.py b/openslides/participant/views.py index f4bbb8448..1cc4dbc72 100644 --- a/openslides/participant/views.py +++ b/openslides/participant/views.py @@ -412,13 +412,16 @@ class Config(FormView): def get_initial(self): return { 'participant_pdf_system_url': config['participant_pdf_system_url'], - 'participant_pdf_welcometext': config['participant_pdf_welcometext']} + 'participant_pdf_welcometext': config['participant_pdf_welcometext'], + 'participant_sort_users_by_first_name': config['participant_sort_users_by_first_name']} def form_valid(self, form): config['participant_pdf_system_url'] = ( form.cleaned_data['participant_pdf_system_url']) config['participant_pdf_welcometext'] = ( form.cleaned_data['participant_pdf_welcometext']) + config['participant_sort_users_by_first_name'] = ( + form.cleaned_data['participant_sort_users_by_first_name']) messages.success( self.request, _('Participants settings successfully saved.')) From e5c132e34cdea1d97b4456bdf7a05ef64a7298e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Fri, 14 Sep 2012 02:46:43 +0200 Subject: [PATCH 026/222] Use new config var for sorting users --- openslides/participant/models.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openslides/participant/models.py b/openslides/participant/models.py index 99581cd37..662dcf9e3 100644 --- a/openslides/participant/models.py +++ b/openslides/participant/models.py @@ -19,6 +19,7 @@ from django.utils.translation import ugettext_lazy as _, ugettext_noop from openslides.utils.person import PersonMixin from openslides.utils.person.signals import receive_persons +from openslides.config.models import config from openslides.config.signals import default_config_value @@ -134,7 +135,10 @@ class UsersAndGroupsToPersons(object): def __init__(self, person_prefix_filter=None, id_filter=None): self.person_prefix_filter = person_prefix_filter self.id_filter = id_filter - self.users = User.objects.all().order_by('last_name') + if config['participant_sort_users_by_first_name']: + self.users = User.objects.all().order_by('first_name') + else: + self.users = User.objects.all().order_by('last_name') self.groups = Group.objects.filter(group_as_person=True).order_by('name') def __iter__(self): From 269b093b28d2157d16d88c80e7db4e8cb29d0016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Fri, 14 Sep 2012 03:02:00 +0200 Subject: [PATCH 027/222] Enhence use of config var and Meta Class for default sorting of users --- openslides/participant/models.py | 8 ++++++-- openslides/participant/views.py | 5 +++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/openslides/participant/models.py b/openslides/participant/models.py index 662dcf9e3..1eef00093 100644 --- a/openslides/participant/models.py +++ b/openslides/participant/models.py @@ -100,6 +100,7 @@ class User(DjangoUser, PersonMixin): ('can_manage_participant', ugettext_noop("Can manage participant")), ) + ordering = ('last_name',) class Group(DjangoGroup, PersonMixin): @@ -126,6 +127,9 @@ class Group(DjangoGroup, PersonMixin): def __unicode__(self): return unicode(self.name) + class Meta: + ordering = ('name',) + class UsersAndGroupsToPersons(object): """ @@ -138,8 +142,8 @@ class UsersAndGroupsToPersons(object): if config['participant_sort_users_by_first_name']: self.users = User.objects.all().order_by('first_name') else: - self.users = User.objects.all().order_by('last_name') - self.groups = Group.objects.filter(group_as_person=True).order_by('name') + self.users = User.objects.all() + self.groups = Group.objects.filter(group_as_person=True) def __iter__(self): if (not self.person_prefix_filter or diff --git a/openslides/participant/views.py b/openslides/participant/views.py index 1cc4dbc72..63d70f77b 100644 --- a/openslides/participant/views.py +++ b/openslides/participant/views.py @@ -53,7 +53,7 @@ from openslides.participant.models import User, Group class Overview(ListView): """ - Show all participants. + Show all participants (users). """ permission_required = 'participant.can_see_participant' template_name = 'participant/overview.html' @@ -96,7 +96,8 @@ class Overview(ListView): query = query.order_by( '%s' % sortfilter['sort'][0]) else: - query = query.order_by('last_name') + if config['participant_sort_users_by_first_name']: + query = query.order_by('first_name') if 'reverse' in sortfilter: query = query.reverse() From 0db8af15b79ad2e9cda5ea4c03405a2d01c3b35b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Fri, 14 Sep 2012 23:53:59 +0200 Subject: [PATCH 028/222] Clean up the code for pull request --- openslides/application/views.py | 2 -- openslides/participant/models.py | 4 ---- 2 files changed, 6 deletions(-) diff --git a/openslides/application/views.py b/openslides/application/views.py index ba073bb51..87eca0f1a 100644 --- a/openslides/application/views.py +++ b/openslides/application/views.py @@ -102,8 +102,6 @@ def overview(request): if sort.startswith('aversion_'): # limit result to last version of an application query = query.filter(aversion__id__in=[x.last_version.id for x in Application.objects.all()]) - else: - pass if 'reverse' in sortfilter: query = query.reverse() diff --git a/openslides/participant/models.py b/openslides/participant/models.py index 1eef00093..a94fcdb41 100644 --- a/openslides/participant/models.py +++ b/openslides/participant/models.py @@ -162,10 +162,6 @@ class UsersAndGroupsToPersons(object): for group in self.groups: yield group - # Are the following two lines superfluous? They only return Users not Groups. - def __getitem__(self, key): - return User.objects.get(pk=key) - @receiver(receive_persons, dispatch_uid="participant") def receive_persons(sender, **kwargs): From 2984fd791ccdd3a18f45b01739713cd84859e9d2 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sat, 15 Sep 2012 09:11:56 +0200 Subject: [PATCH 029/222] small fix to the person api --- openslides/participant/models.py | 13 ++++++++----- openslides/utils/person/__init__.py | 4 ++-- openslides/utils/person/api.py | 12 ++++++++---- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/openslides/participant/models.py b/openslides/participant/models.py index b97ed119c..4977b3dcf 100644 --- a/openslides/participant/models.py +++ b/openslides/participant/models.py @@ -137,7 +137,10 @@ class UsersConnector(object): if (not self.person_prefix_filter or self.person_prefix_filter == User.person_prefix): if self.id_filter: - yield self.users.get(pk=self.id_filter) + try: + yield self.users.get(pk=self.id_filter) + except User.DoesNotExist: + pass else: for user in self.users: yield user @@ -145,14 +148,14 @@ class UsersConnector(object): if (not self.person_prefix_filter or self.person_prefix_filter == Group.person_prefix): if self.id_filter: - yield self.groups.get(pk=self.id_filter) + try: + yield self.groups.get(pk=self.id_filter) + except Group.DoesNotExist: + pass else: for group in self.groups: yield group - def __getitem__(self, key): - return User.objects.get(pk=key) - @receiver(receive_persons, dispatch_uid="participant") def receive_persons(sender, **kwargs): diff --git a/openslides/utils/person/__init__.py b/openslides/utils/person/__init__.py index da896616f..cc983caf9 100644 --- a/openslides/utils/person/__init__.py +++ b/openslides/utils/person/__init__.py @@ -16,7 +16,7 @@ from openslides.utils.person.forms import PersonFormField, MultiplePersonFormFie from openslides.utils.person.models import PersonField, PersonMixin -class EmtyPerson(PersonMixin): +class EmptyPerson(PersonMixin): @property def person_id(self): - return 'emtyuser' + return 'empty' diff --git a/openslides/utils/person/api.py b/openslides/utils/person/api.py index 55b4691a8..49d901f28 100644 --- a/openslides/utils/person/api.py +++ b/openslides/utils/person/api.py @@ -25,13 +25,17 @@ class Persons(object): try: return iter(self._cache) except AttributeError: - return iter(self.iter_persons()) + return self.iter_persons() def __len__(self): return len(list(self.__iter__())) def __getitem__(self, key): - return list(self)[key] + try: + return list(self)[key] + except IndexError: + from openslides.utils.person import EmptyPerson + return EmptyPerson() def iter_persons(self): self._cache = list() @@ -61,6 +65,6 @@ def get_person(person_id): try: person_prefix, id = split_person_id(person_id) except TypeError: - from openslides.utils.person import EmtyPerson - return EmtyPerson() + from openslides.utils.person import EmptyPerson + return EmptyPerson() return Persons(person_prefix_filter=person_prefix, id_filter=id)[0] From eb267acf083d36f06a25cacb46f29ea07d968123 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sat, 15 Sep 2012 09:13:36 +0200 Subject: [PATCH 030/222] removed scrollbar in projector-template --- openslides/projector/static/styles/projector.css | 1 + 1 file changed, 1 insertion(+) diff --git a/openslides/projector/static/styles/projector.css b/openslides/projector/static/styles/projector.css index d784677cb..6e34df58a 100644 --- a/openslides/projector/static/styles/projector.css +++ b/openslides/projector/static/styles/projector.css @@ -12,6 +12,7 @@ body{ font-family: 'Lucida Grande',"Trebuchet MS",Verdana,sans-serif; font-size : 20px; background-color: #FAFAFB; + overflow: hidden; } /*** HEADER ***/ From 9cb9270df3c479e0f266a85b363f20265dde6ad2 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 18 Sep 2012 22:37:53 +0200 Subject: [PATCH 031/222] Assignment: Fixed generating ballot pdf paper (typo: surfix). --- openslides/assignment/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py index 2b7ff4a71..832af4cea 100644 --- a/openslides/assignment/views.py +++ b/openslides/assignment/views.py @@ -567,8 +567,8 @@ class AssignmentPollPDF(PDFView): candidate = option.candidate cell.append(Paragraph(candidate.user.get_full_name(), stylesheet['Ballot_option_name'])) - if candidate.name_surfix: - cell.append(Paragraph("(%s)" % candidate.name_surfix, + if candidate.name_suffix: + cell.append(Paragraph("(%s)" % candidate.name_suffix, stylesheet['Ballot_option_group'])) else: cell.append(Paragraph(" ", From 12d8527255f3dff84816e496d71332d9471c6633 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 18 Sep 2012 22:40:30 +0200 Subject: [PATCH 032/222] Updated translations. --- openslides/locale/de/LC_MESSAGES/django.mo | Bin 32992 -> 33237 bytes openslides/locale/de/LC_MESSAGES/django.po | 536 +++++++++++---------- 2 files changed, 280 insertions(+), 256 deletions(-) diff --git a/openslides/locale/de/LC_MESSAGES/django.mo b/openslides/locale/de/LC_MESSAGES/django.mo index c4e9fae76280e9f976ab620238004b8d575a9d7a..454decced63ba46a5a328ba9ca4f31ae6edb2cbb 100644 GIT binary patch delta 10244 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 diff --git a/openslides/locale/de/LC_MESSAGES/django.po b/openslides/locale/de/LC_MESSAGES/django.po index c77f7c194..d863961d5 100644 --- a/openslides/locale/de/LC_MESSAGES/django.po +++ b/openslides/locale/de/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: OpenSlides 1.x\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-09-11 20:48+0200\n" +"POT-Creation-Date: 2012-09-18 22:27+0200\n" "PO-Revision-Date: 2012-07-28 11:07+0200\n" "Last-Translator: Oskar Hahn \n" "Language-Team: Deutsch \n" @@ -29,19 +29,19 @@ msgstr "Englisch" msgid "Parent item" msgstr "Elternelement" -#: agenda/models.py:42 application/forms.py:22 application/models.py:540 -#: application/templates/application/view.html:249 config/forms.py:61 +#: agenda/models.py:42 application/forms.py:22 application/models.py:541 +#: application/templates/application/view.html:246 config/forms.py:61 #: projector/models.py:32 msgid "Title" msgstr "Titel" -#: agenda/models.py:43 application/forms.py:23 application/models.py:541 -#: application/templates/application/view.html:250 projector/models.py:33 +#: agenda/models.py:43 application/forms.py:23 application/models.py:542 +#: application/templates/application/view.html:247 projector/models.py:33 msgid "Text" msgstr "Text" #: agenda/models.py:44 agenda/templates/agenda/overview.html:65 -#: agenda/templates/agenda/view.html:13 participant/models.py:52 +#: agenda/templates/agenda/view.html:13 participant/models.py:53 #: participant/templates/participant/overview.html:72 msgid "Comment" msgstr "Kommentar" @@ -224,25 +224,25 @@ msgstr "Zusammenfassung für diesen Eintrag projizieren" msgid "Do you want to save the changed order of agenda items?" msgstr "Möchten Sie die geänderte Reihenfolge der Einträge speichern?" -#: agenda/templates/agenda/overview.html:46 application/models.py:574 -#: application/views.py:487 application/views.py:799 application/views.py:850 -#: application/templates/application/view.html:82 +#: agenda/templates/agenda/overview.html:46 application/models.py:575 +#: application/views.py:775 application/views.py:826 +#: application/templates/application/view.html:79 #: application/templates/projector/Application.html:37 -#: assignment/models.py:279 assignment/views.py:564 -#: assignment/templates/assignment/view.html:156 -#: assignment/templates/assignment/view.html:160 +#: assignment/models.py:297 assignment/views.py:576 +#: assignment/templates/assignment/view.html:166 +#: assignment/templates/assignment/view.html:170 #: assignment/templates/projector/Assignment.html:78 #: assignment/templates/projector/Assignment.html:82 utils/utils.py:53 #: utils/views.py:111 msgid "Yes" msgstr "Ja" -#: agenda/templates/agenda/overview.html:47 application/models.py:574 -#: application/views.py:487 application/views.py:799 application/views.py:851 -#: application/templates/application/view.html:83 +#: agenda/templates/agenda/overview.html:47 application/models.py:575 +#: application/views.py:775 application/views.py:827 +#: application/templates/application/view.html:80 #: application/templates/projector/Application.html:38 -#: assignment/models.py:279 assignment/views.py:565 -#: assignment/templates/assignment/view.html:157 +#: assignment/models.py:297 assignment/views.py:577 +#: assignment/templates/assignment/view.html:167 #: assignment/templates/projector/Assignment.html:79 utils/utils.py:53 #: utils/views.py:111 msgid "No" @@ -298,7 +298,7 @@ msgstr "Vorschau" #: agenda/templates/agenda/widget.html:23 #: application/templates/application/widget.html:11 -#: assignment/templates/assignment/view.html:120 +#: assignment/templates/assignment/view.html:130 #: assignment/templates/assignment/widget.html:11 #: projector/templates/projector/custom_slide_widget.html:24 msgid "Delete" @@ -306,15 +306,15 @@ msgstr "Löschen" #: agenda/templates/agenda/widget.html:26 #: application/templates/application/widget.html:14 -#: assignment/templates/assignment/view.html:119 +#: assignment/templates/assignment/view.html:129 #: assignment/templates/assignment/widget.html:14 #: projector/templates/projector/custom_slide_widget.html:27 msgid "Edit" msgstr "Bearbeiten" -#: application/forms.py:25 application/models.py:542 application/views.py:818 -#: application/templates/application/view.html:232 -#: application/templates/application/view.html:252 +#: application/forms.py:25 application/models.py:543 application/views.py:794 +#: application/templates/application/view.html:229 +#: application/templates/application/view.html:249 #: application/templates/projector/Application.html:77 msgid "Reason" msgstr "Begründung" @@ -327,8 +327,8 @@ msgstr "Triviale Änderung" msgid "Trivial changes don't create a new version." msgstr "Triviale Änderungen erzeugen keine neue Version." -#: application/forms.py:44 application/views.py:749 -#: application/templates/application/view.html:25 +#: application/forms.py:44 application/views.py:733 +#: application/templates/application/view.html:22 msgid "Supporters" msgstr "Unterstützer/innen" @@ -402,12 +402,12 @@ msgid "Permitted" msgstr "Zugelassen" #: application/models.py:47 application/templates/application/overview.html:24 -#: application/templates/application/view.html:170 +#: application/templates/application/view.html:167 msgid "Accepted" msgstr "Angenommen" #: application/models.py:48 application/templates/application/overview.html:25 -#: application/templates/application/view.html:175 +#: application/templates/application/view.html:172 msgid "Rejected" msgstr "Abgelehnt" @@ -415,17 +415,17 @@ msgstr "Abgelehnt" msgid "Withdrawed" msgstr "Zurückgezogen" -#: application/models.py:50 application/templates/application/view.html:183 +#: application/models.py:50 application/templates/application/view.html:180 msgid "Adjourned" msgstr "Vertagt" # please check! -#: application/models.py:51 application/templates/application/view.html:186 +#: application/models.py:51 application/templates/application/view.html:183 msgid "Not Concerned" msgstr "Nicht befasst" # please check! -#: application/models.py:52 application/templates/application/view.html:189 +#: application/models.py:52 application/templates/application/view.html:186 msgid "Commited a bill" msgstr "Verwiesen (in Ausschuss)" @@ -437,7 +437,7 @@ msgstr "Verworfen (nicht zulässig)" msgid "Needs Review" msgstr "Benötigt Review" -#: application/models.py:66 application/views.py:733 +#: application/models.py:66 application/views.py:713 #: application/templates/application/overview.html:41 #: application/templates/application/view.html:18 #: application/templates/projector/Application.html:55 @@ -508,7 +508,7 @@ msgstr "Version %s zugelassen" msgid "Version %s not authorized" msgstr "Version %s nicht zugelassen" -#: application/models.py:336 assignment/models.py:66 +#: application/models.py:336 assignment/models.py:69 #, python-format msgid "%s is not a valid status." msgstr "%s ist kein gültiger Status." @@ -535,7 +535,7 @@ msgstr "Status geändert" msgid "by" msgstr "von" -#: application/models.py:455 application/templates/application/view.html:213 +#: application/models.py:455 application/templates/application/view.html:210 #: application/templates/application/widget.html:27 #: application/templates/projector/Application.html:65 msgid "no number" @@ -567,47 +567,46 @@ msgstr "Darf Anträge unterstützen" msgid "Can manage motions" msgstr "Darf Anträge verwalten" -#: application/models.py:575 assignment/models.py:280 +#: application/models.py:576 assignment/models.py:298 msgid "Abstain" msgstr "Enthaltung" -#: application/models.py:601 -msgid "The Assembly may decide," +#: application/models.py:602 +msgid "The assembly may decide," msgstr "Die Versammlung möge beschließen," -#: application/models.py:604 +#: application/models.py:605 #: application/templates/application/base_application.html:9 #: application/templates/application/overview.html:7 #: application/templates/application/overview.html:10 msgid "Motions" msgstr "Anträge" -#: application/views.py:181 +#: application/views.py:179 msgid "You have not the necessary rights to create or edit motions." msgstr "" "Sie haben nicht die nötigen Rechte, um Anträge zu erstellen oder zu " "bearbeiten." -#: application/views.py:186 -msgid "You can not edit this motion. You are not the submitter." -msgstr "" -"Sie dürfen diesen Antrag nicht bearbeiten. Sie sind nicht der Antragsteller" +#: application/views.py:184 +msgid "You can not edit this motion." +msgstr "Sie dürfen diesen Antrag nicht bearbeiten." -#: application/views.py:249 +#: application/views.py:247 msgid "New motion was successfully created." msgstr "Neuer Antrag wurde erfolgreich angelegt." -#: application/views.py:251 +#: application/views.py:249 msgid "Motion was successfully modified." msgstr "Antrag wurde erfolgreich geändert." -#: application/views.py:258 application/views.py:657 assignment/views.py:136 -#: participant/views.py:459 participant/views.py:482 utils/views.py:210 +#: application/views.py:256 application/views.py:634 assignment/views.py:138 +#: participant/views.py:512 participant/views.py:535 utils/views.py:210 #: utils/views.py:228 utils/views.py:252 msgid "Please check the form for errors." msgstr "Bitte kontrollieren Sie das Formular nach Fehlern." -#: application/views.py:265 +#: application/views.py:263 msgid "" "Attention: Do you really want to edit this motion? The supporters will " "not be removed automatically because you can manage motions. Please " @@ -617,7 +616,7 @@ msgstr "" "werden nicht automatisch entfernt, da Sie Anträge verwalten dürfen. " "Prüfen Sie, ob die Unterstützungen noch gültig sind." -#: application/views.py:267 +#: application/views.py:265 #, python-format msgid "" "Attention: Do you really want to edit this motion? All %s supporters " @@ -626,141 +625,132 @@ msgstr "" "Wollen Sie den Antrag wirklich ändern? Alle %s Unterstützer/innen " "werden dann automatisch entfernt. Versuchen Sie diese erneut zu gewinnen." -#: application/views.py:299 +#: application/views.py:297 msgid "Motion number was successfully set." msgstr "Antragsnummer wurde erfolgreich gesetzt." -#: application/views.py:315 +#: application/views.py:313 msgid "Motion was successfully authorized." msgstr "Antrag wurde erfolgreich zugelassen." -#: application/views.py:330 +#: application/views.py:328 msgid "Motion was successfully rejected." msgstr "Antrag wurde erfolgreich verworfen." -#: application/views.py:346 +#: application/views.py:344 #, python-format msgid "Motion status was set to: %s." msgstr "Antragsstatus wurde gesetzt auf: %s." -#: application/views.py:362 +#: application/views.py:360 msgid "Motion status was reset." msgstr "Antragsstatus wurde zurückgesetzt." -#: application/views.py:376 +#: application/views.py:374 msgid "You have support the motion successfully." msgstr "Sie haben den Antrag erfolgreich unterstützt." -#: application/views.py:390 +#: application/views.py:388 msgid "You have unsupport the motion successfully." msgstr "Sie haben dem Antrag erfolgreich Ihre Unterstützung entzogen." -#: application/views.py:404 +#: application/views.py:402 msgid "New vote was successfully created." msgstr "Neue Abstimmung erfolgreich angelegt." -#: application/views.py:420 +#: application/views.py:418 msgid "Poll deleted" msgstr "Abstimmung gelöscht" -#: application/views.py:421 +#: application/views.py:419 msgid "Poll was successfully deleted." msgstr "Abstimmung wurde erfolgreich gelöscht." -#: application/views.py:423 +#: application/views.py:421 #, python-format msgid "the %s. poll" msgstr "die %s. Abstimmung" -#: application/views.py:461 application/views.py:470 +#: application/views.py:459 application/views.py:468 #, python-format msgid "You can not delete motion %s." msgstr "Sie können Antrag %s nicht löschen." -#: application/views.py:466 application/views.py:474 +#: application/views.py:464 application/views.py:472 #, python-format msgid "Motion %s was successfully deleted." msgstr "Antrag %s wurde erfolgreich gelöscht." -#: application/views.py:476 +#: application/views.py:474 msgid "Invalid request" msgstr "Ungültige Anfrage" -#: application/views.py:495 -msgid "Do you really want to delete multiple motions?" -msgstr "Wollen Sie wirklich mehrere Anträge löschen?" - -#: application/views.py:497 -#, python-format -msgid "Do you really want to delete %s?" -msgstr "Soll %s wirklich gelöscht werden?" - -#: application/views.py:521 +#: application/views.py:498 msgid "Poll was updated" msgstr "Abstimmung wurde aktualisiert" -#: application/views.py:538 +#: application/views.py:515 #, python-format msgid "Version %s accepted." msgstr "Version %s akzeptiert." -#: application/views.py:540 +#: application/views.py:517 #, python-format msgid "Do you really want to authorize version %s?" msgstr "Soll Version %s wirklich zugelassen werden?" -#: application/views.py:550 +#: application/views.py:527 #, python-format msgid "Version %s rejected." msgstr "Version %s zurückgewiesen." -#: application/views.py:552 +#: application/views.py:529 msgid "ERROR by rejecting the version." msgstr "FEHLER beim Zurückweisen der Version." -#: application/views.py:554 +#: application/views.py:531 #, python-format msgid "Do you really want to reject version %s?" msgstr "Soll Version %s wirklich zurückgewiesen werden?" -#: application/views.py:584 application/views.py:588 application/views.py:594 -#: application/views.py:597 participant/api.py:77 +#: application/views.py:561 application/views.py:565 application/views.py:571 +#: application/views.py:574 participant/api.py:76 #, python-format msgid "Ignoring malformed line %d in import file." msgstr "Fehlerhafte Zeile %d der Quelldatei wurde ignoriert." -#: application/views.py:643 +#: application/views.py:620 #, python-format msgid "%d motion was successfully imported." msgid_plural "%d motions were successfully imported." msgstr[0] "%d Antrag wurde erfolgreich importiert." msgstr[1] "%d Anträge wurden erfolgreich importiert." -#: application/views.py:646 +#: application/views.py:623 #, python-format msgid "%d motion was successfully modified." msgid_plural "%d motions were successfully modified." msgstr[0] "%d Antrag wurde erfolgreich geändert." msgstr[1] "%d Anträge wurden erfolgreich geändert." -#: application/views.py:649 +#: application/views.py:626 #, python-format msgid "%d new user was added." msgid_plural "%d new users were added." msgstr[0] "%d neuer Nutzer wurde erstellt." msgstr[1] "%d neue Nutzer wurden erstellt." -#: application/views.py:653 participant/api.py:93 +#: application/views.py:630 participant/api.py:92 msgid "Import aborted because of severe errors in the input file." msgstr "Import auf Grund von schweren Fehlern in der Quelldatei abgebrochen." -#: application/views.py:655 participant/api.py:95 +#: application/views.py:632 participant/api.py:94 msgid "Import file has wrong character encoding, only UTF-8 is supported!" msgstr "" "Die Quelldatei benutzt eine ungültige Zeichenkodierung, es wird nur UTF-8 " "wird unterstützt!" -#: application/views.py:659 +#: application/views.py:636 msgid "" "Attention: Existing motions will be modified if you import new motions with " "the same number." @@ -768,7 +758,7 @@ msgstr "" "Achtung: Existierende Anträge werden geändert wenn Sie neue Anträge mit " "identischer Nummer importieren." -#: application/views.py:660 +#: application/views.py:637 msgid "" "Attention: Importing an motions without a number multiple times will create " "duplicates." @@ -776,27 +766,31 @@ msgstr "" "Achtung: Bei mehrfachem Import eines Antrags ohne Nummer können Duplikate " "entstehen." -#: application/views.py:686 application/views.py:912 +#: application/views.py:663 application/views.py:888 msgid "Applications" msgstr "Anträge" -#: application/views.py:693 application/views.py:832 +#: application/views.py:670 application/views.py:808 msgid "Application" msgstr "Antrag" -#: application/views.py:707 application/templates/application/overview.html:84 +#: application/views.py:684 application/templates/application/overview.html:84 msgid "No motions available." msgstr "Keine Anträge vorhanden." -#: application/views.py:712 application/views.py:714 application/views.py:726 -#: application/views.py:728 +#: application/views.py:689 application/views.py:691 application/views.py:706 +#: application/views.py:708 #: application/templates/projector/Application.html:63 msgid "Motion No." msgstr "Antrag Nr." -#: application/views.py:763 application/templates/application/overview.html:20 +#: application/views.py:723 +msgid "Signature" +msgstr "" + +#: application/views.py:746 application/templates/application/overview.html:20 #: application/templates/application/overview.html:40 -#: application/templates/application/view.html:37 +#: application/templates/application/view.html:34 #: application/templates/projector/Application.html:11 #: assignment/templates/assignment/overview.html:14 #: assignment/templates/assignment/overview.html:27 @@ -806,71 +800,71 @@ msgstr "Antrag Nr." msgid "Status" msgstr "Status" -#: application/views.py:782 application/templates/application/view.html:217 -#: application/templates/application/view.html:247 config/models.py:131 +#: application/views.py:760 application/templates/application/view.html:214 +#: application/templates/application/view.html:244 config/models.py:131 #: config/templates/config/version.html:5 #: config/templates/config/version.html:8 #: config/templates/config/version.html:11 msgid "Version" msgstr "Version" -#: application/views.py:792 application/templates/application/view.html:47 -#: assignment/views.py:398 +#: application/views.py:768 application/templates/application/view.html:44 +#: assignment/views.py:410 msgid "Vote results" msgstr "Abstimmungsergebnis" -#: application/views.py:798 +#: application/views.py:774 #: application/templates/application/base_application.html:55 #: application/templates/application/poll_view.html:8 #: application/templates/application/poll_view.html:13 -#: application/templates/application/view.html:69 -#: application/templates/application/view.html:77 +#: application/templates/application/view.html:66 +#: application/templates/application/view.html:74 #: application/templates/projector/Application.html:33 msgid "Vote" msgstr "Abstimmung" -#: application/views.py:799 application/views.py:852 -#: application/templates/application/view.html:84 -#: application/templates/projector/Application.html:39 assignment/views.py:565 -#: assignment/templates/assignment/view.html:158 +#: application/views.py:775 application/views.py:828 +#: application/templates/application/view.html:81 +#: application/templates/projector/Application.html:39 assignment/views.py:577 +#: assignment/templates/assignment/view.html:168 #: assignment/templates/projector/Assignment.html:80 msgid "Abstention" msgstr "Enthaltung" -#: application/views.py:799 application/templates/application/view.html:85 +#: application/views.py:775 application/templates/application/view.html:82 #: application/templates/projector/Application.html:40 -#: assignment/templates/assignment/view.html:180 +#: assignment/templates/assignment/view.html:190 #: assignment/templates/projector/Assignment.html:101 msgid "Invalid" msgstr "Ungültig" -#: application/views.py:799 +#: application/views.py:775 #: application/templates/application/poll_view.html:35 -#: application/templates/application/view.html:87 -#: application/templates/projector/Application.html:42 assignment/views.py:449 +#: application/templates/application/view.html:84 +#: application/templates/projector/Application.html:42 assignment/views.py:461 #: assignment/templates/assignment/poll_view.html:45 -#: assignment/templates/assignment/view.html:192 -#: assignment/templates/assignment/view.html:197 +#: assignment/templates/assignment/view.html:202 +#: assignment/templates/assignment/view.html:207 #: assignment/templates/projector/Assignment.html:111 #: assignment/templates/projector/Assignment.html:117 poll/models.py:76 msgid "Votes cast" msgstr "Abgegebene Stimmen" -#: application/views.py:832 +#: application/views.py:808 msgid "Poll" msgstr "Abstimmung" -#: application/views.py:846 +#: application/views.py:822 #, python-format msgid "Application No. %s" msgstr "Antrag Nr. %s" -#: application/views.py:848 +#: application/views.py:824 #, python-format msgid "%d. Vote" msgstr "%d. Abstimmung" -#: application/views.py:905 +#: application/views.py:881 msgid "Motion settings successfully saved." msgstr "Antrags-Einstellungen wurden erfolgreich gespeichert." @@ -995,7 +989,7 @@ msgid "Number of supporters" msgstr "Anzahl der Unterstützer/innen" #: application/templates/application/overview.html:42 -#: application/templates/application/view.html:112 +#: application/templates/application/view.html:109 msgid "Creation Time" msgstr "Erstellungszeit" @@ -1006,8 +1000,8 @@ msgstr "Antrag projizieren" #: application/templates/application/poll_view.html:7 #: application/templates/application/poll_view.html:12 #: application/templates/application/view.html:7 -#: application/templates/application/view.html:209 -#: application/templates/application/view.html:228 +#: application/templates/application/view.html:206 +#: application/templates/application/view.html:225 #: application/templates/projector/Application.html:7 #: application/templates/projector/Application.html:65 msgid "Motion" @@ -1025,6 +1019,7 @@ msgstr "Mehrheit" #: application/templates/application/poll_view.html:14 #: assignment/templates/assignment/poll_view.html:12 poll/models.py:237 +#: poll/models.py:239 msgid "undocumented" msgstr "nicht erfasst" @@ -1033,13 +1028,13 @@ msgid "Option" msgstr "Wahlmöglichkeit" #: application/templates/application/poll_view.html:22 -#: assignment/models.py:282 +#: assignment/models.py:300 msgid "Votes" msgstr "Stimmen" -#: application/templates/application/poll_view.html:31 assignment/views.py:442 +#: application/templates/application/poll_view.html:31 assignment/views.py:454 #: assignment/templates/assignment/poll_view.html:35 -#: assignment/templates/assignment/view.html:175 +#: assignment/templates/assignment/view.html:185 #: assignment/templates/projector/Assignment.html:97 msgid "Invalid votes" msgstr "Ungültige Stimmen" @@ -1049,131 +1044,127 @@ msgstr "Ungültige Stimmen" msgid "Ballot paper as PDF" msgstr "Stimmzettel als PDF" -#: application/templates/application/view.html:21 -msgid "You!" -msgstr "Sie!" - -#: application/templates/application/view.html:54 -#: application/templates/application/view.html:94 +#: application/templates/application/view.html:51 +#: application/templates/application/view.html:91 msgid "New vote" msgstr "Neue Abstimmung" -#: application/templates/application/view.html:70 +#: application/templates/application/view.html:67 msgid "Edit Vote" msgstr "Abstimmung bearbeiten" -#: application/templates/application/view.html:73 +#: application/templates/application/view.html:70 msgid "Delete Vote" msgstr "Abstimmung löschen" -#: application/templates/application/view.html:102 +#: application/templates/application/view.html:99 msgid "Enter result" msgstr "Ergebnis eingeben" -#: application/templates/application/view.html:119 +#: application/templates/application/view.html:116 msgid "Withdraw" msgstr "Zurückziehen" -#: application/templates/application/view.html:127 +#: application/templates/application/view.html:124 msgid "Unsupport" msgstr "Nicht unterstützen" -#: application/templates/application/view.html:133 +#: application/templates/application/view.html:130 msgid "Support" msgstr "Unterstützen" -#: application/templates/application/view.html:139 +#: application/templates/application/view.html:136 msgid "minimum required supporters" msgstr "minimal erforderliche Unterstützer/innen" -#: application/templates/application/view.html:146 +#: application/templates/application/view.html:143 msgid "Manage motion" msgstr "Antrag Verwalten" -#: application/templates/application/view.html:149 +#: application/templates/application/view.html:146 msgid "Formal validation" msgstr "Formale Gültigkeitsprüfung" -#: application/templates/application/view.html:151 +#: application/templates/application/view.html:148 msgid "Publish" msgstr "Veröffentlichen" -#: application/templates/application/view.html:154 +#: application/templates/application/view.html:151 msgid "Permit" msgstr "Zulassen" -#: application/templates/application/view.html:157 +#: application/templates/application/view.html:154 msgid "Not permit (reject)" msgstr "Nicht zulassen (verwerfen)" -#: application/templates/application/view.html:160 +#: application/templates/application/view.html:157 msgid "Set Number" msgstr "Setze Nummer" -#: application/templates/application/view.html:167 +#: application/templates/application/view.html:164 msgid "Result after vote" msgstr "Ergebnis nach der Abstimmung" -#: application/templates/application/view.html:181 +#: application/templates/application/view.html:178 msgid "Result after debate" msgstr "Ergebnis nach der Debatte" -#: application/templates/application/view.html:192 +#: application/templates/application/view.html:189 msgid "Withdrawed by Submitter" msgstr "Zurückgezogen durch Antragsteller/in" -#: application/templates/application/view.html:197 +#: application/templates/application/view.html:194 msgid "For Administration only:" msgstr "Nur zur Administration:" -#: application/templates/application/view.html:199 +#: application/templates/application/view.html:196 msgid "Reset" msgstr "Zurücksetzen" -#: application/templates/application/view.html:222 +#: application/templates/application/view.html:219 msgid "This is not the newest version." msgstr "Dies ist nicht die neuste Version." -#: application/templates/application/view.html:222 -#: application/templates/application/view.html:224 +#: application/templates/application/view.html:219 +#: application/templates/application/view.html:221 msgid "Go to version" msgstr "Gehe zu Version" -#: application/templates/application/view.html:224 +#: application/templates/application/view.html:221 msgid "This is not the authorized version." msgstr "Dies ist nicht die zugelassene Version." -#: application/templates/application/view.html:242 +#: application/templates/application/view.html:239 msgid "Version History" msgstr "Versionshistorie" -#: application/templates/application/view.html:248 +#: application/templates/application/view.html:245 msgid "Time" msgstr "Zeit" -#: application/templates/application/view.html:259 +#: application/templates/application/view.html:256 msgid "Version authorized" msgstr "Version %d zugelassen" -#: application/templates/application/view.html:262 +#: application/templates/application/view.html:259 msgid "Permit Version" msgstr "Version zulassen" -#: application/templates/application/view.html:265 +#: application/templates/application/view.html:262 msgid "Reject Version" msgstr "Version verwerfen" -#: application/templates/application/view.html:269 +#: application/templates/application/view.html:266 msgid "Version rejected" msgstr "Version verworfen" -#: application/templates/application/view.html:279 -#: application/templates/application/view.html:286 -#: application/templates/application/view.html:293 +#: application/templates/application/view.html:276 +#: application/templates/application/view.html:283 +#: application/templates/application/view.html:290 msgid "unchanged" msgstr "unverändert" -#: application/templates/application/view.html:302 +#: application/templates/application/view.html:299 msgid "Log" msgstr "Log" @@ -1189,7 +1180,7 @@ msgstr "Abstimmungsergebnis" msgid "No poll results available." msgstr "Keine Abstimmungen vorhanden." -#: assignment/forms.py:24 assignment/models.py:54 assignment/views.py:371 +#: assignment/forms.py:24 assignment/models.py:57 assignment/views.py:383 #: assignment/templates/assignment/view.html:13 #: assignment/templates/projector/Assignment.html:21 msgid "Number of available posts" @@ -1228,79 +1219,79 @@ msgstr "Eine Stimme pro Kandidat/in." msgid "Always Yes-No-Abstain per candidate." msgstr "Ja, Nein, Enthaltung pro Kandidat/in." -#: assignment/models.py:45 assignment/templates/assignment/overview.html:15 +#: assignment/models.py:48 assignment/templates/assignment/overview.html:15 #: assignment/templates/assignment/view.html:23 msgid "Searching for candidates" msgstr "Auf Kandidatensuche" -#: assignment/models.py:46 assignment/templates/assignment/overview.html:16 +#: assignment/models.py:49 assignment/templates/assignment/overview.html:16 #: assignment/templates/assignment/view.html:25 msgid "Voting" msgstr "Im Wahlvorgang" -#: assignment/models.py:47 assignment/templates/assignment/overview.html:17 +#: assignment/models.py:50 assignment/templates/assignment/overview.html:17 #: assignment/templates/assignment/view.html:27 msgid "Finished" msgstr "Abgeschlossen" -#: assignment/models.py:50 +#: assignment/models.py:53 msgid "Name" msgstr "Name" -#: assignment/models.py:52 +#: assignment/models.py:55 msgid "Description" msgstr "Beschreibung" -#: assignment/models.py:56 +#: assignment/models.py:59 msgid "Comment on the ballot paper" msgstr "Kommentar für den Stimmzettel" -#: assignment/models.py:68 +#: assignment/models.py:71 #, python-format msgid "The assignment status is already %s." msgstr "Der Wahlstatus ist bereits %s." -#: assignment/models.py:82 +#: assignment/models.py:85 #, python-format msgid "%s is already a candidate." msgstr "%s ist bereits ein/e Kandidat/in." -#: assignment/models.py:84 assignment/views.py:192 +#: assignment/models.py:87 assignment/views.py:200 msgid "The candidate list is already closed." msgstr "Die Kandidatenliste ist bereits geschlossen." -#: assignment/models.py:90 +#: assignment/models.py:94 #, python-format msgid "%s does not want to be a candidate." msgstr "%s möchte nicht kandidieren." -#: assignment/models.py:110 +#: assignment/models.py:109 #, python-format msgid "%s is no candidate" msgstr "%s ist kein/e Kandidat/in" -#: assignment/models.py:233 +#: assignment/models.py:250 msgid "Can see assignment" msgstr "Darf Wahlen sehen" -#: assignment/models.py:235 +#: assignment/models.py:252 msgid "Can nominate another person" msgstr "Darf andere Personen für Wahlen vorschlagen" -#: assignment/models.py:236 +#: assignment/models.py:253 msgid "Can nominate themselves" msgstr "Darf selbst für Wahlen kandidieren" -#: assignment/models.py:237 +#: assignment/models.py:254 msgid "Can manage assignment" msgstr "Darf Wahlen verwalten" -#: assignment/models.py:299 +#: assignment/models.py:317 #, python-format msgid "Ballot %d" msgstr "Wahlgang %d" -#: assignment/models.py:308 assignment/views.py:328 assignment/views.py:651 +#: assignment/models.py:326 assignment/views.py:340 assignment/views.py:663 #: assignment/templates/assignment/base_assignment.html:14 #: assignment/templates/assignment/overview.html:6 #: assignment/templates/assignment/overview.html:9 @@ -1312,110 +1303,121 @@ msgstr "Wahlen" msgid "Candidate %s was nominated successfully." msgstr "Kandidat/in %s wurde erfolgreich vorgeschlagen." -#: assignment/views.py:128 +#: assignment/views.py:130 msgid "New election was successfully created." msgstr "Neue Wahl wurde erfolgreich angelegt." -#: assignment/views.py:130 +#: assignment/views.py:132 msgid "Election was successfully modified." msgstr "Wahl wurde erfolgreich geändert." -#: assignment/views.py:155 +#: assignment/views.py:157 #, python-format msgid "Election %s was successfully deleted." msgstr "Wahl %s wurde erfolgreich gelöscht." -#: assignment/views.py:168 +#: assignment/views.py:170 #, python-format msgid "Election status was set to: %s." msgstr "Wahlstatus wurde gesetzt auf: %s." -#: assignment/views.py:179 +#: assignment/views.py:181 msgid "You have set your candidature successfully." msgstr "Sie haben Ihre Kandidatur erfolgreich gesetzt." -#: assignment/views.py:196 -msgid "You have withdrawn your candidature successfully." -msgstr "Sie haben Ihre Kandidatur erfolgreich zurückgezogen." +#: assignment/views.py:197 +msgid "" +"You have withdrawn your candidature successfully. You can not be nominated " +"by other participants anymore." +msgstr "Sie haben Ihre Kandidatur erfolgreich zurückgezogen. Sie können nun " +"von anderen Teilnehmer/innen nicht mehr vorgeschlagen werden." -#: assignment/views.py:211 +#: assignment/views.py:218 #, python-format msgid "Candidate %s was withdrawn successfully." msgstr "Die Kandidatur von %s wurde erfolgreich zurückgezogen." -#: assignment/views.py:214 +#: assignment/views.py:220 +msgid "%s was unblocked successfully." +msgstr "%s wurde erfolgreich freigegeben." + +#: assignment/views.py:224 #, python-format msgid "Do you really want to withdraw %s from the election?" msgstr "Soll %s wirklich von der Wahl zurückgezogen werden?" -#: assignment/views.py:229 +#: assignment/views.py:226 +msgid "Do you really want to unblock %s from the election?" +msgstr "Soll %s wirklich für die Wahl freigegeben werden?" + +#: assignment/views.py:241 msgid "New ballot was successfully created." msgstr "Neuer Wahlgang erfolgreich angelegt." -#: assignment/views.py:261 +#: assignment/views.py:273 #, python-format msgid "Ballot ID %d does not exist." msgstr "Wahlgang-ID %d existiert nicht." -#: assignment/views.py:268 +#: assignment/views.py:280 msgid "Ballot successfully published." msgstr "Wahlgang wurde erfolgreich veröffentlicht." -#: assignment/views.py:270 +#: assignment/views.py:282 msgid "Ballot successfully unpublished." msgstr "Wahlgang wurde erfolgreich unveröffentlicht." -#: assignment/views.py:283 +#: assignment/views.py:295 msgid "not elected" msgstr "nicht gewählt" -#: assignment/views.py:286 assignment/views.py:469 +#: assignment/views.py:298 assignment/views.py:481 msgid "elected" msgstr "gewählt" -#: assignment/views.py:314 +#: assignment/views.py:326 msgid "Ballot was successfully deleted." msgstr "Abstimmung wurde erfolgreich gelöscht." -#: assignment/views.py:325 +#: assignment/views.py:337 msgid "Assignment" msgstr "Wahl" -#: assignment/views.py:346 assignment/templates/assignment/overview.html:53 +#: assignment/views.py:358 assignment/templates/assignment/overview.html:53 #: assignment/templates/assignment/widget.html:23 msgid "No assignments available." msgstr "Keine Wahlen vorhanden." -#: assignment/views.py:365 +#: assignment/views.py:377 #, python-format msgid "Election: %s" msgstr "Wahlen: %s" -#: assignment/views.py:377 assignment/views.py:410 +#: assignment/views.py:389 assignment/views.py:422 #: assignment/templates/assignment/overview.html:26 #: assignment/templates/assignment/poll_view.html:18 #: assignment/templates/assignment/view.html:36 -#: assignment/templates/assignment/view.html:108 +#: assignment/templates/assignment/view.html:118 #: assignment/templates/projector/Assignment.html:38 #: assignment/templates/projector/Assignment.html:56 msgid "Candidates" msgstr "Kandidaten/innen" -#: assignment/views.py:402 +#: assignment/views.py:414 #: assignment/templates/assignment/base_assignment.html:71 #: assignment/templates/assignment/poll_view.html:5 #: assignment/templates/assignment/poll_view.html:8 -#: assignment/templates/assignment/view.html:102 -#: assignment/templates/assignment/view.html:111 +#: assignment/templates/assignment/view.html:112 +#: assignment/templates/assignment/view.html:121 #: assignment/templates/projector/Assignment.html:59 msgid "ballot" msgstr "Wahlgang" -#: assignment/views.py:405 +#: assignment/views.py:417 msgid "ballots" msgstr "Wahlgänge" -#: assignment/views.py:431 +#: assignment/views.py:443 #, python-format msgid "" "Y: %(YES)s\n" @@ -1426,7 +1428,7 @@ msgstr "" "N: %(NO)s\n" "E: %(ABSTAIN)s" -#: assignment/views.py:508 assignment/views.py:524 +#: assignment/views.py:520 assignment/views.py:536 #: assignment/templates/assignment/overview.html:25 #: assignment/templates/assignment/poll_view.html:5 #: assignment/templates/assignment/view.html:6 @@ -1434,28 +1436,28 @@ msgstr "" msgid "Election" msgstr "Wahl" -#: assignment/views.py:530 +#: assignment/views.py:542 #, python-format msgid "%d. ballot" msgstr "%d. Wahlgang" -#: assignment/views.py:531 +#: assignment/views.py:543 #, python-format msgid "%d candidate" msgid_plural "%d candidates" msgstr[0] "%d Kandidat/in" msgstr[1] "%d Kandidaten/innen" -#: assignment/views.py:533 +#: assignment/views.py:545 #, python-format msgid "%d available posts" msgstr "%d verfügbare Posten" -#: assignment/views.py:644 +#: assignment/views.py:656 msgid "Election settings successfully saved." msgstr "Wahl-Einstellungen wurden erfolgreich gespeichert." -#: assignment/views.py:664 +#: assignment/views.py:676 msgid "Assignments" msgstr "Wahlen" @@ -1522,6 +1524,7 @@ msgid "Change status" msgstr "Status ändern" #: assignment/templates/assignment/view.html:43 +#: assignment/templates/assignment/view.html:96 msgid "Remove candidate" msgstr "Kandidate/in entfernen" @@ -1542,31 +1545,39 @@ msgstr "Selbst kandidieren" msgid "Add new participant" msgstr "Neue/n Teilnehmer/in hinzufügen" -#: assignment/templates/assignment/view.html:93 +#: assignment/templates/assignment/view.html:92 +msgid "Blocked Candidates" +msgstr "Blockierte Kandidaten/innen" + +#: assignment/templates/assignment/view.html:99 +msgid "There are no blocked candidates." +msgstr "Keine blockierten Kandidaten verfügbar." + +#: assignment/templates/assignment/view.html:103 #: assignment/templates/projector/Assignment.html:52 msgid "Election results" msgstr "Wahlergebnisse" -#: assignment/templates/assignment/view.html:116 +#: assignment/templates/assignment/view.html:126 msgid "Publish/unpublish results" msgstr "Ergebnisse veröffentlichen/unveröffentlichen" -#: assignment/templates/assignment/view.html:128 -#: assignment/templates/assignment/view.html:216 +#: assignment/templates/assignment/view.html:138 +#: assignment/templates/assignment/view.html:226 msgid "New ballot" msgstr "Neuer Wahlgang" -#: assignment/templates/assignment/view.html:143 +#: assignment/templates/assignment/view.html:153 #: assignment/templates/projector/Assignment.html:69 msgid "Candidate is elected" msgstr "Kandidat/in ist gewählt" -#: assignment/templates/assignment/view.html:162 +#: assignment/templates/assignment/view.html:172 #: assignment/templates/projector/Assignment.html:84 msgid "was not a
candidate" msgstr "war kein Kandidat" -#: assignment/templates/assignment/view.html:211 +#: assignment/templates/assignment/view.html:221 #: assignment/templates/projector/Assignment.html:126 msgid "No ballots available." msgstr "Keine Wahlgänge vorhanden." @@ -1611,7 +1622,7 @@ msgstr "Präsentationssystem für Tagesordnung, Anträge und Wahlen" msgid "Welcome" msgstr "Willkommen" -#: config/models.py:90 participant/models.py:171 +#: config/models.py:90 participant/models.py:189 msgid "Welcome to OpenSlides!" msgstr "Willkommen bei OpenSlides!" @@ -1692,145 +1703,149 @@ msgstr "System URL" msgid "Printed in PDF of first time passwords only." msgstr "Erscheint nur im PDF der Erst-Passwörter" -#: participant/models.py:28 participant/templates/participant/overview.html:25 +#: participant/forms.py:118 +msgid "Sort users by first name" +msgstr "" + +#: participant/models.py:29 participant/templates/participant/overview.html:25 msgid "Male" msgstr "Männlich" -#: participant/models.py:29 participant/templates/participant/overview.html:26 +#: participant/models.py:30 participant/templates/participant/overview.html:26 msgid "Female" msgstr "Weiblich" -#: participant/models.py:32 participant/templates/participant/overview.html:38 +#: participant/models.py:33 participant/templates/participant/overview.html:38 msgid "Delegate" msgstr "Delegierter" -#: participant/models.py:33 participant/templates/participant/overview.html:39 +#: participant/models.py:34 participant/templates/participant/overview.html:39 msgid "Observer" msgstr "Beobachter" -#: participant/models.py:34 participant/templates/participant/overview.html:40 +#: participant/models.py:35 participant/templates/participant/overview.html:40 msgid "Staff" msgstr "Mitarbeiter" -#: participant/models.py:35 participant/templates/participant/overview.html:41 +#: participant/models.py:36 participant/templates/participant/overview.html:41 msgid "Guest" msgstr "Gast" -#: participant/models.py:40 participant/templates/participant/overview.html:30 +#: participant/models.py:41 participant/templates/participant/overview.html:30 #: participant/templates/participant/overview.html:68 msgid "Category" msgstr "Kategorie" -#: participant/models.py:41 +#: participant/models.py:42 msgid "Will be shown behind the name." msgstr "Wird nach dem Namen angezeigt." -#: participant/models.py:44 participant/templates/participant/overview.html:24 +#: participant/models.py:45 participant/templates/participant/overview.html:24 msgid "Gender" msgstr "Geschlecht" -#: participant/models.py:44 participant/models.py:47 participant/models.py:50 +#: participant/models.py:45 participant/models.py:48 participant/models.py:51 msgid "Only for filter the userlist." msgstr "Nur zum Filtern der Benutzerliste." -#: participant/models.py:47 +#: participant/models.py:48 msgid "Typ" msgstr "Typ" -#: participant/models.py:49 participant/views.py:216 +#: participant/models.py:50 participant/views.py:219 #: participant/templates/participant/overview.html:45 #: participant/templates/participant/overview.html:70 msgid "Committee" msgstr "Amt" -#: participant/models.py:53 +#: participant/models.py:54 msgid "Only for notes." msgstr "Nur für Notizen." -#: participant/models.py:56 +#: participant/models.py:57 msgid "Default password" msgstr "Vorgegebenes Passwort" -#: participant/models.py:98 +#: participant/models.py:99 msgid "Can see participant" msgstr "Darf die Teilnehmer/inen sehen" -#: participant/models.py:100 +#: participant/models.py:101 msgid "Can manage participant" msgstr "Darf die Teilnehmer/inen verwalten" -#: participant/views.py:211 +#: participant/views.py:214 msgid "Participant-list" msgstr "Teilnehmerliste" -#: participant/views.py:212 +#: participant/views.py:215 msgid "List of Participants" msgstr "Teilnehmerliste" -#: participant/views.py:215 participant/templates/participant/overview.html:67 +#: participant/views.py:218 participant/templates/participant/overview.html:67 msgid "Last Name" msgstr "Nachname" -#: participant/views.py:215 participant/templates/participant/overview.html:66 +#: participant/views.py:218 participant/templates/participant/overview.html:66 msgid "First Name" msgstr "Vorname" -#: participant/views.py:215 +#: participant/views.py:218 msgid "Group" msgstr "Gruppe" -#: participant/views.py:215 participant/templates/participant/overview.html:37 +#: participant/views.py:218 participant/templates/participant/overview.html:37 #: participant/templates/participant/overview.html:69 msgid "Type" msgstr "Typ" -#: participant/views.py:244 +#: participant/views.py:247 msgid "Participant-passwords" msgstr "Teilnehmer-Passwoerter" -#: participant/views.py:262 +#: participant/views.py:269 msgid "Account for OpenSlides" msgstr "Zugang für OpenSlides" -#: participant/views.py:264 +#: participant/views.py:271 #, python-format msgid "for %s" msgstr "für %s" -#: participant/views.py:267 +#: participant/views.py:274 #, python-format msgid "User: %s" msgstr "Nutzername: %s" -#: participant/views.py:271 +#: participant/views.py:278 #, python-format msgid "Password: %s" msgstr "Passwort: %s" -#: participant/views.py:276 +#: participant/views.py:283 #, python-format msgid "URL: %s" msgstr "URL: %s" -#: participant/views.py:318 +#: participant/views.py:368 #, python-format msgid "%d new participants were successfully imported." msgstr "%d neue Teilnehmer/innen wurden erfolgreich importiert." -#: participant/views.py:329 +#: participant/views.py:379 msgid "Do you really want to reset the password?" msgstr "Soll das Passwort wirklich zurückgesetzt werden?" -#: participant/views.py:345 +#: participant/views.py:395 #, python-format msgid "The Password for %s was successfully reset." msgstr "Das Passwort für %s wurde erfolgreich zurückgesetzt." -#: participant/views.py:424 +#: participant/views.py:477 msgid "Participants settings successfully saved." msgstr "Teilnehmer/innen-Einstellungen wurden erfolgreich gespeichert." -#: participant/views.py:434 +#: participant/views.py:487 #, python-format msgid "" "Installation was successfully! Use %(user)s (password: %(password)s) for " @@ -1843,15 +1858,15 @@ msgstr "" "Sie das Passwort nach der ersten Anmeldung! Anderenfalls erscheint diese " "Meldung weiterhin für alle und ist ein Sicherheitsrisiko." -#: participant/views.py:457 +#: participant/views.py:510 msgid "User settings successfully saved." msgstr "Nutzereinstellungen wurden erfolgreich gespeichert." -#: participant/views.py:479 +#: participant/views.py:532 msgid "Password successfully changed." msgstr "Password wurde erfolgreich geändert." -#: participant/views.py:497 +#: participant/views.py:550 #: participant/templates/participant/base_participant.html:12 #: participant/templates/participant/overview.html:7 #: participant/templates/participant/overview.html:18 @@ -2172,16 +2187,16 @@ msgstr "Abmelden" msgid "You have access to the following pages:" msgstr "Sie haben Zugriff auf folgende Seiten:" -#: utils/pdf.py:225 +#: utils/pdf.py:224 msgid "%Y-%m-%d %H:%Mh" msgstr "%d.%m.%Y %H:%Mh" -#: utils/pdf.py:226 +#: utils/pdf.py:225 #, python-format msgid "Printed: %s" msgstr "Gedruckt am: %s" -#: utils/pdf.py:237 utils/pdf.py:246 +#: utils/pdf.py:236 utils/pdf.py:245 #, python-format msgid "Page %s" msgstr "Seite %s" @@ -2225,3 +2240,12 @@ msgstr "undefinierter-dateiname" #: utils/jsonfield/fields.py:21 msgid "Enter valid JSON" msgstr "Gebe valides JSON ein" + +#~ msgid "Do you really want to delete multiple motions?" +#~ msgstr "Wollen Sie wirklich mehrere Anträge löschen?" + +#~ msgid "Do you really want to delete %s?" +#~ msgstr "Soll %s wirklich gelöscht werden?" + +#~ msgid "You!" +#~ msgstr "Sie!" From 154847906902021c06c74115c6ac76859ce24ea1 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 18 Sep 2012 22:47:12 +0200 Subject: [PATCH 033/222] Fixed application and assigment ballot paper: don't use old profile object. --- openslides/application/views.py | 4 ++-- openslides/assignment/views.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openslides/application/views.py b/openslides/application/views.py index 87eca0f1a..5b8e3dcce 100644 --- a/openslides/application/views.py +++ b/openslides/application/views.py @@ -833,9 +833,9 @@ class ApplicationPollPDF(PDFView): # set number of ballot papers if ballot_papers_selection == "NUMBER_OF_DELEGATES": - number = User.objects.filter(profile__type__iexact="delegate").count() + number = User.objects.filter(type__iexact="delegate").count() elif ballot_papers_selection == "NUMBER_OF_ALL_PARTICIPANTS": - number = int(Profile.objects.count()) + number = int(User.objects.count()) else: # ballot_papers_selection == "CUSTOM_NUMBER" number = int(ballot_papers_number) number = max(1, number) diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py index 832af4cea..68f561c87 100644 --- a/openslides/assignment/views.py +++ b/openslides/assignment/views.py @@ -554,9 +554,9 @@ class AssignmentPollPDF(PDFView): # set number of ballot papers if ballot_papers_selection == "NUMBER_OF_DELEGATES": - number = User.objects.filter(profile__type__iexact="delegate").count() + number = User.objects.filter(type__iexact="delegate").count() elif ballot_papers_selection == "NUMBER_OF_ALL_PARTICIPANTS": - number = int(Profile.objects.count()) + number = int(User.objects.count()) else: # ballot_papers_selection == "CUSTOM_NUMBER" number = int(ballot_papers_number) number = max(1, number) From 613956b62acefaad72f2b55849d4f203976dfcc0 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 18 Sep 2012 22:55:31 +0200 Subject: [PATCH 034/222] Fixed missing blue 'candidate elected' line in assignment projector template. --- openslides/assignment/templates/projector/Assignment.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openslides/assignment/templates/projector/Assignment.html b/openslides/assignment/templates/projector/Assignment.html index 8627d6022..8a5c50b0e 100644 --- a/openslides/assignment/templates/projector/Assignment.html +++ b/openslides/assignment/templates/projector/Assignment.html @@ -63,8 +63,8 @@ {% for candidate, poll_list in vote_results.items %} - - {% if candidate in assignment.elected.all %} + + {% if candidate in assignment.elected %} @@ -72,8 +72,8 @@ {{ candidate }} {% for vote in poll_list %} - - {% if not assignment_publish_winner_results_only or candidate in assignment.elected.all %} + + {% if not assignment_publish_winner_results_only or candidate in assignment.elected %} {% if 'Yes' in vote and 'No' in vote and 'Abstain' in vote %} {{ vote.Yes }}
{{ vote.No }}
From 3bde0a8af92187462327142190b14d8f5909ed07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Wed, 19 Sep 2012 03:10:15 +0200 Subject: [PATCH 035/222] Use Class-based View to support or unsupport an application. Use QuestionMixin for a confirm message --- openslides/application/models.py | 2 ++ openslides/application/urls.py | 6 ++-- openslides/application/views.py | 55 +++++++++++++++++++------------- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/openslides/application/models.py b/openslides/application/models.py index df1d8195f..e1c6c3555 100644 --- a/openslides/application/models.py +++ b/openslides/application/models.py @@ -263,6 +263,7 @@ class Application(models.Model, SlideMixin): if not self.is_supporter(person): ApplicationSupporter(application=self, person=person).save() self.writelog(_("Supporter: +%s") % (person)) + # TODO: Raise a precise exception for the view in else-clause def unsupport(self, person): """ @@ -274,6 +275,7 @@ class Application(models.Model, SlideMixin): try: object = self.applicationsupporter_set.get(person=person).delete() except ApplicationSupporter.DoesNotExist: + # TODO: Don't do nothing but raise a precise exception for the view pass else: self.writelog(_("Supporter: -%s") % (person)) diff --git a/openslides/application/urls.py b/openslides/application/urls.py index 3b3e83e9e..a6eaec924 100644 --- a/openslides/application/urls.py +++ b/openslides/application/urls.py @@ -13,7 +13,7 @@ from django.conf.urls.defaults import url, patterns from openslides.application.views import (ApplicationDelete, ViewPoll, - ApplicationPDF, ApplicationPollPDF, CreateAgendaItem) + ApplicationPDF, ApplicationPollPDF, CreateAgendaItem, SupportView) urlpatterns = patterns('openslides.application.views', url(r'^$', @@ -99,12 +99,12 @@ urlpatterns = patterns('openslides.application.views', ), url(r'^(?P\d+)/support/$', - 'support', + SupportView.as_view(unsupport=False, answer_url='support/'), name='application_support', ), url(r'^(?P\d+)/unsupport/$', - 'unsupport', + SupportView.as_view(unsupport=True, answer_url='unsupport/'), name='application_unsupport', ), diff --git a/openslides/application/views.py b/openslides/application/views.py index 87eca0f1a..310d8c0d3 100644 --- a/openslides/application/views.py +++ b/openslides/application/views.py @@ -41,7 +41,8 @@ from openslides.utils.pdf import stylesheet from openslides.utils.template import Tab from openslides.utils.utils import (template, permission_required, del_confirm_form, gen_confirm_form) -from openslides.utils.views import PDFView, RedirectView, DeleteView, FormView +from openslides.utils.views import (PDFView, RedirectView, DeleteView, + FormView, SingleObjectMixin, QuestionMixin) from openslides.utils.person import get_person from openslides.config.models import config @@ -363,32 +364,40 @@ def reset(request, application_id): return redirect(reverse('application_view', args=[application_id])) -@permission_required('application.can_support_application') -@template('application/view.html') -def support(request, application_id): +class SupportView(RedirectView, SingleObjectMixin, QuestionMixin): """ - support an application. + Support or unsupport an application """ - try: - Application.objects.get(pk=application_id).support(person=request.user) - messages.success(request, _("You have support the motion successfully.") ) - except Application.DoesNotExist: - pass - return redirect(reverse('application_view', args=[application_id])) + permission_required = 'application.can_support_application' + model = Application + pk_url_kwarg = 'application_id' # TODO: Is this line neccessary? + unsupport = False # Must be given in SupportView.as_view() + answer_url = None # Must be given in SupportView.as_view() + def get_question(self): + if not self.unsupport: + return _('Do you really want to support this motion?') + else: + return _('Do you really want to unsupport this motion?') -@permission_required('application.can_support_application') -@template('application/view.html') -def unsupport(request, application_id): - """ - unsupport an application. - """ - try: - Application.objects.get(pk=application_id).unsupport(person=request.user) - messages.success(request, _("You have unsupport the motion successfully.") ) - except Application.DoesNotExist: - pass - return redirect(reverse('application_view', args=[application_id])) + # TODO: Why do we have to overwrite this method? + def pre_redirect(self, request, *args, **kwargs): + self.confirm_form() + + def pre_post_redirect(self, request, *args, **kwargs): + if self.get_answer().lower() == 'yes': + if not self.unsupport: + Application.objects.get(pk=kwargs['application_id']).support(person=request.user) + # Should the Exception Application.DoesNotExist be kept or not? + self.success_message = _("You have supported this motion successfully.") + else: + Application.objects.get(pk=kwargs['application_id']).unsupport(person=request.user) + # Should the Exception Application.DoesNotExist be kept or not? + self.success_message = _("You have unsupported this motion successfully.") + messages.success(request, self.success_message) + + def get_redirect_url(self, **kwargs): + return reverse('application_view', args=[kwargs['application_id']]) @permission_required('application.can_manage_application') From 4cd1ad5954c030eaee573d5e760ce87553cb2747 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Wed, 19 Sep 2012 11:58:24 +0200 Subject: [PATCH 036/222] Fixed missing supporters number --- openslides/application/templates/application/overview.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openslides/application/templates/application/overview.html b/openslides/application/templates/application/overview.html index 2291b55ac..45bc6a619 100644 --- a/openslides/application/templates/application/overview.html +++ b/openslides/application/templates/application/overview.html @@ -49,7 +49,7 @@ {% if application.number %}{{ application.number }}{% else %}-{% endif %} {{ application.public_version.title }} {% if min_supporters > 0 %} - {{ application.supporter.count }} + {{ application.count_supporters }} {% endif %} {% if application.status != "pub" %} {{ application.get_status_display }}
From 9f9ea81fc698c5ec0adfbeb06eef90328a795d3b Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Wed, 19 Sep 2012 14:16:17 +0200 Subject: [PATCH 037/222] Fixed attribute error if anonymous opens application/assignment view. --- openslides/application/models.py | 5 ++++- openslides/assignment/models.py | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/openslides/application/models.py b/openslides/application/models.py index df1d8195f..bac0f47f0 100644 --- a/openslides/application/models.py +++ b/openslides/application/models.py @@ -164,7 +164,10 @@ class Application(models.Model, SlideMixin): yield object.person def is_supporter(self, person): - return self.applicationsupporter_set.filter(person=person).exists() + try: + return self.applicationsupporter_set.filter(person=person).exists() + except AttributeError: + return False @property def enough_supporters(self): diff --git a/openslides/assignment/models.py b/openslides/assignment/models.py index dcd8a6e15..19c9886bf 100644 --- a/openslides/assignment/models.py +++ b/openslides/assignment/models.py @@ -122,8 +122,11 @@ class Assignment(models.Model, SlideMixin): """ return True, if person is a candidate. """ - return self.assignment_candidats.filter(person=person) \ + try: + return self.assignment_candidats.filter(person=person) \ .exclude(blocked=True).exists() + except AttributeError: + return False def is_blocked(self, person): """ From a60f03aebc0a08ea724363425979107ff22855f7 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Wed, 19 Sep 2012 17:00:40 +0200 Subject: [PATCH 038/222] Fixed: Application is deleted if user clicks 'No' in confirm form. --- openslides/application/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openslides/application/views.py b/openslides/application/views.py index 5b8e3dcce..cc9b18bd5 100644 --- a/openslides/application/views.py +++ b/openslides/application/views.py @@ -466,7 +466,7 @@ class ApplicationDelete(DeleteView): elif self.object: if not 'delete' in self.object.get_allowed_actions(user=request.user): messages.error(request, _("You can not delete motion %s.") % self.object) - else: + elif self.get_answer() == 'yes': title = self.object.title self.object.delete(force=True) messages.success(request, _("Motion %s was successfully deleted.") % title) From 5b97250df2393506c082a43603de7ccacad0c240 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 20 Sep 2012 09:55:27 +0200 Subject: [PATCH 039/222] Small fix with the overlay message --- openslides/projector/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openslides/projector/views.py b/openslides/projector/views.py index 862044b97..6a71ad637 100644 --- a/openslides/projector/views.py +++ b/openslides/projector/views.py @@ -73,6 +73,7 @@ class Projector(TemplateView, AjaxMixin): except AttributeError: #TODO: It has to be an Slide.DoesNotExist data = None ajax = 'on' + active_sid = get_active_slide(True) else: data = get_slide_from_sid(sid) ajax = 'off' @@ -88,7 +89,7 @@ class Projector(TemplateView, AjaxMixin): # Projector Overlays if self.kwargs['sid'] is None: active_defs = ProjectorOverlay.objects.filter(active=True) \ - .filter(Q(sid=sid) | Q(sid=None)).values_list('def_name', + .filter(Q(sid=active_sid) | Q(sid=None)).values_list('def_name', flat=True) for receiver, response in projector_overlays.send(sender=sid, register=False, call=active_defs): From fa9874038e6f6e0cb8e6b59b6d586224949cab28 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Thu, 20 Sep 2012 20:45:37 +0200 Subject: [PATCH 040/222] New welcome widget. --- .../templates/projector/welcome_widget.html | 13 ++++++++++++ openslides/projector/views.py | 21 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 openslides/projector/templates/projector/welcome_widget.html diff --git a/openslides/projector/templates/projector/welcome_widget.html b/openslides/projector/templates/projector/welcome_widget.html new file mode 100644 index 000000000..95a9c4376 --- /dev/null +++ b/openslides/projector/templates/projector/welcome_widget.html @@ -0,0 +1,13 @@ +{% load i18n %} +{% load tags %} + +{% if welcometext %} +

{{ welcometext|safe|linebreaks }}

+{% endif %} + +

{% trans "You have access to the following pages:" %}

+ diff --git a/openslides/projector/views.py b/openslides/projector/views.py index 862044b97..fb3428141 100644 --- a/openslides/projector/views.py +++ b/openslides/projector/views.py @@ -371,6 +371,27 @@ def get_widgets(request): """ widgets = [] + # welcome widget + apps = [] + for app in settings.INSTALLED_APPS: + try: + mod = import_module(app + '.views') + tab = mod.register_tab(request) + except (ImportError, AttributeError): + continue + if tab.permission: + apps.append(tab) + context = { + 'apps': apps, + 'welcometext': config['frontpage_welcometext']} + widgets.append(Widget( + name='welcome', + display_name=config['frontpage_title'], + template='projector/welcome_widget.html', + context=context, + permission_required='projector.can_see_dashboard', + default_column=1)) + # Projector live view widget widgets.append(Widget( name='live_view', From fe69973dccfa728e617365aea0de29589a6d10fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Tue, 23 Oct 2012 02:03:47 +0200 Subject: [PATCH 041/222] Change version number to 1.3a1. Insert git hash as suffix of the version number. (Ticket #388) --- openslides/__init__.py | 84 +++++++++++------------------------------- 1 file changed, 22 insertions(+), 62 deletions(-) diff --git a/openslides/__init__.py b/openslides/__init__.py index f3f4c88a3..17d119cf0 100644 --- a/openslides/__init__.py +++ b/openslides/__init__.py @@ -5,11 +5,14 @@ :license: GNU GPL, see LICENSE for more details. """ -VERSION = (1, 2, 0, 'final', 1) +VERSION = (1, 3, 0, 'alpha', 1) + def get_version(version=None): - """Derives a PEP386-compliant version number from VERSION.""" - # TODO: Get the Version Hash from GIT. + """ + Derives a PEP386-compliant version number from VERSION. Adds id of + the current git commit. + """ if version is None: version = VERSION assert len(version) == 5 @@ -17,67 +20,24 @@ def get_version(version=None): # Now build the two parts of the version number: # main = X.Y[.Z] - # sub = .devN - for pre-alpha releases - # | {a|b|c}N - for alpha, beta and rc releases + # sub = {a|b|c}N for alpha, beta and rc releases + # git's commit id is added - parts = 2 if version[2] == 0 else 3 - main = '.'.join(str(x) for x in version[:parts]) + main_parts = 2 if version[2] == 0 else 3 + main = '.'.join(str(x) for x in version[:main_parts]) - sub = '' - if version[3] == 'alpha' and version[4] == 0: - mercurial_version = hg_version() - if mercurial_version != 'unknown': - sub = '.dev%s' % mercurial_version + if version[3] != 'final': + mapping = {'alpha': 'a', 'beta': 'b', 'rc': 'c'} + sub = mapping[version[3]] + str(version[4]) + try: + git_head_path = '.git/' + open('.git/HEAD', 'r').read()[5:].rstrip() + except IOError: + git_commit_id = 'unknown' else: - sub = '.dev' - - elif version[3] != 'final': - sub = "-" + version[3] + str(version[4]) + import os + git_commit_id = open(os.path.abspath(git_head_path), 'r').read().rstrip() + sub = '%s commit %s' % (sub, git_commit_id) + else: + sub = '' return main + sub - - -def hg_version(): - import socket - import os - import sys - from os.path import realpath, join, dirname - try: - from mercurial import ui as hgui - from mercurial.localrepo import localrepository - from mercurial.node import short as shorthex - from mercurial.error import RepoError - nomercurial = False - except ImportError: - return 'unknown' - - os.environ['HGRCPATH'] = '' - conts = realpath(join(dirname(__file__))) - try: - ui = hgui.ui() - repository = localrepository(ui, join(conts, '..')) - ctx = repository['.'] - if ctx.tags() and ctx.tags() != ['tip']: - version = ' '.join(ctx.tags()) - else: - version = '%(num)s:%(id)s' % { - 'num': ctx.rev(), 'id': shorthex(ctx.node()) - } - except TypeError: - version = 'unknown' - except RepoError: - return 0 - - # This value defines the timeout for sockets in seconds. Per default python - # sockets do never timeout and as such we have blocking workers. - # Socket timeouts are set globally within the whole application. - # The value *must* be a floating point value. - socket.setdefaulttimeout(10.0) - - return version - - -## import os, site -## -## SITE_ROOT = os.path.realpath(os.path.dirname(__file__)) -## site.addsitedir(SITE_ROOT) From c036be05bfaef40a3f5618fc361895e9a6396e1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Tue, 23 Oct 2012 11:54:18 +0200 Subject: [PATCH 042/222] Fix new class based view for support/unsupport motions. Fix strange error in QuestionMixin. --- openslides/application/views.py | 16 +++++----------- openslides/utils/views.py | 2 +- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/openslides/application/views.py b/openslides/application/views.py index 310d8c0d3..8afb73921 100644 --- a/openslides/application/views.py +++ b/openslides/application/views.py @@ -364,13 +364,13 @@ def reset(request, application_id): return redirect(reverse('application_view', args=[application_id])) -class SupportView(RedirectView, SingleObjectMixin, QuestionMixin): +class SupportView(SingleObjectMixin, QuestionMixin, RedirectView): """ Support or unsupport an application """ permission_required = 'application.can_support_application' model = Application - pk_url_kwarg = 'application_id' # TODO: Is this line neccessary? + pk_url_kwarg = 'application_id' unsupport = False # Must be given in SupportView.as_view() answer_url = None # Must be given in SupportView.as_view() @@ -380,24 +380,18 @@ class SupportView(RedirectView, SingleObjectMixin, QuestionMixin): else: return _('Do you really want to unsupport this motion?') - # TODO: Why do we have to overwrite this method? - def pre_redirect(self, request, *args, **kwargs): - self.confirm_form() - def pre_post_redirect(self, request, *args, **kwargs): if self.get_answer().lower() == 'yes': if not self.unsupport: - Application.objects.get(pk=kwargs['application_id']).support(person=request.user) - # Should the Exception Application.DoesNotExist be kept or not? + self.get_object().support(person=request.user) self.success_message = _("You have supported this motion successfully.") else: - Application.objects.get(pk=kwargs['application_id']).unsupport(person=request.user) - # Should the Exception Application.DoesNotExist be kept or not? + self.get_object().unsupport(person=request.user) self.success_message = _("You have unsupported this motion successfully.") messages.success(request, self.success_message) def get_redirect_url(self, **kwargs): - return reverse('application_view', args=[kwargs['application_id']]) + return reverse('application_view', args=[kwargs[self.pk_url_kwarg]]) @permission_required('application.can_manage_application') diff --git a/openslides/utils/views.py b/openslides/utils/views.py index becdbfc8b..363bb2d90 100644 --- a/openslides/utils/views.py +++ b/openslides/utils/views.py @@ -143,7 +143,7 @@ class QuestionMixin(object): 'option_fields': option_fields}) def pre_redirect(self, request, *args, **kwargs): - self.confirm_form(request, self.object) + self.confirm_form() def pre_post_redirect(self, request, *args, **kwargs): messages.success(request) From 681d909fa383e583abf67d6d31599aeced393118 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Wed, 24 Oct 2012 11:04:23 +0200 Subject: [PATCH 043/222] rename application to motion --- .../application/base_application.html | 66 -- .../templates/application/widget.html | 34 - openslides/application/urls.py | 141 ---- openslides/assignment/models.py | 2 +- openslides/config/views.py | 2 +- .../{application => motion}/__init__.py | 0 openslides/{application => motion}/forms.py | 32 +- openslides/{application => motion}/models.py | 188 +++--- .../motion/templates/motion/base_motion.html | 66 ++ .../templates/motion}/config.html | 8 +- .../templates/motion}/edit.html | 10 +- .../templates/motion}/import.html | 6 +- .../templates/motion}/overview.html | 38 +- .../templates/motion}/poll_view.html | 16 +- .../templates/motion}/view.html | 106 +-- .../motion/templates/motion/widget.html | 34 + .../templates/projector/Motion.html} | 28 +- openslides/{application => motion}/tests.py | 12 +- openslides/motion/urls.py | 141 ++++ openslides/{application => motion}/views.py | 606 +++++++++--------- openslides/openslides_global_settings.py | 2 +- .../templates/participant/config.html | 4 +- openslides/urls.py | 2 +- openslides/utils/templatetags/tags.py | 2 +- 24 files changed, 773 insertions(+), 773 deletions(-) delete mode 100644 openslides/application/templates/application/base_application.html delete mode 100644 openslides/application/templates/application/widget.html delete mode 100644 openslides/application/urls.py rename openslides/{application => motion}/__init__.py (100%) rename openslides/{application => motion}/forms.py (77%) rename openslides/{application => motion}/models.py (73%) create mode 100644 openslides/motion/templates/motion/base_motion.html rename openslides/{application/templates/application => motion/templates/motion}/config.html (67%) rename openslides/{application/templates/application => motion/templates/motion}/edit.html (83%) rename openslides/{application/templates/application => motion/templates/motion}/import.html (89%) rename openslides/{application/templates/application => motion/templates/motion}/overview.html (71%) rename openslides/{application/templates/application => motion/templates/motion}/poll_view.html (79%) rename openslides/{application/templates/application => motion/templates/motion}/view.html (64%) create mode 100644 openslides/motion/templates/motion/widget.html rename openslides/{application/templates/projector/Application.html => motion/templates/projector/Motion.html} (74%) rename openslides/{application => motion}/tests.py (77%) create mode 100644 openslides/motion/urls.py rename openslides/{application => motion}/views.py (54%) diff --git a/openslides/application/templates/application/base_application.html b/openslides/application/templates/application/base_application.html deleted file mode 100644 index c886215ef..000000000 --- a/openslides/application/templates/application/base_application.html +++ /dev/null @@ -1,66 +0,0 @@ -{% extends "base.html" %} - -{% load tags %} -{% load i18n %} -{% load staticfiles %} - -{% block submenu %} - {% url application_overview as url_applicationoverview %} -

{% trans "Motions" %}

- - - {# second submenu #} - {% if application %} -
-

{% trans "Application No." %} - {% if application.number != None %} - {{ application.number }} - {% else %} - [-] - {% endif %} -

- - {% endif %} -{% endblock %} diff --git a/openslides/application/templates/application/widget.html b/openslides/application/templates/application/widget.html deleted file mode 100644 index e41c7b370..000000000 --- a/openslides/application/templates/application/widget.html +++ /dev/null @@ -1,34 +0,0 @@ -{% load staticfiles %} -{% load i18n %} -{% load tags %} - - - diff --git a/openslides/application/urls.py b/openslides/application/urls.py deleted file mode 100644 index 3b3e83e9e..000000000 --- a/openslides/application/urls.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -""" - openslides.application.urls - ~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - URL list for the application app. - - :copyright: 2011, 2012 by OpenSlides team, see AUTHORS. - :license: GNU GPL, see LICENSE for more details. -""" - -from django.conf.urls.defaults import url, patterns - -from openslides.application.views import (ApplicationDelete, ViewPoll, - ApplicationPDF, ApplicationPollPDF, CreateAgendaItem) - -urlpatterns = patterns('openslides.application.views', - url(r'^$', - 'overview', - name='application_overview', - ), - - url(r'^(?P\d+)/$', - 'view', - name='application_view', - ), - - url(r'^(?P\d+)/agenda/$', - CreateAgendaItem.as_view(), - name='application_create_agenda', - ), - - url(r'^(?P\d+)/newest/$', - 'view', - {'newest': True}, - name='application_view_newest', - ), - - url(r'^new/$', - 'edit', - name='application_new', - ), - - url(r'^import/$', - 'application_import', - name='application_import', - ), - - url(r'^(?P\d+)/edit/$', - 'edit', - name='application_edit', - ), - - url(r'^(?P\d+)/del/$', - ApplicationDelete.as_view(), - name='application_delete', - ), - - url(r'^del/$', - ApplicationDelete.as_view(), - { 'application_id' : None , 'application_ids' : None }, - name='application_delete', - ), - - url(r'^(?P\d+)/setnumber/$', - 'set_number', - name='application_set_number', - ), - - url(r'^(?P\d+)/setstatus/(?P[a-z]{3})/$', - 'set_status', - name='application_set_status', - ), - - url(r'^(?P\d+)/permit/$', - 'permit', - name='application_permit', - ), - - url(r'^version/(?P\d+)/permit/$', - 'permit_version', - name='application_version_permit', - ), - - url(r'^version/(?P\d+)/reject/$', - 'reject_version', - name='application_version_reject', - ), - - url(r'^(?P\d+)/notpermit/$', - 'notpermit', - name='application_notpermit', - ), - - url(r'^(?P\d+)/reset/$', - 'reset', - name='application_reset', - ), - - url(r'^(?P\d+)/support/$', - 'support', - name='application_support', - ), - - url(r'^(?P\d+)/unsupport/$', - 'unsupport', - name='application_unsupport', - ), - - url(r'^(?P\d+)/gen_poll/$', - 'gen_poll', - name='application_gen_poll', - ), - - url(r'^print/$', - ApplicationPDF.as_view(), - {'application_id': None}, - name='print_applications', - ), - - url(r'^(?P\d+)/print/$', - ApplicationPDF.as_view(), - name='print_application', - ), - - url(r'^poll/(?P\d+)/print/$', - ApplicationPollPDF.as_view(), - name='print_application_poll', - ), - - url(r'^poll/(?P\d+)/$', - ViewPoll.as_view(), - name='application_poll_view', - ), - - url(r'^poll/(?P\d+)/del/$', - 'delete_poll', - name='application_poll_delete', - ), -) diff --git a/openslides/assignment/models.py b/openslides/assignment/models.py index 19c9886bf..af67411a6 100644 --- a/openslides/assignment/models.py +++ b/openslides/assignment/models.py @@ -218,7 +218,7 @@ class Assignment(models.Model, SlideMixin): return self.name def delete(self): - # Remove any Agenda-Item, which is related to this application. + # Remove any Agenda-Item, which is related to this assignment. for item in Item.objects.filter(related_sid=self.sid): item.delete() super(Assignment, self).delete() diff --git a/openslides/config/views.py b/openslides/config/views.py index fc2d5037e..19b7b9953 100644 --- a/openslides/config/views.py +++ b/openslides/config/views.py @@ -67,7 +67,7 @@ class GeneralConfig(FormView): anonymous = Group.objects.get(name='Anonymous') except Group.DoesNotExist: default_perms = [u'can_see_agenda', u'can_see_projector', - u'can_see_application', u'can_see_assignment'] + u'can_see_motion', u'can_see_assignment'] anonymous = Group() anonymous.name = 'Anonymous' anonymous.save() diff --git a/openslides/application/__init__.py b/openslides/motion/__init__.py similarity index 100% rename from openslides/application/__init__.py rename to openslides/motion/__init__.py diff --git a/openslides/application/forms.py b/openslides/motion/forms.py similarity index 77% rename from openslides/application/forms.py rename to openslides/motion/forms.py index a6cc0bfad..cf144feec 100644 --- a/openslides/application/forms.py +++ b/openslides/motion/forms.py @@ -1,10 +1,10 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- """ - openslides.application.forms + openslides.motion.forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Forms for the application app. + Forms for the motion app. :copyright: 2011, 2012 by OpenSlides team, see AUTHORS. :license: GNU GPL, see LICENSE for more details. @@ -15,36 +15,36 @@ from django.utils.translation import ugettext_lazy as _, ugettext_noop from openslides.utils.forms import CssClassMixin from openslides.utils.person import PersonFormField, MultiplePersonFormField -from openslides.application.models import Application +from openslides.motion.models import Motion -class ApplicationForm(forms.Form, CssClassMixin): +class MotionForm(forms.Form, CssClassMixin): title = forms.CharField(widget=forms.TextInput(), label=_("Title")) text = forms.CharField(widget=forms.Textarea(), label=_("Text")) reason = forms.CharField(widget=forms.Textarea(), required=False, label=_("Reason")) -class ApplicationFormTrivialChanges(ApplicationForm): +class MotionFormTrivialChanges(MotionForm): trivial_change = forms.BooleanField(required=False, label=_("Trivial change"), help_text=_("Trivial changes don't create a new version.")) -class ApplicationManagerForm(forms.ModelForm, CssClassMixin): +class MotionManagerForm(forms.ModelForm, CssClassMixin): submitter = PersonFormField() class Meta: - model = Application + model = Motion exclude = ('number', 'status', 'permitted', 'log', 'supporter') -class ApplicationManagerFormSupporter(ApplicationManagerForm): +class MotionManagerFormSupporter(MotionManagerForm): # TODO: Do not show the submitter in the user-list supporter = MultiplePersonFormField(required=False, label=_("Supporters")) -class ApplicationImportForm(forms.Form, CssClassMixin): +class MotionImportForm(forms.Form, CssClassMixin): csvfile = forms.FileField( widget=forms.FileInput(attrs={'size':'50'}), label=_("CSV File"), @@ -58,7 +58,7 @@ class ApplicationImportForm(forms.Form, CssClassMixin): class ConfigForm(forms.Form, CssClassMixin): - application_min_supporters = forms.IntegerField( + motion_min_supporters = forms.IntegerField( widget=forms.TextInput(attrs={'class':'small-input'}), label=_("Number of (minimum) required supporters for a motion"), initial=4, @@ -66,12 +66,12 @@ class ConfigForm(forms.Form, CssClassMixin): max_value=8, help_text=_("Choose 0 to disable the supporting system"), ) - application_preamble = forms.CharField( + motion_preamble = forms.CharField( widget=forms.TextInput(), required=False, label=_("Motion preamble") ) - application_pdf_ballot_papers_selection = forms.ChoiceField( + motion_pdf_ballot_papers_selection = forms.ChoiceField( widget=forms.Select(), required=False, label=_("Number of ballot papers (selection)"), @@ -81,24 +81,24 @@ class ConfigForm(forms.Form, CssClassMixin): ("CUSTOM_NUMBER", _("Use the following custom number")), ] ) - application_pdf_ballot_papers_number = forms.IntegerField( + motion_pdf_ballot_papers_number = forms.IntegerField( widget=forms.TextInput(attrs={'class':'small-input'}), required=False, min_value=1, label=_("Custom number of ballot papers") ) - application_pdf_title = forms.CharField( + motion_pdf_title = forms.CharField( widget=forms.TextInput(), required=False, label=_("Title for PDF document (all motions)") ) - application_pdf_preamble = forms.CharField( + motion_pdf_preamble = forms.CharField( widget=forms.Textarea(), required=False, label=_("Preamble text for PDF document (all motions)") ) - application_allow_trivial_change = forms.BooleanField( + motion_allow_trivial_change = forms.BooleanField( label=_("Allow trivial changes"), help_text=_('Warning: Trivial changes undermine the motions ' 'autorisation system.'), diff --git a/openslides/application/models.py b/openslides/motion/models.py similarity index 73% rename from openslides/application/models.py rename to openslides/motion/models.py index bac0f47f0..4a06dc492 100644 --- a/openslides/application/models.py +++ b/openslides/motion/models.py @@ -1,10 +1,10 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- """ - openslides.application.models + openslides.motion.models ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Models for the application app. + Models for the motion app. :copyright: 2011, 2012 by OpenSlides team, see AUTHORS. :license: GNU GPL, see LICENSE for more details. @@ -34,13 +34,13 @@ from openslides.projector.models import SlideMixin from openslides.agenda.models import Item -class ApplicationSupporter(models.Model): - application = models.ForeignKey("Application") +class MotionSupporter(models.Model): + motion = models.ForeignKey("Motion") person = PersonField() -class Application(models.Model, SlideMixin): - prefix = "application" +class Motion(models.Model, SlideMixin): + prefix = "motion" STATUS = ( ('pub', _('Published')), ('per', _('Permitted')), @@ -74,10 +74,10 @@ class Application(models.Model, SlideMixin): @property def last_version(self): """ - Return last version of the application. + Return last version of the motion. """ try: - return AVersion.objects.filter(application=self).order_by('id') \ + return AVersion.objects.filter(motion=self).order_by('id') \ .reverse()[0] except IndexError: return None @@ -85,7 +85,7 @@ class Application(models.Model, SlideMixin): @property def public_version(self): """ - Return permitted, if the application was permitted, else last_version + Return permitted, if the motion was permitted, else last_version """ if self.permitted is not None: return self.permitted @@ -115,14 +115,14 @@ class Application(models.Model, SlideMixin): @property def versions(self): """ - Return a list of all versions of the application. + Return a list of all versions of the motion. """ - return AVersion.objects.filter(application=self) + return AVersion.objects.filter(motion=self) @property def creation_time(self): """ - Return the time of the creation of the application. + Return the time of the creation of the motion. """ try: return self.versions[0].time @@ -132,7 +132,7 @@ class Application(models.Model, SlideMixin): @property def notes(self): """ - Return some information of the application. + Return some information of the motion. """ note = [] if self.status == "pub" and not self.enough_supporters: @@ -146,9 +146,9 @@ class Application(models.Model, SlideMixin): @property def unpermitted_changes(self): """ - Return True if the application has unpermitted changes. + Return True if the motion has unpermitted changes. - The application has unpermitted changes, if the permitted-version + The motion has unpermitted changes, if the permitted-version is not the lastone and the lastone is not rejected. TODO: rename the property in unchecked__changes """ @@ -160,35 +160,35 @@ class Application(models.Model, SlideMixin): @property def supporters(self): - for object in self.applicationsupporter_set.all(): + for object in self.motionsupporter_set.all(): yield object.person def is_supporter(self, person): try: - return self.applicationsupporter_set.filter(person=person).exists() + return self.motionsupporter_set.filter(person=person).exists() except AttributeError: return False @property def enough_supporters(self): """ - Return True, if the application has enough supporters + Return True, if the motion has enough supporters """ - min_supporters = int(config['application_min_supporters']) + min_supporters = int(config['motion_min_supporters']) if self.status == "pub": return self.count_supporters() >= min_supporters else: return True def count_supporters(self): - return self.applicationsupporter_set.count() + return self.motionsupporter_set.count() @property def missing_supporters(self): """ Return number of missing supporters """ - min_supporters = int(config['application_min_supporters']) + min_supporters = int(config['motion_min_supporters']) delta = min_supporters - self.count_supporters() if delta > 0: return delta @@ -197,9 +197,9 @@ class Application(models.Model, SlideMixin): def save(self, user=None, nonewversion=False, trivial_change=False): """ - Save the Application, and create a new AVersion if necessary + Save the Motion, and create a new AVersion if necessary """ - super(Application, self).save() + super(Motion, self).save() if nonewversion: return last_version = self.last_version @@ -229,14 +229,14 @@ class Application(models.Model, SlideMixin): version = AVersion(title=getattr(self, 'title', ''), text=getattr(self, 'text', ''), reason=getattr(self, 'reason', ''), - application=self) + motion=self) version.save() self.writelog(_("Version %s created") % version.aid, user) - is_manager = user.has_perm('application.can_manage_application') + is_manager = user.has_perm('motion.can_manage_motion') except AttributeError: is_manager = False - supporters = self.applicationsupporter_set.all() + supporters = self.motionsupporter_set.all() if (self.status == "pub" and supporters and not is_manager): @@ -245,7 +245,7 @@ class Application(models.Model, SlideMixin): def reset(self, user): """ - Reset the application. + Reset the motion. """ self.status = "pub" self.permitted = None @@ -254,43 +254,43 @@ class Application(models.Model, SlideMixin): def support(self, person): """ - Add a Supporter to the list of supporters of the application. + Add a Supporter to the list of supporters of the motion. """ if person == self.submitter: # TODO: Use own Exception raise NameError('Supporter can not be the submitter of a ' \ - 'application.') + 'motion.') if self.permitted is not None: # TODO: Use own Exception - raise NameError('This application is already permitted.') + raise NameError('This motion is already permitted.') if not self.is_supporter(person): - ApplicationSupporter(application=self, person=person).save() + MotionSupporter(motion=self, person=person).save() self.writelog(_("Supporter: +%s") % (person)) def unsupport(self, person): """ - remove a supporter from the list of supporters of the application + remove a supporter from the list of supporters of the motion """ if self.permitted is not None: # TODO: Use own Exception - raise NameError('This application is already permitted.') + raise NameError('This motion is already permitted.') try: - object = self.applicationsupporter_set.get(person=person).delete() - except ApplicationSupporter.DoesNotExist: + object = self.motionsupporter_set.get(person=person).delete() + except MotionSupporter.DoesNotExist: pass else: self.writelog(_("Supporter: -%s") % (person)) def set_number(self, number=None, user=None): """ - Set a number for ths application. + Set a number for ths motion. """ if self.number is not None: # TODO: Use own Exception - raise NameError('This application has already a number.') + raise NameError('This motion has already a number.') if number is None: try: - number = Application.objects.aggregate(Max('number')) \ + number = Motion.objects.aggregate(Max('number')) \ ['number__max'] + 1 except TypeError: number = 1 @@ -301,7 +301,7 @@ class Application(models.Model, SlideMixin): def permit(self, user=None): """ - Change the status of this application to permit. + Change the status of this motion to permit. """ self.set_status(user, "per") aversion = self.last_version @@ -314,7 +314,7 @@ class Application(models.Model, SlideMixin): def notpermit(self, user=None): """ - Change the status of this application to 'not permitted (rejected)'. + Change the status of this motion to 'not permitted (rejected)'. """ self.set_status(user, "nop") #TODO: reject last version @@ -327,10 +327,10 @@ class Application(models.Model, SlideMixin): def set_status(self, user, status, force=False): """ - Set the status of the application. + Set the status of the motion. """ error = True - for a, b in Application.STATUS: + for a, b in Motion.STATUS: if status == a: error = False break @@ -364,25 +364,25 @@ class Application(models.Model, SlideMixin): """ actions = [] - # check if user allowed to withdraw an application + # check if user allowed to withdraw an motion if ((self.status == "pub" and self.number and user == self.submitter) or (self.status == "pub" and self.number - and user.has_perm("application.can_manage_application")) + and user.has_perm("motion.can_manage_motion")) or (self.status == "per" and user == self.submitter) or (self.status == "per" - and user.has_perm("application.can_manage_application"))): + and user.has_perm("motion.can_manage_motion"))): actions.append("wit") - #Check if the user can review the application + #Check if the user can review the motion if (self.status == "rev" and (self.submitter == user - or user.has_perm("application.can_manage_application"))): + or user.has_perm("motion.can_manage_motion"))): actions.append("pub") - # Check if the user can support and unspoort the application + # Check if the user can support and unspoort the motion if (self.status == "pub" and user != self.submitter and not self.is_supporter(user)): @@ -391,22 +391,22 @@ class Application(models.Model, SlideMixin): if self.status == "pub" and self.is_supporter(user): actions.append("unsupport") - #Check if the user can edit the application + #Check if the user can edit the motion if (user == self.submitter \ and (self.status in ('pub', 'per'))) \ - or user.has_perm("application.can_manage_application"): + or user.has_perm("motion.can_manage_motion"): actions.append("edit") - # Check if the user can delete the application (admin, manager, owner) + # Check if the user can delete the motion (admin, manager, owner) # reworked as requiered in #100 - if (user.has_perm("applicatoin.can_delete_all_applications") or - (user.has_perm("application.can_manage_application") and + if (user.has_perm("applicatoin.can_delete_all_motions") or + (user.has_perm("motion.can_manage_motion") and self.number is None) or (self.submitter == user and self.number is None)): actions.append("delete") #For the rest, all actions need the manage permission - if not user.has_perm("application.can_manage_application"): + if not user.has_perm("motion.can_manage_motion"): return actions if self.status == "pub": @@ -430,17 +430,17 @@ class Application(models.Model, SlideMixin): def delete(self, force=False): """ - Delete the application. It is not possible, if the application has + Delete the motion. It is not possible, if the motion has allready a number """ if self.number and not force: - raise NameError('The application has already a number. ' \ + raise NameError('The motion has already a number. ' \ 'You can not delete it.') for item in Item.objects.filter(related_sid=self.sid): item.delete() - super(Application, self).delete() + super(Motion, self).delete() def writelog(self, text, user=None): if not self.log: @@ -461,7 +461,7 @@ class Application(models.Model, SlideMixin): def __getattr__(self, name): """ if name is title, text, reason or time, - Return this attribute from the newest version of the application + Return this attribute from the newest version of the motion """ if name in ('title', 'text', 'reason', 'time', 'aid'): try: @@ -476,9 +476,9 @@ class Application(models.Model, SlideMixin): def gen_poll(self, user=None): """ - Generates a poll object for the application + Generates a poll object for the motion """ - poll = ApplicationPoll(application=self) + poll = MotionPoll(motion=self) poll.save() poll.set_options() self.writelog(_("Poll created"), user) @@ -486,7 +486,7 @@ class Application(models.Model, SlideMixin): @property def polls(self): - return self.applicationpoll_set.all() + return self.motionpoll_set.all() @property def results(self): @@ -510,19 +510,19 @@ class Application(models.Model, SlideMixin): """ return the slide dict """ - data = super(Application, self).slide() - data['application'] = self + data = super(Motion, self).slide() + data['motion'] = self data['title'] = self.title - data['template'] = 'projector/Application.html' + data['template'] = 'projector/Motion.html' return data def get_absolute_url(self, link='view'): if link == 'view': - return reverse('application_view', args=[str(self.id)]) + return reverse('motion_view', args=[str(self.id)]) if link == 'edit': - return reverse('application_edit', args=[str(self.id)]) + return reverse('motion_edit', args=[str(self.id)]) if link == 'delete': - return reverse('application_delete', args=[str(self.id)]) + return reverse('motion_delete', args=[str(self.id)]) def __unicode__(self): try: @@ -532,10 +532,10 @@ class Application(models.Model, SlideMixin): class Meta: permissions = ( - ('can_see_application', ugettext_noop("Can see motions")), - ('can_create_application', ugettext_noop("Can create motions")), - ('can_support_application', ugettext_noop("Can support motions")), - ('can_manage_application', ugettext_noop("Can manage motions")), + ('can_see_motion', ugettext_noop("Can see motions")), + ('can_create_motion', ugettext_noop("Can create motions")), + ('can_support_motion', ugettext_noop("Can support motions")), + ('can_manage_motion', ugettext_noop("Can manage motions")), ) ordering = ('number',) @@ -546,7 +546,7 @@ class AVersion(models.Model): reason = models.TextField(null=True, blank=True, verbose_name = _("Reason")) rejected = models.BooleanField() # = Not Permitted time = models.DateTimeField(auto_now=True) - application = models.ForeignKey(Application) + motion = models.ForeignKey(Motion) def __unicode__(self): return "%s %s" % (self.id, self.title) @@ -557,31 +557,31 @@ class AVersion(models.Model): return self._aid except AttributeError: self._aid = AVersion.objects \ - .filter(application=self.application) \ + .filter(motion=self.motion) \ .filter(id__lte=self.id).count() return self._aid -register_slidemodel(Application) +register_slidemodel(Motion) -class ApplicationVote(BaseVote): - option = models.ForeignKey('ApplicationOption') +class MotionVote(BaseVote): + option = models.ForeignKey('MotionOption') -class ApplicationOption(BaseOption): - poll = models.ForeignKey('ApplicationPoll') - vote_class = ApplicationVote +class MotionOption(BaseOption): + poll = models.ForeignKey('MotionPoll') + vote_class = MotionVote -class ApplicationPoll(BasePoll, CountInvalid, CountVotesCast): - option_class = ApplicationOption +class MotionPoll(BasePoll, CountInvalid, CountVotesCast): + option_class = MotionOption vote_values = [ugettext_noop('Yes'), ugettext_noop('No'), ugettext_noop('Abstain')] - application = models.ForeignKey(Application) + motion = models.ForeignKey(Motion) - def get_application(self): - return self.application + def get_motion(self): + return self.motion def set_options(self): #TODO: maybe it is possible with .create() to call this without poll=self @@ -592,20 +592,20 @@ class ApplicationPoll(BasePoll, CountInvalid, CountVotesCast): CountVotesCast.append_pollform_fields(self, fields) def get_absolute_url(self): - return reverse('application_poll_view', args=[self.id]) + return reverse('motion_poll_view', args=[self.id]) def get_ballot(self): - return self.application.applicationpoll_set.filter(id__lte=self.id).count() + return self.motion.motionpoll_set.filter(id__lte=self.id).count() -@receiver(default_config_value, dispatch_uid="application_default_config") +@receiver(default_config_value, dispatch_uid="motion_default_config") def default_config(sender, key, **kwargs): return { - 'application_min_supporters': 0, - 'application_preamble': _('The assembly may decide,'), - 'application_pdf_ballot_papers_selection': 'CUSTOM_NUMBER', - 'application_pdf_ballot_papers_number': '8', - 'application_pdf_title': _('Motions'), - 'application_pdf_preamble': '', - 'application_allow_trivial_change': False, + 'motion_min_supporters': 0, + 'motion_preamble': _('The assembly may decide,'), + 'motion_pdf_ballot_papers_selection': 'CUSTOM_NUMBER', + 'motion_pdf_ballot_papers_number': '8', + 'motion_pdf_title': _('Motions'), + 'motion_pdf_preamble': '', + 'motion_allow_trivial_change': False, }.get(key) diff --git a/openslides/motion/templates/motion/base_motion.html b/openslides/motion/templates/motion/base_motion.html new file mode 100644 index 000000000..1466bfcf2 --- /dev/null +++ b/openslides/motion/templates/motion/base_motion.html @@ -0,0 +1,66 @@ +{% extends "base.html" %} + +{% load tags %} +{% load i18n %} +{% load staticfiles %} + +{% block submenu %} + {% url motion_overview as url_motionoverview %} +

{% trans "Motions" %}

+ + + {# second submenu #} + {% if motion %} +
+

{% trans "Motion No." %} + {% if motion.number != None %} + {{ motion.number }} + {% else %} + [-] + {% endif %} +

+ + {% endif %} +{% endblock %} diff --git a/openslides/application/templates/application/config.html b/openslides/motion/templates/motion/config.html similarity index 67% rename from openslides/application/templates/application/config.html rename to openslides/motion/templates/motion/config.html index 8dd65eddf..8f2ac89b8 100644 --- a/openslides/application/templates/application/config.html +++ b/openslides/motion/templates/motion/config.html @@ -2,18 +2,18 @@ {% load i18n %} -{% block title %}{{ block.super }} – {% trans "Application settings" %}{% endblock %} +{% block title %}{{ block.super }} – {% trans "Motion settings" %}{% endblock %} {% block content %} -

{% trans "Application settings" %}

+

{% trans "Motion settings" %}

{% csrf_token %} {{ form.as_p }}

- - diff --git a/openslides/application/templates/application/edit.html b/openslides/motion/templates/motion/edit.html similarity index 83% rename from openslides/application/templates/application/edit.html rename to openslides/motion/templates/motion/edit.html index aa97ecc04..ec56a07a1 100644 --- a/openslides/application/templates/application/edit.html +++ b/openslides/motion/templates/motion/edit.html @@ -1,10 +1,10 @@ -{% extends "application/base_application.html" %} +{% extends "motion/base_motion.html" %} {% load i18n %} {% block title %} {{ block.super }} – - {% if application %} + {% if motion %} {% trans "Edit motion" %} {% else %} {% trans "New motion" %} @@ -12,7 +12,7 @@ {% endblock %} {% block content %} - {% if application %} + {% if motion %}

{% trans "Edit motion" %}

{% else %}

{% trans "New motion" %}

@@ -28,8 +28,8 @@ - - diff --git a/openslides/application/templates/application/import.html b/openslides/motion/templates/motion/import.html similarity index 89% rename from openslides/application/templates/application/import.html rename to openslides/motion/templates/motion/import.html index a3bf756a7..828f9a00e 100644 --- a/openslides/application/templates/application/import.html +++ b/openslides/motion/templates/motion/import.html @@ -1,4 +1,4 @@ -{% extends "application/base_application.html" %} +{% extends "motion/base_motion.html" %} {% load i18n %} @@ -22,8 +22,8 @@ - - diff --git a/openslides/application/templates/application/overview.html b/openslides/motion/templates/motion/overview.html similarity index 71% rename from openslides/application/templates/application/overview.html rename to openslides/motion/templates/motion/overview.html index 45bc6a619..8d6b92613 100644 --- a/openslides/application/templates/application/overview.html +++ b/openslides/motion/templates/motion/overview.html @@ -1,4 +1,4 @@ -{% extends "application/base_application.html" %} +{% extends "motion/base_motion.html" %} {% load tags %} {% load i18n %} @@ -28,8 +28,8 @@

- {{ applications|length }} - {% blocktrans count counter=applications|length %}motion{% plural %}motions{% endblocktrans %} + {{ motions|length }} + {% blocktrans count counter=motions|length %}motion{% plural %}motions{% endblocktrans %} @@ -42,39 +42,39 @@ - {% for app_info in applications %} - {% with application=app_info.application useractions=app_info.actions %} + {% for app_info in motions %} + {% with motion=app_info.motion useractions=app_info.actions %} - - + {% if motion.active %}activeline{% endif %}"> + + {% if min_supporters > 0 %} - + {% endif %} - - - + + diff --git a/openslides/application/templates/application/poll_view.html b/openslides/motion/templates/motion/poll_view.html similarity index 79% rename from openslides/application/templates/application/poll_view.html rename to openslides/motion/templates/motion/poll_view.html index 67facddf5..b21236f23 100644 --- a/openslides/application/templates/application/poll_view.html +++ b/openslides/motion/templates/motion/poll_view.html @@ -1,16 +1,16 @@ -{% extends 'application/base_application.html' %} +{% extends 'motion/base_motion.html' %} {% load i18n %} {% load staticfiles %} {% block title %} - {{ block.super }} – {% trans "Motion" %} "{{ application.public_version.title }}" + {{ block.super }} – {% trans "Motion" %} "{{ motion.public_version.title }}" – {{ ballot }}. {% trans "Vote" %} {% endblock %} {% block content %} -

{{ application.public_version.title }} ({% trans "Motion" %} - {{ application.number }}) – {{ ballot }}. {% trans "Vote" %}

+

{{ motion.public_version.title }} ({% trans "Motion" %} + {{ motion.number }}) – {{ ballot }}. {% trans "Vote" %}

{% trans "Special values" %}: -1 = {% trans 'majority' %}; -2 = {% trans 'undocumented' %}{% csrf_token %} {{ pre_form }} @@ -40,8 +40,8 @@ {{ post_form }}

- - @@ -54,8 +54,8 @@ - - diff --git a/openslides/application/templates/application/view.html b/openslides/motion/templates/motion/view.html similarity index 64% rename from openslides/application/templates/application/view.html rename to openslides/motion/templates/motion/view.html index bce03af57..28cf76881 100644 --- a/openslides/application/templates/application/view.html +++ b/openslides/motion/templates/motion/view.html @@ -1,4 +1,4 @@ -{% extends "application/base_application.html" %} +{% extends "motion/base_motion.html" %} {% load tags %} {% load i18n %} @@ -16,15 +16,15 @@

@@ -204,8 +204,8 @@

{{ version.title }} ({% trans "Motion" %} - {% if application.number != None %} - {{ application.number }}) + {% if motion.number != None %} + {{ motion.number }}) {% else %} [{% trans "no number" %}]) {% endif %} @@ -213,12 +213,12 @@ {% trans "Version" %} {{ version.aid }} - {% if application.public_version != application.last_version %} + {% if motion.public_version != motion.last_version %} ⋅ - {% if version == application.public_version %} - {% trans "This is not the newest version." %} {% trans "Go to version" %} {{ application.last_version.aid }}. + {% if version == motion.public_version %} + {% trans "This is not the newest version." %} {% trans "Go to version" %} {{ motion.last_version.aid }}. {% else %} - {% trans "This is not the authorized version." %} {% trans "Go to version" %} {{ application.public_version.aid }}. + {% trans "This is not the authorized version." %} {% trans "Go to version" %} {{ motion.public_version.aid }}. {% endif %} {% endif %} @@ -235,7 +235,7 @@ {% endif %} - {% if application.versions|length > 1 %} + {% if motion.versions|length > 1 %}

{% trans "Version History" %}:

{% trans "Number" %}{% trans "Creation Time" %} {% trans "Actions" %}
{% if application.number %}{{ application.number }}{% else %}-{% endif %}{{ application.public_version.title }}{% if motion.number %}{{ motion.number }}{% else %}-{% endif %}{{ motion.public_version.title }}{{ application.count_supporters }}{{ motion.count_supporters }}{% if application.status != "pub" %} - {{ application.get_status_display }}
+
{% if motion.status != "pub" %} + {{ motion.get_status_display }}
{% endif %} - {% for note in application.notes %} + {% for note in motion.notes %} {{ note }} {% if not forloop.last %}
{%endif%} {% endfor %}
{{ application.submitter }}{{ application.creation_time }}{{ motion.submitter }}{{ motion.creation_time }} {% if perms.projector.can_manage_projector %} - + {% endif %} - {% if perms.application.can_manage_application %} - + {% if perms.motion.can_manage_motion %} + {% if "delete" in useractions %} - + {% endif %} {% endif %} - +
@@ -248,18 +248,18 @@ - {% for revision in application.versions %} + {% for revision in motion.versions %}
{% trans "Reason" %}
- {% if application.status != "pub" %} - {% if revision == application.permitted %} + {% if motion.status != "pub" %} + {% if revision == motion.permitted %} {% else %} - {% if perms.application.can_manage_application %} - + {% if perms.motion.can_manage_motion %} + {% endif %} - {% if not revision.rejected and revision.id > application.permitted.id and perms.application.can_manage_application %} - + {% if not revision.rejected and revision.id > motion.permitted.id and perms.motion.can_manage_motion %} + {% endif %} {% endif %} {% if revision.rejected %} @@ -295,9 +295,9 @@
{% endif %} - {% if perms.application.can_manage_application %} + {% if perms.motion.can_manage_motion %}

{% trans "Log" %}:

- {{ application.log|linebreaks }} + {{ motion.log|linebreaks }} {% endif %}
{% endblock %} diff --git a/openslides/motion/templates/motion/widget.html b/openslides/motion/templates/motion/widget.html new file mode 100644 index 000000000..0495d7ac9 --- /dev/null +++ b/openslides/motion/templates/motion/widget.html @@ -0,0 +1,34 @@ +{% load staticfiles %} +{% load i18n %} +{% load tags %} + + + diff --git a/openslides/application/templates/projector/Application.html b/openslides/motion/templates/projector/Motion.html similarity index 74% rename from openslides/application/templates/projector/Application.html rename to openslides/motion/templates/projector/Motion.html index 8f6ff6401..ab094313f 100644 --- a/openslides/application/templates/projector/Application.html +++ b/openslides/motion/templates/projector/Motion.html @@ -4,27 +4,27 @@ {% load i18n %} {% load staticfiles %} -{% block title %}{{ block.super }} - {% trans "Motion" %} {{ application.number }}{% endblock %} +{% block title %}{{ block.super }} - {% trans "Motion" %} {{ motion.number }}{% endblock %} {% block content %}

- {% if application.number != None %} - {% trans "Motion No." %} {{ application.number }} + {% if motion.number != None %} + {% trans "Motion No." %} {{ motion.number }} {% else %} {% trans "Motion" %} [{% trans "no number" %}] {% endif %}

- {{ application.public_version.title }} + {{ motion.public_version.title }}
{% endblock %} {% block scrollcontent %}

-

{{ application.public_version.text|linebreaks }}
- {% if application.public_version.reason %} +
{{ motion.public_version.text|linebreaks }}
+ {% if motion.public_version.reason %}

{% trans "Reason" %}:

- {{ application.public_version.reason|linebreaks }}
+ {{ motion.public_version.reason|linebreaks }} {% endif %}

{% endblock %} diff --git a/openslides/application/tests.py b/openslides/motion/tests.py similarity index 77% rename from openslides/application/tests.py rename to openslides/motion/tests.py index bd3ecb73a..1fb387951 100644 --- a/openslides/application/tests.py +++ b/openslides/motion/tests.py @@ -1,10 +1,10 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- """ - openslides.application.tests + openslides.motion.tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Unit tests for the application app. + Unit tests for the motion app. :copyright: 2011, 2012 by OpenSlides team, see AUTHORS. :license: GNU GPL, see LICENSE for more details. @@ -14,19 +14,19 @@ from django.test import TestCase from django.test.client import Client from openslides.participant.models import User -from openslides.application.models import Application, AVersion +from openslides.motion.models import Motion, AVersion -class ApplicationTest(TestCase): +class MotionTest(TestCase): def setUp(self): self.admin = User(username='testadmin') self.admin.save() self.anonym = User(username='testanoym') self.anonym.save() - self.app1 = Application(submitter=self.admin) + self.app1 = Motion(submitter=self.admin) self.app1.save() def refresh(self): - self.app1 = Application.objects.get(pk=self.app1.id) + self.app1 = Motion.objects.get(pk=self.app1.id) def testVersion(self): self.assertTrue(self.app1.versions.exists()) diff --git a/openslides/motion/urls.py b/openslides/motion/urls.py new file mode 100644 index 000000000..55543d615 --- /dev/null +++ b/openslides/motion/urls.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" + openslides.motion.urls + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + URL list for the motion app. + + :copyright: 2011, 2012 by OpenSlides team, see AUTHORS. + :license: GNU GPL, see LICENSE for more details. +""" + +from django.conf.urls.defaults import url, patterns + +from openslides.motion.views import (MotionDelete, ViewPoll, + MotionPDF, MotionPollPDF, CreateAgendaItem) + +urlpatterns = patterns('openslides.motion.views', + url(r'^$', + 'overview', + name='motion_overview', + ), + + url(r'^(?P\d+)/$', + 'view', + name='motion_view', + ), + + url(r'^(?P\d+)/agenda/$', + CreateAgendaItem.as_view(), + name='motion_create_agenda', + ), + + url(r'^(?P\d+)/newest/$', + 'view', + {'newest': True}, + name='motion_view_newest', + ), + + url(r'^new/$', + 'edit', + name='motion_new', + ), + + url(r'^import/$', + 'motion_import', + name='motion_import', + ), + + url(r'^(?P\d+)/edit/$', + 'edit', + name='motion_edit', + ), + + url(r'^(?P\d+)/del/$', + MotionDelete.as_view(), + name='motion_delete', + ), + + url(r'^del/$', + MotionDelete.as_view(), + { 'motion_id' : None , 'motion_ids' : None }, + name='motion_delete', + ), + + url(r'^(?P\d+)/setnumber/$', + 'set_number', + name='motion_set_number', + ), + + url(r'^(?P\d+)/setstatus/(?P[a-z]{3})/$', + 'set_status', + name='motion_set_status', + ), + + url(r'^(?P\d+)/permit/$', + 'permit', + name='motion_permit', + ), + + url(r'^version/(?P\d+)/permit/$', + 'permit_version', + name='motion_version_permit', + ), + + url(r'^version/(?P\d+)/reject/$', + 'reject_version', + name='motion_version_reject', + ), + + url(r'^(?P\d+)/notpermit/$', + 'notpermit', + name='motion_notpermit', + ), + + url(r'^(?P\d+)/reset/$', + 'reset', + name='motion_reset', + ), + + url(r'^(?P\d+)/support/$', + 'support', + name='motion_support', + ), + + url(r'^(?P\d+)/unsupport/$', + 'unsupport', + name='motion_unsupport', + ), + + url(r'^(?P\d+)/gen_poll/$', + 'gen_poll', + name='motion_gen_poll', + ), + + url(r'^print/$', + MotionPDF.as_view(), + {'motion_id': None}, + name='print_motions', + ), + + url(r'^(?P\d+)/print/$', + MotionPDF.as_view(), + name='print_motion', + ), + + url(r'^poll/(?P\d+)/print/$', + MotionPollPDF.as_view(), + name='print_motion_poll', + ), + + url(r'^poll/(?P\d+)/$', + ViewPoll.as_view(), + name='motion_poll_view', + ), + + url(r'^poll/(?P\d+)/del/$', + 'delete_poll', + name='motion_poll_delete', + ), +) diff --git a/openslides/application/views.py b/openslides/motion/views.py similarity index 54% rename from openslides/application/views.py rename to openslides/motion/views.py index cc9b18bd5..9be63f5ed 100644 --- a/openslides/application/views.py +++ b/openslides/motion/views.py @@ -1,10 +1,10 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- """ - openslides.application.views + openslides.motion.views ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Views for the application app. + Views for the motion app. :copyright: 2011, 2012 by OpenSlides team, see AUTHORS. :license: GNU GPL, see LICENSE for more details. @@ -55,17 +55,17 @@ from openslides.participant.models import User from openslides.agenda.models import Item -from openslides.application.models import Application, AVersion, ApplicationPoll -from openslides.application.forms import (ApplicationForm, - ApplicationFormTrivialChanges, ApplicationManagerForm, - ApplicationManagerFormSupporter, ApplicationImportForm, ConfigForm) +from openslides.motion.models import Motion, AVersion, MotionPoll +from openslides.motion.forms import (MotionForm, + MotionFormTrivialChanges, MotionManagerForm, + MotionManagerFormSupporter, MotionImportForm, ConfigForm) -@permission_required('application.can_see_application') -@template('application/overview.html') +@permission_required('motion.can_see_motion') +@template('motion/overview.html') def overview(request): """ - View all applications + View all motions """ try: sortfilter = parse_qs(request.COOKIES['votecollector_sortfilter']) @@ -84,7 +84,7 @@ def overview(request): else: sortfilter[value] = request.REQUEST[value] - query = Application.objects.all() + query = Motion.objects.all() if 'number' in sortfilter: query = query.filter(number=None) if 'status' in sortfilter: @@ -100,101 +100,101 @@ def overview(request): sort = sortfilter['sort'] query = query.order_by(sort) if sort.startswith('aversion_'): - # limit result to last version of an application - query = query.filter(aversion__id__in=[x.last_version.id for x in Application.objects.all()]) + # limit result to last version of an motion + query = query.filter(aversion__id__in=[x.last_version.id for x in Motion.objects.all()]) if 'reverse' in sortfilter: query = query.reverse() # todo: rewrite this with a .filter() if 'needsup' in sortfilter: - applications = [] - for application in query.all(): - if not application.enough_supporters: - applications.append(application) + motions = [] + for motion in query.all(): + if not motion.enough_supporters: + motions.append(motion) else: - applications = query + motions = query - if type(applications) is not list: - applications = list(query.all()) + if type(motions) is not list: + motions = list(query.all()) # not the most efficient way to do this but 'get_allowed_actions' # is not callable from within djangos templates.. - for (i, application) in enumerate(applications): + for (i, motion) in enumerate(motions): try: - applications[i] = { - 'actions' : application.get_allowed_actions(request.user), - 'application' : application + motions[i] = { + 'actions' : motion.get_allowed_actions(request.user), + 'motion' : motion } except: # todo: except what? - applications[i] = { + motions[i] = { 'actions' : [], - 'application' : application + 'motion' : motion } return { - 'applications': applications, - 'min_supporters': int(config['application_min_supporters']), + 'motions': motions, + 'min_supporters': int(config['motion_min_supporters']), } -@permission_required('application.can_see_application') -@template('application/view.html') -def view(request, application_id, newest=False): +@permission_required('motion.can_see_motion') +@template('motion/view.html') +def view(request, motion_id, newest=False): """ - View one application. + View one motion. """ - application = Application.objects.get(pk=application_id) + motion = Motion.objects.get(pk=motion_id) if newest: - version = application.last_version + version = motion.last_version else: - version = application.public_version - revisions = application.versions - actions = application.get_allowed_actions(user=request.user) + version = motion.public_version + revisions = motion.versions + actions = motion.get_allowed_actions(user=request.user) return { - 'application': application, + 'motion': motion, 'revisions': revisions, 'actions': actions, - 'min_supporters': int(config['application_min_supporters']), + 'min_supporters': int(config['motion_min_supporters']), 'version': version, - #'results': application.results + #'results': motion.results } @login_required -@template('application/edit.html') -def edit(request, application_id=None): +@template('motion/edit.html') +def edit(request, motion_id=None): """ - View a form to edit or create a application. + View a form to edit or create a motion. """ - if request.user.has_perm('application.can_manage_application'): + if request.user.has_perm('motion.can_manage_motion'): is_manager = True else: is_manager = False if not is_manager \ - and not request.user.has_perm('application.can_create_application'): + and not request.user.has_perm('motion.can_create_motion'): messages.error(request, _("You have not the necessary rights to create or edit motions.")) - return redirect(reverse('application_overview')) - if application_id is not None: - application = Application.objects.get(id=application_id) - if not 'edit' in application.get_allowed_actions(request.user): + return redirect(reverse('motion_overview')) + if motion_id is not None: + motion = Motion.objects.get(id=motion_id) + if not 'edit' in motion.get_allowed_actions(request.user): messages.error(request, _("You can not edit this motion.")) - return redirect(reverse('application_view', args=[application.id])) - actions = application.get_allowed_actions(user=request.user) + return redirect(reverse('motion_view', args=[motion.id])) + actions = motion.get_allowed_actions(user=request.user) else: - application = None + motion = None actions = None - formclass = ApplicationFormTrivialChanges \ - if config['application_allow_trivial_change'] and application_id \ - else ApplicationForm + formclass = MotionFormTrivialChanges \ + if config['motion_allow_trivial_change'] and motion_id \ + else MotionForm - managerformclass = ApplicationManagerFormSupporter \ - if config['application_min_supporters'] \ - else ApplicationManagerForm + managerformclass = MotionManagerFormSupporter \ + if config['motion_min_supporters'] \ + else MotionManagerForm if request.method == 'POST': dataform = formclass(request.POST, prefix="data") @@ -202,7 +202,7 @@ def edit(request, application_id=None): if is_manager: managerform = managerformclass(request.POST, - instance=application, + instance=motion, prefix="manager") valid = valid and managerform.is_valid() else: @@ -211,23 +211,23 @@ def edit(request, application_id=None): if valid: del_supporters = True if is_manager: - if application: # Edit application - original_supporters = list(application.supporters) + if motion: # Edit motion + original_supporters = list(motion.supporters) else: original_supporters = [] - application = managerform.save(commit=False) - elif application_id is None: - application = Application(submitter=request.user) - application.title = dataform.cleaned_data['title'] - application.text = dataform.cleaned_data['text'] - application.reason = dataform.cleaned_data['reason'] + motion = managerform.save(commit=False) + elif motion_id is None: + motion = Motion(submitter=request.user) + motion.title = dataform.cleaned_data['title'] + motion.text = dataform.cleaned_data['text'] + motion.reason = dataform.cleaned_data['reason'] try: - trivial_change = config['application_allow_trivial_change'] \ + trivial_change = config['motion_allow_trivial_change'] \ and dataform.cleaned_data['trivial_change'] except KeyError: trivial_change = False - application.save(request.user, trivial_change=trivial_change) + motion.save(request.user, trivial_change=trivial_change) if is_manager: try: new_supporters = set(managerform.cleaned_data['supporter']) @@ -235,232 +235,232 @@ def edit(request, application_id=None): # The managerform has no field for the supporters pass else: - old_supporters = set(application.supporters) + old_supporters = set(motion.supporters) # add new supporters for supporter in new_supporters.difference(old_supporters): - application.support(supporter) + motion.support(supporter) # remove old supporters for supporter in old_supporters.difference(new_supporters): - application.unsupport(supporter) + motion.unsupport(supporter) - if application_id is None: + if motion_id is None: messages.success(request, _('New motion was successfully created.')) else: messages.success(request, _('Motion was successfully modified.')) if not 'apply' in request.POST: - return redirect(reverse('application_view', args=[application.id])) - if application_id is None: - return redirect(reverse('application_edit', args=[application.id])) + return redirect(reverse('motion_view', args=[motion.id])) + if motion_id is None: + return redirect(reverse('motion_edit', args=[motion.id])) else: messages.error(request, _('Please check the form for errors.')) else: - if application_id is None: - initial = {'text': config['application_preamble']} + if motion_id is None: + initial = {'text': config['motion_preamble']} else: - if application.status == "pub" and application.supporters: - if request.user.has_perm('application.can_manage_application'): + if motion.status == "pub" and motion.supporters: + if request.user.has_perm('motion.can_manage_motion'): messages.warning(request, _("Attention: Do you really want to edit this motion? The supporters will not be removed automatically because you can manage motions. Please check if the supports are valid after your changing!")) else: - messages.warning(request, _("Attention: Do you really want to edit this motion? All %s supporters will be removed! Try to convince the supporters again.") % application.count_supporters() ) - initial = {'title': application.title, - 'text': application.text, - 'reason': application.reason} + messages.warning(request, _("Attention: Do you really want to edit this motion? All %s supporters will be removed! Try to convince the supporters again.") % motion.count_supporters() ) + initial = {'title': motion.title, + 'text': motion.text, + 'reason': motion.reason} dataform = formclass(initial=initial, prefix="data") if is_manager: - if application_id is None: + if motion_id is None: initial = {'submitter': request.user.person_id} else: - initial = {'submitter': application.submitter.person_id, - 'supporter': [supporter.person_id for supporter in application.supporters]} + initial = {'submitter': motion.submitter.person_id, + 'supporter': [supporter.person_id for supporter in motion.supporters]} managerform = managerformclass(initial=initial, - instance=application, prefix="manager") + instance=motion, prefix="manager") else: managerform = None return { 'form': dataform, 'managerform': managerform, - 'application': application, + 'motion': motion, 'actions': actions, } -@permission_required('application.can_manage_application') -@template('application/view.html') -def set_number(request, application_id): +@permission_required('motion.can_manage_motion') +@template('motion/view.html') +def set_number(request, motion_id): """ - set a number for an application. + set a number for an motion. """ try: - Application.objects.get(pk=application_id).set_number(user=request.user) + Motion.objects.get(pk=motion_id).set_number(user=request.user) messages.success(request, _("Motion number was successfully set.")) - except Application.DoesNotExist: + except Motion.DoesNotExist: pass except NameError: pass - return redirect(reverse('application_view', args=[application_id])) + return redirect(reverse('motion_view', args=[motion_id])) -@permission_required('application.can_manage_application') -@template('application/view.html') -def permit(request, application_id): +@permission_required('motion.can_manage_motion') +@template('motion/view.html') +def permit(request, motion_id): """ - permit an application. + permit an motion. """ try: - Application.objects.get(pk=application_id).permit(user=request.user) + Motion.objects.get(pk=motion_id).permit(user=request.user) messages.success(request, _("Motion was successfully authorized.")) - except Application.DoesNotExist: + except Motion.DoesNotExist: pass except NameError, e: messages.error(request, e) - return redirect(reverse('application_view', args=[application_id])) + return redirect(reverse('motion_view', args=[motion_id])) -@permission_required('application.can_manage_application') -@template('application/view.html') -def notpermit(request, application_id): +@permission_required('motion.can_manage_motion') +@template('motion/view.html') +def notpermit(request, motion_id): """ - reject (not permit) an application. + reject (not permit) an motion. """ try: - Application.objects.get(pk=application_id).notpermit(user=request.user) + Motion.objects.get(pk=motion_id).notpermit(user=request.user) messages.success(request, _("Motion was successfully rejected.")) - except Application.DoesNotExist: + except Motion.DoesNotExist: pass except NameError, e: messages.error(request, e) - return redirect(reverse('application_view', args=[application_id])) + return redirect(reverse('motion_view', args=[motion_id])) -@template('application/view.html') -def set_status(request, application_id=None, status=None): +@template('motion/view.html') +def set_status(request, motion_id=None, status=None): """ - set a status of an application. + set a status of an motion. """ try: if status is not None: - application = Application.objects.get(pk=application_id) - application.set_status(user=request.user, status=status) - messages.success(request, _("Motion status was set to: %s.") % application.get_status_display()) - except Application.DoesNotExist: + motion = Motion.objects.get(pk=motion_id) + motion.set_status(user=request.user, status=status) + messages.success(request, _("Motion status was set to: %s.") % motion.get_status_display()) + except Motion.DoesNotExist: pass except NameError, e: messages.error(request, e) - return redirect(reverse('application_view', args=[application_id])) + return redirect(reverse('motion_view', args=[motion_id])) -@permission_required('application.can_manage_application') -@template('application/view.html') -def reset(request, application_id): +@permission_required('motion.can_manage_motion') +@template('motion/view.html') +def reset(request, motion_id): """ - reset an application. + reset an motion. """ try: - Application.objects.get(pk=application_id).reset(user=request.user) + Motion.objects.get(pk=motion_id).reset(user=request.user) messages.success(request, _("Motion status was reset.") ) - except Application.DoesNotExist: + except Motion.DoesNotExist: pass - return redirect(reverse('application_view', args=[application_id])) + return redirect(reverse('motion_view', args=[motion_id])) -@permission_required('application.can_support_application') -@template('application/view.html') -def support(request, application_id): +@permission_required('motion.can_support_motion') +@template('motion/view.html') +def support(request, motion_id): """ - support an application. + support an motion. """ try: - Application.objects.get(pk=application_id).support(person=request.user) + Motion.objects.get(pk=motion_id).support(person=request.user) messages.success(request, _("You have support the motion successfully.") ) - except Application.DoesNotExist: + except Motion.DoesNotExist: pass - return redirect(reverse('application_view', args=[application_id])) + return redirect(reverse('motion_view', args=[motion_id])) -@permission_required('application.can_support_application') -@template('application/view.html') -def unsupport(request, application_id): +@permission_required('motion.can_support_motion') +@template('motion/view.html') +def unsupport(request, motion_id): """ - unsupport an application. + unsupport an motion. """ try: - Application.objects.get(pk=application_id).unsupport(person=request.user) + Motion.objects.get(pk=motion_id).unsupport(person=request.user) messages.success(request, _("You have unsupport the motion successfully.") ) - except Application.DoesNotExist: + except Motion.DoesNotExist: pass - return redirect(reverse('application_view', args=[application_id])) + return redirect(reverse('motion_view', args=[motion_id])) -@permission_required('application.can_manage_application') -@template('application/view.html') -def gen_poll(request, application_id): +@permission_required('motion.can_manage_motion') +@template('motion/view.html') +def gen_poll(request, motion_id): """ - gen a poll for this application. + gen a poll for this motion. """ try: - poll = Application.objects.get(pk=application_id).gen_poll(user=request.user) + poll = Motion.objects.get(pk=motion_id).gen_poll(user=request.user) messages.success(request, _("New vote was successfully created.") ) - except Application.DoesNotExist: + except Motion.DoesNotExist: pass # TODO: do not call poll after this excaption - return redirect(reverse('application_poll_view', args=[poll.id])) + return redirect(reverse('motion_poll_view', args=[poll.id])) -@permission_required('application.can_manage_application') +@permission_required('motion.can_manage_motion') def delete_poll(request, poll_id): """ - delete a poll from this application + delete a poll from this motion """ - poll = ApplicationPoll.objects.get(pk=poll_id) - application = poll.application - count = application.polls.filter(id__lte=poll_id).count() + poll = MotionPoll.objects.get(pk=poll_id) + motion = poll.motion + count = motion.polls.filter(id__lte=poll_id).count() if request.method == 'POST': poll.delete() - application.writelog(_("Poll deleted"), request.user) + motion.writelog(_("Poll deleted"), request.user) messages.success(request, _('Poll was successfully deleted.')) else: - del_confirm_form(request, poll, name=_("the %s. poll") % count, delete_link=reverse('application_poll_delete', args=[poll_id])) - return redirect(reverse('application_view', args=[application.id])) + del_confirm_form(request, poll, name=_("the %s. poll") % count, delete_link=reverse('motion_poll_delete', args=[poll_id])) + return redirect(reverse('motion_view', args=[motion.id])) -class ApplicationDelete(DeleteView): +class MotionDelete(DeleteView): """ - Delete one or more Applications. + Delete one or more Motions. """ - permission_required = 'application.can_manage_application' - model = Application - url = 'application_overview' + permission_required = 'motion.can_manage_motion' + model = Motion + url = 'motion_overview' def get_object(self): - self.applications = [] + self.motions = [] - if self.kwargs.get('application_id', None): + if self.kwargs.get('motion_id', None): try: - return Application.objects.get(id=int(self.kwargs['application_id'])) - except Application.DoesNotExist: + return Motion.objects.get(id=int(self.kwargs['motion_id'])) + except Motion.DoesNotExist: return None - if self.kwargs.get('application_ids', []): - for appid in self.kwargs['application_ids']: + if self.kwargs.get('motion_ids', []): + for appid in self.kwargs['motion_ids']: try: - self.applications.append(Application.objects.get(id=int(appid))) - except Application.DoesNotExist: + self.motions.append(Motion.objects.get(id=int(appid))) + except Motion.DoesNotExist: pass - if self.applications: - return self.applications[0] + if self.motions: + return self.motions[0] return None def pre_post_redirect(self, request, *args, **kwargs): self.object = self.get_object() - if len(self.applications): - for application in self.applications: - if not 'delete' in application.get_allowed_actions(user=request.user): - messages.error(request, _("You can not delete motion %s.") % application) + if len(self.motions): + for motion in self.motions: + if not 'delete' in motion.get_allowed_actions(user=request.user): + messages.error(request, _("You can not delete motion %s.") % motion) continue - title = application.title - application.delete(force=True) + title = motion.title + motion.delete(force=True) messages.success(request, _("Motion %s was successfully deleted.") % title) elif self.object: @@ -475,16 +475,16 @@ class ApplicationDelete(DeleteView): class ViewPoll(PollFormView): - permission_required = 'application.can_manage_application' - poll_class = ApplicationPoll - template_name = 'application/poll_view.html' + permission_required = 'motion.can_manage_motion' + poll_class = MotionPoll + template_name = 'motion/poll_view.html' def get_context_data(self, **kwargs): context = super(ViewPoll, self).get_context_data(**kwargs) - self.application = self.poll.get_application() - context['application'] = self.application + self.motion = self.poll.get_motion() + context['motion'] = self.motion context['ballot'] = self.poll.get_ballot() - context['actions'] = self.application.get_allowed_actions(user=self.request.user) + context['actions'] = self.motion.get_allowed_actions(user=self.request.user) return context def get_modelform_class(self): @@ -494,49 +494,49 @@ class ViewPoll(PollFormView): class ViewPollFormClass(cls): def save(self, commit = True): instance = super(ViewPollFormClass, self).save(commit) - application = instance.application - application.writelog(_("Poll was updated"), user) + motion = instance.motion + motion.writelog(_("Poll was updated"), user) return instance return ViewPollFormClass def get_success_url(self): if not 'apply' in self.request.POST: - return reverse('application_view', args=[self.poll.application.id]) + return reverse('motion_view', args=[self.poll.motion.id]) return '' -@permission_required('application.can_manage_application') +@permission_required('motion.can_manage_motion') def permit_version(request, aversion_id): aversion = AVersion.objects.get(pk=aversion_id) - application = aversion.application + motion = aversion.motion if request.method == 'POST': - application.accept_version(aversion, user=request.user) + motion.accept_version(aversion, user=request.user) messages.success(request, _("Version %s accepted.") % (aversion.aid)) else: - gen_confirm_form(request, _('Do you really want to authorize version %s?') % aversion.aid, reverse('application_version_permit', args=[aversion.id])) - return redirect(reverse('application_view', args=[application.id])) + gen_confirm_form(request, _('Do you really want to authorize version %s?') % aversion.aid, reverse('motion_version_permit', args=[aversion.id])) + return redirect(reverse('motion_view', args=[motion.id])) -@permission_required('application.can_manage_application') +@permission_required('motion.can_manage_motion') def reject_version(request, aversion_id): aversion = AVersion.objects.get(pk=aversion_id) - application = aversion.application + motion = aversion.motion if request.method == 'POST': - if application.reject_version(aversion, user=request.user): + if motion.reject_version(aversion, user=request.user): messages.success(request, _("Version %s rejected.") % (aversion.aid)) else: messages.error(request, _("ERROR by rejecting the version.") ) else: - gen_confirm_form(request, _('Do you really want to reject version %s?') % aversion.aid, reverse('application_version_reject', args=[aversion.id])) - return redirect(reverse('application_view', args=[application.id])) + gen_confirm_form(request, _('Do you really want to reject version %s?') % aversion.aid, reverse('motion_version_reject', args=[aversion.id])) + return redirect(reverse('motion_view', args=[motion.id])) -@permission_required('application.can_manage_application') -@template('application/import.html') -def application_import(request): +@permission_required('motion.can_manage_motion') +@template('motion/import.html') +def motion_import(request): if request.method == 'POST': - form = ApplicationImportForm(request.POST, request.FILES) + form = MotionImportForm(request.POST, request.FILES) if form.is_valid(): import_permitted = form.cleaned_data['import_permitted'] try: @@ -545,8 +545,8 @@ def application_import(request): request.FILES['csvfile'].seek(0) users_generated = 0 - applications_generated = 0 - applications_modified = 0 + motions_generated = 0 + motions_modified = 0 with transaction.commit_on_success(): dialect = csv.Sniffer().sniff(request.FILES['csvfile'].readline()) dialect = csv_ext.patchup(dialect) @@ -560,7 +560,7 @@ def application_import(request): except ValueError: messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1)) continue - form = ApplicationForm({'title': title, 'text': text, 'reason': reason}) + form = MotionForm({'title': title, 'text': text, 'reason': reason}) if not form.is_valid(): messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1)) continue @@ -594,37 +594,37 @@ def application_import(request): profile.user.set_password(profile.firstpassword) profile.save() users_generated += 1 - # create / modify the application - application = None + # create / modify the motion + motion = None if number: try: - application = Application.objects.get(number=number) - applications_modified += 1 - except Application.DoesNotExist: - application = None - if application is None: - application = Application(submitter=user) + motion = Motion.objects.get(number=number) + motions_modified += 1 + except Motion.DoesNotExist: + motion = None + if motion is None: + motion = Motion(submitter=user) if number: - application.number = number - applications_generated += 1 + motion.number = number + motions_generated += 1 - application.title = form.cleaned_data['title'] - application.text = form.cleaned_data['text'] - application.reason = form.cleaned_data['reason'] + motion.title = form.cleaned_data['title'] + motion.text = form.cleaned_data['text'] + motion.reason = form.cleaned_data['reason'] if import_permitted: - application.status = 'per' + motion.status = 'per' - application.save(user, trivial_change=True) + motion.save(user, trivial_change=True) - if applications_generated: + if motions_generated: messages.success(request, ungettext('%d motion was successfully imported.', - '%d motions were successfully imported.', applications_generated) % applications_generated) - if applications_modified: + '%d motions were successfully imported.', motions_generated) % motions_generated) + if motions_modified: messages.success(request, ungettext('%d motion was successfully modified.', - '%d motions were successfully modified.', applications_modified) % applications_modified) + '%d motions were successfully modified.', motions_modified) % motions_modified) if users_generated: messages.success(request, ungettext('%d new user was added.', '%d new users were added.', users_generated) % users_generated) - return redirect(reverse('application_overview')) + return redirect(reverse('motion_overview')) except csv.Error: message.error(request, _('Import aborted because of severe errors in the input file.')) @@ -635,7 +635,7 @@ def application_import(request): else: messages.warning(request, _("Attention: Existing motions will be modified if you import new motions with the same number.")) messages.warning(request, _("Attention: Importing an motions without a number multiple times will create duplicates.")) - form = ApplicationImportForm() + form = MotionImportForm() return { 'form': form, } @@ -645,65 +645,65 @@ class CreateAgendaItem(RedirectView): permission_required = 'agenda.can_manage_agenda' def pre_redirect(self, request, *args, **kwargs): - self.application = Application.objects.get(pk=kwargs['application_id']) - self.item = Item(related_sid=self.application.sid) + self.motion = Motion.objects.get(pk=kwargs['motion_id']) + self.item = Item(related_sid=self.motion.sid) self.item.save() def get_redirect_url(self, **kwargs): return reverse('item_overview') -class ApplicationPDF(PDFView): - permission_required = 'application.can_see_application' +class MotionPDF(PDFView): + permission_required = 'motion.can_see_motion' top_space = 0 def get_filename(self): - application_id = self.kwargs['application_id'] - if application_id is None: - filename = _("Applications") + motion_id = self.kwargs['motion_id'] + if motion_id is None: + filename = _("Motions") else: - application = Application.objects.get(id=application_id) - if application.number: - number = application.number + motion = Motion.objects.get(id=motion_id) + if motion.number: + number = motion.number else: number = "" - filename = u'%s%s' % (_("Application"), str(number)) + filename = u'%s%s' % (_("Motion"), str(number)) return filename def append_to_pdf(self, story): - application_id = self.kwargs['application_id'] - if application_id is None: #print all applications - title = config["application_pdf_title"] + motion_id = self.kwargs['motion_id'] + if motion_id is None: #print all motions + title = config["motion_pdf_title"] story.append(Paragraph(title, stylesheet['Heading1'])) - preamble = config["application_pdf_preamble"] + preamble = config["motion_pdf_preamble"] if preamble: story.append(Paragraph("%s" % preamble.replace('\r\n','
'), stylesheet['Paragraph'])) story.append(Spacer(0,0.75*cm)) - applications = Application.objects.all() - if not applications: # No applications existing + motions = Motion.objects.all() + if not motions: # No motions existing story.append(Paragraph(_("No motions available."), stylesheet['Heading3'])) - else: # Print all Applications - # List of applications - for application in applications: - if application.number: - story.append(Paragraph(_("Motion No.")+" %s: %s" % (application.number, application.title), stylesheet['Heading3'])) + else: # Print all Motions + # List of motions + for motion in motions: + if motion.number: + story.append(Paragraph(_("Motion No.")+" %s: %s" % (motion.number, motion.title), stylesheet['Heading3'])) else: - story.append(Paragraph(_("Motion No.")+"   : %s" % (application.title), stylesheet['Heading3'])) - # Applications details (each application on single page) - for application in applications: + story.append(Paragraph(_("Motion No.")+"   : %s" % (motion.title), stylesheet['Heading3'])) + # Motions details (each motion on single page) + for motion in motions: story.append(PageBreak()) - story = self.get_application(application, story) - else: # print selected application - application = Application.objects.get(id=application_id) - story = self.get_application(application, story) + story = self.get_motion(motion, story) + else: # print selected motion + motion = Motion.objects.get(id=motion_id) + story = self.get_motion(motion, story) - def get_application(self, application, story): + def get_motion(self, motion, story): # Preparing Table data = [] - # application number - if application.number: - story.append(Paragraph(_("Motion No.")+" %s" % application.number, stylesheet['Heading1'])) + # motion number + if motion.number: + story.append(Paragraph(_("Motion No.")+" %s" % motion.number, stylesheet['Heading1'])) else: story.append(Paragraph(_("Motion No."), stylesheet['Heading1'])) @@ -713,10 +713,10 @@ class ApplicationPDF(PDFView): cell1a.append(Paragraph("%s:" % _("Submitter"), stylesheet['Heading4'])) cell1b = [] cell1b.append(Spacer(0, 0.2 * cm)) - cell1b.append(Paragraph("%s" % application.submitter, stylesheet['Normal'])) + cell1b.append(Paragraph("%s" % motion.submitter, stylesheet['Normal'])) data.append([cell1a, cell1b]) - if application.status == "pub": + if motion.status == "pub": # Cell for the signature cell2a = [] cell2b = [] @@ -727,14 +727,14 @@ class ApplicationPDF(PDFView): data.append([cell2a, cell2b]) # supporters - if config['application_min_supporters']: + if config['motion_min_supporters']: cell3a = [] cell3b = [] cell3a.append(Paragraph("%s:" % _("Supporters"), stylesheet['Heading4'])) - for supporter in application.supporters: + for supporter in motion.supporters: cell3b.append(Paragraph(".  %s" % supporter, stylesheet['Signaturefield'])) - if application.status == "pub": - for x in range(application.missing_supporters): + if motion.status == "pub": + for x in range(motion.missing_supporters): cell3b.append(Paragraph(".  __________________________________________",stylesheet['Signaturefield'])) cell3b.append(Spacer(0, 0.2 * cm)) data.append([cell3a, cell3b]) @@ -742,27 +742,27 @@ class ApplicationPDF(PDFView): # status cell4a = [] cell4b = [] - note = " ".join(application.notes) + note = " ".join(motion.notes) cell4a.append(Paragraph("%s:" % _("Status"), stylesheet['Heading4'])) if note != "": - if application.status == "pub": + if motion.status == "pub": cell4b.append(Paragraph(note, stylesheet['Normal'])) else: - cell4b.append(Paragraph("%s | %s" % (application.get_status_display(), note), stylesheet['Normal'])) + cell4b.append(Paragraph("%s | %s" % (motion.get_status_display(), note), stylesheet['Normal'])) else: - cell4b.append(Paragraph("%s" % application.get_status_display(), stylesheet['Normal'])) + cell4b.append(Paragraph("%s" % motion.get_status_display(), stylesheet['Normal'])) data.append([cell4a, cell4b]) # Version number (aid) - if application.public_version.aid > 1: + if motion.public_version.aid > 1: cell5a = [] cell5b = [] cell5a.append(Paragraph("%s:" % _("Version"), stylesheet['Heading4'])) - cell5b.append(Paragraph("%s" % application.public_version.aid, stylesheet['Normal'])) + cell5b.append(Paragraph("%s" % motion.public_version.aid, stylesheet['Normal'])) data.append([cell5a, cell5b]) # voting results - poll_results = application.get_poll_results() + poll_results = motion.get_poll_results() if poll_results: cell6a = [] cell6a.append(Paragraph("%s:" % _("Vote results"), stylesheet['Heading4'])) @@ -786,26 +786,26 @@ class ApplicationPDF(PDFView): story.append(Spacer(0, 1 * cm)) # title - story.append(Paragraph(application.public_version.title, stylesheet['Heading3'])) + story.append(Paragraph(motion.public_version.title, stylesheet['Heading3'])) # text - story.append(Paragraph("%s" % application.public_version.text.replace('\r\n','
'), stylesheet['Paragraph'])) + story.append(Paragraph("%s" % motion.public_version.text.replace('\r\n','
'), stylesheet['Paragraph'])) # reason - if application.public_version.reason: + if motion.public_version.reason: story.append(Paragraph(_("Reason")+":", stylesheet['Heading3'])) - story.append(Paragraph("%s" % application.public_version.reason.replace('\r\n','
'), stylesheet['Paragraph'])) + story.append(Paragraph("%s" % motion.public_version.reason.replace('\r\n','
'), stylesheet['Paragraph'])) return story -class ApplicationPollPDF(PDFView): - permission_required = 'application.can_manage_application' +class MotionPollPDF(PDFView): + permission_required = 'motion.can_manage_motion' top_space = 0 def get(self, request, *args, **kwargs): - self.poll = ApplicationPoll.objects.get(id=self.kwargs['poll_id']) - return super(ApplicationPollPDF, self).get(request, *args, **kwargs) + self.poll = MotionPoll.objects.get(id=self.kwargs['poll_id']) + return super(MotionPollPDF, self).get(request, *args, **kwargs) def get_filename(self): - filename = u'%s%s_%s' % (_("Application"), str(self.poll.application.number), _("Poll")) + filename = u'%s%s_%s' % (_("Motion"), str(self.poll.motion.number), _("Poll")) return filename def get_template(self, buffer): @@ -819,8 +819,8 @@ class ApplicationPollPDF(PDFView): circle = "  " % imgpath cell = [] cell.append(Spacer(0,0.8*cm)) - cell.append(Paragraph(_("Application No. %s") % self.poll.application.number, stylesheet['Ballot_title'])) - cell.append(Paragraph(self.poll.application.title, stylesheet['Ballot_subtitle'])) + cell.append(Paragraph(_("Motion No. %s") % self.poll.motion.number, stylesheet['Ballot_title'])) + cell.append(Paragraph(self.poll.motion.title, stylesheet['Ballot_subtitle'])) cell.append(Paragraph(_("%d. Vote") % self.poll.get_ballot(), stylesheet['Ballot_description'])) cell.append(Spacer(0,0.5*cm)) cell.append(Paragraph(circle + unicode(_("Yes")), stylesheet['Ballot_option'])) @@ -828,8 +828,8 @@ class ApplicationPollPDF(PDFView): cell.append(Paragraph(circle + unicode(_("Abstention")), stylesheet['Ballot_option'])) data= [] # get ballot papers config values - ballot_papers_selection = config["application_pdf_ballot_papers_selection"] - ballot_papers_number = config["application_pdf_ballot_papers_number"] + ballot_papers_selection = config["motion_pdf_ballot_papers_selection"] + ballot_papers_number = config["motion_pdf_ballot_papers_number"] # set number of ballot papers if ballot_papers_selection == "NUMBER_OF_DELEGATES": @@ -857,37 +857,37 @@ class ApplicationPollPDF(PDFView): class Config(FormView): permission_required = 'config.can_manage_config' form_class = ConfigForm - template_name = 'application/config.html' + template_name = 'motion/config.html' def get_initial(self): return { - 'application_min_supporters': config['application_min_supporters'], - 'application_preamble': config['application_preamble'], - 'application_pdf_ballot_papers_selection': config['application_pdf_ballot_papers_selection'], - 'application_pdf_ballot_papers_number': config['application_pdf_ballot_papers_number'], - 'application_pdf_title': config['application_pdf_title'], - 'application_pdf_preamble': config['application_pdf_preamble'], - 'application_allow_trivial_change': config['application_allow_trivial_change'], + 'motion_min_supporters': config['motion_min_supporters'], + 'motion_preamble': config['motion_preamble'], + 'motion_pdf_ballot_papers_selection': config['motion_pdf_ballot_papers_selection'], + 'motion_pdf_ballot_papers_number': config['motion_pdf_ballot_papers_number'], + 'motion_pdf_title': config['motion_pdf_title'], + 'motion_pdf_preamble': config['motion_pdf_preamble'], + 'motion_allow_trivial_change': config['motion_allow_trivial_change'], } def form_valid(self, form): - config['application_min_supporters'] = form.cleaned_data['application_min_supporters'] - config['application_preamble'] = form.cleaned_data['application_preamble'] - config['application_pdf_ballot_papers_selection'] = form.cleaned_data['application_pdf_ballot_papers_selection'] - config['application_pdf_ballot_papers_number'] = form.cleaned_data['application_pdf_ballot_papers_number'] - config['application_pdf_title'] = form.cleaned_data['application_pdf_title'] - config['application_pdf_preamble'] = form.cleaned_data['application_pdf_preamble'] - config['application_allow_trivial_change'] = form.cleaned_data['application_allow_trivial_change'] + config['motion_min_supporters'] = form.cleaned_data['motion_min_supporters'] + config['motion_preamble'] = form.cleaned_data['motion_preamble'] + config['motion_pdf_ballot_papers_selection'] = form.cleaned_data['motion_pdf_ballot_papers_selection'] + config['motion_pdf_ballot_papers_number'] = form.cleaned_data['motion_pdf_ballot_papers_number'] + config['motion_pdf_title'] = form.cleaned_data['motion_pdf_title'] + config['motion_pdf_preamble'] = form.cleaned_data['motion_pdf_preamble'] + config['motion_allow_trivial_change'] = form.cleaned_data['motion_allow_trivial_change'] messages.success(self.request, _('Motion settings successfully saved.')) return super(Config, self).form_valid(form) def register_tab(request): - selected = True if request.path.startswith('/application/') else False + selected = True if request.path.startswith('/motion/') else False return Tab( - title=_('Applications'), - url=reverse('application_overview'), - permission=request.user.has_perm('application.can_see_application') or request.user.has_perm('application.can_support_application') or request.user.has_perm('application.can_support_application') or request.user.has_perm('application.can_manage_application'), + title=_('Motions'), + url=reverse('motion_overview'), + permission=request.user.has_perm('motion.can_see_motion') or request.user.has_perm('motion.can_support_motion') or request.user.has_perm('motion.can_support_motion') or request.user.has_perm('motion.can_manage_motion'), selected=selected, ) @@ -895,7 +895,7 @@ def register_tab(request): def get_widgets(request): return [ Widget( - name='applications', - template='application/widget.html', - context={'applications': Application.objects.all()}, - permission_required='application.can_manage_application')] + name='motions', + template='motion/widget.html', + context={'motions': Motion.objects.all()}, + permission_required='motion.can_manage_motion')] diff --git a/openslides/openslides_global_settings.py b/openslides/openslides_global_settings.py index 1da9f28fe..5d3348e9c 100644 --- a/openslides/openslides_global_settings.py +++ b/openslides/openslides_global_settings.py @@ -119,7 +119,7 @@ INSTALLED_APPS = ( 'openslides.poll', 'openslides.projector', 'openslides.agenda', - 'openslides.application', + 'openslides.motion', 'openslides.assignment', 'openslides.participant', 'openslides.config', diff --git a/openslides/participant/templates/participant/config.html b/openslides/participant/templates/participant/config.html index 83a33eae2..1a68ca591 100644 --- a/openslides/participant/templates/participant/config.html +++ b/openslides/participant/templates/participant/config.html @@ -12,8 +12,8 @@ - - diff --git a/openslides/urls.py b/openslides/urls.py index 0a21c503e..ce763b3f2 100644 --- a/openslides/urls.py +++ b/openslides/urls.py @@ -26,7 +26,7 @@ urlpatterns = patterns('', (r'^$', FrontPage.as_view()), (r'^agenda/', include('openslides.agenda.urls')), - (r'^application/', include('openslides.application.urls')), + (r'^motion/', include('openslides.motion.urls')), (r'^assignment/', include('openslides.assignment.urls')), (r'^participant/', include('openslides.participant.urls')), (r'^config/', include('openslides.config.urls')), diff --git a/openslides/utils/templatetags/tags.py b/openslides/utils/templatetags/tags.py index 187c900f3..96809af10 100644 --- a/openslides/utils/templatetags/tags.py +++ b/openslides/utils/templatetags/tags.py @@ -18,7 +18,7 @@ register = template.Library() @register.simple_tag def get_min_supporters(): - return config['application_min_supporters'] + return config['motion_min_supporters'] @register.simple_tag From 17afa3c5d11dd2ee74175a021bdf4f81bfdbd195 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Wed, 24 Oct 2012 11:35:07 +0200 Subject: [PATCH 044/222] fixed #326 whitespace in allready used names --- openslides/participant/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openslides/participant/api.py b/openslides/participant/api.py index 05b5c8bf4..3e5856391 100644 --- a/openslides/participant/api.py +++ b/openslides/participant/api.py @@ -47,7 +47,7 @@ def gen_username(first_name, last_name): i = 0 while True: i += 1 - testname = "%s%s%s" % (first_name, last_name, i) + testname = "%s %s %s" % (first_name, last_name, i) try: User.objects.get(username=testname) except User.DoesNotExist: From c58d47815133f286f27de2f498c17ac691e184cd Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Wed, 24 Oct 2012 11:39:27 +0200 Subject: [PATCH 045/222] rename render_to_forbitten to render_to_forbidden. #370 --- openslides/utils/utils.py | 4 ++-- openslides/utils/views.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openslides/utils/utils.py b/openslides/utils/utils.py index 6d14b35a6..41aaf7544 100644 --- a/openslides/utils/utils.py +++ b/openslides/utils/utils.py @@ -101,13 +101,13 @@ def permission_required(perm, login_url=None): if request.user.has_perm(perm): return func(request, *args, **kw) if request.user.is_authenticated(): - return render_to_forbitten(request) + return render_to_forbidden(request) return redirect(reverse('user_login')) return wrapper return renderer -def render_to_forbitten(request, error= +def render_to_forbidden(request, error= ugettext_lazy("Sorry, you have no rights to see this page.")): return HttpResponseForbidden(render_to_string('403.html', {'error': error}, context_instance=RequestContext(request))) diff --git a/openslides/utils/views.py b/openslides/utils/views.py index becdbfc8b..be40f9062 100644 --- a/openslides/utils/views.py +++ b/openslides/utils/views.py @@ -52,7 +52,7 @@ from django.views.generic.list import TemplateResponseMixin from openslides.config.models import config -from openslides.utils.utils import render_to_forbitten, html_strong +from openslides.utils.utils import render_to_forbidden, html_strong from openslides.utils.signals import template_manipulation from openslides.utils.pdf import firstPage, laterPages @@ -93,7 +93,7 @@ class PermissionMixin(object): return HttpResponseRedirect("%s?next=%s" % (settings.LOGIN_URL, path)) else: - return render_to_forbitten(request) + return render_to_forbidden(request) return _View.dispatch(self, request, *args, **kwargs) From f99fdc69817cb1931371fc6f38323b3237cbd468 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Wed, 24 Oct 2012 12:00:51 +0200 Subject: [PATCH 046/222] fixed inital_data --- initial_data.json | 48 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/initial_data.json b/initial_data.json index 5f7c8e30c..9b25d1a34 100644 --- a/initial_data.json +++ b/initial_data.json @@ -11,14 +11,14 @@ "item" ], [ - "can_create_application", - "application", - "application" + "can_create_motion", + "motion", + "motion" ], [ - "can_see_application", - "application", - "application" + "can_see_motion", + "motion", + "motion" ], [ "can_nominate_other", @@ -60,19 +60,19 @@ "item" ], [ - "can_create_application", - "application", - "application" + "can_create_motion", + "motion", + "motion" ], [ - "can_see_application", - "application", - "application" + "can_see_motion", + "motion", + "motion" ], [ - "can_support_application", - "application", - "application" + "can_support_motion", + "motion", + "motion" ], [ "can_nominate_other", @@ -119,19 +119,19 @@ "item" ], [ - "can_create_application", - "application", - "application" + "can_create_motion", + "motion", + "motion" ], [ - "can_manage_application", - "application", - "application" + "can_manage_motion", + "motion", + "motion" ], [ - "can_see_application", - "application", - "application" + "can_see_motion", + "motion", + "motion" ], [ "can_manage_assignment", From 3e1938941fa8a2e7bcd063fc05892b6a67691c56 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Wed, 24 Oct 2012 12:15:29 +0200 Subject: [PATCH 047/222] Append a default class for the person-api. Also fixed the assignment-ballot-paper for group-persons --- openslides/assignment/views.py | 8 ++++---- openslides/participant/models.py | 15 ++++++++------ openslides/utils/person/__init__.py | 3 ++- openslides/utils/person/api.py | 31 +++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py index 68f561c87..a65d10997 100644 --- a/openslides/assignment/views.py +++ b/openslides/assignment/views.py @@ -430,7 +430,7 @@ class AssignmentPDF(PDFView): for candidate, poll_list in vote_results.iteritems(): row = [] - candidate_string = candidate.user.get_full_name() + candidate_string = candidate.clean_name if candidate in elected_candidates: candidate_string = "* " + candidate_string if candidate.category: @@ -565,7 +565,7 @@ class AssignmentPollPDF(PDFView): if self.poll.yesnoabstain: for option in options: candidate = option.candidate - cell.append(Paragraph(candidate.user.get_full_name(), + cell.append(Paragraph(candidate.clean_name, stylesheet['Ballot_option_name'])) if candidate.name_suffix: cell.append(Paragraph("(%s)" % candidate.name_suffix, @@ -591,9 +591,9 @@ class AssignmentPollPDF(PDFView): else: for option in options: candidate = option.candidate - cell.append(Paragraph(circle + candidate.user.get_full_name(), + cell.append(Paragraph(circle + candidate.clean_name, stylesheet['Ballot_option_name'])) - if candidate.category: + if candidate.name_suffix: cell.append(Paragraph("(%s)" % candidate.category, stylesheet['Ballot_option_group_right'])) else: diff --git a/openslides/participant/models.py b/openslides/participant/models.py index 42b965f69..2cce07709 100644 --- a/openslides/participant/models.py +++ b/openslides/participant/models.py @@ -16,14 +16,14 @@ from django.db.models import signals from django.dispatch import receiver from django.utils.translation import ugettext_lazy as _, ugettext_noop -from openslides.utils.person import PersonMixin +from openslides.utils.person import PersonMixin, Person from openslides.utils.person.signals import receive_persons from openslides.config.models import config from openslides.config.signals import default_config_value -class User(DjangoUser, PersonMixin): +class User(DjangoUser, PersonMixin, Person): person_prefix = 'user' GENDER_CHOICES = ( ('male', _('Male')), @@ -56,6 +56,10 @@ class User(DjangoUser, PersonMixin): max_length=100, null=True, blank=True, verbose_name=_("Default password")) + @property + def clean_name(self): + return self.get_full_name() or self.username + def get_name_suffix(self): return self.category @@ -88,10 +92,9 @@ class User(DjangoUser, PersonMixin): return ('user_delete', [str(self.id)]) def __unicode__(self): - name = self.get_full_name() or self.username if self.name_suffix: - return u"%s (%s)" % (name, self.name_suffix) - return u"%s" % name + return u"%s (%s)" % (self.clean_name, self.name_suffix) + return u"%s" % self.clean_name class Meta: # Rename permissions @@ -103,7 +106,7 @@ class User(DjangoUser, PersonMixin): ordering = ('last_name',) -class Group(DjangoGroup, PersonMixin): +class Group(DjangoGroup, PersonMixin, Person): person_prefix = 'group' django_group = models.OneToOneField(DjangoGroup, editable=False, parent_link=True) diff --git a/openslides/utils/person/__init__.py b/openslides/utils/person/__init__.py index cc983caf9..7a69e8f25 100644 --- a/openslides/utils/person/__init__.py +++ b/openslides/utils/person/__init__.py @@ -11,7 +11,8 @@ """ from openslides.utils.person.signals import receive_persons -from openslides.utils.person.api import generate_person_id, get_person, Persons +from openslides.utils.person.api import (generate_person_id, get_person, + Person, Persons) from openslides.utils.person.forms import PersonFormField, MultiplePersonFormField from openslides.utils.person.models import PersonField, PersonMixin diff --git a/openslides/utils/person/api.py b/openslides/utils/person/api.py index 49d901f28..5c842dea2 100644 --- a/openslides/utils/person/api.py +++ b/openslides/utils/person/api.py @@ -13,6 +13,37 @@ from openslides.utils.person.signals import receive_persons +class Person(object): + """ + Meta-class for all person objects + """ + def person_id(self): + """ + Return an id for representation of ths person. Has to be unique. + """ + raise NotImplementedError('Any person object needs a person_id') + + def __repr__(self): + """ + Return a string for this person. + """ + return str(self.person_id) + + @property + def clean_name(self): + """ + Return the name of this person without a suffix + """ + return unicode(self) + + @property + def name_suffix(self): + """ + Return a suffix for the person-name. + """ + return '' + + class Persons(object): """ A Storage for a multiplicity of different Person-Objects. From 56b9e831c838be5e71bc94f63bf4354e7708c754 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Wed, 24 Oct 2012 12:21:44 +0200 Subject: [PATCH 048/222] Allowd access to the dashboard per default. #361 --- initial_data.json | 20 ++++++++++++++++++++ openslides/config/views.py | 5 +++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/initial_data.json b/initial_data.json index 9b25d1a34..a0d786baf 100644 --- a/initial_data.json +++ b/initial_data.json @@ -44,6 +44,11 @@ "can_see_projector", "projector", "projectorslide" + ], + [ + "can_see_dashboard", + "projector", + "projectorslide" ] ] } @@ -98,6 +103,11 @@ "can_see_projector", "projector", "projectorslide" + ], + [ + "can_see_dashboard", + "projector", + "projectorslide" ] ] } @@ -177,6 +187,11 @@ "can_see_projector", "projector", "projectorslide" + ], + [ + "can_see_dashboard", + "projector", + "projectorslide" ] ] } @@ -206,6 +221,11 @@ "can_see_projector", "projector", "projectorslide" + ], + [ + "can_see_dashboard", + "projector", + "projectorslide" ] ] } diff --git a/openslides/config/views.py b/openslides/config/views.py index 19b7b9953..908ac7db6 100644 --- a/openslides/config/views.py +++ b/openslides/config/views.py @@ -66,8 +66,9 @@ class GeneralConfig(FormView): try: anonymous = Group.objects.get(name='Anonymous') except Group.DoesNotExist: - default_perms = [u'can_see_agenda', u'can_see_projector', - u'can_see_motion', u'can_see_assignment'] + default_perms = ['can_see_agenda', 'can_see_projector', + 'can_see_motion', 'can_see_assignment', + 'can_see_dashboard'] anonymous = Group() anonymous.name = 'Anonymous' anonymous.save() From 57d591fee88b0b3ce563cc01a9504ca64f691a64 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Wed, 24 Oct 2012 12:30:45 +0200 Subject: [PATCH 049/222] Renamed category to detail --- openslides/assignment/views.py | 6 +++--- openslides/participant/forms.py | 4 ++-- openslides/participant/models.py | 14 +++++++------- .../templates/participant/overview.html | 14 +++++++------- openslides/participant/tests.py | 6 +++--- openslides/participant/views.py | 18 +++++++++--------- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py index a65d10997..0c1e1f969 100644 --- a/openslides/assignment/views.py +++ b/openslides/assignment/views.py @@ -433,8 +433,8 @@ class AssignmentPDF(PDFView): candidate_string = candidate.clean_name if candidate in elected_candidates: candidate_string = "* " + candidate_string - if candidate.category: - candidate_string += "\n(%s)" % candidate.category + if candidate.name_suffix: + candidate_string += "\n(%s)" % candidate.name_suffix row.append(candidate_string) for vote in poll_list: if vote == None: @@ -594,7 +594,7 @@ class AssignmentPollPDF(PDFView): cell.append(Paragraph(circle + candidate.clean_name, stylesheet['Ballot_option_name'])) if candidate.name_suffix: - cell.append(Paragraph("(%s)" % candidate.category, + cell.append(Paragraph("(%s)" % candidate.name_suffix, stylesheet['Ballot_option_group_right'])) else: cell.append(Paragraph(" ", diff --git a/openslides/participant/forms.py b/openslides/participant/forms.py index 4687432fe..153285d8f 100644 --- a/openslides/participant/forms.py +++ b/openslides/participant/forms.py @@ -27,7 +27,7 @@ class UserCreateForm(forms.ModelForm, CssClassMixin): class Meta: model = User - fields = ('first_name', 'last_name', 'is_active', 'groups', 'category', + fields = ('first_name', 'last_name', 'is_active', 'groups', 'detail', 'gender', 'type', 'committee', 'comment', 'default_password') @@ -35,7 +35,7 @@ class UserUpdateForm(UserCreateForm): class Meta: model = User fields = ('username', 'first_name', 'last_name', 'is_active', 'groups', - 'category', 'gender', 'type', 'committee', 'comment', + 'detail', 'gender', 'type', 'committee', 'comment', 'default_password') diff --git a/openslides/participant/models.py b/openslides/participant/models.py index 2cce07709..cabb54b7a 100644 --- a/openslides/participant/models.py +++ b/openslides/participant/models.py @@ -37,8 +37,8 @@ class User(DjangoUser, PersonMixin, Person): ) django_user = models.OneToOneField(DjangoUser, editable=False, parent_link=True) - category = models.CharField( - max_length=100, null=True, blank=True, verbose_name=_("Category"), + detail = models.CharField( + max_length=100, blank=True, default='', verbose_name=_("Detail"), help_text=_('Will be shown behind the name.')) gender = models.CharField( max_length=50, choices=GENDER_CHOICES, blank=True, @@ -47,13 +47,13 @@ class User(DjangoUser, PersonMixin, Person): max_length=100, choices=TYPE_CHOICES, blank=True, verbose_name=_("Typ"), help_text=_('Only for filter the userlist.')) committee = models.CharField( - max_length=100, null=True, blank=True, verbose_name=_("Committee"), + max_length=100, blank=True, default='', verbose_name=_("Committee"), help_text=_('Only for filter the userlist.')) comment = models.TextField( - null=True, blank=True, verbose_name=_('Comment'), + blank=True, default='', verbose_name=_('Comment'), help_text=_('Only for notes.')) default_password = models.CharField( - max_length=100, null=True, blank=True, + max_length=100, blank=True, default='', verbose_name=_("Default password")) @property @@ -61,10 +61,10 @@ class User(DjangoUser, PersonMixin, Person): return self.get_full_name() or self.username def get_name_suffix(self): - return self.category + return self.detail def set_name_suffix(self, value): - self.category = value + self.detail = value name_suffix = property(get_name_suffix, set_name_suffix) diff --git a/openslides/participant/templates/participant/overview.html b/openslides/participant/templates/participant/overview.html index 452bdcb53..f950bc302 100644 --- a/openslides/participant/templates/participant/overview.html +++ b/openslides/participant/templates/participant/overview.html @@ -26,11 +26,11 @@ - + + {% for detail in details %} + {% endfor %} - + + {% for level in structure_levels %} + {% endfor %} - - - - """ - % (message, url, csrf(request)['csrf_token'], _("Yes"), _("No"))) + messages.warning( + request, + """ + %s +
+ + + +
+ """ + % (message, url, csrf(request)['csrf_token'], _("Yes"), _("No"))) def del_confirm_form(request, object, name=None, delete_link=None): @@ -63,7 +65,8 @@ def del_confirm_form(request, object, name=None, delete_link=None): name = object if delete_link is None: delete_link = object.get_absolute_url('delete') - gen_confirm_form(request, _('Do you really want to delete %s?') + gen_confirm_form( + request, _('Do you really want to delete %s?') % html_strong(name), delete_link) @@ -79,11 +82,11 @@ def template(template_name): if not isinstance(output, dict): return output context = {} - template_manipulation.send(sender='utils_template', request=request, - context=context) + template_manipulation.send( + sender='utils_template', request=request, context=context) output.update(context) - response = render_to_response(template_name, output, - context_instance=RequestContext(request)) + response = render_to_response( + template_name, output, context_instance=RequestContext(request)) if 'cookie' in output: response.set_cookie(output['cookie'][0], output['cookie'][1]) return response @@ -109,12 +112,12 @@ def permission_required(perm, login_url=None): return renderer -def render_to_forbidden(request, error= - ugettext_lazy("Sorry, you have no rights to see this page.")): +def render_to_forbidden(request, + error=ugettext_lazy("Sorry, you have no rights to see this page.")): # TODO: Integrate this function into the PermissionMixin once the # above function is deleted. - return HttpResponseForbidden(render_to_string('403.html', - {'error': error}, context_instance=RequestContext(request))) + return HttpResponseForbidden(render_to_string( + '403.html', {'error': error}, context_instance=RequestContext(request))) def delete_default_permissions(**kwargs): @@ -122,9 +125,9 @@ def delete_default_permissions(**kwargs): Deletes the permissions, django creates by default for the admin. """ for p in Permission.objects.all(): - if p.codename.startswith('add') \ - or p.codename.startswith('delete') \ - or p.codename.startswith('change'): + if (p.codename.startswith('add') or + p.codename.startswith('delete') or + p.codename.startswith('change')): p.delete() diff --git a/openslides/utils/views.py b/openslides/utils/views.py index 5e814bf9d..b9d1fc4b9 100644 --- a/openslides/utils/views.py +++ b/openslides/utils/views.py @@ -22,8 +22,7 @@ except ImportError: # Is this exception realy necessary? from StringIO import StringIO -from reportlab.platypus import (SimpleDocTemplate, Paragraph, Frame, PageBreak, - Spacer, Table, LongTable, TableStyle, Image) +from reportlab.platypus import SimpleDocTemplate, Spacer from reportlab.lib.units import cm from django.contrib import messages @@ -34,9 +33,9 @@ from django.conf import settings from django.dispatch import receiver from django.http import HttpResponseServerError, HttpResponse, HttpResponseRedirect from django.utils.decorators import method_decorator -from django.utils.translation import ugettext as _, ugettext_noop, ugettext_lazy +from django.utils.translation import ugettext as _, ugettext_lazy from django.utils.importlib import import_module -from django.template import loader, RequestContext +from django.template import RequestContext from django.template.loader import render_to_string from django.views.generic import ( TemplateView as _TemplateView, @@ -50,8 +49,6 @@ from django.views.generic import ( from django.views.generic.detail import SingleObjectMixin from django.views.generic.list import TemplateResponseMixin -from openslides.config.models import config - from openslides.utils.utils import render_to_forbidden, html_strong from openslides.utils.signals import template_manipulation from openslides.utils.pdf import firstPage, laterPages @@ -64,8 +61,8 @@ View = _View class SetCookieMixin(object): def render_to_response(self, context, **response_kwargs): - response = TemplateResponseMixin.render_to_response(self, context, - **response_kwargs) + response = TemplateResponseMixin.render_to_response( + self, context, **response_kwargs) if 'cookie' in context: response.set_cookie(context['cookie'][0], context['cookie'][1]) return response @@ -90,8 +87,8 @@ class PermissionMixin(object): if not self.has_permission(request, *args, **kwargs): if not request.user.is_authenticated(): path = request.get_full_path() - return HttpResponseRedirect("%s?next=%s" % (settings.LOGIN_URL, - path)) + return HttpResponseRedirect( + "%s?next=%s" % (settings.LOGIN_URL, path)) else: return render_to_forbidden(request) return _View.dispatch(self, request, *args, **kwargs) @@ -130,18 +127,18 @@ class QuestionMixin(object): option_fields = "\n".join([ '' % (option[0], unicode(option[1])) for option in self.get_answer_options()]) - messages.warning(self.request, + messages.warning( + self.request, """ %(message)s
%(option_fields)s
- """ % { - 'message': self.get_question(), - 'url': self.get_answer_url(), - 'csrf': csrf(self.request)['csrf_token'], - 'option_fields': option_fields}) + """ % {'message': self.get_question(), + 'url': self.get_answer_url(), + 'csrf': csrf(self.request)['csrf_token'], + 'option_fields': option_fields}) def pre_post_redirect(self, request, *args, **kwargs): # Reacts on the response of the user in a POST-request. @@ -167,16 +164,16 @@ class QuestionMixin(object): class TemplateView(PermissionMixin, _TemplateView): def get_context_data(self, **kwargs): context = super(TemplateView, self).get_context_data(**kwargs) - template_manipulation.send(sender=self.__class__, request=self.request, - context=context) + template_manipulation.send( + sender=self.__class__, request=self.request, context=context) return context class ListView(PermissionMixin, SetCookieMixin, _ListView): def get_context_data(self, **kwargs): context = super(ListView, self).get_context_data(**kwargs) - template_manipulation.send(sender=self.__class__, request=self.request, - context=context) + template_manipulation.send( + sender=self.__class__, request=self.request, context=context) return context @@ -217,8 +214,8 @@ class FormView(PermissionMixin, _FormView): def get_context_data(self, **kwargs): context = super(FormView, self).get_context_data(**kwargs) - template_manipulation.send(sender=self.__class__, request=self.request, - context=context) + template_manipulation.send( + sender=self.__class__, request=self.request, context=context) return context def form_invalid(self, form): @@ -235,8 +232,8 @@ class UpdateView(PermissionMixin, _UpdateView): def get_context_data(self, **kwargs): context = super(UpdateView, self).get_context_data(**kwargs) - template_manipulation.send(sender=self.__class__, request=self.request, - context=context) + template_manipulation.send( + sender=self.__class__, request=self.request, context=context) return context def form_invalid(self, form): @@ -256,8 +253,8 @@ class CreateView(PermissionMixin, _CreateView): def get_context_data(self, **kwargs): context = super(CreateView, self).get_context_data(**kwargs) - template_manipulation.send(sender=self.__class__, request=self.request, - context=context) + template_manipulation.send( + sender=self.__class__, request=self.request, context=context) return context def get_apply_url(self): @@ -299,7 +296,6 @@ class DeleteView(SingleObjectMixin, QuestionMixin, RedirectView): class DetailView(TemplateView, SingleObjectMixin): def get(self, request, *args, **kwargs): self.object = self.get_object() - context = self.get_context_data(object=self.object) return super(DetailView, self).get(request, *args, **kwargs) def get_context_data(self, **kwargs): @@ -329,8 +325,8 @@ class PDFView(PermissionMixin, View): return SimpleDocTemplate(buffer) def build_document(self, pdf_document, story): - pdf_document.build(story, onFirstPage=firstPage, - onLaterPages=laterPages) + pdf_document.build( + story, onFirstPage=firstPage, onLaterPages=laterPages) def render_to_response(self, filename): response = HttpResponse(mimetype='application/pdf') @@ -340,7 +336,7 @@ class PDFView(PermissionMixin, View): buffer = StringIO() pdf_document = self.get_template(buffer) pdf_document.title = self.get_document_title() - story = [Spacer(1, self.get_top_space()*cm)] + story = [Spacer(1, self.get_top_space() * cm)] self.append_to_pdf(story) @@ -351,9 +347,6 @@ class PDFView(PermissionMixin, View): response.write(pdf) return response - def get_filename(self): - return self.filename - def get(self, request, *args, **kwargs): return self.render_to_response(self.get_filename()) @@ -364,9 +357,8 @@ def server_error(request, template_name='500.html'): Templates: `500.html` """ - t = loader.get_template("500.html") - return HttpResponseServerError(render_to_string('500.html', - context_instance=RequestContext(request))) + return HttpResponseServerError(render_to_string( + template_name, context_instance=RequestContext(request))) @receiver(template_manipulation, dispatch_uid="send_register_tab") From 6b2645d11cde92274c517b64af3e0328406c015a Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sat, 24 Nov 2012 15:00:17 +0100 Subject: [PATCH 162/222] reordered the tests moved the tests from the openslides-module to an own module configured coverage --- .coveragerc | 4 ++++ .gitignore | 4 ++++ openslides/agenda/views.py | 2 +- openslides/global_settings.py | 3 +++ tests/__init__.py | 0 openslides/agenda/tests.py => tests/test_agenda.py | 2 +- openslides/motion/tests.py => tests/test_motion.py | 0 openslides/participant/tests.py => tests/test_participant.py | 0 8 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 .coveragerc create mode 100644 tests/__init__.py rename openslides/agenda/tests.py => tests/test_agenda.py (99%) rename openslides/motion/tests.py => tests/test_motion.py (100%) rename openslides/participant/tests.py => tests/test_participant.py (100%) diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 000000000..8655e4714 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,4 @@ +[run] +source=openslides +[report] +exclude_lines = def __(unicode|repr)__ diff --git a/.gitignore b/.gitignore index 6fa3cff77..d43bad4e2 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,7 @@ docs/_build/* build/* dist/* .DS_Store + +# Unit test / coverage reports +.coverage +htmlcov diff --git a/openslides/agenda/views.py b/openslides/agenda/views.py index 2c684bc95..55b42e204 100644 --- a/openslides/agenda/views.py +++ b/openslides/agenda/views.py @@ -27,7 +27,7 @@ from openslides.utils.utils import html_strong from openslides.projector.api import get_active_slide from openslides.projector.projector import Widget, SLIDE from .models import Item -from .agenda.forms import ItemOrderForm, ItemForm +from .forms import ItemOrderForm, ItemForm class Overview(TemplateView): diff --git a/openslides/global_settings.py b/openslides/global_settings.py index fd148ebe5..174d57d09 100644 --- a/openslides/global_settings.py +++ b/openslides/global_settings.py @@ -139,3 +139,6 @@ CACHES = { 'LOCATION': 'openslidecache' } } + +TEST_RUNNER = 'discover_runner.DiscoverRunner' +TEST_DISCOVER_TOP_LEVEL = os.path.dirname(os.path.dirname(__file__)) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/openslides/agenda/tests.py b/tests/test_agenda.py similarity index 99% rename from openslides/agenda/tests.py rename to tests/test_agenda.py index 0e270b36d..4e8a32d1d 100644 --- a/openslides/agenda/tests.py +++ b/tests/test_agenda.py @@ -16,7 +16,7 @@ from django.db.models.query import EmptyQuerySet from openslides.projector.api import get_active_slide from openslides.participant.models import User -from .models import Item +from openslides.agenda.models import Item class ItemTest(TestCase): diff --git a/openslides/motion/tests.py b/tests/test_motion.py similarity index 100% rename from openslides/motion/tests.py rename to tests/test_motion.py diff --git a/openslides/participant/tests.py b/tests/test_participant.py similarity index 100% rename from openslides/participant/tests.py rename to tests/test_participant.py From c405e9b648bcf8a16bb694a78f5496df3fafd8af Mon Sep 17 00:00:00 2001 From: Andy Kittner Date: Sat, 24 Nov 2012 14:22:02 +0100 Subject: [PATCH 163/222] Rework default settings handling (fixes #409) --- openslides/main.py | 155 ++++++++++++++++++++++++++++----------------- 1 file changed, 98 insertions(+), 57 deletions(-) diff --git a/openslides/main.py b/openslides/main.py index 83e41395e..80fe370a2 100755 --- a/openslides/main.py +++ b/openslides/main.py @@ -13,13 +13,15 @@ # for python 2.5 support from __future__ import with_statement -import os -import sys -import optparse -import socket -import time -import threading import base64 +import ctypes +import optparse +import os +import socket +import sys +import tempfile +import threading +import time import webbrowser import django.conf @@ -28,14 +30,15 @@ from django.core.management import execute_from_command_line CONFIG_TEMPLATE = """#!/usr/bin/env python # -*- coding: utf-8 -*- +import openslides.main from openslides.global_settings import * # Use 'DEBUG = True' to get more details for server errors -# (Default for relaeses: 'False') +# (Default for releases: 'False') DEBUG = False TEMPLATE_DEBUG = DEBUG -DBPATH = %(dbpath)r +DBPATH = %(dbpath)s DATABASES = { 'default': { @@ -64,6 +67,10 @@ INSTALLED_APPS += INSTALLED_PLUGINS KEY_LENGTH = 30 +# sentinel used to signal that the database ought to be stored +# relative to the portable's directory +_portable_db_path = object() + _fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() def _fs2unicode(s): @@ -71,8 +78,7 @@ def _fs2unicode(s): return s return s.decode(_fs_encoding) - -def main(argv=None, opt_defaults=None, database_path=None): +def process_options(argv = None): if argv is None: argv = sys.argv[1:] @@ -90,21 +96,48 @@ def main(argv=None, opt_defaults=None, database_path=None): parser.add_option( "--no-reload", action="store_true", help="Do not reload the development server") - if not opt_defaults is None: - parser.set_defaults(**opt_defaults) - opts, args = parser.parse_args(argv) if args: sys.stderr.write("This command does not take arguments!\n\n") parser.print_help() sys.exit(1) + return opts + +def main(argv=None): + opts = process_options(argv) + _main(opts) + +def win32_portable_main(argv=None): + """special entry point for the win32 portable version""" + + opts = process_options(argv) + + database_path = None + + if opts.settings is None: + portable_dir = get_portable_path() + try: + fd, test_file = tempfile.mkstemp(dir=portable_dir) + except OSError: + portable_dir_writeable = False + else: + portable_dir_writeable = True + os.close(fd) + os.unlink(test_file) + + if portable_dir_writeable: + opts.settings = os.path.join(portable_dir, + "openslides", "settings.py") + database_path = _portable_db_path + + _main(opts, database_path=database_path) + +def _main(opts, database_path=None): # Find the path to the settings settings_path = opts.settings if settings_path is None: - config_home = os.environ.get('XDG_CONFIG_HOME', \ - os.path.join(os.path.expanduser('~'), '.config')) - settings_path = os.path.join(config_home, 'openslides', 'settings.py') + settings_path = get_user_config_path('openslides', 'settings.py') # Create settings if necessary if not os.path.exists(settings_path): @@ -141,14 +174,17 @@ def main(argv=None, opt_defaults=None, database_path=None): def create_settings(settings_path, database_path=None): settings_module = os.path.dirname(settings_path) - if database_path is None: - data_home = os.environ.get('XDG_DATA_HOME', \ - os.path.join(os.path.expanduser('~'), '.local', 'share')) - database_path = os.path.join(data_home, 'openslides', 'database.sqlite') + if database_path is _portable_db_path: + database_path = get_portable_db_path() + dbpath_value = 'openslides.main.get_portable_db_path()' + else: + if database_path is None: + database_path = get_user_data_path('openslides', 'database.sqlite') + dbpath_value = repr(_fs2unicode(database_path)) settings_content = CONFIG_TEMPLATE % dict( default_key=base64.b64encode(os.urandom(KEY_LENGTH)), - dbpath=_fs2unicode(database_path)) + dbpath=dbpath_value) if not os.path.exists(settings_module): os.makedirs(settings_module) @@ -269,51 +305,56 @@ def start_browser(url): t = threading.Thread(target=f) t.start() -def win32_portable_main(argv=None): - """special entry point for the win32 portable version""" - import tempfile +def get_user_config_path(*args): + if sys.platform == "win32": + return win32_get_app_data_path(*args) + config_home = os.environ.get('XDG_CONFIG_HOME', \ + os.path.join(os.path.expanduser('~'), '.config')) + + return os.path.join(_fs2unicode(config_home), *args) + +def get_user_data_path(*args): + if sys.platform == "win32": + return win32_get_app_data_path(*args) + + data_home = os.environ.get('XDG_DATA_HOME', \ + os.path.join(os.path.expanduser('~'), '.local', 'share')) + + return os.path.join(_fs2unicode(data_home), *args) + +def get_portable_path(*args): # NOTE: sys.executable will be the path to openslides.exe # since it is essentially a small wrapper that embeds the # python interpreter - portable_dir = os.path.dirname(os.path.abspath(sys.executable)) - try: - fd, test_file = tempfile.mkstemp(dir=portable_dir) - except OSError: - portable_dir_writeable = False - else: - portable_dir_writeable = True - os.close(fd) - os.unlink(test_file) - if portable_dir_writeable: - default_settings = os.path.join(portable_dir, "openslides", - "openslides_personal_settings.py") - database_path = os.path.join(portable_dir, "openslides", - "database.sqlite") - else: - import ctypes + exename = os.path.basename(sys.executable).lower() + if exename != "openslides.exe": + raise Exception("Cannot determine portable path when " + "not running as portable") - shell32 = ctypes.WinDLL("shell32.dll") - SHGetFolderPath = shell32.SHGetFolderPathW - SHGetFolderPath.argtypes = (ctypes.c_void_p, ctypes.c_int, - ctypes.c_void_p, ctypes.c_uint32, ctypes.c_wchar_p) - SHGetFolderPath.restype = ctypes.c_uint32 + portable_dir = _fs2unicode(os.path.dirname(os.path.abspath(sys.executable))) + return os.path.join(portable_dir, *args) - CSIDL_LOCAL_APPDATA = 0x001c - MAX_PATH = 260 +def get_portable_db_path(): + return get_portable_path('openslides', 'database.sqlite') - buf = ctypes.create_unicode_buffer(MAX_PATH) - res = SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, 0, buf) - if res != 0: - raise Exception("Could not deterime APPDATA path") - default_settings = os.path.join(buf.value, "openslides", - "openslides_personal_settings.py") - database_path = os.path.join(buf.value, "openslides", - "database.sqlite") +def win32_get_app_data_path(*args): + shell32 = ctypes.WinDLL("shell32.dll") + SHGetFolderPath = shell32.SHGetFolderPathW + SHGetFolderPath.argtypes = (ctypes.c_void_p, ctypes.c_int, + ctypes.c_void_p, ctypes.c_uint32, ctypes.c_wchar_p) + SHGetFolderPath.restype = ctypes.c_uint32 - main(argv, opt_defaults={ "settings": default_settings }, - database_path=database_path) + CSIDL_LOCAL_APPDATA = 0x001c + MAX_PATH = 260 + + buf = ctypes.create_unicode_buffer(MAX_PATH) + res = SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, 0, 0, buf) + if res != 0: + raise Exception("Could not deterime APPDATA path") + + return os.path.join(buf.value, *args) if __name__ == "__main__": From 220abe45c340563f85473aed6055554b844837e7 Mon Sep 17 00:00:00 2001 From: Andy Kittner Date: Sat, 24 Nov 2012 14:53:08 +0100 Subject: [PATCH 164/222] Copy _ctypes.pyd We need ctypes to determine the local app data directory (used for settings.py when portable dir is not writable) --- extras/win32-portable/prepare_portable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/extras/win32-portable/prepare_portable.py b/extras/win32-portable/prepare_portable.py index 9418b8e10..6554a4939 100644 --- a/extras/win32-portable/prepare_portable.py +++ b/extras/win32-portable/prepare_portable.py @@ -87,6 +87,7 @@ PY_DLLS = [ "_sqlite3.pyd", "_socket.pyd", "select.pyd", + "_ctypes.pyd", ] MSVCR_PUBLIC_KEY = "1fc8b3b9a1e18e3b" From 4eed43f78299032256e4ef8b8b4d1b4577181a95 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sat, 24 Nov 2012 15:26:20 +0100 Subject: [PATCH 165/222] Configured the repo for travis --- .travis.yml | 9 +++++++++ requirements.txt | 4 ++++ 2 files changed, 13 insertions(+) create mode 100644 .travis.yml create mode 100644 requirements.txt diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..c8cbbca3a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: python +python: + - "2.5" + - "2.6" + - "2.7" +install: + - pip install -r requirements.txt --use-mirrors + - pip install coverage django-discover-runner +script: coverage run ./manage.py test folivora && coverage report -m diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..6854e46d1 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +Django==1.4 +django-mptt +reportlab +pil From ddd251a742f94d9b79528287b81c6d6590f38cd5 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sat, 24 Nov 2012 15:43:17 +0100 Subject: [PATCH 166/222] fix for travis --- .travis.yml | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c8cbbca3a..3e6409fbd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,4 +6,4 @@ python: install: - pip install -r requirements.txt --use-mirrors - pip install coverage django-discover-runner -script: coverage run ./manage.py test folivora && coverage report -m +script: coverage run ./manage.py test tests && coverage report -m diff --git a/requirements.txt b/requirements.txt index 6854e46d1..9a69ad2b9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django==1.4 +Django==1.4.2 django-mptt reportlab pil From a7c13e3285db111382d2a31d3e1077d788e138e7 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sat, 24 Nov 2012 16:22:48 +0100 Subject: [PATCH 167/222] added script to create a local settings --- .gitignore | 1 + .travis.yml | 1 + extras/scripts/create_local_settings.py | 15 +++++++++++++++ 3 files changed, 17 insertions(+) create mode 100644 extras/scripts/create_local_settings.py diff --git a/.gitignore b/.gitignore index d43bad4e2..d5edd3499 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ docs/_build/* build/* dist/* .DS_Store +settings.py # Unit test / coverage reports .coverage diff --git a/.travis.yml b/.travis.yml index 3e6409fbd..b65d5b1dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,4 +6,5 @@ python: install: - pip install -r requirements.txt --use-mirrors - pip install coverage django-discover-runner + - python extras/scripts/create_local_settings.py script: coverage run ./manage.py test tests && coverage report -m diff --git a/extras/scripts/create_local_settings.py b/extras/scripts/create_local_settings.py new file mode 100644 index 000000000..1702992e0 --- /dev/null +++ b/extras/scripts/create_local_settings.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os +import sys + +script_path = os.path.realpath(os.path.dirname(__file__)) +sys.path.append(os.path.join(script_path, '..', '..')) + +from openslides.main import create_settings + +if __name__ == "__main__": + cwd = os.getcwd() + create_settings(os.path.join(cwd, 'settings.py'), + os.path.join(cwd, 'database.sqlite')) From 5cf27b358dcaf9dce82478d962edb83234ec5a1e Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sat, 24 Nov 2012 16:28:47 +0100 Subject: [PATCH 168/222] added simplejson into the requirements for python 2.5 --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 9a69ad2b9..5a62061ce 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ Django==1.4.2 django-mptt reportlab pil +simplejson From 65eeffe1c1cce5f4edaa015fc6757c4dc3b0f0ed Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sat, 24 Nov 2012 16:51:21 +0100 Subject: [PATCH 169/222] Changed pil to PIL in requirements --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 5a62061ce..15fe79d8d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ Django==1.4.2 django-mptt reportlab -pil +PIL simplejson From e0ce1052c0031b24927599d7f707962a206c0ddb Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Sat, 24 Nov 2012 17:34:56 +0100 Subject: [PATCH 170/222] Catch AttributeError for 'person.sort_name' in assignment/models.py --- openslides/assignment/models.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openslides/assignment/models.py b/openslides/assignment/models.py index b70972234..c208592c4 100644 --- a/openslides/assignment/models.py +++ b/openslides/assignment/models.py @@ -160,7 +160,10 @@ class Assignment(models.Model, SlideMixin): participants = [] for candidate in candidates.all(): participants.append(candidate.person) - participants.sort(key=lambda person: person.sort_name) + try: + participants.sort(key=lambda person: person.sort_name) + except AttributeError: + pass return participants #return candidates.values_list('person', flat=True) From ec60207cfda60e661da4fa4e355e2f2d3119a444 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Sat, 24 Nov 2012 17:39:28 +0100 Subject: [PATCH 171/222] Fixed typo (candidation -> candidature) --- openslides/assignment/models.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/openslides/assignment/models.py b/openslides/assignment/models.py index c208592c4..cdb9832bf 100644 --- a/openslides/assignment/models.py +++ b/openslides/assignment/models.py @@ -85,16 +85,16 @@ class Assignment(models.Model, SlideMixin): raise NameError(_('%s is already a candidate.') % candidate) if not person.has_perm("assignment.can_manage_assignment") and self.status != 'sea': raise NameError(_('The candidate list is already closed.')) - candidation = self.assignment_candidates.filter(person=candidate) - if candidation and candidate != person and \ + candidature = self.assignment_candidates.filter(person=candidate) + if candidature and candidate != person and \ not person.has_perm("assignment.can_manage_assignment"): - # if the candidation is blocked and anotherone tries to run the + # if the candidature is blocked and anotherone tries to run the # candidate raise NameError( _('%s does not want to be a candidate.') % candidate) - elif candidation: - candidation[0].blocked = False - candidation[0].save() + elif candidature: + candidature[0].blocked = False + candidature[0].save() else: AssignmentCandidate(assignment=self, person=candidate).save() @@ -103,18 +103,18 @@ class Assignment(models.Model, SlideMixin): stop running for a vote """ try: - candidation = self.assignment_candidates.get(person=candidate) + candidature = self.assignment_candidates.get(person=candidate) except AssignmentCandidate.DoesNotExist: raise Exception(_('%s is no candidate') % candidate) - if not candidation.blocked: + if not candidature.blocked: if blocked: - candidation.blocked = True - candidation.save() + candidature.blocked = True + candidature.save() else: - candidation.delete() + candidature.delete() else: - candidation.delete() + candidature.delete() def is_candidate(self, person): @@ -129,7 +129,7 @@ class Assignment(models.Model, SlideMixin): def is_blocked(self, person): """ - return True, if the person is blockt for candidation. + return True, if the person is blockt for candidature. """ return self.assignment_candidates.filter(person=person) \ .filter(blocked=True).exists() From 21a51523a4f4c0b4d901f48aeba2ebe300889fd7 Mon Sep 17 00:00:00 2001 From: Andy Kittner Date: Sat, 24 Nov 2012 20:35:06 +0100 Subject: [PATCH 172/222] Make pep8.py happy --- openslides/main.py | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/openslides/main.py b/openslides/main.py index 80fe370a2..fa3ce3c98 100755 --- a/openslides/main.py +++ b/openslides/main.py @@ -73,12 +73,15 @@ _portable_db_path = object() _fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() + + def _fs2unicode(s): if isinstance(s, unicode): return s return s.decode(_fs_encoding) -def process_options(argv = None): + +def process_options(argv=None): if argv is None: argv = sys.argv[1:] @@ -104,10 +107,12 @@ def process_options(argv = None): return opts + def main(argv=None): opts = process_options(argv) _main(opts) + def win32_portable_main(argv=None): """special entry point for the win32 portable version""" @@ -127,12 +132,13 @@ def win32_portable_main(argv=None): os.unlink(test_file) if portable_dir_writeable: - opts.settings = os.path.join(portable_dir, - "openslides", "settings.py") + opts.settings = os.path.join( + portable_dir, "openslides", "settings.py") database_path = _portable_db_path _main(opts, database_path=database_path) + def _main(opts, database_path=None): # Find the path to the settings settings_path = opts.settings @@ -305,24 +311,28 @@ def start_browser(url): t = threading.Thread(target=f) t.start() + def get_user_config_path(*args): if sys.platform == "win32": return win32_get_app_data_path(*args) - config_home = os.environ.get('XDG_CONFIG_HOME', \ - os.path.join(os.path.expanduser('~'), '.config')) + config_home = os.environ.get( + 'XDG_CONFIG_HOME', os.path.join(os.path.expanduser('~'), '.config')) return os.path.join(_fs2unicode(config_home), *args) + def get_user_data_path(*args): if sys.platform == "win32": return win32_get_app_data_path(*args) - data_home = os.environ.get('XDG_DATA_HOME', \ - os.path.join(os.path.expanduser('~'), '.local', 'share')) + data_home = os.environ.get( + 'XDG_DATA_HOME', os.path.join( + os.path.expanduser('~'), '.local', 'share')) return os.path.join(_fs2unicode(data_home), *args) + def get_portable_path(*args): # NOTE: sys.executable will be the path to openslides.exe # since it is essentially a small wrapper that embeds the @@ -330,20 +340,24 @@ def get_portable_path(*args): exename = os.path.basename(sys.executable).lower() if exename != "openslides.exe": - raise Exception("Cannot determine portable path when " + raise Exception( + "Cannot determine portable path when " "not running as portable") portable_dir = _fs2unicode(os.path.dirname(os.path.abspath(sys.executable))) return os.path.join(portable_dir, *args) + def get_portable_db_path(): return get_portable_path('openslides', 'database.sqlite') + def win32_get_app_data_path(*args): shell32 = ctypes.WinDLL("shell32.dll") SHGetFolderPath = shell32.SHGetFolderPathW - SHGetFolderPath.argtypes = (ctypes.c_void_p, ctypes.c_int, - ctypes.c_void_p, ctypes.c_uint32, ctypes.c_wchar_p) + SHGetFolderPath.argtypes = ( + ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_uint32, + ctypes.c_wchar_p) SHGetFolderPath.restype = ctypes.c_uint32 CSIDL_LOCAL_APPDATA = 0x001c From b3806d8cdd0231c1fb7307df859093e7320482df Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sat, 24 Nov 2012 21:10:55 +0100 Subject: [PATCH 173/222] some tests for the agenda --- openslides/utils/jsonfield/tests.py | 108 ---------------------------- tests/test_agenda.py | 39 ++++++++++ tests/test_init.py | 19 +++++ 3 files changed, 58 insertions(+), 108 deletions(-) delete mode 100644 openslides/utils/jsonfield/tests.py create mode 100644 tests/test_init.py diff --git a/openslides/utils/jsonfield/tests.py b/openslides/utils/jsonfield/tests.py deleted file mode 100644 index 2eb87ec37..000000000 --- a/openslides/utils/jsonfield/tests.py +++ /dev/null @@ -1,108 +0,0 @@ -from django.db import models -from django.test import TestCase -from django.utils import simplejson as json - -from fields import JSONField - - -class JsonModel(models.Model): - json = JSONField() - - -class ComplexEncoder(json.JSONEncoder): - def default(self, obj): - if isinstance(obj, complex): - return { - '__complex__': True, - 'real': obj.real, - 'imag': obj.imag, - } - - return json.JSONEncoder.default(self, obj) - - -def as_complex(dct): - if '__complex__' in dct: - return complex(dct['real'], dct['imag']) - return dct - - -class JSONModelCustomEncoders(models.Model): - # A JSON field that can store complex numbers - json = JSONField( - dump_kwargs={'cls': ComplexEncoder}, - load_kwargs={'object_hook': as_complex}, - ) - - -class JSONFieldTest(TestCase): - """JSONField Wrapper Tests""" - - def test_json_field_create(self): - """Test saving a JSON object in our JSONField""" - - json_obj = { - "item_1": "this is a json blah", - "blergh": "hey, hey, hey"} - - obj = JsonModel.objects.create(json=json_obj) - new_obj = JsonModel.objects.get(id=obj.id) - - self.failUnlessEqual(new_obj.json, json_obj) - - def test_json_field_modify(self): - """Test modifying a JSON object in our JSONField""" - - json_obj_1 = {'a': 1, 'b': 2} - json_obj_2 = {'a': 3, 'b': 4} - - obj = JsonModel.objects.create(json=json_obj_1) - - self.failUnlessEqual(obj.json, json_obj_1) - - obj.json = json_obj_2 - - self.failUnlessEqual(obj.json, json_obj_2) - - obj.save() - - self.failUnlessEqual(obj.json, json_obj_2) - - self.assert_(obj) - - def test_json_field_load(self): - """Test loading a JSON object from the DB""" - - json_obj_1 = {'a': 1, 'b': 2} - - obj = JsonModel.objects.create(json=json_obj_1) - - new_obj = JsonModel.objects.get(id=obj.id) - - self.failUnlessEqual(new_obj.json, json_obj_1) - - def test_json_list(self): - """Test storing a JSON list""" - - json_obj = ["my", "list", "of", 1, "objs", {"hello": "there"}] - - obj = JsonModel.objects.create(json=json_obj) - new_obj = JsonModel.objects.get(id=obj.id) - self.failUnlessEqual(new_obj.json, json_obj) - - def test_empty_objects(self): - """Test storing empty objects""" - - for json_obj in [{}, [], 0, '', False]: - obj = JsonModel.objects.create(json=json_obj) - new_obj = JsonModel.objects.get(id=obj.id) - self.failUnlessEqual(json_obj, obj.json) - self.failUnlessEqual(json_obj, new_obj.json) - - def test_custom_encoder(self): - """Test encoder_cls and object_hook""" - value = 1 + 3j # A complex number - - obj = JSONModelCustomEncoders.objects.create(json=value) - new_obj = JSONModelCustomEncoders.objects.get(pk=obj.pk) - self.failUnlessEqual(value, new_obj.json) diff --git a/tests/test_agenda.py b/tests/test_agenda.py index 4e8a32d1d..14fcf78e2 100644 --- a/tests/test_agenda.py +++ b/tests/test_agenda.py @@ -17,6 +17,7 @@ from django.db.models.query import EmptyQuerySet from openslides.projector.api import get_active_slide from openslides.participant.models import User from openslides.agenda.models import Item +from openslides.agenda.slides import agenda_show class ItemTest(TestCase): @@ -65,6 +66,29 @@ class ItemTest(TestCase): self.item1.related_sid = 'foobar' self.assertFalse(self.item1.get_related_slide() is None) + def test_title_supplement(self): + self.assertEqual(self.item1.get_title_supplement(), '') + + def test_delete_item(self): + new_item1 = Item.objects.create() + new_item2 = Item.objects.create(parent=new_item1) + new_item3 = Item.objects.create(parent=new_item2) + new_item1.delete() + self.assertTrue(new_item3 in Item.objects.all()) + new_item2.delete(with_children=True) + self.assertFalse(new_item3 in Item.objects.all()) + + def test_absolute_url(self): + self.assertEqual(self.item1.get_absolute_url(), '/agenda/1/') + self.assertEqual(self.item1.get_absolute_url('edit'), '/agenda/1/edit/') + self.assertEqual(self.item1.get_absolute_url('delete'), '/agenda/1/del/') + + def test_agenda_slide(self): + data = agenda_show() + self.assertEqual(list(data['items']), list(Item.objects.all().filter(parent=None))) + self.assertEqual(data['template'], 'projector/AgendaSummary.html') + self.assertEqual(data['title'], 'Agenda') + class ViewTest(TestCase): def setUp(self): @@ -94,6 +118,13 @@ class ViewTest(TestCase): def anonymClient(self): return Client() + def testOverview(self): + c = self.adminClient + + response = c.get('/agenda/') + self.assertEqual(response.status_code, 200) + self.assertEqual(len(response.context['items']), len(Item.objects.all())) + def testActivate(self): c = self.adminClient @@ -125,6 +156,14 @@ class ViewTest(TestCase): self.refreshItems() self.assertEqual(response.status_code, 404) + # Test ajax + response = c.get('/agenda/%d/close/' % self.item1.id, + HTTP_X_REQUESTED_WITH='XMLHttpRequest') + self.assertEqual(response.status_code, 200) + response = c.get('/agenda/%d/open/' % self.item1.id, + HTTP_X_REQUESTED_WITH='XMLHttpRequest') + self.assertEqual(response.status_code, 200) + def testEdit(self): c = self.adminClient diff --git a/tests/test_init.py b/tests/test_init.py new file mode 100644 index 000000000..158620f87 --- /dev/null +++ b/tests/test_init.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" + Unit test for OpenSlides __init__.py + + :copyright: 2011, 2012 by OpenSlides team, see AUTHORS. + :license: GNU GPL, see LICENSE for more details. +""" + +from django.test import TestCase + +from openslides import get_version + +class InitTest(TestCase): + def testget_version(self): + self.assertEqual(get_version((1, 3, 0, 'beta', 2)), '1.3-beta2') + self.assertEqual(get_version((1, 0, 0, 'final', 0)), '1.0') + self.assertEqual(get_version((2, 5, 3, 'alpha', 0)), '2.5.3-alpha0') + self.assertEqual(len(get_version((2, 5, 0, 'dev', 0))), 47) From 763da9233be340203cd36e93d478bda7e13ef83d Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sat, 24 Nov 2012 21:21:34 +0100 Subject: [PATCH 174/222] Fixed error in get_version --- tests/test_init.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_init.py b/tests/test_init.py index 158620f87..6155716f1 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -12,8 +12,12 @@ from django.test import TestCase from openslides import get_version class InitTest(TestCase): - def testget_version(self): + def test_get_version(self): self.assertEqual(get_version((1, 3, 0, 'beta', 2)), '1.3-beta2') self.assertEqual(get_version((1, 0, 0, 'final', 0)), '1.0') self.assertEqual(get_version((2, 5, 3, 'alpha', 0)), '2.5.3-alpha0') - self.assertEqual(len(get_version((2, 5, 0, 'dev', 0))), 47) + git_version = get_version((2, 5, 0, 'dev', 0)) + if 'unknown' in git_version: + self.assertEqual(len(git_version), 14) + else: + self.assertEqual(len(git_version), 47) From 3f469ab9d60d06045a706d5140c106c4a85c4ada Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sat, 24 Nov 2012 21:26:09 +0100 Subject: [PATCH 175/222] Commited the fix for get_version --- openslides/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openslides/__init__.py b/openslides/__init__.py index a9fc81a12..93ec6dc61 100644 --- a/openslides/__init__.py +++ b/openslides/__init__.py @@ -29,12 +29,11 @@ def get_version(version=None): if version[3] != 'final': if version[3] == 'dev': try: + import os git_head_path = '.git/' + open('.git/HEAD', 'r').read()[5:].rstrip() + git_commit_id = open(os.path.abspath(git_head_path), 'r').read().rstrip() except IOError: git_commit_id = 'unknown' - else: - import os - git_commit_id = open(os.path.abspath(git_head_path), 'r').read().rstrip() sub = '-%s%s' % (version[3], git_commit_id) else: sub = '-' + version[3] + str(version[4]) From 5d5989b67e9ab2f6b7ce6c2cd5dbb8aa1b0b93e2 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sun, 25 Nov 2012 00:19:38 +0100 Subject: [PATCH 176/222] removed the tests package from the distribution --- .gitignore | 1 + setup.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d5edd3499..7f7a1c453 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ build/* dist/* .DS_Store settings.py +versiontools* # Unit test / coverage reports .coverage diff --git a/setup.py b/setup.py index 6b2911a46..c7da7ef4d 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ setup( author='OpenSlides-Team', author_email='support@openslides.org', license='GPL2+', - packages=find_packages(), + packages=find_packages(exclude=['tests']), include_package_data = True, classifiers = [ # http://pypi.python.org/pypi?%3Aaction=list_classifiers From 691a27655c53e3c4cd47d5fe85dba10e45ef4729 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sun, 25 Nov 2012 00:28:41 +0100 Subject: [PATCH 177/222] Include the README.txt as long-description into the distribution --- README.txt | 17 +++++++++-------- setup.py | 4 ++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/README.txt b/README.txt index 92ca78025..e6449d35b 100644 --- a/README.txt +++ b/README.txt @@ -1,6 +1,6 @@ - ================================== - English README file for OpenSlides - ================================== +================================== +English README file for OpenSlides +================================== This is OpenSlides, version 1.3-beta2 (2012-11-09). @@ -10,7 +10,7 @@ What is OpenSlides? OpenSlides is a free, web-based presentation system for displaying and controlling of agenda, applications and elections of an assembly. -See http://www.openslides.org for more information. +See http://openslides.org for more information. Getting started @@ -18,14 +18,15 @@ Getting started Install and start OpenSlides as described in the INSTALL.txt. If you need help please contact the OpenSlides team on public mailing -list or read the OpenSlides manual. See http://www.openslides.org. +list or read the OpenSlides manual. See http://openslides.org. The start script of OpenSlides ============================== -Simply running - openslides.exe (on Windows) or - python start.py (on Linux/MacOS) +Simply running + openslides.exe (on Windows) or + python start.py (on Linux/MacOS) + will start OpenSlides using djangos development server. It will also try to open OpenSlides in your default webbrowser. diff --git a/setup.py b/setup.py index c7da7ef4d..ed1c3a018 100644 --- a/setup.py +++ b/setup.py @@ -12,9 +12,13 @@ from setuptools import find_packages from openslides import get_version +with open('README.txt') as file: + long_description = file.read() + setup( name='openslides', description='Presentation-System', + long_description=long_description, version=get_version(), url='http://openslides.org', author='OpenSlides-Team', From a31a67c32e649930e75eaff6688517b1cffd55f1 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sun, 25 Nov 2012 00:55:01 +0100 Subject: [PATCH 178/222] removed initial_data --- MANIFEST.in | 7 ++----- .../participant/fixtures/groups_de.json | 0 2 files changed, 2 insertions(+), 5 deletions(-) rename initial_data.json => openslides/participant/fixtures/groups_de.json (100%) diff --git a/MANIFEST.in b/MANIFEST.in index d028d548b..0977abf4e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,5 @@ include AUTHORS include CHANGELOG -include initial_data.json include INSTALL.txt include LICENSE include manage.py @@ -12,16 +11,14 @@ recursive-include openslides/templates * recursive-include openslides/agenda/templates * recursive-include openslides/agenda/static * -recursive-include openslides/application/templates * -recursive-include openslides/application/static * +recursive-include openslides/motion/templates * recursive-include openslides/assignment/templates * recursive-include openslides/assignment/static * recursive-include openslides/config/templates * -recursive-include openslides/config/static * recursive-include openslides/participant/templates * recursive-include openslides/participant/static * +include openslides/participant/initial_data.json recursive-include openslides/poll/templates * -recursive-include openslides/poll/static * recursive-include openslides/projector/templates * recursive-include openslides/projector/static * diff --git a/initial_data.json b/openslides/participant/fixtures/groups_de.json similarity index 100% rename from initial_data.json rename to openslides/participant/fixtures/groups_de.json From fddf929ab5e7350407d1b245d452c0b203369a55 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sun, 25 Nov 2012 00:58:19 +0100 Subject: [PATCH 179/222] Load groups_de when creating the database --- MANIFEST.in | 2 +- openslides/main.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index 0977abf4e..affdfa149 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -17,7 +17,7 @@ recursive-include openslides/assignment/static * recursive-include openslides/config/templates * recursive-include openslides/participant/templates * recursive-include openslides/participant/static * -include openslides/participant/initial_data.json +include openslides/participant/fixtures/groups_de.json recursive-include openslides/poll/templates * recursive-include openslides/projector/templates * recursive-include openslides/projector/static * diff --git a/openslides/main.py b/openslides/main.py index 11f543ab9..f7818b7ab 100755 --- a/openslides/main.py +++ b/openslides/main.py @@ -252,6 +252,7 @@ def run_syncdb(): # now initialize the database argv = ["", "syncdb", "--noinput"] execute_from_command_line(argv) + execute_from_command_line(["", "loaddata", "groups_de"]) def set_system_url(url): From abd21dd345b27eccc24c811a9c1cdea5405a7543 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Mon, 26 Nov 2012 10:05:51 +0100 Subject: [PATCH 180/222] Added more tests for the agenda --- openslides/projector/projector.py | 2 ++ tests/agenda/__init__.py | 0 tests/agenda/models.py | 18 ++++++++++++++++++ tests/{test_agenda.py => agenda/tests.py} | 16 +++++++++++----- 4 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 tests/agenda/__init__.py create mode 100644 tests/agenda/models.py rename tests/{test_agenda.py => agenda/tests.py} (92%) diff --git a/openslides/projector/projector.py b/openslides/projector/projector.py index 885c4291d..6e3129f4b 100644 --- a/openslides/projector/projector.py +++ b/openslides/projector/projector.py @@ -49,6 +49,8 @@ class SlideMixin(object): """ Return True, if the the slide is the active slide. """ + if self.id is None: + return False from openslides.projector.api import get_active_slide return get_active_slide(only_sid=True) == self.sid diff --git a/tests/agenda/__init__.py b/tests/agenda/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/agenda/models.py b/tests/agenda/models.py new file mode 100644 index 000000000..f61694356 --- /dev/null +++ b/tests/agenda/models.py @@ -0,0 +1,18 @@ +from django.db import models + +from openslides.projector.projector import SlideMixin +from openslides.projector.api import register_slidemodel + + +class ReleatedItem(SlideMixin, models.Model): + prefix = 'releateditem' + + name = models.CharField(max_length='255') + + def get_agenda_title(self): + return self.name + + def get_agenda_title_supplement(self): + return 'test item' + +register_slidemodel(ReleatedItem) diff --git a/tests/test_agenda.py b/tests/agenda/tests.py similarity index 92% rename from tests/test_agenda.py rename to tests/agenda/tests.py index 14fcf78e2..05c582f66 100644 --- a/tests/test_agenda.py +++ b/tests/agenda/tests.py @@ -19,6 +19,8 @@ from openslides.participant.models import User from openslides.agenda.models import Item from openslides.agenda.slides import agenda_show +from .models import ReleatedItem + class ItemTest(TestCase): def setUp(self): @@ -26,6 +28,8 @@ class ItemTest(TestCase): self.item2 = Item.objects.create(title='item2') self.item3 = Item.objects.create(title='item1A', parent=self.item1) self.item4 = Item.objects.create(title='item1Aa', parent=self.item3) + self.releated = ReleatedItem.objects.create(name='foo') + self.item5 = Item.objects.create(title='item5', related_sid=self.releated.sid) def testClosed(self): self.assertFalse(self.item1.closed) @@ -47,11 +51,6 @@ class ItemTest(TestCase): self.assertTrue(self.item3 in self.item1.get_children()) self.assertFalse(self.item4 in self.item1.get_children()) - l = Item.objects.all() - self.assertEqual( - str(l), - "[, , , ]") - def testForms(self): for item in Item.objects.all(): initial = item.weight_form.initial @@ -89,6 +88,13 @@ class ItemTest(TestCase): self.assertEqual(data['template'], 'projector/AgendaSummary.html') self.assertEqual(data['title'], 'Agenda') + def test_releated_item(self): + self.assertEqual(self.item5.get_title(), self.releated.name) + self.assertEqual(self.item5.get_title_supplement(), 'test item') + self.assertEqual(self.item5.get_related_type(), 'releateditem') + self.assertEqual(self.item5.print_related_type(), 'Releateditem') + + class ViewTest(TestCase): def setUp(self): From c276bce7802bf17f73c8c3e4d71de7ec18d0c6be Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Mon, 26 Nov 2012 10:11:36 +0100 Subject: [PATCH 181/222] Let travis test pep8 --- .travis.yml | 6 ++++-- openslides/participant/models.py | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b65d5b1dd..c2ab9f6c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,8 @@ python: - "2.7" install: - pip install -r requirements.txt --use-mirrors - - pip install coverage django-discover-runner + - pip install coverage django-discover-runner pep8 - python extras/scripts/create_local_settings.py -script: coverage run ./manage.py test tests && coverage report -m +script: + - coverage run ./manage.py test tests && coverage report -m + - pep8 --max-line-length=150 openslides | grep -v utils/pdf.py | grep -v urls.py | grep -v motion/ diff --git a/openslides/participant/models.py b/openslides/participant/models.py index 0adb6219d..bd771945d 100644 --- a/openslides/participant/models.py +++ b/openslides/participant/models.py @@ -138,7 +138,9 @@ class Group(DjangoGroup, PersonMixin, Person, SlideMixin): person_prefix = 'group' 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.')) + 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")) @models.permalink From a0e4519b6248a48dc0b0dcb804b1f32364bd5721 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Mon, 26 Nov 2012 10:19:45 +0100 Subject: [PATCH 182/222] fixed travis pep8 line --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c2ab9f6c1..ba93efe7c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,4 +9,4 @@ install: - python extras/scripts/create_local_settings.py script: - coverage run ./manage.py test tests && coverage report -m - - pep8 --max-line-length=150 openslides | grep -v utils/pdf.py | grep -v urls.py | grep -v motion/ + - pep8 --max-line-length=150 --exclude="urls.py,motion/,pdf.py" --statistics openslides From bdfb7140139bed2e57984af0d7e3ddf8f022bd1e Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Mon, 26 Nov 2012 10:35:29 +0100 Subject: [PATCH 183/222] fixed pep8 in pdf.py --- .travis.yml | 2 +- openslides/utils/pdf.py | 144 ++++++++++++++++++++-------------------- 2 files changed, 73 insertions(+), 73 deletions(-) diff --git a/.travis.yml b/.travis.yml index ba93efe7c..bad214ce7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,4 +9,4 @@ install: - python extras/scripts/create_local_settings.py script: - coverage run ./manage.py test tests && coverage report -m - - pep8 --max-line-length=150 --exclude="urls.py,motion/,pdf.py" --statistics openslides + - pep8 --max-line-length=150 --exclude="urls.py,motion/" --statistics openslides diff --git a/openslides/utils/pdf.py b/openslides/utils/pdf.py index 439d55744..4064f109e 100755 --- a/openslides/utils/pdf.py +++ b/openslides/utils/pdf.py @@ -116,93 +116,93 @@ stylesheet.add(ParagraphStyle( name='Tablecell', parent=stylesheet['Normal'], fontSize=9)) -stylesheet.add(ParagraphStyle(name = 'Signaturefield', - parent = stylesheet['Normal'], - spaceBefore = 15) +stylesheet.add(ParagraphStyle(name='Signaturefield', + parent=stylesheet['Normal'], + spaceBefore=15) ) # Ballot stylesheets -stylesheet.add(ParagraphStyle(name = 'Ballot_title', - parent = stylesheet['Bold'], - fontSize = 12, - leading = 14, - leftIndent = 30), +stylesheet.add(ParagraphStyle(name='Ballot_title', + parent=stylesheet['Bold'], + fontSize=12, + leading=14, + leftIndent=30), ) -stylesheet.add(ParagraphStyle(name = 'Ballot_subtitle', - parent = stylesheet['Normal'], - fontSize = 10, - leading = 12, - leftIndent = 30, - rightIndent = 20, - spaceAfter = 5), +stylesheet.add(ParagraphStyle(name='Ballot_subtitle', + parent=stylesheet['Normal'], + fontSize=10, + leading=12, + leftIndent=30, + rightIndent=20, + spaceAfter=5), ) -stylesheet.add(ParagraphStyle(name = 'Ballot_description', - parent = stylesheet['Normal'], - fontSize = 7, - leading = 10, - leftIndent = 30), +stylesheet.add(ParagraphStyle(name='Ballot_description', + parent=stylesheet['Normal'], + fontSize=7, + leading=10, + leftIndent=30), ) -stylesheet.add(ParagraphStyle(name = 'Ballot_option', - parent = stylesheet['Normal'], - fontSize = 12, - leading = 24, - leftIndent = 30), +stylesheet.add(ParagraphStyle(name='Ballot_option', + parent=stylesheet['Normal'], + fontSize=12, + leading=24, + leftIndent=30), ) -stylesheet.add(ParagraphStyle(name = 'Monotype', - parent = stylesheet['Normal'], - fontName = 'Courier', - fontSize = 12, - leading = 24, - leftIndent = 30), +stylesheet.add(ParagraphStyle(name='Monotype', + parent=stylesheet['Normal'], + fontName='Courier', + fontSize=12, + leading=24, + leftIndent=30), ) -stylesheet.add(ParagraphStyle(name = 'Ballot_option_name', - parent = stylesheet['Normal'], - fontSize = 12, - leading = 15, - leftIndent = 30), +stylesheet.add(ParagraphStyle(name='Ballot_option_name', + parent=stylesheet['Normal'], + fontSize=12, + leading=15, + leftIndent=30), ) -stylesheet.add(ParagraphStyle(name = 'Ballot_option_group', - parent = stylesheet['Normal'], - fontSize = 8, - leading = 15, - leftIndent = 30), +stylesheet.add(ParagraphStyle(name='Ballot_option_group', + parent=stylesheet['Normal'], + fontSize=8, + leading=15, + leftIndent=30), ) -stylesheet.add(ParagraphStyle(name = 'Ballot_option_YNA', - parent = stylesheet['Normal'], - fontSize = 12, - leading = 15, - leftIndent = 49, - spaceAfter = 18), +stylesheet.add(ParagraphStyle(name='Ballot_option_YNA', + parent=stylesheet['Normal'], + fontSize=12, + leading=15, + leftIndent=49, + spaceAfter=18), ) -stylesheet.add(ParagraphStyle(name = 'Ballot_option_group_right', - parent = stylesheet['Normal'], - fontSize = 8, - leading = 16, - leftIndent = 49), +stylesheet.add(ParagraphStyle(name='Ballot_option_group_right', + parent=stylesheet['Normal'], + fontSize=8, + leading=16, + leftIndent=49), ) -stylesheet.add(ParagraphStyle(name = 'Badge_title', - parent = stylesheet['Bold'], - fontSize = 16, - leading = 22, - leftIndent = 30), +stylesheet.add(ParagraphStyle(name='Badge_title', + parent=stylesheet['Bold'], + fontSize=16, + leading=22, + leftIndent=30), ) -stylesheet.add(ParagraphStyle(name = 'Badge_subtitle', - parent = stylesheet['Normal'], - fontSize = 12, - leading = 24, - leftIndent = 30), +stylesheet.add(ParagraphStyle(name='Badge_subtitle', + parent=stylesheet['Normal'], + fontSize=12, + leading=24, + leftIndent=30), ) stylesheet.add(ParagraphStyle( - name = 'Badge_italic', - parent = stylesheet['Italic'], - fontSize = 12, - leading = 24, - leftIndent = 30, + name='Badge_italic', + parent=stylesheet['Italic'], + fontSize=12, + leading=24, + leftIndent=30, )) stylesheet.add(ParagraphStyle( - name = 'Badge_qrcode', - fontSize = 12, - leftIndent = 190, + name='Badge_qrcode', + fontSize=12, + leftIndent=190, )) @@ -213,13 +213,13 @@ def firstPage(canvas, doc): canvas.setFillGray(0.4) title_line = u"%s | %s" % (config["event_name"], - config["event_description"]) + config["event_description"]) if len(title_line) > 75: title_line = "%s ..." % title_line[:70] canvas.drawString(2.75 * cm, 28 * cm, title_line) if config["event_date"] and config["event_location"]: canvas.drawString(2.75 * cm, 27.6 * cm, u"%s, %s" - % (config["event_date"], config["event_location"])) + % (config["event_date"], config["event_location"])) # time canvas.setFont('Ubuntu', 7) From 4dfd4ac67f81ba9d92299e0561afbb579be067a5 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Mon, 26 Nov 2012 15:48:23 +0100 Subject: [PATCH 184/222] fix _proper_unicode --- openslides/utils/utils.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openslides/utils/utils.py b/openslides/utils/utils.py index d8f054eb0..4c787687a 100644 --- a/openslides/utils/utils.py +++ b/openslides/utils/utils.py @@ -142,12 +142,10 @@ def ajax_request(data): def _propper_unicode(text): - res = '' if not isinstance(text, unicode): - res = u"%s" % text.decode('UTF-8') + return u"%s" % text.decode('UTF-8') else: - res = text - return res + return text def decodedict(dict): From 16847011535c1396531f4d09fd6fa067b58e7760 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 27 Nov 2012 20:09:16 +0100 Subject: [PATCH 185/222] Added Moira Bruelisauer (Thanks for contribute French translation) --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 72ee9b2ef..4dcba64e3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -5,3 +5,4 @@ Authors of OpenSlides in chronological order of first contribution: Norman Jäckel René Köcher Andy Kittner + Moira Brülisauer (French translation) \ No newline at end of file From 01e013cca612349e47b557df76043199ef754893 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 27 Nov 2012 20:09:30 +0100 Subject: [PATCH 186/222] Updated Changlog for 1.3 release. --- CHANGELOG | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index bb83ba535..37c507c76 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,80 @@ CHANGELOG of OpenSlides http://openslides.org +Version 1.3 (unreleased) +======================== +[http://dev.openslides.org/milestone/1.3] + +Projector: +- New public dashboard which allows access for all users per default. (#361) + (changed from the old, limited projector control page) +- New dashboard widgets: + * welcome widget (shows static welcome title and text) + * participant widget + * group widget + * personal widget (shows my motions and my elections) +- Hide scrollbar in projector view. +- Added cache for AJAX version of the projector view. +- Moved projector control icons into projector live widget. (#403) +- New weight field for custom slides (to order custom slides in widget). +- Fixed drag'n'drop behaviour of widgets into empty dashboard column. +- Fixed permissions for agenda, motion and assignment widgets (set to projector.can_manage_projector). +Agenda: +- Fixed slide error if agenda item deleted. (#330) +Motions: +- Translation: Changed 'application' to 'motion'. +- Fixed: Manager could not edit supporters. (#336) +- Fixed attribute error for anonymous users in motion view. (#329) +- Set default sorting of motions by number (in widget). +- CSV import allows to import group as submitter. (#419) +- Updated motion code for new user API. +- Rewrote motion views as class based views. +Elections: +- User can block himself/herself from candidate list after delete his/her candidature. +- Show blocked candidates in separate list. +- Mark elected candidates in candidate list. (#374) +- Show linebreaks in description. (#392) +- Set default sorting of elections by name (in widget). +- Fixed redirect from a poll which does not exists anymore. +- Changed default permissions of anonymous user to see elections. (#334) +- Updated assignment code for new user API. +Participants: +- New user and group API. +- New group option to handle a group as participant (and thus e.g. as submitter of motion). +- CSV import does not delete existing users anymore and append users as new users. +- New user field 'about me'. (#390) +- New config option for sorting users by first or last name (in participant lists, elections and motions). (#303) +- Allowed whitespaces in username, default: . (#326) +- New user and group slides. (#176) +- Don't allow to deactivate the administrator or themself. +- Don't allow to delete themself. +- Renamed participant field 'groups' to 'structure level' (German: Gliederungsebene). +- Rewrote participant views as class based views. +- Made OpenSlides user a child model of Django user model. +- Appended tests. +- Fixed error to allow admins to delete anonymous group + +Other: +- Added French translation (Thanks to Moira). +- Updated setup.py to make an openslides python package. +- Removed frontpage (welcome widget contains it's content) and redirect '/' to dashboard url. + +- Added LOCALE_PATHS to openslides_settings to avoid deprication in Django 1.5. +- Redesigned the DeleteView (append QuestionMixin to send question via the django message API). +- Fixed encoding error in settings.py. (#349) +- Renamed openslides_settings.py to openslides_global_settings.py. +- New default path to database file (XDG_DATA_HOME, e.g. ~/.local/share/openslides/). +- New default path to settings file (XDG_CONFIG_HOME, e.g. ~/.config/openslides/). +- Added special handling to determine location of database and settings file in portable version. +- Don't use similar characters in generated passwords (no 'Il10oO'). +- Localised the datetime in PDF header. (#296) +- Used specific session cookie name. (#332) +- Moved code repository from hg to git (incl. some required updates, e.g. version string function). +- Updated German translations. +- Several code optimizations. +- Several minor and medium issues and errors were fixed. + + Version 1.2 (2012-07-25) ======================== [http://dev.openslides.org/milestone/1.2] From 301a379fa6782c3b514ef58e329931c453afd871 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 27 Nov 2012 20:13:18 +0100 Subject: [PATCH 187/222] Prepared 1.3-rc1 release. --- README.txt | 2 +- openslides/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.txt b/README.txt index e6449d35b..6a3f12f91 100644 --- a/README.txt +++ b/README.txt @@ -2,7 +2,7 @@ English README file for OpenSlides ================================== -This is OpenSlides, version 1.3-beta2 (2012-11-09). +This is OpenSlides, version 1.3-rc1 (2012-11-27). What is OpenSlides? diff --git a/openslides/__init__.py b/openslides/__init__.py index 93ec6dc61..35e4ea998 100644 --- a/openslides/__init__.py +++ b/openslides/__init__.py @@ -5,7 +5,7 @@ :license: GNU GPL, see LICENSE for more details. """ -VERSION = (1, 3, 0, 'beta', 2) +VERSION = (1, 3, 0, 'rc', 1) def get_version(version=None): From 01cf09f017454e8b57386c3e909ba730d15258c6 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 27 Nov 2012 21:22:36 +0100 Subject: [PATCH 188/222] Added Alexis Roussel to AUTHORS (Thanks for French translation correction) --- AUTHORS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 4dcba64e3..41bd3f5df 100644 --- a/AUTHORS +++ b/AUTHORS @@ -5,4 +5,5 @@ Authors of OpenSlides in chronological order of first contribution: Norman Jäckel René Köcher Andy Kittner - Moira Brülisauer (French translation) \ No newline at end of file + Moira Brülisauer (French translation) + Alexis Roussel (French translation) \ No newline at end of file From 94928c20c5bbf6375a221f26c346e3c1783585b7 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 27 Nov 2012 21:22:57 +0100 Subject: [PATCH 189/222] Updated translation msg strings. --- openslides/motion/templates/motion/import.html | 5 ++++- openslides/participant/templates/participant/import.html | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/openslides/motion/templates/motion/import.html b/openslides/motion/templates/motion/import.html index aa36852a7..1c4607693 100644 --- a/openslides/motion/templates/motion/import.html +++ b/openslides/motion/templates/motion/import.html @@ -8,7 +8,10 @@

{% trans "Import motions" %}

{% trans 'Select a CSV file to import motions!' %}

-

{% trans 'Required comma separated values: {number, title, text, reason, first_name, last_name, is_group} (number, reason and is_group are optional and may be empty)' %} +

{% trans 'Required comma separated values' %}: + ({% trans 'number, title, text, reason, first_name, last_name, is_group' %}) +
+ {% trans 'number, reason and is_group are optional and may be empty' %}.
{% trans 'Required CSV file encoding: UTF-8 (Unicode).' %}

diff --git a/openslides/participant/templates/participant/import.html b/openslides/participant/templates/participant/import.html index d01a76e39..4b1777332 100644 --- a/openslides/participant/templates/participant/import.html +++ b/openslides/participant/templates/participant/import.html @@ -8,7 +8,8 @@

{% trans 'Import participants' %}

{% trans 'Select a CSV file to import participants!' %}

-

{% trans 'Required comma separated values: {first_name, last_name, gender, group, type, committee, comment}' %} +

{% trans 'Required comma separated values' %}: + ({% trans 'first_name, last_name, gender, structure level, type, committee, comment' %})
{% trans 'Required CSV file encoding: UTF-8 (Unicode).' %}

From ae35a8c71924fded494064f55c66666b006e1b50 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 27 Nov 2012 21:30:45 +0100 Subject: [PATCH 190/222] Updated translations --- openslides/locale/de/LC_MESSAGES/django.mo | Bin 36496 -> 36177 bytes openslides/locale/de/LC_MESSAGES/django.po | 678 ++++++++-------- openslides/locale/fr/LC_MESSAGES/django.mo | Bin 34607 -> 32703 bytes openslides/locale/fr/LC_MESSAGES/django.po | 897 +++++++++++---------- 4 files changed, 820 insertions(+), 755 deletions(-) diff --git a/openslides/locale/de/LC_MESSAGES/django.mo b/openslides/locale/de/LC_MESSAGES/django.mo index e3d56e4649978a8d843400bddef4646ac535b5e5..2662a31e284ddc27d6e4a50d3fcd750db308dbcd 100644 GIT binary patch delta 10651 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 delta 10907 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 F{Vy-(argiL diff --git a/openslides/locale/de/LC_MESSAGES/django.po b/openslides/locale/de/LC_MESSAGES/django.po index cebb45241..50db5277a 100644 --- a/openslides/locale/de/LC_MESSAGES/django.po +++ b/openslides/locale/de/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: OpenSlides 1.x\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-11-22 10:22+0100\n" +"POT-Creation-Date: 2012-11-27 21:23+0100\n" "PO-Revision-Date: 2012-07-28 11:07+0200\n" "Last-Translator: Emanuel Schuetze \n" "Language-Team: support@openslides.de\n" @@ -17,15 +17,15 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: global_settings.py:36 +#: global_settings.py:33 msgid "German" msgstr "Deutsch" -#: global_settings.py:37 +#: global_settings.py:34 msgid "English" msgstr "Englisch" -#: global_settings.py:38 +#: global_settings.py:35 msgid "French" msgstr "Französisch" @@ -33,43 +33,43 @@ msgstr "Französisch" msgid "Parent item" msgstr "Elternelement" -#: agenda/models.py:42 config/forms.py:61 motion/forms.py:22 -#: motion/models.py:545 motion/templates/motion/view.html:246 -#: projector/models.py:32 +#: agenda/models.py:34 config/forms.py:59 motion/forms.py:22 +#: motion/models.py:539 motion/templates/motion/view.html:246 +#: projector/models.py:29 msgid "Title" msgstr "Titel" -#: agenda/models.py:43 motion/forms.py:23 motion/models.py:546 -#: motion/templates/motion/view.html:247 projector/models.py:33 +#: agenda/models.py:35 motion/forms.py:23 motion/models.py:540 +#: motion/templates/motion/view.html:247 projector/models.py:30 msgid "Text" msgstr "Text" -#: agenda/models.py:44 agenda/templates/agenda/overview.html:65 -#: agenda/templates/agenda/view.html:13 participant/models.py:59 +#: agenda/models.py:36 agenda/templates/agenda/overview.html:65 +#: agenda/templates/agenda/view.html:13 participant/models.py:60 #: participant/templates/participant/overview.html:72 #: participant/templates/participant/user_detail.html:45 msgid "Comment" msgstr "Kommentar" -#: agenda/models.py:45 +#: agenda/models.py:37 msgid "Closed" msgstr "Abgeschlossen" -#: agenda/models.py:46 agenda/templates/agenda/overview.html:71 -#: projector/models.py:34 +#: agenda/models.py:38 agenda/templates/agenda/overview.html:71 +#: projector/models.py:31 msgid "Weight" msgstr "Gewichtung" -#: agenda/models.py:180 +#: agenda/models.py:171 msgid "Can see agenda" msgstr "Darf die Tagesordnung sehen" -#: agenda/models.py:181 +#: agenda/models.py:172 msgid "Can manage agenda" msgstr "Darf die Tagesordung verwalten" -#: agenda/models.py:189 agenda/slides.py:20 agenda/views.py:194 -#: agenda/views.py:195 agenda/views.py:214 agenda/views.py:229 +#: agenda/models.py:180 agenda/slides.py:20 agenda/views.py:191 +#: agenda/views.py:192 agenda/views.py:212 agenda/views.py:226 #: agenda/templates/agenda/base_agenda.html:10 #: agenda/templates/agenda/overview.html:8 #: agenda/templates/agenda/overview.html:52 @@ -79,34 +79,34 @@ msgstr "Darf die Tagesordung verwalten" msgid "Agenda" msgstr "Tagesordnung" -#: agenda/views.py:57 +#: agenda/views.py:54 msgid "You are not authorized to manage the agenda." msgstr "Sie sind nicht berechtigt die Tagesordnung zu ändern." -#: agenda/views.py:73 +#: agenda/views.py:70 msgid "Errors when reordering of the agenda" msgstr "Fehler beim Neusortieren der Tagesordnung" -#: agenda/views.py:134 +#: agenda/views.py:131 #, python-format msgid "Item %s was successfully modified." msgstr "Eintrag %s wurde erfolgreich bearbeitet." -#: agenda/views.py:155 +#: agenda/views.py:152 #, python-format msgid "Item %s was successfully created." msgstr "Eintrag %s wurde erfolgreich angelegt." -#: agenda/views.py:172 +#: agenda/views.py:169 msgid "Yes, with all child items." msgstr "Ja, mit allen Kindelementen." -#: agenda/views.py:180 +#: agenda/views.py:177 #, python-format msgid "Item %s and his children were successfully deleted." msgstr "Eintrag %s und seine Kindelemente wurde erfolgreich gelöscht." -#: agenda/views.py:185 +#: agenda/views.py:182 #, python-format msgid "Item %s was successfully deleted." msgstr "Eintrag %s wurde erfolgreich gelöscht." @@ -170,12 +170,12 @@ msgstr "Speichern" #: assignment/templates/assignment/poll_view.html:73 #: config/templates/config/general.html:60 #: motion/templates/motion/config.html:17 motion/templates/motion/edit.html:33 -#: motion/templates/motion/import.html:27 +#: motion/templates/motion/import.html:30 #: motion/templates/motion/poll_view.html:59 #: participant/templates/participant/config.html:17 #: participant/templates/participant/edit.html:38 #: participant/templates/participant/group_edit.html:32 -#: participant/templates/participant/import.html:27 +#: participant/templates/participant/import.html:28 #: participant/templates/participant/password_change.html:26 #: participant/templates/participant/settings.html:26 #: projector/templates/projector/new.html:20 @@ -197,10 +197,10 @@ msgstr "Übernehmen" #: agenda/templates/agenda/edit.html:35 #: assignment/templates/assignment/edit.html:37 -#: motion/templates/motion/edit.html:37 motion/templates/motion/import.html:31 +#: motion/templates/motion/edit.html:37 motion/templates/motion/import.html:34 #: participant/templates/participant/edit.html:42 #: participant/templates/participant/group_edit.html:36 -#: participant/templates/participant/import.html:31 +#: participant/templates/participant/import.html:32 msgid "required" msgstr "erforderlich" @@ -226,25 +226,25 @@ msgstr "Zusammenfassung für diesen Eintrag projizieren" msgid "Do you want to save the changed order of agenda items?" msgstr "Möchten Sie die geänderte Reihenfolge der Einträge speichern?" -#: agenda/templates/agenda/overview.html:46 assignment/models.py:301 -#: assignment/views.py:579 assignment/templates/assignment/view.html:168 +#: agenda/templates/agenda/overview.html:46 assignment/models.py:294 +#: assignment/views.py:587 assignment/templates/assignment/view.html:168 #: assignment/templates/assignment/view.html:172 #: assignment/templates/projector/Assignment.html:78 -#: assignment/templates/projector/Assignment.html:82 motion/models.py:579 -#: motion/views.py:842 motion/views.py:893 +#: assignment/templates/projector/Assignment.html:82 motion/models.py:574 +#: motion/views.py:830 motion/views.py:881 #: motion/templates/motion/view.html:79 -#: motion/templates/projector/Motion.html:37 utils/utils.py:53 -#: utils/views.py:111 +#: motion/templates/projector/Motion.html:37 utils/utils.py:55 +#: utils/views.py:108 msgid "Yes" msgstr "Ja" -#: agenda/templates/agenda/overview.html:47 assignment/models.py:301 -#: assignment/views.py:580 assignment/templates/assignment/view.html:169 -#: assignment/templates/projector/Assignment.html:79 motion/models.py:579 -#: motion/views.py:842 motion/views.py:894 +#: agenda/templates/agenda/overview.html:47 assignment/models.py:294 +#: assignment/views.py:588 assignment/templates/assignment/view.html:169 +#: assignment/templates/projector/Assignment.html:79 motion/models.py:574 +#: motion/views.py:830 motion/views.py:882 #: motion/templates/motion/view.html:80 -#: motion/templates/projector/Motion.html:38 utils/utils.py:53 -#: utils/views.py:111 +#: motion/templates/projector/Motion.html:38 utils/utils.py:55 +#: utils/views.py:108 msgid "No" msgstr "Nein" @@ -318,7 +318,7 @@ msgstr "Löschen" msgid "Edit" msgstr "Bearbeiten" -#: assignment/forms.py:24 assignment/models.py:57 assignment/views.py:385 +#: assignment/forms.py:24 assignment/models.py:51 assignment/views.py:381 #: assignment/templates/assignment/view.html:13 #: assignment/templates/projector/Assignment.html:21 msgid "Number of available posts" @@ -333,177 +333,177 @@ msgid "Only publish voting results for selected winners (Projector view only)" msgstr "" "Wahlergebnisse der nicht gewählten Kandidaten auf dem Projektor verbergen" -#: assignment/forms.py:47 motion/forms.py:77 +#: assignment/forms.py:46 motion/forms.py:77 msgid "Number of ballot papers (selection)" msgstr "Anzahl der Stimmzettel (Vorauswahl)" -#: assignment/forms.py:49 motion/forms.py:79 +#: assignment/forms.py:48 motion/forms.py:79 msgid "Number of all delegates" msgstr "Anzahl aller Delegierten" -#: assignment/forms.py:50 motion/forms.py:80 +#: assignment/forms.py:49 motion/forms.py:80 msgid "Number of all participants" msgstr "Anzahl aller Teilnehmer/innen" -#: assignment/forms.py:51 motion/forms.py:81 +#: assignment/forms.py:50 motion/forms.py:81 msgid "Use the following custom number" msgstr "Verwende die folgende benutzerdefinierte Anzahl" -#: assignment/forms.py:58 motion/forms.py:88 +#: assignment/forms.py:55 motion/forms.py:88 msgid "Custom number of ballot papers" msgstr "Benutzerdefinierte Anzahl von Stimmzetteln" -#: assignment/forms.py:63 +#: assignment/forms.py:59 msgid "Title for PDF document (all elections)" msgstr "Titel für PDF-Dokument (alle Wahlen)" -#: assignment/forms.py:68 +#: assignment/forms.py:63 msgid "Preamble text for PDF document (all elections)" msgstr "Einleitungstext für PDF-Dokument (alle Wahlen) " -#: assignment/forms.py:72 +#: assignment/forms.py:67 msgid "Election method" msgstr "Wahlmethode" -#: assignment/forms.py:74 +#: assignment/forms.py:69 msgid "Automatic assign of method." msgstr "Automatische Zuordnung der Methode." -#: assignment/forms.py:75 +#: assignment/forms.py:70 msgid "Always one option per candidate." msgstr "Eine Stimme pro Kandidat/in." -#: assignment/forms.py:76 +#: assignment/forms.py:71 msgid "Always Yes-No-Abstain per candidate." msgstr "Ja, Nein, Enthaltung pro Kandidat/in." -#: assignment/models.py:48 assignment/templates/assignment/overview.html:15 +#: assignment/models.py:44 assignment/templates/assignment/overview.html:15 #: assignment/templates/assignment/view.html:23 msgid "Searching for candidates" msgstr "Auf Kandidatensuche" -#: assignment/models.py:49 assignment/templates/assignment/overview.html:16 +#: assignment/models.py:45 assignment/templates/assignment/overview.html:16 #: assignment/templates/assignment/view.html:25 msgid "Voting" msgstr "Im Wahlvorgang" -#: assignment/models.py:50 assignment/templates/assignment/overview.html:17 +#: assignment/models.py:46 assignment/templates/assignment/overview.html:17 #: assignment/templates/assignment/view.html:27 msgid "Finished" msgstr "Abgeschlossen" -#: assignment/models.py:53 +#: assignment/models.py:49 msgid "Name" msgstr "Name" -#: assignment/models.py:55 participant/models.py:134 +#: assignment/models.py:50 participant/models.py:144 msgid "Description" msgstr "Beschreibung" -#: assignment/models.py:59 +#: assignment/models.py:54 msgid "Comment on the ballot paper" msgstr "Kommentar für den Stimmzettel" -#: assignment/models.py:69 motion/models.py:337 +#: assignment/models.py:64 motion/models.py:332 #, python-format msgid "%s is not a valid status." msgstr "%s ist kein gültiger Status." -#: assignment/models.py:71 +#: assignment/models.py:67 #, python-format msgid "The assignment status is already %s." msgstr "Der Wahlstatus ist bereits %s." -#: assignment/models.py:85 +#: assignment/models.py:80 #, python-format msgid "%s is already a candidate." msgstr "%s ist bereits ein/e Kandidat/in." -#: assignment/models.py:87 assignment/views.py:202 +#: assignment/models.py:82 assignment/views.py:195 msgid "The candidate list is already closed." msgstr "Die Kandidatenliste ist bereits geschlossen." -#: assignment/models.py:94 +#: assignment/models.py:89 #, python-format msgid "%s does not want to be a candidate." msgstr "%s möchte nicht kandidieren." -#: assignment/models.py:108 +#: assignment/models.py:103 #, python-format msgid "%s is no candidate" msgstr "%s ist kein/e Kandidat/in" -#: assignment/models.py:254 +#: assignment/models.py:247 msgid "Can see assignment" msgstr "Darf Wahlen sehen" -#: assignment/models.py:256 +#: assignment/models.py:249 msgid "Can nominate another person" msgstr "Darf andere Personen für Wahlen vorschlagen" -#: assignment/models.py:257 +#: assignment/models.py:250 msgid "Can nominate themselves" msgstr "Darf selbst für Wahlen kandidieren" -#: assignment/models.py:258 +#: assignment/models.py:251 msgid "Can manage assignment" msgstr "Darf Wahlen verwalten" -#: assignment/models.py:302 motion/models.py:580 +#: assignment/models.py:294 motion/models.py:574 msgid "Abstain" msgstr "Enthaltung" -#: assignment/models.py:304 motion/templates/motion/poll_view.html:22 +#: assignment/models.py:296 motion/templates/motion/poll_view.html:22 msgid "Votes" msgstr "Stimmen" -#: assignment/models.py:321 +#: assignment/models.py:313 #, python-format msgid "Ballot %d" msgstr "Wahlgang %d" -#: assignment/models.py:330 assignment/views.py:342 assignment/views.py:666 -#: assignment/views.py:680 +#: assignment/models.py:322 assignment/views.py:336 assignment/views.py:675 +#: assignment/views.py:690 #: assignment/templates/assignment/base_assignment.html:14 #: assignment/templates/assignment/overview.html:6 #: assignment/templates/assignment/overview.html:9 msgid "Elections" msgstr "Wahlen" -#: assignment/views.py:88 +#: assignment/views.py:80 #, python-format msgid "Candidate %s was nominated successfully." msgstr "Kandidat/in %s wurde erfolgreich vorgeschlagen." -#: assignment/views.py:130 +#: assignment/views.py:122 msgid "New election was successfully created." msgstr "Neue Wahl wurde erfolgreich angelegt." -#: assignment/views.py:132 +#: assignment/views.py:124 msgid "Election was successfully modified." msgstr "Wahl wurde erfolgreich geändert." -#: assignment/views.py:138 motion/views.py:257 motion/views.py:701 -#: participant/views.py:506 participant/views.py:529 utils/views.py:225 -#: utils/views.py:243 utils/views.py:267 +#: assignment/views.py:130 motion/views.py:245 motion/views.py:689 +#: participant/views.py:508 participant/views.py:531 utils/views.py:222 +#: utils/views.py:240 utils/views.py:264 msgid "Please check the form for errors." msgstr "Bitte kontrollieren Sie das Formular nach Fehlern." -#: assignment/views.py:157 +#: assignment/views.py:149 #, python-format msgid "Election %s was successfully deleted." msgstr "Wahl %s wurde erfolgreich gelöscht." -#: assignment/views.py:170 +#: assignment/views.py:162 #, python-format msgid "Election status was set to: %s." msgstr "Wahlstatus wurde gesetzt auf: %s." -#: assignment/views.py:183 +#: assignment/views.py:175 msgid "You have set your candidature successfully." msgstr "Sie haben Ihre Kandidatur erfolgreich gesetzt." -#: assignment/views.py:199 +#: assignment/views.py:192 msgid "" "You have withdrawn your candidature successfully. You can not be nominated " "by other participants anymore." @@ -511,71 +511,71 @@ msgstr "" "Sie haben Ihre Kandidatur erfolgreich zurückgezogen. Sie können nun von " "anderen Teilnehmer/innen nicht mehr vorgeschlagen werden." -#: assignment/views.py:220 +#: assignment/views.py:213 #, python-format msgid "Candidate %s was withdrawn successfully." msgstr "Die Kandidatur von %s wurde erfolgreich zurückgezogen." -#: assignment/views.py:222 +#: assignment/views.py:215 #, python-format msgid "%s was unblocked successfully." msgstr "%s wurde erfolgreich freigegeben." -#: assignment/views.py:226 +#: assignment/views.py:219 #, python-format msgid "Do you really want to withdraw %s from the election?" msgstr "Soll %s wirklich von der Wahl zurückgezogen werden?" -#: assignment/views.py:228 +#: assignment/views.py:221 #, python-format msgid "Do you really want to unblock %s for the election?" msgstr "Soll %s wirklich für die Wahl freigegeben werden?" -#: assignment/views.py:243 +#: assignment/views.py:236 msgid "New ballot was successfully created." msgstr "Neuer Wahlgang erfolgreich angelegt." -#: assignment/views.py:275 +#: assignment/views.py:268 #, python-format msgid "Ballot ID %d does not exist." msgstr "Wahlgang-ID %d existiert nicht." -#: assignment/views.py:282 +#: assignment/views.py:275 msgid "Ballot successfully published." msgstr "Wahlgang wurde erfolgreich veröffentlicht." -#: assignment/views.py:284 +#: assignment/views.py:277 msgid "Ballot successfully unpublished." msgstr "Wahlgang wurde erfolgreich unveröffentlicht." -#: assignment/views.py:297 +#: assignment/views.py:290 msgid "not elected" msgstr "nicht gewählt" -#: assignment/views.py:300 assignment/views.py:483 +#: assignment/views.py:293 assignment/views.py:482 #: assignment/templates/assignment/view.html:48 msgid "elected" msgstr "gewählt" -#: assignment/views.py:328 +#: assignment/views.py:321 msgid "Ballot was successfully deleted." msgstr "Abstimmung wurde erfolgreich gelöscht." -#: assignment/views.py:339 +#: assignment/views.py:333 msgid "Assignment" msgstr "Wahl" -#: assignment/views.py:360 assignment/templates/assignment/overview.html:59 +#: assignment/views.py:356 assignment/templates/assignment/overview.html:59 #: assignment/templates/assignment/widget.html:23 msgid "No assignments available." msgstr "Keine Wahlen vorhanden." -#: assignment/views.py:379 +#: assignment/views.py:375 #, python-format msgid "Election: %s" msgstr "Wahlen: %s" -#: assignment/views.py:391 assignment/views.py:424 +#: assignment/views.py:388 assignment/views.py:424 #: assignment/templates/assignment/overview.html:26 #: assignment/templates/assignment/poll_view.html:18 #: assignment/templates/assignment/view.html:37 @@ -585,12 +585,12 @@ msgstr "Wahlen: %s" msgid "Candidates" msgstr "Kandidaten/innen" -#: assignment/views.py:412 motion/views.py:835 +#: assignment/views.py:413 motion/views.py:823 #: motion/templates/motion/view.html:44 msgid "Vote results" msgstr "Abstimmungsergebnis" -#: assignment/views.py:416 +#: assignment/views.py:417 #: assignment/templates/assignment/base_assignment.html:71 #: assignment/templates/assignment/poll_view.html:5 #: assignment/templates/assignment/poll_view.html:8 @@ -599,7 +599,7 @@ msgstr "Abstimmungsergebnis" msgid "ballot" msgstr "Wahlgang" -#: assignment/views.py:419 +#: assignment/views.py:420 msgid "ballots" msgstr "Wahlgänge" @@ -625,14 +625,14 @@ msgstr "Ungültige Stimmen" #: assignment/templates/assignment/view.html:202 #: assignment/templates/assignment/view.html:207 #: assignment/templates/projector/Assignment.html:109 -#: assignment/templates/projector/Assignment.html:115 motion/views.py:842 +#: assignment/templates/projector/Assignment.html:115 motion/views.py:830 #: motion/templates/motion/poll_view.html:35 #: motion/templates/motion/view.html:84 #: motion/templates/projector/Motion.html:42 poll/models.py:76 msgid "Votes cast" msgstr "Abgegebene Stimmen" -#: assignment/views.py:522 assignment/views.py:538 +#: assignment/views.py:523 assignment/views.py:541 #: assignment/templates/assignment/overview.html:25 #: assignment/templates/assignment/poll_view.html:5 #: assignment/templates/assignment/view.html:6 @@ -640,33 +640,33 @@ msgstr "Abgegebene Stimmen" msgid "Election" msgstr "Wahl" -#: assignment/views.py:544 +#: assignment/views.py:548 #, python-format msgid "%d. ballot" msgstr "%d. Wahlgang" -#: assignment/views.py:545 +#: assignment/views.py:550 #, python-format msgid "%d candidate" msgid_plural "%d candidates" msgstr[0] "%d Kandidat/in" msgstr[1] "%d Kandidaten/innen" -#: assignment/views.py:547 +#: assignment/views.py:552 #, python-format msgid "%d available post" msgid_plural "%d available posts" msgstr[0] "%d verfügbare Posten" msgstr[1] "%d verfügbare Posten" -#: assignment/views.py:580 assignment/templates/assignment/view.html:170 -#: assignment/templates/projector/Assignment.html:80 motion/views.py:842 -#: motion/views.py:895 motion/templates/motion/view.html:81 +#: assignment/views.py:588 assignment/templates/assignment/view.html:170 +#: assignment/templates/projector/Assignment.html:80 motion/views.py:830 +#: motion/views.py:883 motion/templates/motion/view.html:81 #: motion/templates/projector/Motion.html:39 msgid "Abstention" msgstr "Enthaltung" -#: assignment/views.py:659 +#: assignment/views.py:668 msgid "Election settings successfully saved." msgstr "Wahl-Einstellungen wurden erfolgreich gespeichert." @@ -722,7 +722,7 @@ msgstr "Wahl-Einstellungen" #: assignment/templates/assignment/overview.html:14 #: assignment/templates/assignment/overview.html:27 #: assignment/templates/assignment/view.html:11 -#: assignment/templates/projector/Assignment.html:18 motion/views.py:813 +#: assignment/templates/projector/Assignment.html:18 motion/views.py:801 #: motion/templates/motion/overview.html:20 #: motion/templates/motion/overview.html:40 #: motion/templates/motion/view.html:34 @@ -766,13 +766,13 @@ msgid "Special values" msgstr "Spezielle Werte" #: assignment/templates/assignment/poll_view.html:12 -#: motion/templates/motion/poll_view.html:14 poll/models.py:235 +#: motion/templates/motion/poll_view.html:14 poll/models.py:234 msgid "majority" msgstr "Mehrheit" #: assignment/templates/assignment/poll_view.html:12 -#: motion/templates/motion/poll_view.html:14 poll/models.py:237 -#: poll/models.py:239 +#: motion/templates/motion/poll_view.html:14 poll/models.py:236 +#: poll/models.py:238 msgid "undocumented" msgstr "nicht erfasst" @@ -844,7 +844,7 @@ msgid "was not a
candidate" msgstr "war kein Kandidat" #: assignment/templates/assignment/view.html:191 -#: assignment/templates/projector/Assignment.html:100 motion/views.py:842 +#: assignment/templates/projector/Assignment.html:100 motion/views.py:830 #: motion/templates/motion/view.html:82 #: motion/templates/projector/Motion.html:40 msgid "Invalid" @@ -854,31 +854,31 @@ msgstr "Ungültig" msgid "No results available." msgstr "Keine Ergebnisse vorhanden." -#: config/forms.py:24 +#: config/forms.py:22 msgid "Event name" msgstr "Veranstaltungsname" -#: config/forms.py:30 +#: config/forms.py:28 msgid "Short description of event" msgstr "Kurzbeschreibung der Veranstaltung" -#: config/forms.py:38 +#: config/forms.py:36 msgid "Event date" msgstr "Veranstaltungszeitraum" -#: config/forms.py:44 +#: config/forms.py:42 msgid "Event location" msgstr "Veranstaltungsort" -#: config/forms.py:50 +#: config/forms.py:48 msgid "Event organizer" msgstr "Veranstalter" -#: config/forms.py:55 +#: config/forms.py:53 msgid "Allow access for anonymous guest users" msgstr "Erlaube Zugriff für anonyme Gast-Nutzer" -#: config/forms.py:67 participant/forms.py:114 +#: config/forms.py:65 participant/forms.py:123 msgid "Welcome text" msgstr "Willkommenstext" @@ -886,42 +886,34 @@ msgstr "Willkommenstext" msgid "Can manage configuration" msgstr "Darf die Konfiguration verwalten" -#: config/models.py:84 +#: config/models.py:83 msgid "Presentation and assembly system" msgstr "Präsentations- und Versammlungssystem" -#: config/models.py:89 +#: config/models.py:88 msgid "Welcome to OpenSlides" msgstr "Willkommen bei OpenSlides" -#: config/models.py:90 +#: config/models.py:89 msgid "[Place for your welcome text.]" msgstr "[Platz für Ihren Begrüßungstext.]" -#: config/models.py:103 +#: config/models.py:102 msgid "General" msgstr "Allgemein" -#: config/models.py:127 config/templates/config/version.html:5 +#: config/models.py:126 config/templates/config/version.html:5 #: config/templates/config/version.html:8 -#: config/templates/config/version.html:11 motion/views.py:827 +#: config/templates/config/version.html:11 motion/views.py:815 #: motion/templates/motion/view.html:214 motion/templates/motion/view.html:244 msgid "Version" msgstr "Version" -#: config/views.py:78 -msgid "" -"Anonymous access enabled. Please modify the \"Anonymous\" group to fit your " -"required permissions." -msgstr "" -"Anonymer Zugriff aktiviert. Bitte setzen Sie die Rechte der Gruppe " -"\"Anonymous\" passend zum gewünschten Zugriffslevel." - -#: config/views.py:84 +#: config/views.py:69 msgid "General settings successfully saved." msgstr "Allgemeine Einstellungen erfolgreich gespeichert." -#: config/views.py:119 config/templates/config/base_config.html:7 +#: config/views.py:104 config/templates/config/base_config.html:7 msgid "Configuration" msgstr "Konfiguration" @@ -942,7 +934,7 @@ msgstr "Willkommens-Widget" msgid "System" msgstr "System" -#: motion/forms.py:25 motion/models.py:547 motion/views.py:861 +#: motion/forms.py:25 motion/models.py:541 motion/views.py:849 #: motion/templates/motion/view.html:229 motion/templates/motion/view.html:249 #: motion/templates/projector/Motion.html:77 msgid "Reason" @@ -956,18 +948,18 @@ msgstr "Triviale Änderung" msgid "Trivial changes don't create a new version." msgstr "Triviale Änderungen erzeugen keine neue Version." -#: motion/forms.py:35 motion/models.py:68 motion/views.py:780 +#: motion/forms.py:35 motion/models.py:63 motion/views.py:768 #: motion/templates/motion/overview.html:41 #: motion/templates/motion/view.html:18 #: motion/templates/projector/Motion.html:55 msgid "Submitter" msgstr "Antragsteller/in" -#: motion/forms.py:44 motion/views.py:800 motion/templates/motion/view.html:22 +#: motion/forms.py:44 motion/views.py:788 motion/templates/motion/view.html:22 msgid "Supporters" msgstr "Unterstützer/innen" -#: motion/forms.py:50 participant/forms.py:102 +#: motion/forms.py:50 participant/forms.py:111 msgid "CSV File" msgstr "CSV-Datei" @@ -1008,74 +1000,74 @@ msgid "Warning: Trivial changes undermine the motions autorisation system." msgstr "" "Warnung: Triviale Änderungen unterlaufen das Zulassungssystem von Anträgen." -#: motion/models.py:47 +#: motion/models.py:42 msgid "Published" msgstr "Veröffentlicht" -#: motion/models.py:48 +#: motion/models.py:43 msgid "Permitted" msgstr "Zugelassen" -#: motion/models.py:49 motion/templates/motion/overview.html:24 +#: motion/models.py:44 motion/templates/motion/overview.html:24 #: motion/templates/motion/view.html:167 msgid "Accepted" msgstr "Angenommen" -#: motion/models.py:50 motion/templates/motion/overview.html:25 +#: motion/models.py:45 motion/templates/motion/overview.html:25 #: motion/templates/motion/view.html:172 msgid "Rejected" msgstr "Abgelehnt" -#: motion/models.py:51 +#: motion/models.py:46 msgid "Withdrawed" msgstr "Zurückgezogen" -#: motion/models.py:52 motion/templates/motion/view.html:180 +#: motion/models.py:47 motion/templates/motion/view.html:180 msgid "Adjourned" msgstr "Vertagt" # please check! -#: motion/models.py:53 motion/templates/motion/view.html:183 +#: motion/models.py:48 motion/templates/motion/view.html:183 msgid "Not Concerned" msgstr "Nicht befasst" # please check! -#: motion/models.py:54 motion/templates/motion/view.html:186 +#: motion/models.py:49 motion/templates/motion/view.html:186 msgid "Commited a bill" msgstr "Verwiesen (in Ausschuss)" -#: motion/models.py:55 +#: motion/models.py:50 msgid "Rejected (not authorized)" msgstr "Verworfen (nicht zulässig)" -#: motion/models.py:56 motion/templates/motion/overview.html:27 +#: motion/models.py:51 motion/templates/motion/overview.html:27 msgid "Needs Review" msgstr "Benötigt Review" -#: motion/models.py:105 +#: motion/models.py:100 #, python-format msgid "Version %d authorized" msgstr "Version %d zugelassen" -#: motion/models.py:112 +#: motion/models.py:107 #, python-format msgctxt "Rejected means not authorized" msgid "Version %d rejected" msgstr "Version %d verworfen" -#: motion/models.py:141 +#: motion/models.py:136 msgid "Searching for supporters." msgstr "Auf Unterstützersuche." -#: motion/models.py:143 +#: motion/models.py:138 msgid "Not yet authorized." msgstr "Noch nicht zugelassen." -#: motion/models.py:145 +#: motion/models.py:140 msgid "Not yet authorized changes." msgstr "Noch nicht zugelassene Änderungen." -#: motion/models.py:225 +#: motion/models.py:223 #, python-format msgid "" "Trivial changes to version %(version)d; changed fields: %(changed_fields)s" @@ -1083,51 +1075,51 @@ msgstr "" "Triviale Änderung an Version %(version)d; Geänderte Felder: " "%(changed_fields)s" -#: motion/models.py:236 +#: motion/models.py:235 #, python-format msgid "Version %s created" msgstr "Version %s erstellt" -#: motion/models.py:246 +#: motion/models.py:244 msgid "Supporters removed" msgstr "Unterstützer/innen gelöscht" -#: motion/models.py:255 +#: motion/models.py:253 #, python-format msgid "Status reseted to: %s" msgstr "Status zurückgesetzt auf: %s" -#: motion/models.py:267 +#: motion/models.py:265 #, python-format msgid "Supporter: +%s" msgstr "Unterstützer/in: +%s" -#: motion/models.py:280 +#: motion/models.py:278 #, python-format msgid "Supporter: -%s" msgstr "Unterstützer/in: -%s" -#: motion/models.py:297 +#: motion/models.py:294 #, python-format msgid "Number set: %s" msgstr "Nummer gesetzt: %s" -#: motion/models.py:310 +#: motion/models.py:307 #, python-format msgid "Version %s authorized" msgstr "Version %s zugelassen" -#: motion/models.py:324 +#: motion/models.py:319 #, python-format msgid "Version %s not authorized" msgstr "Version %s nicht zugelassen" -#: motion/models.py:340 +#: motion/models.py:335 #, python-format msgid "The motion status is already '%s.'" msgstr "Der Antragsstatus ist bereits '%s'." -#: motion/models.py:348 +#: motion/models.py:343 #, python-format msgid "" "The motion status is: '%(currentstatus)s'. You can not set the status to " @@ -1136,15 +1128,15 @@ msgstr "" "Der Antragsstatus ist: '%(currentstatus)s'. Sie können den Status nicht auf " "'%(newstatus)s' setzen." -#: motion/models.py:356 +#: motion/models.py:351 msgid "Status modified" msgstr "Status geändert" -#: motion/models.py:449 motion/models.py:451 +#: motion/models.py:443 motion/models.py:445 msgid "by" msgstr "von" -#: motion/models.py:459 motion/templates/motion/view.html:210 +#: motion/models.py:453 motion/templates/motion/view.html:210 #: motion/templates/motion/widget.html:27 #: motion/templates/projector/Motion.html:65 #: participant/templates/participant/personal_info_widget.html:13 @@ -1152,62 +1144,62 @@ msgstr "von" msgid "no number" msgstr "ohne Nummer" -#: motion/models.py:460 motion/templates/motion/widget.html:23 +#: motion/models.py:454 motion/templates/motion/widget.html:23 #: participant/templates/participant/personal_info_widget.html:9 #: participant/templates/participant/personal_info_widget.html:28 msgid "motion" msgstr "Antrag" -#: motion/models.py:485 +#: motion/models.py:479 msgid "Poll created" msgstr "Abstimmung erstellt" -#: motion/models.py:536 +#: motion/models.py:530 msgid "Can see motions" msgstr "Darf Anträge sehen" -#: motion/models.py:537 +#: motion/models.py:531 msgid "Can create motions" msgstr "Darf Anträge erstellen" -#: motion/models.py:538 +#: motion/models.py:532 msgid "Can support motions" msgstr "Darf Anträge unterstützen" -#: motion/models.py:539 +#: motion/models.py:533 msgid "Can manage motions" msgstr "Darf Anträge verwalten" -#: motion/models.py:606 +#: motion/models.py:600 msgid "The assembly may decide," msgstr "Die Versammlung möge beschließen," -#: motion/models.py:609 motion/views.py:730 motion/views.py:955 -#: motion/views.py:966 motion/templates/motion/base_motion.html:9 +#: motion/models.py:603 motion/views.py:718 motion/views.py:943 +#: motion/views.py:954 motion/templates/motion/base_motion.html:9 #: motion/templates/motion/overview.html:7 #: motion/templates/motion/overview.html:10 msgid "Motions" msgstr "Anträge" -#: motion/views.py:180 +#: motion/views.py:173 msgid "You have not the necessary rights to create or edit motions." msgstr "" "Sie haben nicht die nötigen Rechte, um Anträge zu erstellen oder zu " "bearbeiten." -#: motion/views.py:185 +#: motion/views.py:178 msgid "You can not edit this motion." msgstr "Sie dürfen diesen Antrag nicht bearbeiten." -#: motion/views.py:248 +#: motion/views.py:236 msgid "New motion was successfully created." msgstr "Neuer Antrag wurde erfolgreich angelegt." -#: motion/views.py:250 +#: motion/views.py:238 msgid "Motion was successfully modified." msgstr "Antrag wurde erfolgreich geändert." -#: motion/views.py:264 +#: motion/views.py:252 msgid "" "Attention: Do you really want to edit this motion? The supporters will " "not be removed automatically because you can manage motions. Please " @@ -1217,7 +1209,7 @@ msgstr "" "werden nicht automatisch entfernt, da Sie Anträge verwalten dürfen. " "Prüfen Sie, ob die Unterstützungen noch gültig sind." -#: motion/views.py:266 +#: motion/views.py:254 #, python-format msgid "" "Attention: Do you really want to edit this motion? All %s supporters " @@ -1226,128 +1218,128 @@ msgstr "" "Wollen Sie den Antrag wirklich ändern? Alle %s Unterstützer/innen " "werden dann automatisch entfernt. Versuchen Sie diese erneut zu gewinnen." -#: motion/views.py:298 +#: motion/views.py:286 msgid "Motion number was successfully set." msgstr "Antragsnummer wurde erfolgreich gesetzt." -#: motion/views.py:314 +#: motion/views.py:302 msgid "Motion was successfully authorized." msgstr "Antrag wurde erfolgreich zugelassen." -#: motion/views.py:329 +#: motion/views.py:317 msgid "Motion was successfully rejected." msgstr "Antrag wurde erfolgreich verworfen." -#: motion/views.py:345 +#: motion/views.py:333 #, python-format msgid "Motion status was set to: %s." msgstr "Antragsstatus wurde gesetzt auf: %s." -#: motion/views.py:361 +#: motion/views.py:349 msgid "Motion status was reset." msgstr "Antragsstatus wurde zurückgesetzt." -#: motion/views.py:388 +#: motion/views.py:376 msgid "You can not support this motion." msgstr "Sie dürfen diesen Antrag nicht unterstützen." -#: motion/views.py:391 +#: motion/views.py:379 msgid "You can not unsupport this motion." msgstr "Sie dürfen Ihre Unterstützung für diesen Antrag nicht entziehen." -#: motion/views.py:402 +#: motion/views.py:390 msgid "Do you really want to support this motion?" msgstr "Wollen Sie wirklich diesen Antrag unterstützen?" -#: motion/views.py:404 +#: motion/views.py:392 msgid "Do you really want to unsupport this motion?" msgstr "Wollen Sie wirklich Ihre Unterstützung für diesen Antrag entziehen?" -#: motion/views.py:415 +#: motion/views.py:403 msgid "You have supported this motion successfully." msgstr "Sie haben den Antrag erfolgreich unterstützt." -#: motion/views.py:417 +#: motion/views.py:405 msgid "You have unsupported this motion successfully." msgstr "Sie haben dem Antrag erfolgreich Ihre Unterstützung entzogen." -#: motion/views.py:431 +#: motion/views.py:419 msgid "New vote was successfully created." msgstr "Neue Abstimmung erfolgreich angelegt." -#: motion/views.py:447 +#: motion/views.py:435 msgid "Poll deleted" msgstr "Abstimmung gelöscht" -#: motion/views.py:448 +#: motion/views.py:436 msgid "Poll was successfully deleted." msgstr "Abstimmung wurde erfolgreich gelöscht." -#: motion/views.py:450 +#: motion/views.py:438 #, python-format msgid "the %s. poll" msgstr "die %s. Abstimmung" -#: motion/views.py:491 motion/views.py:500 +#: motion/views.py:479 motion/views.py:488 #, python-format msgid "You can not delete motion %s." msgstr "Sie können Antrag %s nicht löschen." -#: motion/views.py:496 motion/views.py:504 +#: motion/views.py:484 motion/views.py:492 #, python-format msgid "Motion %s was successfully deleted." msgstr "Antrag %s wurde erfolgreich gelöscht." -#: motion/views.py:506 +#: motion/views.py:494 msgid "Invalid request" msgstr "Ungültige Anfrage" -#: motion/views.py:530 +#: motion/views.py:518 msgid "Poll was updated" msgstr "Abstimmung wurde aktualisiert" -#: motion/views.py:547 +#: motion/views.py:535 #, python-format msgid "Version %s accepted." msgstr "Version %s akzeptiert." -#: motion/views.py:549 +#: motion/views.py:537 #, python-format msgid "Do you really want to authorize version %s?" msgstr "Soll Version %s wirklich zugelassen werden?" -#: motion/views.py:559 +#: motion/views.py:547 #, python-format msgid "Version %s rejected." msgstr "Version %s zurückgewiesen." -#: motion/views.py:561 +#: motion/views.py:549 msgid "ERROR by rejecting the version." msgstr "FEHLER beim Zurückweisen der Version." -#: motion/views.py:563 +#: motion/views.py:551 #, python-format msgid "Do you really want to reject version %s?" msgstr "Soll Version %s wirklich zurückgewiesen werden?" -#: motion/views.py:599 motion/views.py:603 motion/views.py:609 -#: motion/views.py:612 participant/api.py:76 +#: motion/views.py:587 motion/views.py:591 motion/views.py:597 +#: motion/views.py:600 participant/api.py:81 #, python-format msgid "Ignoring malformed line %d in import file." msgstr "Fehlerhafte Zeile %d der Quelldatei wurde ignoriert." -#: motion/views.py:620 +#: motion/views.py:608 #, python-format msgid "Ignoring line %d because the assigned group may not act as a person." msgstr "" "Fehlerhafte Zeile %d der Quelldatei wurde ignoriert da die verwendete Gruppe " "nicht als Person auftreten darf." -#: motion/views.py:629 +#: motion/views.py:617 msgid "Created by motion import." msgstr "Erstellt durch Antragsimport." -#: motion/views.py:643 +#: motion/views.py:631 #, python-format msgid "" "Ignoring line %d because it contains an incomplete first / last name pair." @@ -1355,52 +1347,52 @@ msgstr "" "Fehlerhafte Zeile %d der Quelldatei wurde ignoriert, da Vor- bzw. Nachname " "Leerstrings enthalten." -#: motion/views.py:681 +#: motion/views.py:669 #, python-format msgid "%d motion was successfully imported." msgid_plural "%d motions were successfully imported." msgstr[0] "%d Antrag wurde erfolgreich importiert." msgstr[1] "%d Anträge wurden erfolgreich importiert." -#: motion/views.py:684 +#: motion/views.py:672 #, python-format msgid "%d motion was successfully modified." msgid_plural "%d motions were successfully modified." msgstr[0] "%d Antrag wurde erfolgreich geändert." msgstr[1] "%d Anträge wurden erfolgreich geändert." -#: motion/views.py:687 +#: motion/views.py:675 #, python-format msgid "%d new user was added." msgid_plural "%d new users were added." msgstr[0] "%d neuer Nutzer wurde erstellt." msgstr[1] "%d neue Nutzer wurden erstellt." -#: motion/views.py:690 +#: motion/views.py:678 #, python-format msgid "%d new group was added." msgid_plural "%d new groups were added." msgstr[0] "%d neue Gruppe wurde erstellt." msgstr[1] "%d neue Gruppen wurden erstellt." -#: motion/views.py:693 +#: motion/views.py:681 #, python-format msgid "%d group assigned to motions." msgid_plural "%d groups assigned to motions." msgstr[0] "%d Gruppe wurde zugewiesen." msgstr[1] "%d Gruppen wurden zugewiesen." -#: motion/views.py:697 participant/api.py:92 +#: motion/views.py:685 participant/api.py:97 msgid "Import aborted because of severe errors in the input file." msgstr "Import auf Grund von schweren Fehlern in der Quelldatei abgebrochen." -#: motion/views.py:699 participant/api.py:94 +#: motion/views.py:687 participant/api.py:99 msgid "Import file has wrong character encoding, only UTF-8 is supported!" msgstr "" "Die Quelldatei benutzt eine ungültige Zeichenkodierung, es wird nur UTF-8 " "wird unterstützt!" -#: motion/views.py:703 +#: motion/views.py:691 msgid "" "Attention: Existing motions will be modified if you import new motions with " "the same number." @@ -1408,7 +1400,7 @@ msgstr "" "Achtung: Existierende Anträge werden geändert wenn Sie neue Anträge mit " "identischer Nummer importieren." -#: motion/views.py:704 +#: motion/views.py:692 msgid "" "Attention: Importing an motions without a number multiple times will create " "duplicates." @@ -1416,7 +1408,7 @@ msgstr "" "Achtung: Bei mehrfachem Import eines Antrags ohne Nummer können Duplikate " "entstehen." -#: motion/views.py:737 motion/views.py:875 +#: motion/views.py:725 motion/views.py:863 #: motion/templates/motion/poll_view.html:7 #: motion/templates/motion/poll_view.html:12 #: motion/templates/motion/view.html:7 motion/templates/motion/view.html:206 @@ -1426,21 +1418,21 @@ msgstr "" msgid "Motion" msgstr "Antrag" -#: motion/views.py:751 motion/templates/motion/overview.html:84 +#: motion/views.py:739 motion/templates/motion/overview.html:84 msgid "No motions available." msgstr "Keine Anträge vorhanden." -#: motion/views.py:756 motion/views.py:758 motion/views.py:773 -#: motion/views.py:775 motion/templates/motion/base_motion.html:24 +#: motion/views.py:744 motion/views.py:746 motion/views.py:761 +#: motion/views.py:763 motion/templates/motion/base_motion.html:24 #: motion/templates/projector/Motion.html:63 msgid "Motion No." msgstr "Antrag Nr." -#: motion/views.py:790 +#: motion/views.py:778 msgid "Signature" msgstr "Unterschrift" -#: motion/views.py:841 motion/templates/motion/base_motion.html:55 +#: motion/views.py:829 motion/templates/motion/base_motion.html:55 #: motion/templates/motion/poll_view.html:8 #: motion/templates/motion/poll_view.html:13 #: motion/templates/motion/view.html:66 motion/templates/motion/view.html:74 @@ -1448,21 +1440,21 @@ msgstr "Unterschrift" msgid "Vote" msgstr "Abstimmung" -#: motion/views.py:875 +#: motion/views.py:863 msgid "Poll" msgstr "Abstimmung" -#: motion/views.py:889 +#: motion/views.py:877 #, python-format msgid "Motion No. %s" msgstr "Antrag Nr. %s" -#: motion/views.py:891 +#: motion/views.py:879 #, python-format msgid "%d. Vote" msgstr "%d. Abstimmung" -#: motion/views.py:948 +#: motion/views.py:936 msgid "Motion settings successfully saved." msgstr "Antrags-Einstellungen wurden erfolgreich gespeichert." @@ -1517,28 +1509,34 @@ msgid "Select a CSV file to import motions!" msgstr "Wählen Sie eine CSV-Datei zum Importieren von Anträgen aus!" #: motion/templates/motion/import.html:11 -msgid "" -"Required comma separated values: {number, title, text, reason, " -"first_name, last_name, is_group} (number, reason and is_group are optional and may be empty)" -msgstr "" -"Erforderliche kommaseparierte Werte: {Nummer, Titel, Text, Begründung, " -"Vorname, Nachname, Gruppenantrag} (Nummer, " -"Begründung und Gruppenantrag sind optional und " -"können auch leer sein)" +#: participant/templates/participant/import.html:11 +msgid "Required comma separated values" +msgstr "Erforderliche kommaseparierte Werte" -#: motion/templates/motion/import.html:13 -#: participant/templates/participant/import.html:13 +#: motion/templates/motion/import.html:12 +msgid "number, title, text, reason, first_name, last_name, is_group" +msgstr "Nummer, Titel, Text, Begründung, Vorname, Nachname, Gruppenantrag" + +#: motion/templates/motion/import.html:14 +msgid "" +"number, reason and is_group are " +"optional and may be empty" +msgstr "" +"Nummer, Begründung und Gruppenantrag " +"sind optional und können auch leer sein." + +#: motion/templates/motion/import.html:16 +#: participant/templates/participant/import.html:14 msgid "Required CSV file encoding: UTF-8 (Unicode)." msgstr "Erforderliches CSV-Datei-Encoding: UTF-8 (Unicode)." -#: motion/templates/motion/import.html:16 -#: participant/templates/participant/import.html:16 +#: motion/templates/motion/import.html:19 +#: participant/templates/participant/import.html:17 msgid "A CSV example file is available in OpenSlides Wiki." msgstr "Eine CSV-Beispiel-Datei gibt es im OpenSlides Wiki." -#: motion/templates/motion/import.html:23 -#: participant/templates/participant/import.html:23 +#: motion/templates/motion/import.html:26 +#: participant/templates/participant/import.html:24 msgid "Import" msgstr "Importieren" @@ -1731,18 +1729,18 @@ msgstr "Keine Abstimmungsergebnisse vorhanden." msgid "Participant" msgstr "Teilnehmer" -#: participant/forms.py:26 participant/views.py:604 +#: participant/forms.py:27 participant/views.py:607 #: participant/templates/participant/group_overview.html:7 #: participant/templates/participant/group_overview.html:10 #: participant/templates/participant/user_detail.html:14 msgid "Groups" msgstr "Gruppen" -#: participant/forms.py:44 +#: participant/forms.py:52 msgid "Permissions" msgstr "Rechte" -#: participant/forms.py:47 participant/views.py:544 participant/views.py:590 +#: participant/forms.py:55 participant/views.py:546 participant/views.py:593 #: participant/templates/participant/base_participant.html:12 #: participant/templates/participant/overview.html:7 #: participant/templates/participant/overview.html:18 @@ -1750,211 +1748,211 @@ msgstr "Rechte" msgid "Participants" msgstr "Teilnehmer/innen" -#: participant/forms.py:83 -msgid "You can not edit the name for the anonymous user" -msgstr "Sie dürfen den Namen für Anonymous nicht bearbeiten." +#: participant/forms.py:92 +msgid "You can not edit the name for this group." +msgstr "Sie dürfen den Namen dieser Gruppe nicht bearbeiten." -#: participant/forms.py:87 +#: participant/forms.py:96 #, python-format msgid "Group name \"%s\" is reserved for internal use." msgstr "Der Gruppenname \"%s\" ist für interne Verwendung reserviert." -#: participant/forms.py:109 +#: participant/forms.py:118 msgid "System URL" msgstr "System URL" -#: participant/forms.py:110 participant/forms.py:115 +#: participant/forms.py:119 participant/forms.py:124 msgid "Printed in PDF of first time passwords only." msgstr "Erscheint nur im PDF der Erst-Passwörter" -#: participant/forms.py:118 +#: participant/forms.py:127 msgid "Sort participants by first name" msgstr "Teilnehmer/innen nach Vornamen sortieren" -#: participant/forms.py:119 +#: participant/forms.py:128 msgid "Disable for sorting by last name" msgstr "Deaktivieren für Sortierung nach Nachnamen" -#: participant/models.py:32 participant/templates/participant/overview.html:25 +#: participant/models.py:33 participant/templates/participant/overview.html:25 msgid "Male" msgstr "Männlich" -#: participant/models.py:33 participant/templates/participant/overview.html:26 +#: participant/models.py:34 participant/templates/participant/overview.html:26 msgid "Female" msgstr "Weiblich" -#: participant/models.py:36 participant/templates/participant/overview.html:38 +#: participant/models.py:37 participant/templates/participant/overview.html:38 msgid "Delegate" msgstr "Delegierter" -#: participant/models.py:37 participant/templates/participant/overview.html:39 +#: participant/models.py:38 participant/templates/participant/overview.html:39 msgid "Observer" msgstr "Beobachter" -#: participant/models.py:38 participant/templates/participant/overview.html:40 +#: participant/models.py:39 participant/templates/participant/overview.html:40 msgid "Staff" msgstr "Mitarbeiter" -#: participant/models.py:39 participant/templates/participant/overview.html:41 +#: participant/models.py:40 participant/templates/participant/overview.html:41 msgid "Guest" msgstr "Gast" -#: participant/models.py:44 participant/templates/participant/overview.html:30 +#: participant/models.py:45 participant/templates/participant/overview.html:30 #: participant/templates/participant/overview.html:68 msgid "Structure level" msgstr "Gliederungsebene" -#: participant/models.py:45 +#: participant/models.py:46 msgid "Will be shown after the name." msgstr "Wird nach dem Namen angezeigt." -#: participant/models.py:48 participant/templates/participant/overview.html:24 +#: participant/models.py:49 participant/templates/participant/overview.html:24 #: participant/templates/participant/user_detail.html:24 msgid "Gender" msgstr "Geschlecht" -#: participant/models.py:48 participant/models.py:51 participant/models.py:54 +#: participant/models.py:49 participant/models.py:52 participant/models.py:55 msgid "Only for filtering the participant list." msgstr "Nur zum Filtern der Teilnehmerliste." -#: participant/models.py:51 +#: participant/models.py:52 msgid "Typ" msgstr "Typ" -#: participant/models.py:53 participant/views.py:259 +#: participant/models.py:54 participant/views.py:255 #: participant/templates/participant/overview.html:45 #: participant/templates/participant/overview.html:70 #: participant/templates/participant/user_detail.html:34 msgid "Committee" msgstr "Amt" -#: participant/models.py:56 +#: participant/models.py:57 #: participant/templates/participant/user_detail.html:39 msgid "About me" msgstr "Über mich" -#: participant/models.py:57 +#: participant/models.py:58 msgid "Your profile text" msgstr "Ihr Profiltext" -#: participant/models.py:60 +#: participant/models.py:61 msgid "Only for notes." msgstr "Nur für Notizen." -#: participant/models.py:63 +#: participant/models.py:64 msgid "Default password" msgstr "Vorgegebenes Passwort" -#: participant/models.py:111 +#: participant/models.py:118 msgid "Can see participant" msgstr "Darf die Teilnehmer/inen sehen" -#: participant/models.py:113 +#: participant/models.py:120 msgid "Can manage participant" msgstr "Darf die Teilnehmer/inen verwalten" -#: participant/models.py:133 +#: participant/models.py:142 msgid "Use this group as participant" msgstr "Verwende diese Gruppe als Teilnehmer/in" -#: participant/models.py:133 +#: participant/models.py:143 msgid "For example as submitter of a motion." msgstr "Zum Beispiel als Antragsteller." -#: participant/models.py:225 +#: participant/models.py:237 msgid "Welcome to OpenSlides!" msgstr "Willkommen bei OpenSlides!" -#: participant/views.py:210 +#: participant/views.py:207 msgid "You can not delete yourself." msgstr "Sie dürfen sich nicht selbst löschen." -#: participant/views.py:212 -msgid "You can not delete the administrator." -msgstr "Sie dürfen den Administrator nicht löschen." - -#: participant/views.py:232 +#: participant/views.py:228 msgid "You can not deactivate yourself." msgstr "Sie dürfen sich nicht selbst deaktivieren." -#: participant/views.py:235 +#: participant/views.py:231 msgid "You can not deactivate the administrator." msgstr "Sie dürfen den Administrator nicht deaktivieren." -#: participant/views.py:254 +#: participant/views.py:250 msgid "Participant-list" msgstr "Teilnehmerliste" -#: participant/views.py:255 +#: participant/views.py:251 msgid "List of Participants" msgstr "Teilnehmerliste" -#: participant/views.py:258 participant/templates/participant/overview.html:67 +#: participant/views.py:254 participant/templates/participant/overview.html:67 msgid "Last Name" msgstr "Nachname" -#: participant/views.py:258 participant/templates/participant/overview.html:66 +#: participant/views.py:254 participant/templates/participant/overview.html:66 msgid "First Name" msgstr "Vorname" -#: participant/views.py:258 +#: participant/views.py:254 #: participant/templates/participant/group_overview.html:13 msgid "Group" msgstr "Gruppe" -#: participant/views.py:258 participant/templates/participant/overview.html:37 +#: participant/views.py:254 participant/templates/participant/overview.html:37 #: participant/templates/participant/overview.html:69 #: participant/templates/participant/user_detail.html:29 msgid "Type" msgstr "Typ" -#: participant/views.py:290 +#: participant/views.py:286 msgid "Participant-passwords" msgstr "Teilnehmer-Passwoerter" -#: participant/views.py:312 +#: participant/views.py:308 msgid "Account for OpenSlides" msgstr "Zugang für OpenSlides" -#: participant/views.py:314 +#: participant/views.py:310 #, python-format msgid "for %s" msgstr "für %s" -#: participant/views.py:317 +#: participant/views.py:313 #, python-format msgid "User: %s" msgstr "Nutzername: %s" -#: participant/views.py:321 +#: participant/views.py:317 #, python-format msgid "Password: %s" msgstr "Passwort: %s" -#: participant/views.py:326 +#: participant/views.py:322 #, python-format msgid "URL: %s" msgstr "URL: %s" -#: participant/views.py:368 +#: participant/views.py:364 #, python-format msgid "%d new participants were successfully imported." msgstr "%d neue Teilnehmer/innen wurden erfolgreich importiert." -#: participant/views.py:379 +#: participant/views.py:375 msgid "Do you really want to reset the password?" msgstr "Soll das Passwort wirklich zurückgesetzt werden?" -#: participant/views.py:392 +#: participant/views.py:388 #, python-format msgid "The Password for %s was successfully reset." msgstr "Das Passwort für %s wurde erfolgreich zurückgesetzt." -#: participant/views.py:471 +#: participant/views.py:445 +msgid "You can not delete this Group." +msgstr "Sie dürfen diese Gruppe nicht löschen." + +#: participant/views.py:473 msgid "Participants settings successfully saved." msgstr "Teilnehmer/innen-Einstellungen wurden erfolgreich gespeichert." -#: participant/views.py:481 +#: participant/views.py:483 #, python-format msgid "" "Installation was successfully! Use %(user)s (password: %(password)s) for " @@ -1967,15 +1965,15 @@ msgstr "" "Sie das Passwort nach der ersten Anmeldung! Anderenfalls erscheint diese " "Meldung weiterhin für alle und ist ein Sicherheitsrisiko." -#: participant/views.py:504 +#: participant/views.py:506 msgid "User settings successfully saved." msgstr "Nutzereinstellungen wurden erfolgreich gespeichert." -#: participant/views.py:526 +#: participant/views.py:528 msgid "Password successfully changed." msgstr "Passwort wurde erfolgreich geändert." -#: participant/views.py:576 +#: participant/views.py:579 msgid "My motions and elections" msgstr "Meine Anträge und Wahlen" @@ -2055,12 +2053,10 @@ msgid "Reset to First Password" msgstr "Auf Erst-Passwort zurücksetzen" #: participant/templates/participant/group_detail.html:14 -#: participant/templates/projector/GroupSlide.html:13 msgid "Members" msgstr "Mitglieder" #: participant/templates/participant/group_detail.html:19 -#: participant/templates/projector/GroupSlide.html:22 msgid "No members available." msgstr "Keine Mitglieder vorhanden." @@ -2073,13 +2069,11 @@ msgstr "Keine Gruppen vorhanden." msgid "Select a CSV file to import participants!" msgstr "Wählen Sie eine CSV-Datei zum Importieren von Teilnehmer/innen aus!" -#: participant/templates/participant/import.html:11 +#: participant/templates/participant/import.html:12 msgid "" -"Required comma separated values: {first_name, last_name, gender, " -"group, type, committee, comment}" +"first_name, last_name, gender, structure level, type, committee, comment" msgstr "" -"Erforderliche kommaseparierte Werte: {Vorname, Nachname, Geschlecht, " -"Gruppe, Typ, Amt, Kommentar}" +"Vorname, Nachname, Geschlecht, Gliederungsebene, Typ, Amt, Kommentar" #: participant/templates/participant/login.html:8 #: participant/templates/participant/login.html:16 @@ -2108,7 +2102,7 @@ msgstr "Weiter als Gast" msgid "Not specified" msgstr "Nicht angegeben" -#: participant/templates/participant/overview.html:53 projector/models.py:67 +#: participant/templates/participant/overview.html:53 projector/models.py:63 msgid "Active" msgstr "Aktiv" @@ -2131,15 +2125,15 @@ msgstr "von" msgid "Last Login" msgstr "Letzer Login" -#: participant/templates/participant/overview.html:100 +#: participant/templates/participant/overview.html:102 msgid "Change status to inactive" msgstr "Status ändern auf inaktiv" -#: participant/templates/participant/overview.html:103 +#: participant/templates/participant/overview.html:105 msgid "Change status to active" msgstr "Status ändern auf aktiv" -#: participant/templates/participant/overview.html:113 +#: participant/templates/participant/overview.html:115 #: participant/templates/participant/user_widget.html:22 msgid "No participants available." msgstr "Keine Teilnehmer/innen vorhanden." @@ -2201,37 +2195,37 @@ msgstr "Ungültige Stimmen" msgid "votes" msgstr "Stimmen" -#: projector/models.py:53 +#: projector/models.py:50 msgid "Can manage the projector" msgstr "Darf den Projektor steuern" -#: projector/models.py:54 +#: projector/models.py:51 msgid "Can see the projector" msgstr "Darf den Projektor sehen" -#: projector/models.py:55 +#: projector/models.py:52 msgid "Can see the dashboard" msgstr "Darf das Dashboard sehen" -#: projector/views.py:206 +#: projector/views.py:199 msgid "Errors in the form" msgstr "Fehler im Formular" -#: projector/views.py:384 projector/templates/projector/base_projector.html:7 +#: projector/views.py:375 projector/templates/projector/base_projector.html:7 #: projector/templates/projector/base_projector.html:12 #: projector/templates/projector/dashboard.html:17 msgid "Dashboard" msgstr "Dashboard" -#: projector/views.py:412 +#: projector/views.py:402 msgid "Projector live view" msgstr "Projektor-Live-Ansicht" -#: projector/views.py:439 +#: projector/views.py:428 msgid "Overlays" msgstr "Einblendungen" -#: projector/views.py:452 +#: projector/views.py:440 msgid "Custom Slides" msgstr "Benutzerdefinierte Folien" @@ -2350,53 +2344,43 @@ msgstr "Stand: %s" msgid "Page %s" msgstr "Seite %s" -#: utils/utils.py:66 utils/views.py:290 +#: utils/utils.py:69 utils/views.py:287 #, python-format msgid "Do you really want to delete %s?" msgstr "Soll %s wirklich gelöscht werden?" -#: utils/utils.py:111 +#: utils/utils.py:116 msgid "Sorry, you have no rights to see this page." msgstr "Bedaure, Sie haben keine Berechtigung diese Seite zu sehen." -#: utils/views.py:109 +#: utils/views.py:106 msgid "Are you sure?" msgstr "Sind Sie sicher?" -#: utils/views.py:110 +#: utils/views.py:107 msgid "Thank you for your answer" msgstr "Danke für Ihre Antwort" -#: utils/views.py:247 +#: utils/views.py:244 #, python-format msgid "%s was successfully modified." msgstr "%s wurde erfolgreich bearbeitet." -#: utils/views.py:278 +#: utils/views.py:275 #, python-format msgid "%s was successfully created." msgstr "%s wurde erfolgreich angelegt." -#: utils/views.py:296 +#: utils/views.py:293 #, python-format msgid "%s was successfully deleted." msgstr "%s wurde erfolgreich gelöscht." -#: utils/views.py:312 +#: utils/views.py:308 msgid "undefined-filename" msgstr "undefinierter-dateiname" -#: utils/jsonfield/fields.py:21 +#: utils/jsonfield/fields.py:22 msgid "Enter valid JSON" msgstr "Gebe valides JSON ein" -#~ msgid "Ignoring line %d because the assigned group does not exist." -#~ msgstr "" -#~ "Fehlerhafte Zeile %d der Quelldatei wurde ignoriert da die verwendete " -#~ "Gruppe nicht existiert." - -#~ msgid "posts" -#~ msgstr "Posten" - -#~ msgid "candidates" -#~ msgstr "Kandidaten/innen" diff --git a/openslides/locale/fr/LC_MESSAGES/django.mo b/openslides/locale/fr/LC_MESSAGES/django.mo index 50f308e0a30e2ea25bb447509bd5458dcdbce538..c8595d553b6a65c804bfc65506cc0db15ca2739e 100644 GIT binary patch delta 9695 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 F{{r^cVITki delta 11451 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\n" "Language-Team: Französisch <>\n" @@ -19,15 +19,15 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -#: global_settings.py:36 +#: global_settings.py:33 msgid "German" msgstr "Allemand" -#: global_settings.py:37 +#: global_settings.py:34 msgid "English" msgstr "Anglais" -#: global_settings.py:38 +#: global_settings.py:35 msgid "French" msgstr "" @@ -35,43 +35,43 @@ msgstr "" msgid "Parent item" msgstr "Elément parent" -#: agenda/models.py:42 config/forms.py:61 motion/forms.py:22 -#: motion/models.py:540 motion/templates/motion/view.html:246 -#: projector/models.py:32 +#: agenda/models.py:34 config/forms.py:59 motion/forms.py:22 +#: motion/models.py:539 motion/templates/motion/view.html:246 +#: projector/models.py:29 msgid "Title" msgstr "Titre" -#: agenda/models.py:43 motion/forms.py:23 motion/models.py:541 -#: motion/templates/motion/view.html:247 projector/models.py:33 +#: agenda/models.py:35 motion/forms.py:23 motion/models.py:540 +#: motion/templates/motion/view.html:247 projector/models.py:30 msgid "Text" msgstr "Texte" -#: agenda/models.py:44 agenda/templates/agenda/overview.html:65 -#: agenda/templates/agenda/view.html:13 participant/models.py:56 +#: agenda/models.py:36 agenda/templates/agenda/overview.html:65 +#: agenda/templates/agenda/view.html:13 participant/models.py:60 #: participant/templates/participant/overview.html:72 #: participant/templates/participant/user_detail.html:45 msgid "Comment" msgstr "Commentaire" -#: agenda/models.py:45 +#: agenda/models.py:37 msgid "Closed" msgstr "Fermé" -#: agenda/models.py:46 agenda/templates/agenda/overview.html:71 -#: projector/models.py:34 +#: agenda/models.py:38 agenda/templates/agenda/overview.html:71 +#: projector/models.py:31 msgid "Weight" msgstr "Pondération" -#: agenda/models.py:180 +#: agenda/models.py:171 msgid "Can see agenda" msgstr "Peut voir l'ordre du jour" -#: agenda/models.py:181 +#: agenda/models.py:172 msgid "Can manage agenda" msgstr "Peut gérer l'ordre du jour" -#: agenda/models.py:189 agenda/slides.py:20 agenda/views.py:194 -#: agenda/views.py:195 agenda/views.py:214 +#: agenda/models.py:180 agenda/slides.py:20 agenda/views.py:191 +#: agenda/views.py:192 agenda/views.py:212 agenda/views.py:226 #: agenda/templates/agenda/base_agenda.html:10 #: agenda/templates/agenda/overview.html:8 #: agenda/templates/agenda/overview.html:52 @@ -81,34 +81,34 @@ msgstr "Peut gérer l'ordre du jour" msgid "Agenda" msgstr "Ordre du jour" -#: agenda/views.py:57 +#: agenda/views.py:54 msgid "You are not authorized to manage the agenda." msgstr "Vous n'êtes pas autorisé à gérer l'ordre du jour." -#: agenda/views.py:73 +#: agenda/views.py:70 msgid "Errors when reordering of the agenda" msgstr "Erreurs en réorganisant de l'ordre du jour" -#: agenda/views.py:134 +#: agenda/views.py:131 #, python-format msgid "Item %s was successfully modified." msgstr "Elément %s a été modifié avec succès." -#: agenda/views.py:155 +#: agenda/views.py:152 #, python-format msgid "Item %s was successfully created." msgstr "Elément %s a été créé avec succès." -#: agenda/views.py:172 +#: agenda/views.py:169 msgid "Yes, with all child items." msgstr "Oui, avec tous les sous-éléments." -#: agenda/views.py:180 +#: agenda/views.py:177 #, python-format msgid "Item %s and his children were successfully deleted." msgstr "Elément %s et ses sous-éléments ont été créé avec succès." -#: agenda/views.py:185 +#: agenda/views.py:182 #, python-format msgid "Item %s was successfully deleted." msgstr "Elément %s a été supprimé avec succès." @@ -172,12 +172,12 @@ msgstr "Enregistrer" #: assignment/templates/assignment/poll_view.html:73 #: config/templates/config/general.html:60 #: motion/templates/motion/config.html:17 motion/templates/motion/edit.html:33 -#: motion/templates/motion/import.html:27 +#: motion/templates/motion/import.html:30 #: motion/templates/motion/poll_view.html:59 #: participant/templates/participant/config.html:17 #: participant/templates/participant/edit.html:38 #: participant/templates/participant/group_edit.html:32 -#: participant/templates/participant/import.html:27 +#: participant/templates/participant/import.html:28 #: participant/templates/participant/password_change.html:26 #: participant/templates/participant/settings.html:26 #: projector/templates/projector/new.html:20 @@ -187,7 +187,7 @@ msgstr "Annuler" #: agenda/templates/agenda/edit.html:27 #: assignment/templates/assignment/edit.html:29 #: assignment/templates/assignment/poll_view.html:69 -#: assignment/templates/assignment/view.html:83 +#: assignment/templates/assignment/view.html:92 #: motion/templates/motion/edit.html:29 #: motion/templates/motion/poll_view.html:55 #: participant/templates/participant/edit.html:34 @@ -199,10 +199,10 @@ msgstr "Appliquer" #: agenda/templates/agenda/edit.html:35 #: assignment/templates/assignment/edit.html:37 -#: motion/templates/motion/edit.html:37 motion/templates/motion/import.html:31 +#: motion/templates/motion/edit.html:37 motion/templates/motion/import.html:34 #: participant/templates/participant/edit.html:42 #: participant/templates/participant/group_edit.html:36 -#: participant/templates/participant/import.html:31 +#: participant/templates/participant/import.html:32 msgid "required" msgstr "requis" @@ -228,25 +228,25 @@ msgstr "Activez le résumé pour cet élément" msgid "Do you want to save the changed order of agenda items?" msgstr "Voulez-vous enregistrer les modifications de l'ordre du jour?" -#: agenda/templates/agenda/overview.html:46 assignment/models.py:302 -#: assignment/views.py:577 assignment/templates/assignment/view.html:184 -#: assignment/templates/assignment/view.html:188 +#: agenda/templates/agenda/overview.html:46 assignment/models.py:294 +#: assignment/views.py:587 assignment/templates/assignment/view.html:168 +#: assignment/templates/assignment/view.html:172 #: assignment/templates/projector/Assignment.html:78 #: assignment/templates/projector/Assignment.html:82 motion/models.py:574 -#: motion/views.py:804 motion/views.py:855 +#: motion/views.py:830 motion/views.py:881 #: motion/templates/motion/view.html:79 -#: motion/templates/projector/Motion.html:37 utils/utils.py:53 -#: utils/views.py:111 +#: motion/templates/projector/Motion.html:37 utils/utils.py:55 +#: utils/views.py:108 msgid "Yes" msgstr "Oui" -#: agenda/templates/agenda/overview.html:47 assignment/models.py:302 -#: assignment/views.py:578 assignment/templates/assignment/view.html:185 +#: agenda/templates/agenda/overview.html:47 assignment/models.py:294 +#: assignment/views.py:588 assignment/templates/assignment/view.html:169 #: assignment/templates/projector/Assignment.html:79 motion/models.py:574 -#: motion/views.py:804 motion/views.py:856 +#: motion/views.py:830 motion/views.py:882 #: motion/templates/motion/view.html:80 -#: motion/templates/projector/Motion.html:38 utils/utils.py:53 -#: utils/views.py:111 +#: motion/templates/projector/Motion.html:38 utils/utils.py:55 +#: utils/views.py:108 msgid "No" msgstr "Non" @@ -301,7 +301,7 @@ msgid "Preview" msgstr "Aperçu" #: agenda/templates/agenda/widget.html:23 -#: assignment/templates/assignment/view.html:148 +#: assignment/templates/assignment/view.html:132 #: assignment/templates/assignment/widget.html:11 #: motion/templates/motion/widget.html:11 #: participant/templates/participant/group_widget.html:11 @@ -311,7 +311,7 @@ msgid "Delete" msgstr "Supprimer" #: agenda/templates/agenda/widget.html:26 -#: assignment/templates/assignment/view.html:147 +#: assignment/templates/assignment/view.html:131 #: assignment/templates/assignment/widget.html:14 #: motion/templates/motion/widget.html:14 #: participant/templates/participant/group_widget.html:14 @@ -320,7 +320,7 @@ msgstr "Supprimer" msgid "Edit" msgstr "Modifier" -#: assignment/forms.py:24 assignment/models.py:57 assignment/views.py:383 +#: assignment/forms.py:24 assignment/models.py:51 assignment/views.py:381 #: assignment/templates/assignment/view.html:13 #: assignment/templates/projector/Assignment.html:21 msgid "Number of available posts" @@ -336,176 +336,177 @@ msgstr "" "Publier seulement les résultat du candidat qui a gagné l'election " "(Uniquement sur la vue projecteur)" -#: assignment/forms.py:47 motion/forms.py:77 +#: assignment/forms.py:46 motion/forms.py:77 msgid "Number of ballot papers (selection)" msgstr "Nombre de bulletins de vote (sélection)" -#: assignment/forms.py:49 motion/forms.py:79 +#: assignment/forms.py:48 motion/forms.py:79 msgid "Number of all delegates" msgstr "Nombre de délégués" -#: assignment/forms.py:50 motion/forms.py:80 +#: assignment/forms.py:49 motion/forms.py:80 msgid "Number of all participants" msgstr "Nombre de participants" -#: assignment/forms.py:51 motion/forms.py:81 +#: assignment/forms.py:50 motion/forms.py:81 msgid "Use the following custom number" msgstr "Utilisez le nombre personnalisé suivant" -#: assignment/forms.py:58 motion/forms.py:88 +#: assignment/forms.py:55 motion/forms.py:88 msgid "Custom number of ballot papers" msgstr "Nombre personnalisé de bulletins de vote" -#: assignment/forms.py:63 +#: assignment/forms.py:59 msgid "Title for PDF document (all elections)" msgstr "Titre du fichier PDF (toutes les élections)" -#: assignment/forms.py:68 +#: assignment/forms.py:63 msgid "Preamble text for PDF document (all elections)" msgstr "Texte de préambule pour le fichier PDF (toutes les élections)" -#: assignment/forms.py:72 +#: assignment/forms.py:67 msgid "Election method" msgstr "Mode d'élection" -#: assignment/forms.py:74 +#: assignment/forms.py:69 msgid "Automatic assign of method." msgstr "Assignation automatique de la méthode." -#: assignment/forms.py:75 +#: assignment/forms.py:70 msgid "Always one option per candidate." msgstr "Toujours une option par candidat" -#: assignment/forms.py:76 +#: assignment/forms.py:71 msgid "Always Yes-No-Abstain per candidate." msgstr "Toujours Oui-Non-Abstention par candidat." -#: assignment/models.py:48 assignment/templates/assignment/overview.html:15 +#: assignment/models.py:44 assignment/templates/assignment/overview.html:15 #: assignment/templates/assignment/view.html:23 msgid "Searching for candidates" msgstr "Recherche de candidats" -#: assignment/models.py:49 assignment/templates/assignment/overview.html:16 +#: assignment/models.py:45 assignment/templates/assignment/overview.html:16 #: assignment/templates/assignment/view.html:25 msgid "Voting" msgstr "Vote" -#: assignment/models.py:50 assignment/templates/assignment/overview.html:17 +#: assignment/models.py:46 assignment/templates/assignment/overview.html:17 #: assignment/templates/assignment/view.html:27 msgid "Finished" msgstr "Terminé" -#: assignment/models.py:53 +#: assignment/models.py:49 msgid "Name" msgstr "Nom" -#: assignment/models.py:55 participant/models.py:120 +#: assignment/models.py:50 participant/models.py:144 msgid "Description" msgstr "Description" -#: assignment/models.py:59 +#: assignment/models.py:54 msgid "Comment on the ballot paper" msgstr "Commentaire sur le bulletin de vote" -#: assignment/models.py:69 motion/models.py:335 +#: assignment/models.py:64 motion/models.py:332 #, python-format msgid "%s is not a valid status." msgstr "%s est un statut invalide." -#: assignment/models.py:71 +#: assignment/models.py:67 #, python-format msgid "The assignment status is already %s." msgstr "Le statut d'assignation est déjà sur %s" -#: assignment/models.py:85 +#: assignment/models.py:80 #, python-format msgid "%s is already a candidate." msgstr "%s est déja un candidat." -#: assignment/models.py:87 assignment/views.py:200 +#: assignment/models.py:82 assignment/views.py:195 msgid "The candidate list is already closed." msgstr "La liste des candidats est déjà fermée" -#: assignment/models.py:94 +#: assignment/models.py:89 #, python-format msgid "%s does not want to be a candidate." msgstr "%s ne veut pas etre un candidat" -#: assignment/models.py:109 +#: assignment/models.py:103 #, python-format msgid "%s is no candidate" msgstr "%s n'est pas un candidat" -#: assignment/models.py:255 +#: assignment/models.py:247 msgid "Can see assignment" msgstr "Peut voir l'assignation" -#: assignment/models.py:257 +#: assignment/models.py:249 msgid "Can nominate another person" msgstr "Peut nonimer une autre personne" -#: assignment/models.py:258 +#: assignment/models.py:250 msgid "Can nominate themselves" msgstr "Peut se nominer soi-même" -#: assignment/models.py:259 +#: assignment/models.py:251 msgid "Can manage assignment" msgstr "Peut gérer l'assignation" -#: assignment/models.py:303 motion/models.py:575 +#: assignment/models.py:294 motion/models.py:574 msgid "Abstain" msgstr "Abstention" -#: assignment/models.py:305 motion/templates/motion/poll_view.html:22 +#: assignment/models.py:296 motion/templates/motion/poll_view.html:22 msgid "Votes" msgstr "Votes" -#: assignment/models.py:322 +#: assignment/models.py:313 #, python-format msgid "Ballot %d" msgstr "Vote %d" -#: assignment/models.py:331 assignment/views.py:340 assignment/views.py:664 +#: assignment/models.py:322 assignment/views.py:336 assignment/views.py:675 +#: assignment/views.py:690 #: assignment/templates/assignment/base_assignment.html:14 #: assignment/templates/assignment/overview.html:6 #: assignment/templates/assignment/overview.html:9 msgid "Elections" msgstr "Elections" -#: assignment/views.py:88 +#: assignment/views.py:80 #, python-format msgid "Candidate %s was nominated successfully." msgstr "Le candidat %s a été nominé avec succès. " -#: assignment/views.py:130 +#: assignment/views.py:122 msgid "New election was successfully created." msgstr "La nouvelle élection a été créée avec succès." -#: assignment/views.py:132 +#: assignment/views.py:124 msgid "Election was successfully modified." msgstr "L'élection a été modifiée avec succès." -#: assignment/views.py:138 motion/views.py:257 motion/views.py:663 -#: participant/views.py:492 participant/views.py:515 utils/views.py:225 -#: utils/views.py:243 utils/views.py:267 +#: assignment/views.py:130 motion/views.py:245 motion/views.py:689 +#: participant/views.py:508 participant/views.py:531 utils/views.py:222 +#: utils/views.py:240 utils/views.py:264 msgid "Please check the form for errors." msgstr "S'il vous plaît vérifier si il a des erreurs dans le formulaire." -#: assignment/views.py:157 +#: assignment/views.py:149 #, python-format msgid "Election %s was successfully deleted." msgstr "L'election %s a été supprimée avec succès." -#: assignment/views.py:170 +#: assignment/views.py:162 #, python-format msgid "Election status was set to: %s." msgstr "Le statut de l'élection a été changé sur %s." -#: assignment/views.py:181 +#: assignment/views.py:175 msgid "You have set your candidature successfully." msgstr "Vous avez inséré votre candidature avec succès." -#: assignment/views.py:197 +#: assignment/views.py:192 msgid "" "You have withdrawn your candidature successfully. You can not be nominated " "by other participants anymore." @@ -513,101 +514,100 @@ msgstr "" "Vous avez retiré votre candidature avec succès. On ne peut plus vous " "nominer comme candidat" -#: assignment/views.py:218 +#: assignment/views.py:213 #, python-format msgid "Candidate %s was withdrawn successfully." msgstr "Le candidat %s a été rejeté avec succès." -#: assignment/views.py:220 +#: assignment/views.py:215 #, python-format msgid "%s was unblocked successfully." msgstr "Le candidat %s a été nominé avec succès." -#: assignment/views.py:224 +#: assignment/views.py:219 #, python-format msgid "Do you really want to withdraw %s from the election?" msgstr "Voulez-vous vraiment exclure %s de cette élection?" -#: assignment/views.py:226 +#: assignment/views.py:221 #, python-format msgid "Do you really want to unblock %s for the election?" msgstr "" "Voulez-vous vraiment repermettre a participer %s à cette élection?" -#: assignment/views.py:241 +#: assignment/views.py:236 msgid "New ballot was successfully created." msgstr "Le nouveau vote a été créé avec succès" -#: assignment/views.py:273 +#: assignment/views.py:268 #, python-format msgid "Ballot ID %d does not exist." msgstr "L'identifiant %d de vote n'existe pas." -#: assignment/views.py:280 +#: assignment/views.py:275 msgid "Ballot successfully published." msgstr "Le vote a été publié avec succès." -#: assignment/views.py:282 +#: assignment/views.py:277 msgid "Ballot successfully unpublished." msgstr "Le vote a été retiré avec succès." -#: assignment/views.py:295 +#: assignment/views.py:290 msgid "not elected" msgstr "non élu" -#: assignment/views.py:298 assignment/views.py:481 -#: assignment/templates/assignment/overview.html:35 +#: assignment/views.py:293 assignment/views.py:482 +#: assignment/templates/assignment/view.html:48 msgid "elected" msgstr "élu" -#: assignment/views.py:326 +#: assignment/views.py:321 msgid "Ballot was successfully deleted." msgstr "Le vote a été supprimé avec succès." -#: assignment/views.py:337 +#: assignment/views.py:333 msgid "Assignment" msgstr "Assignation" -#: assignment/views.py:358 assignment/templates/assignment/overview.html:58 +#: assignment/views.py:356 assignment/templates/assignment/overview.html:59 #: assignment/templates/assignment/widget.html:23 msgid "No assignments available." msgstr "Aucune assignation disponible." -#: assignment/views.py:377 +#: assignment/views.py:375 #, python-format msgid "Election: %s" msgstr "Election: %s" -#: assignment/views.py:389 assignment/views.py:422 +#: assignment/views.py:388 assignment/views.py:424 #: assignment/templates/assignment/overview.html:26 #: assignment/templates/assignment/poll_view.html:18 -#: assignment/templates/assignment/view.html:36 -#: assignment/templates/assignment/view.html:136 +#: assignment/templates/assignment/view.html:37 +#: assignment/templates/assignment/view.html:120 #: assignment/templates/projector/Assignment.html:38 #: assignment/templates/projector/Assignment.html:56 msgid "Candidates" msgstr "Candidats" -#: assignment/views.py:410 motion/views.py:797 +#: assignment/views.py:413 motion/views.py:823 #: motion/templates/motion/view.html:44 msgid "Vote results" msgstr "Résultat du vote" -#: assignment/views.py:414 +#: assignment/views.py:417 #: assignment/templates/assignment/base_assignment.html:71 #: assignment/templates/assignment/poll_view.html:5 #: assignment/templates/assignment/poll_view.html:8 -#: assignment/templates/assignment/view.html:130 -#: assignment/templates/assignment/view.html:139 +#: assignment/templates/assignment/view.html:123 #: assignment/templates/projector/Assignment.html:59 msgid "ballot" msgstr "vote" -#: assignment/views.py:417 +#: assignment/views.py:420 msgid "ballots" msgstr "votes" -#: assignment/views.py:443 +#: assignment/views.py:445 #, python-format msgid "" "Y: %(YES)s\n" @@ -619,26 +619,26 @@ msgstr "" "A: %(ABSTAIN)s" # assignment/templates/assignment/poll_view.html:35 -#: assignment/views.py:454 assignment/templates/assignment/poll_view.html:35 -#: assignment/templates/assignment/view.html:203 -#: assignment/templates/projector/Assignment.html:97 +#: assignment/views.py:456 assignment/templates/assignment/poll_view.html:35 +#: assignment/templates/assignment/view.html:186 +#: assignment/templates/projector/Assignment.html:96 #: motion/templates/motion/poll_view.html:31 msgid "Invalid votes" msgstr "Votes invalides" # assignment/templates/assignment/poll_view.html:45 -#: assignment/views.py:461 assignment/templates/assignment/poll_view.html:45 -#: assignment/templates/assignment/view.html:220 -#: assignment/templates/assignment/view.html:225 -#: assignment/templates/projector/Assignment.html:111 -#: assignment/templates/projector/Assignment.html:117 motion/views.py:804 +#: assignment/views.py:463 assignment/templates/assignment/poll_view.html:45 +#: assignment/templates/assignment/view.html:202 +#: assignment/templates/assignment/view.html:207 +#: assignment/templates/projector/Assignment.html:109 +#: assignment/templates/projector/Assignment.html:115 motion/views.py:830 #: motion/templates/motion/poll_view.html:35 #: motion/templates/motion/view.html:84 #: motion/templates/projector/Motion.html:42 poll/models.py:76 msgid "Votes cast" msgstr "Nombre de votants" -#: assignment/views.py:520 assignment/views.py:536 +#: assignment/views.py:523 assignment/views.py:541 #: assignment/templates/assignment/overview.html:25 #: assignment/templates/assignment/poll_view.html:5 #: assignment/templates/assignment/view.html:6 @@ -646,19 +646,19 @@ msgstr "Nombre de votants" msgid "Election" msgstr "Election" -#: assignment/views.py:542 +#: assignment/views.py:548 #, python-format msgid "%d. ballot" msgstr "%d. vote" -#: assignment/views.py:543 +#: assignment/views.py:550 #, python-format msgid "%d candidate" msgid_plural "%d candidates" msgstr[0] "%d candidat" msgstr[1] "%d candidats" -#: assignment/views.py:545 +#: assignment/views.py:552 #, python-format msgid "%d available post" msgid_plural "%d available posts" @@ -666,21 +666,17 @@ msgstr[0] "%d postes disponibles" msgstr[1] "%d postes disponibles" # assignment/templates/assignment/view.html:160 -#: assignment/views.py:578 assignment/templates/assignment/view.html:186 -#: assignment/templates/projector/Assignment.html:80 motion/views.py:804 -#: motion/views.py:857 motion/templates/motion/view.html:81 +#: assignment/views.py:588 assignment/templates/assignment/view.html:170 +#: assignment/templates/projector/Assignment.html:80 motion/views.py:830 +#: motion/views.py:883 motion/templates/motion/view.html:81 #: motion/templates/projector/Motion.html:39 msgid "Abstention" msgstr "Abstention" -#: assignment/views.py:657 +#: assignment/views.py:668 msgid "Election settings successfully saved." msgstr "Les paramètres de l'élection ont été enregistrés avec succès." -#: assignment/views.py:677 -msgid "Assignments" -msgstr "Assignements" - #: assignment/templates/assignment/base_assignment.html:16 msgid "All elections" msgstr "Toutes les élections" @@ -702,17 +698,17 @@ msgstr "Afficher l'élection" #: assignment/templates/assignment/base_assignment.html:39 #: assignment/templates/assignment/edit.html:8 #: assignment/templates/assignment/edit.html:17 -#: assignment/templates/assignment/overview.html:49 +#: assignment/templates/assignment/overview.html:50 msgid "Edit election" msgstr "Modifier l'élection" #: assignment/templates/assignment/base_assignment.html:44 -#: assignment/templates/assignment/overview.html:50 +#: assignment/templates/assignment/overview.html:51 msgid "Delete election" msgstr "Supprimer l'élection" #: assignment/templates/assignment/base_assignment.html:50 -#: assignment/templates/assignment/overview.html:52 +#: assignment/templates/assignment/overview.html:53 msgid "Election as PDF" msgstr "L'élection en PDF" @@ -733,7 +729,7 @@ msgstr "Paramètres de l'élection" #: assignment/templates/assignment/overview.html:14 #: assignment/templates/assignment/overview.html:27 #: assignment/templates/assignment/view.html:11 -#: assignment/templates/projector/Assignment.html:18 motion/views.py:775 +#: assignment/templates/projector/Assignment.html:18 motion/views.py:801 #: motion/templates/motion/overview.html:20 #: motion/templates/motion/overview.html:40 #: motion/templates/motion/view.html:34 @@ -749,14 +745,21 @@ msgstr[0] "élection" msgstr[1] "élections" #: assignment/templates/assignment/overview.html:35 -msgid "posts" -msgstr "postes" +#, python-format +msgid "posts: %(posts)s" +msgstr "" #: assignment/templates/assignment/overview.html:37 -msgid "candidates" -msgstr "Candidats" +#, fuzzy, python-format +msgid "candidates: %(candidates)s" +msgstr "Aucun candidat n'est disponible" -#: assignment/templates/assignment/overview.html:44 +#: assignment/templates/assignment/overview.html:39 +#, fuzzy, python-format +msgid "elected: %(elected)s" +msgstr "Supprimer l'élection" + +#: assignment/templates/assignment/overview.html:45 msgid "Activate election" msgstr "Activer l'élection" @@ -770,13 +773,13 @@ msgid "Special values" msgstr "Valeurs spéciales" #: assignment/templates/assignment/poll_view.html:12 -#: motion/templates/motion/poll_view.html:14 poll/models.py:235 +#: motion/templates/motion/poll_view.html:14 poll/models.py:234 msgid "majority" msgstr "majorité" #: assignment/templates/assignment/poll_view.html:12 -#: motion/templates/motion/poll_view.html:14 poll/models.py:237 -#: poll/models.py:239 +#: motion/templates/motion/poll_view.html:14 poll/models.py:236 +#: poll/models.py:238 msgid "undocumented" msgstr "non documenté" @@ -789,110 +792,102 @@ msgstr "bulletin de vote en PDF" msgid "Change status" msgstr "Modifier le statut" -#: assignment/templates/assignment/view.html:43 -#: assignment/templates/assignment/view.html:99 -#: assignment/templates/assignment/view.html:113 +#: assignment/templates/assignment/view.html:44 +#: assignment/templates/assignment/view.html:106 msgid "Remove candidate" msgstr "Enlever le candidat" -#: assignment/templates/assignment/view.html:48 +#: assignment/templates/assignment/view.html:51 +#, fuzzy +msgid "Mark candidate as not elected" +msgstr "Le candidat est élu" + +#: assignment/templates/assignment/view.html:57 #: assignment/templates/projector/Assignment.html:44 msgid "No candidates available." msgstr "Aucun candidat n'est disponible" -#: assignment/templates/assignment/view.html:60 +#: assignment/templates/assignment/view.html:69 msgid "Withdraw self candidature" msgstr "Retirer sa propre candidature" -#: assignment/templates/assignment/view.html:66 +#: assignment/templates/assignment/view.html:75 msgid "Self candidature" msgstr "Se proposer comme candidat" -#: assignment/templates/assignment/view.html:77 +#: assignment/templates/assignment/view.html:86 msgid "Add new participant" msgstr "Ajouter un nouveau participant" -#: assignment/templates/assignment/view.html:92 -msgid "Elected Candidates" -msgstr "Candidats bloqué" - -#: assignment/templates/assignment/view.html:104 -msgid "No elected candidates available." -msgstr "Aucun candidat n'est disponible" - -#: assignment/templates/assignment/view.html:109 +#: assignment/templates/assignment/view.html:102 msgid "Blocked Candidates" msgstr "Candidats bloqué" -#: assignment/templates/assignment/view.html:116 +#: assignment/templates/assignment/view.html:109 msgid "No blocked candidates available." msgstr "Aucun candidat n'est disponible" -#: assignment/templates/assignment/view.html:121 +#: assignment/templates/assignment/view.html:115 #: assignment/templates/projector/Assignment.html:52 msgid "Election results" msgstr "Résultat des élections" -#: assignment/templates/assignment/view.html:144 +#: assignment/templates/assignment/view.html:128 msgid "Publish/unpublish results" msgstr "Publier/dépublier les résultats" -#: assignment/templates/assignment/view.html:156 -#: assignment/templates/assignment/view.html:244 +#: assignment/templates/assignment/view.html:140 +#: assignment/templates/assignment/view.html:223 msgid "New ballot" msgstr "Nouveau vote" -#: assignment/templates/assignment/view.html:171 +#: assignment/templates/assignment/view.html:155 #: assignment/templates/projector/Assignment.html:69 msgid "Candidate is elected" msgstr "Le candidat est élu" -#: assignment/templates/assignment/view.html:190 +#: assignment/templates/assignment/view.html:174 #: assignment/templates/projector/Assignment.html:84 msgid "was not a
candidate" msgstr "n'était pas un
candidat" -#: assignment/templates/assignment/view.html:208 -#: assignment/templates/projector/Assignment.html:101 motion/views.py:804 +#: assignment/templates/assignment/view.html:191 +#: assignment/templates/projector/Assignment.html:100 motion/views.py:830 #: motion/templates/motion/view.html:82 #: motion/templates/projector/Motion.html:40 msgid "Invalid" msgstr "Invalide" -#: assignment/templates/assignment/view.html:239 -#: assignment/templates/projector/Assignment.html:128 -msgid "No ballots available." -msgstr "Aucun vote disponible." +#: assignment/templates/assignment/view.html:219 +#, fuzzy +msgid "No results available." +msgstr "Aucun résultat de sondage disponible" -#: assignment/templates/projector/Assignment.html:126 -msgid "Vote results are not published yet." -msgstr "" - -#: config/forms.py:24 +#: config/forms.py:22 msgid "Event name" msgstr "Nom de l'événement" -#: config/forms.py:30 +#: config/forms.py:28 msgid "Short description of event" msgstr "Une courte description de l'événement" -#: config/forms.py:38 +#: config/forms.py:36 msgid "Event date" msgstr "Date de l'événement" -#: config/forms.py:44 +#: config/forms.py:42 msgid "Event location" msgstr "Lieu de l'événement" -#: config/forms.py:50 +#: config/forms.py:48 msgid "Event organizer" msgstr "Organisateur de l'événement" -#: config/forms.py:55 +#: config/forms.py:53 msgid "Allow access for anonymous guest users" msgstr "Permettre l'accès anomyme" -#: config/forms.py:67 participant/forms.py:114 +#: config/forms.py:65 participant/forms.py:123 msgid "Welcome text" msgstr "Texte de bienvenue" @@ -900,47 +895,34 @@ msgstr "Texte de bienvenue" msgid "Can manage configuration" msgstr "Peut gérer la configuration" -#: config/models.py:84 +#: config/models.py:83 msgid "Presentation and assembly system" msgstr "" -#: config/models.py:89 +#: config/models.py:88 msgid "Welcome to OpenSlides" msgstr "Bienvenue sur OpenSlides!" -#: config/models.py:90 +#: config/models.py:89 msgid "[Place for your welcome text.]" msgstr "" -#: config/models.py:92 -#, python-format -msgid "Get professional support for OpenSlides on %s." -msgstr "Obtenez de l'aide professionnelle pour OpenSlides sur %s." - -#: config/models.py:107 +#: config/models.py:102 msgid "General" msgstr "Général" -#: config/models.py:131 config/templates/config/version.html:5 +#: config/models.py:126 config/templates/config/version.html:5 #: config/templates/config/version.html:8 -#: config/templates/config/version.html:11 motion/views.py:789 +#: config/templates/config/version.html:11 motion/views.py:815 #: motion/templates/motion/view.html:214 motion/templates/motion/view.html:244 msgid "Version" msgstr "Version" -#: config/views.py:79 -msgid "" -"Anonymous access enabled. Please modify the \"Anonymous\" group to fit your " -"required permissions." -msgstr "" -"L'accès anonyme a été activé. S'il vous plait, modifiez le groupe \"Anonymous" -"\" pour lui donner les droits nécéssaires" - -#: config/views.py:85 +#: config/views.py:69 msgid "General settings successfully saved." msgstr "Les paramètres généraux ont été enregistrés avec succès." -#: config/views.py:120 config/templates/config/base_config.html:7 +#: config/views.py:104 config/templates/config/base_config.html:7 msgid "Configuration" msgstr "Configuration" @@ -954,14 +936,15 @@ msgid "Event" msgstr "Evénement" #: config/templates/config/general.html:26 -msgid "Frontpage" -msgstr "Page d'accueil" +#, fuzzy +msgid "Welcome Widget" +msgstr "Texte de bienvenue" #: config/templates/config/general.html:41 msgid "System" msgstr "Système" -#: motion/forms.py:25 motion/models.py:542 motion/views.py:823 +#: motion/forms.py:25 motion/models.py:541 motion/views.py:849 #: motion/templates/motion/view.html:229 motion/templates/motion/view.html:249 #: motion/templates/projector/Motion.html:77 msgid "Reason" @@ -975,18 +958,18 @@ msgstr "Changement trivial" msgid "Trivial changes don't create a new version." msgstr "Des changement triviaux ne créent pas une nouvelle version." -#: motion/forms.py:35 motion/models.py:66 motion/views.py:742 +#: motion/forms.py:35 motion/models.py:63 motion/views.py:768 #: motion/templates/motion/overview.html:41 #: motion/templates/motion/view.html:18 #: motion/templates/projector/Motion.html:55 msgid "Submitter" msgstr "Requérant" -#: motion/forms.py:44 motion/views.py:762 motion/templates/motion/view.html:22 +#: motion/forms.py:44 motion/views.py:788 motion/templates/motion/view.html:22 msgid "Supporters" msgstr "Partisants" -#: motion/forms.py:50 participant/forms.py:102 +#: motion/forms.py:50 participant/forms.py:111 msgid "CSV File" msgstr "Fichier CSV" @@ -1028,68 +1011,68 @@ msgstr "" "Attention: Les changements triviaux perturbent le système d'autorisation de " "motion." -#: motion/models.py:45 +#: motion/models.py:42 msgid "Published" msgstr "Publié" -#: motion/models.py:46 +#: motion/models.py:43 msgid "Permitted" msgstr "Permis" -#: motion/models.py:47 motion/templates/motion/overview.html:24 +#: motion/models.py:44 motion/templates/motion/overview.html:24 #: motion/templates/motion/view.html:167 msgid "Accepted" msgstr "Accepté" -#: motion/models.py:48 motion/templates/motion/overview.html:25 +#: motion/models.py:45 motion/templates/motion/overview.html:25 #: motion/templates/motion/view.html:172 msgid "Rejected" msgstr "Rejeté" -#: motion/models.py:49 +#: motion/models.py:46 msgid "Withdrawed" msgstr "Retiré" -#: motion/models.py:50 motion/templates/motion/view.html:180 +#: motion/models.py:47 motion/templates/motion/view.html:180 msgid "Adjourned" msgstr "Ajourné" -#: motion/models.py:51 motion/templates/motion/view.html:183 +#: motion/models.py:48 motion/templates/motion/view.html:183 msgid "Not Concerned" msgstr "Non concerné" -#: motion/models.py:52 motion/templates/motion/view.html:186 +#: motion/models.py:49 motion/templates/motion/view.html:186 msgid "Commited a bill" msgstr "Transféré à (une commission)" -#: motion/models.py:53 +#: motion/models.py:50 msgid "Rejected (not authorized)" msgstr "Rejeté (non autorisé)" -#: motion/models.py:54 motion/templates/motion/overview.html:27 +#: motion/models.py:51 motion/templates/motion/overview.html:27 msgid "Needs Review" msgstr "Doit être revu" -#: motion/models.py:103 +#: motion/models.py:100 #, python-format msgid "Version %d authorized" msgstr "Version %d autorisée" -#: motion/models.py:110 +#: motion/models.py:107 #, python-format msgctxt "Rejected means not authorized" msgid "Version %d rejected" msgstr "Version %d rejetée" -#: motion/models.py:139 +#: motion/models.py:136 msgid "Searching for supporters." msgstr "Recherche de soutien" -#: motion/models.py:141 +#: motion/models.py:138 msgid "Not yet authorized." msgstr "N'est pas encore autorisé" -#: motion/models.py:143 +#: motion/models.py:140 msgid "Not yet authorized changes." msgstr "Les changements ne sont pas encore approuvés." @@ -1101,7 +1084,7 @@ msgstr "" "Changements triviaux à la version %(version)d; les champs modifiés: " "%(changed_fields)s" -#: motion/models.py:234 +#: motion/models.py:235 #, python-format msgid "Version %s created" msgstr "Version %s créée" @@ -1125,27 +1108,27 @@ msgstr "Partisants: +%s" msgid "Supporter: -%s" msgstr "Partisants: -%s" -#: motion/models.py:295 +#: motion/models.py:294 #, python-format msgid "Number set: %s" msgstr "Numéro inséré: %s" -#: motion/models.py:308 +#: motion/models.py:307 #, python-format msgid "Version %s authorized" msgstr "Version %s autorisée" -#: motion/models.py:322 +#: motion/models.py:319 #, python-format msgid "Version %s not authorized" msgstr "Version %s non autorisée" -#: motion/models.py:338 +#: motion/models.py:335 #, python-format msgid "The motion status is already '%s.'" msgstr "La motion a déja le statut '%s'." -#: motion/models.py:346 +#: motion/models.py:343 #, python-format msgid "" "The motion status is: '%(currentstatus)s'. You can not set the status to " @@ -1154,15 +1137,15 @@ msgstr "" "Le statut de la motion est: '%(currentstatus)s'. Vous ne pouvez pas le " "changer le statut sur '%(newstatus)s'." -#: motion/models.py:354 +#: motion/models.py:351 msgid "Status modified" msgstr "Statut modifié" -#: motion/models.py:446 +#: motion/models.py:443 motion/models.py:445 msgid "by" msgstr "par" -#: motion/models.py:454 motion/templates/motion/view.html:210 +#: motion/models.py:453 motion/templates/motion/view.html:210 #: motion/templates/motion/widget.html:27 #: motion/templates/projector/Motion.html:65 #: participant/templates/participant/personal_info_widget.html:13 @@ -1170,60 +1153,60 @@ msgstr "par" msgid "no number" msgstr "pas de nombre" -#: motion/models.py:455 motion/templates/motion/widget.html:23 +#: motion/models.py:454 motion/templates/motion/widget.html:23 #: participant/templates/participant/personal_info_widget.html:9 #: participant/templates/participant/personal_info_widget.html:28 msgid "motion" msgstr "motion" -#: motion/models.py:480 +#: motion/models.py:479 msgid "Poll created" msgstr "Sondage créé" -#: motion/models.py:531 +#: motion/models.py:530 msgid "Can see motions" msgstr "Peut voir les motions" -#: motion/models.py:532 +#: motion/models.py:531 msgid "Can create motions" msgstr "Peut créer des motions" -#: motion/models.py:533 +#: motion/models.py:532 msgid "Can support motions" msgstr "Peut soutenir les motions" -#: motion/models.py:534 +#: motion/models.py:533 msgid "Can manage motions" msgstr "Peut gérer les motions" -#: motion/models.py:601 +#: motion/models.py:600 msgid "The assembly may decide," msgstr "Je demande a l'Assemblée de décider sur..." -#: motion/models.py:604 motion/views.py:692 motion/views.py:917 -#: motion/templates/motion/base_motion.html:9 +#: motion/models.py:603 motion/views.py:718 motion/views.py:943 +#: motion/views.py:954 motion/templates/motion/base_motion.html:9 #: motion/templates/motion/overview.html:7 #: motion/templates/motion/overview.html:10 msgid "Motions" msgstr "Motions" -#: motion/views.py:180 +#: motion/views.py:173 msgid "You have not the necessary rights to create or edit motions." msgstr "Vous n'avez pas l'autorisation de créer ou modifier des motions." -#: motion/views.py:185 +#: motion/views.py:178 msgid "You can not edit this motion." msgstr "Vous ne pouvez pas modifier cette motion." -#: motion/views.py:248 +#: motion/views.py:236 msgid "New motion was successfully created." msgstr "La nouvelle motion a été créée avec succès." -#: motion/views.py:250 +#: motion/views.py:238 msgid "Motion was successfully modified." msgstr "La motion a été modifiée avec succès." -#: motion/views.py:264 +#: motion/views.py:252 msgid "" "Attention: Do you really want to edit this motion? The supporters will " "not be removed automatically because you can manage motions. Please " @@ -1234,7 +1217,7 @@ msgstr "" "gérer les motions. S'il vous plait vérifiez si les partisans sont valables " "après votre modification!" -#: motion/views.py:266 +#: motion/views.py:254 #, python-format msgid "" "Attention: Do you really want to edit this motion? All %s supporters " @@ -1243,151 +1226,181 @@ msgstr "" "Attention: Voulez-vous vraiment modifier cette motion? Tout les %s " "partisans seront supprimés! Essayez de convaincre les partisans à nouveau." -#: motion/views.py:298 +#: motion/views.py:286 msgid "Motion number was successfully set." msgstr "Le numéro de la motion a été mis avec succès." -#: motion/views.py:314 +#: motion/views.py:302 msgid "Motion was successfully authorized." msgstr "La motion a été autorisée avec succès." -#: motion/views.py:329 +#: motion/views.py:317 msgid "Motion was successfully rejected." msgstr "La motion a été rejetée avec succès. " -#: motion/views.py:345 +#: motion/views.py:333 #, python-format msgid "Motion status was set to: %s." msgstr "Le statut de la motion a été changé sur: b>%s
" -#: motion/views.py:361 +#: motion/views.py:349 msgid "Motion status was reset." msgstr "Statut de la motion a été remis à zéro." -#: motion/views.py:388 +#: motion/views.py:376 msgid "You can not support this motion." msgstr "Vous ne pouvez pas supporter cette motion. " -#: motion/views.py:391 +#: motion/views.py:379 msgid "You can not unsupport this motion." msgstr "Vous ne pouvez pas retirer votre support pour cette motion. " -#: motion/views.py:402 +#: motion/views.py:390 msgid "Do you really want to support this motion?" msgstr "Voulez-vous vraiment supporter cette motion?" -#: motion/views.py:404 +#: motion/views.py:392 msgid "Do you really want to unsupport this motion?" msgstr "Voulez-vous vraiment retirer votre support pour cette motion?" -#: motion/views.py:415 +#: motion/views.py:403 msgid "You have supported this motion successfully." msgstr "" "Vous supportez maintenant cette motion, vous avez vous ajouté avec succès." -#: motion/views.py:417 +#: motion/views.py:405 msgid "You have unsupported this motion successfully." msgstr "Vous avez retiré votre support pour cette motion avec succès. " -#: motion/views.py:431 +#: motion/views.py:419 msgid "New vote was successfully created." msgstr "Nouveau vote a été créé avec succès." -#: motion/views.py:447 +#: motion/views.py:435 msgid "Poll deleted" msgstr "Sondage supprimé" -#: motion/views.py:448 +#: motion/views.py:436 msgid "Poll was successfully deleted." msgstr "Le sondage a été supprimé avec succès." -#: motion/views.py:450 +#: motion/views.py:438 #, python-format msgid "the %s. poll" msgstr "le %s. sondage" -#: motion/views.py:491 motion/views.py:500 +#: motion/views.py:479 motion/views.py:488 #, python-format msgid "You can not delete motion %s." msgstr "Vous ne pouvez pas supprimer la motion %s." -#: motion/views.py:496 motion/views.py:504 +#: motion/views.py:484 motion/views.py:492 #, python-format msgid "Motion %s was successfully deleted." msgstr "Motion %s a été supprimé avec succès." -#: motion/views.py:506 +#: motion/views.py:494 msgid "Invalid request" msgstr "Demande invalide" -#: motion/views.py:530 +#: motion/views.py:518 msgid "Poll was updated" msgstr "Le sondage a été actualisé" -#: motion/views.py:547 +#: motion/views.py:535 #, python-format msgid "Version %s accepted." msgstr "Version %s acceptée." -#: motion/views.py:549 +#: motion/views.py:537 #, python-format msgid "Do you really want to authorize version %s?" msgstr "Voulez-vous vraiment autoriser cette version %s" -#: motion/views.py:559 +#: motion/views.py:547 #, python-format msgid "Version %s rejected." msgstr "Version %s rejetée." -#: motion/views.py:561 +#: motion/views.py:549 msgid "ERROR by rejecting the version." msgstr "ERREUR en rejetant la version." -#: motion/views.py:563 +#: motion/views.py:551 #, python-format msgid "Do you really want to reject version %s?" msgstr "Voulez vous vraiment rejeter la version %s?" -#: motion/views.py:593 motion/views.py:597 motion/views.py:603 -#: motion/views.py:606 participant/api.py:76 +#: motion/views.py:587 motion/views.py:591 motion/views.py:597 +#: motion/views.py:600 participant/api.py:81 #, python-format msgid "Ignoring malformed line %d in import file." msgstr "La ligne %d mal formée dans le fichier d'entrée a été ignorée" -#: motion/views.py:649 +#: motion/views.py:608 +#, python-format +msgid "Ignoring line %d because the assigned group may not act as a person." +msgstr "" + +#: motion/views.py:617 +#, fuzzy +msgid "Created by motion import." +msgstr "Peut créer des motions" + +#: motion/views.py:631 +#, python-format +msgid "" +"Ignoring line %d because it contains an incomplete first / last name pair." +msgstr "" + +#: motion/views.py:669 #, python-format msgid "%d motion was successfully imported." msgid_plural "%d motions were successfully imported." msgstr[0] "%d la motion a été importée avec succès." msgstr[1] "%d les motions ont été importées avec succès." -#: motion/views.py:652 +#: motion/views.py:672 #, python-format msgid "%d motion was successfully modified." msgid_plural "%d motions were successfully modified." msgstr[0] "%d la motion a été modifiée avec succès." msgstr[1] "%d les motions ont été modifiées avec succès." -#: motion/views.py:655 +#: motion/views.py:675 #, python-format msgid "%d new user was added." msgid_plural "%d new users were added." msgstr[0] "%d nouvel utilisateur a été créé." msgstr[1] "%d nouveaux utilisateurs ont été créés." -#: motion/views.py:659 participant/api.py:92 +#: motion/views.py:678 +#, fuzzy, python-format +msgid "%d new group was added." +msgid_plural "%d new groups were added." +msgstr[0] "%d nouvel utilisateur a été créé." +msgstr[1] "%d nouveaux utilisateurs ont été créés." + +#: motion/views.py:681 +#, python-format +msgid "%d group assigned to motions." +msgid_plural "%d groups assigned to motions." +msgstr[0] "" +msgstr[1] "" + +#: motion/views.py:685 participant/api.py:97 msgid "Import aborted because of severe errors in the input file." msgstr "" "l'importation a été interrompu en raison d'erreurs graves dans le fichier " "d'entrée" -#: motion/views.py:661 participant/api.py:94 +#: motion/views.py:687 participant/api.py:99 msgid "Import file has wrong character encoding, only UTF-8 is supported!" msgstr "" "Le fichier d'entrée a un mauvais encodage des caractères , seul UTF-8 est " "pris en charge" -#: motion/views.py:665 +#: motion/views.py:691 msgid "" "Attention: Existing motions will be modified if you import new motions with " "the same number." @@ -1395,7 +1408,7 @@ msgstr "" "Attention: Les motions existantes seront modifiées si vous importez de " "nouvelles motions avec le même numéro" -#: motion/views.py:666 +#: motion/views.py:692 msgid "" "Attention: Importing an motions without a number multiple times will create " "duplicates." @@ -1403,7 +1416,7 @@ msgstr "" "Attention: L'importation d'une motion sans numéro à plusieurs reprises " "créera des doublons." -#: motion/views.py:699 motion/views.py:837 +#: motion/views.py:725 motion/views.py:863 #: motion/templates/motion/poll_view.html:7 #: motion/templates/motion/poll_view.html:12 #: motion/templates/motion/view.html:7 motion/templates/motion/view.html:206 @@ -1413,21 +1426,21 @@ msgstr "" msgid "Motion" msgstr "Motion" -#: motion/views.py:713 motion/templates/motion/overview.html:84 +#: motion/views.py:739 motion/templates/motion/overview.html:84 msgid "No motions available." msgstr "Aucune motion disponible" -#: motion/views.py:718 motion/views.py:720 motion/views.py:735 -#: motion/views.py:737 motion/templates/motion/base_motion.html:24 +#: motion/views.py:744 motion/views.py:746 motion/views.py:761 +#: motion/views.py:763 motion/templates/motion/base_motion.html:24 #: motion/templates/projector/Motion.html:63 msgid "Motion No." msgstr "Motion No." -#: motion/views.py:752 +#: motion/views.py:778 msgid "Signature" msgstr "Signature" -#: motion/views.py:803 motion/templates/motion/base_motion.html:55 +#: motion/views.py:829 motion/templates/motion/base_motion.html:55 #: motion/templates/motion/poll_view.html:8 #: motion/templates/motion/poll_view.html:13 #: motion/templates/motion/view.html:66 motion/templates/motion/view.html:74 @@ -1435,21 +1448,21 @@ msgstr "Signature" msgid "Vote" msgstr "Vote" -#: motion/views.py:837 +#: motion/views.py:863 msgid "Poll" msgstr "Sondage" -#: motion/views.py:851 +#: motion/views.py:877 #, python-format msgid "Motion No. %s" msgstr "Motion No %s" -#: motion/views.py:853 +#: motion/views.py:879 #, python-format msgid "%d. Vote" msgstr "%d. Vote" -#: motion/views.py:910 +#: motion/views.py:936 msgid "Motion settings successfully saved." msgstr "Les paramètres des motions ont été enregistrés avec succès" @@ -1504,27 +1517,36 @@ msgid "Select a CSV file to import motions!" msgstr "Selectionnez un fichier CSV pour importer les motions!" #: motion/templates/motion/import.html:11 +#: participant/templates/participant/import.html:11 +msgid "Required comma separated values" +msgstr "" + +#: motion/templates/motion/import.html:12 +msgid "number, title, text, reason, first_name, last_name, is_group" +msgstr "" + +#: motion/templates/motion/import.html:14 +#, fuzzy msgid "" -"Required comma separated values: {number, title, text, reason, " -"first_name, last_name} (number and reason " -"are optional and may be empty)" +"number, reason and is_group are " +"optional and may be empty" msgstr "" "Les valeurs obligatoires, séparées par des virgules: {nombre, titre, " "texte, motivation, prénom, nom} (nombre et " "motivation sont facultatives et peuvent être laissées vides.)" -#: motion/templates/motion/import.html:13 -#: participant/templates/participant/import.html:13 +#: motion/templates/motion/import.html:16 +#: participant/templates/participant/import.html:14 msgid "Required CSV file encoding: UTF-8 (Unicode)." msgstr "Le fichier CSV requièrt un encodage de caractères UTF-8 (Unicode)" -#: motion/templates/motion/import.html:16 -#: participant/templates/participant/import.html:16 +#: motion/templates/motion/import.html:19 +#: participant/templates/participant/import.html:17 msgid "A CSV example file is available in OpenSlides Wiki." msgstr "Un exemple de fichier CSV est disponible sur le Wiki de Openslides. " -#: motion/templates/motion/import.html:23 -#: participant/templates/participant/import.html:23 +#: motion/templates/motion/import.html:26 +#: participant/templates/participant/import.html:24 msgid "Import" msgstr "Importation" @@ -1717,18 +1739,18 @@ msgstr "Aucun résultat de sondage disponible" msgid "Participant" msgstr "Participant" -#: participant/forms.py:26 participant/views.py:590 +#: participant/forms.py:27 participant/views.py:607 #: participant/templates/participant/group_overview.html:7 #: participant/templates/participant/group_overview.html:10 #: participant/templates/participant/user_detail.html:14 msgid "Groups" msgstr "Groupe" -#: participant/forms.py:44 +#: participant/forms.py:52 msgid "Permissions" msgstr "Permissions" -#: participant/forms.py:47 participant/views.py:530 +#: participant/forms.py:55 participant/views.py:546 participant/views.py:593 #: participant/templates/participant/base_participant.html:12 #: participant/templates/participant/overview.html:7 #: participant/templates/participant/overview.html:18 @@ -1736,198 +1758,218 @@ msgstr "Permissions" msgid "Participants" msgstr "Participants" -#: participant/forms.py:83 -msgid "You can not edit the name for the anonymous user" +#: participant/forms.py:92 +#, fuzzy +msgid "You can not edit the name for this group." msgstr "Vous ne pouvez pas modifier le de l'utilisateur anomyme." -#: participant/forms.py:87 +#: participant/forms.py:96 #, python-format msgid "Group name \"%s\" is reserved for internal use." msgstr "Ce nom de groupe \"%s\" est réservé pour une utilisation interne." -#: participant/forms.py:109 +#: participant/forms.py:118 msgid "System URL" msgstr "URL du système" -#: participant/forms.py:110 participant/forms.py:115 +#: participant/forms.py:119 participant/forms.py:124 msgid "Printed in PDF of first time passwords only." msgstr "" "Imprimé dans le PDF avec la liste des premiers mots de passe seulement." -#: participant/forms.py:118 +#: participant/forms.py:127 msgid "Sort participants by first name" msgstr "" -#: participant/forms.py:119 +#: participant/forms.py:128 msgid "Disable for sorting by last name" msgstr "" -#: participant/models.py:29 participant/templates/participant/overview.html:25 +#: participant/models.py:33 participant/templates/participant/overview.html:25 msgid "Male" msgstr "Masculin" -#: participant/models.py:30 participant/templates/participant/overview.html:26 +#: participant/models.py:34 participant/templates/participant/overview.html:26 msgid "Female" msgstr "Féminin" -#: participant/models.py:33 participant/templates/participant/overview.html:38 +#: participant/models.py:37 participant/templates/participant/overview.html:38 msgid "Delegate" msgstr "Délégué" -#: participant/models.py:34 participant/templates/participant/overview.html:39 +#: participant/models.py:38 participant/templates/participant/overview.html:39 msgid "Observer" msgstr "Observateur" -#: participant/models.py:35 participant/templates/participant/overview.html:40 +#: participant/models.py:39 participant/templates/participant/overview.html:40 msgid "Staff" msgstr "Personnel" -#: participant/models.py:36 participant/templates/participant/overview.html:41 +#: participant/models.py:40 participant/templates/participant/overview.html:41 msgid "Guest" msgstr "Invité" -#: participant/models.py:41 participant/templates/participant/overview.html:30 +#: participant/models.py:45 participant/templates/participant/overview.html:30 #: participant/templates/participant/overview.html:68 -msgid "Detail" +msgid "Structure level" msgstr "" -#: participant/models.py:42 +#: participant/models.py:46 msgid "Will be shown after the name." msgstr "Apparait après le nom." -#: participant/models.py:45 participant/templates/participant/overview.html:24 +#: participant/models.py:49 participant/templates/participant/overview.html:24 #: participant/templates/participant/user_detail.html:24 msgid "Gender" msgstr "Sexe" -#: participant/models.py:45 participant/models.py:48 participant/models.py:51 +#: participant/models.py:49 participant/models.py:52 participant/models.py:55 msgid "Only for filtering the participant list." msgstr "Seulement pour filtrer la liste des utilisateurs." -#: participant/models.py:48 +#: participant/models.py:52 msgid "Typ" msgstr "Type" -#: participant/models.py:50 participant/views.py:245 +#: participant/models.py:54 participant/views.py:255 #: participant/templates/participant/overview.html:45 #: participant/templates/participant/overview.html:70 #: participant/templates/participant/user_detail.html:34 msgid "Committee" msgstr "Comité" -#: participant/models.py:53 +#: participant/models.py:57 #: participant/templates/participant/user_detail.html:39 msgid "About me" msgstr "" -#: participant/models.py:54 +#: participant/models.py:58 msgid "Your profile text" msgstr "" -#: participant/models.py:57 +#: participant/models.py:61 msgid "Only for notes." msgstr "Seulement pour des notes." -#: participant/models.py:60 +#: participant/models.py:64 msgid "Default password" msgstr "Premier mot de passe" -#: participant/models.py:108 +#: participant/models.py:118 msgid "Can see participant" msgstr "Peut voir les participants" -#: participant/models.py:110 +#: participant/models.py:120 msgid "Can manage participant" msgstr "Peut gérer des participants" -#: participant/models.py:119 +#: participant/models.py:142 msgid "Use this group as participant" msgstr "" -#: participant/models.py:119 +#: participant/models.py:143 msgid "For example as submitter of a motion." msgstr "" -#: participant/models.py:201 +#: participant/models.py:237 msgid "Welcome to OpenSlides!" msgstr "Bienvenue sur OpenSlides!" -#: participant/views.py:240 +#: participant/views.py:207 +#, fuzzy +msgid "You can not delete yourself." +msgstr "Vous ne pouvez pas supprimer la motion %s." + +#: participant/views.py:228 +msgid "You can not deactivate yourself." +msgstr "" + +#: participant/views.py:231 +#, fuzzy +msgid "You can not deactivate the administrator." +msgstr "Vous ne pouvez pas modifier cette motion." + +#: participant/views.py:250 msgid "Participant-list" msgstr "Liste des participants" -#: participant/views.py:241 +#: participant/views.py:251 msgid "List of Participants" msgstr "La liste des participants" -#: participant/views.py:244 participant/templates/participant/overview.html:67 +#: participant/views.py:254 participant/templates/participant/overview.html:67 msgid "Last Name" msgstr "Nom" -#: participant/views.py:244 participant/templates/participant/overview.html:66 +#: participant/views.py:254 participant/templates/participant/overview.html:66 msgid "First Name" msgstr "Prénom" -#: participant/views.py:244 +#: participant/views.py:254 #: participant/templates/participant/group_overview.html:13 msgid "Group" msgstr "Groupe" -#: participant/views.py:244 participant/templates/participant/overview.html:37 +#: participant/views.py:254 participant/templates/participant/overview.html:37 #: participant/templates/participant/overview.html:69 #: participant/templates/participant/user_detail.html:29 msgid "Type" msgstr "Type" -#: participant/views.py:276 +#: participant/views.py:286 msgid "Participant-passwords" msgstr "Mot de passe du participant" -#: participant/views.py:298 +#: participant/views.py:308 msgid "Account for OpenSlides" msgstr "Compte pour OpenSlides" -#: participant/views.py:300 +#: participant/views.py:310 #, python-format msgid "for %s" msgstr "pour %s" -#: participant/views.py:303 +#: participant/views.py:313 #, python-format msgid "User: %s" msgstr "Utilisateur: %s" -#: participant/views.py:307 +#: participant/views.py:317 #, python-format msgid "Password: %s" msgstr "Mot de passe: %s" -#: participant/views.py:312 +#: participant/views.py:322 #, python-format msgid "URL: %s" msgstr "URL: %s" -#: participant/views.py:354 +#: participant/views.py:364 #, python-format msgid "%d new participants were successfully imported." msgstr "%d nouveaux participants ont été importés avec succès. " -#: participant/views.py:365 +#: participant/views.py:375 msgid "Do you really want to reset the password?" msgstr "Voulez-vous vraiment reinitialser le mot de passe?" -#: participant/views.py:378 +#: participant/views.py:388 #, python-format msgid "The Password for %s was successfully reset." msgstr "Le mot de passe de %s a été initialisé avec succès" -#: participant/views.py:457 +#: participant/views.py:445 +#, fuzzy +msgid "You can not delete this Group." +msgstr "Vous ne pouvez pas modifier cette motion." + +#: participant/views.py:473 msgid "Participants settings successfully saved." msgstr "" "Les modifications des paramètres des participants ont été appliquées avec " "succès" -#: participant/views.py:467 +#: participant/views.py:483 #, python-format msgid "" "Installation was successfully! Use %(user)s (password: %(password)s) for " @@ -1941,22 +1983,18 @@ msgstr "" "ce message apparaîtra toujours pour tout le monde et pourrait représenter un " "risque de sécurité." -#: participant/views.py:490 +#: participant/views.py:506 msgid "User settings successfully saved." msgstr "Les paramètres d'utilisateurs ont été enregistrés avec succès." -#: participant/views.py:512 +#: participant/views.py:528 msgid "Password successfully changed." msgstr "Le mot de passe a été changé avec succès." -#: participant/views.py:562 +#: participant/views.py:579 msgid "My motions and elections" msgstr "" -#: participant/views.py:576 -msgid "Users" -msgstr "Utilisateurs" - #: participant/templates/participant/base_participant.html:15 msgid "All participants" msgstr "Tout les participants" @@ -2003,7 +2041,7 @@ msgid "Edit participant" msgstr "Modifier le participant" #: participant/templates/participant/base_participant.html:50 -#: participant/templates/participant/overview.html:97 +#: participant/templates/participant/overview.html:98 msgid "Delete participant" msgstr "Supprimer le participant" @@ -2049,10 +2087,10 @@ msgstr "Aucun groupe n'est disponible" msgid "Select a CSV file to import participants!" msgstr "Selectionnez un fichier CSV pour importer des participants" -#: participant/templates/participant/import.html:11 +#: participant/templates/participant/import.html:12 +#, fuzzy msgid "" -"Required comma separated values: {first_name, last_name, gender, " -"group, type, committee, comment}" +"first_name, last_name, gender, structure level, type, committee, comment" msgstr "" "Valeurs obligatoires, séparées par des virgules: {prénom, nom, sexe, " "groupe, type, committé, commentaire}" @@ -2084,7 +2122,7 @@ msgstr "Continuer en tant qu'invité" msgid "Not specified" msgstr "Non spécifié" -#: participant/templates/participant/overview.html:53 projector/models.py:67 +#: participant/templates/participant/overview.html:53 projector/models.py:63 msgid "Active" msgstr "Actif" @@ -2107,15 +2145,15 @@ msgstr "de" msgid "Last Login" msgstr "Dernière connexion" -#: participant/templates/participant/overview.html:99 +#: participant/templates/participant/overview.html:102 msgid "Change status to inactive" msgstr "Changer le statut sur inactif" -#: participant/templates/participant/overview.html:102 +#: participant/templates/participant/overview.html:105 msgid "Change status to active" msgstr "Changer le statut sur actif" -#: participant/templates/participant/overview.html:111 +#: participant/templates/participant/overview.html:115 #: participant/templates/participant/user_widget.html:22 msgid "No participants available." msgstr "Aucun participant disponible" @@ -2165,6 +2203,11 @@ msgstr "" msgid "The participant has not logged in yet." msgstr "" +#: participant/templates/projector/GroupSlide.html:11 +#, fuzzy +msgid "participants" +msgstr "participant" + #: poll/models.py:95 msgid "Votes invalid" msgstr "Votes invalides" @@ -2173,43 +2216,40 @@ msgstr "Votes invalides" msgid "votes" msgstr "votes" -#: projector/models.py:53 +#: projector/models.py:50 msgid "Can manage the projector" msgstr "Peut gérer le projecteur" -#: projector/models.py:54 +#: projector/models.py:51 msgid "Can see the projector" msgstr "Peut voir le projecteur" -#: projector/models.py:55 +#: projector/models.py:52 msgid "Can see the dashboard" msgstr "Peut voir la vue d'ensemble" -#: projector/views.py:204 +#: projector/views.py:199 msgid "Errors in the form" msgstr "Erreurs dans le formulaire" -#: projector/views.py:383 projector/templates/projector/dashboard.html:17 +#: projector/views.py:375 projector/templates/projector/base_projector.html:7 +#: projector/templates/projector/base_projector.html:12 +#: projector/templates/projector/dashboard.html:17 msgid "Dashboard" msgstr "Vue d'ensemble" -#: projector/views.py:411 +#: projector/views.py:402 msgid "Projector live view" msgstr "Vue projecteur live" -#: projector/views.py:437 +#: projector/views.py:428 msgid "Overlays" msgstr "Superpositions" -#: projector/views.py:450 +#: projector/views.py:440 msgid "Custom Slides" msgstr "Diapositives personnalisées" -#: projector/templates/projector/base_projector.html:7 -#: projector/templates/projector/base_projector.html:12 -msgid "Projector" -msgstr "Projecteur" - #: projector/templates/projector/base_projector.html:15 msgid "Overview" msgstr "Vue d'ensemble" @@ -2221,7 +2261,6 @@ msgid "Select widgets" msgstr "" #: projector/templates/projector/base_projector.html:22 -#: templates/front_page.html:25 msgid "Projector view" msgstr "Vue projecteur" @@ -2259,27 +2298,23 @@ msgstr "Page d'accueil" msgid "New slide" msgstr "nouvelle diapositive" -#: projector/templates/projector/dashboard.html:21 -msgid "Adjust projector view" -msgstr "Régler la vue projecteur" - -#: projector/templates/projector/dashboard.html:22 +#: projector/templates/projector/live_view_widget.html:10 msgid "Zoom in" msgstr "Zoom avant" -#: projector/templates/projector/dashboard.html:25 +#: projector/templates/projector/live_view_widget.html:13 msgid "Zoom out" msgstr "Zoom arrière" -#: projector/templates/projector/dashboard.html:28 +#: projector/templates/projector/live_view_widget.html:18 msgid "Scroll text up" msgstr "Faire défiler le texte vers le haut" -#: projector/templates/projector/dashboard.html:31 +#: projector/templates/projector/live_view_widget.html:21 msgid "Scroll text down" msgstr "Faire défiler le texte vers le bas" -#: projector/templates/projector/dashboard.html:34 +#: projector/templates/projector/live_view_widget.html:26 msgid "Reset projector view" msgstr "Remettre la vue projecteur à zéro" @@ -2300,8 +2335,7 @@ msgstr "N'a pas pu trouver la page." msgid "Server Error" msgstr "Erreur du serveur" -#: templates/base.html:21 templates/front_page.html:6 -#: templates/front_page.html.py:22 +#: templates/base.html:21 msgid "Home" msgstr "Accueil" @@ -2313,60 +2347,107 @@ msgstr "Déconnecter" msgid "Welcome" msgstr "Bienvenue" -#: templates/front_page.html:12 -msgid "You have access to the following pages:" -msgstr "Vous avez accès aux pages suivantes:" +#: templates/base.html:79 +msgid "" +"Get professional " +"support for OpenSlides." +msgstr "" -#: utils/pdf.py:225 -msgid "%Y-%m-%d %H:%Mh" -msgstr "%d-%m-%Y %H:%Mh" - -#: utils/pdf.py:226 +#: utils/pdf.py:227 #, python-format -msgid "Printed: %s" -msgstr "Imprimé: %s" +msgid "As of: %s" +msgstr "" -#: utils/pdf.py:237 utils/pdf.py:246 +#: utils/pdf.py:238 utils/pdf.py:247 #, python-format msgid "Page %s" msgstr "Page %s" -#: utils/utils.py:66 utils/views.py:290 +#: utils/utils.py:69 utils/views.py:287 #, python-format msgid "Do you really want to delete %s?" msgstr "Voulez-vous vraiment supprimer %s?" -#: utils/utils.py:111 +#: utils/utils.py:116 msgid "Sorry, you have no rights to see this page." msgstr "Désolé, vous n'avez pas le droit de voir cette page" -#: utils/views.py:109 +#: utils/views.py:106 msgid "Are you sure?" msgstr "" -#: utils/views.py:110 +#: utils/views.py:107 msgid "Thank you for your answer" msgstr "" -#: utils/views.py:247 +#: utils/views.py:244 #, python-format msgid "%s was successfully modified." msgstr "%s a été modifié avec succès." -#: utils/views.py:278 +#: utils/views.py:275 #, python-format msgid "%s was successfully created." msgstr "%s a été créé avec succès." -#: utils/views.py:296 +#: utils/views.py:293 #, python-format msgid "%s was successfully deleted." msgstr "%s a été supprimé avec succès" -#: utils/views.py:312 +#: utils/views.py:308 msgid "undefined-filename" msgstr "nom de fichier non-déterminé" -#: utils/jsonfield/fields.py:21 +#: utils/jsonfield/fields.py:22 msgid "Enter valid JSON" msgstr "Entre une JSON valide" + +#~ msgid "Assignments" +#~ msgstr "Assignements" + +#~ msgid "posts" +#~ msgstr "postes" + +#~ msgid "candidates" +#~ msgstr "Candidats" + +#~ msgid "Elected Candidates" +#~ msgstr "Candidats bloqué" + +#~ msgid "No elected candidates available." +#~ msgstr "Aucun candidat n'est disponible" + +#~ msgid "No ballots available." +#~ msgstr "Aucun vote disponible." + +#~ msgid "Get professional support for OpenSlides on %s." +#~ msgstr "Obtenez de l'aide professionnelle pour OpenSlides sur %s." + +#~ msgid "" +#~ "Anonymous access enabled. Please modify the \"Anonymous\" group to fit " +#~ "your required permissions." +#~ msgstr "" +#~ "L'accès anonyme a été activé. S'il vous plait, modifiez le groupe " +#~ "\"Anonymous\" pour lui donner les droits nécéssaires" + +#~ msgid "Frontpage" +#~ msgstr "Page d'accueil" + +#~ msgid "Users" +#~ msgstr "Utilisateurs" + +#~ msgid "Projector" +#~ msgstr "Projecteur" + +#~ msgid "Adjust projector view" +#~ msgstr "Régler la vue projecteur" + +#~ msgid "You have access to the following pages:" +#~ msgstr "Vous avez accès aux pages suivantes:" + +#~ msgid "%Y-%m-%d %H:%Mh" +#~ msgstr "%d-%m-%Y %H:%Mh" + +#~ msgid "Printed: %s" +#~ msgstr "Imprimé: %s" From 3c54d1fd655d9ccc4f9b48484f914443050662f3 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 27 Nov 2012 22:05:06 +0100 Subject: [PATCH 191/222] Updated INSTALL to install OpenSlides via Python Package Index (PyPI) --- INSTALL.txt | 119 ++++++++++++++++++++-------------------------------- 1 file changed, 45 insertions(+), 74 deletions(-) diff --git a/INSTALL.txt b/INSTALL.txt index 68ef8416a..512fae243 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -3,15 +3,56 @@ Installation Instructions for OpenSlides 1.3 Content ------- -I. Installation on Windows (32/64bit) -II. Installation on GNU/Linux and MacOSX +I. Installation on GNU/Linux and MacOSX +II. Installation on Windows (32/64bit) If you need help ask on OpenSlides users mailing list. See http://openslides.org for more information. -I. Installation on Windows (32/64bit) -------------------------------------- +I. Installation on GNU/Linux and MacOSX +---------------------------------------- + +Make sure that you have installed Python (>= 2.5) on your system. + +You can setup a virtualenv environment to install OpenSlides as non-root user. +Run before you start install OpenSlides: + + $ virtualenv .venv + $ source .venv/bin/activate + + + 1. Install OpenSlides: + + $ pip install openslides + + OpenSlides will installed the following required python packages: + + Django + + django-mptt + + ReportLab Toolkit + + Python Imaging Library (PIL) + + 2. Start OpenSlides server and open URL in your default browser: + + $ openslides + + If you run this command the first time a new database and the + admin account are created. Please change the password after + first login! + + Username: admin + Password: admin + + Use 'openslides --help' to show all start options. + + +II. Installation on Windows (32/64bit) +-------------------------------------- + +NOTE: There is a portable version of OpenSlides for Windows which does not +required any install steps! If there is a reason that you can not use the +portable version you should run the following install steps. + 1. Install requirements: @@ -76,73 +117,3 @@ I. Installation on Windows (32/64bit) Use 'python start.py --help' to show all start options. - -II. Installation on GNU/Linux and MacOSX ----------------------------------------- - - 1. Install requirements: - - OpenSlides requires following programs, which should be - installed first: - + Python Programming Language 2 (>= 2.5) - + virtualenv (>= 1.4.1) - + ReportLab Toolkit - + Python Imaging Library (PIL) - - E.g. for ubuntu run: - $ sudo apt-get install python python-virtualenv python-reportlab python-imaging - - 2. Get OpenSlides: - - a) Download latest OpenSlides release from http://openslides.org. - - OR - - b) Clone development version from OpenSlides' github repository - https://github.com/OpenSlides/OpenSlides. - This requires Git, see http://git-scm.com/. - Open command line (cmd) and run: - - git clone git://github.com/OpenSlides/OpenSlides.git - - 3. Setup your virtual environment with virtualenv: - - Go to the (extracted/cloned) root directory of OpenSlides - and create virtualenv environment: - - $ virtualenv .venv - - For virtualenv >= 1.7 use instead: - $ virtualenv --system-site-packages .venv - - 4. Activate the virtual environment: - - $ source .venv/bin/activate - - 5. Install the required python-packages: - - $ pip install django django-mptt - - If you use python < 2.6 you also have to install simplejson: - $ pip install simplejson - - If requirements reportlab or PIL still missing (see 1.): - $ pip install reportlab pil - - 6. Start OpenSlides server and open URL in your default browser: - - $ python start.py - - If you run this script the first time a new database and the - admin account are created. Please change the password after - first login! - - Username: admin - Password: admin - - Use 'python start.py --help' to show all start options. - - 7. Restart OpenSlides: - - To restart OpenSlides after closing the terminal activate the - virtual environment (see 4.) before starting the server (see 6.). From 29b37dad749469ecc5241ada3c4407414f441c1b Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 27 Nov 2012 22:31:41 +0100 Subject: [PATCH 192/222] Fixed file name and path to renamed groups_de.json file. --- extras/win32-portable/prepare_portable.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extras/win32-portable/prepare_portable.py b/extras/win32-portable/prepare_portable.py index 6554a4939..dbdb15da9 100644 --- a/extras/win32-portable/prepare_portable.py +++ b/extras/win32-portable/prepare_portable.py @@ -307,8 +307,8 @@ def main(): shutil.copyfile("extras/win32-portable/openslides.exe", os.path.join(odir, "openslides.exe")) - shutil.copyfile("initial_data.json", - os.path.join(odir, "initial_data.json")) + shutil.copyfile("openslides/participant/fixtures/groups_de.json", + os.path.join(odir, "groups_de.json")) copy_dlls(odir) copy_msvcr(odir) From e7c47395bbd5dab21c3614e4f0dd5756c8e2d260 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Tue, 27 Nov 2012 22:46:54 +0100 Subject: [PATCH 193/222] Gave the empty user all the attributes it needs --- openslides/utils/person/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openslides/utils/person/__init__.py b/openslides/utils/person/__init__.py index e262022b4..430f04c91 100644 --- a/openslides/utils/person/__init__.py +++ b/openslides/utils/person/__init__.py @@ -21,7 +21,7 @@ __all__ = ['receive_persons', 'generate_person_id', 'get_person', 'Person', 'PersonField', 'PersonMixin', 'EmptyPerson'] -class EmptyPerson(PersonMixin): +class EmptyPerson(PersonMixin, Person): @property def person_id(self): return 'empty' From a010df5d1ffc1d2d65ce5311526ec9c094d952f2 Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 27 Nov 2012 22:54:07 +0100 Subject: [PATCH 194/222] Reverted person.sort_name AttributeError fix (e0ce1052c0031b24927599d7f707962a206c0ddb) --- openslides/assignment/models.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openslides/assignment/models.py b/openslides/assignment/models.py index bd5d64622..56269b601 100644 --- a/openslides/assignment/models.py +++ b/openslides/assignment/models.py @@ -152,10 +152,7 @@ class Assignment(models.Model, SlideMixin): participants = [] for candidate in candidates.all(): participants.append(candidate.person) - try: - participants.sort(key=lambda person: person.sort_name) - except AttributeError: - pass + participants.sort(key=lambda person: person.sort_name) return participants #return candidates.values_list('person', flat=True) From 7b837fd38f57a28b83484bb98d8fa7efcb04209a Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Tue, 27 Nov 2012 22:55:41 +0100 Subject: [PATCH 195/222] Added extra line --- AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 41bd3f5df..f4eeb7de7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -6,4 +6,4 @@ Authors of OpenSlides in chronological order of first contribution: René Köcher Andy Kittner Moira Brülisauer (French translation) - Alexis Roussel (French translation) \ No newline at end of file + Alexis Roussel (French translation) From 8306e7bf6e2464ef67e3496cfc172ff72e39e270 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Wed, 28 Nov 2012 13:59:14 +0100 Subject: [PATCH 196/222] Don't allow to remove the registered group --- .../participant/templates/participant/base_participant.html | 2 +- openslides/participant/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openslides/participant/templates/participant/base_participant.html b/openslides/participant/templates/participant/base_participant.html index a0f318179..751c02a3a 100644 --- a/openslides/participant/templates/participant/base_participant.html +++ b/openslides/participant/templates/participant/base_participant.html @@ -66,7 +66,7 @@ {# delete group #} - {% if group.name != 'Anonymous' %} + {% if group.name|lower != 'anonymous' and group.name|lower != 'registered' %}
  • {% trans 'Delete group' %}
  • diff --git a/openslides/participant/views.py b/openslides/participant/views.py index c0fa8d6c5..34cb032a0 100644 --- a/openslides/participant/views.py +++ b/openslides/participant/views.py @@ -441,7 +441,7 @@ class GroupDeleteView(DeleteView): url = 'user_group_overview' def pre_redirect(self, request, *args, **kwargs): - if self.get_object().name.lower() == 'anonymous': + if self.get_object().name.lower() in ['anonymous', 'registered']: messages.error(request, _("You can not delete this Group.")) else: super(GroupDeleteView, self).pre_redirect(request, *args, **kwargs) From d53017eea8cad572b470d50433eb3115040c68e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Wed, 28 Nov 2012 18:02:33 +0100 Subject: [PATCH 197/222] Get git commit id also in detached head mode. --- openslides/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openslides/__init__.py b/openslides/__init__.py index 80ed9bb5e..b4ae8af8c 100644 --- a/openslides/__init__.py +++ b/openslides/__init__.py @@ -40,7 +40,7 @@ def get_git_commit_id(): """ try: git_head = open('.git/HEAD', 'r').read().rstrip() - if True: #starts with 'ref: ' + if git_head[:5] == 'ref: ': git_commit_id = open('.git/%s' % git_head[5:], 'r').read().rstrip() else: git_commit_id = git_head From 728fd4d3688ecd47e22c50e3e535d3b6e7d3bc92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Wed, 28 Nov 2012 18:46:47 +0100 Subject: [PATCH 198/222] Update INSTALL.txt --- INSTALL.txt | 122 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 102 insertions(+), 20 deletions(-) diff --git a/INSTALL.txt b/INSTALL.txt index 512fae243..8a4cdad95 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -3,36 +3,47 @@ Installation Instructions for OpenSlides 1.3 Content ------- -I. Installation on GNU/Linux and MacOSX -II. Installation on Windows (32/64bit) + +I. Installation on GNU/Linux and MacOSX using the Python Package Index (PyPI) +II. Installation on GNU/Linux and MacOSX using the sources +III. Installation on Windows (32/64bit) If you need help ask on OpenSlides users mailing list. See http://openslides.org for more information. -I. Installation on GNU/Linux and MacOSX ----------------------------------------- +I. Installation on GNU/Linux and MacOSX using the Python Package Index (PyPI) +----------------------------------------------------------------------------- -Make sure that you have installed Python (>= 2.5) on your system. + 1. Check requirements: -You can setup a virtualenv environment to install OpenSlides as non-root user. -Run before you start install OpenSlides: + Make sure that you have installed Python (>= 2.5) on your system. - $ virtualenv .venv - $ source .venv/bin/activate + 2. Set up virtual environment with virtualenv (optional): + You can setup a virtual environment to install OpenSlides as + non-root user. + + E. g. for ubuntu run: + $ sudo apt-get install python-virtualenv + + To setup and activate the virtual environment, create your + OpenSlides directory, change to it and run: + + $ virtualenv .venv + $ source .venv/bin/activate + + 3. Install OpenSlides: - 1. Install OpenSlides: - $ pip install openslides - - OpenSlides will installed the following required python packages: + + OpenSlides will install the following required python packages: + Django + django-mptt + ReportLab Toolkit + Python Imaging Library (PIL) - 2. Start OpenSlides server and open URL in your default browser: + 4. Start OpenSlides server and open URL in your default browser: $ openslides @@ -46,8 +57,80 @@ Run before you start install OpenSlides: Use 'openslides --help' to show all start options. -II. Installation on Windows (32/64bit) --------------------------------------- +II. Installation on GNU/Linux and MacOSX using the sources +---------------------------------------------------------- + + 1. Install requirements: + + OpenSlides requires following programs, which should be + installed first: + + Python Programming Language 2 (>= 2.5) + + virtualenv (>= 1.4.1) + + ReportLab Toolkit + + Python Imaging Library (PIL) + + E. g. for ubuntu run: + $ sudo apt-get install python python-virtualenv python-reportlab python-imaging + + 2. Get OpenSlides: + + a) Download latest OpenSlides release from http://openslides.org. + + OR + + b) Clone development version from OpenSlides' github repository + https://github.com/OpenSlides/OpenSlides. This requires Git, + see http://git-scm.com/. + + E. g. for ubuntu run: + $ sudo apt-get install git + $ git clone git://github.com/OpenSlides/OpenSlides.git OpenSlides + + 3. Setup your virtual environment with virtualenv: + + Go to the (extracted/cloned) root directory of OpenSlides + and create virtualenv environment: + + $ virtualenv .venv + + For virtualenv >= 1.7 use instead: + $ virtualenv --system-site-packages .venv + + 4. Activate the virtual environment: + + $ source .venv/bin/activate + + 5. Install the required python-packages: + + $ pip install django django-mptt + + If you use python < 2.6 you also have to install simplejson: + $ pip install simplejson + + If requirements reportlab or PIL still missing (see 1.): + $ pip install reportlab pil + + 6. Start OpenSlides server and open URL in your default browser: + + $ python start.py + + If you run this script the first time a new database and the + admin account are created. Please change the password after + first login! + + Username: admin + Password: admin + + Use 'python start.py --help' to show all start options. + + 7. Restart OpenSlides: + + To restart OpenSlides after closing the terminal activate the + virtual environment (see 4.) before starting the server (see 6.). + + +III. Installation on Windows (32/64bit) +--------------------------------------- NOTE: There is a portable version of OpenSlides for Windows which does not required any install steps! If there is a reason that you can not use the @@ -65,7 +148,6 @@ portable version you should run the following install steps. + Django + django-mptt - a) Download and run 32bit MSI installer from http://www.python.org/: http://python.org/ftp/python/2.7.3/python-2.7.3.msi @@ -98,8 +180,9 @@ portable version you should run the following install steps. OR b) Clone development version from OpenSlides' github repository - https://github.com/OpenSlides/OpenSlides. - This requires Git, see http://git-scm.com/. + https://github.com/OpenSlides/OpenSlides. This requires Git, + see http://git-scm.com/. + Open command line (cmd) and run: git clone git://github.com/OpenSlides/OpenSlides.git @@ -116,4 +199,3 @@ portable version you should run the following install steps. Password: admin Use 'python start.py --help' to show all start options. - From 638c729dce1a37555b74b61b56ff64eb66dac438 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Wed, 28 Nov 2012 19:20:43 +0100 Subject: [PATCH 199/222] fixed manage.py for windows --- manage.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/manage.py b/manage.py index 5ddfd35aa..af82b6f37 100644 --- a/manage.py +++ b/manage.py @@ -8,9 +8,10 @@ """ import os, sys +from django.core.management import execute_from_command_line +from openslides.main import get_user_config_path, setup_django_environment if __name__ == "__main__": - sys.path.append(os.path.join(os.path.expanduser('~'), '.config', 'openslides')) - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings") - from django.core.management import execute_from_command_line + setup_django_environment( + get_user_config_path('openslides', 'settings.py')) execute_from_command_line(sys.argv) From a1b3e1c4228b79f9397c517e99bcc172a8e257cd Mon Sep 17 00:00:00 2001 From: Emanuel Schuetze Date: Thu, 29 Nov 2012 15:00:06 +0100 Subject: [PATCH 200/222] Added python 2.5 support for with_statement. (Fixed install error during 'pip install openslides' on python 2.5 systems.) --- setup.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/setup.py b/setup.py index ed1c3a018..24973a0bf 100644 --- a/setup.py +++ b/setup.py @@ -7,6 +7,9 @@ :license: GNU GPL, see LICENSE for more details. """ +# for python 2.5 support +from __future__ import with_statement + from setuptools import setup from setuptools import find_packages from openslides import get_version From e76ec5e975db710d4b779dc2b73923bc821477e8 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 29 Nov 2012 15:01:49 +0100 Subject: [PATCH 201/222] Added a new command to the startscript to show the version --- openslides/main.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/openslides/main.py b/openslides/main.py index f7818b7ab..bc23fb3bd 100755 --- a/openslides/main.py +++ b/openslides/main.py @@ -27,6 +27,8 @@ import webbrowser import django.conf from django.core.management import execute_from_command_line +from openslides import get_version + CONFIG_TEMPLATE = """#!/usr/bin/env python # -*- coding: utf-8 -*- @@ -78,21 +80,27 @@ def process_options(argv=None): parser = optparse.OptionParser( description="Run openslides using django's builtin webserver") - parser.add_option("-a", "--address", help="IP Address to listen on") - parser.add_option("-p", "--port", type="int", help="Port to listen on") + parser.add_option("-a", "--address", help="IP Address to listen on.") + parser.add_option("-p", "--port", type="int", help="Port to listen on.") parser.add_option( "--syncdb", action="store_true", - help="Update/create database before starting the server") + help="Update/create database before starting the server.") parser.add_option( "--reset-admin", action="store_true", - help="Make sure the user 'admin' exists and uses 'admin' as password") + help="Make sure the user 'admin' exists and uses 'admin' as password.") parser.add_option( "-s", "--settings", help="Path to the openslides configuration.") parser.add_option( "--no-reload", action="store_true", - help="Do not reload the development server") + help="Do not reload the development server.") + parser.add_option( + "--version", action="store_true", + help="Show version and exit.") opts, args = parser.parse_args(argv) + if opts.version: + print get_version() + exit(0) if args: sys.stderr.write("This command does not take arguments!\n\n") parser.print_help() From b9ab6502c1a74a252c3e82fb8129d9f7d5fe5a0b Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 29 Nov 2012 16:39:51 +0100 Subject: [PATCH 202/222] Updated the INSTALL.txt for windows with pypi --- INSTALL.txt | 43 ++++++++++++------------------------------- 1 file changed, 12 insertions(+), 31 deletions(-) diff --git a/INSTALL.txt b/INSTALL.txt index 8a4cdad95..f8bbc6f3d 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -129,24 +129,20 @@ II. Installation on GNU/Linux and MacOSX using the sources virtual environment (see 4.) before starting the server (see 6.). -III. Installation on Windows (32/64bit) ---------------------------------------- +III. Installation on Windows (32bit) using the Python Package Index (PyPI) +----------------------------------------------------------------------------- -NOTE: There is a portable version of OpenSlides for Windows which does not -required any install steps! If there is a reason that you can not use the +NOTE: There is a portable version of OpenSlides for Windows which does not +required any install steps! If there is a reason that you can not use the portable version you should run the following install steps. 1. Install requirements: - OpenSlides requires following programs, which should be + The OpenSlides install requires following programs, which should be installed first: + Python Programming Language 2 (>= 2.5), + Setuptools - + ReportLab Toolkit - + Python Imaging Library (PIL) - + Django - + django-mptt a) Download and run 32bit MSI installer from http://www.python.org/: @@ -163,33 +159,18 @@ portable version you should run the following install steps. http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11.win32-py2.7.exe - d) Install ReportLab Toolkit, Python Imaging Library (PIL), Django - and django-mptt: + + 2. Install OpenSlides: Open command line (cmd) and run: - easy_install django django-mptt reportlab pil - - If you use a 64bit version of Python, you have to install reportlab - and PIL manually - without using easy_install. - - 2. Get OpenSlides: - - a) Download latest OpenSlides release from http://openslides.org. - - OR - - b) Clone development version from OpenSlides' github repository - https://github.com/OpenSlides/OpenSlides. This requires Git, - see http://git-scm.com/. - - Open command line (cmd) and run: - - git clone git://github.com/OpenSlides/OpenSlides.git + easy_install openslides 3. Start OpenSlides server and open URL in your default browser: - python start.py + Open command line (cmd) and run: + + openslides If you run this script the first time a new database and the admin account are created. Please change the password after @@ -198,4 +179,4 @@ portable version you should run the following install steps. Username: admin Password: admin - Use 'python start.py --help' to show all start options. + Use 'openslides --help' to show all start options. From 4410e454c8442718cce5a7f34a756d7a0c223f5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Sat, 1 Dec 2012 13:39:29 +0100 Subject: [PATCH 203/222] Update test for version string. --- openslides/__init__.py | 6 ++++-- tests/test_init.py | 28 +++++++++++++++++++--------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/openslides/__init__.py b/openslides/__init__.py index b4ae8af8c..fd88160f2 100644 --- a/openslides/__init__.py +++ b/openslides/__init__.py @@ -9,13 +9,15 @@ VERSION = (1, 3, 0, 'final', 0) # During development it is the next release RELEASE = False -def get_version(version=None): +def get_version(version=None, release=None): """ Derives a PEP386-compliant version number from VERSION. Adds id of the current git commit. """ if version is None: version = VERSION + if release is None: + release = RELEASE assert len(version) == 5 assert version[3] in ('alpha', 'beta', 'rc', 'final') # Now build the two parts of the version number: @@ -29,7 +31,7 @@ def get_version(version=None): sub = mapping[version[3]] + str(version[4]) else: sub = '' - if not RELEASE: + if not release: sub += '-dev' return main + sub diff --git a/tests/test_init.py b/tests/test_init.py index 6155716f1..411860d79 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -9,15 +9,25 @@ from django.test import TestCase -from openslides import get_version +from openslides import get_version, get_git_commit_id class InitTest(TestCase): def test_get_version(self): - self.assertEqual(get_version((1, 3, 0, 'beta', 2)), '1.3-beta2') - self.assertEqual(get_version((1, 0, 0, 'final', 0)), '1.0') - self.assertEqual(get_version((2, 5, 3, 'alpha', 0)), '2.5.3-alpha0') - git_version = get_version((2, 5, 0, 'dev', 0)) - if 'unknown' in git_version: - self.assertEqual(len(git_version), 14) - else: - self.assertEqual(len(git_version), 47) + """ + Tests the method during development process and for releases. + """ + self.assertEqual(get_version(version=(1, 3, 0, 'beta', 2), release=False), '1.3b2-dev') + self.assertEqual(get_version(version=(1, 0, 0, 'final', 0), release=False), '1.0-dev') + self.assertEqual(get_version(version=(2, 5, 3, 'alpha', 0), release=False), '2.5.3a0-dev') + self.assertEqual(get_version(version=(1, 3, 0, 'beta', 2), release=True), '1.3b2') + self.assertEqual(get_version(version=(1, 0, 0, 'final', 0), release=True), '1.0') + self.assertEqual(get_version(version=(2, 5, 3, 'alpha', 0), release=True), '2.5.3a0') + self.assertEqual(get_version(version=(2, 5, 3, 'final', 0), release=True), '2.5.3') + + def test_get_git_commit_id(self): + """ + Tests the lenght of the git commit id. + """ + git_commit_id = get_git_commit_id() + if not git_commit_id == 'unknown': + self.assertEqual(len(git_commit_id), 40) From c9956f6380ea6ae34072dc19a0c550ef8979761c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Sat, 1 Dec 2012 13:51:00 +0100 Subject: [PATCH 204/222] Clean up INSTALL --- INSTALL.txt | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/INSTALL.txt b/INSTALL.txt index f8bbc6f3d..076e088c0 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -6,7 +6,7 @@ Content I. Installation on GNU/Linux and MacOSX using the Python Package Index (PyPI) II. Installation on GNU/Linux and MacOSX using the sources -III. Installation on Windows (32/64bit) +III. Installation on Windows (32bit) using the Python Package Index (PyPI) If you need help ask on OpenSlides users mailing list. See http://openslides.org for more information. @@ -17,14 +17,15 @@ I. Installation on GNU/Linux and MacOSX using the Python Package Index (PyPI) 1. Check requirements: - Make sure that you have installed Python (>= 2.5) on your system. + Make sure that you have installed Python Programming Language 2 + (>= 2.5) on your system. - 2. Set up virtual environment with virtualenv (optional): + 2. Setup a virtual environment with virtualenv (optional): You can setup a virtual environment to install OpenSlides as non-root user. - E. g. for ubuntu run: + E. g. for Ubuntu run: $ sudo apt-get install python-virtualenv To setup and activate the virtual environment, create your @@ -69,7 +70,7 @@ II. Installation on GNU/Linux and MacOSX using the sources + ReportLab Toolkit + Python Imaging Library (PIL) - E. g. for ubuntu run: + E. g. for Ubuntu run: $ sudo apt-get install python python-virtualenv python-reportlab python-imaging 2. Get OpenSlides: @@ -82,11 +83,11 @@ II. Installation on GNU/Linux and MacOSX using the sources https://github.com/OpenSlides/OpenSlides. This requires Git, see http://git-scm.com/. - E. g. for ubuntu run: + E. g. for Ubuntu run: $ sudo apt-get install git $ git clone git://github.com/OpenSlides/OpenSlides.git OpenSlides - 3. Setup your virtual environment with virtualenv: + 3. Setup a virtual environment with virtualenv: Go to the (extracted/cloned) root directory of OpenSlides and create virtualenv environment: @@ -130,18 +131,17 @@ II. Installation on GNU/Linux and MacOSX using the sources III. Installation on Windows (32bit) using the Python Package Index (PyPI) ------------------------------------------------------------------------------ +-------------------------------------------------------------------------- NOTE: There is a portable version of OpenSlides for Windows which does not required any install steps! If there is a reason that you can not use the portable version you should run the following install steps. - 1. Install requirements: The OpenSlides install requires following programs, which should be installed first: - + Python Programming Language 2 (>= 2.5), + + Python Programming Language 2 (>= 2.5) + Setuptools a) Download and run 32bit MSI installer from http://www.python.org/: @@ -159,7 +159,6 @@ portable version you should run the following install steps. http://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11.win32-py2.7.exe - 2. Install OpenSlides: Open command line (cmd) and run: From a5022a3f001436322d7a08fd596bc7df9067211e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Sat, 1 Dec 2012 14:05:19 +0100 Subject: [PATCH 205/222] Fix pep8 in openslides/__init__.py --- openslides/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openslides/__init__.py b/openslides/__init__.py index fd88160f2..f32ad47e6 100644 --- a/openslides/__init__.py +++ b/openslides/__init__.py @@ -5,7 +5,7 @@ :license: GNU GPL, see LICENSE for more details. """ -VERSION = (1, 3, 0, 'final', 0) # During development it is the next release +VERSION = (1, 3, 0, 'final', 0) # During development it is the next release RELEASE = False From 6ccde4256e39662dcfecab122924cb522f926379 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Sat, 1 Dec 2012 18:07:44 +0100 Subject: [PATCH 206/222] added testing packages to the requirements.txt file --- .travis.yml | 1 - requirements.txt | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bad214ce7..f91d92918 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ python: - "2.7" install: - pip install -r requirements.txt --use-mirrors - - pip install coverage django-discover-runner pep8 - python extras/scripts/create_local_settings.py script: - coverage run ./manage.py test tests && coverage report -m diff --git a/requirements.txt b/requirements.txt index 15fe79d8d..e43764974 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,6 @@ django-mptt reportlab PIL simplejson +coverage +django-discover-runner +pep8 From 046db10d3a270b13371937174c7bebbd19b56362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Wed, 28 Nov 2012 19:08:23 +0100 Subject: [PATCH 207/222] Hide group registered in the group widget. Make custom slides text scrollable. Fix template of personal_info_widget. --- .../participant/templates/participant/group_widget.html | 2 +- .../templates/participant/personal_info_widget.html | 2 +- .../projector/templates/projector/ProjectorSlide.html | 7 ++++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/openslides/participant/templates/participant/group_widget.html b/openslides/participant/templates/participant/group_widget.html index 50cd7e6b6..5c6e285a7 100644 --- a/openslides/participant/templates/participant/group_widget.html +++ b/openslides/participant/templates/participant/group_widget.html @@ -3,7 +3,7 @@