2lenet/dashboard2-bundle
Symfony bundle that adds a customizable dashboard with drag-and-drop style widgets. Generate widgets via console makers, render with Twig templates, and persist layout/config in the database. Includes caching, role-based visibility, and troubleshooting tips.
Installation:
composer require 2lenet/dashboard2-bundle
Add to config/routes.yaml:
dashboard_widgets:
resource: "@LleDashboardBundle/Resources/config/routes.yaml"
Run migrations:
php bin/console make:migration
php bin/console doctrine:migrations:migrate
First Widget: Generate a widget via the maker:
php bin/console make:widget
Follow prompts (e.g., MyFirstWidget). This creates:
src/Widget/MyFirstWidget.php) extending AbstractWidget.templates/widget/my_first_widget.html.twig).Render the Dashboard:
Add a route to your routes.yaml:
dashboard:
path: /dashboard
controller: Lle\DashboardBundle\Controller\DashboardController::index
Visit /dashboard to see your widget.
Widget Creation:
make:widget for CRUD widgets or make:workflow-widget for workflow-specific widgets.AbstractWidget if needed (e.g., for custom logic).Rendering:
render() to return HTML (e.g., via twig() helper):
public function render()
{
return $this->twig('widget/my_first_widget.html.twig', [
'data' => $this->fetchData(),
]);
}
widget_class, widget_header).Configuration:
MyWidgetConfigType) and use createForm():
public function render()
{
$form = $this->createForm(MyWidgetConfigType::class);
return $this->twig('widget/my_first_widget.html.twig', [
'config_form' => $form->createView(),
]);
}
getConfig('key').Static Dashboard:
StaticWidgetProviderInterface to define a fixed widget layout:
public function getMyWidgets(): array
{
return [
'stats' => $this->buildWidget(StatsWidget::class, ['title' => 'System Stats']),
];
}
StaticDashboardController::staticDashboard.Chart Integration:
ChartProviderInterface for dynamic charts:
public function getChartList(): array
{
return ['daily_metrics', 'monthly_trends'];
}
public function getChart(string $key): Chart
{
return $this->chartBuilder->createChart(Chart::TYPE_LINE)->setData(...);
}
Dependencies:
symfony/ux-chartjs).dompdf/dompdf is installed.Security:
supports() (e.g., role checks):
public function supports(): bool
{
return $this->security->isGranted('ROLE_ADMIN');
}
Performance:
getCacheKey() and getCacheTimeout():
public function getCacheKey(): string
{
return md5($this->getConfig('cache_dependency'));
}
Testing:
WidgetTypeInterface in unit tests:
$widget = $this->createMock(AbstractWidget::class);
$widget->method('render')->willReturn('<div>Test</div>');
Missing Routes:
dashboard_widgets routes causes 404s. Verify with:
php bin/console debug:router | grep dashboard
Widget Not Appearing:
supports() or verify user roles (e.g., ROLE_DASHBOARD_WIDGET_NAME).php bin/console cache:clear.Static Dashboard Issues:
getWidget() returns the correct instance by static_index.StaticWidgetProvider prevents shared state issues.Twig Template Errors:
@LleDashboard/widget/base_widget.html.twig explicitly. Missing blocks (e.g., widget_class) may break styling.Form Submission:
getConfig().Widget Cache:
0 from getCacheTimeout().public function getCacheKey(): string
{
$key = $this->getId() . "_" . md5($this->config);
error_log("Cache key: $key");
return $key;
}
Static Dashboard:
$provider = new StaticWidgetProvider($widgetTypes);
dump($provider->getMyWidgets());
Custom Widget Types:
AbstractWidget to add shared logic (e.g., BaseDataWidget with fetchData()).Dynamic Roles:
public function supports(): bool
{
return $this->security->isGranted('ROLE_CUSTOM');
}
Asset Management:
asset() in Twig for static assets (e.g., charts). Run php bin/console asset:install if stylesheets are missing.Event Listeners:
WidgetEvent::POST_RENDER) via Symfony’s event dispatcher:
$this->eventDispatcher->dispatch(new WidgetEvent($this, 'post_render'));
Widget Organization:
src/Widget/Admin/, src/Widget/User/).Reusable Components:
widget/base_chart.html.twig).Performance:
getCacheTimeout(86400) (1 day) and invalidate cache on data changes:
$this->cache->delete($this->getCacheKey());
Localization:
messages.en.yaml):
widget.my_first_widget.name: "My First Widget"
How can I help you explore Laravel packages today?