fix grade orderby

This commit is contained in:
2023-08-07 16:40:21 +02:00
parent dab78cd2a1
commit 2b7b967382
5 changed files with 95 additions and 38 deletions

View File

@@ -1,6 +1,22 @@
type OrderByDirection = 'asc' | 'desc' type OrderByDirection = 'asc' | 'desc'
export function createPrismaOrderBy(input: string | null) { export function createPrismaOrderBy(input: string | null) {
const { key, direction, relation, field } = getOrderByObject(input)
if (relation && field) {
return {
[relation]: {
[field]: direction,
},
}
}
return {
[key]: direction as OrderByDirection,
}
}
export function getOrderByObject(input: string) {
if (!input || input === 'null') { if (!input || input === 'null') {
return undefined return undefined
} }
@@ -18,13 +34,14 @@ export function createPrismaOrderBy(input: string | null) {
const [relation, field] = key.split('.') const [relation, field] = key.split('.')
return { return {
[relation]: { relation,
[field]: direction, field,
}, direction,
} }
} }
return { return {
[key]: direction as OrderByDirection, key,
direction: direction as OrderByDirection,
} }
} }

View File

@@ -17,7 +17,7 @@ export class Card {
} }
export class PaginatedCards { export class PaginatedCards {
items: Omit<Card, 'userId' | 'rating'>[] items: Array<Omit<Card, 'userId' | 'rating'> & { grade: number }>
pagination: Pagination pagination: Pagination
} }

View File

@@ -1,10 +1,13 @@
import { Injectable, InternalServerErrorException, Logger } from '@nestjs/common' import { Injectable, InternalServerErrorException, Logger } from '@nestjs/common'
import { createPrismaOrderBy } from '../../../infrastructure/common/helpers/get-order-by-object' import {
createPrismaOrderBy,
getOrderByObject,
} from '../../../infrastructure/common/helpers/get-order-by-object'
import { Pagination } from '../../../infrastructure/common/pagination/pagination.service' import { Pagination } from '../../../infrastructure/common/pagination/pagination.service'
import { PrismaService } from '../../../prisma.service' import { PrismaService } from '../../../prisma.service'
import { CreateCardDto, GetAllCardsInDeckDto, UpdateCardDto } from '../dto' import { CreateCardDto, GetAllCardsInDeckDto, UpdateCardDto } from '../dto'
import { PaginatedCardsWithGrade } from '../entities/cards.entity' import { CardWithGrade, PaginatedCardsWithGrade } from '../entities/cards.entity'
@Injectable() @Injectable()
export class CardsRepository { export class CardsRepository {
@@ -74,27 +77,70 @@ export class CardsRepository {
contains: answer || undefined, contains: answer || undefined,
}, },
} }
const result = await this.prisma.$transaction([
this.prisma.card.count({ where }), const { key, direction } = getOrderByObject(orderBy)
this.prisma.card.findMany({
orderBy: createPrismaOrderBy(orderBy) || { updated: 'desc' }, if (key === 'grade') {
where, const start = (currentPage - 1) * itemsPerPage
include: {
grades: { const sqlQuery = `
where: { SELECT c.*, g.grade as userGrade
userId, FROM card AS c
}, LEFT JOIN grade AS g ON c.id = g.cardId AND g.userId = ?
select: { WHERE c.deckId = ? AND
grade: true, (c.question LIKE ? OR c.answer LIKE ?)
ORDER BY g.grade ${direction}
LIMIT ?, ?
`
const cardsRaw = (await this.prisma.$queryRawUnsafe(
sqlQuery,
userId,
deckId,
`%${question || ''}%`,
`%${answer || ''}%`,
start,
itemsPerPage
)) satisfies Array<any>
const cards: CardWithGrade[] = cardsRaw.map(({ userGrade, ...card }) => ({
...card,
grades: [
{
grade: userGrade,
},
],
}))
const totalCount = await this.prisma.card.count({ where })
return Pagination.transformPaginationData([totalCount, cards], {
currentPage,
itemsPerPage,
})
} else {
const result = await this.prisma.$transaction([
this.prisma.card.count({ where }),
this.prisma.card.findMany({
orderBy: createPrismaOrderBy(orderBy) || { updated: 'desc' },
where,
include: {
grades: {
where: {
userId,
},
select: {
grade: true,
},
}, },
}, },
}, skip: (currentPage - 1) * itemsPerPage,
skip: (currentPage - 1) * itemsPerPage, take: itemsPerPage,
take: itemsPerPage, }),
}), ])
])
return Pagination.transformPaginationData(result, { currentPage, itemsPerPage }) return Pagination.transformPaginationData(result, { currentPage, itemsPerPage })
}
} catch (e) { } catch (e) {
this.logger.error(e?.message) this.logger.error(e?.message)
throw new InternalServerErrorException(e?.message) throw new InternalServerErrorException(e?.message)

View File

@@ -194,19 +194,12 @@ export class DecksController {
summary: 'Save the grade of a card', summary: 'Save the grade of a card',
}) })
async saveGrade(@Param('id') deckId: string, @Req() req, @Body() body: SaveGradeDto) { async saveGrade(@Param('id') deckId: string, @Req() req, @Body() body: SaveGradeDto) {
const promises = [ const saved = await this.commandBus.execute(
this.commandBus.execute(new GetRandomCardInDeckCommand(req.user.id, deckId, body.cardId)), new SaveGradeCommand(req.user.id, { cardId: body.cardId, grade: body.grade })
this.commandBus.execute( )
new SaveGradeCommand(req.user.id, { cardId: body.cardId, grade: body.grade })
),
]
try { return await this.commandBus.execute(
const [card] = await Promise.all(promises) new GetRandomCardInDeckCommand(req.user.id, saved.deckId, saved.id)
)
return card
} catch (error) {
throw error
}
} }
} }

View File

@@ -42,6 +42,7 @@ export class GetAllCardsInDeckHandler implements ICommandHandler<GetAllCardsInDe
'created', 'created',
'updated', 'updated',
'shots', 'shots',
'grade',
] ]
) )
), ),