admin/fs: ask for virtual folder's name

Massimo Melina committed Mar 13, 2022 at 12:19 UTC d2f1604f1ca58187524d2bacb970000729030bf9
4 files changed +61 -12
admin/src/Form.ts
+5 -5
@@ -2,7 +2,7 @@
2
3 import { createElement as h, FC, Fragment, isValidElement, ReactElement, ReactNode, useEffect, useState } from 'react'
4 import {
5 - Box,
5 + Box, Button,
6 FormControl,
7 FormControlLabel, FormHelperText,
8 FormLabel,
@@ -27,7 +27,7 @@ interface FormProps {
27 defaults?: (f:FieldDescriptor) => Dict | void
28 values: Dict
29 set: (v: any, field: FieldDescriptor) => void
30 - save?: Dict
30 + save?: Partial<Parameters<typeof Button>[0]>
31 stickyBar?: boolean
32 addToBar?: ReactNode[]
33 barSx?: Dict
@@ -37,16 +37,16 @@ export function Form({ fields, values, set, defaults, save, stickyBar, addToBar=
37 const [loading, setLoading] = useStateMounted(false)
38 const onClick = save?.onClick
39 if (onClick)
40 - save.onClick = async function () {
40 + save.onClick = async function (ev) {
41 setLoading(true)
42 - try { return await onClick(this, arguments) }
42 + try { return await onClick(ev) }
43 finally { setLoading(false) }
44 }
45
46 const [pendingSubmit, setPendingSubmit] = useStateMounted(false)
47 useEffect(() => {
48 if (!pendingSubmit) return
49 - setTimeout(save?.onClick)
49 + setTimeout(save?.onClick!)
50 setPendingSubmit(false)
51 }, [pendingSubmit]) //eslint-disable-line
52
admin/src/addFiles.ts
+3 -2
@@ -1,6 +1,6 @@
1 // This file is part of HFS - Copyright 2021-2022, Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt
2
3 -import { alertDialog, newDialog } from './dialog'
3 +import { alertDialog, newDialog, promptDialog } from './dialog'
4 import { createElement as h } from 'react'
5 import { Box } from '@mui/material'
6 import { VfsNode, reloadVfs } from './VfsPage'
@@ -38,7 +38,8 @@ export default function addFiles() {
38
39 export async function addVirtual() {
40 try {
41 - const name = "Folder"+String(Date.now()).slice(8)
41 + const name = await promptDialog("Enter folder name")
42 + if (!name) return
43 const under = getUnder()
44 await apiCall('add_vfs', { under, name })
45 reloadVfs([ (under||'') + '/' + name ])
admin/src/dialog.ts
+52 -5
@@ -6,14 +6,15 @@ import {
6 isValidElement,
7 ReactElement,
8 useEffect,
9 - useRef
9 + useRef,
10 + useState
11 } from 'react'
11 -import { Check, Error as ErrorIcon, Info, Warning } from '@mui/icons-material'
12 -import { newDialog, closeDialog, dialogsDefaults, DialogOptions, Dialogs } from '@hfs/shared/lib/dialogs'
12 +import { Check, Error as ErrorIcon, Forward, Info, Warning } from '@mui/icons-material'
13 +import { newDialog, closeDialog, dialogsDefaults, DialogOptions } from '@hfs/shared/lib/dialogs'
14 +import { Form } from './Form'
15 export * from '@hfs/shared/lib/dialogs'
16
15 -dialogsDefaults.Container = Container
16 -function Container(d:DialogOptions) {
17 +dialogsDefaults.Container = function Container(d:DialogOptions) {
18 useEffect(()=>{
19 ref.current?.focus()
20 }, [])
@@ -83,3 +84,49 @@ export async function confirmDialog(msg: string, { href }: ConfirmOptions={}) :
84 }
85 }
86
87 +type FormProps = Parameters<typeof Form>[0]
88 +export async function formDialog(props: FormProps) : Promise<FormProps['values']> {
89 + return new Promise(resolve => newDialog({
90 + className: 'dialog-confirm',
91 + icon: '?',
92 + onClose: resolve,
93 + Content
94 + }) )
95 +
96 + function Content() {
97 + const [values, setValues] = useState<any>(props.values||{})
98 + return h(Form, {
99 + ...props,
100 + values,
101 + set(v, { k }) {
102 + setValues({ ...values, [k]: v })
103 + },
104 + save: {
105 + ...props.save,
106 + onClick() {
107 + closeDialog(values)
108 + }
109 + }
110 + })
111 + }
112 +}
113 +
114 +export async function promptDialog(msg: string, props:any={}) : Promise<string | undefined> {
115 + return formDialog({
116 + ...props,
117 + fields: [
118 + h(Box, {}, msg),
119 + { k: 'text', label: null, autoFocus: true, },
120 + ],
121 + save: {
122 + children: "Continue",
123 + startIcon: h(Forward),
124 + ...props.save,
125 + },
126 + barSx: { gap: 2 },
127 + addToBar: [
128 + h(Button, { onClick: closeDialog }, "Cancel"),
129 + ...props.addToBar||[],
130 + ]
131 + }).then(values => values?.text)
132 +}
todo.md
+1
@@ -1,5 +1,6 @@
1 # To do
2 - mac/linux binary
3 +- admin/fs: support insert/delete key
4 - if specified config is a folder, check for file config.yaml inside
5 - merge accounts in config
6 - frontend: ok button to inputDialogs