Merge pull request #47305 from nextcloud/backport/47287/stable30

This commit is contained in:
John Molakvoæ 2024-08-18 13:28:00 +02:00 committed by GitHub
commit eb1a26e530
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 149 additions and 33 deletions

View file

@ -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>

View file

@ -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

View file

@ -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')
}
@ -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) {
return t('files_sharing', 'Shared multiple times with different people')
}
if (ownerId && (ownerId !== getCurrentUser()?.uid || isExternal(node))) {
if (node.owner && (node.owner !== getCurrentUser()?.uid || isExternal(node))) {
const ownerDisplayName = node?.attributes?.['owner-display-name']
return t('files_sharing', 'Shared by {ownerDisplayName}', { ownerDisplayName })
}
return t('files_sharing', 'Show sharing options')
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')
}
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')
}
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[]) {
@ -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
}
@ -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
@ -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
@ -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
}

View file

@ -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,

View file

@ -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 {

View file

@ -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
dist/5804-5804.js vendored
View file

@ -1,2 +0,0 @@
"use strict";(self.webpackChunknextcloud=self.webpackChunknextcloud||[]).push([[5804],{34604:(e,t,n)=>{n.d(t,{A:()=>a});var r=n(71354),o=n.n(r),i=n(76314),s=n.n(i)()(o());s.push([e.id,"\n.note-to-recipient[data-v-77889141] {\n\tmargin-inline: var(--row-height)\n}\n.note-to-recipient__text[data-v-77889141] {\n\t/* respect new lines */\n\twhite-space: pre-line;\n}\n.note-to-recipient__heading[data-v-77889141] {\n\tfont-weight: bold;\n}\n@media screen and (max-width: 512px) {\n.note-to-recipient[data-v-77889141] {\n\t\tmargin-inline: var(--default-grid-baseline);\n}\n}\n","",{version:3,sources:["webpack://./apps/files_sharing/src/views/FilesHeaderNoteToRecipient.vue"],names:[],mappings:";AAsDA;CACA;AACA;AAEA;CACA,sBAAA;CACA,qBAAA;AACA;AAEA;CACA,iBAAA;AACA;AAEA;AACA;EACA,2CAAA;AACA;AACA",sourcesContent:["\x3c!--\n - SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n--\x3e\n<template>\n\t<NcNoteCard v-if=\"note.length > 0\"\n\t\tclass=\"note-to-recipient\"\n\t\ttype=\"info\">\n\t\t<p v-if=\"user\" class=\"note-to-recipient__heading\">\n\t\t\t{{ t('files_sharing', 'Note from') }}\n\t\t\t<NcUserBubble :user=\"user.id\" :display-name=\"user.displayName\" />\n\t\t</p>\n\t\t<p v-else class=\"note-to-recipient__heading\">\n\t\t\t{{ t('files_sharing', 'Note:') }}\n\t\t</p>\n\t\t<p class=\"note-to-recipient__text\" v-text=\"note\" />\n\t</NcNoteCard>\n</template>\n\n<script setup lang=\"ts\">\nimport type { Folder } from '@nextcloud/files'\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { t } from '@nextcloud/l10n'\nimport { computed, ref } from 'vue'\n\nimport NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'\nimport NcUserBubble from '@nextcloud/vue/dist/Components/NcUserBubble.js'\n\nconst folder = ref<Folder>()\nconst note = computed<string>(() => folder.value?.attributes.note ?? '')\nconst user = computed(() => {\n\tconst id = folder.value?.attributes?.['owner-id']\n\tconst displayName = folder.value?.attributes?.['owner-display-name']\n\tif (id !== getCurrentUser()?.uid) {\n\t\treturn {\n\t\t\tid,\n\t\t\tdisplayName,\n\t\t}\n\t}\n\treturn null\n})\n\n/**\n * Update the current folder\n * @param newFolder the new folder to show note for\n */\nfunction updateFolder(newFolder: Folder) {\n\tfolder.value = newFolder\n}\n\ndefineExpose({ updateFolder })\n<\/script>\n\n<style scoped>\n.note-to-recipient {\n\tmargin-inline: var(--row-height)\n}\n\n.note-to-recipient__text {\n\t/* respect new lines */\n\twhite-space: pre-line;\n}\n\n.note-to-recipient__heading {\n\tfont-weight: bold;\n}\n\n@media screen and (max-width: 512px) {\n\t.note-to-recipient {\n\t\tmargin-inline: var(--default-grid-baseline);\n\t}\n}\n</style>\n"],sourceRoot:""}]);const a=s},75804:(e,t,n)=>{n.d(t,{default:()=>x});var r=n(85471),o=n(21777),i=n(53334),s=n(80910),a=n(47741);const l=(0,r.pM)({__name:"FilesHeaderNoteToRecipient",setup(e,t){let{expose:n}=t;const l=(0,r.KR)(),d=(0,r.EW)((()=>l.value?.attributes.note??"")),c=(0,r.EW)((()=>{const e=l.value?.attributes?.["owner-id"],t=l.value?.attributes?.["owner-display-name"];return e!==(0,o.HW)()?.uid?{id:e,displayName:t}:null}));function p(e){l.value=e}return n({updateFolder:p}),{__sfc:!0,folder:l,note:d,user:c,updateFolder:p,t:i.t,NcNoteCard:s.A,NcUserBubble:a.N}}});var d=n(85072),c=n.n(d),p=n(97825),u=n.n(p),A=n(77659),m=n.n(A),f=n(55056),_=n.n(f),C=n(10540),h=n.n(C),v=n(41113),N=n.n(v),g=n(34604),b={};b.styleTagTransform=N(),b.setAttributes=_(),b.insert=m().bind(null,"head"),b.domAPI=u(),b.insertStyleElement=h(),c()(g.A,b),g.A&&g.A.locals&&g.A.locals;const x=(0,n(14486).A)(l,(function(){var e=this,t=e._self._c,n=e._self._setupProxy;return n.note.length>0?t(n.NcNoteCard,{staticClass:"note-to-recipient",attrs:{type:"info"}},[n.user?t("p",{staticClass:"note-to-recipient__heading"},[e._v("\n\t\t"+e._s(n.t("files_sharing","Note from"))+"\n\t\t"),t(n.NcUserBubble,{attrs:{user:n.user.id,"display-name":n.user.displayName}})],1):t("p",{staticClass:"note-to-recipient__heading"},[e._v("\n\t\t"+e._s(n.t("files_sharing","Note:"))+"\n\t")]),e._v(" "),t("p",{staticClass:"note-to-recipient__text",domProps:{textContent:e._s(n.note)}})]):e._e()}),[],!1,null,"77889141",null).exports}}]);
//# sourceMappingURL=5804-5804.js.map?v=e347ebb5e67ef9049a78

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
5804-5804.js.license

2
dist/9196-9196.js vendored Normal file
View file

@ -0,0 +1,2 @@
"use strict";(self.webpackChunknextcloud=self.webpackChunknextcloud||[]).push([[9196],{4532:(e,t,n)=>{n.d(t,{A:()=>a});var o=n(71354),r=n.n(o),i=n(76314),s=n.n(i)()(r());s.push([e.id,"\n.note-to-recipient[data-v-514f64d7] {\n\tmargin-inline: var(--row-height)\n}\n.note-to-recipient__text[data-v-514f64d7] {\n\t/* respect new lines */\n\twhite-space: pre-line;\n}\n.note-to-recipient__heading[data-v-514f64d7] {\n\tfont-weight: bold;\n}\n@media screen and (max-width: 512px) {\n.note-to-recipient[data-v-514f64d7] {\n\t\tmargin-inline: var(--default-grid-baseline);\n}\n}\n","",{version:3,sources:["webpack://./apps/files_sharing/src/views/FilesHeaderNoteToRecipient.vue"],names:[],mappings:";AAsDA;CACA;AACA;AAEA;CACA,sBAAA;CACA,qBAAA;AACA;AAEA;CACA,iBAAA;AACA;AAEA;AACA;EACA,2CAAA;AACA;AACA",sourcesContent:["\x3c!--\n - SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n--\x3e\n<template>\n\t<NcNoteCard v-if=\"note.length > 0\"\n\t\tclass=\"note-to-recipient\"\n\t\ttype=\"info\">\n\t\t<p v-if=\"user\" class=\"note-to-recipient__heading\">\n\t\t\t{{ t('files_sharing', 'Note from') }}\n\t\t\t<NcUserBubble :user=\"user.id\" :display-name=\"user.displayName\" />\n\t\t</p>\n\t\t<p v-else class=\"note-to-recipient__heading\">\n\t\t\t{{ t('files_sharing', 'Note:') }}\n\t\t</p>\n\t\t<p class=\"note-to-recipient__text\" v-text=\"note\" />\n\t</NcNoteCard>\n</template>\n\n<script setup lang=\"ts\">\nimport type { Folder } from '@nextcloud/files'\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { t } from '@nextcloud/l10n'\nimport { computed, ref } from 'vue'\n\nimport NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'\nimport NcUserBubble from '@nextcloud/vue/dist/Components/NcUserBubble.js'\n\nconst folder = ref<Folder>()\nconst note = computed<string>(() => folder.value?.attributes.note ?? '')\nconst user = computed(() => {\n\tconst id = folder.value?.owner\n\tconst displayName = folder.value?.attributes?.['owner-display-name']\n\tif (id !== getCurrentUser()?.uid) {\n\t\treturn {\n\t\t\tid,\n\t\t\tdisplayName,\n\t\t}\n\t}\n\treturn null\n})\n\n/**\n * Update the current folder\n * @param newFolder the new folder to show note for\n */\nfunction updateFolder(newFolder: Folder) {\n\tfolder.value = newFolder\n}\n\ndefineExpose({ updateFolder })\n<\/script>\n\n<style scoped>\n.note-to-recipient {\n\tmargin-inline: var(--row-height)\n}\n\n.note-to-recipient__text {\n\t/* respect new lines */\n\twhite-space: pre-line;\n}\n\n.note-to-recipient__heading {\n\tfont-weight: bold;\n}\n\n@media screen and (max-width: 512px) {\n\t.note-to-recipient {\n\t\tmargin-inline: var(--default-grid-baseline);\n\t}\n}\n</style>\n"],sourceRoot:""}]);const a=s},59196:(e,t,n)=>{n.d(t,{default:()=>b});var o=n(85471),r=n(21777),i=n(53334),s=n(80910),a=n(47741);const l=(0,o.pM)({__name:"FilesHeaderNoteToRecipient",setup(e,t){let{expose:n}=t;const l=(0,o.KR)(),d=(0,o.EW)((()=>l.value?.attributes.note??"")),c=(0,o.EW)((()=>{const e=l.value?.owner,t=l.value?.attributes?.["owner-display-name"];return e!==(0,r.HW)()?.uid?{id:e,displayName:t}:null}));function p(e){l.value=e}return n({updateFolder:p}),{__sfc:!0,folder:l,note:d,user:c,updateFolder:p,t:i.t,NcNoteCard:s.A,NcUserBubble:a.N}}});var d=n(85072),c=n.n(d),p=n(97825),u=n.n(p),A=n(77659),f=n.n(A),m=n(55056),_=n.n(m),C=n(10540),h=n.n(C),v=n(41113),N=n.n(v),g=n(4532),x={};x.styleTagTransform=N(),x.setAttributes=_(),x.insert=f().bind(null,"head"),x.domAPI=u(),x.insertStyleElement=h(),c()(g.A,x),g.A&&g.A.locals&&g.A.locals;const b=(0,n(14486).A)(l,(function(){var e=this,t=e._self._c,n=e._self._setupProxy;return n.note.length>0?t(n.NcNoteCard,{staticClass:"note-to-recipient",attrs:{type:"info"}},[n.user?t("p",{staticClass:"note-to-recipient__heading"},[e._v("\n\t\t"+e._s(n.t("files_sharing","Note from"))+"\n\t\t"),t(n.NcUserBubble,{attrs:{user:n.user.id,"display-name":n.user.displayName}})],1):t("p",{staticClass:"note-to-recipient__heading"},[e._v("\n\t\t"+e._s(n.t("files_sharing","Note:"))+"\n\t")]),e._v(" "),t("p",{staticClass:"note-to-recipient__text",domProps:{textContent:e._s(n.note)}})]):e._e()}),[],!1,null,"514f64d7",null).exports}}]);
//# sourceMappingURL=9196-9196.js.map?v=a819b92b9042f565c1cf

1
dist/9196-9196.js.map vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/9196-9196.js.map.license vendored Symbolic link
View file

@ -0,0 +1 @@
9196-9196.js.license

4
dist/files-init.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

4
dist/files-main.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long