@eodash/eodash 5.6.1 → 5.7.1

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 (133) hide show
  1. package/core/client/components/DashboardLayout.vue +1 -1
  2. package/core/client/components/EodashOverlay.vue +27 -4
  3. package/core/client/composables/DefineEodash.js +0 -1
  4. package/core/client/composables/DefineWidgets.js +3 -1
  5. package/core/client/composables/index.js +6 -2
  6. package/core/client/eodashSTAC/EodashCollection.js +79 -45
  7. package/core/client/eodashSTAC/cql.js +64 -0
  8. package/core/client/eodashSTAC/createLayers.js +192 -125
  9. package/core/client/eodashSTAC/helpers.js +423 -97
  10. package/core/client/eodashSTAC/mosaic.js +416 -0
  11. package/core/client/plugins/axios.js +31 -1
  12. package/core/client/store/actions.js +1 -1
  13. package/core/client/store/stac.js +25 -4
  14. package/core/client/store/states.js +20 -2
  15. package/core/client/types.ts +155 -29
  16. package/core/client/utils/bands-editor/exampleSchema.json +50 -50
  17. package/core/client/utils/index.js +4 -0
  18. package/core/client/utils/states.js +10 -0
  19. package/dist/client/{DashboardLayout-CqMb7OXc.js → DashboardLayout-ePbdvUTE.js} +5 -5
  20. package/dist/client/{DynamicWebComponent-DqKqTf7l.js → DynamicWebComponent-g5SdRbjY.js} +1 -1
  21. package/dist/client/{EodashChart-PkUQfH0k.js → EodashChart-ChrkA5oS.js} +7 -6
  22. package/dist/client/{EodashDatePicker-DLJGdTtX.js → EodashDatePicker-CY1TrsDo.js} +3 -3
  23. package/dist/client/{EodashItemFilter-Dk8KjFcX.js → EodashItemFilter-DzshHDlS.js} +2 -1
  24. package/dist/client/{EodashLayerControl-CC1Cogrn.js → EodashLayerControl-DMCeMkSd.js} +70 -22
  25. package/dist/client/{EodashLayoutSwitcher-5WZYd6rr.js → EodashLayoutSwitcher-iJ8mX1rF.js} +3 -3
  26. package/dist/client/EodashMapBtns-C7Cr7q5Y.js +592 -0
  27. package/dist/client/EodashStacInfo-K7-iuXa7.js +169 -0
  28. package/dist/client/{EodashTools-CGZtTh45.js → EodashTools-BEK7e7JM.js} +4 -4
  29. package/dist/client/{ExportState-Ce0ZnrX_.js → ExportState-CqIzfMYQ.js} +6 -168
  30. package/dist/client/{Footer-CnZqEiop.js → Footer-1P0cmBOZ.js} +1 -1
  31. package/dist/client/{Header-Dr5PBIm8.js → Header-CkkBaBNh.js} +2 -2
  32. package/dist/client/MobileLayout-BPf49kDU.js +118 -0
  33. package/dist/client/{PopUp-DjvE_71e.js → PopUp-DPZq5SWI.js} +4 -168
  34. package/dist/client/{ProcessList-kf3olI7W.js → ProcessList-DuI6WpS1.js} +5 -5
  35. package/dist/client/VDivider-Bj9LG_JV.js +168 -0
  36. package/dist/client/{VImg-Bj6uWt6j.js → VImg-Ddv5OyMz.js} +2 -2
  37. package/dist/client/{VMain-Cm0UmKGi.js → VMain-7yqk_qC3.js} +1 -1
  38. package/dist/client/{VTooltip-DbBu-ky3.js → VTooltip-2hAJyEoa.js} +2 -2
  39. package/dist/client/{WidgetsContainer-CfLnd44U.js → WidgetsContainer-2DOrlwCB.js} +1 -1
  40. package/dist/client/{asWebComponent-DfULAbpq.js → asWebComponent-BlFN2lkB.js} +493 -335
  41. package/dist/client/{async-CIbKXEEe.js → async-B2H8ZwUK.js} +21 -10
  42. package/dist/client/create-layers-config-u_vn5hPk.js +182 -0
  43. package/dist/client/dialog-transition-BrMkMiNa.js +170 -0
  44. package/dist/client/eo-dash.js +1 -1
  45. package/dist/client/{forwardRefs-yj3VWOK5.js → forwardRefs-DAlror6d.js} +8 -87
  46. package/dist/client/{handling-s8xt2JwF.js → handling-B6I1V5eG.js} +123 -85
  47. package/dist/client/{helpers-DAVGYl_f.js → helpers-CBqIUSXJ.js} +3034 -1649
  48. package/dist/client/index-BWq1ZKaV.js +3168 -0
  49. package/dist/client/{index-CYz6dT7K.js → index-CJ9UI3ln.js} +2 -2
  50. package/dist/client/index-DXLz4sFR.js +442 -0
  51. package/dist/client/{index-4TrjfJ32.js → index-DhKU6KqM.js} +230 -231
  52. package/dist/client/{index-Bu8BMA9q.js → index-DjQlbWbJ.js} +70 -83
  53. package/dist/client/material-symbols-outlined.woff2 +0 -0
  54. package/dist/client/material-symbols-rounded.woff2 +0 -0
  55. package/dist/client/material-symbols-sharp.woff2 +0 -0
  56. package/dist/client/material-symbols-subset.woff2 +0 -0
  57. package/dist/client/mosaic-BFYLEwyx.js +455 -0
  58. package/dist/client/templates.js +250 -119
  59. package/dist/client/{transition-DaOsiD4u.js → transition-D_W6Wn9v.js} +1 -1
  60. package/dist/node/cli.js +5 -5
  61. package/dist/node/types.d.ts +4 -0
  62. package/dist/types/core/client/composables/DefineEodash.d.ts +1 -1
  63. package/dist/types/core/client/composables/index.d.ts +1 -3
  64. package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +62 -31
  65. package/dist/types/core/client/eodashSTAC/cql.d.ts +15 -0
  66. package/dist/types/core/client/eodashSTAC/createLayers.d.ts +44 -25
  67. package/dist/types/core/client/eodashSTAC/helpers.d.ts +78 -18
  68. package/dist/types/core/client/eodashSTAC/mosaic.d.ts +56 -0
  69. package/dist/types/core/client/store/stac.d.ts +31 -7
  70. package/dist/types/core/client/store/states.d.ts +24 -2
  71. package/dist/types/core/client/types.d.ts +131 -25
  72. package/dist/types/core/client/utils/states.d.ts +12 -0
  73. package/dist/types/templates/baseConfig.d.ts +1 -88
  74. package/dist/types/templates/compare.d.ts +32 -3
  75. package/dist/types/templates/expert.d.ts +18 -0
  76. package/dist/types/templates/explore.d.ts +9 -1
  77. package/dist/types/templates/lite.d.ts +11 -0
  78. package/dist/types/widgets/EodashChart.vue.d.ts +5 -3
  79. package/dist/types/widgets/EodashItemCatalog/index.vue.d.ts +129 -2
  80. package/dist/types/widgets/EodashItemCatalog/methods/filters.d.ts +28 -6
  81. package/dist/types/widgets/EodashItemCatalog/methods/handlers.d.ts +17 -4
  82. package/dist/types/widgets/EodashItemCatalog/methods/map.d.ts +16 -4
  83. package/dist/types/widgets/EodashLayerControl.vue.d.ts +36 -17
  84. package/dist/types/widgets/EodashMap/EodashMapBtns.vue.d.ts +23 -10
  85. package/dist/types/widgets/EodashMap/index.vue.d.ts +91 -35
  86. package/dist/types/widgets/EodashMap/methods/create-layers-config.d.ts +1 -8
  87. package/dist/types/widgets/EodashMap/methods/index.d.ts +5 -1
  88. package/dist/types/widgets/EodashMap/methods/use-map-loading.d.ts +1 -0
  89. package/dist/types/widgets/EodashProcess/index.vue.d.ts +5 -3
  90. package/dist/types/widgets/EodashProcess/methods/composables.d.ts +1 -1
  91. package/dist/types/widgets/EodashProcess/methods/handling.d.ts +13 -8
  92. package/dist/types/widgets/EodashProcess/states.d.ts +1 -1
  93. package/dist/types/widgets/EodashStacInfo.vue.d.ts +20 -0
  94. package/dist/types/widgets/EodashTimeSlider/index.vue.d.ts +54 -0
  95. package/dist/types/widgets/EodashTimeSlider/methods/index.d.ts +34 -0
  96. package/dist/types/widgets/EodashTimeSlider/types.d.ts +52 -0
  97. package/dist/types/widgets/EodashTools.vue.d.ts +5 -5
  98. package/package.json +46 -46
  99. package/templates/baseConfig.js +36 -6
  100. package/templates/compare.js +62 -7
  101. package/templates/expert.js +23 -0
  102. package/templates/explore.js +11 -5
  103. package/templates/lite.js +14 -0
  104. package/widgets/EodashChart.vue +1 -0
  105. package/widgets/EodashItemCatalog/index.vue +363 -35
  106. package/widgets/EodashItemCatalog/methods/filters.js +134 -70
  107. package/widgets/EodashItemCatalog/methods/handlers.js +113 -19
  108. package/widgets/EodashItemCatalog/methods/map.js +142 -28
  109. package/widgets/EodashLayerControl.vue +64 -14
  110. package/widgets/EodashMap/EodashMapBtns.vue +153 -47
  111. package/widgets/EodashMap/index.vue +101 -105
  112. package/widgets/EodashMap/methods/btns.js +37 -5
  113. package/widgets/EodashMap/methods/create-layers-config.js +18 -16
  114. package/widgets/EodashMap/methods/index.js +89 -8
  115. package/widgets/EodashMap/methods/use-map-loading.js +52 -0
  116. package/widgets/EodashProcess/index.vue +2 -1
  117. package/widgets/EodashProcess/methods/async.js +19 -8
  118. package/widgets/EodashProcess/methods/composables.js +63 -77
  119. package/widgets/EodashProcess/methods/custom-endpoints/chart/sentinelhub-endpoint.js +9 -5
  120. package/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.js +7 -4
  121. package/widgets/EodashProcess/methods/handling.js +105 -72
  122. package/widgets/EodashProcess/states.js +1 -1
  123. package/widgets/EodashStacInfo.vue +64 -2
  124. package/widgets/EodashTimeSlider/index.vue +208 -0
  125. package/widgets/EodashTimeSlider/methods/index.js +236 -0
  126. package/widgets/EodashTimeSlider/types.ts +54 -0
  127. package/dist/client/EodashMapBtns-BHrSDNoC.js +0 -435
  128. package/dist/client/EodashStacInfo-B90wobPc.js +0 -107
  129. package/dist/client/EodashTimeSlider-5vm7F3ju.js +0 -53
  130. package/dist/client/MobileLayout-DyMjaeif.js +0 -118
  131. package/dist/client/index-CugS__t5.js +0 -570
  132. package/dist/types/widgets/EodashTimeSlider.vue.d.ts +0 -15
  133. package/widgets/EodashTimeSlider.vue +0 -40
