@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
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <v-main class="pa-0">
3
3
  <eox-layout
4
- :mediaBreakpoints="[0, 960, 1920]"
4
+ :mediaBreakpoints="[0, 960, 1921]"
5
5
  :gap="gap"
6
6
  :style="layoutStyle"
7
7
  >
@@ -1,5 +1,13 @@
1
1
  <template>
2
2
  <div class="eodash-overlay">
3
+ <div class="progress-bar-wrapper">
4
+ <v-progress-linear
5
+ :active="loading.value"
6
+ color="secondary"
7
+ indeterminate
8
+ absolute
9
+ ></v-progress-linear>
10
+ </div>
3
11
  <p>
4
12
  <a href="https://github.com/eodash/eodash" target="_blank"
5
13
  >eodash v{{ version }}</a
@@ -12,12 +20,18 @@
12
20
  </div>
13
21
  </template>
14
22
  <script setup>
15
- import { useTheme } from "vuetify";
23
+ import { useTheme, useLayout } from "vuetify";
16
24
  import pkgJson from "../../../package.json";
25
+ import { loading } from "@/store/states";
26
+ import { computed } from "vue";
27
+
17
28
  const { computedThemes } = useTheme();
29
+ const { mainRect } = useLayout();
18
30
 
19
31
  const version = pkgJson.version;
20
32
 
