summaryrefslogtreecommitdiff
path: root/addons/mail
diff options
context:
space:
mode:
authorXavierDo <xdo@odoo.com>2018-08-14 13:31:45 +0200
committerRomainLibert <rli@odoo.com>2018-08-20 16:00:09 +0200
commit0be33db68a201ab71f5e1deaac31945b95649546 (patch)
treefbc08a20e7de11a6bd10f9f711c61d49168d4b44 /addons/mail
parentc90ff2afd8b129eaa5bd451728d4c6c99a7db89d (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')
-rw-r--r--addons/mail/models/mail_activity.py2
-rw-r--r--addons/mail/static/src/js/activity.js493
-rw-r--r--addons/mail/static/src/js/chatter.js2
-rw-r--r--addons/mail/static/src/scss/mail_activity.scss2
-rw-r--r--addons/mail/static/src/xml/activity.xml8
-rw-r--r--addons/mail/static/src/xml/web_kanban_activity.xml2
-rw-r--r--addons/mail/static/tests/activity_tests.js316
-rw-r--r--addons/mail/static/tests/chatter_tests.js8
-rw-r--r--addons/mail/static/tests/helpers/mock_server.js11
-rw-r--r--addons/mail/views/mail_templates.xml2
10 files changed, 529 insertions, 317 deletions
diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py
index 4cb2fa11d27..bc3119af798 100644
--- a/addons/mail/models/mail_activity.py
+++ b/addons/mail/models/mail_activity.py
@@ -409,7 +409,7 @@ class MailActivity(models.Model):
default_res_id=self.res_id,
default_res_model=self.res_model,
)
- self.action_done()
+ self.action_feedback(feedback)
return {
'name': _('Schedule an Activity'),
'context': wizard_ctx,
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();
diff --git a/addons/mail/views/mail_templates.xml b/addons/mail/views/mail_templates.xml
index fcae7d446cf..fd3face4a83 100644
--- a/addons/mail/views/mail_templates.xml
+++ b/addons/mail/views/mail_templates.xml
@@ -113,6 +113,8 @@
<script type="text/javascript" src="/mail/static/tests/models/cc_throttle_function_tests.js"></script>
<script type="text/javascript" src="/mail/static/tests/models/timer_tests.js"></script>
<script type="text/javascript" src="/mail/static/tests/models/timers_tests.js"></script>
+ <!-- activity view -->
+ <script type="text/javascript" src="/mail/static/tests/activity_tests.js"></script>
</xpath>
</template>