mirror of
https://github.com/Icinga/icingaweb2.git
synced 2025-07-24 22:34:24 +02:00
Fix CSP violations (#5060)
This commit is contained in:
commit
b201b030b2
2
.github/workflows/php.yml
vendored
2
.github/workflows/php.yml
vendored
@ -111,7 +111,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Setup dependencies
|
- name: Setup dependencies
|
||||||
run: |
|
run: |
|
||||||
composer require -n --no-progress mockery/mockery ipl/i18n:@dev
|
composer require -n --no-progress mockery/mockery ipl/i18n:@dev ipl/web:@dev
|
||||||
git clone --depth 1 --branch snapshot/nightly https://github.com/Icinga/icinga-php-thirdparty.git vendor/icinga-php-thirdparty
|
git clone --depth 1 --branch snapshot/nightly https://github.com/Icinga/icinga-php-thirdparty.git vendor/icinga-php-thirdparty
|
||||||
|
|
||||||
- name: PHPUnit
|
- name: PHPUnit
|
||||||
|
@ -262,7 +262,7 @@ class RoleForm extends RepositoryForm
|
|||||||
PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY
|
PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY
|
||||||
)))),
|
)))),
|
||||||
'description' => $spec['description'],
|
'description' => $spec['description'],
|
||||||
'style' => $isUnrestricted ? 'text-decoration:line-through;' : '',
|
'class' => $isUnrestricted ? 'unrestricted-role' : '',
|
||||||
'readonly' => $isUnrestricted ?: null
|
'readonly' => $isUnrestricted ?: null
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
@ -24,7 +24,15 @@ $iframeClass = $isIframe ? ' iframe' : '';
|
|||||||
$innerLayoutScript = $this->layout()->innerLayout . '.phtml';
|
$innerLayoutScript = $this->layout()->innerLayout . '.phtml';
|
||||||
|
|
||||||
?><!DOCTYPE html>
|
?><!DOCTYPE html>
|
||||||
<html class="no-js<?= $iframeClass ?>" lang="<?= $lang ?>">
|
<html
|
||||||
|
class="no-js<?= $iframeClass ?>" lang="<?= $lang ?>"
|
||||||
|
data-icinga-window-name="<?= $this->protectId('Icinga') ?>"
|
||||||
|
data-icinga-timezone="<?= $timezone ?>"
|
||||||
|
data-icinga-base-url="<?= $this->baseUrl(); ?>"
|
||||||
|
<?php if ($isIframe): ?>
|
||||||
|
data-icinga-is-iframe
|
||||||
|
<?php endif ?>
|
||||||
|
>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="google" value="notranslate">
|
<meta name="google" value="notranslate">
|
||||||
@ -39,12 +47,6 @@ $innerLayoutScript = $this->layout()->innerLayout . '.phtml';
|
|||||||
<base target="_parent">
|
<base target="_parent">
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<base href="<?= $this->baseUrl(); ?>/">
|
<base href="<?= $this->baseUrl(); ?>/">
|
||||||
<script type="text/javascript">
|
|
||||||
(function() {
|
|
||||||
var html = document.getElementsByTagName('html')[0];
|
|
||||||
html.className = html.className.replace(/no-js/, 'js');
|
|
||||||
}());
|
|
||||||
</script>
|
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<link rel="stylesheet" href="<?= $this->href($cssfile) ?>" media="all" type="text/css" />
|
<link rel="stylesheet" href="<?= $this->href($cssfile) ?>" media="all" type="text/css" />
|
||||||
<link type="image/png" rel="shortcut icon" href="<?= $this->baseUrl('img/favicon.png') ?>" />
|
<link type="image/png" rel="shortcut icon" href="<?= $this->baseUrl('img/favicon.png') ?>" />
|
||||||
@ -55,25 +57,6 @@ $innerLayoutScript = $this->layout()->innerLayout . '.phtml';
|
|||||||
<div id="layout" class="default-layout<?php if ($showFullscreen): ?> fullscreen-layout<?php endif ?>">
|
<div id="layout" class="default-layout<?php if ($showFullscreen): ?> fullscreen-layout<?php endif ?>">
|
||||||
<?= $this->render($innerLayoutScript); ?>
|
<?= $this->render($innerLayoutScript); ?>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript">
|
|
||||||
(function() {
|
|
||||||
if (document.defaultView && document.defaultView.getComputedStyle) {
|
|
||||||
var matched;
|
|
||||||
var html = document.getElementsByTagName('html')[0];
|
|
||||||
var element = document.getElementById('layout');
|
|
||||||
var name = document.defaultView
|
|
||||||
.getComputedStyle(html)['font-family']
|
|
||||||
.replace(/['",]/g, '');
|
|
||||||
|
|
||||||
if (null !== (matched = name.match(/^([a-z]+)-layout$/))) {
|
|
||||||
element.className = element.className.replace('default-layout', name);
|
|
||||||
if ('object' === typeof window.console) {
|
|
||||||
window.console.log('Icinga Web 2: setting initial layout to ' + name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}());
|
|
||||||
</script>
|
|
||||||
<div id="collapsible-control-ghost" class="collapsible-control">
|
<div id="collapsible-control-ghost" class="collapsible-control">
|
||||||
<button type="button">
|
<button type="button">
|
||||||
<!-- TODO: Accessibility attributes are missing since usage of the Icon class -->
|
<!-- TODO: Accessibility attributes are missing since usage of the Icon class -->
|
||||||
@ -95,13 +78,6 @@ $innerLayoutScript = $this->layout()->innerLayout . '.phtml';
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="<?= $this->href($jsfile) ?>"></script>
|
<script type="text/javascript" src="<?= $this->href($jsfile) ?>"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript" src="<?= $this->href('js/bootstrap.js') ?>"></script>
|
||||||
window.name = '<?= $this->protectId('Icinga') ?>';
|
|
||||||
var icinga = new Icinga({
|
|
||||||
baseUrl: '<?= $this->baseUrl(); ?>',
|
|
||||||
locale: '<?= $lang; ?>',
|
|
||||||
timezone: '<?= $timezone ?>'
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Icinga\Util\Csp;
|
||||||
|
|
||||||
|
?>
|
||||||
<!--
|
<!--
|
||||||
This view provides a workaround to logout from an external authentication provider, in case external
|
This view provides a workaround to logout from an external authentication provider, in case external
|
||||||
authentication was configured (the default is to handle authentications internally in Icingaweb2).
|
authentication was configured (the default is to handle authentications internally in Icingaweb2).
|
||||||
@ -9,44 +14,24 @@
|
|||||||
-->
|
-->
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div id="icinga-logo" aria-hidden="true"></div>
|
<div id="icinga-logo" aria-hidden="true"></div>
|
||||||
<div class="alert alert-warning" id="logout-status">
|
<div class="alert alert-warning" id="logout-in-progress">
|
||||||
<b><?= $this->translate('Logging out...'); ?></b>
|
<b><?= $this->translate('Logging out...'); ?></b>
|
||||||
<br>
|
<p>
|
||||||
<?= $this->translate(
|
<?= $this->translate(
|
||||||
'If this message does not disappear, it might be necessary to quit the'
|
'If this message does not disappear, it might be necessary to quit the'
|
||||||
. ' current session manually by clearing the cache, or by closing the current'
|
. ' current session manually by clearing the cache, or by closing the current'
|
||||||
. ' browser session.'
|
. ' browser session.'
|
||||||
); ?>
|
); ?>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="logout-successful" class="alert alert-success" hidden><?= $this->translate('Logout successful'); ?></div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a href="<?= $this->href('dashboard'); ?>"><?= $this->translate('Login'); ?></a>
|
<a href="<?= $this->href('dashboard'); ?>"><?= $this->translate('Login'); ?></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript" src="<?= $this->href('js/logout.js'); ?>"></script>
|
||||||
/*
|
<style type="text/css" nonce="<?= Csp::getStyleNonce(); ?>">
|
||||||
* When JavaScript is available, trigger an XmlHTTPRequest with the non-existing user 'logout' and abort it
|
|
||||||
* before it is able to finish. This will cause the browser to show a new authentication prompt in the next
|
|
||||||
* request.
|
|
||||||
*/
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
var msg = document.getElementById('logout-status');
|
|
||||||
try {
|
|
||||||
if (navigator.userAgent.toLowerCase().indexOf('msie') !== -1) {
|
|
||||||
document.execCommand('ClearAuthenticationCache');
|
|
||||||
} else {
|
|
||||||
var xhttp = new XMLHttpRequest();
|
|
||||||
xhttp.open('GET', 'arbitrary url', true, 'logout', 'logout');
|
|
||||||
xhttp.send('');
|
|
||||||
xhttp.abort();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
msg.innerHTML = '<?= $this->translate('Logout successful!'); ?>';
|
|
||||||
msg.className = 'alert alert-success';
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<style type="text/css">
|
|
||||||
body {
|
body {
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
background-color: #0095bf;
|
background-color: #0095bf;
|
||||||
@ -66,7 +51,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#logout-status {
|
#logout-in-progress {
|
||||||
margin: 2em 0 1em;
|
margin: 2em 0 1em;
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -7,20 +7,20 @@
|
|||||||
<table class="avp action" data-base-target="_next">
|
<table class="avp action" data-base-target="_next">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 18em;">
|
<th>
|
||||||
<strong><?= t('Dashlet Name') ?></strong>
|
<strong><?= t('Dashlet Name') ?></strong>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<strong><?= t('Url') ?></strong>
|
<strong><?= t('Url') ?></strong>
|
||||||
</th>
|
</th>
|
||||||
<th style="width: 1.4em;"> </th>
|
<th class="icon-col"> </th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php foreach ($this->dashboard->getPanes() as $pane): ?>
|
<?php foreach ($this->dashboard->getPanes() as $pane): ?>
|
||||||
<?php if ($pane->getDisabled()) continue; ?>
|
<?php if ($pane->getDisabled()) continue; ?>
|
||||||
<tr>
|
<tr>
|
||||||
<th colspan="2" style="text-align: left; padding: 0.5em;">
|
<th colspan="2">
|
||||||
<?php if ($pane->isUserWidget()): ?>
|
<?php if ($pane->isUserWidget()): ?>
|
||||||
<?= $this->qlink(
|
<?= $this->qlink(
|
||||||
$pane->getName(),
|
$pane->getName(),
|
||||||
@ -63,7 +63,7 @@
|
|||||||
array('title' => sprintf($this->translate('Edit dashlet %s'), $dashlet->getTitle()))
|
array('title' => sprintf($this->translate('Edit dashlet %s'), $dashlet->getTitle()))
|
||||||
); ?>
|
); ?>
|
||||||
</td>
|
</td>
|
||||||
<td style="table-layout: fixed; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
<td>
|
||||||
<?= $this->qlink(
|
<?= $this->qlink(
|
||||||
$dashlet->getUrl()->getRelativeUrl(),
|
$dashlet->getUrl()->getRelativeUrl(),
|
||||||
$dashlet->getUrl()->getRelativeUrl(),
|
$dashlet->getUrl()->getRelativeUrl(),
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<?php foreach ($this->logData as $value): ?>
|
<?php foreach ($this->logData as $value): ?>
|
||||||
<?php $datetime = new Datetime($value->datetime) ?>
|
<?php $datetime = new Datetime($value->datetime) ?>
|
||||||
<tr class="state">
|
<tr>
|
||||||
<td style="width: 6em; text-align: center">
|
<td>
|
||||||
<?= $this->escape($datetime->format('d.m. H:i')) ?><br />
|
<?= $this->escape($datetime->format('d.m. H:i')) ?><br />
|
||||||
<?= $this->escape($value->loglevel) ?>
|
<?= $this->escape($value->loglevel) ?>
|
||||||
</td>
|
</td>
|
||||||
|
@ -17,9 +17,9 @@ if (! $this->compact): ?>
|
|||||||
<table class="table-row-selectable common-table">
|
<table class="table-row-selectable common-table">
|
||||||
<thead>
|
<thead>
|
||||||
<th><?= $this->translate('Shared Navigation'); ?></th>
|
<th><?= $this->translate('Shared Navigation'); ?></th>
|
||||||
<th style="width: 10em"><?= $this->translate('Type'); ?></th>
|
<th><?= $this->translate('Type'); ?></th>
|
||||||
<th style="width: 10em"><?= $this->translate('Owner'); ?></th>
|
<th><?= $this->translate('Owner'); ?></th>
|
||||||
<th style="width: 5em"><?= $this->translate('Unshare'); ?></th>
|
<th><?= $this->translate('Unshare'); ?></th>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<?php foreach ($items as $item): ?>
|
<?php foreach ($items as $item): ?>
|
||||||
@ -53,7 +53,7 @@ if (! $this->compact): ?>
|
|||||||
)
|
)
|
||||||
); ?></td>
|
); ?></td>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<td data-base-target="_self"><?= $removeForm
|
<td data-base-target="_self" class="remove-nav-item"><?= $removeForm
|
||||||
->setDefault('name', $item->name)
|
->setDefault('name', $item->name)
|
||||||
->setAction(Url::fromPath(
|
->setAction(Url::fromPath(
|
||||||
'navigation/unshare',
|
'navigation/unshare',
|
||||||
|
@ -75,6 +75,7 @@ class Test extends Cli
|
|||||||
|
|
||||||
// Conflicts with `Tests\Icinga\Module\...\Lib`. But it seems it's not needed anyway...
|
// Conflicts with `Tests\Icinga\Module\...\Lib`. But it seems it's not needed anyway...
|
||||||
//$this->getLoader()->registerNamespace('Tests', $this->getBaseDir('test/php/library'));
|
//$this->getLoader()->registerNamespace('Tests', $this->getBaseDir('test/php/library'));
|
||||||
|
$this->getLoader()->registerNamespace('Tests\\Icinga\\Lib', $this->getBaseDir('test/php/Lib'));
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ class BarGraph extends Styleable implements Drawable
|
|||||||
$rect->setAttribute('data-icinga-graph-index', $index);
|
$rect->setAttribute('data-icinga-graph-index', $index);
|
||||||
}
|
}
|
||||||
$rect->setAttribute('data-icinga-graph-type', 'bar');
|
$rect->setAttribute('data-icinga-graph-type', 'bar');
|
||||||
$rect->setAdditionalStyle('clip-path: url(#clip);');
|
$rect->setAdditionalStyle(['clip-path' => 'url(#clip)']);
|
||||||
return $rect;
|
return $rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,8 +165,8 @@ class LineGraph extends Styleable implements Drawable
|
|||||||
$path->setFill($this->fill);
|
$path->setFill($this->fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
$path->setAdditionalStyle('clip-path: url(#clip);');
|
$path->setAdditionalStyle(['clip-path' => 'url(#clip)']);
|
||||||
$path->setId($this->id);
|
$path->setId($this->id ?? uniqid('line-graph-'));
|
||||||
$group = $path->toSvg($ctx);
|
$group = $path->toSvg($ctx);
|
||||||
|
|
||||||
foreach ($this->dataset as $x => $point) {
|
foreach ($this->dataset as $x => $point) {
|
||||||
@ -180,7 +180,7 @@ class LineGraph extends Styleable implements Drawable
|
|||||||
if (isset($this->tooltips[$x])) {
|
if (isset($this->tooltips[$x])) {
|
||||||
$invisible = new Circle($point[0], $point[1], 20);
|
$invisible = new Circle($point[0], $point[1], 20);
|
||||||
$invisible->setFill($this->strokeColor);
|
$invisible->setFill($this->strokeColor);
|
||||||
$invisible->setAdditionalStyle('opacity: 0.0;');
|
$invisible->setAdditionalStyle(['opacity' => '0.0']);
|
||||||
$data = array(
|
$data = array(
|
||||||
'label' => isset($this->graphs[$this->order]['label']) ?
|
'label' => isset($this->graphs[$this->order]['label']) ?
|
||||||
strtolower($this->graphs[$this->order]['label']) : '',
|
strtolower($this->graphs[$this->order]['label']) : '',
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
namespace Icinga\Chart\Primitive;
|
namespace Icinga\Chart\Primitive;
|
||||||
|
|
||||||
|
use DOMDocument;
|
||||||
use DOMElement;
|
use DOMElement;
|
||||||
use Icinga\Chart\Render\RenderContext;
|
use Icinga\Chart\Render\RenderContext;
|
||||||
use Icinga\Chart\Format;
|
use Icinga\Chart\Format;
|
||||||
@ -61,8 +62,23 @@ class Circle extends Styleable implements Drawable
|
|||||||
$circle->setAttribute('cx', Format::formatSVGNumber($coords[0]));
|
$circle->setAttribute('cx', Format::formatSVGNumber($coords[0]));
|
||||||
$circle->setAttribute('cy', Format::formatSVGNumber($coords[1]));
|
$circle->setAttribute('cy', Format::formatSVGNumber($coords[1]));
|
||||||
$circle->setAttribute('r', $this->radius);
|
$circle->setAttribute('r', $this->radius);
|
||||||
$circle->setAttribute('style', $this->getStyle());
|
|
||||||
|
$id = $this->id ?? uniqid('circle-');
|
||||||
|
$circle->setAttribute('id', $id);
|
||||||
|
$this->setId($id);
|
||||||
|
|
||||||
$this->applyAttributes($circle);
|
$this->applyAttributes($circle);
|
||||||
|
|
||||||
|
$style = new DOMDocument();
|
||||||
|
$style->loadHTML($this->getStyle());
|
||||||
|
|
||||||
|
$circle->appendChild(
|
||||||
|
$circle->ownerDocument->importNode(
|
||||||
|
$style->getElementsByTagName('style')->item(0),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return $circle;
|
return $circle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
namespace Icinga\Chart\Primitive;
|
namespace Icinga\Chart\Primitive;
|
||||||
|
|
||||||
|
use DOMDocument;
|
||||||
use DOMElement;
|
use DOMElement;
|
||||||
use Icinga\Chart\Render\RenderContext;
|
use Icinga\Chart\Render\RenderContext;
|
||||||
use Icinga\Chart\Format;
|
use Icinga\Chart\Format;
|
||||||
@ -80,8 +81,23 @@ class Line extends Styleable implements Drawable
|
|||||||
$line->setAttribute('x2', Format::formatSVGNumber($x2));
|
$line->setAttribute('x2', Format::formatSVGNumber($x2));
|
||||||
$line->setAttribute('y1', Format::formatSVGNumber($y1));
|
$line->setAttribute('y1', Format::formatSVGNumber($y1));
|
||||||
$line->setAttribute('y2', Format::formatSVGNumber($y2));
|
$line->setAttribute('y2', Format::formatSVGNumber($y2));
|
||||||
$line->setAttribute('style', $this->getStyle());
|
|
||||||
|
$id = $this->id ?? uniqid('line-');
|
||||||
|
$line->setAttribute('id', $id);
|
||||||
|
$this->setId($id);
|
||||||
|
|
||||||
$this->applyAttributes($line);
|
$this->applyAttributes($line);
|
||||||
|
|
||||||
|
$style = new DOMDocument();
|
||||||
|
$style->loadHTML($this->getStyle());
|
||||||
|
|
||||||
|
$line->appendChild(
|
||||||
|
$line->ownerDocument->importNode(
|
||||||
|
$style->getElementsByTagName('style')->item(0),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return $line;
|
return $line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
namespace Icinga\Chart\Primitive;
|
namespace Icinga\Chart\Primitive;
|
||||||
|
|
||||||
|
use DOMDocument;
|
||||||
use DOMElement;
|
use DOMElement;
|
||||||
use Icinga\Chart\Render\RenderContext;
|
use Icinga\Chart\Render\RenderContext;
|
||||||
use Icinga\Chart\Format;
|
use Icinga\Chart\Format;
|
||||||
@ -162,12 +163,24 @@ class Path extends Styleable implements Drawable
|
|||||||
}
|
}
|
||||||
|
|
||||||
$path = $doc->createElement('path');
|
$path = $doc->createElement('path');
|
||||||
if ($this->id) {
|
|
||||||
$path->setAttribute('id', $this->id);
|
$id = $this->id ?? uniqid('path-');
|
||||||
}
|
$path->setAttribute('id', $id);
|
||||||
|
$this->setId($id);
|
||||||
|
|
||||||
$path->setAttribute('d', $pathDescription);
|
$path->setAttribute('d', $pathDescription);
|
||||||
$path->setAttribute('style', $this->getStyle());
|
|
||||||
$this->applyAttributes($path);
|
$this->applyAttributes($path);
|
||||||
|
$style = new DOMDocument();
|
||||||
|
$style->loadHTML($this->getStyle());
|
||||||
|
|
||||||
|
$path->appendChild(
|
||||||
|
$path->ownerDocument->importNode(
|
||||||
|
$style->getElementsByTagName('style')->item(0),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
$group->appendChild($path);
|
$group->appendChild($path);
|
||||||
return $group;
|
return $group;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
namespace Icinga\Chart\Primitive;
|
namespace Icinga\Chart\Primitive;
|
||||||
|
|
||||||
|
use DOMDocument;
|
||||||
use DOMElement;
|
use DOMElement;
|
||||||
use Icinga\Chart\Render\RenderContext;
|
use Icinga\Chart\Render\RenderContext;
|
||||||
use Icinga\Chart\Format;
|
use Icinga\Chart\Format;
|
||||||
@ -279,9 +280,22 @@ class PieSlice extends Animatable implements Drawable
|
|||||||
$slicePath = $doc->createElement('path');
|
$slicePath = $doc->createElement('path');
|
||||||
|
|
||||||
$slicePath->setAttribute('d', $this->getPieSlicePath($x, $y, $r));
|
$slicePath->setAttribute('d', $this->getPieSlicePath($x, $y, $r));
|
||||||
$slicePath->setAttribute('style', $this->getStyle());
|
|
||||||
$slicePath->setAttribute('data-icinga-graph-type', 'pieslice');
|
$slicePath->setAttribute('data-icinga-graph-type', 'pieslice');
|
||||||
|
|
||||||
|
$id = $this->id ?? uniqid('slice-');
|
||||||
|
$slicePath->setAttribute('id', $id);
|
||||||
|
$this->setId($id);
|
||||||
|
|
||||||
|
$style = new DOMDocument();
|
||||||
|
$style->loadHTML($this->getStyle());
|
||||||
|
|
||||||
|
$slicePath->appendChild(
|
||||||
|
$slicePath->ownerDocument->importNode(
|
||||||
|
$style->getElementsByTagName('style')->item(0),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
$this->applyAttributes($slicePath);
|
$this->applyAttributes($slicePath);
|
||||||
$group->appendChild($slicePath);
|
$group->appendChild($slicePath);
|
||||||
if ($this->caption != "") {
|
if ($this->caption != "") {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
namespace Icinga\Chart\Primitive;
|
namespace Icinga\Chart\Primitive;
|
||||||
|
|
||||||
use DOMElement;
|
use DOMElement;
|
||||||
|
use DOMDocument;
|
||||||
use Icinga\Chart\Render\RenderContext;
|
use Icinga\Chart\Render\RenderContext;
|
||||||
use Icinga\Chart\Format;
|
use Icinga\Chart\Format;
|
||||||
|
|
||||||
@ -95,11 +96,24 @@ class Rect extends Animatable implements Drawable
|
|||||||
$rect->setAttribute('y', Format::formatSVGNumber($y));
|
$rect->setAttribute('y', Format::formatSVGNumber($y));
|
||||||
$rect->setAttribute('width', Format::formatSVGNumber($width));
|
$rect->setAttribute('width', Format::formatSVGNumber($width));
|
||||||
$rect->setAttribute('height', Format::formatSVGNumber($height));
|
$rect->setAttribute('height', Format::formatSVGNumber($height));
|
||||||
$rect->setAttribute('style', $this->getStyle());
|
|
||||||
|
$id = $this->id ?? uniqid('rect-');
|
||||||
|
$rect->setAttribute('id', $id);
|
||||||
|
$this->setId($id);
|
||||||
|
|
||||||
$this->applyAttributes($rect);
|
$this->applyAttributes($rect);
|
||||||
$this->appendAnimation($rect, $ctx);
|
$this->appendAnimation($rect, $ctx);
|
||||||
|
|
||||||
|
$style = new DOMDocument();
|
||||||
|
$style->loadHTML($this->getStyle());
|
||||||
|
|
||||||
|
$rect->appendChild(
|
||||||
|
$rect->ownerDocument->importNode(
|
||||||
|
$style->getElementsByTagName('style')->item(0),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return $rect;
|
return $rect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
namespace Icinga\Chart\Primitive;
|
namespace Icinga\Chart\Primitive;
|
||||||
|
|
||||||
use DOMElement;
|
use DOMElement;
|
||||||
|
use Icinga\Util\Csp;
|
||||||
|
use ipl\Web\Style;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for stylable drawables
|
* Base class for stylable drawables
|
||||||
@ -36,14 +38,14 @@ class Styleable
|
|||||||
/**
|
/**
|
||||||
* Additional styles to be appended to the style attribute
|
* Additional styles to be appended to the style attribute
|
||||||
*
|
*
|
||||||
* @var string
|
* @var array<string, string>
|
||||||
*/
|
*/
|
||||||
public $additionalStyle = '';
|
public $additionalStyle = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The id of this element
|
* The id of this element
|
||||||
*
|
*
|
||||||
* @var string
|
* @var ?string
|
||||||
*/
|
*/
|
||||||
public $id = null;
|
public $id = null;
|
||||||
|
|
||||||
@ -83,7 +85,7 @@ class Styleable
|
|||||||
/**
|
/**
|
||||||
* Set additional styles for this drawable
|
* Set additional styles for this drawable
|
||||||
*
|
*
|
||||||
* @param string $styles The styles to set additionally
|
* @param array<string, string> $styles The styles to set additionally
|
||||||
*
|
*
|
||||||
* @return $this Fluid interface
|
* @return $this Fluid interface
|
||||||
*/
|
*/
|
||||||
@ -121,15 +123,20 @@ class Styleable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the content of the style attribute as a string
|
* Return the ruleset used for styling the DOMNode
|
||||||
*
|
*
|
||||||
* @return string A string containing styles
|
* @return Style A ruleset containing styles
|
||||||
*/
|
*/
|
||||||
public function getStyle()
|
public function getStyle()
|
||||||
{
|
{
|
||||||
$base = sprintf("fill: %s; stroke: %s;stroke-width: %s;", $this->fill, $this->strokeColor, $this->strokeWidth);
|
$styles = $this->additionalStyle;
|
||||||
$base .= ';' . $this->additionalStyle . ';';
|
$styles['fill'] = $this->fill;
|
||||||
return $base;
|
$styles['stroke'] = $this->strokeColor;
|
||||||
|
$styles['stroke-width'] = (string) $this->strokeWidth;
|
||||||
|
|
||||||
|
return (new Style())
|
||||||
|
->setNonce(Csp::getStyleNonce())
|
||||||
|
->add("#$this->id", $styles);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,10 +4,12 @@
|
|||||||
|
|
||||||
namespace Icinga\Chart\Primitive;
|
namespace Icinga\Chart\Primitive;
|
||||||
|
|
||||||
|
use DOMDocument;
|
||||||
use DOMElement;
|
use DOMElement;
|
||||||
use DOMText;
|
use DOMText;
|
||||||
use Icinga\Chart\Render\RenderContext;
|
use Icinga\Chart\Render\RenderContext;
|
||||||
use Icinga\Chart\Format;
|
use Icinga\Chart\Format;
|
||||||
|
use ipl\Html\HtmlDocument;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for the SVG text element
|
* Wrapper for the SVG text element
|
||||||
@ -97,6 +99,15 @@ class Text extends Styleable implements Drawable
|
|||||||
$this->y = $y;
|
$this->y = $y;
|
||||||
$this->text = $text;
|
$this->text = $text;
|
||||||
$this->fontSize = $fontSize;
|
$this->fontSize = $fontSize;
|
||||||
|
|
||||||
|
$this->setAdditionalStyle([
|
||||||
|
'font-size' => $this->fontSize,
|
||||||
|
'font-family' => 'Ubuntu, Calibri, Trebuchet MS, Helvetica, Verdana, sans-serif',
|
||||||
|
'font-weight' => $this->fontWeight,
|
||||||
|
'font-stretch' => $this->fontStretch,
|
||||||
|
'font-style' => 'normal',
|
||||||
|
'text-anchor' => $this->alignment
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -150,19 +161,24 @@ class Text extends Styleable implements Drawable
|
|||||||
list($x, $y) = $ctx->toAbsolute($this->x, $this->y);
|
list($x, $y) = $ctx->toAbsolute($this->x, $this->y);
|
||||||
$text = $ctx->getDocument()->createElement('text');
|
$text = $ctx->getDocument()->createElement('text');
|
||||||
$text->setAttribute('x', Format::formatSVGNumber($x - 15));
|
$text->setAttribute('x', Format::formatSVGNumber($x - 15));
|
||||||
$text->setAttribute(
|
|
||||||
'style',
|
$id = $this->id ?? uniqid('text-');
|
||||||
$this->getStyle()
|
$text->setAttribute('id', $id);
|
||||||
. ';font-size:' . $this->fontSize
|
$this->setId($id);
|
||||||
. '; font-family: Ubuntu, Calibri, Trebuchet MS, Helvetica, Verdana, sans-serif'
|
|
||||||
. ';font-weight: ' . $this->fontWeight
|
|
||||||
. ';font-stretch: ' . $this->fontStretch
|
|
||||||
. '; font-style: normal;'
|
|
||||||
. 'text-anchor: ' . $this->alignment
|
|
||||||
);
|
|
||||||
|
|
||||||
$text->setAttribute('y', Format::formatSVGNumber($y));
|
$text->setAttribute('y', Format::formatSVGNumber($y));
|
||||||
$text->appendChild(new DOMText($this->text));
|
$text->appendChild(new DOMText($this->text));
|
||||||
|
|
||||||
|
$style = new DOMDocument();
|
||||||
|
$style->loadHTML($this->getStyle());
|
||||||
|
|
||||||
|
$text->appendChild(
|
||||||
|
$text->ownerDocument->importNode(
|
||||||
|
$style->getElementsByTagName('style')->item(0),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return $text;
|
return $text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
namespace Icinga\Test {
|
namespace Icinga\Test {
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Icinga\Util\Csp;
|
||||||
use Icinga\Web\Request;
|
use Icinga\Web\Request;
|
||||||
use Icinga\Web\Response;
|
use Icinga\Web\Response;
|
||||||
|
use Icinga\Web\Session;
|
||||||
use ipl\I18n\NoopTranslator;
|
use ipl\I18n\NoopTranslator;
|
||||||
use ipl\I18n\StaticTranslator;
|
use ipl\I18n\StaticTranslator;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
@ -14,6 +16,7 @@ namespace Icinga\Test {
|
|||||||
use Icinga\Data\ConfigObject;
|
use Icinga\Data\ConfigObject;
|
||||||
use Icinga\Data\ResourceFactory;
|
use Icinga\Data\ResourceFactory;
|
||||||
use Icinga\Data\Db\DbConnection;
|
use Icinga\Data\Db\DbConnection;
|
||||||
|
use Tests\Icinga\Lib\FakeSession;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BaseTestCase
|
* Class BaseTestCase
|
||||||
@ -108,6 +111,8 @@ namespace Icinga\Test {
|
|||||||
parent::setUp();
|
parent::setUp();
|
||||||
$this->setupRequestMock();
|
$this->setupRequestMock();
|
||||||
$this->setupResponseMock();
|
$this->setupResponseMock();
|
||||||
|
Session::create(new FakeSession());
|
||||||
|
Csp::createNonce();
|
||||||
|
|
||||||
StaticTranslator::$instance = new NoopTranslator();
|
StaticTranslator::$instance = new NoopTranslator();
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,6 @@ class Announcements extends AbstractWidget
|
|||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
// Force container update on XHR
|
// Force container update on XHR
|
||||||
return '<div style="display: none;"></div>';
|
return '<div hidden></div>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,14 +39,14 @@ class ApplicationStateMessages extends AbstractWidget
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (! (bool) $enabled) {
|
if (! (bool) $enabled) {
|
||||||
return '<div style="display: none;"></div>';
|
return '<div hidden></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$active = $this->getMessages();
|
$active = $this->getMessages();
|
||||||
|
|
||||||
if (empty($active)) {
|
if (empty($active)) {
|
||||||
// Force container update on XHR
|
// Force container update on XHR
|
||||||
return '<div style="display: none;"></div>';
|
return '<div hidden></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$html = '<div>';
|
$html = '<div>';
|
||||||
|
@ -6,7 +6,9 @@ namespace Icinga\Web\Widget\Chart;
|
|||||||
use DateInterval;
|
use DateInterval;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use Icinga\Util\Color;
|
use Icinga\Util\Color;
|
||||||
|
use Icinga\Util\Csp;
|
||||||
use Icinga\Web\Widget\AbstractWidget;
|
use Icinga\Web\Widget\AbstractWidget;
|
||||||
|
use ipl\Web\Style;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a colored grid that visualizes a set of values for each day
|
* Display a colored grid that visualizes a set of values for each day
|
||||||
@ -32,6 +34,9 @@ class HistoryColorGrid extends AbstractWidget
|
|||||||
private $color;
|
private $color;
|
||||||
public $opacity = 1.0;
|
public $opacity = 1.0;
|
||||||
|
|
||||||
|
/** @var array<string, array<string, string>> History grid css rulesets */
|
||||||
|
protected $rulesets = [];
|
||||||
|
|
||||||
public function __construct($color = '#51e551', $start = null, $end = null)
|
public function __construct($color = '#51e551', $start = null, $end = null)
|
||||||
{
|
{
|
||||||
$this->setColor($color);
|
$this->setColor($color);
|
||||||
@ -123,18 +128,30 @@ class HistoryColorGrid extends AbstractWidget
|
|||||||
{
|
{
|
||||||
if (array_key_exists($day, $this->data) && $this->data[$day]['value'] > 0) {
|
if (array_key_exists($day, $this->data) && $this->data[$day]['value'] > 0) {
|
||||||
$entry = $this->data[$day];
|
$entry = $this->data[$day];
|
||||||
return '<a ' .
|
$this->rulesets['.grid-day-with-entry-' . $entry['value']] = [
|
||||||
'style="background-color: ' . $this->calculateColor($entry['value']) . ';'
|
'background-color' => $this->calculateColor($entry['value']),
|
||||||
. ' opacity: ' . $this->opacity . ';" ' .
|
'opacity' => $this->opacity
|
||||||
'aria-label="' . $entry['caption'] . '" ' .
|
];
|
||||||
'title="' . $entry['caption'] . '" ' .
|
|
||||||
'href="' . $entry['url'] . '" ' .
|
return '<a class="grid-day-with-entry-'
|
||||||
'></a>';
|
. $entry['value']
|
||||||
|
. '" '
|
||||||
|
. 'aria-label="' . $entry['caption']
|
||||||
|
. '" '
|
||||||
|
. 'title="' . $entry['caption']
|
||||||
|
. '" '
|
||||||
|
. 'href="' . $entry['url']
|
||||||
|
. '" '
|
||||||
|
. '"></a>';
|
||||||
} else {
|
} else {
|
||||||
return '<span ' .
|
if (! isset($this->rulesets['.grid-day-no-entry'])) {
|
||||||
'style="background-color: ' . $this->calculateColor(0) . '; opacity: ' . $this->opacity . ';" ' .
|
$this->rulesets['.grid-day-no-entry'] = [
|
||||||
'title="No entries for ' . $day . '" ' .
|
'background-color' => $this->calculateColor(0),
|
||||||
'></span>';
|
'opacity' => $this->opacity
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return '<span class="grid-day-no-entry"' . ' title="No entries for ' . $day . '"></span>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,8 +383,18 @@ class HistoryColorGrid extends AbstractWidget
|
|||||||
}
|
}
|
||||||
$grid = $this->createGrid();
|
$grid = $this->createGrid();
|
||||||
if ($this->orientation === self::ORIENTATION_HORIZONTAL) {
|
if ($this->orientation === self::ORIENTATION_HORIZONTAL) {
|
||||||
return $this->renderHorizontal($grid);
|
$html = $this->renderHorizontal($grid);
|
||||||
|
} else {
|
||||||
|
$html = $this->renderVertical($grid);
|
||||||
}
|
}
|
||||||
return $this->renderVertical($grid);
|
|
||||||
|
$historyGridStyle = new Style();
|
||||||
|
$historyGridStyle->setNonce(Csp::getStyleNonce());
|
||||||
|
|
||||||
|
foreach ($this->rulesets as $selector => $properties) {
|
||||||
|
$historyGridStyle->add($selector, $properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $html . $historyGridStyle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -471,7 +471,7 @@ class FilterEditor extends AbstractWidget
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->addTo && $this->addTo == $filter->getId()) {
|
if ($this->addTo && $this->addTo == $filter->getId()) {
|
||||||
$parts[] = '<li style="background: #ffb">' . $this->renderNewFilter() .$this->cancelLink(). '</li>';
|
$parts[] = '<li class="new-filter">' . $this->renderNewFilter() .$this->cancelLink(). '</li>';
|
||||||
}
|
}
|
||||||
|
|
||||||
$class = $level === 0 ? ' class="datafilter"' : '';
|
$class = $level === 0 ? ' class="datafilter"' : '';
|
||||||
@ -575,7 +575,7 @@ class FilterEditor extends AbstractWidget
|
|||||||
$this->elementId('operator', $filter),
|
$this->elementId('operator', $filter),
|
||||||
$ops,
|
$ops,
|
||||||
$filter === null ? null : $filter->getOperatorName(),
|
$filter === null ? null : $filter->getOperatorName(),
|
||||||
array('style' => 'width: 5em')
|
['class' => 'filter-operator']
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,7 +594,7 @@ class FilterEditor extends AbstractWidget
|
|||||||
$this->elementId('sign', $filter),
|
$this->elementId('sign', $filter),
|
||||||
$signs,
|
$signs,
|
||||||
$filter === null ? null : $filter->getSign(),
|
$filter === null ? null : $filter->getSign(),
|
||||||
array('style' => 'width: 4em')
|
['class' => 'filter-rule']
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -738,7 +738,7 @@ class FilterEditor extends AbstractWidget
|
|||||||
|
|
||||||
$html = ' <form method="post" class="search inline" action="'
|
$html = ' <form method="post" class="search inline" action="'
|
||||||
. $preservedUrl
|
. $preservedUrl
|
||||||
. '"><input type="text" name="q" style="width: 8em" class="search" value="" placeholder="'
|
. '"><input type="text" name="q" class="search search-input" value="" placeholder="'
|
||||||
. t('Search...')
|
. t('Search...')
|
||||||
. '" /></form>';
|
. '" /></form>';
|
||||||
|
|
||||||
@ -779,7 +779,7 @@ class FilterEditor extends AbstractWidget
|
|||||||
. '<form action="'
|
. '<form action="'
|
||||||
. Url::fromRequest()
|
. Url::fromRequest()
|
||||||
. '" class="editor" method="POST">'
|
. '" class="editor" method="POST">'
|
||||||
. '<input type="submit" name="submit" value="Apply" style="display:none;"/>'
|
. '<input type="submit" name="submit" value="Apply" hidden/>'
|
||||||
. '<ul class="tree"><li>'
|
. '<ul class="tree"><li>'
|
||||||
. $this->renderFilter($this->filter)
|
. $this->renderFilter($this->filter)
|
||||||
. '</li></ul>'
|
. '</li></ul>'
|
||||||
|
@ -52,7 +52,7 @@ EOT;
|
|||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $closeTpl = <<< 'EOT'
|
private $closeTpl = <<< 'EOT'
|
||||||
<li style="float: right;">
|
<li class="close-container-btn">
|
||||||
<a href="#" title="{TITLE}" aria-label="{TITLE}" class="close-container-control">
|
<a href="#" title="{TITLE}" aria-label="{TITLE}" class="close-container-control">
|
||||||
<i aria-hidden="true" class="icon-cancel"></i>
|
<i aria-hidden="true" class="icon-cancel"></i>
|
||||||
</a>
|
</a>
|
||||||
|
@ -5,11 +5,10 @@
|
|||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<?php foreach ($this->font->glyphs as $icon): ?>
|
<?php foreach ($this->font->glyphs as $icon): ?>
|
||||||
<!-- TODO: move CSS away //-->
|
<div class="icon <?=
|
||||||
<div style="width: 33%; font-size: 1.5em; height: 2em; float: left;" class="<?=
|
|
||||||
$this->font->css_prefix_text . $icon->css
|
$this->font->css_prefix_text . $icon->css
|
||||||
?>">
|
?>">
|
||||||
<?= $this->escape($icon->css) ?> <span style="font-size: 0.6em">(0x<?= dechex($icon->code) ?>)</span>
|
<?= $this->escape($icon->css) ?> <span class="icon-code">(0x<?= dechex($icon->code) ?>)</span>
|
||||||
</div>
|
</div>
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
</div>
|
</div>
|
||||||
|
@ -107,3 +107,14 @@ th {
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 33%;
|
||||||
|
font-size: 1.5em;
|
||||||
|
height: 2em;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-code {
|
||||||
|
font-size: 0.6em;
|
||||||
|
}
|
||||||
|
@ -63,7 +63,7 @@ class Zend_View_Helper_PluginOutput extends Zend_View_Helper_Abstract
|
|||||||
protected static $htmlReplacements = array(
|
protected static $htmlReplacements = array(
|
||||||
"\t",
|
"\t",
|
||||||
"\n",
|
"\n",
|
||||||
'<table style="font-size: 0.75em"'
|
'<table class="output-table"'
|
||||||
);
|
);
|
||||||
|
|
||||||
/** @var \Icinga\Module\Monitoring\Web\Helper\PluginOutputHookRenderer */
|
/** @var \Icinga\Module\Monitoring\Web\Helper\PluginOutputHookRenderer */
|
||||||
|
@ -112,9 +112,9 @@ for ($i = 0; $i < $diff->days; $i += $step) {
|
|||||||
$f->add(new DateInterval('P' . $step . 'D'));
|
$f->add(new DateInterval('P' . $step . 'D'));
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
<div style="width: 33.5em;">
|
<div class="event-grid">
|
||||||
<?php foreach (array_reverse($grids) as $key => $grid): ?>
|
<?php foreach (array_reverse($grids) as $key => $grid): ?>
|
||||||
<div style=" <?= $this->orientation === 'horizontal' ? '' : 'display: inline-block; vertical-align: top; top; margin: 0.5em;' ?>">
|
<div class=" <?= $this->orientation === 'horizontal' ? '' : 'vertical' ?>">
|
||||||
<?= $grid; ?>
|
<?= $grid; ?>
|
||||||
<?= $this->orientation === 'horizontal' ? '<br />' : '' ?>
|
<?= $this->orientation === 'horizontal' ? '<br />' : '' ?>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
<table class="name-value-table">
|
<table class="name-value-table">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 20%"></th>
|
<th></th>
|
||||||
<td><strong><?= $this->escape($contact->contact_alias) ?></strong> (<?= $contact->contact_name ?>)</td>
|
<td><strong><?= $this->escape($contact->contact_alias) ?></strong> (<?= $contact->contact_name ?>)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php if ($contact->contact_email): ?>
|
<?php if ($contact->contact_email): ?>
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Icinga\Util\Csp;
|
||||||
use Icinga\Web\Url;
|
use Icinga\Web\Url;
|
||||||
use Icinga\Util\Color;
|
use Icinga\Util\Color;
|
||||||
|
use ipl\Web\Style;
|
||||||
|
|
||||||
$groupInfo = $timeline->getGroupInfo();
|
$groupInfo = $timeline->getGroupInfo();
|
||||||
$firstRow = ! $beingExtended;
|
$firstRow = ! $beingExtended;
|
||||||
|
$timelineStyle = (new Style())
|
||||||
|
->setNonce(Csp::getStyleNonce())
|
||||||
|
->setModule('monitoring');
|
||||||
|
|
||||||
if (! $beingExtended && !$this->compact): ?>
|
if (! $beingExtended && !$this->compact): ?>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
@ -79,24 +85,72 @@ if (! $beingExtended && !$this->compact): ?>
|
|||||||
<?php foreach ($groupInfo as $groupName => $labelAndColor): ?>
|
<?php foreach ($groupInfo as $groupName => $labelAndColor): ?>
|
||||||
<?php if (array_key_exists($groupName, $timeInfo[1])): ?>
|
<?php if (array_key_exists($groupName, $timeInfo[1])): ?>
|
||||||
<?php
|
<?php
|
||||||
|
$styleId = uniqid();
|
||||||
$circleWidth = $timeline->calculateCircleWidth($timeInfo[1][$groupName], 2);
|
$circleWidth = $timeline->calculateCircleWidth($timeInfo[1][$groupName], 2);
|
||||||
$extrapolatedCircleWidth = $timeline->getExtrapolatedCircleWidth($timeInfo[1][$groupName], 2);
|
$extrapolatedCircleWidth = $timeline->getExtrapolatedCircleWidth($timeInfo[1][$groupName], 2);
|
||||||
?>
|
?>
|
||||||
<?php if ($firstRow && $extrapolatedCircleWidth !== $circleWidth): ?>
|
<?php if ($firstRow && $extrapolatedCircleWidth !== $circleWidth): ?>
|
||||||
<div class="circle-box" style="width: <?= $extrapolatedCircleWidth; ?>;">
|
<?php
|
||||||
<div class="outer-circle extrapolated <?= $timeInfo[1][$groupName]->getClass() ?>" style="<?= sprintf(
|
$timelineStyle->add(
|
||||||
'width: %2$s; height: %2$s; margin-top: -%1$Fem;',
|
"#circle-box-$styleId",
|
||||||
(float) substr($extrapolatedCircleWidth, 0, -2) / 2,
|
['width' => $extrapolatedCircleWidth]
|
||||||
$extrapolatedCircleWidth
|
);
|
||||||
); ?>">
|
|
||||||
|
$timelineStyle->add(
|
||||||
|
"#outer-circle-$styleId",
|
||||||
|
[
|
||||||
|
'width' => $extrapolatedCircleWidth,
|
||||||
|
'height' => $extrapolatedCircleWidth,
|
||||||
|
'margin-top' => sprintf(
|
||||||
|
'-%Fem',
|
||||||
|
(float)substr($extrapolatedCircleWidth, 0, -2) / 2
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
?>
|
||||||
|
<div id="circle-box-<?= $styleId ?>" class="circle-box">
|
||||||
|
<div id="outer-circle-<?= $styleId ?>" class="outer-circle extrapolated <?= $timeInfo[1][$groupName]->getClass() ?>">
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div class="circle-box" style="width: <?= $circleWidth; ?>;">
|
<?php
|
||||||
<div class="outer-circle" style="<?= sprintf(
|
$timelineStyle->add(
|
||||||
'width: %2$s; height: %2$s; margin-top: -%1$Fem;',
|
"#circle-box-$styleId",
|
||||||
(float) substr($circleWidth, 0, -2) / 2,
|
['width' => $circleWidth]
|
||||||
$circleWidth
|
);
|
||||||
); ?>">
|
|
||||||
|
$timelineStyle->add(
|
||||||
|
"#outer-circle-$styleId",
|
||||||
|
[
|
||||||
|
'width' => $circleWidth,
|
||||||
|
'height' => $circleWidth,
|
||||||
|
'margin-top' => sprintf(
|
||||||
|
'-%Fem',
|
||||||
|
(float)substr($circleWidth, 0, -2) / 2
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
?>
|
||||||
|
<div id="circle-box-<?= $styleId ?>" class="circle-box">
|
||||||
|
<div id="outer-circle-<?= $styleId ?>" class="outer-circle">
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
<?php
|
||||||
|
$timelineStyle->add(
|
||||||
|
"#inner-circle-$styleId",
|
||||||
|
[
|
||||||
|
'width' => $circleWidth,
|
||||||
|
'height' => $circleWidth,
|
||||||
|
'margin-top' => sprintf(
|
||||||
|
'-%Fem',
|
||||||
|
(float)substr($circleWidth, 0, -2) / 2
|
||||||
|
),
|
||||||
|
'margin-left' => sprintf(
|
||||||
|
'-%Fem',
|
||||||
|
(float)substr($circleWidth, 0, -2) / 2
|
||||||
|
),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
?>
|
||||||
<?= $this->qlink(
|
<?= $this->qlink(
|
||||||
'',
|
'',
|
||||||
$timeInfo[1][$groupName]->getDetailUrl(),
|
$timeInfo[1][$groupName]->getDetailUrl(),
|
||||||
@ -112,12 +166,8 @@ $extrapolatedCircleWidth = $timeline->getExtrapolatedCircleWidth($timeInfo[1][$g
|
|||||||
strtolower($labelAndColor['label']),
|
strtolower($labelAndColor['label']),
|
||||||
$titleTime
|
$titleTime
|
||||||
),
|
),
|
||||||
'class' => 'inner-circle ' . $timeInfo[1][$groupName]->getClass(),
|
'id' => "inner-circle-$styleId",
|
||||||
'style' => sprintf(
|
'class' => "inner-circle " . $timeInfo[1][$groupName]->getClass()
|
||||||
'width: %2$s; height: %2$s; margin-top: -%1$Fem; margin-left: -%1$Fem;',
|
|
||||||
(float) substr($circleWidth, 0, -2) / 2,
|
|
||||||
(string) $circleWidth
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
); ?>
|
); ?>
|
||||||
</div>
|
</div>
|
||||||
@ -143,3 +193,4 @@ $extrapolatedCircleWidth = $timeline->getExtrapolatedCircleWidth($timeInfo[1][$g
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
<?= $timelineStyle; ?>
|
||||||
|
@ -427,5 +427,6 @@ $dashboard->add(
|
|||||||
/*
|
/*
|
||||||
* CSS
|
* CSS
|
||||||
*/
|
*/
|
||||||
|
$this->provideCssFile('event-grid.less');
|
||||||
$this->provideCssFile('service-grid.less');
|
$this->provideCssFile('service-grid.less');
|
||||||
$this->provideCssFile('tables.less');
|
$this->provideCssFile('tables.less');
|
||||||
|
9
modules/monitoring/public/css/event-grid.less
Normal file
9
modules/monitoring/public/css/event-grid.less
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.event-grid {
|
||||||
|
width: 33.5em;
|
||||||
|
|
||||||
|
.vertical {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
margin: 0.5em;
|
||||||
|
}
|
||||||
|
}
|
@ -654,6 +654,9 @@ form.instance-features span.description, form.object-features span.description {
|
|||||||
.plugin-output {
|
.plugin-output {
|
||||||
border-left: 5px solid @gray-lighter;
|
border-left: 5px solid @gray-lighter;
|
||||||
padding: 0.66em 0.33em;
|
padding: 0.66em 0.33em;
|
||||||
|
.output-table {
|
||||||
|
font-size: 0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
.state-critical {
|
.state-critical {
|
||||||
background-color: @color-critical;
|
background-color: @color-critical;
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Icinga\Util\Csp;
|
||||||
use Icinga\Web\Notification;
|
use Icinga\Web\Notification;
|
||||||
|
use ipl\Web\Style;
|
||||||
|
|
||||||
$pages = $wizard->getPages();
|
$pages = $wizard->getPages();
|
||||||
$finished = isset($success);
|
$finished = isset($success);
|
||||||
$configPages = array_slice($pages, 3, count($pages) - 4, true);
|
$configPages = array_slice($pages, 3, count($pages) - 4, true);
|
||||||
$currentPos = array_search($wizard->getCurrentPage(), $pages, true);
|
$currentPos = array_search($wizard->getCurrentPage(), $pages, true);
|
||||||
list($configPagesLeft, $configPagesRight) = array_chunk($configPages, (int)(count($configPages) / 2), true);
|
list($configPagesLeft, $configPagesRight) = array_chunk($configPages, (int)(count($configPages) / 2), true);
|
||||||
|
$setupStyle = (new Style())
|
||||||
|
->setSelector('.setup-header > .progress-bar')
|
||||||
|
->setNonce(Csp::getStyleNonce());
|
||||||
|
|
||||||
$visitedPages = array_keys($wizard->getPageData());
|
$visitedPages = array_keys($wizard->getPageData());
|
||||||
$maxProgress = max(array_merge([0], array_keys(array_filter(
|
$maxProgress = max(array_merge([0], array_keys(array_filter(
|
||||||
@ -14,12 +19,19 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||||||
function ($page) use ($visitedPages) { return in_array($page->getName(), $visitedPages); }
|
function ($page) use ($visitedPages) { return in_array($page->getName(), $visitedPages); }
|
||||||
))));
|
))));
|
||||||
|
|
||||||
|
$setupStyle->add(
|
||||||
|
'.width-percent-10',
|
||||||
|
['width' => '10%']
|
||||||
|
)->add(
|
||||||
|
'.width-percent-60',
|
||||||
|
['width' => '60%']
|
||||||
|
);
|
||||||
?>
|
?>
|
||||||
<div id="setup-content-wrapper" data-base-target="layout">
|
<div id="setup-content-wrapper" data-base-target="layout">
|
||||||
<div class="setup-header">
|
<div class="setup-header">
|
||||||
<?= $this->img('img/icinga-logo-big.png'); ?>
|
<?= $this->img('img/icinga-logo-big.png'); ?>
|
||||||
<div class="progress-bar">
|
<div class="progress-bar">
|
||||||
<div class="step" style="width: 10%;">
|
<div class="step width-percent-10">
|
||||||
<h1><?= $this->translate('Welcome', 'setup.progress'); ?></h1>
|
<h1><?= $this->translate('Welcome', 'setup.progress'); ?></h1>
|
||||||
<?php $stateClass = $finished || $currentPos > 0 ? 'complete' : (
|
<?php $stateClass = $finished || $currentPos > 0 ? 'complete' : (
|
||||||
$maxProgress > 0 ? 'visited' : 'active'
|
$maxProgress > 0 ? 'visited' : 'active'
|
||||||
@ -30,7 +42,7 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||||||
<td class="right"><div class="line right <?= $stateClass; ?>"></div></td>
|
<td class="right"><div class="line right <?= $stateClass; ?>"></div></td>
|
||||||
</tr></tbody></table>
|
</tr></tbody></table>
|
||||||
</div>
|
</div>
|
||||||
<div class="step" style="width: 10%;">
|
<div class="step width-percent-10">
|
||||||
<h1><?= $this->translate('Modules', 'setup.progress'); ?></h1>
|
<h1><?= $this->translate('Modules', 'setup.progress'); ?></h1>
|
||||||
<?php $stateClass = $finished || $currentPos > 1 ? ' complete' : (
|
<?php $stateClass = $finished || $currentPos > 1 ? ' complete' : (
|
||||||
$maxProgress > 1 ? ' visited' : (
|
$maxProgress > 1 ? ' visited' : (
|
||||||
@ -46,7 +58,7 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||||||
<?= $this->restartForm ?>
|
<?= $this->restartForm ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="step" style="width: 10%;">
|
<div class="step width-percent-10">
|
||||||
<h1><?= $this->translate('Requirements', 'setup.progress'); ?></h1>
|
<h1><?= $this->translate('Requirements', 'setup.progress'); ?></h1>
|
||||||
<?php $stateClass = $finished || $currentPos > 2 ? ' complete' : (
|
<?php $stateClass = $finished || $currentPos > 2 ? ' complete' : (
|
||||||
$maxProgress > 2 ? ' visited' : (
|
$maxProgress > 2 ? ' visited' : (
|
||||||
@ -62,7 +74,7 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||||||
<?= $this->restartForm ?>
|
<?= $this->restartForm ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="step" style="width: 60%;">
|
<div class="step width-percent-60">
|
||||||
<h1><?= $this->translate('Configuration', 'setup.progress'); ?></h1>
|
<h1><?= $this->translate('Configuration', 'setup.progress'); ?></h1>
|
||||||
<table><tbody><tr>
|
<table><tbody><tr>
|
||||||
<td class="left">
|
<td class="left">
|
||||||
@ -76,14 +88,43 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||||||
$pos < $maxProgress ? ' visited' : ($currentPos > 2 ? ' active' : '')
|
$pos < $maxProgress ? ' visited' : ($currentPos > 2 ? ' active' : '')
|
||||||
); ?>
|
); ?>
|
||||||
<?php if ($page === $firstPage): ?>
|
<?php if ($page === $firstPage): ?>
|
||||||
<div class="line left<?= $stateClass; ?>" style="float: left; width: <?= sprintf(
|
<?php
|
||||||
'%.2F',
|
$setupStyle->add(
|
||||||
100 - (count($configPagesLeft) - 1) * $lineWidth
|
'.step .left-line-' . $pos,
|
||||||
); ?>%; margin-right: 0"></div>
|
[
|
||||||
|
'float' => 'left',
|
||||||
|
'width' => sprintf(
|
||||||
|
'%.2F%%',
|
||||||
|
100 - (count($configPagesLeft) - 1) * $lineWidth
|
||||||
|
),
|
||||||
|
'margin-right' => 0
|
||||||
|
]
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
<div class="line left<?= $stateClass; ?> left-line-<?= $pos; ?>"></div>
|
||||||
<?php elseif ($page === $lastPage): ?>
|
<?php elseif ($page === $lastPage): ?>
|
||||||
<div class="line<?= $stateClass; ?>" style="float: left; width: <?= $lineWidth; ?>%; margin-right: -0.1em;"></div>
|
<?php
|
||||||
|
$setupStyle->add(
|
||||||
|
'.step .left-line-' . $pos,
|
||||||
|
[
|
||||||
|
'float' => 'left',
|
||||||
|
'width' => $lineWidth . '%',
|
||||||
|
'margin-right' => '-0.1em'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
<div class="line<?= $stateClass; ?> left-line-<?= $pos; ?>"></div>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div class="line<?= $stateClass; ?>" style="float: left; width: <?= $lineWidth; ?>%;"></div>
|
<?php
|
||||||
|
$setupStyle->add(
|
||||||
|
'.step .left-line-' . $pos,
|
||||||
|
[
|
||||||
|
'float' => 'left',
|
||||||
|
'width' => $lineWidth . '%'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
<div class="line<?= $stateClass; ?> left-line-<?= $pos; ?>"></div>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
</td>
|
</td>
|
||||||
@ -106,14 +147,43 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||||||
$pos < $maxProgress ? ' visited' : ($currentPos > 2 ? ' active' : '')
|
$pos < $maxProgress ? ' visited' : ($currentPos > 2 ? ' active' : '')
|
||||||
); ?>
|
); ?>
|
||||||
<?php if ($page === $firstPage): ?>
|
<?php if ($page === $firstPage): ?>
|
||||||
<div class="line<?= $stateClass; ?>" style="float: left; width: <?= $lineWidth; ?>%; margin-left: -0.1em;"></div>
|
<?php
|
||||||
|
$setupStyle->add(
|
||||||
|
'.step .right-line-' . $pos,
|
||||||
|
[
|
||||||
|
'float' => 'left',
|
||||||
|
'width' => $lineWidth . '%',
|
||||||
|
'margin-right' => '-0.1em'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
<div class="line<?= $stateClass; ?> right-line-<?= $pos; ?>"></div>
|
||||||
<?php elseif ($page === $lastPage): ?>
|
<?php elseif ($page === $lastPage): ?>
|
||||||
<div class="line right<?= $stateClass; ?>" style="float: left; width: <?= sprintf(
|
<?php
|
||||||
'%.2F',
|
$setupStyle->add(
|
||||||
100 - (count($configPagesRight) - 1) * $lineWidth
|
'.step .right-line-' . $pos,
|
||||||
); ?>%; margin-left: 0;"></div>
|
[
|
||||||
|
'float' => 'left',
|
||||||
|
'width' => sprintf(
|
||||||
|
'%.2F%%',
|
||||||
|
100 - (count($configPagesRight) - 1) * $lineWidth
|
||||||
|
),
|
||||||
|
'margin-right' => 0
|
||||||
|
]
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
<div class="line right<?= $stateClass; ?> right-line-<?= $pos; ?>"></div>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div class="line<?= $stateClass; ?>" style="float: left; width: <?= $lineWidth; ?>%;"></div>
|
<?php
|
||||||
|
$setupStyle->add(
|
||||||
|
'.step .right-line-' . $pos,
|
||||||
|
[
|
||||||
|
'float' => 'left',
|
||||||
|
'width' => $lineWidth . '%'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
<div class="line<?= $stateClass; ?> right-line-<?= $pos; ?>"></div>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
</td>
|
</td>
|
||||||
@ -122,7 +192,7 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||||||
<?= $this->restartForm ?>
|
<?= $this->restartForm ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="step" style="width: 10%;">
|
<div class="step width-percent-10">
|
||||||
<h1><?= $this->translate('Finish', 'setup.progress'); ?></h1>
|
<h1><?= $this->translate('Finish', 'setup.progress'); ?></h1>
|
||||||
<?php $stateClass = $finished ? ' complete' : ($pages[$currentPos] === end($pages) ? ' active' : ''); ?>
|
<?php $stateClass = $finished ? ' complete' : ($pages[$currentPos] === end($pages) ? ' active' : ''); ?>
|
||||||
<table><tbody><tr>
|
<table><tbody><tr>
|
||||||
@ -151,3 +221,4 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||||||
}
|
}
|
||||||
?></ul>
|
?></ul>
|
||||||
</div>
|
</div>
|
||||||
|
<?= $setupStyle; ?>
|
||||||
|
@ -26,6 +26,7 @@ parameters:
|
|||||||
ignoreErrors:
|
ignoreErrors:
|
||||||
- '#Unsafe usage of new static\(\)#'
|
- '#Unsafe usage of new static\(\)#'
|
||||||
- '#. but return statement is missing#'
|
- '#. but return statement is missing#'
|
||||||
|
- '#Cannot call method importNode\(\) on DOMDocument\|null.#'
|
||||||
|
|
||||||
# ldap_connect() returns `LDAP\Connection` in php >= 81
|
# ldap_connect() returns `LDAP\Connection` in php >= 81
|
||||||
-
|
-
|
||||||
|
@ -48,3 +48,7 @@
|
|||||||
.primary-nav a {
|
.primary-nav a {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.remove-nav-item {
|
||||||
|
padding-left: 2em;
|
||||||
|
}
|
||||||
|
@ -103,3 +103,7 @@
|
|||||||
#layout.twocols .tabs > li > .close-container-control {
|
#layout.twocols .tabs > li > .close-container-control {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.close-container-btn {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
@ -208,6 +208,10 @@ table.multiselect tr[href] td {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#main div.filter {
|
#main div.filter {
|
||||||
|
.search.search-input {
|
||||||
|
width: 8em;
|
||||||
|
}
|
||||||
|
|
||||||
form.editor {
|
form.editor {
|
||||||
input[type=text], select {
|
input[type=text], select {
|
||||||
width: 12em;
|
width: 12em;
|
||||||
@ -238,6 +242,20 @@ table.multiselect tr[href] td {
|
|||||||
.buttons input:not(:last-child) {
|
.buttons input:not(:last-child) {
|
||||||
margin-right:.5em;
|
margin-right:.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul.tree {
|
||||||
|
.filter-operator {
|
||||||
|
width: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.new-filter {
|
||||||
|
background: #ffb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-rule {
|
||||||
|
width: 4em;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,6 +269,10 @@ form.role-form {
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unrestricted-role {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
.control-label > * {
|
.control-label > * {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
@ -641,3 +663,4 @@ ul.tree li a.error:hover {
|
|||||||
html.no-js .progress-label {
|
html.no-js .progress-label {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
public/js/bootstrap.js
vendored
Normal file
28
public/js/bootstrap.js
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
;(function () {
|
||||||
|
let html = document.documentElement;
|
||||||
|
window.name = html.dataset.icingaWindowName;
|
||||||
|
window.icinga = new Icinga({
|
||||||
|
baseUrl: html.dataset.icingaBaseUrl,
|
||||||
|
locale: html.lang,
|
||||||
|
timezone: html.dataset.icingaTimezone
|
||||||
|
});
|
||||||
|
|
||||||
|
if (! ('icingaIsIframe' in document.documentElement.dataset)) {
|
||||||
|
html.classList.replace('no-js', 'js');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.getComputedStyle) {
|
||||||
|
let matched;
|
||||||
|
let element = document.getElementById('layout');
|
||||||
|
let name = window
|
||||||
|
.getComputedStyle(html)['font-family']
|
||||||
|
.replace(/['",]/g, '');
|
||||||
|
|
||||||
|
if (null !== (matched = name.match(/^([a-z]+)-layout$/))) {
|
||||||
|
element.classList.replace('default-layout', name);
|
||||||
|
if ('object' === typeof window.console) {
|
||||||
|
window.console.log('Icinga Web 2: setting initial layout to ' + name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
@ -28,7 +28,7 @@
|
|||||||
var _this = e.data.self;
|
var _this = e.data.self;
|
||||||
|
|
||||||
$('#layout').append(
|
$('#layout').append(
|
||||||
'<div id="application-state" class="container" style="display: none" data-icinga-url="'
|
'<div id="application-state" class="container" hidden data-icinga-url="'
|
||||||
+ _this.icinga.loader.baseUrl
|
+ _this.icinga.loader.baseUrl
|
||||||
+ '/application-state" data-icinga-refresh="60"></div>'
|
+ '/application-state" data-icinga-refresh="60"></div>'
|
||||||
);
|
);
|
||||||
|
16
public/js/logout.js
Normal file
16
public/js/logout.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
;(function () {
|
||||||
|
/**
|
||||||
|
* When JavaScript is available, trigger an XmlHTTPRequest with the non-existing user 'logout' and abort it
|
||||||
|
* before it is able to finish. This will cause the browser to show a new authentication prompt in the next
|
||||||
|
* request.
|
||||||
|
*/
|
||||||
|
document.getElementById('logout-in-progress').hidden = true;
|
||||||
|
document.getElementById('logout-successful').hidden = false;
|
||||||
|
try {
|
||||||
|
var xhttp = new XMLHttpRequest();
|
||||||
|
xhttp.open('GET', 'arbitrary url', true, 'logout', 'logout');
|
||||||
|
xhttp.send('');
|
||||||
|
xhttp.abort();
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
})();
|
29
test/php/Lib/FakeSession.php
Normal file
29
test/php/Lib/FakeSession.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Icinga\Lib;
|
||||||
|
|
||||||
|
use Icinga\Web\Session\Session;
|
||||||
|
|
||||||
|
class FakeSession extends Session
|
||||||
|
{
|
||||||
|
public function read()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function exists()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function purge()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function refreshId()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return '1234567890';
|
||||||
|
}
|
||||||
|
}
|
@ -120,8 +120,6 @@ class FormTest extends BaseTestCase
|
|||||||
*/
|
*/
|
||||||
public function testWhetherACsrfCounterMeasureIsBeingAdded()
|
public function testWhetherACsrfCounterMeasureIsBeingAdded()
|
||||||
{
|
{
|
||||||
Mockery::mock('alias:Icinga\Web\Session')->shouldReceive('getSession->getId')->andReturn('1234567890');
|
|
||||||
|
|
||||||
$form = new Form();
|
$form = new Form();
|
||||||
$form->create();
|
$form->create();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user