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

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/README.md +1 -1
  2. package/core/client/composables/EodashMap.js +245 -0
  3. package/core/client/composables/index.js +2 -2
  4. package/core/client/eodash.js +1 -2
  5. package/core/client/store/Actions.js +30 -10
  6. package/core/client/store/States.js +4 -1
  7. package/core/client/store/stac.js +52 -2
  8. package/core/client/types.d.ts +6 -2
  9. package/core/client/utils/createLayers.js +147 -40
  10. package/core/client/utils/eodashSTAC.js +94 -19
  11. package/core/client/utils/helpers.js +189 -11
  12. package/core/client/utils/states.js +17 -0
  13. package/dist/client/{DashboardLayout-ulCTLwXv.js → DashboardLayout-CCtyOil0.js} +2 -2
  14. package/dist/client/{DynamicWebComponent-CZJjeckP.js → DynamicWebComponent-But2r1Sj.js} +2 -2
  15. package/dist/client/EodashDatePicker-jeYiWflv.js +247 -0
  16. package/dist/client/{EodashItemFilter-9hK-3-7Y.js → EodashItemFilter-BFlfWeE_.js} +2028 -2024
  17. package/dist/client/EodashLayerControl-BhZL4pYM.js +24358 -0
  18. package/dist/client/{EodashMap-jqF-NaSp.js → EodashMap-C5tOgVOv.js} +22268 -24006
  19. package/dist/client/{EodashMapBtns-F7rE6A-2.js → EodashMapBtns-CdDfVQj0.js} +2 -2
  20. package/dist/client/{ExportState-CHU5c0uO.js → ExportState-CKCCN_VI.js} +142 -136
  21. package/dist/client/{Footer-DjkwaDHV.js → Footer-B9yVgyzx.js} +67 -65
  22. package/dist/client/{Header-V8pZw2HR.js → Header-CPIlUEOq.js} +4 -4
  23. package/dist/client/{IframeWrapper-C8EZZnHk.js → IframeWrapper-DRw1kHJm.js} +1 -1
  24. package/dist/client/{MobileLayout-zOO_ZJVe.js → MobileLayout-CPxVee5U.js} +6 -6
  25. package/dist/client/{PopUp-BNnXTHYD.js → PopUp-Dca-gx9a.js} +5 -5
  26. package/dist/client/{VImg-Cj6-XkWV.js → VImg-PHLA1nP1.js} +2 -2
  27. package/dist/client/{VMain-BXL9EwGV.js → VMain-Ck81LJfb.js} +2 -2
  28. package/dist/client/{VOverlay-C9MeDzGb.js → VOverlay-CL4hiJB8.js} +92 -92
  29. package/dist/client/{WidgetsContainer-Cw4LFyGR.js → WidgetsContainer-jxk3kw-d.js} +1 -1
  30. package/dist/client/asWebComponent-3OsFQJVx.js +23633 -0
  31. package/dist/client/eo-dash.js +1 -1
  32. package/dist/client/{forwardRefs-DF-jCteQ.js → forwardRefs-BxZaq9ml.js} +1 -1
  33. package/dist/client/{index-BfF7LPVL.js → index-Vul961Xy.js} +23 -23
  34. package/dist/client/{lerc-B4lXefGh-WUagmXWl.js → lerc-B4lXefGh-BESXOHWk.js} +1 -1
  35. package/dist/client/{ssrBoot-DNvPtEea.js → ssrBoot-BFMBrCqY.js} +1 -1
  36. package/dist/client/style.css +2 -2
  37. package/dist/client/{transition-Dc2dpya2.js → transition-U5aFjJtV.js} +1 -1
  38. package/dist/client/{webfontloader-qotgY98I.js → webfontloader-D_JbBwHu.js} +1 -1
  39. package/package.json +5 -3
  40. package/widgets/EodashDatePicker.vue +32 -40
  41. package/widgets/EodashItemFilter.vue +2 -0
  42. package/widgets/EodashLayerControl.vue +69 -7
  43. package/widgets/EodashMap.vue +35 -208
  44. package/widgets/ExportState.vue +8 -7
  45. package/dist/client/EodashDatePicker-BClSZg9g.js +0 -252
  46. package/dist/client/EodashLayerControl-p5FdBiiJ.js +0 -20969
  47. package/dist/client/_commonjsHelpers-DaMA6jEr.js +0 -8
  48. package/dist/client/asWebComponent-GN3G-Gdj.js +0 -20451
  49. package/dist/client/helpers-XtsCspQr.js +0 -1390
