@eodash/eodash 5.2.0 → 5.3.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 (119) hide show
  1. package/core/client/components/DashboardLayout.vue +0 -1
  2. package/core/client/composables/index.js +53 -59
  3. package/core/client/eodashSTAC/EodashCollection.js +196 -94
  4. package/core/client/eodashSTAC/auth.js +86 -0
  5. package/core/client/eodashSTAC/createLayers.js +204 -4
  6. package/core/client/eodashSTAC/helpers.js +254 -62
  7. package/core/client/eodashSTAC/parquet.js +0 -13
  8. package/core/client/eodashSTAC/triggers.js +1 -1
  9. package/core/client/store/actions.js +14 -0
  10. package/core/client/store/stac.js +46 -8
  11. package/core/client/store/states.js +6 -0
  12. package/core/client/types.ts +206 -3
  13. package/core/client/utils/bands-editor/arithmetic.js +144 -0
  14. package/core/client/utils/bands-editor/colors.js +36 -0
  15. package/core/client/utils/bands-editor/dom.js +196 -0
  16. package/core/client/utils/bands-editor/exampleSchema.json +1320 -0
  17. package/core/client/utils/bands-editor/index.js +68 -0
  18. package/core/client/utils/bands-editor/rgb.js +102 -0
  19. package/core/client/utils/index.js +5 -2
  20. package/core/client/views/Dashboard.vue +1 -1
  21. package/core/client/vite-env.d.ts +122 -0
  22. package/dist/client/{DashboardLayout-Dq9Kfe6O.js → DashboardLayout-BAstYnhU.js} +4 -5
  23. package/dist/client/{DynamicWebComponent-DCBMXskE.js → DynamicWebComponent-7v4_DFqP.js} +1 -1
  24. package/dist/client/{EodashDatePicker-DtngxU6s.js → EodashDatePicker-IVHLv9UN.js} +20 -22
  25. package/dist/client/{EodashItemFilter-ClQebJQt.js → EodashItemFilter-BPMpnXjo.js} +46 -31
  26. package/dist/client/EodashLayerControl-CSnQh2tb.js +1517 -0
  27. package/dist/client/{EodashLayoutSwitcher-DQ8SfVDd.js → EodashLayoutSwitcher-CPpGM8Pb.js} +4 -4
  28. package/dist/client/EodashMapBtns-C_jyUJ2x.js +301 -0
  29. package/dist/client/{EodashStacInfo-Dt1nF06x.js → EodashStacInfo-DjuWc0Iz.js} +1 -1
  30. package/dist/client/EodashTimeSlider-CDh9Lf02.js +53 -0
  31. package/dist/client/{EodashTools-DV5ykmWc.js → EodashTools-DSvDUUlL.js} +10 -7
  32. package/dist/client/{ExportState-B6zZQUmE.js → ExportState-BhjxS0jG.js} +145 -120
  33. package/dist/client/{Footer-DNhXs8k6.js → Footer-C3PPcdjv.js} +1 -1
  34. package/dist/client/{Header-BjhN5JY4.js → Header-E5NbT7HE.js} +2 -2
  35. package/dist/client/MobileLayout-DY7OHr1k.js +118 -0
  36. package/dist/client/{PopUp-CgpvNr3o.js → PopUp-CSPXdqKI.js} +79 -43
  37. package/dist/client/{ProcessList-vecpxThi.js → ProcessList-C3HV7G0b.js} +5 -6
  38. package/dist/client/{VImg-CETuikH2.js → VImg-FoXcOnWF.js} +6 -3
  39. package/dist/client/{VMain-Ci9DyaGU.js → VMain-Ck2g1QOG.js} +1 -1
  40. package/dist/client/{VTooltip-J4ac48X7.js → VTooltip-F_1Zcvhp.js} +2 -2
  41. package/dist/client/{WidgetsContainer-CCML4TyV.js → WidgetsContainer-Cq9uZEuN.js} +1 -1
  42. package/dist/client/asWebComponent-DZeEbWG0.js +8895 -0
  43. package/dist/client/{async-B7jIrM53.js → async-Dk79llLt.js} +2 -2
  44. package/dist/client/easing-CH0-9wR8.js +35 -0
  45. package/dist/client/eo-dash.js +1 -1
  46. package/dist/client/{forwardRefs-BQclvjMq.js → forwardRefs-BbvoXHtj.js} +58 -45
  47. package/dist/client/{handling-BS24aG1q.js → handling-DxucYlYh.js} +12 -6
  48. package/dist/client/{helpers-wXK7Ywio.js → helpers-CI_7CUmn.js} +568 -281
  49. package/dist/client/index-BO5uGfUe.js +571 -0
  50. package/dist/client/{index-9KR-G20t.js → index-C13BiO9C.js} +2 -2
  51. package/dist/client/{index-4UCzZi8B.js → index-DcCcdbgR.js} +26 -13
  52. package/dist/client/{index-B2XpdgR6.js → index-KrGHjH-_.js} +63 -36
  53. package/dist/client/templates.js +82 -15
  54. package/dist/client/{transition-yBii4fu6.js → transition-Ctkv90El.js} +1 -1
  55. package/dist/node/cli.js +6 -6
  56. package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +24 -10
  57. package/dist/types/core/client/eodashSTAC/auth.d.ts +7 -0
  58. package/dist/types/core/client/eodashSTAC/createLayers.d.ts +15 -3
  59. package/dist/types/core/client/eodashSTAC/helpers.d.ts +47 -16
  60. package/dist/types/core/client/plugins/vuetify.d.ts +14 -14
  61. package/dist/types/core/client/store/actions.d.ts +2 -0
  62. package/dist/types/core/client/store/stac.d.ts +16 -7
  63. package/dist/types/core/client/store/states.d.ts +4 -0
  64. package/dist/types/core/client/types.d.ts +170 -2
  65. package/dist/types/core/client/utils/bands-editor/arithmetic.d.ts +8 -0
  66. package/dist/types/core/client/utils/bands-editor/colors.d.ts +15 -0
  67. package/dist/types/core/client/utils/bands-editor/dom.d.ts +42 -0
  68. package/dist/types/core/client/utils/bands-editor/index.d.ts +20 -0
  69. package/dist/types/core/client/utils/bands-editor/rgb.d.ts +15 -0
  70. package/dist/types/core/client/utils/index.d.ts +1 -1
  71. package/dist/types/templates/baseConfig.d.ts +87 -1
  72. package/dist/types/templates/expert.d.ts +6 -6
  73. package/dist/types/templates/explore.d.ts +67 -0
  74. package/dist/types/templates/index.d.ts +1 -1
  75. package/dist/types/templates/{light.d.ts → lite.d.ts} +5 -5
  76. package/dist/types/widgets/EodashItemCatalog/index.vue.d.ts +21 -0
  77. package/dist/types/widgets/EodashItemCatalog/methods/filters.d.ts +49 -0
  78. package/dist/types/widgets/EodashItemCatalog/methods/handlers.d.ts +4 -0
  79. package/dist/types/widgets/EodashItemCatalog/methods/map.d.ts +12 -0
  80. package/dist/types/widgets/EodashItemCatalog/types.d.ts +14 -0
  81. package/dist/types/widgets/EodashMap/EodashMapBtns.vue.d.ts +2 -0
  82. package/dist/types/widgets/EodashMap/index.vue.d.ts +108 -2
  83. package/dist/types/widgets/EodashMap/methods/create-layers-config.d.ts +1 -1
  84. package/dist/types/widgets/EodashMap/methods/index.d.ts +1 -1
  85. package/dist/types/widgets/EodashProcess/methods/custom-endpoints/layers/eoxhub-workspaces-endpoint.d.ts +1 -1
  86. package/dist/types/widgets/EodashTimeSlider.vue.d.ts +7 -0
  87. package/dist/types/widgets/EodashTools.vue.d.ts +10 -10
  88. package/dist/types/widgets/ExportState.vue.d.ts +2 -0
  89. package/package.json +28 -27
  90. package/templates/baseConfig.js +10 -5
  91. package/templates/compare.js +2 -2
  92. package/templates/expert.js +5 -5
  93. package/templates/explore.js +62 -0
  94. package/templates/index.js +1 -1
  95. package/templates/{light.js → lite.js} +1 -1
  96. package/widgets/EodashDatePicker.vue +15 -18
  97. package/widgets/EodashItemCatalog/index.vue +161 -0
  98. package/widgets/EodashItemCatalog/methods/filters.js +216 -0
  99. package/widgets/EodashItemCatalog/methods/handlers.js +50 -0
  100. package/widgets/EodashItemCatalog/methods/map.js +144 -0
  101. package/widgets/EodashItemCatalog/types.ts +15 -0
  102. package/widgets/EodashItemFilter.vue +35 -28
  103. package/widgets/EodashLayerControl.vue +10 -6
  104. package/widgets/EodashLayoutSwitcher.vue +1 -1
  105. package/widgets/EodashMap/EodashMapBtns.vue +18 -9
  106. package/widgets/EodashMap/index.vue +22 -12
  107. package/widgets/EodashMap/methods/create-layers-config.js +9 -6
  108. package/widgets/EodashMap/methods/index.js +27 -13
  109. package/widgets/EodashProcess/index.vue +17 -1
  110. package/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.js +9 -3
  111. package/widgets/EodashProcess/methods/handling.js +2 -0
  112. package/widgets/EodashProcess/methods/outputs.js +1 -0
  113. package/widgets/EodashTimeSlider.vue +40 -0
  114. package/widgets/EodashTools.vue +7 -3
  115. package/widgets/ExportState.vue +53 -22
  116. package/dist/client/EodashLayerControl-BLBds28C.js +0 -154
  117. package/dist/client/EodashMapBtns-B89_YBDw.js +0 -326
  118. package/dist/client/MobileLayout-JelB6w1G.js +0 -118
  119. package/dist/client/asWebComponent-ZyEzWOOf.js +0 -19092
