Created
January 31, 2018 12:49
-
-
Save AndreasBaumgart/ca40f2ba0cafa170d9406a9da9e14e5b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'rxjs/add/observable/interval'; | |
import {Injectable} from '@angular/core'; | |
import {Headers, Http, Response as HttpResponse} from '@angular/http'; | |
import {Observable} from 'rxjs/Observable'; | |
import {Observer} from 'rxjs/Observer'; | |
import {Store} from '@ngrx/store'; | |
import {getIdentity, State} from '../../store/reducers'; | |
import {Identity} from '../auth/identity'; | |
import {I18nService} from '../i18n/service'; | |
type UserJobStatusStatus = 'pending' | 'processing' | 'ready' | 'fail' | 'internal_fail'; | |
interface UserJobStatus { | |
href: string, | |
status: UserJobStatusStatus, | |
resultUrl: null | string | |
} | |
const POLL_INTERVAL = 2000; | |
@Injectable() | |
export class MpsDownloadService { | |
public static buildHeaders(identity: Identity, currentLocale: string) { | |
return new Headers({ | |
'Content-Type': 'application/json', | |
'Accept': 'application/json', | |
'Authorization': identity.token, | |
'Accept-Language': `${currentLocale}; q=1.0`, | |
}); | |
} | |
constructor(private http: Http, | |
private store$: Store<State>, | |
private i18n: I18nService) { | |
} | |
public downloadDelayed(url: string): Observable<void> { | |
return this.getDelayedDownloadUrl(url) | |
.map(resultUrl => { | |
window.open(resultUrl); | |
}); | |
} | |
public getDelayedDownloadUrl(url: string): Observable<string> { | |
return Observable.create((o: Observer<string>) => { | |
const requirements$ = this.store$.select(getIdentity).take(1).withLatestFrom(this.i18n.getCurrentLocale()); | |
requirements$.subscribe(([identity, currentLocale]: [Identity, string]) => { | |
const headers = MpsDownloadService.buildHeaders(identity, currentLocale); | |
this.http.post(url, {}, {headers}).subscribe((response: HttpResponse) => { | |
const status: UserJobStatus = response.json().data; | |
if (status.status === 'fail') { | |
console.error('Failed to fetch download URL', status); | |
o.error('Failed to fetch download URL'); | |
} else if (status.status === 'ready') { | |
o.next(status.resultUrl); | |
o.complete(); | |
} else { | |
this.pollResult(status.href) | |
.subscribe(resultUrl => { | |
o.next(resultUrl); | |
o.complete(); | |
}); | |
} | |
}); | |
}); | |
}); | |
} | |
public pollResult(jobUrl): Observable<string> { | |
// TODO: Timeout! | |
return Observable | |
.interval(POLL_INTERVAL) | |
.withLatestFrom(this.store$.select(getIdentity), this.i18n.getCurrentLocale()) | |
.map(([_, identity, currentLocale]) => MpsDownloadService.buildHeaders(identity, currentLocale)) | |
.flatMap((headers: Headers) => this.http.get(jobUrl, {headers}).map((response: HttpResponse) => response.json())) | |
.map((data: any) => data.data) | |
.do(status => { | |
if (status.status === 'fail' || status.status === 'internal_fail') { | |
console.error('Download failed', status); | |
throw new Error('Download failed'); | |
} | |
}) | |
.map((status: any) => status.resultUrl) | |
.filter(resultUrl => null !== resultUrl) | |
.take(1) | |
; | |
} | |
public createDelayedDownloadPerformer(url: string): () => Promise<void> { | |
return () => { | |
return new Promise((resolve: () => void) => { | |
this | |
.downloadDelayed(url) | |
.subscribe(resolve); | |
}); | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment