@product7/product7-js 0.5.1 → 0.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/README.md +4 -4
- package/dist/README.md +4 -4
- package/dist/product7-js.js +7124 -7130
- 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/APIService.js +1 -0
- package/src/api/services/{MessengerService.js → WebChatService.js} +15 -15
- package/src/core/APIService.js +16 -16
- package/src/core/Product7.js +4 -4
- package/src/core/WebSocketService.js +3 -3
- package/src/docs/api.md +9 -9
- package/src/docs/example.md +12 -12
- package/src/docs/framework-integrations.md +5 -5
- package/src/index.js +41 -42
- package/src/styles/base.js +9 -9
- package/src/styles/design-tokens.js +2 -2
- package/src/styles/feedback.js +2 -2
- package/src/styles/styles.js +4 -4
- package/src/styles/survey.js +3 -2
- package/src/styles/{messenger-components.js → web-chat-components.js} +114 -114
- package/src/styles/{messenger-core.js → web-chat-core.js} +32 -32
- package/src/styles/{messenger-features.js → web-chat-features.js} +20 -20
- package/src/styles/{messenger-views.js → web-chat-views.js} +137 -137
- package/src/styles/web-chat.js +17 -0
- package/src/styles/{messengerCustomStyles.js → webChatCustomStyles.js} +17 -19
- package/src/widgets/SurveyWidget.js +6 -1
- package/src/widgets/{MessengerWidget.js → WebChatWidget.js} +169 -172
- package/src/widgets/WidgetFactory.js +3 -3
- package/src/widgets/{messenger/MessengerState.js → web-chat/WebChatState.js} +1 -1
- package/src/widgets/{messenger → web-chat}/components/NavigationTabs.js +13 -13
- package/src/widgets/{messenger/components/MessengerLauncher.js → web-chat/components/WebChatLauncher.js} +15 -17
- package/src/widgets/{messenger/components/MessengerPanel.js → web-chat/components/WebChatPanel.js} +11 -11
- package/src/widgets/{messenger → web-chat}/views/ChangelogView.js +17 -17
- package/src/widgets/{messenger → web-chat}/views/ChatView.js +97 -99
- package/src/widgets/{messenger → web-chat}/views/ConversationsView.js +24 -24
- package/src/widgets/{messenger → web-chat}/views/HelpView.js +29 -29
- package/src/widgets/{messenger → web-chat}/views/HomeView.js +53 -55
- package/src/widgets/{messenger → web-chat}/views/PreChatFormView.js +17 -17
- package/src/styles/messenger.js +0 -17
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import { WebSocketService } from '../core/WebSocketService.js';
|
|
1
|
+
import { WebSocketService } from '../core/WebSocketService.js';
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
} from '../styles/
|
|
3
|
+
applywebChatCustomStyles,
|
|
4
|
+
removewebChatCustomStyles,
|
|
5
|
+
} from '../styles/webChatCustomStyles.js';
|
|
6
6
|
import { NotificationSound } from '../utils/NotificationSound.js';
|
|
7
7
|
import { BaseWidget } from './BaseWidget.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { ChangelogView } from './
|
|
12
|
-
import { ChatView } from './
|
|
13
|
-
import { ConversationsView } from './
|
|
14
|
-
import { HelpView } from './
|
|
15
|
-
import { HomeView } from './
|
|
16
|
-
import { PreChatFormView } from './
|
|
17
|
-
|
|
18
|
-
export class
|
|
8
|
+
import { WebChatState } from './web-chat/WebChatState.js';
|
|
9
|
+
import { WebChatLauncher } from './web-chat/components/WebChatLauncher.js';
|
|
10
|
+
import { WebChatPanel } from './web-chat/components/WebChatPanel.js';
|
|
11
|
+
import { ChangelogView } from './web-chat/views/ChangelogView.js';
|
|
12
|
+
import { ChatView } from './web-chat/views/ChatView.js';
|
|
13
|
+
import { ConversationsView } from './web-chat/views/ConversationsView.js';
|
|
14
|
+
import { HelpView } from './web-chat/views/HelpView.js';
|
|
15
|
+
import { HomeView } from './web-chat/views/HomeView.js';
|
|
16
|
+
import { PreChatFormView } from './web-chat/views/PreChatFormView.js';
|
|
17
|
+
|
|
18
|
+
export class WebChatWidget extends BaseWidget {
|
|
19
19
|
constructor(options) {
|
|
20
|
-
super({ ...options, type: '
|
|
20
|
+
super({ ...options, type: 'webChat' });
|
|
21
21
|
this._explicitOptions = options || {};
|
|
22
22
|
const resolvedTheme = options.theme || 'light';
|
|
23
23
|
const hasExplicitTextColor = Object.prototype.hasOwnProperty.call(
|
|
@@ -37,7 +37,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
37
37
|
? options.enableChangelog
|
|
38
38
|
: options.enableNews !== false;
|
|
39
39
|
|
|
40
|
-
this.
|
|
40
|
+
this.webChatOptions = {
|
|
41
41
|
position: options.position || 'right',
|
|
42
42
|
theme: resolvedTheme,
|
|
43
43
|
primaryColor: options.primaryColor || '#155EEF',
|
|
@@ -73,27 +73,27 @@ export class MessengerWidget extends BaseWidget {
|
|
|
73
73
|
|
|
74
74
|
const sdkMetadata = this.sdk?.apiService?.getMetadata() || null;
|
|
75
75
|
|
|
76
|
-
this.
|
|
77
|
-
teamName: this.
|
|
78
|
-
teamAvatars: this.
|
|
79
|
-
greetingMessage: this.
|
|
80
|
-
welcomeMessage: this.
|
|
81
|
-
onlineMessage: this.
|
|
82
|
-
responseTime: this.
|
|
83
|
-
enableHelp: this.
|
|
84
|
-
enableChangelog: this.
|
|
76
|
+
this.WebChatState = new WebChatState({
|
|
77
|
+
teamName: this.webChatOptions.teamName,
|
|
78
|
+
teamAvatars: this.webChatOptions.teamAvatars,
|
|
79
|
+
greetingMessage: this.webChatOptions.greetingMessage,
|
|
80
|
+
welcomeMessage: this.webChatOptions.welcomeMessage,
|
|
81
|
+
onlineMessage: this.webChatOptions.onlineMessage,
|
|
82
|
+
responseTime: this.webChatOptions.responseTime,
|
|
83
|
+
enableHelp: this.webChatOptions.enableHelp,
|
|
84
|
+
enableChangelog: this.webChatOptions.enableChangelog,
|
|
85
85
|
metadata: sdkMetadata,
|
|
86
86
|
urls: {
|
|
87
|
-
feedback: this.
|
|
88
|
-
changelog: this.
|
|
89
|
-
help: this.
|
|
90
|
-
roadmap: this.
|
|
87
|
+
feedback: this.webChatOptions.feedbackUrl,
|
|
88
|
+
changelog: this.webChatOptions.changelogUrl,
|
|
89
|
+
help: this.webChatOptions.helpUrl,
|
|
90
|
+
roadmap: this.webChatOptions.roadmapUrl,
|
|
91
91
|
},
|
|
92
92
|
});
|
|
93
93
|
|
|
94
94
|
// If identify() was called before this widget was created, pre-seed identity
|
|
95
95
|
if (this.sdk?.identified && sdkMetadata) {
|
|
96
|
-
this.
|
|
96
|
+
this.WebChatState.isIdentified = true;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
this.launcher = null;
|
|
@@ -136,63 +136,62 @@ export class MessengerWidget extends BaseWidget {
|
|
|
136
136
|
trigger: false,
|
|
137
137
|
displayMode: 'modal',
|
|
138
138
|
boardName:
|
|
139
|
-
this.
|
|
140
|
-
primaryColor: this.
|
|
141
|
-
theme: this.
|
|
139
|
+
this.webChatOptions.feedbackBoardName || this.sdk.config.boardName,
|
|
140
|
+
primaryColor: this.webChatOptions.primaryColor,
|
|
141
|
+
theme: this.webChatOptions.theme,
|
|
142
142
|
});
|
|
143
143
|
widget.mount();
|
|
144
144
|
return widget;
|
|
145
145
|
} catch (e) {
|
|
146
|
-
console.warn('[
|
|
146
|
+
console.warn('[WebChat] Could not create internal feedback widget:', e);
|
|
147
147
|
return null;
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
151
151
|
_render() {
|
|
152
152
|
const container = document.createElement('div');
|
|
153
|
-
container.className = `
|
|
153
|
+
container.className = `web-chat-widget theme-${this.webChatOptions.theme}`;
|
|
154
154
|
container.style.zIndex = '999999';
|
|
155
155
|
|
|
156
|
-
|
|
157
|
-
primaryColor: this.
|
|
158
|
-
textColor: this.
|
|
159
|
-
backgroundColor: this.
|
|
160
|
-
theme: this.
|
|
156
|
+
applywebChatCustomStyles({
|
|
157
|
+
primaryColor: this.webChatOptions.primaryColor,
|
|
158
|
+
textColor: this.webChatOptions.textColor,
|
|
159
|
+
backgroundColor: this.webChatOptions.backgroundColor,
|
|
160
|
+
theme: this.webChatOptions.theme,
|
|
161
161
|
});
|
|
162
162
|
|
|
163
163
|
// Create internal feedback widget (no floating button) so the
|
|
164
164
|
// "Leave a feedback" button in the home view can open it inline.
|
|
165
|
-
if (!this.
|
|
165
|
+
if (!this.webChatOptions.onFeedbackClick) {
|
|
166
166
|
this._feedbackWidget = this._createInternalFeedbackWidget();
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
if (this._hasTrigger()) {
|
|
170
|
-
this.launcher = new
|
|
171
|
-
position: this.
|
|
172
|
-
primaryColor: this.
|
|
170
|
+
this.launcher = new WebChatLauncher(this.WebChatState, {
|
|
171
|
+
position: this.webChatOptions.position,
|
|
172
|
+
primaryColor: this.webChatOptions.primaryColor,
|
|
173
173
|
});
|
|
174
174
|
container.appendChild(this.launcher.render());
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
this.panel = new
|
|
178
|
-
position: this.
|
|
179
|
-
theme: this.
|
|
180
|
-
primaryColor: this.
|
|
181
|
-
logoUrl: this.
|
|
182
|
-
featuredContent: this.
|
|
177
|
+
this.panel = new WebChatPanel(this.WebChatState, {
|
|
178
|
+
position: this.webChatOptions.position,
|
|
179
|
+
theme: this.webChatOptions.theme,
|
|
180
|
+
primaryColor: this.webChatOptions.primaryColor,
|
|
181
|
+
logoUrl: this.webChatOptions.logoUrl,
|
|
182
|
+
featuredContent: this.webChatOptions.featuredContent,
|
|
183
183
|
onSendMessage:
|
|
184
|
-
this.
|
|
185
|
-
this._handleSendMessage.bind(this),
|
|
184
|
+
this.webChatOptions.onSendMessage || this._handleSendMessage.bind(this),
|
|
186
185
|
onStartConversation: this._handleStartConversation.bind(this),
|
|
187
186
|
onTyping: this.sendTypingIndicator.bind(this),
|
|
188
187
|
onSelectConversation: this._handleSelectConversation.bind(this),
|
|
189
188
|
onStartNewConversation: this._handleNewConversationClick.bind(this),
|
|
190
189
|
onIdentifyContact: this._handleIdentifyContact.bind(this),
|
|
191
190
|
onFeedbackClick:
|
|
192
|
-
this.
|
|
191
|
+
this.webChatOptions.onFeedbackClick ||
|
|
193
192
|
(this._feedbackWidget ? () => this._feedbackWidget.open() : null),
|
|
194
|
-
onArticleClick: this.
|
|
195
|
-
onChangelogClick: this.
|
|
193
|
+
onArticleClick: this.webChatOptions.onArticleClick,
|
|
194
|
+
onChangelogClick: this.webChatOptions.onChangelogClick,
|
|
196
195
|
});
|
|
197
196
|
|
|
198
197
|
this.panel.registerView('home', HomeView);
|
|
@@ -209,7 +208,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
209
208
|
}
|
|
210
209
|
|
|
211
210
|
_attachEvents() {
|
|
212
|
-
this._stateUnsubscribe = this.
|
|
211
|
+
this._stateUnsubscribe = this.WebChatState.subscribe((type, data) => {
|
|
213
212
|
if (type === 'openChange') {
|
|
214
213
|
this._handleOpenChange(data.isOpen);
|
|
215
214
|
}
|
|
@@ -225,11 +224,11 @@ export class MessengerWidget extends BaseWidget {
|
|
|
225
224
|
_handleOpenChange(isOpen) {
|
|
226
225
|
if (isOpen) {
|
|
227
226
|
this.panel.show();
|
|
228
|
-
this.sdk.eventBus.emit('
|
|
227
|
+
this.sdk.eventBus.emit('webChat:opened', { widget: this });
|
|
229
228
|
} else {
|
|
230
229
|
this.panel.hide();
|
|
231
|
-
this.
|
|
232
|
-
this.sdk.eventBus.emit('
|
|
230
|
+
this.WebChatState.reset();
|
|
231
|
+
this.sdk.eventBus.emit('webChat:closed', { widget: this });
|
|
233
232
|
}
|
|
234
233
|
}
|
|
235
234
|
|
|
@@ -248,21 +247,21 @@ export class MessengerWidget extends BaseWidget {
|
|
|
248
247
|
|
|
249
248
|
async _handleStartConversation(messageContent, pendingAttachments) {
|
|
250
249
|
try {
|
|
251
|
-
if (!this.
|
|
252
|
-
this.
|
|
250
|
+
if (!this.WebChatState.isIdentified) {
|
|
251
|
+
this.WebChatState.pendingMessage = {
|
|
253
252
|
content: messageContent,
|
|
254
253
|
attachments: pendingAttachments,
|
|
255
254
|
};
|
|
256
|
-
this.
|
|
255
|
+
this.WebChatState.setView('prechat');
|
|
257
256
|
return null;
|
|
258
257
|
}
|
|
259
258
|
|
|
260
|
-
const openConversation = this.
|
|
259
|
+
const openConversation = this.WebChatState.conversations.find(
|
|
261
260
|
(c) => c.status === 'open'
|
|
262
261
|
);
|
|
263
262
|
|
|
264
263
|
if (openConversation) {
|
|
265
|
-
this.
|
|
264
|
+
this.WebChatState.setActiveConversation(openConversation.id);
|
|
266
265
|
await this._handleSendMessage(
|
|
267
266
|
openConversation.id,
|
|
268
267
|
{ content: messageContent },
|
|
@@ -277,7 +276,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
277
276
|
pendingAttachments
|
|
278
277
|
);
|
|
279
278
|
} catch (error) {
|
|
280
|
-
console.error('[
|
|
279
|
+
console.error('[WebChatWidget] Failed to start conversation:', error);
|
|
281
280
|
return null;
|
|
282
281
|
}
|
|
283
282
|
}
|
|
@@ -286,36 +285,36 @@ export class MessengerWidget extends BaseWidget {
|
|
|
286
285
|
try {
|
|
287
286
|
await this.fetchMessages(conversationId);
|
|
288
287
|
} catch (error) {
|
|
289
|
-
console.error('[
|
|
288
|
+
console.error('[WebChatWidget] Failed to fetch messages:', error);
|
|
290
289
|
}
|
|
291
290
|
}
|
|
292
291
|
|
|
293
292
|
_handleNewConversationClick() {
|
|
294
|
-
const openConversation = this.
|
|
293
|
+
const openConversation = this.WebChatState.conversations.find(
|
|
295
294
|
(c) => c.status === 'open'
|
|
296
295
|
);
|
|
297
296
|
|
|
298
297
|
if (openConversation) {
|
|
299
|
-
this.
|
|
300
|
-
this.
|
|
298
|
+
this.WebChatState.setActiveConversation(openConversation.id);
|
|
299
|
+
this.WebChatState.setView('chat');
|
|
301
300
|
this._handleSelectConversation(openConversation.id);
|
|
302
301
|
} else {
|
|
303
|
-
this.
|
|
304
|
-
this.
|
|
302
|
+
this.WebChatState.setActiveConversation(null);
|
|
303
|
+
this.WebChatState.setView('chat');
|
|
305
304
|
}
|
|
306
305
|
}
|
|
307
306
|
|
|
308
307
|
async _handleIdentifyContact(contactData) {
|
|
309
308
|
try {
|
|
310
309
|
// Route through sdk.identify() so the SDK-level identity state is updated
|
|
311
|
-
// and applyIdentity() handles the
|
|
310
|
+
// and applyIdentity() handles the web chat state + WebSocket as a side effect.
|
|
312
311
|
const result = await this.sdk.identify({
|
|
313
312
|
email: contactData.email,
|
|
314
313
|
name: contactData.name,
|
|
315
314
|
});
|
|
316
315
|
return result;
|
|
317
316
|
} catch (error) {
|
|
318
|
-
console.error('[
|
|
317
|
+
console.error('[WebChatWidget] Failed to identify contact:', error);
|
|
319
318
|
throw error;
|
|
320
319
|
}
|
|
321
320
|
}
|
|
@@ -327,7 +326,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
327
326
|
}
|
|
328
327
|
|
|
329
328
|
applyIdentity(metadata = {}) {
|
|
330
|
-
this.
|
|
329
|
+
this.WebChatState.setIdentified(true, metadata);
|
|
331
330
|
|
|
332
331
|
if (this.apiService?.sessionToken && !this.wsService?.isConnected) {
|
|
333
332
|
this._initWebSocket();
|
|
@@ -342,7 +341,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
342
341
|
}
|
|
343
342
|
throw new Error('Upload failed');
|
|
344
343
|
} catch (error) {
|
|
345
|
-
console.error('[
|
|
344
|
+
console.error('[WebChatWidget] Failed to upload file:', error);
|
|
346
345
|
throw error;
|
|
347
346
|
}
|
|
348
347
|
}
|
|
@@ -361,7 +360,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
361
360
|
});
|
|
362
361
|
} catch (err) {
|
|
363
362
|
console.error(
|
|
364
|
-
'[
|
|
363
|
+
'[WebChatWidget] Skipping failed attachment upload:',
|
|
365
364
|
att.file.name,
|
|
366
365
|
err
|
|
367
366
|
);
|
|
@@ -371,7 +370,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
371
370
|
}
|
|
372
371
|
|
|
373
372
|
async _handleSendMessage(conversationId, message, pendingAttachments) {
|
|
374
|
-
this.sdk.eventBus.emit('
|
|
373
|
+
this.sdk.eventBus.emit('webChat:messageSent', {
|
|
375
374
|
widget: this,
|
|
376
375
|
conversationId,
|
|
377
376
|
message,
|
|
@@ -387,7 +386,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
387
386
|
});
|
|
388
387
|
|
|
389
388
|
if (response.status && response.data) {
|
|
390
|
-
console.log('[
|
|
389
|
+
console.log('[WebChatWidget] Message sent:', response.data.id);
|
|
391
390
|
}
|
|
392
391
|
|
|
393
392
|
if (this.apiService?.mock) {
|
|
@@ -402,11 +401,11 @@ export class MessengerWidget extends BaseWidget {
|
|
|
402
401
|
avatarUrl: null,
|
|
403
402
|
},
|
|
404
403
|
};
|
|
405
|
-
this.
|
|
404
|
+
this.WebChatState.addMessage(conversationId, mockResponse);
|
|
406
405
|
}, 1500);
|
|
407
406
|
}
|
|
408
407
|
} catch (error) {
|
|
409
|
-
console.error('[
|
|
408
|
+
console.error('[WebChatWidget] Failed to send message:', error);
|
|
410
409
|
}
|
|
411
410
|
}
|
|
412
411
|
|
|
@@ -438,20 +437,20 @@ export class MessengerWidget extends BaseWidget {
|
|
|
438
437
|
},
|
|
439
438
|
};
|
|
440
439
|
|
|
441
|
-
this.
|
|
440
|
+
this.WebChatState.upsertMessage(conversation_id, localMessage, {
|
|
442
441
|
reconcileOwnOptimistic: true,
|
|
443
442
|
optimisticMatchWindowMs: 30000,
|
|
444
443
|
});
|
|
445
444
|
|
|
446
445
|
const isOwnMessage = message.sender_type === 'customer';
|
|
447
446
|
|
|
448
|
-
if (!isOwnMessage && this.
|
|
447
|
+
if (!isOwnMessage && this.WebChatState.isIdentified) {
|
|
449
448
|
this._notificationSound.play();
|
|
450
449
|
}
|
|
451
450
|
|
|
452
451
|
if (
|
|
453
|
-
!this.
|
|
454
|
-
this.
|
|
452
|
+
!this.WebChatState.isOpen ||
|
|
453
|
+
this.WebChatState.activeConversationId !== conversation_id
|
|
455
454
|
) {
|
|
456
455
|
this._updateUnreadCount();
|
|
457
456
|
}
|
|
@@ -459,7 +458,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
459
458
|
|
|
460
459
|
_handleTypingStarted(data) {
|
|
461
460
|
if (data.is_agent) {
|
|
462
|
-
this.
|
|
461
|
+
this.WebChatState._notify('typingStarted', {
|
|
463
462
|
conversationId: data.conversation_id,
|
|
464
463
|
userName: data.user_name,
|
|
465
464
|
});
|
|
@@ -467,7 +466,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
467
466
|
}
|
|
468
467
|
|
|
469
468
|
_handleTypingStopped(data) {
|
|
470
|
-
this.
|
|
469
|
+
this.WebChatState._notify('typingStopped', {
|
|
471
470
|
conversationId: data.conversation_id,
|
|
472
471
|
});
|
|
473
472
|
}
|
|
@@ -477,7 +476,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
477
476
|
data?.conversation_id || data?.id || data?.conversation?.id;
|
|
478
477
|
if (!conversationId) return;
|
|
479
478
|
|
|
480
|
-
this.
|
|
479
|
+
this.WebChatState.updateConversation(conversationId, {
|
|
481
480
|
status: 'closed',
|
|
482
481
|
});
|
|
483
482
|
}
|
|
@@ -486,13 +485,13 @@ export class MessengerWidget extends BaseWidget {
|
|
|
486
485
|
try {
|
|
487
486
|
const response = await this.apiService.getUnreadCount();
|
|
488
487
|
if (response.status && response.data) {
|
|
489
|
-
this.
|
|
490
|
-
this.
|
|
491
|
-
count: this.
|
|
488
|
+
this.WebChatState.unreadCount = response.data.unread_count || 0;
|
|
489
|
+
this.WebChatState._notify('unreadCountChange', {
|
|
490
|
+
count: this.WebChatState.unreadCount,
|
|
492
491
|
});
|
|
493
492
|
}
|
|
494
493
|
} catch (error) {
|
|
495
|
-
console.error('[
|
|
494
|
+
console.error('[WebChatWidget] Failed to get unread count:', error);
|
|
496
495
|
}
|
|
497
496
|
}
|
|
498
497
|
|
|
@@ -522,23 +521,23 @@ export class MessengerWidget extends BaseWidget {
|
|
|
522
521
|
);
|
|
523
522
|
this._wsUnsubscribers.push(
|
|
524
523
|
this.wsService.on('connected', () => {
|
|
525
|
-
console.log('[
|
|
526
|
-
if (this.
|
|
524
|
+
console.log('[WebChatWidget] WebSocket connected');
|
|
525
|
+
if (this.WebChatState.activeConversationId) {
|
|
527
526
|
this.wsService.send('conversation:subscribe', {
|
|
528
|
-
conversation_id: this.
|
|
527
|
+
conversation_id: this.WebChatState.activeConversationId,
|
|
529
528
|
});
|
|
530
529
|
}
|
|
531
530
|
})
|
|
532
531
|
);
|
|
533
532
|
this._wsUnsubscribers.push(
|
|
534
533
|
this.wsService.on('disconnected', () => {
|
|
535
|
-
console.log('[
|
|
536
|
-
this.
|
|
534
|
+
console.log('[WebChatWidget] WebSocket disconnected');
|
|
535
|
+
this.WebChatState._notify('connectionChange', { connected: false });
|
|
537
536
|
})
|
|
538
537
|
);
|
|
539
538
|
this._wsUnsubscribers.push(
|
|
540
539
|
this.wsService.on('connected', () => {
|
|
541
|
-
this.
|
|
540
|
+
this.WebChatState._notify('connectionChange', { connected: true });
|
|
542
541
|
})
|
|
543
542
|
);
|
|
544
543
|
|
|
@@ -546,78 +545,78 @@ export class MessengerWidget extends BaseWidget {
|
|
|
546
545
|
}
|
|
547
546
|
|
|
548
547
|
open() {
|
|
549
|
-
this.
|
|
548
|
+
this.WebChatState.setOpen(true);
|
|
550
549
|
}
|
|
551
550
|
|
|
552
551
|
close() {
|
|
553
|
-
this.
|
|
552
|
+
this.WebChatState.setOpen(false);
|
|
554
553
|
}
|
|
555
554
|
|
|
556
555
|
toggle() {
|
|
557
|
-
this.
|
|
556
|
+
this.WebChatState.setOpen(!this.WebChatState.isOpen);
|
|
558
557
|
}
|
|
559
558
|
|
|
560
559
|
navigateTo(view) {
|
|
561
|
-
this.
|
|
562
|
-
if (!this.
|
|
560
|
+
this.WebChatState.setView(view);
|
|
561
|
+
if (!this.WebChatState.isOpen) {
|
|
563
562
|
this.open();
|
|
564
563
|
}
|
|
565
564
|
}
|
|
566
565
|
|
|
567
566
|
setConversations(conversations) {
|
|
568
|
-
this.
|
|
567
|
+
this.WebChatState.setConversations(conversations);
|
|
569
568
|
}
|
|
570
569
|
|
|
571
570
|
addMessage(conversationId, message) {
|
|
572
|
-
this.
|
|
571
|
+
this.WebChatState.addMessage(conversationId, message);
|
|
573
572
|
}
|
|
574
573
|
|
|
575
574
|
setHelpArticles(articles) {
|
|
576
|
-
this.
|
|
575
|
+
this.WebChatState.setHelpArticles(articles);
|
|
577
576
|
}
|
|
578
577
|
|
|
579
578
|
setHomeChangelogItems(items) {
|
|
580
|
-
this.
|
|
579
|
+
this.WebChatState.setHomeChangelogItems(items);
|
|
581
580
|
}
|
|
582
581
|
|
|
583
582
|
setChangelogItems(items) {
|
|
584
|
-
this.
|
|
583
|
+
this.WebChatState.setChangelogItems(items);
|
|
585
584
|
}
|
|
586
585
|
|
|
587
586
|
setUnreadCount(count) {
|
|
588
|
-
this.
|
|
589
|
-
this.
|
|
587
|
+
this.WebChatState.unreadCount = count;
|
|
588
|
+
this.WebChatState._notify('unreadCountChange', { count });
|
|
590
589
|
}
|
|
591
590
|
|
|
592
591
|
getState() {
|
|
593
592
|
return {
|
|
594
|
-
isOpen: this.
|
|
595
|
-
currentView: this.
|
|
596
|
-
unreadCount: this.
|
|
597
|
-
conversations: this.
|
|
593
|
+
isOpen: this.WebChatState.isOpen,
|
|
594
|
+
currentView: this.WebChatState.currentView,
|
|
595
|
+
unreadCount: this.WebChatState.unreadCount,
|
|
596
|
+
conversations: this.WebChatState.conversations,
|
|
598
597
|
};
|
|
599
598
|
}
|
|
600
599
|
|
|
601
600
|
_applyPreviewData() {
|
|
602
|
-
const data = this.
|
|
601
|
+
const data = this.webChatOptions.previewData;
|
|
603
602
|
if (!data || typeof data !== 'object') {
|
|
604
603
|
return;
|
|
605
604
|
}
|
|
606
605
|
|
|
607
606
|
if (Array.isArray(data.conversations)) {
|
|
608
|
-
this.
|
|
607
|
+
this.WebChatState.setConversations(data.conversations);
|
|
609
608
|
}
|
|
610
609
|
|
|
611
610
|
if (Array.isArray(data.helpArticles)) {
|
|
612
|
-
this.
|
|
611
|
+
this.WebChatState.setHelpArticles(data.helpArticles);
|
|
613
612
|
}
|
|
614
613
|
|
|
615
614
|
if (Array.isArray(data.homeChangelogItems)) {
|
|
616
|
-
this.
|
|
615
|
+
this.WebChatState.setHomeChangelogItems(data.homeChangelogItems);
|
|
617
616
|
}
|
|
618
617
|
|
|
619
618
|
if (Array.isArray(data.changelogItems)) {
|
|
620
|
-
this.
|
|
619
|
+
this.WebChatState.setChangelogItems(data.changelogItems);
|
|
621
620
|
}
|
|
622
621
|
|
|
623
622
|
if (typeof data.unreadCount === 'number') {
|
|
@@ -626,49 +625,49 @@ export class MessengerWidget extends BaseWidget {
|
|
|
626
625
|
|
|
627
626
|
if (data.availability && typeof data.availability === 'object') {
|
|
628
627
|
const availability = data.availability;
|
|
629
|
-
this.
|
|
628
|
+
this.WebChatState.agentsOnline = Boolean(
|
|
630
629
|
availability.agentsOnline ??
|
|
631
630
|
availability.agents_online ??
|
|
632
631
|
availability.is_online
|
|
633
632
|
);
|
|
634
|
-
this.
|
|
633
|
+
this.WebChatState.onlineCount =
|
|
635
634
|
availability.onlineCount ?? availability.online_count ?? 0;
|
|
636
|
-
this.
|
|
635
|
+
this.WebChatState.responseTime =
|
|
637
636
|
availability.responseTime ??
|
|
638
637
|
availability.response_time ??
|
|
639
|
-
this.
|
|
640
|
-
this.
|
|
638
|
+
this.WebChatState.responseTime;
|
|
639
|
+
this.WebChatState._notify('availabilityUpdate', availability);
|
|
641
640
|
}
|
|
642
641
|
|
|
643
642
|
if (typeof data.currentView === 'string') {
|
|
644
|
-
this.
|
|
643
|
+
this.WebChatState.setView(data.currentView);
|
|
645
644
|
}
|
|
646
645
|
}
|
|
647
646
|
|
|
648
647
|
async loadInitialData() {
|
|
649
648
|
try {
|
|
650
649
|
const conversations = await this._fetchConversations();
|
|
651
|
-
this.
|
|
650
|
+
this.WebChatState.setConversations(conversations);
|
|
652
651
|
} catch (error) {
|
|
653
|
-
console.error('[
|
|
652
|
+
console.error('[WebChatWidget] Failed to load conversations:', error);
|
|
654
653
|
}
|
|
655
654
|
|
|
656
|
-
if (this.
|
|
655
|
+
if (this.webChatOptions.enableHelp) {
|
|
657
656
|
try {
|
|
658
657
|
const articles = await this._fetchHelpArticles();
|
|
659
|
-
this.
|
|
658
|
+
this.WebChatState.setHelpArticles(articles);
|
|
660
659
|
} catch (error) {
|
|
661
|
-
console.error('[
|
|
660
|
+
console.error('[WebChatWidget] Failed to load help articles:', error);
|
|
662
661
|
}
|
|
663
662
|
}
|
|
664
663
|
|
|
665
|
-
if (this.
|
|
664
|
+
if (this.webChatOptions.enableChangelog) {
|
|
666
665
|
try {
|
|
667
666
|
const { homeItems, changelogItems } = await this._fetchChangelog();
|
|
668
|
-
this.
|
|
669
|
-
this.
|
|
667
|
+
this.WebChatState.setHomeChangelogItems(homeItems);
|
|
668
|
+
this.WebChatState.setChangelogItems(changelogItems);
|
|
670
669
|
} catch (error) {
|
|
671
|
-
console.error('[
|
|
670
|
+
console.error('[WebChatWidget] Failed to load changelog:', error);
|
|
672
671
|
}
|
|
673
672
|
}
|
|
674
673
|
}
|
|
@@ -698,7 +697,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
698
697
|
}
|
|
699
698
|
return [];
|
|
700
699
|
} catch (error) {
|
|
701
|
-
console.error('[
|
|
700
|
+
console.error('[WebChatWidget] Failed to fetch conversations:', error);
|
|
702
701
|
return [];
|
|
703
702
|
}
|
|
704
703
|
}
|
|
@@ -708,10 +707,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
708
707
|
const response = await this.apiService.getHelpCollections();
|
|
709
708
|
if (response.success && response.data) {
|
|
710
709
|
const collections = response.data.collections || response.data;
|
|
711
|
-
const helpBase = (this.
|
|
712
|
-
/\/$/,
|
|
713
|
-
''
|
|
714
|
-
);
|
|
710
|
+
const helpBase = (this.webChatOptions.helpUrl || '').replace(/\/$/, '');
|
|
715
711
|
|
|
716
712
|
const sorted = [...collections].sort(
|
|
717
713
|
(a, b) => (a.order ?? 0) - (b.order ?? 0)
|
|
@@ -732,7 +728,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
732
728
|
}
|
|
733
729
|
return [];
|
|
734
730
|
} catch (error) {
|
|
735
|
-
console.error('[
|
|
731
|
+
console.error('[WebChatWidget] Failed to fetch help articles:', error);
|
|
736
732
|
return [];
|
|
737
733
|
}
|
|
738
734
|
}
|
|
@@ -769,16 +765,16 @@ export class MessengerWidget extends BaseWidget {
|
|
|
769
765
|
},
|
|
770
766
|
};
|
|
771
767
|
});
|
|
772
|
-
this.
|
|
768
|
+
this.WebChatState.setMessages(conversationId, messages);
|
|
773
769
|
|
|
774
770
|
await this.apiService.markConversationAsRead(conversationId);
|
|
775
|
-
this.
|
|
771
|
+
this.WebChatState.markAsRead(conversationId);
|
|
776
772
|
|
|
777
773
|
return messages;
|
|
778
774
|
}
|
|
779
775
|
return [];
|
|
780
776
|
} catch (error) {
|
|
781
|
-
console.error('[
|
|
777
|
+
console.error('[WebChatWidget] Failed to fetch messages:', error);
|
|
782
778
|
return [];
|
|
783
779
|
}
|
|
784
780
|
}
|
|
@@ -806,7 +802,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
806
802
|
status: 'open',
|
|
807
803
|
};
|
|
808
804
|
|
|
809
|
-
this.
|
|
805
|
+
this.WebChatState.addConversation(newConversation);
|
|
810
806
|
|
|
811
807
|
const initialMessages = [
|
|
812
808
|
{
|
|
@@ -819,23 +815,23 @@ export class MessengerWidget extends BaseWidget {
|
|
|
819
815
|
|
|
820
816
|
initialMessages.push({
|
|
821
817
|
id: 'system_rt_' + Date.now(),
|
|
822
|
-
content: this.
|
|
818
|
+
content: this.WebChatState.agentsOnline
|
|
823
819
|
? 'One of our customer support agents will be with you shortly.'
|
|
824
|
-
: this.
|
|
820
|
+
: this.WebChatState.responseTime,
|
|
825
821
|
isSystem: true,
|
|
826
822
|
timestamp: new Date().toISOString(),
|
|
827
823
|
});
|
|
828
824
|
|
|
829
|
-
this.
|
|
825
|
+
this.WebChatState.setMessages(conv.id, initialMessages);
|
|
830
826
|
|
|
831
|
-
this.
|
|
832
|
-
this.
|
|
827
|
+
this.WebChatState.setActiveConversation(conv.id);
|
|
828
|
+
this.WebChatState.setView('chat');
|
|
833
829
|
|
|
834
830
|
return conv;
|
|
835
831
|
}
|
|
836
832
|
return null;
|
|
837
833
|
} catch (error) {
|
|
838
|
-
console.error('[
|
|
834
|
+
console.error('[WebChatWidget] Failed to start conversation:', error);
|
|
839
835
|
return null;
|
|
840
836
|
}
|
|
841
837
|
}
|
|
@@ -850,28 +846,28 @@ export class MessengerWidget extends BaseWidget {
|
|
|
850
846
|
|
|
851
847
|
async _fetchAndApplySettings() {
|
|
852
848
|
try {
|
|
853
|
-
const response = await this.apiService.
|
|
849
|
+
const response = await this.apiService.getWebChatSettings();
|
|
854
850
|
if (!response?.status || !response?.data) return;
|
|
855
851
|
|
|
856
852
|
const s = response.data;
|
|
857
853
|
|
|
858
854
|
// Only apply values that were NOT explicitly passed in options
|
|
859
855
|
if (s.team_name && !this._hasExplicitOption('teamName')) {
|
|
860
|
-
this.
|
|
861
|
-
this.
|
|
856
|
+
this.webChatOptions.teamName = s.team_name;
|
|
857
|
+
this.WebChatState.teamName = s.team_name;
|
|
862
858
|
}
|
|
863
859
|
if (s.logo_url && !this._hasExplicitOption('logoUrl')) {
|
|
864
|
-
this.
|
|
860
|
+
this.webChatOptions.logoUrl = s.logo_url;
|
|
865
861
|
}
|
|
866
862
|
if (s.greeting_message && !this._hasExplicitOption('greetingMessage')) {
|
|
867
|
-
this.
|
|
863
|
+
this.WebChatState.greetingMessage = s.greeting_message;
|
|
868
864
|
}
|
|
869
865
|
if (s.response_time && !this._hasExplicitOption('responseTime')) {
|
|
870
|
-
this.
|
|
866
|
+
this.WebChatState.responseTime = s.response_time;
|
|
871
867
|
}
|
|
872
868
|
|
|
873
869
|
// Notify views to re-render with new values
|
|
874
|
-
this.
|
|
870
|
+
this.WebChatState._notify('availabilityUpdate', {});
|
|
875
871
|
} catch (e) {
|
|
876
872
|
// non-fatal
|
|
877
873
|
}
|
|
@@ -888,23 +884,23 @@ export class MessengerWidget extends BaseWidget {
|
|
|
888
884
|
try {
|
|
889
885
|
const response = await this.apiService.checkAgentsOnline();
|
|
890
886
|
if (response.status && response.data) {
|
|
891
|
-
this.
|
|
887
|
+
this.WebChatState.agentsOnline =
|
|
892
888
|
response.data.agents_online ?? response.data.is_online ?? false;
|
|
893
|
-
this.
|
|
894
|
-
this.
|
|
889
|
+
this.WebChatState.onlineCount = response.data.online_count || 0;
|
|
890
|
+
this.WebChatState.responseTime = response.data.response_time || '';
|
|
895
891
|
|
|
896
892
|
if (response.data.available_agents) {
|
|
897
|
-
this.
|
|
893
|
+
this.WebChatState.setTeamAvatarsFromAgents(
|
|
898
894
|
response.data.available_agents
|
|
899
895
|
);
|
|
900
896
|
}
|
|
901
897
|
|
|
902
|
-
this.
|
|
898
|
+
this.WebChatState._notify('availabilityUpdate', response.data);
|
|
903
899
|
return response.data;
|
|
904
900
|
}
|
|
905
901
|
return { agents_online: false, online_count: 0 };
|
|
906
902
|
} catch (error) {
|
|
907
|
-
console.error('[
|
|
903
|
+
console.error('[WebChatWidget] Failed to check availability:', error);
|
|
908
904
|
return { agents_online: false, online_count: 0 };
|
|
909
905
|
}
|
|
910
906
|
}
|
|
@@ -995,9 +991,10 @@ export class MessengerWidget extends BaseWidget {
|
|
|
995
991
|
|
|
996
992
|
if (response.success && response.data) {
|
|
997
993
|
const changelogs = Array.isArray(response.data) ? response.data : [];
|
|
998
|
-
const changelogBase = (
|
|
999
|
-
|
|
1000
|
-
|
|
994
|
+
const changelogBase = (this.webChatOptions.changelogUrl || '').replace(
|
|
995
|
+
/\/$/,
|
|
996
|
+
''
|
|
997
|
+
);
|
|
1001
998
|
|
|
1002
999
|
const mappedItems = changelogs.map((item) => ({
|
|
1003
1000
|
id: item.id,
|
|
@@ -1020,7 +1017,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
1020
1017
|
|
|
1021
1018
|
return { homeItems: [], changelogItems: [] };
|
|
1022
1019
|
} catch (error) {
|
|
1023
|
-
console.error('[
|
|
1020
|
+
console.error('[WebChatWidget] Failed to fetch changelog:', error);
|
|
1024
1021
|
return { homeItems: [], changelogItems: [] };
|
|
1025
1022
|
}
|
|
1026
1023
|
}
|
|
@@ -1028,7 +1025,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
1028
1025
|
async onMount() {
|
|
1029
1026
|
this._applyPreviewData();
|
|
1030
1027
|
|
|
1031
|
-
if (this.
|
|
1028
|
+
if (this.webChatOptions.autoLoadData) {
|
|
1032
1029
|
// Fetch workspace settings and apply only if not explicitly configured
|
|
1033
1030
|
this._fetchAndApplySettings();
|
|
1034
1031
|
|
|
@@ -1046,10 +1043,10 @@ export class MessengerWidget extends BaseWidget {
|
|
|
1046
1043
|
}
|
|
1047
1044
|
|
|
1048
1045
|
if (
|
|
1049
|
-
this.
|
|
1050
|
-
this.
|
|
1046
|
+
this.webChatOptions.initialView &&
|
|
1047
|
+
this.webChatOptions.initialView !== this.WebChatState.currentView
|
|
1051
1048
|
) {
|
|
1052
|
-
this.
|
|
1049
|
+
this.WebChatState.setView(this.webChatOptions.initialView);
|
|
1053
1050
|
}
|
|
1054
1051
|
}
|
|
1055
1052
|
|
|
@@ -1071,7 +1068,7 @@ export class MessengerWidget extends BaseWidget {
|
|
|
1071
1068
|
}
|
|
1072
1069
|
|
|
1073
1070
|
destroy() {
|
|
1074
|
-
|
|
1071
|
+
removewebChatCustomStyles();
|
|
1075
1072
|
|
|
1076
1073
|
if (this.launcher) {
|
|
1077
1074
|
this.launcher.destroy();
|