@datagouv/components-next 1.0.2-dev.20 → 1.0.2-dev.200
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 +7 -6
- package/assets/main.css +4 -0
- package/dist/{Control-DuZJdKV_.js → Control-B9WQxlpJ.js} +1 -1
- package/dist/{Datafair.client-Ds3VQrRi.js → Datafair.client-CFTmBFoY.js} +9 -9
- package/dist/{Event--kp8kMdJ.js → Event-iXDrp-fy.js} +31 -31
- package/dist/{Image-34hvypZI.js → Image-mNMBOofs.js} +9 -9
- package/dist/ImagePreview.client-BvDM3qjE.js +36 -0
- package/dist/JsonPreview.client-BP6gPRxf.js +40 -0
- package/dist/{Map-BjUnLyj8.js → Map-BfqKMw0S.js} +1739 -1599
- package/dist/{MapContainer.client-B2BijMx5.js → MapContainer.client-D9N3664r.js} +41 -42
- package/dist/{OSM-s40W6sQ2.js → OSM-CcrUhItr.js} +15 -23
- package/dist/{PdfPreview.client-DJBMzrlC.js → PdfPreview.client-C6A6ZiKl.js} +835 -856
- package/dist/Pmtiles.client-B_sDZoqu.js +26333 -0
- package/dist/PreviewWrapper.vue_vue_type_script_setup_true_lang-DGLXBys_.js +60 -0
- package/dist/{ScaleLine-KW-nXqp3.js → ScaleLine-VGQ7nkMS.js} +2 -2
- package/dist/{Tile-DbNFNPfU.js → Tile-CSpn0Ca8.js} +160 -163
- package/dist/{TileImage-BsXBxMtq.js → TileImage-CpbaEFwd.js} +143 -131
- package/dist/{View-BR92hTWP.js → View-BYBpt-AU.js} +483 -422
- package/dist/XmlPreview.client-DFQ1T-LN.js +34 -0
- package/dist/{common-PJfpC179.js → common-BoeTUnDZ.js} +52 -52
- package/dist/components-next.css +1 -52
- package/dist/components-next.js +196 -150
- package/dist/components.css +2 -2
- package/dist/{index-BFQX7Ccz.js → index-B_tPYi5Z.js} +34094 -27864
- package/dist/{leaflet-src-7m1mB8LI.js → leaflet-src-PeylHk0o.js} +162 -164
- package/dist/{main-vqhkVhVS.js → main-CVOZp_Nx.js} +41939 -73132
- package/dist/{proj-DsetBcW7.js → proj-DxGbobp7.js} +662 -626
- package/dist/{text-clamp.esm-B5kW_XMt.js → text-clamp.esm-DVseBqZZ.js} +4 -4
- package/dist/{tilecoord-Db24Px13.js → tilecoord-DvX7WWiA.js} +273 -264
- package/dist/{vue3-json-viewer-BXwup7nO.js → vue3-json-viewer-CJLQFzXZ.js} +10 -16
- package/dist/{vue3-xml-viewer.common-BcNJo35o.js → vue3-xml-viewer.common-CcF3Xd23.js} +1 -1
- package/package.json +47 -38
- package/src/chart.ts +5 -0
- package/src/components/ActivityList/ActivityList.vue +24 -14
- package/src/components/AppLink.vue +3 -0
- package/src/components/BannerAction.vue +6 -2
- package/src/components/Chart/ChartViewer.vue +320 -0
- package/src/components/Chart/ChartViewerWrapper.vue +182 -0
- package/src/components/CopyButton.vue +6 -2
- package/src/components/DataserviceCard.vue +24 -5
- package/src/components/DataserviceQuality.vue +82 -0
- package/src/components/DataserviceQualityInline.vue +31 -0
- package/src/components/DataserviceQualityTooltipContent.vue +79 -0
- package/src/components/DatasetCard.vue +24 -9
- package/src/components/DatasetInformation/DatasetTemporalitySection.vue +7 -4
- package/src/components/DatasetQuality.vue +11 -11
- package/src/components/DatasetQualityInline.vue +2 -2
- package/src/components/DatasetQualityTooltipContent.vue +1 -1
- package/src/components/DiscussionMessageCard.vue +14 -15
- package/src/components/Form/Listbox.vue +101 -0
- package/src/components/Form/SchemaSelect.vue +2 -0
- package/src/components/FormattedDate.vue +81 -0
- package/src/components/InfiniteLoader.vue +53 -0
- package/src/components/LoadingBlock.vue +4 -1
- package/src/components/ObjectCardHeader.vue +11 -4
- package/src/components/OpenApiViewer/ContentTypeSelect.vue +48 -0
- package/src/components/OpenApiViewer/EndpointRequest.vue +164 -0
- package/src/components/OpenApiViewer/EndpointResponses.vue +149 -0
- package/src/components/OpenApiViewer/OpenApiViewer.vue +308 -0
- package/src/components/OpenApiViewer/SchemaPanel.vue +53 -0
- package/src/components/OpenApiViewer/SchemaTree.vue +77 -0
- package/src/components/OpenApiViewer/openapi.ts +150 -0
- package/src/components/OrganizationNameWithCertificate.vue +3 -2
- package/src/components/Pagination.vue +25 -62
- package/src/components/PostCard.vue +13 -15
- package/src/components/RadioInput.vue +7 -2
- package/src/components/ResourceAccordion/DataStructure.vue +11 -33
- package/src/components/ResourceAccordion/Datafair.client.vue +1 -1
- package/src/components/ResourceAccordion/Downloads.vue +172 -0
- package/src/components/ResourceAccordion/ImagePreview.client.vue +48 -0
- package/src/components/ResourceAccordion/JsonPreview.client.vue +23 -104
- package/src/components/ResourceAccordion/MapContainer.client.vue +2 -11
- package/src/components/ResourceAccordion/Metadata.vue +4 -6
- package/src/components/ResourceAccordion/PdfPreview.client.vue +58 -97
- package/src/components/ResourceAccordion/PdfSkeleton.vue +44 -0
- package/src/components/ResourceAccordion/Pmtiles.client.vue +28 -13
- package/src/components/ResourceAccordion/Preview.vue +19 -15
- package/src/components/ResourceAccordion/PreviewWrapper.vue +89 -0
- package/src/components/ResourceAccordion/ResourceAccordion.vue +36 -117
- package/src/components/ResourceAccordion/XmlPreview.client.vue +16 -98
- package/src/components/ResourceExplorer/ResourceExplorer.vue +105 -210
- package/src/components/ResourceExplorer/ResourceExplorerHeader.vue +79 -0
- package/src/components/ResourceExplorer/ResourceExplorerSidebar.vue +104 -71
- package/src/components/ResourceExplorer/ResourceExplorerViewer.vue +143 -291
- package/src/components/ResourceExplorer/ResourceMainAction.vue +240 -0
- package/src/components/ResourceExplorer/ResourceSelector.vue +51 -0
- package/src/components/ResourceExplorer/ResourceViewerHeader.vue +122 -0
- package/src/components/ResourceExplorer/ResourceViewerSkeleton.vue +94 -0
- package/src/components/ResourceListItem.vue +168 -0
- package/src/components/ReuseCard.vue +28 -9
- package/src/components/ReuseDetails.vue +2 -2
- package/src/components/ReuseHorizontalCard.vue +2 -2
- package/src/components/SchemaCard.vue +10 -1
- package/src/components/Search/Filter/AccessTypeFilter.vue +2 -2
- package/src/components/Search/GlobalSearch.vue +229 -123
- package/src/components/Search/SearchInput.vue +5 -4
- package/src/components/Search/Sidemenu.vue +4 -3
- package/src/components/SmallChart.vue +11 -10
- package/src/components/StatBox.vue +13 -5
- package/src/components/TabularExplorer/TabularActiveFilters.vue +79 -0
- package/src/components/TabularExplorer/TabularCell.vue +50 -0
- package/src/components/TabularExplorer/TabularCellPopover.vue +170 -0
- package/src/components/TabularExplorer/TabularColumnsMenu.vue +112 -0
- package/src/components/TabularExplorer/TabularExplorer.vue +299 -0
- package/src/components/TabularExplorer/TabularFilterContent.vue +362 -0
- package/src/components/TabularExplorer/TabularFilterPopover.vue +106 -0
- package/src/components/TabularExplorer/TabularMobileFilterButton.vue +21 -0
- package/src/components/TabularExplorer/TabularMobileFilters.vue +150 -0
- package/src/components/TabularExplorer/TabularRowsInfo.vue +31 -0
- package/src/components/TabularExplorer/TabularSkeleton.vue +92 -0
- package/src/components/TabularExplorer/TabularTable.vue +481 -0
- package/src/components/TabularExplorer/TabularToolbar.vue +25 -0
- package/src/components/TabularExplorer/types.ts +84 -0
- package/src/components/TabularExplorer/useColumnMetadata.ts +98 -0
- package/src/components/TabularExplorer/useTabularContext.ts +82 -0
- package/src/components/TopicCard.vue +13 -14
- package/src/composables/useActiveDescendant.ts +5 -0
- package/src/composables/useDatasetResources.ts +164 -0
- package/src/composables/useHasTabularData.ts +15 -1
- package/src/composables/useMetrics.ts +1 -1
- package/src/composables/useResizable.ts +46 -0
- package/src/composables/useResourceCapabilities.ts +48 -40
- package/src/composables/useSearchFilter.ts +120 -0
- package/src/composables/useStableQueryParams.ts +38 -6
- package/src/composables/useTabularProfile.ts +70 -0
- package/src/composables/useTranslation.ts +24 -9
- package/src/config.ts +21 -3
- package/src/functions/activities.ts +3 -3
- package/src/functions/api.ts +20 -42
- package/src/functions/api.types.ts +1 -0
- package/src/functions/charts.ts +99 -0
- package/src/functions/datasets.ts +0 -17
- package/src/functions/dates.ts +6 -7
- package/src/functions/helpers.ts +15 -0
- package/src/functions/metrics.ts +63 -60
- package/src/functions/paginate.ts +46 -0
- package/src/functions/resourceCapabilities.ts +34 -0
- package/src/functions/resources.ts +136 -1
- package/src/functions/schemas.ts +27 -0
- package/src/functions/scroll.ts +20 -0
- package/src/functions/tabular.ts +214 -0
- package/src/functions/tabularApi.ts +96 -11
- package/src/main.ts +119 -14
- package/src/types/dataservices.ts +17 -0
- package/src/types/organizations.ts +10 -0
- package/src/types/pages.ts +0 -5
- package/src/types/posts.ts +2 -2
- package/src/types/reports.ts +5 -1
- package/src/types/resources.ts +0 -1
- package/src/types/reuses.ts +12 -1
- package/src/types/search.ts +63 -1
- package/src/types/site.ts +5 -3
- package/src/types/ui.ts +2 -0
- package/src/types/users.ts +2 -1
- package/src/types/visualizations.ts +93 -0
- package/assets/swagger-themes/newspaper.css +0 -1670
- package/dist/JsonPreview.client-CYxmz0yV.js +0 -72
- package/dist/Pmtiles.client-C_hvRDuy.js +0 -25185
- package/dist/Swagger.client-B4y0hXME.js +0 -4
- package/dist/XmlPreview.client-LETEfNBH.js +0 -64
- package/src/components/ResourceAccordion/Swagger.client.vue +0 -48
- package/src/functions/pagination.ts +0 -9
- /package/src/components/{DatasetQualityItem.vue → QualityItem.vue} +0 -0
- /package/src/components/{DatasetQualityItemWarning.vue → QualityItemWarning.vue} +0 -0
- /package/src/components/{DatasetQualityScore.vue → QualityScore.vue} +0 -0
|
@@ -56,11 +56,21 @@
|
|
|
56
56
|
:resource
|
|
57
57
|
/>
|
|
58
58
|
<RiSubtractLine
|
|
59
|
-
v-if="resource.schema"
|
|
59
|
+
v-if="resource.schema?.name || resource.schema?.url"
|
|
60
60
|
aria-hidden="true"
|
|
61
61
|
class="size-3 fill-gray-medium"
|
|
62
62
|
/>
|
|
63
|
-
<
|
|
63
|
+
<TranslationT
|
|
64
|
+
class="text-xs mb-0"
|
|
65
|
+
keypath="Mis à jour {date}"
|
|
66
|
+
>
|
|
67
|
+
<template #date>
|
|
68
|
+
<FormattedDate
|
|
69
|
+
:date="lastUpdate"
|
|
70
|
+
format="relative"
|
|
71
|
+
/>
|
|
72
|
+
</template>
|
|
73
|
+
</TranslationT>
|
|
64
74
|
<RiSubtractLine
|
|
65
75
|
aria-hidden="true"
|
|
66
76
|
class="size-3 fill-gray-medium"
|
|
@@ -197,7 +207,10 @@
|
|
|
197
207
|
:key="tab.key"
|
|
198
208
|
class="px-4"
|
|
199
209
|
>
|
|
200
|
-
<div
|
|
210
|
+
<div
|
|
211
|
+
v-if="tab.key === 'map'"
|
|
212
|
+
class="-mx-4 h-[600px]"
|
|
213
|
+
>
|
|
201
214
|
<Pmtiles
|
|
202
215
|
v-if="hasPmtiles"
|
|
203
216
|
:resource="resource"
|
|
@@ -224,6 +237,10 @@
|
|
|
224
237
|
v-else-if="resource.format && resource.format.toLowerCase() === 'xml'"
|
|
225
238
|
:resource="resource"
|
|
226
239
|
/>
|
|
240
|
+
<ImagePreview
|
|
241
|
+
v-else-if="isImagePreviewFormat(resource.format)"
|
|
242
|
+
:resource="resource"
|
|
243
|
+
/>
|
|
227
244
|
<!-- Show Datafair embedded preview (koumoul) -->
|
|
228
245
|
<DatafairPreview
|
|
229
246
|
v-else-if="hasDatafairPreview"
|
|
@@ -231,7 +248,7 @@
|
|
|
231
248
|
:dataset="dataset"
|
|
232
249
|
/>
|
|
233
250
|
<!-- Show Datafair embedded preview (koumoul) -->
|
|
234
|
-
<
|
|
251
|
+
<OpenApiViewer
|
|
235
252
|
v-else-if="hasOpenAPIPreview"
|
|
236
253
|
:url="resource.extras['apidocUrl'] as string"
|
|
237
254
|
/>
|
|
@@ -265,91 +282,13 @@
|
|
|
265
282
|
<div
|
|
266
283
|
v-if="tab.key === 'downloads'"
|
|
267
284
|
>
|
|
268
|
-
<
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
>
|
|
273
|
-
{{ t("URL d'origine") }}
|
|
274
|
-
</dt>
|
|
275
|
-
<dt
|
|
276
|
-
v-else
|
|
277
|
-
class="font-bold fr-text--sm fr-mb-0"
|
|
278
|
-
>
|
|
279
|
-
{{ t('Format original') }}
|
|
280
|
-
</dt>
|
|
281
|
-
<dd class="text-sm pl-0 mb-4 text-gray-medium h-8 flex flex-wrap items-center">
|
|
282
|
-
<span v-if="resource.format === 'url'">
|
|
283
|
-
<a
|
|
284
|
-
:href="resource.latest"
|
|
285
|
-
class="fr-link no-icon-after"
|
|
286
|
-
rel="ugc nofollow noopener"
|
|
287
|
-
target="_blank"
|
|
288
|
-
@click="trackEvent('Jeux de données', 'Télécharger un fichier', 'Bouton : télécharger un fichier')"
|
|
289
|
-
>
|
|
290
|
-
<component
|
|
291
|
-
:is="config.textClamp"
|
|
292
|
-
v-if="config && config.textClamp"
|
|
293
|
-
:auto-resize="true"
|
|
294
|
-
:max-lines="1"
|
|
295
|
-
:text="resource.url"
|
|
296
|
-
>
|
|
297
|
-
<template #after>
|
|
298
|
-
<span class="fr-ml-1v fr-icon-external-link-line fr-icon--sm" />
|
|
299
|
-
</template>
|
|
300
|
-
</component>
|
|
301
|
-
</a>
|
|
302
|
-
</span>
|
|
303
|
-
<span v-else>
|
|
304
|
-
<span class="text-datagouv fr-icon-download-line fr-icon--sm fr-mr-1v fr-mt-1v" />
|
|
305
|
-
<a
|
|
306
|
-
:href="resource.latest"
|
|
307
|
-
class="fr-link"
|
|
308
|
-
rel="ugc nofollow noopener"
|
|
309
|
-
@click="trackEvent('Jeux de données', 'Télécharger un fichier', `Bouton : format ${resource.format}`)"
|
|
310
|
-
>
|
|
311
|
-
<span>{{ t('Format {format}', { format: resource.format }) }}<span v-if="resourceFilesize"> - {{ filesize(resourceFilesize) }}</span></span>
|
|
312
|
-
</a>
|
|
313
|
-
</span>
|
|
314
|
-
<CopyButton
|
|
315
|
-
:label="t('Copier le lien')"
|
|
316
|
-
:copied-label="t('Lien copié !')"
|
|
317
|
-
:text="resource.latest"
|
|
318
|
-
class="relative"
|
|
319
|
-
/>
|
|
320
|
-
</dd>
|
|
321
|
-
<template v-if="generatedFormats.length">
|
|
322
|
-
<dt class="font-bold fr-text--sm fr-mb-0">
|
|
323
|
-
{{ t('Formats générés automatiquement par {platform} (dernière mise à jour {date})', { platform: config.name, date: conversionsLastUpdate }) }}
|
|
324
|
-
</dt>
|
|
325
|
-
<dd
|
|
326
|
-
v-for="generatedFormat in generatedFormats"
|
|
327
|
-
:key="generatedFormat.format"
|
|
328
|
-
class="text-sm pl-0 mb-4 text-gray-medium h-8 flex flex-wrap items-center"
|
|
329
|
-
>
|
|
330
|
-
<span>
|
|
331
|
-
<span class="text-datagouv fr-icon-download-line fr-icon--sm fr-mr-1v fr-mt-1v" />
|
|
332
|
-
<a
|
|
333
|
-
:href="generatedFormat.url"
|
|
334
|
-
class="fr-link"
|
|
335
|
-
rel="ugc nofollow noopener"
|
|
336
|
-
@click="trackEvent('Jeux de données', 'Télécharger un fichier', `Bouton : format ${generatedFormat.format}`)"
|
|
337
|
-
>
|
|
338
|
-
<span>{{ t('Format {format}', { format: generatedFormat.format }) }}<span v-if="generatedFormat.size"> - {{ filesize(generatedFormat.size) }}</span></span>
|
|
339
|
-
</a>
|
|
340
|
-
</span>
|
|
341
|
-
<CopyButton
|
|
342
|
-
:label="t('Copier le lien')"
|
|
343
|
-
:copied-label="t('Lien copié !')"
|
|
344
|
-
:text="generatedFormat.url"
|
|
345
|
-
class="relative"
|
|
346
|
-
/>
|
|
347
|
-
</dd>
|
|
348
|
-
</template>
|
|
349
|
-
</dl>
|
|
285
|
+
<Downloads
|
|
286
|
+
:resource="resource"
|
|
287
|
+
:dataset="dataset"
|
|
288
|
+
/>
|
|
350
289
|
</div>
|
|
351
290
|
<div
|
|
352
|
-
v-if="tab.key === '
|
|
291
|
+
v-if="tab.key === 'api'"
|
|
353
292
|
>
|
|
354
293
|
<div class="fr-mb-4w">
|
|
355
294
|
<p>{{ t("Cette API est générée automatiquement par {platform} à partir du fichier.", { platform: config.name }) }}</p>
|
|
@@ -357,7 +296,7 @@
|
|
|
357
296
|
<p>{{ t("- Si le fichier est supprimé, l'API sera également supprimée.") }}</p>
|
|
358
297
|
<p>{{ t("Pour des usages pérennes, prévoyez que cette API dépend directement du fichier source.") }}</p>
|
|
359
298
|
</div>
|
|
360
|
-
<
|
|
299
|
+
<OpenApiViewer
|
|
361
300
|
v-if="hasTabularData"
|
|
362
301
|
:url="`${config.tabularApiUrl}/api/resources/${props.resource.id}/swagger/`"
|
|
363
302
|
/>
|
|
@@ -374,7 +313,8 @@ import { ref, computed, defineAsyncComponent } from 'vue'
|
|
|
374
313
|
import { RiDownloadLine, RiFileCopyLine, RiFileWarningLine, RiSubtractLine } from '@remixicon/vue'
|
|
375
314
|
import OrganizationNameWithCertificate from '../OrganizationNameWithCertificate.vue'
|
|
376
315
|
import { filesize, summarize } from '../../functions/helpers'
|
|
377
|
-
import
|
|
316
|
+
import FormattedDate from '../FormattedDate.vue'
|
|
317
|
+
import TranslationT from '../TranslationT.vue'
|
|
378
318
|
import MarkdownViewer from '../MarkdownViewer.vue'
|
|
379
319
|
import type { CommunityResource, Resource } from '../../types/resources'
|
|
380
320
|
import type { Dataset, DatasetV2 } from '../../types/datasets'
|
|
@@ -387,9 +327,8 @@ import { trackEvent } from '../../functions/matomo'
|
|
|
387
327
|
import CopyButton from '../CopyButton.vue'
|
|
388
328
|
import { useComponentsConfig } from '../../config'
|
|
389
329
|
import { getOwnerName } from '../../functions/owned'
|
|
390
|
-
import { getResourceFormatIcon, getResourceTitleId, detectOgcService } from '../../functions/resources'
|
|
330
|
+
import { getResourceFormatIcon, getResourceTitleId, detectOgcService, getResourceExternalUrl, getResourceFilesize, isImagePreviewFormat } from '../../functions/resources'
|
|
391
331
|
import BrandedButton from '../BrandedButton.vue'
|
|
392
|
-
import { getResourceExternalUrl, getResourceFilesize } from '../../functions/datasets'
|
|
393
332
|
import { useTranslation } from '../../composables/useTranslation'
|
|
394
333
|
import { useHasTabularData } from '../../composables/useHasTabularData'
|
|
395
334
|
import Metadata from './Metadata.vue'
|
|
@@ -397,11 +336,11 @@ import SchemaBadge from './SchemaBadge.vue'
|
|
|
397
336
|
import ResourceIcon from './ResourceIcon.vue'
|
|
398
337
|
import EditButton from './EditButton.vue'
|
|
399
338
|
import DataStructure from './DataStructure.vue'
|
|
339
|
+
import Downloads from './Downloads.vue'
|
|
400
340
|
import Preview from './Preview.vue'
|
|
401
341
|
import { isOrganizationCertified } from '../../functions/organizations'
|
|
402
|
-
import
|
|
342
|
+
import OpenApiViewer from '../OpenApiViewer/OpenApiViewer.vue'
|
|
403
343
|
|
|
404
|
-
const GENERATED_FORMATS = ['parquet', 'pmtiles', 'geojson']
|
|
405
344
|
const URL_FORMATS = ['url', 'doi', 'www:link', ' www:link-1.0-http--link', 'www:link-1.0-http--partners', 'www:link-1.0-http--related', 'www:link-1.0-http--samples']
|
|
406
345
|
|
|
407
346
|
const props = withDefaults(defineProps<{
|
|
@@ -418,24 +357,23 @@ const props = withDefaults(defineProps<{
|
|
|
418
357
|
|
|
419
358
|
const config = useComponentsConfig()
|
|
420
359
|
|
|
421
|
-
const Swagger = defineAsyncComponent(() => import('./Swagger.client.vue'))
|
|
422
360
|
const MapContainer = defineAsyncComponent(() => import('./MapContainer.client.vue'))
|
|
423
361
|
const Pmtiles = defineAsyncComponent(() => import('./Pmtiles.client.vue'))
|
|
424
362
|
const JsonPreview = defineAsyncComponent(() => import('./JsonPreview.client.vue'))
|
|
425
363
|
const PdfPreview = defineAsyncComponent(() => import('./PdfPreview.client.vue'))
|
|
426
364
|
const XmlPreview = defineAsyncComponent(() => import('./XmlPreview.client.vue'))
|
|
365
|
+
const ImagePreview = defineAsyncComponent(() => import('./ImagePreview.client.vue'))
|
|
427
366
|
const DatafairPreview = defineAsyncComponent(() => import('./Datafair.client.vue'))
|
|
428
367
|
|
|
429
368
|
const { t } = useTranslation()
|
|
430
|
-
const { formatRelativeIfRecentDate } = useFormatDate()
|
|
431
369
|
const checkTabularData = useHasTabularData()
|
|
432
370
|
|
|
433
371
|
const hasPreview = computed(() => {
|
|
434
|
-
// For JSON, PDF, and
|
|
372
|
+
// For JSON, PDF, XML, and image files, show preview.
|
|
435
373
|
// We cannot check for CORS issues here because we cannot use an async component here.
|
|
436
374
|
// If there is a CORS issue when fetching the file for preview, it will be managed and displayed as an error banner by the preview component.
|
|
437
375
|
const format = props.resource.format?.toLowerCase()
|
|
438
|
-
return format === 'json' || format === 'pdf' || format === 'xml'
|
|
376
|
+
return format === 'json' || format === 'pdf' || format === 'xml' || isImagePreviewFormat(format)
|
|
439
377
|
})
|
|
440
378
|
|
|
441
379
|
const hasTabularData = computed(() => checkTabularData(props.resource))
|
|
@@ -462,24 +400,6 @@ const ogcService = computed(() => detectOgcService(props.resource))
|
|
|
462
400
|
|
|
463
401
|
const ogcWms = computed(() => ogcService.value === 'wms')
|
|
464
402
|
|
|
465
|
-
const generatedFormats = computed(() => {
|
|
466
|
-
const formats = GENERATED_FORMATS
|
|
467
|
-
.filter(format => `analysis:parsing:${format}_url` in props.resource.extras)
|
|
468
|
-
.map(format => ({
|
|
469
|
-
url: props.resource.extras[`analysis:parsing:${format}_url`] as string,
|
|
470
|
-
size: props.resource.extras[`analysis:parsing:${format}_size`] as number | undefined,
|
|
471
|
-
format: format,
|
|
472
|
-
}))
|
|
473
|
-
if ('analysis:parsing:parsing_table' in props.resource.extras) {
|
|
474
|
-
formats.push({
|
|
475
|
-
url: `${config.tabularApiUrl}/api/resources/${props.resource.id}/data/json/`,
|
|
476
|
-
size: undefined,
|
|
477
|
-
format: 'json',
|
|
478
|
-
})
|
|
479
|
-
}
|
|
480
|
-
return formats
|
|
481
|
-
})
|
|
482
|
-
|
|
483
403
|
const open = ref(props.expandedOnMount)
|
|
484
404
|
const toggle = () => {
|
|
485
405
|
open.value = !open.value
|
|
@@ -515,7 +435,7 @@ const tabsOptions = computed(() => {
|
|
|
515
435
|
options.push({ key: 'downloads', label: t('Téléchargements') })
|
|
516
436
|
|
|
517
437
|
if (hasTabularData.value) {
|
|
518
|
-
options.push({ key: '
|
|
438
|
+
options.push({ key: 'api', label: t('API') })
|
|
519
439
|
}
|
|
520
440
|
|
|
521
441
|
return options
|
|
@@ -542,7 +462,6 @@ const communityResource = computed<CommunityResource | null>(() => {
|
|
|
542
462
|
const owner = computed(() => communityResource.value ? getOwnerName(communityResource.value) : null)
|
|
543
463
|
|
|
544
464
|
const lastUpdate = props.resource.last_modified
|
|
545
|
-
const conversionsLastUpdate = computed(() => formatRelativeIfRecentDate(props.resource.extras['analysis:parsing:finished_at'] as string | undefined))
|
|
546
465
|
const availabilityChecked = props.resource.extras && 'check:available' in props.resource.extras
|
|
547
466
|
const resourceFilesize = computed(() => getResourceFilesize(props.resource))
|
|
548
467
|
|
|
@@ -1,42 +1,24 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
</div>
|
|
12
|
-
<PreviewUnavailable v-else-if="fileTooLarge">
|
|
13
|
-
{{ fileSizeBytes
|
|
14
|
-
? t("Le fichier XML est trop volumineux pour être prévisualisé. Téléchargez-le depuis l'onglet Téléchargements.")
|
|
15
|
-
: t("La taille du fichier est inconnue, l'aperçu n'est pas disponible. Téléchargez-le depuis l'onglet Téléchargements.")
|
|
16
|
-
}}
|
|
17
|
-
</PreviewUnavailable>
|
|
18
|
-
<PreviewUnavailable v-else-if="error === 'network'">
|
|
19
|
-
{{ t("Ce fichier est hébergé sur un site externe qui ne permet pas la prévisualisation. Téléchargez-le depuis l'onglet Téléchargements.") }}
|
|
20
|
-
</PreviewUnavailable>
|
|
21
|
-
<PreviewUnavailable v-else-if="error">
|
|
22
|
-
{{ t("L'aperçu de ce fichier n'a pas pu être chargé. Téléchargez-le depuis l'onglet Téléchargements.") }}
|
|
23
|
-
</PreviewUnavailable>
|
|
24
|
-
</div>
|
|
2
|
+
<PreviewWrapper
|
|
3
|
+
v-slot="{ data }"
|
|
4
|
+
file-type="XML"
|
|
5
|
+
:resource="resource"
|
|
6
|
+
:max-size="config.maxXmlPreviewCharSize"
|
|
7
|
+
:load="load"
|
|
8
|
+
>
|
|
9
|
+
<XmlViewer :xml="(data as string)" />
|
|
10
|
+
</PreviewWrapper>
|
|
25
11
|
</template>
|
|
26
12
|
|
|
27
13
|
<script setup lang="ts">
|
|
28
|
-
import {
|
|
14
|
+
import { defineAsyncComponent } from 'vue'
|
|
29
15
|
import { useComponentsConfig } from '../../config'
|
|
30
|
-
import
|
|
16
|
+
import PreviewWrapper from './PreviewWrapper.vue'
|
|
31
17
|
import type { Resource } from '../../types/resources'
|
|
32
|
-
import { useTranslation } from '../../composables/useTranslation'
|
|
33
18
|
import '../../types/vue3-xml-viewer.d'
|
|
34
|
-
import { getResourceFilesize } from '../../main'
|
|
35
19
|
|
|
36
20
|
const XmlViewer = defineAsyncComponent(() =>
|
|
37
|
-
import('vue3-xml-viewer').then(
|
|
38
|
-
return module.default || module.XmlViewer
|
|
39
|
-
}),
|
|
21
|
+
import('vue3-xml-viewer').then(module => module.default || module.XmlViewer),
|
|
40
22
|
)
|
|
41
23
|
|
|
42
24
|
const props = defineProps<{
|
|
@@ -44,74 +26,10 @@ const props = defineProps<{
|
|
|
44
26
|
}>()
|
|
45
27
|
|
|
46
28
|
const config = useComponentsConfig()
|
|
47
|
-
const { t } = useTranslation()
|
|
48
29
|
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const fileSizeBytes = computed(() => getResourceFilesize(props.resource))
|
|
55
|
-
|
|
56
|
-
const shouldLoadXml = computed(() => {
|
|
57
|
-
const size = fileSizeBytes.value
|
|
58
|
-
if (!size) {
|
|
59
|
-
// If we don't know the size, don't risk loading a potentially huge file
|
|
60
|
-
return false
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Check if maxXmlPreviewCharSize is configured
|
|
64
|
-
if (!config.maxXmlPreviewCharSize) {
|
|
65
|
-
// If no limit is set, don't load unknown files
|
|
66
|
-
return false
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Convert maxXmlPreviewCharSize from characters to bytes (rough estimate)
|
|
70
|
-
// Assuming average 1 byte per character for XML
|
|
71
|
-
const maxByteSize = config.maxXmlPreviewCharSize
|
|
72
|
-
|
|
73
|
-
return size <= maxByteSize
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
const fetchXmlData = async () => {
|
|
77
|
-
// Check if file is too large or size is unknown before making the request
|
|
78
|
-
if (!shouldLoadXml.value) {
|
|
79
|
-
fileTooLarge.value = true
|
|
80
|
-
return
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
loading.value = true
|
|
84
|
-
error.value = null
|
|
85
|
-
|
|
86
|
-
try {
|
|
87
|
-
const response = await fetch(props.resource.url)
|
|
88
|
-
// const response = await fetch('/test-data.xml') // For testing locally without CORS issues
|
|
89
|
-
if (!response.ok) {
|
|
90
|
-
throw new Error(`HTTP error! status: ${response.status}`)
|
|
91
|
-
}
|
|
92
|
-
const data = await response.text()
|
|
93
|
-
|
|
94
|
-
// Use the XML data as string - let the XML viewer handle large files
|
|
95
|
-
xmlData.value = data
|
|
96
|
-
}
|
|
97
|
-
catch (err) {
|
|
98
|
-
console.error('Error loading XML:', err)
|
|
99
|
-
|
|
100
|
-
if (err instanceof TypeError) {
|
|
101
|
-
error.value = 'network'
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
error.value = 'generic'
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
xmlData.value = null
|
|
108
|
-
}
|
|
109
|
-
finally {
|
|
110
|
-
loading.value = false
|
|
111
|
-
}
|
|
30
|
+
const load = async () => {
|
|
31
|
+
const response = await fetch(props.resource.url)
|
|
32
|
+
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`)
|
|
33
|
+
return response.text()
|
|
112
34
|
}
|
|
113
|
-
|
|
114
|
-
onMounted(() => {
|
|
115
|
-
fetchXmlData()
|
|
116
|
-
})
|
|
117
35
|
</script>
|