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

[stable29] enh: Improvements on sharing details #50015

Open
wants to merge 5 commits into
base: stable29
Choose a base branch
from
Open
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
40 changes: 37 additions & 3 deletions apps/files/src/actions/sidebarAction.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*
*/
import { expect } from '@jest/globals'
import { File, Permission, View, FileAction } from '@nextcloud/files'
import { File, Permission, View, FileAction, Folder } from '@nextcloud/files'

import { action } from './sidebarAction'
import logger from '../logger'
Expand Down Expand Up @@ -125,7 +125,9 @@ describe('Open sidebar action enabled tests', () => {
describe('Open sidebar action exec tests', () => {
test('Open sidebar', async () => {
const openMock = jest.fn()
window.OCA = { Files: { Sidebar: { open: openMock } } }
const defaultTabMock = jest.fn()
window.OCA = { Files: { Sidebar: { open: openMock, setActiveTab: defaultTabMock } } }

const goToRouteMock = jest.fn()
window.OCP = { Files: { Router: { goToRoute: goToRouteMock } } }

Expand All @@ -140,6 +142,36 @@ describe('Open sidebar action exec tests', () => {
// Silent action
expect(exec).toBe(null)
expect(openMock).toBeCalledWith('/foobar.txt')
expect(defaultTabMock).toBeCalledWith('sharing')
expect(goToRouteMock).toBeCalledWith(
null,
{ view: view.id, fileid: '1' },
{ dir: '/' },
true,
)
})

test('Open sidebar for folder', async () => {
const openMock = jest.fn()
const defaultTabMock = jest.fn()
window.OCA = { Files: { Sidebar: { open: openMock, setActiveTab: defaultTabMock } } }

const goToRouteMock = jest.fn()
// @ts-expect-error We only mock what needed, we do not need Files.Router.goTo or Files.Navigation
window.OCP = { Files: { Router: { goToRoute: goToRouteMock } } }

const file = new Folder({
id: 1,
source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar',
owner: 'admin',
mime: 'httpd/unix-directory',
})

const exec = await action.exec(file, view, '/')
// Silent action
expect(exec).toBe(null)
expect(openMock).toBeCalledWith('/foobar')
expect(defaultTabMock).toBeCalledWith('sharing')
expect(goToRouteMock).toBeCalledWith(
null,
{ view: view.id, fileid: 1 },
Expand All @@ -150,7 +182,9 @@ describe('Open sidebar action exec tests', () => {

test('Open sidebar fails', async () => {
const openMock = jest.fn(() => { throw new Error('Mock error') })
window.OCA = { Files: { Sidebar: { open: openMock } } }
const defaultTabMock = jest.fn()
window.OCA = { Files: { Sidebar: { open: openMock, setActiveTab: defaultTabMock } } }

jest.spyOn(logger, 'error').mockImplementation(() => jest.fn())

const file = new File({
Expand Down
3 changes: 3 additions & 0 deletions apps/files/src/actions/sidebarAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ export const action = new FileAction({

async exec(node: Node, view: View, dir: string) {
try {
// Open sidebar and set active tab to sharing by default
window.OCA.Files.Sidebar.setActiveTab('sharing')

// TODO: migrate Sidebar to use a Node instead
await window.OCA.Files.Sidebar.open(node.path)

Expand Down
20 changes: 11 additions & 9 deletions apps/files_sharing/src/components/SharingEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<template>
<li class="sharing-entry">
<NcAvatar class="sharing-entry__avatar"
:is-no-user="share.type !== SHARE_TYPES.SHARE_TYPE_USER"
:is-no-user="share.type !== ShareType.User"
:user="share.shareWith"
:display-name="share.shareWithDisplayName"
:menu-position="'left'"
Expand Down Expand Up @@ -59,6 +59,8 @@
</template>

<script>
import { ShareType } from '@nextcloud/sharing'

import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js'
import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js'
Expand All @@ -85,15 +87,15 @@ export default {
computed: {
title() {
let title = this.share.shareWithDisplayName
if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_GROUP) {
if (this.share.type === ShareType.Group) {
title += ` (${t('files_sharing', 'group')})`
} else if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_ROOM) {
} else if (this.share.type === ShareType.Room) {
title += ` (${t('files_sharing', 'conversation')})`
} else if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_REMOTE) {
} else if (this.share.type === ShareType.Remote) {
title += ` (${t('files_sharing', 'remote')})`
} else if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_REMOTE_GROUP) {
} else if (this.share.type === ShareType.RemoteGroup) {
title += ` (${t('files_sharing', 'remote group')})`
} else if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_GUEST) {
} else if (this.share.type === ShareType.Guest) {
title += ` (${t('files_sharing', 'guest')})`
}
return title
Expand All @@ -106,9 +108,9 @@ export default {
user: this.share.shareWithDisplayName,
owner: this.share.ownerDisplayName,
}
if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_GROUP) {
if (this.share.type === ShareType.Group) {
return t('files_sharing', 'Shared with the group {user} by {owner}', data)
} else if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_ROOM) {
} else if (this.share.type === ShareType.Room) {
return t('files_sharing', 'Shared with the conversation {user} by {owner}', data)
}

Expand All @@ -121,7 +123,7 @@ export default {
* @return {boolean}
*/
hasStatus() {
if (this.share.type !== this.SHARE_TYPES.SHARE_TYPE_USER) {
if (this.share.type !== ShareType.User) {
return false
}

Expand Down
16 changes: 9 additions & 7 deletions apps/files_sharing/src/components/SharingEntryLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@
import { emit } from '@nextcloud/event-bus'
import { generateUrl } from '@nextcloud/router'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { Type as ShareTypes } from '@nextcloud/sharing'
import { ShareType } from '@nextcloud/sharing'
import Vue from 'vue'
import VueQrcode from '@chenfengyuan/vue-qrcode'

Expand Down Expand Up @@ -451,7 +451,7 @@ export default {
*/
isEmailShareType() {
return this.share
? this.share.type === this.SHARE_TYPES.SHARE_TYPE_EMAIL
? this.share.type === ShareType.Email
: false
},

Expand Down Expand Up @@ -575,7 +575,7 @@ export default {
* @return {Array}
*/
externalLinkActions() {
const filterValidAction = (action) => (action.shareType.includes(ShareTypes.SHARE_TYPE_LINK) || action.shareType.includes(ShareTypes.SHARE_TYPE_EMAIL)) && !action.advanced
const filterValidAction = (action) => (action.shareType.includes(ShareType.Link) || action.shareType.includes(ShareType.Email)) && !action.advanced
// filter only the registered actions for said link
return this.ExternalShareActions.actions
.filter(filterValidAction)
Expand All @@ -591,8 +591,10 @@ export default {
},
},
mounted() {
this.defaultExpirationDateEnabled = this.config.defaultExpirationDate instanceof Date
this.share.expireDate = this.defaultExpirationDateEnabled ? this.formatDateToString(this.config.defaultExpirationDate) : ''
if (this.share) {
this.defaultExpirationDateEnabled = this.config.defaultExpirationDate instanceof Date
this.share.expireDate = this.defaultExpirationDateEnabled ? this.formatDateToString(this.config.defaultExpirationDate) : ''
}
},

methods: {
Expand Down Expand Up @@ -621,7 +623,7 @@ export default {
}

const shareDefaults = {
share_type: ShareTypes.SHARE_TYPE_LINK,
share_type: ShareType.Link,
}
if (this.config.isDefaultExpireDateEnforced) {
// default is empty string if not set
Expand Down Expand Up @@ -709,7 +711,7 @@ export default {
const path = (this.fileInfo.path + '/' + this.fileInfo.name).replace('//', '/')
const options = {
path,
shareType: ShareTypes.SHARE_TYPE_LINK,
shareType: ShareType.Link,
password: share.password,
expireDate: share.expireDate,
attributes: JSON.stringify(this.fileInfo.shareAttributes),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
</template>

<script>
import { ShareType } from '@nextcloud/sharing'
import DropdownIcon from 'vue-material-design-icons/TriangleSmallDown.vue'
import SharesMixin from '../mixins/SharesMixin.js'
import ShareDetails from '../mixins/ShareDetails.js'
import ShareTypes from '../mixins/ShareTypes.js'
import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
import IconEyeOutline from 'vue-material-design-icons/EyeOutline.vue'
Expand All @@ -49,7 +49,7 @@ export default {
NcActionButton,
},

mixins: [SharesMixin, ShareDetails, ShareTypes],
mixins: [SharesMixin, ShareDetails],

props: {
share: {
Expand Down Expand Up @@ -119,7 +119,7 @@ export default {
supportsFileDrop() {
if (this.isFolder && this.config.isPublicUploadEnabled) {
const shareType = this.share.type ?? this.share.shareType
return [this.SHARE_TYPES.SHARE_TYPE_LINK, this.SHARE_TYPES.SHARE_TYPE_EMAIL].includes(shareType)
return [ShareType.Link, ShareType.Email].includes(shareType)
}
return false
},
Expand Down
52 changes: 21 additions & 31 deletions apps/files_sharing/src/components/SharingInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ import Config from '../services/ConfigService.js'
import GeneratePassword from '../utils/GeneratePassword.js'
import Share from '../models/Share.js'
import ShareRequests from '../mixins/ShareRequests.js'
import ShareTypes from '../mixins/ShareTypes.js'
import ShareDetails from '../mixins/ShareDetails.js'
import { ShareType } from '@nextcloud/sharing'

export default {
name: 'SharingInput',
Expand All @@ -65,7 +65,7 @@ export default {
NcSelect,
},

mixins: [ShareTypes, ShareRequests, ShareDetails],
mixins: [ShareRequests, ShareDetails],

props: {
shares: {
Expand Down Expand Up @@ -185,20 +185,10 @@ export default {
lookup = true
}

const shareType = [
this.SHARE_TYPES.SHARE_TYPE_USER,
this.SHARE_TYPES.SHARE_TYPE_GROUP,
this.SHARE_TYPES.SHARE_TYPE_REMOTE,
this.SHARE_TYPES.SHARE_TYPE_REMOTE_GROUP,
this.SHARE_TYPES.SHARE_TYPE_CIRCLE,
this.SHARE_TYPES.SHARE_TYPE_ROOM,
this.SHARE_TYPES.SHARE_TYPE_GUEST,
this.SHARE_TYPES.SHARE_TYPE_DECK,
this.SHARE_TYPES.SHARE_TYPE_SCIENCEMESH,
]
const shareType = Object.values(ShareType)

if (getCapabilities().files_sharing.public.enabled === true) {
shareType.push(this.SHARE_TYPES.SHARE_TYPE_EMAIL)
shareType.push(ShareType.Email)
}

let request = null
Expand Down Expand Up @@ -335,7 +325,7 @@ export default {
return arr
}
try {
if (share.value.shareType === this.SHARE_TYPES.SHARE_TYPE_USER) {
if (share.value.shareType === ShareType.User) {
// filter out current user
if (share.value.shareWith === getCurrentUser().uid) {
return arr
Expand All @@ -348,7 +338,7 @@ export default {
}

// filter out existing mail shares
if (share.value.shareType === this.SHARE_TYPES.SHARE_TYPE_EMAIL) {
if (share.value.shareType === ShareType.Email) {
const emails = this.linkShares.map(elem => elem.shareWith)
if (emails.indexOf(share.value.shareWith.trim()) !== -1) {
return arr
Expand Down Expand Up @@ -386,42 +376,42 @@ export default {
*/
shareTypeToIcon(type) {
switch (type) {
case this.SHARE_TYPES.SHARE_TYPE_GUEST:
case ShareType.Guest:
// default is a user, other icons are here to differentiate
// themselves from it, so let's not display the user icon
// case this.SHARE_TYPES.SHARE_TYPE_REMOTE:
// case this.SHARE_TYPES.SHARE_TYPE_USER:
// case ShareType.Remote:
// case ShareType.User:
return {
icon: 'icon-user',
iconTitle: t('files_sharing', 'Guest'),
}
case this.SHARE_TYPES.SHARE_TYPE_REMOTE_GROUP:
case this.SHARE_TYPES.SHARE_TYPE_GROUP:
case ShareType.RemoteGroup:
case ShareType.Group:
return {
icon: 'icon-group',
iconTitle: t('files_sharing', 'Group'),
}
case this.SHARE_TYPES.SHARE_TYPE_EMAIL:
case ShareType.Email:
return {
icon: 'icon-mail',
iconTitle: t('files_sharing', 'Email'),
}
case this.SHARE_TYPES.SHARE_TYPE_CIRCLE:
case ShareType.Team:
return {
icon: 'icon-teams',
iconTitle: t('files_sharing', 'Team'),
}
case this.SHARE_TYPES.SHARE_TYPE_ROOM:
case ShareType.Room:
return {
icon: 'icon-room',
iconTitle: t('files_sharing', 'Talk conversation'),
}
case this.SHARE_TYPES.SHARE_TYPE_DECK:
case ShareType.Deck:
return {
icon: 'icon-deck',
iconTitle: t('files_sharing', 'Deck board'),
}
case this.SHARE_TYPES.SHARE_TYPE_SCIENCEMESH:
case ShareType.Sciencemesh:
return {
icon: 'icon-sciencemesh',
iconTitle: t('files_sharing', 'ScienceMesh'),
Expand All @@ -439,13 +429,13 @@ export default {
*/
formatForMultiselect(result) {
let subname
if (result.value.shareType === this.SHARE_TYPES.SHARE_TYPE_USER && this.config.shouldAlwaysShowUnique) {
if (result.value.shareType === ShareType.User && this.config.shouldAlwaysShowUnique) {
subname = result.shareWithDisplayNameUnique ?? ''
} else if ((result.value.shareType === this.SHARE_TYPES.SHARE_TYPE_REMOTE
|| result.value.shareType === this.SHARE_TYPES.SHARE_TYPE_REMOTE_GROUP
} else if ((result.value.shareType === ShareType.Remote
|| result.value.shareType === ShareType.RemoteGroup
) && result.value.server) {
subname = t('files_sharing', 'on {server}', { server: result.value.server })
} else if (result.value.shareType === this.SHARE_TYPES.SHARE_TYPE_EMAIL) {
} else if (result.value.shareType === ShareType.Email) {
subname = result.value.shareWith
} else {
subname = result.shareWithDescription ?? ''
Expand All @@ -455,7 +445,7 @@ export default {
shareWith: result.value.shareWith,
shareType: result.value.shareType,
user: result.uuid || result.value.shareWith,
isNoUser: result.value.shareType !== this.SHARE_TYPES.SHARE_TYPE_USER,
isNoUser: result.value.shareType !== ShareType.User,
displayName: result.name || result.label,
subname,
shareWithDisplayNameUnique: result.shareWithDisplayNameUnique || '',
Expand Down
32 changes: 0 additions & 32 deletions apps/files_sharing/src/mixins/ShareTypes.js

This file was deleted.

Loading
Loading