Fix CSP violations (#5060)
This commit is contained in:
commit
b201b030b2
|
@ -111,7 +111,7 @@ jobs:
|
|||
|
||||
- name: Setup dependencies
|
||||
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
|
||||
|
||||
- name: PHPUnit
|
||||
|
|
|
@ -262,7 +262,7 @@ class RoleForm extends RepositoryForm
|
|||
PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY
|
||||
)))),
|
||||
'description' => $spec['description'],
|
||||
'style' => $isUnrestricted ? 'text-decoration:line-through;' : '',
|
||||
'class' => $isUnrestricted ? 'unrestricted-role' : '',
|
||||
'readonly' => $isUnrestricted ?: null
|
||||
]
|
||||
)
|
||||
|
|
|
@ -24,7 +24,15 @@ $iframeClass = $isIframe ? ' iframe' : '';
|
|||
$innerLayoutScript = $this->layout()->innerLayout . '.phtml';
|
||||
|
||||
?><!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>
|
||||
<meta charset="utf-8">
|
||||
<meta name="google" value="notranslate">
|
||||
|
@ -39,12 +47,6 @@ $innerLayoutScript = $this->layout()->innerLayout . '.phtml';
|
|||
<base target="_parent">
|
||||
<?php else: ?>
|
||||
<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 ?>
|
||||
<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') ?>" />
|
||||
|
@ -55,25 +57,6 @@ $innerLayoutScript = $this->layout()->innerLayout . '.phtml';
|
|||
<div id="layout" class="default-layout<?php if ($showFullscreen): ?> fullscreen-layout<?php endif ?>">
|
||||
<?= $this->render($innerLayoutScript); ?>
|
||||
</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">
|
||||
<button type="button">
|
||||
<!-- TODO: Accessibility attributes are missing since usage of the Icon class -->
|
||||
|
@ -95,13 +78,6 @@ $innerLayoutScript = $this->layout()->innerLayout . '.phtml';
|
|||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" src="<?= $this->href($jsfile) ?>"></script>
|
||||
<script type="text/javascript">
|
||||
window.name = '<?= $this->protectId('Icinga') ?>';
|
||||
var icinga = new Icinga({
|
||||
baseUrl: '<?= $this->baseUrl(); ?>',
|
||||
locale: '<?= $lang; ?>',
|
||||
timezone: '<?= $timezone ?>'
|
||||
});
|
||||
</script>
|
||||
<script type="text/javascript" src="<?= $this->href('js/bootstrap.js') ?>"></script>
|
||||
</body>
|
||||
</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
|
||||
authentication was configured (the default is to handle authentications internally in Icingaweb2).
|
||||
|
@ -9,44 +14,24 @@
|
|||
-->
|
||||
<div class="content">
|
||||
<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>
|
||||
<br>
|
||||
<?= $this->translate(
|
||||
'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'
|
||||
. ' browser session.'
|
||||
); ?>
|
||||
<p>
|
||||
<?= $this->translate(
|
||||
'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'
|
||||
. ' browser session.'
|
||||
); ?>
|
||||
</p>
|
||||
</div>
|
||||
<div id="logout-successful" class="alert alert-success" hidden><?= $this->translate('Logout successful'); ?></div>
|
||||
|
||||
<div class="container">
|
||||
<a href="<?= $this->href('dashboard'); ?>"><?= $this->translate('Login'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
/*
|
||||
* 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">
|
||||
<script type="text/javascript" src="<?= $this->href('js/logout.js'); ?>"></script>
|
||||
<style type="text/css" nonce="<?= Csp::getStyleNonce(); ?>">
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
background-color: #0095bf;
|
||||
|
@ -66,7 +51,7 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
#logout-status {
|
||||
#logout-in-progress {
|
||||
margin: 2em 0 1em;
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
|
|
|
@ -7,20 +7,20 @@
|
|||
<table class="avp action" data-base-target="_next">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 18em;">
|
||||
<th>
|
||||
<strong><?= t('Dashlet Name') ?></strong>
|
||||
</th>
|
||||
<th>
|
||||
<strong><?= t('Url') ?></strong>
|
||||
</th>
|
||||
<th style="width: 1.4em;"> </th>
|
||||
<th class="icon-col"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($this->dashboard->getPanes() as $pane): ?>
|
||||
<?php if ($pane->getDisabled()) continue; ?>
|
||||
<tr>
|
||||
<th colspan="2" style="text-align: left; padding: 0.5em;">
|
||||
<th colspan="2">
|
||||
<?php if ($pane->isUserWidget()): ?>
|
||||
<?= $this->qlink(
|
||||
$pane->getName(),
|
||||
|
@ -63,7 +63,7 @@
|
|||
array('title' => sprintf($this->translate('Edit dashlet %s'), $dashlet->getTitle()))
|
||||
); ?>
|
||||
</td>
|
||||
<td style="table-layout: fixed; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
<td>
|
||||
<?= $this->qlink(
|
||||
$dashlet->getUrl()->getRelativeUrl(),
|
||||
$dashlet->getUrl()->getRelativeUrl(),
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
<tbody>
|
||||
<?php foreach ($this->logData as $value): ?>
|
||||
<?php $datetime = new Datetime($value->datetime) ?>
|
||||
<tr class="state">
|
||||
<td style="width: 6em; text-align: center">
|
||||
<tr>
|
||||
<td>
|
||||
<?= $this->escape($datetime->format('d.m. H:i')) ?><br />
|
||||
<?= $this->escape($value->loglevel) ?>
|
||||
</td>
|
||||
|
|
|
@ -17,9 +17,9 @@ if (! $this->compact): ?>
|
|||
<table class="table-row-selectable common-table">
|
||||
<thead>
|
||||
<th><?= $this->translate('Shared Navigation'); ?></th>
|
||||
<th style="width: 10em"><?= $this->translate('Type'); ?></th>
|
||||
<th style="width: 10em"><?= $this->translate('Owner'); ?></th>
|
||||
<th style="width: 5em"><?= $this->translate('Unshare'); ?></th>
|
||||
<th><?= $this->translate('Type'); ?></th>
|
||||
<th><?= $this->translate('Owner'); ?></th>
|
||||
<th><?= $this->translate('Unshare'); ?></th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($items as $item): ?>
|
||||
|
@ -53,7 +53,7 @@ if (! $this->compact): ?>
|
|||
)
|
||||
); ?></td>
|
||||
<?php else: ?>
|
||||
<td data-base-target="_self"><?= $removeForm
|
||||
<td data-base-target="_self" class="remove-nav-item"><?= $removeForm
|
||||
->setDefault('name', $item->name)
|
||||
->setAction(Url::fromPath(
|
||||
'navigation/unshare',
|
||||
|
|
|
@ -75,6 +75,7 @@ class Test extends Cli
|
|||
|
||||
// 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\\Icinga\\Lib', $this->getBaseDir('test/php/Lib'));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ class BarGraph extends Styleable implements Drawable
|
|||
$rect->setAttribute('data-icinga-graph-index', $index);
|
||||
}
|
||||
$rect->setAttribute('data-icinga-graph-type', 'bar');
|
||||
$rect->setAdditionalStyle('clip-path: url(#clip);');
|
||||
$rect->setAdditionalStyle(['clip-path' => 'url(#clip)']);
|
||||
return $rect;
|
||||
}
|
||||
|
||||
|
|
|
@ -165,8 +165,8 @@ class LineGraph extends Styleable implements Drawable
|
|||
$path->setFill($this->fill);
|
||||
}
|
||||
|
||||
$path->setAdditionalStyle('clip-path: url(#clip);');
|
||||
$path->setId($this->id);
|
||||
$path->setAdditionalStyle(['clip-path' => 'url(#clip)']);
|
||||
$path->setId($this->id ?? uniqid('line-graph-'));
|
||||
$group = $path->toSvg($ctx);
|
||||
|
||||
foreach ($this->dataset as $x => $point) {
|
||||
|
@ -180,7 +180,7 @@ class LineGraph extends Styleable implements Drawable
|
|||
if (isset($this->tooltips[$x])) {
|
||||
$invisible = new Circle($point[0], $point[1], 20);
|
||||
$invisible->setFill($this->strokeColor);
|
||||
$invisible->setAdditionalStyle('opacity: 0.0;');
|
||||
$invisible->setAdditionalStyle(['opacity' => '0.0']);
|
||||
$data = array(
|
||||
'label' => isset($this->graphs[$this->order]['label']) ?
|
||||
strtolower($this->graphs[$this->order]['label']) : '',
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
namespace Icinga\Chart\Primitive;
|
||||
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use Icinga\Chart\Render\RenderContext;
|
||||
use Icinga\Chart\Format;
|
||||
|
@ -61,8 +62,23 @@ class Circle extends Styleable implements Drawable
|
|||
$circle->setAttribute('cx', Format::formatSVGNumber($coords[0]));
|
||||
$circle->setAttribute('cy', Format::formatSVGNumber($coords[1]));
|
||||
$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);
|
||||
|
||||
$style = new DOMDocument();
|
||||
$style->loadHTML($this->getStyle());
|
||||
|
||||
$circle->appendChild(
|
||||
$circle->ownerDocument->importNode(
|
||||
$style->getElementsByTagName('style')->item(0),
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
return $circle;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
namespace Icinga\Chart\Primitive;
|
||||
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use Icinga\Chart\Render\RenderContext;
|
||||
use Icinga\Chart\Format;
|
||||
|
@ -80,8 +81,23 @@ class Line extends Styleable implements Drawable
|
|||
$line->setAttribute('x2', Format::formatSVGNumber($x2));
|
||||
$line->setAttribute('y1', Format::formatSVGNumber($y1));
|
||||
$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);
|
||||
|
||||
$style = new DOMDocument();
|
||||
$style->loadHTML($this->getStyle());
|
||||
|
||||
$line->appendChild(
|
||||
$line->ownerDocument->importNode(
|
||||
$style->getElementsByTagName('style')->item(0),
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
return $line;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
namespace Icinga\Chart\Primitive;
|
||||
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use Icinga\Chart\Render\RenderContext;
|
||||
use Icinga\Chart\Format;
|
||||
|
@ -162,12 +163,24 @@ class Path extends Styleable implements Drawable
|
|||
}
|
||||
|
||||
$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('style', $this->getStyle());
|
||||
|
||||
$this->applyAttributes($path);
|
||||
$style = new DOMDocument();
|
||||
$style->loadHTML($this->getStyle());
|
||||
|
||||
$path->appendChild(
|
||||
$path->ownerDocument->importNode(
|
||||
$style->getElementsByTagName('style')->item(0),
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
$group->appendChild($path);
|
||||
return $group;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
namespace Icinga\Chart\Primitive;
|
||||
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use Icinga\Chart\Render\RenderContext;
|
||||
use Icinga\Chart\Format;
|
||||
|
@ -279,9 +280,22 @@ class PieSlice extends Animatable implements Drawable
|
|||
$slicePath = $doc->createElement('path');
|
||||
|
||||
$slicePath->setAttribute('d', $this->getPieSlicePath($x, $y, $r));
|
||||
$slicePath->setAttribute('style', $this->getStyle());
|
||||
$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);
|
||||
$group->appendChild($slicePath);
|
||||
if ($this->caption != "") {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
namespace Icinga\Chart\Primitive;
|
||||
|
||||
use DOMElement;
|
||||
use DOMDocument;
|
||||
use Icinga\Chart\Render\RenderContext;
|
||||
use Icinga\Chart\Format;
|
||||
|
||||
|
@ -95,11 +96,24 @@ class Rect extends Animatable implements Drawable
|
|||
$rect->setAttribute('y', Format::formatSVGNumber($y));
|
||||
$rect->setAttribute('width', Format::formatSVGNumber($width));
|
||||
$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->appendAnimation($rect, $ctx);
|
||||
|
||||
$style = new DOMDocument();
|
||||
$style->loadHTML($this->getStyle());
|
||||
|
||||
$rect->appendChild(
|
||||
$rect->ownerDocument->importNode(
|
||||
$style->getElementsByTagName('style')->item(0),
|
||||
true
|
||||
)
|
||||
);
|
||||
|
||||
return $rect;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
namespace Icinga\Chart\Primitive;
|
||||
|
||||
use DOMElement;
|
||||
use Icinga\Util\Csp;
|
||||
use ipl\Web\Style;
|
||||
|
||||
/**
|
||||
* Base class for stylable drawables
|
||||
|
@ -36,14 +38,14 @@ class Styleable
|
|||
/**
|
||||
* Additional styles to be appended to the style attribute
|
||||
*
|
||||
* @var string
|
||||
* @var array<string, string>
|
||||
*/
|
||||
public $additionalStyle = '';
|
||||
public $additionalStyle = [];
|
||||
|
||||
/**
|
||||
* The id of this element
|
||||
*
|
||||
* @var string
|
||||
* @var ?string
|
||||
*/
|
||||
public $id = null;
|
||||
|
||||
|
@ -83,7 +85,7 @@ class Styleable
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
@ -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()
|
||||
{
|
||||
$base = sprintf("fill: %s; stroke: %s;stroke-width: %s;", $this->fill, $this->strokeColor, $this->strokeWidth);
|
||||
$base .= ';' . $this->additionalStyle . ';';
|
||||
return $base;
|
||||
$styles = $this->additionalStyle;
|
||||
$styles['fill'] = $this->fill;
|
||||
$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;
|
||||
|
||||
use DOMDocument;
|
||||
use DOMElement;
|
||||
use DOMText;
|
||||
use Icinga\Chart\Render\RenderContext;
|
||||
use Icinga\Chart\Format;
|
||||
use ipl\Html\HtmlDocument;
|
||||
|
||||
/**
|
||||
* Wrapper for the SVG text element
|
||||
|
@ -97,6 +99,15 @@ class Text extends Styleable implements Drawable
|
|||
$this->y = $y;
|
||||
$this->text = $text;
|
||||
$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);
|
||||
$text = $ctx->getDocument()->createElement('text');
|
||||
$text->setAttribute('x', Format::formatSVGNumber($x - 15));
|
||||
$text->setAttribute(
|
||||
'style',
|
||||
$this->getStyle()
|
||||
. ';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
|
||||
);
|
||||
|
||||
$id = $this->id ?? uniqid('text-');
|
||||
$text->setAttribute('id', $id);
|
||||
$this->setId($id);
|
||||
|
||||
$text->setAttribute('y', Format::formatSVGNumber($y));
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
namespace Icinga\Test {
|
||||
|
||||
use Exception;
|
||||
use Icinga\Util\Csp;
|
||||
use Icinga\Web\Request;
|
||||
use Icinga\Web\Response;
|
||||
use Icinga\Web\Session;
|
||||
use ipl\I18n\NoopTranslator;
|
||||
use ipl\I18n\StaticTranslator;
|
||||
use RuntimeException;
|
||||
|
@ -14,6 +16,7 @@ namespace Icinga\Test {
|
|||
use Icinga\Data\ConfigObject;
|
||||
use Icinga\Data\ResourceFactory;
|
||||
use Icinga\Data\Db\DbConnection;
|
||||
use Tests\Icinga\Lib\FakeSession;
|
||||
|
||||
/**
|
||||
* Class BaseTestCase
|
||||
|
@ -108,6 +111,8 @@ namespace Icinga\Test {
|
|||
parent::setUp();
|
||||
$this->setupRequestMock();
|
||||
$this->setupResponseMock();
|
||||
Session::create(new FakeSession());
|
||||
Csp::createNonce();
|
||||
|
||||
StaticTranslator::$instance = new NoopTranslator();
|
||||
}
|
||||
|
|
|
@ -50,6 +50,6 @@ class Announcements extends AbstractWidget
|
|||
return $html;
|
||||
}
|
||||
// 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) {
|
||||
return '<div style="display: none;"></div>';
|
||||
return '<div hidden></div>';
|
||||
}
|
||||
|
||||
$active = $this->getMessages();
|
||||
|
||||
if (empty($active)) {
|
||||
// Force container update on XHR
|
||||
return '<div style="display: none;"></div>';
|
||||
return '<div hidden></div>';
|
||||
}
|
||||
|
||||
$html = '<div>';
|
||||
|
|
|
@ -6,7 +6,9 @@ namespace Icinga\Web\Widget\Chart;
|
|||
use DateInterval;
|
||||
use DateTime;
|
||||
use Icinga\Util\Color;
|
||||
use Icinga\Util\Csp;
|
||||
use Icinga\Web\Widget\AbstractWidget;
|
||||
use ipl\Web\Style;
|
||||
|
||||
/**
|
||||
* Display a colored grid that visualizes a set of values for each day
|
||||
|
@ -32,6 +34,9 @@ class HistoryColorGrid extends AbstractWidget
|
|||
private $color;
|
||||
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)
|
||||
{
|
||||
$this->setColor($color);
|
||||
|
@ -123,18 +128,30 @@ class HistoryColorGrid extends AbstractWidget
|
|||
{
|
||||
if (array_key_exists($day, $this->data) && $this->data[$day]['value'] > 0) {
|
||||
$entry = $this->data[$day];
|
||||
return '<a ' .
|
||||
'style="background-color: ' . $this->calculateColor($entry['value']) . ';'
|
||||
. ' opacity: ' . $this->opacity . ';" ' .
|
||||
'aria-label="' . $entry['caption'] . '" ' .
|
||||
'title="' . $entry['caption'] . '" ' .
|
||||
'href="' . $entry['url'] . '" ' .
|
||||
'></a>';
|
||||
$this->rulesets['.grid-day-with-entry-' . $entry['value']] = [
|
||||
'background-color' => $this->calculateColor($entry['value']),
|
||||
'opacity' => $this->opacity
|
||||
];
|
||||
|
||||
return '<a class="grid-day-with-entry-'
|
||||
. $entry['value']
|
||||
. '" '
|
||||
. 'aria-label="' . $entry['caption']
|
||||
. '" '
|
||||
. 'title="' . $entry['caption']
|
||||
. '" '
|
||||
. 'href="' . $entry['url']
|
||||
. '" '
|
||||
. '"></a>';
|
||||
} else {
|
||||
return '<span ' .
|
||||
'style="background-color: ' . $this->calculateColor(0) . '; opacity: ' . $this->opacity . ';" ' .
|
||||
'title="No entries for ' . $day . '" ' .
|
||||
'></span>';
|
||||
if (! isset($this->rulesets['.grid-day-no-entry'])) {
|
||||
$this->rulesets['.grid-day-no-entry'] = [
|
||||
'background-color' => $this->calculateColor(0),
|
||||
'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();
|
||||
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()) {
|
||||
$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"' : '';
|
||||
|
@ -575,7 +575,7 @@ class FilterEditor extends AbstractWidget
|
|||
$this->elementId('operator', $filter),
|
||||
$ops,
|
||||
$filter === null ? null : $filter->getOperatorName(),
|
||||
array('style' => 'width: 5em')
|
||||
['class' => 'filter-operator']
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -594,7 +594,7 @@ class FilterEditor extends AbstractWidget
|
|||
$this->elementId('sign', $filter),
|
||||
$signs,
|
||||
$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="'
|
||||
. $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...')
|
||||
. '" /></form>';
|
||||
|
||||
|
@ -779,7 +779,7 @@ class FilterEditor extends AbstractWidget
|
|||
. '<form action="'
|
||||
. Url::fromRequest()
|
||||
. '" 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>'
|
||||
. $this->renderFilter($this->filter)
|
||||
. '</li></ul>'
|
||||
|
|
|
@ -52,7 +52,7 @@ EOT;
|
|||
* @var string
|
||||
*/
|
||||
private $closeTpl = <<< 'EOT'
|
||||
<li style="float: right;">
|
||||
<li class="close-container-btn">
|
||||
<a href="#" title="{TITLE}" aria-label="{TITLE}" class="close-container-control">
|
||||
<i aria-hidden="true" class="icon-cancel"></i>
|
||||
</a>
|
||||
|
|
|
@ -5,11 +5,10 @@
|
|||
|
||||
<div class="content">
|
||||
<?php foreach ($this->font->glyphs as $icon): ?>
|
||||
<!-- TODO: move CSS away //-->
|
||||
<div style="width: 33%; font-size: 1.5em; height: 2em; float: left;" class="<?=
|
||||
<div class="icon <?=
|
||||
$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>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
|
|
|
@ -107,3 +107,14 @@ th {
|
|||
text-align: left;
|
||||
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(
|
||||
"\t",
|
||||
"\n",
|
||||
'<table style="font-size: 0.75em"'
|
||||
'<table class="output-table"'
|
||||
);
|
||||
|
||||
/** @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'));
|
||||
}
|
||||
?>
|
||||
<div style="width: 33.5em;">
|
||||
<div class="event-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; ?>
|
||||
<?= $this->orientation === 'horizontal' ? '<br />' : '' ?>
|
||||
</div>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<table class="name-value-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th style="width: 20%"></th>
|
||||
<th></th>
|
||||
<td><strong><?= $this->escape($contact->contact_alias) ?></strong> (<?= $contact->contact_name ?>)</td>
|
||||
</tr>
|
||||
<?php if ($contact->contact_email): ?>
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
<?php
|
||||
|
||||
use Icinga\Util\Csp;
|
||||
use Icinga\Web\Url;
|
||||
use Icinga\Util\Color;
|
||||
use ipl\Web\Style;
|
||||
|
||||
$groupInfo = $timeline->getGroupInfo();
|
||||
$firstRow = ! $beingExtended;
|
||||
$timelineStyle = (new Style())
|
||||
->setNonce(Csp::getStyleNonce())
|
||||
->setModule('monitoring');
|
||||
|
||||
if (! $beingExtended && !$this->compact): ?>
|
||||
<div class="controls">
|
||||
|
@ -79,24 +85,72 @@ if (! $beingExtended && !$this->compact): ?>
|
|||
<?php foreach ($groupInfo as $groupName => $labelAndColor): ?>
|
||||
<?php if (array_key_exists($groupName, $timeInfo[1])): ?>
|
||||
<?php
|
||||
$styleId = uniqid();
|
||||
$circleWidth = $timeline->calculateCircleWidth($timeInfo[1][$groupName], 2);
|
||||
$extrapolatedCircleWidth = $timeline->getExtrapolatedCircleWidth($timeInfo[1][$groupName], 2);
|
||||
?>
|
||||
<?php if ($firstRow && $extrapolatedCircleWidth !== $circleWidth): ?>
|
||||
<div class="circle-box" style="width: <?= $extrapolatedCircleWidth; ?>;">
|
||||
<div class="outer-circle extrapolated <?= $timeInfo[1][$groupName]->getClass() ?>" style="<?= sprintf(
|
||||
'width: %2$s; height: %2$s; margin-top: -%1$Fem;',
|
||||
(float) substr($extrapolatedCircleWidth, 0, -2) / 2,
|
||||
$extrapolatedCircleWidth
|
||||
); ?>">
|
||||
<?php
|
||||
$timelineStyle->add(
|
||||
"#circle-box-$styleId",
|
||||
['width' => $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: ?>
|
||||
<div class="circle-box" style="width: <?= $circleWidth; ?>;">
|
||||
<div class="outer-circle" style="<?= sprintf(
|
||||
'width: %2$s; height: %2$s; margin-top: -%1$Fem;',
|
||||
(float) substr($circleWidth, 0, -2) / 2,
|
||||
$circleWidth
|
||||
); ?>">
|
||||
<?php
|
||||
$timelineStyle->add(
|
||||
"#circle-box-$styleId",
|
||||
['width' => $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
|
||||
$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(
|
||||
'',
|
||||
$timeInfo[1][$groupName]->getDetailUrl(),
|
||||
|
@ -112,12 +166,8 @@ $extrapolatedCircleWidth = $timeline->getExtrapolatedCircleWidth($timeInfo[1][$g
|
|||
strtolower($labelAndColor['label']),
|
||||
$titleTime
|
||||
),
|
||||
'class' => 'inner-circle ' . $timeInfo[1][$groupName]->getClass(),
|
||||
'style' => sprintf(
|
||||
'width: %2$s; height: %2$s; margin-top: -%1$Fem; margin-left: -%1$Fem;',
|
||||
(float) substr($circleWidth, 0, -2) / 2,
|
||||
(string) $circleWidth
|
||||
)
|
||||
'id' => "inner-circle-$styleId",
|
||||
'class' => "inner-circle " . $timeInfo[1][$groupName]->getClass()
|
||||
)
|
||||
); ?>
|
||||
</div>
|
||||
|
@ -143,3 +193,4 @@ $extrapolatedCircleWidth = $timeline->getExtrapolatedCircleWidth($timeInfo[1][$g
|
|||
</div>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
<?= $timelineStyle; ?>
|
||||
|
|
|
@ -427,5 +427,6 @@ $dashboard->add(
|
|||
/*
|
||||
* CSS
|
||||
*/
|
||||
$this->provideCssFile('event-grid.less');
|
||||
$this->provideCssFile('service-grid.less');
|
||||
$this->provideCssFile('tables.less');
|
||||
|
|
|
@ -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 {
|
||||
border-left: 5px solid @gray-lighter;
|
||||
padding: 0.66em 0.33em;
|
||||
.output-table {
|
||||
font-size: 0.75em;
|
||||
}
|
||||
|
||||
.state-critical {
|
||||
background-color: @color-critical;
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
<?php
|
||||
|
||||
use Icinga\Util\Csp;
|
||||
use Icinga\Web\Notification;
|
||||
use ipl\Web\Style;
|
||||
|
||||
$pages = $wizard->getPages();
|
||||
$finished = isset($success);
|
||||
$configPages = array_slice($pages, 3, count($pages) - 4, true);
|
||||
$currentPos = array_search($wizard->getCurrentPage(), $pages, 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());
|
||||
$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); }
|
||||
))));
|
||||
|
||||
$setupStyle->add(
|
||||
'.width-percent-10',
|
||||
['width' => '10%']
|
||||
)->add(
|
||||
'.width-percent-60',
|
||||
['width' => '60%']
|
||||
);
|
||||
?>
|
||||
<div id="setup-content-wrapper" data-base-target="layout">
|
||||
<div class="setup-header">
|
||||
<?= $this->img('img/icinga-logo-big.png'); ?>
|
||||
<div class="progress-bar">
|
||||
<div class="step" style="width: 10%;">
|
||||
<div class="step width-percent-10">
|
||||
<h1><?= $this->translate('Welcome', 'setup.progress'); ?></h1>
|
||||
<?php $stateClass = $finished || $currentPos > 0 ? 'complete' : (
|
||||
$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>
|
||||
</tr></tbody></table>
|
||||
</div>
|
||||
<div class="step" style="width: 10%;">
|
||||
<div class="step width-percent-10">
|
||||
<h1><?= $this->translate('Modules', 'setup.progress'); ?></h1>
|
||||
<?php $stateClass = $finished || $currentPos > 1 ? ' complete' : (
|
||||
$maxProgress > 1 ? ' visited' : (
|
||||
|
@ -46,7 +58,7 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||
<?= $this->restartForm ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<div class="step" style="width: 10%;">
|
||||
<div class="step width-percent-10">
|
||||
<h1><?= $this->translate('Requirements', 'setup.progress'); ?></h1>
|
||||
<?php $stateClass = $finished || $currentPos > 2 ? ' complete' : (
|
||||
$maxProgress > 2 ? ' visited' : (
|
||||
|
@ -62,7 +74,7 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||
<?= $this->restartForm ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<div class="step" style="width: 60%;">
|
||||
<div class="step width-percent-60">
|
||||
<h1><?= $this->translate('Configuration', 'setup.progress'); ?></h1>
|
||||
<table><tbody><tr>
|
||||
<td class="left">
|
||||
|
@ -76,14 +88,43 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||
$pos < $maxProgress ? ' visited' : ($currentPos > 2 ? ' active' : '')
|
||||
); ?>
|
||||
<?php if ($page === $firstPage): ?>
|
||||
<div class="line left<?= $stateClass; ?>" style="float: left; width: <?= sprintf(
|
||||
'%.2F',
|
||||
100 - (count($configPagesLeft) - 1) * $lineWidth
|
||||
); ?>%; margin-right: 0"></div>
|
||||
<?php
|
||||
$setupStyle->add(
|
||||
'.step .left-line-' . $pos,
|
||||
[
|
||||
'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): ?>
|
||||
<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: ?>
|
||||
<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 endforeach ?>
|
||||
</td>
|
||||
|
@ -106,14 +147,43 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||
$pos < $maxProgress ? ' visited' : ($currentPos > 2 ? ' active' : '')
|
||||
); ?>
|
||||
<?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): ?>
|
||||
<div class="line right<?= $stateClass; ?>" style="float: left; width: <?= sprintf(
|
||||
'%.2F',
|
||||
100 - (count($configPagesRight) - 1) * $lineWidth
|
||||
); ?>%; margin-left: 0;"></div>
|
||||
<?php
|
||||
$setupStyle->add(
|
||||
'.step .right-line-' . $pos,
|
||||
[
|
||||
'float' => 'left',
|
||||
'width' => sprintf(
|
||||
'%.2F%%',
|
||||
100 - (count($configPagesRight) - 1) * $lineWidth
|
||||
),
|
||||
'margin-right' => 0
|
||||
]
|
||||
);
|
||||
?>
|
||||
<div class="line right<?= $stateClass; ?> right-line-<?= $pos; ?>"></div>
|
||||
<?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 endforeach ?>
|
||||
</td>
|
||||
|
@ -122,7 +192,7 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||
<?= $this->restartForm ?>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<div class="step" style="width: 10%;">
|
||||
<div class="step width-percent-10">
|
||||
<h1><?= $this->translate('Finish', 'setup.progress'); ?></h1>
|
||||
<?php $stateClass = $finished ? ' complete' : ($pages[$currentPos] === end($pages) ? ' active' : ''); ?>
|
||||
<table><tbody><tr>
|
||||
|
@ -151,3 +221,4 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||
}
|
||||
?></ul>
|
||||
</div>
|
||||
<?= $setupStyle; ?>
|
||||
|
|
|
@ -26,6 +26,7 @@ parameters:
|
|||
ignoreErrors:
|
||||
- '#Unsafe usage of new static\(\)#'
|
||||
- '#. but return statement is missing#'
|
||||
- '#Cannot call method importNode\(\) on DOMDocument\|null.#'
|
||||
|
||||
# ldap_connect() returns `LDAP\Connection` in php >= 81
|
||||
-
|
||||
|
|
|
@ -48,3 +48,7 @@
|
|||
.primary-nav a {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.remove-nav-item {
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
|
|
@ -103,3 +103,7 @@
|
|||
#layout.twocols .tabs > li > .close-container-control {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.close-container-btn {
|
||||
float: right;
|
||||
}
|
||||
|
|
|
@ -208,6 +208,10 @@ table.multiselect tr[href] td {
|
|||
}
|
||||
|
||||
#main div.filter {
|
||||
.search.search-input {
|
||||
width: 8em;
|
||||
}
|
||||
|
||||
form.editor {
|
||||
input[type=text], select {
|
||||
width: 12em;
|
||||
|
@ -238,6 +242,20 @@ table.multiselect tr[href] td {
|
|||
.buttons input:not(:last-child) {
|
||||
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;
|
||||
}
|
||||
|
||||
.unrestricted-role {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.control-label > * {
|
||||
display: inline-block;
|
||||
}
|
||||
|
@ -641,3 +663,4 @@ ul.tree li a.error:hover {
|
|||
html.no-js .progress-label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
$('#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
|
||||
+ '/application-state" data-icinga-refresh="60"></div>'
|
||||
);
|
||||
|
|
|
@ -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) {
|
||||
}
|
||||
})();
|
|
@ -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()
|
||||
{
|
||||
Mockery::mock('alias:Icinga\Web\Session')->shouldReceive('getSession->getId')->andReturn('1234567890');
|
||||
|
||||
$form = new Form();
|
||||
$form->create();
|
||||
|
||||
|
|
Loading…
Reference in New Issue