@datagouv/components-next 0.2.0 → 1.0.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 (140) hide show
  1. package/README.md +1 -1
  2. package/assets/main.css +56 -1
  3. package/dist/Control-BNCDn-8E.js +148 -0
  4. package/dist/{Datafair.client-x39O4yfF.js → Datafair.client-Dls5AHTE.js} +1 -1
  5. package/dist/Event-BOgJUhNR.js +738 -0
  6. package/dist/Image-BN-4XkIn.js +247 -0
  7. package/dist/{JsonPreview.client-BMsC5JcY.js → JsonPreview.client-DPDTs433.js} +14 -14
  8. package/dist/Map-BdT3i2C4.js +7609 -0
  9. package/dist/MapContainer.client-BdAzd7bj.js +105 -0
  10. package/dist/OSM-CamriM9b.js +71 -0
  11. package/dist/{PdfPreview.client-COOkEkRA.js → PdfPreview.client-CopqSDyt.js} +3 -3
  12. package/dist/{Pmtiles.client-BaiIo4VZ.js → Pmtiles.client-mF6xaOO_.js} +2 -2
  13. package/dist/ScaleLine-BiesrgOv.js +165 -0
  14. package/dist/Swagger.client-eJ7gpfZA.js +4 -0
  15. package/dist/Tile-DCuqwNOI.js +1206 -0
  16. package/dist/TileImage-CmZf8EdU.js +1067 -0
  17. package/dist/View-DcDc7N2K.js +2858 -0
  18. package/dist/{XmlPreview.client-CAdN0w_Y.js → XmlPreview.client-C0OgBkSq.js} +7 -7
  19. package/dist/common-C4rDcQpp.js +243 -0
  20. package/dist/components-next.css +1 -1
  21. package/dist/components-next.js +153 -117
  22. package/dist/components.css +1 -1
  23. package/dist/{MapContainer.client-DeSo8EvG.js → index-BRGqW8aQ.js} +4975 -21416
  24. package/dist/leaflet-src-7m1mB8LI.js +6338 -0
  25. package/dist/{main-Dgri3TQL.js → main-CNHxAJ8J.js} +56758 -51450
  26. package/dist/proj-CKwYjU38.js +1569 -0
  27. package/dist/tilecoord-YW3qEH_j.js +884 -0
  28. package/dist/{vue3-xml-viewer.common-D6skc_Ai.js → vue3-xml-viewer.common-CmAdQfIy.js} +1 -1
  29. package/package.json +5 -1
  30. package/src/components/ActivityList/ActivityList.vue +6 -2
  31. package/src/components/AppLink.vue +4 -1
  32. package/src/components/Avatar.vue +2 -2
  33. package/src/components/AvatarWithName.vue +8 -4
  34. package/src/components/BouncingDots.vue +21 -0
  35. package/src/components/BrandedButton.vue +2 -0
  36. package/src/components/CopyButton.vue +19 -7
  37. package/src/components/DataserviceCard.vue +83 -118
  38. package/src/components/DatasetCard.vue +110 -171
  39. package/src/components/DatasetInformation/DatasetEmbedSection.vue +43 -0
  40. package/src/components/DatasetInformation/DatasetInformationSection.vue +73 -0
  41. package/src/components/DatasetInformation/DatasetSchemaSection.vue +74 -0
  42. package/src/components/DatasetInformation/DatasetSpatialSection.vue +59 -0
  43. package/src/components/DatasetInformation/DatasetTemporalitySection.vue +45 -0
  44. package/src/components/DatasetInformation/index.ts +5 -0
  45. package/src/components/DatasetQualityTooltipContent.vue +3 -3
  46. package/src/components/DescriptionList.vue +1 -4
  47. package/src/components/DescriptionListDetails.vue +5 -0
  48. package/src/components/DescriptionListTerm.vue +5 -0
  49. package/src/components/DiscussionMessageCard.vue +63 -0
  50. package/src/components/ExtraAccordion.vue +4 -4
  51. package/src/components/Form/BadgeSelect.vue +35 -0
  52. package/src/components/Form/FormatSelect.vue +28 -0
  53. package/src/components/Form/GeozoneSelect.vue +52 -0
  54. package/src/components/Form/GranularitySelect.vue +29 -0
  55. package/src/components/Form/LicenseSelect.vue +30 -0
  56. package/src/components/Form/OrganizationSelect.vue +62 -0
  57. package/src/components/Form/OrganizationTypeSelect.vue +34 -0
  58. package/src/components/Form/ReuseTopicSelect.vue +29 -0
  59. package/src/components/Form/SchemaSelect.vue +30 -0
  60. package/src/components/Form/SearchableSelect.vue +334 -0
  61. package/src/components/Form/SelectGroup.vue +132 -0
  62. package/src/components/Form/TagSelect.vue +38 -0
  63. package/src/components/LeafletMap.vue +31 -0
  64. package/src/components/LicenseBadge.vue +24 -0
  65. package/src/components/LoadingBlock.vue +23 -2
  66. package/src/components/MarkdownViewer.vue +3 -1
  67. package/src/components/ObjectCard.vue +42 -0
  68. package/src/components/ObjectCardBadge.vue +22 -0
  69. package/src/components/ObjectCardHeader.vue +35 -0
  70. package/src/components/ObjectCardOwner.vue +43 -0
  71. package/src/components/ObjectCardShortDescription.vue +28 -0
  72. package/src/components/OrganizationCard.vue +35 -20
  73. package/src/components/OrganizationLogo.vue +1 -1
  74. package/src/components/OrganizationNameWithCertificate.vue +13 -7
  75. package/src/components/OwnerTypeIcon.vue +1 -0
  76. package/src/components/Pagination.vue +1 -1
  77. package/src/components/Placeholder.vue +5 -2
  78. package/src/components/PostCard.vue +62 -0
  79. package/src/components/RadioGroup.vue +32 -0
  80. package/src/components/RadioInput.vue +64 -0
  81. package/src/components/ResourceAccordion/EditButton.vue +2 -3
  82. package/src/components/ResourceAccordion/MapContainer.client.vue +20 -16
  83. package/src/components/ResourceAccordion/Metadata.vue +11 -24
  84. package/src/components/ResourceAccordion/Pmtiles.client.vue +1 -1
  85. package/src/components/ResourceAccordion/Preview.vue +1 -1
  86. package/src/components/ResourceAccordion/ResourceAccordion.vue +30 -20
  87. package/src/components/ResourceAccordion/ResourceIcon.vue +1 -0
  88. package/src/components/ResourceAccordion/SchemaBadge.vue +2 -2
  89. package/src/components/ResourceExplorer/ResourceExplorer.vue +243 -0
  90. package/src/components/ResourceExplorer/ResourceExplorerSidebar.vue +116 -0
  91. package/src/components/ResourceExplorer/ResourceExplorerViewer.vue +361 -0
  92. package/src/components/ReuseCard.vue +8 -28
  93. package/src/components/ReuseHorizontalCard.vue +80 -0
  94. package/src/components/Search/BasicAndAdvancedFilters.vue +49 -0
  95. package/src/components/Search/Filter/AccessTypeFilter.vue +37 -0
  96. package/src/components/Search/Filter/DatasetBadgeFilter.vue +40 -0
  97. package/src/components/Search/Filter/FilterButtonGroup.vue +78 -0
  98. package/src/components/Search/Filter/FormatFamilyFilter.vue +39 -0
  99. package/src/components/Search/Filter/LastUpdateRangeFilter.vue +37 -0
  100. package/src/components/Search/Filter/ProducerTypeFilter.vue +39 -0
  101. package/src/components/Search/Filter/ReuseTypeFilter.vue +42 -0
  102. package/src/components/Search/GlobalSearch.vue +611 -0
  103. package/src/components/Search/SearchInput.vue +63 -0
  104. package/src/components/Search/Sidemenu.vue +38 -0
  105. package/src/components/StatBox.vue +5 -5
  106. package/src/components/Tag.vue +30 -0
  107. package/src/components/Toggletip.vue +6 -2
  108. package/src/components/Tooltip.vue +2 -3
  109. package/src/components/TopicCard.vue +134 -0
  110. package/src/components/radioGroupContext.ts +9 -0
  111. package/src/composables/useDebouncedRef.ts +31 -0
  112. package/src/composables/useMetrics.ts +4 -3
  113. package/src/composables/useResourceCapabilities.ts +118 -0
  114. package/src/composables/useRouteQueryBoolean.ts +10 -0
  115. package/src/composables/useSelectModelSync.ts +89 -0
  116. package/src/composables/useStableQueryParams.ts +84 -0
  117. package/src/config.ts +4 -0
  118. package/src/functions/api.ts +17 -6
  119. package/src/functions/api.types.ts +4 -2
  120. package/src/functions/datasets.ts +1 -29
  121. package/src/functions/description.ts +33 -0
  122. package/src/functions/helpers.ts +11 -0
  123. package/src/functions/markdown.ts +60 -16
  124. package/src/functions/metrics.ts +33 -0
  125. package/src/functions/organizations.ts +5 -5
  126. package/src/main.ts +89 -7
  127. package/src/types/dataservices.ts +14 -12
  128. package/src/types/datasets.ts +20 -7
  129. package/src/types/discussions.ts +20 -0
  130. package/src/types/licenses.ts +3 -3
  131. package/src/types/organizations.ts +13 -1
  132. package/src/types/owned.ts +4 -2
  133. package/src/types/pages.ts +70 -0
  134. package/src/types/posts.ts +27 -0
  135. package/src/types/resources.ts +6 -0
  136. package/src/types/reuses.ts +14 -5
  137. package/src/types/search.ts +379 -0
  138. package/src/types/users.ts +12 -3
  139. package/dist/Swagger.client-CpLgaLg6.js +0 -4
  140. package/src/components/DatasetInformationPanel.vue +0 -211
