@eodash/eodash 5.0.0-alpha.2.16 → 5.0.0-alpha.2.18

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 (49) hide show
  1. package/core/client/App.vue +2 -0
  2. package/core/client/composables/EodashMap.js +207 -103
  3. package/core/client/composables/index.js +13 -2
  4. package/core/client/eodash.js +8 -3
  5. package/core/client/plugins/axios.js +8 -0
  6. package/core/client/plugins/index.js +2 -1
  7. package/core/client/store/Actions.js +2 -1
  8. package/core/client/store/States.js +4 -0
  9. package/core/client/store/stac.js +11 -8
  10. package/core/client/utils/createLayers.js +83 -46
  11. package/core/client/utils/eodashSTAC.js +69 -19
  12. package/core/client/utils/helpers.js +108 -35
  13. package/core/client/vite-env.d.ts +1 -0
  14. package/dist/client/{DashboardLayout-CCtyOil0.js → DashboardLayout-Dk6lzKZA.js} +2 -2
  15. package/dist/client/{DynamicWebComponent-But2r1Sj.js → DynamicWebComponent-BkMCGU7a.js} +2 -2
  16. package/dist/client/EodashDatePicker-D27wn0jP.js +276 -0
  17. package/dist/client/EodashItemFilter-DS1mOc2p.js +7651 -0
  18. package/dist/client/{EodashLayerControl-BhZL4pYM.js → EodashLayerControl-BqGA6jbV.js} +5604 -5428
  19. package/dist/client/{EodashMap-C5tOgVOv.js → EodashMap-BnVrfBnA.js} +9083 -9032
  20. package/dist/client/{EodashMapBtns-CdDfVQj0.js → EodashMapBtns-rv-U1nI_.js} +2 -2
  21. package/dist/client/{ExportState-CKCCN_VI.js → ExportState-C3Z1ET5c.js} +138 -131
  22. package/dist/client/{Footer-B9yVgyzx.js → Footer-BBkNiqPm.js} +63 -63
  23. package/dist/client/{Header-CPIlUEOq.js → Header-BQKHLO5P.js} +70 -70
  24. package/dist/client/{IframeWrapper-DRw1kHJm.js → IframeWrapper-BX4e2uxq.js} +1 -1
  25. package/dist/client/{MobileLayout-CPxVee5U.js → MobileLayout-C2aqobN5.js} +43 -41
  26. package/dist/client/{PopUp-Dca-gx9a.js → PopUp-DG3zrW12.js} +15 -15
  27. package/dist/client/{VImg-PHLA1nP1.js → VImg-BLpHACcB.js} +33 -31
  28. package/dist/client/VMain-DOyRcpub.js +38 -0
  29. package/dist/client/VOverlay-DAiInZQP.js +973 -0
  30. package/dist/client/{WidgetsContainer-jxk3kw-d.js → WidgetsContainer-BqoX7R5Z.js} +3 -3
  31. package/dist/client/{asWebComponent-3OsFQJVx.js → asWebComponent-tNU8_fkz.js} +10199 -9314
  32. package/dist/client/eo-dash.js +1 -1
  33. package/dist/client/{forwardRefs-BxZaq9ml.js → forwardRefs-BexjzXbg.js} +1 -1
  34. package/dist/client/{index-Vul961Xy.js → index-F73os72i.js} +23 -23
  35. package/dist/client/{lerc-B4lXefGh-BESXOHWk.js → lerc-B4lXefGh-DhdntrgS.js} +1 -1
  36. package/dist/client/{ssrBoot-BFMBrCqY.js → ssrBoot-C71RpKe4.js} +1 -1
  37. package/dist/client/style.css +2 -2
  38. package/dist/client/{transition-U5aFjJtV.js → transition-DNdd2Y-1.js} +1 -1
  39. package/dist/client/{webfontloader-D_JbBwHu.js → webfontloader-C7dpDL7m.js} +1 -1
  40. package/dist/node/cli.js +1 -1
  41. package/package.json +26 -24
  42. package/widgets/EodashDatePicker.vue +112 -88
  43. package/widgets/EodashLayerControl.vue +3 -1
  44. package/widgets/EodashMap.vue +62 -54
  45. package/widgets/ExportState.vue +4 -2
  46. package/dist/client/EodashDatePicker-jeYiWflv.js +0 -247
  47. package/dist/client/EodashItemFilter-BFlfWeE_.js +0 -10125
  48. package/dist/client/VMain-Ck81LJfb.js +0 -39
  49. package/dist/client/VOverlay-CL4hiJB8.js +0 -972
