]> source.dussan.org Git - nextcloud-server.git/commitdiff
feat(sidebar): Show node owner in metadata subline
authorfenn-cs <fenn25.fn@gmail.com>
Mon, 22 Jul 2024 16:54:39 +0000 (17:54 +0100)
committerfenn-cs <fenn25.fn@gmail.com>
Mon, 7 Oct 2024 13:15:55 +0000 (15:15 +0200)
Resolves: https://github.com/nextcloud/server/issues/46178

Signed-off-by: fenn-cs <fenn25.fn@gmail.com>
apps/files/src/services/WebdavClient.ts
apps/files/src/store/files.ts
apps/files/src/views/Sidebar.vue

index 5563508e2c7bcab24322b903f491ff868904be37..cd33147b03f094c41d1f2766136a08bc1374297d 100644 (file)
@@ -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<Node> => {
+       const propfindPayload = davGetDefaultPropfind()
+       const result = await client.stat(`${davRootPath}${node.path}`, {
+               details: true,
+               data: propfindPayload,
+       }) as ResponseDataDetailed<FileStat>
+       return davResultToNode(result.data)
+}
index 1af675e67ce96d66f4b1b4958d66cdba0c594878..952e3cd41c5b80c9c2900fec947f0c3291771eba 100644 (file)
@@ -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<Node> => {
-       const propfindPayload = davGetDefaultPropfind()
-       const result = await client.stat(`${davRootPath}${node.path}`, {
-               details: true,
-               data: propfindPayload,
-       }) as ResponseDataDetailed<FileStat>
-       return davResultToNode(result.data)
-}
-
 export const useFilesStore = function(...args) {
        const store = defineStore('files', {
                state: (): FilesState => ({
index 5d9f2079253c6d07d75b8eefcd7ee10be7c09628..ca7afac77809be0ba28fbd875f9f60a2c615756a 100644 (file)
                @closing="handleClosing"
                @closed="handleClosed">
                <template v-if="fileInfo" #subname>
-                       <NcIconSvgWrapper v-if="fileInfo.isFavourited"
-                               :path="mdiStar"
-                               :name="t('files', 'Favorite')"
-                               inline />
-                       {{ size }}
-                       <NcDateTime :timestamp="fileInfo.mtime" />
+                       <div class="sidebar__subname">
+                               <NcIconSvgWrapper v-if="fileInfo.isFavourited"
+                                       :path="mdiStar"
+                                       :name="t('files', 'Favorite')"
+                                       inline />
+                               <span>{{ size }}</span>
+                               <span class="sidebar__subname-separator">•</span>
+                               <NcDateTime :timestamp="fileInfo.mtime" />
+                               <span class="sidebar__subname-separator">•</span>
+                               <span>{{ t('files', 'Owner') }}</span>
+                               <NcUserBubble :user="ownerId"
+                                       :display-name="nodeOwnerLabel" />
+                       </div>
                </template>
 
                <!-- TODO: create a standard to allow multiple elements here? -->
@@ -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;
+       }
 </style>