@eodash/eodash 5.0.0-alpha.2.9 → 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 (113) hide show
  1. package/README.md +1 -1
  2. package/core/client/App.vue +13 -1
  3. package/core/client/asWebComponent.js +13 -4
  4. package/core/client/components/DashboardLayout.vue +36 -14
  5. package/core/client/components/Loading.vue +6 -9
  6. package/core/client/components/MobileLayout.vue +16 -14
  7. package/core/client/composables/DefineEodash.js +14 -4
  8. package/core/client/composables/DefineTemplate.js +67 -0
  9. package/core/client/composables/DefineWidgets.js +3 -2
  10. package/core/client/composables/EodashMap.js +360 -0
  11. package/core/client/composables/EodashProcess.js +574 -0
  12. package/core/client/composables/index.js +136 -28
  13. package/core/client/eodash.js +395 -80
  14. package/core/client/eodashSTAC/EodashCollection.js +432 -0
  15. package/core/client/eodashSTAC/createLayers.js +315 -0
  16. package/core/client/eodashSTAC/helpers.js +375 -0
  17. package/core/client/eodashSTAC/triggers.js +43 -0
  18. package/core/client/plugins/axios.js +8 -0
  19. package/core/client/plugins/index.js +2 -1
  20. package/core/client/plugins/vuetify.js +2 -1
  21. package/core/client/store/actions.js +79 -0
  22. package/core/client/store/index.js +4 -18
  23. package/core/client/store/stac.js +99 -9
  24. package/core/client/store/states.js +37 -0
  25. package/core/client/{types.d.ts → types.ts} +66 -20
  26. package/core/client/utils/keys.js +2 -0
  27. package/core/client/utils/states.js +22 -0
  28. package/core/client/views/Dashboard.vue +22 -49
  29. package/core/client/vite-env.d.ts +2 -10
  30. package/dist/client/DashboardLayout-232tRmjz.js +84 -0
  31. package/dist/client/DynamicWebComponent-Cl4LqHU6.js +88 -0
  32. package/dist/client/EodashDatePicker-Pok6bZwU.js +306 -0
  33. package/dist/client/EodashItemFilter-16eMMjTV.js +151 -0
  34. package/dist/client/EodashLayerControl-De7IlCm_.js +120 -0
  35. package/dist/client/EodashLayoutSwitcher-C-3-jjn5.js +52 -0
  36. package/dist/client/EodashMap-CMvbfI6-.js +549 -0
  37. package/dist/client/EodashMapBtns-BeknGDtc.js +107 -0
  38. package/dist/client/EodashProcess-BwKAa9Ee.js +1476 -0
  39. package/dist/client/EodashStacInfo-_BfonNUG.js +85 -0
  40. package/dist/client/EodashTools-PD3XPYuR.js +103 -0
  41. package/dist/client/ExportState-DOrT7M15.js +644 -0
  42. package/dist/client/Footer-CCigxYBo.js +141 -0
  43. package/dist/client/Header-C2cdx4gb.js +437 -0
  44. package/dist/client/IframeWrapper-BgM9aU8f.js +28 -0
  45. package/dist/client/MobileLayout-BdiFjHg7.js +1207 -0
  46. package/dist/client/PopUp--_xn1Cms.js +410 -0
  47. package/dist/client/VImg-9xu2l99m.js +384 -0
  48. package/dist/client/VMain-BUs3kDTd.js +43 -0
  49. package/dist/client/VOverlay-D89omJis.js +1453 -0
  50. package/dist/client/VTooltip-CDu3bErh.js +86 -0
  51. package/dist/client/WidgetsContainer-aFG9yFT6.js +83 -0
  52. package/dist/client/asWebComponent-BRGyP_j5.js +11943 -0
  53. package/dist/client/{style.css → eo-dash.css} +2 -2
  54. package/dist/client/eo-dash.js +2 -6
  55. package/dist/client/forwardRefs-CYrR6bMw.js +245 -0
  56. package/dist/client/index-BZwk0V42.js +199 -0
  57. package/dist/client/ssrBoot-BP7SYRyC.js +22 -0
  58. package/dist/client/transition-DG9nRSW4.js +37 -0
  59. package/dist/node/cli.js +4 -4
  60. package/dist/node/types.d.ts +2 -0
  61. package/package.json +73 -38
  62. package/widgets/EodashDatePicker.vue +176 -134
  63. package/widgets/EodashItemFilter.vue +79 -38
  64. package/widgets/EodashLayerControl.vue +111 -0
  65. package/widgets/EodashLayoutSwitcher.vue +36 -0
  66. package/widgets/EodashMap.vue +108 -133
  67. package/widgets/EodashMapBtns.vue +62 -8
  68. package/widgets/EodashProcess.vue +143 -0
  69. package/widgets/EodashStacInfo.vue +82 -0
  70. package/widgets/EodashTools.vue +83 -0
  71. package/widgets/ExportState.vue +17 -13
  72. package/widgets/PopUp.vue +24 -2
  73. package/core/client/SuspensedDashboard.ce.vue +0 -105
  74. package/core/client/asWebComponent.d.ts +0 -23
  75. package/core/client/store/Actions.js +0 -14
  76. package/core/client/store/States.js +0 -16
  77. package/core/client/utils/eodashSTAC.js +0 -249
  78. package/core/client/utils/helpers.js +0 -38
  79. package/dist/client/DashboardLayout-D0ZF6V2S.js +0 -156
  80. package/dist/client/DynamicWebComponent-CPsMSBHi.js +0 -57
  81. package/dist/client/EodashDatePicker-CBQP7u2X.js +0 -252
  82. package/dist/client/EodashItemFilter-DL2ScI-5.js +0 -7671
  83. package/dist/client/EodashMap-CkKoQlmR.js +0 -86917
  84. package/dist/client/EodashMapBtns-yuO2QmiR.js +0 -36
  85. package/dist/client/ExportState-CCzOhppU.js +0 -558
  86. package/dist/client/Footer-BPAND0yG.js +0 -115
  87. package/dist/client/Header-DLhebNvG.js +0 -350
  88. package/dist/client/IframeWrapper-1GEMHlsW.js +0 -19
  89. package/dist/client/MobileLayout-mGkOYRhu.js +0 -945
  90. package/dist/client/PopUp-1d2bBFjw.js +0 -300
  91. package/dist/client/VImg-DxHcztfM.js +0 -291
  92. package/dist/client/VMain-BLX5vRRn.js +0 -39
  93. package/dist/client/VOverlay-CvrYEmLu.js +0 -967
  94. package/dist/client/WidgetsContainer-CmYjvGm7.js +0 -129
  95. package/dist/client/_commonjsHelpers-DaMA6jEr.js +0 -8
  96. package/dist/client/asWebComponent-B91uK0U7.js +0 -20361
  97. package/dist/client/basedecoder-DHcBySSe-BmCFNFnw.js +0 -88
  98. package/dist/client/decoder-CP4lv0Kb-B6yqkcfC.js +0 -10
  99. package/dist/client/deflate-BXt-9JA_-CWfClgpK.js +0 -10
  100. package/dist/client/eodashSTAC-DBjqe_Ho.js +0 -2788
  101. package/dist/client/eox-stacinfo-l7ALSV90.js +0 -13969
  102. package/dist/client/forwardRefs-BJJiadQP.js +0 -185
  103. package/dist/client/index-Q-bHLjxx.js +0 -153
  104. package/dist/client/jpeg-BAgeD1d3-oeHbFPUL.js +0 -514
  105. package/dist/client/lerc-DzVumYtB-P-KXC0TO.js +0 -1027
  106. package/dist/client/lzw-LAGDNbSC-DkP96qO9.js +0 -84
  107. package/dist/client/packbits-BlDR4Kj5-C66n1-zr.js +0 -24
  108. package/dist/client/pako.esm-CB1uQYY0-DB0PYm1P.js +0 -1081
  109. package/dist/client/raw-CMGvRjfu-BRi6E4i1.js +0 -9
  110. package/dist/client/ssrBoot-yo11mybw.js +0 -17
  111. package/dist/client/transition-CSJhuYGK.js +0 -34
  112. package/dist/client/webfontloader-qotgY98I.js +0 -435
  113. package/dist/client/webimage-BM_pbLN3-L2cGWK5l.js +0 -19
