import { Injectable } from '@angular/core'; import { HttpClient, HttpResponse, HttpHeaders } from '@angular/common/http'; import { Observable, throwError as _throw } from 'rxjs'; import { catchError, tap, map } from 'rxjs/operators'; import { saveAs } from 'file-saver'; import { TranslateService } from '@ngx-translate/core'; import { ConfigService } from '@arrow/bom/config'; import { QueryParams } from './util/http'; import { MessageBusService } from './message-bus/message-bus.service'; import { AnalyticsService } from './analytics.service'; @Injectable() export class DownloadService { private readonly _dataUrl: string; constructor( private _http: HttpClient, private _config: ConfigService, private _messageBus: MessageBusService, private _analyticsService: AnalyticsService, private _translate: TranslateService ) { this._dataUrl = `${this._config.apiUrl}`; } private _handleBlobResponse(response: HttpResponse): void { const fileName = this._getFileNameFromHeaders(response.headers); saveAs(response.body, fileName); } /** * @param headers */ private _getFileNameFromHeaders(headers: HttpHeaders) { if (!headers) return ''; const contentDispositionHeader: string = headers.get('Content-Disposition'); if (!contentDispositionHeader) return ''; const contentDisposition = {}; const contentDispositionParts: Array< string > = contentDispositionHeader.split(';'); for (const contentDispositionPart of contentDispositionParts) { const keyValuePair = contentDispositionPart.split('='); const key = keyValuePair[0].trim(); const value = (keyValuePair[1] || '').trim(); contentDisposition[key] = value; } return contentDisposition['filename'] || ''; } private _handleError(error: any): any { this._messageBus.to('ch:loader', { payload: false }); return _throw(error.message || 'Server error'); } /** * Gets the current bom as a xlsx file * @param bomId - bomId. * @param params? - bom file params * @returns Observable any. */ downloadBom(bomId: string, params?: QueryParams): Observable { const baseUrl = this._config.apiUrl.substring( 0, this._config.apiUrl.length - 3 ); const url = `${baseUrl}/api/boms/${bomId}/excel?${ params ? params.toString() : '' }`; return this._http .get(url, { observe: 'response', responseType: 'blob', withCredentials: true }) .pipe( catchError(() => { const message = `${this._translate.instant( 'BOM.Cannot-download-BOM.' )} ${this._translate.instant('BOM.Please-try-again-later.')} ${this._translate.instant( 'BOM.If-the-problem-persists-please-contact-us.' )}`; return this._handleError(message); }), map((response: HttpResponse) => this._handleBlobResponse(response) ) ); } downloadGeneratedBomFile(fileId: string): Observable { const baseUrl = this._config.apiUrl.substring( 0, this._config.apiUrl.length - 3 ); const url = `${baseUrl}/api/boms/files/${fileId}`; return this._http .get(url, { observe: 'response', responseType: 'blob' }) .pipe( catchError(() => { const message = `${this._translate.instant( 'BOM.Cannot-download-BOM.' )} ${this._translate.instant('BOM.Please-try-again-later.')} ${this._translate.instant( 'BOM.If-the-problem-persists-please-contact-us.' )}`; return this._handleError(message); }), map((response: HttpResponse) => this._handleBlobResponse(response) ) ); } /** * Sends the bom email request to the API. * @param bomId The bom Id. * @param emailData email data supplied in the form. * @returns Observable any. */ emailBom(bomId: string, emailData: any): Observable { const payload = { targetEmails: emailData.recipient.split(',').map(email => email.trim()), senderEmail: emailData.sender, optionalMessage: emailData.message, columnIds: emailData.columnIds, includeCrosses: emailData.includeCrosses }; const newApi = this._dataUrl.substring(0, this._dataUrl.length - 3); const url = `${newApi}/api/boms/${bomId}/email`; return this._http .post(url, payload, { withCredentials: true }) .pipe(catchError(error => this._handleError(error))); } }