Skip to content

Commit

Permalink
facet query, keyword widget
Browse files Browse the repository at this point in the history
  • Loading branch information
nl0 committed Sep 20, 2023
1 parent 8b35ced commit 5aff526
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 11 deletions.
62 changes: 57 additions & 5 deletions catalog/app/containers/Search/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface FacetActions<T extends SearchUIModel.KnownFacetType> {
}

type FilterWidgetProps<T extends SearchUIModel.KnownFacetType> =
SearchUIModel.StateForFacetType<T> & FacetActions<T>
SearchUIModel.StateForFacetType<T> & FacetActions<T> & { path: SearchUIModel.FacetPath }

function ResultTypeSelector() {
const model = SearchUIModel.use()
Expand Down Expand Up @@ -56,8 +56,7 @@ function NumberFilterWidget({
}: FilterWidgetProps<typeof SearchUIModel.FacetTypes.Number>) {
return (
<div>
num
<button onClick={onDeactivate}>x</button>
<button onClick={onDeactivate}>deactivate x</button>
<div>
value:
{value.min} ... {value.max}
Expand All @@ -70,6 +69,59 @@ function NumberFilterWidget({
)
}

function KeywordFilterWidget({
path,
value,
onChange,
onDeactivate,
}: FilterWidgetProps<typeof SearchUIModel.FacetTypes.Keyword>) {
const facetQ = SearchUIModel.useFacetQuery(path)
const select = React.useCallback(
(v: string) => onChange([...value, v]),
[onChange, value],
)
const deselect = React.useCallback(
(v: string) => onChange(value.filter((x) => x !== v)),
[onChange, value],
)
return (
<div>
<button onClick={onDeactivate}>deactivate x</button>
<div>
<div>values:</div>
{value.map((v) => (
<label key={v}>
<input type="checkbox" checked={true} onChange={() => deselect(v)} />
{v}
</label>
))}
{GQL.fold(facetQ, {
fetching: () => <div>fetching values</div>,
data: (d) => {
if (d.search.__typename !== 'BoundedSearch') {
return <div>bad response</div>
}
const { facet } = d.search
if (!facet) {
return <div>facet not found</div>
}
if (facet.__typename !== 'KeywordSearchFacet') {
return <div>bad facet type</div>
}
const availableValues = facet.keywordValues.filter((v) => !value.includes(v))
return availableValues.map((v) => (
<label key={v}>
<input type="checkbox" checked={false} onChange={() => select(v)} />
{v}
</label>
))
},
})}
</div>
</div>
)
}

function GenericFilterWidget({
value,
// extents, // onChange, ,
Expand All @@ -89,7 +141,7 @@ function GenericFilterWidget({
const FILTER_WIDGETS = {
Number: NumberFilterWidget,
Date: GenericFilterWidget,
Keyword: GenericFilterWidget,
Keyword: KeywordFilterWidget,
Text: GenericFilterWidget,
Boolean: GenericFilterWidget,
}
Expand All @@ -101,7 +153,7 @@ function renderFilterWidget<F extends SearchUIModel.KnownFacetDescriptor>(
// eslint-disable-next-line no-underscore-dangle
const FilterWidget = FILTER_WIDGETS[facet.type._tag]
// @ts-expect-error
return <FilterWidget {...facet.state} {...actions} />
return <FilterWidget {...facet.state} {...actions} path={facet.path} />
}

interface FacetWidgetProps<F extends SearchUIModel.KnownFacetDescriptor> {
Expand Down
28 changes: 23 additions & 5 deletions catalog/app/containers/Search/model.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as Types from 'utils/types'
import useMemoEq from 'utils/useMemoEq'

import BASE_SEARCH_QUERY from './gql/BaseSearch.generated'
// import FACET_QUERY from './gql/Facet.generated'
import FACET_QUERY from './gql/Facet.generated'
import FIRST_PAGE_QUERY from './gql/FirstPage.generated'
import NEXT_PAGE_QUERY from './gql/NextPage.generated'

Expand Down Expand Up @@ -489,6 +489,17 @@ function useFilters(activeFacets: KnownFacetDescriptor[]): Model.GQLTypes.Search
return useMemoEq(activeFacets, computeFilters)
}

export function useUpstreamFilters(path: FacetPath): Model.GQLTypes.SearchFilter[] {
const model = useSearchUIModelContext()
const { activeFacets } = model.state
const idx = activeFacets.findIndex((f) => R.equals(f.path, path))
const upstreamFacets = React.useMemo(
() => (idx === -1 ? [] : activeFacets.slice(0, idx)),
[activeFacets, idx],
)
return useMemoEq(upstreamFacets, computeFilters)
}

function useBaseSearchQuery(
{ searchString, resultType, buckets }: SearchUrlState,
filters: Model.GQLTypes.SearchFilter[],
Expand Down Expand Up @@ -526,6 +537,13 @@ export function useNextPageQuery(after: string) {
return GQL.useQuery(NEXT_PAGE_QUERY, { after })
}

export function useFacetQuery(path: FacetPath) {
const model = useSearchUIModelContext()
const { searchString, resultType, buckets } = model.state
const filters = useUpstreamFilters(path)
return GQL.useQuery(FACET_QUERY, { searchString, resultType, buckets, filters, path })
}

export type AvailableFacet = KnownFacetDescriptor
// export interface AvailableFacet {
// descriptor: KnownFacetDescriptor
Expand Down Expand Up @@ -587,9 +605,9 @@ function useAvailableFacets(
function useSearchUIModel() {
const urlState = useUrlState()
const activeFacets = useActiveFacets(urlState)
const baseFilter = useFilters(activeFacets)
const baseSearchQuery = useBaseSearchQuery(urlState, baseFilter)
const firstPageQuery = useFirstPageQuery(urlState, baseFilter)
const baseFilters = useFilters(activeFacets)
const baseSearchQuery = useBaseSearchQuery(urlState, baseFilters)
const firstPageQuery = useFirstPageQuery(urlState, baseFilters)
const availableFacets = useAvailableFacets(baseSearchQuery, activeFacets)

const makeUrl = useMakeUrl()
Expand Down Expand Up @@ -672,7 +690,7 @@ function useSearchUIModel() {
searchString: urlState.searchString,
resultType: urlState.resultType,
buckets: urlState.buckets,
filter: baseFilter,
filters: baseFilters,
order: urlState.order,
activeFacets,
availableFacets,
Expand Down
7 changes: 6 additions & 1 deletion catalog/app/utils/GraphQL/Provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export default function GraphQLProvider({ children }: React.PropsWithChildren<{}
[],
)

// TODO: instantly resolve BoundedSearch(id).facet from BoundedSearch(id).facets
const cacheExchange = React.useMemo(
() =>
GraphCache.cacheExchange({
Expand All @@ -109,7 +110,11 @@ export default function GraphQLProvider({ children }: React.PropsWithChildren<{}
p.bucket?.name && p.policy?.id ? `${p.bucket.name}/${p.policy.id}` : null,
RoleBucketPermission: (p: any) =>
p.bucket?.name && p.role?.id ? `${p.bucket.name}/${p.role.id}` : null,
SearchFacet: (sf: any) => JSON.stringify(sf.path) ?? null,
NumberSearchFacet: () => null,
DateSearchFacet: () => null,
KeywordSearchFacet: () => null,
TextSearchFacet: () => null,
BooleanSearchFacet: () => null,
SearchResultSet: () => null,
SearchResultSetPage: () => null,
Status: () => null,
Expand Down

0 comments on commit 5aff526

Please sign in to comment.