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
text/typescript
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;
}
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
private jsonServerSideRendering: any,
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;
}
}
}