@subiz/widget-v4 4.1.198 → 4.1.200

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 (70) hide show
  1. package/assets/img/default_avatar.png +0 -0
  2. package/assets/img/default_logo.png +0 -0
  3. package/assets/img/default_logo.svg +5 -0
  4. package/assets/less/avatar.less +2 -2
  5. package/assets/less/message.less +6 -1
  6. package/assets/less/widget.less +1 -1
  7. package/assets/less/widget_header.less +2 -1
  8. package/compiled_src/bot.js +3 -18
  9. package/compiled_src/chatbox/Event.js +1 -1
  10. package/compiled_src/chatbox/Events.js +3 -1
  11. package/compiled_src/chatbox/Header.js +2 -2
  12. package/compiled_src/chatbox/QuickReplies.js +2 -1
  13. package/compiled_src/chatbox/Widget.js +2 -1
  14. package/compiled_src/lib.js +2 -1
  15. package/compiled_src/plugin.js +1 -0
  16. package/compiled_src/store/store.js +26 -18
  17. package/compiled_src/util/common.js +27 -14
  18. package/compiled_src/util/common.test.js +43 -133
  19. package/dist/132.js +21 -21
  20. package/dist/185.js +49 -49
  21. package/dist/{19bbfd5aa77.132.js → 19c2dd58182.132.js} +1 -1
  22. package/dist/19c2dd58182.185.js +1 -0
  23. package/dist/19c2dd58182.278.js +1 -0
  24. package/dist/19c2dd58182.339.js +1 -0
  25. package/dist/19c2dd58182.459.js +1 -0
  26. package/dist/19c2dd58182.app.js +1 -0
  27. package/dist/{19bbfd5aa77.chat.html → 19c2dd58182.chat.html} +1 -1
  28. package/dist/19c2dd58182.chat.js +1 -0
  29. package/dist/{19bbfd5aa77.form.html → 19c2dd58182.form.html} +1 -1
  30. package/dist/19c2dd58182.form.js +1 -0
  31. package/dist/{19bbfd5aa77.index.html → 19c2dd58182.index.html} +1 -1
  32. package/dist/{19bbfd5aa77.library.html → 19c2dd58182.library.html} +1 -1
  33. package/dist/19c2dd58182.library.js +1 -0
  34. package/dist/{19bbfd5aa77.preview.html → 19c2dd58182.preview.html} +1 -1
  35. package/dist/19c2dd58182.preview.js +1 -0
  36. package/dist/19c2dd58182.webview.js +1 -0
  37. package/dist/459.js +11 -11
  38. package/dist/74.js +1 -0
  39. package/dist/HASH +1 -1
  40. package/dist/assets/img/default_avatar.e449b04.png +0 -0
  41. package/dist/assets/img/default_logo.dd13a2b.svg +5 -0
  42. package/dist/screenshoot.js +3053 -3038
  43. package/package.json +13 -12
  44. package/src/bot.js +4 -14
  45. package/src/chatbox/Event.js +1 -1
  46. package/src/chatbox/Events.js +3 -2
  47. package/src/chatbox/Header.js +2 -2
  48. package/src/chatbox/QuickReplies.js +10 -10
  49. package/src/chatbox/Widget.js +3 -2
  50. package/src/lib.js +3 -1
  51. package/src/plugin.js +1 -0
  52. package/src/store/store.js +23 -13
  53. package/src/util/common.js +31 -16
  54. package/src/util/common.test.js +108 -193
  55. package/dist/19bbfd5aa77.185.js +0 -1
  56. package/dist/19bbfd5aa77.278.js +0 -1
  57. package/dist/19bbfd5aa77.339.js +0 -1
  58. package/dist/19bbfd5aa77.459.js +0 -1
  59. package/dist/19bbfd5aa77.app.js +0 -1
  60. package/dist/19bbfd5aa77.chat.js +0 -1
  61. package/dist/19bbfd5aa77.form.js +0 -1
  62. package/dist/19bbfd5aa77.library.js +0 -1
  63. package/dist/19bbfd5aa77.preview.js +0 -1
  64. package/dist/19bbfd5aa77.webview.js +0 -1
  65. package/dist/assets/img/default_avatar.5b74dc1.png +0 -0
  66. /package/dist/{19bbfd5aa77.127.js → 19c2dd58182.127.js} +0 -0
  67. /package/dist/{19bbfd5aa77.27.js → 19c2dd58182.27.js} +0 -0
  68. /package/dist/{19bbfd5aa77.490.js → 19c2dd58182.490.js} +0 -0
  69. /package/dist/{19bbfd5aa77.74.js → 19c2dd58182.74.js} +0 -0
  70. /package/dist/{19bbfd5aa77.997.js → 19c2dd58182.997.js} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@subiz/widget-v4",
