@product7/feedback-sdk 1.3.8 → 1.3.9
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/feedback-sdk.js +2824 -2371
- package/dist/feedback-sdk.js.map +1 -1
- package/dist/feedback-sdk.min.js +1 -1
- package/dist/feedback-sdk.min.js.map +1 -1
- package/package.json +1 -1
- package/src/api/services/MessengerService.js +5 -5
- package/src/core/APIService.js +33 -14
- package/src/index.js +1 -1
- package/src/styles/base.js +1 -1
- package/src/styles/changelog.js +58 -40
- package/src/styles/components.js +19 -2
- package/src/styles/design-tokens.js +4 -4
- package/src/styles/feedback.js +3 -8
- package/src/styles/messenger-components.js +473 -0
- package/src/styles/messenger-core.js +37 -268
- package/src/styles/messenger-features.js +89 -267
- package/src/styles/messenger-views.js +391 -325
- package/src/styles/messenger.js +17 -558
- package/src/styles/styles.js +21 -24
- package/src/styles/{surveys.js → survey.js} +55 -20
- package/src/widgets/BaseWidget.js +1 -1
- package/src/widgets/ButtonWidget.js +1 -1
- package/src/widgets/ChangelogWidget.js +1 -1
- package/src/widgets/InlineWidget.js +1 -1
- package/src/widgets/MessengerWidget.js +15 -9
- package/src/widgets/SurveyWidget.js +1 -1
- package/src/widgets/TabWidget.js +1 -1
- package/src/widgets/messenger/MessengerState.js +5 -2
- package/src/widgets/messenger/components/MessengerLauncher.js +22 -18
- package/src/widgets/messenger/components/MessengerPanel.js +1 -1
- package/src/widgets/messenger/components/NavigationTabs.js +36 -15
- package/src/widgets/messenger/views/ChangelogView.js +8 -32
- package/src/widgets/messenger/views/ChatView.js +96 -60
- package/src/widgets/messenger/views/ConversationsView.js +67 -45
- package/src/widgets/messenger/views/HelpView.js +22 -32
- package/src/widgets/messenger/views/HomeView.js +58 -40
- package/src/widgets/messenger/views/PreChatFormView.js +12 -5
- package/src/styles/messenger-help.js +0 -298
- package/src/styles/messenger-themes.js +0 -500
|
@@ -40,7 +40,10 @@ export class ChatView {
|
|
|
40
40
|
data.conversationId === this.state.activeConversationId
|
|
41
41
|
) {
|
|
42
42
|
this._updateContent();
|
|
43
|
-
} else if (
|
|
43
|
+
} else if (
|
|
44
|
+
type === 'messagesUpdate' &&
|
|
45
|
+
data.conversationId === this.state.activeConversationId
|
|
46
|
+
) {
|
|
44
47
|
this._updateContent();
|
|
45
48
|
}
|
|
46
49
|
});
|
|
@@ -60,7 +63,6 @@ export class ChatView {
|
|
|
60
63
|
? this._renderEmptyState(isNewConversation)
|
|
61
64
|
: messages.map((msg) => this._renderMessage(msg)).join('');
|
|
62
65
|
|
|
63
|
-
const avatarHtml = this._renderConversationAvatar(conversation);
|
|
64
66
|
const title = isNewConversation
|
|
65
67
|
? 'New conversation'
|
|
66
68
|
: conversation?.title || 'Chat with team';
|
|
@@ -78,7 +80,6 @@ export class ChatView {
|
|
|
78
80
|
</svg>
|
|
79
81
|
</button>
|
|
80
82
|
<div class="messenger-chat-header-info">
|
|
81
|
-
${avatarHtml}
|
|
82
83
|
<span class="messenger-chat-title">${title}</span>
|
|
83
84
|
</div>
|
|
84
85
|
<button class="sdk-close-btn" aria-label="Close">
|
|
@@ -90,12 +91,16 @@ export class ChatView {
|
|
|
90
91
|
|
|
91
92
|
<div class="messenger-chat-messages">
|
|
92
93
|
${messagesHtml}
|
|
93
|
-
${
|
|
94
|
+
${
|
|
95
|
+
isClosed
|
|
96
|
+
? `
|
|
94
97
|
<div class="messenger-closed-banner">
|
|
95
98
|
<i class="ph ph-check-circle"></i>
|
|
96
99
|
<span>This conversation has been resolved</span>
|
|
97
100
|
</div>
|
|
98
|
-
`
|
|
101
|
+
`
|
|
102
|
+
: ''
|
|
103
|
+
}
|
|
99
104
|
<div class="messenger-typing-indicator">
|
|
100
105
|
<div class="messenger-typing-dots">
|
|
101
106
|
<span></span><span></span><span></span>
|
|
@@ -104,7 +109,10 @@ export class ChatView {
|
|
|
104
109
|
</div>
|
|
105
110
|
</div>
|
|
106
111
|
|
|
107
|
-
${
|
|
112
|
+
${
|
|
113
|
+
isClosed
|
|
114
|
+
? ''
|
|
115
|
+
: `
|
|
108
116
|
<div class="messenger-compose-attachments-preview"></div>
|
|
109
117
|
|
|
110
118
|
<div class="messenger-chat-compose">
|
|
@@ -121,10 +129,13 @@ export class ChatView {
|
|
|
121
129
|
</button>
|
|
122
130
|
<input type="file" class="messenger-compose-file-input" multiple accept="image/*,.pdf,.doc,.docx,.xls,.xlsx,.txt,.zip" />
|
|
123
131
|
</div>
|
|
124
|
-
`
|
|
132
|
+
`
|
|
133
|
+
}
|
|
125
134
|
`;
|
|
126
135
|
|
|
127
|
-
this._typingIndicator = this.element.querySelector(
|
|
136
|
+
this._typingIndicator = this.element.querySelector(
|
|
137
|
+
'.messenger-typing-indicator'
|
|
138
|
+
);
|
|
128
139
|
this._attachEvents();
|
|
129
140
|
this._scrollToBottom();
|
|
130
141
|
this._renderAttachmentPreviews();
|
|
@@ -132,7 +143,8 @@ export class ChatView {
|
|
|
132
143
|
|
|
133
144
|
_renderEmptyState(isNewConversation = false) {
|
|
134
145
|
const avatarHtml = this._renderTeamAvatars();
|
|
135
|
-
const responseTime =
|
|
146
|
+
const responseTime =
|
|
147
|
+
this.state.responseTime || 'We typically reply within a few minutes';
|
|
136
148
|
const isOnline = this.state.agentsOnline;
|
|
137
149
|
|
|
138
150
|
return `
|
|
@@ -150,26 +162,34 @@ export class ChatView {
|
|
|
150
162
|
|
|
151
163
|
_renderMessageAttachments(attachments) {
|
|
152
164
|
if (!attachments || attachments.length === 0) return '';
|
|
153
|
-
return attachments
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
165
|
+
return attachments
|
|
166
|
+
.map((att) => {
|
|
167
|
+
if (att.type === 'image') {
|
|
168
|
+
return `<img class="messenger-message-image" src="${this._escapeHtml(att.url)}" alt="${this._escapeHtml(att.name || 'image')}" data-url="${this._escapeHtml(att.url)}" />`;
|
|
169
|
+
}
|
|
170
|
+
return `<a class="messenger-message-file" href="${this._escapeHtml(att.url)}" data-url="${this._escapeHtml(att.url)}" data-name="${this._escapeHtml(att.name || 'file')}">
|
|
158
171
|
<i class="ph ph-file"></i>
|
|
159
172
|
<span>${this._escapeHtml(att.name || 'file')}</span>
|
|
160
173
|
<i class="ph ph-download-simple messenger-file-download-icon"></i>
|
|
161
174
|
</a>`;
|
|
162
|
-
|
|
175
|
+
})
|
|
176
|
+
.join('');
|
|
163
177
|
}
|
|
164
178
|
|
|
165
179
|
_renderMessage(message) {
|
|
166
180
|
const isOwn = message.isOwn;
|
|
167
|
-
const messageClass = isOwn
|
|
181
|
+
const messageClass = isOwn
|
|
182
|
+
? 'messenger-message-own'
|
|
183
|
+
: 'messenger-message-received';
|
|
168
184
|
const timeStr = this._formatMessageTime(message.timestamp);
|
|
169
185
|
const attachmentsHtml = this._renderMessageAttachments(message.attachments);
|
|
170
186
|
|
|
171
|
-
const contentHtml = message.content
|
|
172
|
-
|
|
187
|
+
const contentHtml = message.content
|
|
188
|
+
? `<div class="messenger-message-content">${this._formatMessageContent(message.content)}</div>`
|
|
189
|
+
: '';
|
|
190
|
+
const bubbleHtml = contentHtml
|
|
191
|
+
? `<div class="messenger-message-bubble">${contentHtml}</div>`
|
|
192
|
+
: '';
|
|
173
193
|
|
|
174
194
|
if (isOwn) {
|
|
175
195
|
return `
|
|
@@ -184,13 +204,15 @@ export class ChatView {
|
|
|
184
204
|
const avatarHtml = this._renderSenderAvatar(message.sender);
|
|
185
205
|
return `
|
|
186
206
|
<div class="messenger-message ${messageClass}">
|
|
187
|
-
<div class="messenger-message-
|
|
188
|
-
<div class="messenger-message-
|
|
189
|
-
<div class="messenger-message-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
207
|
+
<div class="messenger-message-sender">${message.sender?.name || 'Support'}</div>
|
|
208
|
+
<div class="messenger-message-row">
|
|
209
|
+
<div class="messenger-message-avatar">${avatarHtml}</div>
|
|
210
|
+
<div class="messenger-message-wrapper">
|
|
211
|
+
${bubbleHtml}
|
|
212
|
+
${attachmentsHtml}
|
|
213
|
+
</div>
|
|
193
214
|
</div>
|
|
215
|
+
<div class="messenger-message-time">${timeStr}</div>
|
|
194
216
|
</div>
|
|
195
217
|
`;
|
|
196
218
|
}
|
|
@@ -203,17 +225,6 @@ export class ChatView {
|
|
|
203
225
|
return `<div class="sdk-avatar sdk-avatar-sm">${initial}</div>`;
|
|
204
226
|
}
|
|
205
227
|
|
|
206
|
-
_renderConversationAvatar(conversation) {
|
|
207
|
-
if (!conversation?.participants?.length) {
|
|
208
|
-
return `<div class="sdk-avatar sdk-avatar-sm">S</div>`;
|
|
209
|
-
}
|
|
210
|
-
const p = conversation.participants[0];
|
|
211
|
-
if (p.avatarUrl) {
|
|
212
|
-
return `<div class="sdk-avatar sdk-avatar-sm"><img src="${p.avatarUrl}" alt="${p.name}" /></div>`;
|
|
213
|
-
}
|
|
214
|
-
return `<div class="sdk-avatar sdk-avatar-sm">${(p.name || 'S').charAt(0).toUpperCase()}</div>`;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
228
|
_renderTeamAvatars() {
|
|
218
229
|
const avatars = this.state.teamAvatars;
|
|
219
230
|
if (!avatars || avatars.length === 0) {
|
|
@@ -258,7 +269,9 @@ export class ChatView {
|
|
|
258
269
|
}
|
|
259
270
|
|
|
260
271
|
_appendMessage(message) {
|
|
261
|
-
const messagesContainer = this.element.querySelector(
|
|
272
|
+
const messagesContainer = this.element.querySelector(
|
|
273
|
+
'.messenger-chat-messages'
|
|
274
|
+
);
|
|
262
275
|
const emptyState = messagesContainer.querySelector('.messenger-chat-empty');
|
|
263
276
|
if (emptyState) {
|
|
264
277
|
emptyState.remove();
|
|
@@ -271,7 +284,9 @@ export class ChatView {
|
|
|
271
284
|
}
|
|
272
285
|
|
|
273
286
|
_scrollToBottom() {
|
|
274
|
-
const messagesContainer = this.element.querySelector(
|
|
287
|
+
const messagesContainer = this.element.querySelector(
|
|
288
|
+
'.messenger-chat-messages'
|
|
289
|
+
);
|
|
275
290
|
if (messagesContainer) {
|
|
276
291
|
setTimeout(() => {
|
|
277
292
|
messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
|
@@ -283,12 +298,15 @@ export class ChatView {
|
|
|
283
298
|
const input = this.element.querySelector('.messenger-compose-input');
|
|
284
299
|
const sendBtn = this.element.querySelector('.messenger-compose-send');
|
|
285
300
|
if (input && sendBtn) {
|
|
286
|
-
sendBtn.disabled =
|
|
301
|
+
sendBtn.disabled =
|
|
302
|
+
!input.value.trim() && this._pendingAttachments.length === 0;
|
|
287
303
|
}
|
|
288
304
|
}
|
|
289
305
|
|
|
290
306
|
_renderAttachmentPreviews() {
|
|
291
|
-
const container = this.element.querySelector(
|
|
307
|
+
const container = this.element.querySelector(
|
|
308
|
+
'.messenger-compose-attachments-preview'
|
|
309
|
+
);
|
|
292
310
|
if (!container) return;
|
|
293
311
|
|
|
294
312
|
if (this._pendingAttachments.length === 0) {
|
|
@@ -298,27 +316,31 @@ export class ChatView {
|
|
|
298
316
|
}
|
|
299
317
|
|
|
300
318
|
container.style.display = 'flex';
|
|
301
|
-
container.innerHTML = this._pendingAttachments
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
319
|
+
container.innerHTML = this._pendingAttachments
|
|
320
|
+
.map((att, i) => {
|
|
321
|
+
const isImage = att.type.startsWith('image');
|
|
322
|
+
const thumb = isImage
|
|
323
|
+
? `<img class="messenger-attachment-thumb" src="${att.preview}" alt="${this._escapeHtml(att.file.name)}" />`
|
|
324
|
+
: `<div class="messenger-attachment-thumb messenger-attachment-file-icon"><i class="ph ph-file"></i></div>`;
|
|
325
|
+
return `
|
|
307
326
|
<div class="messenger-attachment-preview" data-index="${i}">
|
|
308
327
|
${thumb}
|
|
309
328
|
<button class="messenger-attachment-remove" data-index="${i}" aria-label="Remove">×</button>
|
|
310
329
|
</div>
|
|
311
330
|
`;
|
|
312
|
-
|
|
331
|
+
})
|
|
332
|
+
.join('');
|
|
313
333
|
|
|
314
|
-
container
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
334
|
+
container
|
|
335
|
+
.querySelectorAll('.messenger-attachment-remove')
|
|
336
|
+
.forEach((btn) => {
|
|
337
|
+
btn.addEventListener('click', (e) => {
|
|
338
|
+
const idx = parseInt(e.currentTarget.dataset.index, 10);
|
|
339
|
+
this._pendingAttachments.splice(idx, 1);
|
|
340
|
+
this._renderAttachmentPreviews();
|
|
341
|
+
this._updateSendButtonState();
|
|
342
|
+
});
|
|
320
343
|
});
|
|
321
|
-
});
|
|
322
344
|
}
|
|
323
345
|
|
|
324
346
|
_attachEvents() {
|
|
@@ -361,7 +383,9 @@ export class ChatView {
|
|
|
361
383
|
}
|
|
362
384
|
|
|
363
385
|
const attachBtn = this.element.querySelector('.messenger-compose-attach');
|
|
364
|
-
const fileInput = this.element.querySelector(
|
|
386
|
+
const fileInput = this.element.querySelector(
|
|
387
|
+
'.messenger-compose-file-input'
|
|
388
|
+
);
|
|
365
389
|
|
|
366
390
|
if (attachBtn && fileInput) {
|
|
367
391
|
attachBtn.addEventListener('click', () => {
|
|
@@ -388,7 +412,9 @@ export class ChatView {
|
|
|
388
412
|
});
|
|
389
413
|
}
|
|
390
414
|
|
|
391
|
-
const messagesContainer = this.element.querySelector(
|
|
415
|
+
const messagesContainer = this.element.querySelector(
|
|
416
|
+
'.messenger-chat-messages'
|
|
417
|
+
);
|
|
392
418
|
if (messagesContainer) {
|
|
393
419
|
messagesContainer.addEventListener('click', (e) => {
|
|
394
420
|
const fileLink = e.target.closest('.messenger-message-file');
|
|
@@ -429,12 +455,16 @@ export class ChatView {
|
|
|
429
455
|
|
|
430
456
|
_escapeHtml(text) {
|
|
431
457
|
if (!text) return '';
|
|
432
|
-
return text
|
|
458
|
+
return text
|
|
459
|
+
.replace(/&/g, '&')
|
|
460
|
+
.replace(/</g, '<')
|
|
461
|
+
.replace(/>/g, '>')
|
|
462
|
+
.replace(/"/g, '"');
|
|
433
463
|
}
|
|
434
464
|
|
|
435
465
|
async _sendMessage() {
|
|
436
466
|
if (this._isConversationClosed) return;
|
|
437
|
-
|
|
467
|
+
|
|
438
468
|
const input = this.element.querySelector('.messenger-compose-input');
|
|
439
469
|
const content = input.value.trim();
|
|
440
470
|
const hasAttachments = this._pendingAttachments.length > 0;
|
|
@@ -466,7 +496,11 @@ export class ChatView {
|
|
|
466
496
|
this.state.addMessage(this.state.activeConversationId, message);
|
|
467
497
|
|
|
468
498
|
if (this.options.onSendMessage) {
|
|
469
|
-
this.options.onSendMessage(
|
|
499
|
+
this.options.onSendMessage(
|
|
500
|
+
this.state.activeConversationId,
|
|
501
|
+
message,
|
|
502
|
+
attachmentsToSend
|
|
503
|
+
);
|
|
470
504
|
}
|
|
471
505
|
}
|
|
472
506
|
|
|
@@ -510,7 +544,9 @@ export class ChatView {
|
|
|
510
544
|
_showTypingIndicator(userName) {
|
|
511
545
|
if (this._typingIndicator) {
|
|
512
546
|
this._typingIndicator.style.display = 'flex';
|
|
513
|
-
const textEl = this._typingIndicator.querySelector(
|
|
547
|
+
const textEl = this._typingIndicator.querySelector(
|
|
548
|
+
'.messenger-typing-text'
|
|
549
|
+
);
|
|
514
550
|
if (textEl) {
|
|
515
551
|
textEl.textContent = `${userName || 'Support'} is typing...`;
|
|
516
552
|
}
|
|
@@ -536,4 +572,4 @@ export class ChatView {
|
|
|
536
572
|
this.element.parentNode.removeChild(this.element);
|
|
537
573
|
}
|
|
538
574
|
}
|
|
539
|
-
}
|
|
575
|
+
}
|
|
@@ -4,6 +4,15 @@ export class ConversationsView {
|
|
|
4
4
|
this.options = options;
|
|
5
5
|
this.element = null;
|
|
6
6
|
this._unsubscribe = null;
|
|
7
|
+
this.avatarColors = [
|
|
8
|
+
'#155EEF',
|
|
9
|
+
'#8b5cf6',
|
|
10
|
+
'#10b981',
|
|
11
|
+
'#f59e0b',
|
|
12
|
+
'#ef4444',
|
|
13
|
+
'#ec4899',
|
|
14
|
+
'#06b6d4',
|
|
15
|
+
];
|
|
7
16
|
}
|
|
8
17
|
|
|
9
18
|
render() {
|
|
@@ -27,55 +36,61 @@ export class ConversationsView {
|
|
|
27
36
|
return this.element;
|
|
28
37
|
}
|
|
29
38
|
|
|
39
|
+
_getAvatarColor(name) {
|
|
40
|
+
// Generate consistent color based on name
|
|
41
|
+
const charCode = (name || 'S').charCodeAt(0);
|
|
42
|
+
return this.avatarColors[charCode % this.avatarColors.length];
|
|
43
|
+
}
|
|
44
|
+
|
|
30
45
|
_updateContent() {
|
|
31
46
|
const conversations = this.state.conversations;
|
|
32
|
-
const avatarsHtml = this._renderAvatarStack();
|
|
33
47
|
|
|
34
48
|
let conversationsHtml;
|
|
35
49
|
if (conversations.length === 0) {
|
|
36
50
|
conversationsHtml = `
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
<div class="messenger-empty-state">
|
|
52
|
+
<div class="messenger-empty-state-icon">
|
|
53
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="currentColor" viewBox="0 0 256 256">
|
|
54
|
+
<path d="M216,48H40A16,16,0,0,0,24,64V224a15.85,15.85,0,0,0,9.24,14.5A16.13,16.13,0,0,0,40,240a15.89,15.89,0,0,0,10.25-3.78.69.69,0,0,0,.13-.11L82.5,208H216a16,16,0,0,0,16-16V64A16,16,0,0,0,216,48ZM40,224h0ZM216,192H82.5a16,16,0,0,0-10.3,3.75l-.12.11L40,224V64H216Z"></path>
|
|
55
|
+
</svg>
|
|
56
|
+
</div>
|
|
57
|
+
<h3>No conversations yet</h3>
|
|
58
|
+
<p>Start a new conversation with our team</p>
|
|
59
|
+
</div>
|
|
60
|
+
`;
|
|
47
61
|
} else {
|
|
48
62
|
conversationsHtml = `
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
<div class="messenger-conversations-list">
|
|
64
|
+
${conversations.map((conv) => this._renderConversationItem(conv)).join('')}
|
|
65
|
+
</div>
|
|
66
|
+
`;
|
|
53
67
|
}
|
|
54
68
|
|
|
55
69
|
this.element.innerHTML = `
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
70
|
+
<div class="messenger-conversations-header">
|
|
71
|
+
<h2>Messages</h2>
|
|
72
|
+
<button class="sdk-close-btn" aria-label="Close">
|
|
73
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256">
|
|
74
|
+
<path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
|
|
75
|
+
</svg>
|
|
76
|
+
</button>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<div class="messenger-conversations-body">
|
|
80
|
+
${conversationsHtml}
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<div class="messenger-conversations-footer">
|
|
84
|
+
<button class="messenger-new-message-btn">
|
|
85
|
+
<span>Send us a message</span>
|
|
86
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 256 256" style="flex-shrink: 0;">
|
|
87
|
+
<rect width="256" height="256" fill="none"/>
|
|
88
|
+
<line x1="144" y1="128" x2="80" y2="128" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/>
|
|
89
|
+
<path d="M48.49,221.28A8,8,0,0,0,59.93,231l168-96.09a8,8,0,0,0,0-14l-168-95.85a8,8,0,0,0-11.44,9.67L80,128Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/>
|
|
90
|
+
</svg>
|
|
91
|
+
</button>
|
|
92
|
+
</div>
|
|
93
|
+
`;
|
|
79
94
|
|
|
80
95
|
this._attachEvents();
|
|
81
96
|
}
|
|
@@ -108,34 +123,41 @@ export class ConversationsView {
|
|
|
108
123
|
|
|
109
124
|
_renderConversationAvatars(participants) {
|
|
110
125
|
if (!participants || participants.length === 0) {
|
|
111
|
-
|
|
126
|
+
const color = this._getAvatarColor('S');
|
|
127
|
+
return `<div class="sdk-avatar sdk-avatar-md" style="background-color: ${color};">S</div>`;
|
|
112
128
|
}
|
|
113
129
|
|
|
114
130
|
const p = participants[0];
|
|
115
131
|
if (p.avatarUrl) {
|
|
116
132
|
return `<div class="sdk-avatar sdk-avatar-md"><img src="${p.avatarUrl}" alt="${p.name}" /></div>`;
|
|
117
133
|
}
|
|
118
|
-
|
|
134
|
+
const initial = (p.name || 'S').charAt(0).toUpperCase();
|
|
135
|
+
const color = this._getAvatarColor(p.name);
|
|
136
|
+
return `<div class="sdk-avatar sdk-avatar-md" style="background-color: ${color};">${initial}</div>`;
|
|
119
137
|
}
|
|
120
138
|
|
|
121
139
|
_renderAvatarStack() {
|
|
122
140
|
const avatars = this.state.teamAvatars;
|
|
123
141
|
if (!avatars || avatars.length === 0) {
|
|
142
|
+
const color1 = this._getAvatarColor('S');
|
|
143
|
+
const color2 = this._getAvatarColor('T');
|
|
124
144
|
return `
|
|
125
145
|
<div class="messenger-avatar-stack">
|
|
126
|
-
<div class="sdk-avatar sdk-avatar-sm">S</div>
|
|
127
|
-
<div class="sdk-avatar sdk-avatar-sm">T</div>
|
|
146
|
+
<div class="sdk-avatar sdk-avatar-sm" style="background-color: ${color1};">S</div>
|
|
147
|
+
<div class="sdk-avatar sdk-avatar-sm" style="background-color: ${color2};">T</div>
|
|
128
148
|
</div>
|
|
129
149
|
`;
|
|
130
150
|
}
|
|
131
151
|
|
|
132
152
|
const avatarItems = avatars
|
|
133
153
|
.slice(0, 2)
|
|
134
|
-
.map((avatar) => {
|
|
154
|
+
.map((avatar, index) => {
|
|
135
155
|
if (typeof avatar === 'string' && avatar.startsWith('http')) {
|
|
136
156
|
return `<div class="sdk-avatar sdk-avatar-sm"><img src="${avatar}" alt="Team member" /></div>`;
|
|
137
157
|
}
|
|
138
|
-
|
|
158
|
+
const initial = avatar.charAt(0).toUpperCase();
|
|
159
|
+
const color = this._getAvatarColor(avatar);
|
|
160
|
+
return `<div class="sdk-avatar sdk-avatar-sm" style="background-color: ${color};">${initial}</div>`;
|
|
139
161
|
})
|
|
140
162
|
.join('');
|
|
141
163
|
|
|
@@ -227,4 +249,4 @@ export class ConversationsView {
|
|
|
227
249
|
this.element.parentNode.removeChild(this.element);
|
|
228
250
|
}
|
|
229
251
|
}
|
|
230
|
-
}
|
|
252
|
+
}
|
|
@@ -24,39 +24,29 @@ export class HelpView {
|
|
|
24
24
|
_updateContent() {
|
|
25
25
|
const searchQuery = this.state.helpSearchQuery || '';
|
|
26
26
|
const collections = this.state.helpArticles || [];
|
|
27
|
-
const collectionCount = collections.length;
|
|
28
27
|
|
|
29
28
|
this.element.innerHTML = `
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
</div>
|
|
52
|
-
|
|
53
|
-
<div class="messenger-help-body">
|
|
54
|
-
<div class="messenger-help-collections-header">
|
|
55
|
-
${collectionCount} collections
|
|
56
|
-
</div>
|
|
57
|
-
<div class="messenger-help-collections"></div>
|
|
58
|
-
</div>
|
|
59
|
-
`;
|
|
29
|
+
<div class="messenger-help-header">
|
|
30
|
+
<div class="messenger-help-header-top">
|
|
31
|
+
<h2>Help</h2>
|
|
32
|
+
<button class="sdk-close-btn" aria-label="Close">
|
|
33
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 256 256">
|
|
34
|
+
<path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
|
|
35
|
+
</svg>
|
|
36
|
+
</button>
|
|
37
|
+
</div>
|
|
38
|
+
<input
|
|
39
|
+
type="text"
|
|
40
|
+
class="messenger-help-search-input"
|
|
41
|
+
placeholder="Search for help..."
|
|
42
|
+
value="${searchQuery}"
|
|
43
|
+
/>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div class="messenger-help-body">
|
|
47
|
+
<div class="messenger-help-collections"></div>
|
|
48
|
+
</div>
|
|
49
|
+
`;
|
|
60
50
|
|
|
61
51
|
this._updateCollectionsList();
|
|
62
52
|
this._attachEvents();
|
|
@@ -189,4 +179,4 @@ export class HelpView {
|
|
|
189
179
|
this.element.parentNode.removeChild(this.element);
|
|
190
180
|
}
|
|
191
181
|
}
|
|
192
|
-
}
|
|
182
|
+
}
|