fix: admin/fs: couldn't add items if Home is selected

Massimo Melina committed Mar 13, 2023 at 16:56 UTC fd95477c2c63ff7b996080979a9c606e4740d986
5 files changed +18 -15
admin/src/FileForm.ts
+2 -2
@@ -177,10 +177,10 @@ function who2desc(who: any) {
177 interface LinkFieldProps extends FieldProps<string> {
178 urls: string[]
179 }
180 -function LinkField({ value, urls, }: LinkFieldProps) {
180 +function LinkField({ value, urls }: LinkFieldProps) {
181 const { data, error, reload } = useApiEx('get_config', { only: ['base_url'] })
182 const base: string | undefined = data?.base_url
183 - const link = (base || (urls ? urls[0] : '')) + encodeURI(value||'')
183 + const link = (base || (urls ? urls[0] : '')) + value
184 return h(Box, { display: 'flex', },
185 h(DisplayField, {
186 label: "Link", value: link,
admin/src/VfsPage.ts
+4 -4
@@ -89,8 +89,8 @@ export default function VfsPage() {
89 id2node.clear()
90 const { root } = data
91 if (!root) return
92 - recur(root) // this must be done before state change that would cause Tree to render and expecting id2node
92 root.isRoot = true
93 + recur(root) // this must be done before state change that would cause Tree to render and expecting id2node
94 state.vfs = root
95 // refresh objects of selectedFiles
96 const ids = selectOnReload || state.selectedFiles.map(x => x.id)
@@ -99,13 +99,13 @@ export default function VfsPage() {
99 id2node.get(id)))
100
101 // calculate id and parent fields, and builds the map id2node
102 - function recur(node: VfsNode, pre='', parent: VfsNode|undefined=undefined) {
102 + function recur(node: VfsNode, pre='/', parent: VfsNode|undefined=undefined) {
103 node.parent = parent
104 - node.id = prefix(pre, encodeURIComponent(node.name)) || '/' // root
104 + node.id = node.isRoot ? '/' : prefix(pre, encodeURIComponent(node.name), node.type === 'folder' ? '/' : '')
105 id2node.set(node.id, node)
106 if (!node.children) return
107 for (const n of node.children)
108 - recur(n, (pre && node.id) + '/', node)
108 + recur(n, node.id, node)
109 }
110
111 }, [data, id2node])
admin/src/addFiles.ts
+2 -3
@@ -55,10 +55,9 @@ export async function addVirtual() {
55
56 function getParent() {
57 let f: VfsNode | undefined = state.selectedFiles[0]
58 - if (!f)
58 + if (!f || f.isRoot)
59 return ''
60 if (f.type !== 'folder')
61 f = f.parent
62 - const { id } = f!
63 - return id === '/' ? '' : id
62 + return f?.id || ''
63 }
src/api.vfs.ts
+3 -2
@@ -1,6 +1,6 @@
1 // This file is part of HFS - Copyright 2021-2023, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
3 -import { defaultPerms, getNodeName, nodeIsDirectory, saveVfs, urlToNode, vfs, VfsNode } from './vfs'
3 +import { defaultPerms, getNodeName, isSameFilenameAs, nodeIsDirectory, saveVfs, urlToNode, vfs, VfsNode } from './vfs'
4 import _ from 'lodash'
5 import { stat } from 'fs/promises'
6 import { ApiError, ApiHandlers } from './apiMiddleware'
@@ -105,7 +105,8 @@ const apis: ApiHandlers = {
105 if (isWindowsDrive(source))
106 source += '\\' // slash must be included, otherwise it will refer to the cwd of that drive
107 n.children ||= []
108 - if (n.children.find(x => source && source === x.source || getNodeName(x) === name))
108 + const sameName = isSameFilenameAs(name)
109 + if (n.children.find(x => source && source === x.source || sameName(x)))
110 return new ApiError(HTTP_CONFLICT, 'already present')
111 n.children.unshift({ source, name })
112 await saveVfs()
src/vfs.ts
+7 -4
@@ -65,6 +65,12 @@ function inheritFromParent(parent: VfsNode, child: VfsNode) {
65 return child
66 }
67
68 +export function isSameFilenameAs(name: string) {
69 + const lc = name.toLowerCase()
70 + return (other: string | VfsNode) =>
71 + lc === (typeof other === 'string' ? other : getNodeName(other)).toLowerCase()
72 +}
73 +
74 export async function urlToNode(url: string, ctx?: Koa.Context, parent: VfsNode=vfs, getRest?: (rest: string) => any) : Promise<VfsNode | undefined> {
75 let initialSlashes = 0
76 while (url[initialSlashes] === '/')
@@ -80,10 +86,7 @@ export async function urlToNode(url: string, ctx?: Koa.Context, parent: VfsNode=
86 return
87 }
88 // does the tree node have a child that goes by this name?
83 - const sameName = !IS_WINDOWS ? (x:string) => x === name // easy
84 - : with_(name.toLowerCase(), lc =>
85 - (x: string) => x.toLowerCase() === lc)
86 - const child = parent.children?.find(x => sameName(getNodeName(x)))
89 + const child = parent.children?.find(isSameFilenameAs(name))
90
91 const ret: VfsNode = {
92 ...child,