Skip to content

Commit

Permalink
support boolean facets (#94)
Browse files Browse the repository at this point in the history
  • Loading branch information
abeglova authored Apr 25, 2024
1 parent 501fa94 commit 4a6974a
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,5 @@ export const LEVELS = {
intermediate: "Intermediate",
introductory: "Introductory"
}

export const BOOLEAN_FACET_NAMES = ["certification", "professional"]
10 changes: 8 additions & 2 deletions src/facet_display/FacetDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import React, { useCallback } from "react"
import FilterableFacet from "./FilterableFacet"
import Facet from "./Facet"
import SearchFilter from "./SearchFilter"
import type { FacetManifest, Facets, Aggregation, Bucket } from "./types"
import type {
FacetManifest,
Facets,
Aggregation,
Bucket,
BooleanFacets
} from "./types"
import { LEVELS, DEPARTMENTS } from "../constants"

export type BucketWithLabel = Bucket & { label: string }
Expand All @@ -16,7 +22,7 @@ interface FacetDisplayProps {
* automatically be included in the facet options.
*/
facetOptions: (group: string) => Aggregation | null
activeFacets: Facets
activeFacets: Facets & BooleanFacets
clearAllFilters: () => void
onFacetChange: (name: string, value: string, isEnabled: boolean) => void
}
Expand Down
6 changes: 6 additions & 0 deletions src/facet_display/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type Aggregations = Map<string, Bucket[]>
export type GetSearchPageSize = (ui: string | null) => number

export type FacetKey = keyof Facets
export type BooleanFacetKey = keyof BooleanFacets

export type SingleFacetOptions = {
name: FacetKey
Expand All @@ -31,3 +32,8 @@ export interface Facets {
resource_type?: string[]
content_feature_type?: string[]
}

export interface BooleanFacets {
certification?: boolean | null
professional?: boolean | null
}
63 changes: 63 additions & 0 deletions src/hooks/useValidatedSearchParams.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,69 @@ describe("useResourceSearchParams", () => {
expect(searchParams.current).toEqual(expected)
})

test.each([
{
initial: "?department=6&certification=false",
expected: new URLSearchParams("?department=6&certification=true"),
newValue: "true"
},
{
initial: "?department=6&certification=true",
expected: new URLSearchParams("?department=6"),
newValue: ""
},
{
initial: "?department=6",
expected: new URLSearchParams("?department=6&certification=true"),
newValue: "true"
}
])(
"setSearchParams sets boolean params",
({ initial, expected, newValue }) => {
const { result, searchParams } = setup({ initial })
act(() => {
result.current.setParamValue("certification", newValue)
})
expect(searchParams.current).toEqual(expected)
}
)

test.each([
{
initial: "?resource_type=course&resource_type=program&department=6",
expected: new URLSearchParams("?department=6&resource_type=program"),
newValue: "program"
},
{
initial: "?department=6",
expected: new URLSearchParams("?department=6&resource_type=program"),
newValue: "program"
},
{
initial: "?resource_type=course&resource_type=program&department=6",
expected: new URLSearchParams(
"?department=6&resource_type=podcast&resource_type=program"
),
newValue: ["podcast", "program"]
},
{
initial: "?department=6",
expected: new URLSearchParams(
"?department=6&resource_type=podcast&resource_type=program"
),
newValue: ["podcast", "program"]
}
])(
"setSearchParams sets string params",
({ initial, expected, newValue }) => {
const { result, searchParams } = setup({ initial })
act(() => {
result.current.setParamValue("resource_type", newValue)
})
expect(searchParams.current).toEqual(expected)
}
)

test.each([
{
initial: "?resource_type=course",
Expand Down
46 changes: 45 additions & 1 deletion src/hooks/useValidatedSearchParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ interface UseValidatedSearchParamsResult<ReqParams> {
* - if `checked=false`, value is REMOVED from parameter list.
*/
toggleParamValue: (name: string, rawValue: string, checked: boolean) => void

setParamValue: (name: string, rawValue: string | string[]) => void

/**
* Current search text. May be different from the `q` parameter.
*/
Expand Down Expand Up @@ -86,7 +89,10 @@ const useValidatedSearchParams = <ReqParams>({
const validator = validators[key as keyof ReqParams]
const values = searchParams.getAll(key)
const validated = validator(values)
if (!validated || (Array.isArray(validated) && validated.length === 0)) {
if (
validated === undefined ||
(Array.isArray(validated) && validated.length === 0)
) {
return acc
}
return { ...acc, [key]: validated }
Expand Down Expand Up @@ -174,6 +180,43 @@ const useValidatedSearchParams = <ReqParams>({
[setSearchParams, facets, onFacetsChange, validators]
)

const setParamValue = useCallback(
(name: string, rawValue: string | string[]) => {
const validator = validators[name as keyof ReqParams]
if (!validator) {
console.warn(`Unrecognized search param: ${name}`)
}

const validated = validator(
Array.isArray(rawValue) ? rawValue : [rawValue]
)
const value = validated
if (value === undefined || value === null) {
setSearchParams(current => {
const copy = new URLSearchParams(current)
copy.delete(name)
copy.sort()
return copy
})
} else {
setSearchParams(current => {
const copy = new URLSearchParams(current)
if (Array.isArray(value)) {
copy.delete(name)
value.forEach(v => copy.append(name, v.toString()))
} else {
copy.set(name, value.toString())
}
return copy
})
}
if ((facets as string[]).includes(name)) {
onFacetsChange?.()
}
},
[setSearchParams, facets, onFacetsChange, validators]
)

const [currentText, setCurrentText] = useState(searchParams.get("q") ?? "")
const setCurrentTextAndQuery = useCallback(
(value: string) => {
Expand All @@ -198,6 +241,7 @@ const useValidatedSearchParams = <ReqParams>({
clearParam,
patchParams,
toggleParamValue,
setParamValue,
currentText,
setCurrentText,
setCurrentTextAndQuery
Expand Down

0 comments on commit 4a6974a

Please sign in to comment.