Skip to content

Commit

Permalink
Merge pull request #47305 from nextcloud/backport/47287/stable30
Browse files Browse the repository at this point in the history
  • Loading branch information
skjnldsv authored Aug 18, 2024
2 parents 4bc14ed + 6f40578 commit eb1a26e
Show file tree
Hide file tree
Showing 19 changed files with 147 additions and 31 deletions.
1 change: 1 addition & 0 deletions apps/files/src/components/FileEntry/FileEntryActions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
:close-after-click="!isMenu(action.id)"
:data-cy-files-list-row-action="action.id"
:is-menu="isMenu(action.id)"
:aria-label="action.title?.([source], currentView)"
:title="action.title?.([source], currentView)"
@click="onActionClick(action)">
<template #icon>
Expand Down
2 changes: 1 addition & 1 deletion apps/files/src/newMenu/newFolder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const entry = {
source,
id: fileid,
mtime: new Date(),
owner: getCurrentUser()?.uid || null,
owner: context.owner,
permissions: Permission.ALL,
root: context?.root || '/files/' + getCurrentUser()?.uid,
// Include mount-type from parent folder as this is inherited
Expand Down
40 changes: 25 additions & 15 deletions apps/files_sharing/src/actions/sharingStatusAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ export const action = new FileAction({
displayName(nodes: Node[]) {
const node = nodes[0]
const shareTypes = Object.values(node?.attributes?.['share-types'] || {}).flat() as number[]
const ownerId = node?.attributes?.['owner-id']

if (shareTypes.length > 0
|| (ownerId !== getCurrentUser()?.uid || isExternal(node))) {
|| (node.owner !== getCurrentUser()?.uid || isExternal(node))) {
return t('files_sharing', 'Shared')
}

Expand All @@ -38,19 +37,32 @@ export const action = new FileAction({

title(nodes: Node[]) {
const node = nodes[0]
const ownerId = node?.attributes?.['owner-id']
const ownerDisplayName = node?.attributes?.['owner-display-name']

// Mixed share types
if (Array.isArray(node.attributes?.['share-types']) && node.attributes?.['share-types'].length > 1) {
if (node.owner && (node.owner !== getCurrentUser()?.uid || isExternal(node))) {
const ownerDisplayName = node?.attributes?.['owner-display-name']
return t('files_sharing', 'Shared by {ownerDisplayName}', { ownerDisplayName })
}

const shareTypes = Object.values(node?.attributes?.['share-types'] || {}).flat() as number[]
if (shareTypes.length > 1) {
return t('files_sharing', 'Shared multiple times with different people')
}

if (ownerId && (ownerId !== getCurrentUser()?.uid || isExternal(node))) {
return t('files_sharing', 'Shared by {ownerDisplayName}', { ownerDisplayName })
const sharees = node.attributes.sharees?.sharee as { id: string, 'display-name': string, type: ShareType }[] | undefined
if (!sharees) {
// No sharees so just show the default message to create a new share
return t('files_sharing', 'Show sharing options')
}

return t('files_sharing', 'Show sharing options')
const sharee = [sharees].flat()[0] // the property is sometimes weirdly normalized, so we need to compensate
switch (sharee.type) {
case ShareType.User:
return t('files_sharing', 'Shared with {user}', { user: sharee['display-name'] })
case ShareType.Group:
return t('files_sharing', 'Shared with group {group}', { group: sharee['display-name'] ?? sharee.id })
default:
return t('files_sharing', 'Shared with others')
}
},

iconSvgInline(nodes: Node[]) {
Expand All @@ -69,7 +81,7 @@ export const action = new FileAction({
}

// Group shares
if (shareTypes.includes(ShareType.Grup)
if (shareTypes.includes(ShareType.Group)
|| shareTypes.includes(ShareType.RemoteGroup)) {
return AccountGroupSvg
}
Expand All @@ -79,9 +91,8 @@ export const action = new FileAction({
return CircleSvg
}

const ownerId = node?.attributes?.['owner-id']
if (ownerId && (ownerId !== getCurrentUser()?.uid || isExternal(node))) {
return generateAvatarSvg(ownerId, isExternal(node))
if (node.owner && (node.owner !== getCurrentUser()?.uid || isExternal(node))) {
return generateAvatarSvg(node.owner, isExternal(node))
}

return AccountPlusSvg
Expand All @@ -93,7 +104,6 @@ export const action = new FileAction({
}

const node = nodes[0]
const ownerId = node?.attributes?.['owner-id']
const shareTypes = node.attributes?.['share-types']
const isMixed = Array.isArray(shareTypes) && shareTypes.length > 0

Expand All @@ -104,7 +114,7 @@ export const action = new FileAction({
}

// If the node is shared by someone else
if (ownerId && (ownerId !== getCurrentUser()?.uid || isExternal(node))) {
if (node.owner !== getCurrentUser()?.uid || isExternal(node)) {
return true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ async function updateAvailableAccounts(path: string = '/') {
const { contents } = await currentView.value.getContents(path)
const available = new Map<string, IUserSelectData>()
for (const node of contents) {
const owner = node.owner ?? node.attributes['owner-id']
const owner = node.owner
if (owner && !available.has(owner)) {
available.set(owner, {
id: owner,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import NcUserBubble from '@nextcloud/vue/dist/Components/NcUserBubble.js'
const folder = ref<Folder>()
const note = computed<string>(() => folder.value?.attributes.note ?? '')
const user = computed(() => {
const id = folder.value?.attributes?.['owner-id']
const id = folder.value?.owner
const displayName = folder.value?.attributes?.['owner-display-name']
if (id !== getCurrentUser()?.uid) {
return {
Expand Down
105 changes: 105 additions & 0 deletions cypress/e2e/files_sharing/files-inline-action.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*!
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type { User } from '@nextcloud/cypress'
import { createShare } from './FilesSharingUtils.ts'
import { closeSidebar, getRowForFile } from '../files/FilesUtils.ts'

describe('files_sharing: Files inline status action', { testIsolation: true }, () => {
/**
* Regression test of https://github.com/nextcloud/server/issues/45723
*/
it('No "shared" tag when user ID is purely numerical', () => {
const user = {
language: 'en',
password: 'test1234',
userId: String(Math.floor(Math.random() * 1000)),
} as User
cy.createUser(user)
cy.mkdir(user, '/folder')
cy.login(user)

cy.visit('/apps/files')

getRowForFile('folder')
.should('be.visible')
.find('[data-cy-files-list-row-actions]')
.findByRole('button', { name: 'Shared' })
.should('not.exist')
})

describe('', () => {
let user: User
let sharee: User

beforeEach(() => {
cy.createRandomUser().then(($user) => {
user = $user
})
cy.createRandomUser().then(($user) => {
sharee = $user
})
})

it('Render quick option for sharing', () => {
cy.mkdir(user, '/folder')
cy.login(user)

cy.visit('/apps/files')
getRowForFile('folder')
.should('be.visible')

getRowForFile('folder')
.should('be.visible')
.find('[data-cy-files-list-row-actions]')
.findByRole('button', { name: /Show sharing options/ })
.should('be.visible')
.click()

// check the click opened the sidebar
cy.get('[data-cy-sidebar]')
.should('be.visible')
// and ensure the sharing tab is selected
.findByRole('tab', { name: 'Sharing', selected: true })
.should('exist')
})

it('Render inline status action for sharer', () => {
cy.mkdir(user, '/folder')
cy.login(user)

cy.visit('/apps/files')
getRowForFile('folder')
.should('be.visible')
createShare('folder', sharee.userId)
closeSidebar()

getRowForFile('folder')
.should('be.visible')
.find('[data-cy-files-list-row-actions]')
.findByRole('button', { name: /^Shared with/i })
.should('be.visible')
})

it('Render inline status action for sharee', () => {
cy.mkdir(user, '/folder')
cy.login(user)

cy.visit('/apps/files')
getRowForFile('folder')
.should('be.visible')
createShare('folder', sharee.userId)
closeSidebar()

cy.login(sharee)
cy.visit('/apps/files')

getRowForFile('folder')
.should('be.visible')
.find('[data-cy-files-list-row-actions]')
.findByRole('button', { name: `Shared by ${user.userId}` })
.should('be.visible')
})
})
})
2 changes: 0 additions & 2 deletions dist/5804-5804.js

This file was deleted.

Loading

0 comments on commit eb1a26e

Please sign in to comment.