From 4c729530ce9ab6c1415ddea401aac1198b731572 Mon Sep 17 00:00:00 2001 From: Raul Date: Mon, 2 May 2022 16:58:43 +0200 Subject: [PATCH 1/9] Add CardDetails model Signed-off-by: Raul --- lib/Model/CardDetails.php | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/lib/Model/CardDetails.php b/lib/Model/CardDetails.php index 58523ab14..8f80e5866 100644 --- a/lib/Model/CardDetails.php +++ b/lib/Model/CardDetails.php @@ -22,11 +22,11 @@ */ namespace OCA\Deck\Model; -use DateTime; use OCA\Deck\Db\Board; use OCA\Deck\Db\Card; -class CardDetails extends Card { +class CardDetails extends Card +{ private Card $card; private ?Board $board; @@ -41,6 +41,14 @@ class CardDetails extends Card { } public function jsonSerialize(array $extras = []): array { + $array = parent::jsonSerialize(); + $array['overdue'] = $this->getDueStatus(); + + unset($array['notified']); + unset($array['descriptionPrev']); + unset($array['relatedStack']); + unset($array['relatedBoard']); + $array = $this->card->jsonSerialize(); unset($array['notified'], $array['descriptionPrev'], $array['relatedStack'], $array['relatedBoard']); @@ -51,31 +59,19 @@ class CardDetails extends Card { } private function getDueStatus(): int { - $today = new DateTime(); - $today->setTime(0, 0); - - $match_date = $this->card->getDuedate(); - if (!$match_date) { - return Card::DUEDATE_FUTURE; - } - $match_date->setTime(0, 0); - - $diff = $today->diff($match_date); - $diffDays = (int) $diff->format('%R%a'); // Extract days count in interval - - + $diffDays = $this->getDaysUntilDue(); if ($diffDays === 1) { - return Card::DUEDATE_NEXT; + return static::DUEDATE_NEXT; } if ($diffDays === 0) { - return Card::DUEDATE_NOW; + return static::DUEDATE_NOW; } if ($diffDays < 0) { - return Card::DUEDATE_OVERDUE; + return static::DUEDATE_OVERDUE; } - return Card::DUEDATE_FUTURE; - } + return static::DUEDATE_FUTURE; + } private function appendBoardDetails(&$array): void { if (!$this->board) { @@ -86,6 +82,9 @@ class CardDetails extends Card { $array['board'] = (new BoardSummary($this->board))->jsonSerialize(); } + protected function getter($name) { + return $this->card->getter($name); + } public function __call($name, $arguments) { return $this->card->__call($name, $arguments); } From 6ae61368a7a686e85ebb7df44237fd62587c1ced Mon Sep 17 00:00:00 2001 From: Raul Date: Tue, 3 May 2022 12:59:58 +0200 Subject: [PATCH 2/9] Update Card serialization (`jsonSerialize` usages) to use CardDetails model Signed-off-by: Raul --- lib/Service/OverviewService.php | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/Service/OverviewService.php b/lib/Service/OverviewService.php index 0d883141c..f45f22f33 100644 --- a/lib/Service/OverviewService.php +++ b/lib/Service/OverviewService.php @@ -93,7 +93,7 @@ class OverviewService { public function findUpcomingCards(string $userId): array { $userBoards = $this->boardMapper->findAllForUser($userId); - $foundCards = []; + $overview = []; foreach ($userBoards as $userBoard) { if (count($userBoard->getAcl()) === 0) { // private board: get cards with due date @@ -103,14 +103,27 @@ class OverviewService { $cards = $this->cardMapper->findToMeOrNotAssignedCards($userBoard->getId(), $userId); } - $foundCards[] = array_map( - function (Card $card) use ($userBoard, $userId) { - $this->enrich($card, $userId); - return (new CardDetails($card, $userBoard))->jsonSerialize(); - }, - $cards - ); + foreach ($cards as $card) { + $this->enrich($card, $userId); + $diffDays = $card->getDaysUntilDue(); + + $key = 'later'; + if ($card->getDuedate() === null) { + $key = 'nodue'; + } elseif ($diffDays < 0) { + $key = 'overdue'; + } elseif ($diffDays === 0) { + $key = 'today'; + } elseif ($diffDays === 1) { + $key = 'tomorrow'; + } elseif ($diffDays <= 7) { + $key = 'nextSevenDays'; + } + + $card = (new CardDetails($card, $userBoard)); + $overview[$key][] = $card->jsonSerialize(); + } } - return array_merge(...$foundCards); + return $overview; } } From 3a730cf38f1f4bb427bbb98deb37d63a2826a60d Mon Sep 17 00:00:00 2001 From: Raul Date: Tue, 3 May 2022 13:00:51 +0200 Subject: [PATCH 3/9] Add phpDoc typehints for magic methods Signed-off-by: Raul --- lib/Db/Card.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/Db/Card.php b/lib/Db/Card.php index ed710d716..b866fd3e3 100644 --- a/lib/Db/Card.php +++ b/lib/Db/Card.php @@ -158,6 +158,17 @@ class Card extends RelationalEntity { return $calendar; } + public function getDaysUntilDue(): int { + $today = new DateTime(); + $today->setTime(0, 0); + + $match_date = $this->getDueDateTime() ?? new DateTime(); + $match_date->setTime(0, 0); + + $diff = $today->diff($match_date); + return (int) $diff->format('%R%a'); // Extract days count in interval + } + public function getCalendarPrefix(): string { return 'card'; } From 4388d898ae637540e44f56920b7f4abf21fb37ed Mon Sep 17 00:00:00 2001 From: Raul Date: Wed, 4 May 2022 12:40:51 +0200 Subject: [PATCH 4/9] Include board summary in card details Signed-off-by: Raul --- lib/Db/Card.php | 2 +- lib/Model/BoardSummary.php | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/Db/Card.php b/lib/Db/Card.php index b866fd3e3..c150eb796 100644 --- a/lib/Db/Card.php +++ b/lib/Db/Card.php @@ -92,7 +92,7 @@ class Card extends RelationalEntity { protected $relatedStack = null; protected $relatedBoard = null; - private $databaseType = 'sqlite'; + protected $databaseType = 'sqlite'; public const DUEDATE_FUTURE = 0; public const DUEDATE_NEXT = 1; diff --git a/lib/Model/BoardSummary.php b/lib/Model/BoardSummary.php index 4c363ff3e..2fa827a3b 100644 --- a/lib/Model/BoardSummary.php +++ b/lib/Model/BoardSummary.php @@ -24,7 +24,8 @@ namespace OCA\Deck\Model; use OCA\Deck\Db\Board; -class BoardSummary extends Board { +class BoardSummary extends Board +{ private Board $board; public function __construct(Board $board) { @@ -39,6 +40,10 @@ class BoardSummary extends Board { ]; } + protected function getter($name) { + return $this->board->getter($name); + } + public function __call($name, $arguments) { return $this->board->__call($name, $arguments); } From 308bf80de0345a3d0d6f5a9dc2e5dd3a133a1559 Mon Sep 17 00:00:00 2001 From: Raul Date: Wed, 4 May 2022 15:33:44 +0200 Subject: [PATCH 5/9] Add `Card::getDaysUntilDue()` function Signed-off-by: Raul --- lib/Db/Card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Db/Card.php b/lib/Db/Card.php index c150eb796..b866fd3e3 100644 --- a/lib/Db/Card.php +++ b/lib/Db/Card.php @@ -92,7 +92,7 @@ class Card extends RelationalEntity { protected $relatedStack = null; protected $relatedBoard = null; - protected $databaseType = 'sqlite'; + private $databaseType = 'sqlite'; public const DUEDATE_FUTURE = 0; public const DUEDATE_NEXT = 1; From 99f5e8b76e8cca93079aac990fb9d3273fbda304 Mon Sep 17 00:00:00 2001 From: Raul Date: Wed, 4 May 2022 15:34:54 +0200 Subject: [PATCH 6/9] Use presorted cards on front-end view Signed-off-by: Raul --- src/components/overview/Overview.vue | 63 ++++------------------------ src/store/overview.js | 12 +++--- 2 files changed, 14 insertions(+), 61 deletions(-) diff --git a/src/components/overview/Overview.vue b/src/components/overview/Overview.vue index a7dedef39..ad325d595 100644 --- a/src/components/overview/Overview.vue +++ b/src/components/overview/Overview.vue @@ -31,44 +31,44 @@
-
+

{{ t('deck', 'Overdue') }}

-
+

{{ t('deck', 'Today') }}

-
+

{{ t('deck', 'Tomorrow') }}

-
+

{{ t('deck', 'Next 7 days') }}

-
+

{{ t('deck', 'Later') }}

-
+

{{ t('deck', 'No due') }}

-
+
@@ -83,7 +83,6 @@ import Controls from '../Controls.vue' import CardItem from '../cards/CardItem.vue' import { mapGetters } from 'vuex' -import moment from '@nextcloud/moment' import GlobalSearchResults from '../search/GlobalSearchResults.vue' const FILTER_UPCOMING = 'upcoming' @@ -125,13 +124,6 @@ export default { ...mapGetters([ 'assignedCardsDashboard', ]), - cardsByDueDate() { - switch (this.filter) { - case FILTER_UPCOMING: - return this.groupByDue(this.assignedCardsDashboard) - } - return null - }, }, watch: { '$route.params.filter'() { @@ -153,47 +145,6 @@ export default { } this.loading = false }, - - groupByDue(dataset) { - const all = { - nodue: [], - overdue: [], - today: [], - tomorrow: [], - nextSevenDays: [], - later: [], - } - dataset.forEach(card => { - if (card.duedate === null) { - all.nodue.push(card) - } else { - const hours = Math.floor(moment(card.duedate).diff(this.$root.time, 'seconds') / 60 / 60) - const d = new Date() - const currentHour = d.getHours() - if (hours < 0) { - all.overdue.push(card) - } - if (hours >= 0 && hours < (24 - currentHour)) { - all.today.push(card) - } - if (hours >= (24 - currentHour) && hours < (48 - currentHour)) { - all.tomorrow.push(card) - } - if (hours >= (48 - currentHour) && hours < (24 * 7)) { - all.nextSevenDays.push(card) - } - if (hours >= (24 * 7)) { - all.later.push(card) - } - } - }) - Object.keys(all).forEach((list) => { - all[list] = all[list].sort((a, b) => { - return (new Date(a.duedate)).getTime() - (new Date(b.duedate)).getTime() - }) - }) - return all - }, }, } diff --git a/src/store/overview.js b/src/store/overview.js index e6eeb3c02..d06095308 100644 --- a/src/store/overview.js +++ b/src/store/overview.js @@ -43,12 +43,14 @@ export default { actions: { async loadUpcoming({ commit }) { commit('setCurrentBoard', null) - const assignedCards = await apiClient.get('upcoming') - const assignedCardsFlat = assignedCards.flat() - for (const i in assignedCardsFlat) { - commit('addCard', assignedCardsFlat[i]) + const upcommingCards = await apiClient.get('upcoming') + + for (const dueStatus in upcommingCards) { + for (const idx in upcommingCards[dueStatus]) { + commit('addCard', upcommingCards[dueStatus][idx]) + } } - commit('setAssignedCards', assignedCardsFlat) + commit('setAssignedCards', upcommingCards) }, }, } From 7575bd0bf75761e408ee191094b4a9014727dc38 Mon Sep 17 00:00:00 2001 From: Raul Date: Mon, 9 May 2022 14:44:36 +0200 Subject: [PATCH 7/9] Fix due status calculation Signed-off-by: Raul --- lib/Db/Card.php | 9 ++++++--- lib/Model/BoardSummary.php | 5 ++--- lib/Model/CardDetails.php | 17 ++++++++--------- lib/Service/OverviewService.php | 2 +- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/lib/Db/Card.php b/lib/Db/Card.php index b866fd3e3..5a80ed35a 100644 --- a/lib/Db/Card.php +++ b/lib/Db/Card.php @@ -158,11 +158,14 @@ class Card extends RelationalEntity { return $calendar; } - public function getDaysUntilDue(): int { + public function getDaysUntilDue(): ?int { $today = new DateTime(); - $today->setTime(0, 0); + $match_date = $this->getDuedate(); + if ($match_date === null) { + return null; + } - $match_date = $this->getDueDateTime() ?? new DateTime(); + $today->setTime(0, 0); $match_date->setTime(0, 0); $diff = $today->diff($match_date); diff --git a/lib/Model/BoardSummary.php b/lib/Model/BoardSummary.php index 2fa827a3b..365a454c0 100644 --- a/lib/Model/BoardSummary.php +++ b/lib/Model/BoardSummary.php @@ -24,8 +24,7 @@ namespace OCA\Deck\Model; use OCA\Deck\Db\Board; -class BoardSummary extends Board -{ +class BoardSummary extends Board { private Board $board; public function __construct(Board $board) { @@ -42,7 +41,7 @@ class BoardSummary extends Board protected function getter($name) { return $this->board->getter($name); - } + } public function __call($name, $arguments) { return $this->board->__call($name, $arguments); diff --git a/lib/Model/CardDetails.php b/lib/Model/CardDetails.php index 8f80e5866..d894c274e 100644 --- a/lib/Model/CardDetails.php +++ b/lib/Model/CardDetails.php @@ -25,8 +25,7 @@ namespace OCA\Deck\Model; use OCA\Deck\Db\Board; use OCA\Deck\Db\Card; -class CardDetails extends Card -{ +class CardDetails extends Card { private Card $card; private ?Board $board; @@ -60,18 +59,18 @@ class CardDetails extends Card private function getDueStatus(): int { $diffDays = $this->getDaysUntilDue(); + if ($diffDays === null || $diffDays > 1) { + return static::DUEDATE_FUTURE; + } if ($diffDays === 1) { return static::DUEDATE_NEXT; } if ($diffDays === 0) { return static::DUEDATE_NOW; } - if ($diffDays < 0) { - return static::DUEDATE_OVERDUE; - } - return static::DUEDATE_FUTURE; - } + return static::DUEDATE_OVERDUE; + } private function appendBoardDetails(&$array): void { if (!$this->board) { @@ -83,8 +82,8 @@ class CardDetails extends Card } protected function getter($name) { - return $this->card->getter($name); - } + return $this->card->getter($name); + } public function __call($name, $arguments) { return $this->card->__call($name, $arguments); } diff --git a/lib/Service/OverviewService.php b/lib/Service/OverviewService.php index f45f22f33..8b8b07511 100644 --- a/lib/Service/OverviewService.php +++ b/lib/Service/OverviewService.php @@ -108,7 +108,7 @@ class OverviewService { $diffDays = $card->getDaysUntilDue(); $key = 'later'; - if ($card->getDuedate() === null) { + if ($diffDays === null) { $key = 'nodue'; } elseif ($diffDays < 0) { $key = 'overdue'; From 997e479a69f8955018325067dbc058bbbd612b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Wed, 15 Feb 2023 13:19:12 +0100 Subject: [PATCH 8/9] fix: Review feedback on vue tempalte MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- src/components/overview/Overview.vue | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/overview/Overview.vue b/src/components/overview/Overview.vue index ad325d595..4f1b0a6a5 100644 --- a/src/components/overview/Overview.vue +++ b/src/components/overview/Overview.vue @@ -31,44 +31,44 @@
-
+

{{ t('deck', 'Overdue') }}

-
+

{{ t('deck', 'Today') }}

-
+

{{ t('deck', 'Tomorrow') }}

-
+

{{ t('deck', 'Next 7 days') }}

-
+

{{ t('deck', 'Later') }}

-
+

{{ t('deck', 'No due') }}

-
+
From 2ffecd81d4f6912127a043dd623abf1918024e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Wed, 15 Feb 2023 13:29:26 +0100 Subject: [PATCH 9/9] chore: Fix typings and update psalm baseline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- lib/Db/RelationalEntity.php | 2 +- lib/Model/BoardSummary.php | 2 +- lib/Model/CardDetails.php | 7 ++-- tests/psalm-baseline.xml | 79 +++++++++++++++++++++---------------- 4 files changed, 52 insertions(+), 38 deletions(-) diff --git a/lib/Db/RelationalEntity.php b/lib/Db/RelationalEntity.php index b4683b05b..683f1611f 100644 --- a/lib/Db/RelationalEntity.php +++ b/lib/Db/RelationalEntity.php @@ -127,7 +127,7 @@ class RelationalEntity extends Entity implements \JsonSerializable { } } - public function __call($methodName, $args) { + public function __call(string $methodName, array $args) { $attr = lcfirst(substr($methodName, 7)); if (array_key_exists($attr, $this->_resolvedProperties) && strpos($methodName, 'resolve') === 0) { if ($this->_resolvedProperties[$attr] !== null) { diff --git a/lib/Model/BoardSummary.php b/lib/Model/BoardSummary.php index 365a454c0..7924222ba 100644 --- a/lib/Model/BoardSummary.php +++ b/lib/Model/BoardSummary.php @@ -39,7 +39,7 @@ class BoardSummary extends Board { ]; } - protected function getter($name) { + protected function getter(string $name): mixed { return $this->board->getter($name); } diff --git a/lib/Model/CardDetails.php b/lib/Model/CardDetails.php index d894c274e..ca39b9211 100644 --- a/lib/Model/CardDetails.php +++ b/lib/Model/CardDetails.php @@ -81,10 +81,11 @@ class CardDetails extends Card { $array['board'] = (new BoardSummary($this->board))->jsonSerialize(); } - protected function getter($name) { + protected function getter(string $name): mixed { return $this->card->getter($name); } - public function __call($name, $arguments) { - return $this->card->__call($name, $arguments); + + public function __call(string $methodName, array $args) { + return $this->card->__call($methodName, $args); } } diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml index 2eb5d9228..1fed3db61 100644 --- a/tests/psalm-baseline.xml +++ b/tests/psalm-baseline.xml @@ -1,40 +1,40 @@ - + - + $types - + void - + $this->boardMapper $this->stackMapper - + $this->boardMapper $this->stackMapper - + $modified === null $modified === null - + Util - + $this->userId - + $this->userId - + $cardId $cardId $cardId @@ -44,95 +44,108 @@ - + LoadSidebar - + $modified !== null - + Util - + ExternalCalendar - + ICalendarObject - + ICalendarProvider - + NotFound - + VCalendar VCalendar - + $entity->getId() - + getUserIdGroups - + $labelId - - - $attribute - - - + VCalendar VCalendar + + + public function __construct(Board $board) { + public function __construct(Board $board) { + + + + + public function __construct(Card $card, ?Board $board = null) { + public function __construct(Card $card, ?Board $board = null) { + + - + + try { + $attachment = $this->attachmentMapper->find($attachmentId); + } catch (IMapperException $e) { + throw new NoPermissionException('Permission denied'); + } + - + findAll findAll - + $member !== null - + is_resource($content) is_resource($content) - + getShareByToken - + [self::class, 'listenPreShare']