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

[Platform] Add Profile and ProfileHeader to variant page #376

Merged
merged 9 commits into from
May 28, 2024
2 changes: 1 addition & 1 deletion apps/platform/src/pages/VariantPage/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { MetadataType } from "./types";
type HeaderProps = {
loading: boolean;
metadata: MetadataType;
}
};

function Header({ loading, metadata }: HeaderProps) {
const {
Expand Down
13 changes: 13 additions & 0 deletions apps/platform/src/pages/VariantPage/Profile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import ProfileHeader from "./ProfileHeader";

type ProfileProps = {
varId: string;
};

function Profile({ varId }: ProfileProps) {

return <ProfileHeader varId={varId} />

}

export default Profile;
92 changes: 92 additions & 0 deletions apps/platform/src/pages/VariantPage/ProfileHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { useState, useEffect } from "react";
import { Field, ProfileHeader as BaseProfileHeader } from "ui";
import { Box, Typography } from "@mui/material";
import { InSilicoPredictorsType, MetadataType } from "./types";

type ProfileHeaderProps = {
varId: string;
};

function ProfileHeader({ varId }: ProfileHeaderProps) {

// temp: data will come from gql, fetch local json file for now
const [metadata, setMetadata] =
useState<MetadataType | "waiting" | undefined>("waiting");
useEffect(() => {
fetch("../data/variant-data-2.json")
.then(response => response.json())
.then((allData: MetadataType[]) =>
setMetadata(allData.find(v => v.variantId === varId)));
}, []);

// temp: always set loading to false for now
const loading = false;

// temp: revisit this (use same as other pages) once using gql to get data
if (!metadata) {
return <b>Metadata not found!</b>
} else if (metadata === "waiting") {
return <b>Waiting</b>;
}

return (
<BaseProfileHeader>

<Box>
<Typography variant="subtitle1" mt={0}>Location</Typography>
<Field loading={loading} title="GRCh38">
{metadata.chromosome}:{metadata.position}
</Field>
<Field loading={loading} title="Reference Allele">
{metadata.referenceAllele}
</Field>
<Field loading={loading} title="Alternative Allele (effect allele)">
{metadata.alternateAllele}
</Field>
<Typography variant="subtitle1" mt={1}>Variant Effect Predictor (VEP)</Typography>
<Field loading={loading} title="most severe consequence">
{metadata.vep.mostSevereConsequence.replace(/_/g, ' ')}
</Field>
</Box>

<Box>
<Typography variant="subtitle2">Population Allele Frequencies</Typography>
<table>
{metadata.alleleFrequencies
.map(({populationName, alleleFrequency }) => (
<tr key={populationName}>
<td style={{padding: '0 2em 0 0'}}>
<Typography variant="body2" lineHeight={1.35}>
{populationLabels[populationName as keyof typeof populationLabels]}
</Typography>
</td>
<td style={{padding: 0}}>
<Typography variant="body2" align="right" lineHeight={1}>
{alleleFrequency.toFixed(3)}
</Typography>
</td>
</tr>
))
}
</table>
</Box>

</BaseProfileHeader>
)
}

export default ProfileHeader;

// !! NEEDS CHECKED SINCE DIFFERENT KEYS TO THOSE USED ON CURRENT VARIANT PAGE
const populationLabels = {
afr_adj: 'African/African-American',
amr_adj: 'Latino/Admixed American',
asj_adj: 'Ashkenazi Jewish',
eas_adj: 'East Asian',
fin_adj: 'Finnish',
nfe_adj: 'Non-Finnish European',
ami_adj: 'Non-Finnish European Estonian',
mid_adj: 'Non-Finnish European North-Western European',
sas_adj: 'Non-Finnish European Southern European',
remaining_adj: 'Other (population not assigned)',
};
65 changes: 47 additions & 18 deletions apps/platform/src/pages/VariantPage/VariantPage.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,40 @@

import { useState, useEffect } from "react";
import { useLocation, useParams } from "react-router-dom";
import { BasePage } from "ui";
import { useState, useEffect, lazy, Suspense } from "react";
import {
useLocation,
useParams,
Switch,
Route,
useRouteMatch,
Link,
} from "react-router-dom";
import { Box, Tabs, Tab } from "@mui/material";
import { BasePage, ScrollToTop, LoadingBackdrop } from "ui";
import Header from "./Header";
import NotFoundPage from "../NotFoundPage";
import { MetadataType } from "./types";

// const Profile = lazy(() => import("./Profile"));
const Profile = lazy(() => import("./Profile"));

function VariantPage() {
const location = useLocation();
const { varId } = useParams() as { varId: string };
const [metadata, setMetadata] =
useState<MetadataType | 'waiting' | undefined>('waiting');

// temp: loading is set by useQuery, set to false for now
const loading = false;
const { path } = useRouteMatch();

// temp: data will come from gql, fetch local json file for now
useEffect(() => {
fetch('../data/variant-data-2.json')
.then(response => response.json())
.then((allData: MetadataType[]) =>
setMetadata(allData.find(v => v.variantId === varId)));
}, []);
const [metadata, setMetadata] = useState<MetadataType | "waiting" | undefined>("waiting");
useEffect(() => {
fetch("../data/variant-data-2.json")
.then(response => response.json())
.then((allData: MetadataType[]) => setMetadata(allData.find(v => v.variantId === varId)));
}, []);

// temp: loading is set by useQuery, set to false for now
const loading = false;

// temp: revisit this (use same as other pages) once using gql to get data
if (!metadata) {
return <NotFoundPage />;
} else if (metadata === 'waiting') {
} else if (metadata === "waiting") {
return <b>Waiting</b>;
}

Expand All @@ -39,8 +45,31 @@ function VariantPage() {
location={location}
>
<Header loading={loading} metadata={metadata} />
<ScrollToTop />
<Route
path="/"
render={history => (
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<Tabs value={history.location.pathname !== "/" ? history.location.pathname : false}>
<Tab
label={<Box sx={{ textTransform: "capitalize" }}>Profile</Box>}
value={`/variant/${varId}`}
component={Link}
to={`/variant/${varId}`}
/>
</Tabs>
</Box>
)}
/>
<Suspense fallback={<LoadingBackdrop height={11500} />}>
<Switch>
<Route exact path={path}>
<Profile varId={varId} />
</Route>
</Switch>
</Suspense>
</BasePage>
);
}

export default VariantPage;
export default VariantPage;
2 changes: 0 additions & 2 deletions apps/platform/src/pages/VariantPage/index.js

This file was deleted.

1 change: 1 addition & 0 deletions apps/platform/src/pages/VariantPage/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./VariantPage";
28 changes: 15 additions & 13 deletions apps/platform/src/pages/VariantPage/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
type AlleleFrequencyType = {
export type AlleleFrequencyType = {
populationName: string;
alleleFrequency: number;
};
Expand All @@ -12,6 +12,19 @@ type VepType = {
}[];
};

export type InSilicoPredictorsType = {
cadd?: {
phred: number;
raw: number;
};
revelMax?: number;
spliceaiDsMax?: number;
pangolinLargestDs?: number;
phylop?: number;
siftMax?: number;
polyphenMax?: number;
};

export type MetadataType = {
variantId: string,
chromosome: string,
Expand All @@ -24,16 +37,5 @@ export type MetadataType = {
alleleType: string;
alleleFrequencies: AlleleFrequencyType[];
vep: VepType;
inSilicoPredictors: {
cadd?: {
phred: number;
raw: number;
};
revelMax?: number;
spliceaiDsMax?: number;
pangolinLargestDs?: number;
phylop?: number;
siftMax?: number;
polyphenMax?: number;
};
inSilicoPredictors: InSilicoPredictorsType;
};
Loading