@@ -1,5 +1,5 @@
1
1
  import { registerProjection } from "@/store/Actions";
2
- import { extractRoles } from "./helpers";
2
+ import { extractRoles, getProjectionCode } from "./helpers";
3
3
 
4
4
  /**
5
5
  * @param {string} id
@@ -7,6 +7,7 @@ import { extractRoles } from "./helpers";
7
7
  * @param {Record<string,import("stac-ts").StacAsset>} assets
8
8
  * @param {import("ol/layer/WebGLTile").Style} [style]
9
9
  * @param {Record<string, unknown>} [layerConfig]
10
+ * @param {Record<string, unknown>} [layerDatetime]
10
11
  **/
11
12
  export async function createLayersFromDataAssets(
12
13
  id,
@@ -14,14 +15,17 @@ export async function createLayersFromDataAssets(
14
15
  assets,
15
16
  style,
16
17
  layerConfig,
18
+ layerDatetime,
17
19
  ) {
18
20
  let jsonArray = [];
19
21
  let geoTIFFSources = [];
20
22
  for (const ast in assets) {
21
23
  // register projection if exists
22
- await registerProjection(
23
- /** @type {number | undefined} */ (assets[ast]?.["proj:epsg"]),
24
- );
24
+ const assetProjection =
25
+ /** @type {string | number | {name: string, def: string, extent?:number[]} | undefined} */ (
26
+ assets[ast]?.["proj:epsg"] || assets[ast]?.["eodash:proj4_def"]
27
+ );
28
+ await registerProjection(assetProjection);
25
29
 
26
30
  if (assets[ast]?.type === "application/geo+json") {
27
31
  const layer = {
@@ -34,6 +38,7 @@ export async function createLayersFromDataAssets(
34
38
  properties: {
35
39
  id,
36
40
  title,
41
+ layerDatetime,
37
42
  ...(layerConfig && {
38
43
  layerConfig: {
39
44
  ...layerConfig,
@@ -41,9 +46,13 @@ export async function createLayersFromDataAssets(
41
46
  },
42
47
  }),
43
48
  },
44
- ...(!style?.variables && {style}),
49
+ ...(!style?.variables && { style }),
45
50
  };
46
- extractRoles(layer.properties, assets[ast]?.roles ?? []);
51
+ extractRoles(
52
+ layer.properties,
53
+ assets[ast]?.roles ?? [],
54
+ /** @type {string} */ (assets[ast].id || assets[ast].title || ""),
55
+ );
47
56
  jsonArray.push(layer);
48
57
  } else if (assets[ast]?.type === "image/tiff") {
49
58
  geoTIFFSources.push({ url: assets[ast].href });
@@ -62,6 +71,7 @@ export async function createLayersFromDataAssets(
62
71
  id,
63
72
  title,
64
73
  layerConfig,
74
+ layerDatetime,
65
75
  },
66
76
  style,
67
77
  });
@@ -74,59 +84,156 @@ export async function createLayersFromDataAssets(
74
84
  * @param {import('stac-ts').StacItem} item
75
85
  * @param {string} id
76
86
  * @param {string} title
87
+ * @param {Record<string,any>} [layerDatetime]
77
88
  */
78
- export const createLayersFromLinks = (id, title, item) => {
89
+ export const createLayersFromLinks = async (id, title, item, layerDatetime) => {
79
90
  /** @type {Record<string,any>[]} */
80
91
  const jsonArray = [];
81
92
  const wmsArray = item.links.filter((l) => l.rel === "wms");
82
- const xyzArray = item.links.filter((l) => l.rel === "xyz");
93
+ const wmtsArray = item.links.filter((l) => l.rel === "wmts");
94
+ const xyzArray = item.links.filter((l) => l.rel === "xyz") ?? [];
95
+
96
+ for (const wmsLink of wmsArray ?? []) {
97
+ // Registering setting sub wms link projection
98
+
99
+ const wmsLinkProjection =
100
+ /** @type {number | string | {name: string, def: string} | undefined} */
101
+ (wmsLink?.["proj:epsg"] || wmsLink?.["eodash:proj4_def"]);
102
+
103
+ await registerProjection(wmsLinkProjection);
104
+ const projectionCode = getProjectionCode(wmsLinkProjection || "EPSG:4326");
105
+ let json = {
106
+ type: "Tile",
107
+ properties: {
108
+ id,
109
+ title: wmsLink.title || title || item.id,
110
+ layerDatetime,
111
+ },
112
+ source: {
113
+ type: "TileWMS",
114
+ url: wmsLink.href,
115
+ projection: projectionCode,
116
+ params: {
117
+ LAYERS: wmsLink["wms:layers"],
118
+ TILED: true,
119
+ },
120
+ },
121
+ };
83
122
 
84
- if (wmsArray.length) {
85
- wmsArray.forEach((link) => {
86
- let json = {
123
+ extractRoles(
124
+ json.properties,
125
+ /** @type {string[]} */ (wmsLink.roles),
126
+ /** @type {string} */ (wmsLink.id) ||
127
+ /** @type {string} */ (wmsLink.title) ||
128
+ "",
129
+ );
130
+
131
+ if ("wms:dimensions" in wmsLink) {
132
+ // Expand all dimensions into the params attribute
133
+ Object.assign(json.source.params, wmsLink["wms:dimensions"]);
134
+ }
135
+ jsonArray.push(json);
136
+ }
137
+
138
+ for (const wmtsLink of wmtsArray ?? []) {
139
+ // Registering setting sub wmts link projection
140
+
141
+ const wmtsLinkProjection =
142
+ /** @type {number | string | {name: string, def: string} | undefined} */
143
+ (wmtsLink?.["proj:epsg"] || wmtsLink?.["eodash:proj4_def"]);
144
+
145
+ await registerProjection(wmtsLinkProjection);
146
+ const projectionCode = getProjectionCode(wmtsLinkProjection || "EPSG:3857");
147
+ // TODO: WARNING! This is a temporary project specific implementation
148
+ // that needs to be removed once catalog and wmts creation from capabilities
149
+ // combined with custom view projections is solved
150
+ let json;
151
+ if (wmtsLink.title === "wmts capabilities") {
152
+ json = {
87
153
  type: "Tile",
88
154
  properties: {
89
- id: id || link.id,
90
- title: title || link.title || item.id,
155
+ id,
156
+ title: title || item.id,
157
+ layerDatetime,
91
158
  },
92
159
  source: {
93
- type: "TileWMS",
94
- url: link.href,
95
- params: {
96
- LAYERS: link["wms:layers"],
97
- TILED: true,
160
+ type: "WMTS",
161
+ // TODO: Hard coding url as the current one set is for capabilities
162
+ url: "https://wmts.marine.copernicus.eu/teroWmts",
163
+ layer: wmtsLink["wmts:layer"],
164
+ style: wmtsLink.style || "default",
165
+ // TODO: Hard coding matrixSet until we find solution to wmts creation from capabilities
166
+ matrixSet: "EPSG:3857",
167
+ projection: projectionCode,
168
+ tileGrid: {
169
+ tileSize: [128, 128],
98
170
  },
171
+ dimensions: wmtsLink["wmts:dimensions"],
99
172
  },
100
173
  };
101
-
102
- extractRoles(json.properties, /** @type {string[]} */ (link.roles));
103
-
104
- if ("wms:dimensions" in link) {
105
- // Expand all dimensions into the params attribute
106
- Object.assign(json.source.params, link["wms:dimensions"]);
107
- }
108
- jsonArray.push(json);
109
- });
110
- }
111
-
112
- if (xyzArray.length) {
113
- xyzArray.forEach((link) => {
114
- let json = {
174
+ } else {
175
+ json = {
115
176
  type: "Tile",
116
177
  properties: {
117
- id: link.id || item.id,
118
- title: title || link.title || item.id,
119
- roles: link.roles,
178
+ id,
179
+ title: wmtsLink.title || title || item.id,
180
+ layerDatetime,
120
181
  },
121
182
  source: {
122
- type: "XYZ",
123
- url: link.href,
183
+ type: "WMTS",
184
+ url: wmtsLink,
185
+ layer: wmtsLink["wmts:layer"],
186
+ style: wmtsLink.style || "default",
187
+ matrixSet: wmtsLink.matrixSet || "EPSG:3857",
188
+ projection: projectionCode,
189
+ tileGrid: {
190
+ tileSize: [128, 128],
191
+ },
192
+ dimensions: wmtsLink["wmts:dimensions"],
124
193
  },
125
194
  };
195
+ }
126
196
 
127
- extractRoles(json.properties, /** @type {string[]} */ (link.roles));
128
- jsonArray.push(json);
129
- });
197
+ extractRoles(
198
+ json.properties,
199
+ /** @type {string[]} */ (wmtsLink.roles),
200
+ /** @type {string} */ (wmtsLink.id) ||
201
+ /** @type {string} */ (wmtsLink.title) ||
202
+ "",
203
+ );
204
+
205
+ jsonArray.push(json);
206
+ }
207
+
208
+ for (const xyzLink of xyzArray ?? []) {
209
+ const xyzLinkProjection =
210
+ /** @type {number | string | {name: string, def: string} | undefined} */
211
+ (xyzLink?.["proj:epsg"] || xyzLink?.["eodash:proj4_def"]);
212
+
213
+ await registerProjection(xyzLinkProjection);
214
+
215
+ const projectionCode = getProjectionCode(xyzLinkProjection || "EPSG:3857");
216
+ let json = {
217
+ type: "Tile",
218
+ properties: {
219
+ id,
220
+ title: xyzLink.title || title || item.id,
221
+ roles: xyzLink.roles,
222
+ layerDatetime,
223
+ },
224
+ source: {
225
+ type: "XYZ",
226
+ url: xyzLink.href,
227
+ projection: projectionCode,
228
+ },
229
+ };
230
+
231
+ extractRoles(
232
+ json.properties,
233
+ /** @type {string[]} */ (xyzLink.roles),
234
+ /** @type {string} */ (xyzLink.id || xyzLink.title || ""),
235
+ );
236
+ jsonArray.push(json);
130
237
  }
131
238
  return jsonArray;
132
239
  };
@@ -1,13 +1,16 @@
1
1
  import { Collection, Item } from "stac-js";
2
2
  import { toAbsolute } from "stac-js/src/http.js";
3
3
  import {
4
+ createLayerID,
4
5
  extractLayerConfig,
6
+ extractLayerDatetime,
5
7
  extractRoles,
6
8
  fetchStyle,
9
+ findLayer,
7
10
  generateFeatures,
8
- setMapProjFromCol,
11
+ replaceLayer,
9
12
  } from "./helpers";
10
- import { registerProjection } from "@/store/Actions";
13
+ import { getLayers, registerProjection } from "@/store/Actions";
11
14
  import {
12
15
  createLayersFromDataAssets,
13
16
  createLayersFromLinks,
@@ -20,6 +23,11 @@ export class EodashCollection {
20
23
  /** @type {import("stac-ts").StacCollection | undefined} */
21
24
  #collectionStac;
22
25
 
26
+ // read only
27
+ get collectionStac() {
28
+ return this.#collectionStac;
29
+ }
30
+
23
31
  /**
24
32
  * @type {import("stac-ts").StacLink
25
33
  * | import("stac-ts").StacItem
@@ -52,13 +60,7 @@ export class EodashCollection {
52
60
  let layersJson = [];
53
61
 
54
62
  // Load collectionstac if not yet initialized
55
- if (!this.#collectionStac) {
56
- stac = await axios.get(this.#collectionUrl).then((resp) => resp.data);
57
- this.#collectionStac = new Collection(stac);
58
- }
59
-
60
- // set availabe map projection
61
- setMapProjFromCol(this.#collectionStac);
63
+ stac = await this.fetchCollection();
62
64
 
63
65
  const isGeoDB = stac?.endpointtype === "GeoDB";
64
66
 
@@ -94,7 +96,8 @@ export class EodashCollection {
94
96
  // specific item was requested
95
97
  const item = new Item(stac);
96
98
  this.selectedItem = item;
97
- const title = this.#collectionStac.title || this.#collectionStac.id;
99
+ const title =
100
+ this.#collectionStac?.title || this.#collectionStac?.id || "";
98
101
  layersJson.unshift(
99
102
  ...(await this.buildJsonArray(item, stacItemUrl, title, isGeoDB)),
100
103
  );
@@ -107,11 +110,18 @@ export class EodashCollection {
107
110
  * @param {string} itemUrl
108
111
  * @param {string} title
109
112
  * @param {boolean} isGeoDB
113
+ * @param {string} [itemDatetime]
110
114
  * @returns {Promise<Record<string,any>[]>} arrays
111
115
  * */
112
- async buildJsonArray(item, itemUrl, title, isGeoDB) {
116
+ async buildJsonArray(item, itemUrl, title, isGeoDB, itemDatetime) {
117
+ await this.fetchCollection();
118
+ // registering top level indicator projection
119
+ const indicatorProjection =
120
+ item?.["proj:epsg"] || item?.["eodash:proj4_def"];
113
121
  await registerProjection(
114
- /** @type {number | undefined} */ (item?.["proj:epsg"]),
122
+ /** @type {number | string | {name: string, def: string; extent: number[] | undefined;} } */ (
123
+ indicatorProjection
124
+ ),
115
125
  );
116
126
 
117
127
  const jsonArray = [];
@@ -123,7 +133,7 @@ export class EodashCollection {
123
133
  {
124
134
  type: "Vector",
125
135
  properties: {
126
- id: item.id,
136
+ id: createLayerID(this.#collectionStac?.id ?? "", item.id, false),
127
137
  title: this.#collectionStac?.title || item.id,
128
138
  },
129
139
  source: {
@@ -152,6 +162,11 @@ export class EodashCollection {
152
162
  await fetchStyle(item, itemUrl),
153
163
  );
154
164
 
165
+ const layerDatetime = extractLayerDatetime(
166
+ this.getItems(),
167
+ item.properties?.datetime ?? itemDatetime,
168
+ );
169
+
155
170
  const dataAssets = Object.keys(item?.assets ?? {}).reduce((data, ast) => {
156
171
  if (item.assets[ast].roles?.includes("data")) {
157
172
  data[ast] = item.assets[ast];
@@ -159,19 +174,25 @@ export class EodashCollection {
159
174
  return data;
160
175
  }, /** @type {Record<string,import('stac-ts').StacAsset>} */ ({}));
161
176
  const isSupported =
162
- item.links.some((link) => ["wms", "xyz"].includes(link.rel)) ||
177
+ item.links.some((link) => ["wms", "xyz", "wmts"].includes(link.rel)) ||
163
178
  Object.keys(dataAssets).length;
164
179
 
165
180
  if (isSupported) {
181
+ const links = await createLayersFromLinks(
182
+ createLayerID(this.#collectionStac?.id ?? "", item.id, false),
183
+ title,
184
+ item,
185
+ layerDatetime,
186
+ );
166
187
  jsonArray.push(
167
- ...createLayersFromLinks(item.id, title, item),
168
-
188
+ ...links,
169
189
  ...(await createLayersFromDataAssets(
170
- `${item.collection}_${item.id}_assets`,
190
+ createLayerID(this.#collectionStac?.id ?? "", item.id, true),
171
191
  title || this.#collectionStac?.title || item.id,
172
192
  dataAssets,
173
193
  style,
174
194
  layerConfig,
195
+ layerDatetime,
175
196
  )),
176
197
  );
177
198
  } else {
@@ -182,19 +203,33 @@ export class EodashCollection {
182
203
  displayFootprint: false,
183
204
  data: item,
184
205
  properties: {
185
- id: item.id,
206
+ id: createLayerID(this.#collectionStac?.id ?? "", item.id, false),
186
207
  title: title || item.id,
187
208
  layerConfig,
188
209
  },
189
210
  style,
190
211
  };
191
- extractRoles(json.properties, /** @type {string[]} */ (item?.roles));
212
+ extractRoles(
213
+ json.properties,
214
+ /** @type {string[]} */ (item?.roles),
215
+ item.id || /** @type {string} */ (item.title) || "" + " STAC",
216
+ );
192
217
  jsonArray.push(json);
193
218
  }
194
219
 
195
220
  return jsonArray;
196
221
  }
197
222
 
223
+ async fetchCollection() {
224
+ if (!this.#collectionStac) {
225
+ const col = await axios
226
+ .get(this.#collectionUrl)
227
+ .then((resp) => resp.data);
228
+ this.#collectionStac = new Collection(col);
229
+ }
230
+ return this.#collectionStac;
231
+ }
232
+
198
233
  getItems() {
199
234
  return (
200
235
  this.#collectionStac?.links
@@ -254,4 +289,44 @@ export class EodashCollection {
254
289
  })[0]
255
290
  : this.getItems()?.at(-1);
256
291
  }
292
+
293
+ /**
294
+ *
295
+ * @param {string} datetime
296
+ * @param {string} layer
297
+ */
298
+ async updateLayerJson(datetime, layer) {
299
+ await this.fetchCollection();
300
+
301
+ // get the link of the specified date
302
+ const specifiedLink = this.getItems()?.find(
303
+ (item) =>
304
+ typeof item.datetime === "string" &&
305
+ new Date(item.datetime).toISOString() === datetime,
306
+ );
307
+
308
+ if (!specifiedLink) {
309
+ console.warn(
310
+ "[eodash] no Item found for the provided datetime",
311
+ datetime,
312
+ );
313
+ return;
314
+ }
315
+
316
+ // create json layers from the item
317
+ const newLayers = await this.createLayersJson(specifiedLink);
318
+
319
+ const curentLayers = getLayers();
320
+
321
+ const oldLayer = findLayer(curentLayers, layer);
322
+
323
+ const updatedLayers = replaceLayer(
324
+ curentLayers,
325
+ /** @type {Record<string,any> & { properties:{ id:string; title:string } } } */
326
+ (oldLayer),
327
+ newLayers,
328
+ );
329
+
330
+ return updatedLayers;
331
+ }
257
332
  }
@@ -60,23 +60,27 @@ export function extractLayerConfig(style) {
60
60
  */
61
61
  export const setMapProjFromCol = (STAcCollection) => {
62
62
  // if a projection exists on the collection level
63
- if (STAcCollection?.["proj:epsg"]) {
63
+
64
+ const projection =
65
+ /** @type {number | string | {name: string, def: string} | undefined} */
66
+ (
67
+ STAcCollection?.["eodash:mapProjection"] ||
68
+ STAcCollection?.["proj:epsg"] ||
69
+ STAcCollection?.["eodash:proj4_def"]
70
+ );
71
+ if (projection) {
72
+ const projectionCode = getProjectionCode(projection);
64
73
  if (
65
74
  availableMapProjection.value &&
66
- availableMapProjection.value !== STAcCollection?.["proj:epsg"]
75
+ availableMapProjection.value !== projectionCode
67
76
  ) {
68
- changeMapProjection(
69
- /** @type {number} */
70
- (STAcCollection["proj:epsg"]),
71
- );
77
+ changeMapProjection(projection);
72
78
  }
73
79
  // set it for `EodashMapBtns`
74
- availableMapProjection.value = /** @type {string} */ (
75
- STAcCollection["proj:epsg"]
76
- );
80
+ availableMapProjection.value = /** @type {string} */ (projectionCode);
77
81
  } else {
78
82
  // reset to default projection
79
- changeMapProjection((availableMapProjection.value = ""));
83
+ changeMapProjection((availableMapProjection.value = "EPSG:3857"));
80
84
  }
81
85
  };
82
86
 
@@ -114,14 +118,17 @@ export function extractCollectionUrls(stacObject, basepath) {
114
118
  * Assign extracted roles to layer properties
115
119
  * @param {Record<string,any>} properties
116
120
  * @param {string[]} roles
121
+ * @param {string} id - unique ID for baselayers and overlays
117
122
  * */
118
- export const extractRoles = (properties, roles) => {
123
+ export const extractRoles = (properties, roles, id) => {
119
124
  roles?.forEach((role) => {
120
125
  if (role === "visible") {
121
126
  properties.visible = true;
122
127
  }
123
128
  if (role === "overlay" || role === "baselayer") {
124
129
  properties.group = role;
130
+ const [colId, itemId, isAsset, _random] = properties.id.split(";:;");
131
+ properties.id = [colId, itemId, isAsset, id].join(";:;");
125
132
  }
126
133
  return properties;
127
134
  });
@@ -146,3 +153,174 @@ export const fetchStyle = async (item, itemUrl) => {
146
153
  return styleJson;
147
154
  }
148
155
  };
156
+
157
+ /**
158
+ * Return projection code which is to be registered in `eox-map`
159
+ * @param {string|number|{name: string, def: string}} [projection]
160
+ * @returns {string}
161
+ */
162
+ export const getProjectionCode = (projection) => {
163
+ let code = projection;
164
+ switch (typeof projection) {
165
+ case "number":
166
+ code = `EPSG:${projection}`;
167
+ break;
168
+ case "string":
169
+ code = projection;
170
+ break;
171
+ case "object":
172
+ code = projection?.name;
173
+ }
174
+ return /** @type {string} */ (code);
175
+ };
176
+
177
+ /**
178
+ * @param {import("stac-ts").StacLink[]} [links]
179
+ * @param {string|null} [current]
180
+ **/
181
+ export const extractLayerDatetime = (links, current) => {
182
+ if (!current || !links?.length) {
183
+ return undefined;
184
+ }
185
+
186
+ // check if links has a datetime value
187
+ const hasDatetime = links.some((l) => typeof l.datetime === "string");
188
+ if (!hasDatetime) {
189
+ return undefined;
190
+ }
191
+
192
+ /** @type {string[]} */
193
+ const values = [];
194
+ try {
195
+ current = new Date(current).toISOString();
196
+
197
+ links.reduce((vals, link) => {
198
+ if (link.datetime && link.rel === "item") {
199
+ vals.push(
200
+ new Date(/** @type {string} */ (link.datetime)).toISOString(),
201
+ );
202
+ }
203
+ return vals;
204
+ }, values);
205
+ } catch (e) {
206
+ console.warn("[eodash] not supported datetime format was provided", e);
207
+ return undefined;
208
+ }
209
+ // not enough values
210
+ if (values.length <= 1) {
211
+ return undefined;
212
+ }
213
+
214
+ // item datetime is not included in the item links datetime
215
+ if (!values.includes(current)) {
216
+ return undefined;
217
+ }
218
+
219
+ return {
220
+ values,
221
+ current,
222
+ slider: false,
223
+ disablePlay: true,
224
+ };
225
+ };
226
+
227
+ /**
228
+ * Find layer by ID
229
+ * @param {string} layer
230
+ * @param {Record<string, any>[]} layers
231
+ * @returns {Record<string,any> | undefined}
232
+ **/
233
+ export const findLayer = (layers, layer) => {
234
+ for (const lyr of layers) {
235
+ if (lyr.type === "Group") {
236
+ const found = findLayer(lyr.layers, layer);
237
+ if (!found) {
238
+ continue;
239
+ }
240
+ return found;
241
+ }
242
+ if (lyr.properties.id === layer) {
243
+ return lyr;
244
+ }
245
+ }
246
+ };
247
+
248
+ /**
249
+ * @param {Record<string,any>[]} currentLayers
250
+ * @param {Record<string,any>} oldLayer
251
+ * @param {Record<string,any>[]} newLayers
252
+ * @returns {Record<string,any>[] | undefined}
253
+ */
254
+ export const replaceLayer = (currentLayers, oldLayer, newLayers) => {
255
+ const oldLayerIdx = currentLayers.findIndex(
256
+ (l) => l.properties.id === oldLayer.properties.id,
257
+ );
258
+ if (oldLayerIdx !== -1) {
259
+ currentLayers.splice(oldLayerIdx, 1, ...newLayers);
260
+ return currentLayers;
261
+ }
262
+
263
+ for (const l of currentLayers) {
264
+ if (l.type === "Group") {
265
+ const updatedGroupLyrs = replaceLayer(l.layers, oldLayer, newLayers);
266
+ if (updatedGroupLyrs?.length) {
267
+ l.layers = updatedGroupLyrs;
268
+ return currentLayers;
269
+ }
270
+ }
271
+ }
272
+ };
273
+ /**
274
+ * @param {import('./eodashSTAC.js').EodashCollection[]} indicators
275
+ * @param {import('ol/layer').Layer} layer
276
+ */
277
+ export const getColFromLayer = async (indicators, layer) => {
278
+ // init cols
279
+ const collections = await Promise.all(
280
+ indicators.map((ind) => ind.fetchCollection()),
281
+ );
282
+ const [collectionId, itemId, _asset, _random] = layer.get("id").split(";:;");
283
+
284
+ const chosen = collections.find((col) => {
285
+ const isInd =
286
+ col.id === collectionId &&
287
+ col.links?.some(
288
+ (link) => link.rel === "item" && link.href.includes(itemId),
289
+ );
290
+ return isInd ?? false;
291
+ });
292
+ return indicators.find((ind) => ind.collectionStac?.id === chosen?.id);
293
+ };
294
+ /**
295
+ *
296
+ * @param {string} colId
297
+ * @param {string} itemId
298
+ * @param {boolean} isAsset
299
+ * @returns
300
+ */
301
+ export const createLayerID = (colId, itemId, isAsset) => {
302
+ return `${colId ?? ""};:;${itemId ?? ""};:;${isAsset ? "_asset" : ""};:;${Math.random().toString(16).slice(2)}`;
303
+ };
304
+
305
+ /**
306
+ * creates a structured clone from the layers and
307
+ * removes all properties from the clone
308
+ * except the ID and title
309
+ *
310
+ * @param {Record<string,any>[]} layers
311
+ */
312
+ export const removeUnneededProperties = (layers) => {
313
+ const cloned = structuredClone(layers);
314
+ cloned.forEach((layer) => {
315
+ const id = layer.properties.id;
316
+ const title = layer.properties.title;
317
+ layer.properties = { id, title };
318
+ if (layer["interactions"]) {
319
+ delete layer["interactions"]
320
+ }
321
+ if (layer.type === "Group") {
322
+ layer.layers = removeUnneededProperties(layer.layers);
323
+ }
324
+ });
325
+ return cloned;
326
+ };