frontend/app/BundleList/BundleInfoComponent.tsx (135 lines of code) (raw):

import React, { useEffect, useState } from "react"; import axios from "axios"; import { CircularProgress, Grid, makeStyles } from "@material-ui/core"; import { People } from "@material-ui/icons"; import CommissionIcon from "@guardian/pluto-headers/build/static/c.svg"; import ProjectIcon from "@guardian/pluto-headers/build/static/p.svg"; interface BundleInfoComponentProps { projectId: number; commissionId: number; bundleName: string; spacing?: 0 | 2 | 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10; maxWidth?: string; } interface PlutoCoreProject { id: number; projectTypeId: number; title: string; created: string; updated: string; user: string; workingGroupId: number; commissionId: number; status: string; productionOffice: string; } interface PlutoCoreCommission { id: number; title: string; status: string; owner: string; productionOffice: string; } const useStyles = makeStyles((theme) => ({ inlineIcon: { height: "16px", marginRight: "0.2em", verticalAlign: "middle", }, })); const BundleInfoComponent: React.FC<BundleInfoComponentProps> = (props) => { const [projectInfo, setProjectInfo] = useState<PlutoCoreProject | undefined>( undefined ); const [commissionInfo, setCommissionInfo] = useState< PlutoCoreCommission | undefined >(undefined); const [lastError, setLastError] = useState<string | undefined>(undefined); const [loading, setLoading] = useState<boolean>(true); const classes = useStyles(); const loadCommissionInfo = async () => { try { const response = await axios({ method: "get", url: `/pluto-core/api/pluto/commission/${props.commissionId}`, baseURL: `/`, }); response.data.hasOwnProperty("result") ? setCommissionInfo(response.data.result as PlutoCoreCommission) : setLastError("Commission data was not valid"); } catch (err) { console.error("Could not load commission data: ", err); setCommissionInfo(undefined); setLastError("Could not load commission data"); } }; const loadProjectInfo = async () => { try { const response = await axios({ method: "get", url: `/pluto-core/api/project/${props.projectId}`, baseURL: `/`, }); response.data.hasOwnProperty("result") ? setProjectInfo(response.data.result as PlutoCoreProject) : setLastError("Project data was not valid"); } catch (err) { console.error("Could not load project data: ", err); setProjectInfo(undefined); setLastError("Could not load project data"); } }; /** * set loading to false if both commission and project info have loaded, or if there is an error */ useEffect(() => { if ((projectInfo && commissionInfo) || lastError) { setLoading(false); } }, [projectInfo, commissionInfo, lastError]); /** * load in data on mount */ useEffect(() => { loadCommissionInfo(); loadProjectInfo(); }, []); /** * load in data on update */ useEffect(() => { loadProjectInfo(); }, [props.projectId]); useEffect(() => { loadCommissionInfo(); }, [props.commissionId]); return ( <Grid container spacing={props.spacing ?? 3} style={{ maxWidth: props.maxWidth }} > <Grid item xs={6} style={{ paddingBottom: 0 }}> {loading ? ( <CircularProgress style={{ width: "14px", height: "14px" }} /> ) : null} {commissionInfo ? ( <> <img src={CommissionIcon} alt="C" className={classes.inlineIcon} /> {commissionInfo.title} ({commissionInfo.productionOffice}) </> ) : null} </Grid> <Grid item xs={6} style={{ paddingBottom: 0 }}> {projectInfo ? ( <> <img src={ProjectIcon} alt="P" className={classes.inlineIcon} /> {projectInfo.title} ({projectInfo.productionOffice}) </> ) : null} </Grid> <Grid item xs={6} style={{ paddingBottom: 0 }}> <p style={{ fontStyle: "italic", padding: 0, margin: 0 }}> {props.bundleName} </p> </Grid> <Grid item xs={6} style={{ paddingBottom: 0 }}> {projectInfo?.user ? ( <> <People style={{ marginRight: "0.2em", verticalAlign: "middle" }} /> {projectInfo.user} </> ) : null} </Grid> </Grid> ); }; export default BundleInfoComponent;