diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c577af5..d08b71a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ All notable changes to this project will be documented in this file. +## [0.3.6 - 2023-06-19] + +[`cloud_py_api`](https://github.com/cloud-py-api/cloud_py_api) is **required** to be installed +(or updated) and enabled first. + +### Added + +- Nextcloud Hub 5 (27) support +- Option to delete all duplicates in group except the largest one + +### Updated + +- Updated packages +- Updated l10n + ## [0.3.5 - 2023-03-23] [`cloud_py_api`](https://github.com/cloud-py-api/cloud_py_api) is **required** to be installed diff --git a/README.md b/README.md index 6d8935b3..5263123e 100644 --- a/README.md +++ b/README.md @@ -35,14 +35,3 @@ Starting from 0.2.0 version MediaDC is only included in Nextcloud v25 and higher * [Andrey Borysenko](https://github.com/andrey18106) * [Alexander Piskun](https://github.com/bigcat88) -## Support - -You can support us in several ways: - -- ⭐ Star our work (it really motivates) -- ❗ Create an Issue or feature request (bring to us an excellent idea) -- πŸ’ Resolve some Issue or create a Pull Request (contribute to this project) -- πŸͺ™ Donate with any amount with one of the links below (fund this project) - -[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/donate?hosted_button_id=H5PLJJMWLDNJQ) -[![Liberapay](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/cloud_py_api/donate) diff --git a/appinfo/info.xml b/appinfo/info.xml index 05b770c7..4e03c81d 100755 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -18,21 +18,9 @@ This app allows to find duplicate or similar πŸ“ΈπŸ“Ή photos and videos * **Save your time and cloud space** The title says all... Quick start guide and further information in our [Wiki](https://github.com/cloud-py-api/mediadc/wiki). - -### Support - -You can support us in several ways: - -- ⭐ Star our work (it really motivates) -- ❗ Create an Issue or feature request (bring to us an excellent idea) -- πŸ’ Resolve some Issue or create a Pull Request (contribute to this project) -- πŸͺ™ Donate with any amount with one of the links below (fund this project) - -[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/donate?hosted_button_id=H5PLJJMWLDNJQ) -[![Liberapay](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/cloud_py_api/donate) ]]> - 0.3.5 + 0.3.6 agpl Andrey Borysenko Alexander Piskun @@ -56,7 +44,7 @@ You can support us in several ways: https://raw.githubusercontent.com/cloud-py-api/mediadc/main/screenshots/mediadc_filesplugin.png - + OCA\MediaDC\BackgroundJob\CollectorCleanupJob diff --git a/appinfo/routes.php b/appinfo/routes.php index 4c4c45da..8c4a0857 100755 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -63,6 +63,7 @@ // BATCH ACTIONS API ['name' => 'collector#removeTaskDetailGroups', 'url' => '/api/v1/tasks/{taskId}/details/remove', 'verb' => 'POST'], + ['name' => 'collector#deleteTaskDetailGroupsFiles', 'url' => '/api/v1/tasks/{taskId}/details/delete', 'verb' => 'POST'], ['name' => 'collector#removeTaskDetailFiles', 'url' => '/api/v1/tasks/{taskId}/files/{groupId}/remove', 'verb' => 'POST'], ['name' => 'collector#deleteTaskDetailFiles', 'url' => '/api/v1/tasks/{taskId}/files/{groupId}/delete', 'verb' => 'POST'], ] diff --git a/css/style.css b/css/style.css index ccd04d45..1044dafd 100755 --- a/css/style.css +++ b/css/style.css @@ -1,7 +1,7 @@ /** * @copyright Copyright (c) 2022 Andrey Borysenko * - * @copyright opyright (c) 2022 Alexander Piskun + * @copyright Copyright (c) 2022 Alexander Piskun * * @author 2022 Andrey Borysenko * diff --git a/lib/Controller/CollectorController.php b/lib/Controller/CollectorController.php index 6a0e4869..1fe5df36 100755 --- a/lib/Controller/CollectorController.php +++ b/lib/Controller/CollectorController.php @@ -28,6 +28,7 @@ namespace OCA\MediaDC\Controller; +use Exception; use OCP\IRequest; use OCP\AppFramework\Controller; use OCP\AppFramework\Http; @@ -201,15 +202,17 @@ public function getTaskInfo(int $taskId): JSONResponse { * @param int $taskId target task id * @param string $format export file format (xml, json) * - * @return DataDownloadResponse + * @throws Exception + * @return DataDownloadResponse|null */ - public function getTaskResultsExport(int $taskId, string $format): DataDownloadResponse { + public function getTaskResultsExport(int $taskId, string $format): ?DataDownloadResponse { if (in_array($format, ['xml', 'json'])) { $export = $this->service->exportTaskResults(intval($taskId), $format); if ($export) { return new DataDownloadResponse($export['data'], $export['filename'], $export['contentType']); } } + throw new Exception('Bad request. Requested export format is not supported.'); } /** @@ -330,6 +333,18 @@ public function removeTaskDetailGroups(int $taskId, array $groupIds): JSONRespon } } + /** + * @NoAdminRequired + * @NoCSRFRequired + */ + public function deleteTaskDetailGroupsFiles(int $taskId, array $groupIds): JSONResponse { + if ($taskId && $groupIds) { + return new JSONResponse($this->service->deleteTaskDetailGroupsFiles($taskId, $groupIds), Http::STATUS_OK); + } else { + return new JSONResponse(['success' => false], Http::STATUS_OK); + } + } + /** * @NoAdminRequired * @NoCSRFRequired diff --git a/lib/Db/CollectorTaskDetailMapper.php b/lib/Db/CollectorTaskDetailMapper.php index 9f9a25cf..0a4203d1 100755 --- a/lib/Db/CollectorTaskDetailMapper.php +++ b/lib/Db/CollectorTaskDetailMapper.php @@ -115,6 +115,22 @@ public function findAllByGroupId(int $taskId, int $groupId): array { }, $qb->executeQuery()->fetchAll()); } + public function findAllByGroupIdSize(int $taskId, int $groupId): array { + $qb = $this->db->getQueryBuilder(); + $qb->select( + 'mdc_t_d.fileid', + ) + ->from($this->tableName, 'mdc_t_d') + ->innerJoin('mdc_t_d', 'filecache', 'f', $qb->expr()->eq('mdc_t_d.fileid', 'f.fileid')) + ->where($qb->expr()->eq('mdc_t_d.task_id', $qb->createNamedParameter($taskId, IQueryBuilder::PARAM_INT))) + ->andWhere($qb->expr()->eq('mdc_t_d.group_id', $qb->createNamedParameter($groupId, IQueryBuilder::PARAM_INT))) + ->orderBy('mdc_t_d.group_id', 'ASC') + ->addOrderBy('f.size', 'DESC'); + return array_map(function ($row) { + return intval($row['fileid']); + }, $qb->executeQuery()->fetchAll()); + } + /** * @param int $taskId * @param int $limit diff --git a/lib/Service/CollectorService.php b/lib/Service/CollectorService.php index 52c2280e..d6b40a35 100755 --- a/lib/Service/CollectorService.php +++ b/lib/Service/CollectorService.php @@ -29,6 +29,7 @@ namespace OCA\MediaDC\Service; use DOMDocument; +use OCA\Files_Sharing\SharedStorage; use OCP\Files\File; use OCP\Files\Node; use OCP\Files\Folder; @@ -768,7 +769,7 @@ public function deleteTaskDetailFile($taskId, $groupId, $fileid, $removeIfOneLef } catch (NotPermittedException | NotFoundException $e) { return [ 'success' => false, - 'not_permited' => $e instanceof NotPermittedException, + 'not_permitted' => $e instanceof NotPermittedException, 'not_found' => $e instanceof NotFoundException, ]; } @@ -780,7 +781,7 @@ public function deleteTaskDetailFile($taskId, $groupId, $fileid, $removeIfOneLef } /** - * Remove ColectorTaskDetail groups with deleting coresponding files + * Remove CollectorTaskDetail groups with deleting corresponding files * * @param int $taskId * @param array $groupIds @@ -801,7 +802,45 @@ public function removeTaskDetailGroups(int $taskId, array $groupIds) { } /** - * Delete ColectorTaskDetail groups with deleting coresponding files + * Delete all CollectorTaskDetail group files except one largest + * + * @param int $taskId + * @param array $groupIds + * + * @return array + */ + public function deleteTaskDetailGroupsFiles(int $taskId, array $groupIds) { + $result = []; + foreach ($groupIds as $groupId) { + $groupFiles = $this->tasksDetailsMapper->findAllByGroupIdSize($taskId, $groupId); + $largestFileId = array_splice($groupFiles, 0, 1)[0]; + $this->tasksDetailsMapper->deleteGroupFiles($taskId, $groupId, [$largestFileId]); + $this->markResolvedPhoto($largestFileId, true); + $this->markResolvedVideo($largestFileId, true); + $collectorTask = null; + foreach ($groupFiles as $fileId) { + $deleteFileResult = $this->deleteTaskDetailFile($taskId, $groupId, $fileId, false); + if ($deleteFileResult['success']) { + $collectorTask = $deleteFileResult['task']; + $fileIdIndex = array_search($fileId, $groupFiles); + if ($fileIdIndex !== false) { + array_splice($groupFiles, $fileIdIndex, 1)[0]; + } + } + } + if (count($groupFiles) === 0) { + $result[] = intval($groupId); + } + } + return [ + 'success' => count($result) === count($groupIds), + 'removedGroupIds' => $result, + 'task' => $collectorTask, + ]; + } + + /** + * Delete CollectorTaskDetail groups with deleting corresponding files * * @param int $taskId * @param int $groupId @@ -813,7 +852,7 @@ public function deleteTaskDetailFiles(int $taskId, int $groupId, array $fileIds) $result = []; $errors = [ 'locked' => [], - 'not_permited' => [], + 'not_permitted' => [], 'not_found' => [], ]; $groupFiles = $this->tasksDetailsMapper->findAllByGroupId($taskId, $groupId); @@ -828,8 +867,8 @@ public function deleteTaskDetailFiles(int $taskId, int $groupId, array $fileIds) if (isset($deleteFileResult['locked']) && $deleteFileResult['locked']) { array_push($errors['locked'], $fileId); } - if (isset($deleteFileResult['not_permited']) && $deleteFileResult['not_permited']) { - array_push($errors['not_permited'], $fileId); + if (isset($deleteFileResult['not_permitted']) && $deleteFileResult['not_permitted']) { + array_push($errors['not_permitted'], $fileId); } if (isset($deleteFileResult['not_found']) && $deleteFileResult['not_found']) { array_push($errors['not_found'], $fileId); @@ -855,7 +894,7 @@ public function deleteTaskDetailFiles(int $taskId, int $groupId, array $fileIds) } /** - * Remove ColectorTaskDetail groups with deleting coresponding files + * Remove CollectorTaskDetail groups with deleting corresponding files * * @param int $taskId * @param int $groupId diff --git a/lib/Settings/AdminSettings.php b/lib/Settings/AdminSettings.php index e3ba4c03..c514e42e 100755 --- a/lib/Settings/AdminSettings.php +++ b/lib/Settings/AdminSettings.php @@ -29,17 +29,33 @@ namespace OCA\MediaDC\Settings; use OCA\MediaDC\AppInfo\Application; +use OCA\MediaDC\Db\SettingMapper; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IInitialState; use OCP\Settings\ISettings; class AdminSettings implements ISettings { - public function __construct() { + /** @var SettingMapper */ + private $settingMapper; + + /** @var IInitialState */ + private $initialState; + + public function __construct( + IInitialState $initialState, + SettingMapper $settingMapper + ) { + $this->settingMapper = $settingMapper; + $this->initialState = $initialState; } /** * @return TemplateResponse */ public function getForm() { + $settings = $this->settingMapper->findAll(); + $this->initialState->provideInitialState('settings', $settings); + return new TemplateResponse(Application::APP_ID, 'admin'); } diff --git a/package-lock.json b/package-lock.json index 32a7b3d8..11c60b3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,23 +1,23 @@ { "name": "mediadc", - "version": "0.3.5", + "version": "0.3.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "mediadc", - "version": "0.3.5", + "version": "0.3.6", "license": "agpl", "dependencies": { - "@nextcloud/auth": "^2.0.0", + "@nextcloud/auth": "^2.1.0", "@nextcloud/axios": "^2.3.0", "@nextcloud/dialogs": "^4.0.1", - "@nextcloud/event-bus": "^3.0.2", + "@nextcloud/event-bus": "^3.1.0", "@nextcloud/initial-state": "^2.0.0", "@nextcloud/l10n": "^2.1.0", "@nextcloud/moment": "^1.2.1", - "@nextcloud/router": "^2.0.1", - "@nextcloud/vue": "^7.9.0", + "@nextcloud/router": "^2.1.2", + "@nextcloud/vue": "^7.12.0", "vue": "^2.7.14", "vue-material-design-icons": "^5.2.0", "vue-router": "^3.5.3", @@ -2081,11 +2081,15 @@ } }, "node_modules/@nextcloud/auth": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nextcloud/auth/-/auth-2.0.0.tgz", - "integrity": "sha512-v8K8tvjkOsGt1+gKydVeMiEwWLXlfPWSptXnMqP21Xd6pFAQxNuNNCY679XKU4MNaKzpZqLstCCxv/KrjeQv8A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@nextcloud/auth/-/auth-2.1.0.tgz", + "integrity": "sha512-wf5xQrWQu6fkl3MGegVdyR5mh/EdSQKJByH3m2Url2K2xbML9Y4Y7LAff9jjJAcMt2MkzzJEM463ZBbgTqs0lg==", "dependencies": { - "@nextcloud/event-bus": "^3.0.0" + "@nextcloud/event-bus": "^3.1.0" + }, + "engines": { + "node": "^16.0.0", + "npm": "^7.0.0 || ^8.0.0" } }, "node_modules/@nextcloud/axios": { @@ -2236,11 +2240,11 @@ } }, "node_modules/@nextcloud/event-bus": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@nextcloud/event-bus/-/event-bus-3.0.2.tgz", - "integrity": "sha512-svXCZa4UkoZKsBiGzTi0cVcbPFUOhCm7pMKjGumRwBvHywX+8by478IQ8Grw75PFHxajMJZ0KrOTTM8WnzzEAw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@nextcloud/event-bus/-/event-bus-3.1.0.tgz", + "integrity": "sha512-purXQsXbhbmpcDsbDuR0i7vwUgOsqnIUa7QAD3lV/UZUkUT94SmxBM5LgQ8iV8TQBWWleEwQHy5kYfHeTGF9wg==", "dependencies": { - "semver": "^7.3.7" + "semver": "^7.5.1" }, "engines": { "node": "^16.0.0", @@ -2259,9 +2263,9 @@ } }, "node_modules/@nextcloud/event-bus/node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", + "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -2378,10 +2382,11 @@ } }, "node_modules/@nextcloud/router": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-2.0.1.tgz", - "integrity": "sha512-qLRxTjZS6y9NUPmU6X3Ega5qHPeEx4kCgqwo0I6Y9wV71EGGi9zPnWDsqmmmJj8RkDp30jcfGNWCTwbPAebTDA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-2.1.2.tgz", + "integrity": "sha512-Jj5fgjeHT1vVIgOyUGOeHfwk2KgaO77QGfqZAT6GWXvpAsN0mkqwljkg4FkHrQRouYqCE4VnJ5o8/w0DAN89tA==", "dependencies": { + "@nextcloud/typings": "^1.0.0", "core-js": "^3.6.4" }, "engines": { @@ -2389,6 +2394,28 @@ "npm": "^7.0.0 || ^8.0.0" } }, + "node_modules/@nextcloud/router/node_modules/@nextcloud/typings": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@nextcloud/typings/-/typings-1.7.0.tgz", + "integrity": "sha512-fK1i09FYTfSUBdXswyiCr8ng5MwdWjEWOF7hRvNvq5i+XFUSmGjSsRmpQZFM2AONroHqGGQBkvQqpONUshFBJQ==", + "dependencies": { + "@types/jquery": "3.5.16", + "vue": "^2.7.14", + "vue-router": "<4" + }, + "engines": { + "node": "^16.0.0", + "npm": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@nextcloud/router/node_modules/@types/jquery": { + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.16.tgz", + "integrity": "sha512-bsI7y4ZgeMkmpG9OM710RRzDFp+w4P1RGiIt30C1mSBT+ExCleeh4HObwgArnDFELmRrOpXgSYN9VF1hj+f1lw==", + "dependencies": { + "@types/sizzle": "*" + } + }, "node_modules/@nextcloud/stylelint-config": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@nextcloud/stylelint-config/-/stylelint-config-2.3.0.tgz", @@ -2413,9 +2440,9 @@ } }, "node_modules/@nextcloud/vue": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-7.9.0.tgz", - "integrity": "sha512-ZT2/xuQNzA3HiBcZnqtLNidhyi/HzWL9IIf/l3ADlYTl32es2E32EC87nX4GKML435+apadb/OYCDSdocHqmcg==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-7.12.0.tgz", + "integrity": "sha512-f7x3YFBzc/mt27F7AU+ITLmGCwRpVM0aVTF+DxjaOdelQNTYZBuFJCCOk6nC+x+gg/KWLIxeWm/NWDxToCstbQ==", "dependencies": { "@floating-ui/dom": "^1.1.0", "@nextcloud/auth": "^2.0.0", @@ -2431,7 +2458,7 @@ "@nextcloud/router": "^2.0.0", "@nextcloud/vue-select": "^3.21.2", "@skjnldsv/sanitize-svg": "^1.0.2", - "@vueuse/components": "^9.13.0", + "@vueuse/components": "^10.0.2", "clone": "^2.1.2", "debounce": "1.2.1", "emoji-mart-vue-fast": "^12.0.1", @@ -2863,6 +2890,11 @@ "@types/node": "*" } }, + "node_modules/@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==" + }, "node_modules/@types/sockjs": { "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", @@ -2879,9 +2911,9 @@ "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" }, "node_modules/@types/web-bluetooth": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", - "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz", + "integrity": "sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA==" }, "node_modules/@types/ws": { "version": "8.5.3", @@ -3312,19 +3344,19 @@ } }, "node_modules/@vueuse/components": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-9.13.0.tgz", - "integrity": "sha512-UJ8PjQ4SGb2rsVIy9vhEc6aCu+3+2cc+xEfGNX8/M1NKIuL2Vo6c2Kc2fYFaRzWZkP8HWXu+IcwvnAzL44IEFA==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-10.1.2.tgz", + "integrity": "sha512-HlYFYCg3twMhnQgPS4/muz8XIYKViFVKnpL0Xtw5+9ib2gtWvu1Qu7hj6kDMDtOIw1CnNRsUbMLiNI+LXkxSSQ==", "dependencies": { - "@vueuse/core": "9.13.0", - "@vueuse/shared": "9.13.0", - "vue-demi": "*" + "@vueuse/core": "10.1.2", + "@vueuse/shared": "10.1.2", + "vue-demi": ">=0.14.0" } }, "node_modules/@vueuse/components/node_modules/vue-demi": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", - "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", "hasInstallScript": true, "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", @@ -3347,23 +3379,23 @@ } }, "node_modules/@vueuse/core": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", - "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.1.2.tgz", + "integrity": "sha512-roNn8WuerI56A5uiTyF/TEYX0Y+VKlhZAF94unUfdhbDUI+NfwQMn4FUnUscIRUhv3344qvAghopU4bzLPNFlA==", "dependencies": { - "@types/web-bluetooth": "^0.0.16", - "@vueuse/metadata": "9.13.0", - "@vueuse/shared": "9.13.0", - "vue-demi": "*" + "@types/web-bluetooth": "^0.0.17", + "@vueuse/metadata": "10.1.2", + "@vueuse/shared": "10.1.2", + "vue-demi": ">=0.14.0" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/core/node_modules/vue-demi": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", - "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", "hasInstallScript": true, "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", @@ -3386,28 +3418,28 @@ } }, "node_modules/@vueuse/metadata": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", - "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.1.2.tgz", + "integrity": "sha512-3mc5BqN9aU2SqBeBuWE7ne4OtXHoHKggNgxZR2K+zIW4YLsy6xoZ4/9vErQs6tvoKDX6QAqm3lvsrv0mczAwIQ==", "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/shared": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", - "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.1.2.tgz", + "integrity": "sha512-1uoUTPBlgyscK9v6ScGeVYDDzlPSFXBlxuK7SfrDGyUTBiznb3mNceqhwvZHjtDRELZEN79V5uWPTF1VDV8svA==", "dependencies": { - "vue-demi": "*" + "vue-demi": ">=0.14.0" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/shared/node_modules/vue-demi": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", - "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", "hasInstallScript": true, "bin": { "vue-demi-fix": "bin/vue-demi-fix.js", @@ -6855,18 +6887,24 @@ "peer": true }, "node_modules/fast-xml-parser": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz", - "integrity": "sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.4.tgz", + "integrity": "sha512-fbfMDvgBNIdDJLdLOwacjFAPYt67tr31H9ZhWSm45CDAxvd0I6WTlSOUo7K2P/K5sA5JgMKG64PI3DMcaFdWpQ==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], "dependencies": { - "strnum": "^1.0.4" + "strnum": "^1.0.5" }, "bin": { - "xml2js": "cli.js" - }, - "funding": { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" + "fxparser": "src/cli/cli.js" } }, "node_modules/fastest-levenshtein": { @@ -8260,11 +8298,11 @@ } }, "node_modules/is-svg": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-4.3.2.tgz", - "integrity": "sha512-mM90duy00JGMyjqIVHu9gNTjywdZV+8qNasX8cm/EEYZ53PHDgajvbBwNVvty5dwSAxLUD3p3bdo+7sR/UMrpw==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-4.4.0.tgz", + "integrity": "sha512-v+AgVwiK5DsGtT9ng+m4mClp6zDAmwrW8nZi6Gg15qzvBnRWWdfWA1TGaXyCDnWq5g5asofIgMVl3PjKxvk1ug==", "dependencies": { - "fast-xml-parser": "^3.19.0" + "fast-xml-parser": "^4.1.3" }, "engines": { "node": ">=6" @@ -15251,11 +15289,11 @@ } }, "@nextcloud/auth": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@nextcloud/auth/-/auth-2.0.0.tgz", - "integrity": "sha512-v8K8tvjkOsGt1+gKydVeMiEwWLXlfPWSptXnMqP21Xd6pFAQxNuNNCY679XKU4MNaKzpZqLstCCxv/KrjeQv8A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@nextcloud/auth/-/auth-2.1.0.tgz", + "integrity": "sha512-wf5xQrWQu6fkl3MGegVdyR5mh/EdSQKJByH3m2Url2K2xbML9Y4Y7LAff9jjJAcMt2MkzzJEM463ZBbgTqs0lg==", "requires": { - "@nextcloud/event-bus": "^3.0.0" + "@nextcloud/event-bus": "^3.1.0" } }, "@nextcloud/axios": { @@ -15362,11 +15400,11 @@ } }, "@nextcloud/event-bus": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@nextcloud/event-bus/-/event-bus-3.0.2.tgz", - "integrity": "sha512-svXCZa4UkoZKsBiGzTi0cVcbPFUOhCm7pMKjGumRwBvHywX+8by478IQ8Grw75PFHxajMJZ0KrOTTM8WnzzEAw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@nextcloud/event-bus/-/event-bus-3.1.0.tgz", + "integrity": "sha512-purXQsXbhbmpcDsbDuR0i7vwUgOsqnIUa7QAD3lV/UZUkUT94SmxBM5LgQ8iV8TQBWWleEwQHy5kYfHeTGF9wg==", "requires": { - "semver": "^7.3.7" + "semver": "^7.5.1" }, "dependencies": { "lru-cache": { @@ -15378,9 +15416,9 @@ } }, "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.2.tgz", + "integrity": "sha512-SoftuTROv/cRjCze/scjGyiDtcUyxw1rgYQSZY7XTmtR5hX+dm76iDbTH8TkLPHCQmlbQVSSbNZCPM2hb0knnQ==", "requires": { "lru-cache": "^6.0.0" } @@ -15484,11 +15522,32 @@ } }, "@nextcloud/router": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-2.0.1.tgz", - "integrity": "sha512-qLRxTjZS6y9NUPmU6X3Ega5qHPeEx4kCgqwo0I6Y9wV71EGGi9zPnWDsqmmmJj8RkDp30jcfGNWCTwbPAebTDA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@nextcloud/router/-/router-2.1.2.tgz", + "integrity": "sha512-Jj5fgjeHT1vVIgOyUGOeHfwk2KgaO77QGfqZAT6GWXvpAsN0mkqwljkg4FkHrQRouYqCE4VnJ5o8/w0DAN89tA==", "requires": { + "@nextcloud/typings": "^1.0.0", "core-js": "^3.6.4" + }, + "dependencies": { + "@nextcloud/typings": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@nextcloud/typings/-/typings-1.7.0.tgz", + "integrity": "sha512-fK1i09FYTfSUBdXswyiCr8ng5MwdWjEWOF7hRvNvq5i+XFUSmGjSsRmpQZFM2AONroHqGGQBkvQqpONUshFBJQ==", + "requires": { + "@types/jquery": "3.5.16", + "vue": "^2.7.14", + "vue-router": "<4" + } + }, + "@types/jquery": { + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.16.tgz", + "integrity": "sha512-bsI7y4ZgeMkmpG9OM710RRzDFp+w4P1RGiIt30C1mSBT+ExCleeh4HObwgArnDFELmRrOpXgSYN9VF1hj+f1lw==", + "requires": { + "@types/sizzle": "*" + } + } } }, "@nextcloud/stylelint-config": { @@ -15507,9 +15566,9 @@ } }, "@nextcloud/vue": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-7.9.0.tgz", - "integrity": "sha512-ZT2/xuQNzA3HiBcZnqtLNidhyi/HzWL9IIf/l3ADlYTl32es2E32EC87nX4GKML435+apadb/OYCDSdocHqmcg==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-7.12.0.tgz", + "integrity": "sha512-f7x3YFBzc/mt27F7AU+ITLmGCwRpVM0aVTF+DxjaOdelQNTYZBuFJCCOk6nC+x+gg/KWLIxeWm/NWDxToCstbQ==", "requires": { "@floating-ui/dom": "^1.1.0", "@nextcloud/auth": "^2.0.0", @@ -15525,7 +15584,7 @@ "@nextcloud/router": "^2.0.0", "@nextcloud/vue-select": "^3.21.2", "@skjnldsv/sanitize-svg": "^1.0.2", - "@vueuse/components": "^9.13.0", + "@vueuse/components": "^10.0.2", "clone": "^2.1.2", "debounce": "1.2.1", "emoji-mart-vue-fast": "^12.0.1", @@ -15913,6 +15972,11 @@ "@types/node": "*" } }, + "@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==" + }, "@types/sockjs": { "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", @@ -15929,9 +15993,9 @@ "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==" }, "@types/web-bluetooth": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", - "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==" + "version": "0.0.17", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz", + "integrity": "sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA==" }, "@types/ws": { "version": "8.5.3", @@ -16227,59 +16291,59 @@ } }, "@vueuse/components": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-9.13.0.tgz", - "integrity": "sha512-UJ8PjQ4SGb2rsVIy9vhEc6aCu+3+2cc+xEfGNX8/M1NKIuL2Vo6c2Kc2fYFaRzWZkP8HWXu+IcwvnAzL44IEFA==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-10.1.2.tgz", + "integrity": "sha512-HlYFYCg3twMhnQgPS4/muz8XIYKViFVKnpL0Xtw5+9ib2gtWvu1Qu7hj6kDMDtOIw1CnNRsUbMLiNI+LXkxSSQ==", "requires": { - "@vueuse/core": "9.13.0", - "@vueuse/shared": "9.13.0", - "vue-demi": "*" + "@vueuse/core": "10.1.2", + "@vueuse/shared": "10.1.2", + "vue-demi": ">=0.14.0" }, "dependencies": { "vue-demi": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", - "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", "requires": {} } } }, "@vueuse/core": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", - "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.1.2.tgz", + "integrity": "sha512-roNn8WuerI56A5uiTyF/TEYX0Y+VKlhZAF94unUfdhbDUI+NfwQMn4FUnUscIRUhv3344qvAghopU4bzLPNFlA==", "requires": { - "@types/web-bluetooth": "^0.0.16", - "@vueuse/metadata": "9.13.0", - "@vueuse/shared": "9.13.0", - "vue-demi": "*" + "@types/web-bluetooth": "^0.0.17", + "@vueuse/metadata": "10.1.2", + "@vueuse/shared": "10.1.2", + "vue-demi": ">=0.14.0" }, "dependencies": { "vue-demi": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", - "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", "requires": {} } } }, "@vueuse/metadata": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", - "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==" + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.1.2.tgz", + "integrity": "sha512-3mc5BqN9aU2SqBeBuWE7ne4OtXHoHKggNgxZR2K+zIW4YLsy6xoZ4/9vErQs6tvoKDX6QAqm3lvsrv0mczAwIQ==" }, "@vueuse/shared": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", - "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.1.2.tgz", + "integrity": "sha512-1uoUTPBlgyscK9v6ScGeVYDDzlPSFXBlxuK7SfrDGyUTBiznb3mNceqhwvZHjtDRELZEN79V5uWPTF1VDV8svA==", "requires": { - "vue-demi": "*" + "vue-demi": ">=0.14.0" }, "dependencies": { "vue-demi": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", - "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", "requires": {} } } @@ -18957,11 +19021,11 @@ "peer": true }, "fast-xml-parser": { - "version": "3.21.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz", - "integrity": "sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.4.tgz", + "integrity": "sha512-fbfMDvgBNIdDJLdLOwacjFAPYt67tr31H9ZhWSm45CDAxvd0I6WTlSOUo7K2P/K5sA5JgMKG64PI3DMcaFdWpQ==", "requires": { - "strnum": "^1.0.4" + "strnum": "^1.0.5" } }, "fastest-levenshtein": { @@ -19972,11 +20036,11 @@ } }, "is-svg": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-4.3.2.tgz", - "integrity": "sha512-mM90duy00JGMyjqIVHu9gNTjywdZV+8qNasX8cm/EEYZ53PHDgajvbBwNVvty5dwSAxLUD3p3bdo+7sR/UMrpw==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-4.4.0.tgz", + "integrity": "sha512-v+AgVwiK5DsGtT9ng+m4mClp6zDAmwrW8nZi6Gg15qzvBnRWWdfWA1TGaXyCDnWq5g5asofIgMVl3PjKxvk1ug==", "requires": { - "fast-xml-parser": "^3.19.0" + "fast-xml-parser": "^4.1.3" } }, "is-symbol": { diff --git a/package.json b/package.json index d5799173..1d616658 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mediadc", "description": "Nextcloud Media Duplicate Collector application", - "version": "0.3.5", + "version": "0.3.6", "keywords": [ "nextcloud", "photos", @@ -39,15 +39,15 @@ "extends @nextcloud/browserslist-config" ], "dependencies": { - "@nextcloud/auth": "^2.0.0", + "@nextcloud/auth": "^2.1.0", "@nextcloud/axios": "^2.3.0", "@nextcloud/dialogs": "^4.0.1", - "@nextcloud/event-bus": "^3.0.2", + "@nextcloud/event-bus": "^3.1.0", "@nextcloud/initial-state": "^2.0.0", "@nextcloud/l10n": "^2.1.0", "@nextcloud/moment": "^1.2.1", - "@nextcloud/router": "^2.0.1", - "@nextcloud/vue": "^7.9.0", + "@nextcloud/router": "^2.1.2", + "@nextcloud/vue": "^7.12.0", "vue": "^2.7.14", "vuex": "^3.6.2", "vue-router": "^3.5.3", diff --git a/src/components/details/DetailsFile.vue b/src/components/details/DetailsFile.vue index bfd53f19..26ebd96d 100755 --- a/src/components/details/DetailsFile.vue +++ b/src/components/details/DetailsFile.vue @@ -66,8 +66,7 @@
- {{ file.filename }} - {{ file.filepath }} + {{ !showFullFilePath ? file.filename : file.filepath }} {{ file.fileowner }} {{ formatBytes(Number(file.filesize)) }}
@@ -249,7 +248,7 @@ export default { emit('updateGroupFilesPagination', this.file) } else if ('locked' in res.data && res.data.locked) { showWarning(this.t('mediadc', 'Wait until file has been loaded before deleting it')) - } else if ('not_permited' in res.data && res.data.not_permited) { + } else if ('not_permitted' in res.data && res.data.not_permited) { showError(this.t('mediadc', 'Not enough permissions to delete the file')) } else if ('not_found' in res.data && res.data.not_found) { showError(this.t('mediadc', 'File not found. Probably it\'s has been already deleted')) @@ -376,6 +375,8 @@ body[data-theme-dark] .placeholder { } .filepath { + width: 100%; + line-break: anywhere; border-bottom: 1px solid var(--color-border-dark); padding-bottom: 5px; margin-bottom: 5px; diff --git a/src/components/details/DetailsList.vue b/src/components/details/DetailsList.vue index a522e7af..05dac2af 100755 --- a/src/components/details/DetailsList.vue +++ b/src/components/details/DetailsList.vue @@ -84,29 +84,56 @@ {{ n('mediadc', 'Batch actions for %n group', 'Batch actions for %n groups', checkedDetailGroups.length) }} - + + {{ t('mediadc', 'Uncheck selected') }} {{ n('mediadc', 'Remove group', 'Remove groups', checkedDetailGroups.length) }} + + + + {{ t('mediadc', 'Delete files') }} +
@@ -168,6 +195,10 @@ import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadi import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' import NcActions from '@nextcloud/vue/dist/Components/NcActions.js' import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js' +import MinusBoxOutline from 'vue-material-design-icons/MinusBoxOutline.vue' +import CheckAll from 'vue-material-design-icons/CheckAll.vue' +import CheckUnderline from 'vue-material-design-icons/CheckUnderline.vue' +import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js' import { mapGetters } from 'vuex' @@ -185,6 +216,10 @@ export default { NcActions, NcActionButton, Pagination, + MinusBoxOutline, + CheckAll, + CheckUnderline, + NcLoadingIcon, }, mixins: [Formats], data() { @@ -194,6 +229,7 @@ export default { checkedDetailGroups: [], batchActionsOpened: false, sortGroups: true, + batchDeleting: false, } }, computed: { @@ -346,6 +382,36 @@ export default { } } }, + deleteCheckedGroupsFiles() { + this.batchDeleting = true + axios.post(generateUrl(`/apps/mediadc/api/v1/tasks/${this.task.id}/details/delete`), { groupIds: this.checkedDetailGroups.map(d => d.group_id) }).then(res => { + if (res.data.success) { + emit('openNextDetailGroup', this.checkedDetailGroups[this.checkedDetailGroups.length - 1]) + const updatedDetails = [...this.details] + for (const removedGroupId of res.data.removedGroupIds) { + const checkedIndex = this.checkedDetailGroups.findIndex(d => Number(d.group_id) === removedGroupId) + if (checkedIndex !== -1) { + this.checkedDetailGroups.splice(checkedIndex, 1) + } + const removedDetailIndex = updatedDetails.findIndex(d => Number(d.group_id) === removedGroupId) + updatedDetails.splice(removedDetailIndex, 1) + } + emit('updateTaskInfo') + this.$store.commit('setDetails', updatedDetails) + this.$store.commit('setTask', res.data.task) + showSuccess(this.t('mediadc', 'Selected groups files successfully deleted')) + } else if (res.data.removedGroupIds.length !== 0) { + showWarning(this.t('mediadc', 'Not all selected groups files deleted')) + } else { + showError(this.t('mediadc', 'Failed to delete selected groups files')) + } + this.batchDeleting = false + }).catch(err => { + showError(this.t('mediadc', 'A server error occurred')) + console.debug(err) + this.batchDeleting = false + }) + }, selectAllGroups() { const _details = (!this.filtered) ? this.details : this.detailsFiltered if (this.checkedDetailGroups.length === _details.length) { diff --git a/src/components/settings/AdminSettings.vue b/src/components/settings/AdminSettings.vue index df87de3f..fd88dddd 100755 --- a/src/components/settings/AdminSettings.vue +++ b/src/components/settings/AdminSettings.vue @@ -160,6 +160,7 @@ import axios from '@nextcloud/axios' import { generateUrl } from '@nextcloud/router' import { showError, showSuccess, showWarning } from '@nextcloud/dialogs' +import { loadState } from '@nextcloud/initial-state' import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js' import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' @@ -201,21 +202,29 @@ export default { } }, beforeMount() { - this.getSettings() + this.settings = loadState('mediadc', 'settings', null) + if (this.settings !== null) { + this.mapSettings(this.settings) + } else { + this.getSettings() + } }, methods: { getSettings() { axios.get(generateUrl('/apps/mediadc/api/v1/settings')).then(res => { this.settings = res.data - this.settings.forEach(setting => { - this.mappedSettings[setting.name] = setting - }) - this.algorithms = ['average', 'dhash', 'phash', 'whash'] - this.hashing_algorithm = JSON.parse(this.mappedSettings.hashing_algorithm.value) - this.hash_size = this.mappedSettings.hash_size.value - this.customExcludeList = JSON.parse(this.mappedSettings.exclude_list.value).mask - this.python_binary = JSON.parse(this.mappedSettings.python_binary.value) + this.mapSettings(this.settings) + }) + }, + mapSettings(settings) { + settings.forEach(setting => { + this.mappedSettings[setting.name] = setting }) + this.algorithms = ['average', 'dhash', 'phash', 'whash'] + this.hashing_algorithm = JSON.parse(this.mappedSettings.hashing_algorithm.value) + this.hash_size = this.mappedSettings.hash_size.value + this.customExcludeList = JSON.parse(this.mappedSettings.exclude_list.value).mask + this.python_binary = JSON.parse(this.mappedSettings.python_binary.value) }, saveChanges() { axios.put(generateUrl('/apps/mediadc/api/v1/settings'), { settings: this.settings }) diff --git a/src/views/Collector.vue b/src/views/Collector.vue index 3b43bbc2..c1e3ff3e 100755 --- a/src/views/Collector.vue +++ b/src/views/Collector.vue @@ -42,6 +42,7 @@ import TasksNew from '../components/tasks/TasksNew.vue' import TasksList from '../components/tasks/TasksList.vue' import { loadState } from '@nextcloud/initial-state' +import { mapActions } from 'vuex' export default { name: 'Collector', @@ -65,27 +66,34 @@ export default { } }, beforeMount() { - const tasks = loadState('mediadc', 'tasks', false) - const settings = loadState('mediadc', 'settings', false) - if (tasks) { - this.$store.commit('setTasks', tasks) + if (this.getTasks().length > 0) { this.$emit('update:loading', false) - if (settings) { - this.$store.commit('setSettings', settings) + } else { + const tasks = loadState('mediadc', 'tasks', false) + const settings = loadState('mediadc', 'settings', false) + if (tasks) { + this.$store.commit('setTasks', tasks) this.$emit('update:loading', false) - } else { - this.$store.dispatch('getSettings').then(() => { + if (settings) { + this.$store.commit('setSettings', settings) this.$emit('update:loading', false) + } else { + this.$store.dispatch('getSettings').then(() => { + this.$emit('update:loading', false) + }) + } + } else { + this.$store.dispatch('getTasks', true).then(() => { + this.$store.dispatch('getSettings').then(() => { + this.$emit('update:loading', false) + }) }) } - } else { - this.$store.dispatch('getTasks', true).then(() => { - this.$store.dispatch('getSettings').then(() => { - this.$emit('update:loading', false) - }) - }) } }, + methods: { + ...mapActions(['getTasks', 'getSettings']), + }, } diff --git a/src/views/CollectorDetails.vue b/src/views/CollectorDetails.vue index 0a9262ee..b7bcc68b 100755 --- a/src/views/CollectorDetails.vue +++ b/src/views/CollectorDetails.vue @@ -108,7 +108,7 @@ icon="icon-delete" :close-after-click="true" @click="deleteTask(task)"> - {{ t('mediadc', 'Delete') }} + {{ t('mediadc', 'Delete task') }}