@@ -0,0 +1,144 @@
1
+ import { useOnLayersUpdate } from "@/composables";
2
+ import { mapEl } from "@/store/states";
3
+ import { onMounted, onUnmounted } from "vue";
4
+
5
+ /**
6
+ *
7
+ * @param {import("@/types").GeoJsonFeature[]} features
8
+ */
9
+ export function renderItemsFeatures(features) {
10
+ let analysisLayers =
11
+ /** @type {import("@eox/map/src/layers").EOxLayerTypeGroup} */ (
12
+ mapEl.value?.layers?.find((l) => l.properties?.id === "AnalysisGroup")
13
+ );
14
+ if (!mapEl.value || !features) {
15
+ return;
16
+ }
17
+ if (!analysisLayers) {
18
+ analysisLayers = {
19
+ type: "Group",
20
+ properties: {
21
+ id: "AnalysisGroup",
22
+ title: "Data Layers",
23
+ },
24
+ layers: [],
25
+ };
26
+ mapEl.value.layers = [analysisLayers, ...mapEl.value.layers.reverse()];
27
+ }
28
+
29
+ const stacItemsLayer = {
30
+ type: "Vector",
31
+ properties: {
32
+ id: "stac-items",
33
+ title: "STAC Items",
34
+ },
35
+ source: {
36
+ type: "Vector",
37
+ url:
38
+ "data:application/geo+json," +
39
+ encodeURIComponent(
40
+ JSON.stringify({ type: "FeatureCollection", features }),
41
+ ),
42
+ format: "GeoJSON",
43
+ },
44
+ style: {
45
+ "fill-color": "transparent",
46
+ "stroke-color": "#003170",
47
+ },
48
+ interactions: [
49
+ {
50
+ type: "select",
51
+ options: {
52
+ id: "stac-items",
53
+ condition: "pointermove",
54
+ style: {
55
+ "stroke-color": "white",
56
+ "stroke-width": 3,
57
+ },
58
+ },
59
+ },
60
+ ],
61
+ };
62
+ const exists = analysisLayers.layers.some(
63
+ (l) => l.properties?.id === "stac-items",
64
+ );
65
+ if (exists) {
66
+ //@ts-expect-error todo
67
+ mapEl.value.addOrUpdateLayer(stacItemsLayer);
68
+ return;
69
+ } else {
70
+ //@ts-expect-error todo
71
+ analysisLayers.layers.unshift(stacItemsLayer);
72
+ mapEl.value.layers = [...mapEl.value.layers].reverse();
73
+ }
74
+ }
75
+
76
+ /**
77
+ * @param {import("vue").Ref<any>} itemFilter
78
+ * @param {boolean} bboxFilter
79
+ */
80
+ export const useSearchOnMapMove = (itemFilter, bboxFilter) => {
81
+ if (!bboxFilter) {
82
+ return;
83
+ }
84
+ /** @type {NodeJS.Timeout} */
85
+ let timeout;
86
+ const handler = () => {
87
+ clearTimeout(timeout);
88
+ timeout = setTimeout(() => {
89
+ itemFilter.value?.search();
90
+ }, 800); // 800ms debounce
91
+ };
92
+ onMounted(() => {
93
+ mapEl.value?.map.on("moveend", handler);
94
+ });
95
+ onUnmounted(() => {
96
+ mapEl.value?.map.un("moveend", handler);
97
+ });
98
+ };
99
+ /**
100
+ *
101
+ * @param {import("vue").Ref<import("@/types").GeoJsonFeature[]>} currentItems
102
+ */
103
+ export const useRenderItemsFeatures = (currentItems) => {
104
+ const renderOnUpdate = () =>
105
+ useOnLayersUpdate(() => {
106
+ // consider cases where this is not needed
107
+ renderItemsFeatures(currentItems.value);
108
+ });
109
+ onMounted(() => {
110
+ renderItemsFeatures(currentItems.value);
111
+ renderOnUpdate();
112
+ });
113
+ };
114
+ /**
115
+ *
116
+ * @param {import("vue").Ref<any>} itemfilterEl
117
+ */
118
+ export function useRenderOnFeatureHover(itemfilterEl) {
119
+ /**
120
+ *
121
+ * @param {CustomEvent} evt
122
+ */
123
+ const handler = (evt) => {
124
+ const itemId = evt.detail?.feature?.getId();
125
+ if (!itemId) {
126
+ return;
127
+ }
128
+ const item = itemfilterEl.value.items?.find(
129
+ //@ts-expect-error todo
130
+ (r) => r.id === itemId,
131
+ );
132
+ if (item) {
133
+ itemfilterEl.value.selectedResult = item;
134
+ }
135
+ };
136
+ onMounted(() => {
137
+ //@ts-expect-error todo
138
+ mapEl.value?.addEventListener("select", handler);
139
+ });
140
+ onUnmounted(() => {
141
+ //@ts-expect-error todo
142
+ mapEl.value?.removeEventListener("select", handler);
143
+ });
144
+ }
@@ -0,0 +1,15 @@
1
+ export interface FilterConfigItem {
2
+ property: string;
3
+ type: "range" | "multiselect" | "select";
4
+ title?: string;
5
+ min?: number;
6
+ max?: number;
7
+ filterKeys?: string[];
8
+ state?: Record<string, boolean>;
9
+ placeholder?: string;
10
+ /** svg icon */
11
+ icon?: string;
12
+ unitLabel?: string;
13
+ }
14
+
15
+ export type FiltersConfig = FilterConfigItem[];
@@ -5,22 +5,26 @@
5
5
  ref="eoxItemFilter"
