introduce cloneCard backendFunctionality
Signed-off-by: grnd-alt <salimbelakkaf@outlook.de>
This commit is contained in:
@@ -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'],
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user