diff --git a/doc/02-Installation.md b/doc/02-Installation.md index 5f8c417f..e5a3b4ea 100644 --- a/doc/02-Installation.md +++ b/doc/02-Installation.md @@ -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. diff --git a/library/Businessprocess/BpNode.php b/library/Businessprocess/BpNode.php index 6944f092..2ea8f8e2 100644 --- a/library/Businessprocess/BpNode.php +++ b/library/Businessprocess/BpNode.php @@ -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 @@ public function getStateSummary() $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]++; + } } } } diff --git a/library/Businessprocess/Renderer/Renderer.php b/library/Businessprocess/Renderer/Renderer.php index 35e32257..58e1c4de 100644 --- a/library/Businessprocess/Renderer/Renderer.php +++ b/library/Businessprocess/Renderer/Renderer.php @@ -12,6 +12,7 @@ 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 @@ public function countChildNodes() * @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) - ], - $cnt - ); - } + $itemCount = Html::tag( + 'span', + [ + 'class' => [ + 'item-count', + ] + ], + sprintf(mtp('businessprocess', '%u Child', '%u Children', $totalChildren), $totalChildren) + ); + + $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 @@ public function renderStateBadges($summary) 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()) { diff --git a/library/Businessprocess/Renderer/TileRenderer/NodeTile.php b/library/Businessprocess/Renderer/TileRenderer/NodeTile.php index 261b6cd3..67bb4a62 100644 --- a/library/Businessprocess/Renderer/TileRenderer/NodeTile.php +++ b/library/Businessprocess/Renderer/TileRenderer/NodeTile.php @@ -129,24 +129,7 @@ public function render() } 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(); diff --git a/module.info b/module.info index 7484c035..6a41c7b1 100644 --- a/module.info +++ b/module.info @@ -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 diff --git a/public/css/module.less b/public/css/module.less index 78617c58..75768348 100644 --- a/public/css/module.less +++ b/public/css/module.less @@ -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 > .state-badges { + background-color: transparent; +} +.state-badge { + font-size: .8em; + border: 1px solid @body-bg-color; -td > a > .badges { - background-color: transparent; + &.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; } } -.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; } /** 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 {