@product7/feedback-sdk 1.6.0 → 1.6.3
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 +5 -5
- package/dist/README.md +5 -5
- package/dist/feedback-sdk.js +323 -181
- 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/index.js +12 -4
- package/src/styles/messenger-views.js +147 -23
- package/src/styles/survey.js +0 -10
- package/src/widgets/MessengerWidget.js +7 -1
- package/src/widgets/SurveyWidget.js +14 -10
- package/src/widgets/messenger/components/NavigationTabs.js +13 -36
- package/src/widgets/messenger/views/ChangelogView.js +21 -30
- package/src/widgets/messenger/views/HelpView.js +110 -68
|
@@ -28,20 +28,24 @@ export class HelpView {
|
|
|
28
28
|
<div class="messenger-help-header">
|
|
29
29
|
<div class="messenger-help-header-top">
|
|
30
30
|
<h2>Help</h2>
|
|
31
|
-
<button class="sdk-close-btn" aria-label="Close">
|
|
31
|
+
<button class="sdk-close-btn messenger-help-close-btn" aria-label="Close">
|
|
32
32
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 256 256">
|
|
33
33
|
<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>
|
|
34
34
|
</svg>
|
|
35
35
|
</button>
|
|
36
36
|
</div>
|
|
37
|
-
<
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
37
|
+
<div class="messenger-help-search-wrap">
|
|
38
|
+
<span class="messenger-help-search-icon">
|
|
39
|
+
<iconify-icon icon="ph:magnifying-glass-duotone" width="16" height="16"></iconify-icon>
|
|
40
|
+
</span>
|
|
41
|
+
<input
|
|
42
|
+
type="text"
|
|
43
|
+
class="messenger-help-search-input"
|
|
44
|
+
placeholder="Search for help..."
|
|
45
|
+
value="${searchQuery}"
|
|
46
|
+
/>
|
|
47
|
+
</div>
|
|
43
48
|
</div>
|
|
44
|
-
|
|
45
49
|
<div class="messenger-help-body">
|
|
46
50
|
<div class="messenger-help-collections"></div>
|
|
47
51
|
</div>
|
|
@@ -52,13 +56,11 @@ export class HelpView {
|
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
_updateCollectionsList() {
|
|
55
|
-
const
|
|
56
|
-
'.messenger-help-collections'
|
|
57
|
-
);
|
|
59
|
+
const container = this.element.querySelector('.messenger-help-collections');
|
|
58
60
|
const collections = this.state.helpArticles || [];
|
|
59
61
|
const searchQuery = (this.state.helpSearchQuery || '').toLowerCase();
|
|
60
62
|
|
|
61
|
-
const
|
|
63
|
+
const filtered = searchQuery
|
|
62
64
|
? collections.filter(
|
|
63
65
|
(c) =>
|
|
64
66
|
c.title.toLowerCase().includes(searchQuery) ||
|
|
@@ -66,51 +68,104 @@ export class HelpView {
|
|
|
66
68
|
)
|
|
67
69
|
: collections;
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (headerEl) {
|
|
73
|
-
headerEl.textContent = `${filteredCollections.length} collections`;
|
|
71
|
+
if (filtered.length === 0) {
|
|
72
|
+
container.innerHTML = this._renderEmptyState();
|
|
73
|
+
return;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
container.innerHTML = filtered.map((c) => this._renderCollectionItem(c)).join('');
|
|
77
|
+
this._attachCollectionEvents();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
_avatarColors = [
|
|
81
|
+
{ bg: '#EF4444', text: '#FFFFFF' },
|
|
82
|
+
{ bg: '#F97316', text: '#FFFFFF' },
|
|
83
|
+
{ bg: '#F59E0B', text: '#FFFFFF' },
|
|
84
|
+
{ bg: '#10B981', text: '#FFFFFF' },
|
|
85
|
+
{ bg: '#06B6D4', text: '#FFFFFF' },
|
|
86
|
+
{ bg: '#3B82F6', text: '#FFFFFF' },
|
|
87
|
+
{ bg: '#8B5CF6', text: '#FFFFFF' },
|
|
88
|
+
{ bg: '#EC4899', text: '#FFFFFF' },
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
_getAvatarColor(id) {
|
|
92
|
+
const hash = id.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
|
|
93
|
+
return this._avatarColors[hash % this._avatarColors.length];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
_getInitials(name) {
|
|
97
|
+
if (!name) return 'A';
|
|
98
|
+
return name.split(' ').map((n) => n[0]).join('').toUpperCase().slice(0, 2);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
_renderAuthorAvatar(collection) {
|
|
102
|
+
if (collection.author?.picture) {
|
|
103
|
+
return `<img
|
|
104
|
+
src="${collection.author.picture}"
|
|
105
|
+
alt="${collection.author.name || ''}"
|
|
106
|
+
class="messenger-help-collection-avatar"
|
|
107
|
+
title="${collection.author.name || ''}"
|
|
108
|
+
/>`;
|
|
79
109
|
}
|
|
80
110
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
.join('');
|
|
111
|
+
const { bg, text } = this._getAvatarColor(collection.id);
|
|
112
|
+
const initials = collection.author?.name ? this._getInitials(collection.author.name) : 'A';
|
|
84
113
|
|
|
85
|
-
|
|
114
|
+
return `<span
|
|
115
|
+
class="messenger-help-collection-avatar messenger-help-collection-avatar--initials"
|
|
116
|
+
style="background-color: ${bg}; color: ${text};"
|
|
117
|
+
title="${collection.author?.name || 'Author'}"
|
|
118
|
+
>${initials}</span>`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
_resolveCollectionIcon(icon) {
|
|
122
|
+
if (!icon) return this._defaultCollectionIcon();
|
|
123
|
+
|
|
124
|
+
if (icon.trimStart().startsWith('<')) {
|
|
125
|
+
return `<span class="messenger-help-collection-icon">${icon}</span>`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (icon.startsWith('ph:')) {
|
|
129
|
+
return `<span class="messenger-help-collection-icon">
|
|
130
|
+
<iconify-icon icon="${icon}" width="18" height="18"></iconify-icon>
|
|
131
|
+
</span>`;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return this._defaultCollectionIcon();
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
_defaultCollectionIcon() {
|
|
138
|
+
return `<span class="messenger-help-collection-icon">
|
|
139
|
+
<iconify-icon icon="ph:book-open-duotone" width="18" height="18"></iconify-icon>
|
|
140
|
+
</span>`;
|
|
86
141
|
}
|
|
87
142
|
|
|
88
143
|
_renderCollectionItem(collection) {
|
|
89
144
|
const articleCount = collection.articleCount || 0;
|
|
145
|
+
|
|
90
146
|
return `
|
|
91
147
|
<div class="messenger-help-collection" data-collection-id="${collection.id}">
|
|
148
|
+
${this._resolveCollectionIcon(collection.icon)}
|
|
92
149
|
<div class="messenger-help-collection-content">
|
|
93
|
-
<
|
|
94
|
-
|
|
95
|
-
<
|
|
150
|
+
<div class="messenger-help-collection-title">${collection.title}</div>
|
|
151
|
+
${collection.description ? `<p class="messenger-help-collection-desc">${collection.description}</p>` : ''}
|
|
152
|
+
<div class="messenger-help-collection-meta">
|
|
153
|
+
${this._renderAuthorAvatar(collection)}
|
|
154
|
+
<span class="messenger-help-collection-count">
|
|
155
|
+
${articleCount} ${articleCount === 1 ? 'article' : 'articles'}
|
|
156
|
+
</span>
|
|
157
|
+
</div>
|
|
96
158
|
</div>
|
|
97
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256" class="messenger-help-collection-arrow">
|
|
98
|
-
<path d="M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z"></path>
|
|
99
|
-
</svg>
|
|
100
159
|
</div>
|
|
101
160
|
`;
|
|
102
161
|
}
|
|
103
162
|
|
|
104
163
|
_renderEmptyState() {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
if (isSearching) {
|
|
164
|
+
if (this.state.helpSearchQuery) {
|
|
108
165
|
return `
|
|
109
166
|
<div class="messenger-empty-state">
|
|
110
167
|
<div class="messenger-empty-state-icon">
|
|
111
|
-
<
|
|
112
|
-
<path d="M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"></path>
|
|
113
|
-
</svg>
|
|
168
|
+
<iconify-icon icon="ph:magnifying-glass-duotone" width="48" height="48"></iconify-icon>
|
|
114
169
|
</div>
|
|
115
170
|
<h3>No results found</h3>
|
|
116
171
|
<p>Try a different search term</p>
|
|
@@ -121,9 +176,7 @@ export class HelpView {
|
|
|
121
176
|
return `
|
|
122
177
|
<div class="messenger-empty-state">
|
|
123
178
|
<div class="messenger-empty-state-icon">
|
|
124
|
-
<
|
|
125
|
-
<path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm16-40a8,8,0,0,1-8,8,16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40A8,8,0,0,1,144,176ZM112,84a12,12,0,1,1,12,12A12,12,0,0,1,112,84Z"></path>
|
|
126
|
-
</svg>
|
|
179
|
+
<iconify-icon icon="ph:books-duotone" width="48" height="48"></iconify-icon>
|
|
127
180
|
</div>
|
|
128
181
|
<h3>Help collections</h3>
|
|
129
182
|
<p>No collections available yet</p>
|
|
@@ -132,15 +185,11 @@ export class HelpView {
|
|
|
132
185
|
}
|
|
133
186
|
|
|
134
187
|
_attachEvents() {
|
|
135
|
-
this.element
|
|
136
|
-
.
|
|
137
|
-
|
|
138
|
-
this.state.setOpen(false);
|
|
139
|
-
});
|
|
188
|
+
this.element.querySelector('.messenger-help-close-btn').addEventListener('click', () => {
|
|
189
|
+
this.state.setOpen(false);
|
|
190
|
+
});
|
|
140
191
|
|
|
141
|
-
const searchInput = this.element.querySelector(
|
|
142
|
-
'.messenger-help-search-input'
|
|
143
|
-
);
|
|
192
|
+
const searchInput = this.element.querySelector('.messenger-help-search-input');
|
|
144
193
|
let searchTimeout;
|
|
145
194
|
searchInput.addEventListener('input', (e) => {
|
|
146
195
|
clearTimeout(searchTimeout);
|
|
@@ -153,29 +202,22 @@ export class HelpView {
|
|
|
153
202
|
}
|
|
154
203
|
|
|
155
204
|
_attachCollectionEvents() {
|
|
156
|
-
this.element
|
|
157
|
-
.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
} else if (this.options.onArticleClick) {
|
|
167
|
-
this.options.onArticleClick(collection);
|
|
168
|
-
}
|
|
169
|
-
});
|
|
205
|
+
this.element.querySelectorAll('.messenger-help-collection').forEach((item) => {
|
|
206
|
+
item.addEventListener('click', () => {
|
|
207
|
+
const collection = this.state.helpArticles.find(
|
|
208
|
+
(c) => c.id === item.dataset.collectionId
|
|
209
|
+
);
|
|
210
|
+
if (collection?.url) {
|
|
211
|
+
window.open(collection.url, '_blank');
|
|
212
|
+
} else if (this.options.onArticleClick) {
|
|
213
|
+
this.options.onArticleClick(collection);
|
|
214
|
+
}
|
|
170
215
|
});
|
|
216
|
+
});
|
|
171
217
|
}
|
|
172
218
|
|
|
173
219
|
destroy() {
|
|
174
|
-
if (this._unsubscribe)
|
|
175
|
-
|
|
176
|
-
}
|
|
177
|
-
if (this.element && this.element.parentNode) {
|
|
178
|
-
this.element.parentNode.removeChild(this.element);
|
|
179
|
-
}
|
|
220
|
+
if (this._unsubscribe) this._unsubscribe();
|
|
221
|
+
if (this.element?.parentNode) this.element.parentNode.removeChild(this.element);
|
|
180
222
|
}
|
|
181
|
-
}
|
|
223
|
+
}
|