@@ -1,25 +1,37 @@
1
1
  import { registerProjection } from "@/store/Actions";
2
- import { extractRoles, getProjectionCode } from "./helpers";
2
+ import {
3
+ extractRoles,
4
+ getProjectionCode,
5
+ createLayerID,
6
+ createAssetID,
7
+ } from "./helpers";
8
+ import log from "loglevel";
3
9
 
4
10
  /**
5
- * @param {string} id
11
+ * @param {string} collectionId
6
12
  * @param {string} title
7
13
  * @param {Record<string,import("stac-ts").StacAsset>} assets
14
+ * @param {import("stac-ts").StacItem } item
8
15
  * @param {import("ol/layer/WebGLTile").Style} [style]
9
16
  * @param {Record<string, unknown>} [layerConfig]
10
17
  * @param {Record<string, unknown>} [layerDatetime]
11
18
  **/
12
- export async function createLayersFromDataAssets(
13
- id,
19
+ export async function createLayersFromAssets(
20
+ collectionId,
14
21
  title,
15
22
  assets,
23
+ item,
16
24
  style,
17
25
  layerConfig,
18
26
  layerDatetime,
19
27
  ) {
28
+ log.debug("Creating layers from assets");
20
29
  let jsonArray = [];
21
30
  let geoTIFFSources = [];
22
- for (const ast in assets) {
31
+ /** @type {number|null} */
32
+ let geoTIFFIdx = null;
33
+
34
+ for (const [idx, ast] of Object.keys(assets).entries()) {
23
35
  // register projection if exists
24
36
  const assetProjection =
25
37
  /** @type {string | number | {name: string, def: string, extent?:number[]} | undefined} */ (
@@ -28,6 +40,8 @@ export async function createLayersFromDataAssets(
28
40
  await registerProjection(assetProjection);
29
41
 
30
42
  if (assets[ast]?.type === "application/geo+json") {
43
+ const assetId = createAssetID(collectionId, item.id, idx);
44
+ log.debug("Creating Vector layer from GeoJSON", assetId);
31
45
  const layer = {
32
46
  type: "Vector",
33
47
  source: {
@@ -36,7 +50,7 @@ export async function createLayersFromDataAssets(
36
50
  format: "GeoJSON",
37
51
  },
38
52
  properties: {
39
- id,
53
+ id: assetId,
40
54
  title,
41
55
  layerDatetime,
42
56
  ...(layerConfig && {
@@ -48,19 +62,19 @@ export async function createLayersFromDataAssets(
48
62
  },
49
63
  ...(!style?.variables && { style }),
50
64
  };
51
- extractRoles(
52
- layer.properties,
53
- assets[ast]?.roles ?? [],
54
- /** @type {string} */ (assets[ast].id || assets[ast].title || ""),
55
- );
65
+ extractRoles(layer.properties, assets[ast]);
56
66
  jsonArray.push(layer);
57
67
  } else if (assets[ast]?.type === "image/tiff") {
68
+ geoTIFFIdx = idx;
58
69
  geoTIFFSources.push({ url: assets[ast].href });
59
70
  }
60
71
  }
61
72
 
62
- if (geoTIFFSources.length) {
63
- jsonArray.push({
73
+ if (geoTIFFSources.length && typeof geoTIFFIdx === "number") {
74
+ const geotiffSourceID = collectionId + ";:;GeoTIFF";
75
+ log.debug("Creating WebGLTile layer from GeoTIFF", geotiffSourceID);
76
+ log.debug("Configured Sources", geoTIFFSources);
77
+ const layer = {
64
78
  type: "WebGLTile",
65
79
  source: {
66
80
  type: "GeoTIFF",
@@ -68,25 +82,34 @@ export async function createLayersFromDataAssets(
68
82
  sources: geoTIFFSources,
69
83
  },
70
84
  properties: {
71
- id,
85
+ id: createAssetID(collectionId, item.id, geoTIFFIdx),
72
86
  title,
73
87
  layerConfig,
74
88
  layerDatetime,
75
89
  },
76
90
  style,
77
- });
91
+ };
92
+ jsonArray.push(layer);
78
93
  }
79
94
 
80
95
  return jsonArray;
81
96
  }
82
97
 
83
98
  /**
99
+ * @param {string} collectionId
84
100
  * @param {import('stac-ts').StacItem} item
85
- * @param {string} id
86
101
  * @param {string} title
87
102
  * @param {Record<string,any>} [layerDatetime]
103
+ * @param {string | null} [legendInfo]
88
104
  */
89
- export const createLayersFromLinks = async (id, title, item, layerDatetime) => {
105
+ export const createLayersFromLinks = async (
106
+ collectionId,
107
+ title,
108
+ item,
109
+ layerDatetime,
110
+ legendInfo,
111
+ ) => {
112
+ log.debug("Creating layers from links");
90
113
  /** @type {Record<string,any>[]} */
91
114
  const jsonArray = [];
92
115
  const wmsArray = item.links.filter((l) => l.rel === "wms");
@@ -102,10 +125,17 @@ export const createLayersFromLinks = async (id, title, item, layerDatetime) => {
102
125
 
103
126
  await registerProjection(wmsLinkProjection);
104
127
  const projectionCode = getProjectionCode(wmsLinkProjection || "EPSG:4326");
128
+ const linkId = createLayerID(
129
+ collectionId,
130
+ item.id,
131
+ wmsLink,
132
+ projectionCode,
133
+ );
134
+ log.debug("WMS Layer added", linkId);
105
135
  let json = {
106
136
  type: "Tile",
107
137
  properties: {
108
- id,
138
+ id: linkId,
109
139
  title: wmsLink.title || title || item.id,
110
140
  layerDatetime,
111
141
  },
@@ -113,25 +143,24 @@ export const createLayersFromLinks = async (id, title, item, layerDatetime) => {
113
143
  type: "TileWMS",
114
144
  url: wmsLink.href,
115
145
  projection: projectionCode,
146
+ tileGrid: {
147
+ tileSize: [512, 512],
148
+ },
116
149
  params: {
117
150
  LAYERS: wmsLink["wms:layers"],
118
151
  TILED: true,
119
152
  },
120
153
  },
121
154
  };
122
-
123
- extractRoles(
124
- json.properties,
125
- /** @type {string[]} */ (wmsLink.roles),
126
- /** @type {string} */ (wmsLink.id) ||
127
- /** @type {string} */ (wmsLink.title) ||
128
- "",
129
- );
130
-
155
+ extractRoles(json.properties, wmsLink);
131
156
  if ("wms:dimensions" in wmsLink) {
132
157
  // Expand all dimensions into the params attribute
133
158
  Object.assign(json.source.params, wmsLink["wms:dimensions"]);
134
159
  }
160
+ if (legendInfo !== null) {
161
+ // @ts-expect-error once we have a eox-map config type we can remove this
162
+ json.properties.description = legendInfo;
163
+ }
135
164
  jsonArray.push(json);
136
165
  }
137
166
 
@@ -148,11 +177,21 @@ export const createLayersFromLinks = async (id, title, item, layerDatetime) => {
148
177
  // that needs to be removed once catalog and wmts creation from capabilities
149
178
  // combined with custom view projections is solved
150
179
  let json;
180
+ const linkId = createLayerID(
181
+ collectionId,
182
+ item.id,
183
+ wmtsLink,
184
+ projectionCode,
185
+ );
151
186
  if (wmtsLink.title === "wmts capabilities") {
187
+ log.debug(
188
+ "Warning: WMTS Layer from capabilities added, function needs to be updated",
189
+ linkId,
190
+ );
152
191
  json = {
153
192
  type: "Tile",
154
193
  properties: {
155
- id,
194
+ id: linkId,
156
195
  title: title || item.id,
157
196
  layerDatetime,
158
197
  },
@@ -172,10 +211,14 @@ export const createLayersFromLinks = async (id, title, item, layerDatetime) => {
172
211
  },
173
212
  };
174
213
  } else {
214
+ log.debug(
215
+ "Warning: WMTS Layer from capabilities added, function needs to be updated",
216
+ linkId,
217
+ );
175
218
  json = {
176
219
  type: "Tile",
177
220
  properties: {
178
- id,
221
+ id: linkId,
179
222
  title: wmtsLink.title || title || item.id,
180
223
  layerDatetime,
181
224
  },
@@ -187,21 +230,13 @@ export const createLayersFromLinks = async (id, title, item, layerDatetime) => {
187
230
  matrixSet: wmtsLink.matrixSet || "EPSG:3857",
188
231
  projection: projectionCode,
189
232
  tileGrid: {
190
- tileSize: [128, 128],
233
+ tileSize: [512, 512],
191
234
  },
192
235
  dimensions: wmtsLink["wmts:dimensions"],
193
236
  },
194
237
  };
195
238
  }
196
-
197
- extractRoles(
198
- json.properties,
199
- /** @type {string[]} */ (wmtsLink.roles),
200
- /** @type {string} */ (wmtsLink.id) ||
201
- /** @type {string} */ (wmtsLink.title) ||
202
- "",
203
- );
204
-
239
+ extractRoles(json.properties, wmtsLink);
205
240
  jsonArray.push(json);
206
241
  }
207
242
 
@@ -211,12 +246,18 @@ export const createLayersFromLinks = async (id, title, item, layerDatetime) => {
211
246
  (xyzLink?.["proj:epsg"] || xyzLink?.["eodash:proj4_def"]);
212
247
 
213
248
  await registerProjection(xyzLinkProjection);
214
-
215
249
  const projectionCode = getProjectionCode(xyzLinkProjection || "EPSG:3857");
250
+ const linkId = createLayerID(
251
+ collectionId,
252
+ item.id,
253
+ xyzLink,
254
+ projectionCode,
255
+ );
256
+ log.debug("XYZ Layer added", linkId);
216
257
  let json = {
217
258
  type: "Tile",
218
259
  properties: {
219
- id,
260
+ id: linkId,
220
261
  title: xyzLink.title || title || item.id,
221
262
  roles: xyzLink.roles,
222
263
  layerDatetime,
@@ -228,11 +269,7 @@ export const createLayersFromLinks = async (id, title, item, layerDatetime) => {
228
269
  },
229
270
  };
230
271
 
231
- extractRoles(
232
- json.properties,
233
- /** @type {string[]} */ (xyzLink.roles),
234
- /** @type {string} */ (xyzLink.id || xyzLink.title || ""),
235
- );
272
+ extractRoles(json.properties, xyzLink);
236
273
  jsonArray.push(json);
237
274
  }
238
275
  return jsonArray;
@@ -1,7 +1,6 @@
1
1
  import { Collection, Item } from "stac-js";
2
2
  import { toAbsolute } from "stac-js/src/http.js";
3
3
  import {
4
- createLayerID,
5
4
  extractLayerConfig,
6
5
  extractLayerDatetime,
7
6
  extractRoles,
@@ -11,11 +10,9 @@ import {
11
10
  replaceLayer,
12
11
  } from "./helpers";
13
12
  import { getLayers, registerProjection } from "@/store/Actions";
14
- import {
15
- createLayersFromDataAssets,
16
- createLayersFromLinks,
17
- } from "./createLayers";
18
- import axios from "axios";
13
+ import { createLayersFromAssets, createLayersFromLinks } from "./createLayers";
14
+ import axios from "@/plugins/axios";
15
+ import log from "loglevel";
19
16
 
20
17
  export class EodashCollection {
21
18
  #collectionUrl = "";
@@ -114,6 +111,14 @@ export class EodashCollection {
114
111
  * @returns {Promise<Record<string,any>[]>} arrays
115
112
  * */
116
113
  async buildJsonArray(item, itemUrl, title, isGeoDB, itemDatetime) {
114
+ log.debug(
115
+ "Building JSON array",
116
+ item,
117
+ itemUrl,
118
+ title,
119
+ isGeoDB,
120
+ itemDatetime,
121
+ );
117
122
  await this.fetchCollection();
118
123
  // registering top level indicator projection
119
124
  const indicatorProjection =
@@ -133,7 +138,7 @@ export class EodashCollection {
133
138
  {
134
139
  type: "Vector",
135
140
  properties: {
136
- id: createLayerID(this.#collectionStac?.id ?? "", item.id, false),
141
+ id: this.#collectionStac?.id ?? "",
137
142
  title: this.#collectionStac?.title || item.id,
138
143
  },
139
144
  source: {
@@ -178,18 +183,28 @@ export class EodashCollection {
178
183
  Object.keys(dataAssets).length;
179
184
 
180
185
  if (isSupported) {
186
+ // Checking for potential legend asset
187
+ let legendInfo = null;
188
+ if (this.#collectionStac?.assets?.legend?.href) {
189
+ legendInfo = `
190
+ <div style="text-align:center; width: 100%">
191
+ <img src="${this.#collectionStac.assets.legend.href}" style="max-height:70px; margin-top:-15px; margin-bottom:-20px;" />
192
+ </div>`;
193
+ }
181
194
  const links = await createLayersFromLinks(
182
- createLayerID(this.#collectionStac?.id ?? "", item.id, false),
195
+ this.#collectionStac?.id ?? "",
183
196
  title,
184
197
  item,
185
198
  layerDatetime,
199
+ legendInfo,
186
200
  );
187
201
  jsonArray.push(
188
202
  ...links,
189
- ...(await createLayersFromDataAssets(
190
- createLayerID(this.#collectionStac?.id ?? "", item.id, true),
203
+ ...(await createLayersFromAssets(
204
+ this.#collectionStac?.id ?? "",
191
205
  title || this.#collectionStac?.title || item.id,
192
206
  dataAssets,
207
+ item,
193
208
  style,
194
209
  layerConfig,
195
210
  layerDatetime,
@@ -203,7 +218,7 @@ export class EodashCollection {
203
218
  displayFootprint: false,
204
219
  data: item,
205
220
  properties: {
206
- id: createLayerID(this.#collectionStac?.id ?? "", item.id, false),
221
+ id: this.#collectionStac?.id ?? "",
207
222
  title: title || item.id,
208
223
  layerConfig,
209
224
  },
@@ -211,8 +226,8 @@ export class EodashCollection {
211
226
  };
212
227
  extractRoles(
213
228
  json.properties,
214
- /** @type {string[]} */ (item?.roles),
215
- item.id || /** @type {string} */ (item.title) || "" + " STAC",
229
+ //@ts-expect-error using the item incase no self link is found
230
+ item.links.find((link) => link.rel === "self") ?? item,
216
231
  );
217
232
  jsonArray.push(json);
218
233
  }
@@ -222,6 +237,7 @@ export class EodashCollection {
222
237
 
223
238
  async fetchCollection() {
224
239
  if (!this.#collectionStac) {
240
+ log.debug("Fetching collection file", this.#collectionUrl);
225
241
  const col = await axios
226
242
  .get(this.#collectionUrl)
227
243
  .then((resp) => resp.data);
@@ -260,12 +276,7 @@ export class EodashCollection {
260
276
  }
261
277
 
262
278
  async getExtent() {
263
- if (!this.#collectionStac) {
264
- const stac = await axios
265
- .get(this.#collectionUrl)
266
- .then((resp) => resp.data);
267
- this.#collectionStac = new Collection(stac);
268
- }
279
+ await this.fetchCollection();
269
280
  return this.#collectionStac?.extent;
270
281
  }
271
282
 
@@ -329,4 +340,43 @@ export class EodashCollection {
329
340
 
330
341
  return updatedLayers;
331
342
  }
343
+
344
+ /**
345
+ * Returns base layers and overlay layers of a STAC Collection
346
+ *
347
+ * @param {import("stac-ts").StacCollection} indicator */
348
+ static async getIndicatorLayers(indicator) {
349
+ const indicatorAssets = Object.keys(indicator?.assets ?? {}).reduce(
350
+ (assets, ast) => {
351
+ if (
352
+ indicator.assets?.[ast].roles?.includes("baselayer") ||
353
+ indicator.assets?.[ast].roles?.includes("overlay")
354
+ ) {
355
+ assets[ast] = indicator.assets[ast];
356
+ }
357
+ return assets;
358
+ },
359
+ /** @type {Record<string,import('stac-ts').StacAsset>} */ ({}),
360
+ );
361
+
362
+ return [
363
+ ...(await createLayersFromLinks(
364
+ indicator?.id ?? "",
365
+ indicator?.title || indicator.id,
366
+ //@ts-expect-error indicator instead of item
367
+ indicator,
368
+ // layerDatetime,
369
+ )),
370
+ ...(await createLayersFromAssets(
371
+ indicator?.id ?? "",
372
+ indicator?.title || indicator.id,
373
+ indicatorAssets,
374
+ //@ts-expect-error indicator instead of item
375
+ indicator,
376
+ // style,
377
+ // layerConfig,
378
+ // layerDatetime,
379
+ )),
380
+ ];
381
+ }
332
382
  }
@@ -1,7 +1,8 @@
1
- import { changeMapProjection } from "@/store/Actions";
1
+ import { changeMapProjection, registerProjection } from "@/store/Actions";
2
2
  import { availableMapProjection } from "@/store/States";
3
3
  import { toAbsolute } from "stac-js/src/http.js";
4
- import axios from "axios";
4
+ import axios from "@/plugins/axios";
5
+ import log from "loglevel";
5
6
 
6
7
  /** @param {import("stac-ts").StacLink[]} [links] */
7
8
  export function generateFeatures(links) {
@@ -48,8 +49,14 @@ export function extractLayerConfig(style) {
48
49
  let layerConfig = undefined;
49
50
  if (style?.jsonform) {
50
51
  layerConfig = { schema: style.jsonform, type: "style" };
52
+ style = { ...style };
51
53
  delete style.jsonform;
52
54
  }
55
+ log.debug(
56
+ "extracted layerConfig",
57
+ JSON.parse(JSON.stringify({ layerConfig, style })),
58
+ );
59
+
53
60
  return { layerConfig, style };
54
61
  }
55
62
 
@@ -58,9 +65,9 @@ export function extractLayerConfig(style) {
58
65
  * updates {@link availableMapProjection}
59
66
  * @param {import('stac-ts').StacCollection} [STAcCollection]
60
67
  */
61
- export const setMapProjFromCol = (STAcCollection) => {
68
+ export const setMapProjFromCol = async (STAcCollection) => {
62
69
  // if a projection exists on the collection level
63
-
70
+ log.debug("Checking for available map projection in indicator");
64
71
  const projection =
65
72
  /** @type {number | string | {name: string, def: string} | undefined} */
66
73
  (
@@ -69,18 +76,23 @@ export const setMapProjFromCol = (STAcCollection) => {
69
76
  STAcCollection?.["eodash:proj4_def"]
70
77
  );
71
78
  if (projection) {
79
+ log.debug("Projection found", projection);
80
+ await registerProjection(projection);
72
81
  const projectionCode = getProjectionCode(projection);
73
- if (
74
- availableMapProjection.value &&
75
- availableMapProjection.value !== projectionCode
76
- ) {
77
- changeMapProjection(projection);
82
+ if (availableMapProjection.value !== projectionCode) {
83
+ log.debug(
84
+ "Changing map projection",
85
+ availableMapProjection.value,
86
+ projectionCode,
87
+ );
88
+ await changeMapProjection(projection);
78
89
  }
79
90
  // set it for `EodashMapBtns`
80
91
  availableMapProjection.value = /** @type {string} */ (projectionCode);
81
92
  } else {
82
93
  // reset to default projection
83
- changeMapProjection((availableMapProjection.value = "EPSG:3857"));
94
+ log.debug("Resetting projection to default EPSG:3857");
95
+ await changeMapProjection((availableMapProjection.value = ""));
84
96
  }
85
97
  };
86
98
 
@@ -117,19 +129,23 @@ export function extractCollectionUrls(stacObject, basepath) {
117
129
  /**
118
130
  * Assign extracted roles to layer properties
119
131
  * @param {Record<string,any>} properties
120
- * @param {string[]} roles
121
- * @param {string} id - unique ID for baselayers and overlays
132
+ * @param {import("stac-ts").StacLink | import("stac-ts").StacAsset} linkOrAsset
122
133
  * */
123
- export const extractRoles = (properties, roles, id) => {
134
+ export const extractRoles = (properties, linkOrAsset) => {
135
+ const roles = /** @type {string[]} */ (linkOrAsset.roles);
124
136
  roles?.forEach((role) => {
125
137
  if (role === "visible") {
126
138
  properties.visible = true;
127
139
  }
128
140
  if (role === "overlay" || role === "baselayer") {
129
141
  properties.group = role;
130
- const [colId, itemId, isAsset, _random] = properties.id.split(";:;");
131
- properties.id = [colId, itemId, isAsset, id].join(";:;");
142
+ //remove all the properties and replace the random ID with baselayer
143
+ // provided ID
144
+ const [_colId, _itemId, _isAsset, _random, proj] =
145
+ properties.id.split(";:;");
146
+ properties.id = ["", "", "", "", linkOrAsset.id, proj].join(";:;");
132
147
  }
148
+
133
149
  return properties;
134
150
  });
135
151
  };
@@ -150,7 +166,9 @@ export const fetchStyle = async (item, itemUrl) => {
150
166
 
151
167
  /** @type {import("ol/layer/WebGLTile").Style & {jsonform?:Record<string,any>}} */
152
168
  const styleJson = await axios.get(url).then((resp) => resp.data);
153
- return styleJson;
169
+
170
+ log.debug("fetched styles JSON", JSON.parse(JSON.stringify(styleJson)));
171
+ return { ...styleJson };
154
172
  }
155
173
  };
156
174
 
@@ -176,10 +194,10 @@ export const getProjectionCode = (projection) => {
176
194
 
177
195
  /**
178
196
  * @param {import("stac-ts").StacLink[]} [links]
179
- * @param {string|null} [current]
197
+ * @param {string|null} [currentStep]
180
198
  **/
181
- export const extractLayerDatetime = (links, current) => {
182
- if (!current || !links?.length) {
199
+ export const extractLayerDatetime = (links, currentStep) => {
200
+ if (!currentStep || !links?.length) {
183
201
  return undefined;
184
202
  }
185
203
 
@@ -190,9 +208,9 @@ export const extractLayerDatetime = (links, current) => {
190
208
  }
191
209
 
192
210
  /** @type {string[]} */
193
- const values = [];
211
+ const controlValues = [];
194
212
  try {
195
- current = new Date(current).toISOString();
213
+ currentStep = new Date(currentStep).toISOString();
196
214
 
197
215
  links.reduce((vals, link) => {
198
216
  if (link.datetime && link.rel === "item") {
@@ -201,25 +219,25 @@ export const extractLayerDatetime = (links, current) => {
201
219
  );
202
220
  }
203
221
  return vals;
204
- }, values);
222
+ }, controlValues);
205
223
  } catch (e) {
206
224
  console.warn("[eodash] not supported datetime format was provided", e);
207
225
  return undefined;
208
226
  }
209
- // not enough values
210
- if (values.length <= 1) {
227
+ // not enough controlValues
228
+ if (controlValues.length <= 1) {
211
229
  return undefined;
212
230
  }
213
231
 
214
232
  // item datetime is not included in the item links datetime
215
- if (!values.includes(current)) {
233
+ if (!controlValues.includes(currentStep)) {
216
234
  return undefined;
217
235
  }
218
236
 
219
237
  return {
220
- values,
221
- current,
222
- slider: false,
238
+ controlValues,
239
+ currentStep,
240
+ slider: true,
223
241
  disablePlay: true,
224
242
  };
225
243
  };
@@ -279,7 +297,7 @@ export const getColFromLayer = async (indicators, layer) => {
279
297
  const collections = await Promise.all(
280
298
  indicators.map((ind) => ind.fetchCollection()),
281
299
  );
282
- const [collectionId, itemId, _asset, _random] = layer.get("id").split(";:;");
300
+ const [collectionId, itemId, ..._other] = layer.get("id").split(";:;");
283
301
 
284
302
  const chosen = collections.find((col) => {
285
303
  const isInd =
@@ -291,17 +309,72 @@ export const getColFromLayer = async (indicators, layer) => {
291
309
  });
292
310
  return indicators.find((ind) => ind.collectionStac?.id === chosen?.id);
293
311
  };
312
+
294
313
  /**
314
+ * generates layer specific ID, related functions are: {@link assignProjID} & {@link extractRoles}
315
+ * @param {string} collectionId
316
+ * @param {string} itemId
317
+ * @param {import('stac-ts').StacLink} link
318
+ * @param {string} projectionCode
295
319
  *
296
- * @param {string} colId
320
+ */
321
+ export const createLayerID = (collectionId, itemId, link, projectionCode) => {
322
+ const linkId = link.id || link.title || link.href;
323
+ let lId = `${collectionId ?? ""};:;${itemId ?? ""};:;${linkId ?? ""};:;${projectionCode ?? ""}`;
324
+ // If we are looking at base layers and overlays we remove the collection and item part
325
+ // as we want to make sure tiles are not reloaded when switching layers
326
+ if (
327
+ link.roles &&
328
+ // @ts-expect-error it seems roles it not defined for links yet
329
+ link.roles.find((r) => ["baselayer", "overlay"].includes(r))
330
+ ) {
331
+ lId = `${linkId ?? ""};:;${projectionCode ?? ""}`;
332
+ }
333
+ log.debug("Generated Layer ID", lId);
334
+ return lId;
335
+ };
336
+
337
+ /**
338
+ * generates layer specific ID, related functions are: {@link assignProjID} & {@link extractRoles}
339
+ * @param {string} collectionId
297
340
  * @param {string} itemId
298
- * @param {boolean} isAsset
299
- * @returns
341
+ * @param {number} index
342
+ *
300
343
  */
301
- export const createLayerID = (colId, itemId, isAsset) => {
302
- return `${colId ?? ""};:;${itemId ?? ""};:;${isAsset ? "_asset" : ""};:;${Math.random().toString(16).slice(2)}`;
344
+ export const createAssetID = (collectionId, itemId, index) => {
345
+ let lId = `${collectionId ?? ""};:;${itemId ?? ""};:;${index ?? ""}`;
346
+ log.debug("Generated Asset ID", lId);
347
+ return lId;
303
348
  };
304
349
 
350
+ /**
351
+ *
352
+ * @param {import("stac-ts").StacItem} item
353
+ * @param {import("stac-ts").StacLink | import("stac-ts").StacAsset} linkOrAsset
354
+ * @param {string} id - {@link createLayerID} & {@link extractRoles}
355
+ * @param {{ properties:{id:string} & Record<string, any> }& Record<string,any>} layer
356
+ * @returns
357
+ */
358
+ export function assignProjID(item, linkOrAsset, id, layer) {
359
+ const indicatorProjection =
360
+ /** @type { string | undefined} */
361
+ (item?.["proj:epsg"]) ||
362
+ /** @type { {name?: string} | undefined} */
363
+ (item?.["eodash:mapProjection"])?.name ||
364
+ "EPSG:3857";
365
+
366
+ const idArr = id.split(";:;");
367
+
368
+ idArr.pop();
369
+ idArr.push(indicatorProjection);
370
+ const updatedID = idArr.join(";:;");
371
+ layer.properties.id = updatedID;
372
+
373
+ log.debug("Updating layer id", updatedID);
374
+
375
+ return updatedID;
376
+ }
377
+
305
378
  /**
306
379
  * creates a structured clone from the layers and
307
380
  * removes all properties from the clone
@@ -316,7 +389,7 @@ export const removeUnneededProperties = (layers) => {
316
389
  const title = layer.properties.title;
317
390
  layer.properties = { id, title };
318
391
  if (layer["interactions"]) {
319
- delete layer["interactions"]
392
+ delete layer["interactions"];
320
393
  }
321
394
  if (layer.type === "Group") {
322
395
  layer.layers = removeUnneededProperties(layer.layers);