@theonexai/chartsconnect-chat-widget 1.0.33 → 1.0.35
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/{ChatWidget-lohWj44a.js → ChatWidget-Bs0XV_7i.js} +292 -101
- package/dist/ChatWidget-Bs0XV_7i.js.map +1 -0
- package/dist/ChatWidget-PcqRrOmi.cjs +2 -0
- package/dist/ChatWidget-PcqRrOmi.cjs.map +1 -0
- package/dist/adapters/vue/useChatMode.d.ts +3 -4
- package/dist/adapters/vue/useChatMode.d.ts.map +1 -1
- package/dist/components/ChatWidget.d.ts +1 -3
- package/dist/components/ChatWidget.d.ts.map +1 -1
- package/dist/core/stateManager.d.ts +19 -3
- package/dist/core/stateManager.d.ts.map +1 -1
- package/dist/core/types.d.ts +0 -17
- package/dist/core/types.d.ts.map +1 -1
- package/dist/entry/vite.d.ts +1 -1
- package/dist/hooks/useChatMode.d.ts.map +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.esm.js +1196 -5
- package/dist/index.esm.js.map +1 -1
- package/dist/nuxt.cjs.js +1 -1
- package/dist/nuxt.esm.js +2 -2
- package/dist/sanitize-C8MB41vY.cjs +4 -0
- package/dist/sanitize-C8MB41vY.cjs.map +1 -0
- package/dist/{types-BlZ1psq3.js → sanitize-Cm1kskSD.js} +25 -31
- package/dist/sanitize-Cm1kskSD.js.map +1 -0
- package/dist/services/chatService.d.ts +1 -0
- package/dist/services/chatService.d.ts.map +1 -1
- package/dist/services/dialogflowBackendService.d.ts +0 -2
- package/dist/services/dialogflowBackendService.d.ts.map +1 -1
- package/dist/services/dialogflowClient.d.ts +36 -0
- package/dist/services/dialogflowClient.d.ts.map +1 -0
- package/dist/utils/sanitize.d.ts.map +1 -1
- package/dist/vue.cjs.js +1 -1
- package/dist/vue.esm.js +2 -2
- package/package.json +4 -9
- package/dist/ChatWidget-C2uBKk72.cjs +0 -2
- package/dist/ChatWidget-C2uBKk72.cjs.map +0 -1
- package/dist/ChatWidget-a08SnbWj.js +0 -1284
- package/dist/ChatWidget-a08SnbWj.js.map +0 -1
- package/dist/ChatWidget-lohWj44a.js.map +0 -1
- package/dist/ChatWidget-tA9Ibu8c.cjs +0 -2
- package/dist/ChatWidget-tA9Ibu8c.cjs.map +0 -1
- package/dist/next.cjs.js +0 -2
- package/dist/next.cjs.js.map +0 -1
- package/dist/next.esm.js +0 -9
- package/dist/next.esm.js.map +0 -1
- package/dist/react.cjs.js +0 -2
- package/dist/react.cjs.js.map +0 -1
- package/dist/react.esm.js +0 -5
- package/dist/react.esm.js.map +0 -1
- package/dist/types-BlZ1psq3.js.map +0 -1
- package/dist/types-CSeUPcTU.cjs +0 -4
- package/dist/types-CSeUPcTU.cjs.map +0 -1
- package/dist/vite.cjs.js +0 -2
- package/dist/vite.cjs.js.map +0 -1
- package/dist/vite.esm.js +0 -5
- package/dist/vite.esm.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ref, computed, onUnmounted, watch, defineComponent, nextTick, onMounted, openBlock, createElementBlock, mergeProps, unref, createElementVNode, toDisplayString, withModifiers, createCommentVNode, createTextVNode, Fragment, renderList, normalizeClass } from "vue";
|
|
2
|
-
import {
|
|
2
|
+
import { c as createChatService, a as createDialogflowSession, C as ChatResolvedError, s as sendDialogflowMessage, b as safeLinkifyText } from "./sanitize-Cm1kskSD.js";
|
|
3
3
|
class WidgetStateManager {
|
|
4
4
|
constructor(config) {
|
|
5
5
|
this.listeners = /* @__PURE__ */ new Set();
|
|
@@ -7,6 +7,11 @@ class WidgetStateManager {
|
|
|
7
7
|
this.chatId = null;
|
|
8
8
|
this.supportSessionId = null;
|
|
9
9
|
this.chatService = null;
|
|
10
|
+
this.collectingUserInfo = false;
|
|
11
|
+
this.userInfoStep = null;
|
|
12
|
+
this.collectedUserName = "";
|
|
13
|
+
this.collectedUserEmail = "";
|
|
14
|
+
this.collectedUserMobile = "";
|
|
10
15
|
this.wsConnected = false;
|
|
11
16
|
this.agentTyping = false;
|
|
12
17
|
this.currentAgent = { name: "Agent" };
|
|
@@ -16,7 +21,6 @@ class WidgetStateManager {
|
|
|
16
21
|
this.historyLoaded = null;
|
|
17
22
|
this.typingTimeout = null;
|
|
18
23
|
this.agentTypingTimeout = null;
|
|
19
|
-
this.welcomePopupTimeout = null;
|
|
20
24
|
this.config = config;
|
|
21
25
|
this.state = {
|
|
22
26
|
isOpen: false,
|
|
@@ -28,15 +32,13 @@ class WidgetStateManager {
|
|
|
28
32
|
sessionId: null,
|
|
29
33
|
chatMode: "ai"
|
|
30
34
|
};
|
|
31
|
-
const baseUrl = this.config.backendBaseUrl || "http://localhost:8012";
|
|
32
|
-
const wsUrl = this.config.backendWsUrl || baseUrl.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
|
|
33
35
|
this.chatService = createChatService({
|
|
34
|
-
baseUrl,
|
|
35
|
-
wsUrl,
|
|
36
|
+
baseUrl: this.config.backendBaseUrl || "http://localhost:8012",
|
|
37
|
+
wsUrl: this.config.backendWsUrl || "ws://localhost:8012",
|
|
36
38
|
debug: this.config.debug || false
|
|
37
39
|
});
|
|
38
40
|
if (typeof window !== "undefined" && window.localStorage) {
|
|
39
|
-
const savedMode = localStorage.getItem("
|
|
41
|
+
const savedMode = localStorage.getItem("chartsconnectect_chat_mode");
|
|
40
42
|
this.chatMode = savedMode === "HUMAN" ? "human" : "ai";
|
|
41
43
|
this.state.chatMode = this.chatMode;
|
|
42
44
|
this.chatId = localStorage.getItem("chartsconnect_chat_id");
|
|
@@ -96,7 +98,7 @@ class WidgetStateManager {
|
|
|
96
98
|
});
|
|
97
99
|
if (session.message) {
|
|
98
100
|
const welcomeMessage = {
|
|
99
|
-
id:
|
|
101
|
+
id: `welcome-${Date.now()}`,
|
|
100
102
|
text: session.message,
|
|
101
103
|
sender: "bot",
|
|
102
104
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -113,7 +115,7 @@ class WidgetStateManager {
|
|
|
113
115
|
error: error.message || "Failed to initialize chat"
|
|
114
116
|
});
|
|
115
117
|
const fallbackMessage = {
|
|
116
|
-
id:
|
|
118
|
+
id: `fallback-${Date.now()}`,
|
|
117
119
|
text: this.config.fallbackWelcomeMessage || "Hello! How can I help you today?",
|
|
118
120
|
sender: "bot",
|
|
119
121
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -139,11 +141,11 @@ class WidgetStateManager {
|
|
|
139
141
|
/**
|
|
140
142
|
* Toggle chat
|
|
141
143
|
*/
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
toggleChat() {
|
|
145
|
+
const willBeOpen = !this.state.isOpen;
|
|
146
|
+
this.setState({ isOpen: willBeOpen });
|
|
147
|
+
if (willBeOpen && this.state.showWelcomePopup) {
|
|
148
|
+
this.setState({ showWelcomePopup: false });
|
|
147
149
|
}
|
|
148
150
|
}
|
|
149
151
|
/**
|
|
@@ -165,9 +167,25 @@ class WidgetStateManager {
|
|
|
165
167
|
if (!text.trim() || this.state.isLoading) {
|
|
166
168
|
return;
|
|
167
169
|
}
|
|
170
|
+
if (this.collectingUserInfo) {
|
|
171
|
+
const userMessage = {
|
|
172
|
+
id: `user-${Date.now()}`,
|
|
173
|
+
text: text.trim(),
|
|
174
|
+
sender: "user",
|
|
175
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
176
|
+
};
|
|
177
|
+
this.setState({
|
|
178
|
+
messages: [...this.state.messages, userMessage],
|
|
179
|
+
inputValue: "",
|
|
180
|
+
isLoading: false,
|
|
181
|
+
error: null
|
|
182
|
+
});
|
|
183
|
+
await this.handleUserInfoCollection(text);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
168
186
|
if (!skipUserMessage) {
|
|
169
187
|
const userMessage = {
|
|
170
|
-
id:
|
|
188
|
+
id: `user-${Date.now()}`,
|
|
171
189
|
text: text.trim(),
|
|
172
190
|
sender: "user",
|
|
173
191
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -198,7 +216,7 @@ class WidgetStateManager {
|
|
|
198
216
|
return;
|
|
199
217
|
}
|
|
200
218
|
const errorMessage = {
|
|
201
|
-
id:
|
|
219
|
+
id: `error-${Date.now()}`,
|
|
202
220
|
text: this.config.debug ? `Error: ${error.message || "Failed to send message"}` : error.message?.includes("CORS") || error.message?.includes("Failed to fetch") ? "Unable to connect to Dialogflow. Please check your configuration and network." : "Sorry, I'm having trouble processing your message. Please try again.",
|
|
203
221
|
sender: "bot",
|
|
204
222
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -248,73 +266,31 @@ class WidgetStateManager {
|
|
|
248
266
|
});
|
|
249
267
|
}
|
|
250
268
|
if (response.handoff === true) {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
text: response.response,
|
|
255
|
-
sender: "bot",
|
|
256
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
257
|
-
richContent: response.richContent
|
|
258
|
-
};
|
|
259
|
-
this.setState({
|
|
260
|
-
messages: [...this.state.messages, botMessage],
|
|
261
|
-
isLoading: false
|
|
262
|
-
});
|
|
263
|
-
} else {
|
|
264
|
-
this.setState({ isLoading: false });
|
|
265
|
-
}
|
|
266
|
-
if (response.chat_id && response.support_session_id) {
|
|
267
|
-
this.chatId = response.chat_id;
|
|
268
|
-
this.supportSessionId = response.support_session_id;
|
|
269
|
-
if (typeof window !== "undefined" && window.localStorage) {
|
|
270
|
-
localStorage.setItem("chartsconnect_chat_id", this.chatId);
|
|
271
|
-
localStorage.setItem("chartsconnect_session_id", this.supportSessionId);
|
|
272
|
-
}
|
|
273
|
-
this.switchToHumanMode();
|
|
274
|
-
this.chatResolved = false;
|
|
275
|
-
this.agentAccepted = false;
|
|
276
|
-
const connectingMessage = {
|
|
277
|
-
id: generateMessageId("connecting"),
|
|
278
|
-
text: "Connecting you to a human agent...",
|
|
279
|
-
sender: "bot",
|
|
280
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
281
|
-
};
|
|
282
|
-
this.setState({
|
|
283
|
-
messages: [...this.state.messages, connectingMessage]
|
|
284
|
-
});
|
|
285
|
-
if (this.chatService) {
|
|
286
|
-
this.chatService.connectWebSocket(
|
|
287
|
-
this.chatId,
|
|
288
|
-
this.supportSessionId,
|
|
289
|
-
(message) => {
|
|
290
|
-
this.handleWebSocketMessage(message);
|
|
291
|
-
},
|
|
292
|
-
(connected) => {
|
|
293
|
-
this.wsConnected = connected;
|
|
294
|
-
}
|
|
295
|
-
);
|
|
296
|
-
}
|
|
297
|
-
this.isConnectingToAgent = false;
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
return;
|
|
301
|
-
}
|
|
302
|
-
const responseText = response.response || "";
|
|
303
|
-
if (responseText) {
|
|
304
|
-
const botMessage = {
|
|
305
|
-
id: generateMessageId("bot"),
|
|
306
|
-
text: responseText,
|
|
269
|
+
const botMessage2 = {
|
|
270
|
+
id: `bot-${Date.now()}`,
|
|
271
|
+
text: response.response || this.config.fallbackWelcomeMessage || "No response",
|
|
307
272
|
sender: "bot",
|
|
308
273
|
timestamp: /* @__PURE__ */ new Date(),
|
|
309
274
|
richContent: response.richContent
|
|
310
275
|
};
|
|
311
276
|
this.setState({
|
|
312
|
-
messages: [...this.state.messages,
|
|
277
|
+
messages: [...this.state.messages, botMessage2],
|
|
313
278
|
isLoading: false
|
|
314
279
|
});
|
|
315
|
-
|
|
316
|
-
|
|
280
|
+
this.startUserInfoCollection();
|
|
281
|
+
return;
|
|
317
282
|
}
|
|
283
|
+
const botMessage = {
|
|
284
|
+
id: `bot-${Date.now()}`,
|
|
285
|
+
text: response.response || this.config.fallbackWelcomeMessage || "No response",
|
|
286
|
+
sender: "bot",
|
|
287
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
288
|
+
richContent: response.richContent
|
|
289
|
+
};
|
|
290
|
+
this.setState({
|
|
291
|
+
messages: [...this.state.messages, botMessage],
|
|
292
|
+
isLoading: false
|
|
293
|
+
});
|
|
318
294
|
}
|
|
319
295
|
/**
|
|
320
296
|
* Send message to human support
|
|
@@ -322,7 +298,7 @@ class WidgetStateManager {
|
|
|
322
298
|
async sendHumanMessage(text) {
|
|
323
299
|
if (!this.chatId || !this.supportSessionId) {
|
|
324
300
|
const errorMessage = {
|
|
325
|
-
id:
|
|
301
|
+
id: `error-${Date.now()}`,
|
|
326
302
|
text: "Chat session not initialized. Please try again.",
|
|
327
303
|
sender: "bot",
|
|
328
304
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -422,14 +398,231 @@ class WidgetStateManager {
|
|
|
422
398
|
initializeWelcomePopup() {
|
|
423
399
|
if (this.config.showWelcomePopup !== false) {
|
|
424
400
|
const delay = this.config.welcomePopupDelay || 1500;
|
|
425
|
-
|
|
426
|
-
this.welcomePopupTimeout = null;
|
|
401
|
+
setTimeout(() => {
|
|
427
402
|
if (!this.state.isOpen) {
|
|
428
403
|
this.setState({ showWelcomePopup: true });
|
|
429
404
|
}
|
|
430
405
|
}, delay);
|
|
431
406
|
}
|
|
432
407
|
}
|
|
408
|
+
/**
|
|
409
|
+
* Start user info collection for handoff
|
|
410
|
+
*/
|
|
411
|
+
startUserInfoCollection() {
|
|
412
|
+
this.collectingUserInfo = true;
|
|
413
|
+
this.userInfoStep = "name";
|
|
414
|
+
this.collectedUserName = "";
|
|
415
|
+
this.collectedUserEmail = "";
|
|
416
|
+
this.collectedUserMobile = "";
|
|
417
|
+
const namePrompt = {
|
|
418
|
+
id: `prompt-${Date.now()}`,
|
|
419
|
+
text: "To connect you with a human agent, I'll need some information. Please provide your name:",
|
|
420
|
+
sender: "bot",
|
|
421
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
422
|
+
};
|
|
423
|
+
this.setState({
|
|
424
|
+
messages: [...this.state.messages, namePrompt]
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Handle user info collection
|
|
429
|
+
*/
|
|
430
|
+
async handleUserInfoCollection(text) {
|
|
431
|
+
if (this.userInfoStep === "name") {
|
|
432
|
+
const name = text.trim();
|
|
433
|
+
this.collectedUserName = name;
|
|
434
|
+
this.userInfoStep = "email";
|
|
435
|
+
const emailPrompt = {
|
|
436
|
+
id: `prompt-${Date.now()}`,
|
|
437
|
+
text: "Thank you! Now please provide your email address:",
|
|
438
|
+
sender: "bot",
|
|
439
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
440
|
+
};
|
|
441
|
+
this.setState({
|
|
442
|
+
messages: [...this.state.messages, emailPrompt],
|
|
443
|
+
inputValue: ""
|
|
444
|
+
});
|
|
445
|
+
return;
|
|
446
|
+
} else if (this.userInfoStep === "email") {
|
|
447
|
+
const email = text.trim();
|
|
448
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
449
|
+
if (!emailRegex.test(email)) {
|
|
450
|
+
const invalidEmailMessage = {
|
|
451
|
+
id: `prompt-${Date.now()}`,
|
|
452
|
+
text: "Please provide a valid email address:",
|
|
453
|
+
sender: "bot",
|
|
454
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
455
|
+
};
|
|
456
|
+
this.setState({
|
|
457
|
+
messages: [...this.state.messages, invalidEmailMessage],
|
|
458
|
+
inputValue: ""
|
|
459
|
+
});
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
this.collectedUserEmail = email;
|
|
463
|
+
this.userInfoStep = "mobile";
|
|
464
|
+
const mobilePrompt = {
|
|
465
|
+
id: `prompt-${Date.now()}`,
|
|
466
|
+
text: "Thank you! Now please provide your mobile number:",
|
|
467
|
+
sender: "bot",
|
|
468
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
469
|
+
};
|
|
470
|
+
this.setState({
|
|
471
|
+
messages: [...this.state.messages, mobilePrompt],
|
|
472
|
+
inputValue: ""
|
|
473
|
+
});
|
|
474
|
+
return;
|
|
475
|
+
} else if (this.userInfoStep === "mobile") {
|
|
476
|
+
const mobile = text.trim();
|
|
477
|
+
const mobileRegex = /^[\+]?[(]?[0-9]{1,4}[)]?[-\s\.]?[(]?[0-9]{1,4}[)]?[-\s\.]?[0-9]{1,9}$/;
|
|
478
|
+
if (!mobileRegex.test(mobile) || mobile.length < 10) {
|
|
479
|
+
const invalidMobileMessage = {
|
|
480
|
+
id: `prompt-${Date.now()}`,
|
|
481
|
+
text: "Please provide a valid mobile number (e.g., +1234567890):",
|
|
482
|
+
sender: "bot",
|
|
483
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
484
|
+
};
|
|
485
|
+
this.setState({
|
|
486
|
+
messages: [...this.state.messages, invalidMobileMessage],
|
|
487
|
+
inputValue: ""
|
|
488
|
+
});
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
this.collectedUserMobile = mobile;
|
|
492
|
+
this.collectingUserInfo = false;
|
|
493
|
+
this.userInfoStep = null;
|
|
494
|
+
await this.handleHandoff(this.collectedUserName, this.collectedUserEmail, mobile);
|
|
495
|
+
this.setState({ inputValue: "" });
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Handle handoff from Dialogflow to human support
|
|
500
|
+
*/
|
|
501
|
+
async handleHandoff(customerName, customerEmail, customerMobile) {
|
|
502
|
+
if (!this.chatService) {
|
|
503
|
+
throw new Error("Chat service not initialized");
|
|
504
|
+
}
|
|
505
|
+
try {
|
|
506
|
+
this.isConnectingToAgent = true;
|
|
507
|
+
const dialogflowSessionId = this.state.sessionId;
|
|
508
|
+
const session = await this.chatService.ensureChatInitialized(
|
|
509
|
+
this.chatId,
|
|
510
|
+
this.supportSessionId,
|
|
511
|
+
dialogflowSessionId || null,
|
|
512
|
+
customerName || null,
|
|
513
|
+
customerEmail || null,
|
|
514
|
+
customerMobile || null
|
|
515
|
+
);
|
|
516
|
+
if (!session || !session.chat_id) {
|
|
517
|
+
throw new Error("Failed to initialize chat session");
|
|
518
|
+
}
|
|
519
|
+
const currentChatId = session.chat_id;
|
|
520
|
+
const currentSupportSessionId = session.session_id;
|
|
521
|
+
if (currentChatId !== this.chatId) {
|
|
522
|
+
this.chatId = currentChatId;
|
|
523
|
+
this.supportSessionId = currentSupportSessionId;
|
|
524
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
525
|
+
localStorage.setItem("chartsconnect_chat_id", this.chatId);
|
|
526
|
+
localStorage.setItem("chartsconnect_session_id", this.supportSessionId);
|
|
527
|
+
}
|
|
528
|
+
if (this.config.debug) {
|
|
529
|
+
console.log("✅ Chat initialized:", { chatId: currentChatId, sessionId: currentSupportSessionId });
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
try {
|
|
533
|
+
await this.chatService.requestHandoff(
|
|
534
|
+
currentChatId,
|
|
535
|
+
currentSupportSessionId,
|
|
536
|
+
"Customer requested human agent",
|
|
537
|
+
dialogflowSessionId || null,
|
|
538
|
+
customerName || null,
|
|
539
|
+
customerEmail || null,
|
|
540
|
+
customerMobile || null
|
|
541
|
+
);
|
|
542
|
+
if (this.config.debug) {
|
|
543
|
+
console.log("✅ Handoff requested successfully");
|
|
544
|
+
}
|
|
545
|
+
} catch (handoffError) {
|
|
546
|
+
if (handoffError.message?.includes("Invalid chat_id") || handoffError.message?.includes("Chat not found") || handoffError.message?.includes("unauthorized") || handoffError.message?.includes("400") || handoffError.message?.includes("401") || handoffError.message?.includes("404") || handoffError.message?.includes("expired")) {
|
|
547
|
+
if (this.config.debug) {
|
|
548
|
+
console.log("⚠️ Chat expired or not found. Re-initializing chat...");
|
|
549
|
+
}
|
|
550
|
+
this.chatId = null;
|
|
551
|
+
this.supportSessionId = null;
|
|
552
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
553
|
+
localStorage.removeItem("chartsconnect_chat_id");
|
|
554
|
+
localStorage.removeItem("chartsconnect_session_id");
|
|
555
|
+
}
|
|
556
|
+
const newSession = await this.chatService.startSupportChat(
|
|
557
|
+
dialogflowSessionId || null,
|
|
558
|
+
customerName || null,
|
|
559
|
+
customerEmail || null,
|
|
560
|
+
customerMobile || null
|
|
561
|
+
);
|
|
562
|
+
if (!newSession || !newSession.chat_id) {
|
|
563
|
+
throw new Error("Failed to re-initialize chat session");
|
|
564
|
+
}
|
|
565
|
+
this.chatId = newSession.chat_id;
|
|
566
|
+
this.supportSessionId = newSession.session_id;
|
|
567
|
+
if (typeof window !== "undefined" && window.localStorage) {
|
|
568
|
+
localStorage.setItem("chartsconnect_chat_id", this.chatId);
|
|
569
|
+
localStorage.setItem("chartsconnect_session_id", this.supportSessionId);
|
|
570
|
+
}
|
|
571
|
+
await this.chatService.requestHandoff(
|
|
572
|
+
this.chatId,
|
|
573
|
+
this.supportSessionId,
|
|
574
|
+
"Customer requested human agent",
|
|
575
|
+
dialogflowSessionId || null,
|
|
576
|
+
customerName || null,
|
|
577
|
+
customerEmail || null,
|
|
578
|
+
customerMobile || null
|
|
579
|
+
);
|
|
580
|
+
if (this.config.debug) {
|
|
581
|
+
console.log("✅ Handoff requested successfully after retry");
|
|
582
|
+
}
|
|
583
|
+
} else {
|
|
584
|
+
throw handoffError;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
this.switchToHumanMode();
|
|
588
|
+
this.chatResolved = false;
|
|
589
|
+
this.agentAccepted = false;
|
|
590
|
+
const connectingMessage = {
|
|
591
|
+
id: `connecting-${Date.now()}`,
|
|
592
|
+
text: "Connecting you to a human agent...",
|
|
593
|
+
sender: "bot",
|
|
594
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
595
|
+
};
|
|
596
|
+
this.setState({
|
|
597
|
+
messages: [...this.state.messages, connectingMessage]
|
|
598
|
+
});
|
|
599
|
+
if (currentChatId && currentSupportSessionId) {
|
|
600
|
+
this.chatService.connectWebSocket(
|
|
601
|
+
currentChatId,
|
|
602
|
+
currentSupportSessionId,
|
|
603
|
+
(message) => {
|
|
604
|
+
this.handleWebSocketMessage(message);
|
|
605
|
+
},
|
|
606
|
+
(connected) => {
|
|
607
|
+
this.wsConnected = connected;
|
|
608
|
+
}
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
this.isConnectingToAgent = false;
|
|
612
|
+
} catch (error) {
|
|
613
|
+
console.error("Error handling handoff:", error);
|
|
614
|
+
const errorMessage = {
|
|
615
|
+
id: `error-${Date.now()}`,
|
|
616
|
+
text: this.config.debug ? `Handoff error: ${error.message}` : "Failed to connect to agent. Please try again.",
|
|
617
|
+
sender: "bot",
|
|
618
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
619
|
+
};
|
|
620
|
+
this.setState({
|
|
621
|
+
messages: [...this.state.messages, errorMessage]
|
|
622
|
+
});
|
|
623
|
+
this.isConnectingToAgent = false;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
433
626
|
/**
|
|
434
627
|
* Handle WebSocket messages
|
|
435
628
|
*/
|
|
@@ -439,7 +632,7 @@ class WidgetStateManager {
|
|
|
439
632
|
if (message.content) {
|
|
440
633
|
if (message.sender_type === "agent" || !message.sender_type) {
|
|
441
634
|
const agentMessage = {
|
|
442
|
-
id: message.id ||
|
|
635
|
+
id: message.id || `agent-${Date.now()}`,
|
|
443
636
|
text: message.content,
|
|
444
637
|
sender: "agent",
|
|
445
638
|
timestamp: new Date(message.timestamp || Date.now())
|
|
@@ -485,7 +678,7 @@ class WidgetStateManager {
|
|
|
485
678
|
name: message.to_agent
|
|
486
679
|
};
|
|
487
680
|
const systemMessage = {
|
|
488
|
-
id:
|
|
681
|
+
id: `system-${Date.now()}`,
|
|
489
682
|
text: message.from_agent ? `Chat has been transferred from ${message.from_agent} to ${message.to_agent}` : `Chat has been transferred to ${message.to_agent}`,
|
|
490
683
|
sender: "bot",
|
|
491
684
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -499,7 +692,7 @@ class WidgetStateManager {
|
|
|
499
692
|
this.agentAccepted = true;
|
|
500
693
|
this.isConnectingToAgent = false;
|
|
501
694
|
const acceptedMessage = {
|
|
502
|
-
id: message.id ||
|
|
695
|
+
id: message.id || `agent-accepted-${Date.now()}`,
|
|
503
696
|
text: "You can chat now, the agent has accepted your request.",
|
|
504
697
|
sender: "bot",
|
|
505
698
|
timestamp: message.timestamp ? new Date(message.timestamp) : /* @__PURE__ */ new Date()
|
|
@@ -538,7 +731,7 @@ class WidgetStateManager {
|
|
|
538
731
|
case "error":
|
|
539
732
|
console.error("WebSocket error:", message.error);
|
|
540
733
|
const errorMessage = {
|
|
541
|
-
id:
|
|
734
|
+
id: `error-${Date.now()}`,
|
|
542
735
|
text: message.error || "An error occurred. Please try again.",
|
|
543
736
|
sender: "bot",
|
|
544
737
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -571,7 +764,7 @@ class WidgetStateManager {
|
|
|
571
764
|
localStorage.removeItem("chartsconnect_session_id");
|
|
572
765
|
}
|
|
573
766
|
const thankYouMessage = {
|
|
574
|
-
id:
|
|
767
|
+
id: `resolved-${Date.now()}`,
|
|
575
768
|
text: "Thank you for contacting us!",
|
|
576
769
|
sender: "bot",
|
|
577
770
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -587,6 +780,11 @@ class WidgetStateManager {
|
|
|
587
780
|
sessionId: null
|
|
588
781
|
// Clear session ID to force recreation
|
|
589
782
|
});
|
|
783
|
+
this.collectingUserInfo = false;
|
|
784
|
+
this.userInfoStep = null;
|
|
785
|
+
this.collectedUserName = "";
|
|
786
|
+
this.collectedUserEmail = "";
|
|
787
|
+
this.collectedUserMobile = "";
|
|
590
788
|
if (this.config.dfProjectId && this.config.dfAgentId && this.state.isOpen) {
|
|
591
789
|
try {
|
|
592
790
|
this.setState({ isLoading: true });
|
|
@@ -604,7 +802,7 @@ class WidgetStateManager {
|
|
|
604
802
|
});
|
|
605
803
|
if (session.message) {
|
|
606
804
|
const welcomeMessage = {
|
|
607
|
-
id:
|
|
805
|
+
id: `welcome-${Date.now()}`,
|
|
608
806
|
text: session.message,
|
|
609
807
|
sender: "bot",
|
|
610
808
|
timestamp: /* @__PURE__ */ new Date(),
|
|
@@ -621,7 +819,7 @@ class WidgetStateManager {
|
|
|
621
819
|
error: error.message || "Failed to initialize chat"
|
|
622
820
|
});
|
|
623
821
|
const fallbackMessage = {
|
|
624
|
-
id:
|
|
822
|
+
id: `fallback-${Date.now()}`,
|
|
625
823
|
text: this.config.fallbackWelcomeMessage || "Hello! How can I help you today?",
|
|
626
824
|
sender: "bot",
|
|
627
825
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -644,7 +842,7 @@ class WidgetStateManager {
|
|
|
644
842
|
if (this.chatId && this.supportSessionId) {
|
|
645
843
|
const history = await this.chatService.loadMessageHistory(this.chatId, this.supportSessionId);
|
|
646
844
|
const historyMessages = history.map((msg) => ({
|
|
647
|
-
id: msg.id ||
|
|
845
|
+
id: msg.id || `history-${Date.now()}-${Math.random()}`,
|
|
648
846
|
text: msg.content,
|
|
649
847
|
sender: msg.sender_type === "agent" ? "agent" : "user",
|
|
650
848
|
timestamp: new Date(msg.timestamp)
|
|
@@ -668,7 +866,7 @@ class WidgetStateManager {
|
|
|
668
866
|
console.error("Error loading message history:", error);
|
|
669
867
|
if (this.config.debug) {
|
|
670
868
|
const errorMessage = {
|
|
671
|
-
id:
|
|
869
|
+
id: `error-${Date.now()}`,
|
|
672
870
|
text: `Failed to load chat history: ${error.message}`,
|
|
673
871
|
sender: "bot",
|
|
674
872
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -783,9 +981,7 @@ const _hoisted_3 = { class: "custom-welcome-message" };
|
|
|
783
981
|
const _hoisted_4 = { class: "custom-welcome-cta" };
|
|
784
982
|
const _hoisted_5 = {
|
|
785
983
|
key: 2,
|
|
786
|
-
class: "custom-chat-window"
|
|
787
|
-
role: "dialog",
|
|
788
|
-
"aria-label": "Chat window"
|
|
984
|
+
class: "custom-chat-window"
|
|
789
985
|
};
|
|
790
986
|
const _hoisted_6 = { class: "custom-chat-header" };
|
|
791
987
|
const _hoisted_7 = { class: "custom-chat-header-content" };
|
|
@@ -844,7 +1040,7 @@ const _hoisted_26 = {
|
|
|
844
1040
|
key: 4,
|
|
845
1041
|
class: "custom-agent-typing-indicator"
|
|
846
1042
|
};
|
|
847
|
-
const _hoisted_27 = ["value", "placeholder", "
|
|
1043
|
+
const _hoisted_27 = ["value", "placeholder", "disabled"];
|
|
848
1044
|
const _hoisted_28 = ["disabled"];
|
|
849
1045
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
850
1046
|
...{
|
|
@@ -869,8 +1065,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
869
1065
|
fallbackWelcomeMessage: { default: "Hello! I'm Charts Connect AI Assistant. How can I help you today?" },
|
|
870
1066
|
inputPlaceholder: { default: "Type your message..." },
|
|
871
1067
|
emptyStateMessage: { default: "Hi! I'm Charts Connect AI Assistant. How can I help you today?" },
|
|
872
|
-
debug: { type: Boolean, default: false }
|
|
873
|
-
noMatchMessage: {}
|
|
1068
|
+
debug: { type: Boolean, default: false }
|
|
874
1069
|
},
|
|
875
1070
|
setup(__props) {
|
|
876
1071
|
const props = __props;
|
|
@@ -1013,10 +1208,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1013
1208
|
createElementVNode("div", {
|
|
1014
1209
|
class: "custom-chat-messages",
|
|
1015
1210
|
ref_key: "messagesContainer",
|
|
1016
|
-
ref: messagesContainer
|
|
1017
|
-
role: "log",
|
|
1018
|
-
"aria-live": "polite",
|
|
1019
|
-
"aria-label": "Chat messages"
|
|
1211
|
+
ref: messagesContainer
|
|
1020
1212
|
}, [
|
|
1021
1213
|
isInitializing.value && unref(state).messages.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_15, [..._cache[2] || (_cache[2] = [
|
|
1022
1214
|
createElementVNode("div", { class: "custom-typing-indicator" }, [
|
|
@@ -1040,7 +1232,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1040
1232
|
}, [
|
|
1041
1233
|
createElementVNode("div", {
|
|
1042
1234
|
class: normalizeClass(["custom-message-content", { "custom-handoff-content": isHandoffMessage(message.text) }]),
|
|
1043
|
-
innerHTML: unref(safeLinkifyText)(message.text)
|
|
1235
|
+
innerHTML: unref(safeLinkifyText)(message.text).replace(/\n/g, "<br>")
|
|
1044
1236
|
}, null, 10, _hoisted_17),
|
|
1045
1237
|
message.richContent && Array.isArray(message.richContent) && message.richContent.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_18, [
|
|
1046
1238
|
(openBlock(true), createElementBlock(Fragment, null, renderList(message.richContent, (contentGroup, groupIndex) => {
|
|
@@ -1116,7 +1308,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
1116
1308
|
value: unref(state).inputValue,
|
|
1117
1309
|
onInput: handleInput,
|
|
1118
1310
|
placeholder: config.value.inputPlaceholder,
|
|
1119
|
-
"aria-label": config.value.inputPlaceholder,
|
|
1120
1311
|
disabled: unref(state).isLoading || isInitializing.value || isStartingNewChat.value
|
|
1121
1312
|
}, null, 40, _hoisted_27),
|
|
1122
1313
|
createElementVNode("button", {
|
|
@@ -1156,10 +1347,10 @@ const _export_sfc = (sfc, props) => {
|
|
|
1156
1347
|
}
|
|
1157
1348
|
return target;
|
|
1158
1349
|
};
|
|
1159
|
-
const ChatWidgetComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
1350
|
+
const ChatWidgetComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-11671761"]]);
|
|
1160
1351
|
export {
|
|
1161
1352
|
ChatWidgetComponent as C,
|
|
1162
1353
|
WidgetStateManager as W,
|
|
1163
1354
|
useChatWidget as u
|
|
1164
1355
|
};
|
|
1165
|
-
//# sourceMappingURL=ChatWidget-
|
|
1356
|
+
//# sourceMappingURL=ChatWidget-Bs0XV_7i.js.map
|