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

Use the Vue store for spaces #6427

Merged
merged 3 commits into from
Feb 14, 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
5 changes: 5 additions & 0 deletions changelog/unreleased/enhancement-spaces-use-store
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: Use the Vue store for spaces

Using the store for spaces integrates them seamlessly in our ecosystem and makes it easier to develop spaces even further. E.g. the properties of a space can now be altered without fetching all spaces again. This was achieved by introducing a "buildSpace" method, that transforms a space into a more generic resource object (just like regular files or shares).

https://github.com/owncloud/web/pull/6427
74 changes: 74 additions & 0 deletions packages/web-app-files/src/helpers/resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,80 @@ export function buildResource(resource) {
}
}

export function buildSpace(space) {
let spaceImageData, spaceReadmeData, spacePermissions
let disabled = false

if (space.special) {
spaceImageData = space.special.find((el) => el.specialFolder.name === 'image')
spaceReadmeData = space.special.find((el) => el.specialFolder.name === 'readme')
}

if (space.root) {
spacePermissions = space.root.permissions

if (space.root.deleted) {
disabled = space.root.deleted?.state === 'trashed'
}
}

return {
id: space.id,
fileId: '',
mimeType: '',
Comment on lines +124 to +125
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need those fields, afaik they will never be set

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depends on how the respective fields are used throughout the code. Sometimes there are string modifications applied - which don't work on undefined. IMO ok to keep them defined and empty, like it's done here. Will be cleaned up anyway once we refactor this to TypeScript.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way I understood @kulmann , these fields should be available to keep they resource object "aligned" with the other resources. Maybe I got it wrong though, @kulmann ? Jan is right, some of these fields will never be set.

name: space.name,
description: space.description,
extension: '',
path: '',
webDavPath: '',
type: 'space',
isFolder: true,
mdate: space.lastModifiedDateTime,
size: '',
indicators: [],
permissions: '',
starred: false,
etag: '',
sharePermissions: '',
shareTypes: (function () {
return []
})(),
privateLink: '',
downloadURL: '',
ownerDisplayName: '',
ownerId: '',
disabled,
spaceQuota: space.quota,
spacePermissions,
spaceImageData,
spaceReadmeData,
canUpload: function () {
return true
},
canDownload: function () {
return true
},
canBeDeleted: function () {
return true
},
canRename: function () {
return true
},
canShare: function () {
return true
},
canCreate: function () {
return true
},
isMounted: function () {
return true
},
isReceivedShare: function () {
return false
}
}
}

export function buildWebDavFilesPath(userId, path) {
return `/files/${userId}/${path}`
}
Expand Down
7 changes: 4 additions & 3 deletions packages/web-app-files/src/mixins/spaces/actions/delete.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { mapActions, mapGetters } from 'vuex'
import { mapActions, mapGetters, mapMutations } from 'vuex'
import { clientService } from 'web-pkg/src/services'

export default {
Expand All @@ -19,7 +19,7 @@ export default {
return false
}

return spaces[0].root?.deleted?.state === 'trashed'
return spaces[0].disabled
},
componentType: 'oc-button',
class: 'oc-files-actions-delete-trigger'
Expand All @@ -35,6 +35,7 @@ export default {
'showMessage',
'toggleModalConfirmButton'
]),
...mapMutations('Files', ['REMOVE_FILE']),