@@ -1,209 +1,148 @@
1
1
  <template>
2
- <div class="p-4 border bg-white border-gray-default relative hover:bg-gray-some">
3
- <div
4
- v-if="dataset.private || dataset.archived"
5
- class="absolute top-0 fr-grid-row fr-grid-row--middle fr-mt-n3v fr-ml-n1v"
6
- >
7
- <p
2
+ <ObjectCard>
3
+ <template #badge>
4
+ <ObjectCardBadge
8
5
  v-if="dataset.private"
9
- class="fr-badge fr-badge--sm fr-badge--mention-grey text-gray-medium mr-2"
6
+ :icon="RiLockLine"
10
7
  >
11
- <span
12
- class="fr-icon-lock-line fr-icon--sm"
13
- aria-hidden="true"
14
- />
15
8
  {{ t('Brouillon') }}
16
- </p>
17
- <p
18
- v-if="dataset.archived"
19
- class="fr-badge fr-badge--sm fr-badge--mention-grey text-gray-medium mr-2"
9
+ </ObjectCardBadge>
10
+ <ObjectCardBadge
11
+ v-else-if="dataset.archived"
12
+ :icon="RiArchiveLine"
20
13
  >
21
- <span
22
- class="fr-icon-archive-line fr-icon--sm"
23
- aria-hidden="true"
24
- />
25
14
  {{ t('Archivé') }}
