diff --git a/addons/mail/__init__.py b/addons/mail/__init__.py index 9226c7d74ad..f2cd96d8c83 100644 --- a/addons/mail/__init__.py +++ b/addons/mail/__init__.py @@ -3,4 +3,3 @@ from . import models from . import wizard from . import controllers -from . import validation diff --git a/addons/mail/models/__init__.py b/addons/mail/models/__init__.py index 7df60f71277..9b82416fed2 100644 --- a/addons/mail/models/__init__.py +++ b/addons/mail/models/__init__.py @@ -16,6 +16,7 @@ from . import mail_blacklist from . import mail_channel from . import mail_template from . import mail_shortcode +from . import models from . import res_partner from . import res_users from . import res_company diff --git a/addons/mail/models/mail_activity.py b/addons/mail/models/mail_activity.py index f5bfd7c11cf..a8f7cdbf6c2 100644 --- a/addons/mail/models/mail_activity.py +++ b/addons/mail/models/mail_activity.py @@ -524,8 +524,6 @@ class MailActivity(models.Model): 'state': state, 'o_closest_deadline': group['date_deadline'], } - res_ids_sorted = sorted(res_id_to_deadline, key=lambda item: res_id_to_deadline[item]) - res_id_to_name = dict(self.env[res_model].browse(res_ids_sorted).name_get()) activity_type_infos = [] for elem in sorted(activity_type_ids, key=lambda item: item.sequence): mail_template_info = [] @@ -535,9 +533,8 @@ class MailActivity(models.Model): return { 'activity_types': activity_type_infos, - 'res_ids': [(rid, res_id_to_name[rid]) for rid in res_ids_sorted], + 'activity_res_ids': sorted(res_id_to_deadline, key=lambda item: res_id_to_deadline[item]), 'grouped_activities': activity_data, - 'model': res_model, } diff --git a/addons/mail/models/models.py b/addons/mail/models/models.py new file mode 100644 index 00000000000..4c85b08d2af --- /dev/null +++ b/addons/mail/models/models.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from odoo import models, api +from lxml.builder import E + + +class BaseModel(models.AbstractModel): + _inherit = 'base' + + @api.model + def _get_default_activity_view(self): + """ Generates an empty activity view. + + :returns: a activity view as an lxml document + :rtype: etree._Element + """ + field = E.field(name=self._rec_name_fallback()) + activity_box = E.div(field, {'t-name': "activity-box"}) + templates = E.templates(activity_box) + return E.activity(templates, string=self._description) diff --git a/addons/mail/static/src/js/views/activity/activity_controller.js b/addons/mail/static/src/js/views/activity/activity_controller.js index 6af4c310c01..4ed543dd3ec 100644 --- a/addons/mail/static/src/js/views/activity/activity_controller.js +++ b/addons/mail/static/src/js/views/activity/activity_controller.js @@ -1,34 +1,30 @@ odoo.define('mail.ActivityController', function (require) { "use strict"; -var AbstractController = require('web.AbstractController'); +var BasicController = require('web.BasicController'); -var ActivityController = AbstractController.extend({ - custom_events: _.extend({}, AbstractController.prototype.custom_events, { +var ActivityController = BasicController.extend({ + custom_events: _.extend({}, BasicController.prototype.custom_events, { send_mail_template: '_onSendMailTemplate', - open_view_form: '_onOpenViewForm', - reload: '_onReload', }), + //-------------------------------------------------------------------------- + // Public + //-------------------------------------------------------------------------- + + /** + * Overridden to remove the pager as it makes no sense in this view. + * + * @override + */ + renderPager: function () { + return Promise.resolve(); + }, + //-------------------------------------------------------------------------- // Handlers //-------------------------------------------------------------------------- - /** - * @private - * @param {OdooEvent} event - * @param {string} event.name - * @param {Object} event.data - * @param {boolean} [event.data.activity] - * @param {boolean} [event.data.followers] - * @param {boolean} [event.data.thread] - */ - _onReload: function (event) { - event.stopPropagation(); - var self = this; - this.model.reload().then(self.reload()); - }, - /** * @private * @param {OdooEvent} ev @@ -36,8 +32,8 @@ var ActivityController = AbstractController.extend({ _onSendMailTemplate: function (ev) { var templateID = ev.data.templateID; var activityTypeID = ev.data.activityTypeID; - var state = this.model.get(); - var groupedActivities = state.data.grouped_activities; + var state = this.model.get(this.handle); + var groupedActivities = state.grouped_activities; var resIDS = []; Object.keys(groupedActivities).forEach(function (resID) { var activityByType = groupedActivities[resID]; @@ -52,21 +48,6 @@ var ActivityController = AbstractController.extend({ args: [resIDS, templateID], }); }, - /** - * @private - * @override - * @param {MouseEvent} ev - */ - _onOpenViewForm: function (ev) { - var resID = ev.data.resID; - this.do_action({ - type: 'ir.actions.act_window', - res_model: this.model.modelName, - res_id: resID, - views: [[false, 'form']], - target: 'current' - }); - }, }); return ActivityController; diff --git a/addons/mail/static/src/js/views/activity/activity_model.js b/addons/mail/static/src/js/views/activity/activity_model.js index f5a2feee988..f464cf6a92f 100644 --- a/addons/mail/static/src/js/views/activity/activity_model.js +++ b/addons/mail/static/src/js/views/activity/activity_model.js @@ -1,43 +1,61 @@ odoo.define('mail.ActivityModel', function (require) { 'use strict'; -var AbstractModel = require('web.AbstractModel'); +var BasicModel = require('web.BasicModel'); var session = require('web.session'); -var ActivityModel = AbstractModel.extend({ +var ActivityModel = BasicModel.extend({ + //-------------------------------------------------------------------------- // Public //-------------------------------------------------------------------------- /** - * @override - */ + * Add the following (activity specific) keys when performing a `get` on the + * main list datapoint: + * - activity_types + * - activity_res_ids + * - grouped_activities + * + * @override + */ get: function () { - return this.data; + var result = this._super.apply(this, arguments); + if (result && result.model === this.modelName && result.type === 'list') { + _.extend(result, this.additionalData); + } + return result; }, /** * @override - * @param {Object} params * @param {Array[]} params.domain - * @returns {Promise} */ load: function (params) { + params.domain.push(['activity_ids', '!=', false]); this.domain = params.domain; this.modelName = params.modelName; - this.data = {}; - return this._fetchData(); + params.groupedBy = []; + var def = this._super.apply(this, arguments); + return Promise.all([def, this._fetchData()]).then(function (result) { + return result[0]; + }); }, /** - * @param {any} handle - * @param {Object} params - * @param {Array[]} params.domain - * @returns {Promise} + * @override + * @param {Array[]} [params.domain] */ reload: function (handle, params) { if (params && 'domain' in params) { + params.domain.push(['activity_ids', '!=', false]); this.domain = params.domain; } - return this._fetchData(); + if (params && 'groupBy' in params) { + params.groupBy = []; + } + var def = this._super.apply(this, arguments); + return Promise.all([def, this._fetchData()]).then(function (result) { + return result[0]; + }); }, //-------------------------------------------------------------------------- @@ -61,7 +79,7 @@ var ActivityModel = AbstractModel.extend({ context: session.user_context, } }).then(function (result) { - self.data.data = result; + self.additionalData = result; }); }, }); diff --git a/addons/mail/static/src/js/views/activity/activity_record.js b/addons/mail/static/src/js/views/activity/activity_record.js new file mode 100644 index 00000000000..98da9dcaf8f --- /dev/null +++ b/addons/mail/static/src/js/views/activity/activity_record.js @@ -0,0 +1,62 @@ +odoo.define('mail.ActivityRecord', function (require) { +"use strict"; + +var KanbanRecord = require('web.KanbanRecord'); + +var ActivityRecord = KanbanRecord.extend({ + /** + * @override + */ + init: function (parent, state) { + this._super.apply(this,arguments); + + this.fieldsInfo = state.fieldsInfo.activity; + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @override + * @private + */ + _render: function () { + this.defs = []; + this._replaceElement(this.qweb.render('activity-box', this.qweb_context)); + this.$el.on('click', this._onGlobalClick.bind(this)); + this.$el.addClass('o_activity_record'); + this._processFields(); + this._setupColor(); + return Promise.all(this.defs); + }, + /** + * @override + * @private + */ + _setFieldDisplay: function ($el, fieldName) { + this._super.apply(this, arguments); + + // attribute muted + if (this.fieldsInfo[fieldName].muted) { + $el.addClass('text-muted'); + } + }, + /** + * @override + * @private + */ + _setState: function () { + this._super.apply(this, arguments); + + // activity has a different qweb context + this.qweb_context = { + activity_image: this._getImageURL.bind(this), + record: this.record, + user_context: this.getSession().user_context, + widget: this, + }; + }, +}); +return ActivityRecord; +}); diff --git a/addons/mail/static/src/js/views/activity/activity_renderer.js b/addons/mail/static/src/js/views/activity/activity_renderer.js index 75eb25367e4..640a8859767 100644 --- a/addons/mail/static/src/js/views/activity/activity_renderer.js +++ b/addons/mail/static/src/js/views/activity/activity_renderer.js @@ -2,23 +2,45 @@ odoo.define('mail.ActivityRenderer', function (require) { "use strict"; var AbstractRenderer = require('web.AbstractRenderer'); +var ActivityRecord = require('mail.ActivityRecord'); var core = require('web.core'); var field_registry = require('web.field_registry'); +var qweb = require('web.QWeb'); +var session = require('web.session'); +var utils = require('web.utils'); +var KanbanActivity = field_registry.get('kanban_activity'); var _t = core._t; var QWeb = core.qweb; var ActivityRenderer = AbstractRenderer.extend({ className: 'o_activity_view', events: { - 'click .o_res_name_cell': '_onResNameClicked', 'click .o_send_mail_template': '_onSenMailTemplateClicked', }, + /** + * @override + * @param {Object} params.templates + */ + init: function (parent, state, params) { + this._super.apply(this, arguments); + + this.qweb = new qweb(session.debug, {_s: session.origin}); + this.qweb.add_template(utils.json_node_to_xml(params.templates)); + }, + //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- + /** + * @override + * @private + */ + _getRecord: function (recordId) { + return _.findWhere(this.state.data, { res_id: recordId }); + }, /** * @override * @private @@ -28,7 +50,7 @@ var ActivityRenderer = AbstractRenderer.extend({ .removeClass('table-responsive') .empty(); - if (this.state.data.activity_types.length === 0) { + if (this.state.activity_types.length === 0) { this.$el.append(QWeb.render('ActivityView.nodata')); } else { var $table = $('