@subiz/widget-v4 4.0.46 → 4.0.51

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 (92) hide show
  1. package/assets/img/default.jpg +0 -0
  2. package/assets/img/external-link.svg +1 -0
  3. package/assets/less/message.less +210 -42
  4. package/compiled_src/chatbox/ChatButton.js +12 -6
  5. package/compiled_src/chatbox/Event.js +22 -2
  6. package/compiled_src/chatbox/MessageInput.js +8 -3
  7. package/compiled_src/chatbox/OrderAttachments.js +113 -0
  8. package/compiled_src/chatbox/ProductAttachments.js +79 -0
  9. package/compiled_src/chatbox/TextMessage.js +1 -1
  10. package/compiled_src/chatbox/Widget.js +18 -3
  11. package/compiled_src/chatbox/main.js +5 -4
  12. package/compiled_src/chatbox/time.js +94 -7
  13. package/compiled_src/common.js +1 -1
  14. package/compiled_src/contact/contact.js +1 -1
  15. package/compiled_src/plugin.js +8 -2
  16. package/compiled_src/store/store.js +150 -5
  17. package/compiled_src/util/campaign.js +2 -2
  18. package/compiled_src/util/common.js +78 -49
  19. package/compiled_src/util/extractor.js +3 -3
  20. package/compiled_src/util/pubsub.js +6 -3
  21. package/dist/17d02a15859.178.js +1 -0
  22. package/dist/17d02a15859.213.js +1 -0
  23. package/dist/17d02a15859.362.js +1 -0
  24. package/dist/17d02a15859.441.js +1 -0
  25. package/dist/17d02a15859.605.js +1 -0
  26. package/dist/17d02a15859.619.js +1 -0
  27. package/dist/17d02a15859.678.js +1 -0
  28. package/dist/17d02a15859.712.js +1 -0
  29. package/dist/17d02a15859.782.js +1 -0
  30. package/dist/17d02a15859.app.js +1 -0
  31. package/dist/17d02a15859.index.html +21 -0
  32. package/dist/17d02a15859.library.html +21 -0
  33. package/dist/17d02a15859.library.js +1 -0
  34. package/dist/17d02a15859.preview.html +759 -0
  35. package/dist/17d02a15859.preview.js +1 -0
  36. package/dist/HASH +1 -1
  37. package/dist/assets/img/Facebook.64607ec.png +0 -0
  38. package/dist/assets/img/Zalo.6845707.png +0 -0
  39. package/dist/assets/img/award1a.1a58e10.png +0 -0
  40. package/dist/assets/img/award3a.3b74423.png +0 -0
  41. package/dist/assets/img/award4a.ed6ccd4.png +0 -0
  42. package/dist/assets/img/award5.39eb7ae.png +0 -0
  43. package/dist/assets/img/bubble_default.7d5e4ab.svg +20 -0
  44. package/dist/assets/img/convos_empty.2353007.svg +72 -0
  45. package/dist/assets/img/default_avatar.5b74dc1.png +0 -0
  46. package/dist/assets/img/done_gray.d7e8203.svg +4 -0
  47. package/dist/assets/img/emoji/messenger/sub_23.529_58.824.d5faf14.png +0 -0
  48. package/dist/assets/img/emoji/messenger/sub_23.529_60.784.1420241.png +0 -0
  49. package/dist/assets/img/emoji/messenger/sub_25.490_0.000.1e6b2c0.png +0 -0
  50. package/dist/assets/img/emoji/messenger/sub_25.490_45.098.3dfbc08.png +0 -0
  51. package/dist/assets/img/emoji/messenger/sub_25.490_5.882.4b49e94.png +0 -0
  52. package/dist/assets/img/emoji/messenger/sub_27.451_72.549.7114f58.png +0 -0
  53. package/dist/assets/img/emoji/messenger/sub_27.451_84.314.231e2b7.png +0 -0
  54. package/dist/assets/img/emoji/messenger/sub_27.451_96.078.ddbb008.png +0 -0
  55. package/dist/assets/img/emoji/messenger/sub_29.412_5.882.61f3359.png +0 -0
  56. package/dist/assets/img/emoji/messenger/sub_58.824_100.000.6df72bc.png +0 -0
  57. package/dist/assets/img/emoji/messenger/sub_58.824_45.098.3d7a7ad.png +0 -0
  58. package/dist/assets/img/emoji/messenger/sub_58.824_47.059.0f4d6e2.png +0 -0
  59. package/dist/assets/img/emoji/messenger/sub_58.824_54.902.65724c1.png +0 -0
  60. package/dist/assets/img/emoji/messenger/sub_58.824_64.706.9da3cba.png +0 -0
  61. package/dist/assets/img/emoji/messenger/sub_58.824_72.549.edca5cf.png +0 -0
  62. package/dist/assets/img/emoji/messenger/sub_58.824_78.431.f910f2a.png +0 -0
  63. package/dist/assets/img/emoji/messenger/sub_58.824_88.235.def4e71.png +0 -0
  64. package/dist/assets/img/emoji/messenger/sub_60.784_11.765.49c03d0.png +0 -0
  65. package/dist/assets/img/emoji/messenger/sub_60.784_27.451.46b54e5.png +0 -0
  66. package/dist/assets/img/emoji/messenger/sub_60.784_29.412.e36d284.png +0 -0
  67. package/dist/assets/img/emoji/messenger/sub_60.784_3.922.bb191b0.png +0 -0
  68. package/dist/assets/img/emoji/messenger/sub_60.784_35.294.af7b927.png +0 -0
  69. package/dist/assets/img/emoji/messenger/sub_60.784_7.843.98f2a99.png +0 -0
  70. package/dist/assets/img/empty.29bed2d.svg +23 -0
  71. package/dist/assets/img/examplte_logo.f86535f.svg +1 -0
  72. package/dist/assets/img/external-link.90577cc.svg +1 -0
  73. package/dist/assets/img/fb_inverse_circle.36c2cfc.png +0 -0
  74. package/dist/assets/img/image_default.be0698b.png +0 -0
  75. package/dist/assets/img/loading_static.8f403ae.svg +10 -0
  76. package/dist/assets/img/main-service1.d536cc2.png +0 -0
  77. package/dist/assets/img/main-service2.9b99549.png +0 -0
  78. package/dist/assets/img/rating--average.1ea492c.svg +12 -0
  79. package/dist/assets/img/rating--great.e3d712e.svg +16 -0
  80. package/dist/assets/img/rating--poor.2938a25.svg +12 -0
  81. package/dist/assets/img/send.6db52a9.svg +3 -0
  82. package/dist/assets/img/subiz-mono.877e9f5.svg +3 -0
  83. package/package.json +20 -19
  84. package/src/chatbox/ChatButton.js +10 -6
  85. package/src/chatbox/Event.js +72 -56
  86. package/src/chatbox/OrderAttachments.js +112 -0
  87. package/src/chatbox/ProductAttachments.js +70 -0
  88. package/src/chatbox/TextMessage.js +1 -1
  89. package/src/chatbox/main.js +6 -4
  90. package/src/plugin.js +9 -4
  91. package/src/store/store.js +146 -8
  92. package/src/util/common.js +6 -0