26
- </p>
15
+ </ObjectCardBadge>
16
+ </template>
17
+
18
+ <template #media>
19
+ <OrganizationLogo
20
+ v-if="dataset.organization"
21
+ :organization="dataset.organization"
22
+ size-class="size-12"
23
+ />
24
+ <Avatar
25
+ v-else-if="dataset.owner"
26
+ :user="dataset.owner"
27
+ :size="48"
28
+ />
29
+ <Placeholder
30
+ v-else
31
+ type="Dataset"
32
+ class="size-12"
33
+ />
34
+ </template>
35
+ <ObjectCardHeader
36
+ :icon="RiDatabase2Line"
37
+ :url="datasetUrl || dataset.page"
38
+ :target="datasetUrlInNewTab ? '_blank' : undefined"
39
+ >
40
+ {{ dataset.title }}
41
+ <template
42
+ v-if="dataset.acronym"
43
+ #extra
44
+ >
45
+ <small class="flex-1 ml-2">{{ dataset.acronym }}</small>
46
+ </template>
47
+ </ObjectCardHeader>
48
+ <div
49
+ v-if="dataset.organization || dataset.owner"
50
+ class="text-sm m-0 flex flex-wrap md:flex-nowrap gap-y-1 items-center truncate"
51
+ >
52
+ <ObjectCardOwner
53
+ :organization="dataset.organization"
54
+ :owner="dataset.owner"
55
+ :organization-url="organizationUrl"
56
+ />
57
+ <RiSubtractLine class="hidden md:block size-4 flex-none fill-gray-medium" />
58
+ <div class="w-full md:w-auto text-gray-medium whitespace-nowrap">
59
+ {{ t('Mis à jour {date}', { date: formatRelativeIfRecentDate(dataset.last_update, { dateStyle: 'medium' }) }) }}
60
+ </div>
27
61
  </div>
28
- <div class="flex flex-wrap md:flex-nowrap gap-4 items-start">
29
- <div class="flex-none">
30
- <div class="flex justify-center items-center p-2 border border-gray-lower bg-[#fff]">
31
- <OrganizationLogo
32
- v-if="dataset.organization"
33
- :organization="dataset.organization"
34
- size-class="size-12"
35
- />
36
- <Avatar
37
- v-else-if="dataset.owner"
38
- :user="dataset.owner"
39
- :size="48"
40
- />
41
- <Placeholder
42
- v-else
43
- type="Dataset"
44
- class="size-12"
45
- />
46
- </div>
62
+ <div class="mx-0 -mb-1 flex flex-wrap items-center text-sm text-gray-medium">
63
+ <div class="hidden sm:flex text-gray-medium -ml-2.5">
64
+ <DatasetQualityInline :quality="dataset.quality" />
47
65
  </div>
