Dashboard

The admin dashboard (/textstem) is a grid of widgets. Each person chooses which widgets they see and drags them into their own order; the choice is saved per user in storage/app/preferences/{user id}/dashboard.json. Someone who has never chosen sees every widget.

To add something to the dashboard, such as latest sales or event visits, write a widget. There is no dashboard view to edit.

Who can see it

The dashboard checks the view-dashboard ability. The package defines no gate or permission of that name, so only super-admins pass until you create a view-dashboard permission and give it to your admin roles (Spatie registers each permission as a gate ability). See Authorisation.

Built-in widgets

The package ships these widgets, all in Medialight\Textstem\Livewire\DashboardWidgets: Welcome, Site Overview, Site Health, Site Config Summary, Recently Updated Content, Expiring Content, Content Suggestions, Accessibility Report, Recent Errors, Admin Tasks, Waiting For Review (content approval) and New Form Answers (Form Data only). A package widget whose class has a static isAvailable() returning false is left out.

Creating a widget

php artisan textstem:make:dashboardwidget TopPageViews

This creates app/Livewire/DashboardWidgets/TopPageViews.php and resources/views/livewire/dashboard-widgets/toppageviews/default.blade.php (the folder name is lower-cased). Widgets in app/Livewire/DashboardWidgets/ are found automatically and appear in the dashboard's widget picker; no registration is needed.

A widget is a Livewire component that extends Medialight\Textstem\Livewire\DashboardWidget:

<?php

namespace App\Livewire\DashboardWidgets;

use Medialight\Textstem\Livewire\DashboardWidget;
use Spatie\Analytics\Facades\Analytics;
use Spatie\Analytics\Period;

class TopPageViews extends DashboardWidget
{
    public $span = 2;   // columns, out of 4
    public $rows = 2;   // rows

    public function render()
    {
        $period = 7;

        return view('livewire.dashboard-widgets.toppageviews.default', [
            'period' => $period,
            'data' => Analytics::fetchMostVisitedPages(Period::days($period), 20),
        ]);
    }
}

DashboardWidget gives every widget these properties, which its view passes to <x-widget>:

Property Default Meaning
$span 4 Width in grid columns
$rows 1 Height in grid rows
$rowHeight 72 Row height (or short / tall on <x-widget>)
$fixHeight true Keep the card at its grid height
$title, $description empty Text for the card
$refreshIntervalInSeconds null Re-render on a timer (wire:poll)

The picker labels each widget with its size, for example Top Page Views [2x2].

The widget view

Wrap the content in <x-widget>, which draws the card, the title and an optional footer:

<x-widget :refreshIntervalInSeconds="300" :span="$span" :rowspan="$rows"
          :fixHeight="$fixHeight" :rowHeight="$rowHeight"
          title="Top Pages (past {{ $period }} days)">
    <table class="datatable text-xs">
        <tbody>
        @foreach($data as $item)
            <tr>
                <td>
                    <a href="https://{{ $item['fullPageUrl'] ?? '#' }}" target="_blank">{{ $item['pageTitle'] ?: '--' }}</a>
                </td>
                <td>{{ $item['screenPageViews'] ?? '--' }}</td>
            </tr>
        @endforeach
        </tbody>
    </table>
    <x-slot:footer>
        <a href="https://analytics.google.com" class="link text-sm">Open Analytics</a>
    </x-slot:footer>
</x-widget>

<x-widget> is also available as <x-ts::widget>.

Sharing widgets

textstem:export-widget packs a widget into a ZIP that another site can install at /textstem/tools/install-widget. See Artisan Commands.

esc