filter/sort, file, person

This commit is contained in:
Philipinho
2026-03-08 03:15:49 +00:00
parent ac03a54ae6
commit 674b0ec64a
12 changed files with 982 additions and 59 deletions
+11 -5
View File
@@ -119,10 +119,10 @@ const typeOptionsSchemaMap: Record<BasePropertyTypeValue, z.ZodType> = {
export function validateTypeOptions(
type: BasePropertyTypeValue,
typeOptions: unknown,
): z.SafeParseReturnType<unknown, unknown> {
): z.ZodSafeParseResult<unknown> {
const schema = typeOptionsSchemaMap[type];
if (!schema) {
return { success: false, error: new z.ZodError([{ code: 'custom', message: `Unknown property type: ${type}`, path: ['type'] }]) } as z.SafeParseError<unknown>;
return { success: false, error: new z.ZodError([{ code: 'custom', message: `Unknown property type: ${type}`, path: ['type'] }]) } as z.ZodSafeParseError<unknown>;
}
return schema.safeParse(typeOptions ?? {});
}
@@ -146,7 +146,13 @@ const cellValueSchemaMap: Partial<Record<BasePropertyTypeValue, z.ZodType>> = {
[BasePropertyType.MULTI_SELECT]: z.array(z.string().uuid()),
[BasePropertyType.DATE]: z.string(),
[BasePropertyType.PERSON]: z.array(z.string().uuid()),
[BasePropertyType.FILE]: z.array(z.string().uuid()),
[BasePropertyType.FILE]: z.array(z.object({
id: z.string().uuid(),
fileName: z.string(),
mimeType: z.string().optional(),
fileSize: z.number().optional(),
filePath: z.string().optional(),
})),
[BasePropertyType.CHECKBOX]: z.boolean(),
[BasePropertyType.URL]: z.string().url(),
[BasePropertyType.EMAIL]: z.string().email(),
@@ -161,10 +167,10 @@ export function getCellValueSchema(
export function validateCellValue(
type: BasePropertyTypeValue,
value: unknown,
): z.SafeParseReturnType<unknown, unknown> {
): z.ZodSafeParseResult<unknown> {
const schema = cellValueSchemaMap[type];
if (!schema) {
return { success: false, error: new z.ZodError([{ code: 'custom', message: `Unknown property type: ${type}`, path: [] }]) } as z.SafeParseError<unknown>;
return { success: false, error: new z.ZodError([{ code: 'custom', message: `Unknown property type: ${type}`, path: [] }]) } as z.ZodSafeParseError<unknown>;
}
return schema.safeParse(value);
}
@@ -1,4 +1,5 @@
import { IsNotEmpty, IsObject, IsOptional, IsString, IsUUID } from 'class-validator';
import { IsNotEmpty, IsObject, IsOptional, IsString, IsUUID, IsArray, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';
export class UpdateRowDto {
@IsUUID()
@@ -27,6 +28,27 @@ export class RowIdDto {
baseId: string;
}
class FilterDto {
@IsUUID()
propertyId: string;
@IsString()
@IsNotEmpty()
operator: string;
@IsOptional()
value?: unknown;
}
class SortDto {
@IsUUID()
propertyId: string;
@IsString()
@IsNotEmpty()
direction: string;
}
export class ListRowsDto {
@IsUUID()
baseId: string;
@@ -34,6 +56,18 @@ export class ListRowsDto {
@IsOptional()
@IsUUID()
viewId?: string;
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => FilterDto)
filters?: FilterDto[];
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => SortDto)
sorts?: SortDto[];
}
export class ReorderRowDto {
@@ -93,7 +93,23 @@ export class BaseRowService {
}
async list(dto: ListRowsDto, pagination: PaginationOptions) {
return this.baseRowRepo.findByBaseId(dto.baseId, pagination);
const hasFilters = dto.filters && dto.filters.length > 0;
const hasSorts = dto.sorts && dto.sorts.length > 0;
if (!hasFilters && !hasSorts) {
return this.baseRowRepo.findByBaseId(dto.baseId, pagination);
}
const properties = await this.basePropertyRepo.findByBaseId(dto.baseId);
const propertyTypeMap = new Map(properties.map((p) => [p.id, p.type]));
return this.baseRowRepo.findByBaseIdFiltered(
dto.baseId,
dto.filters ?? [],
dto.sorts ?? [],
propertyTypeMap,
pagination,
);
}
async reorder(dto: ReorderRowDto) {