glib-web 3.4.8 → 3.5.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.
- package/action.js +6 -5
- package/actions/windows/close.js +4 -1
- package/actions/windows/closeAll.js +3 -1
- package/actions/windows/open.js +3 -0
- package/actions/windows/reload.js +4 -0
- package/app.vue +5 -5
- package/components/_badge.vue +2 -2
- package/components/_dropdownMenu.vue +1 -1
- package/components/charts/area.vue +1 -2
- package/components/charts/column.vue +1 -2
- package/components/charts/line.vue +1 -2
- package/components/charts/pie.vue +1 -2
- package/components/charts/series.js +17 -9
- package/components/component.vue +33 -39
- package/components/composable/gmap.js +153 -0
- package/components/fields/location.vue +96 -141
- package/components/fields/richText.vue +15 -4
- package/components/fields/text.vue +9 -9
- package/components/fields/timer.vue +5 -6
- package/components/label.vue +3 -3
- package/components/map.vue +57 -287
- package/components/panels/list.vue +7 -21
- package/components/shareButton.vue +7 -2
- package/index.js +4 -18
- package/nav/appbar.vue +1 -1
- package/nav/drawerButton.vue +10 -52
- package/package.json +3 -3
- package/plugins/gmap.js +30 -0
- package/plugins/vuetify.js +8 -8
- package/store.js +3 -2
- package/utils/format.js +4 -4
package/action.js
CHANGED
|
@@ -53,13 +53,14 @@ import ActionsAnalyticsLogEvent from "./actions/analytics/logEvent";
|
|
|
53
53
|
import ActionCommandsCopy from "./actions/commands/copy";
|
|
54
54
|
import ActionCommandsCustom from "./actions/commands/custom";
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
// TODO: handle promise action
|
|
57
|
+
const ActionToursStart = import("./actions/tours/start");
|
|
58
|
+
const ActionToursStop = import("./actions/tours/stop");
|
|
58
59
|
|
|
59
60
|
import ActionComponentsUpdate from "./actions/components/update";
|
|
60
61
|
|
|
61
|
-
import ActionPopoversOpen from "./actions/popovers/open"
|
|
62
|
-
import ActionPopoversClose from "./actions/popovers/close"
|
|
62
|
+
import ActionPopoversOpen from "./actions/popovers/open";
|
|
63
|
+
import ActionPopoversClose from "./actions/popovers/close";
|
|
63
64
|
|
|
64
65
|
import { vueApp } from "./store";
|
|
65
66
|
|
|
@@ -182,7 +183,7 @@ export default class Action {
|
|
|
182
183
|
// TODO: The execution should be in the following order: onResponse, page render, onLoad
|
|
183
184
|
if (response.header || response.body || response.footer) {
|
|
184
185
|
Utils.http.forceComponentUpdate(() => {
|
|
185
|
-
vueApp.page = response
|
|
186
|
+
vueApp.page = response;
|
|
186
187
|
});
|
|
187
188
|
}
|
|
188
189
|
|
package/actions/windows/close.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import { vueApp } from "../../store";
|
|
2
|
+
|
|
1
3
|
export default class {
|
|
2
4
|
execute(properties, component) {
|
|
5
|
+
vueApp.richTextValues = {};
|
|
3
6
|
Utils.history.back();
|
|
4
7
|
|
|
5
8
|
Utils.type.ifObject(properties["onClose"], it => {
|
|
6
9
|
// Allow time for history.back() to complete, which is important for actions that need
|
|
7
10
|
// to use window.location.href such as windows/reload
|
|
8
|
-
setTimeout(function() {
|
|
11
|
+
setTimeout(function () {
|
|
9
12
|
GLib.action.execute(it, component);
|
|
10
13
|
}, 100);
|
|
11
14
|
});
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
+
import { vueApp } from "../../store";
|
|
1
2
|
import Type from "../../utils/type";
|
|
2
3
|
|
|
3
4
|
export default class {
|
|
4
5
|
execute(properties, component) {
|
|
6
|
+
vueApp.richTextValues = {};
|
|
5
7
|
// TODO
|
|
6
8
|
// window.history.deleteAll()
|
|
7
9
|
|
|
8
10
|
Type.ifObject(properties["onClose"], it => {
|
|
9
11
|
// Allow time for history.back() to complete, which is important for actions that need
|
|
10
12
|
// to use window.location.href such as windows/reload
|
|
11
|
-
setTimeout(function() {
|
|
13
|
+
setTimeout(function () {
|
|
12
14
|
GLib.action.execute(it, component);
|
|
13
15
|
}, 100);
|
|
14
16
|
});
|
package/actions/windows/open.js
CHANGED
package/app.vue
CHANGED
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
<script>
|
|
30
30
|
import NavAppBar from "./nav/appbar.vue";
|
|
31
31
|
import Utils from "./utils/helper";
|
|
32
|
-
import phoenixSocketMixin from "./components/mixins/ws/phoenixSocket.js";
|
|
33
|
-
import actionCableMixin from "./components/mixins/ws/actionCable.js";
|
|
32
|
+
// import phoenixSocketMixin from "./components/mixins/ws/phoenixSocket.js";
|
|
33
|
+
// import actionCableMixin from "./components/mixins/ws/actionCable.js";
|
|
34
34
|
import FormPanel from "./components/panels/form.vue";
|
|
35
35
|
import { vueApp } from "./store";
|
|
36
36
|
|
|
@@ -39,7 +39,7 @@ export default {
|
|
|
39
39
|
"nav-appbar": NavAppBar,
|
|
40
40
|
"panels-form": FormPanel,
|
|
41
41
|
},
|
|
42
|
-
mixins: [phoenixSocketMixin, actionCableMixin],
|
|
42
|
+
// mixins: [phoenixSocketMixin, actionCableMixin],
|
|
43
43
|
props: {
|
|
44
44
|
page: { type: Object, required: true },
|
|
45
45
|
},
|
|
@@ -103,8 +103,8 @@ export default {
|
|
|
103
103
|
$ready() {
|
|
104
104
|
document.title = this.page.title;
|
|
105
105
|
|
|
106
|
-
this.$wsInitPhoenixSocket(this.page.phoenixSocket);
|
|
107
|
-
this.$wsInitActionCable(this.page.actionCable);
|
|
106
|
+
// this.$wsInitPhoenixSocket(this.page.phoenixSocket);
|
|
107
|
+
// this.$wsInitActionCable(this.page.actionCable);
|
|
108
108
|
|
|
109
109
|
// TODO: Remove gtag dependency
|
|
110
110
|
// if (this.$gtag) {
|
package/components/_badge.vue
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<v-badge :color="badge.backgroundColor || 'red'"
|
|
2
|
+
<v-badge :color="badge.backgroundColor || 'red'" overlap :model-value="badgeExists()" :style="styles()">
|
|
3
3
|
<template v-slot:badge>{{ badge.text }}</template>
|
|
4
4
|
<slot />
|
|
5
5
|
</v-badge>
|
|
@@ -12,7 +12,7 @@ export default {
|
|
|
12
12
|
},
|
|
13
13
|
data() {
|
|
14
14
|
return {
|
|
15
|
-
badge: {}
|
|
15
|
+
badge: {}
|
|
16
16
|
};
|
|
17
17
|
},
|
|
18
18
|
methods: {
|
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script setup>
|
|
8
|
-
import 'chartkick/chart.js';
|
|
9
8
|
import { computed } from 'vue';
|
|
10
|
-
|
|
9
|
+
const { singleDataSeries } = await import('./series');
|
|
11
10
|
|
|
12
11
|
const { spec } = defineProps({ spec: Object });
|
|
13
12
|
const color = spec.colors == null ? '' : [spec.colors];
|
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script setup>
|
|
6
|
-
import 'chartkick/chart.js';
|
|
7
6
|
import { computed } from 'vue';
|
|
8
|
-
|
|
7
|
+
const { multipleDataSeries } = await import('./series');
|
|
9
8
|
|
|
10
9
|
const { spec } = defineProps({ spec: Object });
|
|
11
10
|
const color = spec.colors == null ? '' : spec.colors;
|
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script setup>
|
|
6
|
-
import 'chartkick/chart.js';
|
|
7
6
|
import { computed } from 'vue';
|
|
8
|
-
|
|
7
|
+
const { multipleDataSeries } = await import('./series');
|
|
9
8
|
|
|
10
9
|
const { spec } = defineProps({ spec: Object });
|
|
11
10
|
const color = spec.colors == null ? '' : spec.colors;
|
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script setup>
|
|
6
|
-
import 'chartkick/chart.js';
|
|
7
6
|
import { computed } from 'vue';
|
|
8
|
-
|
|
7
|
+
const { singleDataSeries } = await import('./series');
|
|
9
8
|
|
|
10
9
|
const { spec } = defineProps({ spec: Object });
|
|
11
10
|
const color = spec.colors == null ? '' : spec.colors;
|
|
@@ -1,18 +1,26 @@
|
|
|
1
|
+
import { Vue } from "../..";
|
|
2
|
+
|
|
3
|
+
import 'chartkick/chart.js';
|
|
4
|
+
|
|
5
|
+
import VueChartkick from 'vue-chartkick';
|
|
6
|
+
Vue.use(VueChartkick);
|
|
7
|
+
|
|
8
|
+
|
|
1
9
|
const multipleDataSeries = (dataSeries) => {
|
|
2
10
|
return dataSeries.map((value) => {
|
|
3
|
-
let points = null
|
|
11
|
+
let points = null;
|
|
4
12
|
if (Array.isArray(value.points)) {
|
|
5
13
|
points = value.points.reduce((prev, curr) => {
|
|
6
|
-
return Object.assign(prev, { [curr.x]: curr.y })
|
|
7
|
-
}, {})
|
|
14
|
+
return Object.assign(prev, { [curr.x]: curr.y });
|
|
15
|
+
}, {});
|
|
8
16
|
} else {
|
|
9
|
-
points = value.points
|
|
17
|
+
points = value.points;
|
|
10
18
|
}
|
|
11
|
-
return { name: value.title, data: points }
|
|
12
|
-
})
|
|
13
|
-
}
|
|
19
|
+
return { name: value.title, data: points };
|
|
20
|
+
});
|
|
21
|
+
};
|
|
14
22
|
|
|
15
|
-
const singleDataSeries = (dataSeries) => dataSeries.reduce((prev, curr) => Object.assign(prev, { [curr.title]: curr.value }), {})
|
|
23
|
+
const singleDataSeries = (dataSeries) => dataSeries.reduce((prev, curr) => Object.assign(prev, { [curr.title]: curr.value }), {});
|
|
16
24
|
|
|
17
25
|
|
|
18
|
-
export { multipleDataSeries, singleDataSeries }
|
|
26
|
+
export { multipleDataSeries, singleDataSeries };
|
package/components/component.vue
CHANGED
|
@@ -1,33 +1,38 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
<Suspense>
|
|
3
|
+
<fields-text ref="delegate" v-if="name == 'fields-text'" :spec="spec" type="text" />
|
|
4
|
+
<fields-text ref="delegate" v-else-if="name == 'fields-number'" :spec="spec" type="number" />
|
|
5
|
+
<fields-text ref="delegate" v-else-if="name == 'fields-email'" :spec="spec" type="email" />
|
|
6
|
+
<fields-text ref="delegate" v-else-if="name == 'fields-url'" :spec="spec" type="url" />
|
|
7
|
+
<fields-text ref="delegate" v-else-if="name == 'fields-password'" :spec="spec" type="password" />
|
|
8
|
+
<!-- <fields-textarea v-else-if="spec.view == 'fields/textarea-v1'" :spec="spec" />
|
|
8
9
|
<fields-richText v-else-if="spec.view == 'fields/richText-v1'" :spec="spec" /> -->
|
|
9
|
-
|
|
10
|
+
<!-- <fields-file v-else-if="spec.view == 'fields/file-v1'" :spec="spec" />
|
|
10
11
|
<fields-select v-else-if="spec.view == 'fields/select-v1'" :spec="spec" />
|
|
11
12
|
<fields-dynamicSelect
|
|
12
13
|
v-else-if="spec.view == 'fields/dynamicSelect-v1'"
|
|
13
14
|
:spec="spec"
|
|
14
15
|
/> -->
|
|
15
|
-
|
|
16
|
+
<!-- <fields-country v-else-if="spec.view == 'fields/country-v1'" :spec="spec" /> -->
|
|
16
17
|
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
<!-- <fields-latLong v-else-if="spec.view == 'fields/latLong-v1'" :spec="spec" /> -->
|
|
19
|
+
<fields-googlePlace ref="delegate" v-else-if="spec.view == 'fields/googlePlace-v1'" :spec="spec" />
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
<!-- <panels-responsive v-else-if="spec.view == 'panels/scroll-v1'" :spec="spec" /> -->
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
<!-- This component manages its own mouse events, so don't auto-initialize it. -->
|
|
24
|
+
<button ref="delegate" v-else-if="name == 'button'" :spec="spec" />
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
<component ref="delegate" v-else-if="name" :is="name" :id="spec.id" :spec="spec"
|
|
27
|
+
@[menter]="handlePopover(spec.onMouseEnter)" @[mleave]="handlePopover(spec.onMouseLeave)" />
|
|
28
|
+
<div v-else>Unsupported view: {{ spec.view }}</div>
|
|
29
|
+
</Suspense>
|
|
28
30
|
</template>
|
|
29
31
|
|
|
30
32
|
<script>
|
|
33
|
+
import { getCurrentInstance } from 'vue';
|
|
34
|
+
import { defineAsyncComponent } from "vue";
|
|
35
|
+
|
|
31
36
|
import H1 from "./h1.vue";
|
|
32
37
|
import H2 from "./h2.vue";
|
|
33
38
|
import H3 from "./h3.vue";
|
|
@@ -39,7 +44,7 @@ import P from "./p.vue";
|
|
|
39
44
|
import Markdown from "./markdown.vue";
|
|
40
45
|
import Html from "./html.vue";
|
|
41
46
|
import Chip from "./chip.vue";
|
|
42
|
-
|
|
47
|
+
const Datetime = defineAsyncComponent(() => import("./datetime.vue"));
|
|
43
48
|
|
|
44
49
|
import ProgressBar from "./progressbar.vue";
|
|
45
50
|
import ProgressCircle from "./progressCircle.vue";
|
|
@@ -55,7 +60,7 @@ import Switch from "./switch.vue";
|
|
|
55
60
|
import Hr from "./hr.vue";
|
|
56
61
|
import Spacer from "./spacer.vue";
|
|
57
62
|
|
|
58
|
-
|
|
63
|
+
const Map = defineAsyncComponent(() => import("./map.vue"));
|
|
59
64
|
import TabBar from "./tabBar.vue";
|
|
60
65
|
import Calendar from "./calendar.vue";
|
|
61
66
|
|
|
@@ -65,7 +70,7 @@ import SubmitField from "./fields/submit.vue";
|
|
|
65
70
|
import TextAreaField from "./fields/textarea.vue";
|
|
66
71
|
const RichTextField = defineAsyncComponent(() => import("./fields/richText.vue"));
|
|
67
72
|
// import NewRichTextField from "./fields/newRichText.vue";
|
|
68
|
-
|
|
73
|
+
const FileField = defineAsyncComponent(() => import("./fields/file.vue"));
|
|
69
74
|
import AutocompleteField from "./fields/autocomplete.vue";
|
|
70
75
|
import SelectField from "./fields/select.vue";
|
|
71
76
|
import TimeZoneField from "./fields/timeZone.vue";
|
|
@@ -77,14 +82,14 @@ import CheckGroupField from "./fields/checkGroup.vue";
|
|
|
77
82
|
import CheckField from "./fields/check.vue";
|
|
78
83
|
import DateField from "./fields/date.vue";
|
|
79
84
|
import DateTimeField from "./fields/datetime.vue";
|
|
80
|
-
|
|
85
|
+
const LocationField = defineAsyncComponent(() => import("./fields/location.vue"));
|
|
81
86
|
import GooglePlaceField from "./fields/googlePlace.vue";
|
|
82
87
|
import DynamicGroupField from "./fields/dynamicGroup.vue";
|
|
83
88
|
import StripeTokenField from "./fields/stripeToken.vue";
|
|
84
89
|
import StripeExternalAccount from "./fields/stripeExternalAccount.vue";
|
|
85
90
|
import CreditCardField from "./fields/creditCard.vue";
|
|
86
91
|
import RatingField from "./fields/rating.vue";
|
|
87
|
-
|
|
92
|
+
const PhoneField = defineAsyncComponent(() => import("./fields/phone/field.vue"));
|
|
88
93
|
import TimerField from "./fields/timer.vue";
|
|
89
94
|
import OtpField from "./fields/otpField.vue";
|
|
90
95
|
|
|
@@ -110,16 +115,12 @@ import MultimediaVideo from "./multimedia/video.vue";
|
|
|
110
115
|
import AlertBanner from "./banners/alert.vue";
|
|
111
116
|
import SelectBanner from "./banners/select.vue";
|
|
112
117
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
import LineChart from "./charts/line.vue";
|
|
119
|
+
import ColumnChart from "./charts/column.vue";
|
|
120
|
+
import PieChart from "./charts/pie.vue";
|
|
121
|
+
import AreaChart from "./charts/area.vue";
|
|
117
122
|
|
|
118
|
-
|
|
119
|
-
import Action from "../action";
|
|
120
|
-
|
|
121
|
-
import { getCurrentInstance } from 'vue';
|
|
122
|
-
import { defineAsyncComponent } from "vue";
|
|
123
|
+
const ShareButton = defineAsyncComponent(() => import("./shareButton.vue"));
|
|
123
124
|
|
|
124
125
|
export default {
|
|
125
126
|
components: {
|
|
@@ -149,7 +150,7 @@ export default {
|
|
|
149
150
|
"views-hr": Hr,
|
|
150
151
|
"views-spacer": Spacer,
|
|
151
152
|
|
|
152
|
-
|
|
153
|
+
"views-map": Map,
|
|
153
154
|
"views-tabBar": TabBar,
|
|
154
155
|
"views-calendar": Calendar,
|
|
155
156
|
"views-shareButton": ShareButton,
|
|
@@ -232,14 +233,7 @@ export default {
|
|
|
232
233
|
spec: {
|
|
233
234
|
handler(spec) {
|
|
234
235
|
const name = Utils.app.componentName(spec.view);
|
|
235
|
-
|
|
236
|
-
if (strict) {
|
|
237
|
-
this.name = name;
|
|
238
|
-
} else {
|
|
239
|
-
if (getCurrentInstance().appContext.app.components[name]) {
|
|
240
|
-
this.name = name;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
236
|
+
this.name = name;
|
|
243
237
|
},
|
|
244
238
|
immediate: true
|
|
245
239
|
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { onMounted, ref, nextTick } from "vue";
|
|
2
|
+
import { MarkerClusterer } from "@googlemaps/markerclusterer";
|
|
3
|
+
|
|
4
|
+
function waitForGmapLoaded() {
|
|
5
|
+
return new Promise((resolve) => {
|
|
6
|
+
let intervalId = setInterval(() => {
|
|
7
|
+
if (window._gmapLoaded && window.google) {
|
|
8
|
+
clearInterval(intervalId);
|
|
9
|
+
resolve(true);
|
|
10
|
+
}
|
|
11
|
+
}, 150);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function useAutocomplete({ inputRef, options, onPlaceChanged }) {
|
|
16
|
+
let autocompleteInstance = null;
|
|
17
|
+
onMounted(() => {
|
|
18
|
+
let inputElement = null;
|
|
19
|
+
if (inputRef.value instanceof HTMLElement) {
|
|
20
|
+
inputElement = inputRef.value;
|
|
21
|
+
} else {
|
|
22
|
+
inputElement = inputRef.value.$el.querySelector("input[type='text']");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
autocompleteInstance = new google.maps.places.Autocomplete(inputElement, options);
|
|
26
|
+
|
|
27
|
+
if (onPlaceChanged) {
|
|
28
|
+
autocompleteInstance.addListener('place_changed', () => onPlaceChanged(autocompleteInstance));
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
return { autocompleteInstance };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function useGmap({ mapRef, infoWindowRef, options, locations, showCluster = false, showDirection = false }) {
|
|
36
|
+
let mapInstance = null;
|
|
37
|
+
const markers = ref([]);
|
|
38
|
+
const cluster = ref({});
|
|
39
|
+
const selectedMarker = ref({});
|
|
40
|
+
|
|
41
|
+
let infoWindow = null;
|
|
42
|
+
|
|
43
|
+
const drawDirection = () => {
|
|
44
|
+
let directionService = new google.maps.DirectionsService();
|
|
45
|
+
let directionDisplay = new google.maps.DirectionsRenderer();
|
|
46
|
+
|
|
47
|
+
for (let l = 0; l < locations.length; l++) {
|
|
48
|
+
for (let i = 0; i < locations[l].length; i++) {
|
|
49
|
+
let travel = {
|
|
50
|
+
origin: locations[l][i],
|
|
51
|
+
destination: locations[l][i + 1],
|
|
52
|
+
travelMode: "DRIVING"
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
if (!travel.destination) {
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
directionService.route(travel, (response, status) => {
|
|
60
|
+
if (status === "OK") {
|
|
61
|
+
directionDisplay = new google.maps.DirectionsRenderer({
|
|
62
|
+
suppressMarkers: true,
|
|
63
|
+
polylineOptions: {
|
|
64
|
+
strokeColor: "#2ab3a6",
|
|
65
|
+
stropeOpacity: 0.8,
|
|
66
|
+
strokeWeight: 5
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
directionDisplay.setMap(mapInstance);
|
|
70
|
+
directionDisplay.setDirections(response);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const updateMarkers = (locations) => {
|
|
78
|
+
// remove old markers
|
|
79
|
+
if (showCluster && cluster.value.length >= 1) {
|
|
80
|
+
cluster.value.clearMarkers();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (markers.value && markers.value.length >= 1) {
|
|
84
|
+
markers.value.forEach((marker) => marker.setMap(null));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// show the new one
|
|
88
|
+
if (locations && locations.length >= 1) {
|
|
89
|
+
markers.value = locations.map((value) => {
|
|
90
|
+
const marker = new google.maps.Marker({
|
|
91
|
+
position: value,
|
|
92
|
+
map: mapInstance
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
if (value.infoWindow) {
|
|
96
|
+
marker.addListener('click', () => {
|
|
97
|
+
selectedMarker.value = value;
|
|
98
|
+
|
|
99
|
+
nextTick(() => {
|
|
100
|
+
infoWindow.setContent(infoWindowRef.value);
|
|
101
|
+
|
|
102
|
+
infoWindow.open({
|
|
103
|
+
map: mapInstance,
|
|
104
|
+
anchor: marker
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return marker;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (showCluster) {
|
|
116
|
+
cluster.value = new MarkerClusterer({ map: mapInstance, markers: markers.value });
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const mapPromise = () => {
|
|
121
|
+
return new Promise((resolve) => {
|
|
122
|
+
let intervalId = setInterval(() => {
|
|
123
|
+
if (mapInstance) {
|
|
124
|
+
clearInterval(intervalId);
|
|
125
|
+
resolve(mapInstance);
|
|
126
|
+
}
|
|
127
|
+
}, 50);
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
onMounted(async () => {
|
|
132
|
+
await waitForGmapLoaded();
|
|
133
|
+
// initialize static info window (only one info window per one map)
|
|
134
|
+
infoWindow = new google.maps.InfoWindow;
|
|
135
|
+
|
|
136
|
+
const defaultOptions = {
|
|
137
|
+
zoom: 4,
|
|
138
|
+
center: { lat: -42.162376, lng: 172.671437 },
|
|
139
|
+
mapId: Math.random().toString(36).slice(2, 7)
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
mapInstance = new google.maps.Map(mapRef.value, { ...defaultOptions, ...options });
|
|
143
|
+
|
|
144
|
+
if (locations) {
|
|
145
|
+
updateMarkers([locations].flat());
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
return { updateMarkers, mapPromise, mapInstance, selectedMarker, drawDirection };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|