@eodash/eodash 5.0.0-rc.2.4 → 5.0.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/core/client/composables/DefineWidgets.js +8 -1
  2. package/core/client/eodash.js +9 -9
  3. package/core/client/eodashSTAC/createLayers.js +4 -17
  4. package/core/client/eodashSTAC/helpers.js +23 -0
  5. package/core/client/store/stac.js +3 -1
  6. package/core/client/types.ts +127 -21
  7. package/core/client/utils/states.js +9 -0
  8. package/core/client/vite-env.d.ts +0 -13
  9. package/dist/client/{DashboardLayout-D1UcB3RV.js → DashboardLayout-t_PavJPO.js} +2 -2
  10. package/dist/client/{DynamicWebComponent-DtZ_mHL9.js → DynamicWebComponent-y07rVJch.js} +1 -1
  11. package/dist/client/{EodashDatePicker-CYU0MZX5.js → EodashDatePicker-CcOfyzGD.js} +3 -83
  12. package/dist/client/{EodashItemFilter-SE9oW3oZ.js → EodashItemFilter-B9HCvIMi.js} +1 -1
  13. package/dist/client/{EodashLayerControl-BuGe29Nt.js → EodashLayerControl-KStn7Nb_.js} +8 -2
  14. package/dist/client/{EodashLayoutSwitcher-6wLl-Gtd.js → EodashLayoutSwitcher-DqeFO3RN.js} +2 -2
  15. package/dist/client/{EodashMapBtns-BWWu6eHG.js → EodashMapBtns-5BF27qJB.js} +36 -12
  16. package/dist/client/{EodashStacInfo-DjRSGLHM.js → EodashStacInfo-C_hDy6Pd.js} +7 -1
  17. package/dist/client/{EodashTools-CJ4hBH_X.js → EodashTools-BXflvRf8.js} +5 -4
  18. package/dist/client/{ExportState-BqnlEpzR.js → ExportState-C0QRemK1.js} +27 -12
  19. package/dist/client/{Footer-C_3WrfI4.js → Footer-7VGyGUAs.js} +1 -1
  20. package/dist/client/{Header-D_hcGpNG.js → Header-BQJnXHYq.js} +3 -3
  21. package/dist/client/{MobileLayout-CDbupC9v.js → MobileLayout-b8nQ-Vyl.js} +5 -5
  22. package/dist/client/{PopUp-Ba6mY2jQ.js → PopUp-DgNrh9Df.js} +3 -3
  23. package/dist/client/ProcessList-C62SOVO6.js +484 -0
  24. package/dist/client/{VImg-Yc9F9pYq.js → VImg-D4eT3IQ1.js} +2 -2
  25. package/dist/client/{VMain-BiS7HPEk.js → VMain-C3hN2-H3.js} +1 -1
  26. package/dist/client/{VOverlay-B9mxXaCv.js → VOverlay-tAeNygaA.js} +15 -6
  27. package/dist/client/{VTooltip-XJLaLrZQ.js → VTooltip-B0Q3iHMZ.js} +3 -3
  28. package/dist/client/{WidgetsContainer-DRVb_73N.js → WidgetsContainer-CtDHfCYf.js} +1 -1
  29. package/dist/client/{asWebComponent-DZpMGxEY.js → asWebComponent-BJ2NWunV.js} +100 -95
  30. package/dist/client/eo-dash.css +2 -2
  31. package/dist/client/eo-dash.js +1 -1
  32. package/dist/client/{forwardRefs-BtkfywIE.js → forwardRefs-CIFAqXaZ.js} +9 -9
  33. package/dist/client/{EodashMap-DhVCoYMi.js → index-BQ16n4Sk.js} +103 -78
  34. package/dist/client/index-Cv7HBz49.js +85 -0
  35. package/dist/client/{EodashProcess-GSj_LMsK.js → index-Da5xXX6Q.js} +349 -443
  36. package/dist/client/{index-f55xuyof.js → index-DvcUndod.js} +1 -1
  37. package/dist/client/{transition-CtL4BoVi.js → transition-Cdb4K27U.js} +1 -1
  38. package/dist/types/core/client/components/MobileLayout.vue.d.ts +9 -9
  39. package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +11 -6
  40. package/dist/types/core/client/eodashSTAC/createLayers.d.ts +6 -5
  41. package/dist/types/core/client/eodashSTAC/helpers.d.ts +383 -2
  42. package/dist/types/core/client/types.d.ts +85 -19
  43. package/dist/types/core/client/utils/states.d.ts +7 -0
  44. package/dist/types/widgets/EodashDatePicker.vue.d.ts +4 -4
  45. package/dist/types/widgets/EodashItemFilter.vue.d.ts +18 -18
  46. package/dist/types/widgets/EodashLayerControl.vue.d.ts +2 -2
  47. package/dist/types/widgets/EodashLayoutSwitcher.vue.d.ts +2 -2
  48. package/dist/types/widgets/EodashMap/methods/create-layers-config.d.ts +9 -0
  49. package/dist/types/widgets/EodashMap/methods/index.d.ts +5 -0
  50. package/dist/types/widgets/EodashMapBtns.vue.d.ts +8 -2
  51. package/dist/types/widgets/EodashProcess/ProcessList.vue.d.ts +2 -0
  52. package/dist/types/widgets/EodashProcess/methods/async.d.ts +45 -0
  53. package/dist/types/widgets/EodashProcess/methods/composables.d.ts +19 -0
  54. package/dist/types/widgets/EodashProcess/methods/handling.d.ts +78 -0
  55. package/dist/types/widgets/EodashProcess/methods/outputs.d.ts +54 -0
  56. package/dist/types/widgets/EodashProcess/methods/utils.d.ts +42 -0
  57. package/dist/types/widgets/EodashStacInfo.vue.d.ts +12 -12
  58. package/dist/types/widgets/EodashTools.vue.d.ts +44 -6
  59. package/dist/types/widgets/PopUp.vue.d.ts +4 -4
  60. package/package.json +30 -29
  61. package/widgets/EodashLayerControl.vue +8 -1
  62. package/widgets/{EodashMap.vue → EodashMap/index.vue} +53 -29
  63. package/widgets/EodashMap/methods/create-layers-config.js +151 -0
  64. package/{core/client/composables/EodashMap.js → widgets/EodashMap/methods/index.js} +4 -153
  65. package/widgets/EodashMapBtns.vue +33 -7
  66. package/widgets/EodashProcess/ProcessList.vue +82 -0
  67. package/widgets/EodashProcess/index.vue +186 -0
  68. package/widgets/EodashProcess/methods/async.js +209 -0
  69. package/widgets/EodashProcess/methods/composables.js +129 -0
  70. package/widgets/EodashProcess/methods/handling.js +254 -0
  71. package/widgets/EodashProcess/methods/outputs.js +216 -0
  72. package/widgets/EodashProcess/methods/utils.js +138 -0
  73. package/widgets/EodashStacInfo.vue +6 -0
  74. package/widgets/EodashTools.vue +1 -0
  75. package/core/client/composables/EodashProcess.js +0 -624
  76. package/dist/types/core/client/composables/EodashMap.d.ts +0 -6
  77. package/dist/types/core/client/composables/EodashProcess.d.ts +0 -162
  78. package/widgets/EodashProcess.vue +0 -208
  79. /package/dist/types/widgets/{EodashMap.vue.d.ts → EodashMap/index.vue.d.ts} +0 -0
  80. /package/dist/types/widgets/{EodashProcess.vue.d.ts → EodashProcess/index.vue.d.ts} +0 -0