48
- <div class="flex-1 overflow-hidden">
49
- <h4 class="w-full text-base mb-0 flex">
50
- <slot
51
- name="datasetUrl"
52
- :dataset="dataset"
53
- :dataset-url="datasetUrl"
54
- >
55
- <AppLink
56
- :to="datasetUrl"
57
- class="text-gray-title text-base bg-none flex w-full truncate"
58
- :target="datasetUrlInNewTab ? '_blank' : undefined"
59
- >
60
- <span
61
- class="block truncate"
62
- :class="dataset.acronym ? 'flex-initial' : 'flex-1'"
63
- >{{ dataset.title }}</span>
64
- <small
65
- v-if="dataset.acronym"
66
- class="flex-1 ml-2"
67
- >{{ dataset.acronym }}</small>
68
- <span class="absolute inset-0" />
69
- </AppLink>
70
- </slot>
71
- </h4>
72
- <div
73
- v-if="dataset.organization || dataset.owner"
74
- class="text-sm m-0 flex flex-wrap md:flex-nowrap gap-y-1 items-center truncate"
66
+ <RiSubtractLine
67
+ aria-hidden="true"
68
+ class="hidden sm:block size-3"
69
+ />
70
+ <div class="flex flex-wrap items-center gap-1">
71
+ <p
72
+ class="text-sm mb-0 flex items-center gap-0.5"
73
+ :aria-label="t('{n} vues | {n} vue | {n} vues', dataset.metrics.views)"
75
74
  >
76
- <template v-if="dataset.organization">
77
- <div class="-mr-0.5 flex-initial truncate">
78
- <AppLink
79
- v-if="organizationUrl"
80
- class="link text-sm overflow-hidden flex items-center relative z-[2] truncate"
81
- :to="organizationUrl"
82
- >
83
- <OrganizationNameWithCertificate :organization="dataset.organization" />
84
- </AppLink>
85
- <OrganizationNameWithCertificate
86
- v-else
87
- :organization="dataset.organization"
88
- />
89
- </div>
90
- </template>
91
- <div
92
- v-else
93
- class="mr-1 truncate"
94
- >
95
- {{ ownerName }}
96
- </div>
97
- <RiSubtractLine class="hidden md:block size-4 flex-none fill-gray-medium" />
98
- <div class="w-full md:w-auto text-gray-medium whitespace-nowrap">
99
- {{ t('Mis à jour {date}', { date: formatRelativeIfRecentDate(dataset.last_update, { dateStyle: 'medium' }) }) }}
100
- </div>
101
- </div>
102
- <div class="mx-0 -mb-1 flex flex-wrap items-center text-sm text-gray-medium">
103
- <div class="fr-hidden flex-sm dash-after-sm text-gray-medium -ml-2.5">
104
- <DatasetQualityInline :quality="dataset.quality" />
105
- </div>
106
- <div class="flex flex-wrap items-center gap-1">
107
- <p
108
- class="text-sm mb-0 flex items-center gap-0.5"
109
- :aria-label="t('{n} vues | {n} vue | {n} vues', dataset.metrics.views)"
110
- >
111
- <RiEyeLine
112
- aria-hidden="true"
113
- class="size-3.5"
114
- />{{ summarize(dataset.metrics.views) }}
115
- </p>
116
- <p
117
- class="text-sm mb-0 flex items-center gap-0.5"
118
- :aria-label="t('{n} téléchargements des ressources | {n} téléchargement des ressources | {n} téléchargements des ressources', dataset.metrics.resources_downloads)"
119
- >
120
- <RiDownloadLine
121
- aria-hidden="true"
122
- class="size-3.5"
123
- />{{ summarize(dataset.metrics.resources_downloads) }}
124
- </p>
125
- <p
126
- class="text-sm mb-0 flex items-center gap-0.5"
127
- :aria-label="t('{n} réutilisations | {n} réutilisation | {n} réutilisations', dataset.metrics.reuses)"
128
- >
129
- <RiLineChartLine
130
- aria-hidden="true"
131
- class="size-3.5"
132
- />{{ summarize(dataset.metrics.reuses) }}
133
- </p>
134
- <p
135
- class="text-sm mb-0 flex items-center gap-0.5"
136
- :aria-label="t('{n} abonnés | {n} abonné | {n} abonnés', dataset.metrics.followers)"
137
- >
138
- <RiStarLine
139
- aria-hidden="true"
140
- class="size-3.5"
141
- />{{ summarize(dataset.metrics.followers) }}
142
- </p>
143
- </div>
144
- </div>
145
- <component
146
- :is="config.textClamp"
147
- v-if="showDescriptionShort && config && config.textClamp && descriptionShort"
148
- class="fr-text--sm fr-mt-1w fr-mb-0 overflow-wrap-anywhere hidden sm:block"
149
- :auto-resize="true"
150
- :text="descriptionShort"
151
- :max-lines="2"
152
- />
75
+ <RiEyeLine
76
+ aria-hidden="true"
77
+ class="size-3.5"
78
+ />{{ summarize(dataset.metrics.views) }}
79
+ </p>
80
+ <p
81
+ class="text-sm mb-0 flex items-center gap-0.5"
82
+ :aria-label="t('{n} téléchargements des ressources | {n} téléchargement des ressources | {n} téléchargements des ressources', dataset.metrics.resources_downloads)"
83
+ >
84
+ <RiDownloadLine
85
+ aria-hidden="true"
86
+ class="size-3.5"
87
+ />{{ summarize(dataset.metrics.resources_downloads) }}
88
+ </p>
89
+ <p
90
+ class="text-sm mb-0 flex items-center gap-0.5"
91
+ :aria-label="t('{n} réutilisations | {n} réutilisation | {n} réutilisations', dataset.metrics.reuses)"
92
+ >
93
+ <RiLineChartLine
94
+ aria-hidden="true"
95
+ class="size-3.5"
96
+ />{{ summarize(dataset.metrics.reuses) }}
97
+ </p>
98
+ <p
99
+ class="text-sm mb-0 flex items-center gap-0.5"
100
+ :aria-label="t('{n} abonnés | {n} abonné | {n} abonnés', dataset.metrics.followers)"
101
+ >
102
+ <RiStarLine
103
+ aria-hidden="true"
104
+ class="size-3.5"
105
+ />{{ summarize(dataset.metrics.followers) }}
106
+ </p>
153
107
  </div>
