@eodash/eodash 5.0.0-alpha.2.4 → 5.0.0-alpha.2.6
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.
- package/README.md +31 -7
- package/core/client/App.vue +6 -7
- package/core/client/SuspensedDashboard.ce.vue +59 -45
- package/core/client/asWebComponent.d.ts +10 -5
- package/core/client/asWebComponent.js +6 -6
- package/core/client/components/DashboardLayout.vue +63 -21
- package/core/client/components/DynamicWebComponent.vue +44 -44
- package/core/client/components/ErrorAlert.vue +24 -7
- package/core/client/components/Footer.vue +34 -15
- package/core/client/components/Header.vue +10 -5
- package/core/client/components/IframeWrapper.vue +4 -4
- package/core/client/components/Loading.vue +17 -18
- package/core/client/components/MobileLayout.vue +82 -29
- package/core/client/composables/DefineEodash.js +38 -28
- package/core/client/composables/DefineWidgets.js +105 -79
- package/core/client/composables/index.js +43 -141
- package/core/client/eodash.js +46 -39
- package/core/client/main.js +2 -2
- package/core/client/plugins/index.js +11 -9
- package/core/client/plugins/vuetify.js +9 -10
- package/core/client/render.js +4 -5
- package/core/client/store/States.js +8 -13
- package/core/client/store/index.js +14 -11
- package/core/client/store/stac.js +51 -37
- package/core/client/types.d.ts +173 -248
- package/core/client/utils/eodashSTAC.js +151 -66
- package/core/client/utils/helpers.js +18 -20
- package/core/client/utils/index.js +25 -14
- package/core/client/utils/keys.js +2 -2
- package/core/client/views/Dashboard.vue +70 -42
- package/core/client/vite-env.d.ts +19 -17
- package/dist/client/DashboardLayout-BuDcv6LM.js +156 -0
- package/dist/client/{DynamicWebComponent-C4Hotc4H.js → DynamicWebComponent-BEP4rVce.js} +7 -7
- package/dist/client/EodashDatePicker-oFb1zt5E.js +1211 -0
- package/dist/client/EodashItemFilter-BElmgrST.js +63 -0
- package/dist/client/{EodashMap-CGrQjZ1P.js → EodashMap-DXyOgcEd.js} +11333 -14025
- package/dist/client/Footer-CoPx6UXQ.js +115 -0
- package/dist/client/Header-C-zX31Ys.js +635 -0
- package/dist/client/{IframeWrapper-Cg3GMmfW.js → IframeWrapper-2w2ye0zM.js} +4 -4
- package/dist/client/MobileLayout-C9OVcP12.js +945 -0
- package/dist/client/{VMain-BHYlmRic.js → VMain-Dm43jd43.js} +8 -8
- package/dist/client/{WidgetsContainer-dje9QSk0.js → WidgetsContainer-BS87sLqk.js} +12 -5
- package/dist/client/asWebComponent-CpQUVi2N.js +20135 -0
- package/dist/client/{basedecoder-Qm25PwVp-CHo5Pomv.js → basedecoder-DHcBySSe-BmCFNFnw.js} +5 -6
- package/dist/client/{decoder-HRvnjnEI-BQ2rajuJ.js → decoder-CP4lv0Kb-BHrv68IA.js} +1 -1
- package/dist/client/deflate-BXt-9JA_-CWfClgpK.js +10 -0
- package/dist/client/eo-dash.js +3 -3
- package/dist/client/eodashSTAC-Q7kbX1Gy.js +2788 -0
- package/dist/client/{eox-itemfilter-DcQkRD2l.js → eox-itemfilter-TaBxgqq_.js} +1002 -974
- package/dist/client/{eox-map-C3DL31fp.js → eox-map-L7abwKTR.js} +5677 -5695
- package/dist/client/forwardRefs-BVFQ82G4.js +183 -0
- package/dist/client/{index-CaDDfJYE.js → index-dOzyv_xR.js} +43 -74
- package/dist/client/{jpeg-DNfUpLwy-Fjan-04T.js → jpeg-BAgeD1d3-oeHbFPUL.js} +5 -6
- package/dist/client/{lerc-_E46UbWQ-Beu35ovS.js → lerc-DzVumYtB-rm1Xco54.js} +5 -7
- package/dist/client/{lzw-BOMhmEDy-Dboc93VO.js → lzw-LAGDNbSC-DkP96qO9.js} +1 -1
- package/dist/client/{packbits-DaUD6MLm-Bu1PoTGa.js → packbits-BlDR4Kj5-C66n1-zr.js} +1 -1
- package/dist/client/{pako.esm-C3kYPGGQ-BMki8cQY.js → pako.esm-CB1uQYY0-DB0PYm1P.js} +6 -12
- package/dist/client/{raw-CcGKjn8q-DFOt-i8n.js → raw-CMGvRjfu-BRi6E4i1.js} +1 -1
- package/dist/client/{ssrBoot-Dd7m-btU.js → ssrBoot-L9KejErM.js} +3 -3
- package/dist/client/style.css +2 -2
- package/dist/client/transition-DCePIwYR.js +34 -0
- package/dist/client/{webfontloader-CyOFAuFB.js → webfontloader-qotgY98I.js} +56 -92
- package/dist/client/{webimage-D2c098k3-DLj1LQxB.js → webimage-BM_pbLN3-L2cGWK5l.js} +1 -1
- package/dist/node/cli.js +3 -3
- package/dist/node/types.d.ts +32 -38
- package/package.json +13 -14
- package/widgets/EodashDatePicker.vue +145 -41
- package/widgets/EodashItemFilter.vue +41 -22
- package/widgets/EodashMap.vue +87 -20
- package/widgets/WidgetsContainer.vue +45 -27
- package/dist/client/DashboardLayout-ZaSRMD1M.js +0 -149
- package/dist/client/EodashDatePicker-C4kKjxKy.js +0 -1653
- package/dist/client/EodashItemFilter-cBHC0YEM.js +0 -51
- package/dist/client/Footer-pS636dEP.js +0 -118
- package/dist/client/Header-DQuaLdjl.js +0 -605
- package/dist/client/MobileLayout-BLXFBWI_.js +0 -987
- package/dist/client/asWebComponent-Bvb3xkxI.js +0 -13311
- package/dist/client/deflate-Be2Arps5-hDqMz3RA.js +0 -10
- package/dist/client/forwardRefs-Bxeu9Obx.js +0 -142
- package/dist/client/index-DlNICb3T.js +0 -34
|
@@ -1,57 +1,161 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
<VCDatePicker v-model="currentDate" :masks="masks" :attributes="attributes">
|
|
3
|
+
<template #default="{ inputValue, inputEvents }">
|
|
4
|
+
<div
|
|
5
|
+
class="flex rounded-lg border border-gray-300 dark:border-gray-600"
|
|
6
|
+
style="margin: 2px"
|
|
7
|
+
>
|
|
8
|
+
<input
|
|
9
|
+
:value="inputValue"
|
|
10
|
+
v-on="inputEvents"
|
|
11
|
+
style="margin: 1px"
|
|
12
|
+
class="flex-grow px-1 py-1 bg-white dark:bg-gray-700"
|
|
13
|
+
/>
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
16
|
+
</VCDatePicker>
|
|
17
|
+
<v-row align="center" justify="center" style="margin-top: 6px">
|
|
18
|
+
<v-btn
|
|
19
|
+
style="padding: 0px; margin-right: 4px"
|
|
20
|
+
density="compact"
|
|
21
|
+
v-tooltip:bottom="'Set date to oldest available dataset'"
|
|
22
|
+
@click="jumpDate(true)"
|
|
23
|
+
>
|
|
24
|
+
<v-icon :icon="[mdiRayEndArrow]" />
|
|
25
|
+
</v-btn>
|
|
26
|
+
<v-btn
|
|
27
|
+
style="padding: 0px; margin-left: 4px"
|
|
28
|
+
density="compact"
|
|
29
|
+
v-tooltip:bottom="'Set date to latest available dataset'"
|
|
30
|
+
@click="jumpDate(false)"
|
|
31
|
+
>
|
|
32
|
+
<v-icon :icon="[mdiRayStartArrow]" />
|
|
33
|
+
</v-btn>
|
|
34
|
+
</v-row>
|
|
14
35
|
</template>
|
|
36
|
+
|
|
15
37
|
<script setup>
|
|
16
|
-
import {
|
|
17
|
-
import
|
|
38
|
+
import { DatePicker as VCDatePicker } from "v-calendar";
|
|
39
|
+
import "v-calendar/style.css";
|
|
40
|
+
import { computed, ref, onMounted, watch, inject } from "vue";
|
|
41
|
+
import { eodashKey } from "@/utils/keys";
|
|
42
|
+
import { toAbsolute } from "stac-js/src/http.js";
|
|
43
|
+
import { storeToRefs } from "pinia";
|
|
44
|
+
import { useSTAcStore } from "@/store/stac";
|
|
45
|
+
import { datetime } from "@/store/States";
|
|
46
|
+
import { mdiRayStartArrow, mdiRayEndArrow } from "@mdi/js";
|
|
47
|
+
import { extractCollectionUrls } from "@/utils/eodashSTAC";
|
|
18
48
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
49
|
+
/**
|
|
50
|
+
* @param {boolean} reverse
|
|
51
|
+
*/
|
|
52
|
+
function jumpDate(reverse) {
|
|
53
|
+
if (attributes.value && attributes.value.length > 0) {
|
|
54
|
+
// We have potentially multiple collections we need to iterate (currently only one)
|
|
55
|
+
let latestDateMS = reverse ? Infinity : -Infinity;
|
|
56
|
+
attributes.value.forEach((coll) => {
|
|
57
|
+
if (coll?.dates) {
|
|
58
|
+
coll.dates.forEach((d) => {
|
|
59
|
+
// TODO: we need to handle time ranges and other options here
|
|
60
|
+
if (d instanceof Date) {
|
|
61
|
+
if (
|
|
62
|
+
(!reverse && d.getTime() > latestDateMS) ||
|
|
63
|
+
(reverse && d.getTime() < latestDateMS)
|
|
64
|
+
) {
|
|
65
|
+
latestDateMS = d.getTime();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
if (latestDateMS !== 0) {
|
|
72
|
+
currentDate.value = new Date(latestDateMS);
|
|
73
|
+
}
|
|
22
74
|
}
|
|
23
|
-
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const eodashConfig = /** @type {import("@/types").Eodash} */ inject(eodashKey);
|
|
78
|
+
|
|
79
|
+
const masks = ref({
|
|
80
|
+
input: "YYYY-MM-DD",
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Attributes displayed on datepicker
|
|
85
|
+
*
|
|
86
|
+
* @type {import("vue").Ref<
|
|
87
|
+
* (
|
|
88
|
+
* | import("v-calendar/dist/types/src/utils/attribute").AttributeConfig
|
|
89
|
+
* | undefined
|
|
90
|
+
* )[]
|
|
91
|
+
* >}
|
|
92
|
+
*/
|
|
93
|
+
const attributes = ref([]);
|
|
24
94
|
|
|
25
95
|
const currentDate = computed({
|
|
26
96
|
get() {
|
|
27
|
-
return
|
|
97
|
+
return datetime.value ? new Date(datetime.value) : new Date();
|
|
28
98
|
},
|
|
29
99
|
/** @param {Date | string} updatedDate */
|
|
30
100
|
set(updatedDate) {
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (updatedDate instanceof Date && !isNaN(updatedDate)) {
|
|
36
|
-
datetime.value = new Date(updatedDate.getTime() - updatedDate.getTimezoneOffset() * 60000).toISOString()
|
|
101
|
+
if (updatedDate instanceof Date && !isNaN(updatedDate.getTime())) {
|
|
102
|
+
datetime.value = new Date(
|
|
103
|
+
updatedDate.getTime() - updatedDate.getTimezoneOffset() * 60000,
|
|
104
|
+
).toISOString();
|
|
37
105
|
} else {
|
|
38
|
-
datetime.value = new Date().toISOString()
|
|
106
|
+
datetime.value = new Date().toISOString();
|
|
39
107
|
}
|
|
40
|
-
}
|
|
108
|
+
},
|
|
41
109
|
});
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* @type {import("vue").Ref<import("vuetify/components").VDatePicker | null>}
|
|
45
|
-
**/
|
|
46
|
-
const datePicker = ref(null)
|
|
47
|
-
/** @type {import("vue").Ref<string|undefined>} */
|
|
48
|
-
const width = ref()
|
|
49
|
-
/** @type {import("vue").Ref<string|undefined>} */
|
|
50
|
-
const height = ref()
|
|
110
|
+
/** @type {import("@/types").WebComponentProps["onMounted"]} */
|
|
51
111
|
onMounted(() => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
112
|
+
const { selectedStac } = storeToRefs(useSTAcStore());
|
|
113
|
+
watch(
|
|
114
|
+
[selectedStac],
|
|
115
|
+
async ([updatedStac]) => {
|
|
116
|
+
if (updatedStac) {
|
|
117
|
+
const parentCollUrl = toAbsolute(
|
|
118
|
+
`./${updatedStac.id}/collection.json`,
|
|
119
|
+
eodashConfig.stacEndpoint,
|
|
120
|
+
);
|
|
121
|
+
const collectionUrls = extractCollectionUrls(
|
|
122
|
+
selectedStac.value,
|
|
123
|
+
parentCollUrl,
|
|
124
|
+
);
|
|
125
|
+
const wongPalette = [
|
|
126
|
+
"#009E73",
|
|
127
|
+
"#0072B2",
|
|
128
|
+
"#E69F00",
|
|
129
|
+
"#CC79A7",
|
|
130
|
+
"#56B4E9",
|
|
131
|
+
"#D55E00",
|
|
132
|
+
];
|
|
133
|
+
for (let idx = 0; idx < collectionUrls.length; idx++) {
|
|
134
|
+
const stacCollection = await (
|
|
135
|
+
await fetch(collectionUrls[idx])
|
|
136
|
+
).json();
|
|
137
|
+
const dates = stacCollection.links
|
|
138
|
+
.filter(
|
|
139
|
+
(/** @type {{ rel: string; datetime: string }} */ item) =>
|
|
140
|
+
item.rel === "item" && "datetime" in item,
|
|
141
|
+
)
|
|
142
|
+
.map(
|
|
143
|
+
(/** @type {{ datetime: string }} */ it) => new Date(it.datetime),
|
|
144
|
+
);
|
|
145
|
+
attributes.value = [
|
|
146
|
+
{
|
|
147
|
+
bar: {
|
|
148
|
+
style: {
|
|
149
|
+
backgroundColor: wongPalette[idx % wongPalette.length],
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
dates,
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
{ immediate: true },
|
|
159
|
+
);
|
|
160
|
+
});
|
|
57
161
|
</script>
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<DynamicWebComponent
|
|
2
|
+
<DynamicWebComponent
|
|
3
|
+
:link="link"
|
|
4
|
+
tag-name="eox-itemfilter"
|
|
5
|
+
:properties="properties"
|
|
6
|
+
:on-mounted="onMounted"
|
|
7
|
+
/>
|
|
3
8
|
</template>
|
|
4
9
|
<script setup>
|
|
5
10
|
import DynamicWebComponent from "@/components/DynamicWebComponent.vue";
|
|
6
|
-
import { indicator } from "@/store/States";
|
|
7
11
|
|
|
8
12
|
const link = () => import("@eox/itemfilter");
|
|
9
13
|
|
|
@@ -15,43 +19,58 @@ const properties = {
|
|
|
15
19
|
keys: ["title", "themes"],
|
|
16
20
|
title: "Search",
|
|
17
21
|
type: "text",
|
|
18
|
-
expanded: true,
|
|
22
|
+
// expanded: true,
|
|
19
23
|
},
|
|
20
24
|
{
|
|
21
25
|
key: "themes",
|
|
22
|
-
title: "Theme",
|
|
26
|
+
title: "Theme Filter",
|
|
23
27
|
type: "multiselect",
|
|
24
|
-
featured: true,
|
|
28
|
+
// featured: true,
|
|
29
|
+
// expanded: true
|
|
25
30
|
},
|
|
26
31
|
],
|
|
27
32
|
aggregateResults: "themes",
|
|
28
33
|
enableHighlighting: true,
|
|
34
|
+
expandMultipleFilters: false,
|
|
35
|
+
expandMultipleResults: false,
|
|
29
36
|
},
|
|
30
37
|
};
|
|
31
38
|
|
|
32
|
-
/** @type {import("@/types").WebComponentProps["onMounted"]}*/
|
|
39
|
+
/** @type {import("@/types").WebComponentProps["onMounted"]} */
|
|
33
40
|
const onMounted = (el, store) => {
|
|
41
|
+
/** @type {any} */ (el).style.height = "100%";
|
|
42
|
+
|
|
43
|
+
const style = document.createElement("style");
|
|
44
|
+
style.innerHTML = `
|
|
45
|
+
section {
|
|
46
|
+
margin: 0 !important;
|
|
47
|
+
}
|
|
48
|
+
section button#filter-reset {
|
|
49
|
+
padding: 0 8px;
|
|
50
|
+
top: 8px;
|
|
51
|
+
right: 8px;
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
el?.shadowRoot?.appendChild(style);
|
|
55
|
+
|
|
56
|
+
const filterstitle = document.createElement("div");
|
|
57
|
+
filterstitle.setAttribute("slot", "filterstitle");
|
|
58
|
+
filterstitle.innerHTML = `<h4 style="margin: 14px 8px">Indicators</h4>`;
|
|
59
|
+
/** @type {any} */ (el).appendChild(filterstitle);
|
|
60
|
+
const resultstitle = document.createElement("div");
|
|
61
|
+
resultstitle.setAttribute("slot", "resultstitle");
|
|
62
|
+
/** @type {any} */ (el).appendChild(resultstitle);
|
|
63
|
+
|
|
34
64
|
/**
|
|
35
65
|
* @typedef {object} Item
|
|
36
66
|
* @property {string} href
|
|
37
|
-
|
|
67
|
+
*/
|
|
38
68
|
/** @type {any} */ (el).apply(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
);
|
|
42
|
-
// Check if selected indicator was already set in store
|
|
43
|
-
if (indicator && indicator.value !== "") {
|
|
44
|
-
const match = store.stac?.find((item) => item.id === indicator.value);
|
|
45
|
-
if (match) {
|
|
46
|
-
//@ts-expect-error
|
|
47
|
-
(el).selectedResult = match;
|
|
48
|
-
store.loadSelectedSTAC(match.href);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
69
|
+
// Only list child elements in list
|
|
70
|
+
store.stac?.filter((item) => item.rel === "child"),
|
|
71
|
+
);
|
|
51
72
|
/** @type {any} */ (el).config.onSelect =
|
|
52
|
-
/**
|
|
53
|
-
* @param {Item} item
|
|
54
|
-
* */
|
|
73
|
+
/** @param {Item} item */
|
|
55
74
|
async (item) => {
|
|
56
75
|
console.log(item);
|
|
57
76
|
await store.loadSelectedSTAC(item.href);
|
package/widgets/EodashMap.vue
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<DynamicWebComponent
|
|
3
|
-
:
|
|
2
|
+
<DynamicWebComponent
|
|
3
|
+
:link="link"
|
|
4
|
+
tag-name="eox-map"
|
|
5
|
+
:properties="properties"
|
|
6
|
+
:on-mounted="onMounted"
|
|
7
|
+
:on-unmounted="onUnmounted"
|
|
8
|
+
/>
|
|
4
9
|
</template>
|
|
5
10
|
<script setup>
|
|
6
11
|
import { inject, watch } from "vue";
|
|
7
12
|
import { toAbsolute } from "stac-js/src/http.js";
|
|
8
|
-
import { EodashCollection } from "@/utils/eodashSTAC";
|
|
13
|
+
import { EodashCollection, extractCollectionUrls } from "@/utils/eodashSTAC";
|
|
9
14
|
import { eodashKey } from "@/utils/keys";
|
|
10
15
|
import { datetime, mapPosition } from "@/store/States";
|
|
11
16
|
import DynamicWebComponent from "@/components/DynamicWebComponent.vue";
|
|
@@ -14,26 +19,53 @@ import "@eox/map/dist/eox-map-advanced-layers-and-sources.js";
|
|
|
14
19
|
|
|
15
20
|
const eodashConfig = /** @type {import("@/types").Eodash} */ inject(eodashKey);
|
|
16
21
|
|
|
17
|
-
/** @type {Record<string,unknown>} */
|
|
22
|
+
/** @type {Record<string, unknown>} */
|
|
18
23
|
const properties = {
|
|
19
24
|
class: "fill-height fill-width overflow-none",
|
|
20
25
|
center: [15, 48],
|
|
21
|
-
|
|
26
|
+
zoom: 4,
|
|
27
|
+
// TODO: we should probably introduce some way of defining
|
|
28
|
+
layers: [
|
|
29
|
+
{
|
|
30
|
+
type: "Vector",
|
|
31
|
+
source: {
|
|
32
|
+
type: "Vector",
|
|
33
|
+
url: "https://openlayers.org/data/vector/ecoregions.json",
|
|
34
|
+
format: "GeoJSON",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: "Tile",
|
|
39
|
+
properties: {
|
|
40
|
+
id: "osm",
|
|
41
|
+
title: "Background",
|
|
42
|
+
},
|
|
43
|
+
source: {
|
|
44
|
+
type: "OSM",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
22
48
|
};
|
|
23
49
|
// Check if selected indicator was already set in store
|
|
24
50
|
if (mapPosition && mapPosition.value && mapPosition.value.length === 3) {
|
|
25
51
|
// TODO: do further checks for invalid values?
|
|
52
|
+
// TODO: can we expect the values to be in a specific projection
|
|
26
53
|
properties.center = [mapPosition.value?.[0], mapPosition.value[1]];
|
|
27
54
|
properties.zoom = mapPosition.value[2];
|
|
28
55
|
}
|
|
29
56
|
|
|
30
57
|
const link = () => import("@eox/map");
|
|
31
58
|
|
|
32
|
-
/** @type {import("openlayers").EventsListenerFunctionType}*/
|
|
59
|
+
/** @type {import("openlayers").EventsListenerFunctionType} */
|
|
33
60
|
const handleMoveEnd = (evt) => {
|
|
34
61
|
const map = /** @type {import("openlayers").Map | undefined} */ (
|
|
35
|
-
/** @type {
|
|
62
|
+
/** @type {any} */ (evt).map
|
|
36
63
|
);
|
|
64
|
+
/*
|
|
65
|
+
const currentProj = map?.getView().getProjection();
|
|
66
|
+
const transFunc = getTransform(currentProj?.getCode(), 'EPSG:4326');
|
|
67
|
+
const [x, y] = transFunc(map?.getView().getCenter() ?? [0, 0], undefined, undefined);
|
|
68
|
+
*/
|
|
37
69
|
const [x, y] = map?.getView().getCenter() ?? [0, 0];
|
|
38
70
|
const z = map?.getView().getZoom();
|
|
39
71
|
if (!Number.isNaN(x) && !Number.isNaN(y) && !Number.isNaN(z)) {
|
|
@@ -45,7 +77,6 @@ const handleMoveEnd = (evt) => {
|
|
|
45
77
|
const onMounted = (el, store) => {
|
|
46
78
|
/** @type {any} */
|
|
47
79
|
(el)?.map?.on("moveend", handleMoveEnd);
|
|
48
|
-
|
|
49
80
|
const { selectedStac } = storeToRefs(store);
|
|
50
81
|
|
|
51
82
|
watch(
|
|
@@ -54,23 +85,59 @@ const onMounted = (el, store) => {
|
|
|
54
85
|
if (updatedStac) {
|
|
55
86
|
const parentCollUrl = toAbsolute(
|
|
56
87
|
`./${updatedStac.id}/collection.json`,
|
|
57
|
-
eodashConfig.stacEndpoint
|
|
58
|
-
);
|
|
59
|
-
const childCollUrl = toAbsolute(
|
|
60
|
-
updatedStac.links[1].href,
|
|
61
|
-
parentCollUrl
|
|
88
|
+
eodashConfig.stacEndpoint,
|
|
62
89
|
);
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
new Date(updatedTime)
|
|
90
|
+
const collectionUrls = extractCollectionUrls(
|
|
91
|
+
selectedStac.value,
|
|
92
|
+
parentCollUrl,
|
|
67
93
|
);
|
|
68
|
-
|
|
69
|
-
|
|
94
|
+
/** @type {import("@/utils/eodashSTAC").EodashCollection[]} */
|
|
95
|
+
const eodashCollections = [];
|
|
96
|
+
collectionUrls.forEach((cu) => {
|
|
97
|
+
eodashCollections.push(new EodashCollection(cu));
|
|
98
|
+
});
|
|
99
|
+
const layersCollection = [];
|
|
100
|
+
for (let idx = 0; idx < eodashCollections.length; idx++) {
|
|
101
|
+
const ec = eodashCollections[idx];
|
|
102
|
+
let layers;
|
|
103
|
+
if (updatedTime) {
|
|
104
|
+
layers = await ec.createLayersJson(new Date(updatedTime));
|
|
105
|
+
} else {
|
|
106
|
+
layers = await ec.createLayersJson();
|
|
107
|
+
}
|
|
108
|
+
if (layers) {
|
|
109
|
+
layersCollection.push(...layers);
|
|
110
|
+
}
|
|
70
111
|
}
|
|
112
|
+
// TODO: add base layers and overlays as defined in the top collection / indicator
|
|
113
|
+
// Probably best also to introduce background and overlay groups
|
|
114
|
+
// For now adding OSM as background
|
|
115
|
+
layersCollection.push({
|
|
116
|
+
type: "Tile",
|
|
117
|
+
properties: {
|
|
118
|
+
id: "osm",
|
|
119
|
+
title: "Background",
|
|
120
|
+
},
|
|
121
|
+
source: {
|
|
122
|
+
type: "OSM",
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// TODO: we can check if the collection / indicator has a specific
|
|
127
|
+
// projection it wants to be displayed in the map we can register
|
|
128
|
+
// and set the attribute here, e.g. like following
|
|
129
|
+
/*
|
|
130
|
+
(el)?.registerProjection(
|
|
131
|
+
'EPSG:3031','+proj=stere +lat_0=-90 +lat_ts=-71 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs +type=crs'
|
|
132
|
+
);
|
|
133
|
+
(el)?.projection = "EPSG:3031";
|
|
134
|
+
*/
|
|
135
|
+
|
|
136
|
+
/** @type {any} */
|
|
137
|
+
(el).layers = layersCollection;
|
|
71
138
|
}
|
|
72
139
|
},
|
|
73
|
-
{ immediate: true }
|
|
140
|
+
{ immediate: true },
|
|
74
141
|
);
|
|
75
142
|
};
|
|
76
143
|
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<details
|
|
3
|
-
|
|
2
|
+
<details
|
|
3
|
+
is="animated-details"
|
|
4
|
+
v-for="(mod, idx) in importedWidgets"
|
|
5
|
+
ref="detailsEls"
|
|
6
|
+
:key="idx"
|
|
7
|
+
class="overflow-auto"
|
|
8
|
+
exclusive
|
|
9
|
+
>
|
|
4
10
|
<summary ref="summaryEls">{{ mod.value.title }}</summary>
|
|
5
11
|
<span :style="{ height: widgetHeight }" class="d-flex flex-column">
|
|
6
12
|
<component :is="mod.value.component" v-bind="mod.value.props" />
|
|
@@ -8,41 +14,53 @@
|
|
|
8
14
|
</details>
|
|
9
15
|
</template>
|
|
10
16
|
<script setup>
|
|
11
|
-
import { useDefineWidgets } from
|
|
12
|
-
import { nextTick, onMounted } from
|
|
13
|
-
import { ref } from
|
|
14
|
-
import { useLayout } from
|
|
15
|
-
import
|
|
17
|
+
import { useDefineWidgets } from "@/composables/DefineWidgets";
|
|
18
|
+
import { nextTick, onMounted } from "vue";
|
|
19
|
+
import { ref } from "vue";
|
|
20
|
+
import { useLayout } from "vuetify/lib/framework.mjs";
|
|
21
|
+
import "animated-details";
|
|
16
22
|
|
|
17
23
|
const props = defineProps({
|
|
18
24
|
widgets: {
|
|
19
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* @type {import("vue").PropType<
|
|
27
|
+
* Omit<import("@/types").Widget, "layout">[]
|
|
28
|
+
* >}
|
|
29
|
+
*/
|
|
20
30
|
type: Array,
|
|
21
31
|
required: true,
|
|
22
|
-
}
|
|
23
|
-
})
|
|
32
|
+
},
|
|
33
|
+
});
|
|
24
34
|
|
|
25
|
-
const importedWidgets = useDefineWidgets(props.widgets)
|
|
35
|
+
const importedWidgets = useDefineWidgets(props.widgets);
|
|
26
36
|
|
|
27
37
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
* Details elements template ref
|
|
39
|
+
*
|
|
40
|
+
* @type {import("vue").Ref<HTMLDetailsElement[]>}
|
|
41
|
+
*/
|
|
42
|
+
const detailsEls = ref([]);
|
|
32
43
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
const
|
|
44
|
+
* Summary elements template ref
|
|
45
|
+
*
|
|
46
|
+
* @type {import("vue").Ref<HTMLDetailsElement[]>}
|
|
47
|
+
*/
|
|
48
|
+
const summaryEls = ref([]);
|
|
49
|
+
const widgetHeight = ref("");
|
|
50
|
+
const summariesHeights = ref(0);
|
|
39
51
|
|
|
40
|
-
|
|
41
|
-
const { mainRect } = useLayout()
|
|
52
|
+
const { mainRect } = useLayout();
|
|
42
53
|
onMounted(async () => {
|
|
43
54
|
await nextTick(() => {
|
|
44
|
-
summariesHeights.value = summaryEls.value.reduce(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
summariesHeights.value = summaryEls.value.reduce(
|
|
56
|
+
(acc, el) => (acc += el.clientHeight),
|
|
57
|
+
0,
|
|
58
|
+
);
|
|
59
|
+
widgetHeight.value =
|
|
60
|
+
(detailsEls.value[0].parentElement?.scrollHeight ?? 0) -
|
|
61
|
+
summariesHeights.value -
|
|
62
|
+
mainRect.value["top"] +
|
|
63
|
+
"px";
|
|
64
|
+
});
|
|
65
|
+
});
|
|
48
66
|
</script>
|