mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 02:57:57 +00:00 
			
		
		
		
	chore: Replace eventBus with mitt.js [CW-3275] (#9539)
# Replace the deprecated `eventBus` with mitt.js ## Description Since eventBus and it's respective methods are deprecated and removed from all future releases of vue, this was blocking us from migrating. This PR replaces eventBus with [mitt](https://github.com/developit/mitt). I have created a wrapper mitt.js to simulate the same old event names so it's backwards compatible, without making a lot of changes. Fixes # (issue) ## Type of change Please delete options that are not relevant. - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality not to work as expected) - [ ] This change requires a documentation update ## How Has This Been Tested? 1. Made sure all the places we're listening to bus events are working as expected. 2. Respective specsf or the events from mitt. ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] I have commented on my code, particularly in hard-to-understand areas - [x] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [x] Any dependent changes have been merged and published in downstream modules
This commit is contained in:
		| @@ -514,14 +514,14 @@ export default { | ||||
|       this.$store.dispatch('campaigns/get'); | ||||
|     } | ||||
|  | ||||
|     bus.$on('fetch_conversation_stats', () => { | ||||
|     this.$emitter.on('fetch_conversation_stats', () => { | ||||
|       this.$store.dispatch('conversationStats/get', this.conversationFilters); | ||||
|     }); | ||||
|  | ||||
|     bus.$on(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation); | ||||
|     this.$emitter.on(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation); | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     bus.$off(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation); | ||||
|     this.$emitter.off(CMD_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation); | ||||
|   }, | ||||
|   methods: { | ||||
|     updateVirtualListProps(key, value) { | ||||
| @@ -742,7 +742,7 @@ export default { | ||||
|     updateAssigneeTab(selectedTab) { | ||||
|       if (this.activeAssigneeTab !== selectedTab) { | ||||
|         this.resetBulkActions(); | ||||
|         bus.$emit('clearSearchInput'); | ||||
|         this.$emitter.emit('clearSearchInput'); | ||||
|         this.activeAssigneeTab = selectedTab; | ||||
|         if (!this.currentPage) { | ||||
|           this.fetchConversations(); | ||||
|   | ||||
| @@ -25,8 +25,10 @@ | ||||
| <script> | ||||
| import 'highlight.js/styles/default.css'; | ||||
| import { copyTextToClipboard } from 'shared/helpers/clipboard'; | ||||
| import alertMixin from 'shared/mixins/alertMixin'; | ||||
|  | ||||
| export default { | ||||
|   mixins: [alertMixin], | ||||
|   props: { | ||||
|     script: { | ||||
|       type: String, | ||||
| @@ -59,7 +61,7 @@ export default { | ||||
|     async onCopy(e) { | ||||
|       e.preventDefault(); | ||||
|       await copyTextToClipboard(this.script); | ||||
|       bus.$emit('newToastMessage', this.$t('COMPONENTS.CODE.COPY_SUCCESSFUL')); | ||||
|       this.showAlert(this.$t('COMPONENTS.CODE.COPY_SUCCESSFUL')); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
|   | ||||
| @@ -270,10 +270,10 @@ export default { | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.editedValue = this.formattedValue; | ||||
|     bus.$on(BUS_EVENTS.FOCUS_CUSTOM_ATTRIBUTE, this.onFocusAttribute); | ||||
|     this.$emitter.on(BUS_EVENTS.FOCUS_CUSTOM_ATTRIBUTE, this.onFocusAttribute); | ||||
|   }, | ||||
|   destroyed() { | ||||
|     bus.$off(BUS_EVENTS.FOCUS_CUSTOM_ATTRIBUTE, this.onFocusAttribute); | ||||
|     this.$emitter.off(BUS_EVENTS.FOCUS_CUSTOM_ATTRIBUTE, this.onFocusAttribute); | ||||
|   }, | ||||
|   methods: { | ||||
|     onFocusAttribute(focusAttributeKey) { | ||||
|   | ||||
| @@ -18,8 +18,10 @@ | ||||
| <script> | ||||
| import 'highlight.js/styles/default.css'; | ||||
| import { copyTextToClipboard } from 'shared/helpers/clipboard'; | ||||
| import alertMixin from 'shared/mixins/alertMixin'; | ||||
|  | ||||
| export default { | ||||
|   mixins: [alertMixin], | ||||
|   props: { | ||||
|     value: { | ||||
|       type: String, | ||||
| @@ -35,7 +37,7 @@ export default { | ||||
|     async onCopy(e) { | ||||
|       e.preventDefault(); | ||||
|       await copyTextToClipboard(this.value); | ||||
|       bus.$emit('newToastMessage', this.$t('COMPONENTS.CODE.COPY_SUCCESSFUL')); | ||||
|       this.showAlert(this.$t('COMPONENTS.CODE.COPY_SUCCESSFUL')); | ||||
|     }, | ||||
|     toggleMasked() { | ||||
|       this.masked = !this.masked; | ||||
|   | ||||
| @@ -55,7 +55,7 @@ export default { | ||||
|  | ||||
|   mounted() { | ||||
|     window.addEventListener('offline', this.updateOnlineStatus); | ||||
|     window.bus.$on(BUS_EVENTS.WEBSOCKET_DISCONNECT, () => { | ||||
|     this.$emitter.on(BUS_EVENTS.WEBSOCKET_DISCONNECT, () => { | ||||
|       // TODO: Remove this after completing the conversation list refetching | ||||
|       // TODO: DIRTY FIX : CLEAN UP THIS WITH PROPER FIX, DELAYING THE RECONNECT FOR NOW | ||||
|       // THE CABLE IS FIRING IS VERY COMMON AND THUS INTERFERING USER EXPERIENCE | ||||
|   | ||||
| @@ -21,7 +21,7 @@ export default { | ||||
|   }, | ||||
|   methods: { | ||||
|     onMenuItemClick() { | ||||
|       bus.$emit(BUS_EVENTS.TOGGLE_SIDEMENU); | ||||
|       this.$emitter.emit(BUS_EVENTS.TOGGLE_SIDEMENU); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
|   | ||||
| @@ -15,11 +15,13 @@ | ||||
|  | ||||
| <script> | ||||
| import WootSnackbar from './Snackbar.vue'; | ||||
| import alertMixin from 'shared/mixins/alertMixin'; | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     WootSnackbar, | ||||
|   }, | ||||
|   mixins: [alertMixin], | ||||
|   props: { | ||||
|     duration: { | ||||
|       type: Number, | ||||
| @@ -34,10 +36,10 @@ export default { | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     bus.$on('newToastMessage', this.onNewToastMessage); | ||||
|     this.$emitter.on('newToastMessage', this.onNewToastMessage); | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     bus.$off('newToastMessage', this.onNewToastMessage); | ||||
|     this.$emitter.off('newToastMessage', this.onNewToastMessage); | ||||
|   }, | ||||
|   methods: { | ||||
|     onNewToastMessage(message, action) { | ||||
|   | ||||
| @@ -128,12 +128,12 @@ export default { | ||||
|     }, | ||||
|   }, | ||||
|   mounted() { | ||||
|     bus.$on(CMD_REOPEN_CONVERSATION, this.onCmdOpenConversation); | ||||
|     bus.$on(CMD_RESOLVE_CONVERSATION, this.onCmdResolveConversation); | ||||
|     this.$emitter.on(CMD_REOPEN_CONVERSATION, this.onCmdOpenConversation); | ||||
|     this.$emitter.on(CMD_RESOLVE_CONVERSATION, this.onCmdResolveConversation); | ||||
|   }, | ||||
|   destroyed() { | ||||
|     bus.$off(CMD_REOPEN_CONVERSATION, this.onCmdOpenConversation); | ||||
|     bus.$off(CMD_RESOLVE_CONVERSATION, this.onCmdResolveConversation); | ||||
|     this.$emitter.off(CMD_REOPEN_CONVERSATION, this.onCmdOpenConversation); | ||||
|     this.$emitter.off(CMD_RESOLVE_CONVERSATION, this.onCmdResolveConversation); | ||||
|   }, | ||||
|   methods: { | ||||
|     getKeyboardEvents() { | ||||
|   | ||||
| @@ -22,7 +22,7 @@ import { | ||||
|   setYear, | ||||
|   isAfter, | ||||
| } from 'date-fns'; | ||||
|  | ||||
| import { useAlert } from 'dashboard/composables'; | ||||
| import DatePickerButton from './components/DatePickerButton.vue'; | ||||
| import CalendarDateInput from './components/CalendarDateInput.vue'; | ||||
| import CalendarDateRange from './components/CalendarDateRange.vue'; | ||||
| @@ -185,7 +185,7 @@ const updateManualInput = (newDate, calendarType) => { | ||||
| }; | ||||
|  | ||||
| const handleManualInputError = message => { | ||||
|   bus.$emit('newToastMessage', message); | ||||
|   useAlert(message); | ||||
| }; | ||||
|  | ||||
| const resetDatePicker = () => { | ||||
| @@ -201,7 +201,7 @@ const resetDatePicker = () => { | ||||
|  | ||||
| const emitDateRange = () => { | ||||
|   if (!isValid(selectedStartDate.value) || !isValid(selectedEndDate.value)) { | ||||
|     bus.$emit('newToastMessage', 'Please select a valid time range'); | ||||
|     useAlert('Please select a valid time range'); | ||||
|   } else { | ||||
|     showDatePicker.value = false; | ||||
|     emit('dateRangeChanged', [selectedStartDate.value, selectedEndDate.value]); | ||||
|   | ||||
| @@ -81,7 +81,7 @@ export default { | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     bus.$on(CMD_AI_ASSIST, this.onAIAssist); | ||||
|     this.$emitter.on(CMD_AI_ASSIST, this.onAIAssist); | ||||
|     this.initialMessage = this.draftMessage; | ||||
|   }, | ||||
|  | ||||
|   | ||||
| @@ -352,10 +352,16 @@ export default { | ||||
|     // Components using this | ||||
|     // 1. SearchPopover.vue | ||||
|  | ||||
|     bus.$on(BUS_EVENTS.INSERT_INTO_RICH_EDITOR, this.insertContentIntoEditor); | ||||
|     this.$emitter.on( | ||||
|       BUS_EVENTS.INSERT_INTO_RICH_EDITOR, | ||||
|       this.insertContentIntoEditor | ||||
|     ); | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     bus.$off(BUS_EVENTS.INSERT_INTO_RICH_EDITOR, this.insertContentIntoEditor); | ||||
|     this.$emitter.off( | ||||
|       BUS_EVENTS.INSERT_INTO_RICH_EDITOR, | ||||
|       this.insertContentIntoEditor | ||||
|     ); | ||||
|   }, | ||||
|   methods: { | ||||
|     reloadState(content = this.value) { | ||||
|   | ||||
| @@ -473,11 +473,11 @@ export default { | ||||
|   }, | ||||
|   mounted() { | ||||
|     this.hasMediaLoadError = false; | ||||
|     bus.$on(BUS_EVENTS.ON_MESSAGE_LIST_SCROLL, this.closeContextMenu); | ||||
|     this.$emitter.on(BUS_EVENTS.ON_MESSAGE_LIST_SCROLL, this.closeContextMenu); | ||||
|     this.setupHighlightTimer(); | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     bus.$off(BUS_EVENTS.ON_MESSAGE_LIST_SCROLL, this.closeContextMenu); | ||||
|     this.$emitter.off(BUS_EVENTS.ON_MESSAGE_LIST_SCROLL, this.closeContextMenu); | ||||
|     clearTimeout(this.higlightTimeout); | ||||
|   }, | ||||
|   methods: { | ||||
| @@ -531,7 +531,7 @@ export default { | ||||
|       const { conversation_id: conversationId, id: replyTo } = this.data; | ||||
|  | ||||
|       LocalStorage.updateJsonStore(replyStorageKey, conversationId, replyTo); | ||||
|       bus.$emit(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.data); | ||||
|       this.$emitter.emit(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.data); | ||||
|     }, | ||||
|     setupHighlightTimer() { | ||||
|       if (Number(this.$route.query.messageId) !== Number(this.data.id)) { | ||||
|   | ||||
| @@ -324,12 +324,12 @@ export default { | ||||
|   }, | ||||
|  | ||||
|   created() { | ||||
|     bus.$on(BUS_EVENTS.SCROLL_TO_MESSAGE, this.onScrollToMessage); | ||||
|     this.$emitter.on(BUS_EVENTS.SCROLL_TO_MESSAGE, this.onScrollToMessage); | ||||
|     // when a new message comes in, we refetch the label suggestions | ||||
|     bus.$on(BUS_EVENTS.FETCH_LABEL_SUGGESTIONS, this.fetchSuggestions); | ||||
|     this.$emitter.on(BUS_EVENTS.FETCH_LABEL_SUGGESTIONS, this.fetchSuggestions); | ||||
|     // when a message is sent we set the flag to true this hides the label suggestions, | ||||
|     // until the chat is changed and the flag is reset in the watch for currentChat | ||||
|     bus.$on(BUS_EVENTS.MESSAGE_SENT, () => { | ||||
|     this.$emitter.on(BUS_EVENTS.MESSAGE_SENT, () => { | ||||
|       this.messageSentSinceOpened = true; | ||||
|     }); | ||||
|   }, | ||||
| @@ -396,7 +396,7 @@ export default { | ||||
|       this.$store.dispatch('fetchAllAttachments', this.currentChat.id); | ||||
|     }, | ||||
|     removeBusListeners() { | ||||
|       bus.$off(BUS_EVENTS.SCROLL_TO_MESSAGE, this.onScrollToMessage); | ||||
|       this.$emitter.off(BUS_EVENTS.SCROLL_TO_MESSAGE, this.onScrollToMessage); | ||||
|     }, | ||||
|     onScrollToMessage({ messageId = '' } = {}) { | ||||
|       this.$nextTick(() => { | ||||
| @@ -514,7 +514,7 @@ export default { | ||||
|       } else { | ||||
|         this.hasUserScrolled = true; | ||||
|       } | ||||
|       bus.$emit(BUS_EVENTS.ON_MESSAGE_LIST_SCROLL); | ||||
|       this.$emitter.emit(BUS_EVENTS.ON_MESSAGE_LIST_SCROLL); | ||||
|       this.fetchPreviousMessages(e.target.scrollTop); | ||||
|     }, | ||||
|  | ||||
|   | ||||
| @@ -61,14 +61,14 @@ export default { | ||||
|     ...mapGetters({ currentChat: 'getSelectedChat' }), | ||||
|   }, | ||||
|   mounted() { | ||||
|     bus.$on(CMD_MUTE_CONVERSATION, this.mute); | ||||
|     bus.$on(CMD_UNMUTE_CONVERSATION, this.unmute); | ||||
|     bus.$on(CMD_SEND_TRANSCRIPT, this.toggleEmailActionsModal); | ||||
|     this.$emitter.on(CMD_MUTE_CONVERSATION, this.mute); | ||||
|     this.$emitter.on(CMD_UNMUTE_CONVERSATION, this.unmute); | ||||
|     this.$emitter.on(CMD_SEND_TRANSCRIPT, this.toggleEmailActionsModal); | ||||
|   }, | ||||
|   destroyed() { | ||||
|     bus.$off(CMD_MUTE_CONVERSATION, this.mute); | ||||
|     bus.$off(CMD_UNMUTE_CONVERSATION, this.unmute); | ||||
|     bus.$off(CMD_SEND_TRANSCRIPT, this.toggleEmailActionsModal); | ||||
|     this.$emitter.off(CMD_MUTE_CONVERSATION, this.mute); | ||||
|     this.$emitter.off(CMD_UNMUTE_CONVERSATION, this.unmute); | ||||
|     this.$emitter.off(CMD_SEND_TRANSCRIPT, this.toggleEmailActionsModal); | ||||
|   }, | ||||
|   methods: { | ||||
|     mute() { | ||||
|   | ||||
| @@ -596,12 +596,15 @@ export default { | ||||
|     ); | ||||
|  | ||||
|     this.fetchAndSetReplyTo(); | ||||
|     bus.$on(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.fetchAndSetReplyTo); | ||||
|     this.$emitter.on( | ||||
|       BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, | ||||
|       this.fetchAndSetReplyTo | ||||
|     ); | ||||
|  | ||||
|     // A hacky fix to solve the drag and drop | ||||
|     // Is showing on top of new conversation modal drag and drop | ||||
|     // TODO need to find a better solution | ||||
|     bus.$on( | ||||
|     this.$emitter.on( | ||||
|       BUS_EVENTS.NEW_CONVERSATION_MODAL, | ||||
|       this.onNewConversationModalActive | ||||
|     ); | ||||
| @@ -609,10 +612,13 @@ export default { | ||||
|   destroyed() { | ||||
|     document.removeEventListener('paste', this.onPaste); | ||||
|     document.removeEventListener('keydown', this.handleKeyEvents); | ||||
|     bus.$off(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.fetchAndSetReplyTo); | ||||
|     this.$emitter.off( | ||||
|       BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, | ||||
|       this.fetchAndSetReplyTo | ||||
|     ); | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     bus.$off( | ||||
|     this.$emitter.off( | ||||
|       BUS_EVENTS.NEW_CONVERSATION_MODAL, | ||||
|       this.onNewConversationModalActive | ||||
|     ); | ||||
| @@ -625,7 +631,7 @@ export default { | ||||
|         const lines = title.split('\n'); | ||||
|         const nonEmptyLines = lines.filter(line => line.trim() !== ''); | ||||
|         const filteredMarkdown = nonEmptyLines.join(' '); | ||||
|         bus.$emit( | ||||
|         this.$emitter.emit( | ||||
|           BUS_EVENTS.INSERT_INTO_RICH_EDITOR, | ||||
|           `[${filteredMarkdown}](${url})` | ||||
|         ); | ||||
| @@ -867,8 +873,8 @@ export default { | ||||
|           'createPendingMessageAndSend', | ||||
|           messagePayload | ||||
|         ); | ||||
|         bus.$emit(BUS_EVENTS.SCROLL_TO_MESSAGE); | ||||
|         bus.$emit(BUS_EVENTS.MESSAGE_SENT); | ||||
|         this.$emitter.emit(BUS_EVENTS.SCROLL_TO_MESSAGE); | ||||
|         this.$emitter.emit(BUS_EVENTS.MESSAGE_SENT); | ||||
|         this.removeFromDraft(); | ||||
|         this.sendMessageAnalyticsData(messagePayload.private); | ||||
|       } catch (error) { | ||||
| @@ -1194,7 +1200,7 @@ export default { | ||||
|     resetReplyToMessage() { | ||||
|       const replyStorageKey = LOCAL_STORAGE_KEYS.MESSAGE_REPLY_TO; | ||||
|       LocalStorage.deleteFromJsonStore(replyStorageKey, this.conversationId); | ||||
|       bus.$emit(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE); | ||||
|       this.$emitter.emit(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE); | ||||
|     }, | ||||
|     onNewConversationModalActive(isActive) { | ||||
|       // Issue is if the new conversation modal is open and we drag and drop the file | ||||
|   | ||||
| @@ -47,7 +47,9 @@ export default { | ||||
|   }, | ||||
|   methods: { | ||||
|     scrollToMessage() { | ||||
|       bus.$emit(BUS_EVENTS.SCROLL_TO_MESSAGE, { messageId: this.message.id }); | ||||
|       this.$emitter.emit(BUS_EVENTS.SCROLL_TO_MESSAGE, { | ||||
|         messageId: this.message.id, | ||||
|       }); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
|   | ||||
| @@ -167,17 +167,29 @@ export default { | ||||
|     }; | ||||
|   }, | ||||
|   mounted() { | ||||
|     bus.$on(CMD_BULK_ACTION_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation); | ||||
|     bus.$on(CMD_BULK_ACTION_REOPEN_CONVERSATION, this.onCmdReopenConversation); | ||||
|     bus.$on( | ||||
|     this.$emitter.on( | ||||
|       CMD_BULK_ACTION_SNOOZE_CONVERSATION, | ||||
|       this.onCmdSnoozeConversation | ||||
|     ); | ||||
|     this.$emitter.on( | ||||
|       CMD_BULK_ACTION_REOPEN_CONVERSATION, | ||||
|       this.onCmdReopenConversation | ||||
|     ); | ||||
|     this.$emitter.on( | ||||
|       CMD_BULK_ACTION_RESOLVE_CONVERSATION, | ||||
|       this.onCmdResolveConversation | ||||
|     ); | ||||
|   }, | ||||
|   destroyed() { | ||||
|     bus.$off(CMD_BULK_ACTION_SNOOZE_CONVERSATION, this.onCmdSnoozeConversation); | ||||
|     bus.$off(CMD_BULK_ACTION_REOPEN_CONVERSATION, this.onCmdReopenConversation); | ||||
|     bus.$off( | ||||
|     this.$emitter.off( | ||||
|       CMD_BULK_ACTION_SNOOZE_CONVERSATION, | ||||
|       this.onCmdSnoozeConversation | ||||
|     ); | ||||
|     this.$emitter.off( | ||||
|       CMD_BULK_ACTION_REOPEN_CONVERSATION, | ||||
|       this.onCmdReopenConversation | ||||
|     ); | ||||
|     this.$emitter.off( | ||||
|       CMD_BULK_ACTION_RESOLVE_CONVERSATION, | ||||
|       this.onCmdResolveConversation | ||||
|     ); | ||||
|   | ||||
| @@ -2,12 +2,21 @@ import { createLocalVue, mount } from '@vue/test-utils'; | ||||
| import Vuex from 'vuex'; | ||||
| import VueI18n from 'vue-i18n'; | ||||
| import VTooltip from 'v-tooltip'; | ||||
|  | ||||
| import Button from 'dashboard/components/buttons/Button'; | ||||
| import i18n from 'dashboard/i18n'; | ||||
| import FluentIcon from 'shared/components/FluentIcon/DashboardIcon'; | ||||
| import MoreActions from '../MoreActions'; | ||||
|  | ||||
| jest.mock('shared/helpers/mitt', () => ({ | ||||
|   emitter: { | ||||
|     emit: jest.fn(), | ||||
|     on: jest.fn(), | ||||
|     off: jest.fn(), | ||||
|   }, | ||||
| })); | ||||
|  | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| const localVue = createLocalVue(); | ||||
| localVue.use(Vuex); | ||||
| localVue.use(VueI18n); | ||||
| @@ -16,6 +25,12 @@ localVue.use(VTooltip); | ||||
| localVue.component('fluent-icon', FluentIcon); | ||||
| localVue.component('woot-button', Button); | ||||
|  | ||||
| localVue.prototype.$emitter = { | ||||
|   emit: jest.fn(), | ||||
|   on: jest.fn(), | ||||
|   off: jest.fn(), | ||||
| }; | ||||
|  | ||||
| const i18nConfig = new VueI18n({ locale: 'en', messages: i18n }); | ||||
|  | ||||
| describe('MoveActions', () => { | ||||
| @@ -29,12 +44,6 @@ describe('MoveActions', () => { | ||||
|   let moreActions = null; | ||||
|  | ||||
|   beforeEach(() => { | ||||
|     window.bus = { | ||||
|       $emit: jest.fn(), | ||||
|       $on: jest.fn(), | ||||
|       $off: jest.fn(), | ||||
|     }; | ||||
|  | ||||
|     state = { | ||||
|       authenticated: true, | ||||
|       currentChat, | ||||
| @@ -76,7 +85,7 @@ describe('MoveActions', () => { | ||||
|     it('shows alert', async () => { | ||||
|       await moreActions.find('button:first-child').trigger('click'); | ||||
|  | ||||
|       expect(window.bus.$emit).toBeCalledWith( | ||||
|       expect(emitter.emit).toBeCalledWith( | ||||
|         'newToastMessage', | ||||
|         'This contact is blocked successfully. You will not be notified of any future conversations.', | ||||
|         undefined | ||||
| @@ -102,7 +111,7 @@ describe('MoveActions', () => { | ||||
|     it('shows alert', async () => { | ||||
|       await moreActions.find('button:first-child').trigger('click'); | ||||
|  | ||||
|       expect(window.bus.$emit).toBeCalledWith( | ||||
|       expect(emitter.emit).toBeCalledWith( | ||||
|         'newToastMessage', | ||||
|         'This contact is unblocked successfully.', | ||||
|         undefined | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import { getCurrentInstance } from 'vue'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| export const useTrack = () => { | ||||
|   const vm = getCurrentInstance(); | ||||
| @@ -8,5 +9,5 @@ export const useTrack = () => { | ||||
| }; | ||||
|  | ||||
| export function useAlert(message, action) { | ||||
|   bus.$emit('newToastMessage', message, action); | ||||
|   emitter.emit('newToastMessage', message, action); | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| import AuthAPI from '../api/auth'; | ||||
| import BaseActionCableConnector from '../../shared/helpers/BaseActionCableConnector'; | ||||
| import DashboardAudioNotificationHelper from './AudioAlerts/DashboardAudioNotificationHelper'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| class ActionCableConnector extends BaseActionCableConnector { | ||||
|   constructor(app, pubsubToken) { | ||||
| @@ -177,8 +178,8 @@ class ActionCableConnector extends BaseActionCableConnector { | ||||
|  | ||||
|   // eslint-disable-next-line class-methods-use-this | ||||
|   fetchConversationStats = () => { | ||||
|     bus.$emit('fetch_conversation_stats'); | ||||
|     bus.$emit('fetch_overview_reports'); | ||||
|     emitter.emit('fetch_conversation_stats'); | ||||
|     emitter.emit('fetch_overview_reports'); | ||||
|   }; | ||||
|  | ||||
|   onContactDelete = data => { | ||||
| @@ -207,7 +208,7 @@ class ActionCableConnector extends BaseActionCableConnector { | ||||
|  | ||||
|   // eslint-disable-next-line class-methods-use-this | ||||
|   onFirstReplyCreated = () => { | ||||
|     bus.$emit('fetch_overview_reports'); | ||||
|     emitter.emit('fetch_overview_reports'); | ||||
|   }; | ||||
|  | ||||
|   onCacheInvalidate = data => { | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| /* eslint-disable no-console */ | ||||
| import NotificationSubscriptions from '../api/notificationSubscription'; | ||||
| import auth from '../api/auth'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| export const verifyServiceWorkerExistence = (callback = () => {}) => { | ||||
|   if (!('serviceWorker' in navigator)) { | ||||
| @@ -68,7 +69,7 @@ export const registerSubscription = (onSuccess = () => {}) => { | ||||
|       onSuccess(); | ||||
|     }) | ||||
|     .catch(() => { | ||||
|       window.bus.$emit( | ||||
|       emitter.emit( | ||||
|         'newToastMessage', | ||||
|         'This browser does not support desktop notification' | ||||
|       ); | ||||
| @@ -77,7 +78,7 @@ export const registerSubscription = (onSuccess = () => {}) => { | ||||
|  | ||||
| export const requestPushPermissions = ({ onSuccess }) => { | ||||
|   if (!('Notification' in window)) { | ||||
|     window.bus.$emit( | ||||
|     emitter.emit( | ||||
|       'newToastMessage', | ||||
|       'This browser does not support desktop notification' | ||||
|     ); | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import AnalyticsHelper from './AnalyticsHelper'; | ||||
| import DashboardAudioNotificationHelper from './AudioAlerts/DashboardAudioNotificationHelper'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| export const CHATWOOT_SET_USER = 'CHATWOOT_SET_USER'; | ||||
| export const CHATWOOT_RESET = 'CHATWOOT_RESET'; | ||||
| @@ -8,7 +9,7 @@ export const ANALYTICS_IDENTITY = 'ANALYTICS_IDENTITY'; | ||||
| export const ANALYTICS_RESET = 'ANALYTICS_RESET'; | ||||
|  | ||||
| export const initializeAnalyticsEvents = () => { | ||||
|   window.bus.$on(ANALYTICS_IDENTITY, ({ user }) => { | ||||
|   emitter.on(ANALYTICS_IDENTITY, ({ user }) => { | ||||
|     AnalyticsHelper.identify(user); | ||||
|   }); | ||||
| }; | ||||
| @@ -34,12 +35,12 @@ const initializeAudioAlerts = user => { | ||||
| }; | ||||
|  | ||||
| export const initializeChatwootEvents = () => { | ||||
|   window.bus.$on(CHATWOOT_RESET, () => { | ||||
|   emitter.on(CHATWOOT_RESET, () => { | ||||
|     if (window.$chatwoot) { | ||||
|       window.$chatwoot.reset(); | ||||
|     } | ||||
|   }); | ||||
|   window.bus.$on(CHATWOOT_SET_USER, ({ user }) => { | ||||
|   emitter.on(CHATWOOT_SET_USER, ({ user }) => { | ||||
|     if (window.$chatwoot) { | ||||
|       window.$chatwoot.setUser(user.email, { | ||||
|         avatar_url: user.avatar_url, | ||||
|   | ||||
| @@ -110,11 +110,11 @@ export default { | ||||
|   mounted() { | ||||
|     this.handleResize(); | ||||
|     window.addEventListener('resize', this.handleResize); | ||||
|     bus.$on(BUS_EVENTS.TOGGLE_SIDEMENU, this.toggleSidebar); | ||||
|     this.$emitter.on(BUS_EVENTS.TOGGLE_SIDEMENU, this.toggleSidebar); | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     window.removeEventListener('resize', this.handleResize); | ||||
|     bus.$off(BUS_EVENTS.TOGGLE_SIDEMENU, this.toggleSidebar); | ||||
|     this.$emitter.off(BUS_EVENTS.TOGGLE_SIDEMENU, this.toggleSidebar); | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|   | ||||
| @@ -11,6 +11,7 @@ import { | ||||
|   ICON_REOPEN_CONVERSATION, | ||||
|   ICON_RESOLVE_CONVERSATION, | ||||
| } from './CommandBarIcons'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| import { createSnoozeHandlers } from './commandBarActions'; | ||||
|  | ||||
| @@ -37,7 +38,7 @@ export const RESOLVED_CONVERSATION_BULK_ACTIONS = [ | ||||
|     title: 'COMMAND_BAR.COMMANDS.REOPEN_CONVERSATION', | ||||
|     section: 'COMMAND_BAR.SECTIONS.BULK_ACTIONS', | ||||
|     icon: ICON_REOPEN_CONVERSATION, | ||||
|     handler: () => bus.$emit(CMD_BULK_ACTION_REOPEN_CONVERSATION), | ||||
|     handler: () => emitter.emit(CMD_BULK_ACTION_REOPEN_CONVERSATION), | ||||
|   }, | ||||
| ]; | ||||
|  | ||||
| @@ -47,7 +48,7 @@ export const OPEN_CONVERSATION_BULK_ACTIONS = [ | ||||
|     title: 'COMMAND_BAR.COMMANDS.RESOLVE_CONVERSATION', | ||||
|     section: 'COMMAND_BAR.SECTIONS.BULK_ACTIONS', | ||||
|     icon: ICON_RESOLVE_CONVERSATION, | ||||
|     handler: () => bus.$emit(CMD_BULK_ACTION_RESOLVE_CONVERSATION), | ||||
|     handler: () => emitter.emit(CMD_BULK_ACTION_RESOLVE_CONVERSATION), | ||||
|   }, | ||||
| ]; | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import wootConstants from 'dashboard/constants/globals'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| import { | ||||
|   CMD_MUTE_CONVERSATION, | ||||
| @@ -26,7 +27,7 @@ export const OPEN_CONVERSATION_ACTIONS = [ | ||||
|     title: 'COMMAND_BAR.COMMANDS.RESOLVE_CONVERSATION', | ||||
|     section: 'COMMAND_BAR.SECTIONS.CONVERSATION', | ||||
|     icon: ICON_RESOLVE_CONVERSATION, | ||||
|     handler: () => bus.$emit(CMD_RESOLVE_CONVERSATION), | ||||
|     handler: () => emitter.emit(CMD_RESOLVE_CONVERSATION), | ||||
|   }, | ||||
| ]; | ||||
|  | ||||
| @@ -37,7 +38,7 @@ export const createSnoozeHandlers = (busEventName, parentId, section) => { | ||||
|     parent: parentId, | ||||
|     section: section, | ||||
|     icon: ICON_SNOOZE_CONVERSATION, | ||||
|     handler: () => bus.$emit(busEventName, option), | ||||
|     handler: () => emitter.emit(busEventName, option), | ||||
|   })); | ||||
| }; | ||||
|  | ||||
| @@ -61,7 +62,7 @@ export const RESOLVED_CONVERSATION_ACTIONS = [ | ||||
|     title: 'COMMAND_BAR.COMMANDS.REOPEN_CONVERSATION', | ||||
|     section: 'COMMAND_BAR.SECTIONS.CONVERSATION', | ||||
|     icon: ICON_REOPEN_CONVERSATION, | ||||
|     handler: () => bus.$emit(CMD_REOPEN_CONVERSATION), | ||||
|     handler: () => emitter.emit(CMD_REOPEN_CONVERSATION), | ||||
|   }, | ||||
| ]; | ||||
|  | ||||
| @@ -70,7 +71,7 @@ export const SEND_TRANSCRIPT_ACTION = { | ||||
|   title: 'COMMAND_BAR.COMMANDS.SEND_TRANSCRIPT', | ||||
|   section: 'COMMAND_BAR.SECTIONS.CONVERSATION', | ||||
|   icon: ICON_SEND_TRANSCRIPT, | ||||
|   handler: () => bus.$emit(CMD_SEND_TRANSCRIPT), | ||||
|   handler: () => emitter.emit(CMD_SEND_TRANSCRIPT), | ||||
| }; | ||||
|  | ||||
| export const UNMUTE_ACTION = { | ||||
| @@ -78,7 +79,7 @@ export const UNMUTE_ACTION = { | ||||
|   title: 'COMMAND_BAR.COMMANDS.UNMUTE_CONVERSATION', | ||||
|   section: 'COMMAND_BAR.SECTIONS.CONVERSATION', | ||||
|   icon: ICON_UNMUTE_CONVERSATION, | ||||
|   handler: () => bus.$emit(CMD_UNMUTE_CONVERSATION), | ||||
|   handler: () => emitter.emit(CMD_UNMUTE_CONVERSATION), | ||||
| }; | ||||
|  | ||||
| export const MUTE_ACTION = { | ||||
| @@ -86,5 +87,5 @@ export const MUTE_ACTION = { | ||||
|   title: 'COMMAND_BAR.COMMANDS.MUTE_CONVERSATION', | ||||
|   section: 'COMMAND_BAR.SECTIONS.CONVERSATION', | ||||
|   icon: ICON_MUTE_CONVERSATION, | ||||
|   handler: () => bus.$emit(CMD_MUTE_CONVERSATION), | ||||
|   handler: () => emitter.emit(CMD_MUTE_CONVERSATION), | ||||
| }; | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { mapGetters } from 'vuex'; | ||||
| import wootConstants from 'dashboard/constants/globals'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| import { CMD_AI_ASSIST } from './commandBarBusEvents'; | ||||
| import { REPLY_EDITOR_MODES } from 'dashboard/components/widgets/WootWriter/constants'; | ||||
| @@ -318,7 +319,7 @@ export default { | ||||
|         section: this.$t('COMMAND_BAR.SECTIONS.AI_ASSIST'), | ||||
|         priority: item, | ||||
|         icon: item.icon, | ||||
|         handler: () => bus.$emit(CMD_AI_ASSIST, item.key), | ||||
|         handler: () => emitter.emit(CMD_AI_ASSIST, item.key), | ||||
|       })); | ||||
|       return [ | ||||
|         { | ||||
|   | ||||
| @@ -2,6 +2,7 @@ import wootConstants from 'dashboard/constants/globals'; | ||||
|  | ||||
| import { CMD_SNOOZE_NOTIFICATION } from './commandBarBusEvents'; | ||||
| import { ICON_SNOOZE_NOTIFICATION } from './CommandBarIcons'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| import { isAInboxViewRoute } from 'dashboard/helper/routeHelpers'; | ||||
|  | ||||
| @@ -21,7 +22,7 @@ const INBOX_SNOOZE_EVENTS = [ | ||||
|     section: 'COMMAND_BAR.SECTIONS.SNOOZE_NOTIFICATION', | ||||
|     icon: ICON_SNOOZE_NOTIFICATION, | ||||
|     handler: () => | ||||
|       bus.$emit(CMD_SNOOZE_NOTIFICATION, SNOOZE_OPTIONS.AN_HOUR_FROM_NOW), | ||||
|       emitter.emit(CMD_SNOOZE_NOTIFICATION, SNOOZE_OPTIONS.AN_HOUR_FROM_NOW), | ||||
|   }, | ||||
|   { | ||||
|     id: SNOOZE_OPTIONS.UNTIL_TOMORROW, | ||||
| @@ -30,7 +31,7 @@ const INBOX_SNOOZE_EVENTS = [ | ||||
|     parent: 'snooze_notification', | ||||
|     icon: ICON_SNOOZE_NOTIFICATION, | ||||
|     handler: () => | ||||
|       bus.$emit(CMD_SNOOZE_NOTIFICATION, SNOOZE_OPTIONS.UNTIL_TOMORROW), | ||||
|       emitter.emit(CMD_SNOOZE_NOTIFICATION, SNOOZE_OPTIONS.UNTIL_TOMORROW), | ||||
|   }, | ||||
|   { | ||||
|     id: SNOOZE_OPTIONS.UNTIL_NEXT_WEEK, | ||||
| @@ -39,7 +40,7 @@ const INBOX_SNOOZE_EVENTS = [ | ||||
|     parent: 'snooze_notification', | ||||
|     icon: ICON_SNOOZE_NOTIFICATION, | ||||
|     handler: () => | ||||
|       bus.$emit(CMD_SNOOZE_NOTIFICATION, SNOOZE_OPTIONS.UNTIL_NEXT_WEEK), | ||||
|       emitter.emit(CMD_SNOOZE_NOTIFICATION, SNOOZE_OPTIONS.UNTIL_NEXT_WEEK), | ||||
|   }, | ||||
|   { | ||||
|     id: SNOOZE_OPTIONS.UNTIL_NEXT_MONTH, | ||||
| @@ -48,7 +49,7 @@ const INBOX_SNOOZE_EVENTS = [ | ||||
|     parent: 'snooze_notification', | ||||
|     icon: ICON_SNOOZE_NOTIFICATION, | ||||
|     handler: () => | ||||
|       bus.$emit(CMD_SNOOZE_NOTIFICATION, SNOOZE_OPTIONS.UNTIL_NEXT_MONTH), | ||||
|       emitter.emit(CMD_SNOOZE_NOTIFICATION, SNOOZE_OPTIONS.UNTIL_NEXT_MONTH), | ||||
|   }, | ||||
|   { | ||||
|     id: SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME, | ||||
| @@ -57,7 +58,7 @@ const INBOX_SNOOZE_EVENTS = [ | ||||
|     parent: 'snooze_notification', | ||||
|     icon: ICON_SNOOZE_NOTIFICATION, | ||||
|     handler: () => | ||||
|       bus.$emit(CMD_SNOOZE_NOTIFICATION, SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME), | ||||
|       emitter.emit(CMD_SNOOZE_NOTIFICATION, SNOOZE_OPTIONS.UNTIL_CUSTOM_TIME), | ||||
|   }, | ||||
| ]; | ||||
| export default { | ||||
|   | ||||
| @@ -169,7 +169,7 @@ export default { | ||||
|             after: messageId, | ||||
|           }) | ||||
|           .then(() => { | ||||
|             bus.$emit(BUS_EVENTS.SCROLL_TO_MESSAGE, { messageId }); | ||||
|             this.$emitter.emit(BUS_EVENTS.SCROLL_TO_MESSAGE, { messageId }); | ||||
|           }); | ||||
|       } else { | ||||
|         this.$store.dispatch('clearSelectedState'); | ||||
|   | ||||
| @@ -271,7 +271,10 @@ export default { | ||||
|     }, | ||||
|     toggleConversationModal() { | ||||
|       this.showConversationModal = !this.showConversationModal; | ||||
|       bus.$emit(BUS_EVENTS.NEW_CONVERSATION_MODAL, this.showConversationModal); | ||||
|       this.$emitter.emit( | ||||
|         BUS_EVENTS.NEW_CONVERSATION_MODAL, | ||||
|         this.showConversationModal | ||||
|       ); | ||||
|     }, | ||||
|     toggleDeleteModal() { | ||||
|       this.showDeleteModal = !this.showDeleteModal; | ||||
|   | ||||
| @@ -265,7 +265,7 @@ export default { | ||||
|   }, | ||||
|  | ||||
|   mounted() { | ||||
|     bus.$on(BUS_EVENTS.TOGGLE_SIDEMENU, this.toggleSidebar); | ||||
|     this.$emitter.on(BUS_EVENTS.TOGGLE_SIDEMENU, this.toggleSidebar); | ||||
|  | ||||
|     const slug = this.$route.params.portalSlug; | ||||
|     if (slug) this.lastActivePortalSlug = slug; | ||||
| @@ -273,7 +273,7 @@ export default { | ||||
|     this.fetchPortalAndItsCategories(); | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     bus.$off(BUS_EVENTS.TOGGLE_SIDEMENU, this.toggleSidebar); | ||||
|     this.$emitter.off(BUS_EVENTS.TOGGLE_SIDEMENU, this.toggleSidebar); | ||||
|   }, | ||||
|   updated() { | ||||
|     const slug = this.$route.params.portalSlug; | ||||
|   | ||||
| @@ -140,7 +140,7 @@ export default { | ||||
|       this.$store | ||||
|         .dispatch('setActiveChat', { data: selectedConversation }) | ||||
|         .then(() => { | ||||
|           bus.$emit(BUS_EVENTS.SCROLL_TO_MESSAGE); | ||||
|           this.$emitter.emit(BUS_EVENTS.SCROLL_TO_MESSAGE); | ||||
|         }); | ||||
|     }, | ||||
|     findConversation() { | ||||
|   | ||||
| @@ -92,10 +92,10 @@ export default { | ||||
|     ...mapGetters({ meta: 'notifications/getMeta' }), | ||||
|   }, | ||||
|   mounted() { | ||||
|     bus.$on(CMD_SNOOZE_NOTIFICATION, this.onCmdSnoozeNotification); | ||||
|     this.$emitter.on(CMD_SNOOZE_NOTIFICATION, this.onCmdSnoozeNotification); | ||||
|   }, | ||||
|   destroyed() { | ||||
|     bus.$off(CMD_SNOOZE_NOTIFICATION, this.onCmdSnoozeNotification); | ||||
|     this.$emitter.off(CMD_SNOOZE_NOTIFICATION, this.onCmdSnoozeNotification); | ||||
|   }, | ||||
|   methods: { | ||||
|     openSnoozeNotificationModal() { | ||||
|   | ||||
| @@ -69,8 +69,10 @@ | ||||
| <script> | ||||
| import { required, minLength, email } from 'vuelidate/lib/validators'; | ||||
| import { mapGetters } from 'vuex'; | ||||
| import alertMixin from 'shared/mixins/alertMixin'; | ||||
|  | ||||
| export default { | ||||
|   mixins: [alertMixin], | ||||
|   props: { | ||||
|     onClose: { | ||||
|       type: Function, | ||||
| @@ -117,9 +119,6 @@ export default { | ||||
|   }, | ||||
|  | ||||
|   methods: { | ||||
|     showAlert(message) { | ||||
|       bus.$emit('newToastMessage', message); | ||||
|     }, | ||||
|     async addAgent() { | ||||
|       try { | ||||
|         await this.$store.dispatch('agents/create', { | ||||
|   | ||||
| @@ -83,6 +83,7 @@ import WootSubmitButton from '../../../../components/buttons/FormSubmitButton.vu | ||||
| import Modal from '../../../../components/Modal.vue'; | ||||
| import Auth from '../../../../api/auth'; | ||||
| import wootConstants from 'dashboard/constants/globals'; | ||||
| import alertMixin from 'shared/mixins/alertMixin'; | ||||
|  | ||||
| const { AVAILABILITY_STATUS_KEYS } = wootConstants; | ||||
|  | ||||
| @@ -91,6 +92,7 @@ export default { | ||||
|     WootSubmitButton, | ||||
|     Modal, | ||||
|   }, | ||||
|   mixins: [alertMixin], | ||||
|   props: { | ||||
|     id: { | ||||
|       type: Number, | ||||
| @@ -169,9 +171,6 @@ export default { | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     showAlert(message) { | ||||
|       bus.$emit('newToastMessage', message); | ||||
|     }, | ||||
|     async editAgent() { | ||||
|       try { | ||||
|         await this.$store.dispatch('agents/update', { | ||||
|   | ||||
| @@ -130,6 +130,7 @@ import globalConfigMixin from 'shared/mixins/globalConfigMixin'; | ||||
| import Thumbnail from '../../../../components/widgets/Thumbnail.vue'; | ||||
| import AddAgent from './AddAgent.vue'; | ||||
| import EditAgent from './EditAgent.vue'; | ||||
| import alertMixin from 'shared/mixins/alertMixin'; | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
| @@ -137,7 +138,7 @@ export default { | ||||
|     EditAgent, | ||||
|     Thumbnail, | ||||
|   }, | ||||
|   mixins: [globalConfigMixin], | ||||
|   mixins: [globalConfigMixin, alertMixin], | ||||
|   data() { | ||||
|     return { | ||||
|       loading: {}, | ||||
| @@ -230,19 +231,19 @@ export default { | ||||
|     async deleteAgent(id) { | ||||
|       try { | ||||
|         await this.$store.dispatch('agents/delete', id); | ||||
|         this.showAlert(this.$t('AGENT_MGMT.DELETE.API.SUCCESS_MESSAGE')); | ||||
|         this.showAlertMessage(this.$t('AGENT_MGMT.DELETE.API.SUCCESS_MESSAGE')); | ||||
|       } catch (error) { | ||||
|         this.showAlert(this.$t('AGENT_MGMT.DELETE.API.ERROR_MESSAGE')); | ||||
|         this.showAlertMessage(this.$t('AGENT_MGMT.DELETE.API.ERROR_MESSAGE')); | ||||
|       } | ||||
|     }, | ||||
|     // Show SnackBar | ||||
|     showAlert(message) { | ||||
|     showAlertMessage(message) { | ||||
|       // Reset loading, current selected agent | ||||
|       this.loading[this.currentAgent.id] = false; | ||||
|       this.currentAgent = {}; | ||||
|       // Show message | ||||
|       this.agentAPI.message = message; | ||||
|       bus.$emit('newToastMessage', message); | ||||
|       this.showAlert(message); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
|   | ||||
| @@ -132,12 +132,14 @@ | ||||
| import { mapGetters } from 'vuex'; | ||||
| import AddCanned from './AddCanned.vue'; | ||||
| import EditCanned from './EditCanned.vue'; | ||||
| import alertMixin from 'shared/mixins/alertMixin'; | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     AddCanned, | ||||
|     EditCanned, | ||||
|   }, | ||||
|   mixins: [alertMixin], | ||||
|   data() { | ||||
|     return { | ||||
|       loading: {}, | ||||
| @@ -187,13 +189,13 @@ export default { | ||||
|       }); | ||||
|       this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc'; | ||||
|     }, | ||||
|     showAlert(message) { | ||||
|     showAlertMessage(message) { | ||||
|       // Reset loading, current selected agent | ||||
|       this.loading[this.selectedResponse.id] = false; | ||||
|       this.selectedResponse = {}; | ||||
|       // Show message | ||||
|       this.cannedResponseAPI.message = message; | ||||
|       bus.$emit('newToastMessage', message); | ||||
|       this.showAlert(message); | ||||
|     }, | ||||
|     // Edit Function | ||||
|     openAddPopup() { | ||||
| @@ -230,12 +232,14 @@ export default { | ||||
|       this.$store | ||||
|         .dispatch('deleteCannedResponse', id) | ||||
|         .then(() => { | ||||
|           this.showAlert(this.$t('CANNED_MGMT.DELETE.API.SUCCESS_MESSAGE')); | ||||
|           this.showAlertMessage( | ||||
|             this.$t('CANNED_MGMT.DELETE.API.SUCCESS_MESSAGE') | ||||
|           ); | ||||
|         }) | ||||
|         .catch(error => { | ||||
|           const errorMessage = | ||||
|             error?.message || this.$t('CANNED_MGMT.DELETE.API.ERROR_MESSAGE'); | ||||
|           this.showAlert(errorMessage); | ||||
|           this.showAlertMessage(errorMessage); | ||||
|         }); | ||||
|     }, | ||||
|   }, | ||||
|   | ||||
| @@ -51,11 +51,13 @@ import { mapGetters } from 'vuex'; | ||||
| import InboxMembersAPI from '../../../../api/inboxMembers'; | ||||
| import router from '../../../index'; | ||||
| import PageHeader from '../SettingsSubPageHeader.vue'; | ||||
| import alertMixin from 'shared/mixins/alertMixin'; | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     PageHeader, | ||||
|   }, | ||||
|   mixins: [alertMixin], | ||||
|  | ||||
|   validations: { | ||||
|     selectedAgents: { | ||||
| @@ -98,7 +100,7 @@ export default { | ||||
|           }, | ||||
|         }); | ||||
|       } catch (error) { | ||||
|         bus.$emit('newToastMessage', error.message); | ||||
|         this.showAlert(error.message); | ||||
|       } | ||||
|       this.isCreating = false; | ||||
|     }, | ||||
|   | ||||
| @@ -136,12 +136,13 @@ import Settings from './Settings.vue'; | ||||
| import adminMixin from '../../../../mixins/isAdmin'; | ||||
| import accountMixin from '../../../../mixins/account'; | ||||
| import globalConfigMixin from 'shared/mixins/globalConfigMixin'; | ||||
| import alertMixin from 'shared/mixins/alertMixin'; | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     Settings, | ||||
|   }, | ||||
|   mixins: [adminMixin, accountMixin, globalConfigMixin], | ||||
|   mixins: [adminMixin, accountMixin, globalConfigMixin, alertMixin], | ||||
|   data() { | ||||
|     return { | ||||
|       loading: {}, | ||||
| @@ -194,15 +195,9 @@ export default { | ||||
|     async deleteInbox({ id }) { | ||||
|       try { | ||||
|         await this.$store.dispatch('inboxes/delete', id); | ||||
|         bus.$emit( | ||||
|           'newToastMessage', | ||||
|           this.$t('INBOX_MGMT.DELETE.API.SUCCESS_MESSAGE') | ||||
|         ); | ||||
|         this.showAlert(this.$t('INBOX_MGMT.DELETE.API.SUCCESS_MESSAGE')); | ||||
|       } catch (error) { | ||||
|         bus.$emit( | ||||
|           'newToastMessage', | ||||
|           this.$t('INBOX_MGMT.DELETE.API.ERROR_MESSAGE') | ||||
|         ); | ||||
|         this.showAlert(this.$t('INBOX_MGMT.DELETE.API.ERROR_MESSAGE')); | ||||
|       } | ||||
|     }, | ||||
|  | ||||
|   | ||||
| @@ -128,7 +128,7 @@ export default { | ||||
|     this.$store.dispatch('agents/get'); | ||||
|     this.fetchAllData(); | ||||
|  | ||||
|     bus.$on('fetch_overview_reports', () => { | ||||
|     this.$emitter.on('fetch_overview_reports', () => { | ||||
|       this.fetchAllData(); | ||||
|     }); | ||||
|   }, | ||||
|   | ||||
| @@ -6,6 +6,7 @@ import { findPendingMessageIndex } from './helpers'; | ||||
| import { MESSAGE_STATUS } from 'shared/constants/messages'; | ||||
| import wootConstants from 'dashboard/constants/globals'; | ||||
| import { BUS_EVENTS } from '../../../../shared/constants/busEvents'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| const state = { | ||||
|   allConversations: [], | ||||
| @@ -195,8 +196,8 @@ export const mutations = { | ||||
|       const { conversation: { unread_count: unreadCount = 0 } = {} } = message; | ||||
|       chat.unread_count = unreadCount; | ||||
|       if (selectedChatId === conversationId) { | ||||
|         window.bus.$emit(BUS_EVENTS.FETCH_LABEL_SUGGESTIONS); | ||||
|         window.bus.$emit(BUS_EVENTS.SCROLL_TO_MESSAGE); | ||||
|         emitter.emit(BUS_EVENTS.FETCH_LABEL_SUGGESTIONS); | ||||
|         emitter.emit(BUS_EVENTS.SCROLL_TO_MESSAGE); | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
| @@ -218,8 +219,8 @@ export const mutations = { | ||||
|       }; | ||||
|       Vue.set(allConversations, currentConversationIndex, currentConversation); | ||||
|       if (_state.selectedChatId === conversation.id) { | ||||
|         window.bus.$emit(BUS_EVENTS.FETCH_LABEL_SUGGESTIONS); | ||||
|         window.bus.$emit(BUS_EVENTS.SCROLL_TO_MESSAGE); | ||||
|         emitter.emit(BUS_EVENTS.FETCH_LABEL_SUGGESTIONS); | ||||
|         emitter.emit(BUS_EVENTS.SCROLL_TO_MESSAGE); | ||||
|       } | ||||
|     } else { | ||||
|       _state.allConversations.push(conversation); | ||||
|   | ||||
| @@ -1,6 +1,16 @@ | ||||
| import types from '../../../mutation-types'; | ||||
| import { mutations } from '../../conversations'; | ||||
|  | ||||
| jest.mock('shared/helpers/mitt', () => ({ | ||||
|   emitter: { | ||||
|     emit: jest.fn(), | ||||
|     on: jest.fn(), | ||||
|     off: jest.fn(), | ||||
|   }, | ||||
| })); | ||||
|  | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| describe('#mutations', () => { | ||||
|   describe('#EMPTY_ALL_CONVERSATION', () => { | ||||
|     it('empty conversations', () => { | ||||
| @@ -130,7 +140,7 @@ describe('#mutations', () => { | ||||
|           timestamp: 1602256198, | ||||
|         }, | ||||
|       ]); | ||||
|       expect(global.bus.$emit).not.toHaveBeenCalled(); | ||||
|       expect(emitter.emit).not.toHaveBeenCalled(); | ||||
|     }); | ||||
|  | ||||
|     it('add message to the conversation and emit scrollToMessage if it does not exist in the store', () => { | ||||
| @@ -158,7 +168,7 @@ describe('#mutations', () => { | ||||
|           timestamp: 1602256198, | ||||
|         }, | ||||
|       ]); | ||||
|       expect(global.bus.$emit).toHaveBeenCalledWith('SCROLL_TO_MESSAGE'); | ||||
|       expect(emitter.emit).toHaveBeenCalledWith('SCROLL_TO_MESSAGE'); | ||||
|     }); | ||||
|  | ||||
|     it('update message if it exist in the store', () => { | ||||
| @@ -195,7 +205,7 @@ describe('#mutations', () => { | ||||
|           ], | ||||
|         }, | ||||
|       ]); | ||||
|       expect(global.bus.$emit).not.toHaveBeenCalled(); | ||||
|       expect(emitter.emit).not.toHaveBeenCalled(); | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import { | ||||
| } from '../../helper/scriptHelpers'; | ||||
| import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage'; | ||||
| import { LocalStorage } from 'shared/helpers/localStorage'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| Cookies.defaults = { sameSite: 'Lax' }; | ||||
|  | ||||
| @@ -18,8 +19,8 @@ export const setLoadingStatus = (state, status) => { | ||||
| }; | ||||
|  | ||||
| export const setUser = user => { | ||||
|   window.bus.$emit(CHATWOOT_SET_USER, { user }); | ||||
|   window.bus.$emit(ANALYTICS_IDENTITY, { user }); | ||||
|   emitter.emit(CHATWOOT_SET_USER, { user }); | ||||
|   emitter.emit(ANALYTICS_IDENTITY, { user }); | ||||
| }; | ||||
|  | ||||
| export const getHeaderExpiry = response => | ||||
| @@ -70,8 +71,8 @@ export const deleteIndexedDBOnLogout = async () => { | ||||
| }; | ||||
|  | ||||
| export const clearCookiesOnLogout = () => { | ||||
|   window.bus.$emit(CHATWOOT_RESET); | ||||
|   window.bus.$emit(ANALYTICS_RESET); | ||||
|   emitter.emit(CHATWOOT_RESET); | ||||
|   emitter.emit(ANALYTICS_RESET); | ||||
|   clearBrowserSessionCookies(); | ||||
|   clearLocalStorageOnLogout(); | ||||
|   const globalConfig = window.globalConfig || {}; | ||||
|   | ||||
| @@ -15,6 +15,8 @@ import WootUiKit from '../dashboard/components'; | ||||
| import App from '../dashboard/App'; | ||||
| import i18n from '../dashboard/i18n'; | ||||
| import createAxios from '../dashboard/helper/APIHelper'; | ||||
| import { emitter } from '../shared/helpers/mitt'; | ||||
|  | ||||
| import commonHelpers, { isJSONValid } from '../dashboard/helper/commons'; | ||||
| import router, { initalizeRouter } from '../dashboard/routes'; | ||||
| import store from '../dashboard/store'; | ||||
| @@ -93,7 +95,8 @@ commonHelpers(); | ||||
|  | ||||
| window.WootConstants = constants; | ||||
| window.axios = createAxios(axios); | ||||
| window.bus = new Vue(); | ||||
| Vue.prototype.$emitter = emitter; | ||||
|  | ||||
| initializeChatwootEvents(); | ||||
| initializeAnalyticsEvents(); | ||||
| initalizeRouter(); | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import VueI18n from 'vue-i18n'; | ||||
| import App from '../survey/App.vue'; | ||||
| import i18n from '../survey/i18n'; | ||||
| import store from '../survey/store'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| Vue.use(VueI18n); | ||||
| Vue.use(Vuelidate); | ||||
| @@ -14,7 +15,7 @@ const i18nConfig = new VueI18n({ | ||||
| }); | ||||
|  | ||||
| // Event Bus | ||||
| window.bus = new Vue(); | ||||
| Vue.prototype.$emitter = emitter; | ||||
|  | ||||
| Vue.config.productionTip = false; | ||||
|  | ||||
|   | ||||
| @@ -13,7 +13,7 @@ import { | ||||
| } from 'shared/helpers/Validators'; | ||||
| import router from '../widget/router'; | ||||
| import { directive as onClickaway } from 'vue-clickaway'; | ||||
|  | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
| import { domPurifyConfig } from '../shared/helpers/HTMLSanitizer'; | ||||
| const PhoneInput = () => import('../widget/components/Form/PhoneInput'); | ||||
|  | ||||
| @@ -46,7 +46,7 @@ Vue.use(VueFormulate, { | ||||
|   }, | ||||
| }); | ||||
| // Event Bus | ||||
| window.bus = new Vue(); | ||||
| Vue.prototype.$emitter = emitter; | ||||
|  | ||||
| Vue.config.productionTip = false; | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { createConsumer } from '@rails/actioncable'; | ||||
| import { BUS_EVENTS } from 'shared/constants/busEvents'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| const PRESENCE_INTERVAL = 20000; | ||||
| const RECONNECT_INTERVAL = 1000; | ||||
| @@ -28,7 +29,7 @@ class BaseActionCableConnector { | ||||
|           this.onDisconnected(); | ||||
|           this.initReconnectTimer(); | ||||
|           // TODO: Remove this after completing the conversation list refetching | ||||
|           window.bus.$emit(BUS_EVENTS.WEBSOCKET_DISCONNECT); | ||||
|           emitter.emit(BUS_EVENTS.WEBSOCKET_DISCONNECT); | ||||
|         }, | ||||
|       } | ||||
|     ); | ||||
|   | ||||
							
								
								
									
										3
									
								
								app/javascript/shared/helpers/mitt.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								app/javascript/shared/helpers/mitt.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| import mitt from 'mitt'; | ||||
| const emitter = mitt(); | ||||
| export { emitter }; | ||||
							
								
								
									
										25
									
								
								app/javascript/shared/helpers/specs/mitt.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								app/javascript/shared/helpers/specs/mitt.spec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| import { emitter } from '../mitt'; | ||||
|  | ||||
| describe('emitter', () => { | ||||
|   it('should emit and listen to events correctly', () => { | ||||
|     const mockCallback = jest.fn(); | ||||
|  | ||||
|     // Subscribe to an event | ||||
|     emitter.on('event', mockCallback); | ||||
|  | ||||
|     // Emit the event | ||||
|     emitter.emit('event', 'data'); | ||||
|  | ||||
|     // Expect the callback to be called with the correct data | ||||
|     expect(mockCallback).toHaveBeenCalledWith('data'); | ||||
|  | ||||
|     // Unsubscribe from the event | ||||
|     emitter.off('event', mockCallback); | ||||
|  | ||||
|     // Emit the event again | ||||
|     emitter.emit('event', 'data'); | ||||
|  | ||||
|     // Expect the callback not to be called again | ||||
|     expect(mockCallback).toHaveBeenCalledTimes(1); | ||||
|   }); | ||||
| }); | ||||
| @@ -1,7 +1,9 @@ | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| export default { | ||||
|   methods: { | ||||
|     showAlert(message, action) { | ||||
|       bus.$emit('newToastMessage', message, action); | ||||
|       emitter.emit('newToastMessage', message, action); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
|   | ||||
| @@ -53,12 +53,14 @@ import FormInput from '../../../components/Form/Input.vue'; | ||||
| import SubmitButton from '../../../components/Button/SubmitButton.vue'; | ||||
| import { DEFAULT_REDIRECT_URL } from 'dashboard/constants/globals'; | ||||
| import { setNewPassword } from '../../../api/auth'; | ||||
| import alertMixin from 'shared/mixins/alertMixin'; | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
|     FormInput, | ||||
|     SubmitButton, | ||||
|   }, | ||||
|   mixins: [alertMixin], | ||||
|   props: { | ||||
|     resetPasswordToken: { type: String, default: '' }, | ||||
|     redirectUrl: { type: String, default: '' }, | ||||
| @@ -105,10 +107,10 @@ export default { | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     showAlert(message) { | ||||
|     showAlertMessage(message) { | ||||
|       // Reset loading, current selected agent | ||||
|       this.newPasswordAPI.showLoading = false; | ||||
|       bus.$emit('newToastMessage', message); | ||||
|       this.showAlert(message); | ||||
|     }, | ||||
|     submitForm() { | ||||
|       this.newPasswordAPI.showLoading = true; | ||||
| @@ -122,7 +124,7 @@ export default { | ||||
|           window.location = DEFAULT_REDIRECT_URL; | ||||
|         }) | ||||
|         .catch(error => { | ||||
|           this.showAlert( | ||||
|           this.showAlertMessage( | ||||
|             error?.message || this.$t('SET_NEW_PASSWORD.API.ERROR_MESSAGE') | ||||
|           ); | ||||
|         }); | ||||
|   | ||||
| @@ -53,10 +53,11 @@ import { mapGetters } from 'vuex'; | ||||
| import FormInput from '../../../../components/Form/Input.vue'; | ||||
| import { resetPassword } from '../../../../api/auth'; | ||||
| import SubmitButton from '../../../../components/Button/SubmitButton.vue'; | ||||
| import alertMixin from 'shared/mixins/alertMixin'; | ||||
|  | ||||
| export default { | ||||
|   components: { FormInput, SubmitButton }, | ||||
|   mixins: [globalConfigMixin], | ||||
|   mixins: [globalConfigMixin, alertMixin], | ||||
|   data() { | ||||
|     return { | ||||
|       credentials: { email: '' }, | ||||
| @@ -80,10 +81,10 @@ export default { | ||||
|     }, | ||||
|   }, | ||||
|   methods: { | ||||
|     showAlert(message) { | ||||
|     showAlertMessage(message) { | ||||
|       // Reset loading, current selected agent | ||||
|       this.resetPassword.showLoading = false; | ||||
|       bus.$emit('newToastMessage', message); | ||||
|       this.showAlert(message); | ||||
|     }, | ||||
|     submit() { | ||||
|       this.resetPassword.showLoading = true; | ||||
| @@ -93,7 +94,7 @@ export default { | ||||
|           if (res.data && res.data.message) { | ||||
|             successMessage = res.data.message; | ||||
|           } | ||||
|           this.showAlert(successMessage); | ||||
|           this.showAlertMessage(successMessage); | ||||
|         }) | ||||
|         .catch(error => { | ||||
|           let errorMessage = this.$t('RESET_PASSWORD.API.ERROR_MESSAGE'); | ||||
|   | ||||
| @@ -104,6 +104,7 @@ const ERROR_MESSAGES = { | ||||
|   'no-account-found': 'LOGIN.OAUTH.NO_ACCOUNT_FOUND', | ||||
|   'business-account-only': 'LOGIN.OAUTH.BUSINESS_ACCOUNTS_ONLY', | ||||
| }; | ||||
| import alertMixin from 'shared/mixins/alertMixin'; | ||||
|  | ||||
| export default { | ||||
|   components: { | ||||
| @@ -112,7 +113,7 @@ export default { | ||||
|     Spinner, | ||||
|     SubmitButton, | ||||
|   }, | ||||
|   mixins: [globalConfigMixin], | ||||
|   mixins: [globalConfigMixin, alertMixin], | ||||
|   props: { | ||||
|     ssoAuthToken: { type: String, default: '' }, | ||||
|     ssoAccountId: { type: String, default: '' }, | ||||
| @@ -186,15 +187,15 @@ export default { | ||||
|         setTimeout(callback, 0); | ||||
|       } | ||||
|     }, | ||||
|     showAlert(message) { | ||||
|     showAlertMessage(message) { | ||||
|       // Reset loading, current selected agent | ||||
|       this.loginApi.showLoading = false; | ||||
|       this.loginApi.message = message; | ||||
|       bus.$emit('newToastMessage', this.loginApi.message); | ||||
|       this.showAlert(this.loginApi.message); | ||||
|     }, | ||||
|     submitLogin() { | ||||
|       if (this.$v.credentials.email.$invalid && !this.email) { | ||||
|         this.showAlert(this.$t('LOGIN.EMAIL.ERROR')); | ||||
|         this.showAlertMessage(this.$t('LOGIN.EMAIL.ERROR')); | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|   | ||||
| @@ -43,6 +43,7 @@ import { | ||||
| } from './constants/widgetBusEvents'; | ||||
| import darkModeMixin from 'widget/mixins/darkModeMixin'; | ||||
| import { SDK_SET_BUBBLE_VISIBILITY } from '../shared/constants/sharedFrameEvents'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| export default { | ||||
|   name: 'App', | ||||
| @@ -157,34 +158,36 @@ export default { | ||||
|       } | ||||
|     }, | ||||
|     registerUnreadEvents() { | ||||
|       bus.$on(ON_AGENT_MESSAGE_RECEIVED, () => { | ||||
|       emitter.on(ON_AGENT_MESSAGE_RECEIVED, () => { | ||||
|         const { name: routeName } = this.$route; | ||||
|         if ((this.isWidgetOpen || !this.isIFrame) && routeName === 'messages') { | ||||
|           this.$store.dispatch('conversation/setUserLastSeen'); | ||||
|         } | ||||
|         this.setUnreadView(); | ||||
|       }); | ||||
|       bus.$on(ON_UNREAD_MESSAGE_CLICK, () => { | ||||
|       emitter.on(ON_UNREAD_MESSAGE_CLICK, () => { | ||||
|         this.replaceRoute('messages').then(() => this.unsetUnreadView()); | ||||
|       }); | ||||
|     }, | ||||
|     registerCampaignEvents() { | ||||
|       bus.$on(ON_CAMPAIGN_MESSAGE_CLICK, () => { | ||||
|       emitter.on(ON_CAMPAIGN_MESSAGE_CLICK, () => { | ||||
|         if (this.shouldShowPreChatForm) { | ||||
|           this.replaceRoute('prechat-form'); | ||||
|         } else { | ||||
|           this.replaceRoute('messages'); | ||||
|           bus.$emit('execute-campaign', { campaignId: this.activeCampaign.id }); | ||||
|           emitter.emit('execute-campaign', { | ||||
|             campaignId: this.activeCampaign.id, | ||||
|           }); | ||||
|         } | ||||
|         this.unsetUnreadView(); | ||||
|       }); | ||||
|       bus.$on('execute-campaign', campaignDetails => { | ||||
|       emitter.on('execute-campaign', campaignDetails => { | ||||
|         const { customAttributes, campaignId } = campaignDetails; | ||||
|         const { websiteToken } = window.chatwootWebChannel; | ||||
|         this.executeCampaign({ campaignId, websiteToken, customAttributes }); | ||||
|         this.replaceRoute('messages'); | ||||
|       }); | ||||
|       bus.$on('snooze-campaigns', () => { | ||||
|       emitter.on('snooze-campaigns', () => { | ||||
|         const expireBy = addHours(new Date(), 1); | ||||
|         this.campaignsSnoozedTill = Number(expireBy); | ||||
|       }); | ||||
|   | ||||
| @@ -93,6 +93,7 @@ import { isASubmittedFormMessage } from 'shared/helpers/MessageTypeHelper'; | ||||
| import darkModeMixin from 'widget/mixins/darkModeMixin.js'; | ||||
| import ReplyToChip from 'widget/components/ReplyToChip.vue'; | ||||
| import { BUS_EVENTS } from 'shared/constants/busEvents'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| export default { | ||||
|   name: 'AgentMessage', | ||||
| @@ -224,7 +225,7 @@ export default { | ||||
|       this.hasImageError = true; | ||||
|     }, | ||||
|     toggleReply() { | ||||
|       bus.$emit(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.message); | ||||
|       emitter.emit(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.message); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
|  | ||||
| <script> | ||||
| import { BUS_EVENTS } from 'shared/constants/busEvents'; | ||||
| import { emitter } from 'shared/helpers/mitt'; | ||||
|  | ||||
| export default { | ||||
|   data() { | ||||
| @@ -18,7 +19,7 @@ export default { | ||||
|     }; | ||||
|   }, | ||||
|   mounted() { | ||||
|     bus.$on(BUS_EVENTS.SHOW_ALERT, ({ message, type = 'error' }) => { | ||||
|     emitter.on(BUS_EVENTS.SHOW_ALERT, ({ message, type = 'error' }) => { | ||||
|       this.bannerMessage = message; | ||||
|       this.bannerType = type; | ||||
|       this.showBannerMessage = true; | ||||
|   | ||||
| @@ -96,7 +96,7 @@ export default { | ||||
|  | ||||
|           upload.create((error, blob) => { | ||||
|             if (error) { | ||||
|               window.bus.$emit(BUS_EVENTS.SHOW_ALERT, { | ||||
|               this.$emitter.emit(BUS_EVENTS.SHOW_ALERT, { | ||||
|                 message: error, | ||||
|               }); | ||||
|             } else { | ||||
| @@ -107,7 +107,7 @@ export default { | ||||
|             } | ||||
|           }); | ||||
|         } else { | ||||
|           window.bus.$emit(BUS_EVENTS.SHOW_ALERT, { | ||||
|           this.$emitter.emit(BUS_EVENTS.SHOW_ALERT, { | ||||
|             message: this.$t('FILE_SIZE_LIMIT', { | ||||
|               MAXIMUM_FILE_UPLOAD_SIZE: this.fileUploadSizeLimit, | ||||
|             }), | ||||
| @@ -130,7 +130,7 @@ export default { | ||||
|             ...this.getLocalFileAttributes(file), | ||||
|           }); | ||||
|         } else { | ||||
|           window.bus.$emit(BUS_EVENTS.SHOW_ALERT, { | ||||
|           this.$emitter.emit(BUS_EVENTS.SHOW_ALERT, { | ||||
|             message: this.$t('FILE_SIZE_LIMIT', { | ||||
|               MAXIMUM_FILE_UPLOAD_SIZE: this.fileUploadSizeLimit, | ||||
|             }), | ||||
|   | ||||
| @@ -147,12 +147,12 @@ export default { | ||||
|       if (this.hasEmail) { | ||||
|         try { | ||||
|           await sendEmailTranscript(); | ||||
|           window.bus.$emit(BUS_EVENTS.SHOW_ALERT, { | ||||
|           this.$emitter.emit(BUS_EVENTS.SHOW_ALERT, { | ||||
|             message: this.$t('EMAIL_TRANSCRIPT.SEND_EMAIL_SUCCESS'), | ||||
|             type: 'success', | ||||
|           }); | ||||
|         } catch (error) { | ||||
|           window.bus.$emit(BUS_EVENTS.SHOW_ALERT, { | ||||
|           this.$emitter.$emit(BUS_EVENTS.SHOW_ALERT, { | ||||
|             message: this.$t('EMAIL_TRANSCRIPT.SEND_EMAIL_ERROR'), | ||||
|           }); | ||||
|         } | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import { ON_AGENT_MESSAGE_RECEIVED } from '../constants/widgetBusEvents'; | ||||
| import { IFrameHelper } from 'widget/helpers/utils'; | ||||
| import { shouldTriggerMessageUpdateEvent } from './IframeEventHelper'; | ||||
| import { CHATWOOT_ON_MESSAGE } from '../constants/sdkEvents'; | ||||
| import { emitter } from '../../shared/helpers/mitt'; | ||||
|  | ||||
| const isMessageInActiveConversation = (getters, message) => { | ||||
|   const { conversation_id: conversationId } = message; | ||||
| @@ -57,7 +58,7 @@ class ActionCableConnector extends BaseActionCableConnector { | ||||
|  | ||||
|     this.app.$store | ||||
|       .dispatch('conversation/addOrUpdateMessage', data) | ||||
|       .then(() => window.bus.$emit(ON_AGENT_MESSAGE_RECEIVED)); | ||||
|       .then(() => emitter.emit(ON_AGENT_MESSAGE_RECEIVED)); | ||||
|  | ||||
|     IFrameHelper.sendMessage({ | ||||
|       event: 'onEvent', | ||||
|   | ||||
| @@ -31,6 +31,7 @@ | ||||
|   ], | ||||
|   "dependencies": { | ||||
|     "@braid/vue-formulate": "^2.5.2", | ||||
|     "@chatwoot/ninja-keys": "1.2.3", | ||||
|     "@chatwoot/prosemirror-schema": "1.0.9", | ||||
|     "@chatwoot/utils": "^0.0.25", | ||||
|     "@hcaptcha/vue-hcaptcha": "^0.3.2", | ||||
| @@ -67,7 +68,7 @@ | ||||
|     "markdown-it": "^13.0.2", | ||||
|     "markdown-it-link-attributes": "^4.0.1", | ||||
|     "md5": "^2.3.0", | ||||
|     "@chatwoot/ninja-keys": "1.2.3", | ||||
|     "mitt": "^3.0.1", | ||||
|     "opus-recorder": "^8.0.5", | ||||
|     "postcss": "^8.4.31", | ||||
|     "postcss-loader": "^4.2.0", | ||||
|   | ||||
| @@ -14929,6 +14929,11 @@ mississippi@^3.0.0: | ||||
|     stream-each "^1.1.0" | ||||
|     through2 "^2.0.0" | ||||
|  | ||||
| mitt@^3.0.1: | ||||
|   version "3.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1" | ||||
|   integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw== | ||||
|  | ||||
| mixin-deep@^1.2.0: | ||||
|   version "1.3.2" | ||||
|   resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Fayaz Ahmed
					Fayaz Ahmed