docs: remove custom searching mechanism (#11984)
* docs: remove custom searching mechanism * remove grouping * changes to grouping * small title change * update resources sitemap
This commit is contained in:
1 parent
87b75ea959
commit
c96560ccb7
10 files changed
+316
-250
No files matched your search
@@ -21,8 +21,14 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
|||||||
apiKey: process.env.NEXT_PUBLIC_ALGOLIA_API_KEY || "temp",
|
apiKey: process.env.NEXT_PUBLIC_ALGOLIA_API_KEY || "temp",
|
||||||
mainIndexName: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
mainIndexName: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
||||||
indices: [
|
indices: [
|
||||||
process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
{
|
||||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
name: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
||||||
|
title: "Store & Admin API",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
||||||
|
title: "Docs",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
searchProps={{
|
searchProps={{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: `${pageNumber} Module Link`,
|
title: `${pageNumber} Define Module Link`,
|
||||||
}
|
}
|
||||||
|
|
||||||
# {metadata.title}
|
# {metadata.title}
|
||||||
|
|||||||
@@ -16,8 +16,14 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
|||||||
mainIndexName:
|
mainIndexName:
|
||||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
||||||
indices: [
|
indices: [
|
||||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
{
|
||||||
process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
name: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
||||||
|
title: "Docs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
||||||
|
title: "Store & Admin API",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
searchProps={{
|
searchProps={{
|
||||||
|
|||||||
@@ -5,9 +5,54 @@ import { config } from "../config"
|
|||||||
import { basePathUrl } from "../utils/base-path-url"
|
import { basePathUrl } from "../utils/base-path-url"
|
||||||
|
|
||||||
export default function sitemap(): MetadataRoute.Sitemap {
|
export default function sitemap(): MetadataRoute.Sitemap {
|
||||||
return retrieveMdxPages({
|
const items = retrieveMdxPages({
|
||||||
basePath: path.resolve("app"),
|
basePath: path.resolve("app"),
|
||||||
}).map((filePath) => ({
|
}).map((filePath) => ({
|
||||||
url: `${config.baseUrl}${basePathUrl(filePath)}`,
|
url: `${config.baseUrl}${basePathUrl(filePath)}`,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// add some references
|
||||||
|
items.push(
|
||||||
|
{
|
||||||
|
url: `${config.baseUrl}${basePathUrl("/references/file-provider-module")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${config.baseUrl}${basePathUrl("/references/file-service")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${config.baseUrl}${basePathUrl("/references/locking-module-provider")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${config.baseUrl}${basePathUrl("/references/locking-service")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${config.baseUrl}${basePathUrl("/references/notification-provider-module")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${config.baseUrl}${basePathUrl("/references/notification-service")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${config.baseUrl}${basePathUrl("/references/event-service")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${config.baseUrl}${basePathUrl("/references/cache-service")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${config.baseUrl}${basePathUrl("/references/file-service")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${config.baseUrl}${basePathUrl("/references/auth/provider")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${config.baseUrl}${basePathUrl("/references/fulfillment/provider")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${config.baseUrl}${basePathUrl("/references/tax/provider")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${config.baseUrl}${basePathUrl("/references/payment/provider")}`,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return items
|
||||||
}
|
}
|
||||||
@@ -16,8 +16,14 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
|||||||
mainIndexName:
|
mainIndexName:
|
||||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
||||||
indices: [
|
indices: [
|
||||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
{
|
||||||
process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
name: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
||||||
|
title: "Docs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
||||||
|
title: "Store & Admin API",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
searchProps={{
|
searchProps={{
|
||||||
|
|||||||
@@ -16,8 +16,14 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
|||||||
mainIndexName:
|
mainIndexName:
|
||||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
||||||
indices: [
|
indices: [
|
||||||
process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
{
|
||||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
name: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
||||||
|
title: "Docs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
||||||
|
title: "Store & Admin API",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
searchProps={{
|
searchProps={{
|
||||||
|
|||||||
@@ -16,8 +16,14 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
|||||||
mainIndexName:
|
mainIndexName:
|
||||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
||||||
indices: [
|
indices: [
|
||||||
process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
{
|
||||||
process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
name: process.env.NEXT_PUBLIC_DOCS_ALGOLIA_INDEX_NAME || "temp",
|
||||||
|
title: "Docs",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: process.env.NEXT_PUBLIC_API_ALGOLIA_INDEX_NAME || "temp",
|
||||||
|
title: "Store & Admin API",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
searchProps={{
|
searchProps={{
|
||||||
|
|||||||
@@ -11,9 +11,8 @@ import {
|
|||||||
useInstantSearch,
|
useInstantSearch,
|
||||||
} from "react-instantsearch"
|
} from "react-instantsearch"
|
||||||
import { SearchNoResult } from "../NoResults"
|
import { SearchNoResult } from "../NoResults"
|
||||||
import { SearchHitGroupName } from "./GroupName"
|
import { AlgoliaIndex, useSearch } from "@/providers"
|
||||||
import { useSearch } from "@/providers"
|
import { Link, SearchHitGroupName } from "@/components"
|
||||||
import { Link } from "@/components"
|
|
||||||
|
|
||||||
export type Hierarchy = "lvl0" | "lvl1" | "lvl2" | "lvl3" | "lvl4" | "lvl5"
|
export type Hierarchy = "lvl0" | "lvl1" | "lvl2" | "lvl3" | "lvl4" | "lvl5"
|
||||||
|
|
||||||
@@ -43,7 +42,7 @@ export type GroupedHitType = {
|
|||||||
|
|
||||||
export type SearchHitWrapperProps = {
|
export type SearchHitWrapperProps = {
|
||||||
configureProps: ConfigureProps
|
configureProps: ConfigureProps
|
||||||
indices: string[]
|
indices: AlgoliaIndex[]
|
||||||
} & Omit<SearchHitsProps, "indexName" | "setNoResults">
|
} & Omit<SearchHitsProps, "indexName" | "setNoResults">
|
||||||
|
|
||||||
export type IndexResults = {
|
export type IndexResults = {
|
||||||
@@ -57,8 +56,8 @@ export const SearchHitsWrapper = ({
|
|||||||
}: SearchHitWrapperProps) => {
|
}: SearchHitWrapperProps) => {
|
||||||
const { status } = useInstantSearch()
|
const { status } = useInstantSearch()
|
||||||
const [hasNoResults, setHashNoResults] = useState<IndexResults>({
|
const [hasNoResults, setHashNoResults] = useState<IndexResults>({
|
||||||
[indices[0]]: false,
|
[indices[0].name]: false,
|
||||||
[indices[1]]: false,
|
[indices[1].name]: false,
|
||||||
})
|
})
|
||||||
const showNoResults = useMemo(() => {
|
const showNoResults = useMemo(() => {
|
||||||
return Object.values(hasNoResults).every((value) => value === true)
|
return Object.values(hasNoResults).every((value) => value === true)
|
||||||
@@ -74,11 +73,14 @@ export const SearchHitsWrapper = ({
|
|||||||
return (
|
return (
|
||||||
<div className="h-full overflow-auto px-docs_0.5">
|
<div className="h-full overflow-auto px-docs_0.5">
|
||||||
{status !== "loading" && showNoResults && <SearchNoResult />}
|
{status !== "loading" && showNoResults && <SearchNoResult />}
|
||||||
{indices.map((indexName, index) => (
|
{indices.map((index, key) => (
|
||||||
// @ts-expect-error React v19 doesn't see this type as a React element
|
// @ts-expect-error React v19 doesn't see this type as a React element
|
||||||
<Index indexName={indexName} key={index}>
|
<Index indexName={index.name} key={key}>
|
||||||
|
{!hasNoResults[index.name] && (
|
||||||
|
<SearchHitGroupName name={index.title} />
|
||||||
|
)}
|
||||||
<SearchHits
|
<SearchHits
|
||||||
indexName={indexName}
|
indexName={index.name}
|
||||||
setNoResults={setNoResults}
|
setNoResults={setNoResults}
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
@@ -104,30 +106,6 @@ export const SearchHits = ({
|
|||||||
const { status } = useInstantSearch()
|
const { status } = useInstantSearch()
|
||||||
const { setIsOpen } = useSearch()
|
const { setIsOpen } = useSearch()
|
||||||
|
|
||||||
// group by lvl0
|
|
||||||
const grouped: GroupedHitType = useMemo(() => {
|
|
||||||
const grouped: GroupedHitType = {}
|
|
||||||
hits.forEach((hit) => {
|
|
||||||
if (hit.hierarchy.lvl0) {
|
|
||||||
if (!grouped[hit.hierarchy.lvl0]) {
|
|
||||||
grouped[hit.hierarchy.lvl0] = []
|
|
||||||
}
|
|
||||||
grouped[hit.hierarchy.lvl0].push(hit)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// sort groups by number of hits
|
|
||||||
const sortedGroups = Object.fromEntries(
|
|
||||||
Object.entries(grouped).sort(([, a], [, b]) => {
|
|
||||||
const lvl1CountA = a.filter((hit) => hit.type === "lvl1").length
|
|
||||||
const lvl1CountB = b.filter((hit) => hit.type === "lvl1").length
|
|
||||||
|
|
||||||
return lvl1CountB - lvl1CountA
|
|
||||||
})
|
|
||||||
)
|
|
||||||
return sortedGroups
|
|
||||||
}, [hits])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (status !== "loading" && status !== "stalled") {
|
if (status !== "loading" && status !== "stalled") {
|
||||||
setNoResults(indexName, hits.length === 0)
|
setNoResults(indexName, hits.length === 0)
|
||||||
@@ -149,76 +127,71 @@ export const SearchHits = ({
|
|||||||
"[&_mark]:text-medusa-fg-interactive"
|
"[&_mark]:text-medusa-fg-interactive"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{Object.keys(grouped).map((groupName, index) => (
|
{hits.map((item, index) => {
|
||||||
<Fragment key={index}>
|
const hierarchies = Object.values(item.hierarchy)
|
||||||
<SearchHitGroupName name={groupName} />
|
.filter(Boolean)
|
||||||
{grouped[groupName].map((item, index) => {
|
.join(" › ")
|
||||||
const hierarchies = Object.values(item.hierarchy)
|
return (
|
||||||
.filter(Boolean)
|
<div
|
||||||
.join(" › ")
|
className={clsx(
|
||||||
return (
|
"gap-docs_0.25 relative flex flex-1 flex-col p-docs_0.5",
|
||||||
<div
|
"overflow-x-hidden text-ellipsis whitespace-nowrap break-words",
|
||||||
className={clsx(
|
"hover:bg-medusa-bg-base-hover",
|
||||||
"gap-docs_0.25 relative flex flex-1 flex-col p-docs_0.5",
|
"focus:bg-medusa-bg-base-hover",
|
||||||
"overflow-x-hidden text-ellipsis whitespace-nowrap break-words",
|
"focus:outline-none"
|
||||||
"hover:bg-medusa-bg-base-hover",
|
)}
|
||||||
"focus:bg-medusa-bg-base-hover",
|
key={index}
|
||||||
"last:mb-docs_1 focus:outline-none"
|
tabIndex={index}
|
||||||
)}
|
data-hit
|
||||||
key={index}
|
onClick={(e) => {
|
||||||
tabIndex={index}
|
const target = e.target as Element
|
||||||
data-hit
|
if (target.tagName.toLowerCase() === "div") {
|
||||||
onClick={(e) => {
|
target.querySelector("a")?.click()
|
||||||
const target = e.target as Element
|
}
|
||||||
if (target.tagName.toLowerCase() === "div") {
|
}}
|
||||||
target.querySelector("a")?.click()
|
>
|
||||||
}
|
<span
|
||||||
}}
|
className={clsx(
|
||||||
>
|
"text-compact-small-plus text-medusa-fg-base",
|
||||||
<span
|
"max-w-full"
|
||||||
className={clsx(
|
)}
|
||||||
"text-compact-small-plus text-medusa-fg-base",
|
>
|
||||||
"max-w-full"
|
{/* @ts-expect-error React v19 doesn't see this type as a React element */}
|
||||||
)}
|
<Snippet attribute={"hierarchy.lvl1"} hit={item} />
|
||||||
>
|
</span>
|
||||||
|
<span className="text-compact-small text-medusa-fg-subtle text-ellipsis overflow-hidden">
|
||||||
|
{item.type === "content" && (
|
||||||
|
<>
|
||||||
{/* @ts-expect-error React v19 doesn't see this type as a React element */}
|
{/* @ts-expect-error React v19 doesn't see this type as a React element */}
|
||||||
<Snippet attribute={"hierarchy.lvl1"} hit={item} />
|
<Snippet attribute={"content"} hit={item} />
|
||||||
</span>
|
</>
|
||||||
<span className="text-compact-small text-medusa-fg-subtle text-ellipsis overflow-hidden">
|
)}
|
||||||
{item.type === "content" && (
|
{item.type !== "content" && item.description}
|
||||||
<>
|
</span>
|
||||||
{/* @ts-expect-error React v19 doesn't see this type as a React element */}
|
|
||||||
<Snippet attribute={"content"} hit={item} />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{item.type !== "content" && item.description}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span
|
<span
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"text-ellipsis overflow-hidden",
|
"text-ellipsis overflow-hidden",
|
||||||
"text-medusa-fg-muted items-center text-compact-x-small"
|
"text-medusa-fg-muted items-center text-compact-x-small"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{hierarchies}
|
{hierarchies}
|
||||||
</span>
|
</span>
|
||||||
<Link
|
<Link
|
||||||
href={item.url}
|
href={item.url}
|
||||||
className="absolute top-0 left-0 h-full w-full"
|
className="absolute top-0 left-0 h-full w-full"
|
||||||
target="_self"
|
target="_self"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
if (checkIfInternal(item.url)) {
|
if (checkIfInternal(item.url)) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
window.location.href = item.url
|
window.location.href = item.url
|
||||||
setIsOpen(false)
|
setIsOpen(false)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</Fragment>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -159,6 +159,7 @@ export const Search = ({
|
|||||||
// to be applied between the items.
|
// to be applied between the items.
|
||||||
facetFilters: [facetFilters],
|
facetFilters: [facetFilters],
|
||||||
getRankingInfo: true,
|
getRankingInfo: true,
|
||||||
|
hitsPerPage: 3,
|
||||||
}}
|
}}
|
||||||
indices={algolia.indices}
|
indices={algolia.indices}
|
||||||
checkInternalPattern={checkInternalPattern}
|
checkInternalPattern={checkInternalPattern}
|
||||||
|
|||||||
@@ -13,14 +13,10 @@ import { checkArraySameElms } from "../../utils"
|
|||||||
import {
|
import {
|
||||||
liteClient as algoliasearch,
|
liteClient as algoliasearch,
|
||||||
LiteClient as SearchClient,
|
LiteClient as SearchClient,
|
||||||
type SearchResponses,
|
|
||||||
type SearchHits,
|
|
||||||
SearchResponse,
|
|
||||||
} from "algoliasearch/lite"
|
} from "algoliasearch/lite"
|
||||||
import clsx from "clsx"
|
import clsx from "clsx"
|
||||||
// @ts-expect-error can't install the types package because it doesn't support React v19
|
// @ts-expect-error can't install the types package because it doesn't support React v19
|
||||||
import { CSSTransition, SwitchTransition } from "react-transition-group"
|
import { CSSTransition, SwitchTransition } from "react-transition-group"
|
||||||
import { searchFilters } from "../.."
|
|
||||||
|
|
||||||
export type SearchCommand = {
|
export type SearchCommand = {
|
||||||
name: string
|
name: string
|
||||||
@@ -46,11 +42,16 @@ export type SearchContextType = {
|
|||||||
|
|
||||||
const SearchContext = createContext<SearchContextType | null>(null)
|
const SearchContext = createContext<SearchContextType | null>(null)
|
||||||
|
|
||||||
|
export type AlgoliaIndex = {
|
||||||
|
name: string
|
||||||
|
title: string
|
||||||
|
}
|
||||||
|
|
||||||
export type AlgoliaProps = {
|
export type AlgoliaProps = {
|
||||||
appId: string
|
appId: string
|
||||||
apiKey: string
|
apiKey: string
|
||||||
mainIndexName: string
|
mainIndexName: string
|
||||||
indices: string[]
|
indices: AlgoliaIndex[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SearchProviderProps = {
|
export type SearchProviderProps = {
|
||||||
@@ -83,154 +84,170 @@ export const SearchProvider = ({
|
|||||||
const algoliaClient = algoliasearch(algolia.appId, algolia.apiKey)
|
const algoliaClient = algoliasearch(algolia.appId, algolia.apiKey)
|
||||||
return {
|
return {
|
||||||
...algoliaClient,
|
...algoliaClient,
|
||||||
async search(searchParams) {
|
// async search(searchParams) {
|
||||||
const requests =
|
// const requests =
|
||||||
"requests" in searchParams ? searchParams.requests : searchParams
|
// "requests" in searchParams ? searchParams.requests : searchParams
|
||||||
// always send this request, which is the main request with no filters
|
// // always send this request, which is the main request with no filters
|
||||||
const mainRequest = requests[0]
|
// const mainRequest = requests[0]
|
||||||
const params = (mainRequest.params || {}) as Record<string, unknown>
|
// const params = (mainRequest.params || {}) as Record<string, unknown>
|
||||||
if (!params.query) {
|
// if (!params.query) {
|
||||||
return Promise.resolve({
|
// return Promise.resolve({
|
||||||
results: requests.map(() => ({
|
// results: requests.map(() => ({
|
||||||
hits: [],
|
// hits: [],
|
||||||
nbHits: 0,
|
// nbHits: 0,
|
||||||
nbPages: 0,
|
// nbPages: 0,
|
||||||
page: 0,
|
// page: 0,
|
||||||
processingTimeMS: 0,
|
// processingTimeMS: 0,
|
||||||
hitsPerPage: 0,
|
// hitsPerPage: 0,
|
||||||
exhaustiveNbHits: false,
|
// exhaustiveNbHits: false,
|
||||||
query: "",
|
// query: "",
|
||||||
params: "",
|
// params: "",
|
||||||
})),
|
// })),
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
|
|
||||||
// retrieve only requests that have filters
|
// // retrieve only requests that have filters
|
||||||
// this is to ensure that we show no result if no filter is selected
|
// // this is to ensure that we show no result if no filter is selected
|
||||||
const requestsWithFilters = requests.filter((item) => {
|
// const requestsWithFilters = requests.filter((item) => {
|
||||||
if (
|
// if (
|
||||||
!item.params ||
|
// !item.params ||
|
||||||
typeof item.params !== "object" ||
|
// typeof item.params !== "object" ||
|
||||||
!("facetFilters" in item.params)
|
// !("facetFilters" in item.params)
|
||||||
) {
|
// ) {
|
||||||
return false
|
// return false
|
||||||
}
|
// }
|
||||||
|
|
||||||
const facetFilters = item.params.facetFilters as string[]
|
// const facetFilters = item.params.facetFilters as string[]
|
||||||
|
|
||||||
// if no tag filters are specified, there's still one item,
|
// // if no tag filters are specified, there's still one item,
|
||||||
// which is an empty array
|
// // which is an empty array
|
||||||
return facetFilters.length >= 1 && facetFilters[0].length > 0
|
// return facetFilters.length >= 1 && facetFilters[0].length > 0
|
||||||
})
|
// })
|
||||||
|
|
||||||
// check whether a query is entered in the search box
|
// // check whether a query is entered in the search box
|
||||||
const noQueries = requestsWithFilters.every(
|
// const noQueries = requestsWithFilters.every(
|
||||||
(item) =>
|
// (item) =>
|
||||||
!item.facetQuery &&
|
// !item.facetQuery &&
|
||||||
(!item.params ||
|
// (!item.params ||
|
||||||
typeof item.params !== "object" ||
|
// typeof item.params !== "object" ||
|
||||||
!("query" in item.params) ||
|
// !("query" in item.params) ||
|
||||||
!item.params.query)
|
// !item.params.query)
|
||||||
)
|
// )
|
||||||
|
|
||||||
const newRequests: typeof requestsWithFilters = [mainRequest]
|
// const newRequests: typeof requestsWithFilters = [mainRequest]
|
||||||
if (!noQueries) {
|
// if (!noQueries) {
|
||||||
// split requests per tags
|
// // split requests per tags
|
||||||
for (const request of requestsWithFilters) {
|
// for (const request of requestsWithFilters) {
|
||||||
const params = request.params as Record<string, unknown>
|
// const params = request.params as Record<string, unknown>
|
||||||
const facetFilters = (params.facetFilters as string[][])[0]
|
// const facetFilters = (params.facetFilters as string[][])[0]
|
||||||
|
|
||||||
// if only one tag is selected, keep the request as-is
|
// // if only one tag is selected, keep the request as-is
|
||||||
if (facetFilters.length === 1) {
|
// if (facetFilters.length === 1) {
|
||||||
newRequests.push(request)
|
// newRequests.push(request)
|
||||||
|
|
||||||
continue
|
// continue
|
||||||
}
|
// }
|
||||||
|
|
||||||
// if multiple tags are selected, split the tags
|
// // if multiple tags are selected, split the tags
|
||||||
// to retrieve a small subset of results per each tag.
|
// // to retrieve a small subset of results per each tag.
|
||||||
newRequests.push(
|
// newRequests.push(
|
||||||
...facetFilters.map((tag) => {
|
// ...facetFilters.map((tag) => {
|
||||||
// get the filter's details in case it has custom hitsPerPage
|
// // get the filter's details in case it has custom hitsPerPage
|
||||||
const filterDetails = searchFilters.find(
|
// const filterDetails = searchFilters.find(
|
||||||
(item) => `_tags:${item.value}` === tag
|
// (item) => `_tags:${item.value}` === tag
|
||||||
)
|
// )
|
||||||
return {
|
// return {
|
||||||
...request,
|
// ...request,
|
||||||
params: {
|
// params: {
|
||||||
...params,
|
// ...params,
|
||||||
facetFilters: [tag],
|
// facetFilters: [tag],
|
||||||
},
|
// },
|
||||||
hitsPerPage: filterDetails?.hitsPerPage || 3,
|
// hitsPerPage: filterDetails?.hitsPerPage || 3,
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return algoliaClient
|
// return algoliaClient
|
||||||
.search<SearchHits>(newRequests)
|
// .search<ExpandedHits>(newRequests)
|
||||||
.then((response) => {
|
// .then((response) => {
|
||||||
if (newRequests.length === 1) {
|
// if (newRequests.length === 1) {
|
||||||
return response
|
// return response
|
||||||
}
|
// }
|
||||||
// combine results of the same index and return the results
|
// // combine results of the same index and return the results
|
||||||
const resultsByIndex: {
|
// const resultsByIndex: {
|
||||||
[indexName: string]: SearchResponse<SearchHits>
|
// [indexName: string]: SearchResponse<ExpandedHits>
|
||||||
} = {}
|
// } = {}
|
||||||
// extract the response of the main request
|
// // extract the response of the main request
|
||||||
const mainResult = response.results[0]
|
// const mainResult = response.results[0]
|
||||||
|
|
||||||
response.results.forEach((result, indexNum) => {
|
// response.results.forEach((result, indexNum) => {
|
||||||
if (indexNum === 0) {
|
// if (indexNum === 0) {
|
||||||
// ignore the main request's result
|
// // ignore the main request's result
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
const resultIndex = "index" in result ? result.index : undefined
|
// const resultIndex = "index" in result ? result.index : undefined
|
||||||
const resultHits = "hits" in result ? result.hits : []
|
// const resultHits = "hits" in result ? result.hits : []
|
||||||
|
|
||||||
if (!resultIndex) {
|
// if (!resultIndex) {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
resultsByIndex[resultIndex] = {
|
// resultsByIndex[resultIndex] = {
|
||||||
...result,
|
// ...result,
|
||||||
...(resultsByIndex[resultIndex] || {}),
|
// ...(resultsByIndex[resultIndex] || {}),
|
||||||
hits: [
|
// hits: [
|
||||||
...(resultsByIndex[resultIndex]?.hits || []),
|
// ...(resultsByIndex[resultIndex]?.hits || []),
|
||||||
...resultHits,
|
// ...resultHits,
|
||||||
],
|
// ],
|
||||||
nbHits:
|
// nbHits:
|
||||||
(resultsByIndex[resultIndex]?.nbHits || 0) +
|
// (resultsByIndex[resultIndex]?.nbHits || 0) +
|
||||||
resultHits.length,
|
// resultHits.length,
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
|
|
||||||
const newResults = Object.values(resultsByIndex).flatMap(
|
// const newResults = Object.values(resultsByIndex).flatMap(
|
||||||
(result) => ({
|
// (result) => ({
|
||||||
...result,
|
// ...result,
|
||||||
hits: ("hits" in result ? result.hits : []).sort((a, b) => {
|
// hits: ("hits" in result ? result.hits : []).sort((a, b) => {
|
||||||
const typosA = a._rankingInfo?.nbTypos || 0
|
// const typosA = a._rankingInfo?.nbTypos || 0
|
||||||
const typosB = b._rankingInfo?.nbTypos || 0
|
// const typosB = b._rankingInfo?.nbTypos || 0
|
||||||
if (a.type === "lvl1" && typosA <= typosB) {
|
// const tagASortOrder =
|
||||||
return -1
|
// searchFilters.find((item) =>
|
||||||
}
|
// a._tags.find((tag) => tag === item.value)
|
||||||
|
// )?.internalSortOrder || 0
|
||||||
|
// const tagBSortorder =
|
||||||
|
// searchFilters.find((item) =>
|
||||||
|
// b._tags.find((tag) => tag === item.value)
|
||||||
|
// )?.internalSortOrder || 0
|
||||||
|
// if (
|
||||||
|
// a.type === "lvl1" &&
|
||||||
|
// typosA <= typosB &&
|
||||||
|
// tagASortOrder >= tagBSortorder
|
||||||
|
// ) {
|
||||||
|
// return -1
|
||||||
|
// }
|
||||||
|
|
||||||
if (b.type === "lvl1" && typosB <= typosA) {
|
// if (
|
||||||
return 1
|
// b.type === "lvl1" &&
|
||||||
}
|
// typosB <= typosA &&
|
||||||
|
// tagBSortorder >= tagASortOrder
|
||||||
|
// ) {
|
||||||
|
// return 1
|
||||||
|
// }
|
||||||
|
|
||||||
return 0
|
// return 0
|
||||||
}),
|
// }),
|
||||||
})
|
// })
|
||||||
)
|
// )
|
||||||
|
|
||||||
return {
|
// return {
|
||||||
// append the results with the main request's results
|
// // append the results with the main request's results
|
||||||
results: [mainResult, ...newResults],
|
// results: [mainResult, ...newResults],
|
||||||
} as SearchResponses<any>
|
// } as SearchResponses<any>
|
||||||
})
|
// })
|
||||||
},
|
// },
|
||||||
}
|
}
|
||||||
}, [algolia.appId, algolia.apiKey])
|
}, [algolia.appId, algolia.apiKey])
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user