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

View File

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

View File

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

View File

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

View File

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