@product7/feedback-sdk 1.5.2 → 1.5.4
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/dist/feedback-sdk.js +644 -33
- package/dist/feedback-sdk.js.map +1 -1
- package/dist/feedback-sdk.min.js +1 -1
- package/dist/feedback-sdk.min.js.map +1 -1
- package/package.json +1 -1
- package/src/core/FeedbackSDK.js +139 -18
- package/src/styles/survey.js +61 -1
- package/src/widgets/SurveyWidget.js +444 -14
- package/types/index.d.ts +38 -0
package/package.json
CHANGED
package/src/core/FeedbackSDK.js
CHANGED
|
@@ -94,7 +94,9 @@ export class FeedbackSDK {
|
|
|
94
94
|
|
|
95
95
|
try {
|
|
96
96
|
const result = await this.apiService.getActiveSurveys(context);
|
|
97
|
-
const surveys = result.data || []
|
|
97
|
+
const surveys = (result.data || []).map((survey) =>
|
|
98
|
+
this._normalizeSurveyConfig(survey)
|
|
99
|
+
);
|
|
98
100
|
if (context.includeIneligible) {
|
|
99
101
|
return surveys;
|
|
100
102
|
}
|
|
@@ -140,12 +142,13 @@ export class FeedbackSDK {
|
|
|
140
142
|
|
|
141
143
|
return this.showSurvey({
|
|
142
144
|
surveyId: surveyConfig.id,
|
|
143
|
-
surveyType: surveyConfig.type,
|
|
145
|
+
surveyType: surveyConfig.surveyType || surveyConfig.type,
|
|
144
146
|
title: surveyConfig.title,
|
|
145
147
|
description: surveyConfig.description,
|
|
146
|
-
lowLabel: surveyConfig.low_label,
|
|
147
|
-
highLabel: surveyConfig.high_label,
|
|
148
|
-
customQuestions: surveyConfig.questions,
|
|
148
|
+
lowLabel: surveyConfig.lowLabel || surveyConfig.low_label,
|
|
149
|
+
highLabel: surveyConfig.highLabel || surveyConfig.high_label,
|
|
150
|
+
customQuestions: surveyConfig.customQuestions || surveyConfig.questions,
|
|
151
|
+
pages: surveyConfig.pages,
|
|
149
152
|
...displayOptions,
|
|
150
153
|
});
|
|
151
154
|
}
|
|
@@ -166,20 +169,23 @@ export class FeedbackSDK {
|
|
|
166
169
|
return null;
|
|
167
170
|
}
|
|
168
171
|
|
|
172
|
+
const normalizedOptions = this._normalizeSurveyConfig(options);
|
|
173
|
+
|
|
169
174
|
const surveyWidget = this.createWidget('survey', {
|
|
170
|
-
surveyId:
|
|
171
|
-
surveyType:
|
|
172
|
-
position:
|
|
173
|
-
theme:
|
|
174
|
-
title:
|
|
175
|
-
description:
|
|
176
|
-
lowLabel:
|
|
177
|
-
highLabel:
|
|
178
|
-
customQuestions:
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
175
|
+
surveyId: normalizedOptions.surveyId,
|
|
176
|
+
surveyType: normalizedOptions.surveyType || normalizedOptions.type || 'nps',
|
|
177
|
+
position: normalizedOptions.position || 'bottom-right',
|
|
178
|
+
theme: normalizedOptions.theme || this.config.theme || 'light',
|
|
179
|
+
title: normalizedOptions.title,
|
|
180
|
+
description: normalizedOptions.description,
|
|
181
|
+
lowLabel: normalizedOptions.lowLabel,
|
|
182
|
+
highLabel: normalizedOptions.highLabel,
|
|
183
|
+
customQuestions: normalizedOptions.customQuestions,
|
|
184
|
+
pages: normalizedOptions.pages,
|
|
185
|
+
respondentId: normalizedOptions.respondentId,
|
|
186
|
+
email: normalizedOptions.email,
|
|
187
|
+
onSubmit: normalizedOptions.onSubmit,
|
|
188
|
+
onDismiss: normalizedOptions.onDismiss,
|
|
183
189
|
});
|
|
184
190
|
|
|
185
191
|
surveyWidget.mount();
|
|
@@ -194,6 +200,14 @@ export class FeedbackSDK {
|
|
|
194
200
|
return shouldShow;
|
|
195
201
|
}
|
|
196
202
|
|
|
203
|
+
const eligibilityShouldShow = this._getSurveyField(
|
|
204
|
+
survey.eligibility || {},
|
|
205
|
+
['shouldShow', 'should_show']
|
|
206
|
+
);
|
|
207
|
+
if (typeof eligibilityShouldShow === 'boolean') {
|
|
208
|
+
return eligibilityShouldShow;
|
|
209
|
+
}
|
|
210
|
+
|
|
197
211
|
const eligible = this._getSurveyField(survey, [
|
|
198
212
|
'eligible',
|
|
199
213
|
'isEligible',
|
|
@@ -208,6 +222,14 @@ export class FeedbackSDK {
|
|
|
208
222
|
return !isAnswered;
|
|
209
223
|
}
|
|
210
224
|
|
|
225
|
+
const eligibilityAnswered = this._getSurveyField(survey.eligibility || {}, [
|
|
226
|
+
'isAnswered',
|
|
227
|
+
'is_answered',
|
|
228
|
+
]);
|
|
229
|
+
if (typeof eligibilityAnswered === 'boolean') {
|
|
230
|
+
return !eligibilityAnswered;
|
|
231
|
+
}
|
|
232
|
+
|
|
211
233
|
return true;
|
|
212
234
|
}
|
|
213
235
|
|
|
@@ -221,6 +243,15 @@ export class FeedbackSDK {
|
|
|
221
243
|
return explicitReason;
|
|
222
244
|
}
|
|
223
245
|
|
|
246
|
+
const eligibilityReason = this._getSurveyField(survey.eligibility || {}, [
|
|
247
|
+
'reason',
|
|
248
|
+
'suppressionReason',
|
|
249
|
+
'suppression_reason',
|
|
250
|
+
]);
|
|
251
|
+
if (eligibilityReason) {
|
|
252
|
+
return eligibilityReason;
|
|
253
|
+
}
|
|
254
|
+
|
|
224
255
|
const isAnswered = this._getSurveyField(survey, ['isAnswered', 'is_answered']);
|
|
225
256
|
if (isAnswered === true) {
|
|
226
257
|
return 'already_answered';
|
|
@@ -229,6 +260,96 @@ export class FeedbackSDK {
|
|
|
229
260
|
return 'ineligible';
|
|
230
261
|
}
|
|
231
262
|
|
|
263
|
+
_normalizeSurveyConfig(survey = {}) {
|
|
264
|
+
const firstPage = Array.isArray(survey.pages) && survey.pages.length > 0
|
|
265
|
+
? survey.pages[0]
|
|
266
|
+
: null;
|
|
267
|
+
const ratingConfig = firstPage
|
|
268
|
+
? firstPage.rating_config || firstPage.ratingConfig || {}
|
|
269
|
+
: {};
|
|
270
|
+
|
|
271
|
+
const inferredType =
|
|
272
|
+
survey.type ||
|
|
273
|
+
this._inferSurveyTypeFromPage(firstPage) ||
|
|
274
|
+
'nps';
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
...survey,
|
|
278
|
+
surveyId: survey.surveyId || survey.id || null,
|
|
279
|
+
surveyType: survey.surveyType || inferredType,
|
|
280
|
+
type: survey.type || inferredType,
|
|
281
|
+
should_show:
|
|
282
|
+
survey.should_show ??
|
|
283
|
+
(survey.eligibility ? survey.eligibility.should_show : undefined),
|
|
284
|
+
reason:
|
|
285
|
+
survey.reason ||
|
|
286
|
+
(survey.eligibility ? survey.eligibility.reason : undefined),
|
|
287
|
+
title:
|
|
288
|
+
survey.title ||
|
|
289
|
+
survey.name ||
|
|
290
|
+
(firstPage ? firstPage.title : null),
|
|
291
|
+
description:
|
|
292
|
+
survey.description ||
|
|
293
|
+
(firstPage ? firstPage.description : null),
|
|
294
|
+
lowLabel:
|
|
295
|
+
survey.lowLabel ||
|
|
296
|
+
survey.low_label ||
|
|
297
|
+
ratingConfig.low_label ||
|
|
298
|
+
null,
|
|
299
|
+
highLabel:
|
|
300
|
+
survey.highLabel ||
|
|
301
|
+
survey.high_label ||
|
|
302
|
+
ratingConfig.high_label ||
|
|
303
|
+
null,
|
|
304
|
+
customQuestions: survey.customQuestions || survey.questions || [],
|
|
305
|
+
pages: this._normalizeSurveyPages(survey.pages || []),
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
_normalizeSurveyPages(pages = []) {
|
|
310
|
+
if (!Array.isArray(pages)) {
|
|
311
|
+
return [];
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return pages
|
|
315
|
+
.map((page, index) => ({
|
|
316
|
+
id: page.id || `page_${index}`,
|
|
317
|
+
type: page.type || 'rating',
|
|
318
|
+
title: page.title || '',
|
|
319
|
+
description: page.description || '',
|
|
320
|
+
required: page.required !== false,
|
|
321
|
+
position: page.position ?? index,
|
|
322
|
+
ratingConfig: page.ratingConfig || page.rating_config || null,
|
|
323
|
+
multipleChoiceConfig:
|
|
324
|
+
page.multipleChoiceConfig || page.multiple_choice_config || null,
|
|
325
|
+
linkConfig: page.linkConfig || page.link_config || null,
|
|
326
|
+
afterThisPage: page.afterThisPage || page.after_this_page || null,
|
|
327
|
+
}))
|
|
328
|
+
.sort((a, b) => a.position - b.position);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
_inferSurveyTypeFromPage(page) {
|
|
332
|
+
if (!page) return null;
|
|
333
|
+
const ratingConfig = page.rating_config || page.ratingConfig || {};
|
|
334
|
+
const scale = ratingConfig.scale;
|
|
335
|
+
const surveyType = ratingConfig.survey_type;
|
|
336
|
+
const title = (page.title || '').toLowerCase();
|
|
337
|
+
|
|
338
|
+
if (scale === 11 || surveyType === 'nps') {
|
|
339
|
+
return 'nps';
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (
|
|
343
|
+
surveyType === 'emoji' ||
|
|
344
|
+
title.includes('effort') ||
|
|
345
|
+
title.includes('easy')
|
|
346
|
+
) {
|
|
347
|
+
return 'ces';
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return 'csat';
|
|
351
|
+
}
|
|
352
|
+
|
|
232
353
|
_getSurveyField(survey, fields) {
|
|
233
354
|
for (const field of fields) {
|
|
234
355
|
if (survey[field] !== undefined && survey[field] !== null) {
|
package/src/styles/survey.js
CHANGED
|
@@ -311,13 +311,73 @@ export const surveyStyles = `
|
|
|
311
311
|
box-shadow: 0 0 0 3px var(--color-primary-light);
|
|
312
312
|
}
|
|
313
313
|
|
|
314
|
+
.feedback-survey-progress {
|
|
315
|
+
font-size: var(--font-size-xs);
|
|
316
|
+
color: var(--color-text-tertiary);
|
|
317
|
+
margin-bottom: var(--spacing-3);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.feedback-survey-actions {
|
|
321
|
+
display: flex;
|
|
322
|
+
gap: var(--spacing-2);
|
|
323
|
+
margin-top: var(--spacing-3);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.feedback-survey-back {
|
|
327
|
+
padding: var(--spacing-3) var(--spacing-4);
|
|
328
|
+
border: 1px solid var(--color-border);
|
|
329
|
+
border-radius: var(--radius-md);
|
|
330
|
+
background: var(--color-surface);
|
|
331
|
+
color: var(--color-text-primary);
|
|
332
|
+
font-size: var(--font-size-base);
|
|
333
|
+
font-weight: var(--font-weight-medium);
|
|
334
|
+
cursor: pointer;
|
|
335
|
+
font-family: inherit;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.feedback-survey-page-choice-btn {
|
|
339
|
+
width: 100%;
|
|
340
|
+
padding: var(--spacing-3);
|
|
341
|
+
border: 1px solid var(--color-border);
|
|
342
|
+
border-radius: var(--radius-md);
|
|
343
|
+
background: var(--color-surface);
|
|
344
|
+
color: var(--color-text-primary);
|
|
345
|
+
text-align: left;
|
|
346
|
+
font-size: var(--font-size-base);
|
|
347
|
+
cursor: pointer;
|
|
348
|
+
margin-bottom: var(--spacing-2);
|
|
349
|
+
font-family: inherit;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.feedback-survey-page-choice-btn.selected {
|
|
353
|
+
background: var(--color-primary);
|
|
354
|
+
border-color: var(--color-primary);
|
|
355
|
+
color: var(--color-white);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.feedback-survey-page-textarea {
|
|
359
|
+
width: 100%;
|
|
360
|
+
min-height: 96px;
|
|
361
|
+
padding: var(--spacing-3);
|
|
362
|
+
border: 1px solid var(--color-border);
|
|
363
|
+
border-radius: var(--radius-md);
|
|
364
|
+
font-size: var(--font-size-base);
|
|
365
|
+
font-family: inherit;
|
|
366
|
+
box-sizing: border-box;
|
|
367
|
+
outline: none;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.feedback-survey-page-textarea:focus {
|
|
371
|
+
border-color: var(--color-primary);
|
|
372
|
+
box-shadow: 0 0 0 3px var(--color-primary-light);
|
|
373
|
+
}
|
|
374
|
+
|
|
314
375
|
/* ========================================
|
|
315
376
|
SUBMIT & FEEDBACK
|
|
316
377
|
======================================== */
|
|
317
378
|
|
|
318
379
|
.feedback-survey-submit {
|
|
319
380
|
width: 100%;
|
|
320
|
-
margin-top: var(--spacing-3);
|
|
321
381
|
padding: var(--spacing-3);
|
|
322
382
|
background: var(--color-primary);
|
|
323
383
|
color: var(--color-white);
|