mirror of
https://github.com/immich-app/immich.git
synced 2024-12-29 11:24:37 +02:00
fix(server, web): reassigning faces (#9265)
* fix: reassiging faces * fix: rename
This commit is contained in:
parent
090592e5ae
commit
cf79bc9ed7
@ -5,7 +5,7 @@ import { ExifEntity } from 'src/entities/exif.entity';
|
||||
import { ReverseGeocodeResult } from 'src/interfaces/metadata.interface';
|
||||
import { AssetSearchOptions, SearchExploreItem } from 'src/interfaces/search.interface';
|
||||
import { Paginated, PaginationOptions } from 'src/utils/pagination';
|
||||
import { FindOptionsRelations, FindOptionsSelect } from 'typeorm';
|
||||
import { FindOptionsOrder, FindOptionsRelations, FindOptionsSelect } from 'typeorm';
|
||||
|
||||
export type AssetStats = Record<AssetType, number>;
|
||||
|
||||
@ -162,7 +162,11 @@ export interface IAssetRepository {
|
||||
getUploadAssetIdByChecksum(ownerId: string, checksum: Buffer): Promise<string | undefined>;
|
||||
getByAlbumId(pagination: PaginationOptions, albumId: string): Paginated<AssetEntity>;
|
||||
getByUserId(pagination: PaginationOptions, userId: string, options?: AssetSearchOptions): Paginated<AssetEntity>;
|
||||
getById(id: string, relations?: FindOptionsRelations<AssetEntity>): Promise<AssetEntity | null>;
|
||||
getById(
|
||||
id: string,
|
||||
relations?: FindOptionsRelations<AssetEntity>,
|
||||
order?: FindOptionsOrder<AssetEntity>,
|
||||
): Promise<AssetEntity | null>;
|
||||
getWithout(pagination: PaginationOptions, property: WithoutProperty): Paginated<AssetEntity>;
|
||||
getWith(pagination: PaginationOptions, property: WithProperty, libraryId?: string): Paginated<AssetEntity>;
|
||||
getRandom(userId: string, count: number): Promise<AssetEntity[]>;
|
||||
|
@ -85,6 +85,8 @@ FROM
|
||||
LEFT JOIN "person" "AssetFaceEntity__AssetFaceEntity_person" ON "AssetFaceEntity__AssetFaceEntity_person"."id" = "AssetFaceEntity"."personId"
|
||||
WHERE
|
||||
(("AssetFaceEntity"."assetId" = $1))
|
||||
ORDER BY
|
||||
"AssetFaceEntity"."boundingBoxX1" ASC
|
||||
|
||||
-- PersonRepository.getFaceById
|
||||
SELECT DISTINCT
|
||||
|
@ -36,6 +36,7 @@ import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { Paginated, PaginationMode, PaginationOptions, paginate, paginatedBuilder } from 'src/utils/pagination';
|
||||
import {
|
||||
Brackets,
|
||||
FindOptionsOrder,
|
||||
FindOptionsRelations,
|
||||
FindOptionsSelect,
|
||||
FindOptionsWhere,
|
||||
@ -236,12 +237,17 @@ export class AssetRepository implements IAssetRepository {
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID] })
|
||||
getById(id: string, relations: FindOptionsRelations<AssetEntity>): Promise<AssetEntity | null> {
|
||||
getById(
|
||||
id: string,
|
||||
relations: FindOptionsRelations<AssetEntity>,
|
||||
order?: FindOptionsOrder<AssetEntity>,
|
||||
): Promise<AssetEntity | null> {
|
||||
return this.repository.findOne({
|
||||
where: { id },
|
||||
relations,
|
||||
// We are specifically asking for this asset. Return it even if it is soft deleted
|
||||
withDeleted: true,
|
||||
order,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,9 @@ export class PersonRepository implements IPersonRepository {
|
||||
relations: {
|
||||
person: true,
|
||||
},
|
||||
order: {
|
||||
boundingBoxX1: 'ASC',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -227,21 +227,29 @@ export class AssetService {
|
||||
async get(auth: AuthDto, id: string): Promise<AssetResponseDto | SanitizedAssetResponseDto> {
|
||||
await this.access.requirePermission(auth, Permission.ASSET_READ, id);
|
||||
|
||||
const asset = await this.assetRepository.getById(id, {
|
||||
exifInfo: true,
|
||||
tags: true,
|
||||
sharedLinks: true,
|
||||
smartInfo: true,
|
||||
owner: true,
|
||||
faces: {
|
||||
person: true,
|
||||
},
|
||||
stack: {
|
||||
assets: {
|
||||
exifInfo: true,
|
||||
const asset = await this.assetRepository.getById(
|
||||
id,
|
||||
{
|
||||
exifInfo: true,
|
||||
tags: true,
|
||||
sharedLinks: true,
|
||||
smartInfo: true,
|
||||
owner: true,
|
||||
faces: {
|
||||
person: true,
|
||||
},
|
||||
stack: {
|
||||
assets: {
|
||||
exifInfo: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
{
|
||||
faces: {
|
||||
boundingBoxX1: 'ASC',
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (!asset) {
|
||||
throw new BadRequestException('Asset not found');
|
||||
|
@ -36,6 +36,7 @@
|
||||
let selectedPersonToReassign: Record<string, PersonResponseDto> = {};
|
||||
let selectedPersonToCreate: Record<string, string> = {};
|
||||
let editedPerson: PersonResponseDto;
|
||||
let editedFace: AssetFaceResponseDto;
|
||||
|
||||
// loading spinners
|
||||
let isShowLoadingDone = false;
|
||||
@ -155,24 +156,23 @@
|
||||
};
|
||||
|
||||
const handleCreatePerson = (newFeaturePhoto: string | null) => {
|
||||
const personToUpdate = peopleWithFaces.find((face) => face.person?.id === editedPerson.id);
|
||||
if (newFeaturePhoto && personToUpdate) {
|
||||
selectedPersonToCreate[personToUpdate.id] = newFeaturePhoto;
|
||||
if (newFeaturePhoto) {
|
||||
selectedPersonToCreate[editedFace.id] = newFeaturePhoto;
|
||||
}
|
||||
showSelectedFaces = false;
|
||||
};
|
||||
|
||||
const handleReassignFace = (person: PersonResponseDto | null) => {
|
||||
const personToUpdate = peopleWithFaces.find((face) => face.person?.id === editedPerson.id);
|
||||
if (person && personToUpdate) {
|
||||
selectedPersonToReassign[personToUpdate.id] = person;
|
||||
showSelectedFaces = false;
|
||||
if (person) {
|
||||
selectedPersonToReassign[editedFace.id] = person;
|
||||
}
|
||||
showSelectedFaces = false;
|
||||
};
|
||||
|
||||
const handlePersonPicker = (person: PersonResponseDto | null) => {
|
||||
if (person) {
|
||||
editedPerson = person;
|
||||
const handleFacePicker = (face: AssetFaceResponseDto) => {
|
||||
if (face.person) {
|
||||
editedFace = face;
|
||||
editedPerson = face.person;
|
||||
showSelectedFaces = true;
|
||||
}
|
||||
};
|
||||
@ -285,7 +285,7 @@
|
||||
size="18"
|
||||
padding="1"
|
||||
class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform"
|
||||
on:click={() => handlePersonPicker(face.person)}
|
||||
on:click={() => handleFacePicker(face)}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user