@eodash/eodash 5.0.0-alpha.1.9 → 5.0.0-alpha.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -1
  3. package/bin/cli.js +15 -8
  4. package/bin/main.js +9 -0
  5. package/bin/serverConfig.js +58 -29
  6. package/bin/types.d.ts +52 -0
  7. package/bin/utils.js +70 -20
  8. package/core/App.vue +10 -12
  9. package/core/SuspensedDashboard.ce.vue +65 -0
  10. package/core/asWebComponent.d.ts +18 -0
  11. package/core/asWebComponent.js +12 -0
  12. package/core/components/DashboardLayout.vue +11 -25
  13. package/core/components/DynamicWebComponent.vue +6 -6
  14. package/core/components/Footer.vue +11 -12
  15. package/core/components/Header.vue +5 -29
  16. package/core/components/Loading.vue +27 -0
  17. package/core/components/MobileLayout.vue +34 -63
  18. package/core/composables/DefineEodash.js +57 -0
  19. package/core/composables/DefineWidgets.js +26 -15
  20. package/core/composables/index.js +139 -67
  21. package/core/eodash.js +100 -0
  22. package/core/main.js +2 -4
  23. package/core/plugins/index.js +3 -12
  24. package/core/plugins/vuetify.js +5 -2
  25. package/core/store/Actions.js +0 -28
  26. package/core/store/States.js +12 -3
  27. package/core/store/stac.js +7 -5
  28. package/core/types.d.ts +149 -124
  29. package/core/utils/eodashSTAC.js +164 -0
  30. package/core/utils/helpers.js +40 -0
  31. package/core/utils/index.js +28 -0
  32. package/core/utils/keys.js +6 -0
  33. package/core/views/Dashboard.vue +33 -23
  34. package/core/vite-env.d.ts +16 -2
  35. package/dist/.gitkeep +0 -0
  36. package/dist/DashboardLayout-Dp8AnYD9.js +141 -0
  37. package/dist/DynamicWebComponent-BrHVTesn.js +57 -0
  38. package/dist/EodashDatePicker-D_udZ26j.js +1645 -0
  39. package/dist/EodashItemFilter-BLAGx2UD.js +51 -0
  40. package/dist/EodashMap-Bxl_aqY2.js +53405 -0
  41. package/dist/Footer-AohCH8U7.js +118 -0
  42. package/dist/Header-DC50S6GR.js +609 -0
  43. package/dist/IframeWrapper-Dd9zrX9s.js +19 -0
  44. package/dist/MobileLayout-CgToA7Gp.js +523 -0
  45. package/dist/VBtn-Bz7ruRUg.js +1106 -0
  46. package/dist/VMain-BHfWJU2j.js +35 -0
  47. package/dist/WidgetsContainer-DxfCu0I3.js +122 -0
  48. package/dist/_commonjsHelpers-DaMA6jEr.js +8 -0
  49. package/dist/asWebComponent-C8rb3b1D.js +11323 -0
  50. package/dist/basedecoder-Qm25PwVp-CHo5Pomv.js +89 -0
  51. package/dist/color-DpYEub1f.js +115 -0
  52. package/dist/decoder-kAoyGIq9-BBR5CgzS.js +10 -0
  53. package/dist/deflate-Be2Arps5-hDqMz3RA.js +10 -0
  54. package/dist/dimensions-CJaGeSrj.js +53 -0
  55. package/dist/eo-dash.js +6 -0
  56. package/dist/eox-itemfilter-DcQkRD2l.js +7537 -0
  57. package/dist/eox-map-BJ9SIixs.js +36205 -0
  58. package/dist/eox-stacinfo-B-YrT7Ug.js +13698 -0
  59. package/dist/forwardRefs-Bxeu9Obx.js +142 -0
  60. package/dist/index-DTkOfh2g.js +152 -0
  61. package/dist/index-Sa2Vg_gx.js +65 -0
  62. package/dist/jpeg-DNfUpLwy-Fjan-04T.js +515 -0
  63. package/dist/lerc-C9VL9kri-cIdbW0sg.js +1029 -0
  64. package/dist/lzw-BOMhmEDy-Dboc93VO.js +84 -0
  65. package/dist/packbits-DaUD6MLm-Bu1PoTGa.js +24 -0
  66. package/dist/pako.esm-C3kYPGGQ-BMki8cQY.js +1087 -0
  67. package/dist/raw-CcGKjn8q-DFOt-i8n.js +9 -0
  68. package/dist/ssrBoot-D-b4-M19.js +17 -0
  69. package/dist/style.css +5 -0
  70. package/dist/webfontloader-CyOFAuFB.js +471 -0
  71. package/dist/webimage-D2c098k3-DLj1LQxB.js +19 -0
  72. package/package.json +40 -12
  73. package/widgets/EodashDatePicker.vue +56 -0
  74. package/widgets/EodashItemFilter.vue +60 -0
  75. package/widgets/EodashMap.vue +82 -0
  76. package/widgets/WidgetsContainer.vue +1 -1
  77. package/core/composables/DefineConfig.js +0 -45
  78. package/core/eodashConfig.js +0 -136
  79. package/core/plugins/router.js +0 -20
  80. package/core/store/Keys.js +0 -6
