@hellotext/hellotext 2.1.4 → 2.1.6
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/README.md +1 -0
- package/dist/hellotext.js +1 -1
- package/lib/controllers/webchat_controller.cjs +14 -10
- package/lib/controllers/webchat_controller.js +14 -10
- package/lib/core/event.cjs +1 -1
- package/lib/core/event.js +1 -1
- package/lib/hellotext.cjs +3 -1
- package/lib/hellotext.js +4 -4
- package/lib/models/cookies.cjs +6 -1
- package/lib/models/cookies.js +6 -1
- package/lib/models/index.cjs +14 -0
- package/lib/models/index.js +2 -0
- package/lib/models/page.cjs +86 -0
- package/lib/models/page.js +81 -0
- package/lib/models/utm.cjs +41 -0
- package/lib/models/utm.js +38 -0
- package/package.json +1 -1
- package/src/controllers/webchat_controller.js +14 -10
- package/src/core/event.js +1 -0
- package/src/hellotext.js +5 -2
- package/src/models/cookies.js +9 -3
- package/src/models/index.js +2 -0
- package/src/models/page.js +65 -0
- package/src/models/utm.js +33 -0
|
@@ -326,11 +326,7 @@ let _default = /*#__PURE__*/function (_Controller) {
|
|
|
326
326
|
element.querySelector('[data-attachment-container]').appendChild(image);
|
|
327
327
|
});
|
|
328
328
|
}
|
|
329
|
-
|
|
330
|
-
// Clear any typing indicator when message is received
|
|
331
|
-
if (this.typingIndicatorVisible) {
|
|
332
|
-
this.clearTypingIndicator();
|
|
333
|
-
}
|
|
329
|
+
this.clearTypingIndicator();
|
|
334
330
|
this.messagesContainerTarget.appendChild(element);
|
|
335
331
|
_hellotext.default.eventEmitter.dispatch('webchat:message:received', {
|
|
336
332
|
...message,
|
|
@@ -422,8 +418,19 @@ let _default = /*#__PURE__*/function (_Controller) {
|
|
|
422
418
|
this.attachmentContainerTarget.style.display = 'none';
|
|
423
419
|
this.errorMessageContainerTarget.style.display = 'none';
|
|
424
420
|
this.inputTarget.focus();
|
|
421
|
+
|
|
422
|
+
// Set up optimistic typing indicator BEFORE making the API call
|
|
423
|
+
// This prevents race conditions with server responses
|
|
424
|
+
if (!this.typingIndicatorVisible) {
|
|
425
|
+
clearTimeout(this.optimisticTypingTimeout);
|
|
426
|
+
this.optimisticTypingTimeout = setTimeout(() => {
|
|
427
|
+
this.showOptimisticTypingIndicator();
|
|
428
|
+
}, this.optimisticTypingIndicatorWaitValue);
|
|
429
|
+
}
|
|
425
430
|
const response = await this.messagesAPI.create(formData);
|
|
426
431
|
if (response.failed) {
|
|
432
|
+
// Clear the optimistic typing indicator on failure
|
|
433
|
+
clearTimeout(this.optimisticTypingTimeout);
|
|
427
434
|
this.broadcastChannel.postMessage({
|
|
428
435
|
type: 'message:failed',
|
|
429
436
|
id: element.id
|
|
@@ -438,13 +445,10 @@ let _default = /*#__PURE__*/function (_Controller) {
|
|
|
438
445
|
this.conversationIdValue = data.conversation;
|
|
439
446
|
this.webChatChannel.updateSubscriptionWith(this.conversationIdValue);
|
|
440
447
|
}
|
|
448
|
+
|
|
449
|
+
// If there's already a typing indicator visible, reset its timer
|
|
441
450
|
if (this.typingIndicatorVisible) {
|
|
442
451
|
this.resetTypingIndicatorTimer();
|
|
443
|
-
} else {
|
|
444
|
-
clearTimeout(this.optimisticTypingTimeout);
|
|
445
|
-
this.optimisticTypingTimeout = setTimeout(() => {
|
|
446
|
-
this.showOptimisticTypingIndicator();
|
|
447
|
-
}, this.optimisticTypingIndicatorWaitValue);
|
|
448
452
|
}
|
|
449
453
|
this.attachmentContainerTarget.style.display = '';
|
|
450
454
|
}
|
|
@@ -330,11 +330,7 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
330
330
|
element.querySelector('[data-attachment-container]').appendChild(image);
|
|
331
331
|
});
|
|
332
332
|
}
|
|
333
|
-
|
|
334
|
-
// Clear any typing indicator when message is received
|
|
335
|
-
if (this.typingIndicatorVisible) {
|
|
336
|
-
this.clearTypingIndicator();
|
|
337
|
-
}
|
|
333
|
+
this.clearTypingIndicator();
|
|
338
334
|
this.messagesContainerTarget.appendChild(element);
|
|
339
335
|
Hellotext.eventEmitter.dispatch('webchat:message:received', _objectSpread(_objectSpread({}, message), {}, {
|
|
340
336
|
body: element.querySelector('[data-body]').innerText
|
|
@@ -426,8 +422,19 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
426
422
|
this.attachmentContainerTarget.style.display = 'none';
|
|
427
423
|
this.errorMessageContainerTarget.style.display = 'none';
|
|
428
424
|
this.inputTarget.focus();
|
|
425
|
+
|
|
426
|
+
// Set up optimistic typing indicator BEFORE making the API call
|
|
427
|
+
// This prevents race conditions with server responses
|
|
428
|
+
if (!this.typingIndicatorVisible) {
|
|
429
|
+
clearTimeout(this.optimisticTypingTimeout);
|
|
430
|
+
this.optimisticTypingTimeout = setTimeout(() => {
|
|
431
|
+
this.showOptimisticTypingIndicator();
|
|
432
|
+
}, this.optimisticTypingIndicatorWaitValue);
|
|
433
|
+
}
|
|
429
434
|
var response = yield this.messagesAPI.create(formData);
|
|
430
435
|
if (response.failed) {
|
|
436
|
+
// Clear the optimistic typing indicator on failure
|
|
437
|
+
clearTimeout(this.optimisticTypingTimeout);
|
|
431
438
|
this.broadcastChannel.postMessage({
|
|
432
439
|
type: 'message:failed',
|
|
433
440
|
id: element.id
|
|
@@ -442,13 +449,10 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
442
449
|
this.conversationIdValue = data.conversation;
|
|
443
450
|
this.webChatChannel.updateSubscriptionWith(this.conversationIdValue);
|
|
444
451
|
}
|
|
452
|
+
|
|
453
|
+
// If there's already a typing indicator visible, reset its timer
|
|
445
454
|
if (this.typingIndicatorVisible) {
|
|
446
455
|
this.resetTypingIndicatorTimer();
|
|
447
|
-
} else {
|
|
448
|
-
clearTimeout(this.optimisticTypingTimeout);
|
|
449
|
-
this.optimisticTypingTimeout = setTimeout(() => {
|
|
450
|
-
this.showOptimisticTypingIndicator();
|
|
451
|
-
}, this.optimisticTypingIndicatorWaitValue);
|
|
452
456
|
}
|
|
453
457
|
this.attachmentContainerTarget.style.display = '';
|
|
454
458
|
});
|
package/lib/core/event.cjs
CHANGED
|
@@ -68,4 +68,4 @@ let Event = /*#__PURE__*/function () {
|
|
|
68
68
|
return Event;
|
|
69
69
|
}();
|
|
70
70
|
exports.default = Event;
|
|
71
|
-
Event.events = ['session-set', 'forms:collected', 'form:completed', 'webchat:mounted', 'webchat:opened', 'webchat:closed', 'webchat:message:sent', 'webchat:message:received'];
|
|
71
|
+
Event.events = ['session-set', 'utm-set', 'forms:collected', 'form:completed', 'webchat:mounted', 'webchat:opened', 'webchat:closed', 'webchat:message:sent', 'webchat:message:received'];
|
package/lib/core/event.js
CHANGED
|
@@ -63,5 +63,5 @@ var Event = /*#__PURE__*/function () {
|
|
|
63
63
|
}]);
|
|
64
64
|
return Event;
|
|
65
65
|
}();
|
|
66
|
-
Event.events = ['session-set', 'forms:collected', 'form:completed', 'webchat:mounted', 'webchat:opened', 'webchat:closed', 'webchat:message:sent', 'webchat:message:received'];
|
|
66
|
+
Event.events = ['session-set', 'utm-set', 'forms:collected', 'form:completed', 'webchat:mounted', 'webchat:opened', 'webchat:closed', 'webchat:message:sent', 'webchat:message:received'];
|
|
67
67
|
export { Event as default };
|
package/lib/hellotext.cjs
CHANGED
|
@@ -35,6 +35,7 @@ let Hellotext = /*#__PURE__*/function () {
|
|
|
35
35
|
async function initialize(business, config) {
|
|
36
36
|
_core.Configuration.assign(config);
|
|
37
37
|
_models.Session.initialize();
|
|
38
|
+
this.page = new _models.Page();
|
|
38
39
|
this.business = new _models.Business(business);
|
|
39
40
|
this.forms = new _models.FormCollection();
|
|
40
41
|
_classPrivateFieldLooseBase(this, _query)[_query] = new _models.Query();
|
|
@@ -63,11 +64,12 @@ let Hellotext = /*#__PURE__*/function () {
|
|
|
63
64
|
...(params && params.headers || {}),
|
|
64
65
|
...this.headers
|
|
65
66
|
};
|
|
67
|
+
const pageInstance = params && params.url ? new _models.Page(params.url) : this.page;
|
|
66
68
|
const body = {
|
|
67
69
|
session: this.session,
|
|
68
70
|
action,
|
|
69
71
|
...params,
|
|
70
|
-
|
|
72
|
+
...pageInstance.trackingData
|
|
71
73
|
};
|
|
72
74
|
delete body.headers;
|
|
73
75
|
return await _api.default.events.create({
|
package/lib/hellotext.js
CHANGED
|
@@ -13,7 +13,7 @@ var id = 0;
|
|
|
13
13
|
function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
|
|
14
14
|
import { Configuration, Event } from './core';
|
|
15
15
|
import API, { Response } from './api';
|
|
16
|
-
import { Business, FormCollection, Query, Session, Webchat } from './models';
|
|
16
|
+
import { Business, FormCollection, Page, Query, Session, Webchat } from './models';
|
|
17
17
|
import { NotInitializedError } from './errors';
|
|
18
18
|
var _session = /*#__PURE__*/_classPrivateFieldLooseKey("session");
|
|
19
19
|
var _query = /*#__PURE__*/_classPrivateFieldLooseKey("query");
|
|
@@ -33,6 +33,7 @@ var Hellotext = /*#__PURE__*/function () {
|
|
|
33
33
|
var _initialize = _asyncToGenerator(function* (business, config) {
|
|
34
34
|
Configuration.assign(config);
|
|
35
35
|
Session.initialize();
|
|
36
|
+
this.page = new Page();
|
|
36
37
|
this.business = new Business(business);
|
|
37
38
|
this.forms = new FormCollection();
|
|
38
39
|
_classPrivateFieldLooseBase(this, _query)[_query] = new Query();
|
|
@@ -64,12 +65,11 @@ var Hellotext = /*#__PURE__*/function () {
|
|
|
64
65
|
throw new NotInitializedError();
|
|
65
66
|
}
|
|
66
67
|
var headers = _objectSpread(_objectSpread({}, params && params.headers || {}), this.headers);
|
|
68
|
+
var pageInstance = params && params.url ? new Page(params.url) : this.page;
|
|
67
69
|
var body = _objectSpread(_objectSpread({
|
|
68
70
|
session: this.session,
|
|
69
71
|
action
|
|
70
|
-
}, params),
|
|
71
|
-
url: params && params.url || window.location.href
|
|
72
|
-
});
|
|
72
|
+
}, params), pageInstance.trackingData);
|
|
73
73
|
delete body.headers;
|
|
74
74
|
return yield API.events.create({
|
|
75
75
|
headers,
|
package/lib/models/cookies.cjs
CHANGED
|
@@ -21,7 +21,12 @@ let Cookies = /*#__PURE__*/function () {
|
|
|
21
21
|
if (typeof document !== 'undefined') {
|
|
22
22
|
document.cookie = `${name}=${value}; path=/;`;
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
if (name === 'hello_session') {
|
|
25
|
+
_hellotext.default.eventEmitter.dispatch('session-set', value);
|
|
26
|
+
}
|
|
27
|
+
if (name === 'hello_utm') {
|
|
28
|
+
_hellotext.default.eventEmitter.dispatch('utm-set', value);
|
|
29
|
+
}
|
|
25
30
|
return value;
|
|
26
31
|
}
|
|
27
32
|
}, {
|
package/lib/models/cookies.js
CHANGED
|
@@ -14,7 +14,12 @@ var Cookies = /*#__PURE__*/function () {
|
|
|
14
14
|
if (typeof document !== 'undefined') {
|
|
15
15
|
document.cookie = "".concat(name, "=").concat(value, "; path=/;");
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
if (name === 'hello_session') {
|
|
18
|
+
Hellotext.eventEmitter.dispatch('session-set', value);
|
|
19
|
+
}
|
|
20
|
+
if (name === 'hello_utm') {
|
|
21
|
+
Hellotext.eventEmitter.dispatch('utm-set', value);
|
|
22
|
+
}
|
|
18
23
|
return value;
|
|
19
24
|
}
|
|
20
25
|
}, {
|
package/lib/models/index.cjs
CHANGED
|
@@ -27,6 +27,12 @@ Object.defineProperty(exports, "FormCollection", {
|
|
|
27
27
|
return _form_collection.FormCollection;
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
|
+
Object.defineProperty(exports, "Page", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return _page.Page;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
30
36
|
Object.defineProperty(exports, "Query", {
|
|
31
37
|
enumerable: true,
|
|
32
38
|
get: function () {
|
|
@@ -39,6 +45,12 @@ Object.defineProperty(exports, "Session", {
|
|
|
39
45
|
return _session.Session;
|
|
40
46
|
}
|
|
41
47
|
});
|
|
48
|
+
Object.defineProperty(exports, "UTM", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () {
|
|
51
|
+
return _utm.UTM;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
42
54
|
Object.defineProperty(exports, "Webchat", {
|
|
43
55
|
enumerable: true,
|
|
44
56
|
get: function () {
|
|
@@ -49,6 +61,8 @@ var _business = require("./business");
|
|
|
49
61
|
var _cookies = require("./cookies");
|
|
50
62
|
var _form = require("./form");
|
|
51
63
|
var _form_collection = require("./form_collection");
|
|
64
|
+
var _page = require("./page");
|
|
52
65
|
var _query = require("./query");
|
|
53
66
|
var _session = require("./session");
|
|
67
|
+
var _utm = require("./utm");
|
|
54
68
|
var _webchat = require("./webchat");
|
package/lib/models/index.js
CHANGED
|
@@ -2,6 +2,8 @@ export { Business } from './business';
|
|
|
2
2
|
export { Cookies } from './cookies';
|
|
3
3
|
export { Form } from './form';
|
|
4
4
|
export { FormCollection } from './form_collection';
|
|
5
|
+
export { Page } from './page';
|
|
5
6
|
export { Query } from './query';
|
|
6
7
|
export { Session } from './session';
|
|
8
|
+
export { UTM } from './utm';
|
|
7
9
|
export { Webchat } from './webchat';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.Page = void 0;
|
|
7
|
+
var _utm = require("./utm");
|
|
8
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
9
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
|
|
10
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
11
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
12
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
13
|
+
let Page = /*#__PURE__*/function () {
|
|
14
|
+
function Page(url = null) {
|
|
15
|
+
_classCallCheck(this, Page);
|
|
16
|
+
this.utm = new _utm.UTM();
|
|
17
|
+
this._url = url;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get the current page URL
|
|
22
|
+
* @returns {string} The page URL
|
|
23
|
+
*/
|
|
24
|
+
_createClass(Page, [{
|
|
25
|
+
key: "url",
|
|
26
|
+
get: function () {
|
|
27
|
+
return this._url || window.location.href;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get the current page title
|
|
32
|
+
* @returns {string} The page title
|
|
33
|
+
*/
|
|
34
|
+
}, {
|
|
35
|
+
key: "title",
|
|
36
|
+
get: function () {
|
|
37
|
+
return document.title;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get the current page path
|
|
42
|
+
* @returns {string} The page path
|
|
43
|
+
*/
|
|
44
|
+
}, {
|
|
45
|
+
key: "path",
|
|
46
|
+
get: function () {
|
|
47
|
+
if (this._url) {
|
|
48
|
+
try {
|
|
49
|
+
return new URL(this._url).pathname;
|
|
50
|
+
} catch (e) {
|
|
51
|
+
return '/';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return window.location.pathname;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get current UTM parameters
|
|
59
|
+
* @returns {Object} The UTM parameters
|
|
60
|
+
*/
|
|
61
|
+
}, {
|
|
62
|
+
key: "utmParams",
|
|
63
|
+
get: function () {
|
|
64
|
+
return this.utm.current;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get page data for tracking
|
|
69
|
+
* @returns {Object} Object containing page object and utm_params
|
|
70
|
+
*/
|
|
71
|
+
}, {
|
|
72
|
+
key: "trackingData",
|
|
73
|
+
get: function () {
|
|
74
|
+
return {
|
|
75
|
+
page: {
|
|
76
|
+
url: this.url,
|
|
77
|
+
title: this.title,
|
|
78
|
+
path: this.path
|
|
79
|
+
},
|
|
80
|
+
utm_params: this.utmParams
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}]);
|
|
84
|
+
return Page;
|
|
85
|
+
}();
|
|
86
|
+
exports.Page = Page;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
2
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
|
|
3
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
4
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
5
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
6
|
+
import { UTM } from './utm';
|
|
7
|
+
var Page = /*#__PURE__*/function () {
|
|
8
|
+
function Page() {
|
|
9
|
+
var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
|
|
10
|
+
_classCallCheck(this, Page);
|
|
11
|
+
this.utm = new UTM();
|
|
12
|
+
this._url = url;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get the current page URL
|
|
17
|
+
* @returns {string} The page URL
|
|
18
|
+
*/
|
|
19
|
+
_createClass(Page, [{
|
|
20
|
+
key: "url",
|
|
21
|
+
get: function get() {
|
|
22
|
+
return this._url || window.location.href;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get the current page title
|
|
27
|
+
* @returns {string} The page title
|
|
28
|
+
*/
|
|
29
|
+
}, {
|
|
30
|
+
key: "title",
|
|
31
|
+
get: function get() {
|
|
32
|
+
return document.title;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get the current page path
|
|
37
|
+
* @returns {string} The page path
|
|
38
|
+
*/
|
|
39
|
+
}, {
|
|
40
|
+
key: "path",
|
|
41
|
+
get: function get() {
|
|
42
|
+
if (this._url) {
|
|
43
|
+
try {
|
|
44
|
+
return new URL(this._url).pathname;
|
|
45
|
+
} catch (e) {
|
|
46
|
+
return '/';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return window.location.pathname;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get current UTM parameters
|
|
54
|
+
* @returns {Object} The UTM parameters
|
|
55
|
+
*/
|
|
56
|
+
}, {
|
|
57
|
+
key: "utmParams",
|
|
58
|
+
get: function get() {
|
|
59
|
+
return this.utm.current;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get page data for tracking
|
|
64
|
+
* @returns {Object} Object containing page object and utm_params
|
|
65
|
+
*/
|
|
66
|
+
}, {
|
|
67
|
+
key: "trackingData",
|
|
68
|
+
get: function get() {
|
|
69
|
+
return {
|
|
70
|
+
page: {
|
|
71
|
+
url: this.url,
|
|
72
|
+
title: this.title,
|
|
73
|
+
path: this.path
|
|
74
|
+
},
|
|
75
|
+
utm_params: this.utmParams
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}]);
|
|
79
|
+
return Page;
|
|
80
|
+
}();
|
|
81
|
+
export { Page };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.UTM = void 0;
|
|
7
|
+
var _cookies = require("./cookies");
|
|
8
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
9
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
|
|
10
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
11
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
12
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
13
|
+
let UTM = /*#__PURE__*/function () {
|
|
14
|
+
function UTM() {
|
|
15
|
+
_classCallCheck(this, UTM);
|
|
16
|
+
const urlSearchParams = new URLSearchParams(window.location.search);
|
|
17
|
+
const utmsFromUrl = {
|
|
18
|
+
source: urlSearchParams.get('utm_source'),
|
|
19
|
+
medium: urlSearchParams.get('utm_medium'),
|
|
20
|
+
campaign: urlSearchParams.get('utm_campaign'),
|
|
21
|
+
term: urlSearchParams.get('utm_term'),
|
|
22
|
+
content: urlSearchParams.get('utm_content')
|
|
23
|
+
};
|
|
24
|
+
if (utmsFromUrl.source && utmsFromUrl.medium) {
|
|
25
|
+
const cleanUtms = Object.fromEntries(Object.entries(utmsFromUrl).filter(([_, value]) => value));
|
|
26
|
+
_cookies.Cookies.set('hello_utm', JSON.stringify(cleanUtms));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
_createClass(UTM, [{
|
|
30
|
+
key: "current",
|
|
31
|
+
get: function () {
|
|
32
|
+
try {
|
|
33
|
+
return JSON.parse(_cookies.Cookies.get('hello_utm')) || {};
|
|
34
|
+
} catch (e) {
|
|
35
|
+
return {};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}]);
|
|
39
|
+
return UTM;
|
|
40
|
+
}();
|
|
41
|
+
exports.UTM = UTM;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
2
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
|
|
3
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
4
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
5
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
6
|
+
import { Cookies } from './cookies';
|
|
7
|
+
var UTM = /*#__PURE__*/function () {
|
|
8
|
+
function UTM() {
|
|
9
|
+
_classCallCheck(this, UTM);
|
|
10
|
+
var urlSearchParams = new URLSearchParams(window.location.search);
|
|
11
|
+
var utmsFromUrl = {
|
|
12
|
+
source: urlSearchParams.get('utm_source'),
|
|
13
|
+
medium: urlSearchParams.get('utm_medium'),
|
|
14
|
+
campaign: urlSearchParams.get('utm_campaign'),
|
|
15
|
+
term: urlSearchParams.get('utm_term'),
|
|
16
|
+
content: urlSearchParams.get('utm_content')
|
|
17
|
+
};
|
|
18
|
+
if (utmsFromUrl.source && utmsFromUrl.medium) {
|
|
19
|
+
var cleanUtms = Object.fromEntries(Object.entries(utmsFromUrl).filter(_ref => {
|
|
20
|
+
var [_, value] = _ref;
|
|
21
|
+
return value;
|
|
22
|
+
}));
|
|
23
|
+
Cookies.set('hello_utm', JSON.stringify(cleanUtms));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
_createClass(UTM, [{
|
|
27
|
+
key: "current",
|
|
28
|
+
get: function get() {
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(Cookies.get('hello_utm')) || {};
|
|
31
|
+
} catch (e) {
|
|
32
|
+
return {};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}]);
|
|
36
|
+
return UTM;
|
|
37
|
+
}();
|
|
38
|
+
export { UTM };
|
package/package.json
CHANGED
|
@@ -386,11 +386,7 @@ export default class extends Controller {
|
|
|
386
386
|
})
|
|
387
387
|
}
|
|
388
388
|
|
|
389
|
-
|
|
390
|
-
if (this.typingIndicatorVisible) {
|
|
391
|
-
this.clearTypingIndicator()
|
|
392
|
-
}
|
|
393
|
-
|
|
389
|
+
this.clearTypingIndicator()
|
|
394
390
|
this.messagesContainerTarget.appendChild(element)
|
|
395
391
|
|
|
396
392
|
Hellotext.eventEmitter.dispatch('webchat:message:received', {
|
|
@@ -502,9 +498,21 @@ export default class extends Controller {
|
|
|
502
498
|
|
|
503
499
|
this.inputTarget.focus()
|
|
504
500
|
|
|
501
|
+
// Set up optimistic typing indicator BEFORE making the API call
|
|
502
|
+
// This prevents race conditions with server responses
|
|
503
|
+
if (!this.typingIndicatorVisible) {
|
|
504
|
+
clearTimeout(this.optimisticTypingTimeout)
|
|
505
|
+
this.optimisticTypingTimeout = setTimeout(() => {
|
|
506
|
+
this.showOptimisticTypingIndicator()
|
|
507
|
+
}, this.optimisticTypingIndicatorWaitValue)
|
|
508
|
+
}
|
|
509
|
+
|
|
505
510
|
const response = await this.messagesAPI.create(formData)
|
|
506
511
|
|
|
507
512
|
if (response.failed) {
|
|
513
|
+
// Clear the optimistic typing indicator on failure
|
|
514
|
+
clearTimeout(this.optimisticTypingTimeout)
|
|
515
|
+
|
|
508
516
|
this.broadcastChannel.postMessage({
|
|
509
517
|
type: 'message:failed',
|
|
510
518
|
id: element.id,
|
|
@@ -524,13 +532,9 @@ export default class extends Controller {
|
|
|
524
532
|
this.webChatChannel.updateSubscriptionWith(this.conversationIdValue)
|
|
525
533
|
}
|
|
526
534
|
|
|
535
|
+
// If there's already a typing indicator visible, reset its timer
|
|
527
536
|
if (this.typingIndicatorVisible) {
|
|
528
537
|
this.resetTypingIndicatorTimer()
|
|
529
|
-
} else {
|
|
530
|
-
clearTimeout(this.optimisticTypingTimeout)
|
|
531
|
-
this.optimisticTypingTimeout = setTimeout(() => {
|
|
532
|
-
this.showOptimisticTypingIndicator()
|
|
533
|
-
}, this.optimisticTypingIndicatorWaitValue)
|
|
534
538
|
}
|
|
535
539
|
|
|
536
540
|
this.attachmentContainerTarget.style.display = ''
|
package/src/core/event.js
CHANGED
package/src/hellotext.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Configuration, Event } from './core'
|
|
2
2
|
|
|
3
3
|
import API, { Response } from './api'
|
|
4
|
-
import { Business, FormCollection, Query, Session, Webchat } from './models'
|
|
4
|
+
import { Business, FormCollection, Page, Query, Session, Webchat } from './models'
|
|
5
5
|
|
|
6
6
|
import { NotInitializedError } from './errors'
|
|
7
7
|
|
|
@@ -23,6 +23,7 @@ class Hellotext {
|
|
|
23
23
|
Configuration.assign(config)
|
|
24
24
|
Session.initialize()
|
|
25
25
|
|
|
26
|
+
this.page = new Page()
|
|
26
27
|
this.business = new Business(business)
|
|
27
28
|
this.forms = new FormCollection()
|
|
28
29
|
|
|
@@ -54,11 +55,13 @@ class Hellotext {
|
|
|
54
55
|
...this.headers,
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
const pageInstance = params && params.url ? new Page(params.url) : this.page
|
|
59
|
+
|
|
57
60
|
const body = {
|
|
58
61
|
session: this.session,
|
|
59
62
|
action,
|
|
60
63
|
...params,
|
|
61
|
-
|
|
64
|
+
...pageInstance.trackingData,
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
delete body.headers
|
package/src/models/cookies.js
CHANGED
|
@@ -2,17 +2,23 @@ import Hellotext from '../hellotext'
|
|
|
2
2
|
|
|
3
3
|
class Cookies {
|
|
4
4
|
static set(name, value) {
|
|
5
|
-
if(typeof document !== 'undefined') {
|
|
5
|
+
if (typeof document !== 'undefined') {
|
|
6
6
|
document.cookie = `${name}=${value}; path=/;`
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
if (name === 'hello_session') {
|
|
10
|
+
Hellotext.eventEmitter.dispatch('session-set', value)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (name === 'hello_utm') {
|
|
14
|
+
Hellotext.eventEmitter.dispatch('utm-set', value)
|
|
15
|
+
}
|
|
10
16
|
|
|
11
17
|
return value
|
|
12
18
|
}
|
|
13
19
|
|
|
14
20
|
static get(name) {
|
|
15
|
-
if(typeof document !== 'undefined') {
|
|
21
|
+
if (typeof document !== 'undefined') {
|
|
16
22
|
return document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')?.pop()
|
|
17
23
|
} else {
|
|
18
24
|
return undefined
|
package/src/models/index.js
CHANGED
|
@@ -2,6 +2,8 @@ export { Business } from './business'
|
|
|
2
2
|
export { Cookies } from './cookies'
|
|
3
3
|
export { Form } from './form'
|
|
4
4
|
export { FormCollection } from './form_collection'
|
|
5
|
+
export { Page } from './page'
|
|
5
6
|
export { Query } from './query'
|
|
6
7
|
export { Session } from './session'
|
|
8
|
+
export { UTM } from './utm'
|
|
7
9
|
export { Webchat } from './webchat'
|