@datagouv/components-next 0.0.32 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +5 -15
  2. package/assets/labels/hvd.svg +15 -0
  3. package/assets/labels/inspire.svg +20 -0
  4. package/assets/labels/sl.svg +5 -0
  5. package/assets/labels/spd.svg +5 -0
  6. package/assets/labels/sr.svg +5 -0
  7. package/dist/JsonPreview.client-NQ9byxF5.js +92 -0
  8. package/dist/{MapContainer.client-Dhfz-YU8.js → MapContainer.client-D7Y0OXMU.js} +17587 -6826
  9. package/dist/{PdfPreview.client--W0FK7CN.js → PdfPreview.client-DU6FbUh0.js} +47 -48
  10. package/dist/{Pmtiles.client-B6vRTwrm.js → Pmtiles.client-DCOxft6M.js} +7609 -7503
  11. package/dist/Swagger.client-DTHhEAFT.js +4 -0
  12. package/dist/XmlPreview.client-BEOCeCP8.js +84 -0
  13. package/dist/components-next.css +6 -6
  14. package/dist/components-next.js +95 -80
  15. package/dist/components.css +2 -2
  16. package/dist/en-CuSmdvir.js +30 -0
  17. package/dist/hvd-DYeke1vM.js +4 -0
  18. package/dist/inspire-BLXeJvob.js +4 -0
  19. package/dist/{main-yWiuApVL.js → main-DFEQrdg5.js} +53395 -55984
  20. package/dist/{pdf-vue3-Dm2ZCc3P.js → pdf-vue3-IkJO65RH.js} +2 -2
  21. package/dist/{pdf.min-f72cfa08-DAetWL3M.js → pdf.min-f72cfa08-CdgJTooZ.js} +78 -78
  22. package/dist/sl-VR8Tb1_u.js +4 -0
  23. package/dist/spd-BJ-Omhgt.js +4 -0
  24. package/dist/sr-DjSF-8xW.js +4 -0
  25. package/dist/{text-clamp.esm-Mb7Qdtu9.js → text-clamp.esm-B5kW_XMt.js} +54 -55
  26. package/dist/{vue3-json-viewer-B1fiyuLU.js → vue3-json-viewer-BXwup7nO.js} +88 -93
  27. package/dist/{vue3-xml-viewer.common-1QyofKqS.js → vue3-xml-viewer.common-RC76oYFu.js} +54 -54
  28. package/package.json +12 -11
  29. package/src/components/ActivityList/ActivityList.vue +159 -0
  30. package/src/components/ActivityList/UserActivityList.vue +30 -0
  31. package/src/components/AppLink.vue +3 -3
  32. package/src/components/Avatar.vue +1 -0
  33. package/src/components/DataserviceCard.vue +3 -3
  34. package/src/components/DatasetCard.vue +19 -18
  35. package/src/components/DatasetInformationPanel.vue +16 -16
  36. package/src/components/DatasetLabelTag.vue +40 -0
  37. package/src/components/DatasetQuality.vue +13 -10
  38. package/src/components/DatasetQualityInline.vue +5 -2
  39. package/src/components/DatasetQualityScore.vue +3 -3
  40. package/src/components/DatasetQualityTooltipContent.vue +2 -2
  41. package/src/components/DateRangeDetails.vue +7 -3
  42. package/src/components/ExtraAccordion.vue +3 -1
  43. package/src/components/OrganizationNameWithCertificate.vue +2 -2
  44. package/src/components/PaddedContainer.vue +28 -0
  45. package/src/components/Pagination.vue +2 -2
  46. package/src/components/Placeholder.vue +1 -1
  47. package/src/components/ReadMore.vue +17 -17
  48. package/src/components/ResourceAccordion/DataStructure.vue +8 -3
  49. package/src/components/ResourceAccordion/EditButton.vue +2 -2
  50. package/src/components/ResourceAccordion/JsonPreview.client.vue +7 -5
  51. package/src/components/ResourceAccordion/MapContainer.client.vue +2 -2
  52. package/src/components/ResourceAccordion/Metadata.vue +10 -10
  53. package/src/components/ResourceAccordion/PdfPreview.client.vue +7 -5
  54. package/src/components/ResourceAccordion/Pmtiles.client.vue +2 -2
  55. package/src/components/ResourceAccordion/Preview.vue +2 -2
  56. package/src/components/ResourceAccordion/ResourceAccordion.vue +23 -15
  57. package/src/components/ResourceAccordion/SchemaBadge.vue +4 -4
  58. package/src/components/ResourceAccordion/XmlPreview.client.vue +7 -5
  59. package/src/components/ReuseCard.vue +3 -3
  60. package/src/components/ReuseDetails.vue +2 -2
  61. package/src/components/SmallChart.vue +33 -30
  62. package/src/components/StatBox.vue +6 -6
  63. package/src/components/Toggletip.vue +0 -1
  64. package/src/components/TranslationT.vue +51 -0
  65. package/src/composables/useTranslation.ts +169 -0
  66. package/src/functions/activities.ts +36 -0
  67. package/src/functions/api.ts +4 -4
  68. package/src/functions/datasets.ts +28 -0
  69. package/src/functions/dates.ts +4 -4
  70. package/src/functions/helpers.ts +3 -3
  71. package/src/functions/organizations.ts +2 -2
  72. package/src/functions/pagination.ts +9 -0
  73. package/src/functions/resources.ts +2 -2
  74. package/src/functions/reuses.ts +3 -3
  75. package/src/main.ts +24 -20
  76. package/src/types/activity.ts +24 -0
  77. package/src/types/api.ts +8 -0
  78. package/src/types/badges.ts +4 -0
  79. package/src/types/dataservices.ts +6 -8
  80. package/src/types/datasets.ts +2 -1
  81. package/src/types/site.ts +1 -0
  82. package/src/types/topics.ts +17 -2
  83. package/dist/JsonPreview.client-BRhCOHlE.js +0 -93
  84. package/dist/Swagger.client-ch5H8aT2.js +0 -4
  85. package/dist/XmlPreview.client-BcbnRWAp.js +0 -85
