From c255b81093ffdca3606377bafe7f62d79024228f Mon Sep 17 00:00:00 2001 From: gingervitis Date: Sun, 31 Jan 2021 00:48:39 -0800 Subject: [PATCH] rename formfield files for clarity --- .../config/edit-instance-details.tsx | 14 +- .../components/config/edit-server-details.tsx | 13 +- .../config/form-textfield-with-submit.tsx | 137 +++++++++++ .../components/config/form-textfield.tsx | 214 ------------------ ....tsx => form-toggleswitch-with-submit.tsx} | 0 web/pages/index.tsx | 4 +- web/utils/input-statuses.tsx | 2 +- 7 files changed, 154 insertions(+), 230 deletions(-) create mode 100644 web/pages/components/config/form-textfield-with-submit.tsx delete mode 100644 web/pages/components/config/form-textfield.tsx rename web/pages/components/config/{form-toggleswitch.tsx => form-toggleswitch-with-submit.tsx} (100%) diff --git a/web/pages/components/config/edit-instance-details.tsx b/web/pages/components/config/edit-instance-details.tsx index 3ec5129d2..af2821836 100644 --- a/web/pages/components/config/edit-instance-details.tsx +++ b/web/pages/components/config/edit-instance-details.tsx @@ -1,5 +1,5 @@ import React, { useState, useContext, useEffect } from 'react'; -import TextField, { TEXTFIELD_TYPE_TEXTAREA, TEXTFIELD_TYPE_URL } from './form-textfield'; +import TextFieldWithSubmit, { TEXTFIELD_TYPE_TEXTAREA, TEXTFIELD_TYPE_URL } from './form-textfield-with-submit'; import { ServerStatusContext } from '../../../utils/server-status-context'; import { postConfigUpdateToAPI, TEXTFIELD_PROPS_USERNAME, TEXTFIELD_PROPS_INSTANCE_URL, TEXTFIELD_PROPS_SERVER_TITLE, TEXTFIELD_PROPS_STREAM_TITLE, TEXTFIELD_PROPS_SERVER_SUMMARY, TEXTFIELD_PROPS_LOGO, API_YP_SWITCH } from './constants'; @@ -47,7 +47,7 @@ export default function EditInstanceDetails() { return (
- - - - - -
-
- - - (null); + + const [hasChanged, setHasChanged] = useState(false); + const [fieldValueForSubmit, setFieldValueForSubmit] = useState(''); + + const serverStatusData = useContext(ServerStatusContext); + const { setFieldInConfigState } = serverStatusData || {}; + + let resetTimer = null; + + const { + apiPath, + configPath = '', + initialValue, + ...textFieldProps // rest of props + } = props; + + const { + fieldName, + required, + status, + // type, + value, + onChange, + // onBlur, + onSubmit, + } = textFieldProps; + + // 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); + setFieldValueForSubmit(value); + } + }, [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 () => { + if ((required && fieldValueForSubmit !== '') || fieldValueForSubmit !== initialValue) { + setFieldStatus(createInputStatus(STATUS_PROCESSING)); + + // setSubmitStatus('validating'); + + await postConfigUpdateToAPI({ + apiPath, + data: { value: fieldValueForSubmit }, + onSuccess: () => { + setFieldInConfigState({ fieldName, value: fieldValueForSubmit, path: configPath }); + setFieldStatus(createInputStatus(STATUS_SUCCESS)); + // setSubmitStatus('success'); + }, + onError: (message: string) => { + setFieldStatus(createInputStatus(STATUS_ERROR, `There was an error: ${message}`)); + + // setSubmitStatus('error'); + // setSubmitStatusMessage(`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(); + } + } + } + + return ( +
+ + + { hasChanged ? : null } +
+ ); +} + +TextFieldWithSubmit.defaultProps = { + configPath: '', + initialValue: '', +}; diff --git a/web/pages/components/config/form-textfield.tsx b/web/pages/components/config/form-textfield.tsx deleted file mode 100644 index 95c82cae0..000000000 --- a/web/pages/components/config/form-textfield.tsx +++ /dev/null @@ -1,214 +0,0 @@ -import React, { useEffect, useState, useContext } from 'react'; -import { Button, Input, InputNumber } from 'antd'; -import { FormItemProps } from 'antd/es/form'; - -import { RESET_TIMEOUT, postConfigUpdateToAPI } from './constants'; - -import { FieldUpdaterFunc } from '../../../types/config-section'; -import { ServerStatusContext } from '../../../utils/server-status-context'; -import InfoTip from '../info-tip'; - -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 TextFieldProps { - apiPath: string; - fieldName: string; - - configPath?: string; - disabled?: boolean; - initialValue?: string; - label?: string; - maxLength?: number; - placeholder?: string; - required?: boolean; - tip?: string; - type?: string; - value?: string | number; - onSubmit?: () => void; - onBlur?: () => void; - onChange?: FieldUpdaterFunc; -} - - -export default function TextField(props: TextFieldProps) { - const [submitStatus, setSubmitStatus] = useState(''); - const [submitStatusMessage, setSubmitStatusMessage] = useState(''); - const [hasChanged, setHasChanged] = useState(false); - const [fieldValueForSubmit, setFieldValueForSubmit] = useState(''); - - const serverStatusData = useContext(ServerStatusContext); - const { setFieldInConfigState } = serverStatusData || {}; - - let resetTimer = null; - - const { - apiPath, - configPath = '', - disabled = false, - fieldName, - initialValue, - label, - maxLength, - onBlur, - onChange, - onSubmit, - placeholder, - required, - tip, - type, - value, - } = props; - - // Clear out any validation states and messaging - const resetStates = () => { - setSubmitStatus(''); - 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); - setFieldValueForSubmit(value); - } - }, [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 = (e: any) => { - const val = type === TEXTFIELD_TYPE_NUMBER ? e : e.target.value; - - // if an extra onChange handler was sent in as a prop, let's run that too. - if (onChange) { - onChange({ fieldName, value: val }); - } - }; - - // 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 = e => { - if (!onChange) { - return; - } - const val = e.target.value; - if (required && val === '') { - onChange({ fieldName, value: initialValue }); - } - // if an extra onBlur handler was sent in as a prop, let's run that too. - if (onBlur) { - onBlur(); - } - }; - - // how to get current value of input - const handleSubmit = async () => { - if ((required && fieldValueForSubmit !== '') || fieldValueForSubmit !== initialValue) { - setSubmitStatus('validating'); - - await postConfigUpdateToAPI({ - apiPath, - data: { value: fieldValueForSubmit }, - onSuccess: () => { - setFieldInConfigState({ fieldName, value: fieldValueForSubmit, path: configPath }); - setSubmitStatus('success'); - }, - onError: (message: string) => { - setSubmitStatus('error'); - setSubmitStatusMessage(`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(); - } - } - } - - // display the appropriate Ant text field - let Field = Input as typeof Input | typeof InputNumber | typeof Input.TextArea | typeof Input.Password; - let fieldProps = {}; - if (type === TEXTFIELD_TYPE_TEXTAREA) { - Field = Input.TextArea; - fieldProps = { - autoSize: true, - }; - } else if (type === TEXTFIELD_TYPE_PASSWORD) { - Field = Input.Password; - fieldProps = { - visibilityToggle: true, - }; - } else if (type === TEXTFIELD_TYPE_NUMBER) { - Field = InputNumber; - fieldProps = { - type: 'number', - min: 1, - max: (10**maxLength) - 1, - onKeyDown: (e: React.KeyboardEvent) => { - if (e.target.value.length > maxLength - 1 ) - e.preventDefault() - return false; - } - }; - } else if (type === TEXTFIELD_TYPE_URL) { - fieldProps = { - type: 'url', - }; - } - - const fieldId = `field-${fieldName}`; - - return ( -
- { required ? * : null } - -
- -
- - {submitStatus} - {submitStatusMessage} - - { hasChanged ? : null } - -
- ); -} - -TextField.defaultProps = { - configPath: '', - disabled: false, - initialValue: '', - label: '', - maxLength: null, - placeholder: '', - required: false, - tip: '', - type: TEXTFIELD_TYPE_TEXT, - value: '', - onSubmit: () => {}, - onBlur: () => {}, - onChange: () => {}, -}; diff --git a/web/pages/components/config/form-toggleswitch.tsx b/web/pages/components/config/form-toggleswitch-with-submit.tsx similarity index 100% rename from web/pages/components/config/form-toggleswitch.tsx rename to web/pages/components/config/form-toggleswitch-with-submit.tsx diff --git a/web/pages/index.tsx b/web/pages/index.tsx index c8ab68adb..9df1805e2 100644 --- a/web/pages/index.tsx +++ b/web/pages/index.tsx @@ -15,7 +15,7 @@ import { ServerStatusContext } from "../utils/server-status-context"; import StatisticItem from "./components/statistic" import LogTable from "./components/log-table"; import Offline from './offline-notice'; -import TextField from './components/config/form-textfield'; +import TextFieldWithSubmit from './components/config/form-textfield-with-submit'; import { TEXTFIELD_PROPS_STREAM_TITLE } from './components/config/constants'; import { @@ -158,7 +158,7 @@ export default function Home() {
-