immich/server/src/dtos/search.dto.ts
Daniel Dietzler 5e9a7b17d9
fix(server): allow library id to be null in metadata search (#10512)
* fix: allow library id to be null in metadata search

* chore: open api
2024-06-20 16:02:05 -07:00

346 lines
6.5 KiB
TypeScript

import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { IsEnum, IsInt, IsNotEmpty, IsString, Max, Min } from 'class-validator';
import { AlbumResponseDto } from 'src/dtos/album.dto';
import { AssetResponseDto } from 'src/dtos/asset-response.dto';
import { AssetOrder } from 'src/entities/album.entity';
import { AssetType } from 'src/entities/asset.entity';
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation';
class BaseSearchDto {
@ValidateUUID({ optional: true, nullable: true })
libraryId?: string | null;
@IsString()
@IsNotEmpty()
@Optional()
deviceId?: string;
@IsEnum(AssetType)
@Optional()
@ApiProperty({ enumName: 'AssetTypeEnum', enum: AssetType })
type?: AssetType;
@ValidateBoolean({ optional: true })
isArchived?: boolean;
@ValidateBoolean({ optional: true })
@ApiProperty({ default: false })
withArchived?: boolean;
@ValidateBoolean({ optional: true })
isEncoded?: boolean;
@ValidateBoolean({ optional: true })
isFavorite?: boolean;
@ValidateBoolean({ optional: true })
isMotion?: boolean;
@ValidateBoolean({ optional: true })
isOffline?: boolean;
@ValidateBoolean({ optional: true })
isVisible?: boolean;
@ValidateBoolean({ optional: true })
withDeleted?: boolean;
@ValidateBoolean({ optional: true })
withExif?: boolean;
@ValidateDate({ optional: true })
createdBefore?: Date;
@ValidateDate({ optional: true })
createdAfter?: Date;
@ValidateDate({ optional: true })
updatedBefore?: Date;
@ValidateDate({ optional: true })
updatedAfter?: Date;
@ValidateDate({ optional: true })
trashedBefore?: Date;
@ValidateDate({ optional: true })
trashedAfter?: Date;
@ValidateDate({ optional: true })
takenBefore?: Date;
@ValidateDate({ optional: true })
takenAfter?: Date;
@IsString()
@IsNotEmpty()
@Optional()
city?: string;
@IsString()
@IsNotEmpty()
@Optional()
state?: string;
@IsString()
@IsNotEmpty()
@Optional()
country?: string;
@IsString()
@IsNotEmpty()
@Optional()
make?: string;
@IsString()
@IsNotEmpty()
@Optional()
model?: string;
@IsString()
@IsNotEmpty()
@Optional()
lensModel?: string;
@IsInt()
@Min(1)
@Type(() => Number)
@Optional()
page?: number;
@IsInt()
@Min(1)
@Max(1000)
@Type(() => Number)
@Optional()
size?: number;
@ValidateBoolean({ optional: true })
isNotInAlbum?: boolean;
@ValidateUUID({ each: true, optional: true })
personIds?: string[];
}
export class MetadataSearchDto extends BaseSearchDto {
@ValidateUUID({ optional: true })
id?: string;
@IsString()
@IsNotEmpty()
@Optional()
deviceAssetId?: string;
@IsString()
@IsNotEmpty()
@Optional()
checksum?: string;
@ValidateBoolean({ optional: true })
withStacked?: boolean;
@ValidateBoolean({ optional: true })
withPeople?: boolean;
@IsString()
@IsNotEmpty()
@Optional()
originalFileName?: string;
@IsString()
@IsNotEmpty()
@Optional()
originalPath?: string;
@IsString()
@IsNotEmpty()
@Optional()
previewPath?: string;
@IsString()
@IsNotEmpty()
@Optional()
thumbnailPath?: string;
@IsString()
@IsNotEmpty()
@Optional()
encodedVideoPath?: string;
@IsEnum(AssetOrder)
@Optional()
@ApiProperty({ enumName: 'AssetOrder', enum: AssetOrder })
order?: AssetOrder;
}
export class SmartSearchDto extends BaseSearchDto {
@IsString()
@IsNotEmpty()
query!: string;
}
export class SearchPlacesDto {
@IsString()
@IsNotEmpty()
name!: string;
}
export class SearchPeopleDto {
@IsString()
@IsNotEmpty()
name!: string;
@ValidateBoolean({ optional: true })
withHidden?: boolean;
}
export class PlacesResponseDto {
name!: string;
latitude!: number;
longitude!: number;
admin1name?: string;
admin2name?: string;
}
export function mapPlaces(place: GeodataPlacesEntity): PlacesResponseDto {
return {
name: place.name,
latitude: place.latitude,
longitude: place.longitude,
admin1name: place.admin1Name,
admin2name: place.admin2Name,
};
}
export enum SearchSuggestionType {
COUNTRY = 'country',
STATE = 'state',
CITY = 'city',
CAMERA_MAKE = 'camera-make',
CAMERA_MODEL = 'camera-model',
}
export class SearchSuggestionRequestDto {
@IsEnum(SearchSuggestionType)
@IsNotEmpty()
@ApiProperty({ enumName: 'SearchSuggestionType', enum: SearchSuggestionType })
type!: SearchSuggestionType;
@IsString()
@Optional()
country?: string;
@IsString()
@Optional()
state?: string;
@IsString()
@Optional()
make?: string;
@IsString()
@Optional()
model?: string;
}
class SearchFacetCountResponseDto {
@ApiProperty({ type: 'integer' })
count!: number;
value!: string;
}
class SearchFacetResponseDto {
fieldName!: string;
counts!: SearchFacetCountResponseDto[];
}
class SearchAlbumResponseDto {
@ApiProperty({ type: 'integer' })
total!: number;
@ApiProperty({ type: 'integer' })
count!: number;
items!: AlbumResponseDto[];
facets!: SearchFacetResponseDto[];
}
class SearchAssetResponseDto {
@ApiProperty({ type: 'integer' })
total!: number;
@ApiProperty({ type: 'integer' })
count!: number;
items!: AssetResponseDto[];
facets!: SearchFacetResponseDto[];
nextPage!: string | null;
}
export class SearchResponseDto {
albums!: SearchAlbumResponseDto;
assets!: SearchAssetResponseDto;
}
class SearchExploreItem {
value!: string;
data!: AssetResponseDto;
}
export class SearchExploreResponseDto {
fieldName!: string;
items!: SearchExploreItem[];
}
export class MapMarkerDto {
@ValidateBoolean({ optional: true })
isArchived?: boolean;
@ValidateBoolean({ optional: true })
isFavorite?: boolean;
@ValidateDate({ optional: true })
fileCreatedAfter?: Date;
@ValidateDate({ optional: true })
fileCreatedBefore?: Date;
@ValidateBoolean({ optional: true })
withPartners?: boolean;
@ValidateBoolean({ optional: true })
withSharedAlbums?: boolean;
}
export class MemoryLaneDto {
@IsInt()
@Type(() => Number)
@Max(31)
@Min(1)
@ApiProperty({ type: 'integer' })
day!: number;
@IsInt()
@Type(() => Number)
@Max(12)
@Min(1)
@ApiProperty({ type: 'integer' })
month!: number;
}
export class MapMarkerResponseDto {
@ApiProperty()
id!: string;
@ApiProperty({ format: 'double' })
lat!: number;
@ApiProperty({ format: 'double' })
lon!: number;
@ApiProperty()
city!: string | null;
@ApiProperty()
state!: string | null;
@ApiProperty()
country!: string | null;
}