You've already forked immich
							
							
				mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-31 00:18:28 +02:00 
			
		
		
		
	feat(web, mobile): Options to show archived assets in map (#4293)
* Add include archive setting to map on web * open api * better naming for web isArchived variable * add withArchived setting to mobile * (e2e): tests for mapMarker endpoint and isArchived * isArchived to mobile * chore: cleanup test * chore: optimize e2e --------- Co-authored-by: shalong-tanwen <139912620+shalong-tanwen@users.noreply.github.com> Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
This commit is contained in:
		
							
								
								
									
										23
									
								
								cli/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										23
									
								
								cli/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							| @@ -6278,13 +6278,14 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration | ||||
|         }, | ||||
|         /** | ||||
|          *  | ||||
|          * @param {boolean} [isArchived]  | ||||
|          * @param {boolean} [isFavorite]  | ||||
|          * @param {string} [fileCreatedAfter]  | ||||
|          * @param {string} [fileCreatedBefore]  | ||||
|          * @param {*} [options] Override http request option. | ||||
|          * @throws {RequiredError} | ||||
|          */ | ||||
|         getMapMarkers: async (isFavorite?: boolean, fileCreatedAfter?: string, fileCreatedBefore?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => { | ||||
|         getMapMarkers: async (isArchived?: boolean, isFavorite?: boolean, fileCreatedAfter?: string, fileCreatedBefore?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => { | ||||
|             const localVarPath = `/asset/map-marker`; | ||||
|             // use dummy base URL string because the URL constructor only accepts absolute URLs.
 | ||||
|             const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); | ||||
| @@ -6306,6 +6307,10 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration | ||||
|             // http bearer authentication required
 | ||||
|             await setBearerAuthToObject(localVarHeaderParameter, configuration) | ||||
| 
 | ||||
|             if (isArchived !== undefined) { | ||||
|                 localVarQueryParameter['isArchived'] = isArchived; | ||||
|             } | ||||
| 
 | ||||
|             if (isFavorite !== undefined) { | ||||
|                 localVarQueryParameter['isFavorite'] = isFavorite; | ||||
|             } | ||||
| @@ -7134,14 +7139,15 @@ export const AssetApiFp = function(configuration?: Configuration) { | ||||
|         }, | ||||
|         /** | ||||
|          *  | ||||
|          * @param {boolean} [isArchived]  | ||||
|          * @param {boolean} [isFavorite]  | ||||
|          * @param {string} [fileCreatedAfter]  | ||||
|          * @param {string} [fileCreatedBefore]  | ||||
|          * @param {*} [options] Override http request option. | ||||
|          * @throws {RequiredError} | ||||
|          */ | ||||
|         async getMapMarkers(isFavorite?: boolean, fileCreatedAfter?: string, fileCreatedBefore?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<MapMarkerResponseDto>>> { | ||||
|             const localVarAxiosArgs = await localVarAxiosParamCreator.getMapMarkers(isFavorite, fileCreatedAfter, fileCreatedBefore, options); | ||||
|         async getMapMarkers(isArchived?: boolean, isFavorite?: boolean, fileCreatedAfter?: string, fileCreatedBefore?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<MapMarkerResponseDto>>> { | ||||
|             const localVarAxiosArgs = await localVarAxiosParamCreator.getMapMarkers(isArchived, isFavorite, fileCreatedAfter, fileCreatedBefore, options); | ||||
|             return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); | ||||
|         }, | ||||
|         /** | ||||
| @@ -7428,7 +7434,7 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath | ||||
|          * @throws {RequiredError} | ||||
|          */ | ||||
|         getMapMarkers(requestParameters: AssetApiGetMapMarkersRequest = {}, options?: AxiosRequestConfig): AxiosPromise<Array<MapMarkerResponseDto>> { | ||||
|             return localVarFp.getMapMarkers(requestParameters.isFavorite, requestParameters.fileCreatedAfter, requestParameters.fileCreatedBefore, options).then((request) => request(axios, basePath)); | ||||
|             return localVarFp.getMapMarkers(requestParameters.isArchived, requestParameters.isFavorite, requestParameters.fileCreatedAfter, requestParameters.fileCreatedBefore, options).then((request) => request(axios, basePath)); | ||||
|         }, | ||||
|         /** | ||||
|          *  | ||||
| @@ -7846,6 +7852,13 @@ export interface AssetApiGetDownloadInfoRequest { | ||||
|  * @interface AssetApiGetMapMarkersRequest | ||||
|  */ | ||||
| export interface AssetApiGetMapMarkersRequest { | ||||
|     /** | ||||
|      *  | ||||
|      * @type {boolean} | ||||
|      * @memberof AssetApiGetMapMarkers | ||||
|      */ | ||||
|     readonly isArchived?: boolean | ||||
| 
 | ||||
|     /** | ||||
|      *  | ||||
|      * @type {boolean} | ||||
| @@ -8374,7 +8387,7 @@ export class AssetApi extends BaseAPI { | ||||
|      * @memberof AssetApi | ||||
|      */ | ||||
|     public getMapMarkers(requestParameters: AssetApiGetMapMarkersRequest = {}, options?: AxiosRequestConfig) { | ||||
|         return AssetApiFp(this.configuration).getMapMarkers(requestParameters.isFavorite, requestParameters.fileCreatedAfter, requestParameters.fileCreatedBefore, options).then((request) => request(this.axios, this.basePath)); | ||||
|         return AssetApiFp(this.configuration).getMapMarkers(requestParameters.isArchived, requestParameters.isFavorite, requestParameters.fileCreatedAfter, requestParameters.fileCreatedBefore, options).then((request) => request(this.axios, this.basePath)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|   | ||||
| @@ -312,6 +312,7 @@ | ||||
|   "map_settings_dialog_title": "Map Settings", | ||||
|   "map_settings_dark_mode": "Dark mode", | ||||
|   "map_settings_only_show_favorites": "Show Favorite Only", | ||||
|   "map_settings_include_show_archived": "Include Archived", | ||||
|   "map_settings_only_relative_range": "Date range", | ||||
|   "map_settings_dialog_cancel": "Cancel", | ||||
|   "map_settings_dialog_save": "Save", | ||||
|   | ||||
| @@ -1,29 +1,33 @@ | ||||
| class MapState { | ||||
|   final bool isDarkTheme; | ||||
|   final bool showFavoriteOnly; | ||||
|   final bool includeArchived; | ||||
|   final int relativeTime; | ||||
|  | ||||
|   MapState({ | ||||
|     this.isDarkTheme = false, | ||||
|     this.showFavoriteOnly = false, | ||||
|     this.includeArchived = false, | ||||
|     this.relativeTime = 0, | ||||
|   }); | ||||
|  | ||||
|   MapState copyWith({ | ||||
|     bool? isDarkTheme, | ||||
|     bool? showFavoriteOnly, | ||||
|     bool? includeArchived, | ||||
|     int? relativeTime, | ||||
|   }) { | ||||
|     return MapState( | ||||
|       isDarkTheme: isDarkTheme ?? this.isDarkTheme, | ||||
|       showFavoriteOnly: showFavoriteOnly ?? this.showFavoriteOnly, | ||||
|       includeArchived: includeArchived ?? this.includeArchived, | ||||
|       relativeTime: relativeTime ?? this.relativeTime, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   String toString() { | ||||
|     return 'MapSettingsState(isDarkTheme: $isDarkTheme, showFavoriteOnly: $showFavoriteOnly, relativeTime: $relativeTime)'; | ||||
|     return 'MapSettingsState(isDarkTheme: $isDarkTheme, showFavoriteOnly: $showFavoriteOnly, relativeTime: $relativeTime, includeArchived: $includeArchived)'; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
| @@ -33,13 +37,15 @@ class MapState { | ||||
|     return other is MapState && | ||||
|         other.isDarkTheme == isDarkTheme && | ||||
|         other.showFavoriteOnly == showFavoriteOnly && | ||||
|         other.relativeTime == relativeTime; | ||||
|         other.relativeTime == relativeTime && | ||||
|         other.includeArchived == includeArchived; | ||||
|   } | ||||
|  | ||||
|   @override | ||||
|   int get hashCode { | ||||
|     return isDarkTheme.hashCode ^ | ||||
|         showFavoriteOnly.hashCode ^ | ||||
|         relativeTime.hashCode; | ||||
|         relativeTime.hashCode ^ | ||||
|         includeArchived.hashCode; | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -10,6 +10,7 @@ final mapMarkersProvider = | ||||
|   final mapState = ref.read(mapStateNotifier); | ||||
|   DateTime? fileCreatedAfter; | ||||
|   bool? isFavorite; | ||||
|   bool? isIncludeArchived; | ||||
|  | ||||
|   if (mapState.relativeTime != 0) { | ||||
|     fileCreatedAfter = | ||||
| @@ -20,8 +21,13 @@ final mapMarkersProvider = | ||||
|     isFavorite = true; | ||||
|   } | ||||
|  | ||||
|   if (!mapState.includeArchived) { | ||||
|     isIncludeArchived = false; | ||||
|   } | ||||
|  | ||||
|   final markers = await service.getMapMarkers( | ||||
|     isFavorite: isFavorite, | ||||
|     withArchived: isIncludeArchived, | ||||
|     fileCreatedAfter: fileCreatedAfter, | ||||
|   ); | ||||
|  | ||||
|   | ||||
| @@ -11,6 +11,8 @@ class MapStateNotifier extends StateNotifier<MapState> { | ||||
|                 .getSetting<bool>(AppSettingsEnum.mapThemeMode), | ||||
|             showFavoriteOnly: appSettingsProvider | ||||
|                 .getSetting<bool>(AppSettingsEnum.mapShowFavoriteOnly), | ||||
|             includeArchived: appSettingsProvider | ||||
|                 .getSetting<bool>(AppSettingsEnum.mapIncludeArchived), | ||||
|             relativeTime: appSettingsProvider | ||||
|                 .getSetting<int>(AppSettingsEnum.mapRelativeDate), | ||||
|           ), | ||||
| @@ -31,11 +33,19 @@ class MapStateNotifier extends StateNotifier<MapState> { | ||||
|   void switchFavoriteOnly(bool isFavoriteOnly) { | ||||
|     appSettingsProvider.setSetting( | ||||
|       AppSettingsEnum.mapShowFavoriteOnly, | ||||
|       appSettingsProvider, | ||||
|       isFavoriteOnly, | ||||
|     ); | ||||
|     state = state.copyWith(showFavoriteOnly: isFavoriteOnly); | ||||
|   } | ||||
|  | ||||
|   void switchIncludeArchived(bool isIncludeArchived) { | ||||
|     appSettingsProvider.setSetting( | ||||
|       AppSettingsEnum.mapIncludeArchived, | ||||
|       isIncludeArchived, | ||||
|     ); | ||||
|     state = state.copyWith(includeArchived: isIncludeArchived); | ||||
|   } | ||||
|  | ||||
|   void setRelativeTime(int relativeTime) { | ||||
|     appSettingsProvider.setSetting( | ||||
|       AppSettingsEnum.mapRelativeDate, | ||||
|   | ||||
| @@ -23,12 +23,14 @@ class MapSerivce { | ||||
|  | ||||
|   Future<List<MapMarkerResponseDto>> getMapMarkers({ | ||||
|     bool? isFavorite, | ||||
|     bool? withArchived, | ||||
|     DateTime? fileCreatedAfter, | ||||
|     DateTime? fileCreatedBefore, | ||||
|   }) async { | ||||
|     try { | ||||
|       final markers = await _apiService.assetApi.getMapMarkers( | ||||
|         isFavorite: isFavorite, | ||||
|         isArchived: withArchived, | ||||
|         fileCreatedAfter: fileCreatedAfter, | ||||
|         fileCreatedBefore: fileCreatedBefore, | ||||
|       ); | ||||
|   | ||||
| @@ -13,6 +13,7 @@ class MapSettingsDialog extends HookConsumerWidget { | ||||
|     final mapSettings = ref.read(mapStateNotifier); | ||||
|     final isDarkMode = useState(mapSettings.isDarkTheme); | ||||
|     final showFavoriteOnly = useState(mapSettings.showFavoriteOnly); | ||||
|     final showIncludeArchived = useState(mapSettings.includeArchived); | ||||
|     final showRelativeDate = useState(mapSettings.relativeTime); | ||||
|     final ThemeData theme = Theme.of(context); | ||||
|  | ||||
| @@ -48,6 +49,22 @@ class MapSettingsDialog extends HookConsumerWidget { | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     Widget buildIncludeArchivedSetting() { | ||||
|       return SwitchListTile.adaptive( | ||||
|         value: showIncludeArchived.value, | ||||
|         onChanged: (value) { | ||||
|           showIncludeArchived.value = value; | ||||
|         }, | ||||
|         activeColor: theme.primaryColor, | ||||
|         dense: true, | ||||
|         title: Text( | ||||
|           "map_settings_include_show_archived".tr(), | ||||
|           style: | ||||
|               theme.textTheme.labelLarge?.copyWith(fontWeight: FontWeight.bold), | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     Widget buildDateRangeSetting() { | ||||
|       final now = DateTime.now(); | ||||
|       return DropdownMenu( | ||||
| @@ -127,6 +144,8 @@ class MapSettingsDialog extends HookConsumerWidget { | ||||
|             mapSettingsNotifier.switchTheme(isDarkMode.value); | ||||
|             mapSettingsNotifier.switchFavoriteOnly(showFavoriteOnly.value); | ||||
|             mapSettingsNotifier.setRelativeTime(showRelativeDate.value); | ||||
|             mapSettingsNotifier | ||||
|                 .switchIncludeArchived(showIncludeArchived.value); | ||||
|             Navigator.of(context).pop(); | ||||
|           }, | ||||
|           style: TextButton.styleFrom( | ||||
| @@ -166,6 +185,7 @@ class MapSettingsDialog extends HookConsumerWidget { | ||||
|             children: [ | ||||
|               buildMapThemeSetting(), | ||||
|               buildFavoriteOnlySetting(), | ||||
|               buildIncludeArchivedSetting(), | ||||
|               const SizedBox( | ||||
|                 height: 10, | ||||
|               ), | ||||
|   | ||||
| @@ -155,7 +155,8 @@ class MapPageState extends ConsumerState<MapPage> { | ||||
|     ref.listen(mapStateNotifier, (previous, next) { | ||||
|       bool shouldRefetch = | ||||
|           previous?.showFavoriteOnly != next.showFavoriteOnly || | ||||
|               previous?.relativeTime != next.relativeTime; | ||||
|               previous?.relativeTime != next.relativeTime || | ||||
|               previous?.includeArchived != next.includeArchived; | ||||
|       if (shouldRefetch) { | ||||
|         refetchMarkers.value = shouldRefetch; | ||||
|         ref.invalidate(mapMarkersProvider); | ||||
|   | ||||
| @@ -48,6 +48,7 @@ enum AppSettingsEnum<T> { | ||||
|   preferRemoteImage<bool>(StoreKey.preferRemoteImage, null, false), | ||||
|   mapThemeMode<bool>(StoreKey.mapThemeMode, null, false), | ||||
|   mapShowFavoriteOnly<bool>(StoreKey.mapShowFavoriteOnly, null, false), | ||||
|   mapIncludeArchived<bool>(StoreKey.mapIncludeArchived, null, false), | ||||
|   mapRelativeDate<int>(StoreKey.mapRelativeDate, null, 0), | ||||
|   allowSelfSignedSSLCert<bool>(StoreKey.selfSignedCert, null, false), | ||||
|   ; | ||||
|   | ||||
| @@ -179,6 +179,7 @@ enum StoreKey<T> { | ||||
|   mapShowFavoriteOnly<bool>(118, type: bool), | ||||
|   mapRelativeDate<int>(119, type: int), | ||||
|   selfSignedCert<bool>(120, type: bool), | ||||
|   mapIncludeArchived<bool>(121, type: bool), | ||||
|   ; | ||||
|  | ||||
|   const StoreKey( | ||||
|   | ||||
							
								
								
									
										6
									
								
								mobile/openapi/doc/AssetApi.md
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								mobile/openapi/doc/AssetApi.md
									
									
									
										generated
									
									
									
								
							| @@ -902,7 +902,7 @@ 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) | ||||
| 
 | ||||
| # **getMapMarkers** | ||||
| > List<MapMarkerResponseDto> getMapMarkers(isFavorite, fileCreatedAfter, fileCreatedBefore) | ||||
| > List<MapMarkerResponseDto> getMapMarkers(isArchived, isFavorite, fileCreatedAfter, fileCreatedBefore) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @@ -925,12 +925,13 @@ import 'package:openapi/api.dart'; | ||||
| //defaultApiClient.getAuthentication<HttpBearerAuth>('bearer').setAccessToken(yourTokenGeneratorFunction); | ||||
| 
 | ||||
| final api_instance = AssetApi(); | ||||
| final isArchived = true; // bool |  | ||||
| final isFavorite = true; // bool |  | ||||
| final fileCreatedAfter = 2013-10-20T19:20:30+01:00; // DateTime |  | ||||
| final fileCreatedBefore = 2013-10-20T19:20:30+01:00; // DateTime |  | ||||
| 
 | ||||
| try { | ||||
|     final result = api_instance.getMapMarkers(isFavorite, fileCreatedAfter, fileCreatedBefore); | ||||
|     final result = api_instance.getMapMarkers(isArchived, isFavorite, fileCreatedAfter, fileCreatedBefore); | ||||
|     print(result); | ||||
| } catch (e) { | ||||
|     print('Exception when calling AssetApi->getMapMarkers: $e\n'); | ||||
| @@ -941,6 +942,7 @@ try { | ||||
| 
 | ||||
| Name | Type | Description  | Notes | ||||
| ------------- | ------------- | ------------- | ------------- | ||||
|  **isArchived** | **bool**|  | [optional]  | ||||
|  **isFavorite** | **bool**|  | [optional]  | ||||
|  **fileCreatedAfter** | **DateTime**|  | [optional]  | ||||
|  **fileCreatedBefore** | **DateTime**|  | [optional]  | ||||
|   | ||||
							
								
								
									
										13
									
								
								mobile/openapi/lib/api/asset_api.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										13
									
								
								mobile/openapi/lib/api/asset_api.dart
									
									
									
										generated
									
									
									
								
							| @@ -909,12 +909,14 @@ class AssetApi { | ||||
|   /// Performs an HTTP 'GET /asset/map-marker' operation and returns the [Response]. | ||||
|   /// Parameters: | ||||
|   /// | ||||
|   /// * [bool] isArchived: | ||||
|   /// | ||||
|   /// * [bool] isFavorite: | ||||
|   /// | ||||
|   /// * [DateTime] fileCreatedAfter: | ||||
|   /// | ||||
|   /// * [DateTime] fileCreatedBefore: | ||||
|   Future<Response> getMapMarkersWithHttpInfo({ bool? isFavorite, DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, }) async { | ||||
|   Future<Response> getMapMarkersWithHttpInfo({ bool? isArchived, bool? isFavorite, DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, }) async { | ||||
|     // ignore: prefer_const_declarations | ||||
|     final path = r'/asset/map-marker'; | ||||
| 
 | ||||
| @@ -925,6 +927,9 @@ class AssetApi { | ||||
|     final headerParams = <String, String>{}; | ||||
|     final formParams = <String, String>{}; | ||||
| 
 | ||||
|     if (isArchived != null) { | ||||
|       queryParams.addAll(_queryParams('', 'isArchived', isArchived)); | ||||
|     } | ||||
|     if (isFavorite != null) { | ||||
|       queryParams.addAll(_queryParams('', 'isFavorite', isFavorite)); | ||||
|     } | ||||
| @@ -951,13 +956,15 @@ class AssetApi { | ||||
| 
 | ||||
|   /// Parameters: | ||||
|   /// | ||||
|   /// * [bool] isArchived: | ||||
|   /// | ||||
|   /// * [bool] isFavorite: | ||||
|   /// | ||||
|   /// * [DateTime] fileCreatedAfter: | ||||
|   /// | ||||
|   /// * [DateTime] fileCreatedBefore: | ||||
|   Future<List<MapMarkerResponseDto>?> getMapMarkers({ bool? isFavorite, DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, }) async { | ||||
|     final response = await getMapMarkersWithHttpInfo( isFavorite: isFavorite, fileCreatedAfter: fileCreatedAfter, fileCreatedBefore: fileCreatedBefore, ); | ||||
|   Future<List<MapMarkerResponseDto>?> getMapMarkers({ bool? isArchived, bool? isFavorite, DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, }) async { | ||||
|     final response = await getMapMarkersWithHttpInfo( isArchived: isArchived, isFavorite: isFavorite, fileCreatedAfter: fileCreatedAfter, fileCreatedBefore: fileCreatedBefore, ); | ||||
|     if (response.statusCode >= HttpStatus.badRequest) { | ||||
|       throw ApiException(response.statusCode, await _decodeBodyBytes(response)); | ||||
|     } | ||||
|   | ||||
							
								
								
									
										2
									
								
								mobile/openapi/test/asset_api_test.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								mobile/openapi/test/asset_api_test.dart
									
									
									
										generated
									
									
									
								
							| @@ -102,7 +102,7 @@ void main() { | ||||
|       // TODO | ||||
|     }); | ||||
| 
 | ||||
|     //Future<List<MapMarkerResponseDto>> getMapMarkers({ bool isFavorite, DateTime fileCreatedAfter, DateTime fileCreatedBefore }) async | ||||
|     //Future<List<MapMarkerResponseDto>> getMapMarkers({ bool isArchived, bool isFavorite, DateTime fileCreatedAfter, DateTime fileCreatedBefore }) async | ||||
|     test('test getMapMarkers', () async { | ||||
|       // TODO | ||||
|     }); | ||||
|   | ||||
| @@ -1406,6 +1406,14 @@ | ||||
|       "get": { | ||||
|         "operationId": "getMapMarkers", | ||||
|         "parameters": [ | ||||
|           { | ||||
|             "name": "isArchived", | ||||
|             "required": false, | ||||
|             "in": "query", | ||||
|             "schema": { | ||||
|               "type": "boolean" | ||||
|             } | ||||
|           }, | ||||
|           { | ||||
|             "name": "isFavorite", | ||||
|             "required": false, | ||||
|   | ||||
| @@ -22,6 +22,7 @@ export interface LivePhotoSearchOptions { | ||||
| } | ||||
|  | ||||
| export interface MapMarkerSearchOptions { | ||||
|   isArchived?: boolean; | ||||
|   isFavorite?: boolean; | ||||
|   fileCreatedBefore?: Date; | ||||
|   fileCreatedAfter?: Date; | ||||
|   | ||||
| @@ -4,6 +4,12 @@ import { IsBoolean, IsDate } from 'class-validator'; | ||||
| import { Optional, toBoolean } from '../../domain.util'; | ||||
|  | ||||
| export class MapMarkerDto { | ||||
|   @ApiProperty() | ||||
|   @Optional() | ||||
|   @IsBoolean() | ||||
|   @Transform(toBoolean) | ||||
|   isArchived?: boolean; | ||||
|  | ||||
|   @ApiProperty() | ||||
|   @Optional() | ||||
|   @IsBoolean() | ||||
|   | ||||
| @@ -355,7 +355,7 @@ export class AssetRepository implements IAssetRepository { | ||||
|   } | ||||
|  | ||||
|   async getMapMarkers(ownerId: string, options: MapMarkerSearchOptions = {}): Promise<MapMarker[]> { | ||||
|     const { isFavorite, fileCreatedAfter, fileCreatedBefore } = options; | ||||
|     const { isArchived, isFavorite, fileCreatedAfter, fileCreatedBefore } = options; | ||||
|  | ||||
|     const assets = await this.repository.find({ | ||||
|       select: { | ||||
| @@ -368,7 +368,7 @@ export class AssetRepository implements IAssetRepository { | ||||
|       where: { | ||||
|         ownerId, | ||||
|         isVisible: true, | ||||
|         isArchived: false, | ||||
|         isArchived, | ||||
|         exifInfo: { | ||||
|           latitude: Not(IsNull()), | ||||
|           longitude: Not(IsNull()), | ||||
|   | ||||
| @@ -56,6 +56,7 @@ const createAsset = ( | ||||
|     deviceAssetId: `test_${id}`, | ||||
|     deviceId: 'e2e-test', | ||||
|     libraryId, | ||||
|     isVisible: true, | ||||
|     fileCreatedAt: createdAt, | ||||
|     fileModifiedAt: new Date(), | ||||
|     type: AssetType.IMAGE, | ||||
| @@ -89,19 +90,25 @@ describe(`${AssetController.name} (e2e)`, () => { | ||||
|     await api.authApi.adminSignUp(server); | ||||
|     const admin = await api.authApi.adminLogin(server); | ||||
|  | ||||
|     const libraries = await api.libraryApi.getAll(server, admin.accessToken); | ||||
|     const [libraries] = await Promise.all([ | ||||
|       api.libraryApi.getAll(server, admin.accessToken), | ||||
|       api.userApi.create(server, admin.accessToken, user1Dto), | ||||
|       api.userApi.create(server, admin.accessToken, user2Dto), | ||||
|     ]); | ||||
|  | ||||
|     const defaultLibrary = libraries[0]; | ||||
|  | ||||
|     await api.userApi.create(server, admin.accessToken, user1Dto); | ||||
|     user1 = await api.authApi.login(server, { email: user1Dto.email, password: user1Dto.password }); | ||||
|     [user1, user2] = await Promise.all([ | ||||
|       api.authApi.login(server, { email: user1Dto.email, password: user1Dto.password }), | ||||
|       api.authApi.login(server, { email: user2Dto.email, password: user2Dto.password }), | ||||
|     ]); | ||||
|  | ||||
|     asset1 = await createAsset(assetRepository, user1, defaultLibrary.id, new Date('1970-01-01')); | ||||
|     asset2 = await createAsset(assetRepository, user1, defaultLibrary.id, new Date('1970-01-02')); | ||||
|     asset3 = await createAsset(assetRepository, user1, defaultLibrary.id, new Date('1970-02-01')); | ||||
|  | ||||
|     await api.userApi.create(server, admin.accessToken, user2Dto); | ||||
|     user2 = await api.authApi.login(server, { email: user2Dto.email, password: user2Dto.password }); | ||||
|     asset4 = await createAsset(assetRepository, user2, defaultLibrary.id, new Date('1970-01-01')); | ||||
|     [asset1, asset2, asset3, asset4] = await Promise.all([ | ||||
|       createAsset(assetRepository, user1, defaultLibrary.id, new Date('1970-01-01')), | ||||
|       createAsset(assetRepository, user1, defaultLibrary.id, new Date('1970-01-02')), | ||||
|       createAsset(assetRepository, user1, defaultLibrary.id, new Date('1970-02-01')), | ||||
|       createAsset(assetRepository, user2, defaultLibrary.id, new Date('1970-01-01')), | ||||
|     ]); | ||||
|   }); | ||||
|  | ||||
|   afterAll(async () => { | ||||
| @@ -515,4 +522,45 @@ describe(`${AssetController.name} (e2e)`, () => { | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   describe('GET /asset/map-marker', () => { | ||||
|     beforeEach(async () => { | ||||
|       await assetRepository.save({ id: asset1.id, isArchived: true }); | ||||
|       await assetRepository.upsertExif({ assetId: asset1.id, latitude: 0, longitude: 0 }); | ||||
|       await assetRepository.upsertExif({ assetId: asset2.id, latitude: 0, longitude: 0 }); | ||||
|     }); | ||||
|  | ||||
|     it('should require authentication', async () => { | ||||
|       const { status, body } = await request(server).get('/asset/map-marker'); | ||||
|  | ||||
|       expect(status).toBe(401); | ||||
|       expect(body).toEqual(errorStub.unauthorized); | ||||
|     }); | ||||
|  | ||||
|     it('should get map markers for all non-archived assets', async () => { | ||||
|       const { status, body } = await request(server) | ||||
|         .get('/asset/map-marker') | ||||
|         .set('Authorization', `Bearer ${user1.accessToken}`); | ||||
|  | ||||
|       expect(status).toBe(200); | ||||
|       expect(body).toHaveLength(2); | ||||
|       expect(body).toEqual( | ||||
|         expect.arrayContaining([ | ||||
|           expect.objectContaining({ id: asset1.id }), | ||||
|           expect.objectContaining({ id: asset2.id }), | ||||
|         ]), | ||||
|       ); | ||||
|     }); | ||||
|  | ||||
|     it('should get all map markers', async () => { | ||||
|       const { status, body } = await request(server) | ||||
|         .get('/asset/map-marker') | ||||
|         .set('Authorization', `Bearer ${user1.accessToken}`) | ||||
|         .query({ isArchived: false }); | ||||
|  | ||||
|       expect(status).toBe(200); | ||||
|       expect(body).toHaveLength(1); | ||||
|       expect(body).toEqual([expect.objectContaining({ id: asset2.id })]); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
|   | ||||
							
								
								
									
										23
									
								
								web/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										23
									
								
								web/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							| @@ -6278,13 +6278,14 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration | ||||
|         }, | ||||
|         /** | ||||
|          *  | ||||
|          * @param {boolean} [isArchived]  | ||||
|          * @param {boolean} [isFavorite]  | ||||
|          * @param {string} [fileCreatedAfter]  | ||||
|          * @param {string} [fileCreatedBefore]  | ||||
|          * @param {*} [options] Override http request option. | ||||
|          * @throws {RequiredError} | ||||
|          */ | ||||
|         getMapMarkers: async (isFavorite?: boolean, fileCreatedAfter?: string, fileCreatedBefore?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => { | ||||
|         getMapMarkers: async (isArchived?: boolean, isFavorite?: boolean, fileCreatedAfter?: string, fileCreatedBefore?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => { | ||||
|             const localVarPath = `/asset/map-marker`; | ||||
|             // use dummy base URL string because the URL constructor only accepts absolute URLs.
 | ||||
|             const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); | ||||
| @@ -6306,6 +6307,10 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration | ||||
|             // http bearer authentication required
 | ||||
|             await setBearerAuthToObject(localVarHeaderParameter, configuration) | ||||
| 
 | ||||
|             if (isArchived !== undefined) { | ||||
|                 localVarQueryParameter['isArchived'] = isArchived; | ||||
|             } | ||||
| 
 | ||||
|             if (isFavorite !== undefined) { | ||||
|                 localVarQueryParameter['isFavorite'] = isFavorite; | ||||
|             } | ||||
| @@ -7134,14 +7139,15 @@ export const AssetApiFp = function(configuration?: Configuration) { | ||||
|         }, | ||||
|         /** | ||||
|          *  | ||||
|          * @param {boolean} [isArchived]  | ||||
|          * @param {boolean} [isFavorite]  | ||||
|          * @param {string} [fileCreatedAfter]  | ||||
|          * @param {string} [fileCreatedBefore]  | ||||
|          * @param {*} [options] Override http request option. | ||||
|          * @throws {RequiredError} | ||||
|          */ | ||||
|         async getMapMarkers(isFavorite?: boolean, fileCreatedAfter?: string, fileCreatedBefore?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<MapMarkerResponseDto>>> { | ||||
|             const localVarAxiosArgs = await localVarAxiosParamCreator.getMapMarkers(isFavorite, fileCreatedAfter, fileCreatedBefore, options); | ||||
|         async getMapMarkers(isArchived?: boolean, isFavorite?: boolean, fileCreatedAfter?: string, fileCreatedBefore?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<MapMarkerResponseDto>>> { | ||||
|             const localVarAxiosArgs = await localVarAxiosParamCreator.getMapMarkers(isArchived, isFavorite, fileCreatedAfter, fileCreatedBefore, options); | ||||
|             return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); | ||||
|         }, | ||||
|         /** | ||||
| @@ -7428,7 +7434,7 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath | ||||
|          * @throws {RequiredError} | ||||
|          */ | ||||
|         getMapMarkers(requestParameters: AssetApiGetMapMarkersRequest = {}, options?: AxiosRequestConfig): AxiosPromise<Array<MapMarkerResponseDto>> { | ||||
|             return localVarFp.getMapMarkers(requestParameters.isFavorite, requestParameters.fileCreatedAfter, requestParameters.fileCreatedBefore, options).then((request) => request(axios, basePath)); | ||||
|             return localVarFp.getMapMarkers(requestParameters.isArchived, requestParameters.isFavorite, requestParameters.fileCreatedAfter, requestParameters.fileCreatedBefore, options).then((request) => request(axios, basePath)); | ||||
|         }, | ||||
|         /** | ||||
|          *  | ||||
| @@ -7846,6 +7852,13 @@ export interface AssetApiGetDownloadInfoRequest { | ||||
|  * @interface AssetApiGetMapMarkersRequest | ||||
|  */ | ||||
| export interface AssetApiGetMapMarkersRequest { | ||||
|     /** | ||||
|      *  | ||||
|      * @type {boolean} | ||||
|      * @memberof AssetApiGetMapMarkers | ||||
|      */ | ||||
|     readonly isArchived?: boolean | ||||
| 
 | ||||
|     /** | ||||
|      *  | ||||
|      * @type {boolean} | ||||
| @@ -8374,7 +8387,7 @@ export class AssetApi extends BaseAPI { | ||||
|      * @memberof AssetApi | ||||
|      */ | ||||
|     public getMapMarkers(requestParameters: AssetApiGetMapMarkersRequest = {}, options?: AxiosRequestConfig) { | ||||
|         return AssetApiFp(this.configuration).getMapMarkers(requestParameters.isFavorite, requestParameters.fileCreatedAfter, requestParameters.fileCreatedBefore, options).then((request) => request(this.axios, this.basePath)); | ||||
|         return AssetApiFp(this.configuration).getMapMarkers(requestParameters.isArchived, requestParameters.isFavorite, requestParameters.fileCreatedAfter, requestParameters.fileCreatedBefore, options).then((request) => request(this.axios, this.basePath)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|   | ||||
| @@ -32,6 +32,7 @@ | ||||
|     > | ||||
|       <SettingSwitch title="Allow dark mode" bind:checked={settings.allowDarkMode} /> | ||||
|       <SettingSwitch title="Only favorites" bind:checked={settings.onlyFavorites} /> | ||||
|       <SettingSwitch title="Include archived" bind:checked={settings.includeArchived} /> | ||||
|       {#if customDateRange} | ||||
|         <div in:fly={{ y: 10, duration: 200 }} class="flex flex-col gap-4"> | ||||
|           <div class="flex items-center justify-between gap-8"> | ||||
|   | ||||
| @@ -21,6 +21,7 @@ export const locale = persisted<string | undefined>('locale', undefined, { | ||||
|  | ||||
| export interface MapSettings { | ||||
|   allowDarkMode: boolean; | ||||
|   includeArchived: boolean; | ||||
|   onlyFavorites: boolean; | ||||
|   relativeDate: string; | ||||
|   dateAfter: string; | ||||
| @@ -29,6 +30,7 @@ export interface MapSettings { | ||||
|  | ||||
| export const mapSettings = persisted<MapSettings>('map-settings', { | ||||
|   allowDarkMode: true, | ||||
|   includeArchived: false, | ||||
|   onlyFavorites: false, | ||||
|   relativeDate: '', | ||||
|   dateAfter: '', | ||||
|   | ||||
| @@ -44,11 +44,12 @@ | ||||
|     } | ||||
|     abortController = new AbortController(); | ||||
|  | ||||
|     const { onlyFavorites } = $mapSettings; | ||||
|     const { includeArchived, onlyFavorites } = $mapSettings; | ||||
|     const { fileCreatedAfter, fileCreatedBefore } = getFileCreatedDates(); | ||||
|  | ||||
|     const { data } = await api.assetApi.getMapMarkers( | ||||
|       { | ||||
|         isArchived: includeArchived && undefined, | ||||
|         isFavorite: onlyFavorites || undefined, | ||||
|         fileCreatedAfter: fileCreatedAfter || undefined, | ||||
|         fileCreatedBefore, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user