From 08f798afbe5453d46fa33859bf3285bb8ab0aa9d Mon Sep 17 00:00:00 2001 From: Thibaud Dauce Date: Wed, 15 Apr 2026 14:23:04 +0200 Subject: [PATCH 1/6] feat: search custom filters --- components/Design/ThemeTagFilter.vue | 41 ++++++++++++ .../src/components/Search/GlobalSearch.vue | 48 +++++++++++++- .../src/composables/useSearchFilter.ts | 66 +++++++++++++++++++ .../src/composables/useStableQueryParams.ts | 35 +++++++++- datagouv-components/src/main.ts | 4 ++ pages/design/dataset-search.vue | 7 +- 6 files changed, 194 insertions(+), 7 deletions(-) create mode 100644 components/Design/ThemeTagFilter.vue create mode 100644 datagouv-components/src/composables/useSearchFilter.ts diff --git a/components/Design/ThemeTagFilter.vue b/components/Design/ThemeTagFilter.vue new file mode 100644 index 000000000..f44f7a5f9 --- /dev/null +++ b/components/Design/ThemeTagFilter.vue @@ -0,0 +1,41 @@ + + + diff --git a/datagouv-components/src/components/Search/GlobalSearch.vue b/datagouv-components/src/components/Search/GlobalSearch.vue index 30564639c..cd73b04fc 100644 --- a/datagouv-components/src/components/Search/GlobalSearch.vue +++ b/datagouv-components/src/components/Search/GlobalSearch.vue @@ -42,7 +42,7 @@ -
+
@@ -21,6 +25,7 @@ diff --git a/datagouv-components/src/components/Search/GlobalSearch.vue b/datagouv-components/src/components/Search/GlobalSearch.vue index cd73b04fc..f08198c4a 100644 --- a/datagouv-components/src/components/Search/GlobalSearch.vue +++ b/datagouv-components/src/components/Search/GlobalSearch.vue @@ -42,7 +42,7 @@
-
+
diff --git a/datagouv-components/src/components/Search/GlobalSearch.vue b/datagouv-components/src/components/Search/GlobalSearch.vue index f08198c4a..158d76793 100644 --- a/datagouv-components/src/components/Search/GlobalSearch.vue +++ b/datagouv-components/src/components/Search/GlobalSearch.vue @@ -140,6 +140,13 @@ :loading="searchResultsStatus === 'pending'" :style="{ order: getOrder('type') }" /> + > = { organization: organizationId, + organization_facet: organizationId, organization_badge: organizationType, tag, format, diff --git a/datagouv-components/src/composables/useStableQueryParams.ts b/datagouv-components/src/composables/useStableQueryParams.ts index d11734251..1a06d40b9 100644 --- a/datagouv-components/src/composables/useStableQueryParams.ts +++ b/datagouv-components/src/composables/useStableQueryParams.ts @@ -1,5 +1,5 @@ import { computed, ref, watch, type Ref } from 'vue' -import type { SearchTypeConfig } from '../types/search' +import { SearchFilterAliases, type SearchTypeConfig } from '../types/search' import type { CustomFilterEntry } from './useSearchFilter' type FilterRefs = Record> @@ -47,7 +47,8 @@ export function useStableQueryParams(options: StableQueryParamsOptions) { if (filterRef) { const value = filterRef.value if (value !== undefined && value !== '' && value !== null) { - params[filterName as string] = value + const paramName = SearchFilterAliases[filterName as string] ?? filterName as string + params[paramName] = value } } } diff --git a/datagouv-components/src/main.ts b/datagouv-components/src/main.ts index b90789912..0b6aa07b6 100644 --- a/datagouv-components/src/main.ts +++ b/datagouv-components/src/main.ts @@ -24,7 +24,7 @@ import type { Weight, WellType } from './types/ui' import type { User, UserReference } from './types/users' import type { Report, ReportSubject, ReportReason } from './types/reports' import type { GlobalSearchConfig, SearchType, SortOption } from './types/search' -import { getDefaultDatasetConfig, getDefaultDataserviceConfig, getDefaultReuseConfig, getDefaultOrganizationConfig, getDefaultTopicConfig, getDefaultGlobalSearchConfig, defaultDatasetSortOptions, defaultDataserviceSortOptions, defaultReuseSortOptions, defaultOrganizationSortOptions } from './types/search' +import { SearchFilterAliases, getDefaultDatasetConfig, getDefaultDataserviceConfig, getDefaultReuseConfig, getDefaultOrganizationConfig, getDefaultTopicConfig, getDefaultGlobalSearchConfig, defaultDatasetSortOptions, defaultDataserviceSortOptions, defaultReuseSortOptions, defaultOrganizationSortOptions } from './types/search' import { useSearchFilter } from './composables/useSearchFilter' import type { UseSearchFilterOptions } from './composables/useSearchFilter' @@ -222,6 +222,7 @@ export type { } export { + SearchFilterAliases, getDefaultDatasetConfig, getDefaultDataserviceConfig, getDefaultReuseConfig, diff --git a/datagouv-components/src/types/search.ts b/datagouv-components/src/types/search.ts index 30d0f0516..8c33928f5 100644 --- a/datagouv-components/src/types/search.ts +++ b/datagouv-components/src/types/search.ts @@ -289,12 +289,17 @@ export type SortOption = { label: string } +// UI filter keys that map to a different API param name +export const SearchFilterAliases: Record = { + organization_facet: 'organization', +} + export type DatasetSearchConfig = { class: 'datasets' name?: string hiddenFilters?: HiddenFilter[] - basicFilters?: (keyof DatasetSearchFilters)[] - advancedFilters?: (keyof DatasetSearchFilters)[] + basicFilters?: (keyof DatasetSearchFilters | keyof typeof SearchFilterAliases)[] + advancedFilters?: (keyof DatasetSearchFilters | keyof typeof SearchFilterAliases)[] sortOptions?: SortOption[] } @@ -302,8 +307,8 @@ export type DataserviceSearchConfig = { class: 'dataservices' name?: string hiddenFilters?: HiddenFilter[] - basicFilters?: (keyof DataserviceSearchFilters)[] - advancedFilters?: (keyof DataserviceSearchFilters)[] + basicFilters?: (keyof DataserviceSearchFilters | keyof typeof SearchFilterAliases)[] + advancedFilters?: (keyof DataserviceSearchFilters | keyof typeof SearchFilterAliases)[] sortOptions?: SortOption[] } @@ -311,8 +316,8 @@ export type ReuseSearchConfig = { class: 'reuses' name?: string hiddenFilters?: HiddenFilter[] - basicFilters?: (keyof ReuseSearchFilters)[] - advancedFilters?: (keyof ReuseSearchFilters)[] + basicFilters?: (keyof ReuseSearchFilters | keyof typeof SearchFilterAliases)[] + advancedFilters?: (keyof ReuseSearchFilters | keyof typeof SearchFilterAliases)[] sortOptions?: SortOption[] } @@ -329,8 +334,8 @@ export type TopicSearchConfig = { class: 'topics' name?: string hiddenFilters?: HiddenFilter[] - basicFilters?: (keyof TopicSearchFilters)[] - advancedFilters?: (keyof TopicSearchFilters)[] + basicFilters?: (keyof TopicSearchFilters | keyof typeof SearchFilterAliases)[] + advancedFilters?: (keyof TopicSearchFilters | keyof typeof SearchFilterAliases)[] sortOptions?: SortOption[] } From def0b62747351d830ae6e2a4e9a6854df95541bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20Bult=C3=A9?= Date: Wed, 15 Apr 2026 11:02:34 +0200 Subject: [PATCH 6/6] use correct select --- .../Search/Filter/OrganizationFacetFilter.vue | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/datagouv-components/src/components/Search/Filter/OrganizationFacetFilter.vue b/datagouv-components/src/components/Search/Filter/OrganizationFacetFilter.vue index 18326c938..b39db7388 100644 --- a/datagouv-components/src/components/Search/Filter/OrganizationFacetFilter.vue +++ b/datagouv-components/src/components/Search/Filter/OrganizationFacetFilter.vue @@ -1,14 +1,14 @@ @@ -16,7 +16,7 @@ import { computed } from 'vue' import type { FacetItem } from '../../../types/search' import { useTranslation } from '../../../composables/useTranslation' -import FilterButtonGroup from './FilterButtonGroup.vue' +import SearchableSelect from '../../Form/SearchableSelect.vue' const props = defineProps<{ modelValue: string | undefined @@ -31,18 +31,16 @@ const emit = defineEmits<{ const { t } = useTranslation() // organization_id_with_name facet name format: "org-slug|Org Display Name" -const parsed = computed(() => - (props.facets ?? []).map((f) => { - const [id = '', ...labelParts] = f.name.split('|') - return { id, label: labelParts.join('|'), count: f.count } - }), -) - const options = computed(() => - parsed.value.map(({ id, label }) => ({ value: id, label })), + (props.facets ?? []) + .map((f) => { + const [id = '', ...labelParts] = f.name.split('|') + return { value: id, label: labelParts.join('|') } + }) + .filter(o => o.value !== '' && o.label !== ''), ) -const normalizedFacets = computed(() => - parsed.value.map(({ id, count }) => ({ name: id, count })), +const selectedOption = computed(() => + options.value.find(o => o.value === props.modelValue) ?? null, )