From d68f075b8689155dc90506239ad3379cc5fb9168 Mon Sep 17 00:00:00 2001 From: JanAckermann Date: Thu, 24 Feb 2022 11:23:17 +0100 Subject: [PATCH 1/8] Implement QuotaModal component --- .../SideBar/Actions/SpaceActions.vue | 27 ++- .../src/components/Spaces/QuotaModal.vue | 215 ++++++++++++++++++ .../src/mixins/spaces/actions/editQuota.js | 41 ++++ .../src/views/spaces/Project.vue | 16 +- .../unit/components/Spaces/QuotaModal.spec.js | 145 ++++++++++++ .../Spaces/ReadmeContentModal.spec.js | 11 +- .../unit/mixins/spaces/editQuota.spec.js | 28 +++ .../spaces/__snapshots__/Project.spec.js.snap | 2 + 8 files changed, 471 insertions(+), 14 deletions(-) create mode 100644 packages/web-app-files/src/components/Spaces/QuotaModal.vue create mode 100644 packages/web-app-files/src/mixins/spaces/actions/editQuota.js create mode 100644 packages/web-app-files/tests/unit/components/Spaces/QuotaModal.spec.js create mode 100644 packages/web-app-files/tests/unit/mixins/spaces/editQuota.spec.js diff --git a/packages/web-app-files/src/components/SideBar/Actions/SpaceActions.vue b/packages/web-app-files/src/components/SideBar/Actions/SpaceActions.vue index 1d5eb449ef5..fa1cc31c50b 100644 --- a/packages/web-app-files/src/components/SideBar/Actions/SpaceActions.vue +++ b/packages/web-app-files/src/components/SideBar/Actions/SpaceActions.vue @@ -5,6 +5,11 @@ :cancel="closeReadmeContentModal" :space="resources[0]" > + { return $gettext('Actions') }, - components: { ActionMenuItem, ReadmeContentModal }, - mixins: [Rename, Delete, EditDescription, EditReadmeContent, Disable, Restore, UploadImage], + components: { ActionMenuItem, QuotaModal, ReadmeContentModal }, + mixins: [ + Rename, + Delete, + EditDescription, + EditReadmeContent, + Disable, + Restore, + UploadImage, + EditQuota + ], computed: { ...mapGetters('Files', ['highlightedFile']), resources() { @@ -57,6 +73,7 @@ export default { ...this.$_editDescription_items, ...this.$_uploadImage_items, ...this.$_editReadmeContent_items, + ...this.$_editQuota_items, ...this.$_restore_items, ...this.$_delete_items, ...this.$_disable_items @@ -64,11 +81,17 @@ export default { }, readmeContentModalIsOpen() { return this.$data.$_editReadmeContent_modalOpen + }, + quotaModalIsOpen() { + return this.$data.$_editQuota_modalOpen } }, methods: { closeReadmeContentModal() { this.$_editReadmeContent_closeModal() + }, + closeQuotaModal() { + this.$_editQuota_closeModal() } } } diff --git a/packages/web-app-files/src/components/Spaces/QuotaModal.vue b/packages/web-app-files/src/components/Spaces/QuotaModal.vue new file mode 100644 index 00000000000..318ec60301e --- /dev/null +++ b/packages/web-app-files/src/components/Spaces/QuotaModal.vue @@ -0,0 +1,215 @@ + + + diff --git a/packages/web-app-files/src/mixins/spaces/actions/editQuota.js b/packages/web-app-files/src/mixins/spaces/actions/editQuota.js new file mode 100644 index 00000000000..d87e95fbc7b --- /dev/null +++ b/packages/web-app-files/src/mixins/spaces/actions/editQuota.js @@ -0,0 +1,41 @@ +import { mapState } from 'vuex' + +export default { + data: () => { + return { + $_editQuota_modalOpen: false + } + }, + computed: { + ...mapState('Files', ['currentFolder']), + $_editQuota_items() { + return [ + { + name: 'editQuota', + icon: 'hard-drive', + label: () => { + return this.$gettext('Edit quota') + }, + handler: this.$_editQuota_trigger, + isEnabled: ({ resources }) => { + if (resources.length !== 1) { + return false + } + + return resources[0].spaceQuota + }, + componentType: 'oc-button', + class: 'oc-files-actions-edit-quota-content-trigger' + } + ] + } + }, + methods: { + $_editQuota_trigger() { + this.$data.$_editQuota_modalOpen = true + }, + $_editQuota_closeModal() { + this.$data.$_editQuota_modalOpen = false + } + } +} diff --git a/packages/web-app-files/src/views/spaces/Project.vue b/packages/web-app-files/src/views/spaces/Project.vue index 83c1da7803a..4dfdd58cc63 100644 --- a/packages/web-app-files/src/views/spaces/Project.vue +++ b/packages/web-app-files/src/views/spaces/Project.vue @@ -9,6 +9,7 @@ :cancel="closeReadmeContentModal" :space="space" > +
jest.clearAllMocks()) + +describe('QuotaModal', () => { + describe('method "editQuota"', () => { + it('should show message on success', async () => { + mockAxios.request.mockImplementationOnce(() => { + return Promise.resolve({ + data: { + id: '1fe58d8b-aa69-4c22-baf7-97dd57479f22', + spaceQuota: { + remaining: 9999999836, + state: 'normal', + total: 10000000000, + used: 164 + } + } + }) + }) + + const wrapper = getWrapper() + const showMessageStub = jest.spyOn(wrapper.vm, 'showMessage') + const updateResourceFieldStub = jest.spyOn(wrapper.vm, 'UPDATE_RESOURCE_FIELD') + await wrapper.vm.editQuota() + + expect(updateResourceFieldStub).toHaveBeenCalledTimes(1) + expect(showMessageStub).toHaveBeenCalledTimes(1) + }) + + it('should show message on server error', async () => { + mockAxios.request.mockImplementationOnce(() => { + return Promise.reject(new Error()) + }) + + const wrapper = getWrapper() + const showMessageStub = jest.spyOn(wrapper.vm, 'showMessage') + const updateResourceFieldStub = jest.spyOn(wrapper.vm, 'UPDATE_RESOURCE_FIELD') + await wrapper.vm.editQuota() + + expect(updateResourceFieldStub).toHaveBeenCalledTimes(0) + expect(showMessageStub).toHaveBeenCalledTimes(1) + }) + + it('should show message while selected value is not set', async () => { + const wrapper = getWrapper() + const showMessageStub = jest.spyOn(wrapper.vm, 'showMessage') + const updateResourceFieldStub = jest.spyOn(wrapper.vm, 'UPDATE_RESOURCE_FIELD') + wrapper.vm.selectedOption = {} + await wrapper.vm.editQuota() + + expect(updateResourceFieldStub).toHaveBeenCalledTimes(0) + expect(showMessageStub).toHaveBeenCalledTimes(1) + }) + }) + describe('method "optionSelectable"', () => { + it('should return true while option is a number', async () => { + const wrapper = getWrapper() + expect(wrapper.vm.optionSelectable({ value: 11 })).toBeTruthy() + expect(wrapper.vm.optionSelectable({ value: 11.2 })).toBeTruthy() + }) + + it('should return false while option is not a number', async () => { + const wrapper = getWrapper() + expect(wrapper.vm.optionSelectable({ value: null })).toBeFalsy() + expect(wrapper.vm.optionSelectable({ value: 'lorem ipsum' })).toBeFalsy() + }) + }) +}) + +function getWrapper() { + return mount(QuotaModal, { + localVue, + mocks: { + $gettext: jest.fn(), + $gettextInterpolate: jest.fn() + }, + data: () => { + return { + selectedOption: { + displayValue: '10', + displayUnit: 'GB', + value: 10 * Math.pow(10, 9) + } + } + }, + store: createStore(Vuex.Store, { + actions: { + showMessage: jest.fn() + }, + getters: { + configuration: () => ({ + server: 'https://example.com' + }), + getToken: () => 'token' + }, + modules: { + Files: { + namespaced: true, + mutations: { + UPDATE_RESOURCE_FIELD: jest.fn() + } + } + } + }), + propsData: { + cancel: jest.fn(), + space: { + id: '1fe58d8b-aa69-4c22-baf7-97dd57479f22', + spaceQuota: { + remaining: 9999999836, + state: 'normal', + total: 10000000000, + used: 164 + } + } + }, + modules: { + Files: { + namespaced: true, + mutations: { + UPDATE_RESOURCE_FIELD: jest.fn() + }, + state: { + currentFolder: { + id: '1fe58d8b-aa69-4c22-baf7-97dd57479f22', + spaceReadmeData: { + webDavUrl: + 'https://localhost:9200/dav/spaces/1fe58d8b-aa69-4c22-baf7-97dd57479f22/.space/readme.md' + } + } + } + } + }, + stubs: { ...stubs, portal: true, 'oc-modal': true } + }) +} diff --git a/packages/web-app-files/tests/unit/components/Spaces/ReadmeContentModal.spec.js b/packages/web-app-files/tests/unit/components/Spaces/ReadmeContentModal.spec.js index 32b57b45fe8..e8c860e112b 100644 --- a/packages/web-app-files/tests/unit/components/Spaces/ReadmeContentModal.spec.js +++ b/packages/web-app-files/tests/unit/components/Spaces/ReadmeContentModal.spec.js @@ -11,7 +11,7 @@ localVue.use(Vuex) afterEach(() => jest.clearAllMocks()) -describe('editReadmeContent', () => { +describe('ReadeContentModal', () => { describe('method "editReadme"', () => { it('should show message on success', async () => { const wrapper = getWrapper() @@ -69,15 +69,6 @@ function getWrapper(resolvePutFileContents = true) { namespaced: true, mutations: { UPDATE_RESOURCE_FIELD: jest.fn() - }, - state: { - currentFolder: { - id: '1fe58d8b-aa69-4c22-baf7-97dd57479f22', - spaceReadmeData: { - webDavUrl: - 'https://localhost:9200/dav/spaces/1fe58d8b-aa69-4c22-baf7-97dd57479f22/.space/readme.md' - } - } } } } diff --git a/packages/web-app-files/tests/unit/mixins/spaces/editQuota.spec.js b/packages/web-app-files/tests/unit/mixins/spaces/editQuota.spec.js new file mode 100644 index 00000000000..ab366684465 --- /dev/null +++ b/packages/web-app-files/tests/unit/mixins/spaces/editQuota.spec.js @@ -0,0 +1,28 @@ +import Vuex from 'vuex' +import { mount, createLocalVue } from '@vue/test-utils' +import EditQuota from '@files/src/mixins/spaces/actions/editQuota.js' + +const localVue = createLocalVue() +localVue.use(Vuex) + +const Component = { + render() {}, + mixins: [EditQuota] +} + +describe('editQuota', () => { + afterEach(() => jest.clearAllMocks()) + + describe('isEnabled property', () => { + it('should be false when not resource given', () => { + const wrapper = getWrapper() + expect(wrapper.vm.$_editQuota_items[0].isEnabled({ resources: [] })).toBe(false) + }) + }) +}) + +function getWrapper() { + return mount(Component, { + localVue + }) +} diff --git a/packages/web-app-files/tests/unit/views/spaces/__snapshots__/Project.spec.js.snap b/packages/web-app-files/tests/unit/views/spaces/__snapshots__/Project.spec.js.snap index f8dd2e660b1..d2ec3a7e51a 100644 --- a/packages/web-app-files/tests/unit/views/spaces/__snapshots__/Project.spec.js.snap +++ b/packages/web-app-files/tests/unit/views/spaces/__snapshots__/Project.spec.js.snap @@ -3,6 +3,7 @@ exports[`Spaces project view space image should show if given 1`] = `
+
@@ -72,6 +73,7 @@ exports[`Spaces project view space image should show if given 1`] = ` exports[`Spaces project view space readme should show if given 1`] = `
+
From 57714392d8bfd58e343c8c4ce4b2e0ee223e3b5f Mon Sep 17 00:00:00 2001 From: JanAckermann Date: Thu, 3 Mar 2022 10:36:58 +0100 Subject: [PATCH 2/8] Add changelog item --- changelog/unreleased/enhancement-space-quota | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 changelog/unreleased/enhancement-space-quota diff --git a/changelog/unreleased/enhancement-space-quota b/changelog/unreleased/enhancement-space-quota new file mode 100644 index 00000000000..51b81eb2e0b --- /dev/null +++ b/changelog/unreleased/enhancement-space-quota @@ -0,0 +1,6 @@ +Enhancement: Allow updating space quota + +We have implemented a way to update the space's quota + +https://github.com/owncloud/web/pull/6477 +https://github.com/owncloud/web/issues/6470 From b5e7859a5e337a2d7421a7520bb86f2356f556c5 Mon Sep 17 00:00:00 2001 From: JanAckermann Date: Thu, 3 Mar 2022 10:42:44 +0100 Subject: [PATCH 3/8] Remove uneccerssary ids --- packages/web-app-files/src/components/Spaces/QuotaModal.vue | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/web-app-files/src/components/Spaces/QuotaModal.vue b/packages/web-app-files/src/components/Spaces/QuotaModal.vue index 318ec60301e..066d6848e31 100644 --- a/packages/web-app-files/src/components/Spaces/QuotaModal.vue +++ b/packages/web-app-files/src/components/Spaces/QuotaModal.vue @@ -1,7 +1,6 @@