From faa29a0feb9fa982b66e0ab433c826d05a367d0f Mon Sep 17 00:00:00 2001 From: fenn-cs Date: Mon, 22 Jul 2024 17:54:39 +0100 Subject: [PATCH] feat(sidebar): Show node owner in metadata subline Resolves: https://github.com/nextcloud/server/issues/46178 Signed-off-by: fenn-cs --- apps/files/src/services/WebdavClient.ts | 13 ++++- apps/files/src/store/files.ts | 13 +---- apps/files/src/views/Sidebar.vue | 68 +++++++++++++++++++++---- 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/apps/files/src/services/WebdavClient.ts b/apps/files/src/services/WebdavClient.ts index 5563508e2c7..cd33147b03f 100644 --- a/apps/files/src/services/WebdavClient.ts +++ b/apps/files/src/services/WebdavClient.ts @@ -2,6 +2,17 @@ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { davGetClient } from '@nextcloud/files' +import { davGetClient, davGetDefaultPropfind, davResultToNode, davRootPath } from '@nextcloud/files' +import type { FileStat, ResponseDataDetailed } from 'webdav' +import type { Node } from '@nextcloud/files' export const client = davGetClient() + +export const fetchNode = async (node: Node): Promise => { + const propfindPayload = davGetDefaultPropfind() + const result = await client.stat(`${davRootPath}${node.path}`, { + details: true, + data: propfindPayload, + }) as ResponseDataDetailed + return davResultToNode(result.data) +} diff --git a/apps/files/src/store/files.ts b/apps/files/src/store/files.ts index 1af675e67ce..952e3cd41c5 100644 --- a/apps/files/src/store/files.ts +++ b/apps/files/src/store/files.ts @@ -4,27 +4,16 @@ */ import type { FilesStore, RootsStore, RootOptions, Service, FilesState, FileSource } from '../types' -import type { FileStat, ResponseDataDetailed } from 'webdav' import type { Folder, Node } from '@nextcloud/files' -import { davGetDefaultPropfind, davResultToNode, davRootPath } from '@nextcloud/files' import { defineStore } from 'pinia' import { subscribe } from '@nextcloud/event-bus' import logger from '../logger' import Vue from 'vue' -import { client } from '../services/WebdavClient.ts' +import { fetchNode } from '../services/WebdavClient.ts' import { usePathsStore } from './paths.ts' -const fetchNode = async (node: Node): Promise => { - const propfindPayload = davGetDefaultPropfind() - const result = await client.stat(`${davRootPath}${node.path}`, { - details: true, - data: propfindPayload, - }) as ResponseDataDetailed - return davResultToNode(result.data) -} - export const useFilesStore = function(...args) { const store = defineStore('files', { state: (): FilesState => ({ diff --git a/apps/files/src/views/Sidebar.vue b/apps/files/src/views/Sidebar.vue index 5d9f2079253..ca7afac7780 100644 --- a/apps/files/src/views/Sidebar.vue +++ b/apps/files/src/views/Sidebar.vue @@ -17,12 +17,19 @@ @closing="handleClosing" @closed="handleClosed"> @@ -96,6 +103,7 @@ import { encodePath } from '@nextcloud/paths' import { generateUrl } from '@nextcloud/router' import { ShareType } from '@nextcloud/sharing' import { mdiStar, mdiStarOutline } from '@mdi/js' +import { fetchNode } from '../services/WebdavClient.ts' import axios from '@nextcloud/axios' import $ from 'jquery' @@ -104,6 +112,7 @@ import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js' import NcDateTime from '@nextcloud/vue/dist/Components/NcDateTime.js' import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js' import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js' +import NcUserBubble from '@nextcloud/vue/dist/Components/NcUserBubble.js' import FileInfo from '../services/FileInfo.js' import LegacyView from '../components/LegacyView.vue' @@ -123,6 +132,7 @@ export default { NcIconSvgWrapper, SidebarTab, SystemTags, + NcUserBubble, }, setup() { @@ -146,6 +156,7 @@ export default { error: null, loading: true, fileInfo: null, + node: null, isFullScreen: false, hasLowHeight: false, } @@ -287,6 +298,25 @@ export default { isSystemTagsEnabled() { return getCapabilities()?.systemtags?.enabled === true }, + ownerId() { + return this.node?.attributes?.['owner-id'] ?? this.currentUser.uid + }, + currentUserIsOwner() { + return this.ownerId === this.currentUser.uid + }, + nodeOwnerLabel() { + let ownerDisplayName = this.node?.attributes?.['owner-display-name'] + if (this.currentUserIsOwner) { + ownerDisplayName = `${ownerDisplayName} (${t('files', 'You')})` + } + return ownerDisplayName + }, + sharedMultipleTimes() { + if (Array.isArray(node.attributes?.['share-types']) && node.attributes?.['share-types'].length > 1) { + return t('files', 'Shared multiple times with different people') + } + return null + }, }, created() { subscribe('files:node:deleted', this.onNodeDeleted) @@ -460,6 +490,7 @@ export default { this.fileInfo = await FileInfo(this.davPath) // adding this as fallback because other apps expect it this.fileInfo.dir = this.file.split('/').slice(0, -1).join('/') + this.node = await fetchNode({ path: (this.fileInfo.path + '/' + this.fileInfo.name).replace('//', '/') }) // DEPRECATED legacy views // TODO: remove @@ -589,10 +620,25 @@ export default { } } -.sidebar__description { - display: flex; - flex-direction: column; - width: 100%; - gap: 8px 0; +.sidebar__subname { + display: flex; + align-items: center; + gap: 0 8px; + + &-separator { + display: inline-block; + font-weight: bold !important; + } + + .user-bubble__wrapper { + display: inline-flex; + } } + +.sidebar__description { + display: flex; + flex-direction: column; + width: 100%; + gap: 8px 0; + } -- 2.39.5