Laravel Community Tools by Tighten
Laravel Nova icon Nova Packages

Readme

Nova Dashboard

Latest Version on Packagist Total Downloads License

Laravel Nova Dashboard In Action

The missing dashboard for Laravel Nova!

Installation

You can install the package via composer:

composer require mlsolutions/nova-dashboard

List of current available widgets:

Usage

The dashboard itself is simply a standard Laravel Nova card, so you can use it either as a card on any resource or within the default Nova dashboard functionality.

use App\Models\User;
use MlSolutions\NovaDashboard\Card\NovaDashboard;
use MlSolutions\NovaDashboard\Card\View;
use MlSolutions\NovaDashboard\Filters;
use Laravel\Nova\Dashboards\Main as Dashboard;

class Main extends Dashboard
{
    public function cards(): array
    {
        return [
            NovaDashboard::make()
                ->addView('Website Performance', function (View $view) {
                    return $view
                        ->icon('window')
                        ->addWidgets([
                            BounceRate::make(),
                            ConversionRate::make(),
                            WebsiteTraffic::make(),
                            SessionDuration::make(),
                        ])
                        ->addFilters([
                            LocationFilter::make(),
                            UserTypeFilter::make(),
                            DateRangeFilter::make(),
                        ])
                        ->download(
                            resolver: function ($request, View $view, string $format, Filters $filters) {
                                return $filters
                                    ->applyToQueryBuilder(User::query())
                                    ->select('name', 'email', 'created_at');
                            },
                            label: 'Download Report',
                            filename: 'website-performance',
                            formats: ['csv', 'excel'],
                        );
                }),
        ];
    }
}

Static

By default, each widget is draggable, and the user is able to rearrange it to their liking. This behavior can be disabled by calling $view->static().

Widgets

The widgets are responsible for displaying your data on your views; they are essentially standard Nova cards. However, they respond to dashboard events and reload their data whenever the filters change.

Once you have a widget, they are usually configured like this:

class MyCustomWidget extends ValueWidget
{
    /**
     * Here you can configure your widget by calling whatever options are available for each widget
     */
    public function configure(NovaRequest $request): void
    {
        $this->icon('<svg>...</svg>');
        $this->title('Session Duration');
        $this->textColor('#f95738');
        $this->backgroundColor('#f957384f');
    }

    /**
     * This function is responsible for returning the actual data that will be shown on the widget,
     * each widget expects its own format, so please refer to the widget documentation 
     */
    public function value(Filters $filters): mixed
    {
        /**
         * $filters contain all the set values from the filters that were shown on the frontend. 
         * You can retrieve them and implement any custom logic you may have.
         */
        $filterValue = $filters->getFilterValue(LikesFilter::class);
        
        return 'example';
    }
}

All widgets have common methods to configure their size and position. The value is not in pixels but in grid units, ranging from 1 to 12 (corresponding to 12 columns).

$widget->layout(width: 2, height: 1, x: 0, y: 1);
$widget->minWidth(2);
$widget->minHeight(1);

Filters

Filters Preview

These are standard nova filter classes with 1 simple difference, the method ->apply() does not get called by default. Why?

use Illuminate\Http\Request;
use Laravel\Nova\Filters\BooleanFilter;

class ExampleFilter extends BooleanFilter
{
    public function apply(Request $request, $query, $value)
    {
        // this function is required however it is not used by the nova-dashboard
    }
}

Usually your widget ->value() function will receive an instance of MlSolutions\NovaDashboard\Filters this class contains a method for retrieving the value of any given filter, for example:

class SessionDuration extends ValueWidget
{
    public function value(Filters $filters): mixed
    {
        $filterA = $filters->getFilterValue(YourFilterClass::class);
        $filterB = $filters->getFilterValue(YourSecondFilterClass::class);
    }
}

However, if you want to reuse the logic that you have previously set on your filters or share existing filters with the dashboard you can call the method ->applyToQueryBuilder() to get the same behavior:

class SessionDuration extends ValueWidget
{
    public function value(Filters $filters): mixed
    {
        $result = $filters->applyToQueryBuilder(User::query())->get();    
    }
}

->applyToQueryBuilder() will run every filter through the default filter logic of nova.

Downloads

Views can expose a report download button that always uses the filters currently applied in the dashboard.

use App\Models\User;
use MlSolutions\NovaDashboard\Card\View;
use MlSolutions\NovaDashboard\Downloads\DownloadResult;
use MlSolutions\NovaDashboard\Filters;
use Laravel\Nova\Http\Requests\NovaRequest;

$view->download(
    resolver: function (Filters $filters, NovaRequest $request, View $view, string $format) {
        return $filters
            ->applyToQueryBuilder(User::query())
            ->select('name', 'email', 'created_at');
    },
    label: 'Download Users',
    filename: 'users-report',
    formats: ['csv', 'excel'],
);

The resolver receives the current dashboard filter state, not a prebuilt query result.

Available callback arguments:

  • NovaRequest $request: the active Nova request.
  • View $view: the current dashboard view.
  • string $format: either csv or excel.
  • Filters $filters: the same filter object used by widgets.
  • array $filterValues: all current filters serialized as class, name, and value.

This matches how dashboards are commonly built in real projects such as socialnexa-nova: widgets read filter values and then assemble the query or service call that produces the final dataset.

Accepted resolver return types:

  • Eloquent\Builder or Query\Builder: the package runs the query and exports the current result set.
  • Collection, array or any iterable list of rows: columns are inferred automatically.
  • DownloadResult: use it when you want full control over columns, row order or the exported filename.
  • An array with rows, optional columns, and optional filename.

Example with custom column order:

$view->download(
    resolver: function (Filters $filters, NovaRequest $request, View $view, string $format) {
        $rows = $filters
            ->applyToQueryBuilder(User::query())
            ->get()
            ->map(fn (User $user) => [
                'Name' => $user->name,
                'Email' => $user->email,
                'Joined At' => $user->created_at?->toDateString(),
            ]);

        return DownloadResult::make(
            columns: ['Name', 'Email', 'Joined At'],
            rows: $rows,
            filename: 'filtered-users',
        );
    },
);

Example using the raw serialized filter values:

$view->download(
    resolver: function (array $filterValues) {
        $dateRange = data_get($filterValues, App\Nova\Filters\CreateAtDateFilter::class . '.value');

        // Build your own query/service call from the active filter values.
        return [];
    },
);

excel exports a native Excel-compatible .xls file, while csv exports UTF-8 CSV with BOM for spreadsheet compatibility.

⭐️ Show Your Support

Please give a ⭐️ if this project helped you!

Other Packages You Might Like

License

The MIT License (MIT). Please see License File for more information.

Back to Top
Added 11 months ago
Last updated 20 Hours Ago
Version v1.1.1
Nova Version ^4.28.0|^5.0
Composer
mlsolutions/nova-dashboard
GitHub stars 1
Packagist downloads 5,809

Favorites

0 users favorited

Rating

N/A
(out of 5)
★★★★★
★★★★
★★★
★★
0 ratings

Brought to you by Tighten

Issues/Feature Requests Stats Package Ideas