@product7/feedback-sdk 1.6.5 → 1.6.7
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 -0
- package/dist/README.md +4 -0
- package/dist/feedback-sdk.js +188 -17
- 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/api/services/ChangelogService.js +1 -1
- package/src/api/services/HelpService.js +1 -1
- package/src/api/services/MessengerService.js +1 -1
- package/src/api/services/SurveyService.js +1 -1
- package/src/core/BaseAPIService.js +36 -4
- package/src/core/FeedbackSDK.js +60 -5
- package/src/widgets/BaseWidget.js +9 -0
- package/src/widgets/MessengerWidget.js +72 -8
- package/src/widgets/SurveyWidget.js +11 -0
- package/types/index.d.ts +30 -0
package/package.json
CHANGED
|
@@ -90,15 +90,19 @@ export class BaseAPIService {
|
|
|
90
90
|
body: JSON.stringify(payload),
|
|
91
91
|
headers: { 'Content-Type': 'application/json' },
|
|
92
92
|
});
|
|
93
|
+
const initData = this._extractInitResponseData(response);
|
|
93
94
|
|
|
94
|
-
this.sessionToken =
|
|
95
|
-
this.sessionExpiry = new Date(Date.now() +
|
|
95
|
+
this.sessionToken = initData.sessionToken;
|
|
96
|
+
this.sessionExpiry = new Date(Date.now() + initData.expiresIn * 1000);
|
|
96
97
|
this._storeSession();
|
|
97
98
|
|
|
98
99
|
return {
|
|
99
100
|
sessionToken: this.sessionToken,
|
|
100
|
-
config:
|
|
101
|
-
expiresIn:
|
|
101
|
+
config: initData.config,
|
|
102
|
+
expiresIn: initData.expiresIn,
|
|
103
|
+
status: initData.status,
|
|
104
|
+
message: initData.message,
|
|
105
|
+
configVersion: initData.configVersion,
|
|
102
106
|
};
|
|
103
107
|
} catch (error) {
|
|
104
108
|
throw new APIError(
|
|
@@ -109,6 +113,34 @@ export class BaseAPIService {
|
|
|
109
113
|
}
|
|
110
114
|
}
|
|
111
115
|
|
|
116
|
+
_extractInitResponseData(response) {
|
|
117
|
+
const payload =
|
|
118
|
+
response && typeof response.data === 'object' ? response.data : response || {};
|
|
119
|
+
|
|
120
|
+
const sessionToken = payload.session_token || payload.sessionToken;
|
|
121
|
+
const expiresIn = Number(payload.expires_in ?? payload.expiresIn);
|
|
122
|
+
|
|
123
|
+
if (!sessionToken) {
|
|
124
|
+
throw new APIError(500, 'Invalid init response: missing session_token');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!Number.isFinite(expiresIn) || expiresIn <= 0) {
|
|
128
|
+
throw new APIError(500, 'Invalid init response: missing expires_in');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
sessionToken,
|
|
133
|
+
expiresIn,
|
|
134
|
+
config:
|
|
135
|
+
payload.config && typeof payload.config === 'object'
|
|
136
|
+
? payload.config
|
|
137
|
+
: {},
|
|
138
|
+
configVersion: payload.config_version ?? payload.configVersion ?? null,
|
|
139
|
+
status: response?.status ?? payload?.status ?? true,
|
|
140
|
+
message: response?.message ?? payload?.message ?? null,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
112
144
|
async _ensureSession() {
|
|
113
145
|
if (!this.isSessionValid()) {
|
|
114
146
|
await this.init();
|
package/src/core/FeedbackSDK.js
CHANGED
|
@@ -65,6 +65,10 @@ export class FeedbackSDK {
|
|
|
65
65
|
const widgetId = generateId('widget');
|
|
66
66
|
const widgetConfig = this._getWidgetTypeConfig(type);
|
|
67
67
|
const explicitOptions = this._omitUndefined(options);
|
|
68
|
+
const widgetEnabled = this._isWidgetEnabled(type, {
|
|
69
|
+
...widgetConfig,
|
|
70
|
+
...explicitOptions,
|
|
71
|
+
});
|
|
68
72
|
const widgetOptions = {
|
|
69
73
|
id: widgetId,
|
|
70
74
|
sdk: this,
|
|
@@ -72,6 +76,7 @@ export class FeedbackSDK {
|
|
|
72
76
|
...this.config,
|
|
73
77
|
...widgetConfig,
|
|
74
78
|
...explicitOptions,
|
|
79
|
+
enabled: widgetEnabled,
|
|
75
80
|
};
|
|
76
81
|
|
|
77
82
|
try {
|
|
@@ -162,6 +167,7 @@ export class FeedbackSDK {
|
|
|
162
167
|
surveyConfig.showDescription ?? surveyConfig.show_description,
|
|
163
168
|
customQuestions: surveyConfig.customQuestions || surveyConfig.questions,
|
|
164
169
|
pages: surveyConfig.pages,
|
|
170
|
+
enabled: surveyConfig.enabled,
|
|
165
171
|
...displayOptions,
|
|
166
172
|
});
|
|
167
173
|
}
|
|
@@ -184,6 +190,17 @@ export class FeedbackSDK {
|
|
|
184
190
|
|
|
185
191
|
const normalizedOptions = this._normalizeSurveyConfig(options);
|
|
186
192
|
const surveyConfigDefaults = this._getWidgetTypeConfig('survey');
|
|
193
|
+
const surveyEnabled = this._isWidgetEnabled('survey', normalizedOptions);
|
|
194
|
+
|
|
195
|
+
if (!surveyEnabled) {
|
|
196
|
+
this.eventBus.emit('survey:suppressed', {
|
|
197
|
+
surveyId:
|
|
198
|
+
normalizedOptions.surveyId || normalizedOptions.id || options.id || null,
|
|
199
|
+
reason: 'disabled',
|
|
200
|
+
survey: normalizedOptions,
|
|
201
|
+
});
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
187
204
|
|
|
188
205
|
const surveyWidget = this.createWidget('survey', {
|
|
189
206
|
surveyId: normalizedOptions.surveyId,
|
|
@@ -215,6 +232,7 @@ export class FeedbackSDK {
|
|
|
215
232
|
email: normalizedOptions.email,
|
|
216
233
|
onSubmit: normalizedOptions.onSubmit,
|
|
217
234
|
onDismiss: normalizedOptions.onDismiss,
|
|
235
|
+
enabled: surveyEnabled,
|
|
218
236
|
});
|
|
219
237
|
|
|
220
238
|
surveyWidget.mount();
|
|
@@ -308,13 +326,19 @@ export class FeedbackSDK {
|
|
|
308
326
|
: {};
|
|
309
327
|
|
|
310
328
|
const inferredType =
|
|
311
|
-
survey.
|
|
329
|
+
survey.surveyType ||
|
|
330
|
+
survey.survey_type ||
|
|
331
|
+
survey.type ||
|
|
332
|
+
this._inferSurveyTypeFromPage(firstPage) ||
|
|
333
|
+
'nps';
|
|
312
334
|
|
|
313
335
|
return {
|
|
314
336
|
...survey,
|
|
315
|
-
surveyId: survey.surveyId || survey.id || null,
|
|
316
|
-
surveyType: survey.surveyType || inferredType,
|
|
317
|
-
type: survey.type || inferredType,
|
|
337
|
+
surveyId: survey.surveyId || survey.survey_id || survey.id || null,
|
|
338
|
+
surveyType: survey.surveyType || survey.survey_type || inferredType,
|
|
339
|
+
type: survey.type || survey.survey_type || inferredType,
|
|
340
|
+
enabled:
|
|
341
|
+
typeof survey.enabled === 'boolean' ? survey.enabled : undefined,
|
|
318
342
|
should_show:
|
|
319
343
|
survey.should_show ??
|
|
320
344
|
(survey.eligibility ? survey.eligibility.should_show : undefined),
|
|
@@ -343,7 +367,11 @@ export class FeedbackSDK {
|
|
|
343
367
|
showTitle: survey.showTitle ?? survey.show_title ?? null,
|
|
344
368
|
showDescription:
|
|
345
369
|
survey.showDescription ?? survey.show_description ?? null,
|
|
346
|
-
customQuestions:
|
|
370
|
+
customQuestions:
|
|
371
|
+
survey.customQuestions ||
|
|
372
|
+
survey.custom_questions ||
|
|
373
|
+
survey.questions ||
|
|
374
|
+
[],
|
|
347
375
|
pages: this._normalizeSurveyPages(survey.pages || []),
|
|
348
376
|
};
|
|
349
377
|
}
|
|
@@ -418,6 +446,23 @@ export class FeedbackSDK {
|
|
|
418
446
|
return this._toCamelCaseObject(mergedTypeConfig);
|
|
419
447
|
}
|
|
420
448
|
|
|
449
|
+
_isWidgetEnabled(type, options = {}) {
|
|
450
|
+
const typeConfig = this._getWidgetTypeConfig(type);
|
|
451
|
+
if (typeConfig.enabled === false) {
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (typeof options.enabled === 'boolean') {
|
|
456
|
+
return options.enabled;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (typeof typeConfig.enabled === 'boolean') {
|
|
460
|
+
return typeConfig.enabled;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return true;
|
|
464
|
+
}
|
|
465
|
+
|
|
421
466
|
_isPlainObject(value) {
|
|
422
467
|
return Object.prototype.toString.call(value) === '[object Object]';
|
|
423
468
|
}
|
|
@@ -471,11 +516,21 @@ export class FeedbackSDK {
|
|
|
471
516
|
|
|
472
517
|
const configDefaults = this._getWidgetTypeConfig('changelog');
|
|
473
518
|
const explicitOptions = this._omitUndefined(options);
|
|
519
|
+
const changelogEnabled = this._isWidgetEnabled('changelog', explicitOptions);
|
|
520
|
+
|
|
521
|
+
if (!changelogEnabled) {
|
|
522
|
+
this.eventBus.emit('widget:suppressed', {
|
|
523
|
+
type: 'changelog',
|
|
524
|
+
reason: 'disabled',
|
|
525
|
+
});
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
474
528
|
|
|
475
529
|
const changelogWidget = this.createWidget('changelog', {
|
|
476
530
|
...defaults,
|
|
477
531
|
...configDefaults,
|
|
478
532
|
...explicitOptions,
|
|
533
|
+
enabled: changelogEnabled,
|
|
479
534
|
});
|
|
480
535
|
|
|
481
536
|
changelogWidget.mount();
|
|
@@ -48,6 +48,15 @@ export class BaseWidget {
|
|
|
48
48
|
mount(container) {
|
|
49
49
|
if (this.mounted || this.destroyed) return this;
|
|
50
50
|
|
|
51
|
+
if (this.options.enabled === false) {
|
|
52
|
+
this.sdk.eventBus.emit('widget:suppressed', {
|
|
53
|
+
widget: this,
|
|
54
|
+
type: this.type,
|
|
55
|
+
reason: 'disabled',
|
|
56
|
+
});
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
|
|
51
60
|
if (this.options.suppressAfterSubmission && this._hasRecentlySubmitted()) {
|
|
52
61
|
this.sdk.eventBus.emit('widget:suppressed', {
|
|
53
62
|
widget: this,
|
|
@@ -18,6 +18,11 @@ export class MessengerWidget extends BaseWidget {
|
|
|
18
18
|
constructor(options) {
|
|
19
19
|
super({ ...options, type: 'messenger' });
|
|
20
20
|
|
|
21
|
+
const resolvedEnableChangelog =
|
|
22
|
+
typeof options.enableChangelog === 'boolean'
|
|
23
|
+
? options.enableChangelog
|
|
24
|
+
: options.enableNews !== false;
|
|
25
|
+
|
|
21
26
|
this.messengerOptions = {
|
|
22
27
|
position: options.position || 'bottom-right',
|
|
23
28
|
theme: options.theme || 'light',
|
|
@@ -30,7 +35,10 @@ export class MessengerWidget extends BaseWidget {
|
|
|
30
35
|
greetingMessage: options.greetingMessage || 'Hi there 👋',
|
|
31
36
|
welcomeMessage: options.welcomeMessage || 'How can we help?',
|
|
32
37
|
enableHelp: options.enableHelp !== false,
|
|
33
|
-
enableChangelog:
|
|
38
|
+
enableChangelog: resolvedEnableChangelog,
|
|
39
|
+
autoLoadData: options.autoLoadData !== false,
|
|
40
|
+
initialView: options.initialView || 'home',
|
|
41
|
+
previewData: options.previewData || null,
|
|
34
42
|
featuredContent: options.featuredContent || null,
|
|
35
43
|
feedbackUrl: options.feedbackUrl || null,
|
|
36
44
|
changelogUrl: options.changelogUrl || null,
|
|
@@ -498,6 +506,51 @@ export class MessengerWidget extends BaseWidget {
|
|
|
498
506
|
};
|
|
499
507
|
}
|
|
500
508
|
|
|
509
|
+
_applyPreviewData() {
|
|
510
|
+
const data = this.messengerOptions.previewData;
|
|
511
|
+
if (!data || typeof data !== 'object') {
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if (Array.isArray(data.conversations)) {
|
|
516
|
+
this.messengerState.setConversations(data.conversations);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
if (Array.isArray(data.helpArticles)) {
|
|
520
|
+
this.messengerState.setHelpArticles(data.helpArticles);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
if (Array.isArray(data.homeChangelogItems)) {
|
|
524
|
+
this.messengerState.setHomeChangelogItems(data.homeChangelogItems);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (Array.isArray(data.changelogItems)) {
|
|
528
|
+
this.messengerState.setChangelogItems(data.changelogItems);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (typeof data.unreadCount === 'number') {
|
|
532
|
+
this.setUnreadCount(data.unreadCount);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if (data.availability && typeof data.availability === 'object') {
|
|
536
|
+
const availability = data.availability;
|
|
537
|
+
this.messengerState.agentsOnline = Boolean(
|
|
538
|
+
availability.agentsOnline ?? availability.agents_online
|
|
539
|
+
);
|
|
540
|
+
this.messengerState.onlineCount =
|
|
541
|
+
availability.onlineCount ?? availability.online_count ?? 0;
|
|
542
|
+
this.messengerState.responseTime =
|
|
543
|
+
availability.responseTime ??
|
|
544
|
+
availability.response_time ??
|
|
545
|
+
this.messengerState.responseTime;
|
|
546
|
+
this.messengerState._notify('availabilityUpdate', availability);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
if (typeof data.currentView === 'string') {
|
|
550
|
+
this.messengerState.setView(data.currentView);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
501
554
|
async loadInitialData() {
|
|
502
555
|
try {
|
|
503
556
|
const conversations = await this._fetchConversations();
|
|
@@ -824,17 +877,28 @@ export class MessengerWidget extends BaseWidget {
|
|
|
824
877
|
}
|
|
825
878
|
|
|
826
879
|
async onMount() {
|
|
827
|
-
this.
|
|
880
|
+
this._applyPreviewData();
|
|
828
881
|
|
|
829
|
-
if (this.
|
|
830
|
-
this.
|
|
831
|
-
}
|
|
882
|
+
if (this.messengerOptions.autoLoadData) {
|
|
883
|
+
this.loadInitialData();
|
|
832
884
|
|
|
833
|
-
|
|
885
|
+
if (this.apiService?.sessionToken) {
|
|
886
|
+
this._initWebSocket();
|
|
887
|
+
}
|
|
834
888
|
|
|
835
|
-
this._availabilityInterval = setInterval(() => {
|
|
836
889
|
this.checkAgentAvailability();
|
|
837
|
-
|
|
890
|
+
|
|
891
|
+
this._availabilityInterval = setInterval(() => {
|
|
892
|
+
this.checkAgentAvailability();
|
|
893
|
+
}, 60000);
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
if (
|
|
897
|
+
this.messengerOptions.initialView &&
|
|
898
|
+
this.messengerOptions.initialView !== this.messengerState.currentView
|
|
899
|
+
) {
|
|
900
|
+
this.messengerState.setView(this.messengerOptions.initialView);
|
|
901
|
+
}
|
|
838
902
|
}
|
|
839
903
|
|
|
840
904
|
onDestroy() {
|
|
@@ -8,6 +8,8 @@ export class SurveyWidget extends BaseWidget {
|
|
|
8
8
|
surveyId: options.surveyId || null,
|
|
9
9
|
surveyType: options.surveyType || 'nps',
|
|
10
10
|
position: options.position || 'bottom-right',
|
|
11
|
+
enabled:
|
|
12
|
+
typeof options.enabled === 'boolean' ? options.enabled : undefined,
|
|
11
13
|
title: options.title || null,
|
|
12
14
|
description: options.description || null,
|
|
13
15
|
lowLabel: options.lowLabel || null,
|
|
@@ -61,6 +63,15 @@ export class SurveyWidget extends BaseWidget {
|
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
show() {
|
|
66
|
+
if (this.options.enabled === false || this.surveyOptions.enabled === false) {
|
|
67
|
+
this.sdk.eventBus.emit('survey:suppressed', {
|
|
68
|
+
widget: this,
|
|
69
|
+
surveyId: this.surveyOptions.surveyId,
|
|
70
|
+
reason: 'disabled',
|
|
71
|
+
});
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
|
|
64
75
|
this._renderSurvey();
|
|
65
76
|
this.surveyState.isVisible = true;
|
|
66
77
|
this.sdk.eventBus.emit('survey:shown', {
|
package/types/index.d.ts
CHANGED
|
@@ -4,10 +4,14 @@ declare module '@product7/feedback-sdk' {
|
|
|
4
4
|
userContext?: UserContext;
|
|
5
5
|
debug?: boolean;
|
|
6
6
|
boardId?: string;
|
|
7
|
+
siteId?: string;
|
|
8
|
+
sessionToken?: string;
|
|
7
9
|
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
8
10
|
theme?: 'light' | 'dark';
|
|
9
11
|
apiUrl?: string;
|
|
10
12
|
autoShow?: boolean;
|
|
13
|
+
mock?: boolean;
|
|
14
|
+
env?: string;
|
|
11
15
|
widgets?: WidgetConfigMap;
|
|
12
16
|
}
|
|
13
17
|
|
|
@@ -24,6 +28,7 @@ declare module '@product7/feedback-sdk' {
|
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
export interface ButtonWidgetOptions {
|
|
31
|
+
enabled?: boolean;
|
|
27
32
|
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
28
33
|
theme?: 'light' | 'dark';
|
|
29
34
|
boardId?: string;
|
|
@@ -74,6 +79,9 @@ declare module '@product7/feedback-sdk' {
|
|
|
74
79
|
config?: any;
|
|
75
80
|
sessionToken?: string;
|
|
76
81
|
expiresIn?: number;
|
|
82
|
+
status?: boolean;
|
|
83
|
+
message?: string | null;
|
|
84
|
+
configVersion?: number | null;
|
|
77
85
|
}>;
|
|
78
86
|
createWidget(type: 'button', options?: ButtonWidgetOptions): ButtonWidget;
|
|
79
87
|
createWidget(type: 'survey', options?: SurveyWidgetOptions): SurveyWidget;
|
|
@@ -148,6 +156,7 @@ declare module '@product7/feedback-sdk' {
|
|
|
148
156
|
}
|
|
149
157
|
|
|
150
158
|
export interface SurveyWidgetOptions {
|
|
159
|
+
enabled?: boolean;
|
|
151
160
|
surveyId?: string | null;
|
|
152
161
|
surveyType?: SurveyType;
|
|
153
162
|
position?: 'bottom-right' | 'bottom-left' | 'center' | 'bottom';
|
|
@@ -221,6 +230,7 @@ declare module '@product7/feedback-sdk' {
|
|
|
221
230
|
}
|
|
222
231
|
|
|
223
232
|
export interface ChangelogWidgetOptions {
|
|
233
|
+
enabled?: boolean;
|
|
224
234
|
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
225
235
|
theme?: 'light' | 'dark';
|
|
226
236
|
triggerText?: string;
|
|
@@ -250,6 +260,7 @@ declare module '@product7/feedback-sdk' {
|
|
|
250
260
|
}
|
|
251
261
|
|
|
252
262
|
export interface MessengerWidgetOptions {
|
|
263
|
+
enabled?: boolean;
|
|
253
264
|
position?: 'bottom-right' | 'bottom-left';
|
|
254
265
|
theme?: 'light' | 'dark';
|
|
255
266
|
teamName?: string;
|
|
@@ -258,6 +269,25 @@ declare module '@product7/feedback-sdk' {
|
|
|
258
269
|
welcomeMessage?: string;
|
|
259
270
|
enableHelp?: boolean;
|
|
260
271
|
enableChangelog?: boolean;
|
|
272
|
+
enableNews?: boolean;
|
|
273
|
+
autoLoadData?: boolean;
|
|
274
|
+
initialView?: 'home' | 'messages' | 'chat' | 'prechat' | 'help' | 'changelog';
|
|
275
|
+
previewData?: {
|
|
276
|
+
conversations?: any[];
|
|
277
|
+
helpArticles?: any[];
|
|
278
|
+
homeChangelogItems?: any[];
|
|
279
|
+
changelogItems?: any[];
|
|
280
|
+
unreadCount?: number;
|
|
281
|
+
currentView?: string;
|
|
282
|
+
availability?: {
|
|
283
|
+
agentsOnline?: boolean;
|
|
284
|
+
agents_online?: boolean;
|
|
285
|
+
onlineCount?: number;
|
|
286
|
+
online_count?: number;
|
|
287
|
+
responseTime?: string;
|
|
288
|
+
response_time?: string;
|
|
289
|
+
};
|
|
290
|
+
};
|
|
261
291
|
logoUrl?: string;
|
|
262
292
|
primaryColor?: string;
|
|
263
293
|
featuredContent?: {
|