@eodash/eodash 5.0.0-processing → 5.0.0-rc

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 (111) hide show
  1. package/core/client/asWebComponent.js +2 -3
  2. package/core/client/components/DashboardLayout.vue +35 -17
  3. package/core/client/components/Loading.vue +6 -9
  4. package/core/client/components/MobileLayout.vue +16 -14
  5. package/core/client/composables/DefineEodash.js +13 -3
  6. package/core/client/composables/DefineTemplate.js +67 -0
  7. package/core/client/composables/DefineWidgets.js +3 -2
  8. package/core/client/composables/EodashMap.js +23 -12
  9. package/core/client/composables/EodashProcess.js +10 -11
  10. package/core/client/composables/index.js +35 -10
  11. package/core/client/eodash.js +381 -139
  12. package/core/client/{utils/eodashSTAC.js → eodashSTAC/EodashCollection.js} +75 -42
  13. package/core/client/{utils → eodashSTAC}/createLayers.js +10 -8
  14. package/core/client/{utils → eodashSTAC}/helpers.js +45 -68
  15. package/core/client/eodashSTAC/triggers.js +43 -0
  16. package/core/client/plugins/vuetify.js +2 -1
  17. package/core/client/store/{Actions.js → actions.js} +16 -2
  18. package/core/client/store/index.js +4 -18
  19. package/core/client/store/stac.js +4 -4
  20. package/core/client/store/{States.js → states.js} +2 -0
  21. package/{dist/types/core/client/types.d.ts → core/client/types.ts} +47 -8
  22. package/core/client/utils/states.js +8 -3
  23. package/core/client/views/Dashboard.vue +6 -4
  24. package/core/client/vite-env.d.ts +1 -1
  25. package/dist/client/{DashboardLayout-CVMJ4l8M.js → DashboardLayout-232tRmjz.js} +12 -15
  26. package/dist/client/{DynamicWebComponent-Cv8n457T.js → DynamicWebComponent-Cl4LqHU6.js} +1 -1
  27. package/dist/client/{EodashDatePicker-VVkiPmpc.js → EodashDatePicker-Pok6bZwU.js} +75 -163
  28. package/dist/client/EodashItemFilter-16eMMjTV.js +151 -0
  29. package/dist/client/{EodashLayerControl-53WghA8G.js → EodashLayerControl-De7IlCm_.js} +17 -7
  30. package/dist/client/EodashLayoutSwitcher-C-3-jjn5.js +52 -0
  31. package/dist/client/{EodashMap-CQnOePpy.js → EodashMap-CMvbfI6-.js} +101 -38
  32. package/dist/client/EodashMapBtns-BeknGDtc.js +107 -0
  33. package/dist/client/{EodashProcess-cF0unIy8.js → EodashProcess-BwKAa9Ee.js} +9 -10
  34. package/dist/client/EodashStacInfo-_BfonNUG.js +85 -0
  35. package/dist/client/EodashTools-PD3XPYuR.js +103 -0
  36. package/dist/client/{ExportState-BT8MLAW7.js → ExportState-DOrT7M15.js} +5 -5
  37. package/dist/client/{Footer-C6GUG84G.js → Footer-CCigxYBo.js} +1 -1
  38. package/dist/client/{Header-D2dtCWp8.js → Header-C2cdx4gb.js} +3 -3
  39. package/dist/client/{MobileLayout-BAo8Wr8T.js → MobileLayout-BdiFjHg7.js} +28 -31
  40. package/dist/client/{PopUp-Bm01q7Ko.js → PopUp--_xn1Cms.js} +29 -8
  41. package/dist/client/{VImg-B8AbetCE.js → VImg-9xu2l99m.js} +2 -2
  42. package/dist/client/{VMain-DnGlQUyr.js → VMain-BUs3kDTd.js} +1 -1
  43. package/dist/client/{VOverlay-B8Qj7LRG.js → VOverlay-D89omJis.js} +3 -3
  44. package/dist/client/VTooltip-CDu3bErh.js +86 -0
  45. package/dist/client/{WidgetsContainer-CwXRRLS1.js → WidgetsContainer-aFG9yFT6.js} +1 -1
  46. package/dist/client/{asWebComponent-DUUoR7MZ.js → asWebComponent-BRGyP_j5.js} +1374 -1052
  47. package/dist/client/{style.css → eo-dash.css} +1 -1
  48. package/dist/client/eo-dash.js +1 -1
  49. package/dist/client/{forwardRefs-CZJhEAKW.js → forwardRefs-CYrR6bMw.js} +1 -1
  50. package/dist/client/{index-DlIO7sJ3.js → index-BZwk0V42.js} +1 -1
  51. package/dist/client/{transition-BiR8wMn1.js → transition-DG9nRSW4.js} +1 -1
  52. package/dist/node/cli.js +2 -2
  53. package/package.json +47 -33
  54. package/widgets/EodashDatePicker.vue +68 -54
  55. package/widgets/EodashItemFilter.vue +60 -105
  56. package/widgets/EodashLayerControl.vue +17 -4
  57. package/widgets/EodashLayoutSwitcher.vue +36 -0
  58. package/widgets/EodashMap.vue +26 -27
  59. package/widgets/EodashMapBtns.vue +41 -4
  60. package/widgets/EodashProcess.vue +4 -12
  61. package/widgets/EodashStacInfo.vue +82 -0
  62. package/widgets/EodashTools.vue +83 -0
  63. package/widgets/ExportState.vue +3 -3
  64. package/widgets/PopUp.vue +24 -2
  65. package/core/client/asWebComponent.d.ts +0 -23
  66. package/core/client/types.d.ts +0 -279
  67. package/dist/client/EodashItemFilter-CugWNQ86.js +0 -194
  68. package/dist/client/EodashMapBtns-uaRwFtfB.js +0 -66
  69. package/dist/types/core/client/App.vue.d.ts +0 -7
  70. package/dist/types/core/client/asWebComponent.d.ts +0 -9
  71. package/dist/types/core/client/components/DashboardLayout.vue.d.ts +0 -2
  72. package/dist/types/core/client/components/DynamicWebComponent.vue.d.ts +0 -18
  73. package/dist/types/core/client/components/ErrorAlert.vue.d.ts +0 -2
  74. package/dist/types/core/client/components/Footer.vue.d.ts +0 -2
  75. package/dist/types/core/client/components/Header.vue.d.ts +0 -2
  76. package/dist/types/core/client/components/IframeWrapper.vue.d.ts +0 -7
  77. package/dist/types/core/client/components/Loading.vue.d.ts +0 -2
  78. package/dist/types/core/client/components/MobileLayout.vue.d.ts +0 -2
  79. package/dist/types/core/client/composables/DefineEodash.d.ts +0 -2
  80. package/dist/types/core/client/composables/DefineTemplate.d.ts +0 -15
  81. package/dist/types/core/client/composables/DefineWidgets.d.ts +0 -14
  82. package/dist/types/core/client/composables/EodashMap.d.ts +0 -5
  83. package/dist/types/core/client/composables/index.d.ts +0 -30
  84. package/dist/types/core/client/eodash.d.ts +0 -8
  85. package/dist/types/core/client/main.d.ts +0 -2
  86. package/dist/types/core/client/plugins/axios.d.ts +0 -2
  87. package/dist/types/core/client/plugins/index.d.ts +0 -3
  88. package/dist/types/core/client/plugins/vuetify.d.ts +0 -82
  89. package/dist/types/core/client/render.d.ts +0 -1
  90. package/dist/types/core/client/store/Actions.d.ts +0 -12
  91. package/dist/types/core/client/store/States.d.ts +0 -22
  92. package/dist/types/core/client/store/index.d.ts +0 -2
  93. package/dist/types/core/client/store/stac.d.ts +0 -25
  94. package/dist/types/core/client/utils/createLayers.d.ts +0 -45
  95. package/dist/types/core/client/utils/eodashSTAC.d.ts +0 -82
  96. package/dist/types/core/client/utils/helpers.d.ts +0 -84
  97. package/dist/types/core/client/utils/index.d.ts +0 -2
  98. package/dist/types/core/client/utils/keys.d.ts +0 -6
  99. package/dist/types/core/client/utils/states.d.ts +0 -14
  100. package/dist/types/core/client/views/Dashboard.vue.d.ts +0 -9
  101. package/dist/types/widgets/EodashDatePicker.vue.d.ts +0 -7
  102. package/dist/types/widgets/EodashItemFilter.vue.d.ts +0 -42
  103. package/dist/types/widgets/EodashLayerControl.vue.d.ts +0 -11
  104. package/dist/types/widgets/EodashLayoutSwitcher.vue.d.ts +0 -9
  105. package/dist/types/widgets/EodashMap.vue.d.ts +0 -7
  106. package/dist/types/widgets/EodashMapBtns.vue.d.ts +0 -11
  107. package/dist/types/widgets/EodashStacInfo.vue.d.ts +0 -21
  108. package/dist/types/widgets/EodashTools.vue.d.ts +0 -15
  109. package/dist/types/widgets/ExportState.vue.d.ts +0 -7
  110. package/dist/types/widgets/PopUp.vue.d.ts +0 -22
  111. package/dist/types/widgets/WidgetsContainer.vue.d.ts +0 -7
@@ -1,59 +1,13 @@
1
- import { ref, reactive, watch, onScopeDispose, effectScope, Fragment, computed, watchEffect, toRefs, capitalize, shallowRef, warn, getCurrentInstance as getCurrentInstance$1, unref, provide, inject as inject$1, defineComponent as defineComponent$1, camelize, h, toRaw, createVNode, mergeProps, onBeforeUnmount, readonly, onMounted, onDeactivated, onActivated, nextTick, onUnmounted, shallowReactive, defineAsyncComponent, isRef, toRef, onUpdated, Text, Transition, resolveDynamicComponent, withDirectives, useModel, openBlock, createBlock, withCtx, createTextVNode, toDisplayString, createElementVNode, createCommentVNode, onErrorCaptured, Suspense, normalizeProps, createElementBlock, withAsyncContext, normalizeStyle, defineCustomElement } from 'vue';
1
+ import { ref, reactive, watch, onScopeDispose, effectScope, Fragment, computed, watchEffect, toRefs, capitalize, shallowRef, warn, getCurrentInstance as getCurrentInstance$1, unref, provide, inject as inject$1, defineComponent as defineComponent$1, camelize, h, toRaw, createVNode, mergeProps, onBeforeUnmount, readonly, onMounted, onDeactivated, onActivated, nextTick, shallowReactive, onUnmounted, isRef, toRef, onUpdated, Text, Transition, resolveDynamicComponent, withDirectives, useModel, openBlock, createBlock, withCtx, createTextVNode, toDisplayString, createElementVNode, createCommentVNode, defineAsyncComponent, onErrorCaptured, Suspense, normalizeProps, createElementBlock, withAsyncContext, normalizeStyle, defineCustomElement } from 'vue';
2
+ import { defineStore, storeToRefs, createPinia } from 'pinia';
3
+ import { setupCache } from 'axios-cache-interceptor';
2
4
  import log from 'loglevel';
5
+ import { mdiViewDashboardVariant, mdiViewDashboard, mdiAlertCircle, mdiClose, mdiChevronRight, mdiChevronLeft, mdiMenuDown, mdiPlus } from '@mdi/js';
6
+ import { useEventBus, createSharedComposable } from '@vueuse/core';
3
7
  import { toAbsolute } from 'stac-js/src/http.js';
4
- import { setupCache } from 'axios-cache-interceptor';
5
- import { defineStore, storeToRefs, createPinia } from 'pinia';
6
- import { useEventBus } from '@vueuse/core';
7
8
  import { Collection, Item } from 'stac-js';
8
- import { mdiAlertCircle, mdiClose, mdiChevronRight, mdiChevronLeft, mdiMenuDown } from '@mdi/js';
9
9
  import VCalendar from 'v-calendar';
10
10
 
