LP#1646166 Hatch print configiguration interface
authorBill Erickson <berickxx@gmail.com>
Fri, 18 Nov 2016 17:13:38 +0000 (12:13 -0500)
committerBill Erickson <berickxx@gmail.com>
Thu, 26 Jan 2017 15:26:18 +0000 (10:26 -0500)
1. Query printers for available options via Hatch.
2. Allow the user to apply print options on a per-context / per-printer
   basis.
3. As before, store printer conifugration options via Hatch.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/templates/staff/admin/workstation/t_print_config.tt2
Open-ILS/src/templates/staff/css/style.css.tt2
Open-ILS/web/js/ui/default/staff/admin/workstation/app.js
Open-ILS/web/js/ui/default/staff/services/hatch.js

index ce4d670..8f4a34d 100644 (file)
@@ -16,6 +16,9 @@
   <div class="row"> 
     <div class="col-md-12">
       <h2>[% l('Printer Settings for Remote Printing') %]</h2>
+      <div class="alert alert-warning" ng-show="hatchNotConnected()">
+        [% l("Hatch is not connected") %]
+      </div>
     </div>
   </div>
 
                   value="{{printConfig[context].printer}}">
               </div><!-- /input-group -->
             </div><!-- col -->
+            <div class="col-md-4">
+              <span class="pad-right-min">
+                <button class="btn btn-warning" 
+                  ng-click="resetPrinterSettings(context)">
+                  [% l('Reset Form') %]
+                </button>
+              </span>
+              <button class="btn btn-success" 
+                ng-click="savePrinterSettings(context)">
+                [% l('Apply Changes') %]
+              </button>
+            </div>
           </div><!-- row -->
+
           <div class="row" ng-hide="isTestView"> 