154
108
  </div>
155
- </div>
109
+ <ObjectCardShortDescription
110
+ v-if="showDescriptionShort"
111
+ :text="getDescriptionShort(props.dataset)"
112
+ />
113
+ </ObjectCard>
156
114
  </template>
157
115
 
158
116
  <script setup lang="ts">
159
117
  import type { RouteLocationRaw } from 'vue-router'
160
- import { computed, ref, watchEffect } from 'vue'
161
- import { RiDownloadLine, RiEyeLine, RiLineChartLine, RiStarLine, RiSubtractLine } from '@remixicon/vue'
118
+ import { RiArchiveLine, RiDatabase2Line, RiDownloadLine, RiEyeLine, RiLineChartLine, RiLockLine, RiStarLine, RiSubtractLine } from '@remixicon/vue'
162
119
  import type { Dataset, DatasetV2 } from '../types/datasets'
163
120
  import { summarize } from '../functions/helpers'
164
121
  import { useFormatDate } from '../functions/dates'
165
- import { getOwnerName } from '../functions/owned'
166
- import { getDescriptionShort } from '../functions/datasets'
167
- import { useComponentsConfig } from '../config'
122
+ import { getDescriptionShort } from '../functions/description'
168
123
  import { useTranslation } from '../composables/useTranslation'
169
124
  import DatasetQualityInline from './DatasetQualityInline.vue'
170
125
  import Avatar from './Avatar.vue'
171
126
  import Placeholder from './Placeholder.vue'
172
- import OrganizationNameWithCertificate from './OrganizationNameWithCertificate.vue'
173
- import AppLink from './AppLink.vue'
174
127
  import OrganizationLogo from './OrganizationLogo.vue'
128
+ import ObjectCardOwner from './ObjectCardOwner.vue'
129
+ import ObjectCard from './ObjectCard.vue'
130
+ import ObjectCardBadge from './ObjectCardBadge.vue'
131
+ import ObjectCardHeader from './ObjectCardHeader.vue'
132
+ import ObjectCardShortDescription from './ObjectCardShortDescription.vue'
175
133
 
176
134
  type Props = {
177
135
  dataset: Dataset | DatasetV2
178
-
179
- /**
180
- * The datasetUrl is a route location object to allow Vue Router to navigate to the details of a dataset.
181
- * It is used as a separate prop to allow other sites using the package to define their own dataset pages.
182
- */
183
- datasetUrl: RouteLocationRaw
136
+ datasetUrl?: RouteLocationRaw
184
137
  datasetUrlInNewTab?: boolean
185
-
186
- /**
187
- * The organizationUrl is an optional route location object to allow Vue Router to navigate to the details of the organization linked to tha dataset.
188
- * It is used as a separate prop to allow other sites using the package to define their own organization pages.
189
- */
190
138
  organizationUrl?: RouteLocationRaw
191
139
  showDescriptionShort?: boolean
192
140
  }
193
141
 
194
142
  const props = withDefaults(defineProps<Props>(), {
195
- style: () => ({}),
196
143
  showDescriptionShort: true,
197
144
  })
198
145
 
199
146
  const { t } = useTranslation()
200
147
  const { formatRelativeIfRecentDate } = useFormatDate()
201
- const ownerName = computed(() => getOwnerName(props.dataset))
202
- const config = useComponentsConfig()
203
-
204
- const descriptionShort = ref('')
205
- watchEffect(async () => {
206
- if (!props.showDescriptionShort) return
207
- descriptionShort.value = await getDescriptionShort(props.dataset.description, props.dataset.description_short)
208
- })
209
148
  </script>
