@datagouv/components-next 0.0.8 → 0.0.9

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 (103) hide show
  1. package/README.md +34 -14
  2. package/assets/json/vector.json +2377 -0
  3. package/assets/main.css +3 -0
  4. package/assets/swagger-themes/newspaper.css +1669 -0
  5. package/assets/tailwind.config.js +1 -1
  6. package/dist/JsonPreview.client-BIz1_EiB.js +92 -0
  7. package/dist/MapContainer.client-ZDwr4Q_I.js +78276 -0
  8. package/dist/PdfPreview.client-BTTMM27i.js +112 -0
  9. package/dist/Pmtiles.client-4kOoUQcR.js +22377 -0
  10. package/dist/Swagger.client-Q7a5wb51.js +4 -0
  11. package/dist/XmlPreview.client-BYIIkDqf.js +84 -0
  12. package/dist/components-next.css +52 -1
  13. package/dist/components-next.js +42 -41
  14. package/dist/components.css +1 -1
  15. package/dist/main-CLUk9Jj7.js +105843 -0
  16. package/dist/pdf-vue3-BZh6kzke.js +273 -0
  17. package/dist/pdf.min-f72cfa08-DAetWL3M.js +9501 -0
  18. package/dist/{text-clamp.esm-DurZFOvT.js → text-clamp.esm-DP59tec5.js} +1 -1
  19. package/dist/vue3-json-viewer-DIQzFF6K.js +1089 -0
  20. package/dist/vue3-xml-viewer.common-BmKw6vER.js +5437 -0
  21. package/package.json +8 -8
  22. package/src/components/AvatarWithName.vue +6 -2
  23. package/src/components/BannerAction.vue +1 -1
  24. package/src/components/BrandedButton.vue +13 -8
  25. package/src/components/CopyButton.vue +7 -7
  26. package/src/components/DataserviceCard.vue +54 -23
  27. package/src/components/DatasetCard.vue +36 -24
  28. package/src/components/DatasetInformationPanel.vue +19 -18
  29. package/src/components/DatasetQuality.vue +21 -18
  30. package/src/components/DatasetQualityInline.vue +1 -1
  31. package/src/components/DatasetQualityItem.vue +3 -3
  32. package/src/components/DatasetQualityItemWarning.vue +2 -2
  33. package/src/components/DatasetQualityScore.vue +2 -2
  34. package/src/components/DatasetQualityTooltipContent.vue +29 -29
  35. package/src/components/DescriptionDetails.vue +2 -2
  36. package/src/components/ExtraAccordion.vue +10 -7
  37. package/src/components/OrganizationCard.vue +9 -4
  38. package/src/components/OrganizationNameWithCertificate.vue +25 -11
  39. package/src/components/Pagination.vue +26 -15
  40. package/src/components/ReadMore.vue +2 -2
  41. package/src/components/ResourceAccordion/DataStructure.vue +2 -2
  42. package/src/components/ResourceAccordion/EditButton.vue +10 -6
  43. package/src/components/ResourceAccordion/JsonPreview.client.vue +153 -0
  44. package/src/components/ResourceAccordion/MapContainer.client.vue +137 -0
  45. package/src/components/ResourceAccordion/Metadata.vue +33 -54
  46. package/src/components/ResourceAccordion/PdfPreview.client.vue +189 -0
  47. package/src/components/ResourceAccordion/Pmtiles.client.vue +166 -0
  48. package/src/components/ResourceAccordion/Preview.vue +39 -37
  49. package/src/components/ResourceAccordion/ResourceAccordion.vue +141 -63
  50. package/src/components/ResourceAccordion/ResourceIcon.vue +7 -1
  51. package/src/components/ResourceAccordion/SchemaBadge.vue +26 -26
  52. package/src/components/ResourceAccordion/{Swagger.vue → Swagger.client.vue} +1 -1
  53. package/src/components/ResourceAccordion/XmlPreview.client.vue +143 -0
  54. package/src/components/ReuseCard.vue +10 -7
  55. package/src/components/ReuseDetails.vue +3 -3
  56. package/src/components/SimpleBanner.vue +7 -4
  57. package/src/components/SmallChart.vue +23 -9
  58. package/src/components/StatBox.vue +92 -10
  59. package/src/config.ts +6 -2
  60. package/src/functions/api.ts +18 -18
  61. package/src/functions/dates.ts +81 -74
  62. package/src/functions/helpers.ts +5 -4
  63. package/src/functions/organizations.ts +5 -5
  64. package/src/functions/resources.ts +34 -5
  65. package/src/functions/schemas.ts +4 -3
  66. package/src/functions/tabularApi.ts +1 -1
  67. package/src/main.ts +10 -11
  68. package/src/types/badges.ts +3 -3
  69. package/src/types/contact_point.ts +5 -5
  70. package/src/types/dataservices.ts +16 -2
  71. package/src/types/datasets.ts +20 -2
  72. package/src/types/frequency.ts +5 -5
  73. package/src/types/granularity.ts +12 -4
  74. package/src/types/harvest.ts +2 -2
  75. package/src/types/licenses.ts +8 -8
  76. package/src/types/organizations.ts +6 -0
  77. package/src/types/resources.ts +3 -3
  78. package/src/types/reuses.ts +3 -1
  79. package/src/types/site.ts +8 -0
  80. package/src/types/ui.ts +2 -2
  81. package/src/types/users.ts +24 -8
  82. package/src/types/vue3-xml-viewer.d.ts +10 -0
  83. package/dist/Swagger-DjysB-OI.js +0 -67851
  84. package/dist/en-DCRve7vN.js +0 -613
  85. package/dist/fr-DCOnbL-p.js +0 -613
  86. package/dist/locales/de.js +0 -155
  87. package/dist/locales/en.js +0 -155
  88. package/dist/locales/es.js +0 -155
  89. package/dist/locales/fr.js +0 -155
  90. package/dist/locales/it.js +0 -155
  91. package/dist/locales/pt.js +0 -155
  92. package/dist/locales/sr.js +0 -155
  93. package/dist/main-CPW2vNLE.js +0 -32008
  94. package/src/components/DescriptionList/DescriptionDetails.stories.ts +0 -43
  95. package/src/components/DescriptionList/DescriptionList.stories.ts +0 -47
  96. package/src/components/DescriptionList/DescriptionTerm.stories.ts +0 -28
  97. package/src/locales/de.json +0 -154
  98. package/src/locales/en.json +0 -154
  99. package/src/locales/es.json +0 -154
  100. package/src/locales/fr.json +0 -154
  101. package/src/locales/it.json +0 -154
  102. package/src/locales/pt.json +0 -154
  103. package/src/locales/sr.json +0 -154