11
- /** setting default log level globally to warning */
12
- log.setLevel(log.levels.WARN, true);
13
-
14
- /** Currently selected STAC endpoint */
15
- const currentUrl = ref("");
16
-
17
- /** Currently selected compare STAC endpoint */
18
- const currentCompareUrl = ref("");
19
-
20
- /** Currently selected datetime */
21
- const datetime = ref(new Date().toISOString());
22
-
23
- /** Currently selected indicator */
24
- const indicator = ref("");
25
-
26
- /**
27
- * Current map position
28
- *
29
- * @type {import("vue").Ref<(number | undefined)[]>}
30
- */
31
- const mapPosition = ref([]);
32
-
33
- const registeredProjections = ["EPSG:4326", "EPSG:3857"];
34
-
35
- /** available projection to be rendered by `EodashMap` */
36
- const availableMapProjection = ref("EPSG:3857");
37
-
38
- /** @type {import("vue").Ref<HTMLElement & Record<string,any> | null>} */
39
- const mapEl = ref(null);
40
-
41
- /** @type {import("vue").Ref<HTMLElement & Record<string,any> | null>} */
42
- const mapCompareEl = ref(null);
43
-
44
- const __vite_glob_0_1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
45
- __proto__: null,
46
- availableMapProjection,
47
- currentCompareUrl,
48
- currentUrl,
49
- datetime,
50
- indicator,
51
- mapCompareEl,
52
- mapEl,
53
- mapPosition,
54
- registeredProjections
55
- }, Symbol.toStringTag, { value: 'Module' }));
56
-
57
11
  function bind(fn, thisArg) {
58
12
  return function wrap() {
59
13
  return fn.apply(thisArg, arguments);
@@ -1205,7 +1159,7 @@ function encode(val) {
1205
1159
  *
1206
1160
  * @param {string} url The base of the url (e.g., http://www.google.com)
1207
1161
  * @param {object} [params] The params to be appended
1208
- * @param {?object} options
1162
+ * @param {?(object|Function)} options
1209
1163
  *
1210
1164
  * @returns {string} The formatted url
1211
1165
  */
@@ -1217,6 +1171,12 @@ function buildURL(url, params, options) {
1217
1171
 
1218
1172
  const _encode = options && options.encode || encode;
1219
1173
 
1174
+ if (utils$1.isFunction(options)) {
1175
+ options = {
1176
+ serialize: options
1177
+ };
1178
+ }
1179
+
1220
1180
  const serializeFn = options && options.serialize;
1221
1181
 
1222
1182
  let serializedParams;
@@ -2199,68 +2159,18 @@ const progressEventDecorator = (total, throttled) => {
2199
2159
 
2200
2160
  const asyncDecorator = (fn) => (...args) => utils$1.asap(() => fn(...args));
2201
2161
 
2202
- const isURLSameOrigin = platform.hasStandardBrowserEnv ?
2203
-
2204
- // Standard browser envs have full support of the APIs needed to test
2205
- // whether the request URL is of the same origin as current location.
2206
- (function standardBrowserEnv() {
2207
- const msie = platform.navigator && /(msie|trident)/i.test(platform.navigator.userAgent);
2208
- const urlParsingNode = document.createElement('a');
2209
- let originURL;
2210
-
2211
- /**
2212
- * Parse a URL to discover its components
2213
- *
2214
- * @param {String} url The URL to be parsed
2215
- * @returns {Object}
2216
- */
2217
- function resolveURL(url) {
2218
- let href = url;
2219
-
2220
- if (msie) {
2221
- // IE needs attribute set twice to normalize properties
2222
- urlParsingNode.setAttribute('href', href);
2223
- href = urlParsingNode.href;
2224
- }
2225
-
2226
- urlParsingNode.setAttribute('href', href);
2227
-
2228
- // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
2229
- return {
2230
- href: urlParsingNode.href,
2231
- protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
2232
- host: urlParsingNode.host,
2233
- search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
2234
- hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
2235
- hostname: urlParsingNode.hostname,
2236
- port: urlParsingNode.port,
2237
- pathname: (urlParsingNode.pathname.charAt(0) === '/') ?
2238
- urlParsingNode.pathname :
2239
- '/' + urlParsingNode.pathname
2240
- };
2241
- }
2242
-
2243
- originURL = resolveURL(window.location.href);
2244
-
2245
- /**
2246
- * Determine if a URL shares the same origin as the current location
2247
- *
2248
- * @param {String} requestURL The URL to test
2249
- * @returns {boolean} True if URL shares the same origin, otherwise false
2250
- */
2251
- return function isURLSameOrigin(requestURL) {
2252
- const parsed = (utils$1.isString(requestURL)) ? resolveURL(requestURL) : requestURL;
2253
- return (parsed.protocol === originURL.protocol &&
2254
- parsed.host === originURL.host);
2255
- };
2256
- })() :
2162
+ const isURLSameOrigin = platform.hasStandardBrowserEnv ? ((origin, isMSIE) => (url) => {
2163
+ url = new URL(url, platform.origin);
2257
2164
 
2258
- // Non standard browser envs (web workers, react-native) lack needed support.
2259
- (function nonStandardBrowserEnv() {
2260
- return function isURLSameOrigin() {
2261
- return true;
2262
- };
2263
- })();
2165
+ return (
2166
+ origin.protocol === url.protocol &&
2167
+ origin.host === url.host &&
2168
+ (isMSIE || origin.port === url.port)
2169
+ );
2170
+ })(
2171
+ new URL(platform.origin),
2172
+ platform.navigator && /(msie|trident)/i.test(platform.navigator.userAgent)
2173
+ ) : () => true;
2264
2174
 
2265
2175
  const cookies = platform.hasStandardBrowserEnv ?
2266
2176
 
@@ -2362,7 +2272,7 @@ function mergeConfig(config1, config2) {
2362
2272
  config2 = config2 || {};
2363
2273
  const config = {};
2364
2274
 
2365
- function getMergedValue(target, source, caseless) {
2275
+ function getMergedValue(target, source, prop, caseless) {
2366
2276
  if (utils$1.isPlainObject(target) && utils$1.isPlainObject(source)) {
2367
2277
  return utils$1.merge.call({caseless}, target, source);
2368
2278
  } else if (utils$1.isPlainObject(source)) {
@@ -2374,11 +2284,11 @@ function mergeConfig(config1, config2) {
2374
2284
  }
2375
2285
 
2376
2286
  // eslint-disable-next-line consistent-return
2377
- function mergeDeepProperties(a, b, caseless) {
2287
+ function mergeDeepProperties(a, b, prop , caseless) {
2378
2288
  if (!utils$1.isUndefined(b)) {
2379
- return getMergedValue(a, b, caseless);
2289
+ return getMergedValue(a, b, prop , caseless);
2380
2290
  } else if (!utils$1.isUndefined(a)) {
2381
- return getMergedValue(undefined, a, caseless);
2291
+ return getMergedValue(undefined, a, prop , caseless);
2382
2292
  }
2383
2293
  }
2384
2294
 
@@ -2436,7 +2346,7 @@ function mergeConfig(config1, config2) {
2436
2346
  socketPath: defaultToConfig2,
2437
2347
  responseEncoding: defaultToConfig2,
2438
2348
  validateStatus: mergeDirectKeys,
2439
- headers: (a, b) => mergeDeepProperties(headersToObject(a), headersToObject(b), true)
2349
+ headers: (a, b , prop) => mergeDeepProperties(headersToObject(a), headersToObject(b),prop, true)
2440
2350
  };
2441
2351
 
2442
2352
  utils$1.forEach(Object.keys(Object.assign({}, config1, config2)), function computeConfigValue(prop) {
@@ -3178,7 +3088,7 @@ function dispatchRequest(config) {
3178
3088
  });
3179
3089
  }
3180
3090
 
3181
- const VERSION = "1.7.7";
3091
+ const VERSION = "1.7.9";
3182
3092
 
3183
3093
  const validators$1 = {};
3184
3094
 
@@ -3229,6 +3139,14 @@ validators$1.transitional = function transitional(validator, version, message) {
3229
3139
  };
3230
3140
  };
3231
3141
 
3142
+ validators$1.spelling = function spelling(correctSpelling) {
3143
+ return (value, opt) => {
3144
+ // eslint-disable-next-line no-console
3145
+ console.warn(`${opt} is likely a misspelling of ${correctSpelling}`);
3146
+ return true;
3147
+ }
3148
+ };
3149
+
3232
3150
  /**
3233
3151
  * Assert object's properties type
3234
3152
  *
@@ -3298,9 +3216,9 @@ class Axios {
3298
3216
  return await this._request(configOrUrl, config);
3299
3217
  } catch (err) {
3300
3218
  if (err instanceof Error) {
3301
- let dummy;
3219
+ let dummy = {};
3302
3220
 
3303
- Error.captureStackTrace ? Error.captureStackTrace(dummy = {}) : (dummy = new Error());
3221
+ Error.captureStackTrace ? Error.captureStackTrace(dummy) : (dummy = new Error());
3304
3222
 
3305
3223
  // slice off the Error: ... line
3306
3224
  const stack = dummy.stack ? dummy.stack.replace(/^.+\n/, '') : '';
@@ -3355,6 +3273,11 @@ class Axios {
3355
3273
  }
3356
3274
  }
3357
3275
 
3276
+ validator.assertOptions(config, {
3277
+ baseUrl: validators.spelling('baseURL'),
3278
+ withXsrfToken: validators.spelling('withXSRFToken')
3279
+ }, true);
3280
+
3358
3281
  // Set config.method
3359
3282
  config.method = (config.method || this.defaults.method || 'get').toLowerCase();
3360
3283
 
@@ -3792,440 +3715,54 @@ const instance = axios$1.create();
3792
3715
 
3793
3716
  const axios = setupCache(instance, { cacheTakeover: false });
3794
3717
 
3795
- /** @param {import("stac-ts").StacLink[]} [links] */
3796
- function generateFeatures(links) {
3797
- /**
3798
- * @type {import("geojson").Feature[]}
3799
- */
3800
- const features = [];
3801
- links?.forEach((element) => {
3802
- if (element.rel === "item" && "latlng" in element) {
3803
- const [lat, lon] = /** @type {string} */ (element.latlng)
3804
- .split(",")
3805
- .map((it) => Number(it));
3806
- features.push({
3807
- type: "Feature",
3808
- geometry: {
3809
- type: "Point",
3810
- coordinates: [lon, lat],
3811
- },
3812
- properties: { id: element.id },
3813
- });
3814
- }
3815
- });
3816
- const geojsonObject = {
3817
- type: "FeatureCollection",
3818
- crs: {
3819
- type: "name",
3820
- properties: {
3821
- name: "EPSG:4326",
3822
- },
3823
- },
3824
- features,
3825
- };
3826
- return geojsonObject;
3827
- }
3718
+ /** setting default log level globally to warning */
3719
+ log.setLevel(log.levels.WARN, true);
3828
3720
 
3829
- /** @param { import("ol/layer/WebGLTile").Style & { jsonform?: Record<string,any> } & { legend?: Record<string,any> } } [style] */
3830
- function extractLayerConfig(style) {
3831
- /** @type {Record<string,unknown> | undefined} */
3832
- let layerConfig = undefined;
3833
- if (style?.jsonform) {
3834
- layerConfig = { schema: style.jsonform, type: "style" };
3835
- style = { ...style };
3836
- delete style.jsonform;
3837
- if (style?.legend) {
3838
- layerConfig.legend = style.legend;
3839
- delete style.legend;
3840
- }
3841
- }
3842
- log.debug(
3843
- "extracted layerConfig",
3844
- JSON.parse(JSON.stringify({ layerConfig, style })),
3845
- );
3721
+ /** Currently selected STAC endpoint */
3722
+ const currentUrl = ref("");
3846
3723
 
3847
- return { layerConfig, style };
3848
- }
3724
+ /** Currently selected compare STAC endpoint */
3725
+ const currentCompareUrl = ref("");
3849
3726
 
3850
- /**
3851
- * checks if there's a projection on the Collection and
3852
- * updates {@link availableMapProjection}
3853
- * @param {import('stac-ts').StacCollection} [STAcCollection]
3854
- */
3855
- const setMapProjFromCol = async (STAcCollection) => {
3856
- // if a projection exists on the collection level
3857
- log.debug("Checking for available map projection in indicator");
3858
- const projection =
3859
- /** @type {number | string | {name: string, def: string} | undefined} */
3860
- (
3861
- STAcCollection?.["eodash:mapProjection"] ||
3862
- STAcCollection?.["proj:epsg"] ||
3863
- STAcCollection?.["eodash:proj4_def"]
3864
- );
3865
- if (projection) {
3866
- log.debug("Projection found", projection);
3867
- await registerProjection(projection);
3868
- const projectionCode = getProjectionCode(projection);
3869
- if (availableMapProjection.value !== projectionCode) {
3870
- log.debug(
3871
- "Changing map projection",
3872
- availableMapProjection.value,
3873
- projectionCode,
3874
- );
3875
- await changeMapProjection(projection);
3876
- }
3877
- // set it for `EodashMapBtns`
3878
- availableMapProjection.value = /** @type {string} */ (projectionCode);
3879
- } else {
3880
- // reset to default projection
3881
- log.debug("Resetting projection to default EPSG:3857");
3882
- await changeMapProjection((availableMapProjection.value = ""));
3883
- }
3884
- };
3727
+ /** Currently selected datetime */
3728
+ const datetime = ref(new Date().toISOString());
3729
+
3730
+ /** Currently selected indicator */
3731
+ const indicator = ref("");
3885
3732
 
3886
3733
  /**
3887
- * Function to extract collection urls from an indicator
3888
- * @param {import("stac-ts").StacCatalog
3889
- * | import("stac-ts").StacCollection
3890
- * | import("stac-ts").StacItem
3891
- * | null
3892
- * } stacObject
3893
- * @param {string} basepath
3894
- * @returns {string[]}
3734
+ * Current map position
3735
+ *
3736
+ * @type {import("vue").Ref<(number | undefined)[]>}
3895
3737
  */
3896
- function extractCollectionUrls(stacObject, basepath) {
3897
- const collectionUrls = [];
3898
- // Support for two structure types, flat and indicator, simplified here:
3899
- // Flat assumes Catalog-Collection-Item
3900
- // Indicator assumes Catalog-Collection-Collection-Item
3901
- // TODO: this is not the most stable test approach,
3902
- // we should discuss potential other approaches
3903
- if (stacObject?.links && stacObject?.links[1]?.rel === "item") {
3904
- collectionUrls.push(basepath);
3905
- } else if (stacObject?.links[1]?.rel === "child") {
3906
- // TODO: Iterate through all children to create collections
3907
- stacObject.links.forEach((link) => {
3908
- if (link.rel === "child") {
3909
- collectionUrls.push(toAbsolute(link.href, basepath));
3910
- }
3911
- });
3912
- }
3913
- return collectionUrls;
3914
- }
3738
+ const mapPosition = ref([]);
3915
3739
 
3916
- /**
3917
- * Assign extracted roles to layer properties
3918
- * @param {Record<string,any>} properties
3919
- * @param {import("stac-ts").StacLink | import("stac-ts").StacAsset} linkOrAsset
3920
- * */
3921
- const extractRoles = (properties, linkOrAsset) => {
3922
- const roles = /** @type {string[]} */ (linkOrAsset.roles);
3923
- roles?.forEach((role) => {
3924
- if (role === "visible") {
3925
- properties.visible = true;
3926
- }
3927
- if (role === "overlay" || role === "baselayer") {
3928
- properties.group = role;
3929
- //remove all the properties and replace the random ID with baselayer
3930
- // provided ID
3931
- // const [_colId, _itemId, _isAsset, _random, proj] =
3932
- // properties.id.split(";:;");
3933
- // properties.id = ["", "", "", "", linkOrAsset.id, proj].join(";:;");
3934
- }
3740
+ const registeredProjections = ["EPSG:4326", "EPSG:3857"];
3935
3741
 
3936
- return properties;
3937
- });
3938
- };
3742
+ /** available projection to be rendered by `EodashMap` */
3743
+ const availableMapProjection = ref("EPSG:3857");
3939
3744
 
3940
- /**
3941
- * @param {import("stac-ts").StacItem} item
3942
- * @param {string} itemUrl
3943
- **/
3944
- const fetchStyle = async (item, itemUrl) => {
3945
- const styleLink = item.links.find((link) => link.rel.includes("style"));
3946
- if (styleLink) {
3947
- let url = "";
3948
- if (styleLink.href.startsWith("http")) {
3949
- url = styleLink.href;
3950
- } else {
3951
- url = toAbsolute(styleLink.href, itemUrl);
3952
- }
3745
+ /** @type {import("vue").Ref<HTMLElement & Record<string,any> | null>} */
3746
+ const mapEl = ref(null);
3953
3747
 
3954
- /** @type {import("ol/layer/WebGLTile").Style & {jsonform?:Record<string,any>}} */
3955
- const styleJson = await axios.get(url).then((resp) => resp.data);
3748
+ /** @type {import("vue").Ref<HTMLElement & Record<string,any> | null>} */
3749
+ const mapCompareEl = ref(null);
3956
3750
 
3957
- log.debug("fetched styles JSON", JSON.parse(JSON.stringify(styleJson)));
3958
- return { ...styleJson };
3959
- }
3960
- };
3751
+ const activeTemplate = ref("");
3961
3752
 
3962
- /**
3963
- * Return projection code which is to be registered in `eox-map`
3964
- * @param {string|number|{name: string, def: string}} [projection]
3965
- * @returns {string}
3966
- */
3967
- const getProjectionCode = (projection) => {
3968
- let code = projection;
3969
- switch (typeof projection) {
3970
- case "number":
3971
- code = `EPSG:${projection}`;
3972
- break;
3973
- case "string":
3974
- code = projection;
3975
- break;
3976
- case "object":
3977
- code = projection?.name;
3978
- }
3979
- return /** @type {string} */ (code);
3980
- };
3981
-
3982
- /**
3983
- * @param {import("stac-ts").StacLink[]} [links]
3984
- * @param {string|null} [currentStep]
3985
- **/
3986
- const extractLayerDatetime = (links, currentStep) => {
3987
- if (!currentStep || !links?.length) {
3988
- return undefined;
3989
- }
3990
-
3991
- // check if links has a datetime value
3992
- const hasDatetime = links.some((l) => typeof l.datetime === "string");
3993
- if (!hasDatetime) {
3994
- return undefined;
3995
- }
3996
-
3997
- /** @type {string[]} */
3998
- const controlValues = [];
3999
- try {
4000
- currentStep = new Date(currentStep).toISOString();
4001
-
4002
- links.reduce((vals, link) => {
4003
- if (link.datetime && link.rel === "item") {
4004
- vals.push(
4005
- new Date(/** @type {string} */ (link.datetime)).toISOString(),
4006
- );
4007
- }
4008
- return vals;
4009
- }, controlValues);
4010
- } catch (e) {
4011
- console.warn("[eodash] not supported datetime format was provided", e);
4012
- return undefined;
4013
- }
4014
- // not enough controlValues
4015
- if (controlValues.length <= 1) {
4016
- return undefined;
4017
- }
4018
-
4019
- // item datetime is not included in the item links datetime
4020
- if (!controlValues.includes(currentStep)) {
4021
- return undefined;
4022
- }
4023
-
4024
- return {
4025
- controlValues,
4026
- currentStep,
4027
- slider: true,
4028
- disablePlay: true,
4029
- };
4030
- };
4031
-
4032
- /**
4033
- * Find layer by ID
4034
- * @param {string} layer
4035
- * @param {Record<string, any>[]} layers
4036
- * @returns {Record<string,any> | undefined}
4037
- **/
4038
- const findLayer = (layers, layer) => {
4039
- for (const lyr of layers) {
4040
- if (lyr.type === "Group") {
4041
- const found = findLayer(lyr.layers, layer);
4042
- if (!found) {
4043
- continue;
4044
- }
4045
- return found;
4046
- }
4047
- if (lyr.properties.id === layer) {
4048
- return lyr;
4049
- }
4050
- }
4051
- };
4052
-
4053
- /**
4054
- * @param {Record<string,any>[]} currentLayers
4055
- * @param {Record<string,any>} oldLayer
4056
- * @param {Record<string,any>[]} newLayers
4057
- * @returns {Record<string,any>[] | undefined}
4058
- */
4059
- const replaceLayer = (currentLayers, oldLayer, newLayers) => {
4060
- const oldLayerIdx = currentLayers.findIndex(
4061
- (l) => l.properties.id === oldLayer.properties.id,
4062
- );
4063
- if (oldLayerIdx !== -1) {
4064
- currentLayers.splice(oldLayerIdx, 1, ...newLayers);
4065
- return currentLayers;
4066
- }
4067
-
4068
- for (const l of currentLayers) {
4069
- if (l.type === "Group") {
4070
- const updatedGroupLyrs = replaceLayer(l.layers, oldLayer, newLayers);
4071
- if (updatedGroupLyrs?.length) {
4072
- l.layers = updatedGroupLyrs;
4073
- return currentLayers;
4074
- }
4075
- }
4076
- }
4077
- };
4078
- /**
4079
- * @param {import('./eodashSTAC.js').EodashCollection[]} indicators
4080
- * @param {import('ol/layer').Layer} layer
4081
- */
4082
- const getColFromLayer = async (indicators, layer) => {
4083
- // init cols
4084
- const collections = await Promise.all(
4085
- indicators.map((ind) => ind.fetchCollection()),
4086
- );
4087
- const [collectionId, itemId, ..._other] = layer.get("id").split(";:;");
4088
-
4089
- const chosen = collections.find((col) => {
4090
- const isInd =
4091
- col.id === collectionId &&
4092
- col.links?.some(
4093
- (link) => link.rel === "item" && link.href.includes(itemId),
4094
- );
4095
- return isInd ?? false;
4096
- });
4097
- return indicators.find((ind) => ind.collectionStac?.id === chosen?.id);
4098
- };
4099
-
4100
- /**
4101
- * generates layer specific ID, related functions are: {@link assignProjID} & {@link extractRoles}
4102
- * @param {string} collectionId
4103
- * @param {string} itemId
4104
- * @param {import('stac-ts').StacLink} link
4105
- * @param {string} projectionCode
4106
- *
4107
- */
4108
- const createLayerID = (collectionId, itemId, link, projectionCode) => {
4109
- const linkId = link.id || link.title || link.href;
4110
- let lId = `${collectionId ?? ""};:;${itemId ?? ""};:;${linkId ?? ""};:;${projectionCode ?? ""}`;
4111
- // If we are looking at base layers and overlays we remove the collection and item part
4112
- // as we want to make sure tiles are not reloaded when switching layers
4113
- if (
4114
- link.roles &&
4115
- // @ts-expect-error it seems roles it not defined for links yet
4116
- link.roles.find((r) => ["baselayer", "overlay"].includes(r))
4117
- ) {
4118
- lId = `${linkId ?? ""};:;${projectionCode ?? ""}`;
4119
- }
4120
- log.debug("Generated Layer ID", lId);
4121
- return lId;
4122
- };
4123
-
4124
- /**
4125
- * generates layer specific ID, related functions are: {@link assignProjID} & {@link extractRoles}
4126
- * @param {string} collectionId
4127
- * @param {string} itemId
4128
- * @param {number} index
4129
- *
4130
- */
4131
- const createAssetID = (collectionId, itemId, index) => {
4132
- let lId = `${collectionId ?? ""};:;${itemId ?? ""};:;${index ?? ""}`;
4133
- log.debug("Generated Asset ID", lId);
4134
- return lId;
4135
- };
4136
-
4137
- /**
4138
- * creates a structured clone from the layers and
4139
- * removes all properties from the clone
4140
- * except the ID and title
4141
- *
4142
- * @param {Record<string,any>[]} layers
4143
- */
4144
- const removeUnneededProperties = (layers) => {
4145
- const cloned = structuredClone(layers);
4146
- cloned.forEach((layer) => {
4147
- const id = layer.properties.id;
4148
- const title = layer.properties.title;
4149
- layer.properties = { id, title };
4150
- if (layer["interactions"]) {
4151
- delete layer["interactions"];
4152
- }
4153
- if (layer.type === "Group") {
4154
- layer.layers = removeUnneededProperties(layer.layers);
4155
- }
4156
- });
4157
- return cloned;
4158
- };
4159
-
4160
- /**
4161
- * Returns the current layers of {@link mapEl}
4162
- * @returns {Record<string,any>[]}
4163
- */
4164
- const getLayers = () => mapEl.value?.layers.toReversed();
4165
-
4166
- /**
4167
- * Returns the current layers of {@link mapCompareEl}
4168
- * @returns {Record<string,any>[]}
4169
- */
4170
- const getCompareLayers = () => mapCompareEl.value?.layers.toReversed();
4171
-
4172
- /**
4173
- * Register EPSG projection in `eox-map`
4174
- * @param {string|number|{name: string, def: string, extent?:number[]}} [projection]*/
4175
- const registerProjection = async (projection) => {
4176
- let code = getProjectionCode(projection);
4177
- if (!code || registeredProjections.includes(code)) {
4178
- return;
4179
- }
4180
- log.debug("Unregistered projection found, registering it", code);
4181
- registeredProjections.push(code);
4182
- if (typeof projection === "object") {
4183
- // registering whole projection definition
4184
- await mapEl.value?.registerProjection(
4185
- code,
4186
- projection.def,
4187
- projection.extent,
4188
- );
4189
- // also registering for comparison map
4190
- await mapCompareEl.value?.registerProjection(
4191
- code,
4192
- projection.def,
4193
- projection.extent,
4194
- );
4195
- } else {
4196
- await mapEl.value?.registerProjectionFromCode(code);
4197
- // also registering for comparison map
4198
- await mapCompareEl.value?.registerProjectionFromCode(code);
4199
- }
4200
- };
4201
- /**
4202
- * Change `eox-map` projection from an `EPSG` projection
4203
- * @param {string|number|{name: string, def: string}} [projection]*/
4204
- const changeMapProjection = async (projection) => {
4205
- let code = getProjectionCode(projection);
4206
-
4207
- if (!code) {
4208
- mapEl.value?.setAttribute("projection", "EPSG:3857");
4209
- mapCompareEl.value?.setAttribute("projection", "EPSG:3857");
4210
- return;
4211
- }
4212
-
4213
- if (!registeredProjections.includes(code)) {
4214
- await registerProjection(projection);
4215
- }
4216
-
4217
- code = mapEl.value?.getAttribute("projection") === code ? "EPSG:3857" : code;
4218
- mapEl.value?.setAttribute("projection", code);
4219
- mapCompareEl.value?.setAttribute("projection", code);
4220
- };
4221
-
4222
- const __vite_glob_0_0 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
4223
- __proto__: null,
4224
- changeMapProjection,
4225
- getCompareLayers,
4226
- getLayers,
4227
- registerProjection
4228
- }, Symbol.toStringTag, { value: 'Module' }));
3753
+ const states = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
3754
+ __proto__: null,
3755
+ activeTemplate,
3756
+ availableMapProjection,
3757
+ currentCompareUrl,
3758
+ currentUrl,
3759
+ datetime,
3760
+ indicator,
3761
+ mapCompareEl,
3762
+ mapEl,
3763
+ mapPosition,
3764
+ registeredProjections
3765
+ }, Symbol.toStringTag, { value: 'Module' }));
4229
3766
 
4230
3767
  /**
4231
3768
  * Reactive Edoash Instance Object. provided globally in the app, and used as an
@@ -4236,181 +3773,423 @@ const __vite_glob_0_0 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.definePro
4236
3773
  const eodash = reactive({
4237
3774
  id: "demo",
4238
3775
  stacEndpoint:
4239
- // "https://eodashcatalog.eox.at/test-style/trilateral/catalog.json",
3776
+ // "https://eurodatacube.github.io/eodash-catalog/RACE/catalog.json",
4240
3777
  // "https://gtif-cerulean.github.io/catalog/cerulean/catalog.json",
4241
- "https://santilland.github.io/process_example/catalog.json",
3778
+ "https://eodashcatalog.eox.at/samplecatalog/samples/catalog.json",
3779
+ // "https://eodashcatalog.eox.at/test-style/trilateral/catalog.json",
3780
+ // "https://gtif-cerulean.github.io/catalog/cerulean/catalog.json",
4242
3781
  brand: {
4243
3782
  noLayout: true,
4244
3783
  name: "Demo",
4245
3784
  theme: {
4246
3785
  colors: {
4247
- primary: "#fff",
4248
- secondary: "#fff",
4249
- surface: "#fff",
3786
+ primary: "#002742",
3787
+ secondary: "#0071C2",
3788
+ surface: "#ffff",
3789
+ },
3790
+ variables: {
3791
+ "surface-opacity": 0.6,
3792
+ "primary-opacity": 0.8,
4250
3793
  },
4251
3794
  },
4252
3795
  footerText: "Demo configuration of eodash client",
4253
3796
  },
4254
- template: {
4255
- loading: {
4256
- id: Symbol(),
4257
- type: "web-component",
4258
- widget: {
4259
- // https://uiball.com/ldrs/
4260
- link: "https://cdn.jsdelivr.net/npm/ldrs/dist/auto/mirage.js",
4261
- tagName: "l-mirage",
4262
- properties: {
4263
- class: "align-self-center justify-self-center",
4264
- size: "120",
4265
- speed: "2.5",
4266
- color: "#004170",
3797
+ templates: {
3798
+ light: {
3799
+ gap: 16,
3800
+ loading: {
3801
+ id: Symbol(),
3802
+ type: "web-component",
3803
+ widget: {
3804
+ // https://uiball.com/ldrs/
3805
+ link: "https://cdn.jsdelivr.net/npm/ldrs/dist/auto/mirage.js",
3806
+ tagName: "l-mirage",
3807
+ properties: {
3808
+ class: "align-self-center justify-self-center",
3809
+ size: "120",
3810
+ speed: "2.5",
3811
+ color: "#004170",
3812
+ },
4267
3813
  },
4268
3814
  },
4269
- },
4270
- background: {
4271
- id: Symbol(),
4272
- type: "internal",
4273
- widget: {
4274
- name: "EodashMap",
4275
- properties: {
4276
- enableCompare: true,
3815
+ background: {
3816
+ id: Symbol(),
3817
+ type: "internal",
3818
+ widget: {
3819
+ name: "EodashMap",
3820
+ properties: {
3821
+ enableCompare: true,
3822
+ },
4277
3823
  },
4278
3824
  },
3825
+ widgets: [
3826
+ {
3827
+ id: Symbol(),
3828
+ type: "internal",
3829
+ title: "Tools",
3830
+ layout: { x: 0, y: 0, w: 3, h: 1 },
3831
+ widget: {
3832
+ name: "EodashTools",
3833
+ properties: {
3834
+ layoutTarget: "expert",
3835
+ layoutIcon: mdiViewDashboardVariant,
3836
+ itemFilterConfig: {
3837
+ resultType: "cards",
3838
+ filtersTitle: "",
3839
+ style: "--padding: 72px",
3840
+ filterProperties: [],
3841
+ resultsTitle: "Explore more indicators",
3842
+ subTitleProperty: "subtitle",
3843
+ imageProperty: "thumbnail",
3844
+ },
3845
+ },
3846
+ },
3847
+ },
3848
+ {
3849
+ defineWidget: (selectedSTAC) => {
3850
+ return selectedSTAC
3851
+ ? {
3852
+ id: "layercontrol-light",
3853
+ type: "internal",
3854
+ title: "Layers",
3855
+ layout: { x: 0, y: 1, w: 3, h: 3 },
3856
+ widget: {
3857
+ name: "EodashLayerControl",
3858
+ properties: {
3859
+ slider: false,
3860
+ tools: ["datetime", "info", "legend"],
3861
+ cssVars: {
3862
+ "--list-padding": "0",
3863
+ "--tools-button-visibility": "none",
3864
+ "--layer-input-visibility": "none",
3865
+ "--layer-type-visibility": "none",
3866
+ "--padding": "16px",
3867
+ "--padding-vertical": "16px",
3868
+ "--layer-tools-button-visibility": "none",
3869
+ "--layer-summary-visibility": "none",
3870
+ },
3871
+ },
3872
+ },
3873
+ }
3874
+ : null;
3875
+ },
3876
+ },
3877
+ {
3878
+ defineWidget: (selectedSTAC) => {
3879
+ return selectedSTAC
3880
+ ? {
3881
+ id: "stacinfo-light",
3882
+ type: "internal",
3883
+ title: "Information",
3884
+ layout: { x: 9, y: 0, w: 3, h: 6 },
3885
+ widget: {
3886
+ name: "EodashStacInfo",
3887
+ properties: {
3888
+ tags: [],
3889
+ header: [],
3890
+ footer: [],
3891
+ body: ["description"],
3892
+ styleOverride: "",
3893
+ featured: [],
3894
+ },
3895
+ },
3896
+ }
3897
+ : null;
3898
+ },
3899
+ },
3900
+ {
3901
+ defineWidget: (selectedSTAC) => {
3902
+ return selectedSTAC
3903
+ ? {
3904
+ id: "Datepicker",
3905
+ type: "internal",
3906
+ layout: { x: 5, y: 8, w: 2, h: 4 },
3907
+ title: "Date",
3908
+ widget: {
3909
+ name: "EodashDatePicker",
3910
+ properties: {
3911
+ hideArrows: true,
3912
+ hideInputField: true,
3913
+ hintText: `<b>Hint:</b> closest available date is displayed <br />
3914
+ on map (see Analysis Layers)`,
3915
+ },
3916
+ },
3917
+ }
3918
+ : null;
3919
+ },
3920
+ },
3921
+ ],
4279
3922
  },
4280
- widgets: [
4281
- {
3923
+ expert: {
3924
+ loading: {
4282
3925
  id: Symbol(),
4283
- type: "internal",
4284
- title: "Indicators",
4285
- layout: { x: 0, y: 0, w: 3, h: 6 },
3926
+ type: "web-component",
4286
3927
  widget: {
4287
- name: "EodashItemFilter",
3928
+ // https://uiball.com/ldrs/
3929
+ link: "https://cdn.jsdelivr.net/npm/ldrs/dist/auto/mirage.js",
3930
+ tagName: "l-mirage",
4288
3931
  properties: {
4289
- enableCompare: true,
4290
- aggregateResults: "collection_group",
3932
+ class: "align-self-center justify-self-center",
3933
+ size: "120",
3934
+ speed: "2.5",
3935
+ color: "#004170",
4291
3936
  },
4292
3937
  },
4293
3938
  },
4294
- {
3939
+ background: {
4295
3940
  id: Symbol(),
4296
3941
  type: "internal",
4297
- title: "Layer Control",
4298
- layout: { x: 0, y: 6, w: 3, h: 6 },
4299
3942
  widget: {
4300
- name: "EodashLayerControl",
3943
+ name: "EodashMap",
3944
+ properties: {
3945
+ enableCompare: true,
3946
+ },
4301
3947
  },
4302
3948
  },
4303
- /*
4304
- {
4305
- defineWidget: (selectedCompareStac) => {
4306
- return selectedCompareStac
4307
- ? {
4308
- id: Symbol(),
4309
- title: "Layer Control Comparison",
4310
- layout: { x: 9, y: 6, w: 3, h: 6 },
4311
- type: "internal",
4312
- widget: {
4313
- name: "EodashLayerControl",
4314
- properties: {
4315
- map: "second",
4316
- },
3949
+ widgets: [
3950
+ {
3951
+ id: Symbol(),
3952
+ type: "internal",
3953
+ title: "Tools",
3954
+ layout: { x: 0, y: 0, w: 3, h: 1 },
3955
+ widget: {
3956
+ name: "EodashTools",
3957
+ properties: {
3958
+ layoutTarget: "light",
3959
+ layoutIcon: mdiViewDashboard,
3960
+ itemFilterConfig: {
3961
+ resultType: "cards",
3962
+ subTitleProperty: "subtitle",
3963
+ imageProperty: "thumbnail",
3964
+ aggregateResults: "collection_group",
3965
+ style: {
3966
+ "--form-flex-direction": "row",
4317
3967
  },
4318
- }
4319
- : null;
3968
+ },
3969
+ },
3970
+ },
4320
3971
  },
4321
- },
4322
- */
4323
- {
4324
- defineWidget: (selectedSTAC) => {
4325
- return selectedSTAC
4326
- ? {
4327
- id: "Information",
4328
- title: "Information",
4329
- layout: { x: 9, y: 0, w: 3, h: 6 },
4330
- type: "web-component",
4331
- widget: {
4332
- link: async () => await import('@eox/stacinfo'),
4333
- properties: {
4334
- for: currentUrl,
4335
- allowHtml: "true",
4336
- styleOverride: `.single-property {columns: 1!important;}
4337
- h1 {margin:0px!important;font-size:16px!important;}
4338
- header h1:after {
4339
- content:' ';
4340
- display:block;
4341
- border:1px solid #d0d0d0;
4342
- }
4343
- h2 {font-size:15px}
4344
- h3 {font-size:14px}
4345
- summary {cursor: pointer;}
4346
- #properties li > .value { font-weight: normal !important;}
4347
- main {padding-bottom: 10px;}
4348
- .footer-container {line-height:1;}
4349
- .footer-container button {margin-top: -10px;}
4350
- .footer-container small {font-size:10px;line-height:1;}`,
4351
- header: '["title"]',
4352
- tags: '["themes"]',
4353
- subheader: "[]",
4354
- properties: '["satellite","sensor","agency","extent"]',
4355
- featured: '["description","providers","assets","links"]',
4356
- footer: '["sci:citation"]',
3972
+ {
3973
+ id: Symbol(),
3974
+ type: "internal",
3975
+ title: "Layers",
3976
+ layout: { x: 0, y: 1, w: 3, h: 6 },
3977
+ widget: {
3978
+ name: "EodashLayerControl",
3979
+ },
3980
+ },
3981
+ {
3982
+ defineWidget: (selectedSTAC) => {
3983
+ return selectedSTAC
3984
+ ? {
3985
+ id: "Information",
3986
+ title: "Information",
3987
+ layout: { x: 9, y: 0, w: 3, h: 6 },
3988
+ type: "internal",
3989
+ widget: {
3990
+ name: "EodashStacInfo",
3991
+ properties: {
3992
+ showIndicatorsBtn: false,
3993
+ showLayoutSwitcher: false,
3994
+ },
4357
3995
  },
4358
- tagName: "eox-stacinfo",
4359
- },
4360
- }
4361
- : null;
3996
+ }
3997
+ : null;
3998
+ },
4362
3999
  },
4363
- },
4364
- {
4365
- defineWidget: (selectedSTAC) => {
4366
- return selectedSTAC
4367
- ? {
4368
- id: "Datepicker",
4369
- type: "internal",
4370
- layout: { x: 5, y: 10, w: 1, h: 1 },
4371
- title: "Datepicker",
4372
- widget: {
4373
- name: "EodashDatePicker",
4374
- properties: {
4375
- hintText: `<b>Hint:</b> closest available date is displayed <br />
4376
- on map (see Analysis Layers)`,
4000
+ {
4001
+ defineWidget: (selectedSTAC) => {
4002
+ return selectedSTAC
4003
+ ? {
4004
+ id: "Datepicker",
4005
+ type: "internal",
4006
+ layout: { x: 5, y: 8, w: 2, h: 4 },
4007
+ title: "Date",
4008
+ widget: {
4009
+ name: "EodashDatePicker",
4010
+ properties: {
4011
+ hintText: `<b>Hint:</b> closest available date is displayed <br />
4012
+ on map (see Analysis Layers)`,
4013
+ },
4377
4014
  },
4378
- },
4379
- }
4380
- : null;
4015
+ }
4016
+ : null;
4017
+ },
4018
+ },
4019
+ {
4020
+ defineWidget: (selected) => {
4021
+ return selected
4022
+ ? {
4023
+ id: "Buttons",
4024
+ layout: { x: 8, y: 0, w: 1, h: 2 },
4025
+ title: "Buttons",
4026
+ type: "internal",
4027
+ widget: {
4028
+ name: "EodashMapBtns",
4029
+ },
4030
+ }
4031
+ : null;
4032
+ },
4033
+ },
4034
+ {
4035
+ defineWidget: (selectedSTAC) =>
4036
+ selectedSTAC?.links.some((l) => l.rel === "service")
4037
+ ? {
4038
+ id: Symbol(),
4039
+ type: "internal",
4040
+ title: "Processes",
4041
+ layout: { x: 0, y: 7, w: 3, h: 5 },
4042
+ widget: {
4043
+ name: "EodashProcess",
4044
+ },
4045
+ }
4046
+ : null,
4047
+ },
4048
+ ],
4049
+ },
4050
+ compare: {
4051
+ gap: 16,
4052
+ loading: {
4053
+ id: Symbol(),
4054
+ type: "web-component",
4055
+ widget: {
4056
+ // https://uiball.com/ldrs/
4057
+ link: "https://cdn.jsdelivr.net/npm/ldrs/dist/auto/mirage.js",
4058
+ tagName: "l-mirage",
4059
+ properties: {
4060
+ class: "align-self-center justify-self-center",
4061
+ size: "120",
4062
+ speed: "2.5",
4063
+ color: "#004170",
4064
+ },
4381
4065
  },
4382
4066
  },
4383
- {
4384
- defineWidget: (selected) => {
4385
- return selected
4386
- ? {
4387
- id: "Buttons",
4388
- layout: { x: 8, y: 0, w: 1, h: 1 },
4389
- title: "Buttons",
4390
- type: "internal",
4391
- widget: {
4392
- name: "EodashMapBtns",
4393
- },
4394
- }
4395
- : null;
4067
+ background: {
4068
+ id: Symbol(),
4069
+ type: "internal",
4070
+ widget: {
4071
+ name: "EodashMap",
4072
+ properties: {
4073
+ enableCompare: true,
4074
+ },
4396
4075
  },
4397
4076
  },
4398
- {
4399
- defineWidget: (indicator) => {
4400
- return indicator
4401
- ? {
4402
- id: "process",
4403
- layout: { x: 9, y: 6, w: 3, h: 6 },
4404
- title: "Process",
4405
- type: "internal",
4406
- widget: {
4407
- name: "EodashProcess",
4077
+ widgets: [
4078
+ {
4079
+ id: Symbol(),
4080
+ type: "internal",
4081
+ title: "Tools",
4082
+ layout: { x: 0, y: 0, w: 3, h: 1 },
4083
+ widget: {
4084
+ name: "EodashTools",
4085
+ properties: {
4086
+ layoutTarget: "expert",
4087
+ layoutIcon: mdiViewDashboardVariant,
4088
+ itemFilterConfig: {
4089
+ cssVars: {
4090
+ "--form-flex-direction": "row",
4408
4091
  },
4409
- }
4410
- : null;
4092
+ },
4093
+ },
4094
+ },
4411
4095
  },
4412
- },
4413
- ],
4096
+ // compare indicators
4097
+ {
4098
+ id: Symbol(),
4099
+ type: "internal",
4100
+ title: "Tools",
4101
+ layout: { x: 9, y: 0, w: 3, h: 1 },
4102
+ widget: {
4103
+ name: "EodashTools",
4104
+ properties: {
4105
+ showLayoutSwitcher: false,
4106
+ indicatorBtnText: "Select an indicator to compare",
4107
+ itemFilterConfig: {
4108
+ enableCompare: true,
4109
+ // resultsTitle:"Select an indicator to compare",
4110
+ filtersTitle: "Select an indicator to compare",
4111
+ // filterProperties: [],
4112
+ cssVars: {
4113
+ "--form-flex-direction": "row",
4114
+ },
4115
+ },
4116
+ },
4117
+ },
4118
+ },
4119
+ {
4120
+ id: Symbol(),
4121
+ type: "internal",
4122
+ title: "Layers",
4123
+ layout: { x: 0, y: 1, w: 3, h: 6 },
4124
+ widget: {
4125
+ name: "EodashLayerControl",
4126
+ },
4127
+ },
4128
+ {
4129
+ id: Symbol(),
4130
+ title: "Comparison Layers",
4131
+ layout: { x: 9, y: 1, w: 3, h: 6 },
4132
+ type: "internal",
4133
+ widget: {
4134
+ name: "EodashLayerControl",
4135
+ properties: {
4136
+ map: "second",
4137
+ },
4138
+ },
4139
+ },
4140
+ {
4141
+ defineWidget: (selectedSTAC) =>
4142
+ selectedSTAC?.links.some((l) => l.rel === "service")
4143
+ ? {
4144
+ id: Symbol(),
4145
+ type: "internal",
4146
+ title: "Processes",
4147
+ layout: { x: 0, y: 7, w: 3, h: 5 },
4148
+ widget: {
4149
+ name: "EodashProcess",
4150
+ },
4151
+ }
4152
+ : null,
4153
+ },
4154
+ {
4155
+ defineWidget: (selected) => {
4156
+ return selected
4157
+ ? {
4158
+ id: "Buttons",
4159
+ layout: { x: 8, y: 0, w: 1, h: 2 },
4160
+ title: "Buttons",
4161
+ type: "internal",
4162
+ widget: {
4163
+ name: "EodashMapBtns",
4164
+ properties: {
4165
+ compareIndicators: false,
4166
+ },
4167
+ },
4168
+ }
4169
+ : null;
4170
+ },
4171
+ },
4172
+ {
4173
+ defineWidget: (selectedSTAC) => {
4174
+ return selectedSTAC
4175
+ ? {
4176
+ id: "Datepicker",
4177
+ type: "internal",
4178
+ layout: { x: 5, y: 8, w: 2, h: 4 },
4179
+ title: "Date",
4180
+ widget: {
4181
+ name: "EodashDatePicker",
4182
+ properties: {
4183
+ hintText: `<b>Hint:</b> closest available date is displayed <br />
4184
+ on map (see Analysis Layers)`,
4185
+ },
4186
+ },
4187
+ }
4188
+ : null;
4189
+ },
4190
+ },
4191
+ ],
4192
+ },
4414
4193
  },
4415
4194
  });
4416
4195
 
@@ -5556,6 +5335,11 @@ const en = {
5556
5335
  counter: '{0} files',
5557
5336
  counterSize: '{0} files ({1} in total)'
5558
5337
  },
5338
+ fileUpload: {
5339
+ title: 'Drag and drop files here',
5340
+ divider: 'or',
5341
+ browse: 'Browse Files'
5342
+ },
5559
5343
  timePicker: {
5560
5344
  am: 'AM',
5561
5345
  pm: 'PM',
@@ -6897,7 +6681,8 @@ const aliases = {
6897
6681
  calendar: 'mdi-calendar',
6898
6682
  treeviewCollapse: 'mdi-menu-down',
6899
6683
  treeviewExpand: 'mdi-menu-right',
6900
- eyeDropper: 'mdi-eyedropper'
6684
+ eyeDropper: 'mdi-eyedropper',
6685
+ upload: 'mdi-cloud-upload'
6901
6686
  };
6902
6687
  const mdi = {
6903
6688
  // Not using mergeProps here, functional components merge props by default (?)
@@ -7731,7 +7516,7 @@ function createVuetify() {
7731
7516
  goTo
7732
7517
  };
7733
7518
  }
7734
- const version = "3.7.5";
7519
+ const version = "3.7.6";
7735
7520
  createVuetify.version = version;
7736
7521
  function inject(key) {
7737
7522
  const vm = this.$;
@@ -7742,16 +7527,37 @@ function inject(key) {
7742
7527
  }
7743
7528
 
7744
7529
  /**
7745
- * `eodash` injection key.
7530
+ * `eodash` injection key.
7531
+ *
7532
+ * @see {@link "@/plugins/index.js"}
7533
+ */
7534
+ const eodashKey = Symbol("eodash");
7535
+ /** @type {import("@vueuse/core").EventBusKey<"layers:updated"|"time:updated">} */
7536
+ const eoxLayersKey = Symbol("eoxMapLayers");
7537
+
7538
+ /**
7539
+ * Array of eodash STAC Collections extracted from the current selected indicator.
7540
+ * Updated in {@link file://./../store/stac.js `loadSelectedSTAC`} widget
7541
+ *
7542
+ * @type {import('../eodashSTAC/EodashCollection').EodashCollection[]}
7543
+ * @private
7544
+ */
7545
+ const eodashCollections = shallowReactive([]);
7546
+
7547
+ /**
7548
+ * Array of eodash STAC Collections extracted from the current selected COMPARE indicator.
7549
+ * Updated in {@link file://./../store/stac.js ` loadSelectedCompareSTAC`} widget
7746
7550
  *
7747
- * @see {@link "@/plugins/index.js"}
7551
+ * @type {import('../eodashSTAC/EodashCollection').EodashCollection[]}
7552
+ * @private
7748
7553
  */
7749
- const eodashKey = Symbol("eodash");
7750
- /** @type {import("@vueuse/core").EventBusKey<"layers:updated"|"time:updated">} */
7751
- const eoxLayersKey = Symbol("eoxMapLayers");
7554
+ const eodashCompareCollections = shallowReactive([]);
7555
+
7556
+ /** whether the map postion was set in URL params on first load */
7557
+ const posIsSetFromUrl = ref(false);
7752
7558
 
7753
7559
  // functions of this folder can only be consumed inside setup stores,
7754
- // setup functions or vue composition api components
7560
+ // setup functions or vue composition api components https://vuejs.org/guide/reusability/composables
7755
7561
 
7756
7562
 
7757
7563
  /**
@@ -7761,11 +7567,11 @@ const eoxLayersKey = Symbol("eoxMapLayers");
7761
7567
  * @param {string} [base=eodash.stacEndpoint] - Base URL, default value is the
7762
7568
  * root stac catalog. Default is `eodash.stacEndpoint`
7763
7569
  * @returns {import("vue").Ref<string>} - Returns `currentUrl`
7764
- * @see {@link '@/store/States.js'}
7570
+ * @see {@link '@/store/states.js'}
7765
7571
  */
7766
7572
  const useAbsoluteUrl = (rel = "", base = eodash.stacEndpoint) => {
7767
7573
  if (!rel || rel.includes("http")) {
7768
- currentUrl.value = base;
7574
+ currentUrl.value = rel;
7769
7575
  return currentUrl;
7770
7576
  }
7771
7577
 
@@ -7790,7 +7596,7 @@ const useAbsoluteUrl = (rel = "", base = eodash.stacEndpoint) => {
7790
7596
  * @param {string} [base=eodash.stacEndpoint] - Base URL, default value is the
7791
7597
  * root stac catalog. Default is `eodash.stacEndpoint`
7792
7598
  * @returns {import("vue").Ref<string>} - Returns `currentUrl`
7793
- * @see {@link '@/store/States.js'}
7599
+ * @see {@link '@/store/states.js'}
7794
7600
  */
7795
7601
  const useCompareAbsoluteUrl = (rel = "", base = eodash.stacEndpoint) => {
7796
7602
  if (!rel || rel.includes("http")) {
@@ -7857,6 +7663,10 @@ const useURLSearchParametersSync = () => {
7857
7663
  z;
7858
7664
  for (const [key, value] of searchParams) {
7859
7665
  switch (key) {
7666
+ case "template": {
7667
+ activeTemplate.value = value;
7668
+ break;
7669
+ }
7860
7670
  case "indicator": {
7861
7671
  log.debug("Found indicator key in url");
7862
7672
  const { loadSelectedSTAC, stac } = useSTAcStore();
@@ -7892,82 +7702,504 @@ const useURLSearchParametersSync = () => {
7892
7702
  }
7893
7703
  }
7894
7704
 
7895
- if (x && y && z) {
7896
- log.debug("Coordinates found, applying map poisition", x, y, z);
7897
- mapPosition.value = [x, y, z];
7705
+ if (x && y && z) {
7706
+ log.debug("Coordinates found, applying map poisition", x, y, z);
7707
+ mapPosition.value = [x, y, z];
7708
+ if (!posIsSetFromUrl.value) {
7709
+ posIsSetFromUrl.value = true;
7710
+ }
7711
+ }
7712
+ }
7713
+
7714
+ watch(
7715
+ [indicator, mapPosition, datetime, activeTemplate],
7716
+ ([
7717
+ updatedIndicator,
7718
+ updatedMapPosition,
7719
+ updatedDatetime,
7720
+ updatedTemplate,
7721
+ ]) => {
7722
+ if ("URLSearchParams" in window) {
7723
+ const searchParams = new URLSearchParams(window.location.search);
7724
+ if (updatedIndicator !== "") {
7725
+ searchParams.set("indicator", updatedIndicator);
7726
+ }
7727
+
7728
+ if (updatedMapPosition && updatedMapPosition.length === 3) {
7729
+ searchParams.set("x", updatedMapPosition[0]?.toFixed(4) ?? "");
7730
+ searchParams.set("y", updatedMapPosition[1]?.toFixed(4) ?? "");
7731
+ searchParams.set("z", updatedMapPosition[2]?.toFixed(4) ?? "");
7732
+ }
7733
+
7734
+ if (updatedDatetime) {
7735
+ searchParams.set("datetime", updatedDatetime.split("T")?.[0] ?? "");
7736
+ }
7737
+ if (updatedTemplate) {
7738
+ searchParams.set("template", updatedTemplate);
7739
+ }
7740
+ const newRelativePathQuery =
7741
+ window.location.pathname + "?" + searchParams.toString();
7742
+ history.pushState(null, "", newRelativePathQuery);
7743
+ }
7744
+ },
7745
+ );
7746
+ });
7747
+ };
7748
+
7749
+ /**
7750
+ * Converts eox-layout-item to transparent
7751
+ *
7752
+ * @param {import("vue").Ref<HTMLElement|null>} root - components root element ref*/
7753
+ const makePanelTransparent = (root) => {
7754
+ onMounted(() => {
7755
+ const eoxItem = root.value?.parentElement;
7756
+ if (eoxItem?.tagName === "EOX-LAYOUT-ITEM") {
7757
+ eoxItem.classList.remove("bg-surface");
7758
+ }
7759
+ });
7760
+ };
7761
+
7762
+ /**
7763
+ * Listens to the `layers:updated` and `time:updated` events and calls
7764
+ *
7765
+ * @param {import("@vueuse/core").EventBusListener<
7766
+ * "layers:updated"|"time:updated",
7767
+ * {layers:Record<string,any>[]| undefined}
7768
+ * >} listener
7769
+ */
7770
+ const useOnLayersUpdate = (listener) => {
7771
+ const layersEvents = useEventBus(eoxLayersKey);
7772
+
7773
+ const unsubscribe = layersEvents.on(listener);
7774
+
7775
+ onUnmounted(() => {
7776
+ unsubscribe();
7777
+ });
7778
+ };
7779
+
7780
+ /** @param {import("stac-ts").StacLink[]} [links] */
7781
+ function generateFeatures(links) {
7782
+ /**
7783
+ * @type {import("geojson").Feature[]}
7784
+ */
7785
+ const features = [];
7786
+ links?.forEach((element) => {
7787
+ if (element.rel === "item" && "latlng" in element) {
7788
+ const [lat, lon] = /** @type {string} */ (element.latlng)
7789
+ .split(",")
7790
+ .map((it) => Number(it));
7791
+ features.push({
7792
+ type: "Feature",
7793
+ geometry: {
7794
+ type: "Point",
7795
+ coordinates: [lon, lat],
7796
+ },
7797
+ properties: { id: element.id },
7798
+ });
7799
+ }
7800
+ });
7801
+ const geojsonObject = {
7802
+ type: "FeatureCollection",
7803
+ crs: {
7804
+ type: "name",
7805
+ properties: {
7806
+ name: "EPSG:4326",
7807
+ },
7808
+ },
7809
+ features,
7810
+ };
7811
+ return geojsonObject;
7812
+ }
7813
+
7814
+ /**
7815
+ * Sperates and extracts layerConfig (jsonform schema & legend) from a style json
7816
+ *
7817
+ * @param { import("ol/layer/WebGLTile").Style & { jsonform?: Record<string,any> } & { legend?: Record<string,any> } } [style] */
7818
+ function extractLayerConfig(style) {
7819
+ /** @type {Record<string,unknown> | undefined} */
7820
+ let layerConfig = undefined;
7821
+ if (style?.jsonform) {
7822
+ layerConfig = { schema: style.jsonform, type: "style" };
7823
+ style = { ...style };
7824
+ delete style.jsonform;
7825
+ if (style?.legend) {
7826
+ layerConfig.legend = style.legend;
7827
+ delete style.legend;
7828
+ }
7829
+ }
7830
+ log.debug(
7831
+ "extracted layerConfig",
7832
+ JSON.parse(JSON.stringify({ layerConfig, style })),
7833
+ );
7834
+
7835
+ return { layerConfig, style };
7836
+ }
7837
+
7838
+ /**
7839
+ * Function to extract collection urls from an indicator
7840
+ * @param {import("stac-ts").StacCatalog
7841
+ * | import("stac-ts").StacCollection
7842
+ * | import("stac-ts").StacItem
7843
+ * | null
7844
+ * } stacObject
7845
+ * @param {string} basepath
7846
+ */
7847
+ function extractCollectionUrls(stacObject, basepath) {
7848
+ /** @type {string[]} */
7849
+ const collectionUrls = [];
7850
+ // Support for two structure types, flat and indicator, simplified here:
7851
+ // Flat assumes Catalog-Collection-Item
7852
+ // Indicator assumes Catalog-Collection-Collection-Item
7853
+
7854
+ const children = stacObject?.links?.filter(
7855
+ (link) => link.rel === "child" && link.type?.includes("json"),
7856
+ );
7857
+ if (!children?.length) {
7858
+ collectionUrls.push(basepath);
7859
+ return collectionUrls;
7860
+ }
7861
+ children.forEach((link) => {
7862
+ collectionUrls.push(toAbsolute(link.href, basepath));
7863
+ });
7864
+ return collectionUrls;
7865
+ }
7866
+
7867
+ /**
7868
+ * Assign extracted roles to layer properties
7869
+ * @param {Record<string,any>} properties
7870
+ * @param {import("stac-ts").StacLink | import("stac-ts").StacAsset} linkOrAsset
7871
+ * */
7872
+ const extractRoles = (properties, linkOrAsset) => {
7873
+ const roles = /** @type {string[]} */ (linkOrAsset.roles);
7874
+ roles?.forEach((role) => {
7875
+ if (role === "visible") {
7876
+ properties.visible = true;
7877
+ }
7878
+ if (role === "overlay" || role === "baselayer") {
7879
+ properties.group = role;
7880
+ }
7881
+
7882
+ return properties;
7883
+ });
7884
+ };
7885
+
7886
+ /**
7887
+ * Extracts style JSON from a STAC Item
7888
+ * @param {import("stac-ts").StacItem} item
7889
+ * @param {string} itemUrl
7890
+ * @returns
7891
+ **/
7892
+ const fetchStyle = async (item, itemUrl) => {
7893
+ const styleLink = item.links.find((link) => link.rel.includes("style"));
7894
+ if (styleLink) {
7895
+ let url = "";
7896
+ if (styleLink.href.startsWith("http")) {
7897
+ url = styleLink.href;
7898
+ } else {
7899
+ url = toAbsolute(styleLink.href, itemUrl);
7900
+ }
7901
+
7902
+ /** @type {import("ol/layer/WebGLTile").Style & {jsonform?:Record<string,any>}} */
7903
+ const styleJson = await axios.get(url).then((resp) => resp.data);
7904
+
7905
+ log.debug("fetched styles JSON", JSON.parse(JSON.stringify(styleJson)));
7906
+ return { ...styleJson };
7907
+ }
7908
+ };
7909
+
7910
+ /**
7911
+ * Return projection code which is to be registered in `eox-map`
7912
+ * @param {string|number|{name: string, def: string}} [projection]
7913
+ * @returns {string}
7914
+ */
7915
+ const getProjectionCode = (projection) => {
7916
+ let code = projection;
7917
+ switch (typeof projection) {
7918
+ case "number":
7919
+ code = `EPSG:${projection}`;
7920
+ break;
7921
+ case "string":
7922
+ code = projection;
7923
+ break;
7924
+ case "object":
7925
+ code = projection?.name;
7926
+ }
7927
+ return /** @type {string} */ (code);
7928
+ };
7929
+
7930
+ /**
7931
+ * Extracts layercontrol LayerDatetime property from STAC Links
7932
+ * @param {import("stac-ts").StacLink[]} [links]
7933
+ * @param {string|null} [currentStep]
7934
+ **/
7935
+ const extractLayerDatetime = (links, currentStep) => {
7936
+ if (!currentStep || !links?.length) {
7937
+ return undefined;
7938
+ }
7939
+
7940
+ // check if links has a datetime value
7941
+ // TODO: consider datetime ranges
7942
+ const hasDatetime = links.some((l) => typeof l.datetime === "string");
7943
+ if (!hasDatetime) {
7944
+ return undefined;
7945
+ }
7946
+
7947
+ /** @type {string[]} */
7948
+ const controlValues = [];
7949
+ try {
7950
+ currentStep = new Date(currentStep).toISOString();
7951
+
7952
+ links.reduce((vals, link) => {
7953
+ if (link.datetime && link.rel === "item") {
7954
+ vals.push(
7955
+ new Date(/** @type {string} */ (link.datetime)).toISOString(),
7956
+ );
7957
+ }
7958
+ return vals;
7959
+ }, controlValues);
7960
+ } catch (e) {
7961
+ console.warn("[eodash] not supported datetime format was provided", e);
7962
+ return undefined;
7963
+ }
7964
+ // not enough controlValues
7965
+ if (controlValues.length <= 1) {
7966
+ return undefined;
7967
+ }
7968
+
7969
+ // item datetime is not included in the item links datetime
7970
+ if (!controlValues.includes(currentStep)) {
7971
+ return undefined;
7972
+ }
7973
+
7974
+ return {
7975
+ controlValues,
7976
+ currentStep,
7977
+ slider: true,
7978
+ play: false,
7979
+ displayFormat: "DD MMMM YYYY",
7980
+ };
7981
+ };
7982
+
7983
+ /**
7984
+ * Find JSON layer by ID
7985
+ * @param {string} layer
7986
+ * @param {Record<string, any>[]} layers
7987
+ * @returns {Record<string,any> | undefined}
7988
+ **/
7989
+ const findLayer = (layers, layer) => {
7990
+ for (const lyr of layers) {
7991
+ if (lyr.type === "Group") {
7992
+ const found = findLayer(lyr.layers, layer);
7993
+ if (!found) {
7994
+ continue;
7898
7995
  }
7996
+ return found;
7899
7997
  }
7998
+ if (lyr.properties.id === layer) {
7999
+ return lyr;
8000
+ }
8001
+ }
8002
+ };
7900
8003
 
7901
- watch(
7902
- [indicator, mapPosition, datetime],
7903
- ([updatedIndicator, updatedMapPosition, updatedDatetime]) => {
7904
- if ("URLSearchParams" in window) {
7905
- const searchParams = new URLSearchParams(window.location.search);
7906
- if (updatedIndicator !== "") {
7907
- searchParams.set("indicator", updatedIndicator);
7908
- }
7909
-
7910
- if (updatedMapPosition && updatedMapPosition.length === 3) {
7911
- searchParams.set("x", updatedMapPosition[0]?.toFixed(4) ?? "");
7912
- searchParams.set("y", updatedMapPosition[1]?.toFixed(4) ?? "");
7913
- searchParams.set("z", updatedMapPosition[2]?.toFixed(4) ?? "");
7914
- }
8004
+ /**
8005
+ * Removes the layer with the id provided and injects an array of layers in its position
8006
+ * @param {Record<string,any>[]} currentLayers
8007
+ * @param {string} oldLayer - id of the layer to be replaced
8008
+ * @param {Record<string,any>[]} newLayers - array of layers to replace the old layer
8009
+ * @returns {Record<string,any>[] | undefined}
8010
+ */
8011
+ const replaceLayer = (currentLayers, oldLayer, newLayers) => {
8012
+ const oldLayerIdx = currentLayers.findIndex(
8013
+ (l) => l.properties.id === oldLayer,
8014
+ );
7915
8015
 
7916
- if (updatedDatetime) {
7917
- searchParams.set("datetime", updatedDatetime.split("T")?.[0] ?? "");
7918
- }
7919
- const newRelativePathQuery =
7920
- window.location.pathname + "?" + searchParams.toString();
7921
- history.pushState(null, "", newRelativePathQuery);
7922
- }
7923
- },
8016
+ if (oldLayerIdx !== -1) {
8017
+ log.debug(
8018
+ "Replacing layer",
8019
+ oldLayer,
8020
+ "with",
8021
+ newLayers.map((l) => l.properties.id),
7924
8022
  );
7925
- });
7926
- };
8023
+ currentLayers.splice(oldLayerIdx, 1, ...newLayers);
8024
+ return currentLayers;
8025
+ }
7927
8026
 
7928
- /** @param {import("vue").Ref<HTMLElement|null>} root - components root element ref*/
7929
- const makePanelTransparent = (root) => {
7930
- onMounted(() => {
7931
- const eoxItem = root.value?.parentElement;
7932
- if (eoxItem?.tagName === "EOX-LAYOUT-ITEM") {
7933
- eoxItem.classList.remove("bg-surface");
8027
+ for (const l of currentLayers) {
8028
+ if (l.type === "Group") {
8029
+ const updatedGroupLyrs = replaceLayer(l.layers, oldLayer, newLayers);
8030
+ if (updatedGroupLyrs?.length) {
8031
+ l.layers = updatedGroupLyrs;
8032
+ return currentLayers;
8033
+ }
7934
8034
  }
8035
+ }
8036
+ };
8037
+
8038
+ /**
8039
+ * Extracts the STAC collection which the layer was created from.
8040
+ *
8041
+ * @param {import('../eodashSTAC/EodashCollection.js').EodashCollection[]} indicators
8042
+ * @param {import('ol/layer').Layer} layer
8043
+ */
8044
+ const getColFromLayer = async (indicators, layer) => {
8045
+ // init cols
8046
+ const collections = await Promise.all(
8047
+ indicators.map((ind) => ind.fetchCollection()),
8048
+ );
8049
+ const [collectionId, itemId, ..._other] = layer.get("id").split(";:;");
8050
+
8051
+ const chosen = collections.find((col) => {
8052
+ const isInd =
8053
+ col.id === collectionId &&
8054
+ col.links?.some(
8055
+ (link) => link.rel === "item" && link.href.includes(itemId),
8056
+ );
8057
+ return isInd;
7935
8058
  });
8059
+ return indicators.find((ind) => ind.collectionStac?.id === chosen?.id);
7936
8060
  };
7937
8061
 
7938
8062
  /**
7939
- * Listens to the `layers:updated` and `time:updated` events and calls
8063
+ * Generates layer specific ID from STAC Links
8064
+ * related functions are: {@link assignProjID} & {@link createAssetID}
8065
+ *
8066
+ * @param {string} collectionId
8067
+ * @param {string} itemId
8068
+ * @param {import('stac-ts').StacLink} link
8069
+ * @param {string} projectionCode
7940
8070
  *
7941
- * @param {import("@vueuse/core").EventBusListener<
7942
- * "layers:updated"|"time:updated",
7943
- * {layers:Record<string,any>[]| undefined}
7944
- * >} listener
7945
8071
  */
7946
- const useOnLayersUpdate = (listener) => {
7947
- const layersEvents = useEventBus(eoxLayersKey);
8072
+ const createLayerID = (collectionId, itemId, link, projectionCode) => {
8073
+ const linkId = link.id || link.title || link.href;
8074
+ let lId = `${collectionId ?? ""};:;${itemId ?? ""};:;${linkId ?? ""};:;${projectionCode ?? ""}`;
8075
+ // If we are looking at base layers and overlays we remove the collection and item part
8076
+ // as we want to make sure tiles are not reloaded when switching layers
8077
+ if (
8078
+ /** @type {string[]} */
8079
+ (link.roles)?.find((r) => ["baselayer", "overlay"].includes(r))
8080
+ ) {
8081
+ lId = `${linkId ?? ""};:;${projectionCode ?? ""}`;
8082
+ }
8083
+ log.debug("Generated Layer ID", lId);
8084
+ return lId;
8085
+ };
7948
8086
 
7949
- const unsubscribe = layersEvents.on(listener);
8087
+ /**
8088
+ * Generates layer specific ID from STAC assets, related functions are: {@link assignProjID} & {@link createLayerID}
8089
+ *
8090
+ * @param {string} collectionId
8091
+ * @param {string} itemId
8092
+ * @param {number} index
8093
+ *
8094
+ */
8095
+ const createAssetID = (collectionId, itemId, index) => {
8096
+ let lId = `${collectionId ?? ""};:;${itemId ?? ""};:;${index ?? ""}`;
8097
+ log.debug("Generated Asset ID", lId);
8098
+ return lId;
8099
+ };
7950
8100
 
7951
- onUnmounted(() => {
7952
- unsubscribe();
8101
+ /**
8102
+ * creates a structured clone from the layers and
8103
+ * removes all properties from the clone
8104
+ * except the ID and title
8105
+ *
8106
+ * @param {Record<string,any>[]} layers
8107
+ */
8108
+ const removeUnneededProperties = (layers) => {
8109
+ const cloned = structuredClone(layers);
8110
+ cloned.forEach((layer) => {
8111
+ const id = layer.properties.id;
8112
+ const title = layer.properties.title;
8113
+ layer.properties = { id, title };
8114
+ if (layer["interactions"]) {
8115
+ delete layer["interactions"];
8116
+ }
8117
+ if (layer.type === "Group") {
8118
+ layer.layers = removeUnneededProperties(layer.layers);
8119
+ }
7953
8120
  });
8121
+ return cloned;
7954
8122
  };
7955
8123
 
7956
8124
  /**
7957
- * Array of eodash STAC Collections extracted from the current selected indicator.
7958
- * Updated in {@link file://./../store/stac.js `loadSelectedSTAC`} widget
7959
- * @type {import('./eodashSTAC').EodashCollection[]}
7960
- * @private
8125
+ * Returns the current layers of {@link mapEl}
8126
+ * @returns {Record<string,any>[]}
7961
8127
  */
7962
- const eodashCollections = shallowReactive([]);
8128
+ const getLayers = () => mapEl.value?.layers.toReversed();
7963
8129
 
7964
8130
  /**
7965
- * Array of eodash STAC Collections extracted from the current selected COMPARE indicator.
7966
- * Updated in {@link file://./../store/stac.js ` loadSelectedCompareSTAC`} widget
7967
- * @type {import('./eodashSTAC').EodashCollection[]}
7968
- * @private
8131
+ * Returns the current layers of {@link mapCompareEl}
8132
+ * @returns {Record<string,any>[]}
7969
8133
  */
7970
- const eodashCompareCollections = shallowReactive([]);
8134
+ const getCompareLayers = () => mapCompareEl.value?.layers.toReversed();
8135
+
8136
+ /**
8137
+ * Register EPSG projection in `eox-map`
8138
+ * @param {string|number|{name: string, def: string, extent?:number[]}} [projection]*/
8139
+ const registerProjection = async (projection) => {
8140
+ let code = getProjectionCode(projection);
8141
+ if (!code || registeredProjections.includes(code)) {
8142
+ return;
8143
+ }
8144
+ log.debug("Unregistered projection found, registering it", code);
8145
+ registeredProjections.push(code);
8146
+ if (typeof projection === "object") {
8147
+ // registering whole projection definition
8148
+ await mapEl.value?.registerProjection(
8149
+ code,
8150
+ projection.def,
8151
+ projection.extent,
8152
+ );
8153
+ // also registering for comparison map
8154
+ await mapCompareEl.value?.registerProjection(
8155
+ code,
8156
+ projection.def,
8157
+ projection.extent,
8158
+ );
8159
+ } else {
8160
+ await mapEl.value?.registerProjectionFromCode(code);
8161
+ // also registering for comparison map
8162
+ await mapCompareEl.value?.registerProjectionFromCode(code);
8163
+ }
8164
+ };
8165
+ /**
8166
+ * Change `eox-map` projection from an `EPSG` projection
8167
+ * @param {string|number|{name: string, def: string}} [projection]*/
8168
+ const changeMapProjection = async (projection) => {
8169
+ let code = getProjectionCode(projection);
8170
+
8171
+ if (!code) {
8172
+ mapEl.value?.setAttribute("projection", "EPSG:3857");
8173
+ mapCompareEl.value?.setAttribute("projection", "EPSG:3857");
8174
+ return;
8175
+ }
8176
+
8177
+ if (!registeredProjections.includes(code)) {
8178
+ await registerProjection(projection);
8179
+ }
8180
+
8181
+ code = mapEl.value?.getAttribute("projection") === code ? "EPSG:3857" : code;
8182
+ mapEl.value?.setAttribute("projection", code);
8183
+ mapCompareEl.value?.setAttribute("projection", code);
8184
+ };
8185
+
8186
+ /**
8187
+ *
8188
+ * @param {string} template
8189
+ */
8190
+ const setActiveTemplate = (template) => {
8191
+ activeTemplate.value = template;
8192
+ log.debug("Setting active template to", template);
8193
+ };
8194
+
8195
+ const actions = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
8196
+ __proto__: null,
8197
+ changeMapProjection,
8198
+ getCompareLayers,
8199
+ getLayers,
8200
+ registerProjection,
8201
+ setActiveTemplate
8202
+ }, Symbol.toStringTag, { value: 'Module' }));
7971
8203
 
7972
8204
  /**
7973
8205
  * @param {string} collectionId
@@ -8026,10 +8258,11 @@ async function createLayersFromAssets(
8026
8258
  },
8027
8259
  ...(!style?.variables && { style }),
8028
8260
  };
8261
+
8029
8262
  extractRoles(layer.properties, assets[ast]);
8030
- if (extraProperties !== null) {
8031
- layer.properties = { ...layer.properties, ...extraProperties };
8032
- }
8263
+
8264
+ layer.properties = { ...layer.properties, ...(extraProperties ?? {}) };
8265
+
8033
8266
  jsonArray.push(layer);
8034
8267
  } else if (assets[ast]?.type === "image/tiff") {
8035
8268
  geoTIFFIdx = idx;
@@ -8057,7 +8290,7 @@ async function createLayersFromAssets(
8057
8290
  },
8058
8291
  style,
8059
8292
  };
8060
- if (extraProperties !== null) {
8293
+ if (extraProperties) {
8061
8294
  layer.properties = { ...layer.properties, ...extraProperties };
8062
8295
  }
8063
8296
  jsonArray.push(layer);
@@ -8111,10 +8344,11 @@ const createLayersFromLinks = async (
8111
8344
  viewProjectionCode,
8112
8345
  );
8113
8346
  log.debug("WMS Layer added", linkId);
8114
- const tileSize =
8347
+ const tileSize = /** @type {number[]} */ (
8115
8348
  "wms:tilesize" in wmsLink
8116
8349
  ? [wmsLink["wms:tilesize"], wmsLink["wms:tilesize"]]
8117
- : [512, 512];
8350
+ : [512, 512]
8351
+ );
8118
8352
  let json = {
8119
8353
  type: "Tile",
8120
8354
  properties: {
@@ -8279,11 +8513,6 @@ class EodashCollection {
8279
8513
  /** @type {import("stac-ts").StacCollection | undefined} */
8280
8514
  #collectionStac;
8281
8515
 
8282
- // read only
8283
- get collectionStac() {
8284
- return this.#collectionStac;
8285
- }
8286
-
8287
8516
  /**
8288
8517
  * @type {import("stac-ts").StacLink
8289
8518
  * | import("stac-ts").StacItem
@@ -8291,6 +8520,11 @@ class EodashCollection {
8291
8520
  */
8292
8521
  selectedItem;
8293
8522
 
8523
+ // read only
8524
+ get collectionStac() {
8525
+ return this.#collectionStac;
8526
+ }
8527
+
8294
8528
  /** @param {string} collectionUrl */
8295
8529
  constructor(collectionUrl) {
8296
8530
  this.#collectionUrl = collectionUrl;
@@ -8339,9 +8573,7 @@ class EodashCollection {
8339
8573
  this.selectedItem = this.getItem();
8340
8574
 
8341
8575
  if (this.selectedItem) {
8342
- layersJson = /** @type {Record<string,any>[]} */ (
8343
- await this.createLayersJson(this.selectedItem)
8344
- );
8576
+ layersJson = await this.createLayersJson(this.selectedItem);
8345
8577
  } else {
8346
8578
  console.warn(
8347
8579
  "[eodash] the selected collection does not include any items",
@@ -8367,7 +8599,7 @@ class EodashCollection {
8367
8599
  * @param {string} title
8368
8600
  * @param {boolean} isGeoDB
8369
8601
  * @param {string} [itemDatetime]
8370
- * @returns {Promise<Record<string,any>[]>} arrays
8602
+ * @returns {Promise<Record<string,any>[]>} layers
8371
8603
  * */
8372
8604
  async buildJsonArray(item, itemUrl, title, isGeoDB, itemDatetime) {
8373
8605
  log.debug(
@@ -8390,31 +8622,9 @@ class EodashCollection {
8390
8622
 
8391
8623
  const jsonArray = [];
8392
8624
 
8393
- if (isGeoDB) {
8394
- const allFeatures = generateFeatures(this.#collectionStac?.links);
8395
-
8396
- return [
8397
- {
8398
- type: "Vector",
8399
- properties: {
8400
- id: this.#collectionStac?.id ?? "",
8401
- title: this.#collectionStac?.title || item.id,
8402
- },
8403
- source: {
8404
- type: "Vector",
8405
- url: "data:," + encodeURIComponent(JSON.stringify(allFeatures)),
8406
- format: "GeoJSON",
8407
- },
8408
- style: {
8409
- "circle-radius": 5,
8410
- "circle-fill-color": "#00417077",
8411
- "circle-stroke-color": "#004170",
8412
- "fill-color": "#00417077",
8413
- "stroke-color": "#004170",
8414
- },
8415
- interactions: [],
8416
- },
8417
- ];
8625
+ if (isGeoDB) {
8626
+ // handled by getGeoDBLayer
8627
+ return [];
8418
8628
  }
8419
8629
 
8420
8630
  // I propose following approach, we "manually" create configurations
@@ -8447,7 +8657,7 @@ class EodashCollection {
8447
8657
  let extraProperties = null;
8448
8658
  if (this.#collectionStac?.assets?.legend?.href) {
8449
8659
  extraProperties = {
8450
- description: `<div style="text-align:center; width: 100%">
8660
+ description: `<div style="width: 100%">
8451
8661
  <img src="${this.#collectionStac.assets.legend.href}" style="max-height:70px; margin-top:-15px; margin-bottom:-20px;" />
8452
8662
  </div>`,
8453
8663
  };
@@ -8601,14 +8811,14 @@ class EodashCollection {
8601
8811
  currentLayers = getCompareLayers();
8602
8812
  }
8603
8813
 
8604
- const oldLayer = findLayer(currentLayers, layer);
8814
+ /** @type {string | undefined} */
8815
+ const oldLayerID = findLayer(currentLayers, layer)?.properties.id;
8605
8816
 
8606
- const updatedLayers = replaceLayer(
8607
- currentLayers,
8608
- /** @type {Record<string,any> & { properties:{ id:string; title:string } } } */
8609
- (oldLayer),
8610
- newLayers,
8611
- );
8817
+ if (!oldLayerID) {
8818
+ return;
8819
+ }
8820
+
8821
+ const updatedLayers = replaceLayer(currentLayers, oldLayerID, newLayers);
8612
8822
 
8613
8823
  return updatedLayers;
8614
8824
  }
@@ -8651,6 +8861,63 @@ class EodashCollection {
8651
8861
  )),
8652
8862
  ];
8653
8863
  }
8864
+
8865
+ /**
8866
+ * Returns GeoDB layer from a list of EodashCollections
8867
+ *
8868
+ * @param {EodashCollection[]} eodashCollections
8869
+ *
8870
+ **/
8871
+ static getGeoDBLayer(eodashCollections) {
8872
+ const allFeatures = [];
8873
+ for (const collection of eodashCollections) {
8874
+ const isGeoDB = collection.#collectionStac?.endpointtype === "GeoDB";
8875
+ if (!isGeoDB) {
8876
+ continue;
8877
+ }
8878
+ const collectionFeatures = generateFeatures(
8879
+ collection.#collectionStac?.links,
8880
+ ).features;
8881
+ if (collectionFeatures.length) {
8882
+ allFeatures.push(
8883
+ generateFeatures(collection.#collectionStac?.links).features,
8884
+ );
8885
+ }
8886
+ }
8887
+ if (allFeatures.length) {
8888
+ const featureCollection = {
8889
+ type: "FeatureCollection",
8890
+ crs: {
8891
+ type: "name",
8892
+ properties: {
8893
+ name: "EPSG:4326",
8894
+ },
8895
+ },
8896
+ features: allFeatures.flat(),
8897
+ };
8898
+ return {
8899
+ type: "Vector",
8900
+ properties: {
8901
+ id: "geodb-collection",
8902
+ title: "GeoDB Collection",
8903
+ },
8904
+ source: {
8905
+ type: "Vector",
8906
+ url: "data:," + encodeURIComponent(JSON.stringify(featureCollection)),
8907
+ format: "GeoJSON",
8908
+ },
8909
+ style: {
8910
+ "circle-radius": 5,
8911
+ "circle-fill-color": "#00417077",
8912
+ "circle-stroke-color": "#004170",
8913
+ "fill-color": "#00417077",
8914
+ "stroke-color": "#004170",
8915
+ },
8916
+ interactions: [],
8917
+ };
8918
+ }
8919
+ return null;
8920
+ }
8654
8921
  }
8655
8922
 
8656
8923
  const useSTAcStore = defineStore("stac", () => {
@@ -8770,7 +9037,7 @@ const useSTAcStore = defineStore("stac", () => {
8770
9037
  .get(absoluteUrl.value)
8771
9038
  .then(async (resp) => {
8772
9039
  // init eodash collections
8773
- const collectionUrls = extractCollectionUrls(
9040
+ const collectionUrls = await extractCollectionUrls(
8774
9041
  resp.data,
8775
9042
  absoluteUrl.value,
8776
9043
  );
@@ -8814,31 +9081,12 @@ const useSTAcStore = defineStore("stac", () => {
8814
9081
  };
8815
9082
  });
8816
9083
 
8817
- const __vite_glob_0_2 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
8818
- __proto__: null,
8819
- useSTAcStore
8820
- }, Symbol.toStringTag, { value: 'Module' }));
9084
+ //export all actions, states, and pinia stores
8821
9085
 
8822
- const storesImport = /* #__PURE__ */ Object.assign({"./Actions.js": __vite_glob_0_0,"./States.js": __vite_glob_0_1,"./stac.js": __vite_glob_0_2});
8823
-
8824
- const store = /** @type {import("@/types").EodashStore} */ (
8825
- (() => {
8826
- const stores = {};
8827
- for (const [filePath, importedstore] of Object.entries(storesImport)) {
8828
- const storeType =
8829
- filePath.split("/").at(-1)?.slice(0, -3).toLowerCase() ?? "";
8830
- if (!["keys"].includes(storeType)) {
8831
- //@ts-expect-error `importedstore` cant be typed individually
8832
- stores[storeType] = importedstore;
8833
- }
8834
- }
8835
- return stores;
8836
- })()
8837
- );
9086
+ const store = { stac: { useSTAcStore }, actions, states };
8838
9087
 
8839
9088
  /**
8840
- * Sets user defined instance on runtime. Consumes `/@fs/config.js` and assign
8841
- * it to `eodash`
9089
+ * Handles importing user defined instance of Eodash
8842
9090
  *
8843
9091
  * @async
8844
9092
  * @param {string | undefined} runtimeConfig
@@ -8849,6 +9097,17 @@ const useEodashRuntime = async (runtimeConfig) => {
8849
9097
  const eodash = /** @type {import("@/types").Eodash} */ (inject$1(eodashKey));
8850
9098
  /** @param {import("@/types").Eodash} config */
8851
9099
  const assignInstance = (config) => {
9100
+ if ("template" in config) {
9101
+ //@ts-expect-error to do
9102
+ delete eodash.templates;
9103
+ //@ts-expect-error to do
9104
+ eodash.template = config.template;
9105
+ } else if ("templates" in config) {
9106
+ //@ts-expect-error to do
9107
+ delete eodash.template;
9108
+ //@ts-expect-error to do
9109
+ eodash.templates = config.templates;
9110
+ }
8852
9111
  /** @type {(keyof import("@/types").Eodash)[]} */ (
8853
9112
  Object.keys(eodash)
8854
9113
  ).forEach((key) => {
@@ -8868,232 +9127,74 @@ const useEodashRuntime = async (runtimeConfig) => {
8868
9127
  return eodash;
8869
9128
  }
8870
9129
 
8871
- try {
8872
- const configJs = "/config.js";
8873
- assignInstance(
8874
- (await import(/* @vite-ignore */ new URL(configJs, import.meta.url).href))
8875
- .default,
8876
- );
8877
- } catch {
8878
- try {
8879
- assignInstance(
8880
- await Promise.resolve().then(() => eodash$1).then(async (m) => await m["default"]),
8881
- );
8882
- } catch {
8883
- console.error("no dashboard configuration defined");
8884
- }
8885
- }
8886
- return eodash;
8887
- };
8888
-
8889
- /**
8890
- * Loads font in the app using `webfontloader`
8891
- *
8892
- * @param {string} [family]
8893
- * @param {string} [link]
8894
- * @param {boolean} [isWebComponent]
8895
- * @returns {Promise<string>} - Font family name
8896
- * @see {@link "https://github.com/typekit/webfontloader"}
8897
- */
8898
- const loadFont = async (
8899
- family = "",
8900
- link = "",
8901
- isWebComponent = false,
8902
- ) => {
8903
- if (family && link) {
8904
- const WebFontLoader = (await import('webfontloader')).default;
8905
- WebFontLoader.load({
8906
- classes: false,
8907
- custom: {
8908
- // Use FVD notation to include families https://github.com/typekit/fvd
8909
- families: [family],
8910
- // Path to stylesheet that defines font-face
8911
- urls: [link],
8912
- },
8913
- fontactive(familyName, _fvd) {
8914
- const stylesheet = new CSSStyleSheet();
8915
- const styles = isWebComponent
8916
- ? `eo-dash {font-family: ${familyName};}`
8917
- : `* {font-family: ${familyName};}`;
8918
- stylesheet.replaceSync(styles);
8919
- document.adoptedStyleSheets.push(stylesheet);
8920
- },
8921
- fontinactive(familyName, _fvd) {
8922
- throw new Error(`error loading font: ${familyName}`);
8923
- },
8924
- });
8925
- }
8926
- return family;
8927
- };
8928
-
8929
- /**
8930
- * @param {string} text
8931
- * @param {import("vue").Ref<boolean>} showIcon
8932
- **/
8933
- const copyToClipBoard = async (text, showIcon) => {
8934
- await navigator.clipboard.writeText(text);
8935
- showIcon.value = true;
8936
- setTimeout(() => {
8937
- showIcon.value = false;
8938
- }, 2000);
8939
- };
8940
-
8941
- /**
8942
- * @typedef {{
8943
- * component: import("vue").Component | null;
8944
- * props: Record<string, unknown>;
8945
- * title: string;
8946
- * id: string | number | symbol;
8947
- * layout: { x: number; y: number; h: number; w: number };
8948
- * }} DefinedWidget
8949
- */
8950
-
8951
- /** @typedef {import("vue").ShallowRef<DefinedWidget>} ReactiveDefinedWidget */
8952
-
8953
- const internalWidgets = (() => {
8954
- /** @type {Record<string, () => Promise<import("vue").Component>>} */
8955
- const importMap = {
8956
- .../* #__PURE__ */ Object.assign({"/widgets/EodashDatePicker.vue": () => import('./EodashDatePicker-VVkiPmpc.js'),"/widgets/EodashItemFilter.vue": () => import('./EodashItemFilter-CugWNQ86.js'),"/widgets/EodashLayerControl.vue": () => import('./EodashLayerControl-53WghA8G.js'),"/widgets/EodashMap.vue": () => import('./EodashMap-CQnOePpy.js'),"/widgets/EodashMapBtns.vue": () => import('./EodashMapBtns-uaRwFtfB.js'),"/widgets/EodashProcess.vue": () => import('./EodashProcess-cF0unIy8.js'),"/widgets/ExportState.vue": () => import('./ExportState-BT8MLAW7.js'),"/widgets/PopUp.vue": () => import('./PopUp-Bm01q7Ko.js'),"/widgets/WidgetsContainer.vue": () => import('./WidgetsContainer-CwXRRLS1.js')}),
8957
- .../* #__PURE__ */ Object.assign({}),
8958
- };
8959
- for (const key in importMap) {
8960
- const newKey = /** @type {string} */ (key.split("/").at(-1)).slice(0, -4);
8961
- Object.defineProperty(
8962
- importMap,
8963
- newKey,
8964
- /** @type {PropertyDescriptor} */ (
8965
- Object.getOwnPropertyDescriptor(importMap, key)
8966
- ),
8967
- );
8968
- delete importMap[key];
8969
- }
8970
- return importMap;
8971
- })();
8972
-
8973
- /**
8974
- * Composable that converts widgets Configurations to defined imported widgets
8975
- *
8976
- * @param {(
8977
- * | import("@/types").Widget
8978
- * | import("@/types").BackgroundWidget
8979
- * | Omit<import("@/types").Widget, "layout">
8980
- * | undefined
8981
- * )[]
8982
- * | undefined} widgetConfigs
8983
- * @returns {ReactiveDefinedWidget[]}
8984
- */
8985
- const useDefineWidgets = (widgetConfigs) => {
8986
- /** @type {ReactiveDefinedWidget[]} */
8987
- const definedWidgets = [];
8988
-
8989
- for (const config of widgetConfigs ?? []) {
8990
- /** @type {ReactiveDefinedWidget} */
8991
- const definedWidget = shallowRef({
8992
- component: null,
8993
- props: {},
8994
- title: "",
8995
- id: Symbol(),
8996
- layout: { x: 0, y: 0, h: 0, w: 0 },
8997
- });
8998
-
8999
- if ("defineWidget" in (config ?? {})) {
9000
- const { selectedStac } = storeToRefs(useSTAcStore());
9001
- watch(
9002
- selectedStac,
9003
- (updatedStac) => {
9004
- let definedConfig =
9005
- /** @type {import("@/types").FunctionalWidget} */ (
9006
- config
9007
- )?.defineWidget(updatedStac);
9008
- if (definedConfig) {
9009
- definedConfig = reactive(definedConfig);
9010
- }
9011
- definedWidget.value =
9012
- definedWidget.value.id === definedConfig?.id
9013
- ? definedWidget.value
9014
- : getWidgetDefinition(definedConfig);
9015
- },
9016
- { immediate: true },
9017
- );
9018
- } else {
9019
- definedWidget.value = getWidgetDefinition(
9020
- /** @type {import("@/types").StaticWidget} */ (config),
9021
- );
9022
- }
9023
- definedWidgets.push(definedWidget);
9024
- }
9025
- return definedWidgets;
9026
- };
9027
-
9028
- /**
9029
- * Converts a static widget configuration to a defined imported widget
9030
- *
9031
- * @param {import("@/types").StaticWidget
9032
- * | Omit<import("@/types").StaticWidget, "layout">
9033
- * | undefined
9034
- * | null} [config]
9035
- * @returns {DefinedWidget}
9036
- */
9037
- const getWidgetDefinition = (config) => {
9038
- /** @type {DefinedWidget} */
9039
- const importedWidget = {
9040
- component: null,
9041
- props: {},
9042
- title: "",
9043
- id: Symbol(),
9044
- layout: reactive({ x: 0, y: 0, h: 0, w: 0 }),
9045
- };
9046
- switch (config?.type) {
9047
- case "internal":
9048
- importedWidget.component = defineAsyncComponent({
9049
- loader:
9050
- internalWidgets[
9051
- /** @type {import("@/types").InternalComponentWidget} * */ (config)
9052
- ?.widget.name
9053
- ],
9054
- suspensible: true,
9055
- });
9056
- importedWidget.props = reactive(
9057
- /** @type {import("@/types").InternalComponentWidget} * */ (config)
9058
- ?.widget.properties ?? {},
9059
- );
9060
-
9061
- break;
9062
-
9063
- case "web-component":
9064
- importedWidget.component = defineAsyncComponent({
9065
- loader: () => import('./DynamicWebComponent-Cv8n457T.js'),
9066
- suspensible: true,
9067
- });
9068
- importedWidget.props = reactive(config.widget);
9069
-
9070
- break;
9071
- case "iframe":
9072
- importedWidget.component = defineAsyncComponent({
9073
- loader: () => import('./IframeWrapper-BgM9aU8f.js'),
9074
- suspensible: true,
9075
- });
9076
- importedWidget.props = reactive(config.widget);
9077
- break;
9078
-
9079
- default:
9080
- if (!config) {
9081
- return importedWidget;
9082
- } else {
9083
- console.error("Widget type not found");
9084
- }
9085
- break;
9130
+ try {
9131
+ const configJs = "/config.js";
9132
+ assignInstance(
9133
+ (await import(/* @vite-ignore */ new URL(configJs, import.meta.url).href))
9134
+ .default,
9135
+ );
9136
+ } catch {
9137
+ try {
9138
+ assignInstance(
9139
+ await Promise.resolve().then(() => eodash$1).then(async (m) => await m["default"]),
9140
+ );
9141
+ } catch {
9142
+ console.error("no dashboard configuration defined");
9143
+ }
9086
9144
  }
9087
- importedWidget.title = config?.title ?? "";
9088
- importedWidget.id = config?.id ?? importedWidget.id;
9145
+ return eodash;
9146
+ };
9089
9147
 
9090
- if ("layout" in config) {
9091
- importedWidget.layout.x = config.layout.x;
9092
- importedWidget.layout.y = config.layout.y;
9093
- importedWidget.layout.h = config.layout.h;
9094
- importedWidget.layout.w = config.layout.w;
9148
+ /**
9149
+ * Loads font in the app using `webfontloader`
9150
+ *
9151
+ * @param {string} [family]
9152
+ * @param {string} [link]
9153
+ * @param {boolean} [isWebComponent]
9154
+ * @returns {Promise<string>} - Font family name
9155
+ * @see {@link "https://github.com/typekit/webfontloader"}
9156
+ */
9157
+ const loadFont = async (
9158
+ family = "",
9159
+ link = "",
9160
+ isWebComponent = false,
9161
+ ) => {
9162
+ if (family && link) {
9163
+ const WebFontLoader = (await import('webfontloader')).default;
9164
+ WebFontLoader.load({
9165
+ classes: false,
9166
+ custom: {
9167
+ // Use FVD notation to include families https://github.com/typekit/fvd
9168
+ families: [family],
9169
+ // Path to stylesheet that defines font-face
9170
+ urls: [link],
9171
+ },
9172
+ fontactive(familyName, _fvd) {
9173
+ const stylesheet = new CSSStyleSheet();
9174
+ const styles = isWebComponent
9175
+ ? `eo-dash {font-family: ${familyName};}`
9176
+ : `* {font-family: ${familyName};}`;
9177
+ stylesheet.replaceSync(styles);
9178
+ document.adoptedStyleSheets.push(stylesheet);
9179
+ },
9180
+ fontinactive(familyName, _fvd) {
9181
+ throw new Error(`error loading font: ${familyName}`);
9182
+ },
9183
+ });
9095
9184
  }
9096
- return importedWidget;
9185
+ return family;
9186
+ };
9187
+
9188
+ /**
9189
+ * @param {string} text
9190
+ * @param {import("vue").Ref<boolean>} showIcon
9191
+ **/
9192
+ const copyToClipBoard = async (text, showIcon) => {
9193
+ await navigator.clipboard.writeText(text);
9194
+ showIcon.value = true;
9195
+ setTimeout(() => {
9196
+ showIcon.value = false;
9197
+ }, 2000);
9097
9198
  };
9098
9199
 
9099
9200
  const _export_sfc = (sfc, props) => {
@@ -11073,6 +11174,226 @@ return (_ctx, _cache) => {
11073
11174
  };
11074
11175
  const ErrorAlert = /*#__PURE__*/_export_sfc(_sfc_main$3, [['__scopeId',"data-v-ac10aa7f"]]);
11075
11176
 
11177
+ /**
11178
+ * @typedef {{
11179
+ * component: import("vue").Component | null;
11180
+ * props: Record<string, unknown>;
11181
+ * title: string;
11182
+ * id: string | number | symbol;
11183
+ * layout: { x: number; y: number; h: number; w: number };
11184
+ * }} DefinedWidget
11185
+ */
11186
+
11187
+ /** @typedef {import("vue").ShallowRef<DefinedWidget>} ReactiveDefinedWidget */
11188
+ /**
11189
+ * Widgets import map that is created from eodash internals and user defined widgets
11190
+ */
11191
+ const internalWidgets = (() => {
11192
+ /** @type {Record<string, () => Promise<import("vue").Component>>} */
11193
+ const importMap = {
11194
+ .../* #__PURE__ */ Object.assign({"/widgets/EodashDatePicker.vue": () => import('./EodashDatePicker-Pok6bZwU.js'),"/widgets/EodashItemFilter.vue": () => import('./EodashItemFilter-16eMMjTV.js'),"/widgets/EodashLayerControl.vue": () => import('./EodashLayerControl-De7IlCm_.js'),"/widgets/EodashLayoutSwitcher.vue": () => import('./EodashLayoutSwitcher-C-3-jjn5.js'),"/widgets/EodashMap.vue": () => import('./EodashMap-CMvbfI6-.js'),"/widgets/EodashMapBtns.vue": () => import('./EodashMapBtns-BeknGDtc.js'),"/widgets/EodashProcess.vue": () => import('./EodashProcess-BwKAa9Ee.js'),"/widgets/EodashStacInfo.vue": () => import('./EodashStacInfo-_BfonNUG.js'),"/widgets/EodashTools.vue": () => import('./EodashTools-PD3XPYuR.js'),"/widgets/ExportState.vue": () => import('./ExportState-DOrT7M15.js'),"/widgets/PopUp.vue": () => import('./PopUp--_xn1Cms.js'),"/widgets/WidgetsContainer.vue": () => import('./WidgetsContainer-aFG9yFT6.js')}),
11195
+ .../* #__PURE__ */ Object.assign({}),
11196
+ };
11197
+ for (const key in importMap) {
11198
+ const newKey = /** @type {string} */ (key.split("/").at(-1)).slice(0, -4);
11199
+ Object.defineProperty(
11200
+ importMap,
11201
+ newKey,
11202
+ /** @type {PropertyDescriptor} */ (
11203
+ Object.getOwnPropertyDescriptor(importMap, key)
11204
+ ),
11205
+ );
11206
+ delete importMap[key];
11207
+ }
11208
+ return importMap;
11209
+ })();
11210
+
11211
+ /**
11212
+ * Composable that converts widgets Configurations to defined imported widgets
11213
+ *
11214
+ * @param {(
11215
+ * | import("@/types").Widget
11216
+ * | import("@/types").BackgroundWidget
11217
+ * | Omit<import("@/types").Widget, "layout">
11218
+ * | undefined
11219
+ * )[]
11220
+ * | undefined} widgetConfigs
11221
+ */
11222
+ const useDefineWidgets = (widgetConfigs) => {
11223
+ /** @type {ReactiveDefinedWidget[]} */
11224
+ const definedWidgets = [];
11225
+
11226
+ for (const config of widgetConfigs ?? []) {
11227
+ /** @type {ReactiveDefinedWidget} */
11228
+ const definedWidget = shallowRef({
11229
+ component: null,
11230
+ props: {},
11231
+ title: "",
11232
+ id: Symbol(),
11233
+ layout: { x: 0, y: 0, h: 0, w: 0 },
11234
+ });
11235
+
11236
+ if ("defineWidget" in (config ?? {})) {
11237
+ const { selectedStac } = storeToRefs(useSTAcStore());
11238
+ watch(
11239
+ selectedStac,
11240
+ (updatedStac) => {
11241
+ let definedConfig =
11242
+ /** @type {import("@/types").FunctionalWidget} */ (
11243
+ config
11244
+ )?.defineWidget(updatedStac);
11245
+ if (definedConfig) {
11246
+ definedConfig = reactive(definedConfig);
11247
+ }
11248
+ definedWidget.value =
11249
+ definedWidget.value.id === definedConfig?.id
11250
+ ? definedWidget.value
11251
+ : getWidgetDefinition(definedConfig);
11252
+ },
11253
+ { immediate: true },
11254
+ );
11255
+ } else {
11256
+ definedWidget.value = getWidgetDefinition(
11257
+ /** @type {import("@/types").StaticWidget} */ (config),
11258
+ );
11259
+ }
11260
+ definedWidgets.push(definedWidget);
11261
+ }
11262
+ return definedWidgets;
11263
+ };
11264
+
11265
+ /**
11266
+ * Converts a static widget configuration to a defined imported widget
11267
+ *
11268
+ * @param {import("@/types").StaticWidget
11269
+ * | Omit<import("@/types").StaticWidget, "layout">
11270
+ * | undefined
11271
+ * | null} [config]
11272
+ * @returns {DefinedWidget}
11273
+ */
11274
+ const getWidgetDefinition = (config) => {
11275
+ /** @type {DefinedWidget} */
11276
+ const importedWidget = {
11277
+ component: null,
11278
+ props: {},
11279
+ title: "",
11280
+ id: Symbol(),
11281
+ layout: reactive({ x: 0, y: 0, h: 0, w: 0 }),
11282
+ };
11283
+ switch (config?.type) {
11284
+ case "internal":
11285
+ importedWidget.component = defineAsyncComponent({
11286
+ loader:
11287
+ internalWidgets[
11288
+ /** @type {import("@/types").InternalComponentWidget} * */ (config)
11289
+ ?.widget.name
11290
+ ],
11291
+ suspensible: true,
11292
+ });
11293
+ importedWidget.props = reactive(
11294
+ /** @type {import("@/types").InternalComponentWidget} * */ (config)
11295
+ ?.widget.properties ?? {},
11296
+ );
11297
+
11298
+ break;
11299
+
11300
+ case "web-component":
11301
+ importedWidget.component = defineAsyncComponent({
11302
+ loader: () => import('./DynamicWebComponent-Cl4LqHU6.js'),
11303
+ suspensible: true,
11304
+ });
11305
+ importedWidget.props = reactive(config.widget);
11306
+
11307
+ break;
11308
+ case "iframe":
11309
+ importedWidget.component = defineAsyncComponent({
11310
+ loader: () => import('./IframeWrapper-BgM9aU8f.js'),
11311
+ suspensible: true,
11312
+ });
11313
+ importedWidget.props = reactive(config.widget);
11314
+ break;
11315
+
11316
+ default:
11317
+ if (!config) {
11318
+ return importedWidget;
11319
+ } else {
11320
+ console.error("Widget type not found");
11321
+ }
11322
+ break;
11323
+ }
11324
+ importedWidget.title = config?.title ?? "";
11325
+ importedWidget.id = config?.id ?? importedWidget.id;
11326
+
11327
+ if ("layout" in config) {
11328
+ importedWidget.layout.x = config.layout.x;
11329
+ importedWidget.layout.y = config.layout.y;
11330
+ importedWidget.layout.h = config.layout.h;
11331
+ importedWidget.layout.w = config.layout.w;
11332
+ }
11333
+ return importedWidget;
11334
+ };
11335
+
11336
+ /**
11337
+ * @typedef {{
11338
+ * bgWidget:ReturnType< typeof import("./DefineWidgets").useDefineWidgets>[number]| import("vue").ShallowRef<null>
11339
+ * loading: ReturnType< typeof import("./DefineWidgets").useDefineWidgets>[number]| import("vue").ShallowRef<null>
11340
+ * importedWidgets:ReturnType< typeof import("./DefineWidgets").useDefineWidgets>
11341
+ * gap: import("vue").Ref<number>
11342
+ * }} DefinedTemplate
11343
+ **/
11344
+
11345
+ const useTemplate = () => {
11346
+ const eodash = /** @type {import("@/types").Eodash} */ (inject$1(eodashKey));
11347
+
11348
+ /** @type {DefinedTemplate} */
11349
+ const definedTemplate = shallowReactive({
11350
+ bgWidget: shallowRef(null),
11351
+ importedWidgets: [],
11352
+ loading: shallowRef(null),
11353
+ gap: ref(16),
11354
+ });
11355
+
11356
+ if ("template" in eodash) {
11357
+ [definedTemplate.bgWidget] = useDefineWidgets([eodash.template.background]);
11358
+ [definedTemplate.loading] = useDefineWidgets([eodash.template.loading]);
11359
+ definedTemplate.importedWidgets = useDefineWidgets(eodash.template.widgets);
11360
+ definedTemplate.gap.value = eodash.template.gap ?? 16;
11361
+ } else {
11362
+ watch(
11363
+ activeTemplate,
11364
+ (template) => {
11365
+ log.debug("Active template watcher triggered, changing to:", template);
11366
+ if (!template) {
11367
+ template = Object.keys(eodash.templates)[0];
11368
+ activeTemplate.value = template ?? "";
11369
+ log.debug("No template found, setting to first template", template);
11370
+ }
11371
+
11372
+ if (!template || !eodash.templates[template]) {
11373
+ console.error(`[eodash] template not found`);
11374
+ return;
11375
+ }
11376
+
11377
+ const templateConfig = eodash.templates[template];
11378
+ [definedTemplate.bgWidget] = useDefineWidgets([
11379
+ templateConfig.background,
11380
+ ]);
11381
+
11382
+ [definedTemplate.loading] = useDefineWidgets([templateConfig.loading]);
11383
+
11384
+ definedTemplate.importedWidgets = useDefineWidgets(
11385
+ templateConfig.widgets,
11386
+ );
11387
+ definedTemplate.gap.value = templateConfig.gap ?? 16;
11388
+ },
11389
+ { immediate: true },
11390
+ );
11391
+ }
11392
+ return toRefs(definedTemplate);
11393
+ };
11394
+
11395
+ const useDefineTemplate = createSharedComposable(useTemplate);
11396
+
11076
11397
  // Styles
11077
11398
  const breakpointProps = (() => {
11078
11399
  return breakpoints.reduce((props, val) => {
@@ -11317,9 +11638,7 @@ const _sfc_main$2 = {
11317
11638
  __name: 'Loading',
11318
11639
  setup(__props) {
11319
11640
 
11320
- const eodash = /** @type {import("@/types").Eodash} */ (inject$1(eodashKey));
11321
-
11322
- const [loading] = useDefineWidgets([eodash.template.loading]);
11641
+ const { loading } = useDefineTemplate();
11323
11642
 
11324
11643
  const error = ref("");
11325
11644
  onErrorCaptured((e, inst, info) => {
@@ -11347,8 +11666,8 @@ return (_ctx, _cache) => {
11347
11666
  createElementVNode("div", { class: "text-center" }, "Loading...", -1 /* HOISTED */)
11348
11667
  ])),
11349
11668
  default: withCtx(() => [
11350
- (unref(loading).component)
11351
- ? (openBlock(), createBlock(resolveDynamicComponent(unref(loading).component), normalizeProps(mergeProps({ key: 0 }, unref(loading).props)), null, 16 /* FULL_PROPS */))
11669
+ (unref(loading)?.component)
11670
+ ? (openBlock(), createBlock(resolveDynamicComponent(unref(loading)?.component), normalizeProps(mergeProps({ key: 0 }, unref(loading)?.props)), null, 16 /* FULL_PROPS */))
11352
11671
  : (openBlock(), createElementBlock("div", _hoisted_1$1, "Loading..."))
11353
11672
  ]),
11354
11673
  _: 1 /* STABLE */
@@ -11412,15 +11731,17 @@ const { loadSTAC } = useSTAcStore();
11412
11731
  );
11413
11732
 
11414
11733
  const { smAndDown } = useDisplay();
11415
- const TemplateComponent = smAndDown.value
11416
- ? defineAsyncComponent(() => import('./MobileLayout-BAo8Wr8T.js'))
11417
- : defineAsyncComponent(() => import('./DashboardLayout-CVMJ4l8M.js'));
11734
+ const TemplateComponent = computed(() =>
11735
+ smAndDown.value
11736
+ ? defineAsyncComponent(() => import('./MobileLayout-BdiFjHg7.js'))
11737
+ : defineAsyncComponent(() => import('./DashboardLayout-232tRmjz.js')),
11738
+ );
11418
11739
 
11419
11740
  const HeaderComponent = defineAsyncComponent(
11420
- () => import('./Header-D2dtCWp8.js'),
11741
+ () => import('./Header-C2cdx4gb.js'),
11421
11742
  );
11422
11743
  const FooterComponent = defineAsyncComponent(
11423
- () => import('./Footer-C6GUG84G.js'),
11744
+ () => import('./Footer-CCigxYBo.js'),
11424
11745
  );
11425
11746
 
11426
11747
  const templateHeight = props.isWebComponent ? "100%" : "100dvh";
@@ -11572,6 +11893,7 @@ const vuetify = createVuetify({
11572
11893
  next: [mdiChevronRight],
11573
11894
  prev: [mdiChevronLeft],
11574
11895
  subgroup: [mdiMenuDown],
11896
+ plus: [mdiPlus],
11575
11897
  },
11576
11898
  },
11577
11899
  theme: {
@@ -11605,7 +11927,7 @@ function registerPlugins(app) {
11605
11927
  * @type {import("vue").VueElementConstructor<
11606
11928
  * import("vue").ExtractPropTypes<{ config: string }>>}
11607
11929
  * */
11608
- const Eodash = defineCustomElement(_sfc_main, {
11930
+ const EodashConstructor = defineCustomElement(_sfc_main, {
11609
11931
  shadowRoot: false,
11610
11932
  configureApp(app) {
11611
11933
  registerPlugins(app);
@@ -11613,9 +11935,9 @@ const Eodash = defineCustomElement(_sfc_main, {
11613
11935
  });
11614
11936
 
11615
11937
  function register() {
11616
- customElements.define("eo-dash", Eodash);
11938
+ customElements.define("eo-dash", EodashConstructor);
11617
11939
  }
11618
11940
 
11619
11941
  register();
11620
11942
 
11621
- export { datetime as $, makeDensityProps as A, useDensity as B, useBackgroundColor as C, provideDefaults as D, isObject as E, eodashKey as F, useDefineWidgets as G, useLayout as H, IconValue as I, makeDimensionProps as J, useDimension as K, makeBorderProps as L, makeElevationProps as M, makeRoundedProps as N, useBorder as O, useElevation as P, useRounded as Q, VDefaultsProvider as R, clamp as S, consoleWarn as T, makeLayoutItemProps as U, VBtn as V, useToggleScope as W, useLayoutItem as X, getUid as Y, consoleError as Z, _export_sfc as _, useRender as a, useSTAcStore as a0, eodashCollections as a1, VRow as a2, mapCompareEl as a3, mapEl as a4, eodashCompareCollections as a5, getColFromLayer as a6, eoxLayersKey as a7, setMapProjFromCol as a8, EodashCollection as a9, copyToClipBoard as aA, SUPPORTS_INTERSECTION as aB, getCurrentInstance as aC, isOn as aD, eventName as aE, destructComputed as aF, parseAnchor as aG, flipSide as aH, flipAlign as aI, flipCorner as aJ, getAxis as aK, defer as aL, templateRef as aM, matchesSelector as aN, useRouter as aO, useBackButton as aP, Eodash as aQ, register as aR, store as aS, mapPosition as aa, makePanelTransparent as ab, availableMapProjection as ac, changeMapProjection as ad, axios$1 as ae, getLayers as af, extractLayerConfig as ag, useOnLayersUpdate as ah, createSimpleFunctional as ai, makeSizeProps as aj, makeVariantProps as ak, useVariant as al, useSize as am, genOverlays as an, makeLoaderProps as ao, makeLocationProps as ap, makePositionProps as aq, makeRouterProps as ar, Ripple as as, useLoader as at, useLocation as au, usePosition as av, useLink as aw, LoaderSlot as ax, removeUnneededProperties as ay, VCol as az, makeComponentProps as b, makeTagProps as c, makeThemeProps as d, provideTheme as e, useRtl as f, genericComponent as g, useLocale as h, useGroup as i, useProxiedModel as j, keys as k, makeGroupItemProps as l, makeVBtnProps as m, useGroupItem as n, omit as o, propsFactory as p, convertToUnit as q, makeDisplayProps as r, makeGroupProps as s, useDisplay as t, useTextColor as u, useResizeObserver as v, useGoTo as w, IN_BROWSER as x, VIcon as y, focusableChildren as z };
11943
+ export { useSTAcStore as $, makeDensityProps as A, useDensity as B, useBackgroundColor as C, provideDefaults as D, isObject as E, useDefineTemplate as F, useLayout as G, makeDimensionProps as H, IconValue as I, useDimension as J, makeBorderProps as K, makeElevationProps as L, makeRoundedProps as M, useBorder as N, useElevation as O, useRounded as P, VDefaultsProvider as Q, clamp as R, consoleWarn as S, makeLayoutItemProps as T, useToggleScope as U, VBtn as V, useLayoutItem as W, eodashKey as X, consoleError as Y, datetime as Z, _export_sfc as _, useRender as a, eodashCollections as a0, makePanelTransparent as a1, mapCompareEl as a2, mapEl as a3, eodashCompareCollections as a4, getColFromLayer as a5, registerProjection as a6, getProjectionCode as a7, availableMapProjection as a8, changeMapProjection as a9, useLink as aA, LoaderSlot as aB, removeUnneededProperties as aC, VRow as aD, VCol as aE, copyToClipBoard as aF, SUPPORTS_INTERSECTION as aG, getCurrentInstance as aH, useDefineWidgets as aI, isOn as aJ, eventName as aK, destructComputed as aL, parseAnchor as aM, flipSide as aN, flipAlign as aO, flipCorner as aP, getAxis as aQ, defer as aR, templateRef as aS, matchesSelector as aT, useRouter as aU, useBackButton as aV, EodashConstructor as aW, register as aX, store as aY, eoxLayersKey as aa, posIsSetFromUrl as ab, EodashCollection as ac, mapPosition as ad, setActiveTemplate as ae, axios$1 as af, getLayers as ag, extractLayerConfig as ah, useOnLayersUpdate as ai, currentUrl as aj, activeTemplate as ak, getUid as al, createSimpleFunctional as am, makeSizeProps as an, makeVariantProps as ao, useVariant as ap, useSize as aq, genOverlays as ar, makeLoaderProps as as, makeLocationProps as at, makePositionProps as au, makeRouterProps as av, Ripple as aw, useLoader as ax, useLocation as ay, usePosition as az, makeComponentProps as b, makeTagProps as c, makeThemeProps as d, provideTheme as e, useRtl as f, genericComponent as g, useLocale as h, useGroup as i, useProxiedModel as j, keys as k, makeGroupItemProps as l, makeVBtnProps as m, useGroupItem as n, omit as o, propsFactory as p, convertToUnit as q, makeDisplayProps as r, makeGroupProps as s, useDisplay as t, useTextColor as u, useResizeObserver as v, useGoTo as w, IN_BROWSER as x, VIcon as y, focusableChildren as z };