diff --git a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue index 0c46c43e8..c24a02a42 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue @@ -178,8 +178,6 @@ import inboxMixin from 'shared/mixins/inboxMixin'; import uiSettingsMixin from 'dashboard/mixins/uiSettings'; import { DirectUpload } from 'activestorage'; import { frontendURL } from '../../../helper/URLHelper'; -import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage'; -import { LocalStorage } from 'shared/helpers/localStorage'; import { trimContent, debounce } from '@chatwoot/utils'; import wootConstants from 'dashboard/constants/globals'; import { isEditorHotKeyEnabled } from 'dashboard/mixins/uiSettings'; @@ -583,30 +581,15 @@ export default { display_rich_content_editor: !this.showRichContentEditor, }); }, - getSavedDraftMessages() { - return LocalStorage.get(LOCAL_STORAGE_KEYS.DRAFT_MESSAGES) || {}; - }, saveDraft(conversationId, replyType) { if (this.message || this.message === '') { - const savedDraftMessages = this.getSavedDraftMessages(); const key = `draft-${conversationId}-${replyType}`; const draftToSave = trimContent(this.message || ''); - const { - [key]: currentDraft, - ...restOfDraftMessages - } = savedDraftMessages; - const updatedDraftMessages = draftToSave - ? { - ...restOfDraftMessages, - [key]: draftToSave, - } - : restOfDraftMessages; - - LocalStorage.set( - LOCAL_STORAGE_KEYS.DRAFT_MESSAGES, - updatedDraftMessages - ); + this.$store.dispatch('draftMessages/set', { + key, + message: draftToSave, + }); } }, setToDraft(conversationId, replyType) { @@ -615,24 +598,14 @@ export default { }, getFromDraft() { if (this.conversationIdByRoute) { - try { - const key = `draft-${this.conversationIdByRoute}-${this.replyType}`; - const savedDraftMessages = this.getSavedDraftMessages(); - this.message = `${savedDraftMessages[key] || ''}`; - } catch (error) { - this.message = ''; - } + const key = `draft-${this.conversationIdByRoute}-${this.replyType}`; + this.message = this.$store.getters['draftMessages/get'](key) || ''; } }, removeFromDraft() { if (this.conversationIdByRoute) { const key = `draft-${this.conversationIdByRoute}-${this.replyType}`; - const draftMessages = this.getSavedDraftMessages(); - const { [key]: toBeRemoved, ...updatedDraftMessages } = draftMessages; - LocalStorage.set( - LOCAL_STORAGE_KEYS.DRAFT_MESSAGES, - updatedDraftMessages - ); + this.$store.dispatch('draftMessages/delete', { key }); } }, handleKeyEvents(e) { diff --git a/app/javascript/dashboard/store/index.js b/app/javascript/dashboard/store/index.js index 004b8e994..3901223dc 100755 --- a/app/javascript/dashboard/store/index.js +++ b/app/javascript/dashboard/store/index.js @@ -42,6 +42,7 @@ import teamMembers from './modules/teamMembers'; import teams from './modules/teams'; import userNotificationSettings from './modules/userNotificationSettings'; import webhooks from './modules/webhooks'; +import draftMessages from './modules/draftMessages'; import LogRocket from 'logrocket'; import createPlugin from 'logrocket-vuex'; @@ -106,6 +107,7 @@ export default new Vuex.Store({ teams, userNotificationSettings, webhooks, + draftMessages, }, plugins, }); diff --git a/app/javascript/dashboard/store/modules/draftMessages.js b/app/javascript/dashboard/store/modules/draftMessages.js new file mode 100644 index 000000000..929330040 --- /dev/null +++ b/app/javascript/dashboard/store/modules/draftMessages.js @@ -0,0 +1,44 @@ +import Vue from 'vue'; +import types from '../mutation-types'; + +import { LocalStorage } from 'shared/helpers/localStorage'; +import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage'; + +const state = { + records: LocalStorage.get(LOCAL_STORAGE_KEYS.DRAFT_MESSAGES) || {}, +}; + +export const getters = { + get: _state => key => { + return _state.records[key] || ''; + }, +}; + +export const actions = { + set: async ({ commit }, { key, message }) => { + commit(types.SET_DRAFT_MESSAGES, { key, message }); + }, + delete: ({ commit }, { key }) => { + commit(types.SET_DRAFT_MESSAGES, { key }); + }, +}; + +export const mutations = { + [types.SET_DRAFT_MESSAGES]($state, { key, message }) { + Vue.set($state.records, key, message); + LocalStorage.set(LOCAL_STORAGE_KEYS.DRAFT_MESSAGES, $state.records); + }, + [types.REMOVE_DRAFT_MESSAGES]($state, { key }) { + const { [key]: draftToBeRemoved, ...updatedRecords } = $state.records; + Vue.set($state, 'records', updatedRecords); + LocalStorage.set(LOCAL_STORAGE_KEYS.DRAFT_MESSAGES, $state.records); + }, +}; + +export default { + namespaced: true, + state, + getters, + actions, + mutations, +}; diff --git a/app/javascript/dashboard/store/modules/specs/draftMessages/actions.spec.js b/app/javascript/dashboard/store/modules/specs/draftMessages/actions.spec.js new file mode 100644 index 000000000..b2d80d19b --- /dev/null +++ b/app/javascript/dashboard/store/modules/specs/draftMessages/actions.spec.js @@ -0,0 +1,54 @@ +import axios from 'axios'; +import { actions } from '../../draftMessages'; +import types from '../../../mutation-types'; + +const commit = jest.fn(); +global.axios = axios; +jest.mock('axios'); + +describe('#actions', () => { + describe('#set', () => { + it('sends correct actions', async () => { + await actions.set( + { + commit, + state: { + draftMessages: {}, + }, + }, + { key: 'draft-32-REPLY', message: 'Hey how ' } + ); + expect(commit.mock.calls).toEqual([ + [ + types.SET_DRAFT_MESSAGES, + { + key: 'draft-32-REPLY', + message: 'Hey how ', + }, + ], + ]); + }); + }); + + describe('#delete', () => { + it('sends correct actions', async () => { + await actions.delete( + { + commit, + state: { + draftMessages: {}, + }, + }, + { key: 'draft-32-REPLY' } + ); + expect(commit.mock.calls).toEqual([ + [ + types.SET_DRAFT_MESSAGES, + { + key: 'draft-32-REPLY', + }, + ], + ]); + }); + }); +}); diff --git a/app/javascript/dashboard/store/modules/specs/draftMessages/fixtures.js b/app/javascript/dashboard/store/modules/specs/draftMessages/fixtures.js new file mode 100644 index 000000000..268cbf753 --- /dev/null +++ b/app/javascript/dashboard/store/modules/specs/draftMessages/fixtures.js @@ -0,0 +1 @@ +export const data = { 'draft-32-REPLY': 'Hey how ', 'draft-31-REPLY': 'Nice' }; diff --git a/app/javascript/dashboard/store/modules/specs/draftMessages/getters.spec.js b/app/javascript/dashboard/store/modules/specs/draftMessages/getters.spec.js new file mode 100644 index 000000000..31913442c --- /dev/null +++ b/app/javascript/dashboard/store/modules/specs/draftMessages/getters.spec.js @@ -0,0 +1,18 @@ +import { getters } from '../../draftMessages'; +import { data } from './fixtures'; + +describe('#getters', () => { + it('return the payload if key is present', () => { + const state = { + records: data, + }; + expect(getters.get(state)('draft-32-REPLY')).toEqual('Hey how '); + }); + + it('return empty string if key is not present', () => { + const state = { + records: data, + }; + expect(getters.get(state)('draft-22-REPLY')).toEqual(''); + }); +}); diff --git a/app/javascript/dashboard/store/modules/specs/draftMessages/mutations.spec.js b/app/javascript/dashboard/store/modules/specs/draftMessages/mutations.spec.js new file mode 100644 index 000000000..9acc98879 --- /dev/null +++ b/app/javascript/dashboard/store/modules/specs/draftMessages/mutations.spec.js @@ -0,0 +1,33 @@ +import types from '../../../mutation-types'; +import { mutations } from '../../draftMessages'; + +describe('#mutations', () => { + describe('#SET_DRAFT_MESSAGES', () => { + it('sets the draft messages', () => { + const state = { + records: {}, + }; + mutations[types.SET_DRAFT_MESSAGES](state, { + key: 'draft-32-REPLY', + message: 'Hey how ', + }); + expect(state.records).toEqual({ + 'draft-32-REPLY': 'Hey how ', + }); + }); + }); + + describe('#REMOVE_DRAFT_MESSAGES', () => { + it('removes the draft messages', () => { + const state = { + records: { + 'draft-32-REPLY': 'Hey how ', + }, + }; + mutations[types.REMOVE_DRAFT_MESSAGES](state, { + key: 'draft-32-REPLY', + }); + expect(state.records).toEqual({}); + }); + }); +}); diff --git a/app/javascript/dashboard/store/mutation-types.js b/app/javascript/dashboard/store/mutation-types.js index 554288ad1..09148566f 100644 --- a/app/javascript/dashboard/store/mutation-types.js +++ b/app/javascript/dashboard/store/mutation-types.js @@ -25,6 +25,8 @@ export default { SET_CONVERSATION_LAST_SEEN: 'SET_CONVERSATION_LAST_SEEN', SET_LAST_MESSAGE_ID_IN_SYNC_CONVERSATION: 'SET_LAST_MESSAGE_ID_FOR_SYNC_CONVERSATION', + SET_DRAFT_MESSAGES: 'SET_DRAFT_MESSAGES', + REMOVE_DRAFT_MESSAGES: 'REMOVE_DRAFT_MESSAGES', SET_CURRENT_CHAT_WINDOW: 'SET_CURRENT_CHAT_WINDOW', CLEAR_CURRENT_CHAT_WINDOW: 'CLEAR_CURRENT_CHAT_WINDOW',