2021-01-31 09:48:39 +01:00
import React , { useEffect , useState , useContext } from 'react' ;
import { Button } from 'antd' ;
import { RESET_TIMEOUT , postConfigUpdateToAPI } from './constants' ;
import { ServerStatusContext } from '../../../utils/server-status-context' ;
2021-01-31 09:58:27 +01:00
import TextField , { TextFieldProps } from './form-textfield' ;
2021-01-31 10:38:20 +01:00
import {
createInputStatus ,
StatusState ,
STATUS_ERROR ,
STATUS_PROCESSING ,
STATUS_SUCCESS ,
} from '../../../utils/input-statuses' ;
2021-01-31 09:48:39 +01:00
import { UpdateArgs } from '../../../types/config-section' ;
export const TEXTFIELD_TYPE_TEXT = 'default' ;
export const TEXTFIELD_TYPE_PASSWORD = 'password' ; // Input.Password
export const TEXTFIELD_TYPE_NUMBER = 'numeric' ;
export const TEXTFIELD_TYPE_TEXTAREA = 'textarea' ;
export const TEXTFIELD_TYPE_URL = 'url' ;
interface TextFieldWithSubmitProps extends TextFieldProps {
apiPath : string ;
configPath? : string ;
initialValue? : string ;
}
export default function TextFieldWithSubmit ( props : TextFieldWithSubmitProps ) {
const [ fieldStatus , setFieldStatus ] = useState < StatusState > ( null ) ;
const [ hasChanged , setHasChanged ] = useState ( false ) ;
2021-01-31 10:55:19 +01:00
// const [fieldValueForSubmit, setFieldValueForSubmit] = useState<string | number>('');
2021-01-31 09:48:39 +01:00
const serverStatusData = useContext ( ServerStatusContext ) ;
const { setFieldInConfigState } = serverStatusData || { } ;
let resetTimer = null ;
const {
apiPath ,
configPath = '' ,
initialValue ,
. . . textFieldProps // rest of props
} = props ;
2021-01-31 10:55:19 +01:00
const { fieldName , required , status , value , onChange , onSubmit } = textFieldProps ;
2021-01-31 09:48:39 +01:00
// Clear out any validation states and messaging
const resetStates = ( ) = > {
setFieldStatus ( null ) ;
setHasChanged ( false ) ;
clearTimeout ( resetTimer ) ;
resetTimer = null ;
} ;
useEffect ( ( ) = > {
// TODO: Add native validity checks here, somehow
// https://developer.mozilla.org/en-US/docs/Web/API/ValidityState
// const hasValidity = (type !== TEXTFIELD_TYPE_NUMBER && e.target.validity.valid) || type === TEXTFIELD_TYPE_NUMBER ;
if ( ( required && ( value === '' || value === null ) ) || value === initialValue ) {
setHasChanged ( false ) ;
} else {
// show submit button
resetStates ( ) ;
setHasChanged ( true ) ;
2021-01-31 10:55:19 +01:00
// setFieldValueForSubmit(value);
2021-01-31 09:48:39 +01:00
}
} , [ value ] ) ;
// if field is required but value is empty, or equals initial value, then don't show submit/update button. otherwise clear out any result messaging and display button.
const handleChange = ( { fieldName : changedFieldName , value : changedValue } : UpdateArgs ) = > {
if ( onChange ) {
onChange ( { fieldName : changedFieldName , value : changedValue } ) ;
}
} ;
// if you blur a required field with an empty value, restore its original value in state (parent's state), if an onChange from parent is available.
const handleBlur = ( { value : changedValue } : UpdateArgs ) = > {
if ( onChange && required && changedValue === '' ) {
onChange ( { fieldName , value : initialValue } ) ;
}
} ;
// how to get current value of input
const handleSubmit = async ( ) = > {
2021-01-31 10:55:19 +01:00
if ( ( required && value !== '' ) || value !== initialValue ) {
2021-01-31 09:48:39 +01:00
setFieldStatus ( createInputStatus ( STATUS_PROCESSING ) ) ;
await postConfigUpdateToAPI ( {
apiPath ,
2021-01-31 10:55:19 +01:00
data : { value } ,
2021-01-31 09:48:39 +01:00
onSuccess : ( ) = > {
2021-01-31 10:55:19 +01:00
setFieldInConfigState ( { fieldName , value , path : configPath } ) ;
2021-01-31 09:48:39 +01:00
setFieldStatus ( createInputStatus ( STATUS_SUCCESS ) ) ;
} ,
onError : ( message : string ) = > {
setFieldStatus ( createInputStatus ( STATUS_ERROR , ` There was an error: ${ message } ` ) ) ;
} ,
} ) ;
resetTimer = setTimeout ( resetStates , RESET_TIMEOUT ) ;
// if an extra onSubmit handler was sent in as a prop, let's run that too.
if ( onSubmit ) {
onSubmit ( ) ;
}
}
2021-01-31 10:38:20 +01:00
} ;
2021-01-31 09:48:39 +01:00
return (
< div className = "textfield-with-submit-container" >
2021-01-31 10:38:20 +01:00
< TextField
2021-01-31 09:48:39 +01:00
{ . . . textFieldProps }
status = { status || fieldStatus }
onSubmit = { null }
onBlur = { handleBlur }
onChange = { handleChange }
/ >
2021-01-31 10:38:20 +01:00
{ hasChanged ? (
< Button type = "primary" size = "small" className = "submit-button" onClick = { handleSubmit } >
Update
< / Button >
) : null }
2021-01-31 09:48:39 +01:00
< / div >
2021-01-31 10:38:20 +01:00
) ;
2021-01-31 09:48:39 +01:00
}
TextFieldWithSubmit . defaultProps = {
configPath : '' ,
initialValue : '' ,
} ;