UNPKG

stimulsoft-designer-angular

Version:

The Angular Designer component is developed to create reports and dashboards in web browser.

485 lines (477 loc) 21.1 kB
import * as i0 from '@angular/core'; import { Injectable, EventEmitter, Component, ViewChild, Output, Input, NgModule } from '@angular/core'; import { catchError, EMPTY } from 'rxjs'; import * as i1 from '@angular/common/http'; import { CommonModule } from '@angular/common'; class FileSaverService { constructor() { this._global = typeof window === 'object' && window.window === window ? window : typeof self === 'object' && self.self === self ? self : /*typeof global === 'object' && global.global === global ? global : */ this; // Detect WebView inside a native macOS app by ruling out all browsers // We just need to check for 'Safari' because all other browsers (besides Firefox) include that too // https://www.whatismybrowser.com/guides/the-latest-user-agent/macos this.isMacOSWebView = this._global.navigator && /Macintosh/.test(navigator.userAgent) && /AppleWebKit/.test(navigator.userAgent) && !/Safari/.test(navigator.userAgent); this.saveAs = this._global.saveAs || ( // probably in some web worker (typeof window !== 'object' || window !== this._global) ? function saveAs() { } // Use download attribute first if possible (#193 Lumia mobile) unless this is a macOS WebView : ('download' in HTMLAnchorElement.prototype && !this.isMacOSWebView) ? function saveAs(blob, name, opts) { let URL = this._global.URL || this._global.webkitURL; let a = document.createElement('a'); name = name || blob.name || 'download'; a.download = name; a.rel = 'noopener'; // tabnabbing // TODO: detect chrome extensions & packaged apps // a.target = '_blank' if (typeof blob === 'string') { // Support regular links a.href = blob; if (a.origin !== location.origin) { this.corsEnabled(a.href) ? this.download(blob, name, opts) : this.click(a, a.target = '_blank'); } else { this.click(a); } } else { // Support blobs a.href = URL.createObjectURL(blob); let this_ = this; setTimeout(function () { URL.revokeObjectURL(a.href); }, 4E4); // 40s setTimeout(function () { this_.click(a); }, 0); } } // Use msSaveOrOpenBlob as a second approach : 'msSaveOrOpenBlob' in navigator ? function saveAs(blob, name, opts) { name = name || blob.name || 'download'; if (typeof blob === 'string') { if (this.corsEnabled(blob)) { this.download(blob, name, opts); } else { let a = document.createElement('a'); a.href = blob; a.target = '_blank'; let this_ = this; setTimeout(function () { this_.click(a); }); } } else { navigator.msSaveOrOpenBlob(this.bom(blob, opts), name); } } // Fallback to using FileReader and a popup : function saveAs(blob, name, opts, popup) { // Open a popup immediately do go around popup blocker // Mostly only available on user interaction and the fileReader is async so... popup = popup || open('', '_blank'); if (popup) { popup.document.title = popup.document.body.innerText = 'downloading...'; } if (typeof blob === 'string') return this.download(blob, name, opts); let force = blob.type === 'application/octet-stream'; let isSafari = /constructor/i.test(this._global.HTMLElement) || this._global.safari; let isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent); if ((isChromeIOS || (force && isSafari) || this.isMacOSWebView) && typeof FileReader !== 'undefined') { // Safari doesn't allow downloading of blob URLs let reader = new FileReader(); reader.onloadend = function () { let url = reader.result; url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;'); if (popup) popup.location.href = url; else location = url; popup = null; // reverse-tabnabbing #460 }; reader.readAsDataURL(blob); } else { let URL = this._global.URL || this._global.webkitURL; let url = URL.createObjectURL(blob); if (popup) popup.location = url; else location.href = url; popup = null; // reverse-tabnabbing #460 setTimeout(function () { URL.revokeObjectURL(url); }, 4E4); // 40s } }); this._global.saveAs = this.saveAs.saveAs = this.saveAs; /*if (typeof module !== 'undefined') { module.exports = this.saveAs; }*/ } bom(blob, opts) { if (typeof opts === 'undefined') opts = { autoBom: false }; else if (typeof opts !== 'object') { console.warn('Deprecated: Expected third argument to be a object'); opts = { autoBom: !opts }; } // prepend BOM for UTF-8 XML and text/* types (including HTML) // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF if (opts.autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { return new Blob([String.fromCharCode(0xFEFF), blob], { type: blob.type }); } return blob; } download(url, name, opts) { let xhr = new XMLHttpRequest(); xhr.open('GET', url); xhr.responseType = 'blob'; let this_ = this; xhr.onload = function () { this_.saveAs(xhr.response, name, opts); }; xhr.onerror = function () { console.error('could not download file'); }; xhr.send(); } corsEnabled(url) { let xhr = new XMLHttpRequest(); // use sync to avoid popup blocker xhr.open('HEAD', url, false); try { xhr.send(); } catch (e) { } return xhr.status >= 200 && xhr.status <= 299; } // `a.click()` doesn't work for all browsers (#465) click(node) { try { node.dispatchEvent(new MouseEvent('click')); } catch (e) { let evt = document.createEvent('MouseEvents'); evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null); node.dispatchEvent(evt); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FileSaverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FileSaverService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FileSaverService, decorators: [{ type: Injectable }], ctorParameters: () => [] }); class ProxyService { constructor(httpClient, fileSaver) { this.httpClient = httpClient; this.fileSaver = fileSaver; this.openReport = false; } createConnection() { let request = new Object(); request.method = "POST"; request.url = ""; request.headers = {}; request.responseType = "text"; request.readyState = 1; request.status = 0; request.responseText = null; request.statusText = null; request.id = null; request.open = (method, url) => { request.method = method; request.url = url; }; request.setRequestHeader = (key, value) => { request.headers[key] = value; }; request.abort = () => { }; request.onreadystatechange = () => { }; request.send = (data) => { let formData; if (typeof data == 'object') { formData = new FormData(); Object.keys(data).forEach(key => formData.append(key, data[key])); } let needGet = data && data["stiweb_action"] === "Resource"; let observable; if (needGet) { observable = this.httpClient.get(request.url, formData ?? data).pipe(catchError((error) => { return this.catchError(error, request); })); } else { observable = this.httpClient.post(request.url, formData ?? data, { responseType: request.responseType }).pipe(catchError((error) => { return this.catchError(error, request); })); } let downloadFileName; try { let dataObj = JSON.parse(window["StiBase64"].decode(data.stiweb_parameters)); downloadFileName = dataObj.command == "DownloadReport" ? dataObj.reportFile : null; } catch { } observable.subscribe(data => { request.readyState = 4; let resultData = needGet ? JSON.stringify(data) : data; if (request.responseType == "text") request.responseText = resultData; else request.response = resultData; request.status = 200; if (downloadFileName) { let blob = new Blob([data], { type: "application/xml", }); this.fileSaver.saveAs(blob, downloadFileName); request.responseText = "{\"command\":\"SaveReport\"}"; } request.onreadystatechange(); }); }; return request; } ; catchError(error, request) { alert(JSON.stringify(error)); request.status = error.status; request.statusText = error.statusText; request.responseText = error.error; request.readyState = 4; request.onreadystatechange(); return EMPTY; } error(message) { } export(data) { } email(data) { } print(data) { } design() { } postParametersFunction(data) { return this.postParametersFunction_ ? this.postParametersFunction_(data) : {}; } getFormData(data) { const formData = new FormData(); Object.keys(data).forEach(key => formData.append(key, data[key])); return formData; } getData2(url, data) { return this.httpClient.post(url, this.getFormData(data), { responseType: 'blob' }).pipe(catchError((error) => { console.error(error); return EMPTY; })); } saveData(url, params, newWindow, retrieveFileName) { if (retrieveFileName) { params.stiweb_onlyFileName = true; debugger; let observable = this.httpClient.post(url, this.getFormData(params), { responseType: 'json' }).pipe(catchError((error) => { console.error(error); return EMPTY; })); observable.subscribe(resp => { let fileName = resp.fileName; delete params.stiweb_onlyFileName; this.getData2(url, params).subscribe((data) => { this.showData(data, fileName, newWindow); }); }); } else { this.getData2(url, params).subscribe((data) => { this.showData(data, null, newWindow); }); } } showData(data, fileName, newWindow) { if (newWindow) { if (window.navigator && window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveOrOpenBlob(data); } else { var fileURL = URL.createObjectURL(data); window.open(fileURL, '_blank'); } } else { this.fileSaver.saveAs(data, fileName); } } async getText(url) { return new Promise((resolve, reject) => { let observable = this.httpClient.get(url, { responseType: 'text' }).pipe(catchError((error) => { console.log(error); return EMPTY; })); observable.subscribe(data => { resolve(data); }); }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ProxyService, deps: [{ token: i1.HttpClient }, { token: FileSaverService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ProxyService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ProxyService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1.HttpClient }, { type: FileSaverService }] }); class StimulsoftDesignerComponent { constructor(proxy, httpClient) { this.proxy = proxy; this.httpClient = httpClient; /** * Occurs when designer loaded */ this.designerLoaded = new EventEmitter(); this.id = 'aDesigner' + (Math.random() * 10000000).toString(); this.scriptLoading = false; this.loaded = false; } ngOnDestroy() { if (this.chartScripts) { this.head.removeChild(this.chartScripts); } let options = this.designerEl.nativeElement?.firstChild?.jsObject?.options; try { clearTimeout(options.timerAjax); } catch { } try { clearTimeout(options.timerUpdateCache); } catch { } try { clearTimeout(options.timerAutoSave); } catch { } } ngOnInit() { this.addScript(); } ngOnChanges(changes) { this.addScript(); } addScript() { if (this.scriptLoading) return; this.scriptLoading = true; if (this.chartScripts) { this.head.removeChild(this.chartScripts); } this.chartScripts = document.createElement('Script'); this.chartScripts.setAttribute('type', 'text/javascript'); this.head.appendChild(this.chartScripts); let observable = this.httpClient.get(this.requestUrl, { responseType: 'text' }).pipe(catchError((error) => { console.log(error); this.scriptLoading = false; return EMPTY; })); observable.subscribe(data => { if (!this.loaded) { try { this.chartScripts.innerHTML = data; const options = new Stimulsoft.Designer.StiDesignerOptions(); this.loaded = true; setTimeout(() => { this.scriptLoading = false; }); this.showDesigner(); this.designerLoadedF(); } catch { this.scriptLoading = false; } } }); } designerLoadedF() { let jsObject = this.designerEl.nativeElement?.firstChild?.jsObject; if (!jsObject) { setTimeout(() => { this.designerLoadedF(); }); return; } this.designerLoaded.next(null); } showDesigner() { const options = new Stimulsoft.Designer.StiDesignerOptions(); let defaultOptions = Stimulsoft?.Designer?.defaultOptions; if (defaultOptions) { for (let k in defaultOptions) options[k] = defaultOptions[k]; options.useAliasesDictionary = defaultOptions.dictionary.useAliases; } if (this.width) { options.width = this.width; } if (this.height) { options.height = this.height; } this.designer = new Stimulsoft.Designer.StiDesigner(options, 'StiDesigner', false); this.proxy.postParametersFunction_ = this.postParametersFunction; this.designerEl.nativeElement.proxy = this.proxy; this.designer.renderHtml(this.designerEl.nativeElement); } get head() { return document.getElementsByTagName('head')[0]; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StimulsoftDesignerComponent, deps: [{ token: ProxyService }, { token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: StimulsoftDesignerComponent, selector: "stimulsoft-designer-angular", inputs: { requestUrl: "requestUrl", width: "width", height: "height", postParametersFunction: "postParametersFunction" }, outputs: { designerLoaded: "designerLoaded" }, providers: [ProxyService, FileSaverService], viewQueries: [{ propertyName: "designerEl", first: true, predicate: ["designer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: ` <div #designer [attr.id]="id"> <ng-content></ng-content> </div> `, isInline: true }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StimulsoftDesignerComponent, decorators: [{ type: Component, args: [{ selector: 'stimulsoft-designer-angular', template: ` <div #designer [attr.id]="id"> <ng-content></ng-content> </div> `, providers: [ProxyService, FileSaverService] }] }], ctorParameters: () => [{ type: ProxyService }, { type: i1.HttpClient }], propDecorators: { designerEl: [{ type: ViewChild, args: ['designer'] }], designerLoaded: [{ type: Output }], requestUrl: [{ type: Input }], width: [{ type: Input }], height: [{ type: Input }], postParametersFunction: [{ type: Input }] } }); class StimulsoftDesignerModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StimulsoftDesignerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: StimulsoftDesignerModule, declarations: [StimulsoftDesignerComponent], imports: [CommonModule], exports: [StimulsoftDesignerComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StimulsoftDesignerModule, imports: [CommonModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: StimulsoftDesignerModule, decorators: [{ type: NgModule, args: [{ declarations: [StimulsoftDesignerComponent], imports: [ CommonModule ], exports: [StimulsoftDesignerComponent] }] }] }); /* * Public API Surface of stimulsoft-designer-angular */ /** * Generated bundle index. Do not edit. */ export { StimulsoftDesignerComponent, StimulsoftDesignerModule }; //# sourceMappingURL=stimulsoft-designer-angular.mjs.map