-
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
base: customDisplayReference
Are you sure you want to change the base?
Changes from all commits
2ffe0fa
8de1b43
c241f88
cbebed2
b3ac09c
13242fe
3b31130
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.