1414use Icinga \Module \Notifications \Widget \TimeGrid \Timescale ;
1515use Icinga \Module \Notifications \Widget \TimeGrid \Util ;
1616use Icinga \Module \Notifications \Widget \Timeline \Entry ;
17+ use Icinga \Module \Notifications \Widget \Timeline \FakeEntry ;
1718use Icinga \Module \Notifications \Widget \Timeline \FutureEntry ;
1819use Icinga \Module \Notifications \Widget \Timeline \MinimalGrid ;
1920use Icinga \Module \Notifications \Widget \Timeline \Rotation ;
2021use IntlDateFormatter ;
2122use ipl \Html \Attributes ;
2223use ipl \Html \BaseHtmlElement ;
2324use ipl \Html \HtmlElement ;
25+ use ipl \Html \TemplateString ;
2426use ipl \Html \Text ;
2527use ipl \I18n \Translation ;
2628use ipl \Web \Style ;
@@ -42,6 +44,9 @@ class Timeline extends BaseHtmlElement implements EntryProvider
4244 /** @var array<int, Rotation> */
4345 protected $ rotations = [];
4446
47+ /** @var int */
48+ protected int $ scheduleId ;
49+
4550 /** @var DateTime */
4651 protected $ start ;
4752
@@ -88,11 +93,13 @@ public function getStyle(): Style
8893 /**
8994 * Create a new Timeline
9095 *
96+ * @param int $scheduleId The schedule ID
9197 * @param DateTime $start The day the grid should start on
9298 * @param int $days Number of days to show on the grid
9399 */
94- public function __construct (DateTime $ start , int $ days )
100+ public function __construct (int $ scheduleId , DateTime $ start , int $ days )
95101 {
102+ $ this ->scheduleId = $ scheduleId ;
96103 $ this ->start = $ start ;
97104 $ this ->days = $ days ;
98105 }
@@ -194,6 +201,14 @@ public function getEntries(): Traversable
194201 }
195202 }
196203
204+ if (! $ this ->minimalLayout ) {
205+ // Always yield a fake entry to reserve the position for the add-rotation button
206+ yield (new FakeEntry ())
207+ ->setPosition ($ resultPosition ++)
208+ ->setStart ($ this ->getGrid ()->getGridStart ())
209+ ->setEnd ($ this ->getGrid ()->getGridEnd ());
210+ }
211+
197212 $ entryToCellsMap = new SplObjectStorage ();
198213 foreach ($ occupiedCells as $ cell => $ entry ) {
199214 $ cells = $ entryToCellsMap [$ entry ] ?? [];
@@ -313,22 +328,18 @@ protected function assembleSidebarEntry(Rotation $rotation): BaseHtmlElement
313328
314329 protected function assemble ()
315330 {
316- if (empty ($ this ->rotations )) {
317- $ emptyNotice = new HtmlElement (
331+ if ($ this -> minimalLayout && empty ($ this ->rotations )) {
332+ $ this -> addHtml ( new HtmlElement (
318333 'div ' ,
319334 Attributes::create (['class ' => 'empty-notice ' ]),
320335 Text::create ($ this ->translate ('No rotations configured ' ))
321- );
322-
323- if ($ this ->minimalLayout ) {
324- $ this ->getAttributes ()->add (['class ' => 'minimal-layout ' ]);
325- $ this ->addHtml ($ emptyNotice );
326- } else {
327- $ this ->getGrid ()->addToSideBar ($ emptyNotice );
328- }
336+ ));
329337 }
330338
331339 if (! $ this ->minimalLayout ) {
340+ // We yield a fake overlay entry, so we also have to fake a sidebar entry
341+ $ this ->getGrid ()->addToSideBar (new HtmlElement ('div ' ));
342+
332343 $ this ->getGrid ()->addToSideBar (
333344 new HtmlElement (
334345 'div ' ,
@@ -369,7 +380,35 @@ protected function assemble()
369380 new HtmlElement ('div ' , new Attributes (['class ' => 'current-day ' ]), $ currentTime )
370381 );
371382
383+ if (empty ($ this ->rotations )) {
384+ $ newRotationMsg = $ this ->translate (
385+ 'No rotations configured, yet. {{#button}}Add your first Rotation{{/button}} '
386+ );
387+ } else {
388+ $ newRotationMsg = $ this ->translate (
389+ '{{#button}}Add another Rotation{{/button}} to override rotations above '
390+ );
391+ }
392+
372393 $ this ->getGrid ()
394+ ->addHtml (new HtmlElement (
395+ 'div ' ,
396+ new Attributes (['class ' => 'new-rotation-container ' ]),
397+ new HtmlElement (
398+ 'div ' ,
399+ Attributes::create (['class ' => 'new-rotation-content ' ]),
400+ TemplateString::create (
401+ $ newRotationMsg ,
402+ [
403+ 'button ' => (new Link (
404+ new Icon ('circle-plus ' ),
405+ Links::rotationAdd ($ this ->scheduleId ),
406+ ['class ' => empty ($ this ->rotations ) ? 'btn-primary ' : null ]
407+ ))->openInModal ()
408+ ]
409+ )
410+ )
411+ ))
373412 ->addHtml (new Timescale ($ this ->days , $ this ->getStyle ()))
374413 ->addHtml ($ clock );
375414 }
0 commit comments