@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,82 @@
1
+ <template>
2
+ <div class="flex-grow-1 fill-height overflow-auto">
3
+ <eox-stacinfo
4
+ .for="currentUrl"
5
+ .allowHtml="allowHtml"
6
+ .body="body"
7
+ .featured="featured"
8
+ .footer="footer"
9
+ .styleOverride="styleOverride"
10
+ .header="header"
11
+ .subheader="subheader"
12
+ .tags="tags"
13
+ style="--color-primary-lighter: none"
14
+ >
15
+ </eox-stacinfo>
16
+ </div>
17
+ </template>
18
+
19
+ <script setup>
20
+ import "@eox/stacinfo";
21
+ import { currentUrl } from "@/store/states";
22
+
23
+ const {
24
+ allowHtml,
25
+ featured,
26
+ footer,
27
+ header,
28
+ body,
29
+ styleOverride,
30
+ subheader,
31
+ tags,
32
+ } = defineProps({
33
+ allowHtml: {
34
+ type: Boolean,
35
+ default: true,
36
+ },
37
+
38
+ styleOverride: {
39
+ type: String,
40
+ default: `
41
+ .single-property {columns: 1!important;}
42
+ h1 {margin:0px!important;font-size:16px!important;}
43
+ header h1:after {
44
+ content:' ';
45
+ display:block;
46
+ border:1px solid #d0d0d0;
47
+ }
48
+ h2 {font-size:15px}
49
+ h3 {font-size:14px}
50
+ summary {cursor: pointer;}
51
+ #properties li > .value { font-weight: normal !important;}
52
+ main {padding-bottom: 10px;}
53
+ .footer-container {line-height:1;}
54
+ .footer-container button {margin-top: -10px;}
55
+ .footer-container small {font-size:10px;line-height:1;}`,
56
+ },
57
+ header: {
58
+ type: Array,
59
+ default: () => ["title"],
60
+ },
61
+ tags: {
62
+ type: Array,
63
+ default: () => ["themes"],
64
+ },
65
+ subheader: {
66
+ type: Array,
67
+ default: () => [],
68
+ },
69
+ body: {
70
+ type: Array,
71
+ default: () => ["satellite", "sensor", "agency", "extent"],
72
+ },
73
+ featured: {
74
+ type: Array,
75
+ default: () => ["description", "providers", "assets", "links"],
76
+ },
77
+ footer: {
78
+ type: Array,
79
+ default: () => ["sci:citation"],
80
+ },
81
+ });
82
+ </script>
@@ -0,0 +1,83 @@
1
+ <template>
2
+ <div
3
+ ref="rootEl"
4
+ class="d-flex flex-column fill-height overflow-auto bg-primary"
5
+ >
6
+ <div class="d-flex flex-row justify-space-between pa-4 align-center">
7
+ <v-btn
8
+ v-if="props.showIndicatorsBtn"
9
+ color="secondary"
10
+ class="text-none py-2 px-4"
11
+ :append-icon="[mdiPlus]"
12
+ :text="indicatorBtnText"
13
+ @click="dialog = !dialog"
14
+ >
15
+ </v-btn>
16
+ <EodashLayoutSwitcher
17
+ v-if="props.showLayoutSwitcher"
18
+ :target="layoutTarget"
19
+ :icon="layoutIcon"
20
+ />
21
+ </div>
22
+ <PopUp
23
+ v-model="dialog"
24
+ :maxWidth="popupWidth"
25
+ :width="popupWidth"
26
+ :max-height="popupHeight"
27
+ :height="popupHeight"
28
+ >
29
+ <EodashItemFilter
30
+ class="pa-4"
31
+ results-title=""
32
+ v-bind="props.itemFilterConfig"
33
+ @select="dialog = !dialog"
34
+ />
35
+ </PopUp>
36
+ </div>
37
+ </template>
38
+
39
+ <script setup>
40
+ import PopUp from "^/PopUp.vue";
41
+ import EodashItemFilter from "^/EodashItemFilter.vue";
42
+ import EodashLayoutSwitcher from "^/EodashLayoutSwitcher.vue";
43
+ import { mdiPlus, mdiViewDashboard } from "@mdi/js";
44
+ import { computed, ref } from "vue";
45
+ import { makePanelTransparent } from "@/composables";
46
+ import { useDisplay } from "vuetify/lib/framework.mjs";
47
+
48
+ const dialog = ref(false);
49
+
50
+ const { smAndDown } = useDisplay();
51
+ const popupWidth = computed(() => (smAndDown.value ? "80%" : "1500px"));
52
+ const popupHeight = computed(() => (smAndDown.value ? "90%" : "800px"));
53
+
54
+ const props = defineProps({
55
+ showIndicatorsBtn: {
56
+ type: Boolean,
57
+ default: true,
58
+ },
59
+ showLayoutSwitcher: {
60
+ type: Boolean,
61
+ default: true,
62
+ },
63
+ layoutTarget: {
64
+ type: String,
65
+ default: "light",
66
+ },
67
+ // mdi/js icon
68
+ layoutIcon: {
69
+ type: String,
70
+ default: mdiViewDashboard,
71
+ },
72
+ indicatorBtnText: {
73
+ type: String,
74
+ default: "Select indicator",
75
+ },
76
+ itemFilterConfig: {
77
+ type: Object,
78
+ default: () => {},
79
+ },
80
+ });
81
+ const rootEl = ref(null);
82
+ makePanelTransparent(rootEl);
83
+ </script>
@@ -1,17 +1,17 @@
1
1
  <template>
