From 8d6c5c0ab3f6cf5fa4fc91aaccd0d8caf27e0767 Mon Sep 17 00:00:00 2001 From: Marcel Gerber Date: Thu, 11 Apr 2024 18:16:14 +0200 Subject: [PATCH] feat(search): pre-select explorer entities if they appear in search query --- baker/algolia/configureAlgolia.ts | 8 +- site/search/SearchPanel.tsx | 120 +++++++++++++++++++++--------- 2 files changed, 93 insertions(+), 35 deletions(-) diff --git a/baker/algolia/configureAlgolia.ts b/baker/algolia/configureAlgolia.ts index 25e9abca2b1..c83ae4d15b0 100644 --- a/baker/algolia/configureAlgolia.ts +++ b/baker/algolia/configureAlgolia.ts @@ -9,7 +9,7 @@ import { ALGOLIA_INDEXING, ALGOLIA_SECRET_KEY, } from "../../settings/serverSettings.js" -import { countries } from "@ourworldindata/utils" +import { countries, regions } from "@ourworldindata/utils" import { SearchIndexName } from "../../site/search/searchTypes.js" import { getIndexName } from "../../site/search/searchClient.js" @@ -25,6 +25,11 @@ export const getAlgoliaClient = (): SearchClient | undefined => { return client } +const allCountryNamesAndVariants = regions.flatMap((region) => [ + region.name, + ...(("variantNames" in region && region.variantNames) || []), +]) + // This function initializes and applies settings to the Algolia search indices // Algolia settings should be configured here rather than in the Algolia dashboard UI, as then // they are recorded and transferrable across dev/prod instances @@ -164,6 +169,7 @@ export const configureAlgolia = async () => { attributeForDistinct: "explorerSlug", distinct: 4, minWordSizefor1Typo: 6, + optionalWords: allCountryNamesAndVariants, }) const synonyms = [ diff --git a/site/search/SearchPanel.tsx b/site/search/SearchPanel.tsx index 4d9f85c866b..6ac82a8c3bc 100644 --- a/site/search/SearchPanel.tsx +++ b/site/search/SearchPanel.tsx @@ -10,6 +10,9 @@ import { sortBy, groupBy, uniqBy, + EntityName, + Url, + Region, } from "@ourworldindata/utils" import { InstantSearch, @@ -61,6 +64,7 @@ import { import { DEFAULT_GRAPHER_HEIGHT, DEFAULT_GRAPHER_WIDTH, + setSelectedEntityNamesParam, } from "@ourworldindata/grapher" import type { SearchResults as AlgoliaSearchResultsType } from "algoliasearch-helper" import { SiteAnalytics } from "../SiteAnalytics.js" @@ -95,6 +99,22 @@ function PagesHit({ hit }: { hit: IPageHit }) { ) } +const getEntityQueryStr = ( + entities: EntityName[] | null | undefined, + existingQueryStr: string = "" +) => { + if (!entities?.length) return existingQueryStr + else { + return setSelectedEntityNamesParam( + // If we have any entities pre-selected, we want to show the chart tab + Url.fromQueryStr(existingQueryStr).updateQueryParams({ + tab: "chart", + }), + entities + ).queryStr + } +} + function ChartHit({ hit }: { hit: IChartHit }) { const [imgLoaded, setImgLoaded] = useState(false) const [imgError, setImgError] = useState(false) @@ -155,7 +175,11 @@ interface GroupedExplorerViews { const getNumberOfExplorerHits = (rawHits: IExplorerViewHit[]) => uniqBy(rawHits, "explorerSlug").length -function ExplorerViewHits() { +function ExplorerViewHits({ + countriesRegionsToSelect, +}: { + countriesRegionsToSelect?: Region[] +}) { const { hits } = useHits() const groupedHits = useMemo(() => { @@ -193,6 +217,7 @@ function ExplorerViewHits() { groupedHit={group} key={group.explorerSlug} cardPosition={i} + countriesRegionsToSelect={countriesRegionsToSelect} /> ))} @@ -203,14 +228,25 @@ function ExplorerViewHits() { function ExplorerHit({ groupedHit, cardPosition, + countriesRegionsToSelect, }: { groupedHit: GroupedExplorerViews cardPosition: number + countriesRegionsToSelect?: Region[] }) { const firstHit = groupedHit.views[0] + // If the explorer title contains something like "Ukraine" already, don't bother selecting Ukraine in it + const entitiesToSelectExcludingExplorerTitle = + countriesRegionsToSelect?.filter( + (e) => !groupedHit.explorerTitle.includes(e.name) + ) + const queryStr = getEntityQueryStr( + entitiesToSelectExcludingExplorerTitle?.map((e) => e.name) + ) + const exploreAllProps = { - href: `${BAKED_BASE_URL}/${EXPLORERS_ROUTE_FOLDER}/${groupedHit.explorerSlug}`, + href: `${BAKED_BASE_URL}/${EXPLORERS_ROUTE_FOLDER}/${groupedHit.explorerSlug}${queryStr}`, "data-algolia-index": getIndexName(SearchIndexName.ExplorerViews), "data-algolia-object-id": firstHit.objectID, "data-algolia-position": firstHit.hitPositionOverall, @@ -242,38 +278,52 @@ function ExplorerHit({ { ) => getNumberOfExplorerHits(results.hits)} /> - +