@hellotext/hellotext 2.1.2 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/hellotext.js +1 -1
  2. package/lib/api/forms.cjs +2 -1
  3. package/lib/api/forms.js +2 -1
  4. package/lib/api/webchat/messages.cjs +4 -3
  5. package/lib/api/webchat/messages.js +4 -2
  6. package/lib/api/webchats.cjs +2 -0
  7. package/lib/api/webchats.js +3 -1
  8. package/lib/builders/logo_builder.cjs +1 -1
  9. package/lib/builders/logo_builder.js +1 -1
  10. package/lib/channels/application_channel.cjs +9 -6
  11. package/lib/channels/application_channel.js +9 -6
  12. package/lib/channels/webchat_channel.cjs +42 -17
  13. package/lib/channels/webchat_channel.js +42 -17
  14. package/lib/controllers/webchat/emoji_picker_controller.cjs +6 -6
  15. package/lib/controllers/webchat/emoji_picker_controller.js +5 -14
  16. package/lib/controllers/webchat_controller.cjs +174 -47
  17. package/lib/controllers/webchat_controller.js +175 -48
  18. package/lib/core/configuration/locale.cjs +87 -0
  19. package/lib/core/configuration/locale.js +81 -0
  20. package/lib/core/configuration.cjs +11 -0
  21. package/lib/core/configuration.js +11 -0
  22. package/lib/core/index.cjs +15 -1
  23. package/lib/core/index.js +4 -2
  24. package/lib/locales/en.cjs +1 -1
  25. package/lib/locales/en.js +1 -1
  26. package/lib/locales/es.cjs +1 -1
  27. package/lib/locales/es.js +1 -1
  28. package/lib/models/business.cjs +11 -0
  29. package/lib/models/business.js +11 -0
  30. package/lib/models/form_collection.cjs +1 -0
  31. package/lib/models/form_collection.js +2 -1
  32. package/lib/models/index.cjs +4 -4
  33. package/lib/models/index.js +4 -4
  34. package/lib/models/query.cjs +1 -2
  35. package/lib/models/query.js +1 -2
  36. package/lib/models/session.cjs +1 -1
  37. package/lib/models/session.js +1 -1
  38. package/package.json +2 -1
  39. package/src/api/forms.js +3 -1
  40. package/src/api/webchat/messages.js +8 -6
  41. package/src/api/webchats.js +3 -1
  42. package/src/builders/logo_builder.js +1 -1
  43. package/src/channels/application_channel.js +12 -9
  44. package/src/channels/webchat_channel.js +33 -19
  45. package/src/controllers/webchat/emoji_picker_controller.js +9 -15
  46. package/src/controllers/webchat_controller.js +164 -43
  47. package/src/core/configuration/locale.js +50 -0
  48. package/src/core/configuration.js +11 -0
  49. package/src/core/index.js +3 -1
  50. package/src/locales/en.js +4 -4
  51. package/src/locales/es.js +4 -4
  52. package/src/models/business.js +12 -0
  53. package/src/models/form_collection.js +2 -1
  54. package/src/models/index.js +3 -3
  55. package/src/models/query.js +1 -3
  56. package/src/models/session.js +1 -1
package/lib/locales/es.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  white_label: {
3
- powered_by: 'Desarrollado por'
3
+ powered_by: 'Por'
4
4
  },