@@ -0,0 +1,254 @@
1
+ import log from "loglevel";
2
+ import { extractGeometries, getBboxProperty } from "./utils";
3
+ import { datetime, mapEl } from "@/store/states";
4
+ import axios from "@/plugins/axios";
5
+ import { getLayers } from "@/store/actions";
6
+ import {
7
+ getChartValues,
8
+ processGeoTiff,
9
+ processImage,
10
+ processVector,
11
+ } from "./outputs";
12
+
13
+ /**
14
+ * Fetch and set the jsonform schema to initialize the process
15
+ *
16
+ * @export
17
+ * @async
18
+ * @param {Object} params
19
+ * @param {import("vue").Ref<import("stac-ts").StacCollection>} params.selectedStac
20
+ * @param {import("vue").Ref<import("@eox/jsonform").EOxJSONForm | null>} params.jsonformEl
21
+ * @param {import("vue").Ref<Record<string,any> | null>} params.jsonformSchema
22
+ * @param {import("vue").Ref<import("@eox/chart").EOxChart["spec"] | null>} params.chartSpec
23
+ * @param {import("vue").Ref<any[]>} params.processResults
24
+ * @param {import("vue").Ref<boolean>} params.isProcessed
25
+ * @param {import("vue").Ref<boolean>} params.loading
26
+ * @param {import("vue").Ref<boolean>} params.isPolling
27
+ */
28
+ export async function initProcess({
29
+ selectedStac,
30
+ jsonformEl,
31
+ jsonformSchema,
32
+ chartSpec,
33
+ isProcessed,
34
+ processResults,
35
+ loading,
36
+ isPolling,
37
+ }) {
38
+ if (!selectedStac.value) {
39
+ return;
40
+ }
41
+ resetProcess({
42
+ loading,
43
+ isProcessed,
44
+ chartSpec,
45
+ jsonformSchema,
46
+ isPolling,
47
+ processResults,
48
+ });
49
+ if (selectedStac.value["eodash:jsonform"]) {
50
+ jsonformEl.value?.editor.destroy();
51
+ // wait for the layers to be rendered
52
+ jsonformSchema.value = await axios
53
+ //@ts-expect-error eodash extention
54
+ .get(selectedStac.value["eodash:jsonform"])
55
+ .then((resp) => resp.data);
56
+ // remove borders from jsonform
57
+ } else {
58
+ if (!jsonformSchema.value) {
59
+ return;
60
+ }
61
+ jsonformSchema.value = null;
62
+ }
63
+ }
64
+
65
+ /**
66
+ *
67
+ * @param {Object} params
68
+ * @param {import("vue").Ref<boolean>} params.loading
69
+ * @param {import("vue").Ref<import("stac-ts").StacCollection | null>} params.selectedStac
70
+ * @param {import("vue").Ref<import("@eox/jsonform").EOxJSONForm | null>} params.jsonformEl
71
+ * @param {import("vue").Ref<Record<string,any>|null>} params.jsonformSchema
72
+ * @param {import("vue").Ref<import("@eox/chart").EOxChart["spec"] | null>} params.chartSpec
73
+ * @param {import("vue").Ref<Record<string, any> | null>} params.chartData
74
+ * @param {import("vue").Ref<boolean>} params.isPolling
75
+ * @param {import("vue").Ref<any[]>} params.processResults
76
+ */
77
+ export async function handleProcesses({
78
+ loading,
79
+ selectedStac,
80
+ jsonformEl,
81
+ jsonformSchema,
82
+ chartSpec,
83
+ chartData,
84
+ isPolling,
85
+ processResults,
86
+ }) {
87
+ if (!jsonformEl.value || !jsonformSchema.value || !selectedStac.value) {
88
+ return;
89
+ }
90
+ log.debug("Processing...");
91
+ loading.value = true;
92
+ try {
93
+ const serviceLinks = selectedStac.value?.links?.filter(
94
+ (l) => l.rel === "service",
95
+ );
96
+ const bboxProperty = getBboxProperty(jsonformSchema.value);
97
+ const jsonformValue = /** @type {Record<string,any>} */ (
98
+ jsonformEl.value?.value
99
+ );
100
+
101
+ extractGeometries(jsonformValue, jsonformSchema.value);
102
+
103
+ const origBbox = jsonformValue[bboxProperty];
104
+
105
+ const specUrl = /** @type {string} */ (
106
+ selectedStac.value?.["eodash:vegadefinition"]
107
+ );
108
+
109
+ [chartSpec.value, chartData.value] = await getChartValues(
110
+ serviceLinks,
111
+ { ...(jsonformValue ?? {}) },
112
+ specUrl,
113
+ );
114
+ if (Object.keys(chartData.value ?? {}).length) {
115
+ processResults.value.push(chartData.value);
116
+ }
117
+
118
+ //@ts-expect-error we assume that the spec data is of type InlineData
119
+ if (chartSpec.value?.data?.values?.length) {
120
+ //@ts-expect-error we assume that the spec data is of type InlineData
121
+ processResults.value.push(chartSpec.value?.data.values);
122
+ }
123
+
124
+ if (chartSpec.value && !("background" in chartSpec.value)) {
125
+ chartSpec.value["background"] = "transparent";
126
+ }
127
+
128
+ const geotiffLayer = await processGeoTiff(
129
+ serviceLinks,
130
+ jsonformValue,
131
+ selectedStac.value?.id ?? "",
132
+ isPolling,
133
+ //@ts-expect-error TODO
134
+ selectedStac.value?.["eodash:mapProjection"]?.["name"] ?? null,
135
+ );
136
+
137
+ if (geotiffLayer && geotiffLayer.source?.sources.length) {
138
+ processResults.value.push(
139
+ ...(geotiffLayer.source?.sources?.map((source) => source.url) ?? []),
140
+ );
141
+ }
142
+ // 3. vector geojson
143
+ const vectorLayers = await processVector(
144
+ serviceLinks,
145
+ jsonformValue,
146
+ selectedStac.value?.id ?? "",
147
+ );
148
+
149
+ if (vectorLayers?.length) {
150
+ processResults.value.push(
151
+ ...vectorLayers.map((layer) => layer.source?.url),
152
+ );
153
+ }
154
+
155
+ const imageLayers = processImage(serviceLinks, jsonformValue, origBbox);
156
+ if (imageLayers?.length) {
157
+ processResults.value.push(
158
+ ...imageLayers.map((layer) => layer.source?.url),
159
+ );
160
+ }
161
+
162
+ log.debug(
163
+ "rendered layers after processing:",
164
+ geotiffLayer,
165
+ vectorLayers,
166
+ imageLayers,
167
+ );
168
+
169
+ if (geotiffLayer || vectorLayers?.length || imageLayers?.length) {
170
+ const layers = [
171
+ ...(geotiffLayer ? [geotiffLayer] : []),
172
+ ...(vectorLayers ?? []),
173
+ ...(imageLayers ?? []),
174
+ ];
175
+ let currentLayers = [...getLayers()];
176
+ let analysisGroup = currentLayers.find((l) =>
177
+ l.properties.id.includes("AnalysisGroup"),
178
+ );
179
+ analysisGroup?.layers.push(...layers);
180
+
181
+ if (mapEl.value) {
182
+ mapEl.value.layers = [...currentLayers];
183
+ }
184
+ }
185
+ loading.value = false;
186
+ } catch (error) {
187
+ console.error("[eodash] Error while running process:", error);
188
+ loading.value = false;
189
+ throw error;
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Reset the process state
195
+ * @param {Object} params
196
+ * @param {import("vue").Ref<boolean>} params.loading
197
+ * @param {import("vue").Ref<boolean>} params.isProcessed
198
+ * @param {import("vue").Ref<import("@eox/chart").EOxChart["spec"] | null>} params.chartSpec
199
+ * @param {import("vue").Ref<boolean>} params.isPolling
200
+ * @param {import("vue").Ref<any[]>} params.processResults
201
+ * @param {import("vue").Ref<Record<string,any>|null>} params.jsonformSchema
202
+ */
203
+ export function resetProcess({
204
+ loading,
205
+ isProcessed,
206
+ chartSpec,
207
+ jsonformSchema,
208
+ processResults,
209
+ isPolling,
210
+ }) {
211
+ loading.value = false;
212
+ isProcessed.value = false;
213
+ isPolling.value = false;
214
+ chartSpec.value = null;
215
+ processResults.value = [];
216
+ jsonformSchema.value = null;
217
+ }
218
+
219
+ /**
220
+ * Handles the click event on a chart to extract temporal information and update the global datetime value.
221
+ *
222
+ * @param {object} evt - The click event object.
223
+ * @param {object} evt.target - The target of the event, expected to have a Vega-Lite specification (`spec`).
224
+ * @param {object} evt.target.spec - The Vega-Lite specification of the chart.
225
+ * @param {Record<string,{type?:string;field?:string;}>} [evt.target.spec.encoding] - The encoding specification of the chart.
226
+ * @param {object} evt.detail - The detail of the event, containing information about the clicked item.
227
+ * @param {import("vega").Item} evt.detail.item - The Vega item that was clicked.
228
+ */
229
+ export const onChartClick = (evt) => {
230
+ const chartSpec = evt.target?.spec;
231
+ if (!chartSpec) {
232
+ return;
233
+ }
234
+ const encodingKey = Object.keys(chartSpec.encoding ?? {}).find(
235
+ (key) => chartSpec.encoding?.[key].type === "temporal",
236
+ );
237
+ if (!encodingKey) {
238
+ return;
239
+ }
240
+ const temporalKey = chartSpec.encoding?.[encodingKey].field;
241
+ if (!temporalKey) {
242
+ return;
243
+ }
244
+ try {
245
+ const vegaItem = evt.detail.item;
246
+ const temporalValue = new Date(vegaItem.datum.datum[temporalKey]);
247
+ datetime.value = temporalValue.toISOString();
248
+ } catch (error) {
249
+ console.warn(
250
+ "[eodash] Error while setting datetime from eox-chart:",
251
+ error,
252
+ );
253
+ }
254
+ };
@@ -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
  },
@@ -74,6 +74,7 @@ const props = defineProps({
74
74
  default: "Select indicator",
75
75
  },
76
76
  itemFilterConfig: {
77
+ /** @type {import("vue").PropType<InstanceType<import("./EodashItemFilter.vue").default>["$props"]>} */
77
78
  type: Object,
78
79
  default: () => {},
79
80
  },