diff --git a/src/components/SearchResults/Facets/FacetTags.js b/src/components/SearchResults/Facets/FacetTags.js index ceb09a837..d2ed178fa 100644 --- a/src/components/SearchResults/Facets/FacetTags.js +++ b/src/components/SearchResults/Facets/FacetTags.js @@ -7,8 +7,8 @@ import { Overline } from '@leafygreen-ui/typography'; import { theme } from '../../../theme/docsTheme'; import Tag, { searchTagStyle } from '../../Tag'; import SearchContext from '../SearchContext'; -import useFacets from './useFacets'; import { initChecked } from './FacetValue'; +import { getFacetTagVariant } from './utils'; // util to get all current facets, derived from search params const getActiveFacets = (facetOptions, searchParams) => { @@ -97,7 +97,7 @@ const FacetTag = ({ facet: { name, key, id, facets } }) => { }, [facets, handleFacetChange, id, key]); return ( - + {name} @@ -111,8 +111,7 @@ const ClearFacetsTag = ({ onClick }) => ( ); const FacetTags = ({ resultsCount }) => { - const { searchParams, clearFacets } = useContext(SearchContext); - const facets = useFacets(); + const { searchParams, clearFacets, facets } = useContext(SearchContext); // don't have to use state since facet filters are // derived from URL state (search params) const activeFacets = useMemo(() => getActiveFacets(facets, searchParams), [facets, searchParams]); diff --git a/src/components/SearchResults/Facets/Facets.js b/src/components/SearchResults/Facets/Facets.js index 341928611..309d85255 100644 --- a/src/components/SearchResults/Facets/Facets.js +++ b/src/components/SearchResults/Facets/Facets.js @@ -1,9 +1,9 @@ -import React from 'react'; -import useFacets from './useFacets'; +import React, { useContext } from 'react'; +import SearchContext from '../SearchContext'; import FacetGroup from './FacetGroup'; const Facets = () => { - const facets = useFacets(); + const { facets } = useContext(SearchContext); return (
diff --git a/src/components/SearchResults/Facets/utils.js b/src/components/SearchResults/Facets/utils.js new file mode 100644 index 000000000..54362308b --- /dev/null +++ b/src/components/SearchResults/Facets/utils.js @@ -0,0 +1,13 @@ +/** + * + * @param {obj} facet - contains key and id properties as returned by /v2/status ie. + * https://docs-search-transport.mongodb.com/v2/status + * + * @returns {str} blue | green + */ +export const getFacetTagVariant = (facet) => { + if (facet.key === 'target_product') { + return 'green'; + } + return 'blue'; +}; diff --git a/src/components/SearchResults/SearchContext.js b/src/components/SearchResults/SearchContext.js index 7c9b96680..399d3818e 100644 --- a/src/components/SearchResults/SearchContext.js +++ b/src/components/SearchResults/SearchContext.js @@ -1,11 +1,38 @@ -import { createContext, useCallback, useState } from 'react'; +import { createContext, useCallback, useMemo, useState } from 'react'; import { useLocation } from '@gatsbyjs/reach-router'; import { navigate } from 'gatsby'; import { useMarianManifests } from '../../hooks/use-marian-manifests'; +import useFacets from './Facets/useFacets'; export const FACETS_KEY_PREFIX = 'facets.'; export const FACETS_LEVEL_KEY = '>'; +const combineKeyAndId = (facet) => `${facet.key}${FACETS_LEVEL_KEY}${facet.id}`; + +const constructFacetNamesByKey = (facets) => { + const res = {}; + + function extractKeyIdName(facets) { + for (const facet of facets) { + res[combineKeyAndId(facet)] = facet.name; + if (facet?.facets?.length) { + traverseFacetGroup(facet.facets); + } + } + } + + function traverseFacetGroup(facetGroup) { + for (const facet of facetGroup) { + res[combineKeyAndId(facet)] = facet.name; + extractKeyIdName(facet.options); + } + } + + traverseFacetGroup(facets); + + return res; +}; + // Simple context to pass search results, ref, and filters to children const SearchContext = createContext({ filters: {}, @@ -24,11 +51,23 @@ const SearchContext = createContext({ shouldAutofocus: false, showFacets: false, searchParams: {}, + facets: [], + facetNamesByKeyId: {}, + getFacetName: () => {}, }); const SearchContextProvider = ({ children, showFacets = false }) => { const { search } = useLocation(); const { filters, searchPropertyMapping } = useMarianManifests(); + const facets = useFacets(); + const facetNamesByKeyId = useMemo(() => constructFacetNamesByKey(facets), [facets]); + + const getFacetName = useCallback( + (facet) => { + return facetNamesByKeyId?.[combineKeyAndId(facet)]; + }, + [facetNamesByKeyId] + ); // get vars from URL // state management for Search is within URL. const [searchParams, setSearchParams] = useState(new URLSearchParams(search)); @@ -122,6 +161,9 @@ const SearchContextProvider = ({ children, showFacets = false }) => { setShowMobileFilters, showFacets, searchParams, + facets, + facetNamesByKeyId, + getFacetName, }} > {children} diff --git a/src/components/SearchResults/SearchResult.js b/src/components/SearchResults/SearchResult.js index 8b29a92f5..411ddd564 100644 --- a/src/components/SearchResults/SearchResult.js +++ b/src/components/SearchResults/SearchResult.js @@ -5,8 +5,9 @@ import styled from '@emotion/styled'; import { palette } from '@leafygreen-ui/palette'; import { Body } from '@leafygreen-ui/typography'; import { theme } from '../../theme/docsTheme'; -import Tag, { searchTagStyle } from '../Tag'; +import Tag, { searchTagStyle, tagHeightStyle } from '../Tag'; import SearchContext from './SearchContext'; +import { getFacetTagVariant } from './Facets/utils'; const LINK_COLOR = '#494747'; // Use string for match styles due to replace/innerHTML @@ -95,6 +96,8 @@ const StyledTag = styled(Tag)` const StylingTagContainer = styled('div')` bottom: 0; margin-bottom: ${theme.size.medium}; + overflow: hidden; + ${tagHeightStyle}; `; const escapeRegExp = (string) => string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); @@ -132,13 +135,15 @@ const SearchResult = React.memo( title, searchProperty, url, + facets, ...props }) => { - const { searchPropertyMapping, searchTerm } = useContext(SearchContext); + const { searchPropertyMapping, searchTerm, getFacetName, showFacets } = useContext(SearchContext); const highlightedPreviewText = highlightSearchTerm(preview, searchTerm); const resultLinkRef = useRef(null); const category = searchPropertyMapping?.[searchProperty]?.['categoryTitle']; const version = searchPropertyMapping?.[searchProperty]?.['versionSelectorLabel']; + const validFacets = facets?.filter(getFacetName); return ( @@ -155,11 +160,22 @@ const SearchResult = React.memo( __html: sanitizePreviewHtml(highlightedPreviewText), }} /> - - {!!category && {category}} - {!!version && {version}} - {url.includes('/api/') && {'API'}} - + {!showFacets && ( + + {!!category && {category}} + {!!version && {version}} + {url.includes('/api/') && {'API'}} + + )} + {showFacets && validFacets?.length > 0 && ( + + {validFacets.map((facet, idx) => ( + + {getFacetName(facet)} + + ))} + + )} {learnMoreLink && ( diff --git a/src/components/SearchResults/SearchResults.js b/src/components/SearchResults/SearchResults.js index 52e4a97a2..8e5628776 100644 --- a/src/components/SearchResults/SearchResults.js +++ b/src/components/SearchResults/SearchResults.js @@ -359,7 +359,7 @@ const SearchResults = () => { const submitNewSearch = (event) => { const newValue = event.target[0]?.value; const { page } = queryString.parse(search); - if (newValue === searchTerm && parseInt(page) === 1) return; + if (!newValue || (newValue === searchTerm && parseInt(page) === 1)) return; setSearchTerm(newValue); }; @@ -460,7 +460,7 @@ const SearchResults = () => { {!!searchTerm && !!searchFinished && !!searchResults.length && ( <> - {searchResults.map(({ title, preview, url, searchProperty }, index) => ( + {searchResults.map(({ title, preview, url, searchProperty, facets }, index) => ( @@ -471,6 +471,7 @@ const SearchResults = () => { url={url} useLargeTitle searchProperty={searchProperty?.[0]} + facets={facets} /> ))} { diff --git a/src/components/Tag.js b/src/components/Tag.js index 89ec90e05..70be0805f 100644 --- a/src/components/Tag.js +++ b/src/components/Tag.js @@ -11,9 +11,13 @@ const baseStyle = css` padding: ${theme.size.tiny} ${theme.size.small}; `; +export const tagHeightStyle = css` + height: 26px; +`; + export const searchTagStyle = css` cursor: pointer; - height: 26px; + ${tagHeightStyle}; padding: 4px 11px 4px 11px; border-radius: 12px; font-size: ${theme.fontSize.tiny}; diff --git a/tests/unit/__snapshots__/SearchResults.test.js.snap b/tests/unit/__snapshots__/SearchResults.test.js.snap index e84c0459c..670de98e2 100644 --- a/tests/unit/__snapshots__/SearchResults.test.js.snap +++ b/tests/unit/__snapshots__/SearchResults.test.js.snap @@ -1536,6 +1536,8 @@ exports[`Search Results Page considers a given search filter query param and dis .emotion-36 { bottom: 0; margin-bottom: 24px; + overflow: hidden; + height: 26px; } .emotion-42 { @@ -8347,6 +8349,8 @@ exports[`Search Results Page renders results from a given search term query para .emotion-32 { bottom: 0; margin-bottom: 24px; + overflow: hidden; + height: 26px; } .emotion-35 {