From 6c96719052655af4e3ee4661ed82a92b270412b8 Mon Sep 17 00:00:00 2001
From: bjperson
Date: Thu, 18 Dec 2025 14:20:57 +0100
Subject: [PATCH 1/3] feat(datasets): add Atom feed link to search page
Add a link to the datasets Atom feed on the search page.
The link includes current search filters, allowing users to subscribe
to filtered search results via their RSS reader.
Requires opendatateam/udata#3578 for filter support on the Atom endpoint.
---
pages/datasets/search.vue | 56 ++++++++++++++++++++++++++++++---------
1 file changed, 44 insertions(+), 12 deletions(-)
diff --git a/pages/datasets/search.vue b/pages/datasets/search.vue
index e57f3fd2..2639030d 100644
--- a/pages/datasets/search.vue
+++ b/pages/datasets/search.vue
@@ -11,18 +11,43 @@
-
-
- {{ $t('Rechercher parmi les {count} jeux de données sur {site}', {
- count: site.metrics.datasets,
- site: config.public.title,
- }) }}
-
+
+
+
+
+ {{ $t('Rechercher parmi les {count} jeux de données sur {site}', {
+ count: site.metrics.datasets,
+ site: config.public.title,
+ }) }}
+
+
+
+
+
+
+
+ RSS
+
+
@@ -39,5 +64,12 @@ useSeoMeta({
const config = useRuntimeConfig()
+function openRss() {
+ const searchParams = window.location.search
+ const baseUrl = `${config.public.apiBase}/api/1/datasets/recent.atom`
+ const url = searchParams ? `${baseUrl}${searchParams}` : baseUrl
+ window.open(url, '_blank')
+}
+
const { data: site } = await useAPI('/api/1/site/')
From 2c4d7bed04695024efa6116b66bb046a0af7152d Mon Sep 17 00:00:00 2001
From: bjperson
Date: Thu, 18 Dec 2025 18:58:08 +0100
Subject: [PATCH 2/3] feat(datasets): add Atom feed button to search results
Move Atom feed link from page to SearchPage component as requested.
Uses BrandedButton with RiRssLine icon, positioned next to sort control.
URL built from nonFalsyParams for reactive filter support.
Requires opendatateam/udata#3578 for filter support on the Atom endpoint.
---
components/Datasets/SearchPage.vue | 66 +++++++++++++++++++-----------
pages/datasets/search.vue | 56 ++++++-------------------
2 files changed, 53 insertions(+), 69 deletions(-)
diff --git a/components/Datasets/SearchPage.vue b/components/Datasets/SearchPage.vue
index 44c34d40..0236165b 100644
--- a/components/Datasets/SearchPage.vue
+++ b/components/Datasets/SearchPage.vue
@@ -185,33 +185,43 @@
>
{{ t("{count} résultats | {count} résultat | {count} résultats", searchResults.total) }}
-
-
- {{ t('Trier par :') }}
-
-
-
+
+
-
- {{ t('Pertinence') }}
-
-
+
+
- {{ label }}
-
-
+
+ {{ t('Pertinence') }}
+
+
+ {{ label }}
+
+
+
+
@@ -280,7 +290,7 @@
import { BrandedButton, getLink, getOrganizationTypes, LoadingBlock, Pagination, OTHER, USER } from '@datagouv/components-next'
import type { DatasetV2, License, Organization, OrganizationTypes, RegisteredSchema, TranslatedBadge, OrganizationOrSuggest } from '@datagouv/components-next'
import { ref, computed, type Component } from 'vue'
-import { RiCloseCircleLine, RiDownloadLine } from '@remixicon/vue'
+import { RiCloseCircleLine, RiDownloadLine, RiRssLine } from '@remixicon/vue'
import { computedAsync, debouncedRef, useUrlSearchParams } from '@vueuse/core'
import SearchInput from '~/components/Search/SearchInput.vue'
import type { PaginatedArray, SpatialGranularity, SpatialZone, Tag } from '~/types/types'
@@ -320,6 +330,12 @@ const nonFalsyParams = computed(() => {
return { ...propsParams, ...Object.fromEntries(filteredParams), page_size: pageSize }
})
+const atomFeedUrl = computed(() => {
+ const { page, page_size, ...feedParams } = nonFalsyParams.value
+ const query = new URLSearchParams(feedParams).toString()
+ return `${config.public.apiBase}/api/1/datasets/recent.atom${query ? `?${query}` : ''}`
+})
+
const { data: searchResults, status: searchResultsStatus, refresh } = await useAPI>('/api/2/datasets/search/', {
params: nonFalsyParams,
lazy: true,
diff --git a/pages/datasets/search.vue b/pages/datasets/search.vue
index 2639030d..e57f3fd2 100644
--- a/pages/datasets/search.vue
+++ b/pages/datasets/search.vue
@@ -11,43 +11,18 @@
-
-
-
-
- {{ $t('Rechercher parmi les {count} jeux de données sur {site}', {
- count: site.metrics.datasets,
- site: config.public.title,
- }) }}
-
-
-
-
-
-
-
- RSS
-
-
+
+
+ {{ $t('Rechercher parmi les {count} jeux de données sur {site}', {
+ count: site.metrics.datasets,
+ site: config.public.title,
+ }) }}
+
@@ -64,12 +39,5 @@ useSeoMeta({
const config = useRuntimeConfig()
-function openRss() {
- const searchParams = window.location.search
- const baseUrl = `${config.public.apiBase}/api/1/datasets/recent.atom`
- const url = searchParams ? `${baseUrl}${searchParams}` : baseUrl
- window.open(url, '_blank')
-}
-
const { data: site } = await useAPI('/api/1/site/')
From 870bdc812021dbcb044741b8a095dc8c72330ce7 Mon Sep 17 00:00:00 2001
From: Nicolas KEMPF
Date: Tue, 6 Jan 2026 15:35:12 +0100
Subject: [PATCH 3/3] Update SearchPage.vue
---
components/Datasets/SearchPage.vue | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/components/Datasets/SearchPage.vue b/components/Datasets/SearchPage.vue
index 155f9e56..555eb5b9 100644
--- a/components/Datasets/SearchPage.vue
+++ b/components/Datasets/SearchPage.vue
@@ -327,10 +327,10 @@ const params = useUrlSearchParams('history', {
removeFalsyValues: true,
})
-const nonFalsyParams = computed(() => {
+const nonFalsyParams = computed(() => {
const filteredParams = Object.entries(toValue(params)).filter(([_k, v]) => v)
const propsParams = props.organization ? { organization: props.organization.id } : {}
- return { ...propsParams, ...Object.fromEntries(filteredParams), page_size: pageSize }
+ return { ...propsParams, ...Object.fromEntries(filteredParams) as DatasetSearchParams, page_size: pageSize.toFixed(0) }
})
const atomFeedUrl = computed(() => {