@@ -56,29 +56,29 @@ const API_CHECK_INTERVAL = 3000;
5656const MAX_TRIES = 5 ;
5757
5858function attemptsGuardFactory ( maxAttempts : number ) {
59- return ( attemptsCount : number ) => {
60- if ( attemptsCount > maxAttempts ) {
61- throw new Error ( 'Exceeded pool requests, try again!' ) ;
62- }
63- } ;
59+ return ( attemptsCount : number ) => {
60+ if ( attemptsCount > maxAttempts ) {
61+ throw new Error ( 'Exceeded pool requests, try again!' ) ;
62+ }
63+ } ;
6464}
6565
6666export function pollWhile < T > (
67- pollInterval : number ,
68- isPollingActive : ( res : T ) => boolean ,
69- maxAttempts = Infinity ,
70- emitOnlyLast = true ,
67+ pollInterval : number ,
68+ isPollingActive : ( res : T ) => boolean ,
69+ maxAttempts = Infinity ,
70+ emitOnlyLast = true ,
7171) : MonoTypeOperatorFunction < T > {
72- return source$ => {
73- const poll$ = timer ( 0 , pollInterval ) . pipe (
74- scan ( attempts => ++ attempts , 0 ) ,
75- tap ( attemptsGuardFactory ( maxAttempts ) ) ,
76- switchMap ( ( ) => source$ ) ,
77- takeWhile ( isPollingActive , true )
78- ) ;
79-
80- return emitOnlyLast ? poll$ . pipe ( last ( ) ) : poll$ ;
81- } ;
72+ return source$ => {
73+ const poll$ = timer ( 0 , pollInterval ) . pipe (
74+ scan ( attempts => ++ attempts , 0 ) ,
75+ tap ( attemptsGuardFactory ( maxAttempts ) ) ,
76+ switchMap ( ( ) => source$ ) ,
77+ takeWhile ( isPollingActive , true )
78+ ) ;
79+
80+ return emitOnlyLast ? poll$ . pipe ( last ( ) ) : poll$ ;
81+ } ;
8282}
8383
8484
@@ -100,15 +100,15 @@ export class SubmissionSectionUnpaywallComponent extends SectionModelComponent i
100100 public readonly UnpaywallSectionStatus = UnpaywallSectionStatus ;
101101 public readonly status$ = new BehaviorSubject < UnpaywallSectionStatus > ( null ) ;
102102 public readonly loading$ = new BehaviorSubject < boolean > ( true ) ;
103- public readonly unpaywallSection$ = new BehaviorSubject < WorkspaceitemSectionUnpaywallObject > ( null ) ;
103+ public readonly unpaywallSection$ = new BehaviorSubject < WorkspaceitemSectionUnpaywallObject > ( null ) ;
104104 public readonly uploadSection$ = new BehaviorSubject < UploadSection > ( null ) ;
105105
106- protected readonly AlertType = AlertType ;
107- protected readonly section$ = new BehaviorSubject < WorkspaceitemSectionsObject > ( null ) ;
106+ protected readonly AlertType = AlertType ;
107+ protected readonly section$ = new BehaviorSubject < WorkspaceitemSectionsObject > ( null ) ;
108108
109109 private readonly unsubscribe$ = new Subject < void > ( ) ;
110- private readonly fetch$ = new Subject < boolean > ( ) ;
111- private readonly stopFetch$ = new Subject < void > ( ) ;
110+ private readonly fetch$ = new Subject < boolean > ( ) ;
111+ private readonly stopFetch$ = new Subject < void > ( ) ;
112112
113113 constructor (
114114 protected sectionService : SectionsService ,
@@ -148,71 +148,84 @@ export class SubmissionSectionUnpaywallComponent extends SectionModelComponent i
148148 this . initUploadSectionResponseListener ( ) ;
149149 }
150150
151- protected initDoiChangesListener ( ) {
152- this . store . select ( submissionObjectFromIdSelector ( this . submissionId ) )
153- . pipe (
154- filter ( submissionEntry => hasValue ( submissionEntry ?. definition ) && hasValue ( submissionEntry ?. sections ) ) ,
155- map ( value => this . getDoiMetadataValue ( value ) ) ,
156- distinctUntilChanged ( ) ,
157- takeUntil ( this . unsubscribe$ ) ,
158- )
159- . subscribe ( doiValue => ! ! doiValue ? this . showCurrentSection ( ) : this . hideCurrentSection ( ) ) ;
160- }
151+ protected initDoiChangesListener ( ) {
152+ this . store . select ( submissionObjectFromIdSelector ( this . submissionId ) )
153+ . pipe (
154+ filter ( submissionEntry => hasValue ( submissionEntry ?. definition ) && hasValue ( submissionEntry ?. sections ) ) ,
155+ map ( value => this . getDoiMetadataValue ( value ) ) ,
156+ distinctUntilChanged ( ) ,
157+ takeUntil ( this . unsubscribe$ ) ,
158+ )
159+ . subscribe ( doiValue => ! ! doiValue ? this . showCurrentSection ( ) : this . hideCurrentSection ( ) ) ;
160+ }
161161
162- protected initUnpaywallFetching ( ) {
163- this . fetch$ . pipe (
164- switchMap ( ( refreshRequired ) =>
165- this . patchForRefresh ( refreshRequired ) . pipe (
166- pollWhile (
167- API_CHECK_INTERVAL ,
168- res => this . isStillPending ( res ) ,
169- MAX_TRIES
170- ) ,
171- this . getUnpaywallSection ( ) ,
172- takeUntil ( this . stopFetch$ ) ,
173- catchError ( err => {
174- this . notificationsService . error ( err ?. message ) ;
175- return of ( Object . assign ( { } , { ...this . unpaywallSection$ . getValue ( ) , status : UnpaywallSectionStatus . NO_FILE } ) ) ;
176- } ) ,
177- )
178- ) ,
179- takeUntil ( this . unsubscribe$ ) ,
180- ) . subscribe ( unpaywall => {
181- this . updateUnpaywall ( unpaywall ) ;
182-
183- const isLoading = ! unpaywall ?. status || unpaywall ?. status === UnpaywallSectionStatus . PENDING ;
184- this . loading$ . next ( isLoading ) ;
185- if ( ! isLoading ) {
186- this . stopFetch$ . next ( ) ;
187- }
188- } ) ;
189- }
162+ protected initUnpaywallFetching ( ) {
163+ this . fetch$ . pipe (
164+ switchMap ( ( refreshRequired ) =>
165+ this . patchForRefresh ( refreshRequired )
166+ . pipe (
167+ switchMap ( sections => {
168+ let unpaywall = this . extractUnpaywallSection ( sections ) ;
169+ if ( unpaywall . status !== UnpaywallSectionStatus . PENDING ) {
170+ return of ( unpaywall ) ;
171+ } else {
172+ return this . patchForRefresh ( false ) . pipe (
173+ pollWhile (
174+ API_CHECK_INTERVAL ,
175+ res => this . isStillPending ( res ) ,
176+ MAX_TRIES
177+ ) ,
178+ takeUntil ( this . stopFetch$ ) ,
179+ this . getUnpaywallSection ( ) ,
180+ catchError ( err => {
181+ this . notificationsService . error ( err ?. message ) ;
182+ return of ( Object . assign ( { } , {
183+ ...this . unpaywallSection$ . getValue ( ) ,
184+ status : UnpaywallSectionStatus . NO_FILE
185+ } ) ) ;
186+ } )
187+ ) ;
188+ }
189+ } )
190+ )
191+ ) ,
192+ takeUntil ( this . unsubscribe$ ) ,
193+ ) . subscribe ( unpaywall => {
194+ this . updateUnpaywall ( unpaywall ) ;
195+
196+ const isLoading = ! unpaywall ?. status || unpaywall ?. status === UnpaywallSectionStatus . PENDING ;
197+ this . loading$ . next ( isLoading ) ;
198+ if ( ! isLoading ) {
199+ this . stopFetch$ . next ( ) ;
200+ }
201+ } ) ;
202+ }
190203
191- protected initStatusNotification ( ) {
192- this . status$ . pipe (
193- filter ( hasValue ) ,
194- takeUntil ( this . unsubscribe$ ) ,
195- ) . subscribe ( status => this . handleStatusNotification ( status ) ) ;
196- }
204+ protected initStatusNotification ( ) {
205+ this . status$ . pipe (
206+ filter ( hasValue ) ,
207+ takeUntil ( this . unsubscribe$ ) ,
208+ ) . subscribe ( status => this . handleStatusNotification ( status ) ) ;
209+ }
197210
198- protected handleStatusNotification ( status : UnpaywallSectionStatus ) {
199- switch ( status ) {
200- case UnpaywallSectionStatus . NOT_FOUND :
201- this . notificationsService . error ( this . translate . instant ( 'submission.sections.unpaywall.status.not-found' ) ) ;
202- break ;
203- case UnpaywallSectionStatus . NO_FILE :
204- this . notificationsService . warning ( this . translate . instant ( 'submission.sections.unpaywall.status.no-file' ) ) ;
205- break ;
206- case UnpaywallSectionStatus . SUCCESSFUL :
207- this . notificationsService . success ( this . translate . instant ( 'submission.sections.unpaywall.status.successful' ) ) ;
208- break ;
209- case UnpaywallSectionStatus . IMPORTED :
210- this . notificationsService . success ( this . translate . instant ( 'submission.sections.unpaywall.status.imported' ) ) ;
211- break ;
212- default :
213- break ;
214- }
211+ protected handleStatusNotification ( status : UnpaywallSectionStatus ) {
212+ switch ( status ) {
213+ case UnpaywallSectionStatus . NOT_FOUND :
214+ this . notificationsService . error ( this . translate . instant ( 'submission.sections.unpaywall.status.not-found' ) ) ;
215+ break ;
216+ case UnpaywallSectionStatus . NO_FILE :
217+ this . notificationsService . warning ( this . translate . instant ( 'submission.sections.unpaywall.status.no-file' ) ) ;
218+ break ;
219+ case UnpaywallSectionStatus . SUCCESSFUL :
220+ this . notificationsService . success ( this . translate . instant ( 'submission.sections.unpaywall.status.successful' ) ) ;
221+ break ;
222+ case UnpaywallSectionStatus . IMPORTED :
223+ this . notificationsService . success ( this . translate . instant ( 'submission.sections.unpaywall.status.imported' ) ) ;
224+ break ;
225+ default :
226+ break ;
215227 }
228+ }
216229
217230 protected onSectionDestroy ( ) : void {
218231 this . unsubscribe$ . next ( ) ;
@@ -255,62 +268,69 @@ export class SubmissionSectionUnpaywallComponent extends SectionModelComponent i
255268 private updateUnpaywall ( unpaywall : WorkspaceitemSectionUnpaywallObject ) {
256269 this . unpaywallSection$ . next ( unpaywall ) ;
257270 this . status$ . next ( unpaywall ?. status ) ;
258- }
271+ }
259272
260273 private isStillPending ( response : WorkspaceitemSectionsObject ) {
261274 return hasNoValue ( response ?. unpaywall ) || ( response ?. unpaywall as WorkspaceitemSectionUnpaywallObject ) ?. status === UnpaywallSectionStatus . PENDING ;
262275 }
263276
264- private handleFileUpload ( ) {
265- this . patchForAccept ( )
266- . pipe (
267- filter ( hasValue ) ,
268- take ( 1 ) ,
269- ) . subscribe (
270- ( ) => {
271- this . loading$ . next ( true ) ;
272- this . fetch$ . next ( false ) ;
273- this . listenToUploadSectionChanges ( ) ;
274- } ,
275- ( ) => this . stopFetch$ . next ( )
276- ) ;
277- }
277+ private handleFileUpload ( ) {
278+ this . loading$ . next ( true ) ;
279+ this . listenToUploadSectionChanges ( ) ;
280+ this . patchForAccept ( )
281+ . pipe (
282+ filter ( hasValue ) ,
283+ take ( 1 ) ,
284+ this . getUnpaywallSection ( ) ,
285+ catchError ( err => {
286+ this . notificationsService . error ( err ?. message ) ;
287+ return of ( Object . assign ( { } , {
288+ ...this . unpaywallSection$ . getValue ( ) ,
289+ status : UnpaywallSectionStatus . NO_FILE
290+ } ) ) ;
291+ } ) ,
292+ ) . subscribe ( ( unpaywall ) => {
293+ this . updateUnpaywall ( unpaywall ) ;
294+ this . loading$ . next ( false ) ;
295+ this . stopFetch$ . next ( ) ;
296+ } ) ;
297+ }
278298
279- private listenToUploadSectionChanges ( ) {
280- this . uploadSection$ . pipe (
281- pairwise ( ) ,
282- filter ( ( [ prev , curr ] ) => this . isAnyFieldChangedInLength ( curr , prev ) ) ,
283- map ( ( [ prev , curr ] ) => this . mapNewFilesByKey ( curr , prev ) ) ,
284- take ( 1 ) ,
285- takeUntil ( this . stopFetch$ ) ,
286- )
287- . subscribe ( uploadedFiles => Object . keys ( uploadedFiles ) . forEach ( key => this . uploadFiles ( uploadedFiles , key ) ) ) ;
288- }
299+ private listenToUploadSectionChanges ( ) {
300+ this . uploadSection$ . pipe (
301+ pairwise ( ) ,
302+ takeUntil ( this . stopFetch$ ) ,
303+ filter ( ( [ prev , curr ] ) => this . isAnyFieldChangedInLength ( curr , prev ) ) ,
304+ map ( ( [ prev , curr ] ) => this . mapNewFilesByKey ( curr , prev ) ) ,
305+ take ( 1 ) ,
306+ )
307+ . subscribe ( uploadedFiles => Object . keys ( uploadedFiles ) . forEach ( key => this . uploadFiles ( uploadedFiles , key ) ) ) ;
308+ }
289309
290310 private stopApiCheck ( ) : void {
291311 this . loading$ . next ( false ) ;
292312 this . stopFetch$ . next ( ) ;
293313 }
294314
295- private patchForRefresh ( refreshRequired = false ) : Observable < WorkspaceitemSectionsObject > {
296- const { operation, linkPath } = this . createOperation ( 'refresh' , refreshRequired ) ;
297- return this . sendPatchRequest ( linkPath , operation ) ;
298- }
315+ private patchForRefresh ( refreshRequired = false ) : Observable < WorkspaceitemSectionsObject > {
316+ const { operation, linkPath } = this . createOperation ( 'refresh' , refreshRequired ) ;
317+ return this . sendPatchRequest ( linkPath , operation ) ;
318+ }
299319
300- private patchForAccept ( accepted : boolean = true ) : Observable < WorkspaceitemSectionsObject > {
301- const { operation, linkPath } = this . createOperation ( 'accept' , accepted ) ;
302- return this . sendPatchRequest ( linkPath , operation ) ;
303- }
320+ private patchForAccept ( accepted : boolean = true ) : Observable < WorkspaceitemSectionsObject > {
321+ const { operation, linkPath } = this . createOperation ( 'accept' , accepted ) ;
322+ return this . sendPatchRequest ( linkPath , operation ) ;
323+ }
304324
305- private createOperation ( operationPath : string , value : boolean ) {
306- const pathCombiner = new JsonPatchOperationPathCombiner ( 'sections' , this . sectionData . id ) ;
307- const path = pathCombiner . getPath ( operationPath ) ;
308- const operation = { op : 'add' , path : path . path , value } as Operation ;
309- const linkPath = this . submissionService . getSubmissionObjectLinkName ( ) ;
310- return { operation, linkPath } ;
311- }
325+ private createOperation ( operationPath : string , value : boolean ) {
326+ const pathCombiner = new JsonPatchOperationPathCombiner ( 'sections' , this . sectionData . id ) ;
327+ const path = pathCombiner . getPath ( operationPath ) ;
328+ const operation = { op : 'add' , path : path . path , value } as Operation ;
329+ const linkPath = this . submissionService . getSubmissionObjectLinkName ( ) ;
330+ return { operation, linkPath } ;
331+ }
312332
313- private sendPatchRequest ( linkPath : string , operation : Operation ) {
333+ private sendPatchRequest ( linkPath : string , operation : Operation ) : Observable < WorkspaceitemSectionsObject > {
314334 return this . halService . getEndpoint ( linkPath )
315335 . pipe (
316336 map ( ( endpoint : string ) => endpoint . concat ( `/${ this . submissionId } ` ) ) ,
@@ -321,10 +341,13 @@ export class SubmissionSectionUnpaywallComponent extends SectionModelComponent i
321341 ) ;
322342 }
323343
324- private getUnpaywallSection ( ) {
325- return ( source$ : Observable < WorkspaceitemSectionsObject > ) =>
326- source$ . pipe ( map ( sections => sections ?. unpaywall as WorkspaceitemSectionUnpaywallObject ) ) ;
327- }
344+ private getUnpaywallSection ( ) {
345+ return ( source$ : Observable < WorkspaceitemSectionsObject > ) => source$ . pipe ( map ( this . extractUnpaywallSection ) ) ;
346+ }
347+
348+ private extractUnpaywallSection ( sections : WorkspaceitemSectionsObject ) {
349+ return sections ?. unpaywall as WorkspaceitemSectionUnpaywallObject ;
350+ }
328351
329352 private getDoiMetadataValue ( value : SubmissionObjectEntry ) : string {
330353 return value . sections [ value . definition ] ?. data ?. [ DOI_METADATA ] ?. [ 0 ] ?. value ;
@@ -345,30 +368,30 @@ export class SubmissionSectionUnpaywallComponent extends SectionModelComponent i
345368 }
346369
347370 private mapNewFilesByKey ( curr : UploadSection , prev : UploadSection ) {
348- return Object . assign ( { } ,
349- ...Object . keys ( curr )
350- . map ( key => ( { [ key ] : this . getNewFiles ( curr , prev , key ) } ) )
351- ) ;
352- }
371+ return Object . assign ( { } ,
372+ ...Object . keys ( curr )
373+ . map ( key => ( { [ key ] : this . getNewFiles ( curr , prev , key ) } ) )
374+ ) ;
375+ }
353376
354- private uploadFiles ( uploadedFiles : { [ p : string ] : any } , key : string ) {
355- return uploadedFiles [ key ] . forEach ( file => this . sectionUploadService . addUploadedFile ( this . submissionId , key , file . uuid , file ) ) ;
356- }
377+ private uploadFiles ( uploadedFiles : { [ p : string ] : any } , key : string ) {
378+ return uploadedFiles [ key ] . forEach ( file => this . sectionUploadService . addUploadedFile ( this . submissionId , key , file . uuid , file ) ) ;
379+ }
357380
358381 private getNewFiles ( curr : UploadSection , prev : UploadSection , key : string ) {
359- return curr [ key ] ?. files ?. filter ( file => this . notContainsFile ( prev [ key ] , file ) ) ;
360- }
382+ return curr [ key ] ?. files ?. filter ( file => this . notContainsFile ( prev [ key ] , file ) ) ;
383+ }
361384
362385 private notContainsFile ( uploadSection : WorkspaceitemSectionUploadObject , file : WorkspaceitemSectionUploadFileObject ) {
363- return hasNoValue ( uploadSection ?. files ) || ! uploadSection ?. files . some ( f => f . uuid === file . uuid ) ;
364- }
386+ return hasNoValue ( uploadSection ?. files ) || ! uploadSection ?. files . some ( f => f . uuid === file . uuid ) ;
387+ }
365388
366389 private isAnyFieldChangedInLength ( curr : UploadSection , prev : UploadSection ) {
367390 return Object . keys ( curr ) . some ( key => this . isLengthDifferent ( curr , prev , key ) ) ;
368- }
391+ }
369392
370393 private isLengthDifferent ( curr : UploadSection , prev : UploadSection , key : string ) {
371- return curr [ key ] ?. files . length !== prev [ key ] ?. files . length ;
394+ return curr [ key ] ?. files . length !== prev [ key ] ?. files . length ;
372395 }
373396
374397}
0 commit comments