Skip to content
Advertisement

Is there a way to dynamically switch default dashboards in Nova

What I am looking for:

A way to potentially load a appNovaDashboardsDashboardExample as the default dashboard.

Problem

Nova comes with a default dashboard which is build in the NovaServiceProvider and gives you the possibility to add additional dashboards using the dashboards() function.

When using this dashboards() function, you initialize additional dashboards instead of loading in a different dashboard as the default dashboard which is not what I am looking for.

The default dashboard is the standard location you end up after signing in, however not every user should see the same dashboard which is why I am looking for a way to change the default dashboard depending on your ‘roles’.

Current “solution“:

Currently I am calling a custom function in the cards() function. The cards() function expects an array of cards/metrics to populate the default dashboard.

The ‘custom’ function in cards() expects your current role.

The ‘custom’ dashboardContent() function has an array for every dashboard containing their corresponding content.

Depending on what role you have as a user, your dashboard will be filled with the content belonging to your corresponding role.

I have done this by making an array containing all the ‘dashboard arrays’ and giving them a key/value pair using the role enums. So if your role matches an enum array key, it will return the corresponding dashboard array containing the content required to build the default dashboard.

public function dashboardContent($role)
{
    //array of metrics per dashboard
    $role1Metrics = [new Metrics1, new Metrics2, new Metrics3];
    $role2Metrics = [new Metrics1, new Metrics2];
    $role3Metrics = [new Metrics3];

    $dashboard = array(
        Roles::role1()->getValue() => $role1Metrics,
        Roles::role2()->getValue() => $role2Metrics,
        Roles::role3()->getValue() => $role3Metrics
    );

    if (array_key_exists($role, $dashboard)) {
        return $dashboard[$role];
    }
}

This could also be done using a switch case which would look something like this:

public function dashboardContent($role)
{
    //array of metrics per dashboard
    $role1Metrics = [new Metrics1, new Metrics2, new Metrics3];
    $role2Metrics = [new Metrics1, new Metrics2];
    $role3Metrics = [new Metrics3];

    switch($role) {
        case Roles::role1():
            return $role1Metrics;
        case Roles::role2():
            return $role2Metrics;
        case Roles::role3():
            return $role3Metrics;
    }
}

This all works great, and I haven’t noticed any bad performance. However I do not feel good about having to go out of my way like this to use the default dashboard.

Ultimately I would love it if I could make dashboards in appNovaDashboards and to initialize these as default depending on role. As I feel like this would be way more maintainable in the future as the dashboard content will all be in their respective file rather then having to add them to an array in a custom function.

Advertisement

Answer

My issue on GitHub has been marked as next-series implying that this would be considered for the next version. This answers my question and thus means that as of now, this is currently not possible.

I will keep this updated incase of a new version.

However until then, if you are looking for a work around:

In the NovaServiceProvider theres a function called cards(), this is where your default dashboard expects content.

We are going to be making a function called dashboardContent(). In my case dashboardContent() is going to require a role, but this can be whatever (role, auth, id, user) as long as you don’t directly copy my code.

In the cards() function call:

return $this->dashboardContent(CurrentRole::getRole());

Create the function: dashboardContent():

Solution 1: key pairing

public function dashboardContent($role)
{
    //i have 3 roles, so 3 different dashboards
    $role1Metrics = [new Metrics1, new Metrics2, new Metrics3];
    $role2Metrics = [new Metrics1, new Metrics2];
    $role3Metrics = [new Metrics3];

    //i have an enum key => value combination
    $dashboard = array(
        Roles::role1()->getValue() => $role1Metrics,
        Roles::role2()->getValue() => $role2Metrics,
        Roles::role3()->getValue() => $role3Metrics
    );

    //if my enum key matches the users current role, return corresponding dashboard
    if (array_key_exists($role, $dashboard)) {
        return $dashboard[$role];
    }
}

Explanation of above code:

  1. Create an array per dashboard (this is going to contain all the dashboard content) as the cards() function in the NovaServiceProvider expects an array return. You fill these arrays by calling the metrics you have created (which are found in AppNovaMetrics), you simply call them by typing: new MetricsName.

  2. Make an array with a matchable key, in my case I have used enums so I know this data is and can be matched.

  3. Write an if statement to check if the users role matches the array key which in my case it should always do as I am using enums.

Solution 2: switch case

public function dashboardContent($role)
{
    //array of metrics per dashboard
    $role1Metrics = [new Metrics1, new Metrics2, new Metrics3];
    $role2Metrics = [new Metrics1, new Metrics2];
    $role3Metrics = [new Metrics3];

    switch($role) {
        case Roles::role1():
            return $role1Metrics;
        case Roles::role2():
            return $role2Metrics;
        case Roles::role3():
            return $role3Metrics;
    }
}

Explanation of above code:

  1. Create an array per dashboard (this is going to contain all the dashboard content) as the cards() function in the NovaServiceProvider expects an array return. You fill these arrays by calling the metrics you have created (which are found in AppNovaMetrics), you simply call them by typing: new MetricsName.
  2. I made a switch case going through the provided role which will be checked against the enums once again, if it’s a match return the dashboard array containing all the corresponding content.

I have compared both solutions and personally haven’t had a noticeable difference in performance, so either solution should be fine.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement