Merge pull request #3106 from Icinga/feature/navigation-dashboard
Navigation dashboard
This commit is contained in:
commit
fa7bc9aa2d
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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'
|
||||
));
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue