Add long comments with attachment
Signed-off-by: Vitor Mattos <vitor@php.rio>
This commit is contained in:
committed by
Julius Härtl
parent
e87c063076
commit
4561887348
@@ -9,14 +9,13 @@ Project management, time management or ideation, Deck makes it easier for you to
|
|||||||
## Using Deck
|
## Using Deck
|
||||||
Overall, Deck is easy to use. You can create boards, add users, share the Deck, work collaboratively and in real time.
|
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)
|
1. [Create my first board](#1-create-my-first-board)
|
||||||
- 2. [Create stacks and cards](#2-create-stacks-and-cards)
|
2. [Create stacks and cards](#2-create-stacks-and-cards)
|
||||||
- 3. [Handle cards options](#3-handle-cards-options)
|
3. [Handle cards options](#3-handle-cards-options)
|
||||||
- 4. [Archive old tasks](#4-archive-old-tasks)
|
4. [Archive old tasks](#4-archive-old-tasks)
|
||||||
- 5. [Manage your board](#5-manage-your-board)
|
5. [Manage your board](#5-manage-your-board)
|
||||||
- 6. [Import boards](#6-import-boards)
|
6. [Import boards](#6-import-boards)
|
||||||
- [Trello JSON](#trello-json)
|
7. [Search](#7-search)
|
||||||
- [Trello API](#trello-api)
|
|
||||||
|
|
||||||
### 1. Create my first board
|
### 1. Create my first board
|
||||||
In this example, we're going to create a board and share it with an other nextcloud user.
|
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.
|
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.
|
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.
|
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 |
|
| Filter | Operators | Query |
|
||||||
| ----------- | ----------------- | ------------------------------------------------------------ |
|
| ----------- | ----------------- | ------------------------------------------------------------ |
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ use OCA\Deck\AppInfo\Application;
|
|||||||
use OCA\Deck\BadRequestException;
|
use OCA\Deck\BadRequestException;
|
||||||
use OCA\Deck\Db\AclMapper;
|
use OCA\Deck\Db\AclMapper;
|
||||||
use OCA\Deck\Db\AssignmentMapper;
|
use OCA\Deck\Db\AssignmentMapper;
|
||||||
|
use OCA\Deck\Db\Attachment;
|
||||||
|
use OCA\Deck\Db\AttachmentMapper;
|
||||||
use OCA\Deck\Db\Board;
|
use OCA\Deck\Db\Board;
|
||||||
use OCA\Deck\Db\BoardMapper;
|
use OCA\Deck\Db\BoardMapper;
|
||||||
use OCA\Deck\Db\CardMapper;
|
use OCA\Deck\Db\CardMapper;
|
||||||
@@ -61,6 +63,8 @@ class BoardImportService {
|
|||||||
private $cardMapper;
|
private $cardMapper;
|
||||||
/** @var AssignmentMapper */
|
/** @var AssignmentMapper */
|
||||||
private $assignmentMapper;
|
private $assignmentMapper;
|
||||||
|
/** @var AttachmentMapper */
|
||||||
|
private $attachmentMapper;
|
||||||
/** @var ICommentsManager */
|
/** @var ICommentsManager */
|
||||||
private $commentsManager;
|
private $commentsManager;
|
||||||
/** @var string */
|
/** @var string */
|
||||||
@@ -96,6 +100,7 @@ class BoardImportService {
|
|||||||
LabelMapper $labelMapper,
|
LabelMapper $labelMapper,
|
||||||
StackMapper $stackMapper,
|
StackMapper $stackMapper,
|
||||||
AssignmentMapper $assignmentMapper,
|
AssignmentMapper $assignmentMapper,
|
||||||
|
AttachmentMapper $attachmentMapper,
|
||||||
CardMapper $cardMapper,
|
CardMapper $cardMapper,
|
||||||
ICommentsManager $commentsManager
|
ICommentsManager $commentsManager
|
||||||
) {
|
) {
|
||||||
@@ -107,6 +112,7 @@ class BoardImportService {
|
|||||||
$this->stackMapper = $stackMapper;
|
$this->stackMapper = $stackMapper;
|
||||||
$this->cardMapper = $cardMapper;
|
$this->cardMapper = $cardMapper;
|
||||||
$this->assignmentMapper = $assignmentMapper;
|
$this->assignmentMapper = $assignmentMapper;
|
||||||
|
$this->attachmentMapper = $attachmentMapper;
|
||||||
$this->commentsManager = $commentsManager;
|
$this->commentsManager = $commentsManager;
|
||||||
$this->board = new Board();
|
$this->board = new Board();
|
||||||
$this->disableCommentsEvents();
|
$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 {
|
public function setData(\stdClass $data): void {
|
||||||
$this->data = $data;
|
$this->data = $data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace OCA\Deck\Service;
|
|||||||
use OCP\Http\Client\IClient;
|
use OCP\Http\Client\IClient;
|
||||||
use OCP\Http\Client\IClientService;
|
use OCP\Http\Client\IClientService;
|
||||||
use OCP\IL10N;
|
use OCP\IL10N;
|
||||||
|
use OCP\IURLGenerator;
|
||||||
use OCP\IUserManager;
|
use OCP\IUserManager;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
@@ -44,11 +45,12 @@ class BoardImportTrelloApiService extends BoardImportTrelloJsonService {
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
IUserManager $userManager,
|
IUserManager $userManager,
|
||||||
|
IURLGenerator $urlGenerator,
|
||||||
IL10N $l10n,
|
IL10N $l10n,
|
||||||
LoggerInterface $logger,
|
LoggerInterface $logger,
|
||||||
IClientService $httpClientService
|
IClientService $httpClientService
|
||||||
) {
|
) {
|
||||||
parent::__construct($userManager, $l10n);
|
parent::__construct($userManager, $urlGenerator, $l10n);
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
$this->httpClient = $httpClientService->newClient();
|
$this->httpClient = $httpClientService->newClient();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,11 +27,14 @@ use OC\Comments\Comment;
|
|||||||
use OCA\Deck\BadRequestException;
|
use OCA\Deck\BadRequestException;
|
||||||
use OCA\Deck\Db\Acl;
|
use OCA\Deck\Db\Acl;
|
||||||
use OCA\Deck\Db\Assignment;
|
use OCA\Deck\Db\Assignment;
|
||||||
|
use OCA\Deck\Db\Attachment;
|
||||||
use OCA\Deck\Db\Board;
|
use OCA\Deck\Db\Board;
|
||||||
use OCA\Deck\Db\Card;
|
use OCA\Deck\Db\Card;
|
||||||
use OCA\Deck\Db\Label;
|
use OCA\Deck\Db\Label;
|
||||||
use OCA\Deck\Db\Stack;
|
use OCA\Deck\Db\Stack;
|
||||||
|
use OCP\Comments\IComment;
|
||||||
use OCP\IL10N;
|
use OCP\IL10N;
|
||||||
|
use OCP\IURLGenerator;
|
||||||
use OCP\IUser;
|
use OCP\IUser;
|
||||||
use OCP\IUserManager;
|
use OCP\IUserManager;
|
||||||
|
|
||||||
@@ -40,6 +43,8 @@ class BoardImportTrelloJsonService extends ABoardImportService {
|
|||||||
public static $name = 'Trello JSON';
|
public static $name = 'Trello JSON';
|
||||||
/** @var IUserManager */
|
/** @var IUserManager */
|
||||||
private $userManager;
|
private $userManager;
|
||||||
|
/** @var IURLGenerator */
|
||||||
|
private $urlGenerator;
|
||||||
/** @var IL10N */
|
/** @var IL10N */
|
||||||
private $l10n;
|
private $l10n;
|
||||||
/** @var IUser[] */
|
/** @var IUser[] */
|
||||||
@@ -47,9 +52,11 @@ class BoardImportTrelloJsonService extends ABoardImportService {
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
IUserManager $userManager,
|
IUserManager $userManager,
|
||||||
|
IURLGenerator $urlGenerator,
|
||||||
IL10N $l10n
|
IL10N $l10n
|
||||||
) {
|
) {
|
||||||
$this->userManager = $userManager;
|
$this->userManager = $userManager;
|
||||||
|
$this->urlGenerator = $urlGenerator;
|
||||||
$this->l10n = $l10n;
|
$this->l10n = $l10n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,19 +120,48 @@ class BoardImportTrelloJsonService extends ABoardImportService {
|
|||||||
$trelloComments = array_combine($keys, $values);
|
$trelloComments = array_combine($keys, $values);
|
||||||
$trelloComments = $this->sortComments($trelloComments);
|
$trelloComments = $this->sortComments($trelloComments);
|
||||||
foreach ($trelloComments as $commentId => $trelloComment) {
|
foreach ($trelloComments as $commentId => $trelloComment) {
|
||||||
|
$cardId = $this->cards[$trelloCard->id]->getId();
|
||||||
$comment = new Comment();
|
$comment = new Comment();
|
||||||
if (!empty($this->getImportService()->getConfig('uidRelation')->{$trelloComment->memberCreator->username})) {
|
if (!empty($this->getImportService()->getConfig('uidRelation')->{$trelloComment->memberCreator->username})) {
|
||||||
$actor = $this->getImportService()->getConfig('uidRelation')->{$trelloComment->memberCreator->username}->getUID();
|
$actor = $this->getImportService()->getConfig('uidRelation')->{$trelloComment->memberCreator->username}->getUID();
|
||||||
} else {
|
} else {
|
||||||
$actor = $this->getImportService()->getConfig('owner')->getUID();
|
$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
|
$comment
|
||||||
->setActor('users', $actor)
|
->setActor('users', $actor)
|
||||||
->setMessage($this->replaceUsernames($trelloComment->data->text), 0)
|
->setMessage($message)
|
||||||
->setCreationDateTime(
|
->setCreationDateTime(
|
||||||
\DateTime::createFromFormat('Y-m-d\TH:i:s.v\Z', $trelloComment->date)
|
\DateTime::createFromFormat('Y-m-d\TH:i:s.v\Z', $trelloComment->date)
|
||||||
);
|
);
|
||||||
$cardId = $this->cards[$trelloCard->id]->getId();
|
|
||||||
$comments[$cardId][$commentId] = $comment;
|
$comments[$cardId][$commentId] = $comment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,7 +169,7 @@ class BoardImportTrelloJsonService extends ABoardImportService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function sortComments(array $comments): array {
|
private function sortComments(array $comments): array {
|
||||||
$comparison = function($a, $b) {
|
$comparison = function (\stdClass $a, \stdClass $b): int {
|
||||||
if ($a->date == $b->date) {
|
if ($a->date == $b->date) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ class FileService implements IAttachmentService {
|
|||||||
* @return ISimpleFolder
|
* @return ISimpleFolder
|
||||||
* @throws NotPermittedException
|
* @throws NotPermittedException
|
||||||
*/
|
*/
|
||||||
private function getFolder(Attachment $attachment) {
|
public function getFolder(Attachment $attachment) {
|
||||||
$folderName = 'file-card-' . (int)$attachment->getCardId();
|
$folderName = 'file-card-' . (int)$attachment->getCardId();
|
||||||
try {
|
try {
|
||||||
$folder = $this->appData->getFolder($folderName);
|
$folder = $this->appData->getFolder($folderName);
|
||||||
|
|||||||
Reference in New Issue
Block a user