@@ -0,0 +1,166 @@
1
+ <template>
2
+ <div>
3
+ <SimpleBanner
4
+ v-if="hasError"
5
+ type="warning"
6
+ class="flex items-center space-x-2"
7
+ >
8
+ <RiErrorWarningLine class="shink-0 size-6" />
9
+ <span>{{ t("L'aperçu cartographique de ce fichier n'a pas pu être chargé.") }}</span>
10
+ </SimpleBanner>
11
+ <div
12
+ v-else
13
+ class="-mx-4"
14
+ >
15
+ <div
16
+ v-if="pmtilesViewerUrl"
17
+ class="bg-blue-100 text-datagouv fr-hidden fr-unhidden-md p-4"
18
+ >
19
+ <div class="fr-grid-row fr-grid-row--middle fr-grid-row--gutters">
20
+ <div
21
+ class="fr-col-auto"
22
+ v-html="franceSvg"
23
+ />
24
+ <div class="fr-col">
25
+ <p class="fr-text--bold fr-m-0">
26
+ {{ t("Explorer les données en détail") }}
27
+ </p>
28
+ <p class="fr-text--sm fr-m-0 f-italic">
29
+ {{ t("Utiliser un visualisateur PMTiles pour obtenir un aperçu des données.") }}
30
+ </p>
31
+ </div>
32
+ <p class="fr-col-auto fr-my-0">
33
+ <BrandedButton
34
+ :href="pmtilesViewerUrl"
35
+ :icon="RiExternalLinkFill"
36
+ icon-right
37
+ >
38
+ {{ t("Explorer la carte") }}
39
+ </BrandedButton>
40
+ </p>
41
+ </div>
42
+ </div>
43
+ <div
44
+ ref="containerRef"
45
+ style="height: 600px;"
46
+ />
47
+ <div class="fr-px-5v fr-pt-5v">
48
+ {{ t("Aperçu de la carte mis à jour le {date}", { date: lastUpdate }) }}
49
+ </div>
50
+ </div>
51
+ </div>
52
+ </template>
53
+
54
+ <script setup lang="ts">
55
+ import { computed, onMounted, ref } from 'vue'
56
+ import { useI18n } from 'vue-i18n'
57
+ import { RiErrorWarningLine, RiExternalLinkFill } from '@remixicon/vue'
58
+ import { Protocol, PMTiles } from 'pmtiles'
59
+ import maplibregl from 'maplibre-gl'
60
+ import DOMPurify from 'dompurify'
61
+ import { useComponentsConfig } from '../../config'
62
+ import { useFormatDate } from '../../functions/dates'
63
+ import type { Resource } from '../../types/resources'
64
+ import BrandedButton from '../BrandedButton.vue'
65
+ import styleVector from '../../../assets/json/vector.json'
66
+ import SimpleBanner from '../SimpleBanner.vue'
67
+ import franceSvg from './france.svg?raw'
68
+
69
+ const props = defineProps<{ resource: Resource }>()
70
+
71
+ const { t } = useI18n()
72
+ const { formatDate } = useFormatDate()
73
+
74
+ const config = useComponentsConfig()
75
+
76
+ const hasError = ref(false)
77
+ const pmtilesUrl = computed(() => props.resource.extras['analysis:parsing:pmtiles_url'])
78
+ const pmtilesViewerUrl = computed(() => {
79
+ return config.pmtilesViewerBaseUrl ? `${config.pmtilesViewerBaseUrl}${encodeURIComponent(pmtilesUrl.value)}` : null
80
+ })
81
+
82
+ const lastUpdate = computed(() => formatDate(props.resource.extras['analysis:parsing:finished_at']))
83
+
84
+ const container = useTemplateRef('containerRef')
85
+
86
+ async function displayMap() {
87
+ await import('maplibre-gl/dist/maplibre-gl.css')
88
+
89
+ const protocol = new Protocol()
90
+ maplibregl.addProtocol('pmtiles', protocol.tile)
91
+
92
+ const p = new PMTiles(pmtilesUrl.value)
93
+ protocol.add(p)
94
+
95
+ p.getHeader().then((h) => {
96
+ const map = new maplibregl.Map({
97
+ container: container.value, // container id
98
+ style: styleVector,
99
+ zoom: h.maxZoom - 2,
100
+ center: [h.centerLon, h.centerLat],
101
+ })
102
+ map.addControl(new maplibregl.NavigationControl())
103
+
104
+ const popup = new maplibregl.Popup({
105
+ closeButton: false,
106
+ closeOnClick: false,
107
+ })
108
+
109
+ function showMapPopup(e) {
110
+ if (!e.features || !e.features[0])
111
+ popup.remove()
112
+ else {
113
+ const coordinates = e.lngLat
114
+ const description = Object.keys(e.features[0].properties).map((element) => {
115
+ return `<b>${DOMPurify.sanitize(element)} :</b> ${DOMPurify.sanitize(e.features[0].properties[element])}`
116
+ }).join('<br>')
117
+ popup.setLngLat(coordinates).setHTML(description).addTo(map)
118
+ }
119
+ }
120
+
121
+ map.on('load', () => {
122
+ p.getMetadata().then((metadata) => {
123
+ map.addSource('pmtiles_source', {
124
+ type: 'vector',
125
+ url: `pmtiles://${pmtilesUrl.value}`,
126
+ attribution: '© <a href="https://openstreetmap.org">OpenStreetMap</a>',
127
+ })
128
+
129
+ metadata.tilestats.layers.forEach((layer) => {
130
+ const typeLayer = computed(() => {
131
+ switch (layer.geometry) {
132
+ case 'Polygon':
133
+ return 'fill'
134
+ case 'Point':
135
+ return `circle`
136
+ case 'LineString':
137
+ return `line`
138
+ default:
139
+ throwOnNever(layer.geometry, 'Unsupported geometry')
140
+ return ''
141
+ }
142
+ })
143
+ map.addLayer({
144
+ 'id': layer.layer,
145
+ 'source': 'pmtiles_source',
146
+ 'source-layer': layer.layer,
147
+ 'type': typeLayer.value,
148
+ 'paint': {
149
+ [`${typeLayer.value}-color`]: 'steelblue',
150
+ [`${typeLayer.value}-opacity`]: { base: 1, stops: [[0, 0.9], [10, 0.6]] },
151
+ },
152
+ })
153
+ map.on('mousemove', layer.layer, showMapPopup)
154
+ map.on('touchmove', layer.layer, showMapPopup)
155
+ map.on('click', layer.layer, showMapPopup)
156
+ map.on('mouseleave', layer.layer, showMapPopup)
157
+ })
158
+ }).catch (() => hasError.value = true)
159
+ })
160
+ }).catch (() => hasError.value = true)
161
+ }
162
+
163
+ onMounted(() => {
164
+ displayMap()
165
+ })
166
+ </script>
@@ -1,19 +1,18 @@
1
1
  <template>
