From 7750621917e21cd8c6709b22b5d15be4ca422b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20R=C3=B6hrl?= Date: Fri, 7 Feb 2020 12:29:39 +0100 Subject: [PATCH 1/9] X1st try MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jakob Röhrl --- .../card/CardSidebarTabAttachments.vue | 74 +++++++++++++++++- src/components/cards/CardBadges.vue | 7 +- src/services/AttachmentApi.js | 68 ++++++++++++++++ src/store/attachment.js | 77 +++++++++++++++++++ src/store/card.js | 14 ++++ src/store/main.js | 2 + 6 files changed, 237 insertions(+), 5 deletions(-) create mode 100644 src/services/AttachmentApi.js create mode 100644 src/store/attachment.js diff --git a/src/components/card/CardSidebarTabAttachments.vue b/src/components/card/CardSidebarTabAttachments.vue index 100716150..ba9685fb3 100644 --- a/src/components/card/CardSidebarTabAttachments.vue +++ b/src/components/card/CardSidebarTabAttachments.vue @@ -22,30 +22,98 @@ diff --git a/src/components/cards/CardBadges.vue b/src/components/cards/CardBadges.vue index 72f7315fc..1dc509a88 100644 --- a/src/components/cards/CardBadges.vue +++ b/src/components/cards/CardBadges.vue @@ -34,7 +34,9 @@ {{ checkListCheckedCount }}/{{ checkListCount }} -
+
+ {{ card.attachmentCount }} +
@@ -99,9 +101,10 @@ export default { .icon { opacity: 0.5; - padding: 12px 3px; + padding: 12px 14px; margin-right: 10px; background-position: left; + background-size: 16px; span { margin-left: 18px; } diff --git a/src/services/AttachmentApi.js b/src/services/AttachmentApi.js new file mode 100644 index 000000000..241a98daa --- /dev/null +++ b/src/services/AttachmentApi.js @@ -0,0 +1,68 @@ +/* + * @copyright Copyright (c) 2020 Jakob Röhrl + * + * @author Jakob Röhrl + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +import axios from '@nextcloud/axios' +import { generateUrl } from '@nextcloud/router' + +export class AttachmentApi { + + url(url) { + return generateUrl(`/apps/deck${url}`) + } + + async fetchAttachments(cardId) { + const response = await axios({ + method: 'GET', + url: this.url(`/cards/${cardId}/attachments`), + }) + return response.data + } + + async createAttachment({ cardId, formData }) { + try { + const response = await axios({ + method: 'POST', + url: this.url(`/cards/${cardId}/attachment`), + data: formData, + }) + return response.data + } catch (e) { + throw e + } + } + + async deleteAttachment(attachment) { + await axios({ + method: 'DELETE', + url: this.url(`/cards/${attachment.cardId}/attachment/${attachment.id}`), + }) + } + + async displayAttachment(attachment) { + const response = await axios({ + method: 'GET', + url: this.url(`/cards/${attachment.cardId}/attachment/${attachment.id}`), + }) + return response.data + } + +} diff --git a/src/store/attachment.js b/src/store/attachment.js new file mode 100644 index 000000000..ffa3c21d2 --- /dev/null +++ b/src/store/attachment.js @@ -0,0 +1,77 @@ +/* + * @copyright Copyright (c) 2020 Jakob Röhrl + * + * @author Jakob Röhrl + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +import { AttachmentApi } from './../services/AttachmentApi' +import Vue from 'vue' + +const apiClient = new AttachmentApi() + +export default { + state: { + attachments: {}, + }, + getters: { + attachmentsByCard: state => (cardId) => { + if (typeof state.attachments[cardId] === 'undefined') { + return [] + } + return state.attachments[cardId] + }, + + }, + mutations: { + createAttachment(state, { cardId, attachments }) { + if (typeof state.attachments[cardId] === 'undefined') { + Vue.set(state.attachments, cardId, attachments) + } else { + state.attachments[cardId].push(attachments) + } + }, + + deleteAttachment(state, deletedAttachment) { + const existingIndex = state.attachments[deletedAttachment.cardId].findIndex(a => a.id === deletedAttachment.id) + if (existingIndex !== -1) { + state.attachments[deletedAttachment.cardId].splice(existingIndex, 1) + } + }, + + }, + actions: { + async fetchAttachments({ commit }, cardId) { + const attachments = await apiClient.fetchAttachments(cardId) + commit('createAttachment', { cardId, attachments }) + }, + + async createAttachment({ commit }, { cardId, formData }) { + const attachments = await apiClient.createAttachment({ cardId, formData }) + commit('createAttachment', { cardId, attachments }) + commit('cardIncreaseAttachmentCount', cardId) + }, + + async deleteAttachment({ commit }, attachment) { + await apiClient.deleteAttachment(attachment) + commit('deleteAttachment', attachment) + commit('cardDecreaseAttachmentCount', attachment.cardId) + }, + + }, +} diff --git a/src/store/card.js b/src/store/card.js index 24e800f5e..65fffffc1 100644 --- a/src/store/card.js +++ b/src/store/card.js @@ -140,6 +140,20 @@ export default { Vue.set(state.cards[existingIndex], property, card[property]) } }, + cardIncreaseAttachmentCount(state, cardId) { + const existingIndex = state.cards.findIndex(_card => _card.id === cardId) + if (existingIndex !== -1) { + const existingCard = state.cards.find(_card => _card.id === cardId) + Vue.set(state.cards, existingCard.attachmentCount, existingCard.attachmentCount++) + } + }, + cardDecreaseAttachmentCount(state, cardId) { + const existingIndex = state.cards.findIndex(_card => _card.id === cardId) + if (existingIndex !== -1) { + const existingCard = state.cards.find(_card => _card.id === cardId) + Vue.set(state.cards, existingCard.attachmentCount, existingCard.attachmentCount--) + } + }, }, actions: { async addCard({ commit }, card) { diff --git a/src/store/main.js b/src/store/main.js index 56079ff0b..1fef80971 100644 --- a/src/store/main.js +++ b/src/store/main.js @@ -30,6 +30,7 @@ import stack from './stack' import card from './card' import comment from './comment' import trashbin from './trashbin' +import attachment from './attachment' Vue.use(Vuex) @@ -48,6 +49,7 @@ export default new Vuex.Store({ card, comment, trashbin, + attachment, }, strict: debug, state: { From 1e3ff41cb20cdfe4f128aa743560512ac3f6c260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20R=C3=B6hrl?= Date: Fri, 21 Feb 2020 11:12:24 +0100 Subject: [PATCH 2/9] new exception MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jakob Röhrl --- lib/Exceptions/ConflictException.php | 36 +++++++++++++++++++ lib/Service/FileService.php | 4 ++- .../card/CardSidebarTabAttachments.vue | 5 +-- src/services/AttachmentApi.js | 16 ++++----- 4 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 lib/Exceptions/ConflictException.php diff --git a/lib/Exceptions/ConflictException.php b/lib/Exceptions/ConflictException.php new file mode 100644 index 000000000..b44bff031 --- /dev/null +++ b/lib/Exceptions/ConflictException.php @@ -0,0 +1,36 @@ + + * + * @author Jakob Röhrl + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Deck; + + +class ConflictException extends \Exception { + + public function __construct($message) { + parent::__construct($message); + } + + public function getStatus() { + return 409; + } +} \ No newline at end of file diff --git a/lib/Service/FileService.php b/lib/Service/FileService.php index ec03db12c..02f3ab6bc 100644 --- a/lib/Service/FileService.php +++ b/lib/Service/FileService.php @@ -42,6 +42,7 @@ use OCP\IConfig; use OCP\IL10N; use OCP\ILogger; use OCP\IRequest; +use OCP\Deck\ConflictException; class FileService implements IAttachmentService { @@ -146,13 +147,14 @@ class FileService implements IAttachmentService { * @param Attachment $attachment * @throws NotPermittedException * @throws StatusException + * @throws ConflictException */ public function create(Attachment $attachment) { $file = $this->getUploadedFile(); $folder = $this->getFolder($attachment); $fileName = $file['name']; if ($folder->fileExists($fileName)) { - throw new StatusException('File already exists.'); + throw new ConflictException('File already exists.'); } $target = $folder->newFile($fileName); diff --git a/src/components/card/CardSidebarTabAttachments.vue b/src/components/card/CardSidebarTabAttachments.vue index ba9685fb3..8f53a2d56 100644 --- a/src/components/card/CardSidebarTabAttachments.vue +++ b/src/components/card/CardSidebarTabAttachments.vue @@ -80,14 +80,15 @@ export default { clickAddNewAttachmment() { this.$refs.localAttachments.click() }, - onLocalAttachmentSelected(e) { + async onLocalAttachmentSelected(e) { const bodyFormData = new FormData() bodyFormData.append('cardId', this.card.id) bodyFormData.append('type', 'deck_file') bodyFormData.append('file', e.target.files[0]) try { - this.$store.dispatch('createAttachment', { cardId: this.card.id, formData: bodyFormData }) + await this.$store.dispatch('createAttachment', { cardId: this.card.id, formData: bodyFormData }) } catch (e) { + console.log("doppelt") console.log(e) } }, diff --git a/src/services/AttachmentApi.js b/src/services/AttachmentApi.js index 241a98daa..751ccdca4 100644 --- a/src/services/AttachmentApi.js +++ b/src/services/AttachmentApi.js @@ -38,16 +38,12 @@ export class AttachmentApi { } async createAttachment({ cardId, formData }) { - try { - const response = await axios({ - method: 'POST', - url: this.url(`/cards/${cardId}/attachment`), - data: formData, - }) - return response.data - } catch (e) { - throw e - } + const response = await axios({ + method: 'POST', + url: this.url(`/cards/${cardId}/attachment`), + data: formData, + }) + return response.data } async deleteAttachment(attachment) { From 725f99d8b8fe002682838e6e0a29c95f8e563f4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20R=C3=B6hrl?= Date: Fri, 21 Feb 2020 12:08:24 +0100 Subject: [PATCH 3/9] update attachment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jakob Röhrl --- lib/Exceptions/ConflictException.php | 14 +++-- lib/Middleware/ExceptionMiddleware.php | 12 +++++ lib/Service/FileService.php | 5 +- .../card/CardSidebarTabAttachments.vue | 54 +++++++++++++++++-- src/services/AttachmentApi.js | 11 +++- src/store/attachment.js | 9 ++++ 6 files changed, 95 insertions(+), 10 deletions(-) diff --git a/lib/Exceptions/ConflictException.php b/lib/Exceptions/ConflictException.php index b44bff031..53c33601c 100644 --- a/lib/Exceptions/ConflictException.php +++ b/lib/Exceptions/ConflictException.php @@ -21,16 +21,24 @@ * */ -namespace OCA\Deck; +namespace OCA\Deck\Exceptions; +use OCA\Deck\StatusException; -class ConflictException extends \Exception { +class ConflictException extends StatusException { - public function __construct($message) { + private $data; + + public function __construct($message, $data = null) { parent::__construct($message); + $this->data = $data; } public function getStatus() { return 409; } + + public function getData() { + return $this->data; + } } \ No newline at end of file diff --git a/lib/Middleware/ExceptionMiddleware.php b/lib/Middleware/ExceptionMiddleware.php index a4f0610ee..416ef105a 100644 --- a/lib/Middleware/ExceptionMiddleware.php +++ b/lib/Middleware/ExceptionMiddleware.php @@ -25,6 +25,7 @@ namespace OCA\Deck\Middleware; use OCA\Deck\Controller\PageController; use OCA\Deck\StatusException; +use OCA\Deck\Exceptions\ConflictException; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Middleware; use OCP\AppFramework\Http\JSONResponse; @@ -63,6 +64,17 @@ class ExceptionMiddleware extends Middleware { * @throws \Exception */ public function afterException($controller, $methodName, \Exception $exception) { + if ($exception instanceof ConflictException) { + if ($this->config->getSystemValue('loglevel', Util::WARN) === Util::DEBUG) { + $this->logger->logException($exception); + } + return new JSONResponse([ + 'status' => $exception->getStatus(), + 'message' => $exception->getMessage(), + 'data' => $exception->getData(), + ], $exception->getStatus()); + } + if ($exception instanceof StatusException) { if ($this->config->getSystemValue('loglevel', Util::WARN) === Util::DEBUG) { $this->logger->logException($exception); diff --git a/lib/Service/FileService.php b/lib/Service/FileService.php index 02f3ab6bc..0aafd45ce 100644 --- a/lib/Service/FileService.php +++ b/lib/Service/FileService.php @@ -26,6 +26,7 @@ namespace OCA\Deck\Service; use OC\Security\CSP\ContentSecurityPolicyManager; use OCA\Deck\Db\Attachment; use OCA\Deck\StatusException; +use OCA\Deck\Exceptions\ConflictException; use OCP\AppFramework\Http\ContentSecurityPolicy; use OCP\AppFramework\Http\EmptyContentSecurityPolicy; use OCP\AppFramework\Http\FileDisplayResponse; @@ -42,7 +43,7 @@ use OCP\IConfig; use OCP\IL10N; use OCP\ILogger; use OCP\IRequest; -use OCP\Deck\ConflictException; + class FileService implements IAttachmentService { @@ -154,7 +155,7 @@ class FileService implements IAttachmentService { $folder = $this->getFolder($attachment); $fileName = $file['name']; if ($folder->fileExists($fileName)) { - throw new ConflictException('File already exists.'); + throw new ConflictException('File already exists.', $attachment); } $target = $folder->newFile($fileName); diff --git a/src/components/card/CardSidebarTabAttachments.vue b/src/components/card/CardSidebarTabAttachments.vue index 8f53a2d56..de401f96d 100644 --- a/src/components/card/CardSidebarTabAttachments.vue +++ b/src/components/card/CardSidebarTabAttachments.vue @@ -45,17 +45,38 @@ type="file" style="display: none;" @change="onLocalAttachmentSelected"> + + + + @@ -117,4 +151,16 @@ export default { height: 32px; background-size: contain; } + .modal__content { + width: 25vw; + min-width: 250px; + height: 120px; + text-align: center; + margin: 20px 20px 60px 20px; + } + + .modal__content button { + float: right; + margin: 40px 3px 3px 0; + } diff --git a/src/services/AttachmentApi.js b/src/services/AttachmentApi.js index 751ccdca4..66cab0934 100644 --- a/src/services/AttachmentApi.js +++ b/src/services/AttachmentApi.js @@ -38,7 +38,7 @@ export class AttachmentApi { } async createAttachment({ cardId, formData }) { - const response = await axios({ + const response = await axios({ method: 'POST', url: this.url(`/cards/${cardId}/attachment`), data: formData, @@ -46,6 +46,15 @@ export class AttachmentApi { return response.data } + async updateAttachment({ cardId, attachmentId, formData }) { + const response = await axios({ + method: 'PUT', + url: this.url(`/cards/${cardId}/attachment/${attachmentId}`), + data: formData, + }) + return response.data + } + async deleteAttachment(attachment) { await axios({ method: 'DELETE', diff --git a/src/store/attachment.js b/src/store/attachment.js index ffa3c21d2..f8651f42a 100644 --- a/src/store/attachment.js +++ b/src/store/attachment.js @@ -47,6 +47,10 @@ export default { } }, + updateAttachment(state, { cardId, attachment }) { + Vue.set(state.attachments, cardId, attachment) + }, + deleteAttachment(state, deletedAttachment) { const existingIndex = state.attachments[deletedAttachment.cardId].findIndex(a => a.id === deletedAttachment.id) if (existingIndex !== -1) { @@ -67,6 +71,11 @@ export default { commit('cardIncreaseAttachmentCount', cardId) }, + async updateAttachment({ commit }, { cardId, attachmentId, formData }) { + const attachment = await apiClient.updateAttachment({ cardId, attachmentId, formData }) + commit('updateAttachment', { cardId, attachment }) + }, + async deleteAttachment({ commit }, attachment) { await apiClient.deleteAttachment(attachment) commit('deleteAttachment', attachment) From d27a5ac9ba952931f3f3acef013ac33094f97448 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20R=C3=B6hrl?= Date: Wed, 4 Mar 2020 12:59:45 +0100 Subject: [PATCH 4/9] override attachment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jakob Röhrl --- lib/Controller/AttachmentApiController.php | 2 +- lib/Controller/AttachmentController.php | 2 +- lib/Db/AttachmentMapper.php | 16 ++ lib/Service/FileService.php | 7 +- package-lock.json | 21 +++ package.json | 1 + .../card/CardSidebarTabAttachments.vue | 173 +++++++++++++++--- src/services/AttachmentApi.js | 13 +- src/store/attachment.js | 32 +++- 9 files changed, 228 insertions(+), 39 deletions(-) diff --git a/lib/Controller/AttachmentApiController.php b/lib/Controller/AttachmentApiController.php index e2c044e1a..cf027c064 100644 --- a/lib/Controller/AttachmentApiController.php +++ b/lib/Controller/AttachmentApiController.php @@ -45,7 +45,7 @@ class AttachmentApiController extends ApiController { * */ public function getAll() { - $attachment = $this->attachmentService->findAll($this->request->getParam('cardId')); + $attachment = $this->attachmentService->findAll($this->request->getParam('cardId'), true); return new DataResponse($attachment, HTTP::STATUS_OK); } diff --git a/lib/Controller/AttachmentController.php b/lib/Controller/AttachmentController.php index ea31f194a..d595dc2b8 100644 --- a/lib/Controller/AttachmentController.php +++ b/lib/Controller/AttachmentController.php @@ -42,7 +42,7 @@ class AttachmentController extends Controller { * @NoAdminRequired */ public function getAll($cardId) { - return $this->attachmentService->findAll($cardId); + return $this->attachmentService->findAll($cardId, true); } /** diff --git a/lib/Db/AttachmentMapper.php b/lib/Db/AttachmentMapper.php index 2ccae3be8..00a7c61d7 100644 --- a/lib/Db/AttachmentMapper.php +++ b/lib/Db/AttachmentMapper.php @@ -81,6 +81,22 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper { return $this->mapRowToEntity($row); } + public function findByData($cardId, $data) { + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from('deck_attachment') + ->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT))) + ->andWhere($qb->expr()->eq('data', $qb->createNamedParameter($data, IQueryBuilder::PARAM_STR))); + $cursor = $qb->execute(); + $row = $cursor->fetch(PDO::FETCH_ASSOC); + if($row === false) { + $cursor->closeCursor(); + throw new DoesNotExistException('Did expect one result but found none when executing' . $qb); + } + $cursor->closeCursor(); + return $this->mapRowToEntity($row); + } + /** * Find all attachments for a card * diff --git a/lib/Service/FileService.php b/lib/Service/FileService.php index 0aafd45ce..1e4216591 100644 --- a/lib/Service/FileService.php +++ b/lib/Service/FileService.php @@ -25,6 +25,7 @@ namespace OCA\Deck\Service; use OC\Security\CSP\ContentSecurityPolicyManager; use OCA\Deck\Db\Attachment; +use OCA\Deck\Db\AttachmentMapper; use OCA\Deck\StatusException; use OCA\Deck\Exceptions\ConflictException; use OCP\AppFramework\Http\ContentSecurityPolicy; @@ -53,6 +54,7 @@ class FileService implements IAttachmentService { private $logger; private $rootFolder; private $config; + private $attachmentMapper; public function __construct( IL10N $l10n, @@ -60,7 +62,8 @@ class FileService implements IAttachmentService { IRequest $request, ILogger $logger, IRootFolder $rootFolder, - IConfig $config + IConfig $config, + AttachmentMapper $attachmentMapper ) { $this->l10n = $l10n; $this->appData = $appData; @@ -68,6 +71,7 @@ class FileService implements IAttachmentService { $this->logger = $logger; $this->rootFolder = $rootFolder; $this->config = $config; + $this->attachmentMapper = $attachmentMapper; } /** @@ -155,6 +159,7 @@ class FileService implements IAttachmentService { $folder = $this->getFolder($attachment); $fileName = $file['name']; if ($folder->fileExists($fileName)) { + $attachment = $this->attachmentMapper->findByData($attachment->getCardId(), $fileName); throw new ConflictException('File already exists.', $attachment); } diff --git a/package-lock.json b/package-lock.json index eeda19e46..36ff598c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3442,6 +3442,22 @@ "resolved": "https://registry.npmjs.org/@nextcloud/browserslist-config/-/browserslist-config-1.0.0.tgz", "integrity": "sha512-f+sKpdLZXkODV+OY39K1M+Spmd4RgxmtEXmNn4Bviv4R7uBFHXuw+JX9ZdfDeOryfHjJ/TRQxQEp0GMpBwZFUw==" }, + "@nextcloud/dialogs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@nextcloud/dialogs/-/dialogs-1.2.1.tgz", + "integrity": "sha512-v+nnlqdOUpqumD51Fkjo1V9W/xImW7GcY29Iq1ErSDCmkhrS4pk9YDYrZO86teey+pT5nZ0gdGAtiU+LNFQgzw==", + "requires": { + "core-js": "3.6.4", + "toastify-js": "^1.6.2" + }, + "dependencies": { + "core-js": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", + "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==" + } + } + }, "@nextcloud/event-bus": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@nextcloud/event-bus/-/event-bus-1.1.2.tgz", @@ -17828,6 +17844,11 @@ } } }, + "toastify-js": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.7.0.tgz", + "integrity": "sha512-GmPy4zJ/ulCfmCHlfCtgcB+K2xhx2AXW3T/ZZOSjyjaIGevhz+uvR8HSCTay/wBq4tt2mUnBqlObP1sSWGlsnQ==" + }, "tough-cookie": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", diff --git a/package.json b/package.json index f6f2c22d8..2888b99a7 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@nextcloud/auth": "^1.2.1", "@nextcloud/axios": "^1.3.1", "@nextcloud/l10n": "^1.1.0", + "@nextcloud/dialogs": "^1.2.1", "@nextcloud/moment": "^1.1.0", "@nextcloud/router": "^1.0.0", "@nextcloud/vue": "^1.4.0", diff --git a/src/components/card/CardSidebarTabAttachments.vue b/src/components/card/CardSidebarTabAttachments.vue index de401f96d..3ebc600f2 100644 --- a/src/components/card/CardSidebarTabAttachments.vue +++ b/src/components/card/CardSidebarTabAttachments.vue @@ -22,22 +22,6 @@