diff --git a/sign_oca/README.rst b/sign_oca/README.rst index d0486362..73ca58b6 100644 --- a/sign_oca/README.rst +++ b/sign_oca/README.rst @@ -17,13 +17,13 @@ Sign Oca :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsign-lightgray.png?logo=github - :target: https://github.com/OCA/sign/tree/16.0/sign_oca + :target: https://github.com/OCA/sign/tree/17.0/sign_oca :alt: OCA/sign .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/sign-16-0/sign-16-0-sign_oca + :target: https://translation.odoo-community.org/projects/sign-17-0/sign-17-0-sign_oca :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/sign&target_branch=16.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/sign&target_branch=17.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -128,7 +128,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues <https://github.com/OCA/sign/issues>`_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback <https://github.com/OCA/sign/issues/new?body=module:%20sign_oca%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. +`feedback <https://github.com/OCA/sign/issues/new?body=module:%20sign_oca%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. Do not contact contributors directly about support or help with technical issues. @@ -169,6 +169,6 @@ Current `maintainer <https://odoo-community.org/page/maintainer-role>`__: |maintainer-etobella| -This module is part of the `OCA/sign <https://github.com/OCA/sign/tree/16.0/sign_oca>`_ project on GitHub. +This module is part of the `OCA/sign <https://github.com/OCA/sign/tree/17.0/sign_oca>`_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/sign_oca/__manifest__.py b/sign_oca/__manifest__.py index 1b4a58b5..abd930c5 100644 --- a/sign_oca/__manifest__.py +++ b/sign_oca/__manifest__.py @@ -43,10 +43,7 @@ "sign_oca/static/src/elements/signature.esm.js", "sign_oca/static/src/elements/check.esm.js", "sign_oca/static/src/components/sign_oca_pdf/sign_oca_pdf.esm.js", - "sign_oca/static/src/components/sign_oca_pdf/sign_oca_pdf_action.esm.js", - "sign_oca/static/src/components/" - "sign_oca_pdf_common/sign_oca_pdf_common_action.esm.js", - "sign_oca/static/src/js/*.js", + "sign_oca/static/src/components/" "sign_oca/static/src/js/*.js", "sign_oca/static/src/xml/*.xml", ], "web.assets_frontend": [ diff --git a/sign_oca/controllers/main.py b/sign_oca/controllers/main.py index 45033a7c..4d61d537 100644 --- a/sign_oca/controllers/main.py +++ b/sign_oca/controllers/main.py @@ -51,6 +51,11 @@ def get_sign_oca_access(self, signer_id, access_token, **kwargs): "partner": signer_sudo.partner_id, "signer": signer_sudo, "access_token": access_token, + "sign_oca_backend_info": { + "access_token": access_token, + "signer_id": signer_sudo.id, + "lang": signer_sudo.partner_id.lang, + }, }, ) diff --git a/sign_oca/i18n/it.po b/sign_oca/i18n/it.po index 3c90c700..fec08304 100644 --- a/sign_oca/i18n/it.po +++ b/sign_oca/i18n/it.po @@ -1391,6 +1391,3 @@ msgstr "Verrà cancellata la richiesta e tutti gli accessi. Si è sicuri?" #: model_terms:ir.ui.view,arch_db:sign_oca.portal_sign_document_signed msgid "has already been signed" msgstr "è già stato firmato" - -#~ msgid "sign.oca.request.log" -#~ msgstr "sign.oca.request.log" diff --git a/sign_oca/models/sign_oca_request.py b/sign_oca/models/sign_oca_request.py index adaa0fa9..811fd148 100644 --- a/sign_oca/models/sign_oca_request.py +++ b/sign_oca/models/sign_oca_request.py @@ -51,8 +51,6 @@ class SignOcaRequest(models.Model): inverse_name="request_id", auto_join=True, copy=True, - readonly=True, - states={"draft": [("readonly", False)]}, string="Signers", ) signer_id = fields.Many2one( @@ -385,10 +383,7 @@ def _compute_is_allow_signature(self): def _compute_access_url(self): result = super()._compute_access_url() for record in self: - record.access_url = "/sign_oca/document/%s/%s" % ( - record.id, - record.access_token, - ) + record.access_url = f"/sign_oca/document/{record.id}/{record.access_token}" return result @api.onchange("role_id") @@ -613,7 +608,9 @@ def _get_new_hash(self, secure_seq_number): def _compute_hash(self, previous_hash): """Computes the hash of the browse_record given as self, based on the hash - of the previous record in the company's securisation sequence given as parameter""" + of the previous record in the company's securisation sequence given as + parameter + """ self.ensure_one() hash_string = sha256((previous_hash + self._string_to_hash()).encode("utf-8")) return hash_string.hexdigest() diff --git a/sign_oca/models/sign_oca_role.py b/sign_oca/models/sign_oca_role.py index 0006142d..319a7f31 100644 --- a/sign_oca/models/sign_oca_role.py +++ b/sign_oca/models/sign_oca_role.py @@ -20,7 +20,8 @@ class SignOcaRole(models.Model): default="empty", help="This field is used to define how the partner" " will be calculated in the different roles of " - "a request. This field will be used when the 'Sign from Template' action is triggered.", + "a request. This field will be used when the 'Sign from Template' " + "action is triggered.", ) default_partner_id = fields.Many2one( comodel_name="res.partner", string="Default partner" diff --git a/sign_oca/models/sign_oca_template.py b/sign_oca/models/sign_oca_template.py index 18fc6a59..23c96592 100644 --- a/sign_oca/models/sign_oca_template.py +++ b/sign_oca/models/sign_oca_template.py @@ -20,7 +20,9 @@ class SignOcaTemplate(models.Model): string="Model", domain=[("transient", "=", False), ("model", "not like", "sign.oca")], ) - model = fields.Char(compute="_compute_model", compute_sudo=True, store=True) + model = fields.Char( + compute="_compute_model", string="Model name", compute_sudo=True, store=True + ) active = fields.Boolean(default=True) request_ids = fields.One2many("sign.oca.request", inverse_name="template_id") @@ -112,7 +114,7 @@ def _prepare_sign_oca_request_vals_from_record(self, record): return { "name": self.name, "template_id": self.id, - "record_ref": "%s,%s" % (record._name, record.id), + "record_ref": f"{record._name},{record.id}", "signatory_data": self._get_signatory_data(), "data": self.data, "signer_ids": [ diff --git a/sign_oca/security/security.xml b/sign_oca/security/security.xml index 424902d8..d59777fa 100644 --- a/sign_oca/security/security.xml +++ b/sign_oca/security/security.xml @@ -37,6 +37,19 @@ <field name="perm_write" eval="0" /> <field name="perm_unlink" eval="0" /> </record> + <!-- Company Record Rules --> + <record id="sign_oca_request_rule_company" model="ir.rule"> + <field name="name">Sign Request Company</field> + <field name="model_id" ref="model_sign_oca_request" /> + <field name="domain_force">[('company_id', 'in', company_ids)]</field> + </record> + <record id="sign_oca_request_signer_rule_company" model="ir.rule"> + <field name="name">Sign Request Signer Company</field> + <field name="model_id" ref="model_sign_oca_request_signer" /> + <field + name="domain_force" + >[('request_id.company_id', 'in', company_ids)]</field> + </record> <!-- User Record Rules --> <record id="sign_oca_request_rule_user_read" model="ir.rule"> <field name="name">Sign Request user: read</field> diff --git a/sign_oca/static/description/index.html b/sign_oca/static/description/index.html index c7ac703d..05956e14 100644 --- a/sign_oca/static/description/index.html +++ b/sign_oca/static/description/index.html @@ -8,11 +8,10 @@ /* :Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $ +:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $ :Copyright: This stylesheet has been placed in the public domain. Default cascading style sheet for the HTML output of Docutils. -Despite the name, some widely supported CSS2 features are used. See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to customize this style sheet. @@ -275,7 +274,7 @@ margin-left: 2em ; margin-right: 2em } -pre.code .ln { color: gray; } /* line numbers */ +pre.code .ln { color: grey; } /* line numbers */ pre.code, code { background-color: #eeeeee } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } @@ -301,7 +300,7 @@ span.pre { white-space: pre } -span.problematic, pre.problematic { +span.problematic { color: red } span.section-subtitle { @@ -369,7 +368,7 @@ <h1 class="title">Sign Oca</h1> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:4cd44f4785da01198064822b367bcbe928fe915080976d5b1f5f2d8671812e51 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/sign/tree/16.0/sign_oca"><img alt="OCA/sign" src="https://img.shields.io/badge/github-OCA%2Fsign-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/sign-16-0/sign-16-0-sign_oca"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/sign&target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p> +<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/sign/tree/17.0/sign_oca"><img alt="OCA/sign" src="https://img.shields.io/badge/github-OCA%2Fsign-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/sign-17-0/sign-17-0-sign_oca"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/sign&target_branch=17.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p> <p>This module allows to create documents for signature inside Odoo using OWL.</p> <p><strong>Table of contents</strong></p> @@ -493,7 +492,7 @@ <h1><a class="toc-backref" href="#toc-entry-10">Bug Tracker</a></h1> <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/sign/issues">GitHub Issues</a>. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -<a class="reference external" href="https://github.com/OCA/sign/issues/new?body=module:%20sign_oca%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p> +<a class="reference external" href="https://github.com/OCA/sign/issues/new?body=module:%20sign_oca%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p> <p>Do not contact contributors directly about support or help with technical issues.</p> </div> <div class="section" id="credits"> @@ -517,15 +516,13 @@ <h2><a class="toc-backref" href="#toc-entry-13">Contributors</a></h2> <div class="section" id="maintainers"> <h2><a class="toc-backref" href="#toc-entry-14">Maintainers</a></h2> <p>This module is maintained by the OCA.</p> -<a class="reference external image-reference" href="https://odoo-community.org"> -<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /> -</a> +<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a> <p>OCA, or the Odoo Community Association, is a nonprofit organization whose mission is to support the collaborative development of Odoo features and promote its widespread use.</p> <p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p> <p><a class="reference external image-reference" href="https://github.com/etobella"><img alt="etobella" src="https://github.com/etobella.png?size=40px" /></a></p> -<p>This module is part of the <a class="reference external" href="https://github.com/OCA/sign/tree/16.0/sign_oca">OCA/sign</a> project on GitHub.</p> +<p>This module is part of the <a class="reference external" href="https://github.com/OCA/sign/tree/17.0/sign_oca">OCA/sign</a> project on GitHub.</p> <p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p> </div> </div> diff --git a/sign_oca/static/src/components/sign_oca_configure/sign_oca_configure.esm.js b/sign_oca/static/src/components/sign_oca_configure/sign_oca_configure.esm.js index ace400de..dfb5c103 100644 --- a/sign_oca/static/src/components/sign_oca_configure/sign_oca_configure.esm.js +++ b/sign_oca/static/src/components/sign_oca_configure/sign_oca_configure.esm.js @@ -1,9 +1,8 @@ /** @odoo-module QWeb **/ -import {Component} from "@odoo/owl"; import {ControlPanel} from "@web/search/control_panel/control_panel"; import {Dialog} from "@web/core/dialog/dialog"; -import {FormRenderer} from "@web/views/form/form_renderer"; +import {isMobileOS} from "@web/core/browser/feature_detection"; import SignOcaPdfCommon from "../sign_oca_pdf_common/sign_oca_pdf_common.esm.js"; import {_t} from "@web/core/l10n/translation"; import {registry} from "@web/core/registry"; @@ -11,16 +10,18 @@ import {renderToString} from "@web/core/utils/render"; export class SignOcaConfigureControlPanel extends ControlPanel {} SignOcaConfigureControlPanel.template = "sign_oca.SignOcaConfigureControlPanel"; -export class SignOcaConfigure extends SignOcaPdfCommon { +export default class SignOcaConfigure extends SignOcaPdfCommon { setup() { + this.res_id = + this.props.action.params.res_id || this.props.action.context.active_id; super.setup(...arguments); this.field_template = "sign_oca.sign_iframe_field_configure"; this.contextMenu = undefined; - this.isMobile = this.env.device.isMobile || this.env.device.isMobileDevice; + this.isMobile = isMobileOS; } postIframeFields() { super.postIframeFields(...arguments); - _.each( + $.each( this.iframe.el.contentDocument.getElementsByClassName("page"), (page) => { page.addEventListener("mousedown", (e) => { @@ -56,26 +57,22 @@ export class SignOcaConfigure extends SignOcaPdfCommon { if (this.contextMenu && !this.creatingItem) { if (this.contextMenu[0].contains(ev.target)) { this.creatingItem = true; - this.env.services - .rpc({ - model: this.props.model, - method: "add_item", - args: [ - [this.props.res_id], - { - field_id: parseInt(ev.target.dataset.field, 10), - page: parseInt(ev.target.dataset.page, 10), - position_x: parseFloat( - ev.target.parentElement.style.left - ), - position_y: parseFloat( - ev.target.parentElement.style.top - ), - width: 20, - height: 1.5, - }, - ], - }) + this.orm + .call(this.model, "add_item", [ + [this.res_id], + { + field_id: parseInt(ev.target.dataset.field, 10), + page: parseInt(ev.target.dataset.page, 10), + position_x: parseFloat( + ev.target.parentElement.style.left + ), + position_y: parseFloat( + ev.target.parentElement.style.top + ), + width: 20, + height: 1.5, + }, + ]) .then((data) => { this.info.items[data.id] = data; this.postIframeField(data); @@ -139,21 +136,17 @@ export class SignOcaConfigure extends SignOcaPdfCommon { var placeholder = dialog.$el .find("input[name='placeholder']") .val(); - this.env.services - .rpc({ - model: this.props.model, - method: "set_item_data", - args: [ - [this.props.res_id], - item.id, - { - field_id, - role_id, - required, - placeholder, - }, - ], - }) + this.orm + .call(this.model, "set_item_data", [ + [this.res_id], + item.id, + { + field_id, + role_id, + required, + placeholder, + }, + ]) .then(() => { item.field_id = field_id; item.name = _.filter( @@ -173,12 +166,11 @@ export class SignOcaConfigure extends SignOcaPdfCommon { classes: "btn-danger", close: true, click: () => { - this.env.services - .rpc({ - model: this.props.model, - method: "delete_item", - args: [[this.props.res_id], item.id], - }) + this.orm + .call(this.model, "delete_item", [ + [this.res_id], + item.id, + ]) .then(() => { delete this.info.items[item.id]; target.remove(); @@ -239,24 +231,21 @@ export class SignOcaConfigure extends SignOcaPdfCommon { target.css("top", top + "%"); item.position_x = left; item.position_y = top; - this.env.services.rpc({ - model: this.props.model, - method: "set_item_data", - args: [ - [this.props.res_id], - item.id, - { - position_x: left, - position_y: top, - }, - ], - }); + + this.orm.call(this.model, "set_item_data", [ + [this.res_id], + item.id, + { + position_x: left, + position_y: top, + }, + ]); this.movingItem = undefined; }, {once: true} ); }); - _.each(resizeItems, (resizeItem) => { + $.each(resizeItems, (resizeItem) => { resizeItem.addEventListener(startFunction, (mousedownEvent) => { mousedownEvent.preventDefault(); var parentPage = mousedownEvent.target.parentElement.parentElement; @@ -304,18 +293,14 @@ export class SignOcaConfigure extends SignOcaPdfCommon { target.css("height", height + "%"); item.width = width; item.height = height; - this.env.services.rpc({ - model: this.props.model, - method: "set_item_data", - args: [ - [this.props.res_id], - item.id, - { - width: width, - height: height, - }, - ], - }); + this.orm.call(this.model, "set_item_data", [ + [this.res_id], + item.id, + { + width: width, + height: height, + }, + ]); }, {once: true} ); @@ -368,34 +353,10 @@ export class SignOcaConfigure extends SignOcaPdfCommon { target.css("top", top + "%"); } } - -export class SignOcaConfigureAction extends Component { - init(parent, action) { - this._super.apply(this, arguments); - this.model = - (action.params.res_model !== undefined && action.params.res_model) || - action.context.params.res_model; - this.res_id = - (action.params.res_id !== undefined && action.params.res_id) || - action.context.params.id; - } - async start() { - await this._super(...arguments); - this.component = new FormRenderer(this, SignOcaConfigure, { - model: this.model, - res_id: this.res_id, - }); - this.$el.addClass("o_sign_oca_action"); - return this.component.mount(this.$(".o_content")[0]); - } - getState() { - var result = this._super(...arguments); - result = _.extend({}, result, { - res_model: this.model, - res_id: this.res_id, - }); - return result; - } -} SignOcaConfigure.template = "sign_oca.SignOcaConfigure"; -registry.category("actions").add("sign_oca_configure", SignOcaConfigureAction); +SignOcaConfigure.props = []; +SignOcaConfigure.props = { + action: Object, + "*": {optional: true}, +}; +registry.category("actions").add("sign_oca_configure", SignOcaConfigure); diff --git a/sign_oca/static/src/components/sign_oca_pdf/sign_oca_pdf.esm.js b/sign_oca/static/src/components/sign_oca_pdf/sign_oca_pdf.esm.js index d15a14a4..fed42860 100644 --- a/sign_oca/static/src/components/sign_oca_pdf/sign_oca_pdf.esm.js +++ b/sign_oca/static/src/components/sign_oca_pdf/sign_oca_pdf.esm.js @@ -2,12 +2,14 @@ import SignOcaPdfCommon from "../sign_oca_pdf_common/sign_oca_pdf_common.esm.js"; import {registry} from "@web/core/registry"; -const SignRegistry = registry.category("sign_oca"); import {renderToString} from "@web/core/utils/render"; +const SignRegistry = registry.category("sign_oca"); +import {useService} from "@web/core/utils/hooks"; export default class SignOcaPdf extends SignOcaPdfCommon { setup() { super.setup(...arguments); + this.orm = useService("orm"); this.to_sign = false; } async willStart() { @@ -63,15 +65,15 @@ export default class SignOcaPdf extends SignOcaPdfCommon { } async signOca() { const position = await this.getLocation(); - await this.env.services.rpc({ - model: this.props.model, - method: "action_sign", - args: [[this.props.res_id], this.info.items], - kwargs: { + await this.orm.call( + this.model, + "action_sign", + [[this.res_id], this.info.items], + { latitude: position && position.coords && position.coords.latitude, longitude: position && position.coords && position.coords.longitude, - }, - }); + } + ); this.props.trigger("history_back"); } _trigger_up(ev) { @@ -127,3 +129,7 @@ export default class SignOcaPdf extends SignOcaPdfCommon { this.checkToSign(); } } +SignOcaPdf.props = { + to_sign: {type: Boolean, optional: true}, +}; +registry.category("actions").add("sign_oca", SignOcaPdf); diff --git a/sign_oca/static/src/components/sign_oca_pdf_common/sign_oca_pdf_common.esm.js b/sign_oca/static/src/components/sign_oca_pdf_common/sign_oca_pdf_common.esm.js index 1adf6bc1..42b1ed74 100644 --- a/sign_oca/static/src/components/sign_oca_pdf_common/sign_oca_pdf_common.esm.js +++ b/sign_oca/static/src/components/sign_oca_pdf_common/sign_oca_pdf_common.esm.js @@ -1,14 +1,16 @@ /** @odoo-module QWeb **/ +import {_t} from "@web/core/l10n/translation"; import {Component, onMounted, onWillStart, onWillUnmount, useRef} from "@odoo/owl"; import {Dialog} from "@web/core/dialog/dialog"; -import {_t} from "@web/core/l10n/translation"; import {renderToString} from "@web/core/utils/render"; +import {useService} from "@web/core/utils/hooks"; export default class SignOcaPdfCommon extends Component { setup() { super.setup(...arguments); + this.model = "sign.oca.template"; + this.orm = useService("orm"); this.field_template = "sign_oca.sign_iframe_field"; - console.log(this.props); this.pdf_url = this.getPdfUrl(); this.viewer_url = "/web/static/lib/pdfjs/web/viewer.html?file=" + this.pdf_url; this.iframe = useRef("sign_oca_iframe"); @@ -30,14 +32,10 @@ export default class SignOcaPdfCommon extends Component { }); } getPdfUrl() { - return "/web/content/" + this.props.model + "/" + this.props.res_id + "/data"; + return "/web/content/" + this.model + "/" + this.res_id + "/data"; } - async willStart() { - this.info = await this.env.services.rpc({ - model: this.props.model, - method: "get_info", - args: [[this.props.res_id]], - }); + willStart() { + this.info = this.orm.call(this.model, "get_info", [[this.res_id]]); } waitIframeLoaded() { var error = this.iframe.el.contentDocument.getElementById("errorWrapper"); @@ -92,7 +90,7 @@ export default class SignOcaPdfCommon extends Component { .getElementsByTagName("head")[0] .append(iframeCss); this.iframe.el.contentDocument.getElementsByTagName("head")[0].append(iframeJs); - _.each(this.info.items, (item) => { + $.each(this.info.items, (item) => { this.postIframeField(item); }); $(this.iframe.el.contentDocument.getElementsByClassName("page")[0]).append( @@ -123,3 +121,4 @@ export default class SignOcaPdfCommon extends Component { } } SignOcaPdfCommon.template = "sign_oca.SignOcaPdfCommon"; +SignOcaPdfCommon.props = []; diff --git a/sign_oca/static/src/components/sign_oca_pdf_common/sign_oca_pdf_common_action.esm.js b/sign_oca/static/src/components/sign_oca_pdf_common/sign_oca_pdf_common_action.esm.js deleted file mode 100644 index 91166329..00000000 --- a/sign_oca/static/src/components/sign_oca_pdf_common/sign_oca_pdf_common_action.esm.js +++ /dev/null @@ -1,36 +0,0 @@ -/** @odoo-module **/ - -import {Component} from "@odoo/owl"; -import {FormRenderer} from "@web/views/form/form_renderer"; -import SignOcaPdfCommon from "./sign_oca_pdf_common.esm.js"; -import {registry} from "@web/core/registry"; - -export class SignOcaPdfCommonAction extends Component { - init(parent, action) { - this._super.apply(this, arguments); - this.model = - (action.params.res_model !== undefined && action.params.res_model) || - action.context.params.res_model; - this.res_id = - (action.params.res_id !== undefined && action.params.res_id) || - action.context.params.id; - } - async start() { - await this._super(...arguments); - this.component = new FormRenderer(this, SignOcaPdfCommon, { - model: this.model, - res_id: this.res_id, - }); - this.$el.addClass("o_sign_oca_action"); - return this.component.mount(this.$(".o_content")[0]); - } - getState() { - var result = this._super(...arguments); - result = _.extend({}, result, { - res_model: this.model, - res_id: this.res_id, - }); - return result; - } -} -registry.category("actions").add("sign_oca_preview", SignOcaPdfCommonAction); diff --git a/sign_oca/static/src/components/sign_oca_pdf_portal/sign_oca_pdf_portal.esm.js b/sign_oca/static/src/components/sign_oca_pdf_portal/sign_oca_pdf_portal.esm.js index a663cd3e..bf19cc66 100644 --- a/sign_oca/static/src/components/sign_oca_pdf_portal/sign_oca_pdf_portal.esm.js +++ b/sign_oca/static/src/components/sign_oca_pdf_portal/sign_oca_pdf_portal.esm.js @@ -1,31 +1,27 @@ /** @odoo-module **/ -const {App, mount, useRef} = owl; +const {App, whenReady, useRef} = owl; +import {_t} from "@web/core/l10n/translation"; +import {makeEnv, startServices} from "@web/env"; import SignOcaPdf from "../sign_oca_pdf/sign_oca_pdf.esm.js"; -import {makeEnv} from "@web/env"; -import {renderToString} from "@web/core/utils/render"; -import {session} from "@web/session"; import {templates} from "@web/core/assets"; +import {useService} from "@web/core/utils/hooks"; export class SignOcaPdfPortal extends SignOcaPdf { setup() { super.setup(...arguments); + this.rpc = useService("rpc"); this.signOcaFooter = useRef("sign_oca_footer"); + this.signer_id = this.props.signer_id; + this.access_token = this.props.access_token; } async willStart() { - this.info = await this.env.services.rpc({ - route: - "/sign_oca/info/" + - this.props.signer_id + - "/" + - this.props.access_token, - }); + this.info = await this.rpc( + "/sign_oca/info/" + this.signer_id + "/" + this.access_token + ); } - getPdfUrl() { - return ( - "/sign_oca/content/" + this.props.signer_id + "/" + this.props.access_token - ); + return "/sign_oca/content/" + this.signer_id + "/" + this.access_token; } checkToSign() { this.to_sign = this.to_sign_update; @@ -41,49 +37,43 @@ export class SignOcaPdfPortal extends SignOcaPdf { } async _onClickSign() { const position = await this.getLocation(); - this.env.services - .rpc({ - route: - "/sign_oca/sign/" + - this.props.signer_id + - "/" + - this.props.access_token, - params: { - items: this.info.items, - latitude: position && position.coords && position.coords.latitude, - longitude: position && position.coords && position.coords.longitude, - }, - }) - .then((action) => { - // As we are on frontend env, it is not possible to use do_action(), so we - // redirect to the corresponding URL or reload the page if the action is not - // an url. - if (action.type === "ir.actions.act_url") { - window.location = action.url; - } else { - window.location.reload(); - } - }); + this.rpc("/sign_oca/sign/" + this.signer_id + "/" + this.access_token, { + items: this.info.items, + latitude: position && position.coords && position.coords.latitude, + longitude: position && position.coords && position.coords.longitude, + }).then((action) => { + // As we are on frontend env, it is not possible to use do_action(), so we + // redirect to the corresponding URL or reload the page if the action is not + // an url. + if (action.type === "ir.actions.act_url") { + window.location = action.url; + } else { + window.location.reload(); + } + }); } } SignOcaPdfPortal.template = "sign_oca.SignOcaPdfPortal"; SignOcaPdfPortal.props = { - access_token: {type: String}, - signer_id: {type: Number}, + access_token: String, + signer_id: Number, }; -export function initDocumentToSign(properties) { - return session.session_bind(session.origin).then(function () { - return Promise.all([ - session.load_translations(["web", "portal", "sign_oca"]), - ]).then(async function () { - var app = new App(null, {templates, test: true}); - renderToString.app = app; - const env = makeEnv(); - mount(SignOcaPdfPortal, document.body, { - env, - props: properties, - templates: templates, - }); - }); + +export async function initDocumentToSign(document, sign_oca_backend_info) { + await whenReady(); + const env = makeEnv(); + await startServices(env); + const app = new App(SignOcaPdfPortal, { + templates, + env: env, + dev: env.debug, + props: { + access_token: sign_oca_backend_info.access_token, + signer_id: sign_oca_backend_info.signer_id, + }, + translateFn: _t, + translatableAttributes: ["data-tooltip"], }); + return app.mount(document.body); } +export default {SignOcaPdfPortal, initDocumentToSign}; diff --git a/sign_oca/static/src/js/ir_model.esm.js b/sign_oca/static/src/js/ir_model.esm.js deleted file mode 100644 index 6c47804f..00000000 --- a/sign_oca/static/src/js/ir_model.esm.js +++ /dev/null @@ -1,21 +0,0 @@ -/** @odoo-module */ - -import {Component} from "@odoo/owl"; -import {registry} from "@web/core/registry"; -import {standardWidgetProps} from "@web/views/widgets/standard_widget_props"; - - -export class IRModelRequest extends Component { - setup() { - super.setup(); - } -} -IRModelRequest.props = { - ...standardWidgetProps, -}; -IRModelRequest.template = "sign_oca.IrModelRequest"; - -export const irModelRequest = { - component: IRModelRequest, -}; -registry.category("view_widgets").add("sign_oca_ir_model_request", irModelRequest); diff --git a/sign_oca/static/src/js/request_group_view.esm.js b/sign_oca/static/src/js/request_group_view.esm.js deleted file mode 100644 index 1f9b357d..00000000 --- a/sign_oca/static/src/js/request_group_view.esm.js +++ /dev/null @@ -1,48 +0,0 @@ -/* @odoo-module */ - -import {Component, onWillUpdateProps, useEffect, useRef, useState} from "@odoo/owl"; - - -/** - * @typedef {Object} Props - * @property {number} threadId - * @property {string} threadModel - * @extends {Component<Props, Env>} - */ -export class RequestGroupView extends Component { - static template = "sign_oca.RequestGroupView"; - static components = {}; - static props = []; - - setup() {} - - onClickFilterButton(ev) { - this.requestMenuViewOwner.update({isOpen: false}); - // Fetch the data from the button otherwise fetch the ones from the parent (.o_ActivityMenuView_activityGroup). - const data = _.extend({}, $(ev.currentTarget).data(), $(ev.target).data()); - const context = {}; - console.log(data); - - this.env.services.action.doAction( - { - context, - name: data.model_name, - res_model: "sign.oca.request.signer", - search_view_id: [false], - type: "ir.actions.act_window", - domain: [ - ["request_id.state", "=", "sent"], - ["partner_id", "child_of", [session.partner_id]], - ["signed_on", "=", false], - ], - views: [ - [false, "list"], - [false, "form"], - ], - }, - { - clearBreadcrumbs: true, - } - ); - } -} diff --git a/sign_oca/static/src/js/request_groups.esm.js b/sign_oca/static/src/js/request_groups.esm.js deleted file mode 100644 index a59cf415..00000000 --- a/sign_oca/static/src/js/request_groups.esm.js +++ /dev/null @@ -1,30 +0,0 @@ -/* @odoo-module */ - -import {Record} from "@mail/core/common/record"; - -export class RequestGroup extends Record { - static pending_count = 0; - /** @returns {import("models").RequestGroup} */ - static get(data) { - return super.get(data); - } - /** @returns {import("models").RequestGroup|import("models").RequestGroup[]} */ - static insert(data) { - return super.insert(...arguments); - } - - /** @type {number} */ - domain; - /** @type {string} */ - type; - /** @type {number} */ - pending_count; - - _onChangePendingCount() { - if (this.pending_count === 0) { - this.delete(); - } - } -} - -RequestGroup.register(); diff --git a/sign_oca/static/src/js/sign_oca.esm.js b/sign_oca/static/src/js/sign_oca.esm.js index 59eeabe6..a384cf3f 100644 --- a/sign_oca/static/src/js/sign_oca.esm.js +++ b/sign_oca/static/src/js/sign_oca.esm.js @@ -7,63 +7,65 @@ import {patch} from "@web/core/utils/patch"; const {onWillStart} = owl; import {useService} from "@web/core/utils/hooks"; -export const patchControllerSignOca = { - setup() { - this._super(...arguments); - this.userService = useService("user"); - this.orm = useService("orm"); - this.action = useService("action"); - this.showSignOcaTemplateGenerateMulti = false; - onWillStart(async () => { - return Promise.all([this._showSignOcaTemplateGenerateMulti()]); - }); - }, - - async _showSignOcaTemplateGenerateMulti() { - var sign_oca_group_user = await this.userService.hasGroup( - "sign_oca.sign_oca_group_user" - ); - if (sign_oca_group_user) { - await this.orm - .call("sign.oca.template", "search_count", [ - [["model", "=", this.props.resModel]], - ]) - .then((templateCount) => { - this.showSignOcaTemplateGenerateMulti = templateCount !== 0; +export function patchControllerSignOca() { + return { + setup() { + super.setup(...arguments); + this.userService = useService("user"); + this.orm = useService("orm"); + this.action = useService("action"); + this.showSignOcaTemplateGenerateMulti = false; + onWillStart(async () => { + return Promise.all([this._showSignOcaTemplateGenerateMulti()]); + }); + }, + async _showSignOcaTemplateGenerateMulti() { + var sign_oca_group_user = await this.userService.hasGroup( + "sign_oca.sign_oca_group_user" + ); + if (sign_oca_group_user) { + await this.orm + .call("sign.oca.template", "search_count", [ + [["model", "=", this.props.resModel]], + ]) + .then((templateCount) => { + this.showSignOcaTemplateGenerateMulti = templateCount !== 0; + }); + } + }, + async _actionSignOcaTemplateGenerateMulti() { + var resIds = ""; + if (this.getSelectedResIds) resIds = await this.getSelectedResIds(); + else resIds = this.model.root.data.id; + this.action.doAction( + "sign_oca.sign_oca_template_generate_multi_act_window", + { + additionalContext: { + model: this.props.resModel, + active_ids: resIds, + }, + on_close: () => { + this.update({}, {reload: false}); + }, + } + ); + }, + getActionMenuItems() { + const menuItems = this._super.apply(this, arguments); + const otherActionItems = menuItems.other; + if (menuItems && this.showSignOcaTemplateGenerateMulti) { + otherActionItems.push({ + key: "sign", + description: _t("Sign from template"), + callback: () => this._actionSignOcaTemplateGenerateMulti(), }); - } - }, - - async _actionSignOcaTemplateGenerateMulti() { - var resIds = ""; - if (this.getSelectedResIds) resIds = await this.getSelectedResIds(); - else resIds = this.model.root.data.id; - this.action.doAction("sign_oca.sign_oca_template_generate_multi_act_window", { - additionalContext: { - model: this.props.resModel, - active_ids: resIds, - }, - on_close: () => { - this.update({}, {reload: false}); - }, - }); - }, - - getActionMenuItems() { - const menuItems = this._super.apply(this, arguments); - const otherActionItems = menuItems.other; - if (menuItems && this.showSignOcaTemplateGenerateMulti) { - otherActionItems.push({ - key: "sign", - description: _t("Sign from template"), - callback: () => this._actionSignOcaTemplateGenerateMulti(), + } + return Object.assign({}, this.props.info.actionMenus, { + other: otherActionItems, }); - } - return Object.assign({}, this.props.info.actionMenus, { - other: otherActionItems, - }); - }, -}; + }, + }; +} -patch(ListController.prototype, patchControllerSignOca); -patch(FormController.prototype, patchControllerSignOca); +patch(ListController.prototype, patchControllerSignOca()); +patch(FormController.prototype, patchControllerSignOca()); diff --git a/sign_oca/static/src/js/signer_menu_container.esm.js b/sign_oca/static/src/js/signer_menu_container.esm.js deleted file mode 100644 index 9aa8f207..00000000 --- a/sign_oca/static/src/js/signer_menu_container.esm.js +++ /dev/null @@ -1,28 +0,0 @@ -/** @odoo-module **/ - -import {registry} from "@web/core/registry"; -/* eslint-disable */ -import SignerMenuView from "./signer_menu_view.esm"; -/* eslint-enable */ - -const {Component} = owl; - -export class SignerMenuContainer extends Component { - /** - * @override - */ - setup() { - super.setup(); - this.env.services.messaging.modelManager.messagingCreatedPromise.then(() => { - this.signerMenuView = - this.env.services.messaging.modelManager.messaging.models.SignerMenuView.insert(); - this.render(); - }); - } -} - -SignerMenuContainer.template = "sign_oca.SignerMenuContainer"; -registry.category("menu").add("SignerMenuContainer", { - Component: SignerMenuView, - props: {record: Object}, -}); diff --git a/sign_oca/static/src/js/signer_menu_view.esm.js b/sign_oca/static/src/js/signer_menu_view.esm.js deleted file mode 100644 index e7b96548..00000000 --- a/sign_oca/static/src/js/signer_menu_view.esm.js +++ /dev/null @@ -1,25 +0,0 @@ -/** @odoo-module **/ - -import {registry} from "@web/core/registry"; -const {Component} = owl; - -export class SignerMenuView extends Component { - /** - * @override - */ - setup() { - super.setup(); - } - /** - * @returns {SignerMenuView} - */ - get signerMenuView() { - return this.props.record; - } -} - -SignerMenuView.template = "sign_oca.SignerMenuView"; -registry.category("menu").add("SignerMenuView", { - Component: SignerMenuView, - props: {record: Object}, -}); diff --git a/sign_oca/static/src/js/systray.esm.js b/sign_oca/static/src/js/systray.esm.js deleted file mode 100644 index 4d334d20..00000000 --- a/sign_oca/static/src/js/systray.esm.js +++ /dev/null @@ -1,103 +0,0 @@ -/** @odoo-module **/ - -import {attr, many} from "@mail/model/model_field"; -import {registerModel} from "@mail/model/model_core"; -import {session} from "@web/session"; - -registerModel({ - name: "SignerMenuView", - lifecycleHooks: { - _created() { - this.fetchData(); - document.addEventListener("click", this._onClickCaptureGlobal, true); - }, - _willDelete() { - document.removeEventListener("click", this._onClickCaptureGlobal, true); - }, - }, - recordMethods: { - close() { - this.update({isOpen: false}); - }, - async fetchData() { - const data = await this.messaging.rpc({ - model: "res.users", - method: "sign_oca_request_user_count", - args: [], - kwargs: {context: session.user_context}, - }); - - this.update({ - requestGroups: data.map((vals) => - this.messaging.models.RequestGroup.convertData(vals) - ), - extraCount: 0, - }); - }, - /** - * @param {MouseEvent} ev - */ - onClickDropdownToggle(ev) { - ev.preventDefault(); - if (this.isOpen) { - this.update({isOpen: false}); - } else { - this.update({isOpen: true}); - this.fetchData(); - } - }, - /** - * Closes the menu when clicking outside, if appropriate. - * - * @private - * @param {MouseEvent} ev - */ - _onClickCaptureGlobal(ev) { - if (!this.exists()) { - return; - } - if (!this.component || !this.component.root.el) { - return; - } - if (this.component.root.el.contains(ev.target)) { - return; - } - this.close(); - }, - }, - fields: { - requestGroups: many("RequestGroup", { - sort: [["smaller-first", "irModel.id"]], - }), - requestGroupViews: many("RequestGroupView", { - compute() { - return this.requestGroups.map((requestGroup) => { - return { - requestGroup, - }; - }); - }, - inverse: "requestMenuViewOwner", - }), - component: attr(), - counter: attr({ - compute() { - return this.requestGroups.reduce( - (total, group) => total + group.pending_count, - this.extraCount - ); - }, - }), - /** - * Determines the number of activities that have been added in the - * system but not yet taken into account in each activity group counter. - * - * @deprecated this field should be replaced by directly updating the - * counter of each group. - */ - extraCount: attr(), - isOpen: attr({ - default: false, - }), - }, -}); diff --git a/sign_oca/static/src/js/systray.js b/sign_oca/static/src/js/systray.js deleted file mode 100644 index 752593f3..00000000 --- a/sign_oca/static/src/js/systray.js +++ /dev/null @@ -1,70 +0,0 @@ -/* @odoo-module */ - -import {Component, onWillUpdateProps, useEffect, useRef, useState} from "@odoo/owl"; - -import {useService} from "@web/core/utils/hooks"; -import {hidePDFJSButtons} from "@web/libs/pdfjs"; - -/** - * @typedef {Object} Props - * @property {number} threadId - * @property {string} threadModel - * @extends {Component<Props, Env>} - */ -export class AttachmentView extends Component { - static template = "mail.AttachmentView"; - static components = {}; - static props = []; - - setup() { - } - - close() { - this.update({isOpen: false}); - } - async fetchData() { - const data = await this.messaging.rpc({ - model: "res.users", - method: "sign_oca_request_user_count", - args: [], - kwargs: {context: session.user_context}, - }); - - this.update({ - requestGroups: data.map((vals) => - this.messaging.models.RequestGroup.convertData(vals) - ), - extraCount: 0, - }); - } - /** - * @param {MouseEvent} ev - */ - onClickDropdownToggle(ev) { - ev.preventDefault(); - if (this.isOpen) { - this.update({isOpen: false}); - } else { - this.update({isOpen: true}); - this.fetchData(); - } - } - /** - * Closes the menu when clicking outside, if appropriate. - * - * @private - * @param {MouseEvent} ev - */ - onClickCaptureGlobal(ev) { - if (!this.exists()) { - return; - } - if (!this.component || !this.component.root.el) { - return; - } - if (this.component.root.el.contains(ev.target)) { - return; - } - this.close(); - } -} diff --git a/sign_oca/static/src/js/systray_service.esm.js b/sign_oca/static/src/js/systray_service.esm.js index 548640c2..67f98b77 100644 --- a/sign_oca/static/src/js/systray_service.esm.js +++ b/sign_oca/static/src/js/systray_service.esm.js @@ -1,18 +1,68 @@ -/** @odoo-module **/ - -import {SignerMenuContainer} from "./signer_menu_container.esm"; - +/* @odoo-module */ +import {Component, useState} from "@odoo/owl"; +import {Dropdown} from "@web/core/dropdown/dropdown"; +import {DropdownItem} from "@web/core/dropdown/dropdown_item"; import {registry} from "@web/core/registry"; - +import {session} from "@web/session"; +import {useDiscussSystray} from "@mail/utils/common/hooks"; +import {useService} from "@web/core/utils/hooks"; const systrayRegistry = registry.category("systray"); - -export const systrayService = { - start() { - systrayRegistry.add( - "sign_oca.SignerMenu", - {Component: SignerMenuContainer}, - {sequence: 99} +export class SignerMenuView extends Component { + setup() { + this.discussSystray = useDiscussSystray(); + this.orm = useService("orm"); + this.store = useState(useService("mail.store")); + this.action = useService("action"); + this.fetchSystraySigner(); + } + async fetchSystraySigner() { + const groups = await this.orm.call("res.users", "sign_oca_request_user_count"); + let total = 0; + for (const group of groups) { + total += group.total_records || 0; + } + this.store.signerCounter = total; + this.store.signerGroups = groups; + } + onBeforeOpen() { + this.fetchSystraySigner(); + } + availableViews() { + return [ + [false, "kanban"], + [false, "list"], + [false, "form"], + [false, "activity"], + ]; + } + onClickFilterButton(group) { + document.body.click(); // Hack to close dropdown + const context = {}; + const views = this.availableViews(); + var domain = [ + ["request_id.state", "=", "sent"], + ["partner_id", "child_of", [session.partner_id]], + ["signed_on", "=", false], + ]; + this.action.doAction( + { + context, + domain, + name: group.name, + res_model: "sign.oca.request.signer", + search_view_id: [false], + type: "ir.actions.act_window", + views, + }, + { + clearBreadcrumbs: true, + } ); - }, -}; -systrayRegistry.add("request_systray_service", systrayService); + } +} + +SignerMenuView.template = "sign_oca.SignerMenu"; +SignerMenuView.components = {Dropdown, DropdownItem}; +SignerMenuView.props = []; +export const systrayItem = {Component: SignerMenuView}; +systrayRegistry.add("sign_oca.SignerMenuView", systrayItem, {sequence: 99}); diff --git a/sign_oca/static/src/xml/signer_menu_container.xml b/sign_oca/static/src/xml/signer_menu_container.xml deleted file mode 100644 index 12b78e9a..00000000 --- a/sign_oca/static/src/xml/signer_menu_container.xml +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<templates xml:space="preserve"> - <t t-name="sign_oca.SignerMenuContainer"> - <t t-if="signerMenuView"> - <SignerMenuView record="signerMenuView" /> - </t> - </t> -</templates> diff --git a/sign_oca/static/src/xml/systray.xml b/sign_oca/static/src/xml/systray.xml index d840bab8..f71df469 100644 --- a/sign_oca/static/src/xml/systray.xml +++ b/sign_oca/static/src/xml/systray.xml @@ -1,86 +1,53 @@ <?xml version="1.0" encoding="UTF-8" ?> <templates> - <t t-name="sign_oca.SignerMenuView"> - <div class="o_ActivityMenuView dropdown" t-ref="root"> - <a - class="o_ActivityMenuView_dropdownToggle dropdown-toggle o-no-caret o-dropdown--narrow" - t-att-aria-expanded="signerMenuView.isOpen ? 'true' : 'false'" - title="Sign Requests" - href="#" - role="button" - t-on-click="signerMenuView.onClickDropdownToggle" - > - <i class="fa fa-pencil" role="img" aria-label="Sign Requests" /> <span - t-if="signerMenuView.counter > 0" - class="o_ActivityMenuView_counter badge" - t-esc="signerMenuView.counter" + <t t-name="sign_oca.SignerMenu"> + <Dropdown + position="'bottom-end'" + beforeOpen.bind="onBeforeOpen" + autoOpen="false" + menuClass="discussSystray.menuClass" + class="discussSystray.class" + > + <t t-set-slot="toggler"> + <i class="fa fa-pencil" role="img" aria-label="Sign Requests" /> + <span + t-if="store.signerCounter > 0" + class="o-mail-ActivityMenu-counter badge rounded-pill" + t-out="store.signerCounter" /> - </a> - <div - t-if="signerMenuView.isOpen" - class="o_ActivityMenuView_dropdownMenu o-dropdown-menu dropdown-menu-end show bg-view" - role="menu" - > - <div class="o_ActivityMenuView_activityGroups"> - <t t-if="signerMenuView.requestGroupViews.length === 0"> - <div - class="o_ActivityMenuView_noActivity dropdown-item-text text-center d-flex justify-content-center" - > - <span>No requests to sign.</span> - </div> - </t> - <t - t-foreach="signerMenuView.requestGroupViews" - t-as="requestGroupView" - t-key="requestGroupView.localId" - name="activityGroupLoop" + </t> + <t t-set-slot="default"> + <div t-att-class="`${discussSystray.contentClass} o-mail-ActivityMenu`"> + <div + t-if="store.signerCounter === 0" + class="o-mail-ActivityMenu-empty align-items-center text-muted p-2 opacity-50 d-flex justify-content-center" > - <div - class="o_ActivityMenuView_activityGroup" - t-att-data-res_model="requestGroupView.requestGroup.irModel.model" - t-att-data-model_name="requestGroupView.requestGroup.irModel.name" - t-att-data-active_field="requestGroupView.requestGroup.irModel.active_field" - t-att-data-domain="requestGroupView.requestGroup.domain" - data-filter='my' - t-att-data-activity-group-view-local-id="requestGroupView.localId" - t-on-click="requestGroupView.onClickFilterButton" + <span>No requests to sign.</span> + </div> + <div class="d-flex flex-column list-group-flush" name="activityGroups"> + <t + t-foreach="store.signerGroups" + t-as="group" + t-key="group_index" + name="activityGroupLoop" > - <div - t-if="requestGroupView.requestGroup.irModel.iconUrl" - class="o_ActivityMenuView_activityGroupIconContainer" + <div + class="o-mail-ActivityGroup list-group-item list-group-item-action d-flex p-2 cursor-pointer" + t-att-data-model_name="group.model" + t-on-click="() => this.onClickFilterButton(group)" > - <img - t-att-src="requestGroupView.requestGroup.irModel.iconUrl" - alt="Requests" - /> - </div> - <div class="o_ActivityMenuView_activityGroupInfo"> - <div class="o_ActivityMenuView_activityGroupTitle"> - <span class="o_ActivityMenuView_activityGroupName"> - <t - t-esc="requestGroupView.requestGroup.irModel.name" - /> - </span> - </div> - <div> - <button - t-if="requestGroupView.requestGroup.pending_count" - type="button" - class="btn btn-link o_activity_filter_button mr16" - t-att-data-res_model="requestGroupView.requestGroup.irModel.model" - t-att-data-model_name="requestGroupView.requestGroup.irModel.name" - data-filter="pending_count" - > - <t - t-esc="requestGroupView.requestGroup.pending_count" - /> - Pending - </button> + <img alt="Requests" t-att-src="group.icon" /> + <div class="flex-grow-1 overflow-hidden"> + <div + class="d-flex px-2" + name="activityTitle" + t-out="group.name" + /> + <div class="d-flex"> <span - t-if="!requestGroupView.requestGroup.pending_count" - class="o_no_activity mr16" - > - 0 Pending + t-attf-class="#{group.total_records ? '' : 'text-muted'} py-0 px-2" + > + <t t-out="group.total_records" /> Pending </span> </div> </div> @@ -88,6 +55,7 @@ </t> </div> </div> - </div> + </t> + </Dropdown> </t> </templates> diff --git a/sign_oca/templates/assets.xml b/sign_oca/templates/assets.xml index 43626804..4111eb39 100644 --- a/sign_oca/templates/assets.xml +++ b/sign_oca/templates/assets.xml @@ -2,23 +2,32 @@ <odoo> <template id="portal_sign_document"> <t t-call="web.layout"> + <t t-set="html_data" t-value="{'lang': sign_oca_backend_info['lang']}" /> <t t-set="head"> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" /> + <input + type="hidden" + name="csrf_token" + t-att-value="request.csrf_token()" + /> <t t-call-assets="web.assets_frontend" t-js="false" /> <t t-call-assets="web.assets_frontend" t-css="false" /> <script type="text/javascript"> - odoo.define("sign.document_portal", function(require) { - var ajax = require("web.ajax"); - var document_signing = require("@sign_oca/components/sign_oca_pdf_portal/sign_oca_pdf_portal.esm"); - document_signing.initDocumentToSign(<t - t-out="json.dumps({'access_token': access_token, 'signer_id': signer.id})" + odoo.define("sign.document_portal", ["@sign_oca/components/sign_oca_pdf_portal/sign_oca_pdf_portal.esm"], function (require) { + var { initDocumentToSign } = require("@sign_oca/components/sign_oca_pdf_portal/sign_oca_pdf_portal.esm"); + initDocumentToSign(document, <t + t-out="json.dumps(sign_oca_backend_info)" />); }); </script> </t> + <t t-set="body"> + </t> + <body class="o_web_client o_portal_sign_document_body"> + </body> </t> </template> <template id="portal_sign_document_signed"> diff --git a/sign_oca/tests/test_sign.py b/sign_oca/tests/test_sign.py index cf977435..6c44dd8f 100644 --- a/sign_oca/tests/test_sign.py +++ b/sign_oca/tests/test_sign.py @@ -5,18 +5,20 @@ import requests -from odoo.modules.module import get_module_resource -from odoo.tests.common import Form, TransactionCase +from odoo.tests.common import Form +from odoo.tools import misc +from odoo.addons.base.tests.common import BaseCommon -class TestSign(TransactionCase): + +class TestSign(BaseCommon): @classmethod def setUpClass(cls): cls._super_send = requests.Session.send super().setUpClass() cls.data = base64.b64encode( open( - get_module_resource("sign_oca", "tests", "empty.pdf"), + misc.file_path(f"{cls.test_module}/tests/empty.pdf"), "rb", ).read() ) @@ -179,10 +181,7 @@ def test_sign_request_role_with_default(self): def test_sign_request_role_with_expression(self): request_form = Form(self.env["sign.oca.request"]) - request_form.record_ref = "%s,%s" % ( - self.partner_child._name, - self.partner_child.id, - ) + request_form.record_ref = f"{self.partner_child._name},{self.partner_child.id}" with request_form.signer_ids.new() as signer: signer.role_id = self.role_child_partner self.assertEqual(signer.partner_id, self.partner) diff --git a/sign_oca/tests/test_sign_portal.py b/sign_oca/tests/test_sign_portal.py index 84a10da6..a14ea51a 100644 --- a/sign_oca/tests/test_sign_portal.py +++ b/sign_oca/tests/test_sign_portal.py @@ -5,19 +5,19 @@ import requests -from odoo.modules.module import get_module_resource from odoo.tests.common import HttpCase, tagged +from odoo.tools import misc @tagged("post_install", "-at_install") -class TestSign(HttpCase): +class TestSignPortal(HttpCase): @classmethod def setUpClass(cls): cls._super_send = requests.Session.send super().setUpClass() cls.data = base64.b64encode( open( - get_module_resource("sign_oca", "tests", "empty.pdf"), + misc.file_path(f"{cls.test_module}/tests/empty.pdf"), "rb", ).read() ) @@ -62,14 +62,16 @@ def test_portal(self): self.assertEqual( base64.b64decode(self.data), self.url_open( - "/sign_oca/content/%s/%s" - % (self.request.signer_ids.id, self.request.signer_ids.access_token) + "/sign_oca/content/{}/{}".format( + self.request.signer_ids.id, self.request.signer_ids.access_token + ) ).content, ) self.assertEqual( self.url_open( - "/sign_oca/info/%s/%s" - % (self.request.signer_ids.id, self.request.signer_ids.access_token), + "/sign_oca/info/{}/{}".format( + self.request.signer_ids.id, self.request.signer_ids.access_token + ), data="{}", headers={"Content-Type": "application/json"}, ).json()["result"]["items"][str(self.item["id"])], diff --git a/sign_oca/wizards/sign_oca_template_generate.xml b/sign_oca/wizards/sign_oca_template_generate.xml index f5d0f1cd..8b570d7c 100644 --- a/sign_oca/wizards/sign_oca_template_generate.xml +++ b/sign_oca/wizards/sign_oca_template_generate.xml @@ -37,7 +37,7 @@ <field name="name">Sign Oca Template Generate</field> <!-- TODO --> <field name="res_model">sign.oca.template.generate</field> <field name="view_mode">form</field> - <field name="context">{'default_template_id': id}</field> + <field name="context">{'default_template_id': active_id}</field> <field name="target">new</field> </record>