diff options
| author | XavierDo <xdo@odoo.com> | 2018-08-14 13:31:45 +0200 |
|---|---|---|
| committer | RomainLibert <rli@odoo.com> | 2018-08-20 16:00:09 +0200 |
| commit | 0be33db68a201ab71f5e1deaac31945b95649546 (patch) | |
| tree | fbc08a20e7de11a6bd10f9f711c61d49168d4b44 /addons/mail/static | |
| parent | c90ff2afd8b129eaa5bd451728d4c6c99a7db89d (diff) | |
[IMP] mail: refactor activity.js and add some test
activity.js was a little dirty with a lot of copy paste.
Most of the common logic is now in a BasicModel.
This commit also add some tests on activity view
Co-authored-by: RomainLibert <rli@odoo.com>
Diffstat (limited to 'addons/mail/static')
| -rw-r--r-- | addons/mail/static/src/js/activity.js | 493 | ||||
| -rw-r--r-- | addons/mail/static/src/js/chatter.js | 2 | ||||
| -rw-r--r-- | addons/mail/static/src/scss/mail_activity.scss | 2 | ||||
| -rw-r--r-- | addons/mail/static/src/xml/activity.xml | 8 | ||||
| -rw-r--r-- | addons/mail/static/src/xml/web_kanban_activity.xml | 2 | ||||
| -rw-r--r-- | addons/mail/static/tests/activity_tests.js | 316 | ||||
| -rw-r--r-- | addons/mail/static/tests/chatter_tests.js | 8 | ||||
| -rw-r--r-- | addons/mail/static/tests/helpers/mock_server.js | 11 |
8 files changed, 526 insertions, 316 deletions
diff --git a/addons/mail/static/src/js/activity.js b/addons/mail/static/src/js/activity.js index 8f4c6b1e7c7..718bab81fac 100644 --- a/addons/mail/static/src/js/activity.js +++ b/addons/mail/static/src/js/activity.js @@ -40,10 +40,8 @@ function _readActivities(self, ids) { activity.create_date = moment(time.auto_str_to_date(activity.create_date)); activity.date_deadline = moment(time.auto_str_to_date(activity.date_deadline)); }); - - // sort activities by due date + // sort activities by due date activities = _.sortBy(activities, 'date_deadline'); - return activities; }); } @@ -103,7 +101,32 @@ var setDelayLabel = function (activities){ return activities; }; -var AbstractActivityField = AbstractField.extend({ +var BasicActivity = AbstractField.extend({ + events: { + 'click .o_edit_activity': '_onEditActivity', + 'click .o_mark_as_done': '_onMarkActivityDone', + 'click .o_activity_template_preview': '_onPreviewMailTemplate', + 'click .o_schedule_activity': '_onScheduleActivity', + 'click .o_activity_template_send': '_onSendMailTemplate', + 'click .o_unlink_activity': '_onUnlinkActivity', + }, + init: function () { + this._super.apply(this, arguments); + this._draftFeedback = {}; + }, + + //------------------------------------------------------------ + // Public + //------------------------------------------------------------ + + /** + * @param {integer} previousActivityTypeID + * @return {$.Promise} + */ + scheduleActivity: function () { + var callback = this._reload.bind(this, { activity: true, thread: true }); + return this._openActivityForm(false, callback); + }, //------------------------------------------------------------ // Private @@ -159,9 +182,9 @@ var AbstractActivityField = AbstractField.extend({ * @param {integer} id * @param {integer} previousActivityTypeID * @param {function} callback - * @return {$.Promise} + * @return {$.Deferred} */ - _scheduleActivity: function (id, previousActivityTypeID, callback) { + _openActivityForm: function (id, callback) { var action = { type: 'ir.actions.act_window', res_model: 'mail.activity', @@ -172,7 +195,6 @@ var AbstractActivityField = AbstractField.extend({ context: { default_res_id: this.res_id, default_res_model: this.model, - default_previous_activity_type_id: previousActivityTypeID, }, res_id: id || false, }; @@ -193,43 +215,173 @@ var AbstractActivityField = AbstractField.extend({ context: this.record.getContext(), }); }, + + //------------------------------------------------------------ + // Handlers + //------------------------------------------------------------ + + /** + * @private + * @param {MouseEvent} ev + * @returns {$.Promise} + */ + _onEditActivity: function (ev) { + ev.preventDefault(); + var activityID = $(ev.currentTarget).data('activity-id'); + return this._openActivityForm(activityID, this._reload.bind(this)); + }, + /** + * Called when marking an activity as done + * + * It lets the current user write a feedback in a popup menu. + * After writing the feedback and confirm mark as done + * is sent, it marks this activity as done for good with the feedback linked + * to it. + * + * @private + * @param {MouseEvent} ev + */ + _onMarkActivityDone: function (ev) { + ev.stopPropagation(); + ev.preventDefault(); + var self = this; + var $popoverElement = $(ev.currentTarget); + var activityID = $popoverElement.data('activity-id'); + var previousActivityTypeID = $popoverElement.data('previous-activity-type-id'); + if (!$popoverElement.data('bs.popover')) { + $popoverElement.popover({ + template: $(Popover.Default.template).addClass('o_mail_activity_feedback')[0].outerHTML, // Ugly but cannot find another way + container: $popoverElement, + title : _t("Feedback"), + html: true, + trigger:'click', + placement: 'right', // FIXME: this should work, maybe a bug in the popper lib + content : function () { + var $popover = $(QWeb.render('mail.activity_feedback_form', { previous_activity_type_id: previousActivityTypeID })); + $popover.find('#activity_feedback').val(self._draftFeedback[activityID]); + $popover.on('click', '.o_activity_popover_done', function (ev) { + ev.stopPropagation(); + self._markActivityDone({ + activityID: activityID, + feedback: _.escape($popover.find('#activity_feedback').val()), + }); + }); + $popover.on('click', '.o_activity_popover_done_next', function (ev) { + ev.stopPropagation(); + self._markActivityDoneAndScheduleNext({ + activityID: activityID, + feedback: _.escape($popover.find('#activity_feedback').val()), + }); + }); + $popover.on('click', '.o_activity_popover_discard', function (ev) { + ev.stopPropagation(); + $popoverElement.popover('hide'); + }); + return $popover; + }, + }).on('shown.bs.popover', function () { + var $popover = $($(this).data("bs.popover").tip); + $(".o_mail_activity_feedback.popover").not($popover).popover("hide"); + $popover.addClass('o_mail_activity_feedback').attr('tabindex', 0); + $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) { + self._draftFeedback[activityID] = $popover.find('#activity_feedback').val(); + $popover.popover('hide'); + } + }); + }).popover('show'); + } + }, + /** + * @private + * @param {MouseEvent} ev + * @returns {$.Deferred} + */ + _onPreviewMailTemplate: function (ev) { + ev.stopPropagation(); + var templateID = $(ev.currentTarget).data('template-id'); + var action = { + name: _t('Compose Email'), + type: 'ir.actions.act_window', + res_model: 'mail.compose.message', + views: [[false, 'form']], + target: 'new', + context: { + default_res_id: this.res_id, + default_model: this.model, + default_use_template: true, + default_template_id: templateID, + force_email: true, + }, + }; + return this.do_action(action, { on_close: function () {} }); + }, + /** + * @private + * @param {MouseEvent} ev + * @returns {$.Promise} + */ + _onSendMailTemplate: function (ev) { + ev.stopPropagation(); + var templateID = $(ev.currentTarget).data('template-id'); + return this._rpc({ + model: this.model, + method: 'activity_send_mail', + args: [[this.res_id], templateID], + }) + .then(this._reload.bind(this, {activity: true, thread: true, followers: true})); + }, + /** + * @private + * @param {MouseEvent} ev + * @returns {$.Deferred} + */ + _onScheduleActivity: function (ev) { + ev.preventDefault(); + return this._openActivityForm(false, this._reload.bind(this)); + }, + + /** + * @private + * @param {MouseEvent} ev + * @param {Object} options + * @returns {$.Promise} + */ + _onUnlinkActivity: function (ev, options) { + ev.preventDefault(); + var activityID = $(ev.currentTarget).data('activity-id'); + options = _.defaults(options || {}, { + model: 'mail.activity', + args: [[activityID]], + }); + return this._rpc({ + model: options.model, + method: 'unlink', + args: options.args, + }) + .then(this._reload.bind(this, {activity: true})); + }, }); // ----------------------------------------------------------------------------- // Activities Widget for Form views ('mail_activity' widget) // ----------------------------------------------------------------------------- -var Activity = AbstractActivityField.extend({ +var Activity = BasicActivity.extend({ className: 'o_mail_activity', - events: { + events:_.extend({}, BasicActivity.prototype.events, { 'click a': '_onClickRedirect', - 'click .o_activity_edit': '_onEditActivity', - 'click .o_activity_unlink': '_onUnlinkActivity', - 'click .o_activity_done': '_onMarkActivityDone', - 'click .o_activity_template_preview': '_onPreviewMailTemplate', - 'click .o_activity_template_send': '_onSendMailTemplate', - }, + }), specialData: '_fetchSpecialActivity', - /** * @override */ init: function () { this._super.apply(this, arguments); this._activities = this.record.specialData[this.name]; - this._draftFeedback = {}; - }, - - //------------------------------------------------------------ - // Public - //------------------------------------------------------------ - - /** - * @param {integer} previousActivityTypeID - * @return {$.Promise} - */ - scheduleActivity: function (previousActivityTypeID) { - var callback = this._reload.bind(this, { activity: true, thread: true }); - return this._scheduleActivity(false, previousActivityTypeID, callback); }, //------------------------------------------------------------ @@ -293,173 +445,28 @@ var Activity = AbstractActivityField.extend({ * @param {MouseEvent} ev */ _onClickRedirect: function (ev) { - var id = $(ev.target).data('oe-id'); + var id = $(ev.currentTarget).data('oe-id'); if (id) { ev.preventDefault(); - var model = $(ev.target).data('oe-model'); + var model = $(ev.currentTarget).data('oe-model'); this.trigger_up('redirect', { res_id: id, res_model: model, }); } }, - /** - * @private - * @param {MouseEvent} ev - * @param {Object} options - */ - _onEditActivity: function (ev, options) { - ev.preventDefault(); - var self = this; - var activity_id = $(ev.currentTarget).data('activity-id'); - var action = _.defaults(options || {}, { - type: 'ir.actions.act_window', - res_model: 'mail.activity', - view_mode: 'form', - view_type: 'form', - views: [[false, 'form']], - target: 'new', - context: { - default_res_id: this.res_id, - default_res_model: this.model, - }, - res_id: activity_id, - }); - return this.do_action(action, { - on_close: function () { - self._reload({activity: true, thread: true}); - }, - }); - }, - /** - * @private - * @param {MouseEvent} ev - */ - _onPreviewMailTemplate: function (ev) { - var templateID = $(ev.target).data('template-id'); - var action = { - name: _t('Compose Email'), - type: 'ir.actions.act_window', - res_model: 'mail.compose.message', - views: [[false, 'form']], - target: 'new', - context: { - default_res_id: this.res_id, - default_model: this.model, - default_use_template: true, - default_template_id: templateID, - force_email: true, - }, - }; - return this.do_action(action, { on_close: function () {} }); - }, - /** - * @private - * @param {MouseEvent} ev - */ - _onSendMailTemplate: function (ev) { - var templateID = $(ev.target).data('template-id'); - return this._rpc({ - model: this.model, - method: 'activity_send_mail', - args: [[this.res_id], templateID], - }) - .then(this._reload.bind(this, {activity: true, thread: true, followers: true})); - }, - /** - * @private - * @param {MouseEvent} ev - * @param {Object} options - */ - _onUnlinkActivity: function (ev, options) { - ev.preventDefault(); - var activityID = $(ev.currentTarget).data('activity-id'); - options = _.defaults(options || {}, { - model: 'mail.activity', - args: [[activityID]], - }); - return this._rpc({ - model: options.model, - method: 'unlink', - args: options.args, - }) - .then(this._reload.bind(this, {activity: true})); - }, - /** - * Called when marking an activity as done from the Chatter. - * - * It lets the current user write a feedback in a popup menu. - * After writing the feedback and confirm mark as done - * is sent, it marks this activity as done for good with the feedback linked - * to it. - * - * @private - * @param {MouseEvent} ev - */ - _onMarkActivityDone: function (ev) { - ev.preventDefault(); - var self = this; - var $popoverElement = $(ev.currentTarget); - var activityID = $popoverElement.data('activity-id'); - var previousActivityTypeID = $popoverElement.data('previous-activity-type-id'); - if (!$popoverElement.data('bs.popover')) { - $popoverElement.popover({ - template: $(Popover.Default.template).addClass('o_mail_activity_feedback')[0].outerHTML, // Ugly but cannot find another way - container: $popoverElement.parent(), // FIXME Ugly and should probably be in the body as by default but form view should handle destroying popovers - title : _t("Feedback"), - html: true, - trigger:'click', - content : function () { - var $popover = $(QWeb.render('mail.activity_feedback_form', { 'previous_activity_type_id': previousActivityTypeID })); - $popover.find('#activity_feedback').val(self._draftFeedback[activityID]); - $popover.on('click', '.o_activity_popover_done', function () { - self._markActivityDone({ - activityID: activityID, - feedback: _.escape($popover.find('#activity_feedback').val()), - }); - }); - $popover.on('click', '.o_activity_popover_done_next', function () { - self._markActivityDoneAndScheduleNext({ - activityID: activityID, - feedback: _.escape($popover.find('#activity_feedback').val()), - }); - }); - $popover.on('click', '.o_activity_popover_discard', function () { - $popoverElement.popover('hide'); - }); - return $popover; - }, - }).on('shown.bs.popover', function () { - var $popover = $($(this).data("bs.popover").tip); - $(".o_mail_activity_feedback.popover").not($popover).popover("hide"); - $popover.addClass('o_mail_activity_feedback').attr('tabindex', 0); - $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) { - self._draftFeedback[activityID] = $popover.find('#activity_feedback').val(); - $popover.popover('hide'); - } - }); - }).popover('show'); - } - }, + }); // ----------------------------------------------------------------------------- // Activities Widget for Kanban views ('kanban_activity' widget) // ----------------------------------------------------------------------------- -var KanbanActivity = AbstractActivityField.extend({ +var KanbanActivity = BasicActivity.extend({ + className: 'o_mail_activity_kanban', template: 'mail.KanbanActivity', - events: { + events:_.extend({}, BasicActivity.prototype.events, { 'show.bs.dropdown': '_onDropdownShow', - 'click .o_schedule_activity': '_onScheduleActivity', - 'click .o_mark_as_done': '_onMarkActivityDone', - 'click .o_activity_template_preview': '_onPreviewMailTemplate', - 'click .o_activity_template_send': '_onSendMailTemplate', - }, + }), /** * @override @@ -472,7 +479,6 @@ var KanbanActivity = AbstractActivityField.extend({ }); this.selection = selection; this._setState(record); - this._draftFeedback = {}; }, //------------------------------------------------------------ @@ -534,20 +540,6 @@ var KanbanActivity = AbstractActivityField.extend({ this.activityState = this.recordData.activity_state; }, - - //------------------------------------------------------------ - // Public - //------------------------------------------------------------ - - /** - * @param {integer} previousActivityTypeID - * @return {$.Promise} - */ - scheduleActivity: function (previousActivityTypeID) { - var callback = this._reload.bind(this, { activity: true, thread: true }); - return this._scheduleActivity(false, previousActivityTypeID, callback); - }, - //------------------------------------------------------------ // Handlers //------------------------------------------------------------ @@ -558,113 +550,6 @@ var KanbanActivity = AbstractActivityField.extend({ _onDropdownShow: function () { this._renderDropdown(); }, - /** - * @private - * @param {MouseEvent} ev - */ - _onMarkActivityDone: function (ev) { - ev.stopPropagation(); - var self = this; - var $popoverElement = $(ev.currentTarget); - var activityID = $popoverElement.data('activity-id'); - var previousActivityTypeID = $popoverElement.data('previous-activity-type-id'); - - if (!$popoverElement.data('bs.popover')) { - $popoverElement.popover({ - template: $(Popover.Default.template).addClass('o_mail_activity_feedback')[0].outerHTML, // Ugly but cannot find another way - container: $popoverElement.parent(), // FIXME Ugly and should probably be in the body as by default but form view should handle destroying popovers - title : _t("Feedback"), - html: true, - trigger:'click', - content : function () { - var $popover = $(QWeb.render('mail.activity_feedback_form', { 'previous_activity_type_id': previousActivityTypeID })); - $popover.find('#activity_feedback').val(self._draftFeedback[activityID]); - $popover.on('click', function (ev) { - ev.stopPropagation(); - }); - $popover.on('click', '.o_activity_popover_done', function (ev) { - ev.stopPropagation(); - self._markActivityDone({ - activityID: activityID, - feedback: _.escape($popover.find('#activity_feedback').val()), - }); - }); - $popover.on('click', '.o_activity_popover_done_next', function (ev) { - ev.stopPropagation(); - self._markActivityDoneAndScheduleNext({ - activityID: activityID, - feedback: _.escape($popover.find('#activity_feedback').val()), - }); - }); - $popover.on('click', '.o_activity_popover_discard', function (ev) { - ev.stopPropagation(); - $popoverElement.popover('hide'); - }); - return $popover; - }, - }).on('shown.bs.popover', function () { - var $popover = $($(this).data("bs.popover").tip); - $(".o_mail_activity_feedback.popover").not($popover).popover("hide"); - $popover.addClass('o_mail_activity_feedback').attr('tabindex', 0); - $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) { - self._draftFeedback[activityID] = $popover.find('#activity_feedback').val(); - $popover.popover('hide'); - } - }); - }).popover('show'); - } - }, - /** - * @private - * @param {MouseEvent} ev - * @returns {$.Promise} - */ - _onScheduleActivity: function (ev) { - var activityID = $(ev.currentTarget).data('activity-id') || false; - return this._scheduleActivity(activityID, false, this._reload.bind(this)); - }, - /** - * @private - * @param {MouseEvent} ev - */ - _onPreviewMailTemplate: function (ev) { - ev.stopPropagation(); - var templateID = $(ev.target).data('template-id'); - var action = { - name: _t('Compose Email'), - type: 'ir.actions.act_window', - res_model: 'mail.compose.message', - views: [[false, 'form']], - target: 'new', - context: { - default_res_id: this.res_id, - default_model: this.model, - default_use_template: true, - default_template_id: templateID, - force_email: true, - }, - }; - return this.do_action(action, { on_close: function () {} }); - }, - /** - * @private - * @param {MouseEvent} ev - */ - _onSendMailTemplate: function (ev) { - ev.stopPropagation(); - var templateID = $(ev.target).data('template-id'); - return this._rpc({ - model: this.model, - method: 'activity_send_mail', - args: [[this.res_id], templateID], - }) - .then(this._reload.bind(this, {activity: true, thread: true, followers: true})); - }, }); field_registry diff --git a/addons/mail/static/src/js/chatter.js b/addons/mail/static/src/js/chatter.js index 6ec365ceda4..ea0f3dd8e4b 100644 --- a/addons/mail/static/src/js/chatter.js +++ b/addons/mail/static/src/js/chatter.js @@ -440,7 +440,7 @@ var Chatter = Widget.extend({ * @private */ _onScheduleActivity: function () { - this.fields.activity.scheduleActivity(false); + this.fields.activity.scheduleActivity(); }, }); diff --git a/addons/mail/static/src/scss/mail_activity.scss b/addons/mail/static/src/scss/mail_activity.scss index 0582b5312f4..d7970492949 100644 --- a/addons/mail/static/src/scss/mail_activity.scss +++ b/addons/mail/static/src/scss/mail_activity.scss @@ -200,7 +200,7 @@ background-color: $o-brand-lightsecondary; } - &.o_schedule_activity { + &.o_edit_activity { padding: 8px 10px 8px 0px; vertical-align: middle; &:hover { diff --git a/addons/mail/static/src/xml/activity.xml b/addons/mail/static/src/xml/activity.xml index 86d527b01ed..2ddcea9121f 100644 --- a/addons/mail/static/src/xml/activity.xml +++ b/addons/mail/static/src/xml/activity.xml @@ -75,13 +75,13 @@ </div> </t> <div class="o_thread_message_tools btn-group"> - <a role="button" href="#" class="btn btn-link btn-success text-muted o_activity_done o_activity_link mr8" t-att-data-activity-id="activity.id" t-att-data-previous-activity-type-id="activity.activity_type_id[0]" data-toggle="popover"> + <span class="o_mark_as_done" data-toggle="popover" t-att-data-activity-id="activity.id" t-att-data-previous-activity-type-id="activity.activity_type_id[0]"><a role="button" href="#" class="btn btn-link btn-success text-muted o_activity_link mr8"> <i class="fa fa-check"/> Mark Done - </a> - <a role="button" href="#" class="btn btn-link btn-secondary text-muted o_activity_edit o_activity_link" t-att-data-activity-id="activity.id"> + </a></span> + <a role="button" href="#" class="btn btn-link btn-secondary text-muted o_edit_activity o_activity_link" t-att-data-activity-id="activity.id"> <i class="fa fa-pencil"/> Edit </a> - <a role="button" href="#" class="btn btn-link btn-danger text-muted o_activity_unlink o_activity_link" t-att-data-activity-id="activity.id"> + <a role="button" href="#" class="btn btn-link btn-danger text-muted o_unlink_activity o_activity_link" t-att-data-activity-id="activity.id"> <i class="fa fa-times"/> Cancel </a> </div> diff --git a/addons/mail/static/src/xml/web_kanban_activity.xml b/addons/mail/static/src/xml/web_kanban_activity.xml index c31aa5f87ce..31d23859488 100644 --- a/addons/mail/static/src/xml/web_kanban_activity.xml +++ b/addons/mail/static/src/xml/web_kanban_activity.xml @@ -29,7 +29,7 @@ <t t-esc="selection[key]" /> (<t t-esc="logs.length"/>) </strong> </li> - <li t-foreach="logs" t-as="log" t-att-data-activity-id="log.id" class="nav-item o_schedule_activity" role="menuitem"> + <li t-foreach="logs" t-as="log" t-att-data-activity-id="log.id" class="nav-item o_edit_activity" role="menuitem"> <div class="o_activity_title float-left"> <span t-attf-class="fa #{log.icon} fa-fw" role="img" aria-label="Log" title="Log"/> <strong> diff --git a/addons/mail/static/tests/activity_tests.js b/addons/mail/static/tests/activity_tests.js new file mode 100644 index 00000000000..acc59c2f431 --- /dev/null +++ b/addons/mail/static/tests/activity_tests.js @@ -0,0 +1,316 @@ +odoo.define('mail.activity_view_tests', function (require) { +'use strict'; + +var ActivityView = require('mail.ActivityView'); +var testUtils = require('web.test_utils'); + +var createView = testUtils.createView; +var ACTIVITY_DATA = { + "grouped_activities":{ + "13":{ + "1":{ + "count":1, + "state":"planned", + "o_closest_deadline":"2018-08-16", + "ids":[ + 1 + ] + } + }, + "30":{ + "1":{ + "count":1, + "state":"today", + "o_closest_deadline":"2018-08-16", + "ids":[ + 2 + ] + }, + "2":{ + "count":2, + "state":"overdue", + "o_closest_deadline":"2018-09-16", + "ids":[ + 3 + ] + } + } + }, + "activity_types":[ + [ + 1, + "Email", + [ + { + "id":9, + "name":"Task: Rating Request" + }, + { + "id":8, + "name":"Task: Reception Acknowledgment" + } + ] + ], + [ + 2, + "Call", + [] + ] + ], + "model":"task", + "res_ids":[ + [ + 30, + "Office planning" + ], + [ + 13, + "Meeting Room Furnitures" + ] + ] +}; + +QUnit.module('mail', {}, function () { +QUnit.module('activity view', { + beforeEach: function () { + this.data = { + task: { + fields: { + id: {string: 'ID', type: 'integer'}, + }, + records: [ + {id: 13}, + {id: 30}, + ] + }, + partner: { + fields: { + display_name: { string: "Displayed name", type: "char" }, + }, + records: [{ + id: 2, + display_name: "first partner", + }] + }, + 'mail.activity': { + fields: { + activity_type_id: { string: "Activity type", type: "many2one", relation: "mail.activity.type" }, + display_name: { string: "Display name", type: "char" }, + date_deadline: { string: "Due Date", type: "date" }, + state: { + string: 'State', + type: 'selection', + selection: [['overdue', 'Overdue'], ['today', 'Today'], ['planned', 'Planned']], + }, + mail_template_ids: { string: "Mail templates", type: "many2many", relation: "mail.template" }, + user_id: { string: "Assigned to", type: "many2one", relation: 'partner' }, + }, + records:[ + { + id: 1, + display_name: "An activity", + date_deadline: moment().add(3, "days").format("YYYY-MM-DD"), // now + state: "planned", + activity_type_id: 1, + mail_template_ids: [8, 9], + user_id:2, + },{ + id: 2, + display_name: "An activity", + date_deadline: moment().format("YYYY-MM-DD"), // now + state: "today", + activity_type_id: 1, + mail_template_ids: [8, 9], + user_id:2, + },{ + id: 3, + display_name: "An activity", + date_deadline: moment().subtract(2, "days").format("YYYY-MM-DD"), // now + state: "overdue", + activity_type_id: 2, + mail_template_ids: [], + user_id:2, + } + ], + }, + 'mail.template': { + fields: { + name: { string: "Name", type: "char" }, + }, + records: [ + { id: 8, name: "Template1" }, + { id: 9, name: "Template2" }, + ], + }, + 'mail.activity.type': { + fields: { + name: { string: "Name", type: "char" }, + }, + records: [ + { id: 1, name: "Email" }, + { id: 2, name: "Call" }, + ], + }, + }; + } +}); + +QUnit.test('activity view: simple activity rendering', function (assert) { + assert.expect(7); + var activity = createView({ + View: ActivityView, + model: 'task', + data: this.data, + arch: '<activity string="Task"/>', + mockRPC: function(route, args) { + if (args.method === 'get_activity_data') { + return $.when(ACTIVITY_DATA); + } + return this._super(route, args); + } + }); + + assert.strictEqual(activity.$('table').length, 1, + 'should have a table'); + assert.ok(activity.$('table thead tr:first th:nth-child(2) span:first:contains(Email)').length, + 'should contain "Email" in header of first column'); + assert.ok(activity.$('table thead tr:first th:nth-child(3) span:first:contains(Call)').length, + 'should contain "Call" in header of second column'); + assert.ok(activity.$('table tbody tr:first td:first:contains(Office planning)').length, + 'should contain "Office planning" in first colum of first row'); + assert.ok(activity.$('table tbody tr:nth-child(2) td:first:contains(Meeting Room Furnitures)').length, + 'should contain "Meeting Room Furnitures" in first colum of second row'); + assert.ok(activity.$('table tbody tr:first td:nth-child(2).today .o_closest_deadline:contains(Aug 16)').length, + 'should contain an activity for today with date Aug 16 in second cell of first line'); + assert.ok(activity.$('table tbody tr:nth-child(2) td:nth-child(2).planned .o_closest_deadline:contains(Aug 16)').length, + 'should contain a planned activity with date Aug 16 in second cell of second line'); + activity.destroy(); +}); + +QUnit.test('activity view: batch send mail on activity', function (assert) { + assert.expect(6); + var activity = createView({ + View: ActivityView, + model: 'task', + data: this.data, + arch: '<activity string="Task"/>', + mockRPC: function(route, args) { + if (args.method === 'activity_send_mail'){ + assert.step(args.args); + return $.when(); + } + if (args.method === 'get_activity_data') { + return $.when(ACTIVITY_DATA); + } + return this._super(route, args); + }, + }); + assert.notOk(activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) .dropdown-menu.show').length, + 'dropdown shouldn\'t be displayed'); + + activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) i.fa-ellipsis-v').click(); + assert.ok(activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) .dropdown-menu.show').length, + 'dropdown should have appeared'); + + activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) .dropdown-menu.show .o_send_mail_template:first:contains(Task: Rating Request)').click(); + assert.notOk(activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) .dropdown-menu.show').length, + 'dropdown shouldn\'t be displayed'); + + activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) i.fa-ellipsis-v').click(); + activity.$('table thead tr:first th:nth-child(2) span:nth-child(2) .dropdown-menu.show .o_send_mail_template:nth-child(2):contains(Task: Reception Acknowledgment)').click(); + assert.verifySteps([ + [[13, 30], 9], //send mail template 9 on tasl 13 and 30 + [[13, 30], 8] //send mail template 8 on tasl 13 and 30 + ]); + + activity.destroy(); +}); + +QUnit.test('activity view: activity widget', function (assert) { + assert.expect(16); + var activity = createView({ + View: ActivityView, + model: 'task', + data: this.data, + arch: '<activity string="Task"/>', + mockRPC: function(route, args) { + if (args.method === 'activity_send_mail'){ + assert.deepEqual([[30],8],args.args, "Should send template 8 on record 30"); + assert.step('activity_send_mail'); + return $.when(); + } + if (args.method === 'action_done_schedule_next'){ + assert.deepEqual([[3]],args.args, "Should execute action_done_schedule_next on activity 3 only "); + assert.equal(args.kwargs.feedback, "feedback2"); + assert.step('action_done_schedule_next'); + return $.when({serverGeneratedAction: true}); + } + if (args.method === 'get_activity_data') { + return $.when(ACTIVITY_DATA); + } + return this._super(route, args); + }, + intercepts: { + do_action: function (ev) { + var action = ev.data.action; + if (action.serverGeneratedAction) { + assert.step('serverGeneratedAction'); + } else if (action.res_model === 'mail.compose.message') { + assert.deepEqual({ + default_model: "task", + default_res_id: 30, + default_template_id: 8, + default_use_template: true, + force_email: true + }, action.context); + assert.step("do_action_compose"); + } else if (action.res_model === 'mail.activity') { + assert.deepEqual({ + "default_res_id": 30, + "default_res_model": "task" + }, action.context); + assert.step("do_action_activity"); + } else { + assert.step("Unexpected action"); + } + }, + } + }); + var today = activity.$('table tbody tr:first td:nth-child(2).today'); + var dropdown = today.find('.dropdown-menu.o_activity'); + + today.find('.o_closest_deadline').click(); + assert.ok(dropdown.hasClass('show'), "dropdown should be displayed"); + assert.ok(dropdown.find('.o_activity_color_today:contains(Today)').length, "Title should be today"); + assert.ok(dropdown.find('.o_activity_title div div div:first span:contains(template8)').length, + "template8 should be available"); + assert.ok(dropdown.find('.o_activity_title div div div:nth-child(2) span:contains(template9)').length, + "template9 should be available"); + + dropdown.find('.o_activity_title div div div:first .o_activity_template_preview').click(); + dropdown.find('.o_activity_title div div div:first .o_activity_template_send').click(); + var overdue = activity.$('table tbody tr:first td:nth-child(3).overdue'); + overdue.find('.o_closest_deadline').click(); + dropdown = overdue.find('.dropdown-menu.o_activity'); + assert.notOk(dropdown.find('.o_activity_title div div div:first span').length, + "No template should be available"); + + dropdown.find('.o_schedule_activity').click(); + overdue.find('.o_closest_deadline').click(); + dropdown.find('.o_mark_as_done').click(); + dropdown.find('#activity_feedback').val("feedback2"); + + dropdown.find('.o_activity_popover_done_next').click(); + assert.verifySteps([ + "do_action_compose", + "activity_send_mail", + "do_action_activity", + "action_done_schedule_next", + "serverGeneratedAction" + ]); + + activity.destroy(); + }); + +}); +}); diff --git a/addons/mail/static/tests/chatter_tests.js b/addons/mail/static/tests/chatter_tests.js index c1d6edd8207..1b6202121ca 100644 --- a/addons/mail/static/tests/chatter_tests.js +++ b/addons/mail/static/tests/chatter_tests.js @@ -1240,7 +1240,7 @@ QUnit.test('form activity widget: schedule next activity', function (assert) { }, }); //Schedule next activity - form.$('.o_mail_activity .o_activity_done[data-activity-id=1]').click(); + form.$('.o_mail_activity .o_mark_as_done[data-activity-id=1]').click(); assert.strictEqual(form.$('.o_mail_activity_feedback.popover').length, 1, "a feedback popover should be visible"); $('.o_mail_activity_feedback.popover textarea').val('everything is ok'); // write a feedback @@ -1445,16 +1445,16 @@ QUnit.test('form activity widget: mark as done and remove', function (assert) { "there should be two activities"); // remove activity 1 - form.$('.o_mail_activity .o_activity_unlink[data-activity-id=1]').click(); + form.$('.o_mail_activity .o_unlink_activity[data-activity-id=1]').click(); assert.strictEqual(form.$('.o_mail_activity .o_thread_message').length, 1, "there should be one remaining activity"); - assert.ok(!form.$('.o_mail_activity .o_activity_unlink[data-activity-id=1]').length, + assert.ok(!form.$('.o_mail_activity .o_unlink_activity[data-activity-id=1]').length, "activity 1 should have been removed"); // mark activity done assert.ok(!form.$('.o_mail_thread .o_thread_message').length, "there should be no chatter message"); - form.$('.o_mail_activity .o_activity_done[data-activity-id=2]').click(); + form.$('.o_mail_activity .o_mark_as_done[data-activity-id=2]').click(); assert.strictEqual(form.$('.o_mail_activity_feedback.popover').length, 1, "a feedback popover should be visible"); $('.o_mail_activity_feedback.popover textarea').val('everything is ok'); // write a feedback diff --git a/addons/mail/static/tests/helpers/mock_server.js b/addons/mail/static/tests/helpers/mock_server.js index ecf5910a866..c56d354d84e 100644 --- a/addons/mail/static/tests/helpers/mock_server.js +++ b/addons/mail/static/tests/helpers/mock_server.js @@ -168,7 +168,16 @@ MockServer.include({ return $.when(this._mockMessageFormat(args)); } if (args.method === 'activity_format') { - return $.when(this._mockRead(args.model, args.args, args.kwargs)); + var res = this._mockRead(args.model, args.args, args.kwargs); + res = res.map(function(record) { + if (record.mail_template_ids) { + record.mail_template_ids = record.mail_template_ids.map(function(template_id) { + return {id:template_id, name:"template"+template_id}; + }); + } + return record; + }); + return $.when(res); } if (args.method === 'set_message_done') { return $.when(); |
