UNPKG

workplacex-cli

Version:

Create database applications with Angular 11, ASP.NET Core 5.0 and MS-SQL for Linux and Windows.

349 lines (246 loc) 9.94 kB
import { DOCUMENT, Location } from '@angular/common'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core'; import { Meta, Title } from '@angular/platform-browser'; // See also https://angular.io/guide/http import { throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; declare var jsonBrowser: any; // Data from browser, sent by server on first request. export class Json { // AppJson Id!: number; Name: string | undefined; Type: string | undefined; CssClass: string | undefined; Version: string | undefined; VersionBuild: string | undefined; IsServerSideRendering: boolean | undefined; Session: string | undefined; SessionApp: string | undefined; SessionState: string | undefined; RequestCount: number | undefined; ResponseCount: number | undefined; RequestUrlHost: string | undefined; EmbeddedUrl: string | undefined; IsReload: boolean | undefined; List: any; DownloadData: string | undefined; DownloadFileName: string | undefined; DownloadContentType: string | undefined; IsScrollToTop: boolean | undefined; NavigatePathAddHistory: string | undefined; Title: string | undefined; Description: string | undefined; CellList: Cell[] | undefined; StyleColumnList: StyleColumn[] | undefined; IsShowSpinner: boolean | undefined; IsHidePagination: boolean | undefined; IsShowConfig: boolean | undefined; IsShowConfigDeveloper: boolean | undefined; StyleRowList: StyleRow[] | undefined; TextHtml: string | undefined; IsNoSanatize: boolean | undefined; IsNoSanatizeScript: string | undefined; Key: string | undefined; // BingMap BrandTextHtml: string | undefined; // BootstrapNavbar, BulmaNavbar ItemStartList: any; ItemEndList: any; ItemList: any; ButtonList: any; } export class CommandJson { CommandEnum: number | undefined; GridCellId: number | undefined; GridCellText: string | undefined; GridCellTextBase64: string | undefined; GridCellTextBase64FileName: string | undefined; ComponentId: number | undefined; GridIsClickEnum : number | undefined; BootstrapNavbarButtonId: number | undefined; BulmaNavbarItemId: number | undefined; BulmaFilterText: string | undefined; NavigatePath: string | undefined; HtmlButtonId: string | undefined; ResizeColumnIndex: number | undefined; ResizeColumnWidthValue: number | undefined; DialpadText: string | undefined; } export class RequestJson { RequestCount: number | undefined; ResponseCount: number | undefined; BrowserNavigatePathPost: string | undefined; CommandList: CommandJson[] | undefined; } export class Cell { CellEnum!: number; Width: string | undefined; IsSort: boolean | undefined; IsShowSpinner: boolean | undefined; Description: string | undefined; ColumnText: string | undefined; IsSelect: boolean | undefined; Html: string | undefined; HtmlLeft: string | undefined; HtmlRight: string | undefined; IsPassword: boolean | undefined; HtmlIsEdit: boolean | undefined; Align: number | undefined; // CellAnnotationAlignEnum Text: string | undefined; IsReadOnly: boolean | undefined; IsMultiline: boolean | undefined; Placeholder: string | undefined; ErrorParse: string | undefined; ErrorSave: string | undefined; Warning: string | undefined; IsFileUpload: boolean | undefined; GridLookup: any; } export class StyleRow { } export class StyleColumn { Width: string | undefined; WidthValue: number | undefined; WidthUnit: string | undefined; } @Injectable({ providedIn: 'root' }) export class DataService { public json: Json = new Json(); public VersionBuild: string = "Build (WorkplaceX=v3.49.00; Commit=a0d1b52; Pc=DEVPC; Time=2021-03-02 14:34:12 (UTC);)"; /* VersionBuild */ public isRequestPending: boolean = false; // Request is in prgress. requestJsonQueue: RequestJson | undefined // Put latest request in queue, if waiting for pending request. public renderer: Renderer2; // Used for BingMap constructor( private httpClient: HttpClient, // app.module.ts imports: [HttpClientModule @Inject('jsonServerSideRendering') private jsonServerSideRendering: any, @Inject(DOCUMENT) public document: Document, rendererFactory: RendererFactory2, private location: Location, private titleService: Title, private metaTagService: Meta) { this.renderer = rendererFactory.createRenderer(null, null); if (this.jsonServerSideRendering != null) { // Render on SSR server this.json = this.jsonServerSideRendering; this.json.IsServerSideRendering = true; if (this.json.Title != null) { this.titleService.setTitle(this.json.Title); } if (this.json.Description != null) { this.metaTagService.updateTag({ name: 'description', content: this.json.Description }); } } else { // Render in browser if (typeof jsonBrowser == 'undefined') { // jsonBrowser not declared in index.html this.json = <Json>{}; } else { this.json = jsonBrowser; // Provided by index.html coming from ASP.NET Core WebServer for both SSR and not SSR. } this.json.IsServerSideRendering = false; if (window.location.href.endsWith(":4200/")) { // Running in Framework/Framework.Angular/application/ this.json.EmbeddedUrl = "http://" + window.location.hostname + ":5000/"; // http://localhost:5000/ or http://localhost2:5000/ } if (window != null) { // Running on client. this.json.RequestUrlHost = window.location.href; if (typeof jsonBrowser == 'undefined') { this.update(null); // First request if running on http://localhost:4200 } } } } private fileDownload(jsonResponse: Json) { // See also: https://stackoverflow.com/questions/16245767/creating-a-blob-from-a-base64-string-in-javascript if (jsonResponse.DownloadFileName != null) { const byteCharacters = atob(jsonResponse.DownloadData || ""); const byteNumbers = new Array(byteCharacters.length); for (let i = 0; i < byteCharacters.length; i++) { byteNumbers[i] = byteCharacters.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); const blob = new Blob([byteArray], {type: jsonResponse.DownloadContentType}); if (window.navigator && window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveOrOpenBlob(blob, jsonResponse.DownloadFileName); // See also: https://stackoverflow.com/questions/27463901/setting-window-location-or-window-open-in-angularjs-gives-access-is-denied-in } else { const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = jsonResponse.DownloadFileName; link.click(); URL.revokeObjectURL(link.href); } } } private isScrollToTop(jsonResponse: Json) { if (jsonResponse.IsScrollToTop) { document.documentElement.scrollTop = 0; } } public update(commandJson: CommandJson | null): void { var requestJson = <RequestJson> <unknown>{ CommandList: [] } if (commandJson != null) { requestJson.CommandList = [ commandJson ]; } if (this.isRequestPending == false) { // Do not send a new request while old is still processing. // RequestCount if (this.json.RequestCount == null) { this.json.RequestCount = 0; } this.json.RequestCount += 1; this.isRequestPending = true; let requestUrlHost; if (this.json.EmbeddedUrl != null) { requestUrlHost = new URL("/app.json", this.json.EmbeddedUrl).href } else { requestUrlHost = new URL("/app.json", this.json.RequestUrlHost).href } requestJson.RequestCount = this.json.RequestCount; requestJson.ResponseCount = this.json.ResponseCount; requestJson.BrowserNavigatePathPost = window.location.href; // app.json POST this.httpClient.post<Json>( requestUrlHost, JSON.stringify(requestJson), { withCredentials: true } ) .pipe(catchError((error: HttpErrorResponse) => { // import { catchError } from 'rxjs/operators'; this.isRequestPending = false; return throwError("app.json POST failed!"); // import { throwError } from 'rxjs'; })) .subscribe((data: Json) => { let jsonResponse = data; this.fileDownload(jsonResponse); this.isScrollToTop(jsonResponse); if (this.requestJsonQueue == null) { // Apply response if there is no newer request. // Update UI this.json = jsonResponse; this.isRequestPending = false; // Set application title if (this.json.Title != null) { this.titleService.setTitle(this.json.Title); } } else { this.json.ResponseCount = jsonResponse.ResponseCount; let requestJsonQueue = this.requestJsonQueue; this.requestJsonQueue = undefined; this.isRequestPending = false; if (requestJsonQueue.CommandList != null) { this.update(requestJsonQueue.CommandList[0]); // Process latest request. } } this.json.IsServerSideRendering = false; if (this.json.IsReload) { setTimeout(() => { window.location.reload(); }, 1000); // Wait one second then reload. } if (this.json.NavigatePathAddHistory != null) { this.location.go(this.json.NavigatePathAddHistory, "", this.json.NavigatePathAddHistory); // Put path into state. Angular does not preserve traling slash in location. // import { Location } from '@angular/common'; } }); } else { this.requestJsonQueue = requestJson; } } }