From 5be25c656fef19b90e2b9031888496fcf8397a50 Mon Sep 17 00:00:00 2001 From: DrMint <29893320+DrMint@users.noreply.github.com> Date: Sun, 9 Apr 2023 09:59:43 +0200 Subject: [PATCH] Updated meilisearch --- .eslintrc.js | 2 +- package-lock.json | 28 +- package.json | 6 +- src/components/Inputs/ButtonGroup.tsx | 3 +- src/components/Panels/SearchPopup.tsx | 313 +++++++++++------------ src/components/ToolTip.tsx | 4 +- src/helpers/atoms.ts | 1 - src/helpers/formatters.ts | 1 - src/helpers/libraryItem.ts | 1 - src/helpers/logger.ts | 36 +-- src/helpers/search.ts | 61 ++++- src/pages/contents/all.tsx | 24 +- src/pages/dev/showcase/design-system.tsx | 1 - src/pages/library/index.tsx | 25 +- src/pages/news/index.tsx | 24 +- src/pages/wiki/weapons/index.tsx | 26 +- 16 files changed, 282 insertions(+), 274 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 36028d7..4044b88 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -46,7 +46,7 @@ module.exports = { "func-style": ["warn", "expression"], "grouped-accessor-pairs": "warn", "guard-for-in": "warn", - "id-denylist": ["error", "data", "err", "e", "cb", "callback", "i"], + "id-denylist": ["error", "err", "e", "cb", "callback", "i"], // "id-length": "warn", "id-match": "warn", "max-classes-per-file": ["error", 1], diff --git a/package-lock.json b/package-lock.json index 91f1ac8..fbf4c8b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "markdown-to-jsx": "^7.2.0", "marked": "^4.3.0", "material-symbols": "^0.5.5", - "meilisearch": "^0.31.1", + "meilisearch": "^0.32.3", "next": "^13.3.0", "nodemailer": "^6.9.1", "rc-slider": "^10.1.1", @@ -60,7 +60,7 @@ "eslint-plugin-import": "^2.27.5", "graphql": "^16.6.0", "graphql-request": "5.1.0", - "next-sitemap": "^4.0.6", + "next-sitemap": "^4.0.7", "prettier": "^2.8.7", "prettier-plugin-tailwindcss": "^0.2.7", "tailwindcss": "^3.3.1", @@ -8021,9 +8021,9 @@ "integrity": "sha512-NFUsjEVBNZvcRRqslY0RWnmlGgjhJkpDQkQs42o52gT2AmIbaP6V7wTRgyTkLAoD5VtpgpIx9eoOAXcH2ynwkg==" }, "node_modules/meilisearch": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/meilisearch/-/meilisearch-0.31.1.tgz", - "integrity": "sha512-ajMieU0e25lLkT+05J0snX0Ycow1UofxIy5sag03flERUbjXq8ouVwkrJkW27JsKftIeDeffRRRr89LasU9+0w==", + "version": "0.32.3", + "resolved": "https://registry.npmjs.org/meilisearch/-/meilisearch-0.32.3.tgz", + "integrity": "sha512-EOgfBuRE5SiIPIpEDYe2HO0D7a4z5bexIgaAdJFma/dH5hx1kwO+u/qb2g3qKyjG+iA3l8MlmTj/Xd72uahaAw==", "dependencies": { "cross-fetch": "^3.1.5" } @@ -8208,9 +8208,9 @@ } }, "node_modules/next-sitemap": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-4.0.6.tgz", - "integrity": "sha512-pZ9tynYe6mRR189qZqcOlWVgM1Gxo07BJQW0AjerKmLwQOt+6FQMdaDgifgCt6jDT3Y3EG/+NUDDZRcd0gbPkA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-4.0.7.tgz", + "integrity": "sha512-S2g5IwJeO0+ecmFq981fb+Mw9YWmntOuN/qTCxclSkUibOJ8qKIOye0vn6NEJ1S4tKhbY+MTYKgJpNdFZYxLoA==", "dev": true, "funding": [ { @@ -16972,9 +16972,9 @@ "integrity": "sha512-NFUsjEVBNZvcRRqslY0RWnmlGgjhJkpDQkQs42o52gT2AmIbaP6V7wTRgyTkLAoD5VtpgpIx9eoOAXcH2ynwkg==" }, "meilisearch": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/meilisearch/-/meilisearch-0.31.1.tgz", - "integrity": "sha512-ajMieU0e25lLkT+05J0snX0Ycow1UofxIy5sag03flERUbjXq8ouVwkrJkW27JsKftIeDeffRRRr89LasU9+0w==", + "version": "0.32.3", + "resolved": "https://registry.npmjs.org/meilisearch/-/meilisearch-0.32.3.tgz", + "integrity": "sha512-EOgfBuRE5SiIPIpEDYe2HO0D7a4z5bexIgaAdJFma/dH5hx1kwO+u/qb2g3qKyjG+iA3l8MlmTj/Xd72uahaAw==", "requires": { "cross-fetch": "^3.1.5" } @@ -17092,9 +17092,9 @@ } }, "next-sitemap": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-4.0.6.tgz", - "integrity": "sha512-pZ9tynYe6mRR189qZqcOlWVgM1Gxo07BJQW0AjerKmLwQOt+6FQMdaDgifgCt6jDT3Y3EG/+NUDDZRcd0gbPkA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-4.0.7.tgz", + "integrity": "sha512-S2g5IwJeO0+ecmFq981fb+Mw9YWmntOuN/qTCxclSkUibOJ8qKIOye0vn6NEJ1S4tKhbY+MTYKgJpNdFZYxLoA==", "dev": true, "requires": { "@corex/deepmerge": "^4.0.37", diff --git a/package.json b/package.json index 14e8f73..49a8e3b 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "generate": "graphql-codegen --config graphql-codegen.config.js", "tsc": "tsc", "prettier": "prettier --end-of-line auto --write .", - "update": "ncu --interactive --format group" + "upgrade": "ncu --interactive --format group" }, "dependencies": { "@fontsource/opendyslexic": "^4.5.4", @@ -33,7 +33,7 @@ "markdown-to-jsx": "^7.2.0", "marked": "^4.3.0", "material-symbols": "^0.5.5", - "meilisearch": "^0.31.1", + "meilisearch": "^0.32.3", "next": "^13.3.0", "nodemailer": "^6.9.1", "rc-slider": "^10.1.1", @@ -73,7 +73,7 @@ "eslint-plugin-import": "^2.27.5", "graphql": "^16.6.0", "graphql-request": "5.1.0", - "next-sitemap": "^4.0.6", + "next-sitemap": "^4.0.7", "prettier": "^2.8.7", "prettier-plugin-tailwindcss": "^0.2.7", "tailwindcss": "^3.3.1", diff --git a/src/components/Inputs/ButtonGroup.tsx b/src/components/Inputs/ButtonGroup.tsx index 33a4889..71febad 100644 --- a/src/components/Inputs/ButtonGroup.tsx +++ b/src/components/Inputs/ButtonGroup.tsx @@ -1,5 +1,4 @@ -// eslint-disable-next-line import/named -import { Placement } from "tippy.js"; +import type { Placement } from "tippy.js"; import { Button } from "./Button"; import { ToolTip } from "components/ToolTip"; import { cJoin } from "helpers/className"; diff --git a/src/components/Panels/SearchPopup.tsx b/src/components/Panels/SearchPopup.tsx index 603b986..78a0952 100644 --- a/src/components/Panels/SearchPopup.tsx +++ b/src/components/Panels/SearchPopup.tsx @@ -5,9 +5,14 @@ import { sendAnalytics } from "helpers/analytics"; import { atoms } from "contexts/atoms"; import { useAtomPair, useAtomSetter } from "helpers/atoms"; import { TextInput } from "components/Inputs/TextInput"; -import { containsHighlight, CustomSearchResponse, meiliSearch } from "helpers/search"; +import { + containsHighlight, + CustomSearchResponse, + filterHitsWithHighlight, + meiliMultiSearch, +} from "helpers/search"; import { PreviewCard, TranslatedPreviewCard } from "components/PreviewCard"; -import { filterDefined, filterHasAttributes, isDefined } from "helpers/asserts"; +import { filterHasAttributes, isDefined } from "helpers/asserts"; import { MeiliContent, MeiliIndices, @@ -35,160 +40,154 @@ const SEARCH_LIMIT = 8; * ────────────────────────────────────────╯ COMPONENT ╰────────────────────────────────────────── */ +interface MultiResult { + libraryItems?: CustomSearchResponse; + contents?: CustomSearchResponse; + videos?: CustomSearchResponse; + posts?: CustomSearchResponse; + wikiPages?: CustomSearchResponse; + weapons?: CustomSearchResponse; +} + export const SearchPopup = (): JSX.Element => { const [isSearchOpened, setSearchOpened] = useAtomPair(atoms.layout.searchOpened); const [query, setQuery] = useState(""); const { format } = useFormat(); - const [libraryItems, setLibraryItems] = useState>(); - const [contents, setContents] = useState>(); - const [videos, setVideos] = useState>(); - const [posts, setPosts] = useState>(); - const [wikiPages, setWikiPages] = useState>(); - const [weapons, setWeapons] = useState>(); + const [multiResult, setMultiResult] = useState({}); useEffect(() => { - const fetchLibraryItems = async () => { - const searchResult = await meiliSearch(MeiliIndices.LIBRARY_ITEM, query, { - limit: SEARCH_LIMIT, - attributesToRetrieve: [ - "title", - "subtitle", - "descriptions", - "id", - "slug", - "thumbnail", - "release_date", - "price", - "categories", - "metadata", - ], - attributesToHighlight: ["title", "subtitle", "descriptions"], - attributesToCrop: ["descriptions"], - }); - searchResult.hits = searchResult.hits.map((item) => { - if (Object.keys(item._matchesPosition).some((match) => match.startsWith("descriptions"))) { - item._formatted.descriptions = filterDefined(item._formatted.descriptions).filter( - (description) => containsHighlight(JSON.stringify(description)) - ); - } - return item; - }); - setLibraryItems(searchResult); - }; + const fetchMultiResult = async () => { + const searchResults = ( + await meiliMultiSearch([ + { + indexUid: MeiliIndices.LIBRARY_ITEM, + q: query, + limit: SEARCH_LIMIT, + attributesToRetrieve: [ + "title", + "subtitle", + "descriptions", + "id", + "slug", + "thumbnail", + "release_date", + "price", + "categories", + "metadata", + ], + attributesToHighlight: ["title", "subtitle", "descriptions"], + attributesToCrop: ["descriptions"], + }, + { + indexUid: MeiliIndices.CONTENT, + q: query, + limit: SEARCH_LIMIT, + attributesToRetrieve: ["translations", "id", "slug", "categories", "type", "thumbnail"], + attributesToHighlight: ["translations"], + attributesToCrop: ["translations.displayable_description"], + }, + { + indexUid: MeiliIndices.VIDEOS, + q: query, + limit: SEARCH_LIMIT, + attributesToRetrieve: [ + "title", + "channel", + "uid", + "published_date", + "views", + "duration", + "description", + ], + attributesToHighlight: ["title", "channel", "description"], + attributesToCrop: ["description"], + }, + { + indexUid: MeiliIndices.POST, + q: query, + limit: SEARCH_LIMIT, + attributesToRetrieve: ["translations", "thumbnail", "slug", "date", "categories"], + attributesToHighlight: [ + "translations.title", + "translations.excerpt", + "translations.body", + ], + attributesToCrop: ["translations.body"], + filter: ["hidden = false"], + }, + { + indexUid: MeiliIndices.WEAPON, + q: query, + limit: SEARCH_LIMIT, + attributesToHighlight: ["translations.description", "translations.names"], + attributesToCrop: ["translations.description"], + sort: ["slug:asc"], + }, + { + indexUid: MeiliIndices.WIKI_PAGE, + q: query, + limit: SEARCH_LIMIT, + attributesToHighlight: [ + "translations.title", + "translations.aliases", + "translations.summary", + "translations.displayable_description", + ], + attributesToCrop: ["translations.displayable_description"], + }, + ]) + ).results; - const fetchContents = async () => { - const searchResult = await meiliSearch(MeiliIndices.CONTENT, query, { - limit: SEARCH_LIMIT, - attributesToRetrieve: ["translations", "id", "slug", "categories", "type", "thumbnail"], - attributesToHighlight: ["translations"], - attributesToCrop: ["translations.displayable_description"], - }); - searchResult.hits = searchResult.hits.map((item) => { - if (Object.keys(item._matchesPosition).some((match) => match.startsWith("translations"))) { - item._formatted.translations = filterDefined(item._formatted.translations).filter( - (translation) => containsHighlight(JSON.stringify(translation)) - ); - } - return item; - }); - setContents(searchResult); - }; + const result: MultiResult = {}; - const fetchVideos = async () => { - const searchResult = await meiliSearch(MeiliIndices.VIDEOS, query, { - limit: SEARCH_LIMIT, - attributesToRetrieve: [ - "title", - "channel", - "uid", - "published_date", - "views", - "duration", - "description", - ], - attributesToHighlight: ["title", "channel", "description"], - attributesToCrop: ["description"], - }); - setVideos(searchResult); - }; + searchResults.map((searchResult) => { + switch (searchResult.indexUid) { + case MeiliIndices.LIBRARY_ITEM: { + result.libraryItems = filterHitsWithHighlight( + searchResult, + "descriptions" + ); + break; + } - const fetchPosts = async () => { - const searchResult = await meiliSearch(MeiliIndices.POST, query, { - limit: SEARCH_LIMIT, - attributesToRetrieve: ["translations", "thumbnail", "slug", "date", "categories"], - attributesToHighlight: ["translations.title", "translations.excerpt", "translations.body"], - attributesToCrop: ["translations.body"], - filter: ["hidden = false"], - }); - searchResult.hits = searchResult.hits.map((item) => { - if (Object.keys(item._matchesPosition).some((match) => match.startsWith("translations"))) { - item._formatted.translations = filterDefined(item._formatted.translations).filter( - (translation) => JSON.stringify(translation).includes("") - ); - } - return item; - }); - setPosts(searchResult); - }; + case MeiliIndices.CONTENT: { + result.contents = filterHitsWithHighlight(searchResult, "translations"); + break; + } - const fetchWeapons = async () => { - const searchResult = await meiliSearch(MeiliIndices.WEAPON, query, { - limit: SEARCH_LIMIT, - attributesToRetrieve: ["*"], - attributesToHighlight: ["translations.description", "translations.names"], - attributesToCrop: ["translations.description"], - sort: ["slug:asc"], - }); - searchResult.hits = searchResult.hits.map((item) => { - if (Object.keys(item._matchesPosition).some((match) => match.startsWith("translations"))) { - item._formatted.translations = filterDefined(item._formatted.translations).filter( - (translation) => JSON.stringify(translation).includes("") - ); - } - return item; - }); - setWeapons(searchResult); - }; + case MeiliIndices.VIDEOS: { + result.videos = filterHitsWithHighlight(searchResult); + break; + } - const fetchWikiPages = async () => { - const searchResult = await meiliSearch(MeiliIndices.WIKI_PAGE, query, { - limit: SEARCH_LIMIT, - attributesToHighlight: [ - "translations.title", - "translations.aliases", - "translations.summary", - "translations.displayable_description", - ], - attributesToCrop: ["translations.displayable_description"], - }); - searchResult.hits = searchResult.hits.map((item) => { - if ( - Object.keys(item._matchesPosition).filter((match) => match.startsWith("translations")) - .length > 0 - ) { - item._formatted.translations = filterDefined(item._formatted.translations).filter( - (translation) => JSON.stringify(translation).includes("") - ); + case MeiliIndices.POST: { + result.posts = filterHitsWithHighlight(searchResult, "translations"); + break; + } + + case MeiliIndices.WEAPON: { + result.weapons = filterHitsWithHighlight(searchResult, "translations"); + break; + } + + case MeiliIndices.WIKI_PAGE: { + result.wikiPages = filterHitsWithHighlight(searchResult, "translations"); + break; + } + + default: { + console.log("What the fuck?"); + } } - return item; }); - setWikiPages(searchResult); + + setMultiResult(result); }; if (query === "") { - setWikiPages(undefined); - setLibraryItems(undefined); - setContents(undefined); - setVideos(undefined); - setPosts(undefined); - setWeapons(undefined); + setMultiResult({}); } else { - fetchWikiPages(); - fetchLibraryItems(); - fetchContents(); - fetchVideos(); - fetchPosts(); - fetchWeapons(); + fetchMultiResult(); } }, [query]); @@ -207,15 +206,15 @@ export const SearchPopup = (): JSX.Element => {
- {isDefined(libraryItems) && ( + {isDefined(multiResult.libraryItems) && ( + totalHits={multiResult.libraryItems.estimatedTotalHits}>
- {libraryItems.hits.map((item) => ( + {multiResult.libraryItems.hits.map((item) => ( { )} - {isDefined(contents) && ( + {isDefined(multiResult.contents) && ( + totalHits={multiResult.contents.estimatedTotalHits}>
- {contents.hits.map((item) => ( + {multiResult.contents.hits.map((item) => ( { )} - {isDefined(wikiPages) && ( + {isDefined(multiResult.wikiPages) && ( + totalHits={multiResult.wikiPages.estimatedTotalHits}>
- {wikiPages.hits.map((item) => ( + {multiResult.wikiPages.hits.map((item) => ( { )} - {isDefined(posts) && ( + {isDefined(multiResult.posts) && ( + totalHits={multiResult.posts.estimatedTotalHits}>
- {posts.hits.map((item) => ( + {multiResult.posts.hits.map((item) => ( { )} - {isDefined(videos) && ( + {isDefined(multiResult.videos) && ( + totalHits={multiResult.videos.estimatedTotalHits}>
- {videos.hits.map((item) => ( + {multiResult.videos.hits.map((item) => ( { )} - {isDefined(weapons) && ( + {isDefined(multiResult.weapons) && ( + totalHits={multiResult.weapons.estimatedTotalHits}>
- {weapons.hits.map((item) => ( + {multiResult.weapons.hits.map((item) => ( = [Atom, WritableAtom]; export const atomPairing = (anAtom: PrimitiveAtom): AtomPair => { diff --git a/src/helpers/formatters.ts b/src/helpers/formatters.ts index 6af4438..adb1591 100644 --- a/src/helpers/formatters.ts +++ b/src/helpers/formatters.ts @@ -58,7 +58,6 @@ export const prettyInlineTitle = ( return result; }; -/* eslint-disable id-denylist */ export const prettyItemSubType = ( metadata: | { diff --git a/src/helpers/libraryItem.ts b/src/helpers/libraryItem.ts index fb7e11b..48642a5 100644 --- a/src/helpers/libraryItem.ts +++ b/src/helpers/libraryItem.ts @@ -4,7 +4,6 @@ export const isUntangibleGroupItem = ( metadata: | { __typename: string; - // eslint-disable-next-line id-denylist subtype?: { data?: { attributes?: { slug: string } | null } | null } | null; } | null diff --git a/src/helpers/logger.ts b/src/helpers/logger.ts index 78975c9..d176ae4 100644 --- a/src/helpers/logger.ts +++ b/src/helpers/logger.ts @@ -2,28 +2,30 @@ type LoggerMode = "both" | "client" | "server"; const isServer = typeof window === "undefined"; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -export const getLogger = (prefix: string, mode: LoggerMode = "client") => { +type Logger = { + error: (message?: unknown, ...optionalParams: unknown[]) => void; + warn: (message?: unknown, ...optionalParams: unknown[]) => void; + log: (message?: unknown, ...optionalParams: unknown[]) => void; + info: (message?: unknown, ...optionalParams: unknown[]) => void; + debug: (message?: unknown, ...optionalParams: unknown[]) => void; +}; + +export const getLogger = (prefix: string, mode: LoggerMode = "client"): Logger => { if ((mode === "client" && isServer) || (mode === "server" && !isServer)) { return { - error: () => null, - warn: () => null, - log: () => null, - info: () => null, - debug: () => null, + error: () => undefined, + warn: () => undefined, + log: () => undefined, + info: () => undefined, + debug: () => undefined, }; } return { - error: (message?: unknown, ...optionalParams: unknown[]) => - console.error(prefix, message, ...optionalParams), - warn: (message?: unknown, ...optionalParams: unknown[]) => - console.warn(prefix, message, ...optionalParams), - log: (message?: unknown, ...optionalParams: unknown[]) => - console.log(prefix, message, ...optionalParams), - info: (message?: unknown, ...optionalParams: unknown[]) => - console.info(prefix, message, ...optionalParams), - debug: (message?: unknown, ...optionalParams: unknown[]) => - console.debug(prefix, message, ...optionalParams), + error: (message, ...optionalParams) => console.error(prefix, message, ...optionalParams), + warn: (message, ...optionalParams) => console.warn(prefix, message, ...optionalParams), + log: (message, ...optionalParams) => console.log(prefix, message, ...optionalParams), + info: (message, ...optionalParams) => console.info(prefix, message, ...optionalParams), + debug: (message, ...optionalParams) => console.debug(prefix, message, ...optionalParams), }; }; diff --git a/src/helpers/search.ts b/src/helpers/search.ts index 058117a..337d41c 100644 --- a/src/helpers/search.ts +++ b/src/helpers/search.ts @@ -1,7 +1,13 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -// eslint-disable-next-line import/named -import { MatchesPosition, MeiliSearch, SearchParams, SearchResponse } from "meilisearch"; -import { isDefined } from "./asserts"; +import { MeiliSearch } from "meilisearch"; +import type { + SearchParams, + MatchesPosition, + SearchResponse, + MultiSearchQuery, + MultiSearchResponse, + MultiSearchResult, +} from "meilisearch"; +import { filterDefined, isDefined } from "./asserts"; import { MeiliDocumentsType } from "shared/meilisearch-graphql-typings/meiliTypes"; const meili = new MeiliSearch({ @@ -12,20 +18,61 @@ const meili = new MeiliSearch({ interface CustomSearchParams extends Omit< SearchParams, - "cropMarker" | "highlightPostTag" | "highlightPreTag" | "q" | "showMatchesPosition" + | "cropLength" + | "cropMarker" + | "cropMarker" + | "highlightPostTag" + | "highlightPreTag" + | "q" + | "showMatchesPosition" > {} -type CustomHit> = T & { +type CustomHit> = T & { _formatted: Partial; _matchesPosition: MatchesPosition; }; -type CustomHits> = CustomHit[]; +type CustomHits> = CustomHit[]; export interface CustomSearchResponse extends Omit, "hits"> { hits: CustomHits; } +export const meiliMultiSearch = async (queries: MultiSearchQuery[]): Promise => + await meili.multiSearch({ + queries: queries.map((query) => ({ + attributesToHighlight: ["*"], + ...query, + highlightPreTag: "", + highlightPostTag: "", + showMatchesPosition: true, + cropLength: 20, + cropMarker: "...", + })), + }); + +export const filterHitsWithHighlight = ( + searchResult: CustomSearchResponse | MultiSearchResult>, + keyToFilter?: keyof T +): CustomSearchResponse => { + const result = searchResult as unknown as CustomSearchResponse; + if (isDefined(keyToFilter)) { + result.hits = result.hits.map((item) => { + if ( + Object.keys(item._matchesPosition).some((match) => match.startsWith(keyToFilter as string)) + ) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + item._formatted[keyToFilter] = filterDefined(item._formatted[keyToFilter]).filter( + (translation) => JSON.stringify(translation).includes("") + ); + } + return item; + }); + } + return result; +}; + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export const meiliSearch = async ( indexName: I, diff --git a/src/pages/contents/all.tsx b/src/pages/contents/all.tsx index 7ac3773..6c7549e 100644 --- a/src/pages/contents/all.tsx +++ b/src/pages/contents/all.tsx @@ -12,16 +12,16 @@ import { TextInput } from "components/Inputs/TextInput"; import { WithLabel } from "components/Inputs/WithLabel"; import { Button } from "components/Inputs/Button"; import { useDeviceSupportsHover } from "hooks/useMediaQuery"; -import { - filterDefined, - filterHasAttributes, - isDefined, - isDefinedAndNotEmpty, -} from "helpers/asserts"; +import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/asserts"; import { getOpenGraph } from "helpers/openGraph"; import { HorizontalLine } from "components/HorizontalLine"; import { sendAnalytics } from "helpers/analytics"; -import { containsHighlight, CustomSearchResponse, meiliSearch } from "helpers/search"; +import { + containsHighlight, + CustomSearchResponse, + filterHitsWithHighlight, + meiliSearch, +} from "helpers/search"; import { MeiliContent, MeiliIndices } from "shared/meilisearch-graphql-typings/meiliTypes"; import { useTypedRouter } from "hooks/useTypedRouter"; import { TranslatedPreviewCard } from "components/PreviewCard"; @@ -97,15 +97,7 @@ const Contents = (props: Props): JSX.Element => { page, sort: isDefined(currentSortingMethod) ? [currentSortingMethod.meiliAttribute] : undefined, }); - searchResult.hits = searchResult.hits.map((item) => { - if (Object.keys(item._matchesPosition).some((match) => match.startsWith("translations"))) { - item._formatted.translations = filterDefined(item._formatted.translations).filter( - (translation) => containsHighlight(JSON.stringify(translation)) - ); - } - return item; - }); - setContents(searchResult); + setContents(filterHitsWithHighlight(searchResult, "translations")); }; fetchPosts(); }, [query, page, sortingMethod, sortingMethods]); diff --git a/src/pages/dev/showcase/design-system.tsx b/src/pages/dev/showcase/design-system.tsx index ba1dbb5..6ed2452 100644 --- a/src/pages/dev/showcase/design-system.tsx +++ b/src/pages/dev/showcase/design-system.tsx @@ -1,4 +1,3 @@ -/* eslint-disable id-denylist */ import { GetStaticProps } from "next"; import { ReactNode, useState } from "react"; import Slider from "rc-slider"; diff --git a/src/pages/library/index.tsx b/src/pages/library/index.tsx index 6e72584..f0c3c69 100644 --- a/src/pages/library/index.tsx +++ b/src/pages/library/index.tsx @@ -14,17 +14,16 @@ import { TextInput } from "components/Inputs/TextInput"; import { Button } from "components/Inputs/Button"; import { useDeviceSupportsHover } from "hooks/useMediaQuery"; import { ButtonGroup } from "components/Inputs/ButtonGroup"; -import { - filterDefined, - filterHasAttributes, - isDefined, - isDefinedAndNotEmpty, - isUndefined, -} from "helpers/asserts"; +import { filterHasAttributes, isDefined, isDefinedAndNotEmpty, isUndefined } from "helpers/asserts"; import { getOpenGraph } from "helpers/openGraph"; import { HorizontalLine } from "components/HorizontalLine"; import { sendAnalytics } from "helpers/analytics"; -import { containsHighlight, CustomSearchResponse, meiliSearch } from "helpers/search"; +import { + containsHighlight, + CustomSearchResponse, + filterHitsWithHighlight, + meiliSearch, +} from "helpers/search"; import { MeiliIndices, MeiliLibraryItem } from "shared/meilisearch-graphql-typings/meiliTypes"; import { useTypedRouter } from "hooks/useTypedRouter"; import { TranslatedPreviewCard } from "components/PreviewCard"; @@ -178,15 +177,7 @@ const Library = (props: Props): JSX.Element => { sort: isDefined(currentSortingMethod) ? [currentSortingMethod.meiliAttribute] : undefined, filter, }); - searchResult.hits = searchResult.hits.map((item) => { - if (Object.keys(item._matchesPosition).some((match) => match.startsWith("descriptions"))) { - item._formatted.descriptions = filterDefined(item._formatted.descriptions).filter( - (description) => containsHighlight(JSON.stringify(description)) - ); - } - return item; - }); - setLibraryItems(searchResult); + setLibraryItems(filterHitsWithHighlight(searchResult, "descriptions")); }; fetchLibraryItems(); }, [ diff --git a/src/pages/news/index.tsx b/src/pages/news/index.tsx index 40dfad7..c74ecb2 100644 --- a/src/pages/news/index.tsx +++ b/src/pages/news/index.tsx @@ -11,12 +11,7 @@ import { WithLabel } from "components/Inputs/WithLabel"; import { TextInput } from "components/Inputs/TextInput"; import { Button } from "components/Inputs/Button"; import { useDeviceSupportsHover } from "hooks/useMediaQuery"; -import { - filterDefined, - filterHasAttributes, - isDefined, - isDefinedAndNotEmpty, -} from "helpers/asserts"; +import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/asserts"; import { getOpenGraph } from "helpers/openGraph"; import { TranslatedPreviewCard } from "components/PreviewCard"; import { HorizontalLine } from "components/HorizontalLine"; @@ -24,7 +19,12 @@ import { sendAnalytics } from "helpers/analytics"; import { Terminal } from "components/Cli/Terminal"; import { atoms } from "contexts/atoms"; import { useAtomGetter } from "helpers/atoms"; -import { containsHighlight, CustomSearchResponse, meiliSearch } from "helpers/search"; +import { + containsHighlight, + CustomSearchResponse, + filterHitsWithHighlight, + meiliSearch, +} from "helpers/search"; import { MeiliIndices, MeiliPost } from "shared/meilisearch-graphql-typings/meiliTypes"; import { useTypedRouter } from "hooks/useTypedRouter"; import { prettySlug } from "helpers/formatters"; @@ -84,15 +84,7 @@ const News = ({ ...otherProps }: Props): JSX.Element => { sort: ["sortable_date:desc"], filter: ["hidden = false"], }); - searchResult.hits = searchResult.hits.map((item) => { - if (Object.keys(item._matchesPosition).some((match) => match.startsWith("translations"))) { - item._formatted.translations = filterDefined(item._formatted.translations).filter( - (translation) => JSON.stringify(translation).includes("") - ); - } - return item; - }); - setPosts(searchResult); + setPosts(filterHitsWithHighlight(searchResult, "translations")); }; fetchPosts(); }, [query, page]); diff --git a/src/pages/wiki/weapons/index.tsx b/src/pages/wiki/weapons/index.tsx index 9242ac9..f8ba866 100644 --- a/src/pages/wiki/weapons/index.tsx +++ b/src/pages/wiki/weapons/index.tsx @@ -10,16 +10,16 @@ import { PanelHeader } from "components/PanelComponents/PanelHeader"; import { TextInput } from "components/Inputs/TextInput"; import { useTypedRouter } from "hooks/useTypedRouter"; import { useFormat } from "hooks/useFormat"; -import { - filterDefined, - filterHasAttributes, - isDefined, - isDefinedAndNotEmpty, -} from "helpers/asserts"; +import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/asserts"; import { sendAnalytics } from "helpers/analytics"; import { Button } from "components/Inputs/Button"; import { HorizontalLine } from "components/HorizontalLine"; -import { containsHighlight, CustomSearchResponse, meiliSearch } from "helpers/search"; +import { + containsHighlight, + CustomSearchResponse, + filterHitsWithHighlight, + meiliSearch, +} from "helpers/search"; import { MeiliIndices, MeiliWeapon } from "shared/meilisearch-graphql-typings/meiliTypes"; import { ContentPanel, ContentPanelWidthSizes } from "components/Containers/ContentPanel"; import { Paginator } from "components/Containers/Paginator"; @@ -79,17 +79,7 @@ const Weapons = (props: Props): JSX.Element => { attributesToCrop: ["translations.description"], sort: ["slug:asc"], }); - - searchResult.hits = searchResult.hits.map((item) => { - if (Object.keys(item._matchesPosition).some((match) => match.startsWith("translations"))) { - item._formatted.translations = filterDefined(item._formatted.translations).filter( - (translation) => JSON.stringify(translation).includes("") - ); - } - return item; - }); - - setWeapons(searchResult); + setWeapons(filterHitsWithHighlight(searchResult, "translations")); }; fetchPosts(); }, [query, page]);