Merge pull request #305 from Icinga/fix/redesign-state-badge-widget

Redesign state badge widget on tiles
This commit is contained in:
Johannes Meyer 2022-03-10 12:24:26 +01:00 committed by GitHub
commit 5ccc13c862
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 118 additions and 100 deletions

View file

@ -6,6 +6,9 @@ Requirements
* Icinga Web 2 (>= 2.9)
* PHP (>= 7.2)
* Icinga Web 2 libraries:
* [Icinga PHP Library (ipl)](https://github.com/Icinga/icinga-php-library) (>= 0.8)
* [Icinga PHP Thirdparty](https://github.com/Icinga/icinga-php-thirdparty) (>= 0.11)
* Icinga Web 2 modules:
* The `monitoring` or `icingadb` module needs to be configured and enabled.

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(
@ -65,16 +65,27 @@ class BpNode extends Node
$this->counters = self::$emptyStateSummary;
foreach ($this->getChildren() as $child) {
if ($child instanceof BpNode) {
$counters = $child->getStateSummary();
foreach ($counters as $k => $v) {
$this->counters[$k] += $v;
}
} elseif ($child->isMissing()) {
if ($child->isMissing()) {
$this->counters['MISSING']++;
} else {
$state = $child->getStateName($this->getChildState($child));
$this->counters[$state]++;
if ($child->isHandled() && ($state !== 'UP' && $state !== 'OK')) {
$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

@ -12,6 +12,7 @@ use Icinga\Module\Businessprocess\Web\Url;
use ipl\Html\BaseHtmlElement;
use ipl\Html\Html;
use ipl\Html\HtmlDocument;
use ipl\Web\Widget\StateBadge;
abstract class Renderer extends HtmlDocument
{
@ -135,34 +136,31 @@ 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;
}
$itemCount = Html::tag(
'span',
[
'class' => [
'item-count',
]
],
sprintf(mtp('businessprocess', '%u Child', '%u Children', $totalChildren), $totalChildren)
);
$elements[] = Html::tag(
'span',
[
'class' => [
'badge',
'badge-' . strtolower($state)
],
// TODO: We should translate this in this module
'title' => mt('monitoring', $state)
],
$cnt
);
}
$elements[] = array_filter([
$this->createBadgeGroup($summary, 'CRITICAL'),
$this->createBadgeGroup($summary, 'UNKNOWN'),
$this->createBadgeGroup($summary, 'WARNING'),
$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 +170,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], strtolower($state)));
}
return null;
}
protected function createBadgeGroup($summary, $state)
{
$content = [];
if ($summary[$state] !== 0) {
$content[] = Html::tag('li', new StateBadge($summary[$state], strtolower($state)));
}
if ($summary[$state . '-HANDLED'] !== 0) {
$content[] = Html::tag('li', new StateBadge($summary[$state . '-HANDLED'], strtolower($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

@ -1,6 +1,8 @@
Name: Businessprocess
Version: 2.3.1
Depends: monitoring (>= 2.4.1), icingadb (>= 1.0.0), ipl (>= 0.5.0)
Requires:
Libraries: icinga-php-library (>=0.8.0), icinga-php-thirdparty (>=0.11.0)
Modules: monitoring (>=2.4.1), icingadb (>= 1.0.0)
Description: A Business Process viewer and modeler
Provides a web-based process modeler for. It integrates as a module into
Icinga Web 2 and provides a plugin check command for Icinga. Tile and tree

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,49 @@ 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;
// State summary badges
.state-badges {
.state-badges();
.badge {
border: 1px solid @body-bg-color;
margin: 0;
&.state-badges li > ul > li:last-child {
margin-left: 0;
}
li > ul > li:first-child:not(:last-child) .state-badge {
border-right: 0;
}
}
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 {
font-size: .8em;
border: 1px solid @body-bg-color;
&.state-missing {
background: @gray-semilight;
color: @text-color-on-icinga-blue;
}
&.state-critical.handled, &.state-down.handled { background: @color-critical-handled; opacity: 1; }
&.state-unknown.handled { background-color: @color-unknown-handled; opacity: 1; }
&.state-warning.handled { background: @color-warning-handled; opacity: 1; }
}
/** END Badges **/
/** BEGIN Tiles **/
@ -431,7 +432,11 @@ td > a > .badges {
cursor: pointer;
position: relative;
.badges {
.item-count {
margin-right: .5em;
}
.state-badges {
position: absolute;
bottom: 0;
right: 0;
@ -457,17 +462,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 {