@eodash/eodash 5.7.0 → 5.8.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/EodashOverlay.vue +27 -4
- package/core/client/composables/DefineEodash.js +0 -1
- package/core/client/composables/DefineWidgets.js +3 -1
- package/core/client/eodashSTAC/EodashCollection.js +87 -24
- package/core/client/eodashSTAC/cql.js +64 -0
- package/core/client/eodashSTAC/createLayers.js +353 -187
- package/core/client/eodashSTAC/helpers.js +694 -110
- package/core/client/eodashSTAC/mosaic.js +422 -0
- package/core/client/plugins/axios.js +31 -1
- package/core/client/store/actions.js +1 -1
- package/core/client/store/stac.js +54 -4
- package/core/client/store/states.js +20 -2
- package/core/client/types.ts +152 -28
- package/core/client/utils/bands-editor/exampleSchema.json +50 -50
- package/core/client/utils/states.js +10 -0
- package/dist/client/{DashboardLayout-kRsmsNW5.js → DashboardLayout-DEs4f_Vy.js} +2 -2
- package/dist/client/{DynamicWebComponent-CnKhYo0K.js → DynamicWebComponent-PvnV88BA.js} +1 -1
- package/dist/client/EodashChart-D-3AGKZY.js +260 -0
- package/dist/client/{EodashDatePicker-CMPDT-ce.js → EodashDatePicker-Dm_goZzs.js} +3 -3
- package/dist/client/{EodashItemFilter-BpdA8QQa.js → EodashItemFilter-CJy3zYzD.js} +2 -1
- package/dist/client/{EodashLayerControl-BHpDA4_0.js → EodashLayerControl-rL8UnpkA.js} +55 -33
- package/dist/client/{EodashLayoutSwitcher-B1fRUt7G.js → EodashLayoutSwitcher-ZRlESI9O.js} +3 -3
- package/dist/client/{EodashMapBtns-Cpned0tc.js → EodashMapBtns-CG7u2Aq8.js} +227 -112
- package/dist/client/EodashStacInfo-CJhhxthD.js +169 -0
- package/dist/client/{EodashTools-1zHz26gv.js → EodashTools-CWyK8QJT.js} +4 -4
- package/dist/client/{ExportState-DbOm8hBI.js → ExportState-BXhy5TOU.js} +20 -174
- package/dist/client/{Footer-BKg-VVkj.js → Footer-DZPvnhcT.js} +1 -1
- package/dist/client/{Header-DCrwCvmY.js → Header-CiGsDE_a.js} +2 -2
- package/dist/client/{MobileLayout-vWSHpluo.js → MobileLayout-BJHW7x5V.js} +2 -2
- package/dist/client/{PopUp-9uimfK49.js → PopUp-7_XnhvCc.js} +4 -168
- package/dist/client/{ProcessList-CTTIZa06.js → ProcessList-LL_UCbvc.js} +5 -5
- package/dist/client/VDivider-DWYM0WUr.js +168 -0
- package/dist/client/{VImg-CrmB76ZY.js → VImg-B75dgw2K.js} +2 -2
- package/dist/client/{VMain-OKZNpcEG.js → VMain-DvMmOL4f.js} +1 -1
- package/dist/client/{VTooltip-CJw2FyWk.js → VTooltip-ClWHUmWL.js} +2 -2
- package/dist/client/{WidgetsContainer-BaWOnE5R.js → WidgetsContainer-BqaWs4ch.js} +1 -1
- package/dist/client/{asWebComponent-BHWpMuE3.js → asWebComponent-IZanwL-A.js} +677 -379
- package/dist/client/{async-DSKj6g1f.js → async-CiNIOBVz.js} +31 -29
- package/dist/client/{create-layers-config-CBoYedqB.js → create-layers-config-3S3y_kZg.js} +17 -17
- package/dist/client/dialog-transition-c4ZSnzac.js +170 -0
- package/dist/client/eo-dash.js +1 -1
- package/dist/client/{forwardRefs-DH51zPUr.js → forwardRefs-B-c1_6yo.js} +8 -87
- package/dist/client/{handling-BrcDDlgS.js → handling-NvY8Csry.js} +3 -4
- package/dist/client/{helpers-DjZVl_WF.js → helpers-BFuh19CP.js} +1094 -194
- package/dist/client/{index-1JKE68n3.js → index-1wMAyuNL.js} +219 -67
- package/dist/client/{index-CSG_JoOA.js → index-B8jGJSTA.js} +62 -56
- package/dist/client/{index-Cu3-13Xg.js → index-BKQQJkhy.js} +167 -61
- package/dist/client/index-D0jUyol8.js +3167 -0
- package/dist/client/{index-CUjl-ZsI.js → index-KGxz5Egv.js} +2 -2
- package/dist/client/mosaic-vHvSuih6.js +459 -0
- package/dist/client/templates.js +251 -121
- package/dist/client/{transition-OHcz5Qq1.js → transition-BkyUsZh_.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/eodashSTAC/EodashCollection.d.ts +57 -25
- package/dist/types/core/client/eodashSTAC/cql.d.ts +15 -0
- package/dist/types/core/client/eodashSTAC/createLayers.d.ts +42 -23
- package/dist/types/core/client/eodashSTAC/helpers.d.ts +118 -19
- package/dist/types/core/client/eodashSTAC/mosaic.d.ts +56 -0
- package/dist/types/core/client/store/stac.d.ts +38 -8
- package/dist/types/core/client/store/states.d.ts +24 -2
- package/dist/types/core/client/types.d.ts +128 -24
- package/dist/types/core/client/utils/states.d.ts +12 -0
- package/dist/types/templates/baseConfig.d.ts +1 -100
- 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 +10 -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 +35 -16
- package/dist/types/widgets/EodashMap/EodashMapBtns.vue.d.ts +14 -10
- package/dist/types/widgets/EodashMap/index.vue.d.ts +86 -37
- package/dist/types/widgets/EodashMap/methods/create-layers-config.d.ts +1 -1
- 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/custom-endpoints/layers/eoxhub-workspaces-endpoint.d.ts +1 -1
- 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 +20 -0
- package/dist/types/widgets/EodashTimeSlider/methods/index.d.ts +3 -8
- package/dist/types/widgets/EodashTimeSlider/types.d.ts +6 -16
- package/dist/types/widgets/EodashTools.vue.d.ts +5 -5
- package/package.json +34 -34
- package/templates/baseConfig.js +37 -6
- package/templates/compare.js +61 -7
- package/templates/expert.js +24 -2
- package/templates/explore.js +12 -5
- package/templates/lite.js +13 -0
- package/widgets/EodashChart.vue +162 -21
- 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 +141 -28
- package/widgets/EodashLayerControl.vue +51 -25
- package/widgets/EodashMap/EodashMapBtns.vue +109 -48
- package/widgets/EodashMap/index.vue +91 -105
- package/widgets/EodashMap/methods/btns.js +64 -31
- package/widgets/EodashMap/methods/create-layers-config.js +16 -16
- package/widgets/EodashMap/methods/index.js +71 -8
- package/widgets/EodashMap/methods/use-map-loading.js +58 -0
- package/widgets/EodashProcess/index.vue +136 -16
- package/widgets/EodashProcess/methods/composables.js +13 -0
- package/widgets/EodashProcess/methods/outputs.js +0 -1
- package/widgets/EodashProcess/methods/utils.js +29 -27
- package/widgets/EodashProcess/states.js +1 -1
- package/widgets/EodashStacInfo.vue +64 -2
- package/widgets/EodashTimeSlider/index.vue +58 -2
- package/widgets/EodashTimeSlider/methods/index.js +5 -48
- package/widgets/EodashTimeSlider/types.ts +7 -17
- package/widgets/ExportState.vue +13 -4
- package/dist/client/EodashChart-CLDqE93C.js +0 -144
- package/dist/client/EodashStacInfo-BQspAHKH.js +0 -107
- package/dist/client/index-5Jhsa8Xe.js +0 -570
|
@@ -6,9 +6,12 @@ import { useSTAcStore } from "@/store/stac";
|
|
|
6
6
|
import { storeToRefs } from "pinia";
|
|
7
7
|
import { isFirstLoad } from "@/utils/states";
|
|
8
8
|
import { useEmitLayersUpdate, useOnLayersUpdate } from "@/composables";
|
|
9
|
-
|
|
9
|
+
export { useEmitLayersUpdate, useOnLayersUpdate };
|
|
10
|
+
import { isGlobe, mapPosition } from "@/store/states";
|
|
10
11
|
import { sanitizeBbox } from "@/eodashSTAC/helpers";
|
|
11
12
|
import { transformExtent } from "@eox/map";
|
|
13
|
+
|
|
14
|
+
export { useMapLoading } from "./use-map-loading";
|
|
12
15
|
/**
|
|
13
16
|
* Holder for previous compare map view as it is overwritten by sync
|
|
14
17
|
* @type { import("ol").View | null} mapElement
|
|
@@ -39,14 +42,52 @@ export const useHandleMapMoveEnd = (mapElement, mapPosition) => {
|
|
|
39
42
|
}
|
|
40
43
|
};
|
|
41
44
|
|
|
45
|
+
const handleGlobeMoveEnd = () => {
|
|
46
|
+
const camera = mapElement.value?.globe?.planet?.camera;
|
|
47
|
+
const lonLat = camera?.getLonLat();
|
|
48
|
+
if (!lonLat) return;
|
|
49
|
+
const { lon, lat, height } = lonLat;
|
|
50
|
+
if (![lon, lat, height].some(Number.isNaN)) {
|
|
51
|
+
mapPosition.value = [lon, lat, height];
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/** @type {{ events: { off: Function } } | null} */
|
|
56
|
+
let subscribedCamera = null;
|
|
57
|
+
|
|
58
|
+
const subscribeGlobe = (retries = 3) => {
|
|
59
|
+
if (!isGlobe.value) return; // toggled back out during retry
|
|
60
|
+
const camera = mapElement.value?.globe?.planet?.camera;
|
|
61
|
+
if (camera) {
|
|
62
|
+
if (subscribedCamera === camera) return;
|
|
63
|
+
camera.events.on("moveend", handleGlobeMoveEnd);
|
|
64
|
+
subscribedCamera = camera;
|
|
65
|
+
handleGlobeMoveEnd();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (retries > 0) setTimeout(() => subscribeGlobe(retries - 1), 50);
|
|
69
|
+
};
|
|
70
|
+
const unsubscribeGlobe = () => {
|
|
71
|
+
subscribedCamera?.events.off("moveend", handleGlobeMoveEnd);
|
|
72
|
+
subscribedCamera = null;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const stopGlobeWatch = watch(isGlobe, (globe) =>
|
|
76
|
+
globe ? subscribeGlobe() : unsubscribeGlobe(),
|
|
77
|
+
);
|
|
78
|
+
|
|
42
79
|
onMounted(() => {
|
|
43
|
-
|
|
44
|
-
|
|
80
|
+
const map = mapElement.value?.map;
|
|
81
|
+
map?.on("moveend", handleMoveEnd);
|
|
82
|
+
// Seed mapPosition from the initial view
|
|
83
|
+
handleMoveEnd(/** @type {any} */ ({ map }));
|
|
45
84
|
});
|
|
46
85
|
|
|
47
86
|
onUnmounted(() => {
|
|
48
87
|
/** @type {import('ol/Map').default} */
|
|
49
88
|
(mapElement.value?.map)?.un("moveend", handleMoveEnd);
|
|
89
|
+
unsubscribeGlobe();
|
|
90
|
+
stopGlobeWatch();
|
|
50
91
|
});
|
|
51
92
|
};
|
|
52
93
|
|
|
@@ -61,6 +102,7 @@ export const useHandleMapMoveEnd = (mapElement, mapPosition) => {
|
|
|
61
102
|
* @param {import("vue").Ref<import("@eox/map").EOxMap| null>} partnerMap
|
|
62
103
|
* @param {boolean} zoomToExtent
|
|
63
104
|
* @param {import("vue").Ref<import("stac-ts").StacItem | import("stac-ts").StacLink | null>} [selectedItem]
|
|
105
|
+
* @param {Record<string, any>[]} [defaultBaseLayers]
|
|
64
106
|
*/
|
|
65
107
|
export const useInitMap = (
|
|
66
108
|
mapElement,
|
|
@@ -71,6 +113,7 @@ export const useInitMap = (
|
|
|
71
113
|
partnerMap,
|
|
72
114
|
zoomToExtent,
|
|
73
115
|
selectedItem,
|
|
116
|
+
defaultBaseLayers,
|
|
74
117
|
) => {
|
|
75
118
|
log.debug(
|
|
76
119
|
"InitMap",
|
|
@@ -100,12 +143,24 @@ export const useInitMap = (
|
|
|
100
143
|
);
|
|
101
144
|
|
|
102
145
|
if (updatedStac) {
|
|
103
|
-
|
|
146
|
+
const isSameStac = updatedStac?.id === previousStac?.id;
|
|
147
|
+
const isSameItem = updatedItem?.id === previousItem?.id;
|
|
148
|
+
|
|
149
|
+
// Item deselect: overview render is owned by the item catalog widget.
|
|
150
|
+
const isItemDeselect =
|
|
151
|
+
previousItem &&
|
|
152
|
+
!updatedItem &&
|
|
153
|
+
isSameStac &&
|
|
154
|
+
updatedTime === previousTime;
|
|
155
|
+
if (isItemDeselect) return;
|
|
156
|
+
|
|
157
|
+
// Re-fire from our own datetime.value write, skip and clear
|
|
158
|
+
const isOwnDatetimeUpdate =
|
|
104
159
|
internalDatetime !== null &&
|
|
105
160
|
updatedTime === internalDatetime &&
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
) {
|
|
161
|
+
isSameStac &&
|
|
162
|
+
isSameItem;
|
|
163
|
+
if (isOwnDatetimeUpdate) {
|
|
109
164
|
internalDatetime = null;
|
|
110
165
|
return;
|
|
111
166
|
}
|
|
@@ -153,7 +208,9 @@ export const useInitMap = (
|
|
|
153
208
|
updatedStac,
|
|
154
209
|
eodashCols,
|
|
155
210
|
updatedItem ?? updatedTime,
|
|
211
|
+
defaultBaseLayers,
|
|
156
212
|
);
|
|
213
|
+
|
|
157
214
|
log.debug(
|
|
158
215
|
"Assigned layers after changing time only",
|
|
159
216
|
JSON.parse(JSON.stringify(layersCollection)),
|
|
@@ -175,6 +232,11 @@ export const useInitMap = (
|
|
|
175
232
|
if (interval && interval.length > 0 && interval[0].length > 1) {
|
|
176
233
|
// @ts-expect-error this is the defined STAC structure
|
|
177
234
|
endInterval = new Date(interval[0][1]);
|
|
235
|
+
// If end interval is in the future, set to now,
|
|
236
|
+
// for item fetching based on search endpoint
|
|
237
|
+
if (endInterval.getTime() > Date.now()) {
|
|
238
|
+
endInterval = new Date();
|
|
239
|
+
}
|
|
178
240
|
log.debug(
|
|
179
241
|
"Indicator load: found stac extent, setting time to latest value",
|
|
180
242
|
endInterval,
|
|
@@ -200,7 +262,8 @@ export const useInitMap = (
|
|
|
200
262
|
layersCollection = await createLayersConfig(
|
|
201
263
|
updatedStac,
|
|
202
264
|
eodashCols,
|
|
203
|
-
resolvedTime,
|
|
265
|
+
updatedItem ?? resolvedTime,
|
|
266
|
+
defaultBaseLayers,
|
|
204
267
|
);
|
|
205
268
|
|
|
206
269
|
if (zoomToExtent) {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { onUnmounted, watch } from "vue";
|
|
2
|
+
import { loading } from "@/store/states";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Tracks map loading state at the source level via `loading.activeLoads`,
|
|
6
|
+
* the same counter used by the axios plugin. Re-attaches source listeners
|
|
7
|
+
* whenever eox-map fires `layerschanged`, using `getFlatLayersArray`.
|
|
8
|
+
*
|
|
9
|
+
* @param {import("vue").Ref<import("@eox/map").EOxMap | null>} mapElement
|
|
10
|
+
* @param {import("vue").Ref<import("@eox/map").EOxMap | null>} compareMapElement
|
|
11
|
+
*/
|
|
12
|
+
export const useMapLoading = (mapElement, compareMapElement) => {
|
|
13
|
+
// This instance's outstanding loads, so unmount subtracts only its share.
|
|
14
|
+
let localLoads = 0;
|
|
15
|
+
const startHandler = () => {
|
|
16
|
+
localLoads++;
|
|
17
|
+
loading.activeLoads++;
|
|
18
|
+
};
|
|
19
|
+
const endHandler = () => {
|
|
20
|
+
localLoads = Math.max(0, localLoads - 1);
|
|
21
|
+
loading.activeLoads = Math.max(0, loading.activeLoads - 1);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** @param {import("@eox/map").EOxMap | null} newMapEl */
|
|
25
|
+
const watcherHandler = (newMapEl) => {
|
|
26
|
+
if (!newMapEl) return;
|
|
27
|
+
|
|
28
|
+
const hasStartListener = newMapEl.map
|
|
29
|
+
.getListeners("loadstart")
|
|
30
|
+
?.some((listner) => listner === startHandler);
|
|
31
|
+
const hasEndListener = newMapEl.map
|
|
32
|
+
.getListeners("loadend")
|
|
33
|
+
?.some((listner) => listner === endHandler);
|
|
34
|
+
|
|
35
|
+
if (!hasStartListener) {
|
|
36
|
+
newMapEl.map.addEventListener("loadstart", startHandler);
|
|
37
|
+
}
|
|
38
|
+
if (!hasEndListener) {
|
|
39
|
+
newMapEl.map.addEventListener("loadend", endHandler);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
const stopMainWatcher = watch(mapElement, watcherHandler, {
|
|
43
|
+
immediate: true,
|
|
44
|
+
});
|
|
45
|
+
const stopCompareWatcher = watch(compareMapElement, watcherHandler, {
|
|
46
|
+
immediate: true,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
onUnmounted(() => {
|
|
50
|
+
mapElement.value?.map.removeEventListener("loadstart", startHandler);
|
|
51
|
+
mapElement.value?.map.removeEventListener("loadend", endHandler);
|
|
52
|
+
compareMapElement.value?.map.removeEventListener("loadstart", startHandler);
|
|
53
|
+
compareMapElement.value?.map.removeEventListener("loadend", endHandler);
|
|
54
|
+
stopMainWatcher();
|
|
55
|
+
stopCompareWatcher();
|
|
56
|
+
loading.activeLoads = Math.max(0, loading.activeLoads - localLoads);
|
|
57
|
+
});
|
|
58
|
+
};
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div ref="container" class="
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
2
|
+
<div ref="container" class="eodash-process-container">
|
|
3
|
+
<div class="eodash-process-content">
|
|
4
|
+
<ProcessList :map-element="mapElement" :enable-compare="enableCompare" />
|
|
5
|
+
<eox-jsonform
|
|
6
|
+
v-if="jsonformSchema"
|
|
7
|
+
:key="jsonformKey"
|
|
8
|
+
ref="jsonformEl"
|
|
9
|
+
.schema="jsonformSchema"
|
|
10
|
+
></eox-jsonform>
|
|
11
|
+
<EodashChart
|
|
12
|
+
v-if="!areChartsSeparateLayout"
|
|
13
|
+
:vega-embed-options="vegaEmbedOptions"
|
|
14
|
+
:enable-compare="enableCompare"
|
|
15
|
+
>
|
|
16
|
+
</EodashChart>
|
|
17
|
+
</div>
|
|
18
|
+
<div
|
|
19
|
+
class="eodash-process-actions"
|
|
20
|
+
v-if="showExecBtn || (processResults.length && isProcessed && !isAsync)"
|
|
14
21
|
>
|
|
15
|
-
</EodashChart>
|
|
16
|
-
<div class="text-right">
|
|
17
22
|
<v-btn
|
|
18
23
|
v-if="showExecBtn"
|
|
19
24
|
:loading="loading"
|
|
@@ -45,7 +50,7 @@ import "@eox/drawtools";
|
|
|
45
50
|
import "@eox/jsonform";
|
|
46
51
|
import { useSTAcStore } from "@/store/stac";
|
|
47
52
|
import { storeToRefs } from "pinia";
|
|
48
|
-
import { computed, ref, useTemplateRef } from "vue";
|
|
53
|
+
import { computed, ref, useTemplateRef, watch } from "vue";
|
|
49
54
|
import ProcessList from "./ProcessList.vue";
|
|
50
55
|
import EodashChart from "../EodashChart.vue";
|
|
51
56
|
import { handleProcesses } from "./methods/handling";
|
|
@@ -70,6 +75,7 @@ const { enableCompare, vegaEmbedOptions } = defineProps({
|
|
|
70
75
|
default: false,
|
|
71
76
|
},
|
|
72
77
|
vegaEmbedOptions: {
|
|
78
|
+
/** @type {import("vue").PropType<import("vega-embed").EmbedOptions>} */
|
|
73
79
|
type: Object,
|
|
74
80
|
default() {
|
|
75
81
|
return { actions: true };
|
|
@@ -87,6 +93,90 @@ const jsonformEl =
|
|
|
87
93
|
useTemplateRef("jsonformEl")
|
|
88
94
|
);
|
|
89
95
|
|
|
96
|
+
// Inject custom styles into the eox-jsonform shadow DOM to make eox-drawtools inline
|
|
97
|
+
watch(jsonformEl, (el) => {
|
|
98
|
+
if (el && el.shadowRoot) {
|
|
99
|
+
const styleId = "eodash-drawtools-inline-style";
|
|
100
|
+
if (!el.shadowRoot.getElementById(styleId)) {
|
|
101
|
+
const style = document.createElement("style");
|
|
102
|
+
style.id = styleId;
|
|
103
|
+
style.textContent = `
|
|
104
|
+
/* Compact standard form elements */
|
|
105
|
+
.form-control, .form-group {
|
|
106
|
+
margin-bottom: 8px !important;
|
|
107
|
+
}
|
|
108
|
+
.form-control > label, .form-group > label {
|
|
109
|
+
margin-bottom: 2px !important;
|
|
110
|
+
font-size: 0.9em;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* Specific layout for drawtools */
|
|
114
|
+
.form-control:has(eox-drawtools) {
|
|
115
|
+
position: relative;
|
|
116
|
+
padding: 8px 12px !important;
|
|
117
|
+
border: none !important;
|
|
118
|
+
background: transparent !important;
|
|
119
|
+
margin-bottom: 8px !important;
|
|
120
|
+
}
|
|
121
|
+
.form-control:has(eox-drawtools) > label {
|
|
122
|
+
position: absolute;
|
|
123
|
+
left: 12px;
|
|
124
|
+
top: 8px;
|
|
125
|
+
margin: 0 !important;
|
|
126
|
+
width: calc(100% - 180px); /* Give label maximum available width */
|
|
127
|
+
line-height: 1.2;
|
|
128
|
+
display: flex;
|
|
129
|
+
align-items: flex-start;
|
|
130
|
+
padding-top: 8px;
|
|
131
|
+
pointer-events: none; /* Let clicks pass through to buttons if they overlap slightly */
|
|
132
|
+
}
|
|
133
|
+
.form-control:has(eox-drawtools) > eox-drawtools {
|
|
134
|
+
display: block;
|
|
135
|
+
width: 100%;
|
|
136
|
+
}
|
|
137
|
+
`;
|
|
138
|
+
el.shadowRoot.appendChild(style);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const injectDrawtoolsStyle = () => {
|
|
142
|
+
const drawtools = el?.shadowRoot?.querySelector("eox-drawtools");
|
|
143
|
+
if (drawtools && drawtools.shadowRoot) {
|
|
144
|
+
if (
|
|
145
|
+
!drawtools.shadowRoot.getElementById("eodash-drawtools-indent-style")
|
|
146
|
+
) {
|
|
147
|
+
const dtStyle = document.createElement("style");
|
|
148
|
+
dtStyle.id = "eodash-drawtools-indent-style";
|
|
149
|
+
dtStyle.textContent = `
|
|
150
|
+
eox-drawtools-controller {
|
|
151
|
+
display: flex;
|
|
152
|
+
justify-content: flex-end; /* Push buttons to the right */
|
|
153
|
+
min-height: 40px;
|
|
154
|
+
width: 100%;
|
|
155
|
+
}
|
|
156
|
+
eox-drawtools-list {
|
|
157
|
+
display: block;
|
|
158
|
+
margin-top: 10px;
|
|
159
|
+
width: 100%;
|
|
160
|
+
}
|
|
161
|
+
`;
|
|
162
|
+
drawtools.shadowRoot.appendChild(dtStyle);
|
|
163
|
+
return true;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return false;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
if (!injectDrawtoolsStyle()) {
|
|
170
|
+
const observer = new MutationObserver(() => {
|
|
171
|
+
if (injectDrawtoolsStyle()) {
|
|
172
|
+
observer.disconnect();
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
observer.observe(el.shadowRoot, { childList: true, subtree: true });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
90
180
|
const isAsync = computed(
|
|
91
181
|
() =>
|
|
92
182
|
selectedStac.value?.links.filter((l) => l.endpoint === "eoxhub_workspaces")
|
|
@@ -188,7 +278,37 @@ useAutoExec(autoExec, jsonformEl, jsonformSchema, startProcess);
|
|
|
188
278
|
</script>
|
|
189
279
|
<style>
|
|
190
280
|
eox-jsonform {
|
|
191
|
-
padding: 0
|
|
281
|
+
padding: 0 12px;
|
|
192
282
|
min-height: 0px;
|
|
283
|
+
flex-shrink: 0;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/* Force the specific panel wrapping this component to utilize 100% height */
|
|
287
|
+
.bg-surface:has(.eodash-process-container) {
|
|
288
|
+
height: calc(100% - 30px);
|
|
289
|
+
overflow: hidden;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/* Make sure this container takes up full height and acts as a flex column */
|
|
293
|
+
.eodash-process-container {
|
|
294
|
+
height: 100%;
|
|
295
|
+
display: flex;
|
|
296
|
+
flex-direction: column;
|
|
297
|
+
overflow: hidden;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.eodash-process-content {
|
|
301
|
+
flex-grow: 1;
|
|
302
|
+
overflow-y: auto;
|
|
303
|
+
display: flex;
|
|
304
|
+
flex-direction: column;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.eodash-process-actions {
|
|
308
|
+
text-align: right;
|
|
309
|
+
padding: 4px 12px;
|
|
310
|
+
flex-shrink: 0;
|
|
311
|
+
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
|
312
|
+
background: inherit;
|
|
193
313
|
}
|
|
194
314
|
</style>
|
|
@@ -59,6 +59,19 @@ export const useInitProcess = ({
|
|
|
59
59
|
});
|
|
60
60
|
|
|
61
61
|
if (newJsonForm) {
|
|
62
|
+
// Layer rebuilds strip drawtools' selection interactions; remount
|
|
63
|
+
// the form so initSelection re-attaches them.
|
|
64
|
+
const selectionStripped =
|
|
65
|
+
Object.values(newJsonForm.properties ?? {}).some(
|
|
66
|
+
(p) => p?.options?.drawtools?.layerId,
|
|
67
|
+
) &&
|
|
68
|
+
!mapElement.value?.selectInteractions?.[
|
|
69
|
+
"SelectLayerClickInteraction"
|
|
70
|
+
];
|
|
71
|
+
if (selectionStripped) {
|
|
72
|
+
jsonformSchema.value = null;
|
|
73
|
+
await nextTick();
|
|
74
|
+
}
|
|
62
75
|
jsonformSchema.value = newJsonForm;
|
|
63
76
|
}
|
|
64
77
|
}
|
|
@@ -89,10 +89,10 @@ export async function createTiffLayerDefinition(
|
|
|
89
89
|
}
|
|
90
90
|
// We want to make sure the urls are alphabetically sorted
|
|
91
91
|
urls = urls.sort();
|
|
92
|
-
|
|
92
|
+
|
|
93
93
|
const layerdef =
|
|
94
94
|
urls.length > 0
|
|
95
|
-
? {
|
|
95
|
+
? /** @type {import("@eox/map/src/layers").EOxLayerType<"WebGLTile","GeoTIFF">} */ ({
|
|
96
96
|
type: "WebGLTile",
|
|
97
97
|
source: {
|
|
98
98
|
type: "GeoTIFF",
|
|
@@ -106,7 +106,7 @@ export async function createTiffLayerDefinition(
|
|
|
106
106
|
layerControlToolsExpand: true,
|
|
107
107
|
},
|
|
108
108
|
...(style && { style: style }),
|
|
109
|
-
}
|
|
109
|
+
})
|
|
110
110
|
: undefined;
|
|
111
111
|
|
|
112
112
|
// We want to see if the currently selected indicator uses a
|
|
@@ -309,31 +309,33 @@ export async function creatAsyncProcessLayerDefinitions(
|
|
|
309
309
|
|
|
310
310
|
switch (resultItem.type) {
|
|
311
311
|
case "image/tiff": {
|
|
312
|
-
layers.push(
|
|
313
|
-
type
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
...(selectedStac["eodash:mapProjection"]?.["name"] && {
|
|
312
|
+
layers.push(
|
|
313
|
+
/** @type {import("@eox/map/src/layers").EOxLayerType<"WebGLTile","GeoTIFF">} */ ({
|
|
314
|
+
type: "WebGLTile",
|
|
315
|
+
properties: {
|
|
316
|
+
id: endpointLink.id + "_process" + resultItem.id + postfixId,
|
|
317
|
+
title:
|
|
318
|
+
"Results " +
|
|
319
|
+
(selectedStac?.id ?? "") +
|
|
320
|
+
" " +
|
|
321
|
+
(resultItem.id ?? ""),
|
|
322
|
+
layerControlToolsExpand: true,
|
|
323
|
+
...(layerConfig && { layerConfig }),
|
|
324
|
+
...extraProperties,
|
|
325
|
+
},
|
|
326
|
+
source: {
|
|
327
|
+
type: "GeoTIFF",
|
|
328
|
+
normalize: !style,
|
|
329
|
+
sources: resultItem.urls.map((url) => ({ url })),
|
|
331
330
|
//@ts-expect-error TODO
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
331
|
+
...(selectedStac["eodash:mapProjection"]?.["name"] && {
|
|
332
|
+
//@ts-expect-error TODO
|
|
333
|
+
projection: selectedStac["eodash:mapProjection"]["name"],
|
|
334
|
+
}),
|
|
335
|
+
},
|
|
336
|
+
...(style && { style }),
|
|
337
|
+
}),
|
|
338
|
+
);
|
|
337
339
|
break;
|
|
338
340
|
}
|
|
339
341
|
case "application/geo+json": {
|
|
@@ -4,7 +4,7 @@ import { ref } from "vue";
|
|
|
4
4
|
* The list of job result from the server
|
|
5
5
|
* {job_start_datetime: string, job_end_datetime: string,status: string}
|
|
6
6
|
* @type {import("vue").Ref<import("./types").AsyncJob[]>}
|
|
7
|
-
|
|
7
|
+
*/
|
|
8
8
|
export const jobs = ref([]);
|
|
9
9
|
/**
|
|
10
10
|
* The list of jobs results from the server for the compare map
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="flex-grow-1">
|
|
3
3
|
<eox-stacinfo
|
|
4
|
-
|
|
4
|
+
v-if="stacInfoURL"
|
|
5
|
+
.for="stacInfoURL"
|
|
5
6
|
.allowHtml="allowHtml"
|
|
6
7
|
.body="body"
|
|
7
8
|
.featured="featured"
|
|
@@ -9,6 +10,7 @@
|
|
|
9
10
|
.header="header"
|
|
10
11
|
.tags="tags"
|
|
11
12
|
style="--color-primary-lighter: none"
|
|
13
|
+
.styleOverride="styleOverride"
|
|
12
14
|
>
|
|
13
15
|
</eox-stacinfo>
|
|
14
16
|
</div>
|
|
@@ -17,8 +19,21 @@
|
|
|
17
19
|
<script setup>
|
|
18
20
|
import "@eox/stacinfo";
|
|
19
21
|
import { currentUrl } from "@/store/states";
|
|
22
|
+
import { storeToRefs } from "pinia";
|
|
23
|
+
import { useSTAcStore } from "@/store/stac";
|
|
24
|
+
import { computed, onUnmounted, ref, watch } from "vue";
|
|
25
|
+
import { isSTACItem } from "@/eodashSTAC/helpers";
|
|
20
26
|
|
|
21
|
-
const { allowHtml, featured, footer, header, body, tags } = defineProps({
|
|
27
|
+
const { level, allowHtml, featured, footer, header, body, tags } = defineProps({
|
|
28
|
+
level: {
|
|
29
|
+
type: /** @type {import("vue").PropType<"item" | "collection">} */ (String),
|
|
30
|
+
default: "collection",
|
|
31
|
+
validator: (/** @type {string} */ v) => ["collection", "item"].includes(v),
|
|
32
|
+
},
|
|
33
|
+
styleOverride: {
|
|
34
|
+
type: String,
|
|
35
|
+
default: "",
|
|
36
|
+
},
|
|
22
37
|
allowHtml: {
|
|
23
38
|
type: Boolean,
|
|
24
39
|
default: true,
|
|
@@ -92,4 +107,51 @@ const { allowHtml, featured, footer, header, body, tags } = defineProps({
|
|
|
92
107
|
default: () => ["sci:citation", "sci:doi", "sci:publication"],
|
|
93
108
|
},
|
|
94
109
|
});
|
|
110
|
+
|
|
111
|
+
const { selectedItem } = storeToRefs(useSTAcStore());
|
|
112
|
+
|
|
113
|
+
/** @type {import("vue").Ref<string | null>} */
|
|
114
|
+
const itemUrl = ref(null);
|
|
115
|
+
/**
|
|
116
|
+
* Active object URL (only set for the blob fallback)
|
|
117
|
+
* @type {string | null}
|
|
118
|
+
*/
|
|
119
|
+
let activeItemUrl = null;
|
|
120
|
+
|
|
121
|
+
const revokeItem = () => {
|
|
122
|
+
if (activeItemUrl) {
|
|
123
|
+
URL.revokeObjectURL(activeItemUrl);
|
|
124
|
+
activeItemUrl = null;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
watch(
|
|
129
|
+
selectedItem,
|
|
130
|
+
(item) => {
|
|
131
|
+
if (level !== "item" || !item) return;
|
|
132
|
+
revokeItem();
|
|
133
|
+
if (!isSTACItem(item)) {
|
|
134
|
+
itemUrl.value = item.href;
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const selfHref = item?.links?.find((l) => l.rel === "self")?.href;
|
|
138
|
+
if (selfHref) {
|
|
139
|
+
itemUrl.value = selfHref;
|
|
140
|
+
} else if (item) {
|
|
141
|
+
const blob = new Blob([JSON.stringify(item)], {
|
|
142
|
+
type: "application/json",
|
|
143
|
+
});
|
|
144
|
+
activeItemUrl = URL.createObjectURL(blob);
|
|
145
|
+
itemUrl.value = activeItemUrl;
|
|
146
|
+
} else {
|
|
147
|
+
itemUrl.value = null;
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
{ immediate: true },
|
|
151
|
+
);
|
|
152
|
+
onUnmounted(revokeItem);
|
|
153
|
+
|
|
154
|
+
const stacInfoURL = computed(() =>
|
|
155
|
+
level === "item" ? itemUrl.value : currentUrl.value,
|
|
156
|
+
);
|
|
95
157
|
</script>
|