2
2
  <PopUp v-model="dialog">
3
- <v-card>
4
- <v-card-title class="bg-primary">
3
+ <v-card style="max-height: 498px">
4
+ <v-card-title class="bg-primary" style="max-height: 49px">
5
5
  <h5 class="text-h5">Storytelling map configuration</h5>
6
6
  </v-card-title>
7
7
 
8
- <v-card-text class="py-5">
8
+ <v-card-text class="py-5 overflow-auto" style="height: 400px">
9
9
  <p class="text-body-2">
10
- Copy and paste this code into the map layers field of the storytelling
11
- editor:
10
+ Copy and paste this code into the map <b>layers field</b> of the
11
+ storytelling editor:
12
12
  </p>
13
13
  <div class="pa-3 code-block">
14
- {{ getLayers() }}
14
+ {{ removeUnneededProperties(getLayers()) }}
15
15
  </div>
16
16
 
17
17
  <div style="position: absolute; bottom: 15px">
@@ -41,7 +41,7 @@
41
41
 
42
42
  <v-divider></v-divider>
43
43
 
44
- <v-card-actions>
44
+ <v-card-actions style="max-height: 49px">
45
45
  <v-spacer></v-spacer>
46
46
  <v-btn variant="text" @click="dialog = !dialog"> Close </v-btn>
47
47
  </v-card-actions>
@@ -53,8 +53,9 @@ import { mdiClipboardCheckOutline, mdiContentCopy } from "@mdi/js";
53
53
  import PopUp from "./PopUp.vue";
54
54
  import { copyToClipBoard } from "@/utils";
55
55
  import { computed, ref } from "vue";
56
- import { getLayers as getLayerAction } from "@/store/Actions";
57
- import { mapPosition } from "@/store/States";
56
+ import { getLayers as getLayerAction } from "@/store/actions";
57
+ import { mapPosition } from "@/store/states";
58
+ import { removeUnneededProperties } from "@/eodashSTAC/helpers";
58
59
 
59
60
  const dialog = defineModel({ type: Boolean, required: true, default: false });
60
61
 
