diff --git a/CHANGELOG b/CHANGELOG index a0ac8038f..81d9889e2 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -8,6 +8,9 @@ Version 1.6 (unreleased) ======================== [https://github.com/OpenSlides/OpenSlides/issues?milestone=14] +Other: +- Changed widget api. Used new metaclass. + Version 1.5.1 (unreleased) ========================== diff --git a/fabfile.py b/fabfile.py index 916de3be6..3bbff6e0a 100644 --- a/fabfile.py +++ b/fabfile.py @@ -25,7 +25,7 @@ def coverage_report_plain(): Runs all tests and prints the coverage report. """ test() - local('coverage report -m --fail-under=75') + local('coverage report -m --fail-under=76') def coverage(): diff --git a/openslides/account/__init__.py b/openslides/account/__init__.py index e69de29bb..6aef35e80 100644 --- a/openslides/account/__init__.py +++ b/openslides/account/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import widgets # noqa diff --git a/openslides/account/templates/account/personal_info_widget.html b/openslides/account/templates/account/widget_personal_info.html similarity index 93% rename from openslides/account/templates/account/personal_info_widget.html rename to openslides/account/templates/account/widget_personal_info.html index 9d21ecf43..e51048bff 100644 --- a/openslides/account/templates/account/personal_info_widget.html +++ b/openslides/account/templates/account/widget_personal_info.html @@ -1,6 +1,9 @@ +{% extends 'core/widget.html' %} + {% load i18n %} {% load tags %} +{% block content %} -{% if config_motion_min_supporters %} +{% if 'motion_min_supporters'|get_config %}
+{% endblock %} diff --git a/openslides/account/views.py b/openslides/account/views.py deleted file mode 100644 index 7064ce99d..000000000 --- a/openslides/account/views.py +++ /dev/null @@ -1,66 +0,0 @@ -# -*- coding: utf-8 -*- - -from django.contrib.auth.models import AnonymousUser -from django.utils.translation import ugettext as _ - -from openslides.config.api import config -from openslides.projector.projector import Widget - - -def get_widgets(request): - """ - Returns the widgets of the account app. It is only the personal_info_widget. - """ - if not isinstance(request.user, AnonymousUser): - return [get_personal_info_widget(request)] - else: - return [] - - -def get_personal_info_widget(request): - """ - Provides a widget for personal info. It shows your submitted and supported - motions, where you are on the list of speakers and where you are supporter - or candidate. If one of the modules agenda, motion or assignment does - not exist, it is not loaded. If all does not exist, the widget disapears. - """ - personal_info_context = {} - - try: - from openslides.agenda.models import Item - except ImportError: - pass - else: - personal_info_context.update({ - 'items': Item.objects.filter( - speaker__person=request.user, - speaker__begin_time=None)}) - try: - from openslides.motion.models import Motion - except ImportError: - pass - else: - personal_info_context.update({ - 'submitted_motions': Motion.objects.filter(submitter__person=request.user), - 'config_motion_min_supporters': config['motion_min_supporters'], - 'supported_motions': Motion.objects.filter(supporter__person=request.user)}) - try: - from openslides.assignment.models import Assignment - except ImportError: - pass - else: - personal_info_context.update({ - 'assignments': Assignment.objects.filter( - assignmentcandidate__person=request.user, - assignmentcandidate__blocked=False)}) - - if personal_info_context: - return Widget( - request, - name='personal_info', - display_name=_('My items, motions and elections'), - template='account/personal_info_widget.html', - context=personal_info_context, - permission_required=None, - default_column=1, - default_weight=80) diff --git a/openslides/account/widgets.py b/openslides/account/widgets.py new file mode 100644 index 000000000..6d30c7cfe --- /dev/null +++ b/openslides/account/widgets.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- + +from django.contrib.auth.models import AnonymousUser +from django.utils.translation import ugettext_lazy + +from openslides.utils.widgets import Widget + + +class PersonalInfoWidget(Widget): + """ + Provides a widget for personal info. It shows your submitted and supported + motions, where you are on the list of speakers and where you are supporter + or candidate. If one of the modules agenda, motion or assignment does + not exist, it is not loaded. If all does not exist, the widget disapears. + """ + name = 'personal_info' + verbose_name = ugettext_lazy('My items, motions and elections') + default_column = 1 + default_weight = 80 + template_name = 'account/widget_personal_info.html' + + 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 can neither the agenda app, nor the + motion app nor the assignment app be found. + """ + for module in ('agenda', 'motion', 'assignment'): + try: + __import__('openslides.%s' % module) + except ImportError: + continue + else: + active = True + break + else: + active = False + return active + + def get_context_data(self, **context): + """ + Adds the context to the widget. + """ + try: + from openslides.agenda.models import Item + except ImportError: + pass + else: + context.update({ + 'items': Item.objects.filter( + speaker__person=self.request.user, + speaker__begin_time=None)}) + try: + from openslides.motion.models import Motion + except ImportError: + pass + else: + context.update({ + 'submitted_motions': Motion.objects.filter(submitter__person=self.request.user), + 'supported_motions': Motion.objects.filter(supporter__person=self.request.user)}) + try: + from openslides.assignment.models import Assignment + except ImportError: + pass + else: + context.update({ + 'assignments': Assignment.objects.filter( + assignmentcandidate__person=self.request.user, + assignmentcandidate__blocked=False)}) + return super(PersonalInfoWidget, self).get_context_data(**context) diff --git a/openslides/agenda/__init__.py b/openslides/agenda/__init__.py index 9c5992b37..635921a8c 100644 --- a/openslides/agenda/__init__.py +++ b/openslides/agenda/__init__.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- -from . import signals, slides # noqa +from . import signals, slides, widgets # noqa diff --git a/openslides/agenda/templates/agenda/speaker_widget.html b/openslides/agenda/templates/agenda/speaker_widget.html deleted file mode 100644 index 9b6b0e7b1..000000000 --- a/openslides/agenda/templates/agenda/speaker_widget.html +++ /dev/null @@ -1,14 +0,0 @@ -{% load i18n %} - -{% if perms.agenda.can_be_speaker %} -

{% trans 'Put me on the current list of speakers' %}

-{% endif %} - -{% if perms.agenda.can_manage_agenda %} -

- {% trans 'Next speaker' %} - {% trans 'End speach' %} -

-{% endif %} - -

{% trans 'Go to current list of speakers' %}...

diff --git a/openslides/agenda/templates/agenda/widget.html b/openslides/agenda/templates/agenda/widget_item.html similarity index 96% rename from openslides/agenda/templates/agenda/widget.html rename to openslides/agenda/templates/agenda/widget_item.html index ad8ae6bfa..c4dea34bf 100644 --- a/openslides/agenda/templates/agenda/widget.html +++ b/openslides/agenda/templates/agenda/widget_item.html @@ -1,6 +1,9 @@ +{% extends 'core/widget.html' %} + {% load i18n %} {% load tags %} +{% block content %} - -

{% trans "More..." %}

+{% endblock %} diff --git a/openslides/agenda/templates/agenda/widget_list_of_speakers.html b/openslides/agenda/templates/agenda/widget_list_of_speakers.html new file mode 100644 index 000000000..e16ab5069 --- /dev/null +++ b/openslides/agenda/templates/agenda/widget_list_of_speakers.html @@ -0,0 +1,16 @@ +{% extends 'core/widget.html' %} + +{% load i18n %} + +{% block content %} +{% if perms.agenda.can_be_speaker %} +

{% trans 'Put me on the current list of speakers' %}

+{% endif %} +{% if perms.agenda.can_manage_agenda %} +

+ {% trans 'Next speaker' %} + {% trans 'End speach' %} +

+{% endif %} +

{% trans 'Go to current list of speakers' %} ...

+{% endblock %} diff --git a/openslides/agenda/urls.py b/openslides/agenda/urls.py index 032da6fea..194e44855 100644 --- a/openslides/agenda/urls.py +++ b/openslides/agenda/urls.py @@ -8,7 +8,7 @@ urlpatterns = patterns( '', url(r'^$', views.Overview.as_view(), - name='item_overview'), + name='item_overview'), # TODO: Rename this to item_list url(r'^(?P\d+)/$', views.AgendaItemView.as_view(), diff --git a/openslides/agenda/views.py b/openslides/agenda/views.py index 18637e688..b5410de6d 100644 --- a/openslides/agenda/views.py +++ b/openslides/agenda/views.py @@ -13,7 +13,6 @@ from reportlab.platypus import Paragraph from openslides.config.api import config from openslides.projector.api import get_active_slide, update_projector -from openslides.projector.projector import Widget from openslides.utils.exceptions import OpenSlidesError from openslides.utils.pdf import stylesheet from openslides.utils.template import Tab @@ -636,39 +635,3 @@ def register_tab(request): permission=(request.user.has_perm('agenda.can_see_agenda') or request.user.has_perm('agenda.can_manage_agenda')), selected=selected) - - -def get_widgets(request): - """ - Returns the agenda widget for the projector tab. - """ - 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 - - return [ - Widget( - request, - name='agenda', - display_name=_('Agenda'), - template='agenda/widget.html', - context={ - 'agenda_is_active': agenda_is_active, - 'items': Item.objects.all(), - 'active_type': active_type}, - permission_required='projector.can_manage_projector', - default_column=1, - default_weight=20), - - Widget( - request, - name='append_to_list_of_speakers', - display_name=_('List of speakers'), - template='agenda/speaker_widget.html', - permission_required='agenda.can_be_speaker', - default_column=1, - default_weight=30)] diff --git a/openslides/agenda/widgets.py b/openslides/agenda/widgets.py new file mode 100644 index 000000000..666267863 --- /dev/null +++ b/openslides/agenda/widgets.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +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') + permission_required = 'projector.can_manage_projector' + default_column = 1 + default_weight = 20 + template_name = 'agenda/widget_item.html' + 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' + + def check_permission(self): + return (self.request.user.has_perm('agenda.can_manage_agenda') or + self.request.user.has_perm('agenda.can_be_speaker')) diff --git a/openslides/assignment/__init__.py b/openslides/assignment/__init__.py index 9c5992b37..635921a8c 100644 --- a/openslides/assignment/__init__.py +++ b/openslides/assignment/__init__.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- -from . import signals, slides # noqa +from . import signals, slides, widgets # noqa diff --git a/openslides/assignment/templates/assignment/widget.html b/openslides/assignment/templates/assignment/widget.html deleted file mode 100644 index f685de8a4..000000000 --- a/openslides/assignment/templates/assignment/widget.html +++ /dev/null @@ -1,26 +0,0 @@ -{% load i18n %} -{% load tags %} - - - -

{% trans "More..." %}

diff --git a/openslides/assignment/templates/assignment/widget_assignment.html b/openslides/assignment/templates/assignment/widget_assignment.html new file mode 100644 index 000000000..06635f046 --- /dev/null +++ b/openslides/assignment/templates/assignment/widget_assignment.html @@ -0,0 +1,28 @@ +{% extends 'core/widget.html' %} + +{% load i18n %} +{% load tags %} + +{% block content %} + +{% endblock %} diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py index 9fd602094..f9fb3d1c7 100644 --- a/openslides/assignment/views.py +++ b/openslides/assignment/views.py @@ -17,7 +17,6 @@ from openslides.agenda.views import CreateRelatedAgendaItemView as _CreateRelate from openslides.config.api import config from openslides.participant.models import Group, User from openslides.poll.views import PollFormView -from openslides.projector.projector import Widget from openslides.utils.pdf import stylesheet from openslides.utils.person import get_person from openslides.utils.template import Tab @@ -622,15 +621,3 @@ def register_tab(request): request.user.has_perm('assignment.can_manage_assignment')), selected=selected, ) - - -def get_widgets(request): - return [Widget( - request, - name='assignments', - display_name=_('Elections'), - template='assignment/widget.html', - context={'assignments': Assignment.objects.all()}, - permission_required='projector.can_manage_projector', - default_column=1, - default_weight=50)] diff --git a/openslides/assignment/widgets.py b/openslides/assignment/widgets.py new file mode 100644 index 000000000..2f61d5c22 --- /dev/null +++ b/openslides/assignment/widgets.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +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') + permission_required = 'projector.can_manage_projector' + default_column = 1 + default_weight = 50 + template_name = 'assignment/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/core/__init__.py b/openslides/core/__init__.py index 15c1b3efe..a5101f887 100644 --- a/openslides/core/__init__.py +++ b/openslides/core/__init__.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- -from . import signals # noqa +from . import signals, widgets # noqa diff --git a/openslides/core/static/styles/core.css b/openslides/core/static/styles/core.css new file mode 100644 index 000000000..f1e4a8fde --- /dev/null +++ b/openslides/core/static/styles/core.css @@ -0,0 +1,3 @@ +.icon-welcome { + background-position: 0 -24px; +} diff --git a/openslides/core/templates/core/widget.html b/openslides/core/templates/core/widget.html new file mode 100644 index 000000000..f44f32239 --- /dev/null +++ b/openslides/core/templates/core/widget.html @@ -0,0 +1,40 @@ +{% load i18n %} + +
+
+ {% block header %} +

