Skip to content

feat(search): tagFilters#1034

Open
abulte wants to merge 7 commits intodatagouv:mainfrom
ecolabdata:feat/global-search/tag-filters
Open

feat(search): tagFilters#1034
abulte wants to merge 7 commits intodatagouv:mainfrom
ecolabdata:feat/global-search/tag-filters

Conversation

@abulte
Copy link
Copy Markdown
Contributor

@abulte abulte commented Apr 9, 2026

Close ecolabdata/ecospheres#1011

Adds a tagFilters option to GlobalSearchConfig that renders select dropdowns whose values map to the tag API param.

This enables multiple independent predefined-value tag filters (e.g. theme, enjeu, secteur like on https://ecologie.data.gouv.fr/indicators) that merge correctly with hiddenFilters and the native tag filter.

The URL is two-way synced with the dropdowns. Query param name is filter's name.

Example usage:

const config: GlobalSearchConfig = [
    {
        class: 'datasets',
        hiddenFilters: [
            { key: 'tag', value: 'ecospheres-indicateurs' },
            { key: 'organization', value: '67884b4da4fca9c97bbef479' }
        ],
        basicFilters: ['last_update_range', 'badge'],
        advancedFilters: [],
        tagFilters: [
            {
                urlParam: 'theme',
                label: 'Thématique',
                defaultLabel: 'Toutes les thématiques',
                values: [
                    { value: 'ecospheres-indicateurs-theme-mieux-consommer', label: 'Mieux consommer' },
                    { value: 'ecospheres-indicateurs-theme-mieux-produire', label: 'Mieux produire' },
                    // ...
                ]
            },
            {
                urlParam: 'enjeu',
                label: 'Enjeu',
                defaultLabel: 'Tous les enjeux',
                values: [
                    { value: 'ecospheres-indicateurs-enjeu-adaptation-climat', label: 'Adaptation climat' },
                // ...
                ]
            },
            // secteur, levier, maille…
        ]
    }
]

Selecting "Mieux consommer" in Thème dropdown → theme=ecospheres-indicateurs-theme-mieux-consommer in the URL → API receives tag=ecospheres-indicateurs&tag=ecospheres-indicateurs-theme-mieux-consommer.

Bonus

@abulte
Copy link
Copy Markdown
Contributor Author

abulte commented Apr 9, 2026

CI output, failures seem unrelated? https://github.com/ecolabdata/cdata/actions/runs/24194727780

@abulte abulte marked this pull request as ready for review April 9, 2026 16:09
@abulte
Copy link
Copy Markdown
Contributor Author

abulte commented Apr 9, 2026

@maudetes @ThibaudDauce @nicolaskempf57 don't know why it's not assigning you as reviewers 🤷 And I can't do it myself, hence the ping. Thanks!

abulte added a commit to opendatateam/udata-front-kit that referenced this pull request Apr 9, 2026
@ThibaudDauce
Copy link
Copy Markdown
Contributor

Interesting feature! Before merging, I'd like to suggest an alternative approach that avoids adding a parallel filter system inside GlobalSearch.

The core need is: let consumers add custom filter UI that maps to API params. Right now, tagFilters introduces its own ref management (tagFilterRefs), its own merge logic in useStableQueryParams, and requires manual extensions in hasFilters, filtersForReset, resetFilters, and the type-change watcher — all parallel to the existing allFilters system.

Simpler alternative: a slot + reactive hiddenFilters

  1. Add a slot (e.g. #extra-filters) in the sidebar so consumers can render whatever filter UI they need
  2. Make hiddenFilters reactive in useStableQueryParams (today typeConfig is read once, not watched — so changing hiddenFilters via a computed config has no effect)

The consumer would then do:

<GlobalSearch :config="searchConfig">
  <template #extra-filters>
    <MyThemeDropdown v-model="selectedTheme" />
    <MyEnjeuDropdown v-model="selectedEnjeu" />
  </template>
</GlobalSearch>
const searchConfig = computed(() => [{
  class: 'datasets',
  hiddenFilters: [
    { key: 'tag', value: 'ecospheres-indicateurs' },
    ...(selectedTheme.value ? [{ key: 'tag', value: selectedTheme.value }] : []),
    ...(selectedEnjeu.value ? [{ key: 'tag', value: selectedEnjeu.value }] : []),
  ],
}])

Benefits:

  • Zero changes to GlobalSearch's internal filter logic (no tagFilterRefs, no manual extensions in reset/hasFilters/watch)
  • The consumer owns the complexity (which dropdowns, which labels, which values)
  • Generic: works for any custom filter, not just tags
  • Backwards compatible: existing static hiddenFilters keep working

The only work needed inside GlobalSearch/useStableQueryParams is making the config reactive (watch props.config changes) and adding the slot.

That said, if this approach ends up being more complex on your side or doesn't fit your constraints, we can absolutely merge this PR as-is — it works and solves the problem. I'm just wondering if having full control via a slot might actually be simpler and more flexible for you?

@abulte
Copy link
Copy Markdown
Contributor Author

abulte commented Apr 13, 2026

@ThibaudDauce Thanks for the review and the suggestion!

I agree that the new codepath to handle tag filters is suboptimal, especially since it's not used (yet?) in cdata.

But I feel your proposal would push a lot of complexity on downstream projects that use the component. Today, the whole filter lifecycle (url sync, reset, page invalidation, type-switch cleanup) is centralised in GlobalSearch, which make it easy to integrate. If I understand your proposal correctly, this lifecycle would need to be managed partly in downstream apps (for custom filters) and leave the rest to GlobalSearch (for native filters). This feels hard, especially the URL sync stuff which is tricky.

This is all based on my assumptions and "static" analysis, I didn't implement your solution. But I feel like the current solution is good enough given the challenges of the alternative.

@ThibaudDauce
Copy link
Copy Markdown
Contributor

What do you think of this solution? #1048

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GlobalSearch: support tag-based predefined-value filters (tagFilters)

2 participants