Skip to content

Commit d7753cf

Browse files
committed
Støtter søk i flere kategorier
1 parent 71ce8a3 commit d7753cf

File tree

7 files changed

+85
-52
lines changed

7 files changed

+85
-52
lines changed

common/contentSearch.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export type ContentSearchParams = {
2020
from: number;
2121
size: number;
2222
fullQuery?: boolean;
23-
categoryKey?: string;
23+
categoryKeys?: string[];
2424
query?: string;
2525
sort?: ContentSearchSort;
2626
};

server/src/opensearch/queries/contentSearch.ts

+10-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
} from '@opensearch-project/opensearch/api/types';
66
import { ContentSearchParams, ContentSearchSort } from '../../../../common/contentSearch';
77
import { Request } from 'express';
8-
import { parseNumberParam } from '../../utils/queryParams';
8+
import { parseNumberParam, parseToStringArray } from '../../utils/queryParams';
99

1010
const SIZE_DEFAULT = 50;
1111

@@ -27,12 +27,15 @@ const sortParams: Record<ContentSearchSort, SearchSort> = {
2727
} as const;
2828

2929
export const transformQueryToContentSearchParams = (req: Request): ContentSearchParams | null => {
30-
const { query, fullQuery, size, sort, from, categoryKey } = req.query as Record<string, string>;
30+
const { query, fullQuery, size, sort, from, categoryKeys } = req.query as Record<
31+
string,
32+
string
33+
>;
3134

3235
return {
3336
query,
3437
fullQuery: fullQuery === 'true',
35-
categoryKey,
38+
categoryKeys: parseToStringArray(categoryKeys),
3639
sort: isValidSort(sort) ? sort : 'score',
3740
from: parseNumberParam(from) ?? 0,
3841
size: parseNumberParam(size) ?? SIZE_DEFAULT,
@@ -44,7 +47,7 @@ const includedFields = ['contentKey', 'versionKey', 'displayName', 'category.key
4447
export const buildContentSearchParams = (
4548
contentSearchParams: ContentSearchParams
4649
): SearchRequest => {
47-
const { query, from, size, sort = 'score', fullQuery, categoryKey } = contentSearchParams;
50+
const { query, from, size, sort = 'score', fullQuery, categoryKeys } = contentSearchParams;
4851

4952
const must: QueryDslQueryContainer[] = [
5053
{
@@ -72,10 +75,10 @@ export const buildContentSearchParams = (
7275
});
7376
}
7477

75-
if (categoryKey) {
78+
if (categoryKeys) {
7679
must.push({
77-
term: {
78-
'category.key': categoryKey,
80+
terms: {
81+
'category.key': categoryKeys,
7982
},
8083
});
8184
}

server/src/utils/queryParams.ts

+22
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,25 @@ export const parseQueryParamsList = (param: unknown): string[] | null => {
99
export const parseNumberParam = (value: unknown): number | undefined => {
1010
return Number(value) || undefined;
1111
};
12+
13+
export const parseToStringArray = (value: unknown): string[] | undefined => {
14+
try {
15+
if (typeof value !== 'string') {
16+
console.log('Value is not a string');
17+
return undefined;
18+
}
19+
20+
const parsed = JSON.parse(value);
21+
22+
if (Array.isArray(parsed)) {
23+
console.log('Parsed value is an array');
24+
return parsed.map((item) => item.toString());
25+
}
26+
27+
console.log(`Parsed value is something else: ${typeof parsed}`);
28+
return [parsed];
29+
} catch (e) {
30+
console.error(`Error parsing value: ${e}`);
31+
return undefined;
32+
}
33+
};

src/components/left-section/search/SearchInput.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const SearchInput = ({ setSearchResult, className }: Props) => {
1616
const inputRef = useRef<HTMLInputElement>(null);
1717
const [advancedSearchOpen, setAdvancedSearchOpen] = useState(false);
1818

19-
const { fetchSearchSimple } = useApiFetch();
19+
const { fetchSearch } = useApiFetch();
2020

2121
return (
2222
<div className={classNames(style.search, className)}>
@@ -49,7 +49,7 @@ export const SearchInput = ({ setSearchResult, className }: Props) => {
4949
status: 'loading',
5050
});
5151

52-
fetchSearchSimple(queryInput).then((result) => {
52+
fetchSearch({ query: queryInput, from: 0, size: 50 }).then((result) => {
5353
setSearchResult(result);
5454
});
5555
}}

src/fetch/fetchJson.ts

+23-18
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
1-
export const fetchJson = <ResponseType>(
1+
export const fetchJson = async <ResponseType>(
22
url: string,
3-
config?: Record<string, unknown>,
3+
params?: Record<string, any>,
44
retries = 1
5-
): Promise<ResponseType | null> =>
6-
fetch(url, config)
7-
.then((res) => {
8-
if (res.ok) {
9-
return res.json();
10-
}
5+
): Promise<ResponseType | null> => {
6+
const paramsString = params
7+
? new URLSearchParams(params as Record<string, string>).toString()
8+
: null;
9+
const urlWithParams = paramsString ? `${url}?${paramsString}` : url;
1110

12-
throw new Error(`${res.status} - ${res.statusText}`);
13-
})
14-
.catch((e) => {
15-
if (retries > 0) {
16-
console.log(`Failed to fetch from ${url}, retrying`);
17-
return fetchJson(url, config, retries - 1);
18-
}
11+
try {
12+
const res = await fetch(urlWithParams);
13+
if (res.ok) {
14+
return res.json();
15+
}
1916

20-
console.error(`Failed to fetch json from ${url} - ${e}`);
21-
return null;
22-
});
17+
throw new Error(`${res.status} - ${res.statusText}`);
18+
} catch (e) {
19+
if (retries > 0) {
20+
console.log(`Failed to fetch from ${urlWithParams}, retrying`);
21+
return fetchJson(url, params, retries - 1);
22+
}
23+
24+
console.error(`Failed to fetch json from ${url} - ${e}`);
25+
return null;
26+
}
27+
};

src/fetch/useApiFetch.ts

+4-20
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { fetchJson } from './fetchJson';
33
import { CmsContent } from '../../common/cms-documents/content';
44
import { CmsCategoryListItem } from '../../common/cms-documents/category';
55
import { useCallback } from 'react';
6-
import { ContentSearchResult } from '../../common/contentSearch';
6+
import { ContentSearchParams, ContentSearchResult } from '../../common/contentSearch';
77

88
const fetchContent = (basePath: string) => async (contentKey: string) =>
99
fetchJson<CmsContent>(`${basePath}/api/content/${contentKey}`);
@@ -20,37 +20,21 @@ const fetchCategories =
2020
)
2121
: [];
2222

23-
export type FetchCategoryContentsParams = {
24-
categoryKey: string;
25-
from: number;
26-
size: number;
27-
query?: string;
28-
};
29-
30-
const fetchCategoryContents =
31-
(basePath: string) =>
32-
async ({ categoryKey, from, size, query = '' }: FetchCategoryContentsParams) =>
33-
fetchJson<ContentSearchResult>(
34-
`${basePath}/api/search?sort=name&from=${from}&size=${size}&query=${query?.length > 2 ? query : ''}&categoryKey=${categoryKey}`
35-
);
36-
37-
const fetchSearchSimple = (basePath: string) => async (query: string) =>
38-
fetchJson<ContentSearchResult>(`${basePath}/api/search?query=${query}`);
23+
const fetchSearch = (basePath: string) => async (params: ContentSearchParams) =>
24+
fetchJson<ContentSearchResult>(`${basePath}/api/search`, params);
3925

4026
export const useApiFetch = () => {
4127
const { appContext } = useAppState();
4228
const { basePath } = appContext;
4329

4430
return {
45-
// eslint-disable-next-line react-hooks/exhaustive-deps
46-
fetchCategoryContents: useCallback(fetchCategoryContents(basePath), [basePath]),
4731
// eslint-disable-next-line react-hooks/exhaustive-deps
4832
fetchContent: useCallback(fetchContent(basePath), [basePath]),
4933
// eslint-disable-next-line react-hooks/exhaustive-deps
5034
fetchContentVersion: useCallback(fetchContentVersion(basePath), [basePath]),
5135
// eslint-disable-next-line react-hooks/exhaustive-deps
5236
fetchCategories: useCallback(fetchCategories(basePath), [basePath]),
5337
// eslint-disable-next-line react-hooks/exhaustive-deps
54-
fetchSearchSimple: useCallback(fetchSearchSimple(basePath), [basePath]),
38+
fetchSearch: useCallback(fetchSearch(basePath), [basePath]),
5539
};
5640
};

src/fetch/useFetchCategoryContents.ts

+23-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,29 @@
11
import useSWRImmutable from 'swr/immutable';
2-
import { FetchCategoryContentsParams, useApiFetch } from './useApiFetch';
2+
import { useApiFetch } from './useApiFetch';
33

4-
export const useFetchCategoryContents = (params: FetchCategoryContentsParams) => {
5-
const { fetchCategoryContents } = useApiFetch();
4+
type FetchCategoryContentsParams = {
5+
categoryKey: string;
6+
from: number;
7+
size: number;
8+
query?: string;
9+
};
10+
11+
export const useFetchCategoryContents = ({
12+
from,
13+
size,
14+
query,
15+
categoryKey,
16+
}: FetchCategoryContentsParams) => {
17+
const { fetchSearch } = useApiFetch();
18+
19+
const params = {
20+
from,
21+
size,
22+
query,
23+
categoryKeys: [categoryKey],
24+
};
625

7-
const { isLoading, data, error } = useSWRImmutable(params, fetchCategoryContents);
26+
const { isLoading, data, error } = useSWRImmutable(params, fetchSearch);
827

928
return { isLoading, result: data, error };
1029
};

0 commit comments

Comments
 (0)