@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.
- package/core/client/composables/DefineWidgets.js +8 -1
- package/core/client/eodash.js +9 -9
- package/core/client/eodashSTAC/createLayers.js +4 -17
- package/core/client/eodashSTAC/helpers.js +23 -0
- package/core/client/store/stac.js +3 -1
- package/core/client/types.ts +127 -21
- package/core/client/utils/states.js +9 -0
- package/core/client/vite-env.d.ts +0 -13
- package/dist/client/{DashboardLayout-D1UcB3RV.js → DashboardLayout-t_PavJPO.js} +2 -2
- package/dist/client/{DynamicWebComponent-DtZ_mHL9.js → DynamicWebComponent-y07rVJch.js} +1 -1
- package/dist/client/{EodashDatePicker-CYU0MZX5.js → EodashDatePicker-CcOfyzGD.js} +3 -83
- package/dist/client/{EodashItemFilter-SE9oW3oZ.js → EodashItemFilter-B9HCvIMi.js} +1 -1
- package/dist/client/{EodashLayerControl-BuGe29Nt.js → EodashLayerControl-KStn7Nb_.js} +8 -2
- package/dist/client/{EodashLayoutSwitcher-6wLl-Gtd.js → EodashLayoutSwitcher-DqeFO3RN.js} +2 -2
- package/dist/client/{EodashMapBtns-BWWu6eHG.js → EodashMapBtns-5BF27qJB.js} +36 -12
- package/dist/client/{EodashStacInfo-DjRSGLHM.js → EodashStacInfo-C_hDy6Pd.js} +7 -1
- package/dist/client/{EodashTools-CJ4hBH_X.js → EodashTools-BXflvRf8.js} +5 -4
- package/dist/client/{ExportState-BqnlEpzR.js → ExportState-C0QRemK1.js} +27 -12
- package/dist/client/{Footer-C_3WrfI4.js → Footer-7VGyGUAs.js} +1 -1
- package/dist/client/{Header-D_hcGpNG.js → Header-BQJnXHYq.js} +3 -3
- package/dist/client/{MobileLayout-CDbupC9v.js → MobileLayout-b8nQ-Vyl.js} +5 -5
- package/dist/client/{PopUp-Ba6mY2jQ.js → PopUp-DgNrh9Df.js} +3 -3
- package/dist/client/ProcessList-C62SOVO6.js +484 -0
- package/dist/client/{VImg-Yc9F9pYq.js → VImg-D4eT3IQ1.js} +2 -2
- package/dist/client/{VMain-BiS7HPEk.js → VMain-C3hN2-H3.js} +1 -1
- package/dist/client/{VOverlay-B9mxXaCv.js → VOverlay-tAeNygaA.js} +15 -6
- package/dist/client/{VTooltip-XJLaLrZQ.js → VTooltip-B0Q3iHMZ.js} +3 -3
- package/dist/client/{WidgetsContainer-DRVb_73N.js → WidgetsContainer-CtDHfCYf.js} +1 -1
- package/dist/client/{asWebComponent-DZpMGxEY.js → asWebComponent-BJ2NWunV.js} +100 -95
- package/dist/client/eo-dash.css +2 -2
- package/dist/client/eo-dash.js +1 -1
- package/dist/client/{forwardRefs-BtkfywIE.js → forwardRefs-CIFAqXaZ.js} +9 -9
- package/dist/client/{EodashMap-DhVCoYMi.js → index-BQ16n4Sk.js} +103 -78
- package/dist/client/index-Cv7HBz49.js +85 -0
- package/dist/client/{EodashProcess-GSj_LMsK.js → index-Da5xXX6Q.js} +349 -443
- package/dist/client/{index-f55xuyof.js → index-DvcUndod.js} +1 -1
- package/dist/client/{transition-CtL4BoVi.js → transition-Cdb4K27U.js} +1 -1
- package/dist/types/core/client/components/MobileLayout.vue.d.ts +9 -9
- package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +11 -6
- package/dist/types/core/client/eodashSTAC/createLayers.d.ts +6 -5
- package/dist/types/core/client/eodashSTAC/helpers.d.ts +383 -2
- package/dist/types/core/client/types.d.ts +85 -19
- 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 +30 -29
- package/widgets/EodashLayerControl.vue +8 -1
- package/widgets/{EodashMap.vue → EodashMap/index.vue} +53 -29
- 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 -624
- 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 -208
- /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,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
|
},
|
package/widgets/EodashTools.vue
CHANGED