Have you seen our new video tutorials? Check it out!

Dashboard Module

A powerful widget based multi-dashboard display.

Introduction

anomaly.module.dashboard

The Dashboard module provide a powerful widget based multiple dashboard system.

Features

The Dashboard module comes with everything you need to manage and display multiple dashboards.

  • Multiple Dashboards
  • Portable Dashboard API
  • Extension-based Widgets

Installation

You can install the Dashboard module with the addon:install command:

php artisan addon:install anomaly.module.dashboard
Notice: The Dashboard module comes installed with PyroCMS out of the box.

Usage

This section will show you how to use the addon via API and in the view layer.

Widgets

Dashboard widgets are Stream entries that are associated with an extension. The extensions along with configuration using the Configuration module.

Widget Fields

Below is a list of fields in the widgets stream. Fields are accessed as attributes:

$widget->title;

Same goes for decorated instances in Twig:

{{ widget.title }}
Fields
Key Type Description

title

text

The title.

description

textarea

The description.

extension

addon

The widget extension.

column

integer

The column placement.

pinned

boolean

The pinned state.

dashboard

relationship

The related dashboard.

allowed_roles

multiple

The roles allowed to view the widget.

Widget Interface

This section will go over the \Anomaly\DashboardModule\Widget\Contract\WidgetInterface class.

WidgetInterface::output()

The output method returns the complete widget output.

Returns: string
Example
$widget->output();
Twig
{{ widget.output()|raw }}
WidgetInterface::addData()

The addData method adds data to the widget's data for access later in processing and output.

Returns: \Anomaly\Streams\Platform\Entry\Contract\EntryInterface
Arguments
Key Required Type Default Description

$key

true

string

none

The data key.

$data

true

mixed

none

The data.

Example
$widget->addData('example', 'http://pyrocms.com');
WidgetInterface::getData()

The getData method returns the widget's data collection.

Returns: \Anomaly\DashboardModule\Widget\WidgetData
Example
$widget->getData()->get('example');
Twig
{{ widget.getData().get('example') }}
WidgetInterface::setContent()

The setContent method sets the interior content for the widget wrapper view.

Returns: \Anomaly\DashboardModule\Widget\Contract\WidgetInterface
Arguments
Key Required Type Default Description

$content

true

string

none

The rendered content.

Example
$widget->setContent($html);
WidgetInterface::getContent()

The getContent method gets the interior content for the widget wrapper view.

Returns: string
Example
$widget->getContent();
Twig
{{ widget.getContent()|raw }}

Dashboards

Dashboards are stream entries that have multiple widgets associated with it.

Dashboard Fields

Below is a list of fields in the dashboards stream. Fields are accessed as attributes:

$dashboard->name;

Same goes for decorated instances in Twig:

{{ dashboard.name }}
Fields
Key Type Description

name

text

The dashboard name.

slug

slug

The dashboard slug.

description

textarea

The dashboard description.

name

text

The dashboard name.

layout

select

The dashboard column layout.

allowed_roles

multiple

The roles allowed to view the dashboard.

Dashboard Interface

This section will go over the \Anomaly\DashboardModule\Dashboard\Contract\DashboardInterface class.

DashboardInterface::getWidgets()

The getWidgets method returns the related widgets.

Returns: \Anomaly\DashboardModule\Widget\WidgetCollection
Example
foreach ($dashboard->getWidgets() as $widget) {
    echo $widget->title . '<br>';
}
Twig
{% for widget in dashboard.getWidgets() %}
    {{ widget.title }}
{% endfor %}
DashboardInterface::widgets()

The widgets method returns the widget relation.

Returns: \Illuminate\Database\Eloquent\Relations\HasMany
Example
$widgets = $dashboard->widgets()->where('extension', 'anomaly.extension.xml_feed_widget')->get();
Twig
{% set widgets = dashboard.widgets().where('extension', 'anomaly.extension.xml_feed_widget').get() %}

Extensions

This section will go over the addon extensions and how they work.

Widgets

Widget extensions control dashboard widget configuration, data, and output.

Widget Extension

This section will go over the \Anomaly\DashboardModule\Widget\Extension\WidgetExtension class.

WidgetExtension::$view

The view property defines the widget's content view.

protected $view = 'anomaly.extension.xml_feed_widget::view';

The default value is null and will default to looking for resources/views/content.twig.

WidgetExtension::$wrapper

The wrapper property defines the outer wrapper view for the widget output. The default value is the wrapper included in the Dashboard module:

protected $wrapper = 'anomaly.module.dashboard::admin/widgets/widget';
WidgetExtension::load()

The load method is responsible for loading the data into the widget for display later.

Returns: void
Arguments
Key Required Type Default Description

$widget

true

WidgetInterface

none