@@ -1,16 +1,19 @@
1
1
  <template>
2
2
  <v-footer ref="footer" :height="mdAndDown ? '48px' : 'auto'" color="secondary" app
3
3
  class="d-flex justify-space-between">
4
- <p class="pt-0 footer-text">
5
- Phasellus feugiat arcu sapien, et iaculis ipsum elementum sit amet. Mauris cursus commodo interdum.
4
+ <p class="pt-0" style="font-size: 0.8rem;">
5
+ {{ eodash.brand.footerText ?? "" }}
6
6
  </p>
7
- <div class="footer-text">
8
- {{ new Date().getFullYear() }} — <strong>{{ title }}</strong>
7
+ <div>
8
+ <a href="https://github.com/eodash/eodash" class="text-white" target="_blank">eodash</a> by
9
+ <a href="https://eox.at" target="_blank" class="text-white">
10
+ <img :src='`data:image/svg+xml;base64,${base64Logo}`' height="11px">
11
+ </a>
9
12
  </div>
10
13
  </v-footer>
11
14
  </template>
12
15
  <script setup>
13
- import { eodashConfigKey } from '@/store/Keys';
16
+ import { eodashKey } from '@/utils/keys';
14
17
  import { ref } from 'vue';
15
18
  import { inject } from 'vue';
16
19
  import { useDisplay } from 'vuetify/lib/framework.mjs';
@@ -20,13 +23,9 @@ import { useDisplay } from 'vuetify/lib/framework.mjs';
20
23
  * @type {import('vue').Ref<import('vuetify/lib/components/index.mjs').VFooter | null>}
21
24
  */
22
25
  const footer = ref(null)
23
- const eodashConfig = /** @type {import("@/types").EodashConfig} */(inject(eodashConfigKey))
26
+ const eodash = /** @type {import("@/types").Eodash} */(inject(eodashKey))
24
27
 
25
- const title = eodashConfig.brand?.shortName ?? eodashConfig.brand?.name
26
28
  const { mdAndDown } = useDisplay()
