dashboard widgets from event (#246)
This commit is contained in:
@@ -9,16 +9,12 @@
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Entity\User;
|
||||
use App\Repository\Query\TimesheetQuery;
|
||||
use App\Event\DashboardEvent;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
|
||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
* Dashboard controller for the admin area.
|
||||
@@ -28,120 +24,34 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
||||
*/
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
/**
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function __construct(EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->eventDispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/", defaults={}, name="dashboard")
|
||||
* @Method("GET")
|
||||
*/
|
||||
public function indexAction()
|
||||
{
|
||||
$user = $this->getUser();
|
||||
$event = new DashboardEvent($this->getUser());
|
||||
|
||||
$userStats = $this->getDoctrine()->getRepository(User::class)->getGlobalStatistics();
|
||||
|
||||
// FIXME move the other widgets to the Kimai, the inheritence is wrong as Kimai
|
||||
// shouldn't know about Timesheets
|
||||
|
||||
$timesheetRepo = $this->getDoctrine()->getRepository(Timesheet::class);
|
||||
$timesheetUserStats = $timesheetRepo->getUserStatistics($user);
|
||||
$timesheetGlobalStats = $timesheetRepo->getGlobalStatistics();
|
||||
|
||||
$activityStats = $this->getDoctrine()->getRepository(Activity::class)->getGlobalStatistics();
|
||||
$projectStats = $this->getDoctrine()->getRepository(Project::class)->getGlobalStatistics();
|
||||
$customerStats = $this->getDoctrine()->getRepository(Customer::class)->getGlobalStatistics();
|
||||
$this->eventDispatcher->dispatch(
|
||||
DashboardEvent::DASHBOARD,
|
||||
$event
|
||||
);
|
||||
|
||||
return $this->render('dashboard/index.html.twig', [
|
||||
'dashboard_widgets' => $this->getWidgets(),
|
||||
'timesheetGlobal' => $timesheetGlobalStats,
|
||||
'timesheetUser' => $timesheetUserStats,
|
||||
'activity' => $activityStats,
|
||||
'project' => $projectStats,
|
||||
'customer' => $customerStats,
|
||||
'user' => $userStats,
|
||||
'widget_rows' => $event->getWidgetRows()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* colors: blue / yellow / purple / green / black
|
||||
* icons: bar-chart / line-chart / calendar / clock
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getWidgets()
|
||||
{
|
||||
// @codingStandardsIgnoreStart
|
||||
$widgets = [
|
||||
/*
|
||||
[
|
||||
'header' => 'dashboard.you',
|
||||
'widgets' => [
|
||||
"{{ widgets.info_box_progress('Bewilligte Stunden', 'Stunden zur Abrechnung bewilligt', 120, 10, 'star') }}",
|
||||
"{{ widgets.info_box_progress('Umsatz / Monat', '70% Increase in 30 Days', 6830, 30, 'credit-card', 'black') }}",
|
||||
"{{ widgets.info_box_progress('Stunden persönlich', 'Das ist noch nicht genug', 135, 60, 'hourglass') }}",
|
||||
"{{ widgets.info_box_progress('Anzahl Benutzer', 'Mehr ist besser!', 5, 90, 'user') }}",
|
||||
],
|
||||
],
|
||||
*/
|
||||
[
|
||||
'id' => 'profile.stats',
|
||||
'header' => 'dashboard.you',
|
||||
'widgets' => [
|
||||
"{{ widgets.info_box_counter('stats.durationThisMonth', timesheetUser.durationThisMonth|duration(true), 'far fa-hourglass', 'green') }}",
|
||||
//"{{ widgets.info_box_counter('stats.amountThisMonth', timesheetUser.amountThisMonth|money, 'money', 'blue') }}",
|
||||
"{{ widgets.info_box_counter('stats.durationTotal', timesheetUser.durationTotal|duration(true), 'far fa-hourglass', 'red') }}",
|
||||
//"{{ widgets.info_box_counter('stats.amountTotal', timesheetUser.amountTotal|money, 'money', 'yellow') }}",
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
if (!$this->isGranted('ROLE_TEAMLEAD', null)) {
|
||||
return $widgets;
|
||||
}
|
||||
|
||||
$widgets[] = [
|
||||
'id' => 'alluser.stats',
|
||||
'header' => 'dashboard.all',
|
||||
'widgets' => [
|
||||
"{{ widgets.info_box_counter('stats.durationThisMonth', timesheetGlobal.durationThisMonth|duration(true), 'far fa-hourglass', 'blue') }}",
|
||||
"{{ widgets.info_box_counter('stats.durationTotal', timesheetGlobal.durationTotal|duration(true), 'far fa-hourglass', 'yellow') }}",
|
||||
"{{ widgets.info_box_counter('stats.activeRecordings', timesheetGlobal.activeCurrently, 'far fa-hourglass', 'red', path('admin_timesheet', {'state': " . TimesheetQuery::STATE_RUNNING . '})) }}',
|
||||
],
|
||||
];
|
||||
|
||||
$widgets[] = [
|
||||
'id' => 'user.stats',
|
||||
'header' => '',
|
||||
'widgets' => [
|
||||
"{{ widgets.info_box_counter('stats.userTotal', user.totalAmount, 'user', 'red') }}",
|
||||
"{{ widgets.info_box_counter('stats.userActiveThisMoth', timesheetGlobal.activeThisMonth, 'user', 'yellow') }}",
|
||||
"{{ widgets.info_box_counter('stats.userActiveEver', timesheetGlobal.activeTotal, 'user', 'blue') }}",
|
||||
],
|
||||
];
|
||||
|
||||
if (!$this->isGranted('ROLE_ADMIN', null)) {
|
||||
return $widgets;
|
||||
}
|
||||
|
||||
$widgets[] = [
|
||||
'id' => 'alluser.money_stats',
|
||||
'header' => '',
|
||||
'widgets' => [
|
||||
"{{ widgets.info_box_counter('stats.amountThisMonth', timesheetGlobal.amountThisMonth|money, 'far fa-money-bill-alt', 'green') }}",
|
||||
"{{ widgets.info_box_counter('stats.amountTotal', timesheetGlobal.amountTotal|money, 'far fa-money-bill-alt', 'red') }}",
|
||||
],
|
||||
];
|
||||
|
||||
$widgets[] = [
|
||||
'id' => 'admin.stats',
|
||||
'header' => 'dashboard.admin',
|
||||
'widgets' => [
|
||||
"{{ widgets.info_box_more('stats.userTotal', user.totalAmount, ' ', path('admin_user'), 'user') }}",
|
||||
"{{ widgets.info_box_more('stats.customerTotal', customer.count, '', path('admin_customer'), 'customer', 'blue') }}",
|
||||
"{{ widgets.info_box_more('stats.projectsTotal', project.count, '', path('admin_project'), 'project', 'yellow') }}",
|
||||
"{{ widgets.info_box_more('stats.activitiesTotal', activity.count, '', path('admin_activity'), 'activity', 'purple') }}",
|
||||
],
|
||||
];
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
return $widgets;
|
||||
}
|
||||
}
|
||||
|
||||
59
src/Event/DashboardEvent.php
Normal file
59
src/Event/DashboardEvent.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Event;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Model\TimesheetGlobalStatistic;
|
||||
use App\Model\WidgetRow;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
|
||||
class DashboardEvent extends Event
|
||||
{
|
||||
public const DASHBOARD = 'app.dashboard';
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
protected $user;
|
||||
/**
|
||||
* @var WidgetRow[]
|
||||
*/
|
||||
protected $widgetRows = [];
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param TimesheetGlobalStatistic $timesheetStatistic
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function addWidgetRow(WidgetRow $row)
|
||||
{
|
||||
$this->widgetRows[] = $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WidgetRow[]
|
||||
*/
|
||||
public function getWidgetRows()
|
||||
{
|
||||
return $this->widgetRows;
|
||||
}
|
||||
}
|
||||
169
src/EventSubscriber/DashboardSubscriber.php
Normal file
169
src/EventSubscriber/DashboardSubscriber.php
Normal file
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\EventSubscriber;
|
||||
|
||||
use App\Entity\Activity;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Entity\User;
|
||||
use App\Event\DashboardEvent;
|
||||
use App\Model\TimesheetGlobalStatistic;
|
||||
use App\Model\TimesheetStatistic;
|
||||
use App\Model\UserStatistic;
|
||||
use App\Model\WidgetRow;
|
||||
use App\Repository\Query\TimesheetQuery;
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
|
||||
/**
|
||||
* Used to add Dashboard widgets for a user.
|
||||
*/
|
||||
class DashboardSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @var AuthorizationCheckerInterface
|
||||
*/
|
||||
protected $security;
|
||||
/**
|
||||
* @var ManagerRegistry
|
||||
*/
|
||||
protected $registry;
|
||||
|
||||
/**
|
||||
* MenuSubscriber constructor.
|
||||
* @param AuthorizationCheckerInterface $security
|
||||
*/
|
||||
public function __construct(AuthorizationCheckerInterface $security, ManagerRegistry $registry)
|
||||
{
|
||||
$this->security = $security;
|
||||
$this->registry = $registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
DashboardEvent::DASHBOARD => ['onDashboardEvent', 100],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DashboardEvent $event
|
||||
* @throws \Doctrine\ORM\NonUniqueResultException
|
||||
*/
|
||||
public function onDashboardEvent(DashboardEvent $event)
|
||||
{
|
||||
$timesheetRepo = $this->registry->getRepository(Timesheet::class);
|
||||
$timesheetGlobal = $timesheetRepo->getGlobalStatistics();
|
||||
$timesheetUser = $timesheetRepo->getUserStatistics($event->getUser());
|
||||
$userStats = $this->registry->getRepository(User::class)->getGlobalStatistics();
|
||||
|
||||
$this->addUserWidgets($event, $timesheetUser);
|
||||
|
||||
if (!$this->security->isGranted('ROLE_TEAMLEAD')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->addTeamleadWidgets($event, $timesheetGlobal, $userStats);
|
||||
|
||||
if (!$this->security->isGranted('ROLE_ADMIN')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->addAdminWidgets($event, $timesheetGlobal, $userStats);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DashboardEvent $event
|
||||
* @param TimesheetStatistic $timesheet
|
||||
*/
|
||||
protected function addUserWidgets(DashboardEvent $event, TimesheetStatistic $timesheet)
|
||||
{
|
||||
/*
|
||||
$row = new WidgetRow('dashboard.you');
|
||||
$widgets = [
|
||||
[
|
||||
'widgets' => [
|
||||
"{{ widgets.info_box_progress('Bewilligte Stunden', 'Stunden zur Abrechnung bewilligt', 120, 10, 'star') }}",
|
||||
"{{ widgets.info_box_progress('Umsatz / Monat', '70% Increase in 30 Days', 6830, 30, 'credit-card', 'black') }}",
|
||||
"{{ widgets.info_box_progress('Stunden persönlich', 'Das ist noch nicht genug', 135, 60, 'hourglass') }}",
|
||||
"{{ widgets.info_box_progress('Anzahl Benutzer', 'Mehr ist besser!', 5, 90, 'user') }}",
|
||||
],
|
||||
],
|
||||
$event->addWidgetRow($row);
|
||||
*/
|
||||
|
||||
$row = new WidgetRow('profile.stats', 'dashboard.you');
|
||||
$row
|
||||
->add("{{ widgets.info_box_counter('stats.durationThisMonth', " . $timesheet->getDurationThisMonth() . "|duration(true), 'far fa-hourglass', 'green') }}")
|
||||
//->add("{{ widgets.info_box_counter('stats.amountThisMonth', ".$timesheet->getAmountThisMonth()."|money, 'money', 'blue') }}")
|
||||
->add("{{ widgets.info_box_counter('stats.durationTotal', " . $timesheet->getDurationTotal() . "|duration(true), 'far fa-hourglass', 'red') }}")
|
||||
//->add("{{ widgets.info_box_counter('stats.amountTotal', ".$timesheet->getAmountTotal()."|money, 'money', 'yellow') }}")
|
||||
;
|
||||
$event->addWidgetRow($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DashboardEvent $event
|
||||
* @param TimesheetGlobalStatistic $timesheet
|
||||
* @param UserStatistic $userStats
|
||||
*/
|
||||
protected function addTeamleadWidgets(DashboardEvent $event, TimesheetGlobalStatistic $timesheet, UserStatistic $userStats)
|
||||
{
|
||||
$row = new WidgetRow('alluser.stats', 'dashboard.all');
|
||||
$row
|
||||
->add("{{ widgets.info_box_counter('stats.durationThisMonth', " . $timesheet->getDurationThisMonth() . "|duration(true), 'far fa-hourglass', 'blue') }}")
|
||||
->add("{{ widgets.info_box_counter('stats.durationTotal', " . $timesheet->getDurationTotal() . "|duration(true), 'far fa-hourglass', 'yellow') }}")
|
||||
->add("{{ widgets.info_box_counter('stats.activeRecordings', " . $timesheet->getActiveCurrently() . ", 'far fa-hourglass', 'red', path('admin_timesheet', {'state': " . TimesheetQuery::STATE_RUNNING . '})) }}')
|
||||
;
|
||||
$event->addWidgetRow($row);
|
||||
|
||||
$row = new WidgetRow('user.stats');
|
||||
$row
|
||||
->add("{{ widgets.info_box_counter('stats.userTotal', " . $userStats->getTotalAmount() . ", 'user', 'red') }}")
|
||||
->add("{{ widgets.info_box_counter('stats.userActiveThisMoth', " . $timesheet->getActiveThisMonth() . ", 'user', 'yellow') }}")
|
||||
->add("{{ widgets.info_box_counter('stats.userActiveEver', " . $timesheet->getActiveTotal() . ", 'user', 'blue') }}")
|
||||
;
|
||||
$event->addWidgetRow($row);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DashboardEvent $event
|
||||
* @param TimesheetGlobalStatistic $timesheet
|
||||
* @param UserStatistic $user
|
||||
* @throws \Doctrine\ORM\NonUniqueResultException
|
||||
*/
|
||||
protected function addAdminWidgets(DashboardEvent $event, TimesheetGlobalStatistic $timesheet, UserStatistic $user)
|
||||
{
|
||||
$row = new WidgetRow('alluser.money_stats');
|
||||
$row
|
||||
->add("{{ widgets.info_box_counter('stats.amountThisMonth', " . $timesheet->getAmountThisMonth() . "|money, 'far fa-money-bill-alt', 'green') }}")
|
||||
->add("{{ widgets.info_box_counter('stats.amountTotal', " . $timesheet->getAmountTotal() . "|money, 'far fa-money-bill-alt', 'red') }}")
|
||||
;
|
||||
$event->addWidgetRow($row);
|
||||
|
||||
$activity = $this->registry->getRepository(Activity::class)->getGlobalStatistics();
|
||||
$project = $this->registry->getRepository(Project::class)->getGlobalStatistics();
|
||||
$customer = $this->registry->getRepository(Customer::class)->getGlobalStatistics();
|
||||
|
||||
$row = new WidgetRow('admin.stats', 'dashboard.admin');
|
||||
$row
|
||||
->add("{{ widgets.info_box_more('stats.userTotal', " . $user->getTotalAmount() . ", ' ', path('admin_user'), 'user') }}")
|
||||
->add("{{ widgets.info_box_more('stats.customerTotal', " . $customer->getCount() . ", '', path('admin_customer'), 'customer', 'blue') }}")
|
||||
->add("{{ widgets.info_box_more('stats.projectsTotal', " . $project->getCount() . ", '', path('admin_project'), 'project', 'yellow') }}")
|
||||
->add("{{ widgets.info_box_more('stats.activitiesTotal', " . $activity->getCount() . ", '', path('admin_activity'), 'activity', 'purple') }}")
|
||||
;
|
||||
$event->addWidgetRow($row);
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ class TimesheetGlobalStatistic extends TimesheetStatistic
|
||||
*/
|
||||
public function setActiveCurrently($activeCurrently)
|
||||
{
|
||||
$this->activeCurrently = $activeCurrently;
|
||||
$this->activeCurrently = (int) $activeCurrently;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,7 +56,7 @@ class TimesheetGlobalStatistic extends TimesheetStatistic
|
||||
*/
|
||||
public function setActiveThisMonth($activeThisMonth)
|
||||
{
|
||||
$this->activeThisMonth = $activeThisMonth;
|
||||
$this->activeThisMonth = (int) $activeThisMonth;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,6 +72,6 @@ class TimesheetGlobalStatistic extends TimesheetStatistic
|
||||
*/
|
||||
public function setActiveTotal($activeTotal)
|
||||
{
|
||||
$this->activeTotal = $activeTotal;
|
||||
$this->activeTotal = (int) $activeTotal;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class TimesheetStatistic
|
||||
*/
|
||||
public function setDurationThisMonth($durationThisMonth)
|
||||
{
|
||||
$this->durationThisMonth = $durationThisMonth;
|
||||
$this->durationThisMonth = (int) $durationThisMonth;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,7 +66,7 @@ class TimesheetStatistic
|
||||
*/
|
||||
public function setAmountTotal($amountTotal)
|
||||
{
|
||||
$this->amountTotal = $amountTotal;
|
||||
$this->amountTotal = (int) $amountTotal;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +82,7 @@ class TimesheetStatistic
|
||||
*/
|
||||
public function setDurationTotal($durationTotal)
|
||||
{
|
||||
$this->durationTotal = $durationTotal;
|
||||
$this->durationTotal = (int) $durationTotal;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,7 +98,7 @@ class TimesheetStatistic
|
||||
*/
|
||||
public function setAmountThisMonth($amountThisMonth)
|
||||
{
|
||||
$this->amountThisMonth = $amountThisMonth;
|
||||
$this->amountThisMonth = (int) $amountThisMonth;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,6 +32,6 @@ class UserStatistic
|
||||
*/
|
||||
public function setTotalAmount($totalAmount)
|
||||
{
|
||||
$this->totalAmount = $totalAmount;
|
||||
$this->totalAmount = (int) $totalAmount;
|
||||
}
|
||||
}
|
||||
|
||||
71
src/Model/WidgetRow.php
Normal file
71
src/Model/WidgetRow.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
class WidgetRow
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $id;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $title;
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $widgets = [];
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
* @param string $title
|
||||
*/
|
||||
public function __construct(string $id, string $title = '')
|
||||
{
|
||||
$this->id = $id;
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getId(): string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle(): string
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getWidgets(): array
|
||||
{
|
||||
return $this->widgets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $templateString
|
||||
* @return $this
|
||||
*/
|
||||
public function add(string $templateString)
|
||||
{
|
||||
$this->widgets[] = $templateString;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -8,19 +8,24 @@
|
||||
|
||||
{% block main %}
|
||||
|
||||
{% for settings in dashboard_widgets %}
|
||||
{% if settings.header %}
|
||||
{{ widgets.page_header(settings.header) }}
|
||||
{% for row in widget_rows %}
|
||||
{% if row.title %}
|
||||
{{ widgets.page_header(row.title) }}
|
||||
{% endif %}
|
||||
|
||||
{% set width = settings.widgets|length %}
|
||||
{% set width = row.widgets|length %}
|
||||
{% set rawWidth = 12 / width %}
|
||||
{% set columnWidth = rawWidth|round(0, 'floor') %}
|
||||
<div class="row">
|
||||
{% for widgetTemplate in settings.widgets %}
|
||||
{% for widgetTemplate in row.widgets %}
|
||||
<div class="col-md-{{ columnWidth }} col-sm-{{ columnWidth * 2 }} col-xs-{{ columnWidth * 4 }}">
|
||||
{% set widgetString = '{% import "macros/widgets.html.twig" as widgets %}' ~ widgetTemplate %}
|
||||
{{ include(template_from_string(widgetString)) }}
|
||||
{{
|
||||
include(
|
||||
template_from_string(
|
||||
'{% import "macros/widgets.html.twig" as widgets %}' ~ widgetTemplate
|
||||
)
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
namespace App\Tests\Controller;
|
||||
|
||||
use App\Entity\User;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \App\Controller\DashboardController
|
||||
* @group integration
|
||||
@@ -27,4 +29,12 @@ class DashboardControllerTest extends ControllerBaseTest
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
$this->assertMainContentClass($client, 'dashboard');
|
||||
}
|
||||
|
||||
public function testIndexActionForAdmin()
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser(User::ROLE_ADMIN);
|
||||
$this->request($client, '/dashboard/');
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
$this->assertMainContentClass($client, 'dashboard');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,8 +100,8 @@ The files in `translations/` as a quick overview:
|
||||
|
||||
If you want to add your own entries in the navigation bar, you can subscribe to these events:
|
||||
|
||||
- `App\EventConfigureMainMenuEvent::CONFIGURE`
|
||||
- `App\ConfigureAdminMenuEvent::CONFIGURE`
|
||||
- `App\Event\ConfigureMainMenuEvent::CONFIGURE`
|
||||
- `App\Event\ConfigureAdminMenuEvent::CONFIGURE`
|
||||
|
||||
And that's how to use it:
|
||||
|
||||
@@ -111,7 +111,7 @@ use App\Event\ConfigureAdminMenuEvent;
|
||||
use Avanzu\AdminThemeBundle\Model\MenuItemModel;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class MySubscriber implements EventSubscriberInterface
|
||||
class MyMenuSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
@@ -138,6 +138,37 @@ class MySubscriber implements EventSubscriberInterface
|
||||
```
|
||||
For more details check the [official menu subscriber](../../src/EventSubscriber/MenuSubscriber.php).
|
||||
|
||||
## Extending the dashboard with widgets
|
||||
|
||||
If you want to add your own widget rows to the dashboard, you can subscribe to the event:
|
||||
|
||||
- `App\Event\DashboardEvent::DASHBOARD`
|
||||
|
||||
And that's how to use it:
|
||||
|
||||
```php
|
||||
use App\Event\DashboardEvent;
|
||||
use App\Model\WidgetRow;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class MyDashboardSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [DashboardEvent::DASHBOARD => ['onDashboardEvent', 200]];
|
||||
}
|
||||
|
||||
public function onDashboardEvent(DashboardEvent $event)
|
||||
{
|
||||
$row = new WidgetRow('my_id', 'optional.row.title');
|
||||
// this needs to be a valid twig template string
|
||||
$row->add("{{ widgets.info_box_counter('a title', 100, 'far fa-hourglass', 'green') }}");
|
||||
$event->addWidgetRow($row);
|
||||
}
|
||||
}
|
||||
```
|
||||
For more details check the [official dashboard subscriber](../../src/EventSubscriber/DashboardSubscriber.php).
|
||||
|
||||
## Adding tabs to the "control sidebar"
|
||||
|
||||
We use twig globals to render the control sidebar tabs, so adding one is as easy as adding a new config entry:
|
||||
|
||||
Reference in New Issue
Block a user