add new Modal option

This commit is contained in:
Pig Fang 2020-01-28 10:41:10 +08:00
parent 364608a0c6
commit 4953e15369
5 changed files with 107 additions and 30 deletions

View File

@ -16,6 +16,7 @@ export type ModalOptions = {
placeholder?: string placeholder?: string
inputType?: string inputType?: string
validator?(value: any): string | boolean | undefined validator?(value: any): string | boolean | undefined
choices?: { text: string; value: string }[]
type?: string type?: string
showHeader?: boolean showHeader?: boolean
center?: boolean center?: boolean
@ -114,6 +115,7 @@ const Modal = React.forwardRef<HTMLDivElement, ModalOptions & Props>(
dangerousHTML={props.dangerousHTML} dangerousHTML={props.dangerousHTML}
showInput={props.mode === 'prompt'} showInput={props.mode === 'prompt'}
value={value} value={value}
choices={props.choices}
onChange={handleInputChange} onChange={handleInputChange}
inputType={props.inputType} inputType={props.inputType}
placeholder={props.placeholder} placeholder={props.placeholder}

View File

@ -1,4 +1,6 @@
import React from 'react' import React from 'react'
import ModalContent from './ModalContent'
import ModalInput from './ModalInput'
interface Props { interface Props {
text?: string text?: string
@ -6,6 +8,7 @@ interface Props {
showInput: boolean showInput: boolean
inputType?: string inputType?: string
value?: string value?: string
choices?: { text: string; value: string }[]
onChange?: React.ChangeEventHandler<HTMLInputElement> onChange?: React.ChangeEventHandler<HTMLInputElement>
placeholder?: string placeholder?: string
invalid?: boolean invalid?: boolean
@ -13,38 +16,12 @@ interface Props {
} }
const ModalBody: React.FC<Props> = props => { const ModalBody: React.FC<Props> = props => {
const main = (() => {
if (props.children) {
return props.children
} else if (props.text) {
return props.text.split(/\r?\n/).map((line, i) => <p key={i}>{line}</p>)
} else if (props.dangerousHTML) {
return <div dangerouslySetInnerHTML={{ __html: props.dangerousHTML }} />
}
})()
return ( return (
<div className="modal-body"> <div className="modal-body">
{main} <ModalContent text={props.text} dangerousHTML={props.dangerousHTML}>
{props.showInput && ( {props.children}
<> </ModalContent>
<div className="form-group"> {props.showInput && <ModalInput {...props} />}
<input
value={props.value}
onChange={props.onChange}
type={props.inputType}
className="form-control"
placeholder={props.placeholder}
></input>
</div>
{props.invalid && (
<div className="alert alert-danger">
<i className="icon far fa-times-circle"></i>
<span className="ml-1">{props.validatorMessage}</span>
</div>
)}
</>
)}
</div> </div>
) )
} }

View File

@ -0,0 +1,26 @@
import React from 'react'
interface Props {
text?: string
dangerousHTML?: string
}
const ModalContent: React.FC<Props> = props => {
if (props.children) {
return <>{props.children}</>
} else if (props.text) {
return (
<>
{props.text.split(/\r?\n/).map((line, i) => (
<p key={i}>{line}</p>
))}
</>
)
} else if (props.dangerousHTML) {
return <div dangerouslySetInnerHTML={{ __html: props.dangerousHTML }} />
}
return <></>
}
export default ModalContent

View File

@ -0,0 +1,52 @@
import React from 'react'
interface Props {
inputType?: string
value?: string
choices?: { text: string; value: string }[]
onChange?: React.ChangeEventHandler<HTMLInputElement>
placeholder?: string
invalid?: boolean
validatorMessage?: string
}
const ModalInput: React.FC<Props> = props => (
<>
{props.inputType === 'radios' && props.choices ? (
<>
{props.choices.map(choice => (
<div key={choice.value}>
<input
type="radio"
name="modal-radios"
id={`modal-radio-${choice.value}`}
value={choice.value}
onChange={props.onChange}
/>
<label htmlFor={`modal-radio-${choice.value}`} className="ml-1">
{choice.text}
</label>
</div>
))}
</>
) : (
<div className="form-group">
<input
value={props.value}
onChange={props.onChange}
type={props.inputType}
className="form-control"
placeholder={props.placeholder}
></input>
</div>
)}
{props.invalid && (
<div className="alert alert-danger">
<i className="icon far fa-times-circle"></i>
<span className="ml-1">{props.validatorMessage}</span>
</div>
)}
</>
)
export default ModalInput

View File

@ -218,6 +218,26 @@ describe('"prompt" mode', () => {
expect(reject).toBeCalled() expect(reject).toBeCalled()
}) })
it('radio inputs', () => {
const choices = [
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b' },
]
const resolve = jest.fn()
const { getByText, getByLabelText } = render(
<Modal
mode="prompt"
inputType="radios"
choices={choices}
onConfirm={resolve}
show
/>,
)
fireEvent.click(getByLabelText('B'))
fireEvent.click(getByText(trans('general.confirm')))
expect(resolve).toBeCalledWith({ value: 'b' })
})
it('validate input', () => { it('validate input', () => {
const resolve = jest.fn() const resolve = jest.fn()
const reject = jest.fn() const reject = jest.fn()