6
6
  style="overflow: auto; --background-color: none"
7
7
  @select="onSelect"
8
- .items="store.stac?.filter((item) => item.rel === 'child')"
8
+ .items="items"
9
9
  >
10
10
  <h4 slot="filterstitle" style="margin: 14px 8px">{{ filtersTitle }}</h4>
11
-
12
11
  <h4 slot="resultstitle" style="margin: 14px 8px">{{ resultsTitle }}</h4>
13
12
  </eox-itemfilter>
14
13
  </template>
15
14
  <script setup>
16
15
  import { useSTAcStore } from "@/store/stac";
17
16
  import { isFirstLoad } from "@/utils/states";
18
- import "@eox/itemfilter";
19
17
  import { computed, ref } from "vue";
20
18
 
19
+ if (!customElements.get("eox-itemfilter")) {
20
+ await import("@eox/itemfilter");
21
+ }
22
+
21
23
  const store = useSTAcStore();
22
24
  const emit = defineEmits(["select"]);
23
-
25
+ const items = store.isApi
26
+ ? store.stac
27
+ : store.stac?.filter((item) => item.rel === "child");
24
28
  const props = defineProps({
25
29
  enableCompare: {
26
30
  type: Boolean,
@@ -87,31 +91,36 @@ const props = defineProps({
87
91
  },
88
92
  });
89
93
  /**
90
- * @param {import("stac-ts").StacLink} item
94
+ *
95
+ * @param {Function} loader Function to load the item
96
+ * @param {Function} reset Function to reset the selection
91
97
  */
92
- const selectIndicator = async (item) => {
93
- if (item) {
94
- if (isFirstLoad.value) {
95
- // prevent the map from jumping to the initial position
96
- isFirstLoad.value = false;
98
+ const createSelect = (loader, reset) => {
99
+ /**
100
+ * @param {import("stac-ts").StacLink | import("stac-ts").StacCollection} item
101
+ */
102
+ return async (item) => {
103
+ if (item) {
104
+ if (isFirstLoad.value) {
105
+ // prevent the map from jumping to the initial position
106
+ isFirstLoad.value = false;
107
+ }
108
+ const href = /** @type {string} */ (store.isApi ? item.id : item.href);
109
+ await loader(href);
110
+ emit("select", item);
111
+ } else {
112
+ reset();
97
113
  }
98
- await store.loadSelectedSTAC(item.href);
99
- emit("select", item);
100
- } else {
101
- store.selectedStac = null;
102
- }
103
- };
104
- /**
105
- * @param {import("stac-ts").StacLink} item
106
- */
107
- const selectCompareIndicator = (item) => {
108
- if (item) {
109
- store.loadSelectedCompareSTAC(item.href);
110
- emit("select", item);
111
- } else {
112
- store.resetSelectedCompareSTAC();
113
- }
114
+ };
114
115
  };
116
+ const selectIndicator = createSelect(
117
+ store.loadSelectedSTAC,
118
+ () => (store.selectedStac = null),
119
+ );
120
+ const selectCompareIndicator = createSelect(
121
+ store.loadSelectedCompareSTAC,
122
+ store.resetSelectedCompareSTAC,
123
+ );
115
124
  /** @param {any} evt*/
116
125
  const onSelect = async (evt) => {
117
126
  const item = /** @type {import('stac-ts').StacLink} */ evt.detail;
@@ -121,7 +130,6 @@ const onSelect = async (evt) => {
121
130
  selectIndicator(item);
122
131
  }
123
132
  };
124
-
125
133
  const config = computed(() => ({
126
134
  titleProperty: props.titleProperty,
127
135
  enableHighlighting: props.enableHighlighting,
@@ -138,7 +146,6 @@ const config = computed(() => ({
138
146
  /** @type {import("vue").Ref<HTMLElement & Record<string,any> | null>} */
139
147
  const eoxItemFilter = ref(null);
140
148
  </script>
141
-
142
149
  <style scoped>
143
150
  eox-itemfilter {
144
151
  --form-flex-direction: row;
@@ -5,9 +5,9 @@
5
5
  :key="mapElement"
6
6
  v-bind="config"
7
7
  :for="mapElement"
8
+ .customEditorInterfaces="bandsEditorInterface"
8
9
  @datetime:updated="debouncedHandleDateTime"
9
10
  toolsAsList="true"
10
- style="--eox-background-color: transparent"
11
11
  ref="eoxLayercontrol"
12
12
  @layerConfig:change="onLayerConfigChange"
13
13
  >
@@ -22,12 +22,8 @@
22
22
  </span>
23
23
  </template>
24
24
  <script setup>
25
- import "@eox/layercontrol";
26
-
27
- import "@eox/jsonform";
28
- import "@eox/timecontrol";
29
25
  import "color-legend-element";
30
-
26
+ import "@eox/timecontrol";
31
27
  import { computed, ref } from "vue";
32
28
  import { mapEl, mapCompareEl } from "@/store/states";
33
29
  import { getColFromLayer } from "@/eodashSTAC/helpers";
@@ -39,6 +35,14 @@ import {
39
35
  } from "@/utils/states";
40
36
  import { storeToRefs } from "pinia";
41
37
  import { useSTAcStore } from "@/store/stac";
38
+ import { bandsEditorInterface } from "@/utils/bands-editor";
39
+
40
+ if (!customElements.get("eox-layercontrol")) {
41
+ await import("@eox/layercontrol");
42
+ }
43
+ if (!customElements.get("eox-jsonform")) {
44
+ await import("@eox/jsonform");
45
+ }
42
46
 
43
47
  const props = defineProps({
44
48
  map: {
@@ -24,7 +24,7 @@ const { mobile } = useDisplay();
24
24
  defineProps({
25
25
  target: {
26
26
  type: String,
27
- default: "main",
27
+ default: "expert",
28
28
  },
29
29
  // mdi/js icon
30
30
  icon: {
@@ -86,15 +86,8 @@
86
86
  :height="popupHeight"
87
87
  >
88
88
  <EodashItemFilter
89
+ v-bind="itemFilterConfig"
89
90
  :enableCompare="true"
90
- :enableHighlighting="false"
91
- resultType="cards"
92
- style="--select-filter-max-items: 8"
93
- filters-title="Select an indicator to compare"
94
- subTitleProperty="subtitle"
95
- imageProperty="thumbnail"
96
- aggregateResults="collection_group"
97
- results-title=""
98
91
  @select="onSelectCompareIndicator"
99
92
  />
100
93
  </PopUp>
@@ -148,7 +141,11 @@ const {
148
141
  default: true,
149
142
  },
150
143
  compareIndicators: {
151
- /** @type {import("vue").PropType<boolean | {compareTemplate?:string;fallbackTemplate?:string}> }*/
144
+ /** @type {import("vue").PropType<boolean | {
145
+ compareTemplate?:string;
146
+ fallbackTemplate?:string;
147
+ itemFilterConfig?:Partial<InstanceType<import("./EodashItemFilter.vue").default>["$props"]>
148
+ }> }*/
152
149
  type: [Boolean, Object],
153
150
  default: true,
154
151
  },
@@ -181,6 +178,18 @@ const compareIcon = computed(() =>
181
178
  ? mdiCompareRemove
182
179
  : mdiCompare,
183
180
  );
181
+ const itemFilterConfig = {
182
+ enableHighlighting: false,
183
+ resultType: "cards",
184
+ style: "--select-filter-max-items: 8",
185
+ "filters-title": "Select an indicator to compare",
186
+ subTitleProperty: "subtitle",
187
+ imageProperty: "thumbnail",
188
+ aggregateResults: "collection_group",
189
+ "results-title": "",
190
+ ...(typeof compareIndicators === "object" &&
191
+ compareIndicators.itemFilterConfig),
192
+ };
184
193
 
185
194
  const onCompareClick = () => {
186
195
  showCompareIndicators.value =
@@ -43,26 +43,22 @@
43
43
  class="map-buttons-container"
44
44
  :style="`margin: ${btnsPosition.gap}px 0 ${btnsPosition.gap}px 0`"
45
45
  >
46
+ <!-- prettier-ignore -->
46
47
  <EodashMapBtns
47
48
  :style="{
48
- gridColumn: indicator || compareIndicator ? responsiveX : '12',
49
+ gridColumn: (indicator || compareIndicator) ? responsiveX : '12',
49
50
  gridRow: responsiveY,
50
51
  }"
51
52
  :exportMap="(indicator || compareIndicator) ? btnsProps.exportMap : false"
52
- :changeProjection="
53
- (indicator || compareIndicator) ? btnsProps.changeProjection : false
53
+ :changeProjection="(indicator || compareIndicator) ? btnsProps.changeProjection : false
54
54
  "
55
- :compareIndicators="
56
- (indicator || compareIndicator) ? btnsProps.compareIndicators : false
55
+ :compareIndicators="(indicator || compareIndicator) ? btnsProps.compareIndicators : false
57
56
  "
58
- :backToPOIs="
59
- (indicator || compareIndicator) ? btnsProps.backToPOIs : false
57
+ :backToPOIs="(indicator || compareIndicator) ? btnsProps.backToPOIs : false
60
58
  "
61
- :enableSearch="
62
- (indicator || compareIndicator) ? btnsProps.enableSearch : false
59
+ :enableSearch="(indicator || compareIndicator) ? btnsProps.enableSearch : false
63
60
  "
64
- :enableZoom="
65
- (indicator || compareIndicator) ? btnsProps.enableZoom : false
61
+ :enableZoom="(indicator || compareIndicator) ? btnsProps.enableZoom : false
66
62
  "
67
63
  />
68
64
  </div>
@@ -134,6 +130,18 @@ const props = defineProps({
134
130
  }),
135
131
  },
136
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
+ * }> }*/
137
145
  type: Object,
138
146
  default: () => ({
139
147
  enableExportMap: true,
@@ -272,7 +280,8 @@ const showCompare = computed(() =>
272
280
  useHandleMapMoveEnd(eoxMap, mapPosition);
273
281
 
274
282
  onMounted(() => {
275
- const { selectedCompareStac, selectedStac } = storeToRefs(useSTAcStore());
283
+ const { selectedCompareStac, selectedStac, selectedItem } =
284
+ storeToRefs(useSTAcStore());
276
285
  // assign map Element state to eox map
277
286
  mapEl.value = eoxMap.value;
278
287
 
@@ -302,6 +311,7 @@ onMounted(() => {
302
311
  eoxMapLayers,
303
312
  compareMap,
304
313
  props.zoomToExtent,
314
+ selectedItem,
305
315
  );
306
316
  });
307
317
 
@@ -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,
@@ -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 {
@@ -2,7 +2,10 @@ 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, generateLinksFromItems } from "@/eodashSTAC/helpers";
5
+ import {
6
+ getDatetimeProperty,
7
+ generateLinksFromItems,
8
+ } from "@/eodashSTAC/helpers";
6
9
  import { readParquetItems } from "@/eodashSTAC/parquet";
7
10
 
8
11
  /**
@@ -82,10 +85,13 @@ async function fetchVedaCOGsConfig(selectedStac, absoluteUrl) {
82
85
  const parquetAsset = Object.values(collection.assets ?? {}).find(
83
86
  (asset) =>
84
87
  asset.type === "application/vnd.apache.parquet" &&
85
- asset.roles?.includes("collection-mirror"),
88
+ asset.roles?.includes("collection-mirror"),
86
89
  );
87
90
  if (parquetAsset) {
88
- const parquetAbsoluteUrl = toAbsolute(parquetAsset.href, toAbsolute(link.href, absoluteUrl));
91
+ const parquetAbsoluteUrl = toAbsolute(
92
+ parquetAsset.href,
93
+ toAbsolute(link.href, absoluteUrl),
94
+ );
89
95
  await readParquetItems(parquetAbsoluteUrl).then((items) => {
90
96
  collection.links.push(...generateLinksFromItems(items));
91
97
  });
@@ -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
  }),