fix(api): add sort, search, visibility to knowledge entry query DTO (#533)
All checks were successful
ci/woodpecker/push/api Pipeline was successful

Co-authored-by: Jason Woltje <jason@diversecanvas.com>
Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #533.
This commit is contained in:
2026-02-27 05:16:30 +00:00
committed by jason.woltje
parent edcff6a0e0
commit 11f22a7e96
2 changed files with 39 additions and 5 deletions

View File

@@ -1,6 +1,6 @@
import { IsOptional, IsEnum, IsString, IsInt, Min, Max } from "class-validator"; import { IsOptional, IsEnum, IsString, IsInt, IsIn, Min, Max } from "class-validator";
import { Type } from "class-transformer"; import { Type } from "class-transformer";
import { EntryStatus } from "@prisma/client"; import { EntryStatus, Visibility } from "@prisma/client";
/** /**
* DTO for querying knowledge entries (list endpoint) * DTO for querying knowledge entries (list endpoint)
@@ -10,10 +10,28 @@ export class EntryQueryDto {
@IsEnum(EntryStatus, { message: "status must be a valid EntryStatus" }) @IsEnum(EntryStatus, { message: "status must be a valid EntryStatus" })
status?: EntryStatus; status?: EntryStatus;
@IsOptional()
@IsEnum(Visibility, { message: "visibility must be a valid Visibility" })
visibility?: Visibility;
@IsOptional() @IsOptional()
@IsString({ message: "tag must be a string" }) @IsString({ message: "tag must be a string" })
tag?: string; tag?: string;
@IsOptional()
@IsString({ message: "search must be a string" })
search?: string;
@IsOptional()
@IsIn(["updatedAt", "createdAt", "title"], {
message: "sortBy must be updatedAt, createdAt, or title",
})
sortBy?: "updatedAt" | "createdAt" | "title";
@IsOptional()
@IsIn(["asc", "desc"], { message: "sortOrder must be asc or desc" })
sortOrder?: "asc" | "desc";
@IsOptional() @IsOptional()
@Type(() => Number) @Type(() => Number)
@IsInt({ message: "page must be an integer" }) @IsInt({ message: "page must be an integer" })

View File

@@ -48,6 +48,10 @@ export class KnowledgeService {
where.status = query.status; where.status = query.status;
} }
if (query.visibility) {
where.visibility = query.visibility;
}
if (query.tag) { if (query.tag) {
where.tags = { where.tags = {
some: { some: {
@@ -58,6 +62,20 @@ export class KnowledgeService {
}; };
} }
if (query.search) {
where.OR = [
{ title: { contains: query.search, mode: "insensitive" } },
{ content: { contains: query.search, mode: "insensitive" } },
];
}
// Build orderBy
const sortField = query.sortBy ?? "updatedAt";
const sortDirection = query.sortOrder ?? "desc";
const orderBy: Prisma.KnowledgeEntryOrderByWithRelationInput = {
[sortField]: sortDirection,
};
// Get total count // Get total count
const total = await this.prisma.knowledgeEntry.count({ where }); const total = await this.prisma.knowledgeEntry.count({ where });
@@ -71,9 +89,7 @@ export class KnowledgeService {
}, },
}, },
}, },
orderBy: { orderBy,
updatedAt: "desc",
},
skip, skip,
take: limit, take: limit,
}); });