mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-30 02:32:29 +00:00 
			
		
		
		
	feat: Add notification.updated event (#8871)
				
					
				
			This commit is contained in:
		| @@ -24,6 +24,7 @@ class ActionCableConnector extends BaseActionCableConnector { | ||||
|       'conversation.mentioned': this.onConversationMentioned, | ||||
|       'notification.created': this.onNotificationCreated, | ||||
|       'notification.deleted': this.onNotificationDeleted, | ||||
|       'notification.updated': this.onNotificationUpdated, | ||||
|       'first.reply.created': this.onFirstReplyCreated, | ||||
|       'conversation.read': this.onConversationRead, | ||||
|       'conversation.updated': this.onConversationUpdated, | ||||
| @@ -200,6 +201,10 @@ class ActionCableConnector extends BaseActionCableConnector { | ||||
|     this.app.$store.dispatch('notifications/deleteNotification', data); | ||||
|   }; | ||||
|  | ||||
|   onNotificationUpdated = data => { | ||||
|     this.app.$store.dispatch('notifications/updateNotification', data); | ||||
|   }; | ||||
|  | ||||
|   // eslint-disable-next-line class-methods-use-this | ||||
|   onFirstReplyCreated = () => { | ||||
|     bus.$emit('fetch_overview_reports'); | ||||
|   | ||||
| @@ -54,7 +54,7 @@ export const actions = { | ||||
|     try { | ||||
|       await NotificationsAPI.read(primaryActorType, primaryActorId); | ||||
|       commit(types.SET_NOTIFICATIONS_UNREAD_COUNT, unreadCount - 1); | ||||
|       commit(types.UPDATE_NOTIFICATION, { id, read_at: new Date() }); | ||||
|       commit(types.READ_NOTIFICATION, { id, read_at: new Date() }); | ||||
|       commit(types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false }); | ||||
|     } catch (error) { | ||||
|       commit(types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false }); | ||||
| @@ -64,7 +64,7 @@ export const actions = { | ||||
|     commit(types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: true }); | ||||
|     try { | ||||
|       await NotificationsAPI.unRead(id); | ||||
|       commit(types.UPDATE_NOTIFICATION, { id, read_at: null }); | ||||
|       commit(types.READ_NOTIFICATION, { id, read_at: null }); | ||||
|       commit(types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false }); | ||||
|     } catch (error) { | ||||
|       commit(types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false }); | ||||
| @@ -127,6 +127,7 @@ export const actions = { | ||||
|         id, | ||||
|         snoozedUntil, | ||||
|       }); | ||||
|  | ||||
|       const { | ||||
|         data: { snoozed_until = null }, | ||||
|       } = response; | ||||
| @@ -140,6 +141,10 @@ export const actions = { | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   updateNotification: async ({ commit }, data) => { | ||||
|     commit(types.UPDATE_NOTIFICATION, data); | ||||
|   }, | ||||
|  | ||||
|   addNotification({ commit }, data) { | ||||
|     commit(types.ADD_NOTIFICATION, data); | ||||
|   }, | ||||
|   | ||||
| @@ -34,7 +34,7 @@ export const mutations = { | ||||
|       }); | ||||
|     }); | ||||
|   }, | ||||
|   [types.UPDATE_NOTIFICATION]: ($state, { id, read_at }) => { | ||||
|   [types.READ_NOTIFICATION]: ($state, { id, read_at }) => { | ||||
|     Vue.set($state.records[id], 'read_at', read_at); | ||||
|   }, | ||||
|   [types.UPDATE_ALL_NOTIFICATIONS]: $state => { | ||||
| @@ -52,6 +52,15 @@ export const mutations = { | ||||
|     Vue.set($state.meta, 'unreadCount', unreadCount); | ||||
|     Vue.set($state.meta, 'count', count); | ||||
|   }, | ||||
|   [types.UPDATE_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); | ||||
|   }, | ||||
|   [types.DELETE_NOTIFICATION]($state, data) { | ||||
|     const { notification, unread_count: unreadCount, count } = data; | ||||
|     Vue.delete($state.records, notification.id); | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| import axios from 'axios'; | ||||
| import { actions } from '../../notifications/actions'; | ||||
| import types from '../../../mutation-types'; | ||||
|  | ||||
| const commit = jest.fn(); | ||||
| global.axios = axios; | ||||
| jest.mock('axios'); | ||||
| @@ -101,7 +100,7 @@ describe('#actions', () => { | ||||
|       expect(commit.mock.calls).toEqual([ | ||||
|         [types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: true }], | ||||
|         [types.SET_NOTIFICATIONS_UNREAD_COUNT, 1], | ||||
|         [types.UPDATE_NOTIFICATION, { id: 1, read_at: expect.any(Date) }], | ||||
|         [types.READ_NOTIFICATION, { id: 1, read_at: expect.any(Date) }], | ||||
|         [types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false }], | ||||
|       ]); | ||||
|     }); | ||||
| @@ -125,7 +124,7 @@ describe('#actions', () => { | ||||
|       await actions.unread({ commit }, { id: 1 }); | ||||
|       expect(commit.mock.calls).toEqual([ | ||||
|         ['SET_NOTIFICATIONS_UI_FLAG', { isUpdating: true }], | ||||
|         ['UPDATE_NOTIFICATION', { id: 1, read_at: null }], | ||||
|         ['READ_NOTIFICATION', { id: 1, read_at: null }], | ||||
|         ['SET_NOTIFICATIONS_UI_FLAG', { isUpdating: false }], | ||||
|       ]); | ||||
|     }); | ||||
| @@ -264,17 +263,20 @@ describe('#actions', () => { | ||||
|  | ||||
|   describe('snooze', () => { | ||||
|     it('sends correct actions if API is success', async () => { | ||||
|       axios.post.mockResolvedValue({}); | ||||
|       axios.post.mockResolvedValue({ | ||||
|         data: { snoozed_until: '20 Jan, 5.04pm' }, | ||||
|       }); | ||||
|       await actions.snooze({ commit }, { id: 1, snoozedUntil: 1703057715 }); | ||||
|       expect(commit.mock.calls).toEqual([ | ||||
|         [types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: true }], | ||||
|         [types.SNOOZE_NOTIFICATION, { id: 1, snoozed_until: 1703057715 }], | ||||
|         [types.SNOOZE_NOTIFICATION, { id: 1, snoozed_until: '20 Jan, 5.04pm' }], | ||||
|         [types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false }], | ||||
|       ]); | ||||
|     }); | ||||
|     it('sends correct actions if API is error', async () => { | ||||
|       axios.post.mockRejectedValue({ message: 'Incorrect header' }); | ||||
|       await actions.snooze({ commit }, { id: 1, snoozedUntil: 1703057715 }); | ||||
|  | ||||
|       expect(commit.mock.calls).toEqual([ | ||||
|         [types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: true }], | ||||
|         [types.SET_NOTIFICATIONS_UI_FLAG, { isUpdating: false }], | ||||
|   | ||||
| @@ -75,7 +75,7 @@ describe('#mutations', () => { | ||||
|           1: { id: 1, primary_actor_id: 1 }, | ||||
|         }, | ||||
|       }; | ||||
|       mutations[types.UPDATE_NOTIFICATION](state, { | ||||
|       mutations[types.READ_NOTIFICATION](state, { | ||||
|         id: 1, | ||||
|         read_at: true, | ||||
|       }); | ||||
|   | ||||
| @@ -132,6 +132,7 @@ export default { | ||||
|   SET_NOTIFICATIONS_UNREAD_COUNT: 'SET_NOTIFICATIONS_UNREAD_COUNT', | ||||
|   SET_NOTIFICATIONS_UI_FLAG: 'SET_NOTIFICATIONS_UI_FLAG', | ||||
|   UPDATE_NOTIFICATION: 'UPDATE_NOTIFICATION', | ||||
|   READ_NOTIFICATION: 'READ_NOTIFICATION', | ||||
|   ADD_NOTIFICATION: 'ADD_NOTIFICATION', | ||||
|   DELETE_NOTIFICATION: 'DELETE_NOTIFICATION', | ||||
|   UPDATE_ALL_NOTIFICATIONS: 'UPDATE_ALL_NOTIFICATIONS', | ||||
|   | ||||
| @@ -7,6 +7,12 @@ class ActionCableListener < BaseListener | ||||
|     broadcast(account, tokens, NOTIFICATION_CREATED, { notification: notification.push_event_data, unread_count: unread_count, count: count }) | ||||
|   end | ||||
|  | ||||
|   def notification_updated(event) | ||||
|     notification, account, unread_count, count = extract_notification_and_account(event) | ||||
|     tokens = [event.data[:notification].user.pubsub_token] | ||||
|     broadcast(account, tokens, NOTIFICATION_UPDATED, { notification: notification.push_event_data, unread_count: unread_count, count: count }) | ||||
|   end | ||||
|  | ||||
|   def notification_deleted(event) | ||||
|     return if event.data[:notification].user.blank? | ||||
|  | ||||
|   | ||||
| @@ -46,6 +46,7 @@ class Notification < ApplicationRecord | ||||
|   before_create :set_last_activity_at | ||||
|   after_create_commit :process_notification_delivery, :dispatch_create_event | ||||
|   after_destroy_commit :dispatch_destroy_event | ||||
|   after_update_commit :dispatch_update_event | ||||
|  | ||||
|   PRIMARY_ACTORS = ['Conversation'].freeze | ||||
|  | ||||
| @@ -75,7 +76,8 @@ class Notification < ApplicationRecord | ||||
|   def primary_actor_data | ||||
|     { | ||||
|       id: primary_actor.push_event_data[:id], | ||||
|       meta: primary_actor.push_event_data[:meta] | ||||
|       meta: primary_actor.push_event_data[:meta], | ||||
|       inbox_id: primary_actor.push_event_data[:inbox_id] | ||||
|     } | ||||
|   end | ||||
|  | ||||
| @@ -142,6 +144,10 @@ class Notification < ApplicationRecord | ||||
|     Rails.configuration.dispatcher.dispatch(NOTIFICATION_CREATED, Time.zone.now, notification: self) | ||||
|   end | ||||
|  | ||||
|   def dispatch_update_event | ||||
|     Rails.configuration.dispatcher.dispatch(NOTIFICATION_UPDATED, Time.zone.now, notification: self) | ||||
|   end | ||||
|  | ||||
|   def dispatch_destroy_event | ||||
|     Rails.configuration.dispatcher.dispatch(NOTIFICATION_DELETED, Time.zone.now, notification: self) | ||||
|   end | ||||
|   | ||||
| @@ -49,6 +49,7 @@ module Events::Types | ||||
|   # notification events | ||||
|   NOTIFICATION_CREATED = 'notification.created' | ||||
|   NOTIFICATION_DELETED = 'notification.deleted' | ||||
|   NOTIFICATION_UPDATED = 'notification.updated' | ||||
|  | ||||
|   # agent events | ||||
|   AGENT_ADDED = 'agent.added' | ||||
|   | ||||
| @@ -152,6 +152,27 @@ describe ActionCableListener do | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   describe '#notification_updated' do | ||||
|     let(:event_name) { :'notification.updated' } | ||||
|     let!(:notification) { create(:notification, account: account, user: agent) } | ||||
|     let!(:event) { Events::Base.new(event_name, Time.zone.now, notification: notification) } | ||||
|  | ||||
|     it 'sends notification to account admins, inbox agents' do | ||||
|       expect(ActionCableBroadcastJob).to receive(:perform_later).with( | ||||
|         [agent.pubsub_token], | ||||
|         'notification.updated', | ||||
|         { | ||||
|           account_id: notification.account_id, | ||||
|           notification: notification.push_event_data, | ||||
|           unread_count: 1, | ||||
|           count: 1 | ||||
|         } | ||||
|       ) | ||||
|  | ||||
|       listener.notification_updated(event) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   describe '#conversation_updated' do | ||||
|     let(:event_name) { :'conversation.updated' } | ||||
|     let!(:event) { Events::Base.new(event_name, Time.zone.now, conversation: conversation, user: agent, is_private: false) } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Muhsin Keloth
					Muhsin Keloth