@developpement/tp-chatbot-widget 0.0.5 → 0.0.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/package.json +1 -1
- package/src/chatbot.css +0 -1
- package/src/chatbot.js +92 -16
package/package.json
CHANGED
package/src/chatbot.css
CHANGED
package/src/chatbot.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
const CLIENT_THEMES = {
|
|
5
|
-
flix: { primary: '#
|
|
6
|
-
sncf: { primary: '#1a6b5a', name: 'SNCF' },
|
|
5
|
+
flix: { primary: '#5cc500', name: 'Flix Corporate', position: 'left' },
|
|
6
|
+
sncf: { primary: '#1a6b5a', name: 'SNCF', position: 'right' },
|
|
7
7
|
};
|
|
8
|
-
const DEFAULT_THEME = { primary: '#7b1fa2', name: 'Support' };
|
|
8
|
+
const DEFAULT_THEME = { primary: '#7b1fa2', name: 'Support', position: 'right' };
|
|
9
9
|
|
|
10
10
|
function getClientTheme(client_id) {
|
|
11
11
|
return CLIENT_THEMES[client_id] || DEFAULT_THEME;
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
this.view = 'list';
|
|
101
101
|
|
|
102
102
|
this.render();
|
|
103
|
-
this.applyTheme();
|
|
103
|
+
this.applyTheme();
|
|
104
104
|
this.attachEvents();
|
|
105
105
|
this._initialized = true;
|
|
106
106
|
|
|
@@ -109,7 +109,6 @@
|
|
|
109
109
|
this.user_id = this.user_info?.user_id;
|
|
110
110
|
this.showConversationList();
|
|
111
111
|
} else {
|
|
112
|
-
// Attend 500ms que le framework passe le token
|
|
113
112
|
setTimeout(() => {
|
|
114
113
|
const token = this.getAttribute('access-token');
|
|
115
114
|
if (token) {
|
|
@@ -166,6 +165,28 @@
|
|
|
166
165
|
.tp-conv-new-btn { background: linear-gradient(135deg, ${color}, ${dark}) !important; }
|
|
167
166
|
`;
|
|
168
167
|
document.head.appendChild(style);
|
|
168
|
+
|
|
169
|
+
const position = getClientTheme(this.client_id).position || 'right';
|
|
170
|
+
|
|
171
|
+
const host = this.querySelector('.tp-chatbot-host');
|
|
172
|
+
if (host) {
|
|
173
|
+
host.style.width = '360px';
|
|
174
|
+
host.style.left = position === 'left' ? '24px' : 'auto';
|
|
175
|
+
host.style.right = position === 'left' ? 'auto' : '24px';
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const bubble = this.querySelector('.tp-chatbot-bubble');
|
|
179
|
+
if (bubble) {
|
|
180
|
+
bubble.style.marginLeft = position === 'left' ? '0' : 'auto';
|
|
181
|
+
bubble.style.marginRight = position === 'left' ? 'auto' : '0';
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const win = this.querySelector('.tp-chatbot-window');
|
|
185
|
+
if (win) {
|
|
186
|
+
win.style.left = '0';
|
|
187
|
+
win.style.right = 'auto';
|
|
188
|
+
win.style.transformOrigin = position === 'left' ? 'bottom left' : 'bottom right';
|
|
189
|
+
}
|
|
169
190
|
}
|
|
170
191
|
|
|
171
192
|
// ─── Render ───────────────────────────────────────────────────────────────
|
|
@@ -399,7 +420,7 @@
|
|
|
399
420
|
this.last_message_count = conv.messages.length;
|
|
400
421
|
|
|
401
422
|
if (conv.status === 'closed') {
|
|
402
|
-
this.showClosed();
|
|
423
|
+
this.showClosed(conv.csat || null);
|
|
403
424
|
return;
|
|
404
425
|
}
|
|
405
426
|
|
|
@@ -453,10 +474,14 @@
|
|
|
453
474
|
if (input_bar) input_bar.style.display = 'flex';
|
|
454
475
|
|
|
455
476
|
const agent_bar = this.querySelector('#tp-agent-bar');
|
|
456
|
-
if (agent_bar) agent_bar.style.display = '
|
|
477
|
+
if (agent_bar) agent_bar.style.display = 'none';
|
|
457
478
|
|
|
458
479
|
this.conversation_id = await this.createConversation();
|
|
459
|
-
this.
|
|
480
|
+
const client_name = this.client_id === 'flix' ? 'Flix Corporate' : this.client_id === 'sncf' ? 'SNCF' : this.client_id;
|
|
481
|
+
this.addMessage(
|
|
482
|
+
'assistant',
|
|
483
|
+
`Bonjour ${this.user_info?.first_name || ''} ! 👋 Je m'appelle Maria, votre assistante virtuelle ${client_name}. Comment puis-je vous aider aujourd'hui ?`
|
|
484
|
+
);
|
|
460
485
|
this.polling_interval = setInterval(() => this.pollMessages(), 3000);
|
|
461
486
|
}
|
|
462
487
|
|
|
@@ -530,7 +555,11 @@
|
|
|
530
555
|
const close_bar = this.querySelector('#tp-close-bar');
|
|
531
556
|
if (close_bar) close_bar.style.display = 'block';
|
|
532
557
|
|
|
533
|
-
this.
|
|
558
|
+
const client_name = this.client_id === 'flix' ? 'Flix Corporate' : this.client_id === 'sncf' ? 'SNCF' : this.client_id;
|
|
559
|
+
this.addMessage(
|
|
560
|
+
'assistant',
|
|
561
|
+
`Bonjour ${first_name} ! 👋 Je m'appelle Maria, votre assistante virtuelle ${client_name}. Comment puis-je vous aider aujourd'hui ?`
|
|
562
|
+
);
|
|
534
563
|
this.polling_interval = setInterval(() => this.pollMessages(), 3000);
|
|
535
564
|
}
|
|
536
565
|
|
|
@@ -583,7 +612,7 @@
|
|
|
583
612
|
if (typing) typing.remove();
|
|
584
613
|
}
|
|
585
614
|
|
|
586
|
-
showClosed() {
|
|
615
|
+
showClosed(existing_csat = null) {
|
|
587
616
|
this.is_closed = true;
|
|
588
617
|
if (this.polling_interval) {
|
|
589
618
|
clearInterval(this.polling_interval);
|
|
@@ -603,16 +632,30 @@
|
|
|
603
632
|
if (close_bar) close_bar.style.display = 'none';
|
|
604
633
|
|
|
605
634
|
const container = this.querySelector('#tp-messages');
|
|
606
|
-
|
|
635
|
+
|
|
636
|
+
const existing_banner = this.querySelector('#tp-closed-banner');
|
|
637
|
+
if (existing_banner) {
|
|
638
|
+
if (existing_banner.querySelector('#tp-csat-block')) return; // déjà complet
|
|
639
|
+
existing_banner.remove(); // incomplet, on recrée
|
|
640
|
+
}
|
|
607
641
|
|
|
608
642
|
const color = this.getThemeColor();
|
|
609
643
|
const dark = this.shadeColor(color, -20);
|
|
610
644
|
|
|
645
|
+
const csat_html = existing_csat
|
|
646
|
+
? `<div style="font-size:13px;color:#888;margin-bottom:14px;">${existing_csat === 'positive' ? '👍 Merci pour votre retour !' : '👎 Merci, nous allons nous améliorer.'}</div>`
|
|
647
|
+
: `<div style="font-size:12px;color:#888;margin-bottom:10px;">Cette conversation vous a-t-elle été utile ?</div>
|
|
648
|
+
<div style="display:flex;gap:10px;justify-content:center;margin-bottom:14px;">
|
|
649
|
+
<button id="tp-csat-positive" style="padding:8px 20px;border-radius:8px;border:1.5px solid #22c55e;background:white;color:#22c55e;font-size:18px;cursor:pointer;font-weight:700;">👍</button>
|
|
650
|
+
<button id="tp-csat-negative" style="padding:8px 20px;border-radius:8px;border:1.5px solid #ef4444;background:white;color:#ef4444;font-size:18px;cursor:pointer;font-weight:700;">👎</button>
|
|
651
|
+
</div>`;
|
|
652
|
+
|
|
611
653
|
const banner = document.createElement('div');
|
|
612
654
|
banner.id = 'tp-closed-banner';
|
|
613
655
|
banner.innerHTML = `
|
|
614
|
-
<div style="margin:16px;padding:16px;background:#
|
|
615
|
-
<div style="font-size:13px;color:#
|
|
656
|
+
<div style="margin:16px;padding:16px;background:#f9f5ff;border:1px solid #ede8f5;border-radius:12px;text-align:center;">
|
|
657
|
+
<div style="font-size:13px;color:#1a1a2e;font-weight:600;margin-bottom:8px;">✅ Conversation clôturée</div>
|
|
658
|
+
<div id="tp-csat-block">${csat_html}</div>
|
|
616
659
|
<button id="tp-new-conversation" style="padding:10px 20px;background:linear-gradient(135deg,${color},${dark});color:white;border:none;border-radius:8px;font-size:13px;font-weight:600;cursor:pointer;margin-bottom:8px;width:100%;">
|
|
617
660
|
💬 Nouvelle conversation
|
|
618
661
|
</button>
|
|
@@ -624,6 +667,26 @@
|
|
|
624
667
|
container.appendChild(banner);
|
|
625
668
|
container.scrollTop = container.scrollHeight;
|
|
626
669
|
|
|
670
|
+
if (!existing_csat) {
|
|
671
|
+
const submit_csat = async rating => {
|
|
672
|
+
const csat_block = this.querySelector('#tp-csat-block');
|
|
673
|
+
if (!csat_block) return;
|
|
674
|
+
try {
|
|
675
|
+
await fetch(`${this.api_url}/chat/conversations/${this.conversation_id}/csat`, {
|
|
676
|
+
method: 'POST',
|
|
677
|
+
headers: this.getHeaders(true),
|
|
678
|
+
body: JSON.stringify({ user_id: this.user_id, rating }),
|
|
679
|
+
});
|
|
680
|
+
} catch (e) {
|
|
681
|
+
console.error('CSAT error:', e);
|
|
682
|
+
}
|
|
683
|
+
csat_block.innerHTML = `<div style="font-size:13px;color:#888;margin-bottom:14px;">${rating === 'positive' ? '👍 Merci pour votre retour !' : '👎 Merci, nous allons nous améliorer.'}</div>`;
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
this.querySelector('#tp-csat-positive').addEventListener('click', () => submit_csat('positive'));
|
|
687
|
+
this.querySelector('#tp-csat-negative').addEventListener('click', () => submit_csat('negative'));
|
|
688
|
+
}
|
|
689
|
+
|
|
627
690
|
this.querySelector('#tp-new-conversation').addEventListener('click', () => this.startNewConversation());
|
|
628
691
|
this.querySelector('#tp-back-to-list').addEventListener('click', () => this.showConversationList());
|
|
629
692
|
}
|
|
@@ -663,20 +726,29 @@
|
|
|
663
726
|
this.hideTyping();
|
|
664
727
|
|
|
665
728
|
if (response.status === 429) {
|
|
666
|
-
this.addMessage('system',
|
|
667
|
-
const input_bar = this.querySelector('#tp-chatbot-input-bar');
|
|
668
|
-
if (input_bar) input_bar.style.display = 'none';
|
|
729
|
+
this.addMessage('system', data.error?.message || 'Trop de messages. Veuillez patienter avant de réessayer.');
|
|
669
730
|
this.is_loading = false;
|
|
670
731
|
return;
|
|
671
732
|
}
|
|
672
733
|
|
|
673
734
|
this.agent_mode = data.result.agent_mode;
|
|
735
|
+
const source = data.result.source || null;
|
|
736
|
+
|
|
674
737
|
const subtitle = this.querySelector('#tp-subtitle');
|
|
675
738
|
if (subtitle) subtitle.textContent = this.agent_mode ? '👤 Agent humain' : '🤖 Assistant virtuel';
|
|
676
739
|
|
|
677
740
|
if (data.result.reply) {
|
|
678
741
|
this.addMessage(this.agent_mode ? 'agent' : 'assistant', data.result.reply);
|
|
679
742
|
}
|
|
743
|
+
|
|
744
|
+
// Afficher bouton agent si fallback ou ≥ 3 messages user
|
|
745
|
+
const user_msg_count = this.messages.filter(m => m.role === 'user').length;
|
|
746
|
+
const agent_bar = this.querySelector('#tp-agent-bar');
|
|
747
|
+
if (agent_bar && !this.agent_requested && !this.agent_mode) {
|
|
748
|
+
if (source === 'fallback' || source === 'clarification' || source === 'no_match' || user_msg_count >= 5) {
|
|
749
|
+
agent_bar.style.display = 'block';
|
|
750
|
+
}
|
|
751
|
+
}
|
|
680
752
|
} catch {
|
|
681
753
|
this.hideTyping();
|
|
682
754
|
this.addMessage('assistant', 'Une erreur est survenue. Veuillez réessayer.');
|
|
@@ -766,6 +838,10 @@
|
|
|
766
838
|
const typing_el = this.querySelector('#tp-agent-typing');
|
|
767
839
|
if (typing_el) typing_el.remove();
|
|
768
840
|
this.addMessage('agent', msg.content);
|
|
841
|
+
} else if (msg.role === 'assistant') {
|
|
842
|
+
this.addMessage('assistant', msg.content);
|
|
843
|
+
} else if (msg.role === 'system') {
|
|
844
|
+
this.addMessage('system', msg.content);
|
|
769
845
|
}
|
|
770
846
|
});
|
|
771
847
|
this.last_message_count = server_messages.length;
|