diff --git a/CHANGELOG b/CHANGELOG
index cd5ca7186..37dfc1c8f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -11,7 +11,7 @@ Version 2.0.0 (unreleased)
Agenda:
- Updated the tests and changed only small internal parts of method of the
agenda model. No API changes.
-- Deprecated mptt.
+- Removed mptt.
Assignments:
- Renamed app from assignment to assignments.
- Massive refactoring and cleanup of the app.
@@ -48,6 +48,7 @@ Other:
Sheets libraries.
- Used setup.cfg for development tools.
- Fixed bug in LocalizedModelMultipleChoiceField.
+- Removed the django error pages
Version 1.7 (2015-02-16)
diff --git a/openslides/__main__.py b/openslides/__main__.py
index 003ed36c7..9eb0b4a39 100644
--- a/openslides/__main__.py
+++ b/openslides/__main__.py
@@ -7,14 +7,15 @@ from django.core.management import execute_from_command_line
from openslides import __version__ as openslides_version
from openslides.utils.main import (
- get_default_settings_path,
- setup_django_settings_module,
- write_settings,
- UnknownCommand,
ExceptionArgumentParser,
+ UnknownCommand,
+ get_default_settings_path,
get_development_settings_path,
+ is_development,
+ setup_django_settings_module,
start_browser,
- is_development)
+ write_settings,
+)
def main():
diff --git a/openslides/account/__init__.py b/openslides/account/__init__.py
deleted file mode 100644
index 217ee87bc..000000000
--- a/openslides/account/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-default_app_config = 'openslides.account.apps.AccountAppConfig'
diff --git a/openslides/account/apps.py b/openslides/account/apps.py
deleted file mode 100644
index bc1350505..000000000
--- a/openslides/account/apps.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from django.apps import AppConfig
-
-
-class AccountAppConfig(AppConfig):
- name = 'openslides.account'
- verbose_name = 'OpenSlides Account'
-
- def ready(self):
- # Load widget.
- from . import widgets # noqa
diff --git a/openslides/account/templates/account/widget_personal_info.html b/openslides/account/templates/account/widget_personal_info.html
deleted file mode 100644
index d8b37ba8e..000000000
--- a/openslides/account/templates/account/widget_personal_info.html
+++ /dev/null
@@ -1,22 +0,0 @@
-{% extends 'core/widget.html' %}
-
-{% load i18n %}
-{% load tags %}
-
-{% block content %}
- {% for infoblock in infoblocks %}
- {% if infoblock.is_active %}
-
- {{ infoblock.headline }}:
- {% for object in infoblock.get_queryset %}
- {{ object }}
- {% empty %}
- {% trans 'None' %}
- {% endfor %}
-
- {% if not forloop.last %}
-
- {% endif %}
- {% endif %}
- {% endfor %}
-{% endblock %}
diff --git a/openslides/account/widgets.py b/openslides/account/widgets.py
deleted file mode 100644
index 09fb46d23..000000000
--- a/openslides/account/widgets.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from django.contrib.auth.models import AnonymousUser
-from django.utils.translation import ugettext_lazy
-
-from openslides.utils.personal_info import PersonalInfo
-from openslides.utils.widgets import Widget
-
-
-class PersonalInfoWidget(Widget):
- """
- Provides a widget for personal info. It shows all info block given by the
- personal info api. See openslides.utils.personal_info.PersonalInfo.
- """
- name = 'personal_info'
- verbose_name = ugettext_lazy('My personal info')
- default_column = 1
- default_weight = 80
- template_name = 'account/widget_personal_info.html'
- icon_css_class = 'icon-flag'
-
- def check_permission(self):
- """
- The widget is disabled for anonymous users.
- """
- return not isinstance(self.request.user, AnonymousUser)
-
- def is_active(self):
- """
- The widget is disabled if there are no info blocks at the moment.
- """
- for infoblock in PersonalInfo.get_all(self.request):
- if infoblock.is_active():
- active = super(PersonalInfoWidget, self).is_active()
- break
- else:
- active = False
- return active
-
- def get_context_data(self, **context):
- """
- Adds the context to the widget.
- """
- return super(PersonalInfoWidget, self).get_context_data(infoblocks=PersonalInfo.get_all(self.request), **context)
diff --git a/openslides/agenda/apps.py b/openslides/agenda/apps.py
index e7a02aefc..629075e07 100644
--- a/openslides/agenda/apps.py
+++ b/openslides/agenda/apps.py
@@ -6,28 +6,16 @@ class AgendaAppConfig(AppConfig):
verbose_name = 'OpenSlides Agenda'
def ready(self):
- # Load main menu entry, personal info and widgets.
- # Do this by just importing all from these files.
- from . import main_menu, personal_info, widgets # noqa
-
# Import all required stuff.
from django.db.models.signals import pre_delete
from openslides.config.signals import config_signal
- from openslides.projector.api import register_slide
- from openslides.projector.signals import projector_overlays
from openslides.utils.rest_api import router
- from .signals import agenda_list_of_speakers, setup_agenda_config, listen_to_related_object_delete_signal
- from .slides import agenda_slide
+ from .signals import setup_agenda_config, listen_to_related_object_delete_signal
from .views import ItemViewSet
# Connect signals.
config_signal.connect(setup_agenda_config, dispatch_uid='setup_agenda_config')
- projector_overlays.connect(agenda_list_of_speakers, dispatch_uid='agenda_list_of_speakers')
pre_delete.connect(listen_to_related_object_delete_signal, dispatch_uid='agenda_listen_to_related_object_delete_signal')
- # Register slides.
- Item = self.get_model('Item')
- register_slide('agenda', agenda_slide, Item)
-
# Register viewsets.
router.register('agenda/item', ItemViewSet)
diff --git a/openslides/agenda/csv_import.py b/openslides/agenda/csv_import.py
deleted file mode 100644
index 65fb90ff0..000000000
--- a/openslides/agenda/csv_import.py
+++ /dev/null
@@ -1,53 +0,0 @@
-import csv
-import re
-
-from django.db import transaction
-from django.utils.translation import ugettext as _
-
-from openslides.utils import csv_ext
-
-from .models import Item
-
-
-def import_agenda_items(csvfile):
- """
- Performs the import of agenda items form a csv file.
- """
- # Check encoding
- try:
- csvfile.read().decode('utf8')
- except UnicodeDecodeError:
- return_value = '', '', _('Import file has wrong character encoding, only UTF-8 is supported!')
- else:
- csvfile.seek(0)
- # Check dialect
- dialect = csv.Sniffer().sniff(csvfile.readline().decode('utf8'))
- dialect = csv_ext.patchup(dialect)
- csvfile.seek(0)
- # Parse CSV file
- with transaction.atomic():
- success_lines = []
- error_lines = []
- for (line_no, line) in enumerate(csv.reader(
- (line.decode('utf8') for line in csvfile.readlines()), dialect=dialect)):
- if line_no == 0:
- # Do not read the header line
- continue
- # Check format
- try:
- title, text, duration = line[:3]
- except ValueError:
- error_lines.append(line_no + 1)
- continue
- if duration and re.match('^(?:[0-9]{1,2}:[0-5][0-9]|[0-9]+)$', duration) is None:
- error_lines.append(line_no + 1)
- continue
- Item.objects.create(title=title, text=text, duration=duration)
- success_lines.append(line_no + 1)
- success = _('%d items successfully imported.') % len(success_lines)
- if error_lines:
- error = _('Error in the following lines: %s.') % ', '.join(str(number) for number in error_lines)
- else:
- error = ''
- return_value = success, '', error
- return return_value
diff --git a/openslides/agenda/forms.py b/openslides/agenda/forms.py
deleted file mode 100644
index aab531b27..000000000
--- a/openslides/agenda/forms.py
+++ /dev/null
@@ -1,80 +0,0 @@
-import re
-
-from ckeditor.widgets import CKEditorWidget
-from django import forms
-from django.utils.translation import ugettext_lazy
-from mptt.forms import TreeNodeChoiceField
-
-from openslides.utils.forms import CssClassMixin, CleanHtmlFormMixin
-from openslides.users.models import User
-
-from .models import Item, Speaker
-
-
-class ItemForm(CleanHtmlFormMixin, CssClassMixin, forms.ModelForm):
- """
- Form to create of update an item.
- """
- clean_html_fields = ('text', )
-
- parent = TreeNodeChoiceField(
- queryset=Item.objects.all(), label=ugettext_lazy("Parent item"), required=False)
-
- duration = forms.RegexField(
- regex=re.compile('^(?:[0-9]{1,2}:[0-5][0-9]|[0-9]+)$'),
- error_message=ugettext_lazy("Invalid format. Hours from 0 to 99 and minutes from 00 to 59"),
- max_length=5,
- required=False,
- label=ugettext_lazy("Duration"),
- help_text=ugettext_lazy('Input format: HH:MM or M or MM or MMM'))
-
- class Meta:
- model = Item
- fields = ('item_number', 'title', 'text', 'comment', 'tags', 'type', 'duration', 'parent', 'speaker_list_closed')
- widgets = {'text': CKEditorWidget(config_name='images')}
-
-
-class RelatedItemForm(ItemForm):
- """
- Form to update an related item.
- """
- class Meta:
- model = Item
- fields = ('comment', 'duration', 'parent', 'speaker_list_closed')
-
-
-class ItemOrderForm(CssClassMixin, forms.Form):
- """
- Form to change the order of the items.
- """
- weight = forms.IntegerField(
- widget=forms.HiddenInput(attrs={'class': 'menu-weight'}))
- self = forms.IntegerField(
- widget=forms.HiddenInput(attrs={'class': 'menu-mlid'}))
- parent = forms.IntegerField(
- widget=forms.HiddenInput(attrs={'class': 'menu-plid'}))
-
-
-class AppendSpeakerForm(CssClassMixin, forms.Form):
- """
- Form to set an user to a list of speakers.
- """
- speaker = forms.ModelChoiceField(
- User.objects.all(),
- widget=forms.Select(attrs={'class': 'medium-input'}),
- label=ugettext_lazy("Add participant"))
-
- def __init__(self, item, *args, **kwargs):
- self.item = item
- return super(AppendSpeakerForm, self).__init__(*args, **kwargs)
-
- def clean_speaker(self):
- """
- Checks, that the user is not already on the list.
- """
- speaker = self.cleaned_data['speaker']
- if Speaker.objects.filter(user=speaker, item=self.item, begin_time=None).exists():
- raise forms.ValidationError(ugettext_lazy(
- '%s is already on the list of speakers.'
- % str(speaker)))
- return speaker
diff --git a/openslides/agenda/main_menu.py b/openslides/agenda/main_menu.py
deleted file mode 100644
index f97d00804..000000000
--- a/openslides/agenda/main_menu.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.utils.main_menu import MainMenuEntry
-
-
-class AgendaMainMenuEntry(MainMenuEntry):
- """
- Main menu entry for the agenda app.
- """
- verbose_name = ugettext_lazy('Agenda')
- required_permission = 'agenda.can_see'
- default_weight = 20
- pattern_name = '/agenda' # TODO: use generic solution, see issue #1469
- icon_css_class = 'glyphicon-calendar'
diff --git a/openslides/agenda/models.py b/openslides/agenda/models.py
index edf383215..0000866e5 100644
--- a/openslides/agenda/models.py
+++ b/openslides/agenda/models.py
@@ -4,30 +4,22 @@ from django.contrib.auth.models import AnonymousUser
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
-from django.core.urlresolvers import reverse
from django.db import models
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
-from mptt.models import MPTTModel, TreeForeignKey
from openslides.config.api import config
from openslides.core.models import Tag
-from openslides.projector.api import (reset_countdown,
- start_countdown, stop_countdown)
from openslides.projector.models import SlideMixin
+from openslides.users.models import User
from openslides.utils.exceptions import OpenSlidesError
-from openslides.utils.models import AbsoluteUrlMixin
from openslides.utils.rest_api import RESTModelMixin
from openslides.utils.utils import to_roman
-from openslides.users.models import User
-# TODO: remove mptt after removing the django views and forms
-class Item(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, MPTTModel):
+class Item(RESTModelMixin, SlideMixin, models.Model):
"""
An Agenda Item
-
- MPTT-model. See http://django-mptt.github.com/django-mptt/
"""
slide_callback_name = 'agenda'
@@ -76,8 +68,7 @@ class Item(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, MPTTModel):
The intended duration for the topic.
"""
- parent = TreeForeignKey('self', null=True, blank=True,
- related_name='children')
+ parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
"""
The parent item in the agenda tree.
"""
@@ -119,44 +110,35 @@ class Item(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, MPTTModel):
('can_manage', ugettext_noop("Can manage agenda")),
('can_see_orga_items', ugettext_noop("Can see orga items and time scheduling of agenda")))
- class MPTTMeta:
- order_insertion_by = ['weight']
+ def __str__(self):
+ return self.get_title()
def clean(self):
"""
Ensures that the children of orga items are only orga items.
"""
- if self.type == self.AGENDA_ITEM and self.parent is not None and self.parent.type == self.ORGANIZATIONAL_ITEM:
+ if (self.type == self.AGENDA_ITEM and
+ self.parent is not None and
+ self.parent.type == self.ORGANIZATIONAL_ITEM):
raise ValidationError(_('Agenda items can not be child elements of an organizational item.'))
- if self.type == self.ORGANIZATIONAL_ITEM and self.get_descendants().filter(type=self.AGENDA_ITEM).exists():
+ if (self.type == self.ORGANIZATIONAL_ITEM and
+ self.children.filter(type=self.AGENDA_ITEM).exists()):
raise ValidationError(_('Organizational items can not have agenda items as child elements.'))
return super().clean()
- def __str__(self):
- return self.get_title()
-
- def get_absolute_url(self, link='detail'):
+ def delete(self, with_children=False):
"""
- Return the URL to this item.
+ Delete the Item.
- The link can be detail, update or delete.
+ If with_children is True, all children of the item will be deleted as
+ well. If with_children is False, all children will be children of the
+ parent of the item.
"""
- if link == 'detail':
- url = reverse('item_view', args=[str(self.id)])
- elif link == 'update':
- url = reverse('item_edit', args=[str(self.id)])
- elif link == 'delete':
- url = reverse('item_delete', args=[str(self.id)])
- elif link == 'projector_list_of_speakers':
- url = '%s&type=list_of_speakers' % super().get_absolute_url('projector')
- elif link == 'projector_summary':
- url = '%s&type=summary' % super().get_absolute_url('projector')
- elif (link in ('projector', 'projector_preview') and
- self.content_object and isinstance(self.content_object, SlideMixin)):
- url = self.content_object.get_absolute_url(link)
- else:
- url = super().get_absolute_url(link)
- return url
+ if not with_children:
+ for child in self.children.all():
+ child.parent = self.parent
+ child.save()
+ super().delete()
def get_title(self):
"""
@@ -183,39 +165,6 @@ class Item(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, MPTTModel):
except AttributeError:
raise NotImplementedError('You have to provide a get_agenda_title_supplement method on your related model.')
- @property
- def weight_form(self):
- """
- Return the WeightForm for this item.
- """
- from openslides.agenda.forms import ItemOrderForm
- try:
- parent = self.parent.id
- except AttributeError:
- parent = 0
- initial = {
- 'weight': self.weight,
- 'self': self.id,
- 'parent': parent,
- }
- return ItemOrderForm(initial=initial, prefix="i%d" % self.id)
-
- def delete(self, with_children=False):
- """
- Delete the Item.
-
- If with_children is True, all children of the item will be deleted as
- well. If with_children is False, all children will be children of the
- parent of the item.
- """
- if not with_children:
- for child in self.get_children():
- child.move_to(self.parent)
- child.save()
- super().delete()
- # TODO: Try to remove the rebuild call
- Item.objects.rebuild()
-
def get_list_of_speakers(self, old_speakers_count=None, coming_speakers_count=None):
"""
Returns the list of speakers as a list of dictionaries. Each
@@ -316,27 +265,28 @@ class Item(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, MPTTModel):
Returns the number of this agenda item.
"""
if self.type == self.AGENDA_ITEM:
- if self.is_root_node():
+ if self.parent is None:
+ sibling_no = self.sibling_no()
if config['agenda_numeral_system'] == 'arabic':
- return str(self._calc_sibling_no())
+ return str(sibling_no)
else: # config['agenda_numeral_system'] == 'roman'
- return to_roman(self._calc_sibling_no())
+ return to_roman(sibling_no)
else:
- return '%s.%s' % (self.parent.calc_item_no(), self._calc_sibling_no())
+ return '%s.%s' % (self.parent.calc_item_no(), self.sibling_no())
else:
return ''
- def _calc_sibling_no(self):
+ def sibling_no(self):
"""
- Counts all siblings on the same level which are AGENDA_ITEMs.
+ Counts how many AGENDA_ITEMS with the same parent (siblings) have a
+ smaller weight then this item.
+
+ Returns this number + 1 or 0 when self is not an AGENDA_ITEM.
"""
- sibling_no = 0
- prev_sibling = self.get_previous_sibling()
- while prev_sibling is not None:
- if prev_sibling.type == self.AGENDA_ITEM:
- sibling_no += 1
- prev_sibling = prev_sibling.get_previous_sibling()
- return sibling_no + 1
+ return Item.objects.filter(
+ parent=self.parent,
+ type=self.AGENDA_ITEM,
+ weight__lte=self.weight).count()
class SpeakerManager(models.Manager):
@@ -353,7 +303,7 @@ class SpeakerManager(models.Manager):
return self.create(item=item, user=user, weight=weight + 1)
-class Speaker(RESTModelMixin, AbsoluteUrlMixin, models.Model):
+class Speaker(RESTModelMixin, models.Model):
"""
Model for the Speaker list.
"""
@@ -393,16 +343,6 @@ class Speaker(RESTModelMixin, AbsoluteUrlMixin, models.Model):
def __str__(self):
return str(self.user)
- def get_absolute_url(self, link='detail'):
- if link == 'detail':
- url = self.user.get_absolute_url('detail')
- elif link == 'delete':
- url = reverse('agenda_speaker_delete',
- args=[self.item.pk, self.pk])
- else:
- url = super(Speaker, self).get_absolute_url(link)
- return url
-
def begin_speach(self):
"""
Let the user speak.
@@ -421,8 +361,10 @@ class Speaker(RESTModelMixin, AbsoluteUrlMixin, models.Model):
self.save()
# start countdown
if config['agenda_couple_countdown_and_speakers']:
- reset_countdown()
- start_countdown()
+ # TODO: Fix me with the new countdown api
+ # reset_countdown()
+ # start_countdown()
+ pass
def end_speach(self):
"""
@@ -432,7 +374,9 @@ class Speaker(RESTModelMixin, AbsoluteUrlMixin, models.Model):
self.save()
# stop countdown
if config['agenda_couple_countdown_and_speakers']:
- stop_countdown()
+ # TODO: Fix me with the new countdown api
+ # stop_countdown()
+ pass
def get_root_rest_element(self):
"""
diff --git a/openslides/agenda/personal_info.py b/openslides/agenda/personal_info.py
deleted file mode 100644
index b4dba94a7..000000000
--- a/openslides/agenda/personal_info.py
+++ /dev/null
@@ -1,18 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.utils.personal_info import PersonalInfo
-
-from .models import Item
-
-
-class AgendaPersonalInfo(PersonalInfo):
- """
- Class for user info block for the agenda app.
- """
- headline = ugettext_lazy('I am on the list of speakers of the following items')
- default_weight = 10
-
- def get_queryset(self):
- return Item.objects.filter(
- speaker__user=self.request.user,
- speaker__begin_time=None)
diff --git a/openslides/agenda/search_indexes.py b/openslides/agenda/search_indexes.py
index 48325529f..98319de4c 100644
--- a/openslides/agenda/search_indexes.py
+++ b/openslides/agenda/search_indexes.py
@@ -1,4 +1,5 @@
from haystack import indexes
+
from .models import Item
diff --git a/openslides/agenda/serializers.py b/openslides/agenda/serializers.py
index c00443b8a..c8c423d4e 100644
--- a/openslides/agenda/serializers.py
+++ b/openslides/agenda/serializers.py
@@ -1,6 +1,11 @@
from django.core.urlresolvers import reverse
-from openslides.utils.rest_api import CharField, ModelSerializer, RelatedField, get_collection_and_id_from_url
+from openslides.utils.rest_api import (
+ CharField,
+ ModelSerializer,
+ RelatedField,
+ get_collection_and_id_from_url,
+)
from .models import Item, Speaker
diff --git a/openslides/agenda/signals.py b/openslides/agenda/signals.py
index f87fae70e..f48a914bb 100644
--- a/openslides/agenda/signals.py
+++ b/openslides/agenda/signals.py
@@ -3,13 +3,10 @@ from datetime import datetime
from django import forms
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
-from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
-from openslides.config.api import config, ConfigCollection, ConfigVariable
-from openslides.projector.api import get_active_slide, get_active_object
-from openslides.projector.projector import Overlay
+from openslides.config.api import ConfigCollection, ConfigVariable
from .models import Item
@@ -90,54 +87,6 @@ def setup_agenda_config(sender, **kwargs):
'extra_javascript': extra_javascript})
-def agenda_list_of_speakers(sender, **kwargs):
- """
- Receiver function to setup the list of speaker overlay. It is connected
- to the signal openslides.projector.signals.projector_overlays during
- app loading.
- """
- name = 'agenda_speaker'
-
- def get_widget_html():
- """
- Returns the the html-code to show in the overly-widget.
- """
- return render_to_string('agenda/overlay_speaker_widget.html')
-
- def get_projector_html():
- """
- Returns an html-code to show on the projector.
-
- The overlay is only shown on agenda-items and not on the
- list-of-speakers slide.
- """
- slide = get_active_object()
- if slide is None or isinstance(slide, Item):
- item = slide
- 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_id=slide.pk)[0]
- except IndexError:
- item = None
- if item and get_active_slide().get('type', None) != 'list_of_speakers':
- list_of_speakers = item.get_list_of_speakers(
- old_speakers_count=config['agenda_show_last_speakers'],
- coming_speakers_count=5)
-
- value = render_to_string('agenda/overlay_speaker_projector.html', {
- 'list_of_speakers': list_of_speakers,
- 'closed': item.speaker_list_closed})
- else:
- value = None
- return value
-
- return Overlay(name, get_widget_html, get_projector_html)
-
-
def listen_to_related_object_delete_signal(sender, instance, **kwargs):
"""
Receiver function to changed agenda items of a related items that is to
diff --git a/openslides/agenda/slides.py b/openslides/agenda/slides.py
deleted file mode 100644
index 171a84086..000000000
--- a/openslides/agenda/slides.py
+++ /dev/null
@@ -1,60 +0,0 @@
-from django.template.loader import render_to_string
-
-from openslides.config.api import config
-from openslides.projector.api import get_projector_content
-
-from .models import Item
-
-
-def agenda_slide(**kwargs):
- """
- Return the html code for all slides of the agenda app.
-
- If no id is given, show a summary of all parent items.
-
- If an id is given, show the item depending of the argument 'type'.
-
- If 'type' is not set, show only the item.
-
- If 'type' is 'summary', show a summary of all children of the item.
-
- If 'type' is 'list_of_speakers', show the list of speakers for the item.
-
- The function is registered during app loading.
- """
- item_pk = kwargs.get('pk', None)
- slide_type = kwargs.get('type', None)
-
- try:
- item = Item.objects.get(pk=item_pk)
- except Item.DoesNotExist:
- item = None
-
- if slide_type == 'summary' or item is None:
- context = {}
- if item is None:
- items = Item.objects.filter(parent=None, type__exact=Item.AGENDA_ITEM)
- else:
- items = item.get_children().filter(type__exact=Item.AGENDA_ITEM)
- context['title'] = item.get_title()
- context['items'] = items
- slide = render_to_string('agenda/item_slide_summary.html', context)
-
- elif slide_type == 'list_of_speakers':
- list_of_speakers = item.get_list_of_speakers(
- old_speakers_count=config['agenda_show_last_speakers'])
- context = {'title': item.get_title(),
- 'item': item,
- 'list_of_speakers': list_of_speakers}
- slide = render_to_string('agenda/item_slide_list_of_speaker.html', context)
-
- elif item.content_object:
- slide_dict = {
- 'callback': item.content_object.slide_callback_name,
- 'pk': item.content_object.pk}
- slide = get_projector_content(slide_dict)
-
- else:
- context = {'item': item}
- slide = render_to_string('agenda/item_slide.html', context)
- return slide
diff --git a/openslides/agenda/templates/agenda/current_list_of_speakers_projector.html b/openslides/agenda/templates/agenda/current_list_of_speakers_projector.html
deleted file mode 100644
index 10dd26791..000000000
--- a/openslides/agenda/templates/agenda/current_list_of_speakers_projector.html
+++ /dev/null
@@ -1,4 +0,0 @@
-{% extends 'projector.html' %}
-{% load i18n %}
-
-{% block title %}{% trans 'List of speakers' %} – {{ block.super }}{% endblock %}
diff --git a/openslides/agenda/templates/agenda/item_slide.html b/openslides/agenda/templates/agenda/item_slide.html
deleted file mode 100644
index 4d0022053..000000000
--- a/openslides/agenda/templates/agenda/item_slide.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% load i18n %}
-{% load staticfiles %}
-
-
-
-
- {{ item }}
-
-
-{% if item.text %}
- {{ item.text|safe }}
-{% endif %}
diff --git a/openslides/agenda/templates/agenda/item_slide_list_of_speaker.html b/openslides/agenda/templates/agenda/item_slide_list_of_speaker.html
deleted file mode 100644
index 201912753..000000000
--- a/openslides/agenda/templates/agenda/item_slide_list_of_speaker.html
+++ /dev/null
@@ -1,27 +0,0 @@
-{% load i18n %}
-{% load staticfiles %}
-
-
-
-
- {{ title }}
-
- {% trans 'List of speakers' %}
- {% if item.speaker_list_closed %}({% trans 'closed' %} ){% endif %}
-
-
-
-{% if list_of_speakers %}
-
- {% for speaker_dict in list_of_speakers %}
- {# old_speaker, actual_speaker, coming_speaker #}
- {% if speaker_dict.type == 'coming_speaker' %}
- {{ speaker_dict.prefix }}.
- {% endif %}
- {{ speaker_dict.speaker }}
-
- {% endfor %}
-
-{% else %}
- {% trans 'The list of speakers is empty.' %}
-{% endif %}
diff --git a/openslides/agenda/templates/agenda/item_slide_summary.html b/openslides/agenda/templates/agenda/item_slide_summary.html
deleted file mode 100644
index 5f29881fb..000000000
--- a/openslides/agenda/templates/agenda/item_slide_summary.html
+++ /dev/null
@@ -1,17 +0,0 @@
-{% load i18n %}
-{% load staticfiles %}
-
-
-
-
- {% if title %}{{ title }}{% else %}{% trans "Agenda" %}{% endif %}
-
-
-
- {% for item in items %}
-
- {{ item }}
- {{ item.get_title_supplement|safe }}
-
- {% endfor %}
-
diff --git a/openslides/agenda/templates/agenda/overlay_speaker_projector.html b/openslides/agenda/templates/agenda/overlay_speaker_projector.html
deleted file mode 100644
index 209969bd6..000000000
--- a/openslides/agenda/templates/agenda/overlay_speaker_projector.html
+++ /dev/null
@@ -1,22 +0,0 @@
-{% load i18n %}
-{% load staticfiles %}
-
-
-
-
-
{% trans "List of speakers" %} {% if closed %}({% trans 'closed' %} ){% endif %}
- {% if list_of_speakers %}
-
- {% for speaker_dict in list_of_speakers %}
- {# old_speaker, actual_speaker, coming_speaker #}
- {% if speaker_dict.type == 'coming_speaker' %}
- {{ speaker_dict.prefix }}.
- {% endif %}
- {{ speaker_dict.speaker }}
-
- {% endfor %}
-
- {% else %}
-
{% trans 'The list of speakers is empty.' %}
- {% endif %}
-
diff --git a/openslides/agenda/templates/agenda/overlay_speaker_widget.html b/openslides/agenda/templates/agenda/overlay_speaker_widget.html
deleted file mode 100644
index e04535cad..000000000
--- a/openslides/agenda/templates/agenda/overlay_speaker_widget.html
+++ /dev/null
@@ -1,6 +0,0 @@
-{% load i18n %}
-
-
- {% trans 'List of speakers' %}
- ({% trans 'This overlay only appears on agenda slides if it is activated.' %})
-
diff --git a/openslides/agenda/templates/agenda/widget_item.html b/openslides/agenda/templates/agenda/widget_item.html
deleted file mode 100644
index e69de29bb..000000000
diff --git a/openslides/agenda/templates/agenda/widget_list_of_speakers.html b/openslides/agenda/templates/agenda/widget_list_of_speakers.html
deleted file mode 100644
index e69de29bb..000000000
diff --git a/openslides/agenda/urls.py b/openslides/agenda/urls.py
index 922cdef70..0167c21a9 100644
--- a/openslides/agenda/urls.py
+++ b/openslides/agenda/urls.py
@@ -4,14 +4,7 @@ from . import views
urlpatterns = patterns(
'',
-
- # PDF
url(r'^print/$',
views.AgendaPDF.as_view(),
name='agenda_pdf'),
-
- # TODO: remove it after implement projector rest api
- url(r'^list_of_speakers/projector/$',
- views.CurrentListOfSpeakersProjectorView.as_view(),
- name='agenda_current_list_of_speakers_projector'),
)
diff --git a/openslides/agenda/views.py b/openslides/agenda/views.py
index dc3f34935..0cdf00d40 100644
--- a/openslides/agenda/views.py
+++ b/openslides/agenda/views.py
@@ -1,24 +1,11 @@
-# TODO: Rename all views and template names
-
from cgi import escape
from collections import defaultdict
-from json import dumps
from django.contrib.auth import get_user_model
-from django.contrib.contenttypes.models import ContentType
-from django.contrib.staticfiles.templatetags.staticfiles import static
-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_object,
- get_projector_overlays_js,
- get_overlays)
from openslides.utils.exceptions import OpenSlidesError
from openslides.utils.pdf import stylesheet
from openslides.utils.rest_api import (
@@ -28,35 +15,12 @@ from openslides.utils.rest_api import (
detail_route,
list_route,
)
-from openslides.utils.views import (
- AjaxMixin,
- PDFView,
- RedirectView,
- SingleObjectMixin,
- TemplateView)
+from openslides.utils.views import PDFView
from .models import Item, Speaker
from .serializers import ItemSerializer
-class CreateRelatedAgendaItemView(SingleObjectMixin, RedirectView):
- """
- View to create and agenda item for a related object.
-
- This view is only for subclassing in views of related apps. You
- have to define 'model = ....'
- """
- required_permission = 'agenda.can_manage'
- url_name = 'item_overview'
- url_name_args = []
-
- def pre_redirect(self, request, *args, **kwargs):
- """
- Create the agenda item.
- """
- self.item = Item.objects.create(content_object=self.get_object())
-
-
class AgendaPDF(PDFView):
"""
Create a full agenda-PDF.
@@ -77,108 +41,6 @@ class AgendaPDF(PDFView):
story.append(Paragraph(escape(item.get_title()), stylesheet['Item']))
-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('%s %s \n' % (_('List of speakers'), _('Not available.')))
- else:
- content_dict = {
- 'title': item.get_title(),
- 'item': item,
- 'list_of_speakers': item.get_list_of_speakers(
- old_speakers_count=config['agenda_show_last_speakers'])}
- content = render_to_string('agenda/item_slide_list_of_speaker.html', content_dict)
- return content
-
- def get_overlays_and_overlay_js(self):
- """
- Returns the overlays and their JavaScript for this slide as a
- two-tuple. The overlay 'agenda_speaker' is always excluded.
-
- The required JavaScript fot this view is inserted.
- """
- overlays = get_overlays(only_active=True)
- overlays.pop('agenda_speaker', None)
- overlay_js = get_projector_overlays_js(as_json=True)
- # Note: The JavaScript content of overlay 'agenda_speaker' is not
- # excluded because this overlay has no such content at the moment.
- extra_js = SortedDict()
- extra_js['load_file'] = static('js/agenda_current_list_of_speakers_projector.js')
- extra_js['call'] = 'reloadListOfSpeakers();'
- extra_js = dumps(extra_js)
- overlay_js.append(extra_js)
- return overlays, overlay_js
-
- def get_context_data(self, **context):
- """
- Returns the context for the projector template. Contains the content
- of this slide.
- """
- overlays, overlay_js = self.get_overlays_and_overlay_js()
- return super(CurrentListOfSpeakersProjectorView, self).get_context_data(
- content=self.get_content(),
- overlays=overlays,
- overlay_js=overlay_js,
- **context)
-
- def get_ajax_context(self, **context):
- """
- Returns the context including the slide content for ajax response. The
- overlay 'agenda_speaker' is always excluded.
- """
- overlay_dict = {}
- for overlay in get_overlays().values():
- if overlay.is_active() and overlay.name != 'agenda_speaker':
- overlay_dict[overlay.name] = {
- 'html': overlay.get_projector_html(),
- 'javascript': overlay.get_javascript()}
- else:
- overlay_dict[overlay.name] = None
- return super(CurrentListOfSpeakersProjectorView, self).get_ajax_context(
- content=self.get_content(),
- overlays=overlay_dict,
- **context)
-
-
class ItemViewSet(ModelViewSet):
"""
API endpoint to list, retrieve, create, update and destroy agenda items.
diff --git a/openslides/agenda/widgets.py b/openslides/agenda/widgets.py
deleted file mode 100644
index 32290a2ca..000000000
--- a/openslides/agenda/widgets.py
+++ /dev/null
@@ -1,50 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.utils.widgets import Widget
-from openslides.projector.api import get_active_slide
-
-from .models import Item
-
-
-class AgendaWidget(Widget):
- """
- Agenda widget.
- """
- name = 'agenda'
- verbose_name = ugettext_lazy('Agenda')
- required_permission = 'core.can_manage_projector'
- default_column = 1
- default_weight = 20
- template_name = 'agenda/widget_item.html'
- icon_css_class = 'icon-calendar'
- more_link_pattern_name = 'item_overview'
-
- def get_context_data(self, **context):
- active_slide = get_active_slide()
- if active_slide['callback'] == 'agenda':
- agenda_is_active = active_slide.get('pk', 'agenda') == 'agenda'
- active_type = active_slide.get('type', 'text')
- else:
- agenda_is_active = None
- active_type = None
- context.update({
- 'agenda_is_active': agenda_is_active,
- 'items': Item.objects.all(),
- 'active_type': active_type})
- return super(AgendaWidget, self).get_context_data(**context)
-
-
-class ListOfSpeakersWidget(Widget):
- """
- Widget to control the list of speakers.
- """
- name = 'append_to_list_of_speakers'
- verbose_name = ugettext_lazy('List of speakers')
- default_column = 1
- default_weight = 30
- template_name = 'agenda/widget_list_of_speakers.html'
- icon_css_class = 'icon-bell'
-
- def check_permission(self):
- return (self.request.user.has_perm('agenda.can_manage') or
- self.request.user.has_perm('agenda.can_be_speaker'))
diff --git a/openslides/assignments/apps.py b/openslides/assignments/apps.py
index d144d057f..0aa89656c 100644
--- a/openslides/assignments/apps.py
+++ b/openslides/assignments/apps.py
@@ -6,31 +6,15 @@ class AssignmentAppConfig(AppConfig):
verbose_name = 'OpenSlides Assignments'
def ready(self):
- # Load main menu entry, personal info and widgets.
- # Do this by just importing all from these files.
- from . import main_menu, personal_info, widgets # noqa
-
# Import all required stuff.
from openslides.config.signals import config_signal
- from openslides.projector.api import register_slide_model
from openslides.utils.rest_api import router
- from openslides.utils.signals import template_manipulation
from .signals import setup_assignment_config
- from .template import add_assignment_stylesheets
from .views import AssignmentViewSet, AssignmentPollViewSet
# Connect signals.
config_signal.connect(setup_assignment_config, dispatch_uid='setup_assignment_config')
- # Connect template signal.
- template_manipulation.connect(add_assignment_stylesheets, dispatch_uid='add_assignment_stylesheets')
-
- # Register slides.
- Assignment = self.get_model('Assignment')
- AssignmentPoll = self.get_model('AssignmentPoll')
- register_slide_model(Assignment, 'assignments/slide.html')
- register_slide_model(AssignmentPoll, 'assignments/assignmentpoll_slide.html')
-
# Register viewsets.
router.register('assignments/assignment', AssignmentViewSet)
router.register('assignments/assignmentpoll', AssignmentPollViewSet)
diff --git a/openslides/assignments/forms.py b/openslides/assignments/forms.py
deleted file mode 100644
index 97ffcd268..000000000
--- a/openslides/assignments/forms.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from django import forms
-from django.utils.translation import ugettext_lazy
-
-from openslides.users.models import User
-from openslides.utils.forms import CssClassMixin
-
-from .models import Assignment
-
-
-class AssignmentForm(CssClassMixin, forms.ModelForm):
- open_posts = forms.IntegerField(
- min_value=1, initial=1, label=ugettext_lazy("Number of available posts"))
-
- class Meta:
- model = Assignment
- fields = ('title', 'description', 'open_posts', 'poll_description_default')
-
-
-class AssignmentRunForm(CssClassMixin, forms.Form):
- candidate = forms.ModelChoiceField(
- queryset=User.objects.all(),
- widget=forms.Select(attrs={'class': 'medium-input'}),
- label=ugettext_lazy("Nominate a participant"))
diff --git a/openslides/assignments/main_menu.py b/openslides/assignments/main_menu.py
deleted file mode 100644
index 6e7eeb517..000000000
--- a/openslides/assignments/main_menu.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.utils.main_menu import MainMenuEntry
-
-
-class AssignmentMainMenuEntry(MainMenuEntry):
- """
- Main menu entry for the assignment app.
- """
- verbose_name = ugettext_lazy('Elections')
- required_permission = 'assignments.can_see'
- default_weight = 40
- pattern_name = '/assignments' # TODO: use generic solution, see issue #1469
- icon_css_class = 'icon-assignment'
diff --git a/openslides/assignments/models.py b/openslides/assignments/models.py
index b26f8e420..75d29ecb6 100644
--- a/openslides/assignments/models.py
+++ b/openslides/assignments/models.py
@@ -1,21 +1,23 @@
from django.contrib.contenttypes.fields import GenericRelation
-from django.core.urlresolvers import reverse
from django.db import models
from django.utils.datastructures import SortedDict
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
from openslides.agenda.models import Item, Speaker
-from openslides.core.models import Tag
from openslides.config.api import config
-from openslides.poll.models import (BaseOption, BasePoll, BaseVote,
- CollectDefaultVotesMixin,
- PublishPollMixin)
+from openslides.core.models import Tag
+from openslides.poll.models import (
+ BaseOption,
+ BasePoll,
+ BaseVote,
+ CollectDefaultVotesMixin,
+ PublishPollMixin,
+)
from openslides.projector.models import SlideMixin
-from openslides.utils.exceptions import OpenSlidesError
-from openslides.utils.models import AbsoluteUrlMixin
-from openslides.utils.rest_api import RESTModelMixin
from openslides.users.models import User
+from openslides.utils.exceptions import OpenSlidesError
+from openslides.utils.rest_api import RESTModelMixin
class AssignmentRelatedUser(RESTModelMixin, models.Model):
@@ -53,7 +55,7 @@ class AssignmentRelatedUser(RESTModelMixin, models.Model):
return self.assignment
-class Assignment(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, models.Model):
+class Assignment(RESTModelMixin, SlideMixin, models.Model):
slide_callback_name = 'assignment'
PHASE_SEARCH = 0
@@ -133,20 +135,6 @@ class Assignment(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, models.Model):
def __str__(self):
return self.title
- def get_absolute_url(self, link='detail'):
- """
- Returns absolute url to the assignment instance.
- """
- if link == 'detail':
- url = reverse('assignment_detail', args=[str(self.pk)])
- elif link == 'update':
- url = reverse('assignment_update', args=[str(self.pk)])
- elif link == 'delete':
- url = reverse('assignment_delete', args=[str(self.pk)])
- else:
- url = super().get_absolute_url(link)
- return url
-
def get_slide_context(self, **context):
"""
Retuns the context to generate the assignment slide.
@@ -351,7 +339,7 @@ class AssignmentOption(RESTModelMixin, BaseOption):
class AssignmentPoll(RESTModelMixin, SlideMixin, CollectDefaultVotesMixin,
- PublishPollMixin, AbsoluteUrlMixin, BasePoll):
+ PublishPollMixin, BasePoll):
slide_callback_name = 'assignmentpoll'
option_class = AssignmentOption
@@ -365,20 +353,6 @@ class AssignmentPoll(RESTModelMixin, SlideMixin, CollectDefaultVotesMixin,
def __str__(self):
return _("Ballot %d") % self.get_ballot()
- def get_absolute_url(self, link='update'):
- """
- Return an URL for the poll.
-
- The keyargument 'link' can be 'update' or 'delete'.
- """
- if link == 'update':
- url = reverse('assignmentpoll_update', args=[str(self.pk)])
- elif link == 'delete':
- url = reverse('assignmentpoll_delete', args=[str(self.pk)])
- else:
- url = super().get_absolute_url(link)
- return url
-
def get_assignment(self):
return self.assignment
diff --git a/openslides/assignments/personal_info.py b/openslides/assignments/personal_info.py
deleted file mode 100644
index c9630466a..000000000
--- a/openslides/assignments/personal_info.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.utils.personal_info import PersonalInfo
-
-from .models import Assignment, AssignmentRelatedUser
-
-
-class AssignmentPersonalInfo(PersonalInfo):
- """
- Class for personal info block for the assignment app.
- """
- headline = ugettext_lazy('I am candidate for the following elections')
- default_weight = 40
-
- def get_queryset(self):
- return (Assignment.objects.filter(assignment_related_users__user=self.request.user)
- .exclude(assignment_related_users__status=AssignmentRelatedUser.STATUS_BLOCKED))
diff --git a/openslides/assignments/search_indexes.py b/openslides/assignments/search_indexes.py
index 8a9dd4bc8..6bb39dfcc 100644
--- a/openslides/assignments/search_indexes.py
+++ b/openslides/assignments/search_indexes.py
@@ -1,4 +1,5 @@
from haystack import indexes
+
from .models import Assignment
diff --git a/openslides/assignments/serializers.py b/openslides/assignments/serializers.py
index 2ce6204e4..3effc730b 100644
--- a/openslides/assignments/serializers.py
+++ b/openslides/assignments/serializers.py
@@ -7,15 +7,17 @@ from openslides.utils.rest_api import (
ListField,
ListSerializer,
ModelSerializer,
- ValidationError)
+ ValidationError,
+)
from .models import (
- models,
Assignment,
- AssignmentRelatedUser,
AssignmentOption,
AssignmentPoll,
- AssignmentVote)
+ AssignmentRelatedUser,
+ AssignmentVote,
+ models,
+)
class AssignmentRelatedUserSerializer(ModelSerializer):
diff --git a/openslides/assignments/signals.py b/openslides/assignments/signals.py
index 56774c30e..7fbbb0b9a 100644
--- a/openslides/assignments/signals.py
+++ b/openslides/assignments/signals.py
@@ -2,7 +2,11 @@ from django import forms
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
-from openslides.config.api import ConfigGroup, ConfigGroupedCollection, ConfigVariable
+from openslides.config.api import (
+ ConfigGroup,
+ ConfigGroupedCollection,
+ ConfigVariable,
+)
from openslides.poll.models import PERCENT_BASE_CHOICES
diff --git a/openslides/assignments/template.py b/openslides/assignments/template.py
deleted file mode 100644
index 5cb21bb03..000000000
--- a/openslides/assignments/template.py
+++ /dev/null
@@ -1,7 +0,0 @@
-def add_assignment_stylesheets(sender, request, context, **kwargs):
- """
- Receiver function to add the assignment.css to the context. It is
- connected to the signal openslides.utils.signals.template_manipulation
- during app loading.
- """
- context['extra_stylefiles'].append('css/assignment.css')
diff --git a/openslides/assignments/templates/assignments/assignment_detail.html b/openslides/assignments/templates/assignments/assignment_detail.html
deleted file mode 100644
index 2601333c3..000000000
--- a/openslides/assignments/templates/assignments/assignment_detail.html
+++ /dev/null
@@ -1,356 +0,0 @@
-{% extends "base.html" %}
-
-{% load i18n %}
-{% load staticfiles %}
-{% load tags %}
-{% load humanize %}
-
-{% block title %}{% trans "Election" %} "{{ assignment }}" – {{ block.super }}{% endblock %}
-
-
-{% block javascript %}
-
-{% endblock %}
-
-{% block content %}
-
- {{ assignment }}
-
- {% trans "Election" %}
-
-
-
- {% trans "Back to overview" %}
-
-
-
- PDF
-
-
- {% if perms.core.can_manage_projector %}
-
-
-
- {% endif %}
- {% if perms.assignments.can_manage or perms.agenda.can_manage %}
-
- {% endif %}
-
-
-
-
-
-
- {% for tag in assignment.tags.all %}
-
{{ tag }}
- {% endfor %}
-
-
-
{% trans "Description" %}
- {% if assignment.description %}
- {{ assignment.description|linebreaks }}
- {% else %}
- –
- {% endif %}
-
-
-{% if assignment.phase != assignment.PHASE_FINISHED %}
-
{% trans "Candidates" %}
-
- {% for person in assignment.candidates %}
-
- {{ person }}
- {% if perms.assignments.can_manage %}
-
-
-
- {% endif %}
- {% if person in assignment.elected %}
- | {% trans "elected" %}
- {% if perms.assignments.can_manage %}
-
-
-
- {% endif %}
- {% endif %}
-
- {% empty %}
-
- {% trans "No candidates available." %}
-
- {% endfor %}
-
- {% if assignment.phase == assignment.PHASE_SEARCH or perms.assignments.can_manage and assignment.phase == assignment.PHASE_VOTING %}
- {% if perms.assignments.can_nominate_self or perms.assignments.can_nominate_other %}
-
- {% endif %}
- {% endif %}
-{% endif %}
-
-{% if perms.assignments.can_manage and blocked_candidates and assignment.phase != assignment.PHASE_FINISHED %}
-
{% trans "Blocked Candidates" %}
-
- {% for person in blocked_candidates %}
-
- {{ person }}
-
-
-
-
- {% empty %}
- {% trans "No blocked candidates available." %}
- {% endfor %}
-
-{% endif %}
-
-
-
-{% if assignment.phase != assignment.PHASE_SEARCH or polls.exists %}
-
{% trans "Election result" %}
- {% if polls.exists %}
-
- {% else %}
-
{% trans "No ballots available." %}
- {% if assignment.candidates and perms.assignments.can_manage and assignment.phase == assignment.PHASE_VOTING %}
-
-
-
- {% trans 'New ballot' %}
-
-
- {% endif %}
- {% endif %}
-{% endif %}
-
-
-
-
-
-
{% trans "Phases" %}:
- {% trans assignment.get_phase_display %}
-
- {% trans "Number of available posts" %}:
- {{ assignment.posts }}
-
-
- {% if perms.assignments.can_manage %}
-
-
{% trans "Change phase" %}:
-
-
- {% endif %}
-
-
-{% endblock %}
diff --git a/openslides/assignments/templates/assignments/assignmentpoll_form.html b/openslides/assignments/templates/assignments/assignmentpoll_form.html
deleted file mode 100644
index 45f5fcb3c..000000000
--- a/openslides/assignments/templates/assignments/assignmentpoll_form.html
+++ /dev/null
@@ -1,112 +0,0 @@
-{% extends 'base.html' %}
-
-{% load i18n %}
-{% load humanize %}
-{% load tags %}
-
-{% block title %}{% trans "Election" %} "{{ assignment }}", {{ ballotnumber }}. {% trans "ballot" %} – {{ block.super }}{% endblock %}
-
-{% block content %}
-
- {{ assignment }}
-
- {{ ballotnumber|ordinal|safe }} {% trans "ballot" %}
-
-
- {% trans "Back to election" %}
-
- {% if perms.core.can_manage_projector %}
-
-
-
-
- {% trans "Election result" %}
- {% endif %}
- {% if perms.motions.can_manage %}
-
- {% endif %}
-
-
-
-
-{% endblock %}
diff --git a/openslides/assignments/templates/assignments/assignmentpoll_slide.html b/openslides/assignments/templates/assignments/assignmentpoll_slide.html
deleted file mode 100644
index ac702cdd9..000000000
--- a/openslides/assignments/templates/assignments/assignmentpoll_slide.html
+++ /dev/null
@@ -1,59 +0,0 @@
-{% load i18n %}
-{% load humanize %}
-{% load staticfiles %}
-{% load tags %}
-
-
- {{ poll.assignment }}
-
-
- {% trans "Election" %}
- {% if poll.get_ballot > 1 %}| {{ poll.get_ballot|ordinal|safe }} {% trans "ballot" %}{% endif %}
-
-
-
-
-{% if poll.has_votes and poll.published %}
-
- {% for option in poll.get_options %}
-
- {{ option }}
-
- {% if not "assignment_publish_winner_results_only"|get_config or option.candidate in poll.assignment.elected %}
- {% if poll.yesnoabstain %}
- {% trans 'Yes' %}:
- {{ option.Yes }}
- {% trans 'No' %}:
- {{ option.No }}
- {% trans 'Abstention' %}:
- {{ option.Abstain }}
- {% else %}
- {{ option.Votes }}
- {% endif %}
- {% endif %}
-
-
- {% endfor %}
- {% if poll.votesvalid != None %}
-
- {% trans 'Valid votes' %}:
- {{ poll.print_votesvalid }}
-
- {% endif %}
- {% if poll.votesinvalid != None %}
-
- {% trans 'Invalid votes' %}:
- {{ poll.print_votesinvalid }}
-
- {% endif %}
- {% if poll.votescast != None %}
-
- {% trans 'Votes cast' %}:
- {{ poll.print_votescast }}
-
- {% endif %}
-
-{% else %}
- {% trans "No result available." %}
-{% endif %}
-
diff --git a/openslides/assignments/templates/assignments/slide.html b/openslides/assignments/templates/assignments/slide.html
deleted file mode 100644
index 96c8dca1b..000000000
--- a/openslides/assignments/templates/assignments/slide.html
+++ /dev/null
@@ -1,53 +0,0 @@
-{% load i18n %}
-{% load staticfiles %}
-{% load tags %}
-{% load humanize %}
-
-
-
-{{ assignment }}
-
- {% trans "Election" %}
-
-
-
-{% if not assignment.candidates %}
-
-
{{ assignment.description|linebreaks }}
-
-{% endif %}
-
-{% if assignment.candidates and assignment.status != "fin" %}
- {% trans "Candidates" %}
-
- {% for candidate in assignment.candidates %}
- {{ candidate }}
- {% empty %}
-
- {% trans "No candidates available." %}
-
- {% endfor %}
-
-
-{% endif %}
-
-{% if assignment.status == "fin" %}
- {% trans "Elected candidates" %}
-
- {% for person in assignment.elected %}
- {{ person }}
- {% empty %}
-
- {% trans "No candidates elected." %}
-
- {% endfor %}
-
-{% endif %}
diff --git a/openslides/assignments/templates/assignments/widget_assignment.html b/openslides/assignments/templates/assignments/widget_assignment.html
deleted file mode 100644
index e69de29bb..000000000
diff --git a/openslides/assignments/urls.py b/openslides/assignments/urls.py
index cad5efc48..ff5f8d511 100644
--- a/openslides/assignments/urls.py
+++ b/openslides/assignments/urls.py
@@ -4,8 +4,6 @@ from . import views
urlpatterns = patterns(
'',
-
- # PDF
url(r'^print/$',
views.AssignmentPDF.as_view(),
name='assignments_pdf'),
diff --git a/openslides/assignments/views.py b/openslides/assignments/views.py
index a430a9e2f..433679c7b 100644
--- a/openslides/assignments/views.py
+++ b/openslides/assignments/views.py
@@ -5,8 +5,15 @@ from django.utils.translation import ugettext as _
from django.utils.translation import ungettext
from reportlab.lib import colors
from reportlab.lib.units import cm
-from reportlab.platypus import (PageBreak, Paragraph, SimpleDocTemplate, Spacer,
- LongTable, Table, TableStyle)
+from reportlab.platypus import (
+ LongTable,
+ PageBreak,
+ Paragraph,
+ SimpleDocTemplate,
+ Spacer,
+ Table,
+ TableStyle,
+)
from openslides.config.api import config
from openslides.users.models import Group, User # TODO: remove this
@@ -18,14 +25,15 @@ from openslides.utils.rest_api import (
Response,
UpdateModelMixin,
ValidationError,
- detail_route)
+ detail_route,
+)
from openslides.utils.views import PDFView
from .models import Assignment, AssignmentPoll
from .serializers import (
AssignmentAllPollSerializer,
AssignmentFullSerializer,
- AssignmentShortSerializer
+ AssignmentShortSerializer,
)
diff --git a/openslides/assignments/widgets.py b/openslides/assignments/widgets.py
deleted file mode 100644
index f227353b8..000000000
--- a/openslides/assignments/widgets.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.utils.widgets import Widget
-
-from .models import Assignment
-
-
-class AssignmentWidget(Widget):
- """
- Assignment widget.
- """
- name = 'assignment'
- verbose_name = ugettext_lazy('Elections')
- required_permission = 'core.can_manage_projector'
- default_column = 1
- default_weight = 50
- template_name = 'assignments/widget_assignment.html'
- more_link_pattern_name = 'assignment_list'
-
- def get_context_data(self, **context):
- return super(AssignmentWidget, self).get_context_data(
- assignments=Assignment.objects.all(),
- **context)
diff --git a/openslides/config/apps.py b/openslides/config/apps.py
index d1047212c..5629cf41f 100644
--- a/openslides/config/apps.py
+++ b/openslides/config/apps.py
@@ -6,10 +6,6 @@ class ConfigAppConfig(AppConfig):
verbose_name = 'OpenSlides Config'
def ready(self):
- # Load main menu entry.
- # Do this by just importing all from this file.
- from . import main_menu # noqa
-
# Import all required stuff.
from openslides.utils.rest_api import router
from .views import ConfigViewSet
diff --git a/openslides/config/main_menu.py b/openslides/config/main_menu.py
deleted file mode 100644
index 86a6b943e..000000000
--- a/openslides/config/main_menu.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.utils.main_menu import MainMenuEntry
-
-
-class ConfigMainMenuEntry(MainMenuEntry):
- """
- Main menu entry for the config app.
- """
- verbose_name = ugettext_lazy('Configuration')
- required_permission = 'config.can_manage'
- default_weight = 70
- pattern_name = 'config_first_config_collection_view'
- icon_css_class = 'glyphicon-cog'
diff --git a/openslides/config/models.py b/openslides/config/models.py
index c5dfd841e..6b739811d 100644
--- a/openslides/config/models.py
+++ b/openslides/config/models.py
@@ -1,6 +1,5 @@
from django.db import models
from django.utils.translation import ugettext_noop
-
from jsonfield import JSONField
diff --git a/openslides/config/templates/config/config_form.html b/openslides/config/templates/config/config_form.html
deleted file mode 100644
index 868936614..000000000
--- a/openslides/config/templates/config/config_form.html
+++ /dev/null
@@ -1,51 +0,0 @@
-{% extends 'base.html' %}
-
-{% load i18n %}
-
-{% block title %}{% trans "Configuration" %} – {{ block.super }}{% endblock %}
-
-{% block content %}
-
- {% trans 'Configuration' %}
- {% trans active_config_collection_view.title %}
-
-
-
-
-
-{% endblock %}
diff --git a/openslides/config/urls.py b/openslides/config/urls.py
deleted file mode 100644
index f7b636911..000000000
--- a/openslides/config/urls.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from django.conf.urls import patterns, url
-
-from openslides.utils.views import RedirectView
-
-from .signals import config_signal
-from .views import ConfigView
-
-urlpatterns = patterns(
- '',
- url(r'^$',
- RedirectView.as_view(url_name='config_general'),
- name='config_first_config_collection_view')
-)
-
-for receiver, config_collection in config_signal.send(sender='config_urls'):
- if config_collection.is_shown():
- urlpatterns += patterns('', url(r'^%s/$' % config_collection.url,
- ConfigView.as_view(config_collection=config_collection),
- name='config_%s' % config_collection.url))
diff --git a/openslides/config/views.py b/openslides/config/views.py
index ba04465c7..7ebc7f5a0 100644
--- a/openslides/config/views.py
+++ b/openslides/config/views.py
@@ -1,109 +1,10 @@
-from django import forms
-from django.contrib import messages
-from django.core.urlresolvers import reverse
from django.core.exceptions import ValidationError as DjangoValidationError
from django.http import Http404
-from django.utils.translation import ugettext as _
from openslides.utils.rest_api import Response, ValidationError, ViewSet
-from openslides.utils.views import FormView
from .api import config
from .exceptions import ConfigNotFound
-from .signals import config_signal
-
-
-class ConfigView(FormView):
- """
- The view for a config collection.
- """
- required_permission = 'config.can_manage'
- template_name = 'config/config_form.html'
- config_collection = None
- form_class = forms.Form
-
- def get_form(self, *args):
- """
- Gets the form for the view. Includes all form fields given by the
- config collection.
- """
- form = super(ConfigView, self).get_form(*args)
- for name, field in self.generate_form_fields_from_config_collection():
- form.fields[name] = field
- return form
-
- def generate_form_fields_from_config_collection(self):
- """
- Generates the fields for the get_form function.
- """
- for variable in self.config_collection.variables:
- if variable.form_field is not None:
- yield (variable.name, variable.form_field)
-
- def get_initial(self):
- """
- Returns a dictonary with the actual values of the config variables
- as intial value for the form.
- """
- initial = super(ConfigView, self).get_initial()
- for variable in self.config_collection.variables:
- initial.update({variable.name: config[variable.name]})
- return initial
-
- def get_context_data(self, **kwargs):
- """
- Adds to the context the active config view, a list of dictionaries
- containing all config collections each with a flag which is true if its
- view is the active one and adds a flag whether the config collection
- has groups. Adds also extra_stylefiles and extra_javascript.
- """
- context = super(ConfigView, self).get_context_data(**kwargs)
-
- context['active_config_collection_view'] = self.config_collection
-
- config_collection_list = []
- for receiver, config_collection in config_signal.send(sender=self):
- if config_collection.is_shown():
- config_collection_list.append({
- 'config_collection': config_collection,
- 'active': self.request.path == reverse('config_%s' % config_collection.url)})
- context['config_collection_list'] = sorted(
- config_collection_list, key=lambda config_collection_dict: config_collection_dict['config_collection'].weight)
-
- if hasattr(self.config_collection, 'groups'):
- context['groups'] = self.config_collection.groups
- else:
- context['groups'] = None
-
- if 'extra_stylefiles' in self.config_collection.extra_context:
- if 'extra_stylefiles' in context:
- context['extra_stylefiles'].extend(self.config_collection.extra_context['extra_stylefiles'])
- else:
- context['extra_stylefiles'] = self.config_collection.extra_context['extra_stylefiles']
-
- if 'extra_javascript' in self.config_collection.extra_context:
- if 'extra_javascript' in context:
- context['extra_javascript'].extend(self.config_collection.extra_context['extra_javascript'])
- else:
- context['extra_javascript'] = self.config_collection.extra_context['extra_javascript']
-
- return context
-
- def get_success_url(self):
- """
- Returns the success url when changes are saved. Here it is the same
- url as the main menu entry.
- """
- return reverse('config_%s' % self.config_collection.url)
-
- def form_valid(self, form):
- """
- Saves all data of a valid form.
- """
- for key in form.cleaned_data:
- config[key] = form.cleaned_data[key]
- messages.success(self.request, _('%s settings successfully saved.') % _(self.config_collection.title))
- return super(ConfigView, self).form_valid(form)
class ConfigViewSet(ViewSet):
diff --git a/openslides/core/apps.py b/openslides/core/apps.py
index ca50324a6..e46a65943 100644
--- a/openslides/core/apps.py
+++ b/openslides/core/apps.py
@@ -6,9 +6,9 @@ class CoreAppConfig(AppConfig):
verbose_name = 'OpenSlides Core'
def ready(self):
- # Load main menu entry, projector elements and widgets.
+ # Load projector elements.
# Do this by just importing all from these files.
- from . import main_menu, projector, widgets # noqa
+ from . import projector # noqa
# Import all required stuff.
from django.db.models import signals
diff --git a/openslides/core/chatbox.py b/openslides/core/chatbox.py
index 2a9e89a5c..a84314e9c 100644
--- a/openslides/core/chatbox.py
+++ b/openslides/core/chatbox.py
@@ -3,7 +3,6 @@ from datetime import datetime
from django.conf import settings
from django.utils.html import urlize
from django.utils.importlib import import_module
-
from sockjs.tornado import SockJSConnection
diff --git a/openslides/core/forms.py b/openslides/core/forms.py
deleted file mode 100644
index 208a9de4a..000000000
--- a/openslides/core/forms.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from django import forms
-
-from openslides.utils.forms import CssClassMixin
-
-
-class SelectWidgetsForm(CssClassMixin, forms.Form):
- """
- Form to select the widgets.
- """
- widget = forms.BooleanField(required=False)
diff --git a/openslides/core/main_menu.py b/openslides/core/main_menu.py
deleted file mode 100644
index 2d4e5850d..000000000
--- a/openslides/core/main_menu.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.utils.main_menu import MainMenuEntry
-
-
-class DashboardMainMenuEntry(MainMenuEntry):
- """
- Main menu entry to the dashboard.
- """
- verbose_name = ugettext_lazy('Dashboard')
- required_permission = 'core.can_see_dashboard'
- default_weight = 10
- icon_css_class = 'glyphicon-home'
- pattern_name = '/' # TODO: use generic solution, see issue #1469
diff --git a/openslides/core/management/commands/backupdb.py b/openslides/core/management/commands/backupdb.py
index 21755a8e8..a074965ec 100644
--- a/openslides/core/management/commands/backupdb.py
+++ b/openslides/core/management/commands/backupdb.py
@@ -1,7 +1,7 @@
-from optparse import make_option # TODO: Use argpase in Django 1.8
import shutil
+from optparse import make_option # TODO: Use argpase in Django 1.8
-from django.core.management.base import NoArgsCommand, CommandError
+from django.core.management.base import CommandError, NoArgsCommand
from django.db import connection, transaction
from openslides.utils.main import get_database_path_from_settings
diff --git a/openslides/core/management/commands/runserver.py b/openslides/core/management/commands/runserver.py
index f96cc9978..6760426e7 100644
--- a/openslides/core/management/commands/runserver.py
+++ b/openslides/core/management/commands/runserver.py
@@ -1,10 +1,10 @@
-from datetime import datetime
-import sys
-import socket
import errno
+import socket
+import sys
+from datetime import datetime
-from django.core.management.commands.runserver import Command as _Command
from django.core.exceptions import ImproperlyConfigured
+from django.core.management.commands.runserver import Command as _Command
from django.utils import translation
from django.utils.encoding import force_text
diff --git a/openslides/core/migrations/0001_initial.py b/openslides/core/migrations/0001_initial.py
index 79267669e..ff25b5cae 100644
--- a/openslides/core/migrations/0001_initial.py
+++ b/openslides/core/migrations/0001_initial.py
@@ -40,7 +40,7 @@ class Migration(migrations.Migration):
options={
'ordering': ('weight', 'title'),
},
- bases=(openslides.utils.rest_api.RESTModelMixin, openslides.utils.models.AbsoluteUrlMixin, models.Model),
+ bases=(openslides.utils.rest_api.RESTModelMixin, models.Model),
),
migrations.CreateModel(
name='Projector',
@@ -67,7 +67,7 @@ class Migration(migrations.Migration):
'permissions': (('can_manage_tags', 'Can manage tags'),),
'ordering': ('name',),
},
- bases=(openslides.utils.rest_api.RESTModelMixin, openslides.utils.models.AbsoluteUrlMixin, models.Model),
+ bases=(openslides.utils.rest_api.RESTModelMixin, models.Model),
),
migrations.RunPython(
add_default_projector,
diff --git a/openslides/core/models.py b/openslides/core/models.py
index c1d36f8ab..e7a9c36a3 100644
--- a/openslides/core/models.py
+++ b/openslides/core/models.py
@@ -3,7 +3,6 @@ from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
from jsonfield import JSONField
-from openslides.utils.models import AbsoluteUrlMixin
from openslides.utils.projector import ProjectorElement
from openslides.utils.rest_api import RESTModelMixin
@@ -83,7 +82,7 @@ class Projector(RESTModelMixin, models.Model):
yield requirement
-class CustomSlide(RESTModelMixin, AbsoluteUrlMixin, models.Model):
+class CustomSlide(RESTModelMixin, models.Model):
"""
Model for slides with custom content.
"""
@@ -104,7 +103,7 @@ class CustomSlide(RESTModelMixin, AbsoluteUrlMixin, models.Model):
return self.title
-class Tag(RESTModelMixin, AbsoluteUrlMixin, models.Model):
+class Tag(RESTModelMixin, models.Model):
"""
Model for tags. This tags can be used for other models like agenda items,
motions or assignments.
diff --git a/openslides/core/signals.py b/openslides/core/signals.py
index f549468a3..877e87b9c 100644
--- a/openslides/core/signals.py
+++ b/openslides/core/signals.py
@@ -3,7 +3,11 @@ from django.dispatch import Signal
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
-from openslides.config.api import ConfigGroup, ConfigGroupedCollection, ConfigVariable
+from openslides.config.api import (
+ ConfigGroup,
+ ConfigGroupedCollection,
+ ConfigVariable,
+)
# This signal is sent when the migrate command is done. That means it is sent
# after post_migrate sending and creating all Permission objects. Don't use it
diff --git a/openslides/core/templates/base.html b/openslides/core/templates/base.html
deleted file mode 100644
index 1d8bc534e..000000000
--- a/openslides/core/templates/base.html
+++ /dev/null
@@ -1,163 +0,0 @@
-{% load tags %}
-{% load i18n %}
-{% load staticfiles %}
-
-
-
-
-
-
- {% block title %}{% get_config 'event_name' %}{% endblock %}
-
-
-
-
-
-
-
- {% for stylefile in extra_stylefiles %}
-
- {% endfor %}
- {% block header %}{% endblock %}
-
-
-
-
-
-
-
- {% block body %}
-
-
-
-
-
-
-
-
-
-
-
-
-
- ×
-
- {% for message in messages %}
-
- ×
- {{ message|safe }}
-
- {% endfor %}
-
- {% block content %}{% endblock %}
-
-
-
-
-
-
-
-
- {% endblock %}
-
- {% include 'core/chatbox.html' %}
-
-
-
-
-
-
-
-
-
- {% for javascript in extra_javascript %}
-
- {% endfor %}
- {% block javascript %}{% endblock %}
-
-
diff --git a/openslides/core/templates/core/chatbox.html b/openslides/core/templates/core/chatbox.html
deleted file mode 100644
index e5dfb8448..000000000
--- a/openslides/core/templates/core/chatbox.html
+++ /dev/null
@@ -1,22 +0,0 @@
-{% load i18n %}
-
-{% if chat_messages != None %}
-
-
-
- {% for message in chat_messages %}
- {{ message.html_time|safe }} {{ message.html_person|safe }} {{ message.message|urlize }}
- {% endfor %}
-
-
-
-{% endif %}
diff --git a/openslides/core/templates/core/customslide_slide.html b/openslides/core/templates/core/customslide_slide.html
deleted file mode 100644
index a14e39914..000000000
--- a/openslides/core/templates/core/customslide_slide.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% load i18n %}
-
-
- {{ slide.title }}
-
-
-{% if slide.text %}
- {{ slide.text|safe|linebreaks }}
-{% endif %}
diff --git a/openslides/core/templates/core/customslide_update.html b/openslides/core/templates/core/customslide_update.html
deleted file mode 100644
index 6d6c088a4..000000000
--- a/openslides/core/templates/core/customslide_update.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{% extends "base.html" %}
-
-{% load i18n %}
-
-{% block title %}{% trans "Custom slide" %} – {{ block.super }}{% endblock %}
-
-{% block content %}
-
-
-{% endblock %}
diff --git a/openslides/core/templates/core/dashboard.html b/openslides/core/templates/core/dashboard.html
deleted file mode 100644
index 6754d6cce..000000000
--- a/openslides/core/templates/core/dashboard.html
+++ /dev/null
@@ -1,42 +0,0 @@
-{% extends 'base.html' %}
-
-{% load i18n %}
-{% load staticfiles %}
-
-{% block header %}
-
-{% endblock %}
-
-{% block javascript %}
-
-
-{% endblock %}
-
-{% block title %}{% trans 'Dashboard' %} – {{ block.super }}{% endblock %}
-
-{% block content %}
-
-
-
- {% for widget in widgets %}
- {% if widget.default_column == 1 %}
- {{ widget.get_html }}
- {% endif %}
- {% endfor %}
-
-
- {% for widget in widgets %}
- {% if widget.default_column == 2 %}
- {{ widget.get_html }}
- {% endif %}
- {% endfor %}
-
-
-{% endblock %}
diff --git a/openslides/core/templates/core/error.html b/openslides/core/templates/core/error.html
deleted file mode 100644
index ebf045dd5..000000000
--- a/openslides/core/templates/core/error.html
+++ /dev/null
@@ -1,8 +0,0 @@
-{% extends 'base.html' %}
-
-{% block title %}{{ http_error.status_code }} {{ http_error.name }} – {{ block.super }}{% endblock %}
-
-{% block content %}
- {{ http_error.name }}
- {{ http_error.description }}
-{% endblock %}
diff --git a/openslides/core/templates/core/search.html b/openslides/core/templates/core/search.html
deleted file mode 100644
index b296672c9..000000000
--- a/openslides/core/templates/core/search.html
+++ /dev/null
@@ -1,58 +0,0 @@
-{% extends 'base.html' %}
-
-{% load i18n %}
-
-{% block title %}{{ block.super }} – {% trans "Search" %}{% endblock %}
-
-{% block content %}
- {% trans 'Search results' %}
-
-
- {% if query %}
- {% for result in page.object_list %}
- {% if forloop.first %}
-
- {% endif %}
- {% if result.app_label %}
- {% with result_template=result.app_label|add:"-results.html" %}
- {% include "search/"|add:result_template %}
- {% endwith %}
- {% endif %}
- {% if forloop.last %}
-
- {% endif %}
- {% empty %}
- {% trans "No results found." %}
- {% endfor %}
-
- {% if page.has_previous or page.has_next %}
-
- {% endif %}
- {% endif %}
-{% endblock %}
diff --git a/openslides/core/templates/core/select_widgets.html b/openslides/core/templates/core/select_widgets.html
deleted file mode 100644
index fc9c2f838..000000000
--- a/openslides/core/templates/core/select_widgets.html
+++ /dev/null
@@ -1,32 +0,0 @@
-{% extends 'base.html' %}
-
-{% load i18n %}
-
-{% block title %}{% trans 'Select widgets' %} – {{ block.super }}{% endblock %}
-
-{% block content %}
-
-
-
-{% endblock %}
diff --git a/openslides/core/templates/core/tag_list.html b/openslides/core/templates/core/tag_list.html
deleted file mode 100644
index 731844b68..000000000
--- a/openslides/core/templates/core/tag_list.html
+++ /dev/null
@@ -1,61 +0,0 @@
-{% extends "base.html" %}
-{% load i18n %}
-{% load staticfiles %}
-
-{% block title %}{% trans "Tags" %} – {{ block.super }}{% endblock %}
-
-{% block content %}
-
-
-
-
-
-
- {% trans "Tag" %}
- {% trans "Actions" %}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% for tag in tag_list %}
-
- {{ tag }}
-
-
-
-
-
-
-
-
-
-
-
- {% endfor %}
-
- {% trans "You can use these tags for agenda items, motions and elections." %}
-{% endblock %}
-
-{% block javascript %}
-
-{% endblock %}
diff --git a/openslides/core/templates/core/version.html b/openslides/core/templates/core/version.html
deleted file mode 100644
index 9805f862b..000000000
--- a/openslides/core/templates/core/version.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{% extends 'base.html' %}
-
-{% load i18n %}
-
-{% block title %}{% trans 'Version' %} – {{ block.super }}{% endblock %}
-
-{% block content %}
- {% trans 'Version' %}
-
- {% for module in modules %}
-
- {{ module.verbose_name }}
- {% if module.description %}
- ({{ module.description }})
- {% endif %}
- – {% trans 'Version' %} {{ module.version }}
-
- {% endfor %}
-
-{% endblock %}
diff --git a/openslides/core/templates/core/widget.html b/openslides/core/templates/core/widget.html
deleted file mode 100644
index f44f32239..000000000
--- a/openslides/core/templates/core/widget.html
+++ /dev/null
@@ -1,40 +0,0 @@
-{% load i18n %}
-
-
diff --git a/openslides/core/templates/core/widget_customslide.html b/openslides/core/templates/core/widget_customslide.html
deleted file mode 100644
index a2ff73294..000000000
--- a/openslides/core/templates/core/widget_customslide.html
+++ /dev/null
@@ -1,49 +0,0 @@
-{% extends 'core/widget.html' %}
-
-{% load i18n %}
-{% load tags %}
-
-{% block content %}
-
-
-
-
-
-
-
-
- {{ 'welcome_title'|get_config }}
-
-
-
-
-{% for slide in slides %}
-
-
-
-
- {{ slide }}
-
-
-
-
-
-
-
-
-
-
-{% empty %}
- {% trans 'No items available.' %}
-{% endfor %}
-
-
- {% trans 'New' %}
-
-{% endblock %}
diff --git a/openslides/core/templates/core/widget_welcome.html b/openslides/core/templates/core/widget_welcome.html
deleted file mode 100644
index 07b366ebb..000000000
--- a/openslides/core/templates/core/widget_welcome.html
+++ /dev/null
@@ -1,12 +0,0 @@
-{% extends 'core/widget.html' %}
-
-{% load i18n %}
-{% load tags %}
-
-{% block content %}
- {% with 'welcome_text'|get_config as welcometext %}
- {% if welcometext %}
- {{ welcometext|safe|linebreaks }}
- {% endif %}
- {% endwith %}
-{% endblock %}
diff --git a/openslides/core/templates/form.html b/openslides/core/templates/form.html
deleted file mode 100644
index 9d5fa4a7b..000000000
--- a/openslides/core/templates/form.html
+++ /dev/null
@@ -1,22 +0,0 @@
-{{ form.media }}
-{% if form.non_field_errors %}
-
- ×
- {% for msg in form.non_field_errors %}
- {{ msg }}
- {% if not forloop.last %} {% endif %}
- {% endfor %}
-
-{% endif %}
-{% for field in form %}
-
- {{ field.label }}{% if field.field.required %}* {% endif %}:
- {{ field }}
- {% if field.errors %}
- {{ field.errors }}
- {% endif %}
- {% if field.help_text %}
- {{ field.help_text }}
- {% endif %}
-
-{% endfor %}
diff --git a/openslides/core/templates/formbuttons_save.html b/openslides/core/templates/formbuttons_save.html
deleted file mode 100644
index 25dd6fbf4..000000000
--- a/openslides/core/templates/formbuttons_save.html
+++ /dev/null
@@ -1,5 +0,0 @@
-{% load i18n %}
-
-
- {% trans 'Save' %}
-
diff --git a/openslides/core/templates/formbuttons_saveapply.html b/openslides/core/templates/formbuttons_saveapply.html
deleted file mode 100644
index d1be3e218..000000000
--- a/openslides/core/templates/formbuttons_saveapply.html
+++ /dev/null
@@ -1,8 +0,0 @@
-{% load i18n %}
-
-
- {% trans 'Save' %}
-
-
- {% trans 'Apply' %}
-
diff --git a/openslides/core/templatetags/__init__.py b/openslides/core/templatetags/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/openslides/core/templatetags/tags.py b/openslides/core/templatetags/tags.py
deleted file mode 100644
index 6367a8e4b..000000000
--- a/openslides/core/templatetags/tags.py
+++ /dev/null
@@ -1,53 +0,0 @@
-from django import template
-from django.utils.translation import ugettext as _
-
-from openslides.config.api import config
-
-register = template.Library()
-
-
-# TODO: remove the tag get_config
-@register.simple_tag
-def get_config(key):
- return config[key]
-
-
-@register.filter # noqa
-def get_config(key):
- return config[key]
-
-
-@register.filter
-def trans(value):
- return _(value)
-
-
-@register.filter
-def absolute_url(model, link=None):
- """
- Returns the absolute_url to a model. The 'link' argument decides which url
- will be returned. See get_absolute_url() in the model.
-
- Example: {{ motion|absolute_url:'delete' }}
- """
- try:
- if link is None:
- url = model.get_absolute_url()
- else:
- url = model.get_absolute_url(link)
- except ValueError:
- url = ''
- return url
-
-
-@register.filter
-def first_line(text):
- try:
- lines = text.split('\n')
- except AttributeError:
- return ''
- if len(lines) > 1 or len(lines[0]) > 30:
- s = "%s ..."
- else:
- s = "%s"
- return s % lines[0][:30]
diff --git a/openslides/core/urls.py b/openslides/core/urls.py
index 3e556ddea..88093fd89 100644
--- a/openslides/core/urls.py
+++ b/openslides/core/urls.py
@@ -1,46 +1,9 @@
from django.conf.urls import patterns, url
-from openslides.utils.views import RedirectView
-
from . import views
urlpatterns = patterns(
'',
- # Redirect to dashboard URL
- url(r'^$',
- RedirectView.as_view(url_name='core_dashboard'),
- name='home',),
-
- url(r'^dashboard/$',
- views.DashboardView.as_view(),
- name='core_dashboard'),
-
- url(r'^dashboard/select_widgets/$',
- views.SelectWidgetsView.as_view(),
- name='core_select_widgets'),
-
- url(r'^version/$',
- views.VersionView.as_view(),
- name='core_version',),
-
- url(r'^search/$',
- views.SearchView(),
- name='core_search',),
-
- # CustomSlide urls
- url(r'^customslide/new/$',
- views.CustomSlideCreateView.as_view(),
- name='customslide_create'),
-
- url(r'^customslide/(?P\d+)/edit/$',
- views.CustomSlideUpdateView.as_view(),
- name='customslide_update'),
-
- url(r'^customslide/(?P\d+)/del/$',
- views.CustomSlideDeleteView.as_view(),
- name='customslide_delete'),
-
- # Ajax Urls
url(r'^core/url_patterns/$',
views.UrlPatternsView.as_view(),
name='core_url_patterns'),
diff --git a/openslides/core/views.py b/openslides/core/views.py
index 935d1e132..ae11d6b5c 100644
--- a/openslides/core/views.py
+++ b/openslides/core/views.py
@@ -1,38 +1,18 @@
import re
-from django.conf import settings
-from django.contrib import messages
from django.contrib.staticfiles import finders
-from django.core.exceptions import PermissionDenied
-from django.core.urlresolvers import get_resolver, reverse
-from django.db import IntegrityError
+from django.core.urlresolvers import get_resolver
from django.http import HttpResponse
-from django.shortcuts import redirect, render_to_response
-from django.template import RequestContext
-from django.utils.importlib import import_module
-from django.utils.translation import ugettext as _
-from haystack.views import SearchView as _SearchView
-from openslides import __version__ as openslides_version
-from openslides.config.api import config
from openslides.utils import views as utils_views
-from openslides.utils.plugins import (
- get_plugin_description,
- get_plugin_verbose_name,
- get_plugin_version,
-)
from openslides.utils.rest_api import (
ModelViewSet,
ReadOnlyModelViewSet,
Response,
ValidationError,
- detail_route
+ detail_route,
)
-from openslides.utils.signals import template_manipulation
-from openslides.utils.widgets import Widget
-from .exceptions import TagException
-from .forms import SelectWidgetsForm
from .models import CustomSlide, Projector, Tag
from .serializers import (
CustomSlideSerializer,
@@ -211,272 +191,3 @@ class UrlPatternsView(utils_views.APIView):
url, url_kwargs = normalized_regex_bits[0]
result[pattern_name] = self.URL_KWARGS_REGEX.sub(r':\1', url)
return result
-
-
-class ErrorView(utils_views.View):
- """
- View for Http 403, 404 and 500 error pages.
- """
- status_code = None
-
- def dispatch(self, request, *args, **kwargs):
- http_error_strings = {
- 403: {'name': _('Forbidden'),
- 'description': _('Sorry, you have no permission to see this page.'),
- 'status_code': '403'},
- 404: {'name': _('Not Found'),
- 'description': _('Sorry, the requested page could not be found.'),
- 'status_code': '404'},
- 500: {'name': _('Internal Server Error'),
- 'description': _('Sorry, there was an unknown error. Please contact the event manager.'),
- 'status_code': '500'}}
- context = {}
- context['http_error'] = http_error_strings[self.status_code]
- template_manipulation.send(sender=self.__class__, request=request, context=context)
- response = render_to_response(
- 'core/error.html',
- context_instance=RequestContext(request, context))
- response.status_code = self.status_code
- return response
-
-
-# TODO: Remove the following classes one by one.
-
-class DashboardView(utils_views.AjaxMixin, utils_views.TemplateView):
- """
- Overview over all possible slides, the overlays and a live view: the
- Dashboard of OpenSlides. This main view uses the widget api to collect all
- widgets from all apps. See openslides.utils.widgets.Widget for more details.
- """
- required_permission = 'core.can_see_dashboard'
- template_name = 'core/dashboard.html'
-
- def get_context_data(self, **kwargs):
- context = super().get_context_data(**kwargs)
- widgets = []
- for widget in Widget.get_all(self.request):
- if widget.is_active():
- widgets.append(widget)
- context['extra_stylefiles'].extend(widget.get_stylesheets())
- context['extra_javascript'].extend(widget.get_javascript_files())
- context['widgets'] = widgets
- return context
-
-
-class SelectWidgetsView(utils_views.TemplateView):
- """
- Shows a form to select which widgets should be displayed on the own
- dashboard. The setting is saved in the session.
- """
- # TODO: Use another base view class here, e. g. a FormView
- required_permission = 'core.can_see_dashboard'
- template_name = 'core/select_widgets.html'
-
- def get_context_data(self, **kwargs):
- context = super().get_context_data(**kwargs)
- widgets = Widget.get_all(self.request)
- for widget in widgets:
- initial = {'widget': widget.is_active()}
- prefix = widget.name
- if self.request.method == 'POST':
- widget.form = SelectWidgetsForm(
- self.request.POST,
- prefix=prefix,
- initial=initial)
- else:
- widget.form = SelectWidgetsForm(prefix=prefix, initial=initial)
- context['widgets'] = widgets
- return context
-
- def post(self, request, *args, **kwargs):
- """
- Activates or deactivates the widgets in a post request.
- """
- context = self.get_context_data(**kwargs)
- session_widgets = self.request.session.get('widgets', {})
- for widget in context['widgets']:
- if widget.form.is_valid():
- session_widgets[widget.name] = widget.form.cleaned_data['widget']
- else:
- messages.error(request, _('There are errors in the form.'))
- break
- else:
- self.request.session['widgets'] = session_widgets
- return redirect(reverse('core_dashboard'))
-
-
-class VersionView(utils_views.TemplateView):
- """
- Shows version infos.
- """
- template_name = 'core/version.html'
-
- def get_context_data(self, **kwargs):
- """
- Adds version strings to the context.
- """
- context = super().get_context_data(**kwargs)
- context['modules'] = [{'verbose_name': 'OpenSlides',
- 'description': '',
- 'version': openslides_version}]
- # Versions of plugins.
- for plugin in settings.INSTALLED_PLUGINS:
- context['modules'].append({'verbose_name': get_plugin_verbose_name(plugin),
- 'description': get_plugin_description(plugin),
- 'version': get_plugin_version(plugin)})
- return context
-
-
-class SearchView(_SearchView):
- """
- Shows search result page.
- """
- template = 'core/search.html'
-
- def __call__(self, request):
- if not request.user.is_authenticated() and not config['system_enable_anonymous']:
- raise PermissionDenied
- return super().__call__(request)
-
- def extra_context(self):
- """
- Adds extra context variables to set navigation and search filter.
-
- Returns a context dictionary.
- """
- context = {}
- template_manipulation.send(
- sender=self.__class__, request=self.request, context=context)
- context['models'] = self.get_indexed_searchmodels()
- context['get_values'] = self.request.GET.getlist('models')
- return context
-
- def get_indexed_searchmodels(self):
- """
- Iterate over all INSTALLED_APPS and return a list of models which are
- indexed by haystack/whoosh for using in customized model search filter
- in search template search.html. Each list entry contains a verbose name
- of the model and a special form field value for haystack (app_name.model_name),
- e.g. ['Agenda', 'agenda.item'].
- """
- models = []
- # TODO: cache this query!
- for app in settings.INSTALLED_APPS:
- try:
- module = import_module(app + '.search_indexes')
- except ImportError:
- pass
- else:
- models.append([module.Index.modelfilter_name, module.Index.modelfilter_value])
- return models
-
-
-class CustomSlideViewMixin(object):
- """
- Mixin for for CustomSlide Views.
- """
- fields = ('title', 'text', 'weight',)
- required_permission = 'core.can_manage_projector'
- template_name = 'core/customslide_update.html'
- model = CustomSlide
- success_url_name = 'core_dashboard'
- url_name_args = []
-
-
-class CustomSlideCreateView(CustomSlideViewMixin, utils_views.CreateView):
- """
- Create a custom slide.
- """
- pass
-
-
-class CustomSlideUpdateView(CustomSlideViewMixin, utils_views.UpdateView):
- """
- Update a custom slide.
- """
- pass
-
-
-class CustomSlideDeleteView(CustomSlideViewMixin, utils_views.DeleteView):
- """
- Delete a custom slide.
- """
- pass
-
-
-class TagListView(utils_views.AjaxMixin, utils_views.ListView):
- """
- View to list and manipulate tags.
-
- Shows all tags when requested via a GET-request. Manipulates tags with
- POST-requests.
- """
-
- model = Tag
- required_permission = 'core.can_manage_tags'
-
- def post(self, *args, **kwargs):
- return self.ajax_get(*args, **kwargs)
-
- def ajax_get(self, request, *args, **kwargs):
- name, value = request.POST['name'], request.POST.get('value', None)
-
- # Create a new tag
- if name == 'new':
- try:
- tag = Tag.objects.create(name=value)
- except IntegrityError:
- # The name of the tag is already taken. It must be unique.
- self.error = 'Tag name is already taken'
- else:
- self.pk = tag.pk
- self.action = 'created'
-
- # Update an existing tag
- elif name.startswith('edit-tag-'):
- try:
- self.get_tag_queryset(name, 9).update(name=value)
- except TagException as error:
- self.error = str(error)
- except IntegrityError:
- self.error = 'Tag name is already taken'
- except Tag.DoesNotExist:
- self.error = 'Tag does not exist'
- else:
- self.action = 'updated'
-
- # Delete a tag
- elif name.startswith('delete-tag-'):
- try:
- self.get_tag_queryset(name, 11).delete()
- except TagException as error:
- self.error = str(error)
- except Tag.DoesNotExist:
- self.error = 'Tag does not exist'
- else:
- self.action = 'deleted'
- return super().ajax_get(request, *args, **kwargs)
-
- def get_tag_queryset(self, name, place_in_str):
- """
- Get a django-tag-queryset from a string.
-
- 'name' is the string in which the pk is (at the end).
-
- 'place_in_str' is the place where to look for the pk. It has to be an int.
-
- Returns a Tag QuerySet or raises TagException.
- Also sets self.pk to the pk inside the name.
- """
- try:
- self.pk = int(name[place_in_str:])
- except ValueError:
- raise TagException('Invalid name in request')
- return Tag.objects.filter(pk=self.pk)
-
- def get_ajax_context(self, **context):
- return super().get_ajax_context(
- pk=getattr(self, 'pk', None),
- action=getattr(self, 'action', None),
- error=getattr(self, 'error', None),
- **context)
diff --git a/openslides/core/widgets.py b/openslides/core/widgets.py
deleted file mode 100644
index f5a350cdb..000000000
--- a/openslides/core/widgets.py
+++ /dev/null
@@ -1,46 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.config.api import config
-from openslides.projector.api import get_active_slide
-from openslides.utils.widgets import Widget
-
-from .models import CustomSlide
-
-
-class WelcomeWidget(Widget):
- """
- Welcome widget with static info for all users.
- """
- name = 'welcome'
- required_permission = 'core.can_see_dashboard'
- default_column = 1
- default_weight = 10
- template_name = 'core/widget_welcome.html'
- icon_css_class = 'icon-home'
-
- def get_verbose_name(self):
- return config['welcome_title']
-
-
-class CustonSlideWidget(Widget):
- """
- Widget to control custom slides.
- """
- name = 'custom_slide'
- verbose_name = ugettext_lazy('Custom Slides')
- required_permission = 'core.can_manage_projector'
- default_column = 2
- default_weight = 30
- template_name = 'core/widget_customslide.html'
- context = None
- icon_css_class = 'icon-star'
-
- def get_context_data(self, **context):
- """
- Adds custom slides and a flag whether the welcome page is active to
- the context.
- """
- context['slides'] = CustomSlide.objects.all().order_by('weight')
- context['welcomepage_is_active'] = (
- get_active_slide().get('callback', 'default') == 'default')
- return super(CustonSlideWidget, self).get_context_data(**context)
diff --git a/openslides/global_settings.py b/openslides/global_settings.py
index e28b9b52e..5707b001a 100644
--- a/openslides/global_settings.py
+++ b/openslides/global_settings.py
@@ -1,5 +1,5 @@
-import os
import copy
+import os
from django.utils.translation import ugettext_lazy
@@ -11,9 +11,6 @@ AUTH_USER_MODEL = 'users.User'
AUTHENTICATION_BACKENDS = ('openslides.users.auth.CustomizedModelBackend',)
-LOGIN_URL = '/users/'
-LOGIN_REDIRECT_URL = '/'
-
SESSION_COOKIE_NAME = 'OpenSlidesSessionID'
LANGUAGES = (
@@ -89,9 +86,7 @@ INSTALLED_APPS = (
'haystack', # full-text-search
'ckeditor',
'rest_framework',
- 'openslides.poll',
- 'openslides.account',
- 'openslides.projector',
+ 'openslides.poll', # TODO: try to remove this line
'openslides.agenda',
'openslides.motions',
'openslides.assignments',
diff --git a/openslides/mediafiles/apps.py b/openslides/mediafiles/apps.py
index 52fdaee00..0cdbff423 100644
--- a/openslides/mediafiles/apps.py
+++ b/openslides/mediafiles/apps.py
@@ -6,24 +6,9 @@ class MediafileAppConfig(AppConfig):
verbose_name = 'OpenSlides Mediafiles'
def ready(self):
- # Load main menu entry and widgets.
- # Do this by just importing all from these files.
- from . import main_menu, widgets # noqa
-
# Import all required stuff.
- from openslides.projector.api import register_slide
from openslides.utils.rest_api import router
- from openslides.utils.signals import template_manipulation
- from .slides import mediafile_presentation_as_slide
- from .template import add_mediafile_stylesheets
from .views import MediafileViewSet
- # Connect template signal.
- template_manipulation.connect(add_mediafile_stylesheets, dispatch_uid='add_mediafile_stylesheets')
-
- # Register slides.
- Mediafile = self.get_model('Mediafile')
- register_slide('mediafile', mediafile_presentation_as_slide, Mediafile)
-
# Register viewsets.
router.register('mediafiles/mediafile', MediafileViewSet)
diff --git a/openslides/mediafiles/forms.py b/openslides/mediafiles/forms.py
deleted file mode 100644
index 90010832b..000000000
--- a/openslides/mediafiles/forms.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from django.forms import ModelForm
-
-from openslides.utils.forms import CssClassMixin
-
-from .models import Mediafile
-
-
-class MediafileFormMixin(object):
- """
- Mixin for mediafile forms. It is used to delete old files.
- """
- def save(self, *args, **kwargs):
- """
- Method to save the form. Here the override is to delete old files.
- """
- if self.instance.pk is not None:
- old_file = Mediafile.objects.get(pk=self.instance.pk).mediafile
- if not old_file == self.instance.mediafile:
- old_file.delete()
- return super(MediafileFormMixin, self).save(*args, **kwargs)
-
-
-class MediafileNormalUserForm(MediafileFormMixin, CssClassMixin, ModelForm):
- """
- This form is only used by normal users, not by managers.
- """
- class Meta:
- model = Mediafile
- fields = ('mediafile', 'title', 'is_presentable')
-
-
-class MediafileManagerForm(MediafileFormMixin, CssClassMixin, ModelForm):
- """
- This form is only used be managers, not by normal users.
- """
- class Meta:
- model = Mediafile
- fields = ('mediafile', 'title', 'uploader', 'is_presentable')
diff --git a/openslides/mediafiles/main_menu.py b/openslides/mediafiles/main_menu.py
deleted file mode 100644
index e7e8cefc2..000000000
--- a/openslides/mediafiles/main_menu.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.utils.main_menu import MainMenuEntry
-
-
-class MediafileMainMenuEntry(MainMenuEntry):
- """
- Main menu entry for the mediafile app.
- """
- verbose_name = ugettext_lazy('Files')
- default_weight = 60
- pattern_name = '/mediafiles'
- icon_css_class = 'glyphicon-paperclip'
-
- def check_permission(self):
- return (
- self.request.user.has_perm('mediafiles.can_see') or
- self.request.user.has_perm('mediafiles.can_upload') or
- self.request.user.has_perm('mediafiles.can_manage'))
diff --git a/openslides/mediafiles/models.py b/openslides/mediafiles/models.py
index ea0b3b882..749ee138f 100644
--- a/openslides/mediafiles/models.py
+++ b/openslides/mediafiles/models.py
@@ -1,17 +1,15 @@
import mimetypes
-from django.core.urlresolvers import reverse
from django.db import models
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
from openslides.projector.models import SlideMixin
-from openslides.utils.models import AbsoluteUrlMixin
-from openslides.utils.rest_api import RESTModelMixin
from openslides.users.models import User
+from openslides.utils.rest_api import RESTModelMixin
-class Mediafile(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, models.Model):
+class Mediafile(RESTModelMixin, SlideMixin, models.Model):
"""
Class for uploaded files which can be delivered under a certain url.
"""
@@ -68,19 +66,6 @@ class Mediafile(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, models.Model):
self.filetype = ugettext_noop('unknown')
return super(Mediafile, self).save(*args, **kwargs)
- def get_absolute_url(self, link='update'):
- """
- Returns the URL to a mediafile. The link can be 'projector',
- 'update' or 'delete'.
- """
- if link == 'update':
- url = reverse('mediafile_update', kwargs={'pk': str(self.pk)})
- elif link == 'delete':
- url = reverse('mediafile_delete', kwargs={'pk': str(self.pk)})
- else:
- url = super(Mediafile, self).get_absolute_url(link)
- return url
-
def get_filesize(self):
"""
Transforms bytes to kilobytes or megabytes. Returns the size as string.
diff --git a/openslides/mediafiles/search_indexes.py b/openslides/mediafiles/search_indexes.py
index a1de7c4c9..8854f8a35 100644
--- a/openslides/mediafiles/search_indexes.py
+++ b/openslides/mediafiles/search_indexes.py
@@ -1,4 +1,5 @@
from haystack import indexes
+
from .models import Mediafile
diff --git a/openslides/mediafiles/slides.py b/openslides/mediafiles/slides.py
deleted file mode 100644
index 95cb991bb..000000000
--- a/openslides/mediafiles/slides.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from django.template.loader import render_to_string
-
-from openslides.config.api import config
-from openslides.projector.api import SlideError
-
-from .models import Mediafile
-
-
-def mediafile_presentation_as_slide(**kwargs):
- """
- Return the html code for a presentation of a Mediafile.
-
- At the moment, only the presentation of pdfs is supported.
-
- The function is registered during app loading.
- """
- file_pk = kwargs.get('pk', None)
- page_num = kwargs.get('page_num', 1)
-
- try:
- pdf = Mediafile.objects.get(
- pk=file_pk,
- filetype__in=Mediafile.PRESENTABLE_FILE_TYPES,
- is_presentable=True)
- except Mediafile.DoesNotExist:
- raise SlideError
- context = {'pdf': pdf, 'page_num': page_num,
- 'fullscreen': config['pdf_fullscreen']}
- return render_to_string('mediafiles/presentation_slide.html', context)
diff --git a/openslides/mediafiles/template.py b/openslides/mediafiles/template.py
deleted file mode 100644
index 90dc78de1..000000000
--- a/openslides/mediafiles/template.py
+++ /dev/null
@@ -1,7 +0,0 @@
-def add_mediafile_stylesheets(sender, request, context, **kwargs):
- """
- Receiver function to add the mediafile.css to the context. It is
- connected to the signal openslides.utils.signals.template_manipulation
- during app loading.
- """
- context['extra_stylefiles'].append('css/mediafile.css')
diff --git a/openslides/mediafiles/templates/mediafiles/mediafile_form.html b/openslides/mediafiles/templates/mediafiles/mediafile_form.html
deleted file mode 100644
index 70802f997..000000000
--- a/openslides/mediafiles/templates/mediafiles/mediafile_form.html
+++ /dev/null
@@ -1,37 +0,0 @@
-{% extends 'base.html' %}
-
-{% load i18n %}
-
-{% block title %}
- {% if mediafile %}
- {% trans "Edit file" %}
- {% else %}
- {% trans "New file" %}
- {% endif %}
- – {{ block.super }}
-{% endblock %}
-
-{% block content %}
-
- {% if mediafile %}
- {% trans "Edit file" %}
- {% else %}
- {% trans "New file" %}
- {% endif %}
-
- {% trans "Back to overview" %}
-
-
-
-{% endblock %}
diff --git a/openslides/mediafiles/templates/mediafiles/mediafile_list.html b/openslides/mediafiles/templates/mediafiles/mediafile_list.html
deleted file mode 100644
index b1095701f..000000000
--- a/openslides/mediafiles/templates/mediafiles/mediafile_list.html
+++ /dev/null
@@ -1,59 +0,0 @@
-{% extends 'base.html' %}
-
-{% load i18n %}
-{% load tags %}
-
-{% block title %}{% trans 'Files' %} – {{ block.super }}{% endblock %}
-
-{% block content %}
- {% trans 'Files' %}
-
- {% if perms.mediafiles.can_upload %}
- {% trans "New" %}
- {% endif %}
-
-
-
-
- {% trans 'Title' %}
- {% trans 'Type' %}
- {% trans 'Size' %}
- {% trans 'Upload time' %}
- {% trans 'Uploaded by' %}
- {% if perms.mediafiles.can_manage or perms.mediafiles.can_upload %}
- {% trans "Actions" %}
- {% endif %}
-
- {% for mediafile in mediafile_list %}
-
- {{ mediafile }}
- {% trans mediafile.filetype %}
- {{ mediafile.get_filesize }}
- {{ mediafile.timestamp }}
- {{ mediafile.uploader }}
- {% if perms.mediafiles.can_manage or perms.mediafiles.can_upload %}
-
- {% if mediafile.with_action_buttons %}
-
-
-
- {% if perms.mediafiles.can_manage and mediafile.is_presentable %}{% if mediafile.filetype in mediafile.PRESENTABLE_FILE_TYPES %}
-
-
-
-
- {% endif %}{% endif %}
-
- {% else %}
-
- {% endif %}
-
- {% endif %}
-
- {% empty %}
-
- {% trans 'No files available.' %}
-
- {% endfor %}
-
-{% endblock %}
diff --git a/openslides/mediafiles/templates/mediafiles/presentation_slide.html b/openslides/mediafiles/templates/mediafiles/presentation_slide.html
deleted file mode 100644
index 9e5d8d2a1..000000000
--- a/openslides/mediafiles/templates/mediafiles/presentation_slide.html
+++ /dev/null
@@ -1,17 +0,0 @@
-{% load i18n %}
-{% load static %}
-
-
-
-
-
-
-
-
-
-
diff --git a/openslides/mediafiles/templates/mediafiles/widget_pdfpresentation.html b/openslides/mediafiles/templates/mediafiles/widget_pdfpresentation.html
deleted file mode 100644
index aeaa6627d..000000000
--- a/openslides/mediafiles/templates/mediafiles/widget_pdfpresentation.html
+++ /dev/null
@@ -1,50 +0,0 @@
-{% extends 'core/widget.html' %}
-
-{% load i18n %}
-{% load tags %}
-
-{% block content %}
-
-
-
-{% for pdf in pdfs %}
-
-
-
- {{ pdf }}
-
-{% empty %}
- {% trans 'No PDFs available.' %}
-{% endfor %}
-
-{% endblock %}
diff --git a/openslides/mediafiles/urls.py b/openslides/mediafiles/urls.py
deleted file mode 100644
index 789cb9196..000000000
--- a/openslides/mediafiles/urls.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from django.conf.urls import patterns, url
-
-from . import views
-
-urlpatterns = patterns(
- '',
- url(r'^pdf/next/$',
- views.PdfNextView.as_view(),
- name='mediafiles_next_pdf_page'),
- url(r'^pdf/prev/$',
- views.PdfPreviousView.as_view(),
- name='mediafiles_prev_pdf_page'),
- url(r'^pdf/target_page/$',
- views.PdfGoToPageView.as_view(),
- name='mediafiles_target_pdf_page'),
- url(r'^pdf/toggle_fullscreen/$',
- views.PdfToggleFullscreenView.as_view(),
- name='mediafiles_toggle_fullscreen')
-)
diff --git a/openslides/mediafiles/views.py b/openslides/mediafiles/views.py
index 46133f7d6..10a6576ba 100644
--- a/openslides/mediafiles/views.py
+++ b/openslides/mediafiles/views.py
@@ -1,108 +1,9 @@
-from django.http import HttpResponse
-
-from openslides.config.api import config
-from openslides.projector.api import get_active_slide
from openslides.utils.rest_api import ModelViewSet
-from openslides.utils.views import (AjaxView, RedirectView)
from .models import Mediafile
from .serializers import MediafileSerializer
-class PdfNavBaseView(AjaxView):
- """
- BaseView for the Pdf Ajax Navigation.
- """
-
- def get_ajax_context(self, *args, **kwargs):
- return {'current_page': self.active_slide['page_num']}
-
- def load_other_page(self, active_slide):
- """
- Tell connected clients to load an other pdf page.
- """
- config['projector_active_slide'] = active_slide
-
-
-class PdfNextView(PdfNavBaseView):
- """
- Activate the next Page of a pdf and return the number of the current page.
- """
-
- def get(self, request, *args, **kwargs):
- """
- Increment the page number by 1.
-
- If the page number is set in the active slide, we are the value is
- incremented by 1. Otherwise, it is the first page and it is set to 2.
- """
- self.active_slide = get_active_slide()
- if self.active_slide['callback'] == 'mediafile':
- if 'page_num' not in self.active_slide:
- self.active_slide['page_num'] = 2
- else:
- self.active_slide['page_num'] += 1
- self.load_other_page(self.active_slide)
- response = super(PdfNextView, self).get(self, request, *args, **kwargs)
- else:
- # no Mediafile is active and the JavaScript should not do anything.
- response = HttpResponse()
- return response
-
-
-class PdfPreviousView(PdfNavBaseView):
- """
- Activate the previous Page of a pdf and return the number of the current page.
- """
-
- def get(self, request, *args, **kwargs):
- """
- Decrement the page number by 1.
-
- If the page number is set and it is greater than 1, it is decremented
- by 1. Otherwise, it is the first page and nothing happens.
- """
- self.active_slide = get_active_slide()
- response = None
- if self.active_slide['callback'] == 'mediafile':
- if 'page_num' in self.active_slide and self.active_slide['page_num'] > 1:
- self.active_slide['page_num'] -= 1
- self.load_other_page(self.active_slide)
- response = super(PdfPreviousView, self).get(self, request, *args, **kwargs)
- if not response:
- response = HttpResponse()
- return response
-
-
-class PdfGoToPageView(PdfNavBaseView):
- """
- Activate the page set in the textfield.
- """
-
- def get(self, request, *args, **kwargs):
- target_page = int(request.GET.get('page_num'))
- self.active_slide = get_active_slide()
- if target_page:
- self.active_slide['page_num'] = target_page
- self.load_other_page(self.active_slide)
- response = super(PdfGoToPageView, self).get(self, request, *args, **kwargs)
- else:
- response = HttpResponse()
- return response
-
-
-class PdfToggleFullscreenView(RedirectView):
- """
- Toggle fullscreen mode for pdf presentations.
- """
- allow_ajax = True
- url_name = 'core_dashboard'
-
- def get_ajax_context(self, *args, **kwargs):
- config['pdf_fullscreen'] = not config['pdf_fullscreen']
- return {'fullscreen': config['pdf_fullscreen']}
-
-
class MediafileViewSet(ModelViewSet):
"""
API endpoint to list, retrieve, create, update and destroy mediafile
diff --git a/openslides/mediafiles/widgets.py b/openslides/mediafiles/widgets.py
deleted file mode 100644
index dd3a90d67..000000000
--- a/openslides/mediafiles/widgets.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.utils.widgets import Widget
-from openslides.projector.api import get_active_slide
-
-from .models import Mediafile
-
-
-class PDFPresentationWidget(Widget):
- """
- Widget for presentable PDF files.
- """
- name = 'presentations'
- verbose_name = ugettext_lazy('Presentations')
- required_permission = 'core.can_manage_projector'
- default_column = 1
- default_weight = 75
- template_name = 'mediafiles/widget_pdfpresentation.html'
- icon_css_class = 'icon-align-left'
- # javascript_files = None # TODO: Add pdf.js stuff here.
-
- def get_context_data(self, **context):
- pdfs = Mediafile.objects.filter(
- filetype__in=Mediafile.PRESENTABLE_FILE_TYPES,
- is_presentable=True)
- current_page = get_active_slide().get('page_num', 1)
- return super(PDFPresentationWidget, self).get_context_data(
- pdfs=pdfs,
- current_page=current_page,
- **context)
diff --git a/openslides/motions/apps.py b/openslides/motions/apps.py
index 19c8b7807..3a84127e3 100644
--- a/openslides/motions/apps.py
+++ b/openslides/motions/apps.py
@@ -7,14 +7,9 @@ class MotionAppConfig(AppConfig):
verbose_name = 'OpenSlides Motion'
def ready(self):
- # Load main menu entry, personal info and widgets.
- # Do this by just importing all from these files.
- from . import main_menu, personal_info, widgets # noqa
-
# Import all required stuff.
from openslides.config.signals import config_signal
from openslides.utils.rest_api import router
- from openslides.projector.api import register_slide_model
from .signals import create_builtin_workflows, setup_motion_config
from .views import CategoryViewSet, MotionViewSet, WorkflowViewSet
@@ -22,12 +17,6 @@ class MotionAppConfig(AppConfig):
config_signal.connect(setup_motion_config, dispatch_uid='setup_motion_config')
post_migrate.connect(create_builtin_workflows, dispatch_uid='motion_create_builtin_workflows')
- # Register slides.
- Motion = self.get_model('Motion')
- MotionPoll = self.get_model('MotionPoll')
- register_slide_model(Motion, 'motions/slide.html')
- register_slide_model(MotionPoll, 'motions/motionpoll_slide.html')
-
# Register viewsets.
router.register('motions/category', CategoryViewSet)
router.register('motions/motion', MotionViewSet)
diff --git a/openslides/motions/forms.py b/openslides/motions/forms.py
deleted file mode 100644
index 048480e79..000000000
--- a/openslides/motions/forms.py
+++ /dev/null
@@ -1,206 +0,0 @@
-import collections
-
-from django import forms
-from django.utils.translation import ugettext_lazy
-
-from openslides.mediafiles.models import Mediafile
-from openslides.utils.forms import (CleanHtmlFormMixin, CssClassMixin,
- CSVImportForm, LocalizedModelChoiceField)
-from openslides.users.models import User
-
-from ckeditor.widgets import CKEditorWidget
-
-from .models import Category, Motion, Workflow, Tag
-
-
-class BaseMotionForm(CleanHtmlFormMixin, CssClassMixin, forms.ModelForm):
- """
- Base FormClass for a Motion.
-
- For it's own, it append the version data to the fields.
-
- The class can be mixed with the following mixins to add fields for the
- submitter, supporters etc.
- """
- clean_html_fields = ('text', 'reason')
-
- title = forms.CharField(widget=forms.TextInput(), label=ugettext_lazy("Title"))
- """
- Title of the motion. Will be saved in a MotionVersion object.
- """
-
- text = forms.CharField(widget=CKEditorWidget(), label=ugettext_lazy("Text"))
- """
- Text of the motion. Will be saved in a MotionVersion object.
- """
-
- reason = forms.CharField(
- widget=CKEditorWidget(), required=False, label=ugettext_lazy("Reason"))
- """
- Reason of the motion. will be saved in a MotionVersion object.
- """
-
- attachments = forms.ModelMultipleChoiceField(
- queryset=Mediafile.objects.all(),
- required=False,
- label=ugettext_lazy('Attachments'))
- """
- Attachments of the motion.
- """
-
- tags = forms.ModelMultipleChoiceField(
- queryset=Tag.objects.all(),
- required=False,
- label=ugettext_lazy('Tags'))
-
- key_order = ('identifier',
- 'title',
- 'text',
- 'reason',
- 'submitter',
- 'supporter',
- 'category',
- 'tags',
- 'attachments',
- 'workflow',
- 'disable_versioning',)
- """
- Order of fields, including optional fields from mixins (for example MotionSupporterMixin)
- """
-
- class Meta:
- model = Motion
- fields = ()
-
- def __init__(self, *args, **kwargs):
- """
- Fill the FormFields related to the version data with initial data.
- Fill also the initial data for attachments and tags.
- """
- self.motion = kwargs.get('instance', None)
- self.initial = kwargs.setdefault('initial', {})
- if self.motion is not None:
- last_version = self.motion.get_last_version()
- self.initial['title'] = last_version.title
- self.initial['text'] = last_version.text
- self.initial['reason'] = last_version.reason
- self.initial['attachments'] = self.motion.attachments.all()
- self.initial['tags'] = self.motion.tags.all()
- super(BaseMotionForm, self).__init__(*args, **kwargs)
-
- keys = self.fields.keys()
- keys_order = [key for key in self.key_order if key in keys]
- keys_order.extend(set(keys) - set(keys_order))
- self.fields = collections.OrderedDict([(key, self.fields[key]) for key in keys_order])
-
-
-class MotionSubmitterMixin(forms.ModelForm):
- """Mixin to append the submitter field to a MotionForm."""
-
- submitter = forms.ModelMultipleChoiceField(
- User.objects, label=ugettext_lazy("Submitter"), required=False)
- """Submitter of the motion. Can be one or more persons."""
-
- def __init__(self, *args, **kwargs):
- """Fill in the submitter of the motion as default value."""
- if self.motion is not None:
- submitter = self.motion.submitters.all()
- self.initial['submitter'] = submitter
- super(MotionSubmitterMixin, self).__init__(*args, **kwargs)
-
-
-class MotionSupporterMixin(forms.ModelForm):
- """Mixin to append the supporter field to a Motionform."""
-
- supporter = forms.ModelMultipleChoiceField(
- User.objects, required=False, label=ugettext_lazy("Supporters"))
- """Supporter of the motion. Can be one or more persons."""
-
- def __init__(self, *args, **kwargs):
- """Fill in the supporter of the motions as default value."""
- if self.motion is not None:
- supporter = self.motion.supporters.all()
- self.initial['supporter'] = supporter
- super(MotionSupporterMixin, self).__init__(*args, **kwargs)
-
-
-class MotionDisableVersioningMixin(forms.ModelForm):
- """Mixin to add the option to the form to choose to disable versioning."""
-
- disable_versioning = forms.BooleanField(
- required=False, label=ugettext_lazy("Don't create a new version"),
- help_text=ugettext_lazy("Don't create a new version. Useful e.g. for trivial changes."))
- """BooleanField to decide, if a new version will be created, or the
- last_version will be used."""
-
-
-# TODO: Add category and identifier to the form as normal fields (the django way),
-# not as 'new' field from 'new' forms.
-
-class MotionCategoryMixin(forms.ModelForm):
- """
- Mixin to let the user choose the category for the motion.
- """
-
- category = forms.ModelChoiceField(queryset=Category.objects.all(), required=False, label=ugettext_lazy("Category"))
- """
- Category of the motion.
- """
-
- def __init__(self, *args, **kwargs):
- """
- Fill in the category of the motion as default value.
- """
- if self.motion is not None:
- category = self.motion.category
- self.initial['category'] = category
- super(MotionCategoryMixin, self).__init__(*args, **kwargs)
-
-
-class MotionIdentifierMixin(forms.ModelForm):
- """
- Mixin to let the user choose the identifier for the motion.
- """
-
- identifier = forms.CharField(required=False, label=ugettext_lazy('Identifier'))
-
- class Meta:
- model = Motion
- fields = ('identifier',)
-
-
-class MotionWorkflowMixin(forms.ModelForm):
- """
- Mixin to let the user change the workflow of the motion.
- """
-
- workflow = LocalizedModelChoiceField(
- queryset=Workflow.objects.all(),
- empty_label=None,
- label=ugettext_lazy('Workflow'),
- help_text=ugettext_lazy('Set a specific workflow to switch to it. '
- 'If you do so, the state of the motion will be reset.'))
-
-
-class MotionCSVImportForm(CSVImportForm):
- """
- Form for motion import via csv file.
- """
- override = forms.BooleanField(
- required=False,
- label=ugettext_lazy('Override existing motions with the same identifier'),
- help_text=ugettext_lazy('If this is active, every motion with the same identifier as in your csv file will be overridden.'))
- """
- Flag to decide whether existing motions (according to the identifier)
- should be overridden.
- """
-
- default_submitter = forms.ModelChoiceField(
- User.objects.all(),
- required=True,
- label=ugettext_lazy('Default submitter'),
- help_text=ugettext_lazy('This person is used as submitter for any line of your csv file which does not contain valid submitter data.'))
- """
- Person which is used as submitter, if the line of the csv file does
- not contain valid submitter data.
- """
diff --git a/openslides/motions/main_menu.py b/openslides/motions/main_menu.py
deleted file mode 100644
index 7906b4656..000000000
--- a/openslides/motions/main_menu.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.utils.main_menu import MainMenuEntry
-
-
-class MotionMainMenuEntry(MainMenuEntry):
- """
- Main menu entry for the motion app.
- """
- verbose_name = ugettext_lazy('Motions')
- required_permission = 'motions.can_see'
- default_weight = 30
- pattern_name = '/motions' # TODO: use generic solution, see issue #1469
- icon_css_class = 'glyphicon-file'
diff --git a/openslides/motions/models.py b/openslides/motions/models.py
index 80b109128..23897b5fa 100644
--- a/openslides/motions/models.py
+++ b/openslides/motions/models.py
@@ -1,25 +1,28 @@
from django.conf import settings
-from django.core.urlresolvers import reverse
from django.db import models
from django.db.models import Max
from django.utils import formats
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_lazy, ugettext_noop
+from jsonfield import JSONField
from openslides.config.api import config
from openslides.core.models import Tag
from openslides.mediafiles.models import Mediafile
-from openslides.poll.models import (BaseOption, BasePoll, BaseVote, CollectDefaultVotesMixin)
+from openslides.poll.models import (
+ BaseOption,
+ BasePoll,
+ BaseVote,
+ CollectDefaultVotesMixin,
+)
from openslides.projector.models import SlideMixin
-from jsonfield import JSONField
-from openslides.utils.models import AbsoluteUrlMixin
-from openslides.utils.rest_api import RESTModelMixin
from openslides.users.models import User
+from openslides.utils.rest_api import RESTModelMixin
from .exceptions import WorkflowError
-class Motion(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, models.Model):
+class Motion(RESTModelMixin, SlideMixin, models.Model):
"""
The Motion Class.
@@ -191,22 +194,6 @@ class Motion(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, models.Model):
self.active_version = use_version
self.save(update_fields=['active_version'])
- def get_absolute_url(self, link='detail'):
- """
- Return an URL for this version.
-
- The keyword argument 'link' can be 'detail', 'update' or 'delete'.
- """
- if link == 'detail':
- url = reverse('motion_detail', args=[str(self.pk)])
- elif link == 'update':
- url = reverse('motion_update', args=[str(self.pk)])
- elif link == 'delete':
- url = reverse('motion_delete', args=[str(self.pk)])
- else:
- url = super(Motion, self).get_absolute_url(link)
- return url
-
def version_data_changed(self, version):
"""
Compare the version with the last version of the motion.
@@ -535,7 +522,7 @@ class Motion(RESTModelMixin, SlideMixin, AbsoluteUrlMixin, models.Model):
return config['motion_amendments_enabled'] and self.parent is not None
-class MotionVersion(RESTModelMixin, AbsoluteUrlMixin, models.Model):
+class MotionVersion(RESTModelMixin, models.Model):
"""
A MotionVersion object saves some date of the motion.
"""
@@ -572,22 +559,6 @@ class MotionVersion(RESTModelMixin, AbsoluteUrlMixin, models.Model):
counter = self.version_number or ugettext_lazy('new')
return "Motion %s, Version %s" % (self.motion_id, counter)
- def get_absolute_url(self, link='detail'):
- """
- Return the URL of this Version.
-
- The keyargument link can be 'detail' or 'delete'.
- """
- if link == 'detail':
- url = reverse('motion_version_detail', args=[str(self.motion.pk),
- str(self.version_number)])
- elif link == 'delete':
- url = reverse('motion_version_delete', args=[str(self.motion.pk),
- str(self.version_number)])
- else:
- url = super(MotionVersion, self).get_absolute_url(link)
- return url
-
@property
def active(self):
"""Return True, if the version is the active version of a motion. Else: False."""
@@ -600,7 +571,7 @@ class MotionVersion(RESTModelMixin, AbsoluteUrlMixin, models.Model):
return self.motion
-class Category(RESTModelMixin, AbsoluteUrlMixin, models.Model):
+class Category(RESTModelMixin, models.Model):
name = models.CharField(max_length=255, verbose_name=ugettext_lazy("Category name"))
"""Name of the category."""
@@ -613,15 +584,6 @@ class Category(RESTModelMixin, AbsoluteUrlMixin, models.Model):
def __str__(self):
return self.name
- def get_absolute_url(self, link='update'):
- if link == 'update':
- url = reverse('motion_category_update', args=[str(self.pk)])
- elif link == 'delete':
- url = reverse('motion_category_delete', args=[str(self.pk)])
- else:
- url = super(Category, self).get_absolute_url(link)
- return url
-
class Meta:
ordering = ['prefix']
@@ -699,7 +661,7 @@ class MotionOption(RESTModelMixin, BaseOption):
class MotionPoll(RESTModelMixin, SlideMixin, CollectDefaultVotesMixin,
- AbsoluteUrlMixin, BasePoll):
+ BasePoll):
"""The Class to saves the vote result for a motion poll."""
slide_callback_name = 'motionpoll'
@@ -728,22 +690,6 @@ class MotionPoll(RESTModelMixin, SlideMixin, CollectDefaultVotesMixin,
"""Return a string, representing the poll."""
return _('Vote %d') % self.poll_number
- def get_absolute_url(self, link='update'):
- """
- Return an URL for the poll.
-
- The keyargument 'link' can be 'update' or 'delete'.
- """
- if link == 'update':
- url = reverse('motionpoll_update', args=[str(self.motion.pk),
- str(self.poll_number)])
- elif link == 'delete':
- url = reverse('motionpoll_delete', args=[str(self.motion.pk),
- str(self.poll_number)])
- else:
- url = super(MotionPoll, self).get_absolute_url(link)
- return url
-
def set_options(self):
"""Create the option class for this poll."""
# TODO: maybe it is possible with .create() to call this without poll=self
diff --git a/openslides/motions/pdf.py b/openslides/motions/pdf.py
index 7b70bb250..dc3f59dc2 100644
--- a/openslides/motions/pdf.py
+++ b/openslides/motions/pdf.py
@@ -1,7 +1,6 @@
-from cgi import escape
-
-from operator import attrgetter
import random
+from cgi import escape
+from operator import attrgetter
from bs4 import BeautifulSoup
from django.utils.translation import ugettext as _
@@ -16,9 +15,6 @@ from openslides.utils.pdf import stylesheet
from .models import Category
-# Needed to count the delegates
-# TODO: find another way to do this.
-
def motions_to_pdf(pdf, motions):
"""
diff --git a/openslides/motions/personal_info.py b/openslides/motions/personal_info.py
deleted file mode 100644
index 8d7df7298..000000000
--- a/openslides/motions/personal_info.py
+++ /dev/null
@@ -1,30 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.config.api import config
-from openslides.utils.personal_info import PersonalInfo
-
-
-class MotionSubmitterPersonalInfo(PersonalInfo):
- """
- Class for personal info block for motion submitters.
- """
- headline = ugettext_lazy('I submitted the following motions')
- default_weight = 20
-
- def get_queryset(self):
- return None # TODO: Fix this after transforming everything using AngularJS.
-
-
-class MotionSupporterPersonalInfo(PersonalInfo):
- """
- Class for personal info block for motion supporters.
- """
- headline = ugettext_lazy('I support the following motions')
- default_weight = 30
-
- def get_queryset(self):
- if config['motion_min_supporters']:
- return_value = None # TODO: Fix this after transforming everything using AngularJS.
- else:
- return_value = None
- return return_value
diff --git a/openslides/motions/search_indexes.py b/openslides/motions/search_indexes.py
index 9b702f325..8f78acde5 100644
--- a/openslides/motions/search_indexes.py
+++ b/openslides/motions/search_indexes.py
@@ -1,4 +1,5 @@
from haystack import indexes
+
from .models import Motion
diff --git a/openslides/motions/serializers.py b/openslides/motions/serializers.py
index 8802d1455..60c98bc5a 100644
--- a/openslides/motions/serializers.py
+++ b/openslides/motions/serializers.py
@@ -7,7 +7,8 @@ from openslides.utils.rest_api import (
IntegerField,
ModelSerializer,
PrimaryKeyRelatedField,
- ValidationError,)
+ ValidationError,
+)
from .models import (
Category,
@@ -18,7 +19,8 @@ from .models import (
MotionVersion,
MotionVote,
State,
- Workflow,)
+ Workflow,
+)
def validate_workflow_field(value):
diff --git a/openslides/motions/signals.py b/openslides/motions/signals.py
index e420470fc..d19fba34e 100644
--- a/openslides/motions/signals.py
+++ b/openslides/motions/signals.py
@@ -1,8 +1,12 @@
from django import forms
from django.utils.translation import ugettext as _
-from django.utils.translation import ugettext_lazy, ugettext_noop, pgettext
+from django.utils.translation import pgettext, ugettext_lazy, ugettext_noop
-from openslides.config.api import ConfigGroup, ConfigGroupedCollection, ConfigVariable
+from openslides.config.api import (
+ ConfigGroup,
+ ConfigGroupedCollection,
+ ConfigVariable,
+)
from openslides.poll.models import PERCENT_BASE_CHOICES
from .models import State, Workflow
diff --git a/openslides/motions/templates/motions/category_form.html b/openslides/motions/templates/motions/category_form.html
deleted file mode 100644
index 9da1039b6..000000000
--- a/openslides/motions/templates/motions/category_form.html
+++ /dev/null
@@ -1,32 +0,0 @@
-{% extends "base.html" %}
-
-{% load i18n %}
-
-{% block title %}
- {% if category %}
- {% trans "Edit category" %}
- {% else %}
- {% trans "New category" %}
- {% endif %}
- – {{ block.super }}
-{% endblock %}
-
-{% block content %}
-
- {% if category %}
- {% trans "Edit category" %}
- {% else %}
- {% trans "New category" %}
- {% endif %}
-
-
-{% endblock %}
diff --git a/openslides/motions/templates/motions/category_list.html b/openslides/motions/templates/motions/category_list.html
deleted file mode 100644
index e34ce20de..000000000
--- a/openslides/motions/templates/motions/category_list.html
+++ /dev/null
@@ -1,45 +0,0 @@
-{% extends "base.html" %}
-
-{% load tags %}
-{% load i18n %}
-
-{% block title %}{% trans "Motions" %} – {{ block.super }}{% endblock %}
-
-{% block content %}
-
-
-
-
- {% trans "Prefix" %}
- {% trans "Category name" %}
- {% trans "Actions" %}
-
- {% for category in category_list %}
-
- {{ category.prefix }}
- {{ category }}
-
-
-
-
-
-
-
-
- {% empty %}
-
- {% trans "No categories available." %}
-
- {% endfor %}
-
-{% endblock %}
diff --git a/openslides/motions/templates/motions/motion_detail.html b/openslides/motions/templates/motions/motion_detail.html
deleted file mode 100644
index d71e01ecb..000000000
--- a/openslides/motions/templates/motions/motion_detail.html
+++ /dev/null
@@ -1,373 +0,0 @@
-{% extends "base.html" %}
-
-{% load tags %}
-{% load i18n %}
-{% load staticfiles %}
-{% load humanize %}
-
-{% block title %}{% trans "Motion" %} {{ motion.identifier|default:'' }} – {{ block.super }}{% endblock %}
-
-{% block header %}
- {{ block.super }}
-
-{% endblock %}
-
-{% block content %}
-
- {{ title }}
-
-
- {% trans "Motion" %} {{ motion.identifier|default:'' }}
- {% if motion.versions.count > 1 %}
- | {% trans "Version" %} {{ version.version_number }}
- {% if version == motion.active_version %}
- {% trans 'This version is authorized' %}
- {% endif %}
- {% if version.version_number != motion.active_version.version_number %}
-
- {% trans "This version is not authorized." %}
-
- {% endif %}
- {% endif %}
- {% if motion.is_amendment %}
- ({% trans "Amendment of" %} {{ motion.parent.identifier|default:motion.parent }} )
- {% endif %}
-
-
-
-
- {% trans "Back to overview" %}
-
-
-
- PDF
-
-
- {% if perms.core.can_manage_projector %}
-
-
-
- {% endif %}
- {% if perms.motions.can_manage or perms.agenda.can_manage or allowed_actions.edit %}
-
- {% endif %}
-
-
-
-
-
- {# TODO: show only for workflow with versioning #}
- {% with last_version=motion.get_last_version %}
- {% if version.version_number != motion.active_version.version_number %}
-
- {% trans "Go to the authorized version" %}
- (# {{ motion.active_version.version_number }})
-
- {% elif version.version_number != last_version.version_number %}
-
- {% trans "Go to the newest version" %}
- (# {{ last_version.version_number }})
-
- {% endif %}
- {% endwith %}
-
-
-
{% trans "Motion text" %}:
- {{ text|safe }}
-
-
-
-
{% trans "Reason" %}:
- {{ reason|safe|default:'–' }}
-
-
-
- {% with attachments=motion.attachments.all %}
- {% if attachments %}
-
{% trans "Attachments" %}:
- {% for attachment in attachments %}
-
{{ attachment }}
- {% endfor %}
-
- {% endif %}
- {% endwith %}
-
-
- {% with versions=motion.versions.all %}
- {% if versions|length > 1 %}
- {% for version in versions %}
- {% if forloop.first %}
-
{% trans "Version history" %}:
-
- {% endif %}
- {% endfor %}
- {% endif %}
- {% endwith %}
-
-
- {% if perms.motions.can_manage %}
-
-
-
- {% trans "Show log" %}
-
-
-
-
- {% for message in motion.log_messages.all %}
- {{ message }}
- {% endfor %}
-
-
-
- {% endif %}
-
-
-
-
-
-
-
{% trans "Submitter" %}:
- {% for submitter in motion.submitters.all %}
-
{{ submitter }} {% if not forloop.last %}, {% endif %}
- {% endfor %}
-
-
- {% if 'motion_min_supporters'|get_config > 0 %}
-
{% trans "Supporters" %}: *
- {% if not motion.supporters %}
- -
- {% else %}
-
- {% for supporter in motion.supporters.all %}
- {{ supporter }}
- {% endfor %}
-
- {% endif %}
- {% endif %}
-
-
-
{% trans "Status" %}:
-
{% trans motion.state.name %}
-
-
-
-
{% trans "Vote result" %}:
- {% with motion.polls.all as polls %}
- {% for poll in polls %}
-
- {% if polls.count > 1 %}
- {{ poll.poll_number|ordinal|safe }} {% trans "vote" %}:
- {% endif %}
- {% if perms.motions.can_manage %}
- {% if polls.count > 1 %} {% endif %}
-
-
-
-
-
-
-
-
- {% endif %}
- {% if poll.has_votes %}
-
- {% with poll.get_options.0 as option %}
-
{{ option.Yes }}
-
{{ option.No }}
-
{{ option.Abstain }}
- {% if poll.votesvalid != None or poll.votesinvalid != None %}
-
- {% if poll.votesvalid != None %}
-
{{ poll.print_votesvalid }}
- {% endif %}
- {% if poll.votesinvalid != None %}
-
{{ poll.print_votesinvalid }}
- {% endif %}
- {% endif %}
- {% if poll.votescast != None %}
-
-
{{ poll.print_votescast }}
- {% endif %}
- {% endwith %}
-
- {% else %}
-
{% trans 'No result' %}
- {% endif %}
- {% block meta_box_poll_extras %}{% endblock %}
-
- {% empty %}
- {% if not allowed_actions.create_poll %}
- –
- {% endif %}
- {% endfor %}
- {% if allowed_actions.create_poll %}
-
-
-
- {% trans 'New vote' %}
-
-
- {% endif %}
- {% endwith %}
-
-
- {% if motion.category %}
-
{% trans "Category" %}:
- {{ motion.category }}
- {% endif %}
-
-
- {% for tag in motion.tags.all %}
- {% if forloop.first %}
-
{% trans "Tags" %}:
- {% endif %}
-
{{ tag }}
- {% endfor %}
-
-
-
- {% if motion.versions.count > 1 %}
- {% trans "Last changes (of this version)" %}:
- {% else %}
- {% trans "Last changes" %}:
- {% endif %}
-
- {{ version.creation_time }}
-
- {% if 'motion_amendments_enabled'|get_config %}
-
{% trans 'Amendments' %}:
- {% with amendments=motion.amendments.all %}
- {% if amendments %}
-
- {% endif %}
- {% endwith %}
-
-
- {% trans 'New amendment' %}
-
- {% endif %}
-
-
- {% if perms.motions.can_support and 'motion_min_supporters'|get_config > 0 %}
- {% if allowed_actions.unsupport %}
-
-
- {% trans 'Unsupport' %}
-
- {% endif %}
- {% if allowed_actions.support %}
-
-
- {% trans 'Support' %}
-
- {% endif %}
- {% endif %}
-
-
- {% if 'motion_min_supporters'|get_config > 0 %}
-
-
* {% trans "minimum required supporters" %}: {{ 'motion_min_supporters'|get_config }}
- {% endif %}
-
-
- {% if perms.motions.can_manage %}
-
-
-
{% trans "Manage motion" %}
- {% for state in motion.state.next_states.all %}
- {% if forloop.first %}
-
- {% endif %}
- {% endfor %}
-
{% trans "For administration only:" %}
-
- {% trans 'Reset state' %}
-
-
- {% endif %}
-
-
-
-{% endblock %}
diff --git a/openslides/motions/templates/motions/motion_diff.html b/openslides/motions/templates/motions/motion_diff.html
deleted file mode 100644
index 5badd8c34..000000000
--- a/openslides/motions/templates/motions/motion_diff.html
+++ /dev/null
@@ -1,66 +0,0 @@
-{% extends "base.html" %}
-
-{% load i18n %}
-{% load staticfiles %}
-
-{% block title %}{% trans "Motion" %} {{ motion.identifier }} – {{ block.super }}{% endblock %}
-
-{% block header %}
-
-{% endblock %}
-
-
-{% block content %}
-
- {{ motion.title }}
-
-
- {% if motion.identifier != None %}
- {% trans "Motion" %} {{ motion.identifier }},
- {% else %}
- [{% trans "no number" %}] ,
- {% endif %}
- {% trans "Diff view" %}
-
-
-
-
-
-
-{% if version_rev1 and version_rev2 %}
-
-
- {% trans "Version" %} {{ version_rev1.version_number }}
- {% trans "Last changes" %}: {{ version_rev1.creation_time }}
- {{ version_rev1.title }}
-
- {% trans "Version" %} {{ version_rev2.version_number }}
- {% trans "Last changes" %}: {{ version_rev1.creation_time }}
- {{ version_rev2.title }}
-
-
-
-
- {% if not version_rev1.text == version_rev2.text %}
- {{ diff_text|safe }}
- {% else %}
- {{ version_rev1.text }}
- {{ version_rev2.text }}
- {% endif %}
-
-
-{% trans "Reason" %}:
-
- {% if not version_rev1.reason == version_rev2.reason %}
- {{ diff_reason|safe }}
- {% else %}
- {{ version_rev1.reason }}
- {{ version_rev2.reason }}
- {% endif %}
-
-
-{% endif %}
-
-{% endblock %}
diff --git a/openslides/motions/templates/motions/motion_form.html b/openslides/motions/templates/motions/motion_form.html
deleted file mode 100644
index d6752225b..000000000
--- a/openslides/motions/templates/motions/motion_form.html
+++ /dev/null
@@ -1,51 +0,0 @@
-{% extends "base.html" %}
-
-{% load tags %}
-{% load i18n %}
-{% load staticfiles %}
-
-{% block header %}
- {{ block.super }}
-
-{% endblock %}
-
-
-{% block title %}
- {% if motion %}
- {% trans "Edit motion" %}
- {% else %}
- {% trans "New motion" %}
- {% endif %}
- – {{ block.super }}
-{% endblock %}
-
-{% block content %}
-
- {% if motion %}
- {% trans "Edit motion" %}
- {% else %}
- {% trans "New motion" %}
- {% endif %}
-
- {% if motion %}
-
-
- {% trans "Back to motion" %}
- {% else %}
-
-
- {% trans "Back to overview" %}
- {% endif %}
-
-
-
-{% endblock %}
diff --git a/openslides/motions/templates/motions/motion_form_csv_import.html b/openslides/motions/templates/motions/motion_form_csv_import.html
deleted file mode 100644
index af5419345..000000000
--- a/openslides/motions/templates/motions/motion_form_csv_import.html
+++ /dev/null
@@ -1,47 +0,0 @@
-{% extends 'base.html' %}
-
-{% load i18n %}
-
-{% block title %}{% trans 'Import motions' %} – {{ block.super }}{% endblock %}
-
-{% block content %}
-
-
- {% trans 'Select a CSV file to import motions' %}.
-
- {% trans 'Please note' %}:
-
-
- {% trans 'Required comma separated values' %}:
- {% trans 'identifier, title, text, reason, submitter (clean name), category' %}
-
-
- {% trans 'Identifier, reason, submitter and category are optional and may be empty' %}.
-
- {% trans 'The first line (header) is ignored' %}.
-
- {% trans 'Required CSV file encoding is UTF-8' %}.
-
-
- {% trans 'Use the CSV example file from OpenSlides Wiki.' %}
-
-
-
-
-{% endblock %}
diff --git a/openslides/motions/templates/motions/motion_list.html b/openslides/motions/templates/motions/motion_list.html
deleted file mode 100644
index 4eb6e0060..000000000
--- a/openslides/motions/templates/motions/motion_list.html
+++ /dev/null
@@ -1,149 +0,0 @@
-{% extends "base.html" %}
-
-{% load tags %}
-{% load i18n %}
-{% load staticfiles %}
-
-{% block title %}{% trans "Motions" %} – {{ block.super }}{% endblock %}
-
-{% block javascript %}
-
-
-{% endblock %}
-
-{% block content %}
-
- {% trans "Motions" %}
-
- {% if perms.motions.can_create %}
- {% if not 'motion_stop_submitting'|get_config or perms.motions.can_manage %}
-
-
- {% trans 'New' %}
-
- {% endif %}
- {% endif %}
- {% if perms.core.can_manage_tags %}
-
-
- {% trans 'Tags' %}
-
- {% endif %}
- {% if perms.motions.can_manage %}
-
-
- {% trans 'Categories' %}
-
-
-
- {% trans 'Import' %}
- {% endif %}
-
-
- PDF
-
-
-
-
-
-
- {% trans "#" %}
- {% trans "Motion title" %}
- {% trans 'Category' %}
- {% trans "Status" %}
- {% trans "Submitter" %}
- {% if 'motion_min_supporters'|get_config > 0 %}
- {% trans "Supporters" %}
- {% endif %}
- {% trans "Last changes" %}
- {% if perms.motions.can_manage or perms.core.can_manage_projector %}
- {% trans "Actions" %}
- {% endif %}
-
-
- {% for motion in motion_list %}
-
- {{ motion.identifier|default:'' }}
- {% if motion.is_amendment %}
-
- {{ 'motion_amendments_prefix'|get_config }}
-
- {% endif %}
- {{ motion.title }}
- {% for tag in motion.tags.all %}
- {{ tag }}
- {% endfor %}
-
-
- {{ motion.title }}
- {% for tag in motion.tags.all %}
- {{ tag }}
- {% endfor %}
-
- {% if motion.category %}{{ motion.category }}{% else %}–{% endif %}
- {% trans motion.state.name %}
-
- {% for submitter in motion.submitters.all %}
- {{ submitter.person }}{% if not forloop.last %}, {% endif %}
- {% endfor %}
-
- {% if 'motion_min_supporters'|get_config > 0 %}
- {% with supporters=motion.supporters.all|length %}
-
- {% if supporters >= 'motion_min_supporters'|get_config %}
- {{ supporters }}
- {% endif %}
- {% if supporters < 'motion_min_supporters'|get_config %}
- {{ supporters }}
- {% endif %}
-
- {% endwith %}
- {% endif %}
- {{ motion.get_last_version.creation_time }}
- {% if motion.get_last_version.version_number != motion.active_version.version_number %}
-
-
-
- {% endif %}
- {% if perms.motions.can_manage or perms.core.can_manage_projector %}
-
-
- {% if perms.core.can_manage_projector %}
-
-
-
- {% endif %}
- {% if perms.motions.can_manage %}
-
-
-
-
-
-
- {% endif %}
-
-
- {% endif %}
-
- {% endfor %}
-
-{% endblock %}
diff --git a/openslides/motions/templates/motions/motionpoll_form.html b/openslides/motions/templates/motions/motionpoll_form.html
deleted file mode 100644
index 4a0e02c67..000000000
--- a/openslides/motions/templates/motions/motionpoll_form.html
+++ /dev/null
@@ -1,88 +0,0 @@
-{% extends 'base.html' %}
-
-{% load i18n %}
-{% load tags %}
-
-{% block title %}
- {% trans "Motion" %} {{ motion.identifier }}, {{ poll }} – {{ block.super }}
-{% endblock %}
-
-{% block content %}
-
- {{ motion }}
-
-
- {% trans "Motion" %} {{ motion.identifier }}, {{ poll }}
-
-
- {% trans "Back to motion" %}
-
- {% if perms.core.can_manage_projector %}
-
-
-
-
- {% trans "Vote result" %}
- {% endif %}
- {% if perms.motions.can_manage %}
-
- {% endif %}
-
-
-
-
-{% trans "Special values" %}: -1 = {% trans 'majority' %} | -2 = {% trans 'undocumented' %}
-
-
-{% endblock %}
diff --git a/openslides/motions/templates/motions/motionpoll_slide.html b/openslides/motions/templates/motions/motionpoll_slide.html
deleted file mode 100644
index 6b68d9c81..000000000
--- a/openslides/motions/templates/motions/motionpoll_slide.html
+++ /dev/null
@@ -1,54 +0,0 @@
-{% load i18n %}
-{% load humanize %}
-{% load staticfiles %}
-
-
- {{ poll.motion.active_version.title }}
-
-
- {% trans "Motion" %} {{ poll.motion.identifier|default:'' }}
- {% if poll.motion.get_active_version.version_number > 1 %} | {% trans 'Version' %} {{ poll.motion.active_version.version_number }}{% endif %}
- {% if poll.poll_number > 1 %}| {{ poll.poll_number|ordinal|safe }} {% trans "vote" %}{% endif %}
-
-
-
-
- {% if poll.has_votes %}
- {% with poll.get_options.0 as option %}
-
-
- {% trans 'Yes' %}:
- {{ option.Yes }}
-
-
- {% trans 'No' %}:
- {{ option.No }}
-
-
- {% trans 'Abstention' %}:
- {{ option.Abstain }}
-
- {% if poll.votesvalid != None %}
-
- {% trans 'Valid votes' %}:
- {{ poll.print_votesvalid }}
-
- {% endif %}
- {% if poll.votesinvalid != None %}
-
- {% trans 'Invalid votes' %}:
- {{ poll.print_votesinvalid }}
-
- {% endif %}
- {% if poll.votescast != None %}
-
- {% trans 'Votes cast' %}:
- {{ poll.print_votescast }}
-
- {% endif %}
-
- {% endwith %}
- {% else %}
- {% trans "No result available." %}
- {% endif %}
-
diff --git a/openslides/motions/templates/motions/slide.html b/openslides/motions/templates/motions/slide.html
deleted file mode 100644
index ea3f9fe94..000000000
--- a/openslides/motions/templates/motions/slide.html
+++ /dev/null
@@ -1,97 +0,0 @@
-{% load i18n %}
-{% load humanize %}
-{% load staticfiles %}
-
-
-
-
- {{ motion.active_version.title }}
-
- {% trans "Motion" %} {{ motion.identifier|default:'' }}
- {% if motion.is_amendment %}
- ({% trans "Amendment of" %} {{ motion.parent.identifier|default:motion.parent }})
- {% endif %}
- {% if motion.get_active_version.version_number > 1 %} | {% trans 'Version' %} {{ motion.active_version.version_number }}{% endif %}
-
-
-
-
- {{ motion.active_version.text|safe }}
-
-
-{% if motion.active_version.reason %}
-
-
-
{% trans "Reason" %}:
- {{ motion.active_version.reason|safe }}
-
-{% endif %}
diff --git a/openslides/motions/templates/motions/widget_motion.html b/openslides/motions/templates/motions/widget_motion.html
deleted file mode 100644
index e69de29bb..000000000
diff --git a/openslides/motions/urls.py b/openslides/motions/urls.py
index 812c3957d..1fbd5a01c 100644
--- a/openslides/motions/urls.py
+++ b/openslides/motions/urls.py
@@ -4,7 +4,6 @@ from . import views
urlpatterns = patterns(
'',
-
url(r'^pdf/$',
views.MotionPDFView.as_view(print_all_motions=True),
name='motions_pdf'),
diff --git a/openslides/motions/views.py b/openslides/motions/views.py
index 915b92f96..e54481ebf 100644
--- a/openslides/motions/views.py
+++ b/openslides/motions/views.py
@@ -1,18 +1,27 @@
from django.http import Http404
+from django.shortcuts import get_object_or_404
from django.utils.text import slugify
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_noop
-from django.shortcuts import get_object_or_404
from reportlab.platypus import SimpleDocTemplate
from rest_framework import status
from openslides.config.api import config
-from openslides.utils.rest_api import ModelViewSet, Response, ValidationError, detail_route
-from openslides.utils.views import (PDFView, SingleObjectMixin)
+from openslides.utils.rest_api import (
+ ModelViewSet,
+ Response,
+ ValidationError,
+ detail_route,
+)
+from openslides.utils.views import PDFView, SingleObjectMixin
-from .models import (Category, Motion, MotionPoll, MotionVersion, Workflow)
+from .models import Category, Motion, MotionPoll, MotionVersion, Workflow
from .pdf import motion_poll_to_pdf, motion_to_pdf, motions_to_pdf
-from .serializers import CategorySerializer, MotionSerializer, WorkflowSerializer
+from .serializers import (
+ CategorySerializer,
+ MotionSerializer,
+ WorkflowSerializer,
+)
class MotionViewSet(ModelViewSet):
@@ -236,13 +245,13 @@ class MotionViewSet(ModelViewSet):
return Response({'detail': message})
-class PollMixin(object):
+class PollPDFView(PDFView):
"""
- Mixin for the PollUpdateView and the PollDeleteView.
+ Generates a ballotpaper.
"""
required_permission = 'motions.can_manage'
- success_url_name = 'motion_detail'
+ top_space = 0
def get_object(self):
"""
@@ -261,21 +270,6 @@ class PollMixin(object):
self._object = obj
return obj
- def get_url_name_args(self):
- """
- Return the arguments to create the url to the success_url.
- """
- return [self.get_object().motion.pk]
-
-
-class PollPDFView(PollMixin, PDFView):
- """
- Generates a ballotpaper.
- """
-
- required_permission = 'motions.can_manage'
- top_space = 0
-
def get_filename(self):
"""
Return the filename for the PDF.
diff --git a/openslides/motions/widgets.py b/openslides/motions/widgets.py
deleted file mode 100644
index bae2b6586..000000000
--- a/openslides/motions/widgets.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from django.utils.translation import ugettext_lazy
-
-from openslides.utils.widgets import Widget
-
-from .models import Motion
-
-
-class MotionWidget(Widget):
- """
- Motion widget.
- """
- name = 'motion'
- verbose_name = ugettext_lazy('Motions')
- required_permission = 'core.can_manage_projector'
- default_column = 1
- default_weight = 40
- icon_css_class = 'icon-file'
- template_name = 'motions/widget_motion.html'
- more_link_pattern_name = 'motion_list'
-
- def get_context_data(self, **context):
- return super(MotionWidget, self).get_context_data(
- motions=Motion.objects.all(),
- **context)
diff --git a/openslides/poll/forms.py b/openslides/poll/forms.py
deleted file mode 100644
index 031a1ef44..000000000
--- a/openslides/poll/forms.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from django import forms
-
-from openslides.utils.forms import CssClassMixin
-
-
-class OptionForm(CssClassMixin, forms.Form):
- def __init__(self, *args, **kwargs):
- extra = kwargs.pop('extra')
- formid = kwargs.pop('formid')
- kwargs['prefix'] = "option-%s" % formid
- super(OptionForm, self).__init__(*args, **kwargs)
-
- for vote in extra:
- key = vote.value
- value = vote.get_value()
- weight = vote.print_weight(raw=True)
- self.fields[key] = forms.IntegerField(
- label=value,
- initial=weight,
- min_value=-2,
- required=False)
diff --git a/openslides/poll/templates/poll/poll.html b/openslides/poll/templates/poll/poll.html
deleted file mode 100644
index 129d8d859..000000000
--- a/openslides/poll/templates/poll/poll.html
+++ /dev/null
@@ -1,29 +0,0 @@
-{% extends 'base.html' %}
-
-{% block content %}
-
-{% endblock %}
diff --git a/openslides/poll/views.py b/openslides/poll/views.py
deleted file mode 100644
index 9ef1f4ea2..000000000
--- a/openslides/poll/views.py
+++ /dev/null
@@ -1,82 +0,0 @@
-from django.forms.models import modelform_factory
-from django.http import HttpResponseRedirect
-from django.shortcuts import get_object_or_404
-
-from openslides.utils.views import TemplateView, FormMixin
-
-
-class PollFormView(FormMixin, TemplateView):
- poll_class = None
-
- def get(self, request, *args, **kwargs):
- self.poll = self.get_object()
- return super(PollFormView, self).get(request, *args, **kwargs)
-
- def post(self, request, *args, **kwargs):
- self.poll = self.get_object()
- option_forms = self.poll.get_vote_forms(data=self.request.POST)
-
- FormClass = self.get_modelform_class()
- pollform = FormClass(data=self.request.POST, instance=self.poll,
- prefix='pollform')
-
- error = False
- for form in option_forms:
- if not form.is_valid():
- error = True
-
- if not pollform.is_valid():
- error = True
-
- if error:
- response = self.render_to_response(self.get_context_data(
- forms=option_forms,
- pollform=pollform))
- else:
- for form in option_forms:
- data = {}
- for value in self.poll.get_vote_values():
- data[value] = form.cleaned_data[value]
- self.poll.set_vote_objects_with_values(form.option, data)
-
- pollform.save()
- response = HttpResponseRedirect(self.get_success_url())
- return response
-
- def get_poll_class(self):
- if self.poll_class is not None:
- return self.poll_class
- else:
- raise NotImplementedError(
- 'No poll class defined. Either provide a poll_class or define '
- 'a get_poll_class method.')
-
- def get_object(self):
- """
- Returns the poll object. Raises Http404 if the poll does not exist.
- """
- try:
- obj = self._object
- except AttributeError:
- queryset = self.get_poll_class().objects.filter(pk=self.kwargs['poll_id'])
- obj = get_object_or_404(queryset)
- self._object = obj
- return obj
-
- def get_context_data(self, **kwargs):
- context = super(PollFormView, self).get_context_data(**kwargs)
- context['poll'] = self.poll
- if 'forms' in kwargs:
- context['forms'] = kwargs['forms']
- context['pollform'] = kwargs['pollform']
- else:
- context['forms'] = self.poll.get_vote_forms()
- FormClass = self.get_modelform_class()
- context['pollform'] = FormClass(instance=self.poll,
- prefix='pollform')
- return context
-
- def get_modelform_class(self):
- fields = []
- self.poll.append_pollform_fields(fields)
- return modelform_factory(type(self.poll), fields=fields)
diff --git a/openslides/projector/api.py b/openslides/projector/api.py
deleted file mode 100644
index 5b98cf92b..000000000
--- a/openslides/projector/api.py
+++ /dev/null
@@ -1,210 +0,0 @@
-from json import dumps
-from time import time
-
-from django.template.loader import render_to_string
-
-from openslides.config.api import config
-from openslides.utils.exceptions import OpenSlidesError
-
-from .signals import projector_overlays
-
-slide_callback = {}
-"""
-A dictonary where the key is the name of a slide, and the value is a
-callable object which returns the html code for a slide.
-"""
-
-slide_model = {}
-"""
-A dictonary for SlideMixin models to reference from the slide_callback_name to
-the Model
-"""
-# TODO: Find a bether way to do this. Maybe by reimplementing slides with
-# metaclasses
-
-
-class SlideError(OpenSlidesError):
- pass
-
-
-def call_on_projector(calls):
- """
- Sends data to the projector.
-
- The argument call has to be a dictionary with the javascript function name
- as key and the argument for it as value.
- """
- # TODO: remove this function
- projector_js_cache = config['projector_js_cache']
- projector_js_cache.update(calls)
- config['projector_js_cache'] = projector_js_cache
-
-
-def get_projector_content(slide_dict=None):
- """
- Returns the HTML-Content block for the projector.
-
- Slide_dict has to be an dictonary with the key 'callback'.
-
- If slide_dict is None, use the active slide from the database.
- """
- if slide_dict is None:
- slide_dict = config['projector_active_slide'].copy()
- callback = slide_dict.pop('callback', None)
-
- try:
- slide_content = slide_callback[callback](**slide_dict)
- except (KeyError, SlideError):
- slide_content = default_slide()
- return slide_content
-
-
-def default_slide():
- """
- Returns the HTML Code for the default slide.
- """
- return render_to_string('projector/default_slide.html')
-
-
-def get_overlays(only_active=False):
- """
- Returns all overlay objects.
-
- If only_active is True, returns only active overlays.
-
- The returned value is a dictonary with the name of the overlay as key, and
- the overlay object as value.
- """
- overlays = {}
- for receiver, overlay in projector_overlays.send(sender='get_overlays'):
- if not only_active or overlay.is_active():
- overlays[overlay.name] = overlay
- return overlays
-
-
-def get_projector_overlays_js(as_json=False):
- """
- Returns JS-Code for the active overlays.
-
- The retuned value is a list of json objects.
- """
- javascript = []
- for overlay in get_overlays().values():
- if overlay.is_active():
- overlay_js = overlay.get_javascript()
- if overlay_js:
- if as_json:
- overlay_js = dumps(overlay_js)
- javascript.append(overlay_js)
- return javascript
-
-
-def register_slide(name, callback, model=None):
- """
- Registers a function as slide callback.
-
- The optional argument 'model' is used to register a SlideModelClass.
- """
- slide_callback[name] = callback
- if model is not None:
- slide_model[name] = model
-
-
-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:
- raise SlideError
- else:
- context = slide.get_slide_context()
-
- return render_to_string(template, context)
-
- register_slide(SlideModel.slide_callback_name, model_slide, SlideModel)
-
-
-def set_active_slide(callback, **kwargs):
- """
- Set the active Slide.
-
- callback: The name of the slide callback.
- kwargs: Keyword arguments for the slide callback.
- """
- kwargs.update(callback=callback)
- config['projector_active_slide'] = kwargs
-
-
-def get_active_slide():
- """
- Returns the dictonary, which defines the active slide.
- """
- return config['projector_active_slide']
-
-
-def get_active_object():
- """
- Returns an object if the active slide is an instance of SlideMixin.
- In other case, returns None
- """
- active_slide_dict = get_active_slide()
- callback_name = active_slide_dict.get('callback', None)
- object_pk = active_slide_dict.get('pk', None)
- try:
- Model = slide_model[callback_name]
- except KeyError:
- value = None
- else:
- try:
- value = Model.objects.get(pk=object_pk)
- except Model.DoesNotExist:
- value = None
- return value
-
-
-def start_countdown():
- """
- Starts the countdown
- """
- # if we had stopped the countdown resume were we left of
- if config['countdown_state'] == 'paused':
- start_stamp = config['countdown_start_stamp']
- pause_stamp = config['countdown_pause_stamp']
- now = time()
- config['countdown_start_stamp'] = now - \
- (pause_stamp - start_stamp)
- else:
- config['countdown_start_stamp'] = time()
-
- config['countdown_state'] = 'active'
- config['countdown_pause_stamp'] = 0
-
-
-def stop_countdown():
- """
- Stops the countdown
- """
- if config['countdown_state'] == 'active':
- config['countdown_state'] = 'paused'
- config['countdown_pause_stamp'] = time()
-
-
-def reset_countdown():
- """
- Resets the countdown
- """
- config['countdown_start_stamp'] = time()
- config['countdown_pause_stamp'] = 0
- config['countdown_state'] = 'inactive'
diff --git a/openslides/projector/apps.py b/openslides/projector/apps.py
deleted file mode 100644
index 5c02769c1..000000000
--- a/openslides/projector/apps.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from django.apps import AppConfig
-
-
-class ProjectorAppConfig(AppConfig):
- name = 'openslides.projector'
- verbose_name = 'OpenSlides Projector'
-
- def ready(self):
- # Load widgets.
- # Do this by just importing all from this file.
- from . import widgets # noqa
-
- # Import all required stuff.
- from openslides.config.signals import config_signal
- from .signals import (
- countdown, projector_clock, projector_overlays,
- projector_overlay_message, setup_projector_config)
-
- # Connect signals.
- config_signal.connect(setup_projector_config, dispatch_uid='setup_projector_config')
- projector_overlays.connect(countdown, dispatch_uid="projector_countdown")
- projector_overlays.connect(projector_overlay_message, dispatch_uid="projector_overlay_message")
- projector_overlays.connect(projector_clock, dispatch_uid="projector_clock")
diff --git a/openslides/projector/exceptions.py b/openslides/projector/exceptions.py
deleted file mode 100644
index 4ce9d1caf..000000000
--- a/openslides/projector/exceptions.py
+++ /dev/null
@@ -1,2 +0,0 @@
-class ProjectorExceptionWarning(RuntimeWarning):
- pass
diff --git a/openslides/projector/models.py b/openslides/projector/models.py
index 9aa1b2b1d..1066f7f8c 100644
--- a/openslides/projector/models.py
+++ b/openslides/projector/models.py
@@ -1,48 +1,8 @@
-from django.core.urlresolvers import reverse
-
-from openslides.utils.utils import int_or_none
-
-
class SlideMixin(object):
"""
- A Mixin for a Django-Model, for making the model a slide.
+ Deprecated.
+
+ Will be reused or removed when more slides are implemented for the
+ OpenSlides 2.0 projector API
"""
-
- slide_callback_name = None
- """
- Name of the callback to render the model as slide.
- """
-
- def get_absolute_url(self, link='projector'):
- """
- Return the url to activate the slide, if link == 'projector'.
- """
- if link in ('projector', 'projector_preview'):
- url_name = {'projector': 'projector_activate_slide',
- 'projector_preview': 'projector_preview'}[link]
- value = '%s?pk=%d' % (
- reverse(url_name,
- args=[self.slide_callback_name]),
- self.pk)
- else:
- value = super(SlideMixin, self).get_absolute_url(link)
- return value
-
- def is_active_slide(self):
- """
- Return True, if the the slide is the active slide.
- """
- from openslides.projector.api import get_active_slide
- active_slide = get_active_slide()
- slide_pk = int_or_none(active_slide.get('pk', None))
- return (active_slide['callback'] == self.slide_callback_name and
- self.pk == slide_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
+ pass
diff --git a/openslides/projector/projector.py b/openslides/projector/projector.py
deleted file mode 100644
index 0d14b29de..000000000
--- a/openslides/projector/projector.py
+++ /dev/null
@@ -1,93 +0,0 @@
-import warnings
-
-from openslides.config.api import config
-
-from .exceptions import ProjectorExceptionWarning
-
-
-class Overlay(object):
- """
- Represents an overlay which can be seen on the projector.
- """
-
- def __init__(self, name, get_widget_html, get_projector_html,
- get_javascript=None, allways_active=False):
- self.name = name
- self.widget_html_callback = get_widget_html
- self.projector_html_callback = get_projector_html
- self.javascript_callback = get_javascript
- self.allways_active = allways_active
-
- def __repr__(self):
- return self.name
-
- def get_widget_html(self):
- """
- Returns the html code for the overlay widget.
-
- Can return None, if the widget does not want to be in the widget.
- """
- value = None
- if self.widget_html_callback is not None:
- value = self.widget_html_callback()
- return value
-
- def get_projector_html(self):
- """
- Returns the html code for the projector.
- """
- try:
- value = self.get_html_wrapper(self.projector_html_callback())
- except Exception as exception:
- warnings.warn('%s in overlay "%s": %s'
- % (type(exception).__name__, self, exception),
- ProjectorExceptionWarning)
- value = ''
- return value
-
- def get_javascript(self):
- """
- Returns the java-script code for the projector.
- """
- if self.javascript_callback is None:
- value = {}
- else:
- value = self.javascript_callback()
- return value
-
- def get_html_wrapper(self, inner_html):
- """
- Returns the inner_html wrapped in a div.
-
- The html-id of the div is "overlay_OVERLAYNAME"
- """
- full_html = ''
- if inner_html is not None:
- full_html = '%s
' % (self.name, inner_html)
- return full_html
-
- def is_active(self):
- """
- Returns True if the overlay is activated. False in other case.
- """
- return self.allways_active or self.name in config['projector_active_overlays']
-
- def set_active(self, active):
- """
- Publish or depublish the overlay on the projector.
-
- publish, if active is true,
- depublish, if active is false.
- """
- active_overlays = set(config['projector_active_overlays'])
- if active:
- active_overlays.add(self.name)
- else:
- active_overlays.discard(self.name)
- config['projector_active_overlays'] = list(active_overlays)
-
- def show_on_projector(self):
- """
- Retruns True if the overlay should be shoun on the projector.
- """
- return self.is_active() and self.get_projector_html() is not None
diff --git a/openslides/projector/signals.py b/openslides/projector/signals.py
deleted file mode 100644
index b75710e29..000000000
--- a/openslides/projector/signals.py
+++ /dev/null
@@ -1,167 +0,0 @@
-from time import time
-
-from django.contrib.staticfiles.templatetags.staticfiles import static
-from django.core.context_processors import csrf
-from django.dispatch import Signal
-from django.template.loader import render_to_string
-from django.utils.datastructures import SortedDict
-
-from openslides.config.api import config, ConfigCollection, ConfigVariable
-
-from .projector import Overlay
-
-projector_overlays = Signal(providing_args=['request'])
-
-
-def setup_projector_config(sender, **kwargs):
- """
- Receiver function to setup all projector config variables. They are not
- shown on a config view. The function is connected to the signal
- openslides.config.signals.config_signal during app loading.
- """
- # The active slide. The config-value is a dictonary with at least the entry
- # 'callback'.
- projector = ConfigVariable(
- name='projector_active_slide',
- default_value={'callback': None})
-
- projector_message = ConfigVariable(
- name='projector_message',
- default_value='')
-
- countdown_time = ConfigVariable(
- name='countdown_time',
- default_value=60)
-
- countdown_start_stamp = ConfigVariable(
- name='countdown_start_stamp',
- default_value=0)
-
- countdown_pause_stamp = ConfigVariable(
- name='countdown_pause_stamp',
- default_value=0)
-
- countdown_state = ConfigVariable(
- name='countdown_state',
- default_value='inactive')
-
- projector_scale = ConfigVariable(
- name='projector_scale',
- default_value=0)
-
- projector_scroll = ConfigVariable(
- name='projector_scroll',
- default_value=0)
-
- projector_js_cache = ConfigVariable(
- name='projector_js_cache',
- default_value={})
-
- projector_active_overlays = ConfigVariable(
- name='projector_active_overlays',
- default_value=[])
-
- projector_pdf_fullscreen = ConfigVariable(
- name='pdf_fullscreen',
- default_value=False)
-
- return ConfigCollection(
- variables=(
- projector, projector_message,
- countdown_time, countdown_start_stamp, countdown_pause_stamp,
- countdown_state, projector_scale, projector_scroll,
- projector_active_overlays, projector_js_cache,
- projector_pdf_fullscreen))
-
-
-def countdown(sender, **kwargs):
- """
- Receiver function for the projector countdown. The function is
- connected to the signal projector_overlays during app loading.
- """
- name = 'projector_countdown'
- request = kwargs.get('request', None)
-
- def get_widget_html():
- """
- Returns the the html-code to show in the overly-widget.
- """
- context = {
- 'countdown_time': config['countdown_time'],
- 'countdown_state': config['countdown_state']}
- context.update(csrf(request))
- return render_to_string('projector/overlay_countdown_widget.html',
- context)
-
- def get_projector_js():
- """
- Returns JavaScript for the projector
- """
- value = SortedDict()
- value['load_file'] = static('js/countdown.js')
- value['projector_countdown_start'] = int(config['countdown_start_stamp'])
- value['projector_countdown_duration'] = int(config['countdown_time'])
- value['projector_countdown_pause'] = int(config['countdown_pause_stamp'])
- value['projector_countdown_state'] = config['countdown_state']
- value['call'] = 'update_countdown();'
- return value
-
- def get_projector_html():
- """
- Returns an html-code to show on the projector.
- """
- return render_to_string('projector/overlay_countdown_projector.html')
-
- return Overlay(name, get_widget_html, get_projector_html, get_projector_js)
-
-
-def projector_overlay_message(sender, **kwargs):
- """
- Receiver function to show the overlay_message on the projector or the
- form in the overlay-widget on the dashboard. The function is connected
- to the signal projector_overlays during app loading.
- """
- name = 'projector_message'
- request = kwargs.get('request', None)
-
- def get_widget_html():
- """
- Returns the the html-code to show in the overly-widget.
- """
- return render_to_string('projector/overlay_message_widget.html', csrf(request))
-
- def get_projector_html():
- """
- Returns an html-code to show on the projector.
- """
- if config['projector_message']:
- return render_to_string('projector/overlay_message_projector.html',
- {'message': config['projector_message']})
- return None
-
- return Overlay(name, get_widget_html, get_projector_html)
-
-
-def projector_clock(sender, **kwargs):
- """
- Receiver function to show the clock on the projector. The function is
- connected to the signal projector_overlays during app loading.
- """
- name = 'projector_clock'
-
- def get_projector_html():
- """
- Returns the html-code for the clock.
- """
- return render_to_string('projector/overlay_clock_projector.html')
-
- def get_projector_js():
- """
- Returns JavaScript for the projector
- """
- javascript = 'projector.set_server_time(%d);update_clock();' % int(time())
- return {'load_file': static('js/clock.js'),
- 'call': javascript}
-
- return Overlay(name, None, get_projector_html, get_projector_js,
- allways_active=True)
diff --git a/openslides/projector/static/css/projector.css b/openslides/projector/static/css/projector.css
deleted file mode 100644
index e1a29d990..000000000
--- a/openslides/projector/static/css/projector.css
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * OpenSlides default projector styles
- *
- */
-
-body{
- font-size: 20px !important;
- line-height: 24px !important;
- overflow: hidden;
-}
-
-/*** HEADER ***/
-#header {
- box-shadow: 0 0 7px rgba(0,0,0,0.6);
- height: 70px;
- margin-bottom: 20px;
-}
-#logo {
- position: relative;
- left: 75px;
- top: 4px;
- height: 60px;
- margin-right: 35px;
- float: left;
-}
-#eventdata {
- position: relative;
- left: 75px;
- top: 12px;
- height: 50px;
- overflow: hidden;
-}
-#eventdata .title {
- font-size: 26px;
- font-weight: bold;
- }
-#eventdata .title.titleonly {
- position: relative;
- top: 12px;
-}
-#eventdata .description {
- font-size: 18px;
- opacity: 0.5;
-}
-#currentTime {
- border:0 solid #000000;
- font-size:24px;
- position:absolute;
- text-align:right;
- top:110px;
- right:40px;
- padding-left:30px;
- background: url(../img/glyphicons_054_clock_big.png) no-repeat scroll 0px 0px;
-}
-
-/*** CONTENT with base style elements ***/
-#content {
- position: absolute;
- left: 75px;
- top: 150px;
- right: 40px;
- z-index: -1;
- line-height: normal;
- transition-property: margin, font-size;
- transition-duration: 1s;
-}
-h1 {
- font-size: 2.25em;
- margin-bottom: 40px;
- line-height: 1.1em;
- padding-bottom: 10px;
- border-bottom: 1px solid #e6e6e6;
-}
-h1.title_only {
- text-align: center;
- font-size: 2.75em;
- line-height: 1.3em;
- border: 0px;
- padding: 40px;
- margin-left: -35px; /* see #content position 'left' - 'right' for real centering */
-}
-h1 small {
- font-size: 0.55em;
- margin-top: 15px;
- display: block;
-}
-h3 {
- font-size: 1.2em;
-}
-#sidebar {
- width: 255px;
- float: right;
- margin: 0 0 20px 10px;
-}
-ul, ol {
- margin: 0 0 10px 2em;
-}
-li {
- line-height: normal;
-}
-.well h4 {
- margin: 20px 0 2px 0;
-}
-.well h4.first {
- margin-top: 0;
-}
-.well .result {
- line-height: 30px;
-}
-.well .result hr {
- border-top: 1px solid;
- margin: 5px 0;
- width: 10em;
-}
-.result.big {
- font-size: 120%;
- line-height: 40px;
-}
-.result .bold {
- font-weight: bold;
-}
-hr {
- margin: 10px 0;
-}
-.nobr {
- white-space: nowrap;
-}
-
-
-/*** Overlay ***/
-#overlay_transparent {
- background-color: #777777;
- opacity: 0.6;
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
-}
-#overlay_countdown_inner {
- position: fixed;
- right: 40px;
- height: 30px;
- width: 215px;
- margin: 0;
- top: 0;
- font-size: 4em;
- font-weight: bold;
- text-align: center;
- border-radius: 0 0 0.2em 0.2em;
-}
-#overlay_countdown_inner.negative {
- color: #CC0000;
-}
-#overlay_message_inner {
- position: fixed;
- top: 35%;
- left: 10%;
- width: 80%;
- text-align: center;
- border-radius: 0.5em;
- background: #FFFFFF;
- font-size: 2.75em;
- padding: 0.2em 0;
- line-height: normal !important;
-}
-
-
-/*** Table style ***/
-table {
- border-collapse:collapse;
- border-color:#CCCCCC -moz-use-text-color #CCCCCC #CCCCCC;
- border-style:solid none solid solid;
- border-width:1px medium 1px 1px;
- margin:0;
- border-spacing:0px;
-}
-table th {
- border-right:1px solid #CCCCCC;
- color:#333333;
- font-weight:normal;
- padding:10px 10px 10px 10px;
- text-align:left;
- text-transform:uppercase;
-}
-table tr.odd td {
- background:none repeat scroll 0 0 #F1F1F1;
-}
-table td {
- background:none repeat scroll 0 0 #F7F7F7;
- border-right:1px solid #CCCCCC;
- line-height:120%;
- padding: 10px 10px;
- vertical-align:middle;
-}
-tr.total td {
- border-top: 1px solid #333333;
- background-color: #e3e3e3;
-}
-tr.elected td {
- background-color: #BED4DE !important;
-}
diff --git a/openslides/projector/static/img/glyphicons_054_clock_big.png b/openslides/projector/static/img/glyphicons_054_clock_big.png
deleted file mode 100644
index 46a86c1a9..000000000
Binary files a/openslides/projector/static/img/glyphicons_054_clock_big.png and /dev/null differ
diff --git a/openslides/projector/static/img/logo-projector.png b/openslides/projector/static/img/logo-projector.png
deleted file mode 100644
index 9b81eb762..000000000
Binary files a/openslides/projector/static/img/logo-projector.png and /dev/null differ
diff --git a/openslides/projector/static/js/clock.js b/openslides/projector/static/js/clock.js
deleted file mode 100644
index b0471a634..000000000
--- a/openslides/projector/static/js/clock.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * JavaScript functions for clock.
- *
- */
-
-function update_clock() {
- var currentTime = projector.get_server_time()
- var currentHours = currentTime.getHours();
- var currentMinutes = currentTime.getMinutes();
- currentHours = normalise(currentHours);
- currentMinutes = normalise(currentMinutes);
- $('#currentTime').html(currentHours + ':' + currentMinutes);
-}
-
-setInterval('update_clock()', 200);
-
-function normalise(i) {
- if (i < 10) {
- i = "0" + i;
- }
- return i;
-}
diff --git a/openslides/projector/static/js/countdown.js b/openslides/projector/static/js/countdown.js
deleted file mode 100644
index 06d6eb72e..000000000
--- a/openslides/projector/static/js/countdown.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * JavaScript functions for countdown.
- *
- */
-
-
-function update_countdown() {
- var time = projector.get_server_time().getTime() / 1000;
- var totalseconds;
- var min;
- var sec;
- var negative;
- var start = projector.projector_countdown_start;
- var duration = projector.projector_countdown_duration;
- var pause = projector.projector_countdown_pause;
-
- switch (projector.projector_countdown_state) {
- case 'active':
- totalseconds = start + duration - time;
- break;
- case 'paused':
- totalseconds = start + duration - pause;
- break;
- case 'inactive':
- totalseconds = duration;
- break;
- }
- totalseconds = Math.floor(totalseconds);
- if (totalseconds < 0 ) {
- totalseconds = -totalseconds;
- negative = true;
- }
- min = Math.floor(totalseconds / 60);
- sec = Math.floor(totalseconds - (min * 60));
- if (sec < 10) {
- sec = "0" + sec;
- }
- if (negative) {
- min = "-" + min;
- $('#overlay_countdown_inner').addClass('negative');
- }
- else {
- $('#overlay_countdown_inner').removeClass('negative');
- }
- if(totalseconds !== undefined) {
- $('#overlay_countdown_inner').html(min + ":" + sec);
-
- }
-}
-setInterval('update_countdown()', 200);
diff --git a/openslides/projector/static/js/projector.js b/openslides/projector/static/js/projector.js
deleted file mode 100644
index 4ad097062..000000000
--- a/openslides/projector/static/js/projector.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * JavaScript functions for projector.
- *
- */
-
-$(document).ready(function() {
- if ($('#content.reload').length > 0) {
- updater.start();
- }
-});
-
-var projector = {
- _loaded_files: {},
-
- load_file: function(src) {
- if (projector._loaded_files[src] === undefined) {
- projector._loaded_files[src] = document.createElement('script');
- projector._loaded_files[src].setAttribute("type","text/javascript");
- projector._loaded_files[src].setAttribute("src", src);
- $('head').append(projector._loaded_files[src]);
- }
- },
-
- scroll: function(value) {
- $('#content').css('margin-top', -10 * value + 'em');
- },
-
- scale: function(value) {
- $('#content').css('font-size', 100 + 20 * value + '%');
- },
-
- get_server_time: function () {
- var date = new Date();
- date.setTime(date.getTime() - projector.server_time_offset);
- return date;
- },
-
- set_server_time: function(value) {
- var local_time = Date.parse(new Date().toUTCString());
- projector.server_time_offset = local_time - value * 1000;
- },
-
- update_data: function(data) {
- $.each(data, function (key, value) {
- if (key === 'load_file')
- projector.load_file(value);
- else if (key === 'call') {
- try {
- eval(value);
- } catch (e) {}
- } else
- projector[key] = value;
- });
- }
-};
-
-var updater = {
- socket: null,
-
- start: function() {
- var url = "http://" + location.host + "/projector/socket";
- updater.socket = new SockJS(url);
- updater.socket.onmessage = function(event) {
- updater.updateProjector(event.data);
- }
- updater.socket.onclose = function() {
- setTimeout('updater.start()', 5000);
- }
- },
-
- updateProjector: function(data) {
- if (data.content) {
- $('#content').removeClass('fullscreen');
- $('#footer').removeClass('black');
- $('body').removeClass('black');
- $('#content').html(data.content);
- }
- if (data.overlays) {
- $.each(data.overlays, function (key, value) {
- var overlay = $('#overlays #overlay_' + key)
- if (!value)
- overlay.remove();
- else {
- if (overlay.length) {
- overlay.html(value.html)
- } else {
- $('#overlays').append(value.html);
- }
- projector.update_data(value.javascript);
- }
- });
- }
- if (data.calls) {
- $.each(data.calls, function (call, argument) {
- projector[call](argument);
- });
- }
- }
-};
diff --git a/openslides/projector/static/js/sockjs-0.3.min.js b/openslides/projector/static/js/sockjs-0.3.min.js
deleted file mode 100644
index baae37641..000000000
--- a/openslides/projector/static/js/sockjs-0.3.min.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SockJS client, version 0.3.4, http://sockjs.org, MIT License
-
-Copyright (c) 2011-2012 VMware, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-// JSON2 by Douglas Crockford (minified).
-var JSON;JSON||(JSON={}),function(){function str(a,b){var c,d,e,f,g=gap,h,i=b[a];i&&typeof i=="object"&&typeof i.toJSON=="function"&&(i=i.toJSON(a)),typeof rep=="function"&&(i=rep.call(b,a,i));switch(typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";gap+=indent,h=[];if(Object.prototype.toString.apply(i)==="[object Array]"){f=i.length;for(c=0;c1?this._listeners[a]=d.slice(0,e).concat(d.slice(e+1)):delete this._listeners[a];return}return},d.prototype.dispatchEvent=function(a){var b=a.type,c=Array.prototype.slice.call(arguments,0);this["on"+b]&&this["on"+b].apply(this,c);if(this._listeners&&b in this._listeners)for(var d=0;d=3e3&&a<=4999},c.countRTO=function(a){var b;return a>100?b=3*a:b=a+200,b},c.log=function(){b.console&&console.log&&console.log.apply&&console.log.apply(console,arguments)},c.bind=function(a,b){return a.bind?a.bind(b):function(){return a.apply(b,arguments)}},c.flatUrl=function(a){return a.indexOf("?")===-1&&a.indexOf("#")===-1},c.amendUrl=function(b){var d=a.location;if(!b)throw new Error("Wrong url for SockJS");if(!c.flatUrl(b))throw new Error("Only basic urls are supported in SockJS");return b.indexOf("//")===0&&(b=d.protocol+b),b.indexOf("/")===0&&(b=d.protocol+"//"+d.host+b),b=b.replace(/[/]+$/,""),b},c.arrIndexOf=function(a,b){for(var c=0;c=0},c.delay=function(a,b){return typeof a=="function"&&(b=a,a=0),setTimeout(b,a)};var i=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,j={"\0":"\\u0000","\x01":"\\u0001","\x02":"\\u0002","\x03":"\\u0003","\x04":"\\u0004","\x05":"\\u0005","\x06":"\\u0006","\x07":"\\u0007","\b":"\\b","\t":"\\t","\n":"\\n","\x0b":"\\u000b","\f":"\\f","\r":"\\r","\x0e":"\\u000e","\x0f":"\\u000f","\x10":"\\u0010","\x11":"\\u0011","\x12":"\\u0012","\x13":"\\u0013","\x14":"\\u0014","\x15":"\\u0015","\x16":"\\u0016","\x17":"\\u0017","\x18":"\\u0018","\x19":"\\u0019","\x1a":"\\u001a","\x1b":"\\u001b","\x1c":"\\u001c","\x1d":"\\u001d","\x1e":"\\u001e","\x1f":"\\u001f",'"':'\\"',"\\":"\\\\","\x7f":"\\u007f","\x80":"\\u0080","\x81":"\\u0081","\x82":"\\u0082","\x83":"\\u0083","\x84":"\\u0084","\x85":"\\u0085","\x86":"\\u0086","\x87":"\\u0087","\x88":"\\u0088","\x89":"\\u0089","\x8a":"\\u008a","\x8b":"\\u008b","\x8c":"\\u008c","\x8d":"\\u008d","\x8e":"\\u008e","\x8f":"\\u008f","\x90":"\\u0090","\x91":"\\u0091","\x92":"\\u0092","\x93":"\\u0093","\x94":"\\u0094","\x95":"\\u0095","\x96":"\\u0096","\x97":"\\u0097","\x98":"\\u0098","\x99":"\\u0099","\x9a":"\\u009a","\x9b":"\\u009b","\x9c":"\\u009c","\x9d":"\\u009d","\x9e":"\\u009e","\x9f":"\\u009f","\xad":"\\u00ad","\u0600":"\\u0600","\u0601":"\\u0601","\u0602":"\\u0602","\u0603":"\\u0603","\u0604":"\\u0604","\u070f":"\\u070f","\u17b4":"\\u17b4","\u17b5":"\\u17b5","\u200c":"\\u200c","\u200d":"\\u200d","\u200e":"\\u200e","\u200f":"\\u200f","\u2028":"\\u2028","\u2029":"\\u2029","\u202a":"\\u202a","\u202b":"\\u202b","\u202c":"\\u202c","\u202d":"\\u202d","\u202e":"\\u202e","\u202f":"\\u202f","\u2060":"\\u2060","\u2061":"\\u2061","\u2062":"\\u2062","\u2063":"\\u2063","\u2064":"\\u2064","\u2065":"\\u2065","\u2066":"\\u2066","\u2067":"\\u2067","\u2068":"\\u2068","\u2069":"\\u2069","\u206a":"\\u206a","\u206b":"\\u206b","\u206c":"\\u206c","\u206d":"\\u206d","\u206e":"\\u206e","\u206f":"\\u206f","\ufeff":"\\ufeff","\ufff0":"\\ufff0","\ufff1":"\\ufff1","\ufff2":"\\ufff2","\ufff3":"\\ufff3","\ufff4":"\\ufff4","\ufff5":"\\ufff5","\ufff6":"\\ufff6","\ufff7":"\\ufff7","\ufff8":"\\ufff8","\ufff9":"\\ufff9","\ufffa":"\\ufffa","\ufffb":"\\ufffb","\ufffc":"\\ufffc","\ufffd":"\\ufffd","\ufffe":"\\ufffe","\uffff":"\\uffff"},k=/[\x00-\x1f\ud800-\udfff\ufffe\uffff\u0300-\u0333\u033d-\u0346\u034a-\u034c\u0350-\u0352\u0357-\u0358\u035c-\u0362\u0374\u037e\u0387\u0591-\u05af\u05c4\u0610-\u0617\u0653-\u0654\u0657-\u065b\u065d-\u065e\u06df-\u06e2\u06eb-\u06ec\u0730\u0732-\u0733\u0735-\u0736\u073a\u073d\u073f-\u0741\u0743\u0745\u0747\u07eb-\u07f1\u0951\u0958-\u095f\u09dc-\u09dd\u09df\u0a33\u0a36\u0a59-\u0a5b\u0a5e\u0b5c-\u0b5d\u0e38-\u0e39\u0f43\u0f4d\u0f52\u0f57\u0f5c\u0f69\u0f72-\u0f76\u0f78\u0f80-\u0f83\u0f93\u0f9d\u0fa2\u0fa7\u0fac\u0fb9\u1939-\u193a\u1a17\u1b6b\u1cda-\u1cdb\u1dc0-\u1dcf\u1dfc\u1dfe\u1f71\u1f73\u1f75\u1f77\u1f79\u1f7b\u1f7d\u1fbb\u1fbe\u1fc9\u1fcb\u1fd3\u1fdb\u1fe3\u1feb\u1fee-\u1fef\u1ff9\u1ffb\u1ffd\u2000-\u2001\u20d0-\u20d1\u20d4-\u20d7\u20e7-\u20e9\u2126\u212a-\u212b\u2329-\u232a\u2adc\u302b-\u302c\uaab2-\uaab3\uf900-\ufa0d\ufa10\ufa12\ufa15-\ufa1e\ufa20\ufa22\ufa25-\ufa26\ufa2a-\ufa2d\ufa30-\ufa6d\ufa70-\ufad9\ufb1d\ufb1f\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufb4e\ufff0-\uffff]/g,l,m=JSON&&JSON.stringify||function(a){return i.lastIndex=0,i.test(a)&&(a=a.replace(i,function(a){return j[a]})),'"'+a+'"'},n=function(a){var b,c={},d=[];for(b=0;b<65536;b++)d.push(String.fromCharCode(b));return a.lastIndex=0,d.join("").replace(a,function(a){return c[a]="\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4),""}),a.lastIndex=0,c};c.quote=function(a){var b=m(a);return k.lastIndex=0,k.test(b)?(l||(l=n(k)),b.replace(k,function(a){return l[a]})):b};var o=["websocket","xdr-streaming","xhr-streaming","iframe-eventsource","iframe-htmlfile","xdr-polling","xhr-polling","iframe-xhr-polling","jsonp-polling"];c.probeProtocols=function(){var a={};for(var b=0;b0&&h(a)};return c.websocket!==!1&&h(["websocket"]),d["xhr-streaming"]&&!c.null_origin?e.push("xhr-streaming"):d["xdr-streaming"]&&!c.cookie_needed&&!c.null_origin?e.push("xdr-streaming"):h(["iframe-eventsource","iframe-htmlfile"]),d["xhr-polling"]&&!c.null_origin?e.push("xhr-polling"):d["xdr-polling"]&&!c.cookie_needed&&!c.null_origin?e.push("xdr-polling"):h(["iframe-xhr-polling","jsonp-polling"]),e};var p="_sockjs_global";c.createHook=function(){var a="a"+c.random_string(8);if(!(p in b)){var d={};b[p]=function(a){return a in d||(d[a]={id:a,del:function(){delete d[a]}}),d[a]}}return b[p](a)},c.attachMessage=function(a){c.attachEvent("message",a)},c.attachEvent=function(c,d){typeof b.addEventListener!="undefined"?b.addEventListener(c,d,!1):(a.attachEvent("on"+c,d),b.attachEvent("on"+c,d))},c.detachMessage=function(a){c.detachEvent("message",a)},c.detachEvent=function(c,d){typeof b.addEventListener!="undefined"?b.removeEventListener(c,d,!1):(a.detachEvent("on"+c,d),b.detachEvent("on"+c,d))};var q={},r=!1,s=function(){for(var a in q)q[a](),delete q[a]},t=function(){if(r)return;r=!0,s()};c.attachEvent("unload",t),c.unload_add=function(a){var b=c.random_string(8);return q[b]=a,r&&c.delay(s),b},c.unload_del=function(a){a in q&&delete q[a]},c.createIframe=function(b,d){var e=a.createElement("iframe"),f,g,h=function(){clearTimeout(f);try{e.onload=null}catch(a){}e.onerror=null},i=function(){e&&(h(),setTimeout(function(){e&&e.parentNode.removeChild(e),e=null},0),c.unload_del(g))},j=function(a){e&&(i(),d(a))},k=function(a,b){try{e&&e.contentWindow&&e.contentWindow.postMessage(a,b)}catch(c){}};return e.src=b,e.style.display="none",e.style.position="absolute",e.onerror=function(){j("onerror")},e.onload=function(){clearTimeout(f),f=setTimeout(function(){j("onload timeout")},2e3)},a.body.appendChild(e),f=setTimeout(function(){j("timeout")},15e3),g=c.unload_add(i),{post:k,cleanup:i,loaded:h}},c.createHtmlfile=function(a,d){var e=new ActiveXObject("htmlfile"),f,g,i,j=function(){clearTimeout(f)},k=function(){e&&(j(),c.unload_del(g),i.parentNode.removeChild(i),i=e=null,CollectGarbage())},l=function(a){e&&(k(),d(a))},m=function(a,b){try{i&&i.contentWindow&&i.contentWindow.postMessage(a,b)}catch(c){}};e.open(),e.write('
-
-
-
-
-
-
-
-
-
- {% for overlay in overlays.values %}
- {{ overlay.get_projector_html|safe }}
- {% endfor %}
-
-
-
- {{ content }}
-
-
-