mirror of
https://github.com/immich-app/immich.git
synced 2025-06-14 21:38:26 +02:00
* feat: private view * pr feedback * sql generation * feat: visibility column * fix: set visibility value as the same as the still part after unlinked live photos * fix: test * pr feedback
135 lines
2.9 KiB
TypeScript
135 lines
2.9 KiB
TypeScript
import { ApiProperty } from '@nestjs/swagger';
|
|
import { Type } from 'class-transformer';
|
|
import {
|
|
IsDateString,
|
|
IsEnum,
|
|
IsInt,
|
|
IsLatitude,
|
|
IsLongitude,
|
|
IsNotEmpty,
|
|
IsPositive,
|
|
IsString,
|
|
Max,
|
|
Min,
|
|
ValidateIf,
|
|
} from 'class-validator';
|
|
import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
|
import { AssetType, AssetVisibility } from 'src/enum';
|
|
import { AssetStats } from 'src/repositories/asset.repository';
|
|
import { Optional, ValidateAssetVisibility, ValidateBoolean, ValidateUUID } from 'src/validation';
|
|
|
|
export class DeviceIdDto {
|
|
@IsNotEmpty()
|
|
@IsString()
|
|
deviceId!: string;
|
|
}
|
|
|
|
const hasGPS = (o: { latitude: undefined; longitude: undefined }) =>
|
|
o.latitude !== undefined || o.longitude !== undefined;
|
|
const ValidateGPS = () => ValidateIf(hasGPS);
|
|
|
|
export class UpdateAssetBase {
|
|
@ValidateBoolean({ optional: true })
|
|
isFavorite?: boolean;
|
|
|
|
@ValidateAssetVisibility({ optional: true })
|
|
visibility?: AssetVisibility;
|
|
|
|
@Optional()
|
|
@IsDateString()
|
|
dateTimeOriginal?: string;
|
|
|
|
@ValidateGPS()
|
|
@IsLatitude()
|
|
@IsNotEmpty()
|
|
latitude?: number;
|
|
|
|
@ValidateGPS()
|
|
@IsLongitude()
|
|
@IsNotEmpty()
|
|
longitude?: number;
|
|
|
|
@Optional()
|
|
@IsInt()
|
|
@Max(5)
|
|
@Min(-1)
|
|
rating?: number;
|
|
}
|
|
|
|
export class AssetBulkUpdateDto extends UpdateAssetBase {
|
|
@ValidateUUID({ each: true })
|
|
ids!: string[];
|
|
|
|
@Optional()
|
|
duplicateId?: string | null;
|
|
}
|
|
|
|
export class UpdateAssetDto extends UpdateAssetBase {
|
|
@Optional()
|
|
@IsString()
|
|
description?: string;
|
|
|
|
@ValidateUUID({ optional: true, nullable: true })
|
|
livePhotoVideoId?: string | null;
|
|
}
|
|
|
|
export class RandomAssetsDto {
|
|
@Optional()
|
|
@IsInt()
|
|
@IsPositive()
|
|
@Type(() => Number)
|
|
count?: number;
|
|
}
|
|
|
|
export class AssetBulkDeleteDto extends BulkIdsDto {
|
|
@ValidateBoolean({ optional: true })
|
|
force?: boolean;
|
|
}
|
|
|
|
export class AssetIdsDto {
|
|
@ValidateUUID({ each: true })
|
|
assetIds!: string[];
|
|
}
|
|
|
|
export enum AssetJobName {
|
|
REFRESH_FACES = 'refresh-faces',
|
|
REFRESH_METADATA = 'refresh-metadata',
|
|
REGENERATE_THUMBNAIL = 'regenerate-thumbnail',
|
|
TRANSCODE_VIDEO = 'transcode-video',
|
|
}
|
|
|
|
export class AssetJobsDto extends AssetIdsDto {
|
|
@ApiProperty({ enumName: 'AssetJobName', enum: AssetJobName })
|
|
@IsEnum(AssetJobName)
|
|
name!: AssetJobName;
|
|
}
|
|
|
|
export class AssetStatsDto {
|
|
@ValidateAssetVisibility({ optional: true })
|
|
visibility?: AssetVisibility;
|
|
|
|
@ValidateBoolean({ optional: true })
|
|
isFavorite?: boolean;
|
|
|
|
@ValidateBoolean({ optional: true })
|
|
isTrashed?: boolean;
|
|
}
|
|
|
|
export class AssetStatsResponseDto {
|
|
@ApiProperty({ type: 'integer' })
|
|
images!: number;
|
|
|
|
@ApiProperty({ type: 'integer' })
|
|
videos!: number;
|
|
|
|
@ApiProperty({ type: 'integer' })
|
|
total!: number;
|
|
}
|
|
|
|
export const mapStats = (stats: AssetStats): AssetStatsResponseDto => {
|
|
return {
|
|
images: stats[AssetType.IMAGE],
|
|
videos: stats[AssetType.VIDEO],
|
|
total: Object.values(stats).reduce((total, value) => total + value, 0),
|
|
};
|
|
};
|