[IMP] portal: add a generic signature widget to be used in customer portal

This generic widget allow to confirm and sign documents on the customer
portal. Purpose is to reuse it in sale customer portal and online quotes
notably. It is made generic to call a route using parameters given to the
widget. It also supports access token to ease its use in various customer
portal pages where the customer is not always connected but is granted
access through an access token.
This commit is contained in:
Thibault Delavallée
2017-09-06 10:36:37 +02:00
parent 93436f45f9
commit 27f0d3115e
6 changed files with 168 additions and 1 deletions
+1
View File
@@ -24,5 +24,6 @@ a dependency towards website edition and customization capabilities.""",
],
'qweb': [
'static/src/xml/portal_chatter.xml',
'static/src/xml/portal_signature.xml',
],
}
@@ -0,0 +1,118 @@
odoo.define('portal.signature_form', function (require){
"use strict";
require('web_editor.ready');
var ajax = require('web.ajax');
var base = require('web_editor.base');
var core = require('web.core');
var Widget = require("web.Widget");
var rpc = require("web.rpc");
var qweb = core.qweb;
var SignatureForm = Widget.extend({
template: 'portal.portal_signature',
events: {
'click #o_portal_sign_clear': 'clearSign',
'click .o_portal_sign_submit': 'submitSign',
'init #o_portal_sign_accept': 'initSign',
},
init: function(parent, options) {
this._super.apply(this, arguments);
this.options = _.extend(options || {}, {
csrf_token: odoo.csrf_token,
});
},
willStart: function() {
return this._loadTemplates();
},
start: function() {
this.initSign();
},
// Signature
initSign: function () {
this.$("#o_portal_signature").empty().jSignature({
'decor-color': '#D1D0CE',
'color': '#000',
'background-color': '#fff',
});
this.empty_sign = this.$("#o_portal_signature").jSignature('getData', 'image');
},
clearSign: function () {
this.$("#o_portal_signature").jSignature('reset');
},
submitSign: function (ev) {
ev.preventDefault();
// extract data
var self = this;
var $confirm_btn = self.$el.find('button[type="submit"]');
// process : display errors, or submit
var partner_name = self.$("#o_portal_sign_name").val();
var signature = self.$("#o_portal_signature").jSignature('getData', 'image');
var is_empty = signature ? this.empty_sign[1] === signature[1] : true;
this.$('#o_portal_sign_name').toggleClass('has-error', !partner_name);
this.$('#o_portal_sign_draw').toggleClass('panel-danger', is_empty).toggleClass('panel-default', !is_empty);
if (is_empty || ! partner_name) {
return false;
}
$confirm_btn.prepend('<i class="fa fa-spinner fa-spin"></i> ');
$confirm_btn.attr('disabled', true);
return rpc.query({
route: this.options.callUrl,
params: {
'res_id': this.options.resId,
'access_token': this.options.accessToken,
'partner_name': partner_name,
'signature': signature ? signature[1] : false,
},
}).then(function (data) {
self.$('.fa-spinner').remove();
self.$('#o_portal_sign_accept').prepend('<div>PROUT' + data + '</div>');
if (data.error) {
$confirm_btn.attr('disabled', false);
}
else if (data.success) {
$confirm_btn.remove();
var $prout = qweb.render("portal.portal_signature_success", {widget: data});
self.$('#o_portal_sign_draw').parent().replaceWith($prout);
}
});
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* @private
* @returns {Deferred}
*/
_loadTemplates: function () {
return ajax.loadXML('/portal/static/src/xml/portal_signature.xml', qweb);
},
});
base.ready().then(function () {
$('.o_portal_signature_form').each(function () {
var $elem = $(this);
var form = new SignatureForm(null, $elem.data());
form.appendTo($elem);
});
});
return {
SignatureForm: SignatureForm,
};
});
@@ -0,0 +1,30 @@
<templates id="template" xml:space="preserve">
<t t-name="portal.portal_signature">
<form id="o_portal_sign_accept" method="POST">
<input type="hidden" name="csrf_token" t-att-value="widget.options.csrf_token"/>
<div class="form-group">
<label class="control-label" for="name">Your Name</label>
<input type="text" name="partner_name" id="o_portal_sign_name" class="form-control" t-att-value="widget.options.partnerName"/>
</div>
<div class="panel panel-default mt16 mb0" id="o_portal_sign_draw">
<div class="panel-heading">
<div class="pull-right">
<a id="o_portal_sign_clear" class="btn btn-xs">Clear</a>
</div>
<strong>Draw your signature</strong>
</div>
<div id="o_portal_signature" class="panel-body" style="padding: 0"/>
</div>
<div>
<button type="submit" class="btn btn-primary o_portal_sign_submit">Sign &amp; Confirm</button>
</div>
</form>
</t>
<t t-name="portal.portal_signature_success">
<div class="alert alert-success" role="alert">
<strong>Well done!</strong><br />
<span t-esc="widget.success_msg"/>
<a t-att-href="widget.redirect_url">Click here to see your document.</a>
</div>
</t>
</templates>
+2
View File
@@ -11,6 +11,8 @@
<script type="text/javascript" src="/portal/static/src/js/portal.js"></script>
<script type="text/javascript" src="/portal/static/src/js/portal_tour.js"></script>
<script type="text/javascript" src="/portal/static/src/js/portal_chatter.js"></script>
<script type="text/javascript" src="/portal/static/src/js/portal_signature.js"></script>
<script type="text/javascript" src="/web/static/lib/jSignature/jSignatureCustom.js"></script>
</xpath>
</template>
</odoo>
+17
View File
@@ -354,4 +354,21 @@
</div>
</template>
<!--
Container signature template for frontend
:partner-name string: customer name that signs
:res-model string: model of the signed document
:res-id stringied int: id of the signed document
:call-url string: url to call once clicking on the sign button
:access-token string: access token for customer portal
-->
<template id="portal_signature" name="Ask Signature">
<div t-att-class="'o_portal_signature_form'"
t-att-data-partner-name="partner_name"
t-att-data-res-model="object._name"
t-att-data-res-id="object.id"
t-att-data-call-url="callUrl"
t-att-data-access-token="accessToken"/>
</template>
</odoo>
@@ -3,7 +3,6 @@
<template id="assets_frontend" inherit_id="website.assets_frontend" name="Website Quote frontend assets">
<xpath expr="." position="inside">
<script type="text/javascript" src="/web/static/lib/jSignature/jSignatureCustom.js"></script>
<script type="text/javascript" src="/website_quote/static/src/js/website_quotation.js"></script>
<link rel='stylesheet' href='/website_quote/static/src/css/website_quotation.css'/>
</xpath>