@eodash/eodash 5.1.0 → 5.3.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 (133) hide show
  1. package/core/client/components/DashboardLayout.vue +1 -2
  2. package/core/client/components/EodashOverlay.vue +4 -5
  3. package/core/client/components/MobileLayout.vue +42 -21
  4. package/core/client/composables/index.js +54 -60
  5. package/core/client/eodashSTAC/EodashCollection.js +199 -108
  6. package/core/client/eodashSTAC/auth.js +86 -0
  7. package/core/client/eodashSTAC/createLayers.js +234 -4
  8. package/core/client/eodashSTAC/helpers.js +281 -59
  9. package/core/client/eodashSTAC/parquet.js +0 -13
  10. package/core/client/eodashSTAC/triggers.js +1 -1
  11. package/core/client/store/actions.js +14 -0
  12. package/core/client/store/stac.js +46 -8
  13. package/core/client/store/states.js +6 -0
  14. package/core/client/types.ts +206 -3
  15. package/core/client/utils/bands-editor/arithmetic.js +144 -0
  16. package/core/client/utils/bands-editor/colors.js +36 -0
  17. package/core/client/utils/bands-editor/dom.js +196 -0
  18. package/core/client/utils/bands-editor/exampleSchema.json +1320 -0
  19. package/core/client/utils/bands-editor/index.js +68 -0
  20. package/core/client/utils/bands-editor/rgb.js +102 -0
  21. package/core/client/utils/index.js +5 -2
  22. package/core/client/views/Dashboard.vue +1 -1
  23. package/core/client/vite-env.d.ts +122 -0
  24. package/dist/client/{DashboardLayout-ByVs1DrY.js → DashboardLayout-Cq15p4TH.js} +5 -6
  25. package/dist/client/{DynamicWebComponent-C3W7HSQm.js → DynamicWebComponent-Cv-fPRG1.js} +1 -1
  26. package/dist/client/{EodashDatePicker-BIAf1sMT.js → EodashDatePicker-CPlJwEIO.js} +20 -22
  27. package/dist/client/{EodashItemFilter-DPznh8UB.js → EodashItemFilter-Ydebgbjj.js} +46 -31
  28. package/dist/client/EodashLayerControl-COhrkNEs.js +1517 -0
  29. package/dist/client/{EodashLayoutSwitcher-C5qTEffW.js → EodashLayoutSwitcher-pnKhTRZV.js} +4 -4
  30. package/dist/client/EodashMapBtns-Cj0Fx119.js +301 -0
  31. package/dist/client/{EodashStacInfo-CSvvF2jI.js → EodashStacInfo-Dadkg_Nj.js} +1 -1
  32. package/dist/client/EodashTimeSlider-CpoHX0S7.js +53 -0
  33. package/dist/client/{EodashTools-Cv1SXQ5y.js → EodashTools-UGBG7KC9.js} +10 -7
  34. package/dist/client/{ExportState-D-iuwaad.js → ExportState-GtJkAqeZ.js} +145 -121
  35. package/dist/client/{Footer-CyF0zRAk.js → Footer-D3ZPG5c4.js} +1 -1
  36. package/dist/client/{Header-CgD8jDKU.js → Header-z6AK-wpN.js} +2 -3
  37. package/dist/client/MobileLayout-BXNsNftb.js +118 -0
  38. package/dist/client/{PopUp-BsYLvWch.js → PopUp-BbQdjENV.js} +79 -44
  39. package/dist/client/{ProcessList-C2xsLU2_.js → ProcessList-C6VsdsYI.js} +18 -12
  40. package/dist/client/{VImg-OHe8YTs2.js → VImg-CxaMSB99.js} +203 -5
  41. package/dist/client/{VMain-PryTLU4a.js → VMain-Ds7yw0wj.js} +1 -1
  42. package/dist/client/{VTooltip-DZ0fjpB3.js → VTooltip-Cze6CEVh.js} +2 -3
  43. package/dist/client/{WidgetsContainer-B9LBadcC.js → WidgetsContainer-D66bj-JJ.js} +1 -1
  44. package/dist/client/asWebComponent-CWbNRdf9.js +8895 -0
  45. package/dist/client/{async-DkSu_u2K.js → async-BA7oWCMX.js} +69 -5
  46. package/dist/client/easing-CH0-9wR8.js +35 -0
  47. package/dist/client/eo-dash.js +1 -1
  48. package/dist/client/{VOverlay-yUn7p-Uf.js → forwardRefs-BUfxOIo-.js} +308 -28
  49. package/dist/client/{handling-CgmFXkW6.js → handling-DlNTtKB-.js} +27 -6
  50. package/dist/client/{helpers-Dy0Q13tP.js → helpers-CtE0W7iu.js} +595 -278
  51. package/dist/client/{index-skjhlH8u.js → index-CeEZIjO6.js} +26 -13
  52. package/dist/client/{index-Ch_HchK3.js → index-CsKbRDeN.js} +238 -77
  53. package/dist/client/{index-Dqj4tbx2.js → index-D4_NRKrf.js} +2 -2
  54. package/dist/client/index-DeECc3lV.js +571 -0
  55. package/dist/client/material-symbols-outlined.woff2 +0 -0
  56. package/dist/client/material-symbols-rounded.woff2 +0 -0
  57. package/dist/client/material-symbols-sharp.woff2 +0 -0
  58. package/dist/client/material-symbols-subset.woff2 +0 -0
  59. package/dist/client/templates.js +106 -49
  60. package/dist/client/{transition-C98Yn4Vo.js → transition-Byvp3L6Y.js} +1 -1
  61. package/dist/node/cli.js +6 -6
  62. package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +24 -10
  63. package/dist/types/core/client/eodashSTAC/auth.d.ts +7 -0
  64. package/dist/types/core/client/eodashSTAC/createLayers.d.ts +15 -3
  65. package/dist/types/core/client/eodashSTAC/helpers.d.ts +51 -15
  66. package/dist/types/core/client/plugins/vuetify.d.ts +14 -14
  67. package/dist/types/core/client/store/actions.d.ts +2 -0
  68. package/dist/types/core/client/store/stac.d.ts +16 -7
  69. package/dist/types/core/client/store/states.d.ts +4 -0
  70. package/dist/types/core/client/types.d.ts +171 -3
  71. package/dist/types/core/client/utils/bands-editor/arithmetic.d.ts +8 -0
  72. package/dist/types/core/client/utils/bands-editor/colors.d.ts +15 -0
  73. package/dist/types/core/client/utils/bands-editor/dom.d.ts +42 -0
  74. package/dist/types/core/client/utils/bands-editor/index.d.ts +20 -0
  75. package/dist/types/core/client/utils/bands-editor/rgb.d.ts +15 -0
  76. package/dist/types/core/client/utils/index.d.ts +1 -1
  77. package/dist/types/templates/baseConfig.d.ts +87 -1
  78. package/dist/types/templates/compare.d.ts +0 -25
  79. package/dist/types/templates/expert.d.ts +17 -21
  80. package/dist/types/templates/explore.d.ts +67 -0
  81. package/dist/types/templates/index.d.ts +1 -1
  82. package/dist/types/templates/{light.d.ts → lite.d.ts} +9 -0
  83. package/dist/types/widgets/EodashItemCatalog/index.vue.d.ts +21 -0
  84. package/dist/types/widgets/EodashItemCatalog/methods/filters.d.ts +49 -0
  85. package/dist/types/widgets/EodashItemCatalog/methods/handlers.d.ts +4 -0
  86. package/dist/types/widgets/EodashItemCatalog/methods/map.d.ts +12 -0
  87. package/dist/types/widgets/EodashItemCatalog/types.d.ts +14 -0
  88. package/dist/types/widgets/{EodashMapBtns.vue.d.ts → EodashMap/EodashMapBtns.vue.d.ts} +6 -0
  89. package/dist/types/widgets/EodashMap/index.vue.d.ts +114 -0
  90. package/dist/types/widgets/EodashMap/methods/create-layers-config.d.ts +1 -1
  91. package/dist/types/widgets/EodashMap/methods/index.d.ts +1 -1
  92. package/dist/types/widgets/EodashProcess/methods/async.d.ts +1 -0
  93. package/dist/types/widgets/EodashProcess/methods/custom-endpoints/layers/eoxhub-workspaces-endpoint.d.ts +1 -1
  94. package/dist/types/widgets/EodashTimeSlider.vue.d.ts +7 -0
  95. package/dist/types/widgets/EodashTools.vue.d.ts +10 -10
  96. package/dist/types/widgets/ExportState.vue.d.ts +2 -0
  97. package/package.json +31 -28
  98. package/templates/baseConfig.js +10 -5
  99. package/templates/compare.js +2 -22
  100. package/templates/expert.js +19 -18
  101. package/templates/explore.js +62 -0
  102. package/templates/index.js +1 -1
  103. package/templates/{light.js → lite.js} +11 -2
  104. package/widgets/EodashDatePicker.vue +15 -18
  105. package/widgets/EodashItemCatalog/index.vue +161 -0
  106. package/widgets/EodashItemCatalog/methods/filters.js +216 -0
  107. package/widgets/EodashItemCatalog/methods/handlers.js +50 -0
  108. package/widgets/EodashItemCatalog/methods/map.js +144 -0
  109. package/widgets/EodashItemCatalog/types.ts +15 -0
  110. package/widgets/EodashItemFilter.vue +35 -28
  111. package/widgets/EodashLayerControl.vue +10 -6
  112. package/widgets/EodashLayoutSwitcher.vue +1 -1
  113. package/widgets/EodashMap/EodashMapBtns.vue +278 -0
  114. package/widgets/EodashMap/index.vue +263 -38
  115. package/widgets/EodashMap/methods/create-layers-config.js +9 -6
  116. package/widgets/EodashMap/methods/index.js +27 -13
  117. package/widgets/EodashProcess/ProcessList.vue +13 -1
  118. package/widgets/EodashProcess/index.vue +17 -1
  119. package/widgets/EodashProcess/methods/async.js +22 -1
  120. package/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.js +25 -3
  121. package/widgets/EodashProcess/methods/handling.js +2 -0
  122. package/widgets/EodashProcess/methods/outputs.js +1 -0
  123. package/widgets/EodashProcess/methods/utils.js +45 -1
  124. package/widgets/EodashTimeSlider.vue +40 -0
  125. package/widgets/EodashTools.vue +7 -3
  126. package/widgets/ExportState.vue +53 -22
  127. package/dist/client/EodashLayerControl-Bhxjw4V2.js +0 -154
  128. package/dist/client/EodashMapBtns-WoGq8MuV.js +0 -173
  129. package/dist/client/MobileLayout-EKQ_kpSh.js +0 -1226
  130. package/dist/client/asWebComponent-By_7_JjS.js +0 -19193
  131. package/dist/client/forwardRefs-BXxrv98s.js +0 -272
  132. package/dist/client/index-BuhOHXKv.js +0 -199
  133. package/widgets/EodashMapBtns.vue +0 -155
