diff --git a/CHANGELOG b/CHANGELOG index 81c4e33e6..1f5312fc0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -9,6 +9,7 @@ Version 1.6 (unreleased) [https://github.com/OpenSlides/OpenSlides/issues?milestone=14] Agenda: +- New projector view with the current list of speakers. - Added CSV import. Assignment: - Coupled assignment candidates with list of speakers. diff --git a/docs/de/Agenda.rst b/docs/de/Agenda.rst index 548f320a6..1c56f7e33 100644 --- a/docs/de/Agenda.rst +++ b/docs/de/Agenda.rst @@ -137,6 +137,12 @@ Redner. Die Einblendung erscheint nur auf Folien von Tagesordnungspunkten. :scale-latex: 80 :alt: Projektor-Ansicht mit Rednerlisten-Overlay +Schließlich haben Sie die Möglichkeit, die Rednerliste des jeweiligen +Tagesordnungspunktes auf einem gesonderten Projektor anzeigen zu lassen. +Klicken Sie auf der Tagesordnungsseite oben rechts auf auf den +Glocken-Button |bell| und legen Sie die Seite im Vollbildmodus auf einen +eigenen Projektor oder Bildschirm. + Die Rednerliste verwalten ------------------------- diff --git a/openslides/agenda/signals.py b/openslides/agenda/signals.py index 0eccea885..20a1e8624 100644 --- a/openslides/agenda/signals.py +++ b/openslides/agenda/signals.py @@ -101,8 +101,8 @@ def agenda_list_of_speakers(sender, **kwargs): if slide is None or isinstance(slide, Item): item = slide else: - # TODO: If there are more the one items, use the first one in the - # mptt tree that is not closed + # TODO: If there is more than one item, use the first one in the + # mptt tree that is not closed. try: item = Item.objects.filter( content_type=ContentType.objects.get_for_model(slide), diff --git a/openslides/agenda/static/js/agenda_current_list_of_speakers_projector.js b/openslides/agenda/static/js/agenda_current_list_of_speakers_projector.js new file mode 100644 index 000000000..432c4bb6d --- /dev/null +++ b/openslides/agenda/static/js/agenda_current_list_of_speakers_projector.js @@ -0,0 +1,14 @@ +/* + * JavaScript functions for agenda CurrentListOfSpeakersProjectorView + */ + +function reloadListOfSpeakers() { + $.ajax({ + url: '', + success: function (data) { + updater.updateProjector(data); + setTimeout('reloadListOfSpeakers()', 2000); + }, + dataType: 'json' + }); +} diff --git a/openslides/agenda/templates/agenda/current_list_of_speakers_projector.html b/openslides/agenda/templates/agenda/current_list_of_speakers_projector.html new file mode 100644 index 000000000..10dd26791 --- /dev/null +++ b/openslides/agenda/templates/agenda/current_list_of_speakers_projector.html @@ -0,0 +1,4 @@ +{% extends 'projector.html' %} +{% load i18n %} + +{% block title %}{% trans 'List of speakers' %} – {{ block.super }}{% endblock %} diff --git a/openslides/agenda/templates/agenda/overview.html b/openslides/agenda/templates/agenda/overview.html index 6dea8027d..225f38c31 100644 --- a/openslides/agenda/templates/agenda/overview.html +++ b/openslides/agenda/templates/agenda/overview.html @@ -39,6 +39,10 @@ {% trans "Import" %} {% endif %} PDF + {% if perms.core.can_see_projector %} + + {% trans 'List of speakers' %} + {% endif %} diff --git a/openslides/agenda/urls.py b/openslides/agenda/urls.py index 3e926950d..0e854f1c6 100644 --- a/openslides/agenda/urls.py +++ b/openslides/agenda/urls.py @@ -89,6 +89,10 @@ urlpatterns = patterns( views.CurrentListOfSpeakersView.as_view(end_speach=True), name='agenda_end_speach_on_current_list_of_speakers'), + url(r'^list_of_speakers/projector/$', + views.CurrentListOfSpeakersProjectorView.as_view(), + name='agenda_current_list_of_speakers_projector'), + url(r'^csv_import/$', views.ItemCSVImportView.as_view(), name='item_csv_import')) diff --git a/openslides/agenda/views.py b/openslides/agenda/views.py index 0122d7e2e..6f41917e6 100644 --- a/openslides/agenda/views.py +++ b/openslides/agenda/views.py @@ -2,21 +2,33 @@ # TODO: Rename all views and template names from datetime import datetime, timedelta +from json import dumps from django.contrib import messages +from django.contrib.contenttypes.models import ContentType +from django.contrib.staticfiles.templatetags.staticfiles import static from django.core.urlresolvers import reverse from django.db import transaction from django.db.models import Model +from django.template.loader import render_to_string +from django.utils.datastructures import SortedDict +from django.utils.safestring import mark_safe from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy from reportlab.platypus import Paragraph from openslides.config.api import config -from openslides.projector.api import get_active_slide, update_projector +from openslides.projector.api import ( + get_active_object, + get_active_slide, + get_projector_overlays_js, + get_overlays, + update_projector) from openslides.utils.exceptions import OpenSlidesError from openslides.utils.pdf import stylesheet from openslides.utils.utils import html_strong from openslides.utils.views import ( + AjaxMixin, CreateView, CSVImportView, DeleteView, @@ -630,6 +642,108 @@ class CurrentListOfSpeakersView(RedirectView): return reverse('item_view', args=[item.pk]) +class CurrentListOfSpeakersProjectorView(AjaxMixin, TemplateView): + """ + View with the current list of speakers depending on the active slide. + Usefule for the projector. + """ + template_name = 'agenda/current_list_of_speakers_projector.html' + + def get(self, request, *args, **kwargs): + """ + Returns response object depending on request type (ajax or normal). + """ + if request.is_ajax(): + value = self.ajax_get(request, *args, **kwargs) + else: + value = super(CurrentListOfSpeakersProjectorView, self).get(request, *args, **kwargs) + return value + + def get_item(self): + """ + Returns the item of the current slide is an agenda item slide or a + slide of a related model else returns None. + """ + slide_object = get_active_object() + if slide_object is None or isinstance(slide_object, Item): + item = slide_object + else: + # TODO: If there is more than one item, use the first one in the + # mptt tree that is not closed. + try: + item = Item.objects.filter( + content_type=ContentType.objects.get_for_model(slide_object), + object_id=slide_object.pk)[0] + except IndexError: + item = None + return item + + def get_content(self): + """ + Returns the content of this slide. + """ + item = self.get_item() + if item is None: + content = mark_safe('