From 66c3f1f81ab1743a45b3448fff095d6b0f5d37e4 Mon Sep 17 00:00:00 2001 From: Chintan Mehta Date: Tue, 28 Jan 2025 10:00:47 +0000 Subject: [PATCH 1/6] Update GlobalSearchDialog.jsx --- packages/ui/src/components/GlobalSearch/GlobalSearchDialog.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/src/components/GlobalSearch/GlobalSearchDialog.jsx b/packages/ui/src/components/GlobalSearch/GlobalSearchDialog.jsx index c43aaefca..a441b6fd0 100644 --- a/packages/ui/src/components/GlobalSearch/GlobalSearchDialog.jsx +++ b/packages/ui/src/components/GlobalSearch/GlobalSearchDialog.jsx @@ -1,4 +1,4 @@ -import { useCallback, useContext, useEffect, useState } from "react"; +import { useContext, useState } from "react"; import { Box, Dialog, DialogContent, DialogTitle, styled } from "@mui/material"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faMagnifyingGlass } from "@fortawesome/free-solid-svg-icons"; From d05bdb8e0ecaafec4a6b093744e4912c5700e2ef Mon Sep 17 00:00:00 2001 From: Chintan Mehta Date: Thu, 30 Jan 2025 11:57:02 +0000 Subject: [PATCH 2/6] feat: adding study to search query --- .../src/components/Search/SearchQuery.gql | 45 +++++++++++++------ .../GlobalSearch/GlobalSearchListHeader.jsx | 34 +++++++++++--- .../GlobalSearch/GlobalSearchListItem.jsx | 17 ++++--- .../GlobalSearch/utils/searchUtils.js | 40 +++++++---------- 4 files changed, 83 insertions(+), 53 deletions(-) diff --git a/apps/platform/src/components/Search/SearchQuery.gql b/apps/platform/src/components/Search/SearchQuery.gql index a3a17ed9d..69b73f992 100644 --- a/apps/platform/src/components/Search/SearchQuery.gql +++ b/apps/platform/src/components/Search/SearchQuery.gql @@ -1,7 +1,7 @@ query SearchQuery($queryString: String!) { topHit: search( queryString: $queryString - entityNames: ["target", "disease", "drug", "variant"] + entityNames: ["target", "disease", "drug", "variant", "study"] page: { index: 0, size: 1 } ) { hits { @@ -14,9 +14,18 @@ query SearchQuery($queryString: String!) { referenceAllele alternateAllele rsIds - __typename } - + + ... on Study { + # entity + id + hasSumstats + traitFromSource + credibleSets { + count + } + } + ... on Target { id approvedSymbol @@ -46,7 +55,7 @@ query SearchQuery($queryString: String!) { variants: search( queryString: $queryString entityNames: ["variant"] - page: {index: 0, size: 3} + page: { index: 0, size: 3 } ) { hits { id @@ -62,11 +71,23 @@ query SearchQuery($queryString: String!) { } } } - targets: search( - queryString: $queryString - entityNames: ["target"] - page: { index: 0, size: 3 } - ) { + studies: search(queryString: $queryString, entityNames: ["study"], page: { index: 0, size: 3 }) { + hits { + id + entity + object { + ... on Study { + id + hasSumstats + traitFromSource + credibleSets { + credibleSetsCount: count + } + } + } + } + } + targets: search(queryString: $queryString, entityNames: ["target"], page: { index: 0, size: 3 }) { hits { id entity @@ -95,11 +116,7 @@ query SearchQuery($queryString: String!) { } } } - drugs: search( - queryString: $queryString - entityNames: ["drug"] - page: { index: 0, size: 3 } - ) { + drugs: search(queryString: $queryString, entityNames: ["drug"], page: { index: 0, size: 3 }) { hits { id entity diff --git a/packages/ui/src/components/GlobalSearch/GlobalSearchListHeader.jsx b/packages/ui/src/components/GlobalSearch/GlobalSearchListHeader.jsx index 24b015d16..c23a31a74 100644 --- a/packages/ui/src/components/GlobalSearch/GlobalSearchListHeader.jsx +++ b/packages/ui/src/components/GlobalSearch/GlobalSearchListHeader.jsx @@ -1,5 +1,5 @@ import { makeStyles } from "@mui/styles"; -import { Button, Typography, styled } from "@mui/material"; +import { Button, Chip, Typography, styled } from "@mui/material"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faPrescriptionBottleAlt, @@ -40,7 +40,19 @@ const ClearAllButton = styled(Button)` function GlobalSearchListHeader({ listHeader, children }) { const classes = useStyles(); - if (listHeader === "") return { children }; + const NewChip = ( + + ); + + if (!listHeader) return { children }; const getIcon = () => { switch (listHeader) { @@ -60,12 +72,8 @@ function GlobalSearchListHeader({ listHeader, children }) { return ; case "variants": return ; - case "Study": + case "studies": return ; - case "Gene": - return ; - case "Variant": - return ; case "recent": return null; case "Search Suggestions": @@ -75,6 +83,17 @@ function GlobalSearchListHeader({ listHeader, children }) { } }; + function getIconTag() { + switch (listHeader) { + case "variants": + return NewChip; + case "studies": + return NewChip; + default: + return null; + } + } + return (
@@ -82,6 +101,7 @@ function GlobalSearchListHeader({ listHeader, children }) { {listHeader} +
{getIconTag()}
{listHeader === "recent" && ( diff --git a/packages/ui/src/components/GlobalSearch/GlobalSearchListItem.jsx b/packages/ui/src/components/GlobalSearch/GlobalSearchListItem.jsx index 416f6ddde..a5eb71a8e 100644 --- a/packages/ui/src/components/GlobalSearch/GlobalSearchListItem.jsx +++ b/packages/ui/src/components/GlobalSearch/GlobalSearchListItem.jsx @@ -286,7 +286,7 @@ function GlobalSearchListItem({ item, isTopHit = false, onItemClick }) { - + {/* {item.pubAuthor && item.pubAuthor} @@ -299,19 +299,19 @@ function GlobalSearchListItem({ item, isTopHit = false, onItemClick }) { {item.pubJournal && item.pubJournal} - + */} - {item.rsId && ( + {/* {item.rsId && (
Ensembl: {item.rsId}
- )} + )} */} - {item.numAssocLoci > -1 && {item.numAssocLoci} associated loci} + {item.credibleSetsCount > -1 && <>Credible sets count: {item.credibleSetsCount}} {item.hasSumstats && ( @@ -321,19 +321,18 @@ function GlobalSearchListItem({ item, isTopHit = false, onItemClick }) { fontSize: "0.8rem", margin: "0", }} - color="primary" label="summary statistics" /> )} - {item.nInitial && N Study: {item.nInitial}} + {/* {item.nInitial && N Study: {item.nInitial}} */} -
+ {/*
{item.start} {item.start && item.end && `-`} {item.end} -
+
*/} ); } diff --git a/packages/ui/src/components/GlobalSearch/utils/searchUtils.js b/packages/ui/src/components/GlobalSearch/utils/searchUtils.js index 93edbba59..3e49056fb 100644 --- a/packages/ui/src/components/GlobalSearch/utils/searchUtils.js +++ b/packages/ui/src/components/GlobalSearch/utils/searchUtils.js @@ -1,11 +1,13 @@ import { format } from "d3-format"; -const mapStandardKeys = origionalKey => { - switch (origionalKey) { +const mapStandardKeys = originalKey => { + switch (originalKey) { case "studyId": return "id"; case "traitReported": return "name"; + case "traitFromSource": + return "name"; case "approvedName": return "name"; case "approvedSymbol": @@ -13,11 +15,12 @@ const mapStandardKeys = origionalKey => { case "functionDescriptions": return "description"; default: - return origionalKey; + return originalKey; } }; const flattenObj = ob => { + if (!ob) return; const result = {}; Object.entries(ob).forEach(([key, value]) => { @@ -32,12 +35,9 @@ const flattenObj = ob => { result[mapStandardKeys(key)] = value; } }); - return result; }; -const isArray = value => Array.isArray(value) && value.length > 0; - const exceedsArrayLengthLimit = array => { const limitLength = 4; let exceedsLimit = false; @@ -51,25 +51,19 @@ const exceedsArrayLengthLimit = array => { export const formatSearchData = unformattedData => { const formattedData = {}; + // TODO: fix variant search bug + Object.entries(unformattedData).forEach(([key, value]) => { const typesArray = []; - if (isArray(value)) { - value.map(i => - typesArray.push({ - type: key === "topHit" ? "topHit" : key, - entity: key, - ...flattenObj(i), - }) - ); - } else if (isArray(value.hits)) { - value.hits.map(i => - typesArray.push({ - type: key === "topHit" ? "topHit" : i.entity, - entity: i.entity, - ...flattenObj(i.object), - }) - ); - } + + value.hits.map(i => + typesArray.push({ + type: key === "topHit" ? "topHit" : i.entity, + entity: i.entity, + ...flattenObj(i.object), + }) + ); + if (typesArray.length > 0) formattedData[key] = typesArray; }); From 97ebcaba493a46b53ad1509beff17bd218a6f3ac Mon Sep 17 00:00:00 2001 From: Chintan Mehta Date: Thu, 30 Jan 2025 12:20:58 +0000 Subject: [PATCH 3/6] feat: top hit item adjusted --- .../components/GlobalSearch/GlobalSearchListItem.jsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/ui/src/components/GlobalSearch/GlobalSearchListItem.jsx b/packages/ui/src/components/GlobalSearch/GlobalSearchListItem.jsx index a5eb71a8e..72925d4a2 100644 --- a/packages/ui/src/components/GlobalSearch/GlobalSearchListItem.jsx +++ b/packages/ui/src/components/GlobalSearch/GlobalSearchListItem.jsx @@ -79,7 +79,7 @@ const TopHitItem = styled("li")(({ theme }) => ({ const TopHitItemContainer = styled("div")(({ theme }) => ({ cursor: "pointer", width: "100%", - padding: `${theme.spacing(1.5)}`, + padding: `${theme.spacing(1.5)} 0`, borderRadius: theme.spacing(1), })); @@ -235,15 +235,14 @@ function GlobalSearchListItem({ item, isTopHit = false, onItemClick }) { return ( <> {symbolNameOrId(item)} - {item.entity === "variant" && item.rsIds.length > 0 && ( - -  ({item.rsIds.join(", ")}) - - )} ); }; + function getVariantRsIds() { + if (item.entity === "variant" && item.rsIds.length > 0) return item.rsIds.join(", "); + } + if (item.type === "recent") { return ; } @@ -312,6 +311,7 @@ function GlobalSearchListItem({ item, isTopHit = false, onItemClick }) { {item.credibleSetsCount > -1 && <>Credible sets count: {item.credibleSetsCount}} + {getVariantRsIds()} {item.hasSumstats && ( From e3f8bf994a0bf92aa68c3af3fe1d653562f1dac0 Mon Sep 17 00:00:00 2001 From: Chintan Mehta Date: Thu, 30 Jan 2025 14:01:00 +0000 Subject: [PATCH 4/6] Update searchUtils.js --- packages/ui/src/components/GlobalSearch/utils/searchUtils.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/ui/src/components/GlobalSearch/utils/searchUtils.js b/packages/ui/src/components/GlobalSearch/utils/searchUtils.js index 3e49056fb..bdb3bd28c 100644 --- a/packages/ui/src/components/GlobalSearch/utils/searchUtils.js +++ b/packages/ui/src/components/GlobalSearch/utils/searchUtils.js @@ -20,7 +20,6 @@ const mapStandardKeys = originalKey => { }; const flattenObj = ob => { - if (!ob) return; const result = {}; Object.entries(ob).forEach(([key, value]) => { @@ -51,8 +50,6 @@ const exceedsArrayLengthLimit = array => { export const formatSearchData = unformattedData => { const formattedData = {}; - // TODO: fix variant search bug - Object.entries(unformattedData).forEach(([key, value]) => { const typesArray = []; From 30920efecc1f7ddc51265b5136a6c331d5a5fc25 Mon Sep 17 00:00:00 2001 From: Chintan Mehta Date: Thu, 30 Jan 2025 14:42:33 +0000 Subject: [PATCH 5/6] search page results added --- .../src/pages/SearchPage/SearchContainer.jsx | 16 ++++++++ .../src/pages/SearchPage/SearchPageQuery.gql | 29 +++++++++----- .../src/pages/SearchPage/StudyResult.jsx | 39 +++++++++++++++++++ 3 files changed, 74 insertions(+), 10 deletions(-) create mode 100644 apps/platform/src/pages/SearchPage/StudyResult.jsx diff --git a/apps/platform/src/pages/SearchPage/SearchContainer.jsx b/apps/platform/src/pages/SearchPage/SearchContainer.jsx index 8f2320a3b..dd39c9f2c 100644 --- a/apps/platform/src/pages/SearchPage/SearchContainer.jsx +++ b/apps/platform/src/pages/SearchPage/SearchContainer.jsx @@ -10,6 +10,7 @@ import { import { makeStyles } from "@mui/styles"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { + faChartBar, faDna, faMapPin, faPrescriptionBottleAlt, @@ -25,6 +26,7 @@ import TargetDetail from "./TargetDetail"; import TargetResult from "./TargetResult"; import VariantDetail from "./VariantDetail"; import VariantResult from "./VariantResult"; +import StudyResult from "./StudyResult"; const getCounts = entities => { const counts = { @@ -83,6 +85,18 @@ const SearchFilters = ({ entities, entitiesCount, setEntity }) => { } /> + } + label={ + <> + + + Study ({counts.study}) + + + } + /> ; if (object[TYPE_NAME] === "Variant") return ; + if (object[TYPE_NAME] === "Study") + return ; return ; })} diff --git a/apps/platform/src/pages/SearchPage/SearchPageQuery.gql b/apps/platform/src/pages/SearchPage/SearchPageQuery.gql index dae95cc9e..d3c05cad2 100644 --- a/apps/platform/src/pages/SearchPage/SearchPageQuery.gql +++ b/apps/platform/src/pages/SearchPage/SearchPageQuery.gql @@ -1,13 +1,5 @@ -query SearchPageQuery( - $queryString: String! - $index: Int! - $entityNames: [String!]! -) { - search( - queryString: $queryString - entityNames: $entityNames - page: { index: $index, size: 10 } - ) { +query SearchPageQuery($queryString: String!, $index: Int!, $entityNames: [String!]!) { + search(queryString: $queryString, entityNames: $entityNames, page: { index: $index, size: 10 }) { total aggregations { entities { @@ -27,6 +19,15 @@ query SearchPageQuery( rsIds } + ... on Study { + id + hasSumstats + traitFromSource + credibleSets { + credibleSetsCount: count + } + } + ... on Target { id approvedSymbol @@ -66,6 +67,14 @@ query SearchPageQuery( label } } + ... on Study { + id + hasSumstats + traitFromSource + credibleSets { + count + } + } ... on Target { id approvedSymbol diff --git a/apps/platform/src/pages/SearchPage/StudyResult.jsx b/apps/platform/src/pages/SearchPage/StudyResult.jsx new file mode 100644 index 000000000..3eb01d5f8 --- /dev/null +++ b/apps/platform/src/pages/SearchPage/StudyResult.jsx @@ -0,0 +1,39 @@ +import { makeStyles, useTheme } from "@mui/styles"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faChartBar } from "@fortawesome/free-solid-svg-icons"; +import { Highlights, Link } from "ui"; +import { Typography } from "@mui/material"; + +const useStyles = makeStyles(theme => ({ + container: { + marginBottom: "30px", + }, + subtitle: { + fontSize: "20px", + fontWeight: 500, + }, + icon: { + color: theme.palette.primary.main, + }, +})); + +function StudyResult({ data, highlights }) { + const classes = useStyles(); + const theme = useTheme(); + + return ( +
+ + <>{data.id} + + + {data.credibleSets.credibleSetsCount > -1 && ( + <>Credible sets count: {data.credibleSets.credibleSetsCount} + )} + + +
+ ); +} + +export default StudyResult; From 16d8dc5839e17d2192d97579506938b1877e2972 Mon Sep 17 00:00:00 2001 From: Chintan Mehta Date: Thu, 30 Jan 2025 15:01:04 +0000 Subject: [PATCH 6/6] search item click --- packages/ui/src/hooks/useListOption.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/ui/src/hooks/useListOption.js b/packages/ui/src/hooks/useListOption.js index 4f7621adc..fed10d1e6 100644 --- a/packages/ui/src/hooks/useListOption.js +++ b/packages/ui/src/hooks/useListOption.js @@ -4,6 +4,8 @@ import { addSearchToLocalStorage } from "../components/GlobalSearch/utils/search function useListOption() { const navigate = useNavigate(); + const entitiesWitAssociations = ["disease", "target"]; + const openListItem = option => { if (!option) return; const newOption = { ...option }; @@ -12,12 +14,10 @@ function useListOption() { if (newOption.entity === "search") { navigate(`/search?q=${newOption.name}&page=1`); - } else if (newOption.entity === "study") { - navigate(`/${newOption.entity}/${newOption.studyId}`); } else { navigate( `/${newOption.entity}/${newOption.id}${ - newOption.entity !== "drug" && newOption.entity !== "variant" ? "/associations" : "" + entitiesWitAssociations.indexOf(newOption.entity) > -1 ? "/associations" : "" }` ); }