fix: people page

This commit is contained in:
martabal 2023-10-04 17:21:53 +02:00
parent 4dcc1131fa
commit 977a17f9c0
No known key found for this signature in database
GPG key ID: C00196E3148A52BD
18 changed files with 120 additions and 112 deletions

View file

@ -522,10 +522,29 @@ export interface AssetFaceBoxDto {
export interface AssetFaceUpdateDto {
/**
*
* @type {Array<AssetUpdateDto>}
* @type {Array<AssetFaceUpdateItem>}
* @memberof AssetFaceUpdateDto
*/
'data': Array<AssetUpdateDto>;
'data': Array<AssetFaceUpdateItem>;
}
/**
*
* @export
* @interface AssetFaceUpdateItem
*/
export interface AssetFaceUpdateItem {
/**
*
* @type {string}
* @memberof AssetFaceUpdateItem
*/
'assetId': string;
/**
*
* @type {string}
* @memberof AssetFaceUpdateItem
*/
'personId': string;
}
/**
*
@ -835,25 +854,6 @@ export const AssetTypeEnum = {
export type AssetTypeEnum = typeof AssetTypeEnum[keyof typeof AssetTypeEnum];
/**
*
* @export
* @interface AssetUpdateDto
*/
export interface AssetUpdateDto {
/**
*
* @type {string}
* @memberof AssetUpdateDto
*/
'assetId': string;
/**
*
* @type {string}
* @memberof AssetUpdateDto
*/
'personId': string;
}
/**
*
* @export

View file

@ -22,6 +22,7 @@ doc/AssetBulkUploadCheckResponseDto.md
doc/AssetBulkUploadCheckResult.md
doc/AssetFaceBoxDto.md
doc/AssetFaceUpdateDto.md
doc/AssetFaceUpdateItem.md
doc/AssetFileUploadResponseDto.md
doc/AssetIdsDto.md
doc/AssetIdsResponseDto.md
@ -30,7 +31,6 @@ doc/AssetJobsDto.md
doc/AssetResponseDto.md
doc/AssetStatsResponseDto.md
doc/AssetTypeEnum.md
doc/AssetUpdateDto.md
doc/AudioCodec.md
doc/AuditApi.md
doc/AuditDeletesResponseDto.md
@ -196,6 +196,7 @@ lib/model/asset_bulk_upload_check_response_dto.dart
lib/model/asset_bulk_upload_check_result.dart
lib/model/asset_face_box_dto.dart
lib/model/asset_face_update_dto.dart
lib/model/asset_face_update_item.dart
lib/model/asset_file_upload_response_dto.dart
lib/model/asset_ids_dto.dart
lib/model/asset_ids_response_dto.dart
@ -204,7 +205,6 @@ lib/model/asset_jobs_dto.dart
lib/model/asset_response_dto.dart
lib/model/asset_stats_response_dto.dart
lib/model/asset_type_enum.dart
lib/model/asset_update_dto.dart
lib/model/audio_codec.dart
lib/model/audit_deletes_response_dto.dart
lib/model/auth_device_response_dto.dart
@ -335,6 +335,7 @@ test/asset_bulk_upload_check_response_dto_test.dart
test/asset_bulk_upload_check_result_test.dart
test/asset_face_box_dto_test.dart
test/asset_face_update_dto_test.dart
test/asset_face_update_item_test.dart
test/asset_file_upload_response_dto_test.dart
test/asset_ids_dto_test.dart
test/asset_ids_response_dto_test.dart
@ -343,7 +344,6 @@ test/asset_jobs_dto_test.dart
test/asset_response_dto_test.dart
test/asset_stats_response_dto_test.dart
test/asset_type_enum_test.dart
test/asset_update_dto_test.dart
test/audio_codec_test.dart
test/audit_api_test.dart
test/audit_deletes_response_dto_test.dart

View file

@ -211,6 +211,7 @@ Class | Method | HTTP request | Description
- [AssetBulkUploadCheckResult](doc//AssetBulkUploadCheckResult.md)
- [AssetFaceBoxDto](doc//AssetFaceBoxDto.md)
- [AssetFaceUpdateDto](doc//AssetFaceUpdateDto.md)
- [AssetFaceUpdateItem](doc//AssetFaceUpdateItem.md)
- [AssetFileUploadResponseDto](doc//AssetFileUploadResponseDto.md)
- [AssetIdsDto](doc//AssetIdsDto.md)
- [AssetIdsResponseDto](doc//AssetIdsResponseDto.md)
@ -219,7 +220,6 @@ Class | Method | HTTP request | Description
- [AssetResponseDto](doc//AssetResponseDto.md)
- [AssetStatsResponseDto](doc//AssetStatsResponseDto.md)
- [AssetTypeEnum](doc//AssetTypeEnum.md)
- [AssetUpdateDto](doc//AssetUpdateDto.md)
- [AudioCodec](doc//AudioCodec.md)
- [AuditDeletesResponseDto](doc//AuditDeletesResponseDto.md)
- [AuthDeviceResponseDto](doc//AuthDeviceResponseDto.md)

View file

@ -8,7 +8,7 @@ import 'package:openapi/api.dart';
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**data** | [**List<AssetUpdateDto>**](AssetUpdateDto.md) | | [default to const []]
**data** | [**List<AssetFaceUpdateItem>**](AssetFaceUpdateItem.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)

View file

@ -1,4 +1,4 @@
# openapi.model.AssetUpdateDto
# openapi.model.AssetFaceUpdateItem
## Load the model package
```dart

View file

@ -61,6 +61,7 @@ part 'model/asset_bulk_upload_check_response_dto.dart';
part 'model/asset_bulk_upload_check_result.dart';
part 'model/asset_face_box_dto.dart';
part 'model/asset_face_update_dto.dart';
part 'model/asset_face_update_item.dart';
part 'model/asset_file_upload_response_dto.dart';
part 'model/asset_ids_dto.dart';
part 'model/asset_ids_response_dto.dart';
@ -69,7 +70,6 @@ part 'model/asset_jobs_dto.dart';
part 'model/asset_response_dto.dart';
part 'model/asset_stats_response_dto.dart';
part 'model/asset_type_enum.dart';
part 'model/asset_update_dto.dart';
part 'model/audio_codec.dart';
part 'model/audit_deletes_response_dto.dart';
part 'model/auth_device_response_dto.dart';

View file

@ -213,6 +213,8 @@ class ApiClient {
return AssetFaceBoxDto.fromJson(value);
case 'AssetFaceUpdateDto':
return AssetFaceUpdateDto.fromJson(value);
case 'AssetFaceUpdateItem':
return AssetFaceUpdateItem.fromJson(value);
case 'AssetFileUploadResponseDto':
return AssetFileUploadResponseDto.fromJson(value);
case 'AssetIdsDto':
@ -229,8 +231,6 @@ class ApiClient {
return AssetStatsResponseDto.fromJson(value);
case 'AssetTypeEnum':
return AssetTypeEnumTypeTransformer().decode(value);
case 'AssetUpdateDto':
return AssetUpdateDto.fromJson(value);
case 'AudioCodec':
return AudioCodecTypeTransformer().decode(value);
case 'AuditDeletesResponseDto':

View file

@ -16,7 +16,7 @@ class AssetFaceUpdateDto {
this.data = const [],
});
List<AssetUpdateDto> data;
List<AssetFaceUpdateItem> data;
@override
bool operator ==(Object other) => identical(this, other) || other is AssetFaceUpdateDto &&
@ -44,7 +44,7 @@ class AssetFaceUpdateDto {
final json = value.cast<String, dynamic>();
return AssetFaceUpdateDto(
data: AssetUpdateDto.listFromJson(json[r'data']),
data: AssetFaceUpdateItem.listFromJson(json[r'data']),
);
}
return null;

View file

@ -10,9 +10,9 @@
part of openapi.api;
class AssetUpdateDto {
/// Returns a new [AssetUpdateDto] instance.
AssetUpdateDto({
class AssetFaceUpdateItem {
/// Returns a new [AssetFaceUpdateItem] instance.
AssetFaceUpdateItem({
required this.assetId,
required this.personId,
});
@ -22,7 +22,7 @@ class AssetUpdateDto {
String personId;
@override
bool operator ==(Object other) => identical(this, other) || other is AssetUpdateDto &&
bool operator ==(Object other) => identical(this, other) || other is AssetFaceUpdateItem &&
other.assetId == assetId &&
other.personId == personId;
@ -33,7 +33,7 @@ class AssetUpdateDto {
(personId.hashCode);
@override
String toString() => 'AssetUpdateDto[assetId=$assetId, personId=$personId]';
String toString() => 'AssetFaceUpdateItem[assetId=$assetId, personId=$personId]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -42,14 +42,14 @@ class AssetUpdateDto {
return json;
}
/// Returns a new [AssetUpdateDto] instance and imports its values from
/// Returns a new [AssetFaceUpdateItem] instance and imports its values from
/// [value] if it's a [Map], null otherwise.
// ignore: prefer_constructors_over_static_methods
static AssetUpdateDto? fromJson(dynamic value) {
static AssetFaceUpdateItem? fromJson(dynamic value) {
if (value is Map) {
final json = value.cast<String, dynamic>();
return AssetUpdateDto(
return AssetFaceUpdateItem(
assetId: mapValueOfType<String>(json, r'assetId')!,
personId: mapValueOfType<String>(json, r'personId')!,
);
@ -57,11 +57,11 @@ class AssetUpdateDto {
return null;
}
static List<AssetUpdateDto> listFromJson(dynamic json, {bool growable = false,}) {
final result = <AssetUpdateDto>[];
static List<AssetFaceUpdateItem> listFromJson(dynamic json, {bool growable = false,}) {
final result = <AssetFaceUpdateItem>[];
if (json is List && json.isNotEmpty) {
for (final row in json) {
final value = AssetUpdateDto.fromJson(row);
final value = AssetFaceUpdateItem.fromJson(row);
if (value != null) {
result.add(value);
}
@ -70,12 +70,12 @@ class AssetUpdateDto {
return result.toList(growable: growable);
}
static Map<String, AssetUpdateDto> mapFromJson(dynamic json) {
final map = <String, AssetUpdateDto>{};
static Map<String, AssetFaceUpdateItem> mapFromJson(dynamic json) {
final map = <String, AssetFaceUpdateItem>{};
if (json is Map && json.isNotEmpty) {
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
for (final entry in json.entries) {
final value = AssetUpdateDto.fromJson(entry.value);
final value = AssetFaceUpdateItem.fromJson(entry.value);
if (value != null) {
map[entry.key] = value;
}
@ -84,14 +84,14 @@ class AssetUpdateDto {
return map;
}
// maps a json object with a list of AssetUpdateDto-objects as value to a dart map
static Map<String, List<AssetUpdateDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<AssetUpdateDto>>{};
// maps a json object with a list of AssetFaceUpdateItem-objects as value to a dart map
static Map<String, List<AssetFaceUpdateItem>> mapListFromJson(dynamic json, {bool growable = false,}) {
final map = <String, List<AssetFaceUpdateItem>>{};
if (json is Map && json.isNotEmpty) {
// ignore: parameter_assignments
json = json.cast<String, dynamic>();
for (final entry in json.entries) {
map[entry.key] = AssetUpdateDto.listFromJson(entry.value, growable: growable,);
map[entry.key] = AssetFaceUpdateItem.listFromJson(entry.value, growable: growable,);
}
}
return map;

View file

@ -16,7 +16,7 @@ void main() {
// final instance = AssetFaceUpdateDto();
group('test AssetFaceUpdateDto', () {
// List<AssetUpdateDto> data (default value: const [])
// List<AssetFaceUpdateItem> data (default value: const [])
test('to test the property `data`', () async {
// TODO
});

View file

@ -11,11 +11,11 @@
import 'package:openapi/api.dart';
import 'package:test/test.dart';
// tests for AssetUpdateDto
// tests for AssetFaceUpdateItem
void main() {
// final instance = AssetUpdateDto();
// final instance = AssetFaceUpdateItem();
group('test AssetUpdateDto', () {
group('test AssetFaceUpdateItem', () {
// String assetId
test('to test the property `assetId`', () async {
// TODO

View file

@ -5658,7 +5658,7 @@
"properties": {
"data": {
"items": {
"$ref": "#/components/schemas/AssetUpdateDto"
"$ref": "#/components/schemas/AssetFaceUpdateItem"
},
"type": "array"
}
@ -5668,6 +5668,21 @@
],
"type": "object"
},
"AssetFaceUpdateItem": {
"properties": {
"assetId": {
"type": "string"
},
"personId": {
"type": "string"
}
},
"required": [
"personId",
"assetId"
],
"type": "object"
},
"AssetFileUploadResponseDto": {
"properties": {
"duplicate": {
@ -5894,21 +5909,6 @@
],
"type": "string"
},
"AssetUpdateDto": {
"properties": {
"assetId": {
"type": "string"
},
"personId": {
"type": "string"
}
},
"required": [
"personId",
"assetId"
],
"type": "object"
},
"AudioCodec": {
"enum": [
"mp3",

View file

@ -46,10 +46,12 @@ export class PeopleUpdateDto {
export class AssetFaceUpdateDto {
@IsArray()
data!: AssetUpdateDto[];
@ValidateNested({ each: true })
@Type(() => AssetFaceUpdateItem)
data!: AssetFaceUpdateItem[];
}
export class AssetUpdateDto {
export class AssetFaceUpdateItem {
@IsString()
@IsNotEmpty()
personId!: string;

View file

@ -255,7 +255,6 @@ export class PersonService {
await this.access.requirePermission(authUser, Permission.PERSON_WRITE, personId);
const result: PersonResponseDto[] = [];
for (const data of dto.data) {
try {
const [face] = await this.repository.getFacesByIds([{ personId: data.personId, assetId: data.assetId }]);
@ -267,7 +266,10 @@ export class PersonService {
result.push(await this.findOrFail(personId).then(mapPerson));
} catch (error: Error | any) {
this.logger.error(`Unable to un-merge asset ${data.assetId} from ${data.personId}`, error?.stack);
this.logger.error(
`Unable to un-merge asset ${data.assetId} from ${data.personId} to ${personId}`,
error?.stack,
);
}
}
return result;

View file

@ -522,10 +522,29 @@ export interface AssetFaceBoxDto {
export interface AssetFaceUpdateDto {
/**
*
* @type {Array<AssetUpdateDto>}
* @type {Array<AssetFaceUpdateItem>}
* @memberof AssetFaceUpdateDto
*/
'data': Array<AssetUpdateDto>;
'data': Array<AssetFaceUpdateItem>;
}
/**
*
* @export
* @interface AssetFaceUpdateItem
*/
export interface AssetFaceUpdateItem {
/**
*
* @type {string}
* @memberof AssetFaceUpdateItem
*/
'assetId': string;
/**
*
* @type {string}
* @memberof AssetFaceUpdateItem
*/
'personId': string;
}
/**
*
@ -835,25 +854,6 @@ export const AssetTypeEnum = {
export type AssetTypeEnum = typeof AssetTypeEnum[keyof typeof AssetTypeEnum];
/**
*
* @export
* @interface AssetUpdateDto
*/
export interface AssetUpdateDto {
/**
*
* @type {string}
* @memberof AssetUpdateDto
*/
'assetId': string;
/**
*
* @type {string}
* @memberof AssetUpdateDto
*/
'personId': string;
}
/**
*
* @export

View file

@ -26,11 +26,11 @@
let previousId: string;
$: {
console.log('test ', previousId, ' ', asset.id);
if (!previousId) {
previousId = asset.id;
}
if (asset.id !== previousId) {
customFeaturePhoto = new Array<string | null>(asset.people?.length || 0);
showEditFaces = false;
previousId = asset.id;
}

View file

@ -1,23 +1,23 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
import FaceThumbnail from '../../faces-page/face-thumbnail.svelte';
import FaceThumbnail from './face-thumbnail.svelte';
import { quintOut } from 'svelte/easing';
import { fly } from 'svelte/transition';
import { api, AssetUpdateDto, type PersonResponseDto } from '@api';
import ControlAppBar from '../../shared-components/control-app-bar.svelte';
import Button from '../../elements/buttons/button.svelte';
import { api, AssetFaceUpdateItem, type PersonResponseDto } from '@api';
import ControlAppBar from '../shared-components/control-app-bar.svelte';
import Button from '../elements/buttons/button.svelte';
import Merge from 'svelte-material-icons/Merge.svelte';
import Plus from 'svelte-material-icons/Plus.svelte';
import { getAssetControlContext } from '../asset-select-control-bar.svelte';
import LoadingSpinner from '../../shared-components/loading-spinner.svelte';
import LoadingSpinner from '../shared-components/loading-spinner.svelte';
import { handleError } from '$lib/utils/handle-error';
export let people: PersonResponseDto[] = [];
export let assetIds: string[];
export let personId: string;
const { getAssets, clearSelect } = getAssetControlContext();
const assetIds = Array.from(getAssets()).map((a) => a.id);
const data: AssetUpdateDto[] = [];
const data: AssetFaceUpdateItem[] = [];
for (const assetId of assetIds) {
data.push({ assetId, personId });
}
@ -56,11 +56,10 @@
await api.personApi.createPerson({
assetFaceUpdateDto: { data },
});
clearSelect();
} catch (error) {
handleError(error, 'Unable to reassign assets to a new person');
}
dispatch('close');
dispatch('confirm');
};
const handleReassign = async () => {
@ -73,11 +72,10 @@
assetFaceUpdateDto: { data },
});
}
clearSelect();
} catch (error) {
handleError(error, `Unable to reassign assets to ${selectedPerson?.name || 'an existing person'}`);
}
dispatch('close');
dispatch('confirm');
};
</script>

View file

@ -32,7 +32,7 @@
import DotsVertical from 'svelte-material-icons/DotsVertical.svelte';
import Plus from 'svelte-material-icons/Plus.svelte';
import type { PageData } from './$types';
import PeopleList from '$lib/components/photos-page/actions/people-list.svelte';
import PeopleList from '$lib/components/faces-page/people-list.svelte';
import { clickOutside } from '$lib/utils/click-outside';
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
@ -159,6 +159,12 @@
viewMode = ViewMode.VIEW_ASSETS;
};
const handleUnmerge = () => {
$assetStore.removeAssets(Array.from($selectedAssets).map((a) => a.id));
assetInteractionStore.clearMultiselect();
viewMode = ViewMode.VIEW_ASSETS;
};
const handleMergeSameFace = async (response: [PersonResponseDto, PersonResponseDto]) => {
const [personToMerge, personToBeMergedIn] = response;
viewMode = ViewMode.VIEW_ASSETS;
@ -303,10 +309,10 @@
{#if viewMode === ViewMode.UNASSIGN_ASSETS}
<PeopleList
{people}
assetIds={Array.from($selectedAssets).map((a) => a.id)}
personId={data.person.id}
on:close={() => (viewMode = ViewMode.VIEW_ASSETS)}
on:reject={() => changeName()}
on:confirm={(event) => handleMergeSameFace(event.detail)}
on:confirm={handleUnmerge}
/>
{/if}