mirror of
https://github.com/immich-app/immich.git
synced 2025-12-20 01:11:46 +03:00
fix: hide faces (#3352)
* fix: hide faces * remove unused variable * fix: work even if one fails * better style for hidden people * add hide face in the menu dropdown * add buttons to toggle visibility for all faces * add server test * close modal with escape key * fix: explore page * improve show & hide faces modal * keep name on people card * simplify layout * sticky app bar in show-hide page * fix format --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { AssetFaceEntity, PersonEntity } from '@app/infra/entities';
|
||||
import { Transform } from 'class-transformer';
|
||||
import { IsBoolean, IsOptional, IsString } from 'class-validator';
|
||||
import { Transform, Type } from 'class-transformer';
|
||||
import { IsArray, IsBoolean, IsNotEmpty, IsOptional, IsString, ValidateNested } from 'class-validator';
|
||||
import { toBoolean, ValidateUUID } from '../domain.util';
|
||||
|
||||
export class PersonUpdateDto {
|
||||
@@ -26,6 +26,43 @@ export class PersonUpdateDto {
|
||||
isHidden?: boolean;
|
||||
}
|
||||
|
||||
export class PeopleUpdateDto {
|
||||
@IsArray()
|
||||
@ValidateNested({ each: true })
|
||||
@Type(() => PeopleUpdateItem)
|
||||
people!: PeopleUpdateItem[];
|
||||
}
|
||||
|
||||
export class PeopleUpdateItem {
|
||||
/**
|
||||
* Person id.
|
||||
*/
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
id!: string;
|
||||
|
||||
/**
|
||||
* Person name.
|
||||
*/
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
* Asset is used to get the feature face thumbnail.
|
||||
*/
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
featureFaceAssetId?: string;
|
||||
|
||||
/**
|
||||
* Person visibility
|
||||
*/
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
isHidden?: boolean;
|
||||
}
|
||||
|
||||
export class MergePersonDto {
|
||||
@ValidateUUID({ each: true })
|
||||
ids!: string[];
|
||||
|
||||
@@ -188,6 +188,16 @@ describe(PersonService.name, () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateAll', () => {
|
||||
it('should throw an error when personId is invalid', async () => {
|
||||
personMock.getById.mockResolvedValue(null);
|
||||
await expect(
|
||||
sut.updatePeople(authStub.admin, { people: [{ id: 'person-1', name: 'Person 1' }] }),
|
||||
).resolves.toEqual([{ error: BulkIdErrorReason.UNKNOWN, id: 'person-1', success: false }]);
|
||||
expect(personMock.update).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('handlePersonCleanup', () => {
|
||||
it('should delete people without faces', async () => {
|
||||
personMock.getAllWithoutFaces.mockResolvedValue([personStub.noName]);
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
mapPerson,
|
||||
MergePersonDto,
|
||||
PeopleResponseDto,
|
||||
PeopleUpdateDto,
|
||||
PersonResponseDto,
|
||||
PersonSearchDto,
|
||||
PersonUpdateDto,
|
||||
@@ -96,6 +97,24 @@ export class PersonService {
|
||||
return mapPerson(person);
|
||||
}
|
||||
|
||||
async updatePeople(authUser: AuthUserDto, dto: PeopleUpdateDto): Promise<BulkIdResponseDto[]> {
|
||||
const results: BulkIdResponseDto[] = [];
|
||||
for (const person of dto.people) {
|
||||
try {
|
||||
await this.update(authUser, person.id, {
|
||||
isHidden: person.isHidden,
|
||||
name: person.name,
|
||||
featureFaceAssetId: person.featureFaceAssetId,
|
||||
}),
|
||||
results.push({ id: person.id, success: true });
|
||||
} catch (error: Error | any) {
|
||||
this.logger.error(`Unable to update ${person.id} : ${error}`, error?.stack);
|
||||
results.push({ id: person.id, success: false, error: BulkIdErrorReason.UNKNOWN });
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
async handlePersonCleanup() {
|
||||
const people = await this.repository.getAllWithoutFaces();
|
||||
for (const person of people) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
ImmichReadStream,
|
||||
MergePersonDto,
|
||||
PeopleResponseDto,
|
||||
PeopleUpdateDto,
|
||||
PersonResponseDto,
|
||||
PersonSearchDto,
|
||||
PersonService,
|
||||
@@ -32,6 +33,11 @@ export class PersonController {
|
||||
return this.service.getAll(authUser, withHidden);
|
||||
}
|
||||
|
||||
@Put()
|
||||
updatePeople(@AuthUser() authUser: AuthUserDto, @Body() dto: PeopleUpdateDto): Promise<BulkIdResponseDto[]> {
|
||||
return this.service.updatePeople(authUser, dto);
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
getPerson(@AuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<PersonResponseDto> {
|
||||
return this.service.getById(authUser, id);
|
||||
|
||||
Reference in New Issue
Block a user