2
2
  <div>
3
- <div
3
+ <SimpleBanner
4
4
  v-if="hasError"
5
- class="bg-warning-lightest text-warning-dark p-3 mt-8 mx-8 mb-3"
5
+ type="warning"
6
+ class="flex items-center space-x-2"
6
7
  >
7
- <p class="fr-grid-row fr-m-0">
8
- <span
9
- class="fr-icon-warning-line"
10
- aria-hidden="true"
11
- />
12
- {{ t("The preview of this file failed to load.") }}
13
- </p>
14
- </div>
8
+ <RiErrorWarningLine class="shink-0 size-6" />
9
+ <span>{{ t("L'aperçu de ce fichier n'a pas pu être chargé.") }}</span>
10
+ </SimpleBanner>
15
11
  <PreviewLoader v-else-if="loading" />
16
- <template v-else>
12
+ <div
13
+ v-else
14
+ class="-mx-4"
15
+ >
17
16
  <div class="bg-blue-100 text-datagouv fr-hidden fr-unhidden-md p-4">
18
17
  <div class="fr-grid-row fr-grid-row--middle fr-grid-row--gutters">
19
18
  <div
@@ -22,10 +21,10 @@
22
21
  />
23
22
  <div class="fr-col">
24
23
  <p class="fr-text--bold fr-m-0">
