diff --git a/app/controllers/api/v1/accounts/conversations_controller.rb b/app/controllers/api/v1/accounts/conversations_controller.rb index 8753918fc..041ff8af2 100644 --- a/app/controllers/api/v1/accounts/conversations_controller.rb +++ b/app/controllers/api/v1/accounts/conversations_controller.rb @@ -124,6 +124,11 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro @conversation.save! end + def destroy + ::DeleteObjectJob.perform_later(@conversation, Current.user, request.ip) + head :ok + end + private def permitted_update_params diff --git a/app/javascript/dashboard/api/inbox/conversation.js b/app/javascript/dashboard/api/inbox/conversation.js index 1a87e6d96..0f539bfa9 100644 --- a/app/javascript/dashboard/api/inbox/conversation.js +++ b/app/javascript/dashboard/api/inbox/conversation.js @@ -137,6 +137,10 @@ class ConversationApi extends ApiClient { getInboxAssistant(conversationId) { return axios.get(`${this.url}/${conversationId}/inbox_assistant`); } + + delete(conversationId) { + return axios.delete(`${this.url}/${conversationId}`); + } } export default new ConversationApi(); diff --git a/app/javascript/dashboard/components/ChatList.vue b/app/javascript/dashboard/components/ChatList.vue index 089d9e74f..9d6340e4c 100644 --- a/app/javascript/dashboard/components/ChatList.vue +++ b/app/javascript/dashboard/components/ChatList.vue @@ -703,6 +703,15 @@ async function markAsRead(conversationId) { // Ignore error } } + +async function deleteConversation(conversationId) { + try { + await store.dispatch('deleteConversation', conversationId); + useAlert(t('CONVERSATION.SUCCESS_DELETE_CONVERSATION')); + } catch (error) { + useAlert(t('CONVERSATION.FAIL_DELETE_CONVERSATION')); + } +} async function onAssignTeam(team, conversationId = null) { try { await store.dispatch('assignTeam', { @@ -775,6 +784,7 @@ provide('markAsUnread', markAsUnread); provide('markAsRead', markAsRead); provide('assignPriority', assignPriority); provide('isConversationSelected', isConversationSelected); +provide('deleteConversation', deleteConversation); watch(activeTeam, () => resetAndFetchData()); diff --git a/app/javascript/dashboard/components/ConversationItem.vue b/app/javascript/dashboard/components/ConversationItem.vue index dcdf46e7e..a705dd067 100644 --- a/app/javascript/dashboard/components/ConversationItem.vue +++ b/app/javascript/dashboard/components/ConversationItem.vue @@ -16,6 +16,7 @@ export default { 'markAsRead', 'assignPriority', 'isConversationSelected', + 'deleteConversation', ], props: { source: { @@ -67,5 +68,6 @@ export default { @mark-as-unread="markAsUnread" @mark-as-read="markAsRead" @assign-priority="assignPriority" + @delete-conversation="deleteConversation" /> diff --git a/app/javascript/dashboard/components/widgets/conversation/ConversationCard.vue b/app/javascript/dashboard/components/widgets/conversation/ConversationCard.vue index 698690dad..4840b459f 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ConversationCard.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ConversationCard.vue @@ -78,6 +78,7 @@ export default { 'markAsRead', 'assignPriority', 'updateConversationStatus', + 'deleteConversation', ], data() { return { @@ -237,6 +238,10 @@ export default { this.$emit('assignPriority', priority, this.chat.id); this.closeContextMenu(); }, + async deleteConversation() { + this.$emit('deleteConversation', this.chat.id); + this.closeContextMenu(); + }, }, }; @@ -363,6 +368,7 @@ export default { @mark-as-unread="markAsUnread" @mark-as-read="markAsRead" @assign-priority="assignPriority" + @delete-conversation="deleteConversation" /> diff --git a/app/javascript/dashboard/components/widgets/conversation/contextMenu/Index.vue b/app/javascript/dashboard/components/widgets/conversation/contextMenu/Index.vue index fccff3457..cce6609aa 100644 --- a/app/javascript/dashboard/components/widgets/conversation/contextMenu/Index.vue +++ b/app/javascript/dashboard/components/widgets/conversation/contextMenu/Index.vue @@ -45,6 +45,7 @@ export default { 'assignAgent', 'assignTeam', 'assignLabel', + 'deleteConversation', ], data() { return { @@ -121,6 +122,11 @@ export default { icon: 'people-team-add', label: this.$t('CONVERSATION.CARD_CONTEXT_MENU.ASSIGN_TEAM'), }, + deleteOption: { + key: 'delete', + icon: 'delete', + label: this.$t('CONVERSATION.CARD_CONTEXT_MENU.DELETE'), + }, }; }, computed: { @@ -178,6 +184,9 @@ export default { assignPriority(priority) { this.$emit('assignPriority', priority); }, + deleteConversation() { + this.$emit('deleteConversation'); + }, show(key) { // If the conversation status is same as the action, then don't display the option // i.e.: Don't show an option to resolve if the conversation is already resolved. @@ -277,5 +286,11 @@ export default { @click.stop="$emit('assignTeam', team)" /> +
+ diff --git a/app/javascript/dashboard/i18n/locale/en/conversation.json b/app/javascript/dashboard/i18n/locale/en/conversation.json index 26ec6dc16..6cdf4f7aa 100644 --- a/app/javascript/dashboard/i18n/locale/en/conversation.json +++ b/app/javascript/dashboard/i18n/locale/en/conversation.json @@ -134,6 +134,7 @@ "ASSIGN_LABEL": "Assign label", "AGENTS_LOADING": "Loading agents...", "ASSIGN_TEAM": "Assign team", + "DELETE": "Delete conversation", "API": { "AGENT_ASSIGNMENT": { "SUCCESFUL": "Conversation id {conversationId} assigned to \"{agentName}\"", @@ -208,6 +209,8 @@ "ASSIGN_LABEL_SUCCESFUL": "Label assigned successfully", "ASSIGN_LABEL_FAILED": "Label assignment failed", "CHANGE_TEAM": "Conversation team changed", + "SUCCESS_DELETE_CONVERSATION": "Conversation deleted successfully", + "FAIL_DELETE_CONVERSATION": "Couldn't delete conversation! Try again", "FILE_SIZE_LIMIT": "File exceeds the {MAXIMUM_SUPPORTED_FILE_UPLOAD_SIZE} MB attachment limit", "MESSAGE_ERROR": "Unable to send this message, please try again later", "SENT_BY": "Sent by:", diff --git a/app/javascript/dashboard/store/modules/conversations/actions.js b/app/javascript/dashboard/store/modules/conversations/actions.js index 8296f25de..c6fc362e3 100644 --- a/app/javascript/dashboard/store/modules/conversations/actions.js +++ b/app/javascript/dashboard/store/modules/conversations/actions.js @@ -327,6 +327,15 @@ const actions = { } }, + deleteConversation: async ({ commit }, conversationId) => { + try { + await ConversationApi.delete(conversationId); + commit(types.DELETE_CONVERSATION, conversationId); + } catch (error) { + throw new Error(error); + } + }, + addConversation({ commit, state, dispatch, rootState }, conversation) { const { currentInbox, appliedFilters } = state; const { diff --git a/app/javascript/dashboard/store/modules/conversations/index.js b/app/javascript/dashboard/store/modules/conversations/index.js index fc6f10979..2ee6fd061 100644 --- a/app/javascript/dashboard/store/modules/conversations/index.js +++ b/app/javascript/dashboard/store/modules/conversations/index.js @@ -204,6 +204,12 @@ export const mutations = { _state.allConversations.push(conversation); }, + [types.DELETE_CONVERSATION](_state, conversationId) { + _state.allConversations = _state.allConversations.filter( + c => c.id !== conversationId + ); + }, + [types.UPDATE_CONVERSATION](_state, conversation) { const { allConversations } = _state; const index = allConversations.findIndex(c => c.id === conversation.id); diff --git a/app/javascript/dashboard/store/mutation-types.js b/app/javascript/dashboard/store/mutation-types.js index f3817c45a..a63fec2d1 100644 --- a/app/javascript/dashboard/store/mutation-types.js +++ b/app/javascript/dashboard/store/mutation-types.js @@ -56,6 +56,7 @@ export default { SET_ALL_ATTACHMENTS: 'SET_ALL_ATTACHMENTS', ADD_CONVERSATION_ATTACHMENTS: 'ADD_CONVERSATION_ATTACHMENTS', DELETE_CONVERSATION_ATTACHMENTS: 'DELETE_CONVERSATION_ATTACHMENTS', + DELETE_CONVERSATION: 'DELETE_CONVERSATION', SET_CONVERSATION_CAN_REPLY: 'SET_CONVERSATION_CAN_REPLY', diff --git a/config/routes.rb b/config/routes.rb index fbecd2d50..12d96c165 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -98,7 +98,7 @@ Rails.application.routes.draw do namespace :channels do resource :twilio_channel, only: [:create] end - resources :conversations, only: [:index, :create, :show, :update] do + resources :conversations, only: [:index, :create, :show, :update, :destroy] do collection do get :meta get :search