[IMP] mail: automatically compute notification groups
Part of task-2258617 closes odoo/odoo#79789 Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
@@ -82,8 +82,7 @@ export class NotificationList extends Component {
|
||||
});
|
||||
let notifications = threadNeedactionNotifications.concat(threadNotifications);
|
||||
if (this.props.filter === 'all') {
|
||||
const notificationGroups = this.messaging.notificationGroupManager.groups;
|
||||
notifications = Object.values(notificationGroups)
|
||||
notifications = Object.values(this.messaging.models['mail.notification_group'].all())
|
||||
.sort((group1, group2) => group1.sequence - group2.sequence)
|
||||
.map(notificationGroup => {
|
||||
return {
|
||||
|
||||
@@ -389,9 +389,7 @@ function factory(dependencies) {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
_computeFailureNotifications() {
|
||||
return replace(this.notifications.filter(notifications =>
|
||||
['exception', 'bounce'].includes(notifications.notification_status)
|
||||
));
|
||||
return replace(this.notifications.filter(notifications => notifications.isFailure));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -570,9 +568,7 @@ function factory(dependencies) {
|
||||
attachments: many2many('mail.attachment', {
|
||||
inverse: 'messages',
|
||||
}),
|
||||
author: many2one('mail.partner', {
|
||||
inverse: 'messagesAsAuthor',
|
||||
}),
|
||||
author: many2one('mail.partner'),
|
||||
/**
|
||||
* This value is meant to be returned by the server
|
||||
* (and has been sanitized before stored into db).
|
||||
|
||||
@@ -375,11 +375,6 @@ function factory(dependencies) {
|
||||
isCausal: true,
|
||||
readonly: true,
|
||||
}),
|
||||
notificationGroupManager: one2one('mail.notification_group_manager', {
|
||||
default: insertAndReplace(),
|
||||
isCausal: true,
|
||||
readonly: true,
|
||||
}),
|
||||
notificationHandler: one2one('mail.messaging_notification_handler', {
|
||||
default: insertAndReplace(),
|
||||
isCausal: true,
|
||||
|
||||
@@ -224,7 +224,6 @@ function factory(dependencies) {
|
||||
message.update({ author: link(this.messaging.currentPartner) });
|
||||
}
|
||||
}));
|
||||
this.messaging.notificationGroupManager.computeGroups();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,12 +56,10 @@ function factory(dependencies) {
|
||||
channel.isPinned &&
|
||||
channel.localMessageUnreadCounter > 0
|
||||
)).length;
|
||||
const notificationGroupsCounter = this.messaging.notificationGroupManager
|
||||
? this.messaging.notificationGroupManager.groups.reduce(
|
||||
(total, group) => total + group.notifications.length,
|
||||
0
|
||||
)
|
||||
: 0;
|
||||
const notificationGroupsCounter = this.messaging.models['mail.notification_group'].all().reduce(
|
||||
(total, group) => total + group.notifications.length,
|
||||
0
|
||||
);
|
||||
const notificationPemissionCounter = this.messaging.isNotificationPermissionDefault ? 1 : 0;
|
||||
return inboxCounter + unreadChannelsCounter + notificationGroupsCounter + notificationPemissionCounter;
|
||||
}
|
||||
|
||||
-3
@@ -524,8 +524,6 @@ function factory(dependencies) {
|
||||
message.delete();
|
||||
}
|
||||
}
|
||||
// deleting message might have deleted notifications, force recompute
|
||||
this.messaging.notificationGroupManager.computeGroups();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -543,7 +541,6 @@ function factory(dependencies) {
|
||||
message.update({ author: link(this.messaging.currentPartner) });
|
||||
}
|
||||
}
|
||||
this.messaging.notificationGroupManager.computeGroups();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { registerNewModel } from '@mail/model/model_core';
|
||||
import { attr, many2one } from '@mail/model/model_field';
|
||||
import { insert, unlinkAll } from '@mail/model/model_field_command';
|
||||
import { clear, insert, insertAndReplace, unlinkAll } from '@mail/model/model_field_command';
|
||||
|
||||
function factory(dependencies) {
|
||||
|
||||
@@ -44,6 +44,46 @@ function factory(dependencies) {
|
||||
return data2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @returns {boolean}
|
||||
*/
|
||||
_computeIsFailure() {
|
||||
return ['exception', 'bounce'].includes(this.notification_status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @returns {boolean|FieldCommand}
|
||||
*/
|
||||
_computeIsFromCurrentUser() {
|
||||
if (!this.messaging || !this.messaging.currentPartner || !this.message || !this.message.author) {
|
||||
return clear();
|
||||
}
|
||||
return this.messaging.currentPartner === this.message.author;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @returns {FieldCommand}
|
||||
*/
|
||||
_computeNotificationGroup() {
|
||||
if (!this.isFailure || !this.isFromCurrentUser) {
|
||||
return clear();
|
||||
}
|
||||
const thread = this.message.originThread;
|
||||
// Notifications are grouped by model and notification_type.
|
||||
// Except for channel where they are also grouped by id because
|
||||
// we want to open the actual channel in discuss or chat window
|
||||
// and not its kanban/list/form view.
|
||||
return insertAndReplace({
|
||||
notification_type: this.notification_type,
|
||||
res_id: thread.model === 'mail.channel' ? thread.id : null,
|
||||
res_model: thread.model,
|
||||
res_model_name: thread.model_name,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Notification.fields = {
|
||||
@@ -52,9 +92,19 @@ function factory(dependencies) {
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
isFailure: attr({
|
||||
compute: '_computeIsFailure',
|
||||
}),
|
||||
isFromCurrentUser: attr({
|
||||
compute: '_computeIsFromCurrentUser',
|
||||
}),
|
||||
message: many2one('mail.message', {
|
||||
inverse: 'notifications',
|
||||
}),
|
||||
notificationGroup: many2one('mail.notification_group', {
|
||||
compute: '_computeNotificationGroup',
|
||||
inverse: 'notifications',
|
||||
}),
|
||||
notification_status: attr(),
|
||||
notification_type: attr(),
|
||||
partner: many2one('mail.partner'),
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { registerNewModel } from '@mail/model/model_core';
|
||||
import { attr, many2one, one2many } from '@mail/model/model_field';
|
||||
import { clear, insert, unlink } from '@mail/model/model_field_command';
|
||||
import { OnChange } from '@mail/model/model_onchange';
|
||||
|
||||
function factory(dependencies) {
|
||||
|
||||
@@ -90,6 +91,15 @@ function factory(dependencies) {
|
||||
return -Math.max(...this.notifications.map(notification => notification.message.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onChangeNotifications() {
|
||||
if (this.notifications.length === 0) {
|
||||
this.delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the view that displays all the records of the group.
|
||||
*
|
||||
@@ -127,13 +137,18 @@ function factory(dependencies) {
|
||||
date: attr({
|
||||
compute: '_computeDate',
|
||||
}),
|
||||
id: attr({
|
||||
notification_type: attr({
|
||||
readonly: true,
|
||||
}),
|
||||
notifications: one2many('mail.notification', {
|
||||
inverse: 'notificationGroup',
|
||||
}),
|
||||
res_id: attr({
|
||||
readonly: true,
|
||||
}),
|
||||
res_model: attr({
|
||||
readonly: true,
|
||||
required: true,
|
||||
}),
|
||||
notification_type: attr(),
|
||||
notifications: one2many('mail.notification'),
|
||||
res_model: attr(),
|
||||
res_model_name: attr(),
|
||||
/**
|
||||
* States the position of the group inside the notification list.
|
||||
@@ -149,7 +164,13 @@ function factory(dependencies) {
|
||||
compute: '_computeThread',
|
||||
})
|
||||
};
|
||||
NotificationGroup.identifyingFields = ['id'];
|
||||
NotificationGroup.identifyingFields = ['res_model', 'res_id', 'notification_type'];
|
||||
NotificationGroup.onChanges = [
|
||||
new OnChange({
|
||||
dependencies: ['notifications'],
|
||||
methodName: '_onChangeNotifications',
|
||||
}),
|
||||
];
|
||||
NotificationGroup.modelName = 'mail.notification_group';
|
||||
|
||||
return NotificationGroup;
|
||||
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { registerNewModel } from '@mail/model/model_core';
|
||||
import { one2many } from '@mail/model/model_field';
|
||||
import { link } from '@mail/model/model_field_command';
|
||||
|
||||
function factory(dependencies) {
|
||||
|
||||
class NotificationGroupManager extends dependencies['mail.model'] {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Public
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
computeGroups() {
|
||||
// not supported for guests
|
||||
if (this.messaging.isCurrentUserGuest) {
|
||||
return;
|
||||
}
|
||||
for (const group of this.groups) {
|
||||
group.delete();
|
||||
}
|
||||
const groups = [];
|
||||
// TODO batch insert, better logic task-2258605
|
||||
this.messaging.currentPartner.failureNotifications.forEach(notification => {
|
||||
const thread = notification.message.originThread;
|
||||
// Notifications are grouped by model and notification_type.
|
||||
// Except for channel where they are also grouped by id because
|
||||
// we want to open the actual channel in discuss or chat window
|
||||
// and not its kanban/list/form view.
|
||||
const channelId = thread.model === 'mail.channel' ? thread.id : null;
|
||||
const id = `${thread.model}/${channelId}/${notification.notification_type}`;
|
||||
const group = this.messaging.models['mail.notification_group'].insert({
|
||||
id,
|
||||
notification_type: notification.notification_type,
|
||||
res_model: thread.model,
|
||||
res_model_name: thread.model_name,
|
||||
});
|
||||
group.update({ notifications: link(notification) });
|
||||
// avoid linking the same group twice when adding a notification
|
||||
// to an existing group
|
||||
if (!groups.includes(group)) {
|
||||
groups.push(group);
|
||||
}
|
||||
});
|
||||
this.update({ groups: link(groups) });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NotificationGroupManager.fields = {
|
||||
groups: one2many('mail.notification_group'),
|
||||
};
|
||||
NotificationGroupManager.identifyingFields = ['messaging'];
|
||||
NotificationGroupManager.modelName = 'mail.notification_group_manager';
|
||||
|
||||
return NotificationGroupManager;
|
||||
}
|
||||
|
||||
registerNewModel('mail.notification_group_manager', factory);
|
||||
@@ -450,9 +450,6 @@ function factory(dependencies) {
|
||||
default: "",
|
||||
}),
|
||||
email: attr(),
|
||||
failureNotifications: one2many('mail.notification', {
|
||||
related: 'messagesAsAuthor.failureNotifications',
|
||||
}),
|
||||
/**
|
||||
* Whether an attempt was already made to fetch the user corresponding
|
||||
* to this partner. This prevents doing the same RPC multiple times.
|
||||
@@ -477,9 +474,6 @@ function factory(dependencies) {
|
||||
memberThreads: many2many('mail.thread', {
|
||||
inverse: 'members',
|
||||
}),
|
||||
messagesAsAuthor: one2many('mail.message', {
|
||||
inverse: 'author',
|
||||
}),
|
||||
model: attr({
|
||||
default: 'res.partner',
|
||||
}),
|
||||
|
||||
Reference in New Issue
Block a user