@eodash/eodash 5.6.1 → 5.7.1
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 +1 -1
- package/core/client/components/EodashOverlay.vue +27 -4
- package/core/client/composables/DefineEodash.js +0 -1
- package/core/client/composables/DefineWidgets.js +3 -1
- package/core/client/composables/index.js +6 -2
- package/core/client/eodashSTAC/EodashCollection.js +79 -45
- package/core/client/eodashSTAC/cql.js +64 -0
- package/core/client/eodashSTAC/createLayers.js +192 -125
- package/core/client/eodashSTAC/helpers.js +423 -97
- package/core/client/eodashSTAC/mosaic.js +416 -0
- package/core/client/plugins/axios.js +31 -1
- package/core/client/store/actions.js +1 -1
- package/core/client/store/stac.js +25 -4
- package/core/client/store/states.js +20 -2
- package/core/client/types.ts +155 -29
- package/core/client/utils/bands-editor/exampleSchema.json +50 -50
- package/core/client/utils/index.js +4 -0
- package/core/client/utils/states.js +10 -0
- package/dist/client/{DashboardLayout-CqMb7OXc.js → DashboardLayout-ePbdvUTE.js} +5 -5
- package/dist/client/{DynamicWebComponent-DqKqTf7l.js → DynamicWebComponent-g5SdRbjY.js} +1 -1
- package/dist/client/{EodashChart-PkUQfH0k.js → EodashChart-ChrkA5oS.js} +7 -6
- package/dist/client/{EodashDatePicker-DLJGdTtX.js → EodashDatePicker-CY1TrsDo.js} +3 -3
- package/dist/client/{EodashItemFilter-Dk8KjFcX.js → EodashItemFilter-DzshHDlS.js} +2 -1
- package/dist/client/{EodashLayerControl-CC1Cogrn.js → EodashLayerControl-DMCeMkSd.js} +70 -22
- package/dist/client/{EodashLayoutSwitcher-5WZYd6rr.js → EodashLayoutSwitcher-iJ8mX1rF.js} +3 -3
- package/dist/client/EodashMapBtns-C7Cr7q5Y.js +592 -0
- package/dist/client/EodashStacInfo-K7-iuXa7.js +169 -0
- package/dist/client/{EodashTools-CGZtTh45.js → EodashTools-BEK7e7JM.js} +4 -4
- package/dist/client/{ExportState-Ce0ZnrX_.js → ExportState-CqIzfMYQ.js} +6 -168
- package/dist/client/{Footer-CnZqEiop.js → Footer-1P0cmBOZ.js} +1 -1
- package/dist/client/{Header-Dr5PBIm8.js → Header-CkkBaBNh.js} +2 -2
- package/dist/client/MobileLayout-BPf49kDU.js +118 -0
- package/dist/client/{PopUp-DjvE_71e.js → PopUp-DPZq5SWI.js} +4 -168
- package/dist/client/{ProcessList-kf3olI7W.js → ProcessList-DuI6WpS1.js} +5 -5
- package/dist/client/VDivider-Bj9LG_JV.js +168 -0
- package/dist/client/{VImg-Bj6uWt6j.js → VImg-Ddv5OyMz.js} +2 -2
- package/dist/client/{VMain-Cm0UmKGi.js → VMain-7yqk_qC3.js} +1 -1
- package/dist/client/{VTooltip-DbBu-ky3.js → VTooltip-2hAJyEoa.js} +2 -2
- package/dist/client/{WidgetsContainer-CfLnd44U.js → WidgetsContainer-2DOrlwCB.js} +1 -1
- package/dist/client/{asWebComponent-DfULAbpq.js → asWebComponent-BlFN2lkB.js} +493 -335
- package/dist/client/{async-CIbKXEEe.js → async-B2H8ZwUK.js} +21 -10
- package/dist/client/create-layers-config-u_vn5hPk.js +182 -0
- package/dist/client/dialog-transition-BrMkMiNa.js +170 -0
- package/dist/client/eo-dash.js +1 -1
- package/dist/client/{forwardRefs-yj3VWOK5.js → forwardRefs-DAlror6d.js} +8 -87
- package/dist/client/{handling-s8xt2JwF.js → handling-B6I1V5eG.js} +123 -85
- package/dist/client/{helpers-DAVGYl_f.js → helpers-CBqIUSXJ.js} +3034 -1649
- package/dist/client/index-BWq1ZKaV.js +3168 -0
- package/dist/client/{index-CYz6dT7K.js → index-CJ9UI3ln.js} +2 -2
- package/dist/client/index-DXLz4sFR.js +442 -0
- package/dist/client/{index-4TrjfJ32.js → index-DhKU6KqM.js} +230 -231
- package/dist/client/{index-Bu8BMA9q.js → index-DjQlbWbJ.js} +70 -83
- package/dist/client/material-symbols-outlined.woff2 +0 -0
- package/dist/client/material-symbols-rounded.woff2 +0 -0
- package/dist/client/material-symbols-sharp.woff2 +0 -0
- package/dist/client/material-symbols-subset.woff2 +0 -0
- package/dist/client/mosaic-BFYLEwyx.js +455 -0
- package/dist/client/templates.js +250 -119
- package/dist/client/{transition-DaOsiD4u.js → transition-D_W6Wn9v.js} +1 -1
- package/dist/node/cli.js +5 -5
- package/dist/node/types.d.ts +4 -0
- package/dist/types/core/client/composables/DefineEodash.d.ts +1 -1
- package/dist/types/core/client/composables/index.d.ts +1 -3
- package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +62 -31
- package/dist/types/core/client/eodashSTAC/cql.d.ts +15 -0
- package/dist/types/core/client/eodashSTAC/createLayers.d.ts +44 -25
- package/dist/types/core/client/eodashSTAC/helpers.d.ts +78 -18
- package/dist/types/core/client/eodashSTAC/mosaic.d.ts +56 -0
- package/dist/types/core/client/store/stac.d.ts +31 -7
- package/dist/types/core/client/store/states.d.ts +24 -2
- package/dist/types/core/client/types.d.ts +131 -25
- package/dist/types/core/client/utils/states.d.ts +12 -0
- package/dist/types/templates/baseConfig.d.ts +1 -88
- package/dist/types/templates/compare.d.ts +32 -3
- package/dist/types/templates/expert.d.ts +18 -0
- package/dist/types/templates/explore.d.ts +9 -1
- package/dist/types/templates/lite.d.ts +11 -0
- package/dist/types/widgets/EodashChart.vue.d.ts +5 -3
- package/dist/types/widgets/EodashItemCatalog/index.vue.d.ts +129 -2
- package/dist/types/widgets/EodashItemCatalog/methods/filters.d.ts +28 -6
- package/dist/types/widgets/EodashItemCatalog/methods/handlers.d.ts +17 -4
- package/dist/types/widgets/EodashItemCatalog/methods/map.d.ts +16 -4
- package/dist/types/widgets/EodashLayerControl.vue.d.ts +36 -17
- package/dist/types/widgets/EodashMap/EodashMapBtns.vue.d.ts +23 -10
- package/dist/types/widgets/EodashMap/index.vue.d.ts +91 -35
- package/dist/types/widgets/EodashMap/methods/create-layers-config.d.ts +1 -8
- package/dist/types/widgets/EodashMap/methods/index.d.ts +5 -1
- package/dist/types/widgets/EodashMap/methods/use-map-loading.d.ts +1 -0
- package/dist/types/widgets/EodashProcess/index.vue.d.ts +5 -3
- package/dist/types/widgets/EodashProcess/methods/composables.d.ts +1 -1
- package/dist/types/widgets/EodashProcess/methods/handling.d.ts +13 -8
- package/dist/types/widgets/EodashProcess/states.d.ts +1 -1
- package/dist/types/widgets/EodashStacInfo.vue.d.ts +20 -0
- package/dist/types/widgets/EodashTimeSlider/index.vue.d.ts +54 -0
- package/dist/types/widgets/EodashTimeSlider/methods/index.d.ts +34 -0
- package/dist/types/widgets/EodashTimeSlider/types.d.ts +52 -0
- package/dist/types/widgets/EodashTools.vue.d.ts +5 -5
- package/package.json +46 -46
- package/templates/baseConfig.js +36 -6
- package/templates/compare.js +62 -7
- package/templates/expert.js +23 -0
- package/templates/explore.js +11 -5
- package/templates/lite.js +14 -0
- package/widgets/EodashChart.vue +1 -0
- package/widgets/EodashItemCatalog/index.vue +363 -35
- package/widgets/EodashItemCatalog/methods/filters.js +134 -70
- package/widgets/EodashItemCatalog/methods/handlers.js +113 -19
- package/widgets/EodashItemCatalog/methods/map.js +142 -28
- package/widgets/EodashLayerControl.vue +64 -14
- package/widgets/EodashMap/EodashMapBtns.vue +153 -47
- package/widgets/EodashMap/index.vue +101 -105
- package/widgets/EodashMap/methods/btns.js +37 -5
- package/widgets/EodashMap/methods/create-layers-config.js +18 -16
- package/widgets/EodashMap/methods/index.js +89 -8
- package/widgets/EodashMap/methods/use-map-loading.js +52 -0
- package/widgets/EodashProcess/index.vue +2 -1
- package/widgets/EodashProcess/methods/async.js +19 -8
- package/widgets/EodashProcess/methods/composables.js +63 -77
- package/widgets/EodashProcess/methods/custom-endpoints/chart/sentinelhub-endpoint.js +9 -5
- package/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.js +7 -4
- package/widgets/EodashProcess/methods/handling.js +105 -72
- package/widgets/EodashProcess/states.js +1 -1
- package/widgets/EodashStacInfo.vue +64 -2
- package/widgets/EodashTimeSlider/index.vue +208 -0
- package/widgets/EodashTimeSlider/methods/index.js +236 -0
- package/widgets/EodashTimeSlider/types.ts +54 -0
- package/dist/client/EodashMapBtns-BHrSDNoC.js +0 -435
- package/dist/client/EodashStacInfo-B90wobPc.js +0 -107
- package/dist/client/EodashTimeSlider-5vm7F3ju.js +0 -53
- package/dist/client/MobileLayout-DyMjaeif.js +0 -118
- package/dist/client/index-CugS__t5.js +0 -570
- package/dist/types/widgets/EodashTimeSlider.vue.d.ts +0 -15
- package/widgets/EodashTimeSlider.vue +0 -40
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
import { useOnLayersUpdate } from "@/composables";
|
|
2
|
-
import { mapEl } from "@/store/states";
|
|
3
2
|
import { onMounted, onUnmounted } from "vue";
|
|
3
|
+
import { createOnSelectHandler } from "./handlers";
|
|
4
|
+
import { tooltipAdapter } from "@/store/states";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
*
|
|
7
8
|
* @param {import("@/types").GeoJsonFeature[]} features
|
|
9
|
+
* @param {import("vue").Ref<import("@eox/map").EOxMap | null>} mapElement
|
|
10
|
+
* @param {string[] | undefined} hoverProperties
|
|
11
|
+
* @param {object} [stacItemsStyle]
|
|
12
|
+
* @param {object} [stacItemsInteractionStyle]
|
|
8
13
|
*/
|
|
9
|
-
export function renderItemsFeatures(
|
|
14
|
+
export function renderItemsFeatures(
|
|
15
|
+
features,
|
|
16
|
+
mapElement,
|
|
17
|
+
hoverProperties,
|
|
18
|
+
stacItemsStyle,
|
|
19
|
+
stacItemsInteractionStyle,
|
|
20
|
+
) {
|
|
21
|
+
const currentMap = mapElement.value;
|
|
10
22
|
let analysisLayers =
|
|
11
23
|
/** @type {import("@eox/map/src/layers").EOxLayerTypeGroup} */ (
|
|
12
|
-
|
|
24
|
+
currentMap?.layers?.find((l) => l.properties?.id === "AnalysisGroup")
|
|
13
25
|
);
|
|
14
|
-
if (!
|
|
26
|
+
if (!currentMap || !features) {
|
|
15
27
|
return;
|
|
16
28
|
}
|
|
17
29
|
if (!analysisLayers) {
|
|
@@ -23,9 +35,9 @@ export function renderItemsFeatures(features) {
|
|
|
23
35
|
},
|
|
24
36
|
layers: [],
|
|
25
37
|
};
|
|
26
|
-
|
|
38
|
+
currentMap.layers = [...currentMap.layers, analysisLayers];
|
|
27
39
|
}
|
|
28
|
-
|
|
40
|
+
/** @type {import("@eox/map/src/layers").EOxLayerType<"Vector","Vector">} */
|
|
29
41
|
const stacItemsLayer = {
|
|
30
42
|
type: "Vector",
|
|
31
43
|
properties: {
|
|
@@ -34,14 +46,16 @@ export function renderItemsFeatures(features) {
|
|
|
34
46
|
},
|
|
35
47
|
source: {
|
|
36
48
|
type: "Vector",
|
|
49
|
+
//@ts-expect-error todo
|
|
37
50
|
url:
|
|
38
51
|
"data:application/geo+json," +
|
|
39
52
|
encodeURIComponent(
|
|
40
53
|
JSON.stringify({ type: "FeatureCollection", features }),
|
|
41
54
|
),
|
|
42
55
|
format: "GeoJSON",
|
|
56
|
+
projection: "EPSG:4326",
|
|
43
57
|
},
|
|
44
|
-
style: {
|
|
58
|
+
style: stacItemsStyle || {
|
|
45
59
|
"fill-color": "transparent",
|
|
46
60
|
"stroke-color": "#003170",
|
|
47
61
|
},
|
|
@@ -49,35 +63,47 @@ export function renderItemsFeatures(features) {
|
|
|
49
63
|
{
|
|
50
64
|
type: "select",
|
|
51
65
|
options: {
|
|
52
|
-
id: "stac-
|
|
66
|
+
id: "stac-item-hover",
|
|
53
67
|
condition: "pointermove",
|
|
54
|
-
|
|
68
|
+
tooltip: hoverProperties?.length,
|
|
69
|
+
style: stacItemsInteractionStyle || {
|
|
55
70
|
"stroke-color": "white",
|
|
56
71
|
"stroke-width": 3,
|
|
57
72
|
},
|
|
58
73
|
},
|
|
59
74
|
},
|
|
75
|
+
{
|
|
76
|
+
type: "select",
|
|
77
|
+
options: {
|
|
78
|
+
id: "stac-items",
|
|
79
|
+
condition: "click",
|
|
80
|
+
tooltip: false,
|
|
81
|
+
style: stacItemsInteractionStyle || {
|
|
82
|
+
"stroke-color": "#003047",
|
|
83
|
+
"stroke-width": 3.2,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
60
87
|
],
|
|
61
88
|
};
|
|
62
89
|
const exists = analysisLayers.layers.some(
|
|
63
|
-
(l) => l.properties?.id ===
|
|
90
|
+
(l) => l.properties?.id === stacItemsLayer.properties?.id,
|
|
64
91
|
);
|
|
65
92
|
if (exists) {
|
|
66
|
-
|
|
67
|
-
mapEl.value.addOrUpdateLayer(stacItemsLayer);
|
|
93
|
+
currentMap.addOrUpdateLayer(stacItemsLayer);
|
|
68
94
|
return;
|
|
69
95
|
} else {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
mapEl.value.layers = [...mapEl.value.layers];
|
|
96
|
+
analysisLayers.layers.unshift(stacItemsLayer);
|
|
97
|
+
currentMap.layers = [...currentMap.layers];
|
|
73
98
|
}
|
|
74
99
|
}
|
|
75
100
|
|
|
76
101
|
/**
|
|
77
102
|
* @param {import("vue").Ref<any>} itemFilter
|
|
78
103
|
* @param {boolean} bboxFilter
|
|
104
|
+
* @param {import("vue").Ref<import("@eox/map").EOxMap | null>} mapElement
|
|
79
105
|
*/
|
|
80
|
-
export const useSearchOnMapMove = (itemFilter, bboxFilter) => {
|
|
106
|
+
export const useSearchOnMapMove = (itemFilter, bboxFilter, mapElement) => {
|
|
81
107
|
if (!bboxFilter) {
|
|
82
108
|
return;
|
|
83
109
|
}
|
|
@@ -86,58 +112,146 @@ export const useSearchOnMapMove = (itemFilter, bboxFilter) => {
|
|
|
86
112
|
const handler = () => {
|
|
87
113
|
clearTimeout(timeout);
|
|
88
114
|
timeout = setTimeout(() => {
|
|
115
|
+
if (mapElement.value?.projection == "globe") {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
89
118
|
itemFilter.value?.search();
|
|
90
|
-
},
|
|
119
|
+
}, 500);
|
|
91
120
|
};
|
|
92
121
|
onMounted(() => {
|
|
93
|
-
|
|
122
|
+
mapElement.value?.map.on("moveend", handler);
|
|
94
123
|
});
|
|
95
124
|
onUnmounted(() => {
|
|
96
|
-
|
|
125
|
+
mapElement.value?.map.un("moveend", handler);
|
|
97
126
|
});
|
|
98
127
|
};
|
|
99
128
|
/**
|
|
100
129
|
*
|
|
101
130
|
* @param {import("vue").Ref<import("@/types").GeoJsonFeature[]>} currentItems
|
|
131
|
+
* @param {import("vue").Ref<import("@eox/map").EOxMap | null>} mapElement
|
|
132
|
+
* @param {string[] | undefined} hoverProperties
|
|
133
|
+
* @param {object} [stacItemsStyle]
|
|
134
|
+
* @param {object} [stacItemsInteractionStyle]
|
|
102
135
|
*/
|
|
103
|
-
export const useRenderItemsFeatures = (
|
|
136
|
+
export const useRenderItemsFeatures = (
|
|
137
|
+
currentItems,
|
|
138
|
+
mapElement,
|
|
139
|
+
hoverProperties,
|
|
140
|
+
stacItemsStyle,
|
|
141
|
+
stacItemsInteractionStyle,
|
|
142
|
+
) => {
|
|
104
143
|
onMounted(() => {
|
|
105
|
-
renderItemsFeatures(
|
|
144
|
+
renderItemsFeatures(
|
|
145
|
+
currentItems.value,
|
|
146
|
+
mapElement,
|
|
147
|
+
hoverProperties,
|
|
148
|
+
stacItemsStyle,
|
|
149
|
+
stacItemsInteractionStyle,
|
|
150
|
+
);
|
|
106
151
|
});
|
|
107
152
|
|
|
108
153
|
useOnLayersUpdate(() => {
|
|
109
154
|
// consider cases where this is not needed
|
|
110
|
-
renderItemsFeatures(
|
|
155
|
+
renderItemsFeatures(
|
|
156
|
+
currentItems.value,
|
|
157
|
+
mapElement,
|
|
158
|
+
hoverProperties,
|
|
159
|
+
stacItemsStyle,
|
|
160
|
+
stacItemsInteractionStyle,
|
|
161
|
+
);
|
|
111
162
|
});
|
|
112
163
|
};
|
|
164
|
+
/**
|
|
165
|
+
* Registers a tooltip adapter that displays item properties when hovering over map features.
|
|
166
|
+
* @param {string[]} [hoverProperties]
|
|
167
|
+
*/
|
|
168
|
+
export function useHoverTooltip(hoverProperties) {
|
|
169
|
+
/**
|
|
170
|
+
* @param {*} val
|
|
171
|
+
*/
|
|
172
|
+
const formatValue = (val) => {
|
|
173
|
+
if (typeof val === "number") {
|
|
174
|
+
return val.toFixed(0);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (typeof val === "string") {
|
|
178
|
+
// Attempt to parse as date if string looks like ISO date
|
|
179
|
+
if (val.length > 9 && /\d{4}-\d{2}-\d{2}/.test(val)) {
|
|
180
|
+
const timestamp = Date.parse(val);
|
|
181
|
+
if (!isNaN(timestamp)) {
|
|
182
|
+
return new Date(timestamp).toUTCString();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return val;
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* @param {string} key
|
|
190
|
+
*/
|
|
191
|
+
const formatKey = (key) => {
|
|
192
|
+
let formattedKey = key;
|
|
193
|
+
if (key.includes(":")) {
|
|
194
|
+
formattedKey = key.split(":")[1];
|
|
195
|
+
}
|
|
196
|
+
return formattedKey
|
|
197
|
+
.replace(/_/g, " ")
|
|
198
|
+
.replace(/\b\w/g, (c) => c.toUpperCase());
|
|
199
|
+
};
|
|
200
|
+
onMounted(() => {
|
|
201
|
+
tooltipAdapter.value = ({ key, value }) => {
|
|
202
|
+
if (hoverProperties && hoverProperties.includes(key)) {
|
|
203
|
+
return { key: formatKey(key), value: formatValue(value) };
|
|
204
|
+
}
|
|
205
|
+
return undefined;
|
|
206
|
+
};
|
|
207
|
+
});
|
|
208
|
+
onUnmounted(() => {
|
|
209
|
+
tooltipAdapter.value = null;
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
|
|
113
213
|
/**
|
|
114
214
|
*
|
|
115
215
|
* @param {import("vue").Ref<any>} itemfilterEl
|
|
216
|
+
* @param {ReturnType< typeof import("@/store/stac").useSTAcStore>} store
|
|
217
|
+
* @param {import("vue").Ref<import("@eox/map").EOxMap | null>} mapElement
|
|
218
|
+
* @param {boolean} enableCompare
|
|
116
219
|
*/
|
|
117
|
-
export function
|
|
220
|
+
export function useRenderOnFeatureClick(
|
|
221
|
+
itemfilterEl,
|
|
222
|
+
store,
|
|
223
|
+
mapElement,
|
|
224
|
+
enableCompare,
|
|
225
|
+
) {
|
|
226
|
+
const onSelectItem = createOnSelectHandler(store, enableCompare, mapElement);
|
|
118
227
|
/**
|
|
119
228
|
*
|
|
120
229
|
* @param {CustomEvent} evt
|
|
121
230
|
*/
|
|
122
231
|
const handler = (evt) => {
|
|
232
|
+
if (evt.detail.originalEvent.type !== "click") {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
123
235
|
const itemId = evt.detail?.feature?.getId();
|
|
124
236
|
if (!itemId) {
|
|
125
237
|
return;
|
|
126
238
|
}
|
|
127
|
-
const item = itemfilterEl.value.
|
|
239
|
+
const item = itemfilterEl.value.results?.find(
|
|
128
240
|
//@ts-expect-error todo
|
|
129
|
-
(r) => r
|
|
241
|
+
(r) => r?.id === itemId,
|
|
130
242
|
);
|
|
243
|
+
|
|
131
244
|
if (item) {
|
|
132
|
-
|
|
245
|
+
onSelectItem(new CustomEvent("select", { detail: item }));
|
|
133
246
|
}
|
|
134
247
|
};
|
|
248
|
+
|
|
135
249
|
onMounted(() => {
|
|
136
250
|
//@ts-expect-error todo
|
|
137
|
-
|
|
251
|
+
mapElement.value?.addEventListener("select", handler);
|
|
138
252
|
});
|
|
139
253
|
onUnmounted(() => {
|
|
140
254
|
//@ts-expect-error todo
|
|
141
|
-
|
|
255
|
+
mapElement.value?.removeEventListener("select", handler);
|
|
142
256
|
});
|
|
143
257
|
}
|
|
@@ -5,26 +5,31 @@
|
|
|
5
5
|
:key="mapElement"
|
|
6
6
|
v-bind="config"
|
|
7
7
|
:for="mapElement"
|
|
8
|
+
.showLayerZoomState="true"
|
|
8
9
|
.customEditorInterfaces="bandsEditorInterface"
|
|
9
10
|
@datetime:updated="debouncedHandleDateTime"
|
|
10
11
|
toolsAsList="true"
|
|
11
12
|
ref="eoxLayercontrol"
|
|
12
13
|
@layerConfig:change="onLayerConfigChange"
|
|
13
14
|
>
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
<span
|
|
16
|
+
slot="layerstitle"
|
|
17
|
+
class="d-flex justify-space-between ma-2 pa-2 flex-shrink-0"
|
|
18
|
+
>
|
|
19
|
+
<h4 v-if="title">{{ title }}</h4>
|
|
20
|
+
<EodashLayoutSwitcher
|
|
21
|
+
v-if="enableLayoutSwitcher"
|
|
22
|
+
:target="layoutTarget"
|
|
23
|
+
:icon="layoutIcon"
|
|
24
|
+
/>
|
|
25
|
+
</span>
|
|
21
26
|
</eox-layercontrol>
|
|
22
27
|
</span>
|
|
23
28
|
</template>
|
|
24
29
|
<script setup>
|
|
25
30
|
import "color-legend-element";
|
|
26
31
|
import "@eox/timecontrol";
|
|
27
|
-
import { computed, ref } from "vue";
|
|
32
|
+
import { computed, ref, watch } from "vue";
|
|
28
33
|
import { mapEl, mapCompareEl } from "@/store/states";
|
|
29
34
|
import { getColFromLayer } from "@/eodashSTAC/helpers";
|
|
30
35
|
import {
|
|
@@ -33,9 +38,13 @@ import {
|
|
|
33
38
|
layerControlFormValue,
|
|
34
39
|
layerControlFormValueCompare,
|
|
35
40
|
} from "@/utils/states";
|
|
41
|
+
import { updateGeoZarrBands } from "@/eodashSTAC/helpers";
|
|
36
42
|
import { storeToRefs } from "pinia";
|
|
37
43
|
import { useSTAcStore } from "@/store/stac";
|
|
38
44
|
import { bandsEditorInterface } from "@/utils/bands-editor";
|
|
45
|
+
import EodashLayoutSwitcher from "^/EodashLayoutSwitcher.vue";
|
|
46
|
+
import { mdiViewDashboard } from "@mdi/js";
|
|
47
|
+
import { useEmitLayersUpdate } from "@/composables";
|
|
39
48
|
|
|
40
49
|
if (!customElements.get("eox-layercontrol")) {
|
|
41
50
|
await import("@eox/layercontrol");
|
|
@@ -45,22 +54,39 @@ if (!customElements.get("eox-jsonform")) {
|
|
|
45
54
|
}
|
|
46
55
|
|
|
47
56
|
const props = defineProps({
|
|
57
|
+
/** Which map instance this control is bound to. Use `"second"` in a compare-mode layout. */
|
|
48
58
|
map: {
|
|
49
59
|
/** @type {import("vue").PropType<"first" | "second">} */
|
|
50
60
|
//@ts-expect-error todo
|
|
51
61
|
type: String,
|
|
52
62
|
default: "first",
|
|
53
63
|
},
|
|
64
|
+
/** Tool tabs shown inside `eox-layercontrol`. Remove entries to hide individual tabs. */
|
|
54
65
|
tools: {
|
|
55
|
-
type: Array,
|
|
66
|
+
type: /** @type {import("vue").PropType<string[]>} */ (Array),
|
|
56
67
|
default: () => ["datetime", "info", "config", "legend", "opacity"],
|
|
57
68
|
},
|
|
69
|
+
/** Heading rendered above the layer list. Set to `false` to hide it. */
|
|
58
70
|
title: {
|
|
59
|
-
type:
|
|
71
|
+
type: /** @type {import("vue").PropType<string | false>} */ ([
|
|
72
|
+
String,
|
|
73
|
+
Boolean,
|
|
74
|
+
]),
|
|
60
75
|
default: "Layers",
|
|
61
76
|
},
|
|
77
|
+
/** CSS custom-property overrides forwarded to the underlying `eox-layercontrol` element via its `style` attribute. */
|
|
62
78
|
cssVars: {
|
|
63
|
-
type:
|
|
79
|
+
type: /** @type {import("vue").PropType<Record<string, string>>} */ (
|
|
80
|
+
Object
|
|
81
|
+
),
|
|
82
|
+
default: {},
|
|
83
|
+
},
|
|
84
|
+
layoutIcon: {
|
|
85
|
+
type: String,
|
|
86
|
+
default: mdiViewDashboard,
|
|
87
|
+
},
|
|
88
|
+
layoutTarget: {
|
|
89
|
+
type: String,
|
|
64
90
|
},
|
|
65
91
|
});
|
|
66
92
|
|
|
@@ -69,7 +95,12 @@ const config = {
|
|
|
69
95
|
style: props.cssVars,
|
|
70
96
|
};
|
|
71
97
|
|
|
98
|
+
const enableLayoutSwitcher = computed(
|
|
99
|
+
() => !!props.layoutTarget && !!props.layoutIcon,
|
|
100
|
+
);
|
|
101
|
+
|
|
72
102
|
const { selectedCompareStac, selectedStac } = storeToRefs(useSTAcStore());
|
|
103
|
+
|
|
73
104
|
const showControls = computed(() => {
|
|
74
105
|
if (props.map === "second") {
|
|
75
106
|
return mapCompareEl.value !== null && selectedCompareStac.value !== null;
|
|
@@ -81,12 +112,23 @@ const eodashCols =
|
|
|
81
112
|
props.map === "second" ? eodashCompareCollections : eodashCollections;
|
|
82
113
|
const mapElement = props.map === "second" ? mapCompareEl : mapEl;
|
|
83
114
|
|
|
84
|
-
/** @type { import("vue").Ref<
|
|
115
|
+
/** @type { import("vue").Ref<import("@eox/layercontrol").EOxLayerControl | null>} */
|
|
85
116
|
const eoxLayercontrol = ref(null);
|
|
86
117
|
|
|
118
|
+
// eox-timecontrol re-fires datetime:updated after layer reassignment;
|
|
119
|
+
// dedupe by (collectionId, datetime)
|
|
120
|
+
const processedDatetimes = new Map();
|
|
121
|
+
watch([selectedStac, selectedCompareStac], () => processedDatetimes.clear());
|
|
122
|
+
|
|
87
123
|
/** @param {CustomEvent<{layer:import('ol/layer').Layer; datetime:string;}>} evt */
|
|
88
124
|
const handleDatetimeUpdate = async (evt) => {
|
|
89
125
|
const { layer, datetime } = evt.detail;
|
|
126
|
+
const collectionId = layer.get("id")?.split(";:;")[0] ?? layer.get("id");
|
|
127
|
+
if (processedDatetimes.get(collectionId) === datetime) return;
|
|
128
|
+
// First event per collection is eox-timecontrol's mount echo.
|
|
129
|
+
const isFirstEvent = !processedDatetimes.has(collectionId);
|
|
130
|
+
processedDatetimes.set(collectionId, datetime);
|
|
131
|
+
if (isFirstEvent) return;
|
|
90
132
|
|
|
91
133
|
const ec = await getColFromLayer(eodashCols, layer);
|
|
92
134
|
|
|
@@ -97,9 +139,10 @@ const handleDatetimeUpdate = async (evt) => {
|
|
|
97
139
|
updatedLayers = await ec.updateLayerJson(
|
|
98
140
|
datetime,
|
|
99
141
|
layer.get("id"),
|
|
100
|
-
|
|
142
|
+
mapElement.value?.layers ?? [],
|
|
101
143
|
);
|
|
102
144
|
}
|
|
145
|
+
if (!updatedLayers?.length) return;
|
|
103
146
|
/** @type {Record<String,any>[] | undefined} */
|
|
104
147
|
const dataLayers = updatedLayers?.find(
|
|
105
148
|
(l) => l?.properties?.id === "AnalysisGroup",
|
|
@@ -111,9 +154,14 @@ const handleDatetimeUpdate = async (evt) => {
|
|
|
111
154
|
dl.properties.layerControlExpand = true;
|
|
112
155
|
dl.properties.layerControlToolsExpand = true;
|
|
113
156
|
});
|
|
114
|
-
// assign layers to the map
|
|
115
157
|
/** @type {HTMLElement & Record<string,any>} */
|
|
116
158
|
(mapElement.value).layers = updatedLayers;
|
|
159
|
+
// Emit after layer assignment so listeners resolve against the new layer.
|
|
160
|
+
await useEmitLayersUpdate(
|
|
161
|
+
props.map === "second" ? "compareLayertime:updated" : "layertime:updated",
|
|
162
|
+
mapElement.value,
|
|
163
|
+
updatedLayers,
|
|
164
|
+
);
|
|
117
165
|
}
|
|
118
166
|
};
|
|
119
167
|
|
|
@@ -136,6 +184,8 @@ const debouncedHandleDateTime = (evt) => {
|
|
|
136
184
|
* @param {Event & {detail:{layer:import("ol/layer").Layer;jsonformValue:Record<string,any>}}} evt
|
|
137
185
|
*/
|
|
138
186
|
const onLayerConfigChange = (evt) => {
|
|
187
|
+
updateGeoZarrBands(evt.detail.layer, evt.detail.jsonformValue);
|
|
188
|
+
|
|
139
189
|
if (props.map === "second") {
|
|
140
190
|
layerControlFormValueCompare.value = evt.detail.jsonformValue;
|
|
141
191
|
} else {
|