+ +
+ +
+
+ +
+ {{ widget.get_verbose_name }} +

+ {% endblock %} +
+
+ {% block content-wrapper %} +
+ {% block content %} + {% endblock %} +
+
+ {% block footer %} + {% if widget.get_url_for_more %} + +

{% trans 'More ...' %}

+
+ {% endif %} + {% endblock %} +
+ {% endblock %} +
+
diff --git a/openslides/core/templates/core/widget_welcome.html b/openslides/core/templates/core/widget_welcome.html new file mode 100644 index 000000000..07b366ebb --- /dev/null +++ b/openslides/core/templates/core/widget_welcome.html @@ -0,0 +1,12 @@ +{% 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/widgets.py b/openslides/core/widgets.py new file mode 100644 index 000000000..c06ae17cc --- /dev/null +++ b/openslides/core/widgets.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- + +from openslides.config.api import config + +from openslides.utils.widgets import Widget + + +class WelcomeWidget(Widget): + """ + Welcome widget with static info for all users. + """ + name = 'welcome' + permission_required = 'projector.can_see_dashboard' + default_column = 1 + default_weight = 10 + template_name = 'core/widget_welcome.html' + stylesheets = ['styles/core.css'] + + def get_verbose_name(self): + return config['welcome_title'] diff --git a/openslides/mediafile/__init__.py b/openslides/mediafile/__init__.py index e4e03eff4..acd07f9be 100644 --- a/openslides/mediafile/__init__.py +++ b/openslides/mediafile/__init__.py @@ -1,4 +1,4 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from . import slides # noqa +from . import slides, widgets # noqa diff --git a/openslides/mediafile/templates/mediafile/pdfs_widget.html b/openslides/mediafile/templates/mediafile/widget_pdfpresentation.html similarity index 85% rename from openslides/mediafile/templates/mediafile/pdfs_widget.html rename to openslides/mediafile/templates/mediafile/widget_pdfpresentation.html index fbfc3a36c..b368f4eef 100644 --- a/openslides/mediafile/templates/mediafile/pdfs_widget.html +++ b/openslides/mediafile/templates/mediafile/widget_pdfpresentation.html @@ -1,6 +1,9 @@ +{% extends 'core/widget.html' %} + {% load i18n %} {% load tags %} +{% block content %}
- -
{% trans "Page" %}: -
-
- - -

{% trans "More..." %}

- +{% endblock %} diff --git a/openslides/mediafile/views.py b/openslides/mediafile/views.py index 2ffbb2f28..5667a091b 100644 --- a/openslides/mediafile/views.py +++ b/openslides/mediafile/views.py @@ -6,7 +6,6 @@ from django.utils.translation import ugettext as _ from openslides.config.api import config from openslides.projector.api import get_active_slide -from openslides.projector.projector import Widget from openslides.utils.template import Tab from openslides.utils.tornado_webserver import ProjectorSocketHandler from openslides.utils.views import (AjaxView, CreateView, DeleteView, RedirectView, ListView, @@ -190,32 +189,6 @@ class PdfToggleFullscreenView(RedirectView): return {'fullscreen': config['pdf_fullscreen']} -def get_widgets(request): - """ - Return the widgets of the projector app - """ - widgets = [] - - # PDF-Presentation widget - pdfs = Mediafile.objects.filter( - filetype__in=Mediafile.PRESENTABLE_FILE_TYPES, - is_presentable=True - ) - current_page = get_active_slide().get('page_num', 1) - widgets.append(Widget( - request, - name='presentations', - display_name=_('Presentations'), - template='mediafile/pdfs_widget.html', - context={'pdfs': pdfs, 'current_page': current_page, - 'pdf_fullscreen': config['pdf_fullscreen']}, - permission_required='projector.can_manage_projector', - default_column=1, - default_weight=75)) - - return widgets - - def register_tab(request): """ Inserts a new Tab to the views for files. diff --git a/openslides/mediafile/widgets.py b/openslides/mediafile/widgets.py new file mode 100644 index 000000000..533a88a8b --- /dev/null +++ b/openslides/mediafile/widgets.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- + +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') + permission_required = 'projector.can_manage_projector' + default_column = 1 + default_weight = 75 + template_name = 'mediafile/widget_pdfpresentation.html' + more_link_pattern_name = 'mediafile_list' + #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/motion/__init__.py b/openslides/motion/__init__.py index 9c5992b37..635921a8c 100644 --- a/openslides/motion/__init__.py +++ b/openslides/motion/__init__.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- -from . import signals, slides # noqa +from . import signals, slides, widgets # noqa diff --git a/openslides/motion/templates/motion/widget.html b/openslides/motion/templates/motion/widget.html deleted file mode 100644 index e968994a2..000000000 --- a/openslides/motion/templates/motion/widget.html +++ /dev/null @@ -1,29 +0,0 @@ -{% load i18n %} -{% load tags %} - - - -

{% trans "More..." %}

diff --git a/openslides/motion/templates/motion/widget_motion.html b/openslides/motion/templates/motion/widget_motion.html new file mode 100644 index 000000000..e7ee8ef35 --- /dev/null +++ b/openslides/motion/templates/motion/widget_motion.html @@ -0,0 +1,31 @@ +{% extends 'core/widget.html' %} + +{% load i18n %} +{% load tags %} + +{% block content %} + +{% endblock %} diff --git a/openslides/motion/views.py b/openslides/motion/views.py index 5bc0221ed..133831755 100644 --- a/openslides/motion/views.py +++ b/openslides/motion/views.py @@ -12,7 +12,6 @@ from openslides.agenda.views import CreateRelatedAgendaItemView as _CreateRelate from openslides.config.api import config from openslides.poll.views import PollFormView from openslides.projector.api import get_active_slide, update_projector -from openslides.projector.projector import Widget from openslides.utils.template import Tab from openslides.utils.utils import html_strong, htmldiff from openslides.utils.views import (CreateView, DeleteView, DetailView, @@ -824,20 +823,3 @@ def register_tab(request): url=reverse('motion_list'), permission=request.user.has_perm('motion.can_see_motion'), selected=request.path.startswith('/motion/')) - - -def get_widgets(request): - """ - Return the motion widgets for the dashboard. - - There is only one widget. It shows all motions. - """ - return [Widget( - request, - name='motions', - display_name=_('Motions'), - template='motion/widget.html', - context={'motions': Motion.objects.all()}, - permission_required='projector.can_manage_projector', - default_column=1, - default_weight=40)] diff --git a/openslides/motion/widgets.py b/openslides/motion/widgets.py new file mode 100644 index 000000000..dbe118e84 --- /dev/null +++ b/openslides/motion/widgets.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +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') + permission_required = 'projector.can_manage_projector' + default_column = 1 + default_weight = 40 + template_name = 'motion/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/participant/__init__.py b/openslides/participant/__init__.py index 9c5992b37..635921a8c 100644 --- a/openslides/participant/__init__.py +++ b/openslides/participant/__init__.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- -from . import signals, slides # noqa +from . import signals, slides, widgets # noqa diff --git a/openslides/participant/templates/participant/group_widget.html b/openslides/participant/templates/participant/widget_group.html similarity index 90% rename from openslides/participant/templates/participant/group_widget.html rename to openslides/participant/templates/participant/widget_group.html index 32f1c3c16..f5202e60d 100644 --- a/openslides/participant/templates/participant/group_widget.html +++ b/openslides/participant/templates/participant/widget_group.html @@ -1,6 +1,9 @@ +{% extends 'core/widget.html' %} + {% load i18n %} {% load tags %} +{% block content %} - -

{% trans "More..." %}

+{% endblock %} diff --git a/openslides/participant/templates/participant/user_widget.html b/openslides/participant/templates/participant/widget_user.html similarity index 91% rename from openslides/participant/templates/participant/user_widget.html rename to openslides/participant/templates/participant/widget_user.html index c0b081e22..cc4a4d03c 100644 --- a/openslides/participant/templates/participant/user_widget.html +++ b/openslides/participant/templates/participant/widget_user.html @@ -1,5 +1,9 @@ +{% extends 'core/widget.html' %} + {% load i18n %} {% load tags %} + +{% block content %} - -

{% trans "More..." %}

+{% endblock %} diff --git a/openslides/participant/urls.py b/openslides/participant/urls.py index 48afdd480..8d5bbbbd5 100644 --- a/openslides/participant/urls.py +++ b/openslides/participant/urls.py @@ -9,7 +9,7 @@ urlpatterns = patterns( # User url(r'^$', views.UserOverview.as_view(), - name='user_overview'), + name='user_overview'), # TODO: Rename this to user_list url(r'^new/$', views.UserCreateView.as_view(), @@ -53,7 +53,7 @@ urlpatterns = patterns( # Group url(r'^group/$', views.GroupOverview.as_view(), - name='user_group_overview'), + name='user_group_overview'), # TODO: Rename this to group_list url(r'^group/new/$', views.GroupCreateView.as_view(), diff --git a/openslides/participant/views.py b/openslides/participant/views.py index e33966b7c..185fdc61b 100644 --- a/openslides/participant/views.py +++ b/openslides/participant/views.py @@ -10,7 +10,6 @@ from django.utils.translation import ugettext as _ from django.utils.translation import activate, ugettext_lazy from openslides.config.api import config -from openslides.projector.projector import Widget from openslides.utils.template import Tab from openslides.utils.utils import (delete_default_permissions, html_strong, template) @@ -445,43 +444,3 @@ def register_tab(request): request.user.has_perm('participant.can_see_participant') or request.user.has_perm('participant.can_manage_participant')), selected=selected) - - -def get_widgets(request): - """ - Returns all widgets of the participant app. This is a user_widget - and a group_widget. - """ - return [get_user_widget(request), get_group_widget(request)] - - -def get_user_widget(request): - """ - Provides a widget with all users. This is for short activation of - user slides. - """ - return Widget( - request, - name='user', - display_name=_('Participants'), - template='participant/user_widget.html', - context={'users': User.objects.all()}, - permission_required='projector.can_manage_projector', - default_column=1, - default_weight=60) - - -def get_group_widget(request): - """ - Provides a widget with all groups. This is for short activation of - group slides. - """ - return Widget( - request, - name='group', - display_name=_('Groups'), - template='participant/group_widget.html', - context={'groups': Group.objects.all()}, - permission_required='projector.can_manage_projector', - default_column=1, - default_weight=70) diff --git a/openslides/participant/widgets.py b/openslides/participant/widgets.py new file mode 100644 index 000000000..b95157b14 --- /dev/null +++ b/openslides/participant/widgets.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- + +from django.utils.translation import ugettext_lazy + +from openslides.utils.widgets import Widget + +from .models import Group, User + + +class UserWidget(Widget): + """ + Provides a widget with all users. This is for short activation of + user slides. + """ + name = 'user' + verbose_name = ugettext_lazy('Participants') + permission_required = 'projector.can_manage_projector' + default_column = 1 + default_weight = 60 + template_name = 'participant/widget_user.html' + more_link_pattern_name = 'user_overview' + + def get_context_data(self, **context): + return super(UserWidget, self).get_context_data( + users=User.objects.all(), + **context) + + +class GroupWidget(Widget): + """ + Provides a widget with all groups. This is for short activation of + group slides. + """ + name = 'group' + verbose_name = ugettext_lazy('Groups') + permission_required = 'projector.can_manage_projector' + default_column = 1 + default_weight = 70 + template_name = 'participant/widget_group.html' + more_link_pattern_name = 'user_group_overview' + + def get_context_data(self, **context): + return super(GroupWidget, self).get_context_data( + groups=Group.objects.all(), + **context) diff --git a/openslides/projector/__init__.py b/openslides/projector/__init__.py index 9c5992b37..635921a8c 100644 --- a/openslides/projector/__init__.py +++ b/openslides/projector/__init__.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- -from . import signals, slides # noqa +from . import signals, slides, widgets # noqa diff --git a/openslides/projector/api.py b/openslides/projector/api.py index f1b52ddbc..844f185a2 100644 --- a/openslides/projector/api.py +++ b/openslides/projector/api.py @@ -3,10 +3,7 @@ from json import dumps from time import time -from django.conf import settings from django.template.loader import render_to_string -from django.utils.datastructures import SortedDict -from django.utils.importlib import import_module from openslides.config.api import config from openslides.utils.tornado_webserver import ProjectorSocketHandler @@ -224,39 +221,6 @@ def get_active_object(): return value -def get_all_widgets(request, session=False): - """ - Collects the widgets from all apps and returns the Widget objects as sorted - dictionary. - - The session flag decides whether to return only the widgets which are - active, that means that they are mentioned in the session. - """ - all_module_widgets = [] - # TODO: Do not touch the filesystem on any request - for app in settings.INSTALLED_APPS: - try: - mod = import_module(app + '.views') - except ImportError: - continue - try: - mod_get_widgets = mod.get_widgets - except AttributeError: - continue - else: - module_widgets = mod_get_widgets(request) - all_module_widgets.extend(module_widgets) - all_module_widgets.sort(key=lambda widget: widget.default_weight) - session_widgets = request.session.get('widgets', {}) - widgets = SortedDict() - for widget in all_module_widgets: - if (widget.permission_required is None or - request.user.has_perm(widget.permission_required)): - if not session or session_widgets.get(widget.get_name(), True): - widgets[widget.get_name()] = widget - return widgets - - def start_countdown(): """ Starts the countdown diff --git a/openslides/projector/projector.py b/openslides/projector/projector.py index 9c66fb652..b1a73a8a1 100644 --- a/openslides/projector/projector.py +++ b/openslides/projector/projector.py @@ -1,62 +1,8 @@ # -*- coding: utf-8 -*- from django.conf import settings -from django.template import RequestContext -from django.template.loader import render_to_string from openslides.config.api import config -from openslides.utils.exceptions import OpenSlidesError - - -class Widget(object): - """ - Class for a Widget for the Projector-Tab. - """ - def __init__(self, request, name, html=None, template=None, context=None, - permission_required=None, display_name=None, default_column=1, - default_weight=0): - self.name = name - if display_name is None: - self.display_name = name.capitalize() - else: - self.display_name = display_name - - if html is not None: - self.html = html - elif template is not None: - self.html = render_to_string( - template_name=template, - dictionary=context or {}, - context_instance=RequestContext(request)) - else: - raise OpenSlidesError('A Widget must have either a html or a template argument.') - self.permission_required = permission_required - self.default_column = default_column - self.default_weight = default_weight - - def get_name(self): - """ - Returns the lower case of the widget name. - """ - return self.name.lower() - - def get_html(self): - """ - Returns the html code of the widget. - """ - return self.html - - def get_title(self): - """ - Returns the title of the widget. - """ - return self.display_name - - def __repr__(self): - return repr(self.display_name) - - def __unicode__(self): - return unicode(self.display_name) class Overlay(object): diff --git a/openslides/projector/templates/projector/dashboard.html b/openslides/projector/templates/projector/dashboard.html index d2a41d157..db7832696 100644 --- a/openslides/projector/templates/projector/dashboard.html +++ b/openslides/projector/templates/projector/dashboard.html @@ -6,6 +6,7 @@ {% block header %} {% endblock %} + {% block javascript %} @@ -13,71 +14,31 @@ {% endblock %} -{% block title %}{% trans "Dashboard" %} – {{ block.super }}{% endblock %} +{% block title %}{% trans 'Dashboard' %} – {{ block.super }}{% endblock %} {% block content %}

{% trans 'Dashboard' %} - {% trans 'Widgets' %} + + + {% trans 'Widgets' %} +

-
- {% for name, widget in widgets.items %} - {% if widget.default_column == 1 %} -
-
-

- -
- -
-
- -
- {% trans widget.get_title %} -

-
-
-
{{ widget.html }}
-
-
- {% endif %} - {% endfor %} -
- -
- {% for name, widget in widgets.items %} - {% if widget.default_column == 2 %} -
-
-

- -
- -
-
- -
- {% trans widget.get_title %} -

-
-
-
{{ widget.html }}
-
-
- {% endif %} - {% endfor %} -
+
+ {% 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/projector/templates/projector/select_widgets.html b/openslides/projector/templates/projector/select_widgets.html index 470d72093..b9ed3e9b4 100644 --- a/openslides/projector/templates/projector/select_widgets.html +++ b/openslides/projector/templates/projector/select_widgets.html @@ -13,7 +13,7 @@
{% csrf_token %}