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