From 7743c2e126a940da8a1e4494b29d136428ee1bc8 Mon Sep 17 00:00:00 2001 From: Darko Gjorgjijoski Date: Thu, 9 Apr 2026 00:29:56 +0200 Subject: [PATCH] feat(modules): dynamic sidebar group rendering active modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sidebar gains a new section that lists each currently-activated module as a direct shortcut to its settings page. This is the always-visible companion to the company-context Active Modules index — both surface the same set of modules, but the index is the catalog landing page and the sidebar group is the per-module quick access. - BootstrapController returns module_menu populated from \InvoiceShelf\Modules\Registry::allMenu(), but only on the company-context branch — not on the super-admin branch (lines 53-69), since super admins don't see the dynamic group. Because nwidart only boots service providers for currently-activated modules, the registry naturally contains only active modules at request time, no extra filtering needed. - bootstrap.service.ts BootstrapResponse type extended with module_menu?: ModuleMenuItem[]; new ModuleMenuItem interface (title/link/icon) — shaped distinctly from MenuItem because module entries use namespaced i18n keys and don't carry group/ability metadata. - global.store.ts exposes a moduleMenu ref + a hasActiveModules computed. - SiteSidebar.vue appends a new "Modules" section after the existing menuGroups output, in both the mobile (Dialog) and desktop branches. The section is hidden when hasActiveModules is false. Uses the modules.sidebar.section_title i18n key added in the previous commit. --- .../Company/General/BootstrapController.php | 2 + .../scripts/api/services/bootstrap.service.ts | 15 ++++ .../scripts/layouts/partials/SiteSidebar.vue | 71 +++++++++++++++++++ resources/scripts/stores/global.store.ts | 8 ++- 4 files changed, 95 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Company/General/BootstrapController.php b/app/Http/Controllers/Company/General/BootstrapController.php index 484ca1d5..b21409c5 100644 --- a/app/Http/Controllers/Company/General/BootstrapController.php +++ b/app/Http/Controllers/Company/General/BootstrapController.php @@ -15,6 +15,7 @@ use App\Models\Setting; use App\Traits\GeneratesMenuTrait; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use InvoiceShelf\Modules\Registry as ModuleRegistry; use Silber\Bouncer\BouncerFacade; class BootstrapController extends Controller @@ -118,6 +119,7 @@ class BootstrapController extends Controller 'main_menu' => $main_menu, 'setting_menu' => $setting_menu, 'modules' => Module::where('enabled', true)->pluck('name'), + 'module_menu' => array_values(ModuleRegistry::allMenu()), 'pending_invitations' => CompanyInvitationResource::collection($pendingInvitations), ]); } diff --git a/resources/scripts/api/services/bootstrap.service.ts b/resources/scripts/api/services/bootstrap.service.ts index 90561331..5a22fabc 100644 --- a/resources/scripts/api/services/bootstrap.service.ts +++ b/resources/scripts/api/services/bootstrap.service.ts @@ -15,6 +15,20 @@ export interface MenuItem { ability?: string } +/** + * Sidebar item registered by an active module via + * \InvoiceShelf\Modules\Registry::registerMenu() in the module's ServiceProvider::boot(). + * + * Distinct shape from MenuItem because module entries are namespaced (i18n + * keys come from the module's lang files) and don't carry group/ability — + * they always render under the dynamic "Modules" sidebar section. + */ +export interface ModuleMenuItem { + title: string + link: string + icon: string +} + export interface BootstrapResponse { current_user: User current_user_settings: Record @@ -28,6 +42,7 @@ export interface BootstrapResponse { config: Record global_settings: Record modules: string[] + module_menu?: ModuleMenuItem[] admin_mode?: boolean pending_invitations?: Array<{ token: string diff --git a/resources/scripts/layouts/partials/SiteSidebar.vue b/resources/scripts/layouts/partials/SiteSidebar.vue index 0b7123cc..8b27d410 100644 --- a/resources/scripts/layouts/partials/SiteSidebar.vue +++ b/resources/scripts/layouts/partials/SiteSidebar.vue @@ -99,6 +99,34 @@ {{ $t(item.title) }} + + + @@ -168,6 +196,49 @@ + +
+
+ {{ $t('modules.sidebar.section_title') }} +
+
+ + + + {{ $t(item.title) }} + + +
+