mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
* Add Exif-Rating * Integrate star rating as own component * Add e2e tests for rating and validation * Rename component and async handleChangeRating * Display rating can be enabled in app settings * Correct i18n reference Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com> * Star rating: change from slider to buttons * Star rating for clarity * Design updates. * Renaming and code optimization * chore: clean up * chore: e2e formatting * light mode border and default value --------- Co-authored-by: Christoph Suter <christoph@suter-burri.ch> Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com> Co-authored-by: Mert <101130780+mertalev@users.noreply.github.com> Co-authored-by: Jason Rasmussen <jrasm91@gmail.com> Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
137 lines
2.8 KiB
TypeScript
137 lines
2.8 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 } from 'src/entities/asset.entity';
|
|
import { AssetStats } from 'src/interfaces/asset.interface';
|
|
import { Optional, 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;
|
|
|
|
@ValidateBoolean({ optional: true })
|
|
isArchived?: boolean;
|
|
|
|
@Optional()
|
|
@IsDateString()
|
|
dateTimeOriginal?: string;
|
|
|
|
@ValidateGPS()
|
|
@IsLatitude()
|
|
@IsNotEmpty()
|
|
latitude?: number;
|
|
|
|
@ValidateGPS()
|
|
@IsLongitude()
|
|
@IsNotEmpty()
|
|
longitude?: number;
|
|
|
|
@Optional()
|
|
@IsInt()
|
|
@Max(5)
|
|
@Min(0)
|
|
rating?: number;
|
|
}
|
|
|
|
export class AssetBulkUpdateDto extends UpdateAssetBase {
|
|
@ValidateUUID({ each: true })
|
|
ids!: string[];
|
|
|
|
@ValidateUUID({ optional: true })
|
|
stackParentId?: string;
|
|
|
|
@ValidateBoolean({ optional: true })
|
|
removeParent?: boolean;
|
|
|
|
@Optional()
|
|
duplicateId?: string | null;
|
|
}
|
|
|
|
export class UpdateAssetDto extends UpdateAssetBase {
|
|
@Optional()
|
|
@IsString()
|
|
description?: string;
|
|
}
|
|
|
|
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 {
|
|
REGENERATE_THUMBNAIL = 'regenerate-thumbnail',
|
|
REFRESH_METADATA = 'refresh-metadata',
|
|
TRANSCODE_VIDEO = 'transcode-video',
|
|
}
|
|
|
|
export class AssetJobsDto extends AssetIdsDto {
|
|
@ApiProperty({ enumName: 'AssetJobName', enum: AssetJobName })
|
|
@IsEnum(AssetJobName)
|
|
name!: AssetJobName;
|
|
}
|
|
|
|
export class AssetStatsDto {
|
|
@ValidateBoolean({ optional: true })
|
|
isArchived?: boolean;
|
|
|
|
@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),
|
|
};
|
|
};
|