From a5e0412b2a544da2ed51136215b72299c29ab67d Mon Sep 17 00:00:00 2001 From: JanAckermann Date: Wed, 20 Apr 2022 14:34:20 +0200 Subject: [PATCH] Add unshare dialog --- ...nhancement-add-unshare-confirmation-dialog | 6 +++ .../components/SideBar/Shares/FileShares.vue | 33 ++++++++++++- .../SideBar/Shares/SpaceMembers.vue | 48 +++++++++++++++---- .../SideBar/Shares/FileShares.spec.js | 11 +++-- .../SideBar/Shares/SpaceMembers.spec.js | 12 ++++- .../SharingDialog/collaboratorsDialog.js | 14 ++++++ .../objects/app-files/share/actions.ts | 3 +- 7 files changed, 111 insertions(+), 16 deletions(-) create mode 100644 changelog/unreleased/enhancement-add-unshare-confirmation-dialog diff --git a/changelog/unreleased/enhancement-add-unshare-confirmation-dialog b/changelog/unreleased/enhancement-add-unshare-confirmation-dialog new file mode 100644 index 00000000000..65628ce17b6 --- /dev/null +++ b/changelog/unreleased/enhancement-add-unshare-confirmation-dialog @@ -0,0 +1,6 @@ +Enhancement: Add un-share confirmation dialog + +We have implemented a confirmation dialog which pops up if the user clicks the "remove share" button + +https://github.com/owncloud/web/pull/6795 +https://github.com/owncloud/web/issues/6728 diff --git a/packages/web-app-files/src/components/SideBar/Shares/FileShares.vue b/packages/web-app-files/src/components/SideBar/Shares/FileShares.vue index 7bd923436f9..21b8ca223d5 100644 --- a/packages/web-app-files/src/components/SideBar/Shares/FileShares.vue +++ b/packages/web-app-files/src/components/SideBar/Shares/FileShares.vue @@ -41,7 +41,7 @@ :share="collaborator" :modifiable="!collaborator.indirect" :shared-parent-route="getSharedParentRoute(collaborator)" - @onDelete="$_ocCollaborators_deleteShare" + @onDelete="$_ocCollaborators_deleteShare_trigger" /> @@ -306,6 +306,7 @@ export default { 'deleteShare', 'loadIncomingShares' ]), + ...mapActions(['createModal', 'hideModal', 'showMessage']), $_isCollaboratorShare(collaborator) { return ShareTypes.containsAnyValue(ShareTypes.authenticated, [collaborator.shareType]) }, @@ -337,6 +338,23 @@ export default { toggleShareeList() { this.showShareesList = !this.showShareesList }, + + $_ocCollaborators_deleteShare_trigger(share) { + const modal = { + variation: 'danger', + title: this.$gettext('Remove share'), + cancelText: this.$gettext('Cancel'), + confirmText: this.$gettext('Remove'), + icon: 'alarm-warning', + message: this.$gettext('Are you sure you want to remove this share?'), + hasInput: false, + onCancel: this.hideModal, + onConfirm: () => this.$_ocCollaborators_deleteShare(share) + } + + this.createModal(modal) + }, + $_ocCollaborators_deleteShare(share) { this.deleteShare({ client: this.$client, @@ -344,6 +362,19 @@ export default { resource: this.highlightedFile, storageId: this.$route.params.storageId }) + .then(() => { + this.hideModal() + this.showMessage({ + title: this.$gettext('Share was removed successfully') + }) + }) + .catch((error) => { + console.error(error) + this.showMessage({ + title: this.$gettext('Failed to remove share'), + status: 'danger' + }) + }) }, $_reloadShares() { this.loadCurrentFileOutgoingShares({ diff --git a/packages/web-app-files/src/components/SideBar/Shares/SpaceMembers.vue b/packages/web-app-files/src/components/SideBar/Shares/SpaceMembers.vue index 061b7358278..bb09f872d1c 100644 --- a/packages/web-app-files/src/components/SideBar/Shares/SpaceMembers.vue +++ b/packages/web-app-files/src/components/SideBar/Shares/SpaceMembers.vue @@ -13,7 +13,7 @@ @@ -104,6 +104,7 @@ export default defineComponent({ }, methods: { ...mapActions('Files', ['loadCurrentFileOutgoingShares', 'deleteShare']), + ...mapActions(['createModal', 'hideModal', 'showMessage']), isModifiable(share) { if (!this.currentUserIsManager) { @@ -120,21 +121,50 @@ export default defineComponent({ ) return managers.length > 1 }, + + $_ocCollaborators_deleteShare_trigger(share) { + const modal = { + variation: 'danger', + title: this.$gettext('Remove share'), + cancelText: this.$gettext('Cancel'), + confirmText: this.$gettext('Remove'), + icon: 'alarm-warning', + message: this.$gettext('Are you sure you want to remove this share?'), + hasInput: false, + onCancel: this.hideModal, + onConfirm: () => this.$_ocCollaborators_deleteShare(share) + } + + this.createModal(modal) + }, + $_ocCollaborators_deleteShare(share) { this.deleteShare({ client: this.$client, graphClient: this.graphClient, share: share, resource: this.highlightedFile - }).then(() => { - // current user was removed from the share. - if (share.collaborator.name === this.user.id) { - if (isLocationSpacesActive(this.$router, 'files-spaces-projects')) { - return this.$router.go() - } - return this.$router.push(createLocationSpaces('files-spaces-projects')) - } }) + .then(() => { + this.hideModal() + this.showMessage({ + title: this.$gettext('Share was removed successfully') + }) + // current user was removed from the share. + if (share.collaborator.name === this.user.id) { + if (isLocationSpacesActive(this.$router, 'files-spaces-projects')) { + return this.$router.go() + } + return this.$router.push(createLocationSpaces('files-spaces-projects')) + } + }) + .catch((error) => { + console.error(error) + this.showMessage({ + title: this.$gettext('Failed to remove share'), + status: 'danger' + }) + }) } } }) diff --git a/packages/web-app-files/tests/unit/components/SideBar/Shares/FileShares.spec.js b/packages/web-app-files/tests/unit/components/SideBar/Shares/FileShares.spec.js index 9ad8cbea9ce..8305364d3ac 100644 --- a/packages/web-app-files/tests/unit/components/SideBar/Shares/FileShares.spec.js +++ b/packages/web-app-files/tests/unit/components/SideBar/Shares/FileShares.spec.js @@ -91,8 +91,8 @@ describe('FileShares', () => { }) it('reacts on delete events by collaborator list items', async () => { - const spyOnCollaboratorDelete = jest - .spyOn(FileShares.methods, '$_ocCollaborators_deleteShare') + const spyOnCollaboratorDeleteTrigger = jest + .spyOn(FileShares.methods, '$_ocCollaborators_deleteShare_trigger') .mockImplementation() const wrapper = getMountedWrapper({ user, @@ -100,7 +100,7 @@ describe('FileShares', () => { }) wrapper.find(selectors.firstCollaboratorListItem).vm.$emit('onDelete') await wrapper.vm.$nextTick() - expect(spyOnCollaboratorDelete).toHaveBeenCalledTimes(1) + expect(spyOnCollaboratorDeleteTrigger).toHaveBeenCalledTimes(1) }) it('reloads shares if highlighted file is changed', async () => { const spyOnReloadShares = jest @@ -207,6 +207,11 @@ const storeOptions = (data) => { } return { + actions: { + createModal: jest.fn(), + hideModal: jest.fn(), + showMessage: jest.fn() + }, state: { user }, diff --git a/packages/web-app-files/tests/unit/components/SideBar/Shares/SpaceMembers.spec.js b/packages/web-app-files/tests/unit/components/SideBar/Shares/SpaceMembers.spec.js index 88de97fddf3..a55ec8da42f 100644 --- a/packages/web-app-files/tests/unit/components/SideBar/Shares/SpaceMembers.spec.js +++ b/packages/web-app-files/tests/unit/components/SideBar/Shares/SpaceMembers.spec.js @@ -118,12 +118,15 @@ describe('SpaceMembers', () => { outgoingCollaborators: outgoingShares }) - const spyOnCollaboratorDelete = jest.spyOn(wrapper.vm, 'deleteShare') + const spyOnCollaboratorDeleteTrigger = jest.spyOn( + wrapper.vm, + '$_ocCollaborators_deleteShare_trigger' + ) wrapper .find(`div[data-testid="collaborator-user-item-${outgoingShares[0].collaborator.name}"]`) .vm.$emit('onDelete') await wrapper.vm.$nextTick() - expect(spyOnCollaboratorDelete).toHaveBeenCalledTimes(1) + expect(spyOnCollaboratorDeleteTrigger).toHaveBeenCalledTimes(1) }) }) }) @@ -132,6 +135,11 @@ const storeOptions = (data, isInLoadingState) => { const { user, outgoingCollaborators = [] } = data return { + actions: { + createModal: jest.fn(), + hideModal: jest.fn(), + showMessage: jest.fn() + }, state: { user }, diff --git a/tests/acceptance/pageObjects/FilesPageElement/SharingDialog/collaboratorsDialog.js b/tests/acceptance/pageObjects/FilesPageElement/SharingDialog/collaboratorsDialog.js index a2e1cb08b59..1a0a5c8231b 100644 --- a/tests/acceptance/pageObjects/FilesPageElement/SharingDialog/collaboratorsDialog.js +++ b/tests/acceptance/pageObjects/FilesPageElement/SharingDialog/collaboratorsDialog.js @@ -11,10 +11,16 @@ module.exports = { deleteShareWithUserGroup: function (collaborator) { this.expandShareEditDropdown(collaborator) const deleteSelector = this.elements.deleteShareButton.selector + const dialogSelector = this.elements.dialog.selector + const dialogConfirmSelector = this.elements.dialogConfirmBtn.selector + return this.useXpath() .waitForElementVisible(deleteSelector) .waitForAnimationToFinish() // wait for animation of share sliding out .click(deleteSelector) + .waitForElementVisible(dialogSelector) + .waitForAnimationToFinish() // wait for transition on the modal to finish + .click(dialogConfirmSelector) .waitForAjaxCallsToStartAndFinish() }, /** @@ -207,6 +213,14 @@ module.exports = { selector: '//button[contains(@class, "remove-share")]', locateStrategy: 'xpath' }, + dialog: { + selector: '//div[contains(@class, "oc-modal")]', + locateStrategy: 'xpath' + }, + dialogConfirmBtn: { + selector: '//button[contains(@class, "oc-modal-body-actions-confirm")]', + locateStrategy: 'xpath' + }, createShareDialog: { selector: '#new-collaborators-form' }, diff --git a/tests/e2e/support/objects/app-files/share/actions.ts b/tests/e2e/support/objects/app-files/share/actions.ts index cbc2e4cd031..6e33df5ebff 100644 --- a/tests/e2e/support/objects/app-files/share/actions.ts +++ b/tests/e2e/support/objects/app-files/share/actions.ts @@ -176,7 +176,8 @@ export const removeSharee = async (args: removeShareeArgs): Promise => { .locator( `${userColumn}//ul[contains(@class,"collaborator-edit-dropdown-options-list")]//button[contains(@class,"remove-share")]` ) - .click() + .click(), + page.locator('.oc-modal-body-actions-confirm').click() ]) } }