Skip to content

Commit

Permalink
feat(search): pre-select explorer entities if they appear in search q…
Browse files Browse the repository at this point in the history
…uery
  • Loading branch information
marcelgerber committed Apr 15, 2024
1 parent d46ddf7 commit f0346a3
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 35 deletions.
8 changes: 7 additions & 1 deletion baker/algolia/configureAlgolia.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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
Expand Down Expand Up @@ -164,6 +169,7 @@ export const configureAlgolia = async () => {
attributeForDistinct: "explorerSlug",
distinct: 4,
minWordSizefor1Typo: 6,
optionalWords: allCountryNamesAndVariants,
})

const synonyms = [
Expand Down
120 changes: 86 additions & 34 deletions site/search/SearchPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import {
sortBy,
groupBy,
uniqBy,
EntityName,
Url,
Region,
} from "@ourworldindata/utils"
import {
InstantSearch,
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -155,7 +175,11 @@ interface GroupedExplorerViews {
const getNumberOfExplorerHits = (rawHits: IExplorerViewHit[]) =>
uniqBy(rawHits, "explorerSlug").length

function ExplorerViewHits() {
function ExplorerViewHits({
countriesRegionsToSelect,
}: {
countriesRegionsToSelect?: Region[]
}) {
const { hits } = useHits<IExplorerViewHit>()

const groupedHits = useMemo(() => {
Expand Down Expand Up @@ -193,6 +217,7 @@ function ExplorerViewHits() {
groupedHit={group}
key={group.explorerSlug}
cardPosition={i}
countriesRegionsToSelect={countriesRegionsToSelect}
/>
))}
</div>
Expand All @@ -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,
Expand Down Expand Up @@ -242,38 +278,52 @@ function ExplorerHit({
</a>
</div>
<ul className="search-results__explorer-views-list grid grid-cols-2 grid-sm-cols-1">
{groupedHit.views.map((view) => (
<li
key={view.objectID}
className="ais-Hits-item search-results__explorer-view"
>
<a
data-algolia-index={getIndexName(
SearchIndexName.ExplorerViews
)}
data-algolia-object-id={view.objectID}
data-algolia-position={view.hitPositionOverall + 1}
data-algolia-card-position={cardPosition + 1}
data-algolia-position-within-card={
view.hitPositionWithinCard + 1
}
data-algolia-event-name="click_explorer_view"
href={`${BAKED_BASE_URL}/${EXPLORERS_ROUTE_FOLDER}/${view.explorerSlug}${view.viewQueryParams}`}
className="search-results__explorer-view-title-container"
{groupedHit.views.map((view) => {
const entitiesToSelectExcludingViewTitle =
entitiesToSelectExcludingExplorerTitle?.filter(
(e) =>
!view.viewTitle.includes(e.name) &&
!view.explorerTitle.includes(e.name)
)
const queryStr = getEntityQueryStr(
entitiesToSelectExcludingViewTitle?.map((e) => e.name),
view.viewQueryParams
)
return (
<li
key={view.objectID}
className="ais-Hits-item search-results__explorer-view"
>
<Highlight
attribute="viewTitle"
hit={view}
highlightedTagName="strong"
className="search-results__explorer-view-title"
/>
<FontAwesomeIcon icon={faArrowRight} />
</a>
<p className="body-3-medium-italic search-results__explorer-view-subtitle">
{view.viewSubtitle}
</p>
</li>
))}
<a
data-algolia-index={getIndexName(
SearchIndexName.ExplorerViews
)}
data-algolia-object-id={view.objectID}
data-algolia-position={
view.hitPositionOverall + 1
}
data-algolia-card-position={cardPosition + 1}
data-algolia-position-within-card={
view.hitPositionWithinCard + 1
}
data-algolia-event-name="click_explorer_view"
href={`${BAKED_BASE_URL}/${EXPLORERS_ROUTE_FOLDER}/${view.explorerSlug}${queryStr}`}
className="search-results__explorer-view-title-container"
>
<Highlight
attribute="viewTitle"
hit={view}
highlightedTagName="strong"
className="search-results__explorer-view-title"
/>
<FontAwesomeIcon icon={faArrowRight} />
</a>
<p className="body-3-medium-italic search-results__explorer-view-subtitle">
{view.viewSubtitle}
</p>
</li>
)
})}
</ul>
<a
className="search-results__explorer-hit-link-mobile hide-sm-up"
Expand Down Expand Up @@ -639,7 +689,9 @@ const SearchResults = (props: SearchResultsProps) => {
) => getNumberOfExplorerHits(results.hits)}
/>
</header>
<ExplorerViewHits />
<ExplorerViewHits
countriesRegionsToSelect={searchQueryRegionsMatches}
/>
</section>
</NoResultsBoundary>
</Index>
Expand Down

0 comments on commit f0346a3

Please sign in to comment.