Skip to content

Commit

Permalink
Merge pull request #12044 from owncloud/fix/paste-in-same-folder
Browse files Browse the repository at this point in the history
fix: disable paste button in same folder
  • Loading branch information
LukasHirt authored Dec 19, 2024
2 parents 764b4e2 + bc3da28 commit 92b1b3a
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Bugfix: Disable paste action in same folder

We've fixed the state of the "paste files" action when copied resources are from the same folder. The button will be disabled in such case and a tooltip with explanation message displayed.

https://github.com/owncloud/web/pull/12044
https://github.com/owncloud/web/issues/12021
46 changes: 37 additions & 9 deletions packages/web-app-files/src/components/AppBar/CreateAndUpload.vue
Original file line number Diff line number Diff line change
Expand Up @@ -158,14 +158,12 @@
<div
v-if="showPasteHereButton"
id="clipboard-btns"
v-oc-tooltip="
uploadOrFileCreationBlocked ? $gettext('You have no permission to paste files here!') : ''
"
v-oc-tooltip="pasteHereButtonTooltip"
class="oc-button-group"
:class="{ disabled: uploadOrFileCreationBlocked }"
:class="{ disabled: isPasteHereButtonDisabled }"
>
<oc-button
:disabled="uploadOrFileCreationBlocked"
:disabled="isPasteHereButtonDisabled"
class="paste-files-btn"
@click="pasteFileAction"
>
Expand Down Expand Up @@ -270,6 +268,7 @@ export default defineComponent({
const sharesStore = useSharesStore()
const route = useRoute()
const language = useGettext()
const { $gettext } = language
const clipboardStore = useClipboardStore()
const { clearClipboard } = clipboardStore
Expand Down Expand Up @@ -401,6 +400,36 @@ export default defineComponent({
}
}
const uploadOrFileCreationBlocked = computed(() => {
return !unref(canUpload)
})
const isPastingIntoSameFolder = computed(() => {
if (!unref(clipboardResources) || unref(clipboardResources).length < 1) {
return false
}
return !unref(clipboardResources).some(
(resource) => resource.parentFolderId !== unref(currentFolder).id
)
})
const isPasteHereButtonDisabled = computed(() => {
return unref(uploadOrFileCreationBlocked) || unref(isPastingIntoSameFolder)
})
const pasteHereButtonTooltip = computed(() => {
if (unref(uploadOrFileCreationBlocked)) {
return $gettext('You have no permission to paste files here.')
}
if (unref(isPastingIntoSameFolder)) {
return $gettext('You cannot paste resources into the same folder.')
}
return ''
})
onMounted(() => {
uploadCompletedSub = uppyService.subscribe('uploadCompleted', onUploadComplete)
document.addEventListener('paste', handlePasteFileEvent)
Expand Down Expand Up @@ -446,6 +475,9 @@ export default defineComponent({
areFileExtensionsShown,
clearClipboard,
clipboardResources,
uploadOrFileCreationBlocked,
isPasteHereButtonDisabled,
pasteHereButtonTooltip,
// HACK: exported for unit tests:
onUploadComplete
Expand Down Expand Up @@ -493,10 +525,6 @@ export default defineComponent({
return this.$gettext('Upload files or folders')
},
uploadOrFileCreationBlocked() {
return !this.canUpload
},
folderIconResource() {
return { isFolder: true, extension: '' } as Resource
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,34 @@ describe('CreateAndUpload component', () => {
const clipboardStore = useClipboardStore()
expect(clipboardStore.clearClipboard).toHaveBeenCalled()
})
it('should disable the "paste files"-action when clipboardResources are from same folder', () => {
const { wrapper } = getWrapper({
clipboardResources: [mock<Resource>({ parentFolderId: 'current-folder' })],
currentFolder: mock<Resource>({
id: 'current-folder',
canUpload: vi.fn().mockReturnValue(true)
})
})
expect(
wrapper.findComponent<typeof OcButton>(elSelector.pasteFilesBtn).vm.disabled
).toStrictEqual(true)
})

it('should not disable the "paste files"-action when at least one clipboardResources is not from same folder', () => {
const { wrapper } = getWrapper({
clipboardResources: [
mock<Resource>({ parentFolderId: 'current-folder' }),
mock<Resource>({ parentFolderId: 'another-folder' })
],
currentFolder: mock<Resource>({
id: 'current-folder',
canUpload: vi.fn().mockReturnValue(true)
})
})
expect(
wrapper.findComponent<typeof OcButton>(elSelector.pasteFilesBtn).vm.disabled
).toStrictEqual(false)
})
})
describe('method "onUploadComplete"', () => {
it.each([
Expand Down
11 changes: 8 additions & 3 deletions tests/e2e/support/objects/app-files/resource/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const uploadInfoCloseButton = '#close-upload-info-btn'
const uploadErrorCloseButton = '.oc-notification-message-danger button[aria-label="Close"]'
const filesBatchAction = '.files-app-bar-actions .oc-files-actions-%s-trigger'
const pasteButton = '.paste-files-btn'
const breadcrumbRoot = '//nav[contains(@class, "oc-breadcrumb")]/ol/li[1]'
const breadcrumbRoot = '//nav[@id="files-breadcrumb"]//li[1]'
const fileRenameInput = '.oc-text-input'
const deleteButtonSidebar = '#oc-files-actions-sidebar .oc-files-actions-delete-trigger'
const actionConfirmationButton =
Expand Down Expand Up @@ -881,6 +881,11 @@ export const pasteResource = async (args: moveOrCopyResourceArgs): Promise<void>
}
}

const selectBatchAction = async (page: Page, action: string): Promise<void> => {
await page.locator(util.format(filesBatchAction, action)).click()
await page.mouse.move(0, 0)
}

export const moveOrCopyMultipleResources = async (
args: moveOrCopyMultipleResourceArgs
): Promise<void> => {
Expand Down Expand Up @@ -922,7 +927,7 @@ export const moveOrCopyMultipleResources = async (
break
}
case 'batch-action': {
await page.locator(util.format(filesBatchAction, action)).click()
await selectBatchAction(page, action)

await page.locator(breadcrumbRoot).click()
const newLocationPath = newLocation.split('/')
Expand Down Expand Up @@ -994,7 +999,7 @@ export const moveOrCopyResource = async (args: moveOrCopyResourceArgs): Promise<
}
case 'batch-action': {
await page.locator(util.format(checkBox, resourceBase)).click()
await page.locator(util.format(filesBatchAction, action)).click()
await selectBatchAction(page, action)
await pasteResource({ page, resource: resourceBase, newLocation, action, method, option })
break
}
Expand Down

0 comments on commit 92b1b3a

Please sign in to comment.