Decouple menu and dashboard code

This commit is contained in:
Johannes Meyer 2022-04-20 12:56:35 +02:00
parent 8df2c9ea8c
commit 63802dfc45
5 changed files with 110 additions and 120 deletions

View File

@ -35,11 +35,12 @@ class DashboardsController extends CompatController
$this->dashboard = new Dashboard();
$this->dashboard->setUser($this->Auth()->getUser());
$this->dashboard->setTabs($this->getTabs());
$this->dashboard->load();
}
public function indexAction()
{
$this->dashboard->load(DashboardHome::DEFAULT_HOME);
$this->createTabs();
$activeHome = $this->dashboard->getActiveHome();
@ -73,10 +74,7 @@ class DashboardsController extends CompatController
*/
public function homeAction()
{
$home = $this->params->getRequired('home');
if (! $this->dashboard->hasEntry($home)) {
$this->httpNotFound(sprintf(t('Home "%s" not found'), $home));
}
$this->dashboard->load($this->params->getRequired('home'));
$activeHome = $this->dashboard->getActiveHome();
if (! $activeHome->getEntries()) {
@ -101,6 +99,7 @@ class DashboardsController extends CompatController
public function newHomeAction()
{
$this->setTitle(t('Add new Dashboard Home'));
$this->dashboard->load();
$paneForm = (new NewHomePaneForm($this->dashboard))
->on(NewHomePaneForm::ON_SUCCESS, function () {
@ -114,12 +113,17 @@ class DashboardsController extends CompatController
public function editHomeAction()
{
$this->setTitle(t('Update Home'));
$this->dashboard->load();
$home = $this->params->getRequired('home');
if (! $this->dashboard->hasEntry($home)) {
$this->httpNotFound(sprintf(t('Home "%s" not found'), $home));
}
// TODO: Shouldn't be necessary. load() should get the name already and
// the form should otherwise ensure it has the required data
$this->dashboard->activateHome($this->dashboard->getEntry($home));
$homeForm = (new HomePaneForm($this->dashboard))
->on(HomePaneForm::ON_SUCCESS, function () {
$this->redirectNow(Url::fromPath(Dashboard::BASE_ROUTE . '/settings'));
@ -133,12 +137,17 @@ class DashboardsController extends CompatController
public function removeHomeAction()
{
$this->setTitle(t('Remove Home'));
$this->dashboard->load();
$home = $this->params->getRequired('home');
if (! $this->dashboard->hasEntry($home)) {
$this->httpNotFound(sprintf(t('Home "%s" not found'), $home));
}
// TODO: Shouldn't be necessary. load() should get the name already and
// the form should otherwise ensure it has the required data
$this->dashboard->activateHome($this->dashboard->getEntry($home));
$homeForm = (new RemoveHomePaneForm($this->dashboard))
->on(RemoveHomePaneForm::ON_SUCCESS, function () {
$this->redirectNow(Url::fromPath(Dashboard::BASE_ROUTE . '/settings'));
@ -151,12 +160,17 @@ class DashboardsController extends CompatController
public function newPaneAction()
{
$this->setTitle(t('Add new Dashboard'));
$this->dashboard->load();
$home = $this->params->getRequired('home');
if (! $this->dashboard->hasEntry($home)) {
$this->httpNotFound(sprintf(t('Home "%s" not found'), $home));
}
// TODO: Shouldn't be necessary. load() should get the name already and
// the form should otherwise ensure it has the required data
$this->dashboard->activateHome($this->dashboard->getEntry($home));
$paneForm = (new NewHomePaneForm($this->dashboard))
->on(NewHomePaneForm::ON_SUCCESS, function () {
$this->redirectNow(Url::fromPath(Dashboard::BASE_ROUTE . '/settings'));
@ -169,6 +183,7 @@ class DashboardsController extends CompatController
public function editPaneAction()
{
$this->setTitle(t('Update Pane'));
$this->dashboard->load();
$pane = $this->params->getRequired('pane');
$home = $this->params->getRequired('home');
@ -177,6 +192,10 @@ class DashboardsController extends CompatController
$this->httpNotFound(sprintf(t('Home "%s" not found'), $home));
}
// TODO: Shouldn't be necessary. load() should get the name already and
// the form should otherwise ensure it has the required data
$this->dashboard->activateHome($this->dashboard->getEntry($home));
if (! $this->dashboard->getActiveHome()->hasEntry($pane)) {
$this->httpNotFound(sprintf(t('Pane "%s" not found'), $pane));
}
@ -195,6 +214,7 @@ class DashboardsController extends CompatController
public function removePaneAction()
{
$this->setTitle(t('Remove Pane'));
$this->dashboard->load();
$home = $this->params->getRequired('home');
$paneParam = $this->params->getRequired('pane');
@ -203,6 +223,10 @@ class DashboardsController extends CompatController
$this->httpNotFound(sprintf(t('Home "%s" not found'), $home));
}
// TODO: Shouldn't be necessary. load() should get the name already and
// the form should otherwise ensure it has the required data
$this->dashboard->activateHome($this->dashboard->getEntry($home));
if (! $this->dashboard->getActiveHome()->hasEntry($paneParam)) {
$this->httpNotFound(sprintf(t('Pane "%s" not found'), $paneParam));
}
@ -224,6 +248,8 @@ class DashboardsController extends CompatController
$this->setTitle(t('Select Dashlets'));
}
$this->dashboard->load();
$dashletForm = new DashletForm($this->dashboard);
$dashletForm->populate($this->getRequest()->getPost());
$dashletForm->on(DashletForm::ON_SUCCESS, function () {
@ -236,6 +262,7 @@ class DashboardsController extends CompatController
public function editDashletAction()
{
$this->setTitle(t('Edit Dashlet'));
$this->dashboard->load();
$pane = $this->validateDashletParams();
$dashlet = $pane->getEntry($this->getParam('dashlet'));
@ -255,6 +282,8 @@ class DashboardsController extends CompatController
public function removeDashletAction()
{
$this->setTitle(t('Remove Dashlet'));
$this->dashboard->load();
$this->validateDashletParams();
$removeForm = (new RemoveDashletForm($this->dashboard))
@ -281,6 +310,8 @@ class DashboardsController extends CompatController
$originals = $dashboards['originals'];
unset($dashboards['originals']);
$this->dashboard->load();
$orgHome = null;
$orgPane = null;
if ($originals && isset($originals['originalHome'])) {
@ -402,6 +433,8 @@ class DashboardsController extends CompatController
$this->setTitle(t('Add Dashlet'));
}
$this->dashboard->load();
$setupForm = new SetupNewDashboardForm($this->dashboard);
$setupForm->on(SetupNewDashboardForm::ON_SUCCESS, function () use ($setupForm) {
$this->redirectNow($setupForm->getRedirectUrl());
@ -412,7 +445,9 @@ class DashboardsController extends CompatController
public function settingsAction()
{
$this->dashboard->load();
$this->createTabs();
$activeHome = $this->dashboard->getActiveHome();
// We can't grant access the user to the dashboard manager if there aren't any dashboards to manage
if (! $activeHome || (! $activeHome->hasEntries() && count($this->dashboard->getEntries()) === 1)) {
@ -445,8 +480,7 @@ class DashboardsController extends CompatController
{
$tabs = $this->dashboard->getTabs();
$activeHome = $this->dashboard->getActiveHome();
if (($activeHome && $activeHome->hasEntries()) ||
($activeHome && ! $activeHome->isDisabled() && count($this->dashboard->getEntries()) > 1)) {
if ($activeHome && ($activeHome->getName() !== DashboardHome::DEFAULT_HOME || $activeHome->hasEntries())) {
$tabs->extend(new DashboardSettings());
}
@ -463,6 +497,10 @@ class DashboardsController extends CompatController
$this->httpNotFound(sprintf(t('Home "%s" not found'), $home));
}
// TODO: Shouldn't be necessary. load() should get the name already and
// the form should otherwise ensure it has the required data
$this->dashboard->activateHome($this->dashboard->getEntry($home));
if (! $this->dashboard->getActiveHome()->hasEntry($pane)) {
$this->httpNotFound(sprintf(t('Pane "%s" not found'), $pane));
}

View File

@ -5,9 +5,9 @@
namespace Icinga\Web\Dashboard\Common;
use Icinga\Application\Icinga;
use Icinga\Application\Modules\DashletContainer;
use Icinga\Authentication\Auth;
use Icinga\Common\Database;
use Icinga\Exception\Http\HttpNotFoundException;
use Icinga\Exception\ProgrammingError;
use Icinga\Model;
use Icinga\User;
@ -15,13 +15,9 @@ use Icinga\Web\Dashboard\Dashboard;
use Icinga\Web\Dashboard\DashboardHome;
use Icinga\Web\Dashboard\Dashlet;
use Icinga\Web\Dashboard\Pane;
use Icinga\Web\Menu;
use Icinga\Web\Navigation\DashboardPane;
use ipl\Orm\Query;
use ipl\Sql\Connection;
use ipl\Sql\Expression;
use ipl\Stdlib\Filter;
use ipl\Web\Url;
trait DashboardManager
{
@ -40,12 +36,46 @@ trait DashboardManager
*/
private static $defaultPanes = [];
public function load()
/**
* Load the given or all homes (null)
*
* @param ?string $name
*
* @return void
*/
public function load(string $name = null)
{
$this->setEntries((new Menu())->loadHomes());
$this->loadDashboardEntries();
$query = Model\Home::on(self::getConn());
$query->filter(Filter::equal('username', $this::getUser()->getUsername()));
if ($name !== null) {
$query->filter(Filter::equal('name', $name));
/** @var Model\Home $row */
if (($row = $query->first()) === null) {
if ($name === DashboardHome::DEFAULT_HOME) {
$home = $this->initGetDefaultHome();
} else {
throw new HttpNotFoundException(t('Home "%s" not found'), $name);
}
} else {
$home = DashboardHome::create($row);
$this->addEntry($home);
}
$this->activateHome($home);
$home->loadDashboardEntries();
} else {
foreach ($query as $row) {
$this->addEntry(DashboardHome::create($row));
}
if (($firstHome = $this->rewindEntries())) {
$this->activateHome($firstHome);
$firstHome->loadDashboardEntries();
}
}
$this->initGetDefaultHome();
self::deployModuleDashlets();
}
@ -81,25 +111,7 @@ trait DashboardManager
public function loadDashboardEntries(string $name = '')
{
if ($name && $this->hasEntry($name)) {
$home = $this->getEntry($name);
} else {
$requestRoute = Url::fromRequest();
if ($requestRoute->getPath() === Dashboard::BASE_ROUTE) {
$home = $this->initGetDefaultHome();
} else {
$homeParam = $requestRoute->getParam('home');
if (empty($homeParam) || ! $this->hasEntry($homeParam)) {
if (! ($home = $this->rewindEntries())) {
// No dashboard homes
return $this;
}
} else {
$home = $this->getEntry($homeParam);
}
}
}
$home = $this->getEntry($name);
$this->activateHome($home);
$home->loadDashboardEntries();

View File

@ -5,10 +5,10 @@
namespace Icinga\Web\Dashboard;
use Icinga\Exception\ProgrammingError;
use Icinga\Model\Home;
use Icinga\Web\Dashboard\Common\BaseDashboard;
use Icinga\Web\Dashboard\Common\DashboardControls;
use Icinga\Web\Dashboard\Common\Sortable;
use Icinga\Web\Navigation\DashboardHomeItem;
use ipl\Stdlib\Filter;
use function ipl\Stdlib\get_php_type;
@ -53,21 +53,21 @@ class DashboardHome extends BaseDashboard implements Sortable
protected $disabled = false;
/**
* Create a new dashboard home from the given home item
* Create a new dashboard home from the given model
*
* @param DashboardHomeItem $homeItem
* @param Home $home
*
* @return DashboardHome
*/
public static function create(DashboardHomeItem $homeItem): self
public static function create(Home $home): self
{
$self = new self($homeItem->getName());
$self = new self($home->name);
$self
->setTitle($homeItem->getLabel())
->setPriority($homeItem->getPriority())
->setType($homeItem->getAttribute('type'))
->setUuid($homeItem->getAttribute('uuid'))
->setDisabled($homeItem->getAttribute('disabled'));
->setTitle($home->label)
->setPriority($home->priority)
->setType($home->type)
->setUuid($home->id)
->setDisabled((bool) $home->disabled);
return $self;
}

View File

@ -7,7 +7,6 @@ use Icinga\Application\Logger;
use Icinga\Authentication\Auth;
use Icinga\Model\Home;
use Icinga\Web\Dashboard\DashboardHome;
use Icinga\Web\Navigation\DashboardHomeItem;
use Icinga\Web\Navigation\Navigation;
use Icinga\Web\Dashboard\Dashboard;
use ipl\Stdlib\Filter;
@ -23,8 +22,6 @@ class Menu extends Navigation
public function __construct()
{
$this->init();
$this->initHome();
$this->load('menu-item');
}
@ -37,7 +34,8 @@ class Menu extends Navigation
'label' => t('Dashboard'),
'url' => Dashboard::BASE_ROUTE,
'icon' => 'dashboard',
'priority' => 10
'priority' => 10,
'children' => $this->fetchDashboardHomes()
]);
$this->addItem('system', [
'label' => t('System'),
@ -155,49 +153,33 @@ class Menu extends Navigation
}
}
public function initHome()
protected function fetchDashboardHomes()
{
$user = Dashboard::getUser();
$dashboardItem = $this->getItem('dashboard');
$dashboardHomes = [];
try {
$homes = Home::on(Dashboard::getConn());
$homes->filter(Filter::equal('username', $user->getUsername()));
$homes->filter(Filter::equal('username', Auth::getInstance()->getUser()->getUsername()));
foreach ($homes as $home) {
$dashboardHome = new DashboardHomeItem($home->name, [
'uuid' => $home->id,
if ($home->name === DashboardHome::DEFAULT_HOME) {
continue;
}
$dashboardHomes[$home->name] = [
'label' => t($home->label),
'priority' => $home->priority,
'type' => $home->type,
'disabled' => (bool) $home->disabled
]);
$dashboardItem->addChild($dashboardHome);
'url' => Url::fromPath(Dashboard::BASE_ROUTE . '/home', [
'home' => $home->name
])
];
}
} catch (\Exception $_) {
// Nothing to do
// Any database issue will be noticed soon enough, so prevent the Menu
// from being ruined in any case.
}
}
/**
* Load dashboard homes form the navigation menu
*
* @return DashboardHome[]
*/
public function loadHomes()
{
$homes = [];
foreach ($this->getItem('dashboard')->getChildren() as $child) {
if (! $child instanceof DashboardHomeItem) {
continue;
}
$homes[$child->getName()] = DashboardHome::create($child);
}
return $homes;
return $dashboardHomes;
}
}

View File

@ -1,42 +0,0 @@
<?php
/* Icinga Web 2 | (c) 2022 Icinga GmbH | GPLv2+ */
namespace Icinga\Web\Navigation;
use Icinga\Web\Dashboard\Dashboard;
use Icinga\Web\Dashboard\DashboardHome;
use ipl\Web\Url;
class DashboardHomeItem extends NavigationItem
{
/**
* Init this dashboard home
*
* Doesn't set the url of this dashboard home if it's the default one
* to prevent from being rendered as dropdown in the navigation bar
*
* @return void
*/
public function init()
{
if ($this->getName() !== DashboardHome::DEFAULT_HOME) {
$this->setUrl(Url::fromPath(Dashboard::BASE_ROUTE . '/home', [
'home' => $this->getName()
]));
}
}
/**
* Get this dashboard home's url
*
* Parent class would always report a default url if $this->url isn't
* set, which we do it on purpose.
*
* @return \Icinga\Web\Url
*/
public function getUrl()
{
return $this->url;
}
}