@subiz/widget-v4 4.0.83 → 4.0.87

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 (85) hide show
  1. package/.prettierrc.js +1 -1
  2. package/compiled_src/chatbox/AgentsAvatar.js +20 -3
  3. package/compiled_src/chatbox/ChatButton.js +11 -8
  4. package/compiled_src/chatbox/Event.js +12 -0
  5. package/compiled_src/chatbox/Events.js +1 -0
  6. package/compiled_src/chatbox/MessageInput.js +6 -0
  7. package/compiled_src/chatbox/Typing.js +1 -1
  8. package/compiled_src/chatbox/Widget.js +50 -38
  9. package/compiled_src/chatbox/main.js +10 -0
  10. package/compiled_src/popup/popup.js +21 -2
  11. package/compiled_src/store/store.js +24 -40
  12. package/compiled_src/util/common.js +10 -10
  13. package/dist/132.js +162 -44
  14. package/dist/178.js +174 -341
  15. package/dist/182ed9b853b.132.js +1 -0
  16. package/dist/182ed9b853b.178.js +1 -0
  17. package/dist/{17f00e48d38.213.js → 182ed9b853b.213.js} +1 -1
  18. package/dist/{17f00e48d38.335.js → 182ed9b853b.335.js} +1 -1
  19. package/dist/182ed9b853b.362.js +1 -0
  20. package/dist/182ed9b853b.441.js +1 -0
  21. package/dist/{17f00e48d38.605.js → 182ed9b853b.605.js} +0 -0
  22. package/dist/182ed9b853b.678.js +1 -0
  23. package/dist/182ed9b853b.782.js +1 -0
  24. package/dist/182ed9b853b.app.js +1 -0
  25. package/dist/{17f00e48d38.index.html → 182ed9b853b.index.html} +7 -3
  26. package/dist/{17f00e48d38.library.html → 182ed9b853b.library.html} +7 -3
  27. package/dist/182ed9b853b.library.js +1 -0
  28. package/dist/{17f00e48d38.preview.html → 182ed9b853b.preview.html} +1 -1
  29. package/dist/182ed9b853b.preview.js +1 -0
  30. package/dist/182ed9b853b.screenshoot.js +1 -0
  31. package/dist/213.js +28 -1
  32. package/dist/335.js +2 -2
  33. package/dist/362.js +21 -71
  34. package/dist/441.js +152 -57
  35. package/dist/678.js +20 -70
  36. package/dist/782.js +21 -118
  37. package/dist/HASH +1 -1
  38. package/dist/screenshoot.html +1 -1
  39. package/dist/screenshoot.js +208 -174
  40. package/index.html +1 -1
  41. package/package.json +16 -16
  42. package/src/chatbox/AgentsAvatar.js +32 -10
  43. package/src/chatbox/ChatButton.js +11 -4
  44. package/src/chatbox/Event.js +23 -4
  45. package/src/chatbox/Events.js +3 -1
  46. package/src/chatbox/MessageInput.js +14 -5
  47. package/src/chatbox/Typing.js +10 -11
  48. package/src/chatbox/Widget.js +17 -11
  49. package/src/chatbox/main.js +8 -1
  50. package/src/popup/popup.js +37 -12
  51. package/src/store/store.js +24 -36
  52. package/src/util/common.js +16 -19
  53. package/dist/0b82fa7e5c3b07b40a44.png +0 -1
  54. package/dist/0f4af006e38ee8b93633.png +0 -1
  55. package/dist/17f00e48d38.132.js +0 -1
  56. package/dist/17f00e48d38.178.js +0 -1
  57. package/dist/17f00e48d38.362.js +0 -1
  58. package/dist/17f00e48d38.441.js +0 -1
  59. package/dist/17f00e48d38.678.js +0 -1
  60. package/dist/17f00e48d38.782.js +0 -1
  61. package/dist/17f00e48d38.app.js +0 -1
  62. package/dist/17f00e48d38.library.js +0 -1
  63. package/dist/17f00e48d38.preview.js +0 -1
  64. package/dist/17f00e48d38.screenshoot.js +0 -1
  65. package/dist/1ea1c6cd21d25176810c.png +0 -1
  66. package/dist/292d42404e1b03398f61.png +0 -1
  67. package/dist/312d376370831b7bea83.png +0 -1
  68. package/dist/313d1bfc1cf776d1aefe.png +0 -1
  69. package/dist/4aa58bb7a66bb44975aa.png +0 -1
  70. package/dist/56ce063bc6c81adb7322.png +0 -1
  71. package/dist/6a411166ef5cc79e0714.png +0 -1
  72. package/dist/6faf403782fefacc1649.png +0 -1
  73. package/dist/79dca33c68fab79c067f.png +0 -1
  74. package/dist/82da1578fa84f9debaeb.png +0 -1
  75. package/dist/8b8e0f0824743974b282.png +0 -1
  76. package/dist/8d551390d81e39130a3c.png +0 -1
  77. package/dist/9fc61b9479877ebdb6c7.png +0 -1
  78. package/dist/a165d31dcb3dc90f1057.png +0 -1
  79. package/dist/a98d4a5698812c4426b3.png +0 -1
  80. package/dist/c41606bf9d1b604e46d5.png +0 -1
  81. package/dist/ce1f7450ce6c1aacd330.png +0 -1
  82. package/dist/cf8c01e88f4770a6e3e5.png +0 -1
  83. package/dist/dfbcfeab1d5622a737e2.png +0 -1
  84. package/dist/e4893ed8c2f7b8329919.png +0 -1
  85. package/dist/ec2ab4eb4ef73d186186.png +0 -1
