diff options
author | John Molakvoæ <skjnldsv@users.noreply.github.com> | 2023-12-20 17:42:11 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-20 17:42:11 +0100 |
commit | aae99606e04f716fe9bebcac064a7dc8ef0f71e4 (patch) | |
tree | adecd0376b1f80b6cac7f0a02be49cd22e7182d1 /apps | |
parent | 4f7ed475de1d71d3b0481b1681b8d08bb1920a6c (diff) | |
parent | dc82c2798a072c9054c60a14136dd7e2ab78dad7 (diff) | |
download | nextcloud-server-aae99606e04f716fe9bebcac064a7dc8ef0f71e4.tar.gz nextcloud-server-aae99606e04f716fe9bebcac064a7dc8ef0f71e4.zip |
Merge pull request #42366 from nextcloud/fix/dragdrop-join
Diffstat (limited to 'apps')
-rw-r--r-- | apps/files/src/components/DragAndDropNotice.vue | 79 | ||||
-rw-r--r-- | apps/files/src/components/FilesListVirtual.vue | 4 | ||||
-rw-r--r-- | apps/files/src/services/DropService.ts | 14 |
3 files changed, 82 insertions, 15 deletions
diff --git a/apps/files/src/components/DragAndDropNotice.vue b/apps/files/src/components/DragAndDropNotice.vue index 66cddcaff97..df03713601d 100644 --- a/apps/files/src/components/DragAndDropNotice.vue +++ b/apps/files/src/components/DragAndDropNotice.vue @@ -25,23 +25,33 @@ class="files-list__drag-drop-notice" @drop="onDrop"> <div class="files-list__drag-drop-notice-wrapper"> - <TrayArrowDownIcon :size="48" /> - <h3 class="files-list-drag-drop-notice__title"> - {{ t('files', 'Drag and drop files here to upload') }} - </h3> + <template v-if="canUpload && !isQuotaExceeded"> + <TrayArrowDownIcon :size="48" /> + <h3 class="files-list-drag-drop-notice__title"> + {{ t('files', 'Drag and drop files here to upload') }} + </h3> + </template> + + <!-- Not permitted to drop files here --> + <template v-else> + <h3 class="files-list-drag-drop-notice__title"> + {{ cantUploadLabel }} + </h3> + </template> </div> </div> </template> <script lang="ts"> -import { translate as t } from '@nextcloud/l10n' import { defineComponent } from 'vue' +import { Folder, Permission } from '@nextcloud/files' +import { showError, showSuccess } from '@nextcloud/dialogs' +import { translate as t } from '@nextcloud/l10n' import TrayArrowDownIcon from 'vue-material-design-icons/TrayArrowDown.vue' import logger from '../logger.js' import { handleDrop } from '../services/DropService' -import { showSuccess } from '@nextcloud/dialogs' export default defineComponent({ name: 'DragAndDropNotice', @@ -52,7 +62,7 @@ export default defineComponent({ props: { currentFolder: { - type: Object, + type: Folder, required: true, }, }, @@ -63,35 +73,86 @@ export default defineComponent({ } }, + computed: { + /** + * Check if the current folder has create permissions + */ + canUpload() { + return this.currentFolder && (this.currentFolder.permissions & Permission.CREATE) !== 0 + }, + isQuotaExceeded() { + return this.currentFolder?.attributes?.['quota-available-bytes'] === 0 + }, + + cantUploadLabel() { + if (this.isQuotaExceeded) { + return this.t('files', 'Your have used your space quota and cannot upload files anymore') + } else if (!this.canUpload) { + return this.t('files', 'You don’t have permission to upload or create files here') + } + return null + }, + }, + mounted() { // Add events on parent to cover both the table and DragAndDrop notice const mainContent = window.document.querySelector('main.app-content') as HTMLElement mainContent.addEventListener('dragover', this.onDragOver) mainContent.addEventListener('dragleave', this.onDragLeave) + mainContent.addEventListener('drop', this.onContentDrop) }, beforeDestroy() { const mainContent = window.document.querySelector('main.app-content') as HTMLElement mainContent.removeEventListener('dragover', this.onDragOver) mainContent.removeEventListener('dragleave', this.onDragLeave) + mainContent.removeEventListener('drop', this.onContentDrop) }, methods: { onDragOver(event: DragEvent) { + // Needed to keep the drag/drop events chain working + event.preventDefault() + const isForeignFile = event.dataTransfer?.types.includes('Files') + + logger.debug('Drag over DragAndDropNotice', { isForeignFile, event }) if (isForeignFile) { - // Only handle uploading + // Only handle uploading of outside files (not Nextcloud files) this.dragover = true } }, - onDragLeave(/* event: DragEvent */) { + onDragLeave(event: DragEvent) { + // Counter bubbling, make sure we're ending the drag + // only when we're leaving the current element + // Avoid flickering + const currentTarget = event.currentTarget as HTMLElement + if (currentTarget?.contains(event.relatedTarget as HTMLElement)) { + return + } + + if (this.dragover) { + this.dragover = false + } + }, + + onContentDrop(event: DragEvent) { + logger.debug('Drag and drop cancelled, dropped on empty space', { event }) + event.preventDefault() if (this.dragover) { this.dragover = false } }, onDrop(event: DragEvent) { + logger.debug('Dropped on DragAndDropNotice', { event, error: this.cantUploadLabel }) + + if (!this.canUpload || this.isQuotaExceeded) { + showError(this.cantUploadLabel) + return + } + if (this.$el.querySelector('tbody')?.contains(event.target as Node)) { return } diff --git a/apps/files/src/components/FilesListVirtual.vue b/apps/files/src/components/FilesListVirtual.vue index e0f2c50b87f..88bb7e2076a 100644 --- a/apps/files/src/components/FilesListVirtual.vue +++ b/apps/files/src/components/FilesListVirtual.vue @@ -128,7 +128,6 @@ export default defineComponent({ FileEntryGrid, headers: getFileListHeaders(), scrollToIndex: 0, - dndNoticeHeight: 0, } }, @@ -259,7 +258,10 @@ export default defineComponent({ onDragOver(event: DragEvent) { // Detect if we're only dragging existing files or not const isForeignFile = event.dataTransfer?.types.includes('Files') + if (isForeignFile) { + // Only handle uploading of existing Nextcloud files + // See DragAndDropNotice for handling of foreign files return } diff --git a/apps/files/src/services/DropService.ts b/apps/files/src/services/DropService.ts index 4b4f98a01d6..372b849bcc4 100644 --- a/apps/files/src/services/DropService.ts +++ b/apps/files/src/services/DropService.ts @@ -23,11 +23,13 @@ import type { Upload } from '@nextcloud/upload' import type { FileStat, ResponseDataDetailed } from 'webdav' -import { showError } from '@nextcloud/dialogs' -import { emit } from '@nextcloud/event-bus' import { davGetClient, davGetDefaultPropfind, davResultToNode, davRootPath } from '@nextcloud/files' -import { translate as t } from '@nextcloud/l10n' +import { emit } from '@nextcloud/event-bus' import { getUploader } from '@nextcloud/upload' +import { joinPaths } from '@nextcloud/paths' +import { showError } from '@nextcloud/dialogs' +import { translate as t } from '@nextcloud/l10n' + import logger from '../logger.js' export const handleDrop = async (data: DataTransfer) => { @@ -85,10 +87,12 @@ const handleRecursiveUpload = async (entry: FileSystemEntry, path: string = ''): ] } else { const directory = entry as FileSystemDirectoryEntry - logger.debug('Handle directory recursivly', { name: directory.name }) // TODO: Implement this on `@nextcloud/upload` - const absolutPath = `${davRootPath}${getUploader().destination.path}${path}${directory.name}` + const absolutPath = joinPaths(davRootPath, getUploader().destination.path, path, directory.name) + + logger.debug('Handle directory recursively', { name: directory.name, absolutPath }) + const davClient = davGetClient() const dirExists = await davClient.exists(absolutPath) if (!dirExists) { |