@subiz/widget-v4 4.0.58 → 4.0.63
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/assets/img/caret.svg +1 -0
- package/assets/img/done_green.svg +4 -0
- package/assets/img/empty_1.svg +11 -0
- package/assets/img/ghn.svg +17 -0
- package/assets/img/ghtk.svg +18 -0
- package/assets/img/home.svg +1 -0
- package/assets/img/info.svg +1 -0
- package/assets/img/loader.svg +1 -0
- package/assets/img/map-pin.svg +1 -0
- package/assets/img/not_found_search.png +0 -0
- package/assets/img/package.svg +5 -0
- package/assets/img/package_fade.svg +1 -0
- package/assets/img/phone.svg +1 -0
- package/assets/img/search.svg +1 -0
- package/assets/img/shop.svg +1 -0
- package/assets/img/shop_faded.svg +1 -0
- package/assets/img/user.svg +1 -0
- package/assets/img/x.svg +5 -0
- package/assets/less/chatbox.less +35 -0
- package/assets/less/dropdown_select.less +130 -0
- package/assets/less/form.less +7 -20
- package/assets/less/order.less +489 -0
- package/assets/less/rating.less +3 -8
- package/compiled_src/call/call.js +12 -15
- package/compiled_src/chatbox/DropdownSelect.js +239 -0
- package/compiled_src/chatbox/Event.js +4 -2
- package/compiled_src/chatbox/Events.js +1 -0
- package/compiled_src/chatbox/MessageInput.js +4 -7
- package/compiled_src/chatbox/Order.js +281 -0
- package/compiled_src/chatbox/OrderAttachments.js +2 -1
- package/compiled_src/chatbox/Rating.js +7 -10
- package/compiled_src/chatbox/TextMessage.js +9 -2
- package/compiled_src/chatbox/Widget.js +40 -3
- package/compiled_src/chatbox/main.js +2 -1
- package/compiled_src/chatbox/spinner.js +1 -1
- package/compiled_src/chatbox/time.js +3 -1
- package/compiled_src/common.js +40 -1
- package/compiled_src/contact/contact.js +7 -12
- package/compiled_src/lib.js +9 -14
- package/compiled_src/notif/notif.js +12 -15
- package/compiled_src/order/address_picker.js +241 -0
- package/compiled_src/order/icon.js +62 -0
- package/compiled_src/order/index.js +113 -0
- package/compiled_src/order/order.js +1220 -0
- package/compiled_src/plugin.js +9 -42
- package/compiled_src/popup/countdown.js +4 -7
- package/compiled_src/popup/popup.js +40 -13
- package/compiled_src/store/api.js +80 -90
- package/compiled_src/store/api_fake.js +55 -82
- package/compiled_src/store/store.js +163 -158
- package/compiled_src/util/common.js +40 -4
- package/dist/0b82fa7e5c3b07b40a44.png +1 -0
- package/dist/0f4af006e38ee8b93633.png +1 -0
- package/dist/{74.js → 132.js} +2234 -236
- package/dist/178.js +341 -174
- package/dist/17e757ccadd.132.js +1 -0
- package/dist/17e757ccadd.178.js +1 -0
- package/dist/17e757ccadd.213.js +1 -0
- package/dist/17e757ccadd.335.js +1 -0
- package/dist/17e757ccadd.362.js +1 -0
- package/dist/17e757ccadd.441.js +1 -0
- package/dist/17e757ccadd.605.js +1 -0
- package/dist/17e757ccadd.678.js +1 -0
- package/dist/17e757ccadd.782.js +1 -0
- package/dist/17e757ccadd.app.js +1 -0
- package/dist/{17d938a5acb.index.html → 17e757ccadd.index.html} +3 -18
- package/dist/{17d938a5acb.library.html → 17e757ccadd.library.html} +3 -18
- package/dist/17e757ccadd.library.js +1 -0
- package/dist/{17d938a5acb.preview.html → 17e757ccadd.preview.html} +1 -1
- package/dist/17e757ccadd.preview.js +1 -0
- package/dist/17e757ccadd.screenshoot.js +1 -0
- package/dist/1ea1c6cd21d25176810c.png +1 -0
- package/dist/213.js +46 -87
- package/dist/292d42404e1b03398f61.png +1 -0
- package/dist/312d376370831b7bea83.png +1 -0
- package/dist/313d1bfc1cf776d1aefe.png +1 -0
- package/dist/335.js +408 -0
- package/dist/362.js +71 -21
- package/dist/441.js +69 -43
- package/dist/4aa58bb7a66bb44975aa.png +1 -0
- package/dist/56ce063bc6c81adb7322.png +1 -0
- package/dist/605.js +13 -79
- package/dist/678.js +70 -20
- package/dist/6a411166ef5cc79e0714.png +1 -0
- package/dist/6faf403782fefacc1649.png +1 -0
- package/dist/782.js +118 -21
- package/dist/79dca33c68fab79c067f.png +1 -0
- package/dist/82da1578fa84f9debaeb.png +1 -0
- package/dist/8b8e0f0824743974b282.png +1 -0
- package/dist/8d551390d81e39130a3c.png +1 -0
- package/dist/9fc61b9479877ebdb6c7.png +1 -0
- package/dist/HASH +1 -1
- package/dist/a165d31dcb3dc90f1057.png +1 -0
- package/dist/a98d4a5698812c4426b3.png +1 -0
- package/dist/assets/img/caret.998eb8f.svg +1 -0
- package/dist/assets/img/done_green.b817fd4.svg +4 -0
- package/dist/assets/img/empty_1.0b98af0.svg +11 -0
- package/dist/assets/img/ghn.070f8e3.svg +17 -0
- package/dist/assets/img/ghtk.326eac1.svg +18 -0
- package/dist/assets/img/info.ebce7ea.svg +1 -0
- package/dist/assets/img/loader.37000a7.svg +1 -0
- package/dist/assets/img/not_found_search.2ddb8d1.png +0 -0
- package/dist/assets/img/package.8d37d0f.svg +5 -0
- package/dist/assets/img/package_fade.763c001.svg +1 -0
- package/dist/assets/img/search.f9705ff.svg +1 -0
- package/dist/assets/img/shop.f7dc7d8.svg +1 -0
- package/dist/assets/img/shop_faded.df7845a.svg +1 -0
- package/dist/assets/img/x.26fdfa3.svg +5 -0
- package/dist/c41606bf9d1b604e46d5.png +1 -0
- package/dist/ce1f7450ce6c1aacd330.png +1 -0
- package/dist/cf8c01e88f4770a6e3e5.png +1 -0
- package/dist/dfbcfeab1d5622a737e2.png +1 -0
- package/dist/e4893ed8c2f7b8329919.png +1 -0
- package/dist/ec2ab4eb4ef73d186186.png +1 -0
- package/dist/screenshoot.html +1 -1
- package/dist/screenshoot.js +452 -389
- package/index.html +3 -18
- package/order.html +32 -0
- package/package.json +13 -14
- package/src/chatbox/DropdownSelect.js +229 -0
- package/src/chatbox/Event.js +2 -2
- package/src/chatbox/Events.js +43 -42
- package/src/chatbox/Order.js +232 -0
- package/src/chatbox/OrderAttachments.js +2 -1
- package/src/chatbox/TextMessage.js +21 -12
- package/src/chatbox/Widget.js +34 -4
- package/src/chatbox/main.js +2 -2
- package/src/chatbox/spinner.js +1 -1
- package/src/chatbox/time.js +1 -1
- package/src/common.js +52 -8
- package/src/contact/contact.js +1 -1
- package/src/order/address_picker.js +235 -0
- package/src/order/icon.js +32 -0
- package/src/order/index.js +86 -0
- package/src/order/order.js +1157 -0
- package/src/order/scratch +211 -0
- package/src/plugin.js +7 -52
- package/src/popup/popup.js +27 -2
- package/src/store/api.js +26 -1
- package/src/store/store.js +46 -9
- package/src/util/common.js +52 -4
- package/webpack.dev.js +2 -0
- package/dist/17d938a5acb.178.js +0 -1
- package/dist/17d938a5acb.213.js +0 -1
- package/dist/17d938a5acb.362.js +0 -1
- package/dist/17d938a5acb.441.js +0 -1
- package/dist/17d938a5acb.605.js +0 -1
- package/dist/17d938a5acb.619.js +0 -1
- package/dist/17d938a5acb.678.js +0 -1
- package/dist/17d938a5acb.74.js +0 -1
- package/dist/17d938a5acb.782.js +0 -1
- package/dist/17d938a5acb.app.js +0 -1
- package/dist/17d938a5acb.library.js +0 -1
- package/dist/17d938a5acb.preview.js +0 -1
- package/dist/17d938a5acb.screenshoot.js +0 -1
- package/dist/619.js +0 -777
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
renderShipping(order) {
|
|
2
|
+
let editmode = false
|
|
3
|
+
if (!order.status || order.status == 'new') {
|
|
4
|
+
editmode = !order.user_confirmation
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
let user = store.matchUser()
|
|
8
|
+
if (editmode) {
|
|
9
|
+
let addresses = store.matchShippingAddresses()
|
|
10
|
+
|
|
11
|
+
let $addrs = sb.map(addresses, (addr) => {
|
|
12
|
+
let fulladdr = [addr.street, addr.ward, addr.district, addr.region, addr.country].filter((a) => a).join(', ')
|
|
13
|
+
let cls = 'order__card'
|
|
14
|
+
if (this.state.shipping_address === addr.id) cls += ' order__card__active'
|
|
15
|
+
let $phone = null
|
|
16
|
+
if (addr.phone) {
|
|
17
|
+
$phone = (
|
|
18
|
+
<div style='margin-bottom:5px !important; '>
|
|
19
|
+
<img class='order_ship_icon' src={require('../../assets/img/phone.svg')} /> {addr.phone}
|
|
20
|
+
</div>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
return (
|
|
24
|
+
<div class={cls}>
|
|
25
|
+
<div style='width: 100% !important;'>
|
|
26
|
+
<div class='radio'>
|
|
27
|
+
<input
|
|
28
|
+
type='radio'
|
|
29
|
+
id={'shipping_addr.' + addr.id}
|
|
30
|
+
onInput={(e) => this.onChangeShippingAddress(addr.id)}
|
|
31
|
+
name='shipping_address'
|
|
32
|
+
checked={this.state.shipping_address === addr.id}
|
|
33
|
+
/>
|
|
34
|
+
<label class='radio--label ml-2' for={'shipping_addr.' + addr.id}>
|
|
35
|
+
Giao hàng tới <b>{addr.fullname}</b>
|
|
36
|
+
</label>
|
|
37
|
+
<div class='radio--check'>
|
|
38
|
+
<div class='inside'></div>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
<div class='muted mt-1' style='margin-left: 30px !important;'>
|
|
42
|
+
{$phone}
|
|
43
|
+
<div>
|
|
44
|
+
<img class='order_ship_icon' src={require('../../assets/img/home.svg')} /> {fulladdr}
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
let provinces = sb.map(this.state.provinces, (province) => ({id: province.id, name: province.province}))
|
|
53
|
+
let districts = sb.map(this.state.districts, (district) => ({id: district.id, name: district.district}))
|
|
54
|
+
let wards = sb.map(this.state.wards, (ward) => ({id: ward.id, name: ward.ward}))
|
|
55
|
+
let cls = 'order__card'
|
|
56
|
+
let $new = null
|
|
57
|
+
if (this.state.shipping_address === 'new') {
|
|
58
|
+
cls += ' order__card__active'
|
|
59
|
+
$new = (
|
|
60
|
+
<div style='margin-left: 0px !important;'>
|
|
61
|
+
<div class='d-flex'>
|
|
62
|
+
<div class='mr-2' style='flex: 1 !important;'>
|
|
63
|
+
<div class='order_form_label'>{this.props.t('fullname')}</div>
|
|
64
|
+
<input type='text' class='form-control' onInput={this.onChangeFullname} value={this.state.fullname} />
|
|
65
|
+
</div>
|
|
66
|
+
<div class='ml-2' style='flex: 1 !important;'>
|
|
67
|
+
<div class='order_form_label'>{this.props.t('phone')}</div>
|
|
68
|
+
<input type='text' class='form-control' onInput={this.onChangePhone} value={this.state.phone} />
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<div class='' style='width: 100% !important'>
|
|
73
|
+
<div class='order_form_label'>{this.props.t('address')}</div>
|
|
74
|
+
<input type='text' class='form-control' onInput={this.onChangeAddress} value={this.state.address} />
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<div>
|
|
78
|
+
<div class='order_form_label'>{this.props.t('province')}</div>
|
|
79
|
+
<DropdownSelect
|
|
80
|
+
width='180'
|
|
81
|
+
has_search
|
|
82
|
+
loading={this.state.loadProvince}
|
|
83
|
+
full
|
|
84
|
+
items={provinces}
|
|
85
|
+
selected={this.state.selectedProvince}
|
|
86
|
+
onSelect={this.onSelectProvince}
|
|
87
|
+
/>
|
|
88
|
+
</div>
|
|
89
|
+
<div>
|
|
90
|
+
<div class='order_form_label'>{this.props.t('district')}</div>
|
|
91
|
+
<DropdownSelect
|
|
92
|
+
width='180'
|
|
93
|
+
full
|
|
94
|
+
selected={this.state.selectedDistrict}
|
|
95
|
+
has_search
|
|
96
|
+
onSelect={this.onSelectDistrict}
|
|
97
|
+
loading={this.state.loadDistrict}
|
|
98
|
+
items={districts}
|
|
99
|
+
/>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<div class='order_form_label'>{this.props.t('ward')}</div>
|
|
103
|
+
<DropdownSelect
|
|
104
|
+
width='180'
|
|
105
|
+
selected={this.state.selectedWard}
|
|
106
|
+
full
|
|
107
|
+
has_search
|
|
108
|
+
onSelect={this.onSelectWard}
|
|
109
|
+
loading={this.state.loadWard}
|
|
110
|
+
items={wards}
|
|
111
|
+
/>
|
|
112
|
+
</div>
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
$addrs.push(
|
|
117
|
+
<div class={cls}>
|
|
118
|
+
<div style='width: 100% !important;'>
|
|
119
|
+
<div class='radio'>
|
|
120
|
+
<input
|
|
121
|
+
type='radio'
|
|
122
|
+
name='shipping_address'
|
|
123
|
+
id={'shipping_addr.new'}
|
|
124
|
+
onInput={(e) => this.onChangeShippingAddress('new')}
|
|
125
|
+
checked={this.state.shipping_address === 'new'}
|
|
126
|
+
/>
|
|
127
|
+
<label class='radio--label ml-2' for={'shipping_addr.new'}>
|
|
128
|
+
<b>Giao hàng tới địa chỉ khác</b>
|
|
129
|
+
</label>
|
|
130
|
+
<div class='radio--check'>
|
|
131
|
+
<div class='inside'></div>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
{$new}
|
|
135
|
+
</div>
|
|
136
|
+
</div>,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
let shopcls = 'order__card'
|
|
140
|
+
let $shop = null
|
|
141
|
+
if (this.state.shipping_address === 'shop') {
|
|
142
|
+
shopcls += ' order__card__active'
|
|
143
|
+
$shop = (
|
|
144
|
+
<div>
|
|
145
|
+
<div class='d-flex'>
|
|
146
|
+
<div class='mr-2' style='flex: 3 !important;'>
|
|
147
|
+
<div class='order_form_label'>{this.props.t('fullname')}</div>
|
|
148
|
+
<input type='text' class='form-control' onInput={this.onChangeFullname} value={this.state.fullname} />
|
|
149
|
+
</div>
|
|
150
|
+
<div class='ml-2' style='flex: 2 !important;'>
|
|
151
|
+
<div class='order_form_label'>{this.props.t('phones')}</div>
|
|
152
|
+
<input type='text' class='form-control' onInput={this.onChangePhone} value={this.state.phone} />
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
<div>
|
|
156
|
+
<div class='order_form_label'>{this.props.t('email')}</div>
|
|
157
|
+
<input type='text' class='form-control' onInput={this.onChangeEmail} value={this.state.email} />
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
$addrs.unshift(
|
|
164
|
+
<div class={shopcls}>
|
|
165
|
+
<div style='width: 100% !important;'>
|
|
166
|
+
<div class='radio'>
|
|
167
|
+
<input
|
|
168
|
+
type='radio'
|
|
169
|
+
name='shipping_address'
|
|
170
|
+
id={'shipping_addr.shop'}
|
|
171
|
+
onInput={(e) => this.onChangeShippingAddress('shop')}
|
|
172
|
+
checked={this.state.shipping_address === 'shop'}
|
|
173
|
+
/>
|
|
174
|
+
<label class='radio--label ml-2' for={'shipping_addr.shop'}>
|
|
175
|
+
<b>Nhận hàng tại shop</b>
|
|
176
|
+
</label>
|
|
177
|
+
<div class='radio--check'>
|
|
178
|
+
<div class='inside'></div>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
{$shop}
|
|
182
|
+
</div>
|
|
183
|
+
</div>,
|
|
184
|
+
)
|
|
185
|
+
// let $oldaddress = sb.map()
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<div class='order_section'>
|
|
189
|
+
<div class='order_label'>{this.props.t('ship_to')}</div>
|
|
190
|
+
<div class='form'>{$addrs}</div>
|
|
191
|
+
</div>
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
let fulladdr = sb.get(order, 'shipping.address.full_address')
|
|
196
|
+
if (!fulladdr) return null
|
|
197
|
+
let $addr = fulladdr ? <div>{fulladdr}</div> : <i class='i muted'>Chưa có địa chỉ giao hàng</i>
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<div class='order_section'>
|
|
201
|
+
<div class='order_section_label'>{this.props.t('ship_to')}</div>
|
|
202
|
+
{$addr}
|
|
203
|
+
</div>
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
1. ko co dia chi co san => dien luon new
|
|
210
|
+
2. co dia chi => hien thi dia chi co san va option dia chi moi
|
|
211
|
+
3.
|
package/src/plugin.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import sb from './util/index.js'
|
|
2
|
+
import * as common from './common.js'
|
|
2
3
|
import {h, render, createRef} from 'preact'
|
|
3
4
|
|
|
4
5
|
const LoadChatbox = () => import(/*webpackChunkName: "chatbox" */ './chatbox/main.js')
|
|
@@ -6,10 +7,6 @@ const LoadContact = () => import(/*webpackChunkName: "contact" */ './contact/con
|
|
|
6
7
|
const LoadPopup = () => import(/*webpackChunkName: "popup" */ './popup/popup.js')
|
|
7
8
|
const LoadNotif = () => import(/*webpackChunkName: "notif" */ './notif/notif.js')
|
|
8
9
|
|
|
9
|
-
// cache lang messages
|
|
10
|
-
let langMessages = {}
|
|
11
|
-
let downloadLock = false
|
|
12
|
-
|
|
13
10
|
function Plugin(plugin, store, $container, lib) {
|
|
14
11
|
if (!$container) throw '$div must is a valid html node'
|
|
15
12
|
var $div = document.createElement('div')
|
|
@@ -17,7 +14,7 @@ function Plugin(plugin, store, $container, lib) {
|
|
|
17
14
|
$container.appendChild($div) // use body as container
|
|
18
15
|
|
|
19
16
|
// auto detect language first
|
|
20
|
-
let _locale = getLocale(plugin, sb.detectLang())
|
|
17
|
+
let _locale = common.getLocale(plugin, sb.detectLang())
|
|
21
18
|
|
|
22
19
|
var domGate = new sb.Gate()
|
|
23
20
|
var pageIndex = 0
|
|
@@ -136,11 +133,10 @@ function Plugin(plugin, store, $container, lib) {
|
|
|
136
133
|
}
|
|
137
134
|
|
|
138
135
|
// language
|
|
139
|
-
|
|
140
136
|
let t = (key) => {
|
|
141
137
|
if (_locale === 'debug') return `{{${key}}}`
|
|
142
138
|
|
|
143
|
-
let messages = sb.get(langMessages, _locale, [])
|
|
139
|
+
let messages = sb.get(common.langMessages, _locale, [])
|
|
144
140
|
let message = sb.find(messages, (message) => message.key === key)
|
|
145
141
|
return sb.get(message, 'message', key)
|
|
146
142
|
}
|
|
@@ -157,7 +153,7 @@ function Plugin(plugin, store, $container, lib) {
|
|
|
157
153
|
t.locale = () => _locale
|
|
158
154
|
|
|
159
155
|
this.forceDownloadLanguage = async () => {
|
|
160
|
-
await downloadLanguage(store, _locale, true)
|
|
156
|
+
await common.downloadLanguage(store, _locale, true)
|
|
161
157
|
this.update(plugin)
|
|
162
158
|
}
|
|
163
159
|
|
|
@@ -167,8 +163,8 @@ function Plugin(plugin, store, $container, lib) {
|
|
|
167
163
|
this.t = null
|
|
168
164
|
_render() // hide plugin first
|
|
169
165
|
|
|
170
|
-
_locale = getLocale(plugin, locale)
|
|
171
|
-
await downloadLanguage(store, _locale)
|
|
166
|
+
_locale = common.getLocale(plugin, locale)
|
|
167
|
+
await common.downloadLanguage(store, _locale)
|
|
172
168
|
this.t = t
|
|
173
169
|
_render()
|
|
174
170
|
return _locale
|
|
@@ -203,7 +199,7 @@ function Plugin(plugin, store, $container, lib) {
|
|
|
203
199
|
|
|
204
200
|
this.update(plugin)
|
|
205
201
|
// auto detect language firlst
|
|
206
|
-
downloadLanguage(store, _locale).then(() => {
|
|
202
|
+
common.downloadLanguage(store, _locale).then(() => {
|
|
207
203
|
this.t = t
|
|
208
204
|
this.update(plugin)
|
|
209
205
|
})
|
|
@@ -348,44 +344,3 @@ export default class PluginMgr {
|
|
|
348
344
|
this._destroy = true
|
|
349
345
|
}
|
|
350
346
|
}
|
|
351
|
-
|
|
352
|
-
function downloadLanguage(store, locale, force) {
|
|
353
|
-
if (downloadLock)
|
|
354
|
-
return new Promise((resolve) => setTimeout(() => downloadLanguage(store, locale, force).then(resolve), 100))
|
|
355
|
-
|
|
356
|
-
downloadLock = true
|
|
357
|
-
// let locale = getLocale()
|
|
358
|
-
let messages
|
|
359
|
-
if (locale === 'debug' || (langMessages[locale] && !force)) {
|
|
360
|
-
downloadLock = false
|
|
361
|
-
return Promise.resolve()
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
return store.getLocaleContent(locale).then((res) => {
|
|
365
|
-
downloadLock = false
|
|
366
|
-
messages = sb.get(res, 'body.messages', [])
|
|
367
|
-
langMessages[locale] = messages
|
|
368
|
-
})
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
const getLocale = (plugin, loc) => {
|
|
372
|
-
if (!loc) loc = ''
|
|
373
|
-
let found = sb.find(plugin.locales, (l) => l.toLowerCase().trim() === loc.toLowerCase().trim())
|
|
374
|
-
if (found) return found
|
|
375
|
-
|
|
376
|
-
found = sb.find(plugin.locales, (l) => {
|
|
377
|
-
l = l
|
|
378
|
-
.replace('-', '_')
|
|
379
|
-
.split('_')[0]
|
|
380
|
-
.trim()
|
|
381
|
-
.toLowerCase()
|
|
382
|
-
let compareloc = loc
|
|
383
|
-
.replace('-', '_')
|
|
384
|
-
.split('_')[0]
|
|
385
|
-
.trim()
|
|
386
|
-
.toLowerCase()
|
|
387
|
-
return l == compareloc
|
|
388
|
-
})
|
|
389
|
-
if (found) return found
|
|
390
|
-
return plugin.locale || 'en-US'
|
|
391
|
-
}
|
package/src/popup/popup.js
CHANGED
|
@@ -13,6 +13,7 @@ export default class Popup extends Com {
|
|
|
13
13
|
closeAnimation: true,
|
|
14
14
|
pressedSubmit: false,
|
|
15
15
|
imageReady: false,
|
|
16
|
+
fontReady: false,
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
constructor(props) {
|
|
@@ -39,14 +40,37 @@ export default class Popup extends Com {
|
|
|
39
40
|
}
|
|
40
41
|
})
|
|
41
42
|
})
|
|
43
|
+
delete fonts.undefined
|
|
44
|
+
delete fonts.null
|
|
45
|
+
delete fonts['']
|
|
42
46
|
|
|
43
47
|
if (sb.size(images) == 0) this.setState({imageReady: true})
|
|
44
48
|
// preload images and fonts
|
|
45
49
|
sb.map(images, (_, image) => sb.preloadImg(image, () => this.setState({imageReady: true})))
|
|
46
50
|
sb.preloadWebfonts(Object.keys(fonts))
|
|
51
|
+
setTimeout(async () => {
|
|
52
|
+
await this.waitForFont(Object.keys(fonts))
|
|
53
|
+
this.setState({fontReady: true})
|
|
54
|
+
})
|
|
47
55
|
})
|
|
48
56
|
}
|
|
49
57
|
|
|
58
|
+
async waitForFont(fonts) {
|
|
59
|
+
if (sb.size(fonts) == 0) return
|
|
60
|
+
// 2 sec timeout
|
|
61
|
+
let ready = {}
|
|
62
|
+
for (var t = 0; t < 10; t++) {
|
|
63
|
+
for (var i = 0; i < fonts.length; i++) {
|
|
64
|
+
try {
|
|
65
|
+
if (document.fonts.check('normal 16px ' + fonts[i])) ready[fonts[i]] = true
|
|
66
|
+
if (Object.keys(readycount) == fonts.length) return
|
|
67
|
+
} catch (e) {}
|
|
68
|
+
}
|
|
69
|
+
await sb.sleep(200)
|
|
70
|
+
}
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
|
|
50
74
|
openPopup() {
|
|
51
75
|
this.setState({close: false})
|
|
52
76
|
}
|
|
@@ -59,7 +83,7 @@ export default class Popup extends Com {
|
|
|
59
83
|
isFormFilled() {
|
|
60
84
|
let page = sb.get(this.props.plugin.popup, `pages.${this.getPageIndex()}`)
|
|
61
85
|
let form = sb.find(page.components, (com) => com.type === 'form')
|
|
62
|
-
if (!form || !form.form) return
|
|
86
|
+
if (!form || !form.form) return true
|
|
63
87
|
|
|
64
88
|
// fill form
|
|
65
89
|
let fields = sb.get(form, 'form.fields', [])
|
|
@@ -185,7 +209,7 @@ export default class Popup extends Com {
|
|
|
185
209
|
}
|
|
186
210
|
|
|
187
211
|
if (hasConversion) {
|
|
188
|
-
var formData = new FormData(this._formRef.current)
|
|
212
|
+
var formData = this._formRef.current ? new FormData(this._formRef.current) : new FormData()
|
|
189
213
|
var summitFields = []
|
|
190
214
|
|
|
191
215
|
let user = sb.cloneDeep(this.props.store.matchUser())
|
|
@@ -833,6 +857,7 @@ export default class Popup extends Com {
|
|
|
833
857
|
if (!this.props.t) return null
|
|
834
858
|
if (!this.state.cssready) return null
|
|
835
859
|
if (!this.state.imageReady) return null
|
|
860
|
+
if (!this.state.fontReady) return null
|
|
836
861
|
if (this.state.close) return null
|
|
837
862
|
|
|
838
863
|
let popup = sb.get(this.props.plugin, 'popup', {})
|
package/src/store/api.js
CHANGED
|
@@ -47,7 +47,10 @@ export default class {
|
|
|
47
47
|
.get('/conversations')
|
|
48
48
|
|
|
49
49
|
listMessages = (cid, limit, start_id) =>
|
|
50
|
-
this.apireq
|
|
50
|
+
this.apireq
|
|
51
|
+
.addQuery('limit', limit)
|
|
52
|
+
.addQuery('start_id', start_id)
|
|
53
|
+
.get(`/conversations/${cid}/messages`)
|
|
51
54
|
|
|
52
55
|
ajax = ajax
|
|
53
56
|
|
|
@@ -156,4 +159,26 @@ export default class {
|
|
|
156
159
|
this.apireq.post(`/accounts/${this.accid}/campaigns/${impression.campaign_id}/impressions`, impression)
|
|
157
160
|
sendConversion = (conversion) =>
|
|
158
161
|
this.apireq.post(`/accounts/${this.accid}/campaigns/${conversion.campaign_id}/conversions`, conversion)
|
|
162
|
+
|
|
163
|
+
lookupOrder = (key) =>
|
|
164
|
+
ajax
|
|
165
|
+
.setBaseUrl(this.ApiURL)
|
|
166
|
+
.setContentType('text/plain')
|
|
167
|
+
.beforeHook(jsonifyTextPlain)
|
|
168
|
+
.setParser('json')
|
|
169
|
+
.addQuery('x-signed-key', key)
|
|
170
|
+
.get(`/orders/123`)
|
|
171
|
+
|
|
172
|
+
getOrder = (id) => this.apireq.get(`/accounts/${this.accid}/orders/` + id)
|
|
173
|
+
updateOrder = (order) => this.apireq.post(`/accounts/${this.accid}/orders/` + order.id, order)
|
|
174
|
+
|
|
175
|
+
fetchShippingAddresses = () => this.apireq.get(`/accounts/${this.accid}/users/${this.uid}/shipping-addresses`)
|
|
176
|
+
createShippingAddress = (addr) =>
|
|
177
|
+
this.apireq.post(`/accounts/${this.accid}/users/${this.uid}/shipping-addresses`, addr)
|
|
178
|
+
|
|
179
|
+
list_provinces = () => this.apireq.get(`/accounts/${this.accid}/provinces`)
|
|
180
|
+
list_districts = (p) => this.apireq.setQuery(p).get(`/accounts/${this.accid}/districts`)
|
|
181
|
+
list_wards = (p) => this.apireq.setQuery(p).get(`/accounts/${this.accid}/wards`)
|
|
182
|
+
|
|
183
|
+
suggest_address = (keyword) => this.apireq.setQuery({keyword: keyword}).get(`/accounts/${this.accid}/addresses`)
|
|
159
184
|
}
|
package/src/store/store.js
CHANGED
|
@@ -80,6 +80,23 @@ export default class Store {
|
|
|
80
80
|
return sb.Date.now() - (this.g_sync[key] || 0) < 300000
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
async fetchShippingAddresses() {
|
|
84
|
+
let out = await this.api.fetchShippingAddresses()
|
|
85
|
+
if (out.error) return null
|
|
86
|
+
this.cache.put('shipping_address', out.body.shipping_addresses)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
matchShippingAddresses() {
|
|
90
|
+
return this.cache.match('shipping_address')
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
updateOrder(order) {
|
|
94
|
+
return this.api.updateOrder(order)
|
|
95
|
+
}
|
|
96
|
+
createShippingAddress(addr) {
|
|
97
|
+
return this.api.createShippingAddress(addr)
|
|
98
|
+
}
|
|
99
|
+
|
|
83
100
|
async overrideAcc(acc) {
|
|
84
101
|
this.forceAcc = sb.cloneDeep(acc)
|
|
85
102
|
await this.readyGate.entry()
|
|
@@ -149,7 +166,7 @@ export default class Store {
|
|
|
149
166
|
overridePlugin(plugins) {
|
|
150
167
|
if (!Array.isArray(plugins)) throw 'plugins must be be an array'
|
|
151
168
|
let pluginM = {}
|
|
152
|
-
sb.map(plugins, function
|
|
169
|
+
sb.map(plugins, function(plugin) {
|
|
153
170
|
pluginM[plugin.id] = plugin
|
|
154
171
|
})
|
|
155
172
|
this.forcePlugins = pluginM
|
|
@@ -176,8 +193,11 @@ export default class Store {
|
|
|
176
193
|
return this.kv.match('user')
|
|
177
194
|
}
|
|
178
195
|
|
|
196
|
+
suggest_addresses = (keyword) => this.api.suggest_address(keyword)
|
|
197
|
+
|
|
179
198
|
matchSession = () => this.kv.match('session') || {}
|
|
180
199
|
matchAccount = () => this.cache.match('account')
|
|
200
|
+
matchPaymentMethods = () => this.cache.match('payment_methods')
|
|
181
201
|
|
|
182
202
|
matchUnread = () => {
|
|
183
203
|
let user = this.matchUser()
|
|
@@ -231,6 +251,11 @@ export default class Store {
|
|
|
231
251
|
return this.reconnectGate.open()
|
|
232
252
|
}
|
|
233
253
|
|
|
254
|
+
list_provinces = () => this.api.list_provinces()
|
|
255
|
+
list_districts = (p) => this.api.list_districts(p)
|
|
256
|
+
list_wards = (p) => this.api.list_wards(p)
|
|
257
|
+
|
|
258
|
+
list_provices
|
|
234
259
|
listEvents = (id) => {
|
|
235
260
|
if (!id || id === '*' || typeof id !== 'string') return
|
|
236
261
|
if (!this.isInsync('events' + id)) {
|
|
@@ -439,6 +464,7 @@ export default class Store {
|
|
|
439
464
|
}
|
|
440
465
|
|
|
441
466
|
_setUser(user) {
|
|
467
|
+
user = sb.cloneDeep(user)
|
|
442
468
|
let olduser = this.kv.match('user') || {}
|
|
443
469
|
var accid = olduser.account_id || user.account_id
|
|
444
470
|
var id = olduser.id || user.id
|
|
@@ -536,6 +562,10 @@ export default class Store {
|
|
|
536
562
|
this.cache.put('agent', agentM)
|
|
537
563
|
}
|
|
538
564
|
|
|
565
|
+
// payment methods
|
|
566
|
+
let pms = sb.get(setting, 'payment_methods', [])
|
|
567
|
+
this.cache.put('payment_methods', pms)
|
|
568
|
+
|
|
539
569
|
this.pubsub.publish('account')
|
|
540
570
|
}
|
|
541
571
|
|
|
@@ -725,6 +755,14 @@ export default class Store {
|
|
|
725
755
|
return {convo}
|
|
726
756
|
}
|
|
727
757
|
|
|
758
|
+
fetchOrder(id) {
|
|
759
|
+
return this.api.getOrder(id)
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
lookupOrder(key) {
|
|
763
|
+
return this.api.lookupOrder(key)
|
|
764
|
+
}
|
|
765
|
+
|
|
728
766
|
createPostback(cid, postback) {
|
|
729
767
|
return this.api.createPostback(cid, postback)
|
|
730
768
|
}
|
|
@@ -1046,7 +1084,7 @@ function getGaClientId() {
|
|
|
1046
1084
|
if (!hasGA()) return clientId
|
|
1047
1085
|
|
|
1048
1086
|
var allTrackers = window.ga.getAll() || []
|
|
1049
|
-
allTrackers.forEach(function
|
|
1087
|
+
allTrackers.forEach(function(tracker) {
|
|
1050
1088
|
clientId = tracker.get('clientId')
|
|
1051
1089
|
})
|
|
1052
1090
|
|
|
@@ -1063,7 +1101,7 @@ function getGaTrackingIds() {
|
|
|
1063
1101
|
if (!hasGA()) return trackingIds
|
|
1064
1102
|
|
|
1065
1103
|
const allTrackers = window.ga.getAll() || []
|
|
1066
|
-
allTrackers.forEach(function
|
|
1104
|
+
allTrackers.forEach(function(tracker) {
|
|
1067
1105
|
var trackingId = tracker.get('trackingId')
|
|
1068
1106
|
if (trackingId) trackingIds.push(trackingId)
|
|
1069
1107
|
})
|
|
@@ -1081,7 +1119,7 @@ function sendToGA(category, action, label) {
|
|
|
1081
1119
|
if (!hasGA()) return
|
|
1082
1120
|
|
|
1083
1121
|
const allTrackers = window.ga.getAll() || []
|
|
1084
|
-
allTrackers.forEach(function
|
|
1122
|
+
allTrackers.forEach(function(tracker) {
|
|
1085
1123
|
const name = tracker.get('name')
|
|
1086
1124
|
window.ga(name + '.send', 'event', category, action, label)
|
|
1087
1125
|
})
|
|
@@ -1094,7 +1132,7 @@ function sendEventToThirdParty(category, action, label) {
|
|
|
1094
1132
|
}
|
|
1095
1133
|
|
|
1096
1134
|
// from http://detectmobilebrowsers.com/
|
|
1097
|
-
let mobileCheck = (function
|
|
1135
|
+
let mobileCheck = (function(a) {
|
|
1098
1136
|
return (
|
|
1099
1137
|
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
|
|
1100
1138
|
a,
|
|
@@ -1105,7 +1143,6 @@ let mobileCheck = (function (a) {
|
|
|
1105
1143
|
)
|
|
1106
1144
|
})(navigator.userAgent || navigator.vendor || window.opera)
|
|
1107
1145
|
|
|
1108
|
-
let tabletCheck =
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
)
|
|
1146
|
+
let tabletCheck = /(ipad|tablet|(android(?!.*mobile))|(windows(?!.*phone)(.*touch))|kindle|playbook|silk|(puffin(?!.*(IP|AP|WP))))/.test(
|
|
1147
|
+
navigator.userAgent,
|
|
1148
|
+
)
|
package/src/util/common.js
CHANGED
|
@@ -905,7 +905,7 @@ export function getDayName(dayOfWeek) {
|
|
|
905
905
|
}
|
|
906
906
|
|
|
907
907
|
let loadedFonts = {}
|
|
908
|
-
export function preloadWebfonts(fonts) {
|
|
908
|
+
export function preloadWebfonts(fonts, done) {
|
|
909
909
|
for (var i = 0; i < fonts.length; i++) {
|
|
910
910
|
let font = fonts[i]
|
|
911
911
|
if (!font) continue
|
|
@@ -920,8 +920,11 @@ export function preloadWebfonts(fonts) {
|
|
|
920
920
|
// Visible - so we can measure it - but not on the screen
|
|
921
921
|
node.style.position = 'absolute'
|
|
922
922
|
node.style.display = 'block'
|
|
923
|
-
node.style.
|
|
923
|
+
node.style.opacity = '0.1'
|
|
924
|
+
node.style.color = 'transparent'
|
|
925
|
+
node.style.fontSize = '20px'
|
|
924
926
|
node.style.height = '0px'
|
|
927
|
+
node.style.top = '0px'
|
|
925
928
|
node.style.width = '0px'
|
|
926
929
|
|
|
927
930
|
node.style.fontWeight = weight
|
|
@@ -1072,9 +1075,9 @@ export function getUrlParameter() {
|
|
|
1072
1075
|
export var sleep = (ms) => new Promise((res) => setTimeout(res, ms))
|
|
1073
1076
|
|
|
1074
1077
|
export function formatCurrency(val) {
|
|
1075
|
-
if (!val) return 0
|
|
1078
|
+
if (!val) return '0 đ'
|
|
1076
1079
|
val = Math.round(val)
|
|
1077
|
-
return val.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')
|
|
1080
|
+
return val.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,')+ ' đ'
|
|
1078
1081
|
}
|
|
1079
1082
|
|
|
1080
1083
|
function replaceFileUrl(src) {
|
|
@@ -1104,3 +1107,48 @@ function replaceFileUrl(src) {
|
|
|
1104
1107
|
src = src.replace('http://file.mysubiz.com/', fileurl)
|
|
1105
1108
|
return src
|
|
1106
1109
|
}
|
|
1110
|
+
|
|
1111
|
+
export function unicodeToAscii(str) {
|
|
1112
|
+
str = str + ''
|
|
1113
|
+
// worka round Đ not work
|
|
1114
|
+
str = str.replace('đ', 'd').replace('Đ', 'D')
|
|
1115
|
+
return str.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
export function scrollIntoViewIfNeeded($ele) {
|
|
1119
|
+
centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded
|
|
1120
|
+
|
|
1121
|
+
var parent = $ele.parentNode
|
|
1122
|
+
var parentComputedStyle = window.getComputedStyle(parent, null)
|
|
1123
|
+
var parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width'))
|
|
1124
|
+
var parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width'))
|
|
1125
|
+
var overTop = $ele.offsetTop - parent.offsetTop < parent.scrollTop
|
|
1126
|
+
var overBottom =
|
|
1127
|
+
$ele.offsetTop - parent.offsetTop + $ele.clientHeight - parentBorderTopWidth >
|
|
1128
|
+
parent.scrollTop + parent.clientHeight
|
|
1129
|
+
var overLeft = $ele.offsetLeft - parent.offsetLeft < parent.scrollLeft
|
|
1130
|
+
var overRight =
|
|
1131
|
+
$ele.offsetLeft - parent.offsetLeft + $ele.clientWidth - parentBorderLeftWidth >
|
|
1132
|
+
parent.scrollLeft + parent.clientWidth
|
|
1133
|
+
var alignWithTop = overTop && !overBottom
|
|
1134
|
+
|
|
1135
|
+
if ((overTop || overBottom) && centerIfNeeded) {
|
|
1136
|
+
parent.scrollTop =
|
|
1137
|
+
$ele.offsetTop - parent.offsetTop - parent.clientHeight / 2 - parentBorderTopWidth + $ele.clientHeight / 2
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
if ((overLeft || overRight) && centerIfNeeded) {
|
|
1141
|
+
parent.scrollLeft =
|
|
1142
|
+
$ele.offsetLeft - parent.offsetLeft - parent.clientWidth / 2 - parentBorderLeftWidth + $ele.clientWidth / 2
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) {
|
|
1146
|
+
$ele.scrollIntoView(alignWithTop)
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
// if (!Element.prototype.scrollIntoViewIfNeeded) {
|
|
1151
|
+
//Element.prototype.scrollIntoViewIfNeeded = function(centerIfNeeded) {
|
|
1152
|
+
|
|
1153
|
+
//}
|
|
1154
|
+
//}
|
package/webpack.dev.js
CHANGED
|
@@ -7,6 +7,7 @@ module.exports = {
|
|
|
7
7
|
inject: './inject.js',
|
|
8
8
|
preview: './preview.js',
|
|
9
9
|
library: './library.js',
|
|
10
|
+
order: './src/order/index.js',
|
|
10
11
|
screenshoot: './screenshoot.js',
|
|
11
12
|
},
|
|
12
13
|
output: {publicPath: '/'},
|
|
@@ -14,6 +15,7 @@ module.exports = {
|
|
|
14
15
|
optimization: {minimize: false},
|
|
15
16
|
plugins: [
|
|
16
17
|
new HtmlWebpackPlugin({filename: './index.html', template: './index.html', inject: 'body', chunks: ['app']}),
|
|
18
|
+
new HtmlWebpackPlugin({filename: './order.html', template: './order.html', inject: 'body', chunks: ['order']}),
|
|
17
19
|
new HtmlWebpackPlugin({filename: './preview.html', template: './preview.html', chunks: ['preview']}),
|
|
18
20
|
new HtmlWebpackPlugin({filename: './inject.html', template: './inject.html', inject: 'body', chunks: ['inject']}),
|
|
19
21
|
new HtmlWebpackPlugin({filename: './library.html', template: './index.html', inject: 'body', chunks: ['library']}),
|