29
+ const eoxLogo = `<svg width="100%" height="100%" viewBox="0 0 355 85" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;"><g id="ink_ext_XXXXXX"><path id="path5076" d="M152.986,40.52l-0.75,-0.019l-0.737,-0.056l-0.725,-0.093l-0.713,-0.127l-0.7,-0.162l-0.7,-0.196l-0.675,-0.228l-0.65,-0.261l-0.65,-0.292l-0.625,-0.319l-0.612,-0.352l-0.588,-0.377l-0.562,-0.407l-0.55,-0.431l-0.538,-0.457l-0.5,-0.481l-0.487,-0.505l-0.45,-0.528l-0.438,-0.55l-0.4,-0.57l-0.375,-0.59l-0.35,-0.609l-0.325,-0.627l-0.287,-0.645l-0.263,-0.66l-0.225,-0.676l-0.2,-0.69l-0.162,-0.704l-0.125,-0.717l-0.1,-0.728l-0.05,-0.739l-0.025,-0.748c0,-8.023 6.512,-14.532 14.537,-14.532c8.038,0 14.538,6.509 14.538,14.532c0,8.036 -6.5,14.544 -14.538,14.544Z" style="fill:none;"/><path id="path5078" d="M165.748,-0.002c-42.009,0 -76.06,18.985 -76.06,42.402c0,13.268 10.921,25.102 28.021,32.875c-8.081,-5.487 -13.403,-12.973 -14.584,-21.859c-2.685,-20.186 16.83,-40.82 45.148,-49.615c-14.687,6.665 -24.923,21.427 -24.923,38.599c0,23.218 18.648,42.046 41.773,42.383c-0.037,0.005 -0.087,0.015 -0.137,0.02c0.263,0 0.512,0.009 0.762,0.009c42.013,0 76.076,-18.984 76.076,-42.412c0,-13.261 -10.937,-25.097 -28.037,-32.871l0.75,0.522l0.736,0.531l0.713,0.543l0.7,0.555l0.687,0.566l0.664,0.578l0.649,0.588l0.625,0.6l0.613,0.609l0.588,0.621l0.574,0.631l0.562,0.643l0.538,0.652l0.513,0.662l0.5,0.672l0.475,0.684l0.449,0.693l0.438,0.703l0.425,0.713l0.387,0.723l0.375,0.73l0.352,0.74l0.336,0.75l0.3,0.76l0.287,0.77l0.264,0.777l0.25,0.787l0.211,0.795l0.188,0.805l0.175,0.812l0.151,0.82l0.125,0.831c2.675,20.19 -16.838,40.825 -45.151,49.619c14.688,-6.665 24.926,-21.426 24.926,-38.614c0,-23.202 -18.65,-42.026 -41.775,-42.367c0.05,-0.005 0.1,-0.015 0.15,-0.025c-0.262,0 -0.526,-0.01 -0.789,-0.01Zm-13.248,11.314c7.817,0 14.25,6.433 14.25,14.25c0,0.001 0,0.001 0,0.001c0,7.817 -6.433,14.249 -14.25,14.249c-7.817,0 -14.25,-6.432 -14.25,-14.249c0,-0.001 0,-0.001 0,-0.001c0,-7.817 6.433,-14.25 14.25,-14.25Z" style="fill:#fff;fill-rule:nonzero;"/><path id="path5080" d="M213.786,9.529l0.75,0.521l0.738,0.532l0.712,0.544l0.7,0.555l0.688,0.566l0.662,0.577l0.65,0.588l0.625,0.6l0.613,0.61l0.587,0.62l0.575,0.631l0.563,0.643l0.537,0.652l0.513,0.663l0.5,0.672l0.475,0.684l0.45,0.692l0.437,0.703l0.425,0.712l0.388,0.723l0.375,0.731l0.35,0.741l0.337,0.75l0.3,0.76l0.288,0.769l0.262,0.777l0.25,0.786l0.213,0.797l0.187,0.804l0.175,0.812l0.15,0.821l0.125,0.83c2.675,20.19 -16.837,40.825 -45.15,49.619c14.688,-6.665 24.925,-21.426 24.925,-38.614c0,-23.202 -18.65,-42.025 -41.775,-42.367c0.05,-0.005 0.1,-0.015 0.15,-0.025c-0.262,0 -0.525,-0.01 -0.787,-0.01c-42.01,0 -76.062,18.985 -76.062,42.402c0,13.268 10.922,25.103 28.022,32.876c-8.081,-5.487 -13.403,-12.973 -14.584,-21.859c-2.685,-20.187 16.831,-40.82 45.149,-49.615c-14.688,6.665 -24.925,21.426 -24.925,38.598c0,23.218 18.65,42.046 41.775,42.383c-0.038,0.005 -0.088,0.015 -0.138,0.02c0.263,0 0.513,0.01 0.763,0.01c42.012,-0.001 76.075,-18.985 76.075,-42.413c0,-13.261 -10.938,-25.097 -28.038,-32.871Z" style="fill:none;"/><path id="path5082" d="M354.323,82.586l-41.999,-42.002l38.524,-38.515l-29.913,0l-23.562,23.559l-23.563,-23.559l-29.924,0l38.525,38.515l-42,42.002l29.913,0l27.049,-27.046l27.05,27.046l29.9,0" style="fill:#fff;fill-rule:nonzero;"/><path id="path5084" d="M354.323,82.586l-41.999,-42.002l38.524,-38.515l-29.913,0l-23.562,23.559l-23.563,-23.559l-29.924,0l38.525,38.515l-42,42.002l29.913,0l27.049,-27.046l27.05,27.046l29.9,0Z" style="fill:none;"/><path id="path5086" d="M0,2.069l75.033,0l0,16.489l-51.629,0l0,14.931l40.258,0l0,16.495l-40.258,0l0,16.05l53.124,0l0,16.488l-76.528,0l0,-80.453" style="fill:#fff;fill-rule:nonzero;"/><path id="path5088" d="M0,2.069l75.033,0l0,16.489l-51.629,0l0,14.931l40.258,0l0,16.495l-40.258,0l0,16.05l53.124,0l0,16.488l-76.528,0l0,-80.453Z" style="fill:none;"/></g></svg>`
30
+ const base64Logo = window.btoa(eoxLogo)
27
31
  </script>
28
- <style scoped lang='scss'>
29
- .footer-text {
30
- font-size: 0.8rem;
31
- }
32
- </style>
@@ -1,38 +1,14 @@
1
1
  <template>
2
2
  <v-app-bar color="primary">
3
- <v-app-bar-title class="cursor-pointer">{{ title }}</v-app-bar-title>
4
- <v-toolbar-items v-if="eodashConfig.routes">
5
- <v-btn v-for="route in eodashConfig.routes" :key="route.to" variant="text" @click="navigateTo(route.to)">
6
- {{ route.title }}
7
- </v-btn>
8
- </v-toolbar-items>
9
- <v-img class="mx-12 logo" :src="eodashConfig.brand?.logo" />
3
+ <v-app-bar-title>{{ title }}</v-app-bar-title>
4
+ <v-img class="mx-12" style="max-width: 140px;" :src="eodash.brand?.logo" />
10
5
  </v-app-bar>
11
6
  </template>
12
7
  <script setup>
13
- import { eodashConfigKey } from '@/store/Keys';
8
+ import { eodashKey } from '@/utils/keys';
14
9
  import { inject } from 'vue';
15
- import { useRouter } from 'vue-router';
16
10
 
