@datagouv/components-next 1.1.1 → 1.2.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 (54) hide show
  1. package/dist/{Control-DuZJdKV_.js → Control-ZFh5ta_U.js} +1 -1
  2. package/dist/{Datafair.client-BzW-ctDf.js → Datafair.client-rf4T1IkA.js} +1 -1
  3. package/dist/{Event--kp8kMdJ.js → Event-DSQcW7OF.js} +24 -24
  4. package/dist/{Image-34hvypZI.js → Image-BijNEG0p.js} +6 -6
  5. package/dist/{JsonPreview.client-BfMSzR07.js → JsonPreview.client-dzar6iuh.js} +2 -2
  6. package/dist/{Map-BjUnLyj8.js → Map-BUtPf5GN.js} +756 -756
  7. package/dist/{MapContainer.client-CLs-im9i.js → MapContainer.client-D-MoRNhG.js} +37 -38
  8. package/dist/{OSM-s40W6sQ2.js → OSM-D4MTdBtk.js} +2 -2
  9. package/dist/{PdfPreview.client-C13PQCU_.js → PdfPreview.client-DoDYLmJD.js} +2 -2
  10. package/dist/{Pmtiles.client-CL7PXXDl.js → Pmtiles.client-Dzm01Zfm.js} +1 -1
  11. package/dist/{PreviewWrapper.vue_vue_type_script_setup_true_lang-C6XnsZ-7.js → PreviewWrapper.vue_vue_type_script_setup_true_lang-BRNYswg3.js} +1 -1
  12. package/dist/{ScaleLine-KW-nXqp3.js → ScaleLine-hJQIqcZm.js} +2 -2
  13. package/dist/{Tile-DbNFNPfU.js → Tile-Dcl7oIVu.js} +35 -35
  14. package/dist/{TileImage-BsXBxMtq.js → TileImage-BJeHipMX.js} +4 -4
  15. package/dist/{View-BR92hTWP.js → View-xp_P_OHw.js} +412 -401
  16. package/dist/{XmlPreview.client-KaENrbbG.js → XmlPreview.client-cOhwff6P.js} +3 -3
  17. package/dist/{common-PJfpC179.js → common-BjQlan3k.js} +36 -36
  18. package/dist/components-next.css +4 -4
  19. package/dist/components-next.js +160 -155
  20. package/dist/components.css +1 -1
  21. package/dist/{index-C7WVVGgD.js → index-NofRBuyf.js} +32886 -27183
  22. package/dist/{main-K-42Oe8-.js → main-Iz1ZCL6k.js} +41753 -89461
  23. package/dist/{proj-DsetBcW7.js → proj-CsNo9yH1.js} +532 -512
  24. package/dist/{tilecoord-Db24Px13.js → tilecoord-A0fLnBZr.js} +28 -28
  25. package/dist/{vue3-xml-viewer.common-sHPSE-jD.js → vue3-xml-viewer.common-tVI9uXUz.js} +1 -1
  26. package/package.json +11 -4
  27. package/src/chart.ts +5 -0
  28. package/src/components/ActivityList/ActivityList.vue +3 -0
  29. package/src/components/DataserviceCard.vue +3 -0
  30. package/src/components/DatasetCard.vue +9 -4
  31. package/src/components/ObjectCardHeader.vue +11 -4
  32. package/src/components/RadioInput.vue +7 -2
  33. package/src/components/ResourceAccordion/DataStructure.vue +11 -33
  34. package/src/components/ResourceAccordion/Downloads.vue +160 -0
  35. package/src/components/ResourceAccordion/MapContainer.client.vue +1 -3
  36. package/src/components/ResourceAccordion/ResourceAccordion.vue +5 -102
  37. package/src/components/ResourceExplorer/ResourceExplorer.vue +2 -55
  38. package/src/components/ResourceExplorer/ResourceExplorerViewer.vue +26 -135
  39. package/src/components/ResourceExplorer/ResourceSelector.vue +113 -0
  40. package/src/components/ReuseCard.vue +12 -4
  41. package/src/components/Search/GlobalSearch.vue +30 -7
  42. package/src/components/Search/SearchInput.vue +2 -1
  43. package/src/components/TabularExplorer/TabularExplorer.vue +257 -154
  44. package/src/composables/useHasTabularData.ts +7 -0
  45. package/src/composables/useMetrics.ts +1 -1
  46. package/src/composables/useStableQueryParams.ts +7 -3
  47. package/src/composables/useTabularProfile.ts +70 -0
  48. package/src/config.ts +17 -3
  49. package/src/functions/activities.ts +3 -3
  50. package/src/functions/api.ts +5 -34
  51. package/src/functions/metrics.ts +6 -4
  52. package/src/main.ts +39 -6
  53. package/src/types/search.ts +11 -0
  54. package/src/types/ui.ts +2 -0
