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 19, 2023
1 parent 53d9537 commit 699db6d
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 22 deletions.
208 changes: 186 additions & 22 deletions library/Notifications/Widget/Calendar/BaseGrid.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ abstract protected function calculateGridEnd(): DateTime;

abstract protected function getNoOfVisuallyConnectedHours(): int;

abstract protected function getGradientOrientation(): string;

abstract protected function getGridArea(int $rowStart, int $rowEnd, int $colStart, int $colEnd): array;

protected function getSectionsPerStep(): int
Expand Down Expand Up @@ -235,20 +237,23 @@ protected function assembleGridOverlay(BaseHtmlElement $overlay): void
}

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

foreach ($rows as $row => $hours) {
list($rowStart, $rowSpan) = $rowPlacements[spl_object_id($entry)][$row];
$colStart = min($hours);
$colEnd = max($hours);
$startOffset = (int) (($row / $sectionsPerStep) * ($gridBorderAt / 48) + $colStart / 48);
$endOffset = (int) (($row / $sectionsPerStep) * ($gridBorderAt / 48) + $colEnd / 48);
$startDate = (clone $this->getGridStart())->add(new DateInterval("P$startOffset" . 'D'));

// Calculate number of entries that are not displayed in the grid for each date
if ($rowStart > $row + $sectionsPerStep) {
$startOffset = (int) (($row / $sectionsPerStep) * ($gridBorderAt / 48) + $colStart / 48);
$endOffset = (int) (($row / $sectionsPerStep) * ($gridBorderAt / 48) + $colEnd / 48);
$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 @@ -272,11 +277,59 @@ protected function assembleGridOverlay(BaseHtmlElement $overlay): void

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

$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))
]);
$noOfVisuallyConnectedDays = $this->getNoOfVisuallyConnectedHours() / 24;
$rowStartDate = clone $this->getGridStart();
$rowEndDate = clone $rowStartDate;
$rowStartOffset = $startOffset - $startOffset % $noOfVisuallyConnectedDays;
$rowEndOffset = $endOffset
+ ($noOfVisuallyConnectedDays - $endOffset % $noOfVisuallyConnectedDays)
- 1;
$rowStartDate = $rowStartDate->add(new DateInterval('P' . $rowStartOffset . 'D'));
$rowEndDate = $rowEndDate->add(new DateInterval('P' . $rowEndOffset . 'D'));
$gradientOrientation = $this->getGradientOrientation();
$rowEndDate->setTime(23, 59);

$entryStartDate = clone $entry->getStart();
$entryEndDate = clone $entry->getEnd();

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

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

$style->add(".$entryClass", $entryHtmlProperties);
$startText = null;
$endText = null;
if (
$rowStartDate->format('Y-m-d') === $gridStartsAt->format('Y-m-d')
&& $entryStartDate < $gridStartsAt
) {
$startText = $this->translate('starts');
}

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

$entryHtml = new HtmlElement(
'div',
Expand All @@ -289,16 +342,92 @@ 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
{
/**
* Fetch properties for entryHtml
*
* @param string $entryColor
* @param string|null $direction
* @param string|null $opposite
*
* @return array
*/
protected function getEntryHtmlProperties(
string $entryColor,
?string $direction = null,
?string $opposite = null
): array {
$alphaEntry = dechex((int) (256 * 0.1));
$alphaBorder = dechex((int) (256 * 0.5));
switch ($direction) {
case 'top':
case 'left':
$style = [
'background' => sprintf(
'~"linear-gradient(to %s, %s%s calc(100%% - 1em), transparent)"',
$direction,
$entryColor,
$alphaEntry
),
'border-color' => $entryColor . $alphaBorder,
"border-$direction" => 'none',
'border-radius' => $direction === 'top' ? '0 0 0.25em 0.25em' : '0 0.25em 0.25em 0'
];

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

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,
$alphaEntry,
$direction
);
$style["border-$opposite"] = 'none';
$style['border-radius'] = 0;
}

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

return $style;
}

protected function assembleEntry(
BaseHtmlElement $html,
Entry $entry,
?string $startText,
?string $endText,
bool $isContinuation
): void {
if (($url = $entry->getUrl()) !== null) {
$entryContainer = new Link(null, $url);
$html->addHtml($entryContainer);
Expand All @@ -307,6 +436,38 @@ 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'
]
)
);

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

if ($startText) {
$startText .= ' ' . $entry->getStart()->format('d/m/y');
$title->addHtml(
HtmlElement::create(
'div',
['class' => 'starts-at'],
$startText
)
);
$titleAttr = $startText . ' ' . $titleAttr;
}

if ($endText) {
$endText .= ' ' . $entry->getEnd()->format('d/m/y H:i');
$titleAttr = $titleAttr . ' | ' . $endText;
}

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

if (! $isContinuation) {
$title->addHtml(new HtmlElement(
'time',
Expand All @@ -326,16 +487,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 +498,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
5 changes: 5 additions & 0 deletions library/Notifications/Widget/Calendar/DayGrid.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public function setGridStart(DateTime $start): BaseGrid
return parent::setGridStart($start);
}

protected function getGradientOrientation(): string
{
return 'vertical';
}

protected function getMaximumRowSpan(): int
{
return 28;
Expand Down
5 changes: 5 additions & 0 deletions library/Notifications/Widget/Calendar/MonthGrid.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public function setGridStart(DateTime $start): BaseGrid
return parent::setGridStart($start);
}

protected function getGradientOrientation(): string
{
return 'horizontal';
}

protected function calculateGridEnd(): DateTime
{
return (clone $this->getGridStart())->add(new DateInterval('P42D'));
Expand Down
5 changes: 5 additions & 0 deletions library/Notifications/Widget/Calendar/WeekGrid.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public function setGridStart(DateTime $start): BaseGrid
return parent::setGridStart($start);
}

protected function getGradientOrientation(): string
{
return 'vertical';
}

protected function calculateGridEnd(): DateTime
{
return (clone $this->getGridStart())->add(new DateInterval('P7D'));
Expand Down
17 changes: 17 additions & 0 deletions public/css/calendar.less
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,16 @@
padding: .125em;
height: 100%;
max-height: 100%;

.ends-at {
align-self: end;
}
}

.title {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
flex: 0 1 auto;
column-gap: .5em;
overflow: hidden;
Expand Down Expand Up @@ -318,6 +323,18 @@
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;
font-size: 11/12em;
line-height: 12/11 * 1.5;
}

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

0 comments on commit 699db6d

Please sign in to comment.