mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-27 15:54:03 +02:00
Merge branch 'bugfix/service-grid-display_name-9538' into bugfix/service-grid-grouping-postgres-9333
Conflicts: library/Icinga/Data/PivotTable.php modules/monitoring/application/controllers/ListController.php
This commit is contained in:
commit
c8790fad93
@ -62,14 +62,14 @@ with Icinga Web 2 (e.g. an alias) no matter what the primary user id might actua
|
|||||||
|
|
||||||
Directive | Description
|
Directive | Description
|
||||||
------------------------|------------
|
------------------------|------------
|
||||||
**backend** | `ad`
|
**backend** | `msldap`
|
||||||
**resource** | The name of the LDAP resource defined in [resources.ini](resources.md#resources).
|
**resource** | The name of the LDAP resource defined in [resources.ini](resources.md#resources).
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
|
|
||||||
```
|
```
|
||||||
[auth_ad]
|
[auth_ad]
|
||||||
backend = ad
|
backend = msldap
|
||||||
resource = my_ad
|
resource = my_ad
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -31,6 +31,13 @@ class PivotTable implements Sortable
|
|||||||
*/
|
*/
|
||||||
protected $yAxisColumn;
|
protected $yAxisColumn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Column for sorting the result set
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $order = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The filter being applied on the query for the x axis
|
* The filter being applied on the query for the x axis
|
||||||
*
|
*
|
||||||
@ -60,11 +67,18 @@ class PivotTable implements Sortable
|
|||||||
protected $yAxisQuery;
|
protected $yAxisQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Column for sorting the result set
|
* X-axis header
|
||||||
*
|
*
|
||||||
* @var array
|
* @var string|null
|
||||||
*/
|
*/
|
||||||
protected $order = array();
|
protected $xAxisHeader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Y-axis header
|
||||||
|
*
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
protected $yAxisHeader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new pivot table
|
* Create a new pivot table
|
||||||
@ -131,6 +145,56 @@ class PivotTable implements Sortable
|
|||||||
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
|
||||||
*
|
*
|
||||||
@ -163,7 +227,7 @@ class PivotTable implements Sortable
|
|||||||
if ($this->xAxisQuery === null) {
|
if ($this->xAxisQuery === null) {
|
||||||
$this->xAxisQuery = clone $this->baseQuery;
|
$this->xAxisQuery = clone $this->baseQuery;
|
||||||
$this->xAxisQuery->group($this->xAxisColumn);
|
$this->xAxisQuery->group($this->xAxisColumn);
|
||||||
$this->xAxisQuery->columns(array($this->xAxisColumn));
|
$this->xAxisQuery->columns(array($this->xAxisColumn, $this->getXAxisHeader()));
|
||||||
|
|
||||||
if ($this->xAxisFilter !== null) {
|
if ($this->xAxisFilter !== null) {
|
||||||
$this->xAxisQuery->addFilter($this->xAxisFilter);
|
$this->xAxisQuery->addFilter($this->xAxisFilter);
|
||||||
@ -188,7 +252,7 @@ class PivotTable implements Sortable
|
|||||||
if ($this->yAxisQuery === null) {
|
if ($this->yAxisQuery === null) {
|
||||||
$this->yAxisQuery = clone $this->baseQuery;
|
$this->yAxisQuery = clone $this->baseQuery;
|
||||||
$this->yAxisQuery->group($this->yAxisColumn);
|
$this->yAxisQuery->group($this->yAxisColumn);
|
||||||
$this->yAxisQuery->columns(array($this->yAxisColumn));
|
$this->yAxisQuery->columns(array($this->yAxisColumn, $this->getYAxisHeader()));
|
||||||
|
|
||||||
if ($this->yAxisFilter !== null) {
|
if ($this->yAxisFilter !== null) {
|
||||||
$this->yAxisQuery->addFilter($this->yAxisFilter);
|
$this->yAxisQuery->addFilter($this->yAxisFilter);
|
||||||
@ -199,7 +263,6 @@ class PivotTable implements Sortable
|
|||||||
isset($this->order[$this->yAxisColumn]) ? $this->order[$this->yAxisColumn] : self::SORT_ASC
|
isset($this->order[$this->yAxisColumn]) ? $this->order[$this->yAxisColumn] : self::SORT_ASC
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->yAxisQuery;
|
return $this->yAxisQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,33 +339,39 @@ class PivotTable implements Sortable
|
|||||||
($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();
|
||||||
|
$pivotHeader = array(
|
||||||
|
'cols' => $xAxis,
|
||||||
|
'rows' => $yAxis
|
||||||
|
);
|
||||||
|
if (! empty($xAxis) && ! empty($yAxis)) {
|
||||||
|
$xAxisKeys = array_keys($xAxis);
|
||||||
|
$yAxisKeys = array_keys($yAxis);
|
||||||
|
$this->baseQuery
|
||||||
|
->where($this->xAxisColumn, $xAxisKeys)
|
||||||
|
->where($this->yAxisColumn, $yAxisKeys);
|
||||||
|
|
||||||
$pivot = array();
|
foreach ($yAxisKeys as $yAxisKey) {
|
||||||
if (!empty($xAxis) && !empty($yAxis)) {
|
foreach ($xAxisKeys as $xAxisKey) {
|
||||||
$this->baseQuery->where($this->xAxisColumn, $xAxis)->where($this->yAxisColumn, $yAxis);
|
$pivotData[$yAxisKey][$xAxisKey] = null;
|
||||||
|
|
||||||
foreach ($yAxis as $yLabel) {
|
|
||||||
foreach ($xAxis as $xLabel) {
|
|
||||||
$pivot[$yLabel][$xLabel] = 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
namespace Icinga\Util;
|
namespace Icinga\Util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common string helper
|
* Common string functions
|
||||||
*/
|
*/
|
||||||
class String
|
class String
|
||||||
{
|
{
|
||||||
@ -103,8 +103,8 @@ class String
|
|||||||
/**
|
/**
|
||||||
* Check if a string ends with a different string
|
* Check if a string ends with a different string
|
||||||
*
|
*
|
||||||
* @param $haystack The string to search for matches
|
* @param $haystack string The string to search for matches
|
||||||
* @param $needle The string to match at the start of the haystack
|
* @param $needle string The string to match at the start of the haystack
|
||||||
*
|
*
|
||||||
* @return bool Whether or not needle is at the beginning of haystack
|
* @return bool Whether or not needle is at the beginning of haystack
|
||||||
*/
|
*/
|
||||||
|
@ -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',
|
||||||
|
@ -581,29 +581,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->filterQuery($query);
|
$this->filterQuery($query);
|
||||||
$this->applyRestriction('monitoring/filter/objects', $query);
|
$this->applyRestriction('monitoring/filter/objects', $query);
|
||||||
$pivot = $query->pivot(
|
$filter = (bool) $this->params->shift('problems', false) ? Filter::where('service_problem', 1) : null;
|
||||||
'service_description',
|
$pivot = $query
|
||||||
'host_name',
|
->pivot(
|
||||||
$problems ? Filter::where('service_problem', 1) : null,
|
'service_description',
|
||||||
$problems ? Filter::where('service_problem', 1) : null
|
'host_name',
|
||||||
);
|
$filter,
|
||||||
|
$filter ? clone $filter : null
|
||||||
|
)
|
||||||
|
->setXAxisHeader('service_display_name')
|
||||||
|
->setYAxisHeader('host_display_name');
|
||||||
$this->setupSortControl(array(
|
$this->setupSortControl(array(
|
||||||
'host_name' => $this->translate('Hostname'),
|
'host_display_name' => $this->translate('Hostname'),
|
||||||
'service_description' => $this->translate('Service description')
|
'service_display_name' => $this->translate('Service Name')
|
||||||
), $pivot);
|
), $pivot);
|
||||||
$this->view->pivot = $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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,8 +27,8 @@ class Zend_View_Helper_IconImage extends Zend_View_Helper_Abstract
|
|||||||
public function host($object)
|
public function host($object)
|
||||||
{
|
{
|
||||||
if ($object->host_icon_image && ! preg_match('/[\'"]/', $object->host_icon_image)) {
|
if ($object->host_icon_image && ! preg_match('/[\'"]/', $object->host_icon_image)) {
|
||||||
return $this->view->img(
|
return $this->view->icon(
|
||||||
'img/icons/' . Macro::resolveMacros($object->host_icon_image, $object),
|
Macro::resolveMacros($object->host_icon_image, $object),
|
||||||
null,
|
null,
|
||||||
array(
|
array(
|
||||||
'alt' => $object->host_icon_image_alt,
|
'alt' => $object->host_icon_image_alt,
|
||||||
@ -49,8 +49,8 @@ class Zend_View_Helper_IconImage extends Zend_View_Helper_Abstract
|
|||||||
public function service($object)
|
public function service($object)
|
||||||
{
|
{
|
||||||
if ($object->service_icon_image && ! preg_match('/[\'"]/', $object->service_icon_image)) {
|
if ($object->service_icon_image && ! preg_match('/[\'"]/', $object->service_icon_image)) {
|
||||||
return $this->view->img(
|
return $this->view->icon(
|
||||||
'img/icons/' . Macro::resolveMacros($object->service_icon_image, $object),
|
Macro::resolveMacros($object->service_icon_image, $object),
|
||||||
null,
|
null,
|
||||||
array(
|
array(
|
||||||
'alt' => $object->service_icon_image_alt,
|
'alt' => $object->service_icon_image_alt,
|
||||||
|
@ -36,7 +36,8 @@ if (! $this->compact): ?>
|
|||||||
$notification->service_description,
|
$notification->service_description,
|
||||||
$notification->service_display_name,
|
$notification->service_display_name,
|
||||||
$notification->host_name,
|
$notification->host_name,
|
||||||
$notification->host_display_name
|
$notification->host_display_name,
|
||||||
|
'rowaction'
|
||||||
) ?>
|
) ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<?= $this->icon('host', $this->translate('Host')); ?>
|
<?= $this->icon('host', $this->translate('Host')); ?>
|
||||||
|
@ -12,97 +12,84 @@ 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): ?>
|
|
||||||
<?php if (!$hasHeader): ?>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th><?= $this->partial(
|
|
||||||
'joystickPagination.phtml',
|
|
||||||
'default',
|
|
||||||
array(
|
|
||||||
'xAxisPaginator' => $horizontalPaginator,
|
|
||||||
'yAxisPaginator' => $verticalPaginator
|
|
||||||
)
|
|
||||||
); ?></th>
|
|
||||||
<th colspan="<?= count($serviceStates); ?>">
|
|
||||||
<div>
|
|
||||||
<?php
|
|
||||||
$serviceDescriptions = array_keys($serviceStates);
|
|
||||||
$serviceFilter = '(service_description=' . implode('|service_description=', $serviceDescriptions) . ')';
|
|
||||||
|
|
||||||
foreach ($serviceDescriptions as $service_description): ?>
|
<table class="service-grid-table">
|
||||||
<span>
|
<thead>
|
||||||
<?= $this->qlink(
|
<tr>
|
||||||
'<abbr>' . (strlen($service_description) > 18 ? substr($service_description, 0, 18) . '...' : $service_description) . '</abbr>',
|
<th><?= $this->partial(
|
||||||
|
'joystickPagination.phtml',
|
||||||
|
'default',
|
||||||
|
array(
|
||||||
|
'xAxisPaginator' => $horizontalPaginator,
|
||||||
|
'yAxisPaginator' => $verticalPaginator
|
||||||
|
)
|
||||||
|
); ?></th>
|
||||||
|
<?php foreach ($pivotHeader['cols'] as $serviceDescription => $serviceDisplayName): ?>
|
||||||
|
<th class="rotate-45"><div><span><?= $this->qlink(
|
||||||
|
$this->ellipsis($serviceDisplayName, 18),
|
||||||
'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 ?>
|
</tr>
|
||||||
</div>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php $hasHeader = true; ?>
|
<?php foreach ($pivotHeader['rows'] as $hostName => $hostDisplayName): ?>
|
||||||
<?php endif ?>
|
<tr>
|
||||||
<tr>
|
<th><?php
|
||||||
<th>
|
$services = $pivotData[$hostName];
|
||||||
<?= $this->qlink(
|
$serviceFilter = '(service_description=' . implode('|service_description=', array_keys($services)) . ')';
|
||||||
$host_name,
|
echo $this->qlink(
|
||||||
'monitoring/list/services?' . $serviceFilter,
|
$hostDisplayName,
|
||||||
array('host' => $host_name),
|
'monitoring/list/services?' . $serviceFilter,
|
||||||
array('title' => sprintf($this->translate('List all reported services on host %s'), $host_name))
|
array('host_name' => $hostName),
|
||||||
); ?>
|
array('title' => sprintf($this->translate('List all reported services on host %s'), $hostDisplayName))
|
||||||
</th>
|
);
|
||||||
<?php foreach (array_values($serviceStates) as $service): ?>
|
?></th>
|
||||||
<?php if ($service !== null): ?>
|
<?php foreach (array_keys($pivotHeader['cols']) as $serviceDescription): ?>
|
||||||
<td>
|
<td>
|
||||||
<span class="sr-only" id="<?= $service->host_name . '_' . $service->service_description . '_desc'; ?>">
|
<?php
|
||||||
<?= $this->escape($service->service_output); ?>
|
$service = $pivotData[$hostName][$serviceDescription];
|
||||||
</span>
|
if ($service === null): ?>
|
||||||
<?= $this->qlink(
|
<span aria-hidden="true">·</span>
|
||||||
'',
|
<?php continue; endif ?>
|
||||||
'monitoring/show/service',
|
<?php $ariaDescribedById = $this->protectId($service->host_name . '_' . $service->service_description . '_desc') ?>
|
||||||
array(
|
<span class="sr-only" id="<?= $ariaDescribedById ?>">
|
||||||
'host' => $service->host_name,
|
<?= $this->escape($service->service_output) ?>
|
||||||
'service' => $service->service_description
|
</span>
|
||||||
),
|
<?= $this->qlink(
|
||||||
array(
|
'',
|
||||||
'aria-describedby' => $service->host_name . '_' . $service->service_description . '_desc',
|
'monitoring/show/service',
|
||||||
'class' => 'state_' . Service::getStateText($service->service_state). ($service->service_handled ? ' handled' : ''),
|
array(
|
||||||
'title' => $this->escape($service->service_output),
|
'host' => $hostName,
|
||||||
'aria-label' => sprintf(
|
'service' => $serviceDescription
|
||||||
$this->translate('Show detailed information for service %s on host %s'),
|
),
|
||||||
$service->service_description,
|
array(
|
||||||
$service->host_name
|
'aria-describedby' => $ariaDescribedById,
|
||||||
)
|
'class' => 'bg-state-' . Service::getStateText($service->service_state) . ($service->service_handled ? ' handled' : ''),
|
||||||
)
|
'title' => $this->escape($service->service_output),
|
||||||
); ?>
|
'aria-label' => sprintf(
|
||||||
</td>
|
$this->translate('Show detailed information for service %s on host %s'),
|
||||||
<?php else: ?>
|
$service->service_display_name,
|
||||||
<td><span aria-hidden="true">·</span></td>
|
$service->host_display_name
|
||||||
<?php endif ?>
|
)
|
||||||
<?php endforeach ?>
|
)
|
||||||
</tr>
|
); ?>
|
||||||
<?php endforeach ?>
|
</td>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach ?>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -223,3 +223,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');
|
||||||
|
@ -9,7 +9,7 @@ use Icinga\Data\Filter\Filter;
|
|||||||
/**
|
/**
|
||||||
* Query for event history records
|
* Query for event history records
|
||||||
*/
|
*/
|
||||||
class EventHistoryQuery extends IdoQuery
|
class EventhistoryQuery extends IdoQuery
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
|
@ -8,7 +8,7 @@ use Zend_Db_Select;
|
|||||||
/**
|
/**
|
||||||
* Query for host and service group summaries
|
* Query for host and service group summaries
|
||||||
*/
|
*/
|
||||||
class GroupSummaryQuery extends IdoQuery
|
class GroupsummaryQuery extends IdoQuery
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
|
@ -10,7 +10,7 @@ use Icinga\Data\Filter\Filter;
|
|||||||
/**
|
/**
|
||||||
* Query for host and service status summary
|
* Query for host and service status summary
|
||||||
*/
|
*/
|
||||||
class StatusSummaryQuery extends IdoQuery
|
class StatussummaryQuery extends IdoQuery
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
|
@ -29,8 +29,6 @@ abstract class DataView implements QueryInterface, SortRules, FilterColumns, Ite
|
|||||||
*/
|
*/
|
||||||
protected $query;
|
protected $query;
|
||||||
|
|
||||||
protected $filter;
|
|
||||||
|
|
||||||
protected $connection;
|
protected $connection;
|
||||||
|
|
||||||
protected $isSorted = false;
|
protected $isSorted = false;
|
||||||
@ -52,7 +50,6 @@ abstract class DataView implements QueryInterface, SortRules, FilterColumns, Ite
|
|||||||
{
|
{
|
||||||
$this->connection = $connection;
|
$this->connection = $connection;
|
||||||
$this->query = $connection->query($this->getQueryName(), $columns);
|
$this->query = $connection->query($this->getQueryName(), $columns);
|
||||||
$this->filter = Filter::matchAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,7 +88,6 @@ abstract class DataView implements QueryInterface, SortRules, FilterColumns, Ite
|
|||||||
|
|
||||||
public function where($condition, $value = null)
|
public function where($condition, $value = null)
|
||||||
{
|
{
|
||||||
$this->filter->addFilter(Filter::where($condition, $value));
|
|
||||||
$this->query->where($condition, $value);
|
$this->query->where($condition, $value);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -268,9 +264,14 @@ abstract class DataView implements QueryInterface, SortRules, FilterColumns, Ite
|
|||||||
return $columns;
|
return $columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current filter
|
||||||
|
*
|
||||||
|
* @return Filter
|
||||||
|
*/
|
||||||
public function getFilter()
|
public function getFilter()
|
||||||
{
|
{
|
||||||
return $this->filter;
|
return $this->query->getFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -471,8 +472,7 @@ abstract class DataView implements QueryInterface, SortRules, FilterColumns, Ite
|
|||||||
*/
|
*/
|
||||||
public function addFilter(Filter $filter)
|
public function addFilter(Filter $filter)
|
||||||
{
|
{
|
||||||
$this->query->addFilter(clone($filter));
|
$this->query->addFilter($filter);
|
||||||
$this->filter = $filter; // TODO: Hmmmm.... and?
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,7 +496,8 @@ abstract class DataView implements QueryInterface, SortRules, FilterColumns, Ite
|
|||||||
*/
|
*/
|
||||||
public function peekAhead($state = true)
|
public function peekAhead($state = true)
|
||||||
{
|
{
|
||||||
return $this->query->peekAhead($state);
|
$this->query->peekAhead($state);
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -450,21 +450,29 @@ abstract class MonitoredObject implements Filterable
|
|||||||
*/
|
*/
|
||||||
public function fetchEventhistory()
|
public function fetchEventhistory()
|
||||||
{
|
{
|
||||||
$eventHistory = $this->backend->select()->from('eventhistory', array(
|
$eventHistory = $this->backend
|
||||||
'object_type',
|
->select()
|
||||||
'host_name',
|
->from(
|
||||||
'host_display_name',
|
'eventhistory',
|
||||||
'service_description',
|
array(
|
||||||
'service_display_name',
|
'object_type',
|
||||||
'timestamp',
|
'host_name',
|
||||||
'state',
|
'host_display_name',
|
||||||
'output',
|
'service_description',
|
||||||
'type'
|
'service_display_name',
|
||||||
))
|
'timestamp',
|
||||||
|
'state',
|
||||||
|
'output',
|
||||||
|
'type'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
->where('object_type', $this->type)
|
||||||
->where('host_name', $this->host_name);
|
->where('host_name', $this->host_name);
|
||||||
|
|
||||||
if ($this->type === self::TYPE_SERVICE) {
|
if ($this->type === self::TYPE_SERVICE) {
|
||||||
$eventHistory->where('service_description', $this->service_description);
|
$eventHistory->where('service_description', $this->service_description);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->eventhistory = $eventHistory->applyFilter($this->getFilter());
|
$this->eventhistory = $eventHistory->applyFilter($this->getFilter());
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
43
modules/monitoring/public/css/colors.less
Normal file
43
modules/monitoring/public/css/colors.less
Normal file
@ -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;
|
||||||
|
}
|
@ -846,112 +846,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 */
|
||||||
|
38
modules/monitoring/public/css/service-grid.less
Normal file
38
modules/monitoring/public/css/service-grid.less
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
public/css/icinga/mixins.less
Normal file
19
public/css/icinga/mixins.less
Normal file
@ -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;
|
||||||
|
}
|
@ -424,7 +424,9 @@
|
|||||||
this.icinga.ui.reloadCss();
|
this.icinga.ui.reloadCss();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.getResponseHeader('X-Icinga-Redirect')) return;
|
if (req.getResponseHeader('X-Icinga-Redirect')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// div helps getting an XML tree
|
// div helps getting an XML tree
|
||||||
var $resp = $('<div>' + req.responseText + '</div>');
|
var $resp = $('<div>' + req.responseText + '</div>');
|
||||||
@ -515,8 +517,6 @@
|
|||||||
var $el = $(el);
|
var $el = $(el);
|
||||||
if ($el.hasClass('dashboard')) {
|
if ($el.hasClass('dashboard')) {
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
var url = $el.data('icingaUrl');
|
var url = $el.data('icingaUrl');
|
||||||
targets[i].data('icingaUrl', url);
|
targets[i].data('icingaUrl', url);
|
||||||
@ -533,28 +533,9 @@
|
|||||||
|
|
||||||
this.icinga.ui.initializeTriStates($resp);
|
this.icinga.ui.initializeTriStates($resp);
|
||||||
|
|
||||||
/* Should we try to fiddle with responses containing full HTML? */
|
if (rendered) {
|
||||||
/*
|
return;
|
||||||
if ($('body', $resp).length) {
|
|
||||||
req.responseText = $('script', $('body', $resp).html()).remove();
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
/*
|
|
||||||
|
|
||||||
var containers = [];
|
|
||||||
|
|
||||||
$('.dashboard .container').each(function(idx, el) {
|
|
||||||
urls.push($(el).data('icingaUrl'));
|
|
||||||
});
|
|
||||||
console.log(urls);
|
|
||||||
$('.container[data-icinga-refresh]').each(function(idx, el) {
|
|
||||||
var $el = $(el);
|
|
||||||
self.loadUrl($el.data('icingaUrl'), $el).autorefresh = true;
|
|
||||||
el = null;
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (rendered) return;
|
|
||||||
|
|
||||||
// .html() removes outer div we added above
|
// .html() removes outer div we added above
|
||||||
this.renderContentToContainer($resp.html(), req.$target, req.action, req.autorefresh);
|
this.renderContentToContainer($resp.html(), req.$target, req.action, req.autorefresh);
|
||||||
@ -652,8 +633,7 @@
|
|||||||
/*
|
/*
|
||||||
* Test if a manual actions comes in and autorefresh is active: Stop refreshing
|
* Test if a manual actions comes in and autorefresh is active: Stop refreshing
|
||||||
*/
|
*/
|
||||||
if (req.addToHistory && ! req.autorefresh && req.$target.data('icingaRefresh') > 0
|
if (req.addToHistory && ! req.autorefresh && req.$target.data('icingaRefresh') > 0) {
|
||||||
&& req.$target.data('icingaUrl') !== url) {
|
|
||||||
req.$target.data('icingaRefresh', 0);
|
req.$target.data('icingaRefresh', 0);
|
||||||
req.$target.data('icingaUrl', url);
|
req.$target.data('icingaUrl', url);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user