@eodash/eodash 5.6.0 → 5.7.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.
Files changed (91) hide show
  1. package/core/client/components/DashboardLayout.vue +1 -1
  2. package/core/client/composables/index.js +6 -2
  3. package/core/client/eodashSTAC/EodashCollection.js +5 -21
  4. package/core/client/eodashSTAC/createLayers.js +23 -9
  5. package/core/client/eodashSTAC/helpers.js +37 -4
  6. package/core/client/types.ts +8 -1
  7. package/core/client/utils/index.js +4 -0
  8. package/dist/client/{DashboardLayout-DkKDhfgH.js → DashboardLayout-kRsmsNW5.js} +5 -5
  9. package/dist/client/{DynamicWebComponent-BrpkA-e3.js → DynamicWebComponent-CnKhYo0K.js} +1 -1
  10. package/dist/client/{EodashChart-p7_1FRlF.js → EodashChart-CLDqE93C.js} +4 -4
  11. package/dist/client/{EodashDatePicker-HK0Jl7wQ.js → EodashDatePicker-CMPDT-ce.js} +3 -3
  12. package/dist/client/{EodashItemFilter-BYQDA78B.js → EodashItemFilter-BpdA8QQa.js} +1 -1
  13. package/dist/client/{EodashLayerControl-NcrNncGn.js → EodashLayerControl-BHpDA4_0.js} +25 -7
  14. package/dist/client/{EodashLayoutSwitcher-CC2Znd0I.js → EodashLayoutSwitcher-B1fRUt7G.js} +3 -3
  15. package/dist/client/EodashMapBtns-Cpned0tc.js +478 -0
  16. package/dist/client/{EodashStacInfo-BA-0UjvT.js → EodashStacInfo-BQspAHKH.js} +31 -31
  17. package/dist/client/{EodashTools-CWmoH0g_.js → EodashTools-1zHz26gv.js} +4 -4
  18. package/dist/client/{ExportState-CfAfX4RN.js → ExportState-DbOm8hBI.js} +4 -4
  19. package/dist/client/{Footer-DLGxQTZt.js → Footer-BKg-VVkj.js} +1 -1
  20. package/dist/client/{Header-eyEyyzD6.js → Header-DCrwCvmY.js} +2 -2
  21. package/dist/client/MobileLayout-vWSHpluo.js +118 -0
  22. package/dist/client/{PopUp-WNs6Io2N.js → PopUp-9uimfK49.js} +2 -2
  23. package/dist/client/{ProcessList-RzVqbd5E.js → ProcessList-CTTIZa06.js} +4 -4
  24. package/dist/client/{VImg-GKUTFoV-.js → VImg-CrmB76ZY.js} +2 -2
  25. package/dist/client/{VMain-D7_72mHr.js → VMain-OKZNpcEG.js} +1 -1
  26. package/dist/client/{VTooltip-BbmvtvYw.js → VTooltip-CJw2FyWk.js} +2 -2
  27. package/dist/client/{WidgetsContainer-Dw5d7SOW.js → WidgetsContainer-BaWOnE5R.js} +1 -1
  28. package/dist/client/{asWebComponent-DDt7V3Bl.js → asWebComponent-BHWpMuE3.js} +47 -35
  29. package/dist/client/{async-CT3KEV52.js → async-DSKj6g1f.js} +29 -28
  30. package/dist/client/create-layers-config-CBoYedqB.js +182 -0
  31. package/dist/client/eo-dash.js +1 -1
  32. package/dist/client/{forwardRefs-CVzxyoSq.js → forwardRefs-DH51zPUr.js} +2 -2
  33. package/dist/client/{handling-C285F_Mq.js → handling-BrcDDlgS.js} +452 -114
  34. package/dist/client/{helpers-CZFH0EVN.js → helpers-DjZVl_WF.js} +2277 -1504
  35. package/dist/client/{index-B-m7V3Kb.js → index-1JKE68n3.js} +49 -194
  36. package/dist/client/{index-CF3ZMzTz.js → index-5Jhsa8Xe.js} +3 -3
  37. package/dist/client/index-CSG_JoOA.js +436 -0
  38. package/dist/client/{index-DgOXD7wd.js → index-CUjl-ZsI.js} +2 -2
  39. package/dist/client/{index-B_6H-N14.js → index-Cu3-13Xg.js} +84 -90
  40. package/dist/client/material-symbols-outlined.woff2 +0 -0
  41. package/dist/client/material-symbols-rounded.woff2 +0 -0
  42. package/dist/client/material-symbols-sharp.woff2 +0 -0
  43. package/dist/client/material-symbols-subset.woff2 +0 -0
  44. package/dist/client/templates.js +1 -1
  45. package/dist/client/{transition-C2gnrWg0.js → transition-OHcz5Qq1.js} +1 -1
  46. package/dist/node/cli.js +1 -1
  47. package/dist/types/core/client/composables/index.d.ts +1 -3
  48. package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +6 -7
  49. package/dist/types/core/client/eodashSTAC/createLayers.d.ts +3 -3
  50. package/dist/types/core/client/eodashSTAC/helpers.d.ts +1 -0
  51. package/dist/types/core/client/types.d.ts +8 -1
  52. package/dist/types/templates/baseConfig.d.ts +12 -0
  53. package/dist/types/widgets/EodashLayerControl.vue.d.ts +1 -1
  54. package/dist/types/widgets/EodashMap/EodashMapBtns.vue.d.ts +9 -0
  55. package/dist/types/widgets/EodashMap/index.vue.d.ts +7 -0
  56. package/dist/types/widgets/EodashMap/methods/create-layers-config.d.ts +1 -8
  57. package/dist/types/widgets/EodashProcess/methods/composables.d.ts +2 -3
  58. package/dist/types/widgets/EodashProcess/methods/handling.d.ts +15 -10
  59. package/dist/types/widgets/EodashProcess/methods/outputs.d.ts +3 -1
  60. package/dist/types/widgets/EodashProcess/methods/template-helpers.d.ts +99 -0
  61. package/dist/types/widgets/EodashProcess/methods/utils.d.ts +1 -6
  62. package/dist/types/widgets/EodashProcess/types.d.ts +1 -0
  63. package/dist/types/widgets/EodashStacInfo.vue.d.ts +10 -10
  64. package/dist/types/widgets/EodashTimeSlider/index.vue.d.ts +34 -0
  65. package/dist/types/widgets/EodashTimeSlider/methods/index.d.ts +39 -0
  66. package/dist/types/widgets/EodashTimeSlider/types.d.ts +62 -0
  67. package/package.json +32 -32
  68. package/widgets/EodashLayerControl.vue +22 -3
  69. package/widgets/EodashMap/EodashMapBtns.vue +46 -1
  70. package/widgets/EodashMap/index.vue +17 -5
  71. package/widgets/EodashMap/methods/create-layers-config.js +2 -0
  72. package/widgets/EodashMap/methods/index.js +23 -5
  73. package/widgets/EodashProcess/index.vue +17 -13
  74. package/widgets/EodashProcess/methods/async.js +19 -8
  75. package/widgets/EodashProcess/methods/composables.js +63 -74
  76. package/widgets/EodashProcess/methods/custom-endpoints/chart/sentinelhub-endpoint.js +9 -5
  77. package/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.js +7 -4
  78. package/widgets/EodashProcess/methods/handling.js +125 -76
  79. package/widgets/EodashProcess/methods/outputs.js +74 -29
  80. package/widgets/EodashProcess/methods/template-helpers.js +246 -0
  81. package/widgets/EodashProcess/methods/utils.js +7 -17
  82. package/widgets/EodashProcess/types.ts +1 -0
  83. package/widgets/EodashStacInfo.vue +30 -30
  84. package/widgets/EodashTimeSlider/index.vue +152 -0
  85. package/widgets/EodashTimeSlider/methods/index.js +279 -0
  86. package/widgets/EodashTimeSlider/types.ts +64 -0
  87. package/dist/client/EodashMapBtns-BJSh7qT-.js +0 -435
  88. package/dist/client/EodashTimeSlider-GDv1hbw7.js +0 -53
  89. package/dist/client/MobileLayout-RzLOyXwL.js +0 -118
  90. package/dist/types/widgets/EodashTimeSlider.vue.d.ts +0 -15
  91. package/widgets/EodashTimeSlider.vue +0 -40
