Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Dashboard2 Bundle Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. 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
    
  2. First Widget: Generate a widget via the maker:

    php bin/console make:widget
    

    Follow prompts (e.g., MyFirstWidget). This creates:

    • A widget class (src/Widget/MyFirstWidget.php) extending AbstractWidget.
    • A Twig template (templates/widget/my_first_widget.html.twig).
  3. 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.


Implementation Patterns

Core Workflow

  1. Widget Creation:

    • Use make:widget for CRUD widgets or make:workflow-widget for workflow-specific widgets.
    • Manually extend AbstractWidget if needed (e.g., for custom logic).
  2. Rendering:

    • Override render() to return HTML (e.g., via twig() helper):
      public function render()
      {
          return $this->twig('widget/my_first_widget.html.twig', [
              'data' => $this->fetchData(),
          ]);
      }
      
    • Use Twig blocks to customize the Bootstrap 5 card layout (e.g., widget_class, widget_header).
  3. Configuration:

    • Define a form type (e.g., 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(),
          ]);
      }
      
    • Access config values via getConfig('key').
  4. Static Dashboard:

    • Implement StaticWidgetProviderInterface to define a fixed widget layout:
      public function getMyWidgets(): array
      {
          return [
              'stats' => $this->buildWidget(StatsWidget::class, ['title' => 'System Stats']),
          ];
      }
      
    • Route to StaticDashboardController::staticDashboard.
  5. Chart Integration:

    • Implement 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(...);
      }
      

Integration Tips

  • Dependencies:

    • Use Symfony UX Chart for charts (symfony/ux-chartjs).
    • For PDF exports, ensure dompdf/dompdf is installed.
  • Security:

    • Restrict widget visibility via supports() (e.g., role checks):
      public function supports(): bool
      {
          return $this->security->isGranted('ROLE_ADMIN');
      }
      
  • Performance:

    • Leverage caching with getCacheKey() and getCacheTimeout():
      public function getCacheKey(): string
      {
          return md5($this->getConfig('cache_dependency'));
      }
      
  • Testing:

    • Mock WidgetTypeInterface in unit tests:
      $widget = $this->createMock(AbstractWidget::class);
      $widget->method('render')->willReturn('<div>Test</div>');
      

Gotchas and Tips

Pitfalls

  1. Missing Routes:

    • Forgetting to add dashboard_widgets routes causes 404s. Verify with:
      php bin/console debug:router | grep dashboard
      
  2. Widget Not Appearing:

    • Check:
      • Roles: Override supports() or verify user roles (e.g., ROLE_DASHBOARD_WIDGET_NAME).
      • Network Tab: Look for 500 errors in the browser console.
      • Cache: Clear with php bin/console cache:clear.
  3. Static Dashboard Issues:

    • Widget Not Found: Ensure the provider’s getWidget() returns the correct instance by static_index.
    • Configuration Overrides: Cloning widgets in StaticWidgetProvider prevents shared state issues.
  4. Twig Template Errors:

    • Extend @LleDashboard/widget/base_widget.html.twig explicitly. Missing blocks (e.g., widget_class) may break styling.
  5. Form Submission:

    • Config forms must return JSON-serializable data. Avoid complex objects in getConfig().

Debugging

  • Widget Cache:

    • Disable caching temporarily by returning 0 from getCacheTimeout().
    • Log cache keys to verify updates:
      public function getCacheKey(): string
      {
          $key = $this->getId() . "_" . md5($this->config);
          error_log("Cache key: $key");
          return $key;
      }
      
  • Static Dashboard:

    • Test the provider in isolation:
      $provider = new StaticWidgetProvider($widgetTypes);
      dump($provider->getMyWidgets());
      

Extension Points

  1. Custom Widget Types:

    • Extend AbstractWidget to add shared logic (e.g., BaseDataWidget with fetchData()).
  2. Dynamic Roles:

    • Override role generation by implementing a voter:
      public function supports(): bool
      {
          return $this->security->isGranted('ROLE_CUSTOM');
      }
      
  3. Asset Management:

    • Use asset() in Twig for static assets (e.g., charts). Run php bin/console asset:install if stylesheets are missing.
  4. Event Listeners:

    • Hook into widget events (e.g., WidgetEvent::POST_RENDER) via Symfony’s event dispatcher:
      $this->eventDispatcher->dispatch(new WidgetEvent($this, 'post_render'));
      

Pro Tips

  • Widget Organization:

    • Group widgets by domain (e.g., src/Widget/Admin/, src/Widget/User/).
  • Reusable Components:

    • Create base templates for common layouts (e.g., widget/base_chart.html.twig).
  • Performance:

    • For heavy widgets, use getCacheTimeout(86400) (1 day) and invalidate cache on data changes:
      $this->cache->delete($this->getCacheKey());
      
  • Localization:

    • Translate widget names/titles via translation files (e.g., messages.en.yaml):
      widget.my_first_widget.name: "My First Widget"
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
yandex/translate-api
voku/simple_html_dom
league/flysystem-vfs
bkwld/upchuck
filament/spatie-laravel-tags-plugin
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php