From 71f4b6960b5a0f42edb9f2103bb01f8b152c4c60 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 12 Mar 2014 14:41:17 +0100 Subject: [PATCH 01/12] Add servicematrix view refs #4180 --- config/modules/monitoring/menu.ini | 5 + library/Icinga/Data/PivotTable.php | 96 +++++++++------- .../controllers/ListController.php | 27 +++++ .../views/scripts/list/servicematrix.phtml | 51 +++++++++ .../library/Monitoring/DataView/DataView.php | 14 +++ public/css/icinga/monitoring-colors.less | 106 ++++++++++++++++++ 6 files changed, 261 insertions(+), 38 deletions(-) create mode 100644 modules/monitoring/application/views/scripts/list/servicematrix.phtml diff --git a/config/modules/monitoring/menu.ini b/config/modules/monitoring/menu.ini index 81cf36324..7713dcd40 100644 --- a/config/modules/monitoring/menu.ini +++ b/config/modules/monitoring/menu.ini @@ -41,6 +41,11 @@ title = "Services" url = "monitoring/list/services" priority = 50 +[Overview.Servicematrix] +title = "Servicematrix" +url = "monitoring/list/servicematrix" +priority = 51 + [Overview.Servicegroups] title = "Servicegroups" url = "monitoring/list/servicegroups" diff --git a/library/Icinga/Data/PivotTable.php b/library/Icinga/Data/PivotTable.php index 92878a372..fdf08dcba 100644 --- a/library/Icinga/Data/PivotTable.php +++ b/library/Icinga/Data/PivotTable.php @@ -1,14 +1,19 @@ query = $query; - $this->verticalColumn = $verticalColumn; - $this->horizontalColumn = $horizontalColumn; + $this->xAxisColumn = $xAxisColumn; + $this->yAxisColumn = $yAxisColumn; } public function limit($limit = null, $offset = null) @@ -85,51 +97,59 @@ class PivotTable } /** - * Fetch all columns + * Fetch the values to label the x axis with */ - public function fetchAll() + protected function fetchXAxis() { - $xcol = $this->horizontalColumn; - $ycol = $this->verticalColumn; - $queryX = clone($this->query); - $queryX->columns($xcol); - if ($this->limit !== null) { - $queryX->limit($this->getLimit(), $this->getOffset()); - } - $queryX->limit(40); - $listX = $queryX->fetchColumn(); - $queryY = clone($this->query); + $queryClass = get_class($this->query); + $query = new $queryClass($this->query->getDatasource(), array($this->xAxisColumn)); + return $query->fetchColumn(); + } - $queryY->columns($ycol); - if ($this->verticalLimit !== null) { - $queryY->limit($this->getVerticalLimit(), $this->getVerticalOffset()); - } - $queryY->limit(50); - $listY = $queryY->fetchColumn(); + /** + * Fetch the values to label the y axis with + */ + protected function fetchYAxis() + { + $queryClass = get_class($this->query); + $query = new $queryClass($this->query->getDatasource(), array($this->yAxisColumn)); + return $query->fetchColumn(); + } + + /** + * Return the pivot table as array + * + * @return array + */ + public function toArray() + { + $xAxis = $this->fetchXAxis(); + $yAxis = $this->fetchYAxis(); + + $this->query->where($this->xAxisColumn, $xAxis)->where($this->yAxisColumn, $yAxis); + if (!$this->query->hasOrder()) { + $this->query->order($this->xAxisColumn)->order($this->yAxisColumn); + } + + $emptyrow = new stdClass(); + foreach ($this->query->getColumns() as $col) { + $emptyrow->{$col} = null; + } - // TODO: resetOrder - $this->query - ->where($ycol, $listY) - ->where($xcol, $listX) - ->order($ycol) - ->order($xcol); $pivot = array(); - $emptyrow = (object) array(); - foreach ($this->query->listColumns() as $col) { - $emptyrow->$col = null; - } - foreach ($listY as $y) { - foreach ($listX as $x) { + foreach ($xAxis as $x) { + foreach ($yAxis as $y) { $row = clone($emptyrow); - $row->$xcol = $x; - $row->$ycol = $y; + $row->{$this->xAxisColumn} = $x; + $row->{$this->yAxisColumn} = $y; $pivot[$y][$x] = $row; } } foreach ($this->query->fetchAll() as $row) { - $pivot[$row->$ycol][$row->$xcol] = $row; + $pivot[$row->{$this->yAxisColumn}][$row->{$this->xAxisColumn}] = $row; } + return $pivot; } } diff --git a/modules/monitoring/application/controllers/ListController.php b/modules/monitoring/application/controllers/ListController.php index a6b5da9b3..e8ab18d84 100644 --- a/modules/monitoring/application/controllers/ListController.php +++ b/modules/monitoring/application/controllers/ListController.php @@ -458,6 +458,33 @@ class Monitoring_ListController extends Controller $this->view->history = $query->paginate(); } + public function servicematrixAction() + { + $this->view->title = 'Servicematrix'; + $this->addTitleTab('servicematrix'); + $dataview = ServiceStatusView::fromRequest( + $this->getRequest(), + array( + 'host_name', + 'service_description', + 'service_state', + 'service_output', + 'service_handled' + ) + ); + + $this->setupFilterControl($dataview, 'servicematrix'); + $this->setupSortControl( + array( + 'service_state' => 'Service status', + 'service_description' => 'Service description', + 'host_name' => 'Hostname' + ) + ); + + $this->view->matrix = $dataview->pivot('service_description', 'host_name')->toArray(); + } + /** * Apply current users monitoring/filter restrictions to the given query * diff --git a/modules/monitoring/application/views/scripts/list/servicematrix.phtml b/modules/monitoring/application/views/scripts/list/servicematrix.phtml new file mode 100644 index 000000000..78dec4517 --- /dev/null +++ b/modules/monitoring/application/views/scripts/list/servicematrix.phtml @@ -0,0 +1,51 @@ +compact): ?> +
+ tabs; ?> +
+ Sort by sortControl->render($this); ?> +
+
+ +
+ + +matrix as $host_name => $serviceStates): ?> + + + + + + + + + + + + + + + +service_state !== null): ?> + + + + + +
 
