diff --git a/formwork/src/Panel/Controllers/OptionsController.php b/formwork/src/Panel/Controllers/OptionsController.php index 2fb1d01b5..451e93487 100644 --- a/formwork/src/Panel/Controllers/OptionsController.php +++ b/formwork/src/Panel/Controllers/OptionsController.php @@ -12,13 +12,6 @@ final class OptionsController extends AbstractController { - /** - * All options tabs - * - * @var list - */ - private array $tabs = ['site', 'system']; - /** * Options@index action */ @@ -71,11 +64,7 @@ public function systemOptions(Schemes $schemes): Response } return new Response($this->view('@panel.options.system', [ - 'title' => $this->translate('panel.options.options'), - 'tabs' => $this->view('@panel.options.tabs', [ - 'tabs' => $this->tabs, - 'current' => 'system', - ]), + 'title' => $this->translate('panel.options.options'), 'fields' => $form->fields(), ]), $form->getResponseStatus()); } @@ -119,11 +108,7 @@ public function siteOptions(Schemes $schemes): Response } return new Response($this->view('@panel.options.site', [ - 'title' => $this->translate('panel.options.options'), - 'tabs' => $this->view('@panel.options.tabs', [ - 'tabs' => $this->tabs, - 'current' => 'site', - ]), + 'title' => $this->translate('panel.options.options'), 'fields' => $form->fields(), ]), $form->getResponseStatus()); } diff --git a/formwork/src/Panel/Controllers/ToolsController.php b/formwork/src/Panel/Controllers/ToolsController.php index 3edf97755..8ce2284ce 100644 --- a/formwork/src/Panel/Controllers/ToolsController.php +++ b/formwork/src/Panel/Controllers/ToolsController.php @@ -12,13 +12,6 @@ final class ToolsController extends AbstractController { - /** - * All options tabs - * - * @var list - */ - private array $tabs = ['backups', 'updates', 'info']; - /** * Cached composer.json data * @@ -57,11 +50,7 @@ public function backups(): Response ]); return new Response($this->view('@panel.tools.backups', [ - 'title' => $this->translate('panel.tools.backups'), - 'tabs' => $this->view('@panel.tools.tabs', [ - 'tabs' => $this->tabs, - 'current' => 'backups', - ]), + 'title' => $this->translate('panel.tools.backups'), 'backups' => Collection::from($backups), ])); } @@ -76,11 +65,7 @@ public function updates(): Response } return new Response($this->view('@panel.tools.updates', [ - 'title' => $this->translate('panel.tools.updates'), - 'tabs' => $this->view('@panel.tools.tabs', [ - 'tabs' => $this->tabs, - 'current' => 'updates', - ]), + 'title' => $this->translate('panel.tools.updates'), 'currentVersion' => $this->app::VERSION, ])); } @@ -220,11 +205,7 @@ public function info(): Response ksort($data['HTTP Response Headers']); return new Response($this->view('@panel.tools.info', [ - 'title' => $this->translate('panel.tools.info'), - 'tabs' => $this->view('@panel.tools.tabs', [ - 'tabs' => $this->tabs, - 'current' => 'info', - ]), + 'title' => $this->translate('panel.tools.info'), 'formwork' => $formwork, 'warnings' => $warnings, 'info' => $data, diff --git a/formwork/src/Panel/Navigation/NavigationItem.php b/formwork/src/Panel/Navigation/NavigationItem.php index ba2ea9341..fe1fcb8e2 100644 --- a/formwork/src/Panel/Navigation/NavigationItem.php +++ b/formwork/src/Panel/Navigation/NavigationItem.php @@ -2,19 +2,26 @@ namespace Formwork\Panel\Navigation; -use Formwork\Data\Contracts\Arrayable; -use Formwork\Data\Traits\DataArrayable; +use Formwork\Data\Contracts\ArraySerializable; -class NavigationItem implements Arrayable +class NavigationItem implements ArraySerializable { - use DataArrayable; + /** + * @var array + */ + protected array $data = []; /** * @param array $data */ public function __construct(protected string $id, array $data) { - $this->data = $data; + foreach ($data as $key => $value) { + if ($key === 'children') { + $value = NavigationItemCollection::fromArray($value); + } + $this->data[$key] = $value; + } } /** @@ -46,7 +53,7 @@ public function uri(): string */ public function permissions(): ?string { - return $this->data['permissions']; + return $this->data['permissions'] ?? null; } /** @@ -76,4 +83,26 @@ public function visible(): bool { return $this->data['visible'] ?? true; } + + /** + * Get navigation item children + */ + public function children(): ?NavigationItemCollection + { + return $this->data['children'] ?? null; + } + + public function toArray(): array + { + $data = $this->data; + if (isset($data['children'])) { + $data['children'] = $data['children']->toArray(); + } + return [...$data, 'id' => $this->id]; + } + + public static function fromArray(array $data): self + { + return new self($data['id'], $data); + } } diff --git a/formwork/src/Panel/Navigation/NavigationItemCollection.php b/formwork/src/Panel/Navigation/NavigationItemCollection.php index e87c11932..5307a2e73 100644 --- a/formwork/src/Panel/Navigation/NavigationItemCollection.php +++ b/formwork/src/Panel/Navigation/NavigationItemCollection.php @@ -3,12 +3,24 @@ namespace Formwork\Panel\Navigation; use Formwork\Data\AbstractCollection; +use Formwork\Data\Contracts\ArraySerializable; +use Formwork\Utils\Arr; -class NavigationItemCollection extends AbstractCollection +class NavigationItemCollection extends AbstractCollection implements ArraySerializable { protected bool $associative = true; protected ?string $dataType = NavigationItem::class; protected bool $mutable = true; + + public function toArray(): array + { + return Arr::map($this->data, fn(NavigationItem $navigationItem) => $navigationItem->toArray()); + } + + public static function fromArray(array $data): self + { + return new self(Arr::map($data, fn(array $item, string $id) => NavigationItem::fromArray([...$item, 'id' => $id]))); + } } diff --git a/formwork/src/Panel/Panel.php b/formwork/src/Panel/Panel.php index 6e4d3de80..a2ebcad4f 100644 --- a/formwork/src/Panel/Panel.php +++ b/formwork/src/Panel/Panel.php @@ -11,14 +11,12 @@ use Formwork\Languages\LanguageCodes; use Formwork\Panel\Events\PanelNavigationLoadedEvent; use Formwork\Panel\Modals\Modals; -use Formwork\Panel\Navigation\NavigationItem; use Formwork\Panel\Navigation\NavigationItemCollection; use Formwork\Services\Container; use Formwork\Translations\Translations; use Formwork\Users\ColorScheme; use Formwork\Users\User; use Formwork\Users\Users; -use Formwork\Utils\Arr; use Formwork\Utils\FileSystem; use Formwork\Utils\Str; use Formwork\Utils\Uri; @@ -117,15 +115,20 @@ public function route(): string */ public function navigation(): NavigationItemCollection { + if (isset($this->navigation)) { + return $this->navigation; + } + $translation = $this->translations->getCurrent(); - if (!isset($this->navigation)) { - $items = $this->container->call(require $this->config->get('system.panel.config.navigation'), [ + + $this->navigation = NavigationItemCollection::fromArray( + $this->container->call(require $this->config->get('system.panel.config.navigation'), [ 'translation' => $translation, - ]); - $this->navigation = new NavigationItemCollection(); - $this->navigation->setMultiple(Arr::map($items, fn(array $data, string $id) => new NavigationItem($id, $data))); - $this->events->dispatch(new PanelNavigationLoadedEvent($this->navigation, $translation)); - } + ]) + ); + + $this->events->dispatch(new PanelNavigationLoadedEvent($this->navigation, $translation)); + return $this->navigation; } diff --git a/panel/config/navigation.php b/panel/config/navigation.php index b04dc0931..9a29a929b 100644 --- a/panel/config/navigation.php +++ b/panel/config/navigation.php @@ -9,7 +9,6 @@ 'label' => $translation->translate('panel.dashboard.dashboard'), 'uri' => '/dashboard/', 'permissions' => 'panel.dashboard', - 'badge' => null, 'icon' => 'home', ], 'pages' => [ @@ -23,14 +22,12 @@ 'label' => $translation->translate('panel.files.files'), 'uri' => '/files/', 'permissions' => 'panel.files', - 'badge' => null, 'icon' => 'files', ], 'statistics' => [ 'label' => $translation->translate('panel.statistics.statistics'), 'uri' => '/statistics/', 'permissions' => 'panel.statistics', - 'badge' => null, 'icon' => 'chart-line', ], 'users' => [ @@ -44,15 +41,42 @@ 'label' => $translation->translate('panel.options.options'), 'uri' => '/options/', 'permissions' => 'panel.options', - 'badge' => null, 'icon' => 'gear', + 'children' => [ + 'site' => [ + 'label' => $translation->translate('panel.options.site'), + 'uri' => '/options/site/', + 'permissions' => 'panel.options.site', + ], + 'system' => [ + 'label' => $translation->translate('panel.options.system'), + 'uri' => '/options/system/', + 'permissions' => 'panel.options.system', + ], + ], ], 'tools' => [ 'label' => $translation->translate('panel.tools.tools'), 'uri' => '/tools/', 'permissions' => 'panel.tools', - 'badge' => null, 'icon' => 'toolbox', + 'children' => [ + 'backups' => [ + 'label' => $translation->translate('panel.tools.backups'), + 'uri' => '/tools/backups/', + 'permissions' => 'panel.tools.backups', + ], + 'updates' => [ + 'label' => $translation->translate('panel.tools.updates'), + 'uri' => '/tools/updates/', + 'permissions' => 'panel.tools.updates', + ], + 'info' => [ + 'label' => $translation->translate('panel.tools.info'), + 'uri' => '/tools/info/', + 'permissions' => 'panel.tools.info', + ], + ], ], 'plugins' => [ 'label' => $translation->translate('panel.plugins.plugins'), @@ -63,9 +87,7 @@ 'visible' => !$app->plugins()->isEmpty(), ], 'logout' => [ - 'label' => $translation->translate('panel.login.logout'), - 'uri' => '/logout/', - 'permissions' => null, - 'badge' => null, + 'label' => $translation->translate('panel.login.logout'), + 'uri' => '/logout/', ], ]; diff --git a/panel/src/scss/components/_tabs.scss b/panel/src/scss/components/_tabs.scss index 2dce434bf..2bbd7ab5e 100644 --- a/panel/src/scss/components/_tabs.scss +++ b/panel/src/scss/components/_tabs.scss @@ -60,6 +60,10 @@ } } +.tabs-tab .icon { + margin-right: 0.375rem; +} + .tabs-panel { display: none; } diff --git a/panel/views/options/site.php b/panel/views/options/site.php index 3369d3df0..aecf14339 100644 --- a/panel/views/options/site.php +++ b/panel/views/options/site.php @@ -11,7 +11,7 @@ - + insert('@panel._navigation.tabs', ['items' => $panel->navigation()->get('options')->children(), 'current' => 'site']) ?>
insert('@panel.fields', ['fields' => $fields]) ?>
diff --git a/panel/views/options/system.php b/panel/views/options/system.php index 8d26c238a..8cc0ec69f 100644 --- a/panel/views/options/system.php +++ b/panel/views/options/system.php @@ -11,7 +11,7 @@ - + insert('@panel._navigation.tabs', ['items' => $panel->navigation()->get('options')->children(), 'current' => 'system']) ?>
insert('@panel.fields', ['fields' => $fields]) ?>
diff --git a/panel/views/options/tabs.php b/panel/views/options/tabs.php deleted file mode 100644 index 89e2d8bc1..000000000 --- a/panel/views/options/tabs.php +++ /dev/null @@ -1,7 +0,0 @@ -
- - user()->permissions()->has("panel.options.{$tab}")) : ?> - ">translate("panel.options.{$tab}") ?> - - -
\ No newline at end of file diff --git a/panel/views/partials/navigation/sidebar.php b/panel/views/partials/navigation/sidebar.php new file mode 100644 index 000000000..710bd4a6d --- /dev/null +++ b/panel/views/partials/navigation/sidebar.php @@ -0,0 +1,15 @@ + + visible() && ($item->permissions() === null || $panel->user()->permissions()->has($item->permissions()))) : ?> +
  • + + icon()) : ?> + icon($item->icon()) ?> + + escape($item->label()) ?> + badge()) : ?> + badge() ?> + + +
  • + + diff --git a/panel/views/partials/navigation/tabs.php b/panel/views/partials/navigation/tabs.php new file mode 100644 index 000000000..de1c4254d --- /dev/null +++ b/panel/views/partials/navigation/tabs.php @@ -0,0 +1,15 @@ +
    + + visible() && ($item->permissions() === null || $panel->user()->permissions()->has($item->permissions()))) : ?> + + icon()) : ?> + icon($item->icon()) ?> + + escape($item->label()) ?> + badge()) : ?> + badge() ?> + + + + +
    diff --git a/panel/views/partials/sidebar.php b/panel/views/partials/sidebar.php index b31fec0ff..ad122c94d 100644 --- a/panel/views/partials/sidebar.php +++ b/panel/views/partials/sidebar.php @@ -15,21 +15,7 @@ - \ No newline at end of file + diff --git a/panel/views/tools/backups.php b/panel/views/tools/backups.php index 1bdba5b06..6f6898b44 100644 --- a/panel/views/tools/backups.php +++ b/panel/views/tools/backups.php @@ -7,7 +7,8 @@
    translate('panel.tools.tools') ?>
    - +insert('@panel._navigation.tabs', ['items' => $panel->navigation()->get('tools')->children(), 'current' => 'backups']) ?> +
    @@ -51,4 +52,4 @@ - \ No newline at end of file + diff --git a/panel/views/tools/info.php b/panel/views/tools/info.php index 00bbdd0dd..b233ffa98 100644 --- a/panel/views/tools/info.php +++ b/panel/views/tools/info.php @@ -5,7 +5,7 @@
    translate('panel.tools.tools') ?>
    - +insert('@panel._navigation.tabs', ['items' => $panel->navigation()->get('tools')->children(), 'current' => 'info']) ?>
    @@ -44,4 +44,4 @@
    - \ No newline at end of file + diff --git a/panel/views/tools/tabs.php b/panel/views/tools/tabs.php deleted file mode 100644 index 335de6c6b..000000000 --- a/panel/views/tools/tabs.php +++ /dev/null @@ -1,7 +0,0 @@ -
    - - user()->permissions()->has("panel.tools.{$tab}")) : ?> - ">translate("panel.tools.{$tab}") ?> - - -
    \ No newline at end of file diff --git a/panel/views/tools/updates.php b/panel/views/tools/updates.php index 7c10e7418..398dc7e6d 100644 --- a/panel/views/tools/updates.php +++ b/panel/views/tools/updates.php @@ -5,7 +5,7 @@
    translate('panel.tools.tools') ?>
    - +insert('@panel._navigation.tabs', ['items' => $panel->navigation()->get('tools')->children(), 'current' => 'updates']) ?>
    @@ -25,4 +25,4 @@

    Formwork translate('panel.updates.latestVersionAvailable') ?>

    -
    \ No newline at end of file +