> */ public array $plugins = []; public static function getNavigationGroup(): ?string { return __('admin.groups.system'); } public static function getNavigationLabel(): string { return __('admin.nav.plugins'); } public function getTitle(): string { return __('admin.pages.plugins_title'); } public function mount(PluginManager $manager): void { $manager->syncDiscoveredPlugins(); $this->reload($manager); } public function enable(string $name, PluginManager $manager): void { try { $manager->enable($name); $this->reload($manager); Notification::make()->title(__('admin.pages.enable').':'.$name)->success()->send(); } catch (\Throwable $e) { Notification::make()->title($e->getMessage())->danger()->send(); } } public function disable(string $name, PluginManager $manager): void { try { $manager->disable($name); $this->reload($manager); Notification::make()->title(__('admin.pages.disable').':'.$name)->success()->send(); } catch (\Throwable $e) { Notification::make()->title($e->getMessage())->danger()->send(); } } public function showDocs(string $name, PluginManager $manager): void { if ($manager->readDocs($name) === null) { Notification::make()->title(__('admin.messages.plugin_docs_missing'))->warning()->send(); return; } $this->mountAction('viewDocs', ['name' => $name]); } public function viewDocsAction(): Action { return Action::make('viewDocs') ->label(__('admin.pages.plugin_docs')) ->modalHeading(function (array $arguments): string { $name = (string) ($arguments['name'] ?? ''); $plugin = collect($this->plugins)->firstWhere('name', $name); $title = is_array($plugin) ? (string) ($plugin['title'] ?? $name) : $name; return __('admin.pages.plugin_docs').($title !== '' ? ' · '.$title : ''); }) ->modalContent(function (array $arguments): View { return view('filament.partials.plugin-docs', [ 'html' => app(PluginManager::class)->readDocsHtml((string) ($arguments['name'] ?? '')) ?? '', ]); }) ->modalAlignment(Alignment::Center) ->modalWidth(Width::FiveExtraLarge) ->modalSubmitAction(false) ->modalCancelAction(fn (Action $action): Action => $action ->label(__('admin.actions.close')) ->color('primary') ->close() ) ->modalFooterActionsAlignment(Alignment::End) ->closeModalByClickingAway() ->closeModalByEscaping() ->stickyModalHeader() ->stickyModalFooter() ->extraModalWindowAttributes(['class' => 'lb-plugin-docs-modal']); } protected function reload(PluginManager $manager): void { $discovered = $manager->discover(); $records = Plugin::query()->get()->keyBy('name'); $accents = ['#0f8a7a', '#c45c26', '#2563eb', '#7c3aed', '#db2777', '#0891b2']; $this->plugins = $discovered->values()->map(function (array $manifest, int $index) use ($records, $accents, $manager) { $name = (string) $manifest['name']; $titleKey = 'admin.plugins.'.$name.'.title'; $descKey = 'admin.plugins.'.$name.'.description'; $record = $records->get($name); $requires = (array) ($manifest['requires'] ?? []); return [ 'name' => $name, 'title' => __($titleKey) !== $titleKey ? __($titleKey) : ($manifest['title'] ?? $name), 'version' => $manifest['version'] ?? '1.0.0', 'description' => __($descKey) !== $descKey ? __($descKey) : ($manifest['description'] ?? ''), 'enabled' => (bool) ($record?->enabled), 'requires' => $requires, 'has_docs' => $manager->docsPath($name) !== null, 'accent' => $accents[$index % count($accents)], ]; })->all(); } protected function getHeaderActions(): array { return [ Action::make('sync') ->label(__('admin.pages.plugins_sync')) ->action(function (PluginManager $manager): void { $manager->syncDiscoveredPlugins(); $this->reload($manager); Notification::make()->title(__('admin.pages.plugins_sync'))->success()->send(); }), ]; } }