@eodash/eodash 5.2.0 → 5.3.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/core/client/components/DashboardLayout.vue +0 -1
- package/core/client/composables/index.js +53 -59
- package/core/client/eodashSTAC/EodashCollection.js +196 -94
- package/core/client/eodashSTAC/auth.js +86 -0
- package/core/client/eodashSTAC/createLayers.js +204 -4
- package/core/client/eodashSTAC/helpers.js +258 -58
- package/core/client/eodashSTAC/parquet.js +0 -13
- package/core/client/eodashSTAC/triggers.js +1 -1
- package/core/client/store/actions.js +14 -0
- package/core/client/store/stac.js +46 -8
- package/core/client/store/states.js +6 -0
- package/core/client/types.ts +206 -3
- package/core/client/utils/bands-editor/arithmetic.js +144 -0
- package/core/client/utils/bands-editor/colors.js +36 -0
- package/core/client/utils/bands-editor/dom.js +196 -0
- package/core/client/utils/bands-editor/exampleSchema.json +1320 -0
- package/core/client/utils/bands-editor/index.js +68 -0
- package/core/client/utils/bands-editor/rgb.js +102 -0
- package/core/client/utils/index.js +5 -2
- package/core/client/views/Dashboard.vue +1 -1
- package/core/client/vite-env.d.ts +122 -0
- package/dist/client/{DashboardLayout-Dq9Kfe6O.js → DashboardLayout-Cq15p4TH.js} +4 -5
- package/dist/client/{DynamicWebComponent-DCBMXskE.js → DynamicWebComponent-Cv-fPRG1.js} +1 -1
- package/dist/client/{EodashDatePicker-DtngxU6s.js → EodashDatePicker-CPlJwEIO.js} +20 -22
- package/dist/client/{EodashItemFilter-ClQebJQt.js → EodashItemFilter-Ydebgbjj.js} +46 -31
- package/dist/client/EodashLayerControl-COhrkNEs.js +1517 -0
- package/dist/client/{EodashLayoutSwitcher-DQ8SfVDd.js → EodashLayoutSwitcher-pnKhTRZV.js} +4 -4
- package/dist/client/EodashMapBtns-Cj0Fx119.js +301 -0
- package/dist/client/{EodashStacInfo-Dt1nF06x.js → EodashStacInfo-Dadkg_Nj.js} +1 -1
- package/dist/client/EodashTimeSlider-CpoHX0S7.js +53 -0
- package/dist/client/{EodashTools-DV5ykmWc.js → EodashTools-UGBG7KC9.js} +10 -7
- package/dist/client/{ExportState-B6zZQUmE.js → ExportState-GtJkAqeZ.js} +145 -120
- package/dist/client/{Footer-DNhXs8k6.js → Footer-D3ZPG5c4.js} +1 -1
- package/dist/client/{Header-BjhN5JY4.js → Header-z6AK-wpN.js} +2 -2
- package/dist/client/MobileLayout-BXNsNftb.js +118 -0
- package/dist/client/{PopUp-CgpvNr3o.js → PopUp-BbQdjENV.js} +79 -43
- package/dist/client/{ProcessList-vecpxThi.js → ProcessList-C6VsdsYI.js} +5 -6
- package/dist/client/{VImg-CETuikH2.js → VImg-CxaMSB99.js} +6 -3
- package/dist/client/{VMain-Ci9DyaGU.js → VMain-Ds7yw0wj.js} +1 -1
- package/dist/client/{VTooltip-J4ac48X7.js → VTooltip-Cze6CEVh.js} +2 -2
- package/dist/client/{WidgetsContainer-CCML4TyV.js → WidgetsContainer-D66bj-JJ.js} +1 -1
- package/dist/client/asWebComponent-CWbNRdf9.js +8895 -0
- package/dist/client/{async-B7jIrM53.js → async-BA7oWCMX.js} +2 -2
- package/dist/client/easing-CH0-9wR8.js +35 -0
- package/dist/client/eo-dash.js +1 -1
- package/dist/client/{forwardRefs-BQclvjMq.js → forwardRefs-BUfxOIo-.js} +58 -45
- package/dist/client/{handling-BS24aG1q.js → handling-DlNTtKB-.js} +12 -6
- package/dist/client/{helpers-wXK7Ywio.js → helpers-CtE0W7iu.js} +572 -277
- package/dist/client/{index-4UCzZi8B.js → index-CeEZIjO6.js} +26 -13
- package/dist/client/{index-B2XpdgR6.js → index-CsKbRDeN.js} +63 -36
- package/dist/client/{index-9KR-G20t.js → index-D4_NRKrf.js} +2 -2
- package/dist/client/index-DeECc3lV.js +571 -0
- package/dist/client/templates.js +82 -15
- package/dist/client/{transition-yBii4fu6.js → transition-Byvp3L6Y.js} +1 -1
- package/dist/node/cli.js +6 -6
- package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +24 -10
- package/dist/types/core/client/eodashSTAC/auth.d.ts +7 -0
- package/dist/types/core/client/eodashSTAC/createLayers.d.ts +15 -3
- package/dist/types/core/client/eodashSTAC/helpers.d.ts +46 -15
- package/dist/types/core/client/plugins/vuetify.d.ts +14 -14
- package/dist/types/core/client/store/actions.d.ts +2 -0
- package/dist/types/core/client/store/stac.d.ts +16 -7
- package/dist/types/core/client/store/states.d.ts +4 -0
- package/dist/types/core/client/types.d.ts +170 -2
- package/dist/types/core/client/utils/bands-editor/arithmetic.d.ts +8 -0
- package/dist/types/core/client/utils/bands-editor/colors.d.ts +15 -0
- package/dist/types/core/client/utils/bands-editor/dom.d.ts +42 -0
- package/dist/types/core/client/utils/bands-editor/index.d.ts +20 -0
- package/dist/types/core/client/utils/bands-editor/rgb.d.ts +15 -0
- package/dist/types/core/client/utils/index.d.ts +1 -1
- package/dist/types/templates/baseConfig.d.ts +87 -1
- package/dist/types/templates/expert.d.ts +6 -6
- package/dist/types/templates/explore.d.ts +67 -0
- package/dist/types/templates/index.d.ts +1 -1
- package/dist/types/templates/{light.d.ts → lite.d.ts} +5 -5
- package/dist/types/widgets/EodashItemCatalog/index.vue.d.ts +21 -0
- package/dist/types/widgets/EodashItemCatalog/methods/filters.d.ts +49 -0
- package/dist/types/widgets/EodashItemCatalog/methods/handlers.d.ts +4 -0
- package/dist/types/widgets/EodashItemCatalog/methods/map.d.ts +12 -0
- package/dist/types/widgets/EodashItemCatalog/types.d.ts +14 -0
- package/dist/types/widgets/EodashMap/EodashMapBtns.vue.d.ts +2 -0
- package/dist/types/widgets/EodashMap/index.vue.d.ts +108 -2
- package/dist/types/widgets/EodashMap/methods/create-layers-config.d.ts +1 -1
- package/dist/types/widgets/EodashMap/methods/index.d.ts +1 -1
- package/dist/types/widgets/EodashProcess/methods/custom-endpoints/layers/eoxhub-workspaces-endpoint.d.ts +1 -1
- package/dist/types/widgets/EodashTimeSlider.vue.d.ts +7 -0
- package/dist/types/widgets/EodashTools.vue.d.ts +10 -10
- package/dist/types/widgets/ExportState.vue.d.ts +2 -0
- package/package.json +28 -27
- package/templates/baseConfig.js +10 -5
- package/templates/compare.js +2 -2
- package/templates/expert.js +5 -5
- package/templates/explore.js +62 -0
- package/templates/index.js +1 -1
- package/templates/{light.js → lite.js} +1 -1
- package/widgets/EodashDatePicker.vue +15 -18
- package/widgets/EodashItemCatalog/index.vue +161 -0
- package/widgets/EodashItemCatalog/methods/filters.js +216 -0
- package/widgets/EodashItemCatalog/methods/handlers.js +50 -0
- package/widgets/EodashItemCatalog/methods/map.js +144 -0
- package/widgets/EodashItemCatalog/types.ts +15 -0
- package/widgets/EodashItemFilter.vue +35 -28
- package/widgets/EodashLayerControl.vue +10 -6
- package/widgets/EodashLayoutSwitcher.vue +1 -1
- package/widgets/EodashMap/EodashMapBtns.vue +18 -9
- package/widgets/EodashMap/index.vue +22 -12
- package/widgets/EodashMap/methods/create-layers-config.js +9 -6
- package/widgets/EodashMap/methods/index.js +27 -13
- package/widgets/EodashProcess/index.vue +17 -1
- package/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.js +9 -3
- package/widgets/EodashProcess/methods/handling.js +2 -0
- package/widgets/EodashProcess/methods/outputs.js +1 -0
- package/widgets/EodashTimeSlider.vue +40 -0
- package/widgets/EodashTools.vue +7 -3
- package/widgets/ExportState.vue +53 -22
- package/dist/client/EodashLayerControl-BLBds28C.js +0 -154
- package/dist/client/EodashMapBtns-B89_YBDw.js +0 -326
- package/dist/client/MobileLayout-JelB6w1G.js +0 -118
- package/dist/client/asWebComponent-ZyEzWOOf.js +0 -19092
|
@@ -22,6 +22,7 @@ import { setCollectionsPalette } from "@/utils";
|
|
|
22
22
|
import mustache from "mustache";
|
|
23
23
|
import { toAbsolute } from "stac-js/src/http.js";
|
|
24
24
|
import axios from "@/plugins/axios";
|
|
25
|
+
import { storeToRefs } from "pinia";
|
|
25
26
|
|
|
26
27
|
/**
|
|
27
28
|
/** @type {import('@/types').Eodash | null}*/
|
|
@@ -57,68 +58,60 @@ export function useEodash() {
|
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* @param {string} [rel=''] Default is `''`
|
|
63
|
-
* @param {string} [base=eodash.stacEndpoint] - Base URL, default value is the
|
|
64
|
-
* root stac catalog. Default is `eodash.stacEndpoint`
|
|
65
|
-
* @returns {import("vue").Ref<string>} - Returns `currentUrl`
|
|
66
|
-
* @see {@link '@/store/states.js'}
|
|
61
|
+
* @param {import("vue").Ref<string>} absoluteUrl
|
|
62
|
+
* @returns
|
|
67
63
|
*/
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
64
|
+
const createUseAbsoluteUrl = (absoluteUrl) => {
|
|
65
|
+
/**
|
|
66
|
+
* Creates an absolute URL from a relative link and assignes it to `currentUrl`
|
|
67
|
+
*
|
|
68
|
+
* @param {string} [rel=''] Default is `''`
|
|
69
|
+
* @param {string} [base=eodash.stacEndpoint] - Base URL, default value is the
|
|
70
|
+
* root stac catalog. Default is `eodash.stacEndpoint`
|
|
71
|
+
* @returns {import("vue").Ref<string>} - Returns `currentUrl`
|
|
72
|
+
* @see {@link '@/store/states.js'}
|
|
73
|
+
*/
|
|
74
|
+
return (rel = "", base) => {
|
|
75
|
+
const { stacEndpoint, isApi } = storeToRefs(useSTAcStore());
|
|
76
|
+
if (!base) {
|
|
77
|
+
base = stacEndpoint.value ?? undefined;
|
|
78
|
+
if (!base) {
|
|
79
|
+
console.warn(
|
|
80
|
+
"[eodash] No base URL provided for absolute URL construction.",
|
|
81
|
+
);
|
|
82
|
+
return absoluteUrl;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (isApi.value) {
|
|
86
|
+
absoluteUrl.value = base + `/collections/${rel}`;
|
|
87
|
+
return absoluteUrl;
|
|
88
|
+
}
|
|
90
89
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
*/
|
|
100
|
-
export const useCompareAbsoluteUrl = (
|
|
101
|
-
rel = "",
|
|
102
|
-
base = inject(eodashKey)?.stacEndpoint,
|
|
103
|
-
) => {
|
|
104
|
-
if (!rel || rel.includes("http") || !base) {
|
|
105
|
-
currentCompareUrl.value = rel;
|
|
106
|
-
return currentCompareUrl;
|
|
107
|
-
}
|
|
90
|
+
if (rel.includes("http")) {
|
|
91
|
+
absoluteUrl.value = rel;
|
|
92
|
+
return absoluteUrl;
|
|
93
|
+
}
|
|
94
|
+
if (!rel) {
|
|
95
|
+
absoluteUrl.value = base;
|
|
96
|
+
return absoluteUrl;
|
|
97
|
+
}
|
|
108
98
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
99
|
+
const st = base.split("/");
|
|
100
|
+
const arr = rel.split("/");
|
|
101
|
+
st.pop();
|
|
112
102
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
103
|
+
for (let i = 0; i < arr.length; i++) {
|
|
104
|
+
if (arr[i] == ".") continue;
|
|
105
|
+
if (arr[i] == "..") st.pop();
|
|
106
|
+
else st.push(arr[i]);
|
|
107
|
+
}
|
|
118
108
|
|
|
119
|
-
|
|
120
|
-
|
|
109
|
+
absoluteUrl.value = st.join("/");
|
|
110
|
+
return absoluteUrl;
|
|
111
|
+
};
|
|
121
112
|
};
|
|
113
|
+
export const useAbsoluteUrl = createUseAbsoluteUrl(currentUrl);
|
|
114
|
+
export const useCompareAbsoluteUrl = createUseAbsoluteUrl(currentCompareUrl);
|
|
122
115
|
|
|
123
116
|
/**
|
|
124
117
|
* Updates an existing Vuetify theme. updates only the values provided in the
|
|
@@ -178,7 +171,6 @@ export const useURLSearchParametersSync = () => {
|
|
|
178
171
|
}
|
|
179
172
|
case "indicator": {
|
|
180
173
|
log.debug("Found indicator key in url");
|
|
181
|
-
const eodash = inject(eodashKey);
|
|
182
174
|
const match = store.stac?.find(
|
|
183
175
|
(link) => useGetSubCodeId(link) == value,
|
|
184
176
|
);
|
|
@@ -187,7 +179,7 @@ export const useURLSearchParametersSync = () => {
|
|
|
187
179
|
if (searchParams.has("poi")) {
|
|
188
180
|
const indicatorUrl = toAbsolute(
|
|
189
181
|
match.href,
|
|
190
|
-
|
|
182
|
+
store.stacEndpoint ?? "",
|
|
191
183
|
);
|
|
192
184
|
// fetch indicator stac collection without rendering it
|
|
193
185
|
/** @type {import("stac-ts").StacCollection} */
|
|
@@ -224,7 +216,9 @@ export const useURLSearchParametersSync = () => {
|
|
|
224
216
|
await store.loadSelectedSTAC(poiAbsoluteUrl, true);
|
|
225
217
|
}
|
|
226
218
|
} else {
|
|
227
|
-
await store.loadSelectedSTAC(
|
|
219
|
+
await store.loadSelectedSTAC(
|
|
220
|
+
/** @type {string} */ (store.isApi ? match.id : match.href),
|
|
221
|
+
);
|
|
228
222
|
}
|
|
229
223
|
}
|
|
230
224
|
break;
|
|
@@ -2,21 +2,28 @@ import { Collection, Item } from "stac-js";
|
|
|
2
2
|
import { toAbsolute } from "stac-js/src/http.js";
|
|
3
3
|
import {
|
|
4
4
|
extractLayerConfig,
|
|
5
|
-
extractLayerDatetime,
|
|
6
5
|
extractRoles,
|
|
6
|
+
fetchApiItems,
|
|
7
7
|
fetchStyle,
|
|
8
|
+
fetchAllStyles,
|
|
8
9
|
findLayer,
|
|
9
10
|
generateFeatures,
|
|
10
11
|
getDatetimeProperty,
|
|
12
|
+
isSTACItem,
|
|
11
13
|
replaceLayer,
|
|
12
14
|
extractLayerLegend,
|
|
15
|
+
extractLayerTimeValues,
|
|
13
16
|
} from "./helpers";
|
|
14
17
|
import {
|
|
15
18
|
getLayers,
|
|
16
19
|
getCompareLayers,
|
|
17
20
|
registerProjection,
|
|
18
21
|
} from "@/store/actions";
|
|
19
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
createLayerFromRender,
|
|
24
|
+
createLayersFromAssets,
|
|
25
|
+
createLayersFromLinks,
|
|
26
|
+
} from "./createLayers";
|
|
20
27
|
import axios from "@/plugins/axios";
|
|
21
28
|
import log from "loglevel";
|
|
22
29
|
import { dataThemesBrands } from "@/utils/states";
|
|
@@ -24,6 +31,10 @@ import { dataThemesBrands } from "@/utils/states";
|
|
|
24
31
|
export class EodashCollection {
|
|
25
32
|
#collectionUrl = "";
|
|
26
33
|
|
|
34
|
+
isAPI = true;
|
|
35
|
+
/** @type {string | null} */
|
|
36
|
+
rasterEndpoint = null;
|
|
37
|
+
|
|
27
38
|
/** @type {import("stac-ts").StacCollection | undefined} */
|
|
28
39
|
#collectionStac;
|
|
29
40
|
|
|
@@ -45,81 +56,87 @@ export class EodashCollection {
|
|
|
45
56
|
return this.#collectionStac;
|
|
46
57
|
}
|
|
47
58
|
|
|
48
|
-
/**
|
|
49
|
-
|
|
59
|
+
/**
|
|
60
|
+
* @param {string} collectionUrl
|
|
61
|
+
* @param {boolean} isAPI
|
|
62
|
+
* @param {string | null} rasterEndpoint
|
|
63
|
+
*/
|
|
64
|
+
constructor(collectionUrl, isAPI = true, rasterEndpoint = null) {
|
|
50
65
|
this.#collectionUrl = collectionUrl;
|
|
66
|
+
this.isAPI = isAPI;
|
|
67
|
+
this.rasterEndpoint = rasterEndpoint;
|
|
51
68
|
}
|
|
52
69
|
|
|
53
70
|
/**
|
|
54
71
|
* @async
|
|
55
|
-
* @param {import('stac-ts').StacLink | Date} [
|
|
56
|
-
* @returns
|
|
72
|
+
* @param {import("stac-ts").StacItem | import('stac-ts').StacLink | Date } [itemOrDate]
|
|
73
|
+
* @returns {Promise<Record<string,any>[]>} layers
|
|
57
74
|
*/
|
|
58
|
-
createLayersJson = async (
|
|
75
|
+
createLayersJson = async (itemOrDate) => {
|
|
59
76
|
/**
|
|
60
|
-
* @type {import("stac-ts").StacLink | undefined}
|
|
77
|
+
* @type {import("stac-ts").StacLink | import("stac-ts").StacItem | undefined}
|
|
61
78
|
**/
|
|
62
|
-
let
|
|
79
|
+
let itemOrItemLink;
|
|
63
80
|
|
|
64
|
-
/**
|
|
65
|
-
* @type {import("stac-ts").StacCollection | import("stac-ts").StacItem | undefined}
|
|
66
|
-
**/
|
|
67
|
-
let stac;
|
|
68
81
|
// TODO get auxiliary layers from collection
|
|
69
82
|
/** @type {Record<string,any>[]} */
|
|
70
83
|
let layersJson = [];
|
|
71
84
|
|
|
72
|
-
// Load collectionstac if not yet initialized
|
|
73
|
-
|
|
85
|
+
// Load collectionstac if not yet initialized // TODO
|
|
86
|
+
await this.fetchCollection();
|
|
74
87
|
|
|
75
|
-
const isObservationPoint =
|
|
88
|
+
const isObservationPoint = this.#collectionStac?.endpointtype === "GeoDB";
|
|
76
89
|
|
|
77
|
-
if (
|
|
90
|
+
if (itemOrDate instanceof Date) {
|
|
78
91
|
// if collectionStac not yet initialized we do it here
|
|
79
|
-
|
|
92
|
+
itemOrItemLink = await this.getItem(itemOrDate);
|
|
80
93
|
} else {
|
|
81
|
-
|
|
94
|
+
itemOrItemLink = itemOrDate;
|
|
82
95
|
}
|
|
83
|
-
let stacItemUrl = "";
|
|
84
|
-
if (itemLink?.href.startsWith("blob:")) {
|
|
85
|
-
stacItemUrl = itemLink.href;
|
|
86
|
-
} else {
|
|
87
|
-
stacItemUrl = itemLink
|
|
88
|
-
? toAbsolute(itemLink.href, this.#collectionUrl)
|
|
89
|
-
: this.#collectionUrl;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
stac = await axios.get(stacItemUrl).then((resp) => resp.data);
|
|
93
96
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
this
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
if (
|
|
100
|
-
|
|
97
|
+
let stacItemUrl = "";
|
|
98
|
+
if (isSTACItem(itemOrItemLink)) {
|
|
99
|
+
this.selectedItem = itemOrItemLink;
|
|
100
|
+
stacItemUrl = this.#collectionUrl + `/items/${this.selectedItem.id}`;
|
|
101
|
+
} else if (itemOrItemLink) {
|
|
102
|
+
if (itemOrItemLink?.href?.startsWith("blob:")) {
|
|
103
|
+
stacItemUrl = itemOrItemLink.href;
|
|
104
|
+
// Use native fetch for blob URLs to avoid axios/cache interceptor issues
|
|
105
|
+
this.selectedItem = await fetch(stacItemUrl).then(
|
|
106
|
+
async (resp) => await resp.json(),
|
|
107
|
+
);
|
|
101
108
|
} else {
|
|
109
|
+
stacItemUrl = toAbsolute(itemOrItemLink.href, this.#collectionUrl);
|
|
110
|
+
this.selectedItem = await axios
|
|
111
|
+
.get(stacItemUrl)
|
|
112
|
+
.then((resp) => resp.data);
|
|
113
|
+
}
|
|
114
|
+
} else if (!this.selectedItem) {
|
|
115
|
+
this.selectedItem = await this.getItem();
|
|
116
|
+
if (!this.selectedItem) {
|
|
102
117
|
console.warn(
|
|
103
118
|
"[eodash] the selected collection does not include any items",
|
|
104
119
|
);
|
|
120
|
+
return [];
|
|
121
|
+
} else if (this.selectedItem) {
|
|
122
|
+
// if no specific item was requested, we create layers from the latest item
|
|
123
|
+
return this.createLayersJson(this.selectedItem);
|
|
105
124
|
}
|
|
106
|
-
return [];
|
|
107
|
-
} else {
|
|
108
|
-
// specific item was requested
|
|
109
|
-
const item = new Item(stac);
|
|
110
|
-
this.selectedItem = item;
|
|
111
|
-
const title =
|
|
112
|
-
this.#collectionStac?.title || this.#collectionStac?.id || "";
|
|
113
|
-
layersJson.unshift(
|
|
114
|
-
...(await this.buildJsonArray(
|
|
115
|
-
item,
|
|
116
|
-
stacItemUrl,
|
|
117
|
-
title,
|
|
118
|
-
isObservationPoint,
|
|
119
|
-
)),
|
|
120
|
-
);
|
|
121
|
-
return layersJson;
|
|
122
125
|
}
|
|
126
|
+
|
|
127
|
+
// specific item was requested
|
|
128
|
+
const item = new Item(this.selectedItem);
|
|
129
|
+
this.selectedItem = item;
|
|
130
|
+
const title = this.#collectionStac?.title || this.#collectionStac?.id || "";
|
|
131
|
+
layersJson.unshift(
|
|
132
|
+
...(await this.buildJsonArray(
|
|
133
|
+
item,
|
|
134
|
+
stacItemUrl,
|
|
135
|
+
title,
|
|
136
|
+
isObservationPoint,
|
|
137
|
+
)),
|
|
138
|
+
);
|
|
139
|
+
return layersJson;
|
|
123
140
|
};
|
|
124
141
|
|
|
125
142
|
/**
|
|
@@ -131,6 +148,11 @@ export class EodashCollection {
|
|
|
131
148
|
* @returns {Promise<Record<string,any>[]>} layers
|
|
132
149
|
* */
|
|
133
150
|
async buildJsonArray(item, itemUrl, title, isObservationPoint, itemDatetime) {
|
|
151
|
+
if (!item) {
|
|
152
|
+
console.warn("[eodash] no item provided to buildJsonArray");
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
|
|
134
156
|
log.debug(
|
|
135
157
|
"Building JSON array",
|
|
136
158
|
item,
|
|
@@ -161,13 +183,21 @@ export class EodashCollection {
|
|
|
161
183
|
// will try to extract anything it supports but for which we have
|
|
162
184
|
// less control.
|
|
163
185
|
|
|
186
|
+
const rasterformURL = /** @type {string|undefined} */ (
|
|
187
|
+
this.#collectionStac?.["eodash:rasterform"]
|
|
188
|
+
);
|
|
189
|
+
/** @type {import("@/types").EodashRasterJSONForm|undefined} */
|
|
190
|
+
const rasterForm = rasterformURL
|
|
191
|
+
? await axios.get(rasterformURL).then((resp) => resp.data)
|
|
192
|
+
: undefined;
|
|
164
193
|
let { layerConfig, style } = extractLayerConfig(
|
|
165
194
|
this.#collectionStac?.id ?? "",
|
|
166
195
|
await fetchStyle(item, itemUrl),
|
|
196
|
+
rasterForm,
|
|
167
197
|
);
|
|
168
198
|
|
|
169
|
-
const layerDatetime =
|
|
170
|
-
this.getItems(),
|
|
199
|
+
const { layerDatetime, timeControlValues } = extractLayerTimeValues(
|
|
200
|
+
await this.getItems(),
|
|
171
201
|
item.properties?.datetime ??
|
|
172
202
|
item.properties.start_datetime ??
|
|
173
203
|
itemDatetime,
|
|
@@ -180,7 +210,7 @@ export class EodashCollection {
|
|
|
180
210
|
return data;
|
|
181
211
|
}, /** @type {Record<string,import('stac-ts').StacAsset>} */ ({}));
|
|
182
212
|
const isSupported =
|
|
183
|
-
item.links.some((link) => ["wms", "xyz", "wmts"].includes(link.rel)) ||
|
|
213
|
+
item.links.some((link) => ["wms", "xyz", "wmts", "vector-tile"].includes(link.rel)) ||
|
|
184
214
|
Object.keys(dataAssets).length;
|
|
185
215
|
|
|
186
216
|
if (isSupported) {
|
|
@@ -189,17 +219,34 @@ export class EodashCollection {
|
|
|
189
219
|
extraProperties = {
|
|
190
220
|
...extraProperties,
|
|
191
221
|
...(this.color && { color: this.color }),
|
|
222
|
+
...(timeControlValues && {
|
|
223
|
+
timeControlValues,
|
|
224
|
+
timeControlProperty: "TIME",
|
|
225
|
+
}),
|
|
192
226
|
};
|
|
193
227
|
|
|
194
228
|
const links = await createLayersFromLinks(
|
|
195
229
|
this.#collectionStac?.id ?? "",
|
|
196
230
|
title,
|
|
197
231
|
item,
|
|
232
|
+
itemUrl,
|
|
198
233
|
layerDatetime,
|
|
199
234
|
extraProperties,
|
|
200
235
|
);
|
|
201
236
|
|
|
202
237
|
jsonArray.push(
|
|
238
|
+
...((this.rasterEndpoint &&
|
|
239
|
+
createLayerFromRender(
|
|
240
|
+
this.rasterEndpoint,
|
|
241
|
+
this.#collectionStac,
|
|
242
|
+
item,
|
|
243
|
+
{
|
|
244
|
+
...extraProperties,
|
|
245
|
+
...(layerConfig && { layerConfig }),
|
|
246
|
+
...(layerDatetime && { layerDatetime }),
|
|
247
|
+
},
|
|
248
|
+
)) ||
|
|
249
|
+
[]),
|
|
203
250
|
...(await createLayersFromAssets(
|
|
204
251
|
this.#collectionStac?.id ?? "",
|
|
205
252
|
title || this.#collectionStac?.title || item.id,
|
|
@@ -210,8 +257,8 @@ export class EodashCollection {
|
|
|
210
257
|
layerDatetime,
|
|
211
258
|
extraProperties,
|
|
212
259
|
)),
|
|
213
|
-
...links,
|
|
214
260
|
// We add the links after the assets so they are layered underneath assets
|
|
261
|
+
...links,
|
|
215
262
|
);
|
|
216
263
|
} else {
|
|
217
264
|
// fallback to STAC
|
|
@@ -240,21 +287,38 @@ export class EodashCollection {
|
|
|
240
287
|
|
|
241
288
|
async fetchCollection() {
|
|
242
289
|
if (!this.#collectionStac) {
|
|
243
|
-
log.debug("Fetching collection file", this.#collectionUrl);
|
|
244
290
|
const col = await axios
|
|
245
291
|
.get(this.#collectionUrl)
|
|
246
292
|
.then((resp) => resp.data);
|
|
247
293
|
this.#collectionStac = new Collection(col);
|
|
294
|
+
log.debug("Fetching collection file", this.#collectionUrl);
|
|
248
295
|
}
|
|
249
296
|
return this.#collectionStac;
|
|
250
297
|
}
|
|
251
298
|
|
|
252
299
|
/**
|
|
253
300
|
* Returns all item links sorted by datetime ascendingly
|
|
301
|
+
* @param {boolean} [fields=false] if true, fetch items from API with only properties
|
|
302
|
+
* @param {boolean} [first] - if true, returns the first page of items only (for API collections)
|
|
303
|
+
* @returns {Promise<import("stac-ts").StacLink[] | import("stac-ts").StacItem[] | undefined>}
|
|
254
304
|
*/
|
|
255
|
-
getItems() {
|
|
256
|
-
const datetimeProperty = getDatetimeProperty(this.#collectionStac?.links);
|
|
305
|
+
async getItems(fields = false, first = false) {
|
|
257
306
|
const items = this.#collectionStac?.links.filter((i) => i.rel === "item");
|
|
307
|
+
|
|
308
|
+
if (this.isAPI && !items?.length) {
|
|
309
|
+
const itemUrl = this.#collectionUrl + "/items";
|
|
310
|
+
if (fields) {
|
|
311
|
+
return await fetchApiItems(
|
|
312
|
+
itemUrl,
|
|
313
|
+
`fields=properties,-assets,-geometry,-links,-bbox`,
|
|
314
|
+
100,
|
|
315
|
+
first,
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
return await fetchApiItems(itemUrl, undefined, 100, first);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const datetimeProperty = getDatetimeProperty(this.#collectionStac?.links);
|
|
258
322
|
if (!datetimeProperty) {
|
|
259
323
|
return items;
|
|
260
324
|
}
|
|
@@ -270,14 +334,21 @@ export class EodashCollection {
|
|
|
270
334
|
);
|
|
271
335
|
}
|
|
272
336
|
|
|
273
|
-
getDates() {
|
|
274
|
-
const
|
|
275
|
-
|
|
337
|
+
async getDates() {
|
|
338
|
+
const items = await this.getItems(true, false);
|
|
339
|
+
|
|
340
|
+
const datetimeProperty = getDatetimeProperty(items);
|
|
341
|
+
if (!datetimeProperty || !items?.length) {
|
|
276
342
|
return [];
|
|
277
343
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
344
|
+
|
|
345
|
+
const mapToDates = this.isAPI
|
|
346
|
+
? //@ts-expect-error todo
|
|
347
|
+
(i) =>
|
|
348
|
+
new Date(/** @type {string} */ (i.properties?.[datetimeProperty]))
|
|
349
|
+
: //@ts-expect-error todo
|
|
350
|
+
(i) => new Date(/** @type {string} */ (i[datetimeProperty]));
|
|
351
|
+
return items?.map(mapToDates) || [];
|
|
281
352
|
}
|
|
282
353
|
|
|
283
354
|
async getExtent() {
|
|
@@ -288,38 +359,58 @@ export class EodashCollection {
|
|
|
288
359
|
* Get closest Item Link from a certain date,
|
|
289
360
|
* get the latest if no date provided
|
|
290
361
|
* @param {Date} [date]
|
|
362
|
+
* @return {Promise<import("stac-ts").StacItem | import("stac-ts").StacLink | undefined>} item
|
|
291
363
|
**/
|
|
292
|
-
getItem(date) {
|
|
293
|
-
|
|
364
|
+
async getItem(date) {
|
|
365
|
+
if (!date) {
|
|
366
|
+
return (await this.getItems(false, true))?.[0];
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const items = await this.getItems();
|
|
370
|
+
const datetimeProperty = getDatetimeProperty(items);
|
|
294
371
|
if (!datetimeProperty) {
|
|
295
372
|
// in case no datetime property is found, return the first item
|
|
296
|
-
return this.getItems()?.[0];
|
|
373
|
+
return (await this.getItems(false, true))?.[0];
|
|
297
374
|
}
|
|
298
|
-
return
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
375
|
+
return (await this.getItems())?.sort((a, b) => {
|
|
376
|
+
const distanceA = Math.abs(
|
|
377
|
+
new Date(
|
|
378
|
+
/** @type {number} */ (
|
|
379
|
+
//@ts-expect-error TODO
|
|
380
|
+
this.isAPI ? a.properties[datetimeProperty] : a[datetimeProperty]
|
|
381
|
+
),
|
|
382
|
+
).getTime() - date.getTime(),
|
|
383
|
+
);
|
|
384
|
+
const distanceB = Math.abs(
|
|
385
|
+
new Date(
|
|
386
|
+
/** @type {number} */ (
|
|
387
|
+
//@ts-expect-error TODO
|
|
388
|
+
this.isAPI ? b.properties[datetimeProperty] : b[datetimeProperty]
|
|
389
|
+
),
|
|
390
|
+
).getTime() - date.getTime(),
|
|
391
|
+
);
|
|
392
|
+
return distanceA - distanceB;
|
|
393
|
+
})[0];
|
|
311
394
|
}
|
|
312
395
|
|
|
313
396
|
async getToolTipProperties() {
|
|
314
397
|
if (!(this.selectedItem instanceof Item)) {
|
|
315
398
|
return [];
|
|
316
399
|
}
|
|
317
|
-
|
|
400
|
+
// get all style links, which could contribute by tooltip config and aggregate them
|
|
401
|
+
const styles = await fetchAllStyles(
|
|
318
402
|
this.selectedItem,
|
|
319
403
|
`${this.#collectionUrl}/${this.selectedItem.id}`,
|
|
320
404
|
);
|
|
321
|
-
|
|
322
|
-
|
|
405
|
+
// get only unique ids to avoid duplicates
|
|
406
|
+
const aggregatedTooltips = [
|
|
407
|
+
...new Map(
|
|
408
|
+
styles
|
|
409
|
+
.flatMap(style => style.tooltip || [])
|
|
410
|
+
.map(entry => [entry.id, entry])
|
|
411
|
+
).values()
|
|
412
|
+
];
|
|
413
|
+
this.#tooltipProperties = aggregatedTooltips ?? [];
|
|
323
414
|
return this.#tooltipProperties;
|
|
324
415
|
}
|
|
325
416
|
|
|
@@ -331,17 +422,15 @@ export class EodashCollection {
|
|
|
331
422
|
*/
|
|
332
423
|
async updateLayerJson(datetime, layer, map) {
|
|
333
424
|
await this.fetchCollection();
|
|
334
|
-
const datetimeProperty = getDatetimeProperty(
|
|
425
|
+
const datetimeProperty = getDatetimeProperty(
|
|
426
|
+
await this.getItems(true, true),
|
|
427
|
+
);
|
|
335
428
|
if (!datetimeProperty) {
|
|
336
429
|
console.warn("[eodash] no datetime property found in collection");
|
|
337
430
|
return;
|
|
338
431
|
}
|
|
339
432
|
// get the link of the specified date
|
|
340
|
-
const specifiedLink = this.
|
|
341
|
-
(item) =>
|
|
342
|
-
typeof item[datetimeProperty] === "string" &&
|
|
343
|
-
new Date(item[datetimeProperty]).toISOString() === datetime,
|
|
344
|
-
);
|
|
433
|
+
const specifiedLink = await this.getItem(new Date(datetime));
|
|
345
434
|
|
|
346
435
|
if (!specifiedLink) {
|
|
347
436
|
console.warn(
|
|
@@ -350,9 +439,22 @@ export class EodashCollection {
|
|
|
350
439
|
);
|
|
351
440
|
return;
|
|
352
441
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
442
|
+
/** @type {Record<string, any>[]} */
|
|
443
|
+
let newLayers = [];
|
|
444
|
+
if (isSTACItem(specifiedLink)) {
|
|
445
|
+
// if specifiedLink is an item, we create layers from it
|
|
446
|
+
newLayers = await this.buildJsonArray(
|
|
447
|
+
specifiedLink,
|
|
448
|
+
this.#collectionUrl + `/items/${specifiedLink.id}`,
|
|
449
|
+
this.#collectionStac?.title || this.#collectionStac?.id || "",
|
|
450
|
+
this.#collectionStac?.endpointtype === "GeoDB" ||
|
|
451
|
+
!!this.#collectionStac?.locations,
|
|
452
|
+
datetime,
|
|
453
|
+
);
|
|
454
|
+
} else {
|
|
455
|
+
// create json layers from the item
|
|
456
|
+
newLayers = await this.createLayersJson(specifiedLink);
|
|
457
|
+
}
|
|
356
458
|
|
|
357
459
|
let currentLayers = getLayers();
|
|
358
460
|
if (map === "second") {
|
|
@@ -391,10 +493,10 @@ export class EodashCollection {
|
|
|
391
493
|
);
|
|
392
494
|
|
|
393
495
|
return [
|
|
496
|
+
//@ts-expect-error indicator instead of item
|
|
394
497
|
...(await createLayersFromLinks(
|
|
395
498
|
indicator?.id ?? "",
|
|
396
499
|
indicator?.title || indicator.id,
|
|
397
|
-
//@ts-expect-error indicator instead of item
|
|
398
500
|
indicator,
|
|
399
501
|
)),
|
|
400
502
|
...(await createLayersFromAssets(
|