diff --git a/app/controllers/api/v1/accounts/inboxes_controller.rb b/app/controllers/api/v1/accounts/inboxes_controller.rb index 2621a4a33..d492b0d9e 100644 --- a/app/controllers/api/v1/accounts/inboxes_controller.rb +++ b/app/controllers/api/v1/accounts/inboxes_controller.rb @@ -15,6 +15,11 @@ class Api::V1::Accounts::InboxesController < Api::V1::Accounts::BaseController @campaigns = @inbox.campaigns end + def avatar + @inbox.avatar.attachment.destroy! if @inbox.avatar.attached? + head :ok + end + def create ActiveRecord::Base.transaction do channel = create_channel diff --git a/app/javascript/dashboard/api/inboxes.js b/app/javascript/dashboard/api/inboxes.js index b6d8ab860..1cf6ba113 100644 --- a/app/javascript/dashboard/api/inboxes.js +++ b/app/javascript/dashboard/api/inboxes.js @@ -13,6 +13,10 @@ class Inboxes extends ApiClient { getCampaigns(inboxId) { return axios.get(`${this.url}/${inboxId}/campaigns`); } + + deleteInboxAvatar(inboxId) { + return axios.delete(`${this.url}/${inboxId}/avatar`); + } } export default new Inboxes(); diff --git a/app/javascript/dashboard/api/specs/inboxes.spec.js b/app/javascript/dashboard/api/specs/inboxes.spec.js index 6c5cf38ea..b261bb930 100644 --- a/app/javascript/dashboard/api/specs/inboxes.spec.js +++ b/app/javascript/dashboard/api/specs/inboxes.spec.js @@ -27,5 +27,12 @@ describe('#InboxesAPI', () => { '/api/v1/inboxes/2/campaigns' ); }); + + it('#deleteInboxAvatar', () => { + inboxesAPI.deleteInboxAvatar(2); + expect(context.axiosMock.delete).toHaveBeenCalledWith( + '/api/v1/inboxes/2/avatar' + ); + }); }); }); diff --git a/app/javascript/dashboard/components/widgets/forms/AvatarUploader.vue b/app/javascript/dashboard/components/widgets/forms/AvatarUploader.vue index 9af6b4029..89ca4f56a 100644 --- a/app/javascript/dashboard/components/widgets/forms/AvatarUploader.vue +++ b/app/javascript/dashboard/components/widgets/forms/AvatarUploader.vue @@ -1,16 +1,31 @@ - - {{ label }} + + + {{ label }} + - - - + + {{ + this.$t('INBOX_MGMT.DELETE.AVATAR_DELETE_BUTTON_TEXT') + }} + + + + + + + + diff --git a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json index 3731e79a9..603ec58e9 100644 --- a/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json +++ b/app/javascript/dashboard/i18n/locale/en/inboxMgmt.json @@ -232,6 +232,7 @@ }, "DELETE": { "BUTTON_TEXT": "Delete", + "AVATAR_DELETE_BUTTON_TEXT": "Delete Avatar", "CONFIRM": { "TITLE": "Confirm Deletion", "MESSAGE": "Are you sure to delete ", @@ -241,7 +242,9 @@ }, "API": { "SUCCESS_MESSAGE": "Inbox deleted successfully", - "ERROR_MESSAGE": "Could not delete inbox. Please try again later." + "ERROR_MESSAGE": "Could not delete inbox. Please try again later.", + "AVATAR_SUCCESS_MESSAGE": "Inbox avatar deleted successfully", + "AVATAR_ERROR_MESSAGE": "Could not delete the inbox avatar. Please try again later." } }, "TABS": { diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue index b41c13a97..6357f67fd 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/Settings.vue @@ -22,7 +22,9 @@ { + try { + await InboxesAPI.deleteInboxAvatar(inboxId); + } catch (error) { + throw new Error(error); + } + }, }; export const mutations = { diff --git a/app/javascript/dashboard/store/modules/specs/inboxes/actions.spec.js b/app/javascript/dashboard/store/modules/specs/inboxes/actions.spec.js index c2d32976c..da3424267 100644 --- a/app/javascript/dashboard/store/modules/specs/inboxes/actions.spec.js +++ b/app/javascript/dashboard/store/modules/specs/inboxes/actions.spec.js @@ -128,4 +128,19 @@ describe('#actions', () => { ]); }); }); + + describe('#deleteInboxAvatar', () => { + it('sends correct actions if API is success', async () => { + axios.delete.mockResolvedValue(); + await expect( + actions.deleteInboxAvatar({}, inboxList[0].id) + ).resolves.toBe(); + }); + it('sends correct actions if API is error', async () => { + axios.delete.mockRejectedValue({ message: 'Incorrect header' }); + await expect( + actions.deleteInboxAvatar({}, inboxList[0].id) + ).rejects.toThrow(Error); + }); + }); }); diff --git a/app/policies/inbox_policy.rb b/app/policies/inbox_policy.rb index dd3aa9305..851cac7d0 100644 --- a/app/policies/inbox_policy.rb +++ b/app/policies/inbox_policy.rb @@ -53,4 +53,8 @@ class InboxPolicy < ApplicationPolicy def set_agent_bot? @account_user.administrator? end + + def avatar? + @account_user.administrator? + end end diff --git a/config/routes.rb b/config/routes.rb index a4a2f5459..d89332be4 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -102,6 +102,7 @@ Rails.application.routes.draw do get :campaigns, on: :member get :agent_bot, on: :member post :set_agent_bot, on: :member + delete :avatar, on: :member end resources :inbox_members, only: [:create, :show], param: :inbox_id resources :labels, only: [:index, :show, :create, :update, :destroy] diff --git a/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb b/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb index 1a5c31088..1b7262ba8 100644 --- a/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb +++ b/spec/controllers/api/v1/accounts/inboxes_controller_spec.rb @@ -113,6 +113,42 @@ RSpec.describe 'Inboxes API', type: :request do end end + describe 'DELETE /api/v1/accounts/{account.id}/inboxes/{inbox.id}/avatar' do + let(:inbox) { create(:inbox, account: account) } + + context 'when it is an unauthenticated user' do + it 'returns unauthorized' do + delete "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/avatar" + + expect(response).to have_http_status(:unauthorized) + end + end + + context 'when it is an authenticated user' do + before do + create(:inbox_member, user: agent, inbox: inbox) + inbox.avatar.attach(io: File.open(Rails.root.join('spec/assets/avatar.png')), filename: 'avatar.png', content_type: 'image/png') + end + + it 'delete inbox avatar for administrator user' do + delete "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/avatar", + headers: admin.create_new_auth_token, + as: :json + + expect { inbox.avatar.attachment.reload }.to raise_error(ActiveRecord::RecordNotFound) + expect(response).to have_http_status(:success) + end + + it 'returns unauthorized for agent user' do + delete "/api/v1/accounts/#{account.id}/inboxes/#{inbox.id}/avatar", + headers: agent.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:unauthorized) + end + end + end + describe 'DELETE /api/v1/accounts/{account.id}/inboxes/:id' do let(:inbox) { create(:inbox, account: account) }