refactor: changed functions to use pagination logic correctly

This commit is contained in:
2026-07-05 19:20:08 +03:30
parent a14bd490be
commit 9f61152d94
5 changed files with 63 additions and 69 deletions
+2 -1
View File
@@ -925,5 +925,6 @@ export const enum WorkSpaceMessage {
export const enum ProjectMessage {
PROJECT_EXISTS = "پروژه مورد نظر شما از قبل وجود دارد!",
PROJECT_NOT_FOUND = "پروژه مورد نظر شما وجود ندارد!"
PROJECT_NOT_FOUND = "پروژه مورد نظر شما وجود ندارد!",
PROJECT_CONTAINS_TASK_PHASES = "پروژه شامل فاز تسک است. لطفا ابتدا فاز تسک های این پروژه را حذف کنید."
}
-29
View File
@@ -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 { ApiTags, ApiOperation, ApiResponse, ApiParam, ApiQuery } from "@nestjs/swagger";
import { Controller, Get, Post, Patch, Delete, Param, Body, Query } from "@nestjs/common";
import { ApiTags, ApiOperation, ApiResponse, ApiParam } from "@nestjs/swagger";
import { ProjectService } from "../providers/project.service";
import { CreateProjectDto } from "../dto/project/create-project.dto";
import { UpdateProjectDto } from "../dto/project/update-project.dto";
@@ -18,18 +18,9 @@ export class ProjectController {
@Get()
@PermissionsDec(PermissionEnum.PROJECT)
@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" })
findAll(
@Query() pagination: PaginationDto,
@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);
findAll(@Query() pagination: PaginationDto): Promise<{ projects: TMProject[]; count: number; paginate: true }> {
return this.projectService.findAll(pagination);
}
@Get(":id")
@@ -74,11 +65,15 @@ export class ProjectController {
}
@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" })
@ApiResponse({ status: 200, description: "received projects successfully!"})
@ApiResponse({ status: 200, description: "received projects successfully!" })
@ApiResponse({ status: 404, description: "WorkSpace not found" })
findByWorkspace(@Param("wsId") wsId: string): Promise<TMProject[]> {
return this.findByWorkspace(wsId);
findByWorkspace(
@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 { UpdateProjectDto } from "../dto/project/update-project.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 { ProjectMessage, WorkSpaceMessage } from "../../../common/enums/message.enum";
import { WorkspaceService } from "./workspace.service";
@@ -21,37 +19,53 @@ export class ProjectService {
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 limit = pagination.limit ?? 10;
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 {
data,
meta: buildPageFormat(page, limit, totalItems, baseUrl),
};
return { projects, count, paginate: true };
}
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);
const page = pagination.page ?? 1;
const limit = pagination.limit ?? 10;
const skip = (page - 1) * limit;
const [data, totalItems] = await this.projectRepository.findAndCount({
const [projects, count] = await this.projectRepository.findAndCount({
where: { workspaceId },
relations: ["taskPhases", "users"],
relations: {
users: true,
},
select: {
users: {
id: true,
firstName: true,
lastName: true,
},
},
skip,
take: limit,
});
return {
data,
meta: buildPageFormat(page, limit, totalItems, baseUrl),
};
return { projects, count, paginate: true };
}
async findOneOrFail(id: string): Promise<TMProject> {
@@ -112,7 +126,26 @@ export class ProjectService {
}
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);
return project;
}