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 01/22] 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 5b97250df2393506c082a43603de7ccacad0c240 Mon Sep 17 00:00:00 2001 From: Oskar Hahn Date: Thu, 20 Sep 2012 09:55:27 +0200 Subject: [PATCH 02/22] 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 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 03/22] 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 04/22] 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 05/22] 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 06/22] 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 07/22] 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 08/22] 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 09/22] 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 10/22] 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 11/22] 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 %}