LP#1775466 printer uses template parser
authorBill Erickson <berickxx@gmail.com>
Wed, 20 Jun 2018 21:32:31 +0000 (17:32 -0400)
committerBill Erickson <berickxx@gmail.com>
Wed, 5 Sep 2018 14:05:23 +0000 (10:05 -0400)
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.html
Open-ILS/src/eg2/src/app/share/print/print.component.ts
Open-ILS/src/eg2/src/app/share/print/print.service.ts
Open-ILS/src/eg2/src/app/share/util/parser.service.ts
Open-ILS/src/eg2/src/app/staff/common.module.ts
Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts

index e04e003..dd3c201 100644 (file)
@@ -17,6 +17,7 @@ import {PcrudService} from '@eg/core/pcrud.service';
 import {OrgService} from '@eg/core/org.service';
 import {AudioService} from '@eg/share/util/audio.service';
 import {FormatService} from '@eg/share/util/format.service';
+import {TemplateParserService} from '@eg/share/util/parser.service';
 import {PrintService} from '@eg/share/print/print.service';
 
 // Globally available components
@@ -72,7 +73,8 @@ export class EgCommonModule {
                 OrgService,
                 PrintService,
                 AudioService,
-                FormatService
+                FormatService,
+                TemplateParserService
             ]
         };
     }
index 08e2cc6..2f72bda 100644 (file)
@@ -1,18 +1,10 @@
 
+<!-- there should only be one container active at a time -->
 <div id='eg-print-container'>
   <ng-container *ngIf="template">
     <!-- refs to compiled templates are inserted inline -->
     <ng-container *ngTemplateOutlet="template; context:context">
     </ng-container>
   </ng-container>
-
-  <!-- This component only works with JIT compilation 
-
-  <ng-container *ngIf="templateString">
-    <eg-dynamic-component [content]="templateString" 
-      [contextData]="this.context.$implicit">
-    </eg-dynamic-component>
-  </ng-container>
-  -->
 </div>
 
index 53762d6..ad41e5e 100644 (file)
@@ -1,6 +1,6 @@
-import {Component, OnInit, TemplateRef, ElementRef} from '@angular/core';
-// See dynamic.component for details on why it's commented out.
+import {Component, OnInit, TemplateRef, ElementRef, Renderer2} from '@angular/core';
 import {PrintService, PrintRequest} from './print.service';
+import {TemplateParserService} from '@eg/share/util/parser.service';
 
 @Component({
     selector: 'eg-print',
@@ -9,47 +9,100 @@ import {PrintService, PrintRequest} from './print.service';
 
 export class PrintComponent implements OnInit {
 
+    // Template that requires local processing
     template: TemplateRef<any>;
-    //templateString: string;
+
+    // TemplateParserService-compatible template string.  
+    templateString: string;
+
+    // Context data used for processing the template.
     context: any;
 
+    htmlContainer: Element;
+
+    // Final HTML print string
+    htmlResult: string;
+  
     constructor(
+        private renderer: Renderer2,
         private elm: ElementRef,
+        private parser: TemplateParserService,
         private printer: PrintService
     ) {}
 
     ngOnInit() {
         this.printer.onPrintRequest$.subscribe(
             printReq => this.handlePrintRequest(printReq));
+
+        this.htmlContainer = 
+            this.renderer.selectRootElement('#eg-print-container');
     }
 
     handlePrintRequest(printReq: PrintRequest) {
-        this.template = printReq.template;
-        //this.templateString = printReq.templateString;
-        this.context = {$implicit: printReq.contextData};
+        this.applyTemplate(printReq).then(ok => {
+            // Give templates a chance to render before printing
+            setTimeout(() => this.dispatchPrint(printReq));
+        });
+    }
+
+    applyTemplate(printReq: PrintRequest): Promise<void> {
+        return new Promise((resolve, reject) => {
+
+            if (printReq.template) {
+                // Inline template.  Let Angular do the work.
+                this.template = printReq.template;
+                this.context = {$implicit: printReq.contextData};
+                resolve();
+            }
+
+            let promise;
+            if (printReq.templateString) {
+
+                promise = this.parser.apply(
+                    printReq.templateString, printReq.contextData);
+
+            } else if (printReq.htmlString) {
+                promise = Promise.resolve(printReq.htmlString);
+            }
 
-        // Give the template a chance to render inline before printing
-        setTimeout(() => this.dispatchPrint(printReq));
+            promise.then(html => {
+                this.htmlResult = html;
+
+                if (true /* !this.hatch.isActive */) {
+
+                    // Only insert the HTML into the browser DOM when
+                    // printing locally
+                    this.htmlContainer.innerHTML = this.htmlResult;
+                }
+
+                resolve();
+            });
+        });
     }
 
-    dispatchPrint(printReq) {
-        /*
-        if (this.hatch.isActive) {
-            this.printViaHatch();
+    dispatchPrint(printReq: PrintRequest) {
+        if (0 /*this.hatch.isActive*/) {
+            this.printViaHatch(printReq);
         } else {
-        */
+            // Here the needed HTML is already in the page.
             window.print();
-        // }
+        }
     }
 
-    /*
-    printViaHatch(printReq) {
+    printViaHatch(printReq: PrintRequest) {
+
+        if (!this.htmlResult) {
+            // Sometimes the results come from an externally-parsed HTML 
+            // template, other times they come from an in-page template.
+            this.htmlResult = this.elm.nativeElement.innerHTML;
+        }
+
+        /*
         this.hatch.print({
             printContext: printReq.printContext,
-            content: this.elm.nativeElement.innerHTML
+            content: this.htmlResult
         });
+        */
     }
-    */
-
 }
 
