OpenSlides/openslides/utils/widgets.py

134 lines
4.2 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
from django.core.urlresolvers import reverse
from django.dispatch import Signal
from django.template import RequestContext
from django.template.loader import render_to_string
from .dispatch import SignalConnectMetaClass
class Widget(object):
"""
Base class for a widget for the dashboard.
Every app which wants to add widgets to the dashboard has to create a
widget class subclassing from this base class. The name attribute has to
be set. The __metaclass__ attribute (SignalConnectMetaClass) does the
rest of the magic.
For the appearance of the widget there are some optional attributes like
verbose_name, permission_required, default_column, default_weight,
default_active, template_name, context, icon_css_class,
more_link_pattern_name, stylesheets and javascript_files.
"""
__metaclass__ = SignalConnectMetaClass
signal = Signal(providing_args=['request'])
name = None
verbose_name = None
permission_required = None
default_column = 1
default_weight = 0
default_active = True
template_name = None
context = None
icon_css_class = None
more_link_pattern_name = None
stylesheets = None
javascript_files = None
def __init__(self, sender, request, **kwargs):
"""
Initializes the widget instance. This is done when the signal is sent.
Only the required request argument is used. Because of Django's signal
API, we have to take also a sender argument and wildcard keyword
arguments. But they are not used here.
"""
self.request = request
def __repr__(self):
return repr(self.get_verbose_name())
def __unicode__(self):
return unicode(self.get_verbose_name())
@classmethod
def get_dispatch_uid(cls):
"""
Returns the name as a unique string for each class. Returns None for
the base class so it will not be connected to the signal.
"""
return cls.name
def get_verbose_name(self):
"""
Returns a human readable name of the widget.
"""
return self.verbose_name or self.name.capitalize()
def check_permission(self):
"""
Returns True if the request user is allowed to see the widget.
"""
return self.permission_required is None or self.request.user.has_perm(self.permission_required)
def is_active(self):
"""
Returns True if the widget is active to be displayed.
"""
session_widgets = self.request.session.get('widgets', {})
return session_widgets.get(self.name, self.default_active)
def get_html(self):
"""
Returns the html code of the widget.
This method also adds the widget itself to the context.
"""
if self.template_name is not None:
html = render_to_string(
template_name=self.template_name,
dictionary=self.get_context_data(widget=self),
context_instance=RequestContext(self.request))
else:
raise NotImplementedError('A widget class must define either a get_html '
'method or have template_name argument.')
return html
def get_context_data(self, **context):
"""
Returns the context data for the widget template.
"""
return_context = self.context or {}
return_context.update(context)
return return_context
def get_icon_css_class(self):
"""
Returns the css class name of the icon.
"""
return self.icon_css_class or 'icon-%s' % self.name
def get_url_for_more(self):
"""
Returns the url for the link 'More ...' in the base template.
"""
if self.more_link_pattern_name is not None:
url = reverse(self.more_link_pattern_name)
else:
url = None
return url
def get_stylesheets(self):
"""
Returns an interable of stylesheets to be loaded.
"""
return iter(self.stylesheets or [])
def get_javascript_files(self):
"""
Returns an interable of javascript files to be loaded.
"""
return iter(self.javascript_files or [])