diff --git a/addons/mail/controllers/discuss/channel.py b/addons/mail/controllers/discuss/channel.py index cc22a81f7cd..71f3789a4b5 100644 --- a/addons/mail/controllers/discuss/channel.py +++ b/addons/mail/controllers/discuss/channel.py @@ -52,17 +52,17 @@ class ChannelController(http.Controller): @http.route("/discuss/channel/messages", methods=["POST"], type="json", auth="public") @add_guest_to_context - def discuss_channel_messages(self, channel_id, before=None, after=None, limit=30, around=None): + def discuss_channel_messages(self, channel_id, search_term=None, before=None, after=None, limit=30, around=None): channel_member_sudo = request.env["discuss.channel.member"]._get_as_sudo_from_context_or_raise(channel_id=int(channel_id)) domain = [ ("res_id", "=", channel_id), ("model", "=", "discuss.channel"), ("message_type", "!=", "user_notification"), ] - messages = channel_member_sudo.env["mail.message"]._message_fetch(domain, before, after, around, limit) + res = channel_member_sudo.env["mail.message"]._message_fetch(domain, search_term=search_term, before=before, after=after, around=around, limit=limit) if not request.env.user._is_public() and not around: - messages.set_message_done() - return messages.message_format() + res["messages"].set_message_done() + return {**res, "messages": res["messages"].message_format()} @http.route("/discuss/channel/pinned_messages", methods=["POST"], type="json", auth="public") @add_guest_to_context diff --git a/addons/mail/controllers/mailbox.py b/addons/mail/controllers/mailbox.py index 26397082de6..4946680e068 100644 --- a/addons/mail/controllers/mailbox.py +++ b/addons/mail/controllers/mailbox.py @@ -6,19 +6,20 @@ from odoo.http import request class MailboxController(http.Controller): @http.route("/mail/inbox/messages", methods=["POST"], type="json", auth="user") - def discuss_inbox_messages(self, before=None, after=None, limit=30, around=None): + def discuss_inbox_messages(self, search_term=None, before=None, after=None, limit=30, around=None): partner_id = request.env.user.partner_id.id domain = [("needaction", "=", True)] - return (request.env["mail.message"] - ._message_fetch(domain, before, after, around, limit) - ._message_format_personalize(partner_id)) + res = request.env["mail.message"]._message_fetch(domain, search_term=search_term, before=before, after=after, around=around, limit=limit) + return {**res, "messages": res["messages"]._message_format_personalize(partner_id)} @http.route("/mail/history/messages", methods=["POST"], type="json", auth="user") - def discuss_history_messages(self, before=None, after=None, limit=30): + def discuss_history_messages(self, search_term=None, before=None, after=None, limit=30, around=None): domain = [("needaction", "=", False)] - return request.env["mail.message"]._message_fetch(domain, before, after, limit=limit).message_format() + res = request.env["mail.message"]._message_fetch(domain, search_term=search_term, before=before, after=after, around=around, limit=limit) + return {**res, "messages": res["messages"].message_format()} @http.route("/mail/starred/messages", methods=["POST"], type="json", auth="user") - def discuss_starred_messages(self, before=None, after=None, limit=30): + def discuss_starred_messages(self, search_term=None, before=None, after=None, limit=30, around=None): domain = [("starred_partner_ids", "in", [request.env.user.partner_id.id])] - return request.env["mail.message"]._message_fetch(domain, before, after, limit=limit).message_format() + res = request.env["mail.message"]._message_fetch(domain, search_term=search_term, before=before, after=after, around=around, limit=limit) + return {**res, "messages": res["messages"].message_format()} diff --git a/addons/mail/controllers/thread.py b/addons/mail/controllers/thread.py index ca0a293bf58..92d483d4c73 100644 --- a/addons/mail/controllers/thread.py +++ b/addons/mail/controllers/thread.py @@ -16,16 +16,16 @@ class ThreadController(http.Controller): return thread._get_mail_thread_data(request_list) @http.route("/mail/thread/messages", methods=["POST"], type="json", auth="user") - def mail_thread_messages(self, thread_model, thread_id, before=None, after=None, around=None, limit=30): + def mail_thread_messages(self, thread_model, thread_id, search_term=None, before=None, after=None, around=None, limit=30): domain = [ ("res_id", "=", int(thread_id)), ("model", "=", thread_model), ("message_type", "!=", "user_notification"), ] - messages = request.env["mail.message"]._message_fetch(domain, before, after, around, limit) + res = request.env["mail.message"]._message_fetch(domain, search_term=search_term, before=before, after=after, around=around, limit=limit) if not request.env.user._is_public(): - messages.set_message_done() - return messages.message_format() + res["messages"].set_message_done() + return {**res, "messages": res["messages"].message_format()} @http.route("/mail/partner/from_email", methods=["POST"], type="json", auth="user") def mail_thread_partner_from_email(self, emails): diff --git a/addons/mail/models/discuss/discuss_channel.py b/addons/mail/models/discuss/discuss_channel.py index 071175c56a3..6c0ee29a2fa 100644 --- a/addons/mail/models/discuss/discuss_channel.py +++ b/addons/mail/models/discuss/discuss_channel.py @@ -898,7 +898,8 @@ class Channel(models.Model): domain = ["&", ("model", "=", "discuss.channel"), ("res_id", "in", self.ids)] if last_id: domain.append(("id", "<", last_id)) - return self.env['mail.message']._message_fetch(domain=domain, limit=limit).message_format() + res = self.env['mail.message']._message_fetch(domain=domain, limit=limit) + return res["messages"].message_format() def _channel_format(self, fields=None): if not fields: diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py index d0041d72154..ea1f4f8201a 100644 --- a/addons/mail/models/mail_message.py +++ b/addons/mail/models/mail_message.py @@ -933,28 +933,31 @@ class Message(models.Model): return {} @api.model - def _message_fetch(self, domain, before=None, after=None, around=None, limit=30): - """ Get a limited amount of formatted messages with provided domain. - :param domain: the domain to filter messages; - :param before: fetch messages before this message id. - :param after: fetch messages after this message id. - :param around: fetch messages around this message id - i.e. limit//2 before and limit//2 after. - :param limit: the maximum amount of messages to get; - :returns: record set of mail.message sorted in descending order. - """ + def _message_fetch(self, domain, search_term=None, before=None, after=None, around=None, limit=30): + res = {} + if search_term: + # we replace every space by a % to avoid hard spacing matching + search_term = search_term.replace(" ", "%") + domain = expression.AND([domain, expression.OR([ + [("attachment_ids.name", "ilike", search_term)], + [("body", "ilike", search_term)], + [("subject", "ilike", search_term)], + [("subtype_id.description", "ilike", search_term)], + ])]) + domain = expression.AND([domain, [("message_type", "not in", ["user_notification", "notification"])]]) + res["count"] = self.search_count(domain) if around: messages_before = self.search(domain=[*domain, ('id', '<=', around)], limit=limit // 2, order="id DESC") messages_after = self.search(domain=[*domain, ('id', '>', around)], limit=limit // 2, order='id ASC') - return (messages_after + messages_before).sorted('id', reverse=True) + return {**res, "messages": (messages_after + messages_before).sorted('id', reverse=True)} if before: domain = expression.AND([domain, [('id', '<', before)]]) if after: domain = expression.AND([domain, [('id', '>', after)]]) - message_ids = self.search(domain, limit=limit, order='id ASC' if after else 'id DESC') + res["messages"] = self.search(domain, limit=limit, order='id ASC' if after else 'id DESC') if after: - message_ids = message_ids.sorted('id', reverse=True) - return message_ids + res["messages"] = res["messages"].sorted('id', reverse=True) + return res def message_format(self, format_reply=True, msg_vals=None): """ Get the message values in the format for web client. Since message diff --git a/addons/mail/static/src/core/common/attachment_list.js b/addons/mail/static/src/core/common/attachment_list.js index eb753b5f858..aec25ee1878 100644 --- a/addons/mail/static/src/core/common/attachment_list.js +++ b/addons/mail/static/src/core/common/attachment_list.js @@ -13,10 +13,11 @@ import { url } from "@web/core/utils/urls"; * @property {import("models").Attachment[]} attachments * @property {function} unlinkAttachment * @property {number} imagesHeight + * @property {ReturnType} [messageSearch] * @extends {Component} */ export class AttachmentList extends Component { - static props = ["attachments", "unlinkAttachment", "imagesHeight"]; + static props = ["attachments", "unlinkAttachment", "imagesHeight", "messageSearch?"]; static template = "mail.AttachmentList"; setup() { diff --git a/addons/mail/static/src/core/common/attachment_list.xml b/addons/mail/static/src/core/common/attachment_list.xml index 7a948ac6d75..68c153063b6 100644 --- a/addons/mail/static/src/core/common/attachment_list.xml +++ b/addons/mail/static/src/core/common/attachment_list.xml @@ -65,7 +65,7 @@