refactor: move fetching to react query

This commit is contained in:
Carlos Valente
2023-12-15 10:49:52 +01:00
parent 884947374d
commit 95d7b61529
6 changed files with 101 additions and 66 deletions
@@ -9,6 +9,8 @@ export const HTTP_SETTINGS = ['httpSettings'];
export const APP_SETTINGS = ['appSettings']; export const APP_SETTINGS = ['appSettings'];
export const VIEW_SETTINGS = ['viewSettings']; export const VIEW_SETTINGS = ['viewSettings'];
export const RUNTIME = ['runtimeStore']; export const RUNTIME = ['runtimeStore'];
export const SHEET = ['sheet'];
export const SHEET_STATE = ['sheetState'];
const location = window.location; const location = window.location;
const socketProtocol = location.protocol === 'https:' ? 'wss' : 'ws'; const socketProtocol = location.protocol === 'https:' ? 'wss' : 'ws';
+1 -1
View File
@@ -302,7 +302,7 @@ export async function postSheetSettings(data: GoogleSheet): Promise<GoogleSheet>
* @description HTTP request to retrieve google sheets state * @description HTTP request to retrieve google sheets state
* @return {Promise} * @return {Promise}
*/ */
export async function getSheetstate(): Promise<GoogleSheetState> { export async function getSheetState(): Promise<GoogleSheetState> {
const res = await axios.get(`${ontimeURL}/sheet-state`); const res = await axios.get(`${ontimeURL}/sheet-state`);
return res.data; return res.data;
} }
@@ -0,0 +1,21 @@
import { useQuery } from '@tanstack/react-query';
import { queryRefetchIntervalSlow } from '../../ontimeConfig';
import { SHEET } from '../api/apiConstants';
import { getSheetSettings } from '../api/ontimeApi';
const sheetPlaceholder = { worksheet: null, id: null };
export default function useSheet() {
const { data, status, isFetching, isError, refetch } = useQuery({
queryKey: SHEET,
queryFn: getSheetSettings,
placeholderData: sheetPlaceholder,
retry: 5,
retryDelay: (attempt) => attempt * 2500,
refetchInterval: queryRefetchIntervalSlow,
networkMode: 'always',
});
return { data, status, isFetching, isError, refetch };
}
@@ -0,0 +1,16 @@
import { useQuery } from '@tanstack/react-query';
import { SHEET_STATE } from '../api/apiConstants';
import { getSheetState } from '../api/ontimeApi';
export default function useSheetState() {
const { data, status, isFetching, isError, refetch } = useQuery({
queryKey: SHEET_STATE,
queryFn: getSheetState,
placeholderData: null,
enabled: false,
networkMode: 'always',
});
return { data, status, isFetching, isError, refetch };
}
@@ -18,20 +18,20 @@ import { IoArrowUpCircleOutline } from '@react-icons/all-files/io5/IoArrowUpCirc
import { IoCheckmarkCircleOutline } from '@react-icons/all-files/io5/IoCheckmarkCircleOutline'; import { IoCheckmarkCircleOutline } from '@react-icons/all-files/io5/IoCheckmarkCircleOutline';
import { IoCloseCircleOutline } from '@react-icons/all-files/io5/IoCloseCircleOutline'; import { IoCloseCircleOutline } from '@react-icons/all-files/io5/IoCloseCircleOutline';
import { useQueryClient } from '@tanstack/react-query'; import { useQueryClient } from '@tanstack/react-query';
import { GoogleSheetState, OntimeRundown, ProjectData, UserFields } from 'ontime-types'; import { OntimeRundown, ProjectData, UserFields } from 'ontime-types';
import { PROJECT_DATA, RUNDOWN, USERFIELDS } from '../../../common/api/apiConstants'; import { PROJECT_DATA, RUNDOWN, USERFIELDS } from '../../../common/api/apiConstants';
import { maybeAxiosError } from '../../../common/api/apiUtils'; import { maybeAxiosError } from '../../../common/api/apiUtils';
import { import {
getSheetsAuthUrl, getSheetsAuthUrl,
getSheetSettings,
getSheetstate,
patchData, patchData,
postPreviewSheet, postPreviewSheet,
postPushSheet, postPushSheet,
postSheetSettings, postSheetSettings,
uploadSheetClientFile, uploadSheetClientFile,
} from '../../../common/api/ontimeApi'; } from '../../../common/api/ontimeApi';
import useSheet from '../../../common/hooks-query/useSheet';
import useSheetState from '../../../common/hooks-query/useSheetState';
import { projectDataPlaceholder } from '../../../common/models/ProjectData'; import { projectDataPlaceholder } from '../../../common/models/ProjectData';
import { userFieldsPlaceholder } from '../../../common/models/UserFields'; import { userFieldsPlaceholder } from '../../../common/models/UserFields';
import PreviewExcel from '../upload-modal/preview/PreviewExcel'; import PreviewExcel from '../upload-modal/preview/PreviewExcel';
@@ -44,22 +44,15 @@ interface SheetsModalProps {
export default function SheetsModal(props: SheetsModalProps) { export default function SheetsModal(props: SheetsModalProps) {
const { isOpen, onClose } = props; const { isOpen, onClose } = props;
const fileInputRef = useRef<HTMLInputElement>(null); const queryClient = useQueryClient();
const { data } = useSheet();
const { data: sheetState, refetch } = useSheetState();
const [rundown, setRundown] = useState<OntimeRundown | null>(null); const [rundown, setRundown] = useState<OntimeRundown | null>(null);
const [userFields, setUserFields] = useState<UserFields | null>(null); const [userFields, setUserFields] = useState<UserFields | null>(null);
const [project, setProject] = useState<ProjectData | null>(null); const [project, setProject] = useState<ProjectData | null>(null);
const [sheetState, setSheetState] = useState<GoogleSheetState>({ const fileInputRef = useRef<HTMLInputElement>(null);
secret: false,
auth: false,
id: false,
worksheet: false,
worksheetOptions: [],
});
const queryClient = useQueryClient();
const sheetid = useRef<HTMLInputElement>(null); const sheetid = useRef<HTMLInputElement>(null);
const worksheet = useRef<HTMLSelectElement>(null); const worksheet = useRef<HTMLSelectElement>(null);
@@ -69,46 +62,54 @@ export default function SheetsModal(props: SheetsModalProps) {
setUserFields(null); setUserFields(null);
onClose(); onClose();
}; };
const handleClick = () => { const handleClick = () => {
fileInputRef.current?.click(); fileInputRef.current?.click();
}; };
const handleFile = async (event: ChangeEvent<HTMLInputElement>) => { const handleFile = async (event: ChangeEvent<HTMLInputElement>) => {
const selectedFile = event?.target?.files?.[0]; if (!event.target.files?.length) {
if (selectedFile) { return;
await uploadSheetClientFile(selectedFile).catch((err) => {
console.error(err); //TODO: how to show this to the user
});
_onChange();
} }
const selectedFile = event.target.files[0];
try {
await uploadSheetClientFile(selectedFile);
} catch (error) {
// TODO: show this in the modal
console.error(error);
}
_onChange();
}; };
const _onChange = async () => { const _onChange = () => refetch();
setSheetState(await getSheetstate());
};
useEffect(() => { useEffect(() => {
getSheetSettings().then((data) => { if (!data) {
if (data.id == '') { return;
return; }
}
console.log(worksheet.current?.value);
if (
sheetid.current?.value != data.id ||
(worksheet.current?.value != data.worksheet && worksheet.current?.value)
) {
_onChange();
if (sheetid.current) {
sheetid.current.value = data.id;
}
if (worksheet.current) {
worksheet.current.value = data.worksheet;
}
}
});
});
const handelSave = () => { const selectedSheetIdChanged = sheetid.current?.value !== data.id;
const selectedWorksheetChanged = worksheet.current?.value !== data.worksheet && worksheet.current?.value;
if (selectedSheetIdChanged || selectedWorksheetChanged) {
_onChange();
if (sheetid.current) {
sheetid.current.value = data.id;
}
if (worksheet.current) {
worksheet.current.value = data.worksheet;
}
}
}, [data]);
useEffect(() => {
return () => {
// Alex: This function will be run when the component unmounts
console.log('Component is unmounting');
};
}, []);
const handleSave = () => {
postSheetSettings({ id: sheetid.current?.value ?? '', worksheet: worksheet.current?.value ?? '' }).then((data) => { postSheetSettings({ id: sheetid.current?.value ?? '', worksheet: worksheet.current?.value ?? '' }).then((data) => {
_onChange(); _onChange();
if (sheetid.current) { if (sheetid.current) {
@@ -122,7 +123,7 @@ export default function SheetsModal(props: SheetsModalProps) {
const handleAuthenticate = () => { const handleAuthenticate = () => {
getSheetsAuthUrl().then((data) => { getSheetsAuthUrl().then((data) => {
if (data != 'bad') { if (data !== 'bad') {
window.open(data, '_blank', 'noreferrer'); window.open(data, '_blank', 'noreferrer');
//TODO: can we detect when this window is closed //TODO: can we detect when this window is closed
} }
@@ -199,22 +200,18 @@ export default function SheetsModal(props: SheetsModalProps) {
accept='.json' accept='.json'
data-testid='file-input' data-testid='file-input'
/> />
<div>Need to add some help here</div>
<br />
<div> <div>
<Button onClick={handleClick}>Upload Client Secrect</Button> <Button onClick={handleClick}>Upload Client Secret</Button>
{sheetState.secret ? 'have good secret' : 'no or bad secret'} {sheetState?.secret ? 'have good secret' : 'no or bad secret'}
</div> </div>
<br /> <div style={sheetState?.secret ? {} : { display: 'none' }}>
<div style={sheetState.secret ? {} : { display: 'none' }}>
<Button variant='ontime-filled' padding='0 2em' onClick={handleAuthenticate}> <Button variant='ontime-filled' padding='0 2em' onClick={handleAuthenticate}>
Authenticate Authenticate
</Button> </Button>
{sheetState.auth ? 'You are authenticated' : 'You are not authenticated'} {sheetState?.auth ? 'You are authenticated' : 'You are not authenticated'}
</div> </div>
<br /> <div style={sheetState?.auth ? {} : { display: 'none' }}>
<div style={sheetState.auth ? {} : { display: 'none' }}> <label htmlFor='sheetid'>Sheet ID</label>
<label htmlFor='sheetid'>Sheet ID </label>
<InputGroup size='sm'> <InputGroup size='sm'>
<Input <Input
type='text' type='text'
@@ -225,15 +222,14 @@ export default function SheetsModal(props: SheetsModalProps) {
variant='ontime-filled-on-light' variant='ontime-filled-on-light'
/> />
<InputRightAddon> <InputRightAddon>
{sheetState.id ? <IoCheckmarkCircleOutline color='green' /> : <IoCloseCircleOutline color='red' />} {sheetState?.id ? <IoCheckmarkCircleOutline color='green' /> : <IoCloseCircleOutline color='red' />}
</InputRightAddon> </InputRightAddon>
</InputGroup> </InputGroup>
</div> </div>
<br /> <div style={sheetState?.id ? {} : { display: 'none' }}>
<div style={sheetState.id ? {} : { display: 'none' }}>
<label htmlFor='worksheet'>Worksheet </label> <label htmlFor='worksheet'>Worksheet </label>
<Select ref={worksheet} size='sm' id='worksheet'> <Select ref={worksheet} size='sm' id='worksheet'>
{sheetState.worksheetOptions.map((value) => ( {sheetState?.worksheetOptions?.map((value) => (
<option key={value} value={value}> <option key={value} value={value}>
{value} {value}
</option> </option>
@@ -241,9 +237,9 @@ export default function SheetsModal(props: SheetsModalProps) {
</Select> </Select>
</div> </div>
<br /> <br />
<div style={sheetState.worksheet ? {} : { display: 'none' }}> <div style={sheetState?.worksheet ? {} : { display: 'none' }}>
<Button <Button
disabled={!sheetState.worksheet} disabled={!sheetState?.worksheet}
variant='ontime-subtle-on-light' variant='ontime-subtle-on-light'
padding='0 2em' padding='0 2em'
onClick={handlePullData} onClick={handlePullData}
@@ -252,7 +248,7 @@ export default function SheetsModal(props: SheetsModalProps) {
Pull Rundown Pull Rundown
</Button> </Button>
<Button <Button
disabled={!sheetState.worksheet} disabled={!sheetState?.worksheet}
variant='ontime-subtle-on-light' variant='ontime-subtle-on-light'
padding='0 2em' padding='0 2em'
onClick={handlePushData} onClick={handlePushData}
@@ -267,7 +263,7 @@ export default function SheetsModal(props: SheetsModalProps) {
<ModalFooter> <ModalFooter>
<Button variant='ontime-ghost-on-light'>Reset</Button> <Button variant='ontime-ghost-on-light'>Reset</Button>
{!rundown && ( {!rundown && (
<Button variant='ontime-filled' padding='0 2em' onClick={handelSave}> <Button variant='ontime-filled' padding='0 2em' onClick={handleSave}>
Save Save
</Button> </Button>
)} )}
@@ -1,6 +1,6 @@
export type GoogleSheet = { export type GoogleSheet = {
worksheet: string; worksheet: string | null;
id: string; id: string | null;
}; };
export type GoogleSheetState = { export type GoogleSheetState = {
@@ -9,4 +9,4 @@ export type GoogleSheetState = {
id: boolean; id: boolean;
worksheet: boolean; worksheet: boolean;
worksheetOptions: string[]; worksheetOptions: string[];
}; } | null;