3
- "version": "4.1.198",
3
+ "version": "4.1.200",
4
4
  "main": "./compiled_src/lib.js",
5
5
  "scripts": {
6
6
  "dev": "npx webpack serve --config webpack.dev.js",
@@ -13,26 +13,27 @@
13
13
  "@subiz/flow": "^1.1.0",
14
14
  "@subiz/wsclient": "^4.0.34",
15
15
  "cookie_js": "1.4.2",
16
- "core-js": "^3.47.0",
16
+ "core-js": "^3.49.0",
17
17
  "css-loader": "5.2.7",
18
18
  "file-loader": "^6.2.0",
19
- "less": "^4.5.1",
20
- "less-loader": "^12.3.0",
19
+ "less": "^4.6.4",
20
+ "less-loader": "^12.3.2",
21
21
  "preact": "10.19.3"
22
22
  },
23
23
  "devDependencies": {
24
+ "tape": "^5.9.0",
24
25
  "@babel/cli": "^7.28.6",
25
- "@babel/core": "^7.28.6",
26
+ "@babel/core": "^7.29.0",
26
27
  "@babel/plugin-proposal-class-properties": "^7.18.6",
27
28
  "@babel/plugin-transform-react-jsx": "^7.28.6",
28
- "@babel/preset-env": "^7.28.6",
29
- "babel-loader": "^10.0.0",
29
+ "@babel/preset-env": "^7.29.2",
30
+ "babel-loader": "^10.1.1",
30
31
  "babel-plugin-syntax-jsx": "^6.18.0",
31
- "html-webpack-plugin": "^5.6.5",
32
- "puppeteer": "^24.35.0",
33
- "webpack": "^5.104.1",
34
- "webpack-bundle-analyzer": "^5.1.1",
35
- "webpack-cli": "^6.0.1",
32
+ "html-webpack-plugin": "^5.6.6",
33
+ "puppeteer": "^24.40.0",
34
+ "webpack": "^5.105.4",
35
+ "webpack-bundle-analyzer": "^5.2.0",
36
+ "webpack-cli": "^7.0.2",
36
37
  "webpack-dev-server": "^5.2.3"
37
38
  }
38
39
  }
