From 5efce1eea4acb96e7dfb46ba86d4a206879186f8 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Mon, 16 Jun 2014 17:39:51 -0400 Subject: [PATCH] printing improvemetns; decouple some from hatch Signed-off-by: Bill Erickson --- Open-ILS/src/templates/staff/base_js.tt2 | 1 + .../src/templates/staff/circ/patron/t_checkout.tt2 | 13 +- Open-ILS/web/js/ui/default/staff/Gruntfile.js | 1 + .../js/ui/default/staff/admin/workstation/app.js | 37 ++-- .../web/js/ui/default/staff/circ/patron/app.js | 17 +- .../web/js/ui/default/staff/circ/patron/bills.js | 17 +- .../js/ui/default/staff/circ/patron/checkout.js | 43 +++-- .../web/js/ui/default/staff/circ/services/circ.js | 10 +- .../web/js/ui/default/staff/services/coresvc.js | 5 +- Open-ILS/web/js/ui/default/staff/services/hatch.js | 167 ++---------------- Open-ILS/web/js/ui/default/staff/services/print.js | 187 +++++++++++++++++++++ .../ui/default/staff/services/print_templates.js | 0 .../web/js/ui/default/staff/test/karma.conf.js | 1 + 13 files changed, 291 insertions(+), 208 deletions(-) create mode 100644 Open-ILS/web/js/ui/default/staff/services/print.js delete mode 100644 Open-ILS/web/js/ui/default/staff/services/print_templates.js diff --git a/Open-ILS/src/templates/staff/base_js.tt2 b/Open-ILS/src/templates/staff/base_js.tt2 index e56cf474c0..76bc5a32a8 100644 --- a/Open-ILS/src/templates/staff/base_js.tt2 +++ b/Open-ILS/src/templates/staff/base_js.tt2 @@ -25,6 +25,7 @@ + diff --git a/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2 index abb054f3bc..44712d58fb 100644 --- a/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2 +++ b/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2 @@ -84,13 +84,18 @@
-
- - [% l('Auto-Print') %] +
+
-
+
+
+ +
diff --git a/Open-ILS/web/js/ui/default/staff/Gruntfile.js b/Open-ILS/web/js/ui/default/staff/Gruntfile.js index 303cc565bf..883d6dbbfc 100644 --- a/Open-ILS/web/js/ui/default/staff/Gruntfile.js +++ b/Open-ILS/web/js/ui/default/staff/Gruntfile.js @@ -93,6 +93,7 @@ module.exports = function(grunt) { 'services/org.js', 'services/startup.js', 'services/hatch.js', + 'services/print.js', 'services/coresvc.js', 'services/navbar.js', 'services/statusbar.js', 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 2a635e88c9..1dcc683688 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 @@ -266,25 +266,24 @@ function($scope , egCore) { $scope.testPrint = function(withDialog) { if ($scope.contentType == 'text/plain') { - egCore.hatch.print( - $scope.context, - $scope.contentType, - $scope.textPrintContent, - null, - withDialog - ); + egCore.print.print({ + context : $scope.context, + content_type : $scope.contentType, + content : $scope.textPrintContent, + show_dialog : withDialog + }); } else { - egCore.hatch.print( - $scope.context, - $scope.contentType, - $scope.htmlPrintContent, - { + egCore.print.print({ + context : $scope.context, + content_type : $scope.contentType, + content : $scope.htmlPrintContent, + scope : { value1 : 'Value One', value2 : 'Value Two', date_value : '2015-02-04T14:04:34-0400' }, - withDialog - ); + show_dialog : withDialog + }); } } @@ -333,10 +332,6 @@ function($scope , $q , egCore) { } $scope.preview_scope = { - current_location : egCore.idl.toHash( - egCore.org.get(egCore.auth.user().ws_ou())), - today : new Date(), - //bills transactions : [ { @@ -397,7 +392,6 @@ function($scope , $q , egCore) { }, title : seed_record.title, author : seed_record.author, - staff : egCore.idl.toHash(egCore.auth.user()), patron : egCore.idl.toHash(egCore.auth.user()), address : seed_addr } @@ -411,9 +405,12 @@ function($scope , $q , egCore) { $scope.preview_scope.payments[1].xact.title = seed_record.title; $scope.preview_scope.payments[1].xact.copy_barcode = seed_copy.barcode; + // today, staff, current_location, etc. + egCore.print.fleshPrintScope($scope); + $scope.template_changed = function() { $scope.print.load_failed = false; - egCore.hatch.getPrintTemplate($scope.print.template_name) + egCore.print.getPrintTemplate($scope.print.template_name) .then( function(html) { $scope.print.template_content = html; diff --git a/Open-ILS/web/js/ui/default/staff/circ/patron/app.js b/Open-ILS/web/js/ui/default/staff/circ/patron/app.js index 6662f65acc..c8318181a7 100644 --- a/Open-ILS/web/js/ui/default/staff/circ/patron/app.js +++ b/Open-ILS/web/js/ui/default/staff/circ/patron/app.js @@ -506,9 +506,13 @@ function($scope, $q, $location , $filter, egCore, egUser, patronSvc) { $scope.summary_stat_cats = function() { return patronSvc.summary_stat_cats } $scope.print_address = function(addr) { - egCore.hatch.printFromTemplate('default', 'patron_address', { - patron : egCore.idl.toHash(patronSvc.current), - address : egCore.idl.toHash(addr) + egCore.print.print({ + context : 'default', + template : 'patron_address', + scope : { + patron : egCore.idl.toHash(patronSvc.current), + address : egCore.idl.toHash(addr) + } }); } }]) @@ -1161,8 +1165,11 @@ function($scope, $routeParams , $location , egCore , patronSvc , $modal) { $scope.printNote = function(note) { var hash = egCore.idl.toHash(note); hash.usr = egCore.idl.toHash($scope.patron()); - egCore.hatch.printFromTemplate( - 'default', 'patron_note', {note : hash}); + egCore.print.print({ + context : 'default', + template : 'patron_note', + scope : {note : hash} + }); } // perform the initial note fetch diff --git a/Open-ILS/web/js/ui/default/staff/circ/patron/bills.js b/Open-ILS/web/js/ui/default/staff/circ/patron/bills.js index f6e78332c6..5b83989bfe 100644 --- a/Open-ILS/web/js/ui/default/staff/circ/patron/bills.js +++ b/Open-ILS/web/js/ui/default/staff/circ/patron/bills.js @@ -321,8 +321,11 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location, print_data.payment_applied * 100) / 100; for (var i = 0; i < $scope.receipt_count; i++) { - egCore.hatch.printFromTemplate( - 'receipt', 'bill_payment', print_data); + egCore.print.print({ + context : 'receipt', + template : 'bill_payment', + scope : print_data + }); } } @@ -403,13 +406,15 @@ function($scope , $q , $routeParams , egCore , egConfirmDialog , $location, {authoritative : true} ).then( function() { - egCore.hatch.printFromTemplate( - 'receipt', 'bills_current', - { transactions : xacts, + egCore.print.print({ + context : 'receipt', + template : 'bills_current', + scope : { + transactions : xacts, current_location : egCore.idl.toHash( egCore.org.get(egCore.auth.user().ws_ou())) } - ); + }); }, null, function(xact) { diff --git a/Open-ILS/web/js/ui/default/staff/circ/patron/checkout.js b/Open-ILS/web/js/ui/default/staff/circ/patron/checkout.js index c9bfc00722..e8a31516a4 100644 --- a/Open-ILS/web/js/ui/default/staff/circ/patron/checkout.js +++ b/Open-ILS/web/js/ui/default/staff/circ/patron/checkout.js @@ -5,10 +5,10 @@ angular.module('egPatronApp').controller('PatronCheckoutCtrl', ['$scope','$q','$modal','$routeParams','egCore','egUser','patronSvc', - 'egGridDataProvider','$location','egCirc', + 'egGridDataProvider','$location','$timeout','egCirc', function($scope , $q , $modal , $routeParams , egCore , egUser , patronSvc , - egGridDataProvider , $location , egCirc) { + egGridDataProvider , $location , $timeout , egCirc) { $scope.initTab('checkout', $routeParams.id); $scope.focusMe = true; @@ -23,8 +23,12 @@ function($scope , $q , $modal , $routeParams , egCore , egUser , patronSvc , } }); - egCirc.get_circ_mods().then(function(list) { - $scope.circModifiers = list; + var printOnComplete = true; + egCore.org.settings([ + 'circ.staff_client.do_not_auto_attempt_print' + ]).then(function(settings) { + printOnComplete = !Boolean( + settings['circ.staff_client.do_not_auto_attempt_print']); }); egCirc.get_noncat_types().then(function(list) { @@ -123,20 +127,37 @@ function($scope , $q , $modal , $routeParams , egCore , egUser , patronSvc , } } + // TODO: show print dialog $scope.print_receipt = function() { - var print_data = { - circulations : [], - staff : egCore.idl.toHash(egCore.auth.user()), - current_location : egCore.idl.toHash( - egCore.org.get(egCore.auth.user().ws_ou())) - } + var print_data = {circulations : []} + + if ($scope.checkouts.length == 0) return $q.when(); + angular.forEach($scope.checkouts, function(co) { var circ = egCore.idl.toHash(co.payload.circ); circ.title = co.payload.record.title; print_data.circulations.push(circ); }); - egCore.hatch.printFromTemplate('default', 'checkout', print_data); + return egCore.print.print({ + context : 'default', + template : 'checkout', + scope : print_data + }); + } + + // Redirect the user to the barcode entry page to load a new patron. + // If configured to do so, print the receipt first + $scope.done = function() { + if (printOnComplete) { + + $scope.print_receipt().then(function() { + $location.path('/circ/patron/bcsearch'); + }); + + } else { + $location.path('/circ/patron/bcsearch'); + } } }]) diff --git a/Open-ILS/web/js/ui/default/staff/circ/services/circ.js b/Open-ILS/web/js/ui/default/staff/circ/services/circ.js index 2fd18a7730..05a947ac8f 100644 --- a/Open-ILS/web/js/ui/default/staff/circ/services/circ.js +++ b/Open-ILS/web/js/ui/default/staff/circ/services/circ.js @@ -425,13 +425,10 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) { transit : egCore.idl.toHash(transit), title : evt.payload.record.title(), author : evt.payload.record.author(), - staff : egCore.idl.toHash(egCore.auth.user()), copy : egCore.idl.toHash(evt.payload.copy), dest_location : egCore.idl.toHash(egCore.org.get(transit.dest())), dest_address : egCore.idl.toHash(destAddr), - current_location : egCore.idl.toHash( - egCore.org.get(egCore.auth.user().ws_ou())) } var template = 'transit_slip'; @@ -441,8 +438,11 @@ function($modal , $q , egCore , egAlertDialog , egConfirmDialog) { print_context.patron = egCore.idl.toHash(holdUser); } - egCore.hatch.printFromTemplate( - 'default', template, print_context); + egCore.print.print({ + context : 'default', + template : template, + scope : print_context + }); } }], resolve : { diff --git a/Open-ILS/web/js/ui/default/staff/services/coresvc.js b/Open-ILS/web/js/ui/default/staff/services/coresvc.js index 8bedf05e25..690997849c 100644 --- a/Open-ILS/web/js/ui/default/staff/services/coresvc.js +++ b/Open-ILS/web/js/ui/default/staff/services/coresvc.js @@ -9,9 +9,9 @@ angular.module('egCoreMod') .factory('egCore', ['egIDL','egNet','egEnv','egOrg','egPCRUD','egEvent','egAuth', - 'egPerm','egHatch','egStartup','egStrings', + 'egPerm','egHatch','egPrint','egStartup','egStrings', function(egIDL , egNet , egEnv , egOrg , egPCRUD , egEvent , egAuth , - egPerm , egHatch , egStartup , egStrings) { + egPerm , egHatch , egPrint , egStartup , egStrings) { return { idl : egIDL, @@ -23,6 +23,7 @@ function(egIDL , egNet , egEnv , egOrg , egPCRUD , egEvent , egAuth , auth : egAuth, perm : egPerm, hatch : egHatch, + print : egPrint, startup : egStartup, strings : egStrings }; 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 099aa0daa3..bd3f178a29 100644 --- a/Open-ILS/web/js/ui/default/staff/services/hatch.js +++ b/Open-ILS/web/js/ui/default/staff/services/hatch.js @@ -11,9 +11,6 @@ * Most handlers also provide direct remote and local variants to the * application can decide to which to use as needed. * - * Printing is handled locally with an egPrintContainer whose contents - * are made visible during printing using CSS print media. - * * Local storage requests are handled by $window.localStorage. * * Note that all top-level and remote requests return promises. All @@ -28,8 +25,8 @@ angular.module('egCoreMod') .factory('egHatch', - ['$q','$window','$timeout','$interpolate','$rootScope','$http', - function($q , $window , $timeout , $interpolate , $rootScope , $http) { + ['$q','$window','$timeout','$interpolate','$http', + function($q , $window , $timeout , $interpolate , $http) { var service = {}; service.msgId = 0; @@ -40,8 +37,6 @@ angular.module('egCoreMod') service.defaultHatchURL = 'wss://localhost:8443/hatch'; service.hatchRequired = false; - service.printTemplateBase = 'share/print_templates/t_'; - // write a message to the Hatch websocket service.sendToHatch = function(msg) { var msg2 = {}; @@ -201,51 +196,22 @@ angular.module('egCoreMod') } } - service.printFromTemplate = function(context, templateName, printScope) { + service.getPrintConfig = function() { + if (service.printConfig) + return $q.when(service.printConfig); - // populate some common print scope values... - printScope.today = new Date(); - return service.getPrintTemplate(templateName) - .then(function(template) { - service.print(context, 'text/html', template, printScope); + return service.getRemoteItem('eg.print.config') + .then(function(conf) { + return (service.printConfig = conf || {}) }); } - service.print = function( - context, contentType, content, printScope, withDialog) { - - var promise; - if (contentType == 'text/html') { - // all HTML content is assumed to require compilation, regardless - // of the print destination - promise = service.ingestPrintContent( - contentType, content, printScope); - } else { - // text content does not require compilation for remote printing - promise = $q.when(content); - } - - return promise.then(function(html) { - return service.remotePrint( - context, contentType, html, withDialog)['catch']( - - function(msg) { - // remote print not available; - if (contentType != 'text/html') { - // text content does require compilation - // (absorption) for browser printing - service.ingestPrintContent(contentType, content, {}) - .then(function() { $window.print() }); - } else { - // HTML content is already ingested and accessible - // within the page to the printer. - $window.print(); - } - } - ); - }); + service.setPrintConfig = function(conf) { + service.printConfig = conf; + return service.setRemoteItem('eg.print.config', conf); } + service.remotePrint = function( context, contentType, content, withDialog) { @@ -263,24 +229,6 @@ angular.module('egCoreMod') ); } - // ------------- - // print configuration is always stored as remote items, - // since there is no concept of a local printer - service.getPrintConfig = function() { - if (service.printConfig) - return $q.when(service.printConfig); - - return service.getRemoteItem('eg.print.config') - .then(function(conf) { - return (service.printConfig = conf || {}) - }); - } - service.setPrintConfig = function(conf) { - service.printConfig = conf; - return service.setRemoteItem('eg.print.config', conf); - } - // ----------- - // launch the print dialog then attach the resulting configuration // to the requested context, then store the final values. service.configurePrinter = function(context, printer) { @@ -468,97 +416,6 @@ angular.module('egCoreMod') return keys; } - // loads an HTML print template by name from the server - // If no template is available in local/hatch storage, - // fetch the template as an HTML file from the server. - service.getPrintTemplate = function(name) { - var deferred = $q.defer(); - - service.getItem('eg.print.template.' + name) - .then(function(html) { - - if (html) { - // we have a locally stored template - deferred.resolve(html); - return; - } - - var path = service.printTemplateBase + name; - console.debug('fetching template ' + path); - - $http.get(path) - .success(function(data) { deferred.resolve(data) }) - .error(function() { - console.error('unable to locate print template: ' + name); - deferred.reject(); - }); - }); - - return deferred.promise; - } - - service.storePrintTemplate = function(name, html) { - return service.setItem('eg.print.template.' + name, html); - } - return service; }]) -/** - * Container for inserting print data into the browser page. - * On insert, $window.print() is called to print the data. - * The div housing eg-print-container must apply the correct - * print media CSS to ensure this content (and not the rest - * of the page) is printed. - */ - -// FIXME: only apply print CSS when print commands are issued via the -// print container, otherwise using the browser's native print page -// option will always result in empty pages. Move the print CSS -// out of the standalone CSS file and put it into a template file -// for this directive. -.directive('egPrintContainer', ['$compile', function($compile) { - return { - restrict : 'AE', - scope : {}, // isolate our scope - link : function(scope, element, attrs) { - scope.elm = element; - }, - controller : - ['$scope','$q','$window','$timeout','egHatch', - function($scope , $q , $window , $timeout , egHatch) { - - egHatch.ingestPrintContent = function(type, content, printScope) { - - if (type == 'text/csv' || type == 'text/plain') { - // preserve newlines, spaces, etc. - content = '
' + content + '
'; - } - - $scope.elm.html(content); - - var sub_scope = $scope.$new(true); - angular.forEach(printScope, function(val, key) { - sub_scope[key] = val; - }) - - var resp = $compile($scope.elm.contents())(sub_scope); - - var deferred = $q.defer(); - $timeout(function(){ - // give the $digest a chance to complete then - // resolve with the compiled HTML from our - // print container - - deferred.resolve( - resp.contents()[0].parentNode.innerHTML - ); - }); - - return deferred.promise; - } - } - ] - } -}]) - diff --git a/Open-ILS/web/js/ui/default/staff/services/print.js b/Open-ILS/web/js/ui/default/staff/services/print.js new file mode 100644 index 0000000000..d033ac2343 --- /dev/null +++ b/Open-ILS/web/js/ui/default/staff/services/print.js @@ -0,0 +1,187 @@ +/** + */ +angular.module('egCoreMod') + +.factory('egPrint', + ['$q','$window','$timeout','$http','egHatch','egAuth','egIDL','egOrg', +function($q , $window , $timeout , $http , egHatch , egAuth , egIDL , egOrg) { + + var service = {}; + + service.template_base_path = 'share/print_templates/t_'; + + /* + * context : 'default', 'receipt','label', etc. + * scope : data loaded into the template environment + * template : template name (e.g. 'checkout', 'transit_slip' + * content : content to print. If 'template' is set, content is + * derived from the template. + * content_type : 'text/html', 'text/plain', 'text/csv' + * show_dialog : boolean, if true, print dialog is shown. This setting + * only affects remote printers, since browser printers + * do not allow such control + */ + service.print = function(args) { + if (!args) return $q.when(); + + if (args.template) { + // fetch the template, then proceed to printing + + return service.getPrintTemplate(args.template) + .then(function(content) { + args.content = content; + if (!args.content_type) args.content_type = 'html'; + return service.print_content(args); + }); + + } + + return service.print_content(args); + } + + // add commonly used attributes to the print scope + service.fleshPrintScope = function(scope) { + if (!scope) scope = {}; + scope.today = new Date(); + scope.staff = egIDL.toHash(egAuth.user()); + scope.current_location = + egIDL.toHash(egOrg.get(egAuth.user().ws_ou())); + } + + // Template has been fetched (or no template needed) + // Process the template and send the result off to the printer. + service.print_content = function(args) { + service.fleshPrintScope(args.scope); + + var promise; + if (args.content_type == 'text/html') { + + // all HTML content is assumed to require compilation, + // regardless of the print destination + promise = service.ingest_print_content( + args.content_type, args.content, args.scope); + + } else { + // text content does not require compilation for remote printing + promise = $q.when(); + } + + return promise.then(function(html) { + + return egHatch.remotePrint(args.context, + args.content_type, html, args.show_dialog)['catch']( + + function(msg) { + // remote print not available; + + if (args.content_type != 'text/html') { + // text content does require compilation + // (absorption) for browser printing + return service.ingest_print_content( + args.content_type, args.content, args.scope + ).then(function() { $window.print() }); + } else { + // HTML content is already ingested and accessible + // within the page to the printer. + $window.print(); + } + } + ); + }); + } + + // loads an HTML print template by name from the server + // If no template is available in local/hatch storage, + // fetch the template as an HTML file from the server. + service.getPrintTemplate = function(name) { + var deferred = $q.defer(); + + egHatch.getItem('eg.print.template.' + name) + .then(function(html) { + + if (html) { + // we have a locally stored template + deferred.resolve(html); + return; + } + + var path = service.template_base_path + name; + console.debug('fetching template ' + path); + + $http.get(path) + .success(function(data) { deferred.resolve(data) }) + .error(function() { + console.error('unable to locate print template: ' + name); + deferred.reject(); + }); + }); + + return deferred.promise; + } + + service.storePrintTemplate = function(name, html) { + return egHatch.setItem('eg.print.template.' + name, html); + } + + return service; +}]) + + +/** + * Container for inserting print data into the browser page. + * On insert, $window.print() is called to print the data. + * The div housing eg-print-container must apply the correct + * print media CSS to ensure this content (and not the rest + * of the page) is printed. + */ + +// FIXME: only apply print CSS when print commands are issued via the +// print container, otherwise using the browser's native print page +// option will always result in empty pages. Move the print CSS +// out of the standalone CSS file and put it into a template file +// for this directive. +.directive('egPrintContainer', ['$compile', function($compile) { + return { + restrict : 'AE', + scope : {}, // isolate our scope + link : function(scope, element, attrs) { + scope.elm = element; + }, + controller : + ['$scope','$q','$window','$timeout','egHatch','egPrint', + function($scope , $q , $window , $timeout , egHatch , egPrint) { + + egPrint.ingest_print_content = function(type, content, printScope) { + + if (type == 'text/csv' || type == 'text/plain') { + // preserve newlines, spaces, etc. + content = '
' + content + '
'; + } + + $scope.elm.html(content); + + var sub_scope = $scope.$new(true); + angular.forEach(printScope, function(val, key) { + sub_scope[key] = val; + }) + + var resp = $compile($scope.elm.contents())(sub_scope); + + var deferred = $q.defer(); + $timeout(function(){ + // give the $digest a chance to complete then + // resolve with the compiled HTML from our + // print container + + deferred.resolve( + resp.contents()[0].parentNode.innerHTML + ); + }); + + return deferred.promise; + } + } + ] + } +}]) + diff --git a/Open-ILS/web/js/ui/default/staff/services/print_templates.js b/Open-ILS/web/js/ui/default/staff/services/print_templates.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Open-ILS/web/js/ui/default/staff/test/karma.conf.js b/Open-ILS/web/js/ui/default/staff/test/karma.conf.js index 8389f6ae88..a27ca66292 100644 --- a/Open-ILS/web/js/ui/default/staff/test/karma.conf.js +++ b/Open-ILS/web/js/ui/default/staff/test/karma.conf.js @@ -32,6 +32,7 @@ module.exports = function(config){ 'services/env.js', 'services/org.js', 'services/hatch.js', + 'services/print.js', 'services/coresvc.js', 'services/user.js', 'services/startup.js', -- 2.11.0