Skip to content
This repository has been archived by the owner on Feb 26, 2022. It is now read-only.

Commit

Permalink
Merge pull request #29 from LudovicGendre/feature/pagination
Browse files Browse the repository at this point in the history
feat: add pagination (search, take, sort, skip)
  • Loading branch information
Ludovic authored Jan 14, 2022
2 parents 997fedb + de861fa commit 1d7d2e9
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 38 deletions.
12 changes: 6 additions & 6 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,21 @@ model City {
name String
postalCode String
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
users User[]
users User[]
}

model User {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
firstName String
lastName String
avatar String
avatar String?
username String @unique
birthDate DateTime? @db.Timestamptz(6)
email String @unique
sex Int @default(0)
latitude Float
longitude Float
cityId String @db.Uuid()
latitude Float?
longitude Float?
cityId String @db.Uuid
city City @relation(fields: [cityId], references: [id])
animals Animal[]
}
Expand Down
9 changes: 7 additions & 2 deletions src/animal/animal.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ export class AnimalController {
constructor(private readonly animalService: AnimalService) {}

@Get('/')
async list(@Query() query: FilterDto | undefined): Promise<Animal[]> {
return await this.animalService.list({ where: { name: query.search } });
async list(@Query() query: FilterDto<Animal> | undefined): Promise<Animal[]> {
return await this.animalService.list({
skip: parseInt(query.skip) || 0,
take: parseInt(query.take) || 20,
orderBy: { name: query.order },
where: { name: query.search },
});
}

@Get('/:id')
Expand Down
9 changes: 7 additions & 2 deletions src/animal/breed.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ export class BreedController {
constructor(private readonly breedService: BreedService) {}

@Get('/')
async list(@Query() query: FilterDto | undefined): Promise<Breed[]> {
return await this.breedService.list({ where: { name: query.search } });
async list(@Query() query: FilterDto<Breed> | undefined): Promise<Breed[]> {
return await this.breedService.list({
skip: parseInt(query.skip) || 0,
take: parseInt(query.take) || 20,
orderBy: { name: query.order },
where: { name: query.search },
});
}

@Get('/:id')
Expand Down
2 changes: 1 addition & 1 deletion src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { UserModule } from './user/user.module';
PrismaService,
AuthModule,
ConfigModule,
UserModule,
CityModule,
UserModule,
AnimalModule,
BreedModule,
],
Expand Down
3 changes: 2 additions & 1 deletion src/dtos/users/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ export class CreateUserDto {
public username: string;

@ApiProperty()
@IsOptional()
@IsString()
public avatar: string;
public avatar?: string | null;

@ApiProperty()
@IsISO8601()
Expand Down
43 changes: 38 additions & 5 deletions src/dtos/utils/filter.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,46 @@
export class FilterDto {
import { ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { IsEnum, IsInt, IsOptional, Max, Min } from 'class-validator';

export enum Order {
ASC = 'asc',
DESC = 'desc',
}
export class FilterDto<T> {
@ApiPropertyOptional()
public search?: string | null;

@ApiPropertyOptional()
public disablePagination?: true | null;

public skip?: number | null;
@ApiPropertyOptional({
minimum: 1,
default: 1,
})
@Type(() => String)
@IsInt()
@Min(1)
@IsOptional()
public page?: string;

public take?: number | null;
@ApiPropertyOptional({
minimum: 1,
maximum: 50,
default: 10,
})
@Type(() => Number)
@IsInt()
@Min(1)
@Max(50)
@IsOptional()
public take?: string | null;

public sort?: 'ASC' | 'DESC';
@ApiPropertyOptional({ enum: Order, default: Order.ASC })
@IsEnum(Order)
@IsOptional()
public order?: Order;

public orderBy?: string;
get skip(): string {
return ((parseInt(this.page) - 1) * parseInt(this.take)).toString();
}
}
10 changes: 8 additions & 2 deletions src/user/city/city.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@ export class CityController {
constructor(private readonly cityService: CityService) {}

@Get('/')
async list(@Query() query: FilterDto | undefined): Promise<City[]> {
return await this.cityService.list({});
async list(@Query() query: FilterDto<City> | undefined): Promise<City[]> {
console.log(query.order);
return await this.cityService.list({
skip: parseInt(query.skip) || 0,
take: parseInt(query.take) || 20,
orderBy: { name: query.order },
where: { name: query.search },
});
}

@Get('/:id')
Expand Down
7 changes: 5 additions & 2 deletions src/user/city/city.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,18 @@ export class CityService {
): Promise<City | null> {
return this.prisma.city.findUnique({
where: cityWhereUniqueInput,
include: {
users: true,
},
});
}

async list(params: {
skip?: number;
take?: number;
cursor?: Prisma.CityWhereUniqueInput;
where?: Prisma.UserWhereInput;
orderBy?: Prisma.UserOrderByWithRelationInput;
where?: Prisma.CityWhereInput;
orderBy?: Prisma.CityOrderByWithAggregationInput;
}): Promise<City[]> {
const { skip, take, cursor, where, orderBy } = params;
return this.prisma.city.findMany({
Expand Down
31 changes: 18 additions & 13 deletions src/user/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,27 @@ export class UserController {
constructor(private readonly userService: UserService) {}

@Get('/')
async list(@Query() query: FilterDto | undefined): Promise<User[]> {
return await this.userService.list({ where: { username: query.search } });
}

@Get('/city/:id')
async listCity(@Param('id') id: string): Promise<User[]> {
return await this.userService.getCity({
cityWhereUniqueInput: {
id,
},
async list(@Query() query: FilterDto<User> | undefined): Promise<User[]> {
return await this.userService.list({
skip: parseInt(query.skip) || 0,
take: parseInt(query.take) || 20,
orderBy: { username: query.order },
where: { username: query.search },
});
}

@UseGuards(AuthGuard)
// Ludo: Pas nécessaire (duplication), nous avons déjà l'ensemble des users en relation dans /cities/:id

// @Get('/city/:id')
// async listCity(@Param('id') id: string): Promise<User[]> {
// return await this.userService.getCity({
// cityWhereUniqueInput: {
// id,
// },
// });
// }

// @UseGuards(AuthGuard)
@Get('/proximity')
async getUsersInRadius(
@Query('radius') radius: string,
Expand All @@ -60,13 +67,11 @@ export class UserController {
return await this.userService.getUsersInRadius(radius, currentUser);
}

@UseGuards(AuthGuard)
@Get('/:id')
async get(@Param('id') id: string): Promise<User> {
return await this.userService.get({ id: id });
}

@UseGuards(AuthGuard)
@Post('upload')
@UseInterceptors(
FileInterceptor('file', {
Expand Down
6 changes: 2 additions & 4 deletions src/user/user.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma.service';
import { User, Prisma } from '@prisma/client';
import MulterModule from '@nestjs/platform-express';
import { from, Observable } from 'rxjs';
@Injectable()
export class UserService {
constructor(private prisma: PrismaService) {}
Expand All @@ -11,7 +9,7 @@ export class UserService {
userWhereUniqueInput: Prisma.UserWhereUniqueInput,
): Promise<User | null> {
return this.prisma.user.findUnique({
where: userWhereUniqueInput,
where: { id: userWhereUniqueInput.id },
});
}

Expand Down Expand Up @@ -103,7 +101,7 @@ function calcCrow(lat1, lon1, lat2, lon2) {
Math.sin(dLon / 2) *
Math.cos(radLat1) *
Math.cos(radLat2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const d = R * c;
return d;
}
Expand Down

0 comments on commit 1d7d2e9

Please sign in to comment.