diff --git a/docs/User_documentation_en.md b/docs/User_documentation_en.md index 824c80c5c..6000fba0c 100644 --- a/docs/User_documentation_en.md +++ b/docs/User_documentation_en.md @@ -9,14 +9,13 @@ Project management, time management or ideation, Deck makes it easier for you to ## Using Deck Overall, Deck is easy to use. You can create boards, add users, share the Deck, work collaboratively and in real time. -- 1. [Create my first board](#1-create-my-first-board) -- 2. [Create stacks and cards](#2-create-stacks-and-cards) -- 3. [Handle cards options](#3-handle-cards-options) -- 4. [Archive old tasks](#4-archive-old-tasks) -- 5. [Manage your board](#5-manage-your-board) -- 6. [Import boards](#6-import-boards) - - [Trello JSON](#trello-json) - - [Trello API](#trello-api) +1. [Create my first board](#1-create-my-first-board) +2. [Create stacks and cards](#2-create-stacks-and-cards) +3. [Handle cards options](#3-handle-cards-options) +4. [Archive old tasks](#4-archive-old-tasks) +5. [Manage your board](#5-manage-your-board) +6. [Import boards](#6-import-boards) +7. [Search](#7-search) ### 1. Create my first board In this example, we're going to create a board and share it with an other nextcloud user. @@ -136,14 +135,14 @@ Example configuration file: } ``` -## Search +### 7. Search Deck provides a global search either through the unified search in the Nextcloud header or with the inline search next to the board controls. This search allows advanced filtering of cards across all board of the logged in user. For example the search `project tag:ToDo assigned:alice assigned:bob` will return all cards where the card title or description contains project **and** the tag ToDo is set **and** the user alice is assigned **and** the user bob is assigned. -### Supported search filters +#### Supported search filters | Filter | Operators | Query | | ----------- | ----------------- | ------------------------------------------------------------ | diff --git a/lib/Service/BoardImportService.php b/lib/Service/BoardImportService.php index 07cfb790d..5a71a91fb 100644 --- a/lib/Service/BoardImportService.php +++ b/lib/Service/BoardImportService.php @@ -29,6 +29,8 @@ use OCA\Deck\AppInfo\Application; use OCA\Deck\BadRequestException; use OCA\Deck\Db\AclMapper; use OCA\Deck\Db\AssignmentMapper; +use OCA\Deck\Db\Attachment; +use OCA\Deck\Db\AttachmentMapper; use OCA\Deck\Db\Board; use OCA\Deck\Db\BoardMapper; use OCA\Deck\Db\CardMapper; @@ -61,6 +63,8 @@ class BoardImportService { private $cardMapper; /** @var AssignmentMapper */ private $assignmentMapper; + /** @var AttachmentMapper */ + private $attachmentMapper; /** @var ICommentsManager */ private $commentsManager; /** @var string */ @@ -96,6 +100,7 @@ class BoardImportService { LabelMapper $labelMapper, StackMapper $stackMapper, AssignmentMapper $assignmentMapper, + AttachmentMapper $attachmentMapper, CardMapper $cardMapper, ICommentsManager $commentsManager ) { @@ -107,6 +112,7 @@ class BoardImportService { $this->stackMapper = $stackMapper; $this->cardMapper = $cardMapper; $this->assignmentMapper = $assignmentMapper; + $this->attachmentMapper = $attachmentMapper; $this->commentsManager = $commentsManager; $this->board = new Board(); $this->disableCommentsEvents(); @@ -342,6 +348,24 @@ class BoardImportService { } } + public function insertAttachment(Attachment $attachment, string $content): Attachment { + $service = \OC::$server->get(FileService::class); + $folder = $service->getFolder($attachment); + + if ($folder->fileExists($attachment->getData())) { + $attachment = $this->attachmentMapper->findByData($attachment->getCardId(), $attachment->getData()); + throw new ConflictException('File already exists.', $attachment); + } + + $target = $folder->newFile($attachment->getData()); + $target->putContent($content); + + $attachment = $this->attachmentMapper->insert($attachment); + + $service->extendData($attachment); + return $attachment; + } + public function setData(\stdClass $data): void { $this->data = $data; } diff --git a/lib/Service/BoardImportTrelloApiService.php b/lib/Service/BoardImportTrelloApiService.php index 94e8f2432..8cecbbd13 100644 --- a/lib/Service/BoardImportTrelloApiService.php +++ b/lib/Service/BoardImportTrelloApiService.php @@ -26,6 +26,7 @@ namespace OCA\Deck\Service; use OCP\Http\Client\IClient; use OCP\Http\Client\IClientService; use OCP\IL10N; +use OCP\IURLGenerator; use OCP\IUserManager; use Psr\Log\LoggerInterface; @@ -44,11 +45,12 @@ class BoardImportTrelloApiService extends BoardImportTrelloJsonService { public function __construct( IUserManager $userManager, + IURLGenerator $urlGenerator, IL10N $l10n, LoggerInterface $logger, IClientService $httpClientService ) { - parent::__construct($userManager, $l10n); + parent::__construct($userManager, $urlGenerator, $l10n); $this->logger = $logger; $this->httpClient = $httpClientService->newClient(); } diff --git a/lib/Service/BoardImportTrelloJsonService.php b/lib/Service/BoardImportTrelloJsonService.php index 5ea3fa429..2f69d7a19 100644 --- a/lib/Service/BoardImportTrelloJsonService.php +++ b/lib/Service/BoardImportTrelloJsonService.php @@ -27,11 +27,14 @@ use OC\Comments\Comment; use OCA\Deck\BadRequestException; use OCA\Deck\Db\Acl; use OCA\Deck\Db\Assignment; +use OCA\Deck\Db\Attachment; use OCA\Deck\Db\Board; use OCA\Deck\Db\Card; use OCA\Deck\Db\Label; use OCA\Deck\Db\Stack; +use OCP\Comments\IComment; use OCP\IL10N; +use OCP\IURLGenerator; use OCP\IUser; use OCP\IUserManager; @@ -40,6 +43,8 @@ class BoardImportTrelloJsonService extends ABoardImportService { public static $name = 'Trello JSON'; /** @var IUserManager */ private $userManager; + /** @var IURLGenerator */ + private $urlGenerator; /** @var IL10N */ private $l10n; /** @var IUser[] */ @@ -47,9 +52,11 @@ class BoardImportTrelloJsonService extends ABoardImportService { public function __construct( IUserManager $userManager, + IURLGenerator $urlGenerator, IL10N $l10n ) { $this->userManager = $userManager; + $this->urlGenerator = $urlGenerator; $this->l10n = $l10n; } @@ -113,19 +120,48 @@ class BoardImportTrelloJsonService extends ABoardImportService { $trelloComments = array_combine($keys, $values); $trelloComments = $this->sortComments($trelloComments); foreach ($trelloComments as $commentId => $trelloComment) { + $cardId = $this->cards[$trelloCard->id]->getId(); $comment = new Comment(); if (!empty($this->getImportService()->getConfig('uidRelation')->{$trelloComment->memberCreator->username})) { $actor = $this->getImportService()->getConfig('uidRelation')->{$trelloComment->memberCreator->username}->getUID(); } else { $actor = $this->getImportService()->getConfig('owner')->getUID(); } + $message = $this->replaceUsernames($trelloComment->data->text); + if (mb_strlen($message, 'UTF-8') > IComment::MAX_MESSAGE_LENGTH) { + $attachment = new Attachment(); + $attachment->setCardId($cardId); + $attachment->setType('deck_file'); + $attachment->setCreatedBy($actor); + $attachment->setLastModified(time()); + $attachment->setCreatedAt(time()); + $attachment->setData('comment_' . $commentId . '.md'); + $attachment = $this->getImportService()->insertAttachment($attachment, $message); + + $urlToDownloadAttachment = $this->urlGenerator->linkToRouteAbsolute( + 'deck.attachment.display', + [ + 'cardId' => $cardId, + 'attachmentId' => $attachment->getId() + ] + ); + $message = $this->l10n->t( + "This comment has more than %s characters.\n" . + "Added as an attachment to the card with name %s\n" . + "Accessible on URL: %s.", + [ + IComment::MAX_MESSAGE_LENGTH, + 'comment_' . $commentId . '.md', + $urlToDownloadAttachment + ] + ); + } $comment ->setActor('users', $actor) - ->setMessage($this->replaceUsernames($trelloComment->data->text), 0) + ->setMessage($message) ->setCreationDateTime( \DateTime::createFromFormat('Y-m-d\TH:i:s.v\Z', $trelloComment->date) ); - $cardId = $this->cards[$trelloCard->id]->getId(); $comments[$cardId][$commentId] = $comment; } } @@ -133,7 +169,7 @@ class BoardImportTrelloJsonService extends ABoardImportService { } private function sortComments(array $comments): array { - $comparison = function($a, $b) { + $comparison = function (\stdClass $a, \stdClass $b): int { if ($a->date == $b->date) { return 0; } diff --git a/lib/Service/FileService.php b/lib/Service/FileService.php index 2c5e359d3..7158c6d7c 100644 --- a/lib/Service/FileService.php +++ b/lib/Service/FileService.php @@ -86,7 +86,7 @@ class FileService implements IAttachmentService { * @return ISimpleFolder * @throws NotPermittedException */ - private function getFolder(Attachment $attachment) { + public function getFolder(Attachment $attachment) { $folderName = 'file-card-' . (int)$attachment->getCardId(); try { $folder = $this->appData->getFolder($folderName);