@@ -1,45 +1,84 @@
1
1
  <template>
2
- <eox-map-compare
3
- class="fill-height fill-width overflow-none"
4
- .enabled="showCompare"
5
- >
6
- <eox-map
2
+ <span>
3
+ <eox-map-compare
7
4
  class="fill-height fill-width overflow-none"
8
- slot="first"
9
- ref="eoxMap"
10
- id="main"
11
- .animationOptions="animationOptions"
12
- .center="initialCenter"
13
- .zoom="initialZoom"
14
- .layers="eoxMapLayers"
15
- .controls="controls"
5
+ .enabled="showCompare"
16
6
  >
17
- <eox-map-tooltip
18
- :style="mainTooltipStyles"
19
- .propertyTransform="tooltipPropertyTransform('main')"
20
- />
21
- </eox-map>
22
- <eox-map
23
- class="fill-height fill-width overflow-none"
24
- id="compare"
25
- slot="second"
26
- ref="compareMap"
27
- .layers="eoxMapCompareLayers"
7
+ <eox-map
8
+ class="fill-height fill-width overflow-none"
9
+ slot="first"
10
+ ref="eoxMap"
11
+ id="main"
12
+ .animationOptions="animationOptions"
13
+ .center="initialCenter"
14
+ .zoom="initialZoom"
15
+ .layers="eoxMapLayers"
16
+ .controls="controls"
17
+ >
18
+ <eox-map-tooltip
19
+ :style="mainTooltipStyles"
20
+ .propertyTransform="tooltipPropertyTransform('main')"
21
+ />
22
+ </eox-map>
23
+ <eox-map
24
+ class="fill-height fill-width overflow-none"
25
+ id="compare"
26
+ slot="second"
27
+ ref="compareMap"
28
+ .layers="eoxMapCompareLayers"
29
+ >
30
+ <eox-map-tooltip
31
+ :style="compareTooltipStyles"
32
+ .propertyTransform="tooltipPropertyTransform('compare')"
33
+ />
34
+ </eox-map>
35
+ </eox-map-compare>
36
+ <div
37
+ v-if="enableCursorCoordinates"
38
+ id="cursor-coordinates"
39
+ ref="cursor-coords"
40
+ />
41
+ <span v-if="enableScaleLine" id="scale-line" ref="scale-line" />
42
+ <div
43
+ class="map-buttons-container"
44
+ :style="`margin: ${btnsPosition.gap}px 0 ${btnsPosition.gap}px 0`"
28
45
  >
