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] Add search support for shares #7560

Merged
merged 13 commits into from
Sep 8, 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
2 changes: 1 addition & 1 deletion .drone.env
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# The version of OCIS to use in pipelines that test against OCIS
OCIS_COMMITID=fed62d4a1e425e839378cc608d4ff470c8011379
OCIS_COMMITID=a9b1591a3b05225579953ea42df125e49522414d
OCIS_BRANCH=master
8 changes: 8 additions & 0 deletions changelog/unreleased/bugfix-search-share-representation
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Bugfix: Search share representation

We've fixed a bug, where shares in the search were not displayed correctly and clicking on the respective
item did not open the default action or redirect to the correct share route.

https://github.com/owncloud/web/pull/7560
https://github.com/owncloud/web/issues/7043

29 changes: 26 additions & 3 deletions packages/web-app-files/src/components/FilesList/ResourceTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ import { extractDomSelector } from 'web-client/src/helpers/resource'
import { Resource } from 'web-client'
import { ClipboardActions } from '../../helpers/clipboardActions'
import { ShareTypes } from 'web-client/src/helpers/share'
import { createLocationSpaces } from '../../router'
import { createLocationSpaces, createLocationShares } from '../../router'
import { formatDateFromJSDate, formatRelativeDateFromJSDate } from 'web-pkg/src/helpers'
import { SideBarEventTopics } from '../../composables/sideBar'

