Skip to content

Commit

Permalink
Improve visual representation of the entries
Browse files Browse the repository at this point in the history
Entries starting the previous day or ending the next day must be distinguishable.
  • Loading branch information
raviks789 committed Oct 18, 2023
1 parent 71d1d72 commit d0b737a
Show file tree
Hide file tree
Showing 2 changed files with 190 additions and 22 deletions.
202 changes: 180 additions & 22 deletions library/Notifications/Widget/Calendar/BaseGrid.php
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,13 @@ protected function assembleGridOverlay(BaseHtmlElement $overlay): void
}

$this->extraEntriesCount = [];
/** @var Entry $entry */
foreach ($occupiedCells as $entry) {
$continuation = false;
$rows = $occupiedCells->getInfo();
$entryStartDate = clone $entry->getStart();
$entryEndDate = clone $entry->getEnd();

foreach ($rows as $row => $hours) {
list($rowStart, $rowSpan) = $rowPlacements[spl_object_id($entry)][$row];
$rowEnd = $rowStart + $rowSpan;
Expand All @@ -256,11 +260,11 @@ protected function assembleGridOverlay(BaseHtmlElement $overlay): void

// Calculate number of entries that are not displayed in the grid for each date
if ($rowStart > $row + $sectionsPerStep) {
$stepRow = $rowStart - $this->getSectionsPerStep();
$startOffset = $this->getStepOffset($stepRow, $gridArea[1] - 1);
$endOffset = $this->getStepOffset($stepRow, $gridArea[3] - 2);
$startOffset = $this->getStepOffset($rowStart - $sectionsPerStep, $colStart - 1);
$endOffset = $this->getStepOffset($rowEnd - $sectionsPerStep, $colEnd - 2);
$startDate = (clone $this->getGridStart())->add(new DateInterval("P$startOffset" . 'D'));
$duration = $endOffset - $startOffset;

for ($i = 0; $i <= $duration; $i++) {
$countIdx = $startDate->format('Y-m-d');
if (! isset($this->extraEntriesCount[$countIdx])) {
Expand All @@ -275,11 +279,64 @@ protected function assembleGridOverlay(BaseHtmlElement $overlay): void
continue;
}

$style->add(".$entryClass", [
'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))
]);
$startOffset = $this->getStepOffset($rowStart - 1, $colStart - 1);
$endOffset = $this->getStepOffset($rowEnd - 2, $colEnd - 2);

$startDate = clone $this->getGridStart();
$startDate->add(new DateInterval("P$startOffset" . 'D'));

$noOfVisuallyConnectedDays = intval($this->getNoOfVisuallyConnectedHours() / 24);
if ($noOfVisuallyConnectedDays === 7) {
$rowStartDate = clone $gridStartsAt;
$startDaysOffset = $startOffset - $startOffset % 7;
$rowStartDate = $rowStartDate->add(new DateInterval('P' . $startDaysOffset . 'D'));

$endDaysOffset = $endOffset + (6 - $endOffset % 7);
$rowEndDate = clone $gridStartsAt;
$rowEndDate = $rowEndDate->add(new DateInterval('P' . $endDaysOffset . 'D'));
$gradient = 'horizontal';
} else {
$rowStartDate = clone $startDate;
$rowEndDate = clone $startDate;
$gradient = 'vertical';
}

$rowEndDate->setTime(23, 59);

$entryColor = $entry->getAttendee()->getColor();
if ($entryStartDate < $rowStartDate && $entryEndDate > $rowEndDate) {
$gradientDirection = $gradient === 'horizontal' ? 'right' : 'top';
$oppDirection = $gradientDirection === 'top' ? 'bottom' : 'left';
$entryAtrr = $this->getEntryHtmlAttr($entryColor, $gradientDirection, $oppDirection);
} elseif ($entryEndDate > $rowEndDate) {
$gradientDirection = $gradient === 'horizontal' ? 'right' : 'bottom';
$entryAtrr = $this->getEntryHtmlAttr($entryColor, $gradientDirection);
} elseif ($entryStartDate < $rowStartDate) {
$gradientDirection = $gradient === 'horizontal' ? 'left' : 'top';
$entryAtrr = $this->getEntryHtmlAttr($entryColor, $gradientDirection);
} else {
$entryAtrr = $this->getEntryHtmlAttr($entryColor);
}

$entryAtrr['grid-area'] = sprintf('~"%d / %d / %d / %d"', ...$gridArea);

$style->add(".$entryClass", $entryAtrr);
$startText = false;
$endText = false;
if (
$rowStartDate->format('Y-m-d') === $gridStartsAt->format('Y-m-d')
&& $entryStartDate < $gridStartsAt
) {
$startText = true;
}

$rowEndDate->add(new DateInterval('P1D'));
if (
$rowEndDate->format('Y-m-d') === $gridEndsAt->format('Y-m-d')
&& $entryEndDate > $gridEndsAt
) {
$endText = true;
}

$entryHtml = new HtmlElement(
'div',
Expand All @@ -292,16 +349,83 @@ protected function assembleGridOverlay(BaseHtmlElement $overlay): void
'data-col-end' => $gridArea[3]
])
);
$this->assembleEntry($entryHtml, $entry, $continuation);

$this->assembleEntry($entryHtml, $entry, $startText, $endText, $continuation);
$overlay->addHtml($entryHtml);

$continuation = true;
}
}
}

