@eodash/eodash 5.0.0-rc.3 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/core/client/App.vue +8 -2
- package/core/client/asWebComponent.js +5 -5
- package/core/client/components/DashboardLayout.vue +42 -25
- package/core/client/components/EodashOverlay.vue +1 -1
- package/core/client/components/ErrorAlert.vue +2 -2
- package/core/client/components/Footer.vue +4 -4
- package/core/client/components/Header.vue +3 -3
- package/core/client/components/MobileLayout.vue +9 -10
- package/core/client/composables/DefineEodash.js +38 -43
- package/core/client/composables/DefineTemplate.js +4 -2
- package/core/client/composables/DefineWidgets.js +14 -8
- package/core/client/composables/index.js +273 -23
- package/core/client/eodashSTAC/EodashCollection.js +80 -47
- package/core/client/eodashSTAC/helpers.js +136 -27
- package/core/client/eodashSTAC/parquet.js +145 -0
- package/core/client/eodashSTAC/triggers.js +6 -3
- package/core/client/plugins/index.js +4 -3
- package/core/client/plugins/vuetify.js +3 -0
- package/core/client/store/actions.js +21 -4
- package/core/client/store/stac.js +93 -56
- package/core/client/store/states.js +15 -5
- package/core/client/types.ts +59 -43
- package/core/client/utils/index.js +79 -0
- package/core/client/utils/keys.js +2 -2
- package/core/client/utils/states.js +30 -5
- package/core/client/views/Dashboard.vue +36 -32
- package/core/client/vite-env.d.ts +7 -0
- package/dist/client/{DashboardLayout-t_PavJPO.js → DashboardLayout-ByVs1DrY.js} +23 -12
- package/dist/client/{DynamicWebComponent-y07rVJch.js → DynamicWebComponent-C3W7HSQm.js} +1 -1
- package/dist/client/{EodashDatePicker-CcOfyzGD.js → EodashDatePicker-BIAf1sMT.js} +59 -32
- package/dist/client/{EodashItemFilter-B9HCvIMi.js → EodashItemFilter-DPznh8UB.js} +20 -10
- package/dist/client/{EodashLayerControl-KStn7Nb_.js → EodashLayerControl-Bhxjw4V2.js} +29 -16
- package/dist/client/EodashLayoutSwitcher-C5qTEffW.js +61 -0
- package/dist/client/EodashMapBtns-WoGq8MuV.js +173 -0
- package/dist/client/{EodashStacInfo-C_hDy6Pd.js → EodashStacInfo-CSvvF2jI.js} +3 -18
- package/dist/client/{EodashTools-BXflvRf8.js → EodashTools-Cv1SXQ5y.js} +13 -13
- package/dist/client/{ExportState-C0QRemK1.js → ExportState-D-iuwaad.js} +58 -52
- package/dist/client/{Footer-7VGyGUAs.js → Footer-CyF0zRAk.js} +15 -13
- package/dist/client/{Header-BQJnXHYq.js → Header-CgD8jDKU.js} +33 -28
- package/dist/client/{MobileLayout-b8nQ-Vyl.js → MobileLayout-EKQ_kpSh.js} +69 -60
- package/dist/client/{PopUp-DgNrh9Df.js → PopUp-BsYLvWch.js} +19 -10
- package/dist/client/ProcessList-C2xsLU2_.js +191 -0
- package/dist/client/{VImg-D4eT3IQ1.js → VImg-OHe8YTs2.js} +24 -24
- package/dist/client/{VMain-C3hN2-H3.js → VMain-PryTLU4a.js} +7 -7
- package/dist/client/{VOverlay-tAeNygaA.js → VOverlay-yUn7p-Uf.js} +64 -27
- package/dist/client/{VTooltip-B0Q3iHMZ.js → VTooltip-DZ0fjpB3.js} +13 -10
- package/dist/client/{WidgetsContainer-CtDHfCYf.js → WidgetsContainer-B9LBadcC.js} +1 -1
- package/dist/client/asWebComponent-By_7_JjS.js +19193 -0
- package/dist/client/async-DkSu_u2K.js +740 -0
- package/dist/client/eo-dash.js +1 -1
- package/dist/client/{forwardRefs-CIFAqXaZ.js → forwardRefs-BXxrv98s.js} +31 -4
- package/dist/client/handling-CgmFXkW6.js +1212 -0
- package/dist/client/helpers-Dy0Q13tP.js +4534 -0
- package/dist/client/{index-DvcUndod.js → index-BuhOHXKv.js} +2 -4
- package/dist/client/{index-BQ16n4Sk.js → index-Ch_HchK3.js} +39 -32
- package/dist/client/{index-Cv7HBz49.js → index-Dqj4tbx2.js} +2 -2
- package/dist/client/index-skjhlH8u.js +376 -0
- package/dist/client/{ssrBoot-BP7SYRyC.js → ssrBoot-Zgc_Ttvi.js} +2 -2
- package/dist/client/templates.js +850 -0
- package/dist/client/transition-C98Yn4Vo.js +40 -0
- package/dist/node/cli.js +16 -6
- package/dist/node/types.d.ts +1 -1
- package/dist/types/core/client/App.vue.d.ts +2 -2
- package/dist/types/core/client/asWebComponent.d.ts +1 -1
- package/dist/types/core/client/components/DynamicWebComponent.vue.d.ts +1 -3
- package/dist/types/core/client/components/Footer.vue.d.ts +1 -105
- package/dist/types/core/client/components/IframeWrapper.vue.d.ts +1 -1
- package/dist/types/core/client/components/MobileLayout.vue.d.ts +1 -324
- package/dist/types/core/client/composables/DefineEodash.d.ts +2 -2
- package/dist/types/core/client/composables/DefineTemplate.d.ts +1 -1
- package/dist/types/core/client/composables/DefineWidgets.d.ts +4 -4
- package/dist/types/core/client/composables/index.d.ts +24 -2
- package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +9 -6
- package/dist/types/core/client/eodashSTAC/helpers.d.ts +20 -5
- package/dist/types/core/client/eodashSTAC/parquet.d.ts +2 -0
- package/dist/types/core/client/plugins/vuetify.d.ts +7 -4
- package/dist/types/core/client/store/actions.d.ts +3 -2
- package/dist/types/core/client/store/stac.d.ts +16 -13
- package/dist/types/core/client/store/states.d.ts +14 -4
- package/dist/types/core/client/types.d.ts +45 -30
- package/dist/types/core/client/utils/index.d.ts +2 -0
- package/dist/types/core/client/utils/keys.d.ts +4 -4
- package/dist/types/core/client/utils/states.d.ts +59 -47
- package/dist/types/core/client/views/Dashboard.vue.d.ts +2 -2
- package/dist/types/templates/baseConfig.d.ts +4 -0
- package/dist/types/templates/compare.d.ts +210 -0
- package/dist/types/templates/expert.d.ts +151 -0
- package/dist/types/templates/index.d.ts +6 -0
- package/dist/types/templates/light.d.ts +145 -0
- package/dist/types/widgets/EodashDatePicker.vue.d.ts +1 -458
- package/dist/types/widgets/EodashItemFilter.vue.d.ts +3 -3
- package/dist/types/widgets/EodashLayerControl.vue.d.ts +14 -7
- package/dist/types/widgets/EodashLayoutSwitcher.vue.d.ts +1 -3
- package/dist/types/widgets/EodashMap/index.vue.d.ts +1 -4
- package/dist/types/widgets/EodashMapBtns.vue.d.ts +8 -8
- package/dist/types/widgets/EodashProcess/ProcessList.vue.d.ts +8 -1
- package/dist/types/widgets/EodashProcess/index.vue.d.ts +8 -4
- package/dist/types/widgets/EodashProcess/methods/async.d.ts +18 -18
- package/dist/types/widgets/EodashProcess/methods/composables.d.ts +3 -2
- package/dist/types/widgets/EodashProcess/methods/custom-endpoints/chart/index.d.ts +1 -0
- package/dist/types/widgets/EodashProcess/methods/custom-endpoints/chart/sentinelhub-endpoint.d.ts +6 -0
- package/dist/types/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.d.ts +4 -0
- package/dist/types/widgets/EodashProcess/methods/custom-endpoints/layers/eoxhub-workspaces-endpoint.d.ts +5 -0
- package/dist/types/widgets/EodashProcess/methods/custom-endpoints/layers/index.d.ts +1 -0
- package/dist/types/widgets/EodashProcess/methods/handling.d.ts +12 -5
- package/dist/types/widgets/EodashProcess/methods/outputs.d.ts +72 -41
- package/dist/types/widgets/EodashProcess/methods/utils.d.ts +41 -21
- package/dist/types/widgets/EodashProcess/states.d.ts +11 -0
- package/dist/types/widgets/EodashProcess/types.d.ts +41 -0
- package/dist/types/widgets/EodashStacInfo.vue.d.ts +14 -14
- package/dist/types/widgets/EodashTools.vue.d.ts +3 -3
- package/dist/types/widgets/ExportState.vue.d.ts +1 -1
- package/dist/types/widgets/PopUp.vue.d.ts +11 -16
- package/dist/types/widgets/WidgetsContainer.vue.d.ts +3 -6
- package/package.json +53 -45
- package/templates/baseConfig.js +68 -0
- package/templates/compare.js +162 -0
- package/templates/expert.js +123 -0
- package/templates/index.js +8 -0
- package/templates/light.js +130 -0
- package/widgets/EodashDatePicker.vue +80 -31
- package/widgets/EodashItemFilter.vue +26 -11
- package/widgets/EodashLayerControl.vue +20 -11
- package/widgets/EodashLayoutSwitcher.vue +6 -3
- package/widgets/EodashMap/index.vue +3 -8
- package/widgets/EodashMap/methods/create-layers-config.js +4 -3
- package/widgets/EodashMap/methods/index.js +33 -23
- package/widgets/EodashMapBtns.vue +83 -41
- package/widgets/EodashProcess/ProcessList.vue +34 -10
- package/widgets/EodashProcess/index.vue +55 -20
- package/widgets/EodashProcess/methods/async.js +77 -59
- package/widgets/EodashProcess/methods/composables.js +21 -14
- package/widgets/EodashProcess/methods/custom-endpoints/chart/index.js +35 -0
- package/widgets/EodashProcess/methods/custom-endpoints/chart/sentinelhub-endpoint.js +275 -0
- package/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.js +116 -0
- package/widgets/EodashProcess/methods/custom-endpoints/layers/eoxhub-workspaces-endpoint.js +94 -0
- package/widgets/EodashProcess/methods/custom-endpoints/layers/index.js +33 -0
- package/widgets/EodashProcess/methods/handling.js +127 -80
- package/widgets/EodashProcess/methods/outputs.js +376 -125
- package/widgets/EodashProcess/methods/utils.js +398 -10
- package/widgets/EodashProcess/states.js +13 -0
- package/widgets/EodashProcess/types.ts +46 -0
- package/widgets/EodashStacInfo.vue +2 -17
- package/widgets/EodashTools.vue +13 -13
- package/widgets/WidgetsContainer.vue +1 -1
- package/core/client/eodash.js +0 -454
- package/dist/client/EodashLayoutSwitcher-DqeFO3RN.js +0 -52
- package/dist/client/EodashMapBtns-5BF27qJB.js +0 -131
- package/dist/client/ProcessList-C62SOVO6.js +0 -484
- package/dist/client/asWebComponent-BJ2NWunV.js +0 -12479
- package/dist/client/eo-dash.css +0 -5
- package/dist/client/index-Da5xXX6Q.js +0 -780
- package/dist/client/transition-Cdb4K27U.js +0 -37
- package/dist/types/core/client/eodash.d.ts +0 -8
|
@@ -7,17 +7,54 @@ import {
|
|
|
7
7
|
currentUrl,
|
|
8
8
|
datetime,
|
|
9
9
|
indicator,
|
|
10
|
+
mapEl,
|
|
10
11
|
mapPosition,
|
|
12
|
+
poi,
|
|
11
13
|
} from "@/store/states";
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
import { inject, onMounted, onUnmounted, watch } from "vue";
|
|
14
|
+
import { useTheme } from "vuetify";
|
|
15
|
+
import { inject, nextTick, onMounted, onUnmounted, watch } from "vue";
|
|
15
16
|
import { useSTAcStore } from "@/store/stac";
|
|
16
17
|
import log from "loglevel";
|
|
17
18
|
import { eodashKey, eoxLayersKey } from "@/utils/keys";
|
|
18
|
-
import { useEventBus } from "@vueuse/core";
|
|
19
|
-
import {
|
|
19
|
+
import { useEventBus, useMutationObserver } from "@vueuse/core";
|
|
20
|
+
import { isFirstLoad } from "@/utils/states";
|
|
20
21
|
import { setCollectionsPalette } from "@/utils";
|
|
22
|
+
import mustache from "mustache";
|
|
23
|
+
import { toAbsolute } from "stac-js/src/http.js";
|
|
24
|
+
import axios from "@/plugins/axios";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
/** @type {import('@/types').Eodash | null}*/
|
|
28
|
+
|
|
29
|
+
let _eodash = null;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Call this once in a top-level component to inject and store the reactive eodash object.
|
|
33
|
+
* @throws {Error} If eodash is not found in the inject context
|
|
34
|
+
*/
|
|
35
|
+
export function provideEodashInstance() {
|
|
36
|
+
const injected = inject(eodashKey);
|
|
37
|
+
if (!injected) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
"Missing injected eodash – did you forget to call provideEodashInstance in a component?",
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
_eodash = injected;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Access the reactive eodash configuration anywhere after it has been provided.
|
|
47
|
+
* @returns {import('@/types').Eodash | null}
|
|
48
|
+
* @throws {Error} If eodash was not yet provided
|
|
49
|
+
*/
|
|
50
|
+
export function useEodash() {
|
|
51
|
+
if (!_eodash) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
"Eodash not yet available – call provideEodashInstance() first.",
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
return _eodash;
|
|
57
|
+
}
|
|
21
58
|
|
|
22
59
|
/**
|
|
23
60
|
* Creates an absolute URL from a relative link and assignes it to `currentUrl`
|
|
@@ -28,8 +65,11 @@ import { setCollectionsPalette } from "@/utils";
|
|
|
28
65
|
* @returns {import("vue").Ref<string>} - Returns `currentUrl`
|
|
29
66
|
* @see {@link '@/store/states.js'}
|
|
30
67
|
*/
|
|
31
|
-
export const useAbsoluteUrl = (
|
|
32
|
-
|
|
68
|
+
export const useAbsoluteUrl = (
|
|
69
|
+
rel = "",
|
|
70
|
+
base = inject(eodashKey)?.stacEndpoint,
|
|
71
|
+
) => {
|
|
72
|
+
if (!rel || rel.includes("http") || !base) {
|
|
33
73
|
currentUrl.value = rel;
|
|
34
74
|
return currentUrl;
|
|
35
75
|
}
|
|
@@ -57,9 +97,12 @@ export const useAbsoluteUrl = (rel = "", base = eodash.stacEndpoint) => {
|
|
|
57
97
|
* @returns {import("vue").Ref<string>} - Returns `currentUrl`
|
|
58
98
|
* @see {@link '@/store/states.js'}
|
|
59
99
|
*/
|
|
60
|
-
export const useCompareAbsoluteUrl = (
|
|
61
|
-
|
|
62
|
-
|
|
100
|
+
export const useCompareAbsoluteUrl = (
|
|
101
|
+
rel = "",
|
|
102
|
+
base = inject(eodashKey)?.stacEndpoint,
|
|
103
|
+
) => {
|
|
104
|
+
if (!rel || rel.includes("http") || !base) {
|
|
105
|
+
currentCompareUrl.value = rel;
|
|
63
106
|
return currentCompareUrl;
|
|
64
107
|
}
|
|
65
108
|
|
|
@@ -119,6 +162,7 @@ export const useURLSearchParametersSync = () => {
|
|
|
119
162
|
// Analyze currently set url params when first loaded and set them in the store
|
|
120
163
|
if (window.location.search) {
|
|
121
164
|
const searchParams = new URLSearchParams(window.location.search);
|
|
165
|
+
const store = useSTAcStore();
|
|
122
166
|
|
|
123
167
|
/** @type {number | undefined} */
|
|
124
168
|
let x,
|
|
@@ -134,11 +178,54 @@ export const useURLSearchParametersSync = () => {
|
|
|
134
178
|
}
|
|
135
179
|
case "indicator": {
|
|
136
180
|
log.debug("Found indicator key in url");
|
|
137
|
-
const
|
|
138
|
-
const match = stac?.find(
|
|
181
|
+
const eodash = inject(eodashKey);
|
|
182
|
+
const match = store.stac?.find(
|
|
183
|
+
(link) => useGetSubCodeId(link) == value,
|
|
184
|
+
);
|
|
139
185
|
if (match) {
|
|
140
186
|
log.debug("Found match, loading stac item", match);
|
|
141
|
-
|
|
187
|
+
if (searchParams.has("poi")) {
|
|
188
|
+
const indicatorUrl = toAbsolute(
|
|
189
|
+
match.href,
|
|
190
|
+
eodash?.stacEndpoint ?? "",
|
|
191
|
+
);
|
|
192
|
+
// fetch indicator stac collection without rendering it
|
|
193
|
+
/** @type {import("stac-ts").StacCollection} */
|
|
194
|
+
const indicatorStac = await axios
|
|
195
|
+
.get(indicatorUrl)
|
|
196
|
+
.then((resp) => resp.data);
|
|
197
|
+
poi.value = searchParams.get("poi") ?? "";
|
|
198
|
+
// find the process link
|
|
199
|
+
const poiMatch = indicatorStac?.links.find(
|
|
200
|
+
(link) =>
|
|
201
|
+
link.rel === "service" &&
|
|
202
|
+
link.type === "application/json; profile=collection",
|
|
203
|
+
);
|
|
204
|
+
if (poiMatch) {
|
|
205
|
+
log.debug("Found poi match, setting poi", poiMatch);
|
|
206
|
+
// render poi value into the link href
|
|
207
|
+
/** @type {any} */
|
|
208
|
+
let viewForMustache = poi.value;
|
|
209
|
+
const tokens = mustache.parse(poiMatch.href);
|
|
210
|
+
const keyToken = tokens.find(
|
|
211
|
+
(token) => token[0] === "name" && token[1] !== ".",
|
|
212
|
+
);
|
|
213
|
+
// Construct the view object
|
|
214
|
+
if (keyToken) {
|
|
215
|
+
const keyName = keyToken[1];
|
|
216
|
+
viewForMustache = { [keyName]: poi.value };
|
|
217
|
+
}
|
|
218
|
+
/** @type {string} */
|
|
219
|
+
const poiUrl = mustache.render(
|
|
220
|
+
poiMatch.href,
|
|
221
|
+
viewForMustache,
|
|
222
|
+
);
|
|
223
|
+
const poiAbsoluteUrl = toAbsolute(poiUrl, indicatorUrl);
|
|
224
|
+
await store.loadSelectedSTAC(poiAbsoluteUrl, true);
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
await store.loadSelectedSTAC(match.href);
|
|
228
|
+
}
|
|
142
229
|
}
|
|
143
230
|
break;
|
|
144
231
|
}
|
|
@@ -173,19 +260,25 @@ export const useURLSearchParametersSync = () => {
|
|
|
173
260
|
if (x && y && z) {
|
|
174
261
|
log.debug("Coordinates found, applying map poisition", x, y, z);
|
|
175
262
|
mapPosition.value = [x, y, z];
|
|
176
|
-
if (
|
|
177
|
-
|
|
263
|
+
if (mapEl.value) {
|
|
264
|
+
mapEl.value.center = [x, y];
|
|
265
|
+
mapEl.value.zoom = z;
|
|
178
266
|
}
|
|
179
267
|
}
|
|
268
|
+
|
|
269
|
+
if (!isFirstLoad.value) {
|
|
270
|
+
isFirstLoad.value = true;
|
|
271
|
+
}
|
|
180
272
|
}
|
|
181
273
|
|
|
182
274
|
watch(
|
|
183
|
-
[indicator, mapPosition, datetime, activeTemplate],
|
|
275
|
+
[indicator, mapPosition, datetime, activeTemplate, poi],
|
|
184
276
|
([
|
|
185
277
|
updatedIndicator,
|
|
186
278
|
updatedMapPosition,
|
|
187
279
|
updatedDatetime,
|
|
188
280
|
updatedTemplate,
|
|
281
|
+
updatedPoi,
|
|
189
282
|
]) => {
|
|
190
283
|
if ("URLSearchParams" in window) {
|
|
191
284
|
const searchParams = new URLSearchParams(window.location.search);
|
|
@@ -205,6 +298,14 @@ export const useURLSearchParametersSync = () => {
|
|
|
205
298
|
if (updatedTemplate) {
|
|
206
299
|
searchParams.set("template", updatedTemplate);
|
|
207
300
|
}
|
|
301
|
+
if (!updatedPoi) {
|
|
302
|
+
if (searchParams.has("poi")) {
|
|
303
|
+
searchParams.delete("poi");
|
|
304
|
+
}
|
|
305
|
+
} else {
|
|
306
|
+
searchParams.set("poi", updatedPoi);
|
|
307
|
+
}
|
|
308
|
+
|
|
208
309
|
const newRelativePathQuery =
|
|
209
310
|
window.location.pathname + "?" + searchParams.toString();
|
|
210
311
|
history.pushState(null, "", newRelativePathQuery);
|
|
@@ -218,25 +319,28 @@ export const useURLSearchParametersSync = () => {
|
|
|
218
319
|
* Converts eox-layout-item to transparent
|
|
219
320
|
*
|
|
220
321
|
* @param {import("vue").Ref<HTMLElement|null>} root - components root element ref*/
|
|
221
|
-
export const
|
|
322
|
+
export const useTransparentPanel = (root) => {
|
|
222
323
|
onMounted(() => {
|
|
223
|
-
const
|
|
224
|
-
if (
|
|
225
|
-
|
|
324
|
+
const backgroundItem = root.value?.parentElement;
|
|
325
|
+
if (backgroundItem?.classList.contains("bg-surface")) {
|
|
326
|
+
backgroundItem.classList.remove("bg-surface");
|
|
226
327
|
}
|
|
227
328
|
});
|
|
228
329
|
};
|
|
229
330
|
|
|
230
331
|
export const useGetTemplates = () => {
|
|
231
|
-
const eodash =
|
|
232
|
-
|
|
332
|
+
const eodash = inject(eodashKey);
|
|
333
|
+
if (!eodash) {
|
|
334
|
+
return [];
|
|
335
|
+
}
|
|
336
|
+
return "template" in eodash ? [] : Object.keys(eodash?.templates ?? {});
|
|
233
337
|
};
|
|
234
338
|
|
|
235
339
|
/**
|
|
236
340
|
* Listens to the `layers:updated` and `time:updated` events and calls
|
|
237
341
|
*
|
|
238
342
|
* @param {import("@vueuse/core").EventBusListener<
|
|
239
|
-
* "
|
|
343
|
+
* import("@/types").LayersEventBusKeys,
|
|
240
344
|
* {layers:Record<string,any>[]| undefined}
|
|
241
345
|
* >} listener
|
|
242
346
|
*/
|
|
@@ -249,3 +353,149 @@ export const useOnLayersUpdate = (listener) => {
|
|
|
249
353
|
unsubscribe();
|
|
250
354
|
});
|
|
251
355
|
};
|
|
356
|
+
/**
|
|
357
|
+
* @param {import("@/types").LayersEventBusKeys} event
|
|
358
|
+
* @param {import("@eox/map").EOxMap | null} mapEl
|
|
359
|
+
* @param {Record<string,any>[]} layers
|
|
360
|
+
*/
|
|
361
|
+
export const useEmitLayersUpdate = async (event, mapEl, layers) => {
|
|
362
|
+
if (!mapEl) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const layersEvents = useEventBus(eoxLayersKey);
|
|
367
|
+
|
|
368
|
+
const emit = async () =>
|
|
369
|
+
mapEl?.updateComplete.then(async () => {
|
|
370
|
+
await nextTick(() => {
|
|
371
|
+
layersEvents.emit(event, layers);
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
const dl = /** @type {import("ol/layer").Group} */ (
|
|
376
|
+
mapEl.getLayerById("AnalysisGroup")
|
|
377
|
+
);
|
|
378
|
+
await new Promise((res, _rej) => {
|
|
379
|
+
if (!dl) {
|
|
380
|
+
mapEl.map.getLayers().once("add", async () => {
|
|
381
|
+
await emit();
|
|
382
|
+
res(true);
|
|
383
|
+
});
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
dl.getLayers().once("change", async () => {
|
|
388
|
+
await emit();
|
|
389
|
+
res(true);
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* @param {import("stac-ts").StacCollection | import("stac-ts").StacLink | import("stac-ts").StacItem | null} collection
|
|
396
|
+
* @returns {string} - Returns the collection id or subcode if `useSubCode` is enabled
|
|
397
|
+
*/
|
|
398
|
+
export const useGetSubCodeId = (collection) => {
|
|
399
|
+
const eodash = useEodash();
|
|
400
|
+
|
|
401
|
+
if (!collection) {
|
|
402
|
+
return "";
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
if (eodash?.options?.useSubCode) {
|
|
406
|
+
return typeof collection.subcode === "string"
|
|
407
|
+
? collection.subcode
|
|
408
|
+
: /** @type {string} */ (collection.id);
|
|
409
|
+
}
|
|
410
|
+
return /** @type {string} */ (collection.id);
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Composable: Adopt Vuetify styles into eo-dash shadow root
|
|
415
|
+
* - Safe no-op outside Web Component context
|
|
416
|
+
* - Cleans up observers on unmount
|
|
417
|
+
*/
|
|
418
|
+
/**
|
|
419
|
+
* @param {string[]} [keyWords=["vuetify"]] - list of case-insensitive substrings to match against <style> element IDs
|
|
420
|
+
*/
|
|
421
|
+
export function useAdoptStyles(keyWords = ["vuetify"]) {
|
|
422
|
+
/** @type {Array<() => void>} */
|
|
423
|
+
let stops = [];
|
|
424
|
+
|
|
425
|
+
const eoDash =
|
|
426
|
+
/** @type {HTMLElement & { shadowRoot: ShadowRoot | null }} */ (
|
|
427
|
+
document.querySelector("eo-dash")
|
|
428
|
+
);
|
|
429
|
+
if (!eoDash || !eoDash.shadowRoot) return;
|
|
430
|
+
// Require Constructable Stylesheets support
|
|
431
|
+
if (typeof CSSStyleSheet === "undefined") return;
|
|
432
|
+
|
|
433
|
+
const head = document.head;
|
|
434
|
+
const shadow = eoDash.shadowRoot;
|
|
435
|
+
/** @type {Map<string, CSSStyleSheet>} */
|
|
436
|
+
const sheetsById = new Map();
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* @param {string} id
|
|
440
|
+
* @param {string} cssText
|
|
441
|
+
*/
|
|
442
|
+
const updateSheet = (id, cssText) => {
|
|
443
|
+
let sheet = sheetsById.get(id);
|
|
444
|
+
if (!sheet) {
|
|
445
|
+
sheet = new CSSStyleSheet();
|
|
446
|
+
sheet.replaceSync(cssText);
|
|
447
|
+
sheetsById.set(id, sheet);
|
|
448
|
+
shadow.adoptedStyleSheets = [...shadow.adoptedStyleSheets, sheet];
|
|
449
|
+
} else {
|
|
450
|
+
sheet.replaceSync(cssText);
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* @param {HTMLStyleElement} el
|
|
456
|
+
*/
|
|
457
|
+
const handleStyleEl = (el) => {
|
|
458
|
+
const id = el.id || "";
|
|
459
|
+
const idLc = id.toLowerCase();
|
|
460
|
+
if (!keyWords.some((s) => idLc.includes(String(s).toLowerCase()))) return;
|
|
461
|
+
const cssText = (el.textContent || "").replaceAll(":root", ":host");
|
|
462
|
+
if (!cssText) return;
|
|
463
|
+
|
|
464
|
+
updateSheet(id, cssText);
|
|
465
|
+
|
|
466
|
+
const observer = useMutationObserver(
|
|
467
|
+
el,
|
|
468
|
+
() => {
|
|
469
|
+
const nextCss = (el.textContent || "").replaceAll(":root", ":host");
|
|
470
|
+
if (nextCss) updateSheet(id, nextCss);
|
|
471
|
+
},
|
|
472
|
+
{ childList: true, characterData: true, subtree: true },
|
|
473
|
+
);
|
|
474
|
+
if (observer?.stop) stops.push(() => observer.stop());
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* @param {Node} node
|
|
479
|
+
*/
|
|
480
|
+
const handleNode = (node) => {
|
|
481
|
+
if (node instanceof HTMLStyleElement) handleStyleEl(node);
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
head.childNodes.forEach(handleNode);
|
|
485
|
+
|
|
486
|
+
const headObserver = useMutationObserver(
|
|
487
|
+
head,
|
|
488
|
+
(mutations) => {
|
|
489
|
+
mutations?.forEach((m) => {
|
|
490
|
+
m.addedNodes?.forEach(handleNode);
|
|
491
|
+
});
|
|
492
|
+
},
|
|
493
|
+
{ childList: true },
|
|
494
|
+
);
|
|
495
|
+
if (headObserver?.stop) stops.push(() => headObserver.stop());
|
|
496
|
+
|
|
497
|
+
onUnmounted(() => {
|
|
498
|
+
stops.forEach((stop) => stop());
|
|
499
|
+
stops = [];
|
|
500
|
+
});
|
|
501
|
+
}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
fetchStyle,
|
|
8
8
|
findLayer,
|
|
9
9
|
generateFeatures,
|
|
10
|
+
getDatetimeProperty,
|
|
10
11
|
replaceLayer,
|
|
11
12
|
} from "./helpers";
|
|
12
13
|
import {
|
|
@@ -57,10 +58,10 @@ export class EodashCollection {
|
|
|
57
58
|
/**
|
|
58
59
|
* @type {import("stac-ts").StacLink | undefined}
|
|
59
60
|
**/
|
|
60
|
-
let
|
|
61
|
+
let itemLink;
|
|
61
62
|
|
|
62
63
|
/**
|
|
63
|
-
* @type {import("stac-ts").StacCollection | undefined}
|
|
64
|
+
* @type {import("stac-ts").StacCollection | import("stac-ts").StacItem | undefined}
|
|
64
65
|
**/
|
|
65
66
|
let stac;
|
|
66
67
|
// TODO get auxiliary layers from collection
|
|
@@ -70,22 +71,26 @@ export class EodashCollection {
|
|
|
70
71
|
// Load collectionstac if not yet initialized
|
|
71
72
|
stac = await this.fetchCollection();
|
|
72
73
|
|
|
73
|
-
const
|
|
74
|
+
const isObservationPoint = stac?.endpointtype === "GeoDB";
|
|
74
75
|
|
|
75
76
|
if (linkOrDate instanceof Date) {
|
|
76
77
|
// if collectionStac not yet initialized we do it here
|
|
77
|
-
|
|
78
|
+
itemLink = this.getItem(linkOrDate);
|
|
78
79
|
} else {
|
|
79
|
-
|
|
80
|
+
itemLink = linkOrDate;
|
|
81
|
+
}
|
|
82
|
+
let stacItemUrl = "";
|
|
83
|
+
if (itemLink?.href.startsWith("blob:")) {
|
|
84
|
+
stacItemUrl = itemLink.href;
|
|
85
|
+
} else {
|
|
86
|
+
stacItemUrl = itemLink
|
|
87
|
+
? toAbsolute(itemLink.href, this.#collectionUrl)
|
|
88
|
+
: this.#collectionUrl;
|
|
80
89
|
}
|
|
81
|
-
|
|
82
|
-
const stacItemUrl = stacItem
|
|
83
|
-
? toAbsolute(stacItem.href, this.#collectionUrl)
|
|
84
|
-
: this.#collectionUrl;
|
|
85
90
|
|
|
86
91
|
stac = await axios.get(stacItemUrl).then((resp) => resp.data);
|
|
87
92
|
|
|
88
|
-
if (!
|
|
93
|
+
if (!itemLink) {
|
|
89
94
|
// no specific item was requested; render last item
|
|
90
95
|
this.#collectionStac = new Collection(stac);
|
|
91
96
|
this.selectedItem = this.getItem();
|
|
@@ -105,7 +110,12 @@ export class EodashCollection {
|
|
|
105
110
|
const title =
|
|
106
111
|
this.#collectionStac?.title || this.#collectionStac?.id || "";
|
|
107
112
|
layersJson.unshift(
|
|
108
|
-
...(await this.buildJsonArray(
|
|
113
|
+
...(await this.buildJsonArray(
|
|
114
|
+
item,
|
|
115
|
+
stacItemUrl,
|
|
116
|
+
title,
|
|
117
|
+
isObservationPoint,
|
|
118
|
+
)),
|
|
109
119
|
);
|
|
110
120
|
return layersJson;
|
|
111
121
|
}
|
|
@@ -115,20 +125,19 @@ export class EodashCollection {
|
|
|
115
125
|
* @param {import("stac-ts").StacItem} item
|
|
116
126
|
* @param {string} itemUrl
|
|
117
127
|
* @param {string} title
|
|
118
|
-
* @param {boolean}
|
|
128
|
+
* @param {boolean} isObservationPoint
|
|
119
129
|
* @param {string} [itemDatetime]
|
|
120
130
|
* @returns {Promise<Record<string,any>[]>} layers
|
|
121
131
|
* */
|
|
122
|
-
async buildJsonArray(item, itemUrl, title,
|
|
132
|
+
async buildJsonArray(item, itemUrl, title, isObservationPoint, itemDatetime) {
|
|
123
133
|
log.debug(
|
|
124
134
|
"Building JSON array",
|
|
125
135
|
item,
|
|
126
136
|
itemUrl,
|
|
127
137
|
title,
|
|
128
|
-
|
|
138
|
+
isObservationPoint,
|
|
129
139
|
itemDatetime,
|
|
130
140
|
);
|
|
131
|
-
await this.fetchCollection();
|
|
132
141
|
// registering top level indicator projection
|
|
133
142
|
const indicatorProjection =
|
|
134
143
|
item?.["proj:epsg"] || item?.["eodash:proj4_def"];
|
|
@@ -140,8 +149,8 @@ export class EodashCollection {
|
|
|
140
149
|
|
|
141
150
|
const jsonArray = [];
|
|
142
151
|
|
|
143
|
-
if (
|
|
144
|
-
// handled by
|
|
152
|
+
if (isObservationPoint) {
|
|
153
|
+
// handled by getObservationPointsLayer
|
|
145
154
|
return [];
|
|
146
155
|
}
|
|
147
156
|
|
|
@@ -158,7 +167,9 @@ export class EodashCollection {
|
|
|
158
167
|
|
|
159
168
|
const layerDatetime = extractLayerDatetime(
|
|
160
169
|
this.getItems(),
|
|
161
|
-
item.properties?.datetime ??
|
|
170
|
+
item.properties?.datetime ??
|
|
171
|
+
item.properties.start_datetime ??
|
|
172
|
+
itemDatetime,
|
|
162
173
|
);
|
|
163
174
|
|
|
164
175
|
const dataAssets = Object.keys(item?.assets ?? {}).reduce((data, ast) => {
|
|
@@ -191,6 +202,7 @@ export class EodashCollection {
|
|
|
191
202
|
...extraProperties,
|
|
192
203
|
...(this.color && { color: this.color }),
|
|
193
204
|
};
|
|
205
|
+
|
|
194
206
|
const links = await createLayersFromLinks(
|
|
195
207
|
this.#collectionStac?.id ?? "",
|
|
196
208
|
title,
|
|
@@ -198,6 +210,7 @@ export class EodashCollection {
|
|
|
198
210
|
layerDatetime,
|
|
199
211
|
extraProperties,
|
|
200
212
|
);
|
|
213
|
+
|
|
201
214
|
jsonArray.push(
|
|
202
215
|
...links,
|
|
203
216
|
...(await createLayersFromAssets(
|
|
@@ -247,14 +260,21 @@ export class EodashCollection {
|
|
|
247
260
|
return this.#collectionStac;
|
|
248
261
|
}
|
|
249
262
|
|
|
263
|
+
/**
|
|
264
|
+
* Returns all item links sorted by datetime ascendingly
|
|
265
|
+
*/
|
|
250
266
|
getItems() {
|
|
267
|
+
const datetimeProperty = getDatetimeProperty(this.#collectionStac?.links);
|
|
268
|
+
const items = this.#collectionStac?.links.filter((i) => i.rel === "item");
|
|
269
|
+
if (!datetimeProperty) {
|
|
270
|
+
return items;
|
|
271
|
+
}
|
|
251
272
|
return (
|
|
252
|
-
|
|
253
|
-
.filter((i) => i.rel === "item")
|
|
273
|
+
items
|
|
254
274
|
// sort by `datetime`, where oldest is first in array
|
|
255
|
-
|
|
256
|
-
/** @type {number} */ (a
|
|
257
|
-
/** @type {number} */ (b
|
|
275
|
+
?.sort((a, b) =>
|
|
276
|
+
/** @type {number} */ (a[datetimeProperty]) <
|
|
277
|
+
/** @type {number} */ (b[datetimeProperty])
|
|
258
278
|
? -1
|
|
259
279
|
: 1,
|
|
260
280
|
)
|
|
@@ -262,22 +282,16 @@ export class EodashCollection {
|
|
|
262
282
|
}
|
|
263
283
|
|
|
264
284
|
getDates() {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
/** @type {number} */ (b.datetime)
|
|
272
|
-
? -1
|
|
273
|
-
: 1,
|
|
274
|
-
)
|
|
275
|
-
.map((i) => new Date(/** @type {number} */ (i.datetime)))
|
|
285
|
+
const datetimeProperty = getDatetimeProperty(this.#collectionStac?.links);
|
|
286
|
+
if (!datetimeProperty) {
|
|
287
|
+
return [];
|
|
288
|
+
}
|
|
289
|
+
return this.getItems()?.map(
|
|
290
|
+
(i) => new Date(/** @type {number} */ (i[datetimeProperty])),
|
|
276
291
|
);
|
|
277
292
|
}
|
|
278
293
|
|
|
279
294
|
async getExtent() {
|
|
280
|
-
await this.fetchCollection();
|
|
281
295
|
return this.#collectionStac?.extent;
|
|
282
296
|
}
|
|
283
297
|
|
|
@@ -287,14 +301,19 @@ export class EodashCollection {
|
|
|
287
301
|
* @param {Date} [date]
|
|
288
302
|
**/
|
|
289
303
|
getItem(date) {
|
|
304
|
+
const datetimeProperty = getDatetimeProperty(this.#collectionStac?.links);
|
|
305
|
+
if (!datetimeProperty) {
|
|
306
|
+
// in case no datetime property is found, return the first item
|
|
307
|
+
return this.getItems()?.[0];
|
|
308
|
+
}
|
|
290
309
|
return date
|
|
291
310
|
? this.getItems()?.sort((a, b) => {
|
|
292
311
|
const distanceA = Math.abs(
|
|
293
|
-
new Date(/** @type {number} */ (a
|
|
312
|
+
new Date(/** @type {number} */ (a[datetimeProperty])).getTime() -
|
|
294
313
|
date.getTime(),
|
|
295
314
|
);
|
|
296
315
|
const distanceB = Math.abs(
|
|
297
|
-
new Date(/** @type {number} */ (b
|
|
316
|
+
new Date(/** @type {number} */ (b[datetimeProperty])).getTime() -
|
|
298
317
|
date.getTime(),
|
|
299
318
|
);
|
|
300
319
|
return distanceA - distanceB;
|
|
@@ -323,12 +342,16 @@ export class EodashCollection {
|
|
|
323
342
|
*/
|
|
324
343
|
async updateLayerJson(datetime, layer, map) {
|
|
325
344
|
await this.fetchCollection();
|
|
326
|
-
|
|
345
|
+
const datetimeProperty = getDatetimeProperty(this.#collectionStac?.links);
|
|
346
|
+
if (!datetimeProperty) {
|
|
347
|
+
console.warn("[eodash] no datetime property found in collection");
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
327
350
|
// get the link of the specified date
|
|
328
351
|
const specifiedLink = this.getItems()?.find(
|
|
329
352
|
(item) =>
|
|
330
|
-
typeof item
|
|
331
|
-
new Date(item
|
|
353
|
+
typeof item[datetimeProperty] === "string" &&
|
|
354
|
+
new Date(item[datetimeProperty]).toISOString() === datetime,
|
|
332
355
|
);
|
|
333
356
|
|
|
334
357
|
if (!specifiedLink) {
|
|
@@ -348,12 +371,13 @@ export class EodashCollection {
|
|
|
348
371
|
}
|
|
349
372
|
|
|
350
373
|
/** @type {string | undefined} */
|
|
351
|
-
const oldLayerID = findLayer(currentLayers, layer)?.properties
|
|
374
|
+
const oldLayerID = findLayer(currentLayers, layer)?.properties?.id;
|
|
352
375
|
|
|
353
376
|
if (!oldLayerID) {
|
|
354
377
|
return;
|
|
355
378
|
}
|
|
356
379
|
|
|
380
|
+
//@ts-expect-error TODO
|
|
357
381
|
const updatedLayers = replaceLayer(currentLayers, oldLayerID, newLayers);
|
|
358
382
|
|
|
359
383
|
return updatedLayers;
|
|
@@ -395,16 +419,18 @@ export class EodashCollection {
|
|
|
395
419
|
}
|
|
396
420
|
|
|
397
421
|
/**
|
|
398
|
-
* Returns
|
|
422
|
+
* Returns Observation points layer from a list of EodashCollections
|
|
399
423
|
*
|
|
400
424
|
* @param {EodashCollection[]} eodashCollections
|
|
401
425
|
*
|
|
402
426
|
**/
|
|
403
|
-
static
|
|
427
|
+
static getObservationPointsLayer(eodashCollections) {
|
|
404
428
|
const allFeatures = [];
|
|
405
429
|
for (const collection of eodashCollections) {
|
|
406
|
-
const
|
|
407
|
-
|
|
430
|
+
const isObservationPoint =
|
|
431
|
+
collection.#collectionStac?.endpointtype === "GeoDB" ||
|
|
432
|
+
/**@type {boolean} */ (collection.#collectionStac?.locations);
|
|
433
|
+
if (!isObservationPoint) {
|
|
408
434
|
continue;
|
|
409
435
|
}
|
|
410
436
|
const collectionFeatures = generateFeatures(
|
|
@@ -414,6 +440,7 @@ export class EodashCollection {
|
|
|
414
440
|
geoDBID: collection.#collectionStac?.geoDBID,
|
|
415
441
|
themes: collection.#collectionStac?.themes ?? [],
|
|
416
442
|
},
|
|
443
|
+
collection.#collectionStac?.locations ? "child" : "item",
|
|
417
444
|
).features;
|
|
418
445
|
|
|
419
446
|
if (collectionFeatures.length) {
|
|
@@ -475,13 +502,19 @@ export class EodashCollection {
|
|
|
475
502
|
"circle-radius": 10,
|
|
476
503
|
"circle-fill-color": "#00417077",
|
|
477
504
|
"circle-stroke-color": "#004170",
|
|
478
|
-
"fill-color": "#
|
|
505
|
+
"fill-color": "#00417077",
|
|
479
506
|
"stroke-color": "#004170",
|
|
480
507
|
},
|
|
481
508
|
},
|
|
482
509
|
];
|
|
483
510
|
})(),
|
|
484
|
-
interactions:
|
|
511
|
+
interactions: (() => {
|
|
512
|
+
const oldLayer = findLayer([...getLayers()], "geodb-collection");
|
|
513
|
+
if (!oldLayer || !oldLayer.interactions?.length) {
|
|
514
|
+
return [];
|
|
515
|
+
}
|
|
516
|
+
return [...oldLayer.interactions];
|
|
517
|
+
})(),
|
|
485
518
|
};
|
|
486
519
|
}
|
|
487
520
|
}
|