diff --git a/frontend/src/api/phenotype-explorer.ts b/frontend/src/api/phenotype-explorer.ts index 4f20ae28c..adb3884a5 100644 --- a/frontend/src/api/phenotype-explorer.ts +++ b/frontend/src/api/phenotype-explorer.ts @@ -50,7 +50,7 @@ export const getPhenotypes = async (search = ""): ReturnType => { : async () => await getPhenotypeAssociations(item.id), highlight: item.highlight, icon: "category-" + item.category, - info: item.in_taxon || "", + info: item.in_taxon_label || "", })), }; }; diff --git a/frontend/src/api/search.ts b/frontend/src/api/search.ts index ab1a9ba25..5fc9cef24 100644 --- a/frontend/src/api/search.ts +++ b/frontend/src/api/search.ts @@ -1,4 +1,5 @@ -import type { SearchResults } from "@/api/model"; +import { groupBy, uniq } from "lodash"; +import type { SearchResult, SearchResults } from "@/api/model"; import { monarch, request } from "./index"; export type Filters = { [key: string]: string[] }; @@ -16,11 +17,34 @@ export const getSearch = async ( limit, ...filters, }); + return response; }; +type DedupedSearchResults = Omit & { + items: (SearchResult & { dupes: string[] })[]; +}; + export const getAutocomplete = async (q: string) => { const url = `${monarch}/autocomplete`; const response = await request(url, { q }); - return response; + + const transformedResponse: DedupedSearchResults = { + ...response, + items: Object.values( + /** consolidate items */ + groupBy( + response.items, + /** by name, case insensitively */ + (item) => item.name.toLowerCase(), + ), + ).map((dupes) => ({ + ...dupes[0], + /** keep list of duplicated names */ + /** de-dupe this list case sensitively */ + dupes: uniq(dupes.map((dupe) => dupe.name)), + })), + }; + + return transformedResponse; }; diff --git a/frontend/src/api/source.d.ts b/frontend/src/api/source.d.ts deleted file mode 100644 index c359855ee..000000000 --- a/frontend/src/api/source.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -/** possible properties of a source on the sources page */ -export type Source = { - id?: string; - name?: string; - type?: "dataset" | "ontology"; - link?: string; - license?: string; - distribution?: string; - date?: string; - image?: string; - description?: string; - usage?: string; - vocabulary?: string; - files?: string[]; -}; diff --git a/frontend/src/components/AppCheckbox.vue b/frontend/src/components/AppCheckbox.vue index 7bdd04dba..6a2b8e9e3 100644 --- a/frontend/src/components/AppCheckbox.vue +++ b/frontend/src/components/AppCheckbox.vue @@ -46,7 +46,7 @@ function onChange(event: Event) { display: inline-flex; position: relative; align-items: center; - padding: 2px 8px; + padding: 5px 10px; gap: 10px; border-radius: $rounded; cursor: pointer; diff --git a/frontend/src/components/AppSelectAutocomplete.vue b/frontend/src/components/AppSelectAutocomplete.vue index 96c8cd793..d662d64ae 100644 --- a/frontend/src/components/AppSelectAutocomplete.vue +++ b/frontend/src/components/AppSelectAutocomplete.vue @@ -308,7 +308,7 @@ watch(highlighted, () => { } .list { - z-index: 1000; + z-index: 1020; max-height: 300px; overflow-x: auto; overflow-y: auto; diff --git a/frontend/src/components/AppSelectMulti.vue b/frontend/src/components/AppSelectMulti.vue index 2f6894382..decb049a7 100644 --- a/frontend/src/components/AppSelectMulti.vue +++ b/frontend/src/components/AppSelectMulti.vue @@ -388,7 +388,7 @@ watch( } .list { - z-index: 1000; + z-index: 1020; max-width: 90vw; max-height: 300px; overflow-x: auto; diff --git a/frontend/src/components/AppSelectSingle.vue b/frontend/src/components/AppSelectSingle.vue index f79f3d965..4976b605c 100644 --- a/frontend/src/components/AppSelectSingle.vue +++ b/frontend/src/components/AppSelectSingle.vue @@ -265,7 +265,7 @@ watch( } .list { - z-index: 1000; + z-index: 1020; position: fixed; max-width: 90vw; max-height: 300px; diff --git a/frontend/src/pages/about/PageCite.vue b/frontend/src/pages/about/PageCite.vue index d1ed59f67..53262d39e 100644 --- a/frontend/src/pages/about/PageCite.vue +++ b/frontend/src/pages/about/PageCite.vue @@ -82,7 +82,7 @@ To link to a specific page or to algorithmic results presented on this website, please use the URL in your browser's address bar. For example, you would cite the prefixed identifier - OMIM:154700 + OMIM:154700 as:

diff --git a/frontend/src/pages/about/PageTerms.vue b/frontend/src/pages/about/PageTerms.vue index 8e29d76b2..fa49271dc 100644 --- a/frontend/src/pages/about/PageTerms.vue +++ b/frontend/src/pages/about/PageTerms.vue @@ -17,9 +17,10 @@ >3-Clause BSD License. Licensing information for the data sources and ontologies that make up the Monarch knowledge graph can be found on the - sources page. Licensing information for - tools, APIs, algorithms, and workflows can be found on the - overview page. + sources page. Licensing information for tools, APIs, algorithms, and workflows can be + found on the overview page.

Tracking

diff --git a/frontend/src/pages/explore/TabPhenotypeExplorer.vue b/frontend/src/pages/explore/TabPhenotypeExplorer.vue index 1f5ac504f..70f8d72d8 100644 --- a/frontend/src/pages/explore/TabPhenotypeExplorer.vue +++ b/frontend/src/pages/explore/TabPhenotypeExplorer.vue @@ -54,6 +54,7 @@ v-if="bMode.id.includes('these phenotypes')" text="Analyze" icon="bars-progress" + :disabled="isLoading || !aPhenotypes.length || !bPhenotypes.length" @click="runAnalysis" /> - + + Results + Running analysis Error running analysis @@ -132,7 +135,9 @@ import type { Option, Options } from "@/components/AppSelectTags.vue"; import AppSelectTags from "@/components/AppSelectTags.vue"; import ThePhenogrid from "@/components/ThePhenogrid.vue"; import { snackbar } from "@/components/TheSnackbar.vue"; +import { scrollToElement } from "@/router"; import { useQuery } from "@/util/composables"; +import { waitFor } from "@/util/dom"; import { parse } from "@/util/object"; import examples from "./phenotype-explorer.json"; @@ -207,6 +212,8 @@ const { isError, } = useQuery( async function () { + scrollToResults(); + // /** run appropriate analysis based on selected mode */ // if (bMode.value.id.includes("these phenotypes")) return await compareSetToSet( @@ -222,8 +229,15 @@ const { /** default value */ { summary: [], phenogrid: { cols: [], rows: [], cells: {}, unmatched: [] } }, + + scrollToResults, ); +/** scroll results into view */ +async function scrollToResults() { + scrollToElement(await waitFor("#results")); +} + /** when multi select component runs spread options function */ function spreadOptions(option: Option, options: Options, set: string) { /** notify */ diff --git a/frontend/src/pages/explore/TabSearch.vue b/frontend/src/pages/explore/TabSearch.vue index da783f842..83222b196 100644 --- a/frontend/src/pages/explore/TabSearch.vue +++ b/frontend/src/pages/explore/TabSearch.vue @@ -186,9 +186,11 @@ async function runGetAutocomplete( /** if something typed in, get autocomplete options from backend */ if (search.trim()) return (await getAutocomplete(search)).items.map((item) => ({ - label: item.name, - icon: getCategoryIcon(item.category), + label: item.name.toLowerCase(), tooltip: "", + info: + /** show duplicates for gene symbols */ + item.name === item.symbol ? item.dupes.join(" / ") : undefined, })); /** @@ -368,7 +370,7 @@ watch(search, async () => { const query: { [key: string]: string } = {}; if (search.value) query.search = search.value; /** navigate to explore page */ - await router.push({ ...route, name: "Explore", query }); + await router.push({ ...route, name: "Explore", query, hash: "#search" }); }); /** when start page changes */ diff --git a/frontend/src/pages/node/AssociationsSummary.vue b/frontend/src/pages/node/AssociationsSummary.vue index 6babfbd82..9de8b4138 100644 --- a/frontend/src/pages/node/AssociationsSummary.vue +++ b/frontend/src/pages/node/AssociationsSummary.vue @@ -21,7 +21,7 @@ :key="index" class="result" > - + - -