@@ -0,0 +1,43 @@
1
+ <template>
2
+ <div class="space-y-1 py-6">
3
+ <div class="flex items-center space-x-2 mb-1">
4
+ <h3 class="mb-0 uppercase text-gray-plain text-sm font-bold">
5
+ {{ t('Intégrer sur votre site') }}
6
+ </h3>
7
+ <CopyButton
8
+ :hide-label="true"
9
+ :label="t('Copier le code embarqué')"
10
+ :copied-label="t('Code embarqué copié !')"
11
+ :text="embedHtml"
12
+ />
13
+ </div>
14
+ <textarea
15
+ ref="textAreaRef"
16
+ class="bg-gray-lower text-gray-medium rounded font-mono text-sm px-1 py-[2px] w-full border resize-none"
17
+ :value="embedHtml"
18
+ readonly="true"
19
+ @click="selectContent"
20
+ />
21
+ </div>
22
+ </template>
23
+
24
+ <script setup lang="ts">
25
+ import { ref, computed } from 'vue'
26
+ import { useTranslation } from '../../composables/useTranslation'
27
+ import { getDatasetOEmbedHtml } from '../../functions/datasets'
28
+ import type { Dataset, DatasetV2, DatasetV2WithFullObject } from '../../types/datasets'
29
+ import CopyButton from '../CopyButton.vue'
30
+
31
+ const props = defineProps<{
32
+ dataset: Dataset | DatasetV2 | DatasetV2WithFullObject
33
+ }>()
34
+
35
+ const { t } = useTranslation()
36
+ const textAreaRef = ref<HTMLTextAreaElement | null>(null)
37
+
38
+ const embedHtml = computed(() => getDatasetOEmbedHtml('dataset', props.dataset.id))
39
+
40
+ function selectContent(e: Event) {
41
+ (e.target as HTMLTextAreaElement).select()
42
+ }
43
+ </script>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <div class="space-y-1 py-6">
3
+ <h3 class="uppercase text-gray-plain text-sm font-bold">
4
+ {{ t('Informations') }}
5
+ </h3>
6
+ <DescriptionList>
7
+ <div v-if="dataset.tags && dataset.tags.length">
8
+ <DescriptionListTerm>{{ t('Mots-clés') }}</DescriptionListTerm>
9
+ <DescriptionListDetails class="flex flex-wrap gap-2 items-start">
10
+ <AppLink
11
+ v-for="tag in dataset.tags"
12
+ :key="tag"
13
+ class="fr-raw-link"
14
+ :to="getTagUrl(tag)"
15
+ >
16
+ <Tag type="secondary">
17
+ {{ tag }}
18
+ </Tag>
19
+ </AppLink>
20
+ </DescriptionListDetails>
21
+ </div>
22
+ <div>
23
+ <DescriptionListTerm>{{ t('Identifiant') }}</DescriptionListTerm>
24
+ <DescriptionListDetails class="flex items-center gap-2">
25
+ {{ dataset.id }}
26
+ <CopyButton
27
+ class="!-mt-0.5"
28
+ :label="t(`Copier l'identifiant`)"
29
+ :copied-label="t('Identifiant copié !')"
30
+ :text="dataset.id"
31
+ :hide-label="true"
32
+ />
33
+ </DescriptionListDetails>
34
+ </div>
35
+ <div v-if="dataset.license">
36
+ <DescriptionListTerm>{{ t('Licence') }}</DescriptionListTerm>
37
+ <DescriptionListDetails>
38
+ <LicenseBadge :license="dataset.license" />
39
+ </DescriptionListDetails>
40
+ </div>
41
+ <slot />
42
+ </DescriptionList>
43
+ </div>
44
+ </template>
45
+
46
+ <script setup lang="ts">
47
+ import { useTranslation } from '../../composables/useTranslation'
48
+ import { useComponentsConfig } from '../../config'
49
+ import type { DatasetV2WithFullObject } from '../../types/datasets'
50
+ import DescriptionList from '../DescriptionList.vue'
51
+ import DescriptionListTerm from '../DescriptionListTerm.vue'
52
+ import DescriptionListDetails from '../DescriptionListDetails.vue'
53
+ import AppLink from '../AppLink.vue'
54
+ import CopyButton from '../CopyButton.vue'
55
+ import LicenseBadge from '../LicenseBadge.vue'
56
+ import Tag from '../Tag.vue'
57
+
58
+ const props = defineProps<{
59
+ dataset: DatasetV2WithFullObject
60
+ tagUrl?: (tag: string) => string
61
+ }>()
62
+
63
+ const { t } = useTranslation()
64
+ const config = useComponentsConfig()
65
+
66
+ function getTagUrl(tag: string): string {
67
+ if (props.tagUrl) {
68
+ return props.tagUrl(tag)
69
+ }
70
+ const base = config.baseUrl.endsWith('/') ? config.baseUrl.slice(0, -1) : config.baseUrl
71
+ return `${base}/datasets/search?tag=${tag}`
72
+ }
73
+ </script>
@@ -0,0 +1,74 @@
1
+ <template>
2
+ <div
3
+ v-if="schemas && schemas.length"
4
+ class="space-y-1 py-6"
5
+ >
6
+ <h3 class="uppercase text-gray-plain text-sm font-bold">
7
+ {{ t('Schéma de données') }}
8
+ </h3>
9
+ <div class="space-y-4">
10
+ <div
11
+ v-for="schema, index in schemas"
12
+ :key="index"
13
+ class="flex flex-col md:flex-row gap-2 justify-between items-center"
14
+ >
15
+ <p class="text-sm mb-0">
16
+ {{ t('Les fichiers du jeu de données suivent le schéma :') }}
17
+ <Tag
18
+ type="secondary"
19
+ :icon="RiCheckboxCircleLine"
20
+ >
21
+ {{ schema.name || schema.url }}
22
+ </Tag>
23
+ </p>
24
+ <div v-if="schema.url || schema.name">
25
+ <BrandedButton
26
+ color="secondary"
27
+ :icon="RiBook2Line"
28
+ :href="schema.url ? schema.url : `${config.schemasSiteUrl}${schema.name}`"
29
+ >
30
+ {{ t('Voir la documentation du schéma') }}
31
+ </BrandedButton>
32
+ </div>
33
+ </div>
34
+ <p
35
+ v-if="config.schemasSiteUrl && config.schemasSiteName"
36
+ class="text-sm"
37
+ >
38
+ <TranslationT keypath="Les schémas de données permettent de décrire des modèles de données, découvrez comment les schémas améliorent la qualité des données et quels sont les cas d'usages possibles sur {link}">
39
+ <template #link>
40
+ <AppLink
41
+ :to="config.schemasSiteUrl"
42
+ external
43
+ >
44
+ {{ config.schemasSiteName }}
45
+ </AppLink>
46
+ </template>
47
+ </TranslationT>
48
+ </p>
49
+ </div>
50
+ </div>
51
+ </template>
52
+
53
+ <script setup lang="ts">
54
+ import { RiBook2Line, RiCheckboxCircleLine } from '@remixicon/vue'
55
+ import { useTranslation } from '../../composables/useTranslation'
56
+ import { useComponentsConfig } from '../../config'
57
+ import { useFetch } from '../../functions/api'
58
+ import type { Dataset, DatasetV2, DatasetV2WithFullObject } from '../../types/datasets'
59
+ import type { Schema } from '../../types/schemas'
60
+ import Tag from '../Tag.vue'
61
+ import BrandedButton from '../BrandedButton.vue'
62
+ import TranslationT from '../TranslationT.vue'
63
+ import AppLink from '../AppLink.vue'
64
+
65
+ const props = defineProps<{
66
+ dataset: Dataset | DatasetV2 | DatasetV2WithFullObject
67
+ }>()
68
+
69
+ const { t } = useTranslation()
70
+ const config = useComponentsConfig()
71
+
72
+ const { data } = await useFetch<Array<Schema>>(`/api/2/datasets/${props.dataset.id}/schemas/`)
73
+ const schemas = data
74
+ </script>
@@ -0,0 +1,59 @@
1
+ <template>
2
+ <div
3
+ v-if="dataset.spatial"
4
+ class="space-y-1 py-6"
5
+ >
6
+ <h3 class="uppercase text-gray-plain text-sm font-bold">
7
+ {{ t('Couverture spatiale') }}
8
+ </h3>
9
+ <DescriptionList>
10
+ <div v-if="dataset.spatial.zones && dataset.spatial.zones.length">
11
+ <DescriptionListTerm>{{ t('Zones') }}</DescriptionListTerm>
12
+ <DescriptionListDetails>{{ zonesDisplay }}</DescriptionListDetails>
13
+ </div>
14
+ <div v-if="dataset.spatial.geom">
15
+ <DescriptionListTerm>{{ t('Couverture géographique') }}</DescriptionListTerm>
16
+ <DescriptionListDetails>
17
+ <slot
18
+ name="map"
19
+ :geojson="dataset.spatial.geom"
20
+ />
21
+ </DescriptionListDetails>
22
+ </div>
23
+ <div v-if="dataset.spatial.granularity">
24
+ <DescriptionListTerm>{{ t('Granularité de la couverture territoriale') }}</DescriptionListTerm>
25
+ <DescriptionListDetails>{{ dataset.spatial.granularity.name }}</DescriptionListDetails>
26
+ </div>
27
+ <slot />
28
+ </DescriptionList>
29
+ </div>
30
+ </template>
31
+
32
+ <script setup lang="ts">
33
+ import { computed } from 'vue'
34
+ import { useTranslation } from '../../composables/useTranslation'
35
+ import type { DatasetV2WithFullObject } from '../../types/datasets'
36
+ import DescriptionList from '../DescriptionList.vue'
37
+ import DescriptionListTerm from '../DescriptionListTerm.vue'
38
+ import DescriptionListDetails from '../DescriptionListDetails.vue'
39
+
40
+ const props = defineProps<{
41
+ dataset: DatasetV2WithFullObject
42
+ }>()
43
+
44
+ const { t } = useTranslation()
45
+
46
+ const zonesDisplay = computed(() => {
47
+ if (!props.dataset.spatial?.zones?.length) return ''
48
+ const names = props.dataset.spatial.zones.map(z => z.name)
49
+ return humanJoin(names)
50
+ })
51
+
52
+ function humanJoin(source: Array<string>): string {
53
+ const array = [...source]
54
+ if (!array.length) return ''
55
+ if (array.length === 1) return array[0]!
56
+ const last = array.pop()!
57
+ return `${array.join(', ')} ${t('et')} ${last}`
58
+ }
59
+ </script>
@@ -0,0 +1,45 @@
1
+ <template>
2
+ <div class="space-y-1 py-6">
3
+ <h3 class="uppercase text-gray-plain text-sm font-bold">
4
+ {{ t('Temporalité') }}
5
+ </h3>
6
+ <DescriptionList>
7
+ <div>
8
+ <DescriptionListTerm>{{ t('Création') }}</DescriptionListTerm>
9
+ <DescriptionListDetails>{{ formatDate(dataset.created_at) }}</DescriptionListDetails>
10
+ </div>
11
+ <div v-if="dataset.frequency">
12
+ <DescriptionListTerm>{{ t('Fréquence') }}</DescriptionListTerm>
13
+ <DescriptionListDetails>{{ dataset.frequency.label }}</DescriptionListDetails>
14
+ </div>
15
+ <div v-if="dataset.temporal_coverage">
16
+ <DescriptionListTerm>{{ t('Couverture temporelle') }}</DescriptionListTerm>
17
+ <DescriptionListDetails>
18
+ <DateRangeDetails :range="dataset.temporal_coverage" />
19
+ </DescriptionListDetails>
20
+ </div>
21
+ <div>
22
+ <DescriptionListTerm>{{ t('Dernière mise à jour') }}</DescriptionListTerm>
23
+ <DescriptionListDetails>{{ formatDate(dataset.last_update) }}</DescriptionListDetails>
24
+ </div>
25
+ <slot />
26
+ </DescriptionList>
27
+ </div>
28
+ </template>
29
+
30
+ <script setup lang="ts">
31
+ import { useTranslation } from '../../composables/useTranslation'
32
+ import { useFormatDate } from '../../functions/dates'
33
+ import type { DatasetV2WithFullObject } from '../../types/datasets'
34
+ import DescriptionList from '../DescriptionList.vue'
35
+ import DescriptionListTerm from '../DescriptionListTerm.vue'
36
+ import DescriptionListDetails from '../DescriptionListDetails.vue'
37
+ import DateRangeDetails from '../DateRangeDetails.vue'
38
+
39
+ defineProps<{
40
+ dataset: DatasetV2WithFullObject
41
+ }>()
42
+
43
+ const { t } = useTranslation()
44
+ const { formatDate } = useFormatDate()
45
+ </script>
@@ -0,0 +1,5 @@
1
+ export { default as DatasetInformationSection } from './DatasetInformationSection.vue'
2
+ export { default as DatasetTemporalitySection } from './DatasetTemporalitySection.vue'
3
+ export { default as DatasetSpatialSection } from './DatasetSpatialSection.vue'
4
+ export { default as DatasetSchemaSection } from './DatasetSchemaSection.vue'
5
+ export { default as DatasetEmbedSection } from './DatasetEmbedSection.vue'
@@ -1,7 +1,7 @@
1
1
  <template>
