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
|
|
|
|
|
2013-02-06 23:56:21 +01:00
|
|
|
|
The views are automaticly imported from openslides.motion.urls.
|
2013-02-05 18:46:46 +01:00
|
|
|
|
|
2013-06-02 22:23:58 +02: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.
|
|
|
|
|
"""
|
2012-07-08 09:21:39 +02:00
|
|
|
|
|
2013-01-06 12:07:37 +01:00
|
|
|
|
from django.contrib import messages
|
2013-09-25 10:01:01 +02:00
|
|
|
|
from django.core.urlresolvers import reverse
|
2013-10-03 21:49:51 +02:00
|
|
|
|
from django.http import Http404, HttpResponseRedirect
|
2013-06-14 20:24:48 +02:00
|
|
|
|
from django.utils.text import slugify
|
2013-09-25 10:01:01 +02:00
|
|
|
|
from django.utils.translation import ugettext as _
|
|
|
|
|
from django.utils.translation import ugettext_lazy, ugettext_noop
|
2013-09-25 12:53:44 +02:00
|
|
|
|
from reportlab.platypus import SimpleDocTemplate
|
2013-04-24 15:07:39 +02:00
|
|
|
|
|
2013-09-25 10:01:01 +02:00
|
|
|
|
from openslides.agenda.views import CreateRelatedAgendaItemView as _CreateRelatedAgendaItemView
|
|
|
|
|
from openslides.config.api import config
|
2013-09-25 12:53:44 +02:00
|
|
|
|
from openslides.poll.views import PollFormView
|
2013-09-25 10:01:01 +02:00
|
|
|
|
from openslides.projector.api import get_active_slide, update_projector
|
2013-09-25 12:53:44 +02:00
|
|
|
|
from openslides.projector.projector import Widget
|
2013-09-25 10:01:01 +02:00
|
|
|
|
from openslides.utils.template import Tab
|
|
|
|
|
from openslides.utils.utils import html_strong, htmldiff
|
|
|
|
|
from openslides.utils.views import (CreateView, DeleteView, DetailView,
|
|
|
|
|
FormView, ListView, PDFView, QuestionView,
|
|
|
|
|
RedirectView, SingleObjectMixin, UpdateView)
|
2013-02-03 18:18:29 +01:00
|
|
|
|
|
2013-10-03 21:49:51 +02:00
|
|
|
|
from .csv_import import import_motions
|
2013-09-25 10:01:01 +02:00
|
|
|
|
from .forms import (BaseMotionForm, MotionCategoryMixin,
|
|
|
|
|
MotionDisableVersioningMixin, MotionIdentifierMixin,
|
|
|
|
|
MotionImportForm, MotionSubmitterMixin,
|
|
|
|
|
MotionSupporterMixin, MotionWorkflowMixin)
|
|
|
|
|
from .models import (Category, Motion, MotionPoll, MotionSubmitter,
|
|
|
|
|
MotionSupporter, MotionVersion, WorkflowError)
|
|
|
|
|
from .pdf import motion_poll_to_pdf, motion_to_pdf, motions_to_pdf
|
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-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
View, to list all motions.
|
|
|
|
|
"""
|
2013-01-06 12:07:37 +01:00
|
|
|
|
permission_required = 'motion.can_see_motion'
|
2012-10-25 09:23:24 +02:00
|
|
|
|
model = Motion
|
2012-10-28 02:09:47 +02:00
|
|
|
|
|
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-06-01 12:36:42 +02:00
|
|
|
|
class MotionDetailView(DetailView):
|
|
|
|
|
"""
|
|
|
|
|
Show one motion.
|
|
|
|
|
"""
|
|
|
|
|
permission_required = 'motion.can_see_motion'
|
|
|
|
|
model = Motion
|
2013-02-05 18:46:46 +01:00
|
|
|
|
|
2013-06-01 12:36:42 +02:00
|
|
|
|
def get_context_data(self, **kwargs):
|
|
|
|
|
"""
|
|
|
|
|
Return the template context.
|
|
|
|
|
|
2013-06-02 22:23:58 +02:00
|
|
|
|
Append the allowed actions for the motion, the shown version and its
|
|
|
|
|
data to the context.
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
2013-02-03 13:24:29 +01:00
|
|
|
|
version_number = self.kwargs.get('version_number', None)
|
|
|
|
|
if version_number is not None:
|
|
|
|
|
try:
|
2013-06-01 12:36:42 +02:00
|
|
|
|
version = self.object.versions.get(version_number=int(version_number))
|
2013-02-03 13:24:29 +01:00
|
|
|
|
except MotionVersion.DoesNotExist:
|
|
|
|
|
raise Http404('Version %s not found' % version_number)
|
2013-05-22 23:53:01 +02:00
|
|
|
|
else:
|
2013-06-01 12:36:42 +02:00
|
|
|
|
version = self.object.get_active_version()
|
2013-02-03 13:24:29 +01:00
|
|
|
|
|
2013-06-01 12:36:42 +02:00
|
|
|
|
kwargs.update({
|
|
|
|
|
'allowed_actions': self.object.get_allowed_actions(self.request.user),
|
|
|
|
|
'version': version,
|
|
|
|
|
'title': version.title,
|
|
|
|
|
'text': version.text,
|
|
|
|
|
'reason': version.reason})
|
|
|
|
|
return super(MotionDetailView, self).get_context_data(**kwargs)
|
2013-02-02 10:24:28 +01:00
|
|
|
|
|
2013-01-06 12:07:37 +01:00
|
|
|
|
motion_detail = MotionDetailView.as_view()
|
2012-04-27 21:22:44 +02:00
|
|
|
|
|
|
|
|
|
|
2013-06-01 12:36:42 +02:00
|
|
|
|
class MotionEditMixin(object):
|
2013-04-19 16:02:16 +02:00
|
|
|
|
"""
|
2013-06-02 22:23:58 +02:00
|
|
|
|
Mixin for motion views classes to save the version data.
|
2013-04-19 16:02:16 +02:00
|
|
|
|
"""
|
2013-02-05 18:46:46 +01:00
|
|
|
|
|
2013-06-01 12:36:42 +02:00
|
|
|
|
def form_valid(self, form):
|
2013-04-19 16:02:16 +02:00
|
|
|
|
"""
|
2013-06-02 22:23:58 +02:00
|
|
|
|
Saves the CreateForm or UpdateForm into a motion object.
|
2013-04-19 16:02:16 +02:00
|
|
|
|
"""
|
2013-06-01 12:36:42 +02:00
|
|
|
|
self.object = form.save(commit=False)
|
2013-01-26 17:09:13 +01:00
|
|
|
|
|
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
|
|
|
|
|
|
2013-06-20 17:57:15 +02:00
|
|
|
|
self.manipulate_object(form)
|
|
|
|
|
|
|
|
|
|
for attr in ['title', 'text', 'reason']:
|
|
|
|
|
setattr(self.version, attr, form.cleaned_data[attr])
|
|
|
|
|
|
2013-06-14 09:56:16 +02:00
|
|
|
|
self.object.save(use_version=self.version)
|
2013-06-01 12:36:42 +02:00
|
|
|
|
|
|
|
|
|
# Save the submitter an the supporter so the motion.
|
2013-06-02 22:23:58 +02:00
|
|
|
|
# TODO: Only delete and save neccessary submitters and supporters
|
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-10-03 21:49:51 +02:00
|
|
|
|
|
2013-10-16 23:57:29 +02:00
|
|
|
|
# Save the attachments
|
|
|
|
|
self.object.attachments.clear()
|
|
|
|
|
self.object.attachments.add(*form.cleaned_data['attachments'])
|
|
|
|
|
|
2013-10-03 21:49:51 +02:00
|
|
|
|
# Update the projector if the motion is on it. This can not be done in
|
|
|
|
|
# the model, because bulk_create does not call the save method.
|
|
|
|
|
active_slide = get_active_slide()
|
|
|
|
|
active_slide_pk = active_slide.get('pk', None)
|
|
|
|
|
if (active_slide['callback'] == 'motion' and
|
|
|
|
|
unicode(self.object.pk) == unicode(active_slide_pk)):
|
|
|
|
|
update_projector()
|
|
|
|
|
|
2013-09-07 22:57:29 +02:00
|
|
|
|
messages.success(self.request, self.get_success_message())
|
2013-06-01 12:36:42 +02:00
|
|
|
|
return HttpResponseRedirect(self.get_success_url())
|
2013-01-26 15:25:54 +01:00
|
|
|
|
|
|
|
|
|
def get_form_class(self):
|
2013-05-09 23:51:58 +02:00
|
|
|
|
"""
|
2013-06-02 22:23:58 +02:00
|
|
|
|
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.
|
|
|
|
|
"""
|
2013-03-12 23:54:37 +01:00
|
|
|
|
form_classes = []
|
|
|
|
|
|
|
|
|
|
if (self.request.user.has_perm('motion.can_manage_motion') and
|
2013-05-09 23:51:58 +02:00
|
|
|
|
(config['motion_identifier'] == 'manually' or type(self) == MotionUpdateView)):
|
2013-03-12 23:54:37 +01:00
|
|
|
|
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)
|
2013-03-11 20:41:02 +01:00
|
|
|
|
form_classes.append(MotionCategoryMixin)
|
2013-01-26 15:25:54 +01:00
|
|
|
|
if config['motion_min_supporters'] > 0:
|
|
|
|
|
form_classes.append(MotionSupporterMixin)
|
2013-06-14 09:56:16 +02:00
|
|
|
|
form_classes.append(MotionWorkflowMixin)
|
|
|
|
|
|
2013-02-06 23:56:21 +01:00
|
|
|
|
if self.object:
|
|
|
|
|
if config['motion_allow_disable_versioning'] and self.object.state.versioning:
|
|
|
|
|
form_classes.append(MotionDisableVersioningMixin)
|
2013-06-14 09:56:16 +02:00
|
|
|
|
|
2013-01-26 15:25:54 +01:00
|
|
|
|
return type('MotionForm', tuple(form_classes), {})
|
|
|
|
|
|
2012-02-14 16:31:21 +01:00
|
|
|
|
|
2013-06-01 12:36:42 +02:00
|
|
|
|
class MotionCreateView(MotionEditMixin, CreateView):
|
|
|
|
|
"""
|
|
|
|
|
View to create a motion.
|
|
|
|
|
"""
|
2013-01-06 12:07:37 +01:00
|
|
|
|
model = Motion
|
2012-03-18 17:11:58 +01:00
|
|
|
|
|
2013-04-03 00:40:56 +02: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
|
|
|
|
|
|
2013-02-02 21:40:23 +01:00
|
|
|
|
def form_valid(self, form):
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
2013-06-02 22:23:58 +02:00
|
|
|
|
Write a log message if the form is valid.
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
response = super(MotionCreateView, self).form_valid(form)
|
2013-05-16 01:14:14 +02:00
|
|
|
|
self.object.write_log([ugettext_noop('Motion created')], self.request.user)
|
2013-06-14 09:56:16 +02:00
|
|
|
|
if (not 'submitter' in form.cleaned_data or
|
|
|
|
|
not form.cleaned_data['submitter']):
|
2013-03-15 11:35:03 +01:00
|
|
|
|
self.object.add_submitter(self.request.user)
|
2013-06-01 12:36:42 +02:00
|
|
|
|
return response
|
2013-03-15 11:35:03 +01:00
|
|
|
|
|
2013-06-14 09:56:16 +02:00
|
|
|
|
def get_initial(self):
|
|
|
|
|
initial = super(MotionCreateView, self).get_initial()
|
|
|
|
|
if self.request.user.has_perm('motion.can_manage_motion'):
|
|
|
|
|
initial['workflow'] = config['motion_workflow']
|
|
|
|
|
return initial
|
|
|
|
|
|
|
|
|
|
def manipulate_object(self, form):
|
2013-06-20 17:57:15 +02:00
|
|
|
|
"""
|
|
|
|
|
Sets first state according to given or default workflow and initiates
|
|
|
|
|
a new version.
|
|
|
|
|
"""
|
2013-06-14 09:56:16 +02:00
|
|
|
|
workflow = form.cleaned_data.get('workflow', config['motion_workflow'])
|
|
|
|
|
self.object.reset_state(workflow)
|
2013-06-20 17:57:15 +02:00
|
|
|
|
self.version = self.object.get_new_version()
|
2013-06-14 09:56:16 +02:00
|
|
|
|
|
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-06-01 12:36:42 +02:00
|
|
|
|
class MotionUpdateView(MotionEditMixin, UpdateView):
|
|
|
|
|
"""
|
|
|
|
|
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-06-02 22:23:58 +02:00
|
|
|
|
"""
|
|
|
|
|
Check if the request.user has the permission to edit the motion.
|
|
|
|
|
"""
|
2013-05-31 18:30:03 +02:00
|
|
|
|
return self.get_object().get_allowed_actions(request.user)['update']
|
2013-02-02 10:59:07 +01:00
|
|
|
|
|
2013-02-02 21:40:23 +01:00
|
|
|
|
def form_valid(self, form):
|
2013-06-02 22:23:58 +02:00
|
|
|
|
"""
|
2013-06-19 21:59:03 +02:00
|
|
|
|
Writes a log message and removes supports in some cases if the form is valid.
|
2013-06-02 22:23:58 +02:00
|
|
|
|
"""
|
2013-06-01 12:36:42 +02:00
|
|
|
|
response = super(MotionUpdateView, self).form_valid(form)
|
2013-06-19 21:59:03 +02:00
|
|
|
|
self.write_log()
|
2013-05-31 18:30:03 +02:00
|
|
|
|
if (config['motion_remove_supporters'] and self.object.state.allow_support and
|
|
|
|
|
not self.request.user.has_perm('motion.can_manage_motion')):
|
|
|
|
|
self.object.clear_supporters()
|
|
|
|
|
self.object.write_log([ugettext_noop('All supporters removed')], self.request.user)
|
2013-06-01 12:36:42 +02:00
|
|
|
|
return response
|
2013-05-31 18:30:03 +02:00
|
|
|
|
|
2013-06-19 21:59:03 +02:00
|
|
|
|
def write_log(self):
|
|
|
|
|
"""
|
|
|
|
|
Writes a log message. Distinguishs whether a version was created or updated.
|
|
|
|
|
"""
|
|
|
|
|
if self.version.id is None:
|
|
|
|
|
number = self.object.get_last_version().version_number
|
|
|
|
|
created = False
|
|
|
|
|
else:
|
|
|
|
|
number = self.version.version_number
|
|
|
|
|
created = self.used_new_version
|
|
|
|
|
self.object.write_log(
|
2013-06-25 00:59:16 +02:00
|
|
|
|
[ugettext_noop('Motion version'),
|
|
|
|
|
' %d ' % number,
|
|
|
|
|
ugettext_noop('created') if created else ugettext_noop('updated')],
|
2013-06-19 21:59:03 +02:00
|
|
|
|
self.request.user)
|
|
|
|
|
|
2013-06-14 09:56:16 +02:00
|
|
|
|
def get_initial(self):
|
|
|
|
|
initial = super(MotionUpdateView, self).get_initial()
|
|
|
|
|
if self.request.user.has_perm('motion.can_manage_motion'):
|
|
|
|
|
initial['workflow'] = self.object.state.workflow
|
|
|
|
|
return initial
|
|
|
|
|
|
|
|
|
|
def manipulate_object(self, form):
|
2013-06-20 17:57:15 +02:00
|
|
|
|
"""
|
|
|
|
|
Resets state if the workflow should change and decides whether to use a
|
|
|
|
|
new version or the last version.
|
|
|
|
|
"""
|
2013-06-14 09:56:16 +02:00
|
|
|
|
workflow = form.cleaned_data.get('workflow', None)
|
|
|
|
|
if (workflow is not None and
|
|
|
|
|
workflow != self.object.state.workflow):
|
|
|
|
|
self.object.reset_state(workflow)
|
|
|
|
|
|
|
|
|
|
# Decide if a new version is saved to the database
|
|
|
|
|
if (self.object.state.versioning and
|
|
|
|
|
not form.cleaned_data.get('disable_versioning', False)):
|
|
|
|
|
self.version = self.object.get_new_version()
|
2013-06-19 21:59:03 +02:00
|
|
|
|
self.used_new_version = True
|
2013-06-14 09:56:16 +02:00
|
|
|
|
else:
|
|
|
|
|
self.version = self.object.get_last_version()
|
2013-06-19 21:59:03 +02:00
|
|
|
|
self.used_new_version = False
|
2013-06-14 09:56:16 +02:00
|
|
|
|
|
2013-10-11 20:17:43 +02:00
|
|
|
|
motion_update = MotionUpdateView.as_view()
|
2013-01-26 15:25:54 +01:00
|
|
|
|
|
|
|
|
|
|
2013-02-02 00:27:16 +01:00
|
|
|
|
class MotionDeleteView(DeleteView):
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
View to delete a motion.
|
|
|
|
|
"""
|
2013-02-02 00:27:16 +01:00
|
|
|
|
model = Motion
|
|
|
|
|
success_url_name = 'motion_list'
|
2013-02-02 10:59:07 +01:00
|
|
|
|
|
|
|
|
|
def has_permission(self, request, *args, **kwargs):
|
2013-06-01 12:36:42 +02: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']
|
2013-02-02 00:27:16 +01:00
|
|
|
|
|
2013-09-25 12:53:44 +02:00
|
|
|
|
def get_final_message(self):
|
2013-05-22 23:53:01 +02:00
|
|
|
|
return _('%s was successfully deleted.') % _('Motion')
|
|
|
|
|
|
2013-02-02 00:27:16 +01:00
|
|
|
|
motion_delete = MotionDeleteView.as_view()
|
|
|
|
|
|
|
|
|
|
|
2013-06-13 15:43:17 +02:00
|
|
|
|
class VersionDeleteView(DeleteView):
|
|
|
|
|
"""
|
|
|
|
|
View to delete a motion version.
|
|
|
|
|
"""
|
|
|
|
|
model = MotionVersion
|
|
|
|
|
permission_required = 'motion.can_manage_motion'
|
|
|
|
|
success_url_name = 'motion_detail'
|
|
|
|
|
|
|
|
|
|
def get_object(self):
|
2013-07-25 16:53:22 +02:00
|
|
|
|
try:
|
|
|
|
|
motion = Motion.objects.get(pk=int(self.kwargs.get('pk')))
|
|
|
|
|
except Motion.DoesNotExist:
|
|
|
|
|
raise Http404('Motion %s not found.' % self.kwargs.get('pk'))
|
|
|
|
|
try:
|
|
|
|
|
version = MotionVersion.objects.get(
|
|
|
|
|
motion=motion,
|
|
|
|
|
version_number=int(self.kwargs.get('version_number')))
|
|
|
|
|
except MotionVersion.DoesNotExist:
|
|
|
|
|
raise Http404('Version %s not found.' % self.kwargs.get('version_number'))
|
|
|
|
|
if version == motion.active_version:
|
|
|
|
|
raise Http404('You can not delete the active version of a motion.')
|
|
|
|
|
return version
|
2013-06-13 15:43:17 +02:00
|
|
|
|
|
2013-09-25 12:53:44 +02:00
|
|
|
|
def get_url_name_args(self):
|
2013-06-13 15:43:17 +02:00
|
|
|
|
return (self.object.motion_id, )
|
|
|
|
|
|
|
|
|
|
version_delete = VersionDeleteView.as_view()
|
|
|
|
|
|
|
|
|
|
|
2013-09-25 12:53:44 +02:00
|
|
|
|
class VersionPermitView(SingleObjectMixin, QuestionView):
|
2013-04-19 16:02:16 +02:00
|
|
|
|
"""
|
|
|
|
|
View to permit a version of a motion.
|
|
|
|
|
"""
|
2013-02-03 13:24:29 +01:00
|
|
|
|
model = Motion
|
2013-09-25 12:53:44 +02:00
|
|
|
|
final_message = ugettext_lazy('Version successfully permitted.')
|
2013-06-13 15:43:17 +02:00
|
|
|
|
permission_required = 'motion.can_manage_motion'
|
2013-09-25 12:53:44 +02:00
|
|
|
|
question_url_name = 'motion_version_detail'
|
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()
|
2013-06-01 12:36:42 +02:00
|
|
|
|
version_number = self.kwargs.get('version_number', None)
|
|
|
|
|
try:
|
|
|
|
|
self.version = self.object.versions.get(version_number=int(version_number))
|
|
|
|
|
except MotionVersion.DoesNotExist:
|
2013-07-25 16:53:22 +02:00
|
|
|
|
raise Http404('Version %s not found.' % version_number)
|
2013-02-03 13:24:29 +01:00
|
|
|
|
return super(VersionPermitView, self).get(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
def get_url_name_args(self):
|
2013-04-19 16:02:16 +02:00
|
|
|
|
"""
|
2013-06-01 12:36:42 +02:00
|
|
|
|
Returns a list with arguments to create the success- and question_url.
|
2013-04-19 16:02:16 +02:00
|
|
|
|
"""
|
2013-06-01 12:36:42 +02:00
|
|
|
|
return [self.object.pk, self.version.version_number]
|
2013-02-03 13:24:29 +01:00
|
|
|
|
|
2013-09-25 12:53:44 +02:00
|
|
|
|
def get_question_message(self):
|
2013-04-19 16:02:16 +02:00
|
|
|
|
"""
|
|
|
|
|
Return a string, shown to the user as question to permit the version.
|
|
|
|
|
"""
|
2013-06-01 12:36:42 +02:00
|
|
|
|
return _('Are you sure you want permit version %s?') % self.version.version_number
|
2013-02-03 13:24:29 +01:00
|
|
|
|
|
2013-09-25 12:53:44 +02:00
|
|
|
|
def on_clicked_yes(self):
|
2013-04-19 16:02:16 +02:00
|
|
|
|
"""
|
|
|
|
|
Activate the version, if the user chooses 'yes'.
|
|
|
|
|
"""
|
2013-06-01 12:36:42 +02:00
|
|
|
|
self.object.active_version = self.version
|
|
|
|
|
self.object.save(update_fields=['active_version'])
|
2013-05-16 01:28:39 +02:00
|
|
|
|
self.object.write_log(
|
2013-06-25 00:59:16 +02:00
|
|
|
|
message_list=[ugettext_noop('Version'),
|
|
|
|
|
' %d ' % self.version.version_number,
|
|
|
|
|
ugettext_noop('permitted')],
|
2013-05-16 01:28:39 +02:00
|
|
|
|
person=self.request.user)
|
2013-02-03 13:24:29 +01:00
|
|
|
|
|
|
|
|
|
version_permit = VersionPermitView.as_view()
|
|
|
|
|
|
|
|
|
|
|
2013-03-14 23:26:41 +01:00
|
|
|
|
class VersionDiffView(DetailView):
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
Show diff between two versions of a motion.
|
|
|
|
|
"""
|
2013-03-14 21:28:03 +01:00
|
|
|
|
permission_required = 'motion.can_see_motion'
|
|
|
|
|
model = Motion
|
|
|
|
|
template_name = 'motion/motion_diff.html'
|
|
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
Return the template context with versions and html diff strings.
|
|
|
|
|
"""
|
2013-03-14 21:28:03 +01:00
|
|
|
|
try:
|
|
|
|
|
rev1 = int(self.request.GET['rev1'])
|
|
|
|
|
rev2 = int(self.request.GET['rev2'])
|
2013-06-01 12:36:42 +02:00
|
|
|
|
version_rev1 = self.object.versions.get(version_number=rev1)
|
|
|
|
|
version_rev2 = self.object.versions.get(version_number=rev2)
|
2013-03-14 23:22:11 +01:00
|
|
|
|
diff_text = htmldiff(version_rev1.text, version_rev2.text)
|
|
|
|
|
diff_reason = htmldiff(version_rev1.reason, version_rev2.reason)
|
2013-03-14 21:28:03 +01:00
|
|
|
|
except (KeyError, ValueError, MotionVersion.DoesNotExist):
|
2013-04-22 19:59:05 +02:00
|
|
|
|
messages.error(self.request, _('At least one version number is not valid.'))
|
2013-03-14 21:28:03 +01:00
|
|
|
|
version_rev1 = None
|
|
|
|
|
version_rev2 = None
|
|
|
|
|
diff_text = None
|
|
|
|
|
diff_reason = None
|
|
|
|
|
context = super(VersionDiffView, self).get_context_data(**kwargs)
|
|
|
|
|
context.update({
|
2013-03-14 23:22:11 +01:00
|
|
|
|
'version_rev1': version_rev1,
|
|
|
|
|
'version_rev2': version_rev2,
|
|
|
|
|
'diff_text': diff_text,
|
|
|
|
|
'diff_reason': diff_reason,
|
2013-03-14 21:28:03 +01:00
|
|
|
|
})
|
|
|
|
|
return context
|
|
|
|
|
|
|
|
|
|
version_diff = VersionDiffView.as_view()
|
|
|
|
|
|
2013-03-14 21:36:02 +01:00
|
|
|
|
|
2013-09-25 12:53:44 +02:00
|
|
|
|
class SupportView(SingleObjectMixin, QuestionView):
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
View to support or unsupport a motion.
|
2013-02-05 18:46:46 +01:00
|
|
|
|
|
|
|
|
|
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-01-26 18:18:02 +01:00
|
|
|
|
"""
|
2013-02-05 18:46:46 +01:00
|
|
|
|
|
2013-01-26 18:18:02 +01:00
|
|
|
|
permission_required = 'motion.can_support_motion'
|
|
|
|
|
model = Motion
|
|
|
|
|
support = True
|
|
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
Set self.object to a motion.
|
|
|
|
|
"""
|
2013-01-26 18:18:02 +01:00
|
|
|
|
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-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
Return True if the user can support or unsupport the motion. Else: False.
|
|
|
|
|
"""
|
2013-01-26 18:18:02 +01:00
|
|
|
|
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']:
|
2013-01-26 18:18:02 +01:00
|
|
|
|
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']:
|
2013-01-26 18:18:02 +01:00
|
|
|
|
messages.error(request, _('You can not unsupport this motion.'))
|
|
|
|
|
return False
|
|
|
|
|
else:
|
|
|
|
|
return True
|
|
|
|
|
|
2013-09-25 12:53:44 +02:00
|
|
|
|
def get_question_message(self):
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
Return the question string.
|
|
|
|
|
"""
|
2013-03-15 02:14:15 +01:00
|
|
|
|
if self.support:
|
|
|
|
|
return _('Do you really want to support this motion?')
|
|
|
|
|
else:
|
|
|
|
|
return _('Do you really want to unsupport this motion?')
|
2013-03-14 23:45:17 +01:00
|
|
|
|
|
2013-09-25 12:53:44 +02:00
|
|
|
|
def on_clicked_yes(self):
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
Append or remove the request.user from the motion.
|
2013-02-05 18:46:46 +01:00
|
|
|
|
|
2013-02-06 23:56:21 +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
|
2013-01-26 18:18:02 +01:00
|
|
|
|
if self.support:
|
2013-02-03 10:02:06 +01:00
|
|
|
|
self.object.support(person=user)
|
2013-06-19 21:59:03 +02:00
|
|
|
|
self.object.write_log([ugettext_noop('Motion supported')], user)
|
2013-01-26 18:18:02 +01:00
|
|
|
|
else:
|
2013-02-03 10:02:06 +01:00
|
|
|
|
self.object.unsupport(person=user)
|
2013-06-19 21:59:03 +02:00
|
|
|
|
self.object.write_log([ugettext_noop('Motion unsupported')], user)
|
2013-01-26 18:18:02 +01:00
|
|
|
|
|
2013-09-25 12:53:44 +02:00
|
|
|
|
def get_final_message(self):
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
Return the success message.
|
|
|
|
|
"""
|
2013-01-26 18:18:02 +01:00
|
|
|
|
if self.support:
|
|
|
|
|
return _("You have supported this motion successfully.")
|
|
|
|
|
else:
|
|
|
|
|
return _("You have unsupported this motion successfully.")
|
|
|
|
|
|
|
|
|
|
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-06-01 12:36:42 +02: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
|
2013-10-11 20:17:43 +02:00
|
|
|
|
url_name = 'motion_poll_detail'
|
2013-02-01 12:51:54 +01:00
|
|
|
|
|
|
|
|
|
def get(self, request, *args, **kwargs):
|
2013-06-01 12:36:42 +02: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-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
Create the poll for the motion.
|
|
|
|
|
"""
|
2013-02-01 12:51:54 +01:00
|
|
|
|
self.poll = self.object.create_poll()
|
2013-05-16 01:14:14 +02:00
|
|
|
|
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-06-01 12:36:42 +02:00
|
|
|
|
"""
|
2013-10-11 20:17:43 +02:00
|
|
|
|
Return the URL to the UpdateView of the poll.
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
2013-10-11 20:17:43 +02:00
|
|
|
|
return reverse('motion_poll_update', args=[self.object.pk, self.poll.poll_number])
|
2013-02-01 12:51:54 +01:00
|
|
|
|
|
|
|
|
|
poll_create = PollCreateView.as_view()
|
|
|
|
|
|
|
|
|
|
|
2013-02-01 13:24:44 +01:00
|
|
|
|
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()
|
|
|
|
|
|
2013-02-01 13:24:44 +01:00
|
|
|
|
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.
|
|
|
|
|
"""
|
2013-02-01 13:24:44 +01:00
|
|
|
|
return [self.object.motion.pk]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PollUpdateView(PollMixin, PollFormView):
|
2013-04-21 19:12:50 +02:00
|
|
|
|
"""
|
|
|
|
|
View to update a MotionPoll.
|
|
|
|
|
"""
|
2013-09-25 12:53:44 +02:00
|
|
|
|
|
2013-02-01 13:24:44 +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
|
|
|
|
|
2013-02-01 13:24:44 +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)
|
2013-05-16 01:14:14 +02:00
|
|
|
|
self.object.write_log([ugettext_noop('Poll updated')], self.request.user)
|
2013-02-03 10:02:06 +01:00
|
|
|
|
return value
|
|
|
|
|
|
2013-10-11 20:17:43 +02:00
|
|
|
|
poll_update = PollUpdateView.as_view()
|
2013-02-01 12:51:54 +01:00
|
|
|
|
|
|
|
|
|
|
2013-02-01 13:24:44 +01:00
|
|
|
|
class PollDeleteView(PollMixin, DeleteView):
|
2013-04-21 19:12:50 +02:00
|
|
|
|
"""
|
|
|
|
|
View to delete a MotionPoll.
|
|
|
|
|
"""
|
|
|
|
|
|
2013-02-01 13:24:44 +01:00
|
|
|
|
model = MotionPoll
|
|
|
|
|
|
2013-09-25 12:53:44 +02:00
|
|
|
|
def on_clicked_yes(self):
|
2013-04-21 19:12:50 +02:00
|
|
|
|
"""
|
|
|
|
|
Write a log message, if the form is valid.
|
|
|
|
|
"""
|
2013-09-25 12:53:44 +02:00
|
|
|
|
super(PollDeleteView, self).on_clicked_yes()
|
2013-05-22 23:53:01 +02:00
|
|
|
|
self.object.motion.write_log([ugettext_noop('Poll deleted')], self.request.user)
|
2013-02-03 10:02:06 +01:00
|
|
|
|
|
2013-03-09 14:29:40 +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.
|
|
|
|
|
"""
|
2013-03-09 14:29:40 +01:00
|
|
|
|
return reverse('motion_detail', args=[self.object.motion.pk])
|
|
|
|
|
|
2013-02-01 13:24:44 +01:00
|
|
|
|
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'
|
2013-04-24 15:07:39 +02:00
|
|
|
|
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"))
|
|
|
|
|
|
2013-04-24 15:07:39 +02:00
|
|
|
|
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()
|
|
|
|
|
|
|
|
|
|
|
2013-02-01 17:20:11 +01:00
|
|
|
|
class MotionSetStateView(SingleObjectMixin, RedirectView):
|
2013-05-09 23:51:58 +02:00
|
|
|
|
"""
|
|
|
|
|
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.
|
|
|
|
|
"""
|
2013-02-01 17:20:11 +01:00
|
|
|
|
permission_required = 'motion.can_manage_motion'
|
|
|
|
|
url_name = 'motion_detail'
|
|
|
|
|
model = Motion
|
|
|
|
|
reset = False
|
|
|
|
|
|
|
|
|
|
def pre_redirect(self, request, *args, **kwargs):
|
2013-05-09 23:51:58 +02:00
|
|
|
|
"""
|
|
|
|
|
Save the new state and write a log message.
|
|
|
|
|
"""
|
2013-02-01 17:20:11 +01:00
|
|
|
|
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']))
|
2013-02-06 23:56:21 +01:00
|
|
|
|
except WorkflowError, e: # TODO: Is a WorkflowError still possible here?
|
2013-02-02 21:40:23 +01:00
|
|
|
|
messages.error(request, e)
|
2013-02-01 17:20:11 +01:00
|
|
|
|
else:
|
2013-06-16 00:48:04 +02:00
|
|
|
|
self.object.save(update_fields=['state', 'identifier'])
|
2013-05-16 01:14:14 +02:00
|
|
|
|
self.object.write_log(
|
2013-06-25 00:59:16 +02:00
|
|
|
|
message_list=[ugettext_noop('State changed to'), ' %s' % self.object.state.name],
|
2013-05-16 01:14:14 +02:00
|
|
|
|
person=self.request.user)
|
2013-05-16 23:44:07 +02:00
|
|
|
|
messages.success(request,
|
2013-06-01 12:36:42 +02:00
|
|
|
|
_('The state of the motion was set to %s.')
|
|
|
|
|
% html_strong(_(self.object.state.name)))
|
2013-02-01 17:20:11 +01:00
|
|
|
|
|
|
|
|
|
set_state = MotionSetStateView.as_view()
|
|
|
|
|
reset_state = MotionSetStateView.as_view(reset=True)
|
|
|
|
|
|
|
|
|
|
|
2013-09-07 00:18:13 +02:00
|
|
|
|
class CreateRelatedAgendaItemView(_CreateRelatedAgendaItemView):
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
View to create and agenda item for a motion.
|
|
|
|
|
"""
|
2013-02-02 00:51:08 +01:00
|
|
|
|
model = Motion
|
|
|
|
|
|
|
|
|
|
def pre_redirect(self, request, *args, **kwargs):
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
Create the agenda item.
|
|
|
|
|
"""
|
2013-09-07 00:18:13 +02:00
|
|
|
|
super(CreateRelatedAgendaItemView, self).pre_redirect(request, *args, **kwargs)
|
2013-05-16 01:14:14 +02:00
|
|
|
|
self.object.write_log([ugettext_noop('Agenda item created')], self.request.user)
|
2013-02-02 00:51:08 +01:00
|
|
|
|
|
2013-09-07 00:18:13 +02:00
|
|
|
|
create_agenda_item = CreateRelatedAgendaItemView.as_view()
|
2013-02-02 00:51:08 +01:00
|
|
|
|
|
|
|
|
|
|
2013-02-03 18:18:29 +01:00
|
|
|
|
class MotionPDFView(SingleObjectMixin, PDFView):
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
Create the PDF for one, or all motions.
|
2013-02-05 18:46:46 +01:00
|
|
|
|
|
|
|
|
|
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
|
2013-06-01 12:36:42 +02:00
|
|
|
|
motion.
|
|
|
|
|
"""
|
2013-04-22 19:59:05 +02:00
|
|
|
|
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-06-01 12:36:42 +02: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-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
Return the filename for the PDF.
|
|
|
|
|
"""
|
2013-02-03 18:18:29 +01:00
|
|
|
|
if self.print_all_motions:
|
|
|
|
|
return _("Motions")
|
|
|
|
|
else:
|
2013-06-14 20:24:48 +02:00
|
|
|
|
if self.object.identifier:
|
2013-07-07 22:00:10 +02:00
|
|
|
|
suffix = self.object.identifier.replace(' ', '')
|
2013-06-14 20:24:48 +02:00
|
|
|
|
else:
|
|
|
|
|
suffix = self.object.title.replace(' ', '_')
|
|
|
|
|
suffix = slugify(suffix)
|
|
|
|
|
return '%s-%s' % (_("Motion"), suffix)
|
2013-02-03 18:18:29 +01:00
|
|
|
|
|
|
|
|
|
def append_to_pdf(self, pdf):
|
2013-06-01 12:36:42 +02: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-10-21 19:03:07 +02:00
|
|
|
|
url_name_args = []
|
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-10-21 19:03:07 +02:00
|
|
|
|
url_name_args = []
|
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
|
2013-03-11 21:50:16 +01:00
|
|
|
|
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.
|
|
|
|
|
"""
|
2013-05-29 22:29:08 +02:00
|
|
|
|
count_success, count_lines, error_messages, warning_messages = import_motions(
|
2013-05-12 00:47:49 +02:00
|
|
|
|
self.request.FILES['csvfile'],
|
2013-05-16 00:58:37 +02:00
|
|
|
|
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,
|
2013-06-03 22:50:58 +02:00
|
|
|
|
"<strong>%s</strong><br>%s" % (
|
|
|
|
|
_('Summary'),
|
|
|
|
|
_('%(counts)d of %(total)d motions successfully imported.')
|
|
|
|
|
% {'counts': count_success, 'total': 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-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
Return the motion tab.
|
|
|
|
|
"""
|
2013-03-01 17:13:12 +01:00
|
|
|
|
# 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'),
|
2013-03-01 17:13:12 +01:00
|
|
|
|
selected=request.path.startswith('/motion/'))
|
2013-02-02 00:27:16 +01:00
|
|
|
|
|
2013-02-02 10:52:13 +01:00
|
|
|
|
|
2013-02-02 00:27:16 +01:00
|
|
|
|
def get_widgets(request):
|
2013-06-01 12:36:42 +02:00
|
|
|
|
"""
|
|
|
|
|
Return the motion widgets for the dashboard.
|
2013-02-05 18:46:46 +01:00
|
|
|
|
|
|
|
|
|
There is only one widget. It shows all motions.
|
|
|
|
|
"""
|
2013-02-02 00:27:16 +01:00
|
|
|
|
return [Widget(
|
2013-06-13 23:38:58 +02:00
|
|
|
|
request,
|
2013-02-02 00:27:16 +01:00
|
|
|
|
name='motions',
|
|
|
|
|
display_name=_('Motions'),
|
|
|
|
|
template='motion/widget.html',
|
|
|
|
|
context={'motions': Motion.objects.all()},
|
2013-09-07 15:09:37 +02:00
|
|
|
|
permission_required='projector.can_manage_projector',
|
|
|
|
|
default_column=1,
|
|
|
|
|
default_weight=40)]
|