17
- const eodashConfig = /** @type {import("@/types").EodashConfig} */(inject(eodashConfigKey))
11
+ const eodash = /** @type {import("@/types").Eodash} */(inject(eodashKey))
18
12
 
19
- const title = eodashConfig.brand?.name
20
-
21
- const { push } = useRouter()
22
-
23
- /**
24
- * @param {string} to
25
- */
26
- const navigateTo = (to) => {
27
- if (to.toLowerCase().startsWith('http')) {
28
- window.open(to, '_self')
29
- } else {
30
- push(to)
31
- }
32
- }
13
+ const title = eodash.brand?.name
33
14
  </script>
34
- <style scoped lang='scss'>
35
- .logo {
36
- max-width: 140px;
37
- }
38
- </style>
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <v-row class="d-flex justify-center align-center ">
3
+ <v-col class="flex-column justify-center align-center">
4
+ <Suspense>
5
+ <component v-if="loading.component" :is="loading.component" v-bind="loading.props"></component>
6
+ <div v-else class="text-center">
7
+ Loading...
8
+ </div>
9
+ <template #fallback>
10
+ <div class="text-center">
11
+ Loading...
12
+ </div>
13
+ </template>
14
+ </Suspense>
15
+ </v-col>
16
+ </v-row>
17
+ </template>
18
+ <script setup>
19
+ import { inject } from 'vue';
20
+ import { eodashKey } from '@/utils/keys';
21
+ import { useDefineWidgets } from '@/composables/DefineWidgets';
22
+
23
+ const eodash = /** @type {import("@/types").Eodash} */ (inject(eodashKey))
24
+
25
+ const [loading] = useDefineWidgets([eodash.template.loading])
26
+
27
+ </script>
@@ -1,78 +1,49 @@
1
1
  <template>
2
- <v-main class="overflow-none" style="height: 91dvh;">
2
+ <v-main class="overflow-hidden" style="height: 91dvh;">
3
+
4
+ <component id="bg-widget" :is="bgWidget.component" v-bind="bgWidget.props"></component>
5
+
6
+ <div v-show="activeIdx === idx" id="overlay" class="pa-2" v-for="(importedWidget, idx) in importedWidgets"
7
+ :key="idx" :style="{
8
+ bottom: tabsHeightFromBtm, position: 'absolute', overflow: 'hidden',
9
+ width: '100%', left: 0, top: mainRect.top + 'px', zIndex: 1, background: 'rgb(var(--v-theme-surface))'
10
+ }">
11
+ <v-btn icon variant="text" style="height: 5%;position: relative;" @click="activeIdx = -1">&#x2715;</v-btn>
12
+ <component style="height: 94% !important;" :key="importedWidget.value.id" :is="importedWidget.value.component"
13
+ v-show="activeIdx === idx" v-bind="importedWidget.value.props" />
14
+ </div>
15
+
16
+ <v-tabs ref="tabs" align-tabs="center" bg-color="surface"
17
+ :style="{ position: 'relative', bottom: (mainRect.bottom || 48) + 'px', zIndex: 10 }" show-arrows
18
+ v-model="activeIdx">
19
+ <v-tab v-for="(importedWidget, idx) in importedWidgets" :key="idx" :value="idx">
20
+ {{ importedWidget.value.title }}
21
+ </v-tab>
22
+ </v-tabs>
3
23
 
4
- <component :is="bgWidget.component" v-bind="bgWidget.props"></component>
5
-
6
- <v-row no-gutters class="d-flex justify-center align-end">
7
- <v-col v-for="(importedWidget, idx) in importedWidgets" :key="idx" :cols="cols"
8
- class="flex-column fill-height fill-width elevation-1 align-start ma-0 justify-center">
9
- <span class="d-flex pa-2 justify-center ma-0 panel-header align-center fill-width"
10
- @click="handleSelection(idx)">
11
- {{ importedWidget.value.title }}
12
- </span>
13
- <div v-show="activeIdx === idx" class="overlay align-self-end overflow-auto pa-2">
14
- <v-btn icon variant="text" class="close-btn" @click="activeIdx = -1">&#x2715;</v-btn>
15
- <component :key="importedWidget.value.id" :is="importedWidget.value.component" v-show="activeIdx === idx"
16
- v-bind="importedWidget.value.props" />
17
- </div>
18
- </v-col>
19
- </v-row>
20
24
  </v-main>
21
25
  </template>
22
26
  <script setup>
23
- import { eodashConfigKey } from '@/store/Keys';
24
- import { inject } from 'vue';
27
+ import { eodashKey } from '@/utils/keys';
28
+ import { inject, ref, onMounted } from 'vue';
25
29
  import { useDefineWidgets } from '@/composables/DefineWidgets'
26
- import { ref } from 'vue';
30
+ import { useLayout } from "vuetify"
27
31
 
28
- const eodashConfig = /** @type {import("@/types").EodashConfig} */(inject(eodashConfigKey));
32
+ const eodash = /** @type {import("@/types").Eodash} */(inject(eodashKey));
29
33
 
