Skip to content

Commit

Permalink
Add global loading indicator for long running tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
JammingBen committed Mar 15, 2023
1 parent 0cb0d6c commit f42a82a
Show file tree
Hide file tree
Showing 14 changed files with 376 additions and 143 deletions.
17 changes: 9 additions & 8 deletions packages/web-app-admin-settings/src/views/Users.vue
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ import GroupsModal from '../components/Users/GroupsModal.vue'
import { useRemoveFromGroups } from '../mixins/users/removeFromGroups'
import { useAddToGroups } from '../mixins/users/addToGroups'
import { configurationManager } from 'web-pkg'
import { loadingService } from 'web-pkg/src/services'
export default defineComponent({
name: 'UsersView',
Expand Down Expand Up @@ -433,10 +434,10 @@ export default defineComponent({
}
return acc
}, addUsersToGroupsRequests)
await Promise.all(addUsersToGroupsRequests)
const usersResponse = await Promise.all(
usersToFetch.map((userId) => unref(graphClient).users.getUser(userId))
)
const usersResponse = await loadingService.addTask(async () => {
await Promise.all(addUsersToGroupsRequests)
return Promise.all(usersToFetch.map((userId) => unref(graphClient).users.getUser(userId)))
})
for (const { data: updatedUser } of usersResponse) {
const userIndex = unref(users).findIndex((user) => user.id === updatedUser.id)
unref(users)[userIndex] = updatedUser
Expand Down Expand Up @@ -476,10 +477,10 @@ export default defineComponent({
}
return acc
}, removeUsersToGroupsRequests)
await Promise.all(removeUsersToGroupsRequests)
const usersResponse = await Promise.all(
usersToFetch.map((userId) => unref(graphClient).users.getUser(userId))
)
const usersResponse = await loadingService.addTask(async () => {
await Promise.all(removeUsersToGroupsRequests)
return Promise.all(usersToFetch.map((userId) => unref(graphClient).users.getUser(userId)))
})
for (const { data: updatedUser } of usersResponse) {
const userIndex = unref(users).findIndex((user) => user.id === updatedUser.id)
unref(users)[userIndex] = updatedUser
Expand Down
30 changes: 26 additions & 4 deletions packages/web-app-files/src/helpers/resource/actions/transfer.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Resource } from 'web-client'
import { join } from 'path'
import { SpaceResource } from 'web-client/src/helpers'
import { ClientService } from 'web-pkg/src/services'
import { ClientService, loadingService, LoadingTaskState } from 'web-pkg/src/services'
import {
ConflictDialog,
ResolveStrategy,
isResourceBeeingMovedToSameLocation,
resolveFileNameDuplicate
resolveFileNameDuplicate,
FileConflict
} from '../conflictHandling'
import { TransferType } from '.'

Expand Down Expand Up @@ -106,7 +107,6 @@ export class ResourceTransfer extends ConflictDialog {
transferType = TransferType.COPY
}

const errors = []
const targetFolderResources = (
await this.clientService.webdav.listFiles(this.targetSpace, this.targetFolder)
).children
Expand All @@ -116,9 +116,30 @@ export class ResourceTransfer extends ConflictDialog {
this.targetFolder,
targetFolderResources
)

return loadingService.addTask(
({ setProgress }) => {
return this.moveResources(
resolvedConflicts,
targetFolderResources,
transferType,
setProgress
)
},
{ indeterminate: false }
)
}

