diff --git a/app/javascript/dashboard/helper/actionCable.js b/app/javascript/dashboard/helper/actionCable.js index 1dd656659..bbbbe8a8a 100644 --- a/app/javascript/dashboard/helper/actionCable.js +++ b/app/javascript/dashboard/helper/actionCable.js @@ -22,6 +22,7 @@ class ActionCableConnector extends BaseActionCableConnector { 'contact.deleted': this.onContactDelete, 'contact.updated': this.onContactUpdate, 'conversation.mentioned': this.onConversationMentioned, + 'notification.created': this.onNotificationCreated, }; } @@ -134,6 +135,10 @@ class ActionCableConnector extends BaseActionCableConnector { onContactUpdate = data => { this.app.$store.dispatch('contacts/updateContact', data); }; + + onNotificationCreated = data => { + this.app.$store.dispatch('notifications/addNotification', data); + }; } export default { diff --git a/app/javascript/dashboard/store/modules/notifications/actions.js b/app/javascript/dashboard/store/modules/notifications/actions.js index 8bc4fdfcd..d28020b37 100644 --- a/app/javascript/dashboard/store/modules/notifications/actions.js +++ b/app/javascript/dashboard/store/modules/notifications/actions.js @@ -52,4 +52,8 @@ export const actions = { throw new Error(error); } }, + + addNotification({ commit }, data) { + commit(types.ADD_NOTIFICATION, data); + }, }; diff --git a/app/javascript/dashboard/store/modules/notifications/mutations.js b/app/javascript/dashboard/store/modules/notifications/mutations.js index ca896835f..96e6816a6 100644 --- a/app/javascript/dashboard/store/modules/notifications/mutations.js +++ b/app/javascript/dashboard/store/modules/notifications/mutations.js @@ -45,4 +45,14 @@ export const mutations = { Vue.set($state.records[item.id], 'read_at', true); }); }, + + [types.ADD_NOTIFICATION]($state, data) { + const { notification, unread_count: unreadCount, count } = data; + Vue.set($state.records, notification.id, { + ...($state.records[notification.id] || {}), + ...notification, + }); + Vue.set($state.meta, 'unreadCount', unreadCount); + Vue.set($state.meta, 'count', count); + }, }; diff --git a/app/javascript/dashboard/store/modules/specs/notifications/actions.spec.js b/app/javascript/dashboard/store/modules/specs/notifications/actions.spec.js index fd94d9a67..7351905a0 100644 --- a/app/javascript/dashboard/store/modules/specs/notifications/actions.spec.js +++ b/app/javascript/dashboard/store/modules/specs/notifications/actions.spec.js @@ -90,4 +90,12 @@ describe('#actions', () => { await expect(actions.readAll({ commit })).rejects.toThrow(Error); }); }); + describe('#addNotification', () => { + it('sends correct actions if API is success', async () => { + await actions.addNotification({ commit }, { data: 1 }); + expect(commit.mock.calls).toEqual([ + [types.ADD_NOTIFICATION, { data: 1 }], + ]); + }); + }); }); diff --git a/app/javascript/dashboard/store/modules/specs/notifications/mutations.spec.js b/app/javascript/dashboard/store/modules/specs/notifications/mutations.spec.js index 15a097df7..ab8027c6e 100644 --- a/app/javascript/dashboard/store/modules/specs/notifications/mutations.spec.js +++ b/app/javascript/dashboard/store/modules/specs/notifications/mutations.spec.js @@ -93,4 +93,29 @@ describe('#mutations', () => { }); }); }); + + describe('#ADD_NOTIFICATION', () => { + it('add notification', () => { + const state = { + meta: { unreadCount: 4, count: 231 }, + records: { + 1: { id: 1, primary_actor_id: 1 }, + 2: { id: 2, primary_actor_id: 2 }, + }, + }; + const data = { + notification: { id: 3, primary_actor_id: 3 }, + unread_count: 5, + count: 232, + }; + mutations[types.ADD_NOTIFICATION](state, data); + expect(state.records).toEqual({ + 1: { id: 1, primary_actor_id: 1 }, + 2: { id: 2, primary_actor_id: 2 }, + 3: { id: 3, primary_actor_id: 3 }, + }); + expect(state.meta.unreadCount).toEqual(5); + expect(state.meta.count).toEqual(232); + }); + }); }); diff --git a/app/javascript/dashboard/store/mutation-types.js b/app/javascript/dashboard/store/mutation-types.js index 734e0b5e5..9a24fa3b4 100755 --- a/app/javascript/dashboard/store/mutation-types.js +++ b/app/javascript/dashboard/store/mutation-types.js @@ -116,6 +116,7 @@ export default { SET_NOTIFICATIONS_UNREAD_COUNT: 'SET_NOTIFICATIONS_UNREAD_COUNT', SET_NOTIFICATIONS_UI_FLAG: 'SET_NOTIFICATIONS_UI_FLAG', UPDATE_NOTIFICATION: 'UPDATE_NOTIFICATION', + ADD_NOTIFICATION: 'ADD_NOTIFICATION', UPDATE_ALL_NOTIFICATIONS: 'UPDATE_ALL_NOTIFICATIONS', SET_NOTIFICATIONS_ITEM: 'SET_NOTIFICATIONS_ITEM', SET_NOTIFICATIONS: 'SET_NOTIFICATIONS', diff --git a/app/listeners/action_cable_listener.rb b/app/listeners/action_cable_listener.rb index 6fe47953f..815103c33 100644 --- a/app/listeners/action_cable_listener.rb +++ b/app/listeners/action_cable_listener.rb @@ -2,9 +2,9 @@ class ActionCableListener < BaseListener include Events::Types def notification_created(event) - notification, account = extract_notification_and_account(event) + notification, account, unread_count, count = extract_notification_and_account(event) tokens = [event.data[:notification].user.pubsub_token] - broadcast(account, tokens, NOTIFICATION_CREATED, notification.push_event_data) + broadcast(account, tokens, NOTIFICATION_CREATED, { notification: notification.push_event_data, unread_count: unread_count, count: count }) end def message_created(event) diff --git a/app/listeners/base_listener.rb b/app/listeners/base_listener.rb index 4315d400d..21b84c34a 100644 --- a/app/listeners/base_listener.rb +++ b/app/listeners/base_listener.rb @@ -8,7 +8,9 @@ class BaseListener def extract_notification_and_account(event) notification = event.data[:notification] - [notification, notification.account] + unread_count = notification.user.notifications_meta[:unread_count] + count = notification.user.notifications_meta[:count] + [notification, notification.account, unread_count, count] end def extract_message_and_account(event) diff --git a/app/models/account.rb b/app/models/account.rb index c9b9befdb..22aeefcaf 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -72,6 +72,7 @@ class Account < ApplicationRecord has_many :sms_channels, dependent: :destroy_async, class_name: '::Channel::Sms' has_many :working_hours, dependent: :destroy_async has_many :automation_rules, dependent: :destroy + has_many :notifications, dependent: :destroy has_flags ACCOUNT_SETTINGS_FLAGS.merge(column: 'settings_flags').merge(DEFAULT_QUERY_SETTING) diff --git a/app/models/notification.rb b/app/models/notification.rb index 863f1cd39..e0b1ef5ec 100644 --- a/app/models/notification.rb +++ b/app/models/notification.rb @@ -52,15 +52,24 @@ class Notification < ApplicationRecord notification_type: notification_type, primary_actor_type: primary_actor_type, primary_actor_id: primary_actor_id, - primary_actor: primary_actor.push_event_data, + primary_actor: primary_actor_data, read_at: read_at, secondary_actor: secondary_actor&.push_event_data, user: user&.push_event_data, - created_at: created_at, - account_id: account_id + created_at: created_at.to_i, + account_id: account_id, + push_message_title: push_message_title } end + def primary_actor_data + if %w[assigned_conversation_new_message conversation_mention].include? notification_type + primary_actor.conversation.push_event_data + else + primary_actor.push_event_data + end + end + def fcm_push_data { id: id, diff --git a/app/models/user.rb b/app/models/user.rb index ad4abc142..8c4b3ce2f 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -187,4 +187,11 @@ class User < ApplicationRecord def will_save_change_to_email? mutations_from_database.changed?('email') end + + def notifications_meta + { + unread_count: notifications.where(read_at: nil).count, + count: notifications.count + } + end end