Add website static image slots with page grouping and bilingual captions.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
b991a60cbc
commit
1c7678ce67
@@ -0,0 +1,222 @@
|
||||
import { Transform, Type } from 'class-transformer';
|
||||
import {
|
||||
IsArray,
|
||||
IsIn,
|
||||
IsInt,
|
||||
IsOptional,
|
||||
IsString,
|
||||
Matches,
|
||||
Max,
|
||||
MaxLength,
|
||||
Min,
|
||||
MinLength,
|
||||
ValidateNested,
|
||||
} from 'class-validator';
|
||||
import {
|
||||
SPECIAL_GROUP_KEY_MESSAGE,
|
||||
SPECIAL_GROUP_KEY_PATTERN,
|
||||
} from '../../common/special-group-key';
|
||||
|
||||
const emptyToUndefined = ({ value }: { value: unknown }) => {
|
||||
if (value == null) return undefined;
|
||||
if (typeof value !== 'string') return value;
|
||||
const trimmed = value.trim();
|
||||
return trimmed === '' ? undefined : trimmed;
|
||||
};
|
||||
|
||||
export class WebsiteStaticImageItemInputDto {
|
||||
@IsString()
|
||||
imageMediaId!: string;
|
||||
|
||||
@IsOptional()
|
||||
@Transform(emptyToUndefined)
|
||||
@IsString()
|
||||
@MaxLength(255)
|
||||
title?: string;
|
||||
|
||||
@IsOptional()
|
||||
@Transform(emptyToUndefined)
|
||||
@IsString()
|
||||
@MaxLength(255)
|
||||
titleFa?: string;
|
||||
|
||||
@IsOptional()
|
||||
@Transform(emptyToUndefined)
|
||||
@IsString()
|
||||
@MaxLength(255)
|
||||
titleEn?: string;
|
||||
|
||||
@IsOptional()
|
||||
@Transform(emptyToUndefined)
|
||||
@IsString()
|
||||
@MaxLength(500)
|
||||
subtext?: string;
|
||||
|
||||
@IsOptional()
|
||||
@Transform(emptyToUndefined)
|
||||
@IsString()
|
||||
@MaxLength(2048)
|
||||
@Matches(/^(https?:\/\/[^\s]+|\/[^\s]*)$/i, {
|
||||
message: 'linkUrl must be an absolute or site-relative URL',
|
||||
})
|
||||
linkUrl?: string;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
sortOrder?: number;
|
||||
}
|
||||
|
||||
export class CreateWebsiteStaticImageSlotDto {
|
||||
@IsString()
|
||||
@MinLength(1)
|
||||
@MaxLength(100)
|
||||
@Matches(SPECIAL_GROUP_KEY_PATTERN, { message: SPECIAL_GROUP_KEY_MESSAGE })
|
||||
key!: string;
|
||||
|
||||
@IsString()
|
||||
@MinLength(1)
|
||||
@MaxLength(255)
|
||||
label!: string;
|
||||
|
||||
@IsIn(['single', 'list'])
|
||||
kind!: 'single' | 'list';
|
||||
|
||||
@IsOptional()
|
||||
@Transform(emptyToUndefined)
|
||||
@IsString()
|
||||
@Matches(/^[0-9]{1,3}:[0-9]{1,3}$/, {
|
||||
message: 'aspectRatio must look like 16:9',
|
||||
})
|
||||
aspectRatio?: string;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@Max(8000)
|
||||
recommendedWidth?: number;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@Max(24)
|
||||
itemCount?: number;
|
||||
|
||||
@IsOptional()
|
||||
@Transform(emptyToUndefined)
|
||||
@IsString()
|
||||
@MinLength(1)
|
||||
@MaxLength(100)
|
||||
@Matches(SPECIAL_GROUP_KEY_PATTERN, { message: SPECIAL_GROUP_KEY_MESSAGE })
|
||||
pageKey?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => WebsiteStaticImageItemInputDto)
|
||||
items?: WebsiteStaticImageItemInputDto[];
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsInt()
|
||||
sortOrder?: number;
|
||||
}
|
||||
|
||||
export class UpdateWebsiteStaticImageSlotDto {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MinLength(1)
|
||||
@MaxLength(100)
|
||||
@Matches(SPECIAL_GROUP_KEY_PATTERN, { message: SPECIAL_GROUP_KEY_MESSAGE })
|
||||
key?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MinLength(1)
|
||||
@MaxLength(255)
|
||||
label?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsIn(['single', 'list'])
|
||||
kind?: 'single' | 'list';
|
||||
|
||||
@IsOptional()
|
||||
@Transform(emptyToUndefined)
|
||||
@IsString()
|
||||
@Matches(/^[0-9]{1,3}:[0-9]{1,3}$/, {
|
||||
message: 'aspectRatio must look like 16:9',
|
||||
})
|
||||
aspectRatio?: string;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@Max(8000)
|
||||
recommendedWidth?: number | null;
|
||||
|
||||
@IsOptional()
|
||||
@Transform(({ value }) => {
|
||||
if (value === undefined) return undefined
|
||||
if (value === null || value === '') return null
|
||||
return Number(value)
|
||||
})
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
@Max(24)
|
||||
itemCount?: number | null;
|
||||
|
||||
@IsOptional()
|
||||
@Transform(emptyToUndefined)
|
||||
@IsString()
|
||||
@MinLength(1)
|
||||
@MaxLength(100)
|
||||
@Matches(SPECIAL_GROUP_KEY_PATTERN, { message: SPECIAL_GROUP_KEY_MESSAGE })
|
||||
pageKey?: string;
|
||||
|
||||
@IsOptional()
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => WebsiteStaticImageItemInputDto)
|
||||
items?: WebsiteStaticImageItemInputDto[];
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsInt()
|
||||
sortOrder?: number;
|
||||
}
|
||||
|
||||
export class ListWebsiteStaticImageSlotsDto {
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
page?: number;
|
||||
|
||||
@IsOptional()
|
||||
@Type(() => Number)
|
||||
@IsInt()
|
||||
@Min(1)
|
||||
pageSize?: number;
|
||||
|
||||
@IsOptional()
|
||||
@Transform(emptyToUndefined)
|
||||
@IsString()
|
||||
@MinLength(1)
|
||||
@MaxLength(100)
|
||||
@Matches(SPECIAL_GROUP_KEY_PATTERN, { message: SPECIAL_GROUP_KEY_MESSAGE })
|
||||
pageKey?: string;
|
||||
}
|
||||
|
||||
export class PublicWebsiteStaticImagesQueryDto {
|
||||
@IsOptional()
|
||||
@Transform(emptyToUndefined)
|
||||
@IsString()
|
||||
@MinLength(1)
|
||||
@MaxLength(100)
|
||||
@Matches(SPECIAL_GROUP_KEY_PATTERN, { message: SPECIAL_GROUP_KEY_MESSAGE })
|
||||
pageKey?: string;
|
||||
}
|
||||
Reference in New Issue
Block a user