Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This tutorial has a new version, check it out!

Dashboard & Menu Customizations

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $8.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

The only thing we have not talked about is this big, giant menu on the left! This menu is actually the key to one other commonly-asked question: how do I create an admin dashboard?

The answer... like always... lives in the configuration! In config.yml, under design, add a menu key:

... lines 1 - 80
easy_admin:
... line 82
design:
... lines 84 - 94
menu:
... lines 96 - 177

This works like many other config keys. First, it has a simple format: just list the sections in the order you want them: User, Genus, GenusHorde and SubFamily:

... lines 1 - 80
easy_admin:
... line 82
design:
... lines 84 - 94
menu:
- User
- Genus
- GenusHorde
- GenusNote
- SubFamily
... lines 101 - 177

These keys are coming from the keys that we chose for each section's configuration:

... lines 1 - 80
easy_admin:
... lines 82 - 104
entities:
Genus:
... lines 107 - 174
GenusHorde:
... lines 176 - 177

These could have been anything.

Thanks to this, the User link will move from the bottom all the way to the top. There are a lot of other customizations you can make to the menu... but before we get there, I want a dashboard! Yea know, an admin homepage full of important-looking graphs!

Adding a Dashboard

If you downloaded the course code, you should have a tutorial/ directory. Inside, it has an AdminController with a dashboardAction(). Copy that. Then, in src/AppBundle/Controller/EasyAdmin, open our AdminController and paste it there:

... lines 1 - 8
class AdminController extends BaseAdminController
{
... lines 11 - 15
/**
* @Route("/dashboard", name="admin_dashboard")
*/
public function dashboardAction()
{
$em = $this->getDoctrine()->getManager();
$genusRepository = $em->getRepository(Genus::class);
return $this->render('easy_admin/dashboard.html.twig', [
'genusCount' => $genusRepository->getGenusCount(),
'publishedGenusCount' => $genusRepository->getPublishedGenusCount(),
'randomGenus' => $genusRepository->findRandomGenus()
]);
}
}

Thanks to the prefix on the route import:

... lines 1 - 9
easy_admin_bundle:
... lines 11 - 12
prefix: /easyadmin

This creates a new /easyadmin/dashboard route named admin_dashboard. Oh, I'm missing my use statement for @Route. I'll re-type that and hit enter so that it auto-completes the use statement on top:

... lines 1 - 6
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class AdminController extends BaseAdminController
{
... lines 11 - 15
/**
* @Route("/dashboard", name="admin_dashboard")
*/
public function dashboardAction()
{
... lines 21 - 28
}
}

Perfect!

This renders a template, which I will also grab from the tutorial/ directory. Paste that in app/Resources/views/easy_admin:

{% extends '@EasyAdmin/default/layout.html.twig' %}
{% set _content_title = 'Admin dashboard' %}
{% block page_title -%}
{{ _content_title }}
{%- endblock %}
{% block content_header %}
<h1 class="title">{{ _content_title }}</h1>
{% endblock %}
{% block main %}
<div class="row">
<div class="col-sm-4">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Stats</h3>
</div>
<div class="panel-body">
<ul class="list-group" style="margin-left: 0;">
<li class="list-group-item">
<span class="badge">{{ genusCount }}</span>
Genus count
</li>
<li class="list-group-item">
<span class="badge">{{ publishedGenusCount }}</span>
Published genus count
</li>
</ul>
</div>
</div>
</div>
<div class="col-sm-4">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Chart</h3>
</div>
<div class="panel-body">
<script type="text/javascript"
src="https://ssl.gstatic.com/trends_nrtr/1015_RC10/embed_loader.js"></script>
<script type="text/javascript">
trends.embed.renderExploreWidget("TIMESERIES", {
"comparisonItem": [{
"keyword": "funny cat videos",
"geo": "",
"time": "2012-05-17 2017-05-17"
}], "category": 0, "property": ""
}, {
"exploreQuery": "q=funny%20cat%20videos",
"guestPath": "https://trends.google.com:443/trends/embed/"
});
</script>
</div>
</div>
</div>
<div class="col-sm-4">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">{{ randomGenus.name }}</h3>
</div>
<div class="panel-body">
<p>
<img src="{{ asset('images/octopus-rubescens.jpg') }}" />
</p>
<p>{{ randomGenus.funFact }}</p>
<a href="{{ path('easyadmin', {entity: 'Genus', action: 'show', id: randomGenus.id}) }}"
class="btn btn-primary">
Show details
</a>
</div>
</div>
</div>
</div>
{% endblock %}

