feat(ui): filter flags by metadata key-value pairs (closes #3739)#5667
feat(ui): filter flags by metadata key-value pairs (closes #3739)#5667hiepau1231 wants to merge 12 commits intoflipt-io:v2from
Conversation
Add client-side metadata filter feature design: filter popover + chips in FlagTable, pre-filter logic with AND semantics, MetadataFilterPopover component using existing Combobox/Badge/Popover primitives. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Task-by-task TDD plan: MetadataFilter type, applyMetadataFilters utility, MetadataFilterPopover component, FlagTable wiring, smoke test steps. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ISSUE-1: Replace Formik Input with BaseInput in MetadataFilterPopover - ISSUE-2: Add conditional infra files to File Map - ISSUE-3: Correct Jest config key to setupFilesAfterEnv - ISSUE-4: Add FlagTable integration tests (8 cases incl. combined filter) - ISSUE-5: Document filter semantics decision explicitly - ISSUE-6: Fix FlagTable test mocks to use actual import paths Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ISSUE-7: Add jest.useFakeTimers()/act(advanceTimersByTime(600)) around Searchbox debounce in combined text+metadata test - ISSUE-8: Wrap FlagTable in MemoryRouter to satisfy useNavigate() context requirement from FlagListItem and EmptyFlagList child components Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- ISSUE-9: Replace ambiguous mockFlags data + search term. Renamed to Alpha/Beta/Gamma with distinct keys to avoid 'Flag'/'a' substring false-matches. Combined test now uses 'alpha' as search term (uniquely matches key='alpha', name='Alpha' only), making the combined text+metadata AND assertion unambiguous. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
👋 Hi @hiepau1231! Thanks for your contribution to this project. It looks like one or more of your commits are missing a DCO (Developer Certificate of Origin) sign-off. The DCO is a simple way for you to certify that you have the right to submit this code under the project's license. How to fix this: # For future commits, use the -s flag
git commit -s -m "Your commit message"
# To sign off on existing commits in this PR
git rebase HEAD~$(git rev-list --count origin/v2..HEAD) --signoff
git push --force-with-leaseThe 📋 View the failing DCO check for more details For more information about the DCO, visit: https://developercertificate.org/ |
Signed-off-by: hiepau1231 <hiepau1231@gmail.com>
- Add @testing-library/react, jest-dom, @babel/preset-react for JSX test support - Configure setupFilesAfterEnv with jest-dom matchers Signed-off-by: hiepau1231 <hiepau1231@gmail.com>
- Add metadataFilters state, availableMetadataKeys + filteredFlags memos - Pre-filter flags via applyMetadataFilters before passing to TanStack Table - Add MetadataFilterPopover in toolbar - Render active filter chips with per-chip remove and Clear all - Update empty-state condition to handle metadata-only filters Signed-off-by: hiepau1231 <hiepau1231@gmail.com>
- 9 tests covering toolbar, chips, AND logic, empty states, combined text+metadata - Add TextEncoder/TextDecoder polyfill for react-router compatibility in jsdom Signed-off-by: hiepau1231 <hiepau1231@gmail.com>
Signed-off-by: hiepau1231 <hiepau1231@gmail.com>
99b0c01 to
d9ef097
Compare
|
Hey @hiepau1231, thanks for your PR! From my understanding, this issue is mainly about organizing flags using tags. To move it forward, we’ll likely need to define a clear approach for categorizing and structuring flags based on those tags. Search/filtering feels like the final piece of the puzzle once that foundation is in place. Curious to hear your thoughts on how you envision the tagging structure. |
|
Hey @erka, thanks for the feedback! You make a great point. I agree that a proper tagging/categorization system is the bigger goal here, and filtering is just one piece of it. Here's how I was thinking about it: Metadata as the foundation for tags Flipt already has a What a proper tagging structure could look like:
Proposal: I can rescope this PR to just the client-side metadata filter as a quick win (it works with what exists today), and open a separate issue/discussion for the tagging data model design. Or, if you'd prefer to define the tagging structure first, I'm happy to contribute to that design and rebase this work on top of it. What approach would you prefer? |
|
Hey @hiepau1231 I’m open to any direction on this. Perhaps it would be good to document your proposal in the original issue so others can share their thoughts as well. |
Summary
Fixes #3739
Adds client-side metadata filtering to the Flags list page (
/namespaces/:ns/flags). Users can now narrow the flag list by one or more metadata key-value pairs without any backend changes.MetadataFilterPopover— new toolbar button (sliders icon) opens a popover with a key input (with datalist autocomplete from existing flag metadata) and a value input. Submitting adds an active filter.Badgechips below the toolbar, with per-chip×remove and a "Clear all" button.useMemopre-filter (applyMetadataFilters) that runs before TanStack Table sees the data, keeping the change minimal and non-invasive.Changes
ui/src/types/Flag.tsMetadataFilterinterfaceui/src/utils/flagMetadataFilter.tsui/src/components/flags/MetadataFilterPopover.tsxui/src/components/flags/FlagTable.tsxui/src/utils/flagMetadataFilter.test.tsui/src/components/flags/MetadataFilterPopover.test.tsxui/src/components/flags/FlagTable.test.tsxui/babel.config.cjs@babel/preset-reactfor JSX test supportui/src/setupTests.tsTest Plan
applyMetadataFiltersunit tests (8): no filters, single filter, case-insensitive, substring, AND logic, missing key, numeric values, boolean valuesMetadataFilterPopoverunit tests (5): renders trigger, calls onAdd, guards empty key/value, resets after addFlagTableintegration tests (9): renders all flags, Filter button, add chip, hide non-matching, remove chip, AND logic, empty state, clear all, combined text+metadatatsc --noEmitclean,eslintclean