29
- <eox-map-tooltip
30
- :style="compareTooltipStyles"
31
- .propertyTransform="tooltipPropertyTransform('compare')"
46
+ <!-- prettier-ignore -->
47
+ <EodashMapBtns
48
+ :style="{
49
+ gridColumn: (indicator || compareIndicator) ? responsiveX : '12',
50
+ gridRow: responsiveY,
51
+ }"
52
+ :exportMap="(indicator || compareIndicator) ? btnsProps.exportMap : false"
53
+ :changeProjection="(indicator || compareIndicator) ? btnsProps.changeProjection : false
54
+ "
55
+ :compareIndicators="(indicator || compareIndicator) ? btnsProps.compareIndicators : false
56
+ "
57
+ :backToPOIs="(indicator || compareIndicator) ? btnsProps.backToPOIs : false
58
+ "
59
+ :enableSearch="(indicator || compareIndicator) ? btnsProps.enableSearch : false
60
+ "
61
+ :enableZoom="(indicator || compareIndicator) ? btnsProps.enableZoom : false
62
+ "
32
63
  />
33
- </eox-map>
34
- </eox-map-compare>
64
+ </div>
65
+ </span>
35
66
  </template>
36
67
  <script setup>
37
68
  import "@eox/map";
38
69
  import "@eox/map/src/plugins/advancedLayersAndSources";
