@subiz/widget-v4 4.1.209 → 4.1.211

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.
Files changed (137) hide show
  1. package/README.md +21 -2
  2. package/assets/less/chatbox.less +9 -0
  3. package/assets/less/form.less +10 -0
  4. package/assets/less/message.less +114 -13
  5. package/assets/less/widget.less +21 -16
  6. package/compiled_src/call/css.js +1 -1
  7. package/compiled_src/chatbox/Buttons.js +7 -4
  8. package/compiled_src/chatbox/ChatButton.js +115 -29
  9. package/compiled_src/chatbox/Event.js +37 -5
  10. package/compiled_src/chatbox/Events.js +348 -129
  11. package/compiled_src/chatbox/FormAttachment.js +1 -1
  12. package/compiled_src/chatbox/Header.js +6 -2
  13. package/compiled_src/chatbox/InfoMessage.js +1 -1
  14. package/compiled_src/chatbox/MessageInput.js +24 -9
  15. package/compiled_src/chatbox/OrderAttachments.js +13 -13
  16. package/compiled_src/chatbox/QuoteMessage.js +3 -2
  17. package/compiled_src/chatbox/TextMessage.js +22 -18
  18. package/compiled_src/chatbox/Widget.js +200 -129
  19. package/compiled_src/chatbox/block.js +39 -29
  20. package/compiled_src/chatbox/conversation-history.js +44 -0
  21. package/compiled_src/chatbox/event-layout.js +59 -0
  22. package/compiled_src/chatbox/greeting.js +32 -0
  23. package/compiled_src/common.js +13 -9
  24. package/compiled_src/form/css.js +1 -1
  25. package/compiled_src/lib.js +22 -32
  26. package/compiled_src/notif/css.js +1 -1
  27. package/compiled_src/plugin.js +11 -18
  28. package/compiled_src/popup/css.js +1 -1
  29. package/compiled_src/popup/popup.js +1 -1
  30. package/compiled_src/store/api.js +0 -2
  31. package/compiled_src/store/api_fake.js +1 -1
  32. package/compiled_src/store/attachments.js +28 -0
  33. package/compiled_src/store/chain.js +24 -10
  34. package/compiled_src/store/kv.js +9 -13
  35. package/compiled_src/store/lsdb.js +1 -1
  36. package/compiled_src/store/store.js +356 -117
  37. package/compiled_src/util/common.js +48 -41
  38. package/compiled_src/util/event.js +15 -0
  39. package/compiled_src/util/pubsub.js +28 -13
  40. package/compiled_src/util/url.js +18 -0
  41. package/dist/.HASH +1 -0
  42. package/dist/127.js +13 -13
  43. package/dist/132.js +1 -1
  44. package/dist/1a0ddc53cbb.127.js +1 -0
  45. package/dist/{1a08405c848.132.js → 1a0ddc53cbb.132.js} +1 -1
  46. package/dist/{1a08405c848.27.js → 1a0ddc53cbb.27.js} +1 -1
  47. package/dist/1a0ddc53cbb.278.js +1 -0
  48. package/dist/{1a08405c848.339.js → 1a0ddc53cbb.339.js} +1 -1
  49. package/dist/1a0ddc53cbb.459.js +1 -0
  50. package/dist/1a0ddc53cbb.app.js +1 -0
  51. package/dist/1a0ddc53cbb.chat.html +1 -0
  52. package/dist/1a0ddc53cbb.chat.js +1 -0
  53. package/dist/1a0ddc53cbb.form.html +1 -0
  54. package/dist/1a0ddc53cbb.form.js +1 -0
  55. package/dist/1a0ddc53cbb.index.html +72 -0
  56. package/dist/1a0ddc53cbb.library.html +72 -0
  57. package/dist/1a0ddc53cbb.library.js +1 -0
  58. package/dist/1a0ddc53cbb.preview.html +759 -0
  59. package/dist/1a0ddc53cbb.preview.js +1 -0
  60. package/dist/1a0ddc53cbb.webview.js +1 -0
  61. package/dist/27.js +4 -4
  62. package/dist/459.js +4 -4
  63. package/dist/screenshoot.js +1523 -654
  64. package/package.json +10 -3
  65. package/src/call/css.js +1 -1
  66. package/src/chatbox/Buttons.js +5 -4
  67. package/src/chatbox/ChatButton.js +120 -39
  68. package/src/chatbox/Event.js +38 -5
  69. package/src/chatbox/Events.js +306 -134
  70. package/src/chatbox/FormAttachment.js +1 -1
  71. package/src/chatbox/Header.js +4 -4
  72. package/src/chatbox/InfoMessage.js +1 -1
  73. package/src/chatbox/MessageInput.js +15 -10
  74. package/src/chatbox/OrderAttachments.js +13 -13
  75. package/src/chatbox/QuoteMessage.js +3 -2
  76. package/src/chatbox/TextMessage.js +21 -20
  77. package/src/chatbox/Widget.js +150 -150
  78. package/src/chatbox/block.js +29 -27
  79. package/src/chatbox/conversation-history.js +37 -0
  80. package/src/chatbox/event-layout.js +72 -0
  81. package/src/chatbox/greeting.js +13 -0
  82. package/src/common.js +15 -9
  83. package/src/form/css.js +1 -1
  84. package/src/lib.js +22 -35
  85. package/src/notif/css.js +1 -1
  86. package/src/plugin.js +11 -13
  87. package/src/popup/css.js +1 -1
  88. package/src/popup/popup.js +1 -1
  89. package/src/store/api.js +0 -2
  90. package/src/store/api_fake.js +1 -1
  91. package/src/store/attachments.js +21 -0
  92. package/src/store/chain.js +25 -12
  93. package/src/store/kv.js +10 -19
  94. package/src/store/lsdb.js +1 -1
  95. package/src/store/store.js +313 -130
  96. package/src/util/common.js +48 -43
  97. package/src/util/event.js +7 -0
  98. package/src/util/pubsub.js +27 -8
  99. package/src/util/url.js +14 -0
  100. package/test.cjs +59 -0
  101. package/webpack.prod.js +3 -0
  102. package/assets/less/contact.less +0 -126
  103. package/compiled_src/util/common.test.js +0 -414
  104. package/compiled_src/util/event.test.js +0 -38
  105. package/compiled_src/util/extractor.test.js +0 -299
  106. package/compiled_src/util/extractor.test2.js +0 -61
  107. package/compiled_src/util/gate.test.js +0 -18
  108. package/compiled_src/util/pubsub.test.js +0 -35
  109. package/dist/1a08405c848.127.js +0 -1
  110. package/dist/1a08405c848.278.js +0 -1
  111. package/dist/1a08405c848.459.js +0 -1
  112. package/dist/1a08405c848.74.js +0 -1
  113. package/dist/1a08405c848.997.js +0 -1
  114. package/dist/1a08405c848.app.js +0 -1
  115. package/dist/1a08405c848.chat.html +0 -1
  116. package/dist/1a08405c848.chat.js +0 -1
  117. package/dist/1a08405c848.form.html +0 -1
  118. package/dist/1a08405c848.form.js +0 -1
  119. package/dist/1a08405c848.index.html +0 -1
  120. package/dist/1a08405c848.library.html +0 -1
  121. package/dist/1a08405c848.library.js +0 -1
  122. package/dist/1a08405c848.preview.html +0 -1
  123. package/dist/1a08405c848.preview.js +0 -1
  124. package/dist/1a08405c848.webview.js +0 -1
  125. package/dist/74.js +0 -376
  126. package/dist/997.js +0 -37
  127. package/dist/HASH +0 -1
  128. package/src/contact/contact.js +0 -400
  129. package/src/contact/css.js +0 -1
  130. package/src/util/common.test.js +0 -301
  131. package/src/util/event.test.js +0 -31
  132. package/src/util/extractor.test.js +0 -240
  133. package/src/util/extractor.test2.js +0 -56
  134. package/src/util/gate.test.js +0 -20
  135. package/src/util/pubsub.test.js +0 -37
  136. /package/dist/{1a08405c848.185.js → 1a0ddc53cbb.185.js} +0 -0
  137. /package/dist/{1a08405c848.490.js → 1a0ddc53cbb.490.js} +0 -0
