@subiz/widget-v4 4.1.71 → 4.1.73
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.
- package/app.js +0 -42
- package/assets/less/widget.less +6 -5
- package/assets/less/widget_header.less +5 -3
- package/compiled_src/chatbox/AudioAttachments.js +25 -32
- package/compiled_src/chatbox/Event.js +19 -3
- package/compiled_src/chatbox/InfoMessage.js +2 -1
- package/compiled_src/chatbox/OrderAttachments.js +102 -6
- package/compiled_src/chatbox/PoweredBy.js +20 -27
- package/compiled_src/chatbox/TextMessage.js +0 -14
- package/compiled_src/chatbox/VideoAttachments.js +1 -0
- package/compiled_src/chatbox/Widget.js +21 -21
- package/compiled_src/chatbox/time.js +46 -28
- package/compiled_src/lib.js +2 -2
- package/compiled_src/order/icon.js +2 -2
- package/compiled_src/order/index.js +2 -2
- package/compiled_src/plugin.js +2 -4
- package/compiled_src/store/api.js +1 -16
- package/compiled_src/store/store.js +2 -5
- package/compiled_src/util/common.js +12 -494
- package/compiled_src/util/index.js +0 -2
- package/dist/127.js +273 -0
- package/dist/132.js +2 -2
- package/dist/185.js +1885 -0
- package/dist/18eaf7ad0c6.127.js +1 -0
- package/dist/{18e74ca84ff.132.js → 18eaf7ad0c6.132.js} +1 -1
- package/dist/18eaf7ad0c6.185.js +1 -0
- package/dist/18eaf7ad0c6.278.js +1 -0
- package/dist/{18e74ca84ff.490.js → 18eaf7ad0c6.490.js} +1 -1
- package/dist/{18e74ca84ff.74.js → 18eaf7ad0c6.74.js} +1 -1
- package/dist/18eaf7ad0c6.app.js +1 -0
- package/dist/{18e74ca84ff.index.html → 18eaf7ad0c6.index.html} +1 -1
- package/dist/{18e74ca84ff.library.html → 18eaf7ad0c6.library.html} +1 -1
- package/dist/18eaf7ad0c6.library.js +1 -0
- package/dist/{18e74ca84ff.preview.html → 18eaf7ad0c6.preview.html} +1 -1
- package/dist/18eaf7ad0c6.preview.js +1 -0
- package/dist/18eaf7ad0c6.screenshoot.js +1 -0
- package/dist/18eaf7ad0c6.webview.js +1 -0
- package/dist/18ed1c3d33e.127.js +1 -0
- package/dist/18ed1c3d33e.132.js +1 -0
- package/dist/18ed1c3d33e.185.js +1 -0
- package/dist/18ed1c3d33e.27.js +1 -0
- package/dist/18ed1c3d33e.278.js +1 -0
- package/dist/18ed1c3d33e.459.js +1 -0
- package/dist/18ed1c3d33e.490.js +1 -0
- package/dist/18ed1c3d33e.74.js +1 -0
- package/dist/18ed1c3d33e.997.js +1 -0
- package/dist/18ed1c3d33e.app.js +1 -0
- package/dist/18ed1c3d33e.index.html +33 -0
- package/dist/18ed1c3d33e.library.html +33 -0
- package/dist/18ed1c3d33e.library.js +1 -0
- package/dist/18ed1c3d33e.preview.html +759 -0
- package/dist/18ed1c3d33e.preview.js +1 -0
- package/dist/18ed1c3d33e.screenshoot.js +1 -0
- package/dist/18ed1c3d33e.webview.js +1 -0
- package/dist/278.js +1 -1
- package/dist/490.js +1 -1
- package/dist/74.js +1 -1
- package/dist/HASH +1 -1
- package/dist/screenshoot.html +1 -1
- package/dist/screenshoot.js +4740 -627
- package/inject.js +3 -3
- package/package.json +6 -6
- package/src/chatbox/AudioAttachments.js +19 -26
- package/src/chatbox/Event.js +22 -3
- package/src/chatbox/InfoMessage.js +11 -11
- package/src/chatbox/OrderAttachments.js +118 -5
- package/src/chatbox/PoweredBy.js +14 -22
- package/src/chatbox/TextMessage.js +0 -14
- package/src/chatbox/VideoAttachments.js +1 -1
- package/src/chatbox/Widget.js +16 -20
- package/src/chatbox/time.js +54 -24
- package/src/lib.js +2 -2
- package/src/order/icon.js +2 -2
- package/src/order/index.js +2 -2
- package/src/plugin.js +4 -3
- package/src/store/api.js +1 -14
- package/src/store/store.js +3 -11
- package/src/util/common.js +13 -215
- package/src/util/index.js +0 -3
- package/compiled_src/util/order.js +0 -112
- package/dist/18e74ca84ff.278.js +0 -1
- package/dist/18e74ca84ff.497.js +0 -1
- package/dist/18e74ca84ff.app.js +0 -1
- package/dist/18e74ca84ff.library.js +0 -1
- package/dist/18e74ca84ff.preview.js +0 -1
- package/dist/18e74ca84ff.screenshoot.js +0 -1
- package/dist/18e74ca84ff.webview.js +0 -1
- package/dist/497.js +0 -6721
- package/src/util/order.js +0 -120
- /package/dist/{18e74ca84ff.27.js → 18eaf7ad0c6.27.js} +0 -0
- /package/dist/{18e74ca84ff.459.js → 18eaf7ad0c6.459.js} +0 -0
- /package/dist/{18e74ca84ff.997.js → 18eaf7ad0c6.997.js} +0 -0
package/inject.js
CHANGED
|
@@ -38,7 +38,7 @@ function runChatbox(subiz) {
|
|
|
38
38
|
show_close_button: true,
|
|
39
39
|
overlay: true,
|
|
40
40
|
text_color: 'rgba(0,0,0,1)',
|
|
41
|
-
font_family: '
|
|
41
|
+
font_family: 'Inter',
|
|
42
42
|
font_size: '14px',
|
|
43
43
|
background: 'white',
|
|
44
44
|
spacer: '10',
|
|
@@ -410,7 +410,7 @@ function runPopup(subiz) {
|
|
|
410
410
|
overlay: true,
|
|
411
411
|
primary_color: '#FDAD15',
|
|
412
412
|
text_color: '#333',
|
|
413
|
-
font_family: '
|
|
413
|
+
font_family: 'Inter',
|
|
414
414
|
font_size: '14px',
|
|
415
415
|
background: 'white',
|
|
416
416
|
spacer: '10',
|
|
@@ -636,7 +636,7 @@ function runPopup2(subiz) {
|
|
|
636
636
|
overlay: true,
|
|
637
637
|
primary_color: '#E36539',
|
|
638
638
|
text_color: '#333',
|
|
639
|
-
font_family: '
|
|
639
|
+
font_family: 'Inter',
|
|
640
640
|
font_size: '14px',
|
|
641
641
|
background: 'white',
|
|
642
642
|
spacer: '10',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subiz/widget-v4",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.73",
|
|
4
4
|
"main": "./compiled_src/lib.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "npx webpack serve --config webpack.dev.js",
|
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
"lib": "rm -rf compiled_src && npx babel --out-dir=compiled_src src"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@subiz/ajax": "^3.0.
|
|
12
|
+
"@subiz/ajax": "^3.0.14",
|
|
13
13
|
"@subiz/flow": "^1.1.0",
|
|
14
14
|
"@subiz/storage": "0.0.8",
|
|
15
|
-
"@subiz/wsclient": "^4.0.
|
|
15
|
+
"@subiz/wsclient": "^4.0.24",
|
|
16
16
|
"cookie_js": "1.4.2",
|
|
17
17
|
"core-js": "^3.36.1",
|
|
18
18
|
"css-loader": "5.2.7",
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@babel/cli": "^7.24.1",
|
|
26
|
-
"@babel/core": "^7.24.
|
|
26
|
+
"@babel/core": "^7.24.4",
|
|
27
27
|
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
|
28
28
|
"@babel/plugin-transform-react-jsx": "^7.23.4",
|
|
29
|
-
"@babel/preset-env": "^7.24.
|
|
29
|
+
"@babel/preset-env": "^7.24.4",
|
|
30
30
|
"babel-loader": "^9.1.3",
|
|
31
31
|
"babel-plugin-syntax-jsx": "^6.18.0",
|
|
32
32
|
"html-webpack-plugin": "^5.6.0",
|
|
33
|
-
"puppeteer": "^22.6.
|
|
33
|
+
"puppeteer": "^22.6.3",
|
|
34
34
|
"webpack": "^5.91.0",
|
|
35
35
|
"webpack-bundle-analyzer": "^4.10.1",
|
|
36
36
|
"webpack-cli": "^5.1.4",
|
|
@@ -1,31 +1,24 @@
|
|
|
1
1
|
import sb from '../util/index.js'
|
|
2
|
-
import {Com} from '../common.js'
|
|
3
2
|
import {h} from 'preact'
|
|
4
3
|
|
|
5
|
-
export default
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
export default function AudioAttachments(props) {
|
|
5
|
+
let byType = sb.get(props.ev, 'by.type')
|
|
6
|
+
var attachments = sb.get(props.ev, 'data.message.attachments', [])
|
|
7
|
+
var audios = []
|
|
8
|
+
sb.each(attachments, (att, i) => {
|
|
9
|
+
if (!att) return
|
|
10
|
+
if (sb.includes(att.mimetype, 'audio')) audios.push(att)
|
|
11
|
+
})
|
|
12
|
+
if (audios.length === 0) return null
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
var $audios = sb.map(audios, (audio, index) => {
|
|
21
|
-
return (
|
|
22
|
-
<div key={index} class={`audio-attachment audio-attachment--${byType}`}>
|
|
23
|
-
<audio class='audio-attachment__audio' controls>
|
|
24
|
-
<source src={this.props.store.replaceFileUrl(audio.url)} type={audio.mimetype} />
|
|
25
|
-
</audio>
|
|
26
|
-
</div>
|
|
27
|
-
)
|
|
28
|
-
})
|
|
29
|
-
return <div class={`message-${byType} message-${byType}-audio`}>{$audios}</div>
|
|
30
|
-
}
|
|
14
|
+
var $audios = sb.map(audios, (audio, index) => {
|
|
15
|
+
return (
|
|
16
|
+
<div key={index} class={`audio-attachment audio-attachment--${byType}`}>
|
|
17
|
+
<audio class='audio-attachment__audio' controls>
|
|
18
|
+
<source src={props.store.replaceFileUrl(audio.url)} type={audio.mimetype} />
|
|
19
|
+
</audio>
|
|
20
|
+
</div>
|
|
21
|
+
)
|
|
22
|
+
})
|
|
23
|
+
return <div class={`message-${byType} message-${byType}-audio`}>{$audios}</div>
|
|
31
24
|
}
|
package/src/chatbox/Event.js
CHANGED
|
@@ -7,7 +7,10 @@ import FormAttachments from './FormAttachments.js'
|
|
|
7
7
|
import FormSubmitAttachments from './FormSubmitAttachments.js'
|
|
8
8
|
import GenericTemplateAttachments from './GenericTemplateAttachments.js'
|
|
9
9
|
import ProductAttachments from './ProductAttachments.js'
|
|
10
|
-
|
|
10
|
+
let OrderAttachments = false
|
|
11
|
+
|
|
12
|
+
const LoadOrderAttachments = () => import(/*webpackChunkName: "OrderAttachment" */ './OrderAttachments.js')
|
|
13
|
+
|
|
11
14
|
//import FormSubmitAttachment from './formSubmitAttachment.js'
|
|
12
15
|
import VideoAttachments from './VideoAttachments.js'
|
|
13
16
|
import TextMessage from './TextMessage.js'
|
|
@@ -113,14 +116,30 @@ export default class Event extends Com {
|
|
|
113
116
|
)
|
|
114
117
|
}
|
|
115
118
|
|
|
119
|
+
tryLoadOrder(ev) {
|
|
120
|
+
let byType = sb.get(ev, 'by.type')
|
|
121
|
+
if (byType === 'user') return
|
|
122
|
+
// filter out all generic
|
|
123
|
+
|
|
124
|
+
let acc = this.props.store.matchAccount()
|
|
125
|
+
var attachments = sb.get(ev, 'data.message.attachments', [])
|
|
126
|
+
let orders = sb.filter(attachments, (att) => att.type === 'order' && att.order).map((att) => att.order)
|
|
127
|
+
|
|
128
|
+
if (orders.length === 0) return
|
|
129
|
+
if (!OrderAttachments)
|
|
130
|
+
sb.setTimeout(async () => {
|
|
131
|
+
OrderAttachments = (await LoadOrderAttachments()).default
|
|
132
|
+
})
|
|
133
|
+
}
|
|
134
|
+
|
|
116
135
|
renderMessageSent() {
|
|
117
136
|
let ev = this.props.event.ev
|
|
118
|
-
|
|
137
|
+
this.tryLoadOrder(ev)
|
|
119
138
|
var $time = null
|
|
120
139
|
if (this.props.event.show_time) {
|
|
121
140
|
$time = (
|
|
122
141
|
<div class='convo-event-time'>
|
|
123
|
-
<Time time={ev.created} />
|
|
142
|
+
<Time time={ev.created} t={this.props.t} />
|
|
124
143
|
</div>
|
|
125
144
|
)
|
|
126
145
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import sb from '../util/index.js'
|
|
2
2
|
|
|
3
|
-
function getRateLang
|
|
3
|
+
function getRateLang(rating) {
|
|
4
4
|
if (!rating) return 'poor'
|
|
5
5
|
if (rating < 2) return 'poor'
|
|
6
6
|
if (rating < 4) return 'average'
|
|
@@ -8,29 +8,29 @@ function getRateLang (rating) {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
import Time from './time.js'
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import {Com} from '../common.js'
|
|
12
|
+
import {h} from 'preact'
|
|
13
13
|
// [ 'ev'],
|
|
14
14
|
export default class InfoMessage extends Com {
|
|
15
|
-
render
|
|
15
|
+
render() {
|
|
16
16
|
let ev = this.props.ev.ev
|
|
17
17
|
var $time = null
|
|
18
18
|
if (this.props.ev.show_time) {
|
|
19
19
|
$time = (
|
|
20
|
-
<div class=
|
|
21
|
-
<Time time={ev.created} />
|
|
20
|
+
<div class='convo-event-time'>
|
|
21
|
+
<Time time={ev.created} t={this.props.t} />
|
|
22
22
|
</div>
|
|
23
23
|
)
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// if (this.ev.type === 'conversation_rating_requested') return <div class="info-message"></div>
|
|
27
27
|
if (ev.type === 'conversation_rated') {
|
|
28
|
-
var rating = sb.get(ev, 'data.conversation.ratings.0', {
|
|
28
|
+
var rating = sb.get(ev, 'data.conversation.ratings.0', {no_rating: true, rating: 0})
|
|
29
29
|
if (rating.no_rating) return null
|
|
30
30
|
return (
|
|
31
|
-
<div class=
|
|
31
|
+
<div class='convo-event'>
|
|
32
32
|
{$time}
|
|
33
|
-
<div class=
|
|
33
|
+
<div class='info-message'>
|
|
34
34
|
{this.props.t('rated_as') + ' ' + this.props.t(getRateLang(rating.rating)).toLowerCase()}
|
|
35
35
|
</div>
|
|
36
36
|
</div>
|
|
@@ -38,9 +38,9 @@ export default class InfoMessage extends Com {
|
|
|
38
38
|
}
|
|
39
39
|
if (ev.type === 'conversation_state_updated' && sb.get(ev, 'data.conversation.state') === 'ended') {
|
|
40
40
|
return (
|
|
41
|
-
<div class=
|
|
41
|
+
<div class='convo-event'>
|
|
42
42
|
{$time}
|
|
43
|
-
<div class=
|
|
43
|
+
<div class='info-message'>{this.props.t('conversation_ended')}</div>
|
|
44
44
|
</div>
|
|
45
45
|
)
|
|
46
46
|
}
|
|
@@ -15,7 +15,7 @@ export default class ProductAttachments extends Com {
|
|
|
15
15
|
if (orders.length === 0) return null
|
|
16
16
|
|
|
17
17
|
let $orders = sb.map(orders, (order, index) => {
|
|
18
|
-
|
|
18
|
+
calcOrderTotal(order)
|
|
19
19
|
let $note = null
|
|
20
20
|
if (order.note) {
|
|
21
21
|
$note = (
|
|
@@ -50,7 +50,7 @@ export default class ProductAttachments extends Com {
|
|
|
50
50
|
>
|
|
51
51
|
{this.props.t.i18n(product.i18n_name) || product.name}
|
|
52
52
|
</div>
|
|
53
|
-
<div class='order_attachment__product_desc'>{
|
|
53
|
+
<div class='order_attachment__product_desc'>{getProductPropName(product, ' / ')}</div>
|
|
54
54
|
<div class='order_attachment__product_desc'>
|
|
55
55
|
{this.props.t('qty')} {item.quantity} · {sb.formatCurrency(product.price)}
|
|
56
56
|
</div>
|
|
@@ -82,11 +82,11 @@ export default class ProductAttachments extends Com {
|
|
|
82
82
|
if (phone) phone = this.props.t('phn') + ': ' + phone
|
|
83
83
|
|
|
84
84
|
let $shipto = null
|
|
85
|
-
if (
|
|
85
|
+
if (displayOrderShippingAddress(order) || phone) {
|
|
86
86
|
$shipto = (
|
|
87
87
|
<div>
|
|
88
88
|
<div class='order_attachment__label'>{this.props.t('ship_to')}</div>
|
|
89
|
-
<div>{
|
|
89
|
+
<div>{displayOrderShippingAddress(order)}</div>
|
|
90
90
|
<div class='order_attachment__text_truncate'>{phone}</div>
|
|
91
91
|
</div>
|
|
92
92
|
)
|
|
@@ -185,7 +185,7 @@ export default class ProductAttachments extends Com {
|
|
|
185
185
|
<div class={`order_attachment order_attachment__${byType}`}>
|
|
186
186
|
<div class='order_attachment__header'>
|
|
187
187
|
{this.props.t('order')}
|
|
188
|
-
<span class='order_attachment__text_muted order_attachment__text_sm'>{
|
|
188
|
+
<span class='order_attachment__text_muted order_attachment__text_sm'>{getOrderDisplayName(order)}</span>
|
|
189
189
|
</div>
|
|
190
190
|
{$products}
|
|
191
191
|
{$shipto}
|
|
@@ -199,3 +199,116 @@ export default class ProductAttachments extends Com {
|
|
|
199
199
|
return $orders
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
|
+
|
|
203
|
+
function getProductPropName(product, seperator = ' - ') {
|
|
204
|
+
let options = op.get(product, 'options', [])
|
|
205
|
+
let props = op.get(product, 'props', [])
|
|
206
|
+
let multiPropsOptions = op.filter(options, (option) => op.size(option.values) > 1)
|
|
207
|
+
let names = []
|
|
208
|
+
op.each(multiPropsOptions, (option) => {
|
|
209
|
+
let prop = op.find(props, (prop) => prop.key === option.key) || {}
|
|
210
|
+
if (prop.value) names.push(prop.value)
|
|
211
|
+
})
|
|
212
|
+
return names.join(seperator)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function getOrderDisplayName(order = {}) {
|
|
216
|
+
return order.number || order.id || ''
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function displayOrderShippingAddress(order, isShorten) {
|
|
220
|
+
let addr = op.get(order, 'shipping.address', {})
|
|
221
|
+
let fulladdr = [addr.address, addr.ward, addr.district, addr.province]
|
|
222
|
+
.filter((a) => a)
|
|
223
|
+
.join(', ')
|
|
224
|
+
.trim()
|
|
225
|
+
if (isShorten) fulladdr = shortenAddr(fulladdr)
|
|
226
|
+
return fulladdr
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function shortenAddr(str) {
|
|
230
|
+
str = str || ''
|
|
231
|
+
str = str.replace(/Hà Nội/gi, 'HN')
|
|
232
|
+
str = str.replace(/Hồ Chí Minh/gi, 'HCM')
|
|
233
|
+
str = str.replace(/Thành Phố/gi, 'TP')
|
|
234
|
+
|
|
235
|
+
return str
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function calcOrderTotal(order) {
|
|
239
|
+
// compute subtotal first, since it doesn't depend on tax or gloal discount
|
|
240
|
+
let subtotal = 0
|
|
241
|
+
let beforeTaxDiscount = 0
|
|
242
|
+
let ordervalue = 0
|
|
243
|
+
op.map(order.items, (item) => {
|
|
244
|
+
if (!item.product) return 0
|
|
245
|
+
let price = op.get(item, 'product.price', 0) * (item.quantity || 0)
|
|
246
|
+
ordervalue += price
|
|
247
|
+
|
|
248
|
+
// some products that are discounted before tax
|
|
249
|
+
// the discount amount is calculated in product price for
|
|
250
|
+
// simpler calucation in future
|
|
251
|
+
if (item.discount_type == 'percentage') {
|
|
252
|
+
if (item.discount_percentage > 0) {
|
|
253
|
+
beforeTaxDiscount += (price * item.discount_percentage) / 10000
|
|
254
|
+
price = price * (1 - (item.discount_percentage || 0) / 10000)
|
|
255
|
+
}
|
|
256
|
+
} else if (item.discount_type == 'amount') {
|
|
257
|
+
if (item.discount_amount > 0) {
|
|
258
|
+
beforeTaxDiscount += item.discount_amount
|
|
259
|
+
price = price - (item.discount_amount || 0)
|
|
260
|
+
if (price <= 0) price = 0
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
item.total = price
|
|
264
|
+
subtotal += price
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
// TAX
|
|
268
|
+
let taxM = {}
|
|
269
|
+
op.map(order.items, (item, i) => {
|
|
270
|
+
if (!item.product) return
|
|
271
|
+
let tax = item.product.tax
|
|
272
|
+
if (!tax) return
|
|
273
|
+
if (!tax.id) return
|
|
274
|
+
let taxprice = (item.total * tax.percentage) / 10000
|
|
275
|
+
item.total_tax = taxprice
|
|
276
|
+
taxM[i] = {tax: tax, taxprice: taxprice}
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
let totaltax = 0
|
|
280
|
+
op.map(taxM, (t) => (totaltax += t.taxprice))
|
|
281
|
+
|
|
282
|
+
let computed_discount = 0
|
|
283
|
+
if (order.discount_type == 'percentage' && order.discount_percentage > 0) {
|
|
284
|
+
computed_discount = ((subtotal + totaltax) * order.discount_percentage) / 10000
|
|
285
|
+
} else if (order.discount_type == 'amount') {
|
|
286
|
+
computed_discount = order.discount_amount || 0
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// SHIP
|
|
290
|
+
let shippingfee = op.get(order, 'shipping.nominal_fee', 0)
|
|
291
|
+
if (shippingfee > 0) {
|
|
292
|
+
if (op.get(order, 'shipping.tax.id')) {
|
|
293
|
+
let tax = order.shipping.tax
|
|
294
|
+
let taxprice = shippingfee * (tax.percentage / 10000)
|
|
295
|
+
taxM['ship'] = {tax: tax, taxprice: taxprice}
|
|
296
|
+
order.shipping.total_tax = taxprice
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
totaltax = 0
|
|
301
|
+
op.map(taxM, (t) => (totaltax += t.taxprice))
|
|
302
|
+
let total = subtotal + totaltax - computed_discount + shippingfee
|
|
303
|
+
|
|
304
|
+
// add adjustment
|
|
305
|
+
total += order.adjustment || 0
|
|
306
|
+
if (total < 0) total = 0
|
|
307
|
+
order.subtotal = subtotal
|
|
308
|
+
order._computed_discount = computed_discount
|
|
309
|
+
order._taxM = taxM
|
|
310
|
+
order.total = total
|
|
311
|
+
order.total_tax = totaltax
|
|
312
|
+
order._discount_before_tax = beforeTaxDiscount
|
|
313
|
+
order._order_value = ordervalue
|
|
314
|
+
}
|
package/src/chatbox/PoweredBy.js
CHANGED
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
var logo = require('../../assets/img/subiz-mono.svg')
|
|
2
|
-
|
|
3
|
-
import {Com} from '../common.js'
|
|
4
2
|
import {h} from 'preact'
|
|
5
|
-
export default
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (this.props.store.isMobile()) return null
|
|
13
|
-
let user = this.props.store.matchUser() || {}
|
|
14
|
-
var link = `https://subiz.com.vn/?utm_source=${
|
|
15
|
-
window.location.host || `id-${user.account_id}`
|
|
16
|
-
}&utm_medium=widget&utm_campaign=widget_referral`
|
|
3
|
+
export default function PoweredBy(props) {
|
|
4
|
+
// dont render on mobile
|
|
5
|
+
if (props.store.isMobile()) return null
|
|
6
|
+
let user = props.store.matchUser() || {}
|
|
7
|
+
var link = `https://subiz.com.vn/?utm_source=${
|
|
8
|
+
window.location.host || `id-${user.account_id}`
|
|
9
|
+
}&utm_medium=widget&utm_campaign=widget_referral`
|
|
17
10
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
11
|
+
return (
|
|
12
|
+
<div class='poweredby'>
|
|
13
|
+
<a href={link} class='poweredby--text' target='_blank' title='Subiz'>
|
|
14
|
+
<img width='14' height='10' class='poweredby--subiz-logo' src={logo} alt='powerred by subiz' /> Subiz
|
|
15
|
+
</a>
|
|
16
|
+
</div>
|
|
17
|
+
)
|
|
26
18
|
}
|
|
@@ -42,7 +42,6 @@ export default class TextMessage extends Com {
|
|
|
42
42
|
})
|
|
43
43
|
|
|
44
44
|
if (sb.size(tags) === 0) return null
|
|
45
|
-
|
|
46
45
|
if (byType === 'agent') {
|
|
47
46
|
return <div class='message-agent message-text--agent'>{tags}</div>
|
|
48
47
|
}
|
|
@@ -63,19 +62,6 @@ export default class TextMessage extends Com {
|
|
|
63
62
|
if (insert.dynamicField) {
|
|
64
63
|
return sb.get(insert, 'dynamicField.text', '')
|
|
65
64
|
}
|
|
66
|
-
if (insert.mention) {
|
|
67
|
-
if (insert.mention.id == '*' || insert.mention.id == 'all') {
|
|
68
|
-
return <span class='mention'>@{this.$t('all')}</span>
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
let ag = store.matchAgent(insert.mention.id)
|
|
72
|
-
let name = sb.getAgentDisplayName(ag, insert.mention.fullname)
|
|
73
|
-
return (
|
|
74
|
-
<span class='mention' data-agent-id={ag.id} data-agent-fullname={name}>
|
|
75
|
-
@{name}
|
|
76
|
-
</span>
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
65
|
if (insert.emoji) return <Emoji emojiCode={`:${insert.emoji}:`} />
|
|
80
66
|
if (typeof insert === 'string') {
|
|
81
67
|
let $tags = sb.extractText(insert).map((tag, i) => {
|
|
@@ -20,7 +20,7 @@ export default class VideoAttachments extends Com {
|
|
|
20
20
|
|
|
21
21
|
var $videos = sb.map(videos, (video, index) => {
|
|
22
22
|
return (
|
|
23
|
-
<div class={`video-attachment video-attachment--${byType}`}>
|
|
23
|
+
<div key={index} class={`video-attachment video-attachment--${byType}`}>
|
|
24
24
|
<video
|
|
25
25
|
class='video-attachment__video'
|
|
26
26
|
src={this.props.store.replaceFileUrl(video.url)}
|
package/src/chatbox/Widget.js
CHANGED
|
@@ -10,7 +10,9 @@ import MessageInput from './MessageInput.js'
|
|
|
10
10
|
import Events from './Events.js'
|
|
11
11
|
import Typing from './Typing.js'
|
|
12
12
|
import Rating from './Rating.js'
|
|
13
|
-
import Order from './Order.js'
|
|
13
|
+
// import Order from './Order.js'
|
|
14
|
+
let Order = false
|
|
15
|
+
const LoadOrder = () => import(/*webpackChunkName: "Order" */ './Order.js')
|
|
14
16
|
import ListField from './ListField.js'
|
|
15
17
|
|
|
16
18
|
const defaultAvatar = 'https://file-subiz.com/fiqoahedjbgwclpouoml-avatar_default_baa8a1d7.png'
|
|
@@ -426,15 +428,17 @@ export default class Widget extends Com {
|
|
|
426
428
|
let $field = null
|
|
427
429
|
var errclass = field.error ? 'input--error' : ''
|
|
428
430
|
if (field.type === 'text') {
|
|
429
|
-
if (key
|
|
431
|
+
if (key == 'question' || sb.get(field, 'def.multiple_line')) {
|
|
430
432
|
$field = (
|
|
431
433
|
<textarea
|
|
432
434
|
class='form-control'
|
|
433
435
|
ref={(ref) => {
|
|
434
436
|
this['form_' + encode(key)] = ref
|
|
435
437
|
}}
|
|
438
|
+
id={'form_' + encode(key)}
|
|
436
439
|
value={field.value || ''}
|
|
437
440
|
onInput={(e) => this.onInputChange(key, e.target.value)}
|
|
441
|
+
onChange={(e) => this.onInputChange(key, e.target.value)}
|
|
438
442
|
row='4'
|
|
439
443
|
class='form-control'
|
|
440
444
|
></textarea>
|
|
@@ -445,23 +449,10 @@ export default class Widget extends Com {
|
|
|
445
449
|
$field = this.renderRadioField(field)
|
|
446
450
|
} else if (sb.get(field, 'def.select') === 'dropdown') {
|
|
447
451
|
$field = this.renderDropdownField(field)
|
|
448
|
-
} else if (sb.get(field, 'def.multiple_line')) {
|
|
449
|
-
$field = (
|
|
450
|
-
<textarea
|
|
451
|
-
class='form-control'
|
|
452
|
-
ref={(ref) => {
|
|
453
|
-
this['form_' + encode(key)] = ref
|
|
454
|
-
}}
|
|
455
|
-
value={field.value || ''}
|
|
456
|
-
onInput={(e) => this.onInputChange(key, e.target.value)}
|
|
457
|
-
onChange={(e) => this.onInputChange(key, e.target.value)}
|
|
458
|
-
row='4'
|
|
459
|
-
class='form-control'
|
|
460
|
-
></textarea>
|
|
461
|
-
)
|
|
462
452
|
} else {
|
|
463
453
|
$field = (
|
|
464
454
|
<input
|
|
455
|
+
id={'form_' + encode(key)}
|
|
465
456
|
value={field.value || ''}
|
|
466
457
|
onInput={(e) => this.onInputChange(key, e.target.value)}
|
|
467
458
|
onChange={(e) => this.onInputChange(key, e.target.value)}
|
|
@@ -476,6 +467,7 @@ export default class Widget extends Com {
|
|
|
476
467
|
} else if (field.type === 'number') {
|
|
477
468
|
$field = (
|
|
478
469
|
<input
|
|
470
|
+
id={'form_' + encode(key)}
|
|
479
471
|
value={field.value}
|
|
480
472
|
onInput={(e) => this.onInputChange(key, e.target.value)}
|
|
481
473
|
ref={(ref) => {
|
|
@@ -537,6 +529,7 @@ export default class Widget extends Com {
|
|
|
537
529
|
} else if (field.type === 'datetime') {
|
|
538
530
|
$field = (
|
|
539
531
|
<input
|
|
532
|
+
id={'form_' + encode(key)}
|
|
540
533
|
value={field.value}
|
|
541
534
|
onInput={(e) => this.onInputChange(key, e.target.value)}
|
|
542
535
|
class={`form-control ${errclass}`}
|
|
@@ -558,10 +551,10 @@ export default class Widget extends Com {
|
|
|
558
551
|
if (field.label) label = field.label
|
|
559
552
|
return (
|
|
560
553
|
<div key={'form_' + encode(key)}>
|
|
561
|
-
<
|
|
554
|
+
<label class='label' for={'form_' + encode(key)}>
|
|
562
555
|
{label}
|
|
563
556
|
{field.is_required ? <span class='ml-1 red'>*</span> : ''}
|
|
564
|
-
</
|
|
557
|
+
</label>
|
|
565
558
|
{field.error ? <div class='form-control--valid-input--error'>{field.error}</div> : ''}
|
|
566
559
|
{$field}
|
|
567
560
|
</div>
|
|
@@ -824,7 +817,10 @@ export default class Widget extends Com {
|
|
|
824
817
|
if (noschemeurl.startsWith('widget.subiz.com.vn/orders/')) {
|
|
825
818
|
let orderid = noschemeurl.substr('widget.subiz.com.vn/orders/'.length)
|
|
826
819
|
orderid = orderid.split('/')[0]
|
|
827
|
-
|
|
820
|
+
sb.setTimeout(async () => {
|
|
821
|
+
if (!Order) Order = (await LoadOrder()).default
|
|
822
|
+
this.setState({showOrder: true, order_id: orderid})
|
|
823
|
+
})
|
|
828
824
|
// display order instead
|
|
829
825
|
e.preventDefault()
|
|
830
826
|
return
|
|
@@ -935,7 +931,7 @@ export default class Widget extends Com {
|
|
|
935
931
|
<div class='d-flex flex-row'>
|
|
936
932
|
<div class='convo-list--convo-name'>{name}</div>
|
|
937
933
|
<div class='convo-list--convo-time'>
|
|
938
|
-
<Time ago time={time}
|
|
934
|
+
<Time ago time={time} t={this.props.t} short />
|
|
939
935
|
</div>
|
|
940
936
|
</div>
|
|
941
937
|
|
package/src/chatbox/time.js
CHANGED
|
@@ -18,21 +18,28 @@ export default class Time extends Com {
|
|
|
18
18
|
|
|
19
19
|
updateTime() {
|
|
20
20
|
var t = ''
|
|
21
|
+
let forceLocale = ''
|
|
22
|
+
if (this.props.t) {
|
|
23
|
+
if (this.props.t.locale && typeof this.props.t.locale === 'function') {
|
|
24
|
+
forceLocale = this.props.t.locale()
|
|
25
|
+
}
|
|
26
|
+
}
|
|
21
27
|
if (this.props.ago) {
|
|
22
28
|
if (this.props.short) {
|
|
23
29
|
// more than 10 days
|
|
24
|
-
if (Math.abs(this.props.time - new sb.Date().getTime()) > 86400000 * 10) {
|
|
25
|
-
let tim = new sb.Date(this.props.time)
|
|
26
|
-
let tzyear = tim.getFullYear()
|
|
27
|
-
let locale = sb.get(navigator, 'languages.0', 'en-US')
|
|
28
|
-
|
|
29
|
-
let
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
//if (Math.abs(this.props.time - new sb.Date().getTime()) > 86400000 * 10) {
|
|
31
|
+
//let tim = new sb.Date(this.props.time)
|
|
32
|
+
//let tzyear = tim.getFullYear()
|
|
33
|
+
//let locale = sb.get(navigator, 'languages.0', 'en-US')
|
|
34
|
+
//if (forceLocale) locale = forceLocale
|
|
35
|
+
//let tzmonthname = tim.toLocaleDateString(locale, {month: 'short'})
|
|
36
|
+
//let tzdate = tim.getDate()
|
|
37
|
+
//t = tzdate + ' ' + tzmonthname + ' ' + tzyear
|
|
38
|
+
//}
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
if (!t && this.props.time > 0) t = ago(this.props.time, new sb.Date().getTime())
|
|
35
|
-
} else t = sb.shortTime(this.props.time, this.props.tzoffset)
|
|
41
|
+
if (!t && this.props.time > 0) t = ago(this.props.time, new sb.Date().getTime(), this.props.t)
|
|
42
|
+
} else t = sb.shortTime(this.props.time, this.props.tzoffset, Date.now(), forceLocale)
|
|
36
43
|
|
|
37
44
|
if (this.props.uppercase) t = t.toUpperCase()
|
|
38
45
|
|
|
@@ -47,24 +54,47 @@ export default class Time extends Com {
|
|
|
47
54
|
}
|
|
48
55
|
|
|
49
56
|
render() {
|
|
50
|
-
|
|
57
|
+
let locale = sb.get(navigator, 'languages.0', 'en-US')
|
|
58
|
+
if (this.props.t) {
|
|
59
|
+
if (this.props.t.locale && typeof this.props.t.locale === 'function') {
|
|
60
|
+
locale = this.props.t.locale()
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
let title = new Date(this.props.time).toLocaleString(locale)
|
|
64
|
+
return <span style={this.props.style} title={title}>{this.state.t}</span>
|
|
51
65
|
}
|
|
52
66
|
}
|
|
53
67
|
|
|
54
|
-
function ago(timeA, timeB) {
|
|
55
|
-
|
|
56
|
-
s: '%d
|
|
57
|
-
m: '
|
|
58
|
-
mm: '%
|
|
59
|
-
h: '
|
|
60
|
-
hh: '%
|
|
61
|
-
d: '
|
|
62
|
-
dd: '%
|
|
63
|
-
M: '
|
|
64
|
-
MM: '%
|
|
65
|
-
y: '
|
|
66
|
-
yy: '%
|
|
68
|
+
function ago(timeA, timeB, t) {
|
|
69
|
+
let relObj = {
|
|
70
|
+
s: '%d sec',
|
|
71
|
+
m: '1 min',
|
|
72
|
+
mm: '%d mins',
|
|
73
|
+
h: '1 hour',
|
|
74
|
+
hh: '%d hours',
|
|
75
|
+
d: '1 day',
|
|
76
|
+
dd: '%d days',
|
|
77
|
+
M: '1 month',
|
|
78
|
+
MM: '%d months',
|
|
79
|
+
y: '1 year',
|
|
80
|
+
yy: '%d years',
|
|
67
81
|
}
|
|
82
|
+
if (t) {
|
|
83
|
+
relObj = {
|
|
84
|
+
s: `%d ${t('second_short')}`,
|
|
85
|
+
m: `1 ${t('minute_short')}`,
|
|
86
|
+
mm: `%d ${t('minutes_short')}`,
|
|
87
|
+
h: `1 ${t('hour_short')}`,
|
|
88
|
+
hh: `%d ${t('hours_short')}`,
|
|
89
|
+
d: `1 ${t('day_short')}`,
|
|
90
|
+
dd: `%d ${t('days_short')}`,
|
|
91
|
+
M: `1 ${t('month_short')}`,
|
|
92
|
+
MM: `%d ${t('months_short')}`,
|
|
93
|
+
y: `1 ${t('year_short')}`,
|
|
94
|
+
yy: `%d ${t('years_short')}`,
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
68
98
|
const loc = relObj
|
|
69
99
|
const T = [
|
|
70
100
|
{l: 's', r: 44, d: 1000},
|