39
- import { computed, onMounted, ref, toRaw } from "vue";
40
- import { datetime, mapEl, mapPosition, mapCompareEl } from "@/store/states";
70
+ import { computed, onMounted, ref, toRaw, useTemplateRef } from "vue";
71
+ import {
72
+ datetime,
73
+ mapEl,
74
+ mapPosition,
75
+ mapCompareEl,
76
+ indicator,
77
+ compareIndicator,
78
+ } from "@/store/states";
41
79
  import { storeToRefs } from "pinia";
42
80
  import { useSTAcStore } from "@/store/stac";
81
+ import { useDisplay } from "vuetify";
43
82
  import {
44
83
  eodashCollections,
45
84
  eodashCompareCollections,
@@ -53,6 +92,7 @@ import {
53
92
  } from "^/EodashMap/methods";
54
93
  import { inAndOut } from "ol/easing.js";
55
94
  import mustache from "mustache";
95
+ import EodashMapBtns from "^/EodashMap/EodashMapBtns.vue";
56
96
 
57
97
  const props = defineProps({
58
98
  enableCompare: {
@@ -73,18 +113,130 @@ const props = defineProps({
73
113
  type: Boolean,
74
114
  default: true,
75
115
  },
116
+ enableCursorCoordinates: {
117
+ type: Boolean,
118
+ default: true,
119
+ },
120
+ enableScaleLine: {
121
+ type: Boolean,
122
+ default: true,
123
+ },
124
+ btnsPosition: {
125
+ type: Object,
126
+ default: () => ({
127
+ x: "12/9/10",
128
+ y: 1,
129
+ gap: 16,
130
+ }),
131
+ },
132
+ btns: {
133
+ /** @type {import("vue").PropType<{
134
+ * enableExportMap?: boolean;
135
+ * enableChangeProjection?: boolean;
136
+ * enableBackToPOIs?: boolean;
137
+ * enableSearch?: boolean;
138
+ * enableZoom?: boolean;
139
+ * enableCompareIndicators?: boolean | {
140
+ * compareTemplate?:string;
141
+ * fallbackTemplate?:string;
142
+ * itemFilterConfig?:InstanceType<import("../EodashItemFilter.vue").default>["$props"]
143
+ * };
144
+ * }> }*/
145
+ type: Object,
146
+ default: () => ({
147
+ enableExportMap: true,
148
+ enableChangeProjection: true,
149
+ enableCompareIndicators: true,
150
+ enableBackToPOIs: true,
151
+ enableSearch: true,
152
+ enableZoom: true,
153
+ }),
154
+ },
76
155
  });
77
156
 
157
+ // Responsive positioning logic
158
+ const { width } = useDisplay();
159
+
160
+ /**
161
+ * Parse responsive string values (e.g., "1/5/10") into values for different screen sizes
162
+ * Breakpoints: [0, 960, 1920] based on properties passed to eox-layout in DashboardLayout.vue
163
+ * @param {string | number} value
164
+ * @returns {number}
165
+ */
166
+ const parseResponsiveValue = (value) => {
167
+ if (typeof value === "number") {
168
+ return value;
169
+ }
170
+ if (typeof value === "string") {
171
+ const parts = value.split("/");
172
+ const currentWidth = width.value;
173
+
174
+ if (currentWidth < 960) {
175
+ return parseInt(parts[0]) || 1;
176
+ } else if (currentWidth < 1920) {
177
+ return parseInt(parts[1] || parts[0]) || 1;
178
+ } else {
179
+ return parseInt(parts[2] || parts[1] || parts[0]) || 1;
180
+ }
181
+ }
182
+ return 1;
183
+ };
184
+
185
+ const responsiveX = computed(() => parseResponsiveValue(props.btnsPosition.x));
186
+ const responsiveY = computed(() => parseResponsiveValue(props.btnsPosition.y));
187
+ const btnsProps = computed(() => ({
188
+ exportMap: props.btns.enableExportMap ?? true,
189
+ changeProjection: props.btns.enableChangeProjection ?? true,
190
+ compareIndicators: props.btns.enableCompareIndicators ?? true,
191
+ backToPOIs: props.btns.enableBackToPOIs ?? true,
192
+ enableSearch: props.btns.enableSearch ?? true,
193
+ enableZoom: props.btns.enableZoom ?? true,
194
+ }));
195
+
196
+ // Prepare containers for scale line and cursor coordinates
197
+ const scaleLineRef = useTemplateRef("scale-line");
198
+ const cursorCoordsRef = useTemplateRef("cursor-coords");
199
+
78
200
  /** @type {import("vue").Ref<Exclude<import("@/types").EodashStyleJson["tooltip"], undefined>>} */
79
201
  const tooltipProperties = ref([]);
80
202
  /** @type {import("vue").Ref<Exclude<import("@/types").EodashStyleJson["tooltip"], undefined>>} */
81
203
  const compareTooltipProperties = ref([]);
82
- /** @type {import("@eox/map").EOxMap["controls"]} */
83
- const controls = {
84
- Attribution: {
85
- collapsible: true,
86
- },
87
- };
204
+ /** @type {import("vue").ComputedRef<{
205
+ Attribution: { collapsible: boolean };
206
+ ScaleLine?: { target: HTMLElement };
207
+ MousePosition?: { projection: string; coordinateFormat: (c: [number, number]) => string; target: HTMLElement };
208
+ }>} */
209
+ const controls = computed(() => {
210
+ /** @type {{
211
+ Attribution: { collapsible: boolean };
212
+ ScaleLine?: { target: HTMLElement };
213
+ MousePosition?: { projection: string; coordinateFormat: (c: [number, number]) => string; target: HTMLElement };
214
+ }} */
215
+ const controlsObj = {
216
+ Attribution: {
217
+ collapsible: true,
218
+ },
219
+ };
220
+
221
+ if (props.enableScaleLine && scaleLineRef.value) {
222
+ controlsObj.ScaleLine = {
223
+ target: scaleLineRef.value,
224
+ };
225
+ }
226
+
227
+ if (props.enableCursorCoordinates && cursorCoordsRef.value) {
228
+ controlsObj.MousePosition = {
229
+ projection: "EPSG:4326",
230
+ coordinateFormat: (/** @type {[number, number]} */ c) => {
231
+ return `${c[1].toFixed(3)} °N, ${c[0].toFixed(3)} °E`;
232
+ },
233
+ target: cursorCoordsRef.value,
234
+ };
235
+ }
236
+
237
+ return controlsObj;
238
+ });
239
+
88
240
  const initialCenter = toRaw(props.center);
89
241
  const initialZoom = toRaw(mapPosition.value?.[2] ?? props.zoom);
90
242
  /** @type {import("vue").Ref<Record<string,any>[]>} */
@@ -128,7 +280,8 @@ const showCompare = computed(() =>
128
280
  useHandleMapMoveEnd(eoxMap, mapPosition);
129
281
 
130
282
  onMounted(() => {
131
- const { selectedCompareStac, selectedStac } = storeToRefs(useSTAcStore());
283
+ const { selectedCompareStac, selectedStac, selectedItem } =
284
+ storeToRefs(useSTAcStore());
132
285
  // assign map Element state to eox map
133
286
  mapEl.value = eoxMap.value;
134
287
 
@@ -158,6 +311,7 @@ onMounted(() => {
158
311
  eoxMapLayers,
159
312
  compareMap,
160
313
  props.zoomToExtent,
314
+ selectedItem,
161
315
  );
162
316
  });
163
317
 
@@ -210,3 +364,74 @@ const tooltipPropertyTransform = (map) => {
210
364
  };
211
365
  };
212
366
  </script>
367
+
368
+ <style scoped>
369
+ #cursor-coordinates {
370
+ position: fixed;
371
+ left: 24px;
372
+ bottom: 54px; /* Tighter spacing: watermark at 6px + ~48px */
373
+ color: rgba(0, 0, 0, 0.9);
374
+ font-size: 11px;
375
+ font-family: var(--eox-body-font-family);
376
+ background: #fffe;
377
+ border-radius: 4px;
378
+ border: none;
379
+ padding: 0px 3px;
380
+ max-height: 24px;
381
+ }
382
+
383
+ @media (max-width: 959px) {
384
+ #cursor-coordinates {
385
+ display: none; /* Hidden in mobile mode */
386
+ }
387
+ }
388
+
389
+ #scale-line {
390
+ position: fixed;
391
+ left: 24px;
392
+ bottom: 28px; /* Tighter spacing: watermark at 6px + ~22px */
393
+ color: #fff;
394
+ }
395
+
396
+ @media (max-width: 959px) {
397
+ #scale-line {
398
+ bottom: 102px; /* Adjusted for mobile bottom nav - closer to coordinates */
399
+ }
400
+ }
401
+
402
+ :deep(.ol-scale-line) {
403
+ background: #fffe !important;
404
+ border-radius: 4px !important;
405
+ border: none !important;
406
+ padding: 0px 3px 3px 3px !important;
407
+ font-size: 10px !important;
408
+ font-family: var(--eox-body-font-family);
409
+ max-height: 20px;
410
+ }
411
+ :deep(.ol-scale-line-inner) {
412
+ display: flex;
413
+ justify-content: center;
414
+ border: 1px solid rgba(0, 0, 0, 0.5) !important;
415
+ border-top: none !important;
416
+ color: #333 !important;
417
+ font-weight: 500 !important;
418
+ transform: translateY(1px);
419
+ }
420
+
421
+ .map-buttons-container {
422
+ position: fixed;
423
+ top: 0;
424
+ left: 0;
425
+ width: 100%;
426
+ height: 100%;
427
+ display: grid;
428
+ grid-template-columns: repeat(12, 1fr);
429
+ grid-template-rows: repeat(12, 1fr);
430
+ pointer-events: none;
431
+ z-index: 1;
432
+ }
433
+
434
+ .map-buttons-container > * {
435
+ pointer-events: auto;
436
+ }
437
+ </style>
@@ -9,19 +9,19 @@ import log from "loglevel";
9
9
  * | null
