@subiz/widget-v4 4.1.153 → 4.1.156

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 (48) hide show
  1. package/cloudflare_worker.js +4 -2
  2. package/compiled_src/bot.js +9 -0
  3. package/compiled_src/chatbox/AgentsAvatar.js +7 -6
  4. package/compiled_src/chatbox/ChatButton.js +25 -14
  5. package/compiled_src/chatbox/Widget.js +41 -0
  6. package/compiled_src/chatbox/main.js +18 -6
  7. package/compiled_src/store/api.js +52 -1
  8. package/compiled_src/store/store.js +101 -13
  9. package/dist/{197f55a88dc.278.js → 1986e37f014.278.js} +1 -1
  10. package/dist/1986e37f014.app.js +1 -0
  11. package/dist/{197f55a88dc.chat.html → 1986e37f014.chat.html} +1 -1
  12. package/dist/1986e37f014.chat.js +1 -0
  13. package/dist/{197f55a88dc.form.html → 1986e37f014.form.html} +1 -1
  14. package/dist/1986e37f014.form.js +1 -0
  15. package/dist/{197f55a88dc.index.html → 1986e37f014.index.html} +1 -1
  16. package/dist/{197f55a88dc.library.html → 1986e37f014.library.html} +1 -1
  17. package/dist/1986e37f014.library.js +1 -0
  18. package/dist/{197f55a88dc.preview.html → 1986e37f014.preview.html} +1 -1
  19. package/dist/1986e37f014.preview.js +1 -0
  20. package/dist/1986e37f014.webview.js +1 -0
  21. package/dist/278.js +1 -1
  22. package/dist/HASH +1 -1
  23. package/dist/malicious-app.js +15 -13
  24. package/dist/screenshoot.js +71 -8
  25. package/malicious-app.js +15 -13
  26. package/package.json +5 -5
  27. package/src/bot.js +8 -1
  28. package/src/chatbox/AgentsAvatar.js +30 -12
  29. package/src/chatbox/ChatButton.js +30 -17
  30. package/src/chatbox/Widget.js +27 -0
  31. package/src/chatbox/main.js +19 -6
  32. package/src/store/api.js +50 -1
  33. package/src/store/store.js +92 -17
  34. package/dist/197f55a88dc.app.js +0 -1
  35. package/dist/197f55a88dc.chat.js +0 -1
  36. package/dist/197f55a88dc.form.js +0 -1
  37. package/dist/197f55a88dc.library.js +0 -1
  38. package/dist/197f55a88dc.preview.js +0 -1
  39. package/dist/197f55a88dc.webview.js +0 -1
  40. /package/dist/{197f55a88dc.127.js → 1986e37f014.127.js} +0 -0
  41. /package/dist/{197f55a88dc.132.js → 1986e37f014.132.js} +0 -0
  42. /package/dist/{197f55a88dc.185.js → 1986e37f014.185.js} +0 -0
  43. /package/dist/{197f55a88dc.27.js → 1986e37f014.27.js} +0 -0
  44. /package/dist/{197f55a88dc.339.js → 1986e37f014.339.js} +0 -0
  45. /package/dist/{197f55a88dc.459.js → 1986e37f014.459.js} +0 -0
  46. /package/dist/{197f55a88dc.490.js → 1986e37f014.490.js} +0 -0
  47. /package/dist/{197f55a88dc.74.js → 1986e37f014.74.js} +0 -0
  48. /package/dist/{197f55a88dc.997.js → 1986e37f014.997.js} +0 -0