package/index.html CHANGED
@@ -33,7 +33,7 @@
33
33
  window.subiz.q = []
34
34
  // set account it in the very first call
35
35
  window.subiz('setAccount', accid)
36
- window.subiz('expandWidget')
36
+ // window.subiz('expandWidget')
37
37
 
38
38
  if (accid == 'acpxkgumifuoofoosble') {
39
39
  window.subiz('setViewingProduct', {id: '220170', sku: 'ipx', source_id: 'IPHONE10'})
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@subiz/widget-v4",
3
- "version": "4.0.83",
3
+ "version": "4.0.87",
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.22.8",
17
+ "core-js": "^3.25.0",
18
18
  "css-loader": "5.2.7",
19
19
  "file-loader": "^6.2.0",
20
- "less": "^4.1.2",
20
+ "less": "^4.1.3",
21
21
  "less-loader": "^11.0.0",
22
- "marked": "^4.0.16",
23
- "preact": "^10.7.3"
22
+ "marked": "^4.0.19",
23
+ "preact": "^10.10.6"
24
24
  },
25
25
  "devDependencies": {
26
- "@babel/cli": "^7.17.10",
27
- "@babel/core": "^7.18.2",
28
- "@babel/plugin-proposal-class-properties": "^7.17.12",
29
- "@babel/plugin-transform-react-jsx": "^7.17.12",
30
- "@babel/preset-env": "^7.18.2",
26
+ "@babel/cli": "^7.18.10",
27
+ "@babel/core": "^7.18.13",
28
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
29
+ "@babel/plugin-transform-react-jsx": "^7.18.10",
30
+ "@babel/preset-env": "^7.18.10",
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
- "prettier": "^2.6.2",
35
- "puppeteer": "^14.2.1",
36
- "webpack": "^5.73.0",
37
- "webpack-bundle-analyzer": "^4.5.0",
38
- "webpack-cli": "^4.9.2",
39
- "webpack-dev-server": "^4.9.1"
34
+ "prettier": "^2.7.1",
35
+ "puppeteer": "^15.4.0",
36
+ "webpack": "^5.74.0",
37
+ "webpack-bundle-analyzer": "^4.6.1",
38
+ "webpack-cli": "^4.10.0",
39
+ "webpack-dev-server": "^4.10.1"
40
40
  }
41
41
  }