@@ -45,10 +45,14 @@ class MessageInput extends _common.Com {
45
45
  $input.blur();
46
46
  }
47
47
  render() {
48
+ const disabled = this.hasUnfinishRequiredFormOrLock() || this.props.disabled || this.props.is_loading;
48
49
  var $buttons = (0, _preact.h)("div", {
49
50
  class: "d-flex flex-row align-self-end"
50
- }, this.renderEmoji(), (0, _preact.h)("div", {
51
- "data-tooltip-poasition": "top-left",
51
+ }, this.renderEmoji(), (0, _preact.h)("button", {
52
+ type: "button",
53
+ disabled: disabled,
54
+ "aria-label": this.props.t('attachment'),
55
+ "data-tooltip-position": "top-left",
52
56
  class: "message-input--button message-input--attachment-button",
53
57
  onClick: e => this.selectFile(e)
54
58
  }));
@@ -56,7 +60,10 @@ class MessageInput extends _common.Com {
56
60
  if (msg.length > 0) {
57
61
  $buttons = (0, _preact.h)("div", {
58
62
  class: "d-flex flex-row align-self-end"
59
- }, this.renderEmoji(), (0, _preact.h)("div", {
63
+ }, this.renderEmoji(), (0, _preact.h)("button", {
64
+ type: "button",
65
+ disabled: disabled,
66
+ "aria-label": this.props.t('send'),
60
67
  "data-tooltip-position": "top-left",
61
68
  class: "message-input--button message-input--send-button",
62
69
  onClick: () => this.submitMessage()
@@ -70,7 +77,6 @@ class MessageInput extends _common.Com {
70
77
  }));
71
78
  }
72
79
  var containercls = '';
73
- var disabled = this.hasUnfinishRequiredFormOrLock() || this.props.disabled;
74
80
  if (disabled || this.props.is_loading) containercls = 'message-input--disabled';
75
81
  return (0, _preact.h)("div", {
76
82
  class: `message-input ${containercls}`,
@@ -85,6 +91,7 @@ class MessageInput extends _common.Com {
85
91
  multiple: true
86
92
  }), (0, _preact.h)("textarea", {
87
93
  disabled: disabled,
94
+ "aria-label": this.props.t('message_input_help'),
88
95
  class: "message-input--input",
89
96
  maxlength: "1024",
90
97
  placeholder: this.props.t('message_input_help').substr(0, 25),
@@ -247,7 +254,11 @@ class MessageInput extends _common.Com {
247
254
  }, 100);
248
255
  }
249
256
  renderEmoji() {
250
- return (0, _preact.h)("div", null, this.renderEmojiPopup(), (0, _preact.h)("div", {
257
+ return (0, _preact.h)("div", null, this.renderEmojiPopup(), (0, _preact.h)("button", {
258
+ type: "button",
259
+ "aria-label": "Emoji",
260
+ "aria-expanded": !!this.state.openEmoji,
261
+ disabled: this.props.disabled || this.props.is_loading,
251
262
  class: "message-input--button message-input--emoji-button",
252
263
  onClick: e => this.toggleEmoji(e)
253
264
  }));
@@ -277,13 +288,15 @@ class MessageInput extends _common.Com {
277
288
  return e.preventDefault();
278
289
  }
279
290
  this._forceUpdate();
280
- this.sendTyping();
281
291
  }
282
292
  onChange(e) {
293
+ const value = e.target.value;
294
+ const changed = value !== (this.state.msgValue || '');
283
295
  this.setState({
284
- msgValue: e.target.value
296
+ msgValue: value
285
297
  });
286
298
  this.resizeInput();
299
+ if (changed && _index.default.trim(value)) this.sendTyping();
287
300
  }
288
301
  selectFile() {
289
302
  if (this.props.disabled) return;
@@ -315,10 +328,10 @@ class MessageInput extends _common.Com {
315
328
  if (!msg) return;
316
329
  if (this.props.disabled) return;
317
330
  if (this.props.onSend) {
318
- await this.props.onSend({
331
+ if ((await this.props.onSend({
319
332
  text: msg,
320
333
  format: 'plaintext'
321
- });
334
+ })) === false) return;
322
335
  }
323
336
  this.setState({
324
337
  openEmoji: false,
@@ -327,7 +340,9 @@ class MessageInput extends _common.Com {
327
340
  this.resizeInput();
328
341
  }
329
342
  sendTyping() {
343
+ if (this.props.disabled || this.props.is_loading) return;
330
344
  if (!this.props.cid) return;
345
+ if (_index.default.get(this.props.store.matchConvo(this.props.cid), 'state') === 'ended') return;
331
346
  return this.props.store.typing(this.props.cid);
332
347
  }
333
348
  pasteImage(event) {
@@ -167,12 +167,12 @@ class ProductAttachments extends _common.Com {
167
167
  }
168
168
  exports.default = ProductAttachments;
169
169
  function getProductPropName(product, seperator = ' - ') {
170
- let options = op.get(product, 'options', []);
171
- let props = op.get(product, 'props', []);
172
- let multiPropsOptions = op.filter(options, option => op.size(option.values) > 1);
170
+ let options = _index.default.get(product, 'options', []);
171
+ let props = _index.default.get(product, 'props', []);
172
+ let multiPropsOptions = _index.default.filter(options, option => _index.default.size(option.values) > 1);
173
173
  let names = [];
174
- op.each(multiPropsOptions, option => {
175
- let prop = op.find(props, prop => prop.key === option.key) || {};
174
+ _index.default.each(multiPropsOptions, option => {
175
+ let prop = _index.default.find(props, prop => prop.key === option.key) || {};
176
176
  if (prop.value) names.push(prop.value);
177
177
  });
178
178
  return names.join(seperator);
@@ -181,7 +181,7 @@ function getOrderDisplayName(order = {}) {
181
181
  return order.number || order.id || '';
182
182
  }
183
183
  function displayOrderShippingAddress(order, isShorten) {
184
- let addr = op.get(order, 'shipping.address', {});
184
+ let addr = _index.default.get(order, 'shipping.address', {});
185
185
  let fulladdr = [addr.address, addr.ward, addr.district, addr.province].filter(a => a).join(', ').trim();
186
186
  if (isShorten) fulladdr = shortenAddr(fulladdr);
187
187
  return fulladdr;
@@ -197,9 +197,9 @@ function calcOrderTotal(order) {
197
197
  let subtotal = 0;
198
198
  let beforeTaxDiscount = 0;
199
199
  let ordervalue = 0;
200
- op.map(order.items, item => {
200
+ _index.default.map(order.items, item => {
201
201
  if (!item.product) return 0;
202
- let price = op.get(item, 'product.price', 0) * (item.quantity || 0);
202
+ let price = _index.default.get(item, 'product.price', 0) * (item.quantity || 0);
203
203
  ordervalue += price;
204
204
  if (item.discount_type == 'percentage') {
205
205
  if (item.discount_percentage > 0) {
@@ -217,7 +217,7 @@ function calcOrderTotal(order) {
217
217
  subtotal += price;
218
218
  });
219
219
  let taxM = {};
220
- op.map(order.items, (item, i) => {
220
+ _index.default.map(order.items, (item, i) => {
221
221
  if (!item.product) return;
222
222
  let tax = item.product.tax;
223
223
  if (!tax) return;
@@ -230,16 +230,16 @@ function calcOrderTotal(order) {
230
230
  };
231
231
  });
232
232
  let totaltax = 0;
233
- op.map(taxM, t => totaltax += t.taxprice);
233
+ _index.default.map(taxM, t => totaltax += t.taxprice);
234
234
  let computed_discount = 0;
235
235
  if (order.discount_type == 'percentage' && order.discount_percentage > 0) {
236
236
  computed_discount = (subtotal + totaltax) * order.discount_percentage / 10000;
237
237
  } else if (order.discount_type == 'amount') {
238
238
  computed_discount = order.discount_amount || 0;
239
239
  }
240
- let shippingfee = op.get(order, 'shipping.nominal_fee', 0);
240
+ let shippingfee = _index.default.get(order, 'shipping.nominal_fee', 0);
241
241
  if (shippingfee > 0) {
242
- if (op.get(order, 'shipping.tax.id')) {
242
+ if (_index.default.get(order, 'shipping.tax.id')) {
243
243
  let tax = order.shipping.tax;
244
244
  let taxprice = shippingfee * (tax.percentage / 10000);
245
245
  taxM['ship'] = {
@@ -250,7 +250,7 @@ function calcOrderTotal(order) {
250
250
  }
251
251
  }
252
252
  totaltax = 0;
253
- op.map(taxM, t => totaltax += t.taxprice);
253
+ _index.default.map(taxM, t => totaltax += t.taxprice);
254
254
  let total = subtotal + totaltax - computed_discount + shippingfee;
255
255
  total += order.adjustment || 0;
256
256
  if (total < 0) total = 0;
@@ -44,7 +44,7 @@ class QuoteMessage extends _common.Com {
44
44
  if (_index.default.get(this.props, 'chatbox.hide_agent_profile')) sendername = acc.name;
45
45
  }
46
46
  let att = _index.default.get(this.props.ev, 'data.message.attachments.0');
47
- if (att) {
47
+ if (att && !_index.default.get(this.props.ev, 'data.message.deleted')) {
48
48
  let isImg = _index.default.includes(att.mimetype, 'image');
49
49
  if (isImg) {
50
50
  let uri = att.url;
@@ -78,7 +78,8 @@ class QuoteMessage extends _common.Com {
78
78
  let format = _index.default.get(this.props.ev, 'data.message.format', 'plaintext');
79
79
  let block = _index.default.get(this.props.ev, 'data.message.block');
80
80
  let text = _index.default.get(this.props.ev, 'data.message.text');
81
- if (block) text = _index.default.blockToText(block);
81
+ if (block) text = _index.default.blockToText(block) || text;
82
+ if (_index.default.get(this.props.ev, 'data.message.deleted')) text = this.props.t('recalled_message');
82
83
  return (0, _preact.h)("div", {
83
84
  class: "message-quote",
84
85
  onClick: () => this.scrollToSourceEvent(this.props.ev)
@@ -9,8 +9,8 @@ var _block = _interopRequireDefault(require("./block.js"));
9
9
  var _common = require("../common.js");
10
10
  var _preact = require("preact");
11
11
  var _Emoji = _interopRequireDefault(require("./Emoji.js"));
12
- var _time = _interopRequireDefault(require("./time.js"));
13
12
  var _QuoteMessage = _interopRequireDefault(require("./QuoteMessage.js"));
13
+ var _url = require("../util/url.js");
14
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
15
  class TextMessage extends _common.Com {
16
16
  constructor(props) {
@@ -21,12 +21,9 @@ class TextMessage extends _common.Com {
21
21
  }
22
22
  renderTime() {
23
23
  return null;
24
- if (!this.props.showTime && !this.props.isLast && !this.props.isFirst) return null;
25
- return (0, _preact.h)("div", null, (0, _preact.h)(_time.default, {
26
- class: "inline-time",
27
- time: _index.default.get(this.props.ev, 'created', _index.default.Date.now()),
28
- t: this.props.t
29
- }));
24
+ }
25
+ componentWillUnmount() {
26
+ _index.default.clearTimeout(this.focusTimeout);
30
27
  }
31
28
  focusSourceEventFromQuote(ev) {
32
29
  if (ev.id !== this.props.ev.id) return;
@@ -34,7 +31,7 @@ class TextMessage extends _common.Com {
34
31
  let attachmentIndexField = _index.default.find(fields, f => f.key === 'attachment_index');
35
32
  let attachmentIndex = _index.default.get(attachmentIndexField, 'value');
36
33
  try {
37
- attachmentIndex = JSON.parse(attachmentIndex);
34
+ attachmentIndex = _index.default.parseJSON(attachmentIndex);
38
35
  } catch (err) {
39
36
  attachmentIndex = undefined;
40
37
  }
@@ -42,17 +39,22 @@ class TextMessage extends _common.Com {
42
39
  this.setState({
43
40
  focused: true
44
41
  });
45
- if (this.focusTimeout) clearTimeout(this.focusTimeout);
46
- this.focusTimeout = setTimeout(() => {
42
+ if (this.focusTimeout) _index.default.clearTimeout(this.focusTimeout);
43
+ this.focusTimeout = _index.default.setTimeout(() => {
47
44
  this.setState({
48
45
  focused: false
49
46
  });
50
47
  }, 3000);
51
48
  }
52
49
  render() {
53
- var format = _index.default.get(this.props.ev, 'data.message.format', 'plaintext');
50
+ if (_index.default.get(this.props.ev, 'data.message.deleted')) {
51
+ let byType = _index.default.get(this.props.ev, 'by.type') === 'user' ? 'user' : 'agent';
52
+ return (0, _preact.h)("div", {
53
+ class: 'message-' + byType + ' message-text--' + byType + ' message-text--deleted'
54
+ }, this.props.t('recalled_message'));
55
+ }
54
56
  let block = _index.default.get(this.props.ev, 'data.message.block');
55
- if (block) return this.renderBlock(block);
57
+ if (block && !_index.default.isEmptyBlock(block)) return this.renderBlock(block);
56
58
  return this.renderPlainText();
57
59
  }
58
60
  renderPlainText() {
@@ -72,11 +74,14 @@ class TextMessage extends _common.Com {
72
74
  if (!url.startsWith('//') && !url.startsWith('https://') && !url.startsWith('http://') && !url.startsWith('data:')) {
73
75
  url = '//' + url;
74
76
  }
77
+ url = (0, _url.safeUrl)(url);
78
+ if (!url) return tag.text;
75
79
  return (0, _preact.h)("a", {
76
80
  class: "text-message-link",
77
81
  href: url,
78
82
  target: "_blank",
79
- onClick: e => this.props.onLink(e, url)
83
+ rel: "noopener noreferrer",
84
+ onClick: e => this.props.onLink && this.props.onLink(e, url)
80
85
  }, tag.text);
81
86
  }
82
87
  if (tag.type === 'phone') return (0, _preact.h)("a", {
@@ -90,15 +95,10 @@ class TextMessage extends _common.Com {
90
95
  return tag.text;
91
96
  });
92
97
  if (_index.default.size(tags) === 0) return null;
93
- let isDeleted = _index.default.get(this.props.ev, 'data.message.deleted');
94
98
  let attachments = _index.default.get(this.props.ev, 'data.message.attachments', []);
95
99
  let quote = _index.default.find(attachments, att => att.type === 'quote');
96
100
  if (byType === 'agent') {
97
101
  let cls = 'message-agent message-text--agent';
98
- if (isDeleted) {
99
- tags = this.props.t('recalled_message');
100
- cls += ' message-text--deleted';
101
- }
102
102
  if (this.state.focused) cls += ' just-focused';
103
103
  return (0, _preact.h)("div", {
104
104
  class: cls,
@@ -130,6 +130,8 @@ class TextMessage extends _common.Com {
130
130
  }, (0, _preact.h)(_block.default, {
131
131
  block: block,
132
132
  onLink: this.props.onLink,
133
+ store: this.props.store,
134
+ t: this.props.t,
133
135
  textMessage: true
134
136
  }), this.renderTime());
135
137
  }
@@ -141,6 +143,8 @@ class TextMessage extends _common.Com {
141
143
  }, (0, _preact.h)(_block.default, {
142
144
  block: block,
143
145
  onLink: this.props.onLink,
146
+ store: this.props.store,
147
+ t: this.props.t,
144
148
  textMessage: true
145
149
  }));
146
150
  }