@@ -6,9 +6,12 @@ import { useSTAcStore } from "@/store/stac";
6
6
  import { storeToRefs } from "pinia";
7
7
  import { isFirstLoad } from "@/utils/states";
8
8
  import { useEmitLayersUpdate, useOnLayersUpdate } from "@/composables";
9
- import { mapPosition } from "@/store/states";
9
+ export { useEmitLayersUpdate, useOnLayersUpdate };
10
+ import { isGlobe, mapPosition } from "@/store/states";
10
11
  import { sanitizeBbox } from "@/eodashSTAC/helpers";
11
12
  import { transformExtent } from "@eox/map";
13
+
14
+ export { useMapLoading } from "./use-map-loading";
12
15
  /**
13
16
  * Holder for previous compare map view as it is overwritten by sync
14
17
  * @type { import("ol").View | null} mapElement
@@ -39,14 +42,52 @@ export const useHandleMapMoveEnd = (mapElement, mapPosition) => {
39
42
  }
40
43
  };
41
44
 
45
+ const handleGlobeMoveEnd = () => {
46
+ const camera = mapElement.value?.globe?.planet?.camera;
47
+ const lonLat = camera?.getLonLat();
48
+ if (!lonLat) return;
49
+ const { lon, lat, height } = lonLat;
50
+ if (![lon, lat, height].some(Number.isNaN)) {
51
+ mapPosition.value = [lon, lat, height];
52
+ }
53
+ };
54
+
55
+ /** @type {{ events: { off: Function } } | null} */
56
+ let subscribedCamera = null;
57
+
58
+ const subscribeGlobe = (retries = 3) => {
59
+ if (!isGlobe.value) return; // toggled back out during retry
60
+ const camera = mapElement.value?.globe?.planet?.camera;
61
+ if (camera) {
62
+ if (subscribedCamera === camera) return;
63
+ camera.events.on("moveend", handleGlobeMoveEnd);
64
+ subscribedCamera = camera;
65
+ handleGlobeMoveEnd();
66
+ return;
67
+ }
68
+ if (retries > 0) setTimeout(() => subscribeGlobe(retries - 1), 50);
69
+ };
70
+ const unsubscribeGlobe = () => {
71
+ subscribedCamera?.events.off("moveend", handleGlobeMoveEnd);
72
+ subscribedCamera = null;
73
+ };
74
+
75
+ const stopGlobeWatch = watch(isGlobe, (globe) =>
76
+ globe ? subscribeGlobe() : unsubscribeGlobe(),
77
+ );
78
+
42
79
  onMounted(() => {
43
- /** @type {import('ol/Map').default} */
44
- (mapElement.value?.map)?.on("moveend", handleMoveEnd);
80
+ const map = mapElement.value?.map;
81
+ map?.on("moveend", handleMoveEnd);
82
+ // Seed mapPosition from the initial view
83
+ handleMoveEnd(/** @type {any} */ ({ map }));
45
84
  });
