mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-06 07:53:54 +00:00
display errors in UI
This commit is contained in:
@@ -55,6 +55,14 @@ export default function SheetsModal(props: SheetsModalProps) {
|
||||
const sheetRef = useRef<HTMLInputElement>(null);
|
||||
const worksheetRef = useRef<HTMLSelectElement>(null);
|
||||
|
||||
const [errors, setErrors] = useState({
|
||||
clientSecret: '',
|
||||
authenticate: '',
|
||||
sheetId: '',
|
||||
worksheet: '',
|
||||
pullPush: '',
|
||||
});
|
||||
|
||||
const [sheetState, setState] = useState<SheetState>({
|
||||
secret: false,
|
||||
auth: false,
|
||||
@@ -63,10 +71,6 @@ export default function SheetsModal(props: SheetsModalProps) {
|
||||
worksheetOptions: [],
|
||||
});
|
||||
|
||||
const testId = async () => {
|
||||
setState(await getSheetState(sheetRef.current?.value ?? '', worksheetRef.current?.value ?? ''));
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setRundown(null);
|
||||
setProject(null);
|
||||
@@ -81,21 +85,37 @@ export default function SheetsModal(props: SheetsModalProps) {
|
||||
const updateSheetState = () => {
|
||||
const currentSheetId = sheetRef.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) {
|
||||
setErrors({ ...errors, clientSecret: 'Missing file' });
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedFile = event.target.files[0];
|
||||
try {
|
||||
await uploadSheetClientFile(selectedFile);
|
||||
} catch (error) {
|
||||
// TODO: show this in the modal
|
||||
console.error(error);
|
||||
}
|
||||
uploadSheetClientFile(selectedFile)
|
||||
.then(() => {
|
||||
setErrors({ ...errors, clientSecret: '' });
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.response.data.message) {
|
||||
setErrors({ ...errors, clientSecret: err.response.data.message });
|
||||
}
|
||||
});
|
||||
updateSheetState();
|
||||
};
|
||||
|
||||
@@ -106,12 +126,16 @@ export default function SheetsModal(props: SheetsModalProps) {
|
||||
}, [isOpen]);
|
||||
|
||||
const handleAuthenticate = () => {
|
||||
getSheetsAuthUrl().then((data) => {
|
||||
if (data !== 'bad') {
|
||||
getSheetsAuthUrl()
|
||||
.then((data) => {
|
||||
openLink(data);
|
||||
window.addEventListener('focus', () => updateSheetState(), { once: true });
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.response.data.message) {
|
||||
setErrors({ ...errors, authenticate: err.response.data.message });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handlePullData = () => {
|
||||
@@ -180,7 +204,12 @@ export default function SheetsModal(props: SheetsModalProps) {
|
||||
</Alert>
|
||||
{!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
|
||||
ref={fileInputRef}
|
||||
style={{ display: 'none' }}
|
||||
@@ -198,6 +227,7 @@ export default function SheetsModal(props: SheetsModalProps) {
|
||||
title='2 - Authenticate with Google'
|
||||
completed={Boolean(sheetState?.auth)}
|
||||
disabled={!sheetState?.secret}
|
||||
error={errors.authenticate}
|
||||
>
|
||||
<Button
|
||||
size='sm'
|
||||
@@ -209,7 +239,12 @@ export default function SheetsModal(props: SheetsModalProps) {
|
||||
</Button>
|
||||
</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>
|
||||
<Input
|
||||
type='text'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { PropsWithChildren, useEffect, useState } from 'react';
|
||||
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 style from './Step.module.scss';
|
||||
@@ -15,7 +15,7 @@ interface StepProps {
|
||||
export default function Step(props: PropsWithChildren<StepProps>) {
|
||||
const { title, disabled, completed, error, children } = props;
|
||||
const [collapsed, setCollapsed] = useState(disabled);
|
||||
|
||||
|
||||
const handleCollapse = () => setCollapsed((prev) => !prev);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -27,9 +27,14 @@ export default function Step(props: PropsWithChildren<StepProps>) {
|
||||
return (
|
||||
<div className={style.wrapper}>
|
||||
<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>
|
||||
{error && <IoClose className={style.errorIcon} />}
|
||||
</div>
|
||||
{!collapsed && (
|
||||
<>
|
||||
|
||||
@@ -515,11 +515,11 @@ export async function uploadSheetClientFile(req, res) {
|
||||
* @method GET
|
||||
*/
|
||||
export async function sheetAuthUrl(req, res) {
|
||||
const authUrl = await Sheet.openAuthServer();
|
||||
if (!authUrl) {
|
||||
res.status(500).send('Unable to start auth server');
|
||||
} else {
|
||||
try {
|
||||
const authUrl = await Sheet.openAuthServer();
|
||||
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) => {
|
||||
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() });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -54,14 +54,10 @@ class sheet {
|
||||
state.auth = sheet.client !== null;
|
||||
|
||||
if (id != '' && state.auth) {
|
||||
const spreadsheets = await sheets({ version: 'v4', auth: sheet.client })
|
||||
.spreadsheets.get({
|
||||
spreadsheetId: id,
|
||||
includeGridData: false,
|
||||
})
|
||||
.catch((err) => {
|
||||
logger.error(LogOrigin.Server, `Sheet: faild to load sheet ${err}`);
|
||||
});
|
||||
const spreadsheets = await sheets({ version: 'v4', auth: sheet.client }).spreadsheets.get({
|
||||
spreadsheetId: id,
|
||||
includeGridData: false,
|
||||
});
|
||||
if (!spreadsheets || spreadsheets.status != 200) {
|
||||
return state;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user