From 074efe3b4399ae3a9828ed101b463c41b616c76d Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Tue, 20 Jun 2023 10:19:40 +0800 Subject: [PATCH] Show error messages in labels modal --- .../templates/article/SetLabelsControl.tsx | 35 ++++++++++- .../templates/article/SetLabelsModal.tsx | 58 +++++++++++++++---- 2 files changed, 80 insertions(+), 13 deletions(-) diff --git a/packages/web/components/templates/article/SetLabelsControl.tsx b/packages/web/components/templates/article/SetLabelsControl.tsx index 9e17a646e..1e03fb872 100644 --- a/packages/web/components/templates/article/SetLabelsControl.tsx +++ b/packages/web/components/templates/article/SetLabelsControl.tsx @@ -6,7 +6,13 @@ import { StyledText } from '../../elements/StyledText' import { styled, theme } from '../../tokens/stitches.config' import { Label } from '../../../lib/networking/fragments/labelFragment' import { useGetLabelsQuery } from '../../../lib/networking/queries/useGetLabelsQuery' -import { Check, Circle, PencilSimple, Plus } from 'phosphor-react' +import { + Check, + Circle, + PencilSimple, + Plus, + WarningCircle, +} from 'phosphor-react' import { createLabelMutation } from '../../../lib/networking/mutations/createLabelMutation' import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers' import { randomLabelColorHex } from '../../../utils/settings-page/labels/labelColorObjects' @@ -39,6 +45,8 @@ type SetLabelsControlProps = { deleteLastLabel: () => void selectOrCreateLabel: (value: string) => void + + errorMessage?: string } type HeaderProps = { @@ -75,7 +83,8 @@ function Header(props: HeaderProps): JSX.Element { @@ -414,6 +423,28 @@ export function SetLabelsControl(props: SetLabelsControlProps): JSX.Element { selectOrCreateLabel={props.selectOrCreateLabel} clearInputState={props.clearInputState} /> + + {props.errorMessage && ( + <> + {props.errorMessage} + + + )} + ( + undefined + ) + const errorTimeoutRef = useRef() const [highlightLastLabel, setHighlightLastLabel] = useState(false) const [selectedLabels, setSelectedLabels] = useState( @@ -47,9 +51,35 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element { [props, selectedLabels] ) - const showMessage = useCallback((msg: string) => { - console.log('showMessage: ', msg) - }, []) + const showMessage = useCallback( + (msg: string, timeout?: number) => { + if (errorTimeoutRef.current) { + clearTimeout(errorTimeoutRef.current) + errorTimeoutRef.current = undefined + } + setErrorMessage(msg) + if (timeout) { + errorTimeoutRef.current = setTimeout(() => { + setErrorMessage(undefined) + if (errorTimeoutRef.current) { + clearTimeout(errorTimeoutRef.current) + errorTimeoutRef.current = undefined + } + }, timeout) + } + }, + [errorTimeoutRef] + ) + + useEffect(() => { + const maxLengthMessage = 'Max label length: 48 chars' + + if (inputValue.length >= 48) { + showMessage(maxLengthMessage) + } else if (errorMessage === maxLengthMessage) { + setErrorMessage(undefined) + } + }, [inputValue, showMessage]) const clearInputState = useCallback(() => { setTabCount(-1) @@ -59,15 +89,15 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element { }, [tabCount, tabStartValue, highlightLastLabel]) const createLabelAsync = useCallback( - (tempLabel: Label) => { + (newLabels: Label[], tempLabel: Label) => { ;(async () => { - const currentLabels = selectedLabels + const currentLabels = newLabels const newLabel = await createLabelMutation( tempLabel.name, tempLabel.color ) + const idx = currentLabels.findIndex((l) => l.id === tempLabel.id) if (newLabel) { - const idx = currentLabels.findIndex((l) => l.id === tempLabel.id) showSuccessToast(`Created label ${newLabel.name}`, { position: 'bottom-right', }) @@ -78,7 +108,11 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element { setSelectedLabels([...currentLabels, newLabel]) } } else { - showMessage(`Error creating label ${tempLabel.name}`) + showMessage(`Error creating label ${tempLabel.name}`, 5000) + if (idx !== -1) { + currentLabels.splice(idx, 1) + setSelectedLabels([...currentLabels]) + } } })() }, @@ -105,7 +139,7 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element { setSelectedLabels([...current, existing]) clearInputState() } else { - showMessage(`label ${value} already added.`) + showMessage(`label ${value} already added.`, 5000) } } else { const tempLabel = { @@ -116,10 +150,11 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element { createdAt: new Date(), _temporary: true, } - setSelectedLabels([...current, tempLabel]) + const newLabels = [...current, tempLabel] + setSelectedLabels(newLabels) clearInputState() - createLabelAsync(tempLabel) + createLabelAsync(newLabels, tempLabel) } }, [ @@ -183,6 +218,7 @@ export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element { setHighlightLastLabel={setHighlightLastLabel} deleteLastLabel={deleteLastLabel} selectOrCreateLabel={selectOrCreateLabel} + errorMessage={errorMessage} />