@eodash/eodash 5.0.0-alpha.1.13 → 5.0.0-alpha.1.15
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/bin/serverConfig.js +6 -4
- package/bin/utils.js +6 -2
- package/core/App.vue +17 -2
- package/core/components/DashboardLayout.vue +3 -2
- package/core/components/Footer.vue +11 -3
- package/core/components/MobileLayout.vue +28 -45
- package/core/composables/DefineWidgets.js +18 -11
- package/core/composables/index.js +153 -66
- package/core/eodash.js +52 -88
- package/core/main.js +1 -3
- package/core/store/Actions.js +0 -28
- package/core/store/States.js +10 -0
- package/core/store/stac.js +3 -1
- package/core/types.d.ts +74 -46
- package/core/utils/eodashSTAC.js +164 -0
- package/core/utils/helpers.js +40 -0
- package/core/utils/index.js +28 -0
- package/core/views/Dashboard.vue +8 -2
- package/core/vite-env.d.ts +12 -10
- package/package.json +8 -3
- package/widgets/EodashDatePicker.vue +51 -0
- package/widgets/EodashItemFilter.vue +60 -0
- package/widgets/EodashMap.vue +72 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { Collection, Item } from 'stac-js';
|
|
2
|
+
import { toAbsolute } from 'stac-js/src/http.js';
|
|
3
|
+
import { generateFeatures } from './helpers'
|
|
4
|
+
|
|
5
|
+
export class EodashCollection {
|
|
6
|
+
/** @type {string | undefined} */
|
|
7
|
+
#collectionUrl = undefined;
|
|
8
|
+
#collectionStac = undefined;
|
|
9
|
+
/** @type {*} */
|
|
10
|
+
selectedItem = null;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {string} collectionUrl
|
|
14
|
+
*/
|
|
15
|
+
constructor(collectionUrl) {
|
|
16
|
+
this.#collectionUrl = collectionUrl;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* @param {*} item
|
|
20
|
+
* @returns
|
|
21
|
+
* @async
|
|
22
|
+
*/
|
|
23
|
+
createLayersJson = async (item = null) => {
|
|
24
|
+
let stacItem, stac;
|
|
25
|
+
// TODO get auxiliary layers from collection
|
|
26
|
+
let layersJson = [
|
|
27
|
+
{
|
|
28
|
+
type: 'Tile',
|
|
29
|
+
properties: {
|
|
30
|
+
id: 'OSM',
|
|
31
|
+
},
|
|
32
|
+
source: {
|
|
33
|
+
type: 'OSM',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
// Load collectionstac if not yet initialized
|
|
38
|
+
if (!this.#collectionStac) {
|
|
39
|
+
//@ts-expect-error
|
|
40
|
+
const response = await fetch(this.#collectionUrl);
|
|
41
|
+
stac = await response.json();
|
|
42
|
+
this.#collectionStac = new Collection(stac);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if(stac && stac.endpointtype === "GeoDB") {
|
|
46
|
+
// Special handling of point based data
|
|
47
|
+
const allFeatures = generateFeatures(stac.links);
|
|
48
|
+
layersJson.unshift({
|
|
49
|
+
type: "Vector",
|
|
50
|
+
properties: {
|
|
51
|
+
id: stac.id,
|
|
52
|
+
},
|
|
53
|
+
source: {
|
|
54
|
+
type: "Vector",
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
url: "data:," + encodeURIComponent(JSON.stringify(allFeatures)),
|
|
57
|
+
format: "GeoJSON",
|
|
58
|
+
},
|
|
59
|
+
style: {
|
|
60
|
+
"circle-radius": 5,
|
|
61
|
+
"circle-fill-color": "#00417077",
|
|
62
|
+
"circle-stroke-color": "#004170",
|
|
63
|
+
"fill-color": "#00417077",
|
|
64
|
+
"stroke-color": "#004170",
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
return layersJson;
|
|
68
|
+
} else {
|
|
69
|
+
if (item instanceof Date) {
|
|
70
|
+
// if collectionStac not yet initialized we do it here
|
|
71
|
+
stacItem = this.getItems().sort((a, b) => {
|
|
72
|
+
//@ts-expect-error
|
|
73
|
+
const distanceA = Math.abs(new Date(a.datetime) - item);
|
|
74
|
+
//@ts-expect-error
|
|
75
|
+
const distanceB = Math.abs(new Date(b.datetime) - item);
|
|
76
|
+
return distanceA - distanceB;
|
|
77
|
+
})[0];
|
|
78
|
+
this.selectedItem = stacItem;
|
|
79
|
+
} else {
|
|
80
|
+
stacItem = item;
|
|
81
|
+
}
|
|
82
|
+
const response = await fetch(
|
|
83
|
+
stacItem
|
|
84
|
+
? toAbsolute(stacItem.href, this.#collectionUrl)
|
|
85
|
+
: this.#collectionUrl
|
|
86
|
+
);
|
|
87
|
+
stac = await response.json();
|
|
88
|
+
|
|
89
|
+
if (!stacItem) {
|
|
90
|
+
// no specific item was requested; render last item
|
|
91
|
+
this.#collectionStac = new Collection(stac);
|
|
92
|
+
const items = this.getItems();
|
|
93
|
+
this.selectedItem = items[items.length - 1];
|
|
94
|
+
layersJson = await this.createLayersJson(this.selectedItem);
|
|
95
|
+
return layersJson;
|
|
96
|
+
} else {
|
|
97
|
+
// specific item was requested
|
|
98
|
+
const item = new Item(stac);
|
|
99
|
+
this.selectedItem = item;
|
|
100
|
+
//@ts-expect-error
|
|
101
|
+
layersJson.unshift(this.buildJson(item));
|
|
102
|
+
return layersJson;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @param {*} item
|
|
109
|
+
*/
|
|
110
|
+
buildJson(item) {
|
|
111
|
+
let json;
|
|
112
|
+
// TODO implement other types, such as COG
|
|
113
|
+
if (/** @type {import('stac-ts').StacLink[]} */(item.links)
|
|
114
|
+
.find((l) => l.rel === 'wms' || l.rel === 'wmts' || l.rel === 'xyz')) {
|
|
115
|
+
json = {
|
|
116
|
+
type: 'STAC',
|
|
117
|
+
displayWebMapLink: true,
|
|
118
|
+
displayFootprint: false,
|
|
119
|
+
data: item,
|
|
120
|
+
properties: {
|
|
121
|
+
id: item.id,
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
} else {
|
|
125
|
+
// fall back to rendering the feature
|
|
126
|
+
json = {
|
|
127
|
+
type: 'Vector',
|
|
128
|
+
source: {
|
|
129
|
+
type: 'Vector',
|
|
130
|
+
url: 'data:,' + encodeURIComponent(JSON.stringify(item.geometry)),
|
|
131
|
+
format: 'GeoJSON',
|
|
132
|
+
},
|
|
133
|
+
properties: {
|
|
134
|
+
id: item.id,
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return json;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
getItems() {
|
|
143
|
+
return (
|
|
144
|
+
//@ts-expect-error
|
|
145
|
+
// eslint-disable-next-line
|
|
146
|
+
/** @type {import('stac-ts').StacLink[]}*/(this.#collectionStac?.links)
|
|
147
|
+
.filter((i) => i.rel === 'item')
|
|
148
|
+
// sort by `datetime`, where oldest is first in array
|
|
149
|
+
.sort((a, b) => ( /** @type {number} */(a.datetime) < /** @type {number} */(b.datetime) ? -1 : 1))
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
getDates() {
|
|
154
|
+
return (
|
|
155
|
+
//@ts-expect-error
|
|
156
|
+
// eslint-disable-next-line
|
|
157
|
+
/** @type {import('stac-ts').StacLink[]}*/ (this.#collectionStac?.links)
|
|
158
|
+
.filter((i) => i.rel === 'item')
|
|
159
|
+
// sort by `datetime`, where oldest is first in array
|
|
160
|
+
.sort((a, b) => ( /** @type {number} */(a.datetime) < /** @type {number} */(b.datetime) ? -1 : 1))
|
|
161
|
+
.map((i) => new Date( /** @type {number} */(i.datetime)))
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @param {import("stac-ts").StacLink[]} links
|
|
4
|
+
*/
|
|
5
|
+
export function generateFeatures(links) {
|
|
6
|
+
/**
|
|
7
|
+
* @type {{
|
|
8
|
+
* type:string;
|
|
9
|
+
* geometry:{
|
|
10
|
+
* type: string;
|
|
11
|
+
* coordinates: [number, number],
|
|
12
|
+
* }
|
|
13
|
+
* }[]}
|
|
14
|
+
*/
|
|
15
|
+
const features = [];
|
|
16
|
+
links.forEach(element => {
|
|
17
|
+
if (element.rel === "item" && "latlng" in element) {
|
|
18
|
+
//@ts-expect-error
|
|
19
|
+
const [lat, lon] = element.latlng.split(",").map((/** @type {string} */it) => Number(it))
|
|
20
|
+
features.push({
|
|
21
|
+
type: 'Feature',
|
|
22
|
+
geometry: {
|
|
23
|
+
type: 'Point',
|
|
24
|
+
coordinates: [lon, lat],
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
const geojsonObject = {
|
|
30
|
+
'type': 'FeatureCollection',
|
|
31
|
+
'crs': {
|
|
32
|
+
'type': 'name',
|
|
33
|
+
'properties': {
|
|
34
|
+
'name': 'EPSG:4326',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
features,
|
|
38
|
+
};
|
|
39
|
+
return geojsonObject;
|
|
40
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* loads font in the app using `webfontloader`
|
|
3
|
+
* @param {string} [family="Roboto"]
|
|
4
|
+
* @param {string} [link]
|
|
5
|
+
* @returns {Promise<string>} - font family name
|
|
6
|
+
* @see {@link "https://github.com/typekit/webfontloader "}
|
|
7
|
+
*/
|
|
8
|
+
export const loadFont = async (family = "Roboto", link) => {
|
|
9
|
+
const WebFontLoader = (await import('webfontloader')).default;
|
|
10
|
+
if (link) {
|
|
11
|
+
WebFontLoader.load({
|
|
12
|
+
custom: {
|
|
13
|
+
// Use FVD notation to include families https://github.com/typekit/fvd
|
|
14
|
+
families: [family],
|
|
15
|
+
// Path to stylesheet that defines font-face
|
|
16
|
+
urls: [link],
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
WebFontLoader.load({
|
|
22
|
+
google: {
|
|
23
|
+
families: [family]
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return family;
|
|
28
|
+
};
|
package/core/views/Dashboard.vue
CHANGED
|
@@ -6,16 +6,18 @@
|
|
|
6
6
|
|
|
7
7
|
<script setup>
|
|
8
8
|
import { useEodashRuntime } from "@/composables/DefineEodash";
|
|
9
|
-
import { useUpdateTheme } from "@/composables";
|
|
9
|
+
import { useRouteParams, useUpdateTheme } from "@/composables";
|
|
10
10
|
import { useSTAcStore } from '@/store/stac';
|
|
11
11
|
import { defineAsyncComponent } from "vue";
|
|
12
12
|
import { useDisplay, useLayout } from "vuetify/lib/framework.mjs";
|
|
13
|
-
import { loadFont } from '@/
|
|
13
|
+
import { loadFont } from '@/utils'
|
|
14
14
|
import { useSeoMeta } from "@unhead/vue"
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
const eodash = await useEodashRuntime()
|
|
18
18
|
|
|
19
|
+
useRouteParams()
|
|
20
|
+
|
|
19
21
|
const theme = useUpdateTheme('dashboardTheme', eodash.brand?.theme)
|
|
20
22
|
theme.global.name.value = 'dashboardTheme'
|
|
21
23
|
|
|
@@ -36,6 +38,10 @@ useSeoMeta(eodash.brand.meta ?? {})
|
|
|
36
38
|
</script>
|
|
37
39
|
|
|
38
40
|
<style scoped lang="scss">
|
|
41
|
+
html {
|
|
42
|
+
overflow: hidden;
|
|
43
|
+
}
|
|
44
|
+
|
|
39
45
|
* {
|
|
40
46
|
font-family: v-bind('fontFamily');
|
|
41
47
|
}
|
package/core/vite-env.d.ts
CHANGED
|
@@ -11,19 +11,21 @@ declare interface Window {
|
|
|
11
11
|
declare module '@eox/stacinfo' {
|
|
12
12
|
export const EOxStacInfo: CustomElementConstructor
|
|
13
13
|
}
|
|
14
|
+
declare module '@eox/map' {
|
|
15
|
+
export const EOxMap: CustomElementConstructor
|
|
16
|
+
}
|
|
17
|
+
declare module '@eox/itemfilter' {
|
|
18
|
+
export const EOxItemFilter: CustomElementConstructor
|
|
19
|
+
}
|
|
14
20
|
declare module 'user:config' {
|
|
15
21
|
const eodash: import("@/types").Eodash | Promise<import("@/types").Eodash>;
|
|
16
22
|
export default eodash
|
|
17
23
|
}
|
|
18
|
-
declare module
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
declare module '@eox/layercontrol' {
|
|
22
|
-
export const EOxLayerControl: CustomElementConstructor
|
|
23
|
-
}
|
|
24
|
-
declare module '@eox/timecontrol' {
|
|
25
|
-
export const EOxTimeControl: CustomElementConstructor
|
|
24
|
+
declare module "stac-js" {
|
|
25
|
+
const STAC: any, Collection: any, Item: any
|
|
26
|
+
export { STAC, Collection, Item }
|
|
26
27
|
}
|
|
27
|
-
declare module
|
|
28
|
-
|
|
28
|
+
declare module "stac-js/src/http.js" {
|
|
29
|
+
const toAbsolute: any
|
|
30
|
+
export { toAbsolute }
|
|
29
31
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eodash/eodash",
|
|
3
|
-
"version": "5.0.0-alpha.1.
|
|
3
|
+
"version": "5.0.0-alpha.1.15",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"types": "./core/types.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -24,22 +24,27 @@
|
|
|
24
24
|
"preview": "vite preview",
|
|
25
25
|
"lint": "eslint . --fix",
|
|
26
26
|
"docs:generate": "typedoc --options typedoc.config.json",
|
|
27
|
-
"docs:dev": "vitepress dev docs",
|
|
27
|
+
"docs:dev": "vitepress dev docs --port 3333",
|
|
28
28
|
"docs:build": "npm run docs:generate && vitepress build docs",
|
|
29
29
|
"docs:preview": "vitepress preview docs"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
+
"@eox/itemfilter": "^0.14.0",
|
|
32
33
|
"@eox/layout": "^0.1.0",
|
|
34
|
+
"@eox/map": "^1.4.0",
|
|
33
35
|
"@eox/stacinfo": "^0.3.0",
|
|
34
36
|
"@mdi/font": "7.0.96",
|
|
35
37
|
"@unhead/vue": "^1.8.20",
|
|
36
38
|
"@vitejs/plugin-vue": "^5.0.0",
|
|
39
|
+
"@web-comp/core": "^1.0.2",
|
|
40
|
+
"@web-comp/date-picker": "^1.0.8",
|
|
37
41
|
"animated-details": "gist:2912bb049fa906671807415eb0e87188",
|
|
38
42
|
"axios": "^1.6.2",
|
|
39
43
|
"commander": "^12.0.0",
|
|
40
44
|
"core-js": "^3.29.0",
|
|
41
45
|
"pinia": "^2.0.0",
|
|
42
46
|
"sass": "^1.60.0",
|
|
47
|
+
"stac-js": "^0.0.9",
|
|
43
48
|
"stac-ts": "^1.0.3",
|
|
44
49
|
"vite": "^5.1.5",
|
|
45
50
|
"vite-plugin-vuetify": "^2.0.0",
|
|
@@ -68,4 +73,4 @@
|
|
|
68
73
|
"bin": {
|
|
69
74
|
"eodash": "./bin/app.js"
|
|
70
75
|
}
|
|
71
|
-
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<span class="fill-height fill-width align-center justify-center">
|
|
3
|
+
<div v-if="inline" class="fill-height fill-width">
|
|
4
|
+
|
|
5
|
+
<v-text-field base-color="primary" class="fill-height fill-width pa-2 align-center" type="date" bg-color="surface"
|
|
6
|
+
color="primary" density="comfortable" label="Select Date" v-model="currentDate" variant="plain" hide-details />
|
|
7
|
+
</div>
|
|
8
|
+
<v-date-picker v-else ref="datePicker" :width="width" :height="height" hide-header v-model="currentDate"
|
|
9
|
+
color="primary" bg-color="surface" location="center" class="overflow-auto fill-height fill-width"
|
|
10
|
+
position="relative" show-adjacent-months></v-date-picker>
|
|
11
|
+
</span>
|
|
12
|
+
</template>
|
|
13
|
+
<script setup>
|
|
14
|
+
import { computed, ref, onMounted } from "vue";
|
|
15
|
+
import { datetime } from "@/store/States"
|
|
16
|
+
|
|
17
|
+
const props = defineProps(["inline"])
|
|
18
|
+
|
|
19
|
+
const currentDate = computed({
|
|
20
|
+
get() {
|
|
21
|
+
return props.inline ? datetime.value.split("T")[0] : new Date(datetime.value) ?? new Date()
|
|
22
|
+
},
|
|
23
|
+
/** @param {Date | string} updatedDate */
|
|
24
|
+
set(updatedDate) {
|
|
25
|
+
if (props.inline) {
|
|
26
|
+
updatedDate = new Date(updatedDate);
|
|
27
|
+
}
|
|
28
|
+
//@ts-expect-error
|
|
29
|
+
if (updatedDate instanceof Date && !isNaN(updatedDate)) {
|
|
30
|
+
datetime.value = updatedDate.toISOString()
|
|
31
|
+
} else {
|
|
32
|
+
datetime.value = new Date().toISOString()
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @type {import("vue").Ref<import("vuetify/components").VDatePicker | null>}
|
|
39
|
+
**/
|
|
40
|
+
const datePicker = ref(null)
|
|
41
|
+
/** @type {import("vue").Ref<string|undefined>} */
|
|
42
|
+
const width = ref()
|
|
43
|
+
/** @type {import("vue").Ref<string|undefined>} */
|
|
44
|
+
const height = ref()
|
|
45
|
+
onMounted(() => {
|
|
46
|
+
/** @type {HTMLElement} */
|
|
47
|
+
const parentEl = datePicker.value?.$el.parentElement?.parentElement
|
|
48
|
+
width.value = parentEl?.clientWidth ? parentEl.clientWidth + "px" : undefined
|
|
49
|
+
height.value = parentEl?.clientHeight ? parentEl.clientHeight + "px" : undefined
|
|
50
|
+
})
|
|
51
|
+
</script>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<DynamicWebComponent :link="link" tag-name="eox-itemfilter" :properties="properties" :on-mounted="onMounted" />
|
|
3
|
+
</template>
|
|
4
|
+
<script setup>
|
|
5
|
+
import DynamicWebComponent from "@/components/DynamicWebComponent.vue";
|
|
6
|
+
|
|
7
|
+
const link = () => import("@eox/itemfilter");
|
|
8
|
+
|
|
9
|
+
const properties = {
|
|
10
|
+
config: {
|
|
11
|
+
titleProperty: "title",
|
|
12
|
+
filterProperties: [
|
|
13
|
+
{
|
|
14
|
+
keys: ["title", "themes"],
|
|
15
|
+
title: "Search",
|
|
16
|
+
type: "text",
|
|
17
|
+
expanded: true,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
key: "themes",
|
|
21
|
+
title: "Theme",
|
|
22
|
+
type: "multiselect",
|
|
23
|
+
featured: true,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
aggregateResults: "themes",
|
|
27
|
+
enableHighlighting: true,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/** @type {import("../core/types").WebComponentProps["onMounted"]}*/
|
|
32
|
+
const onMounted = (el, store, router) => {
|
|
33
|
+
/**
|
|
34
|
+
* @typedef {object} Item
|
|
35
|
+
* @property {string} href
|
|
36
|
+
* */
|
|
37
|
+
/** @type {any} */ (el).apply(
|
|
38
|
+
// Only list child elements in list
|
|
39
|
+
store.stac?.filter((item) => item.rel === "child")
|
|
40
|
+
);
|
|
41
|
+
// Check if indicator is selected
|
|
42
|
+
const { query } = router.currentRoute.value;
|
|
43
|
+
if ("indicator" in query) {
|
|
44
|
+
const match = store.stac?.find((item) => item.id === query.indicator);
|
|
45
|
+
if (match) {
|
|
46
|
+
//@ts-expect-error
|
|
47
|
+
(el).selectedResult = match;
|
|
48
|
+
store.loadSelectedSTAC(match.href);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** @type {any} */ (el).config.onSelect =
|
|
52
|
+
/**
|
|
53
|
+
* @param {Item} item
|
|
54
|
+
* */
|
|
55
|
+
async (item) => {
|
|
56
|
+
console.log(item);
|
|
57
|
+
await store.loadSelectedSTAC(item.href);
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
</script>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<DynamicWebComponent :link="link" tag-name="eox-map" :properties="properties" :on-mounted="onMounted"
|
|
3
|
+
:on-unmounted="onUnmounted" />
|
|
4
|
+
</template>
|
|
5
|
+
<script setup>
|
|
6
|
+
import { inject, watch } from "vue";
|
|
7
|
+
import { toAbsolute } from "stac-js/src/http.js";
|
|
8
|
+
import { EodashCollection } from "@/utils/eodashSTAC";
|
|
9
|
+
import { eodashKey } from "@/store/Keys";
|
|
10
|
+
import { mapInstance, datetime } from "@/store/States";
|
|
11
|
+
import DynamicWebComponent from "@/components/DynamicWebComponent.vue";
|
|
12
|
+
import { storeToRefs } from "pinia";
|
|
13
|
+
import { useRouter } from "vue-router";
|
|
14
|
+
import "@eox/map/dist/eox-map-advanced-layers-and-sources.js";
|
|
15
|
+
|
|
16
|
+
const eodashConfig = /** @type {import("@/types").Eodash} */ inject(eodashKey);
|
|
17
|
+
|
|
18
|
+
const properties = {
|
|
19
|
+
class: "fill-height fill-width overflow-none",
|
|
20
|
+
center: [15, 48],
|
|
21
|
+
layers: [{ type: "Tile", source: { type: "OSM" } }],
|
|
22
|
+
};
|
|
23
|
+
const router = useRouter();
|
|
24
|
+
const { query } = router.currentRoute.value;
|
|
25
|
+
if ("x" in query && "y" in query) {
|
|
26
|
+
properties.center = [Number(query.x), Number(query.y)];
|
|
27
|
+
}
|
|
28
|
+
if ("z" in query) {
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
properties.zoom = query.z;
|
|
31
|
+
}
|
|
32
|
+
const link = () => import("@eox/map");
|
|
33
|
+
|
|
34
|
+
/** @type {import("openlayers").EventsListenerFunctionType}*/
|
|
35
|
+
let handleMoveEnd;
|
|
36
|
+
|
|
37
|
+
/** @type {import("@/types").WebComponentProps["onMounted"]} */
|
|
38
|
+
const onMounted = (el, store, _router) => {
|
|
39
|
+
mapInstance.value = /** @type {any} */ (el).map;
|
|
40
|
+
|
|
41
|
+
const { selectedStac } = storeToRefs(store);
|
|
42
|
+
|
|
43
|
+
watch(
|
|
44
|
+
[selectedStac, datetime],
|
|
45
|
+
async ([updatedStac, updatedTime]) => {
|
|
46
|
+
if (updatedStac) {
|
|
47
|
+
const parentCollUrl = toAbsolute(
|
|
48
|
+
`./${updatedStac.id}/collection.json`,
|
|
49
|
+
eodashConfig.stacEndpoint
|
|
50
|
+
);
|
|
51
|
+
const childCollUrl = toAbsolute(
|
|
52
|
+
updatedStac.links[1].href,
|
|
53
|
+
parentCollUrl
|
|
54
|
+
);
|
|
55
|
+
const eodash = new EodashCollection(childCollUrl);
|
|
56
|
+
if (updatedTime) {
|
|
57
|
+
/** @type {any} */ (el).layers = await eodash.createLayersJson(
|
|
58
|
+
new Date(updatedTime)
|
|
59
|
+
);
|
|
60
|
+
} else {
|
|
61
|
+
/** @type {any} */ (el).layers = await eodash.createLayersJson();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{ immediate: true }
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
/** @type {import("@/types").WebComponentProps["onUnmounted"]} */
|
|
69
|
+
const onUnmounted = (_el, _store, _router) => {
|
|
70
|
+
mapInstance.value?.un("moveend", handleMoveEnd);
|
|
71
|
+
};
|
|
72
|
+
</script>
|