Skip to content

Commit c7792c0

Browse files
jeremysteeriohyrsky
authored andcommitted
UHF-12236: Fix errors
Signed-off-by: Santeri Hurnanen <santeri.hurnanen@fame.fi>
1 parent 58fc273 commit c7792c0

14 files changed

Lines changed: 205 additions & 177 deletions

File tree

public/themes/custom/hdbt_subtheme/dist/js/hyte-search.min.js

Lines changed: 47 additions & 47 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/themes/custom/hdbt_subtheme/src/js/react/apps/hyte-search/components/KeywordFilter.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useAtomValue, useSetAtom } from 'jotai';
22
import { getKeywordAtom, initializedAtom, setSearchStateAtom } from '../store';
33
import { TextInput } from 'hds-react';
4-
import { Components } from '../../../enum/Components';
4+
import { Components } from 'src/js/react/enum/Components';
55

66
export const KeywordFilter = () => {
77
const initialized = useAtomValue(initializedAtom);

public/themes/custom/hdbt_subtheme/src/js/react/apps/hyte-search/components/ResultCard.tsx

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
1-
// biome-ignore-all lint/correctness/useJsxKeyInIterable: @todo UHF-12501
2-
// biome-ignore-all lint/style/noNonNullAssertion: @todo UHF-12501
3-
import { IconLocation } from 'hds-react';
4-
import { Themes } from '../../../enum/Themes';
1+
import { Themes } from 'src/js/react/enum/Themes';
52
import type TagType from '@/common/types/TagType';
63
import CardItem, { Metarow } from '@/react/common/Card';
7-
import type { Service } from '../types/Service';
4+
import type { Service, Unit } from '../types/Service';
5+
import { getElasticUrlAtom } from '../store';
6+
import { useAtomValue } from 'jotai';
7+
8+
declare const ELASTIC_DEV_URL: string | undefined;
9+
10+
export const ResultCard = ({
11+
description_summary,
12+
name,
13+
name_override,
14+
name_synonyms,
15+
units,
16+
url,
17+
}: Service & { units: Unit[] }) => {
18+
const elasticUrl = useAtomValue(getElasticUrlAtom);
819

9-
export const ResultCard = ({ description_summary, name, name_override, name_synonyms, units, url }: Service) => {
1020
const getUnits = () => {
1121
if (!units?.length) {
1222
return [];
@@ -15,25 +25,33 @@ export const ResultCard = ({ description_summary, name, name_override, name_syno
1525
return [
1626
<Metarow
1727
content={units.length.toString()}
18-
icon={<IconLocation />}
28+
icon={<span className='hel-icon hel-icon--location' />}
1929
label={`${Drupal.t('Locations', {}, { context: 'Hyte search' })}`}
30+
key='location'
2031
/>,
2132
];
2233
};
2334

2435
const getTags = (): TagType[] => {
25-
/** @todo implement better once BE changes are made */
26-
const foundThemes = name_synonyms
27-
?.toString()
28-
.split(',')
29-
.map((tag) => tag.trim())
30-
.filter((tag) => Themes.has(tag));
36+
const foundThemes = name_synonyms?.map((tag) => tag.trim()).filter((tag) => Themes.has(tag));
3137

3238
if (!foundThemes?.length) {
3339
return [];
3440
}
3541

36-
return foundThemes.map((theme: string) => ({ tag: Themes.get(theme)! }));
42+
return foundThemes.map((theme: string) => ({ tag: Themes.get(theme) }));
43+
};
44+
45+
// For ease-of-testing, makes test environment images work
46+
const enrichImageUrl = (imageUrl: string): string => {
47+
if (
48+
typeof ELASTIC_DEV_URL !== 'undefined' &&
49+
elasticUrl.includes('arodevtest') &&
50+
!/^https?:\/\//i.test(imageUrl)
51+
) {
52+
return `https://www.test.hel.ninja${imageUrl}`;
53+
}
54+
return imageUrl;
3755
};
3856

3957
const getImage = (): JSX.Element | undefined => {
@@ -42,15 +60,15 @@ export const ResultCard = ({ description_summary, name, name_override, name_syno
4260
}
4361

4462
const srcSet = units[0]?.['image.variants.1.5_1022w_682h_LQ']
45-
? `${units[0]?.['image.variants.1.5_1022w_682h_LQ']} 2x`
63+
? `${enrichImageUrl(units[0]?.['image.variants.1.5_1022w_682h_LQ'].toString())} 2x`
4664
: undefined;
4765

4866
return (
4967
<img
5068
alt={units[0]?.['image.alt']?.toString() || ''}
5169
data-photographer={units[0]?.['image.photographer']?.toString() || ''}
5270
className='card__image'
53-
src={units[0]?.['image.url']?.[0]}
71+
src={enrichImageUrl(units[0]?.['image.url']?.[0])}
5472
srcSet={srcSet}
5573
title={units[0]?.['image.title']?.toString() || ''}
5674
/>

public/themes/custom/hdbt_subtheme/src/js/react/apps/hyte-search/components/SearchBar.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { TextInput } from 'hds-react';
22
import { useAtomValue, useSetAtom } from 'jotai';
3-
import { Components } from '../../../enum/Components';
3+
import { Components } from 'src/js/react/enum/Components';
44
import { AddressSearch, type AddressWithCoordinates } from '@/react/common/AddressSearch';
55
import { getAddressAtom, initializedAtom, setSearchStateAtom } from '../store';
66

@@ -25,10 +25,7 @@ export const SearchBar = () => {
2525
};
2626

2727
const onSubmit = (address: AddressWithCoordinates) => {
28-
setSearchState({
29-
addressWithCoordinates: address,
30-
[Components.ADDRESS]: address.label,
31-
});
28+
setSearchState({ addressWithCoordinates: address, [Components.ADDRESS]: address.label });
3229
};
3330

3431
return (

public/themes/custom/hdbt_subtheme/src/js/react/apps/hyte-search/components/ThemeFilter.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import { type Option, Select } from 'hds-react';
22
import { useAtomValue, useSetAtom } from 'jotai';
3-
import { Components } from '../../../enum/Components';
4-
import { Themes } from '../../../enum/Themes';
3+
import { Components } from 'src/js/react/enum/Components';
4+
import { Themes } from 'src/js/react/enum/Themes';
55
import { getThemeAtom, initializedAtom, setSearchStateAtom } from '../store';
66

7-
const options = [...Themes].map(([value, label]) => ({ value, label })).sort((a, b) => a.label.localeCompare(b.label));
7+
const options = [...Themes]
8+
.filter(([value]) => ['hh_kul', 'hh_liik', 'hh_opi', 'hh_vet', 'hh_yht'].includes(value))
9+
.map(([value, label]) => ({ value, label }))
10+
.sort((a, b) => a.label.localeCompare(b.label));
811

912
export const ThemeFilter = () => {
1013
const initialized = useAtomValue(initializedAtom);
@@ -23,7 +26,10 @@ export const ThemeFilter = () => {
2326
noTags
2427
options={options}
2528
onChange={setThemes}
26-
texts={{ label: Drupal.t('Theme', {}, { context: 'React search' }) }}
29+
texts={{
30+
label: Drupal.t('Theme', {}, { context: 'React search' }),
31+
placeholder: Drupal.t('Select one or more themes', {}, { context: 'Hyte search' }),
32+
}}
2733
value={themes}
2834
/>
2935
);

public/themes/custom/hdbt_subtheme/src/js/react/apps/hyte-search/containers/ResultsContainer.tsx

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
1-
// biome-ignore-all lint/correctness/useExhaustiveDependencies: @todo UHF-12501
2-
// biome-ignore-all lint/suspicious/noExplicitAny: @todo UHF-12501
31
import type { estypes } from '@elastic/elasticsearch';
42
import { useAtomValue, useSetAtom } from 'jotai';
53
import { useAtomCallback } from 'jotai/react/utils';
64
import { useCallback, useEffect } from 'react';
7-
import { Components } from '../../../enum/Components';
5+
import { Components } from 'src/js/react/enum/Components';
86
import useSwr from 'swr';
97
import { AddressNotFound } from '@/react/common/AddressNotFound';
108
import { GhostList } from '@/react/common/GhostList';
119
import { ResultsWrapper } from '@/react/common/ResultsWrapper';
1210
import { ResultCard } from '../components/ResultCard';
1311
import { useQuery } from '../hooks/useQuery';
14-
import { getPageAtom, initializedAtom, setPageAtom, shouldScrollAtom, submittedStateAtom } from '../store';
15-
import type { Service } from '../types/Service';
12+
import {
13+
getElasticUrlAtom,
14+
getPageAtom,
15+
initializedAtom,
16+
setPageAtom,
17+
shouldScrollAtom,
18+
submittedStateAtom,
19+
} from '../store';
20+
import type { Service, Unit } from '../types/Service';
1621

17-
export const ResultsContainer = ({ url }: { url: string }) => {
22+
export const ResultsContainer = () => {
23+
const url = useAtomValue(getElasticUrlAtom);
1824
const initialized = useAtomValue(initializedAtom);
1925
const query = useQuery();
2026
const submittedState = useAtomValue(submittedStateAtom);
@@ -25,7 +31,7 @@ export const ResultsContainer = ({ url }: { url: string }) => {
2531

2632
const fetcher = useCallback(
2733
(query: string) =>
28-
fetch(url, {
34+
fetch(`${url}/hyte/_search`, {
2935
method: 'POST',
3036
headers: { 'Content-Type': 'application/json' },
3137
body: query,
@@ -46,7 +52,7 @@ export const ResultsContainer = ({ url }: { url: string }) => {
4652
if (!readShouldScroll() && !loading && initialized) {
4753
setShouldScroll(true);
4854
}
49-
}, [loading, readShouldScroll, setShouldScroll]);
55+
}, [initialized, loading, readShouldScroll, setShouldScroll]);
5056

5157
if (!initialized) {
5258
return <GhostList count={10} />;
@@ -56,17 +62,39 @@ export const ResultsContainer = ({ url }: { url: string }) => {
5662
return <AddressNotFound />;
5763
}
5864

59-
const resultItemCallBack = (item: estypes.SearchHit<any>) => (
60-
<ResultCard key={item._id} {...(item.fields as Service)} />
61-
);
65+
const resultItemCallBack = (item: estypes.SearchHit<Service>) => {
66+
const service = item.inner_hits?.collapsed_services.hits.hits[0];
67+
68+
if (!service) {
69+
throw new Error('Service inner hit is missing');
70+
}
71+
72+
const units: Unit[] =
73+
service.inner_hits?.sorted_units.hits.hits.reduce<Unit[]>((acc, unitHit) => {
74+
unitHit?.fields?.units.forEach((unit: Unit) => {
75+
acc.push(unit);
76+
});
77+
return acc;
78+
}, []) ||
79+
service.fields?.units ||
80+
[];
81+
82+
return <ResultCard {...(service.fields as Service)} key={item._id} units={units} />;
83+
};
6284

6385
return (
6486
<ResultsWrapper
6587
currentPage={currentPage}
6688
data={data}
6789
error={error}
6890
getHeaderText={() =>
69-
Drupal.formatPlural(data?.hits.total.value ?? 0, '1 result', '@count results', {}, { context: 'Hyte search' })
91+
Drupal.formatPlural(
92+
data.aggregations?.total_services?.value ?? 0,
93+
'1 result',
94+
'@count results',
95+
{},
96+
{ context: 'Hyte search' },
97+
)
7098
}
7199
isLoading={loading}
72100
resultItemCallBack={resultItemCallBack}

public/themes/custom/hdbt_subtheme/src/js/react/apps/hyte-search/containers/SearchContainer.tsx

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,25 @@
33
import type { estypes } from '@elastic/elasticsearch';
44
import { useAtomValue, useSetAtom } from 'jotai';
55
import { useEffect } from 'react';
6-
import { IndexFields } from '../../../enum/IndexFields';
6+
import { IndexFields } from 'src/js/react/enum/IndexFields';
77
import useSWRImmutable from 'swr/immutable';
8-
import { initializeAppAtom, initializedAtom } from '../store';
8+
import { getElasticUrlAtom, initializeAppAtom, initializedAtom } from '../store';
99
import { FormContainer } from './FormContainer';
1010
import { ResultsContainer } from './ResultsContainer';
1111

1212
const aggsQueryString = JSON.stringify({
1313
_source: false,
14-
aggs: {
15-
themes: {
16-
terms: {
17-
field: `${IndexFields.NAME_SYNONYMS}.keyword`,
18-
size: 10000,
19-
order: { _key: 'asc' },
20-
},
21-
},
22-
},
14+
aggs: { themes: { terms: { field: `${IndexFields.NAME_SYNONYMS}.keyword`, size: 10000, order: { _key: 'asc' } } } },
2315
query: { match_all: {} },
2416
});
2517

26-
export const SearchContainer = ({ url }: { url: string }) => {
18+
export const SearchContainer = () => {
19+
const url = useAtomValue(getElasticUrlAtom);
2720
const initialized = useAtomValue(initializedAtom);
2821
const initializeApp = useSetAtom(initializeAppAtom);
2922

3023
const fetcher = async (query: string) => {
31-
const response = await fetch(url, {
24+
const response = await fetch(`${url}/hyte/_search`, {
3225
method: 'POST',
3326
headers: { 'Content-Type': 'application/json' },
3427
body: query,
@@ -53,7 +46,7 @@ export const SearchContainer = ({ url }: { url: string }) => {
5346
return (
5447
<>
5548
<FormContainer />
56-
<ResultsContainer url={url} />
49+
<ResultsContainer />
5750
</>
5851
);
5952
};

public/themes/custom/hdbt_subtheme/src/js/react/apps/hyte-search/containers/SelectionsContainer.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { useAtomValue, useSetAtom } from 'jotai';
33
import { RESET } from 'jotai/utils';
44

5-
import { Components } from '../../../enum/Components';
5+
import { Components } from 'src/js/react/enum/Components';
66
import FilterButton from '@/react/common/FilterButton';
77
import SelectionsWrapper from '@/react/common/SelectionsWrapper';
88
import { setSearchStateAtom, submitStateAtom, submittedStateAtom } from '../store';

0 commit comments

Comments
 (0)