private async moveResources(
resolvedConflicts: FileConflict[],
targetFolderResources: Resource[],
transferType: TransferType,
setProgress: (args: LoadingTaskState) => void
) {
const movedResources: Resource[] = []
const errors = []

for (let resource of this.resourcesToMove) {
for (let [i, resource] of this.resourcesToMove.entries()) {
// shallow copy of resources to prevent modifying existing rows
resource = { ...resource }
const hasConflict = resolvedConflicts.some((e) => e.resource.id === resource.id)
Expand Down Expand Up @@ -176,6 +197,7 @@ export class ResourceTransfer extends ConflictDialog {
resource.path = join(this.targetFolder.path, resource.name)
resource.webDavPath = join(this.targetFolder.webDavPath, resource.name)
movedResources.push(resource)
setProgress({ total: this.resourcesToMove.length, current: i + 1 })
} catch (error) {
console.error(error)
error.resourceName = resource.name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { join } from 'path'
import { Resource } from 'web-client'
import { ResolveConflict, ResolveStrategy } from '.'

interface FileConflict {
export interface FileConflict {
resource: Resource
strategy?: ResolveStrategy
}
Expand Down
39 changes: 21 additions & 18 deletions packages/web-app-files/src/mixins/actions/downloadArchive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import first from 'lodash-es/first'
import { archiverService } from '../../services'
import { isPublicSpaceResource, Resource } from 'web-client/src/helpers'
import { mapGetters } from 'vuex'
import { loadingService } from 'web-pkg/src/services'

export default {
mixins: [isFilesAppActive],
Expand Down Expand Up @@ -69,7 +70,7 @@ export default {
}
},
methods: {
async $_downloadArchive_trigger({ resources }) {
$_downloadArchive_trigger({ resources }) {
const fileOptions = archiverService.fileIdsSupported
? {
fileIds: resources.map((resource) => resource.fileId)
Expand All @@ -78,25 +79,27 @@ export default {
dir: path.dirname(first<Resource>(resources).path) || '/',
files: resources.map((resource) => resource.name)
}
await archiverService
.triggerDownload({
...fileOptions,
...(isPublicSpaceResource(this.space) && {
publicToken: this.space.id,
publicLinkPassword: this.publicLinkPassword
return loadingService.addTask(() => {
return archiverService
.triggerDownload({
...fileOptions,
...(isPublicSpaceResource(this.space) && {
publicToken: this.space.id,
publicLinkPassword: this.publicLinkPassword
})
})
})
.catch((e) => {
console.error(e)
this.showMessage({
title: this.$ngettext(
'Failed to download the selected folder.', // on single selection only available for folders
'Failed to download the selected files.', // on multi selection available for files+folders
this.selectedFiles.length
),
status: 'danger'
.catch((e) => {
console.error(e)
this.showMessage({
title: this.$ngettext(
'Failed to download the selected folder.', // on single selection only available for folders
'Failed to download the selected files.', // on multi selection available for files+folders
this.selectedFiles.length
),
status: 'danger'
})
})
})
})
}
}
}
41 changes: 22 additions & 19 deletions packages/web-app-files/src/mixins/actions/emptyTrashBin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { isLocationTrashActive } from '../../router'
import { buildWebDavFilesTrashPath } from '../../helpers/resources'
import { buildWebDavSpacesTrashPath } from 'web-client/src/helpers'
import { isProjectSpaceResource } from 'web-client/src/helpers'
import { loadingService } from 'web-pkg'

export default {
computed: {
Expand Down Expand Up @@ -70,27 +71,29 @@ export default {
? buildWebDavSpacesTrashPath(this.space.id)
: buildWebDavFilesTrashPath(this.user.id)

return this.$client.fileTrash
.clearTrashBin(path)
.then(() => {
this.showMessage({
title: this.$gettext('All deleted files were removed')
return loadingService.addTask(() => {
return this.$client.fileTrash
.clearTrashBin(path)
.then(() => {
this.showMessage({
title: this.$gettext('All deleted files were removed')
})
this.clearTrashBin()
})
this.clearTrashBin()
})
.catch((error) => {
console.error(error)
this.showMessage({
title: this.$pgettext(
'Error message in case clearing the trash bin fails',
'Failed to delete all files permanently'
),
status: 'danger'
.catch((error) => {
console.error(error)
this.showMessage({
title: this.$pgettext(
'Error message in case clearing the trash bin fails',
'Failed to delete all files permanently'
),
status: 'danger'
})
})
})
.finally(() => {
this.hideModal()
})
.finally(() => {
this.hideModal()
})
})
}
}
}
18 changes: 14 additions & 4 deletions packages/web-app-files/src/mixins/actions/restore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { mapActions, mapGetters, mapMutations, mapState } from 'vuex'
import { dirname } from 'path'
import { isLocationTrashActive } from '../../router'

import { clientService } from 'web-pkg/src/services'
import { clientService, loadingService, LoadingTaskState } from 'web-pkg/src/services'
import { Resource, isProjectSpaceResource, extractExtensionFromFile } from 'web-client/src/helpers'
import {
ResolveStrategy,
Expand Down Expand Up @@ -165,12 +165,16 @@ export default {
existingPaths
}
},
async $_restore_restoreResources(resources: Resource[], missingFolderPaths: string[]) {
async $_restore_restoreResources(
resources: Resource[],
missingFolderPaths: string[],
setProgress: (args: LoadingTaskState) => void
) {
const restoredResources = []
const failedResources = []

let createdFolderPaths = []
for (const resource of resources) {
for (const [i, resource] of resources.entries()) {
const parentPath = dirname(resource.path)
if (missingFolderPaths.includes(parentPath)) {
const { existingPaths } = await this.$_restore_createFolderStructure(
Expand All @@ -185,6 +189,7 @@ export default {
overwrite: true
})
restoredResources.push(resource)
setProgress({ total: resources.length, current: i + 1 })
} catch (e) {
console.error(e)
failedResources.push(resource)
Expand Down Expand Up @@ -275,7 +280,12 @@ export default {
resource.path = urlJoin(parentPath, resolvedName)
resolvedResources.push(resource)
}
return this.$_restore_restoreResources(resolvedResources, missingFolderPaths)
return loadingService.addTask(
({ setProgress }) => {
return this.$_restore_restoreResources(resolvedResources, missingFolderPaths, setProgress)
},
{ indeterminate: false }
)
}
}
}
Loading

0 comments on commit f42a82a

Please sign in to comment.