@@ -88,19 +89,20 @@ const copyBtns = [
88
89
 
89
90
  const mapStepCode = computed(() => {
90
91
  const [x, y, z] = mapPosition.value;
91
- const preTag = "### <!--{ layers=";
92
+ const preTag = "### <!" + "--{ layers=";
92
93
  const endTag = `zoom="${z}" center=[${[x, y]}] animationOptions={duration:500}}-->
93
94
  #### Tour step title
94
95
  Text describing the current step of the tour and why it is interesting what the map shows currently
95
96
  `;
96
- return `${preTag}'${JSON.stringify(props.getLayers())}' ${endTag}`;
97
+ return `${preTag}'${JSON.stringify(removeUnneededProperties(props.getLayers()))}' ${endTag}`;
97
98
  });
98
99
  const mapEntryCode = computed(() => {
99
100
  const [x, y, z] = mapPosition.value;
100
101
  const preTag =
101
- '## Map Example <!--{as="eox-map" style="width: 100%; height: 500px;" layers=';
102
+ "## Map Example <!" +
103
+ '--{as="eox-map" style="width: 100%; height: 500px;" layers=';
102
104
  const endTag = `zoom="${z}" center=[${[x, y]}] }-->`;
103
- return `${preTag}'${JSON.stringify(props.getLayers())}' ${endTag}`;
105
+ return `${preTag}'${JSON.stringify(removeUnneededProperties(props.getLayers()))}' ${endTag}`;
104
106
  });
105
107
  </script>
106
108
  <style scoped>
@@ -108,5 +110,7 @@ const mapEntryCode = computed(() => {
108
110
  background-color: #ddd;
109
111
  font-family: monospace;
110
112
  font-size: small;
113
+ max-height: 200px;
114
+ overflow-y: auto;
111
115
  }
112
116
  </style>
package/widgets/PopUp.vue CHANGED
@@ -1,8 +1,7 @@
1
1
  <template>
2
2
  <span>
3
3
  <v-dialog
4
- max-width="500px"
5
- max-height="500px"
4
+ v-bind="config"
6
5
  absolute
7
6
  scrollable
8
7
  scroll-strategy="block"
@@ -34,7 +33,30 @@ const props = defineProps({
34
33
  type: Object,
35
34
  default: undefined,
36
35
  },
36
+ maxWidth: {
37
+ type: String,
38
+ default: "500px",
39
+ },
40
+ maxHeight: {
41
+ type: String,
42
+ default: "500px",
43
+ },
44
+ width: {
45
+ type: String,
46
+ default: "500px",
47
+ },
48
+ height: {
49
+ type: String,
50
+ default: "500px",
51
+ },
37
52
  });
38
53
 
54
+ const config = {
55
+ maxWidth: props.maxWidth,
56
+ maxHeight: props.maxHeight,
57
+ width: props.width,
58
+ height: props.height,
59
+ };
60
+
39
61
  const [definedWidget] = useDefineWidgets([props?.widget]);
40
62
  </script>
@@ -1,105 +0,0 @@
1
- <template>
2
- <v-app ref="vAppRef">
3
- <Suspense>
4
- <Dashboard :on-template-mount="setStylesFromHead" :config="config" />
5
-
6
- <template #fallback>
7
- <ErrorAlert @vue:mounted="setStylesFromHead()" v-model="error" />
8
- </template>
9
- </Suspense>
10
- </v-app>
11
- </template>
12
- <script setup>
13
- import Dashboard from "@/views/Dashboard.vue";
14
- import { createApp, getCurrentInstance, onErrorCaptured, ref } from "vue";
15
- import { registerPlugins } from "@/plugins";
16
- import { eodashKey } from "@/utils/keys";
17
- import ErrorAlert from "@/components/ErrorAlert.vue";
18
-
19
- defineProps({
20
- config: {
21
- type: String,
22
- },
23
- });
24
-
25
- /** @type {import("vue").Ref<import("vuetify/components").VApp | null>} */
26
- const vAppRef = ref(null);
27
- const app = createApp({});
28
- registerPlugins(app);
29
-
30
- const inst = getCurrentInstance();
31
-
32
- Object.assign(inst?.appContext ?? {}, app._context);
33
-
34
- //@ts-expect-error Property 'provides' does not exist on type 'ComponentInternalInstance'
35
- Object.assign(inst?.provides ?? {}, app._context.provides);
36
-
37
- /**
38
- * @param {import("vue").Ref<
39
- * HTMLElement | import("vue").ComponentPublicInstance
40
- * >[]} [hiddenElements]
41
- */
42
- function setStylesFromHead(hiddenElements) {
43
- const eodashShadowRoot = vAppRef.value?.$el.getRootNode();
44
- const styleSheet = new CSSStyleSheet();
45
- const head = document.querySelector("head");
46
- let stylesStr = "";
47
-
48
- Array.from(head?.children ?? []).forEach((child) => {
49
- if (child.getAttribute("type") === "text/css") {
50
- stylesStr += `\n ${child.innerHTML}`;
51
- return;
52
- }
53
-
54
- if (
55
- child.tagName == "LINK" &&
56
- child.getAttribute("rel")?.includes("stylesheet")
57
- ) {
58
- eodashShadowRoot?.appendChild(child.cloneNode(true));
59
- }
60
- });
61
-
62
- stylesStr += `\n
63
- ${
64
- //@ts-expect-error Property 'provides' does not exist on type 'ComponentInternalInstance'
65
- /** @type {import("@/types").Eodash} */ (inst?.provides[eodashKey])
66
- ?.brand.noLayout
67
- ? `div.v-application__wrap {
68
- min-height: fit-content;
69
- }`
70
- : ""
71
- }
72
- `;
73
- styleSheet.replaceSync(stylesStr.replaceAll(":root", ":host"));
74
- eodashShadowRoot?.adoptedStyleSheets.push(styleSheet);
75
-
76
- if (
77
- hiddenElements &&
78
- !(
79
- //@ts-expect-error Property 'provides' does not exist on type 'ComponentInternalInstance'
80
- /** @type {import("@/types").Eodash} */ (inst.provides[eodashKey])?.brand
81
- .noLayout
82
- )
83
- ) {
84
- hiddenElements.forEach((element) => {
85
- if (element.value) {
86
- if (element.value instanceof HTMLElement) {
87
- element.value.style.opacity = "1";
88
- } else {
89
- /** @type {HTMLElement} */
90
- (element.value.$el).style.opacity = "1";
91
- }
92
- }
93
- });
94
- }
95
- }
96
-
97
- const error = ref("");
98
- onErrorCaptured((e, comp, info) => {
99
- error.value = `
100
- ${e}.
101
- component: ${comp?.$.type.name}.
102
- info: ${info}.
103
- `;
104
- });
105
- </script>
@@ -1,23 +0,0 @@
1
- /** @group WebComponent */
2
- type EodashConstructor = import("vue").VueElementConstructor<
3
- import("vue").ExtractPropTypes<{ config: string }>
4
- >;
5
- /**
6
- * Eodash Web Component constructor
7
- *
8
- * @group WebComponent
9
- */
10
- export declare const Eodash: EodashConstructor;
11
- /**
12
- * Registers `eo-dash` as Custom Element in the window
13
- *
14
- * @group WebComponent
15
- */
16
- export declare function register(): void;
17
-
18
- /**
19
- * Eodash store @see EodashStore
20
- *
21
- * @group WebComponent
22
- */
23
- export declare const store: import("./types").EodashStore;
@@ -1,14 +0,0 @@
1
- /**
2
- * Returns the current layers of the `eox-map`
3
- * @param {string} [el="eox-map"] - `eox-map` element selector
4
- * @returns {object[]}
5
- */
6
- export const getLayers = (el = "eox-map") =>
7
- customElements.get("eo-dash")
8
- ? document
9
- .querySelector("eo-dash")
10
- ?.shadowRoot?.querySelector(el)
11
- //@ts-expect-error `layers` doesn't exist on type element
12
- ?.layers.toReversed()
13
- : //@ts-expect-error `layers` doesn't exist on type element
14
- document.querySelector(el)?.layers.toReversed();
@@ -1,16 +0,0 @@
1
- import { ref } from "vue";
2
-
3
- /** Currently selected STAC endpoint */
4
- export const currentUrl = ref("");
5
- /** Currently selected datetime */
6
- export const datetime = ref(new Date().toISOString());
7
-
8
- /** Currently selected indicator */
9
- export const indicator = ref("");
10
-
11
- /**
12
- * Current map position
13
- *
14
- * @type {import("vue").Ref<(number | undefined)[]>}
15
- */
16
- export const mapPosition = ref([]);
@@ -1,249 +0,0 @@
1
- import { Collection, Item } from "stac-js";
2
- import { toAbsolute } from "stac-js/src/http.js";
3
- import { generateFeatures } from "./helpers";
4
- import axios from "axios";
5
-
6
- /**
7
- * Function to extract collection urls from an indicator
8
- * @param {import("stac-ts").StacCatalog
9
- * | import("stac-ts").StacCollection
10
- * | import("stac-ts").StacItem
11
- * | null
12
- * } stacObject
13
- * @param {string} basepath
14
- * @returns {string[]}
15
- */
16
- export function extractCollectionUrls(stacObject, basepath) {
17
- const collectionUrls = [];
18
- // Support for two structure types, flat and indicator, simplified here:
19
- // Flat assumes Catalog-Collection-Item
20
- // Indicator assumes Catalog-Collection-Collection-Item
21
- // TODO: this is not the most stable test approach,
22
- // we should discuss potential other approaches
23
- //
24
- if (stacObject?.links && stacObject?.links[1].rel === "item") {
25
- collectionUrls.push(basepath);
26
- } else if (stacObject?.links[1].rel === "child") {
27
- // TODO: Iterate through all children to create collections
28
- stacObject.links.forEach((link) => {
29
- if (link.rel === "child") {
30
- collectionUrls.push(toAbsolute(link.href, basepath));
31
- }
32
- });
33
- }
34
- return collectionUrls;
35
- }
36
- export class EodashCollection {
37
- /** @type {string} */
38
- #collectionUrl = "";
39
- /** @type {import("stac-ts").StacCollection | undefined} */
40
- #collectionStac;
41
- /**
42
- * @type {import("stac-ts").StacLink
43
- * | import("stac-ts").StacItem
44
- * | undefined}
45
- */
46
- selectedItem;
47
-
48
- /** @param {string} collectionUrl */
49
- constructor(collectionUrl) {
50
- this.#collectionUrl = collectionUrl;
51
- }
52
- /**
53
- * @async
54
- * @param {any} item
55
- * @returns
56
- */
57
- createLayersJson = async (item = null) => {
58
- /** @type {import("stac-ts").StacLink | undefined} */
59
- let stacItem,
60
- /** @type {import("stac-ts").StacCollection | undefined} */
61
- stac;
62
- // TODO get auxiliary layers from collection
63
- /** @type {object[]} */
64
- let layersJson = [
65
- /*{
66
- type: "Tile",
67
- properties: {
68
- id: "OSM",
69
- },
70
- source: {
71
- type: "OSM",
72
- },
73
- },*/
74
- ];
75
- // Load collectionstac if not yet initialized
76
- if (!this.#collectionStac) {
77
- const response = await axios.get(this.#collectionUrl);
78
- stac = await response.data;
79
- this.#collectionStac = new Collection(stac);
80
- }
81
-
82
- if (stac && stac.endpointtype === "GeoDB") {
83
- // Special handling of point based data
84
- const allFeatures = generateFeatures(stac.links);
85
- layersJson.unshift({
86
- type: "Vector",
87
- properties: {
88
- id: stac.id,
89
- },
90
- source: {
91
- type: "Vector",
92
- url: "data:," + encodeURIComponent(JSON.stringify(allFeatures)),
93
- format: "GeoJSON",
94
- },
95
- style: {
96
- "circle-radius": 5,
97
- "circle-fill-color": "#00417077",
98
- "circle-stroke-color": "#004170",
99
- "fill-color": "#00417077",
100
- "stroke-color": "#004170",
101
- },
102
- });
103
- return layersJson;
104
- } else {
105
- if (item instanceof Date) {
106
- // if collectionStac not yet initialized we do it here
107
- stacItem = this.getItems()?.sort((a, b) => {
108
- const distanceA = Math.abs(
109
- new Date(/** @type {number} */ (a.datetime)).getTime() -
110
- item.getTime(),
111
- );
112
- const distanceB = Math.abs(
113
- new Date(/** @type {number} */ (b.datetime)).getTime() -
114
- item.getTime(),
115
- );
116
- return distanceA - distanceB;
117
- })[0];
118
- this.selectedItem = stacItem;
119
- } else {
120
- stacItem = item;
121
- }
122
- const response = await fetch(
123
- stacItem
124
- ? toAbsolute(stacItem.href, this.#collectionUrl)
125
- : this.#collectionUrl,
126
- );
127
- stac = await response.json();
128
-
129
- if (!stacItem) {
130
- // no specific item was requested; render last item
131
- this.#collectionStac = new Collection(stac);
132
- const items = this.getItems();
133
- this.selectedItem = items?.[items.length - 1];
134
- if (this.selectedItem) {
135
- layersJson = await this.createLayersJson(this.selectedItem);
136
- } else {
137
- if (import.meta.env.DEV) {
138
- console.warn(
139
- "[eodash] the selected collection does not include any items",
140
- );
141
- }
142
- }
143
- return [];
144
- } else {
145
- // specific item was requested
146
- const item = new Item(stac);
147
- this.selectedItem = item;
148
- layersJson.unshift(...this.buildJsonArray(item));
149
- return layersJson;
150
- }
151
- }
152
- };
153
-
154
- /** @param {import("stac-ts").StacItem} item */
155
- buildJsonArray(item) {
156
- const jsonArray = [];
157
- // TODO: this currently assumes only one layer will be extracted
158
- // from an item, although it think this is currently true
159
- // potentially this could return multiple layers
160
- // TODO: implement other types, such as COG
161
-
162
- // I propose following approach, we "manually" create configurations
163
- // for the rendering options we know and expect.
164
- // If we don't find any we fallback to using the STAC ol item that
165
- // will try to extract anything it supports but for which we have
166
- // less control.
167
- const wms = item.links.find((l) => l.rel === "wms");
168
- // const projDef = false; // TODO: add capability to find projection in item
169
- if (wms) {
170
- let json = {
171
- type: "Tile",
172
- properties: {
173
- id: item.id,
174
- },
175
- source: {
176
- // if no projection information is provided we should
177
- // assume one, else for WMS requests it will try to get
178
- // the map projection that might not be supported
179
- // projection: projDef ? projDef : "EPSG:4326",
180
- type: "TileWMS",
181
- url: wms.href,
182
- params: {
183
- LAYERS: wms["wms:layers"],
184
- TILED: true,
185
- },
186
- },
187
- };
188
- if ("wms:dimensions" in wms) {
189
- // @ts-expect-error: waiting for eox-map to provide type definition
190
- json.source.params.time = wms["wms:dimensions"];
191
- }
192
- jsonArray.push(json);
193
- } else if (item.links.find((l) => l.rel === "wmts" || l.rel === "xyz")) {
194
- jsonArray.push({
195
- type: "STAC",
196
- displayWebMapLink: true,
197
- displayFootprint: false,
198
- data: item,
199
- properties: {
200
- id: item.id,
201
- },
202
- });
203
- } else {
204
- // fall back to rendering the feature
205
- jsonArray.push({
206
- type: "Vector",
207
- source: {
208
- type: "Vector",
209
- url: "data:," + encodeURIComponent(JSON.stringify(item.geometry)),
210
- format: "GeoJSON",
211
- },
212
- properties: {
213
- id: item.id,
214
- },
215
- });
216
- }
217
-
218
- return jsonArray;
219
- }
220
-
221
- getItems() {
222
- return (
223
- this.#collectionStac?.links
224
- .filter((i) => i.rel === "item")
225
- // sort by `datetime`, where oldest is first in array
226
- .sort((a, b) =>
227
- /** @type {number} */ (a.datetime) <
228
- /** @type {number} */ (b.datetime)
229
- ? -1
230
- : 1,
231
- )
232
- );
233
- }
234
-
235
- getDates() {
236
- return (
237
- this.#collectionStac?.links
238
- .filter((i) => i.rel === "item")
239
- // sort by `datetime`, where oldest is first in array
240
- .sort((a, b) =>
241
- /** @type {number} */ (a.datetime) <
242
- /** @type {number} */ (b.datetime)
243
- ? -1
244
- : 1,
245
- )
246
- .map((i) => new Date(/** @type {number} */ (i.datetime)))
247
- );
248
- }
249
- }