Merge branch 'feature/navigation-unhandled-badges-7114'

resolves #7114
This commit is contained in:
Matthias Jentsch 2014-09-05 18:14:44 +02:00
commit 949ea1cc9b
9 changed files with 234 additions and 4 deletions

View File

@ -4,6 +4,7 @@
namespace Icinga\Web;
use Icinga\Web\Menu\MenuItemRenderer;
use RecursiveIterator;
use Zend_Config;
use Icinga\Application\Config;
@ -62,6 +63,13 @@ class Menu implements RecursiveIterator
protected $subMenus = array();
/**
* A custom item renderer used instead of the default rendering logic
*
* @var MenuItemRenderer
*/
protected $itemRenderer = null;
/*
* Parent menu
*
* @var Menu
@ -93,6 +101,15 @@ class Menu implements RecursiveIterator
if ($props !== null) {
foreach ($props as $key => $value) {
$method = 'set' . implode('', array_map('ucfirst', explode('_', strtolower($key))));
if ($key === 'renderer') {
$class = '\Icinga\Web\Menu\\' . $value;
if (!class_exists($class)) {
throw new ConfigurationError(
sprintf('ItemRenderer with class "%s" does not exist', $class)
);
}
$value = new $class;
}
if (method_exists($this, $method)) {
$this->{$method}($value);
} else {
@ -364,6 +381,26 @@ class Menu implements RecursiveIterator
return $this->icon;
}
/**
* Get the class that renders the current menu item
*
* @return MenuItemRenderer
*/
public function getRenderer()
{
return $this->itemRenderer;
}
/**
* Set the class that renders the current menu item
*
* @param MenuItemRenderer $renderer
*/
public function setRenderer(MenuItemRenderer $renderer)
{
$this->itemRenderer = $renderer;
}
/**
* Return whether this menu has any sub menus
*

View File

@ -0,0 +1,14 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Menu;
use Icinga\Web\Menu;
/**
* Renders the html content of a single menu item
*/
interface MenuItemRenderer {
public function render(Menu $menu);
}

View File

@ -0,0 +1,39 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Menu;
use Icinga\Module\Monitoring\Backend;
use Icinga\Web\Menu;
use Icinga\Web\Url;
class ProblemMenuItemRenderer implements MenuItemRenderer {
public function render(Menu $menu)
{
$statusSummary = Backend::createBackend()
->select()->from(
'statusSummary',
array(
'hosts_down_unhandled',
'services_critical_unhandled'
)
)->getQuery()->fetchRow();
$unhandled = $statusSummary->hosts_down_unhandled + $statusSummary->services_critical_unhandled;
$badge = '';
if ($unhandled) {
$badge = sprintf(
'<div class="badge-container"><span class="badge badge-critical">%s</span></div>',
$unhandled
);
}
return sprintf(
'<a href="%s">%s%s %s</a>',
$menu->getUrl() ?: '#',
$menu->getIcon() ? '<img src="' . Url::fromPath($menu->getIcon()) . '" class="icon" /> ' : '',
htmlspecialchars($menu->getTitle()),
$badge
);
}
}

View File

@ -0,0 +1,37 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Menu;
use Icinga\Module\Monitoring\Backend;
use Icinga\Web\Menu;
use Icinga\Web\Url;
class UnhandledHostMenuItemRenderer implements MenuItemRenderer {
public function render(Menu $menu)
{
$statusSummary = Backend::createBackend()
->select()->from(
'statusSummary',
array(
'hosts_down_unhandled'
)
)->getQuery()->fetchRow();
$badge = '';
if ($statusSummary->hosts_down_unhandled) {
$badge = sprintf(
'<div class="badge-container"><span class="badge badge-critical">%s</span></div>',
$statusSummary->hosts_down_unhandled
);
}
return sprintf(
'<a href="%s">%s%s %s</a>',
$menu->getUrl() ?: '#',
$menu->getIcon() ? '<img src="' . Url::fromPath($menu->getIcon()) . '" class="icon" /> ' : '',
htmlspecialchars($menu->getTitle()),
$badge
);
}
}

