icon marking resources missing permissions #190

Massimo Melina committed Apr 2, 2023 at 22:49 UTC fcb171cef08f8d86487678156ec6228035ad88bb
5 files changed +19 -6
frontend/src/BrowseFiles.ts
+5 -1
@@ -23,10 +23,12 @@ import _ from 'lodash'
23 import { t, useI18N } from './i18n'
24 import { deleteFiles } from './menu'
25
26 -export interface DirEntry { n:string, s?:number, m?:string, c?:string,
26 +export interface DirEntry { n:string, s?:number, m?:string, c?:string, p?:string,
27 name: string, uri: string, ext:string, isFolder:boolean, t?:Date } // we memoize these value for speed
28 export type DirList = DirEntry[]
29
30 +const MISSING_PERM = "Missing permission"
31 +
32 export function BrowseFiles() {
33 useFetchList()
34 const { error } = useSnapState()
@@ -237,6 +239,7 @@ const Entry = memo((entry: DirEntry & { midnight: Date, separator?: string }) =>
239 h('dl', { className: 'file-dialog-properties' },
240 h('dt', {}, t`Name:`), h('dd', {}, name),
241 ),
242 + entry.p && h(Fragment, {}, hIcon('password', { style: { marginRight: '.5em' } }), t(MISSING_PERM)),
243 h('div', { className: 'file-menu' },
244 menu.map((e: any, i) => !e?.label ? null :
245 h('a', {
@@ -264,6 +267,7 @@ const EntryProps = memo((entry: DirEntry & { midnight: Date }) => {
267 const dd = '2-digit'
268 return h('div', { className: 'entry-props' },
269 h(CustomCode, { name: 'additionalEntryProps', props: { entry } }),
270 + entry.p && hIcon('password', { className: 'miss-perm', title: t(MISSING_PERM) }),
271 h(EntrySize, { s }),
272 time && h('span', {
273 className: 'entry-ts',
frontend/src/index.scss
+3
@@ -383,8 +383,11 @@ button label {
383 }
384 }
385
386 +.miss-perm { margin: .3em }
387 +
388 .file-dialog-properties {
389 word-break: break-word;
390 + line-height: 1.5em;
391 & dd { margin-left: 1.5em; }
392 }
393 .file-menu {
langs/hfs-lang-en.json
+2 -1
@@ -107,6 +107,7 @@
107 "File menu": "File menu",
108 "Name:": "Name:",
109 "file_open": "Open",
110 - "Download": "Download"
110 + "Download": "Download",
111 + "Missing permission": "Missing permission"
112 }
113 }
langs/hfs-lang-it.json
+2 -1
@@ -101,6 +101,7 @@
101 "File menu": "Menu file",
102 "Name:": "Nome:",
103 "file_open": "Apri",
104 - "Download": "Download"
104 + "Download": "Download",
105 + "Missing permission": "Permesso mancante"
106 }
107 }
src/api.file_list.ts
+7 -3
@@ -15,6 +15,7 @@ import { mapPlugins } from './plugins'
15 import { asyncGeneratorToArray, dirTraversal, pattern2filter } from './misc'
16 import _ from 'lodash'
17 import { HTTP_BAD_REQUEST, HTTP_FOOL, HTTP_METHOD_NOT_ALLOWED, HTTP_NOT_FOUND } from './const'
18 +import Koa from 'koa'
19
20 export const file_list: ApiHandler = async ({ path, offset, limit, search, omit, sse }, ctx) => {
21 let node = await urlToNode(path || '/', ctx)
@@ -63,7 +64,7 @@ export const file_list: ApiHandler = async ({ path, offset, limit, search, omit,
64 if (ctx.aborted) break
65 if (!filter(getNodeName(sub)))
66 continue
66 - const entry = await nodeToDirEntry(sub)
67 + const entry = await nodeToDirEntry(ctx, sub)
68 if (!entry)
69 continue
70 const cbParams = { entry, ctx, listPath:path, node:sub }
@@ -92,9 +93,9 @@ export const file_list: ApiHandler = async ({ path, offset, limit, search, omit,
93 }
94 }
95
95 -export interface DirEntry { n:string, s?:number, m?:Date, c?:Date }
96 +export interface DirEntry { n:string, s?:number, m?:Date, c?:Date, p?: string }
97
97 -async function nodeToDirEntry(node: VfsNode): Promise<DirEntry | null> {
98 +async function nodeToDirEntry(ctx: Koa.Context, node: VfsNode): Promise<DirEntry | null> {
99 let { source, default:def } = node
100 const name = getNodeName(node)
101 if (!source)
@@ -110,6 +111,9 @@ async function nodeToDirEntry(node: VfsNode): Promise<DirEntry | null> {
111 c: ctime,
112 m: Math.abs(+mtime-+ctime) < 1000 ? undefined : mtime,
113 s: folder ? undefined : st.size,
114 + p: ((hasPermission(node, 'can_read', ctx) ? '' : 'R')
115 + + (hasPermission(node, 'can_list', ctx) ? '' : 'L'))
116 + || undefined
117 }
118 }
119 catch {