From 862b9cf94e5e39b4c2f463458875a6237f4694e5 Mon Sep 17 00:00:00 2001 From: Benedikt Kulmann Date: Fri, 18 Mar 2022 10:54:09 +0100 Subject: [PATCH] WIP shared resource view and routing --- .../components/FilesList/ResourceTable.vue | 57 ++++++++++--- packages/web-app-files/src/router/spaces.ts | 4 +- .../src/services/folder/loaderSharedWithMe.ts | 11 ++- .../services/folder/spaces/loaderPersonal.ts | 6 +- .../src/services/folder/spaces/loaderShare.ts | 13 +-- .../src/views/shares/SharedResource.vue | 79 +++++++++++-------- .../src/views/shares/SharedWithMe.vue | 16 ++-- 7 files changed, 121 insertions(+), 65 deletions(-) diff --git a/packages/web-app-files/src/components/FilesList/ResourceTable.vue b/packages/web-app-files/src/components/FilesList/ResourceTable.vue index 4c9e8add1a4..f3773d05dfd 100644 --- a/packages/web-app-files/src/components/FilesList/ResourceTable.vue +++ b/packages/web-app-files/src/components/FilesList/ResourceTable.vue @@ -177,6 +177,13 @@ import { defineComponent, PropType } from '@vue/composition-api' import { Resource } from '../../helpers/resource' import { ShareTypes } from '../../helpers/share' +const mapResourceFields = (resource: Resource, mapping = {}) => { + return Object.keys(mapping).reduce((result, resourceKey) => { + result[mapping[resourceKey]] = resource[resourceKey] + return result + }, {}) +} + export default defineComponent({ mixins: [Rename], model: { @@ -250,6 +257,33 @@ export default defineComponent({ required: false, default: null }, + /** + * Maps resource values to route params. Use `{ resourceFieldName: 'routeParamName' }` as format. + * + * An example would be `{ id: 'fileId' }` to map the value of the `id` field of a resource + * to the `fileId` param of the target route. + * + * Defaults to `{ storageId: 'storageId' } to map the value of the `storageId` field of a resource + * to the `storageId` param of the target route. + */ + targetRouteParamMapping: { + type: Object, + required: false, + default: () => ({ storageId: 'storageId' }) + }, + /** + * Maps resource values to route query options. Use `{ resourceFieldName: 'routeQueryName' }` as format. + * + * An example would be `{ id: 'fileId' }` to map the value of the `id` field of a resource + * to the `fileId` query option of the target route. + * + * Defaults to an empty object because no query options are expected as default. + */ + targetRouteQueryMapping: { + type: Object, + required: false, + default: () => ({}) + }, /** * Asserts whether clicking on the resource name triggers any action */ @@ -534,23 +568,28 @@ export default defineComponent({ this.openWithPanel('sharing-item') }, folderLink(file) { - return this.createFolderLink(file.path, file.storageId) + return this.createFolderLink(file.path, file) }, parentFolderLink(file) { - return this.createFolderLink(path.dirname(file.path), file.storageId) + return this.createFolderLink(path.dirname(file.path), file) }, - createFolderLink(path, storageId) { + createFolderLink(path, file) { if (this.targetRoute === null) { return {} } + const params = { + item: path.replace(/^\//, ''), + ...this.targetRoute.params, + ...mapResourceFields(file, this.targetRouteParamMapping) + } + const query = { + ...this.targetRoute.query, + ...mapResourceFields(file, this.targetRouteQueryMapping) + } return { name: this.targetRoute.name, - query: this.targetRoute.query, - params: { - item: path.replace(/^\//, ''), - ...this.targetRoute.params, - ...(storageId && { storageId }) - } + params, + query } }, fileDragged(file) { diff --git a/packages/web-app-files/src/router/spaces.ts b/packages/web-app-files/src/router/spaces.ts index c977e5bbfc1..72edbc960c3 100644 --- a/packages/web-app-files/src/router/spaces.ts +++ b/packages/web-app-files/src/router/spaces.ts @@ -64,7 +64,9 @@ export const buildRoutes = (components: RouteComponents): RouteConfig[] => [ } }, { - path: 'shares/:item*', + // FIXME: this is cheating. We rely on shares having a drive alias of `shares/` and hardcode it here until we have dynamic routes with drive aliases. + path: 'shares/:shareName?', + // path: 'shares/:shareName?/:item*', name: locationSpacesShare.name, component: components.SharedResource, meta: { diff --git a/packages/web-app-files/src/services/folder/loaderSharedWithMe.ts b/packages/web-app-files/src/services/folder/loaderSharedWithMe.ts index 52641eef2e7..ea700854672 100644 --- a/packages/web-app-files/src/services/folder/loaderSharedWithMe.ts +++ b/packages/web-app-files/src/services/folder/loaderSharedWithMe.ts @@ -1,7 +1,7 @@ import { FolderLoader, FolderLoaderTask, TaskContext } from '../folder' import Router from 'vue-router' import { useTask } from 'vue-concurrency' -import { aggregateResourceShares } from '../../helpers/resources' +import { aggregateResourceShares, buildWebDavSpacesPath } from '../../helpers/resources' import { isLocationSharesActive } from '../../router' import { Store } from 'vuex' import get from 'lodash-es/get' @@ -47,13 +47,12 @@ export class FolderLoaderSharedWithMe implements FolderLoader { getToken ) - // FIXME, HACK 1: `/Shares` path prefix needs to be removed backend side. We remove it client side in the meantime. - // FIXME, HACK 2: webDavPath points to `files//Shares/xyz` but now needs to point to a shares webDavPath according to the storageId of the share. meh. + // FIXME, HACK 1: path needs to be empty because the share has it's own webdav endpoint (we access it's root and thus don't need any relative path). should ideally be removed backend side. + // FIXME, HACK 2: webDavPath points to `files//Shares/xyz` but now needs to point to a shares webdav root. if (get(store, 'getters.capabilities.spaces.enabled', false)) { resources.forEach((resource) => { - if (resource.path.startsWith('/Shares')) { - resource.path = resource.path.substring('/Shares'.length) - } + resource.path = '' + resource.webDavPath = buildWebDavSpacesPath(resource.storageId, '') }) } } diff --git a/packages/web-app-files/src/services/folder/spaces/loaderPersonal.ts b/packages/web-app-files/src/services/folder/spaces/loaderPersonal.ts index e8f94ae226b..8fd7e8dc62d 100644 --- a/packages/web-app-files/src/services/folder/spaces/loaderPersonal.ts +++ b/packages/web-app-files/src/services/folder/spaces/loaderPersonal.ts @@ -2,11 +2,7 @@ import { FolderLoader, FolderLoaderTask, TaskContext } from '../../folder' import Router from 'vue-router' import { useTask } from 'vue-concurrency' import { DavProperties } from 'web-pkg/src/constants' -import { - buildResource, - buildWebDavFilesPath, - buildWebDavSpacesPath -} from '../../../helpers/resources' +import { buildResource, buildWebDavSpacesPath } from '../../../helpers/resources' import { isLocationSpacesActive } from '../../../router' import { Store } from 'vuex' import { fetchResources } from '../util' diff --git a/packages/web-app-files/src/services/folder/spaces/loaderShare.ts b/packages/web-app-files/src/services/folder/spaces/loaderShare.ts index b7dfdc8db8c..7ccf9a880aa 100644 --- a/packages/web-app-files/src/services/folder/spaces/loaderShare.ts +++ b/packages/web-app-files/src/services/folder/spaces/loaderShare.ts @@ -6,6 +6,8 @@ import { buildResource, buildWebDavSpacesPath } from '../../../helpers/resources import { Store } from 'vuex' import get from 'lodash-es/get' +const SHARE_JAIL_ID = 'a0ca6a90-a365-4782-871e-d44447bbc668' + export class FolderLoaderSpacesShare implements FolderLoader { public isEnabled(store: Store): boolean { return get(store, 'getters.capabilities.spaces', false) @@ -16,15 +18,14 @@ export class FolderLoaderSpacesShare implements FolderLoader { } public getTask(context: TaskContext): FolderLoaderTask { - const { - store, - clientService: { owncloudSdk: client } - } = context + const { store, clientService } = context - return useTask(function* (signal1, signal2, ref, storageId, path = null) { + return useTask(function* (signal1, signal2, ref, shareId, path = null) { store.commit('Files/CLEAR_CURRENT_FILES_LIST') - const webDavResponse = yield client.files.list(buildWebDavSpacesPath(storageId, path || '')) + const webDavResponse = yield clientService.owncloudSdk.files.list( + buildWebDavSpacesPath([SHARE_JAIL_ID, shareId].join('!'), path || '') + ) const resources = webDavResponse.map(buildResource) const currentFolder = resources.shift() diff --git a/packages/web-app-files/src/views/shares/SharedResource.vue b/packages/web-app-files/src/views/shares/SharedResource.vue index 43ec78d247f..22a72a9b942 100644 --- a/packages/web-app-files/src/views/shares/SharedResource.vue +++ b/packages/web-app-files/src/views/shares/SharedResource.vue @@ -1,7 +1,17 @@