Skip to content

Commit 3486e7a

Browse files
committed
Redesign state badges for acknowledged nodes
Add and group state badges for acknowkedeged nodes based on state.
1 parent 3154e33 commit 3486e7a

File tree

8 files changed

+236
-84
lines changed

8 files changed

+236
-84
lines changed

configuration.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,5 @@
6161
$this->provideJsFile('vendor/jquery.fn.sortable.js');
6262

6363
$this->provideCssFile('state-ball.less');
64+
$this->provideCssFile('state-badge.less');
65+
$this->provideCssFile('state-badges.less');

library/Businessprocess/BpNode.php

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ class BpNode extends Node
2929
protected $stateOverrides = [];
3030

3131
protected static $emptyStateSummary = array(
32-
'OK' => 0,
33-
'WARNING' => 0,
34-
'CRITICAL' => 0,
35-
'UNKNOWN' => 0,
36-
'PENDING' => 0,
37-
'UP' => 0,
38-
'DOWN' => 0,
39-
'UNREACHABLE' => 0,
40-
'MISSING' => 0,
32+
'CRITICAL' => 0,
33+
'CRITICAL-HANDLED' => 0,
34+
'WARNING' => 0,
35+
'WARNING-HANDLED' => 0,
36+
'UNKNOWN' => 0,
37+
'UNKNOWN-HANDLED' => 0,
38+
'OK' => 0,
39+
'PENDING' => 0,
40+
'MISSING' => 0,
4141
);
4242

4343
protected static $sortStateInversionMap = array(
@@ -73,7 +73,23 @@ public function getStateSummary()
7373
$this->counters['MISSING']++;
7474
} else {
7575
$state = $child->getStateName($this->getChildState($child));
76-
$this->counters[$state]++;
76+
if ($child->isHandled()) {
77+
$state = $state . '-HANDLED';
78+
}
79+
80+
if ($state === 'DOWN') {
81+
$this->counters['CRITICAL']++;
82+
} elseif ($state === 'DOWN-HANDLED') {
83+
$this->counters['CRITICAL-HANDLED']++;
84+
} elseif ($state === 'UNREACHABLE') {
85+
$this->counters['UNKNOWN']++;
86+
} elseif ($state === 'UNREACHABLE-HANDLED') {
87+
$this->counters['UNKNOWN-HANDLED']++;
88+
} elseif ($state === 'UP') {
89+
$this->counters['OK']++;
90+
} else {
91+
$this->counters[$state]++;
92+
}
7793
}
7894
}
7995
}

library/Businessprocess/Renderer/Renderer.php

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
use Icinga\Module\Businessprocess\MonitoredNode;
1010
use Icinga\Module\Businessprocess\Node;
1111
use Icinga\Module\Businessprocess\Web\Url;
12+
use Icinga\Module\Businessprocess\Widget\StateBadge;
1213
use ipl\Html\BaseHtmlElement;
1314
use ipl\Html\Html;
1415
use ipl\Html\HtmlDocument;
16+
use Tests\Icinga\Module\Setup\TrueRequirement;
1517

