# Imports
from django.utils.safestring import mark_safe
from superdjango.exceptions import IMustBeMissingSomething
from superdjango.ui.runtime.panels import Panel
from superdjango.shortcuts import parse_template
import warnings
from ..constants import LOCATION, SIZE, VERB
# Exports
__all__ = (
"BasePanel",
"BigNumberPanel",
"ImagePanel",
"TabularPanel",
)
# TODO: Embed panel for embedding audio, video, etc.
# See quicksite for embed implementation.
# See https://oembed.com/
# See https://github.com/wagtail/wagtail/tree/master/wagtail/embeds
# See https://github.com/abarmat/python-oembed
# TODO: Look at how a form panel might be provided, e.g. for quick data entry.
# TODO: Implement a search panel.
# Classes
[docs]class BasePanel(object):
"""Base class for panel implementations."""
heading = None
icon = None
location = LOCATION.DEFAULT
size = SIZE.MEDIUM
template = None
verb = VERB.DASHBOARD
[docs] def __init__(self):
"""Initialize the panel. Simply sets the ``request`` and ``ui`` to ``None`` for later use."""
self.request = None
self.ui = None
[docs] def as_runtime(self, request, ui):
"""Load the panel for use in output.
:param request: The current HTTP request instance.
:param ui: The current model UI instance.
:type ui: ModelUI
:rtype: Panel
.. note::
This method sets the ``request`` and ``ui`` attributes for use in other methods.
"""
self.request = request
self.ui = ui
return Panel(self.get_content(), **self.get_kwargs())
[docs] def get_content(self):
"""Get the content (output) of the panel.
:rtype: str
.. note::
Content is marked safe.
"""
return mark_safe(parse_template(self.get_template(), self.get_context()))
[docs] def get_context(self):
"""Get the context to be used for rendering the panel template.
:rtype: dict
.. note::
By default, this simply returns ``get_kwargs()``, but child classes may override to include additional
context variables.
"""
return self.get_kwargs()
[docs] def get_kwargs(self):
"""Get the keyword arguments to be passed to the the Panel instance.
:rtype: dict
"""
return {
'heading': self.heading,
'icon': self.icon,
'location': self.location,
'size': self.size,
'url': self.get_url(),
}
[docs] def get_template(self):
"""Get the template to use for rendering the panel.
:rtype: str
:raise: IMustBeMissingSomething
"""
if self.template is None:
raise IMustBeMissingSomething(self.__class__.__name__, "template", "get_template")
return self.template
# noinspection PyMethodMayBeStatic
[docs] def get_url(self):
"""Get the URL for linking to related pages or content.
:rtype: str | None
"""
return None
[docs] def load(self, request, ui):
"""Load the panel for use in output.
:param request: The current HTTP request instance.
:param ui: The current model UI instance.
:type ui: ModelUI
:rtype: Panel
.. note::
This method sets the ``request`` and ``ui`` attributes for use in other methods.
"""
message = "BasePanel.load() has been moved to BasePanel.as_runtime() and will be removed in the next " \
"minor version."
warnings.warn(message, PendingDeprecationWarning)
self.request = request
self.ui = ui
return Panel(self.get_content(), **self.get_kwargs())
[docs]class BigNumberPanel(BasePanel):
"""A panel that prominently displays a numeric value."""
size = SIZE.SMALL
style = "primary"
template = "superdjango/ui/includes/model_dashboard_panel_big_number.html"
[docs] def get_context(self):
"""Add ``number`` and ``style`` to the context."""
context = super().get_context()
context['number'] = self.get_number()
context['style'] = self.style
return context
[docs] def get_number(self):
"""Get the number to be displayed.
:rtype: decimal | float | int
.. note::
Child classes must implement this method.
"""
raise NotImplementedError()
[docs]class ImagePanel(BasePanel):
"""A panel that displays an image."""
size = SIZE.P100
style = ""
[docs] def get_context(self):
"""Add ``image`` and ``style`` to the context."""
context = super().get_context()
context['image'] = self.get_image()
context['style'] = self.style
return context
[docs] def get_image(self):
"""Get the URL of the image to be displayed.
:rtype: str
"""
raise NotImplementedError()
[docs]class TabularPanel(BasePanel):
"""A panel for displaying limited tabular data."""
size = SIZE.LARGE
template = "superdjango/ui/includes/model_dashboard_panel_tabular.html"
[docs] def get_context(self):
"""Add ``table`` to the context."""
context = super().get_context()
context['table'] = self.get_table()
return context
[docs] def get_table(self):
"""Get the table instance to be displayed.
.. note::
Child classes must implement. The table instance is expected to have a ``columns`` attribute that contains
a column instance with a ``label`` attribute, and a ``rows`` attribute that includes a ``data`` list
attribute that contains the data to be displayed.
"""
raise NotImplementedError()