10
10
  * } selectedIndicator
11
11
  * @param {EodashCollection[]} eodashCols
12
- * @param {string} [updatedTime]
12
+ * @param {string | import("stac-ts").StacItem | null} [timeOrItem] - time as a string, or a stac item
13
13
  */
14
14
 
15
15
  export const createLayersConfig = async (
16
16
  selectedIndicator,
17
17
  eodashCols,
18
- updatedTime,
18
+ timeOrItem,
19
19
  ) => {
20
20
  log.debug(
21
21
  "Creating layers config",
22
22
  selectedIndicator,
23
23
  eodashCols,
24
- updatedTime,
24
+ timeOrItem,
25
25
  );
26
26
  const layersCollection = [];
27
27
  const dataLayers = {
@@ -35,11 +35,14 @@ export const createLayersConfig = async (
35
35
  };
36
36
 
37
37
  for (const ec of eodashCols) {
38
+ /** @type {Record<string,any>[]} */
38
39
  let layers;
39
- if (updatedTime) {
40
- layers = await ec.createLayersJson(new Date(updatedTime));
40
+ if (timeOrItem) {
41
+ const dateOrItem =
42
+ typeof timeOrItem === "string" ? new Date(timeOrItem) : timeOrItem;
43
+ layers = await ec.createLayersJson(dateOrItem);
41
44
  } else {
42
- layers = await ec.createLayersJson();
45
+ layers = await ec.createLayersJson(undefined);
43
46
  }
44
47
  // Add expand to all analysis layers
45
48
  layers.forEach((dl) => {
@@ -7,6 +7,7 @@ import { storeToRefs } from "pinia";
7
7
  import { isFirstLoad } from "@/utils/states";
8
8
  import { useEmitLayersUpdate, useOnLayersUpdate } from "@/composables";
9
9
  import { mapPosition } from "@/store/states";
10
+ import { sanitizeBbox } from "@/eodashSTAC/helpers";
10
11
  /**
11
12
  * Holder for previous compare map view as it is overwritten by sync
12
13
  * @type { import("ol").View | null} mapElement
@@ -58,6 +59,7 @@ export const useHandleMapMoveEnd = (mapElement, mapPosition) => {
58
59
  * @param {import("vue").Ref<Record<string,any>[]>} mapLayers
59
60
  * @param {import("vue").Ref<import("@eox/map").EOxMap| null>} partnerMap
60
61
  * @param {boolean} zoomToExtent
62
+ * @param {import("vue").Ref<import("stac-ts").StacItem | import("stac-ts").StacLink | null>} [selectedItem]
61
63
  */
62
64
  export const useInitMap = (
63
65
  mapElement,
@@ -67,6 +69,7 @@ export const useInitMap = (
67
69
  mapLayers,
68
70
  partnerMap,
69
71
  zoomToExtent,
72
+ selectedItem,
70
73
  ) => {
71
74
  log.debug(
72
75
  "InitMap",
@@ -75,10 +78,22 @@ export const useInitMap = (
75
78
  eodashCols.values,
76
79
  datetime.value,
77
80
  );
78
-
81
+ // watch selectedItem if provided
82
+ const watching = selectedItem
83
+ ? [selectedIndicator, datetime, selectedItem]
84
+ : [selectedIndicator, datetime];
79
85
  const stopIndicatorWatcher = watch(
80
- [selectedIndicator, datetime],
81
- async ([updatedStac, updatedTime], [previousStac, previousTime]) => {
86
+ watching,
87
+ async (updated, previous) => {
88
+ const [updatedStac, updatedTime, updatedItem] =
89
+ /** @type {[import("stac-ts").StacCollection, string, import("stac-ts").StacItem | null]} */ (
90
+ selectedItem ? updated : [updated[0], updated[1], null]
91
+ );
92
+ const [previousStac, previousTime, previousItem] =
93
+ /** @type {[import("stac-ts").StacCollection, string, import("stac-ts").StacItem]} */ (
94
+ selectedItem ? previous : [previous[0], previous[1], null]
95
+ );
96
+
82
97
  if (updatedStac) {
83
98
  log.debug(
84
99
  "Selected Indicator watch triggered",
@@ -98,7 +113,9 @@ export const useInitMap = (
98
113
  let layersCollection = [];
99
114
 
100
115
  const onlyTimeChanged =
101
- updatedStac?.id === previousStac?.id && updatedTime !== previousTime;
116
+ updatedStac?.id === previousStac?.id &&
117
+ (updatedTime !== previousTime ||
118
+ (updatedItem && updatedItem?.id !== previousItem?.id));
102
119
 
103
120
  const { selectedCompareStac } = storeToRefs(useSTAcStore());
104
121
  if (mapElement?.value?.id === "main") {
@@ -115,12 +132,12 @@ export const useInitMap = (
115
132
  }
116
133
  }
117
134
 
118
- // We re-crate the configuration if time changed
135
+ // We re-create the configuration if time changed
119
136
  if (onlyTimeChanged) {
120
137
  layersCollection = await createLayersConfig(
121
138
  updatedStac,
122
139
  eodashCols,
123
- updatedTime,
140
+ updatedItem ?? updatedTime,
124
141
  );
125
142
  log.debug(
126
143
  "Assigned layers after changing time only",
@@ -142,7 +159,7 @@ export const useInitMap = (
142
159
  layersCollection = await createLayersConfig(
143
160
  updatedStac,
144
161
  eodashCols,
145
- datetime.value,
162
+ selectedItem ? updatedItem : updatedTime,
146
163
  );
147
164
 
148
165
  // We try to set the current time selection to latest extent date
@@ -157,6 +174,7 @@ export const useInitMap = (
157
174
  );
158
175
  }
159
176
  if (
177
+ !updatedItem &&
160
178
  endInterval !== null &&
161
179
  endInterval.toISOString() !== datetime.value &&
162
180
  !isFirstLoad.value
@@ -168,6 +186,7 @@ export const useInitMap = (
168
186
  // Try to move map view to extent only when main
169
187
  // indicator and map changes
170
188
  if (
189
+ !updatedItem &&
171
190
  mapElement?.value?.id === "main" &&
172
191
  updatedStac.extent?.spatial.bbox &&
173
192
  !(
@@ -178,12 +197,7 @@ export const useInitMap = (
178
197
  ) {
179
198
  // Sanitize extent,
180
199
  const b = updatedStac.extent?.spatial.bbox[0];
181
- const sanitizedExtent = [
182
- b?.[0] > -180 ? b?.[0] : -180,
183
- b?.[1] > -90 ? b?.[1] : -90,
184
- b?.[2] < 180 ? b?.[2] : 180,
185
- b?.[3] < 90 ? b?.[3] : 90,
186
- ];
200
+ const sanitizedExtent = sanitizeBbox([...b]);
187
201
 
188
202
  const reprojExtent = mapElement.value?.transformExtent(
189
203
  sanitizedExtent,
@@ -17,7 +17,14 @@
17
17
  <tbody>
18
18
  <tr v-for="item in currentJobs" :key="item.jobID">
19
19
  <td>
20
- {{ new Date(item.job_start_datetime).toISOString().slice(0, 16) }}
20
+ <a
21
+ class="processUrl"
22
+ target="_blank"
23
+ :href="getJobStatusUrl(item.jobID, currentIndicator)"
24
+ >{{
25
+ new Date(item.job_start_datetime).toISOString().slice(0, 16)
26
+ }}</a
27
+ >
21
28
  </td>
22
29
  <td>{{ item.status }}</td>
23
30
  <td style="padding: 0px">
@@ -73,6 +80,7 @@ import {
73
80
  downloadPreviousResults,
74
81
  loadProcess,
75
82
  updateJobsStatus,
83
+ getJobStatusUrl,
76
84
  } from "./methods/async";
77
85
  import { useOnLayersUpdate } from "@/composables";
78
86
  import { compareJobs, jobs } from "./states";
@@ -103,4 +111,8 @@ div.v-table__wrapper {
103
111
  overflow: hidden !important;
104
112
  height: max-content !important;
105
113
  }
114
+ .processUrl {
115
+ text-decoration: none;
116
+ color: var(--v-theme-primary);
117
+ }
106
118
  </style>
@@ -9,6 +9,7 @@
9
9
  .schema="jsonformSchema"
10
10
  ></eox-jsonform>
11
11
  <eox-chart
12
+ ref="chartElRef"
12
13
  class="chart"
13
14
  v-if="isProcessed && chartSpec"
14
15
  .spec="toRaw(chartSpec)"
@@ -45,7 +46,7 @@ import "@eox/drawtools";
45
46
  import "@eox/jsonform";
46
47
  import { useSTAcStore } from "@/store/stac";
47
48
  import { storeToRefs } from "pinia";
48
- import { computed, ref, toRaw, useTemplateRef } from "vue";
49
+ import { computed, ref, toRaw, useTemplateRef, watch } from "vue";
49
50
  import ProcessList from "./ProcessList.vue";
50
51
  import { handleProcesses, onChartClick } from "./methods/handling";
51
52
  import { useInitProcess, useAutoExec } from "./methods/composables";
@@ -55,6 +56,8 @@ import {
55
56
  indicator,
56
57
  mapCompareEl,
57
58
  mapEl,
59
+ chartEl,
60
+ compareChartEl,
58
61
  } from "@/store/states";
59
62
  import { download } from "./methods/utils";
60
63
  import { compareJobs, jobs } from "./states";
@@ -86,6 +89,10 @@ const jsonformEl =
86
89
  /** @type {Readonly<import("vue").ShallowRef<import("@eox/jsonform").EOxJSONForm | null>>} */ (
87
90
  useTemplateRef("jsonformEl")
88
91
  );
92
+ const chartElRef =
93
+ /** @type {Readonly<import("vue").ShallowRef<import("@eox/chart").EOxChart | null>>} */ (
94
+ useTemplateRef("chartElRef")
95
+ );
89
96
  const isAsync = computed(
90
97
  () =>
91
98
  selectedStac.value?.links.filter((l) => l.endpoint === "eoxhub_workspaces")
@@ -208,6 +215,15 @@ const chartStyles = computed(() => {
208
215
  }
209
216
  return styles;
210
217
  });
218
+
219
+ // Assign chart element to global state based on compare mode
220
+ watch(chartElRef, (newVal) => {
221
+ if (enableCompare) {
222
+ compareChartEl.value = newVal;
223
+ } else {
224
+ chartEl.value = newVal;
225
+ }
226
+ });
211
227
  </script>
212
228
  <style>
213
229
  eox-chart {
@@ -150,7 +150,15 @@ export const downloadPreviousResults = async (jobObject, selectedStac) => {
150
150
  .get(link.href)
151
151
  .then((response) => response.data)
152
152
  .then((data) => {
153
- results.push(...data.urls);
153
+ // either urls is an Array
154
+ if (data.urls) {
155
+ results.push(...data.urls);
156
+ } else {
157
+ // or urls need to be aggregated from mapping objects
158
+ for (const outputMappingObject of Object.values(data)) {
159
+ results.push(...outputMappingObject.urls);
160
+ }
161
+ }
154
162
  });
155
163
  results.forEach((result) => {
156
164
  if (!result) {
@@ -225,3 +233,16 @@ export async function loadPreviousProcess({
225
233
  log.debug("rendered layers after loading previous process:", layers);
226
234
  applyProcessLayersToMap(mapElement, layers);
227
235
  }
236
+
237
+ /**
238
+ * extracts job status url from local storage based on identifier
239
+ *
240
+ * @param {string} jobID
241
+ * @param {string} indicator
242
+ */
243
+ export const getJobStatusUrl = (jobID, indicator) => {
244
+ /** @type {string[]} */
245
+ const jobsUrls = JSON.parse(localStorage.getItem(indicator) || "[]");
246
+ const jobUrl = jobsUrls.find((url) => url.includes(jobID));
247
+ return jobUrl;
248
+ };
@@ -2,7 +2,11 @@ import axios from "@/plugins/axios";
2
2
  import { getBboxProperty } from "../../utils";
3
3
  import { toAbsolute } from "stac-js/src/http.js";
4
4
  import { currentCompareUrl, currentUrl } from "@/store/states";
5
- import { getDatetimeProperty } from "@/eodashSTAC/helpers";
5
+ import {
6
+ getDatetimeProperty,
7
+ generateLinksFromItems,
8
+ } from "@/eodashSTAC/helpers";
9
+ import { readParquetItems } from "@/eodashSTAC/parquet";
6
10
 
7
11
  /**
8
12
  * @param {import("^/EodashProcess/types").CustomEnpointInput} inputs
@@ -75,7 +79,25 @@ async function fetchVedaCOGsConfig(selectedStac, absoluteUrl) {
75
79
  collectionLinks.map((link) =>
76
80
  axios
77
81
  .get(toAbsolute(link.href, absoluteUrl))
78
- .then((resp) => resp.data),
82
+ .then((resp) => resp.data)
83
+ .then(async (collection) => {
84
+ // items in geoparquet handling specially to get item links
85
+ const parquetAsset = Object.values(collection.assets ?? {}).find(
86
+ (asset) =>
87
+ asset.type === "application/vnd.apache.parquet" &&
88
+ asset.roles?.includes("collection-mirror"),
89
+ );
90
+ if (parquetAsset) {
91
+ const parquetAbsoluteUrl = toAbsolute(
92
+ parquetAsset.href,
93
+ toAbsolute(link.href, absoluteUrl),
94
+ );
95
+ await readParquetItems(parquetAbsoluteUrl).then((items) => {
96
+ collection.links.push(...generateLinksFromItems(items));
97
+ });
98
+ }
99
+ return collection;
100
+ }),
79
101
  ),
80
102
  )),
81
103
  );
@@ -86,7 +108,7 @@ async function fetchVedaCOGsConfig(selectedStac, absoluteUrl) {
86
108
  const datetimeProperty = /** @type string **/ (
87
109
  getDatetimeProperty(collection.links)
88
110
  );
89
- let itemLinks = collection.links.filter((link) => link.rel == "item");
111
+ const itemLinks = collection.links.filter((link) => link.rel == "item");
90
112
  configs.push(
91
113
  ...itemLinks.map((link) => ({
92
114
  endpoint: /** @type {string} */ (link["cog_href"]),
@@ -181,7 +181,9 @@ export async function handleProcesses({
181
181
  for (const layer of newLayers) {
182
182
  if (layer.type === "WebGLTile" && layer.source?.type === "GeoTIFF") {
183
183
  processResults.value.push(...(layer.source.sources ?? []));
184
+ //@ts-expect-error TODO
184
185
  } else if (layer.source && "url" in layer.source) {
186
+ //@ts-expect-error TODO
185
187
  processResults.value.push(layer.source.url);
186
188
  }
187
189
  }
@@ -336,6 +336,7 @@ export async function processVector(links, jsonformValue, layerId) {
336
336
  type: "Vector",
337
337
  source: {
338
338
  type: "Vector",
339
+ //@ts-expect-error TODO
339
340
  url: mustache.render(link.href, {
340
341
  ...(jsonformValue ?? {}),
341
342
  }),