11import { Component , Inject , OnInit } from '@angular/core' ;
2- import { HttpDataAddress , DataAddress , AssetInput } from '@think-it-labs/edc-connector-client' ;
3- import { MatDialogRef } from "@angular/material/dialog" ;
2+ import { HttpDataAddress , DataAddress } from '@think-it-labs/edc-connector-client' ;
43import { JsonDoc } from "../../../shared/models/json-doc" ;
54import { StorageType } from "../../../shared/models/storage-type" ;
65import { AmazonS3DataAddress } from "../../../shared/models/amazon-s3-data-address" ;
@@ -89,7 +88,7 @@ export class AssetCreateComponent implements OnInit {
8988 type : 'InesDataStore'
9089 } ;
9190
92- assetType :any ;
91+ assetType : any ;
9392 assetTypes = Object . entries ( ASSET_TYPES ) ;
9493 defaultForms : JsonFormData [ ]
9594 selectedForms : JsonFormData [ ]
@@ -101,7 +100,7 @@ export class AssetCreateComponent implements OnInit {
101100 config = CKEDITOR_CONFIG
102101 selectedAssetTypeVocabularies : Vocabulary [ ]
103102
104- urlPattern : RegExp = / ^ ( f i l e | f t p | h t t p | h t t p s | i m a p | i r c | n n t p | a c a p | i c a p | m t q p | w s s ) : \/ \/ ( l o c a l h o s t | ( [ a - z \d ] ( [ a - z \d - ] * [ a - z \d ] ) * ) | ( ( [ a - z \d ] ( [ a - z \d - ] * [ a - z \d ] ) * ) \. ) + [ a - z ] { 2 , } | ( ( \d { 1 , 3 } \. ) { 3 } \d { 1 , 3 } ) ) ( : \d + ) ? ( \/ [ - a - z \d % _ . ~ + ] * ) * ( \? [ ; & a - z \d % _ . ~ + = - ] * ) ? ( \# [ - a - z \d _ ] * ) ? $ / i ;
103+ urlPattern : RegExp = / ^ h t t p s ? : \/ \/ ( w w w \. ) ? [ - a - z A - Z 0 - 9 @ : % . _ + ~ # = ] { 1 , 256 } \. [ a - z A - Z ] { 2 , 6 } \b ( [ - a - z A - Z 0 - 9 ( ) @ : % _ + . ~ # ? & / / = ] * ) $ / ;
105104
106105 private fetch$ = new BehaviorSubject ( null ) ;
107106
@@ -122,7 +121,7 @@ export class AssetCreateComponent implements OnInit {
122121 }
123122 if ( this . selectedVocabularies ?. length > 0 ) {
124123 this . selectedVocabularies . forEach ( s => {
125- if ( this . selectedAssetTypeVocabularies . find ( satv => satv [ '@id' ] === s [ '@id' ] ) ) {
124+ if ( this . selectedAssetTypeVocabularies . find ( satv => satv [ '@id' ] === s [ '@id' ] ) ) {
126125 this . initVocabularyForm ( s , false )
127126 }
128127 } )
@@ -168,7 +167,7 @@ export class AssetCreateComponent implements OnInit {
168167 const forms : JsonFormData [ ] = [ ...this . defaultForms , ...this . selectedForms ]
169168
170169 let assetDataProperty : any = { }
171- forms . forEach ( async f => {
170+ forms . forEach ( async f => {
172171 if ( f . schema && f . schema . hasOwnProperty ( "@context" ) ) {
173172 // Add context if it is provided in the Json Schema
174173 const jsonSchema : JsonDoc = f . schema as JsonDoc ;
@@ -197,7 +196,7 @@ export class AssetCreateComponent implements OnInit {
197196 dataAddress = this . amazonS3DataAddress ;
198197 } else if ( this . storageTypeId === DATA_ADDRESS_TYPES . httpData ) {
199198 dataAddress = this . httpDataAddress ;
200- } else if ( this . storageTypeId === DATA_ADDRESS_TYPES . inesDataStore ) {
199+ } else if ( this . storageTypeId === DATA_ADDRESS_TYPES . inesDataStore ) {
201200 dataAddress = this . inesDataStoreAddress ;
202201 } else {
203202 this . notificationService . showError ( "Incorrect destination value" ) ;
@@ -213,6 +212,7 @@ export class AssetCreateComponent implements OnInit {
213212 } ;
214213
215214 if ( this . storageTypeId === DATA_ADDRESS_TYPES . inesDataStore && this . inesDataStoreAddress ?. file ) {
215+ this . loadingService . showLoading ( 'Processing the file...' ) ;
216216 const file = this . inesDataStoreAddress ?. file ;
217217
218218 const chunkSize = 1024 * 1024 ;
@@ -229,7 +229,7 @@ export class AssetCreateComponent implements OnInit {
229229 assetInput . blob = new Blob ( chunks ) ;
230230 }
231231
232- this . createAsset ( assetInput )
232+ await this . createAsset ( assetInput )
233233 }
234234 addInfoProperties ( properties : JsonDoc ) {
235235 // Add default information
@@ -245,7 +245,7 @@ export class AssetCreateComponent implements OnInit {
245245 this . addKeywords ( properties ) ;
246246 }
247247
248- addKeywords ( properties : JsonDoc ) {
248+ addKeywords ( properties : JsonDoc ) {
249249 const parsedKeywords : string [ ] = [ ] ;
250250 this . keywords . split ( "," ) . forEach ( keyword => parsedKeywords . push ( keyword . trim ( ) ) ) ;
251251 properties [ "dcat:keyword" ] = parsedKeywords ;
@@ -286,7 +286,7 @@ export class AssetCreateComponent implements OnInit {
286286 if ( ! this . id || ! this . storageTypeId || ! this . name || ! this . version || ! this . description || ! this . keywords || ! this . shortDescription || ! this . assetType ) {
287287 return false ;
288288 } else {
289- if ( this . storageTypeId === DATA_ADDRESS_TYPES . httpData && ( ! this . httpDataAddress . name || ! this . httpDataAddress . baseUrl || ! this . validateUrl ( ) ) ) {
289+ if ( this . storageTypeId === DATA_ADDRESS_TYPES . httpData && ( ! this . httpDataAddress . name || ! this . httpDataAddress . baseUrl || ! this . validateUrl ( ) ) ) {
290290 return false ;
291291 }
292292 if ( this . storageTypeId === DATA_ADDRESS_TYPES . amazonS3 && ! this . amazonS3DataAddress . region ) {
@@ -328,7 +328,7 @@ export class AssetCreateComponent implements OnInit {
328328
329329 if ( this . selectedVocabularies . length > 0 ) {
330330 this . selectedVocabularies . forEach ( s => {
331- if ( this . selectedAssetTypeVocabularies . find ( satv => satv [ '@id' ] === s [ '@id' ] ) ) {
331+ if ( this . selectedAssetTypeVocabularies . find ( satv => satv [ '@id' ] === s [ '@id' ] ) ) {
332332 this . initVocabularyForm ( s , false )
333333 }
334334 } )
@@ -339,24 +339,24 @@ export class AssetCreateComponent implements OnInit {
339339 * Transform to text asset type value
340340 * @returns asset type text
341341 */
342- getAssetTypeText ( ) {
343- return this . assetType ? ASSET_TYPES [ this . assetType as keyof typeof ASSET_TYPES ] : '' ;
342+ getAssetTypeText ( ) {
343+ return this . assetType ? ASSET_TYPES [ this . assetType as keyof typeof ASSET_TYPES ] : '' ;
344344 }
345345
346- setFiles ( event :File [ ] ) {
347- if ( event ?. length > 0 ) {
346+ setFiles ( event : File [ ] ) {
347+ if ( event ?. length > 0 ) {
348348 this . inesDataStoreAddress . file = event [ 0 ]
349- } else {
349+ } else {
350350 delete this . inesDataStoreAddress . file
351351 }
352352 }
353353
354- onSelectionChangeVocabulary ( ) {
354+ onSelectionChangeVocabulary ( ) {
355355 this . selectedForms = [ ]
356356
357357 if ( this . selectedVocabularies . length > 0 ) {
358358 this . selectedVocabularies . forEach ( s => {
359- if ( this . selectedAssetTypeVocabularies . find ( satv => satv [ '@id' ] === s [ '@id' ] ) ) {
359+ if ( this . selectedAssetTypeVocabularies . find ( satv => satv [ '@id' ] === s [ '@id' ] ) ) {
360360 this . initVocabularyForm ( s , false )
361361 }
362362 } )
@@ -366,46 +366,76 @@ export class AssetCreateComponent implements OnInit {
366366 validateUrl ( ) : boolean {
367367 const regex = new RegExp ( this . urlPattern ) ;
368368 return regex . test ( this . httpDataAddress . baseUrl ) ;
369- }
369+ }
370370
371371
372- private createAsset ( asset : AssetInput ) {
373- const newAsset = asset ;
374- if ( newAsset ) {
375- if ( newAsset . dataAddress . type !== DATA_ADDRESS_TYPES . inesDataStore ) {
376- this . assetService . createAsset ( newAsset ) . subscribe ( {
377- next : ( ) => this . fetch$ . next ( null ) ,
378- error : err => this . showError ( err , "This asset cannot be created" ) ,
379- complete : ( ) => {
380- this . navigateToAsset ( )
381- this . notificationService . showInfo ( "Successfully created" ) ;
382- this . loadingService . hideLoading ( ) ;
383- }
384- } )
385- } else {
386- this . assetService . createStorageAsset ( newAsset ) . subscribe ( {
387- next : ( ) => this . fetch$ . next ( null ) ,
388- error : err => this . showError ( err , "This asset cannot be created" ) ,
389- complete : ( ) => {
390- this . navigateToAsset ( )
391- this . notificationService . showInfo ( "Successfully created" ) ;
392- this . loadingService . hideLoading ( ) ;
372+ async createAsset ( assetInput : any ) {
373+ if ( this . storageTypeId === DATA_ADDRESS_TYPES . inesDataStore && this . inesDataStoreAddress . file ) {
374+ const file = this . inesDataStoreAddress . file ;
375+ const chunkSize = 50 * 1024 * 1024 ; // 50 MB
376+ const totalChunks = Math . ceil ( file . size / chunkSize ) ;
377+ const fileName = file . name ;
378+ const maxRetries = 3 ;
379+
380+ for ( let chunkIndex = 0 ; chunkIndex < totalChunks ; chunkIndex ++ ) {
381+ const start = chunkIndex * chunkSize ;
382+ const chunk = file . slice ( start , start + chunkSize ) ;
383+
384+ let attempt = 0 ;
385+ let success = false ;
386+
387+ const progressPercentage = Math . floor ( ( ( chunkIndex + 1 ) / totalChunks ) * 100 ) ;
388+
389+ while ( attempt < maxRetries && ! success ) {
390+ try {
391+ this . loadingService . updateMessage ( `Uploading file: ${ progressPercentage } % completed` ) ;
392+
393+ await this . assetService . uploadChunk ( assetInput , chunk , fileName , chunkIndex , totalChunks ) ;
394+ success = true ;
395+ } catch ( error ) {
396+ attempt ++ ;
397+ if ( attempt >= maxRetries ) {
398+ this . loadingService . hideLoading ( ) ;
399+ this . notificationService . showError ( `Error uploading chunk ${ chunkIndex + 1 } . Maximum retries reached.` ) ;
400+ return ;
401+ }
393402 }
394- } )
403+ }
395404 }
396405
406+ try {
407+ await this . assetService . finalizeUpload ( assetInput , fileName ) ;
408+ this . loadingService . hideLoading ( ) ;
409+ this . notificationService . showInfo ( 'Asset created successfully' ) ;
410+ this . navigateToAsset ( ) ;
411+ } catch ( error : any ) {
412+ this . loadingService . hideLoading ( ) ;
413+ this . notificationService . showError ( 'Error finalizing the asset creation: ' + error . error [ 0 ] . message ) ;
414+ }
415+ } else {
416+ this . assetService . createAsset ( assetInput ) . subscribe ( {
417+ next : ( ) => this . fetch$ . next ( null ) ,
418+ error : ( err ) => {
419+ this . loadingService . hideLoading ( ) ;
420+ this . showError ( err , "Error creating the asset: " + err . error [ 0 ] . message ) ;
421+ } ,
422+ complete : ( ) => {
423+ this . loadingService . hideLoading ( ) ;
424+ this . notificationService . showInfo ( 'Asset created successfully' ) ;
425+ this . navigateToAsset ( ) ;
426+ } ,
427+ } ) ;
397428 }
398429 }
399430
400431
401-
402432 private showError ( error : string , errorMessage : string ) {
403433 this . notificationService . showError ( errorMessage ) ;
404434 console . error ( error ) ;
405435 this . loadingService . hideLoading ( ) ;
406436 }
407437
408- navigateToAsset ( ) {
438+ navigateToAsset ( ) {
409439 this . router . navigate ( [ 'assets' ] )
410440 }
411441}
0 commit comments