@eodash/eodash 5.0.0-alpha.1.13 → 5.0.0-alpha.1.14

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.
@@ -9,7 +9,8 @@ import {
9
9
  cachePath, publicPath, userConfig,
10
10
  buildTargetPath,
11
11
  logger,
12
- rootPath
12
+ rootPath,
13
+ internalWidgetsPath
13
14
  } from "./utils.js";
14
15
  import { readFile } from "fs/promises";
15
16
  import { defineConfig, searchForWorkspaceRoot } from "vite"
@@ -61,7 +62,8 @@ export const serverConfig = /** @type {import('vite').UserConfigFnPromise}*/(def
61
62
  alias: {
62
63
  '@': fileURLToPath(new URL('../core', import.meta.url)),
63
64
  '^': fileURLToPath(new URL('../widgets', import.meta.url)),
64
- "user:config": entryPath
65
+ "user:config": entryPath,
66
+ "user:widgets": internalWidgetsPath
65
67
  },
66
68
  extensions: ['.js', '.json', '.jsx', '.mjs', '.ts', '.tsx', '.vue'],
67
69
  },
@@ -78,7 +80,7 @@ export const serverConfig = /** @type {import('vite').UserConfigFnPromise}*/(def
78
80
  },
79
81
  root: fileURLToPath(new URL('..', import.meta.url)),
80
82
  optimizeDeps: mode === "development" ? {
81
- include: ["webfontloader", "vuetify", "vue", "pinia"],
83
+ include: ["webfontloader", "vuetify", "vue", "pinia", "stac-js", "urijs"],
82
84
  noDiscovery: true,
83
85
  } : {},
84
86
  /** @type {string|false} */
