mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-02 18:47:07 -05: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:
		
							parent
							
								
									c40aa4399b
								
							
						
					
					
						commit
						ed64c91da6
					
				
							
								
								
									
										132
									
								
								cli/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										132
									
								
								cli/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							@ -1802,6 +1802,50 @@ export interface PeopleResponseDto {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    'people': Array<PersonResponseDto>;
 | 
					    'people': Array<PersonResponseDto>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface PeopleUpdateDto
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface PeopleUpdateDto {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {Array<PeopleUpdateItem>}
 | 
				
			||||||
 | 
					     * @memberof PeopleUpdateDto
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'people': Array<PeopleUpdateItem>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface PeopleUpdateItem
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface PeopleUpdateItem {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Person id.
 | 
				
			||||||
 | 
					     * @type {string}
 | 
				
			||||||
 | 
					     * @memberof PeopleUpdateItem
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'id': string;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Person name.
 | 
				
			||||||
 | 
					     * @type {string}
 | 
				
			||||||
 | 
					     * @memberof PeopleUpdateItem
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'name'?: string;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Asset is used to get the feature face thumbnail.
 | 
				
			||||||
 | 
					     * @type {string}
 | 
				
			||||||
 | 
					     * @memberof PeopleUpdateItem
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'featureFaceAssetId'?: string;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Person visibility
 | 
				
			||||||
 | 
					     * @type {boolean}
 | 
				
			||||||
 | 
					     * @memberof PeopleUpdateItem
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'isHidden'?: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 
 | 
					 * 
 | 
				
			||||||
 * @export
 | 
					 * @export
 | 
				
			||||||
@ -8896,6 +8940,50 @@ export const PersonApiAxiosParamCreator = function (configuration?: Configuratio
 | 
				
			|||||||
                options: localVarRequestOptions,
 | 
					                options: localVarRequestOptions,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {PeopleUpdateDto} peopleUpdateDto 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        updatePeople: async (peopleUpdateDto: PeopleUpdateDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
 | 
				
			||||||
 | 
					            // verify required parameter 'peopleUpdateDto' is not null or undefined
 | 
				
			||||||
 | 
					            assertParamExists('updatePeople', 'peopleUpdateDto', peopleUpdateDto)
 | 
				
			||||||
 | 
					            const localVarPath = `/person`;
 | 
				
			||||||
 | 
					            // use dummy base URL string because the URL constructor only accepts absolute URLs.
 | 
				
			||||||
 | 
					            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
 | 
				
			||||||
 | 
					            let baseOptions;
 | 
				
			||||||
 | 
					            if (configuration) {
 | 
				
			||||||
 | 
					                baseOptions = configuration.baseOptions;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options};
 | 
				
			||||||
 | 
					            const localVarHeaderParameter = {} as any;
 | 
				
			||||||
 | 
					            const localVarQueryParameter = {} as any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication cookie required
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication api_key required
 | 
				
			||||||
 | 
					            await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication bearer required
 | 
				
			||||||
 | 
					            // http bearer authentication required
 | 
				
			||||||
 | 
					            await setBearerAuthToObject(localVarHeaderParameter, configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            localVarHeaderParameter['Content-Type'] = 'application/json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            setSearchParams(localVarUrlObj, localVarQueryParameter);
 | 
				
			||||||
 | 
					            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
 | 
				
			||||||
 | 
					            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
 | 
				
			||||||
 | 
					            localVarRequestOptions.data = serializeDataIfNeeded(peopleUpdateDto, localVarRequestOptions, configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                url: toPathString(localVarUrlObj),
 | 
				
			||||||
 | 
					                options: localVarRequestOptions,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {string} id 
 | 
					         * @param {string} id 
 | 
				
			||||||
@ -9005,6 +9093,16 @@ export const PersonApiFp = function(configuration?: Configuration) {
 | 
				
			|||||||
            const localVarAxiosArgs = await localVarAxiosParamCreator.mergePerson(id, mergePersonDto, options);
 | 
					            const localVarAxiosArgs = await localVarAxiosParamCreator.mergePerson(id, mergePersonDto, options);
 | 
				
			||||||
            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
					            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {PeopleUpdateDto} peopleUpdateDto 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        async updatePeople(peopleUpdateDto: PeopleUpdateDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<BulkIdResponseDto>>> {
 | 
				
			||||||
 | 
					            const localVarAxiosArgs = await localVarAxiosParamCreator.updatePeople(peopleUpdateDto, options);
 | 
				
			||||||
 | 
					            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {string} id 
 | 
					         * @param {string} id 
 | 
				
			||||||
@ -9071,6 +9169,15 @@ export const PersonApiFactory = function (configuration?: Configuration, basePat
 | 
				
			|||||||
        mergePerson(requestParameters: PersonApiMergePersonRequest, options?: AxiosRequestConfig): AxiosPromise<Array<BulkIdResponseDto>> {
 | 
					        mergePerson(requestParameters: PersonApiMergePersonRequest, options?: AxiosRequestConfig): AxiosPromise<Array<BulkIdResponseDto>> {
 | 
				
			||||||
            return localVarFp.mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(axios, basePath));
 | 
					            return localVarFp.mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(axios, basePath));
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        updatePeople(requestParameters: PersonApiUpdatePeopleRequest, options?: AxiosRequestConfig): AxiosPromise<Array<BulkIdResponseDto>> {
 | 
				
			||||||
 | 
					            return localVarFp.updatePeople(requestParameters.peopleUpdateDto, options).then((request) => request(axios, basePath));
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {PersonApiUpdatePersonRequest} requestParameters Request parameters.
 | 
					         * @param {PersonApiUpdatePersonRequest} requestParameters Request parameters.
 | 
				
			||||||
@ -9160,6 +9267,20 @@ export interface PersonApiMergePersonRequest {
 | 
				
			|||||||
    readonly mergePersonDto: MergePersonDto
 | 
					    readonly mergePersonDto: MergePersonDto
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Request parameters for updatePeople operation in PersonApi.
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface PersonApiUpdatePeopleRequest
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface PersonApiUpdatePeopleRequest {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {PeopleUpdateDto}
 | 
				
			||||||
 | 
					     * @memberof PersonApiUpdatePeople
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    readonly peopleUpdateDto: PeopleUpdateDto
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Request parameters for updatePerson operation in PersonApi.
 | 
					 * Request parameters for updatePerson operation in PersonApi.
 | 
				
			||||||
 * @export
 | 
					 * @export
 | 
				
			||||||
@ -9243,6 +9364,17 @@ export class PersonApi extends BaseAPI {
 | 
				
			|||||||
        return PersonApiFp(this.configuration).mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(this.axios, this.basePath));
 | 
					        return PersonApiFp(this.configuration).mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(this.axios, this.basePath));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
 | 
				
			||||||
 | 
					     * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					     * @throws {RequiredError}
 | 
				
			||||||
 | 
					     * @memberof PersonApi
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public updatePeople(requestParameters: PersonApiUpdatePeopleRequest, options?: AxiosRequestConfig) {
 | 
				
			||||||
 | 
					        return PersonApiFp(this.configuration).updatePeople(requestParameters.peopleUpdateDto, options).then((request) => request(this.axios, this.basePath));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 
 | 
					     * 
 | 
				
			||||||
     * @param {PersonApiUpdatePersonRequest} requestParameters Request parameters.
 | 
					     * @param {PersonApiUpdatePersonRequest} requestParameters Request parameters.
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										6
									
								
								mobile/openapi/.openapi-generator/FILES
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								mobile/openapi/.openapi-generator/FILES
									
									
									
										generated
									
									
									
								
							@ -72,6 +72,8 @@ doc/OAuthConfigDto.md
 | 
				
			|||||||
doc/OAuthConfigResponseDto.md
 | 
					doc/OAuthConfigResponseDto.md
 | 
				
			||||||
doc/PartnerApi.md
 | 
					doc/PartnerApi.md
 | 
				
			||||||
doc/PeopleResponseDto.md
 | 
					doc/PeopleResponseDto.md
 | 
				
			||||||
 | 
					doc/PeopleUpdateDto.md
 | 
				
			||||||
 | 
					doc/PeopleUpdateItem.md
 | 
				
			||||||
doc/PersonApi.md
 | 
					doc/PersonApi.md
 | 
				
			||||||
doc/PersonResponseDto.md
 | 
					doc/PersonResponseDto.md
 | 
				
			||||||
doc/PersonUpdateDto.md
 | 
					doc/PersonUpdateDto.md
 | 
				
			||||||
@ -210,6 +212,8 @@ lib/model/o_auth_callback_dto.dart
 | 
				
			|||||||
lib/model/o_auth_config_dto.dart
 | 
					lib/model/o_auth_config_dto.dart
 | 
				
			||||||
lib/model/o_auth_config_response_dto.dart
 | 
					lib/model/o_auth_config_response_dto.dart
 | 
				
			||||||
lib/model/people_response_dto.dart
 | 
					lib/model/people_response_dto.dart
 | 
				
			||||||
 | 
					lib/model/people_update_dto.dart
 | 
				
			||||||
 | 
					lib/model/people_update_item.dart
 | 
				
			||||||
lib/model/person_response_dto.dart
 | 
					lib/model/person_response_dto.dart
 | 
				
			||||||
lib/model/person_update_dto.dart
 | 
					lib/model/person_update_dto.dart
 | 
				
			||||||
lib/model/queue_status_dto.dart
 | 
					lib/model/queue_status_dto.dart
 | 
				
			||||||
@ -325,6 +329,8 @@ test/o_auth_config_dto_test.dart
 | 
				
			|||||||
test/o_auth_config_response_dto_test.dart
 | 
					test/o_auth_config_response_dto_test.dart
 | 
				
			||||||
test/partner_api_test.dart
 | 
					test/partner_api_test.dart
 | 
				
			||||||
test/people_response_dto_test.dart
 | 
					test/people_response_dto_test.dart
 | 
				
			||||||
 | 
					test/people_update_dto_test.dart
 | 
				
			||||||
 | 
					test/people_update_item_test.dart
 | 
				
			||||||
test/person_api_test.dart
 | 
					test/person_api_test.dart
 | 
				
			||||||
test/person_response_dto_test.dart
 | 
					test/person_response_dto_test.dart
 | 
				
			||||||
test/person_update_dto_test.dart
 | 
					test/person_update_dto_test.dart
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										3
									
								
								mobile/openapi/README.md
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3
									
								
								mobile/openapi/README.md
									
									
									
										generated
									
									
									
								
							@ -134,6 +134,7 @@ Class | Method | HTTP request | Description
 | 
				
			|||||||
*PersonApi* | [**getPersonAssets**](doc//PersonApi.md#getpersonassets) | **GET** /person/{id}/assets | 
 | 
					*PersonApi* | [**getPersonAssets**](doc//PersonApi.md#getpersonassets) | **GET** /person/{id}/assets | 
 | 
				
			||||||
*PersonApi* | [**getPersonThumbnail**](doc//PersonApi.md#getpersonthumbnail) | **GET** /person/{id}/thumbnail | 
 | 
					*PersonApi* | [**getPersonThumbnail**](doc//PersonApi.md#getpersonthumbnail) | **GET** /person/{id}/thumbnail | 
 | 
				
			||||||
*PersonApi* | [**mergePerson**](doc//PersonApi.md#mergeperson) | **POST** /person/{id}/merge | 
 | 
					*PersonApi* | [**mergePerson**](doc//PersonApi.md#mergeperson) | **POST** /person/{id}/merge | 
 | 
				
			||||||
 | 
					*PersonApi* | [**updatePeople**](doc//PersonApi.md#updatepeople) | **PUT** /person | 
 | 
				
			||||||
*PersonApi* | [**updatePerson**](doc//PersonApi.md#updateperson) | **PUT** /person/{id} | 
 | 
					*PersonApi* | [**updatePerson**](doc//PersonApi.md#updateperson) | **PUT** /person/{id} | 
 | 
				
			||||||
*SearchApi* | [**getExploreData**](doc//SearchApi.md#getexploredata) | **GET** /search/explore | 
 | 
					*SearchApi* | [**getExploreData**](doc//SearchApi.md#getexploredata) | **GET** /search/explore | 
 | 
				
			||||||
*SearchApi* | [**getSearchConfig**](doc//SearchApi.md#getsearchconfig) | **GET** /search/config | 
 | 
					*SearchApi* | [**getSearchConfig**](doc//SearchApi.md#getsearchconfig) | **GET** /search/config | 
 | 
				
			||||||
@ -239,6 +240,8 @@ Class | Method | HTTP request | Description
 | 
				
			|||||||
 - [OAuthConfigDto](doc//OAuthConfigDto.md)
 | 
					 - [OAuthConfigDto](doc//OAuthConfigDto.md)
 | 
				
			||||||
 - [OAuthConfigResponseDto](doc//OAuthConfigResponseDto.md)
 | 
					 - [OAuthConfigResponseDto](doc//OAuthConfigResponseDto.md)
 | 
				
			||||||
 - [PeopleResponseDto](doc//PeopleResponseDto.md)
 | 
					 - [PeopleResponseDto](doc//PeopleResponseDto.md)
 | 
				
			||||||
 | 
					 - [PeopleUpdateDto](doc//PeopleUpdateDto.md)
 | 
				
			||||||
 | 
					 - [PeopleUpdateItem](doc//PeopleUpdateItem.md)
 | 
				
			||||||
 - [PersonResponseDto](doc//PersonResponseDto.md)
 | 
					 - [PersonResponseDto](doc//PersonResponseDto.md)
 | 
				
			||||||
 - [PersonUpdateDto](doc//PersonUpdateDto.md)
 | 
					 - [PersonUpdateDto](doc//PersonUpdateDto.md)
 | 
				
			||||||
 - [QueueStatusDto](doc//QueueStatusDto.md)
 | 
					 - [QueueStatusDto](doc//QueueStatusDto.md)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										15
									
								
								mobile/openapi/doc/PeopleUpdateDto.md
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								mobile/openapi/doc/PeopleUpdateDto.md
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					# openapi.model.PeopleUpdateDto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Load the model package
 | 
				
			||||||
 | 
					```dart
 | 
				
			||||||
 | 
					import 'package:openapi/api.dart';
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Properties
 | 
				
			||||||
 | 
					Name | Type | Description | Notes
 | 
				
			||||||
 | 
					------------ | ------------- | ------------- | -------------
 | 
				
			||||||
 | 
					**people** | [**List<PeopleUpdateItem>**](PeopleUpdateItem.md) |  | [default to const []]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										18
									
								
								mobile/openapi/doc/PeopleUpdateItem.md
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								mobile/openapi/doc/PeopleUpdateItem.md
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					# openapi.model.PeopleUpdateItem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Load the model package
 | 
				
			||||||
 | 
					```dart
 | 
				
			||||||
 | 
					import 'package:openapi/api.dart';
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Properties
 | 
				
			||||||
 | 
					Name | Type | Description | Notes
 | 
				
			||||||
 | 
					------------ | ------------- | ------------- | -------------
 | 
				
			||||||
 | 
					**id** | **String** | Person id. | 
 | 
				
			||||||
 | 
					**name** | **String** | Person name. | [optional] 
 | 
				
			||||||
 | 
					**featureFaceAssetId** | **String** | Asset is used to get the feature face thumbnail. | [optional] 
 | 
				
			||||||
 | 
					**isHidden** | **bool** | Person visibility | [optional] 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										56
									
								
								mobile/openapi/doc/PersonApi.md
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										56
									
								
								mobile/openapi/doc/PersonApi.md
									
									
									
										generated
									
									
									
								
							@ -14,6 +14,7 @@ Method | HTTP request | Description
 | 
				
			|||||||
[**getPersonAssets**](PersonApi.md#getpersonassets) | **GET** /person/{id}/assets | 
 | 
					[**getPersonAssets**](PersonApi.md#getpersonassets) | **GET** /person/{id}/assets | 
 | 
				
			||||||
[**getPersonThumbnail**](PersonApi.md#getpersonthumbnail) | **GET** /person/{id}/thumbnail | 
 | 
					[**getPersonThumbnail**](PersonApi.md#getpersonthumbnail) | **GET** /person/{id}/thumbnail | 
 | 
				
			||||||
[**mergePerson**](PersonApi.md#mergeperson) | **POST** /person/{id}/merge | 
 | 
					[**mergePerson**](PersonApi.md#mergeperson) | **POST** /person/{id}/merge | 
 | 
				
			||||||
 | 
					[**updatePeople**](PersonApi.md#updatepeople) | **PUT** /person | 
 | 
				
			||||||
[**updatePerson**](PersonApi.md#updateperson) | **PUT** /person/{id} | 
 | 
					[**updatePerson**](PersonApi.md#updateperson) | **PUT** /person/{id} | 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -294,6 +295,61 @@ Name | Type | Description  | Notes
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 | 
					[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# **updatePeople**
 | 
				
			||||||
 | 
					> List<BulkIdResponseDto> updatePeople(peopleUpdateDto)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Example
 | 
				
			||||||
 | 
					```dart
 | 
				
			||||||
 | 
					import 'package:openapi/api.dart';
 | 
				
			||||||
 | 
					// TODO Configure API key authorization: cookie
 | 
				
			||||||
 | 
					//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
 | 
				
			||||||
 | 
					// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
 | 
				
			||||||
 | 
					//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
 | 
				
			||||||
 | 
					// TODO Configure API key authorization: api_key
 | 
				
			||||||
 | 
					//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
 | 
				
			||||||
 | 
					// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
 | 
				
			||||||
 | 
					//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
 | 
				
			||||||
 | 
					// TODO Configure HTTP Bearer authorization: bearer
 | 
				
			||||||
 | 
					// Case 1. Use String Token
 | 
				
			||||||
 | 
					//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken('YOUR_ACCESS_TOKEN');
 | 
				
			||||||
 | 
					// Case 2. Use Function which generate token.
 | 
				
			||||||
 | 
					// String yourTokenGeneratorFunction() { ... }
 | 
				
			||||||
 | 
					//defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					final api_instance = PersonApi();
 | 
				
			||||||
 | 
					final peopleUpdateDto = PeopleUpdateDto(); // PeopleUpdateDto | 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					try {
 | 
				
			||||||
 | 
					    final result = api_instance.updatePeople(peopleUpdateDto);
 | 
				
			||||||
 | 
					    print(result);
 | 
				
			||||||
 | 
					} catch (e) {
 | 
				
			||||||
 | 
					    print('Exception when calling PersonApi->updatePeople: $e\n');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Parameters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Name | Type | Description  | Notes
 | 
				
			||||||
 | 
					------------- | ------------- | ------------- | -------------
 | 
				
			||||||
 | 
					 **peopleUpdateDto** | [**PeopleUpdateDto**](PeopleUpdateDto.md)|  | 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Return type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[**List<BulkIdResponseDto>**](BulkIdResponseDto.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Authorization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### HTTP request headers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 - **Content-Type**: application/json
 | 
				
			||||||
 | 
					 - **Accept**: application/json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# **updatePerson**
 | 
					# **updatePerson**
 | 
				
			||||||
> PersonResponseDto updatePerson(id, personUpdateDto)
 | 
					> PersonResponseDto updatePerson(id, personUpdateDto)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								mobile/openapi/lib/api.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								mobile/openapi/lib/api.dart
									
									
									
										generated
									
									
									
								
							@ -105,6 +105,8 @@ part 'model/o_auth_callback_dto.dart';
 | 
				
			|||||||
part 'model/o_auth_config_dto.dart';
 | 
					part 'model/o_auth_config_dto.dart';
 | 
				
			||||||
part 'model/o_auth_config_response_dto.dart';
 | 
					part 'model/o_auth_config_response_dto.dart';
 | 
				
			||||||
part 'model/people_response_dto.dart';
 | 
					part 'model/people_response_dto.dart';
 | 
				
			||||||
 | 
					part 'model/people_update_dto.dart';
 | 
				
			||||||
 | 
					part 'model/people_update_item.dart';
 | 
				
			||||||
part 'model/person_response_dto.dart';
 | 
					part 'model/person_response_dto.dart';
 | 
				
			||||||
part 'model/person_update_dto.dart';
 | 
					part 'model/person_update_dto.dart';
 | 
				
			||||||
part 'model/queue_status_dto.dart';
 | 
					part 'model/queue_status_dto.dart';
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										50
									
								
								mobile/openapi/lib/api/person_api.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										50
									
								
								mobile/openapi/lib/api/person_api.dart
									
									
									
										generated
									
									
									
								
							@ -269,6 +269,56 @@ class PersonApi {
 | 
				
			|||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Performs an HTTP 'PUT /person' operation and returns the [Response].
 | 
				
			||||||
 | 
					  /// Parameters:
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// * [PeopleUpdateDto] peopleUpdateDto (required):
 | 
				
			||||||
 | 
					  Future<Response> updatePeopleWithHttpInfo(PeopleUpdateDto peopleUpdateDto,) async {
 | 
				
			||||||
 | 
					    // ignore: prefer_const_declarations
 | 
				
			||||||
 | 
					    final path = r'/person';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ignore: prefer_final_locals
 | 
				
			||||||
 | 
					    Object? postBody = peopleUpdateDto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final queryParams = <QueryParam>[];
 | 
				
			||||||
 | 
					    final headerParams = <String, String>{};
 | 
				
			||||||
 | 
					    final formParams = <String, String>{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const contentTypes = <String>['application/json'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return apiClient.invokeAPI(
 | 
				
			||||||
 | 
					      path,
 | 
				
			||||||
 | 
					      'PUT',
 | 
				
			||||||
 | 
					      queryParams,
 | 
				
			||||||
 | 
					      postBody,
 | 
				
			||||||
 | 
					      headerParams,
 | 
				
			||||||
 | 
					      formParams,
 | 
				
			||||||
 | 
					      contentTypes.isEmpty ? null : contentTypes.first,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Parameters:
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// * [PeopleUpdateDto] peopleUpdateDto (required):
 | 
				
			||||||
 | 
					  Future<List<BulkIdResponseDto>?> updatePeople(PeopleUpdateDto peopleUpdateDto,) async {
 | 
				
			||||||
 | 
					    final response = await updatePeopleWithHttpInfo(peopleUpdateDto,);
 | 
				
			||||||
 | 
					    if (response.statusCode >= HttpStatus.badRequest) {
 | 
				
			||||||
 | 
					      throw ApiException(response.statusCode, await _decodeBodyBytes(response));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // When a remote server returns no body with a status of 204, we shall not decode it.
 | 
				
			||||||
 | 
					    // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
 | 
				
			||||||
 | 
					    // FormatException when trying to decode an empty string.
 | 
				
			||||||
 | 
					    if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
 | 
				
			||||||
 | 
					      final responseBody = await _decodeBodyBytes(response);
 | 
				
			||||||
 | 
					      return (await apiClient.deserializeAsync(responseBody, 'List<BulkIdResponseDto>') as List)
 | 
				
			||||||
 | 
					        .cast<BulkIdResponseDto>()
 | 
				
			||||||
 | 
					        .toList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Performs an HTTP 'PUT /person/{id}' operation and returns the [Response].
 | 
					  /// Performs an HTTP 'PUT /person/{id}' operation and returns the [Response].
 | 
				
			||||||
  /// Parameters:
 | 
					  /// Parameters:
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								mobile/openapi/lib/api_client.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								mobile/openapi/lib/api_client.dart
									
									
									
										generated
									
									
									
								
							@ -305,6 +305,10 @@ class ApiClient {
 | 
				
			|||||||
          return OAuthConfigResponseDto.fromJson(value);
 | 
					          return OAuthConfigResponseDto.fromJson(value);
 | 
				
			||||||
        case 'PeopleResponseDto':
 | 
					        case 'PeopleResponseDto':
 | 
				
			||||||
          return PeopleResponseDto.fromJson(value);
 | 
					          return PeopleResponseDto.fromJson(value);
 | 
				
			||||||
 | 
					        case 'PeopleUpdateDto':
 | 
				
			||||||
 | 
					          return PeopleUpdateDto.fromJson(value);
 | 
				
			||||||
 | 
					        case 'PeopleUpdateItem':
 | 
				
			||||||
 | 
					          return PeopleUpdateItem.fromJson(value);
 | 
				
			||||||
        case 'PersonResponseDto':
 | 
					        case 'PersonResponseDto':
 | 
				
			||||||
          return PersonResponseDto.fromJson(value);
 | 
					          return PersonResponseDto.fromJson(value);
 | 
				
			||||||
        case 'PersonUpdateDto':
 | 
					        case 'PersonUpdateDto':
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										98
									
								
								mobile/openapi/lib/model/people_update_dto.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								mobile/openapi/lib/model/people_update_dto.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,98 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// AUTO-GENERATED FILE, DO NOT MODIFY!
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// @dart=2.12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ignore_for_file: unused_element, unused_import
 | 
				
			||||||
 | 
					// ignore_for_file: always_put_required_named_parameters_first
 | 
				
			||||||
 | 
					// ignore_for_file: constant_identifier_names
 | 
				
			||||||
 | 
					// ignore_for_file: lines_longer_than_80_chars
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					part of openapi.api;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PeopleUpdateDto {
 | 
				
			||||||
 | 
					  /// Returns a new [PeopleUpdateDto] instance.
 | 
				
			||||||
 | 
					  PeopleUpdateDto({
 | 
				
			||||||
 | 
					    this.people = const [],
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  List<PeopleUpdateItem> people;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  bool operator ==(Object other) => identical(this, other) || other is PeopleUpdateDto &&
 | 
				
			||||||
 | 
					     other.people == people;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  int get hashCode =>
 | 
				
			||||||
 | 
					    // ignore: unnecessary_parenthesis
 | 
				
			||||||
 | 
					    (people.hashCode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() => 'PeopleUpdateDto[people=$people]';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Map<String, dynamic> toJson() {
 | 
				
			||||||
 | 
					    final json = <String, dynamic>{};
 | 
				
			||||||
 | 
					      json[r'people'] = this.people;
 | 
				
			||||||
 | 
					    return json;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Returns a new [PeopleUpdateDto] instance and imports its values from
 | 
				
			||||||
 | 
					  /// [value] if it's a [Map], null otherwise.
 | 
				
			||||||
 | 
					  // ignore: prefer_constructors_over_static_methods
 | 
				
			||||||
 | 
					  static PeopleUpdateDto? fromJson(dynamic value) {
 | 
				
			||||||
 | 
					    if (value is Map) {
 | 
				
			||||||
 | 
					      final json = value.cast<String, dynamic>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return PeopleUpdateDto(
 | 
				
			||||||
 | 
					        people: PeopleUpdateItem.listFromJson(json[r'people']),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static List<PeopleUpdateDto> listFromJson(dynamic json, {bool growable = false,}) {
 | 
				
			||||||
 | 
					    final result = <PeopleUpdateDto>[];
 | 
				
			||||||
 | 
					    if (json is List && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      for (final row in json) {
 | 
				
			||||||
 | 
					        final value = PeopleUpdateDto.fromJson(row);
 | 
				
			||||||
 | 
					        if (value != null) {
 | 
				
			||||||
 | 
					          result.add(value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result.toList(growable: growable);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static Map<String, PeopleUpdateDto> mapFromJson(dynamic json) {
 | 
				
			||||||
 | 
					    final map = <String, PeopleUpdateDto>{};
 | 
				
			||||||
 | 
					    if (json is Map && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      json = json.cast<String, dynamic>(); // ignore: parameter_assignments
 | 
				
			||||||
 | 
					      for (final entry in json.entries) {
 | 
				
			||||||
 | 
					        final value = PeopleUpdateDto.fromJson(entry.value);
 | 
				
			||||||
 | 
					        if (value != null) {
 | 
				
			||||||
 | 
					          map[entry.key] = value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // maps a json object with a list of PeopleUpdateDto-objects as value to a dart map
 | 
				
			||||||
 | 
					  static Map<String, List<PeopleUpdateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
 | 
				
			||||||
 | 
					    final map = <String, List<PeopleUpdateDto>>{};
 | 
				
			||||||
 | 
					    if (json is Map && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      // ignore: parameter_assignments
 | 
				
			||||||
 | 
					      json = json.cast<String, dynamic>();
 | 
				
			||||||
 | 
					      for (final entry in json.entries) {
 | 
				
			||||||
 | 
					        map[entry.key] = PeopleUpdateDto.listFromJson(entry.value, growable: growable,);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// The list of required keys that must be present in a JSON.
 | 
				
			||||||
 | 
					  static const requiredKeys = <String>{
 | 
				
			||||||
 | 
					    'people',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										153
									
								
								mobile/openapi/lib/model/people_update_item.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								mobile/openapi/lib/model/people_update_item.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,153 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// AUTO-GENERATED FILE, DO NOT MODIFY!
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// @dart=2.12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ignore_for_file: unused_element, unused_import
 | 
				
			||||||
 | 
					// ignore_for_file: always_put_required_named_parameters_first
 | 
				
			||||||
 | 
					// ignore_for_file: constant_identifier_names
 | 
				
			||||||
 | 
					// ignore_for_file: lines_longer_than_80_chars
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					part of openapi.api;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PeopleUpdateItem {
 | 
				
			||||||
 | 
					  /// Returns a new [PeopleUpdateItem] instance.
 | 
				
			||||||
 | 
					  PeopleUpdateItem({
 | 
				
			||||||
 | 
					    required this.id,
 | 
				
			||||||
 | 
					    this.name,
 | 
				
			||||||
 | 
					    this.featureFaceAssetId,
 | 
				
			||||||
 | 
					    this.isHidden,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Person id.
 | 
				
			||||||
 | 
					  String id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Person name.
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// Please note: This property should have been non-nullable! Since the specification file
 | 
				
			||||||
 | 
					  /// does not include a default value (using the "default:" property), however, the generated
 | 
				
			||||||
 | 
					  /// source code must fall back to having a nullable type.
 | 
				
			||||||
 | 
					  /// Consider adding a "default:" property in the specification file to hide this note.
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  String? name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Asset is used to get the feature face thumbnail.
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// Please note: This property should have been non-nullable! Since the specification file
 | 
				
			||||||
 | 
					  /// does not include a default value (using the "default:" property), however, the generated
 | 
				
			||||||
 | 
					  /// source code must fall back to having a nullable type.
 | 
				
			||||||
 | 
					  /// Consider adding a "default:" property in the specification file to hide this note.
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  String? featureFaceAssetId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Person visibility
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// Please note: This property should have been non-nullable! Since the specification file
 | 
				
			||||||
 | 
					  /// does not include a default value (using the "default:" property), however, the generated
 | 
				
			||||||
 | 
					  /// source code must fall back to having a nullable type.
 | 
				
			||||||
 | 
					  /// Consider adding a "default:" property in the specification file to hide this note.
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  bool? isHidden;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  bool operator ==(Object other) => identical(this, other) || other is PeopleUpdateItem &&
 | 
				
			||||||
 | 
					     other.id == id &&
 | 
				
			||||||
 | 
					     other.name == name &&
 | 
				
			||||||
 | 
					     other.featureFaceAssetId == featureFaceAssetId &&
 | 
				
			||||||
 | 
					     other.isHidden == isHidden;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  int get hashCode =>
 | 
				
			||||||
 | 
					    // ignore: unnecessary_parenthesis
 | 
				
			||||||
 | 
					    (id.hashCode) +
 | 
				
			||||||
 | 
					    (name == null ? 0 : name!.hashCode) +
 | 
				
			||||||
 | 
					    (featureFaceAssetId == null ? 0 : featureFaceAssetId!.hashCode) +
 | 
				
			||||||
 | 
					    (isHidden == null ? 0 : isHidden!.hashCode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() => 'PeopleUpdateItem[id=$id, name=$name, featureFaceAssetId=$featureFaceAssetId, isHidden=$isHidden]';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Map<String, dynamic> toJson() {
 | 
				
			||||||
 | 
					    final json = <String, dynamic>{};
 | 
				
			||||||
 | 
					      json[r'id'] = this.id;
 | 
				
			||||||
 | 
					    if (this.name != null) {
 | 
				
			||||||
 | 
					      json[r'name'] = this.name;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					    //  json[r'name'] = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (this.featureFaceAssetId != null) {
 | 
				
			||||||
 | 
					      json[r'featureFaceAssetId'] = this.featureFaceAssetId;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					    //  json[r'featureFaceAssetId'] = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (this.isHidden != null) {
 | 
				
			||||||
 | 
					      json[r'isHidden'] = this.isHidden;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					    //  json[r'isHidden'] = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return json;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Returns a new [PeopleUpdateItem] instance and imports its values from
 | 
				
			||||||
 | 
					  /// [value] if it's a [Map], null otherwise.
 | 
				
			||||||
 | 
					  // ignore: prefer_constructors_over_static_methods
 | 
				
			||||||
 | 
					  static PeopleUpdateItem? fromJson(dynamic value) {
 | 
				
			||||||
 | 
					    if (value is Map) {
 | 
				
			||||||
 | 
					      final json = value.cast<String, dynamic>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return PeopleUpdateItem(
 | 
				
			||||||
 | 
					        id: mapValueOfType<String>(json, r'id')!,
 | 
				
			||||||
 | 
					        name: mapValueOfType<String>(json, r'name'),
 | 
				
			||||||
 | 
					        featureFaceAssetId: mapValueOfType<String>(json, r'featureFaceAssetId'),
 | 
				
			||||||
 | 
					        isHidden: mapValueOfType<bool>(json, r'isHidden'),
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static List<PeopleUpdateItem> listFromJson(dynamic json, {bool growable = false,}) {
 | 
				
			||||||
 | 
					    final result = <PeopleUpdateItem>[];
 | 
				
			||||||
 | 
					    if (json is List && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      for (final row in json) {
 | 
				
			||||||
 | 
					        final value = PeopleUpdateItem.fromJson(row);
 | 
				
			||||||
 | 
					        if (value != null) {
 | 
				
			||||||
 | 
					          result.add(value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result.toList(growable: growable);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static Map<String, PeopleUpdateItem> mapFromJson(dynamic json) {
 | 
				
			||||||
 | 
					    final map = <String, PeopleUpdateItem>{};
 | 
				
			||||||
 | 
					    if (json is Map && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      json = json.cast<String, dynamic>(); // ignore: parameter_assignments
 | 
				
			||||||
 | 
					      for (final entry in json.entries) {
 | 
				
			||||||
 | 
					        final value = PeopleUpdateItem.fromJson(entry.value);
 | 
				
			||||||
 | 
					        if (value != null) {
 | 
				
			||||||
 | 
					          map[entry.key] = value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // maps a json object with a list of PeopleUpdateItem-objects as value to a dart map
 | 
				
			||||||
 | 
					  static Map<String, List<PeopleUpdateItem>> mapListFromJson(dynamic json, {bool growable = false,}) {
 | 
				
			||||||
 | 
					    final map = <String, List<PeopleUpdateItem>>{};
 | 
				
			||||||
 | 
					    if (json is Map && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      // ignore: parameter_assignments
 | 
				
			||||||
 | 
					      json = json.cast<String, dynamic>();
 | 
				
			||||||
 | 
					      for (final entry in json.entries) {
 | 
				
			||||||
 | 
					        map[entry.key] = PeopleUpdateItem.listFromJson(entry.value, growable: growable,);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// The list of required keys that must be present in a JSON.
 | 
				
			||||||
 | 
					  static const requiredKeys = <String>{
 | 
				
			||||||
 | 
					    'id',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										27
									
								
								mobile/openapi/test/people_update_dto_test.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								mobile/openapi/test/people_update_dto_test.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// AUTO-GENERATED FILE, DO NOT MODIFY!
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// @dart=2.12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ignore_for_file: unused_element, unused_import
 | 
				
			||||||
 | 
					// ignore_for_file: always_put_required_named_parameters_first
 | 
				
			||||||
 | 
					// ignore_for_file: constant_identifier_names
 | 
				
			||||||
 | 
					// ignore_for_file: lines_longer_than_80_chars
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:openapi/api.dart';
 | 
				
			||||||
 | 
					import 'package:test/test.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// tests for PeopleUpdateDto
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
					  // final instance = PeopleUpdateDto();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  group('test PeopleUpdateDto', () {
 | 
				
			||||||
 | 
					    // List<PeopleUpdateItem> people (default value: const [])
 | 
				
			||||||
 | 
					    test('to test the property `people`', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										46
									
								
								mobile/openapi/test/people_update_item_test.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								mobile/openapi/test/people_update_item_test.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// AUTO-GENERATED FILE, DO NOT MODIFY!
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// @dart=2.12
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ignore_for_file: unused_element, unused_import
 | 
				
			||||||
 | 
					// ignore_for_file: always_put_required_named_parameters_first
 | 
				
			||||||
 | 
					// ignore_for_file: constant_identifier_names
 | 
				
			||||||
 | 
					// ignore_for_file: lines_longer_than_80_chars
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:openapi/api.dart';
 | 
				
			||||||
 | 
					import 'package:test/test.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// tests for PeopleUpdateItem
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
					  // final instance = PeopleUpdateItem();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  group('test PeopleUpdateItem', () {
 | 
				
			||||||
 | 
					    // Person id.
 | 
				
			||||||
 | 
					    // String id
 | 
				
			||||||
 | 
					    test('to test the property `id`', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Person name.
 | 
				
			||||||
 | 
					    // String name
 | 
				
			||||||
 | 
					    test('to test the property `name`', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Asset is used to get the feature face thumbnail.
 | 
				
			||||||
 | 
					    // String featureFaceAssetId
 | 
				
			||||||
 | 
					    test('to test the property `featureFaceAssetId`', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Person visibility
 | 
				
			||||||
 | 
					    // bool isHidden
 | 
				
			||||||
 | 
					    test('to test the property `isHidden`', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										5
									
								
								mobile/openapi/test/person_api_test.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								mobile/openapi/test/person_api_test.dart
									
									
									
										generated
									
									
									
								
							@ -42,6 +42,11 @@ void main() {
 | 
				
			|||||||
      // TODO
 | 
					      // TODO
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Future<List<BulkIdResponseDto>> updatePeople(PeopleUpdateDto peopleUpdateDto) async
 | 
				
			||||||
 | 
					    test('test updatePeople', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Future<PersonResponseDto> updatePerson(String id, PersonUpdateDto personUpdateDto) async
 | 
					    //Future<PersonResponseDto> updatePerson(String id, PersonUpdateDto personUpdateDto) async
 | 
				
			||||||
    test('test updatePerson', () async {
 | 
					    test('test updatePerson', () async {
 | 
				
			||||||
      // TODO
 | 
					      // TODO
 | 
				
			||||||
 | 
				
			|||||||
@ -2546,6 +2546,49 @@
 | 
				
			|||||||
            "api_key": []
 | 
					            "api_key": []
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "put": {
 | 
				
			||||||
 | 
					        "operationId": "updatePeople",
 | 
				
			||||||
 | 
					        "parameters": [],
 | 
				
			||||||
 | 
					        "requestBody": {
 | 
				
			||||||
 | 
					          "required": true,
 | 
				
			||||||
 | 
					          "content": {
 | 
				
			||||||
 | 
					            "application/json": {
 | 
				
			||||||
 | 
					              "schema": {
 | 
				
			||||||
 | 
					                "$ref": "#/components/schemas/PeopleUpdateDto"
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "responses": {
 | 
				
			||||||
 | 
					          "200": {
 | 
				
			||||||
 | 
					            "description": "",
 | 
				
			||||||
 | 
					            "content": {
 | 
				
			||||||
 | 
					              "application/json": {
 | 
				
			||||||
 | 
					                "schema": {
 | 
				
			||||||
 | 
					                  "type": "array",
 | 
				
			||||||
 | 
					                  "items": {
 | 
				
			||||||
 | 
					                    "$ref": "#/components/schemas/BulkIdResponseDto"
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "tags": [
 | 
				
			||||||
 | 
					          "Person"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "security": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "bearer": []
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "cookie": []
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "api_key": []
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "/person/{id}": {
 | 
					    "/person/{id}": {
 | 
				
			||||||
@ -5028,13 +5071,13 @@
 | 
				
			|||||||
            "type": "boolean"
 | 
					            "type": "boolean"
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
          "error": {
 | 
					          "error": {
 | 
				
			||||||
            "type": "string",
 | 
					 | 
				
			||||||
            "enum": [
 | 
					            "enum": [
 | 
				
			||||||
              "duplicate",
 | 
					              "duplicate",
 | 
				
			||||||
              "no_permission",
 | 
					              "no_permission",
 | 
				
			||||||
              "not_found",
 | 
					              "not_found",
 | 
				
			||||||
              "unknown"
 | 
					              "unknown"
 | 
				
			||||||
            ]
 | 
					            ],
 | 
				
			||||||
 | 
					            "type": "string"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "required": [
 | 
					        "required": [
 | 
				
			||||||
@ -5906,6 +5949,44 @@
 | 
				
			|||||||
          "people"
 | 
					          "people"
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
 | 
					      "PeopleUpdateDto": {
 | 
				
			||||||
 | 
					        "type": "object",
 | 
				
			||||||
 | 
					        "properties": {
 | 
				
			||||||
 | 
					          "people": {
 | 
				
			||||||
 | 
					            "type": "array",
 | 
				
			||||||
 | 
					            "items": {
 | 
				
			||||||
 | 
					              "$ref": "#/components/schemas/PeopleUpdateItem"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "required": [
 | 
				
			||||||
 | 
					          "people"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "PeopleUpdateItem": {
 | 
				
			||||||
 | 
					        "type": "object",
 | 
				
			||||||
 | 
					        "properties": {
 | 
				
			||||||
 | 
					          "id": {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "Person id."
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "name": {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "Person name."
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "featureFaceAssetId": {
 | 
				
			||||||
 | 
					            "type": "string",
 | 
				
			||||||
 | 
					            "description": "Asset is used to get the feature face thumbnail."
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "isHidden": {
 | 
				
			||||||
 | 
					            "type": "boolean",
 | 
				
			||||||
 | 
					            "description": "Person visibility"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "required": [
 | 
				
			||||||
 | 
					          "id"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
      "PersonResponseDto": {
 | 
					      "PersonResponseDto": {
 | 
				
			||||||
        "type": "object",
 | 
					        "type": "object",
 | 
				
			||||||
        "properties": {
 | 
					        "properties": {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import { AssetFaceEntity, PersonEntity } from '@app/infra/entities';
 | 
					import { AssetFaceEntity, PersonEntity } from '@app/infra/entities';
 | 
				
			||||||
import { Transform } from 'class-transformer';
 | 
					import { Transform, Type } from 'class-transformer';
 | 
				
			||||||
import { IsBoolean, IsOptional, IsString } from 'class-validator';
 | 
					import { IsArray, IsBoolean, IsNotEmpty, IsOptional, IsString, ValidateNested } from 'class-validator';
 | 
				
			||||||
import { toBoolean, ValidateUUID } from '../domain.util';
 | 
					import { toBoolean, ValidateUUID } from '../domain.util';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class PersonUpdateDto {
 | 
					export class PersonUpdateDto {
 | 
				
			||||||
@ -26,6 +26,43 @@ export class PersonUpdateDto {
 | 
				
			|||||||
  isHidden?: boolean;
 | 
					  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 {
 | 
					export class MergePersonDto {
 | 
				
			||||||
  @ValidateUUID({ each: true })
 | 
					  @ValidateUUID({ each: true })
 | 
				
			||||||
  ids!: string[];
 | 
					  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', () => {
 | 
					  describe('handlePersonCleanup', () => {
 | 
				
			||||||
    it('should delete people without faces', async () => {
 | 
					    it('should delete people without faces', async () => {
 | 
				
			||||||
      personMock.getAllWithoutFaces.mockResolvedValue([personStub.noName]);
 | 
					      personMock.getAllWithoutFaces.mockResolvedValue([personStub.noName]);
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,7 @@ import {
 | 
				
			|||||||
  mapPerson,
 | 
					  mapPerson,
 | 
				
			||||||
  MergePersonDto,
 | 
					  MergePersonDto,
 | 
				
			||||||
  PeopleResponseDto,
 | 
					  PeopleResponseDto,
 | 
				
			||||||
 | 
					  PeopleUpdateDto,
 | 
				
			||||||
  PersonResponseDto,
 | 
					  PersonResponseDto,
 | 
				
			||||||
  PersonSearchDto,
 | 
					  PersonSearchDto,
 | 
				
			||||||
  PersonUpdateDto,
 | 
					  PersonUpdateDto,
 | 
				
			||||||
@ -96,6 +97,24 @@ export class PersonService {
 | 
				
			|||||||
    return mapPerson(person);
 | 
					    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() {
 | 
					  async handlePersonCleanup() {
 | 
				
			||||||
    const people = await this.repository.getAllWithoutFaces();
 | 
					    const people = await this.repository.getAllWithoutFaces();
 | 
				
			||||||
    for (const person of people) {
 | 
					    for (const person of people) {
 | 
				
			||||||
 | 
				
			|||||||
@ -5,6 +5,7 @@ import {
 | 
				
			|||||||
  ImmichReadStream,
 | 
					  ImmichReadStream,
 | 
				
			||||||
  MergePersonDto,
 | 
					  MergePersonDto,
 | 
				
			||||||
  PeopleResponseDto,
 | 
					  PeopleResponseDto,
 | 
				
			||||||
 | 
					  PeopleUpdateDto,
 | 
				
			||||||
  PersonResponseDto,
 | 
					  PersonResponseDto,
 | 
				
			||||||
  PersonSearchDto,
 | 
					  PersonSearchDto,
 | 
				
			||||||
  PersonService,
 | 
					  PersonService,
 | 
				
			||||||
@ -32,6 +33,11 @@ export class PersonController {
 | 
				
			|||||||
    return this.service.getAll(authUser, withHidden);
 | 
					    return this.service.getAll(authUser, withHidden);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Put()
 | 
				
			||||||
 | 
					  updatePeople(@AuthUser() authUser: AuthUserDto, @Body() dto: PeopleUpdateDto): Promise<BulkIdResponseDto[]> {
 | 
				
			||||||
 | 
					    return this.service.updatePeople(authUser, dto);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Get(':id')
 | 
					  @Get(':id')
 | 
				
			||||||
  getPerson(@AuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<PersonResponseDto> {
 | 
					  getPerson(@AuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto): Promise<PersonResponseDto> {
 | 
				
			||||||
    return this.service.getById(authUser, id);
 | 
					    return this.service.getById(authUser, id);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										132
									
								
								web/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										132
									
								
								web/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							@ -1802,6 +1802,50 @@ export interface PeopleResponseDto {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    'people': Array<PersonResponseDto>;
 | 
					    'people': Array<PersonResponseDto>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface PeopleUpdateDto
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface PeopleUpdateDto {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {Array<PeopleUpdateItem>}
 | 
				
			||||||
 | 
					     * @memberof PeopleUpdateDto
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'people': Array<PeopleUpdateItem>;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface PeopleUpdateItem
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface PeopleUpdateItem {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Person id.
 | 
				
			||||||
 | 
					     * @type {string}
 | 
				
			||||||
 | 
					     * @memberof PeopleUpdateItem
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'id': string;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Person name.
 | 
				
			||||||
 | 
					     * @type {string}
 | 
				
			||||||
 | 
					     * @memberof PeopleUpdateItem
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'name'?: string;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Asset is used to get the feature face thumbnail.
 | 
				
			||||||
 | 
					     * @type {string}
 | 
				
			||||||
 | 
					     * @memberof PeopleUpdateItem
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'featureFaceAssetId'?: string;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Person visibility
 | 
				
			||||||
 | 
					     * @type {boolean}
 | 
				
			||||||
 | 
					     * @memberof PeopleUpdateItem
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'isHidden'?: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 
 | 
					 * 
 | 
				
			||||||
 * @export
 | 
					 * @export
 | 
				
			||||||
@ -8940,6 +8984,50 @@ export const PersonApiAxiosParamCreator = function (configuration?: Configuratio
 | 
				
			|||||||
                options: localVarRequestOptions,
 | 
					                options: localVarRequestOptions,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {PeopleUpdateDto} peopleUpdateDto 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        updatePeople: async (peopleUpdateDto: PeopleUpdateDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
 | 
				
			||||||
 | 
					            // verify required parameter 'peopleUpdateDto' is not null or undefined
 | 
				
			||||||
 | 
					            assertParamExists('updatePeople', 'peopleUpdateDto', peopleUpdateDto)
 | 
				
			||||||
 | 
					            const localVarPath = `/person`;
 | 
				
			||||||
 | 
					            // use dummy base URL string because the URL constructor only accepts absolute URLs.
 | 
				
			||||||
 | 
					            const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
 | 
				
			||||||
 | 
					            let baseOptions;
 | 
				
			||||||
 | 
					            if (configuration) {
 | 
				
			||||||
 | 
					                baseOptions = configuration.baseOptions;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const localVarRequestOptions = { method: 'PUT', ...baseOptions, ...options};
 | 
				
			||||||
 | 
					            const localVarHeaderParameter = {} as any;
 | 
				
			||||||
 | 
					            const localVarQueryParameter = {} as any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication cookie required
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication api_key required
 | 
				
			||||||
 | 
					            await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication bearer required
 | 
				
			||||||
 | 
					            // http bearer authentication required
 | 
				
			||||||
 | 
					            await setBearerAuthToObject(localVarHeaderParameter, configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            localVarHeaderParameter['Content-Type'] = 'application/json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            setSearchParams(localVarUrlObj, localVarQueryParameter);
 | 
				
			||||||
 | 
					            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
 | 
				
			||||||
 | 
					            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
 | 
				
			||||||
 | 
					            localVarRequestOptions.data = serializeDataIfNeeded(peopleUpdateDto, localVarRequestOptions, configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                url: toPathString(localVarUrlObj),
 | 
				
			||||||
 | 
					                options: localVarRequestOptions,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {string} id 
 | 
					         * @param {string} id 
 | 
				
			||||||
@ -9049,6 +9137,16 @@ export const PersonApiFp = function(configuration?: Configuration) {
 | 
				
			|||||||
            const localVarAxiosArgs = await localVarAxiosParamCreator.mergePerson(id, mergePersonDto, options);
 | 
					            const localVarAxiosArgs = await localVarAxiosParamCreator.mergePerson(id, mergePersonDto, options);
 | 
				
			||||||
            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
					            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {PeopleUpdateDto} peopleUpdateDto 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        async updatePeople(peopleUpdateDto: PeopleUpdateDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<BulkIdResponseDto>>> {
 | 
				
			||||||
 | 
					            const localVarAxiosArgs = await localVarAxiosParamCreator.updatePeople(peopleUpdateDto, options);
 | 
				
			||||||
 | 
					            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {string} id 
 | 
					         * @param {string} id 
 | 
				
			||||||
@ -9116,6 +9214,15 @@ export const PersonApiFactory = function (configuration?: Configuration, basePat
 | 
				
			|||||||
        mergePerson(id: string, mergePersonDto: MergePersonDto, options?: any): AxiosPromise<Array<BulkIdResponseDto>> {
 | 
					        mergePerson(id: string, mergePersonDto: MergePersonDto, options?: any): AxiosPromise<Array<BulkIdResponseDto>> {
 | 
				
			||||||
            return localVarFp.mergePerson(id, mergePersonDto, options).then((request) => request(axios, basePath));
 | 
					            return localVarFp.mergePerson(id, mergePersonDto, options).then((request) => request(axios, basePath));
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {PeopleUpdateDto} peopleUpdateDto 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        updatePeople(peopleUpdateDto: PeopleUpdateDto, options?: any): AxiosPromise<Array<BulkIdResponseDto>> {
 | 
				
			||||||
 | 
					            return localVarFp.updatePeople(peopleUpdateDto, options).then((request) => request(axios, basePath));
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {string} id 
 | 
					         * @param {string} id 
 | 
				
			||||||
@ -9206,6 +9313,20 @@ export interface PersonApiMergePersonRequest {
 | 
				
			|||||||
    readonly mergePersonDto: MergePersonDto
 | 
					    readonly mergePersonDto: MergePersonDto
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Request parameters for updatePeople operation in PersonApi.
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface PersonApiUpdatePeopleRequest
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface PersonApiUpdatePeopleRequest {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {PeopleUpdateDto}
 | 
				
			||||||
 | 
					     * @memberof PersonApiUpdatePeople
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    readonly peopleUpdateDto: PeopleUpdateDto
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Request parameters for updatePerson operation in PersonApi.
 | 
					 * Request parameters for updatePerson operation in PersonApi.
 | 
				
			||||||
 * @export
 | 
					 * @export
 | 
				
			||||||
@ -9289,6 +9410,17 @@ export class PersonApi extends BaseAPI {
 | 
				
			|||||||
        return PersonApiFp(this.configuration).mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(this.axios, this.basePath));
 | 
					        return PersonApiFp(this.configuration).mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(this.axios, this.basePath));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
 | 
				
			||||||
 | 
					     * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					     * @throws {RequiredError}
 | 
				
			||||||
 | 
					     * @memberof PersonApi
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public updatePeople(requestParameters: PersonApiUpdatePeopleRequest, options?: AxiosRequestConfig) {
 | 
				
			||||||
 | 
					        return PersonApiFp(this.configuration).updatePeople(requestParameters.peopleUpdateDto, options).then((request) => request(this.axios, this.basePath));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 
 | 
					     * 
 | 
				
			||||||
     * @param {PersonApiUpdatePersonRequest} requestParameters Request parameters.
 | 
					     * @param {PersonApiUpdatePersonRequest} requestParameters Request parameters.
 | 
				
			||||||
 | 
				
			|||||||
@ -15,12 +15,15 @@
 | 
				
			|||||||
  export let circle = false;
 | 
					  export let circle = false;
 | 
				
			||||||
  export let hidden = false;
 | 
					  export let hidden = false;
 | 
				
			||||||
  let complete = false;
 | 
					  let complete = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  export let eyeColor = 'white';
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<img
 | 
					<img
 | 
				
			||||||
  style:width={widthStyle}
 | 
					  style:width={widthStyle}
 | 
				
			||||||
  style:height={heightStyle}
 | 
					  style:height={heightStyle}
 | 
				
			||||||
  style:filter={hidden ? 'grayscale(75%)' : 'none'}
 | 
					  style:filter={hidden ? 'grayscale(50%)' : 'none'}
 | 
				
			||||||
 | 
					  style:opacity={hidden ? '0.5' : '1'}
 | 
				
			||||||
  src={url}
 | 
					  src={url}
 | 
				
			||||||
  alt={altText}
 | 
					  alt={altText}
 | 
				
			||||||
  class="object-cover transition duration-300"
 | 
					  class="object-cover transition duration-300"
 | 
				
			||||||
@ -32,9 +35,10 @@
 | 
				
			|||||||
  use:imageLoad
 | 
					  use:imageLoad
 | 
				
			||||||
  on:image-load|once={() => (complete = true)}
 | 
					  on:image-load|once={() => (complete = true)}
 | 
				
			||||||
/>
 | 
					/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{#if hidden}
 | 
					{#if hidden}
 | 
				
			||||||
  <div class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform">
 | 
					  <div class="absolute left-1/2 top-1/2 translate-x-[-50%] translate-y-[-50%] transform">
 | 
				
			||||||
    <EyeOffOutline size="2em" />
 | 
					    <EyeOffOutline size="2em" color={eyeColor} />
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
{/if}
 | 
					{/if}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@
 | 
				
			|||||||
  $: unselectedPeople = people.filter((source) => !selectedPeople.includes(source) && source.id !== person.id);
 | 
					  $: unselectedPeople = people.filter((source) => !selectedPeople.includes(source) && source.id !== person.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  onMount(async () => {
 | 
					  onMount(async () => {
 | 
				
			||||||
    const { data } = await api.personApi.getAllPeople({ withHidden: true });
 | 
					    const { data } = await api.personApi.getAllPeople({ withHidden: false });
 | 
				
			||||||
    people = data.people;
 | 
					    people = data.people;
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -20,17 +20,19 @@
 | 
				
			|||||||
  const onMergeFacesClicked = () => {
 | 
					  const onMergeFacesClicked = () => {
 | 
				
			||||||
    dispatch('merge-faces', person);
 | 
					    dispatch('merge-faces', person);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const onHideFaceClicked = () => {
 | 
				
			||||||
 | 
					    dispatch('hide-face', person);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div id="people-card" class="relative">
 | 
					<div id="people-card" class="relative">
 | 
				
			||||||
  <a href="/people/{person.id}" draggable="false">
 | 
					  <a href="/people/{person.id}" draggable="false">
 | 
				
			||||||
    <div class="w-48 rounded-xl brightness-95 filter">
 | 
					    <div class="h-48 w-48 rounded-xl brightness-95 filter">
 | 
				
			||||||
      <ImageThumbnail shadow url={api.getPeopleThumbnailUrl(person.id)} altText={person.name} widthStyle="100%" />
 | 
					      <ImageThumbnail shadow url={api.getPeopleThumbnailUrl(person.id)} altText={person.name} widthStyle="100%" />
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    {#if person.name}
 | 
					    {#if person.name}
 | 
				
			||||||
      <span
 | 
					      <span class="absolute bottom-2 left-0 w-full select-text px-1 text-center font-medium text-white">
 | 
				
			||||||
        class="w-100 absolute bottom-2 w-full text-ellipsis px-1 text-center font-medium text-white backdrop-blur-[1px] hover:cursor-pointer"
 | 
					 | 
				
			||||||
      >
 | 
					 | 
				
			||||||
        {person.name}
 | 
					        {person.name}
 | 
				
			||||||
      </span>
 | 
					      </span>
 | 
				
			||||||
    {/if}
 | 
					    {/if}
 | 
				
			||||||
@ -50,6 +52,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    {#if showContextMenu}
 | 
					    {#if showContextMenu}
 | 
				
			||||||
      <ContextMenu on:outclick={() => (showContextMenu = false)}>
 | 
					      <ContextMenu on:outclick={() => (showContextMenu = false)}>
 | 
				
			||||||
 | 
					        <MenuOption on:click={() => onHideFaceClicked()} text="Hide face" />
 | 
				
			||||||
        <MenuOption on:click={() => onChangeNameClicked()} text="Change name" />
 | 
					        <MenuOption on:click={() => onChangeNameClicked()} text="Change name" />
 | 
				
			||||||
        <MenuOption on:click={() => onMergeFacesClicked()} text="Merge faces" />
 | 
					        <MenuOption on:click={() => onMergeFacesClicked()} text="Merge faces" />
 | 
				
			||||||
      </ContextMenu>
 | 
					      </ContextMenu>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,19 @@
 | 
				
			|||||||
<script>
 | 
					<script lang="ts">
 | 
				
			||||||
  import { fly } from 'svelte/transition';
 | 
					  import { fly } from 'svelte/transition';
 | 
				
			||||||
  import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
 | 
					  import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
 | 
				
			||||||
  import { quintOut } from 'svelte/easing';
 | 
					  import { quintOut } from 'svelte/easing';
 | 
				
			||||||
  import Close from 'svelte-material-icons/Close.svelte';
 | 
					  import Close from 'svelte-material-icons/Close.svelte';
 | 
				
			||||||
  import IconButton from '../elements/buttons/icon-button.svelte';
 | 
					  import IconButton from '../elements/buttons/icon-button.svelte';
 | 
				
			||||||
  import { createEventDispatcher } from 'svelte';
 | 
					  import { createEventDispatcher } from 'svelte';
 | 
				
			||||||
 | 
					  import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
 | 
				
			||||||
 | 
					  import Restart from 'svelte-material-icons/Restart.svelte';
 | 
				
			||||||
 | 
					  import Eye from 'svelte-material-icons/Eye.svelte';
 | 
				
			||||||
 | 
					  import EyeOff from 'svelte-material-icons/EyeOff.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const dispatch = createEventDispatcher();
 | 
					  const dispatch = createEventDispatcher();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  export let showLoadingSpinner: boolean;
 | 
				
			||||||
 | 
					  export let toggleVisibility: boolean;
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<section
 | 
					<section
 | 
				
			||||||
@ -14,17 +21,30 @@
 | 
				
			|||||||
  class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
 | 
					  class="absolute left-0 top-0 z-[9999] h-full w-full bg-immich-bg dark:bg-immich-dark-bg"
 | 
				
			||||||
>
 | 
					>
 | 
				
			||||||
  <div
 | 
					  <div
 | 
				
			||||||
    class="absolute flex h-16 w-full place-items-center justify-between border-b dark:border-immich-dark-gray dark:text-immich-dark-fg"
 | 
					    class="sticky top-0 z-10 flex h-16 w-full items-center justify-between border-b bg-white p-1 dark:border-immich-dark-gray dark:bg-black dark:text-immich-dark-fg md:p-8"
 | 
				
			||||||
  >
 | 
					  >
 | 
				
			||||||
    <div class="flex w-full items-center justify-between p-8">
 | 
					 | 
				
			||||||
    <div class="flex items-center">
 | 
					    <div class="flex items-center">
 | 
				
			||||||
      <CircleIconButton logo={Close} on:click={() => dispatch('closeClick')} />
 | 
					      <CircleIconButton logo={Close} on:click={() => dispatch('closeClick')} />
 | 
				
			||||||
        <p class="ml-4">Show & hide faces</p>
 | 
					      <p class="ml-4 hidden sm:block">Show & hide faces</p>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div class="flex items-center justify-end">
 | 
				
			||||||
 | 
					      <div class="flex items-center md:mr-8">
 | 
				
			||||||
 | 
					        <CircleIconButton title="Reset faces visibility" logo={Restart} on:click={() => dispatch('reset-visibility')} />
 | 
				
			||||||
 | 
					        <CircleIconButton
 | 
				
			||||||
 | 
					          title="Toggle visibility"
 | 
				
			||||||
 | 
					          logo={toggleVisibility ? Eye : EyeOff}
 | 
				
			||||||
 | 
					          on:click={() => dispatch('toggle-visibility')}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      {#if !showLoadingSpinner}
 | 
				
			||||||
        <IconButton on:click={() => dispatch('doneClick')}>Done</IconButton>
 | 
					        <IconButton on:click={() => dispatch('doneClick')}>Done</IconButton>
 | 
				
			||||||
 | 
					      {:else}
 | 
				
			||||||
 | 
					        <LoadingSpinner />
 | 
				
			||||||
 | 
					      {/if}
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="immich-scrollbar absolute top-16 h-[calc(100%-theme(spacing.16))] w-full p-4 pb-8">
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <div class="flex w-full flex-wrap gap-1 bg-immich-bg p-2 pb-8 dark:bg-immich-dark-bg md:px-8 md:pt-4">
 | 
				
			||||||
    <slot />
 | 
					    <slot />
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
</section>
 | 
					</section>
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@
 | 
				
			|||||||
  import PeopleCard from '$lib/components/faces-page/people-card.svelte';
 | 
					  import PeopleCard from '$lib/components/faces-page/people-card.svelte';
 | 
				
			||||||
  import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
 | 
					  import FullScreenModal from '$lib/components/shared-components/full-screen-modal.svelte';
 | 
				
			||||||
  import Button from '$lib/components/elements/buttons/button.svelte';
 | 
					  import Button from '$lib/components/elements/buttons/button.svelte';
 | 
				
			||||||
  import { api, type PersonResponseDto } from '@api';
 | 
					  import { api, PeopleUpdateItem, type PersonResponseDto } from '@api';
 | 
				
			||||||
  import { goto } from '$app/navigation';
 | 
					  import { goto } from '$app/navigation';
 | 
				
			||||||
  import { AppRoute } from '$lib/constants';
 | 
					  import { AppRoute } from '$lib/constants';
 | 
				
			||||||
  import { handleError } from '$lib/utils/handle-error';
 | 
					  import { handleError } from '$lib/utils/handle-error';
 | 
				
			||||||
@ -17,41 +17,86 @@
 | 
				
			|||||||
  import IconButton from '$lib/components/elements/buttons/icon-button.svelte';
 | 
					  import IconButton from '$lib/components/elements/buttons/icon-button.svelte';
 | 
				
			||||||
  import EyeOutline from 'svelte-material-icons/EyeOutline.svelte';
 | 
					  import EyeOutline from 'svelte-material-icons/EyeOutline.svelte';
 | 
				
			||||||
  import ImageThumbnail from '$lib/components/assets/thumbnail/image-thumbnail.svelte';
 | 
					  import ImageThumbnail from '$lib/components/assets/thumbnail/image-thumbnail.svelte';
 | 
				
			||||||
 | 
					  import { onDestroy, onMount } from 'svelte';
 | 
				
			||||||
 | 
					  import { browser } from '$app/environment';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export let data: PageData;
 | 
					  export let data: PageData;
 | 
				
			||||||
  let selectHidden = false;
 | 
					  let selectHidden = false;
 | 
				
			||||||
  let changeCounter = 0;
 | 
					 | 
				
			||||||
  let initialHiddenValues: Record<string, boolean> = {};
 | 
					  let initialHiddenValues: Record<string, boolean> = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let eyeColorMap: Record<string, string> = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let people = data.people.people;
 | 
					  let people = data.people.people;
 | 
				
			||||||
  let countTotalPeople = data.people.total;
 | 
					  let countTotalPeople = data.people.total;
 | 
				
			||||||
  let countVisiblePeople = data.people.visible;
 | 
					  let countVisiblePeople = data.people.visible;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  let showLoadingSpinner = false;
 | 
				
			||||||
 | 
					  let toggleVisibility = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  people.forEach((person: PersonResponseDto) => {
 | 
					  people.forEach((person: PersonResponseDto) => {
 | 
				
			||||||
    initialHiddenValues[person.id] = person.isHidden;
 | 
					    initialHiddenValues[person.id] = person.isHidden;
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handleCloseClick = () => {
 | 
					  const onKeyboardPress = (event: KeyboardEvent) => handleKeyboardPress(event);
 | 
				
			||||||
    selectHidden = false;
 | 
					
 | 
				
			||||||
    people.forEach((person: PersonResponseDto) => {
 | 
					  onMount(() => {
 | 
				
			||||||
      person.isHidden = initialHiddenValues[person.id];
 | 
					    document.addEventListener('keydown', onKeyboardPress);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onDestroy(() => {
 | 
				
			||||||
 | 
					    if (browser) {
 | 
				
			||||||
 | 
					      document.removeEventListener('keydown', onKeyboardPress);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleKeyboardPress = (event: KeyboardEvent) => {
 | 
				
			||||||
 | 
					    switch (event.key) {
 | 
				
			||||||
 | 
					      case 'Escape':
 | 
				
			||||||
 | 
					        handleCloseClick();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleCloseClick = () => {
 | 
				
			||||||
 | 
					    for (const person of people) {
 | 
				
			||||||
 | 
					      person.isHidden = initialHiddenValues[person.id];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // trigger reactivity
 | 
				
			||||||
 | 
					    people = people;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Reset variables used on the "Show & hide faces"   modal
 | 
				
			||||||
 | 
					    showLoadingSpinner = false;
 | 
				
			||||||
 | 
					    selectHidden = false;
 | 
				
			||||||
 | 
					    toggleVisibility = false;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleResetVisibility = () => {
 | 
				
			||||||
 | 
					    for (const person of people) {
 | 
				
			||||||
 | 
					      person.isHidden = initialHiddenValues[person.id];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // trigger reactivity
 | 
				
			||||||
 | 
					    people = people;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleToggleVisibility = () => {
 | 
				
			||||||
 | 
					    toggleVisibility = !toggleVisibility;
 | 
				
			||||||
 | 
					    for (const person of people) {
 | 
				
			||||||
 | 
					      person.isHidden = toggleVisibility;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // trigger reactivity
 | 
				
			||||||
 | 
					    people = people;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handleDoneClick = async () => {
 | 
					  const handleDoneClick = async () => {
 | 
				
			||||||
    selectHidden = false;
 | 
					    showLoadingSpinner = true;
 | 
				
			||||||
 | 
					    let changed: PeopleUpdateItem[] = [];
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      // Reset the counter before checking changes
 | 
					 | 
				
			||||||
      let changeCounter = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      // Check if the visibility for each person has been changed
 | 
					      // Check if the visibility for each person has been changed
 | 
				
			||||||
      for (const person of people) {
 | 
					      for (const person of people) {
 | 
				
			||||||
        if (person.isHidden !== initialHiddenValues[person.id]) {
 | 
					        if (person.isHidden !== initialHiddenValues[person.id]) {
 | 
				
			||||||
          changeCounter++;
 | 
					          changed.push({ id: person.id, isHidden: person.isHidden });
 | 
				
			||||||
          await api.personApi.updatePerson({
 | 
					 | 
				
			||||||
            id: person.id,
 | 
					 | 
				
			||||||
            personUpdateDto: { isHidden: person.isHidden },
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
          // Update the initial hidden values
 | 
					          // Update the initial hidden values
 | 
				
			||||||
          initialHiddenValues[person.id] = person.isHidden;
 | 
					          initialHiddenValues[person.id] = person.isHidden;
 | 
				
			||||||
@ -61,18 +106,34 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (changeCounter > 0) {
 | 
					      if (changed.length > 0) {
 | 
				
			||||||
 | 
					        const { data: results } = await api.personApi.updatePeople({
 | 
				
			||||||
 | 
					          peopleUpdateDto: { people: changed },
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        const count = results.filter(({ success }) => success).length;
 | 
				
			||||||
 | 
					        if (results.length - count > 0) {
 | 
				
			||||||
 | 
					          notificationController.show({
 | 
				
			||||||
 | 
					            type: NotificationType.Error,
 | 
				
			||||||
 | 
					            message: `Unable to change the visibility for ${results.length - count} ${
 | 
				
			||||||
 | 
					              results.length - count <= 1 ? 'person' : 'people'
 | 
				
			||||||
 | 
					            }`,
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        notificationController.show({
 | 
					        notificationController.show({
 | 
				
			||||||
          type: NotificationType.Info,
 | 
					          type: NotificationType.Info,
 | 
				
			||||||
          message: `Visibility changed for ${changeCounter} ${changeCounter <= 1 ? 'person' : 'people'}`,
 | 
					          message: `Visibility changed for ${count} ${count <= 1 ? 'person' : 'people'}`,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
      handleError(
 | 
					      handleError(
 | 
				
			||||||
        error,
 | 
					        error,
 | 
				
			||||||
        `Unable to change the visibility for ${changeCounter} ${changeCounter <= 1 ? 'person' : 'people'}`,
 | 
					        `Unable to change the visibility for ${changed.length} ${changed.length <= 1 ? 'person' : 'people'}`,
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    // Reset variables used on the "Show & hide faces" modal
 | 
				
			||||||
 | 
					    showLoadingSpinner = false;
 | 
				
			||||||
 | 
					    selectHidden = false;
 | 
				
			||||||
 | 
					    toggleVisibility = false;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let showChangeNameModal = false;
 | 
					  let showChangeNameModal = false;
 | 
				
			||||||
@ -85,6 +146,37 @@
 | 
				
			|||||||
    edittingPerson = detail;
 | 
					    edittingPerson = detail;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleHideFace = async (event: CustomEvent<PersonResponseDto>) => {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const { data: updatedPerson } = await api.personApi.updatePerson({
 | 
				
			||||||
 | 
					        id: event.detail.id,
 | 
				
			||||||
 | 
					        personUpdateDto: { isHidden: true },
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      people = people.map((person: PersonResponseDto) => {
 | 
				
			||||||
 | 
					        if (person.id === updatedPerson.id) {
 | 
				
			||||||
 | 
					          return updatedPerson;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return person;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      people.forEach((person: PersonResponseDto) => {
 | 
				
			||||||
 | 
					        initialHiddenValues[person.id] = person.isHidden;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      countVisiblePeople--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      showChangeNameModal = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      notificationController.show({
 | 
				
			||||||
 | 
					        message: 'Changed visibility succesfully',
 | 
				
			||||||
 | 
					        type: NotificationType.Info,
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    } catch (error) {
 | 
				
			||||||
 | 
					      handleError(error, 'Unable to hide person');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const handleMergeFaces = (event: CustomEvent<PersonResponseDto>) => {
 | 
					  const handleMergeFaces = (event: CustomEvent<PersonResponseDto>) => {
 | 
				
			||||||
    goto(`${AppRoute.PEOPLE}/${event.detail.id}?action=merge`);
 | 
					    goto(`${AppRoute.PEOPLE}/${event.detail.id}?action=merge`);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
@ -132,13 +224,16 @@
 | 
				
			|||||||
  {#if countVisiblePeople > 0}
 | 
					  {#if countVisiblePeople > 0}
 | 
				
			||||||
    <div class="pl-4">
 | 
					    <div class="pl-4">
 | 
				
			||||||
      <div class="flex flex-row flex-wrap gap-1">
 | 
					      <div class="flex flex-row flex-wrap gap-1">
 | 
				
			||||||
        {#key selectHidden}
 | 
					 | 
				
			||||||
        {#each people as person (person.id)}
 | 
					        {#each people as person (person.id)}
 | 
				
			||||||
          {#if !person.isHidden}
 | 
					          {#if !person.isHidden}
 | 
				
			||||||
              <PeopleCard {person} on:change-name={handleChangeName} on:merge-faces={handleMergeFaces} />
 | 
					            <PeopleCard
 | 
				
			||||||
 | 
					              {person}
 | 
				
			||||||
 | 
					              on:change-name={handleChangeName}
 | 
				
			||||||
 | 
					              on:merge-faces={handleMergeFaces}
 | 
				
			||||||
 | 
					              on:hide-face={handleHideFace}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
          {/if}
 | 
					          {/if}
 | 
				
			||||||
        {/each}
 | 
					        {/each}
 | 
				
			||||||
        {/key}
 | 
					 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  {:else}
 | 
					  {:else}
 | 
				
			||||||
@ -184,32 +279,35 @@
 | 
				
			|||||||
  {/if}
 | 
					  {/if}
 | 
				
			||||||
</UserPageLayout>
 | 
					</UserPageLayout>
 | 
				
			||||||
{#if selectHidden}
 | 
					{#if selectHidden}
 | 
				
			||||||
  <ShowHide on:doneClick={handleDoneClick} on:closeClick={handleCloseClick}>
 | 
					  <ShowHide
 | 
				
			||||||
    <div class="pl-4">
 | 
					    on:doneClick={handleDoneClick}
 | 
				
			||||||
      <div class="flex flex-row flex-wrap gap-1">
 | 
					    on:closeClick={handleCloseClick}
 | 
				
			||||||
 | 
					    on:reset-visibility={handleResetVisibility}
 | 
				
			||||||
 | 
					    on:toggle-visibility={handleToggleVisibility}
 | 
				
			||||||
 | 
					    bind:showLoadingSpinner
 | 
				
			||||||
 | 
					    bind:toggleVisibility
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
    {#each people as person (person.id)}
 | 
					    {#each people as person (person.id)}
 | 
				
			||||||
          <div class="relative">
 | 
					      <button
 | 
				
			||||||
            <div class="h-48 w-48 rounded-xl brightness-95 filter">
 | 
					        class="relative h-36 w-36 md:h-48 md:w-48"
 | 
				
			||||||
              <button class="h-full w-full" on:click={() => (person.isHidden = !person.isHidden)}>
 | 
					        on:click={() => (person.isHidden = !person.isHidden)}
 | 
				
			||||||
 | 
					        on:mouseenter={() => (eyeColorMap[person.id] = 'black')}
 | 
				
			||||||
 | 
					        on:mouseleave={() => (eyeColorMap[person.id] = 'white')}
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
        <ImageThumbnail
 | 
					        <ImageThumbnail
 | 
				
			||||||
          bind:hidden={person.isHidden}
 | 
					          bind:hidden={person.isHidden}
 | 
				
			||||||
          shadow
 | 
					          shadow
 | 
				
			||||||
          url={api.getPeopleThumbnailUrl(person.id)}
 | 
					          url={api.getPeopleThumbnailUrl(person.id)}
 | 
				
			||||||
          altText={person.name}
 | 
					          altText={person.name}
 | 
				
			||||||
          widthStyle="100%"
 | 
					          widthStyle="100%"
 | 
				
			||||||
 | 
					          bind:eyeColor={eyeColorMap[person.id]}
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
              </button>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
        {#if person.name}
 | 
					        {#if person.name}
 | 
				
			||||||
              <span
 | 
					          <span class="absolute bottom-2 left-0 w-full select-text px-1 text-center font-medium text-white">
 | 
				
			||||||
                class="w-100 absolute bottom-2 w-full text-ellipsis px-1 text-center font-medium text-white backdrop-blur-[1px] hover:cursor-pointer"
 | 
					 | 
				
			||||||
              >
 | 
					 | 
				
			||||||
            {person.name}
 | 
					            {person.name}
 | 
				
			||||||
          </span>
 | 
					          </span>
 | 
				
			||||||
        {/if}
 | 
					        {/if}
 | 
				
			||||||
          </div>
 | 
					      </button>
 | 
				
			||||||
    {/each}
 | 
					    {/each}
 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    </div>
 | 
					 | 
				
			||||||
  </ShowHide>
 | 
					  </ShowHide>
 | 
				
			||||||
{/if}
 | 
					{/if}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user