index 3460d8a..2825af0 100644 (file)
@@ -1,9 +1,11 @@
 import {Injectable, EventEmitter, TemplateRef} from '@angular/core';
 
 export interface PrintRequest {
-    template: TemplateRef<any>;
-    //templateString?: string,
-    contextData: any;
+    template?: TemplateRef<any>;
+    templateString?: string;
+    templateName?: string; // TODO
+    htmlString?: string,
+    contextData?: any;
     printContext: string;
 }
 
index cbe3830..165866d 100644 (file)
@@ -239,21 +239,33 @@ class ParserInstance {
     getContextStringValue(dotpath: string): string {
 
         // Variable replacements may contain filters.
-        const pieces = dotpath.split('|');
-        const path = pieces[0].trim();
+        const pieces = dotpath.split('|').map(p => p.trim());
+        const path = pieces[0]
         const filter = pieces[1];
         const data = {
+            datatype: null, // potentially applied below
             value: this.getContextValueAt(path)
         };
 
-        // Apply some minimal filter handling for now
         // TODO: teach the format service about processing due dates.
         if (filter) {
-            filter = filter.trim();
-            if (filter.startsWith('date')) {
-                data.datatype = 'timestamp';
-            } else if (filter.startsWith('currency')) {
-                data.datatype = 'money';
+            const fParts = filter.split(':').map(p => p.trim());
+
+            switch (fParts[0]) {
+                case 'date':
+                    data.datatype = 'timestamp';
+                    break;
+                case 'currency':
+                    data.datatype = 'money';
+                    break;
+                case 'limitTo':
+                    const size = fParts[1];
+                    const offset = fParts[2] || 0;
+                    if (size) {
+                        data.value = 
+                            data.value.substring(offset, offset + size);
+                    }
+                    break;
             }
         }
 
index 6527a66..2dfbb3c 100644 (file)
@@ -10,7 +10,6 @@ import {ToastService} from '@eg/share/toast/toast.service';
 import {ToastComponent} from '@eg/share/toast/toast.component';
 import {StringComponent} from '@eg/share/string/string.component';
 import {StringService} from '@eg/share/string/string.service';
-import {TemplateParserService} from '@eg/share/util/parser.service';
 import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
 import {DateSelectComponent} from '@eg/share/date-select/date-select.component';
 
@@ -54,8 +53,7 @@ export class StaffCommonModule {
             providers: [ // Export staff-wide services
                 AccessKeyService,
                 StringService,
-                ToastService,
-                TemplateParserService
+                ToastService
             ]
         };
     }
index 46dcf9d..521db03 100644 (file)
@@ -145,7 +145,7 @@ export class SandboxComponent implements OnInit {
               <ol>
                 <li ng-repeat="copy in copies">
                   <div>Barcode: {{copy.barcode}}</div>
-                  <div>Title: {{copy.title}}</div>
+                  <div>Title: {{copy.title | limitTo:10}}</div>
                   <div ng-repeat="part in copy.parts">
                     part = {{part}}
                   </div>
@@ -181,8 +181,19 @@ export class SandboxComponent implements OnInit {
             ]
         }
 
+        /*
         this.parser.apply(template, context).then(html => {
-            console.log('parsed: ', html);
+            this.printer.print({
+                htmlString: html,
+                printContext: 'default'
+            });
+        });
+        */
+
+        this.printer.print({
+            templateString: template,
+            contextData: context,
+            printContext: 'default'
         });
     }
 }