From 673783cda834e035ab20c1b090428052a626450a Mon Sep 17 00:00:00 2001 From: Benedikt Kulmann Date: Tue, 12 Dec 2023 11:50:06 +0100 Subject: [PATCH] Sidebar panel extension (#10111) * feat: introduce sidebar panels as extension point --------- Co-authored-by: Dominik Schmidt Co-authored-by: Jannik Stehle --- .../enhancement-extensions-sidebar-panels | 7 + changelog/unreleased/enhancement-file-sidebar | 6 + .../src/components/AppTemplate.vue | 60 +- .../src/views/Groups.vue | 220 ++++---- .../src/views/Spaces.vue | 159 +++--- .../src/views/Users.vue | 359 ++++++------ .../tests/unit/components/AppTemplate.spec.ts | 12 +- .../tests/unit/views/Groups.spec.ts | 53 +- .../tests/unit/views/Users.spec.ts | 67 +-- .../views/__snapshots__/General.spec.ts.snap | 2 +- .../views/__snapshots__/Spaces.spec.ts.snap | 7 - .../views/__snapshots__/Users.spec.ts.snap | 2 - .../src/components/AppBar/CreateAndUpload.vue | 3 +- .../src/components/FilesList/QuickActions.vue | 3 +- .../src/components/Search/List.vue | 15 +- .../components/Shares/SharedWithMeSection.vue | 4 +- .../SideBar/Details/FileDetails.vue | 32 +- .../components/SideBar/Details/TagsSelect.vue | 2 +- .../components/SideBar/Shares/FileLinks.vue | 1 - .../src/components/SideBar/SideBar.vue | 361 ------------ .../src/components/Spaces/SpaceHeader.vue | 4 +- .../useResourcesViewDefaults.ts | 2 +- packages/web-app-files/src/extensions.ts | 6 +- packages/web-app-files/src/fileSideBars.ts | 532 ++++++++++-------- packages/web-app-files/src/index.ts | 2 - .../src/services/folder/loaderSpace.ts | 11 +- .../web-app-files/src/views/Favorites.vue | 15 +- .../src/views/shares/SharedViaLink.vue | 23 +- .../src/views/shares/SharedWithMe.vue | 24 +- .../src/views/shares/SharedWithOthers.vue | 21 +- .../src/views/spaces/GenericSpace.vue | 64 ++- .../src/views/spaces/GenericTrash.vue | 14 +- .../src/views/spaces/Projects.vue | 32 +- .../src/views/trash/Overview.vue | 1 - .../mocks/useResourcesViewDefaultsMock.ts | 2 +- .../components/FilesList/QuickActions.spec.ts | 4 +- .../unit/components/SideBar/SideBar.spec.ts | 173 ------ .../components/Spaces/SpaceHeader.spec.ts | 6 +- .../tests/unit/views/Favorites.spec.ts | 2 +- .../unit/views/shares/SharedViaLink.spec.ts | 2 +- .../unit/views/shares/SharedWithMe.spec.ts | 2 +- .../views/shares/SharedWithOthers.spec.ts | 2 +- .../unit/views/spaces/GenericSpace.spec.ts | 2 +- .../unit/views/spaces/GenericTrash.spec.ts | 2 +- .../tests/unit/views/spaces/Projects.spec.ts | 2 +- .../__snapshots__/Projects.spec.ts.snap | 4 +- .../trash/__snapshots__/Overview.spec.ts.snap | 2 +- packages/web-app-importer/src/extensions.ts | 2 +- packages/web-app-ocm/src/extensions.ts | 2 +- packages/web-app-preview/src/App.vue | 24 +- packages/web-client/src/helpers/index.ts | 1 + packages/web-client/src/helpers/item.ts | 4 + .../web-client/src/helpers/resource/types.ts | 2 +- .../web-pkg/src/components/AppBar/AppBar.vue | 23 +- .../src/components/AppBar/SidebarToggle.vue | 55 -- .../web-pkg/src/components/AppBar/index.ts | 1 - .../components/AppTemplates/AppWrapper.vue | 47 +- packages/web-pkg/src/components/AppTopBar.vue | 11 +- .../components/FilesList/ContextActions.vue | 3 +- .../src/components/SideBar/FileSideBar.vue | 290 ++++++++++ .../src/components/SideBar/Files/FileInfo.vue | 84 +++ .../src/components/SideBar/Files/index.ts | 1 + .../src/components/SideBar/SideBar.vue | 205 +++---- .../web-pkg/src/components/SideBar/index.ts | 1 + .../web-pkg/src/components/SideBar/types.ts | 25 +- .../src/composables/appDefaults/index.ts | 1 + .../appDefaults/useAppFolderHandling.ts | 1 + .../composables/capability/useCapability.ts | 9 + packages/web-pkg/src/composables/index.ts | 1 + .../piniaStores/extensionRegistry.ts | 23 +- .../src/composables/sideBar/useSideBar.ts | 32 +- .../composables/spaces/useGetMatchingSpace.ts | 9 + packages/web-pkg/src/services/uppy/types.ts | 6 +- .../unit/components/AppBar/AppBar.spec.ts | 19 +- .../AppBar/__snapshots__/AppBar.spec.ts.snap | 9 +- .../components/sidebar/FileSideBar.spec.ts | 114 ++++ .../files/useFileActionsCreateNewFile.spec.ts | 2 +- .../useFileActionsCreateNewFolder.spec.ts | 2 +- .../files/useFileActionsRename.spec.ts | 8 +- .../files/useFileActionsSetImage.spec.ts | 12 +- .../files/useFileActionsSetReadme.spec.ts | 8 +- .../files/useFileActionsShowDetails.spec.ts | 12 +- .../useFileActionsDeleteResources.spec.ts | 7 +- .../spaces/useSpaceActionsDelete.spec.ts | 10 +- .../spaces/useSpaceActionsDisable.spec.ts | 10 +- .../useSpaceActionsEditDescription.spec.ts | 2 +- .../spaces/useSpaceActionsRename.spec.ts | 4 +- .../spaces/useSpaceActionsRestore.spec.ts | 10 +- .../spaces/useSpaceActionsShowMembers.spec.ts | 4 +- .../composables/sideBar/useSideBar.spec.ts | 38 +- .../helpers/resource/sameResource.spec.ts | 21 +- packages/web-runtime/src/App.vue | 34 +- .../src/components/Topbar/SideBarToggle.vue | 46 ++ .../src/components/Topbar/TopBar.vue | 17 +- .../src/composables/layout/index.ts | 1 + .../src/composables/layout/useLayout.ts | 63 +++ .../web-runtime/src/layouts/Application.vue | 5 +- packages/web-runtime/src/router/helpers.ts | 6 +- packages/web-runtime/src/router/index.ts | 124 ++-- .../web-runtime/src/router/setupAuthGuard.ts | 13 +- .../src/services/auth/authService.ts | 14 +- packages/web-runtime/src/store/apps.ts | 13 - .../components/Topbar}/SidebarToggle.spec.ts | 12 +- .../__snapshots__/SidebarToggle.spec.ts.snap | 4 +- .../src/mocks/defaultStubs.ts | 2 +- .../src/mocks/useGetMatchingSpaceMock.ts | 3 + web.d.ts | 7 +- 107 files changed, 2018 insertions(+), 1832 deletions(-) create mode 100644 changelog/unreleased/enhancement-extensions-sidebar-panels create mode 100644 changelog/unreleased/enhancement-file-sidebar delete mode 100644 packages/web-app-files/src/components/SideBar/SideBar.vue delete mode 100644 packages/web-app-files/tests/unit/components/SideBar/SideBar.spec.ts create mode 100644 packages/web-client/src/helpers/item.ts delete mode 100644 packages/web-pkg/src/components/AppBar/SidebarToggle.vue create mode 100644 packages/web-pkg/src/components/SideBar/FileSideBar.vue create mode 100644 packages/web-pkg/src/components/SideBar/Files/FileInfo.vue create mode 100644 packages/web-pkg/src/components/SideBar/Files/index.ts create mode 100644 packages/web-pkg/tests/unit/components/sidebar/FileSideBar.spec.ts create mode 100644 packages/web-runtime/src/components/Topbar/SideBarToggle.vue create mode 100644 packages/web-runtime/src/composables/layout/index.ts create mode 100644 packages/web-runtime/src/composables/layout/useLayout.ts rename packages/{web-pkg/tests/unit/components/AppBar => web-runtime/tests/unit/components/Topbar}/SidebarToggle.spec.ts (77%) rename packages/{web-pkg/tests/unit/components/AppBar => web-runtime/tests/unit/components/Topbar}/__snapshots__/SidebarToggle.spec.ts.snap (63%) diff --git a/changelog/unreleased/enhancement-extensions-sidebar-panels b/changelog/unreleased/enhancement-extensions-sidebar-panels new file mode 100644 index 00000000000..853fdb325b2 --- /dev/null +++ b/changelog/unreleased/enhancement-extensions-sidebar-panels @@ -0,0 +1,7 @@ +Enhancement: Registering right sidebar panels as extension + +Right sidebar panels can now be registered as extensions via our extension registry. They need to be of type `sidebarPanel`. +The benefit of this is that any app can register additional panels to be shown in the right sidebar while previously the +available panels were hardcoded. + +https://github.com/owncloud/web/pull/10111 diff --git a/changelog/unreleased/enhancement-file-sidebar b/changelog/unreleased/enhancement-file-sidebar new file mode 100644 index 00000000000..463d14ac89f --- /dev/null +++ b/changelog/unreleased/enhancement-file-sidebar @@ -0,0 +1,6 @@ +Enhancement: File sidebar in viewer and editor apps + +Viewer and editor apps now have the same right sidebar available like the `files` app. +This makes in place viewing file details, tagging, sharing, and much more possible. + +https://github.com/owncloud/web/pull/10111 diff --git a/packages/web-app-admin-settings/src/components/AppTemplate.vue b/packages/web-app-admin-settings/src/components/AppTemplate.vue index 8d765815035..963f9ebd4b0 100644 --- a/packages/web-app-admin-settings/src/components/AppTemplate.vue +++ b/packages/web-app-admin-settings/src/components/AppTemplate.vue @@ -22,17 +22,6 @@ :per-page-default="perPageDefault" per-page-storage-prefix="admin-settings" /> - - -
@@ -70,7 +59,7 @@ @@ -234,15 +209,6 @@ export default defineComponent({ top: 0; } -#files-toggle-sidebar { - vertical-align: middle; - border: 3px solid transparent; - &:hover { - background-color: var(--oc-color-background-hover); - border-radius: 3px; - } -} - .admin-settings-app-bar-controls { height: 52px; diff --git a/packages/web-app-admin-settings/src/views/Groups.vue b/packages/web-app-admin-settings/src/views/Groups.vue index 273977a4eb2..7af2828f478 100644 --- a/packages/web-app-admin-settings/src/views/Groups.vue +++ b/packages/web-app-admin-settings/src/views/Groups.vue @@ -6,7 +6,8 @@ :breadcrumbs="breadcrumbs" :side-bar-active-panel="sideBarActivePanel" :side-bar-available-panels="sideBarAvailablePanels" - :side-bar-open="sideBarOpen" + :side-bar-panel-context="sideBarPanelContext" + :is-side-bar-open="isSideBarOpen" :show-batch-actions="!!selectedGroups.length" :batch-actions="batchActions" :batch-action-items="selectedGroups" @@ -19,7 +20,7 @@ class="oc-mr-s" variation="primary" appearance="filled" - @click="toggleCreateGroupModal" + @click="onToggleCreateGroupModal" > @@ -54,28 +55,36 @@ diff --git a/packages/web-app-admin-settings/tests/unit/components/AppTemplate.spec.ts b/packages/web-app-admin-settings/tests/unit/components/AppTemplate.spec.ts index 3dcbcc5ed88..effd4a24555 100644 --- a/packages/web-app-admin-settings/tests/unit/components/AppTemplate.spec.ts +++ b/packages/web-app-admin-settings/tests/unit/components/AppTemplate.spec.ts @@ -58,19 +58,13 @@ describe('AppTemplate', () => { }) describe('sideBar', () => { it('should show when opened', () => { - const { wrapper } = getWrapper({ props: { sideBarOpen: true } }) + const { wrapper } = getWrapper({ props: { isSideBarOpen: true } }) expect(wrapper.find(stubSelectors.sideBar).exists()).toBeTruthy() }) it('should not show when closed', () => { - const { wrapper } = getWrapper({ props: { sideBarOpen: false } }) + const { wrapper } = getWrapper({ props: { isSideBarOpen: false } }) expect(wrapper.find(stubSelectors.sideBar).exists()).toBeFalsy() }) - it('can be toggled', async () => { - const eventSpy = jest.spyOn(eventBus, 'publish') - const { wrapper } = getWrapper({ props: { sideBarAvailablePanels: [jest.fn()] } }) - await wrapper.find(stubSelectors.sideBarToggleButton).trigger('click') - expect(eventSpy).toHaveBeenCalledWith(SideBarEventTopics.toggle) - }) it('can be closed', async () => { const eventSpy = jest.spyOn(eventBus, 'publish') const { wrapper } = getWrapper() @@ -129,7 +123,7 @@ function getWrapper({ props = {}, isMobileWidth = false } = {}) { props: { loading: false, breadcrumbs: [], - sideBarOpen: true, + isSideBarOpen: true, sideBarAvailablePanels: [], sideBarActivePanel: '', ...props diff --git a/packages/web-app-admin-settings/tests/unit/views/Groups.spec.ts b/packages/web-app-admin-settings/tests/unit/views/Groups.spec.ts index 5b7935b4342..4e56f29a7d4 100644 --- a/packages/web-app-admin-settings/tests/unit/views/Groups.spec.ts +++ b/packages/web-app-admin-settings/tests/unit/views/Groups.spec.ts @@ -25,15 +25,14 @@ jest.mock('@ownclouders/web-pkg', () => ({ })) describe('Groups view', () => { - describe('method "createGroup"', () => { + describe('method "onCreateGroup"', () => { it('should hide the modal and show message on success', async () => { - const { wrapper } = getWrapper() - const showMessageStub = jest.spyOn(wrapper.vm, 'showMessage') - const toggleCreateGroupModalStub = jest.spyOn(wrapper.vm, 'toggleCreateGroupModal') - await wrapper.vm.createGroup({ displayName: 'admins' }) + const { wrapper, storeOptions } = getWrapper() + expect(wrapper.vm.createGroupModalOpen).toBeFalsy() + await wrapper.vm.onCreateGroup({ displayName: 'admins' }) - expect(showMessageStub).toHaveBeenCalled() - expect(toggleCreateGroupModalStub).toHaveBeenCalledTimes(1) + expect(storeOptions.actions.showMessage).toHaveBeenCalled() + expect(wrapper.vm.createGroupModalOpen).toBeTruthy() }) it('should show message on error', async () => { @@ -42,17 +41,14 @@ describe('Groups view', () => { clientService.graphAuthenticated.groups.createGroup.mockImplementation(() => mockAxiosReject() ) - const { wrapper } = getWrapper({ clientService }) - const showErrorMessageStub = jest.spyOn(wrapper.vm, 'showErrorMessage') - const toggleCreateGroupModalStub = jest.spyOn(wrapper.vm, 'toggleCreateGroupModal') - await wrapper.vm.createGroup({ displayName: 'admins' }) + const { wrapper, storeOptions } = getWrapper({ clientService }) + await wrapper.vm.onCreateGroup({ displayName: 'admins' }) - expect(showErrorMessageStub).toHaveBeenCalled() - expect(toggleCreateGroupModalStub).toHaveBeenCalledTimes(0) + expect(storeOptions.actions.showErrorMessage).toHaveBeenCalled() }) }) - describe('method "editGroup"', () => { + describe('method "onEditGroup"', () => { it('should emit event on success', async () => { const clientService = getClientServiceMock() clientService.graphAuthenticated.groups.editGroup.mockImplementation(() => mockAxiosResolve()) @@ -69,7 +65,7 @@ describe('Groups view', () => { const busStub = jest.spyOn(eventBus, 'publish') await wrapper.vm.loadResourcesTask.last - const updatedGroup = await wrapper.vm.editGroup(editGroup) + const updatedGroup = await wrapper.vm.onEditGroup(editGroup) expect(updatedGroup.id).toEqual('1') expect(updatedGroup.displayName).toEqual('administrators') @@ -80,11 +76,10 @@ describe('Groups view', () => { jest.spyOn(console, 'error').mockImplementation(() => undefined) const clientService = getClientServiceMock() clientService.graphAuthenticated.groups.editGroup.mockImplementation(() => mockAxiosReject()) - const { wrapper } = getWrapper({ clientService }) - const showErrorMessageStub = jest.spyOn(wrapper.vm, 'showErrorMessage') - await wrapper.vm.editGroup({}) + const { wrapper, storeOptions } = getWrapper({ clientService }) + await wrapper.vm.onEditGroup({}) - expect(showErrorMessageStub).toHaveBeenCalled() + expect(storeOptions.actions.showErrorMessage).toHaveBeenCalled() }) }) @@ -92,23 +87,26 @@ describe('Groups view', () => { describe('EditPanel', () => { it('should be available when one group is selected', () => { const { wrapper } = getWrapper() - wrapper.vm.selectedGroups = [{ id: '1' }] expect( - wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'EditPanel') + wrapper.vm.sideBarAvailablePanels + .find(({ name }) => name === 'EditPanel') + .isVisible({ items: [{ id: '1' }] }) ).toBeTruthy() }) it('should not be available when multiple groups are selected', () => { const { wrapper } = getWrapper() - wrapper.vm.selectedGroups = [{ id: '1' }, { id: '2' }] expect( - wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'EditPanel') + wrapper.vm.sideBarAvailablePanels + .find(({ name }) => name === 'EditPanel') + .isVisible({ items: [{ id: '1' }, { id: '2' }] }) ).toBeFalsy() }) it('should not be available when one read-only group is selected', () => { const { wrapper } = getWrapper() - wrapper.vm.selectedGroups = [{ id: '1', groupTypes: ['ReadOnly'] }] expect( - wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'EditPanel') + wrapper.vm.sideBarAvailablePanels + .find(({ name }) => name === 'EditPanel') + .isVisible({ items: [{ id: '1', groupTypes: ['ReadOnly'] }] }) ).toBeFalsy() }) }) @@ -116,7 +114,9 @@ describe('Groups view', () => { it('should contain DetailsPanel when no group is selected', () => { const { wrapper } = getWrapper() expect( - wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'DetailsPanel') + wrapper.vm.sideBarAvailablePanels + .find(({ name }) => name === 'DetailsPanel') + .isVisible({ items: [] }) ).toBeTruthy() }) }) @@ -150,6 +150,7 @@ function getWrapper({ clientService = getClientServiceMock() } = {}) { const storeOptions = { ...defaultStoreMockOptions } const store = createStore(storeOptions) return { + storeOptions, wrapper: mount(Groups, { global: { plugins: [...defaultPlugins(), store], diff --git a/packages/web-app-admin-settings/tests/unit/views/Users.spec.ts b/packages/web-app-admin-settings/tests/unit/views/Users.spec.ts index b6ee0d065f6..07cefcc603e 100644 --- a/packages/web-app-admin-settings/tests/unit/views/Users.spec.ts +++ b/packages/web-app-admin-settings/tests/unit/views/Users.spec.ts @@ -151,7 +151,7 @@ describe('Users view', () => { expect(createUserButton.exists()).toBeFalsy() }) }) - describe('method "createUser"', () => { + describe('method "onCreateUser"', () => { it('should hide the modal and show message on success', async () => { const clientService = getClientService() clientService.graphAuthenticated.users.createUser.mockImplementation(() => @@ -185,30 +185,26 @@ describe('Users view', () => { surname: 'bene' }) ) - const { wrapper } = getMountedWrapper({ clientService }) - const showMessageStub = jest.spyOn(wrapper.vm, 'showMessage') - const toggleCreateUserModalStub = jest.spyOn(wrapper.vm, 'toggleCreateUserModal') - await wrapper.vm.createUser({ displayName: 'jan' }) + const { wrapper, storeOptions } = getMountedWrapper({ clientService }) + expect(wrapper.vm.createUserModalOpen).toBeFalsy() + await wrapper.vm.onCreateUser({ displayName: 'jan' }) - expect(showMessageStub).toHaveBeenCalled() - expect(toggleCreateUserModalStub).toHaveBeenCalledTimes(1) + expect(storeOptions.actions.showMessage).toHaveBeenCalled() + expect(wrapper.vm.createUserModalOpen).toBeTruthy() }) it('should show message on error', async () => { jest.spyOn(console, 'error').mockImplementation(() => undefined) const clientService = getClientService() clientService.graphAuthenticated.users.createUser.mockImplementation(() => mockAxiosReject()) - const { wrapper } = getMountedWrapper({ clientService }) - const showErrorMessageStub = jest.spyOn(wrapper.vm, 'showErrorMessage') - const toggleCreateUserModalStub = jest.spyOn(wrapper.vm, 'toggleCreateUserModal') - await wrapper.vm.createUser({ displayName: 'jana' }) + const { wrapper, storeOptions } = getMountedWrapper({ clientService }) + await wrapper.vm.onCreateUser({ displayName: 'jana' }) - expect(showErrorMessageStub).toHaveBeenCalled() - expect(toggleCreateUserModalStub).toHaveBeenCalledTimes(0) + expect(storeOptions.actions.showErrorMessage).toHaveBeenCalled() }) }) - describe('method "editUser"', () => { + describe('method "onEditUser"', () => { it('should emit event on success', async () => { const editUser = { appRoleAssignments: [ @@ -283,23 +279,14 @@ describe('Users view', () => { }) ) - const { wrapper } = getMountedWrapper({ - clientService - }) + const { wrapper, storeOptions } = getMountedWrapper({ clientService }) const busStub = jest.spyOn(eventBus, 'publish') - const updateSpaceFieldStub = jest.spyOn(wrapper.vm, 'UPDATE_SPACE_FIELD') - const updateUserDriveStub = jest.spyOn(wrapper.vm, 'updateUserDrive') - const updateUserGroupAssignmentsStub = jest.spyOn(wrapper.vm, 'updateUserGroupAssignments') - const updateUserAppRoleAssignmentsStub = jest.spyOn( - wrapper.vm, - 'updateUserAppRoleAssignments' - ) await wrapper.vm.loadResourcesTask.last const userToUpDate = wrapper.vm.users.find((user) => user.id === '1') - const updatedUser = await wrapper.vm.editUser({ user: userToUpDate, editUser }) + const updatedUser = await wrapper.vm.onEditUser({ user: userToUpDate, editUser }) expect(updatedUser.id).toEqual('1') expect(updatedUser.displayName).toEqual('administrator') @@ -309,48 +296,49 @@ describe('Users view', () => { expect(updatedUser.memberOf[0].id).toEqual('1') expect(busStub).toHaveBeenCalled() - expect(updateUserDriveStub).toHaveBeenCalled() - expect(updateSpaceFieldStub).toHaveBeenCalled() - expect(updateUserGroupAssignmentsStub).toHaveBeenCalled() - expect(updateUserAppRoleAssignmentsStub).toHaveBeenCalled() + expect( + storeOptions.modules.runtime.modules.spaces.mutations.UPDATE_SPACE_FIELD + ).toHaveBeenCalled() }) it('should show message on error', async () => { jest.spyOn(console, 'error').mockImplementation(() => undefined) const clientService = getClientService() clientService.graphAuthenticated.users.editUser.mockImplementation(() => mockAxiosReject()) - const { wrapper } = getMountedWrapper({ clientService }) - const showErrorMessageStub = jest.spyOn(wrapper.vm, 'showErrorMessage') + const { wrapper, storeOptions } = getMountedWrapper({ clientService }) await wrapper.vm.loadResourcesTask.last - await wrapper.vm.editUser({ + await wrapper.vm.onEditUser({ editUser: {} }) - expect(showErrorMessageStub).toHaveBeenCalled() + expect(storeOptions.actions.showErrorMessage).toHaveBeenCalled() }) }) describe('computed method "sideBarAvailablePanels"', () => { it('should contain EditPanel when one user is selected', () => { const { wrapper } = getMountedWrapper() - wrapper.vm.selectedUsers = [{ id: '1' }] expect( - wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'EditPanel').enabled + wrapper.vm.sideBarAvailablePanels + .find(({ name }) => name === 'EditPanel') + .isVisible({ items: [{ id: '1' }] }) ).toBeTruthy() }) it('should contain DetailsPanel no user is selected', () => { const { wrapper } = getMountedWrapper() - wrapper.vm.selectedUsers = [] expect( - wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'DetailsPanel').enabled + wrapper.vm.sideBarAvailablePanels + .find(({ name }) => name === 'DetailsPanel') + .isVisible({ items: [] }) ).toBeTruthy() }) it('should not contain EditPanel when multiple users are selected', () => { const { wrapper } = getMountedWrapper() - wrapper.vm.selectedUsers = [{ id: '1' }, { id: '2' }] expect( - wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'EditPanel') + wrapper.vm.sideBarAvailablePanels + .find(({ name }) => name === 'EditPanel') + .isVisible({ items: [{ id: '1' }, { id: '2' }] }) ).toBeFalsy() }) }) @@ -517,6 +505,7 @@ function getMountedWrapper({ return { mocks, + storeOptions, wrapper: mountType(Users, { global: { plugins: [...defaultPlugins(), store], diff --git a/packages/web-app-admin-settings/tests/unit/views/__snapshots__/General.spec.ts.snap b/packages/web-app-admin-settings/tests/unit/views/__snapshots__/General.spec.ts.snap index c01ad2d76c9..661132031e5 100644 --- a/packages/web-app-admin-settings/tests/unit/views/__snapshots__/General.spec.ts.snap +++ b/packages/web-app-admin-settings/tests/unit/views/__snapshots__/General.spec.ts.snap @@ -2,6 +2,6 @@ exports[`General view renders component 1`] = `
- +
`; diff --git a/packages/web-app-admin-settings/tests/unit/views/__snapshots__/Spaces.spec.ts.snap b/packages/web-app-admin-settings/tests/unit/views/__snapshots__/Spaces.spec.ts.snap index 258f6d63b36..893e3aa3048 100644 --- a/packages/web-app-admin-settings/tests/unit/views/__snapshots__/Spaces.spec.ts.snap +++ b/packages/web-app-admin-settings/tests/unit/views/__snapshots__/Spaces.spec.ts.snap @@ -10,13 +10,6 @@ exports[`Spaces view loading states should render spaces list after loading has
-
diff --git a/packages/web-app-admin-settings/tests/unit/views/__snapshots__/Users.spec.ts.snap b/packages/web-app-admin-settings/tests/unit/views/__snapshots__/Users.spec.ts.snap index 81219294ed2..72935c32420 100644 --- a/packages/web-app-admin-settings/tests/unit/views/__snapshots__/Users.spec.ts.snap +++ b/packages/web-app-admin-settings/tests/unit/views/__snapshots__/Users.spec.ts.snap @@ -10,7 +10,6 @@ exports[`Users view list view renders initially warning if filters are mandatory
-
@@ -71,7 +70,6 @@ exports[`Users view list view renders list initially 1`] = `
-
diff --git a/packages/web-app-files/src/components/AppBar/CreateAndUpload.vue b/packages/web-app-files/src/components/AppBar/CreateAndUpload.vue index eac2522d749..2e67d77d4af 100644 --- a/packages/web-app-files/src/components/AppBar/CreateAndUpload.vue +++ b/packages/web-app-files/src/components/AppBar/CreateAndUpload.vue @@ -328,8 +328,7 @@ export default defineComponent({ const extensionActions = computed(() => { return [ ...extensionRegistry - .requestExtensions('action') - .filter(({ scopes }) => scopes.includes('upload-menu')) + .requestExtensions('action', ['upload-menu']) .map((e) => e.action) ].filter((e) => e.isEnabled()) }) diff --git a/packages/web-app-files/src/components/FilesList/QuickActions.vue b/packages/web-app-files/src/components/FilesList/QuickActions.vue index a6adaefc8a2..d622af92c0d 100644 --- a/packages/web-app-files/src/components/FilesList/QuickActions.vue +++ b/packages/web-app-files/src/components/FilesList/QuickActions.vue @@ -39,8 +39,7 @@ export default defineComponent({ const filteredActions = computed(() => { return unref(extensionRegistry) - .requestExtensions('action') - .filter(({ scopes }) => scopes.includes('files.quick-action')) + .requestExtensions('action', ['resource.quick-action']) .map((e) => e.action) .filter(({ isEnabled }) => isEnabled({ space: props.space, resources: [props.item] })) }) diff --git a/packages/web-app-files/src/components/Search/List.vue b/packages/web-app-files/src/components/Search/List.vue index f4e4e9f8401..97df756a8e3 100644 --- a/packages/web-app-files/src/components/Search/List.vue +++ b/packages/web-app-files/src/components/Search/List.vue @@ -1,7 +1,11 @@ - @@ -157,7 +161,7 @@ import { VisibilityObserver } from '@ownclouders/web-pkg' import { ImageType, ImageDimension } from '@ownclouders/web-pkg' import { NoContentMessage } from '@ownclouders/web-pkg' import { ResourceTable } from '@ownclouders/web-pkg' -import { ContextActions } from '@ownclouders/web-pkg' +import { ContextActions, FileSideBar } from '@ownclouders/web-pkg' import { debounce } from 'lodash-es' import { mapMutations, mapGetters, mapActions } from 'vuex' import { useGettext } from 'vue3-gettext' @@ -179,7 +183,6 @@ import { useFileActions } from '@ownclouders/web-pkg' import { searchLimit } from '../../search/sdk/list' import { Resource } from '@ownclouders/web-client' import FilesViewWrapper from '../FilesViewWrapper.vue' -import SideBar from '../../components/SideBar/SideBar.vue' import { queryItemAsString, useCapabilityFilesTags, @@ -225,7 +228,7 @@ type LastModifiedKeyword = { export default defineComponent({ components: { AppBar, - SideBar, + FileSideBar, AppLoadingSpinner, ContextActions, ListInfo, diff --git a/packages/web-app-files/src/components/Shares/SharedWithMeSection.vue b/packages/web-app-files/src/components/Shares/SharedWithMeSection.vue index 08a479bd2a5..b2ef5ac5134 100644 --- a/packages/web-app-files/src/components/Shares/SharedWithMeSection.vue +++ b/packages/web-app-files/src/components/Shares/SharedWithMeSection.vue @@ -19,7 +19,7 @@ v-model:selectedIds="selectedResourcesIds" :data-test-share-status="shareStatus" class="files-table" - :class="{ 'files-table-squashed': sideBarOpen }" + :class="{ 'files-table-squashed': isSideBarOpen }" :fields-displayed="displayedFields" sidebar-closed :are-thumbnails-displayed="displayThumbnails" @@ -171,7 +171,7 @@ export default defineComponent({ type: Boolean, default: true }, - sideBarOpen: { + isSideBarOpen: { type: Boolean, default: false }, diff --git a/packages/web-app-files/src/components/SideBar/Details/FileDetails.vue b/packages/web-app-files/src/components/SideBar/Details/FileDetails.vue index d3f6e5ea1b0..399e29d2b67 100644 --- a/packages/web-app-files/src/components/SideBar/Details/FileDetails.vue +++ b/packages/web-app-files/src/components/SideBar/Details/FileDetails.vue @@ -154,7 +154,19 @@ import WebDavDetails from '@ownclouders/web-pkg/src/components/SideBar/WebDavDet export default defineComponent({ name: 'FileDetails', components: { TagsSelect, WebDavDetails }, - setup() { + props: { + previewEnabled: { + type: Boolean, + required: false, + default: true + }, + tagsEnabled: { + type: Boolean, + required: false, + default: true + } + }, + setup(props) { const configurationManager = useConfigurationManager() const store = useStore() const clientService = useClientService() @@ -180,11 +192,14 @@ export default defineComponent({ await Promise.all(calls.map((p) => p.catch((e) => e))) } - const isFolder = computed(() => { - return unref(resource).isFolder + const isPreviewEnabled = computed(() => { + if (unref(resource).isFolder) { + return false + } + return props.previewEnabled }) const loadPreviewTask = useTask(function* (signal, resource) { - if (unref(isFolder)) { + if (!unref(isPreviewEnabled)) { preview.value = undefined return } @@ -195,7 +210,7 @@ export default defineComponent({ }) }).restartable() const isPreviewLoading = computed(() => { - if (unref(isFolder)) { + if (!unref(isPreviewEnabled)) { return false } return loadPreviewTask.isRunning || !loadPreviewTask.last @@ -240,12 +255,17 @@ export default defineComponent({ data: tagsHelper({ configurationManager: configurationManager }) } as ContextualHelper + const capabilityFilesTags = useCapabilityFilesTags() + const hasTags = computed(() => { + return props.tagsEnabled && unref(capabilityFilesTags) + }) + return { preview, isPublicLinkContext, space, resource, - hasTags: useCapabilityFilesTags(), + hasTags, isPreviewLoading, ancestorMetaData, sharedAncestor, diff --git a/packages/web-app-files/src/components/SideBar/Details/TagsSelect.vue b/packages/web-app-files/src/components/SideBar/Details/TagsSelect.vue index bebbe9b2b20..3290f87780a 100644 --- a/packages/web-app-files/src/components/SideBar/Details/TagsSelect.vue +++ b/packages/web-app-files/src/components/SideBar/Details/TagsSelect.vue @@ -1,8 +1,8 @@ - - - - diff --git a/packages/web-app-files/src/components/Spaces/SpaceHeader.vue b/packages/web-app-files/src/components/Spaces/SpaceHeader.vue index 16a37c6d2e7..fc5716f8b46 100644 --- a/packages/web-app-files/src/components/Spaces/SpaceHeader.vue +++ b/packages/web-app-files/src/components/Spaces/SpaceHeader.vue @@ -1,7 +1,7 @@ @@ -48,22 +49,26 @@ import ApplicationsMenu from './ApplicationsMenu.vue' import UserMenu from './UserMenu.vue' import Notifications from './Notifications.vue' import FeedbackLink from './FeedbackLink.vue' +import SideBarToggle from './SideBarToggle.vue' import ThemeSwitcher from './ThemeSwitcher.vue' import { useAbility, useCapabilityNotifications, useEmbedMode, + usePublicLinkContext, useRouter, useStore, useThemeStore, useUserContext } from '@ownclouders/web-pkg' +import { isRuntimeRoute } from '../../router' export default { components: { ApplicationsMenu, FeedbackLink, Notifications, + SideBarToggle, ThemeSwitcher, UserMenu }, @@ -81,6 +86,7 @@ export default { const notificationsSupport = useCapabilityNotifications() const isUserContext = useUserContext({ store }) + const isPublicLinkContext = usePublicLinkContext({ store }) const language = useGettext() const router = useRouter() const ability = useAbility() @@ -91,6 +97,13 @@ export default { return unref(isUserContext) && unref(notificationsSupport).includes('list') }) + const isSideBarToggleVisible = computed(() => { + return unref(isUserContext) || unref(isPublicLinkContext) + }) + const isSideBarToggleDisabled = computed(() => { + return isRuntimeRoute(unref(router.currentRoute)) + }) + const isNavItemPermitted = (permittedMenus, navItem) => { if (navItem.menu) { return permittedMenus.includes(navItem.menu) @@ -191,7 +204,9 @@ export default { userMenuItems, appMenuItems, logoWidth, - isEmbedModeEnabled + isEmbedModeEnabled, + isSideBarToggleVisible, + isSideBarToggleDisabled } }, computed: { diff --git a/packages/web-runtime/src/composables/layout/index.ts b/packages/web-runtime/src/composables/layout/index.ts new file mode 100644 index 00000000000..122053ee7bd --- /dev/null +++ b/packages/web-runtime/src/composables/layout/index.ts @@ -0,0 +1 @@ +export * from './useLayout' diff --git a/packages/web-runtime/src/composables/layout/useLayout.ts b/packages/web-runtime/src/composables/layout/useLayout.ts new file mode 100644 index 00000000000..6d09a3b0adc --- /dev/null +++ b/packages/web-runtime/src/composables/layout/useLayout.ts @@ -0,0 +1,63 @@ +import LayoutPlain from '../../layouts/Plain.vue' +import LayoutApplication from '../../layouts/Application.vue' +import LayoutLoading from '../../layouts/Loading.vue' +import { isPublicLinkContextRequired, isUserContextRequired } from '../../router' +import { computed, unref } from 'vue' +import { Router } from 'vue-router' +import { Store } from 'vuex' +import { useStore, useRouter, useUserContext, usePublicLinkContext } from '@ownclouders/web-pkg' + +export interface LayoutOptions { + store?: Store + router?: Router +} + +const layoutTypes = ['plain', 'loading', 'application'] as const +type LayoutType = (typeof layoutTypes)[number] + +export const useLayout = (options?: LayoutOptions) => { + const store = options?.store || useStore() + const router = options?.router || useRouter() + const isPublicLinkContextReady = usePublicLinkContext({ store }) + const isUserContextReady = useUserContext({ store }) + + const layoutType = computed(() => { + const plainLayoutRoutes = [ + 'login', + 'logout', + 'oidcCallback', + 'oidcSilentRedirect', + 'resolvePublicLink', + 'accessDenied' + ] + if ( + !unref(router.currentRoute).name || + plainLayoutRoutes.includes(unref(router.currentRoute).name as string) + ) { + return 'plain' + } + if (isPublicLinkContextRequired(router, unref(router.currentRoute))) { + return unref(isPublicLinkContextReady) ? 'application' : 'loading' + } + if (isUserContextRequired(router, unref(router.currentRoute))) { + return unref(isUserContextReady) ? 'application' : 'loading' + } + return 'application' + }) + + const layout = computed(() => { + switch (unref(layoutType)) { + case 'application': + return LayoutApplication + case 'loading': + return LayoutLoading + case 'plain': + default: + return LayoutPlain + } + }) + + return { + layout + } +} diff --git a/packages/web-runtime/src/layouts/Application.vue b/packages/web-runtime/src/layouts/Application.vue index ccaa42f9077..a6a4ffcaf9f 100644 --- a/packages/web-runtime/src/layouts/Application.vue +++ b/packages/web-runtime/src/layouts/Application.vue @@ -83,7 +83,10 @@ export default defineComponent({ const extensionNavItems = computed(() => extensionRegistry - .requestExtensions('sidebarNav', unref(activeApp)) + .requestExtensions('sidebarNav', [ + unref(activeApp), + `app.${unref(activeApp)}` + ]) .map(({ navItem }) => navItem) .filter((n) => n.enabled(store.getters.capabilities)) ) diff --git a/packages/web-runtime/src/router/helpers.ts b/packages/web-runtime/src/router/helpers.ts index 0ea0e94f280..c8431dc0e83 100644 --- a/packages/web-runtime/src/router/helpers.ts +++ b/packages/web-runtime/src/router/helpers.ts @@ -14,7 +14,7 @@ import { * @param to {Route} * @returns {boolean} */ -export const isUserContext = (router: Router, to: RouteLocation): boolean => { +export const isUserContextRequired = (router: Router, to: RouteLocation): boolean => { const meta = getRouteMeta(to) if (meta.authContext === 'user') { return true @@ -37,7 +37,7 @@ export const isUserContext = (router: Router, to: RouteLocation): boolean => { * @param to {Route} * @returns {boolean} */ -export const isIdpContext = (router: Router, to: RouteLocation): boolean => { +export const isIdpContextRequired = (router: Router, to: RouteLocation): boolean => { const meta = getRouteMeta(to) if (meta.authContext === 'idp') { return true @@ -56,7 +56,7 @@ export const isIdpContext = (router: Router, to: RouteLocation): boolean => { * @param to {Route} * @returns {boolean} */ -export const isPublicLinkContext = (router: Router, to: RouteLocation): boolean => { +export const isPublicLinkContextRequired = (router: Router, to: RouteLocation): boolean => { if ( (to.params.driveAliasAndItem as string)?.startsWith('public/') || (to.params.driveAliasAndItem as string)?.startsWith('ocm/') diff --git a/packages/web-runtime/src/router/index.ts b/packages/web-runtime/src/router/index.ts index 0550737cc69..6625ba7e77f 100644 --- a/packages/web-runtime/src/router/index.ts +++ b/packages/web-runtime/src/router/index.ts @@ -8,7 +8,12 @@ import ResolvePublicLinkPage from '../pages/resolvePublicLink.vue' import ResolvePrivateLinkPage from '../pages/resolvePrivateLink.vue' import { setupAuthGuard } from './setupAuthGuard' import { patchRouter } from './patchCleanPath' -import { createWebHashHistory, createWebHistory, createRouter } from 'vue-router' +import { + createWebHashHistory, + createWebHistory, + createRouter, + RouteLocationNormalizedLoaded +} from 'vue-router' export * from './helpers' export { createRouter } from 'vue-router' @@ -19,6 +24,62 @@ function $gettext(msg) { } export const base = document.querySelector('base') +const routes = [ + { + path: '/login', + name: 'login', + component: LoginPage, + meta: { title: $gettext('Login'), authContext: 'anonymous' } + }, + { + path: '/logout', + name: 'logout', + component: LogoutPage, + meta: { title: $gettext('Logout'), authContext: 'anonymous' } + }, + { + path: '/web-oidc-callback', + name: 'oidcCallback', + component: OidcCallbackPage, + meta: { title: $gettext('Oidc callback'), authContext: 'anonymous' } + }, + { + path: '/web-oidc-silent-redirect', + name: 'oidcSilentRedirect', + component: OidcCallbackPage, + meta: { title: $gettext('Oidc redirect'), authContext: 'anonymous' } + }, + { + path: '/f/:fileId', + name: 'resolvePrivateLink', + component: ResolvePrivateLinkPage, + meta: { title: $gettext('Private link'), authContext: 'user' } + }, + { + path: '/s/:token/:driveAliasAndItem(.*)?', + name: 'resolvePublicLink', + component: ResolvePublicLinkPage, + meta: { title: $gettext('Public link'), authContext: 'anonymous' } + }, + { + path: '/o/:token/:driveAliasAndItem(.*)?', + name: 'resolvePublicOcmLink', + component: ResolvePublicLinkPage, + meta: { title: $gettext('OCM link'), authContext: 'anonymous' } + }, + { + path: '/access-denied', + name: 'accessDenied', + component: AccessDeniedPage, + meta: { title: $gettext('Access denied'), authContext: 'anonymous' } + }, + { + path: '/account', + name: 'account', + component: Account, + meta: { title: $gettext('Account'), authContext: 'user' } + } +] export const router = patchRouter( createRouter({ parseQuery(query) { @@ -32,63 +93,12 @@ export const router = patchRouter( }) }, history: (base && createWebHistory(new URL(base.href).pathname)) || createWebHashHistory(), - routes: [ - { - path: '/login', - name: 'login', - component: LoginPage, - meta: { title: $gettext('Login'), authContext: 'anonymous' } - }, - { - path: '/logout', - name: 'logout', - component: LogoutPage, - meta: { title: $gettext('Logout'), authContext: 'anonymous' } - }, - { - path: '/web-oidc-callback', - name: 'oidcCallback', - component: OidcCallbackPage, - meta: { title: $gettext('Oidc callback'), authContext: 'anonymous' } - }, - { - path: '/web-oidc-silent-redirect', - name: 'oidcSilentRedirect', - component: OidcCallbackPage, - meta: { title: $gettext('Oidc redirect'), authContext: 'anonymous' } - }, - { - path: '/f/:fileId', - name: 'resolvePrivateLink', - component: ResolvePrivateLinkPage, - meta: { title: $gettext('Private link'), authContext: 'user' } - }, - { - path: '/s/:token/:driveAliasAndItem(.*)?', - name: 'resolvePublicLink', - component: ResolvePublicLinkPage, - meta: { title: $gettext('Public link'), authContext: 'anonymous' } - }, - { - path: '/o/:token/:driveAliasAndItem(.*)?', - name: 'resolvePublicOcmLink', - component: ResolvePublicLinkPage, - meta: { title: $gettext('OCM link'), authContext: 'anonymous' } - }, - { - path: '/access-denied', - name: 'accessDenied', - component: AccessDeniedPage, - meta: { title: $gettext('Access denied'), authContext: 'anonymous' } - }, - { - path: '/account', - name: 'account', - component: Account, - meta: { title: $gettext('Account'), authContext: 'user' } - } - ] + routes }) ) +export const isRuntimeRoute = (route: RouteLocationNormalizedLoaded) => { + return routes.map((r) => r.name).includes(route.name.toString()) +} + setupAuthGuard(router) diff --git a/packages/web-runtime/src/router/setupAuthGuard.ts b/packages/web-runtime/src/router/setupAuthGuard.ts index 377d4612273..0aa9841ec95 100644 --- a/packages/web-runtime/src/router/setupAuthGuard.ts +++ b/packages/web-runtime/src/router/setupAuthGuard.ts @@ -1,4 +1,9 @@ -import { extractPublicLinkToken, isIdpContext, isPublicLinkContext, isUserContext } from './index' +import { + extractPublicLinkToken, + isIdpContextRequired, + isPublicLinkContextRequired, + isUserContextRequired +} from './index' import { Router, RouteLocation } from 'vue-router' import { contextRouteNameKey, queryItemAsString, useEmbedMode } from '@ownclouders/web-pkg' import { authService } from '../services/auth/authService' @@ -23,7 +28,7 @@ export const setupAuthGuard = (router: Router) => { return to.name === 'accessDenied' || { name: 'accessDenied' } } - if (isPublicLinkContext(router, to)) { + if (isPublicLinkContextRequired(router, to)) { if (!store.getters['runtime/auth/isPublicLinkContextReady']) { const publicLinkToken = extractPublicLinkToken(to) return { @@ -35,7 +40,7 @@ export const setupAuthGuard = (router: Router) => { return true } - if (isUserContext(router, to)) { + if (isUserContextRequired(router, to)) { if (!store.getters['runtime/auth/isUserContextReady']) { if (unref(isDelegatingAuthentication)) { return { path: '/web-oidc-callback' } @@ -46,7 +51,7 @@ export const setupAuthGuard = (router: Router) => { return true } - if (isIdpContext(router, to)) { + if (isIdpContextRequired(router, to)) { if (!store.getters['runtime/auth/isIdpContextReady']) { if (unref(isDelegatingAuthentication)) { return { path: '/web-oidc-callback' } diff --git a/packages/web-runtime/src/services/auth/authService.ts b/packages/web-runtime/src/services/auth/authService.ts index 9f9c603919e..5b9bc458959 100644 --- a/packages/web-runtime/src/services/auth/authService.ts +++ b/packages/web-runtime/src/services/auth/authService.ts @@ -7,9 +7,9 @@ import { RouteLocation, Router } from 'vue-router' import { extractPublicLinkToken, isAnonymousContext, - isIdpContext, - isPublicLinkContext, - isUserContext + isIdpContextRequired, + isPublicLinkContextRequired, + isUserContextRequired } from '../../router' import { unref } from 'vue' import { Ability } from '@ownclouders/web-client/src/helpers/resource/types' @@ -65,7 +65,7 @@ export class AuthService { }) } - if (isPublicLinkContext(this.router, to)) { + if (isPublicLinkContextRequired(this.router, to)) { const publicLinkToken = extractPublicLinkToken(to) if (publicLinkToken) { await this.publicLinkManager.updateContext(publicLinkToken) @@ -85,7 +85,7 @@ export class AuthService { } if (!isAnonymousContext(this.router, to)) { - const fetchUserData = !isIdpContext(this.router, to) + const fetchUserData = !isIdpContextRequired(this.router, to) if (!this.userManager.areEventHandlersRegistered) { this.userManager.events.addAccessTokenExpired((...args): void => { @@ -242,7 +242,7 @@ export class AuthService { } public async handleAuthError(route: RouteLocation) { - if (isPublicLinkContext(this.router, route)) { + if (isPublicLinkContextRequired(this.router, route)) { const token = extractPublicLinkToken(route) this.publicLinkManager.clear(token) return this.router.push({ @@ -251,7 +251,7 @@ export class AuthService { query: { redirectUrl: route.fullPath } }) } - if (isUserContext(this.router, route) || isIdpContext(this.router, route)) { + if (isUserContextRequired(this.router, route) || isIdpContextRequired(this.router, route)) { // defines a number of seconds after a token expired. // if that threshold surpasses we assume a regular token expiry instead of an auth error. // as a result, the user will be logged out. diff --git a/packages/web-runtime/src/store/apps.ts b/packages/web-runtime/src/store/apps.ts index 86f5c4fedd7..8f29ffca103 100644 --- a/packages/web-runtime/src/store/apps.ts +++ b/packages/web-runtime/src/store/apps.ts @@ -2,7 +2,6 @@ const state = { fileEditors: [], fileEditorConfigs: {}, newFileHandlers: [], - fileSideBars: [], customFilesListIndicators: [], meta: {} } @@ -55,15 +54,6 @@ const mutations = { }) }) } - if (appInfo.fileSideBars) { - // Merge in file side bars into global list - // Reassign object in whole so that it updates the state properly - const list = state.fileSideBars - appInfo.fileSideBars.forEach((sideBar) => { - list.push(sideBar) - }) - state.fileSideBars = list - } if (appInfo.filesListIndicators) { const indicators = state.customFilesListIndicators @@ -109,9 +99,6 @@ const getters = { newFileHandlers: (state) => { return state.newFileHandlers }, - fileSideBars: (state) => { - return state.fileSideBars - }, customFilesListIndicators: (state) => state.customFilesListIndicators, extensionConfigByAppId: (state) => (appId) => { return state.fileEditorConfigs[appId] || {} diff --git a/packages/web-pkg/tests/unit/components/AppBar/SidebarToggle.spec.ts b/packages/web-runtime/tests/unit/components/Topbar/SidebarToggle.spec.ts similarity index 77% rename from packages/web-pkg/tests/unit/components/AppBar/SidebarToggle.spec.ts rename to packages/web-runtime/tests/unit/components/Topbar/SidebarToggle.spec.ts index ab89a75e2ad..b5919497c2a 100644 --- a/packages/web-pkg/tests/unit/components/AppBar/SidebarToggle.spec.ts +++ b/packages/web-runtime/tests/unit/components/Topbar/SidebarToggle.spec.ts @@ -1,5 +1,5 @@ -import SidebarToggle from '../../../../src/components/AppBar/SidebarToggle.vue' -import { eventBus } from '../../../../src/services' +import SidebarToggle from '../../../../src/components/Topbar/SideBarToggle.vue' +import { eventBus } from '@ownclouders/web-pkg/src/services' import { createStore, defaultPlugins, @@ -15,8 +15,8 @@ const selectors = { describe('SidebarToggle component', () => { it.each([true, false])( 'should show the "Toggle sidebar"-button with sidebar opened and closed', - (sideBarOpen) => { - const { wrapper } = getWrapper({ sideBarOpen }) + (isSideBarOpen) => { + const { wrapper } = getWrapper({ isSideBarOpen }) expect(wrapper.find(selectors.toggleSidebarBtn).exists()).toBeTruthy() expect(wrapper.html()).toMatchSnapshot() } @@ -29,7 +29,7 @@ describe('SidebarToggle component', () => { }) }) -function getWrapper({ sideBarOpen = false } = {}) { +function getWrapper({ isSideBarOpen = false } = {}) { const storeOptions = { ...defaultStoreMockOptions } const store = createStore(storeOptions) const mocks = defaultComponentMocks() @@ -37,7 +37,7 @@ function getWrapper({ sideBarOpen = false } = {}) { storeOptions, mocks, wrapper: mount(SidebarToggle, { - props: { sideBarOpen }, + props: { isSideBarOpen }, global: { mocks, plugins: [...defaultPlugins(), store] diff --git a/packages/web-pkg/tests/unit/components/AppBar/__snapshots__/SidebarToggle.spec.ts.snap b/packages/web-runtime/tests/unit/components/Topbar/__snapshots__/SidebarToggle.spec.ts.snap similarity index 63% rename from packages/web-pkg/tests/unit/components/AppBar/__snapshots__/SidebarToggle.spec.ts.snap rename to packages/web-runtime/tests/unit/components/Topbar/__snapshots__/SidebarToggle.spec.ts.snap index e21e1822f98..9ae2b8cc962 100644 --- a/packages/web-pkg/tests/unit/components/AppBar/__snapshots__/SidebarToggle.spec.ts.snap +++ b/packages/web-runtime/tests/unit/components/Topbar/__snapshots__/SidebarToggle.spec.ts.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`SidebarToggle component should show the "Toggle sidebar"-button with sidebar opened and closed 1`] = ` -