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:
parent
fdcc322660
commit
1ff9939a80
11 changed files with 143 additions and 12 deletions
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -53,4 +53,8 @@ class InboxPolicy < ApplicationPolicy
|
|||
def set_agent_bot?
|
||||
@account_user.administrator?
|
||||
end
|
||||
|
||||
def avatar?
|
||||
@account_user.administrator?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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) }
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue