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 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
- import ActionToursStart from "./actions/tours/start";
57
- import ActionToursStop from "./actions/tours/stop";
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
 
@@ -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
  });
@@ -1,5 +1,8 @@
1
+ import { vueApp } from "../../store";
2
+
1
3
  export default class {
2
4
  execute(properties, component) {
5
+ vueApp.richTextValues = {};
3
6
  Utils.http.load(properties, component);
4
7
  }
5
8
  }
@@ -1,5 +1,9 @@
1
+ import { vueApp } from "../../store";
2
+
1
3
  export default class {
2
4
  execute(properties, component) {
5
+ vueApp.richTextValues = {};
6
+
3
7
  if (Utils.settings.reactive) {
4
8
  Utils.http.reload(properties, component);
5
9
  } else {
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) {
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <v-badge :color="badge.backgroundColor || 'red'" :offset-x="badge.offsetX" :offset-y="badge.offsetY" :model-value="badgeExists()" :style="styles()">
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: {
@@ -34,7 +34,7 @@ export default {
34
34
  return determineSize(this.spec.styleClasses)
35
35
  },
36
36
  variant() {
37
- return determineVariant(this.spec.styleClasses, 'text')
37
+ return determineVariant(this.spec.styleClasses, 'elevated')
38
38
  }
39
39
  },
40
40
  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
- import { singleDataSeries } from './series';
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
- import { multipleDataSeries } from './series';
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
- import { multipleDataSeries } from './series';
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
- import { singleDataSeries } from './series';
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 };
@@ -1,33 +1,38 @@
1
1
  <template>
2
- <fields-text v-if="name == 'fields-text'" :spec="spec" type="text" />
3
- <fields-text v-else-if="name == 'fields-number'" :spec="spec" type="number" />
4
- <fields-text v-else-if="name == 'fields-email'" :spec="spec" type="email" />
5
- <fields-text v-else-if="name == 'fields-url'" :spec="spec" type="url" />
6
- <fields-text v-else-if="name == 'fields-password'" :spec="spec" type="password" />
7
- <!-- <fields-textarea v-else-if="spec.view == 'fields/textarea-v1'" :spec="spec" />
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
- <!-- <fields-file v-else-if="spec.view == 'fields/file-v1'" :spec="spec" />
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
- <!-- <fields-country v-else-if="spec.view == 'fields/country-v1'" :spec="spec" /> -->
16
+ <!-- <fields-country v-else-if="spec.view == 'fields/country-v1'" :spec="spec" /> -->
16
17
 
17
- <!-- <fields-latLong v-else-if="spec.view == 'fields/latLong-v1'" :spec="spec" /> -->
18
- <fields-googlePlace v-else-if="spec.view == 'fields/googlePlace-v1'" :spec="spec" />
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
- <!-- <panels-responsive v-else-if="spec.view == 'panels/scroll-v1'" :spec="spec" /> -->
21
+ <!-- <panels-responsive v-else-if="spec.view == 'panels/scroll-v1'" :spec="spec" /> -->
21
22
 
22
- <!-- This component manages its own mouse events, so don't auto-initialize it. -->
23
- <button v-else-if="name == 'button'" :spec="spec" />
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
- <component v-else-if="name" :is="name" :id="spec.id" ref="delegate" :spec="spec"
26
- @[menter]="handlePopover(spec.onMouseEnter)" @[mleave]="handlePopover(spec.onMouseLeave)" />
27
- <div v-else>Unsupported view: {{ spec.view }}</div>
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
- import Datetime from "./datetime.vue";
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
- // import Map from "./map.vue";
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
- import FileField from "./fields/file.vue";
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
- import LocationField from "./fields/location.vue";
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
- import PhoneField from "./fields/phone/field.vue";
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
- const LineChart = defineAsyncComponent(() => import("./charts/line.vue"));
114
- const ColumnChart = defineAsyncComponent(() => import("./charts/column.vue"));
115
- const PieChart = defineAsyncComponent(() => import("./charts/pie.vue"));
116
- const AreaChart = defineAsyncComponent(() => import("./charts/area.vue"));
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
- import ShareButton from "./shareButton.vue";
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
- // "views-map": Map,
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
- const strict = true;
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
+