From bb1289097777a4fa44e76d5c8640a48808835279 Mon Sep 17 00:00:00 2001 From: "Lucas Perais (lpe)" Date: Fri, 10 Aug 2018 15:27:33 +0200 Subject: [PATCH] [FIX] mail: activity don't loose text of feedback popover On an activity, click Mark as done, the popover pops over Now write some text in it, but click somewhere else, like to copy/paste something The popover looses focus, and your text disappears After this commit, we store the value of the popover when hiding it, then, when when showing back the popover, the value is reinjected OPW 1873999 closes #26315 --- addons/mail/static/src/js/activity.js | 35 +++++++++--- addons/mail/static/tests/chatter_tests.js | 70 +++++++++++++++++++++++ 2 files changed, 97 insertions(+), 8 deletions(-) diff --git a/addons/mail/static/src/js/activity.js b/addons/mail/static/src/js/activity.js index ceb182c6038..3c7e491edeb 100644 --- a/addons/mail/static/src/js/activity.js +++ b/addons/mail/static/src/js/activity.js @@ -186,6 +186,28 @@ var Activity = AbstractActivityField.extend({ this.trigger_up('reload_mail_fields', fieldsToReload); }, + /** Binds a focusout handler on a bootstrap popover + * Useful to do some operations on the popover's HTML, + * like keeping the user's input for the feedback + * @param {JQuery} $popover_el: the element on which + * the popover() method has been called + */ + _bindPopoverFocusout: function ($popover_el) { + var self = this; + // Retrieve the actual popover's HTML + var $popover = $popover_el.data("bs.popover").tip(); + var activity_id = $popover_el.data('activity-id'); + $popover.off('focusout'); + $popover.focusout(function (e) { + // outside click of popover hides the popover + // e.relatedTarget is the element receiving the focus + self.feedbackValue[activity_id] = $popover.find('#activity_feedback').val().trim(); + if(!$popover.is(e.relatedTarget) && !$popover.find(e.relatedTarget).length) { + $popover_el.popover('hide'); + } + }); + }, + // handlers _onEditActivity: function (event, options) { event.preventDefault(); @@ -224,19 +246,23 @@ var Activity = AbstractActivityField.extend({ }) .then(this._reload.bind(this, {activity: true})); }, + _onMarkActivityDone: function (event) { event.preventDefault(); var self = this; + this.feedbackValue = this.feedbackValue || {}; var $popover_el = $(event.currentTarget); var activity_id = $popover_el.data('activity-id'); var previous_activity_type_id = $popover_el.data('previous-activity-type-id'); if (!$popover_el.data('bs.popover')) { + this.feedbackValue[activity_id] = ""; $popover_el.popover({ title : _t('Feedback'), html: 'true', trigger:'click', content : function() { var $popover = $(QWeb.render("mail.activity_feedback_form", {'previous_activity_type_id': previous_activity_type_id})); + $popover.find('#activity_feedback').val(self.feedbackValue[activity_id]); $popover.on('click', '.o_activity_popover_done_next', function () { var feedback = _.escape($popover.find('#activity_feedback').val()); var previous_activity_type_id = $popover_el.data('previous-activity-type-id'); @@ -260,14 +286,7 @@ var Activity = AbstractActivityField.extend({ }).on("shown.bs.popover", function () { var $popover = $(this).data("bs.popover").tip(); $popover.find('#activity_feedback').focus(); - $popover.off('focusout'); - $popover.focusout(function (e) { - // outside click of popover hide the popover - // e.relatedTarget is the element receiving the focus - if(!$popover.is(e.relatedTarget) && !$popover.find(e.relatedTarget).length) { - $popover.popover('hide'); - } - }); + self._bindPopoverFocusout($(this)); }).popover('show'); } }, diff --git a/addons/mail/static/tests/chatter_tests.js b/addons/mail/static/tests/chatter_tests.js index 5c986273ad7..c2df3a2eb46 100644 --- a/addons/mail/static/tests/chatter_tests.js +++ b/addons/mail/static/tests/chatter_tests.js @@ -14,6 +14,8 @@ var BasicComposer = Composers.BasicComposer; var createAsyncView = testUtils.createAsyncView; var createView = testUtils.createView; +var Activity = require('mail.Activity'); + QUnit.module('mail', {}, function () { QUnit.module('Chatter', { @@ -68,6 +70,7 @@ QUnit.module('Chatter', { type: 'selection', selection: [['overdue', 'Overdue'], ['today', 'Today'], ['planned', 'Planned']], }, + note : { string: "Note", type: "char" }, }, }, 'mail.activity.type': { @@ -160,6 +163,73 @@ QUnit.test('basic rendering', function (assert) { form.destroy(); }); +QUnit.test('Activity Done keep feedback on blur', function (assert) { + assert.expect(3); + var done = assert.async(); + + this.data['mail.activity'].records = [ + {activity_type_id: 1, id: 1, user_id: 2, state: 'today', note: 'But I\'m talkin\' about Shaft'}, + ]; + this.data.partner.records[0].activity_ids = [1]; + + var shownDef = $.Deferred(); + var hiddenDef = $.Deferred(); + testUtils.patch(Activity, { + _bindPopoverFocusout: function () { + this._super.apply(this, arguments); + shownDef.resolve(); + }, + }); + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + res_id: 2, + arch:'
' + + '
' + + '' + + '
' + + '
', + }); + + // sanity checks + var $activityEl = form.$('.o_mail_activity[name=activity_ids]'); + assert.strictEqual($activityEl.find('.o_thread_message').length, 1, + 'There should be one activity'); + assert.strictEqual($activityEl.find('.o_thread_message .o_thread_message_note').text().trim(), + 'But I\'m talkin\' about Shaft', 'The activity should have the right note'); + + var $popoverEl = $activityEl.find('.o_thread_message_tools .o_activity_done'); + $popoverEl.on('hidden.bs.popover', hiddenDef.resolve.bind(hiddenDef)); + + // open popover + $popoverEl.click(); + + shownDef.then(function () { + // write a feedback and focusout + var $feedbackPopover = $popoverEl.data('bs.popover').tip(); + $feedbackPopover.find('#activity_feedback').val('John Shaft').focusout(); + + hiddenDef.then(function () { + shownDef = $.Deferred(); + + // re-open popover + $popoverEl.click(); + + shownDef.then(function () { + var $feedbackPopover = $popoverEl.data('bs.popover').tip(); + assert.strictEqual($feedbackPopover.find('#activity_feedback').val(), 'John Shaft', + "feedback should have been kept"); + + form.destroy(); + testUtils.unpatch(Activity); + done(); + }); + }); + }); +}); + QUnit.test('chatter is not rendered in mode === create', function (assert) { assert.expect(4);