Skip to content

Commit

Permalink
Improve longer appointment style (#134)
Browse files Browse the repository at this point in the history
fixes #129
  • Loading branch information
nilmerg authored Apr 18, 2024
2 parents 30c5c2e + ddef6dd commit 73ccbc7
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 94 deletions.
127 changes: 108 additions & 19 deletions library/Notifications/Widget/Calendar/BaseGrid.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,25 @@
use SplObjectStorage;
use Traversable;

/**
* @phpstan-type ContinuationType self::ACROSS_GRID | self::FROM_PREV_GRID | self::TO_NEXT_GRID | self::ACROSS_EDGES
*/
abstract class BaseGrid extends BaseHtmlElement
{
use Translation;

/** @var string Continuation type of the entry row continuing from the previous grid */
public const FROM_PREV_GRID = 'from-prev-grid';

/** @var string Continuation type of the entry row continuing to the next grid */
public const TO_NEXT_GRID = 'to-next-grid';

/** @var string Continuation type of the entry row continuing from the previous grid to the next grid */
public const ACROSS_GRID = 'across-grid';

/** @var string Continuation type of the entry row continuing across edges of the grid */
public const ACROSS_EDGES = 'across-edges';

protected $tag = 'div';

protected $defaultAttributes = ['class' => 'calendar-grid'];
Expand Down Expand Up @@ -169,6 +184,7 @@ protected function assembleGridOverlay(BaseHtmlElement $overlay): void
$gridBorderAt = $this->getNoOfVisuallyConnectedHours() * 2;

$cellOccupiers = [];
/** @var SplObjectStorage<Entry, int[][]> $occupiedCells */
$occupiedCells = new SplObjectStorage();
foreach ($this->calendar->getEntries() as $entry) {
$actualStart = $this->roundToNearestThirtyMinute($entry->getStart());
Expand Down Expand Up @@ -236,8 +252,12 @@ protected function assembleGridOverlay(BaseHtmlElement $overlay): void

$this->extraEntriesCount = [];
foreach ($occupiedCells as $entry) {
$continuation = false;
$continuationType = null;
$rows = $occupiedCells->getInfo();
$fromPrevGrid = $gridStartsAt > $entry->getStart();
$remainingRows = count($rows);
$toNextGrid = false;

foreach ($rows as $row => $hours) {
list($rowStart, $rowSpan) = $rowPlacements[spl_object_id($entry)][$row];
$colStart = min($hours);
Expand Down Expand Up @@ -271,33 +291,68 @@ protected function assembleGridOverlay(BaseHtmlElement $overlay): void
);

$entryClass = 'area-' . implode('-', $gridArea);
$lastRow = $remainingRows === 1;

if ($lastRow) {
$toNextGrid = $gridEndsAt < $entry->getEnd();
}

$backward = $continuationType || $fromPrevGrid;
$forward = ! $lastRow || $toNextGrid;
$gradientClass = null;
if ($forward && $backward) {
$gradientClass = 'two-way-gradient';
} elseif ($backward) {
$gradientClass = 'opening-gradient';
} elseif ($forward) {
$gradientClass = 'ending-gradient';
}

$style->add(".$entryClass", [
'--entry-bg' => $entry->getAttendee()->getColor() . dechex((int) (256 * 0.1)),
'grid-area' => sprintf('~"%d / %d / %d / %d"', ...$gridArea),
'background-color' => $entry->getAttendee()->getColor() . dechex((int) (256 * 0.1)),
'border-color' => $entry->getAttendee()->getColor() . dechex((int) (256 * 0.5))
]);

$entryHtml = new HtmlElement(
'div',
Attributes::create([
'class' => ['entry', $entryClass],
'class' => ['entry', $gradientClass, $entryClass],
'data-entry-id' => $entry->getId(),
'data-row-start' => $gridArea[0],
'data-col-start' => $gridArea[1],
'data-row-end' => $gridArea[2],
'data-col-end' => $gridArea[3]
])
);
$this->assembleEntry($entryHtml, $entry, $continuation);

if ($fromPrevGrid) {
$continuationType = $toNextGrid ? self::ACROSS_GRID : self::FROM_PREV_GRID;
} elseif ($toNextGrid) {
$continuationType = self::TO_NEXT_GRID;
} elseif ($forward) {
$continuationType = self::ACROSS_EDGES;
}

$this->assembleEntry($entryHtml, $entry, $continuationType);
$overlay->addHtml($entryHtml);

$continuation = true;
$fromPrevGrid = false;
$remainingRows -= 1;
}
}
}

protected function assembleEntry(BaseHtmlElement $html, Entry $entry, bool $isContinuation): void
/**
* Assemble the entry in the grid
*
* @param BaseHtmlElement $html Container where to add the entry's HTML
* @param Entry $entry The entry to assemble
* @param ?ContinuationType $continuationType Continuation type of the entry's HTML
*
* @return void
*/
protected function assembleEntry(BaseHtmlElement $html, Entry $entry, ?string $continuationType): void
{
if (($url = $entry->getUrl()) !== null) {
$entryContainer = new Link(null, $url);
Expand All @@ -307,13 +362,44 @@ protected function assembleEntry(BaseHtmlElement $html, Entry $entry, bool $isCo
}

$title = new HtmlElement('div', Attributes::create(['class' => 'title']));
if (! $isContinuation) {
$content = new HtmlElement(
'div',
Attributes::create(['class' => 'content'])
);

$titleAttr = $entry->getStart()->format('H:i')
. ' | ' . $entry->getAttendee()->getName()
. ': ' . $entry->getDescription();

$startText = null;
$endText = null;

if ($continuationType === self::ACROSS_GRID) {
$startText = sprintf($this->translate('starts %s'), $entry->getStart()->format('d/m/y'));
$endText = sprintf($this->translate('ends %s'), $entry->getEnd()->format('d/m/y H:i'));
} elseif ($continuationType === self::FROM_PREV_GRID) {
$startText = sprintf($this->translate('starts %s'), $entry->getStart()->format('d/m/y'));
} elseif ($continuationType === self::TO_NEXT_GRID) {
$endText = sprintf($this->translate('ends %s'), $entry->getEnd()->format('d/m/y H:i'));
}

if ($startText) {
$titleAttr = $startText . ' ' . $titleAttr;
}

if ($endText) {
$titleAttr = $titleAttr . ' | ' . $endText;
}

$content->addAttributes(['title' => $titleAttr]);

if ($continuationType !== null) {
$title->addHtml(new HtmlElement(
'time',
Attributes::create([
'datetime' => $entry->getStart()->format(DateTimeInterface::ATOM)
]),
Text::create($entry->getStart()->format('H:i'))
Text::create($entry->getStart()->format($startText ? 'd/m/y H:i' : 'H:i'))
));
}

Expand All @@ -326,16 +412,7 @@ protected function assembleEntry(BaseHtmlElement $html, Entry $entry, bool $isCo
)
);

$entryContainer->addHtml(new HtmlElement(
'div',
Attributes::create(
[
'class' => 'content',
'title' => $entry->getStart()->format('H:i')
. ' | ' . $entry->getAttendee()->getName()
. ': ' . $entry->getDescription()
]
),
$content->addHtml(
$title,
new HtmlElement(
'div',
Expand All @@ -346,7 +423,19 @@ protected function assembleEntry(BaseHtmlElement $html, Entry $entry, bool $isCo
Text::create($entry->getDescription())
)
)
));
);

if ($endText) {
$content->addHtml(
HtmlElement::create(
'div',
['class' => 'ends-at'],
$endText
)
);
}

$entryContainer->addHtml($content);
}

protected function roundToNearestThirtyMinute(DateTime $time): DateTime
Expand Down
32 changes: 1 addition & 31 deletions phpstan-baseline-standard.neon
Original file line number Diff line number Diff line change
Expand Up @@ -1120,24 +1120,9 @@ parameters:
count: 1
path: library/Notifications/Widget/Calendar/Attendee.php

-
message: "#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\\.$#"
count: 1
path: library/Notifications/Widget/Calendar/BaseGrid.php

-
message: "#^Call to an undefined method object\\:\\:getAttendee\\(\\)\\.$#"
count: 2
path: library/Notifications/Widget/Calendar/BaseGrid.php

-
message: "#^Call to an undefined method object\\:\\:getId\\(\\)\\.$#"
count: 1
path: library/Notifications/Widget/Calendar/BaseGrid.php

-
message: "#^Cannot call method format\\(\\) on DateTime\\|null\\.$#"
count: 3
count: 7
path: library/Notifications/Widget/Calendar/BaseGrid.php

-
Expand All @@ -1155,21 +1140,6 @@ parameters:
count: 1
path: library/Notifications/Widget/Calendar/BaseGrid.php

-
message: "#^Parameter \\#1 \\.\\.\\.\\$arg1 of function max expects array, mixed given\\.$#"
count: 1
path: library/Notifications/Widget/Calendar/BaseGrid.php

-
message: "#^Parameter \\#1 \\.\\.\\.\\$arg1 of function min expects array, mixed given\\.$#"
count: 1
path: library/Notifications/Widget/Calendar/BaseGrid.php

-
message: "#^Parameter \\#2 \\$entry of method Icinga\\\\Module\\\\Notifications\\\\Widget\\\\Calendar\\\\BaseGrid\\:\\:assembleEntry\\(\\) expects Icinga\\\\Module\\\\Notifications\\\\Widget\\\\Calendar\\\\Entry, object given\\.$#"
count: 1
path: library/Notifications/Widget/Calendar/BaseGrid.php

-
message: "#^Property Icinga\\\\Module\\\\Notifications\\\\Widget\\\\Calendar\\\\BaseGrid\\:\\:\\$extraEntriesCount type has no value type specified in iterable type array\\.$#"
count: 1
Expand Down
Loading

0 comments on commit 73ccbc7

Please sign in to comment.