PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 1.2.20
Booking for Appointments and Events Calendar – Amelia v1.2.20
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 / assets / views / backend / notifications / common / CustomizeNotifications.vue
ameliabooking / assets / views / backend / notifications / common Last commit date
CustomizeNotifications.vue 1 year ago DialogCombinedPlaceholder.vue 2 years ago DialogManageLanguages.vue 1 year ago DialogPlaceholders.vue 2 years ago InlinePlaceholders.vue 2 years ago
CustomizeNotifications.vue
2295 lines
1 <template>
2 <div>
3
4 <!-- Customize Notifications -->
5 <el-row class="am-customize-notifications">
6
7 <!-- User Type Tabs -->
8 <el-col :md="8" class="">
9 <div class="am-section am-gray-section">
10 <el-tabs v-model="userTypeTab" @tab-click="onChangeUserTypeTab" :active-name="notification.sendTo">
11
12 <!-- To Customer -->
13 <el-tab-pane :label="$root.labels.to_customer" name="customer">
14 <div v-for="entity in ['appointment', 'event', 'customer_other_notifications']"
15 class="am-email-notification-buttons">
16
17 <div class="am-email-notification-labels">
18 {{$root.labels[entity]}} {{$root.labels.notifications}}
19 </div>
20
21 <!-- Create Notification Button -->
22 <div
23 v-if="notInLicence() ? licenceVisible() : true"
24 class="am-button-checkbox"
25 :class="entity !== 'customer_other_notifications' && notInLicence() ? licenceClass() : {}"
26 >
27
28 <el-button
29 size="large"
30 class='am-active-create'
31 style="position:relative;"
32 @click="createNew(entity, true)"
33 v-if="entity !== 'customer_other_notifications'"
34 :disabled="notInLicence()"
35 >
36 <img :src="$root.getUrl+'public/img/am-plus.svg'" style="position: absolute; left:16px"/>
37 {{ $root.labels.create_notification }}
38 </el-button>
39
40 <LicenceBlock
41 v-if="entity !== 'customer_other_notifications' && notInLicence()"
42 >
43 </LicenceBlock>
44 </div>
45 <!-- /Create Notification Button -->
46
47 <!-- Customer's Notifications -->
48 <div
49 v-for="(item, index) in customerNotifications(entity)"
50 v-if="visibleNotification(item.name)"
51 :class="getUnavailableNotificationLicence(item.name) ? licenceClass(getUnavailableNotificationLicence(item.name)) : {}"
52 :style="{marginTop: '24px'}"
53 >
54 <div
55 class="am-button-checkbox"
56 :style="{marginTop: disabledNotification(item.name) ? '0px' : ''}"
57 >
58 <!-- Customer's Notification Button -->
59 <el-button
60 :disabled="disabledNotification(item.name)"
61 size="large"
62 :key="index"
63 @click="getNotification(item.id)"
64 :class="{ 'am-active': item.id === notification.id && showActiveClass, 'text-margin': item.customName && (item.time || item.timeBefore || item.timeAfter) }"
65 >
66 {{ item.customName ? item.customName : $root.labels[item.name] }}
67 </el-button>
68 <!-- /Customer's Notification Button -->
69
70 <!-- Customer's Notification Status Checkbox -->
71 <el-checkbox
72 v-model="item.status"
73 :disabled="disabledNotification(item.name)"
74 @change="changeNotificationStatus(item)"
75 true-label="enabled"
76 false-label="disabled"
77 >
78 </el-checkbox>
79 <!-- /Customer's Notification Status Checkbox -->
80
81 <!-- Customer's Notification Tooltip For Custom Notifications -->
82 <el-tooltip
83 v-if="item.customName"
84 class="item"
85 effect="dark"
86 :content="$root.labels.custom_notification"
87 placement="top"
88 >
89 <span class="am-cron-icon" :class="{ 'active': item.id === notification.id && showActiveClass , 'right': item.time || item.timeBefore || item.timeAfter }">
90 <img class="svg-amelia" :src="$root.getUrl+'public/img/am-edit-notification.svg'"/>
91 </span>
92 </el-tooltip>
93 <!-- /Customer's Notification Tooltip For Custom Notifications -->
94
95 <!-- Customer's Notification Tooltip For Scheduled Notifications -->
96 <el-tooltip
97 v-if="(item.time && item.time !== '00:00:00') || item.timeBefore || item.timeAfter"
98 class="item"
99 effect="dark"
100 :content="$root.labels.requires_scheduling_setup"
101 placement="top"
102 >
103 <span class="am-cron-icon" :class="{ 'active': item.id === notification.id && showActiveClass }">
104 <img class="svg-amelia" :src="$root.getUrl+'public/img/cron-job.svg'"/>
105 </span>
106 </el-tooltip>
107 <!-- /Customer's Notification Tooltip For Scheduled Notifications -->
108 </div>
109
110 <LicenceBlock
111 v-if="getUnavailableNotificationLicence(item.name)"
112 :licence="getUnavailableNotificationLicence(item.name)"
113 >
114 </LicenceBlock>
115
116 </div>
117 <!-- /Customer's Notification -->
118
119 </div>
120 </el-tab-pane>
121 <!-- /To Customer -->
122
123 <!-- To Employee -->
124 <el-tab-pane :label="$root.labels.to_employee" name="provider">
125 <div
126 v-for="entity in ['appointment', 'event', 'provider_other_notifications']"
127 class="am-email-notification-buttons"
128 >
129
130 <div class="am-email-notification-labels">
131 {{$root.labels[entity]}} {{$root.labels.notifications}}
132 </div>
133
134 <!-- Create Notification Button -->
135 <div
136 v-if="notInLicence() ? licenceVisible() : true"
137 class="am-button-checkbox"
138 :class="entity !== 'provider_other_notifications' && notInLicence() ? licenceClass() : {}"
139 >
140
141 <el-button
142 size="large"
143 class='am-active-create'
144 style="position:relative;"
145 @click="createNew(entity, false)"
146 v-if="entity !== 'provider_other_notifications'"
147 :disabled="notInLicence()"
148 >
149 <img :src="$root.getUrl+'public/img/am-plus.svg'" style="position: absolute; left:16px"/>
150 {{ $root.labels.create_notification }}
151 </el-button>
152
153 <LicenceBlock
154 v-if="entity !== 'provider_other_notifications' && notInLicence()"
155 >
156 </LicenceBlock>
157 </div>
158 <!-- /Create Notification Button -->
159
160 <!-- Employee's Notifications -->
161 <div
162 v-for="(item, index) in employeeNotifications(entity)"
163 v-if="visibleNotification(item.name)"
164 :class="getUnavailableNotificationLicence(item.name) ? licenceClass(getUnavailableNotificationLicence(item.name)) : {}"
165 :style="{marginTop: '24px'}"
166 >
167 <div
168 class="am-button-checkbox"
169 :style="{marginTop: disabledNotification(item.name) ? '0px' : ''}"
170 >
171 <!-- Employee's Notification Button -->
172 <el-button
173 :disabled="disabledNotification(item.name)"
174 size="large"
175 :key="index"
176 @click="getNotification(item.id)"
177 :class="{ 'am-active': item.id === notification.id && showActiveClass, 'text-margin': item.customName && (item.time || item.timeBefore || item.timeAfter) }"
178 >
179 {{ item.customName ? item.customName : $root.labels[item.name] }}
180 </el-button>
181 <!-- /Employee's Notification Button -->
182
183 <!-- Employee's Notification Status Checkbox -->
184 <el-checkbox
185 v-model="item.status"
186 :disabled="disabledNotification(item.name)"
187 @change="changeNotificationStatus(item)"
188 true-label="enabled"
189 false-label="disabled"
190 >
191 </el-checkbox>
192 <!-- /Employee's Notification Status Checkbox -->
193
194 <!-- Employee's Notification Tooltip For Custom Notifications -->
195 <el-tooltip
196 v-if="item.customName"
197 class="item"
198 effect="dark"
199 :content="$root.labels.custom_notification"
200 placement="top"
201 >
202 <span class="am-cron-icon" :class="{ 'active': item.id === notification.id && showActiveClass , 'right': item.time || item.timeBefore || item.timeAfter }">
203 <img class="svg-amelia" :src="$root.getUrl+'public/img/am-edit-notification.svg'"/>
204 </span>
205 </el-tooltip>
206 <!-- /Employee's Notification Tooltip For Custom Notifications -->
207
208 <!-- Employee's Notification Tooltip For Scheduled Notifications -->
209 <el-tooltip
210 v-if="item.time || item.timeBefore || item.timeAfter"
211 class="item"
212 effect="dark"
213 :content="$root.labels.requires_scheduling_setup"
214 placement="top"
215 >
216 <span class="am-cron-icon" :class="{ 'active': item.id === notification.id }">
217 <img class="svg-amelia" :src="$root.getUrl+'public/img/cron-job.svg'"/>
218 </span>
219 </el-tooltip>
220 <!-- /Employee's Notification Tooltip For Scheduled Notifications -->
221 </div>
222
223 <LicenceBlock
224 v-if="getUnavailableNotificationLicence(item.name)"
225 :licence="getUnavailableNotificationLicence(item.name)"
226 >
227 </LicenceBlock>
228
229 </div>
230 <!-- /Employee's Notifications -->
231
232 </div>
233 </el-tab-pane>
234 <!-- /To Employee -->
235
236 </el-tabs>
237 </div>
238 </el-col>
239 <!-- /User Type Tabs -->
240
241 <!-- Right Side Content -->
242 <el-col :md="16">
243
244 <!-- Content -->
245 <div class="am-section am-email-form-settings">
246 <transition name="fadeIn">
247 <el-form :model="notification" ref="notification" :rules="rules" @submit.prevent="createNotification">
248
249
250 <div v-if="createNewContent">
251
252 <el-row :gutter="16">
253 <!-- Create Notification -->
254 <el-col :lg="12" :md="12" :sm="12" :xs="24">
255 <div>
256 <h2 v-if="!showActiveClass">{{ $root.labels.create_notification }}</h2>
257 <h2 v-else>{{ this.notification.customName }}</h2>
258 </div>
259 </el-col>
260
261 <el-col :lg="12" :md="12" :sm="12" :xs="24" style="display: flex; justify-content: flex-end">
262 <el-button v-if="!showActiveClass" size="small" @click="getNotification(null)">
263 {{ $root.labels.discard }}
264 </el-button>
265 <el-select
266 v-if="showActiveClass"
267 class="duplicate"
268 :value="$root.labels.duplicate"
269 @change="duplicateNotification($event)"
270 >
271 <el-option
272 v-for="option in duplicateOptions"
273 :key="option.value"
274 :label="option.label"
275 :value="option.value">
276 </el-option>
277 </el-select>
278 <div v-if="showActiveClass">
279 <el-button size="small" @click="showDelete = !showDelete" :loading="!fetchedDelete" style="position: relative">
280 <img :src="$root.getUrl+'public/img/am-trashcan-red.svg'" style="vertical-align: text-bottom">
281 <span class="red">{{ $root.labels.delete }}</span>
282 </el-button>
283 <div v-if="showDelete" class="deleteModal">
284 <p v-html="$root.labels.delete_message">
285 </p>
286 <div style="display: flex; justify-content: flex-end">
287 <el-button size="small" @click="showDelete = false">{{ $root.labels.cancel }}</el-button>
288 <el-button size="small" type="danger" @click="deleteNotification">{{ $root.labels.delete }}</el-button>
289 </div>
290 </div>
291 </div>
292
293 </el-col>
294 <!-- /Create Notification -->
295 </el-row>
296
297 <el-row>
298 <el-col :md="12" :lg="12" :sm="24">
299 <p style="margin:0">{{ $root.labels.notification_name }}</p>
300 <el-form-item prop="notificationCustomName">
301 <el-input
302 v-model="notificationName"
303 ref="notificationName"
304 :placeholder="$root.labels.notification_name_enter"/>
305 </el-form-item>
306
307 </el-col>
308 </el-row>
309
310 <!-- Enable New Notification -->
311 <el-row>
312 <el-col :md="10" :lg="12">
313 <el-switch v-model="notificationEnabled" />
314 <p style="display: inline-block; margin:0; margin-left: 10px">
315 {{ $root.labels.notification_enabled }}
316 </p>
317 </el-col>
318 </el-row>
319 <!-- /Enable New Notification -->
320 <hr style="margin-top: 16px; margin-bottom: 16px"/>
321
322 <el-row>
323 <el-col>
324 <p>{{ $root.labels.notification_type }}</p>
325 <el-radio v-model="notificationType" label="triggered">{{ $root.labels.notification_triggered }}</el-radio>
326 <el-radio v-model="notificationType" label="scheduled">{{ $root.labels.notification_scheduled }}</el-radio>
327 </el-col>
328 </el-row>
329
330 <el-row v-if="notificationType === 'triggered' && notificationEntity === 'appointment'">
331 <el-col>
332 <p>{{ $root.labels.notification_appointment_status }}</p>
333 <el-radio v-model="notificationTrigger" label="approved">{{ $root.labels.approved }}</el-radio>
334 <el-radio v-model="notificationTrigger" label="pending">{{ $root.labels.pending }}</el-radio>
335 <el-radio v-model="notificationTrigger" label="canceled">{{ $root.labels.canceled }}</el-radio>
336 <el-radio v-model="notificationTrigger" label="rejected">{{ $root.labels.rejected }}</el-radio>
337 <el-radio v-model="notificationTrigger" label="rescheduled">{{ $root.labels.rescheduled }}</el-radio>
338 <el-radio v-model="notificationTrigger" label="updated">{{ $root.labels.details_changed }}</el-radio>
339 </el-col>
340 </el-row>
341
342 <el-row v-if="notificationType === 'triggered' && notificationEntity === 'event'">
343 <el-col>
344 <p>{{ $root.labels.notification_event_action }}</p>
345 <el-radio v-model="notificationTrigger" label="approved">{{ $root.labels.booked }}</el-radio>
346 <el-radio v-model="notificationTrigger" label="rejected">{{ $root.labels.canceled_by_admin }}</el-radio>
347 <el-radio v-model="notificationTrigger" label="canceled">{{ $root.labels.canceled_by_attendee }}</el-radio>
348 <el-radio v-model="notificationTrigger" label="rescheduled">{{ $root.labels.rescheduled }}</el-radio>
349 <el-radio v-model="notificationTrigger" label="updated">{{ $root.labels.details_changed }}</el-radio>
350 </el-col>
351 </el-row>
352
353 <el-row v-if="notificationEntity === 'appointment'">
354 <el-col :lg="12" :md="12" :sm="24">
355 <p>{{ $root.labels.services }}</p>
356 <el-select
357 v-model="selectedServices"
358 :placeholder="$root.labels.all_services"
359 multiple
360 filterable
361 collapse-tags
362 >
363 <el-option
364 v-for="service in services"
365 :key="service.id"
366 :label="service.name"
367 :value="service.id">
368 </el-option>
369 </el-select>
370 </el-col>
371 </el-row>
372
373 <el-row v-if="notificationEntity === 'event'">
374 <el-col :lg="12" :md="12" :sm="24">
375 <p>{{ $root.labels.events }}</p>
376 <el-select
377 v-model="selectedEvents"
378 :placeholder="$root.labels.all_events"
379 :remote-method="query => searchEvents(query, true)"
380 :loading="loadingEvents"
381 remote
382 multiple
383 filterable
384 collapse-tags
385 >
386 <el-option
387 v-for="event in searchedEvents"
388 :key="event.id"
389 :label="event.displayName ? event.displayName : event.name"
390 :value="event.id">
391 </el-option>
392 </el-select>
393 </el-col>
394 </el-row>
395
396 <!-- Send Only New Notification -->
397 <el-row v-if="notificationType !== 'scheduled' || notificationTimed !== 'sameDay'">
398 <el-col :md="10" :lg="12">
399 <el-switch v-model="sendOnlyMe" />
400 <p style="display: inline-block; margin:0; margin-left: 10px">
401 {{ $root.labels.send_only_this }}
402 </p>
403 <el-tooltip placement="top">
404 <div slot="content" v-if="entity === 'appointment'" v-html="$root.labels.send_only_this_tooltip"></div>
405 <div slot="content" v-if="entity === 'event'" v-html="$root.labels.send_only_this_tooltip_event"></div>
406 <i class="el-icon-question am-tooltip-icon"></i>
407 </el-tooltip>
408 </el-col>
409 </el-row>
410 <!-- /Send Only New Notification -->
411
412 <hr style="margin-top: 16px; margin-bottom: 16px"/>
413
414 <div v-if="notificationType === 'scheduled'">
415 <el-row>
416 <el-col>
417 <p>{{ $root.labels.schedule }}</p>
418 <el-radio v-model="notificationTimed" label="before">{{ $root.labels.before }}</el-radio>
419 <el-radio v-model="notificationTimed" label="after">{{ $root.labels.after }}</el-radio>
420 <el-radio v-model="notificationTimed" label="sameDay">{{ $root.labels.same_day }}</el-radio>
421 </el-col>
422 </el-row>
423
424 <el-row>
425 <el-col>
426 <p v-if="notificationTimed !== 'sameDay'">{{ $root.labels.choose_when }}</p>
427 <p v-else>{{ $root.labels.time }}</p>
428 </el-col>
429 </el-row>
430
431 <el-row v-if="notificationTimed !== 'sameDay'" :gutter="10">
432 <el-col :lg="6" :md="6" :sm="24">
433 <el-input-number
434 :min="1"
435 v-model="amountTime"
436 :placeholder="$root.labels.enter_number"
437 ></el-input-number>
438 </el-col>
439 <el-col :lg="6" :md="6" :sm="24">
440 <el-select
441 v-model="intervalTime"
442 value-key="id"
443 >
444 <el-option
445 v-for="interval in intervalTimes"
446 :key="interval.value"
447 :label="interval.label"
448 :value="interval.value">
449 </el-option>
450 </el-select>
451
452 </el-col>
453 </el-row>
454
455 <el-row v-else>
456 <el-col :lg="8" :md="8" :sm="24">
457 <el-form-item>
458 <el-time-select
459 :picker-options="getTimeSelectOptionsWithLimits(null, null)"
460 v-model="onTime"/>
461 </el-form-item>
462 </el-col>
463 </el-row>
464
465 <hr style="margin-top: 16px; margin-bottom: 16px"/>
466
467 </div>
468
469 </div>
470
471 <!-- Name & Show Email Codes -->
472 <el-row :gutter="16">
473
474 <!-- Notification Name -->
475 <el-col :span="12" v-if="!createNewContent">
476 <div>
477 <h2>{{ $root.labels[notification.name] }}</h2>
478 <h3 v-if="notificationTimeBased">
479 {{ $root.labels['notification_scheduled'] }}
480 </h3>
481 <h3 v-if="notification.customName">{{ $root.labels[notification.name] }}</h3>
482 </div>
483 </el-col>
484 <!-- /Notification Name -->
485
486 <el-col :span="!createNewContent ? 12 : 24">
487 <!-- Show Email Codes Button -->
488 <div class="align-right">
489 <p class="am-blue-link" @click="showDialogPlaceholders">
490 {{ $root.labels['show_' + type + '_codes'] }}
491 </p>
492 </div>
493 <!-- /Show Email Codes Button -->
494
495 <!-- Select Language -->
496 <div class="align-right" v-if="notification.name !== 'customer_invoice' && notification.sendTo === 'customer' && type !== 'whatsapp' && usedLanguages.length > 0">
497 <el-select class="select-languages" :placeholder="$root.labels.language" v-model="selectedLanguage" clearable filterable @change="changeLanguage">
498 <li class="el-select-dropdown__item" @click="manageLanguages">
499 <span>
500 <img class="option-languages-flag" :src="$root.getUrl+'public/img/translate.svg'">
501 {{ $root.labels.manage_languages }}
502 </span>
503 </li>
504 <hr v-if="usedLanguages.length > 0">
505
506 <template slot="prefix">
507 <img class="select-languages-flag" :src="getLanguageFlag(selectedLanguage)">
508 </template>
509
510 <el-option
511 v-for="(lang, index) in usedLanguages"
512 :key="index"
513 :label="getLanguageLabel(lang)"
514 :value="lang"
515 >
516 <span>
517 <img class="option-languages-flag" :src="getLanguageFlag(lang)">
518 {{ getLanguageLabel(lang) }}
519 </span>
520 </el-option>
521
522 </el-select>
523 </div>
524 <!-- /Select Language -->
525
526 <div v-if="type === 'whatsapp'" class="am-whatsapp-settings-button">
527 <el-button size="small" @click="$emit('openSettings')">
528 <img :src="$root.getUrl+'public/img/am-settings-slider.svg'" style="vertical-align: text-bottom">
529 <span>{{ $root.labels.whatsapp_settings }}</span>
530 </el-button>
531 </div>
532
533 </el-col>
534
535 </el-row>
536 <!-- /Name & Show Email Codes -->
537
538
539 <!-- Inputs -->
540 <el-row :gutter="16">
541
542 <!-- Subject -->
543 <el-col :span="notificationTimeBased && !createNewContent ? 18 : 24" v-if="type === 'email'">
544 <el-form-item :label="$root.labels.subject + ':'">
545 <el-input type="text" v-model="notificationSubject"></el-input>
546 </el-form-item>
547 </el-col>
548 <!-- /Subject -->
549
550 <!-- Templates -->
551 <el-col :span="notificationTimeBased && !createNewContent ? 18 : 24" v-if="type === 'whatsapp'">
552 <el-form-item>
553 <div style="line-height: 40px;">
554 {{ $root.labels.whatsapp_template_name + ':' }}
555 </div>
556 <el-select v-model="notification.whatsAppTemplate" :placeholder="$root.labels.whatsapp_choose_template" @change="updatePlaceholders()">
557 <el-option
558 v-for="template in templates"
559 :key="template.id"
560 :value="template.name"
561 :label="template.name"
562 >
563 <div style="display: flex;justify-content: space-between;">
564 <span>{{template.name}}</span>
565 <span v-if="template.status" :style="{'color': getStatusColor(template) }">{{ template.status ? template.status.charAt(0) + template.status.slice(1).toLowerCase() : '' }}</span>
566 </div>
567 </el-option>
568 </el-select>
569 </el-form-item>
570 </el-col>
571 <!-- /Templates -->
572
573 <!-- Time -->
574 <el-col v-if="notificationTime && !createNewContent" :span="6">
575 <el-form-item :label="$root.labels.scheduled_for + ':'">
576 <el-time-select
577 v-model="notificationTime"
578 :picker-options="timeSelectOptions"
579 :clearable="false"
580 >
581 </el-time-select>
582 </el-form-item>
583 </el-col>
584 <!-- /Time -->
585
586 <!-- Time Before -->
587 <el-col v-if="notification.timeBefore && !createNewContent" :span="6">
588 <el-form-item :label="$root.labels.scheduled_before + ':'">
589 <el-select v-model="notification.timeBefore">
590 <el-option
591 v-for="item in getPossibleDurationsInSeconds(notification.timeBefore, 86400)"
592 :key="item"
593 :label="secondsToNiceDuration(item)"
594 :value="item"
595 >
596 </el-option>
597 </el-select>
598 </el-form-item>
599 </el-col>
600 <!-- /Time Before -->
601
602 <!-- Time After -->
603 <el-col v-if="notification.timeAfter && !createNewContent" :span="6">
604 <el-form-item :label="(notification.entity === 'appointment' ? $root.labels.scheduled_after_appointment : $root.labels.scheduled_after_event) + ':'">
605 <el-select v-model="notification.timeAfter">
606 <el-option
607 v-for="item in getPossibleDurationsInSeconds(notification.timeAfter, 86400)"
608 :key="item"
609 :label="secondsToNiceDuration(item)"
610 :value="item"
611 >
612 </el-option>
613 </el-select>
614 </el-form-item>
615 </el-col>
616 <!-- /Time After -->
617
618 </el-row>
619 <!-- /Inputs -->
620
621
622 <!-- Whatsapp Header -->
623 <div v-if="type === 'whatsapp' && getWhatsAppComponent('header')">
624 <el-row>
625 <el-form-item :label="$root.labels.whatsapp_header + ':'">
626 <!-- Textarea -->
627 <el-input
628 v-if="getWhatsAppComponent('header').text"
629 :value="getWhatsAppComponent('header').text"
630 placeholder=""
631 :disabled="true"
632 >
633 </el-input>
634 </el-form-item>
635 </el-row>
636
637 <WhatsAppPlaceholders
638 ref="whatsAppHeader"
639 class="am-whatsapp-ph-header"
640 :whatsapp-placeholders="whatsAppPlaceholders.header"
641 :rules="whatsAppPhRules.header"
642 name="header"
643 :all-placeholders="getSortedInlinePlaceholders()"
644 :categories="categories"
645 :coupons="coupons"
646 :custom-fields="customFields"
647 :events="events"
648 :userTypeTab="userTypeTab"
649 :all-placeholder-types="groupedPlaceholders"
650 :notification="notification"
651 >
652 </WhatsAppPlaceholders>
653 <!-- /Whatsapp Header -->
654 </div>
655
656
657 <!-- Message -->
658 <el-form-item>
659 <el-row type="flex" align="middle" :gutter="24" style="margin-bottom: 10px;">
660 <el-col :span="12" style="padding-bottom: 5px;">
661 {{ $root.labels.message_colon }}
662 </el-col>
663
664 <el-col :span="12" class="align-right" v-if="type === 'email'">
665 <el-button-group>
666 <el-button
667 size="mini"
668 :type="textMode ? 'default' : 'primary'"
669 @click="changeTextMode"
670 >
671 {{ $root.labels.text_mode }}
672 </el-button>
673 <el-button
674 size="mini"
675 :type="textMode ? 'primary' : 'default'"
676 @click="changeTextMode"
677 >
678 {{ $root.labels.html_mode }}
679 </el-button>
680 </el-button-group>
681 </el-col>
682 </el-row>
683
684 <el-row v-if="type === 'email'">
685 <el-col>
686 <el-alert
687 type="warning"
688 show-icon
689 title=""
690 :description="$root.labels.content_mode_tooltip"
691 :closable="false"
692 style="margin-bottom: 10px"
693 >
694 </el-alert>
695 </el-col>
696 </el-row>
697
698 <!-- Quill Editor -->
699 <quill-editor
700 ref="notificationContent"
701 v-if="type === 'email' && !textMode"
702 v-model="notificationContent"
703 :options="editorOptions"
704 @change="parseQuillEditorContent"
705 >
706 </quill-editor>
707 <!-- /Quill Editor -->
708 <el-input
709 v-if="type === 'email' && textMode"
710 v-model="notificationContentText"
711 type="textarea"
712 :rows="7"
713 placeholder=""
714 @input="changedContentText('notificationContent', 'notificationContentText', null)"
715 >
716 </el-input>
717
718 <!-- Textarea -->
719 <el-input
720 ref="notificationContent"
721 v-if="type === 'sms'"
722 v-model="notificationContent"
723 type="textarea"
724 :rows="7"
725 placeholder=""
726 >
727 </el-input>
728 <!-- /Textarea -->
729
730 <!-- Textarea -->
731 <el-input
732 ref="notificationContent"
733 v-if="type === 'whatsapp' && getWhatsAppComponent('body')"
734 type="textarea"
735 :rows="7"
736 :disabled="true"
737 :value="getWhatsAppComponent('body').text"
738 >
739 </el-input>
740 <!-- /Textarea -->
741
742 <WhatsAppPlaceholders
743 ref="whatsAppBody"
744 v-if="type === 'whatsapp'"
745 :whatsapp-placeholders="whatsAppPlaceholders.body"
746 :notification="notification"
747 :rules="whatsAppPhRules.body"
748 :all-placeholders="getSortedInlinePlaceholders()"
749 name="body"
750 :categories="categories"
751 :coupons="coupons"
752 :custom-fields="customFields"
753 :events="events"
754 :userTypeTab="userTypeTab"
755 :all-placeholder-types="groupedPlaceholders"
756 >
757 </WhatsAppPlaceholders>
758
759 </el-form-item>
760 <!-- /Message -->
761
762 <!-- Insert email placeholders -->
763 <el-form-item v-if="type !== 'whatsapp'">
764 {{ $root.labels.insert_email_placeholders }}:
765 <el-tooltip placement="top">
766 <div slot="content" v-html="$root.labels.insert_email_placeholders_tooltip"></div>
767 <i class="el-icon-question am-tooltip-icon"></i>
768 </el-tooltip>
769 <inline-placeholders
770 :placeholdersNames="getInlinePlaceholdersNames(notification)"
771 :excludedPlaceholders="getExcludedPlaceholders(notification, false, false, true)"
772 :customFields="customFields"
773 :categories="categories"
774 :coupons="coupons"
775 :userTypeTab="userTypeTab"
776 :no-html="type !== 'email'"
777 >
778 </inline-placeholders>
779 </el-form-item>
780 <!-- /Insert email placeholders -->
781
782 <el-row class="am-customize-notifications-combined"
783 v-if="notification.name === 'customer_package_purchased' || notification.name === 'provider_package_purchased' || notification.name === 'customer_package_canceled' || notification.name === 'provider_package_canceled'"
784 >
785 <el-col :span="16">
786 <div class="am-customize-notifications-combined-tooltip">
787 <strong>{{ $root.labels.package_placeholder_label }}</strong>
788 %package_appointments_details%
789 <el-tooltip placement="top">
790 <div slot="content" v-html="$root.labels.ph_package_tooltip"></div>
791 <i class="el-icon-question am-tooltip-icon"/>
792 </el-tooltip>
793 </div>
794 </el-col>
795
796 <el-col :span="8" class="am-align-right">
797 <p class="am-blue-link" @click="openDialogCombinedPlaceholders('packagePlaceholders' + (userTypeTab === 'customer' ? 'Customer' : ''))">
798 {{ $root.labels.configure_placeholder_here }}
799 </p>
800 </el-col>
801 </el-row>
802
803 <el-row class="am-customize-notifications-combined"
804 v-if="!notInLicence() && entity === 'appointment' && (!notification.customName &&
805 (notification.name === 'customer_appointment_approved' ||
806 notification.name === 'provider_appointment_approved' ||
807 notification.name === 'customer_appointment_pending' ||
808 notification.name === 'provider_appointment_pending') ||
809 (notification.customName && notificationType === 'triggered' && (notificationTrigger === 'approved' || notificationTrigger === 'pending')))"
810 >
811 <el-col :span="16">
812 <div class="am-customize-notifications-combined-tooltip">
813 <strong>{{ $root.labels.ph_recurring_appointments_details }}</strong>
814 %recurring_appointments_details%
815 <el-tooltip placement="top">
816 <div slot="content" v-html="$root.labels.ph_recurring_tooltip"></div>
817 <i class="el-icon-question am-tooltip-icon"></i>
818 </el-tooltip>
819 </div>
820 </el-col>
821
822 <el-col :span="8" class="am-align-right">
823 <p class="am-blue-link" @click="openDialogCombinedPlaceholders('recurringPlaceholders' + (userTypeTab === 'customer' ? 'Customer' : ''))">
824 {{ $root.labels.configure_placeholder_here }}
825 </p>
826 </el-col>
827 </el-row>
828 <el-row
829 class="am-customize-notifications-combined"
830 v-else-if="(!notInLicence('pro') && userTypeTab === 'customer' && notification.name === 'customer_cart') || (!notInLicence('pro') && userTypeTab === 'provider' && notification.name === 'provider_cart')"
831 >
832 <el-col :span="16">
833 <div class="am-customize-notifications-combined-tooltip">
834 <strong>{{ $root.labels.ph_cart_appointments_details }}</strong>
835 %cart_appointments_details%
836 <el-tooltip placement="top">
837 <div slot="content" v-html="$root.labels.ph_group_appointments_tooltip"></div>
838 <i class="el-icon-question am-tooltip-icon"></i>
839 </el-tooltip>
840 </div>
841 </el-col>
842
843 <el-col :span="8" class="am-align-right">
844 <p class="am-blue-link" @click="openDialogCombinedPlaceholders('cartPlaceholders' + (userTypeTab === 'customer' ? 'Customer' : ''))">
845 {{ $root.labels.configure_placeholder_here }}
846 </p>
847 </el-col>
848 </el-row>
849
850 <el-row class="am-customize-notifications-combined" v-if="!notInLicence() && notification.sendTo === 'provider' && entity === 'appointment' && notification.name !== 'customer_cart' && notification.name !== 'provider_cart'">
851 <el-col :span="16">
852 <div class="am-customize-notifications-combined-tooltip">
853 <strong>{{ $root.labels.ph_group_appointment_details }}</strong>
854 %group_appointment_details%
855 <el-tooltip placement="top">
856 <div slot="content" v-html="$root.labels.ph_group_appointments_tooltip"></div>
857 <i class="el-icon-question am-tooltip-icon"></i>
858 </el-tooltip>
859 </div>
860 </el-col>
861
862 <el-col :span="8" class="am-align-right">
863 <p class="am-blue-link" @click="openDialogCombinedPlaceholders('groupAppointmentPlaceholder')">
864 {{ $root.labels.configure_placeholder_here }}
865 </p>
866 </el-col>
867 </el-row>
868
869 <el-row class="am-customize-notifications-combined" v-if="notification.sendTo === 'provider' && entity === 'event'">
870 <el-col :span="16">
871 <div class="am-customize-notifications-combined-tooltip">
872 <strong>{{ $root.labels.ph_group_event_details }}</strong>
873 %group_event_details%
874 <el-tooltip placement="top">
875 <div slot="content" v-html="$root.labels.ph_group_event_tooltip"></div>
876 <i class="el-icon-question am-tooltip-icon"></i>
877 </el-tooltip>
878 </div>
879 </el-col>
880
881 <el-col :span="8" class="am-align-right">
882 <p class="am-blue-link" @click="openDialogCombinedPlaceholders('groupEventPlaceholder')">
883 {{ $root.labels.configure_placeholder_here }}
884 </p>
885 </el-col>
886 </el-row>
887
888
889 <div v-if="notification.timeBefroe || notification.timeAfter || (notification.time && notification.customName === null) || (notification.customName !== null && notificationTimed === 'before' && notificationType === 'scheduled')">
890
891 <div v-if="notification.name !== 'customer_birthday_greeting'">
892 <el-row style="display: flex; align-items: center">
893 <el-col :span="22">
894 <p>{{ $root.labels.dont_send_scheduled_email }}</p>
895 </el-col>
896 <el-col :span="2" style="display: flex; justify-content: center">
897 <el-switch v-model="minimumTimeEnabled" @change="changeMinimumTime"/>
898 </el-col>
899 </el-row>
900
901 <el-row :gutter="10" v-if="notification.minimumTimeBeforeBooking">
902 <el-col :lg="6" :md="6" :sm="24">
903 <el-input-number
904 :min="1"
905 v-model="notification.minimumTimeBeforeBooking.amount"
906 :placeholder="$root.labels.enter_number"
907 ></el-input-number>
908 </el-col>
909 <el-col :lg="6" :md="6" :sm="24">
910 <el-select
911 v-model="notification.minimumTimeBeforeBooking.period"
912 >
913 <el-option
914 v-for="interval in intervalTimes.filter(i => i.value !== 'weeks' && i.value !== 'months')"
915 :key="interval.value"
916 :label="interval.label"
917 :value="interval.value">
918 </el-option>
919 </el-select>
920
921 </el-col>
922 </el-row>
923 </div>
924
925 <!-- Cron Message -->
926 <el-alert
927 v-if="showActiveClass && notificationTimeBased || !showActiveClass && notificationType === 'scheduled'"
928 class="am-alert"
929 :title="$root.labels.cron_instruction + ':'"
930 type="info"
931 :description="'*/15 * * * * ' + $root.getAjaxUrl + '/notifications/scheduled/send'"
932 show-icon
933 :closable="false">
934 </el-alert>
935 <!-- /Cron Message -->
936
937 </div>
938
939 <hr/>
940
941 <!-- Cancel & Save Buttons -->
942 <el-row :gutter="16" class="am-email-form-settings__cancel-save">
943
944 <!-- Cancel Button -->
945 <el-col :span="12">
946 <div>
947 <el-button size="small" @click="openTestNotificationModal">
948 {{ $root.labels['send_test_' + type] }}
949 </el-button>
950 </div>
951 </el-col>
952 <!-- /Cancel Button -->
953
954 <!-- Save Button -->
955 <el-col :span="12">
956 <div class="align-right">
957 <el-button v-if="showActiveClass" @click="updateNotification()" :loading="!fetchedUpdate" size="small" type="primary">
958 {{ $root.labels.save }}
959 </el-button>
960 <el-button v-else @click="createNotification()" :loading="!fetchedUpdate" size="small" type="primary">
961 {{ $root.labels.create }}
962 </el-button>
963 </div>
964 </el-col>
965 <!-- /Save Button -->
966
967 </el-row>
968 <!-- /Cancel & Save Buttons -->
969
970
971 <el-alert
972 class="am-sms-warning"
973 v-if="type === 'sms'"
974 type="warning"
975 show-icon
976 title=""
977 v-html="$root.labels.sms_warning"
978 :closable="false"
979 style="margin-bottom: 10px; margin-top: 16px; display: block"
980 >
981 </el-alert>
982
983 </el-form>
984 </transition>
985 </div>
986 <!-- /Content -->
987
988 </el-col>
989 <!-- /Right Side Content -->
990
991 </el-row>
992 <!-- /Customize Notifications -->
993
994 <!-- Dialog Placeholders -->
995 <transition name="slide">
996 <el-dialog
997 class="am-side-dialog am-dialog-email-codes"
998 :visible.sync="dialogPlaceholders"
999 :show-close="false"
1000 v-if="dialogPlaceholders"
1001 >
1002 <dialog-placeholders
1003 :entity="entity"
1004 :type="type"
1005 :notification="notification"
1006 :excludedPlaceholders="getExcludedPlaceholders(notification, true, false, false)"
1007 :customFields="customFields"
1008 :categories="categories"
1009 :coupons="coupons"
1010 :userTypeTab="userTypeTab"
1011 @closeDialogPlaceholders="dialogPlaceholders=false"
1012 >
1013 </dialog-placeholders>
1014 </el-dialog>
1015 </transition>
1016 <!-- Dialog Placeholders -->
1017
1018 <!-- Dialog Placeholders -->
1019 <transition name="slide">
1020 <el-dialog
1021 class="am-side-dialog am-dialog-email-codes"
1022 :visible.sync="dialogCombinedPlaceholder"
1023 :show-close="false"
1024 v-if="dialogCombinedPlaceholder"
1025 >
1026 <dialog-combined-placeholder
1027 @closeDialogCombinedPlaceholder="dialogCombinedPlaceholder=false"
1028 :appointmentsSettings="$root.settings.appointments"
1029 :name="combinedPlaceholderName"
1030 :nameHtml="combinedPlaceholderName + 'Html'"
1031 :customFields="customFields"
1032 :userTypeTab="userTypeTab"
1033 :entity="combinedPlaceholderEntity"
1034 :type="type"
1035 :categories="categories"
1036 :coupons="coupons"
1037 :notification="notification"
1038 :placeholdersNames="getDialogPlaceholderNames(notification)"
1039 :excludedPlaceholders="getExcludedPlaceholders(notification, false, true, false)"
1040 :selectedLanguage="selectedLanguage"
1041 :selectedLanguageHtml="selectedLanguage + 'Html'"
1042 :languagesData="languagesData"
1043 >
1044 </dialog-combined-placeholder>
1045 </el-dialog>
1046 </transition>
1047 <!-- Dialog Placeholders -->
1048
1049 <!-- Test Notification Modal -->
1050 <el-dialog :title="$root.labels['send_test_' + type]" class="am-pop-modal" :visible.sync="testNotificationModal">
1051
1052 <!-- Configure Sender Email Warning -->
1053 <el-alert
1054 v-if="$root.settings.notifications.senderEmail === '' && type === 'email'"
1055 type="warning"
1056 show-icon
1057 title=""
1058 :description="$root.labels.test_email_warning"
1059 :closable="false"
1060 >
1061 </el-alert>
1062 <!-- /Configure Sender Email Warning -->
1063
1064 <!-- SMS Balance Warning -->
1065 <el-alert
1066 v-if="type === 'sms' && !user.balance"
1067 type="warning"
1068 show-icon
1069 title=""
1070 :description="$root.labels.test_sms_warning"
1071 :closable="false"
1072 >
1073 </el-alert>
1074 <!-- /SMS Balance Warning -->
1075
1076 <!-- Form -->
1077 <el-form
1078 v-if="testNotificationModal"
1079 :model="testNotification"
1080 ref="testNotification"
1081 :rules="rules"
1082 label-position="top"
1083 @submit.prevent="sendTestNotification"
1084 v-loading="testNotificationLoading"
1085 >
1086
1087 <!-- Recipient Email -->
1088 <el-form-item v-if="type === 'email'" :label="$root.labels.recipient_email" prop="recipientEmail">
1089 <el-input
1090 v-model="testNotification.recipientEmail"
1091 :placeholder="$root.labels.email_placeholder"
1092 @input="clearValidation()"
1093 auto-complete="off"
1094 >
1095 </el-input>
1096 </el-form-item>
1097 <!-- /Recipient Email -->
1098
1099 <!-- Recipient Phone -->
1100 <el-form-item v-if="type === 'sms'" :label="$root.labels.recipient_phone" prop="recipientPhone">
1101 <phone-input
1102 :savedPhone="testNotification.recipientPhone"
1103 @phoneFormatted="phoneFormatted"
1104 >
1105 </phone-input>
1106 </el-form-item>
1107 <!-- /Recipient Phone -->
1108
1109 <!-- Recipient WhatsApp -->
1110 <el-form-item v-if="type === 'whatsapp'" :label="$root.labels.recipient_phone" prop="recipientWhatsApp">
1111 <phone-input
1112 :savedPhone="testNotification.recipientWhatsApp"
1113 @phoneFormatted="phoneWhatsAppFormatted"
1114 >
1115 </phone-input>
1116 </el-form-item>
1117 <!-- /Recipient WhatsApp -->
1118
1119 <!-- Notification Template -->
1120 <el-form-item :label="$root.labels.notification_template" prop="notificationTemplate">
1121 <el-select v-model="testNotification.notificationTemplate">
1122 <el-option
1123 v-for="notification in notifications.filter(n => n.type === type)"
1124 :key="notification.id"
1125 :label="notification.customName ? notification.customName : notification.sendTo === 'provider' ? $root.labels.employee + ' ' + $root.labels[notification.name] : $root.labels.customer + ' ' + $root.labels[notification.name]"
1126 :value="notification.id"
1127 >
1128 </el-option>
1129 </el-select>
1130 </el-form-item>
1131 <!-- /Notification Template -->
1132
1133 </el-form>
1134 <!-- /Form -->
1135
1136 <!-- Cancel & Send Buttons -->
1137 <span slot="footer" class="dialog-footer">
1138
1139 <!-- Cancel Button -->
1140 <el-button size="small" @click="testNotificationModal = false">
1141 {{ $root.labels.cancel }}
1142 </el-button>
1143 <!-- /Cancel Button -->
1144
1145 <!-- Send Button -->
1146 <el-button
1147 size="small"
1148 type="primary"
1149 @click="sendTestNotification"
1150 :loading="testNotificationLoading"
1151 :disabled="disabledSendTestNotification"
1152 >
1153 {{ $root.labels.send }}
1154 </el-button>
1155 <!-- /Send Button -->
1156
1157 </span>
1158 <!-- /Cancel & Send Buttons -->
1159
1160 </el-dialog>
1161 <!-- /Test Notification Modal -->
1162
1163 </div>
1164 </template>
1165
1166 <script>
1167 import licenceMixin from '../../../../js/common/mixins/licenceMixin'
1168 import durationMixin from '../../../../js/common/mixins/durationMixin'
1169 import Form from 'form-object'
1170 import { quillEditor } from 'vue-quill-editor'
1171 import notifyMixin from '../../../../js/backend/mixins/notifyMixin'
1172 import quillMixin from '../../../../js/backend/mixins/quillMixin'
1173 import imageMixin from '../../../../js/common/mixins/imageMixin'
1174 import DialogPlaceholders from './DialogPlaceholders.vue'
1175 import DialogCombinedPlaceholder from './DialogCombinedPlaceholder.vue'
1176 import PhoneInput from '../../../parts/PhoneInput.vue'
1177 import notificationMixin from '../../../../js/backend/mixins/notificationMixin'
1178 import InlinePlaceholders from './InlinePlaceholders.vue'
1179 import entitiesMixin from '../../../../js/common/mixins/entitiesMixin'
1180 import WhatsAppPlaceholders from '../whatsapp/WhatsAppPlaceholders.vue'
1181 import placeholdersMixin from '../../../../js/backend/mixins/placeholdersMixin'
1182 import priceMixin from '../../../../js/common/mixins/priceMixin'
1183 import whatsappNotificationMixin from '../../../../js/backend/mixins/whatsappNotificationMixin'
1184 import eventMixin from '../../../../js/backend/mixins/eventMixin'
1185
1186 export default {
1187 mixins: [
1188 licenceMixin,
1189 quillMixin,
1190 durationMixin,
1191 notifyMixin,
1192 imageMixin,
1193 notificationMixin,
1194 entitiesMixin,
1195 placeholdersMixin,
1196 priceMixin,
1197 whatsappNotificationMixin,
1198 eventMixin
1199 ],
1200
1201 props: {
1202 categories: {
1203 default: () => [],
1204 type: Array
1205 },
1206 customFields: {
1207 default: () => [],
1208 type: Array
1209 },
1210 coupons: {
1211 default: () => [],
1212 type: Array
1213 },
1214 events: {
1215 default: () => [],
1216 type: Array
1217 },
1218 notifications: {
1219 default: () => [],
1220 type: Array
1221 },
1222 type: {
1223 default: 'email',
1224 type: String
1225 },
1226 user: {
1227 default: () => {},
1228 type: Object
1229 },
1230 passedUsedLanguages: {
1231 default: () => [],
1232 type: Array
1233 },
1234 languagesData: {
1235 default: () => {},
1236 type: Object
1237 },
1238 templates: {
1239 default: () => [],
1240 type: Array
1241 }
1242 },
1243
1244 data () {
1245 let isCustomNameRequired = (rule, input, callback) => {
1246 if (this.createNewContent && !this.notificationName) {
1247 callback(new Error(this.$root.labels.enter_name_warning))
1248 } else {
1249 callback()
1250 }
1251 }
1252
1253 let validatePhone = (rule, input, callback) => {
1254 if (input !== '' && !input.startsWith('+')) {
1255 callback(new Error(this.$root.labels.enter_valid_phone_warning))
1256 } else {
1257 callback()
1258 }
1259 }
1260
1261 return {
1262 minimumTimeEnabled: false,
1263 whatsAppPlaceholders: {
1264 header: [],
1265 body: []
1266 },
1267 whatsAppPhRules: {
1268 header: {},
1269 body: {}
1270 },
1271 notificationContentText: '',
1272 showDelete: false,
1273 newNotification: {},
1274 notificationName: '',
1275 notificationEnabled: true,
1276 amountTime: 1,
1277 intervalTime: 'hours',
1278 createNewContent: false,
1279 notificationType: 'triggered',
1280 notificationTrigger: 'approved',
1281 notificationEntity: 'appointment',
1282 notificationTimed: 'before',
1283 onTime: '00:00',
1284 services: [],
1285 selectedServices: [],
1286 selectedEvents: [],
1287 sendOnlyMe: false,
1288 showActiveClass: true,
1289 duplicateOptions: [
1290 {
1291 label: this.$root.labels.to_employee,
1292 value: 'employee'
1293 },
1294 {
1295 label: this.$root.labels.to_customer,
1296 value: 'customer'
1297 }
1298 ],
1299 dialogPlaceholders: false,
1300 dialogCombinedPlaceholder: false,
1301 combinedPlaceholderName: '',
1302 combinedPlaceholderEntity: '',
1303 fetchedDelete: true,
1304 fetchedUpdate: true,
1305 form: new Form(),
1306 notification: {},
1307 entity: 'appointment',
1308 sendTo: 'customer',
1309 rules: {
1310 recipientEmail: [
1311 {required: true, message: this.$root.labels.enter_recipient_email_warning, trigger: 'submit'},
1312 {type: 'email', message: this.$root.labels.enter_valid_email_warning, trigger: 'submit'}
1313 ],
1314 recipientPhone: [
1315 {required: true, message: this.$root.labels.enter_recipient_phone_warning, trigger: 'submit'},
1316 {validator: validatePhone, trigger: 'submit'}
1317 ],
1318 recipientWhatsApp: [
1319 {required: true, message: this.$root.labels.enter_recipient_phone_warning, trigger: 'submit'},
1320 {validator: validatePhone, trigger: 'submit'}
1321 ],
1322 notificationTemplate: [
1323 {required: true, message: this.$root.labels.select_email_template_warning, trigger: 'submit'}
1324 ],
1325 notificationCustomName: [
1326 {validator: isCustomNameRequired, trigger: 'submit'}
1327 ]
1328 },
1329 testNotification: {
1330 recipientEmail: '',
1331 recipientPhone: '',
1332 recipientWhatsApp: '',
1333 notificationTemplate: 0,
1334 language: null,
1335 type: null
1336 },
1337 testNotificationLoading: false,
1338 testNotificationModal: false,
1339 userTypeTab: 'customer',
1340 selectedLanguage: null,
1341 usedLanguages: [],
1342 intervalTimes: [
1343 {
1344 label: this.$root.labels.minutes,
1345 value: 'minutes'
1346 },
1347 {
1348 label: this.$root.labels.hours,
1349 value: 'hours'
1350 },
1351 {
1352 label: this.$root.labels.days,
1353 value: 'days'
1354 },
1355 {
1356 label: this.$root.labels.weeks,
1357 value: 'weeks'
1358 },
1359 {
1360 label: this.$root.labels.months,
1361 value: 'months'
1362 }
1363 ]
1364 }
1365 },
1366
1367 created () {
1368 Form.defaults.axios = this.$http
1369 },
1370
1371 mounted () {
1372 this.notifications = this.notifications.sort(this.sortNotifications)
1373 this.entity = 'appointment'
1374 if (this.type === 'whatsapp') {
1375 this.setPlaceholders(this.getExcludedPlaceholders(this.notification, false, false, true))
1376 }
1377 this.getNotification(null)
1378 this.usedLanguages = this.passedUsedLanguages
1379 this.services = this.getServicesFromCategories(this.categories)
1380 this.searchedEvents = this.events
1381 },
1382
1383 methods: {
1384 changeMinimumTime (val) {
1385 this.notification.minimumTimeBeforeBooking = val ? {amount: 1, period: 'days'} : null
1386 },
1387
1388 changeTextMode () {
1389 this.textModeChanged('notificationContent', 'notificationContentText', null)
1390
1391 this.notification.textMode = this.textMode
1392 },
1393
1394 changeLanguage () {
1395 if (this.textMode && this.selectedLanguage && this.notification.translations) {
1396 let translations = JSON.parse(this.notification.translations)
1397
1398 if (translations['content'] && translations['content'][this.selectedLanguage]) {
1399 this.notificationContentText = this.process(
1400 translations['content'][this.selectedLanguage].replace('<!-- Content -->', '').replace(/(\r\n|\n|\r)/gm, '')
1401 )
1402 }
1403 } else if (this.textMode && !this.selectedLanguage) {
1404 this.notificationContentText = this.process(
1405 this.notificationContent.replace('<!-- Content -->', '').replace(/(\r\n|\n|\r)/gm, '')
1406 )
1407 }
1408
1409 this.testNotification.language = this.selectedLanguage
1410 },
1411
1412 deleteNotification () {
1413 this.showDelete = false
1414 this.fetchedDelete = false
1415 this.form.post(
1416 `${this.$root.getAjaxUrl}/notifications/delete/` + this.notification.id
1417 ).then((response) => {
1418 this.fetchedDelete = true
1419 const index = this.notifications.map(n => n.id).indexOf(this.notification.id)
1420 if (index > -1) {
1421 this.notifications.splice(index, 1)
1422 let id = this.notifications.find(n => n.sendTo === this.notification.sendTo && n.entity === this.notification.entity &&
1423 n.type === this.notification.type).id
1424 this.getNotification(id)
1425 }
1426 this.notify(this.$root.labels.success, this.$root.labels.notification_deleted, 'success')
1427 }).catch(() => {
1428 this.fetchedDelete = true
1429 this.notify(this.$root.labels.error, this.$root.labels.notification_not_deleted, 'error')
1430 })
1431 },
1432
1433 duplicateNotification (event) {
1434 if (this.notification.customName) {
1435 this.notification = this.getNotificationEntity()
1436 if (event === 'employee') {
1437 this.notification.name = this.notification.name.replace('customer', 'provider')
1438 this.notification.sendTo = 'provider'
1439 } else if (event === 'customer') {
1440 this.notification.name = this.notification.name.replace('provider', 'customer')
1441 this.notification.sendTo = 'customer'
1442 }
1443 this.notification.customName = this.$root.labels.duplicate_of + this.notification.customName
1444 this.callInsert(this.notification)
1445 }
1446 },
1447
1448 manageLanguages () {
1449 this.$emit('manageLanguages')
1450 },
1451
1452 openDialogCombinedPlaceholders (phName) {
1453 let name = phName
1454 this.combinedPlaceholderName = name
1455 this.combinedPlaceholderEntity = name.includes('group') ? 'group' : this.entity
1456 if (this.selectedLanguage) {
1457 if (!this.$root.settings.appointments.translations[name]) {
1458 this.$root.settings.appointments.translations[name] = {}
1459 }
1460
1461 if (!(this.selectedLanguage in this.$root.settings.appointments.translations[name])) {
1462 this.$root.settings.appointments.translations[name][this.selectedLanguage] = this.$root.settings.appointments[name]
1463 }
1464 }
1465
1466 this.dialogCombinedPlaceholder = true
1467 },
1468
1469 getExcludedPlaceholders (notification, isDialog, isCombinedDialog, isInline) {
1470 let excludedPlaceholders = {}
1471
1472 switch (this.userTypeTab) {
1473 case 'provider':
1474 excludedPlaceholders = {
1475 employeePlaceholders: [],
1476 customerPlaceholders: [
1477 '%customer_panel_url%'
1478 ],
1479 appointmentPlaceholders: [
1480 '%zoom_join_url%',
1481 '%appointment_cancel_url%',
1482 '%reservation_name%',
1483 '%reservation_description%',
1484 ...(this.combinedPlaceholderName === 'packagePlaceholders'
1485 ? ['%appointment_reject_url%', '%appointment_approve_url%'] : [])
1486 ],
1487 eventPlaceholders: [
1488 '%zoom_join_url_date%',
1489 '%zoom_join_url_date_time%',
1490 '%event_cancel_url%'
1491 ],
1492 paymentPlaceholders: [
1493 '%payment_link_woocommerce%',
1494 '%payment_link_stripe%',
1495 '%payment_link_paypal%',
1496 '%payment_link_mollie%',
1497 '%payment_link_razorpay%',
1498 '%payment_link_square%'
1499 ]
1500 }
1501
1502 break
1503 case 'customer':
1504 excludedPlaceholders = {
1505 customerPlaceholders: [],
1506 employeePlaceholders: [
1507 '%employee_panel_url%',
1508 '%employee_password%'
1509 ],
1510 appointmentPlaceholders: [
1511 '%zoom_host_url%',
1512 '%booked_customer%',
1513 '%reservation_name%',
1514 '%reservation_description%',
1515 '%group_appointment_details%',
1516 '%appointment_approve_url%',
1517 '%appointment_reject_url%'
1518 ],
1519 eventPlaceholders: [
1520 '%zoom_host_url_date%',
1521 '%zoom_host_url_date_time%',
1522 '%group_event_details%'
1523 ],
1524 paymentPlaceholders: []
1525 }
1526
1527 break
1528 }
1529
1530 excludedPlaceholders.appointmentPlaceholders.push('%reservation_name%')
1531 excludedPlaceholders.appointmentPlaceholders.push('%reservation_description%')
1532 excludedPlaceholders.eventPlaceholders.push('%reservation_name%')
1533 excludedPlaceholders.eventPlaceholders.push('%reservation_description%')
1534
1535 if (notification && notification.name && !notification.name.includes('reschedule') && notification.type !== 'whatsapp') {
1536 excludedPlaceholders.appointmentPlaceholders.push('%initial_appointment_date%')
1537 excludedPlaceholders.appointmentPlaceholders.push('%initial_appointment_date_time%')
1538 excludedPlaceholders.appointmentPlaceholders.push('%initial_appointment_start_time%')
1539 excludedPlaceholders.appointmentPlaceholders.push('%initial_appointment_end_time%')
1540 excludedPlaceholders.eventPlaceholders.push('%initial_event_start_date%')
1541 excludedPlaceholders.eventPlaceholders.push('%initial_event_start_date_time%')
1542 excludedPlaceholders.eventPlaceholders.push('%initial_event_start_time%')
1543 excludedPlaceholders.eventPlaceholders.push('%initial_event_end_date%')
1544 excludedPlaceholders.eventPlaceholders.push('%initial_event_end_date_time%')
1545 excludedPlaceholders.eventPlaceholders.push('%initial_event_end_time%')
1546 }
1547
1548 if (notification && notification.name && (notification.name.includes('canceled') || notification.name.includes('rejected')) && notification.type !== 'whatsapp') {
1549 excludedPlaceholders.paymentPlaceholders.push('%payment_link_woocommerce%')
1550 excludedPlaceholders.paymentPlaceholders.push('%payment_link_stripe%')
1551 excludedPlaceholders.paymentPlaceholders.push('%payment_link_mollie%')
1552 excludedPlaceholders.paymentPlaceholders.push('%payment_link_paypal%')
1553 excludedPlaceholders.paymentPlaceholders.push('%payment_link_razorpay%')
1554 excludedPlaceholders.paymentPlaceholders.push('%payment_link_square%')
1555 }
1556
1557
1558 if (notification && notification.name === 'customer_invoice') {
1559 excludedPlaceholders.customerPlaceholders.push('%customer_panel_url%')
1560 }
1561
1562 if (notification && notification.type !== 'whatsapp') {
1563 switch (notification.entity) {
1564 case 'event':
1565 excludedPlaceholders.paymentPlaceholders.push('%appointment_deposit_payment%')
1566 excludedPlaceholders.paymentPlaceholders.push('%package_deposit_payment%')
1567 break
1568 case 'appointment':
1569 if (['customer_package_purchased', 'customer_package_canceled', 'provider_package_purchased', 'provider_package_canceled'].includes(notification.name)) {
1570 excludedPlaceholders.paymentPlaceholders.push('%appointment_deposit_payment%')
1571 excludedPlaceholders.paymentPlaceholders.push('%event_deposit_payment%')
1572 } else {
1573 excludedPlaceholders.paymentPlaceholders.push('%event_deposit_payment%')
1574 excludedPlaceholders.paymentPlaceholders.push('%package_deposit_payment%')
1575 }
1576 break
1577 }
1578 }
1579
1580 if (isCombinedDialog) {
1581 excludedPlaceholders.employeePlaceholders.push('%employee_panel_url%')
1582 excludedPlaceholders.employeePlaceholders.push('%employee_password%')
1583 excludedPlaceholders.appointmentPlaceholders.push('%booked_customer%')
1584 excludedPlaceholders.appointmentPlaceholders.push('%coupon_used%')
1585 excludedPlaceholders.appointmentPlaceholders.push('%number_of_persons%')
1586 if (this.combinedPlaceholderEntity === 'package') {
1587 excludedPlaceholders.paymentPlaceholders = [
1588 '%payment_link_woocommerce%',
1589 '%payment_link_stripe%',
1590 '%payment_link_paypal%',
1591 '%payment_link_mollie%',
1592 '%payment_link_razorpay%',
1593 '%payment_link_square%'
1594 ]
1595 }
1596 }
1597
1598 if (isCombinedDialog || (
1599 notification && !isInline &&
1600 [
1601 'customer_appointment_approved',
1602 'customer_appointment_pending',
1603 'provider_appointment_approved',
1604 'provider_appointment_pending'
1605 ].indexOf(notification.name) === -1
1606 )
1607 ) {
1608 excludedPlaceholders.appointmentPlaceholders.push('%recurring_appointments_details%')
1609 excludedPlaceholders.appointmentPlaceholders.push('%package_appointments_details%')
1610 }
1611
1612 if (notification && [
1613 'provider_appointment_updated',
1614 'customer_appointment_updated'
1615 ].indexOf(notification.name) !== -1) {
1616 excludedPlaceholders.appointmentPlaceholders.push('%recurring_appointments_details%')
1617 excludedPlaceholders.appointmentPlaceholders.push('%package_appointments_details%')
1618 }
1619
1620 if (isCombinedDialog && notification &&
1621 [
1622 'customer_package_purchased',
1623 'provider_package_purchased',
1624 'customer_package_canceled',
1625 'provider_package_canceled'
1626 ].indexOf(notification.name) !== -1
1627 ) {
1628 excludedPlaceholders.appointmentPlaceholders.push('%appointment_price%')
1629 }
1630
1631 if (this.type === 'sms') {
1632 excludedPlaceholders.paymentPlaceholders = excludedPlaceholders.paymentPlaceholders.concat([
1633 '%payment_link_woocommerce%',
1634 '%payment_link_stripe%',
1635 '%payment_link_paypal%',
1636 '%payment_link_mollie%',
1637 '%payment_link_razorpay%',
1638 '%payment_link_square%'
1639 ])
1640 }
1641
1642 if (notification.name === 'provider_cart' && isCombinedDialog) {
1643 excludedPlaceholders.employeePlaceholders = [
1644 '%employee_email%',
1645 '%employee_first_name%',
1646 '%employee_full_name%',
1647 '%employee_last_name%',
1648 '%employee_note%',
1649 '%employee_description%',
1650 '%employee_phone%',
1651 '%employee_panel_url%',
1652 '%employee_password%'
1653 ]
1654 }
1655
1656 if (notification.name === 'provider_cart' || notification.name === 'customer_cart') {
1657 excludedPlaceholders.paymentPlaceholders = excludedPlaceholders.paymentPlaceholders.concat([
1658 '%payment_due_amount%'
1659 ])
1660 }
1661
1662 return excludedPlaceholders
1663 },
1664
1665 getDialogPlaceholderNames (notification) {
1666 if (this.combinedPlaceholderEntity === 'group') {
1667 if (this.entity === 'appointment') {
1668 return [
1669 'appointmentPlaceholders',
1670 'extrasPlaceholders',
1671 'customFieldsPlaceholders',
1672 'customerPlaceholders'
1673 ]
1674 }
1675 if (this.entity === 'event') {
1676 return [
1677 'eventPlaceholders',
1678 'customFieldsPlaceholders',
1679 'customerPlaceholders'
1680 ]
1681 }
1682 }
1683 let appointmentPh = [
1684 'employeePlaceholders',
1685 'categoryPlaceholders',
1686 'locationPlaceholders',
1687 'appointmentPlaceholders',
1688 'customFieldsPlaceholders',
1689 'extrasPlaceholders'
1690 ]
1691 let packagePh = [
1692 'employeePlaceholders',
1693 'categoryPlaceholders',
1694 'locationPlaceholders',
1695 'appointmentPlaceholders',
1696 'customFieldsPlaceholders'
1697 ]
1698
1699 switch (notification.name) {
1700 case ('provider_appointment_approved'):
1701 case ('provider_appointment_pending'):
1702 case ('provider_cart'):
1703 return appointmentPh
1704 case ('customer_appointment_approved'):
1705 case ('customer_appointment_pending'):
1706 case ('customer_cart'):
1707 return appointmentPh.concat(['paymentPlaceholders'])
1708 case ('customer_package_purchased'):
1709 case ('customer_package_canceled'):
1710 return packagePh.concat(['paymentPlaceholders'])
1711 case ('provider_package_purchased'):
1712 case ('provider_package_canceled'):
1713 return packagePh
1714 }
1715 },
1716
1717 getInlinePlaceholdersNames (notification) {
1718 let common = [
1719 'customerPlaceholders',
1720 'companyPlaceholders',
1721 'paymentPlaceholders'
1722 ]
1723
1724 if (['provider_cart'].indexOf(notification.name) !== -1) {
1725 common.push('employeePlaceholders')
1726 }
1727
1728 if (['provider_cart', 'customer_cart'].indexOf(notification.name) !== -1) {
1729 common = common.filter(ph => ph !== 'paymentPlaceholders')
1730 }
1731
1732 if (['provider_cart', 'customer_cart'].indexOf(notification.name) !== -1 && notification.type === 'whatsapp') {
1733 common.push('cartPlaceholders')
1734 }
1735
1736 if (['customer_birthday_greeting', 'customer_account_recovery', 'customer_invoice'].indexOf(notification.name) !== -1) {
1737 return [
1738 'customerPlaceholders',
1739 'companyPlaceholders'
1740 ]
1741 } else if (['provider_panel_access', 'provider_panel_recovery'].indexOf(notification.name) !== -1) {
1742 return [
1743 'employeePlaceholders',
1744 'companyPlaceholders'
1745 ]
1746 } else {
1747 switch (this.entity) {
1748 case ('package'):
1749
1750 return common.concat(
1751 [
1752 'packagePlaceholders',
1753 'couponsPlaceholders'
1754 ]
1755 )
1756
1757 case ('event'):
1758 if (this.userTypeTab === 'customer') {
1759 common = common.concat(['couponsPlaceholders'])
1760 }
1761
1762 return common.concat(
1763 [
1764 'eventPlaceholders',
1765 'customFieldsPlaceholders',
1766 'employeePlaceholders',
1767 'locationPlaceholders'
1768 ]
1769 )
1770
1771 case ('appointment'):
1772 if (this.userTypeTab === 'customer' && ['customer_cart', 'provider_cart'].indexOf(notification.name) === -1) {
1773 common = common.concat(['couponsPlaceholders'])
1774 }
1775
1776 return common.concat(
1777 notification.name !== 'customer_cart' && notification.name !== 'provider_cart' ?
1778 [
1779 'appointmentPlaceholders',
1780 'customFieldsPlaceholders',
1781 'employeePlaceholders',
1782 'locationPlaceholders',
1783 'extrasPlaceholders',
1784 'categoryPlaceholders'
1785 ] : [
1786 ]
1787 )
1788 }
1789 }
1790
1791 return common
1792 },
1793
1794 getSortedInlinePlaceholders () {
1795 let placeholders = this.getInlinePlaceholdersNames(this.notification)
1796 return placeholders.sort((a, b) => (a.toLowerCase() > b.toLowerCase()) ? 1 : -1)
1797 },
1798
1799 getUnavailableNotificationLicence (name) {
1800 if (this.notInLicence('pro') && (
1801 name === 'customer_cart' ||
1802 name === 'provider_cart' ||
1803 name === 'customer_package_purchased' ||
1804 name === 'customer_package_canceled' ||
1805 name === 'provider_package_purchased' ||
1806 name === 'provider_package_canceled' ||
1807 name === 'customer_event_waiting' ||
1808 name === 'provider_event_waiting'
1809 )) {
1810 return 'pro'
1811 }
1812
1813 if (this.notInLicence('basic') && (
1814 name === 'customer_appointment_next_day_reminder' ||
1815 name === 'customer_appointment_follow_up' ||
1816 name === 'provider_appointment_next_day_reminder' ||
1817 name === 'provider_appointment_follow_up' ||
1818 name === 'customer_event_next_day_reminder' ||
1819 name === 'customer_event_follow_up' ||
1820 name === 'provider_event_next_day_reminder' ||
1821 name === 'customer_invoice'
1822 )) {
1823 return 'basic'
1824 }
1825
1826 if (this.notInLicence('starter') && (
1827 name === 'customer_appointment_rescheduled' ||
1828 name === 'provider_appointment_rescheduled' ||
1829 name === 'customer_appointment_updated' ||
1830 name === 'provider_appointment_updated' ||
1831 name === 'customer_event_rescheduled' ||
1832 name === 'customer_event_updated' ||
1833 name === 'provider_event_rescheduled' ||
1834 name === 'provider_event_updated' ||
1835 name === 'customer_event_canceled' ||
1836 name === 'provider_event_canceled' ||
1837 name === 'customer_account_recovery' ||
1838 name === 'provider_panel_access' ||
1839 name === 'provider_panel_recovery' ||
1840 name === 'provider_panel_access' ||
1841 name === 'provider_panel_recovery' ||
1842 name === 'customer_birthday_greeting'
1843 )) {
1844 return 'starter'
1845 }
1846
1847 return ''
1848 },
1849
1850 visibleNotification (name) {
1851 return this.getUnavailableNotificationLicence(name) !== '' ? this.licenceVisible() : true
1852 },
1853
1854 disabledNotification (name) {
1855 return this.getUnavailableNotificationLicence(name) !== ''
1856 },
1857
1858 isNotificationInLicence (item) {
1859 return item.name === 'customer_cart' ||
1860 item.name === 'provider_cart' ||
1861 item.name === 'customer_package_purchased' ||
1862 item.name === 'customer_package_canceled' ||
1863 item.name === 'provider_package_purchased' ||
1864 item.name === 'provider_package_canceled'
1865 },
1866
1867 onChangeUserTypeTab (tab) {
1868 this.inlineSVG()
1869 if (this.showActiveClass) {
1870 this.entity = 'appointment'
1871 if (this.notification.type !== tab.name) {
1872 this.notification = this.notifications.find(
1873 notification => notification.type === this.type && notification.sendTo === tab.name && notification.entity === this.entity
1874 )
1875 this.sendTo = this.notification.sendTo
1876 this.minimumTimeEnabled = this.notification.minimumTimeBeforeBooking !== null
1877 if (this.notification.customName) {
1878 this.setCustomNotificationFields()
1879 this.createNewContent = true
1880 } else {
1881 this.createNewContent = false
1882 }
1883 if (this.type === 'whatsapp') {
1884 this.setPlaceholders(this.getExcludedPlaceholders(this.notification, false, false, true))
1885 this.updatePlaceholders()
1886 }
1887 this.focusOnName()
1888 }
1889 }
1890 },
1891
1892 getNotification (id) {
1893 this.$refs.notification.clearValidate()
1894 this.createNewContent = false
1895 this.showActiveClass = true
1896 if (id === null) {
1897 this.notification = this.notifications.find(notification => notification.type === this.type && notification.entity === this.entity &&
1898 notification.sendTo === this.sendTo)
1899 } else {
1900 this.notification = this.notifications.find(notification => notification.id === id)
1901 }
1902
1903 if (this.notification.customName) {
1904 this.createNewContent = true
1905 this.setCustomNotificationFields()
1906 }
1907
1908 this.entity = this.notification.entity
1909 this.testNotification.type = this.notification.entity
1910 this.testNotification.notificationTemplate = this.notification.id
1911
1912 if (this.notification.minimumTimeBeforeBooking) {
1913 this.minimumTimeEnabled = true
1914 this.notification.minimumTimeBeforeBooking = typeof this.notification.minimumTimeBeforeBooking === 'string'
1915 ? JSON.parse(this.notification.minimumTimeBeforeBooking) : this.notification.minimumTimeBeforeBooking
1916 } else {
1917 this.minimumTimeEnabled = false
1918 }
1919
1920 if (this.notification.name === 'customer_package_purchased' ||
1921 this.notification.name === 'provider_package_purchased' ||
1922 this.notification.name === 'customer_package_canceled' ||
1923 this.notification.name === 'provider_package_canceled'
1924 ) {
1925 this.entity = 'package'
1926 this.testNotification.type = 'package'
1927 }
1928
1929 this.textMode = this.notification.textMode
1930
1931 this.notificationContentText = this.process(
1932 this.notificationContent.replace('<!-- Content -->', '').replace(/(\r\n|\n|\r)/gm, '')
1933 )
1934
1935 if (this.type === 'whatsapp') {
1936 this.updatePlaceholders()
1937 }
1938
1939 this.focusOnName()
1940 },
1941
1942 createNotification () {
1943 this.$refs.notification.clearValidate()
1944 this.$refs.notification.validate((valid) => {
1945 let whatsappPh = this.type === 'whatsapp' ? this.validateForm() : true
1946 if (valid && whatsappPh) {
1947 let notification = this.getNotificationEntity()
1948 this.callInsert(notification)
1949 } else {
1950 return false
1951 }
1952 })
1953 },
1954
1955 callInsert (notification) {
1956 this.fetchedUpdate = false
1957
1958 let content = notification.content
1959
1960 if (notification.type === 'email') {
1961 content = notification.textMode ? '<!-- Content -->' + notification.content : notification.content.replace('<!-- Content -->', '')
1962 }
1963
1964 this.form.post(`${this.$root.getAjaxUrl}/notifications`, Object.assign({}, notification, {content: content})
1965 ).then((response) => {
1966 if (response.data.update) {
1967 this.notification.content = response.data.notification.content
1968
1969 if (this.notification.type === 'email') {
1970 this.notification.textMode = response.data.notification.content.startsWith('<!-- Content -->')
1971
1972 this.notification.content = response.data.notification.content.replace('<!-- Content -->', '')
1973 }
1974 }
1975 this.fetchedUpdate = true
1976 notification.id = response.data.id
1977 this.notifications.unshift(notification)
1978 this.getNotification(notification.id)
1979 this.notify(this.$root.labels.success, this.$root.labels.notification_saved, 'success')
1980 }).catch((error) => {
1981 let message = this.$root.labels.notification_not_saved
1982
1983 if ('data' in error.response &&
1984 'data' in error.response.data &&
1985 'entityMissing' in error.response.data.data &&
1986 error.response.data.data.entityMissing
1987 ) {
1988 message = error.response.data.message
1989 }
1990
1991 this.fetchedUpdate = true
1992 this.notify(this.$root.labels.error, message, 'error')
1993 })
1994 },
1995
1996 updateNotification () {
1997 this.$refs.notification.clearValidate()
1998 this.$refs.notification.validate((valid) => {
1999 let whatsappPh = this.type === 'whatsapp' ? this.validateForm() : true
2000 if (valid && whatsappPh) {
2001 this.fetchedUpdate = false
2002 if (this.notification.customName) {
2003 let id = this.notification.id
2004 this.notification = this.getNotificationEntity()
2005 this.notification.id = id
2006 }
2007 if (this.type === 'whatsapp') {
2008 this.notification.subject = (this.whatsAppPlaceholders.header.length > 0 && this.whatsAppPlaceholders.header[0].whatsappType === 'location' ? 'location:' : '') + this.whatsAppPlaceholders.header.map(h => h.value).join(' ')
2009 this.notification.content = this.whatsAppPlaceholders.body.map(h => h.value).join(' ')
2010 }
2011 if (!this.minimumTimeEnabled) {
2012 this.notification.minimumTimeBeforeBooking = null
2013 }
2014 let content = this.notification.content
2015
2016 if (this.notification.type === 'email') {
2017 content = this.notification.textMode ? '<!-- Content -->' + this.notification.content : this.notification.content.replace('<!-- Content -->', '')
2018 }
2019 this.form.post(
2020 `${this.$root.getAjaxUrl}/notifications/${this.notification.id}`, Object.assign({}, this.notification, {content: content})
2021 ).then((response) => {
2022 if (response.data.update) {
2023 this.notification.content = response.data.notification.content
2024 }
2025 this.notification = response.data.notification
2026
2027 if (this.notification.type === 'email') {
2028 this.notification.textMode = response.data.notification.content.startsWith('<!-- Content -->')
2029
2030 this.notification.content = response.data.notification.content.replace('<!-- Content -->', '')
2031 }
2032
2033 this.notification.minimumTimeBeforeBooking = this.notification.minimumTimeBeforeBooking ? JSON.parse(this.notification.minimumTimeBeforeBooking) : null
2034 this.setCustomNotificationFields()
2035 let index = this.notifications.map(n => n.id).indexOf(this.notification.id)
2036 if (index !== -1) this.notifications[index] = this.notification
2037 this.fetchedUpdate = true
2038 this.notify(this.$root.labels.success, this.$root.labels.notification_saved, 'success')
2039 }).catch((e) => {
2040 console.log(e)
2041 this.fetchedUpdate = true
2042 this.notify(this.$root.labels.error, this.$root.labels.notification_not_saved, 'error')
2043 })
2044 } else {
2045 return false
2046 }
2047 })
2048 },
2049
2050 changeNotificationStatus (notification) {
2051 this.fetchedUpdate = false
2052 this.form.post(
2053 `${this.$root.getAjaxUrl}/notifications/status/${notification.id}`, notification
2054 ).then(() => {
2055 this.fetchedUpdate = true
2056 this.notify(this.$root.labels.success, this.$root.labels.notification_saved, 'success')
2057 }).catch(() => {
2058 this.fetchedUpdate = true
2059 this.notify(this.$root.labels.error, this.$root.labels.notification_not_saved, 'error')
2060 })
2061 },
2062
2063 showDialogPlaceholders () {
2064 this.dialogPlaceholders = true
2065 },
2066
2067 openTestNotificationModal () {
2068 this.testNotificationModal = true
2069 },
2070
2071 sendTestNotification () {
2072 this.type === 'sms' ? this.sendTestSMS() : this.sendTest()
2073 },
2074
2075 sendTest () {
2076 this.$refs.testNotification.validate((valid) => {
2077 if (valid) {
2078 this.testNotificationLoading = true
2079 this.form.post(
2080 `${this.$root.getAjaxUrl}/notifications/${this.type}/test`, this.testNotification
2081 ).then(() => {
2082 this.onSendTestNotificationSuccess()
2083 }).catch(() => {
2084 this.onSendTestNotificationError()
2085 })
2086 } else {
2087 return false
2088 }
2089 })
2090 },
2091
2092 sendTestSMS () {
2093 this.$refs.testNotification.validate((valid) => {
2094 if (valid) {
2095 this.testNotificationLoading = true
2096 this.sendAmeliaSmsApiRequest('testNotification', this.onSendTestNotificationSuccess, this.onSendTestNotificationError)
2097 } else {
2098 return false
2099 }
2100 })
2101 },
2102
2103 onSendTestNotificationSuccess () {
2104 this.clearValidation()
2105 this.testNotificationModal = false
2106 this.testNotificationLoading = false
2107 this.testNotification = this.resetTestNotificationOnInitialState()
2108 this.notify(this.$root.labels.success, this.$root.labels['test_' + this.type + '_success'], 'success')
2109 },
2110
2111 onSendTestNotificationError () {
2112 this.testNotificationLoading = false
2113 this.notify(this.$root.labels.error, this.$root.labels['test_' + this.type + '_error'], 'error')
2114 },
2115
2116 phoneFormatted (phone) {
2117 this.clearValidation()
2118 this.testNotification.recipientPhone = phone
2119 },
2120
2121 phoneWhatsAppFormatted (phone) {
2122 this.clearValidation()
2123 this.testNotification.recipientWhatsApp = phone
2124 },
2125
2126 clearValidation () {
2127 if (typeof this.$refs.testNotification !== 'undefined') {
2128 this.$refs.testNotification.clearValidate()
2129 }
2130 },
2131
2132 resetTestNotificationOnInitialState () {
2133 return {
2134 recipientEmail: '',
2135 recipientPhone: '',
2136 recipientWhatsApp: '',
2137 notificationTemplate: this.notification.id,
2138 language: this.selectedLanguage,
2139 type: this.entity
2140 }
2141 },
2142
2143 customerNotifications (entity) {
2144 if (entity === 'customer_other_notifications') {
2145 return this.notifications.filter(
2146 notification => notification.type === this.type && notification.sendTo === 'customer' && ['customer_invoice', 'customer_birthday_greeting', 'customer_account_recovery'].indexOf(notification.name) !== -1
2147 )
2148 } else {
2149 let filteredNotifications = this.notifications.filter(
2150 notification => notification.sendTo === 'customer' && notification.type === this.type && notification.entity === entity && ['customer_invoice', 'customer_birthday_greeting', 'customer_account_recovery'].indexOf(notification.name) === -1
2151 )
2152 // change position of app/event updated notifications
2153 let updatedNotification = filteredNotifications.find(n => n.name === 'customer_' + entity + '_updated' && !n.customName)
2154 let index = filteredNotifications.indexOf(updatedNotification)
2155 if (updatedNotification && index !== -1) {
2156 filteredNotifications.splice(index, 1)
2157 let rescheduledNotification = filteredNotifications.find(n => n.name.includes('rescheduled') && !n.customName)
2158 let insertTo = filteredNotifications.indexOf(rescheduledNotification)
2159 filteredNotifications.splice(insertTo, 0, updatedNotification)
2160 }
2161 return filteredNotifications
2162 }
2163 },
2164
2165 employeeNotifications (entity) {
2166 if (entity === 'provider_other_notifications' && (this.type === 'email' || this.type === 'whatsapp')) {
2167 return this.notifications.filter(
2168 notification => notification.type === this.type && notification.sendTo === 'provider' && ['provider_panel_access', 'provider_panel_recovery'].indexOf(notification.name) !== -1
2169 )
2170 } else {
2171 let filteredNotifications = this.notifications.filter(
2172 notification => notification.sendTo === 'provider' && notification.type === this.type && notification.entity === entity && ['provider_panel_access', 'provider_panel_recovery'].indexOf(notification.name) === -1
2173 )
2174 // change position of app/event updated notifications
2175 let updatedNotification = filteredNotifications.find(n => n.name === 'provider_' + entity + '_updated' && !n.customName)
2176 let index = filteredNotifications.indexOf(updatedNotification)
2177 if (updatedNotification && index !== -1) {
2178 filteredNotifications.splice(index, 1)
2179 let rescheduledNotification = filteredNotifications.find(n => n.name.includes('rescheduled') && !n.customName)
2180 let insertTo = filteredNotifications.indexOf(rescheduledNotification)
2181 filteredNotifications.splice(insertTo, 0, updatedNotification)
2182 }
2183 return filteredNotifications
2184 }
2185 },
2186
2187 getLanguageLabel (lang) {
2188 return this.languagesData[lang] ? this.languagesData[lang].name : ''
2189 },
2190
2191 getLanguageFlag (lang) {
2192 if (lang && this.languagesData[lang] && this.languagesData[lang].country_code) {
2193 return this.$root.getUrl + 'public/img/flags/' + this.languagesData[lang].country_code + '.png'
2194 }
2195 return this.$root.getUrl + 'public/img/grey.svg'
2196 }
2197 },
2198
2199 watch: {
2200 'passedUsedLanguages' () {
2201 this.usedLanguages = this.passedUsedLanguages
2202 }
2203 },
2204
2205 computed: {
2206 notificationTime: {
2207 get () {
2208 if (this.notification.time !== null) {
2209 return this.$moment(this.notification.time, 'HH:mm:ss').format('HH:mm')
2210 }
2211
2212 return null
2213 },
2214 set (selected) {
2215 this.notification.time = this.$moment(selected, 'HH:mm').format('HH:mm:ss')
2216 }
2217 },
2218
2219 notificationSubject: {
2220 get () {
2221 if (this.selectedLanguage && this.notification.translations) {
2222 let translations = JSON.parse(this.notification.translations)
2223 if (translations['subject'] && translations['subject'][this.selectedLanguage]) {
2224 return translations['subject'][this.selectedLanguage]
2225 }
2226 }
2227 return this.notification.subject
2228 },
2229 set (subject) {
2230 if (this.selectedLanguage) {
2231 this.notification.translations = this.notification.translations ? this.notification.translations : '{}'
2232 let translations = JSON.parse(this.notification.translations)
2233
2234 if (!translations['subject']) {
2235 translations['subject'] = {}
2236 }
2237 translations['subject'][this.selectedLanguage] = subject
2238 this.notification.translations = JSON.stringify(translations)
2239 } else {
2240 this.notification.subject = subject
2241 }
2242 }
2243 },
2244
2245 notificationContent: {
2246 get () {
2247 if (this.selectedLanguage && this.notification.translations) {
2248 let translations = JSON.parse(this.notification.translations)
2249 if (translations['content'] && translations['content'][this.selectedLanguage]) {
2250 return translations['content'][this.selectedLanguage]
2251 }
2252 }
2253 return this.notification.content
2254 },
2255 set (content) {
2256 if (this.selectedLanguage) {
2257 this.notification.translations = this.notification.translations ? this.notification.translations : '{}'
2258 let translations = JSON.parse(this.notification.translations)
2259
2260 if (!translations['content']) {
2261 translations['content'] = {}
2262 }
2263 translations['content'][this.selectedLanguage] = content
2264 this.notification.translations = JSON.stringify(translations)
2265 } else {
2266 this.notification.content = content
2267 }
2268 }
2269 },
2270
2271 notificationTimeBased () {
2272 return this.notification.time !== null || this.notification.timeBefore !== null || this.notification.timeAfter !== null
2273 },
2274
2275 disabledSendTestNotification () {
2276 if (this.type === 'email' && !this.$root.settings.notifications.senderEmail) {
2277 return true
2278 }
2279
2280 return this.type === 'sms' && (typeof this.user !== 'undefined' && !this.user.balance)
2281 }
2282
2283 },
2284
2285 components: {
2286 WhatsAppPlaceholders,
2287 quillEditor,
2288 DialogPlaceholders,
2289 DialogCombinedPlaceholder,
2290 PhoneInput,
2291 InlinePlaceholders
2292 }
2293 }
2294 </script>
2295