diff --git a/addons/mail/static/src/js/activity.js b/addons/mail/static/src/js/activity.js
index 0b9cfbff599..fd3b13391ac 100644
--- a/addons/mail/static/src/js/activity.js
+++ b/addons/mail/static/src/js/activity.js
@@ -377,6 +377,7 @@ var BasicActivity = AbstractField.extend({
this.$('.o_activity_selected').removeClass('o_activity_selected');
$actLi.toggleClass('o_activity_selected');
$panel.collapse('toggle');
+ $panel.find('#activity_feedback').focus();
} else if (!$markDoneBtn.data('bs.popover')) {
$markDoneBtn.popover({
@@ -418,6 +419,11 @@ var BasicActivity = AbstractField.extend({
_onMarkActivityDoneActions: function ($btn, $form, activityID) {
var self = this;
$form.find('#activity_feedback').val(self._draftFeedback[activityID]);
+ $form.on('keydown', '#activity_feedback', function (ev) {
+ if (ev.key === 'Enter') {
+ ev.stopPropagation(); // Prevent list view actions
+ }
+ });
$form.on('click', '.o_activity_popover_done', function (ev) {
ev.stopPropagation();
self._markActivityDone({
@@ -425,6 +431,16 @@ var BasicActivity = AbstractField.extend({
feedback: $form.find('#activity_feedback').val(),
});
});
+ $form.on('keydown', '.o_activity_popover_done', function (ev) {
+ if (ev.key === 'Enter') {
+ ev.stopPropagation(); // Prevent list view actions
+ ev.preventDefault();
+ self._markActivityDone({
+ activityID,
+ feedback: $form.find('#activity_feedback').val(),
+ });
+ }
+ });
$form.on('click', '.o_activity_popover_done_next', function (ev) {
ev.stopPropagation();
self._markActivityDoneAndScheduleNext({
@@ -432,6 +448,16 @@ var BasicActivity = AbstractField.extend({
feedback: $form.find('#activity_feedback').val(),
});
});
+ $form.on('keydown', '.o_activity_popover_done_next', function (ev) {
+ if (ev.key === 'Enter') {
+ ev.stopPropagation(); // Prevent list view actions
+ ev.preventDefault();
+ self._markActivityDoneAndScheduleNext({
+ activityID,
+ feedback: $form.find('#activity_feedback').val(),
+ });
+ }
+ });
$form.on('click', '.o_activity_popover_discard', function (ev) {
ev.stopPropagation();
if ($btn.data('bs.popover')) {
diff --git a/addons/mail/static/tests/helpers/mock_server.js b/addons/mail/static/tests/helpers/mock_server.js
index 58302ad8a60..72b78722633 100644
--- a/addons/mail/static/tests/helpers/mock_server.js
+++ b/addons/mail/static/tests/helpers/mock_server.js
@@ -154,6 +154,14 @@ MockServer.include({
return;
}
// mail.activity methods
+ if (args.model === 'mail.activity' && args.method === 'action_feedback') {
+ const ids = args.args[0];
+ return this._mockMailActivityActionFeedback(ids);
+ }
+ if (args.model === 'mail.activity' && args.method === 'action_feedback_schedule_next') {
+ const ids = args.args[0];
+ return this._mockMailActivityActionFeedbackScheduleNext(ids);
+ }
if (args.model === 'mail.activity' && args.method === 'activity_format') {
const ids = args.args[0];
return this._mockMailActivityActivityFormat(ids);
@@ -635,6 +643,47 @@ MockServer.include({
return res;
});
},
+ /**
+ * Simulates `_action_done` on `mail.activity`.
+ *
+ * @private
+ * @param {string} model
+ * @param {integer[]} ids
+ * @returns {Object}
+ */
+ _mockMailActivityActionDone(ids) {
+ const activities = this.getRecords('mail.activity', [['id', 'in', ids]]);
+ this._mockUnlink('mail.activity', [activities.map(activity => activity.id)]);
+ },
+ /**
+ * Simulates `action_feedback` on `mail.activity`.
+ *
+ * @private
+ * @param {string} model
+ * @param {integer[]} ids
+ * @returns {Object}
+ */
+ _mockMailActivityActionFeedback(ids) {
+ this._mockMailActivityActionDone(ids);
+ },
+ /**
+ * Simulates `action_feedback_schedule_next` on `mail.activity`.
+ *
+ * @private
+ * @param {string} model
+ * @param {integer[]} ids
+ * @returns {Object}
+ */
+ _mockMailActivityActionFeedbackScheduleNext(ids) {
+ this._mockMailActivityActionDone(ids);
+ return {
+ name: 'Schedule an Activity',
+ view_mode: 'form',
+ res_model: 'mail.activity',
+ views: [[false, 'form']],
+ type: 'ir.actions.act_window',
+ }
+ },
/**
* Simulates `get_activity_data` on `mail.activity`.
*
diff --git a/addons/mail/static/tests/qunit_suite_tests/chatter_tests.js b/addons/mail/static/tests/qunit_suite_tests/chatter_tests.js
index 3f320f48774..5ed2fc831bc 100644
--- a/addons/mail/static/tests/qunit_suite_tests/chatter_tests.js
+++ b/addons/mail/static/tests/qunit_suite_tests/chatter_tests.js
@@ -252,6 +252,100 @@ QUnit.test('list activity exception widget with activity', async function (asser
"there is an exception on a record");
});
+QUnit.test('list activity widget: done the activity with "ENTER" keyboard shortcut', async function (assert) {
+ assert.expect(1);
+
+ const pyEnv = await startServer();
+ const mailActivityTypeId1 = pyEnv['mail.activity.type'].create();
+ const mailActivityId1 = pyEnv['mail.activity'].create([
+ {
+ display_name: "Call with Al",
+ date_deadline: moment().format("YYYY-MM-DD"), // now
+ can_write: true,
+ state: "today",
+ user_id: pyEnv.currentUserId,
+ create_uid: pyEnv.currentUserId,
+ activity_type_id: mailActivityTypeId1,
+ }
+ ]);
+ pyEnv['res.users'].write([pyEnv.currentUserId], {
+ activity_ids: [mailActivityId1],
+ activity_state: 'today',
+ activity_summary: 'Call with Al',
+ activity_type_id: mailActivityTypeId1,
+ });
+
+ const { target: list } = await start({
+ hasView: true,
+ View: ListView,
+ model: 'res.users',
+ arch: `
+
+
+
`,
+ });
+
+ await testUtils.dom.click(list.querySelector('.o_activity_btn span'));
+ await testUtils.dom.click(list.querySelector('.o_mark_as_done'));
+ pyEnv['res.users'].write([pyEnv.currentUserId], {
+ activity_state: '',
+ });
+ await testUtils.dom.triggerEvent(
+ document.querySelector('.o_activity_popover_done'),
+ 'keydown',
+ { key: 'Enter' },
+ );
+
+ assert.containsOnce(list, '.o_mail_activity .o_activity_color_default');
+});
+
+QUnit.test('list activity widget: done and schedule the next activity with "ENTER" keyboard shortcut', async function (assert) {
+ assert.expect(1);
+
+ const pyEnv = await startServer();
+ const mailActivityTypeId1 = pyEnv['mail.activity.type'].create();
+ const mailActivityId1 = pyEnv['mail.activity'].create([
+ {
+ display_name: "Call with Al",
+ date_deadline: moment().format("YYYY-MM-DD"), // now
+ can_write: true,
+ state: "today",
+ user_id: pyEnv.currentUserId,
+ create_uid: pyEnv.currentUserId,
+ activity_type_id: mailActivityTypeId1,
+ }
+ ]);
+ pyEnv['res.users'].write([pyEnv.currentUserId], {
+ activity_ids: [mailActivityId1],
+ activity_state: 'today',
+ activity_summary: 'Call with Al',
+ activity_type_id: mailActivityTypeId1,
+ });
+
+ const { target: list } = await start({
+ hasView: true,
+ View: ListView,
+ model: 'res.users',
+ arch: `
+
+
+
`,
+ intercepts: {
+ do_action: function (ev) {
+ assert.strictEqual(ev.data.action.name, "Schedule an Activity", 'should do a do_action with correct parameters');
+ },
+ },
+ });
+
+ await testUtils.dom.click(list.querySelector('.o_activity_btn span'));
+ await testUtils.dom.click(list.querySelector('.o_mark_as_done'));
+ await testUtils.dom.triggerEvent(
+ document.querySelector('.o_activity_popover_done_next'),
+ 'keydown',
+ { key: 'Enter' },
+ );
+});
+
QUnit.module('FieldMany2ManyTagsEmail');
QUnit.test('fieldmany2many tags email (edition)', async function (assert) {