From b489e21561d045ed760c85b983fe8fa4e339bca7 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Mon, 17 Sep 2018 11:26:11 -0400 Subject: [PATCH] LP#1793005 Angular6 Hatch support / printer settings Adds support for Hatch print communication to the Angular(6) app. Migrates the print preferences settings (eg.print.config.*) from in-Hatch settings to server-stored workstation settings. Signed-off-by: Bill Erickson Signed-off-by: blake --- Open-ILS/src/eg2/src/app/common.module.ts | 2 + .../eg2/src/app/share/print/hatch.service.ts | 109 ++++++++++++++++++ .../src/app/share/print/print.component.ts | 33 ++++-- .../app/staff/sandbox/sandbox.component.html | 2 + .../app/staff/sandbox/sandbox.component.ts | 8 ++ Open-ILS/src/sql/Pg/950.data.seed-values.sql | 39 +++++++ .../Pg/upgrade/XXXX.data.hatch-settings.sql | 43 +++++++ .../web/js/ui/default/staff/services/hatch.js | 4 +- 8 files changed, 231 insertions(+), 9 deletions(-) create mode 100644 Open-ILS/src/eg2/src/app/share/print/hatch.service.ts create mode 100644 Open-ILS/src/sql/Pg/upgrade/XXXX.data.hatch-settings.sql diff --git a/Open-ILS/src/eg2/src/app/common.module.ts b/Open-ILS/src/eg2/src/app/common.module.ts index ec06a91b80..f1d4467830 100644 --- a/Open-ILS/src/eg2/src/app/common.module.ts +++ b/Open-ILS/src/eg2/src/app/common.module.ts @@ -14,6 +14,7 @@ They do not have to be added to the providers list. // consider moving these to core... import {FormatService, FormatValuePipe} from '@eg/core/format.service'; +import {HatchService} from '@eg/share/print/hatch.service'; import {PrintService} from '@eg/share/print/print.service'; // Globally available components @@ -67,6 +68,7 @@ export class EgCommonModule { providers: [ DatePipe, CurrencyPipe, + HatchService, PrintService, FormatService ] diff --git a/Open-ILS/src/eg2/src/app/share/print/hatch.service.ts b/Open-ILS/src/eg2/src/app/share/print/hatch.service.ts new file mode 100644 index 0000000000..015088765a --- /dev/null +++ b/Open-ILS/src/eg2/src/app/share/print/hatch.service.ts @@ -0,0 +1,109 @@ +import {Injectable, EventEmitter} from '@angular/core'; + +export class HatchMessage { + msgid: number; + resolver: (HatchMessage) => void; // promise resolver + rejector: (HatchMessage) => void; // promise rejector + status: number; + message: string; // error message + from: string; + action: string; + settings: any; + content: string; + // Response from Hatch. + response: any; + contentType: string; + showDialog: boolean; + + constructor(hash: any) { + if (hash) { + Object.keys(hash).forEach(key => this[key] = hash[key]); + } + } +} + +@Injectable() +export class HatchService { + + isAvailable: boolean; + msgId: number; + messages: {[msgid:number]: HatchMessage}; + + constructor() { + this.isAvailable = null; + this.messages = {}; + this.msgId = 1; + } + + connect(): boolean { + + if (this.isAvailable !== null) { + return this.isAvailable; + } + + // When the Hatch extension loads, it tacks an attribute onto + // the top-level documentElement to indicate it's available. + if (!window.document.documentElement.getAttribute('hatch-is-open')) { + console.warn('Could not connect to Hatch'); + return this.isAvailable = false; + } + + window.addEventListener('message', event => { + + // We only accept messages from our own content script. + if (event.source !== window) { return; } + + // We only care about messages from the Hatch extension. + if (event.data && event.data.from === 'extension') { + + // Avoid logging full Hatch responses. they can get large. + console.debug( + `Hatch responded to message ID ${event.data.msgid}`); + + this.handleResponse(event.data); + } + }); + + return this.isAvailable = true; + } + + // Send a request from the browser to Hatch. + sendRequest(msg: HatchMessage): Promise { + if (this.isAvailable === false) { + return Promise.reject('Hatch is not connected'); + } + + msg.msgid = this.msgId++; + msg.from = 'page'; + this.messages[msg.msgid] = msg; + window.postMessage(msg, window.location.origin); + + return new Promise((resolve, reject) => { + msg.resolver = resolve; + msg.rejector = reject; + }); + } + + // Handle the data sent back to the browser from Hatch. + handleResponse(data: any) { + + const msg = this.messages[data.msgid]; + if (!msg) { + console.warn(`No Hatch request found with ID ${data.msgid}`); + return; + } + + delete this.messages[data.msgid]; + msg.response = data.content; + msg.message = data.message; + msg.status = Number(data.status); + + if (msg.status === 200) { + msg.resolver(msg); + } else { + console.error(`Hatch request returned status ${msg.status}`, msg); + msg.rejector(msg); + } + } +} + diff --git a/Open-ILS/src/eg2/src/app/share/print/print.component.ts b/Open-ILS/src/eg2/src/app/share/print/print.component.ts index 4f6994982b..e7754abbd3 100644 --- a/Open-ILS/src/eg2/src/app/share/print/print.component.ts +++ b/Open-ILS/src/eg2/src/app/share/print/print.component.ts @@ -1,6 +1,8 @@ import {Component, OnInit, TemplateRef, ElementRef, Renderer2} from '@angular/core'; import {PrintService, PrintRequest} from './print.service'; import {StoreService} from '@eg/core/store.service'; +import {ServerStoreService} from '@eg/core/server-store.service'; +import {HatchService, HatchMessage} from './hatch.service'; @Component({ selector: 'eg-print', @@ -26,6 +28,8 @@ export class PrintComponent implements OnInit { private renderer: Renderer2, private elm: ElementRef, private store: StoreService, + private serverStore: ServerStoreService, + private hatch: HatchService, private printer: PrintService) { this.isPrinting = false; this.printQueue = []; @@ -67,7 +71,7 @@ export class PrintComponent implements OnInit { return; } - if (printReq.text && true /* !this.hatch.isActive */) { + if (printReq.text && !this.useHatch()) { // Insert HTML into the browser DOM for in-browser printing only. if (printReq.contentType === 'text/plain') { @@ -109,7 +113,7 @@ export class PrintComponent implements OnInit { show_dialog: printReq.showDialog }); - if (0 /* this.hatch.isActive */) { + if (this.useHatch()) { this.printViaHatch(printReq); } else { // Here the needed HTML is already in the page. @@ -117,17 +121,32 @@ export class PrintComponent implements OnInit { } } + useHatch(): boolean { + return this.store.getLocalItem('eg.hatch.enable.printing') + && this.hatch.connect(); + } + printViaHatch(printReq: PrintRequest) { // Send a full HTML document to Hatch const html = `${printReq.text}`; - /* - this.hatch.print({ - printContext: printReq.printContext, - content: html + this.serverStore.getItem(`eg.print.config.${printReq.printContext}`) + .then(config => { + + const msg = new HatchMessage({ + action: 'print', + content: html, + settings: config || {}, + contentType: 'text/html', + showDialog: printReq.showDialog + }); + + this.hatch.sendRequest(msg).then( + ok => console.debug('Print request succeeded'), + err => console.warn('Print request failed', err) + ); }); - */ } } diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html index 84e127e3c0..54cd87d11e 100644 --- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html +++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html @@ -114,6 +114,8 @@ Hello, {{context.world}}! + +

