diff options
| author | mgh-odoo <mgh@odoo.com> | 2019-07-10 10:53:10 +0000 |
|---|---|---|
| committer | mgh-odoo <mgh@odoo.com> | 2019-08-14 12:25:12 +0000 |
| commit | 737746c05c832bce918d16c445a84c5d1f9290e4 (patch) | |
| tree | 027cf088a3940e075e99d555e093159f06c01a34 /addons/im_livechat | |
| parent | 3d9abe633282c7eb47b46da0faeab64f98319b38 (diff) | |
[IMP] im_livechat: allow visitors to get a transcript of their live chat
after this commit user can get a copy of the conversation with operator
task-2029660
closes #34620
closes odoo/odoo#35083
Signed-off-by: Martin Geubelle (mge) <mge@openerp.com>
Diffstat (limited to 'addons/im_livechat')
| -rw-r--r-- | addons/im_livechat/__manifest__.py | 1 | ||||
| -rw-r--r-- | addons/im_livechat/controllers/main.py | 6 | ||||
| -rw-r--r-- | addons/im_livechat/data/mail_data.xml | 96 | ||||
| -rw-r--r-- | addons/im_livechat/models/mail_channel.py | 17 | ||||
| -rw-r--r-- | addons/im_livechat/static/src/js/im_livechat.js | 52 | ||||
| -rw-r--r-- | addons/im_livechat/static/src/scss/im_livechat.scss | 14 | ||||
| -rw-r--r-- | addons/im_livechat/static/src/xml/im_livechat.xml | 35 |
7 files changed, 205 insertions, 16 deletions
diff --git a/addons/im_livechat/__manifest__.py b/addons/im_livechat/__manifest__.py index fd5fda2126b..4d988093a94 100644 --- a/addons/im_livechat/__manifest__.py +++ b/addons/im_livechat/__manifest__.py @@ -20,6 +20,7 @@ Help your customers with this chat, and analyse their feedback. """, 'data': [ "data/mail_shortcode_data.xml", + "data/mail_data.xml", "data/im_livechat_channel_data.xml", "security/im_livechat_channel_security.xml", "security/ir.model.access.csv", diff --git a/addons/im_livechat/controllers/main.py b/addons/im_livechat/controllers/main.py index 8e56c2279f3..b90a418f8cd 100644 --- a/addons/im_livechat/controllers/main.py +++ b/addons/im_livechat/controllers/main.py @@ -148,3 +148,9 @@ class LivechatController(http.Controller): Channel = request.env['mail.channel'] channel = Channel.sudo().search([('uuid', '=', uuid)], limit=1) channel.notify_typing(is_typing=is_typing, is_website_user=True) + + @http.route('/im_livechat/email_livechat_transcript', type='json', auth='public', cors="*") + def email_livechat_transcript(self, uuid, email): + channel = request.env['mail.channel'].sudo().search([('uuid', '=', uuid)], limit=1) + if channel: + channel._email_livechat_transcript(email) diff --git a/addons/im_livechat/data/mail_data.xml b/addons/im_livechat/data/mail_data.xml new file mode 100644 index 00000000000..13fe131fb3a --- /dev/null +++ b/addons/im_livechat/data/mail_data.xml @@ -0,0 +1,96 @@ +<?xml version="1.0" encoding="utf-8"?> +<odoo> + <data noupdate="1"> + <template id="livechat_email_template"> +<table border="0" cellpadding="0" cellspacing="0" style="padding-top: 16px; background-color: #F1F1F1; font-family:Verdana, Arial,sans-serif; color: #454748; width: 100%; border-collapse:separate;"><tr><td align="center"> +<table border="0" cellpadding="0" cellspacing="0" width="590" style="padding: 24px; background-color: white; color: #454748; border-collapse:separate;"> +<tbody> + <!-- HEADER --> + <tr> + <td align="center" style="min-width: 590px;"> + <table border="0" cellpadding="0" cellspacing="0" width="100%" style="background-color: white; padding: 0; border-collapse:separate;"> + <tr><td valign="middle"> + <span style="font-size: 10px;">Livechat Conversation</span><br/> + <span style="font-size: 20px; font-weight: bold;"> + <t t-esc="company.name"/> + </span> + </td><td valign="middle" align="right"> + <img t-att-src="'/logo.png?company=%s' % company.id" style="padding: 0px; margin: 0px; height: 48px;" t-att-alt="'%s' % company.name"/> + </td></tr> + <tr><td colspan="2" style="text-align:center;"> + <hr width="100%" style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin:4px 0px 32px 0px;"/> + </td></tr> + </table> + </td> + </tr> + <!-- CONTENT --> + <t t-set="top" t-value="'border-top: thin solid #dee2e6;'" /> + <t t-set="bottom" t-value="'border-bottom: thin solid #dee2e6;'" /> + <t t-set="right" t-value="'border-right: thin solid #dee2e6;'" /> + <t t-set="left" t-value="'border-left: thin solid #dee2e6;'" /> + <tr> + <td style="padding: 0 50px;"> + <div style="font-size: 13px; padding: 10px 0;"> + <span>Hello,</span><br />Here's a copy of your conversation with + <span t-field="channel.livechat_operator_id.name"/>, on the + <span t-field="channel.livechat_channel_id.create_date"/> + </div> + <table cellspacing="0" cellpadding="0" style="width:100%; border-collapse: collapse;"> + <t t-foreach="channel.message_ids.sorted(key=lambda m: m.date)" t-as="message" > + <t t-set="author_name" t-value="message.author_id.name if message.author_id else 'You'" /> + <tr> + <td valign="top" align="center" rowspan="2" t-att-style="'width: 70px;' + top + bottom + left"> + <t t-if="message.author_avatar"> + <img t-attf-alt="{{author_name}}" height="64" width="64" t-attf-src="data:image/png;base64,{{message.author_avatar}}"/> + </t> + <t t-else=""> + <img t-attf-alt="{{author_name}}" height="64" width="64" src="/mail/static/src/img/smiley/avatar.jpg"/> + </t> + </td> + <td t-att-style="'padding-left: 5px; margin: 0px;' + top"> + <strong t-esc="author_name"/> + </td> + <td t-att-style="'font-size: 13px; padding: 5px;' + top + right" align="right"><span t-field="message.date"/></td> + </tr> + <tr> + <td valign="top" colspan="2" t-att-style="'padding-left: 5px;' + bottom + right"> + <span t-field="message.body" style="font-size: 13px;"/> + </td> + </tr> + </t> + </table> + <div style="font-size: 13px; padding: 30px 0;"> + <span>Best regards,</span><br /><br /> + <span t-field="company.name"/> + </div> + </td> + </tr> + <!-- FOOTER --> + <tr> + <td align="center" style="min-width: 590px; padding: 0 8px 0 8px; font-size:11px;"> + <hr width="100%" style="background-color:rgb(204,204,204);border:medium none;clear:both;display:block;font-size:0px;min-height:1px;line-height:0; margin: 16px 0px 4px 0px;"/> + <b t-esc="company.name"/><br/> + <div style="color: #999999;"> + <t t-esc="company.phone"/> + <t t-if="company.email"> | + <a t-att-href="'mailto:%s' % company.email" style="text-decoration:none; color: #999999;"><t t-esc="company.email"/></a> + </t> + <t t-if="company.website"> | + <a t-att-href="'%s' % company.website" style="text-decoration:none; color: #999999;"> + <t t-esc="company.website"/> + </a> + </t> + </div> + </td> + </tr> +</tbody> +</table> +</td></tr> +<!-- POWERED BY --> +<tr><td align="center" style="min-width: 590px;"> + Powered by <a target="_blank" href="https://www.odoo.com?utm_source=db&utm_medium=email" style="color: #875A7B;">Odoo</a> +</td></tr> +</table> + </template> + </data> +</odoo> diff --git a/addons/im_livechat/models/mail_channel.py b/addons/im_livechat/models/mail_channel.py index 7939379ea8c..433c7ff4c53 100644 --- a/addons/im_livechat/models/mail_channel.py +++ b/addons/im_livechat/models/mail_channel.py @@ -159,3 +159,20 @@ class MailChannel(models.Model): def _rating_get_parent_field_name(self): return 'livechat_channel_id' + + def _email_livechat_transcript(self, email): + company = self.env.user.company_id + render_context = { + "company": company, + "channel": self, + } + template = self.env.ref('im_livechat.livechat_email_template') + mail_body = template.render(render_context, engine='ir.qweb', minimal_qcontext=True) + mail_body = self.env['mail.thread']._replace_local_links(mail_body) + mail = self.env['mail.mail'].create({ + 'subject': _('Conversation with %s') % self.livechat_operator_id.name, + 'email_from': self.env.company.email, + 'email_to': email, + 'body_html': mail_body, + }) + mail.send() diff --git a/addons/im_livechat/static/src/js/im_livechat.js b/addons/im_livechat/static/src/js/im_livechat.js index 086f02daa32..44c7dad0f05 100644 --- a/addons/im_livechat/static/src/js/im_livechat.js +++ b/addons/im_livechat/static/src/js/im_livechat.js @@ -410,6 +410,8 @@ var Feedback = Widget.extend({ 'click .o_livechat_rating_choices img': '_onClickSmiley', 'click .o_livechat_no_feedback span': '_onClickNoFeedback', 'click .o_rating_submit_button': '_onClickSend', + 'click .o_email_chat_button': '_onEmailChat', + 'click .o_livechat_email_error .alert-link': '_onTryAgain', }, /** @@ -451,6 +453,15 @@ var Feedback = Widget.extend({ } }); }, + /** + * @private + */ + _showThanksMessage: function () { + this.$('.o_livechat_rating_box').empty().append($('<div />', { + text: _t('Thank you for your feedback'), + class: 'text-muted' + })); + }, //-------------------------------------------------------------------------- // Handlers @@ -466,6 +477,7 @@ var Feedback = Widget.extend({ * @private */ _onClickSend: function () { + this._showThanksMessage(); if (_.isNumber(this.rating)) { this._sendFeedback({ reason: this.$('textarea').val(), close: true }); } @@ -480,14 +492,48 @@ var Feedback = Widget.extend({ this.$('.o_livechat_rating_choices img[data-value="'+this.rating+'"]').addClass('selected'); // only display textearea if bad smiley selected - var shouldCloseChatWindow = false; if (this.rating !== 10) { this.$('.o_livechat_rating_reason').show(); } else { this.$('.o_livechat_rating_reason').hide(); - shouldCloseChatWindow = true; + this._showThanksMessage(); + } + this._sendFeedback({ close: false }); + }, + /** + * @private + */ + _onEmailChat: function () { + var self = this; + var $email = this.$('#o_email'); + + if (utils.is_email($email.val())) { + $email.removeAttr('title').removeClass('is-invalid').prop('disabled', true); + this.$('.o_email_chat_button').prop('disabled', true); + this._rpc({ + route: '/im_livechat/email_livechat_transcript', + params: { + uuid: this._livechat.getUUID(), + email: $email.val(), + } + }).then(function () { + self.$('.o_livechat_email').html($('<strong />', { text: _t('Conversation Sent') })); + }).guardedCatch(function () { + self.$('.o_livechat_email').hide(); + self.$('.o_livechat_email_error').show(); + }); + } else { + $email.addClass('is-invalid').prop('title', _t('Invalid email address')); } - this._sendFeedback({ close: shouldCloseChatWindow }); + }, + /** + * @private + */ + _onTryAgain: function () { + this.$('#o_email').prop('disabled', false); + this.$('.o_email_chat_button').prop('disabled', false); + this.$('.o_livechat_email_error').hide(); + this.$('.o_livechat_email').show(); }, }); diff --git a/addons/im_livechat/static/src/scss/im_livechat.scss b/addons/im_livechat/static/src/scss/im_livechat.scss index 409b6a6726c..9b1142cbefd 100644 --- a/addons/im_livechat/static/src/scss/im_livechat.scss +++ b/addons/im_livechat/static/src/scss/im_livechat.scss @@ -32,17 +32,25 @@ padding: 15px; font-size: 14px; + .o_livechat_email { + font-size: 12px; + > div { + padding: 5px 0; + } + } + .o_livechat_no_feedback { text-decoration: underline; cursor: pointer; + margin: 20px 0; } - .o_livechat_rating_feedback_text { - margin-top: 65px; + .o_livechat_rating_box { + margin: 40px 0 30px 0; } .o_livechat_rating_choices { - margin: 40px 0; + margin: 10px 0; > img { width: 65px; diff --git a/addons/im_livechat/static/src/xml/im_livechat.xml b/addons/im_livechat/static/src/xml/im_livechat.xml index c96f9a05393..c437e87eab0 100644 --- a/addons/im_livechat/static/src/xml/im_livechat.xml +++ b/addons/im_livechat/static/src/xml/im_livechat.xml @@ -4,16 +4,15 @@ <t t-name="im_livechat.FeedBack"> <div class="o_livechat_rating text-center"> - <div class="o_livechat_rating_feedback_text"> - Did we correctly answer your question ? - </div> - <div class="o_livechat_rating_choices"> - <img t-att-src="widget.server_origin + '/rating/static/src/img/rating_10.png'" alt="Good" data-value="10"/> - <img t-att-src="widget.server_origin + '/rating/static/src/img/rating_5.png'" alt="OK" data-value="5"/> - <img t-att-src="widget.server_origin + '/rating/static/src/img/rating_1.png'" alt="Bad" data-value="1" /> - </div> - <div class="o_livechat_no_feedback text-muted"> - <span> I don't want to rate this conversation</span> + <div class="o_livechat_rating_box"> + <div class="o_livechat_rating_feedback_text"> + Did we correctly answer your question ? + </div> + <div class="o_livechat_rating_choices"> + <img t-att-src="widget.server_origin + '/rating/static/src/img/rating_10.png'" alt="Good" data-value="10"/> + <img t-att-src="widget.server_origin + '/rating/static/src/img/rating_5.png'" alt="OK" data-value="5"/> + <img t-att-src="widget.server_origin + '/rating/static/src/img/rating_1.png'" alt="Bad" data-value="1" /> + </div> </div> <div class="o_livechat_rating_reason"> <textarea id="reason" placeholder="Explain your note"></textarea> @@ -21,6 +20,22 @@ <input type="button" class="o_rating_submit_button" value="Send" /> </div> </div> + <div class="o_livechat_email"> + <span class="text-muted">Receive a copy of this conversation</span> + <div class="input-group"> + <input id="o_email" type="text" class="form-control"/> + <button type="button" class="o_email_chat_button btn btn-primary rounded-0"> + <i class="fa fa-paper-plane"/> + </button> + </div> + </div> + <div class="alert alert-danger px-0 o_livechat_email_error" style="display: none;" role="alert"> + Oops! Something went wrong.<br />Please check your internet connection.<br /> + <a href="#" class="alert-link">Try again</a> + </div> + <div class="o_livechat_no_feedback text-muted"> + <span>Close conversation</span> + </div> </div> </t> |
