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:
@ -3037,13 +3037,6 @@ export type SearchCompanyQueryVariables = Exact<{
|
|||||||
|
|
||||||
export type SearchCompanyQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> };
|
export type SearchCompanyQuery = { __typename?: 'Query', searchResults: Array<{ __typename?: 'Company', id: string, name: string, domainName: string }> };
|
||||||
|
|
||||||
export type UploadProfilePictureMutationVariables = Exact<{
|
|
||||||
file: Scalars['Upload'];
|
|
||||||
}>;
|
|
||||||
|
|
||||||
|
|
||||||
export type UploadProfilePictureMutation = { __typename?: 'Mutation', uploadProfilePicture: string };
|
|
||||||
|
|
||||||
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
export type GetCurrentUserQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
@ -3062,6 +3055,20 @@ export type UpdateUserMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type UpdateUserMutation = { __typename?: 'Mutation', updateUser: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } };
|
export type UpdateUserMutation = { __typename?: 'Mutation', updateUser: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } };
|
||||||
|
|
||||||
|
export type UploadProfilePictureMutationVariables = Exact<{
|
||||||
|
file: Scalars['Upload'];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type UploadProfilePictureMutation = { __typename?: 'Mutation', uploadProfilePicture: string };
|
||||||
|
|
||||||
|
export type RemoveProfilePictureMutationVariables = Exact<{
|
||||||
|
where: UserWhereUniqueInput;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type RemoveProfilePictureMutation = { __typename?: 'Mutation', updateUser: { __typename?: 'User', id: string } };
|
||||||
|
|
||||||
export type GetCurrentWorkspaceQueryVariables = Exact<{ [key: string]: never; }>;
|
export type GetCurrentWorkspaceQueryVariables = Exact<{ [key: string]: never; }>;
|
||||||
|
|
||||||
|
|
||||||
@ -4358,37 +4365,6 @@ export function useSearchCompanyLazyQuery(baseOptions?: Apollo.LazyQueryHookOpti
|
|||||||
export type SearchCompanyQueryHookResult = ReturnType<typeof useSearchCompanyQuery>;
|
export type SearchCompanyQueryHookResult = ReturnType<typeof useSearchCompanyQuery>;
|
||||||
export type SearchCompanyLazyQueryHookResult = ReturnType<typeof useSearchCompanyLazyQuery>;
|
export type SearchCompanyLazyQueryHookResult = ReturnType<typeof useSearchCompanyLazyQuery>;
|
||||||
export type SearchCompanyQueryResult = Apollo.QueryResult<SearchCompanyQuery, SearchCompanyQueryVariables>;
|
export type SearchCompanyQueryResult = Apollo.QueryResult<SearchCompanyQuery, SearchCompanyQueryVariables>;
|
||||||
export const UploadProfilePictureDocument = gql`
|
|
||||||
mutation UploadProfilePicture($file: Upload!) {
|
|
||||||
uploadProfilePicture(file: $file)
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
export type UploadProfilePictureMutationFn = Apollo.MutationFunction<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* __useUploadProfilePictureMutation__
|
|
||||||
*
|
|
||||||
* To run a mutation, you first call `useUploadProfilePictureMutation` within a React component and pass it any options that fit your needs.
|
|
||||||
* When your component renders, `useUploadProfilePictureMutation` returns a tuple that includes:
|
|
||||||
* - A mutate function that you can call at any time to execute the mutation
|
|
||||||
* - An object with fields that represent the current status of the mutation's execution
|
|
||||||
*
|
|
||||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
* const [uploadProfilePictureMutation, { data, loading, error }] = useUploadProfilePictureMutation({
|
|
||||||
* variables: {
|
|
||||||
* file: // value for 'file'
|
|
||||||
* },
|
|
||||||
* });
|
|
||||||
*/
|
|
||||||
export function useUploadProfilePictureMutation(baseOptions?: Apollo.MutationHookOptions<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>) {
|
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
|
||||||
return Apollo.useMutation<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>(UploadProfilePictureDocument, options);
|
|
||||||
}
|
|
||||||
export type UploadProfilePictureMutationHookResult = ReturnType<typeof useUploadProfilePictureMutation>;
|
|
||||||
export type UploadProfilePictureMutationResult = Apollo.MutationResult<UploadProfilePictureMutation>;
|
|
||||||
export type UploadProfilePictureMutationOptions = Apollo.BaseMutationOptions<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>;
|
|
||||||
export const GetCurrentUserDocument = gql`
|
export const GetCurrentUserDocument = gql`
|
||||||
query GetCurrentUser {
|
query GetCurrentUser {
|
||||||
currentUser {
|
currentUser {
|
||||||
@ -4514,6 +4490,70 @@ export function useUpdateUserMutation(baseOptions?: Apollo.MutationHookOptions<U
|
|||||||
export type UpdateUserMutationHookResult = ReturnType<typeof useUpdateUserMutation>;
|
export type UpdateUserMutationHookResult = ReturnType<typeof useUpdateUserMutation>;
|
||||||
export type UpdateUserMutationResult = Apollo.MutationResult<UpdateUserMutation>;
|
export type UpdateUserMutationResult = Apollo.MutationResult<UpdateUserMutation>;
|
||||||
export type UpdateUserMutationOptions = Apollo.BaseMutationOptions<UpdateUserMutation, UpdateUserMutationVariables>;
|
export type UpdateUserMutationOptions = Apollo.BaseMutationOptions<UpdateUserMutation, UpdateUserMutationVariables>;
|
||||||
|
export const UploadProfilePictureDocument = gql`
|
||||||
|
mutation UploadProfilePicture($file: Upload!) {
|
||||||
|
uploadProfilePicture(file: $file)
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type UploadProfilePictureMutationFn = Apollo.MutationFunction<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useUploadProfilePictureMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useUploadProfilePictureMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useUploadProfilePictureMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [uploadProfilePictureMutation, { data, loading, error }] = useUploadProfilePictureMutation({
|
||||||
|
* variables: {
|
||||||
|
* file: // value for 'file'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useUploadProfilePictureMutation(baseOptions?: Apollo.MutationHookOptions<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useMutation<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>(UploadProfilePictureDocument, options);
|
||||||
|
}
|
||||||
|
export type UploadProfilePictureMutationHookResult = ReturnType<typeof useUploadProfilePictureMutation>;
|
||||||
|
export type UploadProfilePictureMutationResult = Apollo.MutationResult<UploadProfilePictureMutation>;
|
||||||
|
export type UploadProfilePictureMutationOptions = Apollo.BaseMutationOptions<UploadProfilePictureMutation, UploadProfilePictureMutationVariables>;
|
||||||
|
export const RemoveProfilePictureDocument = gql`
|
||||||
|
mutation RemoveProfilePicture($where: UserWhereUniqueInput!) {
|
||||||
|
updateUser(data: {avatarUrl: {set: null}}, where: $where) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type RemoveProfilePictureMutationFn = Apollo.MutationFunction<RemoveProfilePictureMutation, RemoveProfilePictureMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useRemoveProfilePictureMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useRemoveProfilePictureMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useRemoveProfilePictureMutation` returns a tuple that includes:
|
||||||
|
* - A mutate function that you can call at any time to execute the mutation
|
||||||
|
* - An object with fields that represent the current status of the mutation's execution
|
||||||
|
*
|
||||||
|
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const [removeProfilePictureMutation, { data, loading, error }] = useRemoveProfilePictureMutation({
|
||||||
|
* variables: {
|
||||||
|
* where: // value for 'where'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useRemoveProfilePictureMutation(baseOptions?: Apollo.MutationHookOptions<RemoveProfilePictureMutation, RemoveProfilePictureMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useMutation<RemoveProfilePictureMutation, RemoveProfilePictureMutationVariables>(RemoveProfilePictureDocument, options);
|
||||||
|
}
|
||||||
|
export type RemoveProfilePictureMutationHookResult = ReturnType<typeof useRemoveProfilePictureMutation>;
|
||||||
|
export type RemoveProfilePictureMutationResult = Apollo.MutationResult<RemoveProfilePictureMutation>;
|
||||||
|
export type RemoveProfilePictureMutationOptions = Apollo.BaseMutationOptions<RemoveProfilePictureMutation, RemoveProfilePictureMutationVariables>;
|
||||||
export const GetCurrentWorkspaceDocument = gql`
|
export const GetCurrentWorkspaceDocument = gql`
|
||||||
query GetCurrentWorkspace {
|
query GetCurrentWorkspace {
|
||||||
currentWorkspace {
|
currentWorkspace {
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { useRecoilValue } from 'recoil';
|
|||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
import { TextInput } from '@/ui/components/inputs/TextInput';
|
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';
|
import { useUpdateUserMutation } from '~/generated/graphql';
|
||||||
|
|
||||||
const StyledComboInputContainer = styled.div`
|
const StyledComboInputContainer = styled.div`
|
||||||
|
|||||||
@ -3,13 +3,21 @@ import { useRecoilState } from 'recoil';
|
|||||||
|
|
||||||
import { currentUserState } from '@/auth/states/currentUserState';
|
import { currentUserState } from '@/auth/states/currentUserState';
|
||||||
import { ImageInput } from '@/ui/components/inputs/ImageInput';
|
import { ImageInput } from '@/ui/components/inputs/ImageInput';
|
||||||
import { GET_CURRENT_USER } from '@/users/services';
|
import { GET_CURRENT_USER } from '@/users/queries';
|
||||||
import { useUploadProfilePictureMutation } from '~/generated/graphql';
|
import { getImageAbsoluteURI } from '@/users/utils/getProfilePictureAbsoluteURI';
|
||||||
|
import {
|
||||||
|
useRemoveProfilePictureMutation,
|
||||||
|
useUploadProfilePictureMutation,
|
||||||
|
} from '~/generated/graphql';
|
||||||
|
|
||||||
export function PictureUploader() {
|
export function PictureUploader() {
|
||||||
const [uploadPicture] = useUploadProfilePictureMutation();
|
const [uploadPicture] = useUploadProfilePictureMutation();
|
||||||
|
const [removePicture] = useRemoveProfilePictureMutation();
|
||||||
const [currentUser] = useRecoilState(currentUserState);
|
const [currentUser] = useRecoilState(currentUserState);
|
||||||
async function onUpload(file: File) {
|
async function onUpload(file: File) {
|
||||||
|
if (!file) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
await uploadPicture({
|
await uploadPicture({
|
||||||
variables: {
|
variables: {
|
||||||
file,
|
file,
|
||||||
@ -18,8 +26,22 @@ export function PictureUploader() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const pictureUrl = currentUser?.avatarUrl
|
async function onRemove() {
|
||||||
? `${process.env.REACT_APP_FILES_URL}/${currentUser?.avatarUrl}`
|
await removePicture({
|
||||||
: null;
|
variables: {
|
||||||
return <ImageInput picture={pictureUrl} onUpload={onUpload} />;
|
where: {
|
||||||
|
id: currentUser?.id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
refetchQueries: [getOperationName(GET_CURRENT_USER) ?? ''],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ImageInput
|
||||||
|
picture={getImageAbsoluteURI(currentUser?.avatarUrl)}
|
||||||
|
onUpload={onUpload}
|
||||||
|
onRemove={onRemove}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +0,0 @@
|
|||||||
import { gql } from '@apollo/client';
|
|
||||||
|
|
||||||
export const UPDATE_PROFILE_PICTURE = gql`
|
|
||||||
mutation UploadProfilePicture($file: Upload!) {
|
|
||||||
uploadProfilePicture(file: $file)
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
@ -23,6 +23,7 @@ const Picture = styled.button<{ withPicture: boolean }>`
|
|||||||
height: 66px;
|
height: 66px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
padding: 0;
|
||||||
transition: background 0.1s ease;
|
transition: background 0.1s ease;
|
||||||
|
|
||||||
width: 66px;
|
width: 66px;
|
||||||
@ -132,7 +133,7 @@ export function ImageInput({
|
|||||||
onClick={onRemove}
|
onClick={onRemove}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
title="Remove"
|
title="Remove"
|
||||||
disabled
|
disabled={!picture || disabled}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
</ButtonContainer>
|
</ButtonContainer>
|
||||||
|
|||||||
@ -12,6 +12,7 @@ type OwnProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const StyledAvatar = styled.div<Omit<OwnProps, 'placeholder'>>`
|
export const StyledAvatar = styled.div<Omit<OwnProps, 'placeholder'>>`
|
||||||
|
align-items: center;
|
||||||
background-color: ${(props) =>
|
background-color: ${(props) =>
|
||||||
!isNonEmptyString(props.avatarUrl)
|
!isNonEmptyString(props.avatarUrl)
|
||||||
? props.theme.background.tertiary
|
? props.theme.background.tertiary
|
||||||
@ -22,12 +23,12 @@ export const StyledAvatar = styled.div<Omit<OwnProps, 'placeholder'>>`
|
|||||||
border-radius: ${(props) => (props.type === 'rounded' ? '50%' : '2px')};
|
border-radius: ${(props) => (props.type === 'rounded' ? '50%' : '2px')};
|
||||||
color: ${({ theme }) => theme.font.color.primary};
|
color: ${({ theme }) => theme.font.color.primary};
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-shrink: 0;
|
|
||||||
|
|
||||||
|
flex-shrink: 0;
|
||||||
font-size: ${({ theme }) => theme.font.size.sm};
|
font-size: ${({ theme }) => theme.font.size.sm};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||||
height: ${(props) => props.size}px;
|
|
||||||
|
|
||||||
|
height: ${(props) => props.size}px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: ${(props) => props.size}px;
|
width: ${(props) => props.size}px;
|
||||||
`;
|
`;
|
||||||
|
|||||||
28
front/src/modules/users/queries/update.ts
Normal file
28
front/src/modules/users/queries/update.ts
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
export function getImageAbsoluteURI(imageRelativePath?: string | null) {
|
||||||
|
return imageRelativePath
|
||||||
|
? `${process.env.REACT_APP_FILES_URL}/${imageRelativePath}`
|
||||||
|
: null;
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { Avatar } from '@/users/components/Avatar';
|
import { Avatar } from '@/users/components/Avatar';
|
||||||
|
import { getImageAbsoluteURI } from '@/users/utils/getProfilePictureAbsoluteURI';
|
||||||
import { User } from '~/generated/graphql';
|
import { User } from '~/generated/graphql';
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
const StyledContainer = styled.div`
|
||||||
@ -47,7 +48,7 @@ export function WorkspaceMemberCard({ workspaceMember }: OwnProps) {
|
|||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
<AvatarContainer>
|
<AvatarContainer>
|
||||||
<Avatar
|
<Avatar
|
||||||
avatarUrl={workspaceMember.user.avatarUrl}
|
avatarUrl={getImageAbsoluteURI(workspaceMember.user.avatarUrl)}
|
||||||
placeholder={workspaceMember.user.firstName || ''}
|
placeholder={workspaceMember.user.firstName || ''}
|
||||||
type="squared"
|
type="squared"
|
||||||
size={40}
|
size={40}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import { MainButton } from '@/ui/components/buttons/MainButton';
|
|||||||
import { ImageInput } from '@/ui/components/inputs/ImageInput';
|
import { ImageInput } from '@/ui/components/inputs/ImageInput';
|
||||||
import { TextInput } from '@/ui/components/inputs/TextInput';
|
import { TextInput } from '@/ui/components/inputs/TextInput';
|
||||||
import { SubSectionTitle } from '@/ui/components/section-titles/SubSectionTitle';
|
import { SubSectionTitle } from '@/ui/components/section-titles/SubSectionTitle';
|
||||||
import { GET_CURRENT_USER } from '@/users/services';
|
import { GET_CURRENT_USER } from '@/users/queries';
|
||||||
import { useUpdateUserMutation } from '~/generated/graphql';
|
import { useUpdateUserMutation } from '~/generated/graphql';
|
||||||
|
|
||||||
const StyledContentContainer = styled.div`
|
const StyledContentContainer = styled.div`
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { MainButton } from '@/ui/components/buttons/MainButton';
|
|||||||
import { ImageInput } from '@/ui/components/inputs/ImageInput';
|
import { ImageInput } from '@/ui/components/inputs/ImageInput';
|
||||||
import { TextInput } from '@/ui/components/inputs/TextInput';
|
import { TextInput } from '@/ui/components/inputs/TextInput';
|
||||||
import { SubSectionTitle } from '@/ui/components/section-titles/SubSectionTitle';
|
import { SubSectionTitle } from '@/ui/components/section-titles/SubSectionTitle';
|
||||||
import { GET_CURRENT_USER } from '@/users/services';
|
import { GET_CURRENT_USER } from '@/users/queries';
|
||||||
import { useUpdateWorkspaceMutation } from '~/generated/graphql';
|
import { useUpdateWorkspaceMutation } from '~/generated/graphql';
|
||||||
|
|
||||||
const StyledContentContainer = styled.div`
|
const StyledContentContainer = styled.div`
|
||||||
|
|||||||
31
front/src/pages/auth/__stories__/CreateProfile.stories.tsx
Normal file
31
front/src/pages/auth/__stories__/CreateProfile.stories.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
import { AuthModal } from '@/auth/components/ui/Modal';
|
||||||
|
import { AuthLayout } from '@/ui/layout/AuthLayout';
|
||||||
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
|
import { getRenderWrapperForPage } from '~/testing/renderWrappers';
|
||||||
|
|
||||||
|
import { CreateProfile } from '../CreateProfile';
|
||||||
|
|
||||||
|
const meta: Meta<typeof CreateProfile> = {
|
||||||
|
title: 'Pages/Auth/CreateProfile',
|
||||||
|
component: CreateProfile,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
export type Story = StoryObj<typeof CreateProfile>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
render: getRenderWrapperForPage(
|
||||||
|
<AuthLayout>
|
||||||
|
<AuthModal>
|
||||||
|
<CreateProfile />
|
||||||
|
</AuthModal>
|
||||||
|
</AuthLayout>,
|
||||||
|
'/auth/create-profile',
|
||||||
|
),
|
||||||
|
parameters: {
|
||||||
|
msw: graphqlMocks,
|
||||||
|
},
|
||||||
|
};
|
||||||
31
front/src/pages/auth/__stories__/CreateWorkspace.stories.tsx
Normal file
31
front/src/pages/auth/__stories__/CreateWorkspace.stories.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
import { AuthModal } from '@/auth/components/ui/Modal';
|
||||||
|
import { AuthLayout } from '@/ui/layout/AuthLayout';
|
||||||
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
|
import { getRenderWrapperForPage } from '~/testing/renderWrappers';
|
||||||
|
|
||||||
|
import { CreateWorkspace } from '../CreateWorkspace';
|
||||||
|
|
||||||
|
const meta: Meta<typeof CreateWorkspace> = {
|
||||||
|
title: 'Pages/Auth/CreateWorkspace',
|
||||||
|
component: CreateWorkspace,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
export type Story = StoryObj<typeof CreateWorkspace>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
render: getRenderWrapperForPage(
|
||||||
|
<AuthLayout>
|
||||||
|
<AuthModal>
|
||||||
|
<CreateWorkspace />
|
||||||
|
</AuthModal>
|
||||||
|
</AuthLayout>,
|
||||||
|
'/auth/create-workspace',
|
||||||
|
),
|
||||||
|
parameters: {
|
||||||
|
msw: graphqlMocks,
|
||||||
|
},
|
||||||
|
};
|
||||||
11
front/src/pages/opportunities/__stories__/Opportunities.mdx
Normal file
11
front/src/pages/opportunities/__stories__/Opportunities.mdx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{ /* Opportunities.mdx */ }
|
||||||
|
|
||||||
|
import { Canvas, Meta } from '@storybook/blocks';
|
||||||
|
|
||||||
|
import * as Opportunities from './Opportunities.stories';
|
||||||
|
|
||||||
|
<Meta of={Opportunities} />
|
||||||
|
|
||||||
|
# Opportunities View
|
||||||
|
|
||||||
|
<Canvas of={Opportunities.Default} />
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||||
|
import { getRenderWrapperForPage } from '~/testing/renderWrappers';
|
||||||
|
|
||||||
|
import { Opportunities } from '../Opportunities';
|
||||||
|
|
||||||
|
const meta: Meta<typeof Opportunities> = {
|
||||||
|
title: 'Pages/Opportunities',
|
||||||
|
component: Opportunities,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
export type Story = StoryObj<typeof Opportunities>;
|
||||||
|
|
||||||
|
export const Default: Story = {
|
||||||
|
render: getRenderWrapperForPage(<Opportunities />, '/opportunities'),
|
||||||
|
parameters: {
|
||||||
|
msw: graphqlMocks,
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -77,7 +77,7 @@ export const CompanyName: Story = {
|
|||||||
delay: 200,
|
delay: 200,
|
||||||
});
|
});
|
||||||
|
|
||||||
await sleep(1000);
|
await sleep(500);
|
||||||
|
|
||||||
const qontoChip = canvas
|
const qontoChip = canvas
|
||||||
.getAllByTestId('dropdown-menu-item')
|
.getAllByTestId('dropdown-menu-item')
|
||||||
|
|||||||
@ -197,12 +197,14 @@ export const EditRelation: Story = {
|
|||||||
let secondRowCompanyCell = await canvas.findByText(
|
let secondRowCompanyCell = await canvas.findByText(
|
||||||
mockedPeopleData[1].company.name,
|
mockedPeopleData[1].company.name,
|
||||||
);
|
);
|
||||||
|
await sleep(25);
|
||||||
|
|
||||||
await userEvent.click(secondRowCompanyCell);
|
await userEvent.click(secondRowCompanyCell);
|
||||||
|
|
||||||
secondRowCompanyCell = await canvas.findByText(
|
secondRowCompanyCell = await canvas.findByText(
|
||||||
mockedPeopleData[1].company.name,
|
mockedPeopleData[1].company.name,
|
||||||
);
|
);
|
||||||
|
await sleep(25);
|
||||||
|
|
||||||
await userEvent.click(secondRowCompanyCell);
|
await userEvent.click(secondRowCompanyCell);
|
||||||
|
|
||||||
@ -240,11 +242,13 @@ export const SelectRelationWithKeys: Story = {
|
|||||||
let firstRowCompanyCell = await canvas.findByText(
|
let firstRowCompanyCell = await canvas.findByText(
|
||||||
mockedPeopleData[0].company.name,
|
mockedPeopleData[0].company.name,
|
||||||
);
|
);
|
||||||
|
await sleep(25);
|
||||||
|
|
||||||
await userEvent.click(firstRowCompanyCell);
|
await userEvent.click(firstRowCompanyCell);
|
||||||
firstRowCompanyCell = await canvas.findByText(
|
firstRowCompanyCell = await canvas.findByText(
|
||||||
mockedPeopleData[0].company.name,
|
mockedPeopleData[0].company.name,
|
||||||
);
|
);
|
||||||
|
await sleep(25);
|
||||||
await userEvent.click(firstRowCompanyCell);
|
await userEvent.click(firstRowCompanyCell);
|
||||||
|
|
||||||
const relationInput = await canvas.findByPlaceholderText('Search');
|
const relationInput = await canvas.findByPlaceholderText('Search');
|
||||||
|
|||||||
@ -2,13 +2,15 @@ import { getOperationName } from '@apollo/client/utilities';
|
|||||||
import { graphql } from 'msw';
|
import { graphql } from 'msw';
|
||||||
|
|
||||||
import { CREATE_EVENT } from '@/analytics/services';
|
import { CREATE_EVENT } from '@/analytics/services';
|
||||||
|
import { GET_CLIENT_CONFIG } from '@/client-config/queries';
|
||||||
import { GET_COMPANIES } from '@/companies/services';
|
import { GET_COMPANIES } from '@/companies/services';
|
||||||
import { GET_PEOPLE, UPDATE_PERSON } from '@/people/services';
|
import { GET_PEOPLE, UPDATE_PERSON } from '@/people/services';
|
||||||
|
import { GET_PIPELINES } from '@/pipeline-progress/queries';
|
||||||
import {
|
import {
|
||||||
SEARCH_COMPANY_QUERY,
|
SEARCH_COMPANY_QUERY,
|
||||||
SEARCH_USER_QUERY,
|
SEARCH_USER_QUERY,
|
||||||
} from '@/search/services/search';
|
} from '@/search/services/search';
|
||||||
import { GET_CURRENT_USER } from '@/users/services';
|
import { GET_CURRENT_USER } from '@/users/queries';
|
||||||
import {
|
import {
|
||||||
GetCompaniesQuery,
|
GetCompaniesQuery,
|
||||||
GetPeopleQuery,
|
GetPeopleQuery,
|
||||||
@ -18,6 +20,7 @@ import {
|
|||||||
|
|
||||||
import { mockedCompaniesData } from './mock-data/companies';
|
import { mockedCompaniesData } from './mock-data/companies';
|
||||||
import { mockedPeopleData } from './mock-data/people';
|
import { mockedPeopleData } from './mock-data/people';
|
||||||
|
import { mockedPipelinesData } from './mock-data/pipelines';
|
||||||
import { mockedUsersData } from './mock-data/users';
|
import { mockedUsersData } from './mock-data/users';
|
||||||
import { filterAndSortData, updateOneFromData } from './mock-data';
|
import { filterAndSortData, updateOneFromData } from './mock-data';
|
||||||
|
|
||||||
@ -103,6 +106,13 @@ export const graphqlMocks = [
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
graphql.query(getOperationName(GET_PIPELINES) ?? '', (req, res, ctx) => {
|
||||||
|
return res(
|
||||||
|
ctx.data({
|
||||||
|
findManyPipeline: mockedPipelinesData,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}),
|
||||||
graphql.mutation(getOperationName(CREATE_EVENT) ?? '', (req, res, ctx) => {
|
graphql.mutation(getOperationName(CREATE_EVENT) ?? '', (req, res, ctx) => {
|
||||||
return res(
|
return res(
|
||||||
ctx.data({
|
ctx.data({
|
||||||
@ -110,4 +120,16 @@ export const graphqlMocks = [
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
|
graphql.query(getOperationName(GET_CLIENT_CONFIG) ?? '', (req, res, ctx) => {
|
||||||
|
return res(
|
||||||
|
ctx.data({
|
||||||
|
clientConfig: {
|
||||||
|
demoMode: true,
|
||||||
|
debugMode: false,
|
||||||
|
authProviders: { google: true, password: true, magicLink: false },
|
||||||
|
telemetry: { enabled: false, anonymizationEnabled: true },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|||||||
90
front/src/testing/mock-data/pipelines.ts
Normal file
90
front/src/testing/mock-data/pipelines.ts
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import {
|
||||||
|
Pipeline,
|
||||||
|
PipelineProgress,
|
||||||
|
PipelineProgressableType,
|
||||||
|
PipelineStage,
|
||||||
|
} from '../../generated/graphql';
|
||||||
|
|
||||||
|
type MockedPipeline = Pick<
|
||||||
|
Pipeline,
|
||||||
|
'id' | 'name' | 'pipelineProgressableType' | '__typename'
|
||||||
|
> & {
|
||||||
|
pipelineStages: Array<
|
||||||
|
Pick<PipelineStage, 'id' | 'name' | 'color' | '__typename'> & {
|
||||||
|
pipelineProgresses: Array<
|
||||||
|
Pick<
|
||||||
|
PipelineProgress,
|
||||||
|
| 'id'
|
||||||
|
| 'progressableType'
|
||||||
|
| 'progressableId'
|
||||||
|
| 'amount'
|
||||||
|
| 'closeDate'
|
||||||
|
| '__typename'
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const mockedPipelinesData: Array<MockedPipeline> = [
|
||||||
|
{
|
||||||
|
id: 'fe256b39-3ec3-4fe3-8997-b75aa0bfb400',
|
||||||
|
name: 'Sales pipeline',
|
||||||
|
pipelineProgressableType: PipelineProgressableType.Company,
|
||||||
|
pipelineStages: [
|
||||||
|
{
|
||||||
|
id: 'fe256b39-3ec3-4fe3-8998-b76aa0bfb600',
|
||||||
|
name: 'New',
|
||||||
|
color: '#B76796',
|
||||||
|
pipelineProgresses: [
|
||||||
|
{
|
||||||
|
id: 'fe256b39-3ec3-4fe7-8998-b76aa0bfb600',
|
||||||
|
progressableType: PipelineProgressableType.Company,
|
||||||
|
progressableId: '89bb825c-171e-4bcc-9cf7-43448d6fb278',
|
||||||
|
amount: null,
|
||||||
|
closeDate: null,
|
||||||
|
__typename: 'PipelineProgress',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4a886c90-f4f2-4984-8222-882ebbb905d6',
|
||||||
|
progressableType: PipelineProgressableType.Company,
|
||||||
|
progressableId: 'b396e6b9-dc5c-4643-bcff-61b6cf7523ae',
|
||||||
|
amount: null,
|
||||||
|
closeDate: null,
|
||||||
|
__typename: 'PipelineProgress',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
__typename: 'PipelineStage',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'fe256b39-3ec3-4fe4-8998-b76aa0bfb600',
|
||||||
|
name: 'Screening',
|
||||||
|
color: '#CB912F',
|
||||||
|
pipelineProgresses: [],
|
||||||
|
__typename: 'PipelineStage',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'fe256b39-3ec3-4fe5-8998-b76aa0bfb600',
|
||||||
|
name: 'Meeting',
|
||||||
|
color: '#9065B0',
|
||||||
|
pipelineProgresses: [],
|
||||||
|
__typename: 'PipelineStage',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'fe256b39-3ec3-4fe6-8998-b76aa0bfb600',
|
||||||
|
name: 'Proposal',
|
||||||
|
color: '#337EA9',
|
||||||
|
pipelineProgresses: [],
|
||||||
|
__typename: 'PipelineStage',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'fe256b39-3ec3-4fe7-8998-b76aa0bfb600',
|
||||||
|
name: 'Customer',
|
||||||
|
color: '#079039',
|
||||||
|
pipelineProgresses: [],
|
||||||
|
__typename: 'PipelineStage',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
__typename: 'Pipeline',
|
||||||
|
},
|
||||||
|
];
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { Args, Mutation, Resolver, Query } from '@nestjs/graphql';
|
import { Args, Mutation, Resolver } from '@nestjs/graphql';
|
||||||
import { AuthTokens } from './dto/token.entity';
|
import { AuthTokens } from './dto/token.entity';
|
||||||
import { TokenService } from './services/token.service';
|
import { TokenService } from './services/token.service';
|
||||||
import { RefreshTokenInput } from './dto/refresh-token.input';
|
import { RefreshTokenInput } from './dto/refresh-token.input';
|
||||||
|
|||||||
Reference in New Issue
Block a user