LP1824391 Hatch print-to-file Angular edition user/berick/lpxxx-hatch-omnibus-java-workstations-files
authorBill Erickson <berickxx@gmail.com>
Mon, 15 Apr 2019 15:34:21 +0000 (11:34 -0400)
committerBill Erickson <berickxx@gmail.com>
Fri, 24 May 2019 14:32:32 +0000 (10:32 -0400)
Adds support for the Angular hatch service for sending 'bare' text/plain
print-to-file requests.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/common.module.ts
Open-ILS/src/eg2/src/app/share/print/print.component.ts
Open-ILS/src/eg2/src/app/share/util/htmltotxt.service.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html
Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts

index 80520c7..e083d3c 100644 (file)
@@ -15,6 +15,7 @@ They do not have to be added to the providers list.
 // consider moving these to core...
 import {FormatService, FormatValuePipe} from '@eg/core/format.service';
 import {HatchService} from '@eg/core/hatch.service';
+import {HtmlToTxtService} from '@eg/share/util/htmltotxt.service';
 import {PrintService} from '@eg/share/print/print.service';
 
 // Globally available components
@@ -68,6 +69,7 @@ export class EgCommonModule {
             providers: [
                 DatePipe,
                 CurrencyPipe,
+                HtmlToTxtService,
                 HatchService,
                 PrintService,
                 FormatService
index 33cdcb2..665474b 100644 (file)
@@ -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 = `<html><body>${printReq.text}</body></html>`;
+        if (!printReq.contentType) {
+            printReq.contentType = 'text/html';
+        }
+
+        let content = printReq.text;
+        if (printReq.contentType === 'text/html') {
+            // Send a full HTML document to Hatch
+            content = `<html><body>${printReq.text}</body></html>`;
+        }
 
         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 (file)
index 0000000..e265b3d
--- /dev/null
@@ -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(/&amp;/g, '&');
+        text = text.replace(/&quot;/g, '"');
+        text = text.replace(/&nbsp;/g, ' ');
+        text = text.replace(/&lt;/g, '<');
+        text = text.replace(/&gt;/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 <li> 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.*?>.*?<\/head>/gi, '');
+            line = line.replace(/<br.*?>/gi, '\r\n');
+            line = line.replace(/<table.*?>/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(/<tr.*?>/gi, '');
+            line = line.replace(/<hr.*?>/gi, '\r\n');
+            line = line.replace(/<p.*?>/gi, '');
+            line = line.replace(/<block.*?>/gi, '');
+            line = line.replace(/<li.*?>/gi, ' * ');
+            line = line.replace(/<.+?>/gi, '');
+
+            if (line) { newLines.push(line); }
+        });
+
+        return newLines.join('\n');
+    }
+}
+
index 54cd87d..63d3736 100644 (file)
 <h4>PCRUD auto flesh and FormatService detection</h4>
 <div *ngIf="aMetarecord">Fingerprint: {{aMetarecord}}</div>
 
+
index 543e3cb..bf76fab 100644 (file)
@@ -15,6 +15,7 @@ import {PrintService} from '@eg/share/print/print.service';
 import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
 import {FormatService} from '@eg/core/format.service';
 import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
+import {HtmlToTxtService} from '@eg/share/util/htmltotxt.service';
 
 @Component({
   templateUrl: 'sandbox.component.html'
@@ -73,6 +74,7 @@ export class SandboxComponent implements OnInit {
         private strings: StringService,
         private toast: ToastService,
         private format: FormatService,
+        private h2txt: HtmlToTxtService,
         private printer: PrintService
     ) {
     }
@@ -134,6 +136,9 @@ export class SandboxComponent implements OnInit {
                 idlField: 'metarecord'
             });
         });
+
+        const str = 'C&#xe9;sar&nbsp;&amp;&nbsp;Me';
+        console.log(this.h2txt.htmlToTxt(str));
     }
 
     openEditor() {