summaryrefslogtreecommitdiffstats
path: root/library/Icingadb/Widget/Detail/DowntimeCard.php
diff options
context:
space:
mode:
Diffstat (limited to 'library/Icingadb/Widget/Detail/DowntimeCard.php')
-rw-r--r--library/Icingadb/Widget/Detail/DowntimeCard.php336
1 files changed, 336 insertions, 0 deletions
diff --git a/library/Icingadb/Widget/Detail/DowntimeCard.php b/library/Icingadb/Widget/Detail/DowntimeCard.php
new file mode 100644
index 0000000..68cc922
--- /dev/null
+++ b/library/Icingadb/Widget/Detail/DowntimeCard.php
@@ -0,0 +1,336 @@
+<?php
+
+/* Icinga DB Web | (c) 2020 Icinga GmbH | GPLv2 */
+
+namespace Icinga\Module\Icingadb\Widget\Detail;
+
+use Icinga\Module\Icingadb\Model\Downtime;
+use ipl\Web\Widget\TimeAgo;
+use ipl\Web\Widget\TimeUntil;
+use ipl\Web\Widget\VerticalKeyValue;
+use ipl\Html\BaseHtmlElement;
+use ipl\Html\Html;
+
+class DowntimeCard extends BaseHtmlElement
+{
+ protected $downtime;
+
+ protected $duration;
+
+ protected $defaultAttributes = ['class' => 'progress-bar downtime-progress'];
+
+ protected $tag = 'div';
+
+ public function __construct(Downtime $downtime)
+ {
+ $this->downtime = $downtime;
+
+ $this->start = $this->downtime->scheduled_start_time;
+ $this->end = $this->downtime->scheduled_end_time;
+
+ if ($this->downtime->end_time > $this->downtime->scheduled_end_time) {
+ $this->duration = $this->downtime->end_time - $this->downtime->scheduled_start_time;
+ } else {
+ $this->duration = $this->downtime->scheduled_end_time - $this->downtime->scheduled_start_time;
+ }
+ }
+
+ protected function assemble()
+ {
+ $timeline = Html::tag('div', ['class' => 'downtime-timeline timeline']);
+ $hPadding = 10;
+
+ $above = Html::tag('ul', ['class' => 'above']);
+ $below = Html::tag('ul', ['class' => 'below']);
+
+ $flexProgress = null;
+ $markerFlexStart = null;
+ $markerFlexEnd = null;
+
+ if ($this->downtime->scheduled_end_time < time()) {
+ $endTime = new TimeAgo($this->downtime->scheduled_end_time);
+ } else {
+ $endTime = new TimeUntil($this->downtime->scheduled_end_time);
+ }
+
+ if ($this->downtime->is_flexible && $this->downtime->is_in_effect) {
+ $this->addAttributes(['class' => 'flexible in-effect']);
+
+ $flexStartLeft = $hPadding + $this->calcRelativeLeft($this->downtime->start_time);
+ $flexEndLeft = $hPadding + $this->calcRelativeLeft($this->downtime->end_time);
+
+ $evade = false;
+ if ($flexEndLeft - $flexStartLeft < 2) {
+ $flexStartLeft -= 1;
+ $flexEndLeft += 1;
+
+ if ($flexEndLeft > $hPadding + $this->calcRelativeLeft($this->downtime->scheduled_end_time)) {
+ $flexEndLeft = $hPadding + $this->calcRelativeLeft($this->downtime->scheduled_end_time) - .5;
+ $flexStartLeft = $flexEndLeft - 2;
+ }
+
+ if ($flexStartLeft < $hPadding + $this->calcRelativeLeft($this->downtime->scheduled_start_time)) {
+ $flexStartLeft = $hPadding + $this->calcRelativeLeft($this->downtime->scheduled_start_time) + .5;
+ $flexEndLeft = $flexStartLeft + 2;
+ }
+
+ $evade = true;
+ }
+
+ $markerFlexStart = Html::tag('div', [
+ 'class' => 'marker flex-start',
+ 'style' => sprintf('left: %F%%', $flexStartLeft)
+ ]);
+
+ $markerFlexEnd = Html::tag('div', [
+ 'class' => 'marker flex-end',
+ 'style' => sprintf('left: %F%%', $flexEndLeft)
+ ]);
+
+ if (time() > $this->downtime->scheduled_end_time) {
+ $timelineProgress = Html::tag('div', [
+ 'class' => 'timeline-overlay downtime-elapsed',
+ 'style' => sprintf(
+ 'left: %F%%; width: %F%%;',
+ $hPadding + $this->calcRelativeLeft($this->downtime->start_time),
+ $this->calcRelativeLeft($this->downtime->scheduled_end_time, $this->downtime->start_time)
+ )
+ ]);
+ $flexProgress = Html::tag('div', [
+ 'class' => 'timeline-overlay downtime-overrun',
+ 'style' => sprintf(
+ 'left: %F%%; width: %F%%;',
+ $hPadding + $this->calcRelativeLeft($this->downtime->scheduled_end_time),
+ $this->calcRelativeLeft(time(), $this->downtime->scheduled_end_time)
+ )
+ ]);
+ } else {
+ $timelineProgress = Html::tag('div', [
+ 'class' => 'timeline-overlay downtime-elapsed',
+ 'style' => sprintf(
+ 'left: %F%%; width: %F%%;',
+ $flexStartLeft,
+ $hPadding + $this->calcRelativeLeft(time()) - $flexStartLeft
+ )
+ ]);
+ }
+
+ $above->add([
+ Html::tag(
+ 'li',
+ ['class' => 'start positioned'],
+ Html::tag(
+ 'div',
+ ['class' => 'bubble'],
+ new VerticalKeyValue(t('Scheduled Start'), new TimeAgo($this->downtime->scheduled_start_time))
+ )
+ ),
+ Html::tag(
+ 'li',
+ [
+ 'class' => 'end positioned',
+ 'style' => sprintf(
+ 'left: %F%%',
+ $hPadding + $this->calcRelativeLeft($this->downtime->scheduled_end_time)
+ )
+ ],
+ Html::tag('div', ['class' => 'bubble'], new VerticalKeyValue(t('Scheduled End'), $endTime))
+ )
+ ]);
+
+ $below->add([
+ Html::tag(
+ 'li',
+ [
+ 'class' => 'start positioned',
+ 'style' => sprintf('left: %F%%', $flexStartLeft)
+ ],
+ Html::tag(
+ 'div',
+ ['class' => 'bubble upwards' . ($evade ? ' left' : '')],
+ new VerticalKeyValue(t('Start'), new TimeAgo($this->downtime->start_time))
+ )
+ ),
+ Html::tag(
+ 'li',
+ [
+ 'class' => 'end positioned',
+ 'style' => sprintf('left: %F%%', $flexEndLeft)
+ ],
+ Html::tag(
+ 'div',
+ ['class' => 'bubble upwards' . ($evade ? ' right' : '')],
+ new VerticalKeyValue(t('End'), new TimeUntil($this->downtime->end_time))
+ )
+ )
+ ]);
+ } elseif ($this->downtime->is_flexible) {
+ $this->addAttributes(['class' => 'flexible']);
+
+ $timelineProgress = Html::tag('div', [
+ 'class' => 'timeline-overlay downtime-elapsed',
+ 'style' => sprintf(
+ 'left: %F%%; width: %F%%;',
+ $hPadding + $this->calcRelativeLeft($this->downtime->scheduled_start_time),
+ $this->calcRelativeLeft(time())
+ )
+ ]);
+
+ $above->add([
+ Html::tag(
+ 'li',
+ ['class' => 'start positioned'],
+ Html::tag(
+ 'div',
+ ['class' => 'bubble'],
+ new VerticalKeyValue(
+ t('Scheduled Start'),
+ time() > $this->downtime->scheduled_start_time
+ ? new TimeAgo($this->downtime->scheduled_start_time)
+ : new TimeUntil($this->downtime->scheduled_start_time)
+ )
+ )
+ ),
+ Html::tag(
+ 'li',
+ [
+ 'class' => 'end positioned',
+ 'style' => sprintf(
+ 'left: %F%%',
+ $hPadding + $this->calcRelativeLeft($this->downtime->scheduled_end_time)
+ )
+ ],
+ Html::tag(
+ 'div',
+ ['class' => 'bubble'],
+ new VerticalKeyValue(t('Scheduled End'), $endTime)
+ )
+ )
+ ]);
+
+ $below = null;
+ } else {
+ $timelineProgress = Html::tag('div', [
+ 'class' => 'timeline-overlay downtime-elapsed',
+ 'style' => sprintf(
+ 'left: %F%%; width: %F%%;',
+ $hPadding + $this->calcRelativeLeft($this->downtime->scheduled_start_time),
+ $this->calcRelativeLeft(time())
+ )
+ ]);
+
+ $below->add([
+ Html::tag(
+ 'li',
+ [
+ 'class' => 'start positioned',
+ 'style' => sprintf(
+ 'left: %F%%',
+ $hPadding + $this->calcRelativeLeft($this->downtime->scheduled_start_time)
+ )
+ ],
+ Html::tag(
+ 'div',
+ ['class' => 'bubble upwards'],
+ new VerticalKeyValue(t('Start'), new TimeAgo($this->downtime->scheduled_start_time))
+ )
+ ),
+ Html::tag(
+ 'li',
+ [
+ 'class' => 'end positioned',
+ 'style' => sprintf(
+ 'left: %F%%',
+ $hPadding + $this->calcRelativeLeft($this->downtime->scheduled_end_time)
+ )
+ ],
+ Html::tag(
+ 'div',
+ ['class' => 'bubble upwards'],
+ new VerticalKeyValue(t('End'), new TimeUntil($this->downtime->scheduled_end_time))
+ )
+ )
+ ]);
+ }
+
+ $now = Html::tag(
+ 'li',
+ [
+ 'class' => 'now positioned',
+ 'style' => sprintf(
+ 'left: %F%%',
+ $hPadding + $this->calcRelativeLeft(time(), null, null, -$hPadding + 3)
+ )
+ ],
+ Html::tag(
+ 'div',
+ ['class' => 'bubble'],
+ Html::tag('strong', t('Now'))
+ )
+ );
+ $above->add($now);
+
+ $markerStart = Html::tag('div', [
+ 'class' => 'marker start',
+ 'style' => sprintf(
+ 'left: %F%%',
+ $hPadding + $this->calcRelativeLeft($this->downtime->scheduled_start_time)
+ )
+ ]);
+
+ $markerNow = Html::tag('div', [
+ 'class' => 'marker now',
+ 'style' => sprintf(
+ 'left: %F%%',
+ $hPadding + $this->calcRelativeLeft(time(), null, null, -$hPadding + 3)
+ )
+ ]);
+
+ $markerEnd = Html::tag('div', [
+ 'class' => 'marker end',
+ 'style' => sprintf(
+ 'left: %F%%',
+ $hPadding + $this->calcRelativeLeft($this->downtime->scheduled_end_time)
+ )
+ ]);
+
+ $timeline->add([
+ $timelineProgress,
+ $flexProgress,
+ $markerStart,
+ $markerEnd,
+ $markerFlexStart,
+ $markerFlexEnd,
+ $markerNow,
+ ]);
+
+ $this->add([
+ $above,
+ $timeline,
+ $below
+ ]);
+ }
+
+ protected function calcRelativeLeft($value, $relativeStart = null, $relativeWidth = null, $min = null, $max = null)
+ {
+ if ($relativeStart === null) {
+ $relativeStart = $this->downtime->scheduled_start_time;
+ }
+
+ if ($relativeWidth === null) {
+ $relativeWidth = $this->duration;
+ }
+
+ $left = round(($value - $relativeStart) / $relativeWidth * 80, 2);
+
+ if ($min !== null && $left < $min) {
+ $left = $min;
+ }
+
+ if ($max !== null && $left > $max) {
+ $left = $max;
+ }
+
+ return $left;
+ }
+}