@eodash/eodash 5.6.0 → 5.7.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 +1 -1
- package/core/client/composables/index.js +6 -2
- package/core/client/eodashSTAC/EodashCollection.js +5 -21
- package/core/client/eodashSTAC/createLayers.js +23 -9
- package/core/client/eodashSTAC/helpers.js +37 -4
- package/core/client/types.ts +8 -1
- package/core/client/utils/index.js +4 -0
- package/dist/client/{DashboardLayout-DkKDhfgH.js → DashboardLayout-kRsmsNW5.js} +5 -5
- package/dist/client/{DynamicWebComponent-BrpkA-e3.js → DynamicWebComponent-CnKhYo0K.js} +1 -1
- package/dist/client/{EodashChart-p7_1FRlF.js → EodashChart-CLDqE93C.js} +4 -4
- package/dist/client/{EodashDatePicker-HK0Jl7wQ.js → EodashDatePicker-CMPDT-ce.js} +3 -3
- package/dist/client/{EodashItemFilter-BYQDA78B.js → EodashItemFilter-BpdA8QQa.js} +1 -1
- package/dist/client/{EodashLayerControl-NcrNncGn.js → EodashLayerControl-BHpDA4_0.js} +25 -7
- package/dist/client/{EodashLayoutSwitcher-CC2Znd0I.js → EodashLayoutSwitcher-B1fRUt7G.js} +3 -3
- package/dist/client/EodashMapBtns-Cpned0tc.js +478 -0
- package/dist/client/{EodashStacInfo-BA-0UjvT.js → EodashStacInfo-BQspAHKH.js} +31 -31
- package/dist/client/{EodashTools-CWmoH0g_.js → EodashTools-1zHz26gv.js} +4 -4
- package/dist/client/{ExportState-CfAfX4RN.js → ExportState-DbOm8hBI.js} +4 -4
- package/dist/client/{Footer-DLGxQTZt.js → Footer-BKg-VVkj.js} +1 -1
- package/dist/client/{Header-eyEyyzD6.js → Header-DCrwCvmY.js} +2 -2
- package/dist/client/MobileLayout-vWSHpluo.js +118 -0
- package/dist/client/{PopUp-WNs6Io2N.js → PopUp-9uimfK49.js} +2 -2
- package/dist/client/{ProcessList-RzVqbd5E.js → ProcessList-CTTIZa06.js} +4 -4
- package/dist/client/{VImg-GKUTFoV-.js → VImg-CrmB76ZY.js} +2 -2
- package/dist/client/{VMain-D7_72mHr.js → VMain-OKZNpcEG.js} +1 -1
- package/dist/client/{VTooltip-BbmvtvYw.js → VTooltip-CJw2FyWk.js} +2 -2
- package/dist/client/{WidgetsContainer-Dw5d7SOW.js → WidgetsContainer-BaWOnE5R.js} +1 -1
- package/dist/client/{asWebComponent-DDt7V3Bl.js → asWebComponent-BHWpMuE3.js} +47 -35
- package/dist/client/{async-CT3KEV52.js → async-DSKj6g1f.js} +29 -28
- package/dist/client/create-layers-config-CBoYedqB.js +182 -0
- package/dist/client/eo-dash.js +1 -1
- package/dist/client/{forwardRefs-CVzxyoSq.js → forwardRefs-DH51zPUr.js} +2 -2
- package/dist/client/{handling-C285F_Mq.js → handling-BrcDDlgS.js} +452 -114
- package/dist/client/{helpers-CZFH0EVN.js → helpers-DjZVl_WF.js} +2277 -1504
- package/dist/client/{index-B-m7V3Kb.js → index-1JKE68n3.js} +49 -194
- package/dist/client/{index-CF3ZMzTz.js → index-5Jhsa8Xe.js} +3 -3
- package/dist/client/index-CSG_JoOA.js +436 -0
- package/dist/client/{index-DgOXD7wd.js → index-CUjl-ZsI.js} +2 -2
- package/dist/client/{index-B_6H-N14.js → index-Cu3-13Xg.js} +84 -90
- 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/templates.js +1 -1
- package/dist/client/{transition-C2gnrWg0.js → transition-OHcz5Qq1.js} +1 -1
- package/dist/node/cli.js +1 -1
- package/dist/types/core/client/composables/index.d.ts +1 -3
- package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +6 -7
- package/dist/types/core/client/eodashSTAC/createLayers.d.ts +3 -3
- package/dist/types/core/client/eodashSTAC/helpers.d.ts +1 -0
- package/dist/types/core/client/types.d.ts +8 -1
- package/dist/types/templates/baseConfig.d.ts +12 -0
- package/dist/types/widgets/EodashLayerControl.vue.d.ts +1 -1
- package/dist/types/widgets/EodashMap/EodashMapBtns.vue.d.ts +9 -0
- package/dist/types/widgets/EodashMap/index.vue.d.ts +7 -0
- package/dist/types/widgets/EodashMap/methods/create-layers-config.d.ts +1 -8
- package/dist/types/widgets/EodashProcess/methods/composables.d.ts +2 -3
- package/dist/types/widgets/EodashProcess/methods/handling.d.ts +15 -10
- package/dist/types/widgets/EodashProcess/methods/outputs.d.ts +3 -1
- package/dist/types/widgets/EodashProcess/methods/template-helpers.d.ts +99 -0
- package/dist/types/widgets/EodashProcess/methods/utils.d.ts +1 -6
- package/dist/types/widgets/EodashProcess/types.d.ts +1 -0
- package/dist/types/widgets/EodashStacInfo.vue.d.ts +10 -10
- package/dist/types/widgets/EodashTimeSlider/index.vue.d.ts +34 -0
- package/dist/types/widgets/EodashTimeSlider/methods/index.d.ts +39 -0
- package/dist/types/widgets/EodashTimeSlider/types.d.ts +62 -0
- package/package.json +32 -32
- package/widgets/EodashLayerControl.vue +22 -3
- package/widgets/EodashMap/EodashMapBtns.vue +46 -1
- package/widgets/EodashMap/index.vue +17 -5
- package/widgets/EodashMap/methods/create-layers-config.js +2 -0
- package/widgets/EodashMap/methods/index.js +23 -5
- package/widgets/EodashProcess/index.vue +17 -13
- package/widgets/EodashProcess/methods/async.js +19 -8
- package/widgets/EodashProcess/methods/composables.js +63 -74
- 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 +125 -76
- package/widgets/EodashProcess/methods/outputs.js +74 -29
- package/widgets/EodashProcess/methods/template-helpers.js +246 -0
- package/widgets/EodashProcess/methods/utils.js +7 -17
- package/widgets/EodashProcess/types.ts +1 -0
- package/widgets/EodashStacInfo.vue +30 -30
- package/widgets/EodashTimeSlider/index.vue +152 -0
- package/widgets/EodashTimeSlider/methods/index.js +279 -0
- package/widgets/EodashTimeSlider/types.ts +64 -0
- package/dist/client/EodashMapBtns-BJSh7qT-.js +0 -435
- package/dist/client/EodashTimeSlider-GDv1hbw7.js +0 -53
- package/dist/client/MobileLayout-RzLOyXwL.js +0 -118
- package/dist/types/widgets/EodashTimeSlider.vue.d.ts +0 -15
- package/widgets/EodashTimeSlider.vue +0 -40
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { useTemplateRef, ref, computed, onMounted, openBlock, createElementBlock, unref, createElementVNode, createCommentVNode } from 'vue';
|
|
2
|
+
import { a0 as removeLayers, Q as sanitizeBbox, d as axios, i as mapEl, v as getLayers, A as datetime } from './helpers-DjZVl_WF.js';
|
|
3
|
+
import { L as eodashCollections, _ as _export_sfc, H as useSTAcStore } from './asWebComponent-BHWpMuE3.js';
|
|
4
|
+
import '@eox/timecontrol';
|
|
5
|
+
import '@eox/itemfilter';
|
|
6
|
+
import { storeToRefs } from 'pinia';
|
|
7
|
+
import { c as createLayersConfig } from './create-layers-config-CBoYedqB.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} stacEndpoint
|
|
11
|
+
* @param {[string, string]} selectedRange
|
|
12
|
+
* @param {import("../types").TimelineExportEventDetail["selectedRangeItems"]} selectedRangeItems
|
|
13
|
+
* @param {import("vue").Ref<import("stac-ts").StacCollection|null>} selectedStac
|
|
14
|
+
* @param {Record<string, import("../types").Filter>} filters
|
|
15
|
+
*/
|
|
16
|
+
async function createAnimationLayers(
|
|
17
|
+
stacEndpoint,
|
|
18
|
+
selectedRange,
|
|
19
|
+
selectedRangeItems,
|
|
20
|
+
selectedStac,
|
|
21
|
+
filters,
|
|
22
|
+
) {
|
|
23
|
+
if (eodashCollections[0].isAPI) {
|
|
24
|
+
return await createAPILayers(
|
|
25
|
+
stacEndpoint,
|
|
26
|
+
{ min: selectedRange[0], max: selectedRange[1] },
|
|
27
|
+
mapEl.value?.lonLatExtent,
|
|
28
|
+
selectedStac,
|
|
29
|
+
filters,
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
const { collections: hiddenCollections, layers: hiddenLayers } =
|
|
33
|
+
getHiddenLayers([...getLayers()]);
|
|
34
|
+
|
|
35
|
+
return await Promise.all(
|
|
36
|
+
Object.values(selectedRangeItems).flatMap(async (itemSet) => {
|
|
37
|
+
/** @type {Array<{ layers: Record<string, any>[]; date: string }>} */
|
|
38
|
+
const mapLayersArr = [];
|
|
39
|
+
for (const dateItem of itemSet) {
|
|
40
|
+
await createLayersConfig(
|
|
41
|
+
selectedStac.value,
|
|
42
|
+
eodashCollections.filter(
|
|
43
|
+
(collection) =>
|
|
44
|
+
!hiddenCollections.includes(collection.collectionStac?.id ?? ""),
|
|
45
|
+
),
|
|
46
|
+
dateItem.originalDate,
|
|
47
|
+
).then((layers) => {
|
|
48
|
+
//@ts-expect-error createLayersConfig is not typed strictly
|
|
49
|
+
layers = removeLayers(layers, hiddenLayers);
|
|
50
|
+
//@ts-expect-error createLayersConfig is not typed strictly
|
|
51
|
+
layers = restoreLayersVisibility(layers);
|
|
52
|
+
layers = anonimizeLayersCORS(layers);
|
|
53
|
+
mapLayersArr.push({
|
|
54
|
+
layers,
|
|
55
|
+
date: dateItem.originalDate,
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
return mapLayersArr;
|
|
60
|
+
}),
|
|
61
|
+
).then((results) => results.flat());
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
*
|
|
65
|
+
* @param {string} stacEndpoint
|
|
66
|
+
* @param {{min: string, max: string}} date
|
|
67
|
+
* @param {number[] | undefined} bbox
|
|
68
|
+
* @param {import("vue").Ref<import("stac-ts").StacCollection|null>} selectedStac
|
|
69
|
+
* @param {Record<string, import("../types").Filter>} filters
|
|
70
|
+
* @return {Promise<Array<{ layers: Record<string, any>[]; date: string }>>}
|
|
71
|
+
*/
|
|
72
|
+
async function createAPILayers(
|
|
73
|
+
stacEndpoint,
|
|
74
|
+
date = { min: "", max: "" },
|
|
75
|
+
bbox,
|
|
76
|
+
selectedStac,
|
|
77
|
+
filters,
|
|
78
|
+
) {
|
|
79
|
+
if (!bbox) {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
const url = new URL(stacEndpoint + "/search");
|
|
83
|
+
url.searchParams.set("limit", "100");
|
|
84
|
+
url.searchParams.set("collections", selectedStac.value?.id ?? "");
|
|
85
|
+
url.searchParams.set(
|
|
86
|
+
"datetime",
|
|
87
|
+
`${new Date(date.min).toISOString()}/${new Date(date.max).toISOString()}`,
|
|
88
|
+
);
|
|
89
|
+
url.searchParams.set("bbox", sanitizeBbox(bbox).join(","));
|
|
90
|
+
|
|
91
|
+
const stacFilter = buildStacFilters(filters);
|
|
92
|
+
if (stacFilter) {
|
|
93
|
+
url.searchParams.set("filter", stacFilter);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** @type {import("stac-ts").StacItem[]} */
|
|
97
|
+
const items = await axios
|
|
98
|
+
.get(url.href)
|
|
99
|
+
.then((res) => res.data.features)
|
|
100
|
+
.catch((err) => {
|
|
101
|
+
console.error("[eodash] Error fetching items for animation:", err);
|
|
102
|
+
return [];
|
|
103
|
+
});
|
|
104
|
+
if (!items || !items.length) {
|
|
105
|
+
console.warn("[eodash] No items found for animation.");
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
const { collections: hiddenCollections, layers: hiddenLayers } =
|
|
109
|
+
getHiddenLayers([...getLayers()]);
|
|
110
|
+
return await Promise.all(
|
|
111
|
+
items.map(async (item) => {
|
|
112
|
+
/** @type {Array<{ layers: Record<string, any>[]; date: string }>} */
|
|
113
|
+
const mapLayersArr = [];
|
|
114
|
+
await createLayersConfig(
|
|
115
|
+
selectedStac.value,
|
|
116
|
+
eodashCollections.filter(
|
|
117
|
+
(collection) =>
|
|
118
|
+
!hiddenCollections.includes(collection.collectionStac?.id ?? ""),
|
|
119
|
+
),
|
|
120
|
+
item,
|
|
121
|
+
).then((layers) => {
|
|
122
|
+
//@ts-expect-error createLayersConfig is not typed strictly
|
|
123
|
+
layers = removeLayers(layers, hiddenLayers);
|
|
124
|
+
//@ts-expect-error createLayersConfig is not typed strictly
|
|
125
|
+
layers = restoreLayersVisibility(layers);
|
|
126
|
+
layers = anonimizeLayersCORS(layers);
|
|
127
|
+
mapLayersArr.push({
|
|
128
|
+
layers,
|
|
129
|
+
date: /** @type {string} */ (item.properties.datetime),
|
|
130
|
+
});
|
|
131
|
+
return mapLayersArr;
|
|
132
|
+
});
|
|
133
|
+
return mapLayersArr;
|
|
134
|
+
}),
|
|
135
|
+
).then((results) => results.flat());
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
*
|
|
139
|
+
* @param {Record<string, any>[]} layers
|
|
140
|
+
* @returns {Record<string, any>[]}
|
|
141
|
+
*/
|
|
142
|
+
function anonimizeLayersCORS(layers) {
|
|
143
|
+
return layers.map((layer) => {
|
|
144
|
+
if (layer.type === "Group") {
|
|
145
|
+
layer.layers = anonimizeLayersCORS(layer.layers);
|
|
146
|
+
return layer;
|
|
147
|
+
}
|
|
148
|
+
if (layer.source) {
|
|
149
|
+
layer.source.crossOrigin = "anonymous";
|
|
150
|
+
}
|
|
151
|
+
return layer;
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* returns the list of layers that has visibility hidden
|
|
156
|
+
* @param {import("@eox/map").EoxLayer[]} layers
|
|
157
|
+
* @returns {{ collections: string[]; layers: string[] }}
|
|
158
|
+
*/
|
|
159
|
+
function getHiddenLayers(layers) {
|
|
160
|
+
/** @type {{ collections: string[]; layers: string[] }} */
|
|
161
|
+
const result = { collections: [], layers: [] };
|
|
162
|
+
|
|
163
|
+
for (const layer of layers) {
|
|
164
|
+
// check inner layers if it's a group layer first
|
|
165
|
+
if (layer.type === "Group" && Array.isArray(layer.layers)) {
|
|
166
|
+
const childResult = getHiddenLayers(layer.layers);
|
|
167
|
+
for (const col of childResult.collections) {
|
|
168
|
+
if (!result.collections.includes(col)) {
|
|
169
|
+
result.collections.push(col);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
for (const lyr of childResult.layers) {
|
|
173
|
+
if (!result.layers.includes(lyr)) {
|
|
174
|
+
result.layers.push(lyr);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (!layer.properties?.id) {
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const olLayer = mapEl.value?.getLayerById(layer.properties?.id);
|
|
184
|
+
if (!olLayer) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (olLayer.getVisible() === false) {
|
|
189
|
+
const refId = layer.properties.id;
|
|
190
|
+
if (refId) {
|
|
191
|
+
if (refId.includes(";:;")) {
|
|
192
|
+
// Check if this looks like a typical eodash collection ID with separator
|
|
193
|
+
const parts = refId.split(";:;");
|
|
194
|
+
if (parts.length > 2) {
|
|
195
|
+
const prefix = parts[0];
|
|
196
|
+
if (!result.collections.includes(prefix)) {
|
|
197
|
+
result.collections.push(prefix);
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
// It has a separator but might just be a base layer like `layerId;:;EPSG`
|
|
201
|
+
if (!result.layers.includes(refId)) {
|
|
202
|
+
result.layers.push(refId);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
if (!result.layers.includes(refId)) {
|
|
207
|
+
result.layers.push(refId);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return result;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Iterates through a list of layers and updates layer.properties.visible to true
|
|
219
|
+
* if it is set to false
|
|
220
|
+
* @param {import("@eox/map").EoxLayer[]} layers
|
|
221
|
+
* @returns {import("@eox/map").EoxLayer[]}
|
|
222
|
+
*/
|
|
223
|
+
function restoreLayersVisibility(layers) {
|
|
224
|
+
for (const layer of layers) {
|
|
225
|
+
if (layer.properties && layer.properties.visible === false) {
|
|
226
|
+
layer.properties.visible = true;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (layer.type === "Group" && Array.isArray(layer.layers)) {
|
|
230
|
+
restoreLayersVisibility(layer.layers);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return layers;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Build STAC API filter string from TimeSlider filters
|
|
238
|
+
* @param {Record<string, import("../types").Filter>} filters
|
|
239
|
+
* @returns {string}
|
|
240
|
+
*/
|
|
241
|
+
function buildStacFilters(filters) {
|
|
242
|
+
if (!filters) return "";
|
|
243
|
+
|
|
244
|
+
/** @type {string[]} */
|
|
245
|
+
const stacFilters = [];
|
|
246
|
+
|
|
247
|
+
Object.values(filters).forEach((filter) => {
|
|
248
|
+
if (!filter || !filter.key) return;
|
|
249
|
+
|
|
250
|
+
// strip 'properties.' from key if present
|
|
251
|
+
const propName = filter.key.startsWith("properties.")
|
|
252
|
+
? filter.key.replace("properties.", "")
|
|
253
|
+
: filter.key;
|
|
254
|
+
|
|
255
|
+
if (filter.type === "range" && filter.state) {
|
|
256
|
+
if (
|
|
257
|
+
filter.state.min !== undefined &&
|
|
258
|
+
filter.state.min > (filter.min ?? -Infinity)
|
|
259
|
+
) {
|
|
260
|
+
stacFilters.push(`${propName}>=${filter.state.min}`);
|
|
261
|
+
}
|
|
262
|
+
if (
|
|
263
|
+
filter.state.max !== undefined &&
|
|
264
|
+
filter.state.max < (filter.max ?? Infinity)
|
|
265
|
+
) {
|
|
266
|
+
stacFilters.push(`${propName}<=${filter.state.max}`);
|
|
267
|
+
}
|
|
268
|
+
} else if (filter.type === "multiselect" && filter.stringifiedState) {
|
|
269
|
+
if (filter.stringifiedState.length > 0) {
|
|
270
|
+
stacFilters.push(`${propName} IN (${filter.stringifiedState})`);
|
|
271
|
+
}
|
|
272
|
+
} else if (filter.type === "select" && filter.stringifiedState) {
|
|
273
|
+
if (filter.stringifiedState) {
|
|
274
|
+
stacFilters.push(`${propName}='${filter.stringifiedState}'`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
return stacFilters.join(" AND ");
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const _style_0 = "eox-itemfilter[data-v-2fc72058]{--inline-container-height: 40px}";
|
|
283
|
+
|
|
284
|
+
const _hoisted_1 = [".for", ".animate"];
|
|
285
|
+
const _hoisted_2 = { class: "d-flex g-10 align-center" };
|
|
286
|
+
const _hoisted_3 = [".filterProperties"];
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
const _sfc_main = {
|
|
290
|
+
__name: 'index',
|
|
291
|
+
props: {
|
|
292
|
+
filters: {
|
|
293
|
+
/** @type {import("vue").PropType<import("@eox/itemfilter").EOxItemFilter["filterProperties"]>} */
|
|
294
|
+
type: Array,
|
|
295
|
+
default: () => [],
|
|
296
|
+
},
|
|
297
|
+
animate: {
|
|
298
|
+
type: Boolean,
|
|
299
|
+
default: true,
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
setup(__props) {
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
/** @type {import("vue").ShallowRef<HTMLElement>} */
|
|
307
|
+
const timesliderEl = useTemplateRef("eoxTimecontrol");
|
|
308
|
+
|
|
309
|
+
const startDate = new Date(datetime.value);
|
|
310
|
+
const endDate = new Date(startDate.getTime() + 24 * 60 * 60 * 1000);
|
|
311
|
+
|
|
312
|
+
const selectedRange = /** @type {import("vue").Ref<[string, string]>} */ (
|
|
313
|
+
ref([startDate, endDate].map((d) => d.toISOString()))
|
|
314
|
+
);
|
|
315
|
+
const initDate = [startDate.toISOString().split("T")[0]];
|
|
316
|
+
|
|
317
|
+
const hasMultipleItems = computed(() => {
|
|
318
|
+
return eodashCollections.some((ec) => {
|
|
319
|
+
const itemLinks = ec.collectionStac?.links.filter((l) => l.rel === "item");
|
|
320
|
+
const itemsLink = ec.collectionStac?.links.some((l) => l.rel === "items");
|
|
321
|
+
return (itemLinks && itemLinks.length > 1) || itemsLink;
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Handles the selection event from the time control component.
|
|
327
|
+
* It finds the closest item to the "from" selected date
|
|
328
|
+
* and updates the global datetime state with that item's original date.
|
|
329
|
+
*
|
|
330
|
+
* @param {CustomEvent<import("./types").TimelineSelectionEventDetail>} e
|
|
331
|
+
*/
|
|
332
|
+
const onSelect = (e) => {
|
|
333
|
+
const { selectedItems, date } = e.detail;
|
|
334
|
+
// Update the selected range with the new dates
|
|
335
|
+
selectedRange.value = date;
|
|
336
|
+
|
|
337
|
+
const allItems = Object.keys(selectedItems ?? {}).flatMap(
|
|
338
|
+
(id) => selectedItems[id],
|
|
339
|
+
);
|
|
340
|
+
if (!allItems.length) {
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
const [from] = date;
|
|
344
|
+
const fromDate = new Date(from).getTime();
|
|
345
|
+
|
|
346
|
+
const closestItem = allItems.reduce((prev, curr) => {
|
|
347
|
+
const prevDiff = Math.abs(new Date(prev.originalDate).getTime() - fromDate);
|
|
348
|
+
const currDiff = Math.abs(new Date(curr.originalDate).getTime() - fromDate);
|
|
349
|
+
return currDiff < prevDiff ? curr : prev;
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
if (closestItem) {
|
|
353
|
+
datetime.value = closestItem.originalDate;
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
const { selectedStac, stacEndpoint } = storeToRefs(useSTAcStore());
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
*
|
|
361
|
+
* @param {CustomEvent<import("./types").TimelineExportEventDetail>} evt
|
|
362
|
+
*/
|
|
363
|
+
const onExport = async (evt) => {
|
|
364
|
+
const { generate, selectedRangeItems, filters } = evt.detail;
|
|
365
|
+
|
|
366
|
+
if (!stacEndpoint.value) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const mapLayers = await createAnimationLayers(
|
|
371
|
+
stacEndpoint.value,
|
|
372
|
+
selectedRange.value,
|
|
373
|
+
selectedRangeItems,
|
|
374
|
+
selectedStac,
|
|
375
|
+
filters,
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
if (!mapLayers?.length) {
|
|
379
|
+
console.warn("[eodash] No map layers generated for the animation.");
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
generate({
|
|
384
|
+
mapLayers,
|
|
385
|
+
});
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
onMounted(() => {
|
|
389
|
+
const parentDiv = timesliderEl.value?.parentElement;
|
|
390
|
+
const layoutItem = parentDiv?.parentElement;
|
|
391
|
+
if (parentDiv && layoutItem && __props.animate) {
|
|
392
|
+
parentDiv.style.overflow = "visible";
|
|
393
|
+
layoutItem.style.overflow = "visible";
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
return (_ctx, _cache) => {
|
|
398
|
+
return (hasMultipleItems.value)
|
|
399
|
+
? (openBlock(), createElementBlock("eox-timecontrol", {
|
|
400
|
+
key: unref(unref(mapEl)),
|
|
401
|
+
ref: "eoxTimecontrol",
|
|
402
|
+
".for": unref(mapEl),
|
|
403
|
+
onSelect: onSelect,
|
|
404
|
+
titleKey: "title",
|
|
405
|
+
".externalMapRendering": true,
|
|
406
|
+
".animate": __props.animate,
|
|
407
|
+
".initDate": initDate
|
|
408
|
+
}, [
|
|
409
|
+
createElementVNode("div", _hoisted_2, [
|
|
410
|
+
_cache[0] || (_cache[0] = createElementVNode("eox-timecontrol-date", { class: "flex-grow-1" }, null, -1 /* CACHED */)),
|
|
411
|
+
createElementVNode("eox-timecontrol-picker", {
|
|
412
|
+
".range": false,
|
|
413
|
+
".showDots": true,
|
|
414
|
+
".showItems": true,
|
|
415
|
+
".popup": true
|
|
416
|
+
}, null, 32 /* NEED_HYDRATION */),
|
|
417
|
+
(__props.filters.length)
|
|
418
|
+
? (openBlock(), createElementBlock("eox-itemfilter", {
|
|
419
|
+
key: 0,
|
|
420
|
+
".inlineMode": true,
|
|
421
|
+
showResults: false,
|
|
422
|
+
".filterProperties": __props.filters
|
|
423
|
+
}, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_3))
|
|
424
|
+
: createCommentVNode("v-if", true),
|
|
425
|
+
createElementVNode("eox-timecontrol-timelapse", { onExport: onExport }, null, 32 /* NEED_HYDRATION */)
|
|
426
|
+
]),
|
|
427
|
+
_cache[1] || (_cache[1] = createElementVNode("eox-timecontrol-timeline", { class: "mt-2" }, null, -1 /* CACHED */))
|
|
428
|
+
], 40 /* PROPS, NEED_HYDRATION */, _hoisted_1))
|
|
429
|
+
: createCommentVNode("v-if", true)
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
};
|
|
434
|
+
const index = /*#__PURE__*/_export_sfc(_sfc_main, [['styles',[_style_0]],['__scopeId',"data-v-2fc72058"]]);
|
|
435
|
+
|
|
436
|
+
export { index as default };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolveComponent, render, h, mergeProps } from 'vue';
|
|
2
|
-
import {
|
|
3
|
-
import { V as VTooltip } from './VTooltip-
|
|
2
|
+
import { $ as consoleError, a0 as isObject } from './asWebComponent-BHWpMuE3.js';
|
|
3
|
+
import { V as VTooltip } from './VTooltip-CJw2FyWk.js';
|
|
4
4
|
|
|
5
5
|
// Utilities
|
|
6
6
|
function useDirectiveComponent(component, props) {
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { onMounted, watch, nextTick, ref, useTemplateRef, computed, openBlock, createElementBlock, createVNode, unref, createCommentVNode, createBlock, createElementVNode, withCtx, createTextVNode } from 'vue';
|
|
1
|
+
import { onMounted, watch, nextTick, onUnmounted, ref, useTemplateRef, computed, openBlock, createElementBlock, createVNode, unref, createCommentVNode, createBlock, createElementVNode, withCtx, createTextVNode } from 'vue';
|
|
2
2
|
import '@eox/chart';
|
|
3
3
|
import '@eox/drawtools';
|
|
4
4
|
import '@eox/jsonform';
|
|
5
|
-
import {
|
|
5
|
+
import { N as useOnLayersUpdate, _ as _export_sfc, H as useSTAcStore, J as VBtn } from './asWebComponent-BHWpMuE3.js';
|
|
6
6
|
import { storeToRefs } from 'pinia';
|
|
7
|
-
import { P as ProcessList, c as compareJobs, j as jobs } from './ProcessList-
|
|
8
|
-
import EodashChart from './EodashChart-
|
|
9
|
-
import { i as initProcess, u as updateJsonformIdentifier, h as handleProcesses } from './handling-
|
|
10
|
-
import {
|
|
11
|
-
import { u as updateJobsStatus, d as download, g as
|
|
12
|
-
import { I as compareIndicator, F as indicator, S as mapCompareEl, i as mapEl, M as areChartsSeparateLayout, O as compareChartSpec, N as chartSpec } from './helpers-CZFH0EVN.js';
|
|
7
|
+
import { P as ProcessList, c as compareJobs, j as jobs } from './ProcessList-CTTIZa06.js';
|
|
8
|
+
import EodashChart from './EodashChart-CLDqE93C.js';
|
|
9
|
+
import { i as initProcess, u as updateJsonformIdentifier, h as handleProcesses } from './handling-BrcDDlgS.js';
|
|
10
|
+
import { Y as getCompareLayers, v as getLayers, H as compareIndicator, E as indicator, R as mapCompareEl, i as mapEl, L as areChartsSeparateLayout, N as compareChartSpec, M as chartSpec } from './helpers-DjZVl_WF.js';
|
|
11
|
+
import { u as updateJobsStatus, d as download, g as getDrawToolsProperties } from './async-DSKj6g1f.js';
|
|
13
12
|
import { mdiCogPlayOutline, mdiDownloadCircleOutline } from '@mdi/js';
|
|
14
13
|
|
|
15
14
|
/**
|
|
@@ -19,17 +18,15 @@ import { mdiCogPlayOutline, mdiDownloadCircleOutline } from '@mdi/js';
|
|
|
19
18
|
* @async
|
|
20
19
|
* @param {Object} params
|
|
21
20
|
* @param {import("vue").Ref<import("stac-ts").StacCollection | null>} params.selectedStac
|
|
22
|
-
* @param {import("vue").Ref<import("@eox/jsonform").EOxJSONForm | null>} params.jsonformEl
|
|
23
21
|
* @param {import("vue").Ref<Record<string,any> | null>} params.jsonformSchema
|
|
24
22
|
* @param {import("vue").Ref<any[]>} params.processResults
|
|
25
23
|
* @param {import("vue").Ref<boolean>} params.isProcessed
|
|
26
24
|
* @param {import("vue").Ref<boolean>} params.loading
|
|
27
25
|
* @param {import("vue").Ref<boolean>} params.isPolling
|
|
28
|
-
* @param {import("@eox/map").EOxMap | null} params.mapElement
|
|
26
|
+
* @param {import("vue").Ref<import("@eox/map").EOxMap | null>} params.mapElement
|
|
29
27
|
*/
|
|
30
28
|
const useInitProcess = ({
|
|
31
29
|
selectedStac,
|
|
32
|
-
jsonformEl,
|
|
33
30
|
jsonformSchema,
|
|
34
31
|
isProcessed,
|
|
35
32
|
processResults,
|
|
@@ -37,64 +34,56 @@ const useInitProcess = ({
|
|
|
37
34
|
isPolling,
|
|
38
35
|
mapElement,
|
|
39
36
|
}) => {
|
|
40
|
-
const layersEvents = useEventBus(eoxLayersKey);
|
|
41
|
-
|
|
42
37
|
onMounted(async () => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
isPolling,
|
|
54
|
-
});
|
|
55
|
-
} else {
|
|
56
|
-
layersEvents.once(async () => {
|
|
57
|
-
await initProcess({
|
|
58
|
-
enableCompare: mapElement?.id === "compare",
|
|
59
|
-
selectedStac,
|
|
60
|
-
jsonformEl,
|
|
61
|
-
jsonformSchema,
|
|
62
|
-
isProcessed,
|
|
63
|
-
loading,
|
|
64
|
-
processResults,
|
|
65
|
-
isPolling,
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
}
|
|
38
|
+
await initProcess({
|
|
39
|
+
enableCompare: mapElement.value?.id === "compare",
|
|
40
|
+
selectedStac,
|
|
41
|
+
jsonformSchema,
|
|
42
|
+
isProcessed,
|
|
43
|
+
processResults,
|
|
44
|
+
loading,
|
|
45
|
+
isPolling,
|
|
46
|
+
mapElement: mapElement.value,
|
|
47
|
+
});
|
|
69
48
|
});
|
|
70
49
|
|
|
71
|
-
|
|
72
|
-
mapElement?.id === "compare"
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
50
|
+
useOnLayersUpdate(async (evt) => {
|
|
51
|
+
const enableCompare = mapElement.value?.id === "compare";
|
|
52
|
+
const layerUpdatedKey = enableCompare
|
|
53
|
+
? "compareLayers:updated"
|
|
54
|
+
: "layers:updated";
|
|
55
|
+
const timeUpdatedKeys = enableCompare
|
|
56
|
+
? ["compareLayertime:updated", "compareTime:updated"]
|
|
57
|
+
: ["layertime:updated", "time:updated"];
|
|
58
|
+
|
|
59
|
+
if (timeUpdatedKeys.includes(evt)) {
|
|
60
|
+
// we need to update jsonform on time change in cases
|
|
61
|
+
// when the feature selection layer was time-based,
|
|
62
|
+
// so that it attaches to a correct new layer
|
|
63
|
+
const newJsonForm = await updateJsonformIdentifier({
|
|
81
64
|
jsonformSchema: jsonformSchema.value,
|
|
82
|
-
|
|
83
|
-
|
|
65
|
+
newLayers: enableCompare ? getCompareLayers() : getLayers(),
|
|
66
|
+
enableCompare,
|
|
67
|
+
mapElement: mapElement.value,
|
|
84
68
|
});
|
|
69
|
+
|
|
70
|
+
if (newJsonForm) {
|
|
71
|
+
jsonformSchema.value = newJsonForm;
|
|
72
|
+
}
|
|
85
73
|
}
|
|
86
|
-
|
|
74
|
+
|
|
75
|
+
if (evt !== layerUpdatedKey) {
|
|
87
76
|
return;
|
|
88
77
|
}
|
|
89
78
|
await initProcess({
|
|
90
|
-
enableCompare
|
|
79
|
+
enableCompare,
|
|
91
80
|
selectedStac,
|
|
92
|
-
jsonformEl,
|
|
93
81
|
jsonformSchema,
|
|
94
82
|
isProcessed,
|
|
95
83
|
processResults,
|
|
96
84
|
loading,
|
|
97
85
|
isPolling,
|
|
86
|
+
mapElement: mapElement.value,
|
|
98
87
|
});
|
|
99
88
|
});
|
|
100
89
|
};
|
|
@@ -114,39 +103,40 @@ function useAutoExec(
|
|
|
114
103
|
startProcess,
|
|
115
104
|
) {
|
|
116
105
|
/**
|
|
117
|
-
* @param {
|
|
106
|
+
* @param {any} _e
|
|
118
107
|
**/
|
|
119
108
|
const onJsonFormChange = async (_e) => {
|
|
120
109
|
await startProcess();
|
|
121
110
|
};
|
|
122
111
|
|
|
123
|
-
const addEventListener = async () => {
|
|
124
|
-
await nextTick(() => {
|
|
125
|
-
//@ts-expect-error TODO
|
|
126
|
-
jsonformEl.value?.addEventListener("change", onJsonFormChange);
|
|
127
|
-
});
|
|
128
|
-
};
|
|
129
|
-
const removeEventListener = () => {
|
|
130
|
-
//@ts-expect-error TODO
|
|
131
|
-
jsonformEl.value?.removeEventListener("change", onJsonFormChange);
|
|
132
|
-
};
|
|
133
|
-
|
|
134
112
|
watch(jsonformSchema, (updatedSchema) => {
|
|
135
113
|
autoExec.value = updatedSchema?.options?.["execute"] || false;
|
|
136
114
|
});
|
|
137
115
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
116
|
+
// Re-attach listener whenever the element or autoExec changes
|
|
117
|
+
const stop = watch(
|
|
118
|
+
[autoExec, jsonformEl],
|
|
119
|
+
async ([exec, el], [_prevExec, prevEl]) => {
|
|
120
|
+
// Cleanup if previous element existed
|
|
121
|
+
if (prevEl) {
|
|
122
|
+
prevEl.removeEventListener("change", onJsonFormChange);
|
|
123
|
+
}
|
|
124
|
+
// Add if enabled and we have an element
|
|
125
|
+
if (exec && el) {
|
|
126
|
+
// remove listener before adding to avoid duplicates in case of element change
|
|
127
|
+
el.removeEventListener("change", onJsonFormChange);
|
|
128
|
+
await nextTick();
|
|
129
|
+
el.addEventListener("change", onJsonFormChange);
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{ immediate: true },
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
onUnmounted(() => {
|
|
136
|
+
if (jsonformEl.value) {
|
|
137
|
+
jsonformEl.value.removeEventListener("change", onJsonFormChange);
|
|
138
|
+
}
|
|
139
|
+
stop();
|
|
150
140
|
});
|
|
151
141
|
}
|
|
152
142
|
|
|
@@ -212,13 +202,15 @@ const currentIndicator = __props.enableCompare ? compareIndicator : indicator;
|
|
|
212
202
|
const currentJobs = __props.enableCompare ? compareJobs : jobs;
|
|
213
203
|
|
|
214
204
|
const jsonformKey = computed(
|
|
215
|
-
() =>
|
|
205
|
+
() =>
|
|
206
|
+
currentIndicator.value +
|
|
207
|
+
mapElement.value?.id +
|
|
208
|
+
JSON.stringify(jsonformSchema.value),
|
|
216
209
|
);
|
|
217
210
|
|
|
218
211
|
useInitProcess({
|
|
219
212
|
selectedStac: currentSelectedStac,
|
|
220
|
-
mapElement
|
|
221
|
-
jsonformEl,
|
|
213
|
+
mapElement,
|
|
222
214
|
jsonformSchema,
|
|
223
215
|
isProcessed,
|
|
224
216
|
processResults,
|
|
@@ -245,15 +237,17 @@ const downloadResults = () => {
|
|
|
245
237
|
};
|
|
246
238
|
|
|
247
239
|
const startProcess = async () => {
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
240
|
+
const drawToolsProperties = getDrawToolsProperties(jsonformSchema.value);
|
|
241
|
+
|
|
242
|
+
const anyDrawtoolPropertyEmpty = drawToolsProperties.some(
|
|
243
|
+
(drawToolsProperty) =>
|
|
244
|
+
//@ts-expect-error jsonfrom.value is not typed
|
|
245
|
+
Array.isArray(jsonformEl.value?.value[drawToolsProperty]) &&
|
|
246
|
+
//@ts-expect-error jsonfrom.value is not typed
|
|
247
|
+
!jsonformEl.value?.value[drawToolsProperty].length,
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
if (anyDrawtoolPropertyEmpty) {
|
|
257
251
|
isProcessed.value = false;
|
|
258
252
|
const usedChartSpec = __props.enableCompare ? compareChartSpec : chartSpec;
|
|
259
253
|
usedChartSpec.value = null;
|