@datagouv/components-next 1.0.2-dev.40 → 1.0.2-dev.41
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/dist/{Datafair.client-CYO9vwx6.js → Datafair.client-BAokThtJ.js} +1 -1
- package/dist/JsonPreview.client-DGiaDxVv.js +40 -0
- package/dist/{MapContainer.client-BZsKgRUh.js → MapContainer.client-BKGsAP0Y.js} +2 -2
- package/dist/{PdfPreview.client-ClkseuKU.js → PdfPreview.client-CGjP5ZYb.js} +841 -878
- package/dist/{Pmtiles.client-CUaeaV-O.js → Pmtiles.client-C1I7pwT5.js} +1 -1
- package/dist/PreviewWrapper.vue_vue_type_script_setup_true_lang-BlcvVwW8.js +61 -0
- package/dist/Swagger.client-U7ZDVUHL.js +4 -0
- package/dist/XmlPreview.client-CHUVVEH6.js +34 -0
- package/dist/components-next.js +1 -1
- package/dist/{index-B0fPq7-b.js → index-CzClB3i0.js} +1 -1
- package/dist/{main-ifX24DGW.js → main-CF7lWk6R.js} +8 -8
- package/dist/{vue3-xml-viewer.common-Bkgr-tAS.js → vue3-xml-viewer.common-CAwAbUJl.js} +1 -1
- package/package.json +1 -1
- package/src/components/ResourceAccordion/JsonPreview.client.vue +23 -108
- package/src/components/ResourceAccordion/PdfPreview.client.vue +24 -99
- package/src/components/ResourceAccordion/PreviewWrapper.vue +82 -0
- package/src/components/ResourceAccordion/XmlPreview.client.vue +16 -102
- package/src/main.ts +1 -2
- package/src/types/pages.ts +0 -5
- package/src/types/posts.ts +2 -2
- package/src/types/site.ts +5 -3
- package/dist/JsonPreview.client-B6aU3vl4.js +0 -78
- package/dist/Swagger.client-FpYXdDuX.js +0 -4
- package/dist/XmlPreview.client-BNGHvVnU.js +0 -70
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { defineComponent as ly, ref as cy, computed as dc, useTemplateRef as uy, onMounted as hy, createElementBlock as Mp, openBlock as eh, createBlock as py, withCtx as rm, createTextVNode as nm, toDisplayString as fc, unref as Gs, createCommentVNode as dy, createElementVNode as is, createVNode as fy } from "vue";
|
|
2
|
-
import { c as my, a as gy, d as _y, u as yy, e as xy, f as vy, _ as by, h as wy, i as Ty, K as Sy, t as Py } from "./main-
|
|
2
|
+
import { c as my, a as gy, d as _y, u as yy, e as xy, f as vy, _ as by, h as wy, i as Ty, K as Sy, t as Py } from "./main-CF7lWk6R.js";
|
|
3
3
|
var fn = Uint8Array, Wo = Uint16Array, Iy = Int32Array, mm = new fn([
|
|
4
4
|
0,
|
|
5
5
|
0,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { defineComponent as _, ref as g, computed as h, onMounted as S, nextTick as w, createElementBlock as k, openBlock as l, renderSlot as C, createBlock as n, createCommentVNode as b, toDisplayString as r, unref as a, withCtx as o, createTextVNode as u } from "vue";
|
|
2
|
+
import { a as B, g as E, b as L, _ as c } from "./main-CF7lWk6R.js";
|
|
3
|
+
const R = { class: "text-xs" }, q = {
|
|
4
|
+
key: 1,
|
|
5
|
+
class: "text-gray-medium"
|
|
6
|
+
}, V = /* @__PURE__ */ _({
|
|
7
|
+
__name: "PreviewWrapper",
|
|
8
|
+
props: {
|
|
9
|
+
fileType: {},
|
|
10
|
+
resource: {},
|
|
11
|
+
maxSize: {},
|
|
12
|
+
load: { type: Function }
|
|
13
|
+
},
|
|
14
|
+
emits: ["loaded"],
|
|
15
|
+
setup(s, { emit: x }) {
|
|
16
|
+
const i = s, z = x, { t } = B(), p = g(null), d = g(!1), f = g(null), y = h(() => E(i.resource)), T = h(() => L(i.resource)), v = h(() => {
|
|
17
|
+
const e = y.value, m = i.maxSize;
|
|
18
|
+
return !e || !m ? !1 : e <= m;
|
|
19
|
+
});
|
|
20
|
+
return S(async () => {
|
|
21
|
+
if (!(!v.value || T.value === "blocked")) {
|
|
22
|
+
d.value = !0;
|
|
23
|
+
try {
|
|
24
|
+
p.value = await i.load(), await w(), z("loaded");
|
|
25
|
+
} catch (e) {
|
|
26
|
+
console.error("Error loading preview:", e), f.value = e instanceof TypeError ? "network" : "generic";
|
|
27
|
+
} finally {
|
|
28
|
+
d.value = !1;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}), (e, m) => (l(), k("div", R, [
|
|
32
|
+
p.value !== null ? C(e.$slots, "default", {
|
|
33
|
+
key: 0,
|
|
34
|
+
data: p.value
|
|
35
|
+
}) : d.value ? (l(), k("div", q, r(a(t)("Chargement de l'aperçu {fileType}...", { fileType: s.fileType })), 1)) : v.value ? T.value === "blocked" ? (l(), n(c, { key: 3 }, {
|
|
36
|
+
default: o(() => [
|
|
37
|
+
u(r(a(t)("Ce fichier {fileType} ne peut pas être prévisualisé car il est hébergé sur un site distant qui restreint l'accès (CORS). Téléchargez-le depuis l'onglet Téléchargements.", { fileType: s.fileType })), 1)
|
|
38
|
+
]),
|
|
39
|
+
_: 1
|
|
40
|
+
})) : f.value === "network" ? (l(), n(c, { key: 4 }, {
|
|
41
|
+
default: o(() => [
|
|
42
|
+
u(r(a(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.")), 1)
|
|
43
|
+
]),
|
|
44
|
+
_: 1
|
|
45
|
+
})) : f.value ? (l(), n(c, { key: 5 }, {
|
|
46
|
+
default: o(() => [
|
|
47
|
+
u(r(a(t)("L'aperçu de ce fichier n'a pas pu être chargé. Téléchargez-le depuis l'onglet Téléchargements.")), 1)
|
|
48
|
+
]),
|
|
49
|
+
_: 1
|
|
50
|
+
})) : b("", !0) : (l(), n(c, { key: 2 }, {
|
|
51
|
+
default: o(() => [
|
|
52
|
+
u(r(y.value ? a(t)("Le fichier {fileType} est trop volumineux pour être prévisualisé. Téléchargez-le depuis l'onglet Téléchargements.", { fileType: s.fileType }) : a(t)("La taille du fichier est inconnue, l'aperçu n'est pas disponible. Téléchargez-le depuis l'onglet Téléchargements.")), 1)
|
|
53
|
+
]),
|
|
54
|
+
_: 1
|
|
55
|
+
}))
|
|
56
|
+
]));
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
export {
|
|
60
|
+
V as _
|
|
61
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { defineComponent as i, defineAsyncComponent as m, createBlock as u, openBlock as f, unref as t, withCtx as l, createVNode as p } from "vue";
|
|
2
|
+
import { u as x } from "./main-CF7lWk6R.js";
|
|
3
|
+
import { _ as w } from "./PreviewWrapper.vue_vue_type_script_setup_true_lang-BlcvVwW8.js";
|
|
4
|
+
const X = /* @__PURE__ */ i({
|
|
5
|
+
__name: "XmlPreview.client",
|
|
6
|
+
props: {
|
|
7
|
+
resource: {}
|
|
8
|
+
},
|
|
9
|
+
setup(r) {
|
|
10
|
+
const o = m(
|
|
11
|
+
() => import("./vue3-xml-viewer.common-CAwAbUJl.js").then((e) => e.v).then((e) => e.default || e.XmlViewer)
|
|
12
|
+
), n = r, s = x(), c = async () => {
|
|
13
|
+
const e = await fetch(n.resource.url);
|
|
14
|
+
if (!e.ok) throw new Error(`HTTP error! status: ${e.status}`);
|
|
15
|
+
return e.text();
|
|
16
|
+
};
|
|
17
|
+
return (e, _) => (f(), u(w, {
|
|
18
|
+
"file-type": "XML",
|
|
19
|
+
resource: r.resource,
|
|
20
|
+
"max-size": t(s).maxXmlPreviewCharSize,
|
|
21
|
+
load: c
|
|
22
|
+
}, {
|
|
23
|
+
default: l(({ data: a }) => [
|
|
24
|
+
p(t(o), {
|
|
25
|
+
xml: a
|
|
26
|
+
}, null, 8, ["xml"])
|
|
27
|
+
]),
|
|
28
|
+
_: 1
|
|
29
|
+
}, 8, ["resource", "max-size"]));
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
export {
|
|
33
|
+
X as default
|
|
34
|
+
};
|
package/dist/components-next.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { aU as e, bd as t, y as r, z as o, A as i, B as n, C as c, D as l, i as g, bb as u, be as b, E as d, aT as T, aS as S, F as p, G as C, M as D, H as m, Q as O, R, S as E, T as I, U as f, L as y, J as A, I as h, V as M, O as v, N as z, P as L, W as w, aC as G, bf as P, X as N, Y as _, Z as B, $ as H, a1 as k, bt as U, bg as x, a2 as F, a3 as V, a4 as Q, a5 as W, a6 as Y, a7 as j, bc as q, a8 as X, a9 as J, aa as Z, ac as $, ab as K, br as aa, ad as sa, ae as ea, af as ta, ag as ra, ah as oa, ai as ia, aj as na, ak as ca, al as la, am as ga, an as ua, ao as ba, aD as da, aE as Ta, aF as Sa, ap as pa, aq as Ca, ar as Da, j as ma, as as Oa, at as Ra, au as Ea, av as Ia, aw as fa, a0 as ya, aG as Aa, ay as ha, ax as Ma, az as va, aA as za, bh as La, aB as wa, bG as Ga, bI as Pa, b8 as Na, b6 as _a, x as Ba, bH as Ha, s as ka, r as Ua, w as xa, v as Fa, bu as Va, aY as Qa, aL as Wa, aW as Ya, bl as ja, bC as qa, aZ as Xa, aQ as Ja, b9 as Za, b7 as $a, aR as Ka, m as as, l as ss, q as es, o as ts, n as rs, p as os, aV as is, b3 as ns, b5 as cs, bo as ls, bm as gs, bk as us, f as bs, e as ds, b as Ts, bw as Ss, g as ps, bp as Cs, bs as Ds, bq as ms, ba as Os, bB as Rs, bz as Es, by as Is, bj as fs, bv as ys, bn as As, bi as hs, aN as Ms, b0 as vs, b1 as zs, b2 as Ls, aM as ws, a_ as Gs, a_ as Ps, a$ as Ns, aX as _s, aO as Bs, t as Hs, aH as ks, b4 as Us, aI as xs, u as Fs, bx as Vs, d as Qs, bA as Ws, bD as Ys, bE as js, bF as qs, aP as Xs, aJ as Js, aK as Zs, a as $s } from "./main-
|
|
1
|
+
import { aU as e, bd as t, y as r, z as o, A as i, B as n, C as c, D as l, i as g, bb as u, be as b, E as d, aT as T, aS as S, F as p, G as C, M as D, H as m, Q as O, R, S as E, T as I, U as f, L as y, J as A, I as h, V as M, O as v, N as z, P as L, W as w, aC as G, bf as P, X as N, Y as _, Z as B, $ as H, a1 as k, bt as U, bg as x, a2 as F, a3 as V, a4 as Q, a5 as W, a6 as Y, a7 as j, bc as q, a8 as X, a9 as J, aa as Z, ac as $, ab as K, br as aa, ad as sa, ae as ea, af as ta, ag as ra, ah as oa, ai as ia, aj as na, ak as ca, al as la, am as ga, an as ua, ao as ba, aD as da, aE as Ta, aF as Sa, ap as pa, aq as Ca, ar as Da, j as ma, as as Oa, at as Ra, au as Ea, av as Ia, aw as fa, a0 as ya, aG as Aa, ay as ha, ax as Ma, az as va, aA as za, bh as La, aB as wa, bG as Ga, bI as Pa, b8 as Na, b6 as _a, x as Ba, bH as Ha, s as ka, r as Ua, w as xa, v as Fa, bu as Va, aY as Qa, aL as Wa, aW as Ya, bl as ja, bC as qa, aZ as Xa, aQ as Ja, b9 as Za, b7 as $a, aR as Ka, m as as, l as ss, q as es, o as ts, n as rs, p as os, aV as is, b3 as ns, b5 as cs, bo as ls, bm as gs, bk as us, f as bs, e as ds, b as Ts, bw as Ss, g as ps, bp as Cs, bs as Ds, bq as ms, ba as Os, bB as Rs, bz as Es, by as Is, bj as fs, bv as ys, bn as As, bi as hs, aN as Ms, b0 as vs, b1 as zs, b2 as Ls, aM as ws, a_ as Gs, a_ as Ps, a$ as Ns, aX as _s, aO as Bs, t as Hs, aH as ks, b4 as Us, aI as xs, u as Fs, bx as Vs, d as Qs, bA as Ws, bD as Ys, bE as js, bF as qs, aP as Xs, aJ as Js, aK as Zs, a as $s } from "./main-CF7lWk6R.js";
|
|
2
2
|
export {
|
|
3
3
|
e as AI_SUGGESTION_MIN_DESCRIPTION_LENGTH,
|
|
4
4
|
t as ASSOCIATION,
|
|
@@ -6,7 +6,7 @@ import { a as TileGrid, U as UrlTile, e as extentFromProjection, c as createXYZ,
|
|
|
6
6
|
import { D as DEFAULT_MAX_ZOOM, a as assert, f as forEach, i as intersectsLineString, b as intersectsLineStringArray, l as linearRingssContainsXY, c as intersectsLinearRingMultiArray, d as compose, e as create, g as apply, s as setFromArray, m as multiply, h as scale, r as reset, t as translate } from "./common-PJfpC179.js";
|
|
7
7
|
import { R as RBush$1, C as Collection, a as CollectionEventType, b as asColorLike, d as defaultFillStyle, c as defaultStrokeStyle, e as defaultLineCap, f as defaultLineDash, g as defaultLineDashOffset, h as defaultLineJoin, i as defaultLineWidth, j as defaultMiterLimit, k as defaultPadding, l as defaultTextBaseline, m as defaultTextAlign, n as defaultFont, r as registerFont, o as getTextDimensions, p as drawImageOrLabel, q as measureAndCacheTextWidth, I as Icon, B as BaseVectorLayer, P as PointerInteraction, s as noModifierKeys, t as always, u as shiftKeyOnly, v as InteractionProperty, M as MapBrowserEventType, w as MapBrowserEvent, x as never, y as createEditingStyle, z as primaryAction, A as altKeyOnly, D as singleClick, E as Interaction, F as Fill, S as Stroke, T as Text, G as Style$1, H as CircleStyle, J as checkedFonts, K as Map$1, L as pointerMove, N as ImageStyle, O as Attribution, Z as Zoom, Q as MapProperty } from "./Map-BjUnLyj8.js";
|
|
8
8
|
import { S as SimpleGeometry, d as deflateCoordinate, r as rotate, G as Geometry, m as maxSquaredDelta, a as assignClosestPoint, i as inflateCoordinates, b as douglasPeucker, c as deflateCoordinates, e as arrayMaxSquaredDelta, f as assignClosestArrayPoint, g as inflateCoordinatesArray, h as douglasPeuckerArray, j as deflateCoordinatesArray, P as Point$1, k as multiArrayMaxSquaredDelta, l as assignClosestMultiArrayPoint, n as linearRingss$1, o as orientLinearRingsArray, p as inflateMultiCoordinatesArray, q as getInteriorPointsOfMultiArray, s as linearRingssAreOriented, t as quantizeMultiArray, u as Polygon, v as deflateMultiCoordinatesArray, w as getInteriorPointOfArray, x as inflateEnds, y as transform2D, z as quantizeArray, A as snap, B as transformGeom2D, V as ViewHint, C as getStrideForLayout, D as linearRingsAreOriented, E as orientLinearRings, F as getLayoutForStride, L as LinearRing, H as View, I as ViewProperty, J as fromExtent } from "./View-BR92hTWP.js";
|
|
9
|
-
import { k as commonjsGlobal, c as getDefaultExportFromCjs$1 } from "./main-
|
|
9
|
+
import { k as commonjsGlobal, c as getDefaultExportFromCjs$1 } from "./main-CF7lWk6R.js";
|
|
10
10
|
import { E as EventType$1, a as asArray } from "./Event--kp8kMdJ.js";
|
|
11
11
|
import { Z as ZIndexContext, C as CanvasLayerRenderer, c as canvasPool$1, T as TileLayer, a as CanvasTileLayerRenderer, b as TileProperty } from "./Tile-DbNFNPfU.js";
|
|
12
12
|
function padNumber(i, e, t) {
|
|
@@ -93702,7 +93702,7 @@ const TMe = /* @__PURE__ */ tp(JD), OMe = /* @__PURE__ */ ole({
|
|
|
93702
93702
|
canEdit: { type: Boolean, default: !1 }
|
|
93703
93703
|
},
|
|
93704
93704
|
setup(e) {
|
|
93705
|
-
const t = ["parquet", "pmtiles", "geojson"], n = ["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"], o = e, u = Rn(), f = pa(() => import("./Swagger.client-
|
|
93705
|
+
const t = ["parquet", "pmtiles", "geojson"], n = ["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"], o = e, u = Rn(), f = pa(() => import("./Swagger.client-U7ZDVUHL.js")), c = pa(() => import("./MapContainer.client-BKGsAP0Y.js")), d = pa(() => import("./Pmtiles.client-C1I7pwT5.js")), a = pa(() => import("./JsonPreview.client-DGiaDxVv.js")), h = pa(() => import("./PdfPreview.client-CGjP5ZYb.js")), g = pa(() => import("./XmlPreview.client-CHUVVEH6.js")), m = pa(() => import("./Datafair.client-BAokThtJ.js")), { t: w } = C2(), { formatRelativeIfRecentDate: y } = Ia(), x = jD(), H = s1(() => {
|
|
93706
93706
|
const d1 = o.resource.format?.toLowerCase();
|
|
93707
93707
|
return d1 === "json" || d1 === "pdf" || d1 === "xml";
|
|
93708
93708
|
}), E = s1(() => x(o.resource)), z = s1(() => o.resource.extras["analysis:parsing:pmtiles_url"] || o.resource.format === "pmtiles"), Z = s1(() => kh(o.dataset.organization) && o.resource.extras.datafairEmbed), R = s1(() => kh(o.dataset.organization) && o.resource.extras.apidocUrl), T = s1(() => Wb(o.resource.format) ? o.resource.format : w("Fichier")), B = s1(() => DD(o.resource)), D = s1(() => B.value === "wms"), U = s1(() => {
|
|
@@ -94313,19 +94313,19 @@ const G_e = { class: "border border-gray-default" }, Y_e = { class: "p-4 flex fl
|
|
|
94313
94313
|
},
|
|
94314
94314
|
setup(e) {
|
|
94315
94315
|
const t = pa(
|
|
94316
|
-
() => import("./JsonPreview.client-
|
|
94316
|
+
() => import("./JsonPreview.client-DGiaDxVv.js")
|
|
94317
94317
|
), n = pa(
|
|
94318
|
-
() => import("./PdfPreview.client-
|
|
94318
|
+
() => import("./PdfPreview.client-CGjP5ZYb.js")
|
|
94319
94319
|
), o = pa(
|
|
94320
|
-
() => import("./XmlPreview.client-
|
|
94320
|
+
() => import("./XmlPreview.client-CHUVVEH6.js")
|
|
94321
94321
|
), u = pa(
|
|
94322
|
-
() => import("./Datafair.client-
|
|
94322
|
+
() => import("./Datafair.client-BAokThtJ.js")
|
|
94323
94323
|
), f = pa(
|
|
94324
|
-
() => import("./MapContainer.client-
|
|
94324
|
+
() => import("./MapContainer.client-BKGsAP0Y.js")
|
|
94325
94325
|
), c = pa(
|
|
94326
|
-
() => import("./Pmtiles.client-
|
|
94326
|
+
() => import("./Pmtiles.client-C1I7pwT5.js")
|
|
94327
94327
|
), d = pa(
|
|
94328
|
-
() => import("./Swagger.client-
|
|
94328
|
+
() => import("./Swagger.client-U7ZDVUHL.js")
|
|
94329
94329
|
), a = e, { t: h } = C2(), g = Rn(), { formatRelativeIfRecentDate: m } = Ia(), {
|
|
94330
94330
|
hasTabularData: w,
|
|
94331
94331
|
hasPmtiles: y,
|
package/package.json
CHANGED
|
@@ -1,51 +1,31 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
</div>
|
|
20
|
-
<PreviewUnavailable v-else-if="fileTooLarge">
|
|
21
|
-
{{ fileSizeBytes
|
|
22
|
-
? t("Le fichier JSON est trop volumineux pour être prévisualisé. Téléchargez-le depuis l'onglet Téléchargements.")
|
|
23
|
-
: t("La taille du fichier est inconnue, l'aperçu n'est pas disponible. Téléchargez-le depuis l'onglet Téléchargements.")
|
|
24
|
-
}}
|
|
25
|
-
</PreviewUnavailable>
|
|
26
|
-
<PreviewUnavailable v-else-if="error === 'cors'">
|
|
27
|
-
{{ t("Ce fichier JSON ne peut pas être prévisualisé car il est hébergé sur un site distant qui restreint l'accès (CORS). Téléchargez-le depuis l'onglet Téléchargements.") }}
|
|
28
|
-
</PreviewUnavailable>
|
|
29
|
-
<PreviewUnavailable v-else-if="error === 'network'">
|
|
30
|
-
{{ 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.") }}
|
|
31
|
-
</PreviewUnavailable>
|
|
32
|
-
<PreviewUnavailable v-else-if="error">
|
|
33
|
-
{{ t("L'aperçu de ce fichier n'a pas pu être chargé. Téléchargez-le depuis l'onglet Téléchargements.") }}
|
|
34
|
-
</PreviewUnavailable>
|
|
35
|
-
</div>
|
|
2
|
+
<PreviewWrapper
|
|
3
|
+
v-slot="{ data }"
|
|
4
|
+
file-type="JSON"
|
|
5
|
+
:resource="resource"
|
|
6
|
+
:max-size="config.maxJsonPreviewCharSize"
|
|
7
|
+
:load="load"
|
|
8
|
+
>
|
|
9
|
+
<JsonViewer
|
|
10
|
+
:value="data"
|
|
11
|
+
boxed
|
|
12
|
+
sort
|
|
13
|
+
theme="light"
|
|
14
|
+
:max-depth="3"
|
|
15
|
+
:expand-depth="2"
|
|
16
|
+
:indent-width="2"
|
|
17
|
+
/>
|
|
18
|
+
</PreviewWrapper>
|
|
36
19
|
</template>
|
|
37
20
|
|
|
38
21
|
<script setup lang="ts">
|
|
39
|
-
import {
|
|
22
|
+
import { defineAsyncComponent } from 'vue'
|
|
40
23
|
import { useComponentsConfig } from '../../config'
|
|
41
|
-
import
|
|
24
|
+
import PreviewWrapper from './PreviewWrapper.vue'
|
|
42
25
|
import type { Resource } from '../../types/resources'
|
|
43
|
-
import { getResourceFilesize, getResourceCorsStatus } from '../../functions/resources'
|
|
44
|
-
import { useTranslation } from '../../composables/useTranslation'
|
|
45
26
|
|
|
46
27
|
const JsonViewer = defineAsyncComponent(() =>
|
|
47
28
|
import('vue3-json-viewer').then((module) => {
|
|
48
|
-
// Import CSS when component loads
|
|
49
29
|
import('vue3-json-viewer/dist/vue3-json-viewer.css')
|
|
50
30
|
return module.JsonViewer
|
|
51
31
|
}),
|
|
@@ -56,75 +36,10 @@ const props = defineProps<{
|
|
|
56
36
|
}>()
|
|
57
37
|
|
|
58
38
|
const config = useComponentsConfig()
|
|
59
|
-
const { t } = useTranslation()
|
|
60
39
|
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const fileSizeBytes = computed(() => getResourceFilesize(props.resource))
|
|
67
|
-
|
|
68
|
-
const corsStatus = computed(() => getResourceCorsStatus(props.resource))
|
|
69
|
-
|
|
70
|
-
const isSizeAllowed = computed(() => {
|
|
71
|
-
const size = fileSizeBytes.value
|
|
72
|
-
// Convert maxJsonPreviewCharSize from characters to bytes (rough estimate)
|
|
73
|
-
// Assuming average 1 byte per character for JSON
|
|
74
|
-
const maxByteSize = config.maxJsonPreviewCharSize
|
|
75
|
-
|
|
76
|
-
// If we don't know the size or the max size, don't risk loading a potentially huge file
|
|
77
|
-
if (!size || !maxByteSize) return false
|
|
78
|
-
|
|
79
|
-
return size <= maxByteSize
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
const fetchJsonData = async () => {
|
|
83
|
-
error.value = null
|
|
84
|
-
fileTooLarge.value = false
|
|
85
|
-
|
|
86
|
-
// Check if file is too large or size is unknown
|
|
87
|
-
if (!isSizeAllowed.value) {
|
|
88
|
-
fileTooLarge.value = true
|
|
89
|
-
return
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Check if CORS is allowed
|
|
93
|
-
if (corsStatus.value === 'blocked') {
|
|
94
|
-
error.value = 'cors'
|
|
95
|
-
return
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
loading.value = true
|
|
99
|
-
try {
|
|
100
|
-
const response = await fetch(props.resource.url)
|
|
101
|
-
// const response = await fetch('/test-data.json') // For testing locally without CORS issues
|
|
102
|
-
if (!response.ok) {
|
|
103
|
-
throw new Error(`HTTP error! status: ${response.status}`)
|
|
104
|
-
}
|
|
105
|
-
const data = await response.json()
|
|
106
|
-
|
|
107
|
-
// Use the original data directly - let the JSON viewer handle large files
|
|
108
|
-
jsonData.value = data
|
|
109
|
-
}
|
|
110
|
-
catch (err) {
|
|
111
|
-
console.error('Error loading JSON:', err)
|
|
112
|
-
|
|
113
|
-
if (err instanceof TypeError) {
|
|
114
|
-
error.value = 'network'
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
error.value = 'generic'
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
jsonData.value = null
|
|
121
|
-
}
|
|
122
|
-
finally {
|
|
123
|
-
loading.value = false
|
|
124
|
-
}
|
|
40
|
+
const load = async () => {
|
|
41
|
+
const response = await fetch(props.resource.url)
|
|
42
|
+
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`)
|
|
43
|
+
return response.json()
|
|
125
44
|
}
|
|
126
|
-
|
|
127
|
-
onMounted(() => {
|
|
128
|
-
fetchJsonData()
|
|
129
|
-
})
|
|
130
45
|
</script>
|
|
@@ -1,51 +1,34 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<PreviewWrapper
|
|
3
|
+
v-slot="{ data }"
|
|
4
|
+
file-type="PDF"
|
|
5
|
+
:resource="resource"
|
|
6
|
+
:max-size="config.maxPdfPreviewByteSize"
|
|
7
|
+
:load="load"
|
|
8
|
+
@loaded="renderAllPages"
|
|
9
|
+
>
|
|
3
10
|
<div
|
|
4
|
-
v-if="pdfReady"
|
|
5
11
|
ref="containerRef"
|
|
6
12
|
class="w-full overflow-y-auto max-h-[80vh] space-y-3"
|
|
7
13
|
>
|
|
8
14
|
<canvas
|
|
9
|
-
v-for="page in
|
|
15
|
+
v-for="page in (data as PDFDocumentProxy).numPages"
|
|
10
16
|
:key="page"
|
|
11
17
|
:ref="(el) => setCanvasRef(el as HTMLCanvasElement, page)"
|
|
12
18
|
class="w-full"
|
|
13
19
|
/>
|
|
14
20
|
</div>
|
|
15
|
-
|
|
16
|
-
v-else-if="loading"
|
|
17
|
-
class="text-gray-medium"
|
|
18
|
-
>
|
|
19
|
-
{{ t("Chargement de l'aperçu PDF...") }}
|
|
20
|
-
</div>
|
|
21
|
-
<PreviewUnavailable v-else-if="fileTooLarge">
|
|
22
|
-
{{ fileSizeBytes
|
|
23
|
-
? t("Le fichier PDF est trop volumineux pour être prévisualisé. Téléchargez-le depuis l'onglet Téléchargements.")
|
|
24
|
-
: t("La taille du fichier est inconnue, l'aperçu n'est pas disponible. Téléchargez-le depuis l'onglet Téléchargements.")
|
|
25
|
-
}}
|
|
26
|
-
</PreviewUnavailable>
|
|
27
|
-
<PreviewUnavailable v-else-if="error === 'cors'">
|
|
28
|
-
{{ t("Ce fichier PDF ne peut pas être prévisualisé car il est hébergé sur un site distant qui restreint l'accès (CORS). Téléchargez-le depuis l'onglet Téléchargements.") }}
|
|
29
|
-
</PreviewUnavailable>
|
|
30
|
-
<PreviewUnavailable v-else-if="error === 'network'">
|
|
31
|
-
{{ 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.") }}
|
|
32
|
-
</PreviewUnavailable>
|
|
33
|
-
<PreviewUnavailable v-else-if="error">
|
|
34
|
-
{{ t("L'aperçu de ce fichier n'a pas pu être chargé. Téléchargez-le depuis l'onglet Téléchargements.") }}
|
|
35
|
-
</PreviewUnavailable>
|
|
36
|
-
</div>
|
|
21
|
+
</PreviewWrapper>
|
|
37
22
|
</template>
|
|
38
23
|
|
|
39
24
|
<script setup lang="ts">
|
|
40
|
-
import {
|
|
25
|
+
import { onBeforeUnmount, ref } from 'vue'
|
|
41
26
|
import * as pdfjsLib from 'pdfjs-dist'
|
|
42
27
|
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.min.mjs?url'
|
|
43
28
|
import type { PDFDocumentProxy } from 'pdfjs-dist'
|
|
44
|
-
import
|
|
29
|
+
import PreviewWrapper from './PreviewWrapper.vue'
|
|
45
30
|
import { useComponentsConfig } from '../../config'
|
|
46
31
|
import type { Resource } from '../../types/resources'
|
|
47
|
-
import { getResourceFilesize, getResourceCorsStatus } from '../../functions/resources'
|
|
48
|
-
import { useTranslation } from '../../composables/useTranslation'
|
|
49
32
|
|
|
50
33
|
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker
|
|
51
34
|
|
|
@@ -54,15 +37,8 @@ const props = defineProps<{
|
|
|
54
37
|
}>()
|
|
55
38
|
|
|
56
39
|
const config = useComponentsConfig()
|
|
57
|
-
const { t } = useTranslation()
|
|
58
40
|
|
|
59
41
|
const containerRef = ref<HTMLElement | null>(null)
|
|
60
|
-
const pdfReady = ref(false)
|
|
61
|
-
const loading = ref(false)
|
|
62
|
-
const error = ref<string | null>(null)
|
|
63
|
-
const fileTooLarge = ref(false)
|
|
64
|
-
const totalPages = ref(0)
|
|
65
|
-
|
|
66
42
|
let pdfDoc: PDFDocumentProxy | null = null
|
|
67
43
|
const canvasRefs = new Map<number, HTMLCanvasElement>()
|
|
68
44
|
|
|
@@ -98,73 +74,22 @@ async function renderPage(pageNum: number) {
|
|
|
98
74
|
}).promise
|
|
99
75
|
}
|
|
100
76
|
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return false
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Use maxPdfPreviewByteSize from config, fallback to 10 MB if not set
|
|
113
|
-
const maxByteSize = config.maxPdfPreviewByteSize ?? 10_000_000
|
|
114
|
-
return size <= maxByteSize
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
const loadPdf = async () => {
|
|
118
|
-
error.value = null
|
|
119
|
-
fileTooLarge.value = false
|
|
120
|
-
|
|
121
|
-
if (!shouldLoadPdf.value) {
|
|
122
|
-
fileTooLarge.value = true
|
|
123
|
-
return
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Check if CORS is allowed
|
|
127
|
-
if (corsStatus.value === 'blocked') {
|
|
128
|
-
error.value = 'cors'
|
|
129
|
-
return
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
loading.value = true
|
|
133
|
-
try {
|
|
134
|
-
const loadingTask = pdfjsLib.getDocument({
|
|
135
|
-
url: props.resource.url,
|
|
136
|
-
isEvalSupported: false,
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
pdfDoc = await loadingTask.promise
|
|
140
|
-
totalPages.value = pdfDoc.numPages
|
|
141
|
-
pdfReady.value = true
|
|
142
|
-
|
|
143
|
-
await nextTick()
|
|
77
|
+
const load = async () => {
|
|
78
|
+
const loadingTask = pdfjsLib.getDocument({
|
|
79
|
+
url: props.resource.url,
|
|
80
|
+
isEvalSupported: false,
|
|
81
|
+
})
|
|
82
|
+
pdfDoc = await loadingTask.promise
|
|
83
|
+
return pdfDoc
|
|
84
|
+
}
|
|
144
85
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
catch (err) {
|
|
150
|
-
console.error('Error loading PDF:', err)
|
|
151
|
-
|
|
152
|
-
if (err instanceof TypeError) {
|
|
153
|
-
error.value = 'network'
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
error.value = 'generic'
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
finally {
|
|
160
|
-
loading.value = false
|
|
86
|
+
const renderAllPages = async () => {
|
|
87
|
+
if (!pdfDoc) return
|
|
88
|
+
for (let i = 1; i <= pdfDoc.numPages; i++) {
|
|
89
|
+
await renderPage(i)
|
|
161
90
|
}
|
|
162
91
|
}
|
|
163
92
|
|
|
164
|
-
onMounted(() => {
|
|
165
|
-
loadPdf()
|
|
166
|
-
})
|
|
167
|
-
|
|
168
93
|
onBeforeUnmount(() => {
|
|
169
94
|
pdfDoc?.destroy()
|
|
170
95
|
})
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="text-xs">
|
|
3
|
+
<slot
|
|
4
|
+
v-if="data !== null"
|
|
5
|
+
:data="data"
|
|
6
|
+
/>
|
|
7
|
+
<div
|
|
8
|
+
v-else-if="loading"
|
|
9
|
+
class="text-gray-medium"
|
|
10
|
+
>
|
|
11
|
+
{{ t("Chargement de l'aperçu {fileType}...", { fileType }) }}
|
|
12
|
+
</div>
|
|
13
|
+
<PreviewUnavailable v-else-if="!isSizeAllowed">
|
|
14
|
+
{{ fileSizeBytes
|
|
15
|
+
? t("Le fichier {fileType} est trop volumineux pour être prévisualisé. Téléchargez-le depuis l'onglet Téléchargements.", { fileType })
|
|
16
|
+
: t("La taille du fichier est inconnue, l'aperçu n'est pas disponible. Téléchargez-le depuis l'onglet Téléchargements.")
|
|
17
|
+
}}
|
|
18
|
+
</PreviewUnavailable>
|
|
19
|
+
<PreviewUnavailable v-else-if="corsStatus === 'blocked'">
|
|
20
|
+
{{ t("Ce fichier {fileType} ne peut pas être prévisualisé car il est hébergé sur un site distant qui restreint l'accès (CORS). Téléchargez-le depuis l'onglet Téléchargements.", { fileType }) }}
|
|
21
|
+
</PreviewUnavailable>
|
|
22
|
+
<PreviewUnavailable v-else-if="error === 'network'">
|
|
23
|
+
{{ 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.") }}
|
|
24
|
+
</PreviewUnavailable>
|
|
25
|
+
<PreviewUnavailable v-else-if="error">
|
|
26
|
+
{{ t("L'aperçu de ce fichier n'a pas pu être chargé. Téléchargez-le depuis l'onglet Téléchargements.") }}
|
|
27
|
+
</PreviewUnavailable>
|
|
28
|
+
</div>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script setup lang="ts">
|
|
32
|
+
import { computed, nextTick, onMounted, ref } from 'vue'
|
|
33
|
+
import PreviewUnavailable from './PreviewUnavailable.vue'
|
|
34
|
+
import type { Resource } from '../../types/resources'
|
|
35
|
+
import { getResourceFilesize, getResourceCorsStatus } from '../../functions/resources'
|
|
36
|
+
import { useTranslation } from '../../composables/useTranslation'
|
|
37
|
+
|
|
38
|
+
const props = defineProps<{
|
|
39
|
+
fileType: string
|
|
40
|
+
resource: Resource
|
|
41
|
+
maxSize: number | undefined
|
|
42
|
+
load: () => Promise<unknown>
|
|
43
|
+
}>()
|
|
44
|
+
|
|
45
|
+
const emit = defineEmits<{
|
|
46
|
+
loaded: []
|
|
47
|
+
}>()
|
|
48
|
+
|
|
49
|
+
const { t } = useTranslation()
|
|
50
|
+
|
|
51
|
+
const data = ref<unknown>(null)
|
|
52
|
+
const loading = ref(false)
|
|
53
|
+
const error = ref<'network' | 'generic' | null>(null)
|
|
54
|
+
|
|
55
|
+
const fileSizeBytes = computed(() => getResourceFilesize(props.resource))
|
|
56
|
+
const corsStatus = computed(() => getResourceCorsStatus(props.resource))
|
|
57
|
+
|
|
58
|
+
const isSizeAllowed = computed(() => {
|
|
59
|
+
const size = fileSizeBytes.value
|
|
60
|
+
const max = props.maxSize
|
|
61
|
+
if (!size || !max) return false
|
|
62
|
+
return size <= max
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
onMounted(async () => {
|
|
66
|
+
if (!isSizeAllowed.value || corsStatus.value === 'blocked') return
|
|
67
|
+
|
|
68
|
+
loading.value = true
|
|
69
|
+
try {
|
|
70
|
+
data.value = await props.load()
|
|
71
|
+
await nextTick()
|
|
72
|
+
emit('loaded')
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
console.error('Error loading preview:', err)
|
|
76
|
+
error.value = err instanceof TypeError ? 'network' : 'generic'
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
loading.value = false
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
</script>
|