From 20a7ae2657c4b90512dc24dfaa5e17024e7b37c2 Mon Sep 17 00:00:00 2001 From: David Beguin Date: Fri, 29 Nov 2019 10:29:44 +0000 Subject: [PATCH 1/2] [REF] im_livechat, website_livechat : move close livechat session to base module In order to be able to flag the livechat as inactive when the visitor left the conversation, livechat_active field is moved to im_livechat module, as it is not linked to website_visitor. This commit is also a preparation for next one, which will implement the close conversation right after the first click on x button in livechat window (at visitor side). We needed the livechat_active flag to be available without website installed. Task ID: 2120210 PR #39939 --- addons/im_livechat/controllers/main.py | 10 +++++++ .../im_livechat/models/im_livechat_channel.py | 1 + addons/im_livechat/models/mail_channel.py | 16 +++++++++++ addons/website_livechat/controllers/main.py | 10 ------- .../models/im_livechat_channel.py | 7 ++--- .../website_livechat/models/mail_channel.py | 27 +++++++------------ 6 files changed, 38 insertions(+), 33 deletions(-) diff --git a/addons/im_livechat/controllers/main.py b/addons/im_livechat/controllers/main.py index 41c8c0042dd..99d4a16d60a 100644 --- a/addons/im_livechat/controllers/main.py +++ b/addons/im_livechat/controllers/main.py @@ -158,3 +158,13 @@ class LivechatController(http.Controller): ('uuid', '=', uuid)], limit=1) if channel: channel._email_livechat_transcript(email) + + @http.route('/im_livechat/visitor_leave_session', type='json', auth="public") + def visitor_leave_session(self, uuid): + """ Called when the livechat visitor leaves the conversation. + This will clean the chat request and warn the operator that the conversation is over. + This allows also to re-send a new chat request to the visitor, as while the visitor is + in conversation with an operator, it's not possible to send the visitor a chat request.""" + mail_channel = request.env['mail.channel'].sudo().search([('uuid', '=', uuid)]) + if mail_channel: + mail_channel._close_livechat_session() diff --git a/addons/im_livechat/models/im_livechat_channel.py b/addons/im_livechat/models/im_livechat_channel.py index cb3512ee196..8ccd3f99063 100644 --- a/addons/im_livechat/models/im_livechat_channel.py +++ b/addons/im_livechat/models/im_livechat_channel.py @@ -123,6 +123,7 @@ class ImLivechatChannel(models.Model): channel_partner_to_add.append((4, visitor_user.partner_id.id)) return { 'channel_partner_ids': channel_partner_to_add, + 'livechat_active': True, 'livechat_operator_id': operator_partner_id, 'livechat_channel_id': self.id, 'anonymous_name': False if user_id else anonymous_name, diff --git a/addons/im_livechat/models/mail_channel.py b/addons/im_livechat/models/mail_channel.py index f7276374e13..30ee3699bf5 100644 --- a/addons/im_livechat/models/mail_channel.py +++ b/addons/im_livechat/models/mail_channel.py @@ -33,6 +33,7 @@ class MailChannel(models.Model): anonymous_name = fields.Char('Anonymous Name') channel_type = fields.Selection(selection_add=[('livechat', 'Livechat Conversation')]) + livechat_active = fields.Boolean('Is livechat ongoing?', help='Livechat session is active until visitor leave the conversation.') livechat_channel_id = fields.Many2one('im_livechat.channel', 'Channel') livechat_operator_id = fields.Many2one('res.partner', string='Operator', help="""Operator for this specific channel""") country_id = fields.Many2one('res.country', string="Country", help="Country of the visitor of the channel") @@ -157,6 +158,21 @@ class MailChannel(models.Model): 'info': 'transient_message', }) + def _get_visitor_leave_message(self, operator=False, cancel=False): + return _('Visitor has left the conversation.') + + def _close_livechat_session(self, **kwargs): + """ Set deactivate the livechat channel and notify (the operator) the reason of closing the session.""" + self.ensure_one() + if self.livechat_active: + self.livechat_active = False + # avoid useless notification if the channel is empty + if not self.channel_message_ids: + return + # Notify that the visitor has left the conversation + self.message_post(author_id=self.env.ref('base.partner_root').id, + body=self._get_visitor_leave_message(**kwargs), message_type='comment', subtype_xmlid='mail.mt_comment') + # Rating Mixin def _rating_get_parent_field_name(self): diff --git a/addons/website_livechat/controllers/main.py b/addons/website_livechat/controllers/main.py index 4ab5e56fb61..242d78857f9 100644 --- a/addons/website_livechat/controllers/main.py +++ b/addons/website_livechat/controllers/main.py @@ -65,16 +65,6 @@ class WebsiteLivechat(LivechatController): anonymous_name = visitor_sudo.display_name return super(WebsiteLivechat, self).get_session(channel_id, anonymous_name, previous_operator_id=previous_operator_id, **kwargs) - @http.route('/im_livechat/visitor_leave_session', type='json', auth="public") - def visitor_leave_session(self, uuid): - """ Called when the livechat visitor leaves the conversation. - This will clean the chat request and warn the operator that the conversation is over. - This allows also to re-send a new chat request to the visitor, as while the visitor is - in conversation with an operator, it's not possible to send the visitor a chat request.""" - mail_channel = request.env['mail.channel'].sudo().search([('uuid', '=', uuid)]) - if mail_channel: - mail_channel.close_livechat_request_session() - @http.route('/im_livechat/close_empty_livechat', type='json', auth="public") def close_empty_livechat(self, uuid): """ Called when an operator send a chat request to a visitor but does not speak to him and closes diff --git a/addons/website_livechat/models/im_livechat_channel.py b/addons/website_livechat/models/im_livechat_channel.py index fb1648a9808..6718fd3e48b 100644 --- a/addons/website_livechat/models/im_livechat_channel.py +++ b/addons/website_livechat/models/im_livechat_channel.py @@ -11,15 +11,12 @@ class ImLivechatChannel(models.Model): mail_channel_vals = super(ImLivechatChannel, self)._get_livechat_mail_channel_vals(anonymous_name, operator, user_id=user_id, country_id=country_id) visitor_sudo = self.env['website.visitor']._get_visitor_from_request() if visitor_sudo: - mail_channel_vals.update({ - 'livechat_visitor_id': visitor_sudo.id, - 'livechat_active': True - }) + mail_channel_vals['livechat_visitor_id'] = visitor_sudo.id if not user_id: mail_channel_vals['anonymous_name'] = visitor_sudo.display_name + (' (%s)' % visitor_sudo.country_id.name if visitor_sudo.country_id else '') # As chat requested by the visitor, delete the chat requested by an operator if any to avoid conflicts between two flows chat_request_channel = self.env['mail.channel'].sudo().search([('livechat_visitor_id', '=', visitor_sudo.id), ('livechat_active', '=', True)]) for mail_channel in chat_request_channel: - mail_channel.close_livechat_request_session(type='cancel', speaking_with=operator.name) + mail_channel._close_livechat_session(cancel=True, speaking_with=operator.name) return mail_channel_vals diff --git a/addons/website_livechat/models/mail_channel.py b/addons/website_livechat/models/mail_channel.py index 6f0ddee0fc7..804571bde42 100644 --- a/addons/website_livechat/models/mail_channel.py +++ b/addons/website_livechat/models/mail_channel.py @@ -8,7 +8,6 @@ class MailChannel(models.Model): _inherit = 'mail.channel' livechat_visitor_id = fields.Many2one('website.visitor', string='Visitor') - livechat_active = fields.Boolean('Is livechat ongoing?', help='Livechat session is not considered as active if the visitor left the conversation.') def _execute_channel_pin(self, pinned=False): """ Override to clean an empty livechat channel. @@ -53,23 +52,15 @@ class MailChannel(models.Model): recent_history = self.env['website.track'].search([('page_id', '!=', False), ('visitor_id', '=', visitor.id)], limit=3) return ' → '.join(visit.page_id.name + ' (' + visit.visit_datetime.strftime('%H:%M') + ')' for visit in reversed(recent_history)) - def close_livechat_request_session(self, type='leave', **kwargs): - """ Set deactivate the livechat channel and notify (the operator) the reason of closing the session.""" - self.ensure_one() - if self.livechat_active: - self.livechat_active = False - # avoid useless notification if the channel is empty - if not self.channel_message_ids: - return - # Notify that the visitor has left the conversation - name = _('The visitor') if not self.livechat_visitor_id else self.livechat_visitor_id.display_name - if type == 'cancel': - message = _('has started a conversation with %s. The chat request has been canceled.') % kwargs.get('speaking_with', 'an operator') - else: - message = _('has left the conversation.') - leave_message = '%s %s' % (name, message) - self.message_post(author_id=self.env.ref('base.user_root').sudo().partner_id.id, - body=leave_message, message_type='comment', subtype_xmlid='mail.mt_comment') + def _get_visitor_leave_message(self, operator=False, cancel=False): + name = _('The visitor') if not self.livechat_visitor_id else self.livechat_visitor_id.display_name + if cancel: + message = _("""%s has started a conversation with %s. + The chat request has been canceled.""") % (name, operator or _('an operator')) + else: + message = _('%s has left the conversation.') % name + + return message def message_post(self, **kwargs): """Override to mark the visitor as still connected. From 6f2865e456d4e04ee8e72806481c8e9ab6f23bbc Mon Sep 17 00:00:00 2001 From: David Beguin Date: Fri, 29 Nov 2019 09:52:11 +0000 Subject: [PATCH 2/2] [IMP] im_livechat : set livechat inactive _onCloseChatWindow If the visitor closes the livechat window, he is redirected on rating / feedback / send_transcript screen but he cannot go back to the conversation, except by reloading the whole page. Conversation should then be considered as inactive after the first click on X. This commit close the conversation (set as livechat inactive and send the 'has left conversation' message) at first time the visitor closes the conversation. Task ID: 2120210 PR #39939 --- .../website_livechat/static/src/js/im_livechat.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/addons/website_livechat/static/src/js/im_livechat.js b/addons/website_livechat/static/src/js/im_livechat.js index 6b64318732e..1527057b259 100644 --- a/addons/website_livechat/static/src/js/im_livechat.js +++ b/addons/website_livechat/static/src/js/im_livechat.js @@ -25,21 +25,17 @@ LivechatButton.include({ /** * @override - * Called when the visitor closes the livechat chatter - * (no matter the way : close, send feedback, ..) + * Called when the visitor closes the livechat chatter the first time (first click on X button) * this will deactivate the mail_channel, clean the chat request if any * and allow the operators to send the visitor a new chat request */ - _closeChat: function () { - var self = this; + _onCloseChatWindow: function (ev) { + this._super(ev); var cookie = utils.get_cookie('im_livechat_session'); if (cookie) { var channel = JSON.parse(cookie); - var ready = session.rpc('/im_livechat/visitor_leave_session', {uuid: channel.uuid}); - ready.then(self._super()); - } - else { - this._super(); + session.rpc('/im_livechat/visitor_leave_session', {uuid: channel.uuid}); + utils.set_cookie('im_livechat_session', "", -1); // remove cookie } }, });