@eodash/eodash 5.0.0-rc.2.5 → 5.0.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.
- package/core/client/composables/DefineWidgets.js +8 -1
- package/core/client/eodash.js +9 -9
- package/core/client/eodashSTAC/createLayers.js +4 -18
- package/core/client/eodashSTAC/helpers.js +23 -0
- package/core/client/store/stac.js +3 -1
- package/core/client/types.ts +125 -19
- package/core/client/utils/states.js +9 -0
- package/dist/client/{DashboardLayout-BX3Sm_Vx.js → DashboardLayout-CkWvOMOW.js} +2 -2
- package/dist/client/{DynamicWebComponent-BqoHM1np.js → DynamicWebComponent-DYBbpvUK.js} +1 -1
- package/dist/client/{EodashDatePicker-BoWV2vc8.js → EodashDatePicker-CALmW3SI.js} +3 -83
- package/dist/client/{EodashItemFilter-127fZLyK.js → EodashItemFilter-DlQiE713.js} +1 -1
- package/dist/client/{EodashLayerControl-B-pZaizw.js → EodashLayerControl-DEzEbft7.js} +8 -2
- package/dist/client/{EodashLayoutSwitcher-DwexHfOD.js → EodashLayoutSwitcher-CDeCV8F-.js} +2 -2
- package/dist/client/{EodashMapBtns-Jfn3bpWD.js → EodashMapBtns-CktQCfa-.js} +36 -12
- package/dist/client/{EodashStacInfo-STq_bW7S.js → EodashStacInfo-DPPxDkF6.js} +7 -1
- package/dist/client/{EodashTools-uxSuJhVJ.js → EodashTools-CUaL9s4H.js} +5 -4
- package/dist/client/{ExportState-Ckcb6u01.js → ExportState-DjyIZVhl.js} +27 -12
- package/dist/client/{Footer-C8JP-coH.js → Footer-DyL0JoWt.js} +1 -1
- package/dist/client/{Header-Dxx7q9FW.js → Header-B5Dgty9l.js} +3 -3
- package/dist/client/{MobileLayout-BE19Peep.js → MobileLayout-CRsg_5Q4.js} +5 -5
- package/dist/client/{PopUp-D3IyjsN4.js → PopUp-BfB8s_ki.js} +3 -3
- package/dist/client/ProcessList-DTefwQZx.js +484 -0
- package/dist/client/{VImg-BmCNSu3X.js → VImg-FD1WVphJ.js} +2 -2
- package/dist/client/{VMain-eZDKIfmJ.js → VMain-DJKG4SvM.js} +1 -1
- package/dist/client/{VOverlay-BS-E4Z6g.js → VOverlay-BzOdRu9h.js} +15 -6
- package/dist/client/{VTooltip-BMsliOuh.js → VTooltip-CfeefrXI.js} +3 -3
- package/dist/client/{WidgetsContainer-Cl6M5R5c.js → WidgetsContainer-C2TaTdb6.js} +1 -1
- package/dist/client/{asWebComponent-Df8nUiLs.js → asWebComponent-CLhcT715.js} +100 -96
- package/dist/client/eo-dash.css +2 -2
- package/dist/client/eo-dash.js +1 -1
- package/dist/client/{forwardRefs-lhDuXD-N.js → forwardRefs-Bon_Kku1.js} +9 -9
- package/dist/client/index-4CT7Tz83.js +85 -0
- package/dist/client/{index-Bt5GEGxl.js → index-Bm9cbtx5.js} +1 -1
- package/dist/client/{EodashMap-BSR7_wRA.js → index-CIHH_3dW.js} +101 -80
- package/dist/client/{EodashProcess-CpbZPYBp.js → index-DiGDvTQU.js} +346 -468
- package/dist/client/{transition-DHEuQX4I.js → transition-C5I57hn6.js} +1 -1
- package/dist/types/core/client/components/MobileLayout.vue.d.ts +9 -9
- package/dist/types/core/client/eodashSTAC/helpers.d.ts +3 -2
- package/dist/types/core/client/types.d.ts +83 -17
- package/dist/types/core/client/utils/states.d.ts +7 -0
- package/dist/types/widgets/EodashDatePicker.vue.d.ts +4 -4
- package/dist/types/widgets/EodashItemFilter.vue.d.ts +18 -18
- package/dist/types/widgets/EodashLayerControl.vue.d.ts +2 -2
- package/dist/types/widgets/EodashLayoutSwitcher.vue.d.ts +2 -2
- package/dist/types/widgets/EodashMap/methods/create-layers-config.d.ts +9 -0
- package/dist/types/widgets/EodashMap/methods/index.d.ts +5 -0
- package/dist/types/widgets/EodashMapBtns.vue.d.ts +8 -2
- package/dist/types/widgets/EodashProcess/ProcessList.vue.d.ts +2 -0
- package/dist/types/widgets/EodashProcess/methods/async.d.ts +45 -0
- package/dist/types/widgets/EodashProcess/methods/composables.d.ts +19 -0
- package/dist/types/widgets/EodashProcess/methods/handling.d.ts +78 -0
- package/dist/types/widgets/EodashProcess/methods/outputs.d.ts +54 -0
- package/dist/types/widgets/EodashProcess/methods/utils.d.ts +42 -0
- package/dist/types/widgets/EodashStacInfo.vue.d.ts +12 -12
- package/dist/types/widgets/EodashTools.vue.d.ts +44 -6
- package/dist/types/widgets/PopUp.vue.d.ts +4 -4
- package/package.json +27 -27
- package/widgets/EodashLayerControl.vue +8 -1
- package/widgets/{EodashMap.vue → EodashMap/index.vue} +51 -31
- package/widgets/EodashMap/methods/create-layers-config.js +151 -0
- package/{core/client/composables/EodashMap.js → widgets/EodashMap/methods/index.js} +4 -153
- package/widgets/EodashMapBtns.vue +33 -7
- package/widgets/EodashProcess/ProcessList.vue +82 -0
- package/widgets/EodashProcess/index.vue +186 -0
- package/widgets/EodashProcess/methods/async.js +209 -0
- package/widgets/EodashProcess/methods/composables.js +129 -0
- package/widgets/EodashProcess/methods/handling.js +254 -0
- package/widgets/EodashProcess/methods/outputs.js +216 -0
- package/widgets/EodashProcess/methods/utils.js +138 -0
- package/widgets/EodashStacInfo.vue +6 -0
- package/widgets/EodashTools.vue +1 -0
- package/core/client/composables/EodashProcess.js +0 -654
- package/dist/types/core/client/composables/EodashMap.d.ts +0 -6
- package/dist/types/core/client/composables/EodashProcess.d.ts +0 -162
- package/widgets/EodashProcess.vue +0 -206
- /package/dist/types/widgets/{EodashMap.vue.d.ts → EodashMap/index.vue.d.ts} +0 -0
- /package/dist/types/widgets/{EodashProcess.vue.d.ts → EodashProcess/index.vue.d.ts} +0 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import mustache from "mustache";
|
|
2
|
+
import { extractLayerConfig } from "@/eodashSTAC/helpers";
|
|
3
|
+
import axios from "@/plugins/axios";
|
|
4
|
+
import { createLayerDefinition } from "./utils";
|
|
5
|
+
import { pollProcessStatus } from "./async";
|
|
6
|
+
import { indicator } from "@/store/states";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {import("stac-ts").StacLink[] | undefined} links
|
|
10
|
+
* @param {Record<string,any>|undefined} jsonformValue
|
|
11
|
+
* @param {number[]} origBbox
|
|
12
|
+
*/
|
|
13
|
+
export function processImage(links, jsonformValue, origBbox) {
|
|
14
|
+
if (!links) return;
|
|
15
|
+
const imageLinks = links.filter(
|
|
16
|
+
(link) => link.rel === "service" && link.type === "image/png",
|
|
17
|
+
);
|
|
18
|
+
const layers = [];
|
|
19
|
+
for (const link of imageLinks) {
|
|
20
|
+
layers.push({
|
|
21
|
+
type: "Image",
|
|
22
|
+
properties: {
|
|
23
|
+
id: link.id,
|
|
24
|
+
title: "Results " + link.id,
|
|
25
|
+
},
|
|
26
|
+
source: {
|
|
27
|
+
type: "ImageStatic",
|
|
28
|
+
imageExtent: origBbox,
|
|
29
|
+
url: mustache.render(link.href, {
|
|
30
|
+
...(jsonformValue ?? {}),
|
|
31
|
+
}),
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return layers;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @param {import("stac-ts").StacLink[] | undefined} links
|
|
40
|
+
* @param {Record<string,any> | undefined} jsonformValue
|
|
41
|
+
* @param {string} layerId
|
|
42
|
+
*/
|
|
43
|
+
export async function processVector(links, jsonformValue, layerId) {
|
|
44
|
+
if (!links) return;
|
|
45
|
+
/** @type {Record<string,any>[]} */
|
|
46
|
+
const layers = [];
|
|
47
|
+
const vectorLinks = links.filter(
|
|
48
|
+
(link) => link.rel === "service" && link.type === "application/geo+json",
|
|
49
|
+
);
|
|
50
|
+
if (vectorLinks.length === 0) return layers;
|
|
51
|
+
|
|
52
|
+
let flatStyleJSON = null;
|
|
53
|
+
|
|
54
|
+
for (const link of vectorLinks) {
|
|
55
|
+
if ("eox:flatstyle" in (link ?? {})) {
|
|
56
|
+
flatStyleJSON = await axios
|
|
57
|
+
.get(/** @type {string} */ (link["eox:flatstyle"]))
|
|
58
|
+
.then((resp) => resp.data);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** @type {Record<string,any>|undefined} */
|
|
62
|
+
let layerConfig;
|
|
63
|
+
/** @type {Record<string,any>|undefined} */
|
|
64
|
+
let style;
|
|
65
|
+
if (flatStyleJSON) {
|
|
66
|
+
const extracted = extractLayerConfig(flatStyleJSON);
|
|
67
|
+
layerConfig = extracted.layerConfig;
|
|
68
|
+
style = extracted.style;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
layers.push({
|
|
72
|
+
type: "Vector",
|
|
73
|
+
source: {
|
|
74
|
+
type: "Vector",
|
|
75
|
+
url: mustache.render(link.href, {
|
|
76
|
+
...(jsonformValue ?? {}),
|
|
77
|
+
}),
|
|
78
|
+
format: "GeoJSON",
|
|
79
|
+
},
|
|
80
|
+
properties: {
|
|
81
|
+
id: layerId + "_vector_process",
|
|
82
|
+
title: "Results " + layerId,
|
|
83
|
+
...(layerConfig && { ...layerConfig, ...(style && { style: style }) }),
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return layers;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @param {import("stac-ts").StacLink[] | undefined} links
|
|
92
|
+
* @param {Record<string,any> | undefined} jsonformValue
|
|
93
|
+
* @param {string} specUrl
|
|
94
|
+
* @returns {Promise<[import("@eox/chart").EOxChart["spec"] | null,Record<string,any>|null]>}
|
|
95
|
+
**/
|
|
96
|
+
export async function getChartValues(links, jsonformValue, specUrl) {
|
|
97
|
+
if (!specUrl || !links) return [null, null];
|
|
98
|
+
/** @type {import("vega").Spec} */
|
|
99
|
+
const spec = await axios.get(specUrl).then((resp) => {
|
|
100
|
+
return resp.data;
|
|
101
|
+
});
|
|
102
|
+
// //@ts-expect-error NamedData
|
|
103
|
+
// const dataName = spec?.data?.name;
|
|
104
|
+
const dataLinks = links.filter(
|
|
105
|
+
(link) => link.rel === "service", // && dataName && link.id === dataName,
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
/** @type {Record<string,any>} */
|
|
109
|
+
const dataValues = {};
|
|
110
|
+
for (const link of dataLinks ?? []) {
|
|
111
|
+
if (link.type && ["application/json", "text/csv"].includes(link.type)) {
|
|
112
|
+
const dataUrl = mustache.render(link.href, {
|
|
113
|
+
...(jsonformValue ?? {}),
|
|
114
|
+
...(link["eox:flatstyle"] ?? {}),
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Wait for data to be retrieved
|
|
118
|
+
const data = await axios.get(dataUrl).then((resp) => {
|
|
119
|
+
return resp.data;
|
|
120
|
+
});
|
|
121
|
+
// @ts-expect-error we assume data to exist in spec
|
|
122
|
+
spec.data.values = data;
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
dataValues[/** @type {string} */ (link.id)] = await axios
|
|
127
|
+
.get(
|
|
128
|
+
mustache.render(link.href, {
|
|
129
|
+
...(jsonformValue ?? {}),
|
|
130
|
+
...(link["eox:flatstyle"] ?? {}),
|
|
131
|
+
}),
|
|
132
|
+
)
|
|
133
|
+
.then((resp) => resp.data);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return [spec, dataValues];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @param {import("stac-ts").StacLink[] | undefined} links
|
|
141
|
+
* @param {Record<string,any> | undefined} jsonformValue
|
|
142
|
+
* @param {import("vue").Ref<boolean>} isPolling
|
|
143
|
+
* @param {string} layerId
|
|
144
|
+
* @param {string} projection
|
|
145
|
+
*/
|
|
146
|
+
export async function processGeoTiff(
|
|
147
|
+
links,
|
|
148
|
+
jsonformValue,
|
|
149
|
+
layerId,
|
|
150
|
+
isPolling,
|
|
151
|
+
projection,
|
|
152
|
+
) {
|
|
153
|
+
if (!links) return;
|
|
154
|
+
const geotiffLinks = links.filter(
|
|
155
|
+
(link) => link.rel === "service" && link.type === "image/tiff",
|
|
156
|
+
);
|
|
157
|
+
let urls = [];
|
|
158
|
+
let processId = "";
|
|
159
|
+
for (const link of geotiffLinks ?? []) {
|
|
160
|
+
if (link.endpoint === "eoxhub_workspaces") {
|
|
161
|
+
// TODO: prove of concept, needs to be reworked for sure
|
|
162
|
+
// Special handling for eoxhub workspace process endpoints
|
|
163
|
+
const postBody = await axios
|
|
164
|
+
.get(/** @type {string} */ (link["body"]), { responseType: "text" })
|
|
165
|
+
.then((resp) => resp.data);
|
|
166
|
+
const jsonData = JSON.parse(
|
|
167
|
+
mustache.render(postBody, { ...(jsonformValue ?? {}) }),
|
|
168
|
+
);
|
|
169
|
+
try {
|
|
170
|
+
const responseProcess = await axios.post(link.href, jsonData, {
|
|
171
|
+
headers: {
|
|
172
|
+
"Content-Type": "application/json",
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
console.log(responseProcess.headers.location);
|
|
176
|
+
// We save the process status url into localstorage assigning it to the indicator id
|
|
177
|
+
const currentJobs = JSON.parse(
|
|
178
|
+
localStorage.getItem(indicator.value) || "[]",
|
|
179
|
+
);
|
|
180
|
+
currentJobs.push(responseProcess.headers.location);
|
|
181
|
+
localStorage.setItem(indicator.value, JSON.stringify(currentJobs));
|
|
182
|
+
await pollProcessStatus({
|
|
183
|
+
processUrl: responseProcess.headers.location,
|
|
184
|
+
isPolling,
|
|
185
|
+
})
|
|
186
|
+
.then((resultItem) => {
|
|
187
|
+
// @ts-expect-error we have currently no definition of what is allowed as response
|
|
188
|
+
const resultUrls = resultItem?.urls;
|
|
189
|
+
if (resultUrls?.length < 1) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
//@ts-expect-error todo
|
|
193
|
+
processId = resultItem?.id;
|
|
194
|
+
urls = resultUrls;
|
|
195
|
+
})
|
|
196
|
+
.catch((error) => {
|
|
197
|
+
if (error instanceof Error) {
|
|
198
|
+
console.error("Polling failed:", error.message);
|
|
199
|
+
} else {
|
|
200
|
+
console.error("Unknown error occurred during polling:", error);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
} catch (error) {
|
|
204
|
+
if (error instanceof Error) {
|
|
205
|
+
console.error("Error sending POST request:", error.message);
|
|
206
|
+
} else {
|
|
207
|
+
console.error("Unknown error occurred:", error);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
} else {
|
|
211
|
+
urls.push(mustache.render(link.href, { ...(jsonformValue ?? {}) }));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return createLayerDefinition(links[0], layerId, urls, projection, processId);
|
|
216
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { extractLayerConfig } from "@/eodashSTAC/helpers";
|
|
2
|
+
import axios from "@/plugins/axios";
|
|
3
|
+
import { isMulti } from "@eox/jsonform/src/custom-inputs/spatial/utils";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {Record<string,any> |null} [jsonformSchema]
|
|
7
|
+
**/
|
|
8
|
+
export function getBboxProperty(jsonformSchema) {
|
|
9
|
+
return /** @type {string} */ (
|
|
10
|
+
Object.keys(jsonformSchema?.properties ?? {}).find(
|
|
11
|
+
(key) => jsonformSchema?.properties[key].format === "bounding-box",
|
|
12
|
+
)
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Extracts the keys of type "geojson" from the jsonform schema
|
|
18
|
+
* @param {Record<string,any> |null} [jsonformSchema]
|
|
19
|
+
**/
|
|
20
|
+
export function getGeoJsonProperties(jsonformSchema) {
|
|
21
|
+
return /** @type {string[]} */ (
|
|
22
|
+
Object.keys(jsonformSchema?.properties ?? {}).filter(
|
|
23
|
+
(key) => jsonformSchema?.properties[key].type === "geojson",
|
|
24
|
+
)
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Converts jsonform geojson values to stringified geometries
|
|
30
|
+
* @param {Record<string,any> |null} [jsonformSchema]
|
|
31
|
+
* @param {Record<string,any>} jsonformValue
|
|
32
|
+
**/
|
|
33
|
+
export function extractGeometries(jsonformValue, jsonformSchema) {
|
|
34
|
+
const geojsonKeys = getGeoJsonProperties(jsonformSchema);
|
|
35
|
+
|
|
36
|
+
for (const key of geojsonKeys) {
|
|
37
|
+
if (!jsonformValue[key]) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (isMulti(jsonformSchema?.properties[key])) {
|
|
42
|
+
// jsonformValue[key] is a feature collection
|
|
43
|
+
jsonformValue[key] =
|
|
44
|
+
/** @type {import("ol/format/GeoJSON").GeoJSONFeatureCollection} */ (
|
|
45
|
+
jsonformValue[key]
|
|
46
|
+
).features.map((feature) => JSON.stringify(feature.geometry));
|
|
47
|
+
} else {
|
|
48
|
+
// jsonformValue[key] is a single feature
|
|
49
|
+
jsonformValue[key] = JSON.stringify(jsonformValue[key].geometry);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
*
|
|
56
|
+
* @param {*} link
|
|
57
|
+
* @param {*} layerId
|
|
58
|
+
* @param {string[]} urls
|
|
59
|
+
* @param {*} projection
|
|
60
|
+
* @param {*} processId
|
|
61
|
+
* @returns
|
|
62
|
+
*/
|
|
63
|
+
export async function createLayerDefinition(
|
|
64
|
+
link,
|
|
65
|
+
layerId,
|
|
66
|
+
urls,
|
|
67
|
+
projection,
|
|
68
|
+
processId,
|
|
69
|
+
) {
|
|
70
|
+
let flatStyleJSON = null;
|
|
71
|
+
if ("eox:flatstyle" in (link ?? {})) {
|
|
72
|
+
flatStyleJSON = await axios
|
|
73
|
+
.get(/** @type {string} */ (link["eox:flatstyle"]))
|
|
74
|
+
.then((resp) => resp.data);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** @type {Record<string,any>|undefined} */
|
|
78
|
+
let layerConfig;
|
|
79
|
+
/** @type {Record<string,any>|undefined} */
|
|
80
|
+
let style;
|
|
81
|
+
if (flatStyleJSON) {
|
|
82
|
+
const extracted = extractLayerConfig(layerId ?? "", flatStyleJSON);
|
|
83
|
+
layerConfig = extracted.layerConfig;
|
|
84
|
+
style = extracted.style;
|
|
85
|
+
}
|
|
86
|
+
// We want to make sure the urls are alphabetically sorted
|
|
87
|
+
urls = urls.sort();
|
|
88
|
+
const layerdef =
|
|
89
|
+
urls.length > 0
|
|
90
|
+
? {
|
|
91
|
+
type: "WebGLTile",
|
|
92
|
+
source: {
|
|
93
|
+
type: "GeoTIFF",
|
|
94
|
+
normalize: !style,
|
|
95
|
+
sources: urls.map((url) => ({ url })),
|
|
96
|
+
},
|
|
97
|
+
properties: {
|
|
98
|
+
id: layerId + "_geotiff_process" + processId,
|
|
99
|
+
title: "Results " + layerId,
|
|
100
|
+
...(layerConfig && { layerConfig: layerConfig }),
|
|
101
|
+
layerControlToolsExpand: true,
|
|
102
|
+
},
|
|
103
|
+
...(style && { style: style }),
|
|
104
|
+
}
|
|
105
|
+
: undefined;
|
|
106
|
+
|
|
107
|
+
// We want to see if the currently selected indicator uses a
|
|
108
|
+
// specific map projection if it does we want to apply it
|
|
109
|
+
if (projection && layerdef) {
|
|
110
|
+
//@ts-expect-error TODO
|
|
111
|
+
layerdef.source.projection = projection;
|
|
112
|
+
}
|
|
113
|
+
return layerdef;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* @param {string} fileName
|
|
117
|
+
* @param {string|Record<string,any>} content
|
|
118
|
+
* @returns
|
|
119
|
+
*/
|
|
120
|
+
export const download = (fileName, content) => {
|
|
121
|
+
if (!content) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
let url = /** @type string */ (content);
|
|
125
|
+
if (typeof content === "object") {
|
|
126
|
+
content = JSON.stringify(content);
|
|
127
|
+
const blob = new Blob([content], { type: "text" });
|
|
128
|
+
url = URL.createObjectURL(blob);
|
|
129
|
+
}
|
|
130
|
+
const link = document.createElement("a");
|
|
131
|
+
if (confirm(`Would you like to download ${fileName}?`)) {
|
|
132
|
+
link.href = url;
|
|
133
|
+
link.download = fileName;
|
|
134
|
+
link.click();
|
|
135
|
+
}
|
|
136
|
+
URL.revokeObjectURL(url);
|
|
137
|
+
link.remove();
|
|
138
|
+
};
|
|
@@ -55,26 +55,32 @@ main {padding-bottom: 10px;}
|
|
|
55
55
|
.footer-container small {font-size:10px;line-height:1;}`,
|
|
56
56
|
},
|
|
57
57
|
header: {
|
|
58
|
+
/** @type {import("vue").PropType<string[]>} */
|
|
58
59
|
type: Array,
|
|
59
60
|
default: () => ["title"],
|
|
60
61
|
},
|
|
61
62
|
tags: {
|
|
63
|
+
/** @type {import("vue").PropType<string[]>} */
|
|
62
64
|
type: Array,
|
|
63
65
|
default: () => ["themes"],
|
|
64
66
|
},
|
|
65
67
|
subheader: {
|
|
68
|
+
/** @type {import("vue").PropType<string[]>} */
|
|
66
69
|
type: Array,
|
|
67
70
|
default: () => [],
|
|
68
71
|
},
|
|
69
72
|
body: {
|
|
73
|
+
/** @type {import("vue").PropType<string[]>} */
|
|
70
74
|
type: Array,
|
|
71
75
|
default: () => ["satellite", "sensor", "agency", "extent"],
|
|
72
76
|
},
|
|
73
77
|
featured: {
|
|
78
|
+
/** @type {import("vue").PropType<string[]>} */
|
|
74
79
|
type: Array,
|
|
75
80
|
default: () => ["description", "providers", "assets", "links"],
|
|
76
81
|
},
|
|
77
82
|
footer: {
|
|
83
|
+
/** @type {import("vue").PropType<string[]>} */
|
|
78
84
|
type: Array,
|
|
79
85
|
default: () => ["sci:citation"],
|
|
80
86
|
},
|
package/widgets/EodashTools.vue
CHANGED