Skip to content

Commit

Permalink
Merge pull request #1161 from City-of-Helsinki/UHF-11057
Browse files Browse the repository at this point in the history
UHF-11057: Support address query param in searches
  • Loading branch information
jeremysteerio authored Jan 23, 2025
2 parents 9c34c97 + 6aea3b0 commit 28b825b
Show file tree
Hide file tree
Showing 24 changed files with 211 additions and 81 deletions.
14 changes: 13 additions & 1 deletion dist/js/health-station-search.min.js

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion dist/js/maternity-and-child-health-clinic-search.min.js

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion dist/js/ploughing-schedule.min.js

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion dist/js/school-search.min.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const ResultsList = ({ data, error, isLoading, isValidating, page, updatePage }:
const { size } = AppSettings;
const params = useAtomValue(paramsAtom);
const scrollTarget = createRef<HTMLDivElement>();
const { sv_only, keyword } = params;
const { sv_only, address } = params;
const choices = Boolean(Object.keys(params).length);
useScrollToResults(scrollTarget, choices);

Expand All @@ -54,12 +54,12 @@ const ResultsList = ({ data, error, isLoading, isValidating, page, updatePage }:
}

const results = data.hits.hits;
const total = keyword && sv_only ? data.hits.hits.length : data.hits.total.value;
const total = address && sv_only ? data.hits.hits.length : data.hits.total.value;
const pages = Math.floor(total / size);
const addLastPage = total > size && total % size;
const showPagination = !useMap && (pages > 1 || addLastPage);
const sv_id = results?.[0]?._source?.id?.[0];
const mapIds = keyword && sv_only && sv_id ? data?.aggregations?.ids?.buckets?.filter((item: any) => item.key === sv_id) : data?.aggregations?.ids?.buckets;
const mapIds = address && sv_only && sv_id ? data?.aggregations?.ids?.buckets?.filter((item: any) => item.key === sv_id) : data?.aggregations?.ids?.buckets;

return (
<div className='react-search__results'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ import { paramsAtom, stagedParamsAtom } from '../store';
import SearchParams from '../types/SearchParams';

type SubmitFormType = HTMLFormElement & {
keyword: HTMLInputElement;
address: HTMLInputElement;
};

const ProximityFormContainer = () => {
const ProximityFormContainer = ({ initialParams }: { initialParams?: SearchParams }) => {
const stagedParams = useAtomValue(stagedParamsAtom);
const setParams = useSetAtom(paramsAtom);
const setStagedParams = useSetAtom(stagedParamsAtom);

const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const { keyword, sv_only } = event.target as SubmitFormType;
const { address, sv_only } = event.target as SubmitFormType;
const params: SearchParams = {};

if (keyword.value && keyword.value.length) {
params.keyword = keyword.value;
if (address.value && address.value.length) {
params.address = address.value;
};

params.sv_only = sv_only.checked;
Expand All @@ -33,9 +33,10 @@ const ProximityFormContainer = () => {
className='hdbt-search__filter hdbt-search--react__text-field'
helperText={Drupal.t('Enter the street name and house number', {}, { context: 'React search: street input helper'})}
placeholder={Drupal.t('For example, Kotikatu 1', {}, { context: 'React search: street input helper placeholder'})}
id='keyword'
id='address'
label={Drupal.t('Home address', {}, { context: 'React search: home address'})}
type='search'
defaultValue={initialParams?.address || ''}
/>
<div className='react-search__checkbox-filter-container'>
<fieldset className='hdbt-search--react__fieldset'>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,36 @@
import { Suspense } from 'react';
import { Suspense, useEffect } from 'react';

import { useSetAtom } from 'jotai';
import LoadingOverlay from '@/react/common/LoadingOverlay';
import FormContainer from './FormContainer';
import ResultsContainer from './ResultsContainer';
import useInitialParams from '@/react/common/hooks/useInitialParams';
import { paramsAtom } from '../store';

const SearchContainer = () => (
<Suspense fallback={
<div className='hdbt__loading-wrapper'>
<LoadingOverlay />
</div>
}>
<div className='hdbt-search--react'>
<FormContainer />
<ResultsContainer />
</div>
</Suspense>
);
const SearchContainer = () => {
const setParams = useSetAtom(paramsAtom);
const initialParams = useInitialParams({
address: '',
});

useEffect(() => {
if (initialParams) {
setParams(initialParams);
}
}, [initialParams, setParams]);

return (
<Suspense fallback={
<div className='hdbt__loading-wrapper'>
<LoadingOverlay />
</div>
}>
<div className='hdbt-search--react'>
<FormContainer initialParams={initialParams} />
<ResultsContainer />
</div>
</Suspense>
);
};

export default SearchContainer;
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,21 @@ const UseProximityQuery = (params: SearchParams) => {

const fetcher = async () => {
const { index } = AppSettings;
const { keyword, sv_only } = params;
const { address, sv_only } = params;

let coordinates = null;
let ids = null;

if (keyword) {
let addresses = await getAddresses(getAddressUrls(keyword));
addresses = addresses.filter((address: any) => address.results.length);
if (address) {
let addresses = await getAddresses(getAddressUrls(address));
addresses = addresses.filter((_address: any) => _address.results.length);

if (addresses.length) {
coordinates = parseCoordinates(addresses);
}
}

if (keyword && !coordinates) {
if (address && !coordinates) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
type SearchParams = {
keyword?: string;
address?: string;
page?: number;
query?: string;
sv_only?: boolean;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
interface SubmitEventTarget extends EventTarget {
keyword: HTMLInputElement;
address: HTMLInputElement;
}

export default SubmitEventTarget;
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const ResultsList = ({ data, error, isLoading, isValidating, page, updatePage }:
const { size } = AppSettings;
const params = useAtomValue(paramsAtom);
const scrollTarget = createRef<HTMLDivElement>();
const { sv_only, keyword } = params;
const { sv_only, address } = params;
const choices = Boolean(Object.keys(params).length);
useScrollToResults(scrollTarget, choices);

Expand All @@ -54,12 +54,12 @@ const ResultsList = ({ data, error, isLoading, isValidating, page, updatePage }:
}

const results = data.hits.hits;
const total = keyword && sv_only ? data.hits.hits.length : data.hits.total.value;
const total = address && sv_only ? data.hits.hits.length : data.hits.total.value;
const pages = Math.floor(total / size);
const addLastPage = total > size && total % size;
const showPagination = !useMap && (pages > 1 || addLastPage);
const sv_id = results?.[0]?._source?.id?.[0];
const mapIds = keyword && sv_only && sv_id ? data?.aggregations?.ids?.buckets?.filter((item: any) => item.key === sv_id) : data?.aggregations?.ids?.buckets;
const mapIds = address && sv_only && sv_id ? data?.aggregations?.ids?.buckets?.filter((item: any) => item.key === sv_id) : data?.aggregations?.ids?.buckets;

return (
<div className='react-search__results'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ import { paramsAtom, stagedParamsAtom } from '../store';
import SearchParams from '../types/SearchParams';

type SubmitFormType = HTMLFormElement & {
keyword: HTMLInputElement;
address: HTMLInputElement;
};

const ProximityFormContainer = () => {
const ProximityFormContainer = ({ initialParams }: {initialParams: SearchParams}) => {
const stagedParams = useAtomValue(stagedParamsAtom);
const setParams = useSetAtom(paramsAtom);
const setStagedParams = useSetAtom(stagedParamsAtom);

const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const { keyword, sv_only } = event.target as SubmitFormType;
const { address, sv_only } = event.target as SubmitFormType;
const params: SearchParams = {};

if (keyword.value && keyword.value.length) {
params.keyword = keyword.value;
if (address.value && address.value.length) {
params.address = address.value;
};

params.sv_only = sv_only.checked;
Expand All @@ -33,9 +33,10 @@ const ProximityFormContainer = () => {
className='hdbt-search__filter hdbt-search--react__text-field'
helperText={Drupal.t('Enter the street name and house number', {}, { context: 'React search: street input helper'})}
placeholder={Drupal.t('For example, Kotikatu 1', {}, { context: 'React search: street input helper placeholder'})}
id='keyword'
id='address'
label={Drupal.t('Home address', {}, { context: 'React search: home address'})}
type='search'
defaultValue={initialParams?.address || ''}
/>
<div className='react-search__checkbox-filter-container'>
<fieldset className='hdbt-search--react__fieldset'>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
import { Suspense } from 'react';
import { Suspense, useEffect } from 'react';

import { useSetAtom } from 'jotai';
import LoadingOverlay from '@/react/common/LoadingOverlay';
import FormContainer from './FormContainer';
import ResultsContainer from './ResultsContainer';
import SearchParams from '../types/SearchParams';
import useInitialParams from '@/react/common/hooks/useInitialParams';
import { paramsAtom } from '../store';

const SearchContainer = () => (
<Suspense fallback={
<div className='hdbt__loading-wrapper'>
<LoadingOverlay />
</div>
}>
<div className='hdbt-search--react'>
<FormContainer />
<ResultsContainer />
</div>
</Suspense>
);
const SearchContainer = () => {
const setParams = useSetAtom(paramsAtom);
const initialParams = useInitialParams<SearchParams>({
address: '',
});

useEffect(() => {
if (initialParams) {
setParams(initialParams);
}
});

return (
<Suspense fallback={
<div className='hdbt__loading-wrapper'>
<LoadingOverlay />
</div>
}>
<div className='hdbt-search--react'>
<FormContainer initialParams={initialParams} />
<ResultsContainer />
</div>
</Suspense>
);
};

export default SearchContainer;
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,21 @@ const UseProximityQuery = (params: SearchParams) => {

const fetcher = async () => {
const { index } = AppSettings;
const { keyword, sv_only } = params;
const { address, sv_only } = params;

let coordinates = null;
let ids = null;

if (keyword) {
let addresses = await getAddresses(getAddressUrls(keyword));
addresses = addresses.filter((address: any) => address.results.length);
if (address) {
let addresses = await getAddresses(getAddressUrls(address));
addresses = addresses.filter((_address: any) => _address.results.length);

if (addresses.length) {
coordinates = parseCoordinates(addresses);
}
}

if (keyword && !coordinates) {
if (address && !coordinates) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
type SearchParams = {
keyword?: string;
address?: string;
page?: number;
query?: string;
sv_only?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,20 @@ type SuggestionItemType = {
value: string;
};

const FormContainer = () => {
const FormContainer = ({ initialParams }: { initialParams?: SearchParams}) => {
const setParams = useSetAtom(paramsAtom);
const [keyword, setKeyword] = useState('');
const [address, setAddress] = useState(initialParams?.address);
const { baseUrl, index } = useAtomValue(configurationsAtom);

const onSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const params: SearchParams = {};
params.keyword = keyword;
params.address = address;
setParams(params);
};

console.log(address, initialParams);

const getSuggestions = (searchString: string) => new Promise<SuggestionItemType[]>((resolve, reject) => {
const suggestions = fetch(`${baseUrl}/${index}/_search`, {
method: 'POST',
Expand Down Expand Up @@ -65,10 +67,11 @@ const FormContainer = () => {
label={Drupal.t('Street name', {}, {context: 'Ploughing schedule: Input label'})}
suggestionLabelField='value'
getSuggestions={getSuggestions}
onSubmit={value => setKeyword(value)}
onChange={(value) => setKeyword(value)}
onSubmit={value => setAddress(value)}
onChange={(value) => setAddress(value)}
visibleSuggestions={5}
placeholder={Drupal.t('For example, Mannerheimintie', {}, {context: 'Ploughing schedule: Input placeholder'})}
value={address}
/>
<Button className='hdbt-search--react__submit-button hdbt-search--ploughing-schedule__submit-button' type='submit'>
{Drupal.t('See the ploughing schedule', {}, {context: 'Ploughing schedule: Form title / submit'})}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { Suspense } from 'react';
import { useAtomValue } from 'jotai';
import { Suspense, useEffect } from 'react';
import { useAtom, useAtomValue } from 'jotai';

import LoadingOverlay from '@/react/common/LoadingOverlay';
import FormContainer from './FormContainer';
import ResultsContainer from './ResultsContainer';
import { paramsAtom } from '../store';
import useInitialParams from '@/react/common/hooks/useInitialParams';

const SearchContainer = () => {
const params = useAtomValue(paramsAtom);
const [params, setParams] = useAtom(paramsAtom);
const initialParams = useInitialParams({
address: '',
});

useEffect(() => {
if (initialParams) {
setParams(initialParams);
}
}, []);

return (
<Suspense fallback={
Expand All @@ -16,8 +26,8 @@ const SearchContainer = () => {
</div>
}>
<div>
<FormContainer />
{ params.keyword ? <ResultsContainer /> : '' }
<FormContainer initialParams={initialParams} />
{ params.address ? <ResultsContainer /> : '' }
</div>
</Suspense>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import BooleanQuery from '@/types/BooleanQuery';

const getQueryString = (keyword: string) => {
const getQueryString = (address: string) => {
const query: BooleanQuery = {
bool: {
must: [
{
match: { street_name: keyword }
match: { street_name: address }
}
]
}
Expand Down
Loading

0 comments on commit 28b825b

Please sign in to comment.