@datagouv/components-next 0.2.0 → 1.0.1
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.
- package/README.md +1 -1
- package/assets/main.css +49 -22
- package/dist/Control-BNCDn-8E.js +148 -0
- package/dist/{Datafair.client-x39O4yfF.js → Datafair.client-B5lBpOl8.js} +2 -2
- package/dist/Event-BOgJUhNR.js +738 -0
- package/dist/Image-BN-4XkIn.js +247 -0
- package/dist/{JsonPreview.client-BMsC5JcY.js → JsonPreview.client-Doz1Z0BS.js} +23 -23
- package/dist/Map-BdT3i2C4.js +7609 -0
- package/dist/MapContainer.client-oiieO8H-.js +105 -0
- package/dist/OSM-CamriM9b.js +71 -0
- package/dist/PdfPreview.client-CdAhkDFJ.js +14513 -0
- package/dist/{Pmtiles.client-BaiIo4VZ.js → Pmtiles.client-B0v8tGJQ.js} +3 -3
- package/dist/ScaleLine-BiesrgOv.js +165 -0
- package/dist/Swagger.client-CsK65JnG.js +4 -0
- package/dist/Tile-DCuqwNOI.js +1206 -0
- package/dist/TileImage-CmZf8EdU.js +1067 -0
- package/dist/View-DcDc7N2K.js +2858 -0
- package/dist/{XmlPreview.client-CAdN0w_Y.js → XmlPreview.client-CrjHf74q.js} +17 -17
- package/dist/common-C4rDcQpp.js +243 -0
- package/dist/components-next.css +1 -1
- package/dist/components-next.js +158 -117
- package/dist/components.css +1 -1
- package/dist/{MapContainer.client-DeSo8EvG.js → index-Bbu9rOHt.js} +4975 -21416
- package/dist/leaflet-src-7m1mB8LI.js +6338 -0
- package/dist/{main-Dgri3TQL.js → main-CiH8ZmBI.js} +56973 -51462
- package/dist/proj-CKwYjU38.js +1569 -0
- package/dist/tilecoord-YW3qEH_j.js +884 -0
- package/dist/{vue3-xml-viewer.common-D6skc_Ai.js → vue3-xml-viewer.common-Bi_bsV6C.js} +1 -1
- package/package.json +6 -2
- package/src/components/ActivityList/ActivityList.vue +6 -2
- package/src/components/AppLink.vue +4 -1
- package/src/components/Avatar.vue +2 -2
- package/src/components/AvatarWithName.vue +8 -4
- package/src/components/BouncingDots.vue +21 -0
- package/src/components/BrandedButton.vue +2 -0
- package/src/components/CopyButton.vue +19 -7
- package/src/components/DataserviceCard.vue +85 -120
- package/src/components/DatasetCard.vue +110 -171
- package/src/components/DatasetInformation/DatasetEmbedSection.vue +43 -0
- package/src/components/DatasetInformation/DatasetInformationSection.vue +73 -0
- package/src/components/DatasetInformation/DatasetSchemaSection.vue +74 -0
- package/src/components/DatasetInformation/DatasetSpatialSection.vue +59 -0
- package/src/components/DatasetInformation/DatasetTemporalitySection.vue +45 -0
- package/src/components/DatasetInformation/index.ts +5 -0
- package/src/components/DatasetQuality.vue +23 -16
- package/src/components/DatasetQualityInline.vue +13 -17
- package/src/components/DatasetQualityScore.vue +12 -15
- package/src/components/DatasetQualityTooltipContent.vue +3 -3
- package/src/components/DescriptionList.vue +1 -4
- package/src/components/DescriptionListDetails.vue +5 -0
- package/src/components/DescriptionListTerm.vue +5 -0
- package/src/components/DiscussionMessageCard.vue +63 -0
- package/src/components/ExtraAccordion.vue +4 -4
- package/src/components/Form/BadgeSelect.vue +35 -0
- package/src/components/Form/FormatSelect.vue +28 -0
- package/src/components/Form/GeozoneSelect.vue +52 -0
- package/src/components/Form/GranularitySelect.vue +29 -0
- package/src/components/Form/LicenseSelect.vue +30 -0
- package/src/components/Form/OrganizationSelect.vue +62 -0
- package/src/components/Form/OrganizationTypeSelect.vue +34 -0
- package/src/components/Form/ReuseTopicSelect.vue +29 -0
- package/src/components/Form/SchemaSelect.vue +30 -0
- package/src/components/Form/SearchableSelect.vue +334 -0
- package/src/components/Form/SelectGroup.vue +132 -0
- package/src/components/Form/TagSelect.vue +38 -0
- package/src/components/LeafletMap.vue +31 -0
- package/src/components/LicenseBadge.vue +24 -0
- package/src/components/LoadingBlock.vue +23 -2
- package/src/components/MarkdownViewer.vue +3 -1
- package/src/components/ObjectCard.vue +42 -0
- package/src/components/ObjectCardBadge.vue +22 -0
- package/src/components/ObjectCardHeader.vue +35 -0
- package/src/components/ObjectCardOwner.vue +43 -0
- package/src/components/ObjectCardShortDescription.vue +28 -0
- package/src/components/OrganizationCard.vue +35 -20
- package/src/components/OrganizationHorizontalCard.vue +87 -0
- package/src/components/OrganizationLogo.vue +1 -1
- package/src/components/OrganizationNameWithCertificate.vue +12 -6
- package/src/components/OwnerTypeIcon.vue +1 -0
- package/src/components/Pagination.vue +1 -1
- package/src/components/Placeholder.vue +5 -2
- package/src/components/PostCard.vue +62 -0
- package/src/components/ProgressBar.vue +31 -0
- package/src/components/RadioGroup.vue +32 -0
- package/src/components/RadioInput.vue +64 -0
- package/src/components/ResourceAccordion/Datafair.client.vue +1 -1
- package/src/components/ResourceAccordion/EditButton.vue +2 -3
- package/src/components/ResourceAccordion/JsonPreview.client.vue +3 -3
- package/src/components/ResourceAccordion/MapContainer.client.vue +21 -17
- package/src/components/ResourceAccordion/Metadata.vue +11 -24
- package/src/components/ResourceAccordion/PdfPreview.client.vue +70 -74
- package/src/components/ResourceAccordion/Pmtiles.client.vue +2 -2
- package/src/components/ResourceAccordion/Preview.vue +2 -2
- package/src/components/ResourceAccordion/ResourceAccordion.vue +35 -28
- package/src/components/ResourceAccordion/ResourceIcon.vue +1 -0
- package/src/components/ResourceAccordion/SchemaBadge.vue +2 -2
- package/src/components/ResourceAccordion/XmlPreview.client.vue +3 -3
- package/src/components/ResourceExplorer/ResourceExplorer.vue +243 -0
- package/src/components/ResourceExplorer/ResourceExplorerSidebar.vue +116 -0
- package/src/components/ResourceExplorer/ResourceExplorerViewer.vue +410 -0
- package/src/components/ReuseCard.vue +8 -28
- package/src/components/ReuseHorizontalCard.vue +80 -0
- package/src/components/Search/BasicAndAdvancedFilters.vue +49 -0
- package/src/components/Search/Filter/AccessTypeFilter.vue +37 -0
- package/src/components/Search/Filter/DatasetBadgeFilter.vue +40 -0
- package/src/components/Search/Filter/FilterButtonGroup.vue +78 -0
- package/src/components/Search/Filter/FormatFamilyFilter.vue +39 -0
- package/src/components/Search/Filter/LastUpdateRangeFilter.vue +37 -0
- package/src/components/Search/Filter/ProducerTypeFilter.vue +49 -0
- package/src/components/Search/Filter/ReuseTypeFilter.vue +42 -0
- package/src/components/Search/GlobalSearch.vue +707 -0
- package/src/components/Search/SearchInput.vue +63 -0
- package/src/components/Search/Sidemenu.vue +38 -0
- package/src/components/StatBox.vue +5 -5
- package/src/components/Tag.vue +30 -0
- package/src/components/Toggletip.vue +11 -4
- package/src/components/Tooltip.vue +2 -3
- package/src/components/TopicCard.vue +134 -0
- package/src/components/radioGroupContext.ts +9 -0
- package/src/composables/useDebouncedRef.ts +31 -0
- package/src/composables/useHasTabularData.ts +15 -0
- package/src/composables/useMetrics.ts +4 -3
- package/src/composables/useResourceCapabilities.ts +131 -0
- package/src/composables/useRouteQueryBoolean.ts +10 -0
- package/src/composables/useSelectModelSync.ts +89 -0
- package/src/composables/useStableQueryParams.ts +84 -0
- package/src/composables/useTranslation.ts +2 -1
- package/src/config.ts +4 -0
- package/src/functions/api.ts +25 -6
- package/src/functions/api.types.ts +5 -3
- package/src/functions/datasets.ts +1 -29
- package/src/functions/description.ts +33 -0
- package/src/functions/helpers.ts +11 -0
- package/src/functions/markdown.ts +60 -16
- package/src/functions/metrics.ts +33 -0
- package/src/functions/organizations.ts +5 -5
- package/src/functions/resourceCapabilities.ts +55 -0
- package/src/main.ts +96 -7
- package/src/types/dataservices.ts +14 -12
- package/src/types/datasets.ts +20 -7
- package/src/types/discussions.ts +20 -0
- package/src/types/licenses.ts +3 -3
- package/src/types/organizations.ts +13 -1
- package/src/types/owned.ts +4 -2
- package/src/types/pages.ts +70 -0
- package/src/types/posts.ts +27 -0
- package/src/types/resources.ts +16 -0
- package/src/types/reuses.ts +14 -5
- package/src/types/search.ts +407 -0
- package/src/types/users.ts +12 -3
- package/dist/PdfPreview.client-COOkEkRA.js +0 -107
- package/dist/Swagger.client-CpLgaLg6.js +0 -4
- package/dist/pdf-vue3-IkJO65RH.js +0 -273
- package/dist/pdf.min-f72cfa08-CdgJTooZ.js +0 -9501
- package/src/components/DatasetInformationPanel.vue +0 -211
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
type="warning"
|
|
5
5
|
class="flex items-center space-x-2"
|
|
6
6
|
>
|
|
7
|
-
<RiErrorWarningLine class="
|
|
7
|
+
<RiErrorWarningLine class="shrink-0 size-6" />
|
|
8
8
|
<span>{{ t("L'aperçu cartographique de ce fichier n'a pas pu être chargé.") }}</span>
|
|
9
9
|
</SimpleBanner>
|
|
10
10
|
<div
|
|
@@ -18,22 +18,6 @@
|
|
|
18
18
|
import { onMounted, ref, useTemplateRef } from 'vue'
|
|
19
19
|
import { RiErrorWarningLine } from '@remixicon/vue'
|
|
20
20
|
|
|
21
|
-
import View from 'ol/View'
|
|
22
|
-
import Map from 'ol/Map'
|
|
23
|
-
import ScaleLine from 'ol/control/ScaleLine'
|
|
24
|
-
import TileLayer from 'ol/layer/Tile'
|
|
25
|
-
import OSM from 'ol/source/OSM'
|
|
26
|
-
|
|
27
|
-
import {
|
|
28
|
-
CRS,
|
|
29
|
-
GeoportalAttribution,
|
|
30
|
-
GeoportalFullScreen,
|
|
31
|
-
GeoportalZoom,
|
|
32
|
-
LayerImport,
|
|
33
|
-
LayerSwitcher,
|
|
34
|
-
// @ts-expect-error no types provided
|
|
35
|
-
} from 'geopf-extensions-openlayers'
|
|
36
|
-
|
|
37
21
|
import SimpleBanner from '../SimpleBanner.vue'
|
|
38
22
|
import type { Resource } from '../../types/resources'
|
|
39
23
|
import { useTranslation } from '../../composables/useTranslation'
|
|
@@ -47,6 +31,26 @@ const mapRef = useTemplateRef('mapRef')
|
|
|
47
31
|
const hasError = ref(false)
|
|
48
32
|
|
|
49
33
|
async function displayMap() {
|
|
34
|
+
// Dynamic imports for client-only libraries
|
|
35
|
+
const [
|
|
36
|
+
{ default: View },
|
|
37
|
+
{ default: Map },
|
|
38
|
+
{ default: ScaleLine },
|
|
39
|
+
{ default: TileLayer },
|
|
40
|
+
{ default: OSM },
|
|
41
|
+
geopf,
|
|
42
|
+
] = await Promise.all([
|
|
43
|
+
import('ol/View'),
|
|
44
|
+
import('ol/Map'),
|
|
45
|
+
import('ol/control/ScaleLine'),
|
|
46
|
+
import('ol/layer/Tile'),
|
|
47
|
+
import('ol/source/OSM'),
|
|
48
|
+
// @ts-expect-error no types provided
|
|
49
|
+
import('geopf-extensions-openlayers'),
|
|
50
|
+
])
|
|
51
|
+
|
|
52
|
+
const { CRS, GeoportalAttribution, GeoportalFullScreen, GeoportalZoom, LayerImport, LayerSwitcher } = geopf
|
|
53
|
+
|
|
50
54
|
await import('ol/ol.css')
|
|
51
55
|
await import('@gouvfr/dsfr/dist/dsfr.css')
|
|
52
56
|
await import('@gouvfr/dsfr/dist/utility/icons/icons.css')
|
|
@@ -3,7 +3,6 @@ import { computed } from 'vue'
|
|
|
3
3
|
import type { Resource } from '../../types/resources'
|
|
4
4
|
import CopyButton from '../CopyButton.vue'
|
|
5
5
|
import DescriptionDetails from '../DescriptionDetails.vue'
|
|
6
|
-
import DescriptionList from '../DescriptionList.vue'
|
|
7
6
|
import DescriptionTerm from '../DescriptionTerm.vue'
|
|
8
7
|
import { useFormatDate } from '../../functions/dates'
|
|
9
8
|
import { filesize } from '../../functions/helpers'
|
|
@@ -27,7 +26,7 @@ const { formatDate } = useFormatDate()
|
|
|
27
26
|
<template>
|
|
28
27
|
<div>
|
|
29
28
|
<div class="flex flex-wrap gap-12 flex-col md:flex-row overflow-hidden">
|
|
30
|
-
<
|
|
29
|
+
<dl class="flex-1 max-w-full p-0 m-0">
|
|
31
30
|
<DescriptionTerm>
|
|
32
31
|
{{ t('URL') }}
|
|
33
32
|
<CopyButton
|
|
@@ -90,8 +89,10 @@ const { formatDate } = useFormatDate()
|
|
|
90
89
|
</code>
|
|
91
90
|
</DescriptionDetails>
|
|
92
91
|
</template>
|
|
93
|
-
</
|
|
94
|
-
<
|
|
92
|
+
</dl>
|
|
93
|
+
<dl
|
|
94
|
+
class="p-0 m-0 shrink-0"
|
|
95
|
+
>
|
|
95
96
|
<DescriptionTerm>{{ t('Créée le') }}</DescriptionTerm>
|
|
96
97
|
<DescriptionDetails>
|
|
97
98
|
{{ formatDate(resource.created_at) }}
|
|
@@ -100,8 +101,10 @@ const { formatDate } = useFormatDate()
|
|
|
100
101
|
<DescriptionDetails>
|
|
101
102
|
{{ formatDate(resource.last_modified) }}
|
|
102
103
|
</DescriptionDetails>
|
|
103
|
-
</
|
|
104
|
-
<
|
|
104
|
+
</dl>
|
|
105
|
+
<dl
|
|
106
|
+
class="p-0 m-0 shrink-0"
|
|
107
|
+
>
|
|
105
108
|
<template v-if="resourceFilesize">
|
|
106
109
|
<DescriptionTerm>{{ t('Taille') }}</DescriptionTerm>
|
|
107
110
|
<DescriptionDetails>
|
|
@@ -120,12 +123,12 @@ const { formatDate } = useFormatDate()
|
|
|
120
123
|
<code class="code truncate">{{ resource.mime }}</code>
|
|
121
124
|
</DescriptionDetails>
|
|
122
125
|
</template>
|
|
123
|
-
</
|
|
126
|
+
</dl>
|
|
124
127
|
</div>
|
|
125
128
|
<div>
|
|
126
129
|
<ExtraAccordion
|
|
127
130
|
v-if="hasExtras"
|
|
128
|
-
class="pt-6 mt-6 border-
|
|
131
|
+
class="pt-6 mt-6 border-t border-gray-default"
|
|
129
132
|
:button-text="t('Voir les extras')"
|
|
130
133
|
:title-text="t('Extras de la ressource')"
|
|
131
134
|
title-level="h5"
|
|
@@ -134,19 +137,3 @@ const { formatDate } = useFormatDate()
|
|
|
134
137
|
</div>
|
|
135
138
|
</div>
|
|
136
139
|
</template>
|
|
137
|
-
|
|
138
|
-
<style scoped>
|
|
139
|
-
.gap-3rem {
|
|
140
|
-
gap: 3rem;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
.gap-3rem dl {
|
|
144
|
-
padding-inline-start: 0;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
@container (max-width: 600px) {
|
|
148
|
-
.flex-col-on-small {
|
|
149
|
-
flex-direction: column
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
</style>
|
|
@@ -1,30 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="text-xs">
|
|
3
|
-
<div
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
:
|
|
11
|
-
:
|
|
12
|
-
progress-color="#0063cb"
|
|
13
|
-
:show-page-tooltip="true"
|
|
14
|
-
:show-back-to-top-btn="true"
|
|
15
|
-
:scroll-threshold="300"
|
|
16
|
-
pdf-width="100%"
|
|
17
|
-
:row-gap="12"
|
|
18
|
-
:use-system-fonts="true"
|
|
19
|
-
:disable-range="false"
|
|
20
|
-
:disable-stream="false"
|
|
21
|
-
:disable-auto-fetch="false"
|
|
3
|
+
<div
|
|
4
|
+
v-if="pdfReady"
|
|
5
|
+
ref="containerRef"
|
|
6
|
+
class="w-full overflow-y-auto max-h-[80vh] space-y-3"
|
|
7
|
+
>
|
|
8
|
+
<canvas
|
|
9
|
+
v-for="page in totalPages"
|
|
10
|
+
:key="page"
|
|
11
|
+
:ref="(el) => setCanvasRef(el as HTMLCanvasElement, page)"
|
|
22
12
|
class="w-full"
|
|
23
|
-
@on-progress="handleProgress"
|
|
24
|
-
@on-complete="handleComplete"
|
|
25
|
-
@on-page-change="handlePageChange"
|
|
26
|
-
@on-pdf-init="handlePdfInit"
|
|
27
|
-
@on-error="handleError"
|
|
28
13
|
/>
|
|
29
14
|
</div>
|
|
30
15
|
<div
|
|
@@ -64,19 +49,18 @@
|
|
|
64
49
|
</template>
|
|
65
50
|
|
|
66
51
|
<script setup lang="ts">
|
|
67
|
-
import { computed,
|
|
52
|
+
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
|
|
68
53
|
import { RiErrorWarningLine } from '@remixicon/vue'
|
|
54
|
+
import * as pdfjsLib from 'pdfjs-dist'
|
|
55
|
+
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.min.mjs?url'
|
|
56
|
+
import type { PDFDocumentProxy } from 'pdfjs-dist'
|
|
69
57
|
import SimpleBanner from '../SimpleBanner.vue'
|
|
70
58
|
import { useComponentsConfig } from '../../config'
|
|
71
59
|
import type { Resource } from '../../types/resources'
|
|
72
60
|
import { useTranslation } from '../../composables/useTranslation'
|
|
73
61
|
import { getResourceFilesize } from '../../functions/datasets'
|
|
74
62
|
|
|
75
|
-
|
|
76
|
-
import('pdf-vue3').then((module) => {
|
|
77
|
-
return module.default
|
|
78
|
-
}),
|
|
79
|
-
)
|
|
63
|
+
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker
|
|
80
64
|
|
|
81
65
|
const props = defineProps<{
|
|
82
66
|
resource: Resource
|
|
@@ -85,10 +69,47 @@ const props = defineProps<{
|
|
|
85
69
|
const config = useComponentsConfig()
|
|
86
70
|
const { t } = useTranslation()
|
|
87
71
|
|
|
88
|
-
const
|
|
72
|
+
const containerRef = ref<HTMLElement | null>(null)
|
|
73
|
+
const pdfReady = ref(false)
|
|
89
74
|
const loading = ref(false)
|
|
90
75
|
const error = ref<string | null>(null)
|
|
91
76
|
const fileTooLarge = ref(false)
|
|
77
|
+
const totalPages = ref(0)
|
|
78
|
+
|
|
79
|
+
let pdfDoc: PDFDocumentProxy | null = null
|
|
80
|
+
const canvasRefs = new Map<number, HTMLCanvasElement>()
|
|
81
|
+
|
|
82
|
+
function setCanvasRef(el: HTMLCanvasElement | null, pageNum: number) {
|
|
83
|
+
if (el) canvasRefs.set(pageNum, el)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function renderPage(pageNum: number) {
|
|
87
|
+
if (!pdfDoc) return
|
|
88
|
+
|
|
89
|
+
const canvas = canvasRefs.get(pageNum)
|
|
90
|
+
if (!canvas) return
|
|
91
|
+
|
|
92
|
+
const page = await pdfDoc.getPage(pageNum)
|
|
93
|
+
|
|
94
|
+
const containerWidth = containerRef.value?.clientWidth ?? 800
|
|
95
|
+
const unscaledViewport = page.getViewport({ scale: 1 })
|
|
96
|
+
const scale = containerWidth / unscaledViewport.width
|
|
97
|
+
const viewport = page.getViewport({ scale })
|
|
98
|
+
|
|
99
|
+
const dpr = window.devicePixelRatio || 1
|
|
100
|
+
canvas.width = viewport.width * dpr
|
|
101
|
+
canvas.height = viewport.height * dpr
|
|
102
|
+
canvas.style.width = `${viewport.width}px`
|
|
103
|
+
canvas.style.height = `${viewport.height}px`
|
|
104
|
+
|
|
105
|
+
const context = canvas.getContext('2d')!
|
|
106
|
+
context.scale(dpr, dpr)
|
|
107
|
+
|
|
108
|
+
await page.render({
|
|
109
|
+
canvasContext: context,
|
|
110
|
+
viewport,
|
|
111
|
+
}).promise
|
|
112
|
+
}
|
|
92
113
|
|
|
93
114
|
const fileSizeBytes = computed(() => getResourceFilesize(props.resource))
|
|
94
115
|
|
|
@@ -105,7 +126,6 @@ const shouldLoadPdf = computed(() => {
|
|
|
105
126
|
})
|
|
106
127
|
|
|
107
128
|
const loadPdf = async () => {
|
|
108
|
-
// Check if file is too large or size is unknown before loading
|
|
109
129
|
if (!shouldLoadPdf.value) {
|
|
110
130
|
fileTooLarge.value = true
|
|
111
131
|
return
|
|
@@ -115,19 +135,23 @@ const loadPdf = async () => {
|
|
|
115
135
|
error.value = null
|
|
116
136
|
|
|
117
137
|
try {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
138
|
+
const loadingTask = pdfjsLib.getDocument({
|
|
139
|
+
url: props.resource.url,
|
|
140
|
+
isEvalSupported: false,
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
pdfDoc = await loadingTask.promise
|
|
144
|
+
totalPages.value = pdfDoc.numPages
|
|
145
|
+
pdfReady.value = true
|
|
124
146
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
147
|
+
await nextTick()
|
|
148
|
+
|
|
149
|
+
for (let i = 1; i <= pdfDoc.numPages; i++) {
|
|
150
|
+
await renderPage(i)
|
|
151
|
+
}
|
|
128
152
|
}
|
|
129
153
|
catch (err) {
|
|
130
|
-
console.error('Error
|
|
154
|
+
console.error('Error loading PDF:', err)
|
|
131
155
|
|
|
132
156
|
if (err instanceof TypeError) {
|
|
133
157
|
error.value = 'network'
|
|
@@ -135,45 +159,17 @@ const loadPdf = async () => {
|
|
|
135
159
|
else {
|
|
136
160
|
error.value = 'generic'
|
|
137
161
|
}
|
|
138
|
-
|
|
139
|
-
pdfData.value = false
|
|
140
162
|
}
|
|
141
163
|
finally {
|
|
142
164
|
loading.value = false
|
|
143
165
|
}
|
|
144
166
|
}
|
|
145
167
|
|
|
146
|
-
// Event handlers for PDF component
|
|
147
|
-
const handleProgress = (loadRatio: number) => {
|
|
148
|
-
console.log(`PDF loading progress: ${loadRatio}%`)
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
const handleComplete = () => {
|
|
152
|
-
console.log('PDF download completed')
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const handlePageChange = (page: number) => {
|
|
156
|
-
console.log(`PDF page changed to: ${page}`)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const handlePdfInit = (pdf: unknown) => {
|
|
160
|
-
console.log('PDF initialized:', pdf)
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const handleError = (err: unknown) => {
|
|
164
|
-
console.error('PDF loading error:', err)
|
|
165
|
-
|
|
166
|
-
if (err instanceof TypeError) {
|
|
167
|
-
error.value = 'network'
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
error.value = 'generic'
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
pdfData.value = false
|
|
174
|
-
}
|
|
175
|
-
|
|
176
168
|
onMounted(() => {
|
|
177
169
|
loadPdf()
|
|
178
170
|
})
|
|
171
|
+
|
|
172
|
+
onBeforeUnmount(() => {
|
|
173
|
+
pdfDoc?.destroy()
|
|
174
|
+
})
|
|
179
175
|
</script>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
type="warning"
|
|
6
6
|
class="flex items-center space-x-2"
|
|
7
7
|
>
|
|
8
|
-
<RiErrorWarningLine class="
|
|
8
|
+
<RiErrorWarningLine class="shrink-0 size-6" />
|
|
9
9
|
<span>{{ t("L'aperçu cartographique de ce fichier n'a pas pu être chargé.") }}</span>
|
|
10
10
|
</SimpleBanner>
|
|
11
11
|
<div
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
<p class="fr-text--bold fr-m-0">
|
|
26
26
|
{{ t("Explorer les données en détail") }}
|
|
27
27
|
</p>
|
|
28
|
-
<p class="fr-text--sm fr-m-0
|
|
28
|
+
<p class="fr-text--sm fr-m-0 italic">
|
|
29
29
|
{{ t("Utiliser un visualisateur PMTiles pour obtenir un aperçu des données.") }}
|
|
30
30
|
</p>
|
|
31
31
|
</div>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
type="warning"
|
|
6
6
|
class="flex items-center space-x-2"
|
|
7
7
|
>
|
|
8
|
-
<RiErrorWarningLine class="
|
|
8
|
+
<RiErrorWarningLine class="shrink-0 size-6" />
|
|
9
9
|
<span>{{ t("L'aperçu de ce fichier n'a pas pu être chargé.") }}</span>
|
|
10
10
|
</SimpleBanner>
|
|
11
11
|
<PreviewLoader v-else-if="loading" />
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
<p class="fr-text--bold fr-m-0">
|
|
24
24
|
{{ t("Explorer les données en détail") }}
|
|
25
25
|
</p>
|
|
26
|
-
<p class="fr-text--sm fr-m-0
|
|
26
|
+
<p class="fr-text--sm fr-m-0 italic">
|
|
27
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.") }}
|
|
28
28
|
</p>
|
|
29
29
|
</div>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
>
|
|
10
10
|
<div>
|
|
11
11
|
<div class="flex items-center fr-mb-1v">
|
|
12
|
-
<
|
|
12
|
+
<h3
|
|
13
13
|
:id="resourceTitleId"
|
|
14
14
|
class="fr-m-0"
|
|
15
15
|
>
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
/></span>
|
|
44
44
|
<span class="absolute inset-0 z-1" />
|
|
45
45
|
</button>
|
|
46
|
-
</
|
|
46
|
+
</h3>
|
|
47
47
|
<CopyButton
|
|
48
48
|
:label="t('Copier le lien')"
|
|
49
49
|
:copied-label="t('Lien copié !')"
|
|
@@ -51,22 +51,33 @@
|
|
|
51
51
|
class="z-2"
|
|
52
52
|
/>
|
|
53
53
|
</div>
|
|
54
|
-
<div class="text-gray-medium subheaders-infos">
|
|
54
|
+
<div class="text-gray-medium subheaders-infos flex items-center gap-1">
|
|
55
55
|
<SchemaBadge
|
|
56
56
|
:resource
|
|
57
|
-
class="dash-after"
|
|
58
57
|
/>
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
class="
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
<RiSubtractLine
|
|
59
|
+
v-if="resource.schema"
|
|
60
|
+
aria-hidden="true"
|
|
61
|
+
class="size-3 fill-gray-medium"
|
|
62
|
+
/>
|
|
63
|
+
<span class="text-xs mb-0">{{ t('Mis à jour {date}', { date: formatRelativeIfRecentDate(lastUpdate) }) }}</span>
|
|
64
|
+
<RiSubtractLine
|
|
65
|
+
aria-hidden="true"
|
|
66
|
+
class="size-3 fill-gray-medium"
|
|
67
|
+
/>
|
|
68
|
+
<template v-if="resource.format">
|
|
69
|
+
<span class="text-xs mb-0">
|
|
70
|
+
<span class="hidden sm:inline">{{ t("Format") }}</span>
|
|
71
|
+
{{ resource.format.trim().toLowerCase() }}
|
|
72
|
+
<span v-if="resourceFilesize">({{ filesize(resourceFilesize) }})</span>
|
|
73
|
+
</span>
|
|
74
|
+
<RiSubtractLine
|
|
75
|
+
aria-hidden="true"
|
|
76
|
+
class="size-3 fill-gray-medium"
|
|
77
|
+
/>
|
|
78
|
+
</template>
|
|
68
79
|
<span
|
|
69
|
-
class="inline-flex items-center
|
|
80
|
+
class="inline-flex items-center text-xs mb-0"
|
|
70
81
|
:aria-label="t('{n} téléchargements', resource.metrics.views)"
|
|
71
82
|
>
|
|
72
83
|
<span class="fr-icon-download-line fr-icon--xs fr-mr-1v" />
|
|
@@ -102,6 +113,7 @@
|
|
|
102
113
|
rel="ugc nofollow noopener"
|
|
103
114
|
new-tab
|
|
104
115
|
size="xs"
|
|
116
|
+
color="secondary"
|
|
105
117
|
external
|
|
106
118
|
@click="trackEvent('Jeux de données', 'Télécharger un fichier', 'Bouton : télécharger un fichier')"
|
|
107
119
|
>
|
|
@@ -116,7 +128,7 @@
|
|
|
116
128
|
:id="resource.id + '-copy'"
|
|
117
129
|
:data-clipboard-text="resource.url"
|
|
118
130
|
:aria-describedby="resourceTitleId"
|
|
119
|
-
color="
|
|
131
|
+
color="secondary"
|
|
120
132
|
size="xs"
|
|
121
133
|
:icon="RiFileCopyLine"
|
|
122
134
|
>
|
|
@@ -132,14 +144,15 @@
|
|
|
132
144
|
rel="ugc nofollow noopener"
|
|
133
145
|
:title="downloadButtonTitle"
|
|
134
146
|
download
|
|
135
|
-
class="relative
|
|
147
|
+
class="relative matomo_download z-2"
|
|
136
148
|
:icon="unavailable ? RiFileWarningLine : RiDownloadLine"
|
|
137
149
|
size="xs"
|
|
150
|
+
color="secondary"
|
|
138
151
|
:aria-describedby="resourceTitleId"
|
|
139
152
|
external
|
|
140
153
|
@click="trackEvent('Jeux de données', 'Télécharger un fichier', 'Bouton : télécharger un fichier')"
|
|
141
154
|
>
|
|
142
|
-
|
|
155
|
+
{{ t('Télécharger') }}
|
|
143
156
|
</BrandedButton>
|
|
144
157
|
</p>
|
|
145
158
|
<p
|
|
@@ -358,7 +371,7 @@
|
|
|
358
371
|
|
|
359
372
|
<script setup lang="ts">
|
|
360
373
|
import { ref, computed, defineAsyncComponent } from 'vue'
|
|
361
|
-
import { RiDownloadLine, RiFileCopyLine, RiFileWarningLine } from '@remixicon/vue'
|
|
374
|
+
import { RiDownloadLine, RiFileCopyLine, RiFileWarningLine, RiSubtractLine } from '@remixicon/vue'
|
|
362
375
|
import OrganizationNameWithCertificate from '../OrganizationNameWithCertificate.vue'
|
|
363
376
|
import { filesize, summarize } from '../../functions/helpers'
|
|
364
377
|
import { useFormatDate } from '../../functions/dates'
|
|
@@ -378,6 +391,7 @@ import { getResourceFormatIcon, getResourceTitleId, detectOgcService } from '../
|
|
|
378
391
|
import BrandedButton from '../BrandedButton.vue'
|
|
379
392
|
import { getResourceExternalUrl, getResourceFilesize } from '../../functions/datasets'
|
|
380
393
|
import { useTranslation } from '../../composables/useTranslation'
|
|
394
|
+
import { useHasTabularData } from '../../composables/useHasTabularData'
|
|
381
395
|
import Metadata from './Metadata.vue'
|
|
382
396
|
import SchemaBadge from './SchemaBadge.vue'
|
|
383
397
|
import ResourceIcon from './ResourceIcon.vue'
|
|
@@ -414,6 +428,7 @@ const DatafairPreview = defineAsyncComponent(() => import('./Datafair.client.vue
|
|
|
414
428
|
|
|
415
429
|
const { t } = useTranslation()
|
|
416
430
|
const { formatRelativeIfRecentDate } = useFormatDate()
|
|
431
|
+
const checkTabularData = useHasTabularData()
|
|
417
432
|
|
|
418
433
|
const hasPreview = computed(() => {
|
|
419
434
|
// For JSON, PDF, and XML files, show preview.
|
|
@@ -423,13 +438,7 @@ const hasPreview = computed(() => {
|
|
|
423
438
|
return format === 'json' || format === 'pdf' || format === 'xml'
|
|
424
439
|
})
|
|
425
440
|
|
|
426
|
-
const hasTabularData = computed(() =>
|
|
427
|
-
// Determines if we should show the "Données" tab for tabular files AND the "Structure des données" tab (for tabular data structure)
|
|
428
|
-
return config.tabularApiUrl
|
|
429
|
-
&& props.resource.extras['analysis:parsing:parsing_table']
|
|
430
|
-
&& !props.resource.extras['analysis:parsing:error']
|
|
431
|
-
&& (config.tabularAllowRemote || props.resource.filetype === 'file')
|
|
432
|
-
})
|
|
441
|
+
const hasTabularData = computed(() => checkTabularData(props.resource))
|
|
433
442
|
|
|
434
443
|
const hasPmtiles = computed(() => {
|
|
435
444
|
return props.resource.extras['analysis:parsing:pmtiles_url'] || props.resource.format === 'pmtiles'
|
|
@@ -595,9 +604,7 @@ article {
|
|
|
595
604
|
article header .subheaders-infos .hidden.show-on-small {
|
|
596
605
|
display: inline !important;
|
|
597
606
|
}
|
|
598
|
-
|
|
599
|
-
content: ''
|
|
600
|
-
} */
|
|
607
|
+
*/
|
|
601
608
|
|
|
602
609
|
/* article .fr-pl-4v fr-pr-4v {
|
|
603
610
|
padding: 0.75rem !important;
|
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
>
|
|
10
10
|
<RiInformationLine class="size-4" />
|
|
11
11
|
<template #toggletip="{ close }">
|
|
12
|
-
<div class="flex justify-between border-
|
|
12
|
+
<div class="flex justify-between border-b">
|
|
13
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')"
|
|
17
|
-
class="border-
|
|
17
|
+
class="border-l close-button flex items-center justify-center"
|
|
18
18
|
@click="close"
|
|
19
19
|
>×</button>
|
|
20
20
|
</div>
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
type="warning"
|
|
15
15
|
class="flex items-center space-x-2"
|
|
16
16
|
>
|
|
17
|
-
<RiErrorWarningLine class="
|
|
17
|
+
<RiErrorWarningLine class="shrink-0 size-6" />
|
|
18
18
|
<span>{{ fileSizeBytes
|
|
19
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
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.")
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
type="warning"
|
|
26
26
|
class="flex items-center space-x-2"
|
|
27
27
|
>
|
|
28
|
-
<RiErrorWarningLine class="
|
|
28
|
+
<RiErrorWarningLine class="shrink-0 size-6" />
|
|
29
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
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
type="warning"
|
|
34
34
|
class="flex items-center space-x-2"
|
|
35
35
|
>
|
|
36
|
-
<RiErrorWarningLine class="
|
|
36
|
+
<RiErrorWarningLine class="shrink-0 size-6" />
|
|
37
37
|
<span>{{ t("Erreur lors du chargement de l'aperçu XML.") }}</span>
|
|
38
38
|
</SimpleBanner>
|
|
39
39
|
</div>
|