At this point... the page should work. Cool... but how can I tell EasyAdminBundle to show this page when we go to the admin section's homepage? Right now, if you go directly to /easyadmin, it will take you to whatever the first-defined entity section is... so Genus.

But... add a new menu item and use the expanded config format with label: Dashboard, route: admin_dashboard and - here is the key - default: true:

... lines 1 - 80
easy_admin:
... line 82
design:
... lines 84 - 94
menu:
- { label: 'Dashboard', route: 'admin_dashboard', default: true }
... lines 97 - 178

Thanks to default: true, when you click on the AquaNote logo to go to the admin homepage... ah! You'll get an error! That was not the dramatic success moment I was hoping for.

But... look! It did redirect to /easyadmin/dashboard! The error is just a Ryan mistake: I forgot a use statement for my Genus class. Add that on top:

... lines 1 - 4
use AppBundle\Entity\Genus;
... lines 6 - 8
class AdminController extends BaseAdminController
{
... lines 11 - 18
public function dashboardAction()
{
... line 21
$genusRepository = $em->getRepository(Genus::class);
... lines 23 - 28
}
}

Try it again! Hello super fancy dashboard! Where apparently, somehow, interest in funny cat videos has been decreasing. Well, anyways, say hello to your new dashboard. Where hopefully, you will build infinitely more useful graphs than this.

Now, back to customizing that menu...

Leave a comment!

4
Login or Register to join the conversation
Brent Avatar

I am using Easy Admin and I have plans to add a dashboard with graphs (line, bar, pie, etc.). Is there any particular library and or bundle I should use to accomplish these graphs within Easy Admin?

Thank you in advance!

1 Reply

Hey Brentmtc,

Hm, I don't think there're any specific bundles for this, but there's a plenty of JS libraries on GitHub that could help you to build graphs fast and easy. The only thing you have to do except installing that library and adding some boilerplate code - prepare some real data for it. On SymfonyCasts we use https://github.com/chartjs/... - you can see it on your "Activity" page in "Activity Tracker" section :) But you can take a look at other popular here: https://github.com/search?l...

I hope this helps!

Cheers!

Reply
Brent Avatar

That does help. I believe I am going to try chartjs. Thank you!

Reply

Hey Brentmtc,

Perfect, glad it helped!

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial is built on an older version of Symfony & EasyAdminBundle. Many of the concepts are the same, but you can expect major differences in newer versions.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.3.*", // v3.3.18
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.10.3
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.5
        "symfony/swiftmailer-bundle": "^2.3", // v2.6.7
        "symfony/monolog-bundle": "^2.8", // v2.12.1
        "symfony/polyfill-apcu": "^1.0", // v1.17.0
        "sensio/distribution-bundle": "^5.0", // v5.0.25
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.29
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.4
        "knplabs/knp-markdown-bundle": "^1.4", // 1.7.1
        "doctrine/doctrine-migrations-bundle": "^1.1", // v1.3.2
        "stof/doctrine-extensions-bundle": "^1.2", // v1.3.0
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "javiereguiluz/easyadmin-bundle": "^1.16" // v1.17.21
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.1.7
        "symfony/phpunit-bridge": "^3.0", // v3.4.40
        "nelmio/alice": "^2.1", // v2.3.5
        "doctrine/doctrine-fixtures-bundle": "^2.3" // v2.4.1
    }
}
userVoice