25
- {{ t("Explore data in detail") }}
24
+ {{ t("Explorer les données en détail") }}
26
25
  </p>
27
26
  <p class="fr-text--sm fr-m-0 f-italic">
28
- {{ t("Use our tool to get an overview of data, learn about different columns or perform filters and sorts.") }}
27
+ {{ t("Utiliser notre outil pour obtenir un aperçu des données, en savoir plus sur les différentes colonnes ou réaliser des filtres et des tris.") }}
29
28
  </p>
30
29
  </div>
31
30
  <p class="fr-col-auto fr-my-0">
@@ -34,15 +33,15 @@
34
33
  :icon="RiExternalLinkFill"
35
34
  icon-right
36
35
  >
37
- {{ t("Explore data") }}
36
+ {{ t("Explorer les données") }}
38
37
  </BrandedButton>
39
38
  </p>
40
39
  </div>
41
40
  </div>
42
- <div class="fr-table fr-table--no-background fr-p-0 fr-pt-0-5v fr-m-0">
41
+ <div class="fr-table fr-table--no-background fr-p-0 fr-m-0">
43
42
  <table class="fr-mb-3w">
44
- <caption class="fr-sr-only">
45
- {{ t('Preview of {name}', { name: resource.title }) }}
43
+ <caption class="sr-only">
44
+ {{ t('Prévisualisation de {name}', { name: resource.title }) }}
46
45
  </caption>
47
46
  <thead>
48
47
  <tr>
@@ -51,18 +50,19 @@
51
50
  :key="index"
52
51
  scope="col"
53
52
  >
54
- <div class="fr-grid-row fr-grid-row--middle col-width">
55
- <BrandedButton
56
- color="secondary-softer"
57
- :icon="isSortedBy(col) && sortConfig && sortConfig.type == 'asc' ? RiArrowUpLine : RiArrowDownLine"
58
- icon-right
59
- size="xs"
60
- @click="sortByField(col)"
61
- >
53
+ <BrandedButton
54
+ color="secondary-softer"
55
+ :icon="isSortedBy(col) && sortConfig && sortConfig.type == 'asc' ? RiArrowUpLine : RiArrowDownLine"
56
+ icon-right
57
+ size="xs"
58
+ @click="sortByField(col)"
59
+ >
60
+ <!-- There is a weird bug with `sr-only`, I needed to add a relative parent to avoid full page x scrolling into the void… -->
61
+ <span class="relative">
62
62
  {{ col }}