+ + + + + + + + · + +
+
diff --git a/modules/monitoring/library/Monitoring/DataView/DataView.php b/modules/monitoring/library/Monitoring/DataView/DataView.php index b5152e4a1..3310a1d6b 100644 --- a/modules/monitoring/library/Monitoring/DataView/DataView.php +++ b/modules/monitoring/library/Monitoring/DataView/DataView.php @@ -30,6 +30,7 @@ namespace Icinga\Module\Monitoring\DataView; use Icinga\Data\BaseQuery; +use Icinga\Data\PivotTable; use Icinga\Filter\Filterable; use Icinga\Filter\Query\Tree; use Icinga\Module\Monitoring\Backend; @@ -167,6 +168,19 @@ abstract class DataView implements Filterable return array(); } + /** + * Return a pivot table for the given columns based on the current query + * + * @param string $xAxisColumn The column to use for the x axis + * @param string $yAxisColumn The column to use for the y axis + * + * @return PivotTable + */ + public function pivot($xAxisColumn, $yAxisColumn) + { + return new PivotTable($this->query, $xAxisColumn, $yAxisColumn); + } + /** * Sort the rows, according to the specified sort column and order * diff --git a/public/css/icinga/monitoring-colors.less b/public/css/icinga/monitoring-colors.less index 6c15489eb..fdc2a82de 100644 --- a/public/css/icinga/monitoring-colors.less +++ b/public/css/icinga/monitoring-colors.less @@ -501,6 +501,112 @@ div.box.contactgroup div.box.entry p { /* End of monitoring box element styles */ +/* Monitoring pivot table styles */ + +table.pivot { + width: 100%; + table-layout: fixed; + border-spacing: 0.2em; + border-collapse: separate; + + th, td { + width: 0.5em; + } + + thead { + th { + height: 6em; + padding: 0 0 1em 1.4em; + vertical-align: bottom; + + &:first-of-type { + width: 4em; + } + + span { + font-size: 0.8em; + line-height: 2.4em; + white-space: nowrap; + display: inline-block; + + transform: rotate(-45deg); + transform-origin: bottom left; + -o-transform: rotate(-45deg); + -o-transform-origin: bottom left; + -ms-transform: rotate(-45deg); + -ms-transform-origin: bottom left; + -moz-transform: rotate(-45deg); + -moz-transform-origin: bottom left; + -webkit-transform: rotate(-45deg); + -webkit-transform-origin: bottom left; + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + } + } + } + + tbody { + th { + width: 4em; + font-size: 0.8em; + line-height: 2.2em; + padding-right: 1.2em; + + a { + color: black; + text-decoration: none; + + &:hover { + color: #666; + } + } + } + + td { + padding: 0; + text-align: center; + border-radius: 0.5em; + + a { + padding: 20% 50%; + } + + &.state_ok { + background-color: @colorOk; + } + + &.state_pending { + background-color: @colorPending; + } + + &.state_warning { + background-color: @colorWarning; + + &.handled { + background-color: @colorWarningHandled; + } + } + + &.state_critical { + background-color: @colorCritical; + + &.handled { + background-color: @colorCriticalHandled; + } + } + + &.state_unknown { + background-color: @colorUnknown; + + &.handled { + background-color: @colorUnknownHandled; + } + } + } + } +} + +/* End of monitoring pivot table styles */ + .controls { font-size: 0.9em; } From 0a5c2c5bd732e7023dabf95cb572659de13364cf Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 12 Mar 2014 15:20:33 +0100 Subject: [PATCH 02/12] Make filtering/sorting of the servicematrix work refs #4180 --- library/Icinga/Data/Db/Query.php | 7 ++++++ library/Icinga/Data/PivotTable.php | 23 +++++++++++++++---- .../controllers/ListController.php | 5 ++-- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/library/Icinga/Data/Db/Query.php b/library/Icinga/Data/Db/Query.php index 0031a9987..3dead6476 100644 --- a/library/Icinga/Data/Db/Query.php +++ b/library/Icinga/Data/Db/Query.php @@ -80,6 +80,13 @@ class Query extends BaseQuery $this->baseQuery = $this->db->select(); } + public function __clone() + { + if ($this->baseQuery !== null) { + $this->baseQuery = clone $this->baseQuery; + } + } + /** * Return the raw base query * diff --git a/library/Icinga/Data/PivotTable.php b/library/Icinga/Data/PivotTable.php index fdf08dcba..4d102b636 100644 --- a/library/Icinga/Data/PivotTable.php +++ b/library/Icinga/Data/PivotTable.php @@ -9,10 +9,25 @@ use Icinga\Data\BaseQuery; class PivotTable { + /** + * The query to fetch as pivot table + * + * @var BaseQuery + */ protected $query; + /** + * The column to use for the x axis + * + * @var string + */ protected $xAxisColumn; + /** + * The column to use for the y axis + * + * @var string + */ protected $yAxisColumn; protected $limit; @@ -101,8 +116,8 @@ class PivotTable */ protected function fetchXAxis() { - $queryClass = get_class($this->query); - $query = new $queryClass($this->query->getDatasource(), array($this->xAxisColumn)); + $query = clone $this->query; + $query->setColumns(array($this->xAxisColumn)); return $query->fetchColumn(); } @@ -111,8 +126,8 @@ class PivotTable */ protected function fetchYAxis() { - $queryClass = get_class($this->query); - $query = new $queryClass($this->query->getDatasource(), array($this->yAxisColumn)); + $query = clone $this->query; + $query->setColumns(array($this->yAxisColumn)); return $query->fetchColumn(); } diff --git a/modules/monitoring/application/controllers/ListController.php b/modules/monitoring/application/controllers/ListController.php index e8ab18d84..ef378fab9 100644 --- a/modules/monitoring/application/controllers/ListController.php +++ b/modules/monitoring/application/controllers/ListController.php @@ -476,9 +476,8 @@ class Monitoring_ListController extends Controller $this->setupFilterControl($dataview, 'servicematrix'); $this->setupSortControl( array( - 'service_state' => 'Service status', - 'service_description' => 'Service description', - 'host_name' => 'Hostname' + 'host_name' => 'Hostname', + 'service_description' => 'Service description' ) ); From 5dc7d0dd5643395943adc1d14092fdc0f222c94a Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 12 Mar 2014 15:40:42 +0100 Subject: [PATCH 03/12] Fix servicematrix layout in case there are only a few services being shown refs #4180 --- public/css/icinga/monitoring-colors.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/css/icinga/monitoring-colors.less b/public/css/icinga/monitoring-colors.less index fdc2a82de..c61e4a368 100644 --- a/public/css/icinga/monitoring-colors.less +++ b/public/css/icinga/monitoring-colors.less @@ -504,7 +504,7 @@ div.box.contactgroup div.box.entry p { /* Monitoring pivot table styles */ table.pivot { - width: 100%; + width: 1px; // Ensures that its cells are really of fixed width table-layout: fixed; border-spacing: 0.2em; border-collapse: separate; From 13b509bf4b9d04b91f3639878b0d0e15fe147b9c Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 12 Mar 2014 16:48:24 +0100 Subject: [PATCH 04/12] Do not display hosts without any services in the servicematrix refs #4180 --- library/Icinga/Data/PivotTable.php | 26 ++++++------------- .../views/scripts/list/servicematrix.phtml | 2 +- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/library/Icinga/Data/PivotTable.php b/library/Icinga/Data/PivotTable.php index 4d102b636..8bd5a777d 100644 --- a/library/Icinga/Data/PivotTable.php +++ b/library/Icinga/Data/PivotTable.php @@ -4,7 +4,6 @@ namespace Icinga\Data; -use \stdClass; use Icinga\Data\BaseQuery; class PivotTable @@ -142,26 +141,17 @@ class PivotTable $yAxis = $this->fetchYAxis(); $this->query->where($this->xAxisColumn, $xAxis)->where($this->yAxisColumn, $yAxis); - if (!$this->query->hasOrder()) { - $this->query->order($this->xAxisColumn)->order($this->yAxisColumn); - } - - $emptyrow = new stdClass(); - foreach ($this->query->getColumns() as $col) { - $emptyrow->{$col} = null; - } $pivot = array(); - foreach ($xAxis as $x) { - foreach ($yAxis as $y) { - $row = clone($emptyrow); - $row->{$this->xAxisColumn} = $x; - $row->{$this->yAxisColumn} = $y; - $pivot[$y][$x] = $row; - } - } - foreach ($this->query->fetchAll() as $row) { + if (!array_key_exists($row->{$this->yAxisColumn}, $pivot)) { + $defaults = array(); + foreach ($xAxis as $label) { + $defaults[$label] = null; + } + $pivot[$row->{$this->yAxisColumn}] = $defaults; + } + $pivot[$row->{$this->yAxisColumn}][$row->{$this->xAxisColumn}] = $row; } diff --git a/modules/monitoring/application/views/scripts/list/servicematrix.phtml b/modules/monitoring/application/views/scripts/list/servicematrix.phtml index 78dec4517..c6dd5c3f0 100644 --- a/modules/monitoring/application/views/scripts/list/servicematrix.phtml +++ b/modules/monitoring/application/views/scripts/list/servicematrix.phtml @@ -29,7 +29,7 @@ -service_state !== null): ?> + query = $query; + $this->baseQuery = $query; $this->xAxisColumn = $xAxisColumn; $this->yAxisColumn = $yAxisColumn; - } - - public function limit($limit = null, $offset = null) - { - $this->limit = $limit; - $this->offset = $offset; - return $this; - } - - public function getLimit() - { - if ($this->limit === null) { - return 20; - } - return $this->limit; - } - - public function getOffset() - { - if ($this->limit === null) { - return 20; - } - return $this->offset; - } - - public function verticalLimit($limit = null, $offset = null) - { - // TODO: Trigger limit by calling $this->limit()? - if ($limit === null) { - $limit = $this->getLimit(); - } - if ($offset === null) { - $offset = $this->getOffset(); - } - $this->verticalLimit = $limit; - $this->verticalOffset = $offset; - return $this; - } - - public function paginateVertical($limit = null, $offset = null) - { - $this->verticalLimit($limit, $offset); - return Paginator($this); - } - - public function getVerticalLimit() - { - if ($this->verticalLimit === null) { - return 20; - } - return $this->verticalLimit; - } - - public function getVerticalOffset() - { - if ($this->verticalLimit === null) { - return 20; - } - return $this->verticalOffset; + $this->prepareQueries(); } /** - * Fetch the values to label the x axis with + * Prepare the queries used for the pre processing */ - protected function fetchXAxis() + protected function prepareQueries() { - $query = clone $this->query; - $query->setColumns(array($this->xAxisColumn)); - return $query->fetchColumn(); + $this->xAxisQuery = clone $this->baseQuery; + $this->xAxisQuery->distinct(); + $this->xAxisQuery->setColumns(array($this->xAxisColumn)); + $this->yAxisQuery = clone $this->baseQuery; + $this->yAxisQuery->distinct(); + $this->yAxisQuery->setColumns(array($this->yAxisColumn)); } /** - * Fetch the values to label the y axis with + * Return the value for the given request parameter + * + * @param string $axis The axis for which to return the parameter ('x' or 'y') + * @param string $param The parameter name to return + * @param int $default The default value to return + * + * @return int */ - protected function fetchYAxis() + protected function getPaginationParameter($axis, $param, $default = null) { - $query = clone $this->query; - $query->setColumns(array($this->yAxisColumn)); - return $query->fetchColumn(); + $request = Icinga::app()->getFrontController()->getRequest(); + + $value = $request->getParam($param, ''); + if (strpos($value, ',') > 0) { + $parts = explode(',', $value, 2); + return intval($parts[$axis === 'x' ? 0 : 1]); + } + + return $default !== null ? $default : 0; + } + + /** + * Return a pagination adapter for the x axis query + * + * $limit and $page are taken from the current request if not given. + * + * @param int $limit The maximum amount of entries to fetch + * @param int $page The page to set as current one + * + * @return Zend_Paginator + */ + public function paginateXAxis($limit = null, $page = null) + { + if ($limit === null || $page === null) { + if ($limit === null) { + $limit = $this->getPaginationParameter('x', 'limit', 20); + } + + if ($page === null) { + $page = $this->getPaginationParameter('x', 'page', 1); + } + } + + $this->xAxisQuery->limit($limit, $page > 0 ? ($page - 1) * $limit : 0); + + $paginator = new Zend_Paginator(new QueryAdapter($this->xAxisQuery)); + $paginator->setItemCountPerPage($limit); + $paginator->setCurrentPageNumber($page); + return $paginator; + } + + /** + * Return a pagination adapter for the y axis query + * + * $limit and $page are taken from the current request if not given. + * + * @param int $limit The maximum amount of entries to fetch + * @param int $page The page to set as current one + * + * @return Zend_Paginator + */ + public function paginateYAxis($limit = null, $page = null) + { + if ($limit === null || $page === null) { + if ($limit === null) { + $limit = $this->getPaginationParameter('y', 'limit', 20); + } + + if ($page === null) { + $page = $this->getPaginationParameter('y', 'page', 1); + } + } + + $this->yAxisQuery->limit($limit, $page > 0 ? ($page - 1) * $limit : 0); + + $paginator = new Zend_Paginator(new QueryAdapter($this->yAxisQuery)); + $paginator->setItemCountPerPage($limit); + $paginator->setCurrentPageNumber($page); + return $paginator; } /** @@ -137,22 +163,24 @@ class PivotTable */ public function toArray() { - $xAxis = $this->fetchXAxis(); - $yAxis = $this->fetchYAxis(); - - $this->query->where($this->xAxisColumn, $xAxis)->where($this->yAxisColumn, $yAxis); + $xAxis = $this->xAxisQuery->fetchColumn(); + $yAxis = $this->yAxisQuery->fetchColumn(); $pivot = array(); - foreach ($this->query->fetchAll() as $row) { - if (!array_key_exists($row->{$this->yAxisColumn}, $pivot)) { - $defaults = array(); - foreach ($xAxis as $label) { - $defaults[$label] = null; - } - $pivot[$row->{$this->yAxisColumn}] = $defaults; - } + if (!empty($xAxis) && !empty($yAxis)) { + $this->baseQuery->where($this->xAxisColumn, $xAxis)->where($this->yAxisColumn, $yAxis); - $pivot[$row->{$this->yAxisColumn}][$row->{$this->xAxisColumn}] = $row; + foreach ($this->baseQuery->fetchAll() as $row) { + if (!array_key_exists($row->{$this->yAxisColumn}, $pivot)) { + $defaults = array(); + foreach ($xAxis as $label) { + $defaults[$label] = null; + } + $pivot[$row->{$this->yAxisColumn}] = $defaults; + } + + $pivot[$row->{$this->yAxisColumn}][$row->{$this->xAxisColumn}] = $row; + } } return $pivot; diff --git a/modules/monitoring/application/controllers/ListController.php b/modules/monitoring/application/controllers/ListController.php index ef378fab9..f735e482c 100644 --- a/modules/monitoring/application/controllers/ListController.php +++ b/modules/monitoring/application/controllers/ListController.php @@ -481,7 +481,9 @@ class Monitoring_ListController extends Controller ) ); - $this->view->matrix = $dataview->pivot('service_description', 'host_name')->toArray(); + $this->view->pivot = $dataview->pivot('service_description', 'host_name'); + $this->view->horizontalPaginator = $this->view->pivot->paginateXAxis(); + $this->view->verticalPaginator = $this->view->pivot->paginateYAxis(); } /** diff --git a/modules/monitoring/application/views/scripts/list/servicematrix.phtml b/modules/monitoring/application/views/scripts/list/servicematrix.phtml index c6dd5c3f0..211afff9f 100644 --- a/modules/monitoring/application/views/scripts/list/servicematrix.phtml +++ b/modules/monitoring/application/views/scripts/list/servicematrix.phtml @@ -9,7 +9,7 @@
-matrix as $host_name => $serviceStates): ?> +pivot->toArray() as $host_name => $serviceStates): ?> From c73928d7a8d20aaae0c3afec06b6acf418ced13b Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Fri, 14 Mar 2014 15:49:47 +0100 Subject: [PATCH 08/12] Add pagination control to the servicematrix refs #4180 --- .../views/scripts/pivottablePagination.phtml | 33 +++++++++++++++++++ .../views/scripts/list/servicematrix.phtml | 8 +++++ public/css/icinga/monitoring-colors.less | 28 ++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 application/views/scripts/pivottablePagination.phtml diff --git a/application/views/scripts/pivottablePagination.phtml b/application/views/scripts/pivottablePagination.phtml new file mode 100644 index 000000000..832cba0ef --- /dev/null +++ b/application/views/scripts/pivottablePagination.phtml @@ -0,0 +1,33 @@ +count() <= 1 && $yAxisPaginator->count() <= 1) { + return; // Display this pagination only if there are multiple pages +} + +$xAxisPages = $xAxisPaginator->getPages('all'); +$yAxisPages = $yAxisPaginator->getPages('all'); + +?> + +
+ translate('Navigation'); ?> +
+ +pagesInRange as $yAxisPage): ?> + +pagesInRange as $xAxisPage): ?> + current && $yAxisPage === $yAxisPages->current ? ' class="active"' : ''; ?>> +current || $yAxisPage !== $yAxisPages->current): ?> + + + + + + + +
+
diff --git a/modules/monitoring/application/views/scripts/list/servicematrix.phtml b/modules/monitoring/application/views/scripts/list/servicematrix.phtml index 211afff9f..d48b0cf69 100644 --- a/modules/monitoring/application/views/scripts/list/servicematrix.phtml +++ b/modules/monitoring/application/views/scripts/list/servicematrix.phtml @@ -4,6 +4,14 @@
Sort by sortControl->render($this); ?>
+ partial( + 'pivottablePagination.phtml', + 'default', + array( + 'xAxisPaginator' => $this->horizontalPaginator, + 'yAxisPaginator' => $this->verticalPaginator + ) + ); ?>
diff --git a/public/css/icinga/monitoring-colors.less b/public/css/icinga/monitoring-colors.less index c61e4a368..6ab287ae7 100644 --- a/public/css/icinga/monitoring-colors.less +++ b/public/css/icinga/monitoring-colors.less @@ -503,6 +503,34 @@ div.box.contactgroup div.box.entry p { /* Monitoring pivot table styles */ +div.pivot-pagination { + margin: 1em; + + table { + width: 1px; // Ensures that its cells are really of fixed width + table-layout: fixed; + border-spacing: 0.2em; + border-collapse: separate; + border: 1px solid LightGrey; + border-radius: 0.3em; + + td { + padding: 0; + width: 1.7em; + height: 1.7em; + background-color: #fbfbfb; + + &:hover, &.active { + background-color: #e5e5e5; + } + + a { + padding: 10% 50%; + } + } + } +} + table.pivot { width: 1px; // Ensures that its cells are really of fixed width table-layout: fixed; From 0227c6a49d2ac29d54a3f026e6363a60cda4f3e8 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 17 Mar 2014 09:13:12 +0100 Subject: [PATCH 09/12] Fix hosts without services being displayed in the servicematrix refs #4180 --- .../application/views/scripts/list/servicematrix.phtml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/monitoring/application/views/scripts/list/servicematrix.phtml b/modules/monitoring/application/views/scripts/list/servicematrix.phtml index d48b0cf69..612b01990 100644 --- a/modules/monitoring/application/views/scripts/list/servicematrix.phtml +++ b/modules/monitoring/application/views/scripts/list/servicematrix.phtml @@ -30,6 +30,7 @@ + @@ -53,6 +54,7 @@ + From e355415164710e8e2614cca3267aa945f34c3f7f Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 17 Mar 2014 16:08:12 +0100 Subject: [PATCH 10/12] Fix that queryfilters are being ignored by the parser --- library/Icinga/Data/Db/TreeToSqlParser.php | 3 +-- library/Icinga/Filter/Query/Tree.php | 10 +++++----- library/Icinga/Web/Widget/FilterBadgeRenderer.php | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/library/Icinga/Data/Db/TreeToSqlParser.php b/library/Icinga/Data/Db/TreeToSqlParser.php index facdba9d4..20638bf74 100644 --- a/library/Icinga/Data/Db/TreeToSqlParser.php +++ b/library/Icinga/Data/Db/TreeToSqlParser.php @@ -193,8 +193,7 @@ class TreeToSqlParser if ($tree->root == null) { return; } - $tree->root = $tree->normalizeTree($tree->root); - $sql = $this->nodeToSqlQuery($tree->root); + $sql = $this->nodeToSqlQuery($tree->normalizeTree($tree->root)); if ($this->filtersAggregate()) { $baseQuery->having($sql); diff --git a/library/Icinga/Filter/Query/Tree.php b/library/Icinga/Filter/Query/Tree.php index ced419679..eb2736f6f 100644 --- a/library/Icinga/Filter/Query/Tree.php +++ b/library/Icinga/Filter/Query/Tree.php @@ -232,12 +232,12 @@ class Tree $node->left = $this->removeInvalidFilter($node->left, $filter); $node->right = $this->removeInvalidFilter($node->right, $filter); - if ($node->left && $node->right) { + if ($node->left || $node->right) { + if (!$node->left) { + $node->left = $node->right; + $node->right = null; + } return $node; - } elseif ($node->left) { - return $node->left; - } elseif ($node->right) { - return $node->right; } return null; diff --git a/library/Icinga/Web/Widget/FilterBadgeRenderer.php b/library/Icinga/Web/Widget/FilterBadgeRenderer.php index 2a59fa689..8bf0bced9 100644 --- a/library/Icinga/Web/Widget/FilterBadgeRenderer.php +++ b/library/Icinga/Web/Widget/FilterBadgeRenderer.php @@ -182,6 +182,6 @@ EOT; return ''; } $this->buildBaseUrl(); - return $this->nodeToBadge($this->tree->root); + return $this->nodeToBadge(Tree::normalizeTree($this->tree->root)); } } From 1604f4728b95cc8b8b53779532bb9ba66f27cd58 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Tue, 18 Mar 2014 09:00:16 +0100 Subject: [PATCH 11/12] Fix that the TreeToSqlParser cannot handle partial conjunction nodes --- library/Icinga/Data/Db/TreeToSqlParser.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/Icinga/Data/Db/TreeToSqlParser.php b/library/Icinga/Data/Db/TreeToSqlParser.php index 20638bf74..b1d482ef7 100644 --- a/library/Icinga/Data/Db/TreeToSqlParser.php +++ b/library/Icinga/Data/Db/TreeToSqlParser.php @@ -112,15 +112,14 @@ class TreeToSqlParser private function parseConjunctionNode(Node $node) { $queryString = ''; - $leftQuery = $this->nodeToSqlQuery($node->left); - $rightQuery = $this->nodeToSqlQuery($node->right); + $leftQuery = $node->left !== null ? $this->nodeToSqlQuery($node->left) : ''; + $rightQuery = $node->right !== null ? $this->nodeToSqlQuery($node->right) : ''; if ($leftQuery != '') { $queryString .= $leftQuery . ' '; } if ($rightQuery != '') { - $queryString .= (($queryString !== '') ? $node->type . ' ' : ' ') . $rightQuery; } return $queryString; From e9ec87b0e33c42dd803451be926d54923dd75258 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 19 Mar 2014 09:10:39 +0100 Subject: [PATCH 12/12] Refine styling of the servicematrix refs #4180 --- .../views/scripts/pivottablePagination.phtml | 17 ++- .../views/scripts/list/servicematrix.phtml | 14 +- public/css/icinga/monitoring-colors.less | 139 +++++++++--------- 3 files changed, 98 insertions(+), 72 deletions(-) diff --git a/application/views/scripts/pivottablePagination.phtml b/application/views/scripts/pivottablePagination.phtml index 832cba0ef..0b4c7420e 100644 --- a/application/views/scripts/pivottablePagination.phtml +++ b/application/views/scripts/pivottablePagination.phtml @@ -6,6 +6,7 @@ if ($xAxisPaginator->count() <= 1 && $yAxisPaginator->count() <= 1) { return; // Display this pagination only if there are multiple pages } +$fromTo = $this->translate('%s: %d to %d of %d'); $xAxisPages = $xAxisPaginator->getPages('all'); $yAxisPages = $yAxisPaginator->getPages('all'); @@ -22,7 +23,21 @@ $yAxisPages = $yAxisPaginator->getPages('all'); current || $yAxisPage !== $yAxisPages->current): ?> + )->getAbsoluteUrl(); ?>" title="translate('Hosts'), + ($yAxisPage - 1) * $yAxisPages->itemCountPerPage + 1, + $yAxisPage === $yAxisPages->last ? $yAxisPages->totalItemCount : $yAxisPage * $yAxisPages->itemCountPerPage, + $yAxisPages->totalItemCount + ) . '; ' . sprintf( + $fromTo, + $this->translate('Services'), + ($xAxisPage - 1) * $xAxisPages->itemCountPerPage + 1, + $xAxisPage === $xAxisPages->last ? $xAxisPages->totalItemCount : $xAxisPage * $xAxisPages->itemCountPerPage, + $xAxisPages->totalItemCount + ); ?>"> + +   diff --git a/modules/monitoring/application/views/scripts/list/servicematrix.phtml b/modules/monitoring/application/views/scripts/list/servicematrix.phtml index 612b01990..dac296f46 100644 --- a/modules/monitoring/application/views/scripts/list/servicematrix.phtml +++ b/modules/monitoring/application/views/scripts/list/servicematrix.phtml @@ -22,9 +22,17 @@   + +
- + + + 18 ? substr($service_description, 0, 18) . '...' : $service_description; ?> + + +
+ @@ -39,14 +47,14 @@ - + + ); ?>" title="escape($service->service_output); ?>" class="state_monitoringState($service, 'service'); ?> service_handled ? 'handled' : ''; ?>"> · diff --git a/public/css/icinga/monitoring-colors.less b/public/css/icinga/monitoring-colors.less index 6ab287ae7..b2a7b8f3a 100644 --- a/public/css/icinga/monitoring-colors.less +++ b/public/css/icinga/monitoring-colors.less @@ -507,8 +507,6 @@ div.pivot-pagination { margin: 1em; table { - width: 1px; // Ensures that its cells are really of fixed width - table-layout: fixed; border-spacing: 0.2em; border-collapse: separate; border: 1px solid LightGrey; @@ -516,8 +514,7 @@ div.pivot-pagination { td { padding: 0; - width: 1.7em; - height: 1.7em; + line-height: 1em; background-color: #fbfbfb; &:hover, &.active { @@ -525,63 +522,65 @@ div.pivot-pagination { } a { - padding: 10% 50%; + width: 16px; + height: 16px; + display: block; } } } } table.pivot { - width: 1px; // Ensures that its cells are really of fixed width - table-layout: fixed; - border-spacing: 0.2em; - border-collapse: separate; - - th, td { - width: 0.5em; - } - thead { th { height: 6em; - padding: 0 0 1em 1.4em; - vertical-align: bottom; + padding: 2px; + position: relative; - &:first-of-type { - width: 4em; - } + div { + top: 2px; + left: 2px; + right: -1.5em; + position: absolute; + padding-left: 1.2em; - span { - font-size: 0.8em; - line-height: 2.4em; - white-space: nowrap; - display: inline-block; + span { + width: 1.5em; + margin-right: 4px; + margin-top: 4em; + line-height: 2em; + white-space: nowrap; + display: block; + float: left; - transform: rotate(-45deg); - transform-origin: bottom left; - -o-transform: rotate(-45deg); - -o-transform-origin: bottom left; - -ms-transform: rotate(-45deg); - -ms-transform-origin: bottom left; - -moz-transform: rotate(-45deg); - -moz-transform-origin: bottom left; - -webkit-transform: rotate(-45deg); - -webkit-transform-origin: bottom left; - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + transform: rotate(-45deg); + transform-origin: bottom left; + -o-transform: rotate(-45deg); + -o-transform-origin: bottom left; + -ms-transform: rotate(-45deg); + -ms-transform-origin: bottom left; + -moz-transform: rotate(-45deg); + -moz-transform-origin: bottom left; + -webkit-transform: rotate(-45deg); + -webkit-transform-origin: bottom left; + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); + + abbr { + font-size: 0.8em; + } + } } } } tbody { th { - width: 4em; - font-size: 0.8em; - line-height: 2.2em; - padding-right: 1.2em; + padding: 0 14px 0 0; a { - color: black; + font-size: 0.8em; text-decoration: none; + color: black; &:hover { color: #666; @@ -590,43 +589,47 @@ table.pivot { } td { - padding: 0; + min-width: 1.5em; + min-height: 1.5em; + padding: 2px; text-align: center; - border-radius: 0.5em; a { - padding: 20% 50%; - } + width: 1.5em; + height: 1.5em; + display: block; + border-radius: 0.5em; - &.state_ok { - background-color: @colorOk; - } - - &.state_pending { - background-color: @colorPending; - } - - &.state_warning { - background-color: @colorWarning; - - &.handled { - background-color: @colorWarningHandled; + &.state_ok { + background-color: @colorOk; } - } - &.state_critical { - background-color: @colorCritical; - - &.handled { - background-color: @colorCriticalHandled; + &.state_pending { + background-color: @colorPending; } - } - &.state_unknown { - background-color: @colorUnknown; + &.state_warning { + background-color: @colorWarning; - &.handled { - background-color: @colorUnknownHandled; + &.handled { + background-color: @colorWarningHandled; + } + } + + &.state_critical { + background-color: @colorCritical; + + &.handled { + background-color: @colorCriticalHandled; + } + } + + &.state_unknown { + background-color: @colorUnknown; + + &.handled { + background-color: @colorUnknownHandled; + } } } }