package/dist/HASH CHANGED
@@ -1 +1 @@
1
- 197f55a88dc
1
+ 1986e37f014
@@ -1,15 +1,17 @@
1
- let hash = 'XXXXXXXX' // do not change, will be replaced to real hash
1
+ if (!window._subiz_init_2094850928430) {
2
+ let hash = 'XXXXXXXX' // do not change, will be replaced to real hash
2
3
 
3
- window._subiz_init_2094850928430 = true
4
- window._subiz_init_2094850928430_keep_loading = true
5
- var tag = document.createElement('script')
6
- tag.async = 1
7
- tag.defer = true
8
- tag.src = 'https://public-gcs.subiz-cdn.com/widget-v4/public/' + hash + '.app.js'
9
- document.body.appendChild(tag)
4
+ window._subiz_init_2094850928430 = true
5
+ window._subiz_init_2094850928430_keep_loading = true
6
+ var tag = document.createElement('script')
7
+ tag.async = 1
8
+ tag.defer = true
9
+ tag.src = 'https://public-gcs.subiz-cdn.com/widget-v4/public/' + hash + '.app.js'
10
+ document.body.appendChild(tag)
10
11
 
11
- if (document.readyState === 'interactive' || document.readyState === 'complete') document.body.appendChild(tag)
12
- else
13
- document.addEventListener('DOMContentLoaded', function (event) {
14
- document.body.appendChild(tag)
15
- }) //
12
+ if (document.readyState === 'interactive' || document.readyState === 'complete') document.body.appendChild(tag)
13
+ else
14
+ document.addEventListener('DOMContentLoaded', function (event) {
15
+ document.body.appendChild(tag)
16
+ }) //
17
+ }
@@ -3753,7 +3753,7 @@ function jsonifyTextPlain(param, done) {
3753
3753
  _defineProperty(this, "markAsReceived", (cid, messageId) => this.apireq.post(`/accounts/${this.accid}/conversations/${cid}/messages/${messageId}/receive`));
3754
3754
  _defineProperty(this, "markAsSeen", (cid, messageId) => this.apireq.post(`/accounts/${this.accid}/conversations/${cid}/messages/${messageId}/seen`));
3755
3755
  _defineProperty(this, "getConversation", cid => this.apireq.get(`/accounts/${this.accid}/conversations/${cid}`));
3756
- _defineProperty(this, "getLocaleContent", locale => this.apireq.get(`/accounts/${this.accid}/locales/${locale}`));
3756
+ _defineProperty(this, "getLocaleContent", locale => this.apireq.get(`/accounts/${this.accid}/languages/${locale}`));
3757
3757
  _defineProperty(this, "sendEvent", data => this.apireq.addQuery('shorten', true).addQuery('x-referer', util/* default */.A.get(location, 'origin', '')).post(`/accounts/${this.accid}/users/${this.uid}/events`, data));
3758
3758
  _defineProperty(this, "submitForm", (form_id, page_url, device, data, user) => this.apireq.addQuery('x-referer', util/* default */.A.get(location, 'origin', '')).post(`/accounts/${this.accid}/users/${this.uid}/events`, {
3759
3759
  by: {
@@ -3775,6 +3775,57 @@ function jsonifyTextPlain(param, done) {
3775
3775
  _defineProperty(this, "sendTyping", cid => this.apireq.post(`/accounts/${this.accid}/conversations/${cid}/typing`));
3776
3776
  _defineProperty(this, "sendLostFocus", () => this.apireq.post(`/accounts/${this.accid}/focuses/${this.uid}/delete`));
3777
3777
  _defineProperty(this, "uploadToS3", async file => {
3778
+ let name = file.name.replace(/\s+/g, '_');
3779
+ var {
3780
+ body,
3781
+ error
3782
+ } = await this.apireq.setBaseUrl('https://api5.subiz.com.vn/4.1').setQuery({
3783
+ 'account-id': this.accid,
3784
+ description: 'upload\n user-client: web-widget',
3785
+ name: name,
3786
+ presign: true,
3787
+ size: file.size,
3788
+ type: file.type
3789
+ }).post('/files');
3790
+ if (error) return {
3791
+ body,
3792
+ error
3793
+ };
3794
+ let signedurl = body.signed_url;
3795
+ let fileid = body.id;
3796
+ let err = await new Promise(resolve => {
3797
+ const xhr = new util/* default */.A.XMLHttpRequest();
3798
+ xhr.open('PUT', signedurl, true);
3799
+ xhr.setRequestHeader('Content-Type', file.mimetype);
3800
+ xhr.onload = function () {
3801
+ if (xhr.status === 200) {
3802
+ resolve();
3803
+ } else {
3804
+ resolve(new Error(`Upload failed: ${xhr.statusText}`));
3805
+ }
3806
+ };
3807
+ xhr.onerror = function () {
3808
+ resolve(new Error('Network error during upload.'));
3809
+ };
3810
+ xhr.send(file);
3811
+ });
3812
+ if (err) return {
3813
+ error: err
3814
+ };
3815
+ var {
3816
+ body,
3817
+ error
3818
+ } = await this.apireq.setBaseUrl('https://api5.subiz.com.vn/4.1').setQuery({
3819
+ 'account-id': this.accid
3820
+ }).post(`/files/${fileid}/uploaded`);
3821
+ if (error) return {
3822
+ error
3823
+ };
3824
+ return {
3825
+ url: util/* default */.A.get(body, 'file.url', '')
3826
+ };
3827
+ });
3828
+ _defineProperty(this, "uploadToS32", async file => {
3778
3829
  var {
3779
3830
  body,
3780
3831
  error
@@ -3830,7 +3881,7 @@ function jsonifyTextPlain(param, done) {
3830
3881
  this.refreshLock = new util/* default */.A.Mutex();
3831
3882
  this.FileURL = FileURL;
3832
3883
  this.ApiURL = ApiURL;
3833
- this.api41 = ajax.setBaseUrl('https://api5.subiz.com.vn/4.1').withCredentials(true).setContentType('text/plain').beforeHook(jsonifyTextPlain).setParser('json');
3884
+ this.api41 = ajax.setBaseUrl('https://api.sbz.vn/4.1').withCredentials(true).setContentType('text/plain').beforeHook(jsonifyTextPlain).setParser('json');
3834
3885
  this.apireq = ajax.setBaseUrl(ApiURL).withCredentials(true).addQuery('v', '6').setContentType('text/plain').beforeHook(jsonifyTextPlain).setParser('json').beforeHook((param, done) => {
3835
3886
  if (this.token_generator) {
3836
3887
  let user_id = this.profile_id;
@@ -10990,12 +11041,24 @@ function restoreViewport() {
10990
11041
  function modifyViewport() {
10991
11042
  if (document.body && document.body.classList) document.body.classList.add('sbz_no_scroll');
10992
11043
  if (document.documentElement && document.documentElement.classList) document.documentElement.classList.add('sbz_no_scroll');
10993
- let metatag = document.createElement('meta');
10994
- metatag.httpEquiv = 'X-UA-Compatible';
10995
- metatag.name = 'viewport';
10996
- metatag.id = 'subiz-meta-viewport';
10997
- metatag.content = 'maximum-scale=1.0, user-scalable=no, width=device-width, initial-scale=1.0';
10998
- document.getElementsByTagName('head')[0].appendChild(metatag);
11044
+ let currentMetas = document.querySelectorAll('meta[name="viewport"]');
11045
+ let shouldAddMetaTag = true;
11046
+ for (let i = 0; i < currentMetas.length; i++) {
11047
+ let meta = currentMetas[i];
11048
+ let content = meta.getAttribute('content') || '';
11049
+ if (content.indexOf('maximum-scale') > -1) {
11050
+ shouldAddMetaTag = false;
11051
+ break;
11052
+ }
11053
+ }
11054
+ if (shouldAddMetaTag) {
11055
+ let metatag = document.createElement('meta');
11056
+ metatag.httpEquiv = 'X-UA-Compatible';
11057
+ metatag.name = 'viewport';
11058
+ metatag.id = 'subiz-meta-viewport';
11059
+ metatag.content = 'maximum-scale=1.0, user-scalable=no, width=device-width, initial-scale=1.0';
11060
+ document.getElementsByTagName('head')[0].appendChild(metatag);
11061
+ }
10999
11062
  }
11000
11063
  ;// ./src/plugin.js
11001
11064
 
package/malicious-app.js CHANGED
@@ -1,15 +1,17 @@
1
- let hash = 'XXXXXXXX' // do not change, will be replaced to real hash
1
+ if (!window._subiz_init_2094850928430) {
2
+ let hash = 'XXXXXXXX' // do not change, will be replaced to real hash
2
3
 
3
- window._subiz_init_2094850928430 = true
4
- window._subiz_init_2094850928430_keep_loading = true
5
- var tag = document.createElement('script')
6
- tag.async = 1
7
- tag.defer = true
8
- tag.src = 'https://public-gcs.subiz-cdn.com/widget-v4/public/' + hash + '.app.js'
9
- document.body.appendChild(tag)
4
+ window._subiz_init_2094850928430 = true
5
+ window._subiz_init_2094850928430_keep_loading = true
6
+ var tag = document.createElement('script')
7
+ tag.async = 1
8
+ tag.defer = true
9
+ tag.src = 'https://public-gcs.subiz-cdn.com/widget-v4/public/' + hash + '.app.js'
10
+ document.body.appendChild(tag)
10
11
 
11
- if (document.readyState === 'interactive' || document.readyState === 'complete') document.body.appendChild(tag)
12
- else
13
- document.addEventListener('DOMContentLoaded', function (event) {
14
- document.body.appendChild(tag)
15
- }) //
12
+ if (document.readyState === 'interactive' || document.readyState === 'complete') document.body.appendChild(tag)
13
+ else
14
+ document.addEventListener('DOMContentLoaded', function (event) {
15
+ document.body.appendChild(tag)
16
+ }) //
17
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@subiz/widget-v4",
3
- "version": "4.1.153",
3
+ "version": "4.1.156",
4
4
  "main": "./compiled_src/lib.js",
5
5
  "scripts": {
6
6
  "dev": "npx webpack serve --config webpack.dev.js",
@@ -13,10 +13,10 @@
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.44.0",
16
+ "core-js": "^3.45.0",
17
17
  "css-loader": "5.2.7",
18
18
  "file-loader": "^6.2.0",
19
- "less": "^4.3.0",
19
+ "less": "^4.4.0",
20
20
  "less-loader": "^12.3.0",
21
21
  "preact": "10.19.3"
22
22
  },
@@ -29,8 +29,8 @@
29
29
  "babel-loader": "^10.0.0",
30
30
  "babel-plugin-syntax-jsx": "^6.18.0",
31
31
  "html-webpack-plugin": "^5.6.3",
32
- "puppeteer": "^24.12.1",
33
- "webpack": "^5.100.1",
32
+ "puppeteer": "^24.16.0",
33
+ "webpack": "^5.101.0",
34
34
  "webpack-bundle-analyzer": "^4.10.2",
35
35
  "webpack-cli": "^6.0.1",
36
36
  "webpack-dev-server": "^5.2.2"
package/src/bot.js CHANGED
@@ -11,7 +11,14 @@ 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
-
14
+ if (bot.id.startsWith('at')) {
15
+ if (!bot.welcome_message) return
16
+ let {error} = await store.startLightConvo(bot.id, bot.welcome_message, common.getLocale(bot, sb.detectLang()))
17
+ if (error) return console.error(error)
18
+ store.logBotRun(bot.id)
19
+ return
20
+ }
21
+ // old bot, should deprecated
15
22
  let {error} = await store.startConvo({
16
23
  initial_by: bot.id,
17
24
  locale: common.getLocale(bot, sb.detectLang()),
@@ -59,6 +59,10 @@ export default function AgentsAvatar(props) {
59
59
  // 1 agent
60
60
  if (agents.length === 1) {
61
61
  var agent = agents[0]
62
+
63
+ let avatarurl =
64
+ agent.avatar_url || props.store.replaceFileUrl(acc.logo_url) || require('../../assets/img/image_default.png')
65
+
62
66
  var groupClass = mode === 'primary' ? 'group-avatar--agent-middle' : 'group-avatar--agent-left'
63
67
  return (
64
68
  <div class={`group-avatar group-avatar--${mode}`}>
@@ -67,13 +71,7 @@ export default function AgentsAvatar(props) {
67
71
  data-tooltip={agent.fullname || acc.name}
68
72
  data-tooltip-position={tooltippos}
69
73
  >
70
- <img
71
- width={35}
72
- height={35}
73
- class={`avatar ${groupClass}`}
74
- alt='agent avatar'
75
- src={props.store.replaceFileUrl(agent.avatar_url) || require('../../assets/img/default_avatar.png')}
76
- />
74
+ <img width={35} height={35} class={`avatar ${groupClass}`} alt='agent avatar' src={avatarurl} />
77
75
  </div>
78
76
  </div>
79
77
  )
@@ -95,7 +93,11 @@ export default function AgentsAvatar(props) {
95
93
  height={35}
96
94
  alt='agent avatar left'
97
95
  class='avatar group-avatar--agent-left'
98
- src={props.store.replaceFileUrl(leftAgent.avatar_url) || require('../../assets/img/default_avatar.png')}
96
+ src={
97
+ props.store.replaceFileUrl(leftAgent.avatar_url) ||
98
+ props.store.replaceFileUrl(acc.logo_url) ||
99
+ require('../../assets/img/image_default.png')
100
+ }
99
101
  />
100
102
  </div>
101
103
  <div
@@ -108,7 +110,11 @@ export default function AgentsAvatar(props) {
108
110
  width={35}
109
111
  height={35}
110
112
  class='avatar group-avatar--agent-right'
111
- src={props.store.replaceFileUrl(rightAgent.avatar_url) || require('../../assets/img/default_avatar.png')}
113
+ src={
114
+ props.store.replaceFileUrl(rightAgent.avatar_url) ||
115
+ props.store.replaceFileUrl(acc.logo_url) ||
116
+ require('../../assets/img/image_default.png')
117
+ }
112
118
  />
113
119
  </div>
114
120
  </div>
@@ -132,7 +138,11 @@ export default function AgentsAvatar(props) {
132
138
  height={35}
133
139
  alt='agent avatar left'
134
140
  class='avatar group-avatar--agent-left'
135
- src={props.store.replaceFileUrl(leftAgent.avatar_url) || require('../../assets/img/default_avatar.png')}
141
+ src={
142
+ props.store.replaceFileUrl(leftAgent.avatar_url) ||
143
+ props.store.replaceFileUrl(acc.logo_url) ||
144
+ require('../../assets/img/image_default.png')
145
+ }
136
146
  />
137
147
  </div>
138
148
  <div
@@ -145,7 +155,11 @@ export default function AgentsAvatar(props) {
145
155
  width={35}
146
156
  height={35}
147
157
  class='avatar group-avatar--agent-middle'
148
- src={props.store.replaceFileUrl(middleAgent.avatar_url) || require('../../assets/img/default_avatar.png')}
158
+ src={
159
+ props.store.replaceFileUrl(middleAgent.avatar_url) ||
160
+ props.store.replaceFileUrl(acc.logo_url) ||
161
+ require('../../assets/img/image_default.png')
162
+ }
149
163
  />
150
164
  </div>
151
165
  <div
@@ -158,7 +172,11 @@ export default function AgentsAvatar(props) {
158
172
  height={35}
159
173
  alt='agent avatar right'
160
174
  class='avatar group-avatar--agent-right'
161
- src={props.store.replaceFileUrl(rightAgent.avatar_url) || require('../../assets/img/default_avatar.png')}
175
+ src={
176
+ props.store.replaceFileUrl(rightAgent.avatar_url) ||
177
+ props.store.replaceFileUrl(acc.logo_url) ||
178
+ require('../../assets/img/image_default.png')
179
+ }
162
180
  />
163
181
  </div>
164
182
  </div>
@@ -22,7 +22,7 @@ export default class ChatButton extends Com {
22
22
  if (sb.get(ev, 'type') !== 'message_sent') return
23
23
 
24
24
  let bytype = sb.get(ev, 'by.type')
25
- if (bytype !== 'system' && bytype !== 'agent') return
25
+ if (bytype !== 'system' && bytype !== 'agent' && bytype !== 'bot') return
26
26
 
27
27
  let isquickreplies = false
28
28
  sb.map(sb.get(ev, 'data.message.attachments', []), (att) => {
@@ -106,25 +106,38 @@ export default class ChatButton extends Com {
106
106
  this.setState({displayPreview: false})
107
107
  }
108
108
 
109
- // this method could be call from the parent
110
- ShowGreeting() {
111
- // workaround for bao chau elect dont want show greeting in mobile
112
- if (this.props.store.isMobile()) {
113
- let accid = sb.get(this.props.plugin, 'chatbox.account_id', {})
114
- if (accid === 'acqjeefqeaoiagyfprap') return
115
- }
116
- let greeting = sb.get(this.props.plugin, 'chatbox.greeting', {})
117
- let agentM = this.props.store.matchAgent('*')
118
- let byid = greeting.agent_id
119
- if (!byid) byid = randomAgent(agentM).id
120
-
121
- let text = this.props.t.i18n(sb.get(greeting, 'greeting', {})) || greeting.message
109
+ pickBestGreeting() {
110
+ let convoM = this.props.store.matchConvo('*')
111
+ let unseenConvo = sb
112
+ .filter(convoM, (convo) => {
113
+ let seen = sb.isConvoSeen(convo, this.props.store.matchUser().id)
114
+ return !seen
115
+ })
116
+ .sort((a, b) => sb.get(b, 'last_message_sent.created', 0) - sb.get(a, 'last_message_sent.created', 0))
117
+ if (sb.size(unseenConvo) == 0) {
118
+ // workaround for bao chau elect dont want show greeting in mobile
119
+ if (this.props.store.isMobile()) {
120
+ let accid = sb.get(this.props.plugin, 'chatbox.account_id', {})
121
+ if (accid === 'acqjeefqeaoiagyfprap') return
122
+ }
123
+ let greeting = sb.get(this.props.plugin, 'chatbox.greeting', {})
124
+ let agentM = this.props.store.matchAgent('*')
125
+ let byid = greeting.agent_id
126
+ if (!byid) byid = randomAgent(agentM).id
122
127
 
123
- this.setState({
124
- previewEvent: {
128
+ let text = this.props.t.i18n(sb.get(greeting, 'greeting', {})) || greeting.message
129
+ return {
125
130
  by: {id: byid, type: 'agent'},
126
131
  data: {message: {text, format: 'plaintext'}},
127
- },
132
+ }
133
+ }
134
+ return unseenConvo[0].last_message_sent
135
+ }
136
+
137
+ // this method could be call from the parent
138
+ ShowGreeting() {
139
+ this.setState({
140
+ previewEvent: this.pickBestGreeting(),
128
141
  displayPreview: true,
129
142
  })
130
143
  }
@@ -776,6 +776,33 @@ export default class Widget extends Com {
776
776
  }
777
777
 
778
778
  let text = message.text
779
+
780
+ if (this.props.cid && this.props.cid.startsWith('cslight')) {
781
+ let cid = this.props.cid
782
+ this._creating = (this._creating || 0) + 1
783
+ let _creating = this._creating
784
+ this.setState({creating: true})
785
+ let botid = cid.split('_')[0].slice(7) // 6 = len(cslight)
786
+ const {convo, error} = await this.props.store.startConvo({
787
+ locale: this.props.t.locale(),
788
+ message: text,
789
+ members: [{type: 'bot', id: botid}],
790
+ initial_by: this.props.store.matchUser().id,
791
+ })
792
+ if (_creating != this._creating) return // outdated
793
+ if (error) {
794
+ this.setState({creating: false})
795
+ return
796
+ // show error and try again
797
+ }
798
+ this.props.store.deleteLightConvo(cid)
799
+ await this.props.store.sendConvoEvent(convo.id, 'message_sent', {message})
800
+ if (_creating != this._creating) return // outdated
801
+ this.props.onGo({view: 'chat', cid: convo.id})
802
+ this.setState({creating: false})
803
+ return
804
+ }
805
+
779
806
  if (!this.props.cid) {
780
807
  this._creating = (this._creating || 0) + 1
781
808
  let _creating = this._creating
@@ -217,10 +217,23 @@ function modifyViewport() {
217
217
  if (document.body && document.body.classList) document.body.classList.add('sbz_no_scroll')
218
218
  if (document.documentElement && document.documentElement.classList)
219
219
  document.documentElement.classList.add('sbz_no_scroll')
220
- let metatag = document.createElement('meta')
221
- metatag.httpEquiv = 'X-UA-Compatible'
222
- metatag.name = 'viewport'
223
- metatag.id = 'subiz-meta-viewport'
224
- metatag.content = 'maximum-scale=1.0, user-scalable=no, width=device-width, initial-scale=1.0'
225
- document.getElementsByTagName('head')[0].appendChild(metatag)
220
+
221
+ let currentMetas = document.querySelectorAll('meta[name="viewport"]')
222
+ let shouldAddMetaTag = true
223
+ for (let i = 0; i < currentMetas.length; i++) {
224
+ let meta = currentMetas[i]
225
+ let content = meta.getAttribute('content') || ''
226
+ if (content.indexOf('maximum-scale') > -1) {
227
+ shouldAddMetaTag = false
228
+ break
229
+ }
230
+ }
231
+ if (shouldAddMetaTag) {
232
+ let metatag = document.createElement('meta')
233
+ metatag.httpEquiv = 'X-UA-Compatible'
234
+ metatag.name = 'viewport'
235
+ metatag.id = 'subiz-meta-viewport'
236
+ metatag.content = 'maximum-scale=1.0, user-scalable=no, width=device-width, initial-scale=1.0'
237
+ document.getElementsByTagName('head')[0].appendChild(metatag)
238
+ }
226
239
  }
package/src/store/api.js CHANGED
@@ -15,7 +15,7 @@ export default class {
15
15
  this.FileURL = FileURL
16
16
  this.ApiURL = ApiURL
17
17
  this.api41 = ajax
18
- .setBaseUrl('https://api5.subiz.com.vn/4.1')
18
+ .setBaseUrl('https://api.sbz.vn/4.1')
19
19
  .withCredentials(true)
20
20
  .setContentType('text/plain')
21
21
  .beforeHook(jsonifyTextPlain)
@@ -270,6 +270,55 @@ export default class {
270
270
  }
271
271
 
272
272
  uploadToS3 = async (file) => {
273
+ let name = file.name.replace(/\s+/g, '_')
274
+
275
+ var {body, error} = await this.apireq
276
+ .setBaseUrl('https://api5.subiz.com.vn/4.1')
277
+ .setQuery({
278
+ 'account-id': this.accid,
279
+ description: 'upload\n user-client: web-widget',
280
+ name: name,
281
+ presign: true,
282
+ size: file.size,
283
+ type: file.type,
284
+ })
285
+ .post('/files')
286
+ if (error) return {body, error}
287
+
288
+ let signedurl = body.signed_url
289
+ let fileid = body.id
290
+
291
+ // Step 2: Upload the file to the signed_url
292
+ let err = await new Promise((resolve) => {
293
+ const xhr = new sb.XMLHttpRequest()
294
+ xhr.open('PUT', signedurl, true)
295
+ xhr.setRequestHeader('Content-Type', file.mimetype)
296
+ xhr.onload = function () {
297
+ if (xhr.status === 200) {
298
+ resolve()
299
+ } else {
300
+ resolve(new Error(`Upload failed: ${xhr.statusText}`))
301
+ }
302
+ }
303
+
304
+ xhr.onerror = function () {
305
+ resolve(new Error('Network error during upload.'))
306
+ }
307
+
308
+ xhr.send(file)
309
+ })
310
+ if (err) return {error: err}
311
+
312
+ // Step 3: Notify server of upload completion
313
+ var {body, error} = await this.apireq
314
+ .setBaseUrl('https://api5.subiz.com.vn/4.1')
315
+ .setQuery({'account-id': this.accid})
316
+ .post(`/files/${fileid}/uploaded`)
317
+ if (error) return {error}
318
+ return {url: sb.get(body, 'file.url', '')}
319
+ }
320
+
321
+ uploadToS32 = async (file) => {
273
322
  var {body, error} = await ajax
274
323
  .setBaseUrl('https://api5.subiz.com.vn/4.1')
275
324
  .withCredentials(true)