Use `style` element to create css class for dynamic inline style
The `style` element with `nonce` attribute is used to create css classes for inline styles that are not static. This prevents Content-Security-Policy violations.
This commit is contained in:
parent
459f4198c3
commit
33a5f765b9
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; ?>
|
||||
|
|
|
@ -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,6 +19,13 @@ $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">
|
||||
|
@ -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>
|
||||
|
@ -151,3 +221,4 @@ $maxProgress = max(array_merge([0], array_keys(array_filter(
|
|||
}
|
||||
?></ul>
|
||||
</div>
|
||||
<?= $setupStyle; ?>
|
||||
|
|
|
@ -114,14 +114,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.width-percent-10 {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
.width-percent-60 {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.setup-content {
|
||||
padding: 1.5em 10em 0 10em;
|
||||
|
||||
|
|
Loading…
Reference in New Issue