@subiz/widget-v4 4.0.88 → 4.0.90
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/assets/less/chatbox.less +2 -0
- package/compiled_src/chatbox/Event.js +4 -5
- package/compiled_src/chatbox/TextMessage.js +104 -9
- package/compiled_src/chatbox/Widget.js +58 -8
- package/compiled_src/util/common.js +1 -1
- package/package.json +8 -8
- package/src/chatbox/Event.js +3 -4
- package/src/chatbox/TextMessage.js +82 -15
- package/src/chatbox/Widget.js +54 -4
- package/src/util/common.js +1 -1
- package/dist/132.js +0 -6950
- package/dist/178.js +0 -406
- package/dist/182ee177a49.132.js +0 -1
- package/dist/182ee177a49.178.js +0 -1
- package/dist/182ee177a49.213.js +0 -1
- package/dist/182ee177a49.335.js +0 -1
- package/dist/182ee177a49.362.js +0 -1
- package/dist/182ee177a49.441.js +0 -1
- package/dist/182ee177a49.605.js +0 -1
- package/dist/182ee177a49.678.js +0 -1
- package/dist/182ee177a49.782.js +0 -1
- package/dist/182ee177a49.app.js +0 -1
- package/dist/182ee177a49.index.html +0 -26
- package/dist/182ee177a49.library.html +0 -26
- package/dist/182ee177a49.library.js +0 -1
- package/dist/182ee177a49.preview.html +0 -759
- package/dist/182ee177a49.preview.js +0 -1
- package/dist/182ee177a49.screenshoot.js +0 -1
- package/dist/213.js +0 -3215
- package/dist/335.js +0 -411
- package/dist/362.js +0 -107
- package/dist/441.js +0 -2827
- package/dist/605.js +0 -328
- package/dist/678.js +0 -107
- package/dist/782.js +0 -107
- package/dist/HASH +0 -1
- package/dist/assets/img/Facebook.64607ec.png +0 -0
- package/dist/assets/img/Zalo.6845707.png +0 -0
- package/dist/assets/img/award1a.1a58e10.png +0 -0
- package/dist/assets/img/award3a.3b74423.png +0 -0
- package/dist/assets/img/award4a.ed6ccd4.png +0 -0
- package/dist/assets/img/award5.39eb7ae.png +0 -0
- package/dist/assets/img/bubble_default.7d5e4ab.svg +0 -20
- package/dist/assets/img/caret.998eb8f.svg +0 -1
- package/dist/assets/img/convos_empty.2353007.svg +0 -72
- package/dist/assets/img/default.06e6ee0.jpg +0 -0
- package/dist/assets/img/default_avatar.5b74dc1.png +0 -0
- package/dist/assets/img/done_gray.d7e8203.svg +0 -4
- package/dist/assets/img/done_green.b817fd4.svg +0 -4
- package/dist/assets/img/emoji/messenger/sub_23.529_58.824.d5faf14.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_23.529_60.784.1420241.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_25.490_0.000.1e6b2c0.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_25.490_45.098.3dfbc08.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_25.490_5.882.4b49e94.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_27.451_72.549.7114f58.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_27.451_84.314.231e2b7.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_27.451_96.078.ddbb008.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_29.412_5.882.61f3359.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_100.000.6df72bc.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_45.098.3d7a7ad.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_47.059.0f4d6e2.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_54.902.65724c1.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_64.706.9da3cba.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_72.549.edca5cf.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_78.431.f910f2a.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_58.824_88.235.def4e71.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_60.784_11.765.49c03d0.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_60.784_27.451.46b54e5.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_60.784_29.412.e36d284.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_60.784_3.922.bb191b0.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_60.784_35.294.af7b927.png +0 -0
- package/dist/assets/img/emoji/messenger/sub_60.784_7.843.98f2a99.png +0 -0
- package/dist/assets/img/empty.29bed2d.svg +0 -23
- package/dist/assets/img/empty_1.0b98af0.svg +0 -11
- package/dist/assets/img/examplte_logo.f86535f.svg +0 -1
- package/dist/assets/img/external-link.90577cc.svg +0 -1
- package/dist/assets/img/fb_inverse_circle.36c2cfc.png +0 -0
- package/dist/assets/img/ghn.070f8e3.svg +0 -17
- package/dist/assets/img/ghtk.326eac1.svg +0 -18
- package/dist/assets/img/image_default.be0698b.png +0 -0
- package/dist/assets/img/info.ebce7ea.svg +0 -1
- package/dist/assets/img/loader.37000a7.svg +0 -1
- package/dist/assets/img/loading_static.8f403ae.svg +0 -10
- package/dist/assets/img/main-service1.d536cc2.png +0 -0
- package/dist/assets/img/main-service2.9b99549.png +0 -0
- package/dist/assets/img/not_found_search.2ddb8d1.png +0 -0
- package/dist/assets/img/package.8d37d0f.svg +0 -5
- package/dist/assets/img/package_fade.763c001.svg +0 -1
- package/dist/assets/img/rating--average.1ea492c.svg +0 -12
- package/dist/assets/img/rating--great.e3d712e.svg +0 -16
- package/dist/assets/img/rating--poor.2938a25.svg +0 -12
- package/dist/assets/img/search.f9705ff.svg +0 -1
- package/dist/assets/img/send.6db52a9.svg +0 -3
- package/dist/assets/img/shop.f7dc7d8.svg +0 -1
- package/dist/assets/img/shop_faded.df7845a.svg +0 -1
- package/dist/assets/img/subiz-mono.877e9f5.svg +0 -3
- package/dist/assets/img/x.26fdfa3.svg +0 -5
- package/dist/malicious-app.js +0 -13
- package/dist/screenshoot.html +0 -7
- package/dist/screenshoot.js +0 -5953
package/assets/less/chatbox.less
CHANGED
|
@@ -128,7 +128,7 @@ class Event extends _common.Com {
|
|
|
128
128
|
|
|
129
129
|
var uri = acc.logo_url || require('../../assets/img/image_default.png');
|
|
130
130
|
|
|
131
|
-
if (
|
|
131
|
+
if (_index.default.get(this.props, 'chatbox.hide_agent_profile')) {
|
|
132
132
|
return (0, _preact.h)("div", {
|
|
133
133
|
class: "message-sender"
|
|
134
134
|
}, (0, _preact.h)("img", {
|
|
@@ -142,7 +142,7 @@ class Event extends _common.Com {
|
|
|
142
142
|
|
|
143
143
|
let agentM = this.props.store.matchAgent('*');
|
|
144
144
|
|
|
145
|
-
if (byid !== 'system'
|
|
145
|
+
if (byid !== 'system' && bytype !== 'dummy' && bytype !== 'workflow') {
|
|
146
146
|
uri = _index.default.get(agentM[byid], 'avatar_url') || acc.logo_url || require('../../assets/img/default_avatar.png');
|
|
147
147
|
}
|
|
148
148
|
|
|
@@ -330,11 +330,10 @@ class Event extends _common.Com {
|
|
|
330
330
|
|
|
331
331
|
let byid = _index.default.get(ev, 'by.display_id', _index.default.get(ev, 'by.id'));
|
|
332
332
|
|
|
333
|
-
if (
|
|
334
|
-
let user = this.props.store.matchUser();
|
|
333
|
+
if (bytype === 'user') return _index.default.getUserDisplayName(this.props.store.matchUser());
|
|
335
334
|
let acc = this.props.store.matchAccount();
|
|
336
|
-
if (bytype === 'user') return _index.default.getUserDisplayName(user);
|
|
337
335
|
if (bytype === 'agent') return _index.default.getAgentDisplayName(acc, this.props.store.matchAgent(byid));
|
|
336
|
+
if (byid === 'system' || bytype === 'dummy' || bytype === 'workflow') return acc.name || 'system';
|
|
338
337
|
return '';
|
|
339
338
|
}
|
|
340
339
|
|
|
@@ -100,19 +100,86 @@ class TextMessage extends _common.Com {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
renderDelta() {
|
|
103
|
-
let deltas = _index.default.get(this.props.ev, 'data.message.quill_delta');
|
|
103
|
+
let deltas = _index.default.get(this.props.ev, 'data.message.quill_delta') || _index.default.get(this.props.ev, 'data.message.text');
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
let quilldeltas = _index.default.parseJSON(deltas) || {};
|
|
106
|
+
quilldeltas = trimQuillDelta(quilldeltas);
|
|
107
|
+
if (!quilldeltas || _index.default.size(quilldeltas.ops) === 0) return null;
|
|
107
108
|
|
|
108
|
-
let
|
|
109
|
+
let $deltas = _index.default.map(quilldeltas.ops, delta => {
|
|
110
|
+
let html = '';
|
|
111
|
+
let insert = delta.insert;
|
|
112
|
+
let attributes = delta.attributes;
|
|
109
113
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
if (insert.dynamicField) {
|
|
115
|
+
return _index.default.get(insert, 'dynamicField.text', '');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (insert.mention) {
|
|
119
|
+
if (insert.mention.id == '*' || insert.mention.id == 'all') {
|
|
120
|
+
return (0, _preact.h)("span", {
|
|
121
|
+
class: "mention"
|
|
122
|
+
}, "@", this.$t('all'));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
let ag = store.matchAgent(insert.mention.id);
|
|
126
|
+
|
|
127
|
+
let name = _index.default.getAgentDisplayName(ag, insert.mention.fullname);
|
|
128
|
+
|
|
129
|
+
return (0, _preact.h)("span", {
|
|
130
|
+
class: "mention",
|
|
131
|
+
"data-agent-id": ag.id,
|
|
132
|
+
"data-agent-fullname": name
|
|
133
|
+
}, "@", name);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (insert.emoji) return (0, _preact.h)(_Emoji.default, {
|
|
137
|
+
emojiCode: `:${insert.emoji}:`
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
if (typeof insert === 'string') {
|
|
141
|
+
let $tags = _index.default.extractText(insert).map((tag, i) => {
|
|
142
|
+
if (tag.type === 'link') {
|
|
143
|
+
return (0, _preact.h)("a", {
|
|
144
|
+
href: absLink(tag.text),
|
|
145
|
+
target: "_blank"
|
|
146
|
+
}, tag.text);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return tag.text;
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
if (attributes) {
|
|
153
|
+
if (attributes.italic && attributes.bold) return (0, _preact.h)("span", {
|
|
154
|
+
style: "font-weight: bold; font-style: italic"
|
|
155
|
+
}, $tags);
|
|
156
|
+
if (attributes.italic) return (0, _preact.h)("span", {
|
|
157
|
+
style: "font-style: italic"
|
|
158
|
+
}, $tags);
|
|
159
|
+
if (attributes.bold) return (0, _preact.h)("span", {
|
|
160
|
+
style: "font-weight: bold"
|
|
161
|
+
}, $tags);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return (0, _preact.h)("span", null, $tags);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return null;
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
let byType = _index.default.get(this.ev, 'by.type');
|
|
171
|
+
|
|
172
|
+
if (_index.default.size($deltas) === 0) return null;
|
|
173
|
+
|
|
174
|
+
if (byType === 'agent') {
|
|
175
|
+
return (0, _preact.h)("div", {
|
|
176
|
+
class: "message-agent message-text--agent"
|
|
177
|
+
}, $deltas);
|
|
113
178
|
}
|
|
114
179
|
|
|
115
|
-
return
|
|
180
|
+
return (0, _preact.h)("div", {
|
|
181
|
+
class: "message-user message-text--user"
|
|
182
|
+
}, $deltas);
|
|
116
183
|
}
|
|
117
184
|
|
|
118
185
|
renderMarkdown(text) {
|
|
@@ -187,4 +254,32 @@ const emojiCodes = {
|
|
|
187
254
|
tired: '😩',
|
|
188
255
|
surprised: '😮',
|
|
189
256
|
wink: '😉'
|
|
190
|
-
};
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
function trimQuillDelta(delta) {
|
|
260
|
+
if (!delta) return delta;
|
|
261
|
+
if (!delta.ops || !delta.ops.length) return delta;
|
|
262
|
+
let last = delta.ops[delta.ops.length - 1];
|
|
263
|
+
if (typeof last.insert != 'string') return delta;
|
|
264
|
+
let insert = last.insert.trim();
|
|
265
|
+
|
|
266
|
+
if (insert) {
|
|
267
|
+
if (last.insert != insert) {
|
|
268
|
+
let newops = delta.ops.slice();
|
|
269
|
+
let last = newops.pop();
|
|
270
|
+
last.insert = insert;
|
|
271
|
+
newops.push(last);
|
|
272
|
+
return {
|
|
273
|
+
ops: newops
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return delta;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
let newops = delta.ops.slice();
|
|
281
|
+
newops.pop();
|
|
282
|
+
return trimQuillDelta({
|
|
283
|
+
ops: newops
|
|
284
|
+
});
|
|
285
|
+
}
|
|
@@ -54,6 +54,14 @@ class Widget extends _common.Com {
|
|
|
54
54
|
_defineProperty(this, "msgInput", (0, _preact.createRef)());
|
|
55
55
|
|
|
56
56
|
_defineProperty(this, "sendMessage", async message => {
|
|
57
|
+
let hasPostback = _index.default.find(message.attachments, att => att.type === 'postback');
|
|
58
|
+
|
|
59
|
+
if (this.isFormRequired() && hasPostback) {
|
|
60
|
+
this.onStartConvoClick();
|
|
61
|
+
this.fillQuickReplyToQuestion(message);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
57
65
|
let text = message.text;
|
|
58
66
|
|
|
59
67
|
if (!this.props.cid) {
|
|
@@ -115,7 +123,8 @@ class Widget extends _common.Com {
|
|
|
115
123
|
clickedJoin: false,
|
|
116
124
|
formData: {},
|
|
117
125
|
showOrder: false,
|
|
118
|
-
order_id: ''
|
|
126
|
+
order_id: '',
|
|
127
|
+
quickReplyMessage: {}
|
|
119
128
|
});
|
|
120
129
|
this.props.store.onUpdate(this, _ => this.forceUpdate());
|
|
121
130
|
}
|
|
@@ -133,7 +142,8 @@ class Widget extends _common.Com {
|
|
|
133
142
|
if (prevProp.cid !== this.props.cid) {
|
|
134
143
|
this.closeOrder();
|
|
135
144
|
this.setState({
|
|
136
|
-
clickedJoin: false
|
|
145
|
+
clickedJoin: false,
|
|
146
|
+
quickReplyMessage: {}
|
|
137
147
|
});
|
|
138
148
|
setTimeout(() => {
|
|
139
149
|
this.events && this.events.focus();
|
|
@@ -145,6 +155,15 @@ class Widget extends _common.Com {
|
|
|
145
155
|
}
|
|
146
156
|
|
|
147
157
|
shouldShowForm() {
|
|
158
|
+
let form;
|
|
159
|
+
let accountSetting = this.props.plugin.chatbox || {};
|
|
160
|
+
let acc = this.props.store.matchAccount() || {};
|
|
161
|
+
if (_index.default.get(accountSetting, 'prechat_form.enabled')) form = accountSetting.prechat_form;
|
|
162
|
+
|
|
163
|
+
let offlineEnabled = _index.default.get(accountSetting, 'offline_form.enabled');
|
|
164
|
+
|
|
165
|
+
if (this.isOffline(acc, accountSetting) && offlineEnabled) form = accountSetting.offline_form;
|
|
166
|
+
if (!this.hasSentMessage(this.props.cid) && form && (_index.default.size(form.groups) || form.group_required)) return true;
|
|
148
167
|
let formRequired = this.isFormRequired();
|
|
149
168
|
return formRequired && !this.props.cid || formRequired && this.props.cid && this.state.clickedJoin;
|
|
150
169
|
}
|
|
@@ -260,9 +279,13 @@ class Widget extends _common.Com {
|
|
|
260
279
|
fields: [{
|
|
261
280
|
key: 'to_agent_group',
|
|
262
281
|
value: _index.default.stringify(groupid)
|
|
263
|
-
}]
|
|
282
|
+
}],
|
|
283
|
+
attachments: this.state.quickReplyMessage.attachments
|
|
264
284
|
}
|
|
265
285
|
});
|
|
286
|
+
this.setState({
|
|
287
|
+
quickReplyMessage: {}
|
|
288
|
+
});
|
|
266
289
|
if (form.end_conversation_after_submit) await this.props.store.endConvo(this.props.cid);
|
|
267
290
|
return;
|
|
268
291
|
}
|
|
@@ -308,7 +331,8 @@ class Widget extends _common.Com {
|
|
|
308
331
|
});
|
|
309
332
|
this.setState({
|
|
310
333
|
creating: false,
|
|
311
|
-
clickedJoin: false
|
|
334
|
+
clickedJoin: false,
|
|
335
|
+
quickReplyMessage: {}
|
|
312
336
|
});
|
|
313
337
|
if (!this.props.store.isMobile()) this.focusInput();
|
|
314
338
|
}
|
|
@@ -319,7 +343,8 @@ class Widget extends _common.Com {
|
|
|
319
343
|
key: 'question',
|
|
320
344
|
is_required: true,
|
|
321
345
|
label: this.props.t.i18n(_index.default.get(form, `i18n_question_label`, {})) || form.question_label,
|
|
322
|
-
type: 'text'
|
|
346
|
+
type: 'text',
|
|
347
|
+
value: this.state.quickReplyMessage.text
|
|
323
348
|
};
|
|
324
349
|
this.setState({
|
|
325
350
|
formData
|
|
@@ -381,6 +406,7 @@ class Widget extends _common.Com {
|
|
|
381
406
|
if (_index.default.size(this.state.formData) === 0) return null;
|
|
382
407
|
|
|
383
408
|
let $fields = _index.default.map(this.state.formData, (field, key) => {
|
|
409
|
+
if (this.state.quickReplyMessage.text && key === 'question') return null;
|
|
384
410
|
let $field = null;
|
|
385
411
|
var errclass = field.error ? 'input--error' : '';
|
|
386
412
|
|
|
@@ -648,6 +674,19 @@ class Widget extends _common.Com {
|
|
|
648
674
|
this.focusInput();
|
|
649
675
|
}
|
|
650
676
|
|
|
677
|
+
fillQuickReplyToQuestion(message) {
|
|
678
|
+
let formData = this.state.formData;
|
|
679
|
+
|
|
680
|
+
if (formData) {
|
|
681
|
+
_index.default.set(formData, 'question.value', message.text);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
this.setState({
|
|
685
|
+
formData,
|
|
686
|
+
quickReplyMessage: message
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
|
|
651
690
|
createPostback(postback) {
|
|
652
691
|
this.props.store.createPostback(this.props.cid, postback);
|
|
653
692
|
}
|
|
@@ -718,7 +757,8 @@ class Widget extends _common.Com {
|
|
|
718
757
|
cid: ''
|
|
719
758
|
});
|
|
720
759
|
this.setState({
|
|
721
|
-
clickedJoin: true
|
|
760
|
+
clickedJoin: true,
|
|
761
|
+
quickReplyMessage: {}
|
|
722
762
|
});
|
|
723
763
|
}
|
|
724
764
|
|
|
@@ -745,9 +785,8 @@ class Widget extends _common.Com {
|
|
|
745
785
|
let formData = this.fillForm(form);
|
|
746
786
|
let convo = this.props.store.matchConvo(this.props.cid) || {};
|
|
747
787
|
if (convo.state === 'ended') return true;
|
|
748
|
-
if (this.userHasSent(this.props.cid)) return false;
|
|
749
788
|
if (convo.state && convo.state !== 'pending') delete formData.group;
|
|
750
|
-
return !!_index.default.find(formData, field => field.value == null || field.value === '');
|
|
789
|
+
return !!_index.default.find(formData, field => field.is_required && (field.value == null || field.value === ''));
|
|
751
790
|
}
|
|
752
791
|
|
|
753
792
|
renderConvoSummary(convo) {
|
|
@@ -868,6 +907,17 @@ class Widget extends _common.Com {
|
|
|
868
907
|
return joined;
|
|
869
908
|
}
|
|
870
909
|
|
|
910
|
+
hasSentMessage(cid) {
|
|
911
|
+
let convo = this.props.store.matchConvo(cid) || {};
|
|
912
|
+
|
|
913
|
+
let joined = _index.default.find(convo.members, mem => {
|
|
914
|
+
if (mem.type === 'bot') return true;
|
|
915
|
+
return mem.last_sent;
|
|
916
|
+
});
|
|
917
|
+
|
|
918
|
+
return joined;
|
|
919
|
+
}
|
|
920
|
+
|
|
871
921
|
isOffline(acc, accSetting) {
|
|
872
922
|
let enableWhen = _index.default.get(accSetting, 'offline_form.enable_when');
|
|
873
923
|
|
|
@@ -894,7 +894,7 @@ function checkRunConditions(freq, conds, lastrun, store) {
|
|
|
894
894
|
|
|
895
895
|
case 'source':
|
|
896
896
|
if (size(cond.sources) > 0) {
|
|
897
|
-
let source = store.matchTrafficSource();
|
|
897
|
+
let source = store.matchTrafficSource() || 'direct';
|
|
898
898
|
if (!find(cond.sources, src => norm(src) === norm(source))) return false;
|
|
899
899
|
}
|
|
900
900
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subiz/widget-v4",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.90",
|
|
4
4
|
"main": "./compiled_src/lib.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "npx webpack serve --config webpack.dev.js",
|
|
@@ -14,28 +14,28 @@
|
|
|
14
14
|
"@subiz/storage": "0.0.8",
|
|
15
15
|
"@subiz/wsclient": "^3.1.7",
|
|
16
16
|
"cookie_js": "1.4.2",
|
|
17
|
-
"core-js": "^3.25.
|
|
17
|
+
"core-js": "^3.25.2",
|
|
18
18
|
"css-loader": "5.2.7",
|
|
19
19
|
"file-loader": "^6.2.0",
|
|
20
20
|
"less": "^4.1.3",
|
|
21
21
|
"less-loader": "^11.0.0",
|
|
22
22
|
"marked": "^4.1.0",
|
|
23
|
-
"preact": "^10.
|
|
23
|
+
"preact": "^10.11.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@babel/cli": "^7.18.10",
|
|
27
|
-
"@babel/core": "^7.
|
|
27
|
+
"@babel/core": "^7.19.1",
|
|
28
28
|
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
|
29
|
-
"@babel/plugin-transform-react-jsx": "^7.
|
|
30
|
-
"@babel/preset-env": "^7.
|
|
29
|
+
"@babel/plugin-transform-react-jsx": "^7.19.0",
|
|
30
|
+
"@babel/preset-env": "^7.19.1",
|
|
31
31
|
"babel-loader": "^8.2.5",
|
|
32
32
|
"babel-plugin-syntax-jsx": "^6.18.0",
|
|
33
33
|
"html-webpack-plugin": "^5.5.0",
|
|
34
34
|
"prettier": "^2.7.1",
|
|
35
|
-
"puppeteer": "^
|
|
35
|
+
"puppeteer": "^17.1.3",
|
|
36
36
|
"webpack": "^5.74.0",
|
|
37
37
|
"webpack-bundle-analyzer": "^4.6.1",
|
|
38
38
|
"webpack-cli": "^4.10.0",
|
|
39
|
-
"webpack-dev-server": "^4.
|
|
39
|
+
"webpack-dev-server": "^4.11.1"
|
|
40
40
|
}
|
|
41
41
|
}
|
package/src/chatbox/Event.js
CHANGED
|
@@ -101,7 +101,7 @@ export default class Event extends Com {
|
|
|
101
101
|
|
|
102
102
|
let agentM = this.props.store.matchAgent('*')
|
|
103
103
|
// should replace with subiz logo
|
|
104
|
-
if (byid !== 'system'
|
|
104
|
+
if (byid !== 'system' && bytype !== 'dummy' && bytype !== 'workflow') {
|
|
105
105
|
uri = sb.get(agentM[byid], 'avatar_url') || acc.logo_url || require('../../assets/img/default_avatar.png')
|
|
106
106
|
}
|
|
107
107
|
|
|
@@ -227,11 +227,10 @@ export default class Event extends Com {
|
|
|
227
227
|
getSenderName(ev) {
|
|
228
228
|
let bytype = sb.get(ev, 'by.type')
|
|
229
229
|
let byid = sb.get(ev, 'by.display_id', sb.get(ev, 'by.id'))
|
|
230
|
-
if (
|
|
231
|
-
let user = this.props.store.matchUser()
|
|
230
|
+
if (bytype === 'user') return sb.getUserDisplayName(this.props.store.matchUser())
|
|
232
231
|
let acc = this.props.store.matchAccount()
|
|
233
|
-
if (bytype === 'user') return sb.getUserDisplayName(user)
|
|
234
232
|
if (bytype === 'agent') return sb.getAgentDisplayName(acc, this.props.store.matchAgent(byid))
|
|
233
|
+
if (byid === 'system' || bytype === 'dummy' || bytype === 'workflow') return acc.name || 'system'
|
|
235
234
|
return ''
|
|
236
235
|
}
|
|
237
236
|
}
|
|
@@ -65,22 +65,61 @@ export default class TextMessage extends Com {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
renderDelta() {
|
|
68
|
-
let deltas = sb.get(this.props.ev, 'data.message.quill_delta')
|
|
69
|
-
|
|
70
|
-
deltas = deltas.ops || []
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
68
|
+
let deltas = sb.get(this.props.ev, 'data.message.quill_delta') || sb.get(this.props.ev, 'data.message.text')
|
|
69
|
+
let quilldeltas = sb.parseJSON(deltas) || {}
|
|
70
|
+
// deltas = deltas.ops || []
|
|
71
|
+
quilldeltas = trimQuillDelta(quilldeltas)
|
|
72
|
+
if (!quilldeltas || sb.size(quilldeltas.ops) === 0) return null
|
|
73
|
+
let $deltas = sb.map(quilldeltas.ops, (delta) => {
|
|
74
|
+
let html = ''
|
|
75
|
+
let insert = delta.insert
|
|
76
|
+
let attributes = delta.attributes
|
|
77
|
+
|
|
78
|
+
if (insert.dynamicField) {
|
|
79
|
+
return sb.get(insert, 'dynamicField.text', '')
|
|
80
|
+
}
|
|
81
|
+
if (insert.mention) {
|
|
82
|
+
if (insert.mention.id == '*' || insert.mention.id == 'all') {
|
|
83
|
+
return <span class='mention'>@{this.$t('all')}</span>
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
let ag = store.matchAgent(insert.mention.id)
|
|
87
|
+
let name = sb.getAgentDisplayName(ag, insert.mention.fullname)
|
|
88
|
+
return (
|
|
89
|
+
<span class='mention' data-agent-id={ag.id} data-agent-fullname={name}>
|
|
90
|
+
@{name}
|
|
91
|
+
</span>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
if (insert.emoji) return <Emoji emojiCode={`:${insert.emoji}:`} />
|
|
95
|
+
if (typeof insert === 'string') {
|
|
96
|
+
let $tags = sb.extractText(insert).map((tag, i) => {
|
|
97
|
+
if (tag.type === 'link') {
|
|
98
|
+
return (
|
|
99
|
+
<a href={absLink(tag.text)} target='_blank'>
|
|
100
|
+
{tag.text}
|
|
101
|
+
</a>
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
return tag.text
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
if (attributes) {
|
|
108
|
+
if (attributes.italic && attributes.bold)
|
|
109
|
+
return <span style='font-weight: bold; font-style: italic'>{$tags}</span>
|
|
110
|
+
if (attributes.italic) return <span style='font-style: italic'>{$tags}</span>
|
|
111
|
+
if (attributes.bold) return <span style='font-weight: bold'>{$tags}</span>
|
|
112
|
+
}
|
|
113
|
+
return <span>{$tags}</span>
|
|
114
|
+
}
|
|
115
|
+
return null
|
|
116
|
+
})
|
|
117
|
+
let byType = sb.get(this.ev, 'by.type')
|
|
118
|
+
if (sb.size($deltas) === 0) return null
|
|
119
|
+
if (byType === 'agent') {
|
|
120
|
+
return <div class='message-agent message-text--agent'>{$deltas}</div>
|
|
82
121
|
}
|
|
83
|
-
return
|
|
122
|
+
return <div class='message-user message-text--user'>{$deltas}</div>
|
|
84
123
|
}
|
|
85
124
|
|
|
86
125
|
renderMarkdown(text) {
|
|
@@ -154,3 +193,31 @@ const emojiCodes = {
|
|
|
154
193
|
surprised: '😮',
|
|
155
194
|
wink: '😉',
|
|
156
195
|
}
|
|
196
|
+
|
|
197
|
+
function trimQuillDelta(delta) {
|
|
198
|
+
if (!delta) return delta
|
|
199
|
+
if (!delta.ops || !delta.ops.length) return delta
|
|
200
|
+
let last = delta.ops[delta.ops.length - 1]
|
|
201
|
+
if (typeof last.insert != 'string') return delta
|
|
202
|
+
|
|
203
|
+
let insert = last.insert.trim()
|
|
204
|
+
if (insert) {
|
|
205
|
+
if (last.insert != insert) {
|
|
206
|
+
// just fix the last item
|
|
207
|
+
let newops = delta.ops.slice()
|
|
208
|
+
// let last = sb.cloneDeep(newops.pop())
|
|
209
|
+
let last = newops.pop()
|
|
210
|
+
last.insert = insert
|
|
211
|
+
newops.push(last)
|
|
212
|
+
return {ops: newops}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// last item dont change, do nothing
|
|
216
|
+
return delta
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// remove the last item
|
|
220
|
+
let newops = delta.ops.slice()
|
|
221
|
+
newops.pop()
|
|
222
|
+
return trimQuillDelta({ops: newops})
|
|
223
|
+
}
|
package/src/chatbox/Widget.js
CHANGED
|
@@ -31,6 +31,8 @@ export default class Widget extends Com {
|
|
|
31
31
|
formData: {},
|
|
32
32
|
showOrder: false,
|
|
33
33
|
order_id: '',
|
|
34
|
+
// hot fix for prechat with bot quick reply
|
|
35
|
+
quickReplyMessage: {},
|
|
34
36
|
})
|
|
35
37
|
|
|
36
38
|
this.props.store.onUpdate(this, (_) => this.forceUpdate())
|
|
@@ -49,7 +51,7 @@ export default class Widget extends Com {
|
|
|
49
51
|
|
|
50
52
|
if (prevProp.cid !== this.props.cid) {
|
|
51
53
|
this.closeOrder()
|
|
52
|
-
this.setState({clickedJoin: false})
|
|
54
|
+
this.setState({clickedJoin: false, quickReplyMessage: {}})
|
|
53
55
|
// this.props.store.setLastview('chat', { cid: this.props.cid })
|
|
54
56
|
setTimeout(() => {
|
|
55
57
|
// focus Events then focus MessageInput
|
|
@@ -64,6 +66,17 @@ export default class Widget extends Com {
|
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
shouldShowForm() {
|
|
69
|
+
// always show form when ask agentgroup
|
|
70
|
+
let form
|
|
71
|
+
let accountSetting = this.props.plugin.chatbox || {}
|
|
72
|
+
let acc = this.props.store.matchAccount() || {}
|
|
73
|
+
if (sb.get(accountSetting, 'prechat_form.enabled')) form = accountSetting.prechat_form
|
|
74
|
+
|
|
75
|
+
let offlineEnabled = sb.get(accountSetting, 'offline_form.enabled')
|
|
76
|
+
if (this.isOffline(acc, accountSetting) && offlineEnabled) form = accountSetting.offline_form
|
|
77
|
+
|
|
78
|
+
if (!this.hasSentMessage(this.props.cid) && form && (sb.size(form.groups) || form.group_required)) return true
|
|
79
|
+
|
|
67
80
|
let formRequired = this.isFormRequired()
|
|
68
81
|
return (formRequired && !this.props.cid) || (formRequired && this.props.cid && this.state.clickedJoin)
|
|
69
82
|
}
|
|
@@ -175,9 +188,13 @@ export default class Widget extends Com {
|
|
|
175
188
|
text: firstmsg,
|
|
176
189
|
format: 'plaintext',
|
|
177
190
|
fields: [{key: 'to_agent_group', value: sb.stringify(groupid)}],
|
|
191
|
+
attachments: this.state.quickReplyMessage.attachments,
|
|
178
192
|
},
|
|
179
193
|
})
|
|
180
194
|
|
|
195
|
+
// reset quickReplyMessage
|
|
196
|
+
this.setState({quickReplyMessage: {}})
|
|
197
|
+
|
|
181
198
|
// end_conversation_after_submit only for offline form or prechat form
|
|
182
199
|
if (form.end_conversation_after_submit) await this.props.store.endConvo(this.props.cid)
|
|
183
200
|
return
|
|
@@ -202,6 +219,7 @@ export default class Widget extends Com {
|
|
|
202
219
|
this.setState({
|
|
203
220
|
creating: false,
|
|
204
221
|
clickedJoin: false,
|
|
222
|
+
quickReplyMessage: {},
|
|
205
223
|
})
|
|
206
224
|
if (!this.props.store.isMobile()) this.focusInput()
|
|
207
225
|
}
|
|
@@ -214,9 +232,11 @@ export default class Widget extends Com {
|
|
|
214
232
|
is_required: true,
|
|
215
233
|
label: this.props.t.i18n(sb.get(form, `i18n_question_label`, {})) || form.question_label,
|
|
216
234
|
type: 'text',
|
|
235
|
+
value: this.state.quickReplyMessage.text,
|
|
217
236
|
}
|
|
218
237
|
|
|
219
238
|
this.setState({formData})
|
|
239
|
+
|
|
220
240
|
if (!this.props.store.isMobile()) this.focusInput()
|
|
221
241
|
}
|
|
222
242
|
|
|
@@ -261,6 +281,9 @@ export default class Widget extends Com {
|
|
|
261
281
|
if (sb.size(this.state.formData) === 0) return null
|
|
262
282
|
|
|
263
283
|
let $fields = sb.map(this.state.formData, (field, key) => {
|
|
284
|
+
// not display question when click bot quick reply
|
|
285
|
+
if (this.state.quickReplyMessage.text && key === 'question') return null
|
|
286
|
+
|
|
264
287
|
let $field = null
|
|
265
288
|
var errclass = field.error ? 'input--error' : ''
|
|
266
289
|
if (field.type === 'text') {
|
|
@@ -525,7 +548,23 @@ export default class Widget extends Com {
|
|
|
525
548
|
this.focusInput()
|
|
526
549
|
}
|
|
527
550
|
|
|
551
|
+
fillQuickReplyToQuestion(message) {
|
|
552
|
+
let formData = this.state.formData
|
|
553
|
+
if (formData) {
|
|
554
|
+
sb.set(formData, 'question.value', message.text)
|
|
555
|
+
}
|
|
556
|
+
this.setState({formData, quickReplyMessage: message})
|
|
557
|
+
}
|
|
558
|
+
|
|
528
559
|
sendMessage = async (message) => {
|
|
560
|
+
// hot fix click quick reply with prechat with display prechat form
|
|
561
|
+
let hasPostback = sb.find(message.attachments, (att) => att.type === 'postback')
|
|
562
|
+
if (this.isFormRequired() && hasPostback) {
|
|
563
|
+
this.onStartConvoClick()
|
|
564
|
+
this.fillQuickReplyToQuestion(message)
|
|
565
|
+
return
|
|
566
|
+
}
|
|
567
|
+
|
|
529
568
|
let text = message.text
|
|
530
569
|
if (!this.props.cid) {
|
|
531
570
|
this.creating = true
|
|
@@ -635,7 +674,7 @@ export default class Widget extends Com {
|
|
|
635
674
|
async onStartConvoClick() {
|
|
636
675
|
var convo = this.props.store.matchConvo(this.props.cid) || {}
|
|
637
676
|
if (convo.state === 'ended') return this.props.onGo({view: 'chat', cid: ''})
|
|
638
|
-
this.setState({clickedJoin: true})
|
|
677
|
+
this.setState({clickedJoin: true, quickReplyMessage: {}})
|
|
639
678
|
}
|
|
640
679
|
|
|
641
680
|
onEventFormSubmit() {
|
|
@@ -675,9 +714,10 @@ export default class Widget extends Com {
|
|
|
675
714
|
let convo = this.props.store.matchConvo(this.props.cid) || {}
|
|
676
715
|
|
|
677
716
|
if (convo.state === 'ended') return true
|
|
678
|
-
|
|
717
|
+
// allow button "Tiep tuc chat" display when sent quick_replies msg
|
|
718
|
+
//if (this.userHasSent(this.props.cid)) return false
|
|
679
719
|
if (convo.state && convo.state !== 'pending') delete formData.group
|
|
680
|
-
return !!sb.find(formData, (field) => field.value == null || field.value === '')
|
|
720
|
+
return !!sb.find(formData, (field) => field.is_required && (field.value == null || field.value === ''))
|
|
681
721
|
}
|
|
682
722
|
|
|
683
723
|
renderConvoSummary(convo) {
|
|
@@ -778,6 +818,16 @@ export default class Widget extends Com {
|
|
|
778
818
|
return joined
|
|
779
819
|
}
|
|
780
820
|
|
|
821
|
+
hasSentMessage(cid) {
|
|
822
|
+
let convo = this.props.store.matchConvo(cid) || {}
|
|
823
|
+
let joined = sb.find(convo.members, (mem) => {
|
|
824
|
+
// sometime bot didnt update last_sent
|
|
825
|
+
if (mem.type === 'bot') return true
|
|
826
|
+
return mem.last_sent
|
|
827
|
+
})
|
|
828
|
+
return joined
|
|
829
|
+
}
|
|
830
|
+
|
|
781
831
|
isOffline(acc, accSetting) {
|
|
782
832
|
let enableWhen = sb.get(accSetting, 'offline_form.enable_when')
|
|
783
833
|
let isonline = true
|
package/src/util/common.js
CHANGED
|
@@ -824,7 +824,7 @@ export function checkRunConditions(freq, conds, lastrun, store) {
|
|
|
824
824
|
break
|
|
825
825
|
case 'source':
|
|
826
826
|
if (size(cond.sources) > 0) {
|
|
827
|
-
let source = store.matchTrafficSource()
|
|
827
|
+
let source = store.matchTrafficSource() || 'direct'
|
|
828
828
|
if (!find(cond.sources, (src) => norm(src) === norm(source))) return false
|
|
829
829
|
}
|
|
830
830
|
break
|