diff --git a/addons/mrp_subcontracting/__manifest__.py b/addons/mrp_subcontracting/__manifest__.py index 4c4ab41f3ad..42d89893290 100644 --- a/addons/mrp_subcontracting/__manifest__.py +++ b/addons/mrp_subcontracting/__manifest__.py @@ -56,7 +56,6 @@ 'web/static/src/legacy/scss/ui.scss', 'web/static/src/legacy/scss/modal.scss', 'web/static/src/views/fields/translation_dialog.scss', - 'web/static/src/legacy/scss/name_and_signature.scss', 'web/static/src/scss/fontawesome_overridden.scss', 'web/static/src/legacy/js/promise_extension.js', @@ -104,8 +103,6 @@ 'web/static/src/legacy/js/core/widget.js', 'web/static/src/legacy/js/services/core.js', 'web/static/src/legacy/js/common_env.js', - 'web/static/src/legacy/js/widgets/name_and_signature.js', - 'web/static/src/legacy/xml/name_and_signature.xml', ('include', 'web._assets_bootstrap'), diff --git a/addons/portal/__manifest__.py b/addons/portal/__manifest__.py index e7e50e6aff3..ab007883e02 100644 --- a/addons/portal/__manifest__.py +++ b/addons/portal/__manifest__.py @@ -43,11 +43,10 @@ a dependency towards website editing and customization capabilities.""", 'portal/static/src/xml/portal_chatter.xml', 'portal/static/src/js/portal_composer.js', 'portal/static/src/js/portal_security.js', - 'portal/static/src/js/portal_signature.js', - 'portal/static/src/xml/portal_signature.xml', 'portal/static/src/js/portal_sidebar.js', 'portal/static/src/xml/portal_security.xml', 'portal/static/src/js/components/**/*', + 'portal/static/src/signature_form/**/*', ], 'web.assets_tests': [ 'portal/static/tests/**/*', diff --git a/addons/portal/static/src/js/portal_signature.js b/addons/portal/static/src/js/portal_signature.js deleted file mode 100644 index ddbd7fb9f25..00000000000 --- a/addons/portal/static/src/js/portal_signature.js +++ /dev/null @@ -1,192 +0,0 @@ -/** @odoo-module **/ - -import { _t } from "@web/core/l10n/translation"; -import { renderToElement } from "@web/core/utils/render"; -import publicWidget from "@web/legacy/js/public/public_widget"; -import { NameAndSignature } from "@web/legacy/js/widgets/name_and_signature"; - -/** - * This widget is a signature request form. It uses - * @see NameAndSignature for the input fields, adds a submit - * button, and handles the RPC to save the result. - */ -var SignatureForm = publicWidget.Widget.extend({ - template: 'portal.portal_signature', - events: { - 'click .o_portal_sign_submit': 'async _onClickSignSubmit', - }, - custom_events: { - 'signature_changed': '_onChangeSignature', - }, - - /** - * Overridden to allow options. - * - * @constructor - * @param {Widget} parent - * @param {Object} options - * @param {string} options.callUrl - make RPC to this url - * @param {string} [options.sendLabel='Accept & Sign'] - label of the - * send button - * @param {Object} [options.rpcParams={}] - params for the RPC - * @param {Object} [options.nameAndSignatureOptions={}] - options for - * @see NameAndSignature.init() - */ - init: function (parent, options) { - this._super.apply(this, arguments); - - this.csrf_token = odoo.csrf_token; - - this.callUrl = options.callUrl || ''; - this.rpcParams = options.rpcParams || {}; - this.sendLabel = options.sendLabel || _t("Accept & Sign"); - - this.nameAndSignature = new NameAndSignature(this, - options.nameAndSignatureOptions || {}); - - this.rpc = this.bindService("rpc"); - }, - /** - * Overridden to get the DOM elements - * and to insert the name and signature. - * - * @override - */ - start: function () { - var self = this; - this.$confirm_btn = this.$('.o_portal_sign_submit'); - this.$controls = this.$('.o_portal_sign_controls'); - var subWidgetStart = this.nameAndSignature.replace(this.$('.o_web_sign_name_and_signature')); - return Promise.all([subWidgetStart, this._super.apply(this, arguments)]).then(function () { - self.nameAndSignature.resetSignature(); - }); - }, - - //---------------------------------------------------------------------- - // Public - //---------------------------------------------------------------------- - - /** - * Focuses the name. - * - * @see NameAndSignature.focusName(); - */ - focusName: function () { - this.nameAndSignature.focusName(); - }, - /** - * Resets the signature. - * - * @see NameAndSignature.resetSignature(); - */ - resetSignature: function () { - return this.nameAndSignature.resetSignature(); - }, - - //---------------------------------------------------------------------- - // Handlers - //---------------------------------------------------------------------- - - /** - * Handles click on the submit button. - * - * This will get the current name and signature and validate them. - * If they are valid, they are sent to the server, and the reponse is - * handled. If they are invalid, it will display the errors to the user. - * - * @private - * @param {Event} ev - * @returns {Deferred} - */ - _onClickSignSubmit: function (ev) { - var self = this; - ev.preventDefault(); - - if (!this.nameAndSignature.validateSignature()) { - return; - } - - var name = this.nameAndSignature.getName(); - var signature = this.nameAndSignature.getSignatureImage()[1]; - - return this.rpc( - this.callUrl, - Object.assign(this.rpcParams, { - 'name': name, - 'signature': signature, - }) - ).then(function (data) { - if (data.error) { - self.$('.o_portal_sign_error_msg').remove(); - self.$controls.prepend(renderToElement('portal.portal_signature_error', {widget: data})); - } else if (data.success) { - var $success = renderToElement('portal.portal_signature_success', {widget: data}); - self.$el.empty().append($success); - } - if (data.force_refresh) { - if (data.redirect_url) { - window.location = data.redirect_url; - } else { - window.location.reload(); - } - // no resolve if we reload the page - return new Promise(function () { }); - } - }); - }, - /** - * Toggles the submit button depending on the signature state. - * - * @private - */ - _onChangeSignature: function () { - var isEmpty = this.nameAndSignature.isSignatureEmpty(); - this.$confirm_btn.prop('disabled', isEmpty); - }, -}); - -publicWidget.registry.SignatureForm = publicWidget.Widget.extend({ - selector: '.o_portal_signature_form', - - /** - * @private - */ - start: function () { - var hasBeenReset = false; - - var callUrl = this.$el.data('call-url'); - var nameAndSignatureOptions = { - defaultName: this.$el.data('default-name'), - mode: this.$el.data('mode'), - displaySignatureRatio: this.$el.data('signature-ratio'), - signatureType: this.$el.data('signature-type'), - fontColor: this.$el.data('font-color') || 'black', - }; - var sendLabel = this.$el.data('send-label'); - - var form = new SignatureForm(this, { - callUrl: callUrl, - nameAndSignatureOptions: nameAndSignatureOptions, - sendLabel: sendLabel, - }); - - // Correctly set up the signature area if it is inside a modal - this.$el.closest('.modal').on('shown.bs.modal', function (ev) { - if (!hasBeenReset) { - // Reset it only the first time it is open to get correct - // size. After we want to keep its content on reopen. - hasBeenReset = true; - form.resetSignature(); - } else { - form.focusName(); - } - }); - - return Promise.all([ - this._super.apply(this, arguments), - form.appendTo(this.$el) - ]); - }, -}); - -export default SignatureForm; diff --git a/addons/portal/static/src/signature_form/signature_form.js b/addons/portal/static/src/signature_form/signature_form.js new file mode 100644 index 00000000000..5da333a1387 --- /dev/null +++ b/addons/portal/static/src/signature_form/signature_form.js @@ -0,0 +1,86 @@ +/** @odoo-module **/ + +import { Component, onMounted, useRef, useState } from "@odoo/owl"; +import { _t } from "@web/core/l10n/translation"; +import { registry } from "@web/core/registry"; +import { redirect } from "@web/core/utils/urls"; +import { NameAndSignature } from "@web/core/signature/name_and_signature"; +import { useService } from "@web/core/utils/hooks"; + +/** + * This Component is a signature request form. It uses + * @see NameAndSignature for the input fields, adds a submit + * button, and handles the RPC to save the result. + */ +class SignatureForm extends Component { + static template = "portal.SignatureForm" + static components = { NameAndSignature } + + setup() { + this.rootRef = useRef("root"); + this.rpc = useService("rpc"); + + this.csrfToken = odoo.csrf_token; + this.state = useState({ + error: false, + success: false, + }); + this.signature = useState({ name: this.props.defaultName }); + this.nameAndSignatureProps = { + signature: this.signature, + fontColor: this.props.fontColor || "black", + }; + if (this.props.signatureRatio) { + this.nameAndSignatureProps.displaySignatureRatio = this.props.signatureRatio; + } + if (this.props.signatureType) { + this.nameAndSignatureProps.signatureType = this.props.signatureType; + } + if (this.props.mode) { + this.nameAndSignatureProps.mode = this.props.mode; + } + + // Correctly set up the signature area if it is inside a modal + onMounted(() => { + this.rootRef.el.closest('.modal').addEventListener('shown.bs.modal', () => { + this.signature.resetSignature(); + }); + }); + } + + get sendLabel() { + return this.props.sendLabel || _t("Accept & Sign"); + } + + /** + * Handles click on the submit button. + * + * This will get the current name and signature and validate them. + * If they are valid, they are sent to the server, and the reponse is + * handled. If they are invalid, it will display the errors to the user. + * + * @returns {Promise} + */ + async onClickSubmit() { + const name = this.signature.name; + const signature = this.signature.getSignatureImage()[1]; + const data = await this.rpc(this.props.callUrl, { name, signature }); + if (data.force_refresh) { + if (data.redirect_url) { + redirect(data.redirect_url); + } else { + window.location.reload(); + } + // do not resolve if we reload the page + return new Promise(() => {}); + } + this.state.error = data.error || false; + this.state.success = !data.error && { + message: data.message, + redirectUrl: data.redirect_url, + redirectMessage: data.redirect_message, + }; + } +} + +registry.category("public_components").add("portal.signature_form", SignatureForm); diff --git a/addons/portal/static/src/signature_form/signature_form.xml b/addons/portal/static/src/signature_form/signature_form.xml new file mode 100644 index 00000000000..d0af26a32d7 --- /dev/null +++ b/addons/portal/static/src/signature_form/signature_form.xml @@ -0,0 +1,35 @@ + + + + +
+ + + +
+ +
+
+
+ +
+
+ +
+
+ + +
+
+ + diff --git a/addons/portal/static/src/xml/portal_signature.xml b/addons/portal/static/src/xml/portal_signature.xml deleted file mode 100644 index ccd33541559..00000000000 --- a/addons/portal/static/src/xml/portal_signature.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - -
- -
-
-
- -
-
- - - - - - - - -
- -
-
- diff --git a/addons/portal/views/portal_templates.xml b/addons/portal/views/portal_templates.xml index 58f7207040b..cd6737b3cba 100644 --- a/addons/portal/views/portal_templates.xml +++ b/addons/portal/views/portal_templates.xml @@ -738,19 +738,19 @@ - {number} signature_ratio: ratio of the signature area - {string} signature_type: 'signature' or 'initial' - For the default values and more information, see init() of the widgets - SignatureForm and NameAndSignature. + For default values and more information, see components SignatureForm and NameAndSignature. -->