introduce cloneCard backendFunctionality

Signed-off-by: grnd-alt <salimbelakkaf@outlook.de>
This commit is contained in:
grnd-alt
2024-11-04 12:45:33 +01:00
committed by Julius Knorr
parent 55c44ef6d4
commit 838b648ef6
8 changed files with 76 additions and 4 deletions

View File

@@ -43,6 +43,7 @@ return [
['name' => 'card#read', 'url' => '/cards/{cardId}', 'verb' => 'GET'], ['name' => 'card#read', 'url' => '/cards/{cardId}', 'verb' => 'GET'],
['name' => 'card#create', 'url' => '/cards', 'verb' => 'POST'], ['name' => 'card#create', 'url' => '/cards', 'verb' => 'POST'],
['name' => 'card#update', 'url' => '/cards/{cardId}', 'verb' => 'PUT'], ['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#delete', 'url' => '/cards/{cardId}', 'verb' => 'DELETE'],
['name' => 'card#deleted', 'url' => '/{boardId}/cards/deleted', 'verb' => 'GET'], ['name' => 'card#deleted', 'url' => '/{boardId}/cards/deleted', 'verb' => 'GET'],
['name' => 'card#rename', 'url' => '/cards/{cardId}/rename', 'verb' => 'PUT'], ['name' => 'card#rename', 'url' => '/cards/{cardId}/rename', 'verb' => 'PUT'],

View File

@@ -90,6 +90,15 @@ class CardController extends Controller {
public function update($id, $title, $stackId, $type, $order, $description, $duedate, $deletedAt) { 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); 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 * @NoAdminRequired

View File

@@ -78,6 +78,7 @@ class CardService {
LoggerInterface $logger, LoggerInterface $logger,
IRequest $request, IRequest $request,
CardServiceValidator $cardServiceValidator, CardServiceValidator $cardServiceValidator,
private AssignmentService $assignmentService,
?string $userId, ?string $userId,
) { ) {
$this->cardMapper = $cardMapper; $this->cardMapper = $cardMapper;
@@ -391,6 +392,29 @@ class CardService {
return $card; 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 $id
* @param $title * @param $title

View File

@@ -93,6 +93,18 @@ class LabelService {
return $this->labelMapper->insert($label); 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 * @param $id
* @return \OCP\AppFramework\Db\Entity * @return \OCP\AppFramework\Db\Entity

View File

@@ -21,7 +21,7 @@
:max-height="100" :max-height="100"
label="title" /> label="title" />
<button :disabled="!isBoardAndStackChoosen" class="primary" @click="moveCard"> <button :disabled="!isBoardAndStackChoosen" class="primary" @click="cloneCard">
{{ t('deck', 'Clone card') }} {{ t('deck', 'Clone card') }}
</button> </button>
<button @click="modalShow = false"> <button @click="modalShow = false">
@@ -89,9 +89,8 @@ export default {
return err return err
} }
}, },
async moveCard() { async cloneCard() {
this.copiedCard = Object.assign({}, this.card) this.$store.dispatch('cloneCard', { cardId: this.card.id, targetStackId: this.selectedStack.id })
this.copiedCard.stackId = this.selectedStack.id
this.$store.dispatch('addCard', this.copiedCard) this.$store.dispatch('addCard', this.copiedCard)
this.modalShow = false this.modalShow = false
}, },

View File

@@ -28,6 +28,23 @@ export class CardApi {
}) })
} }
cloneCard(cardId, targetStackId) {
return axios.post(this.url(`/cards/${cardId}/clone`), {
targetStackId,
})
.then(
(response) => {
return Promise.resolve(response.data)
},
(err) => {
return Promise.reject(err)
},
)
.catch((err) => {
return Promise.reject(err)
})
}
deleteCard(cardId) { deleteCard(cardId) {
return axios.delete(this.url(`/cards/${cardId}`)) return axios.delete(this.url(`/cards/${cardId}`))
.then( .then(

View File

@@ -272,6 +272,11 @@ export default {
}, },
}, },
actions: { actions: {
async cloneCard({ commit }, { cardId, targetStackId }) {
const createdCard = await apiClient.cloneCard(cardId, targetStackId)
commit('addCard', createdCard)
return createdCard
},
async addCard({ commit }, card) { async addCard({ commit }, card) {
const createdCard = await apiClient.addCard(card) const createdCard = await apiClient.addCard(card)
commit('addCard', createdCard) commit('addCard', createdCard)

View File

@@ -93,6 +93,9 @@ class CardServiceTest extends TestCase {
/** @var CardServiceValidator|MockObject */ /** @var CardServiceValidator|MockObject */
private $cardServiceValidator; private $cardServiceValidator;
/** @var AssignmentService|MockObject */
private $assignmentService;
public function setUp(): void { public function setUp(): void {
parent::setUp(); parent::setUp();
$this->cardMapper = $this->createMock(CardMapper::class); $this->cardMapper = $this->createMock(CardMapper::class);
@@ -114,6 +117,7 @@ class CardServiceTest extends TestCase {
$this->logger = $this->createMock(LoggerInterface::class); $this->logger = $this->createMock(LoggerInterface::class);
$this->request = $this->createMock(IRequest::class); $this->request = $this->createMock(IRequest::class);
$this->cardServiceValidator = $this->createMock(CardServiceValidator::class); $this->cardServiceValidator = $this->createMock(CardServiceValidator::class);
$this->assignmentService = $this->createMock(AssignmentService::class);
$this->logger->expects($this->any())->method('error'); $this->logger->expects($this->any())->method('error');
@@ -137,6 +141,7 @@ class CardServiceTest extends TestCase {
$this->logger, $this->logger,
$this->request, $this->request,
$this->cardServiceValidator, $this->cardServiceValidator,
$this->assignmentService,
'user1' 'user1'
); );
} }