feat: Ability to remove user profile picture (#3156)

Fixes #3107
This commit is contained in:
Santhosh C 2021-11-27 00:56:07 +05:30 committed by GitHub
parent add004a56e
commit b326da7d94
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 84 additions and 3 deletions

View file

@ -13,6 +13,11 @@ class Api::V1::ProfilesController < Api::BaseController
@user.update!(profile_params) @user.update!(profile_params)
end end
def avatar
@user.avatar.attachment.destroy! if @user.avatar.attached?
head :ok
end
def availability def availability
@user.account_users.find_by!(account_id: availability_params[:account_id]).update!(availability: availability_params[:availability]) @user.account_users.find_by!(account_id: availability_params[:account_id]).update!(availability: availability_params[:availability])
end end

View file

@ -166,4 +166,8 @@ export default {
profile: { ...availabilityData }, profile: { ...availabilityData },
}); });
}, },
deleteAvatar() {
return axios.delete(endPoints('deleteAvatar').url);
},
}; };

View file

@ -36,6 +36,10 @@ const endPoints = {
}, },
params: { omniauth_token: '' }, params: { omniauth_token: '' },
}, },
deleteAvatar: {
url: '/api/v1/profile/avatar',
},
}; };
export default page => { export default page => {

View file

@ -3,6 +3,9 @@
"LINK": "Profile Settings", "LINK": "Profile Settings",
"TITLE": "Profile Settings", "TITLE": "Profile Settings",
"BTN_TEXT": "Update Profile", "BTN_TEXT": "Update Profile",
"DELETE_AVATAR": "Delete Avatar",
"AVATAR_DELETE_SUCCESS": "Avatar has been deleted successfully",
"AVATAR_DELETE_FAILED": "There is an error while deleting avatar, please try again",
"UPDATE_SUCCESS": "Your profile has been updated successfully", "UPDATE_SUCCESS": "Your profile has been updated successfully",
"PASSWORD_UPDATE_SUCCESS": "Your password has been changed successfully", "PASSWORD_UPDATE_SUCCESS": "Your password has been changed successfully",
"AFTER_EMAIL_CHANGED": "Your profile has been updated successfully, please login again as your login credentials are changed", "AFTER_EMAIL_CHANGED": "Your profile has been updated successfully, please login again as your login credentials are changed",
@ -69,7 +72,11 @@
}, },
"AVAILABILITY": { "AVAILABILITY": {
"LABEL": "Availability", "LABEL": "Availability",
"STATUSES_LIST": ["Online", "Busy", "Offline"] "STATUSES_LIST": [
"Online",
"Busy",
"Offline"
]
}, },
"EMAIL": { "EMAIL": {
"LABEL": "Your email address", "LABEL": "Your email address",
@ -196,4 +203,4 @@
"FORWARD_SLASH_KEY": "/" "FORWARD_SLASH_KEY": "/"
} }
} }
} }

View file

@ -14,6 +14,17 @@
:src="avatarUrl" :src="avatarUrl"
@change="handleImageUpload" @change="handleImageUpload"
/> />
<div v-if="showDeleteButton" class="avatar-delete-btn">
<woot-button
type="button"
color-scheme="alert"
variant="hollow"
size="small"
@click="deleteAvatar"
>
{{ $t('PROFILE_SETTINGS.DELETE_AVATAR') }}
</woot-button>
</div>
<label :class="{ error: $v.name.$error }"> <label :class="{ error: $v.name.$error }">
{{ $t('PROFILE_SETTINGS.FORM.NAME.LABEL') }} {{ $t('PROFILE_SETTINGS.FORM.NAME.LABEL') }}
<input <input
@ -177,6 +188,19 @@ export default {
this.avatarFile = file; this.avatarFile = file;
this.avatarUrl = url; this.avatarUrl = url;
}, },
async deleteAvatar() {
try {
await this.$store.dispatch('deleteAvatar');
this.avatarUrl = '';
this.avatarFile = '';
this.showAlert(this.$t('PROFILE_SETTINGS.AVATAR_DELETE_SUCCESS'));
} catch (error) {
this.showAlert(this.$t('PROFILE_SETTINGS.AVATAR_DELETE_FAILED'));
}
},
showDeleteButton() {
return this.avatarUrl && !this.avatarUrl.includes('www.gravatar.com');
},
}, },
}; };
</script> </script>

View file

@ -121,6 +121,15 @@ export const actions = {
} }
}, },
deleteAvatar: async ({ commit }) => {
try {
await authAPI.deleteAvatar();
commit(types.default.SET_CURRENT_USER);
} catch (error) {
// Ignore error
}
},
updateUISettings: async ({ commit }, params) => { updateUISettings: async ({ commit }, params) => {
try { try {
commit(types.default.SET_CURRENT_USER_UI_SETTINGS, params); commit(types.default.SET_CURRENT_USER_UI_SETTINGS, params);

View file

@ -63,7 +63,7 @@ describe('#actions', () => {
}); });
await actions.updateAvailability( await actions.updateAvailability(
{ commit, dispatch }, { commit, dispatch },
{ availability: 'offline', account_id: 1 }, { availability: 'offline', account_id: 1 }
); );
expect(setUser).toHaveBeenCalledTimes(1); expect(setUser).toHaveBeenCalledTimes(1);
expect(commit.mock.calls).toEqual([[types.default.SET_CURRENT_USER]]); expect(commit.mock.calls).toEqual([[types.default.SET_CURRENT_USER]]);

View file

@ -166,10 +166,12 @@ Rails.application.routes.draw do
end end
resource :profile, only: [:show, :update] do resource :profile, only: [:show, :update] do
delete :avatar, on: :collection
member do member do
post :availability post :availability
end end
end end
resource :notification_subscriptions, only: [:create] resource :notification_subscriptions, only: [:create]
namespace :widget do namespace :widget do

View file

@ -102,6 +102,32 @@ RSpec.describe 'Profile API', type: :request do
end end
end end
describe 'DELETE /api/v1/profile/avatar' do
let(:agent) { create(:user, password: 'Test123!', account: account, role: :agent) }
context 'when it is an unauthenticated user' do
it 'returns unauthorized' do
delete '/api/v1/profile/avatar'
expect(response).to have_http_status(:unauthorized)
end
end
context 'when it is an authenticated user' do
before do
agent.avatar.attach(io: File.open(Rails.root.join('spec/assets/avatar.png')), filename: 'avatar.png', content_type: 'image/png')
end
it 'deletes the agent avatar' do
delete '/api/v1/profile/avatar',
headers: agent.create_new_auth_token,
as: :json
expect(response).to have_http_status(:success)
end
end
end
describe 'POST /api/v1/profile/availability' do describe 'POST /api/v1/profile/availability' do
context 'when it is an unauthenticated user' do context 'when it is an unauthenticated user' do
it 'returns unauthorized' do it 'returns unauthorized' do