Merge pull request #3793 from nextcloud/enh/upcomming_card_optimisation
Optimise upcomming overview creation
This commit is contained in:
@@ -158,6 +158,20 @@ class Card extends RelationalEntity {
|
||||
return $calendar;
|
||||
}
|
||||
|
||||
public function getDaysUntilDue(): ?int {
|
||||
$today = new DateTime();
|
||||
$match_date = $this->getDuedate();
|
||||
if ($match_date === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$today->setTime(0, 0);
|
||||
$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';
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -39,6 +39,10 @@ class BoardSummary extends Board {
|
||||
];
|
||||
}
|
||||
|
||||
protected function getter(string $name): mixed {
|
||||
return $this->board->getter($name);
|
||||
}
|
||||
|
||||
public function __call($name, $arguments) {
|
||||
return $this->board->__call($name, $arguments);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
*/
|
||||
namespace OCA\Deck\Model;
|
||||
|
||||
use DateTime;
|
||||
use OCA\Deck\Db\Board;
|
||||
use OCA\Deck\Db\Card;
|
||||
|
||||
@@ -41,6 +40,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,30 +58,18 @@ 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;
|
||||
$diffDays = $this->getDaysUntilDue();
|
||||
if ($diffDays === null || $diffDays > 1) {
|
||||
return static::DUEDATE_FUTURE;
|
||||
}
|
||||
$match_date->setTime(0, 0);
|
||||
|
||||
$diff = $today->diff($match_date);
|
||||
$diffDays = (int) $diff->format('%R%a'); // Extract days count in interval
|
||||
|
||||
|
||||
if ($diffDays === 1) {
|
||||
return Card::DUEDATE_NEXT;
|
||||
return static::DUEDATE_NEXT;
|
||||
}
|
||||
if ($diffDays === 0) {
|
||||
return Card::DUEDATE_NOW;
|
||||
}
|
||||
if ($diffDays < 0) {
|
||||
return Card::DUEDATE_OVERDUE;
|
||||
return static::DUEDATE_NOW;
|
||||
}
|
||||
|
||||
return Card::DUEDATE_FUTURE;
|
||||
return static::DUEDATE_OVERDUE;
|
||||
}
|
||||
|
||||
private function appendBoardDetails(&$array): void {
|
||||
@@ -86,7 +81,11 @@ class CardDetails extends Card {
|
||||
$array['board'] = (new BoardSummary($this->board))->jsonSerialize();
|
||||
}
|
||||
|
||||
public function __call($name, $arguments) {
|
||||
return $this->card->__call($name, $arguments);
|
||||
protected function getter(string $name): mixed {
|
||||
return $this->card->getter($name);
|
||||
}
|
||||
|
||||
public function __call(string $methodName, array $args) {
|
||||
return $this->card->__call($methodName, $args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 ($diffDays === 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,44 +31,44 @@
|
||||
</div>
|
||||
|
||||
<div v-else-if="isValidFilter" class="overview">
|
||||
<div v-if="cardsByDueDate.overdue.length > 0" class="dashboard-column">
|
||||
<div v-if="assignedCardsDashboard.length > 0" class="dashboard-column">
|
||||
<h3>{{ t('deck', 'Overdue') }}</h3>
|
||||
<div v-for="card in cardsByDueDate.overdue" :key="card.id">
|
||||
<div v-for="card in assignedCardsDashboard.overdue" :key="card.id">
|
||||
<CardItem :id="card.id" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-column">
|
||||
<h3>{{ t('deck', 'Today') }}</h3>
|
||||
<div v-for="card in cardsByDueDate.today" :key="card.id">
|
||||
<div v-for="card in assignedCardsDashboard.today" :key="card.id">
|
||||
<CardItem :id="card.id" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-column">
|
||||
<h3>{{ t('deck', 'Tomorrow') }}</h3>
|
||||
<div v-for="card in cardsByDueDate.tomorrow" :key="card.id">
|
||||
<div v-for="card in assignedCardsDashboard.tomorrow" :key="card.id">
|
||||
<CardItem :id="card.id" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-column">
|
||||
<h3>{{ t('deck', 'Next 7 days') }}</h3>
|
||||
<div v-for="card in cardsByDueDate.nextSevenDays" :key="card.id">
|
||||
<div v-for="card in assignedCardsDashboard.nextSevenDays" :key="card.id">
|
||||
<CardItem :id="card.id" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-column">
|
||||
<h3>{{ t('deck', 'Later') }}</h3>
|
||||
<div v-for="card in cardsByDueDate.later" :key="card.id">
|
||||
<div v-for="card in assignedCardsDashboard.later" :key="card.id">
|
||||
<CardItem :id="card.id" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-column">
|
||||
<h3>{{ t('deck', 'No due') }}</h3>
|
||||
<div v-for="card in cardsByDueDate.nodue" :key="card.id">
|
||||
<div v-for="card in assignedCardsDashboard.nodue" :key="card.id">
|
||||
<CardItem :id="card.id" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -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
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,40 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="5.4.0@62db5d4f6a7ae0a20f7cc5a4952d730272fc0863">
|
||||
<files psalm-version="5.6.0@e784128902dfe01d489c4123d69918a9f3c1eac5">
|
||||
<file src="lib/Activity/Filter.php">
|
||||
<MethodSignatureMismatch occurrences="1">
|
||||
<MethodSignatureMismatch>
|
||||
<code>$types</code>
|
||||
</MethodSignatureMismatch>
|
||||
</file>
|
||||
<file src="lib/Command/UserExport.php">
|
||||
<ImplementedReturnTypeMismatch occurrences="1">
|
||||
<ImplementedReturnTypeMismatch>
|
||||
<code>void</code>
|
||||
</ImplementedReturnTypeMismatch>
|
||||
<UndefinedThisPropertyAssignment occurrences="2">
|
||||
<UndefinedThisPropertyAssignment>
|
||||
<code>$this->boardMapper</code>
|
||||
<code>$this->stackMapper</code>
|
||||
</UndefinedThisPropertyAssignment>
|
||||
<UndefinedThisPropertyFetch occurrences="2">
|
||||
<UndefinedThisPropertyFetch>
|
||||
<code>$this->boardMapper</code>
|
||||
<code>$this->stackMapper</code>
|
||||
</UndefinedThisPropertyFetch>
|
||||
</file>
|
||||
<file src="lib/Controller/BoardApiController.php">
|
||||
<TypeDoesNotContainNull occurrences="2">
|
||||
<TypeDoesNotContainNull>
|
||||
<code>$modified === null</code>
|
||||
<code>$modified === null</code>
|
||||
</TypeDoesNotContainNull>
|
||||
<UndefinedClass occurrences="1">
|
||||
<UndefinedClass>
|
||||
<code>Util</code>
|
||||
</UndefinedClass>
|
||||
<UndefinedThisPropertyAssignment occurrences="1">
|
||||
<UndefinedThisPropertyAssignment>
|
||||
<code>$this->userId</code>
|
||||
</UndefinedThisPropertyAssignment>
|
||||
<UndefinedThisPropertyFetch occurrences="1">
|
||||
<UndefinedThisPropertyFetch>
|
||||
<code>$this->userId</code>
|
||||
</UndefinedThisPropertyFetch>
|
||||
</file>
|
||||
<file src="lib/Controller/CommentsApiController.php">
|
||||
<InvalidScalarArgument occurrences="6">
|
||||
<InvalidScalarArgument>
|
||||
<code>$cardId</code>
|
||||
<code>$cardId</code>
|
||||
<code>$cardId</code>
|
||||
@@ -44,95 +44,108 @@
|
||||
</InvalidScalarArgument>
|
||||
</file>
|
||||
<file src="lib/Controller/PageController.php">
|
||||
<UndefinedClass occurrences="1">
|
||||
<UndefinedClass>
|
||||
<code>LoadSidebar</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/Controller/StackApiController.php">
|
||||
<RedundantCondition occurrences="1">
|
||||
<RedundantCondition>
|
||||
<code>$modified !== null</code>
|
||||
</RedundantCondition>
|
||||
<UndefinedClass occurrences="1">
|
||||
<UndefinedClass>
|
||||
<code>Util</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/DAV/Calendar.php">
|
||||
<UndefinedClass occurrences="1">
|
||||
<UndefinedClass>
|
||||
<code>ExternalCalendar</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/DAV/CalendarObject.php">
|
||||
<UndefinedClass occurrences="1">
|
||||
<UndefinedClass>
|
||||
<code>ICalendarObject</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/DAV/CalendarPlugin.php">
|
||||
<UndefinedClass occurrences="1">
|
||||
<UndefinedClass>
|
||||
<code>ICalendarProvider</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/DAV/DeckCalendarBackend.php">
|
||||
<UndefinedClass occurrences="1">
|
||||
<UndefinedClass>
|
||||
<code>NotFound</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/Db/Card.php">
|
||||
<UndefinedClass occurrences="2">
|
||||
<UndefinedClass>
|
||||
<code>VCalendar</code>
|
||||
<code>VCalendar</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/Db/CardMapper.php">
|
||||
<InvalidScalarArgument occurrences="1">
|
||||
<InvalidScalarArgument>
|
||||
<code>$entity->getId()</code>
|
||||
</InvalidScalarArgument>
|
||||
<UndefinedInterfaceMethod occurrences="1">
|
||||
<UndefinedInterfaceMethod>
|
||||
<code>getUserIdGroups</code>
|
||||
</UndefinedInterfaceMethod>
|
||||
</file>
|
||||
<file src="lib/Db/LabelMapper.php">
|
||||
<ParamNameMismatch occurrences="1">
|
||||
<ParamNameMismatch>
|
||||
<code>$labelId</code>
|
||||
</ParamNameMismatch>
|
||||
</file>
|
||||
<file src="lib/Db/RelationalEntity.php">
|
||||
<MethodSignatureMismatch occurrences="1">
|
||||
<code>$attribute</code>
|
||||
</MethodSignatureMismatch>
|
||||
</file>
|
||||
<file src="lib/Db/Stack.php">
|
||||
<UndefinedClass occurrences="2">
|
||||
<UndefinedClass>
|
||||
<code>VCalendar</code>
|
||||
<code>VCalendar</code>
|
||||
</UndefinedClass>
|
||||
</file>
|
||||
<file src="lib/Model/BoardSummary.php">
|
||||
<ConstructorSignatureMismatch>
|
||||
<code>public function __construct(Board $board) {</code>
|
||||
<code>public function __construct(Board $board) {</code>
|
||||
</ConstructorSignatureMismatch>
|
||||
</file>
|
||||
<file src="lib/Model/CardDetails.php">
|
||||
<ConstructorSignatureMismatch>
|
||||
<code>public function __construct(Card $card, ?Board $board = null) {</code>
|
||||
<code>public function __construct(Card $card, ?Board $board = null) {</code>
|
||||
</ConstructorSignatureMismatch>
|
||||
</file>
|
||||
<file src="lib/Service/AttachmentService.php">
|
||||
<InvalidCatch occurrences="1"/>
|
||||
<InvalidCatch>
|
||||
<code>try {
|
||||
$attachment = $this->attachmentMapper->find($attachmentId);
|
||||
} catch (IMapperException $e) {
|
||||
throw new NoPermissionException('Permission denied');
|
||||
}</code>
|
||||
</InvalidCatch>
|
||||
</file>
|
||||
<file src="lib/Service/BoardService.php">
|
||||
<TooManyArguments occurrences="2">
|
||||
<TooManyArguments>
|
||||
<code>findAll</code>
|
||||
<code>findAll</code>
|
||||
</TooManyArguments>
|
||||
</file>
|
||||
<file src="lib/Service/CirclesService.php">
|
||||
<RedundantCondition occurrences="1">
|
||||
<RedundantCondition>
|
||||
<code>$member !== null</code>
|
||||
</RedundantCondition>
|
||||
</file>
|
||||
<file src="lib/Service/FileService.php">
|
||||
<RedundantCondition occurrences="2">
|
||||
<RedundantCondition>
|
||||
<code>is_resource($content)</code>
|
||||
<code>is_resource($content)</code>
|
||||
</RedundantCondition>
|
||||
</file>
|
||||
<file src="lib/Sharing/DeckShareProvider.php">
|
||||
<InvalidReturnType occurrences="1">
|
||||
<InvalidReturnType>
|
||||
<code>getShareByToken</code>
|
||||
</InvalidReturnType>
|
||||
</file>
|
||||
<file src="lib/Sharing/Listener.php">
|
||||
<InvalidArgument occurrences="1">
|
||||
<InvalidArgument>
|
||||
<code>[self::class, 'listenPreShare']</code>
|
||||
</InvalidArgument>
|
||||
</file>
|
||||
|
||||
Reference in New Issue
Block a user