aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files/src
diff options
context:
space:
mode:
authorJohn Molakvoæ <skjnldsv@users.noreply.github.com>2023-07-11 15:06:03 +0200
committerGitHub <noreply@github.com>2023-07-11 15:06:03 +0200
commit2cf8d6d9652a55f81c6800f2e69b71597736c56c (patch)
tree3e48463d8ebc3c01961243e8e6b1fc10a60133b7 /apps/files/src
parent5c6ed30369f5c4edcf46e5e882c6096a7e3cd01e (diff)
parent74763e875737ea2bb0775194544a809041a2e7d6 (diff)
downloadnextcloud-server-2cf8d6d9652a55f81c6800f2e69b71597736c56c.tar.gz
nextcloud-server-2cf8d6d9652a55f81c6800f2e69b71597736c56c.zip
Merge pull request #39196 from nextcloud/feat/f2v/sharing
Diffstat (limited to 'apps/files/src')
-rw-r--r--apps/files/src/actions/downloadAction.ts3
-rw-r--r--apps/files/src/actions/favoriteAction.spec.ts3
-rw-r--r--apps/files/src/actions/favoriteAction.ts13
-rw-r--r--apps/files/src/actions/sidebarAction.spec.ts19
-rw-r--r--apps/files/src/actions/sidebarAction.ts6
-rw-r--r--apps/files/src/actions/viewInFolderAction.spec.ts20
-rw-r--r--apps/files/src/actions/viewInFolderAction.ts6
-rw-r--r--apps/files/src/components/FileEntry.vue29
-rw-r--r--apps/files/src/components/FilesListVirtual.vue1
-rw-r--r--apps/files/src/store/files.ts2
-rw-r--r--apps/files/src/views/favorites.ts17
11 files changed, 94 insertions, 25 deletions
diff --git a/apps/files/src/actions/downloadAction.ts b/apps/files/src/actions/downloadAction.ts
index 44e9fa4b379..13fcde61063 100644
--- a/apps/files/src/actions/downloadAction.ts
+++ b/apps/files/src/actions/downloadAction.ts
@@ -19,12 +19,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
-import { emit } from '@nextcloud/event-bus'
import { Permission, Node, FileType } from '@nextcloud/files'
import { translate as t } from '@nextcloud/l10n'
import ArrowDownSvg from '@mdi/svg/svg/arrow-down.svg?raw'
-import { registerFileAction, FileAction } from '../services/FileAction'
+import { registerFileAction, FileAction, DefaultType } from '../services/FileAction'
import { generateUrl } from '@nextcloud/router'
import type { Navigation } from '../services/Navigation'
diff --git a/apps/files/src/actions/favoriteAction.spec.ts b/apps/files/src/actions/favoriteAction.spec.ts
index 48a00094a0d..57957e67a33 100644
--- a/apps/files/src/actions/favoriteAction.spec.ts
+++ b/apps/files/src/actions/favoriteAction.spec.ts
@@ -22,7 +22,7 @@
import * as favoriteAction from './favoriteAction'
import { action } from './favoriteAction'
import { expect } from '@jest/globals'
-import { File, Folder, Permission } from '@nextcloud/files'
+import { File, Permission } from '@nextcloud/files'
import { FileAction } from '../services/FileAction'
import * as eventBus from '@nextcloud/event-bus'
import axios from '@nextcloud/axios'
@@ -120,6 +120,7 @@ describe('Favorite action enabled tests', () => {
source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt',
owner: 'admin',
mime: 'text/plain',
+ permissions: Permission.ALL,
})
expect(action.enabled).toBeDefined()
diff --git a/apps/files/src/actions/favoriteAction.ts b/apps/files/src/actions/favoriteAction.ts
index 1ae77b6fb21..a33aacf4947 100644
--- a/apps/files/src/actions/favoriteAction.ts
+++ b/apps/files/src/actions/favoriteAction.ts
@@ -20,13 +20,15 @@
*
*/
import { emit } from '@nextcloud/event-bus'
+import { generateUrl } from '@nextcloud/router'
+import { Permission, type Node } from '@nextcloud/files'
import { translate as t } from '@nextcloud/l10n'
import axios from '@nextcloud/axios'
-import StarSvg from '@mdi/svg/svg/star.svg?raw'
+import Vue from 'vue'
+
import StarOutlineSvg from '@mdi/svg/svg/star-outline.svg?raw'
-import type { Node } from '@nextcloud/files'
+import StarSvg from '@mdi/svg/svg/star.svg?raw'
-import { generateUrl } from '@nextcloud/router'
import { registerFileAction, FileAction } from '../services/FileAction'
import logger from '../logger.js'
import type { Navigation } from '../services/Navigation'
@@ -54,7 +56,7 @@ export const favoriteNode = async (node: Node, view: Navigation, willFavorite: b
}
// Update the node webdav attribute
- node.attributes.favorite = willFavorite ? 1 : 0
+ Vue.set(node.attributes, 'favorite', willFavorite ? 1 : 0)
// Dispatch event to whoever is interested
if (willFavorite) {
@@ -85,8 +87,9 @@ export const action = new FileAction({
},
enabled(nodes: Node[]) {
- // We can only favorite nodes within files
+ // We can only favorite nodes within files and with permissions
return !nodes.some(node => !node.root?.startsWith?.('/files'))
+ && nodes.every(node => node.permissions !== Permission.NONE)
},
async exec(node: Node, view: Navigation) {
diff --git a/apps/files/src/actions/sidebarAction.spec.ts b/apps/files/src/actions/sidebarAction.spec.ts
index c4750092ebc..69eabe4be79 100644
--- a/apps/files/src/actions/sidebarAction.spec.ts
+++ b/apps/files/src/actions/sidebarAction.spec.ts
@@ -21,7 +21,7 @@
*/
import { action } from './sidebarAction'
import { expect } from '@jest/globals'
-import { File } from '@nextcloud/files'
+import { File, Permission } from '@nextcloud/files'
import { FileAction } from '../services/FileAction'
import type { Navigation } from '../services/Navigation'
import logger from '../logger'
@@ -51,12 +51,29 @@ describe('Open sidebar action enabled tests', () => {
source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt',
owner: 'admin',
mime: 'text/plain',
+ permissions: Permission.ALL,
})
expect(action.enabled).toBeDefined()
expect(action.enabled!([file], view)).toBe(true)
})
+ test('Disabled without permissions', () => {
+ window.OCA = { Files: { Sidebar: {} } }
+
+ const file = new File({
+ id: 1,
+ source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt',
+ owner: 'admin',
+ mime: 'text/plain',
+ permissions: Permission.NONE,
+ })
+
+ expect(action.enabled).toBeDefined()
+ expect(action.enabled!([file], view)).toBe(false)
+
+ })
+
test('Disabled if more than one node', () => {
window.OCA = { Files: { Sidebar: {} } }
diff --git a/apps/files/src/actions/sidebarAction.ts b/apps/files/src/actions/sidebarAction.ts
index 141cd75ff19..6c553d97902 100644
--- a/apps/files/src/actions/sidebarAction.ts
+++ b/apps/files/src/actions/sidebarAction.ts
@@ -21,9 +21,9 @@
*/
import { translate as t } from '@nextcloud/l10n'
import InformationSvg from '@mdi/svg/svg/information-variant.svg?raw'
-import type { Node } from '@nextcloud/files'
+import { Permission, type Node } from '@nextcloud/files'
-import { registerFileAction, FileAction, DefaultType } from '../services/FileAction'
+import { registerFileAction, FileAction } from '../services/FileAction'
import logger from '../logger.js'
export const ACTION_DETAILS = 'details'
@@ -45,7 +45,7 @@ export const action = new FileAction({
return false
}
- return nodes[0].root?.startsWith('/files/') ?? false
+ return (nodes[0].root?.startsWith('/files/') && nodes[0].permissions !== Permission.NONE) ?? false
},
async exec(node: Node) {
diff --git a/apps/files/src/actions/viewInFolderAction.spec.ts b/apps/files/src/actions/viewInFolderAction.spec.ts
index b16f2663f33..887ed5d47c6 100644
--- a/apps/files/src/actions/viewInFolderAction.spec.ts
+++ b/apps/files/src/actions/viewInFolderAction.spec.ts
@@ -48,12 +48,26 @@ describe('View in folder action enabled tests', () => {
source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt',
owner: 'admin',
mime: 'text/plain',
+ permissions: Permission.ALL,
})
expect(action.enabled).toBeDefined()
expect(action.enabled!([file], view)).toBe(true)
})
+ test('Disabled without permissions', () => {
+ const file = new File({
+ id: 1,
+ source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt',
+ owner: 'admin',
+ mime: 'text/plain',
+ permissions: Permission.NONE,
+ })
+
+ expect(action.enabled).toBeDefined()
+ expect(action.enabled!([file], view)).toBe(false)
+ })
+
test('Disabled for non-dav ressources', () => {
const file = new File({
id: 1,
@@ -107,13 +121,14 @@ describe('View in folder action execute tests', () => {
source: 'https://cloud.domain.com/remote.php/dav/files/admin/foobar.txt',
owner: 'admin',
mime: 'text/plain',
+ permissions: Permission.READ,
})
const exec = await action.exec(file, view, '/')
// Silent action
expect(exec).toBe(null)
expect(goToRouteMock).toBeCalledTimes(1)
- expect(goToRouteMock).toBeCalledWith(null, { view: 'files' }, { dir: '/' })
+ expect(goToRouteMock).toBeCalledWith(null, { fileid: 1, view: 'files' }, { fileid: 1, dir: '/' })
})
test('View in (sub) folder', async () => {
@@ -126,13 +141,14 @@ describe('View in folder action execute tests', () => {
root: '/files/admin',
owner: 'admin',
mime: 'text/plain',
+ permissions: Permission.READ,
})
const exec = await action.exec(file, view, '/')
// Silent action
expect(exec).toBe(null)
expect(goToRouteMock).toBeCalledTimes(1)
- expect(goToRouteMock).toBeCalledWith(null, { view: 'files' }, { dir: '/Foo/Bar' })
+ expect(goToRouteMock).toBeCalledWith(null, { fileid: 1, view: 'files' }, { fileid: 1, dir: '/Foo/Bar' })
})
test('View in folder fails without node', async () => {
diff --git a/apps/files/src/actions/viewInFolderAction.ts b/apps/files/src/actions/viewInFolderAction.ts
index 67e276112dc..2f603e6cf3a 100644
--- a/apps/files/src/actions/viewInFolderAction.ts
+++ b/apps/files/src/actions/viewInFolderAction.ts
@@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
-import { Node, FileType } from '@nextcloud/files'
+import { Node, FileType, Permission } from '@nextcloud/files'
import { translate as t } from '@nextcloud/l10n'
import FolderMoveSvg from '@mdi/svg/svg/folder-move.svg?raw'
@@ -46,6 +46,10 @@ export const action = new FileAction({
return false
}
+ if (node.permissions === Permission.NONE) {
+ return false
+ }
+
return node.type === FileType.File
},
diff --git a/apps/files/src/components/FileEntry.vue b/apps/files/src/components/FileEntry.vue
index 58b914041b2..672d7a0de33 100644
--- a/apps/files/src/components/FileEntry.vue
+++ b/apps/files/src/components/FileEntry.vue
@@ -150,7 +150,7 @@
<script lang='ts'>
import { debounce } from 'debounce'
import { emit } from '@nextcloud/event-bus'
-import { formatFileSize } from '@nextcloud/files'
+import { formatFileSize, Permission } from '@nextcloud/files'
import { Fragment } from 'vue-frag'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { translate } from '@nextcloud/l10n'
@@ -166,6 +166,7 @@ import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
import StarIcon from 'vue-material-design-icons/Star.vue'
import Vue from 'vue'
+import type moment from 'moment'
import { ACTION_DETAILS } from '../actions/sidebarAction.ts'
import { getFileActions, DefaultType } from '../services/FileAction.ts'
@@ -173,7 +174,6 @@ import { hashCode } from '../utils/hashUtils.ts'
import { isCachedPreview } from '../services/PreviewService.ts'
import { useActionsMenuStore } from '../store/actionsmenu.ts'
import { useFilesStore } from '../store/files.ts'
-import type moment from 'moment'
import { useKeyboardStore } from '../store/keyboard.ts'
import { useSelectionStore } from '../store/selection.ts'
import { useUserConfigStore } from '../store/userconfig.ts'
@@ -336,11 +336,16 @@ export default Vue.extend({
}
}
+ if (this.source?.permissions & Permission.READ) {
+ return {
+ download: this.source.basename,
+ href: this.source.source,
+ title: this.t('files', 'Download file {name}', { name: this.displayName }),
+ }
+ }
+
return {
- download: this.source.basename,
- href: this.source.source,
- // TODO: Use first action title ?
- title: this.t('files', 'Download file {name}', { name: this.displayName }),
+ is: 'span',
}
},
@@ -398,7 +403,15 @@ export default Vue.extend({
// Actions shown in the menu
enabledMenuActions() {
- return this.enabledActions.filter(action => action.default !== DefaultType.HIDDEN)
+ return [
+ // Showing inline first for the NcActions inline prop
+ ...this.enabledInlineActions,
+ // Then the rest
+ ...this.enabledActions.filter(action => action.default !== DefaultType.HIDDEN),
+ ].filter((value, index, self) => {
+ // Then we filter duplicates to prevent inline actions to be shown twice
+ return index === self.findIndex(action => action.id === value.id)
+ })
},
openedMenu: {
get() {
@@ -602,7 +615,7 @@ export default Vue.extend({
},
openDetailsIfAvailable(event) {
- const detailsAction = this.enabledDefaultActions.find(action => action.id === ACTION_DETAILS)
+ const detailsAction = this.enabledActions.find(action => action.id === ACTION_DETAILS)
if (detailsAction) {
event.preventDefault()
event.stopPropagation()
diff --git a/apps/files/src/components/FilesListVirtual.vue b/apps/files/src/components/FilesListVirtual.vue
index c1d5c041992..e215714882c 100644
--- a/apps/files/src/components/FilesListVirtual.vue
+++ b/apps/files/src/components/FilesListVirtual.vue
@@ -322,6 +322,7 @@ export default Vue.extend({
}
.files-list__row-name-text {
+ color: var(--color-main-text);
// Make some space for the outline
padding: 5px 10px;
margin-left: -10px;
diff --git a/apps/files/src/store/files.ts b/apps/files/src/store/files.ts
index ac62512988b..c36ebcfecc2 100644
--- a/apps/files/src/store/files.ts
+++ b/apps/files/src/store/files.ts
@@ -58,7 +58,7 @@ export const useFilesStore = function(...args) {
// Update the store all at once
const files = nodes.reduce((acc, node) => {
if (!node.fileid) {
- logger.warn('Trying to update/set a node without fileid', node)
+ logger.error('Trying to update/set a node without fileid', node)
return acc
}
acc[node.fileid] = node
diff --git a/apps/files/src/views/favorites.ts b/apps/files/src/views/favorites.ts
index 73293668664..571db4faab3 100644
--- a/apps/files/src/views/favorites.ts
+++ b/apps/files/src/views/favorites.ts
@@ -129,9 +129,16 @@ export default () => {
// Add a folder to the favorites paths array and update the views
const addPathToFavorites = function(path: string) {
const view = generateFolderView(path)
+
+ // Skip if already exists
+ if (favoriteFolders.find(folder => folder === path)) {
+ return
+ }
+
// Update arrays
favoriteFolders.push(path)
favoriteFoldersViews.push(view)
+
// Update and sort views
updateAndSortViews()
Navigation.register(view)
@@ -140,10 +147,18 @@ export default () => {
// Remove a folder from the favorites paths array and update the views
const removePathFromFavorites = function(path: string) {
const id = generateIdFromPath(path)
- const index = favoriteFolders.findIndex(f => f === path)
+ const index = favoriteFolders.findIndex(folder => folder === path)
+
+ // Skip if not exists
+ if (index === -1) {
+ return
+ }
+
// Update arrays
favoriteFolders.splice(index, 1)
favoriteFoldersViews.splice(index, 1)
+
+ // Update and sort views
Navigation.remove(id)
updateAndSortViews()
}