30
34
  //import widgets
31
- const widgetsConfig = eodashConfig.template.widgets
35
+ const widgetsConfig = eodash.template.widgets
32
36
  const importedWidgets = useDefineWidgets(widgetsConfig)
33
- const [bgWidget] = useDefineWidgets([eodashConfig.template?.background])
34
-
35
-
37
+ const [bgWidget] = useDefineWidgets([eodash.template?.background])
36
38
 
37
- /**
38
- * number of flex columns
39
- */
40
- const cols = importedWidgets.length / 12
39
+ const { mainRect } = useLayout()
41
40
 
42
- /**
43
- * index of the active tab
44
- */
45
41
  const activeIdx = ref(-1)
46
42
 
47
- /**
48
- * @param {number} idx
49
- **/
50
- const handleSelection = (idx) => {
51
- activeIdx.value = activeIdx.value === idx ? -1 : idx
52
- }
43
+ /** @type {import("vue").Ref<import("vuetify/components").VTabs|null>} */
44
+ const tabs = ref(null)
45
+ const tabsHeightFromBtm = ref('')
46
+ onMounted(() => {
47
+ tabsHeightFromBtm.value = mainRect.value.bottom + (/** @type {HTMLElement} */(tabs.value?.$el)?.clientHeight ?? 0) + "px"
48
+ })
53
49
  </script>
54
- <style scoped lang='scss'>
55
- .panel-header {
56
- height: auto;
57
- margin: 0;
58
- width: 100%;
59
- position: relative;
60
- bottom: 64px;
61
- z-index: 10;
62
- background: rgb(var(--v-theme-background));
63
- }
64
-
65
- .overlay {
66
- position: absolute;
67
- width: 100%;
68
- left: 0;
69
- top: 64px;
70
- bottom: 64px;
71
- z-index: 1;
72
- background: rgb(var(--v-theme-background));
73
- }
74
-
75
- .close-btn {
76
- justify-self: end;
77
- }
78
- </style>
@@ -0,0 +1,57 @@
1
+ import store from "@/store";
2
+ import { eodashKey } from "@/utils/keys";
3
+ import { inject } from "vue";
4
+
5
+
6
+
7
+ /**
8
+ * Sets user defined instance on runtime.
9
+ * Consumes `/@fs/config.js` and assign it to `eodash`
10
+ * @async
11
+ * @returns {Promise<import("@/types").Eodash>}
12
+ * @param {string | undefined} runtimeConfig
13
+ * @see {@linkplain '@/eodash.js'}
14
+ */
15
+ export const useEodashRuntime = async (runtimeConfig) => {
16
+ const eodash = /** @type {import("@/types").Eodash} */(inject(eodashKey))
17
+ /**
18
+ * @param {import("@/types").Eodash} config
19
+ */
20
+ const assignInstance = (config) => {
21
+ /** @type {(keyof import("@/types").Eodash)[]} */(Object.keys(eodash))
22
+ .forEach((key) => {
23
+ //@ts-expect-error
24
+ eodash[key] = config[key]
25
+ })
26
+ }
27
+
28
+ if (runtimeConfig) {
29
+ assignInstance((await import( /* @vite-ignore */new URL(runtimeConfig, import.meta.url).href)).default);
30
+ return eodash
31
+ }
32
+
33
+ try {
34
+ assignInstance(
35
+ (await import( /* @vite-ignore */new URL('/config.js', import.meta.url).href)).default
36
+ )
37
+ } catch {
38
+ try {
39
+ assignInstance(await import("user:config").then(async m => await m['default']))
40
+ } catch {
41
+ console.error('no dashboard configuration defined')
42
+ }
43
+ }
44
+ return eodash
45
+ }
46
+
47
+ /**
48
+ * @param {((store:import("@/types").EodashStore)=> Promise<import("@/types").Eodash>)
49
+ * | import("@/types").Eodash} config
50
+ */
51
+ export const createEodash = async (config) => {
52
+ if (config instanceof Function) {
53
+ return await config(store)
54
+ } else {
55
+ return config
56
+ }
57
+ }
@@ -1,8 +1,7 @@
1
1
  import { defineAsyncComponent, reactive, shallowRef, watch } from 'vue'
2
2
  import { useSTAcStore } from '@/store/stac'
3
3
  import { storeToRefs } from 'pinia'
4
-
5
-
4
+ import Loading from '@/components/Loading.vue';
6
5
 
7
6
  /**
8
7
  * @typedef {{
@@ -17,17 +16,27 @@ import { storeToRefs } from 'pinia'
17
16
  * @typedef {import('vue').ShallowRef<DefinedWidget>} ReactiveDefinedWidget
18
17
  */
19
18
 