2
- <h5 class="text-sm text-gray-plain font-bold">
2
+ <p class="text-sm text-gray-plain font-bold mb-0">
3
3
  {{ t("Qualité des métadonnées :") }}
4
- </h5>
4
+ </p>
5
5
  <ul class="list-none pl-0 space-y-2">
6
6
  <DatasetQualityItem
7
7
  :passed="quality.dataset_description_quality"
@@ -52,7 +52,7 @@
52
52
  class="pb-0"
53
53
  />
54
54
  </ul>
55
- <div class="fr-grid-row fr-grid-row--right not-enlarged">
55
+ <div class="fr-grid-row fr-grid-row--right">
56
56
  <a
57
57
  :href="config.datasetQualityGuideUrl"
58
58
  target="_blank"
@@ -1,8 +1,5 @@
1
1
  <template>
2
- <dl class="fr-my-0">
2
+ <dl class="grid grid-cols-1 md:grid-cols-3 gap-6 p-0">
3
3
  <slot />
4
4
  </dl>
5
5
  </template>
6
-
7
- <script setup lang="ts">
8
- </script>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <dd class="p-0 text-sm text-gray-medium">
3
+ <slot />
4
+ </dd>
5
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <dt class="mb-1 p-0 text-sm font-bold">
3
+ <slot />
4
+ </dt>
5
+ </template>