Updated meilisearch
This commit is contained in:
parent
0f735c62cc
commit
5be25c656f
|
@ -46,7 +46,7 @@ module.exports = {
|
||||||
"func-style": ["warn", "expression"],
|
"func-style": ["warn", "expression"],
|
||||||
"grouped-accessor-pairs": "warn",
|
"grouped-accessor-pairs": "warn",
|
||||||
"guard-for-in": "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-length": "warn",
|
||||||
"id-match": "warn",
|
"id-match": "warn",
|
||||||
"max-classes-per-file": ["error", 1],
|
"max-classes-per-file": ["error", 1],
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
"markdown-to-jsx": "^7.2.0",
|
"markdown-to-jsx": "^7.2.0",
|
||||||
"marked": "^4.3.0",
|
"marked": "^4.3.0",
|
||||||
"material-symbols": "^0.5.5",
|
"material-symbols": "^0.5.5",
|
||||||
"meilisearch": "^0.31.1",
|
"meilisearch": "^0.32.3",
|
||||||
"next": "^13.3.0",
|
"next": "^13.3.0",
|
||||||
"nodemailer": "^6.9.1",
|
"nodemailer": "^6.9.1",
|
||||||
"rc-slider": "^10.1.1",
|
"rc-slider": "^10.1.1",
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
"eslint-plugin-import": "^2.27.5",
|
"eslint-plugin-import": "^2.27.5",
|
||||||
"graphql": "^16.6.0",
|
"graphql": "^16.6.0",
|
||||||
"graphql-request": "5.1.0",
|
"graphql-request": "5.1.0",
|
||||||
"next-sitemap": "^4.0.6",
|
"next-sitemap": "^4.0.7",
|
||||||
"prettier": "^2.8.7",
|
"prettier": "^2.8.7",
|
||||||
"prettier-plugin-tailwindcss": "^0.2.7",
|
"prettier-plugin-tailwindcss": "^0.2.7",
|
||||||
"tailwindcss": "^3.3.1",
|
"tailwindcss": "^3.3.1",
|
||||||
|
@ -8021,9 +8021,9 @@
|
||||||
"integrity": "sha512-NFUsjEVBNZvcRRqslY0RWnmlGgjhJkpDQkQs42o52gT2AmIbaP6V7wTRgyTkLAoD5VtpgpIx9eoOAXcH2ynwkg=="
|
"integrity": "sha512-NFUsjEVBNZvcRRqslY0RWnmlGgjhJkpDQkQs42o52gT2AmIbaP6V7wTRgyTkLAoD5VtpgpIx9eoOAXcH2ynwkg=="
|
||||||
},
|
},
|
||||||
"node_modules/meilisearch": {
|
"node_modules/meilisearch": {
|
||||||
"version": "0.31.1",
|
"version": "0.32.3",
|
||||||
"resolved": "https://registry.npmjs.org/meilisearch/-/meilisearch-0.31.1.tgz",
|
"resolved": "https://registry.npmjs.org/meilisearch/-/meilisearch-0.32.3.tgz",
|
||||||
"integrity": "sha512-ajMieU0e25lLkT+05J0snX0Ycow1UofxIy5sag03flERUbjXq8ouVwkrJkW27JsKftIeDeffRRRr89LasU9+0w==",
|
"integrity": "sha512-EOgfBuRE5SiIPIpEDYe2HO0D7a4z5bexIgaAdJFma/dH5hx1kwO+u/qb2g3qKyjG+iA3l8MlmTj/Xd72uahaAw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cross-fetch": "^3.1.5"
|
"cross-fetch": "^3.1.5"
|
||||||
}
|
}
|
||||||
|
@ -8208,9 +8208,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/next-sitemap": {
|
"node_modules/next-sitemap": {
|
||||||
"version": "4.0.6",
|
"version": "4.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-4.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-4.0.7.tgz",
|
||||||
"integrity": "sha512-pZ9tynYe6mRR189qZqcOlWVgM1Gxo07BJQW0AjerKmLwQOt+6FQMdaDgifgCt6jDT3Y3EG/+NUDDZRcd0gbPkA==",
|
"integrity": "sha512-S2g5IwJeO0+ecmFq981fb+Mw9YWmntOuN/qTCxclSkUibOJ8qKIOye0vn6NEJ1S4tKhbY+MTYKgJpNdFZYxLoA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -16972,9 +16972,9 @@
|
||||||
"integrity": "sha512-NFUsjEVBNZvcRRqslY0RWnmlGgjhJkpDQkQs42o52gT2AmIbaP6V7wTRgyTkLAoD5VtpgpIx9eoOAXcH2ynwkg=="
|
"integrity": "sha512-NFUsjEVBNZvcRRqslY0RWnmlGgjhJkpDQkQs42o52gT2AmIbaP6V7wTRgyTkLAoD5VtpgpIx9eoOAXcH2ynwkg=="
|
||||||
},
|
},
|
||||||
"meilisearch": {
|
"meilisearch": {
|
||||||
"version": "0.31.1",
|
"version": "0.32.3",
|
||||||
"resolved": "https://registry.npmjs.org/meilisearch/-/meilisearch-0.31.1.tgz",
|
"resolved": "https://registry.npmjs.org/meilisearch/-/meilisearch-0.32.3.tgz",
|
||||||
"integrity": "sha512-ajMieU0e25lLkT+05J0snX0Ycow1UofxIy5sag03flERUbjXq8ouVwkrJkW27JsKftIeDeffRRRr89LasU9+0w==",
|
"integrity": "sha512-EOgfBuRE5SiIPIpEDYe2HO0D7a4z5bexIgaAdJFma/dH5hx1kwO+u/qb2g3qKyjG+iA3l8MlmTj/Xd72uahaAw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"cross-fetch": "^3.1.5"
|
"cross-fetch": "^3.1.5"
|
||||||
}
|
}
|
||||||
|
@ -17092,9 +17092,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"next-sitemap": {
|
"next-sitemap": {
|
||||||
"version": "4.0.6",
|
"version": "4.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-4.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/next-sitemap/-/next-sitemap-4.0.7.tgz",
|
||||||
"integrity": "sha512-pZ9tynYe6mRR189qZqcOlWVgM1Gxo07BJQW0AjerKmLwQOt+6FQMdaDgifgCt6jDT3Y3EG/+NUDDZRcd0gbPkA==",
|
"integrity": "sha512-S2g5IwJeO0+ecmFq981fb+Mw9YWmntOuN/qTCxclSkUibOJ8qKIOye0vn6NEJ1S4tKhbY+MTYKgJpNdFZYxLoA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@corex/deepmerge": "^4.0.37",
|
"@corex/deepmerge": "^4.0.37",
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
"generate": "graphql-codegen --config graphql-codegen.config.js",
|
"generate": "graphql-codegen --config graphql-codegen.config.js",
|
||||||
"tsc": "tsc",
|
"tsc": "tsc",
|
||||||
"prettier": "prettier --end-of-line auto --write .",
|
"prettier": "prettier --end-of-line auto --write .",
|
||||||
"update": "ncu --interactive --format group"
|
"upgrade": "ncu --interactive --format group"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/opendyslexic": "^4.5.4",
|
"@fontsource/opendyslexic": "^4.5.4",
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
"markdown-to-jsx": "^7.2.0",
|
"markdown-to-jsx": "^7.2.0",
|
||||||
"marked": "^4.3.0",
|
"marked": "^4.3.0",
|
||||||
"material-symbols": "^0.5.5",
|
"material-symbols": "^0.5.5",
|
||||||
"meilisearch": "^0.31.1",
|
"meilisearch": "^0.32.3",
|
||||||
"next": "^13.3.0",
|
"next": "^13.3.0",
|
||||||
"nodemailer": "^6.9.1",
|
"nodemailer": "^6.9.1",
|
||||||
"rc-slider": "^10.1.1",
|
"rc-slider": "^10.1.1",
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
"eslint-plugin-import": "^2.27.5",
|
"eslint-plugin-import": "^2.27.5",
|
||||||
"graphql": "^16.6.0",
|
"graphql": "^16.6.0",
|
||||||
"graphql-request": "5.1.0",
|
"graphql-request": "5.1.0",
|
||||||
"next-sitemap": "^4.0.6",
|
"next-sitemap": "^4.0.7",
|
||||||
"prettier": "^2.8.7",
|
"prettier": "^2.8.7",
|
||||||
"prettier-plugin-tailwindcss": "^0.2.7",
|
"prettier-plugin-tailwindcss": "^0.2.7",
|
||||||
"tailwindcss": "^3.3.1",
|
"tailwindcss": "^3.3.1",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// eslint-disable-next-line import/named
|
import type { Placement } from "tippy.js";
|
||||||
import { Placement } from "tippy.js";
|
|
||||||
import { Button } from "./Button";
|
import { Button } from "./Button";
|
||||||
import { ToolTip } from "components/ToolTip";
|
import { ToolTip } from "components/ToolTip";
|
||||||
import { cJoin } from "helpers/className";
|
import { cJoin } from "helpers/className";
|
||||||
|
|
|
@ -5,9 +5,14 @@ import { sendAnalytics } from "helpers/analytics";
|
||||||
import { atoms } from "contexts/atoms";
|
import { atoms } from "contexts/atoms";
|
||||||
import { useAtomPair, useAtomSetter } from "helpers/atoms";
|
import { useAtomPair, useAtomSetter } from "helpers/atoms";
|
||||||
import { TextInput } from "components/Inputs/TextInput";
|
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 { PreviewCard, TranslatedPreviewCard } from "components/PreviewCard";
|
||||||
import { filterDefined, filterHasAttributes, isDefined } from "helpers/asserts";
|
import { filterHasAttributes, isDefined } from "helpers/asserts";
|
||||||
import {
|
import {
|
||||||
MeiliContent,
|
MeiliContent,
|
||||||
MeiliIndices,
|
MeiliIndices,
|
||||||
|
@ -35,160 +40,154 @@ const SEARCH_LIMIT = 8;
|
||||||
* ────────────────────────────────────────╯ COMPONENT ╰──────────────────────────────────────────
|
* ────────────────────────────────────────╯ COMPONENT ╰──────────────────────────────────────────
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
interface MultiResult {
|
||||||
|
libraryItems?: CustomSearchResponse<MeiliLibraryItem>;
|
||||||
|
contents?: CustomSearchResponse<MeiliContent>;
|
||||||
|
videos?: CustomSearchResponse<MeiliVideo>;
|
||||||
|
posts?: CustomSearchResponse<MeiliPost>;
|
||||||
|
wikiPages?: CustomSearchResponse<MeiliWikiPage>;
|
||||||
|
weapons?: CustomSearchResponse<MeiliWeapon>;
|
||||||
|
}
|
||||||
|
|
||||||
export const SearchPopup = (): JSX.Element => {
|
export const SearchPopup = (): JSX.Element => {
|
||||||
const [isSearchOpened, setSearchOpened] = useAtomPair(atoms.layout.searchOpened);
|
const [isSearchOpened, setSearchOpened] = useAtomPair(atoms.layout.searchOpened);
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
const { format } = useFormat();
|
const { format } = useFormat();
|
||||||
const [libraryItems, setLibraryItems] = useState<CustomSearchResponse<MeiliLibraryItem>>();
|
const [multiResult, setMultiResult] = useState<MultiResult>({});
|
||||||
const [contents, setContents] = useState<CustomSearchResponse<MeiliContent>>();
|
|
||||||
const [videos, setVideos] = useState<CustomSearchResponse<MeiliVideo>>();
|
|
||||||
const [posts, setPosts] = useState<CustomSearchResponse<MeiliPost>>();
|
|
||||||
const [wikiPages, setWikiPages] = useState<CustomSearchResponse<MeiliWikiPage>>();
|
|
||||||
const [weapons, setWeapons] = useState<CustomSearchResponse<MeiliWeapon>>();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchLibraryItems = async () => {
|
const fetchMultiResult = async () => {
|
||||||
const searchResult = await meiliSearch(MeiliIndices.LIBRARY_ITEM, query, {
|
const searchResults = (
|
||||||
limit: SEARCH_LIMIT,
|
await meiliMultiSearch([
|
||||||
attributesToRetrieve: [
|
{
|
||||||
"title",
|
indexUid: MeiliIndices.LIBRARY_ITEM,
|
||||||
"subtitle",
|
q: query,
|
||||||
"descriptions",
|
limit: SEARCH_LIMIT,
|
||||||
"id",
|
attributesToRetrieve: [
|
||||||
"slug",
|
"title",
|
||||||
"thumbnail",
|
"subtitle",
|
||||||
"release_date",
|
"descriptions",
|
||||||
"price",
|
"id",
|
||||||
"categories",
|
"slug",
|
||||||
"metadata",
|
"thumbnail",
|
||||||
],
|
"release_date",
|
||||||
attributesToHighlight: ["title", "subtitle", "descriptions"],
|
"price",
|
||||||
attributesToCrop: ["descriptions"],
|
"categories",
|
||||||
});
|
"metadata",
|
||||||
searchResult.hits = searchResult.hits.map((item) => {
|
],
|
||||||
if (Object.keys(item._matchesPosition).some((match) => match.startsWith("descriptions"))) {
|
attributesToHighlight: ["title", "subtitle", "descriptions"],
|
||||||
item._formatted.descriptions = filterDefined(item._formatted.descriptions).filter(
|
attributesToCrop: ["descriptions"],
|
||||||
(description) => containsHighlight(JSON.stringify(description))
|
},
|
||||||
);
|
{
|
||||||
}
|
indexUid: MeiliIndices.CONTENT,
|
||||||
return item;
|
q: query,
|
||||||
});
|
limit: SEARCH_LIMIT,
|
||||||
setLibraryItems(searchResult);
|
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 result: MultiResult = {};
|
||||||
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 fetchVideos = async () => {
|
searchResults.map((searchResult) => {
|
||||||
const searchResult = await meiliSearch(MeiliIndices.VIDEOS, query, {
|
switch (searchResult.indexUid) {
|
||||||
limit: SEARCH_LIMIT,
|
case MeiliIndices.LIBRARY_ITEM: {
|
||||||
attributesToRetrieve: [
|
result.libraryItems = filterHitsWithHighlight<MeiliLibraryItem>(
|
||||||
"title",
|
searchResult,
|
||||||
"channel",
|
"descriptions"
|
||||||
"uid",
|
);
|
||||||
"published_date",
|
break;
|
||||||
"views",
|
}
|
||||||
"duration",
|
|
||||||
"description",
|
|
||||||
],
|
|
||||||
attributesToHighlight: ["title", "channel", "description"],
|
|
||||||
attributesToCrop: ["description"],
|
|
||||||
});
|
|
||||||
setVideos(searchResult);
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchPosts = async () => {
|
case MeiliIndices.CONTENT: {
|
||||||
const searchResult = await meiliSearch(MeiliIndices.POST, query, {
|
result.contents = filterHitsWithHighlight<MeiliContent>(searchResult, "translations");
|
||||||
limit: SEARCH_LIMIT,
|
break;
|
||||||
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("</mark>")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
setPosts(searchResult);
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchWeapons = async () => {
|
case MeiliIndices.VIDEOS: {
|
||||||
const searchResult = await meiliSearch(MeiliIndices.WEAPON, query, {
|
result.videos = filterHitsWithHighlight<MeiliVideo>(searchResult);
|
||||||
limit: SEARCH_LIMIT,
|
break;
|
||||||
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("</mark>")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
setWeapons(searchResult);
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchWikiPages = async () => {
|
case MeiliIndices.POST: {
|
||||||
const searchResult = await meiliSearch(MeiliIndices.WIKI_PAGE, query, {
|
result.posts = filterHitsWithHighlight<MeiliPost>(searchResult, "translations");
|
||||||
limit: SEARCH_LIMIT,
|
break;
|
||||||
attributesToHighlight: [
|
}
|
||||||
"translations.title",
|
|
||||||
"translations.aliases",
|
case MeiliIndices.WEAPON: {
|
||||||
"translations.summary",
|
result.weapons = filterHitsWithHighlight<MeiliWeapon>(searchResult, "translations");
|
||||||
"translations.displayable_description",
|
break;
|
||||||
],
|
}
|
||||||
attributesToCrop: ["translations.displayable_description"],
|
|
||||||
});
|
case MeiliIndices.WIKI_PAGE: {
|
||||||
searchResult.hits = searchResult.hits.map((item) => {
|
result.wikiPages = filterHitsWithHighlight<MeiliWikiPage>(searchResult, "translations");
|
||||||
if (
|
break;
|
||||||
Object.keys(item._matchesPosition).filter((match) => match.startsWith("translations"))
|
}
|
||||||
.length > 0
|
|
||||||
) {
|
default: {
|
||||||
item._formatted.translations = filterDefined(item._formatted.translations).filter(
|
console.log("What the fuck?");
|
||||||
(translation) => JSON.stringify(translation).includes("</mark>")
|
}
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return item;
|
|
||||||
});
|
});
|
||||||
setWikiPages(searchResult);
|
|
||||||
|
setMultiResult(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (query === "") {
|
if (query === "") {
|
||||||
setWikiPages(undefined);
|
setMultiResult({});
|
||||||
setLibraryItems(undefined);
|
|
||||||
setContents(undefined);
|
|
||||||
setVideos(undefined);
|
|
||||||
setPosts(undefined);
|
|
||||||
setWeapons(undefined);
|
|
||||||
} else {
|
} else {
|
||||||
fetchWikiPages();
|
fetchMultiResult();
|
||||||
fetchLibraryItems();
|
|
||||||
fetchContents();
|
|
||||||
fetchVideos();
|
|
||||||
fetchPosts();
|
|
||||||
fetchWeapons();
|
|
||||||
}
|
}
|
||||||
}, [query]);
|
}, [query]);
|
||||||
|
|
||||||
|
@ -207,15 +206,15 @@ export const SearchPopup = (): JSX.Element => {
|
||||||
<TextInput onChange={setQuery} value={query} placeholder={format("search_title")} />
|
<TextInput onChange={setQuery} value={query} placeholder={format("search_title")} />
|
||||||
|
|
||||||
<div className="flex w-full flex-wrap gap-12 gap-x-16">
|
<div className="flex w-full flex-wrap gap-12 gap-x-16">
|
||||||
{isDefined(libraryItems) && (
|
{isDefined(multiResult.libraryItems) && (
|
||||||
<SearchResultSection
|
<SearchResultSection
|
||||||
title={format("library")}
|
title={format("library")}
|
||||||
icon="auto_stories"
|
icon="auto_stories"
|
||||||
href={`/library?page=1&query=${query}\
|
href={`/library?page=1&query=${query}\
|
||||||
&sort=0&primary=true&secondary=true&subitems=true&status=all`}
|
&sort=0&primary=true&secondary=true&subitems=true&status=all`}
|
||||||
totalHits={libraryItems.estimatedTotalHits}>
|
totalHits={multiResult.libraryItems.estimatedTotalHits}>
|
||||||
<div className="flex flex-wrap items-start gap-x-6 gap-y-8">
|
<div className="flex flex-wrap items-start gap-x-6 gap-y-8">
|
||||||
{libraryItems.hits.map((item) => (
|
{multiResult.libraryItems.hits.map((item) => (
|
||||||
<TranslatedPreviewCard
|
<TranslatedPreviewCard
|
||||||
key={item.id}
|
key={item.id}
|
||||||
className="w-56"
|
className="w-56"
|
||||||
|
@ -255,14 +254,14 @@ export const SearchPopup = (): JSX.Element => {
|
||||||
</SearchResultSection>
|
</SearchResultSection>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isDefined(contents) && (
|
{isDefined(multiResult.contents) && (
|
||||||
<SearchResultSection
|
<SearchResultSection
|
||||||
title={format("contents")}
|
title={format("contents")}
|
||||||
icon="workspaces"
|
icon="workspaces"
|
||||||
href={`/contents/all?page=1&query=${query}&sort=0`}
|
href={`/contents/all?page=1&query=${query}&sort=0`}
|
||||||
totalHits={contents.estimatedTotalHits}>
|
totalHits={multiResult.contents.estimatedTotalHits}>
|
||||||
<div className="flex flex-wrap items-start gap-x-6 gap-y-8">
|
<div className="flex flex-wrap items-start gap-x-6 gap-y-8">
|
||||||
{contents.hits.map((item) => (
|
{multiResult.contents.hits.map((item) => (
|
||||||
<TranslatedPreviewCard
|
<TranslatedPreviewCard
|
||||||
key={item.id}
|
key={item.id}
|
||||||
className="w-56"
|
className="w-56"
|
||||||
|
@ -300,14 +299,14 @@ export const SearchPopup = (): JSX.Element => {
|
||||||
</SearchResultSection>
|
</SearchResultSection>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isDefined(wikiPages) && (
|
{isDefined(multiResult.wikiPages) && (
|
||||||
<SearchResultSection
|
<SearchResultSection
|
||||||
title={format("wiki")}
|
title={format("wiki")}
|
||||||
icon="travel_explore"
|
icon="travel_explore"
|
||||||
href={`/wiki?page=1&query=${query}`}
|
href={`/wiki?page=1&query=${query}`}
|
||||||
totalHits={wikiPages.estimatedTotalHits}>
|
totalHits={multiResult.wikiPages.estimatedTotalHits}>
|
||||||
<div className="flex flex-wrap items-start gap-x-6 gap-y-8">
|
<div className="flex flex-wrap items-start gap-x-6 gap-y-8">
|
||||||
{wikiPages.hits.map((item) => (
|
{multiResult.wikiPages.hits.map((item) => (
|
||||||
<TranslatedPreviewCard
|
<TranslatedPreviewCard
|
||||||
key={item.id}
|
key={item.id}
|
||||||
className="w-56"
|
className="w-56"
|
||||||
|
@ -352,14 +351,14 @@ export const SearchPopup = (): JSX.Element => {
|
||||||
</SearchResultSection>
|
</SearchResultSection>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isDefined(posts) && (
|
{isDefined(multiResult.posts) && (
|
||||||
<SearchResultSection
|
<SearchResultSection
|
||||||
title={format("news")}
|
title={format("news")}
|
||||||
icon="newspaper"
|
icon="newspaper"
|
||||||
href={`/news?page=1&query=${query}`}
|
href={`/news?page=1&query=${query}`}
|
||||||
totalHits={posts.estimatedTotalHits}>
|
totalHits={multiResult.posts.estimatedTotalHits}>
|
||||||
<div className="flex flex-wrap items-start gap-x-6 gap-y-8">
|
<div className="flex flex-wrap items-start gap-x-6 gap-y-8">
|
||||||
{posts.hits.map((item) => (
|
{multiResult.posts.hits.map((item) => (
|
||||||
<TranslatedPreviewCard
|
<TranslatedPreviewCard
|
||||||
className="w-56"
|
className="w-56"
|
||||||
key={item.id}
|
key={item.id}
|
||||||
|
@ -395,14 +394,14 @@ export const SearchPopup = (): JSX.Element => {
|
||||||
</SearchResultSection>
|
</SearchResultSection>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isDefined(videos) && (
|
{isDefined(multiResult.videos) && (
|
||||||
<SearchResultSection
|
<SearchResultSection
|
||||||
title={format("videos")}
|
title={format("videos")}
|
||||||
icon="movie"
|
icon="movie"
|
||||||
href={`/archives/videos?page=1&query=${query}&sort=1&gone=`}
|
href={`/archives/videos?page=1&query=${query}&sort=1&gone=`}
|
||||||
totalHits={videos.estimatedTotalHits}>
|
totalHits={multiResult.videos.estimatedTotalHits}>
|
||||||
<div className="flex flex-wrap items-start gap-x-6 gap-y-8">
|
<div className="flex flex-wrap items-start gap-x-6 gap-y-8">
|
||||||
{videos.hits.map((item) => (
|
{multiResult.videos.hits.map((item) => (
|
||||||
<PreviewCard
|
<PreviewCard
|
||||||
className="w-56"
|
className="w-56"
|
||||||
key={item.uid}
|
key={item.uid}
|
||||||
|
@ -435,14 +434,14 @@ export const SearchPopup = (): JSX.Element => {
|
||||||
</SearchResultSection>
|
</SearchResultSection>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isDefined(weapons) && (
|
{isDefined(multiResult.weapons) && (
|
||||||
<SearchResultSection
|
<SearchResultSection
|
||||||
title={format("weapon", { count: Infinity })}
|
title={format("weapon", { count: Infinity })}
|
||||||
icon="shield"
|
icon="shield"
|
||||||
href={`/wiki/weapons?page=1&query=${query}`}
|
href={`/wiki/weapons?page=1&query=${query}`}
|
||||||
totalHits={weapons.estimatedTotalHits}>
|
totalHits={multiResult.weapons.estimatedTotalHits}>
|
||||||
<div className="flex flex-wrap items-start gap-x-6 gap-y-8">
|
<div className="flex flex-wrap items-start gap-x-6 gap-y-8">
|
||||||
{weapons.hits.map((item) => (
|
{multiResult.weapons.hits.map((item) => (
|
||||||
<TranslatedPreviewCard
|
<TranslatedPreviewCard
|
||||||
key={item.id}
|
key={item.id}
|
||||||
className="w-56"
|
className="w-56"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// eslint-disable-next-line import/named
|
import Tippy from "@tippyjs/react";
|
||||||
import Tippy, { TippyProps } from "@tippyjs/react";
|
import type { TippyProps } from "@tippyjs/react";
|
||||||
import { cJoin } from "helpers/className";
|
import { cJoin } from "helpers/className";
|
||||||
import "tippy.js/animations/scale-subtle.css";
|
import "tippy.js/animations/scale-subtle.css";
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { atom, PrimitiveAtom, Atom, WritableAtom, useAtom } from "jotai";
|
import { atom, PrimitiveAtom, Atom, WritableAtom, useAtom } from "jotai";
|
||||||
import { Dispatch, SetStateAction } from "react";
|
import { Dispatch, SetStateAction } from "react";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-arguments
|
|
||||||
type AtomPair<T> = [Atom<T>, WritableAtom<null, [newText: T], void>];
|
type AtomPair<T> = [Atom<T>, WritableAtom<null, [newText: T], void>];
|
||||||
|
|
||||||
export const atomPairing = <T>(anAtom: PrimitiveAtom<T>): AtomPair<T> => {
|
export const atomPairing = <T>(anAtom: PrimitiveAtom<T>): AtomPair<T> => {
|
||||||
|
|
|
@ -58,7 +58,6 @@ export const prettyInlineTitle = (
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* eslint-disable id-denylist */
|
|
||||||
export const prettyItemSubType = (
|
export const prettyItemSubType = (
|
||||||
metadata:
|
metadata:
|
||||||
| {
|
| {
|
||||||
|
|
|
@ -4,7 +4,6 @@ export const isUntangibleGroupItem = (
|
||||||
metadata:
|
metadata:
|
||||||
| {
|
| {
|
||||||
__typename: string;
|
__typename: string;
|
||||||
// eslint-disable-next-line id-denylist
|
|
||||||
subtype?: { data?: { attributes?: { slug: string } | null } | null } | null;
|
subtype?: { data?: { attributes?: { slug: string } | null } | null } | null;
|
||||||
}
|
}
|
||||||
| null
|
| null
|
||||||
|
|
|
@ -2,28 +2,30 @@ type LoggerMode = "both" | "client" | "server";
|
||||||
|
|
||||||
const isServer = typeof window === "undefined";
|
const isServer = typeof window === "undefined";
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
type Logger = {
|
||||||
export const getLogger = (prefix: string, mode: LoggerMode = "client") => {
|
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)) {
|
if ((mode === "client" && isServer) || (mode === "server" && !isServer)) {
|
||||||
return {
|
return {
|
||||||
error: () => null,
|
error: () => undefined,
|
||||||
warn: () => null,
|
warn: () => undefined,
|
||||||
log: () => null,
|
log: () => undefined,
|
||||||
info: () => null,
|
info: () => undefined,
|
||||||
debug: () => null,
|
debug: () => undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
error: (message?: unknown, ...optionalParams: unknown[]) =>
|
error: (message, ...optionalParams) => console.error(prefix, message, ...optionalParams),
|
||||||
console.error(prefix, message, ...optionalParams),
|
warn: (message, ...optionalParams) => console.warn(prefix, message, ...optionalParams),
|
||||||
warn: (message?: unknown, ...optionalParams: unknown[]) =>
|
log: (message, ...optionalParams) => console.log(prefix, message, ...optionalParams),
|
||||||
console.warn(prefix, message, ...optionalParams),
|
info: (message, ...optionalParams) => console.info(prefix, message, ...optionalParams),
|
||||||
log: (message?: unknown, ...optionalParams: unknown[]) =>
|
debug: (message, ...optionalParams) => console.debug(prefix, message, ...optionalParams),
|
||||||
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),
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
import { MeiliSearch } from "meilisearch";
|
||||||
// eslint-disable-next-line import/named
|
import type {
|
||||||
import { MatchesPosition, MeiliSearch, SearchParams, SearchResponse } from "meilisearch";
|
SearchParams,
|
||||||
import { isDefined } from "./asserts";
|
MatchesPosition,
|
||||||
|
SearchResponse,
|
||||||
|
MultiSearchQuery,
|
||||||
|
MultiSearchResponse,
|
||||||
|
MultiSearchResult,
|
||||||
|
} from "meilisearch";
|
||||||
|
import { filterDefined, isDefined } from "./asserts";
|
||||||
import { MeiliDocumentsType } from "shared/meilisearch-graphql-typings/meiliTypes";
|
import { MeiliDocumentsType } from "shared/meilisearch-graphql-typings/meiliTypes";
|
||||||
|
|
||||||
const meili = new MeiliSearch({
|
const meili = new MeiliSearch({
|
||||||
|
@ -12,20 +18,61 @@ const meili = new MeiliSearch({
|
||||||
interface CustomSearchParams
|
interface CustomSearchParams
|
||||||
extends Omit<
|
extends Omit<
|
||||||
SearchParams,
|
SearchParams,
|
||||||
"cropMarker" | "highlightPostTag" | "highlightPreTag" | "q" | "showMatchesPosition"
|
| "cropLength"
|
||||||
|
| "cropMarker"
|
||||||
|
| "cropMarker"
|
||||||
|
| "highlightPostTag"
|
||||||
|
| "highlightPreTag"
|
||||||
|
| "q"
|
||||||
|
| "showMatchesPosition"
|
||||||
> {}
|
> {}
|
||||||
|
|
||||||
type CustomHit<T = Record<string, any>> = T & {
|
type CustomHit<T = Record<string, unknown>> = T & {
|
||||||
_formatted: Partial<T>;
|
_formatted: Partial<T>;
|
||||||
_matchesPosition: MatchesPosition<T>;
|
_matchesPosition: MatchesPosition<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
type CustomHits<T = Record<string, any>> = CustomHit<T>[];
|
type CustomHits<T = Record<string, unknown>> = CustomHit<T>[];
|
||||||
|
|
||||||
export interface CustomSearchResponse<T> extends Omit<SearchResponse<T>, "hits"> {
|
export interface CustomSearchResponse<T> extends Omit<SearchResponse<T>, "hits"> {
|
||||||
hits: CustomHits<T>;
|
hits: CustomHits<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const meiliMultiSearch = async (queries: MultiSearchQuery[]): Promise<MultiSearchResponse> =>
|
||||||
|
await meili.multiSearch({
|
||||||
|
queries: queries.map((query) => ({
|
||||||
|
attributesToHighlight: ["*"],
|
||||||
|
...query,
|
||||||
|
highlightPreTag: "<mark>",
|
||||||
|
highlightPostTag: "</mark>",
|
||||||
|
showMatchesPosition: true,
|
||||||
|
cropLength: 20,
|
||||||
|
cropMarker: "...",
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const filterHitsWithHighlight = <T extends MeiliDocumentsType["documents"]>(
|
||||||
|
searchResult: CustomSearchResponse<T> | MultiSearchResult<Record<string, unknown>>,
|
||||||
|
keyToFilter?: keyof T
|
||||||
|
): CustomSearchResponse<T> => {
|
||||||
|
const result = searchResult as unknown as CustomSearchResponse<T>;
|
||||||
|
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("</mark>")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||||
export const meiliSearch = async <I extends MeiliDocumentsType["index"]>(
|
export const meiliSearch = async <I extends MeiliDocumentsType["index"]>(
|
||||||
indexName: I,
|
indexName: I,
|
||||||
|
|
|
@ -12,16 +12,16 @@ import { TextInput } from "components/Inputs/TextInput";
|
||||||
import { WithLabel } from "components/Inputs/WithLabel";
|
import { WithLabel } from "components/Inputs/WithLabel";
|
||||||
import { Button } from "components/Inputs/Button";
|
import { Button } from "components/Inputs/Button";
|
||||||
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
||||||
import {
|
import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
filterDefined,
|
|
||||||
filterHasAttributes,
|
|
||||||
isDefined,
|
|
||||||
isDefinedAndNotEmpty,
|
|
||||||
} from "helpers/asserts";
|
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { HorizontalLine } from "components/HorizontalLine";
|
import { HorizontalLine } from "components/HorizontalLine";
|
||||||
import { sendAnalytics } from "helpers/analytics";
|
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 { MeiliContent, MeiliIndices } from "shared/meilisearch-graphql-typings/meiliTypes";
|
||||||
import { useTypedRouter } from "hooks/useTypedRouter";
|
import { useTypedRouter } from "hooks/useTypedRouter";
|
||||||
import { TranslatedPreviewCard } from "components/PreviewCard";
|
import { TranslatedPreviewCard } from "components/PreviewCard";
|
||||||
|
@ -97,15 +97,7 @@ const Contents = (props: Props): JSX.Element => {
|
||||||
page,
|
page,
|
||||||
sort: isDefined(currentSortingMethod) ? [currentSortingMethod.meiliAttribute] : undefined,
|
sort: isDefined(currentSortingMethod) ? [currentSortingMethod.meiliAttribute] : undefined,
|
||||||
});
|
});
|
||||||
searchResult.hits = searchResult.hits.map((item) => {
|
setContents(filterHitsWithHighlight<MeiliContent>(searchResult, "translations"));
|
||||||
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);
|
|
||||||
};
|
};
|
||||||
fetchPosts();
|
fetchPosts();
|
||||||
}, [query, page, sortingMethod, sortingMethods]);
|
}, [query, page, sortingMethod, sortingMethods]);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/* eslint-disable id-denylist */
|
|
||||||
import { GetStaticProps } from "next";
|
import { GetStaticProps } from "next";
|
||||||
import { ReactNode, useState } from "react";
|
import { ReactNode, useState } from "react";
|
||||||
import Slider from "rc-slider";
|
import Slider from "rc-slider";
|
||||||
|
|
|
@ -14,17 +14,16 @@ import { TextInput } from "components/Inputs/TextInput";
|
||||||
import { Button } from "components/Inputs/Button";
|
import { Button } from "components/Inputs/Button";
|
||||||
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
||||||
import { ButtonGroup } from "components/Inputs/ButtonGroup";
|
import { ButtonGroup } from "components/Inputs/ButtonGroup";
|
||||||
import {
|
import { filterHasAttributes, isDefined, isDefinedAndNotEmpty, isUndefined } from "helpers/asserts";
|
||||||
filterDefined,
|
|
||||||
filterHasAttributes,
|
|
||||||
isDefined,
|
|
||||||
isDefinedAndNotEmpty,
|
|
||||||
isUndefined,
|
|
||||||
} from "helpers/asserts";
|
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { HorizontalLine } from "components/HorizontalLine";
|
import { HorizontalLine } from "components/HorizontalLine";
|
||||||
import { sendAnalytics } from "helpers/analytics";
|
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 { MeiliIndices, MeiliLibraryItem } from "shared/meilisearch-graphql-typings/meiliTypes";
|
||||||
import { useTypedRouter } from "hooks/useTypedRouter";
|
import { useTypedRouter } from "hooks/useTypedRouter";
|
||||||
import { TranslatedPreviewCard } from "components/PreviewCard";
|
import { TranslatedPreviewCard } from "components/PreviewCard";
|
||||||
|
@ -178,15 +177,7 @@ const Library = (props: Props): JSX.Element => {
|
||||||
sort: isDefined(currentSortingMethod) ? [currentSortingMethod.meiliAttribute] : undefined,
|
sort: isDefined(currentSortingMethod) ? [currentSortingMethod.meiliAttribute] : undefined,
|
||||||
filter,
|
filter,
|
||||||
});
|
});
|
||||||
searchResult.hits = searchResult.hits.map((item) => {
|
setLibraryItems(filterHitsWithHighlight<MeiliLibraryItem>(searchResult, "descriptions"));
|
||||||
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);
|
|
||||||
};
|
};
|
||||||
fetchLibraryItems();
|
fetchLibraryItems();
|
||||||
}, [
|
}, [
|
||||||
|
|
|
@ -11,12 +11,7 @@ import { WithLabel } from "components/Inputs/WithLabel";
|
||||||
import { TextInput } from "components/Inputs/TextInput";
|
import { TextInput } from "components/Inputs/TextInput";
|
||||||
import { Button } from "components/Inputs/Button";
|
import { Button } from "components/Inputs/Button";
|
||||||
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
import { useDeviceSupportsHover } from "hooks/useMediaQuery";
|
||||||
import {
|
import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
filterDefined,
|
|
||||||
filterHasAttributes,
|
|
||||||
isDefined,
|
|
||||||
isDefinedAndNotEmpty,
|
|
||||||
} from "helpers/asserts";
|
|
||||||
import { getOpenGraph } from "helpers/openGraph";
|
import { getOpenGraph } from "helpers/openGraph";
|
||||||
import { TranslatedPreviewCard } from "components/PreviewCard";
|
import { TranslatedPreviewCard } from "components/PreviewCard";
|
||||||
import { HorizontalLine } from "components/HorizontalLine";
|
import { HorizontalLine } from "components/HorizontalLine";
|
||||||
|
@ -24,7 +19,12 @@ import { sendAnalytics } from "helpers/analytics";
|
||||||
import { Terminal } from "components/Cli/Terminal";
|
import { Terminal } from "components/Cli/Terminal";
|
||||||
import { atoms } from "contexts/atoms";
|
import { atoms } from "contexts/atoms";
|
||||||
import { useAtomGetter } from "helpers/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 { MeiliIndices, MeiliPost } from "shared/meilisearch-graphql-typings/meiliTypes";
|
||||||
import { useTypedRouter } from "hooks/useTypedRouter";
|
import { useTypedRouter } from "hooks/useTypedRouter";
|
||||||
import { prettySlug } from "helpers/formatters";
|
import { prettySlug } from "helpers/formatters";
|
||||||
|
@ -84,15 +84,7 @@ const News = ({ ...otherProps }: Props): JSX.Element => {
|
||||||
sort: ["sortable_date:desc"],
|
sort: ["sortable_date:desc"],
|
||||||
filter: ["hidden = false"],
|
filter: ["hidden = false"],
|
||||||
});
|
});
|
||||||
searchResult.hits = searchResult.hits.map((item) => {
|
setPosts(filterHitsWithHighlight<MeiliPost>(searchResult, "translations"));
|
||||||
if (Object.keys(item._matchesPosition).some((match) => match.startsWith("translations"))) {
|
|
||||||
item._formatted.translations = filterDefined(item._formatted.translations).filter(
|
|
||||||
(translation) => JSON.stringify(translation).includes("</mark>")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
setPosts(searchResult);
|
|
||||||
};
|
};
|
||||||
fetchPosts();
|
fetchPosts();
|
||||||
}, [query, page]);
|
}, [query, page]);
|
||||||
|
|
|
@ -10,16 +10,16 @@ import { PanelHeader } from "components/PanelComponents/PanelHeader";
|
||||||
import { TextInput } from "components/Inputs/TextInput";
|
import { TextInput } from "components/Inputs/TextInput";
|
||||||
import { useTypedRouter } from "hooks/useTypedRouter";
|
import { useTypedRouter } from "hooks/useTypedRouter";
|
||||||
import { useFormat } from "hooks/useFormat";
|
import { useFormat } from "hooks/useFormat";
|
||||||
import {
|
import { filterHasAttributes, isDefined, isDefinedAndNotEmpty } from "helpers/asserts";
|
||||||
filterDefined,
|
|
||||||
filterHasAttributes,
|
|
||||||
isDefined,
|
|
||||||
isDefinedAndNotEmpty,
|
|
||||||
} from "helpers/asserts";
|
|
||||||
import { sendAnalytics } from "helpers/analytics";
|
import { sendAnalytics } from "helpers/analytics";
|
||||||
import { Button } from "components/Inputs/Button";
|
import { Button } from "components/Inputs/Button";
|
||||||
import { HorizontalLine } from "components/HorizontalLine";
|
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 { MeiliIndices, MeiliWeapon } from "shared/meilisearch-graphql-typings/meiliTypes";
|
||||||
import { ContentPanel, ContentPanelWidthSizes } from "components/Containers/ContentPanel";
|
import { ContentPanel, ContentPanelWidthSizes } from "components/Containers/ContentPanel";
|
||||||
import { Paginator } from "components/Containers/Paginator";
|
import { Paginator } from "components/Containers/Paginator";
|
||||||
|
@ -79,17 +79,7 @@ const Weapons = (props: Props): JSX.Element => {
|
||||||
attributesToCrop: ["translations.description"],
|
attributesToCrop: ["translations.description"],
|
||||||
sort: ["slug:asc"],
|
sort: ["slug:asc"],
|
||||||
});
|
});
|
||||||
|
setWeapons(filterHitsWithHighlight<MeiliWeapon>(searchResult, "translations"));
|
||||||
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("</mark>")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
|
|
||||||
setWeapons(searchResult);
|
|
||||||
};
|
};
|
||||||
fetchPosts();
|
fetchPosts();
|
||||||
}, [query, page]);
|
}, [query, page]);
|
||||||
|
|
Loading…
Reference in New Issue