Skip to content

Commit 4dbefab

Browse files
chinmehtacarcruz
andauthored
[Platform]: cs async tooltip and study author (#694)
--------- Co-authored-by: Carlos Cruz <me@carcruzcast.com>
1 parent 6ecf4f3 commit 4dbefab

File tree

12 files changed

+146
-58
lines changed

12 files changed

+146
-58
lines changed

apps/platform/src/pages/CredibleSetPage/ProfileHeader.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
DetailPopover,
1313
SummaryStatsTable,
1414
DisplaySampleSize,
15+
StudyPublication,
1516
} from "ui";
1617
import { Box, Typography } from "@mui/material";
1718
import CREDIBLE_SET_PROFILE_HEADER_FRAGMENT from "./ProfileHeader.gql";
@@ -248,8 +249,11 @@ function ProfileHeader() {
248249
)}
249250
{study?.publicationFirstAuthor && (
250251
<Field loading={loading} title="Publication">
251-
{study?.publicationFirstAuthor} <i>et al.</i> {study?.publicationJournal} (
252-
{study?.publicationDate?.slice(0, 4)})
252+
<StudyPublication
253+
publicationFirstAuthor={study.publicationFirstAuthor}
254+
publicationDate={study.publicationDate}
255+
publicationJournal={study.publicationJournal}
256+
/>
253257
</Field>
254258
)}
255259
{study?.pubmedId && (

apps/platform/src/pages/SearchPage/SearchContainer.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,6 @@ function SearchContainer({ q, page, entities, data, onPageChange, onSetEntity })
229229
md={6}
230230
sx={{
231231
display: "flex",
232-
alignItems: "center",
233232
justifyContent: "center",
234233
}}
235234
>

apps/platform/src/pages/SearchPage/StudyResult.jsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { makeStyles, useTheme } from "@mui/styles";
1+
import { makeStyles } from "@mui/styles";
22
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
33
import { faChartBar } from "@fortawesome/free-solid-svg-icons";
4-
import { Highlights, Link } from "ui";
4+
import { Highlights, Link, StudyPublication } from "ui";
55
import { Box, Typography } from "@mui/material";
66
import { getStudyItemMetaData } from "@ot/utils";
77

@@ -20,7 +20,6 @@ const useStyles = makeStyles(theme => ({
2020

2121
function StudyResult({ data, highlights }) {
2222
const classes = useStyles();
23-
const theme = useTheme();
2423

2524
return (
2625
<div className={classes.container}>
@@ -42,12 +41,11 @@ function StudyResult({ data, highlights }) {
4241
<Box sx={{ display: "flex", flexDirection: "row", gap: 1 }}>
4342
<div>
4443
{" "}
45-
{data.publicationFirstAuthor && (
46-
<>
47-
{data.publicationFirstAuthor} <i>et al.</i> {data.publicationJournal} (
48-
{data.publicationDate?.slice(0, 4)})
49-
</>
50-
)}
44+
<StudyPublication
45+
publicationFirstAuthor={data.publicationFirstAuthor}
46+
publicationDate={data.publicationDate}
47+
publicationJournal={data.publicationJournal}
48+
/>
5149
</div>
5250
</Box>
5351
<div>

apps/platform/src/pages/StudyPage/StudyProfileHeader.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
LabelChip,
1010
DisplaySampleSize,
1111
PublicationsDrawer,
12+
StudyPublication,
1213
} from "ui";
1314
import { Box } from "@mui/material";
1415
import { populationMap } from "@ot/constants";
@@ -106,8 +107,11 @@ function ProfileHeader() {
106107
)}
107108
{publicationFirstAuthor && (
108109
<Field loading={loading} title="Publication">
109-
{publicationFirstAuthor} <i>et al.</i> {publicationJournal} (
110-
{publicationDate?.slice(0, 4)})
110+
<StudyPublication
111+
publicationFirstAuthor={publicationFirstAuthor}
112+
publicationDate={publicationDate}
113+
publicationJournal={publicationJournal}
114+
/>
111115
</Field>
112116
)}
113117
{pubmedId && (

packages/ui/src/components/GlobalSearch/GlobalSearchListItem.jsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { faXmark, faClockRotateLeft, faArrowTrendUp } from "@fortawesome/free-so
77
import { clearRecentItem } from "./utils/searchUtils";
88
import DisplayVariantId from "../DisplayVariantId";
99
import { getStudyItemMetaData } from "@ot/utils";
10+
import StudyPublication from "../StudyPublication";
1011

1112
const ListItem = styled("li")(({ theme }) => ({
1213
cursor: "pointer",
@@ -215,12 +216,11 @@ function TopHitListItem({ item, onItemClick }) {
215216
<Typography variant="subtitle1">
216217
{item.symbol && item.name}
217218

218-
{item.publicationFirstAuthor && (
219-
<>
220-
{item.publicationFirstAuthor} <i>et al.</i> {item.publicationJournal} (
221-
{item.publicationDate?.slice(0, 4)})
222-
</>
223-
)}
219+
<StudyPublication
220+
publicationFirstAuthor={item.publicationFirstAuthor}
221+
publicationDate={item.publicationDate}
222+
publicationJournal={item.publicationJournal}
223+
/>
224224
</Typography>
225225
</Box>
226226
<JustifyBetween>

packages/ui/src/components/Navigate.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,15 @@
11
import { Box } from "@mui/material";
22
import Link from "./Link";
33
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
4-
import {
5-
faArrowRight,
6-
faArrowRightToBracket,
7-
faCaretRight,
8-
faChevronRight,
9-
faArrowUpRightFromSquare,
10-
} from "@fortawesome/free-solid-svg-icons";
4+
import { faArrowRightToBracket } from "@fortawesome/free-solid-svg-icons";
115

126
type NavigateProps = {
137
to: string;
148
};
159

1610
export default function Navigate({ to }: NavigateProps) {
1711
return (
18-
<Link to={to}>
12+
<Link asyncTooltip to={to}>
1913
<Box display="flex" justifyContent="center" alignItems="center" gap={1}>
2014
View
2115
<FontAwesomeIcon size="sm" icon={faArrowRightToBracket} />

packages/ui/src/components/OtAsyncTooltip/OtAsyncTooltip.tsx

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,15 @@ import {
1010
TooltipProps,
1111
} from "@mui/material";
1212
import { useLazyQuery } from "@apollo/client";
13-
import { getEntityIcon, getEntityQuery, getQueryVariables } from "./utils/asyncTooltipUtil";
13+
import {
14+
getEntityDescription,
15+
getEntityIcon,
16+
getEntityQuery,
17+
getQueryVariables,
18+
} from "./utils/asyncTooltipUtil";
1419
import { naLabel } from "@ot/constants";
1520

16-
import { getStudyItemMetaData } from "@ot/utils";
21+
import StudyPublication from "../StudyPublication";
1722

1823
const DELAY_REQUEST = 1000;
1924

@@ -56,8 +61,10 @@ function OtAsyncTooltip({ children, entity, id }: OtAsyncTooltipProps): ReactEle
5661
});
5762

5863
function getTooltipContent() {
64+
let entityAccessor = entity;
5965
if (loading || !data) return <AsyncTooltipLoadingView />;
60-
return <AsyncTooltipDataView entity={entity} data={data?.[entity]} />;
66+
if (entity === "credible-set") entityAccessor = "credibleSet";
67+
return <AsyncTooltipDataView entity={entity} data={data?.[entityAccessor]} />;
6168
}
6269

6370
function abortApiCall() {
@@ -119,41 +126,33 @@ function AsyncTooltipDataView({
119126
entity: string;
120127
data: Record<string, unknown>;
121128
}): ReactElement {
122-
function getLabel() {
123-
return data?.name || data?.id || naLabel;
124-
}
125-
126-
function getDescription() {
127-
let descText = "";
128-
129-
if (Array.isArray(data.description) && data.description.length)
130-
descText = data?.description[0].substring(0, 150);
131-
else if (Array.isArray(data.description) && !data.description.length) descText = "";
132-
else if (data.description) descText = data?.description.substring(0, 150);
133-
134-
// study subtext
135-
descText += getStudyItemMetaData({
136-
studyType: data?.studyType,
137-
nSamples: data?.nSamples,
138-
credibleSetsCount: data?.credibleSets?.credibleSetsCount,
139-
});
140-
141-
if (!descText) return "No description available.";
142-
143-
return descText;
144-
}
129+
const showSubText = !!data?.mostSevereConsequence?.label || data?.publicationFirstAuthor;
145130

146131
function getSubtext() {
147-
let finalSubText = "";
132+
let finalSubText;
148133

134+
// variant subtext
149135
const mostSevereConsequence = data?.mostSevereConsequence?.label;
136+
if (mostSevereConsequence) finalSubText = `Most severe consequence: ${mostSevereConsequence}`;
150137

151-
if (mostSevereConsequence) finalSubText += `Most severe consequence: ${mostSevereConsequence}`;
138+
// study subtext
139+
const publicationData = data?.publicationFirstAuthor;
140+
if (publicationData)
141+
finalSubText = (
142+
<StudyPublication
143+
publicationDate={data?.publicationDate}
144+
publicationFirstAuthor={data?.publicationFirstAuthor}
145+
publicationJournal={data?.publicationJournal}
146+
/>
147+
);
152148

153149
return finalSubText;
154150
}
155151

156-
const showSubText = !!data?.mostSevereConsequence?.label;
152+
function getLabel() {
153+
if (entity === "credible-set") return "Credible set";
154+
return data?.name || data?.id || naLabel;
155+
}
157156

158157
return (
159158
<Box sx={{ p: 1 }}>
@@ -184,7 +183,7 @@ function AsyncTooltipDataView({
184183
{getLabel()}
185184
</Box>{" "}
186185
<Box sx={{ typography: "body2", color: theme => theme.palette.grey[800] }}>
187-
{getDescription()}
186+
{getEntityDescription(entity, data)}
188187
</Box>
189188
</Box>
190189
</Box>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
query CredibleSetsTooltipQuery($studyLocusId: String!) {
2+
credibleSet(studyLocusId: $studyLocusId) {
3+
id: studyLocusId
4+
variant {
5+
id
6+
}
7+
study {
8+
id
9+
studyType
10+
}
11+
}
12+
}

packages/ui/src/components/OtAsyncTooltip/queries/StudyTooltipQuery.gql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,8 @@ query StudyTooltipQuery($studyId: String!) {
77
credibleSets {
88
credibleSetsCount: count
99
}
10+
publicationFirstAuthor
11+
publicationDate
12+
publicationJournal
1013
}
1114
}

packages/ui/src/components/OtAsyncTooltip/utils/asyncTooltipUtil.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,17 @@ import DISEASE_TOOLTIP_QUERY from "../queries/DiseaseTooltipQuery.gql";
33
import STUDY_TOOLTIP_QUERY from "../queries/StudyTooltipQuery.gql";
44
import TARGET_TOOLTIP_QUERY from "../queries/TargetTooltipQuery.gql";
55
import VARIANT_TOOLTIP_QUERY from "../queries/VariantTooltipQuery.gql";
6+
import CREDIBLE_SETS_TOOLTIP_QUERY from "../queries/CredibleSetsTooltipQuery.gql";
67
import {
78
faChartBar,
9+
faDiagramProject,
810
faDna,
911
faMapPin,
1012
faPrescriptionBottleAlt,
1113
faStethoscope,
1214
faTag,
1315
} from "@fortawesome/free-solid-svg-icons";
16+
import { getStudyItemMetaData } from "@ot/utils";
1417

1518
export function getQueryVariables(entity: string, id: string): Record<string, string> {
1619
switch (entity) {
@@ -24,6 +27,8 @@ export function getQueryVariables(entity: string, id: string): Record<string, st
2427
return { variantId: id };
2528
case "study":
2629
return { studyId: id };
30+
case "credible-set":
31+
return { studyLocusId: id };
2732
default:
2833
return { id };
2934
}
@@ -41,6 +46,8 @@ export const getEntityQuery = (entity: string) => {
4146
return TARGET_TOOLTIP_QUERY;
4247
case "variant":
4348
return VARIANT_TOOLTIP_QUERY;
49+
case "credible-set":
50+
return CREDIBLE_SETS_TOOLTIP_QUERY;
4451
default:
4552
return;
4653
}
@@ -58,7 +65,48 @@ export const getEntityIcon = (entity: string) => {
5865
return faDna;
5966
case "variant":
6067
return faMapPin;
68+
case "credible-set":
69+
return faDiagramProject;
6170
default:
6271
return faTag;
6372
}
6473
};
74+
75+
export const getEntityDescription = (entity, data) => {
76+
switch (entity) {
77+
case "drug":
78+
return getTrimmedDescription(data?.description);
79+
case "disease":
80+
return getTrimmedDescription(data?.description);
81+
case "study":
82+
return getStudyItemMetaData({
83+
studyType: data?.studyType,
84+
nSamples: data?.nSamples,
85+
credibleSetsCount: data?.credibleSets?.credibleSetsCount,
86+
});
87+
case "target":
88+
return getTrimmedDescription(data?.description[0] || "");
89+
case "variant":
90+
return getTrimmedDescription(data?.description);
91+
case "credible-set":
92+
return getCredibleSetsDescription({
93+
variantId: data?.variant.id,
94+
studyId: data?.study.id,
95+
});
96+
default:
97+
return "No description available.";
98+
}
99+
};
100+
101+
const getTrimmedDescription = (description: string | null) => {
102+
if (!description || description.length < 1) return "No description available.";
103+
return description.substring(0, 150);
104+
};
105+
106+
export const getCredibleSetsDescription = ({ variantId, studyId }): string => {
107+
let metaData = "";
108+
if (variantId) metaData += `Lead Variant: ${variantId}`;
109+
if (studyId) metaData += ` • Study ID: ${studyId}`;
110+
111+
return metaData;
112+
};

0 commit comments

Comments
 (0)