@eodash/eodash 5.0.0-alpha.2.13 → 5.0.0-alpha.2.15

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 (38) hide show
  1. package/core/client/composables/index.js +36 -1
  2. package/core/client/eodash.js +27 -6
  3. package/core/client/store/States.js +4 -0
  4. package/core/client/store/stac.js +42 -2
  5. package/core/client/utils/createLayers.js +1 -1
  6. package/core/client/utils/eodashSTAC.js +2 -4
  7. package/core/client/utils/helpers.js +0 -4
  8. package/dist/client/{DashboardLayout-v8_zE0jH.js → DashboardLayout-DQE4aB6e.js} +2 -2
  9. package/dist/client/{DynamicWebComponent-DSY-5Ke4.js → DynamicWebComponent-TrDsJuF8.js} +3 -3
  10. package/dist/client/{EodashDatePicker-C6VRIC7r.js → EodashDatePicker-CkA9rHp6.js} +4 -4
  11. package/dist/client/{EodashItemFilter-BBXcouVm.js → EodashItemFilter-Bp0lcvbI.js} +3609 -3555
  12. package/dist/client/EodashLayerControl-lfLYqyeU.js +20963 -0
  13. package/dist/client/{EodashMap-DY7I6iY4.js → EodashMap--2y6XErO.js} +39009 -63663
  14. package/dist/client/{EodashMapBtns-k00mMvVA.js → EodashMapBtns-BSf3iUAb.js} +2 -2
  15. package/dist/client/{ExportState-Cf40G0wJ.js → ExportState-BTONkMIz.js} +4 -4
  16. package/dist/client/{Footer-DrCAj7E9.js → Footer-B7JDXdxT.js} +1 -1
  17. package/dist/client/{Header-BZT87lHO.js → Header-Dlumetq0.js} +4 -4
  18. package/dist/client/{IframeWrapper-DTynglc_.js → IframeWrapper-DRjSqhFx.js} +1 -1
  19. package/dist/client/{MobileLayout-BymTNZp0.js → MobileLayout-9z2X_rmU.js} +6 -6
  20. package/dist/client/{PopUp-CwXUqqZg.js → PopUp-CXbMBYGh.js} +6 -6
  21. package/dist/client/{VImg-B-YTQawu.js → VImg-Dgk5tryv.js} +2 -2
  22. package/dist/client/{VMain-D7s76eFm.js → VMain-Ubv9jyyL.js} +2 -2
  23. package/dist/client/{VOverlay-DdGIY0gS.js → VOverlay-CqZC2CbA.js} +29 -29
  24. package/dist/client/{WidgetsContainer-CFR37y2l.js → WidgetsContainer-CHK_3dlD.js} +3 -3
  25. package/dist/client/{asWebComponent-C2Gm8JDg.js → asWebComponent-Ddg71BJk.js} +4081 -4034
  26. package/dist/client/{decoder-Cth6J7EK-DdAwx7Hm.js → decoder-DJlmx386-DJlmx386.js} +4 -6
  27. package/dist/client/eo-dash.js +1 -1
  28. package/dist/client/{forwardRefs-BFBakSKN.js → forwardRefs-OX_5lLJW.js} +1 -1
  29. package/dist/client/{helpers-VeeVIAhm.js → helpers-BCawTwFg.js} +6 -7
  30. package/dist/client/{index-DAqRmdAt.js → index-B_KfD-iF.js} +5 -5
  31. package/dist/client/{lerc-BgbQqdFI-CNkQ6JUx.js → lerc-B4lXefGh-CplqAh1B.js} +33 -33
  32. package/dist/client/{ssrBoot-BBelCodY.js → ssrBoot-BZTPJZkq.js} +1 -1
  33. package/dist/client/{transition-CxxPQppy.js → transition-Dq8XIV_D.js} +1 -1
  34. package/package.json +5 -5
  35. package/widgets/EodashItemFilter.vue +83 -4
  36. package/widgets/EodashLayerControl.vue +2 -7
  37. package/widgets/EodashMap.vue +191 -123
  38. package/dist/client/EodashLayerControl-BtfpgLGi.js +0 -31500
