Merge pull request #3106 from Icinga/feature/navigation-dashboard

Navigation dashboard
This commit is contained in:
lippserd 2017-11-21 23:03:44 +01:00 committed by GitHub
commit fa7bc9aa2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 246 additions and 70 deletions

View File

@ -5,6 +5,7 @@ namespace Icinga\Controllers;
use Exception;
use Icinga\Application\Config;
use Icinga\Application\Icinga;
use Icinga\Exception\NotFoundError;
use Icinga\Data\DataArray\ArrayDatasource;
use Icinga\Data\Filter\FilterMatchCaseInsensitive;
@ -407,4 +408,25 @@ class NavigationController extends Controller
$this->httpNotFound(sprintf($this->translate('Navigation item "%s" not found'), $form->getValue('name')));
}
}
public function dashboardAction()
{
$name = $this->params->getRequired('name');
$this->getTabs()->add('dashboard', array(
'active' => true,
'label' => ucwords($name),
'url' => Url::fromRequest()
));
$menu = Icinga::app()->getMenu();
$navigation = $menu->findItem($name);
if ($navigation === null) {
$this->httpNotFound($this->translate('Navigation not found'));
}
$this->view->navigation = $navigation;
}
}

View File

@ -0,0 +1,16 @@
<div class="controls">
<?= $tabs ?>
</div>
<div class="content">
<?php foreach ($navigation as $item): /** @var \Icinga\Web\Navigation\NavigationItem $item */?>
<a class="dashboard-link" href="<?= $this->url($item->getUrl(), $item->getUrlParameters()) ?>">
<div class="link-icon">
<?= $this->icon($item->getIcon() ?: 'forward', null, array('aria-hidden' => true)) ?>
</div>
<div class="link-meta">
<div class="link-label"><?= $this->escape($item->getLabel()) ?></div>
<div class="link-description"><?= $this->escape($item->getDescription() ?: sprintf('Open %s', strtolower($item->getLabel()))) ?></div>
</div>
</a>
<?php endforeach ?>
</div>

View File

