diff --git a/composer.lock b/composer.lock index c9efe9538..598fbfe99 100644 --- a/composer.lock +++ b/composer.lock @@ -1257,12 +1257,12 @@ "source": { "type": "git", "url": "https://github.com/nextcloud-deps/ocp.git", - "reference": "1aaead8ad471e72441257d41fb15eb55ea174d00" + "reference": "5636b942e35ee391b1103150261d83d3d753d657" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/1aaead8ad471e72441257d41fb15eb55ea174d00", - "reference": "1aaead8ad471e72441257d41fb15eb55ea174d00", + "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/5636b942e35ee391b1103150261d83d3d753d657", + "reference": "5636b942e35ee391b1103150261d83d3d753d657", "shasum": "" }, "require": { @@ -1294,7 +1294,7 @@ "issues": "https://github.com/nextcloud-deps/ocp/issues", "source": "https://github.com/nextcloud-deps/ocp/tree/master" }, - "time": "2023-01-11T00:37:34+00:00" + "time": "2023-02-08T00:37:37+00:00" }, { "name": "nikic/php-parser", @@ -5477,5 +5477,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.2.0" } diff --git a/img/card.svg b/img/card.svg new file mode 100644 index 000000000..38366bb8c --- /dev/null +++ b/img/card.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 0bccdd332..1363cb299 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -50,7 +50,9 @@ use OCA\Deck\Listeners\LiveUpdateListener; use OCA\Deck\Middleware\DefaultBoardMiddleware; use OCA\Deck\Middleware\ExceptionMiddleware; use OCA\Deck\Notification\Notifier; +use OCA\Deck\Reference\BoardReferenceProvider; use OCA\Deck\Reference\CardReferenceProvider; +use OCA\Deck\Reference\CommentReferenceProvider; use OCA\Deck\Search\CardCommentProvider; use OCA\Deck\Search\DeckProvider; use OCA\Deck\Service\PermissionService; @@ -88,7 +90,7 @@ class Application extends App implements IBootstrap { $container = $this->getContainer(); $eventDispatcher = $container->get(IEventDispatcher::class); $eventDispatcher->addListener(RenderReferenceEvent::class, function () { - Util::addScript(self::APP_ID, self::APP_ID . '-card-reference'); + Util::addScript(self::APP_ID, self::APP_ID . '-reference'); }); } @@ -128,7 +130,8 @@ class Application extends App implements IBootstrap { // reference widget $context->registerReferenceProvider(CardReferenceProvider::class); - // $context->registerEventListener(RenderReferenceEvent::class, CardReferenceListener::class); + $context->registerReferenceProvider(BoardReferenceProvider::class); + $context->registerReferenceProvider(CommentReferenceProvider::class); $context->registerEventListener(BeforeTemplateRenderedEvent::class, BeforeTemplateRenderedListener::class); diff --git a/lib/Reference/BoardReferenceProvider.php b/lib/Reference/BoardReferenceProvider.php new file mode 100644 index 000000000..f0f9abbfb --- /dev/null +++ b/lib/Reference/BoardReferenceProvider.php @@ -0,0 +1,128 @@ + + * + * @author Julien Veyssier + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace OCA\Deck\Reference; + +use OCA\Deck\AppInfo\Application; +use OCA\Deck\Service\BoardService; +use OCP\Collaboration\Reference\IReference; +use OCP\Collaboration\Reference\IReferenceProvider; +use OCP\Collaboration\Reference\Reference; +use OCP\IL10N; +use OCP\IURLGenerator; + +class BoardReferenceProvider implements IReferenceProvider { + private IURLGenerator $urlGenerator; + private BoardService $boardService; + private ?string $userId; + private IL10N $l10n; + + public function __construct(BoardService $boardService, + IURLGenerator $urlGenerator, + IL10N $l10n, + ?string $userId) { + $this->urlGenerator = $urlGenerator; + $this->boardService = $boardService; + $this->userId = $userId; + $this->l10n = $l10n; + } + + /** + * @inheritDoc + */ + public function matchReference(string $referenceText): bool { + $start = $this->urlGenerator->getAbsoluteURL('/apps/' . Application::APP_ID); + $startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/' . Application::APP_ID); + + // link example: https://nextcloud.local/index.php/apps/deck/#/board/2 + $noIndexMatch = preg_match('/^' . preg_quote($start, '/') . '\/#\/board\/[0-9]+$/', $referenceText) === 1; + $indexMatch = preg_match('/^' . preg_quote($startIndex, '/') . '\/#\/board\/[0-9]+$/', $referenceText) === 1; + + return $noIndexMatch || $indexMatch; + } + + /** + * @inheritDoc + */ + public function resolveReference(string $referenceText): ?IReference { + if ($this->matchReference($referenceText)) { + $boardId = $this->getBoardId($referenceText); + if ($boardId !== null) { + $board = $this->boardService->find($boardId)->jsonSerialize(); + $board = $this->sanitizeSerializedBoard($board); + /** @var IReference $reference */ + $reference = new Reference($referenceText); + $reference->setTitle($this->l10n->t('Deck board') . ': ' . $board['title']); + $ownerDisplayName = $board['owner']['displayname'] ?? $board['owner']['uid'] ?? '???'; + $reference->setDescription($this->l10n->t('Owned by %1$s', [$ownerDisplayName])); + $imageUrl = $this->urlGenerator->getAbsoluteURL( + $this->urlGenerator->imagePath(Application::APP_ID, 'deck-dark.svg') + ); + $reference->setImageUrl($imageUrl); + $reference->setRichObject(Application::APP_ID . '-board', [ + 'id' => $boardId, + 'board' => $board, + ]); + return $reference; + } + } + + return null; + } + + private function sanitizeSerializedBoard(array $board): array { + unset($board['labels']); + $board['owner'] = $board['owner']->jsonSerialize(); + unset($board['acl']); + unset($board['users']); + + return $board; + } + + private function getBoardId(string $url): ?int { + $start = $this->urlGenerator->getAbsoluteURL('/apps/' . Application::APP_ID); + $startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/' . Application::APP_ID); + + preg_match('/^' . preg_quote($start, '/') . '\/#\/board\/([0-9]+)$/', $url, $matches); + if (!$matches) { + preg_match('/^' . preg_quote($startIndex, '/') . '\/#\/board\/([0-9]+)$/', $url, $matches); + } + if ($matches && count($matches) > 1) { + return (int) $matches[1]; + } + + return null; + } + + public function getCachePrefix(string $referenceId): string { + $boardId = $this->getBoardId($referenceId); + if ($boardId !== null) { + return (string) $boardId; + } + + return $referenceId; + } + + public function getCacheKey(string $referenceId): ?string { + return $this->userId ?? ''; + } +} diff --git a/lib/Reference/CardReferenceProvider.php b/lib/Reference/CardReferenceProvider.php index 37c2e8868..f0bea2cc0 100644 --- a/lib/Reference/CardReferenceProvider.php +++ b/lib/Reference/CardReferenceProvider.php @@ -30,28 +30,73 @@ use OCA\Deck\Model\CardDetails; use OCA\Deck\Service\BoardService; use OCA\Deck\Service\CardService; use OCA\Deck\Service\StackService; +use OCP\Collaboration\Reference\ADiscoverableReferenceProvider; use OCP\Collaboration\Reference\IReference; -use OCP\Collaboration\Reference\IReferenceProvider; +use OCP\Collaboration\Reference\ISearchableReferenceProvider; use OCP\Collaboration\Reference\Reference; +use OCP\IL10N; use OCP\IURLGenerator; -class CardReferenceProvider implements IReferenceProvider { +class CardReferenceProvider extends ADiscoverableReferenceProvider implements ISearchableReferenceProvider { private CardService $cardService; private IURLGenerator $urlGenerator; private BoardService $boardService; private StackService $stackService; private ?string $userId; + private IL10N $l10n; public function __construct(CardService $cardService, BoardService $boardService, StackService $stackService, IURLGenerator $urlGenerator, + IL10N $l10n, ?string $userId) { $this->cardService = $cardService; $this->urlGenerator = $urlGenerator; $this->boardService = $boardService; $this->stackService = $stackService; $this->userId = $userId; + $this->l10n = $l10n; + } + + /** + * @inheritDoc + */ + public function getId(): string { + return Application::APP_ID . '-ref-cards'; + } + + /** + * @inheritDoc + */ + public function getTitle(): string { + return $this->l10n->t('Deck boards, cards and comments'); + } + + /** + * @inheritDoc + */ + public function getOrder(): int { + return 10; + } + + /** + * @inheritDoc + */ + public function getIconUrl(): string { + return $this->urlGenerator->getAbsoluteURL( + $this->urlGenerator->imagePath(Application::APP_ID, 'deck-dark.svg') + ); + } + + /** + * @inheritDoc + */ + public function getSupportedSearchProviderIds(): array { + return [ + 'search-deck-card-board', + 'search-deck-comment', + ]; } /** diff --git a/lib/Reference/CommentReferenceProvider.php b/lib/Reference/CommentReferenceProvider.php new file mode 100644 index 000000000..e31323c2e --- /dev/null +++ b/lib/Reference/CommentReferenceProvider.php @@ -0,0 +1,191 @@ + + * + * @author Julien Veyssier + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace OCA\Deck\Reference; + +use OCA\Deck\AppInfo\Application; +use OCA\Deck\Db\Assignment; +use OCA\Deck\Db\Attachment; +use OCA\Deck\Db\Label; +use OCA\Deck\Model\CardDetails; +use OCA\Deck\Service\BoardService; +use OCA\Deck\Service\CardService; +use OCA\Deck\Service\CommentService; +use OCA\Deck\Service\StackService; +use OCP\Collaboration\Reference\IReference; +use OCP\Collaboration\Reference\IReferenceProvider; +use OCP\Collaboration\Reference\Reference; +use OCP\IL10N; +use OCP\IURLGenerator; + +class CommentReferenceProvider implements IReferenceProvider { + private CardService $cardService; + private IURLGenerator $urlGenerator; + private BoardService $boardService; + private StackService $stackService; + private ?string $userId; + private IL10N $l10n; + private CommentService $commentService; + + public function __construct(CardService $cardService, + BoardService $boardService, + StackService $stackService, + CommentService $commentService, + IURLGenerator $urlGenerator, + IL10N $l10n, + ?string $userId) { + $this->cardService = $cardService; + $this->urlGenerator = $urlGenerator; + $this->boardService = $boardService; + $this->stackService = $stackService; + $this->userId = $userId; + $this->l10n = $l10n; + $this->commentService = $commentService; + } + + /** + * @inheritDoc + */ + public function matchReference(string $referenceText): bool { + $start = $this->urlGenerator->getAbsoluteURL('/apps/' . Application::APP_ID); + $startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/' . Application::APP_ID); + + // link example: https://nextcloud.local/index.php/apps/deck/#/board/2/card/11/comments/501 + $noIndexMatch = preg_match('/^' . preg_quote($start, '/') . '\/#\/board\/[0-9]+\/card\/[0-9]+\/comments\/\d+$/', $referenceText) === 1; + $indexMatch = preg_match('/^' . preg_quote($startIndex, '/') . '\/#\/board\/[0-9]+\/card\/[0-9]+\/comments\/\d+$/', $referenceText) === 1; + + return $noIndexMatch || $indexMatch; + } + + /** + * @inheritDoc + */ + public function resolveReference(string $referenceText): ?IReference { + if ($this->matchReference($referenceText)) { + $ids = $this->getIds($referenceText); + if ($ids !== null) { + [$boardId, $cardId, $commentId] = $ids; + + $card = $this->cardService->find($cardId)->jsonSerialize(); + $board = $this->boardService->find($boardId)->jsonSerialize(); + $stack = $this->stackService->find((int) $card['stackId'])->jsonSerialize(); + $card = $this->sanitizeSerializedCard($card); + $board = $this->sanitizeSerializedBoard($board); + $stack = $this->sanitizeSerializedStack($stack); + + $comment = $this->commentService->getFormatted($cardId, $commentId); + + /** @var IReference $reference */ + $reference = new Reference($referenceText); + $reference->setTitle($comment['message']); + $boardOwnerDisplayName = $board['owner']['displayname'] ?? $board['owner']['uid'] ?? '???'; + $reference->setDescription( + $this->l10n->t('From %1$s, in %2$s/%3$s, owned by %4$s', [ + $comment['actorDisplayName'], + $board['title'], + $stack['title'], + $boardOwnerDisplayName + ]) + ); + $imageUrl = $this->urlGenerator->getAbsoluteURL( + $this->urlGenerator->imagePath('core', 'actions/comment.svg') + ); + $reference->setImageUrl($imageUrl); + $reference->setRichObject(Application::APP_ID . '-comment', [ + 'id' => $ids, + 'board' => $board, + 'card' => $card, + 'stack' => $stack, + 'comment' => $comment, + ]); + return $reference; + } + } + + return null; + } + + private function sanitizeSerializedStack(array $stack): array { + $stack['cards'] = array_map(function (CardDetails $cardDetails) { + $result = $cardDetails->jsonSerialize(); + unset($result['assignedUsers']); + return $result; + }, $stack['cards']); + + return $stack; + } + + private function sanitizeSerializedBoard(array $board): array { + unset($board['labels']); + $board['owner'] = $board['owner']->jsonSerialize(); + unset($board['acl']); + unset($board['users']); + + return $board; + } + + private function sanitizeSerializedCard(array $card): array { + $card['labels'] = array_map(function (Label $label) { + return $label->jsonSerialize(); + }, $card['labels']); + $card['assignedUsers'] = array_map(function (Assignment $assignment) { + $result = $assignment->jsonSerialize(); + $result['participant'] = $result['participant']->jsonSerialize(); + return $result; + }, $card['assignedUsers']); + $card['owner'] = $card['owner']->jsonSerialize(); + unset($card['relatedStack']); + unset($card['relatedBoard']); + $card['attachments'] = array_map(function (Attachment $attachment) { + return $attachment->jsonSerialize(); + }, $card['attachments']); + + return $card; + } + + private function getIds(string $url): ?array { + $start = $this->urlGenerator->getAbsoluteURL('/apps/' . Application::APP_ID); + $startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/' . Application::APP_ID); + + preg_match('/^' . preg_quote($start, '/') . '\/#\/board\/([0-9]+)\/card\/([0-9]+)\/comments\/(\d+)$/', $url, $matches); + if (!$matches) { + preg_match('/^' . preg_quote($startIndex, '/') . '\/#\/board\/([0-9]+)\/card\/([0-9]+)\/comments\/(\d+)$/', $url, $matches); + } + if ($matches && count($matches) > 3) { + return [ + (int) $matches[1], + (int) $matches[2], + (int) $matches[3], + ]; + } + + return null; + } + + public function getCachePrefix(string $referenceId): string { + return $referenceId; + } + + public function getCacheKey(string $referenceId): ?string { + return $this->userId ?? ''; + } +} diff --git a/lib/Search/BoardSearchResultEntry.php b/lib/Search/BoardSearchResultEntry.php index c68fccb86..360cfb474 100644 --- a/lib/Search/BoardSearchResultEntry.php +++ b/lib/Search/BoardSearchResultEntry.php @@ -26,13 +26,16 @@ declare(strict_types=1); namespace OCA\Deck\Search; +use OCA\Deck\AppInfo\Application; use OCA\Deck\Db\Board; use OCP\Search\SearchResultEntry; class BoardSearchResultEntry extends SearchResultEntry { public function __construct(Board $board, $urlGenerator) { parent::__construct( - '', + $urlGenerator->getAbsoluteURL( + $urlGenerator->imagePath(Application::APP_ID, 'deck-dark.svg') + ), $board->getTitle(), '', $urlGenerator->linkToRouteAbsolute('deck.page.index') . '#/board/' . $board->getId(), diff --git a/lib/Search/CardCommentProvider.php b/lib/Search/CardCommentProvider.php index 802cc22c1..4a637a626 100644 --- a/lib/Search/CardCommentProvider.php +++ b/lib/Search/CardCommentProvider.php @@ -49,7 +49,7 @@ class CardCommentProvider implements IProvider { } public function getId(): string { - return 'deck-comment'; + return 'search-deck-comment'; } public function getName(): string { @@ -65,7 +65,7 @@ class CardCommentProvider implements IProvider { $results ); } - + return SearchResult::paginated( $this->l10n->t('Card comments'), $results, diff --git a/lib/Search/CardSearchResultEntry.php b/lib/Search/CardSearchResultEntry.php index a7369b56c..8ce2313b0 100644 --- a/lib/Search/CardSearchResultEntry.php +++ b/lib/Search/CardSearchResultEntry.php @@ -26,6 +26,7 @@ declare(strict_types=1); namespace OCA\Deck\Search; +use OCA\Deck\AppInfo\Application; use OCA\Deck\Db\Board; use OCA\Deck\Db\Card; use OCA\Deck\Db\Stack; @@ -33,6 +34,14 @@ use OCP\Search\SearchResultEntry; class CardSearchResultEntry extends SearchResultEntry { public function __construct(Board $board, Stack $stack, Card $card, $urlGenerator) { - parent::__construct('', $card->getTitle(), $board->getTitle() . ' » ' . $stack->getTitle(), $urlGenerator->linkToRouteAbsolute('deck.page.index') . '#/board/' . $board->getId() . '/card/' . $card->getId(), 'icon-deck'); + parent::__construct( + $urlGenerator->getAbsoluteURL( + $urlGenerator->imagePath(Application::APP_ID, 'card.svg') + ), + $card->getTitle(), + $board->getTitle() . ' » ' . $stack->getTitle(), + $urlGenerator->linkToRouteAbsolute('deck.page.index') . '#/board/' . $board->getId() . '/card/' . $card->getId(), + 'icon-deck' + ); } } diff --git a/lib/Search/CommentSearchResultEntry.php b/lib/Search/CommentSearchResultEntry.php index d8a541413..c36117273 100644 --- a/lib/Search/CommentSearchResultEntry.php +++ b/lib/Search/CommentSearchResultEntry.php @@ -36,7 +36,9 @@ class CommentSearchResultEntry extends SearchResultEntry { public function __construct(string $commentId, string $commentMessage, string $commentAuthor, Card $card, IURLGenerator $urlGenerator, IL10N $l10n) { parent::__construct( - '', + $urlGenerator->getAbsoluteURL( + $urlGenerator->imagePath('core', 'actions/comment.svg') + ), // TRANSLATORS This is describing the author and card title related to a comment e.g. "Jane on MyTask" $l10n->t('%s on %s', [$commentAuthor, $card->getTitle()]), $commentMessage, diff --git a/lib/Search/DeckProvider.php b/lib/Search/DeckProvider.php index 34c47df9f..77794fb16 100644 --- a/lib/Search/DeckProvider.php +++ b/lib/Search/DeckProvider.php @@ -29,6 +29,7 @@ namespace OCA\Deck\Search; use OCA\Deck\Db\Board; use OCA\Deck\Db\Card; use OCA\Deck\Service\SearchService; +use OCP\IL10N; use OCP\IURLGenerator; use OCP\IUser; use OCP\Search\IProvider; @@ -36,30 +37,26 @@ use OCP\Search\ISearchQuery; use OCP\Search\SearchResult; class DeckProvider implements IProvider { - - /** - * @var SearchService - */ - private $searchService; - /** - * @var IURLGenerator - */ - private $urlGenerator; + private IL10N $l10n; + private SearchService $searchService; + private IURLGenerator $urlGenerator; public function __construct( SearchService $searchService, - IURLGenerator $urlGenerator + IURLGenerator $urlGenerator, + IL10N $l10n ) { + $this->l10n = $l10n; $this->searchService = $searchService; $this->urlGenerator = $urlGenerator; } public function getId(): string { - return 'deck'; + return 'search-deck-card-board'; } public function getName(): string { - return 'Deck'; + return $this->l10n->t('Deck boards and cards'); } public function search(IUser $user, ISearchQuery $query): SearchResult { @@ -99,14 +96,14 @@ class DeckProvider implements IProvider { // if both cards and boards results are less then the limit, we know we won't get more if (count($resultEntries) < $query->getLimit()) { return SearchResult::complete( - 'Deck', + $this->getName(), $resultEntries ); } $newCursor = $this->getNewCursor($boardObjects, $cardObjects); return SearchResult::paginated( - 'Deck', + $this->getName(), $resultEntries, $newCursor ); diff --git a/lib/Service/CommentService.php b/lib/Service/CommentService.php index e9768d710..b33f84342 100644 --- a/lib/Service/CommentService.php +++ b/lib/Service/CommentService.php @@ -76,6 +76,42 @@ class CommentService { return new DataResponse($result); } + /** + * @param int $cardId + * @param int $commentId + * @return IComment + * @throws NoPermissionException + * @throws NotFoundException + */ + private function get(int $cardId, int $commentId): IComment { + $this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ); + try { + $comment = $this->commentsManager->get((string) $commentId); + if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || (int) $comment->getObjectId() !== $cardId) { + throw new CommentNotFoundException(); + } + } catch (CommentNotFoundException $e) { + throw new NotFoundException('No comment found.'); + } + if ($comment->getParentId() !== '0') { + $this->permissionService->checkPermission($this->cardMapper, $comment->getParentId(), Acl::PERMISSION_READ); + } + + return $comment; + } + + /** + * @param int $cardId + * @param int $commentId + * @return array + * @throws NoPermissionException + * @throws NotFoundException + */ + public function getFormatted(int $cardId, int $commentId): array { + $comment = $this->get($cardId, $commentId); + return $this->formatComment($comment); + } + /** * @param string $cardId * @param string $message @@ -126,21 +162,10 @@ class CommentService { if (!is_numeric($commentId)) { throw new BadRequestException('A valid comment id must be provided'); } - $this->permissionService->checkPermission($this->cardMapper, $cardId, Acl::PERMISSION_READ); - try { - $comment = $this->commentsManager->get($commentId); - if ($comment->getObjectType() !== Application::COMMENT_ENTITY_TYPE || $comment->getObjectId() !== $cardId) { - throw new CommentNotFoundException(); - } - } catch (CommentNotFoundException $e) { - throw new NotFoundException('No comment found.'); - } + $comment = $this->get((int) $cardId, (int) $commentId); if ($comment->getActorType() !== 'users' || $comment->getActorId() !== $this->userId) { throw new NoPermissionException('Only authors are allowed to edit their comment.'); } - if ($comment->getParentId() !== '0') { - $this->permissionService->checkPermission($this->cardMapper, $comment->getParentId(), Acl::PERMISSION_READ); - } $comment->setMessage($message); $this->commentsManager->save($comment); diff --git a/src/init-card-reference.js b/src/init-reference.js similarity index 66% rename from src/init-card-reference.js rename to src/init-reference.js index 618a9065d..25b630a37 100644 --- a/src/init-card-reference.js +++ b/src/init-reference.js @@ -23,6 +23,8 @@ import { registerWidget } from '@nextcloud/vue-richtext' import { Tooltip } from '@nextcloud/vue' import Vue from 'vue' import CardReferenceWidget from './views/CardReferenceWidget.vue' +import BoardReferenceWidget from './views/BoardReferenceWidget.vue' +import CommentReferenceWidget from './views/CommentReferenceWidget.vue' import { translate, translatePlural } from '@nextcloud/l10n' @@ -48,3 +50,33 @@ registerWidget('deck-card', (el, { richObjectType, richObject, accessible }) => }, }).$mount(el) }) + +registerWidget('deck-board', (el, { richObjectType, richObject, accessible }) => { + el.parentNode.style['max-width'] = '400px' + el.parentNode.style['margin-left'] = '0' + el.parentNode.style['margin-right'] = '0' + + const Widget = Vue.extend(BoardReferenceWidget) + new Widget({ + propsData: { + richObjectType, + richObject, + accessible, + }, + }).$mount(el) +}) + +registerWidget('deck-comment', (el, { richObjectType, richObject, accessible }) => { + el.parentNode.style['max-width'] = '400px' + el.parentNode.style['margin-left'] = '0' + el.parentNode.style['margin-right'] = '0' + + const Widget = Vue.extend(CommentReferenceWidget) + new Widget({ + propsData: { + richObjectType, + richObject, + accessible, + }, + }).$mount(el) +}) diff --git a/src/views/BoardReferenceWidget.vue b/src/views/BoardReferenceWidget.vue new file mode 100644 index 000000000..06ddc49db --- /dev/null +++ b/src/views/BoardReferenceWidget.vue @@ -0,0 +1,128 @@ + + + + + + + + + {{ board.title }} + + + + + {{ t('deck', 'Owner') + ': ' }} + + + + + + + + diff --git a/src/views/CardReferenceWidget.vue b/src/views/CardReferenceWidget.vue index a0d711690..2f2db2fa0 100644 --- a/src/views/CardReferenceWidget.vue +++ b/src/views/CardReferenceWidget.vue @@ -1,7 +1,7 @@ + + + + + + + + {{ card.title }} + + + + + + {{ dueDate }} + + + + + + {{ t('deck', '{stack} in {board}', { stack: stack.title, board: board.title }) }} + + + + + + {{ label.title }} + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/integration/features/bootstrap/SearchContext.php b/tests/integration/features/bootstrap/SearchContext.php index 8ed46ff39..127255d01 100644 --- a/tests/integration/features/bootstrap/SearchContext.php +++ b/tests/integration/features/bootstrap/SearchContext.php @@ -21,7 +21,7 @@ class SearchContext implements Context { $this->boardContext = $environment->getContext('BoardContext'); } - + /** * @When /^searching for "([^"]*)"$/ * @param string $term @@ -39,7 +39,7 @@ class SearchContext implements Context { * https://cloud.nextcloud.com/ocs/v2.php/search/providers/talk-conversations/search?term=an&from=%2Fapps%2Fdashboard%2F */ public function searchingForComments(string $term) { - $this->requestContext->sendOCSRequest('GET', '/search/providers/deck-comment/search?term=' . urlencode($term), []); + $this->requestContext->sendOCSRequest('GET', '/search/providers/search-deck-comment/search?term=' . urlencode($term), []); $this->requestContext->getResponse()->getBody()->seek(0); $data = (string)$this->getResponse()->getBody(); $this->unifiedSearchResult = json_decode($data, true); diff --git a/webpack.js b/webpack.js index d5db80b35..76d7462a5 100644 --- a/webpack.js +++ b/webpack.js @@ -12,7 +12,7 @@ webpackConfig.entry = { dashboard: path.join(__dirname, 'src', 'init-dashboard.js'), calendar: path.join(__dirname, 'src', 'init-calendar.js'), talk: path.join(__dirname, 'src', 'init-talk.js'), - 'card-reference': path.join(__dirname, 'src', 'init-card-reference.js'), + reference: path.join(__dirname, 'src', 'init-reference.js'), } webpackConfig.stats = {