LP#1793005 Angular6 Hatch support / printer settings
[working/Evergreen.git] / Open-ILS / src / eg2 / src / app / share / print / hatch.service.ts
1 import {Injectable, EventEmitter} from '@angular/core';
2
3 export class HatchMessage {
4     msgid: number;
5     resolver: (HatchMessage) => void; // promise resolver
6     rejector: (HatchMessage) => void; // promise rejector
7     status: number;
8     message: string; // error message
9     from: string;
10     action: string;
11     settings: any;
12     content: string;
13     // Response from Hatch.
14     response: any;
15     contentType: string;
16     showDialog: boolean;
17
18     constructor(hash: any) {
19         if (hash) {
20             Object.keys(hash).forEach(key => this[key] = hash[key]);
21         }
22     }
23 }
24
25 @Injectable()
26 export class HatchService {
27
28     isAvailable: boolean;
29     msgId: number;
30     messages: {[msgid:number]: HatchMessage};
31
32     constructor() {
33         this.isAvailable = null;
34         this.messages = {};
35         this.msgId = 1;
36     }
37
38     connect(): boolean {
39
40         if (this.isAvailable !== null) {
41             return this.isAvailable;
42         }
43
44         // When the Hatch extension loads, it tacks an attribute onto
45         // the top-level documentElement to indicate it's available.
46         if (!window.document.documentElement.getAttribute('hatch-is-open')) {
47             console.warn('Could not connect to Hatch');
48             return this.isAvailable = false;
49         }
50
51         window.addEventListener('message', event => {
52
53             // We only accept messages from our own content script.
54             if (event.source !== window) { return; }
55
56             // We only care about messages from the Hatch extension.
57             if (event.data && event.data.from === 'extension') {
58
59                 // Avoid logging full Hatch responses. they can get large.
60                 console.debug(
61                     `Hatch responded to message ID ${event.data.msgid}`);
62
63                 this.handleResponse(event.data);
64             }
65         }); 
66
67         return this.isAvailable = true;
68     }
69
70     // Send a request from the browser to Hatch.
71     sendRequest(msg: HatchMessage): Promise<HatchMessage> {
72         if (this.isAvailable === false) {
73             return Promise.reject('Hatch is not connected');
74         }
75
76         msg.msgid = this.msgId++;
77         msg.from = 'page';
78         this.messages[msg.msgid] = msg;
79         window.postMessage(msg, window.location.origin);
80
81         return new Promise((resolve, reject) => {
82             msg.resolver = resolve;
83             msg.rejector = reject;
84         });
85     }
86
87     // Handle the data sent back to the browser from Hatch.
88     handleResponse(data: any) {
89
90         const msg = this.messages[data.msgid]; 
91         if (!msg) {
92             console.warn(`No Hatch request found with ID ${data.msgid}`);
93             return;
94         }
95
96         delete this.messages[data.msgid];
97         msg.response = data.content;
98         msg.message = data.message;
99         msg.status = Number(data.status);
100
101         if (msg.status === 200) {
102             msg.resolver(msg);
103         } else {
104             console.error(`Hatch request returned status ${msg.status}`, msg);
105             msg.rejector(msg);
106         }
107     }
108 }
109