diff --git a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts index 9b058cd5b1..543e3cb72b 100644 --- a/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts @@ -187,7 +187,15 @@ export class SandboxComponent implements OnInit { text: 'hello', printContext: 'default' }); + } + printWithDialog() { + this.printer.print({ + template: this.printTemplate, + contextData: {world : this.world}, + printContext: 'default', + showDialog: true + }); } changeDate(date) { diff --git a/Open-ILS/src/sql/Pg/950.data.seed-values.sql b/Open-ILS/src/sql/Pg/950.data.seed-values.sql index 3c8a257018..928cdbe766 100644 --- a/Open-ILS/src/sql/Pg/950.data.seed-values.sql +++ b/Open-ILS/src/sql/Pg/950.data.seed-values.sql @@ -19874,6 +19874,45 @@ INSERT INTO config.org_unit_setting_type 'bool' ); + +INSERT INTO config.workstation_setting_type (name, grp, datatype, label) +VALUES ( + 'eg.print.config.default', 'gui', 'object', + oils_i18n_gettext ( + 'eg.print.config.default', + 'Print config for default context', + 'cwst', 'label' + ) +), ( + 'eg.print.config.receipt', 'gui', 'object', + oils_i18n_gettext ( + 'eg.print.config.receipt', + 'Print config for receipt context', + 'cwst', 'label' + ) +), ( + 'eg.print.config.label', 'gui', 'object', + oils_i18n_gettext ( + 'eg.print.config.label', + 'Print config for label context', + 'cwst', 'label' + ) +), ( + 'eg.print.config.mail', 'gui', 'object', + oils_i18n_gettext ( + 'eg.print.config.mail', + 'Print config for mail context', + 'cwst', 'label' + ) +), ( + 'eg.print.config.offline', 'gui', 'object', + oils_i18n_gettext ( + 'eg.print.config.offline', + 'Print config for offline context', + 'cwst', 'label' + ) +); + INSERT INTO config.usr_activity_type (id, ewhat, ehow, egroup, enabled, transient, label) VALUES ( diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.hatch-settings.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.hatch-settings.sql new file mode 100644 index 0000000000..15d9513af7 --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.hatch-settings.sql @@ -0,0 +1,43 @@ +BEGIN; + +--SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version); + +INSERT INTO config.workstation_setting_type (name, grp, datatype, label) +VALUES ( + 'eg.print.config.default', 'gui', 'object', + oils_i18n_gettext ( + 'eg.print.config.default', + 'Print config for default context', + 'cwst', 'label' + ) +), ( + 'eg.print.config.receipt', 'gui', 'object', + oils_i18n_gettext ( + 'eg.print.config.receipt', + 'Print config for receipt context', + 'cwst', 'label' + ) +), ( + 'eg.print.config.label', 'gui', 'object', + oils_i18n_gettext ( + 'eg.print.config.label', + 'Print config for label context', + 'cwst', 'label' + ) +), ( + 'eg.print.config.mail', 'gui', 'object', + oils_i18n_gettext ( + 'eg.print.config.mail', + 'Print config for mail context', + 'cwst', 'label' + ) +), ( + 'eg.print.config.offline', 'gui', 'object', + oils_i18n_gettext ( + 'eg.print.config.offline', + 'Print config for offline context', + 'cwst', 'label' + ) +); + +COMMIT; diff --git a/Open-ILS/web/js/ui/default/staff/services/hatch.js b/Open-ILS/web/js/ui/default/staff/services/hatch.js index 467091aaae..5b6f9235d2 100644 --- a/Open-ILS/web/js/ui/default/staff/services/hatch.js +++ b/Open-ILS/web/js/ui/default/staff/services/hatch.js @@ -200,11 +200,11 @@ angular.module('egCoreMod') } service.getPrintConfig = function(context) { - return service.getRemoteItem('eg.print.config.' + context); + return service.getItem('eg.print.config.' + context); } service.setPrintConfig = function(context, config) { - return service.setRemoteItem('eg.print.config.' + context, config); + return service.setItem('eg.print.config.' + context, config); } service.getPrinterOptions = function(name) { -- 2.43.2