@@ -0,0 +1,432 @@
1
+ import { Collection, Item } from "stac-js";
2
+ import { toAbsolute } from "stac-js/src/http.js";
3
+ import {
4
+ extractLayerConfig,
5
+ extractLayerDatetime,
6
+ extractRoles,
7
+ fetchStyle,
8
+ findLayer,
9
+ generateFeatures,
10
+ replaceLayer,
11
+ } from "./helpers";
12
+ import {
13
+ getLayers,
14
+ getCompareLayers,
15
+ registerProjection,
16
+ } from "@/store/actions";
17
+ import { createLayersFromAssets, createLayersFromLinks } from "./createLayers";
18
+ import axios from "@/plugins/axios";
19
+ import log from "loglevel";
20
+
21
+ export class EodashCollection {
22
+ #collectionUrl = "";
23
+
24
+ /** @type {import("stac-ts").StacCollection | undefined} */
25
+ #collectionStac;
26
+
27
+ /**
28
+ * @type {import("stac-ts").StacLink
29
+ * | import("stac-ts").StacItem
30
+ * | undefined}
31
+ */
32
+ selectedItem;
33
+
34
+ // read only
35
+ get collectionStac() {
36
+ return this.#collectionStac;
37
+ }
38
+
39
+ /** @param {string} collectionUrl */
40
+ constructor(collectionUrl) {
41
+ this.#collectionUrl = collectionUrl;
42
+ }
43
+
44
+ /**
45
+ * @async
46
+ * @param {import('stac-ts').StacLink | Date} [linkOrDate]
47
+ * @returns
48
+ */
49
+ createLayersJson = async (linkOrDate) => {
50
+ /**
51
+ * @type {import("stac-ts").StacLink | undefined}
52
+ **/
53
+ let stacItem;
54
+
55
+ /**
56
+ * @type {import("stac-ts").StacCollection | undefined}
57
+ **/
58
+ let stac;
59
+ // TODO get auxiliary layers from collection
60
+ /** @type {Record<string,any>[]} */
61
+ let layersJson = [];
62
+
63
+ // Load collectionstac if not yet initialized
64
+ stac = await this.fetchCollection();
65
+
66
+ const isGeoDB = stac?.endpointtype === "GeoDB";
67
+
68
+ if (linkOrDate instanceof Date) {
69
+ // if collectionStac not yet initialized we do it here
70
+ stacItem = this.getItem(linkOrDate);
71
+ } else {
72
+ stacItem = linkOrDate;
73
+ }
74
+
75
+ const stacItemUrl = stacItem
76
+ ? toAbsolute(stacItem.href, this.#collectionUrl)
77
+ : this.#collectionUrl;
78
+
79
+ stac = await axios.get(stacItemUrl).then((resp) => resp.data);
80
+
81
+ if (!stacItem) {
82
+ // no specific item was requested; render last item
83
+ this.#collectionStac = new Collection(stac);
84
+ this.selectedItem = this.getItem();
85
+
86
+ if (this.selectedItem) {
87
+ layersJson = await this.createLayersJson(this.selectedItem);
88
+ } else {
89
+ console.warn(
90
+ "[eodash] the selected collection does not include any items",
91
+ );
92
+ }
93
+ return [];
94
+ } else {
95
+ // specific item was requested
96
+ const item = new Item(stac);
97
+ this.selectedItem = item;
98
+ const title =
99
+ this.#collectionStac?.title || this.#collectionStac?.id || "";
100
+ layersJson.unshift(
101
+ ...(await this.buildJsonArray(item, stacItemUrl, title, isGeoDB)),
102
+ );
103
+ return layersJson;
104
+ }
105
+ };
106
+
107
+ /**
108
+ * @param {import("stac-ts").StacItem} item
109
+ * @param {string} itemUrl
110
+ * @param {string} title
111
+ * @param {boolean} isGeoDB
112
+ * @param {string} [itemDatetime]
113
+ * @returns {Promise<Record<string,any>[]>} layers
114
+ * */
115
+ async buildJsonArray(item, itemUrl, title, isGeoDB, itemDatetime) {
116
+ log.debug(
117
+ "Building JSON array",
118
+ item,
119
+ itemUrl,
120
+ title,
121
+ isGeoDB,
122
+ itemDatetime,
123
+ );
124
+ await this.fetchCollection();
125
+ // registering top level indicator projection
126
+ const indicatorProjection =
127
+ item?.["proj:epsg"] || item?.["eodash:proj4_def"];
128
+ await registerProjection(
129
+ /** @type {number | string | {name: string, def: string; extent: number[] | undefined;} } */ (
130
+ indicatorProjection
131
+ ),
132
+ );
133
+
134
+ const jsonArray = [];
135
+
136
+ if (isGeoDB) {
137
+ // handled by getGeoDBLayer
138
+ return [];
139
+ }
140
+
141
+ // I propose following approach, we "manually" create configurations
142
+ // for the rendering options we know and expect.
143
+ // If we don't find any we fallback to using the STAC ol item that
144
+ // will try to extract anything it supports but for which we have
145
+ // less control.
146
+
147
+ let { layerConfig, style } = extractLayerConfig(
148
+ await fetchStyle(item, itemUrl),
149
+ );
150
+
151
+ const layerDatetime = extractLayerDatetime(
152
+ this.getItems(),
153
+ item.properties?.datetime ?? itemDatetime,
154
+ );
155
+
156
+ const dataAssets = Object.keys(item?.assets ?? {}).reduce((data, ast) => {
157
+ if (item.assets[ast].roles?.includes("data")) {
158
+ data[ast] = item.assets[ast];
159
+ }
160
+ return data;
161
+ }, /** @type {Record<string,import('stac-ts').StacAsset>} */ ({}));
162
+ const isSupported =
163
+ item.links.some((link) => ["wms", "xyz", "wmts"].includes(link.rel)) ||
164
+ Object.keys(dataAssets).length;
165
+
166
+ if (isSupported) {
167
+ // Checking for potential legend asset
168
+ let extraProperties = null;
169
+ if (this.#collectionStac?.assets?.legend?.href) {
170
+ extraProperties = {
171
+ description: `<div style="width: 100%">
172
+ <img src="${this.#collectionStac.assets.legend.href}" style="max-height:70px; margin-top:-15px; margin-bottom:-20px;" />
173
+ </div>`,
174
+ };
175
+ }
176
+ // Check if collection has eox:colorlegend definition, if yes overwrite legend description
177
+ if (this.#collectionStac && this.#collectionStac["eox:colorlegend"]) {
178
+ extraProperties = {
179
+ layerLegend: this.#collectionStac["eox:colorlegend"],
180
+ };
181
+ }
182
+ const links = await createLayersFromLinks(
183
+ this.#collectionStac?.id ?? "",
184
+ title,
185
+ item,
186
+ layerDatetime,
187
+ extraProperties,
188
+ );
189
+ jsonArray.push(
190
+ ...links,
191
+ ...(await createLayersFromAssets(
192
+ this.#collectionStac?.id ?? "",
193
+ title || this.#collectionStac?.title || item.id,
194
+ dataAssets,
195
+ item,
196
+ style,
197
+ layerConfig,
198
+ layerDatetime,
199
+ extraProperties,
200
+ )),
201
+ );
202
+ } else {
203
+ // fallback to STAC
204
+ const json = {
205
+ type: "STAC",
206
+ displayWebMapLink: true,
207
+ displayFootprint: false,
208
+ data: item,
209
+ properties: {
210
+ id: this.#collectionStac?.id ?? "",
211
+ title: title || item.id,
212
+ layerConfig,
213
+ },
214
+ style,
215
+ };
216
+ extractRoles(
217
+ json.properties,
218
+ //@ts-expect-error using the item incase no self link is found
219
+ item.links.find((link) => link.rel === "self") ?? item,
220
+ );
221
+ jsonArray.push(json);
222
+ }
223
+
224
+ return jsonArray;
225
+ }
226
+
227
+ async fetchCollection() {
228
+ if (!this.#collectionStac) {
229
+ log.debug("Fetching collection file", this.#collectionUrl);
230
+ const col = await axios
231
+ .get(this.#collectionUrl)
232
+ .then((resp) => resp.data);
233
+ this.#collectionStac = new Collection(col);
234
+ }
235
+ return this.#collectionStac;
236
+ }
237
+
238
+ getItems() {
239
+ return (
240
+ this.#collectionStac?.links
241
+ .filter((i) => i.rel === "item")
242
+ // sort by `datetime`, where oldest is first in array
243
+ .sort((a, b) =>
244
+ /** @type {number} */ (a.datetime) <
245
+ /** @type {number} */ (b.datetime)
246
+ ? -1
247
+ : 1,
248
+ )
249
+ );
250
+ }
251
+
252
+ getDates() {
253
+ return (
254
+ this.#collectionStac?.links
255
+ .filter((i) => i.rel === "item")
256
+ // sort by `datetime`, where oldest is first in array
257
+ .sort((a, b) =>
258
+ /** @type {number} */ (a.datetime) <
259
+ /** @type {number} */ (b.datetime)
260
+ ? -1
261
+ : 1,
262
+ )
263
+ .map((i) => new Date(/** @type {number} */ (i.datetime)))
264
+ );
265
+ }
266
+
267
+ async getExtent() {
268
+ await this.fetchCollection();
269
+ return this.#collectionStac?.extent;
270
+ }
271
+
272
+ /**
273
+ * Get closest Item Link from a certain date,
274
+ * get the latest if no date provided
275
+ * @param {Date} [date]
276
+ **/
277
+ getItem(date) {
278
+ return date
279
+ ? this.getItems()?.sort((a, b) => {
280
+ const distanceA = Math.abs(
281
+ new Date(/** @type {number} */ (a.datetime)).getTime() -
282
+ date.getTime(),
283
+ );
284
+ const distanceB = Math.abs(
285
+ new Date(/** @type {number} */ (b.datetime)).getTime() -
286
+ date.getTime(),
287
+ );
288
+ return distanceA - distanceB;
289
+ })[0]
290
+ : this.getItems()?.at(-1);
291
+ }
292
+
293
+ /**
294
+ *
295
+ * @param {string} datetime
296
+ * @param {string} layer
297
+ * @param {string} map
298
+ */
299
+ async updateLayerJson(datetime, layer, map) {
300
+ await this.fetchCollection();
301
+
302
+ // get the link of the specified date
303
+ const specifiedLink = this.getItems()?.find(
304
+ (item) =>
305
+ typeof item.datetime === "string" &&
306
+ new Date(item.datetime).toISOString() === datetime,
307
+ );
308
+
309
+ if (!specifiedLink) {
310
+ console.warn(
311
+ "[eodash] no Item found for the provided datetime",
312
+ datetime,
313
+ );
314
+ return;
315
+ }
316
+
317
+ // create json layers from the item
318
+ const newLayers = await this.createLayersJson(specifiedLink);
319
+
320
+ let currentLayers = getLayers();
321
+ if (map === "second") {
322
+ currentLayers = getCompareLayers();
323
+ }
324
+
325
+ /** @type {string | undefined} */
326
+ const oldLayerID = findLayer(currentLayers, layer)?.properties.id;
327
+
328
+ if (!oldLayerID) {
329
+ return;
330
+ }
331
+
332
+ const updatedLayers = replaceLayer(currentLayers, oldLayerID, newLayers);
333
+
334
+ return updatedLayers;
335
+ }
336
+
337
+ /**
338
+ * Returns base layers and overlay layers of a STAC Collection
339
+ *
340
+ * @param {import("stac-ts").StacCollection} indicator */
341
+ static async getIndicatorLayers(indicator) {
342
+ const indicatorAssets = Object.keys(indicator?.assets ?? {}).reduce(
343
+ (assets, ast) => {
344
+ if (
345
+ indicator.assets?.[ast].roles?.includes("baselayer") ||
346
+ indicator.assets?.[ast].roles?.includes("overlay")
347
+ ) {
348
+ assets[ast] = indicator.assets[ast];
349
+ }
350
+ return assets;
351
+ },
352
+ /** @type {Record<string,import('stac-ts').StacAsset>} */ ({}),
353
+ );
354
+
355
+ return [
356
+ ...(await createLayersFromLinks(
357
+ indicator?.id ?? "",
358
+ indicator?.title || indicator.id,
359
+ //@ts-expect-error indicator instead of item
360
+ indicator,
361
+ // layerDatetime,
362
+ )),
363
+ ...(await createLayersFromAssets(
364
+ indicator?.id ?? "",
365
+ indicator?.title || indicator.id,
366
+ indicatorAssets,
367
+ //@ts-expect-error indicator instead of item
368
+ indicator,
369
+ // style,
370
+ // layerConfig,
371
+ // layerDatetime,
372
+ )),
373
+ ];
374
+ }
375
+
376
+ /**
377
+ * Returns GeoDB layer from a list of EodashCollections
378
+ *
379
+ * @param {EodashCollection[]} eodashCollections
380
+ *
381
+ **/
382
+ static getGeoDBLayer(eodashCollections) {
383
+ const allFeatures = [];
384
+ for (const collection of eodashCollections) {
385
+ const isGeoDB = collection.#collectionStac?.endpointtype === "GeoDB";
386
+ if (!isGeoDB) {
387
+ continue;
388
+ }
389
+ const collectionFeatures = generateFeatures(
390
+ collection.#collectionStac?.links,
391
+ ).features;
392
+ if (collectionFeatures.length) {
393
+ allFeatures.push(
394
+ generateFeatures(collection.#collectionStac?.links).features,
395
+ );
396
+ }
397
+ }
398
+ if (allFeatures.length) {
399
+ const featureCollection = {
400
+ type: "FeatureCollection",
401
+ crs: {
402
+ type: "name",
403
+ properties: {
404
+ name: "EPSG:4326",
405
+ },
406
+ },
407
+ features: allFeatures.flat(),
408
+ };
409
+ return {
410
+ type: "Vector",
411
+ properties: {
412
+ id: "geodb-collection",
413
+ title: "GeoDB Collection",
414
+ },
415
+ source: {
416
+ type: "Vector",
417
+ url: "data:," + encodeURIComponent(JSON.stringify(featureCollection)),
418
+ format: "GeoJSON",
419
+ },
420
+ style: {
421
+ "circle-radius": 5,
422
+ "circle-fill-color": "#00417077",
423
+ "circle-stroke-color": "#004170",
424
+ "fill-color": "#00417077",
425
+ "stroke-color": "#004170",
426
+ },
427
+ interactions: [],
428
+ };
429
+ }
430
+ return null;
431
+ }
432
+ }