Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[full-ci] Upload progress & overlay improvements #7067

Merged
merged 12 commits into from
Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions changelog/unreleased/enhancement-upload-improvements
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Enhancement: Upload progress & overlay improvements

* Remove fetching of newly uploaded files to improve performance
* Redesign the upload overlay
* Show uploading files in the upload overlay
* Immediately show the upload overlay when uploading folders to tell the user that the upload is starting
* Only show top level folders in the upload overlay when uploading folders
* Remove the Uppy StatusBar plugin

https://github.com/owncloud/web/pull/7067
https://github.com/owncloud/web/issues/7066
https://github.com/owncloud/web/issues/7069
80 changes: 20 additions & 60 deletions packages/web-app-files/src/components/AppBar/CreateAndUpload.vue
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ import { defineComponent, getCurrentInstance, onMounted } from '@vue/composition
import { UppyResource, useUpload } from 'web-runtime/src/composables/upload'
import { useUploadHelpers } from '../../composables/upload'
import { SHARE_JAIL_ID } from '../../services/folder'
import { bus } from 'web-pkg/src/instance'

export default defineComponent({
components: {
Expand All @@ -141,7 +142,7 @@ export default defineComponent({
onMounted(() => {
const filesSelectedSub = uppyService.subscribe('filesSelected', instance.onFilesSelected)
const uploadSuccessSub = uppyService.subscribe('uploadSuccess', instance.onFileSuccess)
const uploadErrorSub = uppyService.subscribe('uploadError', instance.onFileError)
const uploadCompletedSub = uppyService.subscribe('uploadCompleted', instance.onUploadComplete)

uppyService.useDropTarget({
targetSelector: '#files-view',
Expand All @@ -151,7 +152,7 @@ export default defineComponent({
instance.$on('beforeDestroy', () => {
uppyService.unsubscribe('filesSelected', filesSelectedSub)
uppyService.unsubscribe('uploadSuccess', uploadSuccessSub)
uppyService.unsubscribe('uploadError', uploadErrorSub)
uppyService.unsubscribe('uploadCompleted', uploadCompletedSub)
uppyService.removeDropTarget()
})
})
Expand Down Expand Up @@ -276,76 +277,33 @@ export default defineComponent({
...mapMutations('Files', ['UPSERT_RESOURCE']),
...mapMutations(['SET_QUOTA']),

async onFileSuccess(file: UppyResource) {
try {
onFileSuccess() {
if (this.user?.quota) {
this.SET_QUOTA(this.user.quota)
}
},

onUploadComplete(result) {
if (result.successful) {
const file = result.successful[0]

if (!file) {
return
}

let pathFileWasUploadedTo = file.meta.currentFolder
if (file.meta.relativeFolder) {
pathFileWasUploadedTo += file.meta.relativeFolder
}

const fileIsInCurrentPath = pathFileWasUploadedTo === this.currentPath

await this.$nextTick()

let path = pathUtil.join(pathFileWasUploadedTo, file.name)
let resource

if (this.isPersonalLocation) {
if (this.hasShareJail) {
path = buildWebDavSpacesPath(this.personalDriveId, path || '')
} else {
path = buildWebDavFilesPath(this.user.id, path)
}
resource = await this.$client.files.fileInfo(path, DavProperties.Default)
} else if (this.isSpacesProjectLocation) {
path = buildWebDavSpacesPath(this.$route.params.storageId, path)
resource = await this.$client.files.fileInfo(path, DavProperties.Default)
} else if (this.isSpacesShareLocation) {
path = buildWebDavSpacesPath([SHARE_JAIL_ID, this.$route.query.shareId].join('!'), path)
resource = await this.$client.files.fileInfo(path, DavProperties.Default)
} else {
resource = await this.$client.publicFiles.getFileInfo(
path,
this.publicLinkPassword,
DavProperties.PublicLink
)
}

resource = buildResource(resource)

this.$uppyService.publish('uploadedFileFetched', {
uppyResource: file,
fetchedFile: resource
})

// Update table only if the file was uploaded to the current directory
if (fileIsInCurrentPath) {
this.UPSERT_RESOURCE(resource)

if (this.isPersonalLocation) {
this.loadIndicators({
client: this.$client,
currentFolder: this.currentFolder.path,
encodePath: this.encodePath
})
}
bus.publish('app.files.list.load')
}

const user = await this.$client.users.getUser(this.user.id)

this.SET_QUOTA(user.quota)
} catch (error) {
console.error(error)
}
},

onFileError(file) {
this.showMessage({
title: this.$gettext('Failed to upload'),
status: 'danger'
})
},

showCreateResourceModal(
isFolder = true,
ext = 'txt',
Expand Down Expand Up @@ -773,7 +731,9 @@ export default defineComponent({
},

async handleUppyFileUpload(files: UppyResource[]) {
this.$uppyService.publish('uploadStarted')
await this.createDirectoryTree(files)
this.$uppyService.publish('addedForUpload', files)
await this.updateStoreForCreatedFolders(files)
this.$uppyService.uploadFiles(files)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useActiveLocation } from '../router'
import { isLocationPublicActive, isLocationSpacesActive } from '../../router'
import { computed, onMounted, ref, Ref, unref } from '@vue/composition-api'
import { SHARE_JAIL_ID } from '../../services/folder'
import * as uuid from 'uuid'

interface UploadHelpersResult {
inputFilesToUppyFiles(inputFileOptions): UppyResource[]
Expand Down Expand Up @@ -181,6 +182,7 @@ const inputFilesToUppyFiles = ({

const { params } = unref(route)
const currentFolder = unref(currentPath)
const topLevelFolderIds = {}

for (const file of files) {
// Get the relative path of the file when the file was inside a directory on the client computer
Expand All @@ -206,6 +208,15 @@ const inputFilesToUppyFiles = ({
params: { ...params, item }
}

let topLevelFolderId
if (relativeFilePath) {
const topLevelDirectory = relativeFilePath.replace(/^\/+/, '').split('/')[0]
if (!topLevelFolderIds[topLevelDirectory]) {
topLevelFolderIds[topLevelDirectory] = uuid.v4()
}
topLevelFolderId = topLevelFolderIds[topLevelDirectory]
}

uppyFiles.push({
source: 'file input',
name: file.name,
Expand All @@ -217,7 +228,9 @@ const inputFilesToUppyFiles = ({
relativePath: relativeFilePath, // uppy needs this property to be named relativePath
route: fileRoute,
tusEndpoint,
webDavBasePath: unref(webDavBasePath) // WebDAV base path where the files will be uploaded to
webDavBasePath: unref(webDavBasePath), // WebDAV base path where the files will be uploaded to
uploadId: uuid.v4(),
topLevelFolderId
}
})
}
Expand Down
28 changes: 6 additions & 22 deletions packages/web-app-files/src/views/FilesDrop.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import { createLocationOperations, createLocationPublic } from '../router'
import ResourceUpload from '../components/AppBar/Upload/ResourceUpload.vue'
import { getCurrentInstance, onMounted } from '@vue/composition-api/dist/vue-composition-api'
import { useUpload } from 'web-runtime/src/composables/upload'
import * as uuid from 'uuid'

export default {
components: {
Expand All @@ -53,8 +54,6 @@ export default {

onMounted(() => {
const filesSelectedSub = uppyService.subscribe('filesSelected', instance.onFilesSelected)
const uploadSuccessSub = uppyService.subscribe('uploadSuccess', instance.onFileSuccess)
const uploadErrorSub = uppyService.subscribe('uploadError', instance.onFileError)

uppyService.useDropTarget({
targetSelector: '#files-drop-container',
Expand All @@ -63,8 +62,6 @@ export default {

instance.$on('beforeDestroy', () => {
uppyService.unsubscribe('filesSelected', filesSelectedSub)
uppyService.unsubscribe('uploadSuccess', uploadSuccessSub)
uppyService.unsubscribe('uploadError', uploadErrorSub)
uppyService.removeDropTarget()
})
})
Expand Down Expand Up @@ -150,35 +147,22 @@ export default {
},

onFilesSelected(files) {
this.$uppyService.publish('uploadStarted')

const uppyResources = files.map((file) => ({
source: 'FileDrop',
name: file.name,
type: file.type,
data: file,
meta: {
tusEndpoint: this.url,
relativePath: file.webkitRelativePath || file.relativePath || ''
relativePath: file.webkitRelativePath || file.relativePath || '',
uploadId: uuid.v4()
}
}))

this.$uppyService.publish('addedForUpload', uppyResources)
this.$uppyService.uploadFiles(uppyResources)
},

onFileSuccess(uppyResource) {
this.$uppyService.publish('uploadedFileFetched', {
uppyResource,
fetchedFile: {
name: uppyResource.name
}
})
},

onFileError(error) {
console.error(error)
this.showMessage({
title: this.$gettext('Failed to upload'),
status: 'danger'
})
}
}
}
Expand Down
1 change: 0 additions & 1 deletion packages/web-runtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"@sentry/integrations": "^6.19.7",
"@uppy/core": "^2.2.0",
"@uppy/drop-target": "^1.1.3",
"@uppy/status-bar": "^2.2.1",
"@uppy/tus": "^2.4.0",
"@uppy/xhr-upload": "^2.1.0",
"@vue/composition-api": "^1.4.9",
Expand Down
Loading