$_delete_trigger({ spaces }) {
if (spaces.length !== 1) {
Expand Down Expand Up @@ -66,7 +67,7 @@ export default {
})
.then(() => {
this.hideModal()
this.loadSpacesTask.perform(this)
this.REMOVE_FILE({ id })
})
.catch((error) => {
this.showMessage({
Expand Down
11 changes: 8 additions & 3 deletions packages/web-app-files/src/mixins/spaces/actions/disable.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { mapActions, mapGetters } from 'vuex'
import { mapActions, mapGetters, mapMutations } from 'vuex'
import { clientService } from 'web-pkg/src/services'

export default {
Expand All @@ -19,7 +19,7 @@ export default {
return false
}

return spaces[0].root?.deleted?.state !== 'trashed'
return !spaces[0].disabled
},
componentType: 'oc-button',
class: 'oc-files-actions-disable-trigger'
Expand All @@ -35,6 +35,7 @@ export default {
'showMessage',
'toggleModalConfirmButton'
]),
...mapMutations('Files', ['UPDATE_RESOURCE_FIELD']),

$_disable_trigger({ spaces }) {
if (spaces.length !== 1) {
Expand Down Expand Up @@ -62,7 +63,11 @@ export default {
.deleteDrive(id)
.then(() => {
this.hideModal()
this.loadSpacesTask.perform(this)
this.UPDATE_RESOURCE_FIELD({
id,
field: 'disabled',
value: true
})
})
.catch((error) => {
this.showMessage({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { mapActions, mapGetters } from 'vuex'
import { mapActions, mapGetters, mapMutations } from 'vuex'
import { clientService } from 'web-pkg/src/services'

export default {
Expand Down Expand Up @@ -29,6 +29,7 @@ export default {
'showMessage',
'toggleModalConfirmButton'
]),
...mapMutations('Files', ['UPDATE_RESOURCE_FIELD']),

$_editDescription_trigger({ spaces }) {
if (spaces.length !== 1) {
Expand Down Expand Up @@ -57,7 +58,11 @@ export default {
.updateDrive(id, { description }, {})
.then(() => {
this.hideModal()
this.loadSpacesTask.perform(this)
this.UPDATE_RESOURCE_FIELD({
id,
field: 'description',
value: description
})
})
.catch((error) => {
this.showMessage({
Expand Down
9 changes: 7 additions & 2 deletions packages/web-app-files/src/mixins/spaces/actions/rename.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { mapActions, mapGetters } from 'vuex'
import { mapActions, mapGetters, mapMutations } from 'vuex'
import { clientService } from 'web-pkg/src/services'

export default {
Expand Down Expand Up @@ -29,6 +29,7 @@ export default {
'showMessage',
'toggleModalConfirmButton'
]),
...mapMutations('Files', ['UPDATE_RESOURCE_FIELD']),

$_rename_trigger({ spaces }) {
if (spaces.length !== 1) {
Expand Down Expand Up @@ -64,7 +65,11 @@ export default {
.updateDrive(id, { name }, {})
.then(() => {
this.hideModal()
this.loadSpacesTask.perform(this)
this.UPDATE_RESOURCE_FIELD({
id,
field: 'name',
value: name
})
})
.catch((error) => {
this.showMessage({
Expand Down
11 changes: 8 additions & 3 deletions packages/web-app-files/src/mixins/spaces/actions/restore.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { mapActions, mapGetters } from 'vuex'
import { mapActions, mapGetters, mapMutations } from 'vuex'
import { clientService } from 'web-pkg/src/services'

export default {
Expand All @@ -19,7 +19,7 @@ export default {
return false
}

return spaces[0].root?.deleted?.state === 'trashed'
return spaces[0].disabled
},
componentType: 'oc-button',
class: 'oc-files-actions-restore-trigger'
Expand All @@ -35,6 +35,7 @@ export default {
'showMessage',
'toggleModalConfirmButton'
]),
...mapMutations('Files', ['UPDATE_RESOURCE_FIELD']),

$_restore_trigger({ spaces }) {
if (spaces.length !== 1) {
Expand Down Expand Up @@ -70,7 +71,11 @@ export default {
)
.then(() => {
this.hideModal()
this.loadSpacesTask.perform(this)
this.UPDATE_RESOURCE_FIELD({
id,
field: 'disabled',
value: false
})
})
.catch((error) => {
this.showMessage({
Expand Down
65 changes: 37 additions & 28 deletions packages/web-app-files/src/views/spaces/Project.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="space-overview">
<list-loader v-if="loadSpaceTask.isRunning" />
<list-loader v-if="loadFilesListTask.isRunning" />
<template v-else>
<not-found-message v-if="!space.id" class="space-not-found oc-height-1-1" />
<div
Expand Down Expand Up @@ -77,7 +77,7 @@ import { useStore, useRouter, useRouteQuery } from 'web-pkg/src/composables'
import marked from 'marked'
import MixinAccessibleBreadcrumb from '../../mixins/accessibleBreadcrumb'
import { bus } from 'web-pkg/src/instance'
import { buildResource, buildWebDavSpacesPath } from '../../helpers/resources'
import { buildResource, buildSpace, buildWebDavSpacesPath } from '../../helpers/resources'
import ResourceTable, { determineSortFields } from '../../components/FilesList/ResourceTable.vue'
import { createLocationSpaces } from '../../router'
import { usePagination, useSort } from '../../composables'
Expand Down Expand Up @@ -136,19 +136,13 @@ export default {
sortBy
})

const loadSpaceTask = useTask(function* () {
const response = yield graphClient.drives.getDrive(spaceId)
space.value = response.data || {}
})
const loadReadmeTask = useTask(function* (signal, ref) {
const markdownEntry = space.value?.special?.find((el) => el?.specialFolder?.name === 'readme')

if (!markdownEntry) {
if (!space.value.spaceReadmeData) {
return
}

const fileContents = yield ref.$client.files.getFileContents(
buildWebDavSpacesPath(space.value.id, markdownEntry.name)
buildWebDavSpacesPath(space.value.id, space.value.spaceReadmeData.name)
)

if (ref.markdownResizeObserver) {
Expand All @@ -162,14 +156,12 @@ export default {
}
})
const loadImageTask = useTask(function* (signal, ref) {
const imageEntry = space.value?.special?.find((el) => el?.specialFolder?.name === 'image')

if (!imageEntry) {
if (!space.value.spaceImageData) {
return
}

const fileContents = yield ref.$client.files.getFileContents(
buildWebDavSpacesPath(space.value.id, imageEntry.name),
buildWebDavSpacesPath(space.value.id, space.value.spaceImageData.name),
{
responseType: 'arrayBuffer'
}
Expand All @@ -180,11 +172,30 @@ export default {

const loadFilesListTask = useTask(function* (signal, ref, sameRoute, path = null) {
ref.CLEAR_CURRENT_FILES_LIST()
const response = yield ref.$client.files.list(
const graphResponse = yield graphClient.drives.getDrive(spaceId)

if (!graphResponse.data) {
return
}

space.value = buildSpace(graphResponse.data)

const webDavResponse = yield ref.$client.files.list(
buildWebDavSpacesPath(ref.$route.params.spaceId, path || '')
)

const resources = response.map(buildResource)
let resources = []
if (!path) {
// space front page -> use space as current folder
resources.push(space.value)

const webDavResources = webDavResponse.map(buildResource)
webDavResources.shift() // Remove webdav entry for the space itself
resources = resources.concat(webDavResources)
} else {
resources = webDavResponse.map(buildResource)
}

const currentFolder = resources.shift()

ref.LOAD_FILES({
Expand All @@ -193,23 +204,22 @@ export default {
})
ref.loadIndicators({
client: ref.$client,
currentFolder: currentFolder.path
currentFolder: currentFolder?.path
})

ref.accessibleBreadcrumb_focusAndAnnounceBreadcrumb(sameRoute)
ref.scrollToResourceFromRoute()
})

const loadResourcesTask = useTask(function* (signal, ref, sameRoute, path) {
yield loadSpaceTask.perform(ref)
loadReadmeTask.perform(ref)
loadImageTask.perform(ref)
loadFilesListTask.perform(ref, sameRoute, path)
yield loadFilesListTask.perform(ref, sameRoute, path)

// Only load when in space root, no need to fetch in subdirectories
if (!path) {
loadReadmeTask.perform(ref)
loadImageTask.perform(ref)
}
Comment on lines +215 to +218
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

})

return {
space,
loadSpaceTask,
loadImageTask,
loadReadmeTask,
markdownContent,
Expand Down Expand Up @@ -276,9 +286,8 @@ export default {
const sameRoute = to.name === from?.name
const sameItem = to.params?.item === from?.params?.item

if (!sameRoute || !sameItem) {
this.loadFilesListTask.perform(this, sameRoute, to.params.item)
this.loadReadmeTask.perform(this)
if ((!sameRoute || !sameItem) && from) {
this.loadResourcesTask.perform(this, sameRoute, to.params.item)
}
},
immediate: true
Expand Down
Loading