feat (server, web): Implement Archive (#2225)

* feat (server, web): add archive

* chore: generate api

* feat (web): add empty placeholder for archive page

* chore: remove title on favorites page

Duplicates sidebar selection. Two pages (Archive and Favorites)
are consistent now

* refactor (web): create EmptyPlaceholder component for empty pages

* fixed menu close button not close:

* fix (web): remove not necessary store call

* test (web): simplify asset tests code

* test (web): simplify asset tests code

* chore (server): remove isArchived while uploading

* chore (server): remove isArchived from typesense schema

* chore: generate api

* fix (web): delete asset from archive page

* chore: change archive asset count endpoint

old endpoint: /asset/archived-count-by-user-id
new endpoint: /asset/stat/archive

* chore: generate api

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
Sergey Kondrikov 2023-04-12 18:37:52 +03:00 committed by GitHub
parent eb9481b668
commit d314805caf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 861 additions and 97 deletions

View file

@ -25,6 +25,7 @@ class AssetResponseDto {
required this.fileModifiedAt,
required this.updatedAt,
required this.isFavorite,
required this.isArchived,
required this.mimeType,
required this.duration,
required this.webpPath,
@ -59,6 +60,8 @@ class AssetResponseDto {
bool isFavorite;
bool isArchived;
String? mimeType;
String duration;
@ -101,6 +104,7 @@ class AssetResponseDto {
other.fileModifiedAt == fileModifiedAt &&
other.updatedAt == updatedAt &&
other.isFavorite == isFavorite &&
other.isArchived == isArchived &&
other.mimeType == mimeType &&
other.duration == duration &&
other.webpPath == webpPath &&
@ -125,6 +129,7 @@ class AssetResponseDto {
(fileModifiedAt.hashCode) +
(updatedAt.hashCode) +
(isFavorite.hashCode) +
(isArchived.hashCode) +
(mimeType == null ? 0 : mimeType!.hashCode) +
(duration.hashCode) +
(webpPath == null ? 0 : webpPath!.hashCode) +
@ -135,7 +140,7 @@ class AssetResponseDto {
(tags.hashCode);
@override
String toString() => 'AssetResponseDto[type=$type, id=$id, deviceAssetId=$deviceAssetId, ownerId=$ownerId, deviceId=$deviceId, originalPath=$originalPath, originalFileName=$originalFileName, resizePath=$resizePath, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, updatedAt=$updatedAt, isFavorite=$isFavorite, mimeType=$mimeType, duration=$duration, webpPath=$webpPath, encodedVideoPath=$encodedVideoPath, exifInfo=$exifInfo, smartInfo=$smartInfo, livePhotoVideoId=$livePhotoVideoId, tags=$tags]';
String toString() => 'AssetResponseDto[type=$type, id=$id, deviceAssetId=$deviceAssetId, ownerId=$ownerId, deviceId=$deviceId, originalPath=$originalPath, originalFileName=$originalFileName, resizePath=$resizePath, fileCreatedAt=$fileCreatedAt, fileModifiedAt=$fileModifiedAt, updatedAt=$updatedAt, isFavorite=$isFavorite, isArchived=$isArchived, mimeType=$mimeType, duration=$duration, webpPath=$webpPath, encodedVideoPath=$encodedVideoPath, exifInfo=$exifInfo, smartInfo=$smartInfo, livePhotoVideoId=$livePhotoVideoId, tags=$tags]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -155,6 +160,7 @@ class AssetResponseDto {
json[r'fileModifiedAt'] = this.fileModifiedAt;
json[r'updatedAt'] = this.updatedAt;
json[r'isFavorite'] = this.isFavorite;
json[r'isArchived'] = this.isArchived;
if (this.mimeType != null) {
json[r'mimeType'] = this.mimeType;
} else {
@ -221,6 +227,7 @@ class AssetResponseDto {
fileModifiedAt: mapValueOfType<String>(json, r'fileModifiedAt')!,
updatedAt: mapValueOfType<String>(json, r'updatedAt')!,
isFavorite: mapValueOfType<bool>(json, r'isFavorite')!,
isArchived: mapValueOfType<bool>(json, r'isArchived')!,
mimeType: mapValueOfType<String>(json, r'mimeType'),
duration: mapValueOfType<String>(json, r'duration')!,
webpPath: mapValueOfType<String>(json, r'webpPath'),
@ -290,6 +297,7 @@ class AssetResponseDto {
'fileModifiedAt',
'updatedAt',
'isFavorite',
'isArchived',
'mimeType',
'duration',
'webpPath',

View file

@ -15,6 +15,7 @@ class UpdateAssetDto {
UpdateAssetDto({
this.tagIds = const [],
this.isFavorite,
this.isArchived,
});
List<String> tagIds;
@ -27,19 +28,29 @@ class UpdateAssetDto {
///
bool? isFavorite;
///
/// 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? isArchived;
@override
bool operator ==(Object other) => identical(this, other) || other is UpdateAssetDto &&
other.tagIds == tagIds &&
other.isFavorite == isFavorite;
other.isFavorite == isFavorite &&
other.isArchived == isArchived;
@override
int get hashCode =>
// ignore: unnecessary_parenthesis
(tagIds.hashCode) +
(isFavorite == null ? 0 : isFavorite!.hashCode);
(isFavorite == null ? 0 : isFavorite!.hashCode) +
(isArchived == null ? 0 : isArchived!.hashCode);
@override
String toString() => 'UpdateAssetDto[tagIds=$tagIds, isFavorite=$isFavorite]';
String toString() => 'UpdateAssetDto[tagIds=$tagIds, isFavorite=$isFavorite, isArchived=$isArchived]';
Map<String, dynamic> toJson() {
final json = <String, dynamic>{};
@ -49,6 +60,11 @@ class UpdateAssetDto {
} else {
// json[r'isFavorite'] = null;
}
if (this.isArchived != null) {
json[r'isArchived'] = this.isArchived;
} else {
// json[r'isArchived'] = null;
}
return json;
}
@ -75,6 +91,7 @@ class UpdateAssetDto {
? (json[r'tagIds'] as List).cast<String>()
: const [],
isFavorite: mapValueOfType<bool>(json, r'isFavorite'),
isArchived: mapValueOfType<bool>(json, r'isArchived'),
);
}
return null;