5
5
  errors: {
6
6
  parameter_not_unique: 'Este valor ya está en uso.',
@@ -43,6 +43,17 @@ let Business = /*#__PURE__*/function () {
43
43
  get: function () {
44
44
  return this.data.whitelist !== 'disabled';
45
45
  }
46
+ }, {
47
+ key: "setLocale",
48
+ value: function setLocale(locale) {
49
+ if (!_locales.default[locale]) {
50
+ return console.warn(`Locale ${locale} not found`);
51
+ }
52
+ if (!this.data) {
53
+ this.data = {};
54
+ }
55
+ this.data.locale = locale;
56
+ }
46
57
  }, {
47
58
  key: "locale",
48
59
  get: function () {
@@ -36,6 +36,17 @@ var Business = /*#__PURE__*/function () {
36
36
  get: function get() {
37
37
  return this.data.whitelist !== 'disabled';
38
38
  }
39
+ }, {
40
+ key: "setLocale",
41
+ value: function setLocale(locale) {
42
+ if (!locales[locale]) {
43
+ return console.warn("Locale ".concat(locale, " not found"));
44
+ }
45
+ if (!this.data) {
46
+ this.data = {};
47
+ }
48
+ this.data.locale = locale;
49
+ }
39
50
  }, {
40
51
  key: "locale",
41
52
  get: function get() {
@@ -91,6 +91,7 @@ let FormCollection = /*#__PURE__*/function () {
91
91
  if (this.includes(data.id)) return;
92
92
  if (!_hellotext.default.business.data) {
93
93
  _hellotext.default.business.setData(data.business);
94
+ _hellotext.default.business.setLocale(_core.Locale.toString());
94
95
  }
95
96
  if (!_hellotext.default.business.enabledWhitelist) {
96
97
  console.warn('No whitelist has been configured. It is advised to whitelist the domain to avoid bots from submitting forms.');
@@ -10,7 +10,7 @@ var id = 0;
10
10
  function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
11
11
  import API from '../api/forms';
12
12
  import Hellotext from '../hellotext';
13
- import { Configuration } from '../core';
13
+ import { Configuration, Locale } from '../core';
14
14
  import { Form } from './form';
15
15
  import { NotInitializedError } from '../errors';
16
16
  var _formIdsToFetch = /*#__PURE__*/_classPrivateFieldLooseKey("formIdsToFetch");
@@ -92,6 +92,7 @@ var FormCollection = /*#__PURE__*/function () {
92
92
  if (this.includes(data.id)) return;
93
93
  if (!Hellotext.business.data) {
94
94
  Hellotext.business.setData(data.business);
95
+ Hellotext.business.setLocale(Locale.toString());
95
96
  }
96
97
  if (!Hellotext.business.enabledWhitelist) {
97
98
  console.warn('No whitelist has been configured. It is advised to whitelist the domain to avoid bots from submitting forms.');
@@ -46,9 +46,9 @@ Object.defineProperty(exports, "Webchat", {
46
46
  }
47
47
  });
48
48
  var _business = require("./business");
49
- var _form = require("./form");
50
- var _query = require("./query");
51
49
  var _cookies = require("./cookies");
50
+ var _form = require("./form");
52
51
  var _form_collection = require("./form_collection");
53
- var _webchat = require("./webchat");
54
- var _session = require("./session");
52
+ var _query = require("./query");
53
+ var _session = require("./session");
54
+ var _webchat = require("./webchat");
@@ -1,7 +1,7 @@
1
1
  export { Business } from './business';
2
- export { Form } from './form';
3
- export { Query } from './query';
4
2
  export { Cookies } from './cookies';
3
+ export { Form } from './form';
5
4
  export { FormCollection } from './form_collection';
6
- export { Webchat } from './webchat';
7
- export { Session } from './session';
5
+ export { Query } from './query';
6
+ export { Session } from './session';
7
+ export { Webchat } from './webchat';
@@ -4,7 +4,6 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.Query = void 0;
7
- var _cookies = require("./cookies");
8
7
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
9
8
  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
9
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
@@ -33,7 +32,7 @@ let Query = /*#__PURE__*/function () {
33
32
  }, {
34
33
  key: "session",
35
34
  get: function () {
36
- return this.get('session') || _cookies.Cookies.get('hello_session');
35
+ return this.get('session');
37
36
  }
38
37
  }, {
39
38
  key: "toHellotextParam",
@@ -3,7 +3,6 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+
3
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
4
  function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
5
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
6
  var Query = /*#__PURE__*/function () {
8
7
  function Query() {
9
8
  _classCallCheck(this, Query);
@@ -27,7 +26,7 @@ var Query = /*#__PURE__*/function () {
27
26
  }, {
28
27
  key: "session",
29
28
  get: function get() {
30
- return this.get('session') || Cookies.get('hello_session');
29
+ return this.get('session');
31
30
  }
32
31
  }, {
33
32
  key: "toHellotextParam",
@@ -34,7 +34,7 @@ let Session = /*#__PURE__*/function () {
34
34
  key: "initialize",
35
35
  value: function initialize() {
36
36
  _classPrivateFieldLooseBase(this, _query)[_query] = new _query2.Query();
37
- this.session = _core.Configuration.session || _classPrivateFieldLooseBase(this, _query)[_query].session || _cookies.Cookies.get('hello_session');
37
+ this.session = _classPrivateFieldLooseBase(this, _query)[_query].session || _core.Configuration.session || _cookies.Cookies.get('hello_session');
38
38
  if (!this.session && _core.Configuration.autoGenerateSession) {
39
39
  this.session = crypto.randomUUID();
40
40
  }
@@ -28,7 +28,7 @@ var Session = /*#__PURE__*/function () {
28
28
  key: "initialize",
29
29
  value: function initialize() {
30
30
  _classPrivateFieldLooseBase(this, _query)[_query] = new Query();
31
- this.session = Configuration.session || _classPrivateFieldLooseBase(this, _query)[_query].session || Cookies.get('hello_session');
31
+ this.session = _classPrivateFieldLooseBase(this, _query)[_query].session || Configuration.session || Cookies.get('hello_session');
32
32
  if (!this.session && Configuration.autoGenerateSession) {
33
33
  this.session = crypto.randomUUID();
34
34
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hellotext/hellotext",
3
- "version": "2.1.2",
3
+ "version": "2.1.4",
4
4
  "description": "Hellotext JavaScript Client",
5
5
  "source": "src/index.js",
6
6
  "main": "lib/index.cjs",
@@ -91,6 +91,7 @@
91
91
  "url": "https://github.com/hellotext/hellotext.js/issues"
92
92
  },
93
93
  "dependencies": {
94
+ "@emoji-mart/data": "^1.2.1",
94
95
  "@floating-ui/dom": "^1.7.3",
95
96
  "@hotwired/stimulus": "^3.0.0",
96
97
  "emoji-mart": "^5.6.0"
package/src/api/forms.js CHANGED
@@ -1,5 +1,5 @@
1
+ import { Configuration, Locale } from '../core'
1
2
  import Hellotext from '../hellotext'
2
- import { Configuration } from '../core'
3
3
 
4
4
  import { Response } from './response'
5
5
 
@@ -10,7 +10,9 @@ export default class FormsAPI {
10
10
 
11
11
  static async get(id) {
12
12
  const url = new URL(`${this.endpoint}/${id}`)
13
+
13
14
  url.searchParams.append('session', Hellotext.session)
15
+ url.searchParams.append('locale', Locale.toString())
14
16
 
15
17
  return fetch(url, {
16
18
  method: 'GET',
@@ -1,5 +1,5 @@
1
- import Hellotext from '../../hellotext'
2
1
  import { Configuration } from '../../core'
2
+ import Hellotext from '../../hellotext'
3
3
 
4
4
  import { Response } from '../response'
5
5
 
@@ -31,19 +31,21 @@ class WebchatMessagesAPI {
31
31
  headers: {
32
32
  Authorization: `Bearer ${Hellotext.business.id}`,
33
33
  },
34
- body: formData
34
+ body: formData,
35
35
  })
36
36
 
37
37
  return new Response(response.ok, response)
38
38
  }
39
39
 
40
- markAsSeen() {
41
- fetch(this.url + '/seen', {
40
+ markAsSeen(messageId = null) {
41
+ const url = messageId ? this.url + `/${messageId}` : this.url + '/seen'
42
+
43
+ fetch(url, {
42
44
  method: 'PATCH',
43
45
  headers: Hellotext.headers,
44
46
  body: JSON.stringify({
45
- session: Hellotext.session
46
- })
47
+ session: Hellotext.session,
48
+ }),
47
49
  })
48
50
  }
49
51
 
@@ -1,4 +1,4 @@
1
- import { Configuration } from '../core'
1
+ import { Configuration, Locale } from '../core'
2
2
  import Hellotext from '../hellotext'
3
3
 
4
4
  class WebchatsAPI {
@@ -10,6 +10,7 @@ class WebchatsAPI {
10
10
  const url = new URL(`${this.endpoint}/${id}`)
11
11
 
12
12
  url.searchParams.append('session', Hellotext.session)
13
+ url.searchParams.append('locale', Locale.toString())
13
14
 
14
15
  Object.entries(Configuration.webchat.style).forEach(([key, value]) => {
15
16
  url.searchParams.append(`style[${key}]`, value)
@@ -26,6 +27,7 @@ class WebchatsAPI {
26
27
 
27
28
  if (!Hellotext.business.data) {
28
29
  Hellotext.business.setData(data.business)
30
+ Hellotext.business.setLocale(data.locale)
29
31
  }
30
32
 
31
33
  return new DOMParser().parseFromString(data.html, 'text/html').querySelector('article')
@@ -14,7 +14,7 @@ class LogoBuilder {
14
14
  return `
15
15
  <div data-logo-container>
16
16
  <small>${Hellotext.business.locale.white_label.powered_by}</small>
17
-
17
+
18
18
  <a href="${url}" rel="noreferrer" target="_blank">
19
19
  <svg data-hello-brand viewBox="0 0 224 43" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
20
20
  <title>Hellotext</title>
@@ -1,28 +1,31 @@
1
+ import { Configuration } from '../core'
2
+
1
3
  class ApplicationChannel {
2
- static webSocket;
4
+ static webSocket
3
5
 
4
- send({ command, identifier }) {
5
- const data = {
6
+ send({ command, identifier, data }) {
7
+ const payload = {
6
8
  command,
7
- identifier: JSON.stringify(identifier)
9
+ identifier: JSON.stringify(identifier),
10
+ data: JSON.stringify(data || {}),
8
11
  }
9
12
 
10
13
  if (this.webSocket.readyState === WebSocket.OPEN) {
11
- this.webSocket.send(JSON.stringify(data))
14
+ this.webSocket.send(JSON.stringify(payload))
12
15
  } else {
13
16
  this.webSocket.addEventListener('open', () => {
14
- this.webSocket.send(JSON.stringify(data))
17
+ this.webSocket.send(JSON.stringify(payload))
15
18
  })
16
19
  }
17
20
  }
18
21
 
19
22
  onMessage(callback) {
20
- this.webSocket.addEventListener('message', (event) => {
23
+ this.webSocket.addEventListener('message', event => {
21
24
  const data = JSON.parse(event.data)
22
25
  const { type, message } = data
23
26
 
24
27
  if (this.ignoredEvents.includes(type)) {
25
- return;
28
+ return
26
29
  }
27
30
 
28
31
  callback(message)
@@ -31,7 +34,7 @@ class ApplicationChannel {
31
34
 
32
35
  get webSocket() {
33
36
  if (!ApplicationChannel.webSocket) {
34
- return ApplicationChannel.webSocket = new WebSocket("wss://www.hellotext.com/cable")
37
+ return (ApplicationChannel.webSocket = new WebSocket(Configuration.actionCableUrl))
35
38
  }
36
39
 
37
40
  return ApplicationChannel.webSocket
@@ -13,18 +13,18 @@ class WebchatChannel extends ApplicationChannel {
13
13
 
14
14
  subscribe() {
15
15
  const params = {
16
- channel: "WebchatChannel",
16
+ channel: 'WebchatChannel',
17
17
  id: this.id,
18
18
  session: this.session,
19
19
  conversation: this.conversation,
20
20
  }
21
21
 
22
- this.send( { command: 'subscribe', identifier: params })
22
+ this.send({ command: 'subscribe', identifier: params })
23
23
  }
24
24
 
25
25
  unsubscribe() {
26
26
  const params = {
27
- channel: "WebchatChannel",
27
+ channel: 'WebchatChannel',
28
28
  id: this.id,
29
29
  session: this.session,
30
30
  conversation: this.conversation,
@@ -33,32 +33,46 @@ class WebchatChannel extends ApplicationChannel {
33
33
  this.send({ command: 'unsubscribe', identifier: params })
34
34
  }
35
35
 
36
- onMessage(callback) {
37
- super.onMessage((message) => {
38
- if(message.type !== 'message') return
39
- callback(message)
40
- })
36
+ startTypingIndicator() {
37
+ const params = {
38
+ channel: 'WebchatChannel',
39
+ id: this.id,
40
+ session: this.session,
41
+ conversation: this.conversation,
42
+ }
43
+
44
+ this.send({ command: 'message', identifier: params, data: { action: 'started_typing' } })
41
45
  }
42
46
 
43
- onConversationAssignment(callback) {
44
- super.onMessage((message) => {
45
- if(message.type === 'conversation.assigned') {
46
- callback(message)
47
- }
47
+ stopTypingIndicator() {
48
+ const params = {
49
+ channel: 'WebchatChannel',
50
+ id: this.id,
51
+ session: this.session,
52
+ conversation: this.conversation,
53
+ }
54
+
55
+ this.send({ command: 'typing:stop', identifier: params, data: { action: 'stopped_typing' } })
56
+ }
57
+
58
+ onMessage(callback) {
59
+ super.onMessage(message => {
60
+ if (message.type !== 'message') return
61
+ callback(message)
48
62
  })
49
63
  }
50
64
 
51
- onAgentOnline(callback) {
52
- super.onMessage((message) => {
53
- if(message.type === 'agent_is_online') {
65
+ onReaction(callback) {
66
+ super.onMessage(message => {
67
+ if (message.type === 'reaction.create' || message.type === 'reaction.destroy') {
54
68
  callback(message)
55
69
  }
56
70
  })
57
71
  }
58
72
 
59
- onReaction(callback) {
60
- super.onMessage((message) => {
61
- if(message.type === 'reaction.create' || message.type === 'reaction.destroy') {
73
+ onTypingStart(callback) {
74
+ super.onMessage(message => {
75
+ if (message.type === 'started_typing') {
62
76
  callback(message)
63
77
  }
64
78
  })
@@ -1,23 +1,23 @@
1
+ import { autoPlacement, offset, shift } from '@floating-ui/dom'
1
2
  import { Controller } from '@hotwired/stimulus'
2
- import { computePosition, autoUpdate, shift, autoPlacement, offset } from '@floating-ui/dom'
3
+
4
+ import en from '@emoji-mart/data/i18n/en.json'
5
+ import es from '@emoji-mart/data/i18n/es.json'
3
6
 
4
7
  import { Picker } from 'emoji-mart'
5
8
 
6
9
  import { usePopover } from '../mixins/usePopover'
7
10
 
8
11
  export default class extends Controller {
9
- static targets = [
10
- 'button',
11
- 'popover',
12
- ]
12
+ static targets = ['button', 'popover']
13
13
 
14
14
  static values = {
15
- placement: { type: String, default: "bottom-end" },
15
+ placement: { type: String, default: 'bottom-end' },
16
16
  open: { type: Boolean, default: false },
17
17
  autoPlacement: { type: Boolean, default: false },
18
18
  disabled: { type: Boolean, default: false },
19
19
  size: { type: Number, default: 24 },
20
- perLine: { type: Number, default: 9 }
20
+ perLine: { type: Number, default: 9 },
21
21
  }
22
22
 
23
23
  initialize() {
@@ -62,13 +62,7 @@ export default class extends Controller {
62
62
  skinTonePosition: 'none',
63
63
  emojiSize: this.sizeValue,
64
64
  perLine: this.perLineValue,
65
- data: async () => {
66
- const response = await fetch(
67
- 'https://cdn.jsdelivr.net/npm/@emoji-mart/data',
68
- )
69
-
70
- return response.json()
71
- }
65
+ i18n: Hellotext.business.locale === 'es' ? es : en,
72
66
  })
73
67
  }
74
68
 
@@ -76,7 +70,7 @@ export default class extends Controller {
76
70
  return [
77
71
  offset(5),
78
72
  shift({ padding: 24 }),
79
- autoPlacement({ allowedPlacements: ['top', 'bottom' ]}),
73
+ autoPlacement({ allowedPlacements: ['top', 'bottom'] }),
80
74
  ]
81
75
  }
82
76
  }