@@ -1,6 +1,6 @@
1
- import { T as _, W as nt, n as xt, c as H, b as et } from "./Image-34hvypZI.js";
2
- import { z as Tt, g as pt } from "./common-PJfpC179.js";
3
- import { aC as It, E as ft, al as Xt, U as dt, g as at, X as Wt, w as Mt, F as b, n as _t, L, an as gt, aS as vt, x as Yt, r as Lt, aT as Ft, ak as wt, aI as yt, az as Dt, aJ as Ot, aU as st, ae as ot, i as Ct, W as z, a1 as $, d as V, l as Pt, u as rt, a7 as ht, I as At, a as Rt } from "./proj-DsetBcW7.js";
1
+ import { T as _, W as nt, n as xt, c as H, b as et } from "./Image-BijNEG0p.js";
2
+ import { z as Tt, g as pt } from "./common-BjQlan3k.js";
3
+ import { aD as It, E as ft, al as Xt, U as dt, g as at, X as Wt, w as Mt, F as b, n as _t, L, an as gt, aU as vt, x as Yt, r as Lt, aV as Ft, ak as wt, aJ as yt, aA as Dt, aK as Ot, aW as st, ae as ot, i as Ct, W as z, a1 as $, d as V, l as Pt, u as rt, a7 as ht, I as At, a as Rt } from "./proj-CsNo9yH1.js";
4
4
  class mt extends It {
5
5
  /**
6
6
  * @param {import("./tilecoord.js").TileCoord} tileCoord Tile coordinate.
@@ -339,7 +339,7 @@ function ut(a, t, e, s) {
339
339
  }
340
340
  return i;
341
341
  }
342
- function Nt(a, t, e, s) {
342
+ function Kt(a, t, e, s) {
343
343
  const n = Yt(e);
344
344
  let i = ut(
345
345
  a,
@@ -356,7 +356,7 @@ function Nt(a, t, e, s) {
356
356
  ), isFinite(i) && i > 0;
357
357
  }), i;
358
358
  }
359
- function St(a, t, e, s, n, i, c, m, g, T, X, x, F, w) {
359
+ function Nt(a, t, e, s, n, i, c, m, g, T, X, x, F, w) {
360
360
  const r = H(
361
361
  Math.round(e * a),
362
362
  Math.round(e * t),
@@ -409,7 +409,7 @@ function St(a, t, e, s, n, i, c, m, g, T, X, x, F, w) {
409
409
  return m.getTriangles().forEach(function(o, y, C) {
410
410
  const p = o.source, I = o.target;
411
411
  let v = p[0][0], Y = p[0][1], W = p[1][0], M = p[1][1], D = p[2][0], A = p[2][1];
412
- const G = h((I[0][0] - u[0]) / i), N = h(
412
+ const G = h((I[0][0] - u[0]) / i), K = h(
413
413
  -(I[0][1] - u[1]) / i
414
414
  ), R = h((I[1][0] - u[0]) / i), k = h(
415
415
  -(I[1][1] - u[1]) / i
@@ -420,32 +420,32 @@ function St(a, t, e, s, n, i, c, m, g, T, X, x, F, w) {
420
420
  const Et = [
421
421
  [W, M, 0, 0, R - G],
422
422
  [D, A, 0, 0, U - G],
423
- [0, 0, W, M, k - N],
424
- [0, 0, D, A, Q - N]
425
- ], S = vt(Et);
426
- if (!S)
423
+ [0, 0, W, M, k - K],
424
+ [0, 0, D, A, Q - K]
425
+ ], N = vt(Et);
426
+ if (!N)
427
427
  return;
428
428
  if (r.save(), r.beginPath(), Gt() || !x) {
429
429
  r.moveTo(R, k);
430
- const O = 4, K = G - R, it = N - k;
430
+ const O = 4, S = G - R, it = K - k;
431
431
  for (let P = 0; P < O; P++)
432
432
  r.lineTo(
433
- R + h((P + 1) * K / O),
433
+ R + h((P + 1) * S / O),
434
434
  k + h(P * it / (O - 1))
435
435
  ), P != O - 1 && r.lineTo(
436
- R + h((P + 1) * K / O),
436
+ R + h((P + 1) * S / O),
437
437
  k + h((P + 1) * it / (O - 1))
438
438
  );
439
439
  r.lineTo(U, Q);
440
440
  } else
441
- r.moveTo(R, k), r.lineTo(G, N), r.lineTo(U, Q);
441
+ r.moveTo(R, k), r.lineTo(G, K), r.lineTo(U, Q);
442
442
  r.clip(), r.transform(
443
- S[0],
444
- S[2],
445
- S[1],
446
- S[3],
443
+ N[0],
444
+ N[2],
445
+ N[1],
446
+ N[3],
447
447
  G,
448
- N
448
+ K
449
449
  ), r.translate(
450
450
  E[0] - j,
451
451
  E[3] - q
@@ -454,10 +454,10 @@ function St(a, t, e, s, n, i, c, m, g, T, X, x, F, w) {
454
454
  if (l)
455
455
  Z = l.canvas, r.scale(d, -d);
456
456
  else {
457
- const O = g[0], K = O.extent;
457
+ const O = g[0], S = O.extent;
458
458
  Z = O.image, r.scale(
459
- L(K) / Z.width,
460
- -b(K) / Z.height
459
+ L(S) / Z.width,
460
+ -b(S) / Z.height
461
461
  );
462
462
  }
463
463
  r.drawImage(Z, 0, 0), r.restore();
@@ -467,7 +467,7 @@ function St(a, t, e, s, n, i, c, m, g, T, X, x, F, w) {
467
467
  }), r.restore()), r.canvas;
468
468
  }
469
469
  const Zt = 10, lt = 0.25;
470
- class Kt {
470
+ class St {
471
471
  /**
472
472
  * @param {import("../proj/Projection.js").default} sourceProj Source projection.
473
473
  * @param {import("../proj/Projection.js").default} targetProj Target projection.
@@ -715,7 +715,7 @@ class Vt extends mt {
715
715
  l && (h ? h = V(h, l) : h = l);
716
716
  const f = n.getResolution(
717
717
  this.wrappedTileCoord_[0]
718
- ), d = Nt(
718
+ ), d = Kt(
719
719
  t,
720
720
  s,
721
721
  E,
@@ -726,7 +726,7 @@ class Vt extends mt {
726
726
  return;
727
727
  }
728
728
  const u = X !== void 0 ? X : bt;
729
- if (this.triangulation_ = new Kt(
729
+ if (this.triangulation_ = new St(
730
730
  t,
731
731
  s,
732
732
  E,
@@ -806,7 +806,7 @@ class Vt extends mt {
806
806
  ), g = this.targetTileGrid_.getTileCoordExtent(
807
807
  this.wrappedTileCoord_
808
808
  );
809
- this.canvas_ = St(
809
+ this.canvas_ = Nt(
810
810
  n,
811
811
  i,
812
812
  this.pixelRatio_,
@@ -890,13 +890,13 @@ export {
890
890
  zt as I,
891
891
  Vt as R,
892
892
  mt as T,
893
- Kt as a,
893
+ St as a,
894
894
  Bt as b,
895
895
  ut as c,
896
896
  Jt as d,
897
897
  $t as e,
898
898
  ts as g,
899
899
  ss as h,
900
- St as r,
900
+ Nt as r,
901
901
  es as w
902
902
  };
@@ -1,4 +1,4 @@
1
- import { c as Ke } from "./main-K-42Oe8-.js";
1
+ import { c as Ke } from "./main-Iz1ZCL6k.js";
2
2
  import We from "vue";
3
3
  function Fe(I, K) {
4
4
  for (var V = 0; V < K.length; V++) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datagouv/components-next",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "engines": {
@@ -10,6 +10,12 @@
10
10
  "yarn": "use-pnpm-instead"
11
11
  },
12
12
  "main": "./src/main.ts",
13
+ "exports": {
14
+ ".": "./src/main.ts",
15
+ "./chart": "./src/chart.ts",
16
+ "./assets/*": "./assets/*",
17
+ "./dist/*": "./dist/*"
18
+ },
13
19
  "sideEffects": false,
14
20
  "files": [
15
21
  "assets",
@@ -26,8 +32,7 @@
26
32
  "@vueuse/router": "^14.2.1",
27
33
  "chart.js": "^4.4.8",
28
34
  "dompurify": "^3.2.5",
29
- "echarts": "^6.0.0",
30
- "geopf-extensions-openlayers": "^1.0.0-beta.5",
35
+ "geopf-extensions-openlayers": "^1.0.0-beta.10",
31
36
  "leaflet": "^1.9.4",
32
37
  "maplibre-gl": "^5.6.2",
33
38
  "ofetch": "^1.4.1",
@@ -67,6 +72,7 @@
67
72
  "@vue/eslint-config-prettier": "^10.2.0",
68
73
  "@vue/eslint-config-typescript": "^14.3.0",
69
74
  "@vue/tsconfig": "^0.8.0",
75
+ "echarts": "^6.0.0",
70
76
  "eslint": "^9.18.0",
71
77
  "eslint-plugin-vue": "^10.0",
72
78
  "jiti": "^2.4.2",
@@ -83,7 +89,8 @@
83
89
  },
84
90
  "peerDependencies": {
85
91
  "vue": "^3.5.13",
86
- "vue-router": "^4.5.0 || ^5.0.0"
92
+ "vue-router": "^4.5.0 || ^5.0.0",
93
+ "echarts": "^6.0.0"
87
94
  },
88
95
  "scarfSettings": {
89
96
  "enabled": false
package/src/chart.ts ADDED
@@ -0,0 +1,5 @@
1
+ import ChartViewer from './components/Chart/ChartViewer.vue'
2
+ import ChartViewerWrapper from './components/Chart/ChartViewerWrapper.vue'
3
+ import SmallChart from './components/SmallChart.vue'
4
+
5
+ export { ChartViewer, ChartViewerWrapper, SmallChart }
@@ -77,6 +77,9 @@
77
77
  v-bind="{ class: '', activity }"
78
78
  >
79
79
  {{ getActivityTranslation(activity) }}
80
+ <template v-if="'resource_id' in activity.extras">
81
+ {{ activity.extras.resource_id }}
82
+ </template>
80
83
  </slot>
81
84
  </p>
82
85
  <p class="m-0 flex-none text-xs text-gray-medium">
@@ -53,6 +53,7 @@
53
53
  <ObjectCardHeader
54
54
  :icon="isTabularApi ? RiSparklingLine : RiTerminalLine"
55
55
  :url="dataserviceUrl || dataservice.self_web_url"
56
+ :title-tag="titleTag"
56
57
  >
57
58
  {{ dataservice.title }}
58
59
  </ObjectCardHeader>
@@ -115,6 +116,7 @@ import { useComponentsConfig } from '../config'
115
116
  import { useFormatDate } from '../functions/dates'
116
117
  import { summarize } from '../functions/helpers'
117
118
  import type { Dataservice } from '../types/dataservices'
119
+ import type { TitleTag } from '../types/ui'
118
120
  import { useTranslation } from '../composables/useTranslation'
119
121
  import OrganizationLogo from './OrganizationLogo.vue'
120
122
  import Avatar from './Avatar.vue'
@@ -130,6 +132,7 @@ type Props = {
130
132
  dataserviceUrl?: RouteLocationRaw
131
133
  organizationUrl?: RouteLocationRaw
132
134
  showDescription?: boolean
135
+ titleTag?: TitleTag
133
136
  }
134
137
 
135
138
  const props = withDefaults(defineProps<Props>(), {
@@ -36,6 +36,7 @@
36
36
  :icon="RiDatabase2Line"
37
37
  :url="datasetUrl || dataset.page"
38
38
  :target="datasetUrlInNewTab ? '_blank' : undefined"
39
+ :title-tag="titleTag"
39
40
  >
40
41
  {{ dataset.title }}
41
42
  <template
@@ -106,10 +107,12 @@
106
107
  </p>
107
108
  </div>
108
109
  </div>
109
- <ObjectCardShortDescription
110
- v-if="showDescriptionShort"
111
- :text="getDescriptionShort(props.dataset)"
112
- />
110
+ <slot>
111
+ <ObjectCardShortDescription
112
+ v-if="showDescriptionShort"
113
+ :text="getDescriptionShort(props.dataset)"
114
+ />
115
+ </slot>
113
116
  </ObjectCard>
114
117
  </template>
115
118
 
@@ -117,6 +120,7 @@
117
120
  import type { RouteLocationRaw } from 'vue-router'
118
121
  import { RiArchiveLine, RiDatabase2Line, RiDownloadLine, RiEyeLine, RiLineChartLine, RiLockLine, RiStarLine, RiSubtractLine } from '@remixicon/vue'
119
122
  import type { Dataset, DatasetV2 } from '../types/datasets'
123
+ import type { TitleTag } from '../types/ui'
120
124
  import { summarize } from '../functions/helpers'
121
125
  import { useFormatDate } from '../functions/dates'
122
126
  import { getDescriptionShort } from '../functions/description'
@@ -137,6 +141,7 @@ type Props = {
137
141
  datasetUrlInNewTab?: boolean
138
142
  organizationUrl?: RouteLocationRaw
139
143
  showDescriptionShort?: boolean
144
+ titleTag?: TitleTag
140
145
  }
141
146
 
142
147
  const props = withDefaults(defineProps<Props>(), {
@@ -1,5 +1,8 @@
1
1
  <template>
2
- <h3 class="w-full text-base flex">
2
+ <component
3
+ :is="titleTag"
4
+ class="w-full text-base font-bold flex"
5
+ >
3
6
  <AppLink
4
7
  :to="url"
5
8
  class="text-gray-title text-base bg-none flex items-center w-full truncate gap-1"
@@ -19,17 +22,21 @@
19
22
  <slot name="extra" />
20
23
  <span class="absolute inset-0" />
21
24
  </AppLink>
22
- </h3>
25
+ </component>
23
26
  </template>
24
27
 
25
28
  <script setup lang="ts">
26
29
  import type { Component } from 'vue'
27
30
  import type { RouteLocationRaw } from 'vue-router'
31
+ import type { TitleTag } from '../types/ui'
28
32
  import AppLink from './AppLink.vue'
29
33
 
30
- defineProps<{
34
+ withDefaults(defineProps<{
31
35
  icon: Component
32
36
  url: RouteLocationRaw
33
37
  target?: string
34
- }>()
38
+ titleTag?: TitleTag
39
+ }>(), {
40
+ titleTag: 'h3',
41
+ })
35
42
  </script>
@@ -13,9 +13,14 @@
13
13
  >
14
14
  <component
15
15
  :is="icon"
16
- v-if="icon"
16
+ v-if="icon && typeof icon !== 'string'"
17
17
  class="w-4 h-4"
18
18
  />
19
+ <span
20
+ v-else-if="icon"
21
+ :class="icon"
22
+ aria-hidden="true"
23
+ />
19
24
  <span class="text-sm flex-1 min-w-0">
20
25
  <slot />
21
26
  </span>
@@ -40,7 +45,7 @@ type Props = {
40
45
  value: string
41
46
  count?: number
42
47
  loading?: boolean
43
- icon?: Component
48
+ icon?: Component | string
44
49
  highlighted?: boolean
45
50
  }
46
51
 
@@ -49,45 +49,23 @@
49
49
  </template>
50
50
 
51
51
  <script setup lang="ts">
52
- import { onMounted, ref } from 'vue'
52
+ import { computed } from 'vue'
53
53
  import type { Resource } from '../../types/resources'
54
- import { useGetProfile } from '../../functions/tabularApi'
55
54
  import { useTranslation } from '../../composables/useTranslation'
55
+ import { injectTabularProfile } from '../../composables/useTabularProfile'
56
56
  import PreviewLoader from './PreviewLoader.vue'
57
57
 
58
58
  const props = defineProps<{ resource: Resource }>()
59
- const getProfile = useGetProfile()
60
59
  const { t } = useTranslation()
61
60
 
62
- type ColumnInfo = {
63
- score: number
64
- format: string
65
- python_type: string
66
- }
61
+ // Profile is shared with sibling components (e.g. TabularExplorer) via
62
+ // `provideTabularProfile` in the parent. Falls back to a local fetch
63
+ // when no parent provides it (standalone usage).
64
+ const { data: profileData, status } = await injectTabularProfile(() => props.resource.id)
67
65
 
68
- const columns = ref<Array<string>>([])
69
- const columnsInfo = ref<Record<string, ColumnInfo>>({})
70
- const loading = ref(true)
71
- const hasError = ref(false)
72
- const hasColumnInfo = ref(false)
73
-
74
- onMounted(async () => {
75
- try {
76
- const response = await getProfile(props.resource.id) // Assurez-vous que cette fonction retourne bien les données attendues
77
- if ('profile' in response && response.profile) {
78
- columns.value = Object.keys(response.profile.columns)
79
- columnsInfo.value = response.profile.columns
80
- hasColumnInfo.value = true
81
- loading.value = false
82
- }
83
- else {
84
- hasError.value = true
85
- loading.value = false
86
- }
87
- }
88
- catch {
89
- hasError.value = true
90
- loading.value = false
91
- }
92
- })
66
+ const loading = computed(() => status.value === 'idle' || status.value === 'pending')
67
+ const hasError = computed(() => status.value === 'error')
68
+ const hasColumnInfo = computed(() => !!profileData.value?.profile?.columns)
69
+ const columns = computed(() => profileData.value?.profile ? Object.keys(profileData.value.profile.columns) : [])
70
+ const columnsInfo = computed(() => profileData.value?.profile?.columns ?? {})
93
71
  </script>
@@ -0,0 +1,160 @@
1
+ <template>
2
+ <dl class="fr-pl-0">
3
+ <dt
4
+ v-if="resource.format === 'url'"
5
+ class="font-bold fr-text--sm fr-mb-0"
6
+ >
7
+ {{ t("URL d'origine") }}
8
+ </dt>
9
+ <dt
10
+ v-else
11
+ class="font-bold fr-text--sm fr-mb-0"
12
+ >
13
+ {{ t('Format original') }}
14
+ </dt>
15
+ <dd class="text-sm pl-0 mb-4 text-gray-medium h-8 flex flex-wrap items-center">
16
+ <span
17
+ v-if="resource.format === 'url'"
18
+ class="inline-flex items-center max-w-full"
19
+ >
20
+ <a
21
+ :href="resource.latest"
22
+ class="fr-link no-icon-after truncate"
23
+ rel="ugc nofollow noopener"
24
+ target="_blank"
25
+ @click="trackEvent('Jeux de données', 'Télécharger un fichier', 'Bouton : télécharger un fichier')"
26
+ >
27
+ {{ resource.url }}
28
+ </a>
29
+ <span class="fr-ml-1v fr-icon-external-link-line fr-icon--sm shrink-0" />
30
+ </span>
31
+ <span v-else>
32
+ <span class="text-datagouv fr-icon-download-line fr-icon--sm fr-mr-1v fr-mt-1v" />
33
+ <a
34
+ :href="resource.latest"
35
+ class="fr-link"
36
+ rel="ugc nofollow noopener"
37
+ @click="trackEvent('Jeux de données', 'Télécharger un fichier', `Bouton : format ${resource.format}`)"
38
+ >
39
+ <span>{{ t('Format {format}', { format: resource.format }) }}<span v-if="resourceFilesize"> - {{ filesize(resourceFilesize) }}</span></span>
40
+ </a>
41
+ </span>
42
+ <CopyButton
43
+ :label="t('Copier le lien')"
44
+ :copied-label="t('Lien copié !')"
45
+ :text="resource.latest"
46
+ class="relative"
47
+ />
48
+ </dd>
49
+ <template v-if="generatedFormats.length">
50
+ <dt class="font-bold fr-text--sm fr-mb-0">
51
+ {{ t('Formats générés automatiquement par {platform} (dernière mise à jour {date})', { platform: config.name, date: conversionsLastUpdate }) }}
52
+ </dt>
53
+ <dd
54
+ v-for="generatedFormat in generatedFormats"
55
+ :key="generatedFormat.format"
56
+ class="text-sm pl-0 mb-4 text-gray-medium h-8 flex flex-wrap items-center"
57
+ >
58
+ <span>
59
+ <span class="text-datagouv fr-icon-download-line fr-icon--sm fr-mr-1v fr-mt-1v" />
60
+ <a
61
+ :href="generatedFormat.url"
62
+ class="fr-link"
63
+ rel="ugc nofollow noopener"
64
+ @click="trackEvent('Jeux de données', 'Télécharger un fichier', `Bouton : format ${generatedFormat.format}`)"
65
+ >
66
+ <span>{{ t('Format {format}', { format: generatedFormat.format }) }}<span v-if="generatedFormat.size"> - {{ filesize(generatedFormat.size) }}</span></span>
67
+ </a>
68
+ </span>
69
+ <CopyButton
70
+ :label="t('Copier le lien')"
71
+ :copied-label="t('Lien copié !')"
72
+ :text="generatedFormat.url"
73
+ class="relative"
74
+ />
75
+ </dd>
76
+ </template>
77
+ <template v-if="wfsFormats.length">
78
+ <dt class="font-bold fr-text--sm fr-mb-0">
79
+ <div class="flex gap-1 items-center">
80
+ {{ t('Formats exportés depuis le service WFS') }}
81
+ <span v-if="defaultWfsProjection"> ({{ t('projection {crs}', { crs: defaultWfsProjection }) }})</span>
82
+ <Tooltip>
83
+ <RiInformationLine
84
+ class="flex-none size-4"
85
+ :aria-label="t(`Le lien de téléchargement interroge directement le flux WFS distant. Le nombre de features téléchargées peut être limité.`)"
86
+ aria-hidden="true"
87
+ />
88
+ <template #tooltip>
89
+ <p class="text-sm font-normal mb-0">
90
+ {{ t(`Le lien de téléchargement interroge directement le flux WFS distant.`) }}
91
+ </p>
92
+ <p class="text-sm font-normal mb-0">
93
+ {{ t(`Le nombre de features téléchargées peut être limité.`) }}
94
+ </p>
95
+ </template>
96
+ </Tooltip>
97
+ </div>
98
+ </dt>
99
+ <dd
100
+ v-for="wfsFormat in wfsFormats"
101
+ :key="wfsFormat.format"
102
+ class="text-sm pl-0 mb-4 text-gray-medium h-8 flex flex-wrap items-center"
103
+ >
104
+ <span>
105
+ <span class="text-datagouv fr-icon-download-line fr-icon--sm fr-mr-1v fr-mt-1v" />
106
+ <a
107
+ :href="wfsFormat.url"
108
+ class="fr-link"
109
+ rel="ugc nofollow noopener"
110
+ @click="trackEvent('Jeux de données', 'Télécharger un fichier', `Bouton : format ${wfsFormat.format}`)"
111
+ >
112
+ <span>{{ t('Format {format}', { format: wfsFormat.format }) }}</span>
113
+ </a>
114
+ </span>
115
+ <CopyButton
116
+ :label="t('Copier le lien')"
117
+ :copied-label="t('Lien copié !')"
118
+ :text="wfsFormat.url"
119
+ class="relative"
120
+ />
121
+ </dd>
122
+ </template>
123
+ </dl>
124
+ </template>
125
+
126
+ <script setup lang="ts">
127
+ import { computed } from 'vue'
128
+ import { RiInformationLine } from '@remixicon/vue'
129
+ import CopyButton from '../CopyButton.vue'
130
+ import Tooltip from '../Tooltip.vue'
131
+ import { filesize } from '../../functions/helpers'
132
+ import { getResourceFilesize } from '../../functions/resources'
133
+ import { trackEvent } from '../../functions/matomo'
134
+ import { useComponentsConfig } from '../../config'
135
+ import { useFormatDate } from '../../functions/dates'
136
+ import { useTranslation } from '../../composables/useTranslation'
137
+ import { useResourceCapabilities } from '../../composables/useResourceCapabilities'
138
+ import type { Resource } from '../../types/resources'
139
+ import type { Dataset, DatasetV2 } from '../../types/datasets'
140
+
141
+ const props = defineProps<{
142
+ resource: Resource
143
+ dataset: Dataset | DatasetV2
144
+ }>()
145
+
146
+ const { t } = useTranslation()
147
+ const config = useComponentsConfig()
148
+ const { formatRelativeIfRecentDate } = useFormatDate()
149
+
150
+ const { generatedFormats, wfsFormats, defaultWfsProjection } = useResourceCapabilities(
151
+ () => props.resource,
152
+ () => props.dataset,
153
+ )
154
+
155
+ const resourceFilesize = computed(() => getResourceFilesize(props.resource))
156
+
157
+ const conversionsLastUpdate = computed(() =>
158
+ formatRelativeIfRecentDate(props.resource.extras['analysis:parsing:finished_at'] as string | undefined),
159
+ )
160
+ </script>
@@ -89,10 +89,8 @@ async function displayMap() {
89
89
 
90
90
  const attributions = new GeoportalAttribution({
91
91
  position: 'bottom-right',
92
- // collapsed option is ignored by the library, thus the override below
93
- // see https://github.com/IGNF/geopf-extensions-openlayers/issues/497
92
+ collapsed: false,
94
93
  })
95
- attributions.setCollapsed(false)
96
94
  map.addControl(attributions)
97
95
 
98
96
  const layerImport = new LayerImport({