diff options
| author | Hiral Bhavsar <hbh@odoo.com> | 2019-02-04 06:18:08 +0000 |
|---|---|---|
| committer | Martin Geubelle <mge@odoo.com> | 2019-05-03 10:19:40 +0000 |
| commit | b2de618f9ff9969ff0644f3be10752f23d9738dc (patch) | |
| tree | a7f54bb16273f3b626a96d363e0f54bf19bb4ba3 /addons/mail/static/src/js | |
| parent | b29d4da037fbf73717cccdfcdf76d96e5b1b009b (diff) | |
[IMP] base,mail: allow to customize the activity view
The activity view has been greatly improved to allow to customize it
more easily. It works quite similarly to the kanban view, defining
`<field>` tags at the top and using these fields in the `<template>`
section. The template name used to define the activity cards is
`activity-box`.
Note that these activity cards are rendered using `KanbanRecord` widget
(this has implied that ActivityView inherits from `BasicView`).
Also note that the view validation has been moved in base to include the
common grammar.
Task 1894990
Diffstat (limited to 'addons/mail/static/src/js')
5 files changed, 167 insertions, 80 deletions
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', }), //-------------------------------------------------------------------------- - // Handlers + // Public //-------------------------------------------------------------------------- /** - * @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] + * Overridden to remove the pager as it makes no sense in this view. + * + * @override */ - _onReload: function (event) { - event.stopPropagation(); - var self = this; - this.model.reload().then(self.reload()); + renderPager: function () { + return Promise.resolve(); }, + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + /** * @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,19 +2,34 @@ 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 //-------------------------------------------------------------------------- @@ -23,12 +38,19 @@ var ActivityRenderer = AbstractRenderer.extend({ * @override * @private */ + _getRecord: function (recordId) { + return _.findWhere(this.state.data, { res_id: recordId }); + }, + /** + * @override + * @private + */ _render: function () { this.$el .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 = $('<table>') @@ -46,7 +68,7 @@ var ActivityRenderer = AbstractRenderer.extend({ * @returns {jQueryElement} a jquery element <tbody> */ _renderBody: function () { - var $rows = _.map(this.state.data.res_ids, this._renderRow.bind(this)); + var $rows = _.map(this.state.activity_res_ids, this._renderRow.bind(this)); return $('<tbody>').append($rows); }, /** @@ -56,7 +78,7 @@ var ActivityRenderer = AbstractRenderer.extend({ _renderHeader: function () { var $tr = $('<tr>') .append($('<th>')) //empty cell for name - .append(_.map(this.state.data.activity_types, this._renderHeaderCell.bind(this))); + .append(_.map(this.state.activity_types, this._renderHeaderCell.bind(this))); return $('<thead>').append($tr); }, /** @@ -73,22 +95,23 @@ var ActivityRenderer = AbstractRenderer.extend({ }, /** * @private - * @param {Object} data + * @param {integer} resId * @returns {jQueryElement} a <tr> element */ - _renderRow: function (data) { + _renderRow: function (resId) { var self = this; - var res_id = data[0]; - var name = data[1]; - var $nameTD = $('<td>') - .addClass("o_res_name_cell") - .html(name) - .data('res-id', res_id); - var $cells = _.map(this.state.data.activity_types, function (node) { + var record = this._getRecord(resId); + var $nameTD = $('<td>', { + class: _.contains(this.filteredResIDs, resId) ? 'o_activity_filter_' + this.activeFilter : '', + }); + var activityRecord = new ActivityRecord(this, record, { qweb: this.qweb }); + this.defs.push(activityRecord.appendTo($nameTD)); + + var $cells = _.map(this.state.activity_types, function (node) { var $td = $('<td>').addClass("o_activity_summary_cell"); var activity_type_id = node[0]; - var activity_group = self.state.data.grouped_activities[res_id][activity_type_id]; - activity_group = activity_group || {count: 0, ids: [], state: false}; + var activity_group = self.state.grouped_activities[resId]; + activity_group = activity_group && activity_group[activity_type_id] || {count: 0, ids: [], state: false}; if (activity_group.state) { $td.addClass(activity_group.state); } @@ -114,16 +137,15 @@ var ActivityRenderer = AbstractRenderer.extend({ }, }, fieldsInfo: {}, - model: self.state.data.model, - ref: res_id, // not necessary, i think + model: self.state.model, + ref: resId, // not necessary, i think type: 'record', - res_id: res_id, + res_id: resId, getContext: function () { return {}; // session.user_context }, //todo intercept event or changes on record to update view }; - var KanbanActivity = field_registry.get('kanban_activity'); var widget = new KanbanActivity(self, "activity_ids", record, {}); widget.appendTo($td).then(function() { // replace clock by closest deadline @@ -166,15 +188,6 @@ var ActivityRenderer = AbstractRenderer.extend({ templateID: templateID, }); }, - /** - * @private - * @override - * @param {MouseEvent} ev - */ - _onResNameClicked: function (ev) { - var resID = $(ev.currentTarget).data('res-id'); - this.trigger_up('open_view_form', {resID: resID}); - }, }); return ActivityRenderer; diff --git a/addons/mail/static/src/js/views/activity/activity_view.js b/addons/mail/static/src/js/views/activity/activity_view.js index 9f0cec6b761..b21a68215d1 100644 --- a/addons/mail/static/src/js/views/activity/activity_view.js +++ b/addons/mail/static/src/js/views/activity/activity_view.js @@ -4,23 +4,36 @@ odoo.define('mail.ActivityView', function (require) { var ActivityController = require('mail.ActivityController'); var ActivityModel = require('mail.ActivityModel'); var ActivityRenderer = require('mail.ActivityRenderer'); -var AbstractView = require('web.AbstractView'); +var BasicView = require('web.BasicView'); var core = require('web.core'); var view_registry = require('web.view_registry'); var _lt = core._lt; -var ActivityView = AbstractView.extend({ +var ActivityView = BasicView.extend({ accesskey: "a", display_name: _lt('Activity'), icon: 'fa-clock-o', - config: _.extend({}, AbstractView.prototype.config, { + config: _.extend({}, BasicView.prototype.config, { Controller: ActivityController, Model: ActivityModel, Renderer: ActivityRenderer, }), viewType: 'activity', searchMenuTypes: ['filter', 'favorite'], + + /** + * @override + */ + init: function () { + this._super.apply(this, arguments); + + this.loadParams.type = 'list'; + // limit makes no sense in this view as we display all records having activities + this.loadParams.limit = false; + + this.rendererParams.templates = _.findWhere(this.arch.children, { 'tag': 'templates' }); + }, }); view_registry.add('activity', ActivityView); |
