diff --git a/library/Notifications/Widget/Timeline.php b/library/Notifications/Widget/Timeline.php index bb1e9028..3d7ccaa3 100644 --- a/library/Notifications/Widget/Timeline.php +++ b/library/Notifications/Widget/Timeline.php @@ -12,9 +12,11 @@ use Icinga\Module\Notifications\Widget\TimeGrid\EntryProvider; use Icinga\Module\Notifications\Widget\TimeGrid\GridStep; use Icinga\Module\Notifications\Widget\TimeGrid\Timescale; +use Icinga\Module\Notifications\Widget\TimeGrid\Util; use Icinga\Module\Notifications\Widget\Timeline\Entry; use Icinga\Module\Notifications\Widget\Timeline\MinimalGrid; use Icinga\Module\Notifications\Widget\Timeline\Rotation; +use IntlDateFormatter; use ipl\Html\Attributes; use ipl\Html\BaseHtmlElement; use ipl\Html\HtmlElement; @@ -24,6 +26,7 @@ use ipl\Web\Url; use ipl\Web\Widget\Icon; use ipl\Web\Widget\Link; +use Locale; use SplObjectStorage; use Traversable; @@ -318,8 +321,41 @@ protected function assemble() ) ); + $dateFormatter = new IntlDateFormatter( + Locale::getDefault(), + IntlDateFormatter::NONE, + IntlDateFormatter::SHORT + ); + + $now = new DateTime(); + $currentTime = new HtmlElement( + 'div', + new Attributes(['class' => 'time-hand']), + new HtmlElement( + 'div', + new Attributes(['class' => 'now', 'title' => $dateFormatter->format($now)]), + Text::create($this->translate('now')) + ) + ); + + $now = Util::roundToNearestThirtyMinute($now); + + $this->getStyle()->addFor($currentTime, [ + '--timeStartColumn' => + $now->format('G') * 2 // 2 columns per hour + + ($now->format('i') >= 30 ? 1 : 0) // 1 column for the half hour + + 1 // CSS starts counting columns from 1, not zero + ]); + + $clock = new HtmlElement( + 'div', + new Attributes(['class' => 'clock']), + new HtmlElement('div', new Attributes(['class' => 'current-day']), $currentTime) + ); + $this->getGrid() - ->addHtml(new Timescale($this->days, $this->getStyle())); + ->addHtml(new Timescale($this->days, $this->getStyle())) + ->addHtml($clock); } $this->addHtml( diff --git a/public/css/timeline.less b/public/css/timeline.less index 84fec062..84cfb040 100644 --- a/public/css/timeline.less +++ b/public/css/timeline.less @@ -15,7 +15,7 @@ .time-grid-header { box-sizing: border-box; position: sticky; - z-index: 1; + z-index: 2; // overlap the .clock .time-hand top: 0; } @@ -49,6 +49,7 @@ .overlay .entry { margin-top: 1em; margin-bottom: 1em; + z-index: 2; // overlap the .clock .time-hand .title { height: 100%; @@ -115,6 +116,34 @@ grid-area: ~"1 / -2 / 1 / -1"; } } + + .clock { + display: grid; + grid-template-columns: repeat(var(--primaryColumns), 1fr); + grid-area: ~"3 / 2 / 4 / 3"; + border-top: 1px solid transparent; // left not required, otherwise the .time-hand is not aligned properly + + .current-day { + display: grid; + grid-template-columns: repeat(var(--columnsPerStep), 1fr); + grid-area: ~"1 / 1 / 2 / 2"; + + .time-hand { + grid-area: ~"1 / var(--timeStartColumn) / 2 / calc(var(--timeStartColumn) + 1)"; + display: flex; + align-items: flex-end; + width: 1px; + border-left: 1px solid red; + z-index: 1; + + .now { + .rounded-corners(); + padding: 0 .25em; + transform: translate(-50%, 50%); + } + } + } + } } } @@ -185,6 +214,13 @@ color: @gray-semilight; background: @body-bg-color; } + + .clock .now { + background-color: @gray-light; + font-size: 0.75em; + color: red; + .user-select(none); + } } .timeline.minimal-layout .empty-notice {