The widget entry instance.

WidgetExtension::content()

The content method is responsible for setting the content on the widget. This method normally won't need overriding in your own extensions.

Returns: void
Arguments
Key Required Type Default Description

$widget

true

WidgetInterface

none

The widget entry instance.

WidgetExtension::output()

The output method returns the rendered widget output including the wrapper. This method runs the load and content methods before returning the rendered output. You can override this method to inject additional processing before output.

Returns: string
Arguments
Key Required Type Default Description

$widget

true

WidgetInterface

none

The widget entry instance.

Writing Widgets

This section will show you how to write your own custom dashboard widget.

Creating the extension

The first thing we need to do is to use the make:addon command to create our extension:

php artisan make:addon anomaly.extension.xml_feed_extension
Extending the widget extension

The extension you create must extend the \Anomaly\DashboardModule\Widget\Extension\WidgetExtension class:

<?php namespace Anomaly\XmlFeedWidgetExtension;

use Anomaly\DashboardModule\Widget\Contract\WidgetInterface;
use Anomaly\DashboardModule\Widget\Extension\WidgetExtension;
use Anomaly\XmlFeedWidgetExtension\Command\LoadItems;

class XmlFeedWidgetExtension extends WidgetExtension
{

    /**
     * This extension provides the "Recent News"
     * widget for the main dashboard.
     *
     * @var string
     */
    protected $provides = 'anomaly.module.dashboard::widget.xml_feed';

    /**
     * Load the widget data.
     *
     * @param WidgetInterface $widget
     */
    protected function load(WidgetInterface $widget)
    {
        $this->dispatch(new LoadItems($widget));
    }
}

You must define the provides property as anomaly.module.dashboard::widget.your_widget_slug so that it's picked up as a supported extension.

Defining extension configuration

Most every widget and even extension will likely need configuration to differentiate it from other same instances. In this example we want to allow users to define a custom XML feed URL if desired. Create a resources/config/configuration.php file to define your fields for the Configuration module:

<?php

return [
    'url' => [
        'type'   => 'anomaly.field_type.url',
        'config' => [
            'default_value' => 'http://www.pyrocms.com/posts/rss.xml',
        ],
    ],
];
Load widget data

The primary task of any widget is loading data into the widget in order to display it later. In this example we will use a command thats dispatched within the load method:

protected function load(WidgetInterface $widget)
{
    $this->dispatch(new LoadItems($widget));
}

Our LoadItems command is responsible for loading the data:

<?php namespace Anomaly\XmlFeedWidgetExtension\Command;

use Anomaly\ConfigurationModule\Configuration\Contract\ConfigurationRepositoryInterface;
use Anomaly\DashboardModule\Widget\Contract\WidgetInterface;
use Illuminate\Contracts\Cache\Repository;

class LoadItems
{

    /**
     * The widget instance.
     *
     * @var WidgetInterface
     */
    protected $widget;

    /**
     * Create a new LoadItems instance.
     *
     * @param WidgetInterface $widget
     */
    public function __construct(WidgetInterface $widget)
    {
        $this->widget = $widget;
    }

    /**
     * Handle the widget data.
     *
     * @param \SimplePie                       $rss
     * @param Repository                       $cache
     * @param ConfigurationRepositoryInterface $configuration
     */
    public function handle(\SimplePie $rss, Repository $cache, ConfigurationRepositoryInterface $configuration)
    {
        $items = $cache->remember(
            __METHOD__ . '_' . $this->widget->getId(),
            30,
            function () use ($rss, $configuration) {

                $rss->enable_cache(false);

                $rss->set_feed_url(
                    $configuration->value(
                        'anomaly.extension.xml_feed_widget::url',
                        $this->widget->getId(),
                        'http://www.pyrocms.com/posts/rss.xml'
                    )
                );

                // Make the request.
                $rss->init();

                return $rss->get_items(0, 5);
            }
        );

        $this->widget->addData('items', $items);
    }
}
Note: Learn more about using the [Configuration module](/documentation/configuration-module).
Define the content view

The content view will display your widget content using the data loaded prior. By default the content view is defined as resources/views/content.twig within your extension:

{% for item in widget.data.items %}

    <div class="media">

        <div class="media-left">
            <i class="fa fa-calendar fa-lg text-faded"></i>
        </div>

        <div class="media-body">

            <h3 class="media-heading">
                <a href="{{ item.get_permalink() }}" target="_blank">
                    {{ item.get_title() }}
                </a>

                <br>

                <small class="text-muted">
                    {{ item.get_date()|date('F j, Y') }}
                </small>
            </h3>

            {{ item.get_description()|striptags }}

        </div>

    </div>

    {% if not loop.last %}
        <hr>
    {% endif %}

{% endfor %}