diff --git a/app/javascript/dashboard/components/ChatList.vue b/app/javascript/dashboard/components/ChatList.vue index 9f333f4c8..6fd51f747 100644 --- a/app/javascript/dashboard/components/ChatList.vue +++ b/app/javascript/dashboard/components/ChatList.vue @@ -377,6 +377,9 @@ export default { if (this.conversationType === 'mention') { return this.$t('CHAT_LIST.MENTION_HEADING'); } + if (this.conversationType === 'participating') { + return this.$t('CONVERSATION_PARTICIPANTS.SIDEBAR_MENU_TITLE'); + } if (this.conversationType === 'unattended') { return this.$t('CHAT_LIST.UNATTENDED_HEADING'); } diff --git a/app/javascript/dashboard/components/layout/config/sidebarItems/conversations.js b/app/javascript/dashboard/components/layout/config/sidebarItems/conversations.js index 9455bf8af..a8302bd58 100644 --- a/app/javascript/dashboard/components/layout/config/sidebarItems/conversations.js +++ b/app/javascript/dashboard/components/layout/config/sidebarItems/conversations.js @@ -14,6 +14,8 @@ const conversations = accountId => ({ 'conversations_through_team', 'conversation_mentions', 'conversation_through_mentions', + 'conversation_participating', + 'conversation_through_participating', 'folder_conversations', 'conversations_through_folders', 'conversation_unattended', diff --git a/app/javascript/dashboard/components/layout/sidebarComponents/OptionsMenu.vue b/app/javascript/dashboard/components/layout/sidebarComponents/OptionsMenu.vue index c100fe93a..2dba51a5e 100644 --- a/app/javascript/dashboard/components/layout/sidebarComponents/OptionsMenu.vue +++ b/app/javascript/dashboard/components/layout/sidebarComponents/OptionsMenu.vue @@ -154,6 +154,7 @@ export default { left: var(--space-slab); bottom: var(--space-larger); min-width: 22rem; + top: unset; z-index: var(--z-index-low); } diff --git a/app/javascript/dashboard/helper/URLHelper.js b/app/javascript/dashboard/helper/URLHelper.js index f181ff761..68cadfb72 100644 --- a/app/javascript/dashboard/helper/URLHelper.js +++ b/app/javascript/dashboard/helper/URLHelper.js @@ -56,6 +56,8 @@ export const conversationUrl = ({ url = `accounts/${accountId}/custom_view/${foldersId}/conversations/${id}`; } else if (conversationType === 'mention') { url = `accounts/${accountId}/mentions/conversations/${id}`; + } else if (conversationType === 'participating') { + url = `accounts/${accountId}/participating/conversations/${id}`; } else if (conversationType === 'unattended') { url = `accounts/${accountId}/unattended/conversations/${id}`; } diff --git a/app/javascript/dashboard/i18n/locale/en/contact.json b/app/javascript/dashboard/i18n/locale/en/contact.json index 14ab0032d..3b92097a1 100644 --- a/app/javascript/dashboard/i18n/locale/en/contact.json +++ b/app/javascript/dashboard/i18n/locale/en/contact.json @@ -346,4 +346,5 @@ "ERROR_MESSAGE": "Could not merge contacts, try again!" } } + } diff --git a/app/javascript/dashboard/i18n/locale/en/conversation.json b/app/javascript/dashboard/i18n/locale/en/conversation.json index 444fd0011..f98a3cdc0 100644 --- a/app/javascript/dashboard/i18n/locale/en/conversation.json +++ b/app/javascript/dashboard/i18n/locale/en/conversation.json @@ -255,6 +255,23 @@ "CC": "Cc", "SUBJECT": "Subject" }, + "CONVERSATION_PARTICIPANTS": { + "SIDEBAR_MENU_TITLE": "Participating", + "SIDEBAR_TITLE": "Conversation participants", + "NO_RECORDS_FOUND": "No results found", + "ADD_PARTICIPANTS": "Select participants", + "REMANING_PARTICIPANTS_TEXT": "+%{count} others", + "REMANING_PARTICIPANT_TEXT": "+%{count} other", + "TOTAL_PARTICIPANTS_TEXT": "%{count} people are participating.", + "TOTAL_PARTICIPANT_TEXT": "%{count} person is participating.", + "NO_PARTICIPANTS_TEXT": "No one is participating!.", + "WATCH_CONVERSATION": "Join conversation", + "YOU_ARE_WATCHING": "You are participating", + "API": { + "ERROR_MESSAGE": "Could not update, try again!", + "SUCCESS_MESSAGE": "Participants updated!" + } + }, "TRANSLATE_MODAL": { "TITLE": "View translated content", "DESC": "You can view the translated content in each langauge.", diff --git a/app/javascript/dashboard/i18n/locale/en/generalSettings.json b/app/javascript/dashboard/i18n/locale/en/generalSettings.json index f1d87ee73..367b35b1c 100644 --- a/app/javascript/dashboard/i18n/locale/en/generalSettings.json +++ b/app/javascript/dashboard/i18n/locale/en/generalSettings.json @@ -82,6 +82,7 @@ "conversation_creation": "New conversation", "conversation_assignment": "Conversation Assigned", "assigned_conversation_new_message": "New Message", + "participating_conversation_new_message": "New Message", "conversation_mention": "Mention" } }, diff --git a/app/javascript/dashboard/i18n/locale/en/settings.json b/app/javascript/dashboard/i18n/locale/en/settings.json index d1e2a6ed8..9fff8d68b 100644 --- a/app/javascript/dashboard/i18n/locale/en/settings.json +++ b/app/javascript/dashboard/i18n/locale/en/settings.json @@ -79,7 +79,8 @@ "CONVERSATION_ASSIGNMENT": "Send email notifications when a conversation is assigned to me", "CONVERSATION_CREATION": "Send email notifications when a new conversation is created", "CONVERSATION_MENTION": "Send email notifications when you are mentioned in a conversation", - "ASSIGNED_CONVERSATION_NEW_MESSAGE": "Send email notifications when a new message is created in an assigned conversation" + "ASSIGNED_CONVERSATION_NEW_MESSAGE": "Send email notifications when a new message is created in an assigned conversation", + "PARTICIPATING_CONVERSATION_NEW_MESSAGE": "Send email notifications when a new message is created in a participating conversation" }, "API": { "UPDATE_SUCCESS": "Your notification preferences are updated successfully", @@ -92,6 +93,7 @@ "CONVERSATION_CREATION": "Send push notifications when a new conversation is created", "CONVERSATION_MENTION": "Send push notifications when you are mentioned in a conversation", "ASSIGNED_CONVERSATION_NEW_MESSAGE": "Send push notifications when a new message is created in an assigned conversation", + "PARTICIPATING_CONVERSATION_NEW_MESSAGE": "Send push notifications when a new message is created in a participating conversation", "HAS_ENABLED_PUSH": "You have enabled push for this browser.", "REQUEST_PUSH": "Enable push notifications" }, @@ -188,6 +190,7 @@ "CONVERSATIONS": "Conversations", "ALL_CONVERSATIONS": "All Conversations", "MENTIONED_CONVERSATIONS": "Mentions", + "PARTICIPATING_CONVERSATIONS": "Participating", "UNATTENDED_CONVERSATIONS": "Unattended", "REPORTS": "Reports", "SETTINGS": "Settings", diff --git a/app/javascript/dashboard/mixins/specs/uiSettings.spec.js b/app/javascript/dashboard/mixins/specs/uiSettings.spec.js index 7959f8996..4ac9c207d 100644 --- a/app/javascript/dashboard/mixins/specs/uiSettings.spec.js +++ b/app/javascript/dashboard/mixins/specs/uiSettings.spec.js @@ -120,6 +120,7 @@ describe('uiSettingsMixin', () => { { name: 'conversation_info' }, { name: 'contact_attributes' }, { name: 'previous_conversation' }, + { name: 'conversation_participants' }, ]); }); }); diff --git a/app/javascript/dashboard/mixins/uiSettings.js b/app/javascript/dashboard/mixins/uiSettings.js index e517d6961..08a46c5c1 100644 --- a/app/javascript/dashboard/mixins/uiSettings.js +++ b/app/javascript/dashboard/mixins/uiSettings.js @@ -5,6 +5,7 @@ export const DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER = [ { name: 'conversation_info' }, { name: 'contact_attributes' }, { name: 'previous_conversation' }, + { name: 'conversation_participants' }, ]; export const DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER = [ { name: 'contact_attributes' }, diff --git a/app/javascript/dashboard/routes/dashboard/conversation/ContactPanel.vue b/app/javascript/dashboard/routes/dashboard/conversation/ContactPanel.vue index 4c20bfec2..ff43b1e22 100644 --- a/app/javascript/dashboard/routes/dashboard/conversation/ContactPanel.vue +++ b/app/javascript/dashboard/routes/dashboard/conversation/ContactPanel.vue @@ -39,6 +39,24 @@ /> +
+ + + +
+
+
+
+
+

+ + {{ totalWatchersText }} +

+

+ {{ $t('CONVERSATION_PARTICIPANTS.NO_PARTICIPANTS_TEXT') }} +

+
+ +
+
+
+ +

+ {{ $t('CONVERSATION_PARTICIPANTS.YOU_ARE_WATCHING') }} +

+ + {{ $t('CONVERSATION_PARTICIPANTS.WATCH_CONVERSATION') }} + +
+ +
+ + + + diff --git a/app/javascript/dashboard/routes/dashboard/conversation/conversation.routes.js b/app/javascript/dashboard/routes/dashboard/conversation/conversation.routes.js index b1b0504a6..d63de6cdf 100644 --- a/app/javascript/dashboard/routes/dashboard/conversation/conversation.routes.js +++ b/app/javascript/dashboard/routes/dashboard/conversation/conversation.routes.js @@ -121,7 +121,6 @@ export default { conversationType: 'mention', }), }, - { path: frontendURL('accounts/:accountId/unattended/conversations'), name: 'conversation_unattended', @@ -141,5 +140,24 @@ export default { conversationType: 'unattended', }), }, + { + path: frontendURL('accounts/:accountId/participating/conversations'), + name: 'conversation_participating', + roles: ['administrator', 'agent'], + component: ConversationView, + props: () => ({ conversationType: 'participating' }), + }, + { + path: frontendURL( + 'accounts/:accountId/participating/conversations/:conversationId' + ), + name: 'conversation_through_participating', + roles: ['administrator', 'agent'], + component: ConversationView, + props: route => ({ + conversationId: route.params.conversationId, + conversationType: 'participating', + }), + }, ], }; diff --git a/app/javascript/dashboard/routes/dashboard/settings/profile/NotificationSettings.vue b/app/javascript/dashboard/routes/dashboard/settings/profile/NotificationSettings.vue index 5e287a686..2c3650c29 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/profile/NotificationSettings.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/profile/NotificationSettings.vue @@ -216,6 +216,22 @@ }}
+
+ + +
+ +
+ + +
diff --git a/app/javascript/dashboard/store/modules/conversationWatchers.js b/app/javascript/dashboard/store/modules/conversationWatchers.js index d8da9cdb8..1e1050e49 100644 --- a/app/javascript/dashboard/store/modules/conversationWatchers.js +++ b/app/javascript/dashboard/store/modules/conversationWatchers.js @@ -23,7 +23,7 @@ export const getters = { export const actions = { show: async ({ commit }, { conversationId }) => { - commit(types.SET_CONVERSATION_WATCHERS_UI_FLAG, { + commit(types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: true, }); @@ -31,21 +31,21 @@ export const actions = { const response = await ConversationInboxApi.fetchParticipants( conversationId ); - commit(types.SET_CONVERSATION_WATCHERS, { + commit(types.SET_CONVERSATION_PARTICIPANTS, { conversationId, data: response.data, }); } catch (error) { throwErrorMessage(error); } finally { - commit(types.SET_CONVERSATION_WATCHERS_UI_FLAG, { + commit(types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: false, }); } }, update: async ({ commit }, { conversationId, userIds }) => { - commit(types.SET_CONVERSATION_WATCHERS_UI_FLAG, { + commit(types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: true, }); @@ -54,14 +54,14 @@ export const actions = { conversationId, userIds, }); - commit(types.SET_CONVERSATION_WATCHERS, { + commit(types.SET_CONVERSATION_PARTICIPANTS, { conversationId, data: response.data, }); } catch (error) { throwErrorMessage(error); } finally { - commit(types.SET_CONVERSATION_WATCHERS_UI_FLAG, { + commit(types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: false, }); } @@ -69,14 +69,14 @@ export const actions = { }; export const mutations = { - [types.SET_CONVERSATION_WATCHERS_UI_FLAG]($state, data) { + [types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG]($state, data) { $state.uiFlags = { ...$state.uiFlags, ...data, }; }, - [types.SET_CONVERSATION_WATCHERS]($state, { data, conversationId }) { + [types.SET_CONVERSATION_PARTICIPANTS]($state, { data, conversationId }) { Vue.set($state.records, conversationId, data); }, }; diff --git a/app/javascript/dashboard/store/modules/conversations/getters.js b/app/javascript/dashboard/store/modules/conversations/getters.js index 75d9aef44..e02fa7c40 100644 --- a/app/javascript/dashboard/store/modules/conversations/getters.js +++ b/app/javascript/dashboard/store/modules/conversations/getters.js @@ -91,6 +91,12 @@ const getters = { value => value.id === Number(conversationId) ); }, + getConversationParticipants: _state => { + return _state.conversationParticipants; + }, + getConversationLastSeen: _state => { + return _state.conversationLastSeen; + }, }; export default getters; diff --git a/app/javascript/dashboard/store/modules/conversations/index.js b/app/javascript/dashboard/store/modules/conversations/index.js index a8a2fdabe..03ac280f6 100644 --- a/app/javascript/dashboard/store/modules/conversations/index.js +++ b/app/javascript/dashboard/store/modules/conversations/index.js @@ -13,6 +13,8 @@ const state = { currentInbox: null, selectedChatId: null, appliedFilters: [], + conversationParticipants: [], + conversationLastSeen: null, }; // mutations diff --git a/app/javascript/dashboard/store/modules/specs/conversationWatchers/actions.spec.js b/app/javascript/dashboard/store/modules/specs/conversationWatchers/actions.spec.js index 115c505ce..25b28a5bb 100644 --- a/app/javascript/dashboard/store/modules/specs/conversationWatchers/actions.spec.js +++ b/app/javascript/dashboard/store/modules/specs/conversationWatchers/actions.spec.js @@ -12,12 +12,12 @@ describe('#actions', () => { axios.get.mockResolvedValue({ data: { id: 1 } }); await actions.show({ commit }, { conversationId: 1 }); expect(commit.mock.calls).toEqual([ - [types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isFetching: true }], + [types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: true }], [ - types.SET_CONVERSATION_WATCHERS, + types.SET_CONVERSATION_PARTICIPANTS, { conversationId: 1, data: { id: 1 } }, ], - [types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isFetching: false }], + [types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: false }], ]); }); it('sends correct actions if API is error', async () => { @@ -26,8 +26,8 @@ describe('#actions', () => { actions.show({ commit }, { conversationId: 1 }) ).rejects.toThrow(Error); expect(commit.mock.calls).toEqual([ - [types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isFetching: true }], - [types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isFetching: false }], + [types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: true }], + [types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isFetching: false }], ]); }); }); @@ -40,12 +40,12 @@ describe('#actions', () => { { conversationId: 2, userIds: [{ id: 2 }] } ); expect(commit.mock.calls).toEqual([ - [types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isUpdating: true }], + [types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: true }], [ - types.SET_CONVERSATION_WATCHERS, + types.SET_CONVERSATION_PARTICIPANTS, { conversationId: 2, data: [{ id: 2 }] }, ], - [types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isUpdating: false }], + [types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: false }], ]); }); it('sends correct actions if API is error', async () => { @@ -54,8 +54,8 @@ describe('#actions', () => { actions.update({ commit }, { conversationId: 1, content: 'hi' }) ).rejects.toThrow(Error); expect(commit.mock.calls).toEqual([ - [types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isUpdating: true }], - [types.SET_CONVERSATION_WATCHERS_UI_FLAG, { isUpdating: false }], + [types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: true }], + [types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG, { isUpdating: false }], ]); }); }); diff --git a/app/javascript/dashboard/store/modules/specs/conversationWatchers/mutations.spec.js b/app/javascript/dashboard/store/modules/specs/conversationWatchers/mutations.spec.js index 781e8eaa8..9dc44fbbf 100644 --- a/app/javascript/dashboard/store/modules/specs/conversationWatchers/mutations.spec.js +++ b/app/javascript/dashboard/store/modules/specs/conversationWatchers/mutations.spec.js @@ -2,13 +2,13 @@ import types from '../../../mutation-types'; import { mutations } from '../../conversationWatchers'; describe('#mutations', () => { - describe('#SET_CONVERSATION_WATCHERS', () => { + describe('#SET_CONVERSATION_PARTICIPANTS', () => { it('sets an individual record', () => { let state = { records: {}, }; - mutations[types.SET_CONVERSATION_WATCHERS](state, { + mutations[types.SET_CONVERSATION_PARTICIPANTS](state, { data: [], conversationId: 1, }); @@ -16,7 +16,7 @@ describe('#mutations', () => { }); }); - describe('#SET_CONVERSATION_WATCHERS_UI_FLAG', () => { + describe('#SET_CONVERSATION_PARTICIPANTS_UI_FLAG', () => { it('set ui flags', () => { let state = { uiFlags: { @@ -25,7 +25,7 @@ describe('#mutations', () => { }, }; - mutations[types.SET_CONVERSATION_WATCHERS_UI_FLAG](state, { + mutations[types.SET_CONVERSATION_PARTICIPANTS_UI_FLAG](state, { isFetching: false, }); expect(state.uiFlags).toEqual({ diff --git a/app/javascript/dashboard/store/mutation-types.js b/app/javascript/dashboard/store/mutation-types.js old mode 100755 new mode 100644 index c2d8b30f8..ceff83fab --- a/app/javascript/dashboard/store/mutation-types.js +++ b/app/javascript/dashboard/store/mutation-types.js @@ -21,6 +21,7 @@ export default { CLEAR_CONTACT_CONVERSATIONS: 'CLEAR_CONTACT_CONVERSATIONS', SET_CONVERSATION_FILTERS: 'SET_CONVERSATION_FILTERS', CLEAR_CONVERSATION_FILTERS: 'CLEAR_CONVERSATION_FILTERS', + SET_CONVERSATION_LAST_SEEN: 'SET_CONVERSATION_LAST_SEEN', SET_CURRENT_CHAT_WINDOW: 'SET_CURRENT_CHAT_WINDOW', CLEAR_CURRENT_CHAT_WINDOW: 'CLEAR_CURRENT_CHAT_WINDOW', @@ -260,6 +261,7 @@ export default { EDIT_MACRO: 'EDIT_MACRO', DELETE_MACRO: 'DELETE_MACRO', - SET_CONVERSATION_WATCHERS_UI_FLAG: 'SET_CONVERSATION_WATCHERS_UI_FLAG', - SET_CONVERSATION_WATCHERS: 'SET_CONVERSATION_WATCHERS', + SET_CONVERSATION_PARTICIPANTS_UI_FLAG: + 'SET_CONVERSATION_PARTICIPANTS_UI_FLAG', + SET_CONVERSATION_PARTICIPANTS: 'SET_CONVERSATION_PARTICIPANTS', }; diff --git a/app/javascript/shared/components/ChatForm.vue b/app/javascript/shared/components/ChatForm.vue index 347bf39d9..bf3d830eb 100644 --- a/app/javascript/shared/components/ChatForm.vue +++ b/app/javascript/shared/components/ChatForm.vue @@ -86,8 +86,8 @@