diff --git a/CHANGELOG b/CHANGELOG
index ceff56008..d5524d69a 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -9,7 +9,7 @@ Version 1.6 (unreleased)
[https://github.com/OpenSlides/OpenSlides/issues?milestone=14]
Participants:
-- Disable widgets by default.
+- Disabled widgets by default.
Files:
- Enabled update and delete view for uploader refering to his own files.
Other:
@@ -18,6 +18,9 @@ Other:
- Renamed config api classes.
- Renamed some classes of the poll api.
- Inserted api for the personal info widget.
+- Changed api for main menu entries.
+- Enhanced http error pages.
+- Moved dashboard and select widgets view from projector to core app.
Version 1.5.1 (unreleased)
diff --git a/openslides/agenda/__init__.py b/openslides/agenda/__init__.py
index fbfccf222..f8db99882 100644
--- a/openslides/agenda/__init__.py
+++ b/openslides/agenda/__init__.py
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
-from . import personal_info, signals, slides, widgets # noqa
+from . import main_menu, personal_info, signals, slides, widgets # noqa
diff --git a/openslides/agenda/main_menu.py b/openslides/agenda/main_menu.py
new file mode 100644
index 000000000..4a4324d7b
--- /dev/null
+++ b/openslides/agenda/main_menu.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+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')
+ permission_required = 'agenda.can_see_agenda'
+ default_weight = 20
+ pattern_name = 'item_overview'
+ icon_css_class = 'icon-calendar'
diff --git a/openslides/agenda/views.py b/openslides/agenda/views.py
index b5410de6d..4e7557e7d 100644
--- a/openslides/agenda/views.py
+++ b/openslides/agenda/views.py
@@ -15,7 +15,6 @@ from openslides.config.api import config
from openslides.projector.api import get_active_slide, update_projector
from openslides.utils.exceptions import OpenSlidesError
from openslides.utils.pdf import stylesheet
-from openslides.utils.template import Tab
from openslides.utils.utils import html_strong
from openslides.utils.views import (CreateView, DeleteView, FormView, PDFView,
RedirectView, SingleObjectMixin,
@@ -569,7 +568,7 @@ class CurrentListOfSpeakersView(RedirectView):
messages.error(request, _(
'There is no list of speakers for the current slide. '
'Please choose the agenda item manually from the agenda.'))
- return reverse('dashboard')
+ return reverse('core_dashboard')
if self.set_speaker:
if item.speaker_list_closed:
@@ -613,25 +612,11 @@ class CurrentListOfSpeakersView(RedirectView):
if item.type == Item.ORGANIZATIONAL_ITEM:
if reverse_to_dashboard or not self.request.user.has_perm('agenda.can_see_orga_items'):
- return reverse('dashboard')
+ return reverse('core_dashboard')
else:
return reverse('item_view', args=[item.pk])
else:
if reverse_to_dashboard or not self.request.user.has_perm('agenda.can_see_agenda'):
- return reverse('dashboard')
+ return reverse('core_dashboard')
else:
return reverse('item_view', args=[item.pk])
-
-
-def register_tab(request):
- """
- Registers the agenda tab.
- """
- selected = request.path.startswith('/agenda/')
- return Tab(
- title=_('Agenda'),
- app='agenda',
- url=reverse('item_overview'),
- permission=(request.user.has_perm('agenda.can_see_agenda') or
- request.user.has_perm('agenda.can_manage_agenda')),
- selected=selected)
diff --git a/openslides/assignment/__init__.py b/openslides/assignment/__init__.py
index fbfccf222..8b1da0397 100644
--- a/openslides/assignment/__init__.py
+++ b/openslides/assignment/__init__.py
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
-from . import personal_info, signals, slides, widgets # noqa
+from . import main_menu, personal_info, signals, slides, template, widgets # noqa
diff --git a/openslides/assignment/main_menu.py b/openslides/assignment/main_menu.py
new file mode 100644
index 000000000..6313ab88e
--- /dev/null
+++ b/openslides/assignment/main_menu.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+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')
+ permission_required = 'assignment.can_see_assignment'
+ default_weight = 40
+ pattern_name = 'assignment_list'
+ icon_css_class = 'icon-charts'
diff --git a/openslides/assignment/static/img/glyphicons_041_charts.png b/openslides/assignment/static/img/glyphicons_041_charts.png
new file mode 100644
index 000000000..556b7cce5
Binary files /dev/null and b/openslides/assignment/static/img/glyphicons_041_charts.png differ
diff --git a/openslides/assignment/static/img/glyphicons_041_charts_white.png b/openslides/assignment/static/img/glyphicons_041_charts_white.png
new file mode 100644
index 000000000..83cd93b8c
Binary files /dev/null and b/openslides/assignment/static/img/glyphicons_041_charts_white.png differ
diff --git a/openslides/assignment/static/styles/assignment.css b/openslides/assignment/static/styles/assignment.css
index 5bd992410..67363c94f 100644
--- a/openslides/assignment/static/styles/assignment.css
+++ b/openslides/assignment/static/styles/assignment.css
@@ -1,3 +1,11 @@
+.icon-charts {
+ background-image: url("../img/glyphicons_041_charts.png");
+ background-position: 0px center;
+}
+.leftmenu ul li.active a span.ico i.icon-charts {
+ background-image: url("../img/glyphicons_041_charts_white.png");
+}
+
td.elected {
background-color: #BED4DE !important;
}
diff --git a/openslides/assignment/template.py b/openslides/assignment/template.py
new file mode 100644
index 000000000..5e7aa25f1
--- /dev/null
+++ b/openslides/assignment/template.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+
+from django.dispatch import receiver
+
+from openslides.utils.signals import template_manipulation
+
+
+@receiver(template_manipulation, dispatch_uid="add_assignment_stylesheets")
+def add_assignment_stylesheets(sender, request, context, **kwargs):
+ """
+ Adds the assignment.css to the context.
+ """
+ context['extra_stylefiles'].append('styles/assignment.css')
diff --git a/openslides/assignment/views.py b/openslides/assignment/views.py
index f9fb3d1c7..941f6f65f 100644
--- a/openslides/assignment/views.py
+++ b/openslides/assignment/views.py
@@ -19,7 +19,6 @@ from openslides.participant.models import Group, User
from openslides.poll.views import PollFormView
from openslides.utils.pdf import stylesheet
from openslides.utils.person import get_person
-from openslides.utils.template import Tab
from openslides.utils.utils import html_strong
from openslides.utils.views import (CreateView, DeleteView, DetailView,
ListView, PDFView, PermissionMixin,
@@ -606,18 +605,3 @@ class AssignmentPollPDF(PDFView):
('GRID', (0, 0), (-1, -1), 0.25, colors.grey),
('VALIGN', (0, 0), (-1, -1), 'TOP')]))
story.append(t)
-
-
-def register_tab(request):
- selected = request.path.startswith('/assignment/')
- return Tab(
- title=_('Elections'),
- app='assignment',
- url=reverse('assignment_list'),
- permission=(
- request.user.has_perm('assignment.can_see_assignment') or
- request.user.has_perm('assignment.can_nominate_other') or
- request.user.has_perm('assignment.can_nominate_self') or
- request.user.has_perm('assignment.can_manage_assignment')),
- selected=selected,
- )
diff --git a/openslides/config/__init__.py b/openslides/config/__init__.py
index e69de29bb..d42c22903 100644
--- a/openslides/config/__init__.py
+++ b/openslides/config/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+
+from . import main_menu # noqa
diff --git a/openslides/config/main_menu.py b/openslides/config/main_menu.py
new file mode 100644
index 000000000..b9249652d
--- /dev/null
+++ b/openslides/config/main_menu.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+
+from django.utils.translation import ugettext_lazy
+
+from openslides.utils.main_menu import MainMenuEntry
+
+from .signals import config_signal
+
+
+class ConfigMainMenuEntry(MainMenuEntry):
+ """
+ Main menu entry for the config app.
+ """
+ verbose_name = ugettext_lazy('Configuration')
+ default_weight = 70
+ pattern_name = 'config_first_config_collection_view'
+ icon_css_class = 'icon-cog'
+
+ def check_permission(self):
+ """
+ Checks against all permissions of all config collections.
+ """
+ for receiver, config_collection in config_signal.send(sender=self):
+ if config_collection.is_shown():
+ if self.request.user.has_perm(config_collection.required_permission):
+ return_value = True
+ break
+ else:
+ return_value = False
+ return return_value
diff --git a/openslides/config/views.py b/openslides/config/views.py
index 49e7e2d1e..9680eb375 100644
--- a/openslides/config/views.py
+++ b/openslides/config/views.py
@@ -5,7 +5,6 @@ from django.contrib import messages
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
-from openslides.utils.template import Tab
from openslides.utils.views import FormView
from .api import config
@@ -109,15 +108,3 @@ class ConfigView(FormView):
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)
-
-
-def register_tab(request):
- """
- Registers the entry for this app in the main menu.
- """
- return Tab(
- title=_('Configuration'),
- app='config',
- url=reverse('config_first_config_collection_view'),
- permission=request.user.has_perm('config.can_manage'),
- selected=request.path.startswith('/config/'))
diff --git a/openslides/core/__init__.py b/openslides/core/__init__.py
index a5101f887..0c6390484 100644
--- a/openslides/core/__init__.py
+++ b/openslides/core/__init__.py
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
-from . import signals, widgets # noqa
+from . import main_menu, signals, widgets # noqa
diff --git a/openslides/projector/forms.py b/openslides/core/forms.py
similarity index 100%
rename from openslides/projector/forms.py
rename to openslides/core/forms.py
diff --git a/openslides/core/main_menu.py b/openslides/core/main_menu.py
new file mode 100644
index 000000000..e44425e51
--- /dev/null
+++ b/openslides/core/main_menu.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+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')
+ permission_required = 'projector.can_see_dashboard'
+ default_weight = 10
+ icon_css_class = 'icon-home'
+ pattern_name = 'core_dashboard'
diff --git a/openslides/projector/static/img/glyphicons_335_pushpin.png b/openslides/core/static/img/glyphicons_335_pushpin.png
similarity index 100%
rename from openslides/projector/static/img/glyphicons_335_pushpin.png
rename to openslides/core/static/img/glyphicons_335_pushpin.png
diff --git a/openslides/projector/static/javascript/dashboard.js b/openslides/core/static/javascript/dashboard.js
similarity index 100%
rename from openslides/projector/static/javascript/dashboard.js
rename to openslides/core/static/javascript/dashboard.js
diff --git a/openslides/projector/static/javascript/jquery.form.js b/openslides/core/static/javascript/jquery.form.js
similarity index 100%
rename from openslides/projector/static/javascript/jquery.form.js
rename to openslides/core/static/javascript/jquery.form.js
diff --git a/openslides/core/static/styles/core.css b/openslides/core/static/styles/core.css
deleted file mode 100644
index f1e4a8fde..000000000
--- a/openslides/core/static/styles/core.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.icon-welcome {
- background-position: 0 -24px;
-}
diff --git a/openslides/projector/static/styles/dashboard.css b/openslides/core/static/styles/dashboard.css
similarity index 100%
rename from openslides/projector/static/styles/dashboard.css
rename to openslides/core/static/styles/dashboard.css
diff --git a/openslides/projector/templates/projector/dashboard.html b/openslides/core/templates/core/dashboard.html
similarity index 89%
rename from openslides/projector/templates/projector/dashboard.html
rename to openslides/core/templates/core/dashboard.html
index db7832696..2df494226 100644
--- a/openslides/projector/templates/projector/dashboard.html
+++ b/openslides/core/templates/core/dashboard.html
@@ -1,4 +1,4 @@
-{% extends "base.html" %}
+{% extends 'base.html' %}
{% load i18n %}
{% load staticfiles %}
@@ -19,7 +19,7 @@
{% block content %}
{% trans 'Dashboard' %}
-
+
{% trans 'Widgets' %}
diff --git a/openslides/core/templates/core/error.html b/openslides/core/templates/core/error.html
new file mode 100644
index 000000000..ebf045dd5
--- /dev/null
+++ b/openslides/core/templates/core/error.html
@@ -0,0 +1,8 @@
+{% 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/projector/templates/projector/select_widgets.html b/openslides/core/templates/core/select_widgets.html
similarity index 83%
rename from openslides/projector/templates/projector/select_widgets.html
rename to openslides/core/templates/core/select_widgets.html
index b9ed3e9b4..fc9c2f838 100644
--- a/openslides/projector/templates/projector/select_widgets.html
+++ b/openslides/core/templates/core/select_widgets.html
@@ -1,4 +1,4 @@
-{% extends "base.html" %}
+{% extends 'base.html' %}
{% load i18n %}
@@ -7,7 +7,7 @@
{% block content %}
diff --git a/openslides/core/urls.py b/openslides/core/urls.py
index dc157fe90..b859ddeba 100644
--- a/openslides/core/urls.py
+++ b/openslides/core/urls.py
@@ -10,14 +10,21 @@ urlpatterns = patterns(
'',
# Redirect to dashboard URL
url(r'^$',
- RedirectView.as_view(url='projector/dashboard/'),
+ 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='search',),
-)
+ name='core_search',))
diff --git a/openslides/core/views.py b/openslides/core/views.py
index 7d28d4584..219d6c85a 100644
--- a/openslides/core/views.py
+++ b/openslides/core/views.py
@@ -1,8 +1,13 @@
# -*- coding: utf-8 -*-
from django.conf import settings
+from django.contrib import messages
from django.core.exceptions import PermissionDenied
+from django.core.urlresolvers import reverse
+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 get_version as get_openslides_version
@@ -10,7 +15,73 @@ from openslides import get_git_commit_id, RELEASE
from openslides.config.api import config
from openslides.utils.plugins import get_plugin_description, get_plugin_verbose_name, get_plugin_version
from openslides.utils.signals import template_manipulation
-from openslides.utils.views import TemplateView
+from openslides.utils.views import AjaxMixin, TemplateView, View
+from openslides.utils.widgets import Widget
+
+from .forms import SelectWidgetsForm
+
+
+class DashboardView(AjaxMixin, 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.
+ """
+ permission_required = 'projector.can_see_dashboard' # TODO: Rename this to core.can_see_dashboard
+ template_name = 'core/dashboard.html'
+
+ def get_context_data(self, **kwargs):
+ context = super(DashboardView, self).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(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
+ permission_required = 'projector.can_see_dashboard' # TODO: Rename this to core.can_see_dashboard
+ template_name = 'core/select_widgets.html'
+
+ def get_context_data(self, **kwargs):
+ context = super(SelectWidgetsView, self).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(TemplateView):
@@ -82,3 +153,30 @@ class SearchView(_SearchView):
else:
models.append([module.Index.modelfilter_name, module.Index.modelfilter_value])
return models
+
+
+class ErrorView(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
diff --git a/openslides/core/widgets.py b/openslides/core/widgets.py
index c06ae17cc..acd0b2ff4 100644
--- a/openslides/core/widgets.py
+++ b/openslides/core/widgets.py
@@ -14,7 +14,7 @@ class WelcomeWidget(Widget):
default_column = 1
default_weight = 10
template_name = 'core/widget_welcome.html'
- stylesheets = ['styles/core.css']
+ icon_css_class = 'icon-home'
def get_verbose_name(self):
return config['welcome_title']
diff --git a/openslides/global_settings.py b/openslides/global_settings.py
index a12030fb5..8028aff5c 100644
--- a/openslides/global_settings.py
+++ b/openslides/global_settings.py
@@ -117,6 +117,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.i18n',
'django.core.context_processors.static',
'openslides.utils.auth.anonymous_context_additions',
+ 'openslides.utils.main_menu.main_menu_entries',
)
CACHES = {
diff --git a/openslides/mediafile/__init__.py b/openslides/mediafile/__init__.py
index acd07f9be..0a79488ec 100644
--- a/openslides/mediafile/__init__.py
+++ b/openslides/mediafile/__init__.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from . import slides, widgets # noqa
+from . import main_menu, slides, template, widgets # noqa
diff --git a/openslides/mediafile/main_menu.py b/openslides/mediafile/main_menu.py
new file mode 100644
index 000000000..157a3fa36
--- /dev/null
+++ b/openslides/mediafile/main_menu.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+
+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 = 'mediafile_list'
+ icon_css_class = 'icon-paperclip'
+
+ def check_permission(self):
+ return (
+ self.request.user.has_perm('mediafile.can_see') or
+ self.request.user.has_perm('mediafile.can_upload') or
+ self.request.user.has_perm('mediafile.can_manage'))
diff --git a/openslides/mediafile/static/img/glyphicons_062_paperclip.png b/openslides/mediafile/static/img/glyphicons_062_paperclip.png
new file mode 100644
index 000000000..fed88de96
Binary files /dev/null and b/openslides/mediafile/static/img/glyphicons_062_paperclip.png differ
diff --git a/openslides/mediafile/static/img/glyphicons_062_paperclip_white.png b/openslides/mediafile/static/img/glyphicons_062_paperclip_white.png
new file mode 100644
index 000000000..cceb92174
Binary files /dev/null and b/openslides/mediafile/static/img/glyphicons_062_paperclip_white.png differ
diff --git a/openslides/mediafile/static/styles/mediafile.css b/openslides/mediafile/static/styles/mediafile.css
index dde6abd0e..e984e5cd4 100644
--- a/openslides/mediafile/static/styles/mediafile.css
+++ b/openslides/mediafile/static/styles/mediafile.css
@@ -1,8 +1,8 @@
/** Navigation icons (mapping to glyphicons-halflings) **/
-.icon-mediafile {
+.icon-paperclip {
background-image: url("../img/glyphicons_062_paperclip.png");
background-position: 0;
}
-.leftmenu ul li.active a span.ico i.icon-mediafile {
+.leftmenu ul li.active a span.ico i.icon-paperclip {
background-image: url("../img/glyphicons_062_paperclip_white.png");
}
diff --git a/openslides/mediafile/template.py b/openslides/mediafile/template.py
new file mode 100644
index 000000000..ce49ed11a
--- /dev/null
+++ b/openslides/mediafile/template.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+
+from django.dispatch import receiver
+
+from openslides.utils.signals import template_manipulation
+
+
+@receiver(template_manipulation, dispatch_uid="add_mediafile_stylesheets")
+def add_mediafile_stylesheets(sender, request, context, **kwargs):
+ """
+ Adds the mediafile.css to the context.
+ """
+ context['extra_stylefiles'].append('styles/mediafile.css')
diff --git a/openslides/mediafile/views.py b/openslides/mediafile/views.py
index 0d67f3671..cee2c91f6 100644
--- a/openslides/mediafile/views.py
+++ b/openslides/mediafile/views.py
@@ -1,12 +1,9 @@
# -*- coding: utf-8 -*-
-from django.core.urlresolvers import reverse
from django.http import HttpResponse
-from django.utils.translation import ugettext as _
from openslides.config.api import config
from openslides.projector.api import get_active_slide
-from openslides.utils.template import Tab
from openslides.utils.tornado_webserver import ProjectorSocketHandler
from openslides.utils.views import (AjaxView, CreateView, DeleteView, RedirectView, ListView,
UpdateView)
@@ -199,7 +196,7 @@ class PdfToggleFullscreenView(RedirectView):
Toggle fullscreen mode for pdf presentations.
"""
allow_ajax = True
- url_name = 'dashboard'
+ url_name = 'core_dashboard'
def get_ajax_context(self, *args, **kwargs):
config['pdf_fullscreen'] = not config['pdf_fullscreen']
@@ -208,19 +205,3 @@ class PdfToggleFullscreenView(RedirectView):
ProjectorSocketHandler.send_updates(
{'calls': {'toggle_fullscreen': config['pdf_fullscreen']}})
return {'fullscreen': config['pdf_fullscreen']}
-
-
-def register_tab(request):
- """
- Inserts a new Tab to the views for files.
- """
- selected = request.path.startswith('/mediafile/')
- return Tab(
- title=_('Files'),
- app='mediafile', # TODO: Rename this to icon='mediafile' later
- stylefile='styles/mediafile.css',
- url=reverse('mediafile_list'),
- permission=(request.user.has_perm('mediafile.can_see') or
- request.user.has_perm('mediafile.can_upload') or
- request.user.has_perm('mediafile.can_manage')),
- selected=selected)
diff --git a/openslides/motion/__init__.py b/openslides/motion/__init__.py
index fbfccf222..f8db99882 100644
--- a/openslides/motion/__init__.py
+++ b/openslides/motion/__init__.py
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
-from . import personal_info, signals, slides, widgets # noqa
+from . import main_menu, personal_info, signals, slides, widgets # noqa
diff --git a/openslides/motion/main_menu.py b/openslides/motion/main_menu.py
new file mode 100644
index 000000000..05bbd9c4b
--- /dev/null
+++ b/openslides/motion/main_menu.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+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')
+ permission_required = 'motion.can_see_motion'
+ default_weight = 30
+ pattern_name = 'motion_list'
+ icon_css_class = 'icon-file'
diff --git a/openslides/motion/views.py b/openslides/motion/views.py
index 133831755..dc1fb7d9d 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.utils.template import Tab
from openslides.utils.utils import html_strong, htmldiff
from openslides.utils.views import (CreateView, DeleteView, DetailView,
FormView, ListView, PDFView, QuestionView,
@@ -810,16 +809,3 @@ class MotionCSVImportView(FormView):
return super(MotionCSVImportView, self).form_valid(form)
motion_csv_import = MotionCSVImportView.as_view()
-
-
-def register_tab(request):
- """
- Return the motion tab.
- """
- # TODO: Find a better way to set the selected var.
- return Tab(
- title=_('Motions'),
- app='motion',
- url=reverse('motion_list'),
- permission=request.user.has_perm('motion.can_see_motion'),
- selected=request.path.startswith('/motion/'))
diff --git a/openslides/participant/__init__.py b/openslides/participant/__init__.py
index 635921a8c..c57e8c26e 100644
--- a/openslides/participant/__init__.py
+++ b/openslides/participant/__init__.py
@@ -1,3 +1,3 @@
# -*- coding: utf-8 -*-
-from . import signals, slides, widgets # noqa
+from . import main_menu, signals, slides, widgets # noqa
diff --git a/openslides/participant/main_menu.py b/openslides/participant/main_menu.py
new file mode 100644
index 000000000..443588563
--- /dev/null
+++ b/openslides/participant/main_menu.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+
+from django.utils.translation import ugettext_lazy
+
+from openslides.utils.main_menu import MainMenuEntry
+
+
+class ParticipantMainMenuEntry(MainMenuEntry):
+ """
+ Main menu entry for the participant app.
+ """
+ verbose_name = ugettext_lazy('Participants')
+ permission_required = 'participant.can_see_participant'
+ default_weight = 50
+ pattern_name = 'user_overview'
+ icon_css_class = 'icon-user'
diff --git a/openslides/participant/templates/participant/login.html b/openslides/participant/templates/participant/login.html
index 84da3ab8f..5e6260cb6 100644
--- a/openslides/participant/templates/participant/login.html
+++ b/openslides/participant/templates/participant/login.html
@@ -43,7 +43,7 @@
{% trans 'Login' %}
{% if os_enable_anonymous_login %}
-
+
{% trans 'Continue as guest' %}
{% endif %}
diff --git a/openslides/participant/views.py b/openslides/participant/views.py
index 185fdc61b..accfbb909 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.utils.template import Tab
from openslides.utils.utils import (delete_default_permissions, html_strong,
template)
from openslides.utils.views import (CreateView, DeleteView, DetailView,
@@ -420,7 +419,7 @@ def user_settings_password(request):
if form.is_valid():
form.save()
messages.success(request, _('Password successfully changed.'))
- return redirect(reverse('dashboard'))
+ return redirect(reverse('core_dashboard'))
else:
messages.error(request, _('Please check the form for errors.'))
else:
@@ -429,18 +428,3 @@ def user_settings_password(request):
return {
'form': form,
}
-
-
-def register_tab(request):
- """
- Registers the participant tab.
- """
- selected = request.path.startswith('/participant/')
- return Tab(
- title=_('Participants'),
- app='participant',
- url=reverse('user_overview'),
- permission=(
- request.user.has_perm('participant.can_see_participant') or
- request.user.has_perm('participant.can_manage_participant')),
- selected=selected)
diff --git a/openslides/projector/models.py b/openslides/projector/models.py
index fdfe9f11c..ce58a5098 100644
--- a/openslides/projector/models.py
+++ b/openslides/projector/models.py
@@ -110,7 +110,8 @@ class ProjectorSlide(SlideMixin, models.Model):
"""
Model for Slides, only for the projector. Also called custom slides.
"""
- # TODO: Rename it to CustomSlide
+ # TODO: Rename it to CustomSlide and move it to core app.
+ # Check and rename permissions.
slide_callback_name = 'projector_slide'
title = models.CharField(max_length=256, verbose_name=ugettext_lazy("Title"))
diff --git a/openslides/projector/templates/projector/new.html b/openslides/projector/templates/projector/new.html
index d1e3d77e8..6d6c088a4 100644
--- a/openslides/projector/templates/projector/new.html
+++ b/openslides/projector/templates/projector/new.html
@@ -7,7 +7,7 @@
{% block content %}