@hellotext/hellotext 1.7.0 → 1.7.2
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 -1
- package/__tests__/models/form_collection_test.js +1 -1
- package/dist/hellotext.js +1 -1
- package/docs/forms.md +17 -4
- package/lib/controllers/form_controller.js +19 -14
- package/lib/hellotext.js +3 -8
- package/lib/index.js +0 -2
- package/lib/locales/en.js +4 -10
- package/lib/locales/es.js +4 -10
- package/lib/models/form.js +0 -3
- package/package.json +1 -1
- package/src/controllers/form_controller.js +21 -17
- package/src/hellotext.js +4 -4
- package/src/index.js +0 -2
- package/src/locales/en.js +4 -10
- package/src/locales/es.js +4 -10
- package/src/models/form.js +0 -4
- package/styles/index.css +2 -0
- package/alpha.html +0 -23
- package/lib/builders/otp_builder.js +0 -39
- package/lib/controllers/otp_controller.js +0 -139
- package/src/builders/otp_builder.js +0 -46
- package/src/controllers/otp_controller.js +0 -101
package/docs/forms.md
CHANGED
|
@@ -79,15 +79,28 @@ This will mount the form regardless if the user has completed the form or not.
|
|
|
79
79
|
|
|
80
80
|
Hellotext automatically validates the form inputs based on how they were configured on the dashboard
|
|
81
81
|
using browser's native [checkValidity()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement/checkValidity).
|
|
82
|
+
|
|
82
83
|
Once the user tries to submit the form and there are missing required fields,
|
|
83
84
|
the submission is halted and we display default browser's error message using [HTMLObjectElement.validationMessage](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validationMessage) property.
|
|
84
85
|
|
|
85
|
-
|
|
86
|
+
If the form contains a unique property and the client enters a value that is already taken,
|
|
87
|
+
the submission will not be complete. Instead, an error will be reported to the client and the form will not be submitted.
|
|
88
|
+
|
|
89
|
+
Uniqueness errors use the browser's native [setCustomValidity()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity)
|
|
90
|
+
method which are reported as normal form validation errors, they can be styled with the `input:invalid` selector.
|
|
91
|
+
|
|
92
|
+
### Understanding Verification
|
|
86
93
|
|
|
87
94
|
Hellotext protects you from bot submissions and protects your customers from identity theft and impersonation.
|
|
88
|
-
|
|
89
|
-
an email
|
|
90
|
-
|
|
95
|
+
|
|
96
|
+
When a subscriber fills the form with an email and/or phone number, Hellotext sends a verification link to the value the submission had at the time of creation.
|
|
97
|
+
When the customer clicks the link in their email and/or the SMS they receive, the attribute is verified.
|
|
98
|
+
Once the email/phone number were verified, the data is considered to be _verified_.
|
|
99
|
+
|
|
100
|
+
Once verification of a submission is complete, Hellotext performs an automatic merge (if needed) of all profiles
|
|
101
|
+
that have the same email and/or phone number. After automatic merging, if a property has multiple values,
|
|
102
|
+
it will be visible in the Audience page and the user can see the values that were merged and they can decide which one
|
|
103
|
+
to ignore and which one to accept.
|
|
91
104
|
|
|
92
105
|
### Form Completion
|
|
93
106
|
|
|
@@ -8,7 +8,6 @@ var _stimulus = require("@hotwired/stimulus");
|
|
|
8
8
|
var _hellotext = _interopRequireDefault(require("../hellotext"));
|
|
9
9
|
var _models = require("../models");
|
|
10
10
|
var _forms = _interopRequireDefault(require("../api/forms"));
|
|
11
|
-
var _otp_builder = require("../builders/otp_builder");
|
|
12
11
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
12
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
14
13
|
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
@@ -60,30 +59,35 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
60
59
|
this.buttonTarget.disabled = true;
|
|
61
60
|
var response = yield _forms.default.submit(this.form.id, this.formData);
|
|
62
61
|
this.buttonTarget.disabled = false;
|
|
62
|
+
var data = yield response.json();
|
|
63
63
|
if (response.failed) {
|
|
64
|
-
|
|
64
|
+
data.errors.forEach(error => {
|
|
65
|
+
var {
|
|
66
|
+
type,
|
|
67
|
+
parameter
|
|
68
|
+
} = error;
|
|
69
|
+
var input = this.inputTargets.find(input => input.name === parameter);
|
|
70
|
+
input.setCustomValidity(_hellotext.default.business.locale.errors[type]);
|
|
71
|
+
input.reportValidity();
|
|
72
|
+
input.addEventListener('input', () => {
|
|
73
|
+
input.setCustomValidity('');
|
|
74
|
+
input.reportValidity();
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
return this.showErrorMessages();
|
|
65
78
|
}
|
|
66
79
|
this.buttonTarget.style.display = 'none';
|
|
67
80
|
this.element.querySelectorAll('input').forEach(input => input.disabled = true);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
this.completed();
|
|
71
|
-
} else {
|
|
72
|
-
_hellotext.default.setSession(submission.session);
|
|
73
|
-
this.revealOTPContainer(submission.id);
|
|
81
|
+
if (!data.identified) {
|
|
82
|
+
_hellotext.default.setSession(data.session);
|
|
74
83
|
}
|
|
84
|
+
this.completed();
|
|
75
85
|
});
|
|
76
86
|
function submit(_x) {
|
|
77
87
|
return _submit.apply(this, arguments);
|
|
78
88
|
}
|
|
79
89
|
return submit;
|
|
80
90
|
}()
|
|
81
|
-
}, {
|
|
82
|
-
key: "revealOTPContainer",
|
|
83
|
-
value: function revealOTPContainer(submissionId) {
|
|
84
|
-
var paragraph = this.requiredInputs.find(input => input.name === 'email') ? _hellotext.default.business.locale.otp.sent_to_email : _hellotext.default.business.locale.otp.sent_to_phone;
|
|
85
|
-
this.element.appendChild(_otp_builder.OTPBuilder.build(submissionId, paragraph));
|
|
86
|
-
}
|
|
87
91
|
}, {
|
|
88
92
|
key: "completed",
|
|
89
93
|
value: function completed() {
|
|
@@ -104,6 +108,7 @@ var _default = /*#__PURE__*/function (_Controller) {
|
|
|
104
108
|
key: "clearErrorMessages",
|
|
105
109
|
value: function clearErrorMessages() {
|
|
106
110
|
this.element.querySelectorAll('input').forEach(input => {
|
|
111
|
+
input.setCustomValidity('');
|
|
107
112
|
var parent = input.closest('article');
|
|
108
113
|
parent.querySelector('[data-error-container]').innerText = '';
|
|
109
114
|
});
|
package/lib/hellotext.js
CHANGED
|
@@ -23,12 +23,11 @@ function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototy
|
|
|
23
23
|
var id = 0;
|
|
24
24
|
function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
|
|
25
25
|
var _session = /*#__PURE__*/_classPrivateFieldLooseKey("session");
|
|
26
|
-
var _config = /*#__PURE__*/_classPrivateFieldLooseKey("config");
|
|
27
26
|
var _query = /*#__PURE__*/_classPrivateFieldLooseKey("query");
|
|
28
27
|
var _mintAnonymousSession = /*#__PURE__*/_classPrivateFieldLooseKey("mintAnonymousSession");
|
|
29
28
|
/**
|
|
30
29
|
* @typedef {Object} Config
|
|
31
|
-
* @property {Boolean}
|
|
30
|
+
* @property {Boolean} autoGenerateSession
|
|
32
31
|
* @property {Boolean} autoMountForms
|
|
33
32
|
*/
|
|
34
33
|
var Hellotext = /*#__PURE__*/function () {
|
|
@@ -44,14 +43,14 @@ var Hellotext = /*#__PURE__*/function () {
|
|
|
44
43
|
* @param { Config } config
|
|
45
44
|
*/
|
|
46
45
|
function initialize(business, config) {
|
|
47
|
-
|
|
46
|
+
_core.Configuration.assign(config);
|
|
48
47
|
_classPrivateFieldLooseBase(this, _query)[_query] = new _models.Query();
|
|
49
48
|
this.business = new _models.Business(business);
|
|
50
49
|
this.forms = new _models.FormCollection();
|
|
51
50
|
if (_classPrivateFieldLooseBase(this, _query)[_query].inPreviewMode) return;
|
|
52
51
|
if (_classPrivateFieldLooseBase(this, _query)[_query].session) {
|
|
53
52
|
_classPrivateFieldLooseBase(this, _session)[_session] = _models.Cookies.set('hello_session', _classPrivateFieldLooseBase(this, _query)[_query].session);
|
|
54
|
-
} else if (
|
|
53
|
+
} else if (_core.Configuration.autoGenerateSession) {
|
|
55
54
|
_classPrivateFieldLooseBase(this, _mintAnonymousSession)[_mintAnonymousSession]().then(response => {
|
|
56
55
|
_classPrivateFieldLooseBase(this, _session)[_session] = _models.Cookies.set('hello_session', response.id);
|
|
57
56
|
});
|
|
@@ -178,10 +177,6 @@ Object.defineProperty(Hellotext, _session, {
|
|
|
178
177
|
writable: true,
|
|
179
178
|
value: void 0
|
|
180
179
|
});
|
|
181
|
-
Object.defineProperty(Hellotext, _config, {
|
|
182
|
-
writable: true,
|
|
183
|
-
value: void 0
|
|
184
|
-
});
|
|
185
180
|
Object.defineProperty(Hellotext, _query, {
|
|
186
181
|
writable: true,
|
|
187
182
|
value: void 0
|
package/lib/index.js
CHANGED
|
@@ -7,12 +7,10 @@ exports.default = void 0;
|
|
|
7
7
|
var _stimulus = require("@hotwired/stimulus");
|
|
8
8
|
var _hellotext = _interopRequireDefault(require("./hellotext"));
|
|
9
9
|
var _form_controller = _interopRequireDefault(require("./controllers/form_controller"));
|
|
10
|
-
var _otp_controller = _interopRequireDefault(require("./controllers/otp_controller"));
|
|
11
10
|
require("../styles/index.css");
|
|
12
11
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
12
|
var application = _stimulus.Application.start();
|
|
14
13
|
application.register('hellotext--form', _form_controller.default);
|
|
15
|
-
application.register('hellotext--otp', _otp_controller.default);
|
|
16
14
|
window.Hellotext = _hellotext.default;
|
|
17
15
|
var _default = _hellotext.default;
|
|
18
16
|
exports.default = _default;
|
package/lib/locales/en.js
CHANGED
|
@@ -5,18 +5,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _default = {
|
|
8
|
-
otp: {
|
|
9
|
-
sent_to_email: 'A One-Time Password has been sent to your email address',
|
|
10
|
-
sent_to_phone: 'An One-Time Password has been sent to your phone number',
|
|
11
|
-
resend_successful: 'The One-Time Password has been resent successfully',
|
|
12
|
-
invalid: 'Invalid One-Time Password',
|
|
13
|
-
resend: 'Resend verification code',
|
|
14
|
-
submit: 'Submit',
|
|
15
|
-
throttled: 'You have reached the maximum number of attempts. Please try again in 1 minute.',
|
|
16
|
-
placeholder: 'Enter the code here'
|
|
17
|
-
},
|
|
18
8
|
white_label: {
|
|
19
9
|
powered_by: 'Powered by'
|
|
10
|
+
},
|
|
11
|
+
errors: {
|
|
12
|
+
parameter_not_unique: 'This value is taken.',
|
|
13
|
+
blank: 'This field is required.'
|
|
20
14
|
}
|
|
21
15
|
};
|
|
22
16
|
exports.default = _default;
|
package/lib/locales/es.js
CHANGED
|
@@ -5,18 +5,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _default = {
|
|
8
|
-
otp: {
|
|
9
|
-
sent_to_email: 'Un código de un solo uso ha sido enviado a tu correo electrónico',
|
|
10
|
-
sent_to_phone: 'Un código de un solo uso ha sido enviado a tu número de teléfono',
|
|
11
|
-
resend_successful: 'El código de un solo uso ha sido reenviado exitosamente',
|
|
12
|
-
invalid: 'Código de un solo uso inválido',
|
|
13
|
-
resend: 'Reenviar código de verificación',
|
|
14
|
-
submit: 'Enviar',
|
|
15
|
-
throttled: 'Has alcanzado el número máximo de intentos. Por favor intenta de nuevo en 1 minuto.',
|
|
16
|
-
placeholder: 'Ingresa el código aquí'
|
|
17
|
-
},
|
|
18
8
|
white_label: {
|
|
19
9
|
powered_by: 'Desarrollado por'
|
|
10
|
+
},
|
|
11
|
+
errors: {
|
|
12
|
+
parameter_not_unique: 'Este valor ya está en uso.',
|
|
13
|
+
blank: 'Este campo es obligatorio.'
|
|
20
14
|
}
|
|
21
15
|
};
|
|
22
16
|
exports.default = _default;
|
package/lib/models/form.js
CHANGED
package/package.json
CHANGED
|
@@ -5,8 +5,6 @@ import { Form } from '../models'
|
|
|
5
5
|
|
|
6
6
|
import FormsAPI from '../api/forms'
|
|
7
7
|
|
|
8
|
-
import { OTPBuilder } from '../builders/otp_builder'
|
|
9
|
-
|
|
10
8
|
export default class extends Controller {
|
|
11
9
|
static values = {
|
|
12
10
|
data: Object,
|
|
@@ -43,29 +41,34 @@ export default class extends Controller {
|
|
|
43
41
|
const response = await FormsAPI.submit(this.form.id, this.formData)
|
|
44
42
|
this.buttonTarget.disabled = false
|
|
45
43
|
|
|
44
|
+
const data = await response.json()
|
|
45
|
+
|
|
46
46
|
if (response.failed) {
|
|
47
|
-
|
|
47
|
+
data.errors.forEach(error => {
|
|
48
|
+
const { type, parameter } = error
|
|
49
|
+
|
|
50
|
+
const input = this.inputTargets.find(input => input.name === parameter)
|
|
51
|
+
|
|
52
|
+
input.setCustomValidity(Hellotext.business.locale.errors[type])
|
|
53
|
+
input.reportValidity()
|
|
54
|
+
|
|
55
|
+
input.addEventListener('input', () => {
|
|
56
|
+
input.setCustomValidity('')
|
|
57
|
+
input.reportValidity()
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
return this.showErrorMessages()
|
|
48
62
|
}
|
|
49
63
|
|
|
50
64
|
this.buttonTarget.style.display = 'none'
|
|
51
65
|
this.element.querySelectorAll('input').forEach(input => (input.disabled = true))
|
|
52
66
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (submission.identified) {
|
|
56
|
-
this.completed()
|
|
57
|
-
} else {
|
|
58
|
-
Hellotext.setSession(submission.session)
|
|
59
|
-
this.revealOTPContainer(submission.id)
|
|
67
|
+
if (!data.identified) {
|
|
68
|
+
Hellotext.setSession(data.session)
|
|
60
69
|
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
revealOTPContainer(submissionId) {
|
|
64
|
-
const paragraph = this.requiredInputs.find(input => input.name === 'email')
|
|
65
|
-
? Hellotext.business.locale.otp.sent_to_email
|
|
66
|
-
: Hellotext.business.locale.otp.sent_to_phone
|
|
67
70
|
|
|
68
|
-
this.
|
|
71
|
+
this.completed()
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
completed() {
|
|
@@ -84,6 +87,7 @@ export default class extends Controller {
|
|
|
84
87
|
|
|
85
88
|
clearErrorMessages() {
|
|
86
89
|
this.element.querySelectorAll('input').forEach(input => {
|
|
90
|
+
input.setCustomValidity('')
|
|
87
91
|
const parent = input.closest('article')
|
|
88
92
|
parent.querySelector('[data-error-container]').innerText = ''
|
|
89
93
|
})
|
package/src/hellotext.js
CHANGED
|
@@ -7,13 +7,12 @@ import { NotInitializedError } from './errors'
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @typedef {Object} Config
|
|
10
|
-
* @property {Boolean}
|
|
10
|
+
* @property {Boolean} autoGenerateSession
|
|
11
11
|
* @property {Boolean} autoMountForms
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
class Hellotext {
|
|
15
15
|
static #session
|
|
16
|
-
static #config
|
|
17
16
|
static #query
|
|
18
17
|
|
|
19
18
|
static eventEmitter = new Event()
|
|
@@ -26,7 +25,8 @@ class Hellotext {
|
|
|
26
25
|
* @param { Config } config
|
|
27
26
|
*/
|
|
28
27
|
static initialize(business, config) {
|
|
29
|
-
|
|
28
|
+
Configuration.assign(config)
|
|
29
|
+
|
|
30
30
|
this.#query = new Query()
|
|
31
31
|
|
|
32
32
|
this.business = new Business(business)
|
|
@@ -36,7 +36,7 @@ class Hellotext {
|
|
|
36
36
|
|
|
37
37
|
if (this.#query.session) {
|
|
38
38
|
this.#session = Cookies.set('hello_session', this.#query.session)
|
|
39
|
-
} else if (
|
|
39
|
+
} else if (Configuration.autoGenerateSession) {
|
|
40
40
|
this.#mintAnonymousSession().then(response => {
|
|
41
41
|
this.#session = Cookies.set('hello_session', response.id)
|
|
42
42
|
})
|
package/src/index.js
CHANGED
|
@@ -2,11 +2,9 @@ import { Application } from '@hotwired/stimulus'
|
|
|
2
2
|
import Hellotext from './hellotext'
|
|
3
3
|
|
|
4
4
|
import FormController from './controllers/form_controller'
|
|
5
|
-
import OTPController from './controllers/otp_controller'
|
|
6
5
|
|
|
7
6
|
const application = Application.start()
|
|
8
7
|
application.register('hellotext--form', FormController)
|
|
9
|
-
application.register('hellotext--otp', OTPController)
|
|
10
8
|
|
|
11
9
|
import '../styles/index.css'
|
|
12
10
|
|
package/src/locales/en.js
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
export default {
|
|
2
|
-
otp: {
|
|
3
|
-
sent_to_email: 'A One-Time Password has been sent to your email address',
|
|
4
|
-
sent_to_phone: 'An One-Time Password has been sent to your phone number',
|
|
5
|
-
resend_successful: 'The One-Time Password has been resent successfully',
|
|
6
|
-
invalid: 'Invalid One-Time Password',
|
|
7
|
-
resend: 'Resend verification code',
|
|
8
|
-
submit: 'Submit',
|
|
9
|
-
throttled: 'You have reached the maximum number of attempts. Please try again in 1 minute.',
|
|
10
|
-
placeholder: 'Enter the code here',
|
|
11
|
-
},
|
|
12
2
|
white_label: {
|
|
13
3
|
powered_by: 'Powered by',
|
|
14
4
|
},
|
|
5
|
+
errors: {
|
|
6
|
+
parameter_not_unique: 'This value is taken.',
|
|
7
|
+
blank: 'This field is required.'
|
|
8
|
+
}
|
|
15
9
|
}
|
package/src/locales/es.js
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
export default {
|
|
2
|
-
otp: {
|
|
3
|
-
sent_to_email: 'Un código de un solo uso ha sido enviado a tu correo electrónico',
|
|
4
|
-
sent_to_phone: 'Un código de un solo uso ha sido enviado a tu número de teléfono',
|
|
5
|
-
resend_successful: 'El código de un solo uso ha sido reenviado exitosamente',
|
|
6
|
-
invalid: 'Código de un solo uso inválido',
|
|
7
|
-
resend: 'Reenviar código de verificación',
|
|
8
|
-
submit: 'Enviar',
|
|
9
|
-
throttled: 'Has alcanzado el número máximo de intentos. Por favor intenta de nuevo en 1 minuto.',
|
|
10
|
-
placeholder: 'Ingresa el código aquí'
|
|
11
|
-
},
|
|
12
2
|
white_label: {
|
|
13
3
|
powered_by: 'Desarrollado por',
|
|
14
4
|
},
|
|
5
|
+
errors: {
|
|
6
|
+
parameter_not_unique: 'Este valor ya está en uso.',
|
|
7
|
+
blank: 'Este campo es obligatorio.'
|
|
8
|
+
}
|
|
15
9
|
}
|
package/src/models/form.js
CHANGED
package/styles/index.css
CHANGED
package/alpha.html
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport"
|
|
6
|
-
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
|
|
7
|
-
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
8
|
-
<title>Document</title>
|
|
9
|
-
</head>
|
|
10
|
-
<body>
|
|
11
|
-
|
|
12
|
-
hello there
|
|
13
|
-
<script type="module">
|
|
14
|
-
import 'https://unpkg.com/@hellotext/hellotext@latest/dist/hellotext.js';
|
|
15
|
-
|
|
16
|
-
Hellotext.initialize('zGrDJ1Lb', {
|
|
17
|
-
apiRoot: 'http://api.lvh.me:3000',
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
// Hellotext.initialize('deadass')
|
|
21
|
-
</script>
|
|
22
|
-
</body>
|
|
23
|
-
</html>
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.OTPBuilder = void 0;
|
|
7
|
-
var _hellotext = _interopRequireDefault(require("../hellotext"));
|
|
8
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
9
|
-
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
10
|
-
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); } }
|
|
11
|
-
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
12
|
-
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
13
|
-
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); }
|
|
14
|
-
function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; }
|
|
15
|
-
var id = 0;
|
|
16
|
-
function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
|
|
17
|
-
var _template = /*#__PURE__*/_classPrivateFieldLooseKey("template");
|
|
18
|
-
var OTPBuilder = /*#__PURE__*/function () {
|
|
19
|
-
function OTPBuilder() {
|
|
20
|
-
_classCallCheck(this, OTPBuilder);
|
|
21
|
-
}
|
|
22
|
-
_createClass(OTPBuilder, null, [{
|
|
23
|
-
key: "build",
|
|
24
|
-
value: function build(submissionId, label) {
|
|
25
|
-
var element = _classPrivateFieldLooseBase(this, _template)[_template](submissionId, label);
|
|
26
|
-
var container = document.createElement('div');
|
|
27
|
-
container.innerHTML = element;
|
|
28
|
-
return container;
|
|
29
|
-
}
|
|
30
|
-
}]);
|
|
31
|
-
return OTPBuilder;
|
|
32
|
-
}();
|
|
33
|
-
exports.OTPBuilder = OTPBuilder;
|
|
34
|
-
function _template2(submissionId, label) {
|
|
35
|
-
return "\n <article \n data-controller=\"hellotext--otp\" \n data-hellotext--otp-submission-id-value=\"".concat(submissionId, "\"\n data-hellotext--form-target=\"otpContainer\"\n data-form-otp\n >\n <header data-otp-header>\n <p>").concat(label, "</p>\n <input \n type=\"text\"\n name=\"otp\"\n data-hellotext--otp-target=\"input\"\n placeholder=\"").concat(_hellotext.default.business.locale.otp.placeholder, "\"\n maxlength=\"6\"\n />\n </header>\n \n <footer data-otp-footer>\n <button type=\"button\" data-hellotext--otp-target=\"submitButton\" data-action=\"hellotext--otp#submit\">\n ").concat(_hellotext.default.business.locale.otp.submit, "\n </button>\n \n <button type=\"button\" data-hellotext--otp-target=\"resendButton\" data-action=\"hellotext--otp#resend\">\n ").concat(_hellotext.default.business.locale.otp.resend, "\n </button>\n </footer>\n </article>\n ");
|
|
36
|
-
}
|
|
37
|
-
Object.defineProperty(OTPBuilder, _template, {
|
|
38
|
-
value: _template2
|
|
39
|
-
});
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
var _stimulus = require("@hotwired/stimulus");
|
|
8
|
-
var _hellotext = _interopRequireDefault(require("../hellotext"));
|
|
9
|
-
var _submissions = _interopRequireDefault(require("../api/submissions"));
|
|
10
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
-
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
12
|
-
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
13
|
-
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
14
|
-
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); } }
|
|
15
|
-
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
16
|
-
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
17
|
-
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); }
|
|
18
|
-
function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get.bind(); } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); }
|
|
19
|
-
function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
|
|
20
|
-
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
21
|
-
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
22
|
-
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
|
|
23
|
-
function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
|
|
24
|
-
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
|
25
|
-
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
26
|
-
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
27
|
-
var _default = /*#__PURE__*/function (_Controller) {
|
|
28
|
-
_inherits(_default, _Controller);
|
|
29
|
-
var _super = _createSuper(_default);
|
|
30
|
-
function _default() {
|
|
31
|
-
_classCallCheck(this, _default);
|
|
32
|
-
return _super.apply(this, arguments);
|
|
33
|
-
}
|
|
34
|
-
_createClass(_default, [{
|
|
35
|
-
key: "initialize",
|
|
36
|
-
value: function initialize() {
|
|
37
|
-
_get(_getPrototypeOf(_default.prototype), "initialize", this).call(this);
|
|
38
|
-
this.attempts = 0;
|
|
39
|
-
this.onInputChange = this.onInputChange.bind(this);
|
|
40
|
-
this.throttleInterval = setInterval(() => {
|
|
41
|
-
this.attempts = 0;
|
|
42
|
-
}, 60000);
|
|
43
|
-
}
|
|
44
|
-
}, {
|
|
45
|
-
key: "connect",
|
|
46
|
-
value: function connect() {
|
|
47
|
-
this.inputTarget.addEventListener('input', this.onInputChange);
|
|
48
|
-
this.inputTarget.focus();
|
|
49
|
-
_get(_getPrototypeOf(_default.prototype), "connect", this).call(this);
|
|
50
|
-
}
|
|
51
|
-
}, {
|
|
52
|
-
key: "disconnect",
|
|
53
|
-
value: function disconnect() {
|
|
54
|
-
clearInterval(this.throttleInterval);
|
|
55
|
-
this.inputTarget.removeEventListener('input', this.onInputChange);
|
|
56
|
-
_get(_getPrototypeOf(_default.prototype), "disconnect", this).call(this);
|
|
57
|
-
}
|
|
58
|
-
}, {
|
|
59
|
-
key: "resend",
|
|
60
|
-
value: function () {
|
|
61
|
-
var _resend = _asyncToGenerator(function* () {
|
|
62
|
-
if (this.throttled) {
|
|
63
|
-
return alert(_hellotext.default.business.locale.otp.throttled);
|
|
64
|
-
}
|
|
65
|
-
this.resendButtonTarget.disabled = true;
|
|
66
|
-
var response = yield _submissions.default.resendOTP(this.submissionIdValue);
|
|
67
|
-
if (response.succeeded) {
|
|
68
|
-
this.resendButtonTarget.disabled = false;
|
|
69
|
-
}
|
|
70
|
-
alert(_hellotext.default.business.locale.otp.resend_successful);
|
|
71
|
-
this.attempts += 1;
|
|
72
|
-
});
|
|
73
|
-
function resend() {
|
|
74
|
-
return _resend.apply(this, arguments);
|
|
75
|
-
}
|
|
76
|
-
return resend;
|
|
77
|
-
}()
|
|
78
|
-
}, {
|
|
79
|
-
key: "onInputChange",
|
|
80
|
-
value: function onInputChange() {
|
|
81
|
-
if (this.inputTarget.value.length !== 6) return;
|
|
82
|
-
this.submit();
|
|
83
|
-
}
|
|
84
|
-
}, {
|
|
85
|
-
key: "submit",
|
|
86
|
-
value: function () {
|
|
87
|
-
var _submit = _asyncToGenerator(function* () {
|
|
88
|
-
if (this.inputTarget.value.length !== 6) {
|
|
89
|
-
return alert(_hellotext.default.business.locale.otp.invalid);
|
|
90
|
-
}
|
|
91
|
-
this.disable();
|
|
92
|
-
var response = yield _submissions.default.verifyOTP(this.submissionIdValue, this.inputTarget.value);
|
|
93
|
-
if (response.succeeded) {
|
|
94
|
-
this.dispatch('verified', {
|
|
95
|
-
detail: {
|
|
96
|
-
submissionId: this.submissionIdValue
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
} else {
|
|
100
|
-
alert(_hellotext.default.business.locale.otp.invalid);
|
|
101
|
-
setTimeout(() => {
|
|
102
|
-
this.inputTarget.value = '';
|
|
103
|
-
this.inputTarget.focus();
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
this.enable();
|
|
107
|
-
});
|
|
108
|
-
function submit() {
|
|
109
|
-
return _submit.apply(this, arguments);
|
|
110
|
-
}
|
|
111
|
-
return submit;
|
|
112
|
-
}() // private
|
|
113
|
-
}, {
|
|
114
|
-
key: "disable",
|
|
115
|
-
value: function disable() {
|
|
116
|
-
this.inputTarget.disabled = true;
|
|
117
|
-
this.resendButtonTarget.disabled = true;
|
|
118
|
-
this.submitButtonTarget.disabled = true;
|
|
119
|
-
}
|
|
120
|
-
}, {
|
|
121
|
-
key: "enable",
|
|
122
|
-
value: function enable() {
|
|
123
|
-
this.inputTarget.disabled = false;
|
|
124
|
-
this.resendButtonTarget.disabled = false;
|
|
125
|
-
this.submitButtonTarget.disabled = false;
|
|
126
|
-
}
|
|
127
|
-
}, {
|
|
128
|
-
key: "throttled",
|
|
129
|
-
get: function get() {
|
|
130
|
-
return this.attempts >= 3;
|
|
131
|
-
}
|
|
132
|
-
}]);
|
|
133
|
-
return _default;
|
|
134
|
-
}(_stimulus.Controller);
|
|
135
|
-
exports.default = _default;
|
|
136
|
-
_default.values = {
|
|
137
|
-
submissionId: String
|
|
138
|
-
};
|
|
139
|
-
_default.targets = ['input', 'submitButton', 'resendButton'];
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import Hellotext from '../hellotext'
|
|
2
|
-
|
|
3
|
-
class OTPBuilder {
|
|
4
|
-
static build(submissionId, label) {
|
|
5
|
-
const element = this.#template(submissionId, label)
|
|
6
|
-
const container = document.createElement('div')
|
|
7
|
-
|
|
8
|
-
container.innerHTML = element
|
|
9
|
-
|
|
10
|
-
return container
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
static #template(submissionId, label) {
|
|
14
|
-
return `
|
|
15
|
-
<article
|
|
16
|
-
data-controller="hellotext--otp"
|
|
17
|
-
data-hellotext--otp-submission-id-value="${submissionId}"
|
|
18
|
-
data-hellotext--form-target="otpContainer"
|
|
19
|
-
data-form-otp
|
|
20
|
-
>
|
|
21
|
-
<header data-otp-header>
|
|
22
|
-
<p>${label}</p>
|
|
23
|
-
<input
|
|
24
|
-
type="text"
|
|
25
|
-
name="otp"
|
|
26
|
-
data-hellotext--otp-target="input"
|
|
27
|
-
placeholder="${Hellotext.business.locale.otp.placeholder}"
|
|
28
|
-
maxlength="6"
|
|
29
|
-
/>
|
|
30
|
-
</header>
|
|
31
|
-
|
|
32
|
-
<footer data-otp-footer>
|
|
33
|
-
<button type="button" data-hellotext--otp-target="submitButton" data-action="hellotext--otp#submit">
|
|
34
|
-
${Hellotext.business.locale.otp.submit}
|
|
35
|
-
</button>
|
|
36
|
-
|
|
37
|
-
<button type="button" data-hellotext--otp-target="resendButton" data-action="hellotext--otp#resend">
|
|
38
|
-
${Hellotext.business.locale.otp.resend}
|
|
39
|
-
</button>
|
|
40
|
-
</footer>
|
|
41
|
-
</article>
|
|
42
|
-
`
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export { OTPBuilder }
|