From: Bill Erickson Date: Mon, 15 Apr 2019 15:34:21 +0000 (-0400) Subject: LP1824391 Hatch print-to-file Angular edition X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=ade69e7ed53f2d8ea90f8d277a3a9c8c1d2e7730;p=working%2FEvergreen.git LP1824391 Hatch print-to-file Angular edition Adds support for the Angular hatch service for sending 'bare' text/plain print-to-file requests. Signed-off-by: Bill Erickson --- diff --git a/Open-ILS/src/eg2/src/app/app.component.ts b/Open-ILS/src/eg2/src/app/app.component.ts index 3f95092c5a..ae68ffbd23 100644 --- a/Open-ILS/src/eg2/src/app/app.component.ts +++ b/Open-ILS/src/eg2/src/app/app.component.ts @@ -2,7 +2,7 @@ import {Component} from '@angular/core'; @Component({ selector: 'eg-root', - template: '' + template: '' }) export class BaseComponent { diff --git a/Open-ILS/src/eg2/src/app/common.module.ts b/Open-ILS/src/eg2/src/app/common.module.ts index 76394c3924..ad62290554 100644 --- a/Open-ILS/src/eg2/src/app/common.module.ts +++ b/Open-ILS/src/eg2/src/app/common.module.ts @@ -15,6 +15,7 @@ They do not have to be added to the providers list. // consider moving these to core... import {HatchService} from '@eg/share/print/hatch.service'; +import {HtmlToTxtService} from '@eg/share/util/htmltotxt.service'; import {PrintService} from '@eg/share/print/print.service'; // Globally available components @@ -69,6 +70,7 @@ export class EgCommonModule { return { ngModule: EgCommonModule, providers: [ + HtmlToTxtService, HatchService, PrintService ] diff --git a/Open-ILS/src/eg2/src/app/share/print/print.component.ts b/Open-ILS/src/eg2/src/app/share/print/print.component.ts index 33cdcb2641..665474b532 100644 --- a/Open-ILS/src/eg2/src/app/share/print/print.component.ts +++ b/Open-ILS/src/eg2/src/app/share/print/print.component.ts @@ -3,6 +3,8 @@ import {PrintService, PrintRequest} from './print.service'; import {StoreService} from '@eg/core/store.service'; import {ServerStoreService} from '@eg/core/server-store.service'; import {HatchService, HatchMessage} from '@eg/core/hatch.service'; +import {HtmlToTxtService} from '@eg/share/util/htmltotxt.service'; +const HATCH_FILE_WRITER_PRINTER = 'hatch_file_writer'; @Component({ selector: 'eg-print', @@ -31,6 +33,7 @@ export class PrintComponent implements OnInit { private elm: ElementRef, private store: StoreService, private serverStore: ServerStoreService, + private h2txt: HtmlToTxtService, private hatch: HatchService, private printer: PrintService) { this.isPrinting = false; @@ -128,19 +131,43 @@ export class PrintComponent implements OnInit { printViaHatch(printReq: PrintRequest) { - // Send a full HTML document to Hatch - const html = `${printReq.text}`; + if (!printReq.contentType) { + printReq.contentType = 'text/html'; + } + + let content = printReq.text; + if (printReq.contentType === 'text/html') { + // Send a full HTML document to Hatch + content = `${printReq.text}`; + } this.serverStore.getItem(`eg.print.config.${printReq.printContext}`) .then(config => { - const msg = new HatchMessage({ - action: 'print', - content: html, - settings: config || {}, - contentType: 'text/html', - showDialog: printReq.showDialog - }); + let msg: HatchMessage; + + if (config && config.printer === HATCH_FILE_WRITER_PRINTER) { + + const text = printReq.contentType === 'text/plain' ? + content : this.h2txt.htmlToTxt(content); + + msg = new HatchMessage({ + action: 'set', + key: `receipt.${printReq.printContext}.txt`, + content: text, + bare: true + }); + + } else { + + msg = new HatchMessage({ + action: 'print', + content: content, + settings: config || {}, + contentType: 'text/html', + showDialog: printReq.showDialog + }); + } this.hatch.sendRequest(msg).then( ok => console.debug('Print request succeeded'), diff --git a/Open-ILS/src/eg2/src/app/share/util/htmltotxt.service.ts b/Open-ILS/src/eg2/src/app/share/util/htmltotxt.service.ts new file mode 100644 index 0000000000..e265b3d2fa --- /dev/null +++ b/Open-ILS/src/eg2/src/app/share/util/htmltotxt.service.ts @@ -0,0 +1,75 @@ +import {Injectable} from '@angular/core'; + +const ENTITY_REGEX = /&[^\s]+;/; + +/** + * Translates HTML text into plain text. + */ + +@Injectable() +export class HtmlToTxtService { + + unEscapeHtml(text: string): string { + text = text.replace(/&/g, '&'); + text = text.replace(/"/g, '"'); + text = text.replace(/ /g, ' '); + text = text.replace(/</g, '<'); + text = text.replace(/>/g, '>'); + return text; + } + + // https://stackoverflow.com/questions/7394748 + entityToChars(text: string): string { + if (text && text.match(ENTITY_REGEX)) { + const node = document.createElement('textarea'); + node.innerHTML = text; + return node.value; + } + return text; + } + + // Translate an HTML string into plain text. + // Removes HTML elements. + // Replaces
  • with "*" + // Replaces HTML entities with their character equivalent. + htmlToTxt(html: string): string { + if (!html || html === '') { + return ''; + } + + // First remove multi-line comments. + html = html.replace(//gs, ''); + + const lines = html.split(/\n/); + const newLines = []; + + lines.forEach(line => { + + if (!line) { + newLines.push(line); + return; + } + + line = this.unEscapeHtml(line); + line = this.entityToChars(line); + + line = line.replace(/.*?<\/head>/gi, ''); + line = line.replace(//gi, '\r\n'); + line = line.replace(//gi, ''); + line = line.replace(/<\/tr>/gi, '\r\n'); // end of row + line = line.replace(/<\/td>/gi, ' '); // end of cell + line = line.replace(/<\/th>/gi, ' '); // end of th + line = line.replace(//gi, ''); + line = line.replace(//gi, '\r\n'); + line = line.replace(//gi, ''); + line = line.replace(//gi, ''); + line = line.replace(//gi, ' * '); + line = line.replace(/<.+?>/gi, ''); + + if (line) { newLines.push(line); } + }); + + return newLines.join('\n'); + } +} + diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html index 2febd8eb3b..fd37420ee3 100644 --- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html +++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html @@ -363,3 +363,4 @@ + diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts index 740d4d14b8..3f0965a496 100644 --- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts @@ -19,6 +19,7 @@ import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component'; import {FormatService} from '@eg/core/format.service'; import {StringComponent} from '@eg/share/string/string.component'; import {GridComponent} from '@eg/share/grid/grid.component'; +import {HtmlToTxtService} from '@eg/share/util/htmltotxt.service'; @Component({ templateUrl: 'sandbox.component.html' @@ -105,6 +106,7 @@ export class SandboxComponent implements OnInit { private strings: StringService, private toast: ToastService, private format: FormatService, + private h2txt: HtmlToTxtService, private printer: PrintService ) { // BroadcastChannel is not yet defined in PhantomJS and elsewhere @@ -251,6 +253,9 @@ export class SandboxComponent implements OnInit { b.cancel_time('2019-03-25T11:07:59-0400'); this.bresvEditor.mode = 'create'; this.bresvEditor.record = b; + + const str = 'César & Me'; + console.log(this.h2txt.htmlToTxt(str)); } sbChannelHandler = msg => { diff --git a/Open-ILS/src/eg2/src/app/staff/staff.component.html b/Open-ILS/src/eg2/src/app/staff/staff.component.html index 9002fa8e1f..6cc1bc02fd 100644 --- a/Open-ILS/src/eg2/src/app/staff/staff.component.html +++ b/Open-ILS/src/eg2/src/app/staff/staff.component.html @@ -21,3 +21,7 @@ + + + +