@@ -10,6 +10,26 @@ export default class AgentsAvatar extends Com {
10
10
 
11
11
  render() {
12
12
  let accountSetting = this.props.plugin.chatbox
13
+ let acc = this.props.store.matchAccount()
14
+ var tooltippos = this.props.tooltipPos || 'bottom'
15
+ var mode = this.props.mode || 'primary'
16
+
17
+ if (accountSetting && accountSetting.hide_agent_profile) {
18
+ return (
19
+ <div class={`group-avatar group-avatar--${mode}`}>
20
+ <div class='d-inline-block pos-relative' data-tooltip={acc.name} data-tooltip-position={tooltippos}>
21
+ <img
22
+ width={35}
23
+ height={35}
24
+ alt='agent avatar left'
25
+ class='avatar group-avatar--agent-left'
26
+ src={this.props.store.replaceFileUrl(acc.logo_url) || require('../../assets/img/image_default.png')}
27
+ />
28
+ </div>
29
+ </div>
30
+ )
31
+ }
32
+
13
33
  let agentM = this.props.store.matchAgent('*')
14
34
  var agents = sb.map(this.props.agent_ids, (id) => agentM[id])
15
35
  if (this.props.agent_ids === undefined || sb.size(this.props.agent_ids) === 0) {
@@ -23,10 +43,6 @@ export default class AgentsAvatar extends Com {
23
43
  }
24
44
 
25
45
  agents = sb.filter(agents, (ag) => !!ag)
26
- let acc = this.props.store.matchAccount()
27
-
28
- var tooltippos = this.props.tooltipPos || 'bottom'
29
- var mode = this.props.mode || 'primary'
30
46
  if (agents.length === 0) {
31
47
  // use account avatar
32
48
  return (
@@ -53,7 +69,8 @@ export default class AgentsAvatar extends Com {
53
69
  <div
54
70
  class='d-inline-block pos-relative'
55
71
  data-tooltip={agent.fullname || acc.name}
56
- data-tooltip-position={tooltippos}>
72
+ data-tooltip-position={tooltippos}
73
+ >
57
74
  <img
58
75
  width={35}
59
76
  height={35}
@@ -75,7 +92,8 @@ export default class AgentsAvatar extends Com {
75
92
  <div
76
93
  class='d-inline-block pos-relative'
77
94
  data-tooltip={leftAgent.fullname || acc.name}
78
- data-tooltip-position={tooltippos}>
95
+ data-tooltip-position={tooltippos}
96
+ >
79
97
  <img
80
98
  width={35}
81
99
  height={35}
@@ -89,7 +107,8 @@ export default class AgentsAvatar extends Com {
89
107
  <div
90
108
  class='d-inline-block pos-relative'
91
109
  data-tooltip={rightAgent.fullname || acc.name}
92
- data-tooltip-position={tooltippos}>
110
+ data-tooltip-position={tooltippos}
111
+ >
93
112
  <img
94
113
  alt='agent avatar right'
95
114
  width={35}
@@ -114,7 +133,8 @@ export default class AgentsAvatar extends Com {
114
133
  <div
115
134
  class='d-inline-block pos-relative'
116
135
  data-tooltip={leftAgent.fullname || acc.name}
117
- data-tooltip-position={tooltippos}>
136
+ data-tooltip-position={tooltippos}
137
+ >
118
138
  <img
119
139
  width={35}
120
140
  height={35}
@@ -128,7 +148,8 @@ export default class AgentsAvatar extends Com {
128
148
  <div
129
149
  class='d-inline-block pos-relative'
130
150
  data-tooltip={middleAgent.fullname || acc.name}
131
- data-tooltip-position={tooltippos}>
151
+ data-tooltip-position={tooltippos}
152
+ >
132
153
  <img
133
154
  alt='agent avatar middle'
134
155
  width={35}
@@ -142,7 +163,8 @@ export default class AgentsAvatar extends Com {
142
163
  <div
143
164
  class='d-inline-block pos-relative'
144
165
  data-tooltip={rightAgent.fullname || acc.name}
145
- data-tooltip-position={tooltippos}>
166
+ data-tooltip-position={tooltippos}
167
+ >
146
168
  <img
147
169
  width={35}
148
170
  height={35}
@@ -175,6 +175,13 @@ export default class ChatButton extends Com {
175
175
  position = sb.get(accountSetting, 'mobile_button.position') || position
176
176
  }
177
177
 
178
+ if (accountSetting && accountSetting.hide_agent_profile) {
179
+ agent = Object.assign({}, account, {
180
+ avatar_url: account.logo_url || require('../../assets/img/image_default.png'),
181
+ fullname: account.name || this.props.t('agent'),
182
+ })
183
+ }
184
+
178
185
  let cls = 'widget-preview widget-preview--' + position
179
186
  if (!this.state.displayPreview) cls += ' widget-preview--hidden'
180
187
 
@@ -206,13 +213,13 @@ export default class ChatButton extends Com {
206
213
  }
207
214
 
208
215
  onProfileReady() {
209
- if (this.state.buttonLoaded) this.setState({opacity: 1})
210
- this.setState({profileLoaded: true})
216
+ if (this._buttonLoaded) this.setState({opacity: 1})
217
+ this._profileLoaded = true
211
218
  }
212
219
 
213
220
  onButtonReady() {
214
- if (this.state.profileLoaded) this.setState({opacity: 1})
215
- this.setState({buttonLoaded: true})
221
+ if (this._profileLoaded) this.setState({opacity: 1})
222
+ this._buttonLoaded = true
216
223
  }
217
224
 
218
225
  renderButton() {
@@ -90,6 +90,15 @@ export default class Event extends Com {
90
90
  let acc = this.props.store.matchAccount()
91
91
  var uri = acc.logo_url || require('../../assets/img/image_default.png')
92
92
 
93
+ if (true || sb.get(this.props, 'chatbox.hide_agent_profile')) {
94
+ return (
95
+ <div class='message-sender'>
96
+ <img alt='sender' class='message-sender-avatar' src={this.props.store.replaceFileUrl(uri)} />
97
+ <p class='message-sender-name'>{acc.name}</p>
98
+ </div>
99
+ )
100
+ }
101
+
93
102
  let agentM = this.props.store.matchAgent('*')
94
103
  // should replace with subiz logo
95
104
  if (byid !== 'system' || bytype !== 'dummy') {
@@ -130,7 +139,7 @@ export default class Event extends Com {
130
139
  <AudioAttachments store={this.props.store} ev={ev} />
131
140
  <VideoAttachments store={this.props.store} ev={ev} />
132
141
  <FileAttachments store={this.props.store} ev={ev} />
133
- <ButtonAttachments store={this.props.store} ev={ev} t={this.props.t}/>
142
+ <ButtonAttachments store={this.props.store} ev={ev} t={this.props.t} />
134
143
  <FormAttachments
135
144
  store={this.props.store}
136
145
  onSubmit={this.props.onFormSubmit}
@@ -139,8 +148,18 @@ export default class Event extends Com {
139
148
  t={this.props.t}
140
149
  />
141
150
  <FormSubmitAttachments store={this.props.store} ev={ev} t={this.props.t} />
142
- <GenericTemplateAttachments store={this.props.store} ev={ev} onSelect={(e) => this.choosePostbackBtn(e)} t={this.props.t}/>
143
- <ProductAttachments t={this.props.t} onPostback={(e) => this.choosePostbackBtn(e)} store={this.props.store} ev={ev} />
151
+ <GenericTemplateAttachments
152
+ store={this.props.store}
153
+ ev={ev}
154
+ onSelect={(e) => this.choosePostbackBtn(e)}
155
+ t={this.props.t}
156
+ />
157
+ <ProductAttachments
158
+ t={this.props.t}
159
+ onPostback={(e) => this.choosePostbackBtn(e)}
160
+ store={this.props.store}
161
+ ev={ev}
162
+ />
144
163
  <OrderAttachments t={this.props.t} store={this.props.store} ev={ev} />
145
164
  <QuickReplies store={this.props.store} ev={ev} onSelect={(e) => this.chooseQuickReply(e)} />
146
165
  </div>
@@ -182,7 +201,7 @@ export default class Event extends Com {
182
201
  <AudioAttachments store={this.props.store} ev={ev} />
183
202
  <VideoAttachments store={this.props.store} ev={ev} />
184
203
  <FileAttachments store={this.props.store} ev={ev} />
185
- <ButtonAttachments store={this.props.store} ev={ev} t={this.props.t}/>
204
+ <ButtonAttachments store={this.props.store} ev={ev} t={this.props.t} />
186
205
  <FormAttachments store={this.props.store} onSubmit={this.props.onFormSubmit} ref={this.refForm} ev={ev} />
187
206
  <ProductAttachments t={this.props.t} store={this.props.store} ev={ev} />
188
207
  <FormSubmitAttachments store={this.props.store} ev={ev} />
@@ -57,6 +57,7 @@ export default class Events extends Com {
57
57
 
58
58
  let $events = sb.map(events, (ev) => (
59
59
  <Event
60
+ chatbox={this.props.chatbox}
60
61
  onLink={this.props.onLink}
61
62
  store={this.props.store}
62
63
  onFormSubmit={this.props.onFormSubmit}
@@ -82,7 +83,8 @@ export default class Events extends Com {
82
83
  style={style}
83
84
  ref={(ref) => (this.refBody = ref)}
84
85
  class='widget-body--events-container'
85
- onMouseOver={this.checkAndSeen}>
86
+ onMouseOver={this.checkAndSeen}
87
+ >
86
88
  <div class='widget-body--events'>{$events}</div>
87
89
  <PoweredBy store={this.props.store} />
88
90
  </div>
@@ -21,7 +21,7 @@ export default class MessageInput extends Com {
21
21
  this.forceUpdate()
22
22
  }, 500)
23
23
 
24
- this.resizeInput = sb.throttle(function() {
24
+ this.resizeInput = sb.throttle(function () {
25
25
  // TODO: ctrl+A then press backspace dont reset size rightaway
26
26
  const input = this.refMessageInput.current
27
27
  input.style.setProperty('height', '1em', 'important')
@@ -30,6 +30,12 @@ export default class MessageInput extends Com {
30
30
  }, 5)
31
31
  }
32
32
 
33
+ blur() {
34
+ const $input = this.refMessageInput.current
35
+ if (!$input) return
36
+ $input.blur()
37
+ }
38
+
33
39
  render() {
34
40
  var buttons = (
35
41
  <div class='d-flex flex-row align-self-end'>
@@ -37,7 +43,8 @@ export default class MessageInput extends Com {
37
43
  <div
38
44
  data-tooltip-poasition='top-left'
39
45
  class='message-input--button message-input--attachment-button'
40
- onClick={(e) => this.selectFile(e)}></div>
46
+ onClick={(e) => this.selectFile(e)}
47
+ ></div>
41
48
  </div>
42
49
  )
43
50
  var msg = sb.trim(this.refMessageInput.current && this.refMessageInput.current.value)
@@ -48,7 +55,8 @@ export default class MessageInput extends Com {
48
55
  <div
49
56
  data-tooltip-position='top-left'
50
57
  class='message-input--button message-input--send-button'
51
- onClick={() => this.submitMessage()}></div>
58
+ onClick={() => this.submitMessage()}
59
+ ></div>
52
60
  </div>
53
61
  )
54
62
  }
@@ -62,7 +70,8 @@ export default class MessageInput extends Com {
62
70
  class={`message-input ${containercls}`}
63
71
  onClick={(e) => {
64
72
  this.refMessageInput.current && this.refMessageInput.current.focus()
65
- }}>
73
+ }}
74
+ >
66
75
  <input class='d-none' ref={this.refFileInput} type='file' onChange={(e) => this.sendFile(e)} multiple />
67
76
  <textarea
68
77
  disabled={disabled}
@@ -258,7 +267,7 @@ export default class MessageInput extends Com {
258
267
  input.focus()
259
268
  }
260
269
 
261
- onEnter = sb.throttle(function() {
270
+ onEnter = sb.throttle(function () {
262
271
  this.submitMessage()
263
272
  }, 50)
264
273
 
@@ -1,24 +1,23 @@
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
  export default class Typing extends Com {
6
- constructor (props) {
6
+ constructor(props) {
7
7
  super(props)
8
8
  }
9
9
 
10
- componentDidMount () {
10
+ componentDidMount() {
11
11
  this.setState({
12
12
  isShow: false,
13
13
  ev: {},
14
14
  })
15
15
 
16
- this.props.store.onConvoEvent(this, ev => {
16
+ this.props.store.onConvoEvent(this, (ev) => {
17
17
  if (sb.convoOfEv(ev) !== this.props.cid) return
18
18
  let user = this.props.store.matchUser()
19
19
  if (sb.get(ev, 'by.id') === user.id) return
20
20
 
21
-
22
21
  let oldby = sb.get(this.state.ev, 'by.id')
23
22
  if (oldby && sb.get(ev, 'by.id') !== oldby) return
24
23
 
@@ -26,27 +25,27 @@ export default class Typing extends Com {
26
25
  // stop the typing
27
26
  if (this.timer) clearTimeout(this.timer)
28
27
  this.timer = null
29
- this.setState({ isShow: false })
28
+ this.setState({isShow: false})
30
29
  return
31
30
  }
32
31
 
33
32
  // dont show typing of agent, some agent dont like this
34
- let ag = this.props.store.matchAgent(ev.by.id)
33
+ let ag = this.props.store.matchAgent(ev.by.id) || {}
35
34
  if (ag.type == 'agent') return
36
35
 
37
36
  if (sb.get(ev, 'type') !== 'conversation_typing') return
38
- this.setState({ ev: ev, isShow: true })
37
+ this.setState({ev: ev, isShow: true})
39
38
  if (this.timer) clearTimeout(this.timer)
40
39
  this.timer = setTimeout(() => {
41
40
  if (sb.convoOfEv(ev) !== this.props.cid) return
42
41
 
43
42
  this.timer = null
44
- this.setState({ isShow: false })
43
+ this.setState({isShow: false})
45
44
  }, 5000)
46
45
  })
47
46
  }
48
47
 
49
- render () {
48
+ render() {
50
49
  let account = this.props.store.matchAccount()
51
50
  var cls = this.state.isShow ? '' : 'typing--hidden'
52
51
  let byid = sb.get(this.state.ev, 'by.display_id', sb.get(this.state.ev, 'by.id'))
@@ -18,7 +18,7 @@ const defaultAvatar = 'https://file-subiz.com/fiqoahedjbgwclpouoml-avatar_defaul
18
18
  import Spinner from './spinner.js'
19
19
  import Time from './time.js'
20
20
  import {Com} from '../common.js'
21
- import {h} from 'preact'
21
+ import {h, createRef} from 'preact'
22
22
 
23
23
  // ['cid', 'view', 'isShow'], // view: chat, list
24
24
  export default class Widget extends Com {
@@ -36,6 +36,7 @@ export default class Widget extends Com {
36
36
  this.props.store.onUpdate(this, (_) => this.forceUpdate())
37
37
  }
38
38
 
39
+ msgInput = createRef()
39
40
  componentDidMount() {
40
41
  if (!this.props.store.isMobile()) this.focusInput()
41
42
  }
@@ -148,9 +149,11 @@ export default class Widget extends Com {
148
149
  let data = sb.cloneDeep(this.state.formData)
149
150
  // update user info based on form data
150
151
  let user = sb.cloneDeep(this.props.store.matchUser())
152
+ let is_lead = false
151
153
  sb.map(data, (field, key) => {
152
154
  if (!key.startsWith('attr:')) return
153
155
  var attr = {key: key.substr(5)}
156
+ is_lead = is_lead || key == 'emails' || key == 'phones'
154
157
  if (field.type === 'number') attr.number = parseInt(field.value)
155
158
  if (field.type === 'datetime') attr.datetime = new sb.Date(field.value).toISOString()
156
159
  if (field.type === 'list') attr.list = field.value
@@ -158,6 +161,8 @@ export default class Widget extends Com {
158
161
  sb.setUserAttr(user, attr)
159
162
  })
160
163
 
164
+ if (is_lead) sb.setUserAttr(user, {key: 'lead_source', text: 'widget'})
165
+
161
166
  let firstmsg = sb.get(data, 'question.value')
162
167
  let groupid = sb.get(data, 'group.value', '')
163
168
 
@@ -184,8 +189,8 @@ export default class Widget extends Com {
184
189
  let req = {group_id: groupid, message: firstmsg, locale: this.props.t.locale(), initial_by: user.id}
185
190
 
186
191
  this.setState({creatingError: null})
192
+ await this.props.store.setUser(user)
187
193
  const {error, convo} = await this.props.store.startConvo(req)
188
- this.props.store.setUser(user)
189
194
  if (error) {
190
195
  this.setState({creating: false, creatingError: error})
191
196
  return
@@ -269,7 +274,8 @@ export default class Widget extends Com {
269
274
  value={field.value || ''}
270
275
  onInput={(e) => this.onInputChange(key, e.target.value)}
271
276
  row='4'
272
- class='form-control'></textarea>
277
+ class='form-control'
278
+ ></textarea>
273
279
  )
274
280
  } else {
275
281
  $field = (
@@ -479,7 +485,7 @@ export default class Widget extends Com {
479
485
 
480
486
  blur() {
481
487
  if (this.props.store.isPreview) return
482
- var $input = this.msgInput
488
+ var $input = this.msgInput.current
483
489
  if (!$input) return
484
490
  setTimeout(() => $input && $input.blur())
485
491
  setTimeout(() => $input && $input.blur(), 300) // force lose focus
@@ -507,7 +513,7 @@ export default class Widget extends Com {
507
513
  return
508
514
  }
509
515
 
510
- var $input = this.msgInput
516
+ var $input = this.msgInput.current
511
517
  if (!$input) return
512
518
  setTimeout(() => $input.focus())
513
519
  setTimeout(() => $input.focus(), 300) // force focus
@@ -519,7 +525,7 @@ export default class Widget extends Com {
519
525
  this.focusInput()
520
526
  }
521
527
 
522
- async sendMessage(message) {
528
+ sendMessage = async (message) => {
523
529
  let text = message.text
524
530
  if (!this.props.cid) {
525
531
  this.creating = true
@@ -549,9 +555,9 @@ export default class Widget extends Com {
549
555
  let $input = (
550
556
  <MessageInput
551
557
  store={this.props.store}
552
- ref={(ref) => (this.msgInput = ref)}
558
+ ref={this.msgInput}
553
559
  cid={this.props.cid}
554
- onSend={(e) => this.sendMessage(e)}
560
+ onSend={this.sendMessage}
555
561
  t={this.props.t}
556
562
  />
557
563
  )
@@ -573,6 +579,7 @@ export default class Widget extends Com {
573
579
  isShow={this.props.isShow}
574
580
  onLink={this.onLink}
575
581
  store={this.props.store}
582
+ chatbox={this.props.plugin.chatbox || {}}
576
583
  onFormSubmit={(e) => this.onEventFormSubmit(e)}
577
584
  ref={(ref) => (this.events = ref)}
578
585
  cid={this.props.cid}
@@ -674,6 +681,7 @@ export default class Widget extends Com {
674
681
  }
675
682
 
676
683
  renderConvoSummary(convo) {
684
+ let accountSetting = this.props.plugin.chatbox || {}
677
685
  let agentM = this.props.store.matchAgent('*')
678
686
 
679
687
  let ags = sb.filter(convo.members, (m) => {
@@ -683,9 +691,8 @@ export default class Widget extends Com {
683
691
  agentids = agentids || sb.agentsOfConvo(convo)[0]
684
692
 
685
693
  let agents = sb.map(agentids, (id) => agentM[id] || {avatar_url: defaultAvatar, fullname: 'Offline Agent'})
686
-
687
694
  var name = sb.each(agents, (ag) => ag.fullname).join(', ')
688
- if (!name) name = this.props.store.matchAccount().name
695
+ if (accountSetting.hide_agent_profile || !name) name = this.props.store.matchAccount().name
689
696
  if (!name) name = this.props.t('agent')
690
697
 
691
698
  var $you = null
@@ -694,7 +701,6 @@ export default class Widget extends Com {
694
701
  }
695
702
 
696
703
  let seen = sb.isConvoSeen(convo, this.props.store.matchUser().id)
697
-
698
704
  var lastmsg = this.renderMessagePreview(convo.last_message_sent || {data: {message: sb.get(convo, 'last_message')}})
699
705
 
700
706
  var time =
@@ -125,8 +125,15 @@ export default class Main extends Com {
125
125
  }
126
126
  p = p || {}
127
127
 
128
- if (this.props.store.isMobile()) modifyViewport()
128
+ if (!p.view && !p.cid) {
129
+ let convoM = this.props.store.matchConvo('*')
130
+ let redconvo = sb.find(convoM, (convo) => !sb.isConvoSeen(convo, this.props.store.matchUser().id))
131
+ // try to show first convo
132
+ p.cid = sb.get(redconvo, 'id', sb.get(convoM, '0.id'))
133
+ p.view = 'chat'
134
+ }
129
135
 
136
+ if (this.props.store.isMobile()) modifyViewport()
130
137
  this.setState({widgetConvoId: p.cid, widgetView: p.view})
131
138
  this.props.store.setIsOpen(true)
132
139
 
@@ -156,7 +156,8 @@ export default class Popup extends Com {
156
156
  height='24'
157
157
  viewBox='0 0 24 24'
158
158
  stroke-linecap='round'
159
- stroke-linejoin='round'>
159
+ stroke-linejoin='round'
160
+ >
160
161
  <line x1='17' y1='7' x2='7' y2='17' style='stroke-width: 3 !important;'></line>
161
162
  <line x1='7' y1='7' x2='17' y2='17' style='stroke-width: 3 !important;'></line>
162
163
  </svg>
@@ -213,12 +214,26 @@ export default class Popup extends Com {
213
214
  var summitFields = []
214
215
 
215
216
  let user = sb.cloneDeep(this.props.store.matchUser())
217
+ let is_lead = false
218
+
219
+ // modified pairs to convert data of multiple-choice value ['khu_vuc', '1'], ['khu_vuc', '2'] => ['khu_vuc', '1,2']
220
+ let modifiedPairs = {}
216
221
  for (var pair of formData.entries()) {
222
+ if (modifiedPairs[pair[0]]) {
223
+ let currentValue = sb.get(modifiedPairs, `${pair[0]}.1`, '')
224
+ currentValue += `,${pair[1]}`
225
+ sb.set(modifiedPairs, `${pair[0]}.1`, currentValue)
226
+ } else {
227
+ modifiedPairs[pair[0]] = [pair[0], pair[1]]
228
+ }
229
+ }
230
+
231
+ for (const [_, pair] of Object.entries(modifiedPairs)) {
217
232
  let page = sb.get(this.props.plugin.popup, `pages.${this.getPageIndex()}`)
218
233
  let form = sb.find(page.components, (com) => com.type === 'form')
219
234
  let fields = sb.get(form, 'form.fields', [])
220
235
 
221
- let field = sb.find(fields, (field) => field.key === pair[0])
236
+ let field = sb.find(fields, (field) => field.key === pair[0]) || {}
222
237
  if (!field.type) return
223
238
 
224
239
  summitFields.push({key: pair[0], type: field.type, value: sb.stringify(pair[1])})
@@ -226,10 +241,12 @@ export default class Popup extends Com {
226
241
  let key = pair[0]
227
242
  if (key === 'email') key = 'emails'
228
243
  if (key === 'phone') key = 'phones'
229
-
244
+ is_lead = is_lead || key == 'emails' || key == 'phones'
230
245
  sb.setUserAttr(user, {key: key, text: pair[1]})
231
246
  }
247
+ if (is_lead) sb.setUserAttr(user, {key: 'lead_source', text: 'plugin.' + this.props.plugin.id})
232
248
  this.props.store.sendConversion(this.props.plugin.id, summitFields, this.impressionToken)
249
+
233
250
  this.props.store.setUser(user)
234
251
  }
235
252
 
@@ -277,7 +294,8 @@ export default class Popup extends Com {
277
294
  <div
278
295
  class={'btn btn__primary '}
279
296
  style={this.js2css(primarystyle)}
280
- onClick={(e) => this.onButtonClick(e, 'primary')}>
297
+ onClick={(e) => this.onButtonClick(e, 'primary')}
298
+ >
281
299
  {this.props.t.i18n(com.buttons.i18n_primary_text) || com.buttons.primary_text}
282
300
  </div>
283
301
  )
@@ -290,7 +308,8 @@ export default class Popup extends Com {
290
308
  <div
291
309
  class={'btn btn__secondary'}
292
310
  style={this.js2css(style)}
293
- onClick={(e) => this.onButtonClick(e, 'secondary')}>
311
+ onClick={(e) => this.onButtonClick(e, 'secondary')}
312
+ >
294
313
  {this.props.t.i18n(com.buttons.i18n_secondary_text) || com.buttons.secondary_text}
295
314
  </div>
296
315
  )
@@ -303,7 +322,8 @@ export default class Popup extends Com {
303
322
  display: 'flex',
304
323
  flex_direction: buttonsstyle.flex_direction,
305
324
  align_items: buttonsstyle.align_items,
306
- })}>
325
+ })}
326
+ >
307
327
  {$primary}
308
328
  <div style={this.js2css({width: '10px', height: '1px'})} />
309
329
  {$secondary}
@@ -503,7 +523,8 @@ export default class Popup extends Com {
503
523
  color: popup.text_color,
504
524
  font_family: popup.font_family,
505
525
  font_size: popup.font_size || '14px',
506
- })}>
526
+ })}
527
+ >
507
528
  {this.props.t.i18n(field.i18n_label) || field.label}
508
529
  </div>
509
530
  )
@@ -517,7 +538,8 @@ export default class Popup extends Com {
517
538
  $error = (
518
539
  <div
519
540
  class='text__danger '
520
- style={this.js2css({margin_top: '5px', font_family: popup.font_family, font_size: popup.font_size})}>
541
+ style={this.js2css({margin_top: '5px', font_family: popup.font_family, font_size: popup.font_size})}
542
+ >
521
543
  {this.props.t('invalid_field')}
522
544
  </div>
523
545
  )
@@ -527,7 +549,8 @@ export default class Popup extends Com {
527
549
  $error = (
528
550
  <div
529
551
  class='text__danger '
530
- style={this.js2css({margin_top: '5px', font_family: popup.font_family, font_size: popup.font_size})}>
552
+ style={this.js2css({margin_top: '5px', font_family: popup.font_family, font_size: popup.font_size})}
553
+ >
531
554
  {this.props.t('required')}
532
555
  </div>
533
556
  )
@@ -547,7 +570,8 @@ export default class Popup extends Com {
547
570
  style={this.js2css(com.style)}
548
571
  class='form popup_component'
549
572
  ref={this._formRef}
550
- onClick={(e) => e.stopPropagation()}>
573
+ onClick={(e) => e.stopPropagation()}
574
+ >
551
575
  {$fields}
552
576
  </form>
553
577
  )
@@ -600,7 +624,8 @@ export default class Popup extends Com {
600
624
  <span
601
625
  style={this.js2css(
602
626
  Object.assign({white_space: 'nowrap', overflow: 'hidden', text_overflow: 'ellipsis'}, textstyle),
603
- )}>
627
+ )}
628
+ >
604
629
  {this.props.t('follow_us_on_facebook')}
605
630
  </span>
606
631
  </div>
@@ -919,7 +944,7 @@ export default class Popup extends Com {
919
944
  if (com.type === 'image') return this.renderImageComponent(com, i)
920
945
  })
921
946
 
922
- // fix bug image only popup has white block
947
+ // fix bug image only popup has white block
923
948
  let formComponents = sb.filter(page.components, (com) => com.type !== 'image')
924
949
  if (!formComponents.length) {
925
950
  formcss.background = 'transparent'