@eodash/eodash 5.7.1 → 5.8.0

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 (66) hide show
  1. package/core/client/eodashSTAC/EodashCollection.js +14 -5
  2. package/core/client/eodashSTAC/createLayers.js +193 -80
  3. package/core/client/eodashSTAC/helpers.js +330 -39
  4. package/core/client/eodashSTAC/mosaic.js +10 -4
  5. package/core/client/store/stac.js +29 -0
  6. package/core/client/types.ts +5 -0
  7. package/dist/client/{DashboardLayout-ePbdvUTE.js → DashboardLayout-DEs4f_Vy.js} +2 -2
  8. package/dist/client/{DynamicWebComponent-g5SdRbjY.js → DynamicWebComponent-PvnV88BA.js} +1 -1
  9. package/dist/client/EodashChart-D-3AGKZY.js +260 -0
  10. package/dist/client/{EodashDatePicker-CY1TrsDo.js → EodashDatePicker-Dm_goZzs.js} +3 -3
  11. package/dist/client/{EodashItemFilter-DzshHDlS.js → EodashItemFilter-CJy3zYzD.js} +2 -2
  12. package/dist/client/{EodashLayerControl-DMCeMkSd.js → EodashLayerControl-rL8UnpkA.js} +11 -19
  13. package/dist/client/{EodashLayoutSwitcher-iJ8mX1rF.js → EodashLayoutSwitcher-ZRlESI9O.js} +3 -3
  14. package/dist/client/{EodashMapBtns-C7Cr7q5Y.js → EodashMapBtns-CG7u2Aq8.js} +34 -33
  15. package/dist/client/{EodashStacInfo-K7-iuXa7.js → EodashStacInfo-CJhhxthD.js} +2 -2
  16. package/dist/client/{EodashTools-BEK7e7JM.js → EodashTools-CWyK8QJT.js} +4 -4
  17. package/dist/client/{ExportState-CqIzfMYQ.js → ExportState-BXhy5TOU.js} +19 -11
  18. package/dist/client/{Footer-1P0cmBOZ.js → Footer-DZPvnhcT.js} +1 -1
  19. package/dist/client/{Header-CkkBaBNh.js → Header-CiGsDE_a.js} +2 -2
  20. package/dist/client/{MobileLayout-BPf49kDU.js → MobileLayout-BJHW7x5V.js} +2 -2
  21. package/dist/client/{PopUp-DPZq5SWI.js → PopUp-7_XnhvCc.js} +3 -3
  22. package/dist/client/{ProcessList-DuI6WpS1.js → ProcessList-LL_UCbvc.js} +4 -4
  23. package/dist/client/{VDivider-Bj9LG_JV.js → VDivider-DWYM0WUr.js} +2 -2
  24. package/dist/client/{VImg-Ddv5OyMz.js → VImg-B75dgw2K.js} +2 -2
  25. package/dist/client/{VMain-7yqk_qC3.js → VMain-DvMmOL4f.js} +1 -1
  26. package/dist/client/{VTooltip-2hAJyEoa.js → VTooltip-ClWHUmWL.js} +2 -2
  27. package/dist/client/{WidgetsContainer-2DOrlwCB.js → WidgetsContainer-BqaWs4ch.js} +1 -1
  28. package/dist/client/{asWebComponent-BlFN2lkB.js → asWebComponent-IZanwL-A.js} +239 -91
  29. package/dist/client/{async-B2H8ZwUK.js → async-CiNIOBVz.js} +31 -29
  30. package/dist/client/{create-layers-config-u_vn5hPk.js → create-layers-config-3S3y_kZg.js} +1 -1
  31. package/dist/client/{dialog-transition-BrMkMiNa.js → dialog-transition-c4ZSnzac.js} +2 -2
  32. package/dist/client/eo-dash.js +1 -1
  33. package/dist/client/{forwardRefs-DAlror6d.js → forwardRefs-B-c1_6yo.js} +2 -2
  34. package/dist/client/{handling-B6I1V5eG.js → handling-NvY8Csry.js} +3 -4
  35. package/dist/client/{helpers-CBqIUSXJ.js → helpers-BFuh19CP.js} +328 -40
  36. package/dist/client/{index-DhKU6KqM.js → index-1wMAyuNL.js} +17 -9
  37. package/dist/client/{index-DXLz4sFR.js → index-B8jGJSTA.js} +4 -4
  38. package/dist/client/{index-DjQlbWbJ.js → index-BKQQJkhy.js} +166 -61
  39. package/dist/client/{index-BWq1ZKaV.js → index-D0jUyol8.js} +10 -11
  40. package/dist/client/{index-CJ9UI3ln.js → index-KGxz5Egv.js} +2 -2
  41. package/dist/client/{mosaic-BFYLEwyx.js → mosaic-vHvSuih6.js} +10 -6
  42. package/dist/client/templates.js +6 -7
  43. package/dist/client/{transition-D_W6Wn9v.js → transition-BkyUsZh_.js} +1 -1
  44. package/dist/types/core/client/eodashSTAC/helpers.d.ts +47 -7
  45. package/dist/types/core/client/store/stac.d.ts +8 -2
  46. package/dist/types/core/client/types.d.ts +5 -0
  47. package/dist/types/templates/explore.d.ts +1 -0
  48. package/dist/types/widgets/EodashProcess/methods/custom-endpoints/layers/eoxhub-workspaces-endpoint.d.ts +1 -1
  49. package/package.json +5 -5
  50. package/templates/baseConfig.js +2 -1
  51. package/templates/compare.js +0 -1
  52. package/templates/expert.js +2 -3
  53. package/templates/explore.js +1 -0
  54. package/templates/lite.js +0 -1
  55. package/widgets/EodashChart.vue +161 -21
  56. package/widgets/EodashItemCatalog/methods/map.js +0 -1
  57. package/widgets/EodashLayerControl.vue +10 -15
  58. package/widgets/EodashMap/index.vue +3 -1
  59. package/widgets/EodashMap/methods/btns.js +27 -26
  60. package/widgets/EodashMap/methods/use-map-loading.js +8 -2
  61. package/widgets/EodashProcess/index.vue +135 -16
  62. package/widgets/EodashProcess/methods/composables.js +13 -0
  63. package/widgets/EodashProcess/methods/outputs.js +0 -1
  64. package/widgets/EodashProcess/methods/utils.js +29 -27
  65. package/widgets/ExportState.vue +13 -4
  66. package/dist/client/EodashChart-ChrkA5oS.js +0 -145
