More projector fixtures
* Update projector when polls are updated. * Update projector when assignment candidates are updated * Update projector when motion submitter are updated * Fixed the assignment publish poll view * Added projector.api.register_slide_model
This commit is contained in:
parent
38251f0819
commit
6aae8bff15
@ -18,22 +18,31 @@ from django.utils.datastructures import SortedDict
|
||||
from openslides.utils.person import PersonField
|
||||
from openslides.utils.utils import html_strong
|
||||
from openslides.config.api import config
|
||||
from openslides.projector.models import SlideMixin
|
||||
from openslides.projector.models import SlideMixin, RelatedModelMixin
|
||||
from openslides.poll.models import (
|
||||
BasePoll, CountInvalid, CountVotesCast, BaseOption, PublishPollMixin, BaseVote)
|
||||
|
||||
|
||||
class AssignmentCandidate(models.Model):
|
||||
class AssignmentCandidate(RelatedModelMixin, models.Model):
|
||||
"""
|
||||
Many2Many table between an assignment and the candidates.
|
||||
"""
|
||||
assignment = models.ForeignKey("Assignment")
|
||||
person = PersonField(db_index=True)
|
||||
elected = models.BooleanField(default=False)
|
||||
blocked = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
unique_together = ("assignment", "person")
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.person)
|
||||
|
||||
class Meta:
|
||||
unique_together = ("assignment", "person")
|
||||
def get_related_model(self):
|
||||
"""
|
||||
Returns the assignment
|
||||
"""
|
||||
return self.assignment
|
||||
|
||||
|
||||
class Assignment(SlideMixin, models.Model):
|
||||
@ -74,6 +83,12 @@ class Assignment(SlideMixin, models.Model):
|
||||
return reverse('assignment_delete', args=[str(self.id)])
|
||||
return super(Assignment, self).get_absolute_url(link)
|
||||
|
||||
def get_slide_context(self, **context):
|
||||
context.update({
|
||||
'polls': self.poll_set.filter(published=True),
|
||||
'vote_results': self.vote_results(only_published=True)})
|
||||
return super(Assignment, self).get_slide_context(**context)
|
||||
|
||||
def set_status(self, status):
|
||||
status_dict = dict(self.STATUS)
|
||||
if status not in status_dict:
|
||||
@ -241,15 +256,29 @@ class AssignmentOption(BaseOption):
|
||||
return unicode(self.candidate)
|
||||
|
||||
|
||||
class AssignmentPoll(BasePoll, CountInvalid, CountVotesCast, PublishPollMixin):
|
||||
class AssignmentPoll(RelatedModelMixin, CountInvalid, CountVotesCast,
|
||||
PublishPollMixin, BasePoll):
|
||||
option_class = AssignmentOption
|
||||
|
||||
assignment = models.ForeignKey(Assignment, related_name='poll_set')
|
||||
yesnoabstain = models.NullBooleanField()
|
||||
|
||||
def __unicode__(self):
|
||||
return _("Ballot %d") % self.get_ballot()
|
||||
|
||||
@models.permalink
|
||||
def get_absolute_url(self, link='detail'):
|
||||
if link == 'view' or link == 'detail' or link == 'update':
|
||||
return ('assignment_poll_view', [str(self.pk)])
|
||||
if link == 'delete':
|
||||
return ('assignment_poll_delete', [str(self.pk)])
|
||||
|
||||
def get_assignment(self):
|
||||
return self.assignment
|
||||
|
||||
def get_related_model(self):
|
||||
return self.assignment
|
||||
|
||||
def get_vote_values(self):
|
||||
if self.yesnoabstain is None:
|
||||
if config['assignment_poll_vote_values'] == 'votes':
|
||||
@ -274,13 +303,3 @@ class AssignmentPoll(BasePoll, CountInvalid, CountVotesCast, PublishPollMixin):
|
||||
|
||||
def get_ballot(self):
|
||||
return self.assignment.poll_set.filter(id__lte=self.id).count()
|
||||
|
||||
@models.permalink
|
||||
def get_absolute_url(self, link='detail'):
|
||||
if link == 'view' or link == 'detail' or link == 'update':
|
||||
return ('assignment_poll_view', [str(self.id)])
|
||||
if link == 'delete':
|
||||
return ('assignment_poll_delete', [str(self.id)])
|
||||
|
||||
def __unicode__(self):
|
||||
return _("Ballot %d") % self.get_ballot()
|
||||
|
@ -10,29 +10,8 @@
|
||||
:license: GNU GPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.projector.api import register_slide
|
||||
from openslides.projector.api import register_slide_model
|
||||
from .models import Assignment
|
||||
|
||||
|
||||
def assignment_slide(**kwargs):
|
||||
"""
|
||||
Slide for an Assignment
|
||||
"""
|
||||
assignment_pk = kwargs.get('pk', None)
|
||||
try:
|
||||
assignment = Assignment.objects.get(pk=assignment_pk)
|
||||
except Assignment.DoesNotExist:
|
||||
return ''
|
||||
|
||||
polls = assignment.poll_set
|
||||
context = {
|
||||
'polls': polls.filter(published=True),
|
||||
'vote_results': assignment.vote_results(only_published=True),
|
||||
'assignment': assignment}
|
||||
|
||||
return render_to_string('assignment/slide.html', context)
|
||||
|
||||
register_slide(Assignment.slide_callback_name, assignment_slide)
|
||||
register_slide_model(Assignment, 'assignment/slide.html')
|
||||
|
@ -179,7 +179,7 @@
|
||||
{% endfor %}
|
||||
{% if assignment.candidates and perms.assignment.can_manage_assignment and assignment.status == "vot" %}
|
||||
<th class="span1 nobr">
|
||||
<a href="{% url 'assignment_poll_create' assignment.id %}" class="btn btn-mini">
|
||||
<a href="{% url 'assignment_poll_create' assignment.pk %}" class="btn btn-mini">
|
||||
<i class="icon-plus"></i> {% trans 'New ballot' %}
|
||||
</a>
|
||||
</th>
|
||||
|
@ -99,6 +99,8 @@ urlpatterns = patterns('openslides.assignment.views',
|
||||
name='assignment_poll_delete',
|
||||
),
|
||||
|
||||
# TODO: use seperate urls to publish and unpublish the poll
|
||||
# see assignment_user_elected
|
||||
url(r'^poll/(?P<pk>\d+)/pub/$',
|
||||
SetPublishStatusView.as_view(),
|
||||
name='assignment_poll_publish_status',
|
||||
|
@ -246,10 +246,10 @@ class PollUpdateView(PollFormView):
|
||||
class SetPublishStatusView(SingleObjectMixin, RedirectView):
|
||||
model = AssignmentPoll
|
||||
permission_required = 'assignment.can_manage_assignment'
|
||||
url_name = 'assignment_list'
|
||||
url_name = 'assignment_detail'
|
||||
allow_ajax = True
|
||||
|
||||
def get_ajax_context(self):
|
||||
def get_ajax_context(self, **kwargs):
|
||||
return {'published': self.object.published}
|
||||
|
||||
def pre_redirect(self, *args, **kwargs):
|
||||
@ -258,15 +258,11 @@ class SetPublishStatusView(SingleObjectMixin, RedirectView):
|
||||
except self.model.DoesNotExist:
|
||||
messages.error(self.request, _('Ballot ID %d does not exist.') %
|
||||
int(kwargs['poll_id']))
|
||||
return
|
||||
if self.object.published:
|
||||
self.object.set_published(False)
|
||||
else:
|
||||
self.object.set_published(True)
|
||||
if self.object.published:
|
||||
messages.success(self.request, _("Ballot successfully published."))
|
||||
else:
|
||||
messages.success(self.request, _("Ballot successfully unpublished."))
|
||||
if self.object.published:
|
||||
self.object.set_published(False)
|
||||
else:
|
||||
self.object.set_published(True)
|
||||
|
||||
|
||||
class SetElectedView(SingleObjectMixin, RedirectView):
|
||||
@ -281,14 +277,14 @@ class SetElectedView(SingleObjectMixin, RedirectView):
|
||||
self.elected = kwargs['elected']
|
||||
self.object.set_elected(self.person, self.elected)
|
||||
|
||||
def get_ajax_context(self):
|
||||
def get_ajax_context(self, **kwargs):
|
||||
if self.elected:
|
||||
link = reverse('assignment_user_not_elected',
|
||||
args=[self.object.id, self.person.person_id])
|
||||
text = _('not elected')
|
||||
else:
|
||||
link = reverse('assignment_user_elected',
|
||||
args=[self.self.object.id, self.person.person_id])
|
||||
args=[self.object.id, self.person.person_id])
|
||||
text = _('elected')
|
||||
return {'elected': self.elected, 'link': link, 'text': text}
|
||||
|
||||
|
@ -23,14 +23,15 @@ from django.utils import formats
|
||||
from django.utils.translation import pgettext
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy, ugettext_noop
|
||||
|
||||
from openslides.utils.jsonfield import JSONField
|
||||
from openslides.utils.person import PersonField
|
||||
from openslides.agenda.models import Item
|
||||
from openslides.config.api import config
|
||||
from openslides.participant.models import User
|
||||
from openslides.poll.models import (
|
||||
BaseOption, BasePoll, CountVotesCast, CountInvalid, BaseVote)
|
||||
from openslides.participant.models import User
|
||||
from openslides.projector.models import SlideMixin
|
||||
from openslides.agenda.models import Item
|
||||
from openslides.projector.models import SlideMixin, RelatedModelMixin
|
||||
from openslides.projector.api import (update_projector, get_active_slide)
|
||||
from openslides.utils.jsonfield import JSONField
|
||||
from openslides.utils.person import PersonField
|
||||
|
||||
from .exceptions import MotionError, WorkflowError
|
||||
|
||||
@ -584,7 +585,7 @@ class MotionVersion(models.Model):
|
||||
return self.active_version.exists()
|
||||
|
||||
|
||||
class MotionSubmitter(models.Model):
|
||||
class MotionSubmitter(RelatedModelMixin, models.Model):
|
||||
"""Save the submitter of a Motion."""
|
||||
|
||||
motion = models.ForeignKey('Motion', related_name="submitter")
|
||||
@ -597,6 +598,9 @@ class MotionSubmitter(models.Model):
|
||||
"""Return the name of the submitter as string."""
|
||||
return unicode(self.person)
|
||||
|
||||
def get_related_model(self):
|
||||
return self.motion
|
||||
|
||||
|
||||
class MotionSupporter(models.Model):
|
||||
"""Save the submitter of a Motion."""
|
||||
@ -695,7 +699,7 @@ class MotionOption(BaseOption):
|
||||
"""The VoteClass, to witch this Class links."""
|
||||
|
||||
|
||||
class MotionPoll(CountInvalid, CountVotesCast, BasePoll):
|
||||
class MotionPoll(RelatedModelMixin, CountInvalid, CountVotesCast, BasePoll):
|
||||
"""The Class to saves the poll results for a motion poll."""
|
||||
|
||||
motion = models.ForeignKey(Motion, related_name='polls')
|
||||
@ -722,7 +726,8 @@ class MotionPoll(CountInvalid, CountVotesCast, BasePoll):
|
||||
return _('Vote %d') % self.poll_number
|
||||
|
||||
def get_absolute_url(self, link='edit'):
|
||||
"""Return an URL for the poll.
|
||||
"""
|
||||
Return an URL for the poll.
|
||||
|
||||
The keyargument 'link' can be 'edit' or 'delete'.
|
||||
"""
|
||||
@ -744,9 +749,13 @@ class MotionPoll(CountInvalid, CountVotesCast, BasePoll):
|
||||
CountInvalid.append_pollform_fields(self, fields)
|
||||
CountVotesCast.append_pollform_fields(self, fields)
|
||||
|
||||
def get_related_model(self):
|
||||
return self.motion
|
||||
|
||||
|
||||
class State(models.Model):
|
||||
"""Defines a state for a motion.
|
||||
"""
|
||||
Defines a state for a motion.
|
||||
|
||||
Every state belongs to a workflow. All states of a workflow are linked together
|
||||
via 'next_states'. One of these states is the first state, but this
|
||||
|
@ -10,26 +10,7 @@
|
||||
:license: GNU GPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from openslides.projector.api import register_slide
|
||||
from openslides.projector.api import register_slide_model
|
||||
from .models import Motion
|
||||
|
||||
|
||||
def motion_slide(**kwargs):
|
||||
"""
|
||||
Slide for the motion app.
|
||||
"""
|
||||
motion_pk = kwargs.get('pk', None)
|
||||
try:
|
||||
motion = Motion.objects.get(pk=motion_pk)
|
||||
except Motion.DoesNotExist:
|
||||
return ''
|
||||
|
||||
context = {
|
||||
'motion': motion,
|
||||
'title': motion.title}
|
||||
|
||||
return render_to_string('motion/slide.html', context)
|
||||
|
||||
register_slide(Motion.slide_callback_name, motion_slide)
|
||||
register_slide_model(Motion, 'motion/slide.html')
|
||||
|
@ -11,36 +11,36 @@
|
||||
:copyright: (c) 2011–2013 by the OpenSlides team, see AUTHORS.
|
||||
:license: GNU GPL, see LICENSE for more details.
|
||||
"""
|
||||
from reportlab.platypus import SimpleDocTemplate
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.contrib import messages
|
||||
from django.db import transaction
|
||||
from django.db.models import Model
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.utils.text import slugify
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy, ugettext_noop
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
|
||||
from reportlab.platypus import SimpleDocTemplate
|
||||
|
||||
from openslides.agenda.views import (
|
||||
CreateRelatedAgendaItemView as _CreateRelatedAgendaItemView)
|
||||
from openslides.config.api import config
|
||||
from openslides.poll.views import PollFormView
|
||||
from openslides.projector.api import get_active_slide, update_projector
|
||||
from openslides.projector.projector import Widget
|
||||
from openslides.utils.pdf import stylesheet
|
||||
from openslides.utils.template import Tab
|
||||
from openslides.utils.utils import html_strong, htmldiff
|
||||
from openslides.utils.views import (
|
||||
TemplateView, RedirectView, UpdateView, CreateView, DeleteView, PDFView,
|
||||
DetailView, ListView, FormView, QuestionMixin, SingleObjectMixin)
|
||||
from openslides.utils.template import Tab
|
||||
from openslides.utils.utils import html_strong, htmldiff
|
||||
from openslides.poll.views import PollFormView
|
||||
from openslides.projector.api import get_active_slide
|
||||
from openslides.projector.projector import Widget
|
||||
from openslides.config.api import config
|
||||
from openslides.agenda.views import CreateRelatedAgendaItemView as _CreateRelatedAgendaItemView
|
||||
|
||||
from .models import (Motion, MotionSubmitter, MotionSupporter, MotionPoll,
|
||||
MotionVersion, State, WorkflowError, Category)
|
||||
from .csv_import import import_motions
|
||||
from .forms import (BaseMotionForm, MotionSubmitterMixin, MotionSupporterMixin,
|
||||
MotionDisableVersioningMixin, MotionCategoryMixin,
|
||||
MotionIdentifierMixin, MotionWorkflowMixin, MotionImportForm)
|
||||
from .models import (Motion, MotionSubmitter, MotionSupporter, MotionPoll,
|
||||
MotionVersion, State, WorkflowError, Category)
|
||||
from .pdf import motions_to_pdf, motion_to_pdf, motion_poll_to_pdf
|
||||
from .csv_import import import_motions
|
||||
|
||||
|
||||
class MotionListView(ListView):
|
||||
@ -127,6 +127,15 @@ class MotionEditMixin(object):
|
||||
MotionSupporter.objects.bulk_create(
|
||||
[MotionSupporter(motion=self.object, person=person)
|
||||
for person in form.cleaned_data['supporter']])
|
||||
|
||||
# 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()
|
||||
|
||||
messages.success(self.request, self.get_success_message())
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
|
@ -80,6 +80,11 @@ class User(SlideMixin, PersonMixin, Person, DjangoUser):
|
||||
return reverse('user_delete', args=[str(self.id)])
|
||||
return super(User, self).get_absolute_url(link)
|
||||
|
||||
def get_slide_context(self, **context):
|
||||
# Does not call super. In this case the context would override the name
|
||||
# 'user'.
|
||||
return {'shown_user': self}
|
||||
|
||||
@property
|
||||
def clean_name(self):
|
||||
if self.title:
|
||||
|
@ -10,39 +10,8 @@
|
||||
:license: GNU GPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from openslides.projector.api import register_slide
|
||||
from openslides.projector.api import register_slide_model
|
||||
from .models import User, Group
|
||||
|
||||
|
||||
def user_slide(**kwargs):
|
||||
"""
|
||||
Slide for the user model.
|
||||
"""
|
||||
user_pk = kwargs.get('pk', None)
|
||||
try:
|
||||
user = User.objects.get(pk=user_pk)
|
||||
except User.DoesNotExist:
|
||||
return ''
|
||||
|
||||
context = {'shown_user': user}
|
||||
return render_to_string('participant/user_slide.html', context)
|
||||
|
||||
register_slide(User.slide_callback_name, user_slide)
|
||||
|
||||
|
||||
def group_slide(**kwargs):
|
||||
"""
|
||||
Slide for the group model.
|
||||
"""
|
||||
group_pk = kwargs.get('pk', None)
|
||||
try:
|
||||
group = Group.objects.get(pk=group_pk)
|
||||
except Group.DoesNotExist:
|
||||
return ''
|
||||
|
||||
context = {'group': group}
|
||||
return render_to_string('participant/group_slide.html', context)
|
||||
|
||||
register_slide(Group.slide_callback_name, group_slide)
|
||||
register_slide_model(User, 'participant/user_slide.html')
|
||||
register_slide_model(Group, 'participant/group_slide.html')
|
||||
|
@ -40,18 +40,17 @@ def update_projector():
|
||||
|
||||
def update_projector_overlay(overlay):
|
||||
"""
|
||||
Update one overlay on the projector.
|
||||
Update one or all overlay on the projector.
|
||||
|
||||
Checks if the overlay is activated and updates it in this case.
|
||||
|
||||
'overlay' has to be an overlay object, the name of a ovleray or None.
|
||||
|
||||
If 'overlay' is None, then all overlays are updated.
|
||||
The argument 'overlay' has to be an overlay object, the name of a
|
||||
ovleray or None. If it is None, all overlays will be updated.
|
||||
"""
|
||||
if isinstance(overlay, basestring):
|
||||
overlay = get_overlays()[overlay]
|
||||
if overlay is None:
|
||||
overlays = [overlay for overlay in get_overlays().values()]
|
||||
elif isinstance(overlay, basestring):
|
||||
overlays = [get_overlays()[overlay]]
|
||||
else:
|
||||
overlays = [overlay]
|
||||
|
||||
@ -132,6 +131,33 @@ def register_slide(name, callback):
|
||||
slide_callback[name] = callback
|
||||
|
||||
|
||||
def register_slide_model(SlideModel, template):
|
||||
"""
|
||||
Shortcut for register_slide for a Model with the SlideMixin.
|
||||
|
||||
The Argument 'SlideModel' has to be a Django-Model-Class, which is a subclass
|
||||
of SlideMixin. Template has to be a string to the path of a template.
|
||||
"""
|
||||
|
||||
def model_slide(**kwargs):
|
||||
"""
|
||||
Return the html code for the model slide.
|
||||
"""
|
||||
slide_pk = kwargs.get('pk', None)
|
||||
|
||||
try:
|
||||
slide = SlideModel.objects.get(pk=slide_pk)
|
||||
except SlideModel.DoesNotExist:
|
||||
slide = None
|
||||
context = {'slide': None}
|
||||
else:
|
||||
context = slide.get_slide_context()
|
||||
|
||||
return render_to_string(template, context)
|
||||
|
||||
register_slide(SlideModel.slide_callback_name, model_slide)
|
||||
|
||||
|
||||
def set_active_slide(callback, kwargs={}):
|
||||
"""
|
||||
Set the active Slide.
|
||||
@ -147,7 +173,7 @@ def set_active_slide(callback, kwargs={}):
|
||||
|
||||
def get_active_slide():
|
||||
"""
|
||||
Returns the dictonary, witch defindes the active slide.
|
||||
Returns the dictonary, which defines the active slide.
|
||||
"""
|
||||
return config['projector_active_slide']
|
||||
|
||||
|
@ -19,6 +19,39 @@ from django.core.urlresolvers import reverse
|
||||
from openslides.utils.utils import int_or_none
|
||||
|
||||
|
||||
class RelatedModelMixin(object):
|
||||
"""
|
||||
Mixin for motion related models, that appear on the motion slide.
|
||||
"""
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""
|
||||
Saves the model and updates the projector, if the motion in on it.
|
||||
"""
|
||||
from .api import update_projector
|
||||
value = super(RelatedModelMixin, self).save(*args, **kwargs)
|
||||
if self.get_related_model().is_active_slide():
|
||||
update_projector()
|
||||
return value
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
"""
|
||||
Deletes the model and updates the projector, if the motion in on it.
|
||||
"""
|
||||
from .api import update_projector
|
||||
value = super(RelatedModelMixin, self).delete(*args, **kwargs)
|
||||
if self.get_related_model().is_active_slide():
|
||||
update_projector()
|
||||
return value
|
||||
|
||||
def get_related_model(self):
|
||||
"""
|
||||
Return the pk of the related model.
|
||||
"""
|
||||
raise ImproperlyConfigured(
|
||||
'%s has to have a method "get_related_model_pk"' % type(self))
|
||||
|
||||
|
||||
class SlideMixin(object):
|
||||
"""
|
||||
A Mixin for a Django-Model, for making the model a slide.
|
||||
@ -34,42 +67,32 @@ class SlideMixin(object):
|
||||
Updates the projector, if 'self' is the active slide.
|
||||
"""
|
||||
from openslides.projector.api import update_projector
|
||||
super(SlideMixin, self).save(*args, **kwargs)
|
||||
value = super(SlideMixin, self).save(*args, **kwargs)
|
||||
if self.is_active_slide():
|
||||
update_projector()
|
||||
return value
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
from openslides.projector.api import update_projector
|
||||
super(SlideMixin, self).delete(*args, **kwargs)
|
||||
value = super(SlideMixin, self).delete(*args, **kwargs)
|
||||
if self.is_active_slide():
|
||||
update_projector()
|
||||
|
||||
def get_slide_callback_name(self):
|
||||
"""
|
||||
Returns the name of the slide callback, which is used to render the slide.
|
||||
"""
|
||||
if self.slide_callback_name is None:
|
||||
raise ImproperlyConfigured(
|
||||
"SlideMixin requires either a definition of 'slide_callback_name'"
|
||||
" or an implementation of 'get_slide_callback_name()'")
|
||||
else:
|
||||
return self.slide_callback_name
|
||||
return value
|
||||
|
||||
def get_absolute_url(self, link='projector'):
|
||||
"""
|
||||
Return the url to activate the slide, if link == 'projector'
|
||||
Return the url to activate the slide, if link == 'projector'.
|
||||
"""
|
||||
if link == 'projector':
|
||||
url_name = 'projector_activate_slide'
|
||||
elif link == 'projector_preview':
|
||||
url_name = 'projector_preview'
|
||||
|
||||
if link in ('projector', 'projector_preview'):
|
||||
return '%s?pk=%d' % (
|
||||
url_name = {'projector': 'projector_activate_slide',
|
||||
'projector_preview': 'projector_preview'}[link]
|
||||
value = '%s?pk=%d' % (
|
||||
reverse(url_name,
|
||||
args=[self.get_slide_callback_name()]),
|
||||
args=[self.slide_callback_name]),
|
||||
self.pk)
|
||||
return super(SlideMixin, self).get_absolute_url(link)
|
||||
else:
|
||||
value = super(SlideMixin, self).get_absolute_url(link)
|
||||
return value
|
||||
|
||||
def is_active_slide(self):
|
||||
"""
|
||||
@ -78,15 +101,24 @@ class SlideMixin(object):
|
||||
from openslides.projector.api import get_active_slide
|
||||
active_slide = get_active_slide()
|
||||
pk = int_or_none(active_slide.get('pk', None))
|
||||
|
||||
return (active_slide['callback'] == self.get_slide_callback_name() and
|
||||
return (active_slide['callback'] == self.slide_callback_name and
|
||||
self.pk == pk)
|
||||
|
||||
def get_slide_context(self, **context):
|
||||
"""
|
||||
Returns the context for the template which renders the slide.
|
||||
"""
|
||||
slide_name = self._meta.object_name.lower()
|
||||
context.update({'slide': self,
|
||||
slide_name: self})
|
||||
return context
|
||||
|
||||
|
||||
class ProjectorSlide(SlideMixin, models.Model):
|
||||
"""
|
||||
Model for Slides, only for the projector. Also called custom slides.
|
||||
"""
|
||||
# TODO: Rename it to CustomSlide
|
||||
slide_callback_name = 'projector_slide'
|
||||
|
||||
title = models.CharField(max_length=256, verbose_name=ugettext_lazy("Title"))
|
||||
|
@ -102,7 +102,7 @@ class Overlay(object):
|
||||
|
||||
def set_active(self, active):
|
||||
"""
|
||||
Publish or depublish the ovleray on the projector.
|
||||
Publish or depublish the overlay on the projector.
|
||||
|
||||
publish, if active is true,
|
||||
depublish, if active is false.
|
||||
|
@ -10,27 +10,9 @@
|
||||
:license: GNU GPL, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from openslides.config.api import config
|
||||
from openslides.projector.api import register_slide
|
||||
from openslides.projector.api import register_slide_model
|
||||
|
||||
from .models import ProjectorSlide
|
||||
|
||||
|
||||
def projector_slide(**kwargs):
|
||||
"""
|
||||
Return the html code for a custom slide.
|
||||
"""
|
||||
slide_pk = kwargs.get('pk', None)
|
||||
|
||||
try:
|
||||
slide = ProjectorSlide.objects.get(pk=slide_pk)
|
||||
except ProjectorSlide.DoesNotExist:
|
||||
slide = None
|
||||
|
||||
context = {'slide': slide}
|
||||
return render_to_string('projector/slide_projectorslide.html', context)
|
||||
|
||||
|
||||
register_slide('projector_slide', projector_slide)
|
||||
register_slide_model(ProjectorSlide, 'projector/slide_projectorslide.html')
|
||||
|
@ -39,8 +39,14 @@ class DjangoStaticFileHandler(StaticFileHandler):
|
||||
|
||||
|
||||
class ProjectorSocketHandler(WebSocketHandler):
|
||||
"""
|
||||
Handels the websocket for the projector.
|
||||
"""
|
||||
waiters = set()
|
||||
|
||||
# The following lines can be uncommented, if there are any problems with
|
||||
# websockts in iOS Safari 5.0
|
||||
|
||||
## def allow_draft76(self):
|
||||
## # for iOS 5.0 Safari
|
||||
## return True
|
||||
|
Loading…
Reference in New Issue
Block a user