diff --git a/datahub-web-react/src/app/search/SearchPage.tsx b/datahub-web-react/src/app/search/SearchPage.tsx index e57b14150..589b36b74 100644 --- a/datahub-web-react/src/app/search/SearchPage.tsx +++ b/datahub-web-react/src/app/search/SearchPage.tsx @@ -1,124 +1,124 @@ import React, { useEffect } from 'react'; import * as QueryString from 'query-string'; import { useHistory, useLocation, useParams } from 'react-router'; import { Alert } from 'antd'; import { SearchablePage } from './SearchablePage'; import { useEntityRegistry } from '../useEntityRegistry'; import { FacetFilterInput, EntityType } from '../../types.generated'; import useFilters from './utils/useFilters'; import { navigateToSearchUrl } from './utils/navigateToSearchUrl'; import { SearchResults } from './SearchResults'; import analytics, { EventType } from '../analytics'; import { useGetSearchResultsForMultipleQuery } from '../../graphql/search.generated'; import { SearchCfg } from '../../conf'; import { ENTITY_FILTER_NAME } from './utils/constants'; import { GetSearchResultsParams } from '../entity/shared/components/styled/search/types'; type SearchPageParams = { type?: string; }; /** * A search results page. */ export const SearchPage = () => { const history = useHistory(); const location = useLocation(); const entityRegistry = useEntityRegistry(); const params = QueryString.parse(location.search, { arrayFormat: 'comma' }); - const query: string = params.query ? (params.query as string) : ''; + const query: string = decodeURIComponent(params.query ? (params.query as string) : ''); const activeType = entityRegistry.getTypeOrDefaultFromPathName(useParams().type || '', undefined); const page: number = params.page && Number(params.page as string) > 0 ? Number(params.page as string) : 1; const filters: Array = useFilters(params); const filtersWithoutEntities: Array = filters.filter( (filter) => filter.field !== ENTITY_FILTER_NAME, ); const entityFilters: Array = filters .filter((filter) => filter.field === ENTITY_FILTER_NAME) .map((filter) => filter.value.toUpperCase() as EntityType); const { data, loading, error } = useGetSearchResultsForMultipleQuery({ variables: { input: { types: entityFilters, query, start: (page - 1) * SearchCfg.RESULTS_PER_PAGE, count: SearchCfg.RESULTS_PER_PAGE, filters: filtersWithoutEntities, }, }, }); // we need to extract refetch on its own so paging thru results for csv download // doesnt also update search results const { refetch } = useGetSearchResultsForMultipleQuery({ variables: { input: { types: entityFilters, query, start: (page - 1) * SearchCfg.RESULTS_PER_PAGE, count: SearchCfg.RESULTS_PER_PAGE, filters: filtersWithoutEntities, }, }, }); const callSearchOnVariables = (variables: GetSearchResultsParams['variables']) => { return refetch(variables).then((res) => res.data.searchAcrossEntities); }; useEffect(() => { if (!loading) { analytics.event({ type: EventType.SearchResultsViewEvent, query, total: data?.searchAcrossEntities?.count || 0, }); } }, [query, data, loading]); const onSearch = (q: string, type?: EntityType) => { if (q.trim().length === 0) { return; } analytics.event({ type: EventType.SearchEvent, query: q, entityTypeFilter: activeType, pageNumber: 1, originPath: window.location.pathname, }); navigateToSearchUrl({ type: type || activeType, query: q, page: 1, history }); }; const onChangeFilters = (newFilters: Array) => { navigateToSearchUrl({ type: activeType, query, page: 1, filters: newFilters, history }); }; const onChangePage = (newPage: number) => { navigateToSearchUrl({ type: activeType, query, page: newPage, filters, history }); }; return ( {!loading && error && ( )} ); }; diff --git a/datahub-web-react/src/app/search/utils/navigateToSearchUrl.ts b/datahub-web-react/src/app/search/utils/navigateToSearchUrl.ts index 4e5c8be11..3827283bb 100644 --- a/datahub-web-react/src/app/search/utils/navigateToSearchUrl.ts +++ b/datahub-web-react/src/app/search/utils/navigateToSearchUrl.ts @@ -1,69 +1,69 @@ import * as QueryString from 'query-string'; import { RouteComponentProps } from 'react-router-dom'; import filtersToQueryStringParams from './filtersToQueryStringParams'; import { EntityType, FacetFilterInput } from '../../../types.generated'; import { PageRoutes } from '../../../conf/Global'; export const navigateToSearchUrl = ({ type: newType, query: newQuery, page: newPage = 1, filters: newFilters, history, }: { type?: EntityType; query?: string; page?: number; filters?: Array; history: RouteComponentProps['history']; }) => { const constructedFilters = newFilters || []; if (newType) { constructedFilters.push({ field: 'entity', value: newType }); } const search = QueryString.stringify( { ...filtersToQueryStringParams(constructedFilters), - query: newQuery, + query: encodeURIComponent(newQuery || ''), page: newPage, }, { arrayFormat: 'comma' }, ); history.push({ pathname: `${PageRoutes.SEARCH}`, search, }); }; export const navigateToSearchLineageUrl = ({ entityUrl, query: newQuery, page: newPage = 1, filters: newFilters, history, }: { entityUrl: string; query?: string; page?: number; filters?: Array; history: RouteComponentProps['history']; }) => { const constructedFilters = newFilters || []; const search = QueryString.stringify( { ...filtersToQueryStringParams(constructedFilters), - query: newQuery, + query: encodeURIComponent(newQuery || ''), page: newPage, }, { arrayFormat: 'comma' }, ); history.push({ pathname: entityUrl, search, }); };