PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.8
Booking for Appointments and Events Calendar – Amelia v2.4.8
2.4.8 2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / v3 / src / assets / js / public / public.js
ameliabooking / v3 / src / assets / js / public Last commit date
actions.js 1 month ago booking.js 1 day ago cabinet.js 1 month ago cart.js 1 day ago catalog.js 1 day ago coupon.js 1 month ago customFields.js 1 month ago customFontFace.js 1 month ago eventFormCssVars.js 1 month ago events.js 1 month ago facebookPixel.js 1 month ago ivy.js 1 month ago package.js 1 day ago panel.js 1 month ago public.js 1 month ago renderActions.js 1 month ago restore.js 1 day ago slots.js 1 day ago stripePaymentIntent.js 1 day ago translation.js 1 month ago user.js 1 month ago
public.js
506 lines
1 import { createApp, defineAsyncComponent } from 'vue/dist/vue.esm-bundler'
2 import { createStore } from 'vuex'
3 import entities from './../../../store/modules/entities'
4 import booking from './../../../store/modules/booking'
5 import event from './../../../store/modules/event'
6 import attendee from './../../../store/modules/attendee'
7 import appointment from './../../../store/modules/appointment'
8 import employee from './../../../store/modules/employee'
9 import eventEntities from '../../../store/modules/eventEntities'
10 import eventBooking from '../../../store/modules/eventBooking'
11 import shortcodeParams from '../../../store/modules/shortcodeParams'
12 import params from '../../../store/modules/params'
13 import pagination from '../../../store/modules/pagination'
14 import customerInfo from '../../../store/modules/customerInfo'
15 import customFields from '../../../store/modules/customFields'
16 import recurring from '../../../store/modules/recurring'
17 import persons from '../../../store/modules/persons.js'
18 import tickets from '../../../store/modules/tickets.js'
19 import payment from '../../../store/modules/payment.js'
20 import bookableType from '../../../store/modules/bookableType.js'
21 import coupon from '../../../store/modules/coupon.js'
22 import auth from '../../../store/modules/auth.js'
23 import cabinet from '../../../store/modules/cabinet.js'
24 import cabinetFilters from '../../../store/modules/cabinetFilters.js'
25 import eventWaitingListOptions from '../../../store/modules/eventWaitingListOptions'
26 import stepByStepFilters from '../../../store/modules/stepByStepFilters.js'
27 import appointmentWaitingListOptions from '../../../store/modules/appointmentWaitingListOptions'
28
29 import { provide, ref, reactive, readonly } from 'vue'
30 import VueGtag from 'vue-gtag'
31 import { MazUi } from 'maz-ui/plugins'
32 import { mazUi as mazUiThemePreset } from '@maz-ui/themes/presets/mazUi'
33 import 'maz-ui/styles'
34 import { install, init } from './facebookPixel.js'
35
36 import { useLicence } from '../common/licence'
37
38 import dayjs from 'dayjs'
39 import updateLocale from 'dayjs/plugin/updateLocale'
40
41 dayjs.extend(updateLocale)
42
43 dayjs.updateLocale(dayjs.locale(), {
44 weekStart: window.wpAmeliaSettings.wordpress.startOfWeek,
45 })
46
47 // It is necessary to investigate what is the best practice
48 // import axios from './plugins/axios'
49
50 const StepFormWrapper = defineAsyncComponent({
51 loader: () => import('../../../views/public/StepForm/BookingStepForm.vue'),
52 })
53
54 const CatalogFormWrapper = defineAsyncComponent({
55 loader: () => import('../../../views/public/CatalogForm/CatalogForm.vue'),
56 })
57
58 const EventsListFormWrapper = defineAsyncComponent({
59 loader: () => import('../../../views/public/EventForm/EventListForm/EventsListForm.vue'),
60 })
61
62 const EventsCalendarFormWrapper = defineAsyncComponent({
63 loader: () => import('../../../views/public/EventForm/EventCalendarForm/EvensCalendarForm.vue'),
64 })
65
66 const WpaEventsLandingFormWrapper = defineAsyncComponent({
67 loader: () =>
68 import('../../../views/public/EventForm/WpaEventsLandingForm/WpaEventsLandingForm.vue'),
69 })
70
71 const DialogForms = defineAsyncComponent({
72 loader: () => import('../../../views/public/Dialog/DialogForms.vue'),
73 })
74
75 const CustomerPanelWrapper = defineAsyncComponent({
76 loader: () => import('../../../views/public/Cabinet/CustomerPanel/CustomerPanel.vue'),
77 })
78
79 if (typeof window.ameliaShortcodeData === 'undefined') {
80 window.ameliaShortcodeData = [{ counter: null }]
81 }
82
83 const dynamicCdn = window.wpAmeliaUrls.wpAmeliaPluginURL + 'v3/public/'
84
85 window.__dynamic_handler__ = function (importer) {
86 return dynamicCdn + 'assets/' + importer
87 }
88 // @ts-ignore
89 window.__dynamic_preload__ = function (preloads) {
90 return preloads.map((preload) => dynamicCdn + preload)
91 }
92
93 function ameliaBeforeFormSubmit(submit, onError, data) {
94 let formFound = false
95
96 if (window.ameliaShortcodeDataTriggered !== undefined) {
97 window.ameliaShortcodeDataTriggered.forEach((shortcodeData) => {
98 if (parseInt(shortcodeData.ivy) === parseInt(data.formId)) {
99 shortcodeData.ivy = data
100 shortcodeData.trigger = 'ivy'
101
102 setTimeout(() => {
103 const ivyForm = document.getElementsByClassName('ivyforms-form-' + data.formId)[0]
104 if (ivyForm) {
105 ivyForm.style.display = 'none'
106 }
107 }, 200)
108
109 window.amelia.load(shortcodeData)
110
111 formFound = true
112 }
113 })
114 }
115
116 if (!formFound) {
117 submit()
118 }
119 }
120
121 function registerAmeliaIvyFormsHook() {
122 let wpAmeliaSettings = JSON.parse(JSON.stringify(window.wpAmeliaSettings))
123
124 if (wpAmeliaSettings.featuresIntegrations?.ivy?.enabled === false) {
125 return false
126 }
127
128 const register = window.IvyForms?.hooks?.registerBeforeFormSubmit
129
130 if (typeof register !== 'function') {
131 return false
132 }
133
134 window.IvyForms?.hooks?.registerBeforeFormSubmit(ameliaBeforeFormSubmit)
135 }
136
137 if (!registerAmeliaIvyFormsHook()) {
138 window.addEventListener('ivyforms:ready', () => registerAmeliaIvyFormsHook(), { once: true })
139 }
140
141 let isMounted = ref(false)
142
143 function getMazLocale() {
144 const locale = Array.isArray(window.localeLanguage) ? window.localeLanguage[0] : ''
145
146 if (typeof locale !== 'string' || !locale) {
147 return 'en'
148 }
149
150 // Normalize WP locale formats like en_US -> en for maz-ui locale keys.
151 return locale.toLowerCase().replace('_', '-').split('-')[0] || 'en'
152 }
153
154 if (window.ameliaShortcodeDataTriggered !== undefined) {
155 window.ameliaShortcodeDataTriggered.forEach((shortCodeData) => {
156 // * Shortcodes that are rendered in Amelia Popup
157 if (shortCodeData.in_dialog) {
158 // * Collection of all external buttons that are connected to "Amelia popup"
159 let externalButtonsLoading = setInterval(() => {
160 let externalButtons =
161 shortCodeData.trigger_type && shortCodeData.trigger_type === 'class'
162 ? [...document.getElementsByClassName(shortCodeData.trigger)]
163 : [document.getElementById(shortCodeData.trigger)]
164
165 if (
166 externalButtons.length > 0 &&
167 externalButtons[0] !== null &&
168 typeof externalButtons[0] !== 'undefined'
169 ) {
170 clearInterval(externalButtonsLoading)
171
172 // * Detect if form loaded from redirection
173 if ('ameliaCache' in window && window.ameliaCache.length && window.ameliaCache[0]) {
174 let cacheData = JSON.parse(window.ameliaCache[0])
175 if (
176 cacheData &&
177 'request' in cacheData &&
178 'form' in cacheData.request &&
179 'shortcode' in cacheData.request.form &&
180 'trigger' in cacheData.request.form.shortcode &&
181 cacheData.request.form.shortcode.trigger &&
182 parseInt(cacheData.request.form.shortcode.counter) === parseInt(shortCodeData.counter)
183 ) {
184 shortCodeData.isRestored = true
185 }
186 }
187
188 // * vue creation
189 createAmelia(shortCodeData)
190
191 // * Made the buttons invisible because amelia components are not fully loaded
192 externalButtons.forEach((btn) => {
193 btn.style.pointerEvents = 'none'
194 })
195
196 // Create a timeout to prevent buttons from being permanently disabled
197 let componentLoadTimeout
198
199 let componentsLoaded = setInterval(() => {
200 if (isMounted.value) {
201 clearInterval(componentsLoaded)
202 clearTimeout(componentLoadTimeout)
203 // * Made the buttons visible because amelia components are fully loaded
204 externalButtons.forEach((btn) => {
205 btn.style.removeProperty('pointer-events')
206 })
207 }
208 }, 250)
209
210 // Safety timeout - if components don't load within 12 seconds, enable buttons anyway
211 componentLoadTimeout = setTimeout(() => {
212 clearInterval(componentsLoaded)
213 console.warn('Amelia components loading timeout')
214 externalButtons.forEach((btn) => {
215 btn.style.removeProperty('pointer-events')
216 })
217 }, 12000)
218 }
219 }, 250)
220 } else if (!shortCodeData.ivy) {
221 let ameliaPopUpLoaded = false
222
223 let ameliaBookingButtonLoadInterval = setInterval(function () {
224 let ameliaPopUpButtons =
225 shortCodeData.trigger_type && shortCodeData.trigger_type === 'class'
226 ? [...document.getElementsByClassName(shortCodeData.trigger)]
227 : [document.getElementById(shortCodeData.trigger)]
228
229 if (
230 !ameliaPopUpLoaded &&
231 ameliaPopUpButtons.length > 0 &&
232 ameliaPopUpButtons[0] !== null &&
233 typeof ameliaPopUpButtons[0] !== 'undefined'
234 ) {
235 ameliaPopUpLoaded = true
236
237 clearInterval(ameliaBookingButtonLoadInterval)
238 ameliaPopUpButtons.forEach((ameliaPopUpButton) => {
239 ameliaPopUpButton.onclick = function () {
240 let ameliaBookingFormLoadInterval = setInterval(function () {
241 let ameliaPopUpForms = document.getElementsByClassName(
242 'amelia-skip-load-' + shortCodeData.counter,
243 )
244
245 if (ameliaPopUpForms.length) {
246 clearInterval(ameliaBookingFormLoadInterval)
247 for (let i = 0; i < ameliaPopUpForms.length; i++) {
248 if (
249 !ameliaPopUpForms[i].classList.contains(
250 'amelia-v2-booking-' + shortCodeData.counter + '-loaded',
251 )
252 ) {
253 createAmelia(shortCodeData)
254 }
255 }
256 }
257 }, 1000)
258 }
259
260 if ('ameliaCache' in window && window.ameliaCache.length && window.ameliaCache[0]) {
261 let cacheData = JSON.parse(window.ameliaCache[0])
262
263 if (
264 cacheData &&
265 'request' in cacheData &&
266 'form' in cacheData.request &&
267 'shortcode' in cacheData.request.form &&
268 'trigger' in cacheData.request.form.shortcode &&
269 cacheData.request.form.shortcode.trigger
270 ) {
271 if (
272 !('trigger_type' in cacheData.request.form.shortcode) ||
273 !cacheData.request.form.shortcode.trigger_type ||
274 cacheData.request.form.shortcode.trigger_type === 'id'
275 ) {
276 let el = document.getElementById(cacheData.request.form.shortcode.trigger)
277
278 if (typeof el !== 'undefined') {
279 el.click()
280 }
281 } else if (
282 'trigger_type' in cacheData.request.form.shortcode &&
283 cacheData.request.form.shortcode.trigger_type === 'class'
284 ) {
285 let el = document.getElementsByClassName(cacheData.request.form.shortcode.trigger)
286
287 if (typeof el !== 'undefined' && el.length) {
288 el[0].click()
289 }
290 }
291 }
292 }
293 })
294 }
295 }, 1000)
296 }
297 })
298 }
299
300 window.ameliaShortcodeData.forEach((item) => {
301 createAmelia(item)
302 })
303
304 function createAmelia(shortcodeData) {
305 let wpAmeliaSettings = JSON.parse(JSON.stringify(window.wpAmeliaSettings))
306
307 if (window?.ameliaActions?.init) {
308 window.ameliaActions.init(shortcodeData, wpAmeliaSettings)
309 }
310
311 const settings = reactive(wpAmeliaSettings)
312
313 let wpAmeliaTimeZones = 'wpAmeliaTimeZones' in window ? window.wpAmeliaTimeZones : []
314
315 let app = createApp({
316 setup() {
317 const baseURLs = reactive(window.wpAmeliaUrls)
318 const labels = reactive(window.wpAmeliaLabels)
319 const timeZones = reactive(wpAmeliaTimeZones)
320 const timeZone = ref('wpAmeliaTimeZone' in window ? window.wpAmeliaTimeZone[0] : '')
321 const localLanguage = ref(window.localeLanguage[0])
322 const licence = reactive(useLicence())
323 provide('settings', readonly(settings))
324 provide('baseUrls', readonly(baseURLs))
325 provide('labels', readonly(labels))
326 provide('timeZones', readonly(timeZones))
327 provide('timeZone', readonly(timeZone))
328 provide('localLanguage', readonly(localLanguage))
329 provide('shortcodeData', readonly(ref(shortcodeData)))
330 provide('licence', licence)
331 provide('isMounted', isMounted)
332 },
333 })
334
335 if (settings.featuresIntegrations.googleAnalytics.enabled && settings.googleTag.id) {
336 app.use(VueGtag, {
337 config: { id: wpAmeliaSettings.googleTag.id },
338 })
339 }
340
341 if (settings.featuresIntegrations.googleAnalytics.enabled && settings.googleAnalytics.id) {
342 app.use(VueGtag, {
343 config: { id: wpAmeliaSettings.googleAnalytics.id },
344 })
345 }
346
347 if (settings.facebookPixel.id) {
348 install()
349
350 init(wpAmeliaSettings.facebookPixel.id)
351 }
352
353 let data =
354 'ameliaCache' in window && window.ameliaCache.length && window.ameliaCache[0]
355 ? JSON.parse(window.ameliaCache[0])
356 : null
357
358 app.use(MazUi, {
359 theme: {
360 preset: mazUiThemePreset,
361 strategy: 'runtime',
362 darkModeStrategy: 'class',
363 },
364 translations: {
365 locale: getMazLocale(),
366 fallbackLocale: 'en',
367 },
368 })
369
370 app
371 .component('StepFormWrapper', StepFormWrapper)
372 .component('CatalogFormWrapper', CatalogFormWrapper)
373 .component('EventsListFormWrapper', EventsListFormWrapper)
374 .component('EventsCalendarFormWrapper', EventsCalendarFormWrapper)
375 .component('WpaEventsLandingFormWrapper', WpaEventsLandingFormWrapper)
376 .component('DialogForms', DialogForms)
377 .component('CustomerPanelWrapper', CustomerPanelWrapper)
378 .use(
379 createStore({
380 namespaced: true,
381
382 state: () => ({
383 settings: reactive(wpAmeliaSettings),
384 labels: reactive(window.wpAmeliaLabels),
385 localLanguage: ref(window.localeLanguage[0]),
386 baseUrls: reactive(window.wpAmeliaUrls),
387 timeZones: reactive(wpAmeliaTimeZones),
388 timeZone: ref('wpAmeliaTimeZone' in window ? window.wpAmeliaTimeZone[0] : ''),
389 isRtl: ref(document.documentElement.dir === 'rtl'),
390 ready: false,
391 loading: true,
392 formKey: '',
393 restoring:
394 data &&
395 data?.request?.form?.shortcode?.counter &&
396 parseInt(data.request.form.shortcode.counter) === parseInt(shortcodeData.counter),
397 restored: false,
398 ivy: shortcodeData.ivy,
399 }),
400
401 getters: {
402 getSettings(state) {
403 return state.settings
404 },
405
406 getLabels(state) {
407 return state.labels
408 },
409
410 getLocalLanguage(state) {
411 return state.localLanguage
412 },
413
414 getBaseUrls(state) {
415 return state.baseUrls
416 },
417
418 getRestoring(state) {
419 return state.restoring
420 },
421
422 getRestored(state) {
423 return state.restored
424 },
425
426 getReady(state) {
427 return state.ready
428 },
429
430 getLoading(state) {
431 return state.loading
432 },
433
434 getFormKey(state) {
435 return state.formKey
436 },
437
438 getIsRtl(state) {
439 return state.isRtl
440 },
441
442 getIvy(state) {
443 return state.ivy
444 },
445 },
446
447 mutations: {
448 setRestoring(state, payload) {
449 state.restoring = payload
450 },
451
452 setRestored(state, payload) {
453 state.restored = payload
454 },
455
456 setReady(state, payload) {
457 state.ready = payload
458 },
459
460 setLoading(state, payload) {
461 state.loading = payload
462 },
463
464 setFormKey(state, payload) {
465 state.formKey = payload
466 },
467
468 setIvy(state, payload) {
469 state.ivy = payload
470 },
471 },
472
473 modules: {
474 entities,
475 booking,
476 event,
477 attendee,
478 appointment,
479 employee,
480 eventEntities,
481 eventBooking,
482 shortcodeParams,
483 params,
484 pagination,
485 customerInfo,
486 customFields,
487 recurring,
488 persons,
489 tickets,
490 payment,
491 bookableType,
492 coupon,
493 auth,
494 cabinet,
495 cabinetFilters,
496 eventWaitingListOptions,
497 stepByStepFilters,
498 appointmentWaitingListOptions,
499 },
500 }),
501 )
502 .mount(`#amelia-v2-booking${shortcodeData.counter !== null ? '-' + shortcodeData.counter : ''}`)
503 }
504
505 window.amelia = { load: createAmelia }
506