1618
abstract class Renderer extends HtmlDocument
1719
{
@@ -135,34 +137,34 @@ public function countChildNodes()
135137
* @param $summary
136138
* @return BaseHtmlElement
137139
*/
138-
public function renderStateBadges($summary)
140+
public function renderStateBadges($summary, $totalChildren)
139141
{
140142
$elements = [];
141143

142-
foreach ($summary as $state => $cnt) {
143-
if ($cnt === 0
144-
|| $state === 'OK'
145-
|| $state === 'UP'
146-
) {
147-
continue;
148-
}
149-
150-
$elements[] = Html::tag(
151-
'span',
152-
[
153-
'class' => [
154-
'badge',
155-
'badge-' . strtolower($state)
156-
],
157-
// TODO: We should translate this in this module
158-
'title' => mt('monitoring', $state)
144+
$itemCount = Html::tag(
145+
'span',
146+
[
147+
'class' => [
148+
'item-count',
159149
],
160-
$cnt
161-
);
162-
}
150+
// TODO: We should translate this in this module
151+
'title' => mt('monitoring', 'widget')
152+
],
153+
$totalChildren
154+
);
155+
156+
$elements[] = array_filter([
157+
$this->createBadgeGroup($summary, 'CRITICAL'),
158+
$this->createBadgeGroup($summary, 'UNKNOWN'),
159+
$this->createBadgeGroup($summary, 'WARNING'),
160+
$this->createBadge($summary, 'OK'),
161+
$this->createBadge($summary, 'MISSING'),
162+
$this->createBadge($summary, 'PENDING')
163+
]);
163164

164165
if (!empty($elements)) {
165-
$container = Html::tag('div', ['class' => 'badges']);
166+
$container = Html::tag('ul', ['class' => 'state-badges']);
167+
$container->add($itemCount);
166168
foreach ($elements as $element) {
167169
$container->add($element);
168170
}
@@ -172,12 +174,39 @@ public function renderStateBadges($summary)
172174
return null;
173175
}
174176

177+
protected function createBadge($summary, $state)
178+
{
179+
if ($summary[$state] !== 0) {
180+
return Html::tag('li', new StateBadge($summary[$state], $state));
181+
}
182+
183+
return null;
184+
}
185+
186+
protected function createBadgeGroup($summary, $state)
187+
{
188+
$content = [];
189+
if ($summary[$state] !== 0) {
190+
$content[] = Html::tag('li', new StateBadge($summary[$state], $state));
191+
}
192+
193+
if ($summary[$state . '-HANDLED'] !== 0) {
194+
$content[] = Html::tag('li', new StateBadge($summary[$state . '-HANDLED'], $state, true));
195+
}
196+
197+
if (empty($content)) {
198+
return null;
199+
}
200+
201+
return Html::tag('li', Html::tag('ul', $content));
202+
}
203+
175204
public function getNodeClasses(Node $node)
176205
{
177206
if ($node->isMissing()) {
178207
$classes = array('missing');
179208
} else {
180-
if ($node->isEmpty() && ! $node instanceof MonitoredNode) {
209+
if ($node->isEmpty() && !$node instanceof MonitoredNode) {
181210
$classes = array('empty');
182211
} else {
183212
$classes = [strtolower($node->getStateName(
@@ -205,7 +234,7 @@ public function getNodeClasses(Node $node)
205234
/**
206235
* Return the url to the given node's source configuration
207236
*
208-
* @param BpNode $node
237+
* @param BpNode $node
209238
*
210239
* @return Url
211240
*/
@@ -221,12 +250,12 @@ public function getSourceUrl(BpNode $node)
221250

222251
$url = clone $this->getUrl();
223252
$url->setParams([
224-
'config' => $node->getBpConfig()->getName(),
225-
'node' => $name
253+
'config' => $node->getBpConfig()->getName(),
254+
'node' => $name
226255
]);
227256
// This depends on the fact that the node's root path is the last element in $paths
228257
$url->getParams()->addValues('path', array_slice(array_pop($paths), 0, -1));
229-
if (! $this->isLocked()) {
258+
if (!$this->isLocked()) {
230259
$url->getParams()->add('unlocked', true);
231260
}
232261

library/Businessprocess/Renderer/TileRenderer/NodeTile.php

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -126,18 +126,7 @@ public function render()
126126
}
127127

128128
if ($node instanceof BpNode && !$renderer->isBreadcrumb()) {
129-
$this->add(Html::tag(
130-
'p',
131-
['class' => 'children-count'],
132-
$node->hasChildren()
133-
? Html::tag(
134-
'span',
135-
null,
136-
sprintf('%u %s', $node->countChildren(), mt('businessprocess', 'Children'))
137-
)
138-
: null
139-
));
140-
$this->add($renderer->renderStateBadges($node->getStateSummary()));
129+
$this->add($renderer->renderStateBadges($node->getStateSummary(), $node->countChildren()));
141130
}
142131

143132
return parent::render();
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
namespace Icinga\Module\Businessprocess\Widget;
4+
5+
use ipl\Html\BaseHtmlElement;
6+
7+
class StateBadge extends BaseHtmlElement
8+
{
9+
protected $defaultAttributes = ['class' => 'state-badge'];
10+
11+
/** @var mixed Badge content */
12+
protected $content;
13+
14+
/** @var bool Whether the state is handled */
15+
protected $isHandled;
16+
17+
/** @var string Textual representation of a state */
18+
protected $state;
19+
20+
/**
21+
* Create a new state badge
22+
*
23+
* @param mixed $content Content of the badge
24+
* @param string $state Textual representation of a state
25+
* @param bool $isHandled True if state is handled
26+
*/
27+
public function __construct($content, $state, $isHandled = false, $group = false)
28+
{
29+
$this->content = $content;
30+
$this->isHandled = $isHandled;
31+
$this->state = strtolower($state);
32+
}
33+
34+
protected function assemble()
35+
{
36+
$this->setTag('span');
37+
38+
$class = "state-{$this->state}";
39+
if ($this->isHandled) {
40+
$class .= ' handled';
41+
}
42+
43+
$this->addAttributes(['class' => $class]);
44+
45+
$this->add($this->content);
46+
}
47+
}

public/css/module.less

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -314,19 +314,6 @@ ul.bp {
314314
overflow: hidden;
315315
}
316316
}
317-
318-
.badge {
319-
margin-top: 0.25em;
320-
text-decoration: none;
321-
322-
&:last-child {
323-
margin-right: 0;
324-
}
325-
326-
&:hover {
327-
box-shadow: 0px 0px 5px #666;
328-
}
329-
}
330317
}
331318

332319
.dashboard-tile,
@@ -357,37 +344,27 @@ ul.bp {
357344
}
358345
/** END Dashboard **/
359346

360-
/** BEGIN Badges **/
361-
.badges {
362-
background-color: fade(@body-bg-color, 50%);
363-
border-radius: 0.45em;
364-
display: block;
365-
padding: 0.3em 0.4em;
347+
// State summary badges
348+
.state-badges {
349+
.state-badges();
350+
}
366351

367-
.badge {
368-
border: 1px solid white;
369-
margin: 0;
370-
}
352+
// Node children count
353+
.item-count {
354+
font-size: 1em;
355+
text-align: center;
356+
color: @text-color-inverted;
371357
}
372358

373-
div.bp .badges {
359+
div.bp .state-badges {
374360
display: inline-block;
375361
padding-top: 0;
376362
}
377363

378-
379-
380-
td > a > .badges {
364+
td > a > .state-badges {
381365
background-color: transparent;
382366
}
383367

384-
.badge-critical, .badge-down { background: @colorCritical; }
385-
.badge-unknown, .badge-unreachable { background: @colorUnknown; }
386-
.badge-warning { background: @colorWarning; }
387-
.badge-pending { background: @colorPending; }
388-
.badge-missing { background: #ccc; }
389-
/** END Badges **/
390-
391368
/** BEGIN Tiles **/
392369
.tiles:after {
393370
content:'';
@@ -412,7 +389,12 @@ td > a > .badges {
412389
cursor: pointer;
413390
position: relative;
414391

415-
.badges {
392+
393+
.item-count {
394+
margin-right: .5em;
395+
}
396+
397+
.state-badges {
416398
position: absolute;
417399
bottom: 0;
418400
right: 0;

0 commit comments

Comments
 (0)