From 60b74e3d6d626a7f7599acbeaadb650cbf56cc6c Mon Sep 17 00:00:00 2001 From: John Molakvoæ Date: Tue, 28 Mar 2023 13:47:52 +0200 Subject: feat(files): batch actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ --- apps/files/src/actions/deleteAction.ts | 28 +++- apps/files/src/components/FileEntry.vue | 11 -- .../src/components/FilesListActionsHeader.vue | 168 +++++++++++++++++++++ apps/files/src/components/FilesListFooter.vue | 1 + apps/files/src/components/FilesListHeader.vue | 82 +++++----- .../files/src/components/FilesListHeaderButton.vue | 2 + 6 files changed, 237 insertions(+), 55 deletions(-) create mode 100644 apps/files/src/components/FilesListActionsHeader.vue (limited to 'apps/files/src') diff --git a/apps/files/src/actions/deleteAction.ts b/apps/files/src/actions/deleteAction.ts index acf855c8d15..88ec345fcf2 100644 --- a/apps/files/src/actions/deleteAction.ts +++ b/apps/files/src/actions/deleteAction.ts @@ -19,11 +19,13 @@ * along with this program. If not, see . * */ +import { emit } from '@nextcloud/event-bus' import { registerFileAction, Permission, FileAction, Node } from '@nextcloud/files' import { translate as t } from '@nextcloud/l10n' import axios from '@nextcloud/axios' import TrashCan from '@mdi/svg/svg/trash-can.svg?raw' -import { emit } from '@nextcloud/event-bus' + +import logger from '../logger' registerFileAction(new FileAction({ id: 'delete', @@ -33,20 +35,30 @@ registerFileAction(new FileAction({ : t('files', 'Delete') }, iconSvgInline: () => TrashCan, + enabled(nodes: Node[]) { return nodes.length > 0 && nodes .map(node => node.permissions) .every(permission => (permission & Permission.DELETE) !== 0) }, + async exec(node: Node) { - // No try...catch here, let the files app handle the error - await axios.delete(node.source) + try { + await axios.delete(node.source) - // Let's delete even if it's moved to the trashbin - // since it has been removed from the current view - // and changing the view will trigger a reload anyway. - emit('files:file:deleted', node) - return true + // Let's delete even if it's moved to the trashbin + // since it has been removed from the current view + // and changing the view will trigger a reload anyway. + emit('files:file:deleted', node) + return true + } catch (error) { + logger.error('Error while deleting a file', { error, source: node.source, node }) + return false + } + }, + async execBatch(nodes: Node[], view) { + return Promise.all(nodes.map(node => this.exec(node, view))) }, + order: 100, })) diff --git a/apps/files/src/components/FileEntry.vue b/apps/files/src/components/FileEntry.vue index 420af67f9eb..fa4c67cb553 100644 --- a/apps/files/src/components/FileEntry.vue +++ b/apps/files/src/components/FileEntry.vue @@ -138,7 +138,6 @@ export default Vue.extend({ Fragment, NcActionButton, NcActions, - NcButton, NcCheckboxRadioSwitch, NcLoadingIcon, }, @@ -328,16 +327,6 @@ export default Vue.extend({ }, methods: { - /** - * Get a cached note from the store - * - * @param {number} fileId the file id to get - * @return {Folder|File} - */ - getNode(fileId) { - return this.filesStore.getNode(fileId) - }, - async debounceIfNotCached() { if (!this.previewUrl) { return diff --git a/apps/files/src/components/FilesListActionsHeader.vue b/apps/files/src/components/FilesListActionsHeader.vue new file mode 100644 index 00000000000..9abb30c6c2e --- /dev/null +++ b/apps/files/src/components/FilesListActionsHeader.vue @@ -0,0 +1,168 @@ + + + + + + diff --git a/apps/files/src/components/FilesListFooter.vue b/apps/files/src/components/FilesListFooter.vue index 51907e03a9c..6f2cad358b1 100644 --- a/apps/files/src/components/FilesListFooter.vue +++ b/apps/files/src/components/FilesListFooter.vue @@ -149,6 +149,7 @@ tr { border-top: 1px solid var(--color-border); // Prevent hover effect on the whole row background-color: transparent !important; + border-bottom: none !important; } td { diff --git a/apps/files/src/components/FilesListHeader.vue b/apps/files/src/components/FilesListHeader.vue index e39d7b4cade..66b2845ea11 100644 --- a/apps/files/src/components/FilesListHeader.vue +++ b/apps/files/src/components/FilesListHeader.vue @@ -25,35 +25,43 @@ - - - - - - - - - - - - - - - - - - - - - - {{ column.title }} - - + + + + + @@ -66,9 +74,10 @@ import Vue from 'vue' import { useFilesStore } from '../store/files' import { useSelectionStore } from '../store/selection' import { useSortingStore } from '../store/sorting' +import FilesListActionsHeader from './FilesListActionsHeader.vue' +import FilesListHeaderButton from './FilesListHeaderButton.vue' import logger from '../logger.js' import Navigation from '../services/Navigation' -import FilesListHeaderButton from './FilesListHeaderButton.vue' export default Vue.extend({ name: 'FilesListHeader', @@ -76,6 +85,7 @@ export default Vue.extend({ components: { FilesListHeaderButton, NcCheckboxRadioSwitch, + FilesListActionsHeader, }, props: { @@ -129,22 +139,22 @@ export default Vue.extend({ } }, + selectedNodes() { + return this.selectionStore.selected + }, + isAllSelected() { - return this.selectedFiles.length === this.nodes.length + return this.selectedNodes.length === this.nodes.length }, isNoneSelected() { - return this.selectedFiles.length === 0 + return this.selectedNodes.length === 0 }, isSomeSelected() { return !this.isAllSelected && !this.isNoneSelected }, - selectedFiles() { - return this.selectionStore.selected - }, - sortingMode() { return this.sortingStore.getSortingMode(this.currentView.id) || this.currentView.defaultSortKey diff --git a/apps/files/src/components/FilesListHeaderButton.vue b/apps/files/src/components/FilesListHeaderButton.vue index 2e0c398ab25..cde77ff21fe 100644 --- a/apps/files/src/components/FilesListHeaderButton.vue +++ b/apps/files/src/components/FilesListHeaderButton.vue @@ -123,6 +123,7 @@ export default Vue.extend({ .button-vue__wrapper { flex-direction: row-reverse; // Take max inner width for text overflow ellipsis + // Remove when https://github.com/nextcloud/nextcloud-vue/pull/3936 is merged width: 100%; } @@ -133,6 +134,7 @@ export default Vue.extend({ opacity: 0; } + // Remove when https://github.com/nextcloud/nextcloud-vue/pull/3936 is merged .button-vue__text { overflow: hidden; white-space: nowrap; -- cgit v1.2.3