+            <div class="col-md-10">
+              <div class="row">
+                <div class="col-md-1"></div>
+                <div class="col-md-2">
+                  <label>[% l('Print Color') %]</label>
+                </div>
+                <div class="col-md-4">
+                  <select
+                    class="form-control"
+                    ng-model="printConfig[context].printColor"
+                    ng-options="val for val in printerOptions.printColor | orderBy:'val'">
+                  </select>  
+                </div>
+                <div class="col-md-3">
+                  <span>[% l('Default: [_1]', 
+                    '{{printerOptions.defaultPrintColor}}') %]</span>
+                </div>
+              </div>
+              <div class="row">
+                <div class="col-md-1"></div>
+                <div class="col-md-2">
+                  <label>[% l('Paper Source') %]</label>
+                </div>
+                <div class="col-md-4">
+                  <select
+                    class="form-control"
+                    ng-model="printConfig[context].paperSource"
+                    ng-options="val for val in printerOptions.paperSource | orderBy:'val'">
+                  </select>  
+                </div>
+                <div class="col-md-3">
+                  <span>[% l('Default: [_1]', 
+                    '{{printerOptions.defaultPaperSource}}') %]</span>
+                </div>
+              </div>
+
+              <div class="row">
+                <div class="col-md-1"></div>
+                <div class="col-md-2">
+                  <label>[% l('Paper Type') %]</label>
+                </div>
+                <div class="col-md-4">
+                  <select
+                    class="form-control"
+                    ng-model="printConfig[context].paper"
+                    ng-options="val for val in printerOptions.paper | orderBy:'val'">
+                  </select>  
+                </div>
+                <div class="col-md-3">
+                  <span>[% l('Default: [_1]', 
+                    '{{printerOptions.defaultPaper}}') %]</span>
+                </div>
+              </div>
+
+              <div class="row">
+                <div class="col-md-1"></div>
+                <div class="col-md-2">
+                  <label>[% l('Page Orientation') %]</label>
+                </div>
+                <div class="col-md-4">
+                  <select
+                    class="form-control"
+                    ng-model="printConfig[context].pageOrientation"
+                    ng-options="val for val in printerOptions.pageOrientation | orderBy:'val'">
+                  </select>  
+                </div>
+                <div class="col-md-3">
+                  <span>[% l('Default: [_1]', 
+                    '{{printerOptions.defaultPageOrientation}}') %]</span>
+                </div>
+              </div>
+
+              <div class="row">
+                <div class="col-md-1"></div>
+                <div class="col-md-2">
+                  <label>[% l('Collation') %]</label>
+                </div>
+                <div class="col-md-4">
+                  <select
+                    class="form-control"
+                    ng-model="printConfig[context].collation"
+                    ng-options="val for val in printerOptions.collation | orderBy:'val'">
+                  </select>  
+                </div>
+                <div class="col-md-3">
+                  <span>[% l('Default: [_1]', 
+                    '{{printerOptions.defaultCollation}}') %]</span>
+                </div>
+              </div>
+
+              <div class="row">
+                <div class="col-md-1"></div>
+                <div class="col-md-2">
+                  <label>[% l('Print Quality') %]</label>
+                </div>
+                <div class="col-md-4">
+                  <select
+                    class="form-control"
+                    ng-model="printConfig[context].printQuality"
+                    ng-options="val for val in printerOptions.printQuality | orderBy:'val'">
+                  </select>  
+                </div>
+                <div class="col-md-3">
+                  <span>[% l('Default: [_1]', 
+                    '{{printerOptions.defaultPrintQuality}}') %]</span>
+                </div>
+              </div>
+
+              <div class="row">
+                <div class="col-md-1"></div>
+                <div class="col-md-2">
+                  <label>[% l('Print Sides') %]</label>
+                </div>
+                <div class="col-md-4">
+                  <select
+                    class="form-control"
+                    ng-model="printConfig[context].printSides"
+                    ng-options="val for val in printerOptions.printSides | orderBy:'val'">
+                  </select>  
+                </div>
+                <div class="col-md-3">
+                  <span>[% l('Default: [_1]', 
+                    '{{printerOptions.defaultPrintSides}}') %]</span>
+                </div>
+              </div>
+
+              <div class="row">
+                <div class="col-md-1"></div>
+                <div class="col-md-2">
+                  <label>[% l('Number of Copies') %]</label>
+                </div>
+                <div class="col-md-4">
+                  <input type="text" size="4" class="form-control"
+                    ng-model="printConfig[context].copies"/>
+                </div>
+                <div class="col-md-3">
+                  <span>[% l('Default: [_1]', 
+                    '{{printerOptions.defaultCopies}}') %]</span>
+                </div>
+              </div>
+
+              <div class="row">
+                <div class="col-md-1">
+                  <input type="radio" name="margins" 
+                    ng-click="printConfig[context].autoMargins=true"
+                    ng-checked="printConfig[context].autoMargins"/>
+                </div>
+                <div class="col-md-2">
+                  <label>[% l('Automatic Margins') %]</label>
+                </div>
+                <div class="col-md-4">
+                  <select
+                    class="form-control"
+                    ng-model="printConfig[context].marginType"
+                    ng-disabled="!printConfig[context].autoMargins" 
+                    ng-options="val for val in printerOptions.marginType | orderBy:'val'">
+                  </select>  
+                </div>
+                <div class="col-md-3">
+                  <span>[% l('Default: [_1]', 
+                    '{{printerOptions.defaultMarginType}}') %]</span>
+                </div>
+              </div>
+
+              <div class="row">
+                <div class="col-md-1">
+                  <input type="radio" name="margins"
+                    ng-click="printConfig[context].autoMargins=false"
+                    ng-checked="!printConfig[context].autoMargins"/>
+                </div>
+                <div class="col-md-2">
+                  <label>[% l('Manual Margins') %]</label>
+                </div>
+                <div class="col-md-2">
+                  <div class="input-group">
+                    <span class="input-group-addon">[% l('Left') %]</span>
+                    <input type="text" class="form-control"
+                      ng-disabled="printConfig[context].autoMargins"
+                      ng-model="printConfig[context].leftMargin"/>
+                  </div>
+                </div>
+                <div class="col-md-2">
+                  <div class="input-group">
+                    <span class="input-group-addon">[% l('Top') %]</span>
+                    <input type="text" class="form-control"
+                      ng-disabled="printConfig[context].autoMargins"
+                      ng-model="printConfig[context].topMargin"/>
+                  </div>
+                </div>
+              </div>
+              <div class="row">
+                <div class="col-md-3"></div>
+                <div class="col-md-2">
+                  <div class="input-group">
+                    <span class="input-group-addon">[% l('Right') %]</span>
+                    <input type="text" class="form-control"
+                      ng-disabled="printConfig[context].autoMargins"
+                      ng-model="printConfig[context].rightMargin"/>
+                  </div>
+                </div>
+                <div class="col-md-2">
+                  <div class="input-group">
+                    <span class="input-group-addon">[% l('Bottom') %]</span>
+                    <input type="text" class="form-control"
+                      ng-disabled="printConfig[context].autoMargins"
+                      ng-model="printConfig[context].bottomMargin"/>
+                  </div>
+                </div>
+              </div>
+
+              <div class="row">
+                <div class="col-md-1"></div>
+                <div class="col-md-2"><label>[% l('Page Ranges') %]</label></div>
+                <div class="col-md-2">
+                  [% l('All Pages') %]
+                  <input type='radio' name='pageRanges' 
+                    ng-checked="printConfig[context].allPages"
+                    ng-click="printConfig[context].allPages=true"/>
+                </div>
+                <div class="col-md-2">
+                  [% l('Page Range') %]
+                  <input type='radio' name='pageRanges' 
+                    ng-checked="!printConfig[context].allPages"
+                    ng-click="printConfig[context].allPages=false"/>
+                </div>
+              </div>
+              <div class="row">
+                <div class="col-md-3"></div>
+                <div class="col-md-2">
+                  <div class="input-group">
+                    <span class="input-group-addon">[% l('Start') %]</span>
+                    <input type="text" class="form-control"
+                      ng-disabled="printConfig[context].allPages"
+                      ng-model="printConfig[context].pageRanges[0]"/>
+                  </div>
+                </div>
+                <div class="col-md-2">
+                  <div class="input-group">
+                    <span class="input-group-addon">[% l('End') %]</span>
+                    <input type="text" class="form-control"
+                      ng-disabled="printConfig[context].allPages"
+                      ng-model="printConfig[context].pageRanges[1]"/>
+                  </div>
+                </div>
+                <!-- TODO: support multiple page ranges by 
+                    dynamically adding additional pageRanges[X] pairs -->
+              </div>
+            </div><!-- col -->
+          </div><!-- row -->
+
+          <div class="row" ng-hide="isTestView">
             <div class="col-md-12">
