diff --git a/library/Graphite/ProvidedHook/Monitoring/DetailviewExtension.php b/library/Graphite/ProvidedHook/Monitoring/DetailviewExtension.php index e5495ee..0b3f163 100644 --- a/library/Graphite/ProvidedHook/Monitoring/DetailviewExtension.php +++ b/library/Graphite/ProvidedHook/Monitoring/DetailviewExtension.php @@ -20,6 +20,7 @@ class DetailviewExtension extends DetailviewExtensionHook ->setWidth(440) ->setHeight(220) ->setClasses(['monitored-object-detail-view']) + ->setMaxVisibleGraphs(2) ->setPreloadDummy() ->handleRequest(); } diff --git a/library/Graphite/Web/Widget/Graphs.php b/library/Graphite/Web/Widget/Graphs.php index b4861c8..799e12f 100644 --- a/library/Graphite/Web/Widget/Graphs.php +++ b/library/Graphite/Web/Widget/Graphs.php @@ -78,6 +78,13 @@ abstract class Graphs extends AbstractWidget */ protected $classes = []; + /** + * The amount of graphs to show + * + * @var int + */ + protected $maxVisibleGraphs; + /** * Whether to serve a transparent dummy image first and let the JS code load the actual graph * @@ -157,19 +164,34 @@ abstract class Graphs extends AbstractWidget $imageBaseUrl = $this->preloadDummy ? $this->getDummyImageBaseUrl() : $this->getImageBaseUrl(); $templates = static::getAllTemplates()->getTemplates(); $checkCommand = $this->obscuredCheckCommand === null ? $this->checkCommand : $this->obscuredCheckCommand; + $limit = $this->maxVisibleGraphs; $classes = $this->classes; $classes[] = 'images'; $div = '
{$view->escape($view->translate('No graphs found'))}
" : implode($result); + if (! empty($result)) { + if ($limit && $renderedGraphs > $limit) { + $result[] = '{$view->escape($view->translate('No graphs found'))}
"; + } } /** @@ -226,6 +256,13 @@ abstract class Graphs extends AbstractWidget */ abstract protected function designedForMyMonitoredObjectType(Template $template); + /** + * Return a identifier specifying the monitored object we display graphs for + * + * @return string + */ + abstract protected function getMonitoredObjectIdentifier(); + /** * Return a filter specifying the monitored object we display graphs for * @@ -351,6 +388,29 @@ abstract class Graphs extends AbstractWidget return $this; } + /** + * Get the amount of graphs to show + * + * @return int + */ + public function getMaxVisbileGraphs() + { + return $this->maxVisibleGraphs; + } + + /** + * Set the amount of graphs to show + * + * @param int $count + * + * @return $this + */ + public function setMaxVisibleGraphs($count) + { + $this->maxVisibleGraphs = (int) $count; + return $this; + } + /** * Get whether to serve a transparent dummy image first and let the JS code load the actual graph * diff --git a/library/Graphite/Web/Widget/Graphs/Host.php b/library/Graphite/Web/Widget/Graphs/Host.php index 21a669f..1b67ca9 100644 --- a/library/Graphite/Web/Widget/Graphs/Host.php +++ b/library/Graphite/Web/Widget/Graphs/Host.php @@ -56,6 +56,11 @@ class Host extends Graphs return false; } + protected function getMonitoredObjectIdentifier() + { + return $this->host; + } + protected function getMonitoredObjectFilter() { return ['host.name' => $this->host]; diff --git a/library/Graphite/Web/Widget/Graphs/Service.php b/library/Graphite/Web/Widget/Graphs/Service.php index 3b292d2..f102ebf 100644 --- a/library/Graphite/Web/Widget/Graphs/Service.php +++ b/library/Graphite/Web/Widget/Graphs/Service.php @@ -65,6 +65,11 @@ class Service extends Graphs return false; } + protected function getMonitoredObjectIdentifier() + { + return $this->host . ':' . $this->service; + } + protected function getMonitoredObjectFilter() { return ['host.name' => $this->host, 'service.name' => $this->service]; diff --git a/public/css/module.less b/public/css/module.less index 0f11b38..df0ceba 100644 --- a/public/css/module.less +++ b/public/css/module.less @@ -1,7 +1,4 @@ div.images { - - display: inline-block; - h3 { clear: both; } @@ -13,6 +10,55 @@ div.images { } +.collapsible { + clear: right; // Because the label is floating right + + height: 0; + opacity: 0; + visibility: hidden; + + -webkit-transition: opacity 0.2s linear, visibility 0.2s; + -moz-transition: opacity 0.2s linear, visibility 0.2s; + -o-transition: opacity 0.2s linear, visibility 0.2s; + transition: opacity 0.2s linear, visibility 0.2s; +} + +input[type="checkbox"].collapsible-toggle { + display: none; + + & + label { + float: right; + margin-right: 1em; + + cursor: pointer; + user-select: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + } + + &:checked ~ .collapsible { + height: auto; + opacity: 1; + visibility: visible; + + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + -o-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; + } + & ~ label span.collapsible-hide { + display: none; + } + + &:checked ~ label span.collapsible-show { + display: none; + } + &:checked ~ label span.collapsible-hide { + display: inline; + } +} + div.images.monitored-object-detail-view { display: block;