From bade59a3a75ff11bcce9c0d038028276e8814fe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Theys?= Date: Mon, 17 Oct 2022 16:25:31 +0000 Subject: [PATCH] [IMP] mail, test_mail: convert legacy code from activity view cell MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit task-3026018 closes odoo/odoo#103326 Related: odoo/enterprise#32853 Signed-off-by: Alexandre Kühn (aku) --- .../activity_cell_view/activity_cell_view.js | 25 +++++ .../activity_cell_view.scss | 3 + .../activity_cell_view/activity_cell_view.xml | 13 +++ .../activity_cell_view_container.js | 101 ++++++++++++++++++ .../activity_cell_view_container.xml | 8 ++ .../activity_list_view/activity_list_view.xml | 6 +- .../kanban_field_activity_view_container.js | 2 +- .../list_field_activity_view_container.js | 2 +- addons/mail/static/src/js/activity.js | 40 ++----- .../js/views/activity/activity_controller.js | 7 ++ .../src/js/views/activity/activity_model.js | 36 +------ .../js/views/activity/activity_renderer.js | 21 +--- addons/mail/static/src/models/activity.js | 22 ++-- .../static/src/models/activity_cell_view.js | 53 +++++++++ .../static/src/models/activity_list_view.js | 34 +++++- .../src/models/activity_list_view_item.js | 16 ++- ...activity_mark_done_popover_content_view.js | 28 +++-- .../mail/static/src/models/file_uploader.js | 10 +- addons/mail/static/src/models/popover_view.js | 16 ++- .../mail/static/src/scss/activity_view.scss | 35 ++---- addons/mail/static/src/xml/activity_view.xml | 17 ++- .../test_mail/static/tests/activity_tests.js | 31 +++--- 22 files changed, 353 insertions(+), 173 deletions(-) create mode 100644 addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view.js create mode 100644 addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view.scss create mode 100644 addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view.xml create mode 100644 addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view_container.js create mode 100644 addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view_container.xml create mode 100644 addons/mail/static/src/models/activity_cell_view.js diff --git a/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view.js b/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view.js new file mode 100644 index 00000000000..87ae49a84a4 --- /dev/null +++ b/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view.js @@ -0,0 +1,25 @@ +/** @odoo-module **/ + +import { useRefToModel } from '@mail/component_hooks/use_ref_to_model'; +import { registerMessagingComponent } from '@mail/utils/messaging_component'; + +const { Component } = owl; + +export class ActivityCellView extends Component { + + setup() { + useRefToModel({ fieldName: 'contentRef', refName: 'content' }); + } + + get activityCellView() { + return this.props.record; + } + +} + +Object.assign(ActivityCellView, { + props: { record: Object }, + template: 'mail.ActivityCellView', +}); + +registerMessagingComponent(ActivityCellView); diff --git a/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view.scss b/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view.scss new file mode 100644 index 00000000000..5ed6ded61bd --- /dev/null +++ b/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view.scss @@ -0,0 +1,3 @@ +.o_ActivityCellView_activityCount { + @include o-position-absolute($bottom: 0, $right: 0); +} diff --git a/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view.xml b/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view.xml new file mode 100644 index 00000000000..c8b464b3feb --- /dev/null +++ b/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view.xml @@ -0,0 +1,13 @@ + + + + +
+
+
+ +
+
+ + + diff --git a/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view_container.js b/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view_container.js new file mode 100644 index 00000000000..d6703af3b87 --- /dev/null +++ b/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view_container.js @@ -0,0 +1,101 @@ +/** @odoo-module **/ + +// ensure components are registered beforehand. +import '@mail/backend_components/activity_cell_view/activity_cell_view'; +import { insert } from '@mail/model/model_field_command'; +import { getMessagingComponent } from '@mail/utils/messaging_component'; + +const { Component, onWillDestroy, onWillUpdateProps } = owl; + +const getNextId = (function () { + let tmpId = 0; + return () => { + tmpId += 1; + return tmpId; + }; +})(); + +/** + * Container for messaging component ActivityCellView ensuring messaging + * records are ready before rendering ActivityCellView component. + */ +export class ActivityCellViewContainer extends Component { + + /** + * @override + */ + setup() { + super.setup(); + this.activityCellView = undefined; + this.activityCellViewId = getNextId(); + this._insertFromProps(this.props); + onWillUpdateProps(nextProps => this._insertFromProps(nextProps)); + onWillDestroy(() => this._deleteRecord()); + } + + /** + * @private + */ + _deleteRecord() { + if (this.activityCellView) { + if (this.activityCellView.exists()) { + this.activityCellView.delete(); + } + this.activityCellView = undefined; + } + } + + /** + * @private + */ + async _insertFromProps(props) { + const messaging = await this.env.services.messaging.get(); + if (owl.status(this) === "destroyed") { + this._deleteRecord(); + return; + } + const activityCellView = messaging.models['ActivityCellView'].insert({ + activityType: { + id: props.activityTypeId, + }, + closestDeadline: props.closestDeadline, + id: this.activityCellViewId, + reloadFunc: props.reloadFunc, + thread: { + activities: insert(props.activityIds.map(activityId => { + return { + id: activityId, + type: { + id: props.activityTypeId, + }, + }; + })), + hasActivities: true, + id: props.resId, + model: props.resModel, + }, + }); + if (activityCellView !== this.activityCellView) { + this._deleteRecord(); + this.activityCellView = activityCellView; + } + this.render(); + } + +} + +Object.assign(ActivityCellViewContainer, { + components: { ActivityCellView: getMessagingComponent('ActivityCellView') }, + props: { + activityIds: { + type: Array, + elements: Number, + }, + activityTypeId: Number, + closestDeadline: String, + reloadFunc: Function, + resId: Number, + resModel: String, + }, + template: 'mail.ActivityCellViewContainer', +}); diff --git a/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view_container.xml b/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view_container.xml new file mode 100644 index 00000000000..783f3b7525d --- /dev/null +++ b/addons/mail/static/src/backend_components/activity_cell_view/activity_cell_view_container.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/addons/mail/static/src/backend_components/activity_list_view/activity_list_view.xml b/addons/mail/static/src/backend_components/activity_list_view/activity_list_view.xml index b88217cce5d..b25752ecb99 100644 --- a/addons/mail/static/src/backend_components/activity_list_view/activity_list_view.xml +++ b/addons/mail/static/src/backend_components/activity_list_view/activity_list_view.xml @@ -8,7 +8,7 @@
- Overdue + Overdue
@@ -18,7 +18,7 @@
- Today + Today
@@ -28,7 +28,7 @@
- Planned + Planned
diff --git a/addons/mail/static/src/backend_components/kanban_field_activity_view/kanban_field_activity_view_container.js b/addons/mail/static/src/backend_components/kanban_field_activity_view/kanban_field_activity_view_container.js index 0fc4e00b7c0..1ce89575dc3 100644 --- a/addons/mail/static/src/backend_components/kanban_field_activity_view/kanban_field_activity_view_container.js +++ b/addons/mail/static/src/backend_components/kanban_field_activity_view/kanban_field_activity_view_container.js @@ -59,7 +59,7 @@ export class KanbanFieldActivityViewContainer extends Component { const kanbanFieldActivityView = messaging.models['KanbanFieldActivityView'].insert({ id: this.kanbanFieldActivityViewId, thread: { - activities: this.props.value.records.map(activityData => { + activities: props.value.records.map(activityData => { return { id: activityData.resId, }; diff --git a/addons/mail/static/src/backend_components/list_field_activity_view/list_field_activity_view_container.js b/addons/mail/static/src/backend_components/list_field_activity_view/list_field_activity_view_container.js index f137bb34665..4c91f4d555a 100644 --- a/addons/mail/static/src/backend_components/list_field_activity_view/list_field_activity_view_container.js +++ b/addons/mail/static/src/backend_components/list_field_activity_view/list_field_activity_view_container.js @@ -59,7 +59,7 @@ export class ListFieldActivityViewContainer extends Component { const listFieldActivityView = messaging.models['ListFieldActivityView'].insert({ id: this.listFieldActivityViewId, thread: { - activities: this.props.value.records.map(activityData => { + activities: props.value.records.map(activityData => { return { id: activityData.resId, }; diff --git a/addons/mail/static/src/js/activity.js b/addons/mail/static/src/js/activity.js index d5c9091628b..f60fc3f9678 100644 --- a/addons/mail/static/src/js/activity.js +++ b/addons/mail/static/src/js/activity.js @@ -45,7 +45,6 @@ const KanbanActivity = AbstractField.extend({ this.selection[key] = value; } this.defaultActivityType = options.activityType; - this.isActivityViewCell = options.isActivityViewCell; }, async willStart() { await this._super(); @@ -379,38 +378,17 @@ const KanbanActivity = AbstractField.extend({ * @private */ _render() { - if (this.isActivityViewCell) { - // replace clock by closest deadline - const $date = $('
'); - const date = moment(this.record.data.closest_deadline).toDate(); - // To remove year only if current year - if (moment().year() === moment(date).year()) { - $date.text(date.toLocaleDateString(moment().locale(), { - day: 'numeric', month: 'short' - })); - } else { - $date.text(moment(date).format('ll')); - } - this.$('a').html($date); - if (this.record.data.activity_ids.res_ids.length > 1) { - this.$('a').append($('', { - class: 'badge bg-light rounded-pill border-0 ' + this.record.data.activity_state, - text: this.record.data.activity_ids.res_ids.length, - })); - } + // span classes need to be updated manually because the template cannot + // be re-rendered eaasily (because of the dropdown state) + const spanClasses = ['fa', 'fa-lg', 'fa-fw']; + spanClasses.push('o_activity_color_' + (this.record.data.activity_state || 'default')); + if (this.recordData.activity_exception_decoration) { + spanClasses.push('text-' + this.recordData.activity_exception_decoration); + spanClasses.push(this.recordData.activity_exception_icon); } else { - // span classes need to be updated manually because the template cannot - // be re-rendered eaasily (because of the dropdown state) - const spanClasses = ['fa', 'fa-lg', 'fa-fw']; - spanClasses.push('o_activity_color_' + (this.record.data.activity_state || 'default')); - if (this.recordData.activity_exception_decoration) { - spanClasses.push('text-' + this.recordData.activity_exception_decoration); - spanClasses.push(this.recordData.activity_exception_icon); - } else { - spanClasses.push('fa-clock-o'); - } - this.$('.o_activity_btn > span').removeClass().addClass(spanClasses.join(' ')); + spanClasses.push('fa-clock-o'); } + this.$('.o_activity_btn > span').removeClass().addClass(spanClasses.join(' ')); if (this.$el.hasClass('show')) { // note: this part of the rendering might be asynchronous this._renderDropdown(); 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 7e249476fc5..8b5506bde8e 100644 --- a/addons/mail/static/src/js/views/activity/activity_controller.js +++ b/addons/mail/static/src/js/views/activity/activity_controller.js @@ -14,6 +14,7 @@ var _t = core._t; var ActivityController = BasicController.extend({ custom_events: _.extend({}, BasicController.prototype.custom_events, { empty_cell_clicked: '_onEmptyCell', + reload_data: '_onReloadData', send_mail_template: '_onSendMailTemplate', schedule_activity: '_onScheduleActivity', }), @@ -53,6 +54,12 @@ var ActivityController = BasicController.extend({ // Handlers //-------------------------------------------------------------------------- + /** + * @private + */ + _onReloadData() { + this.trigger_up('reload'); + }, /** * @private */ 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 715329e1228..8b07fa48b2e 100644 --- a/addons/mail/static/src/js/views/activity/activity_model.js +++ b/addons/mail/static/src/js/views/activity/activity_model.js @@ -20,44 +20,10 @@ const ActivityModel = BasicModel.extend({ __get: function () { var result = this._super.apply(this, arguments); if (result && result.model === this.modelName && result.type === 'list') { - _.extend(result, this.additionalData, {getKanbanActivityData: this.getKanbanActivityData}); + _.extend(result, this.additionalData); } return result; }, - /** - * @param {Object} activityGroup - * @param {integer} resId - * @returns {Object} - */ - getKanbanActivityData(activityGroup, resId) { - return { - data: { - activity_ids: { - model: 'mail.activity', - res_ids: activityGroup.ids, - }, - activity_state: activityGroup.state, - closest_deadline: activityGroup.o_closest_deadline, - }, - fields: { - activity_ids: {}, - activity_state: { - selection: [ - ['overdue', "Overdue"], - ['today', "Today"], - ['planned', "Planned"], - ], - }, - }, - fieldsInfo: {}, - model: this.model, - type: 'record', - res_id: resId, - getContext: function () { - return {}; - }, - }; - }, /** * @override * @param {Array[]} params.domain 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 01e0d622c8a..8411c9e56b9 100644 --- a/addons/mail/static/src/js/views/activity/activity_renderer.js +++ b/addons/mail/static/src/js/views/activity/activity_renderer.js @@ -1,10 +1,10 @@ /** @odoo-module **/ import ActivityRecord from '@mail/js/views/activity/activity_record'; +import { ActivityCellViewContainer } from '@mail/backend_components/activity_cell_view/activity_cell_view_container'; import AbstractRendererOwl from 'web.AbstractRendererOwl'; import core from 'web.core'; -import field_registry from 'web.field_registry'; import KanbanColumnProgressBar from 'web.KanbanColumnProgressBar'; import { ComponentAdapter } from 'web.OwlCompatibility'; import QWeb from 'web.QWeb'; @@ -13,7 +13,6 @@ import utils from 'web.utils'; const { useState } = owl; const _t = core._t; -const KanbanActivity = field_registry.get('kanban_activity'); /** * Owl Component Adapter for ActivityRecord which is KanbanRecord (Odoo Widget) @@ -31,21 +30,6 @@ class ActivityRecordAdapter extends ComponentAdapter { } } -/** - * Owl Component Adapter for KanbanActivity. - * TODO: Remove this adapter when KanbanActivity is a Component. - */ -class ActivityCellAdapter extends ComponentAdapter { - renderWidget() { - this.widget._render(); - } - - updateWidget(nextProps) { - const record = nextProps.widgetArgs[1]; - this.widget._reset(record); - } -} - /** * Owl Component Adapter for KanbanColumnProgressBar (Odoo Widget) * TODO: Remove this adapter when KanbanColumnProgressBar is a Component @@ -94,7 +78,6 @@ class ActivityRenderer extends AbstractRendererOwl { }); this.widgetComponents = { ActivityRecord, - KanbanActivity, KanbanColumnProgressBar, }; } @@ -209,8 +192,8 @@ class ActivityRenderer extends AbstractRendererOwl { } ActivityRenderer.components = { + ActivityCellViewContainer, ActivityRecordAdapter, - ActivityCellAdapter, KanbanColumnProgressBarAdapter, }; ActivityRenderer.template = 'mail.ActivityRenderer'; diff --git a/addons/mail/static/src/models/activity.js b/addons/mail/static/src/models/activity.js index 4b484c87c25..fc6fe52b9f7 100644 --- a/addons/mail/static/src/models/activity.js +++ b/addons/mail/static/src/models/activity.js @@ -179,7 +179,6 @@ registerModel({ /** * @param {Object} param0 * @param {string} param0.feedback - * @returns {Object} */ async markAsDoneAndScheduleNext({ feedback }) { const thread = this.thread; @@ -198,17 +197,18 @@ registerModel({ if (!action) { return; } - this.env.services.action.doAction( - action, - { - onClose: () => { - if (!thread.exists()) { - return; - } - thread.fetchData(['activities']); + await new Promise(resolve => { + this.env.services.action.doAction( + action, + { + onClose: resolve, }, - }, - ); + ); + }); + if (!thread.exists()) { + return; + } + thread.fetchData(['activities']); }, }, fields: { diff --git a/addons/mail/static/src/models/activity_cell_view.js b/addons/mail/static/src/models/activity_cell_view.js new file mode 100644 index 00000000000..589ddfdd85a --- /dev/null +++ b/addons/mail/static/src/models/activity_cell_view.js @@ -0,0 +1,53 @@ +/** @odoo-module **/ + +import { registerModel } from '@mail/model/model_core'; +import { attr, many, one } from '@mail/model/model_field'; +import { clear } from '@mail/model/model_field_command'; + +registerModel({ + name: 'ActivityCellView', + recordMethods: { + onClick() { + this.update({ activityListPopoverView: this.activityListPopoverView ? clear() : {} }); + }, + }, + fields: { + activityListPopoverView: one('PopoverView', { + inverse: 'activityCellViewOwnerAsActivityList', + }), + activityType: one('ActivityType', { + required: true, + }), + closestDeadline: attr({ + required: true, + }), + closestDeadlineFormatted: attr({ + compute() { + const date = moment(this.closestDeadline).toDate(); + // To remove year only if current year + if (moment().year() === moment(date).year()) { + return date.toLocaleDateString(moment().locale(), { + day: 'numeric', month: 'short' + }); + } else { + return moment(date).format('ll'); + } + }, + }), + contentRef: attr(), + filteredActivities: many('Activity', { + compute() { + return this.thread.activities.filter(activity => activity.type === this.activityType); + }, + }), + id: attr({ + identifying: true, + }), + reloadFunc: attr({ + required: true, + }), + thread: one('Thread', { + required: true, + }), + }, +}); diff --git a/addons/mail/static/src/models/activity_list_view.js b/addons/mail/static/src/models/activity_list_view.js index 34f30575724..4f000597acd 100644 --- a/addons/mail/static/src/models/activity_list_view.js +++ b/addons/mail/static/src/models/activity_list_view.js @@ -2,6 +2,7 @@ import { registerModel } from '@mail/model/model_core'; import { attr, many, one } from '@mail/model/model_field'; +import { clear } from '@mail/model/model_field_command'; import session from 'web.session'; @@ -29,13 +30,22 @@ registerModel({ }, recordMethods: { onClickAddActivityButton() { + const reloadFunc = this.reloadFunc; const thread = this.thread; const webRecord = this.webRecord; this.messaging.openActivityForm({ + defaultActivityTypeId: this.popoverViewOwner.activityCellViewOwnerAsActivityList + ? this.popoverViewOwner.activityCellViewOwnerAsActivityList.activityType.id + : undefined, thread, }).then(() => { thread.fetchData(['activities']); - webRecord.model.load({ resId: thread.id }); + if (reloadFunc) { + reloadFunc(); + } + if (webRecord) { + webRecord.model.load({ resId: thread.id }); + } }); this.popoverViewOwner.delete(); }, @@ -43,6 +53,9 @@ registerModel({ fields: { activities: many('Activity', { compute() { + if (this.popoverViewOwner.activityCellViewOwnerAsActivityList) { + return this.popoverViewOwner.activityCellViewOwnerAsActivityList.filteredActivities; + } return this.thread && this.thread.activities; }, sort: [ @@ -70,9 +83,20 @@ registerModel({ identifying: true, inverse: 'activityListView', }), + reloadFunc: attr({ + compute() { + return this.popoverViewOwner.activityCellViewOwnerAsActivityList ? this.popoverViewOwner.activityCellViewOwnerAsActivityList.reloadFunc : clear(); + }, + }), thread: one('Thread', { compute() { - return this.popoverViewOwner.activityButtonViewOwnerAsActivityList.thread; + if (this.popoverViewOwner.activityButtonViewOwnerAsActivityList) { + return this.popoverViewOwner.activityButtonViewOwnerAsActivityList.thread; + } + if (this.popoverViewOwner.activityCellViewOwnerAsActivityList) { + return this.popoverViewOwner.activityCellViewOwnerAsActivityList.thread; + } + return clear(); }, required: true, }), @@ -81,9 +105,11 @@ registerModel({ }), webRecord: attr({ compute() { - return this.popoverViewOwner.activityButtonViewOwnerAsActivityList.webRecord; + if (this.popoverViewOwner.activityButtonViewOwnerAsActivityList) { + return this.popoverViewOwner.activityButtonViewOwnerAsActivityList.webRecord; + } + return clear(); }, - required: true, }), }, }); diff --git a/addons/mail/static/src/models/activity_list_view_item.js b/addons/mail/static/src/models/activity_list_view_item.js index 9d3a5a8ffa8..e8995df1303 100644 --- a/addons/mail/static/src/models/activity_list_view_item.js +++ b/addons/mail/static/src/models/activity_list_view_item.js @@ -12,10 +12,16 @@ registerModel({ recordMethods: { onClickEditActivityButton() { const popoverViewOwner = this.activityListViewOwner.popoverViewOwner; + const reloadFunc = this.reloadFunc; const webRecord = this.webRecord; const thread = this.activity.thread; this.activity.edit().then(() => { - webRecord.model.load({ resId: thread.id }); + if (reloadFunc) { + reloadFunc(); + } + if (webRecord) { + webRecord.model.load({ resId: thread.id }); + } }); popoverViewOwner.delete(); }, @@ -117,11 +123,15 @@ registerModel({ markDoneView: one('ActivityMarkDonePopoverContentView', { inverse: 'activityListViewItemOwner', }), + reloadFunc: attr({ + compute() { + return this.activityListViewOwner.reloadFunc ? this.activityListViewOwner.reloadFunc : clear(); + }, + }), webRecord: attr({ compute() { - return this.activityListViewOwner.webRecord; + return this.activityListViewOwner.webRecord ? this.activityListViewOwner.webRecord : clear(); }, - required: true, }), }, }); diff --git a/addons/mail/static/src/models/activity_mark_done_popover_content_view.js b/addons/mail/static/src/models/activity_mark_done_popover_content_view.js index bf336944a48..daea5ac1bac 100644 --- a/addons/mail/static/src/models/activity_mark_done_popover_content_view.js +++ b/addons/mail/static/src/models/activity_mark_done_popover_content_view.js @@ -34,6 +34,7 @@ registerModel({ */ async onClickDone() { const chatter = this.activityViewOwner && this.activityViewOwner.activityBoxView.chatter; + const reloadFunc = this.reloadFunc; const webRecord = this.webRecord; const thread = this.activity.thread; await this.activity.markAsDone({ @@ -42,6 +43,9 @@ registerModel({ if (chatter && chatter.exists() && chatter.component) { chatter.reloadParentView(); } + if (reloadFunc) { + reloadFunc(); + } if (webRecord) { webRecord.model.load({ resId: thread.id }); } @@ -51,21 +55,25 @@ registerModel({ */ async onClickDoneAndScheduleNext() { const chatter = this.activityViewOwner && this.activityViewOwner.activityBoxView.chatter; + const reloadFunc = this.reloadFunc; const webRecord = this.webRecord; const thread = this.activity.thread; const activityListViewOwner = this.activityListViewItemOwner && this.activityListViewItemOwner.activityListViewOwner; - await this.activity.markAsDoneAndScheduleNext({ - feedback: this.feedbackTextareaRef.el.value, - }); + const activity = this.activity; + const feedback = this.feedbackTextareaRef.el.value; + if (activityListViewOwner && activityListViewOwner.exists()) { + activityListViewOwner.popoverViewOwner.delete(); + } + await activity.markAsDoneAndScheduleNext({ feedback }); if (chatter && chatter.exists() && chatter.component) { chatter.reloadParentView(); } + if (reloadFunc) { + reloadFunc(); + } if (webRecord) { webRecord.model.load({ resId: thread.id }); } - if (activityListViewOwner && activityListViewOwner.exists()) { - activityListViewOwner.popoverViewOwner.delete(); - } }, /** * Handles keydown on this activity mark done. @@ -141,6 +149,14 @@ registerModel({ identifying: true, inverse: 'activityMarkDonePopoverContentView', }), + reloadFunc: attr({ + compute() { + if (this.activityListViewItemOwner) { + return this.activityListViewItemOwner.reloadFunc; + } + return clear(); + }, + }), webRecord: attr({ compute() { if (this.activityListViewItemOwner) { diff --git a/addons/mail/static/src/models/file_uploader.js b/addons/mail/static/src/models/file_uploader.js index e27655f25f5..41ee430fe13 100644 --- a/addons/mail/static/src/models/file_uploader.js +++ b/addons/mail/static/src/models/file_uploader.js @@ -94,6 +94,7 @@ registerModel({ * @returns {Promise} */ async _performUpload({ files }) { + const reloadFunc = this.activityListViewItemOwner && this.activityListViewItemOwner.reloadFunc; const webRecord = this.activityListViewItemOwner && this.activityListViewItemOwner.webRecord; const composer = this.composerView && this.composerView.composer; // save before async const thread = this.thread; // save before async @@ -149,15 +150,18 @@ registerModel({ } } } + if (activity && activity.exists()) { + await activity.markAsDone({ attachments }); + } + if (reloadFunc) { + reloadFunc(); + } if (webRecord) { webRecord.model.load({ resId: thread.id }); } if (chatter && chatter.exists() && chatter.shouldReloadParentFromFileChanged) { chatter.reloadParentView(); } - if (activity && activity.exists()) { - activity.markAsDone({ attachments }); - } }, }, fields: { diff --git a/addons/mail/static/src/models/popover_view.js b/addons/mail/static/src/models/popover_view.js index 4afc474c418..043f0b014c5 100644 --- a/addons/mail/static/src/models/popover_view.js +++ b/addons/mail/static/src/models/popover_view.js @@ -50,9 +50,13 @@ registerModel({ identifying: true, inverse: 'activityListPopoverView', }), + activityCellViewOwnerAsActivityList: one('ActivityCellView', { + identifying: true, + inverse: 'activityListPopoverView', + }), activityListView: one('ActivityListView', { compute() { - return this.activityButtonViewOwnerAsActivityList ? {} : clear(); + return this.activityButtonViewOwnerAsActivityList || this.activityCellViewOwnerAsActivityList ? {} : clear(); }, inverse: 'popoverViewOwner', }), @@ -92,6 +96,9 @@ registerModel({ if (this.activityButtonViewOwnerAsActivityList) { return this.activityButtonViewOwnerAsActivityList.buttonRef; } + if (this.activityCellViewOwnerAsActivityList) { + return this.activityCellViewOwnerAsActivityList.contentRef; + } if (this.messageActionViewOwnerAsReaction) { return this.messageActionViewOwnerAsReaction.actionRef; } @@ -171,7 +178,7 @@ registerModel({ if (this.emojiPickerView) { return this.emojiPickerView; } - if (this.activityButtonViewOwnerAsActivityList) { + if (this.activityButtonViewOwnerAsActivityList || this.activityCellViewOwnerAsActivityList) { return this.activityListView; } if (this.messageNotificationPopoverContentView) { @@ -217,7 +224,7 @@ registerModel({ if (this.emojiPickerView) { return 'EmojiPickerView'; } - if (this.activityButtonViewOwnerAsActivityList) { + if (this.activityButtonViewOwnerAsActivityList || this.activityCellViewOwnerAsActivityList) { return 'ActivityListView'; } if (this.messageNotificationPopoverContentView) { @@ -296,6 +303,9 @@ registerModel({ if (this.activityButtonViewOwnerAsActivityList) { return 'bottom-start'; } + if (this.activityCellViewOwnerAsActivityList) { + return 'bottom-start'; + } if (this.messageActionViewOwnerAsReaction) { return 'top'; } diff --git a/addons/mail/static/src/scss/activity_view.scss b/addons/mail/static/src/scss/activity_view.scss index 329df6fcb4d..712c53fc440 100644 --- a/addons/mail/static/src/scss/activity_view.scss +++ b/addons/mail/static/src/scss/activity_view.scss @@ -4,11 +4,10 @@ thead > tr > th:first-of-type { min-width: 300px; } - tbody > tr > td, tfoot > tr > td { - cursor: pointer; - } } .o_activity_summary_cell { + padding: 0; // to cancel unwanted padding of coming from bootstrap + &.planned { background-color: map-get($theme-colors, 'success'); } @@ -18,19 +17,6 @@ &.today { background-color: map-get($theme-colors, 'warning'); } - .o_kanban_inline_block { - min-height: 42px; - } - .dropdown-toggle { - cursor: pointer; - .o_closest_deadline { - height: 42px; - width: 100%; - color: #FFF; - text-align: center; - line-height: 42px; - } - } &.o_activity_empty_cell { > i { display: none; @@ -44,19 +30,6 @@ } } } - .o_activity_btn > .badge { - @include o-position-absolute($bottom: 0, $right: 0); - - &.planned { - @extend .text-success; - } - &.overdue { - @extend .text-danger; - } - &.today { - @extend .text-warning; - } - } } // it contains a kanban card representing the record @@ -170,3 +143,7 @@ } } } + +.o_activity_view_table { + height: 1px; // this value is ignored on the table but it is necessary to ensure h-100 works on descendants to vertically center content inside cells +} diff --git a/addons/mail/static/src/xml/activity_view.xml b/addons/mail/static/src/xml/activity_view.xml index f0deed6c449..94da654ab88 100644 --- a/addons/mail/static/src/xml/activity_view.xml +++ b/addons/mail/static/src/xml/activity_view.xml @@ -15,7 +15,7 @@