display errors in UI

This commit is contained in:
arc-alex
2024-01-03 01:52:30 +01:00
parent ba89673d5f
commit cb6dee552f
4 changed files with 76 additions and 35 deletions
@@ -55,6 +55,14 @@ export default function SheetsModal(props: SheetsModalProps) {
const sheetRef = useRef<HTMLInputElement>(null); const sheetRef = useRef<HTMLInputElement>(null);
const worksheetRef = useRef<HTMLSelectElement>(null); const worksheetRef = useRef<HTMLSelectElement>(null);
const [errors, setErrors] = useState({
clientSecret: '',
authenticate: '',
sheetId: '',
worksheet: '',
pullPush: '',
});
const [sheetState, setState] = useState<SheetState>({ const [sheetState, setState] = useState<SheetState>({
secret: false, secret: false,
auth: false, auth: false,
@@ -63,10 +71,6 @@ export default function SheetsModal(props: SheetsModalProps) {
worksheetOptions: [], worksheetOptions: [],
}); });
const testId = async () => {
setState(await getSheetState(sheetRef.current?.value ?? '', worksheetRef.current?.value ?? ''));
};
const handleClose = () => { const handleClose = () => {
setRundown(null); setRundown(null);
setProject(null); setProject(null);
@@ -81,21 +85,37 @@ export default function SheetsModal(props: SheetsModalProps) {
const updateSheetState = () => { const updateSheetState = () => {
const currentSheetId = sheetRef.current?.value ?? ''; const currentSheetId = sheetRef.current?.value ?? '';
const currentWorksheet = worksheetRef.current?.value ?? ''; const currentWorksheet = worksheetRef.current?.value ?? '';
getSheetState(currentSheetId, currentWorksheet).then((data) => setState(data)); return getSheetState(currentSheetId, currentWorksheet).then((data) => setState(data));
}; };
const handleFile = async (event: ChangeEvent<HTMLInputElement>) => { const testId = () => {
const currentSheetId = sheetRef.current?.value ?? '';
const currentWorksheet = worksheetRef.current?.value ?? '';
getSheetState(currentSheetId, currentWorksheet)
.then((data) => setState(data))
.catch((err) => {
if (err.response.data.message) {
setErrors({ ...errors, sheetId: err.response.data.message });
}
});
};
const handleFile = (event: ChangeEvent<HTMLInputElement>) => {
if (!event.target.files?.length) { if (!event.target.files?.length) {
setErrors({ ...errors, clientSecret: 'Missing file' });
return; return;
} }
const selectedFile = event.target.files[0]; const selectedFile = event.target.files[0];
try { uploadSheetClientFile(selectedFile)
await uploadSheetClientFile(selectedFile); .then(() => {
} catch (error) { setErrors({ ...errors, clientSecret: '' });
// TODO: show this in the modal })
console.error(error); .catch((err) => {
} if (err.response.data.message) {
setErrors({ ...errors, clientSecret: err.response.data.message });
}
});
updateSheetState(); updateSheetState();
}; };
@@ -106,12 +126,16 @@ export default function SheetsModal(props: SheetsModalProps) {
}, [isOpen]); }, [isOpen]);
const handleAuthenticate = () => { const handleAuthenticate = () => {
getSheetsAuthUrl().then((data) => { getSheetsAuthUrl()
if (data !== 'bad') { .then((data) => {
openLink(data); openLink(data);
window.addEventListener('focus', () => updateSheetState(), { once: true }); window.addEventListener('focus', () => updateSheetState(), { once: true });
} })
}); .catch((err) => {
if (err.response.data.message) {
setErrors({ ...errors, authenticate: err.response.data.message });
}
});
}; };
const handlePullData = () => { const handlePullData = () => {
@@ -180,7 +204,12 @@ export default function SheetsModal(props: SheetsModalProps) {
</Alert> </Alert>
{!rundown ? ( {!rundown ? (
<> <>
<Step title='1 - Upload OAuth 2.0 Client ID' completed={Boolean(sheetState?.secret)} disabled={false}> <Step
title='1 - Upload OAuth 2.0 Client ID'
completed={Boolean(sheetState?.secret)}
disabled={false}
error={errors.clientSecret}
>
<Input <Input
ref={fileInputRef} ref={fileInputRef}
style={{ display: 'none' }} style={{ display: 'none' }}
@@ -198,6 +227,7 @@ export default function SheetsModal(props: SheetsModalProps) {
title='2 - Authenticate with Google' title='2 - Authenticate with Google'
completed={Boolean(sheetState?.auth)} completed={Boolean(sheetState?.auth)}
disabled={!sheetState?.secret} disabled={!sheetState?.secret}
error={errors.authenticate}
> >
<Button <Button
size='sm' size='sm'
@@ -209,7 +239,12 @@ export default function SheetsModal(props: SheetsModalProps) {
</Button> </Button>
</Step> </Step>
<Step title='3 - Add Document ID' completed={Boolean(sheetState?.id)} disabled={!sheetState?.auth}> <Step
title='3 - Add Document ID'
completed={Boolean(sheetState?.id)}
disabled={!sheetState?.auth}
error={errors.sheetId}
>
<HStack> <HStack>
<Input <Input
type='text' type='text'
@@ -1,6 +1,6 @@
import { PropsWithChildren, useEffect, useState } from 'react'; import { PropsWithChildren, useEffect, useState } from 'react';
import { IoCheckmarkCircle } from '@react-icons/all-files/io5/IoCheckmarkCircle'; import { IoCheckmarkCircle } from '@react-icons/all-files/io5/IoCheckmarkCircle';
import { IoClose } from '@react-icons/all-files/io5/IoClose'; import { IoCloseCircle } from '@react-icons/all-files/io5/IoCloseCircle';
import { IoRadioButtonOffOutline } from '@react-icons/all-files/io5/IoRadioButtonOffOutline'; import { IoRadioButtonOffOutline } from '@react-icons/all-files/io5/IoRadioButtonOffOutline';
import style from './Step.module.scss'; import style from './Step.module.scss';
@@ -15,7 +15,7 @@ interface StepProps {
export default function Step(props: PropsWithChildren<StepProps>) { export default function Step(props: PropsWithChildren<StepProps>) {
const { title, disabled, completed, error, children } = props; const { title, disabled, completed, error, children } = props;
const [collapsed, setCollapsed] = useState(disabled); const [collapsed, setCollapsed] = useState(disabled);
const handleCollapse = () => setCollapsed((prev) => !prev); const handleCollapse = () => setCollapsed((prev) => !prev);
useEffect(() => { useEffect(() => {
@@ -27,9 +27,14 @@ export default function Step(props: PropsWithChildren<StepProps>) {
return ( return (
<div className={style.wrapper}> <div className={style.wrapper}>
<div className={style.header} onClick={handleCollapse}> <div className={style.header} onClick={handleCollapse}>
{completed ? <IoCheckmarkCircle className={style.step} /> : <IoRadioButtonOffOutline className={style.step} />} {completed ? (
<IoCheckmarkCircle className={style.step} style={{ color: 'green' }} />
) : error ? (
<IoCloseCircle className={style.step} style={{ color: 'red' }} />
) : (
<IoRadioButtonOffOutline className={style.step} />
)}
<span className={style.title}>{title}</span> <span className={style.title}>{title}</span>
{error && <IoClose className={style.errorIcon} />}
</div> </div>
{!collapsed && ( {!collapsed && (
<> <>
@@ -515,11 +515,11 @@ export async function uploadSheetClientFile(req, res) {
* @method GET * @method GET
*/ */
export async function sheetAuthUrl(req, res) { export async function sheetAuthUrl(req, res) {
const authUrl = await Sheet.openAuthServer(); try {
if (!authUrl) { const authUrl = await Sheet.openAuthServer();
res.status(500).send('Unable to start auth server');
} else {
res.status(200).send(authUrl); res.status(200).send(authUrl);
} catch (error) {
res.status(500).send({ message: error.toString() });
} }
} }
@@ -529,5 +529,10 @@ export async function sheetAuthUrl(req, res) {
*/ */
export const getSheetState = async (req, res) => { export const getSheetState = async (req, res) => {
const { id, worksheet } = req.body; const { id, worksheet } = req.body;
res.status(200).send(await Sheet.getSheetState(id, worksheet)); try {
const state = await Sheet.getSheetState(id, worksheet);
res.status(200).send(state);
} catch (error) {
res.status(500).send({ message: error.toString() });
}
}; };
+4 -8
View File
@@ -54,14 +54,10 @@ class sheet {
state.auth = sheet.client !== null; state.auth = sheet.client !== null;
if (id != '' && state.auth) { if (id != '' && state.auth) {
const spreadsheets = await sheets({ version: 'v4', auth: sheet.client }) const spreadsheets = await sheets({ version: 'v4', auth: sheet.client }).spreadsheets.get({
.spreadsheets.get({ spreadsheetId: id,
spreadsheetId: id, includeGridData: false,
includeGridData: false, });
})
.catch((err) => {
logger.error(LogOrigin.Server, `Sheet: faild to load sheet ${err}`);
});
if (!spreadsheets || spreadsheets.status != 200) { if (!spreadsheets || spreadsheets.status != 200) {
return state; return state;
} }