fix(knowledge-base): align Filter by metadata pickers with app dropdowns#13117
Conversation
The "+ Filter by metadata" popover used plain <Input> fields backed by a
native HTML <datalist> for key/value suggestions. The browser-native
dropdown looked nothing like the shadcn `Select` used right next to it
(e.g. "All sources") — QA flagged the inconsistency.
Replace each free-text input with a shadcn-style combobox built on
Popover + Command (cmdk):
- Outline button trigger with chevron, matching SelectTrigger.
- Suggestion list rendered as CommandItem rows with a check on the
current selection.
- When the typed query is not in the suggestions, a "Use \"foo\"" item
appears so users can still commit a custom key/value.
- Closing the picker clears the search query; selecting an item
commits and closes.
Validation, refetch-on-open, error messaging, and submit flow are
unchanged. Tests rewritten against the new combobox testids and a
jsdom shim for Element.prototype.scrollIntoView (cmdk calls it).
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## release-1.10.0 #13117 +/- ##
==================================================
+ Coverage 54.59% 54.74% +0.14%
==================================================
Files 2140 2144 +4
Lines 199789 200145 +356
Branches 30123 30188 +65
==================================================
+ Hits 109084 109562 +478
+ Misses 89523 89402 -121
+ Partials 1182 1181 -1
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
…ules
ChunksMetadataFilter was holding data fetching, derived option lists,
validation rules, popover orchestration, and the combobox UI all in one
file. Split along single-responsibility lines so each piece changes for
its own reason:
- MetadataCombobox.tsx — presentational Popover+Command combobox with
custom-entry fallback. Generic over options/testId; reusable.
- hooks/useChunksMetadataFilter.ts — wraps useGetKbMetadataKeys and
derives availableKeys / valueSuggestions / flags / refetch.
- metadataFilterValidation.ts — pure KEY_PATTERN + validateMetadataFilter
returning { ok, key, value } | { ok: false, error }. Testable in
isolation; no DOM.
- ChunksMetadataFilter.tsx — orchestration only: outer popover, form
state, submit. Composes the three above.
Adds focused unit tests for the validator (regex + happy path + empty
+ uppercase). Existing integration test for the filter itself is left
untouched.
Custom Fields validation only fired on blur and lived in MetadataEditor's
local state, so an invalid key like "Year" still let the user advance to
Review & Build. StepReview rendered the raw pairs (showing "Year: 2020"
in the summary) but ``metadataPairsToFormValue`` silently filtered the
invalid row out at submit — the backend never received that metadata.
The UI was effectively lying.
Single source of truth in metadataValidation.ts:
- validateMetadataPair (per-row: empty, regex, value length)
- validateMetadataPairs (cross-row: duplicates, max count)
- filterValidMetadataPairs (clean trimmed set for display/submit)
Wired through:
- MetadataEditor derives errors from the prop list via the shared
validator, dropping the blur-only local state. Errors always
reflect the current input.
- useKnowledgeBaseForm.getValidationErrors now checks run-level and
per-file metadata. handleNext blocks while any row is invalid and
surfaces a single error key under validationErrors.metadata.
- StepConfiguration renders that error next to the Custom Fields
block.
- StepReview filters the summary through filterValidMetadataPairs so
it only shows pairs the backend will actually persist.
Adds focused unit tests for the new validator (per-row rules, dupes,
max-count, filter behavior).
Summary
Knowledge-base UX polish bundle for 1.10.0: brings the chunks browser's Filter by metadata popover in line with the rest of the app, slims the component along single-responsibility lines, and closes a bug where the Ingest Files modal silently dropped invalid Custom Fields after letting the user click Next Step.
Three logical changes
ChunksMetadataFilterinto focused modules (SOLID-aligned).1. Combobox parity for Filter by metadata
The popover used plain
<Input>fields backed by a native HTML<datalist>for key/value suggestions. The browser-native dropdown looked nothing like the shadcnSelectused right next to it (e.g. All sources) — QA flagged the inconsistency.Both pickers now use a shadcn-style combobox so the popover matches every other dropdown in the app:
Popover+Command(cmdk):SelectTrigger.CommandItemrows with a check on the current selection.KEY_PATTERNvalidation, refetch-on-open, error message, "Showing first 50 values per key" hint, and submit flow are unchanged.2.
ChunksMetadataFilterrefactorThe original file held data fetching, derived option lists, validation rules, popover orchestration, and the combobox UI all in one place. Split along single-responsibility lines so each piece changes for its own reason:
MetadataCombobox.tsx— presentationalPopover+Commandcombobox with custom-entry fallback. Generic overoptions/testId; reusable.hooks/useChunksMetadataFilter.ts— wrapsuseGetKbMetadataKeys, derivesavailableKeys/valueSuggestions/ flags /refetch. Encapsulates data plumbing.metadataFilterValidation.ts— pureKEY_PATTERN+validateMetadataFilterreturning{ ok, key, value } | { ok: false, error }. Testable in isolation, no DOM.ChunksMetadataFilter.tsx— orchestration only: outer popover, form state (key/value/error), submit. Composes the three above.3. Bug fix: gate Next Step on metadata-pair validity
Symptom — In the Ingest Files modal → Custom Fields, typing an invalid key like
Yearshowed the red "Keys must be 1-32 lowercase letters, digits, or underscores" message, but clicking Next Step still advanced to Review & Build. The summary even renderedMetadata: Year: 2020, suggesting the row would be persisted.Root cause — three permissive layers:
MetadataEditorvalidated key-on-blur and stored the error in component-local state; the parent never heard about it.useKnowledgeBaseForm.getValidationErrorsvalidated name / embedding / backend / file size but did not checkmetadataPairs. SohandleNextproceeded.StepReviewrendered raw pairs, whilemetadataPairsToFormValuesilently filtered the invalid row out at submit — backend never received it. The UI lied to the user.Fix — single source of truth in
metadataValidation.ts:validateMetadataPair— per-row (empty, regex, value length).validateMetadataPairs— cross-row (duplicates, max count).filterValidMetadataPairs— clean trimmed set for display/submit.Wired through every surface that used to disagree:
MetadataEditorderives errors from the prop list via the shared validator, dropping the blur-only local state. Errors always reflect the current input.useKnowledgeBaseForm.getValidationErrorsnow checks run-level and per-file metadata.handleNextblocks while any row is invalid and surfaces a singlevalidationErrors.metadatakey.StepConfigurationrenders that error next to the Custom Fields block.StepReviewfilters the summary throughfilterValidMetadataPairsso it only shows pairs the backend will actually persist.Tests
metadataFilterValidation.test.ts— covers chunks-browser key/value validator (regex, empty, uppercase, happy path).metadataValidation.test.ts— covers Ingest Files validator (per-row rules, duplicates, max-count cap,filterValidMetadataPairs).ChunksMetadataFilter.test.tsx— new combobox testids (chunks-metadata-filter-{key,value,input,option-*,custom}), plus a jsdom shim forElement.prototype.scrollIntoViewbecause cmdk calls it on selection.knowledgePagejest suite: 130/130 ✅knowledgeBaseUploadModaljest suite: 91/91 ✅make format_frontendclean.Test plan
Filter by metadata combobox
truncated: truefrom the server still shows the "Showing first 50 values per key" hint.Ingest Files → Custom Fields validation gating
Screenshots
Before

After
