Redesign state badges for acknowledged nodes

Add and group state badges for acknowkedeged nodes based on state.
This commit is contained in:
Ravi Kumar Kempapura Srinivasa 2021-09-13 16:11:51 +02:00 committed by Johannes Meyer
parent 711677f903
commit f0aae66544
8 changed files with 240 additions and 95 deletions

View file

@ -59,3 +59,6 @@ $this->provideRestriction(
$this->provideJsFile('vendor/Sortable.js');
$this->provideJsFile('behavior/sortable.js');
$this->provideJsFile('vendor/jquery.fn.sortable.js');
$this->provideCssFile('state-badge.less');
$this->provideCssFile('state-badges.less');

View file

@ -30,15 +30,15 @@ class BpNode extends Node
protected $stateOverrides = [];
protected static $emptyStateSummary = array(
'OK' => 0,
'WARNING' => 0,
'CRITICAL' => 0,
'UNKNOWN' => 0,
'PENDING' => 0,
'UP' => 0,
'DOWN' => 0,
'UNREACHABLE' => 0,
'MISSING' => 0,
'CRITICAL' => 0,
'CRITICAL-HANDLED' => 0,
'WARNING' => 0,
'WARNING-HANDLED' => 0,
'UNKNOWN' => 0,
'UNKNOWN-HANDLED' => 0,
'OK' => 0,
'PENDING' => 0,
'MISSING' => 0,
);
protected static $sortStateInversionMap = array(
@ -74,7 +74,23 @@ class BpNode extends Node
$this->counters['MISSING']++;
} else {
$state = $child->getStateName($this->getChildState($child));
$this->counters[$state]++;
if ($child->isHandled()) {
$state = $state . '-HANDLED';
}
if ($state === 'DOWN') {
$this->counters['CRITICAL']++;
} elseif ($state === 'DOWN-HANDLED') {
$this->counters['CRITICAL-HANDLED']++;
} elseif ($state === 'UNREACHABLE') {
$this->counters['UNKNOWN']++;
} elseif ($state === 'UNREACHABLE-HANDLED') {
$this->counters['UNKNOWN-HANDLED']++;
} elseif ($state === 'UP') {
$this->counters['OK']++;
} else {
$this->counters[$state]++;
}
}
}
}

View file

