feat: unmerge people
This commit is contained in:
parent
acdc66413c
commit
c30a5db8f4
22 changed files with 696 additions and 41 deletions
107
cli/src/api/open-api/api.ts
generated
107
cli/src/api/open-api/api.ts
generated
|
@ -3663,6 +3663,25 @@ export const TranscodePolicy = {
|
|||
export type TranscodePolicy = typeof TranscodePolicy[keyof typeof TranscodePolicy];
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface UnMergePersonDto
|
||||
*/
|
||||
export interface UnMergePersonDto {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UnMergePersonDto
|
||||
*/
|
||||
'assetId': string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UnMergePersonDto
|
||||
*/
|
||||
'personId': string;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
|
@ -11080,6 +11099,50 @@ export const PersonApiAxiosParamCreator = function (configuration?: Configuratio
|
|||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {UnMergePersonDto} unMergePersonDto
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
unMergePerson: async (unMergePersonDto: UnMergePersonDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
// verify required parameter 'unMergePersonDto' is not null or undefined
|
||||
assertParamExists('unMergePerson', 'unMergePersonDto', unMergePersonDto)
|
||||
const localVarPath = `/person/unmerge`;
|
||||
// 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: 'POST', ...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(unMergePersonDto, localVarRequestOptions, configuration)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {PeopleUpdateDto} peopleUpdateDto
|
||||
|
@ -11233,6 +11296,16 @@ export const PersonApiFp = function(configuration?: Configuration) {
|
|||
const localVarAxiosArgs = await localVarAxiosParamCreator.mergePerson(id, mergePersonDto, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {UnMergePersonDto} unMergePersonDto
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async unMergePerson(unMergePersonDto: UnMergePersonDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<BulkIdResponseDto>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.unMergePerson(unMergePersonDto, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {PeopleUpdateDto} peopleUpdateDto
|
||||
|
@ -11309,6 +11382,15 @@ export const PersonApiFactory = function (configuration?: Configuration, basePat
|
|||
mergePerson(requestParameters: PersonApiMergePersonRequest, options?: AxiosRequestConfig): AxiosPromise<Array<BulkIdResponseDto>> {
|
||||
return localVarFp.mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {PersonApiUnMergePersonRequest} requestParameters Request parameters.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
unMergePerson(requestParameters: PersonApiUnMergePersonRequest, options?: AxiosRequestConfig): AxiosPromise<BulkIdResponseDto> {
|
||||
return localVarFp.unMergePerson(requestParameters.unMergePersonDto, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
|
||||
|
@ -11407,6 +11489,20 @@ export interface PersonApiMergePersonRequest {
|
|||
readonly mergePersonDto: MergePersonDto
|
||||
}
|
||||
|
||||
/**
|
||||
* Request parameters for unMergePerson operation in PersonApi.
|
||||
* @export
|
||||
* @interface PersonApiUnMergePersonRequest
|
||||
*/
|
||||
export interface PersonApiUnMergePersonRequest {
|
||||
/**
|
||||
*
|
||||
* @type {UnMergePersonDto}
|
||||
* @memberof PersonApiUnMergePerson
|
||||
*/
|
||||
readonly unMergePersonDto: UnMergePersonDto
|
||||
}
|
||||
|
||||
/**
|
||||
* Request parameters for updatePeople operation in PersonApi.
|
||||
* @export
|
||||
|
@ -11504,6 +11600,17 @@ export class PersonApi extends BaseAPI {
|
|||
return PersonApiFp(this.configuration).mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {PersonApiUnMergePersonRequest} requestParameters Request parameters.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof PersonApi
|
||||
*/
|
||||
public unMergePerson(requestParameters: PersonApiUnMergePersonRequest, options?: AxiosRequestConfig) {
|
||||
return PersonApiFp(this.configuration).unMergePerson(requestParameters.unMergePersonDto, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
|
||||
|
|
3
mobile/openapi/.openapi-generator/FILES
generated
3
mobile/openapi/.openapi-generator/FILES
generated
|
@ -138,6 +138,7 @@ doc/TimeBucketSize.md
|
|||
doc/ToneMapping.md
|
||||
doc/TranscodeHWAccel.md
|
||||
doc/TranscodePolicy.md
|
||||
doc/UnMergePersonDto.md
|
||||
doc/UpdateAlbumDto.md
|
||||
doc/UpdateAssetDto.md
|
||||
doc/UpdateLibraryDto.md
|
||||
|
@ -295,6 +296,7 @@ lib/model/time_bucket_size.dart
|
|||
lib/model/tone_mapping.dart
|
||||
lib/model/transcode_hw_accel.dart
|
||||
lib/model/transcode_policy.dart
|
||||
lib/model/un_merge_person_dto.dart
|
||||
lib/model/update_album_dto.dart
|
||||
lib/model/update_asset_dto.dart
|
||||
lib/model/update_library_dto.dart
|
||||
|
@ -441,6 +443,7 @@ test/time_bucket_size_test.dart
|
|||
test/tone_mapping_test.dart
|
||||
test/transcode_hw_accel_test.dart
|
||||
test/transcode_policy_test.dart
|
||||
test/un_merge_person_dto_test.dart
|
||||
test/update_album_dto_test.dart
|
||||
test/update_asset_dto_test.dart
|
||||
test/update_library_dto_test.dart
|
||||
|
|
2
mobile/openapi/README.md
generated
2
mobile/openapi/README.md
generated
|
@ -146,6 +146,7 @@ Class | Method | HTTP request | Description
|
|||
*PersonApi* | [**getPersonAssets**](doc//PersonApi.md#getpersonassets) | **GET** /person/{id}/assets |
|
||||
*PersonApi* | [**getPersonThumbnail**](doc//PersonApi.md#getpersonthumbnail) | **GET** /person/{id}/thumbnail |
|
||||
*PersonApi* | [**mergePerson**](doc//PersonApi.md#mergeperson) | **POST** /person/{id}/merge |
|
||||
*PersonApi* | [**unMergePerson**](doc//PersonApi.md#unmergeperson) | **POST** /person/unmerge |
|
||||
*PersonApi* | [**updatePeople**](doc//PersonApi.md#updatepeople) | **PUT** /person |
|
||||
*PersonApi* | [**updatePerson**](doc//PersonApi.md#updateperson) | **PUT** /person/{id} |
|
||||
*SearchApi* | [**getExploreData**](doc//SearchApi.md#getexploredata) | **GET** /search/explore |
|
||||
|
@ -311,6 +312,7 @@ Class | Method | HTTP request | Description
|
|||
- [ToneMapping](doc//ToneMapping.md)
|
||||
- [TranscodeHWAccel](doc//TranscodeHWAccel.md)
|
||||
- [TranscodePolicy](doc//TranscodePolicy.md)
|
||||
- [UnMergePersonDto](doc//UnMergePersonDto.md)
|
||||
- [UpdateAlbumDto](doc//UpdateAlbumDto.md)
|
||||
- [UpdateAssetDto](doc//UpdateAssetDto.md)
|
||||
- [UpdateLibraryDto](doc//UpdateLibraryDto.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 |
|
||||
[**getPersonThumbnail**](PersonApi.md#getpersonthumbnail) | **GET** /person/{id}/thumbnail |
|
||||
[**mergePerson**](PersonApi.md#mergeperson) | **POST** /person/{id}/merge |
|
||||
[**unMergePerson**](PersonApi.md#unmergeperson) | **POST** /person/unmerge |
|
||||
[**updatePeople**](PersonApi.md#updatepeople) | **PUT** /person |
|
||||
[**updatePerson**](PersonApi.md#updateperson) | **PUT** /person/{id} |
|
||||
|
||||
|
@ -295,6 +296,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)
|
||||
|
||||
# **unMergePerson**
|
||||
> BulkIdResponseDto unMergePerson(unMergePersonDto)
|
||||
|
||||
|
||||
|
||||
### 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 unMergePersonDto = UnMergePersonDto(); // UnMergePersonDto |
|
||||
|
||||
try {
|
||||
final result = api_instance.unMergePerson(unMergePersonDto);
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling PersonApi->unMergePerson: $e\n');
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------
|
||||
**unMergePersonDto** | [**UnMergePersonDto**](UnMergePersonDto.md)| |
|
||||
|
||||
### Return type
|
||||
|
||||
[**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)
|
||||
|
||||
# **updatePeople**
|
||||
> List<BulkIdResponseDto> updatePeople(peopleUpdateDto)
|
||||
|
||||
|
|
16
mobile/openapi/doc/UnMergePersonDto.md
generated
Normal file
16
mobile/openapi/doc/UnMergePersonDto.md
generated
Normal file
|
@ -0,0 +1,16 @@
|
|||
# openapi.model.UnMergePersonDto
|
||||
|
||||
## Load the model package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**assetId** | **String** | |
|
||||
**personId** | **String** | |
|
||||
|
||||
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
|
||||
|
||||
|
1
mobile/openapi/lib/api.dart
generated
1
mobile/openapi/lib/api.dart
generated
|
@ -165,6 +165,7 @@ part 'model/time_bucket_size.dart';
|
|||
part 'model/tone_mapping.dart';
|
||||
part 'model/transcode_hw_accel.dart';
|
||||
part 'model/transcode_policy.dart';
|
||||
part 'model/un_merge_person_dto.dart';
|
||||
part 'model/update_album_dto.dart';
|
||||
part 'model/update_asset_dto.dart';
|
||||
part 'model/update_library_dto.dart';
|
||||
|
|
47
mobile/openapi/lib/api/person_api.dart
generated
47
mobile/openapi/lib/api/person_api.dart
generated
|
@ -269,6 +269,53 @@ class PersonApi {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'POST /person/unmerge' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [UnMergePersonDto] unMergePersonDto (required):
|
||||
Future<Response> unMergePersonWithHttpInfo(UnMergePersonDto unMergePersonDto,) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/person/unmerge';
|
||||
|
||||
// ignore: prefer_final_locals
|
||||
Object? postBody = unMergePersonDto;
|
||||
|
||||
final queryParams = <QueryParam>[];
|
||||
final headerParams = <String, String>{};
|
||||
final formParams = <String, String>{};
|
||||
|
||||
const contentTypes = <String>['application/json'];
|
||||
|
||||
|
||||
return apiClient.invokeAPI(
|
||||
path,
|
||||
'POST',
|
||||
queryParams,
|
||||
postBody,
|
||||
headerParams,
|
||||
formParams,
|
||||
contentTypes.isEmpty ? null : contentTypes.first,
|
||||
);
|
||||
}
|
||||
|
||||
/// Parameters:
|
||||
///
|
||||
/// * [UnMergePersonDto] unMergePersonDto (required):
|
||||
Future<BulkIdResponseDto?> unMergePerson(UnMergePersonDto unMergePersonDto,) async {
|
||||
final response = await unMergePersonWithHttpInfo(unMergePersonDto,);
|
||||
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) {
|
||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'BulkIdResponseDto',) as BulkIdResponseDto;
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Performs an HTTP 'PUT /person' operation and returns the [Response].
|
||||
/// Parameters:
|
||||
///
|
||||
|
|
2
mobile/openapi/lib/api_client.dart
generated
2
mobile/openapi/lib/api_client.dart
generated
|
@ -421,6 +421,8 @@ class ApiClient {
|
|||
return TranscodeHWAccelTypeTransformer().decode(value);
|
||||
case 'TranscodePolicy':
|
||||
return TranscodePolicyTypeTransformer().decode(value);
|
||||
case 'UnMergePersonDto':
|
||||
return UnMergePersonDto.fromJson(value);
|
||||
case 'UpdateAlbumDto':
|
||||
return UpdateAlbumDto.fromJson(value);
|
||||
case 'UpdateAssetDto':
|
||||
|
|
106
mobile/openapi/lib/model/un_merge_person_dto.dart
generated
Normal file
106
mobile/openapi/lib/model/un_merge_person_dto.dart
generated
Normal file
|
@ -0,0 +1,106 @@
|
|||
//
|
||||
// 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 UnMergePersonDto {
|
||||
/// Returns a new [UnMergePersonDto] instance.
|
||||
UnMergePersonDto({
|
||||
required this.assetId,
|
||||
required this.personId,
|
||||
});
|
||||
|
||||
String assetId;
|
||||
|
||||
String personId;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is UnMergePersonDto &&
|
||||
other.assetId == assetId &&
|
||||
other.personId == personId;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(assetId.hashCode) +
|
||||
(personId.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'UnMergePersonDto[assetId=$assetId, personId=$personId]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'assetId'] = this.assetId;
|
||||
json[r'personId'] = this.personId;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [UnMergePersonDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static UnMergePersonDto? fromJson(dynamic value) {
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return UnMergePersonDto(
|
||||
assetId: mapValueOfType<String>(json, r'assetId')!,
|
||||
personId: mapValueOfType<String>(json, r'personId')!,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<UnMergePersonDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <UnMergePersonDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = UnMergePersonDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, UnMergePersonDto> mapFromJson(dynamic json) {
|
||||
final map = <String, UnMergePersonDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = UnMergePersonDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of UnMergePersonDto-objects as value to a dart map
|
||||
static Map<String, List<UnMergePersonDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<UnMergePersonDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = UnMergePersonDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'assetId',
|
||||
'personId',
|
||||
};
|
||||
}
|
||||
|
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
|
||||
});
|
||||
|
||||
//Future<BulkIdResponseDto> unMergePerson(UnMergePersonDto unMergePersonDto) async
|
||||
test('test unMergePerson', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
//Future<List<BulkIdResponseDto>> updatePeople(PeopleUpdateDto peopleUpdateDto) async
|
||||
test('test updatePeople', () async {
|
||||
// TODO
|
||||
|
|
32
mobile/openapi/test/un_merge_person_dto_test.dart
generated
Normal file
32
mobile/openapi/test/un_merge_person_dto_test.dart
generated
Normal file
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// 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 UnMergePersonDto
|
||||
void main() {
|
||||
// final instance = UnMergePersonDto();
|
||||
|
||||
group('test UnMergePersonDto', () {
|
||||
// String assetId
|
||||
test('to test the property `assetId`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// String personId
|
||||
test('to test the property `personId`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
|
@ -3189,6 +3189,48 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"/person/unmerge": {
|
||||
"post": {
|
||||
"operationId": "unMergePerson",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/UnMergePersonDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/BulkIdResponseDto"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"bearer": []
|
||||
},
|
||||
{
|
||||
"cookie": []
|
||||
},
|
||||
{
|
||||
"api_key": []
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Person"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/person/{id}": {
|
||||
"get": {
|
||||
"operationId": "getPerson",
|
||||
|
@ -7967,6 +8009,21 @@
|
|||
],
|
||||
"type": "string"
|
||||
},
|
||||
"UnMergePersonDto": {
|
||||
"properties": {
|
||||
"assetId": {
|
||||
"type": "string"
|
||||
},
|
||||
"personId": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"assetId",
|
||||
"personId"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"UpdateAlbumDto": {
|
||||
"properties": {
|
||||
"albumName": {
|
||||
|
|
|
@ -58,6 +58,15 @@ export class MergePersonDto {
|
|||
ids!: string[];
|
||||
}
|
||||
|
||||
export class UnMergePersonDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
assetId!: string;
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
personId!: string;
|
||||
}
|
||||
|
||||
export class PersonSearchDto {
|
||||
@IsBoolean()
|
||||
@Transform(toBoolean)
|
||||
|
|
|
@ -22,6 +22,7 @@ export interface IPersonRepository {
|
|||
getAssets(personId: string): Promise<AssetEntity[]>;
|
||||
prepareReassignFaces(data: UpdateFacesData): Promise<string[]>;
|
||||
reassignFaces(data: UpdateFacesData): Promise<number>;
|
||||
removeFaceFromPerson(oldPersonId: string, newPersonId: string, assetId: string): Promise<number>;
|
||||
|
||||
create(entity: Partial<PersonEntity>): Promise<PersonEntity>;
|
||||
update(entity: Partial<PersonEntity>): Promise<PersonEntity>;
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
PersonResponseDto,
|
||||
PersonSearchDto,
|
||||
PersonUpdateDto,
|
||||
UnMergePersonDto,
|
||||
mapPerson,
|
||||
} from './person.dto';
|
||||
import { IPersonRepository, UpdateFacesData } from './person.repository';
|
||||
|
@ -147,6 +148,56 @@ export class PersonService {
|
|||
return true;
|
||||
}
|
||||
|
||||
async unMergePerson(authUser: AuthUserDto, dto: UnMergePersonDto): Promise<BulkIdResponseDto> {
|
||||
await this.access.requirePermission(authUser, Permission.PERSON_WRITE, dto.personId);
|
||||
|
||||
const oldPerson = await this.findOrFail(dto.personId);
|
||||
|
||||
const newPerson = await this.repository.create({ ownerId: authUser.id });
|
||||
let result: BulkIdResponseDto;
|
||||
try {
|
||||
const mergePerson = await this.repository.getById(oldPerson.id);
|
||||
if (!mergePerson) {
|
||||
result = { id: oldPerson.id, success: false, error: BulkIdErrorReason.NOT_FOUND };
|
||||
}
|
||||
|
||||
this.logger.log(`un-merging ${dto.assetId} from ${oldPerson.id}`);
|
||||
await this.repository.removeFaceFromPerson(oldPerson.id, newPerson.id, dto.assetId);
|
||||
|
||||
await this.repository.update({
|
||||
id: newPerson.id,
|
||||
faceAssetId: dto.assetId,
|
||||
});
|
||||
|
||||
const assetId = dto.assetId;
|
||||
const face = await this.repository.getFaceById({ personId: newPerson.id, assetId });
|
||||
if (!face) {
|
||||
throw new BadRequestException('Invalid assetId for feature face');
|
||||
}
|
||||
await this.jobRepository.queue({
|
||||
name: JobName.GENERATE_FACE_THUMBNAIL,
|
||||
data: {
|
||||
personId: newPerson.id,
|
||||
assetId: dto.assetId,
|
||||
boundingBox: {
|
||||
x1: face.boundingBoxX1,
|
||||
x2: face.boundingBoxX2,
|
||||
y1: face.boundingBoxY1,
|
||||
y2: face.boundingBoxY2,
|
||||
},
|
||||
imageHeight: face.imageHeight,
|
||||
imageWidth: face.imageWidth,
|
||||
},
|
||||
});
|
||||
|
||||
result = { id: oldPerson.id, success: true };
|
||||
} catch (error: Error | any) {
|
||||
this.logger.error(`Unable to un-merge asset ${dto.assetId} from ${oldPerson.id}`, error?.stack);
|
||||
result = { id: oldPerson.id, success: false, error: BulkIdErrorReason.UNKNOWN };
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async mergePerson(authUser: AuthUserDto, id: string, dto: MergePersonDto): Promise<BulkIdResponseDto[]> {
|
||||
const mergeIds = dto.ids;
|
||||
await this.access.requirePermission(authUser, Permission.PERSON_WRITE, id);
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
PersonSearchDto,
|
||||
PersonService,
|
||||
PersonUpdateDto,
|
||||
UnMergePersonDto,
|
||||
} from '@app/domain';
|
||||
import { Body, Controller, Get, Param, Post, Put, Query, StreamableFile } from '@nestjs/common';
|
||||
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
|
||||
|
@ -28,6 +29,11 @@ function asStreamableFile({ stream, type, length }: ImmichReadStream) {
|
|||
export class PersonController {
|
||||
constructor(private service: PersonService) {}
|
||||
|
||||
@Post('/unmerge')
|
||||
unMergePerson(@AuthUser() authUser: AuthUserDto, @Body() dto: UnMergePersonDto): Promise<BulkIdResponseDto> {
|
||||
return this.service.unMergePerson(authUser, dto);
|
||||
}
|
||||
|
||||
@Get()
|
||||
getAllPeople(@AuthUser() authUser: AuthUserDto, @Query() withHidden: PersonSearchDto): Promise<PeopleResponseDto> {
|
||||
return this.service.getAll(authUser, withHidden);
|
||||
|
|
|
@ -40,6 +40,18 @@ export class PersonRepository implements IPersonRepository {
|
|||
return result.affected ?? 0;
|
||||
}
|
||||
|
||||
async removeFaceFromPerson(oldPersonId: string, newPersonId: string, assetId: string): Promise<number> {
|
||||
const result = await this.assetFaceRepository
|
||||
.createQueryBuilder()
|
||||
.update()
|
||||
.set({ personId: newPersonId })
|
||||
.where({ personId: oldPersonId })
|
||||
.andWhere({ assetId })
|
||||
.execute();
|
||||
|
||||
return result.affected ?? 0;
|
||||
}
|
||||
|
||||
delete(entity: PersonEntity): Promise<PersonEntity | null> {
|
||||
return this.personRepository.remove(entity);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ export const newPersonRepositoryMock = (): jest.Mocked<IPersonRepository> => {
|
|||
getAssets: jest.fn(),
|
||||
getAllWithoutFaces: jest.fn(),
|
||||
|
||||
removeFaceFromPerson: jest.fn(),
|
||||
|
||||
create: jest.fn(),
|
||||
update: jest.fn(),
|
||||
deleteAll: jest.fn(),
|
||||
|
|
107
web/src/api/open-api/api.ts
generated
107
web/src/api/open-api/api.ts
generated
|
@ -3663,6 +3663,25 @@ export const TranscodePolicy = {
|
|||
export type TranscodePolicy = typeof TranscodePolicy[keyof typeof TranscodePolicy];
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface UnMergePersonDto
|
||||
*/
|
||||
export interface UnMergePersonDto {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UnMergePersonDto
|
||||
*/
|
||||
'assetId': string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof UnMergePersonDto
|
||||
*/
|
||||
'personId': string;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
|
@ -11080,6 +11099,50 @@ export const PersonApiAxiosParamCreator = function (configuration?: Configuratio
|
|||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {UnMergePersonDto} unMergePersonDto
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
unMergePerson: async (unMergePersonDto: UnMergePersonDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
// verify required parameter 'unMergePersonDto' is not null or undefined
|
||||
assertParamExists('unMergePerson', 'unMergePersonDto', unMergePersonDto)
|
||||
const localVarPath = `/person/unmerge`;
|
||||
// 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: 'POST', ...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(unMergePersonDto, localVarRequestOptions, configuration)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
};
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {PeopleUpdateDto} peopleUpdateDto
|
||||
|
@ -11233,6 +11296,16 @@ export const PersonApiFp = function(configuration?: Configuration) {
|
|||
const localVarAxiosArgs = await localVarAxiosParamCreator.mergePerson(id, mergePersonDto, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {UnMergePersonDto} unMergePersonDto
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async unMergePerson(unMergePersonDto: UnMergePersonDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<BulkIdResponseDto>> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.unMergePerson(unMergePersonDto, options);
|
||||
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {PeopleUpdateDto} peopleUpdateDto
|
||||
|
@ -11309,6 +11382,15 @@ export const PersonApiFactory = function (configuration?: Configuration, basePat
|
|||
mergePerson(requestParameters: PersonApiMergePersonRequest, options?: AxiosRequestConfig): AxiosPromise<Array<BulkIdResponseDto>> {
|
||||
return localVarFp.mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {PersonApiUnMergePersonRequest} requestParameters Request parameters.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
unMergePerson(requestParameters: PersonApiUnMergePersonRequest, options?: AxiosRequestConfig): AxiosPromise<BulkIdResponseDto> {
|
||||
return localVarFp.unMergePerson(requestParameters.unMergePersonDto, options).then((request) => request(axios, basePath));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
|
||||
|
@ -11407,6 +11489,20 @@ export interface PersonApiMergePersonRequest {
|
|||
readonly mergePersonDto: MergePersonDto
|
||||
}
|
||||
|
||||
/**
|
||||
* Request parameters for unMergePerson operation in PersonApi.
|
||||
* @export
|
||||
* @interface PersonApiUnMergePersonRequest
|
||||
*/
|
||||
export interface PersonApiUnMergePersonRequest {
|
||||
/**
|
||||
*
|
||||
* @type {UnMergePersonDto}
|
||||
* @memberof PersonApiUnMergePerson
|
||||
*/
|
||||
readonly unMergePersonDto: UnMergePersonDto
|
||||
}
|
||||
|
||||
/**
|
||||
* Request parameters for updatePeople operation in PersonApi.
|
||||
* @export
|
||||
|
@ -11504,6 +11600,17 @@ export class PersonApi extends BaseAPI {
|
|||
return PersonApiFp(this.configuration).mergePerson(requestParameters.id, requestParameters.mergePersonDto, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {PersonApiUnMergePersonRequest} requestParameters Request parameters.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof PersonApi
|
||||
*/
|
||||
public unMergePerson(requestParameters: PersonApiUnMergePersonRequest, options?: AxiosRequestConfig) {
|
||||
return PersonApiFp(this.configuration).unMergePerson(requestParameters.unMergePersonDto, options).then((request) => request(this.axios, this.basePath));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {PersonApiUpdatePeopleRequest} requestParameters Request parameters.
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
import { createEventDispatcher } from 'svelte';
|
||||
import ArrowLeft from 'svelte-material-icons/ArrowLeft.svelte';
|
||||
import CloudDownloadOutline from 'svelte-material-icons/CloudDownloadOutline.svelte';
|
||||
import AlertOutline from 'svelte-material-icons/AlertOutline.svelte';
|
||||
import ContentCopy from 'svelte-material-icons/ContentCopy.svelte';
|
||||
import DeleteOutline from 'svelte-material-icons/DeleteOutline.svelte';
|
||||
import DotsVertical from 'svelte-material-icons/DotsVertical.svelte';
|
||||
|
@ -47,6 +46,7 @@
|
|||
asProfileImage: void;
|
||||
runJob: AssetJobName;
|
||||
playSlideShow: void;
|
||||
unMergePerson: void;
|
||||
}>();
|
||||
|
||||
let contextMenuPosition = { x: 0, y: 0 };
|
||||
|
@ -75,14 +75,6 @@
|
|||
<CircleIconButton isOpacity={true} logo={ArrowLeft} on:click={() => dispatch('goBack')} />
|
||||
</div>
|
||||
<div class="flex w-[calc(100%-3rem)] justify-end gap-2 overflow-hidden text-white">
|
||||
{#if asset.isOffline}
|
||||
<CircleIconButton
|
||||
isOpacity={true}
|
||||
logo={AlertOutline}
|
||||
on:click={() => dispatch('showDetail')}
|
||||
title="Asset Offline"
|
||||
/>
|
||||
{/if}
|
||||
{#if showMotionPlayButton}
|
||||
{#if isMotionPhotoPlaying}
|
||||
<CircleIconButton
|
||||
|
@ -143,9 +135,7 @@
|
|||
{/if}
|
||||
|
||||
{#if isOwner}
|
||||
{#if !asset.isReadOnly && !asset.isExternal}
|
||||
<CircleIconButton isOpacity={true} logo={DeleteOutline} on:click={() => dispatch('delete')} title="Delete" />
|
||||
{/if}
|
||||
<CircleIconButton isOpacity={true} logo={DeleteOutline} on:click={() => dispatch('delete')} title="Delete" />
|
||||
<div use:clickOutside on:outclick={() => (isShowAssetOptions = false)}>
|
||||
<CircleIconButton isOpacity={true} logo={DotsVertical} on:click={showOptionsMenu} title="More" />
|
||||
{#if isShowAssetOptions}
|
||||
|
@ -162,6 +152,7 @@
|
|||
text={asset.isArchived ? 'Unarchive' : 'Archive'}
|
||||
/>
|
||||
<MenuOption on:click={() => onMenuClick('asProfileImage')} text="As profile picture" />
|
||||
<MenuOption on:click={() => dispatch('unMergePerson')} text="Unmerge person" />
|
||||
<MenuOption
|
||||
on:click={() => onJobClick(AssetJobName.RefreshMetadata)}
|
||||
text={api.getAssetJobName(AssetJobName.RefreshMetadata)}
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { AlbumResponseDto, api, AssetJobName, AssetResponseDto, AssetTypeEnum, SharedLinkResponseDto } from '@api';
|
||||
import {
|
||||
AlbumResponseDto,
|
||||
api,
|
||||
AssetJobName,
|
||||
AssetResponseDto,
|
||||
AssetTypeEnum,
|
||||
PersonResponseDto,
|
||||
SharedLinkResponseDto,
|
||||
} from '@api';
|
||||
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
|
||||
import ChevronLeft from 'svelte-material-icons/ChevronLeft.svelte';
|
||||
import ChevronRight from 'svelte-material-icons/ChevronRight.svelte';
|
||||
|
@ -28,6 +36,8 @@
|
|||
import Close from 'svelte-material-icons/Close.svelte';
|
||||
import ProgressBar, { ProgressBarStatus } from '../shared-components/progress-bar/progress-bar.svelte';
|
||||
import { shouldIgnoreShortcut } from '$lib/utils/shortcut';
|
||||
import FullScreenModal from '../shared-components/full-screen-modal.svelte';
|
||||
import ImageThumbnail from '../assets/thumbnail/image-thumbnail.svelte';
|
||||
|
||||
export let assetStore: AssetStore | null = null;
|
||||
export let asset: AssetResponseDto;
|
||||
|
@ -50,9 +60,12 @@
|
|||
let addToSharedAlbum = true;
|
||||
let shouldPlayMotionPhoto = false;
|
||||
let isShowProfileImageCrop = false;
|
||||
let shouldShowDownloadButton = sharedLink ? sharedLink.allowDownload : !asset.isOffline;
|
||||
let showUnMergeModal = false;
|
||||
let shouldShowDownloadButton = sharedLink ? sharedLink.allowDownload : true;
|
||||
let canCopyImagesToClipboard: boolean;
|
||||
|
||||
$: people = asset.people || [];
|
||||
|
||||
const onKeyboardPress = (keyInfo: KeyboardEvent) => handleKeyboardPress(keyInfo);
|
||||
|
||||
onMount(async () => {
|
||||
|
@ -89,6 +102,27 @@
|
|||
}
|
||||
};
|
||||
|
||||
const handleUnMergePerson = async (person: PersonResponseDto) => {
|
||||
try {
|
||||
const { data } = await api.personApi.unMergePerson({
|
||||
unMergePersonDto: { assetId: asset.id, personId: person.id },
|
||||
});
|
||||
if (data.success) {
|
||||
notificationController.show({
|
||||
type: NotificationType.Info,
|
||||
message: `Asset un-merged from ${person.name ? person.name : person.id}`,
|
||||
});
|
||||
}
|
||||
people = people.filter((item) => item.id !== person.id);
|
||||
|
||||
if (people.length < 1) {
|
||||
showUnMergeModal = false;
|
||||
}
|
||||
} catch (error) {
|
||||
handleError(error, `Unable to un-merge asset for person ${person.name ? person.name : person.id}`);
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyboardPress = (event: KeyboardEvent) => {
|
||||
if (shouldIgnoreShortcut(event)) {
|
||||
return;
|
||||
|
@ -382,9 +416,43 @@
|
|||
on:asProfileImage={() => (isShowProfileImageCrop = true)}
|
||||
on:runJob={({ detail: job }) => handleRunJob(job)}
|
||||
on:playSlideShow={handlePlaySlideshow}
|
||||
on:unMergePerson={() => (showUnMergeModal = true)}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{#if showUnMergeModal}
|
||||
<FullScreenModal on:clickOutside={() => (showUnMergeModal = false)}>
|
||||
<div
|
||||
class="w-[500px] max-w-[95vw] rounded-3xl border bg-immich-bg p-4 py-8 shadow-sm dark:border-immich-dark-gray dark:bg-immich-dark-gray dark:text-immich-dark-fg"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col place-content-center place-items-center gap-4 px-4 text-immich-primary dark:text-immich-dark-primary"
|
||||
>
|
||||
<section class="px-4 py-4 text-sm">
|
||||
<h2>PEOPLE</h2>
|
||||
|
||||
<div class="mt-4 flex flex-wrap gap-2">
|
||||
{#each people as person (person.id)}
|
||||
<button class="w-[90px]" on:click={() => handleUnMergePerson(person)}>
|
||||
<ImageThumbnail
|
||||
curve
|
||||
shadow
|
||||
url={api.getPeopleThumbnailUrl(person.id)}
|
||||
altText={person.name}
|
||||
title={person.name}
|
||||
widthStyle="90px"
|
||||
heightStyle="90px"
|
||||
thumbhash={null}
|
||||
/>
|
||||
<p class="mt-1 truncate font-medium" title={person.name}>{person.name}</p>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</FullScreenModal>
|
||||
{/if}
|
||||
|
||||
{#if !isSlideshowMode && showNavigation}
|
||||
<div class="column-span-1 z-[999] col-start-1 row-span-1 row-start-2 mb-[60px] justify-self-start">
|
||||
|
|
|
@ -25,10 +25,6 @@
|
|||
$: isOwner = $page?.data?.user?.id === asset.ownerId;
|
||||
|
||||
$: {
|
||||
if (textarea) {
|
||||
textarea.value = asset?.exifInfo?.description || '';
|
||||
}
|
||||
|
||||
// Get latest description from server
|
||||
if (asset.id && !api.isSharedLink) {
|
||||
api.assetApi.getAssetById({ id: asset.id }).then((res) => {
|
||||
|
@ -101,20 +97,6 @@
|
|||
<p class="text-lg text-immich-fg dark:text-immich-dark-fg">Info</p>
|
||||
</div>
|
||||
|
||||
{#if asset.isOffline}
|
||||
<section class="px-4 py-4">
|
||||
<div role="alert">
|
||||
<div class="rounded-t bg-red-500 px-4 py-2 font-bold text-white">Asset offline</div>
|
||||
<div class="rounded-b border border-t-0 border-red-400 bg-red-100 px-4 py-3 text-red-700">
|
||||
<p>
|
||||
This asset is offline. Immich can not access its file location. Please ensure the asset is available and
|
||||
then rescan the library.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{/if}
|
||||
|
||||
<section class="mx-4 mt-10" style:display={!isOwner && textarea?.value == '' ? 'none' : 'block'}>
|
||||
<textarea
|
||||
bind:this={textarea}
|
||||
|
@ -170,16 +152,8 @@
|
|||
{/if}
|
||||
|
||||
<div class="px-4 py-4">
|
||||
{#if !asset.exifInfo && !asset.isExternal}
|
||||
{#if !asset.exifInfo}
|
||||
<p class="text-sm">NO EXIF INFO AVAILABLE</p>
|
||||
{:else if !asset.exifInfo && asset.isExternal}
|
||||
<div class="flex gap-4 py-4">
|
||||
<div>
|
||||
<p class="break-all">
|
||||
Metadata not loaded for {asset.originalPath}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<p class="text-sm">DETAILS</p>
|
||||
{/if}
|
||||
|
|
Loading…
Add table
Reference in a new issue