19
+ const internalWidgets = (() => {
20
+ /**
21
+ * @type {Record<string,() => Promise<import('vue').Component>>}
22
+ */
23
+ const importMap = {
24
+ ...import.meta.glob('^/**/*.vue'),
25
+ ...import.meta.glob("user:widgets/**/*.vue")
26
+ }
27
+ for (const key in importMap) {
28
+ const newKey = /** @type {string} */(key.split('/').at(-1)).slice(0, -4)
29
+ Object.defineProperty(importMap, newKey,
30
+ /** @type {PropertyDescriptor} */(Object.getOwnPropertyDescriptor(importMap, key)));
31
+ delete importMap[key];
32
+ }
33
+ return importMap
34
+ })();
20
35
 
21
36
 
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
37
  /**
29
38
  * Composable that converts widgets Configurations to defined imported widgets
30
- * @param { (import("@/types").WidgetConfig | import("@/types").BackgroundWidgetConfig | undefined)[] |
39
+ * @param { (import("@/types").Widget | import("@/types").BackgroundWidget | undefined)[] |
31
40
  * import("@/types").WidgetsContainerProps['widgets'] | undefined} widgetConfigs
32
41
  * @returns {Array<ReactiveDefinedWidget>}
33
42
  **/
@@ -46,7 +55,6 @@ export const useDefineWidgets = (widgetConfigs) => {
46
55
  props: {},
47
56
  title: '',
48
57
  id: Symbol(),
49
- no: '4'
50
58
  })
51
59
 
