mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	feat(web,server): run jobs for specific assets (#3712)
* feat(web,server): manually queue asset job * chore: open api * chore: tests
This commit is contained in:
		
							
								
								
									
										124
									
								
								cli/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										124
									
								
								cli/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							@@ -525,6 +525,42 @@ export const AssetIdsResponseDtoErrorEnum = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export type AssetIdsResponseDtoErrorEnum = typeof AssetIdsResponseDtoErrorEnum[keyof typeof AssetIdsResponseDtoErrorEnum];
 | 
					export type AssetIdsResponseDtoErrorEnum = typeof AssetIdsResponseDtoErrorEnum[keyof typeof AssetIdsResponseDtoErrorEnum];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @enum {string}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const AssetJobName = {
 | 
				
			||||||
 | 
					    RegenerateThumbnail: 'regenerate-thumbnail',
 | 
				
			||||||
 | 
					    RefreshMetadata: 'refresh-metadata',
 | 
				
			||||||
 | 
					    TranscodeVideo: 'transcode-video'
 | 
				
			||||||
 | 
					} as const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AssetJobName = typeof AssetJobName[keyof typeof AssetJobName];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface AssetJobsDto
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface AssetJobsDto {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {Array<string>}
 | 
				
			||||||
 | 
					     * @memberof AssetJobsDto
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'assetIds': Array<string>;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {AssetJobName}
 | 
				
			||||||
 | 
					     * @memberof AssetJobsDto
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'name': AssetJobName;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 
 | 
					 * 
 | 
				
			||||||
 * @export
 | 
					 * @export
 | 
				
			||||||
@@ -5784,6 +5820,50 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
 | 
				
			|||||||
                options: localVarRequestOptions,
 | 
					                options: localVarRequestOptions,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {AssetJobsDto} assetJobsDto 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        runAssetJobs: async (assetJobsDto: AssetJobsDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
 | 
				
			||||||
 | 
					            // verify required parameter 'assetJobsDto' is not null or undefined
 | 
				
			||||||
 | 
					            assertParamExists('runAssetJobs', 'assetJobsDto', assetJobsDto)
 | 
				
			||||||
 | 
					            const localVarPath = `/asset/jobs`;
 | 
				
			||||||
 | 
					            // 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: 'POST', ...baseOptions, ...options};
 | 
				
			||||||
 | 
					            const localVarHeaderParameter = {} as any;
 | 
				
			||||||
 | 
					            const localVarQueryParameter = {} as any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication cookie required
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication api_key required
 | 
				
			||||||
 | 
					            await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication bearer required
 | 
				
			||||||
 | 
					            // http bearer authentication required
 | 
				
			||||||
 | 
					            await setBearerAuthToObject(localVarHeaderParameter, configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            localVarHeaderParameter['Content-Type'] = 'application/json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            setSearchParams(localVarUrlObj, localVarQueryParameter);
 | 
				
			||||||
 | 
					            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
 | 
				
			||||||
 | 
					            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
 | 
				
			||||||
 | 
					            localVarRequestOptions.data = serializeDataIfNeeded(assetJobsDto, localVarRequestOptions, configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                url: toPathString(localVarUrlObj),
 | 
				
			||||||
 | 
					                options: localVarRequestOptions,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {SearchAssetDto} searchAssetDto 
 | 
					         * @param {SearchAssetDto} searchAssetDto 
 | 
				
			||||||
@@ -6331,6 +6411,16 @@ export const AssetApiFp = function(configuration?: Configuration) {
 | 
				
			|||||||
            const localVarAxiosArgs = await localVarAxiosParamCreator.importFile(importAssetDto, options);
 | 
					            const localVarAxiosArgs = await localVarAxiosParamCreator.importFile(importAssetDto, options);
 | 
				
			||||||
            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
					            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {AssetJobsDto} assetJobsDto 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        async runAssetJobs(assetJobsDto: AssetJobsDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
 | 
				
			||||||
 | 
					            const localVarAxiosArgs = await localVarAxiosParamCreator.runAssetJobs(assetJobsDto, options);
 | 
				
			||||||
 | 
					            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {SearchAssetDto} searchAssetDto 
 | 
					         * @param {SearchAssetDto} searchAssetDto 
 | 
				
			||||||
@@ -6584,6 +6674,15 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
 | 
				
			|||||||
        importFile(requestParameters: AssetApiImportFileRequest, options?: AxiosRequestConfig): AxiosPromise<AssetFileUploadResponseDto> {
 | 
					        importFile(requestParameters: AssetApiImportFileRequest, options?: AxiosRequestConfig): AxiosPromise<AssetFileUploadResponseDto> {
 | 
				
			||||||
            return localVarFp.importFile(requestParameters.importAssetDto, options).then((request) => request(axios, basePath));
 | 
					            return localVarFp.importFile(requestParameters.importAssetDto, options).then((request) => request(axios, basePath));
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {AssetApiRunAssetJobsRequest} requestParameters Request parameters.
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        runAssetJobs(requestParameters: AssetApiRunAssetJobsRequest, options?: AxiosRequestConfig): AxiosPromise<void> {
 | 
				
			||||||
 | 
					            return localVarFp.runAssetJobs(requestParameters.assetJobsDto, options).then((request) => request(axios, basePath));
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {AssetApiSearchAssetRequest} requestParameters Request parameters.
 | 
					         * @param {AssetApiSearchAssetRequest} requestParameters Request parameters.
 | 
				
			||||||
@@ -7066,6 +7165,20 @@ export interface AssetApiImportFileRequest {
 | 
				
			|||||||
    readonly importAssetDto: ImportAssetDto
 | 
					    readonly importAssetDto: ImportAssetDto
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Request parameters for runAssetJobs operation in AssetApi.
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface AssetApiRunAssetJobsRequest
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface AssetApiRunAssetJobsRequest {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {AssetJobsDto}
 | 
				
			||||||
 | 
					     * @memberof AssetApiRunAssetJobs
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    readonly assetJobsDto: AssetJobsDto
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Request parameters for searchAsset operation in AssetApi.
 | 
					 * Request parameters for searchAsset operation in AssetApi.
 | 
				
			||||||
 * @export
 | 
					 * @export
 | 
				
			||||||
@@ -7472,6 +7585,17 @@ export class AssetApi extends BaseAPI {
 | 
				
			|||||||
        return AssetApiFp(this.configuration).importFile(requestParameters.importAssetDto, options).then((request) => request(this.axios, this.basePath));
 | 
					        return AssetApiFp(this.configuration).importFile(requestParameters.importAssetDto, options).then((request) => request(this.axios, this.basePath));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @param {AssetApiRunAssetJobsRequest} requestParameters Request parameters.
 | 
				
			||||||
 | 
					     * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					     * @throws {RequiredError}
 | 
				
			||||||
 | 
					     * @memberof AssetApi
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public runAssetJobs(requestParameters: AssetApiRunAssetJobsRequest, options?: AxiosRequestConfig) {
 | 
				
			||||||
 | 
					        return AssetApiFp(this.configuration).runAssetJobs(requestParameters.assetJobsDto, options).then((request) => request(this.axios, this.basePath));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 
 | 
					     * 
 | 
				
			||||||
     * @param {AssetApiSearchAssetRequest} requestParameters Request parameters.
 | 
					     * @param {AssetApiSearchAssetRequest} requestParameters Request parameters.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								mobile/openapi/.openapi-generator/FILES
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								mobile/openapi/.openapi-generator/FILES
									
									
									
										generated
									
									
									
								
							@@ -23,6 +23,8 @@ doc/AssetBulkUploadCheckResult.md
 | 
				
			|||||||
doc/AssetFileUploadResponseDto.md
 | 
					doc/AssetFileUploadResponseDto.md
 | 
				
			||||||
doc/AssetIdsDto.md
 | 
					doc/AssetIdsDto.md
 | 
				
			||||||
doc/AssetIdsResponseDto.md
 | 
					doc/AssetIdsResponseDto.md
 | 
				
			||||||
 | 
					doc/AssetJobName.md
 | 
				
			||||||
 | 
					doc/AssetJobsDto.md
 | 
				
			||||||
doc/AssetResponseDto.md
 | 
					doc/AssetResponseDto.md
 | 
				
			||||||
doc/AssetStatsResponseDto.md
 | 
					doc/AssetStatsResponseDto.md
 | 
				
			||||||
doc/AssetTypeEnum.md
 | 
					doc/AssetTypeEnum.md
 | 
				
			||||||
@@ -168,6 +170,8 @@ lib/model/asset_bulk_upload_check_result.dart
 | 
				
			|||||||
lib/model/asset_file_upload_response_dto.dart
 | 
					lib/model/asset_file_upload_response_dto.dart
 | 
				
			||||||
lib/model/asset_ids_dto.dart
 | 
					lib/model/asset_ids_dto.dart
 | 
				
			||||||
lib/model/asset_ids_response_dto.dart
 | 
					lib/model/asset_ids_response_dto.dart
 | 
				
			||||||
 | 
					lib/model/asset_job_name.dart
 | 
				
			||||||
 | 
					lib/model/asset_jobs_dto.dart
 | 
				
			||||||
lib/model/asset_response_dto.dart
 | 
					lib/model/asset_response_dto.dart
 | 
				
			||||||
lib/model/asset_stats_response_dto.dart
 | 
					lib/model/asset_stats_response_dto.dart
 | 
				
			||||||
lib/model/asset_type_enum.dart
 | 
					lib/model/asset_type_enum.dart
 | 
				
			||||||
@@ -282,6 +286,8 @@ test/asset_bulk_upload_check_result_test.dart
 | 
				
			|||||||
test/asset_file_upload_response_dto_test.dart
 | 
					test/asset_file_upload_response_dto_test.dart
 | 
				
			||||||
test/asset_ids_dto_test.dart
 | 
					test/asset_ids_dto_test.dart
 | 
				
			||||||
test/asset_ids_response_dto_test.dart
 | 
					test/asset_ids_response_dto_test.dart
 | 
				
			||||||
 | 
					test/asset_job_name_test.dart
 | 
				
			||||||
 | 
					test/asset_jobs_dto_test.dart
 | 
				
			||||||
test/asset_response_dto_test.dart
 | 
					test/asset_response_dto_test.dart
 | 
				
			||||||
test/asset_stats_response_dto_test.dart
 | 
					test/asset_stats_response_dto_test.dart
 | 
				
			||||||
test/asset_type_enum_test.dart
 | 
					test/asset_type_enum_test.dart
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								mobile/openapi/README.md
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3
									
								
								mobile/openapi/README.md
									
									
									
										generated
									
									
									
								
							@@ -107,6 +107,7 @@ Class | Method | HTTP request | Description
 | 
				
			|||||||
*AssetApi* | [**getTimeBuckets**](doc//AssetApi.md#gettimebuckets) | **GET** /asset/time-buckets | 
 | 
					*AssetApi* | [**getTimeBuckets**](doc//AssetApi.md#gettimebuckets) | **GET** /asset/time-buckets | 
 | 
				
			||||||
*AssetApi* | [**getUserAssetsByDeviceId**](doc//AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} | 
 | 
					*AssetApi* | [**getUserAssetsByDeviceId**](doc//AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} | 
 | 
				
			||||||
*AssetApi* | [**importFile**](doc//AssetApi.md#importfile) | **POST** /asset/import | 
 | 
					*AssetApi* | [**importFile**](doc//AssetApi.md#importfile) | **POST** /asset/import | 
 | 
				
			||||||
 | 
					*AssetApi* | [**runAssetJobs**](doc//AssetApi.md#runassetjobs) | **POST** /asset/jobs | 
 | 
				
			||||||
*AssetApi* | [**searchAsset**](doc//AssetApi.md#searchasset) | **POST** /asset/search | 
 | 
					*AssetApi* | [**searchAsset**](doc//AssetApi.md#searchasset) | **POST** /asset/search | 
 | 
				
			||||||
*AssetApi* | [**serveFile**](doc//AssetApi.md#servefile) | **GET** /asset/file/{id} | 
 | 
					*AssetApi* | [**serveFile**](doc//AssetApi.md#servefile) | **GET** /asset/file/{id} | 
 | 
				
			||||||
*AssetApi* | [**updateAsset**](doc//AssetApi.md#updateasset) | **PUT** /asset/{id} | 
 | 
					*AssetApi* | [**updateAsset**](doc//AssetApi.md#updateasset) | **PUT** /asset/{id} | 
 | 
				
			||||||
@@ -197,6 +198,8 @@ Class | Method | HTTP request | Description
 | 
				
			|||||||
 - [AssetFileUploadResponseDto](doc//AssetFileUploadResponseDto.md)
 | 
					 - [AssetFileUploadResponseDto](doc//AssetFileUploadResponseDto.md)
 | 
				
			||||||
 - [AssetIdsDto](doc//AssetIdsDto.md)
 | 
					 - [AssetIdsDto](doc//AssetIdsDto.md)
 | 
				
			||||||
 - [AssetIdsResponseDto](doc//AssetIdsResponseDto.md)
 | 
					 - [AssetIdsResponseDto](doc//AssetIdsResponseDto.md)
 | 
				
			||||||
 | 
					 - [AssetJobName](doc//AssetJobName.md)
 | 
				
			||||||
 | 
					 - [AssetJobsDto](doc//AssetJobsDto.md)
 | 
				
			||||||
 - [AssetResponseDto](doc//AssetResponseDto.md)
 | 
					 - [AssetResponseDto](doc//AssetResponseDto.md)
 | 
				
			||||||
 - [AssetStatsResponseDto](doc//AssetStatsResponseDto.md)
 | 
					 - [AssetStatsResponseDto](doc//AssetStatsResponseDto.md)
 | 
				
			||||||
 - [AssetTypeEnum](doc//AssetTypeEnum.md)
 | 
					 - [AssetTypeEnum](doc//AssetTypeEnum.md)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										55
									
								
								mobile/openapi/doc/AssetApi.md
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										55
									
								
								mobile/openapi/doc/AssetApi.md
									
									
									
										generated
									
									
									
								
							@@ -29,6 +29,7 @@ Method | HTTP request | Description
 | 
				
			|||||||
[**getTimeBuckets**](AssetApi.md#gettimebuckets) | **GET** /asset/time-buckets | 
 | 
					[**getTimeBuckets**](AssetApi.md#gettimebuckets) | **GET** /asset/time-buckets | 
 | 
				
			||||||
[**getUserAssetsByDeviceId**](AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} | 
 | 
					[**getUserAssetsByDeviceId**](AssetApi.md#getuserassetsbydeviceid) | **GET** /asset/{deviceId} | 
 | 
				
			||||||
[**importFile**](AssetApi.md#importfile) | **POST** /asset/import | 
 | 
					[**importFile**](AssetApi.md#importfile) | **POST** /asset/import | 
 | 
				
			||||||
 | 
					[**runAssetJobs**](AssetApi.md#runassetjobs) | **POST** /asset/jobs | 
 | 
				
			||||||
[**searchAsset**](AssetApi.md#searchasset) | **POST** /asset/search | 
 | 
					[**searchAsset**](AssetApi.md#searchasset) | **POST** /asset/search | 
 | 
				
			||||||
[**serveFile**](AssetApi.md#servefile) | **GET** /asset/file/{id} | 
 | 
					[**serveFile**](AssetApi.md#servefile) | **GET** /asset/file/{id} | 
 | 
				
			||||||
[**updateAsset**](AssetApi.md#updateasset) | **PUT** /asset/{id} | 
 | 
					[**updateAsset**](AssetApi.md#updateasset) | **PUT** /asset/{id} | 
 | 
				
			||||||
@@ -1192,6 +1193,60 @@ 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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# **runAssetJobs**
 | 
				
			||||||
 | 
					> runAssetJobs(assetJobsDto)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Example
 | 
				
			||||||
 | 
					```dart
 | 
				
			||||||
 | 
					import 'package:openapi/api.dart';
 | 
				
			||||||
 | 
					// TODO Configure API key authorization: cookie
 | 
				
			||||||
 | 
					//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKey = 'YOUR_API_KEY';
 | 
				
			||||||
 | 
					// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
 | 
				
			||||||
 | 
					//defaultApiClient.getAuthentication<ApiKeyAuth>('cookie').apiKeyPrefix = 'Bearer';
 | 
				
			||||||
 | 
					// TODO Configure API key authorization: api_key
 | 
				
			||||||
 | 
					//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKey = 'YOUR_API_KEY';
 | 
				
			||||||
 | 
					// uncomment below to setup prefix (e.g. Bearer) for API key, if needed
 | 
				
			||||||
 | 
					//defaultApiClient.getAuthentication<ApiKeyAuth>('api_key').apiKeyPrefix = 'Bearer';
 | 
				
			||||||
 | 
					// 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();
 | 
				
			||||||
 | 
					final assetJobsDto = AssetJobsDto(); // AssetJobsDto | 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					try {
 | 
				
			||||||
 | 
					    api_instance.runAssetJobs(assetJobsDto);
 | 
				
			||||||
 | 
					} catch (e) {
 | 
				
			||||||
 | 
					    print('Exception when calling AssetApi->runAssetJobs: $e\n');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Parameters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Name | Type | Description  | Notes
 | 
				
			||||||
 | 
					------------- | ------------- | ------------- | -------------
 | 
				
			||||||
 | 
					 **assetJobsDto** | [**AssetJobsDto**](AssetJobsDto.md)|  | 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Return type
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void (empty response body)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Authorization
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### HTTP request headers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 - **Content-Type**: application/json
 | 
				
			||||||
 | 
					 - **Accept**: Not defined
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# **searchAsset**
 | 
					# **searchAsset**
 | 
				
			||||||
> List<AssetResponseDto> searchAsset(searchAssetDto)
 | 
					> List<AssetResponseDto> searchAsset(searchAssetDto)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								mobile/openapi/doc/AssetJobName.md
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								mobile/openapi/doc/AssetJobName.md
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					# openapi.model.AssetJobName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Load the model package
 | 
				
			||||||
 | 
					```dart
 | 
				
			||||||
 | 
					import 'package:openapi/api.dart';
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Properties
 | 
				
			||||||
 | 
					Name | Type | Description | Notes
 | 
				
			||||||
 | 
					------------ | ------------- | ------------- | -------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[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
									
								
								mobile/openapi/doc/AssetJobsDto.md
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								mobile/openapi/doc/AssetJobsDto.md
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					# openapi.model.AssetJobsDto
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Load the model package
 | 
				
			||||||
 | 
					```dart
 | 
				
			||||||
 | 
					import 'package:openapi/api.dart';
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Properties
 | 
				
			||||||
 | 
					Name | Type | Description | Notes
 | 
				
			||||||
 | 
					------------ | ------------- | ------------- | -------------
 | 
				
			||||||
 | 
					**assetIds** | **List<String>** |  | [default to const []]
 | 
				
			||||||
 | 
					**name** | [**AssetJobName**](AssetJobName.md) |  | 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								mobile/openapi/lib/api.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								mobile/openapi/lib/api.dart
									
									
									
										generated
									
									
									
								
							@@ -60,6 +60,8 @@ part 'model/asset_bulk_upload_check_result.dart';
 | 
				
			|||||||
part 'model/asset_file_upload_response_dto.dart';
 | 
					part 'model/asset_file_upload_response_dto.dart';
 | 
				
			||||||
part 'model/asset_ids_dto.dart';
 | 
					part 'model/asset_ids_dto.dart';
 | 
				
			||||||
part 'model/asset_ids_response_dto.dart';
 | 
					part 'model/asset_ids_response_dto.dart';
 | 
				
			||||||
 | 
					part 'model/asset_job_name.dart';
 | 
				
			||||||
 | 
					part 'model/asset_jobs_dto.dart';
 | 
				
			||||||
part 'model/asset_response_dto.dart';
 | 
					part 'model/asset_response_dto.dart';
 | 
				
			||||||
part 'model/asset_stats_response_dto.dart';
 | 
					part 'model/asset_stats_response_dto.dart';
 | 
				
			||||||
part 'model/asset_type_enum.dart';
 | 
					part 'model/asset_type_enum.dart';
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										39
									
								
								mobile/openapi/lib/api/asset_api.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										39
									
								
								mobile/openapi/lib/api/asset_api.dart
									
									
									
										generated
									
									
									
								
							@@ -1227,6 +1227,45 @@ class AssetApi {
 | 
				
			|||||||
    return null;
 | 
					    return null;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Performs an HTTP 'POST /asset/jobs' operation and returns the [Response].
 | 
				
			||||||
 | 
					  /// Parameters:
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// * [AssetJobsDto] assetJobsDto (required):
 | 
				
			||||||
 | 
					  Future<Response> runAssetJobsWithHttpInfo(AssetJobsDto assetJobsDto,) async {
 | 
				
			||||||
 | 
					    // ignore: prefer_const_declarations
 | 
				
			||||||
 | 
					    final path = r'/asset/jobs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ignore: prefer_final_locals
 | 
				
			||||||
 | 
					    Object? postBody = assetJobsDto;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    final queryParams = <QueryParam>[];
 | 
				
			||||||
 | 
					    final headerParams = <String, String>{};
 | 
				
			||||||
 | 
					    final formParams = <String, String>{};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const contentTypes = <String>['application/json'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return apiClient.invokeAPI(
 | 
				
			||||||
 | 
					      path,
 | 
				
			||||||
 | 
					      'POST',
 | 
				
			||||||
 | 
					      queryParams,
 | 
				
			||||||
 | 
					      postBody,
 | 
				
			||||||
 | 
					      headerParams,
 | 
				
			||||||
 | 
					      formParams,
 | 
				
			||||||
 | 
					      contentTypes.isEmpty ? null : contentTypes.first,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Parameters:
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// * [AssetJobsDto] assetJobsDto (required):
 | 
				
			||||||
 | 
					  Future<void> runAssetJobs(AssetJobsDto assetJobsDto,) async {
 | 
				
			||||||
 | 
					    final response = await runAssetJobsWithHttpInfo(assetJobsDto,);
 | 
				
			||||||
 | 
					    if (response.statusCode >= HttpStatus.badRequest) {
 | 
				
			||||||
 | 
					      throw ApiException(response.statusCode, await _decodeBodyBytes(response));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /// Performs an HTTP 'POST /asset/search' operation and returns the [Response].
 | 
					  /// Performs an HTTP 'POST /asset/search' operation and returns the [Response].
 | 
				
			||||||
  /// Parameters:
 | 
					  /// Parameters:
 | 
				
			||||||
  ///
 | 
					  ///
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								mobile/openapi/lib/api_client.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								mobile/openapi/lib/api_client.dart
									
									
									
										generated
									
									
									
								
							@@ -215,6 +215,10 @@ class ApiClient {
 | 
				
			|||||||
          return AssetIdsDto.fromJson(value);
 | 
					          return AssetIdsDto.fromJson(value);
 | 
				
			||||||
        case 'AssetIdsResponseDto':
 | 
					        case 'AssetIdsResponseDto':
 | 
				
			||||||
          return AssetIdsResponseDto.fromJson(value);
 | 
					          return AssetIdsResponseDto.fromJson(value);
 | 
				
			||||||
 | 
					        case 'AssetJobName':
 | 
				
			||||||
 | 
					          return AssetJobNameTypeTransformer().decode(value);
 | 
				
			||||||
 | 
					        case 'AssetJobsDto':
 | 
				
			||||||
 | 
					          return AssetJobsDto.fromJson(value);
 | 
				
			||||||
        case 'AssetResponseDto':
 | 
					        case 'AssetResponseDto':
 | 
				
			||||||
          return AssetResponseDto.fromJson(value);
 | 
					          return AssetResponseDto.fromJson(value);
 | 
				
			||||||
        case 'AssetStatsResponseDto':
 | 
					        case 'AssetStatsResponseDto':
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								mobile/openapi/lib/api_helper.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3
									
								
								mobile/openapi/lib/api_helper.dart
									
									
									
										generated
									
									
									
								
							@@ -55,6 +55,9 @@ String parameterToString(dynamic value) {
 | 
				
			|||||||
  if (value is DateTime) {
 | 
					  if (value is DateTime) {
 | 
				
			||||||
    return value.toUtc().toIso8601String();
 | 
					    return value.toUtc().toIso8601String();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  if (value is AssetJobName) {
 | 
				
			||||||
 | 
					    return AssetJobNameTypeTransformer().encode(value).toString();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  if (value is AssetTypeEnum) {
 | 
					  if (value is AssetTypeEnum) {
 | 
				
			||||||
    return AssetTypeEnumTypeTransformer().encode(value).toString();
 | 
					    return AssetTypeEnumTypeTransformer().encode(value).toString();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										88
									
								
								mobile/openapi/lib/model/asset_job_name.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								mobile/openapi/lib/model/asset_job_name.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// 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 AssetJobName {
 | 
				
			||||||
 | 
					  /// Instantiate a new enum with the provided [value].
 | 
				
			||||||
 | 
					  const AssetJobName._(this.value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// The underlying value of this enum member.
 | 
				
			||||||
 | 
					  final String value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() => value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  String toJson() => value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static const regenerateThumbnail = AssetJobName._(r'regenerate-thumbnail');
 | 
				
			||||||
 | 
					  static const refreshMetadata = AssetJobName._(r'refresh-metadata');
 | 
				
			||||||
 | 
					  static const transcodeVideo = AssetJobName._(r'transcode-video');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// List of all possible values in this [enum][AssetJobName].
 | 
				
			||||||
 | 
					  static const values = <AssetJobName>[
 | 
				
			||||||
 | 
					    regenerateThumbnail,
 | 
				
			||||||
 | 
					    refreshMetadata,
 | 
				
			||||||
 | 
					    transcodeVideo,
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static AssetJobName? fromJson(dynamic value) => AssetJobNameTypeTransformer().decode(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static List<AssetJobName>? listFromJson(dynamic json, {bool growable = false,}) {
 | 
				
			||||||
 | 
					    final result = <AssetJobName>[];
 | 
				
			||||||
 | 
					    if (json is List && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      for (final row in json) {
 | 
				
			||||||
 | 
					        final value = AssetJobName.fromJson(row);
 | 
				
			||||||
 | 
					        if (value != null) {
 | 
				
			||||||
 | 
					          result.add(value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result.toList(growable: growable);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Transformation class that can [encode] an instance of [AssetJobName] to String,
 | 
				
			||||||
 | 
					/// and [decode] dynamic data back to [AssetJobName].
 | 
				
			||||||
 | 
					class AssetJobNameTypeTransformer {
 | 
				
			||||||
 | 
					  factory AssetJobNameTypeTransformer() => _instance ??= const AssetJobNameTypeTransformer._();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const AssetJobNameTypeTransformer._();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  String encode(AssetJobName data) => data.value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Decodes a [dynamic value][data] to a AssetJobName.
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// If [allowNull] is true and the [dynamic value][data] cannot be decoded successfully,
 | 
				
			||||||
 | 
					  /// then null is returned. However, if [allowNull] is false and the [dynamic value][data]
 | 
				
			||||||
 | 
					  /// cannot be decoded successfully, then an [UnimplementedError] is thrown.
 | 
				
			||||||
 | 
					  ///
 | 
				
			||||||
 | 
					  /// The [allowNull] is very handy when an API changes and a new enum value is added or removed,
 | 
				
			||||||
 | 
					  /// and users are still using an old app with the old code.
 | 
				
			||||||
 | 
					  AssetJobName? decode(dynamic data, {bool allowNull = true}) {
 | 
				
			||||||
 | 
					    if (data != null) {
 | 
				
			||||||
 | 
					      switch (data) {
 | 
				
			||||||
 | 
					        case r'regenerate-thumbnail': return AssetJobName.regenerateThumbnail;
 | 
				
			||||||
 | 
					        case r'refresh-metadata': return AssetJobName.refreshMetadata;
 | 
				
			||||||
 | 
					        case r'transcode-video': return AssetJobName.transcodeVideo;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					          if (!allowNull) {
 | 
				
			||||||
 | 
					            throw ArgumentError('Unknown enum value to decode: $data');
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Singleton [AssetJobNameTypeTransformer] instance.
 | 
				
			||||||
 | 
					  static AssetJobNameTypeTransformer? _instance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										108
									
								
								mobile/openapi/lib/model/asset_jobs_dto.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								mobile/openapi/lib/model/asset_jobs_dto.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,108 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// 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 AssetJobsDto {
 | 
				
			||||||
 | 
					  /// Returns a new [AssetJobsDto] instance.
 | 
				
			||||||
 | 
					  AssetJobsDto({
 | 
				
			||||||
 | 
					    this.assetIds = const [],
 | 
				
			||||||
 | 
					    required this.name,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  List<String> assetIds;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  AssetJobName name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  bool operator ==(Object other) => identical(this, other) || other is AssetJobsDto &&
 | 
				
			||||||
 | 
					     other.assetIds == assetIds &&
 | 
				
			||||||
 | 
					     other.name == name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  int get hashCode =>
 | 
				
			||||||
 | 
					    // ignore: unnecessary_parenthesis
 | 
				
			||||||
 | 
					    (assetIds.hashCode) +
 | 
				
			||||||
 | 
					    (name.hashCode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() => 'AssetJobsDto[assetIds=$assetIds, name=$name]';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Map<String, dynamic> toJson() {
 | 
				
			||||||
 | 
					    final json = <String, dynamic>{};
 | 
				
			||||||
 | 
					      json[r'assetIds'] = this.assetIds;
 | 
				
			||||||
 | 
					      json[r'name'] = this.name;
 | 
				
			||||||
 | 
					    return json;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// Returns a new [AssetJobsDto] instance and imports its values from
 | 
				
			||||||
 | 
					  /// [value] if it's a [Map], null otherwise.
 | 
				
			||||||
 | 
					  // ignore: prefer_constructors_over_static_methods
 | 
				
			||||||
 | 
					  static AssetJobsDto? fromJson(dynamic value) {
 | 
				
			||||||
 | 
					    if (value is Map) {
 | 
				
			||||||
 | 
					      final json = value.cast<String, dynamic>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return AssetJobsDto(
 | 
				
			||||||
 | 
					        assetIds: json[r'assetIds'] is List
 | 
				
			||||||
 | 
					            ? (json[r'assetIds'] as List).cast<String>()
 | 
				
			||||||
 | 
					            : const [],
 | 
				
			||||||
 | 
					        name: AssetJobName.fromJson(json[r'name'])!,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static List<AssetJobsDto> listFromJson(dynamic json, {bool growable = false,}) {
 | 
				
			||||||
 | 
					    final result = <AssetJobsDto>[];
 | 
				
			||||||
 | 
					    if (json is List && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      for (final row in json) {
 | 
				
			||||||
 | 
					        final value = AssetJobsDto.fromJson(row);
 | 
				
			||||||
 | 
					        if (value != null) {
 | 
				
			||||||
 | 
					          result.add(value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result.toList(growable: growable);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static Map<String, AssetJobsDto> mapFromJson(dynamic json) {
 | 
				
			||||||
 | 
					    final map = <String, AssetJobsDto>{};
 | 
				
			||||||
 | 
					    if (json is Map && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      json = json.cast<String, dynamic>(); // ignore: parameter_assignments
 | 
				
			||||||
 | 
					      for (final entry in json.entries) {
 | 
				
			||||||
 | 
					        final value = AssetJobsDto.fromJson(entry.value);
 | 
				
			||||||
 | 
					        if (value != null) {
 | 
				
			||||||
 | 
					          map[entry.key] = value;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // maps a json object with a list of AssetJobsDto-objects as value to a dart map
 | 
				
			||||||
 | 
					  static Map<String, List<AssetJobsDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
 | 
				
			||||||
 | 
					    final map = <String, List<AssetJobsDto>>{};
 | 
				
			||||||
 | 
					    if (json is Map && json.isNotEmpty) {
 | 
				
			||||||
 | 
					      // ignore: parameter_assignments
 | 
				
			||||||
 | 
					      json = json.cast<String, dynamic>();
 | 
				
			||||||
 | 
					      for (final entry in json.entries) {
 | 
				
			||||||
 | 
					        map[entry.key] = AssetJobsDto.listFromJson(entry.value, growable: growable,);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return map;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /// The list of required keys that must be present in a JSON.
 | 
				
			||||||
 | 
					  static const requiredKeys = <String>{
 | 
				
			||||||
 | 
					    'assetIds',
 | 
				
			||||||
 | 
					    'name',
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										5
									
								
								mobile/openapi/test/asset_api_test.dart
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								mobile/openapi/test/asset_api_test.dart
									
									
									
										generated
									
									
									
								
							@@ -129,6 +129,11 @@ void main() {
 | 
				
			|||||||
      // TODO
 | 
					      // TODO
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Future runAssetJobs(AssetJobsDto assetJobsDto) async
 | 
				
			||||||
 | 
					    test('test runAssetJobs', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Future<List<AssetResponseDto>> searchAsset(SearchAssetDto searchAssetDto) async
 | 
					    //Future<List<AssetResponseDto>> searchAsset(SearchAssetDto searchAssetDto) async
 | 
				
			||||||
    test('test searchAsset', () async {
 | 
					    test('test searchAsset', () async {
 | 
				
			||||||
      // TODO
 | 
					      // TODO
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										21
									
								
								mobile/openapi/test/asset_job_name_test.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								mobile/openapi/test/asset_job_name_test.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// 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 AssetJobName
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  group('test AssetJobName', () {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								mobile/openapi/test/asset_jobs_dto_test.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								mobile/openapi/test/asset_jobs_dto_test.dart
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -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 AssetJobsDto
 | 
				
			||||||
 | 
					void main() {
 | 
				
			||||||
 | 
					  // final instance = AssetJobsDto();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  group('test AssetJobsDto', () {
 | 
				
			||||||
 | 
					    // List<String> assetIds (default value: const [])
 | 
				
			||||||
 | 
					    test('to test the property `assetIds`', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // AssetJobName name
 | 
				
			||||||
 | 
					    test('to test the property `name`', () async {
 | 
				
			||||||
 | 
					      // TODO
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1367,6 +1367,41 @@
 | 
				
			|||||||
        ]
 | 
					        ]
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "/asset/jobs": {
 | 
				
			||||||
 | 
					      "post": {
 | 
				
			||||||
 | 
					        "operationId": "runAssetJobs",
 | 
				
			||||||
 | 
					        "parameters": [],
 | 
				
			||||||
 | 
					        "requestBody": {
 | 
				
			||||||
 | 
					          "content": {
 | 
				
			||||||
 | 
					            "application/json": {
 | 
				
			||||||
 | 
					              "schema": {
 | 
				
			||||||
 | 
					                "$ref": "#/components/schemas/AssetJobsDto"
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "required": true
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "responses": {
 | 
				
			||||||
 | 
					          "204": {
 | 
				
			||||||
 | 
					            "description": ""
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "security": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "bearer": []
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "cookie": []
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "api_key": []
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "tags": [
 | 
				
			||||||
 | 
					          "Asset"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "/asset/map-marker": {
 | 
					    "/asset/map-marker": {
 | 
				
			||||||
      "get": {
 | 
					      "get": {
 | 
				
			||||||
        "operationId": "getMapMarkers",
 | 
					        "operationId": "getMapMarkers",
 | 
				
			||||||
@@ -5042,6 +5077,33 @@
 | 
				
			|||||||
        ],
 | 
					        ],
 | 
				
			||||||
        "type": "object"
 | 
					        "type": "object"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
 | 
					      "AssetJobName": {
 | 
				
			||||||
 | 
					        "enum": [
 | 
				
			||||||
 | 
					          "regenerate-thumbnail",
 | 
				
			||||||
 | 
					          "refresh-metadata",
 | 
				
			||||||
 | 
					          "transcode-video"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "type": "string"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "AssetJobsDto": {
 | 
				
			||||||
 | 
					        "properties": {
 | 
				
			||||||
 | 
					          "assetIds": {
 | 
				
			||||||
 | 
					            "items": {
 | 
				
			||||||
 | 
					              "format": "uuid",
 | 
				
			||||||
 | 
					              "type": "string"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "type": "array"
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          "name": {
 | 
				
			||||||
 | 
					            "$ref": "#/components/schemas/AssetJobName"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "required": [
 | 
				
			||||||
 | 
					          "assetIds",
 | 
				
			||||||
 | 
					          "name"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "type": "object"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
      "AssetResponseDto": {
 | 
					      "AssetResponseDto": {
 | 
				
			||||||
        "properties": {
 | 
					        "properties": {
 | 
				
			||||||
          "checksum": {
 | 
					          "checksum": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,15 +7,17 @@ import {
 | 
				
			|||||||
  newAccessRepositoryMock,
 | 
					  newAccessRepositoryMock,
 | 
				
			||||||
  newAssetRepositoryMock,
 | 
					  newAssetRepositoryMock,
 | 
				
			||||||
  newCryptoRepositoryMock,
 | 
					  newCryptoRepositoryMock,
 | 
				
			||||||
 | 
					  newJobRepositoryMock,
 | 
				
			||||||
  newStorageRepositoryMock,
 | 
					  newStorageRepositoryMock,
 | 
				
			||||||
} from '@test';
 | 
					} from '@test';
 | 
				
			||||||
import { when } from 'jest-when';
 | 
					import { when } from 'jest-when';
 | 
				
			||||||
import { Readable } from 'stream';
 | 
					import { Readable } from 'stream';
 | 
				
			||||||
import { ICryptoRepository } from '../crypto';
 | 
					import { ICryptoRepository } from '../crypto';
 | 
				
			||||||
 | 
					import { IJobRepository, JobName } from '../index';
 | 
				
			||||||
import { IStorageRepository } from '../storage';
 | 
					import { IStorageRepository } from '../storage';
 | 
				
			||||||
import { AssetStats, IAssetRepository } from './asset.repository';
 | 
					import { AssetStats, IAssetRepository } from './asset.repository';
 | 
				
			||||||
import { AssetService, UploadFieldName } from './asset.service';
 | 
					import { AssetService, UploadFieldName } from './asset.service';
 | 
				
			||||||
import { AssetStatsResponseDto, DownloadResponseDto } from './dto';
 | 
					import { AssetJobName, AssetStatsResponseDto, DownloadResponseDto } from './dto';
 | 
				
			||||||
import { mapAsset } from './response-dto';
 | 
					import { mapAsset } from './response-dto';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const downloadResponse: DownloadResponseDto = {
 | 
					const downloadResponse: DownloadResponseDto = {
 | 
				
			||||||
@@ -145,6 +147,7 @@ describe(AssetService.name, () => {
 | 
				
			|||||||
  let accessMock: IAccessRepositoryMock;
 | 
					  let accessMock: IAccessRepositoryMock;
 | 
				
			||||||
  let assetMock: jest.Mocked<IAssetRepository>;
 | 
					  let assetMock: jest.Mocked<IAssetRepository>;
 | 
				
			||||||
  let cryptoMock: jest.Mocked<ICryptoRepository>;
 | 
					  let cryptoMock: jest.Mocked<ICryptoRepository>;
 | 
				
			||||||
 | 
					  let jobMock: jest.Mocked<IJobRepository>;
 | 
				
			||||||
  let storageMock: jest.Mocked<IStorageRepository>;
 | 
					  let storageMock: jest.Mocked<IStorageRepository>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  it('should work', () => {
 | 
					  it('should work', () => {
 | 
				
			||||||
@@ -155,8 +158,9 @@ describe(AssetService.name, () => {
 | 
				
			|||||||
    accessMock = newAccessRepositoryMock();
 | 
					    accessMock = newAccessRepositoryMock();
 | 
				
			||||||
    assetMock = newAssetRepositoryMock();
 | 
					    assetMock = newAssetRepositoryMock();
 | 
				
			||||||
    cryptoMock = newCryptoRepositoryMock();
 | 
					    cryptoMock = newCryptoRepositoryMock();
 | 
				
			||||||
 | 
					    jobMock = newJobRepositoryMock();
 | 
				
			||||||
    storageMock = newStorageRepositoryMock();
 | 
					    storageMock = newStorageRepositoryMock();
 | 
				
			||||||
    sut = new AssetService(accessMock, assetMock, cryptoMock, storageMock);
 | 
					    sut = new AssetService(accessMock, assetMock, cryptoMock, jobMock, storageMock);
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe('canUpload', () => {
 | 
					  describe('canUpload', () => {
 | 
				
			||||||
@@ -532,4 +536,24 @@ describe(AssetService.name, () => {
 | 
				
			|||||||
      expect(assetMock.updateAll).toHaveBeenCalledWith(['asset-1', 'asset-2'], { isArchived: true });
 | 
					      expect(assetMock.updateAll).toHaveBeenCalledWith(['asset-1', 'asset-2'], { isArchived: true });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  describe('run', () => {
 | 
				
			||||||
 | 
					    it('should run the refresh metadata job', async () => {
 | 
				
			||||||
 | 
					      accessMock.asset.hasOwnerAccess.mockResolvedValue(true);
 | 
				
			||||||
 | 
					      await sut.run(authStub.admin, { assetIds: ['asset-1'], name: AssetJobName.REFRESH_METADATA }),
 | 
				
			||||||
 | 
					        expect(jobMock.queue).toHaveBeenCalledWith({ name: JobName.METADATA_EXTRACTION, data: { id: 'asset-1' } });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('should run the refresh thumbnails job', async () => {
 | 
				
			||||||
 | 
					      accessMock.asset.hasOwnerAccess.mockResolvedValue(true);
 | 
				
			||||||
 | 
					      await sut.run(authStub.admin, { assetIds: ['asset-1'], name: AssetJobName.REGENERATE_THUMBNAIL }),
 | 
				
			||||||
 | 
					        expect(jobMock.queue).toHaveBeenCalledWith({ name: JobName.GENERATE_JPEG_THUMBNAIL, data: { id: 'asset-1' } });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    it('should run the transcode video', async () => {
 | 
				
			||||||
 | 
					      accessMock.asset.hasOwnerAccess.mockResolvedValue(true);
 | 
				
			||||||
 | 
					      await sut.run(authStub.admin, { assetIds: ['asset-1'], name: AssetJobName.TRANSCODE_VIDEO }),
 | 
				
			||||||
 | 
					        expect(jobMock.queue).toHaveBeenCalledWith({ name: JobName.VIDEO_CONVERSION, data: { id: 'asset-1' } });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,11 +8,14 @@ import { AuthUserDto } from '../auth';
 | 
				
			|||||||
import { ICryptoRepository } from '../crypto';
 | 
					import { ICryptoRepository } from '../crypto';
 | 
				
			||||||
import { mimeTypes } from '../domain.constant';
 | 
					import { mimeTypes } from '../domain.constant';
 | 
				
			||||||
import { HumanReadableSize, usePagination } from '../domain.util';
 | 
					import { HumanReadableSize, usePagination } from '../domain.util';
 | 
				
			||||||
 | 
					import { IJobRepository, JobName } from '../job';
 | 
				
			||||||
import { ImmichReadStream, IStorageRepository, StorageCore, StorageFolder } from '../storage';
 | 
					import { ImmichReadStream, IStorageRepository, StorageCore, StorageFolder } from '../storage';
 | 
				
			||||||
import { IAssetRepository } from './asset.repository';
 | 
					import { IAssetRepository } from './asset.repository';
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  AssetBulkUpdateDto,
 | 
					  AssetBulkUpdateDto,
 | 
				
			||||||
  AssetIdsDto,
 | 
					  AssetIdsDto,
 | 
				
			||||||
 | 
					  AssetJobName,
 | 
				
			||||||
 | 
					  AssetJobsDto,
 | 
				
			||||||
  DownloadArchiveInfo,
 | 
					  DownloadArchiveInfo,
 | 
				
			||||||
  DownloadInfoDto,
 | 
					  DownloadInfoDto,
 | 
				
			||||||
  DownloadResponseDto,
 | 
					  DownloadResponseDto,
 | 
				
			||||||
@@ -54,6 +57,7 @@ export class AssetService {
 | 
				
			|||||||
    @Inject(IAccessRepository) accessRepository: IAccessRepository,
 | 
					    @Inject(IAccessRepository) accessRepository: IAccessRepository,
 | 
				
			||||||
    @Inject(IAssetRepository) private assetRepository: IAssetRepository,
 | 
					    @Inject(IAssetRepository) private assetRepository: IAssetRepository,
 | 
				
			||||||
    @Inject(ICryptoRepository) private cryptoRepository: ICryptoRepository,
 | 
					    @Inject(ICryptoRepository) private cryptoRepository: ICryptoRepository,
 | 
				
			||||||
 | 
					    @Inject(IJobRepository) private jobRepository: IJobRepository,
 | 
				
			||||||
    @Inject(IStorageRepository) private storageRepository: IStorageRepository,
 | 
					    @Inject(IStorageRepository) private storageRepository: IStorageRepository,
 | 
				
			||||||
  ) {
 | 
					  ) {
 | 
				
			||||||
    this.access = new AccessCore(accessRepository);
 | 
					    this.access = new AccessCore(accessRepository);
 | 
				
			||||||
@@ -275,4 +279,24 @@ export class AssetService {
 | 
				
			|||||||
    await this.access.requirePermission(authUser, Permission.ASSET_UPDATE, ids);
 | 
					    await this.access.requirePermission(authUser, Permission.ASSET_UPDATE, ids);
 | 
				
			||||||
    await this.assetRepository.updateAll(ids, options);
 | 
					    await this.assetRepository.updateAll(ids, options);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async run(authUser: AuthUserDto, dto: AssetJobsDto) {
 | 
				
			||||||
 | 
					    await this.access.requirePermission(authUser, Permission.ASSET_UPDATE, dto.assetIds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const id of dto.assetIds) {
 | 
				
			||||||
 | 
					      switch (dto.name) {
 | 
				
			||||||
 | 
					        case AssetJobName.REFRESH_METADATA:
 | 
				
			||||||
 | 
					          await this.jobRepository.queue({ name: JobName.METADATA_EXTRACTION, data: { id } });
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case AssetJobName.REGENERATE_THUMBNAIL:
 | 
				
			||||||
 | 
					          await this.jobRepository.queue({ name: JobName.GENERATE_JPEG_THUMBNAIL, data: { id } });
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case AssetJobName.TRANSCODE_VIDEO:
 | 
				
			||||||
 | 
					          await this.jobRepository.queue({ name: JobName.VIDEO_CONVERSION, data: { id } });
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,20 @@
 | 
				
			|||||||
 | 
					import { ApiProperty } from '@nestjs/swagger';
 | 
				
			||||||
 | 
					import { IsEnum } from 'class-validator';
 | 
				
			||||||
import { ValidateUUID } from '../../domain.util';
 | 
					import { ValidateUUID } from '../../domain.util';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class AssetIdsDto {
 | 
					export class AssetIdsDto {
 | 
				
			||||||
  @ValidateUUID({ each: true })
 | 
					  @ValidateUUID({ each: true })
 | 
				
			||||||
  assetIds!: string[];
 | 
					  assetIds!: string[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export enum AssetJobName {
 | 
				
			||||||
 | 
					  REGENERATE_THUMBNAIL = 'regenerate-thumbnail',
 | 
				
			||||||
 | 
					  REFRESH_METADATA = 'refresh-metadata',
 | 
				
			||||||
 | 
					  TRANSCODE_VIDEO = 'transcode-video',
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export class AssetJobsDto extends AssetIdsDto {
 | 
				
			||||||
 | 
					  @ApiProperty({ enumName: 'AssetJobName', enum: AssetJobName })
 | 
				
			||||||
 | 
					  @IsEnum(AssetJobName)
 | 
				
			||||||
 | 
					  name!: AssetJobName;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
import {
 | 
					import {
 | 
				
			||||||
  AssetBulkUpdateDto,
 | 
					  AssetBulkUpdateDto,
 | 
				
			||||||
  AssetIdsDto,
 | 
					  AssetIdsDto,
 | 
				
			||||||
 | 
					  AssetJobsDto,
 | 
				
			||||||
  AssetResponseDto,
 | 
					  AssetResponseDto,
 | 
				
			||||||
  AssetService,
 | 
					  AssetService,
 | 
				
			||||||
  AssetStatsDto,
 | 
					  AssetStatsDto,
 | 
				
			||||||
@@ -78,6 +79,12 @@ export class AssetController {
 | 
				
			|||||||
    return this.service.getByTimeBucket(authUser, dto);
 | 
					    return this.service.getByTimeBucket(authUser, dto);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Post('jobs')
 | 
				
			||||||
 | 
					  @HttpCode(HttpStatus.NO_CONTENT)
 | 
				
			||||||
 | 
					  runAssetJobs(@AuthUser() authUser: AuthUserDto, @Body() dto: AssetJobsDto): Promise<void> {
 | 
				
			||||||
 | 
					    return this.service.run(authUser, dto);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Put()
 | 
					  @Put()
 | 
				
			||||||
  @HttpCode(HttpStatus.NO_CONTENT)
 | 
					  @HttpCode(HttpStatus.NO_CONTENT)
 | 
				
			||||||
  updateAssets(@AuthUser() authUser: AuthUserDto, @Body() dto: AssetBulkUpdateDto): Promise<void> {
 | 
					  updateAssets(@AuthUser() authUser: AuthUserDto, @Body() dto: AssetBulkUpdateDto): Promise<void> {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ import {
 | 
				
			|||||||
  APIKeyApi,
 | 
					  APIKeyApi,
 | 
				
			||||||
  AssetApi,
 | 
					  AssetApi,
 | 
				
			||||||
  AssetApiFp,
 | 
					  AssetApiFp,
 | 
				
			||||||
 | 
					  AssetJobName,
 | 
				
			||||||
  AuthenticationApi,
 | 
					  AuthenticationApi,
 | 
				
			||||||
  Configuration,
 | 
					  Configuration,
 | 
				
			||||||
  ConfigurationParameters,
 | 
					  ConfigurationParameters,
 | 
				
			||||||
@@ -120,6 +121,26 @@ export class ImmichApi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return names[jobName];
 | 
					    return names[jobName];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public getAssetJobName(job: AssetJobName) {
 | 
				
			||||||
 | 
					    const names: Record<AssetJobName, string> = {
 | 
				
			||||||
 | 
					      [AssetJobName.RefreshMetadata]: 'Refresh metadata',
 | 
				
			||||||
 | 
					      [AssetJobName.RegenerateThumbnail]: 'Refresh thumbnails',
 | 
				
			||||||
 | 
					      [AssetJobName.TranscodeVideo]: 'Refresh encoded videos',
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return names[job];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public getAssetJobMessage(job: AssetJobName) {
 | 
				
			||||||
 | 
					    const messages: Record<AssetJobName, string> = {
 | 
				
			||||||
 | 
					      [AssetJobName.RefreshMetadata]: 'Refreshing metadata',
 | 
				
			||||||
 | 
					      [AssetJobName.RegenerateThumbnail]: `Regenerating thumbnails`,
 | 
				
			||||||
 | 
					      [AssetJobName.TranscodeVideo]: `Refreshing encoded video`,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return messages[job];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const api = new ImmichApi({ basePath: '/api' });
 | 
					export const api = new ImmichApi({ basePath: '/api' });
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										124
									
								
								web/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										124
									
								
								web/src/api/open-api/api.ts
									
									
									
										generated
									
									
									
								
							@@ -525,6 +525,42 @@ export const AssetIdsResponseDtoErrorEnum = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export type AssetIdsResponseDtoErrorEnum = typeof AssetIdsResponseDtoErrorEnum[keyof typeof AssetIdsResponseDtoErrorEnum];
 | 
					export type AssetIdsResponseDtoErrorEnum = typeof AssetIdsResponseDtoErrorEnum[keyof typeof AssetIdsResponseDtoErrorEnum];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @enum {string}
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const AssetJobName = {
 | 
				
			||||||
 | 
					    RegenerateThumbnail: 'regenerate-thumbnail',
 | 
				
			||||||
 | 
					    RefreshMetadata: 'refresh-metadata',
 | 
				
			||||||
 | 
					    TranscodeVideo: 'transcode-video'
 | 
				
			||||||
 | 
					} as const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type AssetJobName = typeof AssetJobName[keyof typeof AssetJobName];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface AssetJobsDto
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface AssetJobsDto {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {Array<string>}
 | 
				
			||||||
 | 
					     * @memberof AssetJobsDto
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'assetIds': Array<string>;
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {AssetJobName}
 | 
				
			||||||
 | 
					     * @memberof AssetJobsDto
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    'name': AssetJobName;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * 
 | 
					 * 
 | 
				
			||||||
 * @export
 | 
					 * @export
 | 
				
			||||||
@@ -5784,6 +5820,50 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
 | 
				
			|||||||
                options: localVarRequestOptions,
 | 
					                options: localVarRequestOptions,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {AssetJobsDto} assetJobsDto 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        runAssetJobs: async (assetJobsDto: AssetJobsDto, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
 | 
				
			||||||
 | 
					            // verify required parameter 'assetJobsDto' is not null or undefined
 | 
				
			||||||
 | 
					            assertParamExists('runAssetJobs', 'assetJobsDto', assetJobsDto)
 | 
				
			||||||
 | 
					            const localVarPath = `/asset/jobs`;
 | 
				
			||||||
 | 
					            // 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: 'POST', ...baseOptions, ...options};
 | 
				
			||||||
 | 
					            const localVarHeaderParameter = {} as any;
 | 
				
			||||||
 | 
					            const localVarQueryParameter = {} as any;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication cookie required
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication api_key required
 | 
				
			||||||
 | 
					            await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // authentication bearer required
 | 
				
			||||||
 | 
					            // http bearer authentication required
 | 
				
			||||||
 | 
					            await setBearerAuthToObject(localVarHeaderParameter, configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					            localVarHeaderParameter['Content-Type'] = 'application/json';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            setSearchParams(localVarUrlObj, localVarQueryParameter);
 | 
				
			||||||
 | 
					            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
 | 
				
			||||||
 | 
					            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
 | 
				
			||||||
 | 
					            localVarRequestOptions.data = serializeDataIfNeeded(assetJobsDto, localVarRequestOptions, configuration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                url: toPathString(localVarUrlObj),
 | 
				
			||||||
 | 
					                options: localVarRequestOptions,
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {SearchAssetDto} searchAssetDto 
 | 
					         * @param {SearchAssetDto} searchAssetDto 
 | 
				
			||||||
@@ -6331,6 +6411,16 @@ export const AssetApiFp = function(configuration?: Configuration) {
 | 
				
			|||||||
            const localVarAxiosArgs = await localVarAxiosParamCreator.importFile(importAssetDto, options);
 | 
					            const localVarAxiosArgs = await localVarAxiosParamCreator.importFile(importAssetDto, options);
 | 
				
			||||||
            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
					            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {AssetJobsDto} assetJobsDto 
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        async runAssetJobs(assetJobsDto: AssetJobsDto, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<void>> {
 | 
				
			||||||
 | 
					            const localVarAxiosArgs = await localVarAxiosParamCreator.runAssetJobs(assetJobsDto, options);
 | 
				
			||||||
 | 
					            return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {SearchAssetDto} searchAssetDto 
 | 
					         * @param {SearchAssetDto} searchAssetDto 
 | 
				
			||||||
@@ -6584,6 +6674,15 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
 | 
				
			|||||||
        importFile(requestParameters: AssetApiImportFileRequest, options?: AxiosRequestConfig): AxiosPromise<AssetFileUploadResponseDto> {
 | 
					        importFile(requestParameters: AssetApiImportFileRequest, options?: AxiosRequestConfig): AxiosPromise<AssetFileUploadResponseDto> {
 | 
				
			||||||
            return localVarFp.importFile(requestParameters.importAssetDto, options).then((request) => request(axios, basePath));
 | 
					            return localVarFp.importFile(requestParameters.importAssetDto, options).then((request) => request(axios, basePath));
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * 
 | 
				
			||||||
 | 
					         * @param {AssetApiRunAssetJobsRequest} requestParameters Request parameters.
 | 
				
			||||||
 | 
					         * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					         * @throws {RequiredError}
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        runAssetJobs(requestParameters: AssetApiRunAssetJobsRequest, options?: AxiosRequestConfig): AxiosPromise<void> {
 | 
				
			||||||
 | 
					            return localVarFp.runAssetJobs(requestParameters.assetJobsDto, options).then((request) => request(axios, basePath));
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 
 | 
					         * 
 | 
				
			||||||
         * @param {AssetApiSearchAssetRequest} requestParameters Request parameters.
 | 
					         * @param {AssetApiSearchAssetRequest} requestParameters Request parameters.
 | 
				
			||||||
@@ -7066,6 +7165,20 @@ export interface AssetApiImportFileRequest {
 | 
				
			|||||||
    readonly importAssetDto: ImportAssetDto
 | 
					    readonly importAssetDto: ImportAssetDto
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Request parameters for runAssetJobs operation in AssetApi.
 | 
				
			||||||
 | 
					 * @export
 | 
				
			||||||
 | 
					 * @interface AssetApiRunAssetJobsRequest
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export interface AssetApiRunAssetJobsRequest {
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @type {AssetJobsDto}
 | 
				
			||||||
 | 
					     * @memberof AssetApiRunAssetJobs
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    readonly assetJobsDto: AssetJobsDto
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Request parameters for searchAsset operation in AssetApi.
 | 
					 * Request parameters for searchAsset operation in AssetApi.
 | 
				
			||||||
 * @export
 | 
					 * @export
 | 
				
			||||||
@@ -7472,6 +7585,17 @@ export class AssetApi extends BaseAPI {
 | 
				
			|||||||
        return AssetApiFp(this.configuration).importFile(requestParameters.importAssetDto, options).then((request) => request(this.axios, this.basePath));
 | 
					        return AssetApiFp(this.configuration).importFile(requestParameters.importAssetDto, options).then((request) => request(this.axios, this.basePath));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 
 | 
				
			||||||
 | 
					     * @param {AssetApiRunAssetJobsRequest} requestParameters Request parameters.
 | 
				
			||||||
 | 
					     * @param {*} [options] Override http request option.
 | 
				
			||||||
 | 
					     * @throws {RequiredError}
 | 
				
			||||||
 | 
					     * @memberof AssetApi
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public runAssetJobs(requestParameters: AssetApiRunAssetJobsRequest, options?: AxiosRequestConfig) {
 | 
				
			||||||
 | 
					        return AssetApiFp(this.configuration).runAssetJobs(requestParameters.assetJobsDto, options).then((request) => request(this.axios, this.basePath));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * 
 | 
					     * 
 | 
				
			||||||
     * @param {AssetApiSearchAssetRequest} requestParameters Request parameters.
 | 
					     * @param {AssetApiSearchAssetRequest} requestParameters Request parameters.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
  import { page } from '$app/stores';
 | 
					  import { page } from '$app/stores';
 | 
				
			||||||
  import { clickOutside } from '$lib/utils/click-outside';
 | 
					  import { clickOutside } from '$lib/utils/click-outside';
 | 
				
			||||||
  import type { AssetResponseDto } from '@api';
 | 
					  import { AssetJobName, AssetResponseDto, AssetTypeEnum, api } from '@api';
 | 
				
			||||||
  import { createEventDispatcher } from 'svelte';
 | 
					  import { createEventDispatcher } from 'svelte';
 | 
				
			||||||
  import ArrowLeft from 'svelte-material-icons/ArrowLeft.svelte';
 | 
					  import ArrowLeft from 'svelte-material-icons/ArrowLeft.svelte';
 | 
				
			||||||
  import CloudDownloadOutline from 'svelte-material-icons/CloudDownloadOutline.svelte';
 | 
					  import CloudDownloadOutline from 'svelte-material-icons/CloudDownloadOutline.svelte';
 | 
				
			||||||
@@ -29,7 +29,22 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  const isOwner = asset.ownerId === $page.data.user?.id;
 | 
					  const isOwner = asset.ownerId === $page.data.user?.id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const dispatch = createEventDispatcher();
 | 
					  type MenuItemEvent = 'addToAlbum' | 'addToSharedAlbum' | 'asProfileImage' | 'runJob';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const dispatch = createEventDispatcher<{
 | 
				
			||||||
 | 
					    goBack: void;
 | 
				
			||||||
 | 
					    stopMotionPhoto: void;
 | 
				
			||||||
 | 
					    playMotionPhoto: void;
 | 
				
			||||||
 | 
					    download: void;
 | 
				
			||||||
 | 
					    showDetail: void;
 | 
				
			||||||
 | 
					    favorite: void;
 | 
				
			||||||
 | 
					    delete: void;
 | 
				
			||||||
 | 
					    toggleArchive: void;
 | 
				
			||||||
 | 
					    addToAlbum: void;
 | 
				
			||||||
 | 
					    addToSharedAlbum: void;
 | 
				
			||||||
 | 
					    asProfileImage: void;
 | 
				
			||||||
 | 
					    runJob: AssetJobName;
 | 
				
			||||||
 | 
					  }>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let contextMenuPosition = { x: 0, y: 0 };
 | 
					  let contextMenuPosition = { x: 0, y: 0 };
 | 
				
			||||||
  let isShowAssetOptions = false;
 | 
					  let isShowAssetOptions = false;
 | 
				
			||||||
@@ -39,7 +54,12 @@
 | 
				
			|||||||
    isShowAssetOptions = !isShowAssetOptions;
 | 
					    isShowAssetOptions = !isShowAssetOptions;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const onMenuClick = (eventName: string) => {
 | 
					  const onJobClick = (name: AssetJobName) => {
 | 
				
			||||||
 | 
					    isShowAssetOptions = false;
 | 
				
			||||||
 | 
					    dispatch('runJob', name);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const onMenuClick = (eventName: MenuItemEvent) => {
 | 
				
			||||||
    isShowAssetOptions = false;
 | 
					    isShowAssetOptions = false;
 | 
				
			||||||
    dispatch(eventName);
 | 
					    dispatch(eventName);
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
@@ -114,22 +134,35 @@
 | 
				
			|||||||
    {#if isOwner}
 | 
					    {#if isOwner}
 | 
				
			||||||
      <CircleIconButton isOpacity={true} logo={DeleteOutline} on:click={() => dispatch('delete')} title="Delete" />
 | 
					      <CircleIconButton isOpacity={true} logo={DeleteOutline} on:click={() => dispatch('delete')} title="Delete" />
 | 
				
			||||||
      <div use:clickOutside on:outclick={() => (isShowAssetOptions = false)}>
 | 
					      <div use:clickOutside on:outclick={() => (isShowAssetOptions = false)}>
 | 
				
			||||||
        <CircleIconButton isOpacity={true} logo={DotsVertical} on:click={showOptionsMenu} title="More">
 | 
					        <CircleIconButton isOpacity={true} logo={DotsVertical} on:click={showOptionsMenu} title="More" />
 | 
				
			||||||
          {#if isShowAssetOptions}
 | 
					        {#if isShowAssetOptions}
 | 
				
			||||||
            <ContextMenu {...contextMenuPosition} direction="left">
 | 
					          <ContextMenu {...contextMenuPosition} direction="left">
 | 
				
			||||||
              <MenuOption on:click={() => onMenuClick('addToAlbum')} text="Add to Album" />
 | 
					            <MenuOption on:click={() => onMenuClick('addToAlbum')} text="Add to Album" />
 | 
				
			||||||
              <MenuOption on:click={() => onMenuClick('addToSharedAlbum')} text="Add to Shared Album" />
 | 
					            <MenuOption on:click={() => onMenuClick('addToSharedAlbum')} text="Add to Shared Album" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              {#if isOwner}
 | 
					            {#if isOwner}
 | 
				
			||||||
 | 
					              <MenuOption
 | 
				
			||||||
 | 
					                on:click={() => dispatch('toggleArchive')}
 | 
				
			||||||
 | 
					                text={asset.isArchived ? 'Unarchive' : 'Archive'}
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					              <MenuOption on:click={() => onMenuClick('asProfileImage')} text="As profile picture" />
 | 
				
			||||||
 | 
					              <MenuOption
 | 
				
			||||||
 | 
					                on:click={() => onJobClick(AssetJobName.RefreshMetadata)}
 | 
				
			||||||
 | 
					                text={api.getAssetJobName(AssetJobName.RefreshMetadata)}
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					              <MenuOption
 | 
				
			||||||
 | 
					                on:click={() => onJobClick(AssetJobName.RegenerateThumbnail)}
 | 
				
			||||||
 | 
					                text={api.getAssetJobName(AssetJobName.RegenerateThumbnail)}
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					              {#if asset.type === AssetTypeEnum.Video}
 | 
				
			||||||
                <MenuOption
 | 
					                <MenuOption
 | 
				
			||||||
                  on:click={() => dispatch('toggleArchive')}
 | 
					                  on:click={() => onJobClick(AssetJobName.TranscodeVideo)}
 | 
				
			||||||
                  text={asset.isArchived ? 'Unarchive' : 'Archive'}
 | 
					                  text={api.getAssetJobName(AssetJobName.TranscodeVideo)}
 | 
				
			||||||
                />
 | 
					                />
 | 
				
			||||||
              {/if}
 | 
					              {/if}
 | 
				
			||||||
              <MenuOption on:click={() => onMenuClick('asProfileImage')} text="As profile picture" />
 | 
					            {/if}
 | 
				
			||||||
            </ContextMenu>
 | 
					          </ContextMenu>
 | 
				
			||||||
          {/if}
 | 
					        {/if}
 | 
				
			||||||
        </CircleIconButton>
 | 
					 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    {/if}
 | 
					    {/if}
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
  import { goto } from '$app/navigation';
 | 
					  import { goto } from '$app/navigation';
 | 
				
			||||||
  import { AlbumResponseDto, api, AssetResponseDto, AssetTypeEnum, SharedLinkResponseDto } from '@api';
 | 
					  import { AlbumResponseDto, api, AssetJobName, AssetResponseDto, AssetTypeEnum, SharedLinkResponseDto } from '@api';
 | 
				
			||||||
  import { createEventDispatcher, onDestroy, onMount } from 'svelte';
 | 
					  import { createEventDispatcher, onDestroy, onMount } from 'svelte';
 | 
				
			||||||
  import ChevronLeft from 'svelte-material-icons/ChevronLeft.svelte';
 | 
					  import ChevronLeft from 'svelte-material-icons/ChevronLeft.svelte';
 | 
				
			||||||
  import ChevronRight from 'svelte-material-icons/ChevronRight.svelte';
 | 
					  import ChevronRight from 'svelte-material-icons/ChevronRight.svelte';
 | 
				
			||||||
@@ -245,6 +245,15 @@
 | 
				
			|||||||
        return 'Asset';
 | 
					        return 'Asset';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleRunJob = async (name: AssetJobName) => {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      await api.assetApi.runAssetJobs({ assetJobsDto: { assetIds: [asset.id], name } });
 | 
				
			||||||
 | 
					      notificationController.show({ type: NotificationType.Info, message: api.getAssetJobMessage(name) });
 | 
				
			||||||
 | 
					    } catch (error) {
 | 
				
			||||||
 | 
					      handleError(error, `Unable to submit job`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<section
 | 
					<section
 | 
				
			||||||
@@ -270,6 +279,7 @@
 | 
				
			|||||||
      on:stopMotionPhoto={() => (shouldPlayMotionPhoto = false)}
 | 
					      on:stopMotionPhoto={() => (shouldPlayMotionPhoto = false)}
 | 
				
			||||||
      on:toggleArchive={toggleArchive}
 | 
					      on:toggleArchive={toggleArchive}
 | 
				
			||||||
      on:asProfileImage={() => (isShowProfileImageCrop = true)}
 | 
					      on:asProfileImage={() => (isShowProfileImageCrop = true)}
 | 
				
			||||||
 | 
					      on:runJob={({ detail: job }) => handleRunJob(job)}
 | 
				
			||||||
    />
 | 
					    />
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					<script lang="ts">
 | 
				
			||||||
 | 
					  import MenuOption from '$lib/components/shared-components/context-menu/menu-option.svelte';
 | 
				
			||||||
 | 
					  import {
 | 
				
			||||||
 | 
					    NotificationType,
 | 
				
			||||||
 | 
					    notificationController,
 | 
				
			||||||
 | 
					  } from '$lib/components/shared-components/notification/notification';
 | 
				
			||||||
 | 
					  import { handleError } from '$lib/utils/handle-error';
 | 
				
			||||||
 | 
					  import { AssetJobName, AssetTypeEnum, api } from '@api';
 | 
				
			||||||
 | 
					  import { getAssetControlContext } from '../asset-select-control-bar.svelte';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  export let jobs: AssetJobName[] = [
 | 
				
			||||||
 | 
					    AssetJobName.RegenerateThumbnail,
 | 
				
			||||||
 | 
					    AssetJobName.RefreshMetadata,
 | 
				
			||||||
 | 
					    AssetJobName.TranscodeVideo,
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const { getAssets, clearSelect } = getAssetControlContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  $: isAllVideos = Array.from(getAssets()).every((asset) => asset.type === AssetTypeEnum.Video);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleRunJob = async (name: AssetJobName) => {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      const ids = Array.from(getAssets()).map(({ id }) => id);
 | 
				
			||||||
 | 
					      await api.assetApi.runAssetJobs({ assetJobsDto: { assetIds: ids, name } });
 | 
				
			||||||
 | 
					      notificationController.show({ message: api.getAssetJobMessage(name), type: NotificationType.Info });
 | 
				
			||||||
 | 
					      clearSelect();
 | 
				
			||||||
 | 
					    } catch (error) {
 | 
				
			||||||
 | 
					      handleError(error, 'Unable to submit job');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{#each jobs as job}
 | 
				
			||||||
 | 
					  {#if isAllVideos || job !== AssetJobName.TranscodeVideo}
 | 
				
			||||||
 | 
					    <MenuOption text={api.getAssetJobName(job)} on:click={() => handleRunJob(job)} />
 | 
				
			||||||
 | 
					  {/if}
 | 
				
			||||||
 | 
					{/each}
 | 
				
			||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
  import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
 | 
					  import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte';
 | 
				
			||||||
  import AddToAlbum from '$lib/components/photos-page/actions/add-to-album.svelte';
 | 
					  import AddToAlbum from '$lib/components/photos-page/actions/add-to-album.svelte';
 | 
				
			||||||
  import ArchiveAction from '$lib/components/photos-page/actions/archive-action.svelte';
 | 
					  import ArchiveAction from '$lib/components/photos-page/actions/archive-action.svelte';
 | 
				
			||||||
 | 
					  import AssetJobActions from '$lib/components/photos-page/actions/asset-job-actions.svelte';
 | 
				
			||||||
  import CreateSharedLink from '$lib/components/photos-page/actions/create-shared-link.svelte';
 | 
					  import CreateSharedLink from '$lib/components/photos-page/actions/create-shared-link.svelte';
 | 
				
			||||||
  import DeleteAssets from '$lib/components/photos-page/actions/delete-assets.svelte';
 | 
					  import DeleteAssets from '$lib/components/photos-page/actions/delete-assets.svelte';
 | 
				
			||||||
  import DownloadAction from '$lib/components/photos-page/actions/download-action.svelte';
 | 
					  import DownloadAction from '$lib/components/photos-page/actions/download-action.svelte';
 | 
				
			||||||
@@ -52,6 +53,7 @@
 | 
				
			|||||||
          <FavoriteAction menuItem removeFavorite={isAllFavorite} />
 | 
					          <FavoriteAction menuItem removeFavorite={isAllFavorite} />
 | 
				
			||||||
          <DownloadAction menuItem />
 | 
					          <DownloadAction menuItem />
 | 
				
			||||||
          <ArchiveAction menuItem onArchive={(ids) => assetStore.removeAssets(ids)} />
 | 
					          <ArchiveAction menuItem onArchive={(ids) => assetStore.removeAssets(ids)} />
 | 
				
			||||||
 | 
					          <AssetJobActions />
 | 
				
			||||||
        </AssetSelectContextMenu>
 | 
					        </AssetSelectContextMenu>
 | 
				
			||||||
      </AssetSelectControlBar>
 | 
					      </AssetSelectControlBar>
 | 
				
			||||||
    {/if}
 | 
					    {/if}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user