Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve longer appointment style #134

Merged
merged 4 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
*/
raviks789 marked this conversation as resolved.
Show resolved Hide resolved
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) {
raviks789 marked this conversation as resolved.
Show resolved Hide resolved
$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
Loading