@@ -1,7 +1,7 @@
1
1
  import { ref, watch, nextTick, mergeProps, createVNode, normalizeStyle, normalizeClass, useModel, openBlock, createElementBlock, withCtx, createBlock, resolveDynamicComponent, unref, createCommentVNode, renderSlot, mergeModels } from 'vue';
2
- import { g as genericComponent, z as useProxiedModel, c as useRender, p as propsFactory, C as omit, V as VDefaultsProvider, l as provideTheme, f as useBackgroundColor, h as useBorder, b as useDimension, i as useElevation, j as useLocation, aj as usePosition, k as useRounded, r as makeThemeProps, m as makeTagProps, s as makeRoundedProps, ak as makePositionProps, t as makeLocationProps, v as makeElevationProps, d as makeDimensionProps, e as makeComponentProps, w as makeBorderProps, as as useDefineWidgets } from './asWebComponent-BlFN2lkB.js';
3
- import { u as useScopeId, f as forwardRefs, m as makeVOverlayProps, a as VOverlay } from './forwardRefs-DAlror6d.js';
4
- import { V as VDialogTransition } from './dialog-transition-BrMkMiNa.js';
2
+ import { g as genericComponent, z as useProxiedModel, c as useRender, p as propsFactory, C as omit, V as VDefaultsProvider, l as provideTheme, f as useBackgroundColor, h as useBorder, b as useDimension, i as useElevation, j as useLocation, aj as usePosition, k as useRounded, r as makeThemeProps, m as makeTagProps, s as makeRoundedProps, ak as makePositionProps, t as makeLocationProps, v as makeElevationProps, d as makeDimensionProps, e as makeComponentProps, w as makeBorderProps, as as useDefineWidgets } from './asWebComponent-IZanwL-A.js';
3
+ import { u as useScopeId, f as forwardRefs, m as makeVOverlayProps, a as VOverlay } from './forwardRefs-B-c1_6yo.js';
4
+ import { V as VDialogTransition } from './dialog-transition-c4ZSnzac.js';
5
5
 