63
- <span class="sr-only">{{ sortConfig && sortConfig.type == 'desc' ? t("Sort ascending") : t("Sort descending") }}</span>
64
- </BrandedButton>
65
- </div>
63
+ <span class="sr-only">{{ sortConfig && sortConfig.type == 'desc' ? t("Trier par ordre croissant") : t("Trier par ordre décroissant") }}</span>
64
+ </span>
65
+ </BrandedButton>
66
66
  </th>
67
67
  </tr>
68
68
  </thead>
@@ -76,7 +76,7 @@
76
76
  :key="colIndex"
77
77
  class="cell-padding"
78
78
  >
79
- <div class="fr-grid-row fr-grid-row--middle fr-text--xs w-100 style-cell">
79
+ <div class="fr-grid-row fr-grid-row--middle fr-text--xs w-full style-cell">
80
80
  <div class="fr-my-auto">
81
81
  {{ row[col] }}
82
82
  </div>
@@ -94,30 +94,32 @@
94
94
  @change="changePage"
95
95
  />
96
96
  <div class="fr-px-5v">
97
- {{ t("Preview updated on {date}", { date: lastUpdate }) }} —
98
- {{ t('{count} columns', columns.length) }} —
99
- {{ t('{count} rows', rowCount) }}
97
+ {{ t("Dernière mise à jour de la prévisualisation : {date}", { date: lastUpdate }) }} —
98
+ {{ t('{count} colonnes', columns.length) }} —
99
+ {{ t('Lignes {count}', rowCount) }}
100
100
  </div>
101
- </template>
101
+ </div>
102
102
  </div>
103
103
  </template>
104
104
 
105
105
  <script setup lang="ts">
106
106
  import { computed, onMounted, ref } from 'vue'
107
107
  import { useI18n } from 'vue-i18n'
108
- import { RiArrowDownLine, RiArrowUpLine, RiExternalLinkFill } from '@remixicon/vue'
108
+ import { RiArrowDownLine, RiArrowUpLine, RiErrorWarningLine, RiExternalLinkFill } from '@remixicon/vue'
109
109
  import Pagination from '../Pagination.vue'
110
110
  import { getData, type SortConfig } from '../../functions/tabularApi'
111
- import { formatDate } from '../../functions/dates'
111
+ import { useFormatDate } from '../../functions/dates'
112
112
  import type { Resource } from '../../types/resources'
113
113
  import { useComponentsConfig } from '../../config'
114
114
  import BrandedButton from '../BrandedButton.vue'
115
+ import SimpleBanner from '../SimpleBanner.vue'
115
116
  import franceSvg from './france.svg?raw'
116
117
  import PreviewLoader from './PreviewLoader.vue'
117
118
 
118
119
  const props = defineProps<{ resource: Resource }>()
119
120
 
120
121
  const { t } = useI18n()
122
+ const { formatDate } = useFormatDate()
121
123
 
122
124
  const rows = ref<Array<Record<string, unknown>>>([])
123
125
  const columns = ref<Array<string>>([])
@@ -126,7 +128,7 @@ const hasError = ref(false)
126
128
  const sortConfig = ref<SortConfig>(null)
127
129
  const rowCount = ref(0)
128
130
  const config = useComponentsConfig()
129
- const pageSize = computed(() => config.tabularApiPageSize || 20)
131
+ const pageSize = computed(() => config.tabularApiPageSize || 15)
130
132
  const currentPage = ref(1)
131
133
 
132
134
  /**
@@ -197,7 +199,7 @@ function sortByField(col: string) {
197
199
  getTableInfos(currentPage.value, sortConfig.value)
198
200
  };
199
201
 
200
- const lastUpdate = formatDate(props.resource.extras['analysis:parsing:finished_at'])
202
+ const lastUpdate = computed(() => formatDate(props.resource.extras['analysis:parsing:finished_at']))
201
203
 
202
204
  onMounted(() => {
203
205
  getTableInfos(currentPage.value)