Merge pull request #4033 from nextcloud/enh/4032/implement-new-dashboard-widget-interfaces

This commit is contained in:
Julius Härtl
2022-09-21 18:40:31 +02:00
committed by GitHub
2 changed files with 110 additions and 13 deletions

View File

@@ -26,18 +26,34 @@ declare(strict_types=1);
namespace OCA\Deck\Dashboard; namespace OCA\Deck\Dashboard;
use OCP\Dashboard\IWidget; use DateTime;
use OCA\Deck\AppInfo\Application;
use OCA\Deck\Db\Label;
use OCA\Deck\Service\OverviewService;
use OCP\Dashboard\IAPIWidget;
use OCP\Dashboard\IButtonWidget;
use OCP\Dashboard\IIconWidget;
use OCP\Dashboard\Model\WidgetButton;
use OCP\Dashboard\Model\WidgetItem;
use OCP\IDateTimeFormatter;
use OCP\IL10N; use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\Util;
class DeckWidget implements IWidget { class DeckWidget implements IAPIWidget, IButtonWidget, IIconWidget {
private IL10N $l10n;
private OverviewService $dashboardService;
private IURLGenerator $urlGenerator;
private IDateTimeFormatter $dateTimeFormatter;
/** public function __construct(IL10N $l10n,
* @var IL10N OverviewService $dashboardService,
*/ IDateTimeFormatter $dateTimeFormatter,
private $l10n; IURLGenerator $urlGenerator) {
public function __construct(IL10N $l10n) {
$this->l10n = $l10n; $this->l10n = $l10n;
$this->dashboardService = $dashboardService;
$this->urlGenerator = $urlGenerator;
$this->dateTimeFormatter = $dateTimeFormatter;
} }
/** /**
@@ -68,17 +84,88 @@ class DeckWidget implements IWidget {
return 'icon-deck'; return 'icon-deck';
} }
/**
* @inheritDoc
*/
public function getIconUrl(): string {
return $this->urlGenerator->getAbsoluteURL(
$this->urlGenerator->imagePath(Application::APP_ID, 'deck-dark.svg')
);
}
/** /**
* @inheritDoc * @inheritDoc
*/ */
public function getUrl(): ?string { public function getUrl(): ?string {
return null; return $this->urlGenerator->getAbsoluteURL(
$this->urlGenerator->linkToRoute(Application::APP_ID . '.page.index')
);
} }
/** /**
* @inheritDoc * @inheritDoc
*/ */
public function load(): void { public function load(): void {
\OCP\Util::addScript('deck', 'deck-dashboard'); Util::addScript('deck', 'deck-dashboard');
}
/**
* @inheritDoc
*/
public function getItems(string $userId, ?string $since = null, int $limit = 7): array {
$upcomingCards = $this->dashboardService->findUpcomingCards($userId);
$nowTimestamp = (new Datetime())->getTimestamp();
$sinceTimestamp = $since !== null ? (new Datetime($since))->getTimestamp() : null;
$upcomingCards = array_filter($upcomingCards, static function (array $card) use ($nowTimestamp, $sinceTimestamp) {
if ($card['duedate']) {
$ts = (new Datetime($card['duedate']))->getTimestamp();
return $ts > $nowTimestamp && ($sinceTimestamp === null || $ts > $sinceTimestamp);
}
return false;
});
usort($upcomingCards, static function ($a, $b) {
$a = new Datetime($a['duedate']);
$ta = $a->getTimestamp();
$b = new Datetime($b['duedate']);
$tb = $b->getTimestamp();
return ($ta > $tb) ? 1 : -1;
});
$upcomingCards = array_slice($upcomingCards, 0, $limit);
$urlGenerator = $this->urlGenerator;
$dateTimeFormatter = $this->dateTimeFormatter;
return array_map(static function (array $card) use ($urlGenerator, $dateTimeFormatter) {
$formattedDueDate = $dateTimeFormatter->formatDateTime(new DateTime($card['duedate']));
return new WidgetItem(
$card['title'] . ' (' . $formattedDueDate . ')',
implode(
', ',
array_map(static function (Label $label) {
return $label->jsonSerialize()['title'];
}, $card['labels'])
),
$urlGenerator->getAbsoluteURL(
$urlGenerator->linkToRoute(Application::APP_ID . '.page.redirectToCard', ['cardId' => $card['id']])
),
$urlGenerator->getAbsoluteURL(
$urlGenerator->imagePath(Application::APP_ID, 'deck-dark.svg')
),
$card['duedate']
);
}, $upcomingCards);
}
/**
* @inheritDoc
*/
public function getWidgetButtons(string $userId): array {
return [
new WidgetButton(
WidgetButton::TYPE_MORE,
$this->urlGenerator->getAbsoluteURL(
$this->urlGenerator->linkToRoute(Application::APP_ID . '.page.index')
),
$this->l10n->t('Load more')
),
];
} }
} }

View File

@@ -48,21 +48,26 @@
</template> </template>
</NcDashboardWidget> </NcDashboardWidget>
<div class="center-button"> <div class="center-button">
<button @click="toggleAddCardModel"> <NcButton @click="toggleAddCardModel">
<template #icon>
<PlusIcon :size="20" />
</template>
{{ t('deck', 'Add card') }} {{ t('deck', 'Add card') }}
</button> </NcButton>
<CardCreateDialog v-if="showAddCardModal" @close="toggleAddCardModel" /> <CardCreateDialog v-if="showAddCardModal" @close="toggleAddCardModel" />
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import PlusIcon from 'vue-material-design-icons/Plus.vue'
import { NcDashboardWidget } from '@nextcloud/vue' import { NcDashboardWidget } from '@nextcloud/vue'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import labelStyle from './../mixins/labelStyle.js' import labelStyle from './../mixins/labelStyle.js'
import DueDate from '../components/cards/badges/DueDate.vue' import DueDate from '../components/cards/badges/DueDate.vue'
import { generateUrl } from '@nextcloud/router' import { generateUrl } from '@nextcloud/router'
import CardCreateDialog from '../CardCreateDialog.vue' import CardCreateDialog from '../CardCreateDialog.vue'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
export default { export default {
name: 'Dashboard', name: 'Dashboard',
@@ -70,6 +75,8 @@ export default {
DueDate, DueDate,
NcDashboardWidget, NcDashboardWidget,
CardCreateDialog, CardCreateDialog,
NcButton,
PlusIcon,
}, },
mixins: [labelStyle], mixins: [labelStyle],
data() { data() {
@@ -120,7 +127,10 @@ export default {
@import './../css/labels'; @import './../css/labels';
.center-button { .center-button {
text-align: center; display: flex;
align-items: center;
justify-content: center;
margin-top: 8px;
} }
#deck-widget-empty-content { #deck-widget-empty-content {