OpenSlides/openslides/motion/views.py

750 lines
25 KiB
Python
Raw Normal View History

2011-07-31 10:46:29 +02:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
2012-10-24 11:04:23 +02:00
openslides.motion.views
2013-01-06 12:07:37 +01:00
~~~~~~~~~~~~~~~~~~~~~~~
2011-07-31 10:46:29 +02:00
2012-10-24 11:04:23 +02:00
Views for the motion app.
2011-07-31 10:46:29 +02:00
The views are automaticly imported from openslides.motion.urls.
2013-02-05 18:46:46 +01:00
:copyright: (c) 2011-2013 by the OpenSlides team, see AUTHORS.
2011-07-31 10:46:29 +02:00
:license: GNU GPL, see LICENSE for more details.
"""
from django.core.urlresolvers import reverse
2013-01-06 12:07:37 +01:00
from django.contrib import messages
from django.db import transaction
2013-01-06 12:07:37 +01:00
from django.db.models import Model
from django.utils.translation import ugettext as _, ugettext_lazy, ugettext_noop
2013-01-06 12:07:37 +01:00
from django.views.generic.detail import SingleObjectMixin
2013-01-26 15:25:54 +01:00
from django.http import Http404
2012-06-11 13:43:48 +02:00
from reportlab.platypus import SimpleDocTemplate
from openslides.utils.pdf import stylesheet
from openslides.utils.views import (
2013-01-06 12:07:37 +01:00
TemplateView, RedirectView, UpdateView, CreateView, DeleteView, PDFView,
2013-02-01 12:51:54 +01:00
DetailView, ListView, FormView, QuestionMixin, SingleObjectMixin)
2013-01-06 12:07:37 +01:00
from openslides.utils.template import Tab
from openslides.utils.utils import html_strong, htmldiff
2013-02-01 12:51:54 +01:00
from openslides.poll.views import PollFormView
2013-01-06 12:07:37 +01:00
from openslides.projector.api import get_active_slide
from openslides.projector.projector import Widget, SLIDE
from openslides.config.api import config
2013-02-02 00:51:08 +01:00
from openslides.agenda.models import Item
2013-02-03 18:18:29 +01:00
2013-03-11 20:17:19 +01:00
from .models import (Motion, MotionSubmitter, MotionSupporter, MotionPoll,
MotionVersion, State, WorkflowError, Category)
2013-01-26 15:25:54 +01:00
from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin,
MotionDisableVersioningMixin, MotionCategoryMixin,
MotionIdentifierMixin, MotionSetWorkflowMixin, MotionImportForm)
2013-04-21 19:12:50 +02:00
from .pdf import motions_to_pdf, motion_to_pdf, motion_poll_to_pdf
2013-05-08 18:07:09 +02:00
from .csv_import import import_motions
2011-07-31 10:46:29 +02:00
2013-02-02 00:37:43 +01:00
2013-01-06 12:07:37 +01:00
class MotionListView(ListView):
2013-02-05 18:46:46 +01:00
"""View, to list all motions."""
2013-01-06 12:07:37 +01:00
permission_required = 'motion.can_see_motion'
model = Motion
2013-01-06 12:07:37 +01:00
motion_list = MotionListView.as_view()
2012-10-28 19:59:41 +01:00
2011-07-31 10:46:29 +02:00
2013-02-03 13:24:29 +01:00
class GetVersionMixin(object):
2013-02-05 18:46:46 +01:00
"""Mixin to set a specific version to a motion."""
2013-02-03 13:24:29 +01:00
def get_object(self):
2013-02-05 18:46:46 +01:00
"""Return a Motion object. The id is taken from the url and the version
is set to the version with the 'version_number' from the URL."""
2013-02-03 13:24:29 +01:00
object = super(GetVersionMixin, self).get_object()
version_number = self.kwargs.get('version_number', None)
if version_number is not None:
try:
object.version = int(version_number)
except MotionVersion.DoesNotExist:
raise Http404('Version %s not found' % version_number)
else:
object.version = object.get_last_not_rejected_version()
2013-02-03 13:24:29 +01:00
return object
class MotionDetailView(GetVersionMixin, DetailView):
2013-02-05 18:46:46 +01:00
"""Show one motion."""
2013-01-06 12:07:37 +01:00
permission_required = 'motion.can_see_motion'
2012-10-24 11:04:23 +02:00
model = Motion
def get_context_data(self, **kwargs):
2013-02-05 18:46:46 +01:00
"""Return the template context.
Append the allowed actions for the motion to the context.
"""
context = super(MotionDetailView, self).get_context_data(**kwargs)
context['allowed_actions'] = self.object.get_allowed_actions(self.request.user)
return context
2013-01-06 12:07:37 +01:00
motion_detail = MotionDetailView.as_view()
2013-01-06 12:07:37 +01:00
class MotionMixin(object):
2013-04-19 16:02:16 +02:00
"""
Mixin for MotionViewsClasses to save the version data.
"""
2013-02-05 18:46:46 +01:00
2013-01-06 12:07:37 +01:00
def manipulate_object(self, form):
2013-04-19 16:02:16 +02:00
"""
Saves the version data into the motion object before it is saved in
the Database. Does also set category, identifier and new workflow
if given.
2013-04-19 16:02:16 +02:00
"""
2013-01-26 15:25:54 +01:00
super(MotionMixin, self).manipulate_object(form)
2013-01-06 12:07:37 +01:00
for attr in ['title', 'text', 'reason']:
setattr(self.object, attr, form.cleaned_data[attr])
if type(self) == MotionCreateView:
self.object.new_version
else:
for attr in ['title', 'text', 'reason']:
if getattr(self.object, attr) != getattr(self.object.last_version, attr):
new_data = True
break
else:
new_data = False
if new_data and self.object.state.versioning and not form.cleaned_data.get('disable_versioning', False):
self.object.new_version
2013-03-12 23:35:08 +01:00
try:
self.object.category = form.cleaned_data['category']
except KeyError:
pass
try:
self.object.identifier = form.cleaned_data['identifier']
except KeyError:
pass
workflow = form.cleaned_data.get('set_workflow', None)
if workflow:
self.object.reset_state(workflow)
2013-01-26 15:25:54 +01:00
def post_save(self, form):
"""
Save the submitter an the supporter so the motion.
"""
2013-01-26 15:25:54 +01:00
super(MotionMixin, self).post_save(form)
2013-01-26 16:42:23 +01:00
# TODO: only delete and save neccessary submitters and supporter
2013-02-01 12:51:54 +01:00
if 'submitter' in form.cleaned_data:
self.object.submitter.all().delete()
MotionSubmitter.objects.bulk_create(
[MotionSubmitter(motion=self.object, person=person)
for person in form.cleaned_data['submitter']])
if 'supporter' in form.cleaned_data:
self.object.supporter.all().delete()
MotionSupporter.objects.bulk_create(
[MotionSupporter(motion=self.object, person=person)
for person in form.cleaned_data['supporter']])
2013-01-26 15:25:54 +01:00
def get_form_class(self):
"""
Return the FormClass to Create or Update the Motion.
2013-02-05 18:46:46 +01:00
forms.BaseMotionForm is the base for the Class, and some FormMixins
will be mixed in dependence of some config values. See motion.forms
for more information on the mixins.
"""
form_classes = []
if (self.request.user.has_perm('motion.can_manage_motion') and
(config['motion_identifier'] == 'manually' or type(self) == MotionUpdateView)):
form_classes.append(MotionIdentifierMixin)
form_classes.append(BaseMotionForm)
2013-02-05 18:46:46 +01:00
2013-01-26 15:25:54 +01:00
if self.request.user.has_perm('motion.can_manage_motion'):
form_classes.append(MotionSubmitterMixin)
form_classes.append(MotionCategoryMixin)
2013-01-26 15:25:54 +01:00
if config['motion_min_supporters'] > 0:
form_classes.append(MotionSupporterMixin)
if self.object:
if config['motion_allow_disable_versioning'] and self.object.state.versioning:
form_classes.append(MotionDisableVersioningMixin)
if self.request.user.has_perm('motion.can_manage_motion'):
form_classes.append(MotionSetWorkflowMixin)
2013-01-26 15:25:54 +01:00
return type('MotionForm', tuple(form_classes), {})
2012-02-14 16:31:21 +01:00
2013-01-06 12:07:37 +01:00
class MotionCreateView(MotionMixin, CreateView):
2013-02-05 18:46:46 +01:00
"""View to create a motion."""
2013-01-06 12:07:37 +01:00
model = Motion
2012-03-18 17:11:58 +01:00
def has_permission(self, request, *args, **kwargs):
"""
Checks whether the requesting user can submit a new motion. He needs
at least the permission 'motion.can_create_motion'. If the submitting
of new motions by non-staff users is stopped via config variable
'motion_stop_submitting', the requesting user needs also to have
'motion.can_manage_motion'.
"""
if request.user.has_perm('motion.can_create_motion'):
return not config['motion_stop_submitting'] or request.user.has_perm('motion.can_manage_motion')
return False
def form_valid(self, form):
2013-02-05 18:46:46 +01:00
"""Write a log message, if the form is valid."""
value = super(MotionCreateView, self).form_valid(form)
self.object.write_log([ugettext_noop('Motion created')], self.request.user)
return value
2013-03-15 11:35:03 +01:00
def post_save(self, form):
super(MotionCreateView, self).post_save(form)
if not 'submitter' in form.cleaned_data:
self.object.add_submitter(self.request.user)
2013-01-06 12:07:37 +01:00
motion_create = MotionCreateView.as_view()
2012-03-18 17:11:58 +01:00
2012-06-11 13:43:48 +02:00
2013-01-06 12:07:37 +01:00
class MotionUpdateView(MotionMixin, UpdateView):
2013-02-05 18:46:46 +01:00
"""View to update a motion."""
2013-01-06 12:07:37 +01:00
model = Motion
2012-06-11 13:43:48 +02:00
2013-02-02 10:59:07 +01:00
def has_permission(self, request, *args, **kwargs):
2013-02-05 18:46:46 +01:00
"""Check, if the request.user has the permission to edit the motion."""
2013-02-02 10:59:07 +01:00
return self.get_object().get_allowed_actions(request.user)['edit']
def form_valid(self, form):
2013-02-05 18:46:46 +01:00
"""Write a log message, if the form is valid."""
value = super(MotionUpdateView, self).form_valid(form)
self.object.write_log([ugettext_noop('Motion updated')], self.request.user)
return value
2013-01-06 12:07:37 +01:00
motion_edit = MotionUpdateView.as_view()
2013-01-26 15:25:54 +01:00
class MotionDeleteView(DeleteView):
2013-02-05 18:46:46 +01:00
"""View to delete a motion."""
model = Motion
success_url_name = 'motion_list'
2013-02-02 10:59:07 +01:00
def has_permission(self, request, *args, **kwargs):
2013-02-05 18:46:46 +01:00
"""Check if the request.user has the permission to delete the motion."""
2013-02-02 10:59:07 +01:00
return self.get_object().get_allowed_actions(request.user)['delete']
def get_success_message(self):
return _('%s was successfully deleted.') % _('Motion')
motion_delete = MotionDeleteView.as_view()
2013-02-03 13:24:29 +01:00
class VersionPermitView(GetVersionMixin, SingleObjectMixin, QuestionMixin, RedirectView):
2013-04-19 16:02:16 +02:00
"""
View to permit a version of a motion.
"""
2013-02-05 18:46:46 +01:00
2013-02-03 13:24:29 +01:00
model = Motion
question_url_name = 'motion_version_detail'
success_url_name = 'motion_version_detail'
2013-04-19 16:02:16 +02:00
success_message = ugettext_lazy('Version successfully permitted.')
2013-02-03 13:24:29 +01:00
def get(self, *args, **kwargs):
2013-04-19 16:02:16 +02:00
"""
Set self.object to a motion.
"""
2013-02-03 13:24:29 +01:00
self.object = self.get_object()
return super(VersionPermitView, self).get(*args, **kwargs)
def get_url_name_args(self):
2013-04-19 16:02:16 +02:00
"""
Return a list with arguments to create the success- and question_url.
"""
2013-02-03 13:24:29 +01:00
return [self.object.pk, self.object.version.version_number]
def get_question(self):
2013-04-19 16:02:16 +02:00
"""
Return a string, shown to the user as question to permit the version.
"""
2013-02-03 13:24:29 +01:00
return _('Are you sure you want permit Version %s?') % self.object.version.version_number
def case_yes(self):
2013-04-19 16:02:16 +02:00
"""
Activate the version, if the user chooses 'yes'.
"""
self.object.set_active_version(self.object.version)
self.object.save(ignore_version_data=True)
self.object.write_log(
message_list=[ugettext_noop('Version %d permitted') % self.object.version.version_number],
person=self.request.user)
2013-02-03 13:24:29 +01:00
version_permit = VersionPermitView.as_view()
class VersionRejectView(GetVersionMixin, SingleObjectMixin, QuestionMixin, RedirectView):
"""
View to reject a version.
"""
2013-02-03 13:24:29 +01:00
model = Motion
question_url_name = 'motion_version_detail'
success_url_name = 'motion_detail'
2013-02-03 13:24:29 +01:00
def get(self, *args, **kwargs):
"""
Set self.object to a motion.
"""
2013-02-03 13:24:29 +01:00
self.object = self.get_object()
return super(VersionRejectView, self).get(*args, **kwargs)
def get_url_name_args(self):
"""
Return a list with arguments to create the success- and question_url.
"""
2013-02-03 13:24:29 +01:00
return [self.object.pk, self.object.version.version_number]
def get_question(self):
return _('Are you sure you want reject Version %s?') % self.object.version.version_number
def case_yes(self):
"""
Reject the version, if the user chooses 'yes'.
"""
self.object.reject_version(self.object.version)
self.object.save(ignore_version_data=True)
self.object.write_log(
message_list=[ugettext_noop('Version %d rejected') % self.object.version.version_number],
person=self.request.user)
2013-02-03 13:24:29 +01:00
def get_success_url_name_args(self):
"""
Returns the motion pk as argument for the success url name.
"""
return [self.object.pk]
2013-02-03 13:24:29 +01:00
version_reject = VersionRejectView.as_view()
class VersionDiffView(DetailView):
"""Show diff between two versions of a motion."""
permission_required = 'motion.can_see_motion'
model = Motion
template_name = 'motion/motion_diff.html'
def get_context_data(self, **kwargs):
"""Return the template context with versions and html diff strings."""
try:
rev1 = int(self.request.GET['rev1'])
rev2 = int(self.request.GET['rev2'])
2013-03-14 23:35:57 +01:00
version_rev1 = self.object.versions.get(version_number=self.request.GET['rev1'])
version_rev2 = self.object.versions.get(version_number=self.request.GET['rev2'])
diff_text = htmldiff(version_rev1.text, version_rev2.text)
diff_reason = htmldiff(version_rev1.reason, version_rev2.reason)
except (KeyError, ValueError, MotionVersion.DoesNotExist):
messages.error(self.request, _('At least one version number is not valid.'))
version_rev1 = None
version_rev2 = None
diff_text = None
diff_reason = None
context = super(VersionDiffView, self).get_context_data(**kwargs)
context.update({
'version_rev1': version_rev1,
'version_rev2': version_rev2,
'diff_text': diff_text,
'diff_reason': diff_reason,
})
return context
version_diff = VersionDiffView.as_view()
class SupportView(SingleObjectMixin, QuestionMixin, RedirectView):
2013-02-05 18:46:46 +01:00
"""View to support or unsupport a motion.
If self.support is True, the view will append a request.user to the supporter list.
If self.support is False, the view will remove a request.user from the supporter list.
"""
2013-02-05 18:46:46 +01:00
permission_required = 'motion.can_support_motion'
model = Motion
support = True
def get(self, request, *args, **kwargs):
2013-02-05 18:46:46 +01:00
"""Set self.object to a motion."""
self.object = self.get_object()
return super(SupportView, self).get(request, *args, **kwargs)
2013-02-02 10:59:07 +01:00
def check_permission(self, request):
2013-02-05 18:46:46 +01:00
"""Return True if the user can support or unsupport the motion. Else: False."""
allowed_actions = self.object.get_allowed_actions(request.user)
2013-02-02 10:59:07 +01:00
if self.support and not allowed_actions['support']:
messages.error(request, _('You can not support this motion.'))
return False
2013-02-02 10:59:07 +01:00
elif not self.support and not allowed_actions['unsupport']:
messages.error(request, _('You can not unsupport this motion.'))
return False
else:
return True
2013-03-14 23:35:57 +01:00
def get_question(self):
2013-03-15 02:14:15 +01:00
"""Return the question string."""
if self.support:
return _('Do you really want to support this motion?')
else:
return _('Do you really want to unsupport this motion?')
def case_yes(self):
"""Append or remove the request.user from the motion.
2013-02-05 18:46:46 +01:00
First the method checks the permissions, and writes a log message after
2013-02-05 18:46:46 +01:00
appending or removing the user.
"""
2013-02-02 10:59:07 +01:00
if self.check_permission(self.request):
2013-02-03 10:02:06 +01:00
user = self.request.user
if self.support:
2013-02-03 10:02:06 +01:00
self.object.support(person=user)
self.object.write_log([ugettext_noop("Supporter: +%s") % user], user)
else:
2013-02-03 10:02:06 +01:00
self.object.unsupport(person=user)
self.object.write_log([ugettext_noop("Supporter: -%s") % user], user)
def get_success_message(self):
2013-02-05 18:46:46 +01:00
"""Return the success message."""
if self.support:
return _("You have supported this motion successfully.")
else:
return _("You have unsupported this motion successfully.")
def get_redirect_url(self, **kwargs):
2013-02-05 18:46:46 +01:00
"""Return the url, the view should redirect to."""
return self.object.get_absolute_url()
motion_support = SupportView.as_view(support=True)
motion_unsupport = SupportView.as_view(support=False)
2013-02-01 12:51:54 +01:00
class PollCreateView(SingleObjectMixin, RedirectView):
2013-02-05 18:46:46 +01:00
"""View to create a poll for a motion."""
2013-02-01 12:51:54 +01:00
permission_required = 'motion.can_manage_motion'
model = Motion
def get(self, request, *args, **kwargs):
2013-02-05 18:46:46 +01:00
"""Set self.object to a motion."""
2013-02-01 12:51:54 +01:00
self.object = self.get_object()
return super(PollCreateView, self).get(request, *args, **kwargs)
def pre_redirect(self, request, *args, **kwargs):
2013-02-05 18:46:46 +01:00
"""Create the poll for the motion."""
2013-02-01 12:51:54 +01:00
self.poll = self.object.create_poll()
self.object.write_log([ugettext_noop("Poll created")], request.user)
2013-02-01 12:51:54 +01:00
messages.success(request, _("New vote was successfully created."))
def get_redirect_url(self, **kwargs):
2013-02-05 18:46:46 +01:00
"""Return the URL to the EditView of the poll."""
2013-02-01 12:51:54 +01:00
return reverse('motion_poll_edit', args=[self.object.pk, self.poll.poll_number])
poll_create = PollCreateView.as_view()
class PollMixin(object):
2013-04-21 19:12:50 +02:00
"""
Mixin for the PollUpdateView and the PollDeleteView.
"""
2013-02-01 12:51:54 +01:00
permission_required = 'motion.can_manage_motion'
success_url_name = 'motion_detail'
def get_object(self):
2013-04-21 19:12:50 +02:00
"""
Return a MotionPoll object.
2013-02-05 18:46:46 +01:00
Use the motion id and the poll_number from the url kwargs to get the
object.
"""
2013-02-01 12:51:54 +01:00
return MotionPoll.objects.filter(
motion=self.kwargs['pk'],
poll_number=self.kwargs['poll_number']).get()
def get_url_name_args(self):
2013-04-21 19:12:50 +02:00
"""
Return the arguments to create the url to the success_url.
"""
return [self.object.motion.pk]
class PollUpdateView(PollMixin, PollFormView):
2013-04-21 19:12:50 +02:00
"""
View to update a MotionPoll.
"""
2013-02-05 18:46:46 +01:00
poll_class = MotionPoll
2013-04-21 19:12:50 +02:00
"""
Poll Class to use for this view.
"""
2013-02-05 18:46:46 +01:00
template_name = 'motion/poll_form.html'
2013-02-01 12:51:54 +01:00
def get_context_data(self, **kwargs):
2013-04-21 19:12:50 +02:00
"""
Return the template context.
2013-02-05 18:46:46 +01:00
Append the motion object to the context.
"""
2013-02-01 12:51:54 +01:00
context = super(PollUpdateView, self).get_context_data(**kwargs)
context.update({
2013-04-21 19:12:50 +02:00
'motion': self.poll.motion,
'poll': self.poll})
2013-02-01 12:51:54 +01:00
return context
2013-02-03 10:02:06 +01:00
def form_valid(self, form):
2013-04-21 19:12:50 +02:00
"""
Write a log message, if the form is valid.
"""
2013-02-03 10:02:06 +01:00
value = super(PollUpdateView, self).form_valid(form)
self.object.write_log([ugettext_noop('Poll updated')], self.request.user)
2013-02-03 10:02:06 +01:00
return value
2013-02-01 12:51:54 +01:00
poll_edit = PollUpdateView.as_view()
class PollDeleteView(PollMixin, DeleteView):
2013-04-21 19:12:50 +02:00
"""
View to delete a MotionPoll.
"""
model = MotionPoll
2013-02-03 10:02:06 +01:00
def case_yes(self):
2013-04-21 19:12:50 +02:00
"""
Write a log message, if the form is valid.
"""
2013-02-03 10:02:06 +01:00
super(PollDeleteView, self).case_yes()
self.object.motion.write_log([ugettext_noop('Poll deleted')], self.request.user)
2013-02-03 10:02:06 +01:00
def get_redirect_url(self, **kwargs):
2013-04-21 19:12:50 +02:00
"""
Return the URL to the DetailView of the motion.
"""
return reverse('motion_detail', args=[self.object.motion.pk])
poll_delete = PollDeleteView.as_view()
2013-04-21 19:12:50 +02:00
class PollPDFView(PollMixin, PDFView):
"""
Generates a ballotpaper.
"""
permission_required = 'motion.can_manage_motion'
top_space = 0
2013-04-21 19:12:50 +02:00
def get(self, *args, **kwargs):
self.object = self.get_object()
return super(PollPDFView, self).get(*args, **kwargs)
def get_filename(self):
"""
Return the filename for the PDF.
"""
return u'%s%s_%s' % (_("Motion"), str(self.object.poll_number), _("Poll"))
def get_template(self, buffer):
return SimpleDocTemplate(
buffer, topMargin=-6, bottomMargin=-6, leftMargin=0, rightMargin=0,
showBoundary=False)
def build_document(self, pdf_document, story):
pdf_document.build(story)
2013-04-21 19:12:50 +02:00
def append_to_pdf(self, pdf):
"""
Append PDF objects.
"""
motion_poll_to_pdf(pdf, self.object)
poll_pdf = PollPDFView.as_view()
class MotionSetStateView(SingleObjectMixin, RedirectView):
"""
View to set the state of a motion.
2013-02-05 18:46:46 +01:00
If self.reset is False, the new state is taken from url.
If self.reset is True, the default state is taken.
"""
permission_required = 'motion.can_manage_motion'
url_name = 'motion_detail'
model = Motion
reset = False
def pre_redirect(self, request, *args, **kwargs):
"""
Save the new state and write a log message.
"""
self.object = self.get_object()
try:
if self.reset:
self.object.reset_state()
else:
2013-03-12 22:03:56 +01:00
self.object.set_state(int(kwargs['state']))
except WorkflowError, e: # TODO: Is a WorkflowError still possible here?
messages.error(request, e)
else:
self.object.save(ignore_version_data=True)
self.object.write_log(
message_list=[ugettext_noop('State changed to '), self.object.state.name],
person=self.request.user)
2013-05-16 23:44:07 +02:00
messages.success(request,
_('The state of the motion was set to %s.') % html_strong(_(self.object.state.name)))
set_state = MotionSetStateView.as_view()
reset_state = MotionSetStateView.as_view(reset=True)
2013-02-02 00:51:08 +01:00
class CreateAgendaItemView(SingleObjectMixin, RedirectView):
2013-02-05 18:46:46 +01:00
"""View to create and agenda item for a motion."""
2013-02-02 00:51:08 +01:00
permission_required = 'agenda.can_manage_agenda'
model = Motion
url_name = 'item_overview'
url_name_args = []
2013-02-02 00:51:08 +01:00
def get(self, request, *args, **kwargs):
2013-02-05 18:46:46 +01:00
"""Set self.object to a motion."""
2013-02-02 00:51:08 +01:00
self.object = self.get_object()
return super(CreateAgendaItemView, self).get(request, *args, **kwargs)
def pre_redirect(self, request, *args, **kwargs):
2013-02-05 18:46:46 +01:00
"""Create the agenda item."""
2013-02-02 00:51:08 +01:00
self.item = Item.objects.create(related_sid=self.object.sid)
self.object.write_log([ugettext_noop('Agenda item created')], self.request.user)
2013-02-02 00:51:08 +01:00
create_agenda_item = CreateAgendaItemView.as_view()
2013-02-03 18:18:29 +01:00
class MotionPDFView(SingleObjectMixin, PDFView):
2013-02-05 18:46:46 +01:00
"""Create the PDF for one, or all motions.
If self.print_all_motions is True, the view returns a PDF with all motions.
If self.print_all_motions is False, the view returns a PDF with only one
motion."""
permission_required = 'motion.can_see_motion'
2013-02-03 18:18:29 +01:00
model = Motion
top_space = 0
print_all_motions = False
def get(self, request, *args, **kwargs):
2013-02-05 18:46:46 +01:00
"""Set self.object to a motion."""
2013-02-03 18:18:29 +01:00
if not self.print_all_motions:
self.object = self.get_object()
return super(MotionPDFView, self).get(request, *args, **kwargs)
def get_filename(self):
2013-02-05 18:46:46 +01:00
"""Return the filename for the PDF."""
2013-02-03 18:18:29 +01:00
if self.print_all_motions:
return _("Motions")
else:
return _("Motion: %s") % unicode(self.object)
def append_to_pdf(self, pdf):
2013-02-05 18:46:46 +01:00
"""Append PDF objects."""
2013-02-03 18:18:29 +01:00
if self.print_all_motions:
motions_to_pdf(pdf)
else:
motion_to_pdf(pdf, self.object)
motion_list_pdf = MotionPDFView.as_view(print_all_motions=True)
motion_detail_pdf = MotionPDFView.as_view(print_all_motions=False)
2013-03-11 20:17:19 +01:00
class CategoryListView(ListView):
permission_required = 'motion.can_manage_motion'
model = Category
category_list = CategoryListView.as_view()
class CategoryCreateView(CreateView):
permission_required = 'motion.can_manage_motion'
model = Category
2013-03-11 21:29:56 +01:00
success_url_name = 'motion_category_list'
2013-03-11 20:17:19 +01:00
category_create = CategoryCreateView.as_view()
class CategoryUpdateView(UpdateView):
permission_required = 'motion.can_manage_motion'
model = Category
2013-03-11 21:29:56 +01:00
success_url_name = 'motion_category_list'
2013-03-11 20:17:19 +01:00
category_update = CategoryUpdateView.as_view()
2013-03-11 21:38:07 +01:00
class CategoryDeleteView(DeleteView):
permission_required = 'motion.can_manage_motion'
model = Category
question_url_name = 'motion_category_list'
2013-03-11 21:38:07 +01:00
success_url_name = 'motion_category_list'
category_delete = CategoryDeleteView.as_view()
2013-05-08 18:07:09 +02:00
class MotionCSVImportView(FormView):
"""
Import motions via csv.
"""
2013-05-12 00:47:49 +02:00
permission_required = 'motion.can_manage_motion'
2013-05-08 18:07:09 +02:00
template_name = 'motion/motion_form_csv_import.html'
form_class = MotionImportForm
success_url_name = 'motion_list'
2013-05-12 00:47:49 +02:00
def get_initial(self, *args, **kwargs):
"""
Sets the request user as initial for the default submitter.
"""
return_value = super(MotionCSVImportView, self).get_initial(*args, **kwargs)
return_value.update({'default_submitter': self.request.user.person_id})
return return_value
2013-05-08 18:07:09 +02:00
def form_valid(self, form):
2013-05-12 00:47:49 +02:00
"""
Processes the import function.
"""
count_success, count_lines, error_messages, warning_messages = import_motions(
2013-05-12 00:47:49 +02:00
self.request.FILES['csvfile'],
default_submitter=form.cleaned_data['default_submitter'],
override=form.cleaned_data['override'],
importing_person=self.request.user)
2013-05-08 18:07:09 +02:00
for message in error_messages:
messages.error(self.request, message)
2013-05-12 00:47:49 +02:00
for message in warning_messages:
messages.warning(self.request, message)
2013-05-08 18:07:09 +02:00
if count_success:
messages.success(
self.request,
"<strong>%s</strong><br>%s" % (_('Summary'), _('%d of %d motions successfully imported.') % (count_success, count_lines)))
2013-05-08 18:07:09 +02:00
return super(MotionCSVImportView, self).form_valid(form)
motion_csv_import = MotionCSVImportView.as_view()
2013-01-26 15:25:54 +01:00
def register_tab(request):
2013-02-05 18:46:46 +01:00
"""Return the motion tab."""
# TODO: Find a better way to set the selected var.
2013-01-26 15:25:54 +01:00
return Tab(
title=_('Motions'),
2013-01-02 23:22:12 +01:00
app='motion',
2013-01-26 15:25:54 +01:00
url=reverse('motion_list'),
permission=request.user.has_perm('motion.can_see_motion'),
selected=request.path.startswith('/motion/'))
2013-02-02 10:52:13 +01:00
def get_widgets(request):
2013-02-05 18:46:46 +01:00
"""Return the motion widgets for the dashboard.
There is only one widget. It shows all motions.
"""
return [Widget(
name='motions',
display_name=_('Motions'),
template='motion/widget.html',
context={'motions': Motion.objects.all()},
permission_required='projector.can_manage_projector')]