]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/share/print/print.component.ts
LP1825896 Store workstations in Hatch when available
[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 '@eg/core/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     useHatch: boolean;
30
31     constructor(
32         private renderer: Renderer2,
33         private elm: ElementRef,
34         private store: StoreService,
35         private serverStore: ServerStoreService,
36         private hatch: HatchService,
37         private toast: ToastService,
38         private strings: StringService,
39         private printer: PrintService) {
40         this.isPrinting = false;
41         this.printQueue = [];
42     }
43
44     ngOnInit() {
45         this.printer.onPrintRequest$.subscribe(
46             printReq => this.handlePrintRequest(printReq));
47
48         this.htmlContainer =
49             this.renderer.selectRootElement('#eg-print-html-container');
50
51         this.serverStore.getItem('eg.hatch.enable.printing')
52             .then(use => this.useHatch = use);
53     }
54
55     handlePrintRequest(printReq: PrintRequest) {
56
57         if (this.isPrinting) {
58             // Avoid print collisions by queuing requests as needed.
59             this.printQueue.push(printReq);
60             return;
61         }
62
63         this.isPrinting = true;
64
65         this.applyTemplate(printReq).then(() => {
66             // Give templates a chance to render before printing
67             setTimeout(() => {
68                 this.dispatchPrint(printReq);
69                 this.reset();
70             });
71         });
72     }
73
74     applyTemplate(printReq: PrintRequest): Promise<any> {
75
76         if (printReq.template) {
77             // Local Angular template.
78             this.template = printReq.template;
79             this.context = {$implicit: printReq.contextData};
80             return Promise.resolve();
81         }
82
83         let promise;
84
85         // Precompiled text
86         if (printReq.text) {
87             promise = Promise.resolve();
88
89         } else if (printReq.templateName || printReq.templateId) {
90             // Server-compiled template
91
92             promise = this.printer.compileRemoteTemplate(printReq).then(
93                 response => {
94                     printReq.text = response.content;
95                     printReq.contentType = response.contentType;
96                 },
97                 err => {
98
99                     if (err && err.notFound) {
100
101                         this.strings.interpolate(
102                             'eg.print.template.not_found',
103                             {name: printReq.templateName}
104                         ).then(msg => this.toast.danger(msg));
105
106                     } else {
107
108                         console.error('Print generation failed', printReq);
109
110                         this.strings.interpolate(
111                             'eg.print.template.error',
112                             {name: printReq.templateName, id: printReq.templateId}
113                         ).then(msg => this.toast.danger(msg));
114                     }
115
116                     return Promise.reject(new Error(
117                         'Error compiling server-hosted print template'));
118                 }
119             );
120
121         } else {
122             console.error('Cannot find template', printReq);
123             return Promise.reject(new Error('Cannot find print template'));
124         }
125
126         return promise.then(() => {
127
128             // Insert HTML into the browser DOM for in-browser printing.
129             if (printReq.text && !this.useHatch()) {
130
131                 if (printReq.contentType === 'text/plain') {
132                 // Wrap text/plain content in pre's to prevent
133                 // unintended html formatting.
134                     printReq.text = `<pre>${printReq.text}</pre>`;
135                 }
136
137                 this.htmlContainer.innerHTML = printReq.text;
138             }
139         });
140     }
141
142     // Clear the print data
143     reset() {
144         this.isPrinting = false;
145         this.template = null;
146         this.context = null;
147         this.htmlContainer.innerHTML = '';
148
149         if (this.printQueue.length) {
150             this.handlePrintRequest(this.printQueue.pop());
151         }
152     }
153
154     dispatchPrint(printReq: PrintRequest) {
155
156         if (!printReq.text) {
157             // Sometimes the results come from an externally-parsed HTML
158             // template, other times they come from an in-page template.
159             printReq.text = this.elm.nativeElement.innerHTML;
160         }
161
162         // Retain a copy of each printed document in localStorage
163         // so it may be reprinted.
164         this.store.setLocalItem('eg.print.last_printed', {
165             content: printReq.text,
166             context: printReq.printContext,
167             content_type: printReq.contentType,
168             show_dialog: printReq.showDialog
169         });
170
171         if (this.useHatch) {
172             this.printViaHatch(printReq);
173         } else {
174             // Here the needed HTML is already in the page.
175             window.print();
176         }
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