1 import {Component, OnInit, TemplateRef, ElementRef, Renderer2} from '@angular/core';
2 import {PrintService, PrintRequest} from './print.service';
3 import {StoreService} from '@eg/core/store.service';
4 import {ServerStoreService} from '@eg/core/server-store.service';
5 import {HatchService, HatchMessage} from './hatch.service';
6 import {ToastService} from '@eg/share/toast/toast.service';
7 import {StringService} from '@eg/share/string/string.service';
11 templateUrl: './print.component.html'
14 export class PrintComponent implements OnInit {
16 // Template that requires local processing
17 template: TemplateRef<any>;
19 // Context data used for processing the template.
22 // Insertion point for externally-compiled templates
23 htmlContainer: Element;
27 printQueue: PrintRequest[];
30 private renderer: Renderer2,
31 private elm: ElementRef,
32 private store: StoreService,
33 private serverStore: ServerStoreService,
34 private hatch: HatchService,
35 private toast: ToastService,
36 private strings: StringService,
37 private printer: PrintService) {
38 this.isPrinting = false;
43 this.printer.onPrintRequest$.subscribe(
44 printReq => this.handlePrintRequest(printReq));
47 this.renderer.selectRootElement('#eg-print-html-container');
50 handlePrintRequest(printReq: PrintRequest) {
52 if (this.isPrinting) {
53 // Avoid print collisions by queuing requests as needed.
54 this.printQueue.push(printReq);
58 this.isPrinting = true;
60 this.applyTemplate(printReq).then(() => {
61 // Give templates a chance to render before printing
63 this.dispatchPrint(printReq);
69 applyTemplate(printReq: PrintRequest): Promise<any> {
71 if (printReq.template) {
72 // Local Angular template.
73 this.template = printReq.template;
74 this.context = {$implicit: printReq.contextData};
75 return Promise.resolve();
82 promise = Promise.resolve();
84 } else if (printReq.templateName || printReq.templateId) {
85 // Server-compiled template
87 promise = this.printer.compileRemoteTemplate(printReq).then(
89 printReq.text = response.content;
90 printReq.contentType = response.contentType;
94 if (err && err.notFound) {
96 this.strings.interpolate(
97 'eg.print.template.not_found',
98 {name: printReq.templateName}
99 ).then(msg => this.toast.danger(msg));
103 console.error('Print generation failed', printReq);
105 this.strings.interpolate(
106 'eg.print.template.error',
107 {name: printReq.templateName, id: printReq.templateId}
108 ).then(msg => this.toast.danger(msg));
111 return Promise.reject(new Error(
112 'Error compiling server-hosted print template'));
117 console.error('Cannot find template', printReq);
118 return Promise.reject(new Error('Cannot find print template'));
121 return promise.then(() => {
123 // Insert HTML into the browser DOM for in-browser printing.
124 if (printReq.text && !this.useHatch()) {
126 if (printReq.contentType === 'text/plain') {
127 // Wrap text/plain content in pre's to prevent
128 // unintended html formatting.
129 printReq.text = `<pre>${printReq.text}</pre>`;
132 this.htmlContainer.innerHTML = printReq.text;
137 // Clear the print data
139 this.isPrinting = false;
140 this.template = null;
142 this.htmlContainer.innerHTML = '';
144 if (this.printQueue.length) {
145 this.handlePrintRequest(this.printQueue.pop());
149 dispatchPrint(printReq: PrintRequest) {
151 if (!printReq.text) {
152 // Sometimes the results come from an externally-parsed HTML
153 // template, other times they come from an in-page template.
154 printReq.text = this.elm.nativeElement.innerHTML;
157 // Retain a copy of each printed document in localStorage
158 // so it may be reprinted.
159 this.store.setLocalItem('eg.print.last_printed', {
160 content: printReq.text,
161 context: printReq.printContext,
162 content_type: printReq.contentType,
163 show_dialog: printReq.showDialog
166 if (this.useHatch()) {
167 this.printViaHatch(printReq);
169 // Here the needed HTML is already in the page.
174 useHatch(): boolean {
175 return this.store.getLocalItem('eg.hatch.enable.printing')
176 && this.hatch.connect();
179 printViaHatch(printReq: PrintRequest) {
181 // Send a full HTML document to Hatch
182 let html = printReq.text;
183 if (printReq.contentType === 'text/html') {
184 html = `<html><body>${printReq.text}</body></html>`;
187 this.serverStore.getItem(`eg.print.config.${printReq.printContext}`)
190 const msg = new HatchMessage({
193 settings: config || {},
194 contentType: 'text/html',
195 showDialog: printReq.showDialog
198 this.hatch.sendRequest(msg).then(
199 ok => console.debug('Print request succeeded'),
200 err => console.warn('Print request failed', err)