Add ability to remove profile picture on Profile Settings (#538)

* Add ability to remove profile picture on Profile Settings

* Fix lint

* Fix according to review
This commit is contained in:
Charles Bochet
2023-07-08 10:41:16 -07:00
committed by GitHub
parent e2822ed095
commit 36ace6cc03
22 changed files with 363 additions and 75 deletions

View File

@ -6,7 +6,7 @@ import { useRecoilValue } from 'recoil';
import { currentUserState } from '@/auth/states/currentUserState';
import { TextInput } from '@/ui/components/inputs/TextInput';
import { GET_CURRENT_USER } from '@/users/services';
import { GET_CURRENT_USER } from '@/users/queries';
import { useUpdateUserMutation } from '~/generated/graphql';
const StyledComboInputContainer = styled.div`

View File

@ -3,13 +3,21 @@ import { useRecoilState } from 'recoil';
import { currentUserState } from '@/auth/states/currentUserState';
import { ImageInput } from '@/ui/components/inputs/ImageInput';
import { GET_CURRENT_USER } from '@/users/services';
import { useUploadProfilePictureMutation } from '~/generated/graphql';
import { GET_CURRENT_USER } from '@/users/queries';
import { getImageAbsoluteURI } from '@/users/utils/getProfilePictureAbsoluteURI';
import {
useRemoveProfilePictureMutation,
useUploadProfilePictureMutation,
} from '~/generated/graphql';
export function PictureUploader() {
const [uploadPicture] = useUploadProfilePictureMutation();
const [removePicture] = useRemoveProfilePictureMutation();
const [currentUser] = useRecoilState(currentUserState);
async function onUpload(file: File) {
if (!file) {
return;
}
await uploadPicture({
variables: {
file,
@ -18,8 +26,22 @@ export function PictureUploader() {
});
}
const pictureUrl = currentUser?.avatarUrl
? `${process.env.REACT_APP_FILES_URL}/${currentUser?.avatarUrl}`
: null;
return <ImageInput picture={pictureUrl} onUpload={onUpload} />;
async function onRemove() {
await removePicture({
variables: {
where: {
id: currentUser?.id,
},
},
refetchQueries: [getOperationName(GET_CURRENT_USER) ?? ''],
});
}
return (
<ImageInput
picture={getImageAbsoluteURI(currentUser?.avatarUrl)}
onUpload={onUpload}
onRemove={onRemove}
/>
);
}

View File

@ -1,7 +0,0 @@
import { gql } from '@apollo/client';
export const UPDATE_PROFILE_PICTURE = gql`
mutation UploadProfilePicture($file: Upload!) {
uploadProfilePicture(file: $file)
}
`;

View File

@ -23,6 +23,7 @@ const Picture = styled.button<{ withPicture: boolean }>`
height: 66px;
justify-content: center;
overflow: hidden;
padding: 0;
transition: background 0.1s ease;
width: 66px;
@ -132,7 +133,7 @@ export function ImageInput({
onClick={onRemove}
variant="secondary"
title="Remove"
disabled
disabled={!picture || disabled}
fullWidth
/>
</ButtonContainer>

View File

@ -12,6 +12,7 @@ type OwnProps = {
};
export const StyledAvatar = styled.div<Omit<OwnProps, 'placeholder'>>`
align-items: center;
background-color: ${(props) =>
!isNonEmptyString(props.avatarUrl)
? props.theme.background.tertiary
@ -22,12 +23,12 @@ export const StyledAvatar = styled.div<Omit<OwnProps, 'placeholder'>>`
border-radius: ${(props) => (props.type === 'rounded' ? '50%' : '2px')};
color: ${({ theme }) => theme.font.color.primary};
display: flex;
flex-shrink: 0;
flex-shrink: 0;
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};
height: ${(props) => props.size}px;
height: ${(props) => props.size}px;
justify-content: center;
width: ${(props) => props.size}px;
`;

View File

@ -0,0 +1,28 @@
import { gql } from '@apollo/client';
export const UPDATE_USER = gql`
mutation UpdateUser($data: UserUpdateInput!, $where: UserWhereUniqueInput!) {
updateUser(data: $data, where: $where) {
id
email
displayName
firstName
lastName
avatarUrl
}
}
`;
export const UPDATE_PROFILE_PICTURE = gql`
mutation UploadProfilePicture($file: Upload!) {
uploadProfilePicture(file: $file)
}
`;
export const REMOVE_PROFILE_PICTURE = gql`
mutation RemoveProfilePicture($where: UserWhereUniqueInput!) {
updateUser(data: { avatarUrl: { set: null } }, where: $where) {
id
}
}
`;

View File

@ -1,14 +0,0 @@
import { gql } from '@apollo/client';
export const UPDATE_USER = gql`
mutation UpdateUser($data: UserUpdateInput!, $where: UserWhereUniqueInput!) {
updateUser(data: $data, where: $where) {
id
email
displayName
firstName
lastName
avatarUrl
}
}
`;

View File

@ -0,0 +1,5 @@
export function getImageAbsoluteURI(imageRelativePath?: string | null) {
return imageRelativePath
? `${process.env.REACT_APP_FILES_URL}/${imageRelativePath}`
: null;
}

View File

@ -1,6 +1,7 @@
import styled from '@emotion/styled';
import { Avatar } from '@/users/components/Avatar';
import { getImageAbsoluteURI } from '@/users/utils/getProfilePictureAbsoluteURI';
import { User } from '~/generated/graphql';
const StyledContainer = styled.div`
@ -47,7 +48,7 @@ export function WorkspaceMemberCard({ workspaceMember }: OwnProps) {
<StyledContainer>
<AvatarContainer>
<Avatar
avatarUrl={workspaceMember.user.avatarUrl}
avatarUrl={getImageAbsoluteURI(workspaceMember.user.avatarUrl)}
placeholder={workspaceMember.user.firstName || ''}
type="squared"
size={40}