@@ -17,6 +17,10 @@ import "@eox/itemfilter";
17
17
  import { onMounted, ref } from "vue";
18
18
 
19
19
  const props = defineProps({
20
+ enableCompare: {
21
+ type: Boolean,
22
+ default: false,
23
+ },
20
24
  filtersTitle: {
21
25
  type: String,
22
26
  default: "Indicators",
@@ -35,8 +39,8 @@ const props = defineProps({
35
39
  default: "themes",
36
40
  },
37
41
  enableHighlighting: { type: Boolean, default: true },
38
- expandMultipleFilters: { type: Boolean, default: false },
39
- expandMultipleResults: { type: Boolean, default: false },
42
+ expandMultipleFilters: { type: Boolean, default: true },
43
+ expandMultipleResults: { type: Boolean, default: true },
40
44
  filterProperties: {
41
45
  /** @type {import("vue").PropType<{
42
46
  * keys:string[];
@@ -61,9 +65,18 @@ const props = defineProps({
61
65
  });
62
66
  /** @param {any} evt*/
63
67
  const onSelect = async (evt) => {
68
+ // reset the style of all compare buttons
69
+ eoxItemFilter.value?.shadowRoot
70
+ ?.querySelectorAll(".compareMapButton")
71
+ .forEach((res) => res.setAttribute("style", defaultStyle));
64
72
  const item = /** @type {import('stac-ts').StacLink} */ evt.detail;
65
- await store.loadSelectedSTAC(item.href);
66
- console.log(item, store.selectedStac);
73
+ if (item) {
74
+ await store.loadSelectedSTAC(item.href);
75
+ } else {
76
+ // TODO: it is possible to unselect items now
77
+ // we need to consider how to reset to "default"
78
+ // if that happens here
79
+ }
67
80
  };
68
81
  const config = {
69
82
  titleProperty: props.titleProperty,
@@ -78,6 +91,69 @@ const eoxItemFilter = ref(null);
78
91
 
79
92
  const store = useSTAcStore();
80
93
 
94
+ const defaultStyle =
95
+ "float:right; height:15px; padding:4px; margin-top:-4px; background-color:white;";
96
+ const highlightStyle =
97
+ "float:right; height:15px; padding:4px; margin-top:-4px; background-color:#9bcaeb;";
98
+
99
+ const injectCompareButtons = () => {
100
+ setTimeout(() => {
101
+ /** @type {any} */
102
+ (eoxItemFilter.value)?.shadowRoot
103
+ .querySelectorAll("details>summary")
104
+ .forEach((/** @type {HTMLElement} */ el) =>
105
+ el.setAttribute("style", "width: 100%"),
106
+ );
107
+ /** @type {any} */
108
+ (eoxItemFilter.value)?.shadowRoot
109
+ .querySelectorAll("details>div li")
110
+ .forEach((/** @type {HTMLElement} */ res) => {
111
+ let compareButton = document.createElement("button");
112
+ compareButton.className = "compareMapButton";
113
+ compareButton.dataset.id = res.children[0].id;
114
+
115
+ compareButton.onclick = async (
116
+ /** {Event & { currentTarget: HTMLElement }} */ evt,
117
+ ) => {
118
+ // reset the style of all compare buttons
119
+ eoxItemFilter.value?.shadowRoot
120
+ ?.querySelectorAll(".compareMapButton")
121
+ .forEach((res) => {
122
+ res.setAttribute("style", defaultStyle);
123
+ });
124
+ const currentTarget = /** @type {HTMLElement}*/ (evt.currentTarget);
125
+ currentTarget?.setAttribute("style", highlightStyle);
126
+ const selected = eoxItemFilter.value?.items.find(
127
+ (/** @type {HTMLElement} */ it) =>
128
+ it.id === currentTarget?.dataset.id,
129
+ );
130
+ if (selected) {
131
+ await store.loadSelectedCompareSTAC(selected.href);
132
+ }
133
+ };
134
+ compareButton.setAttribute("style", defaultStyle);
135
+ const svgIcon = document.createElementNS(
136
+ "http://www.w3.org/2000/svg",
137
+ "svg",
138
+ );
139
+ const iconPath = document.createElementNS(
140
+ "http://www.w3.org/2000/svg",
141
+ "path",
142
+ );
143
+ svgIcon.setAttribute("width", "15");
144
+ svgIcon.setAttribute("height", "15");
145
+ svgIcon.setAttribute("viewBox", "0 0 24 24");
146
+ iconPath.setAttribute(
147
+ "d",
148
+ "M19,3H14V5H19V18L14,12V21H19A2,2 0 0,0 21,19V5C21,3.89 20.1,3 19,3M10,18H5L10,12M10,3H5C3.89,3 3,3.89 3,5V19A2,2 0 0,0 5,21H10V23H12V1H10V3Z",
149
+ );
150
+ svgIcon.appendChild(iconPath);
151
+ compareButton.appendChild(svgIcon);
152
+ res.append(compareButton);
153
+ });
154
+ }, 100);
155
+ };
156
+
81
157
  onMounted(() => {
82
158
  const style = document.createElement("style");
83
159
  style.innerHTML = `
@@ -96,5 +172,8 @@ onMounted(() => {
96
172
  const items = store.stac?.filter((item) => item.rel === "child");
97
173
  /** @type {any} */
98
174
  (eoxItemFilter.value).items = items;
175
+ if (props.enableCompare) {
176
+ injectCompareButtons();
177
+ }
99
178
  });
100
179
  </script>
@@ -1,18 +1,13 @@
1
1
  <template>
2
2
  <span class="d-flex flex-column fill-height overflow-auto pa-4">
3
- <eox-layercontrol ref="eoxLayercontrol" />
3
+ <eox-layercontrol v-if="mapEl" :for="mapEl" ref="eoxLayercontrol" />
4
4
  </span>
5
5
  </template>
6
6
  <script setup>
7
7
  import "@eox/layercontrol";
8
8
  import "@eox/jsonform";
9
- import { onMounted, ref } from "vue";
9
+ import { ref } from "vue";
10
10
  import { mapEl } from "@/store/States";
11
11
  /** @type { import("vue").Ref<HTMLElement & Record<string,any> | null>} */
12
12
  const eoxLayercontrol = ref(null);
13
-
14
- onMounted(() => {
15
- /** @type{ HTMLElement & Record<string,any> }*/
16
- (eoxLayercontrol.value).for = mapEl.value;
17
- });
18
13
  </script>
@@ -1,23 +1,55 @@
1
1
  <template>
2
- <eox-map
2
+ <eox-map-compare
3
3
  class="fill-height fill-width overflow-none"
4
- ref="eoxMap"
5
- :config="eoxMapConfig"
6
- />
4
+ :enabled="showCompare"
5
+ >
6
+ <eox-map
7
+ class="fill-height fill-width overflow-none"
8
+ slot="first"
9
+ sync="eox-map#compare"
10
+ ref="eoxMap"
11
+ id="main"
12
+ :config="eoxMapConfig"
13
+ />
14
+ <eox-map
15
+ class="fill-height fill-width overflow-none"
16
+ id="compare"
17
+ slot="second"
18
+ ref="compareMap"
19
+ :config="eoxCompareMapConfig"
20
+ />
21
+ </eox-map-compare>
7
22
  </template>
8
23
  <script setup>
9
- import { transformExtent } from "ol/proj";
10
24
  import { onMounted, onUnmounted, reactive, ref, watch } from "vue";
11
25
  import { EodashCollection } from "@/utils/eodashSTAC";
12
- import { extractCollectionUrls, uid } from "@/utils/helpers";
13
- import { currentUrl, datetime, mapEl, mapPosition } from "@/store/States";
26
+ import { extractCollectionUrls } from "@/utils/helpers";
27
+ import {
28
+ currentUrl,
29
+ currentCompareUrl,
30
+ datetime,
31
+ mapEl,
32
+ mapPosition,
33
+ } from "@/store/States";
34
+ import { transformExtent } from "ol/proj";
14
35
  import { storeToRefs } from "pinia";
15
36
  import { useSTAcStore } from "@/store/stac";
16
37
  import "@eox/map";
17
38
  import "@eox/map/dist/eox-map-advanced-layers-and-sources.js";
18
39
 
40
+ const props = defineProps({
41
+ enableCompare: {
42
+ type: Boolean,
43
+ default: false,
44
+ },
45
+ });
46
+
19
47
  /** @type {import("vue").Ref<(HTMLElement & Record<string,any>) | null>} */
20
48
  const eoxMap = ref(null);
49
+ /** @type {import("vue").Ref<(HTMLElement & Record<string,any>) | null>} */
50
+ const compareMap = ref(null);
51
+
52
+ const showCompare = ref("first");
21
53
 
22
54
  const eoxMapConfig = reactive({
23
55
  /** @type {(number|undefined)[] | undefined} */
@@ -26,18 +58,6 @@ const eoxMapConfig = reactive({
26
58
  zoom: 4,
27
59
  // TODO: we should probably introduce some way of defining
28
60
  layers: [
29
- {
30
- type: "Vector",
31
- source: {
32
- type: "Vector",
33
- url: "https://openlayers.org/data/vector/ecoregions.json",
34
- format: "GeoJSON",
35
- },
36
- properties: {
37
- id: "Regions",
38
- title: "Regions",
39
- },
40
- },
41
61
  {
42
62
  type: "Tile",
43
63
  properties: {
@@ -51,6 +71,14 @@ const eoxMapConfig = reactive({
51
71
  ],
52
72
  });
53
73
 
74
+ const eoxCompareMapConfig = reactive({
75
+ /** @type {(number|undefined)[] | undefined} */
76
+ center: [15, 48],
77
+ /** @type {number | undefined} */
78
+ zoom: 4,
79
+ layers: [],
80
+ });
81
+
54
82
  // Check if selected indicator was already set in store
55
83
  if (mapPosition && mapPosition.value && mapPosition.value.length === 3) {
56
84
  // TODO: do further checks for invalid values?
@@ -72,6 +100,121 @@ const handleMoveEnd = (evt) => {
72
100
  };
73
101
 
74
102
  const store = useSTAcStore();
103
+ /**
104
+ *
105
+ * @param {import("vue").Ref<string>} baseUrl
106
+ * @param {string} updatedTime
107
+ * @param {import("vue").Ref<
108
+ * | import("stac-ts").StacCatalog
109
+ * | import("stac-ts").StacCollection
110
+ * | import("stac-ts").StacItem
111
+ * | null
112
+ * >} selectedStac
113
+ */
114
+ const createLayersConfig = async (baseUrl, updatedTime, selectedStac) => {
115
+ const collectionUrls = extractCollectionUrls(
116
+ selectedStac.value,
117
+ baseUrl.value,
118
+ );
119
+ const eodashCollections = collectionUrls.map(
120
+ (cu) => new EodashCollection(cu),
121
+ );
122
+
123
+ const layersCollection = [];
124
+ const dataLayers = {
125
+ type: "Group",
126
+ properties: {
127
+ id: "AnalysisGroup",
128
+ title: "Analysis Layers",
129
+ layerControlExpand: true,
130
+ },
131
+ layers: /** @type {Record<string,any>[]}*/ ([]),
132
+ };
133
+
134
+ for (const ec of eodashCollections) {
135
+ let layers;
136
+ if (updatedTime) {
137
+ layers = await ec.createLayersJson(new Date(updatedTime));
138
+ } else {
139
+ layers = await ec.createLayersJson();
140
+ }
141
+ if (layers) {
142
+ dataLayers.layers.push(...layers);
143
+ }
144
+ }
145
+ // Add expand to all analysis layers
146
+ dataLayers.layers.forEach((dl) => {
147
+ dl.properties.layerControlExpand = true;
148
+ dl.properties.layerControlToolsExpand = true;
149
+ });
150
+
151
+ layersCollection.push(dataLayers);
152
+ const indicator = new EodashCollection(currentUrl.value);
153
+ const indicatorLayers = await indicator.buildJsonArray(
154
+ //@ts-expect-error we use this function to generate collection level visualization
155
+ selectedStac.value,
156
+ currentUrl.value,
157
+ selectedStac.value?.title ?? "",
158
+ selectedStac.value?.endpointtype ?? false,
159
+ );
160
+
161
+ const baseLayers = {
162
+ type: "Group",
163
+ properties: {
164
+ id: "BaseLayersGroup",
165
+ title: "Base Layers",
166
+ },
167
+ layers: /** @type {Record<string,any>[]}*/ ([]),
168
+ };
169
+
170
+ const indicatorBaseLayers = indicatorLayers.filter(
171
+ (l) => l.properties.group === "baselayer",
172
+ );
173
+ if (indicatorBaseLayers.length) {
174
+ baseLayers.layers.push(...indicatorBaseLayers);
175
+
176
+ // Add exclusive to baselayers and make sure only one is selected
177
+ baseLayers.layers.forEach((bl) => {
178
+ bl.properties.layerControlExclusive = true;
179
+ });
180
+ } else {
181
+ // Default to some baselayer
182
+ baseLayers.layers.push({
183
+ type: "Tile",
184
+ properties: {
185
+ id: "osm",
186
+ title: "Background",
187
+ layerControlExclusive: true,
188
+ },
189
+ source: {
190
+ type: "OSM",
191
+ },
192
+ });
193
+ }
194
+
195
+ if (baseLayers.layers.length) {
196
+ layersCollection.push(baseLayers);
197
+ }
198
+
199
+ const overlayLayers = {
200
+ type: "Group",
201
+ properties: {
202
+ id: "OverlayGroup",
203
+ title: "Overlay Layers",
204
+ },
205
+ layers: /** @type {Record<string,any>[]}*/ ([]),
206
+ };
207
+
208
+ const indicatorOverlays = indicatorLayers.filter(
209
+ (l) => l.properties.group === "overlay",
210
+ );
211
+ if (indicatorOverlays.length) {
212
+ overlayLayers.layers.push(...indicatorOverlays);
213
+ layersCollection.unshift(overlayLayers);
214
+ }
215
+
216
+ return layersCollection;
217
+ };
75
218
 
76
219
  onMounted(() => {
77
220
  mapEl.value = /** @type {HTMLElement & Record<string,any>} */ (eoxMap.value);
@@ -79,126 +222,51 @@ onMounted(() => {
79
222
  /** @type {import('ol/Map').default} */
80
223
  (eoxMap.value?.map)?.on("moveend", handleMoveEnd);
81
224
 
82
- const { selectedStac } = storeToRefs(store);
225
+ const { selectedStac, selectedCompareStac } = storeToRefs(store);
226
+ if (props.enableCompare) {
227
+ watch(
228
+ [selectedCompareStac, datetime],
229
+ async (
230
+ [updatedCompareStac, updatedTime],
231
+ [_previousCompareStac, _previousTime],
232
+ ) => {
233
+ if (updatedCompareStac) {
234
+ const compareLayersCollection = await createLayersConfig(
235
+ currentCompareUrl,
236
+ updatedTime,
237
+ selectedCompareStac,
238
+ );
239
+ /** @type {any} */
240
+ (compareMap.value).layers = compareLayersCollection;
241
+ showCompare.value = "";
242
+ }
243
+ },
244
+ );
245
+ }
83
246
 
84
247
  watch(
85
248
  [selectedStac, datetime],
86
249
  async ([updatedStac, updatedTime], [previousSTAC, _previousTime]) => {
87
250
  if (updatedStac) {
88
- const collectionUrls = extractCollectionUrls(
89
- selectedStac.value,
90
- currentUrl.value,
91
- );
92
-
93
- const eodashCollections = collectionUrls.map(
94
- (cu) => new EodashCollection(cu),
251
+ const layersCollection = await createLayersConfig(
252
+ currentUrl,
253
+ updatedTime,
254
+ selectedStac,
95
255
  );
96
-
97
- const layersCollection = [];
98
- const dataLayers = {
99
- type: "Group",
100
- properties: {
101
- id: uid(),
102
- title: "Analysis Layers",
103
- layerControlExpand: true,
104
- },
105
- layers: /** @type {Record<string,any>[]}*/ ([]),
106
- };
107
-
108
- for (const ec of eodashCollections) {
109
- let layers;
110
- if (updatedTime) {
111
- layers = await ec.createLayersJson(new Date(updatedTime));
112
- } else {
113
- layers = await ec.createLayersJson();
114
- }
115
- if (layers) {
116
- dataLayers.layers.push(...layers);
117
- }
118
- }
119
- // Add expand to all analysis layers
120
- dataLayers.layers.forEach((dl) => {
121
- dl.properties.layerControlExpand = true;
122
- dl.properties.layerControlToolsExpand = true;
123
- });
124
-
125
- layersCollection.push(dataLayers);
126
- const indicator = new EodashCollection(currentUrl.value);
127
- const indicatorLayers = await indicator.buildJsonArray(
128
- // @ts-expect-error we pass a collection instead of an item, we want to reuse the layer extraction logic
129
- selectedStac.value,
130
- currentUrl.value,
131
- selectedStac.value?.title ?? "",
132
- selectedStac.value?.endpointtype ?? false,
133
- );
134
-
135
- const baseLayers = {
136
- type: "Group",
137
- properties: {
138
- id: uid(),
139
- title: "Base Layers",
140
- },
141
- layers: /** @type {Record<string,any>[]}*/ ([]),
142
- };
143
-
144
- const indicatorBaseLayers = indicatorLayers.filter(
145
- (l) => l.properties.group === "baselayer",
146
- );
147
- if (indicatorBaseLayers.length) {
148
- baseLayers.layers.push(...indicatorBaseLayers);
149
-
150
- // Add exclusive to baselayers and make sure only one is selected
151
- baseLayers.layers.forEach((bl) => {
152
- bl.properties.layerControlExclusive = true;
153
- });
154
- } else {
155
- // Default to some baselayer
156
- baseLayers.layers.push({
157
- type: "Tile",
158
- properties: {
159
- id: "osm",
160
- title: "Background",
161
- layerControlExclusive: true,
162
- },
163
- source: {
164
- type: "OSM",
165
- },
166
- });
167
- }
168
-
169
- if (baseLayers.layers.length) {
170
- layersCollection.push(baseLayers);
171
- }
172
-
173
- const overlayLayers = {
174
- type: "Group",
175
- properties: {
176
- id: uid(),
177
- title: "Overlay Layers",
178
- },
179
- layers: /** @type {Record<string,any>[]}*/ ([]),
180
- };
181
-
182
- const indicatorOverlays = indicatorLayers.filter(
183
- (l) => l.properties.group === "overlay",
184
- );
185
- if (indicatorOverlays.length) {
186
- overlayLayers.layers.push(...indicatorOverlays);
187
- layersCollection.unshift(overlayLayers);
188
- }
189
-
190
256
  /** @type {any} */
191
257
  (eoxMap.value).layers = layersCollection;
192
258
 
193
259
  // only on different indicator selection and not on time change
194
260
  if (previousSTAC?.id !== updatedStac.id) {
261
+ showCompare.value = "first";
195
262
  // Try to move map view to extent
196
- const extent = await indicator.getExtent();
197
263
  // Make sure for now we are always converting from 4326
198
264
  // of stac items into current map projection
199
265
  // TODO: This might change if we decide to use 4326 as default for zoom and extent
200
266
  // Sanitize extent
201
- const b = extent.spatial.bbox[0];
267
+ // @ts-expect-error we will need to change the approach to use
268
+ // native eox-map transformation once included
269
+ const b = updatedStac.extent?.spatial.bbox[0];
202
270
  const sanitizedExtent = [
203
271
  b[0] > -180 ? b[0] : -180,
204
272
  b[1] > -90 ? b[1] : -90,