adjust other status info areas

This commit is contained in:
gingervitis
2021-01-31 22:07:00 -08:00
parent a8d515724c
commit 05167f77e5
4 changed files with 48 additions and 50 deletions

View File

@@ -9,12 +9,14 @@ import {
API_SOCIAL_HANDLES, API_SOCIAL_HANDLES,
postConfigUpdateToAPI, postConfigUpdateToAPI,
RESET_TIMEOUT, RESET_TIMEOUT,
SUCCESS_STATES,
DEFAULT_SOCIAL_HANDLE, DEFAULT_SOCIAL_HANDLE,
OTHER_SOCIAL_HANDLE_OPTION, OTHER_SOCIAL_HANDLE_OPTION,
} from './constants'; } from './constants';
import { SocialHandle } from '../../../types/config-section'; import { SocialHandle, UpdateArgs } from '../../../types/config-section';
import { isValidUrl } from '../../../utils/urls'; import { isValidUrl } from '../../../utils/urls';
import TextField from './form-textfield';
import { createInputStatus, STATUS_ERROR, STATUS_SUCCESS } from '../../../utils/input-statuses';
import InputStatusInfo from './input-status-info';
const { Title } = Typography; const { Title } = Typography;
@@ -31,7 +33,6 @@ export default function EditSocialLinks() {
const [modalDataState, setModalDataState] = useState(DEFAULT_SOCIAL_HANDLE); const [modalDataState, setModalDataState] = useState(DEFAULT_SOCIAL_HANDLE);
const [submitStatus, setSubmitStatus] = useState(null); const [submitStatus, setSubmitStatus] = useState(null);
const [submitStatusMessage, setSubmitStatusMessage] = useState('');
const serverStatusData = useContext(ServerStatusContext); const serverStatusData = useContext(ServerStatusContext);
const { serverConfig, setFieldInConfigState } = serverStatusData || {}; const { serverConfig, setFieldInConfigState } = serverStatusData || {};
@@ -71,7 +72,6 @@ export default function EditSocialLinks() {
const resetStates = () => { const resetStates = () => {
setSubmitStatus(null); setSubmitStatus(null);
setSubmitStatusMessage('');
resetTimer = null; resetTimer = null;
clearTimeout(resetTimer); clearTimeout(resetTimer);
}; };
@@ -106,8 +106,8 @@ export default function EditSocialLinks() {
const { value } = event.target; const { value } = event.target;
updateModalState('platform', value); updateModalState('platform', value);
}; };
const handleUrlChange = event => {
const { value } = event.target; const handleUrlChange = ({ value }: UpdateArgs) => {
updateModalState('url', value); updateModalState('url', value);
}; };
@@ -127,13 +127,12 @@ export default function EditSocialLinks() {
setModalProcessing(false); setModalProcessing(false);
handleModalCancel(); handleModalCancel();
setSubmitStatus('success'); setSubmitStatus(createInputStatus(STATUS_SUCCESS));
setSubmitStatusMessage('Social Handles updated.');
resetTimer = setTimeout(resetStates, RESET_TIMEOUT); resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
}, },
onError: (message: string) => { onError: (message: string) => {
setSubmitStatus('error'); setSubmitStatus(createInputStatus(STATUS_ERROR, `There was an error: ${message}`));
setSubmitStatusMessage(message);
resetTimer = setTimeout(resetStates, RESET_TIMEOUT); resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
}, },
}); });
@@ -221,24 +220,16 @@ export default function EditSocialLinks() {
}, },
]; ];
const { icon: newStatusIcon = null, message: newStatusMessage = '' } =
SUCCESS_STATES[submitStatus] || {};
const statusMessage = (
<div className={`status-message ${submitStatus || ''}`}>
{newStatusIcon} {newStatusMessage} {submitStatusMessage}
</div>
);
const okButtonProps = { const okButtonProps = {
disabled: !isValidUrl(modalDataState.url), disabled: !isValidUrl(modalDataState.url),
}; };
return ( return (
<div className={`socialLinksEditor`}> <div className="social-links-edit-container">
<Title level={2}>Social Links</Title> <Title level={2}>Social Links</Title>
<p>Add all your social media handles and links to your other profiles here.</p> <p>Add all your social media handles and links to your other profiles here.</p>
{statusMessage} <InputStatusInfo status={submitStatus} />
<Table <Table
className="dataTable" className="dataTable"
@@ -273,14 +264,14 @@ export default function EditSocialLinks() {
</> </>
) : null} ) : null}
<br /> <br />
URL <TextField
<Input fieldName="social-url"
label="URL"
placeholder="Url to page" placeholder="Url to page"
defaultValue={modalDataState.url}
value={modalDataState.url} value={modalDataState.url}
onChange={handleUrlChange} onChange={handleUrlChange}
/> />
{statusMessage} <InputStatusInfo status={submitStatus} />
</Modal> </Modal>
<br /> <br />
<Button <Button