@@ -100,7 +102,7 @@ export const serverConfig = /** @type {import('vite').UserConfigFnPromise}*/(def
100
102
  * @type {import("vite").ServerHook}
101
103
  */
102
104
  async function configureServer(server) {
103
- server.watcher.add([entryPath, runtimeConfigPath])
105
+ server.watcher.add([entryPath, runtimeConfigPath, path.join(internalWidgetsPath, "**/*.vue")])
104
106
 
105
107
  let updatedPath = ''
106
108
  const loggerInfo = logger.info
package/bin/utils.js CHANGED
@@ -21,6 +21,7 @@ const pkg = JSON.parse(
21
21
  * @property {string | false} publicDir
22
22
  * @property {string} outDir
23
23
  * @property {string} entryPoint
24
+ * @property {string} widgets
24
25
  * @property {string} cacheDir
25
26
  * @property {string} runtime
26
27
  * @property {string} base
@@ -33,7 +34,8 @@ cli.version(pkg.version, '-v, --version', 'output the current version')
33
34
  .option('--publicDir <path>', 'path to statically served assets folder')
34
35
  .option('--no-publicDir', 'stop serving static assets')
35
36
  .option('--outDir <path>', 'minified output folder')
36
- .option('-e, --entryPoint <path>', 'file exporting `defineConfig`')
37
+ .option('-e, --entryPoint <path>', 'file exporting `createEodash`')
38
+ .option('-w, --widgets <path>', 'folder that contains vue components as internal widgets')
37
39
  .option('--cacheDir <path>', 'cache folder')
38
40
  .option('-r, --runtime <path>', 'file exporting eodash client runtime config')
39
41
  .option('-b, --base <path>', 'base public path')
@@ -52,6 +54,7 @@ export const appPath = fileURLToPath(new URL("..", import.meta.url)),
52
54
  srcPath = path.join(rootPath, "/src"),
53
55
  runtimeConfigPath = userConfig.runtime ? path.resolve(rootPath, userConfig.runtime) : path.join(srcPath, "./runtime.js"),
54
56
  entryPath = userConfig.entryPoint ? path.resolve(rootPath, userConfig.entryPoint) : path.join(srcPath, "/main.js"),
57
+ internalWidgetsPath = userConfig.widgets ? path.resolve(rootPath, userConfig.widgets) : path.join(srcPath, "widgets"),
55
58
  dotEodashPath = path.join(rootPath, "/.eodash"),
56
59
  buildTargetPath = userConfig.outDir ? path.resolve(rootPath, userConfig.outDir) : path.join(dotEodashPath, '/dist'),
57
60
  cachePath = userConfig.cacheDir ? path.resolve(rootPath, userConfig.cacheDir) : path.join(dotEodashPath, 'cache');
@@ -84,6 +87,7 @@ async function getUserConfig(options, command) {
84
87
  entryPoint: options.entryPoint ?? config?.entryPoint,
85
88
  outDir: options.outDir ?? config?.outDir,
86
89
  publicDir: options.publicDir ?? config?.publicDir,
87
- runtime: options.runtime ?? config?.runtime
90
+ runtime: options.runtime ?? config?.runtime,
91
+ widgets: options.widgets ?? config?.widgets
88
92
  }
89
93
  }
@@ -2,8 +2,6 @@ import { defineAsyncComponent, reactive, shallowRef, watch } from 'vue'
2
2
  import { useSTAcStore } from '@/store/stac'
3
3
  import { storeToRefs } from 'pinia'
4
4
 
5
-
6
-
7
5
  /**
8
6
  * @typedef {{
9
7
  * component:import('vue').Component | null;
@@ -17,14 +15,24 @@ import { storeToRefs } from 'pinia'
17
15
  * @typedef {import('vue').ShallowRef<DefinedWidget>} ReactiveDefinedWidget
18
16
  */
19
17
 
18
+ const internalWidgets = (() => {
19
+ /**
20
+ * @type {Record<string,() => Promise<import('vue').Component>>}
21
+ */
22
+ const importMap = {
23
+ ...import.meta.glob('^/**/*.vue'),
24
+ ...import.meta.glob("user:widgets/**/*.vue")
25
+ }
26
+ for (const key in importMap) {
27
+ const newKey = /** @type {string} */(key.split('/').at(-1)).slice(0, -4)
28
+ Object.defineProperty(importMap, newKey,
29
+ /** @type {PropertyDescriptor} */(Object.getOwnPropertyDescriptor(importMap, key)));
30
+ delete importMap[key];
31
+ }
32
+ return importMap
33
+ })();
20
34
 
21
35
 
22
- /**
23
- * import map to all vue components inside `widgets` directory.
24
- * @type {Record<string,() => Promise<import('vue').Component>>}
25
- */
26
- const internalWidgets = import.meta.glob('^/**/*.vue')
27
-
28
36
  /**
29
37
  * Composable that converts widgets Configurations to defined imported widgets
30
38
  * @param { (import("@/types").Widget | import("@/types").BackgroundWidget | undefined)[] |
@@ -46,7 +54,6 @@ export const useDefineWidgets = (widgetConfigs) => {
46
54
  props: {},
47
55
  title: '',
48
56
  id: Symbol(),
49
- no: '4'
50
57
  })
51
58
 
52
59
  if ('defineWidget' in (config ?? {})) {
@@ -84,7 +91,7 @@ const getWidgetDefinition = (config) => {
84
91
  switch (config?.type) {
85
92
  case 'internal':
86
93
  importedWidget.component = defineAsyncComponent({
87
- loader: internalWidgets[`/widgets/${/** @type {import("@/types").InternalComponentWidget} **/(config)?.widget.name}.vue`],
94
+ loader: internalWidgets[/** @type {import("@/types").InternalComponentWidget} **/(config)?.widget.name],
88
95
  suspensible: true
89
96
  })
90
97
  importedWidget.props = reactive(/** @type {import("@/types").InternalComponentWidget} **/(config)?.widget.props ?? {})
@@ -2,10 +2,11 @@
2
2
  // setup functions or vue composition api components
3
3
 
4
4
  import { reactive } from "vue"
5
- import { currentUrl } from "@/store/States"
5
+ import { currentUrl, datetime, mapInstance, indicator } from "@/store/States"
6
6
  import eodashConfig from "@/eodash"
7
7
  import { useTheme } from "vuetify/lib/framework.mjs"
8
-
8
+ import { useRouter } from "vue-router"
9
+ import { onMounted, onUnmounted, watch } from "vue"
9
10
 
10
11
  /**
11
12
  * Creates an absolute URL from a relative link and assignes it to `currentUrl`
@@ -145,3 +146,50 @@ export const useUpdateTheme = (themeName, themeDefinition = {}) => {
145
146
  })
146
147
  return theme
147
148
  }
149
+
150
+
151
+ /**
152
+ * Composable that initiates route query params to store
153
+ * STAC related values
154
+ */
155
+ export const useRouteParams = () => {
156
+ const router = useRouter()
157
+ /**
158
+ * @type {import("openlayers").EventsListenerFunctionType}
159
+ */
160
+ const handleMoveEnd = (evt) => {
161
+ const map = /** @type {import("openlayers").Map | undefined} */ (/** @type {*} */ (evt).map)
162
+ const [x, y] = map?.getView().getCenter() ?? [0, 0]
163
+ const z = map?.getView().getZoom()
164
+ const currentQuery = router.currentRoute.value.query
165
+ router.push({
166
+ query: {
167
+ ...currentQuery,
168
+ x, y, z
169
+ }
170
+ })
171
+
172
+ }
173
+ onMounted(() => {
174
+ watch([datetime, mapInstance, currentUrl, indicator], ([updatedDate, updatedMap, updatedUrl, updatedIndicator]) => {
175
+ const [x, y] = updatedMap?.getView().getCenter() ?? [0, 0]
176
+ const currentQuery = router.currentRoute.value.query
177
+ router.push({
178
+ query: {
179
+ ...currentQuery,
180
+ indicator: updatedIndicator,
181
+ x,
182
+ y,
183
+ z: updatedMap?.getView().getZoom(),
184
+ datetime: updatedDate,
185
+ url: updatedUrl,
186
+ }
187
+ })
188
+ updatedMap?.on("moveend", handleMoveEnd)
189
+ })
190
+ })
191
+
192
+ onUnmounted(() => {
193
+ mapInstance.value?.un("moveend", handleMoveEnd)
194
+ })
195
+ }
package/core/eodash.js CHANGED
@@ -1,9 +1,5 @@
1
1
  import { reactive } from "vue";
2
- import { currentUrl, mapInstance } from './store/States';
3
- /**
4
- * @type {Function | null}
5
- */
6
- let handleMoveEnd = null;
2
+ import { currentUrl } from './store/States';
7
3
 
8
4
  /**
9
5
  * Reactive Edoash Instance Object. provided globally in the app,
@@ -31,34 +27,10 @@ const eodash = reactive({
31
27
  template: {
32
28
  background: {
33
29
  id: Symbol(),
30
+ type: "internal",
34
31
  widget: {
35
- link: 'https://cdn.skypack.dev/@eox/map',
36
- properties: {
37
- class: "fill-height fill-width overflow-none",
38
- center: [15, 48],
39
- layers: [{ type: "Tile", source: { type: "OSM" } }],
40
- },
41
- tagName: 'eox-map',
42
- onMounted(el, _, router) {
43
- /** @type {any} */(el).zoom = router.currentRoute.value.query['z'];
44
-
45
- mapInstance.value = /** @type {any} */(el).map;
46
-
47
- mapInstance.value?.on('moveend', handleMoveEnd =
48
- /** @param {any} evt */(evt) => {
49
- router.push({
50
- query: {
51
- z: `${evt.map.getView().getZoom()}`
52
- }
53
- });
54
- });
55
- },
56
- onUnmounted(_el, _store, _router) {
57
- //@ts-expect-error
58
- mapInstance.value?.un('moveend', handleMoveEnd);
59
- }
60
- },
61
- type: 'web-component'
32
+ name: 'EodashMap'
33
+ }
62
34
  },
63
35
  widgets: [
64
36
  {
package/core/main.js CHANGED
@@ -1,4 +1,2 @@
1
- // Plugins
2
1
  export { createEodash } from '@/composables/DefineEodash';
3
-
4
-
2
+ export { default as store } from "@/store"
@@ -1,28 +0,0 @@
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
- };
@@ -10,3 +10,13 @@ export const currentUrl = ref('');
10
10
  * @type {import("vue").Ref<import('openlayers').Map | null>}
11
11
  */
12
12
  export const mapInstance = ref(null);
13
+
14
+ /**
15
+ * currently selected datetime
16
+ */
17
+ export const datetime = ref(new Date().toISOString());
18
+
19
+ /**
20
+ * Currently selected indicator
21
+ */
22
+ export const indicator = ref("")
@@ -3,6 +3,7 @@ import { inject, ref } from 'vue';
3
3
  import axios from 'axios';
4
4
  import { useAbsoluteUrl } from '@/composables/index';
5
5
  import { eodashKey } from '@/store/Keys';
6
+ import { assignIndicator } from '@/utils';
6
7
 
7
8
  export const useSTAcStore = defineStore('stac', () => {
8
9
  /**
@@ -14,7 +15,7 @@ export const useSTAcStore = defineStore('stac', () => {
14
15
  /**
15
16
  * selected STAC object.
16
17
  * @type {import('vue').Ref<import('stac-ts').StacCatalog |
17
- * import('stac-ts').StacCollection |import('stac-ts').StacItem
18
+ * import('stac-ts').StacCollection |import('stac-ts').StacItem
18
19
  * | null>}
19
20
  */
20
21
  const selectedStac = ref(null);
@@ -54,6 +55,7 @@ export const useSTAcStore = defineStore('stac', () => {
54
55
 
55
56
  await axios.get(absoluteUrl.value).then(resp => {
56
57
  selectedStac.value = resp.data;
58
+ assignIndicator(selectedStac.value)
57
59
  }).catch(err => console.error(err));
58
60
  }
59
61
 
package/core/types.d.ts CHANGED
@@ -323,10 +323,16 @@ export interface EodashStore {
323
323
  * OpenLayers map instance
324
324
  */
325
325
  mapInstance: Ref<Map | null>
326
+ /**
327
+ * currently selected datetime
328
+ */
329
+ datetime: Ref<string>
330
+ /**
331
+ * Currently selected indicator
332
+ */
333
+ indicator: Ref<string>
326
334
  }
327
- actions: {
328
- loadFont: (family?: string, link?: string) => Promise<string>;
329
- };
335
+ actions: {};
330
336
  /**
331
337
  * Pinia store definition used to navigate the root STAC catalog.
332
338
  */
@@ -376,6 +382,7 @@ export interface EodashConfig {
376
382
  * file exporting eodash client runtime config
377
383
  */
378
384
  runtime?: string
385
+ widgets?: string
379
386
  }
380
387
  /**
381
388
  * project entry point should export this function as a default
@@ -383,4 +390,5 @@ export interface EodashConfig {
383
390
  *
384
391
  * @param configCallback
385
392
  */
386
- export declare const createEodash: (configCallback: (store: EodashStore) => Eodash | Promise<Eodash>) => Eodash
393
+ export declare const createEodash: (configCallback: (store: EodashStore) => Eodash | Promise<Eodash>) => Promise<Eodash>
394
+ export declare const store: EodashStore
@@ -0,0 +1,129 @@
1
+ import { Collection, Item } from 'stac-js';
2
+ import { toAbsolute } from 'stac-js/src/http.js';
3
+
4
+ export class EodashCollection {
5
+ /** @type {string | undefined} */
6
+ #collectionUrl = undefined;
7
+ #collectionStac = undefined;
8
+ /** @type {*} */
9
+ selectedItem = null;
10
+
11
+ /**
12
+ * @param {string} collectionUrl
13
+ */
14
+ constructor(collectionUrl) {
15
+ this.#collectionUrl = collectionUrl;
16
+ }
17
+ /**
18
+ * @param {*} item
19
+ * @returns
20
+ * @async
21
+ */
22
+ createLayersJson = async (item = null) => {
23
+ let stacItem;
24
+ if (item instanceof Date) {
25
+ // if collectionStac not yet initialized we do it here
26
+ if (!this.#collectionStac) {
27
+ const response = await fetch(this.#collectionUrl);
28
+ const stac = await response.json();
29
+ this.#collectionStac = new Collection(stac);
30
+ }
31
+ stacItem = this.getItems().sort((a, b) => {
32
+ //@ts-expect-error
33
+ const distanceA = Math.abs(new Date(a.datetime) - item);
34
+ //@ts-expect-error
35
+ const distanceB = Math.abs(new Date(b.datetime) - item);
36
+ return distanceA - distanceB;
37
+ })[0];
38
+ this.selectedItem = stacItem;
39
+ } else {
40
+ stacItem = item;
41
+ }
42
+ const response = await fetch(
43
+ stacItem
44
+ ? toAbsolute(stacItem.href, this.#collectionUrl)
45
+ : this.#collectionUrl
46
+ );
47
+ const stac = await response.json();
48
+
49
+ // TODO get auxiliary layers from collection
50
+ let layersJson = [
51
+ {
52
+ type: 'Tile',
53
+ properties: {
54
+ id: 'OSM',
55
+ },
56
+ source: {
57
+ type: 'OSM',
58
+ },
59
+ },
60
+ ];
61
+
62
+ if (!stacItem) {
63
+ // no specific item was requested; render last item
64
+ this.#collectionStac = new Collection(stac);
65
+ const items = this.getItems();
66
+ this.selectedItem = items[items.length - 1];
67
+ layersJson = await this.createLayersJson(this.selectedItem);
68
+ return layersJson;
69
+ } else {
70
+ // specific item was requested
71
+ const item = new Item(stac);
72
+ this.selectedItem = item;
73
+ //@ts-expect-error
74
+ layersJson.unshift(this.buildJson(item));
75
+ return layersJson;
76
+ }
77
+ }
78
+
79
+ /**
80
+ * @param {*} item
81
+ */
82
+ buildJson(item) {
83
+ let json;
84
+ // TODO implement other types, such as COG
85
+ if (/** @type {import('stac-ts').StacLink[]} */(item.links).find((l) => l.rel === 'wms' || l.rel === 'wmts')) {
86
+ json = {
87
+ type: 'STAC',
88
+ displayWebMapLink: true,
89
+ displayFootprint: false,
90
+ data: item,
91
+ };
92
+ } else {
93
+ // fall back to rendering the feature
94
+ json = {
95
+ type: 'Vector',
96
+ source: {
97
+ type: 'Vector',
98
+ url: 'data:,' + encodeURIComponent(JSON.stringify(item.geometry)),
99
+ format: 'GeoJSON',
100
+ },
101
+ };
102
+ }
103
+
104
+ return json;
105
+ }
106
+
107
+ getItems() {
108
+ return (
109
+ //@ts-expect-error
110
+ // eslint-disable-next-line
111
+ /** @type {import('stac-ts').StacLink[]}*/(this.#collectionStac?.links)
112
+ .filter((i) => i.rel === 'item')
113
+ // sort by `datetime`, where oldest is first in array
114
+ .sort((a, b) => ( /** @type {number} */(a.datetime) < /** @type {number} */(b.datetime) ? -1 : 1))
115
+ );
116
+ }
117
+
118
+ getDates() {
119
+ return (
120
+ //@ts-expect-error
121
+ // eslint-disable-next-line
122
+ /** @type {import('stac-ts').StacLink[]}*/ (this.#collectionStac?.links)
123
+ .filter((i) => i.rel === 'item')
124
+ // sort by `datetime`, where oldest is first in array
125
+ .sort((a, b) => ( /** @type {number} */(a.datetime) < /** @type {number} */(b.datetime) ? -1 : 1))
126
+ .map((i) => new Date( /** @type {number} */(i.datetime)))
127
+ );
128
+ }
129
+ }
@@ -0,0 +1,48 @@
1
+ import { indicator } from '@/store/States';
2
+
3
+ /**
4
+ * loads font in the app using `webfontloader`
5
+ * @param {string} [family="Roboto"]
6
+ * @param {string} [link]
7
+ * @returns {Promise<string>} - font family name
8
+ * @see {@link "https://github.com/typekit/webfontloader "}
9
+ */
10
+ export const loadFont = async (family = "Roboto", link) => {
11
+ const WebFontLoader = (await import('webfontloader')).default;
12
+ if (link) {
13
+ WebFontLoader.load({
14
+ custom: {
15
+ // Use FVD notation to include families https://github.com/typekit/fvd
16
+ families: [family],
17
+ // Path to stylesheet that defines font-face
18
+ urls: [link],
19
+ },
20
+ });
21
+ }
22
+ else {
23
+ WebFontLoader.load({
24
+ google: {
25
+ families: [family]
26
+ }
27
+ });
28
+ }
29
+ return family;
30
+ };
31
+
32
+
33
+ /**
34
+ * @param {import('stac-ts').StacCatalog | import('stac-ts').StacCollection | import('stac-ts').StacItem | null} selectedSTAC
35
+ * @see {@link indicator}
36
+ */
37
+ export const assignIndicator = (selectedSTAC) => {
38
+ const code = /** @type {string | undefined} */ (selectedSTAC?.code);
39
+ const subcode = /** @type {string | string[] | undefined} */ (selectedSTAC?.subcode);
40
+
41
+ if (selectedSTAC?.code || selectedSTAC?.subcode) {
42
+ indicator.value = code ? code :
43
+ Array.isArray(subcode) ? subcode[0] : subcode ?? ""
44
+ } else {
45
+ indicator.value = ""
46
+ }
47
+ console.log(indicator.value,/** @type {string} */(selectedSTAC?.code)),/** @type {string[]} */(selectedSTAC?.subcode)
48
+ }
@@ -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 '@/store/Actions'
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
  }
@@ -11,19 +11,18 @@ 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
+ }
14
17
  declare module 'user:config' {
15
18
  const eodash: import("@/types").Eodash | Promise<import("@/types").Eodash>;
16
19
  export default eodash
17
20
  }
18
- declare module '@eox/chart' {
19
- export const EOxChart: CustomElementConstructor
20
- }
21
- declare module '@eox/layercontrol' {
22
- export const EOxLayerControl: CustomElementConstructor
23
- }
24
- declare module '@eox/timecontrol' {
25
- export const EOxTimeControl: CustomElementConstructor
21
+ declare module "stac-js" {
22
+ const STAC: any, Collection: any, Item: any
23
+ export { STAC, Collection, Item }
26
24
  }
27
- declare module '@eox/jsonform' {
28
- export const EOxJSONForm: CustomElementConstructor
25
+ declare module "stac-js/src/http.js" {
26
+ const toAbsolute: any
27
+ export { toAbsolute }
29
28
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eodash/eodash",
3
- "version": "5.0.0-alpha.1.13",
3
+ "version": "5.0.0-alpha.1.14",
4
4
  "type": "module",
5
5
  "types": "./core/types.d.ts",
6
6
  "files": [
@@ -30,16 +30,20 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@eox/layout": "^0.1.0",
33
+ "@eox/map": "^1.4.0",
33
34
  "@eox/stacinfo": "^0.3.0",
34
35
  "@mdi/font": "7.0.96",
35
36
  "@unhead/vue": "^1.8.20",
36
37
  "@vitejs/plugin-vue": "^5.0.0",
38
+ "@web-comp/core": "^1.0.2",
39
+ "@web-comp/date-picker": "^1.0.8",
37
40
  "animated-details": "gist:2912bb049fa906671807415eb0e87188",
38
41
  "axios": "^1.6.2",
39
42
  "commander": "^12.0.0",
40
43
  "core-js": "^3.29.0",
41
44
  "pinia": "^2.0.0",
42
45
  "sass": "^1.60.0",
46
+ "stac-js": "^0.0.9",
43
47
  "stac-ts": "^1.0.3",
44
48
  "vite": "^5.1.5",
45
49
  "vite-plugin-vuetify": "^2.0.0",
@@ -0,0 +1,32 @@
1
+ <template>
2
+ <span class="fill-height fill-width align-center justify-center">
3
+ <div v-if="inline" class="fill-height fill-width">
4
+ <!-- <p class="text-subtitle-1 ma-1 pa-2">currently selected date is {{ currentDate }}</p> -->
5
+ <v-text-field base-color="primary" density="comfortable" type="date" bg-color="surface" color="primary"
6
+ validate-on="input" min="1980-01-01" :max="new Date().toISOString().split(`T`)[0]" label="Select Date"
7
+ :value="currentDate" v-model="currentDate" />
8
+ </div>
9
+
10
+ <v-date-picker v-else v-model="currentDate" color="primary" elevation="0" bg-color="surface" location="center"
11
+ class="overflow-auto fill-height fill-width" :max="new Date()" position="relative"
12
+ show-adjacent-months></v-date-picker>
13
+ </span>
14
+ </template>
15
+ <script setup>
16
+ import { computed } from "vue";
17
+ import { datetime } from "@/store/States"
18
+
19
+ const props = defineProps(["inline"])
20
+ const currentDate = computed({
21
+ get() {
22
+ return props.inline ? datetime.value.split("T")[0] : new Date(datetime.value) ?? new Date()
23
+ },
24
+ /** @param {Date | string} updatedDate */
25
+ set(updatedDate) {
26
+ if (props.inline) {
27
+ updatedDate = new Date(updatedDate) ?? new Date()
28
+ }
29
+ datetime.value = /** @type {Date} */ (updatedDate).toISOString()
30
+ }
31
+ })
32
+ </script>
@@ -0,0 +1,54 @@
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 '@eox/map/dist/eox-map-advanced-layers-and-sources.js';
14
+
15
+ const eodashConfig = /** @type {import("@/types").Eodash} */ inject(eodashKey)
16
+
17
+ const properties = {
18
+ class: "fill-height fill-width overflow-none",
19
+ center: [15, 48],
20
+ layers: [{ type: "Tile", source: { type: "OSM" } }],
21
+ }
22
+ const link = () => import("@eox/map")
23
+
24
+ /** @type {import("openlayers").EventsListenerFunctionType}*/
25
+ let handleMoveEnd;
26
+
27
+ /** @type {import("@/types").WebComponentProps["onMounted"]} */
28
+ const onMounted = (el, store, router) => {
29
+ datetime.value = /** @type {string} */ (router.currentRoute.value.query["datetime"] ?? "");
30
+ mapInstance.value = /** @type {any} */(el).map;
31
+
32
+ const { selectedStac } = storeToRefs(store)
33
+
34
+ watch([selectedStac, datetime], async ([updatedStac, updatedTime]) => {
35
+ if (updatedStac) {
36
+ const parentCollUrl = toAbsolute(updatedStac.links[1].href, eodashConfig.stacEndpoint);
37
+ const childCollUrl = toAbsolute(updatedStac.links[1].href, parentCollUrl);
38
+ const eodash = new EodashCollection(childCollUrl);
39
+ if (updatedTime) {
40
+ /** @type {any} */(el).layers = await eodash.createLayersJson(new Date(updatedTime));
41
+ } else {
42
+ /** @type {any} */(el).layers = await eodash.createLayersJson();
43
+ }
44
+ }
45
+ }, { immediate: true })
46
+ }
47
+ /** @type {import("@/types").WebComponentProps["onUnmounted"]} */
48
+ const onUnmounted = (_el, _store, _router) => {
49
+ mapInstance.value?.un('moveend', handleMoveEnd);
50
+ }
51
+
52
+
53
+
54
+ </script>