-              <h2>[% l('Compiled Printer Settings') %]</h2>
+              <h3>[% l('Compiled Printer Settings') %]</h3>
               <pre>{{printerConfString()}}</pre>
             </div><!-- col -->
           </div><!-- row -->
index 93881b6..4e6f962 100644 (file)
@@ -128,6 +128,7 @@ table.list tr.selected td { /* deprecated? */
 .pad-vert {padding : 20px 0px 10px 0px;}
 .pad-left {padding-left: 10px;}
 .pad-right {padding-right: 10px;}
+.pad-right-min {padding-right: 5px;}
 .pad-all-min {padding : 5px; }
 .pad-all-min2 {padding : 2px; }
 .pad-all {padding : 10px; }
index 4530599..be8536e 100644 (file)
@@ -220,18 +220,18 @@ function($scope , $window , $location , egCore , egConfirmDialog) {
 .controller('PrintConfigCtrl',
        ['$scope','egCore',
 function($scope , egCore) {
-    console.log('PrintConfigCtrl');
-
-    $scope.actionPending = false;
-    $scope.isTestView = false;
 
+    $scope.printConfig = {};
     $scope.setContext = function(ctx) { 
         $scope.context = ctx; 
         $scope.isTestView = false;
-        $scope.actionPending = false;
     }
     $scope.setContext('default');
 
+    $scope.hatchNotConnected = function() {
+        return !egCore.hatch.hatchAvailable;
+    }
+
     $scope.getPrinterByAttr = function(attr, value) {
         var printer;
         angular.forEach($scope.printers, function(p) {
@@ -240,50 +240,48 @@ function($scope , egCore) {
         return printer;
     }
 
-    $scope.currentPrinter = function() {
-        if ($scope.printConfig && $scope.printConfig[$scope.context]) {
-            return $scope.getPrinterByAttr(
-                'name', $scope.printConfig[$scope.context].printer
-            );
-        }
-    }
-
     // fetch info on all remote printers
     egCore.hatch.getPrinters()
     .then(function(printers) { 
         $scope.printers = printers;
-        $scope.defaultPrinter = 
-            $scope.getPrinterByAttr('is-default', true);
-    })
-    .then(function() { return egCore.hatch.getPrintConfig() })
-    .then(function(config) {
-        $scope.printConfig = config;
-
-        var pname = '';
-        if ($scope.defaultPrinter) {
-            pname = $scope.defaultPrinter.name;
-
-        } else if ($scope.printers.length == 1) {
-            // if the OS does not report a default printer, but only
-            // one printer is available, treat it as the default.
-            pname = $scope.printers[0].name;
-        }
 
-        // apply the default printer to every context which has
-        // no printer configured.
+        var def = $scope.getPrinterByAttr('is-default', true);
+        if (!def && printers.length) def = printers[0];
+
+        if (def) {
+            $scope.defaultPrinter = def;
+            loadPrinterOptions(def.name);
+        }
+    }).then(function() {
         angular.forEach(
             ['default','receipt','label','mail','offline'],
             function(ctx) {
-                if (!$scope.printConfig[ctx]) {
-                    $scope.printConfig[ctx] = {
-                        context : ctx,
-                        printer : pname
+                egCore.hatch.getPrintConfig(ctx).then(function(conf) {
+                    if (conf) {
+                        $scope.printConfig[ctx] = conf;
+                    } else {
+                        $scope.resetPrinterSettings(ctx);
                     }
-                }
+                });
             }
         );
     });
 
+    $scope.resetPrinterSettings = function(context) {
+        $scope.printConfig[context] = {
+            context : context,
+            printer : $scope.defaultPrinter ? $scope.defaultPrinter.name : null,
+            autoMargins : true, 
+            allPages : true,
+            pageRanges : []
+        };
+    }
+
+    $scope.savePrinterSettings = function(context) {
+        return egCore.hatch.setPrintConfig(
+            context, $scope.printConfig[context]);
+    }
+
     $scope.printerConfString = function() {
         if ($scope.printConfigError) return $scope.printConfigError;
         if (!$scope.printConfig) return;
@@ -292,24 +290,14 @@ function($scope , egCore) {
             $scope.printConfig[$scope.context], undefined, 2);
     }
 
-    $scope.resetConfig = function() {
-        $scope.actionPending = true;
-        $scope.printConfigError = null;
-        $scope.printConfig[$scope.context] = {
-            context : $scope.context
-        }
-        
-        if ($scope.defaultPrinter) {
-            $scope.printConfig[$scope.context].printer = 
-                $scope.defaultPrinter.name;
-        }
-
-        egCore.hatch.setPrintConfig($scope.printConfig)
-        .finally(function() {$scope.actionPending = false});
+    function loadPrinterOptions(name) {
+        egCore.hatch.getPrinterOptions(name).then(
+            function(options) {$scope.printerOptions = options});
     }
 
     $scope.setPrinter = function(name) {
         $scope.printConfig[$scope.context].printer = name;
+        loadPrinterOptions(name);
     }
 
     // for testing
index c38920e..c235294 100644 (file)
@@ -33,6 +33,7 @@ angular.module('egCoreMod')
     service.messages = {};
     service.pending = [];
     service.hatchAvailable = null;
+    service.cachedPrintConfig = {};
     service.state = 'IDLE'; // IDLE, INIT, CONNECTED, NO_CONNECTION
 
     // write a message to the Hatch port
@@ -188,31 +189,15 @@ angular.module('egCoreMod')
         };
     }
 
-    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);
-    }
-
-
     service.remotePrint = function(
         context, contentType, content, withDialog) {
 
-        return service.getPrintConfig().then(
-            function(conf) {
+        return service.getPrintConfig(context).then(
+            function(config) {
                 // print configuration retrieved; print
                 return service.attemptHatchDelivery({
                     action : 'print',
-                    config : conf[context],
+                    settings : config,
                     content : content, 
                     contentType : contentType,
                     showDialog : withDialog,
@@ -221,43 +206,27 @@ angular.module('egCoreMod')
         );
     }
 
-    // launch the print dialog then attach the resulting configuration
-    // to the requested context, then store the final values.
-    service.configurePrinter = function(context, printer) {
-
-        // load current settings
-        return service.getPrintConfig()
-
-        // dispatch the print configuration request
+    // 'force' avoids using the config cache
+    service.getPrintConfig = function(context, force) {
+        if (service.cachedPrintConfig[context] && !force) {
+            return $q.when(service.cachedPrintConfig[context])
+        }
+        return service.getRemoteItem('eg.print.config.' + context)
         .then(function(config) {
+            return service.cachedPrintConfig[context] = config;
+        });
+    }
 
-            // loaded remote config
-            if (!config[context]) config[context] = {};
-            config[context].printer = printer;
-            return service.attemptHatchDelivery({
-                key : 'no-op', 
-                action : 'print-config',
-                config : config[context]
-            })
-        })
-
-        // set the returned settings to the requested context
-        .then(function(newconf) {
-            if (angular.isObject(newconf)) {
-                newconf.printer = printer;
-                return service.printConfig[context] = newconf;
-            } else {
-                console.warn("configurePrinter() returned " + newconf);
-            }
-        })
-
-        // store the newly linked settings
-        .then(function() {
-            service.setItem('eg.print.config', service.printConfig);
-        })
+    service.setPrintConfig = function(context, config) {
+        service.cachedPrintConfig[context] = config;
+        return service.setRemoteItem('eg.print.config.' + context, config);
+    }
 
-        // return the final settings to the caller
-        .then(function() {return service.printConfig});
+    service.getPrinterOptions = function(name) {
+        return service.attemptHatchDelivery({
+            action : 'printer-options',
+            printer : name
+        });
     }
 
     service.getPrinters = function() {