Skip to content

Commit 0dd85aa

Browse files
Feature/improved rotation tooltips (#374)
1 parent 17cf24a commit 0dd85aa

6 files changed

Lines changed: 662 additions & 19 deletions

File tree

library/Notifications/Widget/Timeline.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,16 @@ public function getEntries(): Traversable
185185
$occupiedCells = [];
186186
foreach ($rotations as $rotation) {
187187
$entryFound = false;
188+
if (! $this->minimalLayout) {
189+
$flyoutInfo = $rotation->generateEntryInfo();
190+
}
191+
188192
foreach ($rotation->fetchTimeperiodEntries($this->start, $this->getGrid()->getGridEnd()) as $entry) {
189193
$entryFound = true;
190194
if (! $this->minimalLayout) {
191195
$entry->setPosition($maxPriority - $rotation->getPriority());
196+
$entry->setFlyoutContent($flyoutInfo);
197+
$entry->calculateAndSetWidthClass($this->getGrid());
192198

193199
yield $entry;
194200
}
@@ -256,6 +262,8 @@ public function getEntries(): Traversable
256262
$resultEntry->setUrl($entry->getUrl());
257263
$resultEntry->getAttributes()
258264
->add('data-rotation-position', $entry->getPosition());
265+
$resultEntry->setFlyoutContent($entry->getFlyoutContent())
266+
->calculateAndSetWidthClass($this->getGrid());
259267
}
260268

261269
yield $resultEntry;

library/Notifications/Widget/Timeline/Entry.php

Lines changed: 90 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Icinga\Module\Notifications\Widget\Timeline;
66

7+
use Icinga\Module\Notifications\Widget\TimeGrid\BaseGrid;
78
use ipl\Html\Attributes;
89
use ipl\Html\BaseHtmlElement;
910
use Icinga\Module\Notifications\Widget\TimeGrid;
@@ -16,6 +17,18 @@ class Entry extends TimeGrid\Entry
1617
/** @var Member */
1718
protected $member;
1819

20+
/** @var ?EntryFlyout Content of the flyoutmenu that is shown when the entry is hovered */
21+
protected ?EntryFlyout $flyoutContent = null;
22+
23+
/**
24+
* @var string A CSS class that changes the placement of the flyout
25+
*
26+
* "narrow-entry": centers the flyout's caret on the entry
27+
* "medium-entry": behaves like narrow entry in minimal and poor layout, otherwise as a wide entry
28+
* "wide-entry": the flyout has a fixed offset
29+
*/
30+
protected string $widthClass = "wide-entry";
31+
1932
public function setMember(Member $member): self
2033
{
2134
$this->member = $member;
@@ -33,6 +46,80 @@ public function getColor(int $transparency): string
3346
return TimeGrid\Util::calculateEntryColor($this->getMember()->getName(), $transparency);
3447
}
3548

49+
/**
50+
* Set content of a tooltip that is shown when the entry is hovered
51+
*
52+
* @param EntryFlyout $content
53+
*
54+
* @return static
55+
*/
56+
public function setFlyoutContent(EntryFlyout $content): static
57+
{
58+
$this->flyoutContent = $content;
59+
60+
return $this;
61+
}
62+
63+
/**
64+
* Return the entry's flyout element
65+
*
66+
* @return EntryFlyout|null
67+
*/
68+
public function getFlyoutContent(): ?EntryFlyout
69+
{
70+
return $this->flyoutContent;
71+
}
72+
73+
/**
74+
* Set value of $widthClass which will be a CSS class of the rendered entry
75+
*
76+
* @param string $widthClass
77+
*
78+
* @return $this
79+
*/
80+
public function setWidthClass(string $widthClass): static
81+
{
82+
$this->widthClass = $widthClass;
83+
84+
return $this;
85+
}
86+
87+
/**
88+
* Return the current width class
89+
*
90+
* @return string
91+
*/
92+
public function getWidthClass(): string
93+
{
94+
return $this->widthClass;
95+
}
96+
97+
/**
98+
* Assign a width class based on the fraction of the grid duration occupied by this entry
99+
*
100+
* @param BaseGrid $grid
101+
* @param float $mediumThreshold Fraction of grid duration below which the entry is considered medium width
102+
* @param float $narrowThreshold Fraction of grid duration below which the entry is considered narrow
103+
*
104+
* @return $this
105+
*/
106+
public function calculateAndSetWidthClass(BaseGrid $grid, $mediumThreshold = 0.2, $narrowThreshold = 0.1): static
107+
{
108+
$totalGridDuration = $grid->getGridEnd()->getTimestamp() - $grid->getGridStart()->getTimestamp();
109+
$start = max($this->getStart()->getTimestamp(), $grid->getGridStart()->getTimestamp());
110+
$end = min($this->getEnd()->getTimestamp(), $grid->getGridEnd()->getTimestamp());
111+
$duration = $end - $start;
112+
if ($duration / $totalGridDuration < $narrowThreshold) {
113+
$this->setWidthClass('narrow-entry');
114+
} elseif ($duration / $totalGridDuration < $mediumThreshold) {
115+
$this->setWidthClass('medium-entry');
116+
} else {
117+
$this->setWidthClass('wide-entry');
118+
}
119+
120+
return $this;
121+
}
122+
36123
protected function assembleContainer(BaseHtmlElement $container): void
37124
{
38125
$container->addHtml(
@@ -48,24 +135,9 @@ protected function assembleContainer(BaseHtmlElement $container): void
48135
)
49136
);
50137

51-
$dateType = \IntlDateFormatter::NONE;
52-
$timeType = \IntlDateFormatter::SHORT;
53-
if (
54-
$this->getStart()->diff($this->getEnd())->days > 0
55-
|| $this->getStart()->format('Y-m-d') !== $this->getEnd()->format('Y-m-d')
56-
) {
57-
$dateType = \IntlDateFormatter::SHORT;
138+
if (isset($this->flyoutContent)) {
139+
$this->addHtml($this->flyoutContent->withActiveMember($this->getMember()));
140+
$this->getAttributes()->add('class', $this->getWidthClass());
58141
}
59-
60-
$formatter = new \IntlDateFormatter(\Locale::getDefault(), $dateType, $timeType);
61-
62-
$container->addAttributes([
63-
'title' => sprintf(
64-
$this->translate('%s is available from %s to %s'),
65-
$this->getMember()->getName(),
66-
$formatter->format($this->getStart()),
67-
$formatter->format($this->getEnd())
68-
)
69-
]);
70142
}
71143
}

0 commit comments

Comments
 (0)