mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	feat(web): add asset and album count info (#623)
* Get asset and album count * Generate APIs * Added asset count for each type * Added api on the web * Added info button for asset and album count to trigger getting info on hover * Remove websocket event from photo page
This commit is contained in:
		@@ -6,10 +6,12 @@ doc/AddAssetsDto.md
 | 
				
			|||||||
doc/AddUsersDto.md
 | 
					doc/AddUsersDto.md
 | 
				
			||||||
doc/AdminSignupResponseDto.md
 | 
					doc/AdminSignupResponseDto.md
 | 
				
			||||||
doc/AlbumApi.md
 | 
					doc/AlbumApi.md
 | 
				
			||||||
 | 
					doc/AlbumCountResponseDto.md
 | 
				
			||||||
doc/AlbumResponseDto.md
 | 
					doc/AlbumResponseDto.md
 | 
				
			||||||
doc/AssetApi.md
 | 
					doc/AssetApi.md
 | 
				
			||||||
doc/AssetCountByTimeBucket.md
 | 
					doc/AssetCountByTimeBucket.md
 | 
				
			||||||
doc/AssetCountByTimeBucketResponseDto.md
 | 
					doc/AssetCountByTimeBucketResponseDto.md
 | 
				
			||||||
 | 
					doc/AssetCountByUserIdResponseDto.md
 | 
				
			||||||
doc/AssetFileUploadResponseDto.md
 | 
					doc/AssetFileUploadResponseDto.md
 | 
				
			||||||
doc/AssetResponseDto.md
 | 
					doc/AssetResponseDto.md
 | 
				
			||||||
doc/AssetTypeEnum.md
 | 
					doc/AssetTypeEnum.md
 | 
				
			||||||
@@ -70,9 +72,11 @@ lib/auth/oauth.dart
 | 
				
			|||||||
lib/model/add_assets_dto.dart
 | 
					lib/model/add_assets_dto.dart
 | 
				
			||||||
lib/model/add_users_dto.dart
 | 
					lib/model/add_users_dto.dart
 | 
				
			||||||
lib/model/admin_signup_response_dto.dart
 | 
					lib/model/admin_signup_response_dto.dart
 | 
				
			||||||
 | 
					lib/model/album_count_response_dto.dart
 | 
				
			||||||
lib/model/album_response_dto.dart
 | 
					lib/model/album_response_dto.dart
 | 
				
			||||||
lib/model/asset_count_by_time_bucket.dart
 | 
					lib/model/asset_count_by_time_bucket.dart
 | 
				
			||||||
lib/model/asset_count_by_time_bucket_response_dto.dart
 | 
					lib/model/asset_count_by_time_bucket_response_dto.dart
 | 
				
			||||||
 | 
					lib/model/asset_count_by_user_id_response_dto.dart
 | 
				
			||||||
lib/model/asset_file_upload_response_dto.dart
 | 
					lib/model/asset_file_upload_response_dto.dart
 | 
				
			||||||
lib/model/asset_response_dto.dart
 | 
					lib/model/asset_response_dto.dart
 | 
				
			||||||
lib/model/asset_type_enum.dart
 | 
					lib/model/asset_type_enum.dart
 | 
				
			||||||
@@ -111,3 +115,4 @@ lib/model/user_count_response_dto.dart
 | 
				
			|||||||
lib/model/user_response_dto.dart
 | 
					lib/model/user_response_dto.dart
 | 
				
			||||||
lib/model/validate_access_token_response_dto.dart
 | 
					lib/model/validate_access_token_response_dto.dart
 | 
				
			||||||
pubspec.yaml
 | 
					pubspec.yaml
 | 
				
			||||||
 | 
					test/asset_count_by_user_id_response_dto_test.dart
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,6 +69,7 @@ Class | Method | HTTP request | Description
 | 
				
			|||||||
*AlbumApi* | [**addUsersToAlbum**](doc//AlbumApi.md#adduserstoalbum) | **PUT** /album/{albumId}/users | 
 | 
					*AlbumApi* | [**addUsersToAlbum**](doc//AlbumApi.md#adduserstoalbum) | **PUT** /album/{albumId}/users | 
 | 
				
			||||||
*AlbumApi* | [**createAlbum**](doc//AlbumApi.md#createalbum) | **POST** /album | 
 | 
					*AlbumApi* | [**createAlbum**](doc//AlbumApi.md#createalbum) | **POST** /album | 
 | 
				
			||||||
*AlbumApi* | [**deleteAlbum**](doc//AlbumApi.md#deletealbum) | **DELETE** /album/{albumId} | 
 | 
					*AlbumApi* | [**deleteAlbum**](doc//AlbumApi.md#deletealbum) | **DELETE** /album/{albumId} | 
 | 
				
			||||||
 | 
					*AlbumApi* | [**getAlbumCountByUserId**](doc//AlbumApi.md#getalbumcountbyuserid) | **GET** /album/count-by-user-id | 
 | 
				
			||||||
*AlbumApi* | [**getAlbumInfo**](doc//AlbumApi.md#getalbuminfo) | **GET** /album/{albumId} | 
 | 
					*AlbumApi* | [**getAlbumInfo**](doc//AlbumApi.md#getalbuminfo) | **GET** /album/{albumId} | 
 | 
				
			||||||
*AlbumApi* | [**getAllAlbums**](doc//AlbumApi.md#getallalbums) | **GET** /album | 
 | 
					*AlbumApi* | [**getAllAlbums**](doc//AlbumApi.md#getallalbums) | **GET** /album | 
 | 
				
			||||||
*AlbumApi* | [**removeAssetFromAlbum**](doc//AlbumApi.md#removeassetfromalbum) | **DELETE** /album/{albumId}/assets | 
 | 
					*AlbumApi* | [**removeAssetFromAlbum**](doc//AlbumApi.md#removeassetfromalbum) | **DELETE** /album/{albumId}/assets | 
 | 
				
			||||||
@@ -81,6 +82,7 @@ Class | Method | HTTP request | Description
 | 
				
			|||||||
*AssetApi* | [**getAssetById**](doc//AssetApi.md#getassetbyid) | **GET** /asset/assetById/{assetId} | 
 | 
					*AssetApi* | [**getAssetById**](doc//AssetApi.md#getassetbyid) | **GET** /asset/assetById/{assetId} | 
 | 
				
			||||||
*AssetApi* | [**getAssetByTimeBucket**](doc//AssetApi.md#getassetbytimebucket) | **POST** /asset/time-bucket | 
 | 
					*AssetApi* | [**getAssetByTimeBucket**](doc//AssetApi.md#getassetbytimebucket) | **POST** /asset/time-bucket | 
 | 
				
			||||||
*AssetApi* | [**getAssetCountByTimeBucket**](doc//AssetApi.md#getassetcountbytimebucket) | **POST** /asset/count-by-time-bucket | 
 | 
					*AssetApi* | [**getAssetCountByTimeBucket**](doc//AssetApi.md#getassetcountbytimebucket) | **POST** /asset/count-by-time-bucket | 
 | 
				
			||||||
 | 
					*AssetApi* | [**getAssetCountByUserId**](doc//AssetApi.md#getassetcountbyuserid) | **GET** /asset/count-by-user-id | 
 | 
				
			||||||
*AssetApi* | [**getAssetSearchTerms**](doc//AssetApi.md#getassetsearchterms) | **GET** /asset/search-terms | 
 | 
					*AssetApi* | [**getAssetSearchTerms**](doc//AssetApi.md#getassetsearchterms) | **GET** /asset/search-terms | 
 | 
				
			||||||
*AssetApi* | [**getAssetThumbnail**](doc//AssetApi.md#getassetthumbnail) | **GET** /asset/thumbnail/{assetId} | 
 | 
					*AssetApi* | [**getAssetThumbnail**](doc//AssetApi.md#getassetthumbnail) | **GET** /asset/thumbnail/{assetId} | 
 | 
				
			||||||
*AssetApi* | [**getCuratedLocations**](doc//AssetApi.md#getcuratedlocations) | **GET** /asset/curated-locations | 
 | 
					*AssetApi* | [**getCuratedLocations**](doc//AssetApi.md#getcuratedlocations) | **GET** /asset/curated-locations | 
 | 
				
			||||||
@@ -113,9 +115,11 @@ Class | Method | HTTP request | Description
 | 
				
			|||||||
 - [AddAssetsDto](doc//AddAssetsDto.md)
 | 
					 - [AddAssetsDto](doc//AddAssetsDto.md)
 | 
				
			||||||
 - [AddUsersDto](doc//AddUsersDto.md)
 | 
					 - [AddUsersDto](doc//AddUsersDto.md)
 | 
				
			||||||
 - [AdminSignupResponseDto](doc//AdminSignupResponseDto.md)
 | 
					 - [AdminSignupResponseDto](doc//AdminSignupResponseDto.md)
 | 
				
			||||||
 | 
					 - [AlbumCountResponseDto](doc//AlbumCountResponseDto.md)
 | 
				
			||||||
 - [AlbumResponseDto](doc//AlbumResponseDto.md)
 | 
					 - [AlbumResponseDto](doc//AlbumResponseDto.md)
 | 
				
			||||||
 - [AssetCountByTimeBucket](doc//AssetCountByTimeBucket.md)
 | 
					 - [AssetCountByTimeBucket](doc//AssetCountByTimeBucket.md)
 | 
				
			||||||
 - [AssetCountByTimeBucketResponseDto](doc//AssetCountByTimeBucketResponseDto.md)
 | 
					 - [AssetCountByTimeBucketResponseDto](doc//AssetCountByTimeBucketResponseDto.md)
 | 
				
			||||||
 | 
					 - [AssetCountByUserIdResponseDto](doc//AssetCountByUserIdResponseDto.md)
 | 
				
			||||||
 - [AssetFileUploadResponseDto](doc//AssetFileUploadResponseDto.md)
 | 
					 - [AssetFileUploadResponseDto](doc//AssetFileUploadResponseDto.md)
 | 
				
			||||||
 - [AssetResponseDto](doc//AssetResponseDto.md)
 | 
					 - [AssetResponseDto](doc//AssetResponseDto.md)
 | 
				
			||||||
 - [AssetTypeEnum](doc//AssetTypeEnum.md)
 | 
					 - [AssetTypeEnum](doc//AssetTypeEnum.md)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,7 @@ Method | HTTP request | Description
 | 
				
			|||||||
[**addUsersToAlbum**](AlbumApi.md#adduserstoalbum) | **PUT** /album/{albumId}/users | 
 | 
					[**addUsersToAlbum**](AlbumApi.md#adduserstoalbum) | **PUT** /album/{albumId}/users | 
 | 
				
			||||||
[**createAlbum**](AlbumApi.md#createalbum) | **POST** /album | 
 | 
					[**createAlbum**](AlbumApi.md#createalbum) | **POST** /album | 
 | 
				
			||||||
[**deleteAlbum**](AlbumApi.md#deletealbum) | **DELETE** /album/{albumId} | 
 | 
					[**deleteAlbum**](AlbumApi.md#deletealbum) | **DELETE** /album/{albumId} | 
 | 
				
			||||||
 | 
					[**getAlbumCountByUserId**](AlbumApi.md#getalbumcountbyuserid) | **GET** /album/count-by-user-id | 
 | 
				
			||||||
[**getAlbumInfo**](AlbumApi.md#getalbuminfo) | **GET** /album/{albumId} | 
 | 
					[**getAlbumInfo**](AlbumApi.md#getalbuminfo) | **GET** /album/{albumId} | 
 | 
				
			||||||
[**getAllAlbums**](AlbumApi.md#getallalbums) | **GET** /album | 
 | 
					[**getAllAlbums**](AlbumApi.md#getallalbums) | **GET** /album | 
 | 
				
			||||||
[**removeAssetFromAlbum**](AlbumApi.md#removeassetfromalbum) | **DELETE** /album/{albumId}/assets | 
 | 
					[**removeAssetFromAlbum**](AlbumApi.md#removeassetfromalbum) | **DELETE** /album/{albumId}/assets | 
 | 
				
			||||||
@@ -211,6 +212,49 @@ void (empty response body)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# **getAlbumCountByUserId**
 | 
				
			||||||
 | 
					> AlbumCountResponseDto getAlbumCountByUserId()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Example
 | 
				
			||||||
 | 
					```dart
 | 
				
			||||||
 | 
					import 'package:openapi/api.dart';
 | 
				
			||||||
 | 
					// 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 = AlbumApi();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					try {
 | 
				
			||||||
 | 
					    final result = api_instance.getAlbumCountByUserId();
 | 
				
			||||||
 | 
					    print(result);
 | 
				
			||||||
 | 
					} catch (e) {
 | 
				
			||||||
 | 
					    print('Exception when calling AlbumApi->getAlbumCountByUserId: $e\n');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Parameters
 | 
				
			||||||
 | 
					This endpoint does not need any parameter.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Return type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[**AlbumCountResponseDto**](AlbumCountResponseDto.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Authorization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[bearer](../README.md#bearer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### HTTP request headers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 - **Content-Type**: Not defined
 | 
				
			||||||
 | 
					 - **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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# **getAlbumInfo**
 | 
					# **getAlbumInfo**
 | 
				
			||||||
> AlbumResponseDto getAlbumInfo(albumId)
 | 
					> AlbumResponseDto getAlbumInfo(albumId)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										17
									
								
								mobile/openapi/doc/AlbumCountResponseDto.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								mobile/openapi/doc/AlbumCountResponseDto.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					# openapi.model.AlbumCountResponseDto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Load the model package
 | 
				
			||||||
 | 
					```dart
 | 
				
			||||||
 | 
					import 'package:openapi/api.dart';
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Properties
 | 
				
			||||||
 | 
					Name | Type | Description | Notes
 | 
				
			||||||
 | 
					------------ | ------------- | ------------- | -------------
 | 
				
			||||||
 | 
					**owned** | **int** |  | 
 | 
				
			||||||
 | 
					**shared** | **int** |  | 
 | 
				
			||||||
 | 
					**sharing** | **int** |  | 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -16,6 +16,7 @@ Method | HTTP request | Description
 | 
				
			|||||||
[**getAssetById**](AssetApi.md#getassetbyid) | **GET** /asset/assetById/{assetId} | 
 | 
					[**getAssetById**](AssetApi.md#getassetbyid) | **GET** /asset/assetById/{assetId} | 
 | 
				
			||||||
[**getAssetByTimeBucket**](AssetApi.md#getassetbytimebucket) | **POST** /asset/time-bucket | 
 | 
					[**getAssetByTimeBucket**](AssetApi.md#getassetbytimebucket) | **POST** /asset/time-bucket | 
 | 
				
			||||||
[**getAssetCountByTimeBucket**](AssetApi.md#getassetcountbytimebucket) | **POST** /asset/count-by-time-bucket | 
 | 
					[**getAssetCountByTimeBucket**](AssetApi.md#getassetcountbytimebucket) | **POST** /asset/count-by-time-bucket | 
 | 
				
			||||||
 | 
					[**getAssetCountByUserId**](AssetApi.md#getassetcountbyuserid) | **GET** /asset/count-by-user-id | 
 | 
				
			||||||
[**getAssetSearchTerms**](AssetApi.md#getassetsearchterms) | **GET** /asset/search-terms | 
 | 
					[**getAssetSearchTerms**](AssetApi.md#getassetsearchterms) | **GET** /asset/search-terms | 
 | 
				
			||||||
[**getAssetThumbnail**](AssetApi.md#getassetthumbnail) | **GET** /asset/thumbnail/{assetId} | 
 | 
					[**getAssetThumbnail**](AssetApi.md#getassetthumbnail) | **GET** /asset/thumbnail/{assetId} | 
 | 
				
			||||||
[**getCuratedLocations**](AssetApi.md#getcuratedlocations) | **GET** /asset/curated-locations | 
 | 
					[**getCuratedLocations**](AssetApi.md#getcuratedlocations) | **GET** /asset/curated-locations | 
 | 
				
			||||||
@@ -363,6 +364,49 @@ 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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# **getAssetCountByUserId**
 | 
				
			||||||
 | 
					> AssetCountByUserIdResponseDto getAssetCountByUserId()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Example
 | 
				
			||||||
 | 
					```dart
 | 
				
			||||||
 | 
					import 'package:openapi/api.dart';
 | 
				
			||||||
 | 
					// 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 = AssetApi();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					try {
 | 
				
			||||||
 | 
					    final result = api_instance.getAssetCountByUserId();
 | 
				
			||||||
 | 
					    print(result);
 | 
				
			||||||
 | 
					} catch (e) {
 | 
				
			||||||
 | 
					    print('Exception when calling AssetApi->getAssetCountByUserId: $e\n');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Parameters
 | 
				
			||||||
 | 
					This endpoint does not need any parameter.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Return type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[**AssetCountByUserIdResponseDto**](AssetCountByUserIdResponseDto.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Authorization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[bearer](../README.md#bearer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### HTTP request headers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 - **Content-Type**: Not defined
 | 
				
			||||||
 | 
					 - **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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# **getAssetSearchTerms**
 | 
					# **getAssetSearchTerms**
 | 
				
			||||||
> List<String> getAssetSearchTerms()
 | 
					> List<String> getAssetSearchTerms()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								mobile/openapi/doc/AssetCountByUserIdResponseDto.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								mobile/openapi/doc/AssetCountByUserIdResponseDto.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					# openapi.model.AssetCountByUserIdResponseDto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Load the model package
 | 
				
			||||||
 | 
					```dart
 | 
				
			||||||
 | 
					import 'package:openapi/api.dart';
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Properties
 | 
				
			||||||
 | 
					Name | Type | Description | Notes
 | 
				
			||||||
 | 
					------------ | ------------- | ------------- | -------------
 | 
				
			||||||
 | 
					**photos** | **int** |  | 
 | 
				
			||||||
 | 
					**videos** | **int** |  | 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -37,9 +37,11 @@ part 'api/user_api.dart';
 | 
				
			|||||||
part 'model/add_assets_dto.dart';
 | 
					part 'model/add_assets_dto.dart';
 | 
				
			||||||
part 'model/add_users_dto.dart';
 | 
					part 'model/add_users_dto.dart';
 | 
				
			||||||
part 'model/admin_signup_response_dto.dart';
 | 
					part 'model/admin_signup_response_dto.dart';
 | 
				
			||||||
 | 
					part 'model/album_count_response_dto.dart';
 | 
				
			||||||
part 'model/album_response_dto.dart';
 | 
					part 'model/album_response_dto.dart';
 | 
				
			||||||
part 'model/asset_count_by_time_bucket.dart';
 | 
					part 'model/asset_count_by_time_bucket.dart';
 | 
				
			||||||
part 'model/asset_count_by_time_bucket_response_dto.dart';
 | 
					part 'model/asset_count_by_time_bucket_response_dto.dart';
 | 
				
			||||||
 | 
					part 'model/asset_count_by_user_id_response_dto.dart';
 | 
				
			||||||
part 'model/asset_file_upload_response_dto.dart';
 | 
					part 'model/asset_file_upload_response_dto.dart';
 | 
				
			||||||
part 'model/asset_response_dto.dart';
 | 
					part 'model/asset_response_dto.dart';
 | 
				
			||||||
part 'model/asset_type_enum.dart';
 | 
					part 'model/asset_type_enum.dart';
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -207,6 +207,47 @@ class AlbumApi {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Performs an HTTP 'GET /album/count-by-user-id' operation and returns the [Response].
 | 
				
			||||||
 | 
					  Future<Response> getAlbumCountByUserIdWithHttpInfo() async {
 | 
				
			||||||
 | 
					    // ignore: prefer_const_declarations
 | 
				
			||||||
 | 
					    final path = r'/album/count-by-user-id';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ignore: prefer_final_locals
 | 
				
			||||||
 | 
					    Object? postBody;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final queryParams = <QueryParam>[];
 | 
				
			||||||
 | 
					    final headerParams = <String, String>{};
 | 
				
			||||||
 | 
					    final formParams = <String, String>{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const contentTypes = <String>[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return apiClient.invokeAPI(
 | 
				
			||||||
 | 
					      path,
 | 
				
			||||||
 | 
					      'GET',
 | 
				
			||||||
 | 
					      queryParams,
 | 
				
			||||||
 | 
					      postBody,
 | 
				
			||||||
 | 
					      headerParams,
 | 
				
			||||||
 | 
					      formParams,
 | 
				
			||||||
 | 
					      contentTypes.isEmpty ? null : contentTypes.first,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<AlbumCountResponseDto?> getAlbumCountByUserId() async {
 | 
				
			||||||
 | 
					    final response = await getAlbumCountByUserIdWithHttpInfo();
 | 
				
			||||||
 | 
					    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), 'AlbumCountResponseDto',) as AlbumCountResponseDto;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Performs an HTTP 'GET /album/{albumId}' operation and returns the [Response].
 | 
					  /// Performs an HTTP 'GET /album/{albumId}' operation and returns the [Response].
 | 
				
			||||||
  /// Parameters:
 | 
					  /// Parameters:
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -395,6 +395,47 @@ class AssetApi {
 | 
				
			|||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Performs an HTTP 'GET /asset/count-by-user-id' operation and returns the [Response].
 | 
				
			||||||
 | 
					  Future<Response> getAssetCountByUserIdWithHttpInfo() async {
 | 
				
			||||||
 | 
					    // ignore: prefer_const_declarations
 | 
				
			||||||
 | 
					    final path = r'/asset/count-by-user-id';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ignore: prefer_final_locals
 | 
				
			||||||
 | 
					    Object? postBody;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final queryParams = <QueryParam>[];
 | 
				
			||||||
 | 
					    final headerParams = <String, String>{};
 | 
				
			||||||
 | 
					    final formParams = <String, String>{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const contentTypes = <String>[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return apiClient.invokeAPI(
 | 
				
			||||||
 | 
					      path,
 | 
				
			||||||
 | 
					      'GET',
 | 
				
			||||||
 | 
					      queryParams,
 | 
				
			||||||
 | 
					      postBody,
 | 
				
			||||||
 | 
					      headerParams,
 | 
				
			||||||
 | 
					      formParams,
 | 
				
			||||||
 | 
					      contentTypes.isEmpty ? null : contentTypes.first,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<AssetCountByUserIdResponseDto?> getAssetCountByUserId() async {
 | 
				
			||||||
 | 
					    final response = await getAssetCountByUserIdWithHttpInfo();
 | 
				
			||||||
 | 
					    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), 'AssetCountByUserIdResponseDto',) as AssetCountByUserIdResponseDto;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Performs an HTTP 'GET /asset/search-terms' operation and returns the [Response].
 | 
					  /// Performs an HTTP 'GET /asset/search-terms' operation and returns the [Response].
 | 
				
			||||||
  Future<Response> getAssetSearchTermsWithHttpInfo() async {
 | 
					  Future<Response> getAssetSearchTermsWithHttpInfo() async {
 | 
				
			||||||
    // ignore: prefer_const_declarations
 | 
					    // ignore: prefer_const_declarations
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -198,12 +198,16 @@ class ApiClient {
 | 
				
			|||||||
          return AddUsersDto.fromJson(value);
 | 
					          return AddUsersDto.fromJson(value);
 | 
				
			||||||
        case 'AdminSignupResponseDto':
 | 
					        case 'AdminSignupResponseDto':
 | 
				
			||||||
          return AdminSignupResponseDto.fromJson(value);
 | 
					          return AdminSignupResponseDto.fromJson(value);
 | 
				
			||||||
 | 
					        case 'AlbumCountResponseDto':
 | 
				
			||||||
 | 
					          return AlbumCountResponseDto.fromJson(value);
 | 
				
			||||||
        case 'AlbumResponseDto':
 | 
					        case 'AlbumResponseDto':
 | 
				
			||||||
          return AlbumResponseDto.fromJson(value);
 | 
					          return AlbumResponseDto.fromJson(value);
 | 
				
			||||||
        case 'AssetCountByTimeBucket':
 | 
					        case 'AssetCountByTimeBucket':
 | 
				
			||||||
          return AssetCountByTimeBucket.fromJson(value);
 | 
					          return AssetCountByTimeBucket.fromJson(value);
 | 
				
			||||||
        case 'AssetCountByTimeBucketResponseDto':
 | 
					        case 'AssetCountByTimeBucketResponseDto':
 | 
				
			||||||
          return AssetCountByTimeBucketResponseDto.fromJson(value);
 | 
					          return AssetCountByTimeBucketResponseDto.fromJson(value);
 | 
				
			||||||
 | 
					        case 'AssetCountByUserIdResponseDto':
 | 
				
			||||||
 | 
					          return AssetCountByUserIdResponseDto.fromJson(value);
 | 
				
			||||||
        case 'AssetFileUploadResponseDto':
 | 
					        case 'AssetFileUploadResponseDto':
 | 
				
			||||||
          return AssetFileUploadResponseDto.fromJson(value);
 | 
					          return AssetFileUploadResponseDto.fromJson(value);
 | 
				
			||||||
        case 'AssetResponseDto':
 | 
					        case 'AssetResponseDto':
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										127
									
								
								mobile/openapi/lib/model/album_count_response_dto.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								mobile/openapi/lib/model/album_count_response_dto.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,127 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// 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 AlbumCountResponseDto {
 | 
				
			||||||
 | 
					  /// Returns a new [AlbumCountResponseDto] instance.
 | 
				
			||||||
 | 
					  AlbumCountResponseDto({
 | 
				
			||||||
 | 
					    required this.owned,
 | 
				
			||||||
 | 
					    required this.shared,
 | 
				
			||||||
 | 
					    required this.sharing,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int owned;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int shared;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int sharing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  bool operator ==(Object other) => identical(this, other) || other is AlbumCountResponseDto &&
 | 
				
			||||||
 | 
					     other.owned == owned &&
 | 
				
			||||||
 | 
					     other.shared == shared &&
 | 
				
			||||||
 | 
					     other.sharing == sharing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  int get hashCode =>
 | 
				
			||||||
 | 
					    // ignore: unnecessary_parenthesis
 | 
				
			||||||
 | 
					    (owned.hashCode) +
 | 
				
			||||||
 | 
					    (shared.hashCode) +
 | 
				
			||||||
 | 
					    (sharing.hashCode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() => 'AlbumCountResponseDto[owned=$owned, shared=$shared, sharing=$sharing]';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Map<String, dynamic> toJson() {
 | 
				
			||||||
 | 
					    final _json = <String, dynamic>{};
 | 
				
			||||||
 | 
					      _json[r'owned'] = owned;
 | 
				
			||||||
 | 
					      _json[r'shared'] = shared;
 | 
				
			||||||
 | 
					      _json[r'sharing'] = sharing;
 | 
				
			||||||
 | 
					    return _json;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Returns a new [AlbumCountResponseDto] instance and imports its values from
 | 
				
			||||||
 | 
					  /// [value] if it's a [Map], null otherwise.
 | 
				
			||||||
 | 
					  // ignore: prefer_constructors_over_static_methods
 | 
				
			||||||
 | 
					  static AlbumCountResponseDto? fromJson(dynamic value) {
 | 
				
			||||||
 | 
					    if (value is Map) {
 | 
				
			||||||
 | 
					      final json = value.cast<String, dynamic>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Ensure that the map contains the required keys.
 | 
				
			||||||
 | 
					      // Note 1: the values aren't checked for validity beyond being non-null.
 | 
				
			||||||
 | 
					      // Note 2: this code is stripped in release mode!
 | 
				
			||||||
 | 
					      assert(() {
 | 
				
			||||||
 | 
					        requiredKeys.forEach((key) {
 | 
				
			||||||
 | 
					          assert(json.containsKey(key), 'Required key "AlbumCountResponseDto[$key]" is missing from JSON.');
 | 
				
			||||||
 | 
					          assert(json[key] != null, 'Required key "AlbumCountResponseDto[$key]" has a null value in JSON.');
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					      }());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return AlbumCountResponseDto(
 | 
				
			||||||
 | 
					        owned: mapValueOfType<int>(json, r'owned')!,
 | 
				
			||||||
 | 
					        shared: mapValueOfType<int>(json, r'shared')!,
 | 
				
			||||||
 | 
					        sharing: mapValueOfType<int>(json, r'sharing')!,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static List<AlbumCountResponseDto>? listFromJson(dynamic json, {bool growable = false,}) {
 | 
				
			||||||
 | 
					    final result = <AlbumCountResponseDto>[];
 | 
				
			||||||
 | 
					    if (json is List && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      for (final row in json) {
 | 
				
			||||||
 | 
					        final value = AlbumCountResponseDto.fromJson(row);
 | 
				
			||||||
 | 
					        if (value != null) {
 | 
				
			||||||
 | 
					          result.add(value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result.toList(growable: growable);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static Map<String, AlbumCountResponseDto> mapFromJson(dynamic json) {
 | 
				
			||||||
 | 
					    final map = <String, AlbumCountResponseDto>{};
 | 
				
			||||||
 | 
					    if (json is Map && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      json = json.cast<String, dynamic>(); // ignore: parameter_assignments
 | 
				
			||||||
 | 
					      for (final entry in json.entries) {
 | 
				
			||||||
 | 
					        final value = AlbumCountResponseDto.fromJson(entry.value);
 | 
				
			||||||
 | 
					        if (value != null) {
 | 
				
			||||||
 | 
					          map[entry.key] = value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // maps a json object with a list of AlbumCountResponseDto-objects as value to a dart map
 | 
				
			||||||
 | 
					  static Map<String, List<AlbumCountResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
 | 
				
			||||||
 | 
					    final map = <String, List<AlbumCountResponseDto>>{};
 | 
				
			||||||
 | 
					    if (json is Map && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      json = json.cast<String, dynamic>(); // ignore: parameter_assignments
 | 
				
			||||||
 | 
					      for (final entry in json.entries) {
 | 
				
			||||||
 | 
					        final value = AlbumCountResponseDto.listFromJson(entry.value, growable: growable,);
 | 
				
			||||||
 | 
					        if (value != null) {
 | 
				
			||||||
 | 
					          map[entry.key] = value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// The list of required keys that must be present in a JSON.
 | 
				
			||||||
 | 
					  static const requiredKeys = <String>{
 | 
				
			||||||
 | 
					    'owned',
 | 
				
			||||||
 | 
					    'shared',
 | 
				
			||||||
 | 
					    'sharing',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -0,0 +1,119 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// 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 AssetCountByUserIdResponseDto {
 | 
				
			||||||
 | 
					  /// Returns a new [AssetCountByUserIdResponseDto] instance.
 | 
				
			||||||
 | 
					  AssetCountByUserIdResponseDto({
 | 
				
			||||||
 | 
					    required this.photos,
 | 
				
			||||||
 | 
					    required this.videos,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int photos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int videos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  bool operator ==(Object other) => identical(this, other) || other is AssetCountByUserIdResponseDto &&
 | 
				
			||||||
 | 
					     other.photos == photos &&
 | 
				
			||||||
 | 
					     other.videos == videos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  int get hashCode =>
 | 
				
			||||||
 | 
					    // ignore: unnecessary_parenthesis
 | 
				
			||||||
 | 
					    (photos.hashCode) +
 | 
				
			||||||
 | 
					    (videos.hashCode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() => 'AssetCountByUserIdResponseDto[photos=$photos, videos=$videos]';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Map<String, dynamic> toJson() {
 | 
				
			||||||
 | 
					    final _json = <String, dynamic>{};
 | 
				
			||||||
 | 
					      _json[r'photos'] = photos;
 | 
				
			||||||
 | 
					      _json[r'videos'] = videos;
 | 
				
			||||||
 | 
					    return _json;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Returns a new [AssetCountByUserIdResponseDto] instance and imports its values from
 | 
				
			||||||
 | 
					  /// [value] if it's a [Map], null otherwise.
 | 
				
			||||||
 | 
					  // ignore: prefer_constructors_over_static_methods
 | 
				
			||||||
 | 
					  static AssetCountByUserIdResponseDto? fromJson(dynamic value) {
 | 
				
			||||||
 | 
					    if (value is Map) {
 | 
				
			||||||
 | 
					      final json = value.cast<String, dynamic>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      // Ensure that the map contains the required keys.
 | 
				
			||||||
 | 
					      // Note 1: the values aren't checked for validity beyond being non-null.
 | 
				
			||||||
 | 
					      // Note 2: this code is stripped in release mode!
 | 
				
			||||||
 | 
					      assert(() {
 | 
				
			||||||
 | 
					        requiredKeys.forEach((key) {
 | 
				
			||||||
 | 
					          assert(json.containsKey(key), 'Required key "AssetCountByUserIdResponseDto[$key]" is missing from JSON.');
 | 
				
			||||||
 | 
					          assert(json[key] != null, 'Required key "AssetCountByUserIdResponseDto[$key]" has a null value in JSON.');
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					      }());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return AssetCountByUserIdResponseDto(
 | 
				
			||||||
 | 
					        photos: mapValueOfType<int>(json, r'photos')!,
 | 
				
			||||||
 | 
					        videos: mapValueOfType<int>(json, r'videos')!,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static List<AssetCountByUserIdResponseDto>? listFromJson(dynamic json, {bool growable = false,}) {
 | 
				
			||||||
 | 
					    final result = <AssetCountByUserIdResponseDto>[];
 | 
				
			||||||
 | 
					    if (json is List && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      for (final row in json) {
 | 
				
			||||||
 | 
					        final value = AssetCountByUserIdResponseDto.fromJson(row);
 | 
				
			||||||
 | 
					        if (value != null) {
 | 
				
			||||||
 | 
					          result.add(value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result.toList(growable: growable);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static Map<String, AssetCountByUserIdResponseDto> mapFromJson(dynamic json) {
 | 
				
			||||||
 | 
					    final map = <String, AssetCountByUserIdResponseDto>{};
 | 
				
			||||||
 | 
					    if (json is Map && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      json = json.cast<String, dynamic>(); // ignore: parameter_assignments
 | 
				
			||||||
 | 
					      for (final entry in json.entries) {
 | 
				
			||||||
 | 
					        final value = AssetCountByUserIdResponseDto.fromJson(entry.value);
 | 
				
			||||||
 | 
					        if (value != null) {
 | 
				
			||||||
 | 
					          map[entry.key] = value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // maps a json object with a list of AssetCountByUserIdResponseDto-objects as value to a dart map
 | 
				
			||||||
 | 
					  static Map<String, List<AssetCountByUserIdResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
 | 
				
			||||||
 | 
					    final map = <String, List<AssetCountByUserIdResponseDto>>{};
 | 
				
			||||||
 | 
					    if (json is Map && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      json = json.cast<String, dynamic>(); // ignore: parameter_assignments
 | 
				
			||||||
 | 
					      for (final entry in json.entries) {
 | 
				
			||||||
 | 
					        final value = AssetCountByUserIdResponseDto.listFromJson(entry.value, growable: growable,);
 | 
				
			||||||
 | 
					        if (value != null) {
 | 
				
			||||||
 | 
					          map[entry.key] = value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// The list of required keys that must be present in a JSON.
 | 
				
			||||||
 | 
					  static const requiredKeys = <String>{
 | 
				
			||||||
 | 
					    'photos',
 | 
				
			||||||
 | 
					    'videos',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										37
									
								
								mobile/openapi/test/album_count_response_dto_test.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								mobile/openapi/test/album_count_response_dto_test.dart
									
									
									
									
									
										Normal file
									
								
							@@ -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 AlbumCountResponseDto
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
					  // final instance = AlbumCountResponseDto();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  group('test AlbumCountResponseDto', () {
 | 
				
			||||||
 | 
					    // int owned
 | 
				
			||||||
 | 
					    test('to test the property `owned`', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // int shared
 | 
				
			||||||
 | 
					    test('to test the property `shared`', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // int sharing
 | 
				
			||||||
 | 
					    test('to test the property `sharing`', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -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 AssetCountByUserIdResponseDto
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
					  // final instance = AssetCountByUserIdResponseDto();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  group('test AssetCountByUserIdResponseDto', () {
 | 
				
			||||||
 | 
					    // int photos
 | 
				
			||||||
 | 
					    test('to test the property `photos`', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // int videos
 | 
				
			||||||
 | 
					    test('to test the property `videos`', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -10,6 +10,7 @@ import { CreateAlbumDto } from './dto/create-album.dto';
 | 
				
			|||||||
import { GetAlbumsDto } from './dto/get-albums.dto';
 | 
					import { GetAlbumsDto } from './dto/get-albums.dto';
 | 
				
			||||||
import { RemoveAssetsDto } from './dto/remove-assets.dto';
 | 
					import { RemoveAssetsDto } from './dto/remove-assets.dto';
 | 
				
			||||||
import { UpdateAlbumDto } from './dto/update-album.dto';
 | 
					import { UpdateAlbumDto } from './dto/update-album.dto';
 | 
				
			||||||
 | 
					import { AlbumCountResponseDto } from './response-dto/album-count-response.dto';
 | 
				
			||||||
import { AlbumResponseDto } from './response-dto/album-response.dto';
 | 
					import { AlbumResponseDto } from './response-dto/album-response.dto';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IAlbumRepository {
 | 
					export interface IAlbumRepository {
 | 
				
			||||||
@@ -23,6 +24,7 @@ export interface IAlbumRepository {
 | 
				
			|||||||
  addAssets(album: AlbumEntity, addAssetsDto: AddAssetsDto): Promise<AlbumEntity>;
 | 
					  addAssets(album: AlbumEntity, addAssetsDto: AddAssetsDto): Promise<AlbumEntity>;
 | 
				
			||||||
  updateAlbum(album: AlbumEntity, updateAlbumDto: UpdateAlbumDto): Promise<AlbumEntity>;
 | 
					  updateAlbum(album: AlbumEntity, updateAlbumDto: UpdateAlbumDto): Promise<AlbumEntity>;
 | 
				
			||||||
  getListByAssetId(userId: string, assetId: string): Promise<AlbumEntity[]>;
 | 
					  getListByAssetId(userId: string, assetId: string): Promise<AlbumEntity[]>;
 | 
				
			||||||
 | 
					  getCountByUserId(userId: string): Promise<AlbumCountResponseDto>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const ALBUM_REPOSITORY = 'ALBUM_REPOSITORY';
 | 
					export const ALBUM_REPOSITORY = 'ALBUM_REPOSITORY';
 | 
				
			||||||
@@ -42,6 +44,18 @@ export class AlbumRepository implements IAlbumRepository {
 | 
				
			|||||||
    private dataSource: DataSource,
 | 
					    private dataSource: DataSource,
 | 
				
			||||||
  ) {}
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async getCountByUserId(userId: string): Promise<AlbumCountResponseDto> {
 | 
				
			||||||
 | 
					    const ownedAlbums = await this.albumRepository.find({ where: { ownerId: userId }, relations: ['sharedUsers'] });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const sharedAlbums = await this.userAlbumRepository.count({
 | 
				
			||||||
 | 
					      where: { sharedUserId: userId },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const sharingAlbums = ownedAlbums.map((album) => album.sharedUsers?.length || 0).reduce((a, b) => a + b, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return new AlbumCountResponseDto(ownedAlbums.length, sharedAlbums, sharingAlbums);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async create(ownerId: string, createAlbumDto: CreateAlbumDto): Promise<AlbumEntity> {
 | 
					  async create(ownerId: string, createAlbumDto: CreateAlbumDto): Promise<AlbumEntity> {
 | 
				
			||||||
    return this.dataSource.transaction(async (transactionalEntityManager) => {
 | 
					    return this.dataSource.transaction(async (transactionalEntityManager) => {
 | 
				
			||||||
      // Create album entity
 | 
					      // Create album entity
 | 
				
			||||||
@@ -154,23 +168,23 @@ export class AlbumRepository implements IAlbumRepository {
 | 
				
			|||||||
    let query = this.albumRepository.createQueryBuilder('album');
 | 
					    let query = this.albumRepository.createQueryBuilder('album');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const albums = await query
 | 
					    const albums = await query
 | 
				
			||||||
        .where('album.ownerId = :ownerId', { ownerId: userId })
 | 
					      .where('album.ownerId = :ownerId', { ownerId: userId })
 | 
				
			||||||
        .andWhere((qb) => {
 | 
					      .andWhere((qb) => {
 | 
				
			||||||
          // shared with userId
 | 
					        // shared with userId
 | 
				
			||||||
          const subQuery = qb
 | 
					        const subQuery = qb
 | 
				
			||||||
              .subQuery()
 | 
					          .subQuery()
 | 
				
			||||||
              .select('assetAlbum.albumId')
 | 
					          .select('assetAlbum.albumId')
 | 
				
			||||||
              .from(AssetAlbumEntity, 'assetAlbum')
 | 
					          .from(AssetAlbumEntity, 'assetAlbum')
 | 
				
			||||||
              .where('assetAlbum.assetId = :assetId', {assetId: assetId})
 | 
					          .where('assetAlbum.assetId = :assetId', { assetId: assetId })
 | 
				
			||||||
              .getQuery();
 | 
					          .getQuery();
 | 
				
			||||||
          return `album.id IN ${subQuery}`;
 | 
					        return `album.id IN ${subQuery}`;
 | 
				
			||||||
        })
 | 
					      })
 | 
				
			||||||
        .leftJoinAndSelect('album.assets', 'assets')
 | 
					      .leftJoinAndSelect('album.assets', 'assets')
 | 
				
			||||||
        .leftJoinAndSelect('assets.assetInfo', 'assetInfo')
 | 
					      .leftJoinAndSelect('assets.assetInfo', 'assetInfo')
 | 
				
			||||||
        .leftJoinAndSelect('album.sharedUsers', 'sharedUser')
 | 
					      .leftJoinAndSelect('album.sharedUsers', 'sharedUser')
 | 
				
			||||||
        .leftJoinAndSelect('sharedUser.userInfo', 'userInfo')
 | 
					      .leftJoinAndSelect('sharedUser.userInfo', 'userInfo')
 | 
				
			||||||
        .orderBy('"assetInfo"."createdAt"::timestamptz', 'ASC')
 | 
					      .orderBy('"assetInfo"."createdAt"::timestamptz', 'ASC')
 | 
				
			||||||
        .getMany();
 | 
					      .getMany();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return albums;
 | 
					    return albums;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -228,9 +242,10 @@ export class AlbumRepository implements IAlbumRepository {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // TODO: No need to return boolean if using a singe delete query
 | 
					    // TODO: No need to return boolean if using a singe delete query
 | 
				
			||||||
    if (deleteAssetCount == removeAssetsDto.assetIds.length) {
 | 
					    if (deleteAssetCount == removeAssetsDto.assetIds.length) {
 | 
				
			||||||
      const retAlbum = await this.get(album.id) as AlbumEntity;
 | 
					      const retAlbum = (await this.get(album.id)) as AlbumEntity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (retAlbum?.assets?.length === 0) { // is empty album
 | 
					      if (retAlbum?.assets?.length === 0) {
 | 
				
			||||||
 | 
					        // is empty album
 | 
				
			||||||
        await this.albumRepository.update(album.id, { albumThumbnailAssetId: null });
 | 
					        await this.albumRepository.update(album.id, { albumThumbnailAssetId: null });
 | 
				
			||||||
        retAlbum.albumThumbnailAssetId = null;
 | 
					        retAlbum.albumThumbnailAssetId = null;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,6 +11,7 @@ import {
 | 
				
			|||||||
  ParseUUIDPipe,
 | 
					  ParseUUIDPipe,
 | 
				
			||||||
  Put,
 | 
					  Put,
 | 
				
			||||||
  Query,
 | 
					  Query,
 | 
				
			||||||
 | 
					  Header,
 | 
				
			||||||
} from '@nestjs/common';
 | 
					} from '@nestjs/common';
 | 
				
			||||||
import { ParseMeUUIDPipe } from '../validation/parse-me-uuid-pipe';
 | 
					import { ParseMeUUIDPipe } from '../validation/parse-me-uuid-pipe';
 | 
				
			||||||
import { AlbumService } from './album.service';
 | 
					import { AlbumService } from './album.service';
 | 
				
			||||||
@@ -24,6 +25,7 @@ import { UpdateAlbumDto } from './dto/update-album.dto';
 | 
				
			|||||||
import { GetAlbumsDto } from './dto/get-albums.dto';
 | 
					import { GetAlbumsDto } from './dto/get-albums.dto';
 | 
				
			||||||
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
 | 
					import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
 | 
				
			||||||
import { AlbumResponseDto } from './response-dto/album-response.dto';
 | 
					import { AlbumResponseDto } from './response-dto/album-response.dto';
 | 
				
			||||||
 | 
					import { AlbumCountResponseDto } from './response-dto/album-count-response.dto';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO might be worth creating a AlbumParamsDto that validates `albumId` instead of using the pipe.
 | 
					// TODO might be worth creating a AlbumParamsDto that validates `albumId` instead of using the pipe.
 | 
				
			||||||
@UseGuards(JwtAuthGuard)
 | 
					@UseGuards(JwtAuthGuard)
 | 
				
			||||||
@@ -33,6 +35,11 @@ import { AlbumResponseDto } from './response-dto/album-response.dto';
 | 
				
			|||||||
export class AlbumController {
 | 
					export class AlbumController {
 | 
				
			||||||
  constructor(private readonly albumService: AlbumService) {}
 | 
					  constructor(private readonly albumService: AlbumService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Get('count-by-user-id')
 | 
				
			||||||
 | 
					  async getAlbumCountByUserId(@GetAuthUser() authUser: AuthUserDto): Promise<AlbumCountResponseDto> {
 | 
				
			||||||
 | 
					    return this.albumService.getAlbumCountByUserId(authUser);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Post()
 | 
					  @Post()
 | 
				
			||||||
  async createAlbum(@GetAuthUser() authUser: AuthUserDto, @Body(ValidationPipe) createAlbumDto: CreateAlbumDto) {
 | 
					  async createAlbum(@GetAuthUser() authUser: AuthUserDto, @Body(ValidationPipe) createAlbumDto: CreateAlbumDto) {
 | 
				
			||||||
    return this.albumService.create(authUser, createAlbumDto);
 | 
					    return this.albumService.create(authUser, createAlbumDto);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,7 +116,8 @@ describe('Album service', () => {
 | 
				
			|||||||
      removeAssets: jest.fn(),
 | 
					      removeAssets: jest.fn(),
 | 
				
			||||||
      removeUser: jest.fn(),
 | 
					      removeUser: jest.fn(),
 | 
				
			||||||
      updateAlbum: jest.fn(),
 | 
					      updateAlbum: jest.fn(),
 | 
				
			||||||
      getListByAssetId: jest.fn()
 | 
					      getListByAssetId: jest.fn(),
 | 
				
			||||||
 | 
					      getCountByUserId: jest.fn(),
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    sut = new AlbumService(albumRepositoryMock);
 | 
					    sut = new AlbumService(albumRepositoryMock);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ import { UpdateAlbumDto } from './dto/update-album.dto';
 | 
				
			|||||||
import { GetAlbumsDto } from './dto/get-albums.dto';
 | 
					import { GetAlbumsDto } from './dto/get-albums.dto';
 | 
				
			||||||
import { AlbumResponseDto, mapAlbum, mapAlbumExcludeAssetInfo } from './response-dto/album-response.dto';
 | 
					import { AlbumResponseDto, mapAlbum, mapAlbumExcludeAssetInfo } from './response-dto/album-response.dto';
 | 
				
			||||||
import { ALBUM_REPOSITORY, IAlbumRepository } from './album-repository';
 | 
					import { ALBUM_REPOSITORY, IAlbumRepository } from './album-repository';
 | 
				
			||||||
 | 
					import { AlbumCountResponseDto } from './response-dto/album-count-response.dto';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Injectable()
 | 
					@Injectable()
 | 
				
			||||||
export class AlbumService {
 | 
					export class AlbumService {
 | 
				
			||||||
@@ -118,4 +119,8 @@ export class AlbumService {
 | 
				
			|||||||
    const updatedAlbum = await this._albumRepository.updateAlbum(album, updateAlbumDto);
 | 
					    const updatedAlbum = await this._albumRepository.updateAlbum(album, updateAlbumDto);
 | 
				
			||||||
    return mapAlbum(updatedAlbum);
 | 
					    return mapAlbum(updatedAlbum);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async getAlbumCountByUserId(authUser: AuthUserDto): Promise<AlbumCountResponseDto> {
 | 
				
			||||||
 | 
					    return this._albumRepository.getCountByUserId(authUser.id);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					import { ApiProperty } from '@nestjs/swagger';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class AlbumCountResponseDto {
 | 
				
			||||||
 | 
					  @ApiProperty({ type: 'integer' })
 | 
				
			||||||
 | 
					  owned!: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @ApiProperty({ type: 'integer' })
 | 
				
			||||||
 | 
					  shared!: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @ApiProperty({ type: 'integer' })
 | 
				
			||||||
 | 
					  sharing!: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(owned: number, shared: number, sharing: number) {
 | 
				
			||||||
 | 
					    this.owned = owned;
 | 
				
			||||||
 | 
					    this.shared = shared;
 | 
				
			||||||
 | 
					    this.sharing = sharing;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -9,6 +9,7 @@ import { CuratedObjectsResponseDto } from './response-dto/curated-objects-respon
 | 
				
			|||||||
import { AssetCountByTimeBucket } from './response-dto/asset-count-by-time-group-response.dto';
 | 
					import { AssetCountByTimeBucket } from './response-dto/asset-count-by-time-group-response.dto';
 | 
				
			||||||
import { TimeGroupEnum } from './dto/get-asset-count-by-time-bucket.dto';
 | 
					import { TimeGroupEnum } from './dto/get-asset-count-by-time-bucket.dto';
 | 
				
			||||||
import { GetAssetByTimeBucketDto } from './dto/get-asset-by-time-bucket.dto';
 | 
					import { GetAssetByTimeBucketDto } from './dto/get-asset-by-time-bucket.dto';
 | 
				
			||||||
 | 
					import { AssetCountByUserIdResponseDto } from './response-dto/asset-count-by-user-id-response.dto';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IAssetRepository {
 | 
					export interface IAssetRepository {
 | 
				
			||||||
  create(
 | 
					  create(
 | 
				
			||||||
@@ -25,6 +26,7 @@ export interface IAssetRepository {
 | 
				
			|||||||
  getDetectedObjectsByUserId(userId: string): Promise<CuratedObjectsResponseDto[]>;
 | 
					  getDetectedObjectsByUserId(userId: string): Promise<CuratedObjectsResponseDto[]>;
 | 
				
			||||||
  getSearchPropertiesByUserId(userId: string): Promise<SearchPropertiesDto[]>;
 | 
					  getSearchPropertiesByUserId(userId: string): Promise<SearchPropertiesDto[]>;
 | 
				
			||||||
  getAssetCountByTimeBucket(userId: string, timeBucket: TimeGroupEnum): Promise<AssetCountByTimeBucket[]>;
 | 
					  getAssetCountByTimeBucket(userId: string, timeBucket: TimeGroupEnum): Promise<AssetCountByTimeBucket[]>;
 | 
				
			||||||
 | 
					  getAssetCountByUserId(userId: string): Promise<AssetCountByUserIdResponseDto>;
 | 
				
			||||||
  getAssetByTimeBucket(userId: string, getAssetByTimeBucketDto: GetAssetByTimeBucketDto): Promise<AssetEntity[]>;
 | 
					  getAssetByTimeBucket(userId: string, getAssetByTimeBucketDto: GetAssetByTimeBucketDto): Promise<AssetEntity[]>;
 | 
				
			||||||
  getAssetByChecksum(userId: string, checksum: Buffer): Promise<AssetEntity>;
 | 
					  getAssetByChecksum(userId: string, checksum: Buffer): Promise<AssetEntity>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -38,6 +40,28 @@ export class AssetRepository implements IAssetRepository {
 | 
				
			|||||||
    private assetRepository: Repository<AssetEntity>,
 | 
					    private assetRepository: Repository<AssetEntity>,
 | 
				
			||||||
  ) {}
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async getAssetCountByUserId(userId: string): Promise<AssetCountByUserIdResponseDto> {
 | 
				
			||||||
 | 
					    // Get asset count by AssetType
 | 
				
			||||||
 | 
					    const res = await this.assetRepository
 | 
				
			||||||
 | 
					      .createQueryBuilder('asset')
 | 
				
			||||||
 | 
					      .select(`COUNT(asset.id)`, 'count')
 | 
				
			||||||
 | 
					      .addSelect(`asset.type`, 'type')
 | 
				
			||||||
 | 
					      .where('"userId" = :userId', { userId: userId })
 | 
				
			||||||
 | 
					      .groupBy('asset.type')
 | 
				
			||||||
 | 
					      .getRawMany();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const assetCountByUserId = new AssetCountByUserIdResponseDto(0, 0);
 | 
				
			||||||
 | 
					    res.map((item) => {
 | 
				
			||||||
 | 
					      if (item.type === 'IMAGE') {
 | 
				
			||||||
 | 
					        assetCountByUserId.photos = item.count;
 | 
				
			||||||
 | 
					      } else if (item.type === 'VIDEO') {
 | 
				
			||||||
 | 
					        assetCountByUserId.videos = item.count;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return assetCountByUserId;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async getAssetByTimeBucket(userId: string, getAssetByTimeBucketDto: GetAssetByTimeBucketDto): Promise<AssetEntity[]> {
 | 
					  async getAssetByTimeBucket(userId: string, getAssetByTimeBucketDto: GetAssetByTimeBucketDto): Promise<AssetEntity[]> {
 | 
				
			||||||
    // Get asset entity from a list of time buckets
 | 
					    // Get asset entity from a list of time buckets
 | 
				
			||||||
    return await this.assetRepository
 | 
					    return await this.assetRepository
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,6 +48,7 @@ import { AssetCountByTimeBucketResponseDto } from './response-dto/asset-count-by
 | 
				
			|||||||
import { GetAssetCountByTimeBucketDto } from './dto/get-asset-count-by-time-bucket.dto';
 | 
					import { GetAssetCountByTimeBucketDto } from './dto/get-asset-count-by-time-bucket.dto';
 | 
				
			||||||
import { GetAssetByTimeBucketDto } from './dto/get-asset-by-time-bucket.dto';
 | 
					import { GetAssetByTimeBucketDto } from './dto/get-asset-by-time-bucket.dto';
 | 
				
			||||||
import { QueryFailedError } from 'typeorm';
 | 
					import { QueryFailedError } from 'typeorm';
 | 
				
			||||||
 | 
					import { AssetCountByUserIdResponseDto } from './response-dto/asset-count-by-user-id-response.dto';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@UseGuards(JwtAuthGuard)
 | 
					@UseGuards(JwtAuthGuard)
 | 
				
			||||||
@ApiBearerAuth()
 | 
					@ApiBearerAuth()
 | 
				
			||||||
@@ -78,7 +79,13 @@ export class AssetController {
 | 
				
			|||||||
    const checksum = await this.assetService.calculateChecksum(file.path);
 | 
					    const checksum = await this.assetService.calculateChecksum(file.path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const savedAsset = await this.assetService.createUserAsset(authUser, assetInfo, file.path, file.mimetype, checksum);
 | 
					      const savedAsset = await this.assetService.createUserAsset(
 | 
				
			||||||
 | 
					        authUser,
 | 
				
			||||||
 | 
					        assetInfo,
 | 
				
			||||||
 | 
					        file.path,
 | 
				
			||||||
 | 
					        file.mimetype,
 | 
				
			||||||
 | 
					        checksum,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (!savedAsset) {
 | 
					      if (!savedAsset) {
 | 
				
			||||||
        await this.backgroundTaskService.deleteFileOnDisk([
 | 
					        await this.backgroundTaskService.deleteFileOnDisk([
 | 
				
			||||||
@@ -104,7 +111,7 @@ export class AssetController {
 | 
				
			|||||||
      ]); // simulate asset to make use of delete queue (or use fs.unlink instead)
 | 
					      ]); // simulate asset to make use of delete queue (or use fs.unlink instead)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (err instanceof QueryFailedError && (err as any).constraint === 'UQ_userid_checksum') {
 | 
					      if (err instanceof QueryFailedError && (err as any).constraint === 'UQ_userid_checksum') {
 | 
				
			||||||
        const existedAsset = await this.assetService.getAssetByChecksum(authUser.id, checksum)
 | 
					        const existedAsset = await this.assetService.getAssetByChecksum(authUser.id, checksum);
 | 
				
			||||||
        return new AssetFileUploadResponseDto(existedAsset.id);
 | 
					        return new AssetFileUploadResponseDto(existedAsset.id);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -172,6 +179,10 @@ export class AssetController {
 | 
				
			|||||||
    return this.assetService.getAssetCountByTimeBucket(authUser, getAssetCountByTimeGroupDto);
 | 
					    return this.assetService.getAssetCountByTimeBucket(authUser, getAssetCountByTimeGroupDto);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Get('/count-by-user-id')
 | 
				
			||||||
 | 
					  async getAssetCountByUserId(@GetAuthUser() authUser: AuthUserDto): Promise<AssetCountByUserIdResponseDto> {
 | 
				
			||||||
 | 
					    return this.assetService.getAssetCountByUserId(authUser);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
   * Get all AssetEntity belong to the user
 | 
					   * Get all AssetEntity belong to the user
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,6 +61,7 @@ describe('AssetService', () => {
 | 
				
			|||||||
      getSearchPropertiesByUserId: jest.fn(),
 | 
					      getSearchPropertiesByUserId: jest.fn(),
 | 
				
			||||||
      getAssetByTimeBucket: jest.fn(),
 | 
					      getAssetByTimeBucket: jest.fn(),
 | 
				
			||||||
      getAssetByChecksum: jest.fn(),
 | 
					      getAssetByChecksum: jest.fn(),
 | 
				
			||||||
 | 
					      getAssetCountByUserId: jest.fn(),
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sui = new AssetService(assetRepositoryMock, a);
 | 
					    sui = new AssetService(assetRepositoryMock, a);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,6 +35,7 @@ import {
 | 
				
			|||||||
} from './response-dto/asset-count-by-time-group-response.dto';
 | 
					} from './response-dto/asset-count-by-time-group-response.dto';
 | 
				
			||||||
import { GetAssetCountByTimeBucketDto } from './dto/get-asset-count-by-time-bucket.dto';
 | 
					import { GetAssetCountByTimeBucketDto } from './dto/get-asset-count-by-time-bucket.dto';
 | 
				
			||||||
import { GetAssetByTimeBucketDto } from './dto/get-asset-by-time-bucket.dto';
 | 
					import { GetAssetByTimeBucketDto } from './dto/get-asset-by-time-bucket.dto';
 | 
				
			||||||
 | 
					import { AssetCountByUserIdResponseDto } from './response-dto/asset-count-by-user-id-response.dto';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const fileInfo = promisify(stat);
 | 
					const fileInfo = promisify(stat);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -479,4 +480,8 @@ export class AssetService {
 | 
				
			|||||||
    fileReadStream.pipe(sha1Hash);
 | 
					    fileReadStream.pipe(sha1Hash);
 | 
				
			||||||
    return deferred;
 | 
					    return deferred;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getAssetCountByUserId(authUser: AuthUserDto): Promise<AssetCountByUserIdResponseDto> {
 | 
				
			||||||
 | 
					    return this._assetRepository.getAssetCountByUserId(authUser.id);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					import { ApiProperty } from '@nestjs/swagger';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class AssetCountByUserIdResponseDto {
 | 
				
			||||||
 | 
					  @ApiProperty({ type: 'integer' })
 | 
				
			||||||
 | 
					  photos!: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @ApiProperty({ type: 'integer' })
 | 
				
			||||||
 | 
					  videos!: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(photos: number, videos: number) {
 | 
				
			||||||
 | 
					    this.photos = photos;
 | 
				
			||||||
 | 
					    this.videos = videos;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -84,6 +84,31 @@ export interface AdminSignupResponseDto {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    'createdAt': string;
 | 
					    'createdAt': string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface AlbumCountResponseDto
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface AlbumCountResponseDto {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {number}
 | 
				
			||||||
 | 
					     * @memberof AlbumCountResponseDto
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'owned': number;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {number}
 | 
				
			||||||
 | 
					     * @memberof AlbumCountResponseDto
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'shared': number;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {number}
 | 
				
			||||||
 | 
					     * @memberof AlbumCountResponseDto
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'sharing': number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 
 | 
					 * 
 | 
				
			||||||
 * @export
 | 
					 * @export
 | 
				
			||||||
@@ -183,6 +208,25 @@ export interface AssetCountByTimeBucketResponseDto {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    'buckets': Array<AssetCountByTimeBucket>;
 | 
					    'buckets': Array<AssetCountByTimeBucket>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface AssetCountByUserIdResponseDto
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface AssetCountByUserIdResponseDto {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {number}
 | 
				
			||||||
 | 
					     * @memberof AssetCountByUserIdResponseDto
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'photos': number;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {number}
 | 
				
			||||||
 | 
					     * @memberof AssetCountByUserIdResponseDto
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'videos': number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 
 | 
					 * 
 | 
				
			||||||
 * @export
 | 
					 * @export
 | 
				
			||||||
@@ -1408,6 +1452,39 @@ export const AlbumApiAxiosParamCreator = function (configuration?: Configuration
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					            setSearchParams(localVarUrlObj, localVarQueryParameter);
 | 
				
			||||||
 | 
					            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
 | 
				
			||||||
 | 
					            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                url: toPathString(localVarUrlObj),
 | 
				
			||||||
 | 
					                options: localVarRequestOptions,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        getAlbumCountByUserId: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
 | 
				
			||||||
 | 
					            const localVarPath = `/album/count-by-user-id`;
 | 
				
			||||||
 | 
					            // 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: 'GET', ...baseOptions, ...options};
 | 
				
			||||||
 | 
					            const localVarHeaderParameter = {} as any;
 | 
				
			||||||
 | 
					            const localVarQueryParameter = {} as any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication bearer required
 | 
				
			||||||
 | 
					            // http bearer authentication required
 | 
				
			||||||
 | 
					            await setBearerAuthToObject(localVarHeaderParameter, configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
            setSearchParams(localVarUrlObj, localVarQueryParameter);
 | 
					            setSearchParams(localVarUrlObj, localVarQueryParameter);
 | 
				
			||||||
            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
 | 
					            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
 | 
				
			||||||
            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
 | 
					            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
 | 
				
			||||||
@@ -1676,6 +1753,15 @@ export const AlbumApiFp = function(configuration?: Configuration) {
 | 
				
			|||||||
            const localVarAxiosArgs = await localVarAxiosParamCreator.deleteAlbum(albumId, options);
 | 
					            const localVarAxiosArgs = await localVarAxiosParamCreator.deleteAlbum(albumId, options);
 | 
				
			||||||
            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
					            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        async getAlbumCountByUserId(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AlbumCountResponseDto>> {
 | 
				
			||||||
 | 
					            const localVarAxiosArgs = await localVarAxiosParamCreator.getAlbumCountByUserId(options);
 | 
				
			||||||
 | 
					            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {string} albumId 
 | 
					         * @param {string} albumId 
 | 
				
			||||||
@@ -1778,6 +1864,14 @@ export const AlbumApiFactory = function (configuration?: Configuration, basePath
 | 
				
			|||||||
        deleteAlbum(albumId: string, options?: any): AxiosPromise<void> {
 | 
					        deleteAlbum(albumId: string, options?: any): AxiosPromise<void> {
 | 
				
			||||||
            return localVarFp.deleteAlbum(albumId, options).then((request) => request(axios, basePath));
 | 
					            return localVarFp.deleteAlbum(albumId, options).then((request) => request(axios, basePath));
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        getAlbumCountByUserId(options?: any): AxiosPromise<AlbumCountResponseDto> {
 | 
				
			||||||
 | 
					            return localVarFp.getAlbumCountByUserId(options).then((request) => request(axios, basePath));
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {string} albumId 
 | 
					         * @param {string} albumId 
 | 
				
			||||||
@@ -1883,6 +1977,16 @@ export class AlbumApi extends BaseAPI {
 | 
				
			|||||||
        return AlbumApiFp(this.configuration).deleteAlbum(albumId, options).then((request) => request(this.axios, this.basePath));
 | 
					        return AlbumApiFp(this.configuration).deleteAlbum(albumId, options).then((request) => request(this.axios, this.basePath));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					     * @throws {RequiredError}
 | 
				
			||||||
 | 
					     * @memberof AlbumApi
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public getAlbumCountByUserId(options?: AxiosRequestConfig) {
 | 
				
			||||||
 | 
					        return AlbumApiFp(this.configuration).getAlbumCountByUserId(options).then((request) => request(this.axios, this.basePath));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 
 | 
					     * 
 | 
				
			||||||
     * @param {string} albumId 
 | 
					     * @param {string} albumId 
 | 
				
			||||||
@@ -2236,6 +2340,39 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
 | 
				
			|||||||
                options: localVarRequestOptions,
 | 
					                options: localVarRequestOptions,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        getAssetCountByUserId: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
 | 
				
			||||||
 | 
					            const localVarPath = `/asset/count-by-user-id`;
 | 
				
			||||||
 | 
					            // 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: 'GET', ...baseOptions, ...options};
 | 
				
			||||||
 | 
					            const localVarHeaderParameter = {} as any;
 | 
				
			||||||
 | 
					            const localVarQueryParameter = {} as any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication bearer required
 | 
				
			||||||
 | 
					            // http bearer authentication required
 | 
				
			||||||
 | 
					            await setBearerAuthToObject(localVarHeaderParameter, configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            setSearchParams(localVarUrlObj, localVarQueryParameter);
 | 
				
			||||||
 | 
					            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
 | 
				
			||||||
 | 
					            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                url: toPathString(localVarUrlObj),
 | 
				
			||||||
 | 
					                options: localVarRequestOptions,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {*} [options] Override http request option.
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
@@ -2640,6 +2777,15 @@ export const AssetApiFp = function(configuration?: Configuration) {
 | 
				
			|||||||
            const localVarAxiosArgs = await localVarAxiosParamCreator.getAssetCountByTimeBucket(getAssetCountByTimeBucketDto, options);
 | 
					            const localVarAxiosArgs = await localVarAxiosParamCreator.getAssetCountByTimeBucket(getAssetCountByTimeBucketDto, options);
 | 
				
			||||||
            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
					            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        async getAssetCountByUserId(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<AssetCountByUserIdResponseDto>> {
 | 
				
			||||||
 | 
					            const localVarAxiosArgs = await localVarAxiosParamCreator.getAssetCountByUserId(options);
 | 
				
			||||||
 | 
					            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {*} [options] Override http request option.
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
@@ -2800,6 +2946,14 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
 | 
				
			|||||||
        getAssetCountByTimeBucket(getAssetCountByTimeBucketDto: GetAssetCountByTimeBucketDto, options?: any): AxiosPromise<AssetCountByTimeBucketResponseDto> {
 | 
					        getAssetCountByTimeBucket(getAssetCountByTimeBucketDto: GetAssetCountByTimeBucketDto, options?: any): AxiosPromise<AssetCountByTimeBucketResponseDto> {
 | 
				
			||||||
            return localVarFp.getAssetCountByTimeBucket(getAssetCountByTimeBucketDto, options).then((request) => request(axios, basePath));
 | 
					            return localVarFp.getAssetCountByTimeBucket(getAssetCountByTimeBucketDto, options).then((request) => request(axios, basePath));
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        getAssetCountByUserId(options?: any): AxiosPromise<AssetCountByUserIdResponseDto> {
 | 
				
			||||||
 | 
					            return localVarFp.getAssetCountByUserId(options).then((request) => request(axios, basePath));
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {*} [options] Override http request option.
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
@@ -2966,6 +3120,16 @@ export class AssetApi extends BaseAPI {
 | 
				
			|||||||
        return AssetApiFp(this.configuration).getAssetCountByTimeBucket(getAssetCountByTimeBucketDto, options).then((request) => request(this.axios, this.basePath));
 | 
					        return AssetApiFp(this.configuration).getAssetCountByTimeBucket(getAssetCountByTimeBucketDto, options).then((request) => request(this.axios, this.basePath));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					     * @throws {RequiredError}
 | 
				
			||||||
 | 
					     * @memberof AssetApi
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public getAssetCountByUserId(options?: AxiosRequestConfig) {
 | 
				
			||||||
 | 
					        return AssetApiFp(this.configuration).getAssetCountByUserId(options).then((request) => request(this.axios, this.basePath));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 
 | 
					     * 
 | 
				
			||||||
     * @param {*} [options] Override http request option.
 | 
					     * @param {*} [options] Override http request option.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,11 +5,19 @@
 | 
				
			|||||||
	import ImageAlbum from 'svelte-material-icons/ImageAlbum.svelte';
 | 
						import ImageAlbum from 'svelte-material-icons/ImageAlbum.svelte';
 | 
				
			||||||
	import ImageOutline from 'svelte-material-icons/ImageOutline.svelte';
 | 
						import ImageOutline from 'svelte-material-icons/ImageOutline.svelte';
 | 
				
			||||||
	import AccountMultipleOutline from 'svelte-material-icons/AccountMultipleOutline.svelte';
 | 
						import AccountMultipleOutline from 'svelte-material-icons/AccountMultipleOutline.svelte';
 | 
				
			||||||
 | 
						import InformationOutline from 'svelte-material-icons/InformationOutline.svelte';
 | 
				
			||||||
	import SideBarButton from './side-bar-button.svelte';
 | 
						import SideBarButton from './side-bar-button.svelte';
 | 
				
			||||||
	import StatusBox from '../status-box.svelte';
 | 
						import StatusBox from '../status-box.svelte';
 | 
				
			||||||
 | 
						import { AlbumCountResponseDto, api, AssetCountByUserIdResponseDto } from '@api';
 | 
				
			||||||
 | 
						import { fade } from 'svelte/transition';
 | 
				
			||||||
 | 
						import LoadingSpinner from '../loading-spinner.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let selectedAction: AppSideBarSelection;
 | 
						let selectedAction: AppSideBarSelection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						let showAssetCount: boolean = false;
 | 
				
			||||||
 | 
						let showSharingCount = false;
 | 
				
			||||||
 | 
						let showAlbumsCount = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	onMount(async () => {
 | 
						onMount(async () => {
 | 
				
			||||||
		if ($page.routeId == 'albums') {
 | 
							if ($page.routeId == 'albums') {
 | 
				
			||||||
			selectedAction = AppSideBarSelection.ALBUMS;
 | 
								selectedAction = AppSideBarSelection.ALBUMS;
 | 
				
			||||||
@@ -19,35 +27,130 @@
 | 
				
			|||||||
			selectedAction = AppSideBarSelection.SHARING;
 | 
								selectedAction = AppSideBarSelection.SHARING;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const getAssetCount = async () => {
 | 
				
			||||||
 | 
							const { data: assetCount } = await api.assetApi.getAssetCountByUserId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								videos: assetCount.videos,
 | 
				
			||||||
 | 
								photos: assetCount.photos
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const getAlbumCount = async () => {
 | 
				
			||||||
 | 
							const { data: albumCount } = await api.albumApi.getAlbumCountByUserId();
 | 
				
			||||||
 | 
							return {
 | 
				
			||||||
 | 
								shared: albumCount.shared,
 | 
				
			||||||
 | 
								sharing: albumCount.sharing,
 | 
				
			||||||
 | 
								owned: albumCount.owned
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<section id="sidebar" class="flex flex-col gap-1 pt-8 pr-6">
 | 
					<section id="sidebar" class="flex flex-col gap-1 pt-8 pr-6">
 | 
				
			||||||
	<a sveltekit:prefetch sveltekit:noscroll href={$page.routeId !== 'photos' ? `/photos` : null}>
 | 
						<a
 | 
				
			||||||
 | 
							sveltekit:prefetch
 | 
				
			||||||
 | 
							sveltekit:noscroll
 | 
				
			||||||
 | 
							href={$page.routeId !== 'photos' ? `/photos` : null}
 | 
				
			||||||
 | 
							class="relative"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
		<SideBarButton
 | 
							<SideBarButton
 | 
				
			||||||
			title="Photos"
 | 
								title={`Photos`}
 | 
				
			||||||
			logo={ImageOutline}
 | 
								logo={ImageOutline}
 | 
				
			||||||
			actionType={AppSideBarSelection.PHOTOS}
 | 
								actionType={AppSideBarSelection.PHOTOS}
 | 
				
			||||||
			isSelected={selectedAction === AppSideBarSelection.PHOTOS}
 | 
								isSelected={selectedAction === AppSideBarSelection.PHOTOS}
 | 
				
			||||||
		/></a
 | 
							/>
 | 
				
			||||||
	>
 | 
							<div
 | 
				
			||||||
	<a sveltekit:prefetch href={$page.routeId !== 'sharing' ? `/sharing` : null}>
 | 
								id="asset-count-info"
 | 
				
			||||||
 | 
								class="absolute right-4 top-[15px] z-40 text-xs hover:cursor-help"
 | 
				
			||||||
 | 
								on:mouseenter={() => (showAssetCount = true)}
 | 
				
			||||||
 | 
								on:mouseleave={() => (showAssetCount = false)}
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<InformationOutline size={18} color="#4250af" />
 | 
				
			||||||
 | 
								{#if showAssetCount}
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										transition:fade={{ duration: 200 }}
 | 
				
			||||||
 | 
										id="asset-count-info-detail"
 | 
				
			||||||
 | 
										class="w-32 rounded-lg px-4 py-2 shadow-lg bg-white absolute -right-[135px] top-0 z-[9999] flex place-items-center place-content-center"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{#await getAssetCount()}
 | 
				
			||||||
 | 
											<LoadingSpinner />
 | 
				
			||||||
 | 
										{:then data}
 | 
				
			||||||
 | 
											<div>
 | 
				
			||||||
 | 
												<p>{data.videos} Videos</p>
 | 
				
			||||||
 | 
												<p>{data.photos} Photos</p>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										{/await}
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<a sveltekit:prefetch href={$page.routeId !== 'sharing' ? `/sharing` : null} class="relative">
 | 
				
			||||||
		<SideBarButton
 | 
							<SideBarButton
 | 
				
			||||||
			title="Sharing"
 | 
								title="Sharing"
 | 
				
			||||||
			logo={AccountMultipleOutline}
 | 
								logo={AccountMultipleOutline}
 | 
				
			||||||
			actionType={AppSideBarSelection.SHARING}
 | 
								actionType={AppSideBarSelection.SHARING}
 | 
				
			||||||
			isSelected={selectedAction === AppSideBarSelection.SHARING}
 | 
								isSelected={selectedAction === AppSideBarSelection.SHARING}
 | 
				
			||||||
		/></a
 | 
							/>
 | 
				
			||||||
	>
 | 
							<div
 | 
				
			||||||
 | 
								id="sharing-count-info"
 | 
				
			||||||
 | 
								class="absolute right-4 top-[15px] z-40 text-xs hover:cursor-help"
 | 
				
			||||||
 | 
								on:mouseenter={() => (showSharingCount = true)}
 | 
				
			||||||
 | 
								on:mouseleave={() => (showSharingCount = false)}
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<InformationOutline size={18} color="#4250af" />
 | 
				
			||||||
 | 
								{#if showSharingCount}
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										transition:fade={{ duration: 200 }}
 | 
				
			||||||
 | 
										id="asset-count-info-detail"
 | 
				
			||||||
 | 
										class="w-32 rounded-lg px-4 py-2 shadow-lg bg-white absolute -right-[135px] top-0 z-[9999] flex place-items-center place-content-center"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{#await getAlbumCount()}
 | 
				
			||||||
 | 
											<LoadingSpinner />
 | 
				
			||||||
 | 
										{:then data}
 | 
				
			||||||
 | 
											<div>
 | 
				
			||||||
 | 
												<p>{data.shared + data.sharing} albums</p>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										{/await}
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</a>
 | 
				
			||||||
	<div class="text-xs ml-5 my-4">
 | 
						<div class="text-xs ml-5 my-4">
 | 
				
			||||||
		<p>LIBRARY</p>
 | 
							<p>LIBRARY</p>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<a sveltekit:prefetch href={$page.routeId !== 'albums' ? `/albums` : null}>
 | 
						<a sveltekit:prefetch href={$page.routeId !== 'albums' ? `/albums` : null} class="relative">
 | 
				
			||||||
		<SideBarButton
 | 
							<SideBarButton
 | 
				
			||||||
			title="Albums"
 | 
								title="Albums"
 | 
				
			||||||
			logo={ImageAlbum}
 | 
								logo={ImageAlbum}
 | 
				
			||||||
			actionType={AppSideBarSelection.ALBUMS}
 | 
								actionType={AppSideBarSelection.ALBUMS}
 | 
				
			||||||
			isSelected={selectedAction === AppSideBarSelection.ALBUMS}
 | 
								isSelected={selectedAction === AppSideBarSelection.ALBUMS}
 | 
				
			||||||
		/>
 | 
							/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								id="album-count-info"
 | 
				
			||||||
 | 
								class="absolute right-4 top-[15px] z-40 text-xs hover:cursor-help"
 | 
				
			||||||
 | 
								on:mouseenter={() => (showAlbumsCount = true)}
 | 
				
			||||||
 | 
								on:mouseleave={() => (showAlbumsCount = false)}
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<InformationOutline size={18} color="#4250af" />
 | 
				
			||||||
 | 
								{#if showAlbumsCount}
 | 
				
			||||||
 | 
									<div
 | 
				
			||||||
 | 
										transition:fade={{ duration: 200 }}
 | 
				
			||||||
 | 
										id="asset-count-info-detail"
 | 
				
			||||||
 | 
										class="w-32 rounded-lg px-4 py-2 shadow-lg bg-white absolute -right-[135px] top-0 z-[9999] flex place-items-center place-content-center"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										{#await getAlbumCount()}
 | 
				
			||||||
 | 
											<LoadingSpinner />
 | 
				
			||||||
 | 
										{:then data}
 | 
				
			||||||
 | 
											<div>
 | 
				
			||||||
 | 
												<p>{data.owned} albums</p>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										{/await}
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								{/if}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
	</a>
 | 
						</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<!-- Status Box -->
 | 
						<!-- Status Box -->
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,14 +26,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	export let data: PageData;
 | 
						export let data: PageData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	onMount(async () => {
 | 
					 | 
				
			||||||
		openWebsocketConnection();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return () => {
 | 
					 | 
				
			||||||
			closeWebsocketConnection();
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const deleteSelectedAssetHandler = async () => {
 | 
						const deleteSelectedAssetHandler = async () => {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			if (
 | 
								if (
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user