protected function assembleEntry(BaseHtmlElement $html, Entry $entry, bool $isContinuation): void
{
protected function getEntryHtmlAttr(
string $entryColor,
?string $direction = null,
?string $opposite = null
): array {
$alpha = dechex((int) (256 * 0.1));
switch ($direction) {
case 'top':
case 'left':
$style = [
'background' => sprintf(
'~"linear-gradient(to %s, %s%s calc(100%% - 1em), transparent)"',
$direction,
$entryColor,
$alpha
),
'border-color' => $entryColor . $alpha,
'border-left' => 'none',
"border-$direction" => 'none',
'border-radius' => $direction === 'top' ? '0 0 0.25em 0.25em' : '0 0.25em 0.25em 0'
];

if ($opposite !== null) {
$style['background'] = sprintf(
'~"linear-gradient'
. '(to %3$s, transparent, %1$s%2$s 0.5em, %1$s%2$s calc(100%% - 0.5em), transparent)'
. '"',
$entryColor,
$alpha,
$direction
);
$style["border-$opposite"] = 'none';
$style['border-radius'] = 0;
}

break;
case 'bottom':
case 'right':
$style = [
'background' => sprintf(
'~"linear-gradient(to %s, %s%s calc(100%% - 1em), transparent)"',
$direction,
$entryColor,
$alpha
),
'border-color' => $entryColor . $alpha,
"border-$direction" => 'none',
'border-radius' => $direction === 'bottom' ? '0.25em 0.25em 0 0' : '0.25em 0 0 0.25em'
];

break;
default:
$style = [
'background-color' => $entryColor . $alpha,
'border-color' => $entryColor . $alpha
];
}

return $style;
}

protected function assembleEntry(
BaseHtmlElement $html,
Entry $entry,
bool $startText,
bool $endText,
bool $isContinuation
): void {
if (($url = $entry->getUrl()) !== null) {
$entryContainer = new Link(null, $url);
$html->addHtml($entryContainer);
Expand All @@ -310,6 +434,37 @@ protected function assembleEntry(BaseHtmlElement $html, Entry $entry, bool $isCo
}

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

if ($startText) {
$content->addHtml(
HtmlElement::create(
'div',
['class' => 'starts-at'],
$this->translate(sprintf('starts %s', $entry->getStart()->format('d/m/y')))
)
);
$titleAttr = $this->translate(
'starts '
. $entry->getStart()->format('H:i')
. ' | ' . $entry->getAttendee()->getName()
. ': ' . $entry->getDescription()
);
} else {
$titleAttr = $entry->getStart()->format('H:i')
. ' | ' . $entry->getAttendee()->getName()
. ': ' . $entry->getDescription();
}

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

if (! $isContinuation) {
$title->addHtml(new HtmlElement(
'time',
Expand All @@ -329,16 +484,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 @@ -349,7 +495,19 @@ protected function assembleEntry(BaseHtmlElement $html, Entry $entry, bool $isCo
Text::create($entry->getDescription())
)
)
));
);

if ($endText) {
$content->addHtml(
HtmlElement::create(
'div',
['class' => 'ends-at'],
$this->translate(sprintf('ends %s', $entry->getEnd()->format('d/m/y H:i')))
)
);
}

$entryContainer->addHtml($content);
}

protected function roundToNearestThirtyMinute(DateTime $time): DateTime
Expand Down
10 changes: 10 additions & 0 deletions public/css/calendar.less
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,16 @@
text-decoration: none;
}

.starts-at,
.ends-at {
z-index: -1;
mix-blend-mode: multiply;
color: @text-color-light;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.extra-count:hover {
text-decoration: underline;
}
Expand Down

0 comments on commit d0b737a

Please sign in to comment.