mirror of
https://github.com/KevinMidboe/immich.git
synced 2025-10-29 17:40:28 +00:00
refactor(server): tags (#2589)
* refactor: tags * chore: open api * chore: unused import * feat: add/remove/get tag assets * chore: open api * chore: finish tag tests for add/remove assets
This commit is contained in:
@@ -7,6 +7,7 @@ import { PersonEntity } from './person.entity';
|
||||
import { SharedLinkEntity } from './shared-link.entity';
|
||||
import { SmartInfoEntity } from './smart-info.entity';
|
||||
import { SystemConfigEntity } from './system-config.entity';
|
||||
import { TagEntity } from './tag.entity';
|
||||
import { UserTokenEntity } from './user-token.entity';
|
||||
import { UserEntity } from './user.entity';
|
||||
|
||||
@@ -34,6 +35,7 @@ export const databaseEntities = [
|
||||
SharedLinkEntity,
|
||||
SmartInfoEntity,
|
||||
SystemConfigEntity,
|
||||
TagEntity,
|
||||
UserEntity,
|
||||
UserTokenEntity,
|
||||
];
|
||||
|
||||
@@ -21,7 +21,7 @@ export class TagEntity {
|
||||
userId!: string;
|
||||
|
||||
@Column({ type: 'uuid', comment: 'The new renamed tagId', nullable: true })
|
||||
renameTagId!: string;
|
||||
renameTagId!: string | null;
|
||||
|
||||
@ManyToMany(() => AssetEntity, (asset) => asset.tags)
|
||||
assets!: AssetEntity[];
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
ISmartInfoRepository,
|
||||
IStorageRepository,
|
||||
ISystemConfigRepository,
|
||||
ITagRepository,
|
||||
IUserRepository,
|
||||
IUserTokenRepository,
|
||||
} from '@app/domain';
|
||||
@@ -45,6 +46,7 @@ import {
|
||||
SharedLinkRepository,
|
||||
SmartInfoRepository,
|
||||
SystemConfigRepository,
|
||||
TagRepository,
|
||||
TypesenseRepository,
|
||||
UserRepository,
|
||||
UserTokenRepository,
|
||||
@@ -68,6 +70,7 @@ const providers: Provider[] = [
|
||||
{ provide: ISmartInfoRepository, useClass: SmartInfoRepository },
|
||||
{ provide: IStorageRepository, useClass: FilesystemProvider },
|
||||
{ provide: ISystemConfigRepository, useClass: SystemConfigRepository },
|
||||
{ provide: ITagRepository, useClass: TagRepository },
|
||||
{ provide: IUserRepository, useClass: UserRepository },
|
||||
{ provide: IUserTokenRepository, useClass: UserTokenRepository },
|
||||
];
|
||||
|
||||
@@ -14,6 +14,7 @@ export * from './person.repository';
|
||||
export * from './shared-link.repository';
|
||||
export * from './smart-info.repository';
|
||||
export * from './system-config.repository';
|
||||
export * from './tag.repository';
|
||||
export * from './typesense.repository';
|
||||
export * from './user-token.repository';
|
||||
export * from './user.repository';
|
||||
|
||||
123
server/libs/infra/src/repositories/tag.repository.ts
Normal file
123
server/libs/infra/src/repositories/tag.repository.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
import { ITagRepository } from '@app/domain';
|
||||
import { AssetEntity, TagEntity } from '@app/infra/entities';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
@Injectable()
|
||||
export class TagRepository implements ITagRepository {
|
||||
constructor(
|
||||
@InjectRepository(AssetEntity) private assetRepository: Repository<AssetEntity>,
|
||||
@InjectRepository(TagEntity) private repository: Repository<TagEntity>,
|
||||
) {}
|
||||
|
||||
getById(userId: string, id: string): Promise<TagEntity | null> {
|
||||
return this.repository.findOne({
|
||||
where: {
|
||||
id,
|
||||
userId,
|
||||
},
|
||||
relations: {
|
||||
user: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getAll(userId: string): Promise<TagEntity[]> {
|
||||
return this.repository.find({ where: { userId } });
|
||||
}
|
||||
|
||||
create(tag: Partial<TagEntity>): Promise<TagEntity> {
|
||||
return this.save(tag);
|
||||
}
|
||||
|
||||
update(tag: Partial<TagEntity>): Promise<TagEntity> {
|
||||
return this.save(tag);
|
||||
}
|
||||
|
||||
async remove(tag: TagEntity): Promise<void> {
|
||||
await this.repository.remove(tag);
|
||||
}
|
||||
|
||||
async getAssets(userId: string, tagId: string): Promise<AssetEntity[]> {
|
||||
return this.assetRepository.find({
|
||||
where: {
|
||||
tags: {
|
||||
userId,
|
||||
id: tagId,
|
||||
},
|
||||
},
|
||||
relations: {
|
||||
exifInfo: true,
|
||||
tags: true,
|
||||
faces: {
|
||||
person: true,
|
||||
},
|
||||
},
|
||||
order: {
|
||||
createdAt: 'ASC',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async addAssets(userId: string, id: string, assetIds: string[]): Promise<void> {
|
||||
for (const assetId of assetIds) {
|
||||
const asset = await this.assetRepository.findOneOrFail({
|
||||
where: {
|
||||
ownerId: userId,
|
||||
id: assetId,
|
||||
},
|
||||
relations: {
|
||||
tags: true,
|
||||
},
|
||||
});
|
||||
asset.tags.push({ id } as TagEntity);
|
||||
await this.assetRepository.save(asset);
|
||||
}
|
||||
}
|
||||
|
||||
async removeAssets(userId: string, id: string, assetIds: string[]): Promise<void> {
|
||||
for (const assetId of assetIds) {
|
||||
const asset = await this.assetRepository.findOneOrFail({
|
||||
where: {
|
||||
ownerId: userId,
|
||||
id: assetId,
|
||||
},
|
||||
relations: {
|
||||
tags: true,
|
||||
},
|
||||
});
|
||||
asset.tags = asset.tags.filter((tag) => tag.id !== id);
|
||||
await this.assetRepository.save(asset);
|
||||
}
|
||||
}
|
||||
|
||||
hasAsset(userId: string, tagId: string, assetId: string): Promise<boolean> {
|
||||
return this.repository.exist({
|
||||
where: {
|
||||
id: tagId,
|
||||
userId,
|
||||
assets: {
|
||||
id: assetId,
|
||||
},
|
||||
},
|
||||
relations: {
|
||||
assets: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
hasName(userId: string, name: string): Promise<boolean> {
|
||||
return this.repository.exist({
|
||||
where: {
|
||||
name,
|
||||
userId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private async save(tag: Partial<TagEntity>): Promise<TagEntity> {
|
||||
const { id } = await this.repository.save(tag);
|
||||
return this.repository.findOneOrFail({ where: { id }, relations: { user: true } });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user