form enhancements
This commit is contained in:
parent
5bb6b5f2e7
commit
6d8780373a
|
@ -3,7 +3,7 @@ import InputGroup from 'react-bootstrap/InputGroup'
|
||||||
import BootstrapForm from 'react-bootstrap/Form'
|
import BootstrapForm from 'react-bootstrap/Form'
|
||||||
import Alert from 'react-bootstrap/Alert'
|
import Alert from 'react-bootstrap/Alert'
|
||||||
import { Formik, Form as FormikForm, useFormikContext, useField, FieldArray } from 'formik'
|
import { Formik, Form as FormikForm, useFormikContext, useField, FieldArray } from 'formik'
|
||||||
import React, { useEffect, useRef, useState } from 'react'
|
import React, { createContext, useContext, useEffect, useState } from 'react'
|
||||||
import copy from 'clipboard-copy'
|
import copy from 'clipboard-copy'
|
||||||
import Thumb from '../svgs/thumb-up-fill.svg'
|
import Thumb from '../svgs/thumb-up-fill.svg'
|
||||||
import { Col, Dropdown as BootstrapDropdown, Nav } from 'react-bootstrap'
|
import { Col, Dropdown as BootstrapDropdown, Nav } from 'react-bootstrap'
|
||||||
|
@ -132,10 +132,11 @@ function FormGroup ({ className, label, children }) {
|
||||||
|
|
||||||
function InputInner ({
|
function InputInner ({
|
||||||
prepend, append, hint, showValid, onChange, overrideValue,
|
prepend, append, hint, showValid, onChange, overrideValue,
|
||||||
innerRef, storageKeyPrefix, noForm, clear, onKeyDown, ...props
|
innerRef, noForm, clear, onKeyDown, ...props
|
||||||
}) {
|
}) {
|
||||||
const [field, meta, helpers] = noForm ? [{}, {}, {}] : useField(props)
|
const [field, meta, helpers] = noForm ? [{}, {}, {}] : useField(props)
|
||||||
const formik = noForm ? null : useFormikContext()
|
const formik = noForm ? null : useFormikContext()
|
||||||
|
const storageKeyPrefix = useContext(StorageKeyPrefixContext)
|
||||||
|
|
||||||
const storageKey = storageKeyPrefix ? storageKeyPrefix + '-' + props.name : undefined
|
const storageKey = storageKeyPrefix ? storageKeyPrefix + '-' + props.name : undefined
|
||||||
|
|
||||||
|
@ -155,7 +156,7 @@ function InputInner ({
|
||||||
}
|
}
|
||||||
}, [overrideValue])
|
}, [overrideValue])
|
||||||
|
|
||||||
const invalid = meta.touched && meta.error
|
const invalid = (!formik || formik.submitCount > 0) && meta.touched && meta.error
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -363,6 +364,8 @@ export function Checkbox ({ children, label, groupClassName, hiddenLabel, extra,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StorageKeyPrefixContext = createContext()
|
||||||
|
|
||||||
export function Form ({
|
export function Form ({
|
||||||
initial, schema, onSubmit, children, initialError, validateImmediately, storageKeyPrefix, ...props
|
initial, schema, onSubmit, children, initialError, validateImmediately, storageKeyPrefix, ...props
|
||||||
}) {
|
}) {
|
||||||
|
@ -389,46 +392,10 @@ export function Form ({
|
||||||
>
|
>
|
||||||
<FormikForm {...props} noValidate>
|
<FormikForm {...props} noValidate>
|
||||||
{error && <Alert variant='danger' onClose={() => setError(undefined)} dismissible>{error}</Alert>}
|
{error && <Alert variant='danger' onClose={() => setError(undefined)} dismissible>{error}</Alert>}
|
||||||
{storageKeyPrefix
|
<StorageKeyPrefixContext.Provider value={storageKeyPrefix}>
|
||||||
? React.Children.map(children, (child) => {
|
|
||||||
// if child has a type that's a string, it's a dom element and can't get a prop
|
|
||||||
if (child) {
|
|
||||||
let childProps = {}
|
|
||||||
if (typeof child.type !== 'string') {
|
|
||||||
childProps = { storageKeyPrefix }
|
|
||||||
}
|
|
||||||
return React.cloneElement(child, childProps)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
: children}
|
|
||||||
</FormikForm>
|
|
||||||
</Formik>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SyncForm ({
|
|
||||||
initial, schema, children, action, ...props
|
|
||||||
}) {
|
|
||||||
const ref = useRef(null)
|
|
||||||
return (
|
|
||||||
<Formik
|
|
||||||
initialValues={initial}
|
|
||||||
validationSchema={schema}
|
|
||||||
validateOnBlur={false}
|
|
||||||
onSubmit={() => ref.current.submit()}
|
|
||||||
>
|
|
||||||
{props => (
|
|
||||||
<form
|
|
||||||
ref={ref}
|
|
||||||
onSubmit={props.handleSubmit}
|
|
||||||
onReset={props.handleReset}
|
|
||||||
action={action}
|
|
||||||
method='POST'
|
|
||||||
noValidate
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</form>
|
</StorageKeyPrefixContext.Provider>
|
||||||
)}
|
</FormikForm>
|
||||||
</Formik>
|
</Formik>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,7 @@ function TopLevelItem ({ item, noReply, ...props }) {
|
||||||
return (
|
return (
|
||||||
<ItemComponent
|
<ItemComponent
|
||||||
item={item}
|
item={item}
|
||||||
|
full
|
||||||
right={
|
right={
|
||||||
<>
|
<>
|
||||||
<Share item={item} />
|
<Share item={item} />
|
||||||
|
|
|
@ -15,7 +15,7 @@ import DontLikeThisDropdownItem from './dont-link-this'
|
||||||
import BookmarkDropdownItem from './bookmark'
|
import BookmarkDropdownItem from './bookmark'
|
||||||
import { CopyLinkDropdownItem } from './share'
|
import { CopyLinkDropdownItem } from './share'
|
||||||
|
|
||||||
export default function ItemInfo ({ item, commentsText, className, embellishUser, extraInfo, onEdit, editText }) {
|
export default function ItemInfo ({ item, full, commentsText, className, embellishUser, extraInfo, onEdit, editText }) {
|
||||||
const editThreshold = new Date(item.createdAt).getTime() + 10 * 60000
|
const editThreshold = new Date(item.createdAt).getTime() + 10 * 60000
|
||||||
const me = useMe()
|
const me = useMe()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
@ -23,8 +23,9 @@ export default function ItemInfo ({ item, commentsText, className, embellishUser
|
||||||
useState(item.mine && (Date.now() < editThreshold))
|
useState(item.mine && (Date.now() < editThreshold))
|
||||||
const [hasNewComments, setHasNewComments] = useState(false)
|
const [hasNewComments, setHasNewComments] = useState(false)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// if we are showing toc, then this is a full item
|
if (!full) {
|
||||||
setHasNewComments(newComments(item))
|
setHasNewComments(newComments(item))
|
||||||
|
}
|
||||||
}, [item])
|
}, [item])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -18,7 +18,7 @@ export function SearchTitle ({ title }) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Item ({ item, rank, belowTitle, right, children }) {
|
export default function Item ({ item, rank, belowTitle, right, full, children }) {
|
||||||
const titleRef = useRef()
|
const titleRef = useRef()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -58,7 +58,7 @@ export default function Item ({ item, rank, belowTitle, right, children }) {
|
||||||
</a>
|
</a>
|
||||||
</>}
|
</>}
|
||||||
</div>
|
</div>
|
||||||
<ItemInfo item={item} />
|
<ItemInfo full={full} item={item} />
|
||||||
{belowTitle}
|
{belowTitle}
|
||||||
</div>
|
</div>
|
||||||
{right}
|
{right}
|
||||||
|
|
|
@ -179,6 +179,7 @@ export function WithdrawlForm () {
|
||||||
name='invoice'
|
name='invoice'
|
||||||
required
|
required
|
||||||
autoFocus
|
autoFocus
|
||||||
|
clear
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
label='max fee'
|
label='max fee'
|
||||||
|
|
Loading…
Reference in New Issue