Merge branch 'bugfix/service-grid-grouping-postgres-9333'
Conflicts: modules/monitoring/application/controllers/ListController.php modules/monitoring/library/Monitoring/Backend/Ido/Query/IdoQuery.php fixes #9333 fixes #9538
This commit is contained in:
commit
c294283636
|
@ -4,23 +4,23 @@
|
||||||
namespace Icinga\Application\Modules;
|
namespace Icinga\Application\Modules;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Zend_Controller_Router_Route;
|
||||||
use Zend_Controller_Router_Route_Abstract;
|
use Zend_Controller_Router_Route_Abstract;
|
||||||
use Zend_Controller_Router_Route as Route;
|
use Zend_Controller_Router_Route_Regex;
|
||||||
use Zend_Controller_Router_Route_Regex as RegexRoute;
|
|
||||||
use Icinga\Application\ApplicationBootstrap;
|
use Icinga\Application\ApplicationBootstrap;
|
||||||
use Icinga\Application\Config;
|
use Icinga\Application\Config;
|
||||||
use Icinga\Application\Icinga;
|
use Icinga\Application\Icinga;
|
||||||
use Icinga\Application\Logger;
|
use Icinga\Application\Logger;
|
||||||
use Icinga\Data\ConfigObject;
|
use Icinga\Data\ConfigObject;
|
||||||
|
use Icinga\Exception\IcingaException;
|
||||||
|
use Icinga\Exception\ProgrammingError;
|
||||||
|
use Icinga\Module\Setup\SetupWizard;
|
||||||
|
use Icinga\Util\File;
|
||||||
use Icinga\Util\Translator;
|
use Icinga\Util\Translator;
|
||||||
use Icinga\Web\Hook;
|
use Icinga\Web\Hook;
|
||||||
use Icinga\Web\Menu;
|
use Icinga\Web\Menu;
|
||||||
use Icinga\Web\Widget;
|
use Icinga\Web\Widget;
|
||||||
use Icinga\Web\Widget\Dashboard\Pane;
|
use Icinga\Web\Widget\Dashboard\Pane;
|
||||||
use Icinga\Module\Setup\SetupWizard;
|
|
||||||
use Icinga\Util\File;
|
|
||||||
use Icinga\Exception\ProgrammingError;
|
|
||||||
use Icinga\Exception\IcingaException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module handling
|
* Module handling
|
||||||
|
@ -188,7 +188,7 @@ class Module
|
||||||
/**
|
/**
|
||||||
* A set of menu elements
|
* A set of menu elements
|
||||||
*
|
*
|
||||||
* @var array
|
* @var Menu[]
|
||||||
*/
|
*/
|
||||||
protected $menuItems = array();
|
protected $menuItems = array();
|
||||||
|
|
||||||
|
@ -770,6 +770,7 @@ class Module
|
||||||
{
|
{
|
||||||
$this->launchConfigScript();
|
$this->launchConfigScript();
|
||||||
$tabs = Widget::create('tabs');
|
$tabs = Widget::create('tabs');
|
||||||
|
/** @var \Icinga\Web\Widget\Tabs $tabs */
|
||||||
$tabs->add('info', array(
|
$tabs->add('info', array(
|
||||||
'url' => 'config/module',
|
'url' => 'config/module',
|
||||||
'urlParams' => array('name' => $this->getName()),
|
'urlParams' => array('name' => $this->getName()),
|
||||||
|
@ -1039,12 +1040,13 @@ class Module
|
||||||
protected function registerRoutes()
|
protected function registerRoutes()
|
||||||
{
|
{
|
||||||
$router = $this->app->getFrontController()->getRouter();
|
$router = $this->app->getFrontController()->getRouter();
|
||||||
|
/** @var \Zend_Controller_Router_Rewrite $router */
|
||||||
foreach ($this->routes as $name => $route) {
|
foreach ($this->routes as $name => $route) {
|
||||||
$router->addRoute($name, $route);
|
$router->addRoute($name, $route);
|
||||||
}
|
}
|
||||||
$router->addRoute(
|
$router->addRoute(
|
||||||
$this->name . '_jsprovider',
|
$this->name . '_jsprovider',
|
||||||
new Route(
|
new Zend_Controller_Router_Route(
|
||||||
'js/' . $this->name . '/:file',
|
'js/' . $this->name . '/:file',
|
||||||
array(
|
array(
|
||||||
'controller' => 'static',
|
'controller' => 'static',
|
||||||
|
@ -1055,7 +1057,7 @@ class Module
|
||||||
);
|
);
|
||||||
$router->addRoute(
|
$router->addRoute(
|
||||||
$this->name . '_img',
|
$this->name . '_img',
|
||||||
new RegexRoute(
|
new Zend_Controller_Router_Route_Regex(
|
||||||
'img/' . $this->name . '/(.+)',
|
'img/' . $this->name . '/(.+)',
|
||||||
array(
|
array(
|
||||||
'controller' => 'static',
|
'controller' => 'static',
|
||||||
|
|
|
@ -4,12 +4,11 @@
|
||||||
namespace Icinga\Data;
|
namespace Icinga\Data;
|
||||||
|
|
||||||
use Icinga\Data\Filter\Filter;
|
use Icinga\Data\Filter\Filter;
|
||||||
use Icinga\Data\SimpleQuery;
|
|
||||||
use Icinga\Application\Icinga;
|
use Icinga\Application\Icinga;
|
||||||
use Icinga\Web\Paginator\Adapter\QueryAdapter;
|
use Icinga\Web\Paginator\Adapter\QueryAdapter;
|
||||||
use Zend_Paginator;
|
use Zend_Paginator;
|
||||||
|
|
||||||
class PivotTable
|
class PivotTable implements Sortable
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* The query to fetch as pivot table
|
* The query to fetch as pivot table
|
||||||
|
@ -19,53 +18,74 @@ class PivotTable
|
||||||
protected $baseQuery;
|
protected $baseQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The query to fetch the x axis labels
|
* X-axis pivot column
|
||||||
*
|
|
||||||
* @var SimpleQuery
|
|
||||||
*/
|
|
||||||
protected $xAxisQuery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The query to fetch the y axis labels
|
|
||||||
*
|
|
||||||
* @var SimpleQuery
|
|
||||||
*/
|
|
||||||
protected $yAxisQuery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The column that contains the labels for the x axis
|
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $xAxisColumn;
|
protected $xAxisColumn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The column that contains the labels for the y axis
|
* Y-axis pivot column
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $yAxisColumn;
|
protected $yAxisColumn;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The filter being applied on the query for the x axis
|
* Column for sorting the result set
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $order = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The filter being applied on the query for the x-axis
|
||||||
*
|
*
|
||||||
* @var Filter
|
* @var Filter
|
||||||
*/
|
*/
|
||||||
protected $xAxisFilter;
|
protected $xAxisFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The filter being applied on the query for the y axis
|
* The filter being applied on the query for the y-axis
|
||||||
*
|
*
|
||||||
* @var Filter
|
* @var Filter
|
||||||
*/
|
*/
|
||||||
protected $yAxisFilter;
|
protected $yAxisFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The query to fetch the leading x-axis rows and their headers
|
||||||
|
*
|
||||||
|
* @var SimpleQuery
|
||||||
|
*/
|
||||||
|
protected $xAxisQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The query to fetch the leading y-axis rows and their headers
|
||||||
|
*
|
||||||
|
* @var SimpleQuery
|
||||||
|
*/
|
||||||
|
protected $yAxisQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X-axis header column
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
protected $xAxisHeader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Y-axis header column
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
protected $yAxisHeader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new pivot table
|
* Create a new pivot table
|
||||||
*
|
*
|
||||||
* @param SimpleQuery $query The query to fetch as pivot table
|
* @param SimpleQuery $query The query to fetch as pivot table
|
||||||
* @param string $xAxisColumn The column that contains the labels for the x axis
|
* @param string $xAxisColumn X-axis pivot column
|
||||||
* @param string $yAxisColumn The column that contains the labels for the y axis
|
* @param string $yAxisColumn Y-axis pivot column
|
||||||
*/
|
*/
|
||||||
public function __construct(SimpleQuery $query, $xAxisColumn, $yAxisColumn)
|
public function __construct(SimpleQuery $query, $xAxisColumn, $yAxisColumn)
|
||||||
{
|
{
|
||||||
|
@ -75,7 +95,32 @@ class PivotTable
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the filter to apply on the query for the x axis
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getOrder()
|
||||||
|
{
|
||||||
|
return $this->order;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function hasOrder()
|
||||||
|
{
|
||||||
|
return ! empty($this->order);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function order($field, $direction = null)
|
||||||
|
{
|
||||||
|
$this->order[$field] = $direction;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the filter to apply on the query for the x-axis
|
||||||
*
|
*
|
||||||
* @param Filter $filter
|
* @param Filter $filter
|
||||||
*
|
*
|
||||||
|
@ -88,7 +133,7 @@ class PivotTable
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the filter to apply on the query for the y axis
|
* Set the filter to apply on the query for the y-axis
|
||||||
*
|
*
|
||||||
* @param Filter $filter
|
* @param Filter $filter
|
||||||
*
|
*
|
||||||
|
@ -100,6 +145,56 @@ class PivotTable
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the x-axis header
|
||||||
|
*
|
||||||
|
* Defaults to {@link $xAxisColumn} in case no x-axis header has been set using {@link setXAxisHeader()}
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getXAxisHeader()
|
||||||
|
{
|
||||||
|
return $this->xAxisHeader !== null ? $this->xAxisHeader : $this->xAxisColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the x-axis header
|
||||||
|
*
|
||||||
|
* @param string $xAxisHeader
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setXAxisHeader($xAxisHeader)
|
||||||
|
{
|
||||||
|
$this->xAxisHeader = (string) $xAxisHeader;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the y-axis header
|
||||||
|
*
|
||||||
|
* Defaults to {@link $yAxisColumn} in case no x-axis header has been set using {@link setYAxisHeader()}
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getYAxisHeader()
|
||||||
|
{
|
||||||
|
return $this->yAxisHeader !== null ? $this->yAxisHeader : $this->yAxisColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the y-axis header
|
||||||
|
*
|
||||||
|
* @param string $yAxisHeader
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setYAxisHeader($yAxisHeader)
|
||||||
|
{
|
||||||
|
$this->yAxisHeader = (string) $yAxisHeader;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the value for the given request parameter
|
* Return the value for the given request parameter
|
||||||
*
|
*
|
||||||
|
@ -131,17 +226,19 @@ class PivotTable
|
||||||
{
|
{
|
||||||
if ($this->xAxisQuery === null) {
|
if ($this->xAxisQuery === null) {
|
||||||
$this->xAxisQuery = clone $this->baseQuery;
|
$this->xAxisQuery = clone $this->baseQuery;
|
||||||
$this->xAxisQuery->group($this->xAxisColumn);
|
$xAxisHeader = $this->getXAxisHeader();
|
||||||
$this->xAxisQuery->columns(array($this->xAxisColumn));
|
$columns = array($this->xAxisColumn, $xAxisHeader);
|
||||||
$this->xAxisQuery->setUseSubqueryCount();
|
$this->xAxisQuery->group(array_unique($columns)); // xAxisColumn and header may be the same column
|
||||||
|
$this->xAxisQuery->columns($columns);
|
||||||
|
|
||||||
if ($this->xAxisFilter !== null) {
|
if ($this->xAxisFilter !== null) {
|
||||||
$this->xAxisQuery->addFilter($this->xAxisFilter);
|
$this->xAxisQuery->addFilter($this->xAxisFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $this->xAxisQuery->hasOrder($this->xAxisColumn)) {
|
$this->xAxisQuery->order(
|
||||||
$this->xAxisQuery->order($this->xAxisColumn, 'asc');
|
$xAxisHeader,
|
||||||
}
|
isset($this->order[$xAxisHeader]) ? $this->order[$xAxisHeader] : self::SORT_ASC
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->xAxisQuery;
|
return $this->xAxisQuery;
|
||||||
|
@ -156,24 +253,25 @@ class PivotTable
|
||||||
{
|
{
|
||||||
if ($this->yAxisQuery === null) {
|
if ($this->yAxisQuery === null) {
|
||||||
$this->yAxisQuery = clone $this->baseQuery;
|
$this->yAxisQuery = clone $this->baseQuery;
|
||||||
$this->yAxisQuery->group($this->yAxisColumn);
|
$yAxisHeader = $this->getYAxisHeader();
|
||||||
$this->yAxisQuery->columns(array($this->yAxisColumn));
|
$columns = array($this->yAxisColumn, $yAxisHeader);
|
||||||
$this->yAxisQuery->setUseSubqueryCount();
|
$this->yAxisQuery->group(array_unique($columns)); // yAxisColumn and header may be the same column
|
||||||
|
$this->yAxisQuery->columns($columns);
|
||||||
|
|
||||||
if ($this->yAxisFilter !== null) {
|
if ($this->yAxisFilter !== null) {
|
||||||
$this->yAxisQuery->addFilter($this->yAxisFilter);
|
$this->yAxisQuery->addFilter($this->yAxisFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $this->yAxisQuery->hasOrder($this->yAxisColumn)) {
|
$this->yAxisQuery->order(
|
||||||
$this->yAxisQuery->order($this->yAxisColumn, 'asc');
|
$yAxisHeader,
|
||||||
|
isset($this->order[$yAxisHeader]) ? $this->order[$yAxisHeader] : self::SORT_ASC
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return $this->yAxisQuery;
|
return $this->yAxisQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a pagination adapter for the x axis query
|
* Return a pagination adapter for the x-axis query
|
||||||
*
|
*
|
||||||
* $limit and $page are taken from the current request if not given.
|
* $limit and $page are taken from the current request if not given.
|
||||||
*
|
*
|
||||||
|
@ -204,7 +302,7 @@ class PivotTable
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a pagination adapter for the y axis query
|
* Return a pagination adapter for the y-axis query
|
||||||
*
|
*
|
||||||
* $limit and $page are taken from the current request if not given.
|
* $limit and $page are taken from the current request if not given.
|
||||||
*
|
*
|
||||||
|
@ -235,7 +333,7 @@ class PivotTable
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the pivot table as array
|
* Return the pivot table as an array of pivot data and pivot header
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
@ -245,33 +343,39 @@ class PivotTable
|
||||||
($this->xAxisFilter === null && $this->yAxisFilter === null)
|
($this->xAxisFilter === null && $this->yAxisFilter === null)
|
||||||
|| ($this->xAxisFilter !== null && $this->yAxisFilter !== null)
|
|| ($this->xAxisFilter !== null && $this->yAxisFilter !== null)
|
||||||
) {
|
) {
|
||||||
$xAxis = $this->queryXAxis()->fetchColumn();
|
$xAxis = $this->queryXAxis()->fetchPairs();
|
||||||
$yAxis = $this->queryYAxis()->fetchColumn();
|
$yAxis = $this->queryYAxis()->fetchPairs();
|
||||||
} else {
|
} else {
|
||||||
if ($this->xAxisFilter !== null) {
|
if ($this->xAxisFilter !== null) {
|
||||||
$xAxis = $this->queryXAxis()->fetchColumn();
|
$xAxis = $this->queryXAxis()->fetchPairs();
|
||||||
$yAxis = $this->queryYAxis()->where($this->xAxisColumn, $xAxis)->fetchColumn();
|
$yAxis = $this->queryYAxis()->where($this->xAxisColumn, $xAxis)->fetchPairs();
|
||||||
} else { // $this->yAxisFilter !== null
|
} else { // $this->yAxisFilter !== null
|
||||||
$yAxis = $this->queryYAxis()->fetchColumn();
|
$yAxis = $this->queryYAxis()->fetchPairs();
|
||||||
$xAxis = $this->queryXAxis()->where($this->yAxisColumn, $yAxis)->fetchColumn();
|
$xAxis = $this->queryXAxis()->where($this->yAxisColumn, $yAxis)->fetchPairs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$pivotData = array();
|
||||||
$pivot = array();
|
$pivotHeader = array(
|
||||||
|
'cols' => $xAxis,
|
||||||
|
'rows' => $yAxis
|
||||||
|
);
|
||||||
if (! empty($xAxis) && ! empty($yAxis)) {
|
if (! empty($xAxis) && ! empty($yAxis)) {
|
||||||
$this->baseQuery->where($this->xAxisColumn, $xAxis)->where($this->yAxisColumn, $yAxis);
|
$xAxisKeys = array_keys($xAxis);
|
||||||
|
$yAxisKeys = array_keys($yAxis);
|
||||||
|
$this->baseQuery
|
||||||
|
->where($this->xAxisColumn, $xAxisKeys)
|
||||||
|
->where($this->yAxisColumn, $yAxisKeys);
|
||||||
|
|
||||||
foreach ($yAxis as $yLabel) {
|
foreach ($yAxisKeys as $yAxisKey) {
|
||||||
foreach ($xAxis as $xLabel) {
|
foreach ($xAxisKeys as $xAxisKey) {
|
||||||
$pivot[$yLabel][$xLabel] = null;
|
$pivotData[$yAxisKey][$xAxisKey] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->baseQuery as $row) {
|
foreach ($this->baseQuery as $row) {
|
||||||
$pivot[$row->{$this->yAxisColumn}][$row->{$this->xAxisColumn}] = $row;
|
$pivotData[$row->{$this->yAxisColumn}][$row->{$this->xAxisColumn}] = $row;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return array($pivotData, $pivotHeader);
|
||||||
return $pivot;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ class StyleSheet
|
||||||
protected static $lessFiles = array(
|
protected static $lessFiles = array(
|
||||||
'../application/fonts/fontello-ifont/css/ifont-embedded.css',
|
'../application/fonts/fontello-ifont/css/ifont-embedded.css',
|
||||||
'css/vendor/tipsy.css',
|
'css/vendor/tipsy.css',
|
||||||
|
'css/icinga/mixins.less',
|
||||||
'css/icinga/defaults.less',
|
'css/icinga/defaults.less',
|
||||||
'css/icinga/animation.less',
|
'css/icinga/animation.less',
|
||||||
'css/icinga/layout-colors.less',
|
'css/icinga/layout-colors.less',
|
||||||
|
|
|
@ -118,12 +118,12 @@ class SortBox extends AbstractWidget
|
||||||
if ($request === null) {
|
if ($request === null) {
|
||||||
$request = Icinga::app()->getRequest();
|
$request = Icinga::app()->getRequest();
|
||||||
}
|
}
|
||||||
|
if (null === $sort = $request->getParam('sort')) {
|
||||||
if (($sort = $request->getParam('sort'))) {
|
list($sort, $dir) = $this->getSortDefaults();
|
||||||
$this->query->order($sort, $request->getParam('dir'));
|
} else {
|
||||||
} elseif (($dir = $request->getParam('dir'))) {
|
list($_, $dir) = $this->getSortDefaults($sort);
|
||||||
$this->query->order(null, $dir);
|
|
||||||
}
|
}
|
||||||
|
$this->query->order($sort, $request->getParam('dir', $dir));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -148,8 +148,10 @@ class SortBox extends AbstractWidget
|
||||||
if ($column !== null && isset($sortRules[$column]['order'])) {
|
if ($column !== null && isset($sortRules[$column]['order'])) {
|
||||||
$direction = strtoupper($sortRules[$column]['order']) === Sortable::SORT_DESC ? 'desc' : 'asc';
|
$direction = strtoupper($sortRules[$column]['order']) === Sortable::SORT_DESC ? 'desc' : 'asc';
|
||||||
}
|
}
|
||||||
|
} elseif ($column === null) {
|
||||||
|
reset($this->sortFields);
|
||||||
|
$column = key($this->sortFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
return array($column, $direction);
|
return array($column, $direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -556,29 +556,36 @@ class Monitoring_ListController extends Controller
|
||||||
{
|
{
|
||||||
$this->addTitleTab('servicegrid', $this->translate('Service Grid'), $this->translate('Show the Service Grid'));
|
$this->addTitleTab('servicegrid', $this->translate('Service Grid'), $this->translate('Show the Service Grid'));
|
||||||
$this->setAutorefreshInterval(15);
|
$this->setAutorefreshInterval(15);
|
||||||
$problems = (bool) $this->params->shift('problems', 0);
|
|
||||||
$query = $this->backend->select()->from('servicestatus', array(
|
$query = $this->backend->select()->from('servicestatus', array(
|
||||||
|
'host_display_name',
|
||||||
'host_name',
|
'host_name',
|
||||||
'service_description',
|
'service_description',
|
||||||
'service_state',
|
'service_display_name',
|
||||||
|
'service_handled',
|
||||||
'service_output',
|
'service_output',
|
||||||
'service_handled'
|
'service_state'
|
||||||
));
|
));
|
||||||
$this->applyRestriction('monitoring/filter/objects', $query);
|
$this->applyRestriction('monitoring/filter/objects', $query);
|
||||||
$this->filterQuery($query);
|
$this->filterQuery($query);
|
||||||
$this->setupSortControl(array(
|
$filter = (bool) $this->params->shift('problems', false) ? Filter::where('service_problem', 1) : null;
|
||||||
'host_name' => $this->translate('Hostname'),
|
$pivot = $query
|
||||||
'service_description' => $this->translate('Service description')
|
->pivot(
|
||||||
), $query);
|
|
||||||
$pivot = $query->pivot(
|
|
||||||
'service_description',
|
'service_description',
|
||||||
'host_name',
|
'host_name',
|
||||||
$problems ? Filter::where('service_problem', 1) : null,
|
$filter,
|
||||||
$problems ? Filter::where('service_problem', 1) : null
|
$filter ? clone $filter : null
|
||||||
);
|
)
|
||||||
$this->view->pivot = $pivot;
|
->setXAxisHeader('service_display_name')
|
||||||
|
->setYAxisHeader('host_display_name');
|
||||||
|
$this->setupSortControl(array(
|
||||||
|
'host_display_name' => $this->translate('Hostname'),
|
||||||
|
'service_display_name' => $this->translate('Service Name')
|
||||||
|
), $pivot);
|
||||||
$this->view->horizontalPaginator = $pivot->paginateXAxis();
|
$this->view->horizontalPaginator = $pivot->paginateXAxis();
|
||||||
$this->view->verticalPaginator = $pivot->paginateYAxis();
|
$this->view->verticalPaginator = $pivot->paginateYAxis();
|
||||||
|
list($pivotData, $pivotHeader) = $pivot->toArray();
|
||||||
|
$this->view->pivotData = $pivotData;
|
||||||
|
$this->view->pivotHeader = $pivotHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,19 +12,14 @@ if (! $this->compact): ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<div class="content" data-base-target="_next">
|
<div class="content" data-base-target="_next">
|
||||||
<?php
|
<?php
|
||||||
|
if (empty($pivotData)) {
|
||||||
$hasHeader = false;
|
|
||||||
$pivotData = $this->pivot->toArray();
|
|
||||||
if (count($pivotData) === 0) {
|
|
||||||
echo $this->translate('No services found matching the filter') . '</div>';
|
echo $this->translate('No services found matching the filter') . '</div>';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$hostFilter = '(host_name=' . implode('|host_name=', array_keys($pivotData)) . ')';
|
$hostFilter = '(host_name=' . implode('|host_name=', array_keys($pivotData)) . ')';
|
||||||
?>
|
?>
|
||||||
<table class="pivot servicestates">
|
|
||||||
<?php foreach ($pivotData as $host_name => $serviceStates): ?>
|
<table class="service-grid-table">
|
||||||
<?php if (!$hasHeader): ?>
|
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th><?= $this->partial(
|
<th><?= $this->partial(
|
||||||
|
@ -35,71 +30,63 @@ $hostFilter = '(host_name=' . implode('|host_name=', array_keys($pivotData)) . '
|
||||||
'yAxisPaginator' => $verticalPaginator
|
'yAxisPaginator' => $verticalPaginator
|
||||||
)
|
)
|
||||||
); ?></th>
|
); ?></th>
|
||||||
<th colspan="<?= count($serviceStates); ?>">
|
<?php foreach ($pivotHeader['cols'] as $serviceDescription => $serviceDisplayName): ?>
|
||||||
<div>
|
<th class="rotate-45"><div><span><?= $this->qlink(
|
||||||
<?php
|
$this->ellipsis($serviceDisplayName, 18),
|
||||||
$serviceDescriptions = array_keys($serviceStates);
|
|
||||||
$serviceFilter = '(service_description=' . implode('|service_description=', $serviceDescriptions) . ')';
|
|
||||||
|
|
||||||
foreach ($serviceDescriptions as $service_description): ?>
|
|
||||||
<span>
|
|
||||||
<?= $this->qlink(
|
|
||||||
'<abbr>' . (strlen($service_description) > 18 ? substr($service_description, 0, 18) . '...' : $service_description) . '</abbr>',
|
|
||||||
'monitoring/list/services?' . $hostFilter,
|
'monitoring/list/services?' . $hostFilter,
|
||||||
array(
|
array('service_description' => $serviceDescription),
|
||||||
'service_description' => $service_description
|
array('title' => sprintf(
|
||||||
),
|
$this->translate('List all services with the name "%s" on all reported hosts'),
|
||||||
array(
|
$serviceDisplayName
|
||||||
'title' => sprintf($this->translate('List all services with the name "%s" on all reported hosts'), $service_description)
|
)),
|
||||||
),
|
|
||||||
false
|
false
|
||||||
); ?>
|
) ?></span></div></th>
|
||||||
</span>
|
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php $hasHeader = true; ?>
|
<?php foreach ($pivotHeader['rows'] as $hostName => $hostDisplayName): ?>
|
||||||
<?php endif ?>
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th><?php
|
||||||
<?= $this->qlink(
|
$services = $pivotData[$hostName];
|
||||||
$host_name,
|
$serviceFilter = '(service_description=' . implode('|service_description=', array_keys($services)) . ')';
|
||||||
|
echo $this->qlink(
|
||||||
|
$hostDisplayName,
|
||||||
'monitoring/list/services?' . $serviceFilter,
|
'monitoring/list/services?' . $serviceFilter,
|
||||||
array('host' => $host_name),
|
array('host_name' => $hostName),
|
||||||
array('title' => sprintf($this->translate('List all reported services on host %s'), $host_name))
|
array('title' => sprintf($this->translate('List all reported services on host %s'), $hostDisplayName))
|
||||||
); ?>
|
);
|
||||||
</th>
|
?></th>
|
||||||
<?php foreach (array_values($serviceStates) as $service): ?>
|
<?php foreach (array_keys($pivotHeader['cols']) as $serviceDescription): ?>
|
||||||
<?php if ($service !== null): ?>
|
|
||||||
<td>
|
<td>
|
||||||
<span class="sr-only" id="<?= $service->host_name . '_' . $service->service_description . '_desc'; ?>">
|
<?php
|
||||||
<?= $this->escape($service->service_output); ?>
|
$service = $pivotData[$hostName][$serviceDescription];
|
||||||
|
if ($service === null): ?>
|
||||||
|
<span aria-hidden="true">·</span>
|
||||||
|
<?php continue; endif ?>
|
||||||
|
<?php $ariaDescribedById = $this->protectId($service->host_name . '_' . $service->service_description . '_desc') ?>
|
||||||
|
<span class="sr-only" id="<?= $ariaDescribedById ?>">
|
||||||
|
<?= $this->escape($service->service_output) ?>
|
||||||
</span>
|
</span>
|
||||||
<?= $this->qlink(
|
<?= $this->qlink(
|
||||||
'',
|
'',
|
||||||
'monitoring/show/service',
|
'monitoring/show/service',
|
||||||
array(
|
array(
|
||||||
'host' => $service->host_name,
|
'host' => $hostName,
|
||||||
'service' => $service->service_description
|
'service' => $serviceDescription
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'aria-describedby' => $service->host_name . '_' . $service->service_description . '_desc',
|
'aria-describedby' => $ariaDescribedById,
|
||||||
'class' => 'state_' . Service::getStateText($service->service_state). ($service->service_handled ? ' handled' : ''),
|
'class' => 'bg-state-' . Service::getStateText($service->service_state) . ($service->service_handled ? ' handled' : ''),
|
||||||
'title' => $this->escape($service->service_output),
|
'title' => $this->escape($service->service_output),
|
||||||
'aria-label' => sprintf(
|
'aria-label' => sprintf(
|
||||||
$this->translate('Show detailed information for service %s on host %s'),
|
$this->translate('Show detailed information for service %s on host %s'),
|
||||||
$service->service_description,
|
$service->service_display_name,
|
||||||
$service->host_name
|
$service->host_display_name
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
); ?>
|
); ?>
|
||||||
</td>
|
</td>
|
||||||
<?php else: ?>
|
|
||||||
<td><span aria-hidden="true">·</span></td>
|
|
||||||
<?php endif ?>
|
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
|
|
|
@ -240,3 +240,9 @@ $dashboard->add(
|
||||||
$this->translate('Host Problems'),
|
$this->translate('Host Problems'),
|
||||||
'monitoring/list/hosts?host_problem=1&sort=host_severity'
|
'monitoring/list/hosts?host_problem=1&sort=host_severity'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CSS
|
||||||
|
*/
|
||||||
|
$this->provideCssFile('colors.less');
|
||||||
|
$this->provideCssFile('service-grid.less');
|
||||||
|
|
|
@ -257,62 +257,65 @@ class HoststatusQuery extends IdoQuery
|
||||||
*/
|
*/
|
||||||
public function getGroup()
|
public function getGroup()
|
||||||
{
|
{
|
||||||
$group = array();
|
$group = parent::getGroup() ?: array();
|
||||||
if ($this->hasJoinedVirtualTable('hostgroups') || $this->hasJoinedVirtualTable('services')) {
|
if (! is_array($group)) {
|
||||||
$group = array('h.host_id', 'ho.object_id');
|
$group = array($group);
|
||||||
if ($this->hasJoinedVirtualTable('hoststatus')) {
|
|
||||||
$group[] = 'hs.hoststatus_id';
|
|
||||||
}
|
}
|
||||||
|
$groupedTables = array();
|
||||||
if ($this->hasJoinedVirtualTable('serviceproblemsummary')) {
|
|
||||||
$group[] = 'sps.unhandled_services_count';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->hasJoinedVirtualTable('hostgroups')) {
|
|
||||||
$selected = false;
|
|
||||||
foreach ($this->columns as $alias => $column) {
|
|
||||||
if ($column instanceof Zend_Db_Expr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$table = $this->aliasToTableName(
|
|
||||||
$this->hasAliasName($alias) ? $alias : $this->customAliasToAlias($alias)
|
|
||||||
);
|
|
||||||
if ($table === 'hostgroups') {
|
|
||||||
$selected = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($selected) {
|
|
||||||
$group[] = 'hg.hostgroup_id';
|
|
||||||
$group[] = 'hgo.object_id';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->hasJoinedVirtualTable('servicegroups')) {
|
if ($this->hasJoinedVirtualTable('servicegroups')) {
|
||||||
$selected = false;
|
$serviceGroupColumns = array_keys($this->columnMap['servicegroups']);
|
||||||
|
$selectedServiceGroupColumns = array_intersect($serviceGroupColumns, array_keys($this->columns));
|
||||||
|
if (! empty($selectedServiceGroupColumns)) {
|
||||||
|
$group[] = 'ho.object_id';
|
||||||
|
$group[] = 'h.host_id';
|
||||||
|
$group[] = 'sgo.object_id';
|
||||||
|
$group[] = 'sg.servicegroup_id';
|
||||||
|
$groupedTables['hosts'] = true;
|
||||||
|
$groupedTables['servicegroups'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($this->hasJoinedVirtualTable('hostgroups')) {
|
||||||
|
$hostGroupColumns = array_keys($this->columnMap['hostgroups']);
|
||||||
|
$selectedHostGroupColumns = array_intersect($hostGroupColumns, array_keys($this->columns));
|
||||||
|
if (! empty($selectedHostGroupColumns)) {
|
||||||
|
if (! isset($groupedTables['hosts'])) {
|
||||||
|
$group[] = 'ho.object_id';
|
||||||
|
$group[] = 'h.host_id';
|
||||||
|
$groupedTables['hosts'] = true;
|
||||||
|
}
|
||||||
|
$group[] = 'hgo.object_id';
|
||||||
|
$group[] = 'hg.hostgroup_id';
|
||||||
|
$groupedTables['hostgroups'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! empty($groupedTables)) {
|
||||||
foreach ($this->columns as $alias => $column) {
|
foreach ($this->columns as $alias => $column) {
|
||||||
if ($column instanceof Zend_Db_Expr) {
|
if ($column instanceof Zend_Db_Expr || $column === '(NULL)') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
$tableName = $this->aliasToTableName(
|
||||||
$table = $this->aliasToTableName(
|
|
||||||
$this->hasAliasName($alias) ? $alias : $this->customAliasToAlias($alias)
|
$this->hasAliasName($alias) ? $alias : $this->customAliasToAlias($alias)
|
||||||
);
|
);
|
||||||
if ($table === 'servicegroups') {
|
if (isset($groupedTables[$tableName])) {
|
||||||
$selected = true;
|
continue;
|
||||||
|
}
|
||||||
|
switch ($tableName) {
|
||||||
|
case 'hoststatus':
|
||||||
|
$group[] = 'hs.hoststatus_id';
|
||||||
break;
|
break;
|
||||||
|
case 'serviceproblemsummary':
|
||||||
|
$group[] = 'sps.unhandled_services_count';
|
||||||
|
break;
|
||||||
|
case 'services':
|
||||||
|
$group[] = 'so.object_id';
|
||||||
|
$group[] = 's.service_id';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
$groupedTables[$tableName] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($selected) {
|
|
||||||
$group[] = 'sg.servicegroup_id';
|
|
||||||
$group[] = 'sgo.object_id';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $group;
|
return $group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -461,17 +461,23 @@ abstract class IdoQuery extends DbQuery
|
||||||
if ($filter->getExpression() === '*') {
|
if ($filter->getExpression() === '*') {
|
||||||
return; // Wildcard only filters are ignored so stop early here to avoid joining a table for nothing
|
return; // Wildcard only filters are ignored so stop early here to avoid joining a table for nothing
|
||||||
}
|
}
|
||||||
|
$alias = $filter->getColumn();
|
||||||
$col = $filter->getColumn();
|
$this->requireColumn($alias);
|
||||||
$this->requireColumn($col);
|
if ($this->isCustomvar($alias)) {
|
||||||
|
$column = $this->getCustomvarColumnName($alias);
|
||||||
if ($this->isCustomvar($col)) {
|
|
||||||
$col = $this->getCustomvarColumnName($col);
|
|
||||||
} else {
|
} else {
|
||||||
$col = $this->aliasToColumnName($col);
|
$column = $this->aliasToColumnName($alias);
|
||||||
}
|
}
|
||||||
|
if (isset($this->columnsWithoutCollation[$alias])) {
|
||||||
|
$expression = $filter->getExpression();
|
||||||
|
if (is_array($expression)) {
|
||||||
|
$filter->setExpression(array_map('strtolower', $expression));
|
||||||
|
} else {
|
||||||
|
$filter->setExpression(strtolower($expression));
|
||||||
|
|
||||||
$filter->setColumn($col);
|
}
|
||||||
|
}
|
||||||
|
$filter->setColumn($column);
|
||||||
} else {
|
} else {
|
||||||
foreach ($filter->filters() as $filter) {
|
foreach ($filter->filters() as $filter) {
|
||||||
$this->requireFilterColumns($filter);
|
$this->requireFilterColumns($filter);
|
||||||
|
@ -489,48 +495,11 @@ abstract class IdoQuery extends DbQuery
|
||||||
return parent::addFilter($filter);
|
return parent::addFilter($filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Recurse the given filter and ensure that any string conversion is case-insensitive
|
|
||||||
*
|
|
||||||
* @param Filter $filter
|
|
||||||
*/
|
|
||||||
protected function lowerColumnsWithoutCollation(Filter $filter)
|
|
||||||
{
|
|
||||||
if ($filter instanceof FilterExpression) {
|
|
||||||
if (
|
|
||||||
in_array($filter->getColumn(), $this->columnsWithoutCollation)
|
|
||||||
&& strpos($filter->getColumn(), 'LOWER') !== 0
|
|
||||||
) {
|
|
||||||
$filter->setColumn('LOWER(' . $filter->getColumn() . ')');
|
|
||||||
$expression = $filter->getExpression();
|
|
||||||
if (is_array($expression)) {
|
|
||||||
$filter->setExpression(array_map('strtolower', $expression));
|
|
||||||
} else {
|
|
||||||
$filter->setExpression(strtolower($expression));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
foreach ($filter->filters() as $chainedFilter) {
|
|
||||||
$this->lowerColumnsWithoutCollation($chainedFilter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function applyFilterSql($select)
|
|
||||||
{
|
|
||||||
if (! empty($this->columnsWithoutCollation)) {
|
|
||||||
$this->lowerColumnsWithoutCollation($this->filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::applyFilterSql($select);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function where($condition, $value = null)
|
public function where($condition, $value = null)
|
||||||
{
|
{
|
||||||
if ($value === '*') {
|
if ($value === '*') {
|
||||||
return $this; // Wildcard only filters are ignored so stop early here to avoid joining a table for nothing
|
return $this; // Wildcard only filters are ignored so stop early here to avoid joining a table for nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->requireColumn($condition);
|
$this->requireColumn($condition);
|
||||||
$col = $this->getMappedField($condition);
|
$col = $this->getMappedField($condition);
|
||||||
if ($col === null) {
|
if ($col === null) {
|
||||||
|
@ -578,7 +547,6 @@ abstract class IdoQuery extends DbQuery
|
||||||
if (! empty($this->columnsWithoutCollation)) {
|
if (! empty($this->columnsWithoutCollation)) {
|
||||||
return in_array($column, $this->columnsWithoutCollation) || strpos($column, 'LOWER') !== 0;
|
return in_array($column, $this->columnsWithoutCollation) || strpos($column, 'LOWER') !== 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return preg_match('/ COLLATE .+$/', $column) === 1;
|
return preg_match('/ COLLATE .+$/', $column) === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,27 +571,27 @@ abstract class IdoQuery extends DbQuery
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply postgresql specific query initialization
|
* Apply PostgreSQL specific query initialization
|
||||||
*/
|
*/
|
||||||
private function initializeForPostgres()
|
private function initializeForPostgres()
|
||||||
{
|
{
|
||||||
$this->customVarsJoinTemplate =
|
$this->customVarsJoinTemplate =
|
||||||
'%1$s = %2$s.object_id AND LOWER(%2$s.varname) = %3$s';
|
'%1$s = %2$s.object_id AND LOWER(%2$s.varname) = %3$s';
|
||||||
foreach ($this->columnMap as $table => &$columns) {
|
foreach ($this->columnMap as $table => &$columns) {
|
||||||
foreach ($columns as $key => & $value) {
|
foreach ($columns as $alias => &$column) {
|
||||||
$value = preg_replace('/ COLLATE .+$/', '', $value, -1, $count);
|
if (false !== $pos = strpos($column, ' COLLATE')) {
|
||||||
if ($count > 0) {
|
$column = 'LOWER(' . substr($column, 0, $pos) . ')';
|
||||||
$this->columnsWithoutCollation[] = $this->getMappedField($key);
|
$this->columnsWithoutCollation[$alias] = true;
|
||||||
}
|
}
|
||||||
$value = preg_replace(
|
$column = preg_replace(
|
||||||
'/inet_aton\(([[:word:].]+)\)/i',
|
'/inet_aton\(([[:word:].]+)\)/i',
|
||||||
'(CASE WHEN $1 ~ \'(?:[0-9]{1,3}\\\\.){3}[0-9]{1,3}\' THEN $1::inet - \'0.0.0.0\' ELSE NULL END)',
|
'(CASE WHEN $1 ~ \'(?:[0-9]{1,3}\\\\.){3}[0-9]{1,3}\' THEN $1::inet - \'0.0.0.0\' ELSE NULL END)',
|
||||||
$value
|
$column
|
||||||
);
|
);
|
||||||
$value = preg_replace(
|
$column = preg_replace(
|
||||||
'/UNIX_TIMESTAMP(\((?>[^()]|(?-1))*\))/i',
|
'/UNIX_TIMESTAMP(\((?>[^()]|(?-1))*\))/i',
|
||||||
'CASE WHEN ($1 < \'1970-01-03 00:00:00+00\'::timestamp with time zone) THEN 0 ELSE UNIX_TIMESTAMP($1) END',
|
'CASE WHEN ($1 < \'1970-01-03 00:00:00+00\'::timestamp with time zone) THEN 0 ELSE UNIX_TIMESTAMP($1) END',
|
||||||
$value
|
$column
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -381,68 +381,60 @@ class ServicestatusQuery extends IdoQuery
|
||||||
if (! is_array($group)) {
|
if (! is_array($group)) {
|
||||||
$group = array($group);
|
$group = array($group);
|
||||||
}
|
}
|
||||||
|
$groupedTables = array();
|
||||||
if ($this->hasJoinedVirtualTable('hostgroups') || $this->hasJoinedVirtualTable('servicegroups')) {
|
|
||||||
$group[] = 's.service_id';
|
|
||||||
$group[] = 'so.object_id';
|
|
||||||
|
|
||||||
if ($this->hasJoinedVirtualTable('hosts')) {
|
|
||||||
$group[] = 'h.host_id';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->hasJoinedVirtualTable('hoststatus')) {
|
|
||||||
$group[] = 'hs.hoststatus_id';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->hasJoinedVirtualTable('servicestatus')) {
|
|
||||||
$group[] = 'ss.servicestatus_id';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->hasJoinedVirtualTable('hostgroups')) {
|
|
||||||
$selected = false;
|
|
||||||
foreach ($this->columns as $alias => $column) {
|
|
||||||
if ($column instanceof Zend_Db_Expr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$table = $this->aliasToTableName(
|
|
||||||
$this->hasAliasName($alias) ? $alias : $this->customAliasToAlias($alias)
|
|
||||||
);
|
|
||||||
if ($table === 'hostgroups') {
|
|
||||||
$selected = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($selected) {
|
|
||||||
$group[] = 'hg.hostgroup_id';
|
|
||||||
$group[] = 'hgo.object_id';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->hasJoinedVirtualTable('servicegroups')) {
|
if ($this->hasJoinedVirtualTable('servicegroups')) {
|
||||||
$selected = false;
|
$serviceGroupColumns = array_keys($this->columnMap['servicegroups']);
|
||||||
|
$selectedServiceGroupColumns = array_intersect($serviceGroupColumns, array_keys($this->columns));
|
||||||
|
if (! empty($selectedServiceGroupColumns)) {
|
||||||
|
$group[] = 'so.object_id';
|
||||||
|
$group[] = 's.service_id';
|
||||||
|
$group[] = 'sgo.object_id';
|
||||||
|
$group[] = 'sg.servicegroup_id';
|
||||||
|
$groupedTables['services'] = true;
|
||||||
|
$groupedTables['servicegroups'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($this->hasJoinedVirtualTable('hostgroups')) {
|
||||||
|
$hostGroupColumns = array_keys($this->columnMap['hostgroups']);
|
||||||
|
$selectedHostGroupColumns = array_intersect($hostGroupColumns, array_keys($this->columns));
|
||||||
|
if (! empty($selectedHostGroupColumns)) {
|
||||||
|
if (! isset($groupedTables['services'])) {
|
||||||
|
$group[] = 'so.object_id';
|
||||||
|
$group[] = 's.service_id';
|
||||||
|
$groupedTables['services'] = true;
|
||||||
|
}
|
||||||
|
$group[] = 'hgo.object_id';
|
||||||
|
$group[] = 'hg.hostgroup_id';
|
||||||
|
$groupedTables['hostgroups'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! empty($groupedTables)) {
|
||||||
foreach ($this->columns as $alias => $column) {
|
foreach ($this->columns as $alias => $column) {
|
||||||
if ($column instanceof Zend_Db_Expr) {
|
if ($column instanceof Zend_Db_Expr || $column === '(NULL)') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
$tableName = $this->aliasToTableName(
|
||||||
$table = $this->aliasToTableName(
|
|
||||||
$this->hasAliasName($alias) ? $alias : $this->customAliasToAlias($alias)
|
$this->hasAliasName($alias) ? $alias : $this->customAliasToAlias($alias)
|
||||||
);
|
);
|
||||||
if ($table === 'servicegroups') {
|
if (isset($groupedTables[$tableName])) {
|
||||||
$selected = true;
|
continue;
|
||||||
|
}
|
||||||
|
switch ($tableName) {
|
||||||
|
case 'hosts':
|
||||||
|
$group[] = 'h.host_id';
|
||||||
break;
|
break;
|
||||||
|
case 'hoststatus':
|
||||||
|
$group[] = 'hs.hoststatus_id';
|
||||||
|
break;
|
||||||
|
case 'servicestatus':
|
||||||
|
$group[] = 'ss.servicestatus_id';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
$groupedTables[$tableName] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($selected) {
|
|
||||||
$group[] = 'sg.servicegroup_id';
|
|
||||||
$group[] = 'sgo.object_id';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $group;
|
return $group;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*! Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
.bg-state-ok,
|
||||||
|
.bg-state-up {
|
||||||
|
background-color: @colorOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-state-warning {
|
||||||
|
background-color: @colorWarning;
|
||||||
|
|
||||||
|
&.handled {
|
||||||
|
background-color: @colorWarningHandled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-state-critical,
|
||||||
|
.bg-state-down {
|
||||||
|
background-color: @colorCritical;
|
||||||
|
|
||||||
|
&.handled {
|
||||||
|
background-color: @colorCriticalHandled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-state-unreachable {
|
||||||
|
background-color: @colorUnreachable;
|
||||||
|
|
||||||
|
&.handled {
|
||||||
|
background-color: @colorUnreachableHandled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-state-unknown {
|
||||||
|
background-color: @colorUnknown;
|
||||||
|
|
||||||
|
&.handled {
|
||||||
|
background-color: @colorUnknownHandled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-state-pending {
|
||||||
|
background-color: @colorPending;
|
||||||
|
}
|
|
@ -842,112 +842,6 @@ table.joystick-pagination {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
table.pivot {
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: black;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: @colorTextDefault;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > thead {
|
|
||||||
th {
|
|
||||||
height: 6em;
|
|
||||||
|
|
||||||
div {
|
|
||||||
margin-right: -1.5em;
|
|
||||||
padding-left: 1.3em;
|
|
||||||
|
|
||||||
span {
|
|
||||||
width: 1.5em;
|
|
||||||
margin-right: 0.25em;
|
|
||||||
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);
|
|
||||||
|
|
||||||
abbr {
|
|
||||||
border: 0; // Remove highlighting in firefox
|
|
||||||
font-size: 0.8em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > tbody {
|
|
||||||
th {
|
|
||||||
padding: 0 14px 0 0;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-size: 0.8em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
td {
|
|
||||||
padding: 2px;
|
|
||||||
min-width: 1.5em;
|
|
||||||
line-height: 1.5em;
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
a {
|
|
||||||
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_critical {
|
|
||||||
background-color: @colorCritical;
|
|
||||||
|
|
||||||
&.handled {
|
|
||||||
background-color: @colorCriticalHandled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.state_unknown {
|
|
||||||
background-color: @colorUnknown;
|
|
||||||
|
|
||||||
&.handled {
|
|
||||||
background-color: @colorUnknownHandled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* End of monitoring pivot table styles */
|
/* End of monitoring pivot table styles */
|
||||||
|
|
||||||
/* Monitoring timeline styles */
|
/* Monitoring timeline styles */
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*! Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
table.service-grid-table {
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
th {
|
||||||
|
a {
|
||||||
|
color: @colorMainLink;
|
||||||
|
font-weight: normal;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
text-align: center;
|
||||||
|
width: 1.5em;
|
||||||
|
|
||||||
|
a {
|
||||||
|
.rounded-corners(0.4em);
|
||||||
|
display: block;
|
||||||
|
height: 1.5em;
|
||||||
|
width: 1.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
th.rotate-45 {
|
||||||
|
height: 6em;
|
||||||
|
|
||||||
|
div {
|
||||||
|
.transform(translate(0.4em, 2.1em) rotate(315deg));
|
||||||
|
width: 1.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
/*! Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
||||||
|
|
||||||
|
.transform(@transform) {
|
||||||
|
-webkit-transform: @transform;
|
||||||
|
-moz-transform: @transform;
|
||||||
|
-ms-transform: @transform;
|
||||||
|
-o-transform: @transform;
|
||||||
|
transform: @transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-corners(@border-radius: 0.4em) {
|
||||||
|
-webkit-border-radius: @border-radius;
|
||||||
|
-moz-border-radius: @border-radius;
|
||||||
|
border-radius: @border-radius;
|
||||||
|
|
||||||
|
-webkit-background-clip: padding-box;
|
||||||
|
-moz-background-clip: padding;
|
||||||
|
background-clip: padding-box;
|
||||||
|
}
|
Loading…
Reference in New Issue