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 @@
+
+
+ |
+
+
+
+
+
+
+ {{ action.displayName(nodes, currentView) }}
+
+
+ |
+
+
+
+
+
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 }}
-
- |
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+
+
+
+ {{ 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;
diff --git a/apps/files_trashbin/src/actions/restoreAction.ts b/apps/files_trashbin/src/actions/restoreAction.ts
index 201fffe6a53..fe896f6b618 100644
--- a/apps/files_trashbin/src/actions/restoreAction.ts
+++ b/apps/files_trashbin/src/actions/restoreAction.ts
@@ -19,13 +19,13 @@
* along with this program. If not, see .
*
*/
+import { emit } from '@nextcloud/event-bus'
+import { generateRemoteUrl } from '@nextcloud/router'
+import { getCurrentUser } from '@nextcloud/auth'
import { registerFileAction, Permission, FileAction, Node } from '@nextcloud/files'
import { translate as t } from '@nextcloud/l10n'
import axios from '@nextcloud/axios'
import History from '@mdi/svg/svg/history.svg?raw'
-import { generateRemoteUrl } from '@nextcloud/router'
-import { getCurrentUser } from '@nextcloud/auth'
-import { emit } from '@nextcloud/event-bus'
registerFileAction(new FileAction({
id: 'restore',
@@ -33,6 +33,7 @@ registerFileAction(new FileAction({
return t('files_trashbin', 'Restore')
},
iconSvgInline: () => History,
+
enabled(nodes: Node[], view) {
// Only available in the trashbin view
if (view.id !== 'trashbin') {
@@ -44,22 +45,31 @@ registerFileAction(new FileAction({
.map(node => node.permissions)
.every(permission => (permission & Permission.READ) !== 0)
},
+
async exec(node: Node) {
- // No try...catch here, let the files app handle the error
- const destination = generateRemoteUrl(`dav/trashbin/${getCurrentUser()?.uid}/restore/${node.basename}`)
- await axios({
- method: 'MOVE',
- url: node.source,
- headers: {
- destination,
- },
- })
+ try {
+ const destination = generateRemoteUrl(`dav/trashbin/${getCurrentUser()?.uid}/restore/${node.basename}`)
+ await axios({
+ method: 'MOVE',
+ url: node.source,
+ headers: {
+ destination,
+ },
+ })
- // Let's pretend the file is deleted since
- // we don't know the restored location
- emit('files:file:deleted', node)
- return true
+ // Let's pretend the file is deleted since
+ // we don't know the restored location
+ emit('files:file:deleted', node)
+ return true
+ } catch (error) {
+ console.error(error)
+ return false
+ }
+ },
+ async execBatch(nodes: Node[], view) {
+ return Promise.all(nodes.map(node => this.exec(node, view)))
},
+
order: 1,
inline: () => true,
}))