6
6
  const makeVDialogProps = propsFactory({
7
7
  fullscreen: Boolean,
@@ -1,9 +1,9 @@
1
1
  import { ref, createVNode, normalizeStyle, normalizeClass, createElementVNode, toRefs, onMounted, openBlock, createElementBlock, unref, createBlock, withCtx, Fragment, renderList, withDirectives, createTextVNode, toDisplayString, toRef, createCommentVNode } from 'vue';
2
2
  import { mdiOpenInNew, mdiUploadBox, mdiDownloadBox, mdiTrashCanOutline } from '@mdi/js';
3
- import { g as genericComponent, l as provideTheme, W as useDensity, c as useRender, p as propsFactory, r as makeThemeProps, m as makeTagProps, Z as makeDensityProps, e as makeComponentProps, q as convertToUnit, _ as _export_sfc, H as useSTAcStore, L as useOnLayersUpdate, K as VIcon, J as VBtn } from './asWebComponent-BlFN2lkB.js';
4
- import { Q as compareIndicator, M as indicator } from './helpers-CBqIUSXJ.js';
5
- import { u as updateJobsStatus, j as getJobStatusUrl, l as loadProcess, k as downloadPreviousResults, m as deleteJob } from './async-B2H8ZwUK.js';
6
- import { T as Tooltip } from './index-CJ9UI3ln.js';
3
+ import { g as genericComponent, l as provideTheme, W as useDensity, c as useRender, p as propsFactory, r as makeThemeProps, m as makeTagProps, Z as makeDensityProps, e as makeComponentProps, q as convertToUnit, _ as _export_sfc, H as useSTAcStore, L as useOnLayersUpdate, K as VIcon, J as VBtn } from './asWebComponent-IZanwL-A.js';
4
+ import { U as compareIndicator, Q as indicator } from './helpers-BFuh19CP.js';
5
+ import { u as updateJobsStatus, j as getJobStatusUrl, l as loadProcess, k as downloadPreviousResults, m as deleteJob } from './async-CiNIOBVz.js';
6
+ import { T as Tooltip } from './index-KGxz5Egv.js';
7
7
 
8
8
  /**
9
9
  * The list of job result from the server
@@ -1,6 +1,6 @@
1
1
  import { createVNode, normalizeStyle, normalizeClass, computed, toRef, createElementVNode } from 'vue';
2
- import { g as genericComponent, l as provideTheme, h as useBorder, U as useVariant, W as useDensity, k as useRounded, ao as useSize, c as useRender, K as VIcon, V as VDefaultsProvider, a1 as genOverlays, p as propsFactory, Q as IconValue, X as makeVariantProps, r as makeThemeProps, m as makeTagProps, ap as makeSizeProps, s as makeRoundedProps, Z as makeDensityProps, e as makeComponentProps, w as makeBorderProps, a2 as useTextColor, q as convertToUnit } from './asWebComponent-BlFN2lkB.js';
3
- import { V as VImg } from './VImg-Ddv5OyMz.js';
2
+ import { g as genericComponent, l as provideTheme, h as useBorder, U as useVariant, W as useDensity, k as useRounded, ao as useSize, c as useRender, K as VIcon, V as VDefaultsProvider, a1 as genOverlays, p as propsFactory, Q as IconValue, X as makeVariantProps, r as makeThemeProps, m as makeTagProps, ap as makeSizeProps, s as makeRoundedProps, Z as makeDensityProps, e as makeComponentProps, w as makeBorderProps, a2 as useTextColor, q as convertToUnit } from './asWebComponent-IZanwL-A.js';
3
+ import { V as VImg } from './VImg-B75dgw2K.js';
4
4
 
5
5
  const makeVAvatarProps = propsFactory({
6
6
  start: Boolean,
@@ -1,6 +1,6 @@
1
1
  import { h, TransitionGroup, Transition, createElementVNode, normalizeStyle, normalizeClass, computed, shallowRef, ref, watch, onBeforeMount, nextTick, onBeforeUnmount, toRef, withDirectives, createVNode, mergeProps, Fragment, vShow } from 'vue';
2
- import { aq as SUPPORTS_INTERSECTION, g as genericComponent, ar as PREFERS_REDUCED_MOTION, p as propsFactory, b as useDimension, c as useRender, d as makeDimensionProps, e as makeComponentProps, f as useBackgroundColor, k as useRounded, N as getCurrentInstance, q as convertToUnit, s as makeRoundedProps } from './asWebComponent-BlFN2lkB.js';
3
- import { M as MaybeTransition, m as makeTransitionProps$1 } from './transition-D_W6Wn9v.js';
2
+ import { aq as SUPPORTS_INTERSECTION, g as genericComponent, ar as PREFERS_REDUCED_MOTION, p as propsFactory, b as useDimension, c as useRender, d as makeDimensionProps, e as makeComponentProps, f as useBackgroundColor, k as useRounded, N as getCurrentInstance, q as convertToUnit, s as makeRoundedProps } from './asWebComponent-IZanwL-A.js';
3
+ import { M as MaybeTransition, m as makeTransitionProps$1 } from './transition-BkyUsZh_.js';
4
4
 
5
5
  // Utilities
6
6
  function mounted(el, binding) {
@@ -1,5 +1,5 @@
1
1
  import { createVNode, normalizeStyle, normalizeClass, createElementVNode } from 'vue';
2
- import { g as genericComponent, b as useDimension, a as useLayout, c as useRender, p as propsFactory, m as makeTagProps, d as makeDimensionProps, e as makeComponentProps } from './asWebComponent-BlFN2lkB.js';
2
+ import { g as genericComponent, b as useDimension, a as useLayout, c as useRender, p as propsFactory, m as makeTagProps, d as makeDimensionProps, e as makeComponentProps } from './asWebComponent-IZanwL-A.js';
3
3
  import { u as useSsrBoot } from './ssrBoot-Zgc_Ttvi.js';
4
4
 
5
5
  const makeVMainProps = propsFactory({
@@ -1,6 +1,6 @@
1
1
  import { useId, toRef, ref, computed, mergeProps, createVNode } from 'vue';
2
- import { u as useScopeId, f as forwardRefs, m as makeVOverlayProps, a as VOverlay } from './forwardRefs-DAlror6d.js';
3
- import { g as genericComponent, z as useProxiedModel, c as useRender, p as propsFactory, C as omit } from './asWebComponent-BlFN2lkB.js';
2
+ import { u as useScopeId, f as forwardRefs, m as makeVOverlayProps, a as VOverlay } from './forwardRefs-B-c1_6yo.js';
3
+ import { g as genericComponent, z as useProxiedModel, c as useRender, p as propsFactory, C as omit } from './asWebComponent-IZanwL-A.js';
4
4
 
5
5
  const makeVTooltipProps = propsFactory({
6
6
  id: String,
@@ -1,5 +1,5 @@
1
1
  import { ref, onMounted, nextTick, openBlock, createElementBlock, Fragment, renderList, unref, createElementVNode, toDisplayString, normalizeStyle, createBlock, resolveDynamicComponent, mergeProps } from 'vue';
2
- import { as as useDefineWidgets, a as useLayout } from './asWebComponent-BlFN2lkB.js';
2
+ import { as as useDefineWidgets, a as useLayout } from './asWebComponent-IZanwL-A.js';
3
3
  import 'animated-details';
4
4
 
5
5
  const _sfc_main = {
@@ -1,6 +1,6 @@
1
1
  import { warn, capitalize, reactive, watchEffect, toRef, shallowRef, Fragment, getCurrentInstance as getCurrentInstance$1, ref, computed, unref, provide, inject as inject$1, defineComponent as defineComponent$1, h, camelize, toValue, createVNode, mergeProps, createElementVNode, normalizeClass, watch, onScopeDispose, effectScope, toRaw, toRefs, getCurrentScope, onBeforeUnmount, readonly, onMounted, useId, onDeactivated, onActivated, nextTick, onUnmounted, isRef, normalizeStyle, onUpdated, Text, Transition, resolveDynamicComponent, withDirectives, toDisplayString, useModel, openBlock, createBlock, withCtx, createTextVNode, createCommentVNode, defineAsyncComponent, shallowReactive, onErrorCaptured, Suspense, normalizeProps, createElementBlock, useCssVars, withAsyncContext, defineCustomElement } from 'vue';
2
2
  import { storeToRefs, defineStore, createPinia } from 'pinia';
3
- import { r as registerProjection, c as createLayerID, e as extractRoles, a as extractEoxLegendLink, b as resolveStyle, d as extractLayerConfig, f as axios, g as applyTitilerUpscaling, h as addTooltipInteraction, i as createAssetID, j as getBandsProperty, m as mergeGeojsons, k as fetchStyle, l as encodeURLObject, n as mapEl, o as getProjectionCode, p as isSTACItem, q as extractLayerTimeValues, s as fetchApiItems, t as getDatetimeProperty, u as fetchPreAggregations, v as fetchAllStyles, w as findLayer, x as findLayersByLayerPrefix, y as replaceLayer, z as generateFeatures, A as dataThemesBrands, B as getLayers, C as extractLayerLegend, D as extractCollectionUrls, E as generateLinksFromItems, F as revokeCollectionBlobUrls, G as collectionsPalette, H as datetime, I as poi, J as activeTemplate, K as mapPosition, L as isFirstLoad, M as indicator, N as currentUrl, O as currentCompareUrl, P as eodashCompareCollections, Q as compareIndicator, R as comparePoi, S as eodashCollections, T as states, U as actions, V as areChartsSeparateLayout, W as chartSpec, X as compareChartSpec, Y as loading } from './helpers-CBqIUSXJ.js';
3
+ import { r as registerProjection, c as createLayerID, f as fetchRasterForm, e as extractLayerConfig, a as extractRoles, b as extractEoxLegendLink, d as applyTitilerUpscaling, g as axios, h as resolveStyle, i as addTooltipInteraction, j as createAssetID, k as getBandsProperty, m as mergeGeojsons, l as resolveRenders, n as normalizeRescale, o as normalizeNodata, p as encodeURLObject, q as mapEl, s as getProjectionCode, t as isSTACItem, u as extractLayerTimeValues, v as fetchStyle, w as fetchApiItems, x as getDatetimeProperty, y as fetchPreAggregations, z as fetchAllStyles, A as findLayer, B as findLayersByLayerPrefix, C as replaceLayer, D as generateFeatures, E as dataThemesBrands, F as getLayers, G as extractLayerLegend, H as extractCollectionUrls, I as generateLinksFromItems, J as revokeCollectionBlobUrls, K as collectionsPalette, L as datetime, M as poi, N as activeTemplate, O as mapPosition, P as isFirstLoad, Q as indicator, R as currentUrl, S as currentCompareUrl, T as eodashCompareCollections, U as compareIndicator, V as comparePoi, W as eodashCollections, X as states, Y as actions, Z as areChartsSeparateLayout, _ as chartSpec, $ as compareChartSpec, a0 as loading } from './helpers-BFuh19CP.js';
4
4
  import log from 'loglevel';
5
5
  import { useEventBus, useMutationObserver, createSharedComposable } from '@vueuse/core';
6
6
  import { Item, Collection } from 'stac-js';
@@ -8,6 +8,7 @@ import { toAbsolute } from 'stac-js/src/http.js';
8
8
  import { parquetRead } from 'hyparquet';
9
9
  import WebFontLoader from 'webfontloader';
10
10
  import mustache from 'mustache';
11
+ import '@eox/layercontrol';
11
12
  import { mdiClose, mdiAlertCircle, mdiPlus, mdiMenuDown, mdiChevronLeft, mdiChevronRight } from '@mdi/js';
12
13
  import VCalendar from 'v-calendar';
13
14
 
@@ -4107,6 +4108,10 @@ const createLayersFromLinks = async (
4107
4108
  item.links.filter((l) => l.rel === "vector-tile") ?? [];
4108
4109
  const mapboxStyleDocumentArray =
4109
4110
  item.links.filter((l) => l.rel === "mapbox-style-document") ?? [];
4111
+ // An xyz link takes precedence over a tilejson link;
4112
+ const tilejsonArray = xyzArray.length
4113
+ ? []
4114
+ : (item.links.filter((l) => l.rel === "tilejson") ?? []);
4110
4115
  // Taking projection code from main map view, as main view defines
4111
4116
  // projection for comparison map
4112
4117
  const viewProjectionCode = mapEl?.value?.projection || "EPSG:3857";
@@ -4129,6 +4134,20 @@ const createLayersFromLinks = async (
4129
4134
  wmsLink,
4130
4135
  viewProjectionCode,
4131
4136
  );
4137
+ const rasterForm = await fetchRasterForm(
4138
+ /** @type {string|object|undefined} */ (
4139
+ wmsLink?.["eodash:rasterform"] ||
4140
+ item?.["eodash:rasterform"] ||
4141
+ collection?.["eodash:rasterform"]
4142
+ ),
4143
+ );
4144
+ let { layerConfig } = extractLayerConfig(
4145
+ collectionId,
4146
+ {},
4147
+ rasterForm,
4148
+ "tileUrl",
4149
+ );
4150
+
4132
4151
  log.debug("WMS Layer added", linkId);
4133
4152
  const tileSize = /** @type {number[]} */ (
4134
4153
  "wms:tilesize" in wmsLink
@@ -4141,6 +4160,7 @@ const createLayersFromLinks = async (
4141
4160
  id: linkId,
4142
4161
  title: wmsLink.title || title || item.id,
4143
4162
  layerDatetime,
4163
+ layerConfig,
4144
4164
  },
4145
4165
  source: {
4146
4166
  type: "TileWMS",
@@ -4196,15 +4216,18 @@ const createLayersFromLinks = async (
4196
4216
  (wmtsLink?.["proj:epsg"] || wmtsLink?.["eodash:proj4_def"]);
4197
4217
 
4198
4218
  await registerProjection(wmtsLinkProjection);
4199
- const key =
4200
- /** @type {string | undefined} */ (wmtsLink["key"]) || undefined;
4201
4219
 
4202
- const styles = await resolveStyle(item, collection, key);
4203
- // get the correct style which is attached to a link
4220
+ const rasterForm = await fetchRasterForm(
4221
+ /** @type {string|object|undefined} */ (
4222
+ wmtsLink?.["eodash:rasterform"] ||
4223
+ item?.["eodash:rasterform"] ||
4224
+ collection?.["eodash:rasterform"]
4225
+ ),
4226
+ );
4204
4227
  const returnedLayerConfig = extractLayerConfig(
4205
4228
  collectionId,
4206
- styles,
4207
- undefined,
4229
+ {},
4230
+ rasterForm,
4208
4231
  "tileUrl",
4209
4232
  );
4210
4233
  const projectionCode = getProjectionCode(wmtsLinkProjection || "EPSG:3857");
@@ -4227,14 +4250,6 @@ const createLayersFromLinks = async (
4227
4250
  // TODO, this does not yet work between layer time changes because we do not get
4228
4251
  // updated variables from OL layer due to usage of tileurlfunction
4229
4252
 
4230
- // update dimensions with current value of style variables if applicable
4231
- const variables = returnedLayerConfig?.style?.variables;
4232
- if (variables) {
4233
- for (const [kk, vv] of Object.entries(variables)) {
4234
- dimensionsWithoutStyle[kk] = vv;
4235
- }
4236
- }
4237
-
4238
4253
  if (wmtsLink.href.includes("marine.copernicus")) {
4239
4254
  log.debug(
4240
4255
  "Warning: WMTS Layer from capabilities added, function needs to be updated",
@@ -4275,6 +4290,7 @@ const createLayersFromLinks = async (
4275
4290
  id: linkId,
4276
4291
  title: wmtsLink.title || title || item.id,
4277
4292
  layerDatetime,
4293
+ layerConfig: returnedLayerConfig.layerConfig,
4278
4294
  },
4279
4295
  source: {
4280
4296
  type: "WMTSCapabilities",
@@ -4304,19 +4320,16 @@ const createLayersFromLinks = async (
4304
4320
  const xyzLinkProjection =
4305
4321
  /** @type {number | string | {name: string, def: string} | undefined} */
4306
4322
  (xyzLink?.["proj:epsg"] || xyzLink?.["eodash:proj4_def"]);
4307
- const key = /** @type {string | undefined} */ (xyzLink["key"]) || undefined;
4308
- const rasterformURL = /** @type {string|undefined} */ (
4309
- collection?.["eodash:rasterform"]
4323
+ const rasterForm = await fetchRasterForm(
4324
+ /** @type {string|object|undefined} */ (
4325
+ xyzLink?.["eodash:rasterform"] ||
4326
+ item?.["eodash:rasterform"] ||
4327
+ collection?.["eodash:rasterform"]
4328
+ ),
4310
4329
  );
4311
- /** @type {import("@/types").EodashRasterJSONForm|undefined} */
4312
- const rasterForm = rasterformURL
4313
- ? await axios.get(rasterformURL).then((resp) => resp.data)
4314
- : undefined;
4315
- const styles = await resolveStyle(item, collection, key);
4316
- // get the correct style which is attached to a link
4317
- let { layerConfig, style } = extractLayerConfig(
4330
+ let { layerConfig } = extractLayerConfig(
4318
4331
  collectionId,
4319
- styles,
4332
+ {},
4320
4333
  rasterForm,
4321
4334
  "tileUrl",
4322
4335
  );
@@ -4329,19 +4342,6 @@ const createLayersFromLinks = async (
4329
4342
  viewProjectionCode,
4330
4343
  );
4331
4344
  let xyzUrl = xyzLink.href;
4332
- // TODO, this does not yet work between layer time changes because we do not get
4333
- // updated variables from OL layer due to usage of tileurlfunction
4334
-
4335
- // update url query params with current value of style variables if applicable
4336
- const variables = style?.variables;
4337
- if (variables) {
4338
- const [base, query] = xyzUrl.split("?");
4339
- const params = new URLSearchParams(query);
4340
- for (const [kk, vv] of Object.entries(variables)) {
4341
- params.set(kk, JSON.stringify(vv));
4342
- }
4343
- xyzUrl = `${base}?${params.toString()}`;
4344
- }
4345
4345
  const { supportedUpscalingEndpoints } = useSTAcStore();
4346
4346
  const upscaling = applyTitilerUpscaling(
4347
4347
  xyzUrl,
@@ -4400,6 +4400,96 @@ const createLayersFromLinks = async (
4400
4400
  jsonArray.push(json);
4401
4401
  }
4402
4402
 
4403
+ for (const tilejsonLink of tilejsonArray) {
4404
+ // The tilejson href is a complete URL with the render params baked in by the
4405
+ // STAC producer; fetch it and use its `tiles[0]` template as an XYZ source.
4406
+ const tileJSON = await axios
4407
+ .get(tilejsonLink.href)
4408
+ .then((res) => res.data)
4409
+ .catch((err) => {
4410
+ console.error("[eodash] Failed to fetch item TileJSON", err);
4411
+ return null;
4412
+ });
4413
+ if (!tileJSON?.tiles?.[0]) {
4414
+ console.warn(
4415
+ "[eodash] No tile URL in item TileJSON response",
4416
+ tilejsonLink.href,
4417
+ );
4418
+ continue;
4419
+ }
4420
+ // Only raster XYZ tiles are supported; skip vector & TMS scheme TileJSON
4421
+ if (tileJSON.vector_layers || tileJSON.scheme === "tms") {
4422
+ console.warn(
4423
+ "[eodash] Unsupported TileJSON (only raster XYZ is supported)",
4424
+ tilejsonLink.href,
4425
+ );
4426
+ continue;
4427
+ }
4428
+
4429
+ const tilejsonProjection =
4430
+ /** @type {number | string | {name: string, def: string} | undefined} */
4431
+ (tilejsonLink?.["proj:epsg"] || tilejsonLink?.["eodash:proj4_def"]);
4432
+ await registerProjection(tilejsonProjection);
4433
+ const projectionCode = getProjectionCode(tilejsonProjection || "EPSG:3857");
4434
+ const rasterForm = await fetchRasterForm(
4435
+ /** @type {string|object|undefined} */ (
4436
+ tilejsonLink?.["eodash:rasterform"] ||
4437
+ item?.["eodash:rasterform"] ||
4438
+ collection?.["eodash:rasterform"]
4439
+ ),
4440
+ );
4441
+ const { layerConfig } = extractLayerConfig(
4442
+ collectionId,
4443
+ {},
4444
+ rasterForm,
4445
+ "tileUrl",
4446
+ );
4447
+ const linkId = createLayerID(
4448
+ collectionId,
4449
+ item.id,
4450
+ tilejsonLink,
4451
+ viewProjectionCode,
4452
+ );
4453
+
4454
+ log.debug("TileJSON layer added", linkId);
4455
+ /** @type {Record<string, any>} */
4456
+ const json = {
4457
+ type: "Tile",
4458
+ properties: {
4459
+ id: linkId,
4460
+ title: tilejsonLink.title || title || item.id,
4461
+ roles: tilejsonLink.roles,
4462
+ layerDatetime,
4463
+ layerConfig,
4464
+ },
4465
+ source: {
4466
+ type: "XYZ",
4467
+ ...(tileJSON.tiles.length > 1
4468
+ ? { urls: tileJSON.tiles }
4469
+ : { url: tileJSON.tiles[0] }),
4470
+ projection: projectionCode,
4471
+ // Link attribution wins; the TileJSON document's own is the fallback.
4472
+ ...(tilejsonLink.attribution || tileJSON.attribution
4473
+ ? {
4474
+ attributions: tilejsonLink.attribution || tileJSON.attribution,
4475
+ }
4476
+ : {}),
4477
+ },
4478
+ };
4479
+ if (Number.isFinite(tileJSON.minzoom)) json.minZoom = tileJSON.minzoom;
4480
+ if (Number.isFinite(tileJSON.maxzoom)) json.maxZoom = tileJSON.maxzoom;
4481
+
4482
+ extractRoles(json.properties, tilejsonLink);
4483
+ if (extraProperties !== null) {
4484
+ json.properties = {
4485
+ ...json.properties,
4486
+ ...extraProperties,
4487
+ ...extractEoxLegendLink(tilejsonLink),
4488
+ };
4489
+ }
4490
+ jsonArray.push(json);
4491
+ }
4492
+
4403
4493
  for (const vectorTileLink of vectorTileArray ?? []) {
4404
4494
  const vectorTileLinkProjection =
4405
4495
  /** @type {number | string | {name: string, def: string} | undefined} */
@@ -4551,72 +4641,85 @@ const createLayerFromRender = async (
4551
4641
  item,
4552
4642
  extraProperties,
4553
4643
  ) => {
4554
- if (!collection || !collection.renders || !item) {
4644
+ // config renders > collection STAC renders > item renders
4645
+ const renders = /** @type {Record<string,import("@/types").Render>} */ (
4646
+ resolveRenders(collection, useEodash()?.options?.renders) ?? item?.renders
4647
+ );
4648
+ if (!collection || !item || !renders) {
4555
4649
  return [];
4556
4650
  }
4557
4651
 
4558
- // Skip when an explicit xyz link already targets the collection on the same endpoint
4559
- const hasMatchingXyzLink = item.links?.some(
4652
+ // Yield to a raster xyz/tilejson link createLayersFromLinks renders it.
4653
+ const hasMatchingTileLink = item.links?.some(
4560
4654
  (link) =>
4561
- link.rel === "xyz" &&
4562
- link.href?.includes(rasterURL) &&
4563
- link.href?.includes(`/collections/${collection.id}/`),
4655
+ (link.rel === "xyz" || link.rel === "tilejson") &&
4656
+ link.href?.includes(rasterURL),
4564
4657
  );
4565
- if (hasMatchingXyzLink) {
4658
+ if (hasMatchingTileLink) {
4566
4659
  return [];
4567
4660
  }
4568
4661
 
4569
- const rasterformURL = /** @type {string|undefined} */ (
4570
- collection?.["eodash:rasterform"]
4571
- );
4572
- /** @type {import("@/types").EodashRasterJSONForm|undefined} */
4573
- const rasterForm = rasterformURL
4574
- ? await axios.get(rasterformURL).then((resp) => resp.data)
4575
- : undefined;
4576
- let { layerConfig } = extractLayerConfig(
4577
- collection.id,
4578
- await fetchStyle(item),
4579
- rasterForm,
4662
+ const rasterForm = await fetchRasterForm(
4663
+ /** @type {string|object|undefined} */ (
4664
+ item?.["eodash:rasterform"] || collection?.["eodash:rasterform"]
4665
+ ),
4580
4666
  );
4667
+ let { layerConfig } = extractLayerConfig(collection.id, {}, rasterForm);
4668
+
4669
+ /**
4670
+ * Resolves the first defined value of a property across a render's assets,
4671
+ * checking item assets before falling back to collection assets.
4672
+ * @param {import("@/types").Render} render
4673
+ * @param {string} propertyName
4674
+ * @returns {any}
4675
+ */
4676
+ const getRenderAssetProperty = (render, propertyName) => {
4677
+ for (const assetKey of render.assets ?? []) {
4678
+ const asset = item?.assets?.[assetKey] ?? collection?.assets?.[assetKey];
4679
+ const value = asset?.[propertyName];
4680
+ if (value !== undefined) {
4681
+ return value;
4682
+ }
4683
+ }
4684
+ return undefined;
4685
+ };
4581
4686
 
4582
- const renders = /** @type {Record<string,import("@/types").Render>} */ (
4583
- collection.renders ?? item?.renders
4584
- );
4585
4687
  const layers = [];
4586
- // special case for rescale
4587
4688
  for (const key in renders) {
4588
4689
  const title = renders[key].title;
4589
4690
 
4590
- const assetsCollection =
4591
- renders[key].assets[0] in item["assets"] ? item : collection;
4691
+ const expression =
4692
+ renders[key].expression ??
4693
+ getRenderAssetProperty(renders[key], "expression");
4592
4694
 
4593
4695
  const paramsObject = {
4594
- assets: renders[key].assets,
4595
- expression:
4596
- renders[key].expression ??
4597
- assetsCollection["assets"]?.[renders[key].assets[0]]?.expression,
4598
- nodata:
4599
- renders[key].nodata ??
4600
- assetsCollection["assets"]?.[renders[key].assets[0]]?.nodata,
4696
+ // TiTiler treats assets and expression as mutually exclusive band selection
4697
+ assets: expression ? undefined : renders[key].assets,
4698
+ expression,
4699
+ nodata: normalizeNodata(
4700
+ renders[key].nodata ?? getRenderAssetProperty(renders[key], "nodata"),
4701
+ ),
4601
4702
  resampling:
4602
4703
  renders[key].resampling ??
4603
- assetsCollection["assets"]?.[renders[key].assets[0]]?.resampling,
4704
+ getRenderAssetProperty(renders[key], "resampling"),
4604
4705
  color_formula:
4605
4706
  renders[key].color_formula ??
4606
- assetsCollection["assets"]?.[renders[key].assets[0]]?.color_formula,
4707
+ getRenderAssetProperty(renders[key], "color_formula"),
4607
4708
  colormap:
4608
4709
  renders[key].colormap ??
4609
- assetsCollection["assets"]?.[renders[key].assets[0]]?.colormap,
4710
+ getRenderAssetProperty(renders[key], "colormap"),
4610
4711
  colormap_name:
4611
4712
  renders[key].colormap_name ??
4612
- assetsCollection["assets"]?.[renders[key].assets[0]]?.colormap_name,
4613
- rescale:
4614
- renders[key].rescale ??
4615
- assetsCollection["assets"]?.[renders[key].assets[0]]?.rescale,
4713
+ getRenderAssetProperty(renders[key], "colormap_name"),
4714
+ rescale: normalizeRescale(
4715
+ renders[key].rescale ?? getRenderAssetProperty(renders[key], "rescale"),
4716
+ ),
4717
+ bidx: renders[key].bidx,
4718
+ tilesize: renders[key].tilesize,
4616
4719
  };
4617
4720
  const paramsStr = encodeURLObject(paramsObject);
4618
4721
  const url = `${rasterURL}/collections/${collection.id}/items/${item.id}/tiles/WebMercatorQuad/{z}/{x}/{y}?${paramsStr}`;
4619
- layers.push({
4722
+ const json = {
4620
4723
  /** @type {"Tile"} */
4621
4724
  type: "Tile",
4622
4725
  properties: {
@@ -4639,7 +4742,14 @@ const createLayerFromRender = async (
4639
4742
  url,
4640
4743
  projection: "EPSG:3857",
4641
4744
  },
4642
- });
4745
+ };
4746
+ if (renders[key].tilesize) {
4747
+ // @ts-expect-error tileGrid is added here and supported in eox-map layer definition
4748
+ json.source.tileGrid = {
4749
+ tileSize: [renders[key].tilesize, renders[key].tilesize],
4750
+ };
4751
+ }
4752
+ layers.push(json);
4643
4753
  }
4644
4754
 
4645
4755
  return layers;
@@ -4811,9 +4921,14 @@ class EodashCollection {
4811
4921
 
4812
4922
  const isSupported =
4813
4923
  item.links.some((link) =>
4814
- ["wms", "xyz", "wmts", "vector-tile", "mapbox-style-document"].includes(
4815
- link.rel,
4816
- ),
4924
+ [
4925
+ "wms",
4926
+ "xyz",
4927
+ "wmts",
4928
+ "vector-tile",
4929
+ "mapbox-style-document",
4930
+ "tilejson",
4931
+ ].includes(link.rel),
4817
4932
  ) || Object.keys(dataAssets).length;
4818
4933
 
4819
4934
  if (isSupported) {
@@ -4975,7 +5090,9 @@ class EodashCollection {
4975
5090
  (/** @type {any} */ a) => a.key?.startsWith("datetime_") || a.interval,
4976
5091
  );
4977
5092
  if (datetimeAgg?.buckets) {
4978
- return datetimeAgg.buckets.map((/** @type {any} */ b) => new Date(b.key));
5093
+ return datetimeAgg.buckets
5094
+ .map((/** @type {any} */ b) => new Date(b.key))
5095
+ .filter((/** @type {Date} */ d) => !isNaN(d.getTime()));
4979
5096
  }
4980
5097
 
4981
5098
  const items = await this.getItems(true, false, centerDatetime);
@@ -4990,7 +5107,9 @@ class EodashCollection {
4990
5107
  new Date(/** @type {string} */ (i.properties?.[datetimeProperty]))
4991
5108
  : //@ts-expect-error todo
4992
5109
  (i) => new Date(/** @type {string} */ (i[datetimeProperty]));
4993
- return items?.map(mapToDates) || [];
5110
+ return (items ?? [])
5111
+ .map(mapToDates)
5112
+ .filter((/** @type {Date} */ d) => !isNaN(d.getTime()));
4994
5113
  }
4995
5114
 
4996
5115
  async getExtent() {
@@ -6101,6 +6220,12 @@ const useSTAcStore = defineStore("stac", () => {
6101
6220
  */
6102
6221
  const supportedUpscalingEndpoints = ref([]);
6103
6222
 
6223
+ /**
6224
+ * Registry of colormap ranges
6225
+ * @type {import("vue").Ref<Record<string, string[]> | null>}
6226
+ */
6227
+ const colormapRegistry = ref(null);
6228
+
6104
6229
  /**
6105
6230
  * Links of the root STAC catalog
6106
6231
  *
@@ -6160,6 +6285,26 @@ const useSTAcStore = defineStore("stac", () => {
6160
6285
  rasterEndpoint.value = endpoint.rasterEndpoint ?? null;
6161
6286
  supportedUpscalingEndpoints.value =
6162
6287
  endpoint.supportedUpscalingEndpoints ?? [];
6288
+ if (endpoint.colormapRegistry) {
6289
+ loadColormapRegistry(endpoint.colormapRegistry);
6290
+ }
6291
+ }
6292
+
6293
+ /**
6294
+ * Loads the colormap registry from a URL or object
6295
+ * @param {string | Record<string, string[]>} registry
6296
+ */
6297
+ async function loadColormapRegistry(registry) {
6298
+ if (typeof registry === "object") {
6299
+ colormapRegistry.value = registry;
6300
+ return;
6301
+ }
6302
+ try {
6303
+ const resp = await axios.get(registry);
6304
+ colormapRegistry.value = resp.data;
6305
+ } catch (err) {
6306
+ log.error("Error loading colormap registry", err);
6307
+ }
6163
6308
  }
6164
6309
 
6165
6310
  /**
@@ -6233,6 +6378,7 @@ const useSTAcStore = defineStore("stac", () => {
6233
6378
  await axios
6234
6379
  .get(absoluteUrl.value)
6235
6380
  .then(async (resp) => {
6381
+ resp.data["eodash:layerExclusive"] = true;
6236
6382
  await updateEodashCollections(
6237
6383
  eodashCollections,
6238
6384
  resp.data,
@@ -6345,6 +6491,8 @@ const useSTAcStore = defineStore("stac", () => {
6345
6491
  selectedItem,
6346
6492
  selectedCompareItem,
6347
6493
  supportedUpscalingEndpoints,
6494
+ colormapRegistry,
6495
+ loadColormapRegistry,
6348
6496
  };
6349
6497
  });
6350
6498
 
@@ -8596,7 +8744,7 @@ const ErrorAlert = /*#__PURE__*/_export_sfc(_sfc_main$4, [['styles',[_style_0$2]
8596
8744
  const internalWidgets = (() => {
8597
8745
  /** @type {Record<string, () => Promise<import("vue").Component>>} */
8598
8746
  const importMap = {
8599
- .../* #__PURE__ */ Object.assign({"/widgets/EodashChart.vue": () => import('./EodashChart-ChrkA5oS.js'),"/widgets/EodashDatePicker.vue": () => import('./EodashDatePicker-CY1TrsDo.js'),"/widgets/EodashItemCatalog/index.vue": () => import('./index-BWq1ZKaV.js'),"/widgets/EodashItemFilter.vue": () => import('./EodashItemFilter-DzshHDlS.js'),"/widgets/EodashLayerControl.vue": () => import('./EodashLayerControl-DMCeMkSd.js'),"/widgets/EodashLayoutSwitcher.vue": () => import('./EodashLayoutSwitcher-iJ8mX1rF.js'),"/widgets/EodashMap/EodashMapBtns.vue": () => import('./EodashMapBtns-C7Cr7q5Y.js'),"/widgets/EodashMap/index.vue": () => import('./index-DhKU6KqM.js'),"/widgets/EodashProcess/ProcessList.vue": () => import('./ProcessList-DuI6WpS1.js').then(n => n.a),"/widgets/EodashProcess/index.vue": () => import('./index-DjQlbWbJ.js'),"/widgets/EodashStacInfo.vue": () => import('./EodashStacInfo-K7-iuXa7.js'),"/widgets/EodashTimeSlider/index.vue": () => import('./index-DXLz4sFR.js'),"/widgets/EodashTools.vue": () => import('./EodashTools-BEK7e7JM.js'),"/widgets/ExportState.vue": () => import('./ExportState-CqIzfMYQ.js'),"/widgets/PopUp.vue": () => import('./PopUp-DPZq5SWI.js'),"/widgets/WidgetsContainer.vue": () => import('./WidgetsContainer-2DOrlwCB.js')}),
8747
+ .../* #__PURE__ */ Object.assign({"/widgets/EodashChart.vue": () => import('./EodashChart-D-3AGKZY.js'),"/widgets/EodashDatePicker.vue": () => import('./EodashDatePicker-Dm_goZzs.js'),"/widgets/EodashItemCatalog/index.vue": () => import('./index-D0jUyol8.js'),"/widgets/EodashItemFilter.vue": () => import('./EodashItemFilter-CJy3zYzD.js'),"/widgets/EodashLayerControl.vue": () => import('./EodashLayerControl-rL8UnpkA.js'),"/widgets/EodashLayoutSwitcher.vue": () => import('./EodashLayoutSwitcher-ZRlESI9O.js'),"/widgets/EodashMap/EodashMapBtns.vue": () => import('./EodashMapBtns-CG7u2Aq8.js'),"/widgets/EodashMap/index.vue": () => import('./index-1wMAyuNL.js'),"/widgets/EodashProcess/ProcessList.vue": () => import('./ProcessList-LL_UCbvc.js').then(n => n.a),"/widgets/EodashProcess/index.vue": () => import('./index-BKQQJkhy.js'),"/widgets/EodashStacInfo.vue": () => import('./EodashStacInfo-CJhhxthD.js'),"/widgets/EodashTimeSlider/index.vue": () => import('./index-B8jGJSTA.js'),"/widgets/EodashTools.vue": () => import('./EodashTools-CWyK8QJT.js'),"/widgets/ExportState.vue": () => import('./ExportState-BXhy5TOU.js'),"/widgets/PopUp.vue": () => import('./PopUp-7_XnhvCc.js'),"/widgets/WidgetsContainer.vue": () => import('./WidgetsContainer-BqaWs4ch.js')}),
8600
8748
  .../* #__PURE__ */ Object.assign({}),
8601
8749
  };
8602
8750
  for (const key in importMap) {
@@ -8730,7 +8878,7 @@ const getWidgetDefinition = (config) => {
8730
8878
 
8731
8879
  case "web-component":
8732
8880
  importedWidget.component = defineAsyncComponent({
8733
- loader: () => import('./DynamicWebComponent-g5SdRbjY.js'),
8881
+ loader: () => import('./DynamicWebComponent-PvnV88BA.js'),
8734
8882
  suspensible: true,
8735
8883
  });
8736
8884
  importedWidget.props = reactive(config.widget);
@@ -9127,7 +9275,7 @@ return (_ctx, _cache) => {
9127
9275
 
9128
9276
  };
9129
9277
 
9130
- const version = "5.7.1";
9278
+ const version = "5.8.0";
9131
9279
  const pkgJson = {
9132
9280
  version};
9133
9281
 
@@ -9256,15 +9404,15 @@ const { smAndDown } = useDisplay();
9256
9404
 
9257
9405
  const TemplateComponent = computed(() =>
9258
9406
  smAndDown.value
9259
- ? defineAsyncComponent(() => import('./MobileLayout-BPf49kDU.js'))
9260
- : defineAsyncComponent(() => import('./DashboardLayout-ePbdvUTE.js')),
9407
+ ? defineAsyncComponent(() => import('./MobileLayout-BJHW7x5V.js'))
9408
+ : defineAsyncComponent(() => import('./DashboardLayout-DEs4f_Vy.js')),
9261
9409
  );
9262
9410
 
9263
9411
  const HeaderComponent = defineAsyncComponent(
9264
- () => import('./Header-CkkBaBNh.js'),
9412
+ () => import('./Header-CiGsDE_a.js'),
9265
9413
  );
9266
9414
  const FooterComponent = defineAsyncComponent(
9267
- () => import('./Footer-1P0cmBOZ.js'),
9415
+ () => import('./Footer-DZPvnhcT.js'),
9268
9416
  );
9269
9417
 
9270
9418
  const error = ref("");