Skip to content

Commit

Permalink
Merge branch 'develop' into feat/DEVSU-2244-cd8t-percentile-visibilit…
Browse files Browse the repository at this point in the history
…y-toggle
  • Loading branch information
bnguyen-bcgsc authored Mar 28, 2024
2 parents 1db6b73 + df83ea3 commit 4f6af23
Show file tree
Hide file tree
Showing 11 changed files with 279 additions and 15 deletions.
8 changes: 6 additions & 2 deletions app/common.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ type CopyNumberType = {
kbMatches?: KbMatchType<'cnv'>[];
log2Cna: string | null;
lohState: string | null;
selected: boolean;
size: number | null;
start: number | null;
variantType: 'cnv';
Expand All @@ -182,6 +183,7 @@ type StructuralVariantType = {
ntermGene: string | null;
ntermTranscript: string | null;
omicSupport: boolean;
selected: boolean;
svg: string | null;
svgTitle: string | null;
variantType: 'sv';
Expand Down Expand Up @@ -209,6 +211,7 @@ type SmallMutationType = {
rnaAltCount: number | null;
rnaDepth: number | null;
rnaRefCount: number | null;
selected: boolean;
startPosition: number | null;
transcript: string | null;
tumourAltCopies: number | null;
Expand Down Expand Up @@ -242,11 +245,14 @@ type ExpOutliersType = {
primarySitekIQR: number | null;
rnaReads: number | null;
rpkm: number | null;
selected: boolean;
tpm: number | null;
variantType: 'exp';
} & RecordDefaults;

type TmburType = {
adjustedTmb: number | null;
adjustedTmbComment: string | null;
cdsBasesIn1To22AndXAndY: string;
cdsIndels: number;
cdsIndelTmb: number;
Expand All @@ -255,8 +261,6 @@ type TmburType = {
comments: string;
genomeSnvTmb: number;
genomeIndelTmb: number;
adjustedTmb: number | null;
adjustedTmbComment: string | null;
tmbHidden: boolean;
kbCategory: string | null;
kbMatches: KbMatchType[];
Expand Down
6 changes: 6 additions & 0 deletions app/components/VariantEditDialog/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.variant-edit-dialog {
&__form-control {
min-width: 160px;
margin: 0 0 16px;
}
}
140 changes: 140 additions & 0 deletions app/components/VariantEditDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import React, {
useState, useEffect, useContext, useCallback,
} from 'react';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Button,
} from '@mui/material';

import api from '@/services/api';
import AsyncButton from '@/components/AsyncButton';

import ConfirmContext from '@/context/ConfirmContext';
import ReportContext from '@/context/ReportContext';
import snackbar from '@/services/SnackbarUtils';
import useConfirmDialog from '@/hooks/useConfirmDialog';
import {
CopyNumberType, SmallMutationType, StructuralVariantType, ExpOutliersType,
} from '@/common';
import { GeneVariantType } from '@/views/ReportView/components/GenomicSummary/types';

import './index.scss';

type VariantEditDialogProps = {
editData: SmallMutationType | CopyNumberType | StructuralVariantType | ExpOutliersType;
variantType: string;
isOpen: boolean;
onClose: (newData?: SmallMutationType | CopyNumberType | StructuralVariantType | ExpOutliersType) => void;
showErrorSnackbar: (message: string) => void;
};

const VariantEditDialog = ({
editData,
variantType,
isOpen = false,
onClose,
showErrorSnackbar,
}: VariantEditDialogProps): JSX.Element => {
const { showConfirmDialog } = useConfirmDialog();
const { report } = useContext(ReportContext);
const { isSigned } = useContext(ConfirmContext);
const [variant, setVariant] = useState('');
const [variants, setVariants] = useState<GeneVariantType[]>();
const [isApiCalling, setIsApiCalling] = useState(false);

useEffect(() => {
if (editData) {
let newVariant;
switch (variantType) {
case 'snv':
newVariant = `${editData?.gene.name}:${editData?.proteinChange}`;
setVariant(newVariant);
break;
case 'cnv':
newVariant = `${editData?.gene.name} (${editData?.cnvState})`;
setVariant(newVariant);
break;
case 'sv':
newVariant = `${editData?.displayName}`;
setVariant(newVariant);
break;
case 'exp':
newVariant = `${editData?.gene.name} (${editData?.expressionState})`;
setVariant(newVariant);
break;
default:
break;
}
}
}, [editData, variantType]);

useEffect(() => {
async function fetchVariants() {
const variantsResp = api.get(`/reports/${report.ident}/summary/genomic-alterations-identified`).request();
if (variantsResp) {
setVariants(await variantsResp);
}
}

fetchVariants();
}, [report.ident]);

const availableVariants = variants?.map(({ geneVariant }) => geneVariant);

const handleSubmit = useCallback(async () => {
if (!availableVariants.includes(variant)) {
setIsApiCalling(true);
const req = api.post(`/reports/${report.ident}/summary/genomic-alterations-identified`, { geneVariant: variant });
try {
if (isSigned) {
showConfirmDialog(req);
setIsApiCalling(false);
} else {
await req.request();
onClose({ ...editData });
snackbar.success('Variant added to key alterations.');
}
} catch (err) {
showErrorSnackbar(`Error updating key alterations: ${err.message}`);
onClose();
} finally {
setIsApiCalling(false);
}
} else {
snackbar.error('Variant already in key alterations.');
onClose();
}
}, [availableVariants, variant, report.ident, isSigned, showConfirmDialog, onClose, editData, showErrorSnackbar]);

const handleClose = useCallback(() => {
onClose();
}, [onClose]);

return (
<Dialog open={isOpen} maxWidth="sm" fullWidth className="variant-edit-dialog">
<DialogTitle>Key Alterations Edit</DialogTitle>
<DialogContent>
<div className="variant-edit-dialog__body">
<p>
Variant:
{' '}
{variant}
</p>
</div>
<DialogActions className="variant-edit-dialog__actions">
<AsyncButton isLoading={isApiCalling} color="secondary" onClick={handleSubmit} component="label">
Add to Summary
</AsyncButton>
<Button onClick={handleClose}>
Cancel
</Button>
</DialogActions>
</DialogContent>
</Dialog>
);
};

export default VariantEditDialog;
2 changes: 1 addition & 1 deletion app/hooks/useConfirmDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const useConfirmDialog = () => {
title="Confirm Action"
text={textDict[report?.template.name]}
confirmText="Yes"
cancelText="cancel"
cancelText="Cancel"
/>,
document.getElementById('alert-dialog'),
);
Expand Down
2 changes: 1 addition & 1 deletion app/views/ProjectsView/columnDefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const readOnlyColDefs = [
},
{
headerName: 'Number of reports',
valueGetter: ({ data }) => data?.reports?.length,
valueGetter: ({ data }) => Number(data?.reportCount),
},
{
headerName: 'Number of users',
Expand Down
6 changes: 3 additions & 3 deletions app/views/ProjectsView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,22 @@ const Projects = (): JSX.Element => {

useEffect(() => {
const getData = async () => {
const projectsResp = await api.get('/project?admin=true').request();
const projectsResp = await api.get(`/project?admin=${adminAccess}`).request();

setProjects(projectsResp);
setLoading(false);
};

getData();
}, []);
}, [adminAccess]);

const handleEditStart = (rowData) => {
setShowDialog(true);
setEditData(rowData);
};

const handleDelete = useCallback(async ({ ident }) => {
// eslint-disable-next-line no-restricted-globals
// eslint-disable-next-line no-restricted-globals, no-alert
if (confirm('Are you sure you want to remove this project?')) {
await api.del(`/project/${ident}`, {}).request();
const newProjects = projects.filter((project) => project.ident !== ident);
Expand Down
26 changes: 26 additions & 0 deletions app/views/ReportView/components/CopyNumber/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import {

import DataTable from '@/components/DataTable';
import ReportContext from '@/context/ReportContext';
import useReport from '@/hooks/useReport';
import api, { ApiCallSet } from '@/services/api';
import { CNVSTATE, EXPLEVEL } from '@/constants';
import Image from '@/components/Image';
import ImageType from '@/components/Image/types';
import snackbar from '@/services/SnackbarUtils';
import { CopyNumberType } from '@/common';
import withLoading, { WithLoadingInjectedProps } from '@/hoc/WithLoading';
import VariantEditDialog from '@/components/VariantEditDialog';
import columnDefs from './columnDefs';

import './index.scss';
Expand Down Expand Up @@ -50,6 +52,7 @@ const CopyNumber = ({
setIsLoading,
}: CopyNumberProps): JSX.Element => {
const { report } = useContext(ReportContext);
const { canEdit } = useReport();
const theme = useTheme();
const [images, setImages] = useState<ImageType[]>([]);
const [circos, setCircos] = useState<ImageType>();
Expand All @@ -70,6 +73,8 @@ const CopyNumber = ({
} return accumulator;
}, []),
);
const [showDialog, setShowDialog] = useState(false);
const [editData, setEditData] = useState<CopyNumberType | null>();

useEffect(() => {
if (report) {
Expand Down Expand Up @@ -187,6 +192,16 @@ const CopyNumber = ({
maxHeight: `calc(100vh - ${theme.mixins.toolbar.minHeight as number * 3}px)`,
}), [theme.mixins?.toolbar?.minHeight]);

const handleEditStart = (rowData: CopyNumberType) => {
setShowDialog(true);
setEditData(rowData);
};

const handleEditClose = () => {
setShowDialog(false);
setEditData(null);
};

const handleVisibleColsChange = (change) => setVisibleCols(change);

return (
Expand All @@ -195,6 +210,15 @@ const CopyNumber = ({
{!isLoading && (
<>
<Typography variant="h3" className="copy-number__title">Summary of Copy Number Events</Typography>
{showDialog && (
<VariantEditDialog
editData={editData}
variantType="cnv"
isOpen={showDialog}
onClose={handleEditClose}
showErrorSnackbar={snackbar.error}
/>
)}
{circos ? (
<div className="copy-number__circos">
<Image
Expand All @@ -218,6 +242,8 @@ const CopyNumber = ({
demoDescription={INFO_BUBBLES[key]}
visibleColumns={visibleCols}
syncVisibleColumns={handleVisibleColsChange}
canEdit={canEdit}
onEdit={handleEditStart}
/>
</React.Fragment>
))}
Expand Down
29 changes: 29 additions & 0 deletions app/views/ReportView/components/Expression/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@ import React, {
import { Typography, Paper } from '@mui/material';
import DataTable from '@/components/DataTable';
import api from '@/services/api';
import snackbar from '@/services/SnackbarUtils';
import DemoDescription from '@/components/DemoDescription';
import ReportContext from '@/context/ReportContext';
import useReport from '@/hooks/useReport';
import withLoading, { WithLoadingInjectedProps } from '@/hoc/WithLoading';
import { ImageType } from '@/components/Image';
import { ExpOutliersType } from '@/common';
import VariantEditDialog from '@/components/VariantEditDialog';
import columnDefs from './columnDefs';
import processExpression from './processData';
import {
Expand Down Expand Up @@ -59,13 +63,17 @@ const Expression = ({
setIsLoading,
}: ExpressionProps): JSX.Element => {
const { report } = useContext(ReportContext);
const { canEdit } = useReport();
const [tissueSites, setTissueSites] = useState<TissueSitesType>();
const [comparators, setComparators] = useState<ComparatorsType>();
const [expOutliers, setExpOutliers] = useState<ProcessedExpressionOutliers>();
const [visibleCols, setVisibleCols] = useState<string[]>(
columnDefs.reduce(getVisibleColsFromColDefReducer, []),
);

const [showDialog, setShowDialog] = useState(false);
const [editData, setEditData] = useState<ExpOutliersType | null>();

useEffect(() => {
if (report && report.ident) {
const getData = async () => {
Expand Down Expand Up @@ -159,6 +167,16 @@ const Expression = ({
}
}, [report]);

const handleEditStart = (rowData: ExpOutliersType) => {
setShowDialog(true);
setEditData(rowData);
};

const handleEditClose = () => {
setShowDialog(false);
setEditData(null);
};

return (!isLoading && (
<>
<div className="expression--padded">
Expand Down Expand Up @@ -218,6 +236,15 @@ const Expression = ({
<Typography align="center">No comparator data to display</Typography>
)}
</div>
{showDialog && (
<VariantEditDialog
editData={editData}
variantType="exp"
isOpen={showDialog}
onClose={handleEditClose}
showErrorSnackbar={snackbar.error}
/>
)}
{expOutliers && (Object.entries(TITLE_MAP).map(([key, titleText]) => (
<DataTable
key={key}
Expand All @@ -228,6 +255,8 @@ const Expression = ({
syncVisibleColumns={setVisibleCols}
canToggleColumns
demoDescription={INFO_BUBBLES[key]}
canEdit={canEdit}
onEdit={handleEditStart}
/>
)))}
</>
Expand Down
Loading

0 comments on commit 4f6af23

Please sign in to comment.