33
+ const topPosition = computed(() => `${mainRect.value.top}px`);
34
+
21
35
  const eoxLogo = `<svg width="100%" height="100%" viewBox="0 0 355 85" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><g id="ink_ext_XXXXXX"><path id="path5076" d="M152.986,40.52l-0.75,-0.019l-0.737,-0.056l-0.725,-0.093l-0.713,-0.127l-0.7,-0.162l-0.7,-0.196l-0.675,-0.228l-0.65,-0.261l-0.65,-0.292l-0.625,-0.319l-0.612,-0.352l-0.588,-0.377l-0.562,-0.407l-0.55,-0.431l-0.538,-0.457l-0.5,-0.481l-0.487,-0.505l-0.45,-0.528l-0.438,-0.55l-0.4,-0.57l-0.375,-0.59l-0.35,-0.609l-0.325,-0.627l-0.287,-0.645l-0.263,-0.66l-0.225,-0.676l-0.2,-0.69l-0.162,-0.704l-0.125,-0.717l-0.1,-0.728l-0.05,-0.739l-0.025,-0.748c0,-8.023 6.512,-14.532 14.537,-14.532c8.038,0 14.538,6.509 14.538,14.532c0,8.036 -6.5,14.544 -14.538,14.544Z" style="fill:none;"/><path id="path5078" d="M165.748,-0.002c-42.009,0 -76.06,18.985 -76.06,42.402c0,13.268 10.921,25.102 28.021,32.875c-8.081,-5.487 -13.403,-12.973 -14.584,-21.859c-2.685,-20.186 16.83,-40.82 45.148,-49.615c-14.687,6.665 -24.923,21.427 -24.923,38.599c0,23.218 18.648,42.046 41.773,42.383c-0.037,0.005 -0.087,0.015 -0.137,0.02c0.263,0 0.512,0.009 0.762,0.009c42.013,0 76.076,-18.984 76.076,-42.412c0,-13.261 -10.937,-25.097 -28.037,-32.871l0.75,0.522l0.736,0.531l0.713,0.543l0.7,0.555l0.687,0.566l0.664,0.578l0.649,0.588l0.625,0.6l0.613,0.609l0.588,0.621l0.574,0.631l0.562,0.643l0.538,0.652l0.513,0.662l0.5,0.672l0.475,0.684l0.449,0.693l0.438,0.703l0.425,0.713l0.387,0.723l0.375,0.73l0.352,0.74l0.336,0.75l0.3,0.76l0.287,0.77l0.264,0.777l0.25,0.787l0.211,0.795l0.188,0.805l0.175,0.812l0.151,0.82l0.125,0.831c2.675,20.19 -16.838,40.825 -45.151,49.619c14.688,-6.665 24.926,-21.426 24.926,-38.614c0,-23.202 -18.65,-42.026 -41.775,-42.367c0.05,-0.005 0.1,-0.015 0.15,-0.025c-0.262,0 -0.526,-0.01 -0.789,-0.01Zm-13.248,11.314c7.817,0 14.25,6.433 14.25,14.25c0,0.001 0,0.001 0,0.001c0,7.817 -6.433,14.249 -14.25,14.249c-7.817,0 -14.25,-6.432 -14.25,-14.249c0,-0.001 0,-0.001 0,-0.001c0,-7.817 6.433,-14.25 14.25,-14.25Z"
22
36
  style="fill:${computedThemes.value["dashboardTheme"].colors["on-secondary"]};fill-rule:nonzero;"/><path id="path5080" d="M213.786,9.529l0.75,0.521l0.738,0.532l0.712,0.544l0.7,0.555l0.688,0.566l0.662,0.577l0.65,0.588l0.625,0.6l0.613,0.61l0.587,0.62l0.575,0.631l0.563,0.643l0.537,0.652l0.513,0.663l0.5,0.672l0.475,0.684l0.45,0.692l0.437,0.703l0.425,0.712l0.388,0.723l0.375,0.731l0.35,0.741l0.337,0.75l0.3,0.76l0.288,0.769l0.262,0.777l0.25,0.786l0.213,0.797l0.187,0.804l0.175,0.812l0.15,0.821l0.125,0.83c2.675,20.19 -16.837,40.825 -45.15,49.619c14.688,-6.665 24.925,-21.426 24.925,-38.614c0,-23.202 -18.65,-42.025 -41.775,-42.367c0.05,-0.005 0.1,-0.015 0.15,-0.025c-0.262,0 -0.525,-0.01 -0.787,-0.01c-42.01,0 -76.062,18.985 -76.062,42.402c0,13.268 10.922,25.103 28.022,32.876c-8.081,-5.487 -13.403,-12.973 -14.584,-21.859c-2.685,-20.187 16.831,-40.82 45.149,-49.615c-14.688,6.665 -24.925,21.426 -24.925,38.598c0,23.218 18.65,42.046 41.775,42.383c-0.038,0.005 -0.088,0.015 -0.138,0.02c0.263,0 0.513,0.01 0.763,0.01c42.012,-0.001 76.075,-18.985 76.075,-42.413c0,-13.261 -10.938,-25.097 -28.038,-32.871Z" style="fill:none;"/><path id="path5082" d="M354.323,82.586l-41.999,-42.002l38.524,-38.515l-29.913,0l-23.562,23.559l-23.563,-23.559l-29.924,0l38.525,38.515l-42,42.002l29.913,0l27.049,-27.046l27.05,27.046l29.9,0"
23
37
  style="fill:${computedThemes.value["dashboardTheme"].colors["on-secondary"]};fill-rule:nonzero;"/><path id="path5084" d="M354.323,82.586l-41.999,-42.002l38.524,-38.515l-29.913,0l-23.562,23.559l-23.563,-23.559l-29.924,0l38.525,38.515l-42,42.002l29.913,0l27.049,-27.046l27.05,27.046l29.9,0Z" style="fill:none;"/><path id="path5086" d="M0,2.069l75.033,0l0,16.489l-51.629,0l0,14.931l40.258,0l0,16.495l-40.258,0l0,16.05l53.124,0l0,16.488l-76.528,0l0,-80.453"
@@ -26,7 +40,7 @@ const base64Logo = btoa(eoxLogo);
26
40
  </script>
27
41
  <style scoped lang="scss">
28
42
  .eodash-overlay {
29
- position: fixed;
43
+ position: absolute;
30
44
  top: 0;
31
45
  left: 0;
32
46
  width: 100%;
@@ -40,10 +54,19 @@ const base64Logo = btoa(eoxLogo);
40
54
  );
41
55
  z-index: 9999;
42
56
  pointer-events: none;
57
+
58
+ .progress-bar-wrapper {
59
+ position: absolute;
60
+ top: v-bind("topPosition");
61
+ left: 0;
62
+ width: 100%;
63
+ z-index: 10000;
64
+ }
65
+
43
66
  p {
44
67
  position: fixed;
45
- bottom: 6px;
46
- left: 24px;
68
+ bottom: 8px;
69
+ left: 162px;
47
70
  color: rgba(var(--v-theme-on-secondary), 1);
48
71
  }
49
72
  a {
@@ -7,7 +7,6 @@ import { inject, reactive } from "vue";
7
7
  *
8
8
  * @async
9
9
  * @param {string | undefined| (()=> Promise<import("@/types").Eodash>) | Function} runtimeConfig
10
- * @returns {Promise<import("@/types").Eodash | null | undefined>}
11
10
  * @see {@linkplain '@/eodash.js'}
12
11
  */
13
12
  export const useEodashRuntime = async (
@@ -88,7 +88,9 @@ export const useDefineWidgets = (widgetConfigs) => {
88
88
  config
89
89
  )?.defineWidget(updatedStac, updatedCompareStac);
90
90
  if (definedConfig) {
91
- definedConfig = reactive(definedConfig);
91
+ definedConfig = /** @type {import("@/types").StaticWidget} */ (
92
+ reactive(definedConfig)
93
+ );
92
94
  }
93
95
  definedWidget.value =
94
96
  definedConfig && definedWidget.value.id === definedConfig.id
@@ -331,11 +331,12 @@ export const useGetTemplates = () => {
331
331
  };
332
332
 
333
333
  /**
334
- * Listens to the `layers:updated` and `time:updated` events and calls
334
+ * Subscribes to layers/time update events on the shared bus, with automatic
335
+ * cleanup on component unmount.
335
336
  *
336
337
  * @param {import("@vueuse/core").EventBusListener<
337
338
  * import("@/types").LayersEventBusKeys,
338
- * {layers:Record<string,any>[]| undefined}
339
+ * Record<string,any>[] | undefined
339
340
  * >} listener
340
341
  */
341
342
  export const useOnLayersUpdate = (listener) => {
@@ -348,6 +349,9 @@ export const useOnLayersUpdate = (listener) => {
348
349
  });
349
350
  };
350
351
  /**
352
+ * Emits a layers-update event on the shared bus once the map has applied its
353
+ * pending updates. Always pass the full layers array, not a partial subset.
354
+ *
351
355
  * @param {import("@/types").LayersEventBusKeys} event
352
356
  * @param {import("@eox/map").EOxMap | null} mapEl
353
357
  * @param {Record<string,any>[]} layers
@@ -4,6 +4,7 @@ import {
4
4
  extractLayerConfig,
5
5
  extractRoles,
6
6
  fetchApiItems,
7
+ fetchPreAggregations,
7
8
  fetchStyle,
8
9
  fetchAllStyles,
9
10
  findLayer,
@@ -15,11 +16,7 @@ import {
15
16
  extractLayerTimeValues,
16
17
  replaceLayer,
17
18
  } from "./helpers";
18
- import {
19
- getLayers,
20
- getCompareLayers,
21
- registerProjection,
22
- } from "@/store/actions";
19
+ import { getLayers, registerProjection } from "@/store/actions";
23
20
  import {
24
21
  createLayerFromRender,
25
22
  createLayersFromAssets,
@@ -28,8 +25,6 @@ import {
28
25
  import axios from "@/plugins/axios";
29
26
  import log from "loglevel";
30
27
  import { dataThemesBrands } from "@/utils/states";
31
- import { useEventBus } from "@vueuse/core";
32
- import { eoxLayersKey } from "@/utils/keys";
33
28
 
34
29
  export class EodashCollection {
35
30
  #collectionUrl = "";
@@ -179,11 +174,13 @@ export class EodashCollection {
179
174
  // will try to extract anything it supports but for which we have
180
175
  // less control.
181
176
 
182
- const { layerDatetime, timeControlValues } = extractLayerTimeValues(
183
- await this.getItems(),
177
+ const itemDate =
184
178
  item.properties?.datetime ??
185
- item.properties.start_datetime ??
186
- itemDatetime,
179
+ item.properties.start_datetime ??
180
+ itemDatetime;
181
+ const { layerDatetime, timeControlValues } = extractLayerTimeValues(
182
+ await this.getDates(itemDate),
183
+ itemDate,
187
184
  );
188
185
 
189
186
  const dataAssets = Object.keys(item?.assets ?? {}).reduce((data, ast) => {
@@ -210,6 +207,10 @@ export class EodashCollection {
210
207
  timeControlValues,
211
208
  timeControlProperty: "TIME",
212
209
  }),
210
+ ...(!!this.#collectionStac?.["eodash:layerExclusive"] && {
211
+ layerControlExclusive: true,
212
+ layerControlExpand: false,
213
+ }),
213
214
  };
214
215
 
215
216
  const links = await createLayersFromLinks(
@@ -230,6 +231,7 @@ export class EodashCollection {
230
231
  item,
231
232
  layerDatetime,
232
233
  extraProperties,
234
+ this.#collectionStac,
233
235
  )),
234
236
  ...((this.rasterEndpoint &&
235
237
  (await createLayerFromRender(
@@ -285,24 +287,33 @@ export class EodashCollection {
285
287
 
286
288
  /**
287
289
  * Returns all item links sorted by datetime ascendingly
288
- * @param {boolean} [fields=false] if true, fetch items from API with only properties
290
+ * @param {boolean} [fields=false] if true, fetch items from API with only properties.datetime to optimize performance
289
291
  * @param {boolean} [first] - if true, returns the first page of items only (for API collections)
292
+ * @param {string | Date} [centerDatetime] - Date to center the search around if items exceed maxNumber
290
293
  * @returns {Promise<import("stac-ts").StacLink[] | import("stac-ts").StacItem[] | undefined>}
291
294
  */
292
- async getItems(fields = false, first = false) {
295
+ async getItems(fields = false, first = false, centerDatetime = undefined) {
293
296
  const items = this.#collectionStac?.links.filter((i) => i.rel === "item");
294
-
295
- if (this.isAPI && !items?.length) {
297
+ if (this.isAPI && !items?.length && !first) {
296
298
  const itemUrl = this.#collectionUrl + "/items";
297
299
  if (fields) {
298
300
  return await fetchApiItems(
299
301
  itemUrl,
300
- `fields=properties,-assets,-geometry,-links,-bbox`,
302
+ `fields=properties.datetime,-assets,-geometry,-links,-bbox`,
301
303
  100,
302
304
  first,
305
+ 1000,
306
+ centerDatetime,
303
307
  );
304
308
  }
305
- return await fetchApiItems(itemUrl, undefined, 100, first);
309
+ return await fetchApiItems(
310
+ itemUrl,
311
+ undefined,
312
+ 100,
313
+ first,
314
+ 100,
315
+ centerDatetime,
316
+ );
306
317
  }
307
318
 
308
319
  const datetimeProperty = getDatetimeProperty(this.#collectionStac?.links);
@@ -321,9 +332,34 @@ export class EodashCollection {
321
332
  );
322
333
  }
323
334
 
324
- async getDates() {
325
- const items = await this.getItems(true, false);
335
+ /**
336
+ * Returns all available dates for the collection, sorted as the source
337
+ * provides. Tries the daily `pre-aggregation` link first (cheap, single
338
+ * request), falls back to fetching items via the API. Use anywhere the
339
+ * collection's date list is needed (date picker, mosaic time control,
340
+ * single-item time slider).
341
+ *
342
+ * NOTE: only the `daily` aggregation interval is consumed today. Other
343
+ * intervals (`monthly`, `hourly`) fall through to the API path.
344
+ *
345
+ * @param {string | Date} [centerDatetime]
346
+ * @returns {Promise<Date[]>}
347
+ */
348
+ async getDates(centerDatetime) {
349
+ await this.fetchCollection();
326
350
 
351
+ const aggregation = await fetchPreAggregations(
352
+ this.#collectionStac,
353
+ this.#collectionUrl,
354
+ );
355
+ const datetimeAgg = aggregation?.aggregations?.find(
356
+ (/** @type {any} */ a) => a.key?.startsWith("datetime_") || a.interval,
357
+ );
358
+ if (datetimeAgg?.buckets) {
359
+ return datetimeAgg.buckets.map((/** @type {any} */ b) => new Date(b.key));
360
+ }
361
+
362
+ const items = await this.getItems(true, false, centerDatetime);
327
363
  const datetimeProperty = getDatetimeProperty(items);
328
364
  if (!datetimeProperty || !items?.length) {
329
365
  return [];
@@ -349,21 +385,33 @@ export class EodashCollection {
349
385
  * @return {Promise<import("stac-ts").StacItem | import("stac-ts").StacLink | undefined>} item
350
386
  **/
351
387
  async getItem(date) {
352
- if (!date) {
353
- const items = await this.getItems(false, true);
354
- // in case no datetime property is found, return the last item
388
+ let items = await this.getItems(false, true);
389
+ if (!(date instanceof Date) || isNaN(date.getTime())) {
390
+ // in case no date was provided, return the last item
355
391
  return items && items.at(-1);
356
392
  }
357
393
 
358
- const items = await this.getItems();
394
+ if (this.isAPI) {
395
+ const urlArr = this.#collectionUrl.split("/").slice(0, -2);
396
+ const searchURL = urlArr.join("/") + "/search";
397
+ const targetItem = await axios
398
+ .get(searchURL, {
399
+ params: {
400
+ collections: this.#collectionStac?.id,
401
+ datetime: `../${date.toISOString()}`,
402
+ limit: 1,
403
+ sortby: "-datetime",
404
+ },
405
+ })
406
+ .then((resp) => resp.data?.features?.[0]);
407
+ return targetItem;
408
+ }
359
409
  const datetimeProperty = getDatetimeProperty(items);
360
410
  if (!datetimeProperty) {
361
- // in case no datetime property is found, return the last item
362
- const items = await this.getItems(false, true);
363
411
  // in case no datetime property is found, return the last item
364
412
  return items && items.at(-1);
365
413
  }
366
- return (await this.getItems())?.sort((a, b) => {
414
+ return items?.sort((a, b) => {
367
415
  const distanceA = Math.abs(
368
416
  new Date(
369
417
  /** @type {number} */ (
@@ -403,15 +451,14 @@ export class EodashCollection {
403
451
  }
404
452
 
405
453
  /**
406
- *
407
454
  * @param {string} datetime
408
- * @param {string} layer
409
- * @param {string} map
455
+ * @param {string} layerId
456
+ * @param {import("@eox/map").EoxLayer[]} currentLayers
410
457
  */
411
- async updateLayerJson(datetime, layer, map) {
458
+ async updateLayerJson(datetime, layerId, currentLayers) {
412
459
  await this.fetchCollection();
413
460
  const datetimeProperty = getDatetimeProperty(
414
- await this.getItems(true, true),
461
+ await this.getItems(false, true),
415
462
  );
416
463
  if (!datetimeProperty) {
417
464
  console.warn("[eodash] no datetime property found in collection");
@@ -443,12 +490,7 @@ export class EodashCollection {
443
490
  newLayers = await this.createLayersJson(specifiedLink);
444
491
  }
445
492
 
446
- let currentLayers = getLayers();
447
- if (map === "second") {
448
- currentLayers = getCompareLayers();
449
- }
450
-
451
- const oldLayer = findLayer(currentLayers, layer);
493
+ const oldLayer = findLayer(currentLayers, layerId);
452
494
 
453
495
  const toBeReplacedLayers = findLayersByLayerPrefix(currentLayers, oldLayer);
454
496
 
@@ -462,14 +504,6 @@ export class EodashCollection {
462
504
  newLayers,
463
505
  );
464
506
 
465
- // Emit event to update potential widget dependencies such as process layer ids
466
- const layersEvents = useEventBus(eoxLayersKey);
467
- if (map === "second") {
468
- layersEvents.emit("compareLayertime:updated", newLayers);
469
- } else {
470
- layersEvents.emit("layertime:updated", newLayers);
471
- }
472
-
473
507
  return updatedLayers;
474
508
  }
475
509
 
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Keys that are catalog based and have dedicated parameters
3
+ * sent to a remote API (e.g. TiTiler, eoAPI STAC search).
4
+ * @type {string[]}
5
+ */
6
+ const SKIP_KEYS = ["collection", "datetime", "bbox"];
7
+
8
+ /**
9
+ * Strips the "properties." prefix that eox-itemfilter catalog configs add to
10
+ * item property keys (e.g. "properties.eo:cloud_cover" -> "eo:cloud_cover").
11
+ * Keys without the prefix are returned unchanged.
12
+ * @param {string} key
13
+ * @returns {string}
14
+ */
15
+ function normalizeFilterKey(key) {
16
+ return key.startsWith("properties.") ? key.slice("properties.".length) : key;
17
+ }
18
+
19
+ /**
20
+ * Builds a CQL2-text filter string from an eox-itemfilter filters record.
21
+ *
22
+ * Handles range, multiselect, and select filter types.
23
+ * - Strips "properties." prefix from keys (catalog eox-itemfilter convention).
24
+ * - Double-quotes property names that contain non-word characters (e.g. "eo:cloud_cover").
25
+ * - Skips catalog-only keys (e.g. "collection").
26
+ *
27
+ * Compatible with both TiTiler's `filter` param and the STAC API `filter` param
28
+ * (both accept CQL2-text).
29
+ *
30
+ * @param {import("@/types").ItemFilterFilters | null | undefined} filters
31
+ * @returns {string}
32
+ */
33
+ export function buildCqlFilter(filters) {
34
+ if (!filters) return "";
35
+
36
+ /** @type {string[]} */
37
+ const parts = [];
38
+
39
+ for (const filter of Object.values(filters)) {
40
+ if (!filter?.key || SKIP_KEYS.includes(filter.key)) continue;
41
+
42
+ const key = normalizeFilterKey(filter.key);
43
+ const prop = /\W/.test(key) ? `"${key}"` : key;
44
+
45
+ if (filter.type === "range" && filter.state) {
46
+ const { min, max } = filter.state;
47
+ if (min != null && min > (filter.min ?? -Infinity)) {
48
+ parts.push(`${prop} >= ${min}`);
49
+ }
50
+ if (max != null && max < (filter.max ?? Infinity)) {
51
+ parts.push(`${prop} <= ${max}`);
52
+ }
53
+ } else if (
54
+ filter.type === "multiselect" &&
55
+ filter.stringifiedState?.length
56
+ ) {
57
+ parts.push(`${prop} IN (${filter.stringifiedState})`);
58
+ } else if (filter.type === "select" && filter.stringifiedState) {
59
+ parts.push(`${prop} = '${filter.stringifiedState}'`);
60
+ }
61
+ }
62
+
63
+ return parts.join(" AND ");
64
+ }