1: <?php
2:
3: declare(strict_types=1);
4:
5: namespace Atk4\Ui\Layout;
6:
7: use Atk4\Ui\Header;
8: use Atk4\Ui\Icon;
9: use Atk4\Ui\Js\Jquery;
10: use Atk4\Ui\Js\JsBlock;
11: use Atk4\Ui\Layout;
12: use Atk4\Ui\Menu;
13: use Atk4\Ui\MenuItem;
14:
15: /**
16: * Implements a classic 100% width admin layout.
17: *
18: * Optional left menu in inverse with fixed width is most suitable for contextual navigation or
19: * providing core object list (e.g. folders in mail)
20: *
21: * Another menu on the top for actions that can have a pull-down menus.
22: *
23: * A top-right spot is for user icon or personal menu, labels or stats.
24: *
25: * On top of the content there is automated title showing page title but can also work as a bread-crumb or container for buttons.
26: *
27: * Footer for a short copyright notice and perhaps some debug elements.
28: *
29: * Spots:
30: * - LeftMenu (has_menuLeft)
31: * - Menu
32: * - RightMenu (has_menuRight)
33: * - Footer
34: *
35: * - Content
36: */
37: class Admin extends Layout implements NavigableInterface
38: {
39: /** @var Menu Top horizontal menu */
40: public $menu;
41: /** @var Menu|null Left vertical menu */
42: public $menuLeft;
43: /** @var Menu Right vertical menu pull-down */
44: public $menuRight;
45:
46: /** @var MenuItem */
47: public $burger;
48:
49: /** @var bool Whether or not left Menu is visible on Page load. */
50: public $isMenuLeftVisible = true;
51:
52: public $defaultTemplate = 'layout/admin.html';
53:
54: #[\Override]
55: protected function init(): void
56: {
57: parent::init();
58:
59: if ($this->menu === null) {
60: $this->menu = Menu::addTo(
61: $this,
62: ['inverted fixed horizontal atk-admin-top-menu', 'element' => 'header'],
63: ['TopMenu']
64: );
65: $this->burger = $this->menu->addItem(['class' => ['icon']]);
66: $this->burger->on('click', new JsBlock([
67: (new Jquery('.atk-sidenav'))->toggleClass('visible'),
68: (new Jquery('body'))->toggleClass('atk-sidenav-visible'),
69: ]));
70: Icon::addTo($this->burger, ['content']);
71:
72: Header::addTo($this->menu, [$this->getApp()->title, 'size' => 4]);
73: }
74:
75: if ($this->menuRight === null) {
76: $this->menuRight = Menu::addTo($this->menu, ['ui' => false], ['RightMenu'])
77: ->addClass('right menu')->removeClass('item');
78: }
79:
80: if ($this->menuLeft === null) {
81: $this->menuLeft = Menu::addTo($this, ['ui' => 'atk-sidenav-content'], ['LeftMenu']);
82: }
83:
84: $this->template->trySet('version', $this->getApp()->version);
85: }
86:
87: #[\Override]
88: public function addMenuGroup($seed): Menu
89: {
90: return $this->menuLeft->addGroup($seed);
91: }
92:
93: #[\Override]
94: public function addMenuItem($name, $action = null, $group = null): MenuItem
95: {
96: if ($group) {
97: return $group->addItem($name, $action);
98: }
99:
100: return $this->menuLeft->addItem($name, $action);
101: }
102:
103: #[\Override]
104: protected function renderView(): void
105: {
106: if (count($this->menuLeft->elements) === 0) {
107: // no items were added, so lets add dashboard
108: $this->menuLeft->addItem(['Dashboard', 'icon' => 'dashboard'], ['index']);
109: }
110: if (!$this->isMenuLeftVisible) {
111: $this->template->tryDel('CssVisibility');
112: }
113:
114: parent::renderView();
115: }
116: }
117: