Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dashboard updates #430

Merged
merged 2 commits into from May 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,13 @@ This Changelog tracks changes to this project. The notes below include a summary
- `fixed` for any bug fixes.
- `security` in case of vulnerabilities.

## 20 May 2022

- `changed` reverted previous "wes" -> "wes_normal" and "wes_tumor_only" -> "wes_tumor"
- `changed` link location from just the text to whole chip
- `added` links to the clinical data chips
- api already changed to return under clinical_participants

## 19 May 2022

- `changed` WES display on data-overview to compensate for the changes in counting in the API
Expand Down
85 changes: 55 additions & 30 deletions src/components/data-overview/DataOverviewPage.test.tsx
Expand Up @@ -28,6 +28,10 @@ it("displays data as expected", async () => {
case "/downloadable_files/facet_groups_for_links":
return {
facets: {
clinical_participants: {
received: ["clinical_participants"],
analyzed: [] // none
},
atacseq: {
// test multiple values as well as space
received: ["atacseq_assay", "atacseq assay"],
Expand All @@ -52,11 +56,11 @@ it("displays data as expected", async () => {
received: ["tcr_assay"],
analyzed: ["tcr_analysis"]
},
wes_normal: {
wes: {
received: ["wes_assay"],
analyzed: ["wes_analysis"]
},
wes_tumor: {
wes_tumor_only: {
received: ["wes_assay"],
analyzed: ["wes_tumor_only_analysis"]
}
Expand All @@ -72,12 +76,14 @@ it("displays data as expected", async () => {
expected_assays: ["atacseq", "wes", "h&e", "ihc"],
"h&e": 11,
atacseq: 3,
wes_normal: 5,
wes_tumor: 6,
wes: 5,
wes_analysis: 5,
wes_tumor_only: 6,
wes_tumor_only_analysis: 1,
ihc: 0,
excluded_samples: { wes_analysis: [excluded] }
excluded_samples: {
wes_tumor_only_analysis: [excluded]
}
},
{
trial_id: "tr2",
Expand All @@ -87,8 +93,8 @@ it("displays data as expected", async () => {
expected_assays: ["atacseq", "h&e", "ihc"],
"h&e": 21,
atacseq: 0,
wes_normal: 0,
wes_tumor: 0,
wes: 0,
wes_tumor_only: 0,
ihc: 22
}
];
Expand All @@ -97,17 +103,20 @@ it("displays data as expected", async () => {
}
});

const { findByText, queryByText, getByTestId } = renderAsRouteComponent(
DataOverviewPage
);
const {
findByText,
queryByText,
getByTestId,
queryAllByText
} = renderAsRouteComponent(DataOverviewPage);

// from per-trial data summaries
expect(await findByText(/trial/i)).toBeInTheDocument();
expect(queryByText(/tr1/i)).toBeInTheDocument();
expect(queryByText(/tr2/i)).toBeInTheDocument();
expect(queryByText(/h&e/i)).toBeInTheDocument();
expect(queryByText(/wes_normal/i)).toBeInTheDocument();
expect(queryByText(/wes_tumor/i)).toBeInTheDocument();
expect(queryAllByText(/wes/i).length).toEqual(2);
expect(queryByText(/wes_tumor_only/i)).toBeInTheDocument();
expect(queryByText(/1 kb/i)).toBeInTheDocument();
expect(queryByText(/1 mb/i)).toBeInTheDocument();
expect(
Expand All @@ -117,10 +126,10 @@ it("displays data as expected", async () => {
innerText(getByTestId("data-tr1-atacseq-received"), "3")
).toBeInTheDocument();
expect(
innerText(getByTestId("data-tr1-wes_tumor-received"), "6")
innerText(getByTestId("data-tr1-wes_tumor_only-received"), "6")
).toBeInTheDocument();
expect(
innerText(getByTestId("data-tr1-wes_normal-received"), "5")
innerText(getByTestId("data-tr1-wes-received"), "5")
).toBeInTheDocument();
expect(
innerText(getByTestId("data-tr1-ihc-received"), "0")
Expand All @@ -132,51 +141,67 @@ it("displays data as expected", async () => {
innerText(getByTestId("data-tr2-ihc-received"), "22")
).toBeInTheDocument();
expect(
innerText(getByTestId("na-tr2-wes_tumor-received"), "-")
innerText(getByTestId("na-tr2-wes_tumor_only-received"), "-")
).toBeInTheDocument();
expect(
innerText(getByTestId("na-tr2-wes_normal-received"), "-")
innerText(getByTestId("na-tr2-wes-received"), "-")
).toBeInTheDocument();

const wesAnalyzed = getByTestId("data-tr1-wes_normal-analyzed");
expect(innerText(wesAnalyzed, "5")).toBeInTheDocument();
const wesTumorOnlyAnalyzed = getByTestId("data-tr1-wes_tumor-analyzed");
const wesTumorOnlyAnalyzed = getByTestId(
"data-tr1-wes_tumor_only-analyzed"
);
expect(innerText(wesTumorOnlyAnalyzed, "1")).toBeInTheDocument();
expect(wesTumorOnlyAnalyzed.children[0]).toHaveStyle(
`background: ${theme.palette.warning.light}`
);
const wesAnalyzed = getByTestId("data-tr1-wes-analyzed");
expect(innerText(wesAnalyzed, "5")).toBeInTheDocument();
expect(wesAnalyzed.children[0]).toHaveStyle(
`background: ${theme.palette.success.light}`
);

// links to file browser
expect(getByTestId("link-tr1-atacseq-received")).toHaveAttribute(
expect(getByTestId("chip-tr1-atacseq-received")).toHaveAttribute(
"href",
"/browse-data?file_view=1&trial_ids=tr1&facets=atacseq_assay&facets=atacseq%20assay"
);
// wes_tumor and wes_normal assay point to the same place
expect(getByTestId("link-tr1-wes_normal-received")).toHaveAttribute(
// wes_tumor and wes assay point to the same place
expect(getByTestId("chip-tr1-wes-received")).toHaveAttribute(
"href",
"/browse-data?file_view=1&trial_ids=tr1&facets=wes_assay"
);
expect(getByTestId("link-tr1-wes_tumor-received")).toHaveAttribute(
expect(getByTestId("chip-tr1-wes_tumor_only-received")).toHaveAttribute(
"href",
"/browse-data?file_view=1&trial_ids=tr1&facets=wes_assay"
);

// sample exclusions are displayed on hover
fireEvent.mouseOver(wesAnalyzed.firstElementChild!);
fireEvent.mouseOver(wesTumorOnlyAnalyzed.firstElementChild!);
expect(await findByText(excluded.cimac_id)).toBeInTheDocument();
expect(
queryByText(new RegExp(excluded.reason_excluded, "i"))
).toBeInTheDocument();

// clinical data is displayed (and colored) as expected
const partialClinical = queryByText(/1 \/ 2 participants/i);
expect(partialClinical).toBeInTheDocument();
expect(partialClinical?.closest("div")).toHaveStyle(
expect(queryByText(/0 \/ 3 participants/i)).toBeInTheDocument();
expect(getByTestId("chip-tr1-clinical_participants")).toHaveStyle(
`color: ${theme.palette.primary.main}`
); // blue
const fullClinical = queryByText(/0 \/ 3 participants/i);
expect(fullClinical).toBeInTheDocument();
expect(fullClinical?.closest("div")).toHaveStyle(
expect(queryByText(/0 \/ 3 participants/i)).toBeInTheDocument();
expect(getByTestId("chip-tr2-clinical_participants")).toHaveStyle(
`color: ${theme.palette.text.primary}`
); // grey

// clinical data links generated as expected
expect(getByTestId("chip-tr1-clinical_participants")).toHaveAttribute(
"href",
"/browse-data?file_view=1&trial_ids=tr1&facets=clinical_participants"
);
expect(getByTestId("chip-tr2-clinical_participants")).toHaveAttribute(
"href",
"/browse-data?file_view=1&trial_ids=tr2&facets=clinical_participants"
);

// from CIDC-wide data overview
expect(queryByText(/1 gb/i)).toBeInTheDocument();
});
Expand Down
85 changes: 43 additions & 42 deletions src/components/data-overview/DataOverviewPage.tsx
Expand Up @@ -10,7 +10,6 @@ import {
Typography,
withStyles,
Chip,
Link,
Tooltip,
TableContainer,
Divider
Expand Down Expand Up @@ -42,8 +41,8 @@ const ASSAYS_WITH_ANALYSIS = [
"cytof",
"rna",
"tcr",
"wes_normal",
"wes_tumor"
"wes",
"wes_tumor_only"
];

const HeaderCell = withStyles({
Expand Down Expand Up @@ -95,11 +94,23 @@ const useDataStyles = makeStyles({
const ColoredData: React.FC<{
status: IngestionStatus;
tooltip?: string | React.ReactElement;
}> = ({ status, tooltip, children }) => {
linkTarget?: string;
dataTestId?: string;
}> = ({ status, tooltip, children, linkTarget, dataTestId }) => {
const classes = useDataStyles();
const chip = (
<Chip className={classes[status]} size="small" label={children} />
);
const chip =
linkTarget && dataTestId ? (
<Chip
className={classes[status]}
size="small"
label={children}
component="a"
href={linkTarget}
data-testid={dataTestId}
/>
) : (
<Chip className={classes[status]} size="small" label={children} />
);
return tooltip ? (
<Tooltip title={<Typography variant="caption">{tooltip}</Typography>}>
{chip}
Expand Down Expand Up @@ -132,18 +143,10 @@ const AssayCell: React.FC<{
break;
case "analyzed":
let analysis: string;
switch (assay) {
case "wes_tumor":
analysis = "wes_tumor_only_analysis";
break;
case "wes_normal":
analysis = "wes_analysis";
break;
case "rna":
analysis = "rna_level1_analysis";
break;
default:
analysis = `${assay}_analysis`;
if (assay === "rna") {
analysis = "rna_level1_analysis";
} else {
analysis = `${assay}_analysis`;
}

const excluded =
Expand Down Expand Up @@ -192,30 +195,23 @@ const AssayCell: React.FC<{

let linkTarget: string = `/browse-data?file_view=1&trial_ids=${overview.trial_id}`;
for (const facet of facets) {
linkTarget = linkTarget + `&facets=` + encodeURI(facet);
linkTarget =
linkTarget + `&facets=` + encodeURI(facet).replace("&", "%26");
}

let countWithLink: number | React.ReactElement;
countWithLink =
!count || count === 0 ? (
count
) : (
<Link
href={linkTarget}
data-testid={`link-${overview.trial_id}-${assay}-${stage}`}
>
{count}
</Link>
);

return (
<TableCell
key={assay}
align="center"
data-testid={`data-${overview.trial_id}-${assay}-${stage}`}
>
<ColoredData status={status} tooltip={tooltip}>
{countWithLink}
<ColoredData
status={status}
tooltip={tooltip}
linkTarget={linkTarget}
dataTestId={`chip-${overview.trial_id}-${assay}-${stage}`}
>
{count || 0}
</ColoredData>
</TableCell>
);
Expand All @@ -226,6 +222,13 @@ const DataOverviewRow: React.FC<{
assays: string[];
facets: IFacetsForLinks;
}> = ({ overview, assays, facets }) => {
let clinicalLinkTarget: string = `/browse-data?file_view=1&trial_ids=${overview.trial_id}`;
for (const facet of facets.facets[`clinical_participants`][`received`]) {
clinicalLinkTarget =
clinicalLinkTarget +
`&facets=` +
encodeURI(facet).replace("&", "%26");
}
return (
<>
<TableRow>
Expand All @@ -235,6 +238,8 @@ const DataOverviewRow: React.FC<{
</TableCell>
<TableCell rowSpan={3} align="right">
<Chip
component="a"
href={clinicalLinkTarget}
style={{ width: "100%" }}
color={
overview.clinical_participants > 0
Expand All @@ -243,6 +248,7 @@ const DataOverviewRow: React.FC<{
}
variant="outlined"
label={`${overview.clinical_participants} / ${overview.total_participants} participants`}
data-testid={`chip-${overview.trial_id}-clinical_participants`}
/>
</TableCell>
</TableRow>
Expand All @@ -254,9 +260,7 @@ const DataOverviewRow: React.FC<{
</TableCell>
{assays.map(assay =>
overview.expected_assays.includes(
["wes_normal", "wes_tumor"].includes(assay)
? "wes"
: assay
assay === "wes_tumor_only" ? "wes" : assay
) || overview[assay] > 0 ? (
<AssayCell
key={assay}
Expand Down Expand Up @@ -285,9 +289,7 @@ const DataOverviewRow: React.FC<{
{assays.map(assay =>
ASSAYS_WITH_ANALYSIS.includes(assay) &&
overview.expected_assays.includes(
["wes_normal", "wes_tumor"].includes(assay)
? "wes"
: assay
assay === "wes_tumor_only" ? "wes" : assay
) ? (
<AssayCell
key={assay}
Expand Down Expand Up @@ -340,7 +342,6 @@ const DataOverviewPage: React.FC<RouteComponentProps> = withIdToken(
</Grid>
);
}
console.log(facets.facets);

if (summary.length === 0) {
return <Typography>No data found.</Typography>;
Expand Down