diff --git a/app/components/TumourSummaryEdit/index.tsx b/app/components/TumourSummaryEdit/index.tsx index 16383ecfe..9f22a8ca8 100644 --- a/app/components/TumourSummaryEdit/index.tsx +++ b/app/components/TumourSummaryEdit/index.tsx @@ -28,6 +28,7 @@ import { } from '@/common'; import snackbar from '@/services/SnackbarUtils'; import { getMicbSiteIntegrationStatusLabel } from '@/utils/getMicbSiteIntegrationStatusLabel'; +import { useQueryClient } from 'react-query'; const MICB_SITE_STEPS = { yes: 'no', @@ -83,11 +84,16 @@ const TumourSummaryEdit = ({ const [tmburMutDirty, setTmburMutDirty] = useState(false); const [msiDirty, setMsiDirty] = useState(false); const [isApiCalling, setIsApiCalling] = useState(false); + const queryClient = useQueryClient(); useEffect(() => { if (microbial) { // Note: filter out any placeholder 'none's, it gives a false positive to the front-end code - setNewMicrobialData(cloneDeep(microbial).filter(({ species }) => species.toLowerCase() !== 'none')); + setNewMicrobialData( + cloneDeep(microbial).filter( + ({ species }) => species.toLowerCase() !== 'none' + ) + ); } }, [microbial]); @@ -147,7 +153,7 @@ const TumourSummaryEdit = ({ }); } }, [msi]); - + const handleReportChange = useCallback((event: React.ChangeEvent) => { const { target: { value, name } } = event; setNewReportData((prevVal) => ({ ...prevVal, [name]: value })); @@ -360,6 +366,27 @@ const TumourSummaryEdit = ({ } snackbar.success('Successfully updated Tumour Summary'); + queryClient.refetchQueries({ + queryKey: [`/reports/${report.ident}/summary/microbial`] + }); + queryClient.refetchQueries({ + queryKey: [`/reports/${report.ident}/comparators`] + }); + queryClient.refetchQueries({ + queryKey: [`/reports/${report.ident}/mutation-signatures`] + }); + queryClient.refetchQueries({ + queryKey: [`/reports/${report.ident}/mutation-burden`] + }); + queryClient.refetchQueries({ + queryKey: [`/reports/${report.ident}/immune-cell-types`] + }); + queryClient.refetchQueries({ + queryKey: [`/reports/${report.ident}/msi`] + }); + queryClient.refetchQueries({ + queryKey: [`/reports/${report.ident}/tmbur-mutation-burden`] + }); onEditClose( true, microbialDirty ? microbialResp : null, @@ -393,6 +420,7 @@ const TumourSummaryEdit = ({ newMsiData, isSigned, newMicrobialData, + queryClient, microbial, report?.ident, tCellCd8?.ident, diff --git a/app/views/ReportView/components/Appendices/types.d.ts b/app/views/ReportView/components/Appendices/types.d.ts index f7e9d3663..b239ad8a3 100644 --- a/app/views/ReportView/components/Appendices/types.d.ts +++ b/app/views/ReportView/components/Appendices/types.d.ts @@ -28,6 +28,7 @@ type TcgaType = { type ComparatorType = { analysisRole: string; createdAt: string; + deletedAt: string; description: string | null; ident: string; name: string; diff --git a/app/views/ReportView/components/GenomicSummary/defaultStates.ts b/app/views/ReportView/components/GenomicSummary/defaultStates.ts index 0f3728096..92a0f7985 100644 --- a/app/views/ReportView/components/GenomicSummary/defaultStates.ts +++ b/app/views/ReportView/components/GenomicSummary/defaultStates.ts @@ -7,6 +7,7 @@ const defaultMutationBurden: MutationBurdenType = { ident: '', updatedAt: null, createdAt: null, + deletedAt: null, codingIndelPercentile: null, codingIndelsCount: null, codingSnvCount: null, @@ -27,8 +28,10 @@ const defaultTmbur: TmburType = { ident: '', updatedAt: null, createdAt: null, + deletedAt: null, adjustedTmb: null, adjustedTmbComment: null, + displayName: '', cdsBasesIn1To22AndXAndY: '', cdsIndels: 0, cdsIndelTmb: 0, @@ -58,6 +61,7 @@ const defaultMsi: MsiType = { ident: '', updatedAt: null, createdAt: null, + deletedAt: null, score: null, kbCategory: null, germline: null, @@ -68,6 +72,7 @@ const defaultImmune: ImmuneType = { ident: '', updatedAt: null, createdAt: null, + deletedAt: null, cellType: null, kbCategory: null, percentile: null, @@ -82,6 +87,7 @@ const defaultComparator: ComparatorType = { ident: '', updatedAt: null, createdAt: null, + deletedAt: null, analysisRole: '', description: null, name: '', diff --git a/app/views/ReportView/components/GenomicSummary/index.tsx b/app/views/ReportView/components/GenomicSummary/index.tsx index e2a747d25..458f58b31 100644 --- a/app/views/ReportView/components/GenomicSummary/index.tsx +++ b/app/views/ReportView/components/GenomicSummary/index.tsx @@ -30,6 +30,7 @@ import TumourSummary from '../TumourSummary'; import { defaultComparator, defaultImmune, defaultMsi, defaultMutationBurden, defaultTmbur, } from './defaultStates'; +import { useQuery } from 'react-query'; type GenomicSummaryProps = { loadedDispatch?: SummaryProps['loadedDispatch']; @@ -56,79 +57,168 @@ const GenomicSummary = ({ const [primaryBurden, setPrimaryBurden] = useState(defaultMutationBurden); const [msi, setMsi] = useState(defaultMsi); const [tmburMutBur, setTmburMutBur] = useState(defaultTmbur); - const [microbial, setMicrobial] = useState([]); const [tCellCd8, setTCellCd8] = useState(defaultImmune); const [primaryComparator, setPrimaryComparator] = useState(defaultComparator); const classNamePrefix = printVersion ? 'genomic-summary--print' : 'genomic-summary'; - useEffect(() => { - if (report) { - const getData = async () => { - try { - const apiCalls = new ApiCallSet([ - api.get(`/reports/${report.ident}/summary/microbial`), - api.get(`/reports/${report.ident}/comparators`), - api.get(`/reports/${report.ident}/mutation-signatures`), - api.get(`/reports/${report.ident}/mutation-burden`), - api.get(`/reports/${report.ident}/immune-cell-types`), - api.get(`/reports/${report.ident}/msi`), - ]); - - const [ - microbialResp, - comparatorsResp, - signaturesResp, - burdenResp, - immuneResp, - msiResp, - ] = await apiCalls.request() as [ - MicrobialType[], - ComparatorType[], - MutationSignatureType[], - MutationBurdenType[], - ImmuneType[], - MsiType[], - ]; - - try { - const tmburResp = await api.get(`/reports/${report.ident}/tmbur-mutation-burden`).request(); - if (tmburResp) { - setTmburMutBur(tmburResp); - } - } catch (e) { - // tmbur does not exist in records before this implementation, and no backfill will be done on the backend, silent fail this - // eslint-disable-next-line no-console - console.error('tmbur-mutation-burden call error', e?.message); - } - - setPrimaryComparator(comparatorsResp.find(({ analysisRole }) => analysisRole === 'mutation burden (primary)')); - setPrimaryBurden(burdenResp.find((entry: Record) => entry.role === 'primary')); - setTCellCd8(immuneResp.find(({ cellType }) => cellType === 'T cells CD8')); - setSignatures(signaturesResp); - - if (microbialResp) { - setMicrobial(microbialResp); - } - - if (msiResp.length) { - setMsi(msiResp[0]); - } - - if (loadedDispatch) { - loadedDispatch({ type: 'summary-genomic' }); - } - } catch (err) { - snackbar.error(`Network error: ${err?.message ?? err}`); - } finally { - setIsLoading(false); + const {data: microbialData, isError: microbialError} = useQuery( + `/reports/${report.ident}/summary/microbial`, + async ({ queryKey: [route] }) => await api.get(route).request(), + { + staleTime: Infinity, + enabled: Boolean(report), + select: (response) => { + return response; + }, + onError: () => { + // eslint-disable-next-line no-console + console.error('microbial call error'); + }, + }, + ); + + const {data: primaryComparatorData, isError: primaryComparatorError} = useQuery( + `/reports/${report.ident}/comparators`, + async ({ queryKey: [route] }) => await api.get(route).request(), + { + staleTime: Infinity, + enabled: Boolean(report), + select: (response) => { + return response.find(({ analysisRole }) => analysisRole === 'mutation burden (primary)'); + }, + onError: () => { + // eslint-disable-next-line no-console + console.error('comparators call error'); + }, + }, + ); + + const {data: signaturesData, isError: signaturesError} = useQuery( + `/reports/${report.ident}/mutation-signatures`, + async ({ queryKey: [route] }) => await api.get(route).request(), + { + staleTime: Infinity, + enabled: Boolean(report), + select: (response) => { + return response; + }, + onError: () => { + // eslint-disable-next-line no-console + console.error('mutation signatures call error'); + }, + }, + ); + + const {data: tCellCd8Data, isError: tCellCd8Error} = useQuery( + `/reports/${report.ident}/immune-cell-types`, + async ({ queryKey: [route] }) => await api.get(route).request(), + { + staleTime: Infinity, + enabled: Boolean(report), + select: (response) => { + return response.find(({ cellType }) => cellType === 'T cells CD8'); + }, + onError: () => { + // eslint-disable-next-line no-console + console.error('immune cell types call error'); + }, + }, + ); + + const {data: primaryBurdenData, isError: primaryBurdenError} = useQuery( + `/reports/${report.ident}/mutation-burden`, + async ({ queryKey: [route] }) => await api.get(route).request(), + { + staleTime: Infinity, + enabled: Boolean(report), + select: (response) => { + return response.find((entry: Record) => entry.role === 'primary'); + }, + onError: () => { + // eslint-disable-next-line no-console + console.error('mutation burden call error'); + }, + }, + ); + + const {data: msiData, isError: msiError} = useQuery( + `/reports/${report.ident}/msi`, + async ({ queryKey: [route] }) => await api.get(route).request(), + { + staleTime: Infinity, + enabled: Boolean(report), + select: (response) => { + if (response.length) { + return response[0]; + } else { + return null; } - }; + }, + onError: () => { + // eslint-disable-next-line no-console + console.error('msi call error'); + }, + }, + ); - getData(); + const {data: tmburMutBurData, isError: tmburMutBurError} = useQuery( + `/reports/${report.ident}/tmbur-mutation-burden`, + async ({ queryKey: [route] }) => await api.get(route).request(), + { + staleTime: Infinity, + enabled: Boolean(report), + select: (response) => { + return response; + }, + onError: () => { + // eslint-disable-next-line no-console + console.error('tmbur mutation burden call error'); + }, + }, + ); + + useEffect(() => { + if (report) { + if (microbialData) { + setMicrobial(microbialData); + } + if (primaryComparatorData) { + setPrimaryComparator(primaryComparatorData); + } + if (signaturesData) { + setSignatures(signaturesData); + } + if (tCellCd8Data) { + setTCellCd8(tCellCd8Data); + } + if (primaryBurdenData) { + setPrimaryBurden(primaryBurdenData); + } + if (msiData) { + setMsi(msiData); + } + if (tmburMutBurData) { + setTmburMutBur(tmburMutBurData); + } + if (loadedDispatch) { + loadedDispatch({ type: 'summary-genomic' }); + } + setIsLoading(false); } - }, [loadedDispatch, report, setIsLoading, isPrint]); + }, [ + report, + microbialData, + primaryComparatorData, + signaturesData, + tCellCd8Data, + primaryBurdenData, + msiData, + tmburMutBurData, + loadedDispatch, + setIsLoading, + ]); useEffect(() => { if (report) { @@ -298,7 +388,7 @@ const GenomicSummary = ({ } }, [setReport]); - if (isLoading || !report || !tumourSummary) { + if (isLoading || !report || !tumourSummary || microbialError || primaryComparatorError || signaturesError || primaryBurdenError || tCellCd8Error || msiError || tmburMutBurError) { return null; }