diff options
author | John Molakvoæ <skjnldsv@protonmail.com> | 2024-02-01 18:59:58 +0100 |
---|---|---|
committer | backportbot[bot] <backportbot[bot]@users.noreply.github.com> | 2024-02-07 08:53:32 +0000 |
commit | c48edcb2be0815ec549fdedaf957711412e3e2f8 (patch) | |
tree | c50daba43445b57545574868421a3f00bf5330a6 /apps/files | |
parent | 5dc2200ca02d4461ac61dd0e68bcbfa76068435c (diff) | |
download | nextcloud-server-c48edcb2be0815ec549fdedaf957711412e3e2f8.tar.gz nextcloud-server-c48edcb2be0815ec549fdedaf957711412e3e2f8.zip |
fix(files): drop to folder path and user feedback
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
Diffstat (limited to 'apps/files')
-rw-r--r-- | apps/files/src/components/DragAndDropNotice.vue | 50 | ||||
-rw-r--r-- | apps/files/src/components/FileEntry.vue | 35 | ||||
-rw-r--r-- | apps/files/src/components/FileEntryGrid.vue | 42 |
3 files changed, 96 insertions, 31 deletions
diff --git a/apps/files/src/components/DragAndDropNotice.vue b/apps/files/src/components/DragAndDropNotice.vue index 3f7126fac67..a9c1d8e99ad 100644 --- a/apps/files/src/components/DragAndDropNotice.vue +++ b/apps/files/src/components/DragAndDropNotice.vue @@ -47,6 +47,7 @@ import { defineComponent } from 'vue' import { Folder, Permission } from '@nextcloud/files' import { showError, showSuccess } from '@nextcloud/dialogs' import { translate as t } from '@nextcloud/l10n' +import { UploadStatus } from '@nextcloud/upload' import TrayArrowDownIcon from 'vue-material-design-icons/TrayArrowDown.vue' @@ -143,10 +144,11 @@ export default defineComponent({ } }, - onDrop(event: DragEvent) { - logger.debug('Dropped on DragAndDropNotice', { event, error: this.cantUploadLabel }) + async onDrop(event: DragEvent) { + logger.debug('Dropped on DragAndDropNotice', { event }) - if (!this.canUpload || this.isQuotaExceeded) { + // cantUploadLabel is null if we can upload + if (this.cantUploadLabel) { showError(this.cantUploadLabel) return } @@ -162,23 +164,31 @@ export default defineComponent({ // Start upload logger.debug(`Uploading files to ${this.currentFolder.path}`) // Process finished uploads - handleDrop(event.dataTransfer).then((uploads) => { - logger.debug('Upload terminated', { uploads }) - showSuccess(t('files', 'Upload successful')) - - // Scroll to last upload in current directory if terminated - const lastUpload = uploads.findLast((upload) => !upload.file.webkitRelativePath.includes('/') && upload.response?.headers?.['oc-fileid']) - if (lastUpload !== undefined) { - this.$router.push({ - ...this.$route, - params: { - view: this.$route.params?.view ?? 'files', - // Remove instanceid from header response - fileid: parseInt(lastUpload.response!.headers['oc-fileid']), - }, - }) - } - }) + const uploads = await handleDrop(event.dataTransfer) + logger.debug('Upload terminated', { uploads }) + + if (uploads.some((upload) => upload.status === UploadStatus.FAILED)) { + showError(t('files', 'Some files could not be uploaded')) + const failedUploads = uploads.filter((upload) => upload.status === UploadStatus.FAILED) + logger.debug('Some files could not be uploaded', { failedUploads }) + } else { + showSuccess(t('files', 'Files uploaded successfully')) + } + + // Scroll to last successful upload in current directory if terminated + const lastUpload = uploads.findLast((upload) => upload.status !== UploadStatus.FAILED + && !upload.file.webkitRelativePath.includes('/') + && upload.response?.headers?.['oc-fileid']) + + if (lastUpload !== undefined) { + this.$router.push({ + ...this.$route, + params: { + view: this.$route.params?.view ?? 'files', + fileid: parseInt(lastUpload.response!.headers['oc-fileid']), + }, + }) + } } this.dragover = false }, diff --git a/apps/files/src/components/FileEntry.vue b/apps/files/src/components/FileEntry.vue index 8b4c7b71ef9..8243dc1199c 100644 --- a/apps/files/src/components/FileEntry.vue +++ b/apps/files/src/components/FileEntry.vue @@ -101,7 +101,7 @@ import type { PropType } from 'vue' import { extname, join } from 'path' import { FileType, formatFileSize, Permission, Folder, File as NcFile, NodeStatus, Node, View } from '@nextcloud/files' import { getUploader } from '@nextcloud/upload' -import { showError } from '@nextcloud/dialogs' +import { showError, showSuccess } from '@nextcloud/dialogs' import { translate as t } from '@nextcloud/l10n' import { vOnClickOutside } from '@vueuse/components' import moment from '@nextcloud/moment' @@ -515,12 +515,37 @@ export default defineComponent({ logger.debug('Dropped', { event, selection: this.draggingFiles }) // Check whether we're uploading files - if (event.dataTransfer?.files?.length > 0) { + if (event.dataTransfer?.files + && event.dataTransfer.files.length > 0) { const uploader = getUploader() - event.dataTransfer.files.forEach((file: File) => { - uploader.upload(join(this.source.path, file.name), file) - }) + + // Check whether the uploader is in the same folder + // This should never happen™ + if (!uploader.destination.path.startsWith(uploader.destination.path)) { + logger.error('The current uploader destination is not the same as the current folder') + showError(t('files', 'An error occurred while uploading. Please try again later.')) + return + } + logger.debug(`Uploading files to ${this.source.path}`) + const queue = [] as Promise<Upload>[] + for (const file of event.dataTransfer.files) { + // Because the uploader destination is properly set to the current folder + // we can just use the basename as the relative path. + queue.push(uploader.upload(join(this.source.basename, file.name), file)) + } + + const results = await Promise.allSettled(queue) + const errors = results.filter(result => result.status === 'rejected') + if (errors.length > 0) { + logger.error('Error while uploading files', { errors }) + showError(t('files', 'Some files could not be uploaded')) + return + } + + logger.debug('Files uploaded successfully') + showSuccess(t('files', 'Files uploaded successfully')) + return } diff --git a/apps/files/src/components/FileEntryGrid.vue b/apps/files/src/components/FileEntryGrid.vue index 99fd45813ed..d42da54431c 100644 --- a/apps/files/src/components/FileEntryGrid.vue +++ b/apps/files/src/components/FileEntryGrid.vue @@ -78,7 +78,7 @@ import type { PropType } from 'vue' import { extname, join } from 'path' import { FileType, Permission, Folder, File as NcFile, NodeStatus, Node, View } from '@nextcloud/files' import { getUploader } from '@nextcloud/upload' -import { showError } from '@nextcloud/dialogs' +import { showError, showSuccess } from '@nextcloud/dialogs' import { translate as t } from '@nextcloud/l10n' import { generateUrl } from '@nextcloud/router' import { vOnClickOutside } from '@vueuse/components' @@ -358,7 +358,12 @@ export default Vue.extend({ logger.debug('Drag ended') }, - async onDrop(event) { + async onDrop(event: DragEvent) { + // skip if native drop like text drag and drop from files names + if (!this.draggingFiles && !event.dataTransfer?.files?.length) { + return + } + event.preventDefault() event.stopPropagation() @@ -374,12 +379,37 @@ export default Vue.extend({ logger.debug('Dropped', { event, selection: this.draggingFiles }) // Check whether we're uploading files - if (event.dataTransfer?.files?.length > 0) { + if (event.dataTransfer?.files + && event.dataTransfer.files.length > 0) { const uploader = getUploader() - event.dataTransfer.files.forEach((file: File) => { - uploader.upload(join(this.source.path, file.name), file) - }) + + // Check whether the uploader is in the same folder + // This should never happen™ + if (!uploader.destination.path.startsWith(uploader.destination.path)) { + logger.error('The current uploader destination is not the same as the current folder') + showError(t('files', 'An error occurred while uploading. Please try again later.')) + return + } + logger.debug(`Uploading files to ${this.source.path}`) + const queue = [] as Promise<Upload>[] + for (const file of event.dataTransfer.files) { + // Because the uploader destination is properly set to the current folder + // we can just use the basename as the relative path. + queue.push(uploader.upload(join(this.source.basename, file.name), file)) + } + + const results = await Promise.allSettled(queue) + const errors = results.filter(result => result.status === 'rejected') + if (errors.length > 0) { + logger.error('Error while uploading files', { errors }) + showError(t('files', 'Some files could not be uploaded')) + return + } + + logger.debug('Files uploaded successfully') + showSuccess(t('files', 'Files uploaded successfully')) + return } |