diff --git a/appinfo/routes.php b/appinfo/routes.php index 1f3208c53..d56023645 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -43,6 +43,7 @@ return [ ['name' => 'card#read', 'url' => '/cards/{cardId}', 'verb' => 'GET'], ['name' => 'card#create', 'url' => '/cards', 'verb' => 'POST'], ['name' => 'card#update', 'url' => '/cards/{cardId}', 'verb' => 'PUT'], + ['name' => 'card#clone', 'url' => '/cards/{cardId}/clone', 'verb' => 'POST'], ['name' => 'card#delete', 'url' => '/cards/{cardId}', 'verb' => 'DELETE'], ['name' => 'card#deleted', 'url' => '/{boardId}/cards/deleted', 'verb' => 'GET'], ['name' => 'card#rename', 'url' => '/cards/{cardId}/rename', 'verb' => 'PUT'], diff --git a/lib/Controller/CardController.php b/lib/Controller/CardController.php index c6ea2edf1..c0e6d10c3 100644 --- a/lib/Controller/CardController.php +++ b/lib/Controller/CardController.php @@ -90,6 +90,15 @@ class CardController extends Controller { public function update($id, $title, $stackId, $type, $order, $description, $duedate, $deletedAt) { return $this->cardService->update($id, $title, $stackId, $type, $this->userId, $description, $order, $duedate, $deletedAt); } + /** + * @NoAdminRequired + * @param $cardId + * @param $targetStackId + * @return \OCP\AppFramework\Db\Entity + */ + public function clone(int $cardId, ?int $targetStackId = null) { + return $this->cardService->cloneCard($cardId, $targetStackId); + } /** * @NoAdminRequired diff --git a/lib/Service/CardService.php b/lib/Service/CardService.php index fbce40646..e93c9be0a 100644 --- a/lib/Service/CardService.php +++ b/lib/Service/CardService.php @@ -78,6 +78,7 @@ class CardService { LoggerInterface $logger, IRequest $request, CardServiceValidator $cardServiceValidator, + private AssignmentService $assignmentService, ?string $userId, ) { $this->cardMapper = $cardMapper; @@ -391,6 +392,29 @@ class CardService { return $card; } + public function cloneCard(int $id, ?int $targetStackId = null):Card { + $this->permissionService->checkPermission($this->cardMapper, $id, Acl::PERMISSION_READ); + $originCard = $this->cardMapper->find($id); + if ($targetStackId == null) { + $targetStackId = $originCard->getStackId(); + } + $this->permissionService->checkPermission($this->stackMapper, $targetStackId, Acl::PERMISSION_EDIT); + $newCard = $this->create($originCard->getTitle(), $targetStackId, $originCard->getType(), $originCard->getOrder(), $originCard->getOwner()); + $boardId = $this->stackMapper->findBoardId($targetStackId); + foreach ($this->labelMapper->findAssignedLabelsForCard($id) as $label) { + if ($boardId != $this->stackMapper->findBoardId($originCard->getStackId())) { + $label = $this->labelService->cloneLabelIfNotExists($label->getId(), $boardId); + } + $this->assignLabel($newCard->getId(), $label->getId()); + } + foreach ($this->assignedUsersMapper->findAll($id) as $assignement) { + $this->assignmentService->assignUser($newCard->getId(), $assignement->getParticipant()); + } + $newCard->setDescription($originCard->getDescription()); + $card = $this->enrichCards([$this->cardMapper->update($newCard)]); + return $card[0]; + } + /** * @param $id * @param $title diff --git a/lib/Service/LabelService.php b/lib/Service/LabelService.php index 98150a62c..69f372c42 100644 --- a/lib/Service/LabelService.php +++ b/lib/Service/LabelService.php @@ -93,6 +93,18 @@ class LabelService { return $this->labelMapper->insert($label); } + public function cloneLabelIfNotExists(int $labelId, int $targetBoardId): Label { + $this->permissionService->checkPermission(null, $targetBoardId, Acl::PERMISSION_MANAGE); + $boardLabels = $this->boardService->find($targetBoardId)->getLabels(); + $originLabel = $this->find($labelId); + $filteredValues = array_values(array_filter($boardLabels, fn ($item) => $item->getTitle() === $originLabel->getTitle())); + if (empty($filteredValues)) { + $label = $this->create($originLabel->getTitle(), $originLabel->getColor(), $targetBoardId); + return $label; + } + return $originLabel; + } + /** * @param $id * @return \OCP\AppFramework\Db\Entity diff --git a/src/CardCloneDialog.vue b/src/CardCloneDialog.vue index b0d1b4f27..94fbe8d66 100644 --- a/src/CardCloneDialog.vue +++ b/src/CardCloneDialog.vue @@ -21,7 +21,7 @@ :max-height="100" label="title" /> -