parent
84ebc333ef
commit
dbb90f07de
1 changed files with 145 additions and 0 deletions
@ -0,0 +1,145 @@ |
|||||||
|
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 Link from './Link'; |
||||||
|
import List from './List'; |
||||||
|
import periodicFetch from '../lib/fetchers/periodicFetch'; |
||||||
|
import { BodyText } from './Text'; |
||||||
|
import useProtect from '../hooks/useProtect'; |
||||||
|
import useProtectedState from '../hooks/useProtectedState'; |
||||||
|
|
||||||
|
type AnvilJobs = { |
||||||
|
[jobUUID: string]: { |
||||||
|
jobCommand: string; |
||||||
|
jobName: string; |
||||||
|
jobProgress: number; |
||||||
|
jobUUID: string; |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
type JobSummaryOptionalPropsWithDefault = { |
||||||
|
openInitially?: boolean; |
||||||
|
}; |
||||||
|
|
||||||
|
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<JobSummaryOptionalPropsWithDefault> & |
||||||
|
JobSummaryOptionalPropsWithoutDefault = { |
||||||
|
onFetchSuccessAppend: undefined, |
||||||
|
openInitially: false, |
||||||
|
}; |
||||||
|
|
||||||
|
const JobSummary = forwardRef<JobSummaryForwardedRefContent, JobSummaryProps>( |
||||||
|
( |
||||||
|
{ |
||||||
|
onFetchSuccessAppend, |
||||||
|
openInitially = JOB_SUMMARY_DEFAULT_PROPS.openInitially, |
||||||
|
}, |
||||||
|
ref, |
||||||
|
) => { |
||||||
|
const { protect } = useProtect(); |
||||||
|
|
||||||
|
const [anvilJobs, setAnvilJobs] = useProtectedState<AnvilJobs>({}, protect); |
||||||
|
const [isOpenJobSummary, setIsOpenJobSummary] = |
||||||
|
useState<boolean>(openInitially); |
||||||
|
const [menuAnchorElement, setMenuAnchorElement] = useState< |
||||||
|
HTMLElement | undefined |
||||||
|
>(); |
||||||
|
|
||||||
|
periodicFetch<AnvilJobs>(`${API_BASE_URL}/job`, { |
||||||
|
onError: () => { |
||||||
|
setAnvilJobs({}); |
||||||
|
}, |
||||||
|
onSuccess: (rawAnvilJobs) => { |
||||||
|
setAnvilJobs(rawAnvilJobs); |
||||||
|
|
||||||
|
onFetchSuccessAppend?.call(null, rawAnvilJobs); |
||||||
|
}, |
||||||
|
}); |
||||||
|
|
||||||
|
useImperativeHandle( |
||||||
|
ref, |
||||||
|
() => ({ |
||||||
|
setAnchor: (value) => setMenuAnchorElement(value), |
||||||
|
setOpen: (value) => setIsOpenJobSummary(value), |
||||||
|
}), |
||||||
|
[], |
||||||
|
); |
||||||
|
|
||||||
|
const jobList = useMemo( |
||||||
|
() => ( |
||||||
|
<FlexBox> |
||||||
|
<List |
||||||
|
scroll |
||||||
|
listEmpty="No currently running and recently completed jobs." |
||||||
|
listItems={anvilJobs} |
||||||
|
listProps={{ |
||||||
|
sx: { maxHeight: JOB_LIST_LENGTH, width: JOB_LIST_LENGTH }, |
||||||
|
}} |
||||||
|
renderListItem={(jobUUID, { jobName, jobProgress }) => ( |
||||||
|
<FlexBox sm="row" sx={{ width: '97%' }} xs="column"> |
||||||
|
<FlexBox spacing={0} sx={{ width: 'inherit' }}> |
||||||
|
<BodyText |
||||||
|
sx={{ |
||||||
|
overflowX: 'hidden', |
||||||
|
textOverflow: 'ellipsis', |
||||||
|
whiteSpace: 'nowrap', |
||||||
|
}} |
||||||
|
> |
||||||
|
{jobName} |
||||||
|
</BodyText> |
||||||
|
<ProgressBar progressPercentage={jobProgress} /> |
||||||
|
</FlexBox> |
||||||
|
</FlexBox> |
||||||
|
)} |
||||||
|
/> |
||||||
|
<Link href="cgi-bin/striker?jobs=true">More details</Link> |
||||||
|
</FlexBox> |
||||||
|
), |
||||||
|
[anvilJobs], |
||||||
|
); |
||||||
|
const jobSummary = useMemo( |
||||||
|
() => ( |
||||||
|
<Menu |
||||||
|
anchorEl={menuAnchorElement} |
||||||
|
MenuListProps={{ sx: { padding: '.8em 1.6em' } }} |
||||||
|
onClose={() => { |
||||||
|
setIsOpenJobSummary(false); |
||||||
|
setMenuAnchorElement(undefined); |
||||||
|
}} |
||||||
|
open={isOpenJobSummary} |
||||||
|
variant="menu" |
||||||
|
> |
||||||
|
{jobList} |
||||||
|
</Menu> |
||||||
|
), |
||||||
|
[isOpenJobSummary, jobList, menuAnchorElement], |
||||||
|
); |
||||||
|
|
||||||
|
return jobSummary; |
||||||
|
}, |
||||||
|
); |
||||||
|
|
||||||
|
JobSummary.defaultProps = JOB_SUMMARY_DEFAULT_PROPS; |
||||||
|
JobSummary.displayName = 'JobSummary'; |
||||||
|
|
||||||
|
export type { JobSummaryForwardedRefContent, JobSummaryProps }; |
||||||
|
|
||||||
|
export default JobSummary; |
Loading…
Reference in new issue