diff options
| author | fja-odoo <fja@odoo.com> | 2020-04-24 10:50:28 +0000 |
|---|---|---|
| committer | fja-odoo <fja@odoo.com> | 2020-06-05 10:58:50 +0000 |
| commit | 541148613451f4c14a299672d91c4397d8a9f6de (patch) | |
| tree | c798cd359c3960d4ae86ebc9847666a3a30bf4a6 /addons/website_form/static/src | |
| parent | fea1706f275e88a0d28dd2776c6aa0dd62c1bf3d (diff) | |
[IMP] google_recaptcha, *: integrate recaptchaV3
* = base_setup, website_form, website_sale, website_crm,
crm_iap_lead_website, website_hr_recruitment, website_mass_mailing
Integrate reCaptchaV3 on website_form submit and website_mass_mailing
subscription.
You can now use ReCaptchaV3 to add reCaptcha verification in any module
using google_recaptcha.
Also added a better error management on the form with custom messages.
task-2217980
closes odoo/odoo#48466
Related: odoo/enterprise#9649
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
Diffstat (limited to 'addons/website_form/static/src')
5 files changed, 70 insertions, 24 deletions
diff --git a/addons/website_form/static/src/snippets/s_website_form/000.js b/addons/website_form/static/src/snippets/s_website_form/000.js index 4d08906c6b5..b06a9b62a74 100644 --- a/addons/website_form/static/src/snippets/s_website_form/000.js +++ b/addons/website_form/static/src/snippets/s_website_form/000.js @@ -3,6 +3,7 @@ odoo.define('website_form.s_website_form', function (require) { var core = require('web.core'); var time = require('web.time'); + const {ReCaptcha} = require('google_recaptcha.ReCaptchaV3'); var ajax = require('web.ajax'); var publicWidget = require('web.public.widget'); @@ -21,11 +22,19 @@ odoo.define('website_form.s_website_form', function (require) { */ init: function () { this._super(...arguments); + this._recaptcha = new ReCaptcha(); this.__started = new Promise(resolve => this.__startResolve = resolve); }, - + willStart: function () { + const res = this._super(...arguments); + if (!this.$target[0].classList.contains('s_website_form_no_recaptcha')) { + this._recaptcha.loadLibs(); + } + return res; + }, start: function () { var self = this; + // Initialize datetimepickers var datepickers_options = { minDate: moment({y: 1900}), @@ -86,7 +95,7 @@ odoo.define('website_form.s_website_form', function (require) { this.$target.parent().find('.s_website_form_end_message').addClass('d-none'); }, - send: function (e) { + send: async function (e) { e.preventDefault(); // Prevent the default submit behavior // Prevent users from crazy clicking this.$target.find('.s_website_form_send, .o_website_form_send').addClass('disabled'); // !compatibility @@ -95,7 +104,7 @@ odoo.define('website_form.s_website_form', function (require) { self.$target.find('#s_website_form_result, #o_website_form_result').empty(); // !compatibility if (!self.check_error_fields({})) { - self.update_status('invalid'); + self.update_status('error', _t("Please fill in the form correctly.")); return false; } @@ -132,6 +141,13 @@ odoo.define('website_form.s_website_form', function (require) { } }); + const tokenObj = await this._recaptcha.getToken('website_form'); + if (tokenObj.token) { + form_values['recaptcha_token_response'] = tokenObj.token; + } else if (tokenObj.error) { + self.update_status('error', tokenObj.error); + return false; + } // Post form and handle result ajax.post(this.$target.attr('action') + (this.$target.data('force_action') || this.$target.data('model_name')), form_values) .then(function (result_data) { @@ -140,7 +156,7 @@ odoo.define('website_form.s_website_form', function (require) { result_data = JSON.parse(result_data); if (!result_data.id) { // Failure, the server didn't return the created record ID - self.update_status('error'); + self.update_status('error', result_data.error ? result_data.error : false); if (result_data.error_fields) { // If the server return a list of bad fields, show these fields for users self.check_error_fields(result_data.error_fields); @@ -265,17 +281,23 @@ odoo.define('website_form.s_website_form', function (require) { return value; }, - update_status: function (status) { + update_status: function (status, message) { if (status !== 'success') { // Restore send button behavior if result is an error this.$target.find('.s_website_form_send, .o_website_form_send').removeClass('disabled'); // !compatibility } var $result = this.$('#s_website_form_result, #o_website_form_result'); // !compatibility + if (status === 'error' && !message) { + message = _t("An error has occured, the form has not been sent."); + } + // Note: we still need to wait that the widget is properly started // before any qweb rendering which depends on xmlDependencies // because the event handlers are binded before the call to // willStart for public widgets... - this.__started.then(() => $result.replaceWith(qweb.render(`website_form.status_${status}`))); + this.__started.then(() => $result.replaceWith(qweb.render(`website_form.status_${status}`, { + message: message, + }))); }, }); }); diff --git a/addons/website_form/static/src/snippets/s_website_form/001.scss b/addons/website_form/static/src/snippets/s_website_form/001.scss index acfaae6f5a1..375a4bb5fe0 100644 --- a/addons/website_form/static/src/snippets/s_website_form/001.scss +++ b/addons/website_form/static/src/snippets/s_website_form/001.scss @@ -43,15 +43,15 @@ padding-bottom: 0.5rem; } - .s_website_form_submit { + .s_website_form_submit, .s_website_form_recaptcha { .s_website_form_label { float: left; height: 1px; } - &.s_website_form_no_submit_label { - .s_website_form_label { - display: none; - } + } + .s_website_form_no_submit_label { + .s_website_form_label { + display: none; } } } diff --git a/addons/website_form/static/src/snippets/s_website_form/options.js b/addons/website_form/static/src/snippets/s_website_form/options.js index f21f3e11ef2..582791f381f 100644 --- a/addons/website_form/static/src/snippets/s_website_form/options.js +++ b/addons/website_form/static/src/snippets/s_website_form/options.js @@ -9,7 +9,10 @@ const qweb = core.qweb; const _t = core._t; const FormEditor = options.Class.extend({ - xmlDependencies: ['/website_form/static/src/xml/website_form_editor.xml'], + xmlDependencies: [ + '/website_form/static/src/xml/website_form_editor.xml', + '/google_recaptcha/static/src/xml/recaptcha.xml', + ], //---------------------------------------------------------------------- // Private @@ -340,8 +343,8 @@ options.registry.WebsiteFormEditor = FormEditor.extend({ const proms = [this._super(...arguments)]; // Disable text edition this.$target.attr('contentEditable', false); - // Make button editable - this.$target.find('.s_website_form_send').attr('contentEditable', true); + // Make button and recaptcha editable + this.$target.find('.s_website_form_send, .s_website_form_recaptcha').attr('contentEditable', true); // Get potential message this.$message = this.$target.parent().find('.s_website_form_end_message'); this.showEndMessage = false; @@ -479,6 +482,22 @@ options.registry.WebsiteFormEditor = FormEditor.extend({ this.$target[0].dataset.mark = value.trim(); this._setLabelsMark(); }, + /** + * Toggle the recaptcha legal terms + */ + toggleRecaptchaLegal: function (previewMode, value, params) { + const recaptchaLegalEl = this.$target[0].querySelector('.s_website_form_recaptcha'); + if (recaptchaLegalEl) { + recaptchaLegalEl.remove(); + } else { + const template = document.createElement('template'); + const labelWidth = this.$target[0].querySelector('.s_website_form_label').style.width; + template.innerHTML = qweb.render("webite_form.s_website_form_recaptcha_legal", {labelWidth: labelWidth}); + const legal = template.content.firstElementChild; + legal.setAttribute('contentEditable', true); + this.$target.find('.s_website_form_submit').before(legal); + } + }, //-------------------------------------------------------------------------- // Private @@ -503,6 +522,8 @@ options.registry.WebsiteFormEditor = FormEditor.extend({ return this.$target[0].dataset.successMode; case 'setMark': return this._getMark(); + case 'toggleRecaptchaLegal': + return !this.$target[0].querySelector('.s_website_form_recaptcha') || ''; } return this._super(...arguments); }, @@ -643,7 +664,7 @@ options.registry.WebsiteFormEditor = FormEditor.extend({ await formInfo.formFields.forEach(async field => { field.formatInfo = formatInfo; await this._fetchFieldRecords(field); - this.$target.find('.s_website_form_submit').before(this._renderField(field)); + this.$target.find('.s_website_form_submit, .s_website_form_recaptcha').first().before(this._renderField(field)); }); } }, @@ -1219,7 +1240,7 @@ options.registry.AddFieldForm = FormEditor.extend({ const field = this._getCustomField('char', 'Custom Text'); field.formatInfo = this._getDefaultFormat(); const htmlField = this._renderField(field); - this.$target.find('.s_website_form_submit').before(htmlField); + this.$target.find('.s_website_form_submit, .s_website_form_recaptcha').first().before(htmlField); this.trigger_up('activate_snippet', { $snippet: $(htmlField), }); diff --git a/addons/website_form/static/src/xml/website_form.xml b/addons/website_form/static/src/xml/website_form.xml index 5403f763e24..9c1390c74df 100644 --- a/addons/website_form/static/src/xml/website_form.xml +++ b/addons/website_form/static/src/xml/website_form.xml @@ -8,17 +8,11 @@ </span> </t> - <!-- Missing field status --> - <t t-name="website_form.status_invalid"> - <span id="s_website_form_result" class="text-danger ml8"> - <i class="fa fa-close mr4" role="img" aria-label="Error" title="Error"/>Please fill in the form correctly. - </span> - </t> - <!-- Error status --> <t t-name="website_form.status_error"> <span id="s_website_form_result" class="text-danger ml8"> - <i class="fa fa-close mr4" role="img" aria-label="Error" title="Error"/>An error has occured, the form has not been sent. + <i class="fa fa-close mr4" role="img" aria-label="Error" title="Error"/> + <t t-esc="message"/> </span> </t> </templates> diff --git a/addons/website_form/static/src/xml/website_form_editor.xml b/addons/website_form/static/src/xml/website_form_editor.xml index 6db59f01a22..13d4ae1aeb5 100644 --- a/addons/website_form/static/src/xml/website_form_editor.xml +++ b/addons/website_form/static/src/xml/website_form_editor.xml @@ -21,6 +21,15 @@ </div> </t> + <t t-name="webite_form.s_website_form_recaptcha_legal"> + <div class="col-12 s_website_form_recaptcha" data-name="Recaptcha Legal"> + <div t-attf-style="width: #{labelWidth or '200px'}" class="s_website_form_label"/> + <div class="col-sm"> + <t t-call="google_recaptcha.recaptcha_legal_terms"/> + </div> + </div> + </t> + <!-- Generic Field Layout --> <!-- Changes made here needs to be reflected in the different Form view (Contact Us, Jobs, ...) --> <t t-name="website_form.field"> |
