diff --git a/admin/src/FileForm.ts b/admin/src/FileForm.ts index b5b9253c..d3ae0cea 100644 --- a/admin/src/FileForm.ts +++ b/admin/src/FileForm.ts @@ -171,17 +171,18 @@ export default function FileForm({ file, addToBar, statusApi, accounts, saved }: showTimestamps && { k: 'mtime', comp: DisplayField, sm: 6, lg: showSize && 4, label: "Modified", toField: formatTimestamp }, showAccept && { k: 'accept', label: "Accept on upload", placeholder: "anything", xl: showWebsite ? 4 : 12, helperText: h(Link, { href: ACCEPT_LINK, target: '_blank' }, "Example: .zip") }, - showWebsite && { k: 'default', comp: BoolField, xl: true, + showWebsite && { k: 'default', comp: BoolField, xl: showWebsite ? 8 : 12, label: "Serve as web-page if index.html is found" + (inheritedDefault && values.default == null ? ' (inherited)' : ''), value: values.default ?? inheritedDefault, toField: Boolean, fromField: (v:boolean) => v && !inheritedDefault ? 'index.html' : v ? null : false, helperText: md("...instead of showing list of files") }, - isDir && { k: 'masks', multiline: true, + { k: 'comment', multiline: true, xl: true }, + isDir && { k: 'masks', multiline: true, xl: 6, toField: yaml.stringify, fromField: v => v ? yaml.parse(v) : undefined, sx: { '& textarea': { fontFamily: 'monospace' } }, helperText: ["Special field, leave empty unless you know what you are doing. YAML syntax. ", wikiLink('Masks-field', "(examples)")] - } + }, ] }) diff --git a/src/api.get_file_list.ts b/src/api.get_file_list.ts index d606181f..538d133e 100644 --- a/src/api.get_file_list.ts +++ b/src/api.get_file_list.ts @@ -45,7 +45,7 @@ export const get_file_list: ApiHandler = async ({ uri='/', offset, limit, search const can_archive = admin || hasPermission(fakeChild, 'can_archive', ctx) const can_comment = can_upload && areCommentsEnabled() const can_overwrite = can_upload && (can_delete || !dontOverwriteUploading.get()) - const comment = await getCommentFor(node.source) + const comment = node.comment ?? await getCommentFor(node.source) const props = { can_archive, can_upload, can_delete, can_overwrite, can_comment, comment, accept: node.accept } ctx.state.browsing = uri.replace(/\/{2,}/g, '/') updateConnectionForCtx(ctx) @@ -126,7 +126,7 @@ export const get_file_list: ApiHandler = async ({ uri='/', offset, limit, search m: !st || Math.abs(+st.mtime - +st.ctime) < 1000 ? undefined : st.mtime, s: isFolder ? undefined : st?.size, p: (pr + pl + pd + pa) || undefined, - comment: await getCommentFor(source), + comment: node.comment ?? await getCommentFor(source), web: await hasDefaultFile(node, ctx) ? true : undefined, } } diff --git a/src/api.vfs.ts b/src/api.vfs.ts index b5da899f..3b87ca5a 100644 --- a/src/api.vfs.ts +++ b/src/api.vfs.ts @@ -23,7 +23,7 @@ async function urlToNodeOriginal(uri: string) { return n?.isTemp ? n.original : n } -const ALLOWED_KEYS = ['name','source','masks','default','accept','rename','mime','url','target', ...PERM_KEYS] +const ALLOWED_KEYS = ['name','source','masks','default','accept','rename','mime','url','target','comment', ...PERM_KEYS] const apis: ApiHandlers = { diff --git a/src/vfs.ts b/src/vfs.ts index 12c46d6f..391c0ef6 100644 --- a/src/vfs.ts +++ b/src/vfs.ts @@ -42,6 +42,7 @@ export interface VfsNodeStored extends VfsPerms { rename?: Record masks?: Masks // express fields for descendants that are not in the tree accept?: string + comment?: string } export interface VfsNode extends VfsNodeStored { // include fields that are only filled at run-time isTemp?: true // this node doesn't belong to the tree and was created by necessity