feat: I can upload a photo on person show page (#1103)
* I can upload a photo on person show page Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: RubensRafael <rubensrafael2@live.com> Co-authored-by: Rubens Rafael <70234898+RubensRafael@users.noreply.github.com> * Add requested changes Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: RubensRafael <rubensrafael2@live.com> Co-authored-by: Rubens Rafael <70234898+RubensRafael@users.noreply.github.com> --------- Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: RubensRafael <rubensrafael2@live.com> Co-authored-by: Rubens Rafael <70234898+RubensRafael@users.noreply.github.com>
This commit is contained in:
@ -848,6 +848,7 @@ export type EnumPipelineProgressableTypeFilter = {
|
|||||||
|
|
||||||
export enum FileFolder {
|
export enum FileFolder {
|
||||||
Attachment = 'Attachment',
|
Attachment = 'Attachment',
|
||||||
|
PersonPicture = 'PersonPicture',
|
||||||
ProfilePicture = 'ProfilePicture',
|
ProfilePicture = 'ProfilePicture',
|
||||||
WorkspaceLogo = 'WorkspaceLogo'
|
WorkspaceLogo = 'WorkspaceLogo'
|
||||||
}
|
}
|
||||||
@ -928,6 +929,7 @@ export type Mutation = {
|
|||||||
uploadAttachment: Scalars['String'];
|
uploadAttachment: Scalars['String'];
|
||||||
uploadFile: Scalars['String'];
|
uploadFile: Scalars['String'];
|
||||||
uploadImage: Scalars['String'];
|
uploadImage: Scalars['String'];
|
||||||
|
uploadPersonPicture: Scalars['String'];
|
||||||
uploadProfilePicture: Scalars['String'];
|
uploadProfilePicture: Scalars['String'];
|
||||||
uploadWorkspaceLogo: Scalars['String'];
|
uploadWorkspaceLogo: Scalars['String'];
|
||||||
verify: Verify;
|
verify: Verify;
|
||||||
@ -1094,6 +1096,12 @@ export type MutationUploadImageArgs = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export type MutationUploadPersonPictureArgs = {
|
||||||
|
file: Scalars['Upload'];
|
||||||
|
id: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export type MutationUploadProfilePictureArgs = {
|
export type MutationUploadProfilePictureArgs = {
|
||||||
file: Scalars['Upload'];
|
file: Scalars['Upload'];
|
||||||
};
|
};
|
||||||
@ -2582,6 +2590,21 @@ export type DeleteManyPersonMutationVariables = Exact<{
|
|||||||
|
|
||||||
export type DeleteManyPersonMutation = { __typename?: 'Mutation', deleteManyPerson: { __typename?: 'AffectedRows', count: number } };
|
export type DeleteManyPersonMutation = { __typename?: 'Mutation', deleteManyPerson: { __typename?: 'AffectedRows', count: number } };
|
||||||
|
|
||||||
|
export type UploadPersonPictureMutationVariables = Exact<{
|
||||||
|
id: Scalars['String'];
|
||||||
|
file: Scalars['Upload'];
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type UploadPersonPictureMutation = { __typename?: 'Mutation', uploadPersonPicture: string };
|
||||||
|
|
||||||
|
export type RemovePersonPictureMutationVariables = Exact<{
|
||||||
|
where: PersonWhereUniqueInput;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
|
export type RemovePersonPictureMutation = { __typename?: 'Mutation', updateOnePerson?: { __typename?: 'Person', id: string, avatarUrl?: string | null } | null };
|
||||||
|
|
||||||
export type GetPipelinesQueryVariables = Exact<{
|
export type GetPipelinesQueryVariables = Exact<{
|
||||||
where?: InputMaybe<PipelineWhereInput>;
|
where?: InputMaybe<PipelineWhereInput>;
|
||||||
}>;
|
}>;
|
||||||
@ -4398,6 +4421,72 @@ export function useDeleteManyPersonMutation(baseOptions?: Apollo.MutationHookOpt
|
|||||||
export type DeleteManyPersonMutationHookResult = ReturnType<typeof useDeleteManyPersonMutation>;
|
export type DeleteManyPersonMutationHookResult = ReturnType<typeof useDeleteManyPersonMutation>;
|
||||||
export type DeleteManyPersonMutationResult = Apollo.MutationResult<DeleteManyPersonMutation>;
|
export type DeleteManyPersonMutationResult = Apollo.MutationResult<DeleteManyPersonMutation>;
|
||||||
export type DeleteManyPersonMutationOptions = Apollo.BaseMutationOptions<DeleteManyPersonMutation, DeleteManyPersonMutationVariables>;
|
export type DeleteManyPersonMutationOptions = Apollo.BaseMutationOptions<DeleteManyPersonMutation, DeleteManyPersonMutationVariables>;
|
||||||
|
export const UploadPersonPictureDocument = gql`
|
||||||
|
mutation UploadPersonPicture($id: String!, $file: Upload!) {
|
||||||
|
uploadPersonPicture(id: $id, file: $file)
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type UploadPersonPictureMutationFn = Apollo.MutationFunction<UploadPersonPictureMutation, UploadPersonPictureMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useUploadPersonPictureMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useUploadPersonPictureMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useUploadPersonPictureMutation` 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 [uploadPersonPictureMutation, { data, loading, error }] = useUploadPersonPictureMutation({
|
||||||
|
* variables: {
|
||||||
|
* id: // value for 'id'
|
||||||
|
* file: // value for 'file'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useUploadPersonPictureMutation(baseOptions?: Apollo.MutationHookOptions<UploadPersonPictureMutation, UploadPersonPictureMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useMutation<UploadPersonPictureMutation, UploadPersonPictureMutationVariables>(UploadPersonPictureDocument, options);
|
||||||
|
}
|
||||||
|
export type UploadPersonPictureMutationHookResult = ReturnType<typeof useUploadPersonPictureMutation>;
|
||||||
|
export type UploadPersonPictureMutationResult = Apollo.MutationResult<UploadPersonPictureMutation>;
|
||||||
|
export type UploadPersonPictureMutationOptions = Apollo.BaseMutationOptions<UploadPersonPictureMutation, UploadPersonPictureMutationVariables>;
|
||||||
|
export const RemovePersonPictureDocument = gql`
|
||||||
|
mutation RemovePersonPicture($where: PersonWhereUniqueInput!) {
|
||||||
|
updateOnePerson(data: {avatarUrl: null}, where: $where) {
|
||||||
|
id
|
||||||
|
avatarUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export type RemovePersonPictureMutationFn = Apollo.MutationFunction<RemovePersonPictureMutation, RemovePersonPictureMutationVariables>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* __useRemovePersonPictureMutation__
|
||||||
|
*
|
||||||
|
* To run a mutation, you first call `useRemovePersonPictureMutation` within a React component and pass it any options that fit your needs.
|
||||||
|
* When your component renders, `useRemovePersonPictureMutation` 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 [removePersonPictureMutation, { data, loading, error }] = useRemovePersonPictureMutation({
|
||||||
|
* variables: {
|
||||||
|
* where: // value for 'where'
|
||||||
|
* },
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useRemovePersonPictureMutation(baseOptions?: Apollo.MutationHookOptions<RemovePersonPictureMutation, RemovePersonPictureMutationVariables>) {
|
||||||
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
|
return Apollo.useMutation<RemovePersonPictureMutation, RemovePersonPictureMutationVariables>(RemovePersonPictureDocument, options);
|
||||||
|
}
|
||||||
|
export type RemovePersonPictureMutationHookResult = ReturnType<typeof useRemovePersonPictureMutation>;
|
||||||
|
export type RemovePersonPictureMutationResult = Apollo.MutationResult<RemovePersonPictureMutation>;
|
||||||
|
export type RemovePersonPictureMutationOptions = Apollo.BaseMutationOptions<RemovePersonPictureMutation, RemovePersonPictureMutationVariables>;
|
||||||
export const GetPipelinesDocument = gql`
|
export const GetPipelinesDocument = gql`
|
||||||
query GetPipelines($where: PipelineWhereInput) {
|
query GetPipelines($where: PipelineWhereInput) {
|
||||||
findManyPipeline(where: $where) {
|
findManyPipeline(where: $where) {
|
||||||
|
|||||||
@ -54,3 +54,18 @@ export const DELETE_MANY_PERSON = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const UPDATE_PERSON_PICTURE = gql`
|
||||||
|
mutation UploadPersonPicture($id: String!, $file: Upload!) {
|
||||||
|
uploadPersonPicture(id: $id, file: $file)
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const REMOVE_PERSON_PICTURE = gql`
|
||||||
|
mutation RemovePersonPicture($where: PersonWhereUniqueInput!) {
|
||||||
|
updateOnePerson(data: { avatarUrl: null }, where: $where) {
|
||||||
|
id
|
||||||
|
avatarUrl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { ChangeEvent, useRef } from 'react';
|
||||||
import { Tooltip } from 'react-tooltip';
|
import { Tooltip } from 'react-tooltip';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { v4 as uuidV4 } from 'uuid';
|
import { v4 as uuidV4 } from 'uuid';
|
||||||
@ -16,6 +17,7 @@ type OwnProps = {
|
|||||||
title: string;
|
title: string;
|
||||||
date: string;
|
date: string;
|
||||||
renderTitleEditComponent?: () => JSX.Element;
|
renderTitleEditComponent?: () => JSX.Element;
|
||||||
|
onUploadPicture?: (file: File) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledShowPageSummaryCard = styled.div`
|
const StyledShowPageSummaryCard = styled.div`
|
||||||
@ -62,27 +64,52 @@ const StyledTooltip = styled(Tooltip)`
|
|||||||
padding: ${({ theme }) => theme.spacing(2)};
|
padding: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledAvatarWrapper = styled.div`
|
||||||
|
cursor: pointer;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledFileInput = styled.input`
|
||||||
|
display: none;
|
||||||
|
`;
|
||||||
|
|
||||||
export function ShowPageSummaryCard({
|
export function ShowPageSummaryCard({
|
||||||
id,
|
id,
|
||||||
logoOrAvatar,
|
logoOrAvatar,
|
||||||
title,
|
title,
|
||||||
date,
|
date,
|
||||||
renderTitleEditComponent,
|
renderTitleEditComponent,
|
||||||
|
onUploadPicture,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
const beautifiedCreatedAt =
|
const beautifiedCreatedAt =
|
||||||
date !== '' ? beautifyPastDateRelativeToNow(date) : '';
|
date !== '' ? beautifyPastDateRelativeToNow(date) : '';
|
||||||
const exactCreatedAt = date !== '' ? beautifyExactDateTime(date) : '';
|
const exactCreatedAt = date !== '' ? beautifyExactDateTime(date) : '';
|
||||||
const dateElementId = `date-id-${uuidV4()}`;
|
const dateElementId = `date-id-${uuidV4()}`;
|
||||||
|
const inputFileRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
const onFileChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
if (e.target.files) onUploadPicture?.(e.target.files[0]);
|
||||||
|
};
|
||||||
|
const onAvatarClick = () => {
|
||||||
|
if (onUploadPicture) inputFileRef?.current?.click?.();
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledShowPageSummaryCard>
|
<StyledShowPageSummaryCard>
|
||||||
<Avatar
|
<StyledAvatarWrapper onClick={onAvatarClick}>
|
||||||
avatarUrl={logoOrAvatar}
|
<Avatar
|
||||||
size="xl"
|
avatarUrl={logoOrAvatar}
|
||||||
colorId={id}
|
size="xl"
|
||||||
placeholder={title}
|
colorId={id}
|
||||||
type="rounded"
|
placeholder={title}
|
||||||
/>
|
type="rounded"
|
||||||
|
/>
|
||||||
|
<StyledFileInput
|
||||||
|
ref={inputFileRef}
|
||||||
|
onChange={onFileChange}
|
||||||
|
type="file"
|
||||||
|
/>
|
||||||
|
</StyledAvatarWrapper>
|
||||||
|
|
||||||
<StyledInfoContainer>
|
<StyledInfoContainer>
|
||||||
<StyledTitle>
|
<StyledTitle>
|
||||||
{renderTitleEditComponent ? (
|
{renderTitleEditComponent ? (
|
||||||
|
|||||||
@ -1,15 +1,19 @@
|
|||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
|
import { getOperationName } from '@apollo/client/utilities';
|
||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
|
|
||||||
import { Timeline } from '@/activities/timeline/components/Timeline';
|
import { Timeline } from '@/activities/timeline/components/Timeline';
|
||||||
import { PersonPropertyBox } from '@/people/components/PersonPropertyBox';
|
import { PersonPropertyBox } from '@/people/components/PersonPropertyBox';
|
||||||
import { usePersonQuery } from '@/people/queries';
|
import { GET_PERSON, usePersonQuery } from '@/people/queries';
|
||||||
import { IconUser } from '@/ui/icon';
|
import { IconUser } from '@/ui/icon';
|
||||||
import { WithTopBarContainer } from '@/ui/layout/components/WithTopBarContainer';
|
import { WithTopBarContainer } from '@/ui/layout/components/WithTopBarContainer';
|
||||||
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
|
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
|
||||||
import { ShowPageRightContainer } from '@/ui/layout/show-page/components/ShowPageRightContainer';
|
import { ShowPageRightContainer } from '@/ui/layout/show-page/components/ShowPageRightContainer';
|
||||||
import { ShowPageSummaryCard } from '@/ui/layout/show-page/components/ShowPageSummaryCard';
|
import { ShowPageSummaryCard } from '@/ui/layout/show-page/components/ShowPageSummaryCard';
|
||||||
import { CommentableType } from '~/generated/graphql';
|
import {
|
||||||
|
CommentableType,
|
||||||
|
useUploadPersonPictureMutation,
|
||||||
|
} from '~/generated/graphql';
|
||||||
|
|
||||||
import { PeopleFullNameEditableField } from '../../modules/people/editable-field/components/PeopleFullNameEditableField';
|
import { PeopleFullNameEditableField } from '../../modules/people/editable-field/components/PeopleFullNameEditableField';
|
||||||
import { ShowPageContainer } from '../../modules/ui/layout/components/ShowPageContainer';
|
import { ShowPageContainer } from '../../modules/ui/layout/components/ShowPageContainer';
|
||||||
@ -21,6 +25,20 @@ export function PersonShow() {
|
|||||||
const person = data?.findUniquePerson;
|
const person = data?.findUniquePerson;
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const [uploadPicture] = useUploadPersonPictureMutation();
|
||||||
|
|
||||||
|
async function onUploadPicture(file: File) {
|
||||||
|
if (!file || !person?.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await uploadPicture({
|
||||||
|
variables: {
|
||||||
|
file,
|
||||||
|
id: person?.id,
|
||||||
|
},
|
||||||
|
refetchQueries: [getOperationName(GET_PERSON) ?? ''],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithTopBarContainer
|
<WithTopBarContainer
|
||||||
@ -38,6 +56,7 @@ export function PersonShow() {
|
|||||||
renderTitleEditComponent={() =>
|
renderTitleEditComponent={() =>
|
||||||
person ? <PeopleFullNameEditableField people={person} /> : <></>
|
person ? <PeopleFullNameEditableField people={person} /> : <></>
|
||||||
}
|
}
|
||||||
|
onUploadPicture={onUploadPicture}
|
||||||
/>
|
/>
|
||||||
{person && <PersonPropertyBox person={person} />}
|
{person && <PersonPropertyBox person={person} />}
|
||||||
</ShowPageLeftContainer>
|
</ShowPageLeftContainer>
|
||||||
|
|||||||
@ -5,6 +5,7 @@ export const settings: Settings = {
|
|||||||
imageCropSizes: {
|
imageCropSizes: {
|
||||||
'profile-picture': ['original'],
|
'profile-picture': ['original'],
|
||||||
'workspace-logo': ['original'],
|
'workspace-logo': ['original'],
|
||||||
|
'person-picture': ['original'],
|
||||||
},
|
},
|
||||||
maxFileSize: '10MB',
|
maxFileSize: '10MB',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -4,6 +4,7 @@ export enum FileFolder {
|
|||||||
ProfilePicture = 'profile-picture',
|
ProfilePicture = 'profile-picture',
|
||||||
WorkspaceLogo = 'workspace-logo',
|
WorkspaceLogo = 'workspace-logo',
|
||||||
Attachment = 'attachment',
|
Attachment = 'attachment',
|
||||||
|
PersonPicture = 'person-picture',
|
||||||
}
|
}
|
||||||
|
|
||||||
registerEnumType(FileFolder, {
|
registerEnumType(FileFolder, {
|
||||||
|
|||||||
@ -2,13 +2,14 @@ import { Module } from '@nestjs/common';
|
|||||||
|
|
||||||
import { CommentModule } from 'src/core/comment/comment.module';
|
import { CommentModule } from 'src/core/comment/comment.module';
|
||||||
import { ActivityModule } from 'src/core/activity/activity.module';
|
import { ActivityModule } from 'src/core/activity/activity.module';
|
||||||
|
import { FileModule } from 'src/core/file/file.module';
|
||||||
|
|
||||||
import { PersonService } from './person.service';
|
import { PersonService } from './person.service';
|
||||||
import { PersonResolver } from './person.resolver';
|
import { PersonResolver } from './person.resolver';
|
||||||
import { PersonRelationsResolver } from './person-relations.resolver';
|
import { PersonRelationsResolver } from './person-relations.resolver';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [CommentModule, ActivityModule],
|
imports: [CommentModule, ActivityModule, FileModule],
|
||||||
providers: [PersonService, PersonResolver, PersonRelationsResolver],
|
providers: [PersonService, PersonResolver, PersonRelationsResolver],
|
||||||
exports: [PersonService],
|
exports: [PersonService],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
|
||||||
import { AbilityFactory } from 'src/ability/ability.factory';
|
import { AbilityFactory } from 'src/ability/ability.factory';
|
||||||
|
import { FileUploadService } from 'src/core/file/services/file-upload.service';
|
||||||
|
|
||||||
import { PersonService } from './person.service';
|
import { PersonService } from './person.service';
|
||||||
import { PersonResolver } from './person.resolver';
|
import { PersonResolver } from './person.resolver';
|
||||||
@ -20,6 +21,10 @@ describe('PersonResolver', () => {
|
|||||||
provide: AbilityFactory,
|
provide: AbilityFactory,
|
||||||
useValue: {},
|
useValue: {},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: FileUploadService,
|
||||||
|
useValue: {},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,9 @@ import { UseGuards } from '@nestjs/common';
|
|||||||
|
|
||||||
import { accessibleBy } from '@casl/prisma';
|
import { accessibleBy } from '@casl/prisma';
|
||||||
import { Prisma } from '@prisma/client';
|
import { Prisma } from '@prisma/client';
|
||||||
|
import { FileUpload, GraphQLUpload } from 'graphql-upload';
|
||||||
|
|
||||||
|
import { FileFolder } from 'src/core/file/interfaces/file-folder.interface';
|
||||||
|
|
||||||
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
|
||||||
import { Person } from 'src/core/@generated/person/person.model';
|
import { Person } from 'src/core/@generated/person/person.model';
|
||||||
@ -34,13 +37,18 @@ import {
|
|||||||
import { UserAbility } from 'src/decorators/user-ability.decorator';
|
import { UserAbility } from 'src/decorators/user-ability.decorator';
|
||||||
import { AppAbility } from 'src/ability/ability.factory';
|
import { AppAbility } from 'src/ability/ability.factory';
|
||||||
import { Workspace } from 'src/core/@generated/workspace/workspace.model';
|
import { Workspace } from 'src/core/@generated/workspace/workspace.model';
|
||||||
|
import { streamToBuffer } from 'src/utils/stream-to-buffer';
|
||||||
|
import { FileUploadService } from 'src/core/file/services/file-upload.service';
|
||||||
|
|
||||||
import { PersonService } from './person.service';
|
import { PersonService } from './person.service';
|
||||||
|
|
||||||
@UseGuards(JwtAuthGuard)
|
@UseGuards(JwtAuthGuard)
|
||||||
@Resolver(() => Person)
|
@Resolver(() => Person)
|
||||||
export class PersonResolver {
|
export class PersonResolver {
|
||||||
constructor(private readonly personService: PersonService) {}
|
constructor(
|
||||||
|
private readonly personService: PersonService,
|
||||||
|
private readonly fileUploadService: FileUploadService,
|
||||||
|
) {}
|
||||||
|
|
||||||
@Query(() => [Person], {
|
@Query(() => [Person], {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
@ -156,4 +164,32 @@ export class PersonResolver {
|
|||||||
select: prismaSelect.value,
|
select: prismaSelect.value,
|
||||||
} as Prisma.PersonCreateArgs);
|
} as Prisma.PersonCreateArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Mutation(() => String)
|
||||||
|
@UseGuards(AbilityGuard)
|
||||||
|
@CheckAbilities(UpdatePersonAbilityHandler)
|
||||||
|
async uploadPersonPicture(
|
||||||
|
@Args('id') id: string,
|
||||||
|
@Args({ name: 'file', type: () => GraphQLUpload })
|
||||||
|
{ createReadStream, filename, mimetype }: FileUpload,
|
||||||
|
): Promise<string> {
|
||||||
|
const stream = createReadStream();
|
||||||
|
const buffer = await streamToBuffer(stream);
|
||||||
|
|
||||||
|
const { paths } = await this.fileUploadService.uploadImage({
|
||||||
|
file: buffer,
|
||||||
|
filename,
|
||||||
|
mimeType: mimetype,
|
||||||
|
fileFolder: FileFolder.PersonPicture,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.personService.update({
|
||||||
|
where: { id },
|
||||||
|
data: {
|
||||||
|
avatarUrl: paths[0],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return paths[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user