From da9febc5c8c3362ab7e8ac125765d4df75f26e48 Mon Sep 17 00:00:00 2001 From: "Stefan-Calin Crainiciuc (stcc)" Date: Thu, 2 Mar 2023 18:39:41 +0000 Subject: [PATCH] [FIX] web: signature widget works in mobile view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Steps to reproduce: - Install stock - Config > Shipping > enable Signature on delivery orders - Create delivery order > Validate - Switch to mobile view - Action > Sign Issue: We get a traceback: `Uncaught Promise > Component is destroyed`. This happens because the signature widget is destroyed when the Action dropdown is folded. Solution: Use the orm service in `this.env.services` to perform the `write`. We have to also update the view in order to see the new delivery slip. opw-3133731 closes odoo/odoo#114954 X-original-commit: ad555010ea668324aeee21f8aabd41fe352eb0f5 Signed-off-by: Géry Debongnie Signed-off-by: Stefan-Calin Crainiciuc (stcc) --- .../src/views/widgets/signature/signature.js | 8 ++- .../tests/views/widgets/signature_tests.js | 72 ++++++++++++++++++- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/addons/web/static/src/views/widgets/signature/signature.js b/addons/web/static/src/views/widgets/signature/signature.js index b4bf0185301..0427de71691 100644 --- a/addons/web/static/src/views/widgets/signature/signature.js +++ b/addons/web/static/src/views/widgets/signature/signature.js @@ -52,13 +52,15 @@ export class SignatureWidget extends Component { this.dialogService.add(SignatureDialog, dialogProps); } - uploadSignature({ signatureImage }) { + async uploadSignature({ signatureImage }) { const file = signatureImage[1]; - const { resModel, resId } = this.props.record; + const { model, resModel, resId } = this.props.record; - this.orm.write(resModel, [resId], { + await this.env.services.orm.write(resModel, [resId], { [this.props.signatureField]: file, }); + await this.props.record.load(); + model.notify(); } } diff --git a/addons/web/static/tests/views/widgets/signature_tests.js b/addons/web/static/tests/views/widgets/signature_tests.js index 09c07a9f7ff..dc0b00daa0c 100644 --- a/addons/web/static/tests/views/widgets/signature_tests.js +++ b/addons/web/static/tests/views/widgets/signature_tests.js @@ -1,7 +1,9 @@ /** @odoo-module **/ -import { click, getFixture, patchWithCleanup } from "@web/../tests/helpers/utils"; +import { click, getFixture, patchWithCleanup, editInput, nextTick } from "@web/../tests/helpers/utils"; import { makeView, setupViewRegistries } from "@web/../tests/views/helpers"; +import { patchUiSize } from "@mail/../tests/helpers/patch_ui_size"; import { NameAndSignature } from "@web/core/signature/name_and_signature"; +import { SignatureWidget } from "@web/views/widgets/signature/signature"; let serverData; let target; @@ -20,6 +22,7 @@ QUnit.module("Widgets", (hooks) => { relation: "product", }, sign: { string: "Signature", type: "binary" }, + signature: { string: "", type: "string" }, }, records: [ { @@ -151,4 +154,71 @@ QUnit.module("Widgets", (hooks) => { await click(target, ".o_widget_signature button.o_sign_button"); assert.containsNone(target, ".modal .modal-body a.o_web_sign_auto_button"); }); + + QUnit.test("Signature widget works inside of a dropdown", async (assert) => { + assert.expect(7); + patchWithCleanup(SignatureWidget.prototype, { + async onClickSignature() { + await this._super.apply(this, arguments); + assert.step("onClickSignature"); + }, + async uploadSignature({signatureImage}) { + await this._super.apply(this, arguments); + assert.step("uploadSignature"); + }, + }); + + // force mobile view + patchUiSize({ width: 225 }); + + await makeView({ + type: "form", + resModel: "partner", + resId: 1, + serverData, + arch: ` +
+
+
+ + + `, + mockRPC: async (route, args) => { + if (route === "/web/sign/get_fonts/") { + return {}; + } + }, + }); + + // change display_name to enable auto-sign feature + await editInput(target, ".o_field_widget[name=display_name] input", "test"); + + // open the signature dialog + await click(target, ".o_statusbar_buttons .dropdown-toggle"); + await click(target, ".o_widget_signature button.o_sign_button"); + + assert.containsOnce(target, ".modal-dialog", "Should have one modal opened"); + + // use auto-sign feature, might take a while + await click(target, ".o_web_sign_auto_button"); + + assert.containsOnce(target, ".modal-footer button.btn-primary"); + + let maxDelay = 100; + while (target.querySelector(".modal-footer button.btn-primary")["disabled"] && maxDelay > 0) { + await nextTick(); + maxDelay--; + } + + assert.equal(maxDelay > 0, true, "Timeout exceeded"); + + // close the dialog and save the signature + await click(target, ".modal-footer button.btn-primary:enabled"); + + assert.containsNone(target, ".modal-dialog", "Should have no modal opened"); + + assert.verifySteps(["onClickSignature", "uploadSignature"], "An error has occurred while signing"); + }); });