feat: Ability to remove inbox avatar (#2885)

* Delete inbox avatar

1) New API endpoint added for deleting inbox avatar.
2) Delete avatar button in the inbox settings page.

Co-authored-by: Sojan Jose <sojan@pepalo.com>
Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
Aswin Dev P.S 2021-08-31 15:12:05 +05:30 committed by GitHub
parent fdcc322660
commit 1ff9939a80
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 143 additions and 12 deletions

View file

@ -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

View file

@ -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();

View file

@ -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'
);
});
});
});

View file

@ -1,7 +1,21 @@
<template>
<div>
<label>
<span v-if="label">{{ label }}</span>
</label>
<woot-thumbnail v-if="src" size="80px" :src="src" />
<div v-if="src && deleteAvatar" class="avatar-delete-btn">
<woot-button
color-scheme="alert"
variant="hollow"
size="tiny"
@click="onAvatarDelete"
>{{
this.$t('INBOX_MGMT.DELETE.AVATAR_DELETE_BUTTON_TEXT')
}}</woot-button
>
</div>
<label>
<input
id="file"
ref="file"
@ -11,6 +25,7 @@
/>
<slot></slot>
</label>
</div>
</template>
<script>
@ -24,6 +39,10 @@ export default {
type: String,
default: '',
},
deleteAvatar: {
type: Boolean,
default: false,
},
},
watch: {},
methods: {
@ -35,6 +54,17 @@ export default {
url: URL.createObjectURL(file),
});
},
onAvatarDelete() {
this.$refs.file.value = null;
this.$emit('onAvatarDelete');
},
},
};
</script>
<style lang="scss" scoped>
.avatar-delete-btn {
margin-top: var(--space-smaller);
margin-bottom: var(--space-smaller);
}
</style>

View file

@ -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": {

View file

@ -22,7 +22,9 @@
<woot-avatar-uploader
:label="$t('INBOX_MGMT.ADD.WEBSITE_CHANNEL.CHANNEL_AVATAR.LABEL')"
:src="avatarUrl"
deleteAvatar
@change="handleImageUpload"
@onAvatarDelete="handleAvatarDelete"
/>
<woot-input
v-model.trim="selectedInboxName"
@ -544,6 +546,23 @@ export default {
this.avatarFile = file;
this.avatarUrl = url;
},
async handleAvatarDelete() {
try {
await this.$store.dispatch(
'inboxes/deleteInboxAvatar',
this.currentInboxId
);
this.avatarFile = null;
this.avatarUrl = '';
this.showAlert(this.$t('INBOX_MGMT.DELETE.API.AVATAR_SUCCESS_MESSAGE'));
} catch (error) {
this.showAlert(
error.message
? error.message
: this.$t('INBOX_MGMT.DELETE.API.AVATAR_ERROR_MESSAGE')
);
}
},
},
validations: {
selectedAgents: {

View file

@ -173,6 +173,13 @@ export const actions = {
throw new Error(error.message);
}
},
deleteInboxAvatar: async (_, inboxId) => {
try {
await InboxesAPI.deleteInboxAvatar(inboxId);
} catch (error) {
throw new Error(error);
}
},
};
export const mutations = {

View file

@ -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);
});
});
});

View file

@ -53,4 +53,8 @@ class InboxPolicy < ApplicationPolicy
def set_agent_bot?
@account_user.administrator?
end
def avatar?
@account_user.administrator?
end
end

View file

@ -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]

View file

@ -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) }