diff --git a/pos_chatter/__init__.py b/pos_chatter/__init__.py index eb43f035a..d773dae75 100644 --- a/pos_chatter/__init__.py +++ b/pos_chatter/__init__.py @@ -19,3 +19,4 @@ # If not, see . ################################################################################ from . import controllers +from . import models diff --git a/pos_chatter/controllers/systray.py b/pos_chatter/controllers/systray.py index f5adfb086..72a16a6b8 100644 --- a/pos_chatter/controllers/systray.py +++ b/pos_chatter/controllers/systray.py @@ -38,21 +38,31 @@ class SystrayController(http.Controller): @http.route('/pos_systray/message_data', auth='public', type='json') def get_data_pos_systray(self): - """ - Summary: - Getting data to the Message chatter list. - Return: - it contains details about chatter list. - """ - return [{'id': mail_channel_id.id, - 'type': mail_channel_id.channel_type, - 'name': mail_channel_id.name, - 'message_body': request.env['mail.message'].search( - [('model', '=', 'discuss.channel'), - ('res_id', '=', mail_channel_id.id)], limit=1).body - } for mail_channel_id in request.env['discuss.channel'].search([]) - for partner_id in mail_channel_id.channel_partner_ids - if partner_id.id == request.env.user.partner_id.id] + channels = request.env['discuss.channel'].search([]) + partner_id = request.env.user.partner_id.id + + data = [] + for mail_channel in channels: + if partner_id in mail_channel.channel_partner_ids.ids: + message = request.env['mail.message'].search( + [('model', '=', 'discuss.channel'), + ('res_id', '=', mail_channel.id)], + limit=1, order="id desc" + ) + messages = request.env['mail.message'].search_count( + [('model', '=', 'discuss.channel'), + ('res_id', '=', mail_channel.id), + ('is_read', '=', False)] + ) + data.append({ + 'message_id': message.id, + 'id': mail_channel.id, + 'type': mail_channel.channel_type, + 'name': mail_channel.name, + 'message_body': message.body if message else "", + 'count': messages + }) + return data @http.route('/pos_systray/chat_message', auth='public', type='json') def get_data_chat_box(self, **kw): @@ -105,6 +115,7 @@ class SystrayController(http.Controller): 'model': 'discuss.channel', 'res_id': int(data['res_id']), 'message_type': 'comment', + 'is_read': True, 'author_id': request.env.user.partner_id.id }) return True diff --git a/pos_chatter/models/__init__.py b/pos_chatter/models/__init__.py new file mode 100644 index 000000000..a2bc21ba5 --- /dev/null +++ b/pos_chatter/models/__init__.py @@ -0,0 +1 @@ +from . import mail_message diff --git a/pos_chatter/models/mail_message.py b/pos_chatter/models/mail_message.py new file mode 100644 index 000000000..d4e51d2cc --- /dev/null +++ b/pos_chatter/models/mail_message.py @@ -0,0 +1,29 @@ +from odoo import models, fields , api + + +class MailMessage(models.Model): + _inherit = "mail.message" + + is_read = fields.Boolean(string="Read", default=False) + + @api.model + def compute_read_message(self, datas): + print(datas) + try: + messages = self.env['mail.message'].search([ + ('model', '=', 'discuss.channel'), + ('res_id', '=', datas), + ('is_read', '=', False) + ]) + for message in messages: + if message.is_read is False: + message.write({'is_read': True}) + print(f"Marked messages as read: {message.ids}") + else: + print("No unread messages found.") + except Exception as e: + print(f"An error occurred: {str(e)}") + + + + diff --git a/pos_chatter/static/description/assets/screenshots/1.png b/pos_chatter/static/description/assets/screenshots/1.png index a3b37c99f..68681b491 100644 Binary files a/pos_chatter/static/description/assets/screenshots/1.png and b/pos_chatter/static/description/assets/screenshots/1.png differ diff --git a/pos_chatter/static/description/assets/screenshots/2.png b/pos_chatter/static/description/assets/screenshots/2.png index c690610e7..f539bb126 100644 Binary files a/pos_chatter/static/description/assets/screenshots/2.png and b/pos_chatter/static/description/assets/screenshots/2.png differ diff --git a/pos_chatter/static/description/index.html b/pos_chatter/static/description/index.html index 808a8f536..23afb5bf4 100644 --- a/pos_chatter/static/description/index.html +++ b/pos_chatter/static/description/index.html @@ -161,7 +161,7 @@

- Chat list.

