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() {
-