Skip to content

Commit

Permalink
admin: "create folder" button in file-picker
Browse files Browse the repository at this point in the history
  • Loading branch information
rejetto committed Oct 28, 2023
1 parent 7143f32 commit bb8aed7
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 13 deletions.
22 changes: 18 additions & 4 deletions admin/src/FilePicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ import {
TextField,
Typography
} from '@mui/material'
import { enforceFinal, formatBytes, isWindowsDrive, spinner, Center, err2msg, basename } from './misc'
import { ArrowUpward, VerticalAlignTop } from '@mui/icons-material'
import { enforceFinal, formatBytes, isWindowsDrive, spinner, Center, err2msg, basename, IconBtn, Flex } from './misc'
import { ArrowUpward, CreateNewFolder, VerticalAlignTop } from '@mui/icons-material'
import { StringField } from '@hfs/mui-grid-form'
import { FileIcon, FolderIcon } from './VfsTree'
import { FixedSizeList } from 'react-window'
import { promptDialog } from './dialog'

export interface DirEntry { n:string, s?:number, m?:string, c?:string, k?:'d' }

Expand All @@ -42,7 +43,7 @@ export default function FilePicker({ onSelect, multiple=true, files=true, folder
}
}).finally(() => setReady(true))
}, [from])
const { list, error, connecting } = useApiList<DirEntry>(ready && 'get_ls', { path: cwd, files, fileMask })
const { list, error, connecting, reload } = useApiList<DirEntry>(ready && 'get_ls', { path: cwd, files, fileMask })
useEffect(() => {
setSel([])
setFilter('')
Expand Down Expand Up @@ -143,7 +144,7 @@ export default function FilePicker({ onSelect, multiple=true, files=true, folder
}
})
),
h(Box, { display:'flex', gap: 1 },
h(Flex, {},
(multiple || folders || !files) && h(Button, {
variant: 'contained',
disabled: !cwd || !folders && !sel.length && files,
Expand All @@ -153,13 +154,26 @@ export default function FilePicker({ onSelect, multiple=true, files=true, folder
}
}, files && (sel.length || !folders) ? `Select (${sel.length})` : `Select this folder`),
h(TextField, {
size: 'small',
value: filter,
label: `Filter results (${filteredList.length}${filteredList.length < list.length ? '/'+list.length : ''})`,
onChange(ev) {
setFilterBounced(ev.target.value)
},
sx: { flex: 1 },
}),
h(IconBtn, {
icon: CreateNewFolder,
doneMessage: true,
title: "Create folder",
sx: { mt: '5px' },
async onClick() {
const s = await promptDialog("New folder name")
if (!s) return false
await apiCall('mkdir', { path: `${cwd}/${s}` })
reload()
}
}),
),
)
)
Expand Down
19 changes: 11 additions & 8 deletions admin/src/mui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,12 @@ interface IconBtnProps extends Omit<IconButtonProps, 'disabled'|'title'|'onClick
progress?: boolean | number
link?: string
confirm?: string
doneMessage?: boolean | string // displayed only if the result of onClick !== false
tooltipProps?: Partial<TooltipProps>
onClick: (...args: Parameters<NonNullable<IconButtonProps['onClick']>>) => Promisable<any>
}

export const IconBtn = forwardRef(({ title, icon, onClick, disabled, progress, link, tooltipProps, confirm, ...rest }: IconBtnProps, ref: any) => {
export const IconBtn = forwardRef(({ title, icon, onClick, disabled, progress, link, tooltipProps, confirm, doneMessage, sx, ...rest }: IconBtnProps, ref: any) => {
const [loading, setLoading] = useStateMounted(false)
if (typeof disabled === 'string')
title = disabled
Expand All @@ -107,12 +108,13 @@ export const IconBtn = forwardRef(({ title, icon, onClick, disabled, progress, l
ref,
disabled: Boolean(loading || progress || disabled),
...rest,
sx: { height: 'fit-content', ...sx },
async onClick(...args) {
if (confirm && !await confirmDialog(confirm)) return
const ret = onClick?.apply(this,args)
if (ret && ret instanceof Promise) {
setLoading(true)
ret.catch(alertDialog).finally(()=> setLoading(false))
ret.then(x => x !== false && execDoneMessage(doneMessage), alertDialog).finally(()=> setLoading(false))
}
}
},
Expand All @@ -135,7 +137,7 @@ interface BtnProps extends Omit<LoadingButtonProps,'disabled'|'title'|'onClick'>
progress?: boolean | number
link?: string
confirm?: boolean | string
doneMessage?: boolean | string
doneMessage?: boolean | string // displayed only if the result of onClick !== false
tooltipProps?: TooltipProps
onClick: (...args: Parameters<NonNullable<ButtonProps['onClick']>>) => Promisable<any>
}
Expand All @@ -161,11 +163,7 @@ export function Btn({ icon, title, onClick, disabled, progress, link, tooltipPro
const ret = onClick?.apply(this,args)
if (ret && ret instanceof Promise) {
setLoading(true)
ret.then(async res => {
if (doneMessage)
toast(doneMessage === true ? "Operation completed" : doneMessage, 'success')
return res
}, alertDialog)
ret.then(x => x !== false && execDoneMessage(doneMessage), alertDialog)
.finally(()=> setLoading(false))
}
}
Expand All @@ -175,6 +173,11 @@ export function Btn({ icon, title, onClick, disabled, progress, link, tooltipPro
return ret
}

function execDoneMessage(msg: boolean | string | undefined) {
if (msg)
toast(msg === true ? "Operation completed" : msg, 'success')
}

export function iconTooltip(icon: SvgIconComponent, tooltip: ReactNode, sx?: SxProps) {
return h(Tooltip, { title: tooltip, children: h(icon, { sx: { verticalAlign: 'bottom', ...sx } }) })
}
Expand Down
7 changes: 6 additions & 1 deletion src/api.vfs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { getNodeName, isSameFilenameAs, nodeIsDirectory, saveVfs, urlToNode, vfs, VfsNode, applyParentToChild,
permsFromParent } from './vfs'
import _ from 'lodash'
import { stat } from 'fs/promises'
import { mkdir, stat } from 'fs/promises'
import { ApiError, ApiHandlers, SendListReadable } from './apiMiddleware'
import { dirname, extname, join, resolve } from 'path'
import { dirStream, enforceFinal, isDirectory, isWindowsDrive, makeMatcher, PERM_KEYS, VfsNodeAdminSend } from './misc'
Expand Down Expand Up @@ -168,6 +168,11 @@ const apis: ApiHandlers = {
return { path, isFolder: await isDirectory(path) }
},

async mkdir({ path }) {
await mkdir(path, { recursive: true })
return {}
},

get_ls({ path, files=true, fileMask }, ctx) {
return new SendListReadable({
async doAtStart(list) {
Expand Down

0 comments on commit bb8aed7

Please sign in to comment.