Skip to content

Commit

Permalink
Fix "no selection" panel for root nodes in all files and public links
Browse files Browse the repository at this point in the history
  • Loading branch information
kulmann committed Mar 2, 2022
1 parent 4d58f7a commit db22aa5
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 51 deletions.
7 changes: 7 additions & 0 deletions changelog/unreleased/bugfix-right-sidebar-no-selection
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Bugfix: No selection info right sidebar

We fixed that the right sidebar was not showing the "no selection" info panel anymore in the root of "All files". In addition we also use the same "no selection" info panel now in the root nodes of public links.

https://github.com/owncloud/web/issues/6502
https://github.com/owncloud/web/issues/6182
https://github.com/owncloud/web/pull/6505
34 changes: 27 additions & 7 deletions packages/web-app-files/src/components/SideBar/SideBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ import { VisibilityObserver } from 'web-pkg/src/observer'
import { DavProperties } from 'web-pkg/src/constants'
import { buildResource } from '../../helpers/resources'
import { isLocationCommonActive, isLocationSharesActive } from '../../router'
import {
isLocationCommonActive,
isLocationPublicActive,
isLocationSharesActive
} from '../../router'
import { computed } from '@vue/composition-api'
import FileInfo from './FileInfo.vue'
Expand Down Expand Up @@ -120,7 +124,7 @@ export default {
},
computed: {
...mapGetters('Files', ['highlightedFile', 'selectedFiles', 'currentFolder']),
...mapGetters('Files', ['highlightedFile', 'selectedFiles', 'publicLinkPassword']),
...mapGetters(['fileSideBars', 'capabilities']),
...mapState('Files/sidebar', { sidebarActivePanel: 'activePanel' }),
activeAvailablePanelName() {
Expand Down Expand Up @@ -189,7 +193,13 @@ export default {
return this.selectedFiles && this.selectedFiles.length > 1
},
isRootFolder() {
return !this.highlightedFile?.path
const pathSegments = this.highlightedFile?.path?.split('/').filter(Boolean) || []
if (isLocationPublicActive(this.$router, 'files-public-files')) {
// root node of a public link has the public link token as path
// root path `/` like for personal home doesn't exist for public links
return pathSegments.length === 1
}
return !pathSegments.length
},
highlightedFileThumbnail() {
return this.highlightedFile?.thumbnail
Expand Down Expand Up @@ -304,12 +314,22 @@ export default {
this.selectedFile = this.highlightedFile
return
}
this.loading = true
try {
const item = await this.$client.files.fileInfo(
this.highlightedFile.webDavPath,
DavProperties.Default
)
let item
if (isLocationPublicActive(this.$router, 'files-public-files')) {
item = await this.$client.publicFiles.getFileInfo(
this.highlightedFile.webDavPath,
this.publicLinkPassword,
DavProperties.PublicLink
)
} else {
item = await this.$client.files.fileInfo(
this.highlightedFile.webDavPath,
DavProperties.Default
)
}
this.selectedFile = buildResource(item)
this.$set(this.selectedFile, 'thumbnail', this.highlightedFile.thumbnail || null)
Expand Down
184 changes: 140 additions & 44 deletions packages/web-app-files/tests/unit/components/SideBar/SideBar.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ import SideBar from '@files/src/components/SideBar/SideBar.vue'
import { createLocationSpaces } from '../../../../src/router'

jest.mock('web-pkg/src/observer')
jest.mock('@files/src/helpers/resources', () => {
const original = jest.requireActual('@files/src/helpers/resources')
return {
...original,
buildResource: jest.fn()
}
})

const simpleOwnFolder = {
type: 'folder',
Expand All @@ -21,63 +28,151 @@ const simpleOwnFolder = {
size: '740'
}

const selectors = {
noSelectionInfoPanel: 'noselection-stub'
}

describe('SideBar', () => {
it('fetches file info if 1 item is selected', () => {
const mockFileInfo = jest.fn()
mockFileInfo.mockReturnValueOnce(Files['/'][1])

createWrapper({
item: simpleOwnFolder,
selectedItems: [simpleOwnFolder],
mocks: { $client: { files: { fileInfo: mockFileInfo } } }
describe('file info', () => {
beforeEach(() => {
buildResource.mockImplementation((item) => item)
})
afterEach(() => {
jest.clearAllMocks()
})
it('fetches file info if 1 item is selected', () => {
const mockFileInfo = jest.fn()
mockFileInfo.mockReturnValueOnce(Files['/'][1])

expect(mockFileInfo).toHaveBeenCalledTimes(1)
})

it('fetches file info if the selected item changes', async () => {
const spyOnFetchFileInfo = jest
.spyOn(SideBar.methods, 'fetchFileInfo')
.mockImplementation(jest.fn)
createWrapper({
item: simpleOwnFolder,
selectedItems: [simpleOwnFolder],
mocks: { $client: { files: { fileInfo: mockFileInfo } } }
})

const wrapper = createWrapper({
item: simpleOwnFolder,
selectedItems: [simpleOwnFolder]
expect(mockFileInfo).toHaveBeenCalledTimes(1)
})

// fetchFileInfo is called once in created()
expect(spyOnFetchFileInfo).toHaveBeenCalledTimes(1)
it('fetches file info if the selected item changes', async () => {
const spyOnFetchFileInfo = jest
.spyOn(SideBar.methods, 'fetchFileInfo')
.mockImplementation(jest.fn)

const wrapper = createWrapper({
item: simpleOwnFolder,
selectedItems: [simpleOwnFolder]
})

// fetchFileInfo is called once in created()
expect(spyOnFetchFileInfo).toHaveBeenCalledTimes(1)

// it should be called again when a different file is loaded
const resource = Files['/'][4]
resource.path = `${resource.name}`
wrapper.vm.$store.commit('Files/SET_HIGHLIGHTED_FILE', resource)
await wrapper.vm.$nextTick()
expect(spyOnFetchFileInfo).toHaveBeenCalledTimes(2)

// and again if the file is renamed
const renamedResource = renameResource(Object.assign({}, resource), 'foobar.png', '')
wrapper.vm.$store.commit('Files/SET_HIGHLIGHTED_FILE', Object.assign(renamedResource))
await wrapper.vm.$nextTick()
expect(spyOnFetchFileInfo).toHaveBeenCalledTimes(3)
})

// it should be called again when a different file is loaded
const resource = buildResource(Files['/'][4])
resource.path = `${resource.name}`
wrapper.vm.$store.commit('Files/SET_HIGHLIGHTED_FILE', resource)
await wrapper.vm.$nextTick()
expect(spyOnFetchFileInfo).toHaveBeenCalledTimes(2)
it('does not fetch file info if multiple items are selected', () => {
const mockFileInfo = jest.fn().mockReturnValue({})

// and again if the file is renamed
const renamedResource = renameResource(Object.assign({}, resource), 'foobar.png', '')
wrapper.vm.$store.commit('Files/SET_HIGHLIGHTED_FILE', Object.assign(renamedResource))
await wrapper.vm.$nextTick()
expect(spyOnFetchFileInfo).toHaveBeenCalledTimes(3)
createWrapper({
item: simpleOwnFolder,
selectedItems: [simpleOwnFolder, simpleOwnFolder],
mocks: { $client: { files: { fileInfo: mockFileInfo } } }
})

jest.resetAllMocks()
expect(mockFileInfo).not.toHaveBeenCalled()
})
})

it('does not fetch file info if multiple items are selected', () => {
const mockFileInfo = jest.fn()

createWrapper({
item: simpleOwnFolder,
selectedItems: [simpleOwnFolder, simpleOwnFolder],
mocks: { $client: { files: { fileInfo: mockFileInfo } } }
describe('no selection info panel', () => {
afterEach(() => {
jest.clearAllMocks()
})
describe('for public links', () => {
it.each([
[
'shows in root node',
{
path: '/publicLinkToken',
noSelectionExpected: true
}
],
[
'does not show in non-root node',
{
path: '/publicLinkToken/some-folder',
noSelectionExpected: false
}
]
])('%s', async (name, { path, noSelectionExpected }) => {
const item = { path }
const mockFileInfo = jest.fn()
mockFileInfo.mockReturnValue(item)
buildResource.mockReturnValue(item)
const wrapper = createWrapper({
item,
selectedItems: [],
mocks: {
$client: { publicFiles: { getFileInfo: mockFileInfo } }
},
currentRouteName: 'files-public-files'
})
await wrapper.vm.$nextTick()
await wrapper.vm.$nextTick()
expect(wrapper.find(selectors.noSelectionInfoPanel).exists()).toBe(noSelectionExpected)
})
})
describe('for all files', () => {
it.each([
[
'shows in root node',
{
path: '/',
noSelectionExpected: true
}
],
[
'does not show in non-root node',
{
path: '/some-folder',
noSelectionExpected: false
}
]
])('%s', async (name, { path, noSelectionExpected }) => {
const item = { path }
const mockFileInfo = jest.fn()
mockFileInfo.mockReturnValue(item)
buildResource.mockReturnValue(item)
const wrapper = createWrapper({
item,
selectedItems: [],
mocks: {
$client: { files: { fileInfo: mockFileInfo } }
}
})
await wrapper.vm.$nextTick()
await wrapper.vm.$nextTick()
expect(wrapper.find(selectors.noSelectionInfoPanel).exists()).toBe(noSelectionExpected)
})
})

expect(mockFileInfo).not.toHaveBeenCalled()
})
})

function createWrapper({ item, selectedItems, mocks }) {
function createWrapper({
item,
selectedItems,
mocks,
currentRouteName = 'files-spaces-personal-home'
}) {
const localVue = createLocalVue()
localVue.use(Vuex)
localVue.use(VueCompositionAPI)
Expand Down Expand Up @@ -111,7 +206,8 @@ function createWrapper({ item, selectedItems, mocks }) {
},
getters: {
highlightedFile: (state) => state.highlightedFile,
selectedFiles: () => selectedItems
selectedFiles: () => selectedItems,
publicLinkPassword: () => ''
},
mutations: {
SET_HIGHLIGHTED_FILE(state, file) {
Expand All @@ -137,7 +233,7 @@ function createWrapper({ item, selectedItems, mocks }) {
mocks: merge(
{
$router: {
currentRoute: createLocationSpaces('files-spaces-personal-home'),
currentRoute: createLocationSpaces(currentRouteName),
resolve: (r) => {
return { href: r.name }
}
Expand Down

0 comments on commit db22aa5

Please sign in to comment.