mirror of
https://github.com/abhinavxd/libredesk.git
synced 2025-10-24 00:23:36 +00:00
feat: store last message sender in conversation as this will be used to show the Reply icon in the conversations list.
- Introduces new column `last_message_sender` in conversations table. - Changes to propogate this new column in websocket updates.
This commit is contained in:
@@ -39,10 +39,14 @@
|
|||||||
|
|
||||||
<!-- Message preview and unread count -->
|
<!-- Message preview and unread count -->
|
||||||
<div class="flex items-start justify-between gap-2">
|
<div class="flex items-start justify-between gap-2">
|
||||||
<p class="text-sm text-gray-600 line-clamp-2 flex-1">
|
<div class="text-sm text-gray-600 flex items-center gap-1.5 flex-1">
|
||||||
<Reply class="inline-block w-4 h-4 mr-1.5 text-green-600 flex-shrink-0" />
|
<Reply
|
||||||
|
class="text-green-600 flex-shrink-0"
|
||||||
|
size="15"
|
||||||
|
v-if="conversation.last_message_sender === 'agent'"
|
||||||
|
/>
|
||||||
{{ trimmedLastMessage }}
|
{{ trimmedLastMessage }}
|
||||||
</p>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="conversation.unread_message_count > 0"
|
v-if="conversation.unread_message_count > 0"
|
||||||
class="flex items-center justify-center w-6 h-6 bg-green-600 text-white text-xs font-medium rounded-full"
|
class="flex items-center justify-center w-6 h-6 bg-green-600 text-white text-xs font-medium rounded-full"
|
||||||
|
|||||||
@@ -545,10 +545,12 @@ export const useConversationStore = defineStore('conversation', () => {
|
|||||||
if (listConversation) {
|
if (listConversation) {
|
||||||
listConversation.last_message = message.content
|
listConversation.last_message = message.content
|
||||||
listConversation.last_message_at = message.created_at
|
listConversation.last_message_at = message.created_at
|
||||||
|
listConversation.last_message_sender = message.sender_type
|
||||||
if (listConversation.uuid !== conversation?.data?.uuid) {
|
if (listConversation.uuid !== conversation?.data?.uuid) {
|
||||||
listConversation.unread_message_count += 1
|
listConversation.unread_message_count += 1
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Conversation is not in the list, fetch the first page of the conversations list as this updated conversation might be at the top.
|
||||||
fetchFirstPageConversations()
|
fetchFirstPageConversations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ export class WebSocketClient {
|
|||||||
|
|
||||||
const data = JSON.parse(event.data)
|
const data = JSON.parse(event.data)
|
||||||
const handlers = {
|
const handlers = {
|
||||||
|
// On new message, update the message in the conversation list and in the currently opened conversation.
|
||||||
[WS_EVENT.NEW_MESSAGE]: () => {
|
[WS_EVENT.NEW_MESSAGE]: () => {
|
||||||
this.convStore.updateConversationList(data.data)
|
this.convStore.updateConversationList(data.data)
|
||||||
this.convStore.updateConversationMessage(data.data)
|
this.convStore.updateConversationMessage(data.data)
|
||||||
|
|||||||
@@ -399,8 +399,8 @@ func (c *Manager) ActiveUserConversationsCount(userID int) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateConversationLastMessage updates the last message details for a conversation.
|
// UpdateConversationLastMessage updates the last message details for a conversation.
|
||||||
func (c *Manager) UpdateConversationLastMessage(convesationID int, conversationUUID, lastMessage string, lastMessageAt time.Time) error {
|
func (c *Manager) UpdateConversationLastMessage(conversation int, conversationUUID, lastMessage, lastMessageSenderType string, lastMessageAt time.Time) error {
|
||||||
if _, err := c.q.UpdateConversationLastMessage.Exec(convesationID, conversationUUID, lastMessage, lastMessageAt); err != nil {
|
if _, err := c.q.UpdateConversationLastMessage.Exec(conversation, conversationUUID, lastMessage, lastMessageSenderType, lastMessageAt); err != nil {
|
||||||
c.lo.Error("error updating conversation last message", "error", err)
|
c.lo.Error("error updating conversation last message", "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -356,10 +356,10 @@ func (m *Manager) InsertMessage(message *models.Message) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update conversation last message details in conversation metadata.
|
// Update conversation last message details in conversation metadata.
|
||||||
m.UpdateConversationLastMessage(message.ConversationID, message.ConversationUUID, message.TextContent, message.CreatedAt)
|
m.UpdateConversationLastMessage(message.ConversationID, message.ConversationUUID, message.TextContent, message.SenderType, message.CreatedAt)
|
||||||
|
|
||||||
// Broadcast new message.
|
// Broadcast new message.
|
||||||
m.BroadcastNewMessage(message.ConversationUUID, message.TextContent, message.UUID, message.CreatedAt.Format(time.RFC3339), message.Type, message.Private)
|
m.BroadcastNewMessage(message)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ type Conversation struct {
|
|||||||
CustomAttributes pq.StringArray `db:"custom_attributes" json:"custom_attributes"`
|
CustomAttributes pq.StringArray `db:"custom_attributes" json:"custom_attributes"`
|
||||||
LastMessageAt null.Time `db:"last_message_at" json:"last_message_at"`
|
LastMessageAt null.Time `db:"last_message_at" json:"last_message_at"`
|
||||||
LastMessage null.String `db:"last_message" json:"last_message"`
|
LastMessage null.String `db:"last_message" json:"last_message"`
|
||||||
|
LastMessageSender null.String `db:"last_message_sender" json:"last_message_sender"`
|
||||||
Contact umodels.User `db:"contact" json:"contact"`
|
Contact umodels.User `db:"contact" json:"contact"`
|
||||||
SLAPolicyID null.Int `db:"sla_policy_id" json:"sla_policy_id"`
|
SLAPolicyID null.Int `db:"sla_policy_id" json:"sla_policy_id"`
|
||||||
SlaPolicyName null.String `db:"sla_policy_name" json:"sla_policy_name"`
|
SlaPolicyName null.String `db:"sla_policy_name" json:"sla_policy_name"`
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ SELECT
|
|||||||
conversations.subject,
|
conversations.subject,
|
||||||
conversations.last_message,
|
conversations.last_message,
|
||||||
conversations.last_message_at,
|
conversations.last_message_at,
|
||||||
|
conversations.last_message_sender,
|
||||||
conversations.next_sla_deadline_at,
|
conversations.next_sla_deadline_at,
|
||||||
conversations.priority_id,
|
conversations.priority_id,
|
||||||
(
|
(
|
||||||
@@ -197,7 +198,7 @@ SET assignee_last_seen_at = now(),
|
|||||||
WHERE uuid = $1;
|
WHERE uuid = $1;
|
||||||
|
|
||||||
-- name: update-conversation-last-message
|
-- name: update-conversation-last-message
|
||||||
UPDATE conversations SET last_message = $3, last_message_at = $4 WHERE CASE
|
UPDATE conversations SET last_message = $3, last_message_sender = $4, last_message_at = $5, updated_at = NOW() WHERE CASE
|
||||||
WHEN $1 > 0 THEN id = $1
|
WHEN $1 > 0 THEN id = $1
|
||||||
ELSE uuid = $2
|
ELSE uuid = $2
|
||||||
END
|
END
|
||||||
|
|||||||
@@ -2,24 +2,26 @@ package conversation
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
cmodels "github.com/abhinavxd/libredesk/internal/conversation/models"
|
||||||
wsmodels "github.com/abhinavxd/libredesk/internal/ws/models"
|
wsmodels "github.com/abhinavxd/libredesk/internal/ws/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BroadcastNewMessage broadcasts a new message to all users.
|
// BroadcastNewMessage broadcasts a new message to all users.
|
||||||
func (m *Manager) BroadcastNewMessage(conversationUUID, content, messageUUID, lastMessageAt, typ string, private bool) {
|
func (m *Manager) BroadcastNewMessage(message *cmodels.Message) {
|
||||||
message := wsmodels.Message{
|
m.broadcastToUsers([]int{}, wsmodels.Message{
|
||||||
Type: wsmodels.MessageTypeNewMessage,
|
Type: wsmodels.MessageTypeNewMessage,
|
||||||
Data: map[string]interface{}{
|
Data: map[string]interface{}{
|
||||||
"conversation_uuid": conversationUUID,
|
"conversation_uuid": message.ConversationUUID,
|
||||||
"content": content,
|
"content": message.TextContent,
|
||||||
"created_at": lastMessageAt,
|
"created_at": message.CreatedAt.Format(time.RFC3339),
|
||||||
"uuid": messageUUID,
|
"uuid": message.UUID,
|
||||||
"private": private,
|
"private": message.Private,
|
||||||
"type": typ,
|
"type": message.Type,
|
||||||
|
"sender_type": message.SenderType,
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
m.broadcastToUsers([]int{}, message)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BroadcastMessageUpdate broadcasts a message update to all users.
|
// BroadcastMessageUpdate broadcasts a message update to all users.
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ CREATE TABLE conversations (
|
|||||||
waiting_since TIMESTAMPTZ NULL,
|
waiting_since TIMESTAMPTZ NULL,
|
||||||
last_message_at TIMESTAMPTZ NULL,
|
last_message_at TIMESTAMPTZ NULL,
|
||||||
last_message TEXT NULL,
|
last_message TEXT NULL,
|
||||||
|
last_message_sender message_sender_type NULL,
|
||||||
next_sla_deadline_at TIMESTAMPTZ NULL,
|
next_sla_deadline_at TIMESTAMPTZ NULL,
|
||||||
snoozed_until TIMESTAMPTZ NULL
|
snoozed_until TIMESTAMPTZ NULL
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user