]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/share/print/print.component.ts
20c056721db0e2bde0084e0434467181b69028da
[Evergreen.git] / Open-ILS / src / eg2 / src / app / share / print / print.component.ts
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';
8
9 @Component({
10     selector: 'eg-print',
11     templateUrl: './print.component.html'
12 })
13
14 export class PrintComponent implements OnInit {
15
16     // Template that requires local processing
17     template: TemplateRef<any>;
18
19     // Context data used for processing the template.
20     context: any;
21
22     // Insertion point for externally-compiled templates
23     htmlContainer: Element;
24
25     isPrinting: boolean;
26
27     printQueue: PrintRequest[];
28
29     constructor(
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;
39         this.printQueue = [];
40     }
41
42     ngOnInit() {
43         this.printer.onPrintRequest$.subscribe(
44             printReq => this.handlePrintRequest(printReq));
45
46         this.htmlContainer =
47             this.renderer.selectRootElement('#eg-print-html-container');
48     }
49
50     handlePrintRequest(printReq: PrintRequest) {
51
52         if (this.isPrinting) {
53             // Avoid print collisions by queuing requests as needed.
54             this.printQueue.push(printReq);
55             return;
56         }
57
58         this.isPrinting = true;
59
60         this.applyTemplate(printReq).then(() => {
61             // Give templates a chance to render before printing
62             setTimeout(() => {
63                 this.dispatchPrint(printReq);
64                 this.reset();
65             });
66         });
67     }
68
69     applyTemplate(printReq: PrintRequest): Promise<any> {
70
71         if (printReq.template) {
72             // Local Angular template.
73             this.template = printReq.template;
74             this.context = {$implicit: printReq.contextData};
75             return Promise.resolve();
76         }
77
78         let promise;
79
80         // Precompiled text
81         if (printReq.text) {
82             promise = Promise.resolve();
83
84         } else if (printReq.templateName || printReq.templateId) {
85             // Server-compiled template
86
87             promise = this.printer.compileRemoteTemplate(printReq).then(
88                 response => {
89                     printReq.text = response.content;
90                     printReq.contentType = response.contentType;
91                 },
92                 err => {
93
94                     if (err && err.notFound) {
95
96                         this.strings.interpolate(
97                             'eg.print.template.not_found',
98                             {name: printReq.templateName}
99                         ).then(msg => this.toast.danger(msg));
100
101                     } else {
102
103                         console.error('Print generation failed', printReq);
104
105                         this.strings.interpolate(
106                             'eg.print.template.error',
107                             {name: printReq.templateName, id: printReq.templateId}
108                         ).then(msg => this.toast.danger(msg));
109                     }
110
111                     return Promise.reject(new Error(
112                         'Error compiling server-hosted print template'));
113                 }
114             );
115
116         } else {
117             console.error('Cannot find template', printReq);
118             return Promise.reject(new Error('Cannot find print template'));
119         }
120
121         return promise.then(() => {
122
123             // Insert HTML into the browser DOM for in-browser printing.
124             if (printReq.text && !this.useHatch()) {
125
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>`;
130                 }
131
132                 this.htmlContainer.innerHTML = printReq.text;
133             }
134         });
135     }
136
137     // Clear the print data
138     reset() {
139         this.isPrinting = false;
140         this.template = null;
141         this.context = null;
142         this.htmlContainer.innerHTML = '';
143
144         if (this.printQueue.length) {
145             this.handlePrintRequest(this.printQueue.pop());
146         }
147     }
148
149     dispatchPrint(printReq: PrintRequest) {
150
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;
155         }
156
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
164         });
165
166         if (this.useHatch()) {
167             this.printViaHatch(printReq);
168         } else {
169             // Here the needed HTML is already in the page.
170             window.print();
171         }
172     }
173
174     useHatch(): boolean {
175         return this.store.getLocalItem('eg.hatch.enable.printing')
176             && this.hatch.connect();
177     }
178
179     printViaHatch(printReq: PrintRequest) {
180
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>`;
185         }
186
187         this.serverStore.getItem(`eg.print.config.${printReq.printContext}`)
188         .then(config => {
189
190             const msg = new HatchMessage({
191                 action: 'print',
192                 content: html,
193                 settings: config || {},
194                 contentType: 'text/html',
195                 showDialog: printReq.showDialog
196             });
197
198             this.hatch.sendRequest(msg).then(
199                 ok  => console.debug('Print request succeeded'),
200                 err => console.warn('Print request failed', err)
201             );
202         });
203     }
204 }
205