@eodash/eodash 5.6.1 → 5.7.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 (133) hide show
  1. package/core/client/components/DashboardLayout.vue +1 -1
  2. package/core/client/components/EodashOverlay.vue +27 -4
  3. package/core/client/composables/DefineEodash.js +0 -1
  4. package/core/client/composables/DefineWidgets.js +3 -1
  5. package/core/client/composables/index.js +6 -2
  6. package/core/client/eodashSTAC/EodashCollection.js +79 -45
  7. package/core/client/eodashSTAC/cql.js +64 -0
  8. package/core/client/eodashSTAC/createLayers.js +192 -125
  9. package/core/client/eodashSTAC/helpers.js +423 -97
  10. package/core/client/eodashSTAC/mosaic.js +416 -0
  11. package/core/client/plugins/axios.js +31 -1
  12. package/core/client/store/actions.js +1 -1
  13. package/core/client/store/stac.js +25 -4
  14. package/core/client/store/states.js +20 -2
  15. package/core/client/types.ts +155 -29
  16. package/core/client/utils/bands-editor/exampleSchema.json +50 -50
  17. package/core/client/utils/index.js +4 -0
  18. package/core/client/utils/states.js +10 -0
  19. package/dist/client/{DashboardLayout-CqMb7OXc.js → DashboardLayout-ePbdvUTE.js} +5 -5
  20. package/dist/client/{DynamicWebComponent-DqKqTf7l.js → DynamicWebComponent-g5SdRbjY.js} +1 -1
  21. package/dist/client/{EodashChart-PkUQfH0k.js → EodashChart-ChrkA5oS.js} +7 -6
  22. package/dist/client/{EodashDatePicker-DLJGdTtX.js → EodashDatePicker-CY1TrsDo.js} +3 -3
  23. package/dist/client/{EodashItemFilter-Dk8KjFcX.js → EodashItemFilter-DzshHDlS.js} +2 -1
  24. package/dist/client/{EodashLayerControl-CC1Cogrn.js → EodashLayerControl-DMCeMkSd.js} +70 -22
  25. package/dist/client/{EodashLayoutSwitcher-5WZYd6rr.js → EodashLayoutSwitcher-iJ8mX1rF.js} +3 -3
  26. package/dist/client/EodashMapBtns-C7Cr7q5Y.js +592 -0
  27. package/dist/client/EodashStacInfo-K7-iuXa7.js +169 -0
  28. package/dist/client/{EodashTools-CGZtTh45.js → EodashTools-BEK7e7JM.js} +4 -4
  29. package/dist/client/{ExportState-Ce0ZnrX_.js → ExportState-CqIzfMYQ.js} +6 -168
  30. package/dist/client/{Footer-CnZqEiop.js → Footer-1P0cmBOZ.js} +1 -1
  31. package/dist/client/{Header-Dr5PBIm8.js → Header-CkkBaBNh.js} +2 -2
  32. package/dist/client/MobileLayout-BPf49kDU.js +118 -0
  33. package/dist/client/{PopUp-DjvE_71e.js → PopUp-DPZq5SWI.js} +4 -168
  34. package/dist/client/{ProcessList-kf3olI7W.js → ProcessList-DuI6WpS1.js} +5 -5
  35. package/dist/client/VDivider-Bj9LG_JV.js +168 -0
  36. package/dist/client/{VImg-Bj6uWt6j.js → VImg-Ddv5OyMz.js} +2 -2
  37. package/dist/client/{VMain-Cm0UmKGi.js → VMain-7yqk_qC3.js} +1 -1
  38. package/dist/client/{VTooltip-DbBu-ky3.js → VTooltip-2hAJyEoa.js} +2 -2
  39. package/dist/client/{WidgetsContainer-CfLnd44U.js → WidgetsContainer-2DOrlwCB.js} +1 -1
  40. package/dist/client/{asWebComponent-DfULAbpq.js → asWebComponent-BlFN2lkB.js} +493 -335
  41. package/dist/client/{async-CIbKXEEe.js → async-B2H8ZwUK.js} +21 -10
  42. package/dist/client/create-layers-config-u_vn5hPk.js +182 -0
  43. package/dist/client/dialog-transition-BrMkMiNa.js +170 -0
  44. package/dist/client/eo-dash.js +1 -1
  45. package/dist/client/{forwardRefs-yj3VWOK5.js → forwardRefs-DAlror6d.js} +8 -87
  46. package/dist/client/{handling-s8xt2JwF.js → handling-B6I1V5eG.js} +123 -85
  47. package/dist/client/{helpers-DAVGYl_f.js → helpers-CBqIUSXJ.js} +3034 -1649
  48. package/dist/client/index-BWq1ZKaV.js +3168 -0
  49. package/dist/client/{index-CYz6dT7K.js → index-CJ9UI3ln.js} +2 -2
  50. package/dist/client/index-DXLz4sFR.js +442 -0
  51. package/dist/client/{index-4TrjfJ32.js → index-DhKU6KqM.js} +230 -231
  52. package/dist/client/{index-Bu8BMA9q.js → index-DjQlbWbJ.js} +70 -83
  53. package/dist/client/material-symbols-outlined.woff2 +0 -0
  54. package/dist/client/material-symbols-rounded.woff2 +0 -0
  55. package/dist/client/material-symbols-sharp.woff2 +0 -0
  56. package/dist/client/material-symbols-subset.woff2 +0 -0
  57. package/dist/client/mosaic-BFYLEwyx.js +455 -0
  58. package/dist/client/templates.js +250 -119
  59. package/dist/client/{transition-DaOsiD4u.js → transition-D_W6Wn9v.js} +1 -1
  60. package/dist/node/cli.js +5 -5
  61. package/dist/node/types.d.ts +4 -0
  62. package/dist/types/core/client/composables/DefineEodash.d.ts +1 -1
  63. package/dist/types/core/client/composables/index.d.ts +1 -3
  64. package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +62 -31
  65. package/dist/types/core/client/eodashSTAC/cql.d.ts +15 -0
  66. package/dist/types/core/client/eodashSTAC/createLayers.d.ts +44 -25
  67. package/dist/types/core/client/eodashSTAC/helpers.d.ts +78 -18
  68. package/dist/types/core/client/eodashSTAC/mosaic.d.ts +56 -0
  69. package/dist/types/core/client/store/stac.d.ts +31 -7
  70. package/dist/types/core/client/store/states.d.ts +24 -2
  71. package/dist/types/core/client/types.d.ts +131 -25
  72. package/dist/types/core/client/utils/states.d.ts +12 -0
  73. package/dist/types/templates/baseConfig.d.ts +1 -88
  74. package/dist/types/templates/compare.d.ts +32 -3
  75. package/dist/types/templates/expert.d.ts +18 -0
  76. package/dist/types/templates/explore.d.ts +9 -1
  77. package/dist/types/templates/lite.d.ts +11 -0
  78. package/dist/types/widgets/EodashChart.vue.d.ts +5 -3
  79. package/dist/types/widgets/EodashItemCatalog/index.vue.d.ts +129 -2
  80. package/dist/types/widgets/EodashItemCatalog/methods/filters.d.ts +28 -6
  81. package/dist/types/widgets/EodashItemCatalog/methods/handlers.d.ts +17 -4
  82. package/dist/types/widgets/EodashItemCatalog/methods/map.d.ts +16 -4
  83. package/dist/types/widgets/EodashLayerControl.vue.d.ts +36 -17
  84. package/dist/types/widgets/EodashMap/EodashMapBtns.vue.d.ts +23 -10
  85. package/dist/types/widgets/EodashMap/index.vue.d.ts +91 -35
  86. package/dist/types/widgets/EodashMap/methods/create-layers-config.d.ts +1 -8
  87. package/dist/types/widgets/EodashMap/methods/index.d.ts +5 -1
  88. package/dist/types/widgets/EodashMap/methods/use-map-loading.d.ts +1 -0
  89. package/dist/types/widgets/EodashProcess/index.vue.d.ts +5 -3
  90. package/dist/types/widgets/EodashProcess/methods/composables.d.ts +1 -1
  91. package/dist/types/widgets/EodashProcess/methods/handling.d.ts +13 -8
  92. package/dist/types/widgets/EodashProcess/states.d.ts +1 -1
  93. package/dist/types/widgets/EodashStacInfo.vue.d.ts +20 -0
  94. package/dist/types/widgets/EodashTimeSlider/index.vue.d.ts +54 -0
  95. package/dist/types/widgets/EodashTimeSlider/methods/index.d.ts +34 -0
  96. package/dist/types/widgets/EodashTimeSlider/types.d.ts +52 -0
  97. package/dist/types/widgets/EodashTools.vue.d.ts +5 -5
  98. package/package.json +46 -46
  99. package/templates/baseConfig.js +36 -6
  100. package/templates/compare.js +62 -7
  101. package/templates/expert.js +23 -0
  102. package/templates/explore.js +11 -5
  103. package/templates/lite.js +14 -0
  104. package/widgets/EodashChart.vue +1 -0
  105. package/widgets/EodashItemCatalog/index.vue +363 -35
  106. package/widgets/EodashItemCatalog/methods/filters.js +134 -70
  107. package/widgets/EodashItemCatalog/methods/handlers.js +113 -19
  108. package/widgets/EodashItemCatalog/methods/map.js +142 -28
  109. package/widgets/EodashLayerControl.vue +64 -14
  110. package/widgets/EodashMap/EodashMapBtns.vue +153 -47
  111. package/widgets/EodashMap/index.vue +101 -105
  112. package/widgets/EodashMap/methods/btns.js +37 -5
  113. package/widgets/EodashMap/methods/create-layers-config.js +18 -16
  114. package/widgets/EodashMap/methods/index.js +89 -8
  115. package/widgets/EodashMap/methods/use-map-loading.js +52 -0
  116. package/widgets/EodashProcess/index.vue +2 -1
  117. package/widgets/EodashProcess/methods/async.js +19 -8
  118. package/widgets/EodashProcess/methods/composables.js +63 -77
  119. package/widgets/EodashProcess/methods/custom-endpoints/chart/sentinelhub-endpoint.js +9 -5
  120. package/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.js +7 -4
  121. package/widgets/EodashProcess/methods/handling.js +105 -72
  122. package/widgets/EodashProcess/states.js +1 -1
  123. package/widgets/EodashStacInfo.vue +64 -2
  124. package/widgets/EodashTimeSlider/index.vue +208 -0
  125. package/widgets/EodashTimeSlider/methods/index.js +236 -0
  126. package/widgets/EodashTimeSlider/types.ts +54 -0
  127. package/dist/client/EodashMapBtns-BHrSDNoC.js +0 -435
  128. package/dist/client/EodashStacInfo-B90wobPc.js +0 -107
  129. package/dist/client/EodashTimeSlider-5vm7F3ju.js +0 -53
  130. package/dist/client/MobileLayout-DyMjaeif.js +0 -118
  131. package/dist/client/index-CugS__t5.js +0 -570
  132. package/dist/types/widgets/EodashTimeSlider.vue.d.ts +0 -15
  133. package/widgets/EodashTimeSlider.vue +0 -40
