feat: tags (#11980)
* feat: tags * fix: folder tree icons * navigate to tag from detail panel * delete tag * Tag position and add tag button * Tag asset in detail panel * refactor form * feat: navigate to tag page from clicking on a tag * feat: delete tags from the tag page * refactor: moving tag section in detail panel and add + tag button * feat: tag asset action in detail panel * refactor add tag form * fdisable add tag button when there is no selection * feat: tag bulk endpoint * feat: tag colors * chore: clean up * chore: unit tests * feat: write tags to sidecar * Remove tag and auto focus on tag creation form opened * chore: regenerate migration * chore: linting * add color picker to tag edit form * fix: force render tags timeline on navigating back from asset viewer * feat: read tags from keywords * chore: clean up --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
@@ -140,7 +140,7 @@ export function mapAsset(entity: AssetEntity, options: AssetMapOptions = {}): As
|
||||
exifInfo: entity.exifInfo ? mapExif(entity.exifInfo) : undefined,
|
||||
smartInfo: entity.smartInfo ? mapSmartInfo(entity.smartInfo) : undefined,
|
||||
livePhotoVideoId: entity.livePhotoVideoId,
|
||||
tags: entity.tags?.map(mapTag),
|
||||
tags: entity.tags?.map((tag) => mapTag(tag)),
|
||||
people: peopleWithFaces(entity.faces),
|
||||
unassignedFaces: entity.faces?.filter((face) => !face.person).map((a) => mapFacesWithoutPerson(a)),
|
||||
checksum: entity.checksum.toString('base64'),
|
||||
|
||||
+44
-18
@@ -1,38 +1,64 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||
import { TagEntity, TagType } from 'src/entities/tag.entity';
|
||||
import { Optional } from 'src/validation';
|
||||
import { Transform } from 'class-transformer';
|
||||
import { IsHexColor, IsNotEmpty, IsString } from 'class-validator';
|
||||
import { TagEntity } from 'src/entities/tag.entity';
|
||||
import { Optional, ValidateUUID } from 'src/validation';
|
||||
|
||||
export class CreateTagDto {
|
||||
export class TagCreateDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
name!: string;
|
||||
|
||||
@IsEnum(TagType)
|
||||
@IsNotEmpty()
|
||||
@ApiProperty({ enumName: 'TagTypeEnum', enum: TagType })
|
||||
type!: TagType;
|
||||
@ValidateUUID({ optional: true, nullable: true })
|
||||
parentId?: string | null;
|
||||
|
||||
@IsHexColor()
|
||||
@Optional({ nullable: true, emptyToNull: true })
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export class UpdateTagDto {
|
||||
@IsString()
|
||||
@Optional()
|
||||
name?: string;
|
||||
export class TagUpdateDto {
|
||||
@Optional({ nullable: true, emptyToNull: true })
|
||||
@IsHexColor()
|
||||
@Transform(({ value }) => (typeof value === 'string' && value[0] !== '#' ? `#${value}` : value))
|
||||
color?: string | null;
|
||||
}
|
||||
|
||||
export class TagUpsertDto {
|
||||
@IsString({ each: true })
|
||||
@IsNotEmpty({ each: true })
|
||||
tags!: string[];
|
||||
}
|
||||
|
||||
export class TagBulkAssetsDto {
|
||||
@ValidateUUID({ each: true })
|
||||
tagIds!: string[];
|
||||
|
||||
@ValidateUUID({ each: true })
|
||||
assetIds!: string[];
|
||||
}
|
||||
|
||||
export class TagBulkAssetsResponseDto {
|
||||
@ApiProperty({ type: 'integer' })
|
||||
count!: number;
|
||||
}
|
||||
|
||||
export class TagResponseDto {
|
||||
id!: string;
|
||||
@ApiProperty({ enumName: 'TagTypeEnum', enum: TagType })
|
||||
type!: string;
|
||||
name!: string;
|
||||
userId!: string;
|
||||
value!: string;
|
||||
createdAt!: Date;
|
||||
updatedAt!: Date;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export function mapTag(entity: TagEntity): TagResponseDto {
|
||||
return {
|
||||
id: entity.id,
|
||||
type: entity.type,
|
||||
name: entity.name,
|
||||
userId: entity.userId,
|
||||
name: entity.value.split('/').at(-1) as string,
|
||||
value: entity.value,
|
||||
createdAt: entity.createdAt,
|
||||
updatedAt: entity.updatedAt,
|
||||
color: entity.color ?? undefined,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,6 +19,9 @@ export class TimeBucketDto {
|
||||
@ValidateUUID({ optional: true })
|
||||
personId?: string;
|
||||
|
||||
@ValidateUUID({ optional: true })
|
||||
tagId?: string;
|
||||
|
||||
@ValidateBoolean({ optional: true })
|
||||
isArchived?: boolean;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user