@@ -45,6 +45,8 @@ export default class Main extends Com {
45
45
  widgetView: '',
46
46
  widgetConvoId: '',
47
47
  })
48
+
49
+ this.checkExpand()
48
50
  this.props.store.onResetCSS(this, () => this.refreshCSS())
49
51
  this.props.store.onConvoEvent(this, (_) => this.checkExpand())
50
52
  this.props.store.onUpdate(this, (_) => this.checkExpand())
@@ -114,7 +116,7 @@ export default class Main extends Com {
114
116
  }
115
117
 
116
118
  async showWidget(p) {
117
- this.refButton.current && this.refButton.current.clearPreview()
119
+ this.refButton.current && this.refButton.current.ClearPreview()
118
120
  if (!p.view) {
119
121
  let lastview = this.props.store.matchLastview() || {}
120
122
  p.view = sb.get(lastview, 'view')
@@ -136,11 +138,11 @@ export default class Main extends Com {
136
138
  }
137
139
 
138
140
  showGreeting() {
139
- this.refButton.current && this.refButton.current.showGreeting()
141
+ this.refButton.current && this.refButton.current.ShowGreeting()
140
142
  }
141
143
 
142
144
  hideGreeting() {
143
- this.refButton.current && this.refButton.current.hideGreeting()
145
+ this.refButton.current && this.refButton.current.HideGreeting()
144
146
  }
145
147
 
146
148
  hideWidget() {
@@ -151,7 +153,7 @@ export default class Main extends Com {
151
153
  }
152
154
 
153
155
  onWidgetClose() {
154
- this.refButton.current && this.refButton.current.clearPreview()
156
+ this.refButton.current && this.refButton.current.ClearPreview()
155
157
  this.props.store.setHasManuallyClosed()
156
158
  this.hideWidget()
157
159
  }
package/src/plugin.js CHANGED
@@ -29,7 +29,7 @@ function Plugin(plugin, store, $container, lib) {
29
29
 
30
30
  this.getState = () => state
31
31
 
32
- var run = async function() {
32
+ var run = async function () {
33
33
  if (_destroy) return
34
34
  if (state !== 'hold') return
35
35
 
@@ -370,10 +370,15 @@ function downloadLanguage(store, locale, force) {
370
370
  }
371
371
 
372
372
  const getLocale = (plugin, loc) => {
373
- let found = sb.find(plugin.locales, (l) => l === loc)
373
+ if (!loc) loc = ''
374
+ let found = sb.find(plugin.locales, (l) => l.toLowerCase().trim() === loc.toLowerCase().trim())
374
375
  if (found) return loc
375
- found = sb.find(plugin.locales, (l) => (l || '').toLowerCase().includes(loc.toLowerCase()))
376
- if (found) return found
377
376
 
377
+ found = sb.find(plugin.locales, (l) => {
378
+ l = l.replace('-', '_').split('_')[0].trim().toLowerCase()
379
+ let compareloc = loc.replace('-', '_').split('_')[0].trim().toLowerCase()
380
+ return l == compareloc
381
+ })
382
+ if (found) return found
378
383
  return plugin.locale || 'en-US'
379
384
  }
@@ -149,7 +149,7 @@ export default class Store {
149
149
  overridePlugin(plugins) {
150
150
  if (!Array.isArray(plugins)) throw 'plugins must be be an array'
151
151
  let pluginM = {}
152
- sb.map(plugins, function(plugin) {
152
+ sb.map(plugins, function (plugin) {
153
153
  pluginM[plugin.id] = plugin
154
154
  })
155
155
  this.forcePlugins = pluginM
@@ -930,6 +930,143 @@ export default class Store {
930
930
  setTimeout(() => this.loopTime(), 60000)
931
931
  }
932
932
 
933
+ getPrice(obj, field, currency) {
934
+ if (!obj) return 0
935
+ if (!currency) return obj[field] || 0
936
+ let defcur = sb.get(this.matchAccount(), 'currency')
937
+ if (currency != defcur) return sb.get(obj, [field + '_locale', currency], 0)
938
+ return obj[field] || 0
939
+ }
940
+
941
+ getOrderTotal(order) {
942
+ let subtotal = 0
943
+ sb.map(order.items, (item) => {
944
+ if (!item.product) return 0
945
+ let price = this.getPrice(item.product, 'price', order.currency) * item.quantity
946
+
947
+ if (item.discount_type) {
948
+ if (item.discount_type == 'percentage') {
949
+ if (item.discount_before_tax && item.discount_percentage > 0) {
950
+ price = price * (1 - item.discount_percentage / 10000)
951
+ }
952
+ } else if (item.discount_type == 'amount') {
953
+ let computed_discount = this.getPrice(item, 'discount', order.currency)
954
+ if (item.discount_before_tax && computed_discount > 0) {
955
+ price = price - computed_discount
956
+ if (price <= 0) price = 0
957
+ }
958
+ }
959
+ }
960
+ subtotal += price
961
+ })
962
+
963
+ let computed_discount = 0
964
+ // add specific item discount after tax to computed_discount
965
+ sb.map(order.items, (item) => {
966
+ if (!item.discount_type) return
967
+ if (!item.product) return 0
968
+ let price = this.getPrice(item.product, 'price', order.currency) * item.quantity
969
+
970
+ let tax = item.product.tax
971
+ let taxprice = 0
972
+ if (tax && tax.id) taxprice = (price * tax.percentage) / 10000
973
+
974
+ if (item.discount_type == 'percentage' && !item.discount_before_tax && item.discount_percentage > 0) {
975
+ computed_discount += ((price + taxprice) * item.discount_percentage) / 10000
976
+ } else if (item.discount_type == 'amount') {
977
+ let itemdiscount = this.getPrice(item, 'discount', order.currency)
978
+ if (!item.discount_before_tax && itemdiscount > 0) {
979
+ // CAUTION: easy to miss condition
980
+ if (itemdiscount > price + taxprice) itemdiscount = price + taxprice
981
+ computed_discount += itemdiscount
982
+ }
983
+ }
984
+ })
985
+
986
+ // TAX
987
+ let totaltax = 0
988
+ let taxM = {}
989
+ sb.map(order.items, (item, i) => {
990
+ if (!item.product) return
991
+ let tax = item.product.tax
992
+ if (!tax) return
993
+ if (!tax.id) return
994
+ let price = this.getPrice(item.product, 'price', order.currency) * item.quantity
995
+
996
+ if (item.discount_type) {
997
+ if (item.discount_type == 'percentage') {
998
+ if (item.discount_before_tax && item.discount_percentage > 0) {
999
+ price = price * (1 - item.discount_percentage / 10000)
1000
+ }
1001
+ } else if (item.discount_type == 'amount') {
1002
+ let computed_discount = this.getPrice(item, 'discount', order.currency)
1003
+ if (item.discount_before_tax && computed_discount > 0) {
1004
+ price = price - computed_discount
1005
+ if (price <= 0) price = 0
1006
+ }
1007
+ }
1008
+ }
1009
+ let taxprice = (price * tax.percentage) / 10000
1010
+
1011
+ taxM[i] = {
1012
+ tax: tax,
1013
+ taxprice: taxprice,
1014
+ }
1015
+ })
1016
+
1017
+ // have discount before tax
1018
+ if (order.discount_before_tax) {
1019
+ // decrease tax by discount percentage
1020
+ if (order.discount_type == 'percentage' && order.discount_percentage > 0) {
1021
+ sb.map(taxM, (t) => {
1022
+ t.taxprice = t.taxprice * (1 - order.discount_percentage / 10000)
1023
+ })
1024
+ computed_discount += (subtotal * order.discount_percentage) / 10000
1025
+ } else if (order.discount_type == 'amount') {
1026
+ let discount = this.getPrice(order, 'discount', order.currency)
1027
+ if (subtotal > 0) {
1028
+ sb.map(taxM, (t) => {
1029
+ // CAUTION: easy to miss
1030
+ if (discount > subtotal) discount = subtotal
1031
+
1032
+ t.taxprice = t.taxprice * (1 - discount / subtotal)
1033
+ })
1034
+ }
1035
+ computed_discount += discount
1036
+ }
1037
+ } else {
1038
+ if (order.discount_type == 'percentage' && order.discount_percentage > 0) {
1039
+ let taxprice = 0
1040
+ sb.map(taxM, (t) => (taxprice += t.taxprice))
1041
+ computed_discount += ((subtotal + taxprice) * order.discount_percentage) / 10000
1042
+ } else if (order.discount_type == 'amount') {
1043
+ let discount = this.getPrice(order, 'discount', order.currency)
1044
+ computed_discount += discount
1045
+ }
1046
+ }
1047
+
1048
+ // SHIP
1049
+ let shippingfee = this.getPrice(order.shipping, 'fee', order.currency)
1050
+ if (shippingfee > 0) {
1051
+ if (sb.get(order, 'shipping.tax.id')) {
1052
+ let tax = order.shipping.tax
1053
+ let taxprice = (shippingfee * tax.percentage) / 10000
1054
+ taxM['ship'] = {tax: tax, taxprice: taxprice}
1055
+ }
1056
+ }
1057
+
1058
+ let taxprice = 0
1059
+ sb.map(taxM, (t) => (taxprice += t.taxprice))
1060
+ let total = subtotal + taxprice - computed_discount + shippingfee
1061
+
1062
+ // add adjustment
1063
+ let adj = this.getPrice(order, 'adjustment', order.currency)
1064
+ total += adj
1065
+
1066
+ if (total < 0) total = 0
1067
+ return {subtotal, computed_discount, taxM, total}
1068
+ }
1069
+
933
1070
  replaceFileUrl(src) {
934
1071
  if (!src) return ''
935
1072
 
@@ -1042,7 +1179,7 @@ function getGaClientId() {
1042
1179
  if (!hasGA()) return clientId
1043
1180
 
1044
1181
  var allTrackers = window.ga.getAll() || []
1045
- allTrackers.forEach(function(tracker) {
1182
+ allTrackers.forEach(function (tracker) {
1046
1183
  clientId = tracker.get('clientId')
1047
1184
  })
1048
1185
 
@@ -1059,7 +1196,7 @@ function getGaTrackingIds() {
1059
1196
  if (!hasGA()) return trackingIds
1060
1197
 
1061
1198
  const allTrackers = window.ga.getAll() || []
1062
- allTrackers.forEach(function(tracker) {
1199
+ allTrackers.forEach(function (tracker) {
1063
1200
  var trackingId = tracker.get('trackingId')
1064
1201
  if (trackingId) trackingIds.push(trackingId)
1065
1202
  })
@@ -1077,7 +1214,7 @@ function sendToGA(category, action, label) {
1077
1214
  if (!hasGA()) return
1078
1215
 
1079
1216
  const allTrackers = window.ga.getAll() || []
1080
- allTrackers.forEach(function(tracker) {
1217
+ allTrackers.forEach(function (tracker) {
1081
1218
  const name = tracker.get('name')
1082
1219
  window.ga(name + '.send', 'event', category, action, label)
1083
1220
  })
@@ -1090,7 +1227,7 @@ function sendEventToThirdParty(category, action, label) {
1090
1227
  }
1091
1228
 
1092
1229
  // from http://detectmobilebrowsers.com/
1093
- let mobileCheck = (function(a) {
1230
+ let mobileCheck = (function (a) {
1094
1231
  return (
1095
1232
  /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
1096
1233
  a,
@@ -1101,6 +1238,7 @@ let mobileCheck = (function(a) {
1101
1238
  )
1102
1239
  })(navigator.userAgent || navigator.vendor || window.opera)
1103
1240
 
1104
- let tabletCheck = /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(
1105
- navigator.userAgent,
1106
- )
1241
+ let tabletCheck =
1242
+ /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(
1243
+ navigator.userAgent,
1244
+ )
@@ -1071,6 +1071,12 @@ export function getUrlParameter() {
1071
1071
 
1072
1072
  export var sleep = (ms) => new Promise((res) => setTimeout(res, ms))
1073
1073
 
1074
+ export function formatCurrency(val) {
1075
+ if (!val) return 0
1076
+ val = Math.round(val)
1077
+ return val.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')
1078
+ }
1079
+
1074
1080
  function replaceFileUrl(src) {
1075
1081
  let fileurl = 'https://vcdn.subiz-cdn.com/file/'
1076
1082
  if (!src) return ''