admin/fs: "open in new browser" option for links
Massimo Melina committed
Apr 12, 2024 at 14:36 UTC
9d01aa7b8edb0e540cf0fa56db083c4cc0f398dc
7 files changed
+15
-4
admin/src/FileForm.ts
+8
@@ -151,6 +151,14 @@ export default function FileForm({ file, addToBar, statusApi, accounts, saved }:
151
helperText: !values.source ? "This field is empty, and thus this element is a virtual-folder. You can set this field, pointing at any folder/file on disk."
152
: isDir ? "Content from this path on disk will be listed, but you can also add more" : undefined,
153
},
154
+ isLink && {
155
+ k: 'target',
156
+ comp: BoolField,
157
+ sm: 6,
158
+ label: "Open in new browser",
159
+ fromField: x => x ? '_blank' : null,
160
+ toField: x => x > '',
161
+ },
162
!isLink && { k: 'id', comp: LinkField, statusApi, xs: 12 },
163
perm('can_read', "Who can see but not download will be asked to login"),
164
perm('can_see', "If you can't see, you may still download with a direct link"),
config.md
+1
@@ -124,6 +124,7 @@ Valid keys in a node are:
124
Value is a dictionary, where the key is the original name.
125
- `mime`: specify what mime to use for this resource. Use "auto" for automatic detection.
126
- `url`: when this value is present, the element is a link to the URL you specify.
127
+- `target`: optional, for links only, used to [open the link in a new browser](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target). E.g. `_blank`
128
- `accept`: valid only on upload folders, used to restrict the type of files you can upload. E.g. `.zip,.rar`
129
- `default`: to be used with a folder where you want to serve a default html. E.g.: "index.html". Using this will make `mime` default to "auto".
130
- `can_read`: specify who can download this entry. Value is a `WhoCan` descriptor, which is one of these values
frontend/src/BrowseFiles.ts
+1
-1
@@ -231,7 +231,7 @@ const Entry = ({ entry, midnight, separator }: EntryProps) => {
231
h('a', { href: uri, onClick, tabIndex: -1, 'aria-hidden': true }, ico),
232
h(Link, { to: containerDir, className: 'container-folder', tabIndex: -1 }, containerName),
233
h('a', { href: uri, onClick, ...ariaProps }, name)
234
- ] : [h('a', { href: uri, onClick, ...ariaProps }, ico, name)],
234
+ ] : [h('a', { href: uri, onClick, target: entry.target, ...ariaProps }, ico, name)],
235
),
236
h(CustomCode, { name: 'afterEntryName', entry }),
237
entry.comment && h('div', { className: 'entry-comment' }, entry.comment),
frontend/src/state.ts
+1
@@ -94,6 +94,7 @@ export class DirEntry {
94
public readonly icon?: string
95
public readonly web?: true
96
public readonly url?: string
97
+ public readonly target?: string
98
public comment?: string
99
// we memoize these value for speed
100
public readonly name: string
src/api.get_file_list.ts
+2
-2
@@ -15,7 +15,7 @@ import { ctxAdminAccess } from './adminApis'
15
import { dontOverwriteUploading } from './upload'
16
import { SendListReadable } from './SendList'
17
18
-export interface DirEntry { n:string, s?:number, m?:Date, c?:Date, p?: string, comment?: string, web?: boolean, url?: string }
18
+export interface DirEntry { n:string, s?:number, m?:Date, c?:Date, p?: string, comment?: string, web?: boolean, url?: string, target?: string }
19
20
export const get_file_list: ApiHandler = async ({ uri='/', offset, limit, search, c, onlyFolders, admin }, ctx) => {
21
const node = await urlToNode(uri, ctx)
@@ -106,7 +106,7 @@ export const get_file_list: ApiHandler = async ({ uri='/', offset, limit, search
106
const { source, url } = node
107
const name = getNodeName(node)
108
if (url)
109
- return name ? { n: name, url } : null
109
+ return name ? { n: name, url, target: node.target } : null
110
const isFolder = await nodeIsDirectory(node)
111
try {
112
const st = source ? await stat(source) : undefined
src/api.vfs.ts
+1
-1
@@ -21,7 +21,7 @@ async function urlToNodeOriginal(uri: string) {
21
return n?.isTemp ? n.original : n
22
}
23
24
-const ALLOWED_KEYS = ['name','source','masks','default','accept','rename','mime','url', ...PERM_KEYS]
24
+const ALLOWED_KEYS = ['name','source','masks','default','accept','rename','mime','url','target', ...PERM_KEYS]
25
26
const apis: ApiHandlers = {
27
src/vfs.ts
+1
@@ -18,6 +18,7 @@ export interface VfsNodeStored extends VfsPerms {
18
name?: string
19
source?: string
20
url?: string
21
+ target?: string
22
children?: VfsNode[]
23
default?: string | false // we could have used empty string to override inherited default, but false is clearer, even reading the yaml, and works well with pickProps(), where empty strings are removed
24
mime?: string | Record<string, string>