[IMP] mail: activity keyboard navigation improvement
PURPOSE Improve some mail activity issues regarding keyboard navigation. SPECIFICATIONS When done an activity using the record list view, allowing user ENTER key support on "Done" or "Done and Schedule Next" button to post feedback and mark the activity as done. Task-2528109 closes odoo/odoo#82879 Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
@@ -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')) {
|
||||
|
||||
@@ -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`.
|
||||
*
|
||||
|
||||
@@ -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: `
|
||||
<list>
|
||||
<field name="activity_ids" widget="list_activity"/>
|
||||
</list>`,
|
||||
});
|
||||
|
||||
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: `
|
||||
<list>
|
||||
<field name="activity_ids" widget="list_activity"/>
|
||||
</list>`,
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user