mirror of
https://github.com/ershisan99/flashcards-api.git
synced 2025-12-16 20:59:26 +00:00
file upload in progress
This commit is contained in:
@@ -62,6 +62,7 @@
|
||||
"@nestjs/testing": "^9.4.1",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/jest": "29.5.1",
|
||||
"@types/multer": "^1.4.7",
|
||||
"@types/node": "18.16.12",
|
||||
"@types/supertest": "^2.0.12",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.6",
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
import { Body, Controller, Delete, Get, Param, Patch, Req, UseGuards } from '@nestjs/common'
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
Param,
|
||||
Patch,
|
||||
Req,
|
||||
UploadedFiles,
|
||||
UseGuards,
|
||||
UseInterceptors,
|
||||
} from '@nestjs/common'
|
||||
import { CardsService } from './cards.service'
|
||||
import { UpdateCardDto } from './dto/update-card.dto'
|
||||
import { CommandBus } from '@nestjs/cqrs'
|
||||
import { DeleteCardByIdCommand, GetDeckByIdCommand, UpdateDeckCommand } from './use-cases'
|
||||
import { DeleteCardByIdCommand, GetDeckByIdCommand } from './use-cases'
|
||||
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'
|
||||
import { FileFieldsInterceptor } from '@nestjs/platform-express'
|
||||
|
||||
@Controller('cards')
|
||||
export class CardsController {
|
||||
@@ -16,9 +28,23 @@ export class CardsController {
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@UseInterceptors(
|
||||
FileFieldsInterceptor([
|
||||
{ name: 'questionImg', maxCount: 1 },
|
||||
{ name: 'answerImg', maxCount: 1 },
|
||||
])
|
||||
)
|
||||
@Patch(':id')
|
||||
update(@Param('id') id: string, @Body() updateDeckDto: UpdateCardDto, @Req() req) {
|
||||
return this.commandBus.execute(new UpdateDeckCommand(id, updateDeckDto, req.user.id))
|
||||
update(
|
||||
@Param('id') id: string,
|
||||
@Req() req,
|
||||
@UploadedFiles()
|
||||
files: { questionImg: Express.Multer.File[]; answerImg: Express.Multer.File[] },
|
||||
@Body() body: UpdateCardDto
|
||||
) {
|
||||
console.log({ body })
|
||||
console.log(files)
|
||||
// return this.commandBus.execute(new UpdateCardCommand(id, body, req.user.id))
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
|
||||
@@ -2,10 +2,10 @@ import { Module } from '@nestjs/common'
|
||||
import { CardsService } from './cards.service'
|
||||
import { CardsController } from './cards.controller'
|
||||
import { CqrsModule } from '@nestjs/cqrs'
|
||||
import { DeleteCardByIdHandler, GetDeckByIdHandler, UpdateDeckHandler } from './use-cases'
|
||||
import { DeleteCardByIdHandler, GetDeckByIdHandler, UpdateCardHandler } from './use-cases'
|
||||
import { CardsRepository } from './infrastructure/cards.repository'
|
||||
|
||||
const commandHandlers = [GetDeckByIdHandler, DeleteCardByIdHandler, UpdateDeckHandler]
|
||||
const commandHandlers = [GetDeckByIdHandler, DeleteCardByIdHandler, UpdateCardHandler]
|
||||
|
||||
@Module({
|
||||
imports: [CqrsModule],
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Length } from 'class-validator'
|
||||
import { IsOptional, Length } from 'class-validator'
|
||||
|
||||
export class CreateCardDto {
|
||||
@Length(3, 500)
|
||||
@@ -6,4 +6,20 @@ export class CreateCardDto {
|
||||
|
||||
@Length(3, 500)
|
||||
answer: string
|
||||
|
||||
@IsOptional()
|
||||
@Length(3, 500)
|
||||
questionImg?: string
|
||||
|
||||
@IsOptional()
|
||||
@Length(3, 500)
|
||||
answerImg?: string
|
||||
|
||||
@IsOptional()
|
||||
@Length(3, 500)
|
||||
questionVideo?: string
|
||||
|
||||
@IsOptional()
|
||||
@Length(3, 500)
|
||||
answerVideo?: string
|
||||
}
|
||||
|
||||
@@ -1,16 +1,4 @@
|
||||
import { PartialType } from '@nestjs/mapped-types'
|
||||
import { CreateCardDto } from './create-card.dto'
|
||||
import { IsOptionalOrEmptyString } from '../../../infrastructure/decorators/is-optional-or-empty-string'
|
||||
import { IsBoolean } from 'class-validator'
|
||||
|
||||
export class UpdateCardDto extends PartialType(CreateCardDto) {
|
||||
@IsOptionalOrEmptyString()
|
||||
name: string
|
||||
|
||||
@IsOptionalOrEmptyString()
|
||||
@IsBoolean()
|
||||
isPrivate: boolean
|
||||
|
||||
@IsOptionalOrEmptyString()
|
||||
cover: string
|
||||
}
|
||||
export class UpdateCardDto extends PartialType(CreateCardDto) {}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { GetAllCardsInDeckDto } from '../dto/get-all-cards.dto'
|
||||
import { CreateCardDto } from '../dto/create-card.dto'
|
||||
import { Pagination } from '../../../infrastructure/common/pagination/pagination.service'
|
||||
import { createPrismaOrderBy } from '../../../infrastructure/common/helpers/get-order-by-object'
|
||||
import { UpdateCardDto } from '../dto/update-card.dto'
|
||||
|
||||
@Injectable()
|
||||
export class CardsRepository {
|
||||
@@ -146,12 +147,9 @@ export class CardsRepository {
|
||||
}
|
||||
}
|
||||
|
||||
public async updateDeckById(
|
||||
id: string,
|
||||
data: { name?: string; cover?: string; isPrivate?: boolean }
|
||||
) {
|
||||
public async updateCardById(id: string, data: UpdateCardDto) {
|
||||
try {
|
||||
return await this.prisma.deck.update({
|
||||
return await this.prisma.card.update({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './get-deck-by-id-use-case'
|
||||
export * from './delete-card-by-id-use-case'
|
||||
export * from './update-deck-use-case'
|
||||
export * from './update-card-use-case'
|
||||
|
||||
29
src/modules/cards/use-cases/update-card-use-case.ts
Normal file
29
src/modules/cards/use-cases/update-card-use-case.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'
|
||||
import { CardsRepository } from '../infrastructure/cards.repository'
|
||||
import { UpdateCardDto } from '../dto/update-card.dto'
|
||||
import { BadRequestException, NotFoundException } from '@nestjs/common'
|
||||
|
||||
export class UpdateCardCommand {
|
||||
constructor(
|
||||
public readonly cardId: string,
|
||||
public readonly card: UpdateCardDto,
|
||||
public readonly userId: string
|
||||
) {}
|
||||
}
|
||||
|
||||
@CommandHandler(UpdateCardCommand)
|
||||
export class UpdateCardHandler implements ICommandHandler<UpdateCardCommand> {
|
||||
constructor(private readonly cardsRepository: CardsRepository) {}
|
||||
|
||||
async execute(command: UpdateCardCommand) {
|
||||
const card = await this.cardsRepository.findCardById(command.cardId)
|
||||
|
||||
if (!card) throw new NotFoundException(`Card with id ${command.cardId} not found`)
|
||||
|
||||
if (card.userId !== command.userId) {
|
||||
throw new BadRequestException(`You can't change a card that you don't own`)
|
||||
}
|
||||
|
||||
return await this.cardsRepository.updateCardById(command.cardId, command.card)
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { CommandHandler, ICommandHandler } from '@nestjs/cqrs'
|
||||
import { CardsRepository } from '../infrastructure/cards.repository'
|
||||
import { UpdateCardDto } from '../dto/update-card.dto'
|
||||
import { BadRequestException, NotFoundException } from '@nestjs/common'
|
||||
|
||||
export class UpdateDeckCommand {
|
||||
constructor(
|
||||
public readonly deckId: string,
|
||||
public readonly deck: UpdateCardDto,
|
||||
public readonly userId: string
|
||||
) {}
|
||||
}
|
||||
|
||||
@CommandHandler(UpdateDeckCommand)
|
||||
export class UpdateDeckHandler implements ICommandHandler<UpdateDeckCommand> {
|
||||
constructor(private readonly deckRepository: CardsRepository) {}
|
||||
|
||||
async execute(command: UpdateDeckCommand) {
|
||||
const deck = await this.deckRepository.findCardById(command.deckId)
|
||||
|
||||
if (!deck) throw new NotFoundException(`Deck with id ${command.deckId} not found`)
|
||||
|
||||
if (deck.userId !== command.userId) {
|
||||
throw new BadRequestException(`You can't change a deck that you don't own`)
|
||||
}
|
||||
|
||||
return await this.deckRepository.updateDeckById(command.deckId, command.deck)
|
||||
}
|
||||
}
|
||||
@@ -8,13 +8,16 @@ import { pick } from 'remeda'
|
||||
export class GetRandomCardInDeckCommand {
|
||||
constructor(public readonly userId: string, public readonly deckId: string) {}
|
||||
}
|
||||
|
||||
type CardWithGrade = Prisma.cardGetPayload<{ include: { grades: true } }>
|
||||
|
||||
@CommandHandler(GetRandomCardInDeckCommand)
|
||||
export class GetRandomCardInDeckHandler implements ICommandHandler<GetRandomCardInDeckCommand> {
|
||||
constructor(
|
||||
private readonly cardsRepository: CardsRepository,
|
||||
private readonly decksRepository: DecksRepository
|
||||
) {}
|
||||
|
||||
private async getSmartRandomCard(cards: Array<CardWithGrade>) {
|
||||
const selectionPool: Array<CardWithGrade> = []
|
||||
cards.forEach(card => {
|
||||
|
||||
@@ -1935,6 +1935,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
|
||||
integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
|
||||
|
||||
"@types/multer@^1.4.7":
|
||||
version "1.4.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.7.tgz#89cf03547c28c7bbcc726f029e2a76a7232cc79e"
|
||||
integrity sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==
|
||||
dependencies:
|
||||
"@types/express" "*"
|
||||
|
||||
"@types/node@*":
|
||||
version "20.4.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.2.tgz#129cc9ae69f93824f92fac653eebfb4812ab4af9"
|
||||
|
||||
Reference in New Issue
Block a user