From 17f265f1833670227aeec51279f40d30db4aa400 Mon Sep 17 00:00:00 2001 From: Bill Erickson <berickxx@gmail.com> Date: Fri, 12 Apr 2019 12:52:09 -0400 Subject: [PATCH] LP1824391 Hatch File Writer print support Adds support for translating receipt data to plain text and writing the output to a file instead of sending it to a printer. Adds a new stock printer named "Hatch File Writer" to the print configuration interface. Signed-off-by: Bill Erickson <berickxx@gmail.com> Signed-off-by: Jason Boyer <JBoyer@eoli.info> --- .../staff/admin/workstation/t_print_config.tt2 | 26 +++++++-- .../js/ui/default/staff/admin/workstation/app.js | 21 ++++++- Open-ILS/web/js/ui/default/staff/services/hatch.js | 66 +++++++++++++++++++++- Open-ILS/web/js/ui/default/staff/services/print.js | 12 ++-- 4 files changed, 112 insertions(+), 13 deletions(-) diff --git a/Open-ILS/src/templates/staff/admin/workstation/t_print_config.tt2 b/Open-ILS/src/templates/staff/admin/workstation/t_print_config.tt2 index 043a446305..4e4063201f 100644 --- a/Open-ILS/src/templates/staff/admin/workstation/t_print_config.tt2 +++ b/Open-ILS/src/templates/staff/admin/workstation/t_print_config.tt2 @@ -70,7 +70,12 @@ <ul uib-dropdown-menu> <li ng-repeat="printer in printers"> <a href='' ng-click="setPrinter(printer.name)"> - {{printer.name}} + <span ng-if="printer.name == 'hatch_file_writer'"> + [% l('Hatch File Writer') %] + </span> + <span ng-if="printer.name != 'hatch_file_writer'"> + {{printer.name}} + </span> </a> </li> </ul> @@ -81,8 +86,10 @@ <input ng-if="printers[0] && !printConfig[context]" type="text" class="form-control" disabled="disabled" value="[% l('No Printer Selected') %]"> - <input ng-if="printConfig[context].printer" type="text" - class="form-control" disabled="disabled" + <input ng-if="useFileWriter()" type="text" disabled="disabled" + class="form-control" value="[% l('Hatch File Writer') %]"/> + <input ng-if="printConfig[context].printer && !useFileWriter()" + type="text" class="form-control" disabled="disabled" value="{{printConfig[context].printer}}"> </div><!-- /input-group --> </div><!-- col --> @@ -100,7 +107,17 @@ </div> </div><!-- row --> - <div class="row" ng-hide="isTestView || !hatchIsOpen()"> + <div class="pad-vert" + ng-show="!isTestView && hatchIsOpen() && useFileWriter()"> + <div class="alert alert-info"> + [% |l %]Hatch File Writer translates print output to plain text +and writes the content to a text file in the Hatch profile directory. No +additional settings are required.[% END %] + </div> + </div> + + <div class="row" + ng-show="!isTestView && hatchIsOpen() && !useFileWriter()" <div class="col-md-10"> <div class="row"> <div class="col-md-1"></div> @@ -136,7 +153,6 @@ '{{printerOptions.defaultPaperSource}}') %]</span> </div> </div> - <div class="row"> <div class="col-md-1"></div> <div class="col-md-2"> diff --git a/Open-ILS/web/js/ui/default/staff/admin/workstation/app.js b/Open-ILS/web/js/ui/default/staff/admin/workstation/app.js index b8d9a95100..9dfbc9c873 100644 --- a/Open-ILS/web/js/ui/default/staff/admin/workstation/app.js +++ b/Open-ILS/web/js/ui/default/staff/admin/workstation/app.js @@ -279,8 +279,12 @@ function($scope , egCore) { } function loadPrinterOptions(name) { - egCore.hatch.getPrinterOptions(name).then( - function(options) {$scope.printerOptions = options}); + if (name == 'hatch_file_writer') { + $scope.printerOptions = {}; + } else { + egCore.hatch.getPrinterOptions(name).then( + function(options) {$scope.printerOptions = options}); + } } $scope.setPrinter = function(name) { @@ -311,6 +315,13 @@ function($scope , egCore) { } } + $scope.useFileWriter = function() { + return ( + $scope.printConfig[$scope.context] && + $scope.printConfig[$scope.context].printer == 'hatch_file_writer' + ); + } + // Load startup data.... // Don't bother talking to Hatch if it's not there. if (!egCore.hatch.hatchAvailable) return; @@ -320,6 +331,12 @@ function($scope , egCore) { .then(function(printers) { $scope.printers = printers; + printers.push({ + // We need a static name for saving configs. + // Human-friendly label is set in the template. + name: 'hatch_file_writer' + }); + var def = $scope.getPrinterByAttr('is-default', true); if (!def && printers.length) def = printers[0]; 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 6b565201b6..1e907c5c13 100644 --- a/Open-ILS/web/js/ui/default/staff/services/hatch.js +++ b/Open-ILS/web/js/ui/default/staff/services/hatch.js @@ -162,6 +162,13 @@ angular.module('egCoreMod') return service.getPrintConfig(context).then( function(config) { + if (config.printer == 'hatch_file_writer') { + if (contentType == 'text/html') { + content = service.html2txt(content); + } + return service.setRemoteItem( + 'receipt.' + context + '.txt', content, true); + } // print configuration retrieved; print return service.attemptHatchDelivery({ action : 'print', @@ -704,12 +711,15 @@ angular.module('egCoreMod') // set the value for a stored or new item - service.setRemoteItem = function(key, value) { + // When "bare" is true, the value will not be JSON-encoded + // on the file system. + service.setRemoteItem = function(key, value, bare) { service.keyCache[key] = value; return service.attemptHatchDelivery({ key : key, content : value, action : 'set', + bare: bare }); } @@ -1002,6 +1012,60 @@ angular.module('egCoreMod') return $q.when(null); } + // COPIED FROM XUL util/text.js + service.reverse_preserve_string_in_html = function( text ) { + text = text.replace(/&/g, '&'); + text = text.replace(/"/g, '"'); + text = text.replace(/'/g, "'"); + text = text.replace(/ /g, ' '); + text = text.replace(/</g, '<'); + text = text.replace(/>/g, '>'); + return text; + } + + // COPIED FROM XUL util/print.js + service.html2txt = function(html) { + var lines = html.split(/\n/); + var new_lines = []; + for (var i = 0; i < lines.length; i++) { + var line = lines[i]; + if (!line) { + new_lines.push(line); + continue; + } + + // This undoes the util.text.preserve_string_in_html + // call that spine_label.js does + line = service.reverse_preserve_string_in_html(line); + + // This looks for @hex attributes containing 2-digit hex + // codes, and converts them into real characters + line = line.replace(/(<.+?)hex=['"](.+?)['"](.*?>)/gi, + function(str,p1,p2,p3,offset,s) { + + var raw_chars = ''; + var hex_chars = p2.match(/[0-9,a-f,A-F][0-9,a-f,A-F]/g); + for (var j = 0; j < hex_chars.length; j++) { + raw_chars += String.fromCharCode( parseInt(hex_chars[j],16) ); + } + return p1 + p3 + raw_chars; + }); + + line = line.replace(/<head.*?>.*?<\/head>/gi, ''); + line = line.replace(/<br.*?>/gi,'\r\n'); + line = line.replace(/<table.*?>/gi,''); + line = line.replace(/<tr.*?>/gi,''); + line = line.replace(/<hr.*?>/gi,'\r\n'); + line = line.replace(/<p.*?>/gi,''); + line = line.replace(/<block.*?>/gi,''); + line = line.replace(/<li.*?>/gi,' * '); + line = line.replace(/<.+?>/gi,''); + if (line) { new_lines.push(line); } + } + + return new_lines.join('\n'); + } + // The only requirement for opening Hatch is that the DOM be loaded. // Open the connection now so its state will be immediately available. service.openHatch(); diff --git a/Open-ILS/web/js/ui/default/staff/services/print.js b/Open-ILS/web/js/ui/default/staff/services/print.js index d12a6cd84f..ae1108241e 100644 --- a/Open-ILS/web/js/ui/default/staff/services/print.js +++ b/Open-ILS/web/js/ui/default/staff/services/print.js @@ -106,16 +106,18 @@ function($q , $window , $timeout , $http , egHatch , egAuth , egIDL , egOrg , eg if (args.content_type == 'text/html') { promise = service.ingest_print_content( - args.content_type, args.content, args.scope); + args.content_type, args.content, args.scope + ).then(function(html) { + // For good measure, wrap the compiled HTML in container tags. + return "<html><body>" + html + "</body></html>"; + }); } else { // text content requires no compilation for remote printing. promise = $q.when(args.content); } - return promise.then(function(html) { - // For good measure, wrap the compiled HTML in container tags. - html = "<html><body>" + html + "</body></html>"; - service.last_print.content = html; + return promise.then(function(content) { + service.last_print.content = content; service.last_print.context = args.context || 'default'; service.last_print.content_type = args.content_type; service.last_print.show_dialog = args.show_dialog; -- 2.11.0