-
Notifications
You must be signed in to change notification settings - Fork 7
feat(website, config): add an option for search presets #6136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8be713f
7661f39
3672777
a678c32
bb0533f
0a84e57
05a48a4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,13 @@ import { useEffect, useMemo, useRef, useState } from 'react'; | |
| import { createOptionsProviderHook, type OptionsProvider } from './AutoCompleteOptions.ts'; | ||
| import { FloatingLabelContainer } from './FloatingLabelContainer.tsx'; | ||
| import { getClientLogger } from '../../../clientLogger.ts'; | ||
| import { type GroupedMetadataFilter, type MetadataFilter, type SetSomeFieldValues } from '../../../types/config.ts'; | ||
| import { | ||
| type FieldPresetMap, | ||
| type FieldValueUpdate, | ||
| type GroupedMetadataFilter, | ||
| type MetadataFilter, | ||
| type SetSomeFieldValues, | ||
| } from '../../../types/config.ts'; | ||
| import { formatNumberWithDefaultLocale } from '../../../utils/formatNumber.tsx'; | ||
| import { NULL_QUERY_VALUE } from '../../../utils/search.ts'; | ||
| import { Button } from '../../common/Button'; | ||
|
|
@@ -26,6 +32,7 @@ type MultiChoiceAutoCompleteFieldProps = { | |
| setSomeFieldValues: SetSomeFieldValues; | ||
| fieldValues: (string | null)[]; | ||
| maxDisplayedOptions?: number; | ||
| fieldPresets?: FieldPresetMap; | ||
| }; | ||
|
|
||
| export const MultiChoiceAutoCompleteField = ({ | ||
|
|
@@ -34,10 +41,12 @@ export const MultiChoiceAutoCompleteField = ({ | |
| setSomeFieldValues, | ||
| fieldValues, | ||
| maxDisplayedOptions = 1000, | ||
| fieldPresets, | ||
| }: MultiChoiceAutoCompleteFieldProps) => { | ||
| const inputRef = useRef<HTMLInputElement>(null); | ||
| const [query, setQuery] = useState(''); | ||
| const [isFocused, setIsFocused] = useState(false); | ||
| const lastPresetKeysRef = useRef<string[]>([]); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The This is a known limitation of using a ref for this kind of ephemeral state, but worth noting as a known edge case since the behaviour can seem surprising (stale filter values persist until manually cleared after a page reload).
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure if there is a better way to handle this, @theosanderson do you have any better ideas? |
||
|
|
||
| // Maximum number of badges to show before switching to summary | ||
| const MAX_VISIBLE_BADGES = 2; | ||
|
|
@@ -63,17 +72,58 @@ export const MultiChoiceAutoCompleteField = ({ | |
| }, [options, query, maxDisplayedOptions]); | ||
|
|
||
| const handleChange = (value: string[] | null) => { | ||
| const updates: FieldValueUpdate[] = []; | ||
|
|
||
| // Clear values from the last applied preset | ||
| for (const key of lastPresetKeysRef.current) { | ||
| updates.push([key, '']); | ||
| } | ||
| if (!value || value.length === 0) { | ||
| setSomeFieldValues([field.name, '']); | ||
| updates.unshift([field.name, '']); | ||
| lastPresetKeysRef.current = []; | ||
| } else { | ||
| const convertedValues = value.map((v) => (v === NULL_QUERY_VALUE ? null : v)); | ||
| setSomeFieldValues([field.name, convertedValues]); | ||
| updates.unshift([field.name, convertedValues]); | ||
|
|
||
| if (fieldPresets) { | ||
| const presetAccumulator: Record<string, string[]> = {}; | ||
| const presetContributorCount: Record<string, number> = {}; | ||
| for (const v of value) { | ||
| const preset = fieldPresets[v]; | ||
| if (!preset) continue; | ||
| for (const [k, pv] of Object.entries(preset)) { | ||
| (presetAccumulator[k] ??= []).push(pv); | ||
| presetContributorCount[k] = (presetContributorCount[k] ?? 0) + 1; | ||
| } | ||
| } | ||
|
|
||
| const appliedKeys: string[] = []; | ||
| for (const [k, vals] of Object.entries(presetAccumulator)) { | ||
| const uniqueVals = [...new Set(vals)]; | ||
|
|
||
| // Only apply the preset value if all selected options contribute the same value for this key | ||
| if (uniqueVals.length === 1 && presetContributorCount[k] === value.length) { | ||
| updates.push([k, uniqueVals[0]]); | ||
| appliedKeys.push(k); | ||
| } | ||
| } | ||
| lastPresetKeysRef.current = appliedKeys; | ||
| } else { | ||
| lastPresetKeysRef.current = []; | ||
| } | ||
| } | ||
|
|
||
| setSomeFieldValues(...updates); | ||
| }; | ||
|
|
||
| const handleClear = () => { | ||
| const updates: FieldValueUpdate[] = [[field.name, '']]; | ||
| for (const key of lastPresetKeysRef.current) { | ||
| updates.push([key, '']); | ||
| } | ||
| lastPresetKeysRef.current = []; | ||
| setQuery(''); | ||
| handleChange([]); | ||
| setSomeFieldValues(...updates); | ||
| }; | ||
|
|
||
| // Convert selectedValues Set to array for Combobox value | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.