Dashboard Widgets¶
Dashboard in Cantemo gives user a quick overview of their tasks, system status etc. Each user can customize their dashboard by adding dashboard widgets and configuring them. These widgets are implemented as plugins using the IDashboardWidget-interface.
When the dashboard loads, it loads the contents of each widget using AJAX. Widgets can request a refresh with JavaScript, which in practice mean that the dashboard code will reload the widget contents with a new AJAX request.
IDashboardWidget¶
- class portal.generic.dashboard_interfaces.IDashboardWidget¶
An IDashboardWidget-plugin defines one type of widget that can be added one or more times in the dashboard, with separate settings for each instance.
- Requires:
__init__ -method that defines:
name
for the plugin,configurable
, andtemplate_name
get_list_title() -static method
get_render_data() -static method
force_show_config() -static method, required only if
self.configurable
isTrue
get_config_form() -static method, required only if
self.configurable
isTrue
See below for detailed specifications of the methods.
- __init__()¶
- Must initialize:
self.name - Unique plugin name
self.configurable - Whether this widget can be configured (if True,
get_config_form()
andforce_show_config()
must be implemented)self.template_name - Template for rendering this widget, can use default
IDashboardWidget.default_template
- default_template = 'dashboard/base_widget.html'¶
Default template for widget rendering
- static force_show_config(settings, request)¶
Return True if the widget configuration form should be shown, even if normal rendering was requested. This method is not used if self.configurable is False.
See TextWidgetForcedConfig in example widgets for example usage.
- Args:
settings - widget instance settings data from database
request - the current request
- static get_config_form(settings, request)¶
Returns the configuration form of the widget. This method is not used if self.configurable is False.
Note that Django classes must be imported within this method, not during package initialisation (top of the Python file).
Example implementation value that shows a form with two fields, title and text:
@staticmethod def get_config_form(settings, request): from django import forms class TextWidgetSettingsForm(forms.Form): title = forms.CharField(label='Widget title', max_length=100, initial="Title") text = forms.CharField(label='Widget text', max_length=10000, widget=forms.Textarea(attrs={'rows': 5})) return TextWidgetSettingsForm
- Supported form field types:
django.forms.IntegerField
django.forms.CharField
django.forms.BooleanField
django.forms.ChoiceField
django.forms.EmailField
django.forms.FloatField
django.forms.NullBooleanField
django.forms.URLField
- Args:
settings - widget instance settings data from database
request - the current request
- static get_list_title()¶
Returns UI text for selecting this widget type.
- static get_render_data(render_data, settings, request)¶
Returns a dictionary that is passed to the template to render this widget. This method is allowed to take a long time, the UI will show appropriate loading spinners.
For example:
Change
render_data['title']
to set widget title based on settings or current request.When using default template, set
render_data['content']
to set text of the widget.
- Args:
- render_data is a dict with following default values
id – widget instance id
title – get_list_title()
settings - widget instance settings data from database
request - the current request
- Returns:
A dictionary with template data
An example dashboard widget plugin that shows a text:
from portal.pluginbase.core import Plugin, implements
from portal.generic.dashboard_interfaces import IDashboardWidget
class HelloWidget(Plugin):
implements(IDashboardWidget)
def __init__(self):
self.name = 'HelloWidget'
self.plugin_guid = '2BFADB52-56B8-47B3-BA63-1383CD42F678'
self.template_name = IDashboardWidget.default_template
self.configurable = False
# Note: Since configurable is False, this class does not need to implement
# force_show_config() and get_config_form()
@staticmethod
def get_list_title():
return "Hello widget"
@staticmethod
def get_render_data(render_data, settings, request):
render_data['content'] = "Hello world!"
return render_data
HelloWidget()
Dashboard Widget Templates and JavaScript¶
If a dashboard widget only wants to show textual content, it can just define render_data['content']
as in
the example above. Custom widget layouts can be defined in templates, which must extent the template
"dashboard/base_widget.html"
and define their content in {% block widget_content %}
.
Widgets can include JavaScript code in their templates directly inside a <script>
-tag.
To request a refresh, a widget should call the cntmo.app.dashboard.reloadWidgetAfter()-function in JavaScript:
cntmo.app.dashboard.reloadWidgetAfter('{{ id }}', <time_in_milliseconds>);
There can be multiple instances of a single widget class visible at the same time. If animation or similar is user
in JavaScript, all ids should use the widget instance id, available through {{ id }}
.
Below is an example of a widget template that includes an animated <div> and refreshes at the given interval. Below
python code references this from portal/plugins/corewidgets/templates/corewidgets/refresh_widget.html
:
{% themeextends "dashboard/base_widget.html" %}
{% block widget_content %}
{{ content }}
<!-- Using an id here based on widgets id -- otherwise multiple
refresh_widgets will mess with each other -->
<div id="timer-bar{{ id }}"
style="background-color: #00b7ea; height: 1px; width: 100%"> </div>
<!-- script below is loaded with the HTML and executed normally -->
<script>
// Ask to reload widget in given time, converted to milliseconds.
cntmo.app.dashboard.reloadWidgetAfter('{{ id }}',
{{ refresh_interval }}000);
// Animate timer bar using jQuery UI. Called after a small timeout,
// so that when adding this widget
// for the first time the layout has finished before animation starts.
setTimeout(function() {
$("#timer-bar{{ id }}").hide("slide",
{direction: "left", easing: "linear"},
{{ refresh_interval }}000);
}, 100);
</script>
{% endblock widget_content %}
Below is the related Python code that should be put in a plugins.py-file:
from django.utils.translation import gettext as _
from portal.pluginbase.core import Plugin, implements
from portal.generic.dashboard_interfaces import IDashboardWidget
class RefreshWidget(Plugin):
"""
Example of a widget that automatically refreshes every 10 seconds.
Uses custom template which does JS reload using
cntmo.app.dashboard.reloadWidgetAfter(id, time_ms)-function.
"""
implements(IDashboardWidget)
default_interval = 10
def __init__(self):
self.name = 'RefreshWidget'
self.plugin_guid = '3622B952-E9C0-4429-BD00-65B6958322BF'
self.template_name = 'corewidgets/refresh_widget.html'
self.configurable = True
@staticmethod
def get_list_title():
return _("Refresh widget")
@staticmethod
def get_render_data(render_data, settings, request):
from datetime import datetime
render_data['content'] = _("Time on server: {}").format(
datetime.now().isoformat(' '))
# Make sure refresh_interval is passed to template (use default
# if user has not edited settings yet)
if 'refresh_interval' in settings:
render_data['refresh_interval'] = settings['refresh_interval']
else:
render_data['refresh_interval'] = RefreshWidget.default_interval
return render_data
@staticmethod
def get_config_form(settings, request):
# Django classes MUST be imported inside method, not when package
# is initialized
from django import forms
class RefreshWidgetSettingsForm(forms.Form):
refresh_interval = forms.IntegerField(
label=_('Refresh interval (seconds):'),
initial=RefreshWidget.default_interval, min_value=1)
return RefreshWidgetSettingsForm
@staticmethod
def force_show_config(settings, request):
return False
# Register widget plugin
RefreshWidget()
See the example dashboard widget plugins for more information and implementation examples.