52
60
  if ('defineWidget' in (config ?? {})) {
@@ -84,17 +92,19 @@ const getWidgetDefinition = (config) => {
84
92
  switch (config?.type) {
85
93
  case 'internal':
86
94
  importedWidget.component = defineAsyncComponent({
87
- loader: internalWidgets[`/widgets/${/** @type {import("@/types").InternalComponentConfig} **/(config)?.widget.name}.vue`],
88
- suspensible: true
95
+ loader: internalWidgets[/** @type {import("@/types").InternalComponentWidget} **/(config)?.widget.name],
96
+ suspensible: true,
97
+ loadingComponent: Loading
89
98
  })
90
- importedWidget.props = reactive(/** @type {import("@/types").InternalComponentConfig} **/(config)?.widget.props ?? {})
99
+ importedWidget.props = reactive(/** @type {import("@/types").InternalComponentWidget} **/(config)?.widget.properties ?? {})
91
100
 
92
101
  break;
93
102
 
94
103
  case 'web-component':
95
104
  importedWidget.component = defineAsyncComponent({
96
105
  loader: () => import('@/components/DynamicWebComponent.vue'),
97
- suspensible: true
106
+ suspensible: true,
107
+ loadingComponent: Loading
98
108
  })
99
109
  importedWidget.props = reactive(config.widget)
100
110
 
@@ -102,7 +112,8 @@ const getWidgetDefinition = (config) => {
102
112
  case 'iframe':
103
113
  importedWidget.component = defineAsyncComponent({
104
114
  loader: () => import('@/components/IframeWrapper.vue'),
105
- suspensible: true
115
+ suspensible: true,
116
+ loadingComponent: Loading
106
117
  })
107
118
  importedWidget.props = reactive(config.widget)
108
119
  break;
@@ -1,23 +1,23 @@
1
1
  // functions of this folder can only be consumed inside setup stores,
2
2
  // setup functions or vue composition api components
3
3
 
4
- import { reactive } from "vue"
5
- import { currentUrl } from "@/store/States"
6
- import eodashConfig from "@/eodashConfig"
7
- import { useTheme } from "vuetify/lib/framework.mjs"
8
-
4
+ import { reactive } from "vue";
5
+ import { currentUrl, indicator, mapPosition } from "@/store/States";
6
+ import eodash from "@/eodash";
7
+ import { useTheme } from "vuetify/lib/framework.mjs";
8
+ import { onMounted, watch } from "vue";
9
9
 
10
10
  /**
11
11
  * Creates an absolute URL from a relative link and assignes it to `currentUrl`
12
12
  * @param {string} [rel = '']
13
- * @param {string} [base = eodashConfig.stacEndpoint] - base URL, default value is the root stac catalog
13
+ * @param {string} [base = eodash.stacEndpoint] - base URL, default value is the root stac catalog
14
14
  * @returns {import('vue').Ref<string>} - returns `currentUrl`
15
15
  * @see {@link '@/store/States.js'}
16
16
  */
17
- export const useAbsoluteUrl = (rel = '', base = eodashConfig.stacEndpoint) => {
18
- if (!rel || rel.includes('http')) {
19
- currentUrl.value = base
20
- return currentUrl
17
+ export const useAbsoluteUrl = (rel = "", base = eodash.stacEndpoint) => {
18
+ if (!rel || rel.includes("http")) {
19
+ currentUrl.value = base;
20
+ return currentUrl;
21
21
  }
22
22
 
23
23
  const st = base.split("/");
@@ -25,102 +25,122 @@ export const useAbsoluteUrl = (rel = '', base = eodashConfig.stacEndpoint) => {
25
25
  st.pop();
26
26
 
27
27
  for (let i = 0; i < arr.length; i++) {
28
- if (arr[i] == ".")
29
- continue;
30
- if (arr[i] == "..")
31
- st.pop();
32
- else
33
- st.push(arr[i]);
28
+ if (arr[i] == ".") continue;
29
+ if (arr[i] == "..") st.pop();
30
+ else st.push(arr[i]);
34
31
  }
35
32
 
36
33
  currentUrl.value = st.join("/");
37
- return currentUrl
38
- }
34
+ return currentUrl;
35
+ };
39
36
 
40
37
  /**
41
38
  * Adds slide in and out functionality to Elements
42
39
  * @param {import('vue').Ref<HTMLElement[]|null>} elements - elements to add the functionality to
43
- * @param {import("@/types").WidgetConfig[]} configs
40
+ * @param {import("@/types").Widget[]} configs
44
41
  */
45
42
  export const useSlidePanels = (elements, configs) => {
46
-
47
43
  /**
48
44
  * Sliding direction
49
45
  */
50
- const slideDirs = configs.map(m => m.layout.x == 0 ? 'left' : m.layout.x == 12 - m.layout.w ? 'right' : m.layout.y < 6 ? 'up' : 'down')
46
+ const slideDirs = configs.map((m) =>
47
+ m.layout.x == 0
48
+ ? "left"
49
+ : m.layout.x == 12 - m.layout.w
50
+ ? "right"
51
+ : m.layout.y < 6
52
+ ? "up"
53
+ : "down"
54
+ );
51
55
 
52
56
  /**
53
57
  * Array of sliding button's style and icons
54
58
  */
55
- const slideBtns = slideDirs.map(d => {
56
- const btn = reactive({ style: {}, icon: { in: '', out: '' }, active: false })
57
- switch (d) {
58
- case 'left':
59
- btn.style = { 'top': '50%', 'right': '-11%' }
60
- btn.icon.in = 'mdi-chevron-double-right'
61
- btn.icon.out = 'mdi-chevron-double-left'
59
+ const slideBtns = slideDirs.map((dir, idx) => {
60
+ const btn = reactive({
61
+ style: {},
62
+ icon: { in: "", out: "" },
63
+ active: false,
64
+ enabled: true,
65
+ });
66
+ if (configs[idx].slidable === false) {
67
+ btn.enabled = false;
68
+ return btn;
69
+ }
70
+
71
+ switch (dir) {
72
+ case "left":
73
+ btn.style = { top: "50%", right: "-11%" };
74
+ btn.icon.in = "mdi-chevron-double-right";
75
+ btn.icon.out = "mdi-chevron-double-left";
62
76
 
63
77
  break;
64
- case 'right':
65
- btn.style = { 'top': '50%', 'left': '-11%' }
66
- btn.icon.in = 'mdi-chevron-double-left'
67
- btn.icon.out = 'mdi-chevron-double-right'
78
+ case "right":
79
+ btn.style = { top: "50%", left: "-11%" };
80
+ btn.icon.in = "mdi-chevron-double-left";
81
+ btn.icon.out = "mdi-chevron-double-right";
68
82
 
69
83
  break;
70
- case 'up':
71
- btn.style = { 'right': '50%', 'bottom': '-17%' }
72
- btn.icon.in = 'mdi-chevron-double-down'
73
- btn.icon.out = 'mdi-chevron-double-up'
84
+ case "up":
85
+ btn.style = { right: "50%", bottom: "-17%" };
86
+ btn.icon.in = "mdi-chevron-double-down";
87
+ btn.icon.out = "mdi-chevron-double-up";
74
88
 
75
89
  break;
76
- case 'down':
77
- btn.style = { 'right': '50%', 'top': '-17%' }
78
- btn.icon.in = 'mdi-chevron-double-up'
79
- btn.icon.out = 'mdi-chevron-double-down'
90
+ case "down":
91
+ btn.style = { right: "50%", top: "-17%" };
92
+ btn.icon.in = "mdi-chevron-double-up";
93
+ btn.icon.out = "mdi-chevron-double-down";
80
94
  break;
81
95
 
82
96
  default:
83
- console.error('sliding error')
97
+ console.error("sliding error");
84
98
  break;
85
99
  }
86
- return btn
87
- })
100
+ return btn;
101
+ });
88
102
 
89
103
  /**
90
104
  * Transforms the element's position based on the direction
91
105
  * @param {number} idx - index of the pressed element
92
106
  */
93
107
  const slideInOut = (idx) => {
94
- const parentStyle = /** @type {CSSStyleDeclaration} */ (elements.value?.[idx].style)
108
+ const parentStyle = /** @type {CSSStyleDeclaration} */ (
109
+ elements.value?.[idx].style
110
+ );
95
111
  if (parentStyle?.transform.length) {
96
- slideBtns[idx].active = false
112
+ slideBtns[idx].active = false;
97
113
  parentStyle.transform = "";
98
114
  } else {
99
- slideBtns[idx].active = true
100
- parentStyle.transition = "transform 0.3s ease-in-out"
115
+ slideBtns[idx].active = true;
116
+ parentStyle.transition = "transform 0.3s ease-in-out";
101
117
  switch (slideDirs[idx]) {
102
- case 'left':
103
- parentStyle.transform = "translateX(-100%)"
118
+ case "left":
119
+ parentStyle.transform = "translateX(-100%)";
104
120
  break;
105
- case 'right':
106
- parentStyle.transform = "translateX(100%)"
121
+ case "right":
122
+ parentStyle.transform = "translateX(100%)";
107
123
  break;
108
- case 'up':
109
- parentStyle.transform = `translateY(-${((configs[idx].layout.y / configs[idx].layout.h) * 100) + 100}%)`
124
+ case "up":
125
+ parentStyle.transform = `translateY(-${(configs[idx].layout.y / configs[idx].layout.h) * 100 + 100
126
+ }%)`;
110
127
  break;
111
- case 'down':
112
- parentStyle.transform = `translateY(${((Math.max(0, 12 - configs[idx].layout.y - configs[idx].layout.h) / configs[idx].layout.h) * 100) + 100}%)`;
128
+ case "down":
129
+ parentStyle.transform = `translateY(${(Math.max(0, 12 - configs[idx].layout.y - configs[idx].layout.h) /
130
+ configs[idx].layout.h) *
131
+ 100 +
132
+ 100
133
+ }%)`;
113
134
  break;
114
135
 
115
136
  default:
116
- console.error('sliding error')
137
+ console.error("sliding error");
117
138
  break;
118
139
  }
119
140
  }
120
- }
121
- return { slideBtns, slideInOut }
122
- }
123
-
141
+ };
142
+ return { slideBtns, slideInOut };
143
+ };
124
144
 
125
145
  /**
126
146
  * Updates an existing Vuetify theme.
@@ -132,16 +152,68 @@ export const useSlidePanels = (elements, configs) => {
132
152
  export const useUpdateTheme = (themeName, themeDefinition = {}) => {
133
153
  const theme = useTheme();
134
154
 
135
- /** @type {Array<keyof import('vuetify').ThemeDefinition>} */(Object.keys(themeDefinition)).forEach((key) => {
136
- if (key === 'dark') {
137
- theme.themes.value[themeName][key] = /** @type {Boolean} */ (themeDefinition[key])
155
+ /** @type {Array<keyof import('vuetify').ThemeDefinition>} */ (
156
+ Object.keys(themeDefinition)
157
+ ).forEach((key) => {
158
+ if (key === "dark") {
159
+ theme.themes.value[themeName][key] = /** @type {Boolean} */ (
160
+ themeDefinition[key]
161
+ );
138
162
  } else {
139
163
  //@ts-expect-error
140
164
  theme.themes.value[themeName][key] = {
141
165
  ...theme.themes.value[themeName][key],
142
- ...themeDefinition[key]
166
+ ...themeDefinition[key],
167
+ };
168
+ }
169
+ });
170
+ return theme;
171
+ };
172
+
173
+ /**
174
+ * Composable that syncs store and URLSearchParameters
175
+ */
176
+
177
+ export const useURLSearchParametersSync = () => {
178
+ onMounted(() => {
179
+ // Analyze currently set url params when first loaded and set them in the store
180
+ if ('URLSearchParams' in window) {
181
+ const searchParams = new URLSearchParams(window.location.search);
182
+ let x, y, z;
183
+ searchParams.forEach((value, key) => {
184
+ if (key === "indicator") {
185
+ indicator.value = value;
186
+ }
187
+ if (key === "x") {
188
+ x = value;
189
+ }
190
+ if (key === "y") {
191
+ y = value;
192
+ }
193
+ if (key === "z") {
194
+ z = value;
195
+ }
196
+ })
197
+ if (x !== undefined && y !== undefined && z !== undefined) {
198
+ mapPosition.value = [x, y, z];
143
199
  }
144
200
  }
145
- })
146
- return theme
147
- }
201
+ watch(
202
+ [indicator, mapPosition],
203
+ ([updatedIndicator, updatedMapPosition]) => {
204
+ if ('URLSearchParams' in window) {
205
+ const searchParams = new URLSearchParams(window.location.search);
206
+ if (updatedIndicator !== "") {
207
+ searchParams.set("indicator", updatedIndicator);
208
+ }
209
+ if (updatedMapPosition && updatedMapPosition.length === 3) {
210
+ searchParams.set("x", updatedMapPosition[0]?.toFixed(4) ?? '');
211
+ searchParams.set("y", updatedMapPosition[1]?.toFixed(4) ?? '');
212
+ searchParams.set("z", updatedMapPosition[2]?.toFixed(4) ?? '');
213
+ }
214
+ const newRelativePathQuery = window.location.pathname + '?' + searchParams.toString();
215
+ history.pushState(null, '', newRelativePathQuery);
216
+ }
217
+ })
218
+ });
219
+ };