Add long comments with attachment

Signed-off-by: Vitor Mattos <vitor@php.rio>
This commit is contained in:
Vitor Mattos
2021-07-26 23:58:30 -03:00
committed by Julius Härtl
parent e87c063076
commit 4561887348
5 changed files with 76 additions and 15 deletions

View File

@@ -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 |
| ----------- | ----------------- | ------------------------------------------------------------ |

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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;
}

View File

@@ -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);