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()
])
}
}