@@ -12,6 +12,10 @@ import {
12
12
  extractEoxLegendLink,
13
13
  addTooltipInteraction,
14
14
  fetchStyle,
15
+ resolveStyle,
16
+ getBandsProperty,
17
+ applyTitilerUpscaling,
18
+ encodeURLObject,
15
19
  } from "./helpers";
16
20
  import { handleAuthenticationOfLink } from "./auth";
17
21
  import log from "loglevel";
@@ -41,6 +45,7 @@ function buildCapabilitiesUrl(href) {
41
45
  * @param {import("stac-ts").StacItem | import("stac-ts").StacCollection } stacObject
42
46
  * @param {Record<string, unknown>} [layerDatetime]
43
47
  * @param {object | null} [extraProperties]
48
+ * @param {import("stac-ts").StacCollection | null} [collection] - Used to fall back to a collection-level style link.
44
49
  **/
45
50
  export async function createLayersFromAssets(
46
51
  collectionId,
@@ -49,6 +54,7 @@ export async function createLayersFromAssets(
49
54
  stacObject,
50
55
  layerDatetime,
51
56
  extraProperties,
57
+ collection,
52
58
  ) {
53
59
  log.debug("Creating layers from assets");
54
60
  const jsonArray = [];
@@ -60,24 +66,43 @@ export async function createLayersFromAssets(
60
66
 
61
67
  const fgbIdx = [];
62
68
  const fgbSources = [];
69
+ const zarrAssetIds = [];
70
+ const zarrIdx = [];
63
71
  const assetIds = [];
64
72
 
65
73
  for (const [idx, assetId] of Object.keys(assets).entries()) {
66
74
  assetIds.push(assetId);
67
75
 
68
- if (assets[assetId]?.type === "application/geo+json") {
76
+ if (
77
+ assets[assetId]?.type?.includes("application/geo+json") &&
78
+ assets[assetId]?.href?.includes("http")
79
+ ) {
69
80
  geoJsonSources.push(assets[assetId].href);
70
81
  geoJsonIdx.push(idx);
71
- } else if (assets[assetId]?.type === "application/vnd.flatgeobuf") {
82
+ } else if (
83
+ assets[assetId]?.type?.includes("application/vnd.flatgeobuf") &&
84
+ assets[assetId]?.href?.includes("http")
85
+ ) {
72
86
  fgbSources.push(assets[assetId].href);
73
87
  fgbIdx.push(idx);
74
- } else if (assets[assetId]?.type === "image/tiff") {
88
+ } else if (
89
+ assets[assetId]?.type ==
90
+ "application/vnd.zarr; version=3; profile=multiscales"
91
+ ) {
92
+ zarrAssetIds.push(assetId);
93
+ zarrIdx.push(idx);
94
+ } else if (
95
+ assets[assetId]?.type?.includes("image/tiff") &&
96
+ assets[assetId]?.href?.includes("http")
97
+ ) {
75
98
  geoTIFFIdx.push(idx);
76
99
  geoTIFFSources.push({
77
100
  url: assets[assetId].href,
78
- attributions: assets[assetId].attribution,
101
+ ...(assets[assetId].attribution
102
+ ? { attributions: assets[assetId].attribution }
103
+ : {}),
79
104
  });
80
- } else if (assets[assetId]?.type === "application/geodb+json") {
105
+ } else if (assets[assetId]?.type?.includes("application/geodb+json")) {
81
106
  const responseData = await (await fetch(assets[assetId].href)).json();
82
107
  geoJsonIdx.push(idx);
83
108
  if (
@@ -138,11 +163,122 @@ export async function createLayersFromAssets(
138
163
  }
139
164
  }
140
165
 
166
+ if (geoTIFFSources.length) {
167
+ for (const [i, geotiffSource] of geoTIFFSources.entries()) {
168
+ const assetName = assetIds[geoTIFFIdx[i]];
169
+ const styles = await resolveStyle(
170
+ stacObject,
171
+ collection,
172
+ undefined,
173
+ assetName,
174
+ );
175
+ // get the correct style which is not attached to a link
176
+ let { layerConfig, style } = extractLayerConfig(collectionId, styles);
177
+ let assetLayerId = createAssetID(
178
+ collectionId,
179
+ stacObject.id,
180
+ geoTIFFIdx[i],
181
+ );
182
+ if (
183
+ assets[assetName]?.roles?.includes("overlay") ||
184
+ assets[assetName]?.roles?.includes("baselayer")
185
+ ) {
186
+ // to prevent them being removed by date change on main dataset
187
+ assetLayerId = assetName;
188
+ }
189
+ log.debug("Creating WebGLTile layer from GeoTIFF", assetLayerId);
190
+ log.debug("Configured Sources", geoTIFFSources);
191
+ const sources =
192
+ stacObject?.["eodash:merge_assets"] !== false
193
+ ? geoTIFFSources
194
+ : [geotiffSource];
195
+ const layer = {
196
+ type: "WebGLTile",
197
+ source: {
198
+ type: "GeoTIFF",
199
+ normalize: !style,
200
+ interpolate: false,
201
+ sources,
202
+ },
203
+ properties: {
204
+ id: assetLayerId,
205
+ title: assets[assetName]?.title || title,
206
+ layerConfig,
207
+ layerDatetime,
208
+ },
209
+ style,
210
+ };
211
+ if (extraProperties) {
212
+ layer.properties = { ...layer.properties, ...extraProperties };
213
+ }
214
+ extractRoles(layer.properties, assets[assetName]);
215
+ addTooltipInteraction(layer, style);
216
+ jsonArray.push(layer);
217
+ if (stacObject?.["eodash:merge_assets"] !== false) break;
218
+ }
219
+ }
220
+
221
+ if (zarrAssetIds.length) {
222
+ for (const [i, assetName] of zarrAssetIds.entries()) {
223
+ const fetchedStyle = await resolveStyle(
224
+ stacObject,
225
+ collection,
226
+ undefined,
227
+ assetName,
228
+ );
229
+ const { layerConfig, style } = extractLayerConfig(
230
+ collectionId,
231
+ fetchedStyle,
232
+ );
233
+ const bandsPath = getBandsProperty(layerConfig?.schema);
234
+ const defaultBands = bandsPath?.reduce(
235
+ (node, key) => node?.[key],
236
+ layerConfig?.schema,
237
+ )?.default ?? ["b04", "b03", "b02"];
238
+
239
+ let assetLayerId = createAssetID(collectionId, stacObject.id, zarrIdx[i]);
240
+ if (
241
+ assets[assetName]?.roles?.includes("overlay") ||
242
+ assets[assetName]?.roles?.includes("baselayer")
243
+ ) {
244
+ assetLayerId = assetName;
245
+ }
246
+
247
+ log.debug("Creating WebGLTile layer from GeoZarr", assetLayerId);
248
+
249
+ const layer = {
250
+ type: "WebGLTile",
251
+ properties: {
252
+ id: assetLayerId,
253
+ title: assets[assetName]?.title || title,
254
+ layerConfig,
255
+ layerDatetime,
256
+ },
257
+ source: {
258
+ type: "GeoZarr",
259
+ url: assets[assetName].href,
260
+ bands: defaultBands,
261
+ },
262
+ ...(style ? { style } : {}),
263
+ };
264
+ if (extraProperties) {
265
+ layer.properties = { ...layer.properties, ...extraProperties };
266
+ }
267
+ extractRoles(layer.properties, assets[assetName]);
268
+ jsonArray.push(layer);
269
+ }
270
+ }
271
+
141
272
  if (geoJsonSources.length) {
142
273
  for (const [i, geoJsonSource] of geoJsonSources.entries()) {
143
274
  // fetch styles and separate them by their mapping between links and assets
144
275
  const assetName = assetIds[geoJsonIdx[i]];
145
- const styles = await fetchStyle(stacObject, undefined, assetName);
276
+ const styles = await resolveStyle(
277
+ stacObject,
278
+ collection,
279
+ undefined,
280
+ assetName,
281
+ );
146
282
  // get the correct style which is not attached to a link
147
283
  let { layerConfig, style } = extractLayerConfig(collectionId, styles);
148
284
  let assetLayerId = createAssetID(
@@ -178,7 +314,9 @@ export async function createLayersFromAssets(
178
314
  type: "Vector",
179
315
  url: geoJSONURL,
180
316
  format: { type: "GeoJSON", dataProjection: projection },
181
- attributions: assets[assetName].attribution,
317
+ ...(assets[assetName].attribution
318
+ ? { attributions: assets[assetName].attribution }
319
+ : {}),
182
320
  },
183
321
  properties: {
184
322
  id: assetLayerId,
@@ -206,7 +344,12 @@ export async function createLayersFromAssets(
206
344
  for (const [i, fgbSource] of fgbSources.entries()) {
207
345
  // fetch styles and separate them by their mapping between links and assets
208
346
  const assetName = assetIds[fgbIdx[i]];
209
- const styles = await fetchStyle(stacObject, undefined, assetName);
347
+ const styles = await resolveStyle(
348
+ stacObject,
349
+ collection,
350
+ undefined,
351
+ assetName,
352
+ );
210
353
  // get the correct style which is not attached to a link
211
354
  let { layerConfig, style } = extractLayerConfig(collectionId, styles);
212
355
  let assetLayerId = createAssetID(collectionId, stacObject.id, fgbIdx[i]);
@@ -239,7 +382,9 @@ export async function createLayersFromAssets(
239
382
  ...urlsObject,
240
383
  type: "FlatGeoBuf",
241
384
  projection,
242
- attributions: assets[assetName].attribution,
385
+ ...(assets[assetName].attribution
386
+ ? { attributions: assets[assetName].attribution }
387
+ : {}),
243
388
  },
244
389
  properties: {
245
390
  id: assetLayerId,
@@ -264,56 +409,6 @@ export async function createLayersFromAssets(
264
409
  }
265
410
  }
266
411
 
267
- if (geoTIFFSources.length) {
268
- for (const [i, geotiffSource] of geoTIFFSources.entries()) {
269
- const assetName = assetIds[geoTIFFIdx[i]];
270
- const styles = await fetchStyle(stacObject, undefined, assetName);
271
- // get the correct style which is not attached to a link
272
- let { layerConfig, style } = extractLayerConfig(collectionId, styles);
273
- let assetLayerId = createAssetID(
274
- collectionId,
275
- stacObject.id,
276
- geoTIFFIdx[i],
277
- );
278
- if (
279
- assets[assetName]?.roles?.includes("overlay") ||
280
- assets[assetName]?.roles?.includes("baselayer")
281
- ) {
282
- // to prevent them being removed by date change on main dataset
283
- assetLayerId = assetName;
284
- }
285
- log.debug("Creating WebGLTile layer from GeoTIFF", assetLayerId);
286
- log.debug("Configured Sources", geoTIFFSources);
287
- const sources =
288
- stacObject?.["eodash:merge_assets"] !== false
289
- ? geoTIFFSources
290
- : [geotiffSource];
291
- const layer = {
292
- type: "WebGLTile",
293
- source: {
294
- type: "GeoTIFF",
295
- normalize: !style,
296
- interpolate: false,
297
- sources,
298
- },
299
- properties: {
300
- id: assetLayerId,
301
- title: assets[assetName]?.title || title,
302
- layerConfig,
303
- layerDatetime,
304
- },
305
- style,
306
- };
307
- if (extraProperties) {
308
- layer.properties = { ...layer.properties, ...extraProperties };
309
- }
310
- extractRoles(layer.properties, assets[assetName]);
311
- addTooltipInteraction(layer, style);
312
- jsonArray.push(layer);
313
- if (stacObject?.["eodash:merge_assets"] !== false) break;
314
- }
315
- }
316
-
317
412
  return jsonArray;
318
413
  }
319
414
 
@@ -385,7 +480,7 @@ export const createLayersFromLinks = async (
385
480
  tileGrid: {
386
481
  tileSize,
387
482
  },
388
- attributions: wmsLink.attribution,
483
+ ...(wmsLink.attribution ? { attributions: wmsLink.attribution } : {}),
389
484
  params: {
390
485
  LAYERS: wmsLink["wms:layers"],
391
486
  TILED: true,
@@ -435,7 +530,7 @@ export const createLayersFromLinks = async (
435
530
  const key =
436
531
  /** @type {string | undefined} */ (wmtsLink["key"]) || undefined;
437
532
 
438
- const styles = await fetchStyle(item, key);
533
+ const styles = await resolveStyle(item, collection, key);
439
534
  // get the correct style which is attached to a link
440
535
  const returnedLayerConfig = extractLayerConfig(
441
536
  collectionId,
@@ -496,7 +591,9 @@ export const createLayersFromLinks = async (
496
591
  tileGrid: {
497
592
  tileSize: [128, 128],
498
593
  },
499
- attributions: wmtsLink.attribution,
594
+ ...(wmtsLink.attribution
595
+ ? { attributions: wmtsLink.attribution }
596
+ : {}),
500
597
  dimensions: dimensionsWithoutStyle,
501
598
  },
502
599
  };
@@ -516,7 +613,9 @@ export const createLayersFromLinks = async (
516
613
  layer: wmtsLink["wmts:layer"],
517
614
  style: extractedStyle,
518
615
  ...(matrixSet ? { matrixSet } : {}),
519
- attributions: wmtsLink.attribution,
616
+ ...(wmtsLink.attribution
617
+ ? { attributions: wmtsLink.attribution }
618
+ : {}),
520
619
  dimensions: dimensionsWithoutStyle,
521
620
  },
522
621
  };
@@ -544,7 +643,7 @@ export const createLayersFromLinks = async (
544
643
  const rasterForm = rasterformURL
545
644
  ? await axios.get(rasterformURL).then((resp) => resp.data)
546
645
  : undefined;
547
- const styles = await fetchStyle(item, key);
646
+ const styles = await resolveStyle(item, collection, key);
548
647
  // get the correct style which is attached to a link
549
648
  let { layerConfig, style } = extractLayerConfig(
550
649
  collectionId,
@@ -561,7 +660,6 @@ export const createLayersFromLinks = async (
561
660
  viewProjectionCode,
562
661
  );
563
662
  let xyzUrl = xyzLink.href;
564
-
565
663
  // TODO, this does not yet work between layer time changes because we do not get
566
664
  // updated variables from OL layer due to usage of tileurlfunction
567
665
 
@@ -575,11 +673,14 @@ export const createLayersFromLinks = async (
575
673
  }
576
674
  xyzUrl = `${base}?${params.toString()}`;
577
675
  }
578
-
579
676
  const { supportedUpscalingEndpoints } = useSTAcStore();
580
- const isUpscalingSupported = supportedUpscalingEndpoints.some(
581
- (/** @type {string} */ endpoint) => xyzUrl.includes(endpoint),
677
+ const upscaling = applyTitilerUpscaling(
678
+ xyzUrl,
679
+ supportedUpscalingEndpoints,
582
680
  );
681
+ if (upscaling) {
682
+ xyzUrl = upscaling.url;
683
+ }
583
684
 
584
685
  // Add sharding for s2maps automatically
585
686
  if (xyzUrl.includes("s2maps-tiles.eu")) {
@@ -598,15 +699,15 @@ export const createLayersFromLinks = async (
598
699
  },
599
700
  source: {
600
701
  type: "XYZ",
601
- url: isUpscalingSupported ? xyzUrl.replace("{y}", "{y}@2x") : xyzUrl,
702
+ url: xyzUrl,
602
703
  projection: projectionCode,
603
- attributions: xyzLink.attribution,
704
+ ...(xyzLink.attribution ? { attributions: xyzLink.attribution } : {}),
604
705
  },
605
706
  };
606
- if (isUpscalingSupported) {
707
+ if (upscaling) {
607
708
  // @ts-expect-error tileGrid is added here and supported in eox-map layer definition
608
709
  json.source.tileGrid = {
609
- tileSize: [512, 512],
710
+ tileSize: upscaling.tileSize,
610
711
  };
611
712
  }
612
713
  if (
@@ -649,7 +750,7 @@ export const createLayersFromLinks = async (
649
750
  const key =
650
751
  /** @type {string | undefined} */ (vectorTileLink["key"]) || undefined;
651
752
  // fetch styles and separate them by their mapping between links and assets
652
- const styles = await fetchStyle(item, key);
753
+ const styles = await resolveStyle(item, collection, key);
653
754
  // get the correct style which is not attached to a link
654
755
  let { layerConfig, style } = extractLayerConfig(collectionId, styles);
655
756
 
@@ -686,7 +787,9 @@ export const createLayersFromLinks = async (
686
787
  },
687
788
  url: href,
688
789
  projection: projectionCode,
689
- attributions: vectorTileLink.attribution,
790
+ ...(vectorTileLink.attribution
791
+ ? { attributions: vectorTileLink.attribution }
792
+ : {}),
690
793
  },
691
794
  interactions: [],
692
795
  ...(!style?.variables && { style }),
@@ -733,7 +836,7 @@ export const createLayersFromLinks = async (
733
836
  ),
734
837
  applyOptions,
735
838
  );
736
- applyOptions = /** @type { object } */ (optionsObject);
839
+ applyOptions = /** @type {object} */ (optionsObject);
737
840
  href = url;
738
841
  }
739
842
  const json = {
@@ -745,7 +848,9 @@ export const createLayersFromLinks = async (
745
848
  layerDatetime,
746
849
  mapboxStyle: href,
747
850
  projection: projectionCode,
748
- attributions: mapboxStyleDocumentLink.attribution,
851
+ ...(mapboxStyleDocumentLink.attribution
852
+ ? { attributions: mapboxStyleDocumentLink.attribution }
853
+ : {}),
749
854
  applyOptions,
750
855
  },
751
856
  interactions: [],
@@ -781,6 +886,17 @@ export const createLayerFromRender = async (
781
886
  return [];
782
887
  }
783
888
 
889
+ // Skip when an explicit xyz link already targets the collection on the same endpoint
890
+ const hasMatchingXyzLink = item.links?.some(
891
+ (link) =>
892
+ link.rel === "xyz" &&
893
+ link.href?.includes(rasterURL) &&
894
+ link.href?.includes(`/collections/${collection.id}/`),
895
+ );
896
+ if (hasMatchingXyzLink) {
897
+ return [];
898
+ }
899
+
784
900
  const rasterformURL = /** @type {string|undefined} */ (
785
901
  collection?.["eodash:rasterform"]
786
902
  );
@@ -859,52 +975,3 @@ export const createLayerFromRender = async (
859
975
 
860
976
  return layers;
861
977
  };
862
- /**
863
- *
864
- * @param {Record<string,any>} obj
865
- * @returns {string}
866
- */
867
- function encodeURLObject(obj) {
868
- let str = "";
869
- for (const key in obj) {
870
- const value = obj[key];
871
- if (value === null || value === undefined || value === "") {
872
- continue;
873
- }
874
-
875
- const valueType = Array.isArray(value) ? "array" : typeof value;
876
-
877
- switch (valueType) {
878
- case "array": {
879
- // Check if any element in the array is itself an array (multi-dimensional)
880
- const hasNestedArrays = value.some((/** @type {any} */ item) =>
881
- Array.isArray(item),
882
- );
883
-
884
- if (hasNestedArrays) {
885
- // For multi-dimensional arrays, repeat the key with different values
886
- for (const val of value) {
887
- if (Array.isArray(val)) {
888
- str += `${key}=${val.join(",")}&`;
889
- } else {
890
- str += `${key}=${val}&`;
891
- }
892
- }
893
- } else {
894
- // For simple arrays, join with commas
895
- str += `${key}=${value.join(",")}&`;
896
- }
897
- break;
898
- }
899
- case "object": {
900
- str += `${key}=${encodeURI(JSON.stringify(value))}&`;
901
- break;
902
- }
903
- default: {
904
- str += `${key}=${encodeURIComponent(value)}&`;
905
- break;
906
- }
907
- }
908
- }
909
- return str;
910
- }