+ Chat list with unread message counts.
diff --git a/pos_chatter/static/src/js/pos_msg_view.js b/pos_chatter/static/src/js/pos_msg_view.js index 0e3a9ce21..1bf33f410 100644 --- a/pos_chatter/static/src/js/pos_msg_view.js +++ b/pos_chatter/static/src/js/pos_msg_view.js @@ -1,87 +1,126 @@ /** @odoo-module **/ import { jsonrpc } from "@web/core/network/rpc_service"; -const { mount,xml, onMounted, useState, useRef} = owl; -import { ChatMsgView } from "./pos_chat_view" +const { mount, xml, onMounted, useState, useRef } = owl; +import { ChatMsgView } from "./pos_chat_view"; + export class PosMsgView extends owl.Component { - setup(){ - super.setup() - this.root = useRef("root") - onMounted(this.render_msg_view) + setup() { + super.setup(); + this.root = useRef("root"); + onMounted(this.render_msg_view); this.MsgWindow = new ChatMsgView(); this.state = useState({ - 'data': {} + data: [], + counts: { + all: 0, + chat: 0, + channels: 0 + } }); } - /** for getting all chat list */ - render_msg_view(data){ - var self = this - jsonrpc('/pos_systray/message_data',).then(function(data){ - var message_list = [] - var messages = data - $(messages).each(function(message){ - const htmlString = messages[message].message_body; + + /** Fetch all chat messages */ + render_msg_view() { + const self = this; + jsonrpc("/pos_systray/message_data").then((data) => { + const message_list = data.map((message) => { const parser = new DOMParser(); - const parsedHtml = parser.parseFromString(htmlString, 'text/html'); - const plainText = parsedHtml.documentElement.textContent; - message_list.push({ - 'id': messages[message].id, - 'type': messages[message].type, - 'name': messages[message].name, - 'message_body': plainText - }) + const parsedHtml = parser.parseFromString(message.message_body, "text/html"); + let plainText = parsedHtml.documentElement.textContent; + + // Format SMS failure messages + if (message.type === 'sms_failure') { + plainText = `SMS Failure: Contact\nAn error occurred when sending an SMS\nAug 18`; + } + + return { + id: message.id, + type: message.type, + name: message.name, + message_body: plainText, + count: message.count || 0, + }; }); - self.state.data = message_list - }) + + // Calculate counts for each category + const counts = { + chat: message_list.filter(m => m.type === 'chat').reduce((sum, msg) => sum + msg.count, 0), + all: message_list.filter(m => m.type === 'channel').reduce((sum, msg) => sum + msg.count, 0), + channels: message_list.reduce((sum, msg) => sum + msg.count, 0), + }; + + self.state.data = message_list; + self.state.counts = counts; + }).catch((error) => { + console.error("Error fetching messages:", error); + alert("Failed to load messages. Please try again."); + }); } - /** for click function for navbar*/ - _onClickAllMessage(){ - this.root.el.querySelector('#all_message').style.display = "block" - this.root.el.querySelector('#all_chat').style.display = "none" - this.root.el.querySelector('#all_channels').style.display = "none" - this.root.el.querySelector('#all_message_button').style.color = "#000" - this.root.el.querySelector('#all_chat_button').style.color = "#9c9a97" - this.root.el.querySelector('#all_channels_button').style.color = "#9c9a97" + /** Toggle visibility between All, Chat, and Channels */ + toggleView(activeButtonId, activeSectionId) { + ["all_message", "all_chat", "all_channels"].forEach((id) => { + const element = this.root.el.querySelector(`#${id}`); + if (element) { + element.style.display = id === activeSectionId ? "block" : "none"; + } + }); + + ["all_message_button", "all_chat_button", "all_channels_button"].forEach((id) => { + const element = this.root.el.querySelector(`#${id}`); + if (element) { + element.style.color = id === activeButtonId ? "#000" : "#9c9a97"; + } + }); + } + + _onClickAllMessage() { + this.toggleView("all_message_button", "all_message"); } - /** for click function for navbar*/ - _onClickAllChannels(){ - this.root.el.querySelector('#all_message').style.display = "none" - this.root.el.querySelector('#all_chat').style.display = "none" - this.root.el.querySelector('#all_channels').style.display = "block" - this.root.el.querySelector('#all_message_button').style.color = "#9c9a97" - this.root.el.querySelector('#all_chat_button').style.color = "#9c9a97" - this.root.el.querySelector('#all_channels_button').style.color = "#000" + + _onClickAllChannels() { + this.toggleView("all_channels_button", "all_channels"); } - /** for click function for navbar*/ - _onClickAllChat(){ - this.root.el.querySelector('#all_message').style.display = "none" - this.root.el.querySelector('#all_chat').style.display = "block" - this.root.el.querySelector('#all_channels').style.display = "none" - this.root.el.querySelector('#all_message_button').style.color = "#9c9a97" - this.root.el.querySelector('#all_chat_button').style.color = "#000" - this.root.el.querySelector('#all_channels_button').style.color = "#9c9a97" + + _onClickAllChat() { + this.toggleView("all_chat_button", "all_chat"); } - /** On clicking the chat or channel open the corresponding chat view */ - _onClickToMessage(ev){ - var self = this - var channel_id = ev.currentTarget.getAttribute("value") - this.__owl__.remove() - if($("#pos_chat_view").length == 0){ - this.schedule_dropdown = mount(ChatMsgView, document.body, {props: { - channel_id - }}) - }else if($("#pos_chat_view").length > 0){ - this.schedule_dropdown = mount(ChatMsgView, document.body, {props: { - channel_id - }}) + + /** Open chat view */ + _onClickToMessage(ev) { + const channel_id = ev.currentTarget.getAttribute("value"); + if (!channel_id || isNaN(parseInt(channel_id))) { + console.error("Invalid channel_id:", channel_id); + alert("Cannot open chat: Invalid message ID"); + return; } + + const self = this; + jsonrpc("/web/dataset/call_kw/mail.message/compute_read_message", { + model: "mail.message", + method: "compute_read_message", + args: [parseInt(channel_id)], + kwargs: {} + }).then(() => { + self.__owl__.remove(); + self.schedule_dropdown = mount(ChatMsgView, document.body, { props: { channel_id: parseInt(channel_id) } }); + }).catch((error) => { + console.error("RPC Error Details:", { + message: error.message, + data: error.data, + type: error.type, + stack: error.stack + }); + alert("Failed to load chat. Please try again."); + }); } } -PosMsgView.template = xml` - //template for pos messages list view -
-
+ +PosMsgView.template = xml` +
+
+

All

Channels

-
-
- + + + +
+
+
+
-
- - - - - - -
+ margin-bottom: 15px;padding: 4px 12px;display:flex;cursor:pointer;position:relative;" t-att-value="data.id" + t-on-click="_onClickToMessage"> +
+ + + + + + + + + +
- -
- +
+ + + +
+ +
-
-
-