View File

@@ -28,7 +28,7 @@ interface TextFieldWithSubmitProps extends TextFieldProps {
} }
export default function TextFieldWithSubmit(props: TextFieldWithSubmitProps) { export default function TextFieldWithSubmit(props: TextFieldWithSubmitProps) {
const [fieldStatus, setFieldStatus] = useState<StatusState>(null); const [submitStatus, setSubmitStatus] = useState<StatusState>(null);
const [hasChanged, setHasChanged] = useState(false); const [hasChanged, setHasChanged] = useState(false);
@@ -48,7 +48,7 @@ export default function TextFieldWithSubmit(props: TextFieldWithSubmitProps) {
// Clear out any validation states and messaging // Clear out any validation states and messaging
const resetStates = () => { const resetStates = () => {
setFieldStatus(null); setSubmitStatus(null);
setHasChanged(false); setHasChanged(false);
clearTimeout(resetTimer); clearTimeout(resetTimer);
resetTimer = null; resetTimer = null;
@@ -84,17 +84,17 @@ export default function TextFieldWithSubmit(props: TextFieldWithSubmitProps) {
// how to get current value of input // how to get current value of input
const handleSubmit = async () => { const handleSubmit = async () => {
if ((required && value !== '') || value !== initialValue) { if ((required && value !== '') || value !== initialValue) {
setFieldStatus(createInputStatus(STATUS_PROCESSING)); setSubmitStatus(createInputStatus(STATUS_PROCESSING));
await postConfigUpdateToAPI({ await postConfigUpdateToAPI({
apiPath, apiPath,
data: { value }, data: { value },
onSuccess: () => { onSuccess: () => {
setFieldInConfigState({ fieldName, value, path: configPath }); setFieldInConfigState({ fieldName, value, path: configPath });
setFieldStatus(createInputStatus(STATUS_SUCCESS)); setSubmitStatus(createInputStatus(STATUS_SUCCESS));
}, },
onError: (message: string) => { onError: (message: string) => {
setFieldStatus(createInputStatus(STATUS_ERROR, `There was an error: ${message}`)); setSubmitStatus(createInputStatus(STATUS_ERROR, `There was an error: ${message}`));
}, },
}); });
resetTimer = setTimeout(resetStates, RESET_TIMEOUT); resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
@@ -115,7 +115,6 @@ export default function TextFieldWithSubmit(props: TextFieldWithSubmitProps) {
<div className="textfield-component"> <div className="textfield-component">
<TextField <TextField
{...textFieldProps} {...textFieldProps}
status={status || fieldStatus}
onSubmit={null} onSubmit={null}
onBlur={handleBlur} onBlur={handleBlur}
onChange={handleChange} onChange={handleChange}
@@ -125,7 +124,7 @@ export default function TextFieldWithSubmit(props: TextFieldWithSubmitProps) {
<p className="label-spacer" /> <p className="label-spacer" />
<div className="lower-content"> <div className="lower-content">
<div className="field-tip">{tip}</div> <div className="field-tip">{tip}</div>
<InputStatusInfo status={status || fieldStatus} /> <InputStatusInfo status={status || submitStatus} />
<div className="update-button-container"> <div className="update-button-container">
<Button <Button
type="primary" type="primary"

View File

@@ -1,8 +1,15 @@
import React, { useState, useContext } from 'react'; import React, { useState, useContext } from 'react';
import { Switch } from 'antd'; import { Switch } from 'antd';
import { FormItemProps } from 'antd/es/form'; import {
createInputStatus,
StatusState,
STATUS_ERROR,
STATUS_PROCESSING,
STATUS_SUCCESS,
} from '../../../utils/input-statuses';
import InputStatusInfo from './input-status-info';
import { RESET_TIMEOUT, SUCCESS_STATES, postConfigUpdateToAPI } from './constants'; import { RESET_TIMEOUT, postConfigUpdateToAPI } from './constants';
import { ServerStatusContext } from '../../../utils/server-status-context'; import { ServerStatusContext } from '../../../utils/server-status-context';
import InfoTip from '../info-tip'; import InfoTip from '../info-tip';
@@ -19,8 +26,7 @@ interface ToggleSwitchProps {
} }
export default function ToggleSwitch(props: ToggleSwitchProps) { export default function ToggleSwitch(props: ToggleSwitchProps) {
const [submitStatus, setSubmitStatus] = useState<FormItemProps['validateStatus']>(''); const [submitStatus, setSubmitStatus] = useState<StatusState>(null);
const [submitStatusMessage, setSubmitStatusMessage] = useState('');
let resetTimer = null; let resetTimer = null;
@@ -30,37 +36,35 @@ export default function ToggleSwitch(props: ToggleSwitchProps) {
const { apiPath, checked, configPath = '', disabled = false, fieldName, label, tip } = props; const { apiPath, checked, configPath = '', disabled = false, fieldName, label, tip } = props;
const resetStates = () => { const resetStates = () => {
setSubmitStatus(''); setSubmitStatus(null);
clearTimeout(resetTimer); clearTimeout(resetTimer);
resetTimer = null; resetTimer = null;
}; };
const handleChange = async (isChecked: boolean) => { const handleChange = async (isChecked: boolean) => {
setSubmitStatus('validating'); setSubmitStatus(createInputStatus(STATUS_PROCESSING));
await postConfigUpdateToAPI({ await postConfigUpdateToAPI({
apiPath, apiPath,
data: { value: isChecked }, data: { value: isChecked },
onSuccess: () => { onSuccess: () => {
setFieldInConfigState({ fieldName, value: isChecked, path: configPath }); setFieldInConfigState({ fieldName, value: isChecked, path: configPath });
setSubmitStatus('success'); setSubmitStatus(createInputStatus(STATUS_SUCCESS));
}, },
onError: (message: string) => { onError: (message: string) => {
setSubmitStatus('error'); setSubmitStatus(createInputStatus(STATUS_ERROR, `There was an error: ${message}`));
setSubmitStatusMessage(`There was an error: ${message}`);
}, },
}); });
resetTimer = setTimeout(resetStates, RESET_TIMEOUT); resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
}; };
const { icon: newStatusIcon = null, message: newStatusMessage = '' } = const loading = submitStatus !== null && submitStatus.type === STATUS_PROCESSING;
SUCCESS_STATES[submitStatus] || {};
return ( return (
<div className="toggleswitch-container"> <div className="toggleswitch-container">
<div className="toggleswitch"> <div className="toggleswitch">
<Switch <Switch
className={`switch field-${fieldName}`} className={`switch field-${fieldName}`}
loading={submitStatus === 'validating'} loading={loading}
onChange={handleChange} onChange={handleChange}
defaultChecked={checked} defaultChecked={checked}
checked={checked} checked={checked}
@@ -71,11 +75,8 @@ export default function ToggleSwitch(props: ToggleSwitchProps) {
<span className="label"> <span className="label">
{label} <InfoTip tip={tip} /> {label} <InfoTip tip={tip} />
</span> </span>
{submitStatus}
</div>
<div className={`status-message ${submitStatus || ''}`}>
{newStatusIcon} {newStatusMessage} {submitStatusMessage}
</div> </div>
<InputStatusInfo status={submitStatus} />
</div> </div>
); );
} }

View File

@@ -1,5 +1,6 @@
// Base styles for form-textfield, form-textfield-with-submit, and helper components. // Base styles for form-textfield, form-textfield-with-submit, and helper components.
/* STATUS-CONTAINER BASE */
.status-container { .status-container {
&.status-success { &.status-success {
color: var(--ant-success); color: var(--ant-success);
@@ -25,12 +26,15 @@
} }
} }
/* TIP CONTAINER BASE */
.field-tip { .field-tip {
font-size: .7em; font-size: .7em;
color: rgba(255,255,255,.7) color: rgba(255,255,255,.5)
} }
/* TEXTFIELD-CONTAINER BASE */
.textfield-container { .textfield-container {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@@ -99,7 +103,7 @@
} }
} }
/* TEXTFIELD-WITH-SUBMIT-CONTAINER BASE */
.textfield-with-submit-container { .textfield-with-submit-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -139,6 +143,9 @@
} }
.status-container { .status-container {
margin: .5em; margin: .5em;
&.empty {
display: none;
}
} }
} }
.update-button-container { .update-button-container {