package/src/bot.js CHANGED
@@ -11,27 +11,17 @@ export default function (store) {
11
11
  run = () => true // dont run twice
12
12
  let match = sb.checkRunConditions(bot.initiative_frequency, bot.conditions, store.matchLastBotRun(bot.id), store)
13
13
  if (!match) return
14
- if (bot.id.startsWith('at')) {
15
- if (!bot.welcome_message) return
14
+
15
+ let welcomMessages = bot.welcome_messages
16
+ if (sb.size(welcomMessages)) {
16
17
  let {error} = await store.startLightConvo(
17
18
  bot.id,
18
- bot.welcome_message,
19
+ bot.welcome_messages,
19
20
  common.getLocale(bot, sb.detectLang()),
20
21
  false,
21
22
  )
22
- if (error) return console.error(error)
23
23
  store.logBotRun(bot.id)
24
- return
25
24
  }
26
- // old bot, should deprecated
27
- let {error} = await store.startConvo({
28
- initial_by: bot.id,
29
- locale: common.getLocale(bot, sb.detectLang()),
30
- state: 'active',
31
- members: [{type: 'bot', id: bot.id}],
32
- })
33
- if (error) return console.error(error)
34
- store.logBotRun(bot.id)
35
25
  }
36
26
 
37
27
  let triggers = sb.get(bot, 'triggers') || []
@@ -451,7 +451,7 @@ export default class Event extends Com {
451
451
  <div class='message-event-action-btn-svg dislike' />
452
452
  </div>
453
453
  </div>
454
- {sb.get(this.props.event, 'is_end') && (
454
+ {sb.get(this.props.event, 'is_end') && !this.props.isConvoEnded && (
455
455
  <div class='message-event-actions-static'>
456
456
  <div class={likecls} onClick={() => this.onSendReaction(hasLike ? 'remove_like' : 'like')}>
457
457
  <div class='message-event-action-btn-svg like' />
@@ -148,7 +148,7 @@ export default class Events extends Com {
148
148
  events.push(fakeev)
149
149
 
150
150
  let $events = sb.map(events, (ev) => {
151
- let isLast = ev.is_last_message_send
151
+ let isLast = ev.is_last_message_send && sb.get(convo, 'state') !== 'ended'
152
152
  return (
153
153
  <Event
154
154
  isLast={isLast}
@@ -160,6 +160,7 @@ export default class Events extends Com {
160
160
  onPostback={this.props.onPostback}
161
161
  onFocusSourceEventFromQuote={this.onFocusSourceEventFromQuote}
162
162
  ref={(ele) => this.setEventChildRef(ele, ev.ev.id)}
163
+ isConvoEnded={sb.get(convo, 'state') === 'ended'}
163
164
  event={ev}
164
165
  t={this.props.t}
165
166
  key={ev.ev.id}
@@ -206,7 +207,7 @@ export default class Events extends Com {
206
207
  if (this.state.loading) $tryAgainBtn = <Spinner size='16' mode='blue' />
207
208
  return (
208
209
  <div class='widget-body--events-container widget-body--events-container__error'>
209
- <img alt='empty' src={convoemptyimg} />
210
+ <img alt='empty' class='widget_body_empty_img' src={convoemptyimg} />
210
211
  <div class='widget_body__events__error_msg'>{this.props.t('load_convo_error')}</div>
211
212
  <div class='widget_body__events__error_retry'>{$tryAgainBtn}</div>
212
213
  </div>
@@ -20,7 +20,7 @@ export default class Header extends Com {
20
20
  height={38}
21
21
  alt={acc.name}
22
22
  class='avatar avatar__account'
23
- src={this.props.store.replaceFileUrl(logo_url) || require('../../assets/img/image_default.png')}
23
+ src={this.props.store.replaceFileUrl(logo_url) || require('../../assets/img/default_logo.svg')}
24
24
  />
25
25
  )
26
26
  }
@@ -37,7 +37,7 @@ export default class Header extends Com {
37
37
  width={38}
38
38
  height={38}
39
39
  class='avatar avatar__account'
40
- src={this.props.store.replaceFileUrl(logoUrl) || require('../../assets/img/image_default.png')}
40
+ src={this.props.store.replaceFileUrl(logoUrl) || require('../../assets/img/default_logo.svg')}
41
41
  />
42
42
  )
43
43
  }
@@ -1,25 +1,25 @@
1
1
  import sb from '../util/index.js'
2
- import { Com } from '../common.js'
3
- import { h } from 'preact'
2
+ import {Com} from '../common.js'
3
+ import {h} from 'preact'
4
4
 
5
5
  // props: [ ev],
6
6
  export default class QuickReplies extends Com {
7
- constructor (props) {
7
+ constructor(props) {
8
8
  super(props)
9
9
  }
10
10
 
11
- render () {
11
+ render() {
12
12
  if (sb.get(this.props.ev, 'by.type') === 'user') return null
13
13
 
14
14
  let quickreplies = []
15
- sb.map(sb.get(this.props.ev, 'data.message.attachments', []), att => {
15
+ sb.map(sb.get(this.props.ev, 'data.message.attachments', []), (att) => {
16
16
  if (!att) return
17
17
  if (att.type === 'quick_replies') {
18
18
  quickreplies = sb.get(att, 'quick_replies', [])
19
19
  }
20
20
  })
21
21
 
22
- quickreplies = sb.filter(quickreplies, r => r.title)
22
+ quickreplies = sb.filter(quickreplies, (r) => r.title)
23
23
 
24
24
  if (quickreplies.length === 0) return null
25
25
 
@@ -29,7 +29,7 @@ export default class QuickReplies extends Com {
29
29
 
30
30
  // has user msg bellow => dont show
31
31
  let events = sb.map(this.props.store.listEvents(cid))
32
- events = sb.orderBy(events, 'created', 'asc').filter(ev => ev.type === 'message_sent')
32
+ events = sb.orderBy(events, 'created', 'asc').filter((ev) => ev.type === 'message_sent')
33
33
  let evindex = 0
34
34
  for (var i = 0; i < events.length; i++) {
35
35
  if (events[i].id === this.props.ev.id) {
@@ -42,12 +42,12 @@ export default class QuickReplies extends Com {
42
42
  if (sb.get(events[i], 'by.type') === 'user') return null
43
43
  }
44
44
 
45
- let $replies = sb.map(quickreplies, r => (
46
- <div class="message_quick_reply" onClick={e => this.props.onSelect(r)}>
45
+ let $replies = sb.map(quickreplies, (r) => (
46
+ <div class='message_quick_reply' onClick={(e) => this.props.onSelect(r)} title={r.title}>
47
47
  {r.title}
48
48
  </div>
49
49
  ))
50
50
 
51
- return <div class="message_quick_replies">{$replies}</div>
51
+ return <div class='message_quick_replies'>{$replies}</div>
52
52
  }
53
53
  }
@@ -70,6 +70,7 @@ export default class Widget extends Com {
70
70
 
71
71
  console.log('check ev pass condition', ev)
72
72
  if (!messageSentDict[ev.id]) {
73
+ let accid = sb.get(this.props.store.matchAccount(), 'id')
73
74
  this.props.store.sendBugReport(
74
75
  '[WIDGET ' + accid + '] Missing agent message sent evid ' + ev.id + ', cid ' + sb.convoOfEv(ev),
75
76
  )
@@ -753,7 +754,7 @@ export default class Widget extends Com {
753
754
  $body = (
754
755
  <div class='convo-list--list'>
755
756
  <div class='empty-container'>
756
- <img alt='empty' src={empty} />
757
+ <img class='widget_body_empty_img' alt='empty' src={empty} />
757
758
  <div class='empty-desc'>{this.props.t('empty_convo')}</div>
758
759
  </div>
759
760
  </div>
@@ -855,7 +856,7 @@ export default class Widget extends Com {
855
856
  locale: this.props.t.locale(),
856
857
  message: text,
857
858
  members: [{type: 'bot', id: botid, bot_version: oldconvo.bot_version}],
858
- initial_by: this.props.store.matchUser().id,
859
+ initial_by: botid,
859
860
  is_testing: oldconvo.is_testing,
860
861
  greeting_message: greeting_msg,
861
862
  })
package/src/lib.js CHANGED
@@ -84,6 +84,8 @@ class Widget {
84
84
  let ref = param.ref
85
85
 
86
86
  let user = await this.store.init(accid, undefined, ref, param)
87
+
88
+ if (this.store.isDead()) return user
87
89
  sb.setTimeout(() => window.postMessage({type: 'widget_loaded', account_id: accid}, '*'), 0) // send to chrome extension
88
90
 
89
91
  // add container to client site
@@ -266,7 +268,7 @@ class Widget {
266
268
  startConvo(req) {
267
269
  req = sb.cloneDeep(req) || {}
268
270
  if (req.welcome_message) {
269
- return this.store.startLightConvo(req.bot_id, req.welcome_message, req.locale, req.is_testing, req.bot_version)
271
+ return this.store.startLightConvo(req.bot_id, [req.welcome_message], req.locale, req.is_testing, req.bot_version)
270
272
  }
271
273
  let members = req.members || []
272
274
  if (req.bot_id) {
package/src/plugin.js CHANGED
@@ -12,6 +12,7 @@ function Plugin(plugin, store, $container, lib) {
12
12
  if (!$container) throw '$div must is a valid html node'
13
13
  var $div = document.createElement('div')
14
14
  $div.id = plugin.id
15
+ if (store.isDead()) return
15
16
  let acc = store.matchAccount()
16
17
  $div.setAttribute('sbz-plugin-type', plugin.type)
17
18
  $div.setAttribute('sbz-plugin-account-id', acc.id)
@@ -846,7 +846,7 @@ export default class Store {
846
846
  setting = sb.cloneDeep(setting) || {}
847
847
  setting.account = Object.assign({}, setting.account, this.forceAcc)
848
848
  if (!setting.account.logo_url) {
849
- setting.account.logo_url = 'https://vcdn.subiz-cdn.com/file/fiqpezhkmeyesdscyetk-default_logo.jpg'
849
+ setting.account.logo_url = 'https://vcdn.subiz-cdn.com/widget-v4/public/assets/img/default_logo.dd13a2b.svg'
850
850
  }
851
851
  // user && session
852
852
  if (setting.user) {
@@ -1121,28 +1121,34 @@ export default class Store {
1121
1121
  this.kv.put('light_convos', this.lightConvos)
1122
1122
  }
1123
1123
 
1124
- startLightConvo(botid, message, locale, is_testing, botversion) {
1124
+ startLightConvo(botid, messages, locale, is_testing, botversion) {
1125
1125
  let convoid = 'cslight' + botid + '_' + this.now()
1126
1126
  let user = this.cache.match('user') || {}
1127
1127
 
1128
1128
  let old = this.lightConvos[convoid]
1129
1129
  if (old) return {convo: old}
1130
1130
  let now = this.now()
1131
- let ev = {}
1132
- ev.created = now
1133
- ev.event_time = now
1134
- ev.id = 'evfake' + now
1135
- ev.type = 'message_sent'
1136
- ev.by = {id: botid, type: 'bot'}
1137
- ev.data = {message: message}
1138
- ev.data.message.conversation_id = convoid
1131
+
1132
+ let lastev = {}
1133
+ let newevs = sb.map(messages, (message, idx) => {
1134
+ let ev = {}
1135
+ ev.created = now
1136
+ ev.event_time = now
1137
+ ev.id = 'evfake' + now + idx
1138
+ ev.type = 'message_sent'
1139
+ ev.by = {id: botid, type: 'bot'}
1140
+ ev.data = {message: message}
1141
+ ev.data.message.conversation_id = convoid
1142
+ lastev = ev
1143
+ return ev
1144
+ })
1139
1145
  let newconvo = {
1140
1146
  id: convoid,
1141
1147
  locale: locale,
1142
1148
  initial_by: botid,
1143
1149
  created: now,
1144
1150
  actived: now,
1145
- last_message_sent: ev,
1151
+ last_message_sent: lastev,
1146
1152
  members: [
1147
1153
  {type: 'user', id: user.id},
1148
1154
  {type: 'bot', id: botid, membership: 'active'},
@@ -1150,13 +1156,14 @@ export default class Store {
1150
1156
  state: 'active',
1151
1157
  touchpoint: {id: convoid, channel: 'subiz', source: 'web'},
1152
1158
  traffic_source: 'direct',
1153
- events: [ev],
1159
+ events: newevs,
1160
+ //events: [ev],
1154
1161
  is_testing: is_testing,
1155
1162
  bot_versio: botversion,
1156
1163
  }
1157
1164
  this.lightConvos[convoid] = newconvo
1158
1165
  this.kv.put('light_convos', this.lightConvos)
1159
- this.pubsub.publish('events', ev)
1166
+ this.pubsub.publish('events', lastev)
1160
1167
  return {convo: newconvo}
1161
1168
  }
1162
1169
 
@@ -1467,6 +1474,9 @@ export default class Store {
1467
1474
  this.pubsub.publish('destroy')
1468
1475
  }
1469
1476
 
1477
+ isDead() {
1478
+ return this._die
1479
+ }
1470
1480
  destroy() {
1471
1481
  this._die = true
1472
1482
  this.clearBrowserData()
@@ -950,22 +950,8 @@ export function checkRunConditions(freq, conds, lastrun, store) {
950
950
  var cond = conds[i]
951
951
  switch (cond.key) {
952
952
  case 'url':
953
- let exclude_urls = filter(cond.exclude_urls, (url) => norm(url))
954
- if (size(exclude_urls) > 0) {
955
- let found = find(exclude_urls, (url) => {
956
- return norm(window.location.href).indexOf(norm(url)) > -1
957
- })
958
- if (found) return false
959
- }
960
-
961
- // ignore empty url
962
- let urls = filter(cond.urls, (url) => norm(url))
963
- if (size(urls) > 0) {
964
- let found = find(urls, (url) => {
965
- return norm(window.location.href).indexOf(norm(url)) > -1
966
- })
967
- if (!found) return false
968
- }
953
+ // url = qlhd.minvoice.com.vn, exclude_urls ["minvoice.com.vn","minvoice.net","hdt.minvoice.com.vn"], urls ["qlhd.minvoice.com.vn"] => must pass
954
+ if (!checkUrlCondition(cond, window.location.href)) return false
969
955
  break
970
956
  case 'url_path':
971
957
  let excludePaths = filter(cond.exclude_url_paths, (url) => norm(url))
@@ -1616,3 +1602,32 @@ function isEmptyAttachment(msg) {
1616
1602
  ) == 0
1617
1603
  )
1618
1604
  }
1605
+ export function checkUrlCondition(cond, href) {
1606
+ // url = qlhd.minvoice.com.vn, exclude_urls ["minvoice.com.vn","minvoice.net","hdt.minvoice.com.vn"], urls ["qlhd.minvoice.com.vn"] => must pass
1607
+ let exclude_urls = filter(cond.exclude_urls, (url) => norm(url))
1608
+ let foundExclude = false
1609
+ let excludeLen = 0
1610
+ map(exclude_urls, (url) => {
1611
+ if (norm(href).indexOf(url) > -1) {
1612
+ if (excludeLen < size(url)) excludeLen = size(url)
1613
+ foundExclude = true
1614
+ }
1615
+ })
1616
+
1617
+ // ignore empty url
1618
+ let includeLen = 0
1619
+ let urls = filter(cond.urls, (url) => norm(url))
1620
+ let foundInclude = size(urls) == 0
1621
+ map(urls, (url) => {
1622
+ if (norm(href).indexOf(url) > -1) {
1623
+ if (includeLen < size(url)) includeLen = size(url)
1624
+ foundInclude = true
1625
+ }
1626
+ })
1627
+ if (foundExclude) {
1628
+ if (excludeLen >= includeLen) return false
1629
+ }
1630
+
1631
+ if (!foundInclude) return false
1632
+ return true
1633
+ }