mirror of https://github.com/immich-app/immich.git
feat(server,web): hide faces (#3262)
* feat: hide faces * fix: types * pr feedback * fix: svelte checks * feat: new server endpoint * refactor: rename person count dto * fix(server): linter * fix: remove duplicate button * docs: add comments * pr feedback * fix: get unhidden faces * fix: do not use PersonCountResponseDto * fix: transition * pr feedback * pr feedback * fix: remove unused check * add server tests * rename persons to people * feat: add exit button * pr feedback * add server tests * pr feedback * pr feedback * fix: show & hide faces * simplify * fix: close button * pr feeback * pr feeback --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com>pull/3330/head
parent
02b70e693c
commit
f28fc8fa5c
@ -0,0 +1,17 @@
|
||||
# openapi.model.PeopleResponseDto
|
||||
|
||||
## Load the model package
|
||||
```dart
|
||||
import 'package:openapi/api.dart';
|
||||
```
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
**total** | **num** | |
|
||||
**visible** | **num** | |
|
||||
**people** | [**List<PersonResponseDto>**](PersonResponseDto.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)
|
||||
|
||||
|
||||
@ -0,0 +1,114 @@
|
||||
//
|
||||
// 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 PeopleResponseDto {
|
||||
/// Returns a new [PeopleResponseDto] instance.
|
||||
PeopleResponseDto({
|
||||
required this.total,
|
||||
required this.visible,
|
||||
this.people = const [],
|
||||
});
|
||||
|
||||
num total;
|
||||
|
||||
num visible;
|
||||
|
||||
List<PersonResponseDto> people;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) => identical(this, other) || other is PeopleResponseDto &&
|
||||
other.total == total &&
|
||||
other.visible == visible &&
|
||||
other.people == people;
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
// ignore: unnecessary_parenthesis
|
||||
(total.hashCode) +
|
||||
(visible.hashCode) +
|
||||
(people.hashCode);
|
||||
|
||||
@override
|
||||
String toString() => 'PeopleResponseDto[total=$total, visible=$visible, people=$people]';
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final json = <String, dynamic>{};
|
||||
json[r'total'] = this.total;
|
||||
json[r'visible'] = this.visible;
|
||||
json[r'people'] = this.people;
|
||||
return json;
|
||||
}
|
||||
|
||||
/// Returns a new [PeopleResponseDto] instance and imports its values from
|
||||
/// [value] if it's a [Map], null otherwise.
|
||||
// ignore: prefer_constructors_over_static_methods
|
||||
static PeopleResponseDto? fromJson(dynamic value) {
|
||||
if (value is Map) {
|
||||
final json = value.cast<String, dynamic>();
|
||||
|
||||
return PeopleResponseDto(
|
||||
total: num.parse('${json[r'total']}'),
|
||||
visible: num.parse('${json[r'visible']}'),
|
||||
people: PersonResponseDto.listFromJson(json[r'people']),
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static List<PeopleResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||
final result = <PeopleResponseDto>[];
|
||||
if (json is List && json.isNotEmpty) {
|
||||
for (final row in json) {
|
||||
final value = PeopleResponseDto.fromJson(row);
|
||||
if (value != null) {
|
||||
result.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.toList(growable: growable);
|
||||
}
|
||||
|
||||
static Map<String, PeopleResponseDto> mapFromJson(dynamic json) {
|
||||
final map = <String, PeopleResponseDto>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||
for (final entry in json.entries) {
|
||||
final value = PeopleResponseDto.fromJson(entry.value);
|
||||
if (value != null) {
|
||||
map[entry.key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// maps a json object with a list of PeopleResponseDto-objects as value to a dart map
|
||||
static Map<String, List<PeopleResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||
final map = <String, List<PeopleResponseDto>>{};
|
||||
if (json is Map && json.isNotEmpty) {
|
||||
// ignore: parameter_assignments
|
||||
json = json.cast<String, dynamic>();
|
||||
for (final entry in json.entries) {
|
||||
map[entry.key] = PeopleResponseDto.listFromJson(entry.value, growable: growable,);
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/// The list of required keys that must be present in a JSON.
|
||||
static const requiredKeys = <String>{
|
||||
'total',
|
||||
'visible',
|
||||
'people',
|
||||
};
|
||||
}
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
//
|
||||
// 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 PeopleResponseDto
|
||||
void main() {
|
||||
// final instance = PeopleResponseDto();
|
||||
|
||||
group('test PeopleResponseDto', () {
|
||||
// num total
|
||||
test('to test the property `total`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// num visible
|
||||
test('to test the property `visible`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
// List<PersonResponseDto> people (default value: const [])
|
||||
test('to test the property `people`', () async {
|
||||
// TODO
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class Infra1689281196844 implements MigrationInterface {
|
||||
name = 'Infra1689281196844'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "person" ADD "isHidden" boolean NOT NULL DEFAULT false`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "person" DROP COLUMN "isHidden"`);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
<script>
|
||||
import { fly } from 'svelte/transition';
|
||||
import CircleIconButton from '../elements/buttons/circle-icon-button.svelte';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
import Close from 'svelte-material-icons/Close.svelte';
|
||||
import IconButton from '../elements/buttons/icon-button.svelte';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
</script>
|
||||
|
||||
<section
|
||||
transition:fly={{ y: 500, duration: 100, easing: quintOut }}
|
||||
class="absolute top-0 left-0 w-full h-full bg-immich-bg dark:bg-immich-dark-bg z-[9999]"
|
||||
>
|
||||
<div
|
||||
class="absolute border-b dark:border-immich-dark-gray flex justify-between place-items-center dark:text-immich-dark-fg w-full h-16"
|
||||
>
|
||||
<div class="flex items-center justify-between p-8 w-full">
|
||||
<div class="flex items-center">
|
||||
<CircleIconButton logo={Close} on:click={() => dispatch('closeClick')} />
|
||||
<p class="ml-4">Show & hide faces</p>
|
||||
</div>
|
||||
<IconButton on:click={() => dispatch('doneClick')}>Done</IconButton>
|
||||
</div>
|
||||
<div class="absolute top-16 h-[calc(100%-theme(spacing.16))] w-full immich-scrollbar p-4 pb-8">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
Loading…
Reference in New Issue