@hellotext/hellotext 1.8.7 → 2.0.0
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/dist/hellotext.js +1 -1
- package/lib/api/businesses.cjs +37 -0
- package/lib/api/businesses.js +3 -9
- package/lib/api/events.cjs +45 -0
- package/lib/api/events.js +8 -14
- package/lib/api/forms.cjs +51 -0
- package/lib/api/forms.js +10 -17
- package/lib/api/index.cjs +51 -0
- package/lib/api/index.js +10 -23
- package/lib/api/response.cjs +76 -0
- package/lib/api/response.js +1 -7
- package/lib/api/submissions.cjs +47 -0
- package/lib/api/submissions.js +9 -17
- package/lib/api/webchat/messages.cjs +70 -0
- package/lib/api/webchat/messages.js +10 -18
- package/lib/api/webchats.cjs +44 -0
- package/lib/api/webchats.js +8 -16
- package/lib/builders/input_builder.cjs +61 -0
- package/lib/builders/input_builder.js +4 -11
- package/lib/builders/logo_builder.cjs +50 -0
- package/lib/builders/logo_builder.js +5 -12
- package/lib/channels/application_channel.cjs +67 -0
- package/lib/channels/application_channel.js +1 -8
- package/lib/channels/{web_chat_channel.js → webchat_channel.cjs} +35 -20
- package/lib/channels/webchat_channel.js +3 -11
- package/lib/controllers/form_controller.cjs +141 -0
- package/lib/controllers/form_controller.js +15 -22
- package/lib/controllers/mixins/usePopover.cjs +59 -0
- package/lib/controllers/mixins/usePopover.js +6 -14
- package/lib/controllers/{web_chat/pagination_controller.js → webchat/emoji_picker_controller.cjs} +74 -29
- package/lib/controllers/webchat/emoji_picker_controller.js +11 -17
- package/lib/controllers/webchat_controller.cjs +433 -0
- package/lib/controllers/webchat_controller.js +49 -51
- package/lib/core/configuration/forms.cjs +49 -0
- package/lib/core/configuration/forms.js +2 -8
- package/lib/core/configuration/{web_chat.js → webchat.cjs} +53 -38
- package/lib/core/configuration/webchat.js +2 -9
- package/lib/core/configuration.cjs +65 -0
- package/lib/core/configuration.js +8 -13
- package/lib/core/event.cjs +71 -0
- package/lib/core/event.js +5 -11
- package/lib/core/index.cjs +20 -0
- package/lib/core/index.js +2 -20
- package/lib/errors/index.cjs +19 -0
- package/lib/errors/index.js +2 -19
- package/lib/errors/invalid_event.cjs +34 -0
- package/lib/errors/invalid_event.js +1 -7
- package/lib/errors/not_initialized_error.cjs +34 -0
- package/lib/errors/not_initialized_error.js +1 -7
- package/lib/hellotext.cjs +152 -0
- package/lib/hellotext.js +18 -27
- package/lib/index.cjs +20 -0
- package/lib/index.js +12 -20
- package/lib/locales/en.cjs +22 -0
- package/lib/locales/en.js +2 -9
- package/lib/locales/es.cjs +22 -0
- package/lib/locales/es.js +2 -9
- package/lib/locales/index.cjs +14 -0
- package/lib/locales/index.js +6 -14
- package/lib/models/business.cjs +65 -0
- package/lib/models/business.js +5 -12
- package/lib/models/cookies.cjs +40 -0
- package/lib/models/cookies.js +3 -10
- package/lib/models/form.cjs +166 -0
- package/lib/models/form.js +10 -17
- package/lib/models/form_collection.cjs +119 -0
- package/lib/models/form_collection.js +15 -22
- package/lib/models/index.cjs +54 -0
- package/lib/models/index.js +7 -54
- package/lib/models/query.cjs +51 -0
- package/lib/models/query.js +3 -9
- package/lib/models/session.cjs +58 -0
- package/lib/models/session.js +12 -17
- package/lib/models/{web_chat.js → webchat.cjs} +14 -22
- package/lib/models/webchat.js +6 -13
- package/lib/vanilla.cjs +13 -0
- package/lib/vanilla.js +1 -13
- package/package.json +34 -7
- package/src/controllers/webchat_controller.js +72 -47
- package/src/hellotext.js +3 -4
- package/src/models/session.js +4 -3
- package/.babelrc +0 -24
- package/.github/workflows/ci.yml +0 -24
- package/.prettierignore +0 -3
- package/.prettierrc.json +0 -18
- package/MIT-LICENSE +0 -20
- package/__tests__/builders/input_builder_test.js +0 -117
- package/__tests__/core/configuration/forms_test.js +0 -30
- package/__tests__/core/configuration/webchat_test.js +0 -163
- package/__tests__/core/configuration_test.js +0 -28
- package/__tests__/core/event_test.js +0 -56
- package/__tests__/hellotext_test.js +0 -197
- package/__tests__/models/business_test.js +0 -26
- package/__tests__/models/cookies_test.js +0 -25
- package/__tests__/models/form_collection_test.js +0 -103
- package/__tests__/models/form_test.js +0 -131
- package/__tests__/models/query_test.js +0 -97
- package/docs/forms.md +0 -176
- package/docs/tracking.md +0 -203
- package/docs/webchat.md +0 -101
- package/jest.config.js +0 -4
- package/jest.setup.js +0 -16
- package/lib/api/web_chat/messages.js +0 -74
- package/lib/api/web_chats.js +0 -53
- package/styles/index.css +0 -38
- package/webpack.config.js +0 -24
package/lib/vanilla.js
CHANGED
|
@@ -1,13 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
Object.defineProperty(exports, "default", {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: function get() {
|
|
9
|
-
return _hellotext.default;
|
|
10
|
-
}
|
|
11
|
-
});
|
|
12
|
-
var _hellotext = _interopRequireDefault(require("./hellotext"));
|
|
13
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
1
|
+
export { default } from './hellotext';
|
package/package.json
CHANGED
|
@@ -1,15 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hellotext/hellotext",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Hellotext JavaScript Client",
|
|
5
5
|
"source": "src/index.js",
|
|
6
|
-
"main": "lib/index.
|
|
6
|
+
"main": "lib/index.cjs",
|
|
7
|
+
"module": "lib/index.js",
|
|
8
|
+
"browser": "dist/hellotext.js",
|
|
9
|
+
"unpkg": "dist/hellotext.js",
|
|
7
10
|
"author": "Hellotext",
|
|
8
11
|
"license": "MIT",
|
|
9
12
|
"homepage": "https://github.com/hellotext/hellotext.js",
|
|
13
|
+
"files": [
|
|
14
|
+
"lib",
|
|
15
|
+
"dist",
|
|
16
|
+
"src"
|
|
17
|
+
],
|
|
10
18
|
"exports": {
|
|
11
|
-
".":
|
|
12
|
-
|
|
19
|
+
".": {
|
|
20
|
+
"import": "./lib/index.js",
|
|
21
|
+
"require": "./lib/index.cjs",
|
|
22
|
+
"default": "./dist/hellotext.js"
|
|
23
|
+
},
|
|
24
|
+
"./vanilla": {
|
|
25
|
+
"import": "./lib/vanilla.js",
|
|
26
|
+
"require": "./lib/vanilla.cjs"
|
|
27
|
+
},
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
30
|
+
"sideEffects": [
|
|
31
|
+
"*.css",
|
|
32
|
+
"./lib/index.js",
|
|
33
|
+
"./lib/index.cjs"
|
|
34
|
+
],
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=14.0.0"
|
|
13
37
|
},
|
|
14
38
|
"devDependencies": {
|
|
15
39
|
"@babel/cli": "^7.20.7",
|
|
@@ -38,9 +62,12 @@
|
|
|
38
62
|
],
|
|
39
63
|
"scripts": {
|
|
40
64
|
"test": "NODE_ENV=test jest",
|
|
41
|
-
"build": "npm run build:
|
|
42
|
-
"build:
|
|
43
|
-
"build:
|
|
65
|
+
"build": "npm run clean && npm run build:esm && npm run build:cjs && npm run build:bundle",
|
|
66
|
+
"build:esm": "babel src -d lib",
|
|
67
|
+
"build:cjs": "BABEL_ENV=cjs babel src -d lib --out-file-extension .cjs",
|
|
68
|
+
"build:bundle": "webpack",
|
|
69
|
+
"clean": "rm -rf lib dist",
|
|
70
|
+
"prepublishOnly": "npm test && npm run build"
|
|
44
71
|
},
|
|
45
72
|
"bugs": {
|
|
46
73
|
"url": "https://github.com/hellotext/hellotext.js/issues"
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import { flip, offset, shift } from '@floating-ui/dom'
|
|
1
2
|
import { Controller } from '@hotwired/stimulus'
|
|
2
|
-
import { shift, flip, offset } from '@floating-ui/dom'
|
|
3
3
|
|
|
4
4
|
import WebchatMessagesAPI from '../api/webchat/messages'
|
|
5
5
|
import WebchatChannel from '../channels/webchat_channel'
|
|
6
|
-
import Hellotext from
|
|
6
|
+
import Hellotext from '../hellotext'
|
|
7
7
|
|
|
8
8
|
import { Webchat as WebchatConfiguration, behaviors } from '../core/configuration/webchat'
|
|
9
9
|
|
|
10
|
-
import { usePopover } from './mixins/usePopover'
|
|
11
10
|
import { LogoBuilder } from '../builders/logo_builder'
|
|
11
|
+
import { usePopover } from './mixins/usePopover'
|
|
12
12
|
|
|
13
13
|
export default class extends Controller {
|
|
14
14
|
static values = {
|
|
@@ -16,7 +16,7 @@ export default class extends Controller {
|
|
|
16
16
|
conversationId: String,
|
|
17
17
|
media: Object,
|
|
18
18
|
fileSizeErrorMessage: String,
|
|
19
|
-
placement: { type: String, default:
|
|
19
|
+
placement: { type: String, default: 'bottom-end' },
|
|
20
20
|
open: { type: Boolean, default: false },
|
|
21
21
|
autoPlacement: { type: Boolean, default: false },
|
|
22
22
|
disabled: { type: Boolean, default: false },
|
|
@@ -46,7 +46,13 @@ export default class extends Controller {
|
|
|
46
46
|
|
|
47
47
|
initialize() {
|
|
48
48
|
this.messagesAPI = new WebchatMessagesAPI(this.idValue)
|
|
49
|
-
|
|
49
|
+
|
|
50
|
+
this.webChatChannel = new WebchatChannel(
|
|
51
|
+
this.idValue,
|
|
52
|
+
Hellotext.session,
|
|
53
|
+
this.conversationIdValue,
|
|
54
|
+
)
|
|
55
|
+
|
|
50
56
|
this.files = []
|
|
51
57
|
|
|
52
58
|
this.onMessageReceived = this.onMessageReceived.bind(this)
|
|
@@ -79,7 +85,7 @@ export default class extends Controller {
|
|
|
79
85
|
this.toolbarTarget.appendChild(LogoBuilder.build())
|
|
80
86
|
}
|
|
81
87
|
|
|
82
|
-
if(localStorage.getItem(`hellotext--webchat--${this.idValue}`) === 'opened') {
|
|
88
|
+
if (localStorage.getItem(`hellotext--webchat--${this.idValue}`) === 'opened') {
|
|
83
89
|
this.openValue = true
|
|
84
90
|
}
|
|
85
91
|
|
|
@@ -95,10 +101,18 @@ export default class extends Controller {
|
|
|
95
101
|
}
|
|
96
102
|
|
|
97
103
|
async onScroll() {
|
|
98
|
-
if(
|
|
104
|
+
if (
|
|
105
|
+
this.messagesContainerTarget.scrollTop > 300 ||
|
|
106
|
+
!this.nextPageValue ||
|
|
107
|
+
this.fetchingNextPage
|
|
108
|
+
)
|
|
109
|
+
return
|
|
99
110
|
|
|
100
111
|
this.fetchingNextPage = true
|
|
101
|
-
const response = await this.messagesAPI.index({
|
|
112
|
+
const response = await this.messagesAPI.index({
|
|
113
|
+
page: this.nextPageValue,
|
|
114
|
+
session: Hellotext.session,
|
|
115
|
+
})
|
|
102
116
|
|
|
103
117
|
const { next: nextPage, messages } = await response.json()
|
|
104
118
|
|
|
@@ -118,13 +132,13 @@ export default class extends Controller {
|
|
|
118
132
|
|
|
119
133
|
element.querySelector('[data-body]').innerHTML = div.innerHTML
|
|
120
134
|
|
|
121
|
-
if(message.state === 'received') {
|
|
135
|
+
if (message.state === 'received') {
|
|
122
136
|
element.classList.add('received')
|
|
123
137
|
} else {
|
|
124
138
|
element.classList.remove('received')
|
|
125
139
|
}
|
|
126
140
|
|
|
127
|
-
if(attachments) {
|
|
141
|
+
if (attachments) {
|
|
128
142
|
attachments.forEach(attachmentUrl => {
|
|
129
143
|
const image = this.attachmentImageTarget.cloneNode(true)
|
|
130
144
|
|
|
@@ -150,7 +164,12 @@ export default class extends Controller {
|
|
|
150
164
|
}
|
|
151
165
|
|
|
152
166
|
onClickOutside(event) {
|
|
153
|
-
if (
|
|
167
|
+
if (
|
|
168
|
+
WebchatConfiguration.behaviour === behaviors.POPOVER &&
|
|
169
|
+
this.openValue &&
|
|
170
|
+
event.target.nodeType &&
|
|
171
|
+
this.element.contains(event.target) === false
|
|
172
|
+
) {
|
|
154
173
|
this.openValue = false
|
|
155
174
|
}
|
|
156
175
|
}
|
|
@@ -158,7 +177,7 @@ export default class extends Controller {
|
|
|
158
177
|
onPopoverOpened() {
|
|
159
178
|
this.inputTarget.focus()
|
|
160
179
|
|
|
161
|
-
if(!this.scrolled) {
|
|
180
|
+
if (!this.scrolled) {
|
|
162
181
|
this.messagesContainerTarget.scroll({
|
|
163
182
|
top: this.messagesContainerTarget.scrollHeight,
|
|
164
183
|
behavior: 'instant',
|
|
@@ -171,7 +190,7 @@ export default class extends Controller {
|
|
|
171
190
|
|
|
172
191
|
localStorage.setItem(`hellotext--webchat--${this.idValue}`, 'opened')
|
|
173
192
|
|
|
174
|
-
if(this.unreadCounterTarget.style.display === 'none') return
|
|
193
|
+
if (this.unreadCounterTarget.style.display === 'none') return
|
|
175
194
|
|
|
176
195
|
this.unreadCounterTarget.style.display = 'none'
|
|
177
196
|
this.unreadCounterTarget.innerText = '0'
|
|
@@ -183,7 +202,7 @@ export default class extends Controller {
|
|
|
183
202
|
Hellotext.eventEmitter.dispatch('webchat:closed')
|
|
184
203
|
|
|
185
204
|
setTimeout(() => {
|
|
186
|
-
this.inputTarget.value =
|
|
205
|
+
this.inputTarget.value = ''
|
|
187
206
|
})
|
|
188
207
|
|
|
189
208
|
localStorage.setItem(`hellotext--webchat--${this.idValue}`, 'closed')
|
|
@@ -195,12 +214,12 @@ export default class extends Controller {
|
|
|
195
214
|
|
|
196
215
|
const reactionsContainer = messageElement.querySelector('[data-reactions]')
|
|
197
216
|
|
|
198
|
-
if(type === 'reaction.destroy') {
|
|
217
|
+
if (type === 'reaction.destroy') {
|
|
199
218
|
const reactionElement = reactionsContainer.querySelector(`[data-id="${reaction.id}"]`)
|
|
200
219
|
return reactionElement.remove()
|
|
201
220
|
}
|
|
202
221
|
|
|
203
|
-
if(reactionsContainer.querySelector(`[data-id="${reaction.id}"]`)) {
|
|
222
|
+
if (reactionsContainer.querySelector(`[data-id="${reaction.id}"]`)) {
|
|
204
223
|
const reactionElement = reactionsContainer.querySelector(`[data-id="${reaction.id}"]`)
|
|
205
224
|
reactionElement.innerText = reaction.emoji
|
|
206
225
|
} else {
|
|
@@ -225,7 +244,7 @@ export default class extends Controller {
|
|
|
225
244
|
element.querySelector('[data-body]').innerHTML = div.innerHTML
|
|
226
245
|
element.setAttribute('data-hellotext--webchat-target', 'message')
|
|
227
246
|
|
|
228
|
-
if(attachments) {
|
|
247
|
+
if (attachments) {
|
|
229
248
|
attachments.forEach(attachmentUrl => {
|
|
230
249
|
const image = this.attachmentImageTarget.cloneNode(true)
|
|
231
250
|
image.src = attachmentUrl
|
|
@@ -245,7 +264,7 @@ export default class extends Controller {
|
|
|
245
264
|
element.scrollIntoView({ behavior: 'smooth' })
|
|
246
265
|
this.setOfflineTimeout()
|
|
247
266
|
|
|
248
|
-
if(this.openValue) return
|
|
267
|
+
if (this.openValue) return
|
|
249
268
|
|
|
250
269
|
this.unreadCounterTarget.style.display = 'flex'
|
|
251
270
|
|
|
@@ -258,7 +277,7 @@ export default class extends Controller {
|
|
|
258
277
|
|
|
259
278
|
this.titleTarget.innerText = user.name
|
|
260
279
|
|
|
261
|
-
if(user.online) {
|
|
280
|
+
if (user.online) {
|
|
262
281
|
this.onlineStatusTarget.style.display = 'flex'
|
|
263
282
|
} else {
|
|
264
283
|
this.onlineStatusTarget.style.display = 'none'
|
|
@@ -275,7 +294,7 @@ export default class extends Controller {
|
|
|
275
294
|
|
|
276
295
|
const message = {
|
|
277
296
|
body: this.inputTarget.value,
|
|
278
|
-
attachments: this.files
|
|
297
|
+
attachments: this.files,
|
|
279
298
|
}
|
|
280
299
|
|
|
281
300
|
formData.append('message[body]', this.inputTarget.value)
|
|
@@ -294,9 +313,9 @@ export default class extends Controller {
|
|
|
294
313
|
element.setAttribute('data-hellotext--webchat-target', 'message')
|
|
295
314
|
element.querySelector('[data-body]').innerText = this.inputTarget.value
|
|
296
315
|
|
|
297
|
-
const attachments =
|
|
316
|
+
const attachments = this.attachmentContainerTarget.querySelectorAll('img')
|
|
298
317
|
|
|
299
|
-
if(attachments.length > 0) {
|
|
318
|
+
if (attachments.length > 0) {
|
|
300
319
|
attachments.forEach(attachment => {
|
|
301
320
|
element.querySelector('[data-attachment-container]').appendChild(attachment)
|
|
302
321
|
})
|
|
@@ -305,16 +324,16 @@ export default class extends Controller {
|
|
|
305
324
|
this.messagesContainerTarget.appendChild(element)
|
|
306
325
|
element.scrollIntoView({ behavior: 'smooth' })
|
|
307
326
|
|
|
308
|
-
this.inputTarget.value =
|
|
327
|
+
this.inputTarget.value = ''
|
|
309
328
|
this.files = []
|
|
310
|
-
this.attachmentContainerTarget.
|
|
311
|
-
this.
|
|
329
|
+
this.attachmentContainerTarget.style.display = 'none'
|
|
330
|
+
this.errorMessageContainerTarget.style.display = 'none'
|
|
312
331
|
|
|
313
332
|
this.inputTarget.focus()
|
|
314
333
|
|
|
315
334
|
const response = await this.messagesAPI.create(formData)
|
|
316
335
|
|
|
317
|
-
if(response.failed) {
|
|
336
|
+
if (response.failed) {
|
|
318
337
|
return element.classList.add('failed')
|
|
319
338
|
}
|
|
320
339
|
|
|
@@ -324,10 +343,12 @@ export default class extends Controller {
|
|
|
324
343
|
|
|
325
344
|
Hellotext.eventEmitter.dispatch('webchat:message:sent', message)
|
|
326
345
|
|
|
327
|
-
if(data.conversation !== this.conversationIdValue) {
|
|
346
|
+
if (data.conversation !== this.conversationIdValue) {
|
|
328
347
|
this.conversationIdValue = data.conversation
|
|
329
348
|
this.webChatChannel.updateSubscriptionWith(this.conversationIdValue)
|
|
330
349
|
}
|
|
350
|
+
|
|
351
|
+
this.attachmentContainerTarget.style.display = ''
|
|
331
352
|
}
|
|
332
353
|
|
|
333
354
|
openAttachment() {
|
|
@@ -335,29 +356,32 @@ export default class extends Controller {
|
|
|
335
356
|
}
|
|
336
357
|
|
|
337
358
|
onFileInputChange() {
|
|
338
|
-
this.errorMessageContainerTarget.
|
|
359
|
+
this.errorMessageContainerTarget.style.display = 'none'
|
|
339
360
|
|
|
340
361
|
this.files = Array.from(this.attachmentInputTarget.files)
|
|
341
362
|
|
|
342
363
|
const fileMaxSizeTooMuch = this.files.find(file => {
|
|
343
|
-
const type = file.type.split(
|
|
364
|
+
const type = file.type.split('/')[0]
|
|
344
365
|
|
|
345
|
-
if(['image', 'video', 'audio'].includes(type)) {
|
|
366
|
+
if (['image', 'video', 'audio'].includes(type)) {
|
|
346
367
|
return this.mediaValue[type].max_size < file.size
|
|
347
368
|
} else {
|
|
348
369
|
return this.mediaValue.document.max_size < file.size
|
|
349
370
|
}
|
|
350
371
|
})
|
|
351
372
|
|
|
352
|
-
if(fileMaxSizeTooMuch) {
|
|
353
|
-
const type = fileMaxSizeTooMuch.type.split(
|
|
373
|
+
if (fileMaxSizeTooMuch) {
|
|
374
|
+
const type = fileMaxSizeTooMuch.type.split('/')[0]
|
|
354
375
|
const mediaType = ['image', 'audio', 'video'].includes(type) ? type : 'document'
|
|
355
376
|
|
|
356
|
-
this.errorMessageContainerTarget.innerText = this.fileSizeErrorMessageValue.replace(
|
|
377
|
+
this.errorMessageContainerTarget.innerText = this.fileSizeErrorMessageValue.replace(
|
|
378
|
+
'%{limit}',
|
|
379
|
+
this.byteToMegabyte(this.mediaValue[mediaType].max_size),
|
|
380
|
+
)
|
|
357
381
|
return
|
|
358
382
|
}
|
|
359
383
|
|
|
360
|
-
this.errorMessageContainerTarget.innerText =
|
|
384
|
+
this.errorMessageContainerTarget.innerText = ''
|
|
361
385
|
this.files.forEach(file => this.createAttachmentElement(file))
|
|
362
386
|
this.inputTarget.focus()
|
|
363
387
|
}
|
|
@@ -365,11 +389,11 @@ export default class extends Controller {
|
|
|
365
389
|
createAttachmentElement(file) {
|
|
366
390
|
const element = this.attachmentElement()
|
|
367
391
|
|
|
368
|
-
this.attachmentContainerTarget.
|
|
392
|
+
this.attachmentContainerTarget.style.display = ''
|
|
369
393
|
|
|
370
394
|
element.setAttribute('data-name', file.name)
|
|
371
395
|
|
|
372
|
-
if(file.type.startsWith(
|
|
396
|
+
if (file.type.startsWith('image/')) {
|
|
373
397
|
const thumbnail = this.attachmentImageTarget.cloneNode(true)
|
|
374
398
|
|
|
375
399
|
thumbnail.src = URL.createObjectURL(file)
|
|
@@ -380,8 +404,13 @@ export default class extends Controller {
|
|
|
380
404
|
this.attachmentContainerTarget.appendChild(element)
|
|
381
405
|
this.attachmentContainerTarget.style.display = 'flex'
|
|
382
406
|
} else {
|
|
383
|
-
element.querySelector(
|
|
384
|
-
|
|
407
|
+
const main = element.querySelector('main')
|
|
408
|
+
main.style.height = '5rem'
|
|
409
|
+
main.style.borderRadius = '0.375rem'
|
|
410
|
+
main.style.backgroundColor = '#e5e7eb'
|
|
411
|
+
main.style.padding = '0.25rem'
|
|
412
|
+
|
|
413
|
+
element.querySelector('p[data-attachment-name]').innerText = file.name
|
|
385
414
|
}
|
|
386
415
|
}
|
|
387
416
|
|
|
@@ -395,18 +424,18 @@ export default class extends Controller {
|
|
|
395
424
|
}
|
|
396
425
|
|
|
397
426
|
attachmentTargetDisconnected() {
|
|
398
|
-
if(this.attachmentTargets.length === 0) {
|
|
399
|
-
this.attachmentContainerTarget.innerHTML =
|
|
427
|
+
if (this.attachmentTargets.length === 0) {
|
|
428
|
+
this.attachmentContainerTarget.innerHTML = ''
|
|
400
429
|
this.attachmentContainerTarget.style.display = 'none'
|
|
401
430
|
}
|
|
402
431
|
}
|
|
403
432
|
|
|
404
433
|
attachmentElement() {
|
|
405
434
|
const element = this.attachmentTemplateTarget.cloneNode(true)
|
|
406
|
-
element.removeAttribute(
|
|
435
|
+
element.removeAttribute('hidden')
|
|
407
436
|
element.style.display = 'flex'
|
|
408
437
|
|
|
409
|
-
element.setAttribute(
|
|
438
|
+
element.setAttribute('data-hellotext--webchat-target', 'attachment')
|
|
410
439
|
|
|
411
440
|
return element
|
|
412
441
|
}
|
|
@@ -439,10 +468,6 @@ export default class extends Controller {
|
|
|
439
468
|
}
|
|
440
469
|
|
|
441
470
|
get middlewares() {
|
|
442
|
-
return [
|
|
443
|
-
offset(5),
|
|
444
|
-
shift({ padding: 24 }),
|
|
445
|
-
flip(),
|
|
446
|
-
]
|
|
471
|
+
return [offset(5), shift({ padding: 24 }), flip()]
|
|
447
472
|
}
|
|
448
473
|
}
|
package/src/hellotext.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Configuration, Event } from './core'
|
|
2
2
|
|
|
3
3
|
import API, { Response } from './api'
|
|
4
|
-
import { Business,
|
|
4
|
+
import { Business, FormCollection, Query, Session, Webchat } from './models'
|
|
5
5
|
|
|
6
6
|
import { NotInitializedError } from './errors'
|
|
7
7
|
|
|
8
|
-
|
|
9
8
|
class Hellotext {
|
|
10
9
|
static #session
|
|
11
10
|
static #query
|
|
@@ -47,7 +46,7 @@ class Hellotext {
|
|
|
47
46
|
}
|
|
48
47
|
|
|
49
48
|
const headers = {
|
|
50
|
-
...(params && params.headers) || {},
|
|
49
|
+
...((params && params.headers) || {}),
|
|
51
50
|
...this.headers,
|
|
52
51
|
}
|
|
53
52
|
|
package/src/models/session.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {Configuration} from '../core'
|
|
2
|
-
import {Cookies
|
|
1
|
+
import { Configuration } from '../core'
|
|
2
|
+
import { Cookies } from './cookies'
|
|
3
|
+
import { Query } from './query'
|
|
3
4
|
|
|
4
5
|
class Session {
|
|
5
6
|
static #session
|
|
@@ -29,4 +30,4 @@ class Session {
|
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
export {Session}
|
|
33
|
+
export { Session }
|
package/.babelrc
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"presets": [
|
|
3
|
-
[
|
|
4
|
-
"@babel/preset-env",
|
|
5
|
-
{
|
|
6
|
-
"targets": {
|
|
7
|
-
"esmodules": true
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
]
|
|
11
|
-
],
|
|
12
|
-
"plugins": [
|
|
13
|
-
[
|
|
14
|
-
"@babel/plugin-proposal-private-methods",
|
|
15
|
-
{
|
|
16
|
-
"loose": true
|
|
17
|
-
}
|
|
18
|
-
],
|
|
19
|
-
["@babel/plugin-proposal-private-property-in-object", { "loose": true }],
|
|
20
|
-
["@babel/plugin-proposal-class-properties", { "loose": true }],
|
|
21
|
-
"@babel/plugin-transform-classes",
|
|
22
|
-
"@babel/plugin-proposal-export-default-from"
|
|
23
|
-
]
|
|
24
|
-
}
|
package/.github/workflows/ci.yml
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
name: Tests
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
pull_request:
|
|
5
|
-
branches:
|
|
6
|
-
- '*'
|
|
7
|
-
push:
|
|
8
|
-
branches:
|
|
9
|
-
- main
|
|
10
|
-
|
|
11
|
-
jobs:
|
|
12
|
-
test:
|
|
13
|
-
runs-on: ubuntu-latest
|
|
14
|
-
strategy:
|
|
15
|
-
matrix:
|
|
16
|
-
node: ['20', '22']
|
|
17
|
-
name: Node ${{ matrix.node }}
|
|
18
|
-
steps:
|
|
19
|
-
- uses: actions/checkout@v2
|
|
20
|
-
- uses: actions/setup-node@v2
|
|
21
|
-
with:
|
|
22
|
-
node-version: ${{ matrix.node }}
|
|
23
|
-
- run: npm install
|
|
24
|
-
- run: npm run test
|
package/.prettierignore
DELETED
package/.prettierrc.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"arrowParens": "avoid",
|
|
3
|
-
"bracketSpacing": true,
|
|
4
|
-
"printWidth": 100,
|
|
5
|
-
"semi": false,
|
|
6
|
-
"singleQuote": true,
|
|
7
|
-
"tabWidth": 2,
|
|
8
|
-
"trailingComma": "all",
|
|
9
|
-
"useTabs": false,
|
|
10
|
-
"overrides": [
|
|
11
|
-
{
|
|
12
|
-
"files": "*.json",
|
|
13
|
-
"options": {
|
|
14
|
-
"printWidth": 200
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
]
|
|
18
|
-
}
|
package/MIT-LICENSE
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
Copyright (c) 2022 HelloText
|
|
2
|
-
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
-
a copy of this software and associated documentation files (the
|
|
5
|
-
"Software"), to deal in the Software without restriction, including
|
|
6
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
-
the following conditions:
|
|
10
|
-
|
|
11
|
-
The above copyright notice and this permission notice shall be
|
|
12
|
-
included in all copies or substantial portions of the Software.
|
|
13
|
-
|
|
14
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @jest-environment jsdom
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import Hellotext from '../../src/hellotext'
|
|
6
|
-
import { InputBuilder } from '../../src/builders/input_builder'
|
|
7
|
-
|
|
8
|
-
describe('when the input is first_name', () => {
|
|
9
|
-
const data = {
|
|
10
|
-
label: 'First Name',
|
|
11
|
-
type: 'text',
|
|
12
|
-
required: true,
|
|
13
|
-
placeholder: 'Enter your first name',
|
|
14
|
-
kind: 'first_name',
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
it('builds an article element that contains a label and input elements', () => {
|
|
18
|
-
const article = InputBuilder.build(data)
|
|
19
|
-
const label = article.querySelector('label')
|
|
20
|
-
const input = article.querySelector('input')
|
|
21
|
-
|
|
22
|
-
expect(label.innerText).toEqual('First Name')
|
|
23
|
-
expect(label.getAttribute('for')).toEqual('first_name')
|
|
24
|
-
|
|
25
|
-
expect(input.id).toEqual('first_name')
|
|
26
|
-
expect(input.type).toEqual('text')
|
|
27
|
-
expect(input.required).toEqual(true)
|
|
28
|
-
expect(input.placeholder).toEqual('Enter your first name')
|
|
29
|
-
expect(input.name).toEqual('first_name')
|
|
30
|
-
})
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
describe('when the input is last_name', () => {
|
|
34
|
-
const data = {
|
|
35
|
-
label: 'Last Name',
|
|
36
|
-
type: 'text',
|
|
37
|
-
required: false,
|
|
38
|
-
placeholder: 'Enter your last name',
|
|
39
|
-
kind: 'last_name',
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
it('builds an article element that contains a label and input elements', () => {
|
|
43
|
-
const article = InputBuilder.build(data)
|
|
44
|
-
const label = article.querySelector('label')
|
|
45
|
-
const input = article.querySelector('input')
|
|
46
|
-
|
|
47
|
-
expect(label.innerText).toEqual('Last Name')
|
|
48
|
-
expect(label.getAttribute('for')).toEqual('last_name')
|
|
49
|
-
|
|
50
|
-
expect(input.id).toEqual('last_name')
|
|
51
|
-
expect(input.type).toEqual('text')
|
|
52
|
-
expect(input.required).toEqual(false)
|
|
53
|
-
expect(input.placeholder).toEqual('Enter your last name')
|
|
54
|
-
expect(input.name).toEqual('last_name')
|
|
55
|
-
})
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
describe('when the input belongs to a property', () => {
|
|
59
|
-
const data = {
|
|
60
|
-
label: 'Email',
|
|
61
|
-
type: 'email',
|
|
62
|
-
required: true,
|
|
63
|
-
placeholder: 'Enter your email',
|
|
64
|
-
kind: 'email',
|
|
65
|
-
property: 'xybz',
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
it('builds an article element that contains a label and input elements', () => {
|
|
69
|
-
const article = InputBuilder.build(data)
|
|
70
|
-
const label = article.querySelector('label')
|
|
71
|
-
const input = article.querySelector('input')
|
|
72
|
-
|
|
73
|
-
expect(label.innerText).toEqual('Email')
|
|
74
|
-
expect(label.getAttribute('for')).toEqual('email')
|
|
75
|
-
|
|
76
|
-
expect(input.id).toEqual('email')
|
|
77
|
-
expect(input.type).toEqual('email')
|
|
78
|
-
expect(input.required).toEqual(true)
|
|
79
|
-
expect(input.placeholder).toEqual('Enter your email')
|
|
80
|
-
expect(input.name).toEqual('email')
|
|
81
|
-
})
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
describe('when the input is a phone number', () => {
|
|
85
|
-
const data = {
|
|
86
|
-
label: 'Phone',
|
|
87
|
-
type: 'tel',
|
|
88
|
-
required: true,
|
|
89
|
-
placeholder: 'Enter your phone number',
|
|
90
|
-
kind: 'phone',
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
beforeEach(() => {
|
|
94
|
-
Hellotext.business = {
|
|
95
|
-
country: {
|
|
96
|
-
prefix: '598',
|
|
97
|
-
code: 'UY',
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
it('builds an article element that contains a label and input elements', () => {
|
|
103
|
-
const article = InputBuilder.build(data)
|
|
104
|
-
const label = article.querySelector('label')
|
|
105
|
-
const input = article.querySelector('input')
|
|
106
|
-
|
|
107
|
-
expect(label.innerText).toEqual('Phone')
|
|
108
|
-
expect(label.getAttribute('for')).toEqual('phone')
|
|
109
|
-
|
|
110
|
-
expect(input.id).toEqual('phone')
|
|
111
|
-
expect(input.type).toEqual('tel')
|
|
112
|
-
expect(input.required).toEqual(true)
|
|
113
|
-
expect(input.placeholder).toEqual('Enter your phone number')
|
|
114
|
-
expect(input.name).toEqual('phone')
|
|
115
|
-
expect(input.value).toEqual('+598')
|
|
116
|
-
})
|
|
117
|
-
})
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Forms } from '../../../src/core/configuration/forms'
|
|
2
|
-
|
|
3
|
-
describe('Forms', () => {
|
|
4
|
-
describe('.autoMount', () => {
|
|
5
|
-
it('is true by default', () => {
|
|
6
|
-
expect(Forms.autoMount).toEqual(true)
|
|
7
|
-
})
|
|
8
|
-
|
|
9
|
-
it('can be set to false', () => {
|
|
10
|
-
Forms.autoMount = false
|
|
11
|
-
expect(Forms.autoMount).toEqual(false)
|
|
12
|
-
})
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
describe('.successMessage', () => {
|
|
16
|
-
it('is true by default', () => {
|
|
17
|
-
expect(Forms.successMessage).toEqual(true)
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it('can be set to false', () => {
|
|
21
|
-
Forms.successMessage = false
|
|
22
|
-
expect(Forms.successMessage).toEqual(false)
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it('can be set to a string', () => {
|
|
26
|
-
Forms.successMessage = 'Thank you for your submission'
|
|
27
|
-
expect(Forms.successMessage).toEqual('Thank you for your submission')
|
|
28
|
-
})
|
|
29
|
-
})
|
|
30
|
-
})
|