import { Menu } from '@mui/material'; import { forwardRef, useImperativeHandle, useMemo, useState } from 'react'; import API_BASE_URL from '../lib/consts/API_BASE_URL'; import { ProgressBar } from './Bars'; import FlexBox from './FlexBox'; import List from './List'; import periodicFetch from '../lib/fetchers/periodicFetch'; import { BodyText } from './Text'; import useProtectedState from '../hooks/useProtectedState'; type AnvilJobs = { [jobUUID: string]: { jobCommand: string; jobName: string; jobProgress: number; jobUUID: string; }; }; type JobSummaryOptionalPropsWithDefault = { openInitially?: boolean; refreshInterval?: number; }; type JobSummaryOptionalPropsWithoutDefault = { onFetchSuccessAppend?: (data: AnvilJobs) => void; }; type JobSummaryOptionalProps = JobSummaryOptionalPropsWithDefault & JobSummaryOptionalPropsWithoutDefault; type JobSummaryProps = JobSummaryOptionalProps; type JobSummaryForwardedRefContent = { setAnchor?: (element: HTMLElement | undefined) => void; setOpen?: (value: boolean) => void; }; const JOB_LIST_LENGTH = '20em'; const JOB_SUMMARY_DEFAULT_PROPS: Required & JobSummaryOptionalPropsWithoutDefault = { onFetchSuccessAppend: undefined, openInitially: false, refreshInterval: 10000, }; const JobSummary = forwardRef( ( { onFetchSuccessAppend, openInitially = JOB_SUMMARY_DEFAULT_PROPS.openInitially, refreshInterval = JOB_SUMMARY_DEFAULT_PROPS.refreshInterval, }, ref, ) => { const [anvilJobs, setAnvilJobs] = useProtectedState({}); const [isOpenJobSummary, setIsOpenJobSummary] = useState(openInitially); const [menuAnchorElement, setMenuAnchorElement] = useState< HTMLElement | undefined >(); const loadTimestamp = useMemo(() => Math.floor(Date.now() / 1000), []); periodicFetch(`${API_BASE_URL}/job?start=${loadTimestamp}`, { onError: () => { setAnvilJobs({}); }, onSuccess: (rawAnvilJobs) => { setAnvilJobs(rawAnvilJobs); onFetchSuccessAppend?.call(null, rawAnvilJobs); }, refreshInterval, }); useImperativeHandle( ref, () => ({ setAnchor: (value) => setMenuAnchorElement(value), setOpen: (value) => setIsOpenJobSummary(value), }), [], ); const jobList = useMemo( () => ( ( {jobName} )} /> ), [anvilJobs], ); const jobSummary = useMemo( () => ( { setIsOpenJobSummary(false); setMenuAnchorElement(undefined); }} open={isOpenJobSummary} variant="menu" > {jobList} ), [isOpenJobSummary, jobList, menuAnchorElement], ); return jobSummary; }, ); JobSummary.defaultProps = JOB_SUMMARY_DEFAULT_PROPS; JobSummary.displayName = 'JobSummary'; export type { JobSummaryForwardedRefContent, JobSummaryProps }; export default JobSummary;