Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stable28] fix(files_sharing): open-in-files should open a folder and not the parent #46754

Merged
merged 5 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/files_sharing/src/actions/openInFilesAction.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,6 @@ describe('Open in files action execute tests', () => {
// Silent action
expect(exec).toBe(null)
expect(goToRouteMock).toBeCalledTimes(1)
expect(goToRouteMock).toBeCalledWith(null, { fileid: 1, view: 'files' }, { dir: '/Foo', openfile: 'true' })
expect(goToRouteMock).toBeCalledWith(null, { fileid: '1', view: 'files' }, { dir: '/Foo', openfile: 'true' })
})
})
16 changes: 13 additions & 3 deletions apps/files_sharing/src/actions/openInFilesAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*/
import type { Node } from '@nextcloud/files'

import { registerFileAction, FileAction, DefaultType } from '@nextcloud/files'
import { registerFileAction, FileAction, DefaultType, FileType } from '@nextcloud/files'
import { translate as t } from '@nextcloud/l10n'

import { sharesViewId, sharedWithYouViewId, sharedWithOthersViewId, sharingByLinksViewId } from '../views/shares'
Expand All @@ -41,10 +41,20 @@ export const action = new FileAction({
].includes(view.id),

async exec(node: Node) {
const isFolder = node.type === FileType.Folder

window.OCP.Files.Router.goToRoute(
null, // use default route
{ view: 'files', fileid: node.fileid },
{ dir: node.dirname, openfile: 'true' },
{
view: 'files',
fileid: String(node.fileid),
},
{
// If this node is a folder open the folder in files
dir: isFolder ? node.path : node.dirname,
// otherwise if this is a file, we should open it
openfile: isFolder ? undefined : 'true',
},
)
return null
},
Expand Down
1 change: 1 addition & 0 deletions apps/files_sharing/src/components/SharingEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
@open-sharing-details="openShareDetailsForCustomSettings(share)" />
</div>
<NcButton class="sharing-entry__action"
data-cy-files-sharing-share-actions
:aria-label="t('files_sharing', 'Open Sharing Details')"
type="tertiary"
@click="openSharingDetails(share)">
Expand Down
35 changes: 27 additions & 8 deletions apps/files_sharing/src/views/SharingDetailsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<div ref="quickPermissions" class="sharingTabDetailsView__quick-permissions">
<div>
<NcCheckboxRadioSwitch :button-variant="true"
data-cy-files-sharing-share-permissions-bundle="read-only"
:checked.sync="sharingPermission"
:value="bundledPermissions.READ_ONLY.toString()"
name="sharing_permission_radio"
Expand All @@ -31,6 +32,7 @@
</template>
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch :button-variant="true"
data-cy-files-sharing-share-permissions-bundle="upload-edit"
:checked.sync="sharingPermission"
:value="bundledPermissions.ALL.toString()"
name="sharing_permission_radio"
Expand All @@ -48,6 +50,7 @@
</template>
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch v-if="allowsFileDrop"
data-cy-files-sharing-share-permissions-bundle="file-drop"
:button-variant="true"
:checked.sync="sharingPermission"
:value="bundledPermissions.FILE_DROP.toString()"
Expand All @@ -62,6 +65,7 @@
</template>
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch :button-variant="true"
data-cy-files-sharing-share-permissions-bundle="custom"
:checked.sync="sharingPermission"
:value="'custom'"
name="sharing_permission_radio"
Expand Down Expand Up @@ -146,7 +150,10 @@
@update:checked="queueUpdate('hideDownload')">
{{ t('files_sharing', 'Hide download') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch v-if="!isPublicShare" :disabled="!canSetDownload" :checked.sync="canDownload">
<NcCheckboxRadioSwitch v-if="!isPublicShare"
:disabled="!canSetDownload"
:checked.sync="canDownload"
data-cy-files-sharing-share-permissions-checkbox="download">
{{ t('files_sharing', 'Allow download') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch :checked.sync="writeNoteToRecipientIsChecked">
Expand All @@ -163,21 +170,30 @@
</NcCheckboxRadioSwitch>
<section v-if="setCustomPermissions" class="custom-permissions-group">
<NcCheckboxRadioSwitch :disabled="!canRemoveReadPermission"
:checked.sync="hasRead">
:checked.sync="hasRead"
data-cy-files-sharing-share-permissions-checkbox="read">
{{ t('files_sharing', 'Read') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch v-if="isFolder" :disabled="!canSetCreate" :checked.sync="canCreate">
<NcCheckboxRadioSwitch v-if="isFolder"
:disabled="!canSetCreate"
:checked.sync="canCreate"
data-cy-files-sharing-share-permissions-checkbox="create">
{{ t('files_sharing', 'Create') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch :disabled="!canSetEdit" :checked.sync="canEdit">
<NcCheckboxRadioSwitch :disabled="!canSetEdit"
:checked.sync="canEdit"
data-cy-files-sharing-share-permissions-checkbox="update">
{{ t('files_sharing', 'Edit') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch v-if="config.isResharingAllowed && share.type !== SHARE_TYPES.SHARE_TYPE_LINK"
:disabled="!canSetReshare"
:checked.sync="canReshare">
:checked.sync="canReshare"
data-cy-files-sharing-share-permissions-checkbox="share">
{{ t('files_sharing', 'Share') }}
</NcCheckboxRadioSwitch>
<NcCheckboxRadioSwitch :disabled="!canSetDelete" :checked.sync="canDelete">
<NcCheckboxRadioSwitch :disabled="!canSetDelete"
:checked.sync="canDelete"
data-cy-files-sharing-share-permissions-checkbox="delete">
{{ t('files_sharing', 'Delete') }}
</NcCheckboxRadioSwitch>
</section>
Expand All @@ -200,10 +216,13 @@

<div class="sharingTabDetailsView__footer">
<div class="button-group">
<NcButton @click="$emit('close-sharing-details')">
<NcButton data-cy-files-sharing-share-editor-action="cancel"
@click="$emit('close-sharing-details')">
{{ t('files_sharing', 'Cancel') }}
</NcButton>
<NcButton type="primary" @click="saveShare">
<NcButton type="primary"
data-cy-files-sharing-share-editor-action="save"
@click="saveShare">
{{ shareButtonText }}
<template v-if="creating" #icon>
<NcLoadingIcon />
Expand Down
7 changes: 6 additions & 1 deletion apps/files_versions/src/components/Version.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<NcListItem class="version"
:name="versionLabel"
:force-display-actions="true"
data-files-versions-version
:data-files-versions-version="version.fileVersion"
@click="click">
<template #icon>
<div v-if="!(loadPreview || previewLoaded)" class="version__image" />
Expand Down Expand Up @@ -47,6 +47,7 @@
</template>
<template #actions>
<NcActionButton v-if="enableLabeling && hasUpdatePermissions"
data-cy-files-versions-version-action="label"
:close-after-click="true"
@click="labelUpdate">
<template #icon>
Expand All @@ -55,6 +56,7 @@
{{ version.label === '' ? t('files_versions', 'Name this version') : t('files_versions', 'Edit version name') }}
</NcActionButton>
<NcActionButton v-if="!isCurrent && canView && canCompare"
data-cy-files-versions-version-action="compare"
:close-after-click="true"
@click="compareVersion">
<template #icon>
Expand All @@ -63,6 +65,7 @@
{{ t('files_versions', 'Compare to current version') }}
</NcActionButton>
<NcActionButton v-if="!isCurrent && hasUpdatePermissions"
data-cy-files-versions-version-action="restore"
:close-after-click="true"
@click="restoreVersion">
<template #icon>
Expand All @@ -71,6 +74,7 @@
{{ t('files_versions', 'Restore version') }}
</NcActionButton>
<NcActionLink v-if="isDownloadable"
data-cy-files-versions-version-action="download"
:href="downloadURL"
:close-after-click="true"
:download="downloadURL">
Expand All @@ -80,6 +84,7 @@
{{ t('files_versions', 'Download version') }}
</NcActionLink>
<NcActionButton v-if="!isCurrent && enableDeletion && hasDeletePermissions"
data-cy-files-versions-version-action="delete"
:close-after-click="true"
@click="deleteVersion">
<template #icon>
Expand Down
183 changes: 183 additions & 0 deletions cypress/e2e/files_sharing/FilesSharingUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/**
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
/* eslint-disable jsdoc/require-jsdoc */
import { triggerActionForFile } from '../files/FilesUtils'

export interface ShareSetting {
read: boolean
update: boolean
delete: boolean
share: boolean
download: boolean
note: string
}

export function createShare(fileName: string, username: string, shareSettings: Partial<ShareSetting> = {}) {
openSharingPanel(fileName)

cy.get('#app-sidebar-vue').within(() => {
cy.get('#sharing-search-input').clear()
cy.intercept({ times: 1, method: 'GET', url: '**/apps/files_sharing/api/v1/sharees?*' }).as('userSearch')
cy.get('#sharing-search-input').type(username)
cy.wait('@userSearch')
})

cy.get(`[user="${username}"]`).click()

// HACK: Save the share and then update it, as permissions changes are currently not saved for new share.
cy.get('[data-cy-files-sharing-share-editor-action="save"]').click({ scrollBehavior: 'nearest' })
updateShare(fileName, 0, shareSettings)
}

export function updateShare(fileName: string, index: number, shareSettings: Partial<ShareSetting> = {}) {
openSharingPanel(fileName)

cy.intercept({ times: 1, method: 'PUT', url: '**/apps/files_sharing/api/v1/shares/*' }).as('updateShare')

cy.get('#app-sidebar-vue').within(() => {
cy.get('[data-cy-files-sharing-share-actions]').eq(index).click()
cy.get('[data-cy-files-sharing-share-permissions-bundle="custom"]').click()

if (shareSettings.download !== undefined) {
cy.get('[data-cy-files-sharing-share-permissions-checkbox="download"]').find('input').as('downloadCheckbox')
if (shareSettings.download) {
// Force:true because the checkbox is hidden by the pretty UI.
cy.get('@downloadCheckbox').check({ force: true, scrollBehavior: 'nearest' })
} else {
// Force:true because the checkbox is hidden by the pretty UI.
cy.get('@downloadCheckbox').uncheck({ force: true, scrollBehavior: 'nearest' })
}
}

if (shareSettings.read !== undefined) {
cy.get('[data-cy-files-sharing-share-permissions-checkbox="read"]').find('input').as('readCheckbox')
if (shareSettings.read) {
// Force:true because the checkbox is hidden by the pretty UI.
cy.get('@readCheckbox').check({ force: true, scrollBehavior: 'nearest' })
} else {
// Force:true because the checkbox is hidden by the pretty UI.
cy.get('@readCheckbox').uncheck({ force: true, scrollBehavior: 'nearest' })
}
}

if (shareSettings.update !== undefined) {
cy.get('[data-cy-files-sharing-share-permissions-checkbox="update"]').find('input').as('updateCheckbox')
if (shareSettings.update) {
// Force:true because the checkbox is hidden by the pretty UI.
cy.get('@updateCheckbox').check({ force: true, scrollBehavior: 'nearest' })
} else {
// Force:true because the checkbox is hidden by the pretty UI.
cy.get('@updateCheckbox').uncheck({ force: true, scrollBehavior: 'nearest' })
}
}

if (shareSettings.delete !== undefined) {
cy.get('[data-cy-files-sharing-share-permissions-checkbox="delete"]').find('input').as('deleteCheckbox')
if (shareSettings.delete) {
// Force:true because the checkbox is hidden by the pretty UI.
cy.get('@deleteCheckbox').check({ force: true, scrollBehavior: 'nearest' })
} else {
// Force:true because the checkbox is hidden by the pretty UI.
cy.get('@deleteCheckbox').uncheck({ force: true, scrollBehavior: 'nearest' })
}
}

if (shareSettings.note !== undefined) {
cy.findByRole('checkbox', { name: /note to recipient/i }).check({ force: true, scrollBehavior: 'nearest' })
cy.findByRole('textbox', { name: /note to recipient/i }).type(shareSettings.note)
}

cy.get('[data-cy-files-sharing-share-editor-action="save"]').click({ scrollBehavior: 'nearest' })

cy.wait('@updateShare')
})
}

export function openSharingPanel(fileName: string) {
triggerActionForFile(fileName, 'details')

cy.get('#app-sidebar-vue')
.get('[aria-controls="tab-sharing"]')
.click()
}

type FileRequestOptions = {
label?: string
note?: string
password?: string
/* YYYY-MM-DD format */
expiration?: string
}

/**
* Create a file request for a folder
* @param path The path of the folder, leading slash is required
* @param options The options for the file request
*/
export const createFileRequest = (path: string, options: FileRequestOptions = {}) => {
if (!path.startsWith('/')) {
throw new Error('Path must start with a slash')
}

// Navigate to the folder
cy.visit('/apps/files/files?dir=' + path)

// Open the file request dialog
cy.get('[data-cy-upload-picker] .action-item__menutoggle').first().click()
cy.contains('.upload-picker__menu-entry button', 'Create file request').click()
cy.get('[data-cy-file-request-dialog]').should('be.visible')

// Check and fill the first page options
cy.get('[data-cy-file-request-dialog-fieldset="label"]').should('be.visible')
cy.get('[data-cy-file-request-dialog-fieldset="destination"]').should('be.visible')
cy.get('[data-cy-file-request-dialog-fieldset="note"]').should('be.visible')

cy.get('[data-cy-file-request-dialog-fieldset="destination"] input').should('contain.value', path)
if (options.label) {
cy.get('[data-cy-file-request-dialog-fieldset="label"] input').type(`{selectall}${options.label}`)
}
if (options.note) {
cy.get('[data-cy-file-request-dialog-fieldset="note"] textarea').type(`{selectall}${options.note}`)
}

// Go to the next page
cy.get('[data-cy-file-request-dialog-controls="next"]').click()
cy.get('[data-cy-file-request-dialog-fieldset="expiration"] input[type="checkbox"]').should('exist')
cy.get('[data-cy-file-request-dialog-fieldset="expiration"] input[type="date"]').should('not.exist')
cy.get('[data-cy-file-request-dialog-fieldset="password"] input[type="checkbox"]').should('exist')
cy.get('[data-cy-file-request-dialog-fieldset="password"] input[type="password"]').should('not.exist')
if (options.expiration) {
cy.get('[data-cy-file-request-dialog-fieldset="expiration"] input[type="checkbox"]').check({ force: true })
cy.get('[data-cy-file-request-dialog-fieldset="expiration"] input[type="date"]').type(`{selectall}${options.expiration}`)
}
if (options.password) {
cy.get('[data-cy-file-request-dialog-fieldset="password"] input[type="checkbox"]').check({ force: true })
cy.get('[data-cy-file-request-dialog-fieldset="password"] input[type="password"]').type(`{selectall}${options.password}`)
}

// Create the file request
cy.get('[data-cy-file-request-dialog-controls="next"]').click()

// Get the file request URL
cy.get('[data-cy-file-request-dialog-fieldset="link"]').then(($link) => {
const url = $link.val()
cy.log(`File request URL: ${url}`)
cy.wrap(url).as('fileRequestUrl')
})

// Close
cy.get('[data-cy-file-request-dialog-controls="finish"]').click()
}

export const enterGuestName = (name: string) => {
cy.get('[data-cy-public-auth-prompt-dialog]').should('be.visible')
cy.get('[data-cy-public-auth-prompt-dialog-name]').should('be.visible')
cy.get('[data-cy-public-auth-prompt-dialog-submit]').should('be.visible')

cy.get('[data-cy-public-auth-prompt-dialog-name]').type(`{selectall}${name}`)
cy.get('[data-cy-public-auth-prompt-dialog-submit]').click()

cy.get('[data-cy-public-auth-prompt-dialog]').should('not.exist')
}
Loading
Loading