View File

@ -0,0 +1,37 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Web\Menu;
use Icinga\Module\Monitoring\Backend;
use Icinga\Web\Menu;
use Icinga\Web\Url;
class UnhandledServiceMenuItemRenderer implements MenuItemRenderer {
public function render(Menu $menu)
{
$statusSummary = Backend::createBackend()
->select()->from(
'statusSummary',
array(
'services_critical_unhandled'
)
)->getQuery()->fetchRow();
$badge = '';
if ($statusSummary->services_critical_unhandled) {
$badge = sprintf(
'<div class="badge-container"><span class="badge badge-critical">%s</span></div>',
$statusSummary->services_critical_unhandled
);
}
return sprintf(
'<a href="%s">%s%s %s</a>',
$menu->getUrl() ?: '#',
$menu->getIcon() ? '<img src="' . Url::fromPath($menu->getIcon()) . '" class="icon" /> ' : '',
htmlspecialchars($menu->getTitle()),
$badge
);
}
}

View File

@ -91,6 +91,9 @@ class MenuRenderer extends RecursiveIteratorIterator
*/
public function renderChild(Menu $child)
{
if ($child->getRenderer() !== null) {
return $child->getRenderer()->render($child);
}
return sprintf(
'<a href="%s">%s%s</a>',
$child->getUrl() ?: '#',

View File

@ -31,14 +31,17 @@ $this->provideSearchUrl($this->translate('Servicegroups'), 'monitoring/list/serv
* Problems Section
*/
$section = $this->menuSection($this->translate('Problems'), array(
'icon' => 'img/icons/error.png',
'priority' => 20
'renderer' => 'ProblemMenuItemRenderer',
'icon' => 'img/icons/error.png',
'priority' => 20
));
$section->add($this->translate('Unhandled Hosts'), array(
'renderer' => 'UnhandledHostMenuItemRenderer',
'url' => 'monitoring/list/hosts?host_problem=1&host_handled=0',
'priority' => 40
));
$section->add($this->translate('Unhandled Services'), array(
'renderer' => 'UnhandledServiceMenuItemRenderer',
'url' => 'monitoring/list/services?service_problem=1&service_handled=0&sort=service_severity',
'priority' => 40
));

View File

@ -26,7 +26,6 @@
#menu li {
margin-left: 0.5em;
margin-right: 0.5em;
}
#menu > ul > li {
@ -159,7 +158,7 @@
}
#menu li.hover > ul a {
width: 100%;
width: 95%;
display: block;
color: white;
}

View File

@ -179,3 +179,64 @@ ul.tree li a.error:hover {
padding: 1.5em;
height: 80vh;
}
.badge-container {
font-size: 1em;
display: inline-block;
float: right;
margin-right: 0.6em;
}
li li .badge-container {
/*
fix margin for smaller font-size of list elements
1 = 0,8em / 0.8em
*/
margin-right: 0.75em;
}
#layout.hoveredmenu .hover > a > .badge-container {
margin-right: 14.15em;
}
.badge {
position: relative;
top: -0.2em;
display: inline-block;
min-width: 1em;
padding: 3px 7px;
font-size: 0.8em;
font-weight: 700;
line-height: 1.1em;
color: white;
text-align: center;
white-space: nowrap;
vertical-align: baseline;
border-radius: 1em;
background-color: @colorInvalid;
}
li li .badge {
font-size: 0.975em;
}
.badge-critical {
background-color: @colorCritical;
}
.badge-warning {
background-color: @colorWarning;
}
.badge-ok {
background-color: @colorOk;
}
.badge-pending {
background-color: @colorPending;
}
.badge-pending {
background-color: @colorUnknown;
}