46
85
 
47
86
  onUnmounted(() => {
48
87
  /** @type {import('ol/Map').default} */
49
88
  (mapElement.value?.map)?.un("moveend", handleMoveEnd);
89
+ unsubscribeGlobe();
90
+ stopGlobeWatch();
50
91
  });
51
92
  };
52
93
 
@@ -61,6 +102,7 @@ export const useHandleMapMoveEnd = (mapElement, mapPosition) => {
61
102
  * @param {import("vue").Ref<import("@eox/map").EOxMap| null>} partnerMap
62
103
  * @param {boolean} zoomToExtent
63
104
  * @param {import("vue").Ref<import("stac-ts").StacItem | import("stac-ts").StacLink | null>} [selectedItem]
105
+ * @param {Record<string, any>[]} [defaultBaseLayers]
64
106
  */
65
107
  export const useInitMap = (
66
108
  mapElement,
@@ -71,6 +113,7 @@ export const useInitMap = (
71
113
  partnerMap,
72
114
  zoomToExtent,
73
115
  selectedItem,
116
+ defaultBaseLayers,
74
117
  ) => {
75
118
  log.debug(
76
119
  "InitMap",
@@ -83,6 +126,10 @@ export const useInitMap = (
83
126
  const watching = selectedItem
84
127
  ? [selectedIndicator, datetime, selectedItem]
85
128
  : [selectedIndicator, datetime];
129
+ // Tags datetime values we set ourselves so the watcher skips its own echo.
130
+ /** @type {string | null} */
131
+ let internalDatetime = null;
132
+
86
133
  const stopIndicatorWatcher = watch(
87
134
  watching,
88
135
  async (updated, previous) => {
@@ -96,6 +143,28 @@ export const useInitMap = (
96
143
  );
97
144
 
98
145
  if (updatedStac) {
146
+ const isSameStac = updatedStac?.id === previousStac?.id;
147
+ const isSameItem = updatedItem?.id === previousItem?.id;
148
+
149
+ // Item deselect: overview render is owned by the item catalog widget.
150
+ const isItemDeselect =
151
+ previousItem &&
152
+ !updatedItem &&
153
+ isSameStac &&
154
+ updatedTime === previousTime;
155
+ if (isItemDeselect) return;
156
+
157
+ // Re-fire from our own datetime.value write, skip and clear
158
+ const isOwnDatetimeUpdate =
159
+ internalDatetime !== null &&
160
+ updatedTime === internalDatetime &&
161
+ isSameStac &&
162
+ isSameItem;
163
+ if (isOwnDatetimeUpdate) {
164
+ internalDatetime = null;
165
+ return;
166
+ }
167
+
99
168
  log.debug(
100
169
  "Selected Indicator watch triggered",
101
170
  updatedStac,
@@ -139,13 +208,14 @@ export const useInitMap = (
139
208
  updatedStac,
140
209
  eodashCols,
141
210
  updatedItem ?? updatedTime,
211
+ defaultBaseLayers,
142
212
  );
213
+
143
214
  log.debug(
144
215
  "Assigned layers after changing time only",
145
216
  JSON.parse(JSON.stringify(layersCollection)),
146
217
  );
147
218
  mapLayers.value = layersCollection;
148
-
149
219
  useEmitLayersUpdate(
150
220
  mapElement.value?.id === "compare"
151
221
  ? "compareTime:updated"
@@ -162,27 +232,38 @@ export const useInitMap = (
162
232
  if (interval && interval.length > 0 && interval[0].length > 1) {
163
233
  // @ts-expect-error this is the defined STAC structure
164
234
  endInterval = new Date(interval[0][1]);
235
+ // If end interval is in the future, set to now,
236
+ // for item fetching based on search endpoint
237
+ if (endInterval.getTime() > Date.now()) {
238
+ endInterval = new Date();
239
+ }
165
240
  log.debug(
166
241
  "Indicator load: found stac extent, setting time to latest value",
167
242
  endInterval,
168
243
  );
169
244
  }
245
+ let resolvedTime = updatedItem ?? updatedTime;
170
246
  if (
171
247
  !updatedItem &&
172
248
  endInterval !== null &&
173
249
  endInterval.toISOString() !== datetime.value &&
174
250
  !isFirstLoad.value
175
251
  ) {
176
- datetime.value = endInterval.toISOString();
252
+ resolvedTime = endInterval.toISOString();
253
+ internalDatetime = resolvedTime;
254
+ datetime.value = resolvedTime;
177
255
  } else if (isFirstLoad.value && !datetime.value && endInterval) {
178
- datetime.value = endInterval.toISOString();
256
+ resolvedTime = endInterval.toISOString();
257
+ internalDatetime = resolvedTime;
258
+ datetime.value = resolvedTime;
179
259
  }
180
260
 
181
261
  /** @type {Record<string,any>[]} */
182
262
  layersCollection = await createLayersConfig(
183
263
  updatedStac,
184
264
  eodashCols,
185
- updatedItem ?? updatedTime,
265
+ updatedItem ?? resolvedTime,
266
+ defaultBaseLayers,
186
267
  );
187
268
 
188
269
  if (zoomToExtent) {
@@ -251,7 +332,7 @@ export const useUpdateTooltipProperties = (
251
332
  * @param {string} evt */
252
333
  const listenTo = (evt) =>
253
334
  enableCompare ? evt.includes("compare") : !evt.includes("compare");
254
- useOnLayersUpdate(async (evt, _payload) => {
335
+ useOnLayersUpdate(async (evt) => {
255
336
  if (!listenTo(evt)) {
256
337
  return;
257
338
  }
@@ -0,0 +1,52 @@
1
+ import { onUnmounted, watch } from "vue";
2
+ import { loading } from "@/store/states";
3
+
4
+ /**
5
+ * Tracks map loading state at the source level via `loading.activeLoads`,
6
+ * the same counter used by the axios plugin. Re-attaches source listeners
7
+ * whenever eox-map fires `layerschanged`, using `getFlatLayersArray`.
8
+ *
9
+ * @param {import("vue").Ref<import("@eox/map").EOxMap | null>} mapElement
10
+ * @param {import("vue").Ref<import("@eox/map").EOxMap | null>} compareMapElement
11
+ */
12
+ export const useMapLoading = (mapElement, compareMapElement) => {
13
+ const startHandler = () => {
14
+ loading.activeLoads++;
15
+ };
16
+ const endHandler = () => {
17
+ loading.activeLoads--;
18
+ };
19
+
20
+ /** @param {import("@eox/map").EOxMap | null} newMapEl */
21
+ const watcherHandler = (newMapEl) => {
22
+ if (!newMapEl) return;
23
+
24
+ const hasStartListener = newMapEl.map
25
+ .getListeners("loadstart")
26
+ ?.some((listner) => listner === startHandler);
27
+ const hasEndListener = newMapEl.map
28
+ .getListeners("loadend")
29
+ ?.some((listner) => listner === endHandler);
30
+
31
+ if (!hasStartListener) {
32
+ newMapEl.map.addEventListener("loadstart", startHandler);
33
+ }
34
+ if (!hasEndListener) {
35
+ newMapEl.map.addEventListener("loadend", endHandler);
36
+ }
37
+ };
38
+ const stopMainWatcher = watch(mapElement, watcherHandler, {
39
+ immediate: true,
40
+ });
41
+ const stopCompareWatcher = watch(compareMapElement, watcherHandler, {
42
+ immediate: true,
43
+ });
44
+
45
+ onUnmounted(() => {
46
+ mapElement.value?.map.removeEventListener("loadstart", startHandler);
47
+ mapElement.value?.map.removeEventListener("loadend", endHandler);
48
+ stopMainWatcher();
49
+ stopCompareWatcher();
50
+ loading.activeLoads = 0;
51
+ });
52
+ };
@@ -70,6 +70,7 @@ const { enableCompare, vegaEmbedOptions } = defineProps({
70
70
  default: false,
71
71
  },
72
72
  vegaEmbedOptions: {
73
+ /** @type {import("vue").PropType<import("vega-embed").EmbedOptions>} */
73
74
  type: Object,
74
75
  default() {
75
76
  return { actions: true };
@@ -119,7 +120,7 @@ const jsonformKey = computed(
119
120
 
120
121
  useInitProcess({
121
122
  selectedStac: currentSelectedStac,
122
- mapElement: mapElement.value,
123
+ mapElement,
123
124
  jsonformSchema,
124
125
  isProcessed,
125
126
  processResults,
@@ -106,16 +106,27 @@ export async function updateJobsStatus(jobs, indicator) {
106
106
  jobsUrls.map((url) =>
107
107
  axios
108
108
  .get(url, { params: { t: Date.now() } })
109
- .then((response) => response.data),
109
+ .then((response) => response.data)
110
+ .catch((error) => {
111
+ if (axios.isAxiosError(error)) {
112
+ console.warn(
113
+ `Job URL not accessible: ${url}. Maybe was deleted from the processing endpoint or endpoint is unavailable. Skipping...`,
114
+ );
115
+ return null;
116
+ }
117
+ throw error;
118
+ }),
110
119
  ),
111
120
  );
112
- jobResults.sort((a, b) => {
113
- return (
114
- new Date(b.job_start_datetime).getTime() -
115
- new Date(a.job_start_datetime).getTime()
116
- );
117
- });
118
- jobs.value.splice(0, jobs.value.length, ...jobResults);
121
+ const validResults = jobResults
122
+ .filter((job) => job !== null)
123
+ .sort((a, b) => {
124
+ return (
125
+ new Date(b.job_start_datetime).getTime() -
126
+ new Date(a.job_start_datetime).getTime()
127
+ );
128
+ });
129
+ jobs.value.splice(0, jobs.value.length, ...validResults);
119
130
  }
120
131
 
121
132
  /**
@@ -1,8 +1,7 @@
1
1
  import { initProcess, updateJsonformIdentifier } from "./handling";
2
- import { useEventBus } from "@vueuse/core";
3
- import { nextTick, onMounted, watch } from "vue";
4
- import { eoxLayersKey } from "@/utils/keys";
2
+ import { nextTick, onMounted, onUnmounted, watch } from "vue";
5
3
  import { useOnLayersUpdate } from "@/composables";
4
+ import { getCompareLayers, getLayers } from "@/store/actions";
6
5
  /**
7
6
  * Composable resposible of timing the Initialization of the process
8
7
  *
@@ -15,7 +14,7 @@ import { useOnLayersUpdate } from "@/composables";
15
14
  * @param {import("vue").Ref<boolean>} params.isProcessed
16
15
  * @param {import("vue").Ref<boolean>} params.loading
17
16
  * @param {import("vue").Ref<boolean>} params.isPolling
18
- * @param {import("@eox/map").EOxMap | null} params.mapElement
17
+ * @param {import("vue").Ref<import("@eox/map").EOxMap | null>} params.mapElement
19
18
  */
20
19
  export const useInitProcess = ({
21
20
  selectedStac,
@@ -26,60 +25,45 @@ export const useInitProcess = ({
26
25
  isPolling,
27
26
  mapElement,
28
27
  }) => {
29
- const layersEvents = useEventBus(eoxLayersKey);
30
-
31
28
  onMounted(async () => {
32
- // wait for the layers to be rendered
33
- if ((mapElement?.layers.length ?? 0) > 1) {
34
- await initProcess({
35
- enableCompare: mapElement?.id === "compare",
36
- selectedStac,
37
- jsonformSchema,
38
- isProcessed,
39
- processResults,
40
- loading,
41
- isPolling,
42
- });
43
- } else {
44
- layersEvents.once(async () => {
45
- await initProcess({
46
- enableCompare: mapElement?.id === "compare",
47
- selectedStac,
48
- jsonformSchema,
49
- isProcessed,
50
- loading,
51
- processResults,
52
- isPolling,
53
- });
54
- });
55
- }
29
+ await initProcess({
30
+ enableCompare: mapElement.value?.id === "compare",
31
+ selectedStac,
32
+ jsonformSchema,
33
+ isProcessed,
34
+ processResults,
35
+ loading,
36
+ isPolling,
37
+ mapElement: mapElement.value,
38
+ });
56
39
  });
57
- const enableCompare = mapElement?.id === "compare";
58
- const evtKey = enableCompare ? "compareLayers:updated" : "layers:updated";
59
- useOnLayersUpdate(async (evt, _payload) => {
60
- if (
61
- evt == "layertime:updated" ||
62
- evt == "compareLayertime:updated" ||
63
- evt == "time:updated" ||
64
- evt == "compareTime:updated"
65
- ) {
66
- const shouldMainJsonFormUpdate =
67
- ["layertime:updated", "time:updated"].includes(evt) && !enableCompare;
68
- const shouldCompareJsonFormUpdate =
69
- ["compareLayertime:updated", "compareTime:updated"].includes(evt) &&
70
- enableCompare;
71
- // we need to update jsonform on time change in cases when the feature selection layer was time-based, so that it attaches to a correct new layer
72
- if (shouldMainJsonFormUpdate || shouldCompareJsonFormUpdate) {
73
- const newJsonForm = await updateJsonformIdentifier({
74
- jsonformSchema: jsonformSchema.value,
75
- // @ts-expect-error TODO payload coming from time update events is not an object with layers property
76
- newLayers: _payload,
77
- enableCompare,
78
- });
40
+
41
+ useOnLayersUpdate(async (evt) => {
42
+ const enableCompare = mapElement.value?.id === "compare";
43
+ const layerUpdatedKey = enableCompare
44
+ ? "compareLayers:updated"
45
+ : "layers:updated";
46
+ const timeUpdatedKeys = enableCompare
47
+ ? ["compareLayertime:updated", "compareTime:updated"]
48
+ : ["layertime:updated", "time:updated"];
49
+
50
+ if (timeUpdatedKeys.includes(evt)) {
51
+ // we need to update jsonform on time change in cases
52
+ // when the feature selection layer was time-based,
53
+ // so that it attaches to a correct new layer
54
+ const newJsonForm = await updateJsonformIdentifier({
55
+ jsonformSchema: jsonformSchema.value,
56
+ newLayers: enableCompare ? getCompareLayers() : getLayers(),
57
+ enableCompare,
58
+ mapElement: mapElement.value,
59
+ });
60
+
61
+ if (newJsonForm) {
79
62
  jsonformSchema.value = newJsonForm;
80
63
  }
81
64
  }
82
- if (evt !== evtKey) {
65
+
66
+ if (evt !== layerUpdatedKey) {
83
67
  return;
84
68
  }
85
69
  await initProcess({
@@ -90,6 +74,7 @@ export const useInitProcess = ({
90
74
  processResults,
91
75
  loading,
92
76
  isPolling,
77
+ mapElement: mapElement.value,
93
78
  });
94
79
  });
95
80
  };
@@ -109,38 +94,39 @@ export function useAutoExec(
109
94
  startProcess,
110
95
  ) {
111
96
  /**
112
- * @param {CustomEvent} _e
97
+ * @param {any} _e
113
98
  **/
114
99
  const onJsonFormChange = async (_e) => {
115
100
  await startProcess();
116
101
  };
117
102
 
118
- const addEventListener = async () => {
119
- await nextTick(() => {
120
- //@ts-expect-error TODO
121
- jsonformEl.value?.addEventListener("change", onJsonFormChange);
122
- });
123
- };
124
- const removeEventListener = () => {
125
- //@ts-expect-error TODO
126
- jsonformEl.value?.removeEventListener("change", onJsonFormChange);
127
- };
128
-
129
103
  watch(jsonformSchema, (updatedSchema) => {
130
104
  autoExec.value = updatedSchema?.options?.["execute"] || false;
131
105
  });
132
106
 
133
- onMounted(() => {
134
- watch(
135
- autoExec,
136
- async (exec) => {
137
- if (exec) {
138
- await addEventListener();
139
- } else {
140
- removeEventListener();
141
- }
142
- },
143
- { immediate: true },
144
- );
107
+ // Re-attach listener whenever the element or autoExec changes
108
+ const stop = watch(
109
+ [autoExec, jsonformEl],
110
+ async ([exec, el], [_prevExec, prevEl]) => {
111
+ // Cleanup if previous element existed
112
+ if (prevEl) {
113
+ prevEl.removeEventListener("change", onJsonFormChange);
114
+ }
115
+ // Add if enabled and we have an element
116
+ if (exec && el) {
117
+ // remove listener before adding to avoid duplicates in case of element change
118
+ el.removeEventListener("change", onJsonFormChange);
119
+ await nextTick();
120
+ el.addEventListener("change", onJsonFormChange);
121
+ }
122
+ },
123
+ { immediate: true },
124
+ );
125
+
126
+ onUnmounted(() => {
127
+ if (jsonformEl.value) {
128
+ jsonformEl.value.removeEventListener("change", onJsonFormChange);
129
+ }
130
+ stop();
145
131
  });
146
132
  }
@@ -58,7 +58,7 @@ export async function handleSentinelHubProcess({
58
58
  );
59
59
 
60
60
  // fetch data from sentinel hub
61
- return await Promise.all(
61
+ const results = await Promise.all(
62
62
  timePairs.map(([to, from]) => {
63
63
  return fetchSentinelHubData({
64
64
  url: endpoint,
@@ -67,14 +67,18 @@ export async function handleSentinelHubProcess({
67
67
  from,
68
68
  to,
69
69
  exampleLink: evalScriptLink,
70
- }).catch((err) =>
70
+ }).catch((err) => {
71
71
  console.error(
72
72
  "[eodash] Error while fetching data from sentinel hub endpoint:",
73
73
  err,
74
- ),
75
- );
74
+ );
75
+ return [];
76
+ });
76
77
  }),
77
- ).then((data) => data.flat().map((data) => data.outputs.data));
78
+ )
79
+ .then((data) => data.filter((result) => result.length > 0))
80
+ .then((data) => data.flat().map((data) => data.outputs.data));
81
+ return results;
78
82
  }
79
83
 
80
84
  /**
@@ -37,7 +37,7 @@ export async function handleVedaEndpoint({
37
37
  vedaLink,
38
38
  );
39
39
  // TODO: convert jsonform bbox type to geojson in the schema to avoid the conversion here
40
- return await Promise.all(
40
+ const results = await Promise.all(
41
41
  configs.map(({ endpoint, datetime }) => {
42
42
  const url = new URL(vedaEndpoint);
43
43
  const key = vedaLink.endpoint === "veda_stac" ? "ids" : "url";
@@ -56,14 +56,17 @@ export async function handleVedaEndpoint({
56
56
  fetchedSats.date = datetime;
57
57
  return fetchedSats;
58
58
  })
59
- .catch((resp) =>
59
+ .catch((resp) => {
60
60
  console.error(
61
61
  "[eodash] Error while fetching data from veda endpoint:",
62
62
  resp,
63
- ),
64
- );
63
+ );
64
+ return null;
65
+ });
65
66
  }),
66
67
  );
68
+ // Filter out the nulls (failed requests) before returning
69
+ return results.filter((result) => result !== null);
67
70
  }
68
71
 
69
72
  /**