@@ -11,10 +11,10 @@
11
11
  </template>
12
12
 
13
13
  <script setup lang="ts">
14
- import { useI18n } from 'vue-i18n'
15
14
  import { RiPencilLine } from '@remixicon/vue'
16
15
  import { computed } from 'vue'
17
16
  import BrandedButton from '../BrandedButton.vue'
17
+ import { useTranslation } from '../../composables/useTranslation'
18
18
 
19
19
  type Props = {
20
20
  datasetId: string
@@ -26,7 +26,7 @@ const props = withDefaults(defineProps<Props>(), {
26
26
  isCommunityResource: false,
27
27
  })
28
28
 
29
- const { t } = useI18n()
29
+ const { t } = useTranslation()
30
30
 
31
31
  const adminUrl = computed(() => {
32
32
  if (props.isCommunityResource) {
@@ -15,7 +15,7 @@
15
15
  v-else-if="loading"
16
16
  class="text-gray-medium"
17
17
  >
18
- {{ $t("Chargement de l'aperçu JSON...") }}
18
+ {{ t("Chargement de l'aperçu JSON...") }}
19
19
  </div>
20
20
  <SimpleBanner
21
21
  v-else-if="fileTooLarge"
@@ -24,8 +24,8 @@
24
24
  >
25
25
  <RiErrorWarningLine class="shink-0 size-6" />
26
26
  <span>{{ fileSizeBytes
27
- ? $t("Fichier JSON trop volumineux pour l'aperçu. Pour consulter le fichier complet, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.")
28
- : $t("L'aperçu n'est pas disponible car la taille du fichier est inconnue. Pour consulter le fichier complet, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.")
27
+ ? t("Fichier JSON trop volumineux pour l'aperçu. Pour consulter le fichier complet, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.")
28
+ : t("L'aperçu n'est pas disponible car la taille du fichier est inconnue. Pour consulter le fichier complet, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.")
29
29
  }}</span>
30
30
  </SimpleBanner>
31
31
  <SimpleBanner
@@ -34,7 +34,7 @@
34
34
  class="flex items-center space-x-2"
35
35
  >
36
36
  <RiErrorWarningLine class="shink-0 size-6" />
37
- <span>{{ $t("Ce fichier JSON ne peut pas être prévisualisé, peut-être parce qu'il est hébergé sur un autre site qui ne l'autorise pas. Pour le consulter, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.") }}</span>
37
+ <span>{{ t("Ce fichier JSON ne peut pas être prévisualisé, peut-être parce qu'il est hébergé sur un autre site qui ne l'autorise pas. Pour le consulter, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.") }}</span>
38
38
  </SimpleBanner>
39
39
  <SimpleBanner
40
40
  v-else-if="error"
@@ -42,7 +42,7 @@
42
42
  class="flex items-center space-x-2"
43
43
  >
44
44
  <RiErrorWarningLine class="shink-0 size-6" />
45
- <span>{{ $t("Erreur lors du chargement de l'aperçu JSON.") }}</span>
45
+ <span>{{ t("Erreur lors du chargement de l'aperçu JSON.") }}</span>
46
46
  </SimpleBanner>
47
47
  </div>
48
48
  </template>
@@ -54,6 +54,7 @@ import { RiErrorWarningLine } from '@remixicon/vue'
54
54
  import { useComponentsConfig } from '../../config'
55
55
  import SimpleBanner from '../SimpleBanner.vue'
56
56
  import type { Resource } from '../../types/resources'
57
+ import { useTranslation } from '../../composables/useTranslation'
57
58
 
58
59
  const JsonViewer = defineAsyncComponent(() =>
59
60
  import('vue3-json-viewer').then((module) => {
@@ -68,6 +69,7 @@ const props = defineProps<{
68
69
  }>()
69
70
 
70
71
  const config = useComponentsConfig()
72
+ const { t } = useTranslation()
71
73
 
72
74
  const jsonData = ref<unknown>(null)
73
75
  const loading = ref(false)
@@ -16,7 +16,6 @@
16
16
 
17
17
  <script setup lang = "ts">
18
18
  import { onMounted, ref, useTemplateRef } from 'vue'
19
- import { useI18n } from 'vue-i18n'
20
19
  import { RiErrorWarningLine } from '@remixicon/vue'
21
20
 
22
21
  import View from 'ol/View'
@@ -37,10 +36,11 @@ import {
37
36
 
38
37
  import SimpleBanner from '../SimpleBanner.vue'
39
38
  import type { Resource } from '../../types/resources'
39
+ import { useTranslation } from '../../composables/useTranslation'
40
40
 
41
41
  const props = defineProps<{ resource: Resource }>()
42
42
 
43
- const { t } = useI18n()
43
+ const { t } = useTranslation()
44
44
 
45
45
  let map = null
46
46
  const mapRef = useTemplateRef('mapRef')
@@ -1,5 +1,4 @@
1
1
  <script setup lang="ts">
2
- import { useI18n } from 'vue-i18n'
3
2
  import { computed } from 'vue'
4
3
  import type { Resource } from '../../types/resources'
5
4
  import CopyButton from '../CopyButton.vue'
@@ -10,6 +9,7 @@ import { useFormatDate } from '../../functions/dates'
10
9
  import { filesize } from '../../functions/helpers'
11
10
  import ExtraAccordion from '../ExtraAccordion.vue'
12
11
  import { getResourceTitleId, getResourceLabel } from '../../functions/resources'
12
+ import { useTranslation } from '../../composables/useTranslation'
13
13
 
14
14
  const props = defineProps<{
15
15
  resource: Resource
@@ -18,7 +18,7 @@ const props = defineProps<{
18
18
  const hasExtras = computed(() => Object.keys(props.resource.extras).length)
19
19
  const resourceTitleId = computed(() => getResourceTitleId(props.resource))
20
20
 
21
- const { t } = useI18n()
21
+ const { t } = useTranslation()
22
22
  const { formatDate } = useFormatDate()
23
23
  </script>
24
24
 
@@ -29,8 +29,8 @@ const { formatDate } = useFormatDate()
29
29
  <DescriptionTerm>
30
30
  {{ t('URL') }}
31
31
  <CopyButton
32
- :label="$t(`Copier l'URL`)"
33
- :copied-label="$t('URL copiée!')"
32
+ :label="t(`Copier l'URL`)"
33
+ :copied-label="t('URL copiée !')"
34
34
  :text="resource.url"
35
35
  :aria-describedby="resourceTitleId"
36
36
  />
@@ -45,8 +45,8 @@ const { formatDate } = useFormatDate()
45
45
  <DescriptionTerm>
46
46
  {{ t('URL stable') }}
47
47
  <CopyButton
48
- :label="$t(`Copier l'URL stable`)"
49
- :copied-label="$t('URL stable copiée!')"
48
+ :label="t(`Copier l'URL stable`)"
49
+ :copied-label="t('URL stable copiée !')"
50
50
  :text="resource.latest"
51
51
  :aria-describedby="resourceTitleId"
52
52
  />
@@ -61,8 +61,8 @@ const { formatDate } = useFormatDate()
61
61
  <DescriptionTerm>
62
62
  {{ t('Identifiant') }}
63
63
  <CopyButton
64
- :label="$t(`Copier l'identifiant`)"
65
- :copied-label="$t('ID copié !')"
64
+ :label="t(`Copier l'identifiant`)"
65
+ :copied-label="t('ID copié !')"
66
66
  :text="resource.id"
67
67
  :aria-describedby="resourceTitleId"
68
68
  />
@@ -76,8 +76,8 @@ const { formatDate } = useFormatDate()
76
76
  <DescriptionTerm>
77
77
  {{ resource.checksum.type }}
78
78
  <CopyButton
79
- :label="$t('Copier la somme de contrôle')"
80
- :copied-label="$t('Somme de contrôle copiée !')"
79
+ :label="t('Copier la somme de contrôle')"
80
+ :copied-label="t('Somme de contrôle copiée !')"
81
81
  :text="resource.checksum.value"
82
82
  :aria-describedby="resourceTitleId"
83
83
  />
@@ -31,7 +31,7 @@
31
31
  v-else-if="loading"
32
32
  class="text-gray-medium"
33
33
  >
34
- {{ $t("Chargement de l'aperçu PDF...") }}
34
+ {{ t("Chargement de l'aperçu PDF...") }}
35
35
  </div>
36
36
  <SimpleBanner
37
37
  v-else-if="fileTooLarge"
@@ -40,8 +40,8 @@
40
40
  >
41
41
  <RiErrorWarningLine class="shink-0 size-6" />
42
42
  <span>{{ fileSizeBytes
43
- ? $t("Fichier PDF trop volumineux pour l'aperçu. Pour consulter le fichier complet, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.")
44
- : $t("L'aperçu n'est pas disponible car la taille du fichier est inconnue. Pour consulter le fichier complet, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.")
43
+ ? t("Fichier PDF trop volumineux pour l'aperçu. Pour consulter le fichier complet, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.")
44
+ : t("L'aperçu n'est pas disponible car la taille du fichier est inconnue. Pour consulter le fichier complet, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.")
45
45
  }}</span>
46
46
  </SimpleBanner>
47
47
  <SimpleBanner
@@ -50,7 +50,7 @@
50
50
  class="flex items-center space-x-2"
51
51
  >
52
52
  <RiErrorWarningLine class="shink-0 size-6" />
53
- <span>{{ $t("Ce fichier PDF ne peut pas être prévisualisé, peut-être parce qu'il est hébergé sur un autre site qui ne l'autorise pas. Pour le consulter, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.") }}</span>
53
+ <span>{{ t("Ce fichier PDF ne peut pas être prévisualisé, peut-être parce qu'il est hébergé sur un autre site qui ne l'autorise pas. Pour le consulter, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.") }}</span>
54
54
  </SimpleBanner>
55
55
  <SimpleBanner
56
56
  v-else-if="error"
@@ -58,7 +58,7 @@
58
58
  class="flex items-center space-x-2"
59
59
  >
60
60
  <RiErrorWarningLine class="shink-0 size-6" />
61
- <span>{{ $t("Erreur lors du chargement de l'aperçu PDF. Pour consulter le fichier, téléchargez-le depuis l'onglet Téléchargements.") }}</span>
61
+ <span>{{ t("Erreur lors du chargement de l'aperçu PDF. Pour consulter le fichier, téléchargez-le depuis l'onglet Téléchargements.") }}</span>
62
62
  </SimpleBanner>
63
63
  </div>
64
64
  </template>
@@ -69,6 +69,7 @@ import { RiErrorWarningLine } from '@remixicon/vue'
69
69
  import SimpleBanner from '../SimpleBanner.vue'
70
70
  import { useComponentsConfig } from '../../config'
71
71
  import type { Resource } from '../../types/resources'
72
+ import { useTranslation } from '../../composables/useTranslation'
72
73
 
73
74
  const PDF = defineAsyncComponent(() =>
74
75
  import('pdf-vue3').then((module) => {
@@ -81,6 +82,7 @@ const props = defineProps<{
81
82
  }>()
82
83
 
83
84
  const config = useComponentsConfig()
85
+ const { t } = useTranslation()
84
86
 
85
87
  const pdfData = ref<boolean>(false)
86
88
  const loading = ref(false)
@@ -53,7 +53,6 @@
53
53
 
54
54
  <script setup lang="ts">
55
55
  import { computed, onMounted, ref, useTemplateRef } from 'vue'
56
- import { useI18n } from 'vue-i18n'
57
56
  import { RiErrorWarningLine, RiExternalLinkFill } from '@remixicon/vue'
58
57
  import { Protocol, PMTiles } from 'pmtiles'
59
58
  import maplibregl from 'maplibre-gl'
@@ -65,11 +64,12 @@ import type { Resource } from '../../types/resources'
65
64
  import BrandedButton from '../BrandedButton.vue'
66
65
  import styleVector from '../../../assets/json/vector.json'
67
66
  import SimpleBanner from '../SimpleBanner.vue'
67
+ import { useTranslation } from '../../composables/useTranslation'
68
68
  import franceSvg from './france.svg?raw'
69
69
 
70
70
  const props = defineProps<{ resource: Resource }>()
71
71
 
72
- const { t } = useI18n()
72
+ const { t } = useTranslation()
73
73
  const { formatDate } = useFormatDate()
74
74
 
75
75
  const config = useComponentsConfig()
@@ -104,7 +104,6 @@
104
104
 
105
105
  <script setup lang="ts">
106
106
  import { computed, onMounted, ref } from 'vue'
107
- import { useI18n } from 'vue-i18n'
108
107
  import { RiArrowDownLine, RiArrowUpLine, RiErrorWarningLine, RiExternalLinkFill } from '@remixicon/vue'
109
108
  import Pagination from '../Pagination.vue'
110
109
  import { getData, type SortConfig } from '../../functions/tabularApi'
@@ -113,12 +112,13 @@ import type { Resource } from '../../types/resources'
113
112
  import { useComponentsConfig } from '../../config'
114
113
  import BrandedButton from '../BrandedButton.vue'
115
114
  import SimpleBanner from '../SimpleBanner.vue'
115
+ import { useTranslation } from '../../composables/useTranslation'
116
116
  import franceSvg from './france.svg?raw'
117
117
  import PreviewLoader from './PreviewLoader.vue'
118
118
 
119
119
  const props = defineProps<{ resource: Resource }>()
120
120
 
121
- const { t } = useI18n()
121
+ const { t } = useTranslation()
122
122
  const { formatDate } = useFormatDate()
123
123
 
124
124
  const rows = ref<Array<Record<string, unknown>>>([])
@@ -45,8 +45,8 @@
45
45
  </button>
46
46
  </h4>
47
47
  <CopyButton
48
- :label="$t('Copier le lien')"
49
- :copied-label="$t('Lien copié !')"
48
+ :label="t('Copier le lien')"
49
+ :copied-label="t('Lien copié !')"
50
50
  :text="resourceExternalUrl"
51
51
  class="z-2"
52
52
  />
@@ -104,7 +104,7 @@
104
104
  size="xs"
105
105
  external
106
106
  >
107
- {{ $t('Visiter') }}
107
+ {{ t('Visiter') }}
108
108
  </BrandedButton>
109
109
  </p>
110
110
  <p
@@ -243,13 +243,13 @@
243
243
  v-if="resource.format === 'url'"
244
244
  class="font-bold fr-text--sm fr-mb-0"
245
245
  >
246
- {{ $t("URL d'origine") }}
246
+ {{ t("URL d'origine") }}
247
247
  </dt>
248
248
  <dt
249
249
  v-else
250
250
  class="font-bold fr-text--sm fr-mb-0"
251
251
  >
252
- {{ $t('Format original') }}
252
+ {{ t('Format original') }}
253
253
  </dt>
254
254
  <dd class="text-sm pl-0 mb-4 text-gray-medium h-8 flex flex-wrap items-center">
255
255
  <span v-if="resource.format === 'url'">
@@ -279,19 +279,19 @@
279
279
  class="fr-link"
280
280
  rel="ugc nofollow noopener"
281
281
  >
282
- <span>{{ $t('Format {format}', { format: resource.format }) }}<span v-if="resource.filesize"> - {{ filesize(resource.filesize) }}</span></span>
282
+ <span>{{ t('Format {format}', { format: resource.format }) }}<span v-if="resource.filesize"> - {{ filesize(resource.filesize) }}</span></span>
283
283
  </a>
284
284
  </span>
285
285
  <CopyButton
286
- :label="$t('Copier le lien')"
287
- :copied-label="$t('Lien copié !')"
286
+ :label="t('Copier le lien')"
287
+ :copied-label="t('Lien copié !')"
288
288
  :text="resource.latest"
289
289
  class="relative"
290
290
  />
291
291
  </dd>
292
292
  <template v-if="generatedFormats.length">
293
293
  <dt class="font-bold fr-text--sm fr-mb-0">
294
- {{ $t('Formats générés automatiquement par {platform} (dernière mise à jour {date})', { platform: config.name, date: conversionsLastUpdate }) }}
294
+ {{ t('Formats générés automatiquement par {platform} (dernière mise à jour {date})', { platform: config.name, date: conversionsLastUpdate }) }}
295
295
  </dt>
296
296
  <dd
297
297
  v-for="generatedFormat in generatedFormats"
@@ -305,12 +305,12 @@
305
305
  class="fr-link"
306
306
  rel="ugc nofollow noopener"
307
307
  >
308
- <span>{{ $t('Format {format}', { format: generatedFormat.format }) }}<span v-if="generatedFormat.size"> - {{ filesize(generatedFormat.size) }}</span></span>
308
+ <span>{{ t('Format {format}', { format: generatedFormat.format }) }}<span v-if="generatedFormat.size"> - {{ filesize(generatedFormat.size) }}</span></span>
309
309
  </a>
310
310
  </span>
311
311
  <CopyButton
312
- :label="$t('Copier le lien')"
313
- :copied-label="$t('Lien copié !')"
312
+ :label="t('Copier le lien')"
313
+ :copied-label="t('Lien copié !')"
314
314
  :text="generatedFormat.url"
315
315
  class="relative"
316
316
  />
@@ -321,7 +321,12 @@
321
321
  <div
322
322
  v-if="tab.key === 'swagger'"
323
323
  >
324
- <div>{{ t("Swagger généré automatiquement par {platform}. Ce swagger vous permet d'interroger les données par API en les filtrant par valeur de colonne.", { platform: config.name }) }}</div>
324
+ <div class="fr-mb-4w">
325
+ <p>{{ t("Cette API est générée automatiquement par {platform} à partir du fichier.", { platform: config.name }) }}</p>
326
+ <p>{{ t("- Si le fichier est modifié, l'API sera mise à jour et sa structure pourra changer.") }}</p>
327
+ <p>{{ t("- Si le fichier est supprimé, l'API sera également supprimée.") }}</p>
328
+ <p>{{ t("Pour des usages pérennes, prévoyez que cette API dépend directement du fichier source.") }}</p>
329
+ </div>
325
330
  <Swagger
326
331
  v-if="hasTabularData"
327
332
  :url="`${config.tabularApiUrl}/api/resources/${props.resource.id}/swagger/`"
@@ -336,7 +341,6 @@
336
341
 
337
342
  <script setup lang="ts">
338
343
  import { ref, computed, defineAsyncComponent } from 'vue'
339
- import { useI18n } from 'vue-i18n'
340
344
  import { RiDownloadLine, RiFileCopyLine, RiFileWarningLine } from '@remixicon/vue'
341
345
  import OrganizationNameWithCertificate from '../OrganizationNameWithCertificate.vue'
342
346
  import { filesize, summarize } from '../../functions/helpers'
@@ -356,6 +360,7 @@ import { getOwnerName } from '../../functions/owned'
356
360
  import { getResourceFormatIcon, getResourceTitleId, detectOgcService } from '../../functions/resources'
357
361
  import BrandedButton from '../BrandedButton.vue'
358
362
  import { getResourceExternalUrl } from '../../functions/datasets'
363
+ import { useTranslation } from '../../composables/useTranslation'
359
364
  import Metadata from './Metadata.vue'
360
365
  import SchemaBadge from './SchemaBadge.vue'
361
366
  import ResourceIcon from './ResourceIcon.vue'
@@ -386,7 +391,7 @@ const JsonPreview = defineAsyncComponent(() => import('./JsonPreview.client.vue'
386
391
  const PdfPreview = defineAsyncComponent(() => import('./PdfPreview.client.vue'))
387
392
  const XmlPreview = defineAsyncComponent(() => import('./XmlPreview.client.vue'))
388
393
 
389
- const { t } = useI18n()
394
+ const { t } = useTranslation()
390
395
  const { formatRelativeIfRecentDate } = useFormatDate()
391
396
 
392
397
  const hasPreview = computed(() => {
@@ -475,6 +480,9 @@ const tabsOptions = computed(() => {
475
480
  })
476
481
  const switchTab = (index: number) => {
477
482
  const option = tabsOptions.value[index]
483
+ if (!option) {
484
+ return
485
+ }
478
486
  trackEvent(['View resource tab', props.resource.id, option.label])
479
487
 
480
488
  if (option.key === 'data') {
@@ -4,13 +4,13 @@
4
4
  class="inline-flex mb-0 items-baseline text-xs"
5
5
  >
6
6
  <Toggletip
7
- :button-props="{ class: 'relative z-2 -ml-3 top-1 -my-3', title: $t('Schéma de données') }"
7
+ :button-props="{ class: 'relative z-2 -ml-3 top-1 -my-3', title: t('Schéma de données') }"
8
8
  no-margin
9
9
  >
10
10
  <RiInformationLine class="size-4" />
11
11
  <template #toggletip="{ close }">
12
12
  <div class="flex justify-between border-bottom">
13
- <h5 class="fr-text--sm fr-my-0 fr-p-2v">{{ $t("Schéma de données") }}</h5>
13
+ <h5 class="fr-text--sm fr-my-0 fr-p-2v">{{ t("Schéma de données") }}</h5>
14
14
  <button
15
15
  type="button"
16
16
  :title="t('Fermer')"
@@ -97,17 +97,17 @@
97
97
  <script setup lang="ts">
98
98
  import { RiInformationLine } from '@remixicon/vue'
99
99
  import { computed, onMounted, ref } from 'vue'
100
- import { useI18n } from 'vue-i18n'
101
100
  import type { Resource } from '../../types/resources'
102
101
  import Toggletip from '../Toggletip.vue'
103
102
  import type { RegisteredSchema, ValidataError } from '../../functions/schemas'
104
103
  import { findSchemaInCatalog, useGetCatalog, useGetSchemaDocumentation, useGetSchemaValidationUrl } from '../../functions/schemas'
104
+ import { useTranslation } from '../../composables/useTranslation'
105
105
 
106
106
  const props = defineProps<{
107
107
  resource: Resource
108
108
  }>()
109
109
 
110
- const { t } = useI18n()
110
+ const { t } = useTranslation()
111
111
  const getSchemaValidationUrl = useGetSchemaValidationUrl()
112
112
  const getSchemaDocumentation = useGetSchemaDocumentation()
113
113
  const getCatalog = useGetCatalog()
@@ -7,7 +7,7 @@
7
7
  v-else-if="loading"
8
8
  class="text-gray-medium"
9
9
  >
10
- {{ $t("Chargement de l'aperçu XML...") }}
10
+ {{ t("Chargement de l'aperçu XML...") }}
11
11
  </div>
12
12
  <SimpleBanner
13
13
  v-else-if="fileTooLarge"
@@ -16,8 +16,8 @@
16
16
  >
17
17
  <RiErrorWarningLine class="shink-0 size-6" />
18
18
  <span>{{ fileSizeBytes
19
- ? $t("Fichier XML trop volumineux pour l'aperçu. Pour consulter le fichier complet, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.")
20
- : $t("L'aperçu n'est pas disponible car la taille du fichier est inconnue. Pour consulter le fichier complet, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.")
19
+ ? t("Fichier XML trop volumineux pour l'aperçu. Pour consulter le fichier complet, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.")
20
+ : t("L'aperçu n'est pas disponible car la taille du fichier est inconnue. Pour consulter le fichier complet, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.")
21
21
  }}</span>
22
22
  </SimpleBanner>
23
23
  <SimpleBanner
@@ -26,7 +26,7 @@
26
26
  class="flex items-center space-x-2"
27
27
  >
28
28
  <RiErrorWarningLine class="shink-0 size-6" />
29
- <span>{{ $t("Ce fichier XML ne peut pas être prévisualisé, peut-être parce qu'il est hébergé sur un autre site qui ne l'autorise pas. Pour le consulter, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.") }}</span>
29
+ <span>{{ t("Ce fichier XML ne peut pas être prévisualisé, peut-être parce qu'il est hébergé sur un autre site qui ne l'autorise pas. Pour le consulter, téléchargez-le en cliquant sur le bouton bleu ou depuis l'onglet Téléchargements.") }}</span>
30
30
  </SimpleBanner>
31
31
  <SimpleBanner
32
32
  v-else-if="error"
@@ -34,7 +34,7 @@
34
34
  class="flex items-center space-x-2"
35
35
  >
36
36
  <RiErrorWarningLine class="shink-0 size-6" />
37
- <span>{{ $t("Erreur lors du chargement de l'aperçu XML.") }}</span>
37
+ <span>{{ t("Erreur lors du chargement de l'aperçu XML.") }}</span>
38
38
  </SimpleBanner>
39
39
  </div>
40
40
  </template>
@@ -46,6 +46,7 @@ import { RiErrorWarningLine } from '@remixicon/vue'
46
46
  import { useComponentsConfig } from '../../config'
47
47
  import SimpleBanner from '../SimpleBanner.vue'
48
48
  import type { Resource } from '../../types/resources'
49
+ import { useTranslation } from '../../composables/useTranslation'
49
50
  import '../../types/vue3-xml-viewer.d.ts'
50
51
 
51
52
  const XmlViewer = defineAsyncComponent(() =>
@@ -59,6 +60,7 @@ const props = defineProps<{
59
60
  }>()
60
61
 
61
62
  const config = useComponentsConfig()
63
+ const { t } = useTranslation()
62
64
 
63
65
  const xmlData = ref<string | null>(null)
64
66
  const loading = ref(false)
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <article class="fr-enlarge-link group/reuse-card bg-white border border-gray-default flex flex-col relative">
2
+ <article class="fr-enlarge-link group/reuse-card bg-white border border-gray-default hover:bg-gray-some flex flex-col relative">
3
3
  <div class="flex flex-col h-full flex-1 order-2 px-8">
4
4
  <div class="order-1 flex flex-col px-4 py-1 h-full -mx-8">
5
5
  <h3 class="font-bold text-base mt-1 mb-0 truncate">
@@ -75,11 +75,11 @@
75
75
  <script setup lang="ts">
76
76
  import { RiLockLine, RiSubtractLine } from '@remixicon/vue'
77
77
  import { computed } from 'vue'
78
- import { useI18n } from 'vue-i18n'
79
78
  import type { RouteLocationRaw } from 'vue-router'
80
79
  import { useFormatDate } from '../functions/dates'
81
80
  import { getOwnerName } from '../functions/owned'
82
81
  import type { Reuse } from '../types/reuses'
82
+ import { useTranslation } from '../composables/useTranslation'
83
83
  import AppLink from './AppLink.vue'
84
84
  import OrganizationNameWithCertificate from './OrganizationNameWithCertificate.vue'
85
85
  import ReuseDetails from './ReuseDetails.vue'
@@ -100,7 +100,7 @@ const props = defineProps<{
100
100
  organizationUrl?: RouteLocationRaw
101
101
  }>()
102
102
 
103
- const { t } = useI18n()
103
+ const { t } = useTranslation()
104
104
  const { formatRelativeIfRecentDate } = useFormatDate()
105
105
 
106
106
  const ownerName = computed(() => getOwnerName(props.reuse))
@@ -30,16 +30,16 @@
30
30
 
31
31
  <script setup lang="ts">
32
32
  import { RiEyeLine, RiStarLine, RiSubtractLine } from '@remixicon/vue'
33
- import { useI18n } from 'vue-i18n'
34
33
  import { useReuseType } from '../composables/useReuseType'
35
34
  import { summarize } from '../functions/helpers'
36
35
  import type { Reuse } from '../types/reuses'
36
+ import { useTranslation } from '../composables/useTranslation'
37
37
 
38
38
  const props = defineProps<{
39
39
  reuse: Reuse
40
40
  }>()
41
41
 
42
- const { t } = useI18n()
42
+ const { t } = useTranslation()
43
43
 
44
44
  const { label: reuseType } = useReuseType(() => props.reuse.type)
45
45
  </script>
@@ -57,7 +57,10 @@ const data = computed(() => {
57
57
  months.sort()
58
58
  const orderedData: Record<string, number> = {}
59
59
  for (const month of months) {
60
- orderedData[month] = props.data[month]
60
+ orderedData[month] = 0
61
+ if (props.data[month]) {
62
+ orderedData[month] = props.data[month]
63
+ }
61
64
  }
62
65
  return orderedData
63
66
  })
@@ -76,33 +79,33 @@ const additionalDatasetConfig = computed<{
76
79
  borderDash: (ctx: ScriptableLineSegmentContext) => Array<number>
77
80
  }
78
81
  } | object>(() => {
79
- if (props.type === 'bar') {
80
- return {
81
- type: 'bar',
82
- barPercentage: 1,
83
- categoryPercentage: 0.9,
84
- // Change the color of the last bar only
85
- backgroundColor: months.value.map((_value, index) => index === months.value.length - 1 ? (props.lastWithLowEmphasis ? LIGHT_COLOR_WITH_OPACITY : COLOR) : LIGHT_COLOR),
86
- }
87
- }
88
-
89
- if (props.type === 'line') {
90
- if (props.lastWithLowEmphasis) {
91
- return {
92
- type: 'line',
93
- segment: {
94
- borderColor: (ctx: ScriptableLineSegmentContext) => last(ctx, COLOR_WITH_OPACITY) || COLOR,
95
- borderDash: (ctx: ScriptableLineSegmentContext) => last(ctx, [3, 3]) || [6, 0],
96
- },
97
- }
98
- }
99
- return {
100
- type: 'line',
101
- }
102
- }
103
-
104
- return {}
105
- })
82
+ if (props.type === 'bar') {
83
+ return {
84
+ type: 'bar',
85
+ barPercentage: 1,
86
+ categoryPercentage: 0.9,
87
+ // Change the color of the last bar only
88
+ backgroundColor: months.value.map((_value, index) => index === months.value.length - 1 ? (props.lastWithLowEmphasis ? LIGHT_COLOR_WITH_OPACITY : COLOR) : LIGHT_COLOR),
89
+ }
90
+ }
91
+
92
+ if (props.type === 'line') {
93
+ if (props.lastWithLowEmphasis) {
94
+ return {
95
+ type: 'line',
96
+ segment: {
97
+ borderColor: (ctx: ScriptableLineSegmentContext) => last(ctx, COLOR_WITH_OPACITY) || COLOR,
98
+ borderDash: (ctx: ScriptableLineSegmentContext) => last(ctx, [3, 3]) || [6, 0],
99
+ },
100
+ }
101
+ }
102
+ return {
103
+ type: 'line',
104
+ }
105
+ }
106
+
107
+ return {}
108
+ })
106
109
 
107
110
  const getMonthYear = (dateAsString: string): string => {
108
111
  const date = new Date(dateAsString)
@@ -110,8 +113,8 @@ const getMonthYear = (dateAsString: string): string => {
110
113
  return `${(date.getMonth() + 1).toString().padStart(2, '0')}/${date.getFullYear().toString().slice(-2)}`
111
114
  }
112
115
 
113
- const startDate = computed(() => months.value.length ? getMonthYear(months.value[0]) : null)
114
- const endDate = computed(() => months.value.length ? getMonthYear(months.value[months.value.length - 1]) : null)
116
+ const startDate = computed(() => months.value.length ? getMonthYear(months.value[0]!) : null)
117
+ const endDate = computed(() => months.value.length ? getMonthYear(months.value[months.value.length - 1]!) : null)
115
118
 
116
119
  const OPTIONS = {
117
120
  // @ts-expect-error animation can be `true` but the typing is not expecting it