From 1e003256b1088fcc464cce1c38b4a83c97a134c9 Mon Sep 17 00:00:00 2001 From: raviks789 <33730024+raviks789@users.noreply.github.com> Date: Fri, 22 Sep 2023 17:22:23 +0200 Subject: [PATCH 1/3] Add day mode to the calendar --- library/Notifications/Widget/Calendar.php | 11 +- .../Widget/Calendar/Controls.php | 10 +- .../Notifications/Widget/Calendar/DayGrid.php | 108 ++++++++++++++++++ public/css/calendar.less | 35 ++++++ 4 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 library/Notifications/Widget/Calendar/DayGrid.php diff --git a/library/Notifications/Widget/Calendar.php b/library/Notifications/Widget/Calendar.php index 7e252a91..d75d271e 100644 --- a/library/Notifications/Widget/Calendar.php +++ b/library/Notifications/Widget/Calendar.php @@ -7,6 +7,7 @@ use DateTime; use Icinga\Module\Notifications\Widget\Calendar\BaseGrid; use Icinga\Module\Notifications\Widget\Calendar\Controls; +use Icinga\Module\Notifications\Widget\Calendar\DayGrid; use Icinga\Module\Notifications\Widget\Calendar\Entry; use Icinga\Module\Notifications\Widget\Calendar\MonthGrid; use Icinga\Module\Notifications\Widget\Calendar\Util; @@ -31,6 +32,9 @@ class Calendar extends BaseHtmlElement /** @var string Mode to show a specific calendar week */ public const MODE_WEEK = 'week'; + /** @var string Mode to show only the day */ + public const MODE_DAY = 'day'; + protected $tag = 'div'; protected $defaultAttributes = ['class' => 'calendar']; @@ -83,10 +87,11 @@ protected function getModeStart(): DateTime return DateTime::createFromFormat('Y-m-d\TH:i:s', $month . '-01T00:00:00'); case self::MODE_WEEK: - default: $week = $this->getControls()->getValue('week') ?: (new DateTime())->format('Y-\WW'); return (new DateTime())->setTimestamp(strtotime($week)); + default: + return DateTime::createFromFormat('Y-m-d', $this->getControls()->getValue('day')); } } @@ -95,8 +100,10 @@ public function getGrid(): BaseGrid if ($this->grid === null) { if ($this->getControls()->getViewMode() === self::MODE_MONTH) { $this->grid = new MonthGrid($this, $this->getModeStart()); - } else { // $mode === self::MODE_WEEK + } elseif ($this->getControls()->getViewMode() === self::MODE_WEEK) { $this->grid = new WeekGrid($this, $this->getModeStart()); + } else { + $this->grid = new DayGrid($this, $this->getModeStart()); } } diff --git a/library/Notifications/Widget/Calendar/Controls.php b/library/Notifications/Widget/Calendar/Controls.php index c5f1d7c1..407f3ead 100644 --- a/library/Notifications/Widget/Calendar/Controls.php +++ b/library/Notifications/Widget/Calendar/Controls.php @@ -37,7 +37,6 @@ protected function assemble() ]); break; case Calendar::MODE_WEEK: - default: $this->addElement('input', 'week', [ 'class' => 'autosubmit', 'type' => 'week', @@ -45,10 +44,19 @@ protected function assemble() 'label' => $this->translate('Calendar Week') ]); break; + default: + $this->addElement('input', 'day', [ + 'class' => 'autosubmit', + 'type' => 'date', + 'value' => (new DateTime())->format('Y-m-d'), + 'label' => $this->translate('Date') + ]); + break; } $modeParam = 'mode'; $options = [ + Calendar::MODE_DAY => $this->translate('Day'), Calendar::MODE_WEEK => $this->translate('Week'), Calendar::MODE_MONTH => $this->translate('Month') ]; diff --git a/library/Notifications/Widget/Calendar/DayGrid.php b/library/Notifications/Widget/Calendar/DayGrid.php new file mode 100644 index 00000000..610a0cd1 --- /dev/null +++ b/library/Notifications/Widget/Calendar/DayGrid.php @@ -0,0 +1,108 @@ +getGridStart())->add(new DateInterval('P1D')); + } + + protected function getNoOfVisuallyConnectedHours(): int + { + return 24; + } + + protected function getGridArea(int $rowStart, int $rowEnd, int $colStart, int $colEnd): array + { + return [$colStart, $rowStart, $colEnd, $rowEnd]; + } + + protected function createGridSteps(): Traversable + { + $interval = new DateInterval('P1D'); + $hourStartsAt = clone $this->getGridStart(); + for ($i = 0; $i < 24; $i++) { + yield $hourStartsAt; + + $hourStartsAt->add($interval); + } + } + + protected function createHeader(): BaseHtmlElement + { + $header = new HtmlElement('div', Attributes::create(['class' => 'header'])); + + $currentDay = clone $this->getGridStart(); + $interval = new DateInterval('P1D'); + $header->addHtml(new HtmlElement( + 'div', + Attributes::create(['class' => 'column-title']), + new HtmlElement( + 'span', + Attributes::create(['class' => 'day-name']), + Text::create($this->getGridStart()->format('D')) + ), + new HtmlElement( + 'span', + Attributes::create(['class' => 'day-number']), + Text::create($currentDay->format('d')) + ) + )); + + return $header; + } + + protected function createSidebar(): BaseHtmlElement + { + $sidebar = new HtmlElement('div', Attributes::create(['class' => 'sidebar'])); + + $time = (new DateTime())->setTime(0, 0); + $interval = new DateInterval('PT1H'); + for ($i = 0; $i < 24; $i++) { + $sidebar->addHtml(new HtmlElement( + 'div', + Attributes::create(['class' => 'row-title']), + new HtmlElement( + 'span', + Attributes::create(['class' => 'hour']), + Text::create($time->format('H:i')) + ) + )); + + $time->add($interval); + } + + return $sidebar; + } + + protected function assemble() + { + $this->getAttributes()->add('class', 'day'); + + $this->addHtml( + $this->createHeader(), + $this->createSidebar(), + $this->createGrid(), + $this->createGridOverlay() + ); + } +} diff --git a/public/css/calendar.less b/public/css/calendar.less index c653f2f1..92156a56 100644 --- a/public/css/calendar.less +++ b/public/css/calendar.less @@ -174,10 +174,39 @@ } } +.calendar-grid.day { + @days: 1; + @hours: 24; + @rowsPerHour: 2; + @columnsPerDay: 28; + + .sidebar { + grid-template-rows: repeat(@hours, 1fr); + } + + .grid, + .overlay { + display: grid; + grid-template-rows: repeat(@hours * @rowsPerHour, 1fr); + grid-template-columns: repeat(@days * @columnsPerDay, minmax(2em, 1fr)); + } + + .grid, + .overlay { + border-left: none; + } + + .step { + grid-column-end: span @columnsPerDay; + grid-row-end: span @rowsPerHour; + } +} + .calendar-grid { display: grid; &.week, + &.day, &.month { .header { grid-area: ~"1 / 2 / 2 / 3"; @@ -201,6 +230,10 @@ grid-template-columns: 4em minmax(0, 1fr); grid-template-rows: 1.5em minmax(0, 1fr); } + &.day { + grid-template-columns: 6em minmax(0, 1fr); + grid-template-rows: 2.5em minmax(0, 1fr); + } .overlay { pointer-events: none; @@ -214,9 +247,11 @@ /* Design */ .calendar-controls { + input[type="date"], input[type="month"], input[type="week"] { background-color: @low-sat-blue; + width: auto; } .view-mode-switcher label { From df7e54f4af11879254d236cc2ce63adb208dced7 Mon Sep 17 00:00:00 2001 From: raviks789 <33730024+raviks789@users.noreply.github.com> Date: Fri, 22 Sep 2023 17:38:34 +0200 Subject: [PATCH 2/3] Show extra appointments link for week and month views --- library/Notifications/Model/Timeperiod.php | 2 +- library/Notifications/Widget/Calendar.php | 23 ++++- .../Widget/Calendar/BaseGrid.php | 47 ++++++++-- .../Notifications/Widget/Calendar/DayGrid.php | 23 ++++- .../Widget/Calendar/ExtraEntryCount.php | 72 +++++++++++++++ .../Widget/Calendar/MonthGrid.php | 7 ++ .../Widget/Calendar/WeekGrid.php | 12 +++ library/Notifications/Widget/Schedule.php | 89 +++++++++++-------- public/css/calendar.less | 23 ++++- public/css/form.less | 4 + 10 files changed, 250 insertions(+), 52 deletions(-) create mode 100644 library/Notifications/Widget/Calendar/ExtraEntryCount.php diff --git a/library/Notifications/Model/Timeperiod.php b/library/Notifications/Model/Timeperiod.php index 0484b927..26861beb 100644 --- a/library/Notifications/Model/Timeperiod.php +++ b/library/Notifications/Model/Timeperiod.php @@ -36,7 +36,7 @@ public function createRelations(Relations $relations) $relations->hasOne('parent', Schedule::class) ->setCandidateKey('owned_by_schedule_id') ->setJoinType('LEFT'); - $relations->hasMany('entry', TimeperiodEntry::class) + $relations->hasMany('timeperiod_entry', TimeperiodEntry::class) ->setJoinType('LEFT'); } } diff --git a/library/Notifications/Widget/Calendar.php b/library/Notifications/Widget/Calendar.php index d75d271e..4e005ccb 100644 --- a/library/Notifications/Widget/Calendar.php +++ b/library/Notifications/Widget/Calendar.php @@ -51,6 +51,9 @@ class Calendar extends BaseHtmlElement /** @var Url */ protected $addEntryUrl; + /** @var Url */ + protected $url; + public function setControls(Controls $controls): self { $this->controls = $controls; @@ -79,6 +82,22 @@ public function getAddEntryUrl(): ?Url return $this->addEntryUrl; } + public function setUrl(?Url $url): self + { + $this->url = $url; + + return $this; + } + + public function prepareDayViewUrl(DateTime $date): Url + { + $url = clone $this->url; + return $url->overwriteParams([ + 'mode' => 'day', + 'day' => $date->format('Y-m-d') + ]); + } + protected function getModeStart(): DateTime { switch ($this->getControls()->getViewMode()) { @@ -91,7 +110,9 @@ protected function getModeStart(): DateTime return (new DateTime())->setTimestamp(strtotime($week)); default: - return DateTime::createFromFormat('Y-m-d', $this->getControls()->getValue('day')); + $day = $this->getControls()->getValue('day') ?: (new DateTime())->format('Y-m-d'); + + return DateTime::createFromFormat('Y-m-d H:i:s', $day . ' 00:00:00'); } } diff --git a/library/Notifications/Widget/Calendar/BaseGrid.php b/library/Notifications/Widget/Calendar/BaseGrid.php index fc48b0ba..1e01dc2e 100644 --- a/library/Notifications/Widget/Calendar/BaseGrid.php +++ b/library/Notifications/Widget/Calendar/BaseGrid.php @@ -4,6 +4,7 @@ namespace Icinga\Module\Notifications\Widget\Calendar; +use DateInterval; use DateTime; use DateTimeInterface; use Icinga\Module\Notifications\Widget\Calendar; @@ -35,6 +36,9 @@ abstract class BaseGrid extends BaseHtmlElement /** @var DateTime */ protected $end; + /** @var array Extra counts stored as [date1 => count1, date2 => count2]*/ + protected $extraEntriesCount = []; + /** * Create a new calendar * @@ -137,6 +141,18 @@ protected function createGridOverlay(): BaseHtmlElement return $overlay; } + /** + * Fetch the count of additional entries for the given date + * + * @param DateTime $date + * + * @return int + */ + public function getExtraEntryCount(DateTime $date): int + { + return $this->extraEntriesCount[$date->format('Y-m-d')] ?? 0; + } + protected function assembleGridOverlay(BaseHtmlElement $overlay): void { $style = (new Style())->setNonce(Csp::getStyleNonce()); @@ -218,21 +234,42 @@ protected function assembleGridOverlay(BaseHtmlElement $overlay): void } } + $this->extraEntriesCount = []; 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); + + // Calculate number of entries that are not displayed in the grid for each date if ($rowStart > $row + $sectionsPerStep) { - // TODO: Register as +1 + $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])) { + $this->extraEntriesCount[$countIdx] = 1; + } else { + $this->extraEntriesCount[$countIdx] += 1; + } + + $startDate->add(new DateInterval('P1D')); + } + continue; } - $rowEnd = $rowStart + $rowSpan; - $colStart = min($hours) + 1; - $colEnd = max($hours) + 2; + $gridArea = $this->getGridArea( + $rowStart, + $rowStart + $rowSpan, + $colStart + 1, + $colEnd + 2 + ); - $gridArea = $this->getGridArea($rowStart, $rowEnd, $colStart, $colEnd); $entryClass = 'area-' . implode('-', $gridArea); $style->add(".$entryClass", [ diff --git a/library/Notifications/Widget/Calendar/DayGrid.php b/library/Notifications/Widget/Calendar/DayGrid.php index 610a0cd1..82ddab32 100644 --- a/library/Notifications/Widget/Calendar/DayGrid.php +++ b/library/Notifications/Widget/Calendar/DayGrid.php @@ -6,6 +6,7 @@ use DateInterval; use DateTime; +use InvalidArgumentException; use ipl\Html\Attributes; use ipl\Html\BaseHtmlElement; use ipl\Html\HtmlElement; @@ -14,13 +15,20 @@ class DayGrid extends BaseGrid { - protected $mode = 'day'; - public function setGridStart(DateTime $start): BaseGrid { + if ($start->format('H:i:s') !== '00:00:00') { + throw new InvalidArgumentException('Start is not midnight'); + } + return parent::setGridStart($start); } + protected function getMaximumRowSpan(): int + { + return 28; + } + protected function calculateGridEnd(): DateTime { return (clone $this->getGridStart())->add(new DateInterval('P1D')); @@ -50,6 +58,15 @@ protected function createGridSteps(): Traversable protected function createHeader(): BaseHtmlElement { $header = new HtmlElement('div', Attributes::create(['class' => 'header'])); + $dayNames = [ + 'Mon' => t('Mon', 'monday'), + 'Tue' => t('Tue', 'tuesday'), + 'Wed' => t('Wed', 'wednesday'), + 'Thu' => t('Thu', 'thursday'), + 'Fri' => t('Fri', 'friday'), + 'Sat' => t('Sat', 'saturday'), + 'Sun' => t('Sun', 'sunday') + ]; $currentDay = clone $this->getGridStart(); $interval = new DateInterval('P1D'); @@ -59,7 +76,7 @@ protected function createHeader(): BaseHtmlElement new HtmlElement( 'span', Attributes::create(['class' => 'day-name']), - Text::create($this->getGridStart()->format('D')) + Text::create($dayNames[$currentDay->format('D')]) ), new HtmlElement( 'span', diff --git a/library/Notifications/Widget/Calendar/ExtraEntryCount.php b/library/Notifications/Widget/Calendar/ExtraEntryCount.php new file mode 100644 index 00000000..cac3f92f --- /dev/null +++ b/library/Notifications/Widget/Calendar/ExtraEntryCount.php @@ -0,0 +1,72 @@ +grid = $grid; + + return $this; + } + + /** + * Set the grid step for which the extra count is being registered + * + * @param DateTime $gridStep + * + * @return $this + */ + public function setGridStep(DateTime $gridStep): self + { + $this->gridStep = clone $gridStep; + + return $this; + } + + protected function assemble() + { + $count = $this->grid->getExtraEntryCount($this->gridStep); + $this->addAttributes(['class' => 'extra-count']) + ->setBaseTarget('_self') + ->setContent( + sprintf( + $this->translatePlural( + '+%d entry', + '+%d entries', + $count + ), + $count + ) + ); + } + + public function renderUnwrapped() + { + if ($this->grid->getExtraEntryCount($this->gridStep) > 0) { + return parent::renderUnwrapped(); + } + + return ''; + } +} diff --git a/library/Notifications/Widget/Calendar/MonthGrid.php b/library/Notifications/Widget/Calendar/MonthGrid.php index e925cc1a..d53ee06b 100644 --- a/library/Notifications/Widget/Calendar/MonthGrid.php +++ b/library/Notifications/Widget/Calendar/MonthGrid.php @@ -36,6 +36,13 @@ protected function calculateGridEnd(): DateTime protected function assembleGridStep(BaseHtmlElement $content, DateTime $step): void { $content->addHtml(Text::create($step->format('j'))); + + $dayViewUrl = $this->calendar->prepareDayViewUrl($step); + $content->addHtml( + (new ExtraEntryCount(null, $dayViewUrl)) + ->setGrid($this) + ->setGridStep($step) + ); } protected function getRowStartModifier(): int diff --git a/library/Notifications/Widget/Calendar/WeekGrid.php b/library/Notifications/Widget/Calendar/WeekGrid.php index d26835b4..7e298fbf 100644 --- a/library/Notifications/Widget/Calendar/WeekGrid.php +++ b/library/Notifications/Widget/Calendar/WeekGrid.php @@ -116,6 +116,18 @@ protected function createSidebar(): BaseHtmlElement return $sidebar; } + protected function assembleGridStep(BaseHtmlElement $content, DateTime $step): void + { + if ($step->format('H') === '23') { + $dayViewUrl = $this->calendar->prepareDayViewUrl($step); + $content->addHtml( + (new ExtraEntryCount(null, $dayViewUrl)) + ->setGrid($this) + ->setGridStep($step) + ); + } + } + protected function assemble() { $this->getAttributes()->add('class', 'week'); diff --git a/library/Notifications/Widget/Schedule.php b/library/Notifications/Widget/Schedule.php index 13bbed38..abfdd3b1 100644 --- a/library/Notifications/Widget/Schedule.php +++ b/library/Notifications/Widget/Schedule.php @@ -5,6 +5,9 @@ namespace Icinga\Module\Notifications\Widget; use DateTimeZone; +use Icinga\Module\Notifications\Common\Database; +use Icinga\Module\Notifications\Model\ScheduleMember; +use Icinga\Module\Notifications\Model\TimeperiodEntry; use Icinga\Module\Notifications\Widget\Calendar\Attendee; use Icinga\Module\Notifications\Widget\Calendar\Controls; use Icinga\Module\Notifications\Widget\Calendar\Entry; @@ -44,47 +47,55 @@ protected function assembleCalendar(Calendar $calendar): void ['schedule' => $this->schedule->id] )); - $members = $this->schedule->member->with(['timeperiod', 'contact', 'contactgroup']); - foreach ($members as $member) { - if ($member->contact_id !== null) { - $attendee = new Attendee($member->contact->full_name); - $attendee->setColor($member->contact->color); - } else { // $member->contactgroup_id !== null - $attendee = new Attendee($member->contactgroup->name); - $attendee->setColor($member->contactgroup->color); - $attendee->setIcon('users'); - } + $calendar->setUrl(Url::fromPath( + 'notifications/schedules', + ['schedule' => $this->schedule->id] + )); - $entries = $member->timeperiod->entry; - - // TODO: This shouldn't be necessary. ipl/orm should be able to handle this by itself - $entries->setFilter(Filter::all(Filter::equal('timeperiod_id', $member->timeperiod->id))); - $entries->getSelectBase()->resetWhere(); - - $entryFilter = Filter::any( - Filter::all( // all entries that start in the shown range - Filter::greaterThanOrEqual('start_time', $calendar->getGrid()->getGridStart()->getTimestamp()), - Filter::lessThanOrEqual('start_time', $calendar->getGrid()->getGridEnd()->getTimestamp()) - ), - Filter::all( // all entries that end in the shown range - Filter::greaterThanOrEqual('end_time', $calendar->getGrid()->getGridStart()->getTimestamp()), - Filter::lessThanOrEqual('end_time', $calendar->getGrid()->getGridEnd()->getTimestamp()) - ), - Filter::all( // all entries that start before and end after the shown range - Filter::lessThanOrEqual('start_time', $calendar->getGrid()->getGridStart()->getTimestamp()), - Filter::greaterThanOrEqual('end_time', $calendar->getGrid()->getGridEnd()->getTimestamp()) - ), - Filter::none( // all entries that are repeated and may still occur in the shown range - Filter::lessThanOrEqual('until_time', $calendar->getGrid()->getGridStart()->getTimestamp()) - ), - Filter::all( // all entries that are repeated endlessly and already started in the past - Filter::unlike('until_time', '*'), - Filter::like('rrule', '*'), - Filter::lessThanOrEqual('start_time', $calendar->getGrid()->getGridStart()->getTimestamp()) - ) - ); + $db = Database::get(); + $entries = TimeperiodEntry::on($db) + ->filter(Filter::equal('timeperiod.schedule.id', $this->schedule->id)) + ->orderBy(['start_time', 'timeperiod_id']); + + $entryFilter = Filter::any( + Filter::all( // all entries that start in the shown range + Filter::greaterThanOrEqual('start_time', $calendar->getGrid()->getGridStart()->getTimestamp()), + Filter::lessThanOrEqual('start_time', $calendar->getGrid()->getGridEnd()->getTimestamp()) + ), + Filter::all( // all entries that end in the shown range + Filter::greaterThanOrEqual('end_time', $calendar->getGrid()->getGridStart()->getTimestamp()), + Filter::lessThanOrEqual('end_time', $calendar->getGrid()->getGridEnd()->getTimestamp()) + ), + Filter::all( // all entries that start before and end after the shown range + Filter::lessThanOrEqual('start_time', $calendar->getGrid()->getGridStart()->getTimestamp()), + Filter::greaterThanOrEqual('end_time', $calendar->getGrid()->getGridEnd()->getTimestamp()) + ), + Filter::none( // all entries that are repeated and may still occur in the shown range + Filter::lessThanOrEqual('until_time', $calendar->getGrid()->getGridStart()->getTimestamp()) + ), + Filter::all( // all entries that are repeated endlessly and already started in the past + Filter::unlike('until_time', '*'), + Filter::like('rrule', '*'), + Filter::lessThanOrEqual('start_time', $calendar->getGrid()->getGridStart()->getTimestamp()) + ) + ); + + foreach ($entries->filter($entryFilter) as $entry) { + $members = ScheduleMember::on($db) + ->with(['timeperiod', 'contact', 'contactgroup']) + ->filter(Filter::equal('timeperiod_id', $entry->timeperiod_id)) + ->orderBy(['contact_id', 'contactgroup_id']); + + foreach ($members as $member) { + if ($member->contact_id !== null) { + $attendee = new Attendee($member->contact->full_name); + $attendee->setColor($member->contact->color); + } else { // $member->contactgroup_id !== null + $attendee = new Attendee($member->contactgroup->name); + $attendee->setColor($member->contactgroup->color); + $attendee->setIcon('users'); + } - foreach ($member->timeperiod->entry->filter($entryFilter) as $entry) { $calendar->addEntry( (new Entry($entry->id)) ->setDescription($entry->description) diff --git a/public/css/calendar.less b/public/css/calendar.less index 92156a56..7867810c 100644 --- a/public/css/calendar.less +++ b/public/css/calendar.less @@ -66,11 +66,25 @@ .entry { > a { display: block; - height: 100%; overflow: hidden; + + &:first-of-type { + height: 100%; + } } } + .overlay { + position: relative; + } + + .extra-count { + z-index: 99; + position: absolute; + bottom: 1px; // 1px is the border-width of an entry, this makes it so it doesn't overlap + right: 1px; + } + .entry { overflow: hidden; @@ -138,10 +152,13 @@ .step { grid-row-end: span @rowsPerDay; grid-column-end: span @columnsPerDay; + position: relative; > a { text-align: right; - padding-right: .25em; + &:first-of-type { + padding-right: .25em; + } } } } @@ -171,6 +188,7 @@ .step { grid-column-end: span @columnsPerDay; grid-row-end: span @rowsPerHour; + position: relative; } } @@ -251,7 +269,6 @@ input[type="month"], input[type="week"] { background-color: @low-sat-blue; - width: auto; } .view-mode-switcher label { diff --git a/public/css/form.less b/public/css/form.less index d78d99e2..98f00e4c 100644 --- a/public/css/form.less +++ b/public/css/form.less @@ -15,6 +15,10 @@ border-radius: 0; border: none; } + + input[type="date"] { + width: auto; + } } .entry-form { From 68ea48928774c9bf985aa5ec4dd15d277f3e9188 Mon Sep 17 00:00:00 2001 From: raviks789 <33730024+raviks789@users.noreply.github.com> Date: Tue, 10 Oct 2023 17:05:38 +0200 Subject: [PATCH 3/3] `Calendar`: Ceil the limit for the recurrent entries For example an entry that runs over 48 hours, starts at monday at midnight and is repeated every 2 days. Requires to ceil the limit to show the last entry in the week view that goes into the next week. --- library/Notifications/Widget/Calendar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Notifications/Widget/Calendar.php b/library/Notifications/Widget/Calendar.php index 4e005ccb..07fc2c44 100644 --- a/library/Notifications/Widget/Calendar.php +++ b/library/Notifications/Widget/Calendar.php @@ -152,7 +152,7 @@ public function getEntries(): Traversable $length = $start->diff($end); $visibleHours = Util::diffHours($start, $grid->getGridEnd()); - $limit = (int) floor($visibleHours / (Util::diffHours($start, $end) ?: 0.5)); + $limit = (int) ceil($visibleHours / (Util::diffHours($start, $end) ?: 0.5)); if ($limit > $visibleHours) { $limit = $visibleHours; }