@product7/product7-js 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/README.md +4 -3
- package/dist/product7-js.js +487 -725
- package/dist/product7-js.js.map +1 -1
- package/dist/product7-js.min.js +1 -1
- package/dist/product7-js.min.js.map +1 -1
- package/package.json +1 -1
- package/src/api/services/FeedbackService.js +2 -2
- package/src/api/services/SurveyService.js +2 -2
- package/src/core/Product7.js +3 -1
- package/src/styles/survey.js +177 -345
- package/src/widgets/MessengerWidget.js +9 -5
- package/src/widgets/SurveyWidget.js +149 -225
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { NotificationSound } from '../utils/NotificationSound.js';
|
|
2
1
|
import { WebSocketService } from '../core/WebSocketService.js';
|
|
3
2
|
import {
|
|
4
3
|
applyMessengerCustomStyles,
|
|
5
4
|
removeMessengerCustomStyles,
|
|
6
5
|
} from '../styles/messengerCustomStyles.js';
|
|
6
|
+
import { NotificationSound } from '../utils/NotificationSound.js';
|
|
7
7
|
import { BaseWidget } from './BaseWidget.js';
|
|
8
8
|
import { MessengerState } from './messenger/MessengerState.js';
|
|
9
9
|
import { MessengerLauncher } from './messenger/components/MessengerLauncher.js';
|
|
@@ -95,12 +95,16 @@ export class MessengerWidget extends BaseWidget {
|
|
|
95
95
|
this._wsUnsubscribers = [];
|
|
96
96
|
this._feedbackWidget = null;
|
|
97
97
|
|
|
98
|
-
const notificationSoundOption =
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
const notificationSoundOption =
|
|
99
|
+
options.notificationSound !== undefined
|
|
100
|
+
? options.notificationSound
|
|
101
|
+
: true;
|
|
101
102
|
|
|
102
103
|
this._notificationSound = new NotificationSound({
|
|
103
|
-
soundUrl:
|
|
104
|
+
soundUrl:
|
|
105
|
+
typeof notificationSoundOption === 'string'
|
|
106
|
+
? notificationSoundOption
|
|
107
|
+
: undefined,
|
|
104
108
|
volume: options.notificationVolume ?? 0.4,
|
|
105
109
|
});
|
|
106
110
|
|
|
@@ -36,6 +36,8 @@ export class SurveyWidget extends BaseWidget {
|
|
|
36
36
|
: null,
|
|
37
37
|
customQuestions: options.customQuestions || [],
|
|
38
38
|
pages: Array.isArray(options.pages) ? options.pages : [],
|
|
39
|
+
thankYouConfig:
|
|
40
|
+
options.thankYouConfig || options.thank_you_config || null,
|
|
39
41
|
respondentId: options.respondentId || null,
|
|
40
42
|
email: options.email || null,
|
|
41
43
|
onSubmit: options.onSubmit || null,
|
|
@@ -364,10 +366,6 @@ export class SurveyWidget extends BaseWidget {
|
|
|
364
366
|
|
|
365
367
|
_shouldShowActions() {
|
|
366
368
|
if (this._isMultiPageSurvey()) {
|
|
367
|
-
const page = this._getCurrentPage();
|
|
368
|
-
if (page && page.type === 'link') {
|
|
369
|
-
return false;
|
|
370
|
-
}
|
|
371
369
|
return true;
|
|
372
370
|
}
|
|
373
371
|
if (typeof this.surveyOptions.showSubmitButton === 'boolean') {
|
|
@@ -416,8 +414,6 @@ export class SurveyWidget extends BaseWidget {
|
|
|
416
414
|
return this._renderMultipleChoicePage(page);
|
|
417
415
|
case 'text':
|
|
418
416
|
return this._renderTextPage(page);
|
|
419
|
-
case 'link':
|
|
420
|
-
return this._renderLinkPage(page);
|
|
421
417
|
default:
|
|
422
418
|
return '';
|
|
423
419
|
}
|
|
@@ -425,62 +421,36 @@ export class SurveyWidget extends BaseWidget {
|
|
|
425
421
|
|
|
426
422
|
_renderRatingPage(page) {
|
|
427
423
|
const pageId = page.id || `page_${this.surveyState.currentPageIndex}`;
|
|
428
|
-
const config = page.
|
|
424
|
+
const config = page.rating_config || page.ratingConfig || {};
|
|
429
425
|
const scale = Number(config.scale) || 5;
|
|
430
|
-
const
|
|
431
|
-
const configType = config.survey_type;
|
|
432
|
-
let ratingType;
|
|
433
|
-
if (topSurveyType === 'nps') {
|
|
434
|
-
ratingType = 'nps';
|
|
435
|
-
} else if (configType) {
|
|
436
|
-
ratingType = configType;
|
|
437
|
-
} else if (topSurveyType === 'ces') {
|
|
438
|
-
ratingType = 'ces';
|
|
439
|
-
} else if (topSurveyType === 'csat') {
|
|
440
|
-
ratingType = 'emoji';
|
|
441
|
-
} else {
|
|
442
|
-
ratingType = topSurveyType || 'csat';
|
|
443
|
-
}
|
|
426
|
+
const ratingType = config.survey_type || 'number';
|
|
444
427
|
const pageAnswer = this.surveyState.pageAnswers[pageId] || {};
|
|
445
428
|
const currentRating = pageAnswer.rating;
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
const
|
|
459
|
-
config.low_label || this.surveyOptions.lowLabel || defaultLowLabel;
|
|
460
|
-
const highLabel =
|
|
461
|
-
config.high_label || this.surveyOptions.highLabel || defaultHighLabel;
|
|
429
|
+
|
|
430
|
+
const labelDefaults = {
|
|
431
|
+
nps:
|
|
432
|
+
scale === 11
|
|
433
|
+
? ['Not likely', 'Very likely']
|
|
434
|
+
: ['Strongly Disagree', 'Strongly Agree'],
|
|
435
|
+
emoji: ['Very dissatisfied', 'Very satisfied'],
|
|
436
|
+
number: ['Poor', 'Excellent'],
|
|
437
|
+
star: ['Poor', 'Excellent'],
|
|
438
|
+
};
|
|
439
|
+
const [defaultLow, defaultHigh] = labelDefaults[ratingType] || ['', ''];
|
|
440
|
+
const lowLabel = config.low_label || defaultLow;
|
|
441
|
+
const highLabel = config.high_label || defaultHigh;
|
|
462
442
|
const labels = this._renderScaleLabels(lowLabel, highLabel);
|
|
463
443
|
|
|
464
444
|
if (ratingType === 'nps') {
|
|
465
|
-
const npsScale = Number.isFinite(scale) && scale >= 2 ? scale :
|
|
445
|
+
const npsScale = Number.isFinite(scale) && scale >= 2 ? scale : 11;
|
|
466
446
|
const start = npsScale === 11 ? 0 : 1;
|
|
467
|
-
const values = Array.from(
|
|
468
|
-
{ length: npsScale },
|
|
469
|
-
(_, index) => start + index
|
|
470
|
-
);
|
|
471
|
-
const usesSegmentedScale = values.length <= 7;
|
|
472
|
-
const containerClass = usesSegmentedScale
|
|
473
|
-
? 'feedback-survey-ces feedback-survey-rating-scale'
|
|
474
|
-
: 'feedback-survey-nps';
|
|
475
|
-
const buttonClass = usesSegmentedScale
|
|
476
|
-
? 'feedback-survey-page-rating-btn feedback-survey-nps-btn feedback-survey-ces-btn feedback-survey-rating-scale-btn'
|
|
477
|
-
: 'feedback-survey-page-rating-btn feedback-survey-nps-btn';
|
|
447
|
+
const values = Array.from({ length: npsScale }, (_, i) => start + i);
|
|
478
448
|
return `
|
|
479
|
-
<div class="
|
|
449
|
+
<div class="feedback-survey-nps" data-page-id="${pageId}">
|
|
480
450
|
${values
|
|
481
451
|
.map((n) => {
|
|
482
452
|
const selected = currentRating === n ? ' selected' : '';
|
|
483
|
-
return `<button class="
|
|
453
|
+
return `<button class="feedback-survey-page-rating-btn feedback-survey-nps-btn feedback-survey-nps-score-${n}${selected}" data-page-id="${pageId}" data-score="${n}">${n}</button>`;
|
|
484
454
|
})
|
|
485
455
|
.join('')}
|
|
486
456
|
</div>
|
|
@@ -488,28 +458,7 @@ export class SurveyWidget extends BaseWidget {
|
|
|
488
458
|
`;
|
|
489
459
|
}
|
|
490
460
|
|
|
491
|
-
if (ratingType === '
|
|
492
|
-
const cesLabels = [
|
|
493
|
-
'Very Difficult',
|
|
494
|
-
'Difficult',
|
|
495
|
-
'Neutral',
|
|
496
|
-
'Easy',
|
|
497
|
-
'Very Easy',
|
|
498
|
-
];
|
|
499
|
-
return `
|
|
500
|
-
<div class="feedback-survey-ces-list" data-page-id="${pageId}">
|
|
501
|
-
${cesLabels
|
|
502
|
-
.map((label, i) => {
|
|
503
|
-
const score = i + 1;
|
|
504
|
-
const selected = currentRating === score ? ' selected' : '';
|
|
505
|
-
return `<button class="feedback-survey-page-rating-btn feedback-survey-ces-list-btn${selected}" data-page-id="${pageId}" data-score="${score}">${label}</button>`;
|
|
506
|
-
})
|
|
507
|
-
.join('')}
|
|
508
|
-
</div>
|
|
509
|
-
`;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
if (ratingType === 'emoji' && scale === 5) {
|
|
461
|
+
if (ratingType === 'emoji') {
|
|
513
462
|
const emojis = [
|
|
514
463
|
'\uD83D\uDE1E',
|
|
515
464
|
'\uD83D\uDE15',
|
|
@@ -517,9 +466,12 @@ export class SurveyWidget extends BaseWidget {
|
|
|
517
466
|
'\uD83D\uDE42',
|
|
518
467
|
'\uD83D\uDE04',
|
|
519
468
|
];
|
|
469
|
+
const emojiScale =
|
|
470
|
+
Number.isFinite(scale) && scale >= 2 ? Math.min(scale, 5) : 5;
|
|
520
471
|
return `
|
|
521
472
|
<div class="feedback-survey-csat" data-page-id="${pageId}">
|
|
522
473
|
${emojis
|
|
474
|
+
.slice(0, emojiScale)
|
|
523
475
|
.map((emoji, i) => {
|
|
524
476
|
const score = i + 1;
|
|
525
477
|
const selected = currentRating === score ? ' selected' : '';
|
|
@@ -535,27 +487,27 @@ export class SurveyWidget extends BaseWidget {
|
|
|
535
487
|
const starScale = Number.isFinite(scale) && scale >= 2 ? scale : 5;
|
|
536
488
|
return `
|
|
537
489
|
<div class="feedback-survey-stars" data-page-id="${pageId}">
|
|
538
|
-
${
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
490
|
+
${Array.from({ length: starScale }, (_, i) => {
|
|
491
|
+
const score = i + 1;
|
|
492
|
+
const filled =
|
|
493
|
+
typeof currentRating === 'number' && currentRating >= score
|
|
494
|
+
? ' filled'
|
|
495
|
+
: '';
|
|
496
|
+
return `<button class="feedback-survey-page-rating-btn feedback-survey-star-btn${filled}" data-page-id="${pageId}" data-score="${score}"><iconify-icon icon="ph:star-duotone" width="32" height="32" style="pointer-events:none;"></iconify-icon></button>`;
|
|
497
|
+
}).join('')}
|
|
545
498
|
</div>
|
|
546
499
|
${labels}
|
|
547
500
|
`;
|
|
548
501
|
}
|
|
549
502
|
|
|
503
|
+
const numScale = Number.isFinite(scale) && scale >= 2 ? scale : 5;
|
|
550
504
|
return `
|
|
551
505
|
<div class="feedback-survey-rating-scale" data-page-id="${pageId}">
|
|
552
|
-
${
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
})
|
|
558
|
-
.join('')}
|
|
506
|
+
${Array.from({ length: numScale }, (_, i) => {
|
|
507
|
+
const score = i + 1;
|
|
508
|
+
const selected = currentRating === score ? ' selected' : '';
|
|
509
|
+
return `<button class="feedback-survey-page-rating-btn feedback-survey-rating-scale-btn${selected}" data-page-id="${pageId}" data-score="${score}">${score}</button>`;
|
|
510
|
+
}).join('')}
|
|
559
511
|
</div>
|
|
560
512
|
${labels}
|
|
561
513
|
`;
|
|
@@ -605,32 +557,6 @@ export class SurveyWidget extends BaseWidget {
|
|
|
605
557
|
`;
|
|
606
558
|
}
|
|
607
559
|
|
|
608
|
-
_renderLinkPage(page) {
|
|
609
|
-
const pageId = page.id || `page_${this.surveyState.currentPageIndex}`;
|
|
610
|
-
const config = page.link_config || page.linkConfig || {};
|
|
611
|
-
const buttonText = config.button_text || config.buttonText || 'Click here';
|
|
612
|
-
const linkText = config.link_text || config.linkText || '';
|
|
613
|
-
const redirectUrl = config.redirect_url || config.redirectUrl || '#';
|
|
614
|
-
const openIn = config.open_in || config.openIn || 'new_tab';
|
|
615
|
-
const target = openIn === 'new_tab' ? '_blank' : '_self';
|
|
616
|
-
const pageAnswer = this.surveyState.pageAnswers[pageId] || {};
|
|
617
|
-
const clicked = pageAnswer.clicked === true;
|
|
618
|
-
|
|
619
|
-
const iconExternalLink = `<iconify-icon icon="ph:arrow-square-out-duotone" width="15" height="15"></iconify-icon>`;
|
|
620
|
-
return `
|
|
621
|
-
<div class="feedback-survey-link-page" data-page-id="${pageId}">
|
|
622
|
-
${linkText ? `<p class="feedback-survey-link-text">${linkText}</p>` : ''}
|
|
623
|
-
<a class="feedback-survey-link-btn${clicked ? ' selected' : ''}"
|
|
624
|
-
href="${redirectUrl}"
|
|
625
|
-
target="${target}"
|
|
626
|
-
rel="noopener noreferrer"
|
|
627
|
-
data-page-id="${pageId}">
|
|
628
|
-
${buttonText} ${iconExternalLink}
|
|
629
|
-
</a>
|
|
630
|
-
</div>
|
|
631
|
-
`;
|
|
632
|
-
}
|
|
633
|
-
|
|
634
560
|
_renderCustomQuestions() {
|
|
635
561
|
if (
|
|
636
562
|
!this.surveyOptions.customQuestions ||
|
|
@@ -913,24 +839,6 @@ export class SurveyWidget extends BaseWidget {
|
|
|
913
839
|
});
|
|
914
840
|
}
|
|
915
841
|
}
|
|
916
|
-
|
|
917
|
-
if (page.type === 'link') {
|
|
918
|
-
this.surveyElement
|
|
919
|
-
.querySelectorAll('.feedback-survey-link-btn')
|
|
920
|
-
.forEach((btn) => {
|
|
921
|
-
btn.addEventListener('click', () => {
|
|
922
|
-
const pId = btn.dataset.pageId;
|
|
923
|
-
this._setPageAnswer(pId, { clicked: true });
|
|
924
|
-
btn.classList.add('selected');
|
|
925
|
-
|
|
926
|
-
const navigation = page.afterThisPage || page.after_this_page;
|
|
927
|
-
const goesTo = navigation ? navigation.default : null;
|
|
928
|
-
if (!goesTo || goesTo === 'end_survey') {
|
|
929
|
-
setTimeout(() => this._handleSubmit(), 400);
|
|
930
|
-
}
|
|
931
|
-
});
|
|
932
|
-
});
|
|
933
|
-
}
|
|
934
842
|
}
|
|
935
843
|
|
|
936
844
|
_selectNPS(score) {
|
|
@@ -939,11 +847,7 @@ export class SurveyWidget extends BaseWidget {
|
|
|
939
847
|
.querySelectorAll('.feedback-survey-nps-btn')
|
|
940
848
|
.forEach((btn) => {
|
|
941
849
|
const btnScore = parseInt(btn.dataset.score);
|
|
942
|
-
|
|
943
|
-
btn.classList.add('selected');
|
|
944
|
-
} else {
|
|
945
|
-
btn.classList.remove('selected');
|
|
946
|
-
}
|
|
850
|
+
btn.classList.toggle('selected', btnScore === score);
|
|
947
851
|
});
|
|
948
852
|
this._maybeAutoSubmit();
|
|
949
853
|
}
|
|
@@ -954,50 +858,16 @@ export class SurveyWidget extends BaseWidget {
|
|
|
954
858
|
.querySelectorAll('.feedback-survey-csat-btn')
|
|
955
859
|
.forEach((btn) => {
|
|
956
860
|
const btnScore = parseInt(btn.dataset.score);
|
|
957
|
-
|
|
958
|
-
btn.classList.add('selected');
|
|
959
|
-
} else {
|
|
960
|
-
btn.classList.remove('selected');
|
|
961
|
-
}
|
|
962
|
-
});
|
|
963
|
-
this._maybeAutoSubmit();
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
_selectCES(score) {
|
|
967
|
-
this.surveyState.score = score;
|
|
968
|
-
this.surveyElement
|
|
969
|
-
.querySelectorAll('.feedback-survey-ces-btn')
|
|
970
|
-
.forEach((btn) => {
|
|
971
|
-
const btnScore = parseInt(btn.dataset.score);
|
|
972
|
-
if (btnScore === score) {
|
|
973
|
-
btn.classList.add('selected');
|
|
974
|
-
} else {
|
|
975
|
-
btn.classList.remove('selected');
|
|
976
|
-
}
|
|
861
|
+
btn.classList.toggle('selected', btnScore === score);
|
|
977
862
|
});
|
|
978
863
|
this._maybeAutoSubmit();
|
|
979
864
|
}
|
|
980
865
|
|
|
981
866
|
_maybeAutoSubmit() {
|
|
982
|
-
if (!this._shouldAutoSubmitOnSelect())
|
|
983
|
-
return;
|
|
984
|
-
}
|
|
867
|
+
if (!this._shouldAutoSubmitOnSelect()) return;
|
|
985
868
|
this._handleSubmit();
|
|
986
869
|
}
|
|
987
870
|
|
|
988
|
-
_selectFrequency(freq) {
|
|
989
|
-
this.surveyState.customAnswers.frequency = freq;
|
|
990
|
-
this.surveyElement
|
|
991
|
-
.querySelectorAll('.feedback-survey-freq-btn')
|
|
992
|
-
.forEach((btn) => {
|
|
993
|
-
if (btn.dataset.freq === freq) {
|
|
994
|
-
btn.classList.add('selected');
|
|
995
|
-
} else {
|
|
996
|
-
btn.classList.remove('selected');
|
|
997
|
-
}
|
|
998
|
-
});
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
871
|
_setSubmitLoading(loading) {
|
|
1002
872
|
const btn = this.surveyElement?.querySelector('.feedback-survey-submit');
|
|
1003
873
|
if (!btn) return;
|
|
@@ -1077,8 +947,7 @@ export class SurveyWidget extends BaseWidget {
|
|
|
1077
947
|
await this.apiService.submitSurveyResponse(surveyId, responseData);
|
|
1078
948
|
|
|
1079
949
|
this.sdk.eventBus.emit('survey:submitted', { widget: this, response });
|
|
1080
|
-
this.
|
|
1081
|
-
this._showSuccessNotification();
|
|
950
|
+
this._showThankYouScreen();
|
|
1082
951
|
} catch (error) {
|
|
1083
952
|
console.error('[SurveyWidget] Failed to submit survey:', error);
|
|
1084
953
|
this._showError('Something went wrong. Please try again.');
|
|
@@ -1114,9 +983,8 @@ export class SurveyWidget extends BaseWidget {
|
|
|
1114
983
|
|
|
1115
984
|
_validateCurrentPage() {
|
|
1116
985
|
const page = this._getCurrentPage();
|
|
1117
|
-
if (!page || page.required
|
|
986
|
+
if (!page || page.required !== true) return true;
|
|
1118
987
|
const pageId = page.id || `page_${this.surveyState.currentPageIndex}`;
|
|
1119
|
-
|
|
1120
988
|
const answer = this.surveyState.pageAnswers[pageId] || {};
|
|
1121
989
|
|
|
1122
990
|
if (page.type === 'rating') {
|
|
@@ -1127,9 +995,10 @@ export class SurveyWidget extends BaseWidget {
|
|
|
1127
995
|
}
|
|
1128
996
|
|
|
1129
997
|
if (page.type === 'multiple_choice') {
|
|
1130
|
-
const
|
|
1131
|
-
|
|
1132
|
-
|
|
998
|
+
const hasAnswer =
|
|
999
|
+
Boolean(answer.value) ||
|
|
1000
|
+
(Array.isArray(answer.values) && answer.values.length > 0);
|
|
1001
|
+
if (!hasAnswer) {
|
|
1133
1002
|
this._showError('Please select an option');
|
|
1134
1003
|
return false;
|
|
1135
1004
|
}
|
|
@@ -1142,55 +1011,88 @@ export class SurveyWidget extends BaseWidget {
|
|
|
1142
1011
|
}
|
|
1143
1012
|
}
|
|
1144
1013
|
|
|
1145
|
-
if (page.type === 'link') {
|
|
1146
|
-
if (page.required && !answer.clicked) {
|
|
1147
|
-
this._showError('Please click the link to continue');
|
|
1148
|
-
return false;
|
|
1149
|
-
}
|
|
1150
|
-
}
|
|
1151
|
-
|
|
1152
1014
|
return true;
|
|
1153
1015
|
}
|
|
1154
1016
|
|
|
1155
1017
|
_getNextPageIndex() {
|
|
1156
|
-
if (!this._isMultiPageSurvey())
|
|
1157
|
-
return -1;
|
|
1158
|
-
}
|
|
1018
|
+
if (!this._isMultiPageSurvey()) return -1;
|
|
1159
1019
|
|
|
1160
1020
|
const page = this._getCurrentPage();
|
|
1161
1021
|
const total = this.surveyOptions.pages.length;
|
|
1162
1022
|
const currentIndex = this.surveyState.currentPageIndex;
|
|
1163
1023
|
const fallbackNext = currentIndex + 1 < total ? currentIndex + 1 : -1;
|
|
1164
|
-
const navigation = page ? page.
|
|
1165
|
-
if (!navigation)
|
|
1166
|
-
return fallbackNext;
|
|
1167
|
-
}
|
|
1024
|
+
const navigation = page ? page.after_this_page || page.afterThisPage : null;
|
|
1025
|
+
if (!navigation) return fallbackNext;
|
|
1168
1026
|
|
|
1169
|
-
const
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
}
|
|
1027
|
+
const conditions = Array.isArray(navigation.conditions)
|
|
1028
|
+
? navigation.conditions
|
|
1029
|
+
: [];
|
|
1030
|
+
const pageId = page.id || `page_${currentIndex}`;
|
|
1031
|
+
const answer = this.surveyState.pageAnswers[pageId] || {};
|
|
1173
1032
|
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
return fallbackNext;
|
|
1033
|
+
for (const condition of conditions) {
|
|
1034
|
+
if (this._evaluateCondition(condition, page, answer)) {
|
|
1035
|
+
return this._resolvePageTarget(condition.go_to, total, fallbackNext);
|
|
1036
|
+
}
|
|
1179
1037
|
}
|
|
1180
1038
|
|
|
1181
|
-
|
|
1182
|
-
|
|
1039
|
+
return this._resolvePageTarget(navigation.default, total, fallbackNext);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
_evaluateCondition(condition, page, answer) {
|
|
1043
|
+
const { operator, values } = condition;
|
|
1044
|
+
if (!operator || !Array.isArray(values)) return false;
|
|
1045
|
+
|
|
1046
|
+
let answerValue = null;
|
|
1047
|
+
if (page.type === 'rating') {
|
|
1048
|
+
answerValue = typeof answer.rating === 'number' ? answer.rating : null;
|
|
1049
|
+
} else if (page.type === 'multiple_choice') {
|
|
1050
|
+
answerValue =
|
|
1051
|
+
answer.value ||
|
|
1052
|
+
(Array.isArray(answer.values) ? answer.values[0] : null);
|
|
1053
|
+
} else if (page.type === 'text') {
|
|
1054
|
+
answerValue = answer.text || null;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
if (operator === 'is_empty')
|
|
1058
|
+
return answerValue === null || answerValue === '';
|
|
1059
|
+
if (operator === 'not_empty')
|
|
1060
|
+
return answerValue !== null && answerValue !== '';
|
|
1061
|
+
if (answerValue === null) return false;
|
|
1062
|
+
|
|
1063
|
+
const [v1, v2] = values;
|
|
1064
|
+
switch (operator) {
|
|
1065
|
+
case 'equals':
|
|
1066
|
+
return String(answerValue) === String(v1);
|
|
1067
|
+
case 'greater_than':
|
|
1068
|
+
return Number(answerValue) > Number(v1);
|
|
1069
|
+
case 'less_than':
|
|
1070
|
+
return Number(answerValue) < Number(v1);
|
|
1071
|
+
case 'between':
|
|
1072
|
+
return (
|
|
1073
|
+
Number(answerValue) >= Number(v1) && Number(answerValue) <= Number(v2)
|
|
1074
|
+
);
|
|
1075
|
+
case 'contains':
|
|
1076
|
+
return String(answerValue).includes(String(v1));
|
|
1077
|
+
default:
|
|
1078
|
+
return false;
|
|
1183
1079
|
}
|
|
1080
|
+
}
|
|
1184
1081
|
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1082
|
+
_resolvePageTarget(target, total, fallback) {
|
|
1083
|
+
if (!target) return fallback;
|
|
1084
|
+
if (target === 'end_survey') return -1;
|
|
1085
|
+
if (target === 'next_page' || target === 'next') return fallback;
|
|
1086
|
+
if (typeof target === 'number')
|
|
1087
|
+
return target >= 0 && target < total ? target : fallback;
|
|
1088
|
+
if (typeof target === 'string') {
|
|
1089
|
+
const normalizedId = target.replace(/^page:/, '');
|
|
1090
|
+
const idx = this.surveyOptions.pages.findIndex(
|
|
1091
|
+
(p) => p.id === normalizedId
|
|
1189
1092
|
);
|
|
1190
|
-
return
|
|
1093
|
+
return idx >= 0 ? idx : fallback;
|
|
1191
1094
|
}
|
|
1192
|
-
|
|
1193
|
-
return fallbackNext;
|
|
1095
|
+
return fallback;
|
|
1194
1096
|
}
|
|
1195
1097
|
|
|
1196
1098
|
_getSubmissionRating() {
|
|
@@ -1295,23 +1197,45 @@ export class SurveyWidget extends BaseWidget {
|
|
|
1295
1197
|
setTimeout(() => error.remove(), 3000);
|
|
1296
1198
|
}
|
|
1297
1199
|
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1200
|
+
_showThankYouScreen() {
|
|
1201
|
+
if (!this.surveyElement) return;
|
|
1202
|
+
|
|
1203
|
+
const config = this.surveyOptions.thankYouConfig || {};
|
|
1204
|
+
const title = config.title || 'Thanks for your feedback!';
|
|
1205
|
+
const buttonText = config.button_text || null;
|
|
1206
|
+
const buttonUrl = config.button_url || '#';
|
|
1207
|
+
|
|
1208
|
+
if (this._escapeHandler) {
|
|
1209
|
+
document.removeEventListener('keydown', this._escapeHandler);
|
|
1210
|
+
this._escapeHandler = null;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
this.surveyElement.innerHTML = `
|
|
1214
|
+
<button class="feedback-survey-close"><iconify-icon icon="ph:x-duotone" width="16" height="16"></iconify-icon></button>
|
|
1215
|
+
<div class="feedback-survey-thankyou">
|
|
1216
|
+
<iconify-icon icon="ph:check-circle-duotone" width="48" height="48" class="feedback-survey-thankyou-icon"></iconify-icon>
|
|
1217
|
+
<h3 class="feedback-survey-thankyou-title">${title}</h3>
|
|
1218
|
+
${
|
|
1219
|
+
buttonText
|
|
1220
|
+
? `
|
|
1221
|
+
<a class="feedback-survey-thankyou-btn" href="${buttonUrl}" target="_blank" rel="noopener noreferrer">
|
|
1222
|
+
${buttonText}
|
|
1223
|
+
<iconify-icon icon="ph:arrow-square-out-duotone" width="15" height="15" style="pointer-events:none;"></iconify-icon>
|
|
1224
|
+
</a>`
|
|
1225
|
+
: ''
|
|
1226
|
+
}
|
|
1306
1227
|
</div>
|
|
1307
1228
|
`;
|
|
1308
|
-
document.body.appendChild(notification);
|
|
1309
1229
|
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1230
|
+
const closeBtn = this.surveyElement.querySelector('.feedback-survey-close');
|
|
1231
|
+
if (closeBtn) closeBtn.addEventListener('click', () => this._closeSurvey());
|
|
1232
|
+
|
|
1233
|
+
setTimeout(
|
|
1234
|
+
() => {
|
|
1235
|
+
if (this.surveyElement) this._closeSurvey();
|
|
1236
|
+
},
|
|
1237
|
+
buttonText ? 6000 : 3500
|
|
1238
|
+
);
|
|
1315
1239
|
}
|
|
1316
1240
|
|
|
1317
1241
|
_closeSurvey(resetState = true, immediate = false) {
|