@ -9,6 +9,7 @@ use Icinga\Module\Businessprocess\ImportedNode;
use Icinga\Module\Businessprocess\MonitoredNode;
use Icinga\Module\Businessprocess\Node;
use Icinga\Module\Businessprocess\Web\Url;
use Icinga\Module\Businessprocess\Widget\StateBadge;
use ipl\Html\BaseHtmlElement;
use ipl\Html\Html;
use ipl\Html\HtmlDocument;
@ -135,34 +136,39 @@ abstract class Renderer extends HtmlDocument
* @param $summary
* @return BaseHtmlElement
*/
public function renderStateBadges($summary)
public function renderStateBadges($summary, $totalChildren)
{
$elements = [];
foreach ($summary as $state => $cnt) {
if ($cnt === 0
|| $state === 'OK'
|| $state === 'UP'
) {
continue;
}
$elements[] = Html::tag(
'span',
[
'class' => [
'badge',
'badge-' . strtolower($state)
],
// TODO: We should translate this in this module
'title' => mt('monitoring', $state)
$itemCount = Html::tag(
'span',
[
'class' => [
'item-count',
],
$cnt
);
}
'title' => sprintf('%u %s', $totalChildren, mtp(
'businessprocess',
'Child',
'Children',
$totalChildren,
'businessprocess.nodes'
))
],
$totalChildren
);
$elements[] = array_filter([
$this->createBadgeGroup($summary, 'CRITICAL'),
$this->createBadgeGroup($summary, 'UNKNOWN'),
$this->createBadgeGroup($summary, 'WARNING'),
$this->createBadge($summary, 'OK'),
$this->createBadge($summary, 'MISSING'),
$this->createBadge($summary, 'PENDING')
]);
if (!empty($elements)) {
$container = Html::tag('div', ['class' => 'badges']);
$container = Html::tag('ul', ['class' => 'state-badges']);
$container->add($itemCount);
foreach ($elements as $element) {
$container->add($element);
}
@ -172,6 +178,33 @@ abstract class Renderer extends HtmlDocument
return null;
}
protected function createBadge($summary, $state)
{
if ($summary[$state] !== 0) {
return Html::tag('li', new StateBadge($summary[$state], $state));
}
return null;
}
protected function createBadgeGroup($summary, $state)
{
$content = [];
if ($summary[$state] !== 0) {
$content[] = Html::tag('li', new StateBadge($summary[$state], $state));
}
if ($summary[$state . '-HANDLED'] !== 0) {
$content[] = Html::tag('li', new StateBadge($summary[$state . '-HANDLED'], $state, true));
}
if (empty($content)) {
return null;
}
return Html::tag('li', Html::tag('ul', $content));
}
public function getNodeClasses(Node $node)
{
if ($node->isMissing()) {

View file

@ -129,24 +129,7 @@ class NodeTile extends BaseHtmlElement
}
if ($node instanceof BpNode && !$renderer->isBreadcrumb()) {
$this->add(Html::tag(
'p',
['class' => 'children-count'],
$node->hasChildren()
? Html::tag(
'span',
null,
sprintf('%u %s', $node->countChildren(), mtp(
'businessprocess',
'Child',
'Children',
$node->countChildren(),
'businessprocess.nodes'
))
)
: null
));
$this->add($renderer->renderStateBadges($node->getStateSummary()));
$this->add($renderer->renderStateBadges($node->getStateSummary(), $node->countChildren()));
}
return parent::render();

View file

@ -0,0 +1,47 @@
<?php
namespace Icinga\Module\Businessprocess\Widget;
use ipl\Html\BaseHtmlElement;
class StateBadge extends BaseHtmlElement
{
protected $defaultAttributes = ['class' => 'state-badge'];
/** @var mixed Badge content */
protected $content;
/** @var bool Whether the state is handled */
protected $isHandled;
/** @var string Textual representation of a state */
protected $state;
/**
* Create a new state badge
*
* @param mixed $content Content of the badge
* @param string $state Textual representation of a state
* @param bool $isHandled True if state is handled
*/
public function __construct($content, $state, $isHandled = false, $group = false)
{
$this->content = $content;
$this->isHandled = $isHandled;
$this->state = strtolower($state);
}
protected function assemble()
{
$this->setTag('span');
$class = "state-{$this->state}";
if ($this->isHandled) {
$class .= ' handled';
}
$this->addAttributes(['class' => $class]);
$this->add($this->content);
}
}

View file

@ -330,19 +330,6 @@ ul.bp {
}
}
}
.badge {
margin-top: 0.25em;
text-decoration: none;
&:last-child {
margin-right: 0;
}
&:hover {
box-shadow: 0px 0px 5px @gray-light;
}
}
}
.dashboard-tile,
@ -376,35 +363,31 @@ ul.bp {
}
/** END Dashboard **/
/** BEGIN Badges **/
.badges {
background-color: fade(@body-bg-color, 50%);
border-radius: 0.45em;
display: block;
padding: 0.3em 0.4em;
.badge {
border: 1px solid @body-bg-color;
margin: 0;
}
// State summary badges
.state-badges {
.state-badges();
}
div.bp .badges {
// Node children count
.item-count {
font-size: 1em;
text-align: center;
color: @text-color-inverted;
}
div.bp .state-badges {
display: inline-block;
padding-top: 0;
}
td > a > .badges {
td > a > .state-badges {
background-color: transparent;
}
.badge-critical, .badge-down { background: @color-critical; }
.badge-unknown, .badge-unreachable { background: @color-unknown; }
.badge-warning { background: @color-warning }
.badge-pending { background: @color-pending }
.badge-missing { background: @gray-semilight; color: @text-color-on-icinga-blue; }
.state-badge.state-missing {
background: @gray-semilight;
color: @text-color-on-icinga-blue;
}
/** END Badges **/
/** BEGIN Tiles **/
@ -431,7 +414,11 @@ td > a > .badges {
cursor: pointer;
position: relative;
.badges {
.item-count {
margin-right: .5em;
}
.state-badges {
position: absolute;
bottom: 0;
right: 0;
@ -457,17 +444,6 @@ td > a > .badges {
padding: 1em 1em 0;
font-weight: bold;
word-wrap: break-word;
& + p.children-count {
margin: 0;
font-size: .5em;
text-align: center;
span {
font-size: .8em;
font-weight: bold;
}
}
}
&:hover {

View file

@ -0,0 +1,60 @@
.state-badge {
.rounded-corners();
color: @text-color-on-icinga-blue;
display: inline-block;
font-size: .8em;
min-width: 2em;
padding: .25em;
text-align: center;
border: 1px solid black;
&.state-critical {
background-color: @color-critical
}
&.state-critical.handled {
background-color: @color-critical-handled
}
&.state-down {
background-color: @color-down
}
&.state-down.handled {
background-color: @color-down-handled
}
&.state-ok {
background-color: @color-ok
}
&.state-pending {
background-color: @color-pending
}
&.state-unknown {
background-color: @color-unknown
}
&.state-unknown.handled {
background-color: @color-unknown-handled
}
&.state-up {
background-color: @color-up
}
&.state-warning {
background-color: @color-warning
}
&.state-warning.handled {
background-color: @color-warning-handled
}
}
a .state-badge {
&:hover {
filter: brightness(80%);
}
}

View file

@ -0,0 +1,27 @@
.state-badges() {
&.state-badges {
padding: 0;
ul {
padding: 0;
}
li {
display: inline-block;
}
li > ul > li:first-child:not(:last-child) .state-badge {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}
li > ul > li:last-child:not(:first-child) .state-badge {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
}
> li:not(:last-child) {
margin-right: .25em;
}
}
}