diff --git a/apps/client/src/common/api/apiConstants.ts b/apps/client/src/common/api/apiConstants.ts index 4ad3a12f3..73730a789 100644 --- a/apps/client/src/common/api/apiConstants.ts +++ b/apps/client/src/common/api/apiConstants.ts @@ -9,6 +9,8 @@ export const HTTP_SETTINGS = ['httpSettings']; export const APP_SETTINGS = ['appSettings']; export const VIEW_SETTINGS = ['viewSettings']; export const RUNTIME = ['runtimeStore']; +export const SHEET = ['sheet']; +export const SHEET_STATE = ['sheetState']; const location = window.location; const socketProtocol = location.protocol === 'https:' ? 'wss' : 'ws'; diff --git a/apps/client/src/common/api/ontimeApi.ts b/apps/client/src/common/api/ontimeApi.ts index 53b4d5645..5ba416ea1 100644 --- a/apps/client/src/common/api/ontimeApi.ts +++ b/apps/client/src/common/api/ontimeApi.ts @@ -302,7 +302,7 @@ export async function postSheetSettings(data: GoogleSheet): Promise * @description HTTP request to retrieve google sheets state * @return {Promise} */ -export async function getSheetstate(): Promise { +export async function getSheetState(): Promise { const res = await axios.get(`${ontimeURL}/sheet-state`); return res.data; } diff --git a/apps/client/src/common/hooks-query/useSheet.ts b/apps/client/src/common/hooks-query/useSheet.ts new file mode 100644 index 000000000..3239e2ea4 --- /dev/null +++ b/apps/client/src/common/hooks-query/useSheet.ts @@ -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 }; +} diff --git a/apps/client/src/common/hooks-query/useSheetState.ts b/apps/client/src/common/hooks-query/useSheetState.ts new file mode 100644 index 000000000..c85a73190 --- /dev/null +++ b/apps/client/src/common/hooks-query/useSheetState.ts @@ -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 }; +} diff --git a/apps/client/src/features/modals/sheets-modal/SheetsModal.tsx b/apps/client/src/features/modals/sheets-modal/SheetsModal.tsx index 00240e197..1e3f806ad 100644 --- a/apps/client/src/features/modals/sheets-modal/SheetsModal.tsx +++ b/apps/client/src/features/modals/sheets-modal/SheetsModal.tsx @@ -18,20 +18,20 @@ import { IoArrowUpCircleOutline } from '@react-icons/all-files/io5/IoArrowUpCirc import { IoCheckmarkCircleOutline } from '@react-icons/all-files/io5/IoCheckmarkCircleOutline'; import { IoCloseCircleOutline } from '@react-icons/all-files/io5/IoCloseCircleOutline'; 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 { maybeAxiosError } from '../../../common/api/apiUtils'; import { getSheetsAuthUrl, - getSheetSettings, - getSheetstate, patchData, postPreviewSheet, postPushSheet, postSheetSettings, uploadSheetClientFile, } 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 { userFieldsPlaceholder } from '../../../common/models/UserFields'; import PreviewExcel from '../upload-modal/preview/PreviewExcel'; @@ -44,22 +44,15 @@ interface SheetsModalProps { export default function SheetsModal(props: SheetsModalProps) { const { isOpen, onClose } = props; - const fileInputRef = useRef(null); + const queryClient = useQueryClient(); + const { data } = useSheet(); + const { data: sheetState, refetch } = useSheetState(); const [rundown, setRundown] = useState(null); const [userFields, setUserFields] = useState(null); const [project, setProject] = useState(null); - const [sheetState, setSheetState] = useState({ - secret: false, - auth: false, - id: false, - worksheet: false, - worksheetOptions: [], - }); - - const queryClient = useQueryClient(); - + const fileInputRef = useRef(null); const sheetid = useRef(null); const worksheet = useRef(null); @@ -69,46 +62,54 @@ export default function SheetsModal(props: SheetsModalProps) { setUserFields(null); onClose(); }; + const handleClick = () => { fileInputRef.current?.click(); }; const handleFile = async (event: ChangeEvent) => { - const selectedFile = event?.target?.files?.[0]; - if (selectedFile) { - await uploadSheetClientFile(selectedFile).catch((err) => { - console.error(err); //TODO: how to show this to the user - }); - _onChange(); + if (!event.target.files?.length) { + return; } + + 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 () => { - setSheetState(await getSheetstate()); - }; + const _onChange = () => refetch(); useEffect(() => { - getSheetSettings().then((data) => { - if (data.id == '') { - 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; - } - } - }); - }); + if (!data) { + return; + } - 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) => { _onChange(); if (sheetid.current) { @@ -122,7 +123,7 @@ export default function SheetsModal(props: SheetsModalProps) { const handleAuthenticate = () => { getSheetsAuthUrl().then((data) => { - if (data != 'bad') { + if (data !== 'bad') { window.open(data, '_blank', 'noreferrer'); //TODO: can we detect when this window is closed } @@ -199,22 +200,18 @@ export default function SheetsModal(props: SheetsModalProps) { accept='.json' data-testid='file-input' /> -
Need to add some help here
-
- - {sheetState.secret ? 'have good secret' : 'no or bad secret'} + + {sheetState?.secret ? 'have good secret' : 'no or bad secret'}
-
-
+
- {sheetState.auth ? 'You are authenticated' : 'You are not authenticated'} + {sheetState?.auth ? 'You are authenticated' : 'You are not authenticated'}
-
-
- +
+ - {sheetState.id ? : } + {sheetState?.id ? : }
-
-
+

-
+
{!rundown && ( - )} diff --git a/packages/types/src/definitions/core/GoogleSheet.type.ts b/packages/types/src/definitions/core/GoogleSheet.type.ts index 58e664bbb..b6376eb74 100644 --- a/packages/types/src/definitions/core/GoogleSheet.type.ts +++ b/packages/types/src/definitions/core/GoogleSheet.type.ts @@ -1,6 +1,6 @@ export type GoogleSheet = { - worksheet: string; - id: string; + worksheet: string | null; + id: string | null; }; export type GoogleSheetState = { @@ -9,4 +9,4 @@ export type GoogleSheetState = { id: boolean; worksheet: boolean; worksheetOptions: string[]; -}; +} | null;