refactor: changed functions to use pagination logic correctly
This commit is contained in:
@@ -925,5 +925,6 @@ export const enum WorkSpaceMessage {
|
|||||||
|
|
||||||
export const enum ProjectMessage {
|
export const enum ProjectMessage {
|
||||||
PROJECT_EXISTS = "پروژه مورد نظر شما از قبل وجود دارد!",
|
PROJECT_EXISTS = "پروژه مورد نظر شما از قبل وجود دارد!",
|
||||||
PROJECT_NOT_FOUND = "پروژه مورد نظر شما وجود ندارد!"
|
PROJECT_NOT_FOUND = "پروژه مورد نظر شما وجود ندارد!",
|
||||||
|
PROJECT_CONTAINS_TASK_PHASES = "پروژه شامل فاز تسک است. لطفا ابتدا فاز تسک های این پروژه را حذف کنید."
|
||||||
}
|
}
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import { IPageFormat } from "../interfaces/IPagination";
|
|
||||||
|
|
||||||
export function buildPageFormat(
|
|
||||||
page: number,
|
|
||||||
limit: number,
|
|
||||||
totalItems: number,
|
|
||||||
baseUrl: string,
|
|
||||||
): IPageFormat {
|
|
||||||
const totalPages = Math.ceil(totalItems / limit);
|
|
||||||
|
|
||||||
const prevPage =
|
|
||||||
page > 1
|
|
||||||
? `${baseUrl}?page=${page - 1}&limit=${limit}`
|
|
||||||
: false;
|
|
||||||
|
|
||||||
const nextPage =
|
|
||||||
page < totalPages
|
|
||||||
? `${baseUrl}?page=${page + 1}&limit=${limit}`
|
|
||||||
: false;
|
|
||||||
|
|
||||||
return {
|
|
||||||
page,
|
|
||||||
limit,
|
|
||||||
totalItems,
|
|
||||||
totalPages,
|
|
||||||
prevPage,
|
|
||||||
nextPage,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import { IPageFormat } from "./IPagination";
|
|
||||||
|
|
||||||
export interface PaginatedResult<T> {
|
|
||||||
data: T[];
|
|
||||||
meta: IPageFormat;
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Controller, Get, Post, Patch, Delete, Param, Body, Query, Headers } from "@nestjs/common";
|
import { Controller, Get, Post, Patch, Delete, Param, Body, Query } from "@nestjs/common";
|
||||||
import { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiQuery } from "@nestjs/swagger";
|
import { ApiTags, ApiOperation, ApiResponse, ApiParam } from "@nestjs/swagger";
|
||||||
import { ProjectService } from "../providers/project.service";
|
import { ProjectService } from "../providers/project.service";
|
||||||
import { CreateProjectDto } from "../dto/project/create-project.dto";
|
import { CreateProjectDto } from "../dto/project/create-project.dto";
|
||||||
import { UpdateProjectDto } from "../dto/project/update-project.dto";
|
import { UpdateProjectDto } from "../dto/project/update-project.dto";
|
||||||
@@ -18,18 +18,9 @@ export class ProjectController {
|
|||||||
@Get()
|
@Get()
|
||||||
@PermissionsDec(PermissionEnum.PROJECT)
|
@PermissionsDec(PermissionEnum.PROJECT)
|
||||||
@ApiOperation({ summary: "Get all projects, optionally filtered by workspace" })
|
@ApiOperation({ summary: "Get all projects, optionally filtered by workspace" })
|
||||||
@ApiQuery({ name: "workspaceId", required: false, description: "Filter projects by workspace ID" })
|
|
||||||
@ApiResponse({ status: 200, description: "Paginated list of projects" })
|
@ApiResponse({ status: 200, description: "Paginated list of projects" })
|
||||||
findAll(
|
findAll(@Query() pagination: PaginationDto): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
||||||
@Query() pagination: PaginationDto,
|
return this.projectService.findAll(pagination);
|
||||||
@Query("workspaceId") workspaceId: string,
|
|
||||||
@Headers("host") host: string,
|
|
||||||
@Headers("x-forwarded-proto") proto?: string,
|
|
||||||
) {
|
|
||||||
const protocol = proto ?? "http";
|
|
||||||
const baseUrl = `${protocol}://${host}/task-manager/projects`;
|
|
||||||
if (workspaceId) return this.projectService.findByWorkspace(workspaceId, pagination, baseUrl);
|
|
||||||
return this.projectService.findAll(pagination, baseUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get(":id")
|
@Get(":id")
|
||||||
@@ -74,11 +65,15 @@ export class ProjectController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Get("/workspace/:wsId")
|
@Get("/workspace/:wsId")
|
||||||
@ApiOperation({summary: "Get projects of a specific workspace"})
|
@PermissionsDec(PermissionEnum.PROJECT)
|
||||||
|
@ApiOperation({ summary: "Get projects of a specific workspace" })
|
||||||
@ApiParam({ name: "wsId", description: "Workspace ID" })
|
@ApiParam({ name: "wsId", description: "Workspace ID" })
|
||||||
@ApiResponse({ status: 200, description: "received projects successfully!"})
|
@ApiResponse({ status: 200, description: "received projects successfully!" })
|
||||||
@ApiResponse({ status: 404, description: "WorkSpace not found" })
|
@ApiResponse({ status: 404, description: "WorkSpace not found" })
|
||||||
findByWorkspace(@Param("wsId") wsId: string): Promise<TMProject[]> {
|
findByWorkspace(
|
||||||
return this.findByWorkspace(wsId);
|
@Param("wsId") wsId: string,
|
||||||
|
@Query() pagination: PaginationDto,
|
||||||
|
): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
||||||
|
return this.projectService.findByWorkspace(wsId, pagination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ import { TMProject } from "../entities/project.entity";
|
|||||||
import { CreateProjectDto } from "../dto/project/create-project.dto";
|
import { CreateProjectDto } from "../dto/project/create-project.dto";
|
||||||
import { UpdateProjectDto } from "../dto/project/update-project.dto";
|
import { UpdateProjectDto } from "../dto/project/update-project.dto";
|
||||||
import { PaginationDto } from "../../../common/DTO/pagination.dto";
|
import { PaginationDto } from "../../../common/DTO/pagination.dto";
|
||||||
import { PaginatedResult } from "../../../common/interfaces/paginated-result.interface";
|
|
||||||
import { buildPageFormat } from "../../../common/helpers/pagination.helper";
|
|
||||||
import { User } from "../../users/entities/user.entity";
|
import { User } from "../../users/entities/user.entity";
|
||||||
import { ProjectMessage, WorkSpaceMessage } from "../../../common/enums/message.enum";
|
import { ProjectMessage, WorkSpaceMessage } from "../../../common/enums/message.enum";
|
||||||
import { WorkspaceService } from "./workspace.service";
|
import { WorkspaceService } from "./workspace.service";
|
||||||
@@ -21,37 +19,53 @@ export class ProjectService {
|
|||||||
private readonly userRepository: Repository<User>,
|
private readonly userRepository: Repository<User>,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async findAll(pagination: PaginationDto, baseUrl: string): Promise<PaginatedResult<TMProject>> {
|
async findAll(pagination: PaginationDto): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
||||||
const page = pagination.page ?? 1;
|
const page = pagination.page ?? 1;
|
||||||
const limit = pagination.limit ?? 10;
|
const limit = pagination.limit ?? 10;
|
||||||
const skip = (page - 1) * limit;
|
const skip = (page - 1) * limit;
|
||||||
|
|
||||||
const [data, totalItems] = await this.projectRepository.findAndCount({ skip, take: limit });
|
const [projects, count] = await this.projectRepository.findAndCount({
|
||||||
|
skip: skip,
|
||||||
|
take: limit,
|
||||||
|
relations: {
|
||||||
|
users: true,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
users: {
|
||||||
|
id: true,
|
||||||
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return { projects, count, paginate: true };
|
||||||
data,
|
|
||||||
meta: buildPageFormat(page, limit, totalItems, baseUrl),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async findByWorkspace(workspaceId: string, pagination: PaginationDto, baseUrl: string): Promise<PaginatedResult<TMProject>> {
|
async findByWorkspace(workspaceId: string, pagination: PaginationDto): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
|
||||||
await this.workspaceService.findOneOrFail(workspaceId);
|
await this.workspaceService.findOneOrFail(workspaceId);
|
||||||
|
|
||||||
const page = pagination.page ?? 1;
|
const page = pagination.page ?? 1;
|
||||||
const limit = pagination.limit ?? 10;
|
const limit = pagination.limit ?? 10;
|
||||||
const skip = (page - 1) * limit;
|
const skip = (page - 1) * limit;
|
||||||
|
|
||||||
const [data, totalItems] = await this.projectRepository.findAndCount({
|
const [projects, count] = await this.projectRepository.findAndCount({
|
||||||
where: { workspaceId },
|
where: { workspaceId },
|
||||||
relations: ["taskPhases", "users"],
|
relations: {
|
||||||
|
users: true,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
users: {
|
||||||
|
id: true,
|
||||||
|
firstName: true,
|
||||||
|
lastName: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
skip,
|
skip,
|
||||||
take: limit,
|
take: limit,
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return { projects, count, paginate: true };
|
||||||
data,
|
|
||||||
meta: buildPageFormat(page, limit, totalItems, baseUrl),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOneOrFail(id: string): Promise<TMProject> {
|
async findOneOrFail(id: string): Promise<TMProject> {
|
||||||
@@ -112,7 +126,26 @@ export class ProjectService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async remove(id: string): Promise<TMProject> {
|
async remove(id: string): Promise<TMProject> {
|
||||||
const project = await this.findOneOrFail(id);
|
const project = await this.projectRepository.findOne({
|
||||||
|
where: {
|
||||||
|
id,
|
||||||
|
},
|
||||||
|
relations: {
|
||||||
|
taskPhases: true,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
taskPhases: {
|
||||||
|
id: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!project) throw new NotFoundException(ProjectMessage.PROJECT_NOT_FOUND);
|
||||||
|
|
||||||
|
const taskPhases = project.taskPhases;
|
||||||
|
if (taskPhases !== undefined && taskPhases.length) {
|
||||||
|
throw new BadRequestException(ProjectMessage.PROJECT_CONTAINS_TASK_PHASES);
|
||||||
|
}
|
||||||
await this.projectRepository.delete(id);
|
await this.projectRepository.delete(id);
|
||||||
return project;
|
return project;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user