Expand Down Expand Up @@ -593,15 +593,19 @@ export default defineComponent({
return this.createFolderLink(file.path, file)
},
parentFolderLink(file) {
if (file.shareId && file.path === '/') {
return createLocationShares('files-shares-with-me')
}

return this.createFolderLink(path.dirname(file.path), file)
},
createFolderLink(path, resource) {
createFolderLink(filePath, resource) {
if (this.targetRoute === null) {
return {}
}

const params = {
item: path.replace(/^\//, '') || '/',
item: filePath.replace(/^\//, '') || '/',
...mapResourceFields(resource, this.targetRouteParamMapping),
...this.targetRoute.params
}
Expand All @@ -610,6 +614,19 @@ export default defineComponent({
...this.targetRoute.query
}

if (resource.shareId) {
return createLocationSpaces('files-spaces-share', {
params: {
...params,
shareName: path.basename(resource.shareRoot)
},
query: {
...query,
shareId: resource.shareId
}
})
}

const matchingSpace = this.getMatchingSpace(resource.storageId)

if (this.hasProjectSpaces) {
Expand Down Expand Up @@ -798,6 +815,12 @@ export default defineComponent({
return this.$gettext('All files and folders')
}

if (resource.shareId) {
return resource.path === '/'
? this.$gettext('Shared with me')
: path.basename(resource.shareRoot)
}

return this.$gettext('Personal')
}
}
Expand Down
49 changes: 32 additions & 17 deletions packages/web-app-files/src/components/Search/Preview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
<oc-resource
:resource="resource"
:is-path-displayed="true"
:folder-link="folderLink(resource)"
:parent-folder-link="parentFolderLink(resource)"
:folder-link="folderLink"
:parent-folder-link="parentFolderLink"
:parent-folder-name-default="defaultParentFolderName"
:is-thumbnail-displayed="displayThumbnails"
@click="$_fileActions_triggerDefaultAction(resource)"
Expand All @@ -22,7 +22,7 @@ import Vue from 'vue'
import { mapGetters, mapState } from 'vuex'
import { createLocationSpaces } from '../../router'
import path from 'path'
import { useAccessToken, useCapabilityShareJailEnabled, useStore } from 'web-pkg/src/composables'
import { useCapabilityShareJailEnabled, useStore } from 'web-pkg/src/composables'

const visibilityObserver = new VisibilityObserver()

Expand All @@ -48,9 +48,7 @@ export default {
hasShareJail: useCapabilityShareJailEnabled(),
resourceTargetLocation: createLocationSpaces('files-spaces-personal', {
params: { storageId: store.getters.user.id }
}),
resourceTargetLocationSpace: createLocationSpaces('files-spaces-project'),
accessToken: useAccessToken({ store })
})
}
},
data() {
Expand All @@ -66,6 +64,12 @@ export default {
return this.spaces.find((space) => space.id === this.resource.storageId)
},
defaultParentFolderName() {
if (this.resource.shareId) {
return this.resource.path === '/'
? this.$gettext('Shared with me')
: path.basename(this.resource.shareRoot)
}

if (!this.hasShareJail) {
return this.$gettext('All files and folders')
}
Expand All @@ -76,6 +80,12 @@ export default {

return this.$gettext('Personal')
},
folderLink() {
return this.createFolderLink(this.resource.path, this.resource)
},
parentFolderLink() {
return this.createFolderLink(path.dirname(this.resource.path), this.resource)
},
displayThumbnails() {
return !this.configuration?.options?.disablePreviews
}
Expand Down Expand Up @@ -110,29 +120,34 @@ export default {
visibilityObserver.disconnect()
},
methods: {
folderLink(file) {
return this.createFolderLink(file.path, file.storageId)
},
parentFolderLink(file) {
return this.createFolderLink(path.dirname(file.path), file.storageId)
},
createFolderLink(path, storageId) {
if (this.resourceTargetLocation === null || this.resourceTargetLocationSpace === null) {
createFolderLink(filePath, resource) {
if (this.resourceTargetLocation === null) {
return {}
}

if (resource.shareId) {
return createLocationSpaces('files-spaces-share', {
params: {
shareName: path.basename(resource.shareRoot)
},
query: {
shareId: resource.shareId
}
})
}

if (this.matchingSpace?.driveType === 'project') {
return createLocationSpaces('files-spaces-project', {
params: { storageId, item: path.replace(/^\//, '') || undefined }
params: { storageId: resource.storageId, item: filePath.replace(/^\//, '') || undefined }
})
}

return {
name: this.resourceTargetLocation.name,
params: {
item: path.replace(/^\//, '') || undefined,
item: filePath.replace(/^\//, '') || undefined,
...this.resourceTargetLocation.params,
...(storageId && { storageId })
...(resource.storageId && { storageId: resource.storageId })
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion packages/web-app-files/src/helpers/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,10 @@ export function buildResource(resource): Resource {
})(),
privateLink: resource.fileInfo[DavProperty.PrivateLink],
downloadURL: resource.fileInfo[DavProperty.DownloadURL],
ownerDisplayName: resource.fileInfo[DavProperty.OwnerDisplayName],
shareId: resource.fileInfo[DavProperty.ShareId],
shareRoot: resource.fileInfo[DavProperty.ShareRoot],
ownerId: resource.fileInfo[DavProperty.OwnerId],
ownerDisplayName: resource.fileInfo[DavProperty.OwnerDisplayName],
canUpload: function () {
return this.permissions.indexOf(DavPermission.FolderCreateable) >= 0
},
Expand Down
9 changes: 2 additions & 7 deletions packages/web-app-files/src/search/sdk/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,8 @@ export default class List implements SearchList {

return {
range,
values: results.map((plainResource) => {
let resourceName = decodeURIComponent(plainResource.name)
if (resourceName.startsWith('/dav')) {
resourceName = resourceName.slice(4)
}

const resource = buildResource({ ...plainResource, name: resourceName })
values: results.map((result) => {
const resource = buildResource(result)
return { id: resource.id, data: resource }
})
}
Expand Down
8 changes: 2 additions & 6 deletions packages/web-app-files/src/search/sdk/preview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,8 @@ export default class Preview implements SearchPreview {
previewSearchLimit, // todo: add configuration option, other places need that too... needs consolidation
DavProperties.Default
)
const resources = results.reduce((acc, plainResource) => {
let resourceName = decodeURIComponent(plainResource.name)
if (resourceName.startsWith('/dav')) {
resourceName = resourceName.slice(4)
}
const resource = buildResource({ ...plainResource, name: resourceName })
const resources = results.reduce((acc, result) => {
const resource = buildResource(result)

// filter results if hidden files shouldn't be shown due to settings
if (!resource.name.startsWith('.') || areHiddenFilesShown) {
Expand Down
67 changes: 46 additions & 21 deletions packages/web-app-files/tests/unit/components/Search/Preview.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,24 @@ localVue.use(DesignSystem)
localVue.use(VueCompositionAPI)
localVue.use(Vuex)

const searchResult = {
id: 1234,
data: {
storageId: 1,
name: 'lorem.txt',
path: '/'
}
}

const user = { id: 'test' }

describe('Preview component', () => {
it('should set correct props on oc-resource component', () => {
const wrapper = getWrapper()
const ocResource = wrapper.find('oc-resource-stub')

expect(ocResource.exists()).toBeTruthy()
expect(ocResource.props().resource).toMatchObject(searchResult.data)
expect(ocResource.props().resource).toMatchObject(wrapper.vm.searchResult.data)
})
describe('folder and parent folder link', () => {
describe('computed folderLink and parentFolderLink', () => {
it('should be empty if no resource target location given', () => {
const wrapper = getWrapper({ resourceTargetLocation: null })
expect(wrapper.vm.folderLink(searchResult.data)).toEqual({})
expect(wrapper.vm.parentFolderLink(searchResult.data)).toEqual({})
expect(wrapper.vm.folderLink).toEqual({})
expect(wrapper.vm.parentFolderLink).toEqual({})
})
it('should use the items storageId for the resource target location if present', () => {
const wrapper = getWrapper({ resourceTargetLocation: { name: 'some-route' } })
expect(wrapper.vm.folderLink(searchResult.data).params.storageId).toEqual(1)
expect(wrapper.vm.parentFolderLink(searchResult.data).params.storageId).toEqual(1)
expect(wrapper.vm.folderLink.params.storageId).toEqual('1')
expect(wrapper.vm.parentFolderLink.params.storageId).toEqual('1')
})
})

Expand All @@ -56,15 +45,41 @@ describe('Preview component', () => {
resourceTargetLocation: null,
spaces: [
{
id: 1,
id: '1',
driveType: 'project',
name: 'New space'
}
]
})
expect(wrapper.vm.defaultParentFolderName).toEqual('New space')
})
it('should equal "Personal" if resource storage is not representing a project space', () => {
it('should equal the share name if resource is representing a file or folder in the root of a share', () => {
const wrapper = getWrapper({
searchResult: {
id: '1',
data: {
path: '/1/My share',
shareRoot: '/My share',
shareId: '1'
}
}
})
expect(wrapper.vm.defaultParentFolderName).toEqual('My share')
})
it('should equal the "Shared with me" if resource is representing the root share', () => {
const wrapper = getWrapper({
searchResult: {
id: '1',
data: {
path: '/',
shareRoot: '/My share',
shareId: '1'
}
}
})
expect(wrapper.vm.defaultParentFolderName).toEqual('Shared with me')
})
it('should equal "Personal" if resource storage is not representing the personal home', () => {
const wrapper = getWrapper({
resourceTargetLocation: null,
spaces: [
Expand All @@ -86,7 +101,16 @@ function getWrapper({
params: {}
},
spaces = [],
hasShareJail = true
hasShareJail = true,
searchResult = {
id: '1',
data: {
storageId: '1',
name: 'lorem.txt',
path: '/'
}
},
user = { id: 'test' }
} = {}) {
return shallowMount(Preview, {
localVue,
Expand Down Expand Up @@ -114,7 +138,8 @@ function getWrapper({
}
}),
mocks: {
$route: route
$route: route,
$gettext: (text) => text
},
propsData: {
searchResult
Expand Down
2 changes: 2 additions & 0 deletions packages/web-client/src/helpers/resource/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export interface Resource {
starred?: boolean
etag?: string
sharePermissions?: number
shareId?: string
shareRoot?: string
shareTypes?: number[]
privateLink?: string

Expand Down
4 changes: 4 additions & 0 deletions packages/web-pkg/src/constants/dav.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export abstract class DavProperty {
static readonly ResourceType: string = '{DAV:}resourcetype'
static readonly DownloadURL: string = '{http://owncloud.org/ns}downloadURL'

static readonly ShareId: string = '{http://owncloud.org/ns}shareid'
static readonly ShareRoot: string = '{http://owncloud.org/ns}shareroot'
static readonly ShareTypes: string = '{http://owncloud.org/ns}share-types'
static readonly SharePermissions: string =
'{http://open-collaboration-services.org/ns}share-permissions'
Expand Down Expand Up @@ -53,6 +55,8 @@ export abstract class DavProperties {
DavProperty.Name,
DavProperty.OwnerId,
DavProperty.OwnerDisplayName,
DavProperty.ShareId,
DavProperty.ShareRoot,
DavProperty.ShareTypes,
DavProperty.PrivateLink,
DavProperty.ContentLength,
Expand Down