@@ -0,0 +1,436 @@
1
+ import { useTemplateRef, ref, computed, onMounted, openBlock, createElementBlock, unref, createElementVNode, createCommentVNode } from 'vue';
2
+ import { a0 as removeLayers, Q as sanitizeBbox, d as axios, i as mapEl, v as getLayers, A as datetime } from './helpers-DjZVl_WF.js';
3
+ import { L as eodashCollections, _ as _export_sfc, H as useSTAcStore } from './asWebComponent-BHWpMuE3.js';
4
+ import '@eox/timecontrol';
5
+ import '@eox/itemfilter';
6
+ import { storeToRefs } from 'pinia';
7
+ import { c as createLayersConfig } from './create-layers-config-CBoYedqB.js';
8
+
9
+ /**
10
+ * @param {string} stacEndpoint
11
+ * @param {[string, string]} selectedRange
12
+ * @param {import("../types").TimelineExportEventDetail["selectedRangeItems"]} selectedRangeItems
13
+ * @param {import("vue").Ref<import("stac-ts").StacCollection|null>} selectedStac
14
+ * @param {Record<string, import("../types").Filter>} filters
15
+ */
16
+ async function createAnimationLayers(
17
+ stacEndpoint,
18
+ selectedRange,
19
+ selectedRangeItems,
20
+ selectedStac,
21
+ filters,
22
+ ) {
23
+ if (eodashCollections[0].isAPI) {
24
+ return await createAPILayers(
25
+ stacEndpoint,
26
+ { min: selectedRange[0], max: selectedRange[1] },
27
+ mapEl.value?.lonLatExtent,
28
+ selectedStac,
29
+ filters,
30
+ );
31
+ }
32
+ const { collections: hiddenCollections, layers: hiddenLayers } =
33
+ getHiddenLayers([...getLayers()]);
34
+
35
+ return await Promise.all(
36
+ Object.values(selectedRangeItems).flatMap(async (itemSet) => {
37
+ /** @type {Array<{ layers: Record<string, any>[]; date: string }>} */
38
+ const mapLayersArr = [];
39
+ for (const dateItem of itemSet) {
40
+ await createLayersConfig(
41
+ selectedStac.value,
42
+ eodashCollections.filter(
43
+ (collection) =>
44
+ !hiddenCollections.includes(collection.collectionStac?.id ?? ""),
45
+ ),
46
+ dateItem.originalDate,
47
+ ).then((layers) => {
48
+ //@ts-expect-error createLayersConfig is not typed strictly
49
+ layers = removeLayers(layers, hiddenLayers);
50
+ //@ts-expect-error createLayersConfig is not typed strictly
51
+ layers = restoreLayersVisibility(layers);
52
+ layers = anonimizeLayersCORS(layers);
53
+ mapLayersArr.push({
54
+ layers,
55
+ date: dateItem.originalDate,
56
+ });
57
+ });
58
+ }
59
+ return mapLayersArr;
60
+ }),
61
+ ).then((results) => results.flat());
62
+ }
63
+ /**
64
+ *
65
+ * @param {string} stacEndpoint
66
+ * @param {{min: string, max: string}} date
67
+ * @param {number[] | undefined} bbox
68
+ * @param {import("vue").Ref<import("stac-ts").StacCollection|null>} selectedStac
69
+ * @param {Record<string, import("../types").Filter>} filters
70
+ * @return {Promise<Array<{ layers: Record<string, any>[]; date: string }>>}
71
+ */
72
+ async function createAPILayers(
73
+ stacEndpoint,
74
+ date = { min: "", max: "" },
75
+ bbox,
76
+ selectedStac,
77
+ filters,
78
+ ) {
79
+ if (!bbox) {
80
+ return [];
81
+ }
82
+ const url = new URL(stacEndpoint + "/search");
83
+ url.searchParams.set("limit", "100");
84
+ url.searchParams.set("collections", selectedStac.value?.id ?? "");
85
+ url.searchParams.set(
86
+ "datetime",
87
+ `${new Date(date.min).toISOString()}/${new Date(date.max).toISOString()}`,
88
+ );
89
+ url.searchParams.set("bbox", sanitizeBbox(bbox).join(","));
90
+
91
+ const stacFilter = buildStacFilters(filters);
92
+ if (stacFilter) {
93
+ url.searchParams.set("filter", stacFilter);
94
+ }
95
+
96
+ /** @type {import("stac-ts").StacItem[]} */
97
+ const items = await axios
98
+ .get(url.href)
99
+ .then((res) => res.data.features)
100
+ .catch((err) => {
101
+ console.error("[eodash] Error fetching items for animation:", err);
102
+ return [];
103
+ });
104
+ if (!items || !items.length) {
105
+ console.warn("[eodash] No items found for animation.");
106
+ return [];
107
+ }
108
+ const { collections: hiddenCollections, layers: hiddenLayers } =
109
+ getHiddenLayers([...getLayers()]);
110
+ return await Promise.all(
111
+ items.map(async (item) => {
112
+ /** @type {Array<{ layers: Record<string, any>[]; date: string }>} */
113
+ const mapLayersArr = [];
114
+ await createLayersConfig(
115
+ selectedStac.value,
116
+ eodashCollections.filter(
117
+ (collection) =>
118
+ !hiddenCollections.includes(collection.collectionStac?.id ?? ""),
119
+ ),
120
+ item,
121
+ ).then((layers) => {
122
+ //@ts-expect-error createLayersConfig is not typed strictly
123
+ layers = removeLayers(layers, hiddenLayers);
124
+ //@ts-expect-error createLayersConfig is not typed strictly
125
+ layers = restoreLayersVisibility(layers);
126
+ layers = anonimizeLayersCORS(layers);
127
+ mapLayersArr.push({
128
+ layers,
129
+ date: /** @type {string} */ (item.properties.datetime),
130
+ });
131
+ return mapLayersArr;
132
+ });
133
+ return mapLayersArr;
134
+ }),
135
+ ).then((results) => results.flat());
136
+ }
137
+ /**
138
+ *
139
+ * @param {Record<string, any>[]} layers
140
+ * @returns {Record<string, any>[]}
141
+ */
142
+ function anonimizeLayersCORS(layers) {
143
+ return layers.map((layer) => {
144
+ if (layer.type === "Group") {
145
+ layer.layers = anonimizeLayersCORS(layer.layers);
146
+ return layer;
147
+ }
148
+ if (layer.source) {
149
+ layer.source.crossOrigin = "anonymous";
150
+ }
151
+ return layer;
152
+ });
153
+ }
154
+ /**
155
+ * returns the list of layers that has visibility hidden
156
+ * @param {import("@eox/map").EoxLayer[]} layers
157
+ * @returns {{ collections: string[]; layers: string[] }}
158
+ */
159
+ function getHiddenLayers(layers) {
160
+ /** @type {{ collections: string[]; layers: string[] }} */
161
+ const result = { collections: [], layers: [] };
162
+
163
+ for (const layer of layers) {
164
+ // check inner layers if it's a group layer first
165
+ if (layer.type === "Group" && Array.isArray(layer.layers)) {
166
+ const childResult = getHiddenLayers(layer.layers);
167
+ for (const col of childResult.collections) {
168
+ if (!result.collections.includes(col)) {
169
+ result.collections.push(col);
170
+ }
171
+ }
172
+ for (const lyr of childResult.layers) {
173
+ if (!result.layers.includes(lyr)) {
174
+ result.layers.push(lyr);
175
+ }
176
+ }
177
+ }
178
+
179
+ if (!layer.properties?.id) {
180
+ continue;
181
+ }
182
+
183
+ const olLayer = mapEl.value?.getLayerById(layer.properties?.id);
184
+ if (!olLayer) {
185
+ continue;
186
+ }
187
+
188
+ if (olLayer.getVisible() === false) {
189
+ const refId = layer.properties.id;
190
+ if (refId) {
191
+ if (refId.includes(";:;")) {
192
+ // Check if this looks like a typical eodash collection ID with separator
193
+ const parts = refId.split(";:;");
194
+ if (parts.length > 2) {
195
+ const prefix = parts[0];
196
+ if (!result.collections.includes(prefix)) {
197
+ result.collections.push(prefix);
198
+ }
199
+ } else {
200
+ // It has a separator but might just be a base layer like `layerId;:;EPSG`
201
+ if (!result.layers.includes(refId)) {
202
+ result.layers.push(refId);
203
+ }
204
+ }
205
+ } else {
206
+ if (!result.layers.includes(refId)) {
207
+ result.layers.push(refId);
208
+ }
209
+ }
210
+ }
211
+ }
212
+ }
213
+
214
+ return result;
215
+ }
216
+
217
+ /**
218
+ * Iterates through a list of layers and updates layer.properties.visible to true
219
+ * if it is set to false
220
+ * @param {import("@eox/map").EoxLayer[]} layers
221
+ * @returns {import("@eox/map").EoxLayer[]}
222
+ */
223
+ function restoreLayersVisibility(layers) {
224
+ for (const layer of layers) {
225
+ if (layer.properties && layer.properties.visible === false) {
226
+ layer.properties.visible = true;
227
+ }
228
+
229
+ if (layer.type === "Group" && Array.isArray(layer.layers)) {
230
+ restoreLayersVisibility(layer.layers);
231
+ }
232
+ }
233
+ return layers;
234
+ }
235
+
236
+ /**
237
+ * Build STAC API filter string from TimeSlider filters
238
+ * @param {Record<string, import("../types").Filter>} filters
239
+ * @returns {string}
240
+ */
241
+ function buildStacFilters(filters) {
242
+ if (!filters) return "";
243
+
244
+ /** @type {string[]} */
245
+ const stacFilters = [];
246
+
247
+ Object.values(filters).forEach((filter) => {
248
+ if (!filter || !filter.key) return;
249
+
250
+ // strip 'properties.' from key if present
251
+ const propName = filter.key.startsWith("properties.")
252
+ ? filter.key.replace("properties.", "")
253
+ : filter.key;
254
+
255
+ if (filter.type === "range" && filter.state) {
256
+ if (
257
+ filter.state.min !== undefined &&
258
+ filter.state.min > (filter.min ?? -Infinity)
259
+ ) {
260
+ stacFilters.push(`${propName}>=${filter.state.min}`);
261
+ }
262
+ if (
263
+ filter.state.max !== undefined &&
264
+ filter.state.max < (filter.max ?? Infinity)
265
+ ) {
266
+ stacFilters.push(`${propName}<=${filter.state.max}`);
267
+ }
268
+ } else if (filter.type === "multiselect" && filter.stringifiedState) {
269
+ if (filter.stringifiedState.length > 0) {
270
+ stacFilters.push(`${propName} IN (${filter.stringifiedState})`);
271
+ }
272
+ } else if (filter.type === "select" && filter.stringifiedState) {
273
+ if (filter.stringifiedState) {
274
+ stacFilters.push(`${propName}='${filter.stringifiedState}'`);
275
+ }
276
+ }
277
+ });
278
+
279
+ return stacFilters.join(" AND ");
280
+ }
281
+
282
+ const _style_0 = "eox-itemfilter[data-v-2fc72058]{--inline-container-height: 40px}";
283
+
284
+ const _hoisted_1 = [".for", ".animate"];
285
+ const _hoisted_2 = { class: "d-flex g-10 align-center" };
286
+ const _hoisted_3 = [".filterProperties"];
287
+
288
+
289
+ const _sfc_main = {
290
+ __name: 'index',
291
+ props: {
292
+ filters: {
293
+ /** @type {import("vue").PropType<import("@eox/itemfilter").EOxItemFilter["filterProperties"]>} */
294
+ type: Array,
295
+ default: () => [],
296
+ },
297
+ animate: {
298
+ type: Boolean,
299
+ default: true,
300
+ },
301
+ },
302
+ setup(__props) {
303
+
304
+
305
+
306
+ /** @type {import("vue").ShallowRef<HTMLElement>} */
307
+ const timesliderEl = useTemplateRef("eoxTimecontrol");
308
+
309
+ const startDate = new Date(datetime.value);
310
+ const endDate = new Date(startDate.getTime() + 24 * 60 * 60 * 1000);
311
+
312
+ const selectedRange = /** @type {import("vue").Ref<[string, string]>} */ (
313
+ ref([startDate, endDate].map((d) => d.toISOString()))
314
+ );
315
+ const initDate = [startDate.toISOString().split("T")[0]];
316
+
317
+ const hasMultipleItems = computed(() => {
318
+ return eodashCollections.some((ec) => {
319
+ const itemLinks = ec.collectionStac?.links.filter((l) => l.rel === "item");
320
+ const itemsLink = ec.collectionStac?.links.some((l) => l.rel === "items");
321
+ return (itemLinks && itemLinks.length > 1) || itemsLink;
322
+ });
323
+ });
324
+
325
+ /**
326
+ * Handles the selection event from the time control component.
327
+ * It finds the closest item to the "from" selected date
328
+ * and updates the global datetime state with that item's original date.
329
+ *
330
+ * @param {CustomEvent<import("./types").TimelineSelectionEventDetail>} e
331
+ */
332
+ const onSelect = (e) => {
333
+ const { selectedItems, date } = e.detail;
334
+ // Update the selected range with the new dates
335
+ selectedRange.value = date;
336
+
337
+ const allItems = Object.keys(selectedItems ?? {}).flatMap(
338
+ (id) => selectedItems[id],
339
+ );
340
+ if (!allItems.length) {
341
+ return;
342
+ }
343
+ const [from] = date;
344
+ const fromDate = new Date(from).getTime();
345
+
346
+ const closestItem = allItems.reduce((prev, curr) => {
347
+ const prevDiff = Math.abs(new Date(prev.originalDate).getTime() - fromDate);
348
+ const currDiff = Math.abs(new Date(curr.originalDate).getTime() - fromDate);
349
+ return currDiff < prevDiff ? curr : prev;
350
+ });
351
+
352
+ if (closestItem) {
353
+ datetime.value = closestItem.originalDate;
354
+ }
355
+ };
356
+
357
+ const { selectedStac, stacEndpoint } = storeToRefs(useSTAcStore());
358
+
359
+ /**
360
+ *
361
+ * @param {CustomEvent<import("./types").TimelineExportEventDetail>} evt
362
+ */
363
+ const onExport = async (evt) => {
364
+ const { generate, selectedRangeItems, filters } = evt.detail;
365
+
366
+ if (!stacEndpoint.value) {
367
+ return;
368
+ }
369
+
370
+ const mapLayers = await createAnimationLayers(
371
+ stacEndpoint.value,
372
+ selectedRange.value,
373
+ selectedRangeItems,
374
+ selectedStac,
375
+ filters,
376
+ );
377
+
378
+ if (!mapLayers?.length) {
379
+ console.warn("[eodash] No map layers generated for the animation.");
380
+ return;
381
+ }
382
+
383
+ generate({
384
+ mapLayers,
385
+ });
386
+ };
387
+
388
+ onMounted(() => {
389
+ const parentDiv = timesliderEl.value?.parentElement;
390
+ const layoutItem = parentDiv?.parentElement;
391
+ if (parentDiv && layoutItem && __props.animate) {
392
+ parentDiv.style.overflow = "visible";
393
+ layoutItem.style.overflow = "visible";
394
+ }
395
+ });
396
+
397
+ return (_ctx, _cache) => {
398
+ return (hasMultipleItems.value)
399
+ ? (openBlock(), createElementBlock("eox-timecontrol", {
400
+ key: unref(unref(mapEl)),
401
+ ref: "eoxTimecontrol",
402
+ ".for": unref(mapEl),
403
+ onSelect: onSelect,
404
+ titleKey: "title",
405
+ ".externalMapRendering": true,
406
+ ".animate": __props.animate,
407
+ ".initDate": initDate
408
+ }, [
409
+ createElementVNode("div", _hoisted_2, [
410
+ _cache[0] || (_cache[0] = createElementVNode("eox-timecontrol-date", { class: "flex-grow-1" }, null, -1 /* CACHED */)),
411
+ createElementVNode("eox-timecontrol-picker", {
412
+ ".range": false,
413
+ ".showDots": true,
414
+ ".showItems": true,
415
+ ".popup": true
416
+ }, null, 32 /* NEED_HYDRATION */),
417
+ (__props.filters.length)
418
+ ? (openBlock(), createElementBlock("eox-itemfilter", {
419
+ key: 0,
420
+ ".inlineMode": true,
421
+ showResults: false,
422
+ ".filterProperties": __props.filters
423
+ }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_3))
424
+ : createCommentVNode("v-if", true),
425
+ createElementVNode("eox-timecontrol-timelapse", { onExport: onExport }, null, 32 /* NEED_HYDRATION */)
426
+ ]),
427
+ _cache[1] || (_cache[1] = createElementVNode("eox-timecontrol-timeline", { class: "mt-2" }, null, -1 /* CACHED */))
428
+ ], 40 /* PROPS, NEED_HYDRATION */, _hoisted_1))
429
+ : createCommentVNode("v-if", true)
430
+ }
431
+ }
432
+
433
+ };
434
+ const index = /*#__PURE__*/_export_sfc(_sfc_main, [['styles',[_style_0]],['__scopeId',"data-v-2fc72058"]]);
435
+
436
+ export { index as default };
@@ -1,6 +1,6 @@
1
1
  import { resolveComponent, render, h, mergeProps } from 'vue';