@ -302,14 +302,18 @@ class Web extends EmbeddedWeb
),
'children' => array(
'about' => array(
'label' => t('About'),
'url' => 'about',
'priority' => 700
'icon' => 'info',
'description' => t('Open about page'),
'label' => t('About'),
'url' => 'about',
'priority' => 700
),
'announcements' => array(
'label' => t('Announcements'),
'url' => 'announcements',
'priority' => 710
'icon' => 'megaphone',
'description' => t('List announcements'),
'label' => t('Announcements'),
'url' => 'announcements',
'priority' => 710
)
)
),
@ -320,28 +324,36 @@ class Web extends EmbeddedWeb
'priority' => 800,
'children' => array(
'application' => array(
'label' => t('Application'),
'url' => 'config/general',
'permission' => 'config/application/*',
'priority' => 810
'icon' => 'wrench',
'description' => t('Open application configuration'),
'label' => t('Application'),
'url' => 'config/general',
'permission' => 'config/application/*',
'priority' => 810
),
'authentication' => array(
'label' => t('Authentication'),
'permission' => 'config/authentication/*',
'priority' => 830,
'url' => 'role/list'
'icon' => 'users',
'description' => t('Open authentication configuration'),
'label' => t('Authentication'),
'permission' => 'config/authentication/*',
'priority' => 830,
'url' => 'role/list'
),
'navigation' => array(
'label' => t('Shared Navigation'),
'url' => 'navigation/shared',
'permission' => 'config/application/navigation',
'priority' => 840,
'icon' => 'sitemap',
'description' => t('Open shared navigation configuration'),
'label' => t('Shared Navigation'),
'url' => 'navigation/shared',
'permission' => 'config/application/navigation',
'priority' => 840,
),
'modules' => array(
'label' => t('Modules'),
'url' => 'config/modules',
'permission' => 'config/modules',
'priority' => 890
'icon' => 'cubes',
'description' => t('Open module configuration'),
'label' => t('Modules'),
'url' => 'config/modules',
'permission' => 'config/modules',
'priority' => 890
)
)
),
@ -352,15 +364,19 @@ class Web extends EmbeddedWeb
'priority' => 900,
'children' => array(
'account' => array(
'label' => t('My Account'),
'priority' => 100,
'url' => 'account'
'icon' => 'sliders',
'description' => t('Open your account preferences'),
'label' => t('My Account'),
'priority' => 100,
'url' => 'account'
),
'logout' => array(
'label' => t('Logout'),
'priority' => 200,
'attributes' => array('target' => '_self'),
'url' => 'authentication/logout'
'icon' => 'off',
'description' => t('Log out'),
'label' => t('Logout'),
'priority' => 200,
'attributes' => array('target' => '_self'),
'url' => 'authentication/logout'
)
)
)
@ -368,10 +384,12 @@ class Web extends EmbeddedWeb
if (Logger::writesToFile()) {
$menu['system']['children']['application_log'] = array(
'label' => t('Application Log'),
'url' => 'list/applicationlog',
'permission' => 'application/log',
'priority' => 900
'icon' => 'doc-text',
'description' => t(''),
'label' => t('Application Log'),
'url' => 'list/applicationlog',
'permission' => 'application/log',
'priority' => 900
);
}
} else {

View File

@ -363,7 +363,7 @@ class Navigation implements ArrayAccess, Countable, IteratorAggregate
*
* @return NavigationItem
*/
protected function findItem($name)
public function findItem($name)
{
$item = $this->getItem($name);
if ($item !== null) {

View File

@ -88,6 +88,13 @@ class NavigationItem implements IteratorAggregate
*/
protected $label;
/**
* The item's description
*
* @var string
*/
protected $description;
/**
* This item's parent
*
@ -481,6 +488,30 @@ class NavigationItem implements IteratorAggregate
return $this;
}
/**
* Get the item's description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set the item's description
*
* @param string $description
*
* @return $this
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Set this item's url target
*
@ -512,7 +543,7 @@ class NavigationItem implements IteratorAggregate
public function getUrl()
{
if ($this->url === null && $this->hasChildren()) {
$this->setUrl(Url::fromPath('#'));
$this->setUrl(Url::fromPath('navigation/dashboard', array('name' => strtolower($this->getName()))));
}
return $this->url;

View File

@ -162,6 +162,9 @@ class RecursiveNavigationRenderer extends RecursiveIteratorIterator implements N
foreach ($this as $item) {
/** @var NavigationItem $item */
if ($item->shouldRender()) {
if ($this->getDepth() > 0) {
$item->setIcon(null);
}
if ($this->getUseStandardItemRenderer()) {
$renderer = new NavigationItemRenderer();
$content = $renderer->render($item);

View File

@ -130,7 +130,9 @@ $section = $this->menuSection(N_('Problems'), array(
'priority' => 20
));
$section->add(N_('Host Problems'), array(
'renderer' => array(
'icon' => 'host',
'description' => $this->translate('List current host problems'),
'renderer' => array(
'MonitoringBadgeNavigationItemRenderer',
'columns' => array(
'hosts_down_unhandled' => $this->translate('%d unhandled hosts down')
@ -142,7 +144,9 @@ $section->add(N_('Host Problems'), array(
'priority' => 50
));
$section->add(N_('Service Problems'), array(
'renderer' => array(
'icon' => 'service',
'description' => $this->translate('List current service problems'),
'renderer' => array(
'MonitoringBadgeNavigationItemRenderer',
'columns' => array(
'services_critical_unhandled' => $this->translate('%d unhandled services critical')
@ -154,12 +158,16 @@ $section->add(N_('Service Problems'), array(
'priority' => 60
));
$section->add(N_('Service Grid'), array(
'url' => 'monitoring/list/servicegrid?problems',
'priority' => 70
'icon' => 'services',
'description' => $this->translate('Display service problems as grid'),
'url' => 'monitoring/list/servicegrid?problems',
'priority' => 70
));
$section->add(N_('Current Downtimes'), array(
'url' => 'monitoring/list/downtimes?downtime_is_in_effect=1',
'priority' => 80
'icon' => 'plug',
'description' => $this->translate('List current downtimes'),
'url' => 'monitoring/list/downtimes?downtime_is_in_effect=1',
'priority' => 80
));
/*
@ -170,40 +178,58 @@ $section = $this->menuSection(N_('Overview'), array(
'priority' => 30
));
$section->add(N_('Tactical Overview'), array(
'url' => 'monitoring/tactical',
'priority' => 40
'icon' => 'chart-pie',
'description' => $this->translate('Open tactical overview'),
'url' => 'monitoring/tactical',
'priority' => 40
));
$section->add(N_('Hosts'), array(
'url' => 'monitoring/list/hosts',
'priority' => 50
'icon' => 'host',
'description' => $this->translate('List hosts'),
'url' => 'monitoring/list/hosts',
'priority' => 50
));
$section->add(N_('Services'), array(
'url' => 'monitoring/list/services',
'priority' => 50
'icon' => 'service',
'description' => $this->translate('List services'),
'url' => 'monitoring/list/services',
'priority' => 50
));
$section->add(N_('Servicegroups'), array(
'url' => 'monitoring/list/servicegroups',
'priority' => 60
'icon' => 'services',
'description' => $this->translate('List service groups'),
'url' => 'monitoring/list/servicegroups',
'priority' => 60
));
$section->add(N_('Hostgroups'), array(
'url' => 'monitoring/list/hostgroups',
'priority' => 60
'icon' => 'host',
'description' => $this->translate('List host groups'),
'url' => 'monitoring/list/hostgroups',
'priority' => 60
));
$section->add(N_('Contacts'), array(
'url' => 'monitoring/list/contacts',
'priority' => 70
'icon' => 'user',
'description' => $this->translate('List contacts'),
'url' => 'monitoring/list/contacts',
'priority' => 70
));
$section->add(N_('Contactgroups'), array(
'url' => 'monitoring/list/contactgroups',
'priority' => 70
'icon' => 'users',
'description' => $this->translate('List users'),
'url' => 'monitoring/list/contactgroups',
'priority' => 70
));
$section->add(N_('Comments'), array(
'url' => 'monitoring/list/comments?comment_type=comment|comment_type=ack',
'priority' => 80
'icon' => 'chat-empty',
'description' => $this->translate('List comments'),
'url' => 'monitoring/list/comments?comment_type=comment|comment_type=ack',
'priority' => 80
));
$section->add(N_('Downtimes'), array(
'url' => 'monitoring/list/downtimes',
'priority' => 80
'icon' => 'plug',
'description' => $this->translate('List downtimes'),
'url' => 'monitoring/list/downtimes',
'priority' => 80
));
/*
@ -214,20 +240,28 @@ $section = $this->menuSection(N_('History'), array(
'priority' => 90
));
$section->add(N_('Event Grid'), array(
'priority' => 10,
'url' => 'monitoring/list/eventgrid'
'icon' => 'history',
'description' => $this->translate('Open event grid'),
'priority' => 10,
'url' => 'monitoring/list/eventgrid'
));
$section->add(N_('Event Overview'), array(
'priority' => 20,
'url' => 'monitoring/list/eventhistory?timestamp>=-7%20days'
'icon' => 'history',
'description' => $this->translate('Open event overview'),
'priority' => 20,
'url' => 'monitoring/list/eventhistory?timestamp>=-7%20days'
));
$section->add(N_('Notifications'), array(
'priority' => 30,
'url' => 'monitoring/list/notifications?notification_timestamp>=-7%20days',
'icon' => 'bell',
'description' => $this->translate('List notifications'),
'priority' => 30,
'url' => 'monitoring/list/notifications?notification_timestamp>=-7%20days',
));
$section->add(N_('Timeline'), array(
'priority' => 40,
'url' => 'monitoring/timeline'
'icon' => 'clock',
'description' => $this->translate('Open timeline'),
'priority' => 40,
'url' => 'monitoring/timeline'
));
/*
@ -243,9 +277,11 @@ $section = $this->menuSection(N_('Reporting'), array(
*/
$section = $this->menuSection(N_('System'));
$section->add(N_('Monitoring Health'), array(
'url' => 'monitoring/health/info',
'priority' => 720,
'renderer' => 'BackendAvailabilityNavigationItemRenderer'
'icon' => 'check',
'description' => $this->translate('Open monitoring health'),
'url' => 'monitoring/health/info',
'priority' => 720,
'renderer' => 'BackendAvailabilityNavigationItemRenderer'
));
/*

View File

@ -44,6 +44,56 @@
}
}
.dashboard-link {
.clearfix();
display: block;
max-width: 100%;
vertical-align: middle;
padding: 1em;
width: 36em;
&:hover {
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
-webkit-background-clip: padding-box;
-moz-background-clip: padding;
background-clip: padding-box;
-webkit-box-shadow: 0 0 0.5em 0 rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0 0 0.5em 0 rgba(0, 0, 0, 0.2);
box-shadow: 0 0 0.5em 0 rgba(0, 0, 0, 0.2);
background-color: @tr-hover-color;
text-decoration: none;
}
}
.link-meta {
display: table-cell;
vertical-align: middle;
}
.link-label {
font-weight: @font-weight-bold;
}
.link-description {
color: @text-color-light;
}
.link-icon {
display: table-cell;
padding-right: .5em;
vertical-align: middle;
> i {
font-size: 3em;
opacity: 0.7;
}
}
table.historycolorgrid {
font-size: 1.5em;
}