2
- import { a0 as consoleError, a1 as isObject } from './asWebComponent-DDt7V3Bl.js';
3
- import { V as VTooltip } from './VTooltip-BbmvtvYw.js';
2
+ import { $ as consoleError, a0 as isObject } from './asWebComponent-BHWpMuE3.js';
3
+ import { V as VTooltip } from './VTooltip-CJw2FyWk.js';
4
4
 
5
5
  // Utilities
6
6
  function useDirectiveComponent(component, props) {
@@ -1,15 +1,14 @@
1
- import { onMounted, watch, nextTick, ref, useTemplateRef, computed, openBlock, createElementBlock, createVNode, unref, createCommentVNode, createBlock, createElementVNode, withCtx, createTextVNode } from 'vue';
1
+ import { onMounted, watch, nextTick, onUnmounted, ref, useTemplateRef, computed, openBlock, createElementBlock, createVNode, unref, createCommentVNode, createBlock, createElementVNode, withCtx, createTextVNode } from 'vue';
2
2
  import '@eox/chart';
3
3
  import '@eox/drawtools';
4
4
  import '@eox/jsonform';
5
- import { U as eoxLayersKey, N as useOnLayersUpdate, _ as _export_sfc, H as useSTAcStore, J as VBtn } from './asWebComponent-DDt7V3Bl.js';
5
+ import { N as useOnLayersUpdate, _ as _export_sfc, H as useSTAcStore, J as VBtn } from './asWebComponent-BHWpMuE3.js';
6
6
  import { storeToRefs } from 'pinia';
7
- import { P as ProcessList, c as compareJobs, j as jobs } from './ProcessList-RzVqbd5E.js';
8
- import EodashChart from './EodashChart-p7_1FRlF.js';
9
- import { i as initProcess, u as updateJsonformIdentifier, h as handleProcesses } from './handling-C285F_Mq.js';
10
- import { useEventBus } from '@vueuse/core';
11
- import { u as updateJobsStatus, d as download, g as getDrawToolsProperty } from './async-CT3KEV52.js';
12
- import { I as compareIndicator, F as indicator, S as mapCompareEl, i as mapEl, M as areChartsSeparateLayout, O as compareChartSpec, N as chartSpec } from './helpers-CZFH0EVN.js';
7
+ import { P as ProcessList, c as compareJobs, j as jobs } from './ProcessList-CTTIZa06.js';
8
+ import EodashChart from './EodashChart-CLDqE93C.js';
9
+ import { i as initProcess, u as updateJsonformIdentifier, h as handleProcesses } from './handling-BrcDDlgS.js';
10
+ import { Y as getCompareLayers, v as getLayers, H as compareIndicator, E as indicator, R as mapCompareEl, i as mapEl, L as areChartsSeparateLayout, N as compareChartSpec, M as chartSpec } from './helpers-DjZVl_WF.js';
11
+ import { u as updateJobsStatus, d as download, g as getDrawToolsProperties } from './async-DSKj6g1f.js';
13
12
  import { mdiCogPlayOutline, mdiDownloadCircleOutline } from '@mdi/js';
14
13
 
15
14
  /**
@@ -19,17 +18,15 @@ import { mdiCogPlayOutline, mdiDownloadCircleOutline } from '@mdi/js';
19
18
  * @async
20
19
  * @param {Object} params
21
20
  * @param {import("vue").Ref<import("stac-ts").StacCollection | null>} params.selectedStac
22
- * @param {import("vue").Ref<import("@eox/jsonform").EOxJSONForm | null>} params.jsonformEl
23
21
  * @param {import("vue").Ref<Record<string,any> | null>} params.jsonformSchema
24
22
  * @param {import("vue").Ref<any[]>} params.processResults
25
23
  * @param {import("vue").Ref<boolean>} params.isProcessed
26
24
  * @param {import("vue").Ref<boolean>} params.loading
27
25
  * @param {import("vue").Ref<boolean>} params.isPolling
28
- * @param {import("@eox/map").EOxMap | null} params.mapElement
26
+ * @param {import("vue").Ref<import("@eox/map").EOxMap | null>} params.mapElement
29
27
  */
30
28
  const useInitProcess = ({
31
29
  selectedStac,
32
- jsonformEl,
33
30
  jsonformSchema,
34
31
  isProcessed,
35
32
  processResults,
@@ -37,64 +34,56 @@ const useInitProcess = ({
37
34
  isPolling,
38
35
  mapElement,
39
36
  }) => {
40
- const layersEvents = useEventBus(eoxLayersKey);
41
-
42
37
  onMounted(async () => {
43
- // wait for the layers to be rendered
44
- if ((mapElement?.layers.length ?? 0) > 1) {
45
- await initProcess({
46
- enableCompare: mapElement?.id === "compare",
47
- selectedStac,
48
- jsonformEl,
49
- jsonformSchema,
50
- isProcessed,
51
- processResults,
52
- loading,
53
- isPolling,
54
- });
55
- } else {
56
- layersEvents.once(async () => {
57
- await initProcess({
58
- enableCompare: mapElement?.id === "compare",
59
- selectedStac,
60
- jsonformEl,
61
- jsonformSchema,
62
- isProcessed,
63
- loading,
64
- processResults,
65
- isPolling,
66
- });
67
- });
68
- }
38
+ await initProcess({
39
+ enableCompare: mapElement.value?.id === "compare",
40
+ selectedStac,
41
+ jsonformSchema,
42
+ isProcessed,
43
+ processResults,
44
+ loading,
45
+ isPolling,
46
+ mapElement: mapElement.value,
47
+ });
69
48
  });
70
49
 
71
- const evtKey =
72
- mapElement?.id === "compare" ? "compareLayers:updated" : "layers:updated";
73
- useOnLayersUpdate(async (evt, _payload) => {
74
- if (
75
- evt == "layertime:updated" ||
76
- evt == "compareLayertime:updated" ||
77
- evt == "time:updated" ||
78
- evt == "compareTime:updated"
79
- ) {
80
- await updateJsonformIdentifier({
50
+ useOnLayersUpdate(async (evt) => {
51
+ const enableCompare = mapElement.value?.id === "compare";
52
+ const layerUpdatedKey = enableCompare
53
+ ? "compareLayers:updated"
54
+ : "layers:updated";
55
+ const timeUpdatedKeys = enableCompare
56
+ ? ["compareLayertime:updated", "compareTime:updated"]
57
+ : ["layertime:updated", "time:updated"];
58
+
59
+ if (timeUpdatedKeys.includes(evt)) {
60
+ // we need to update jsonform on time change in cases
61
+ // when the feature selection layer was time-based,
62
+ // so that it attaches to a correct new layer
63
+ const newJsonForm = await updateJsonformIdentifier({
81
64
  jsonformSchema: jsonformSchema.value,
82
- // @ts-expect-error TODO payload coming from time update events is not an object with layers property
83
- newLayers: _payload,
65
+ newLayers: enableCompare ? getCompareLayers() : getLayers(),
66
+ enableCompare,
67
+ mapElement: mapElement.value,
84
68
  });
69
+
70
+ if (newJsonForm) {
71
+ jsonformSchema.value = newJsonForm;
72
+ }
85
73
  }
86
- if (evt !== evtKey) {
74
+
75
+ if (evt !== layerUpdatedKey) {
87
76
  return;
88
77
  }
89
78
  await initProcess({
90
- enableCompare: mapElement?.id === "compare",
79
+ enableCompare,
91
80
  selectedStac,
92
- jsonformEl,
93
81
  jsonformSchema,
94
82
  isProcessed,
95
83
  processResults,
96
84
  loading,
97
85
  isPolling,
86
+ mapElement: mapElement.value,
98
87
  });
99
88
  });
100
89
  };
@@ -114,39 +103,40 @@ function useAutoExec(
114
103
  startProcess,
115
104
  ) {
116
105
  /**
117
- * @param {CustomEvent} _e
106
+ * @param {any} _e
118
107
  **/
119
108
  const onJsonFormChange = async (_e) => {
120
109
  await startProcess();
121
110
  };
122
111
 
123
- const addEventListener = async () => {
124
- await nextTick(() => {
125
- //@ts-expect-error TODO
126
- jsonformEl.value?.addEventListener("change", onJsonFormChange);
127
- });
128
- };
129
- const removeEventListener = () => {
130
- //@ts-expect-error TODO
131
- jsonformEl.value?.removeEventListener("change", onJsonFormChange);
132
- };
133
-
134
112
  watch(jsonformSchema, (updatedSchema) => {
135
113
  autoExec.value = updatedSchema?.options?.["execute"] || false;
136
114
  });
137
115
 
138
- onMounted(() => {
139
- watch(
140
- autoExec,
141
- async (exec) => {
142
- if (exec) {
143
- await addEventListener();
144
- } else {
145
- removeEventListener();
146
- }
147
- },
148
- { immediate: true },
149
- );
116
+ // Re-attach listener whenever the element or autoExec changes
117
+ const stop = watch(
118
+ [autoExec, jsonformEl],
119
+ async ([exec, el], [_prevExec, prevEl]) => {
120
+ // Cleanup if previous element existed
121
+ if (prevEl) {
122
+ prevEl.removeEventListener("change", onJsonFormChange);
123
+ }
124
+ // Add if enabled and we have an element
125
+ if (exec && el) {
126
+ // remove listener before adding to avoid duplicates in case of element change
127
+ el.removeEventListener("change", onJsonFormChange);
128
+ await nextTick();
129
+ el.addEventListener("change", onJsonFormChange);
130
+ }
131
+ },
132
+ { immediate: true },
133
+ );
134
+
135
+ onUnmounted(() => {
136
+ if (jsonformEl.value) {
137
+ jsonformEl.value.removeEventListener("change", onJsonFormChange);
138
+ }
139
+ stop();
150
140
  });
151
141
  }
152
142
 
@@ -212,13 +202,15 @@ const currentIndicator = __props.enableCompare ? compareIndicator : indicator;
212
202
  const currentJobs = __props.enableCompare ? compareJobs : jobs;
213
203
 
214
204
  const jsonformKey = computed(
215
- () => currentIndicator.value + mapElement.value?.id,
205
+ () =>
206
+ currentIndicator.value +
207
+ mapElement.value?.id +
208
+ JSON.stringify(jsonformSchema.value),
216
209
  );
217
210
 
218
211
  useInitProcess({
219
212
  selectedStac: currentSelectedStac,
220
- mapElement: mapElement.value,
221
- jsonformEl,
213
+ mapElement,
222
214
  jsonformSchema,
223
215
  isProcessed,
224
216
  processResults,
@@ -245,15 +237,17 @@ const downloadResults = () => {
245
237
  };
246
238
 
247
239
  const startProcess = async () => {
248
- const drawToolsProperty = getDrawToolsProperty(jsonformSchema.value);
249
- const propertyIsEmpty =
250
- drawToolsProperty &&
251
- //@ts-expect-error jsonfrom.value is not typed
252
- Array.isArray(jsonformEl.value?.value[drawToolsProperty]) &&
253
- //@ts-expect-error jsonfrom.value is not typed
254
- !jsonformEl.value?.value[drawToolsProperty].length;
255
-
256
- if (propertyIsEmpty) {
240
+ const drawToolsProperties = getDrawToolsProperties(jsonformSchema.value);
241
+
242
+ const anyDrawtoolPropertyEmpty = drawToolsProperties.some(
243
+ (drawToolsProperty) =>
244
+ //@ts-expect-error jsonfrom.value is not typed
245
+ Array.isArray(jsonformEl.value?.value[drawToolsProperty]) &&
246
+ //@ts-expect-error jsonfrom.value is not typed
247
+ !jsonformEl.value?.value[drawToolsProperty].length,
248
+ );
249
+
250
+ if (anyDrawtoolPropertyEmpty) {
257
251
  isProcessed.value = false;
258
252
  const usedChartSpec = __props.enableCompare ? compareChartSpec : chartSpec;
259
253
  usedChartSpec.value = null;