From ae4b29cc87b9110b1dd8e060ab5bcb3c66b4a423 Mon Sep 17 00:00:00 2001 From: Adam Bowling Date: Wed, 13 Feb 2019 12:40:17 -0500 Subject: [PATCH] LP#1775870 Fixes random sort order for print labels, picking up the sort field specified by the user in the source grid supplying the copies. In the case that no sort field was clicked, copies are loaded into the label print interface in ascending order from oldest to newest entry on the source grid. This branch is dependent on the spine label customizations submitted in a=commit;h=ace4c873538c95459fdba5439a6167fe665551c1. Signed-off-by: Adam Bowling --- .../web/js/ui/default/staff/cat/bucket/copy/app.js | 43 +- .../web/js/ui/default/staff/cat/catalog/app.js | 41 +- Open-ILS/web/js/ui/default/staff/cat/item/app.js | 12 +- .../web/js/ui/default/staff/cat/printlabels/app.js | 565 ++++++++++++++++----- .../web/js/ui/default/staff/cat/volcopy/app.js | 11 +- .../web/js/ui/default/staff/circ/checkin/app.js | 12 +- .../web/js/ui/default/staff/circ/services/item.js | 0 7 files changed, 517 insertions(+), 167 deletions(-) mode change 100644 => 100755 Open-ILS/web/js/ui/default/staff/cat/bucket/copy/app.js mode change 100644 => 100755 Open-ILS/web/js/ui/default/staff/cat/catalog/app.js mode change 100644 => 100755 Open-ILS/web/js/ui/default/staff/cat/item/app.js mode change 100644 => 100755 Open-ILS/web/js/ui/default/staff/cat/printlabels/app.js mode change 100644 => 100755 Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js mode change 100644 => 100755 Open-ILS/web/js/ui/default/staff/circ/checkin/app.js mode change 100644 => 100755 Open-ILS/web/js/ui/default/staff/circ/services/item.js diff --git a/Open-ILS/web/js/ui/default/staff/cat/bucket/copy/app.js b/Open-ILS/web/js/ui/default/staff/cat/bucket/copy/app.js old mode 100644 new mode 100755 index f39346ef35..62a4063c83 --- a/Open-ILS/web/js/ui/default/staff/cat/bucket/copy/app.js +++ b/Open-ILS/web/js/ui/default/staff/cat/bucket/copy/app.js @@ -586,24 +586,41 @@ function($scope, $q , $routeParams , $timeout , $window , $uibModal , bucketSvc }); } - $scope.print_labels = function() { - var cp_list = [] + $scope.print_labels = function () { + var cp_list = []; angular.forEach($scope.gridControls.selectedItems(), function (i) { cp_list.push(i.id); }) - egCore.net.request( - 'open-ils.actor', - 'open-ils.actor.anon_cache.set_value', - null, 'print-labels-these-copies', { - copies : cp_list - } - ).then(function(key) { - if (key) { - var url = egCore.env.basePath + 'cat/printlabels/' + key; - $timeout(function() { $window.open(url, '_blank') }); + var cp_full = [], promises = []; + promises.push( + egCore.pcrud.search('ccbi', { bucket: bucketSvc.currentBucket.a[2], "target_copy": { "in": cp_list } }).then( + null + , null + , function (ccbi) { + cp_full.push(egCore.idl.toHash(ccbi, true)); + } + ) + ); + + $q.all(promises).then(function () { + if (cp_full.length > 0) { + egCore.net.request( + 'open-ils.actor', + 'open-ils.actor.anon_cache.set_value', + null, 'print-labels-these-copies', { + copies: cp_full + } + ).then(function (key) { + if (key) { + var url = egCore.env.basePath + 'cat/printlabels/' + key; + $timeout(function () { $window.open(url, '_blank') }); + } else { + alert('Could not create anonymous cache key!'); + } + }); } else { - alert('Could not create anonymous cache key!'); + alert('Could not create print label export.'); } }); } diff --git a/Open-ILS/web/js/ui/default/staff/cat/catalog/app.js b/Open-ILS/web/js/ui/default/staff/cat/catalog/app.js old mode 100644 new mode 100755 index 422ebeb34d..29bf84924b --- a/Open-ILS/web/js/ui/default/staff/cat/catalog/app.js +++ b/Open-ILS/web/js/ui/default/staff/cat/catalog/app.js @@ -1632,18 +1632,37 @@ function($scope , $routeParams , $location , $window , $q , egCore , egHolds , e } $scope.selectedHoldingsPrintLabels = function() { - egCore.net.request( - 'open-ils.actor', - 'open-ils.actor.anon_cache.set_value', - null, 'print-labels-these-copies', { - copies : gatherSelectedHoldingsIds() - } - ).then(function(key) { - if (key) { - var url = egCore.env.basePath + 'cat/printlabels/' + key; - $timeout(function() { $window.open(url, '_blank') }); + var cp_list = gatherSelectedHoldingsIds(); + + var cp_full = [], promises = []; + promises.push( + egCore.pcrud.search('ccbi', { bucket: $scope.bucket_id, "target_copy": { "in": cp_list } }).then( + null + , null + , function (ccbi) { + cp_full.push(egCore.idl.toHash(ccbi, true)); + } + ) + ); + + $q.all(promises).then(function () { + if (cp_full.length > 0) { + egCore.net.request( + 'open-ils.actor', + 'open-ils.actor.anon_cache.set_value', + null, 'print-labels-these-copies', { + copies: cp_full + } + ).then(function (key) { + if (key) { + var url = egCore.env.basePath + 'cat/printlabels/' + key; + $timeout(function () { $window.open(url, '_blank') }); + } else { + alert('Could not create anonymous cache key!'); + } + }); } else { - alert('Could not create anonymous cache key!'); + alert('Could not create print label export.'); } }); } diff --git a/Open-ILS/web/js/ui/default/staff/cat/item/app.js b/Open-ILS/web/js/ui/default/staff/cat/item/app.js old mode 100644 new mode 100755 index 19e45f921a..638495c011 --- a/Open-ILS/web/js/ui/default/staff/cat/item/app.js +++ b/Open-ILS/web/js/ui/default/staff/cat/item/app.js @@ -525,13 +525,21 @@ function($scope , $q , $routeParams , $location , $timeout , $window , egCore , $scope.transferItems = function (){ itemSvc.transferItems(copyGrid.selectedItems()); } - + $scope.print_labels = function() { + var cp_list = gatherSelectedHoldingsIds(); + !$scope.gridDataProvider.sort ? cp_list.reverse() : $scope.gridDataProvider.sort.length === 0 ? cp_list.reverse() : false; + var i = 1; + var cp_full = []; + angular.forEach(cp_list, function (copy) { + cp_full.push({id: i, target_copy: copy}) + i++; + }); egCore.net.request( 'open-ils.actor', 'open-ils.actor.anon_cache.set_value', null, 'print-labels-these-copies', { - copies : gatherSelectedHoldingsIds() + copies : cp_full } ).then(function(key) { if (key) { diff --git a/Open-ILS/web/js/ui/default/staff/cat/printlabels/app.js b/Open-ILS/web/js/ui/default/staff/cat/printlabels/app.js old mode 100644 new mode 100755 index f6f02da043..866babe0a1 --- a/Open-ILS/web/js/ui/default/staff/cat/printlabels/app.js +++ b/Open-ILS/web/js/ui/default/staff/cat/printlabels/app.js @@ -5,69 +5,69 @@ angular.module('egPrintLabels', ['ngRoute', 'ui.bootstrap', 'egCoreMod', 'egUiMod', 'egGridMod']) -.config(function($routeProvider, $locationProvider, $compileProvider) { +.config(function ($routeProvider, $locationProvider, $compileProvider) { $locationProvider.html5Mode(true); $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|mailto|blob):/); // grid export - + var resolver = { - delay : ['egStartup', function(egStartup) { return egStartup.go(); }] + delay: ['egStartup', function (egStartup) { return egStartup.go(); }] }; $routeProvider.when('/cat/printlabels/:dataKey', { templateUrl: './cat/printlabels/t_view', controller: 'LabelCtrl', - resolve : resolver + resolve: resolver }); }) -.factory('itemSvc', +.factory('itemSvc', ['egCore', -function(egCore) { +function (egCore) { var service = { - copies : [], // copy barcode search results - index : 0 // search grid index + copies: [], // copy barcode search results + index: 0 // search grid index }; - service.flesh = { - flesh : 3, - flesh_fields : { - acp : ['call_number','location','status','location','floating','circ_modifier','age_protect'], - acn : ['record','prefix','suffix'], - bre : ['simple_record','creator','editor'] + service.flesh = { + flesh: 3, + flesh_fields: { + acp: ['call_number', 'location', 'status', 'location', 'floating', 'circ_modifier', 'age_protect', 'circ_lib'], + acn: ['record', 'prefix', 'suffix', 'owning_lib'], + bre: ['simple_record', 'creator', 'editor'] }, - select : { + select: { // avoid fleshing MARC on the bre // note: don't add simple_record.. not sure why - bre : ['id','tcn_value','creator','editor'], - } + bre: ['id', 'tcn_value', 'creator', 'editor'], + } } // resolved with the last received copy - service.fetch = function(barcode, id, noListDupes) { + service.fetch = function (barcode, id, noListDupes) { var promise; if (barcode) { - promise = egCore.pcrud.search('acp', - {barcode : barcode, deleted : 'f'}, service.flesh); + promise = egCore.pcrud.search('acp', + { barcode: barcode, deleted: 'f' }, service.flesh); } else { promise = egCore.pcrud.retrieve('acp', id, service.flesh); } var lastRes; return promise.then( - function() {return lastRes}, + function () { return lastRes }, null, // error // notify reads the stream of copies, one at a time. - function(copy) { + function (copy) { var flatCopy; if (noListDupes) { // use the existing copy if possible flatCopy = service.copies.filter( - function(c) {return c.id == copy.id()})[0]; + function (c) { return c.id == copy.id() })[0]; } if (!flatCopy) { @@ -77,8 +77,8 @@ function(egCore) { } return lastRes = { - copy : copy, - index : flatCopy.index + copy: copy, + index: flatCopy.index } } ); @@ -90,19 +90,66 @@ function(egCore) { /** * Label controller! */ -.controller('LabelCtrl', - ['$scope','$q','$window','$routeParams','$location','$timeout','egCore','egNet','ngToast','itemSvc', -function($scope , $q , $window , $routeParams , $location , $timeout , egCore , egNet , ngToast , itemSvc ) { +.controller('LabelCtrl', + ['$scope', '$q', '$window', '$routeParams', '$location', '$timeout', 'egCore', 'egNet', 'ngToast', 'itemSvc', 'labelOutputRowsFilter', +function ($scope, $q, $window, $routeParams, $location, $timeout, egCore, egNet, ngToast, itemSvc, labelOutputRowsFilter) { var dataKey = $routeParams.dataKey; console.debug('dataKey: ' + dataKey); $scope.print = { - template_name : 'item_label', - template_output : '', - template_context : 'default' + template_name: 'item_label', + template_output: '', + template_context: 'default' }; + var toolbox_settings = { + feed_option: { + options: [ + { label: "Continuous", value: "continuous" }, + { label: "Sheet", value: "sheet" }, + ], + selected: "continuous" + }, + label_set: { + margin_between: 0, + size: 1 + }, + mode: { + options: [ + { label: "Spine Label", value: "spine-only" }, + { label: "Pocket Label", value: "spine-pocket" } + ], + selected: "spine-pocket" + }, + page: { + column_class: ["spine", "pocket"], + dimensions: { + columns: 2, + rows: 1 + }, + label: { + gap: { + size: 0 + }, + set: { + size: 2 + } + }, + margins: { + top: { size: 0, label: "Top" }, + left: { size: 0, label: "Left" }, + }, + space_between_labels: { + horizontal: { size: 0, label: "Horizontal" }, + vertical: { size: 0, label: "Vertical" } + }, + start_position: { + column: 1, + row: 1 + } + } + }; if (dataKey && dataKey.length > 0) { @@ -115,9 +162,10 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , if (data) { $scope.preview_scope = { - 'copies' : [] - ,'settings' : {} - ,'get_cn_for' : function(copy) { + 'copies': [] + , 'settings': {} + , 'toolbox_settings': JSON.parse(JSON.stringify(toolbox_settings)) + , 'get_cn_for': function (copy) { var key = $scope.rendered_cn_key_by_copy_id[copy.id]; if (key) { var manual_cn = $scope.rendered_call_number_set[key]; @@ -130,22 +178,22 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , return '...'; } } - ,'get_bib_for' : function(copy) { + , 'get_bib_for': function (copy) { return $scope.record_details[copy['call_number.record.id']]; } - ,'get_cn_prefix' : function(copy) { + , 'get_cn_prefix': function (copy) { return copy['call_number.prefix.label']; } - ,'get_cn_suffix' : function(copy) { + , 'get_cn_suffix': function (copy) { return copy['call_number.suffix.label']; } - ,'get_location_prefix' : function(copy) { + , 'get_location_prefix': function (copy) { return copy['location.label_prefix']; } - ,'get_location_suffix' : function(copy) { + , 'get_location_suffix': function (copy) { return copy['location.label_suffix']; } - ,'get_cn_and_location_prefix' : function(copy,separator) { + , 'get_cn_and_location_prefix': function (copy, separator) { var acpl_prefix = copy['location.label_prefix'] || ''; var cn_prefix = copy['call_number.prefix.label'] || ''; var prefix = acpl_prefix + ' ' + cn_prefix; @@ -153,7 +201,7 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , if (separator && prefix != '') { prefix += separator; } return prefix; } - ,'get_cn_and_location_suffix' : function(copy,separator) { + , 'get_cn_and_location_suffix': function (copy, separator) { var acpl_suffix = copy['location.label_suffix'] || ''; var cn_suffix = copy['call_number.suffix.label'] || ''; var suffix = cn_suffix + ' ' + acpl_suffix; @@ -161,6 +209,12 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , if (separator && suffix != '') { suffix = separator + suffix; } return suffix; } + , 'valid_print_label_start_column': function () { + return !angular.isNumber(toolbox_settings.page.dimensions.columns) || !angular.isNumber(toolbox_settings.page.start_position.column) ? false : (toolbox_settings.page.start_position.column <= toolbox_settings.page.dimensions.columns); + } + , 'valid_print_label_start_row': function () { + return !angular.isNumber(toolbox_settings.page.dimensions.rows) || !angular.isNumber(toolbox_settings.page.start_position.row) ? false : (toolbox_settings.page.start_position.row <= toolbox_settings.page.dimensions.rows); + } }; $scope.record_details = {}; $scope.org_unit_settings = {}; @@ -168,56 +222,62 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , var promises = []; $scope.org_unit_setting_list = [ 'webstaff.cat.label.font.family' - ,'webstaff.cat.label.font.size' - ,'webstaff.cat.label.font.weight' - ,'webstaff.cat.label.inline_css' - ,'webstaff.cat.label.left_label.height' - ,'webstaff.cat.label.left_label.left_margin' - ,'webstaff.cat.label.left_label.width' - ,'webstaff.cat.label.right_label.height' - ,'webstaff.cat.label.right_label.left_margin' - ,'webstaff.cat.label.right_label.width' - ,'webstaff.cat.label.call_number_wrap_filter_height' - ,'webstaff.cat.label.call_number_wrap_filter_width' + , 'webstaff.cat.label.font.size' + , 'webstaff.cat.label.font.weight' + , 'webstaff.cat.label.inline_css' + , 'webstaff.cat.label.left_label.height' + , 'webstaff.cat.label.left_label.left_margin' + , 'webstaff.cat.label.left_label.width' + , 'webstaff.cat.label.right_label.height' + , 'webstaff.cat.label.right_label.left_margin' + , 'webstaff.cat.label.right_label.width' + , 'webstaff.cat.label.call_number_wrap_filter_height' + , 'webstaff.cat.label.call_number_wrap_filter_width' ]; promises.push( - egCore.pcrud.search('coust',{name:$scope.org_unit_setting_list}).then( + egCore.pcrud.search('coust', { name: $scope.org_unit_setting_list }).then( null - ,null - ,function(yaous) { + , null + , function (yaous) { $scope.org_unit_settings[yaous.name()] = egCore.idl.toHash(yaous, true); } ) ); promises.push( - egCore.org.settings($scope.org_unit_setting_list).then(function(res) { + egCore.org.settings($scope.org_unit_setting_list).then(function (res) { $scope.preview_scope.settings = res; - egCore.hatch.getItem('cat.printlabels.last_settings').then(function(last_settings) { + egCore.hatch.getItem('cat.printlabels.last_settings').then(function (last_settings) { if (last_settings) { for (s in last_settings) { $scope.preview_scope.settings[s] = last_settings[s]; } } }); + egCore.hatch.getItem('cat.printlabels.last_toolbox_settings').then(function (last_toolbox_settings) { + if (last_toolbox_settings) { + $scope.preview_scope.toolbox_settings = JSON.parse(JSON.stringify(last_toolbox_settings)); + } + }); }) ); - angular.forEach(data.copies, function(copy) { + angular.forEach(data.copies, function (copy) { promises.push( - itemSvc.fetch(null,copy).then(function(res) { + itemSvc.fetch(null, copy.target_copy).then(function (res) { var flat_copy = egCore.idl.toHash(res.copy, true); + flat_copy.copy_bucket_item_id = copy.id; $scope.preview_scope.copies.push(flat_copy); - $scope.record_details[ flat_copy['call_number.record.id'] ] = 1; + $scope.record_details[flat_copy['call_number.record.id']] = 1; }) ) }); - $q.all(promises).then(function() { + $q.all(promises).then(function () { var promises2 = []; - angular.forEach($scope.record_details, function(el,k,obj) { + angular.forEach($scope.record_details, function (el, k, obj) { promises2.push( egNet.request( 'open-ils.search', @@ -229,7 +289,9 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , ); }); - $q.all(promises2).then(function() { + $q.all(promises2).then(function () { + // sort copies into the order they were entered into the bucket + $scope.preview_scope.copies.sort((a, b) => (a.copy_bucket_item_id > b.copy_bucket_item_id) ? 1 : ((b.copy_bucket_item_id > a.copy_bucket_item_id) ? -1 : 0)); // today, staff, current_location, etc. egCore.print.fleshPrintScope($scope.preview_scope); $scope.template_changed(); // load the default @@ -245,14 +307,20 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , } + $scope.checkForToolboxCustomizations = function (tText, redraw) { + var re = /eg\_plt\_(\d+)/; + redraw ? $scope.redraw_label_table() : false; + return re.test(tText); + } + $scope.fetchTemplates = function (set_default) { - return egCore.hatch.getItem('cat.printlabels.templates').then(function(t) { + return egCore.hatch.getItem('cat.printlabels.templates').then(function (t) { if (t) { $scope.templates = t; $scope.template_name_list = Object.keys(t); if (set_default) { - egCore.hatch.getItem('cat.printlabels.default_template').then(function(d) { - if ($scope.template_name_list.indexOf(d,0) > -1) { + egCore.hatch.getItem('cat.printlabels.default_template').then(function (d) { + if ($scope.template_name_list.indexOf(d, 0) > -1) { $scope.template_name = d; } }); @@ -269,6 +337,9 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , for (var s in $scope.templates[n].settings) { $scope.preview_scope.settings[s] = $scope.templates[n].settings[s]; } + if ($scope.templates[n].toolbox_settings) { + $scope.preview_scope.toolbox_settings = JSON.parse(JSON.stringify($scope.templates[n].toolbox_settings)); + } egCore.hatch.setItem('cat.printlabels.default_template', n); $scope.save_locally(); } @@ -281,7 +352,7 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , egCore.hatch.setItem('cat.printlabels.templates', $scope.templates); $scope.fetchTemplates(); ngToast.create(egCore.strings.PRINT_LABEL_TEMPLATE_SUCCESS_DELETE); - egCore.hatch.getItem('cat.printlabels.default_template').then(function(d) { + egCore.hatch.getItem('cat.printlabels.default_template').then(function (d) { if (d && d == n) { egCore.hatch.removeItem('cat.printlabels.default_template'); } @@ -293,10 +364,11 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , if (n) { $scope.templates[n] = { - content : $scope.print.template_content - ,context : $scope.print.template_context - ,cn_content : $scope.print.cn_template_content - ,settings : $scope.preview_scope.settings + content: $scope.print.template_content + , context: $scope.print.template_context + , cn_content: $scope.print.cn_template_content + , settings: JSON.parse(JSON.stringify($scope.preview_scope.settings)) + , toolbox_settings: JSON.parse(JSON.stringify($scope.preview_scope.toolbox_settings)) }; $scope.template_name_list = Object.keys($scope.templates); @@ -313,53 +385,59 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , } $scope.templates = {}; - $scope.imported_templates = { data : '' }; + $scope.imported_templates = { data: '' }; $scope.template_name = ''; $scope.template_name_list = []; - $scope.print_labels = function() { + $scope.print_labels = function () { return egCore.print.print({ - context : $scope.print.template_context, - template : $scope.print.template_name, - scope : $scope.preview_scope, + context: $scope.print.template_context, + template: $scope.print.template_name, + scope: $scope.preview_scope, }); } - $scope.template_changed = function() { + $scope.template_changed = function () { $scope.print.load_failed = false; egCore.print.getPrintTemplate('item_label') .then( - function(html) { + function (html) { $scope.print.template_content = html; + $scope.checkForToolboxCustomizations(html, true); }, - function() { + function () { $scope.print.template_content = ''; $scope.print.load_failed = true; } ); egCore.print.getPrintTemplateContext('item_label') - .then(function(template_context) { + .then(function (template_context) { $scope.print.template_context = template_context; }); egCore.print.getPrintTemplate('item_label_cn') .then( - function(html) { + function (html) { $scope.print.cn_template_content = html; }, - function() { + function () { $scope.print.cn_template_content = ''; $scope.print.load_failed = true; } ); - egCore.hatch.getItem('cat.printlabels.last_settings').then(function(s) { + egCore.hatch.getItem('cat.printlabels.last_settings').then(function (s) { if (s) { - $scope.preview_scope.settings = s; + $scope.preview_scope.settings = JSON.parse(JSON.stringify(s)); + } + }); + egCore.hatch.getItem('cat.printlabels.last_toolbox_settings').then(function (t) { + if (t) { + $scope.preview_scope.toolbox_settings = JSON.parse(JSON.stringify(t)); } }); } - $scope.reset_to_default = function() { + $scope.reset_to_default = function () { egCore.print.removePrintTemplate( 'item_label' ); @@ -370,18 +448,20 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , 'item_label_cn' ); egCore.hatch.removeItem('cat.printlabels.last_settings'); + egCore.hatch.removeItem('cat.printlabels.last_toolbox_settings'); for (s in $scope.preview_scope.settings) { $scope.preview_scope.settings[s] = undefined; } - $scope.preview_scope.settings = {}; - egCore.org.settings($scope.org_unit_setting_list).then(function(res) { + $scope.preview_scope.toolbox_settings = JSON.parse(JSON.stringify(toolbox_settings)); + + egCore.org.settings($scope.org_unit_setting_list).then(function (res) { $scope.preview_scope.settings = res; }); $scope.template_changed(); } - $scope.save_locally = function() { + $scope.save_locally = function () { egCore.print.storePrintTemplate( 'item_label', $scope.print.template_content @@ -394,21 +474,25 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , 'item_label_cn', $scope.print.cn_template_content ); - egCore.hatch.setItem('cat.printlabels.last_settings', $scope.preview_scope.settings); + egCore.hatch.setItem('cat.printlabels.last_settings', JSON.parse(JSON.stringify($scope.preview_scope.settings))); + egCore.hatch.setItem('cat.printlabels.last_toolbox_settings', JSON.parse(JSON.stringify($scope.preview_scope.toolbox_settings))); } - $scope.imported_print_templates = { data : '' }; - $scope.$watch('imported_templates.data', function(newVal, oldVal) { + $scope.imported_print_templates = { data: '' }; + $scope.$watch('imported_templates.data', function (newVal, oldVal) { if (newVal && newVal != oldVal) { try { var data = JSON.parse(newVal); - angular.forEach(data, function(el,k) { + angular.forEach(data, function (el, k) { $scope.templates[k] = { - content : el.content - ,context : el.context - ,cn_content : el.cn_content - ,settings : el.settings + content: el.content + , context: el.context + , cn_content: el.cn_content + , settings: JSON.parse(JSON.stringify(el.settings)) }; + if (el.toolbox_settings) { + $scope.templates[k].toolbox_settings = JSON.parse(JSON.stringify(el.toolbox_settings)); + } }); $scope.saveTemplate(); $scope.template_changed(); // refresh @@ -421,18 +505,18 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , $scope.rendered_call_number_set = {}; $scope.rendered_cn_key_by_copy_id = {}; - $scope.rebuild_cn_set = function() { - $timeout(function(){ + $scope.rebuild_cn_set = function () { + $timeout(function () { $scope.rendered_call_number_set = {}; $scope.rendered_cn_key_by_copy_id = {}; for (var i = 0; i < $scope.preview_scope.copies.length; i++) { var copy = $scope.preview_scope.copies[i]; - var rendered_cn = document.getElementById('cn_for_copy_'+copy.id); + var rendered_cn = document.getElementById('cn_for_copy_' + copy.id); if (rendered_cn && rendered_cn.textContent) { var key = rendered_cn.textContent; if (typeof $scope.rendered_call_number_set[key] == 'undefined') { $scope.rendered_call_number_set[key] = { - value : key + value: key }; } $scope.rendered_cn_key_by_copy_id[copy.id] = key; @@ -442,46 +526,198 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , }); } - $scope.$watch('print.cn_template_content', function(newVal, oldVal) { + $scope.redraw_label_table = function () { + if ($scope.print_label_form.$valid && $scope.print.template_content && $scope.preview_scope) { + $scope.preview_scope.label_output_copies = labelOutputRowsFilter($scope.preview_scope.copies, $scope.preview_scope.toolbox_settings); + var d = new Date().getTime().toString(); + var html = $scope.print.template_content; + if ($scope.checkForToolboxCustomizations(html)) { + html = html.replace(/eg\_plt\_\d+/, "eg_plt_" + d); + $scope.print.template_content = html; + } else { + var table = " 0 && toolbox_settings.feed_option.selected === 'sheet' ? ' page-break' : ''}}\" ng-init=\"parentIndex = $index\" ng-repeat=\"row in label_output_copies\">\n"; + table += "\n"; + table += "\n" + table += "\n"; + table += "
0 ? toolbox_settings.page.space_between_labels.vertical.size : parentIndex > 0 ? toolbox_settings.page.space_between_labels.vertical.size : 0}} 0 0 {{$index === 0 ? toolbox_settings.page.margins.left.size : col.styl ? col.styl : toolbox_settings.page.space_between_labels.horizontal.size}};\" ng-repeat=\"col in row.columns\">\n"; + table += "
\n";
+                table += "{{col.c ? get_cn_for(col.c) : ''}}";
+                table += "
\n"; + table += "
 0 && toolbox_settings.feed_option.selected === 'sheet' ? ' page-break' : ''}}\" style=\"border: none;  margin-bottom: 0; margin-top: 0; overflow: hidden;\" ng-if=\"col.cls === 'pocket'\">\n";
+                table += "{{col.c ? col.c.barcode : ''}}\n";
+                table += "{{col.c ? col.c['call_number.label'] : ''}}\n";
+                table += "{{col.c ? get_bib_for(col.c).author : ''}}\n";
+                table += "{{col.c ? (get_bib_for(col.c).title | wrap:28:'once':'  ') : ''}}\n";
+                table += "
\n"; + table += "
"; + var comments = html.match(/\<\!\-\-(?:(?!\-\-\>)(?:.|\s))*\-\-\>\s*/g); + html = html.replace(/\<\!\-\-(?:(?!\-\-\>)(?:.|\s))*\-\-\>\s*/g, ''); + var style = html.match(/\]*\>(?:(?!\<\/style\>)(?:.|\s))*\<\/style\>\s*/gi); + var output = (comments ? comments.join("\n") : "") + (style ? style.join("\n") : "") + table; + output = output.replace(/\n+/, "\n"); + $scope.print.template_content = output; + } + } + } + + $scope.$watch('print.cn_template_content', function (newVal, oldVal) { if (newVal && newVal != oldVal) { $scope.rebuild_cn_set(); } }); - $scope.$watch("preview_scope.settings['webstaff.cat.label.call_number_wrap_filter_height']", function(newVal, oldVal) { + $scope.$watch("preview_scope.settings['webstaff.cat.label.call_number_wrap_filter_height']", function (newVal, oldVal) { if (newVal && newVal != oldVal) { $scope.rebuild_cn_set(); } }); - $scope.$watch("preview_scope.settings['webstaff.cat.label.call_number_wrap_filter_width']", function(newVal, oldVal) { + $scope.$watch("preview_scope.settings['webstaff.cat.label.call_number_wrap_filter_width']", function (newVal, oldVal) { + if (newVal && newVal != oldVal) { + $scope.rebuild_cn_set(); + } + }); + + $scope.$watchGroup(['preview_scope.toolbox_settings.page.margins.top.size', 'preview_scope.toolbox_settings.page.margins.left.size', 'preview_scope.toolbox_settings.page.dimensions.rows', 'preview_scope.toolbox_settings.page.dimensions.columns', 'preview_scope.toolbox_settings.page.space_between_labels.horizontal.size', 'preview_scope.toolbox_settings.page.space_between_labels.vertical.size', 'preview_scope.toolbox_settings.page.start_position.row', 'preview_scope.toolbox_settings.page.start_position.column', 'preview_scope.toolbox_settings.page.label.gap.size'], function (newVal, oldVal) { + if (newVal && newVal != oldVal && $scope.preview_scope.label_output_copies) { + $scope.redraw_label_table(); + } + }); + + $scope.$watch("preview_scope.toolbox_settings.mode.selected", function (newVal, oldVal) { + if (newVal && newVal != oldVal && $scope.preview_scope) { + var ts_p = $scope.preview_scope.toolbox_settings.page; + if (ts_p.label.set.size === 1) { + if (newVal === "spine-pocket") { + ts_p.column_class = ["spine", "pocket"]; + ts_p.label.set.size = 2; + } else { + ts_p.column_class = ["spine"]; + } + } else { + if (newVal === "spine-only") { + for (var i = 0; i < ts_p.label.set.size; i++) { + ts_p.column_class[i] = "spine"; + } + } else { + ts_p.label.set.size === 2 ? ts_p.column_class = ["spine", "pocket"] : false; + } + } + $scope.redraw_label_table(); + } + }); + + $scope.$watch("preview_scope.toolbox_settings.page.label.set.size", function (newVal, oldVal) { + if (newVal && newVal != oldVal && oldVal) { + var ts_p = $scope.preview_scope.toolbox_settings.page; + if (angular.isNumber(newVal)) { + while (ts_p.column_class.length > ts_p.label.set.size) { + ts_p.column_class.splice((ts_p.column_class.length - 1), 1); + } + while (ts_p.column_class.length < ts_p.label.set.size) { + ts_p.column_class.push("spine"); + } + } + } + }); + + $scope.$watch('print.cn_template_content', function (newVal, oldVal) { + if (newVal && newVal != oldVal) { + $scope.rebuild_cn_set(); + } + }); + + $scope.$watch("preview_scope.settings['webstaff.cat.label.call_number_wrap_filter_height']", function (newVal, oldVal) { + if (newVal && newVal != oldVal) { + $scope.rebuild_cn_set(); + } + }); + + $scope.$watch("preview_scope.settings['webstaff.cat.label.call_number_wrap_filter_width']", function (newVal, oldVal) { if (newVal && newVal != oldVal) { $scope.rebuild_cn_set(); } }); $scope.current_tab = 'call_numbers'; - $scope.set_tab = function(tab) { + $scope.set_tab = function (tab) { $scope.current_tab = tab; } }]) -// -.directive('egPrintTemplateOutput', ['$compile',function($compile) { - return function(scope, element, attrs) { +.directive("egPrintLabelColumnBounds", function () { + return { + link: function (scope, element, attr, ctrl) { + function withinBounds(v) { + scope.$watch("preview_scope.toolbox_settings.page.dimensions.columns", function (newVal, oldVal) { + ctrl.$setValidity("egWithinPrintColumnBounds", scope.preview_scope.valid_print_label_start_column()) + }); + return v; + } + ctrl.$parsers.push(withinBounds); + ctrl.$formatters.push(withinBounds); + }, + require: "ngModel" + } +}) + +.directive("egPrintLabelRowBounds", function () { + return { + link: function (scope, element, attr, ctrl) { + function withinBounds(v) { + scope.$watch("preview_scope.toolbox_settings.page.dimensions.rows", function (newVal, oldVal) { + ctrl.$setValidity("egWithinPrintRowBounds", scope.preview_scope.valid_print_label_start_row()); + }); + return v; + } + ctrl.$parsers.push(withinBounds); + ctrl.$formatters.push(withinBounds); + }, + require: "ngModel" + } +}) + +.directive("egPrintLabelValidCss", function () { + return { + require: "ngModel", + link: function (scope, element, attr, ctrl) { + function floatValidation(v) { + ctrl.$setValidity("isFloat", v.toString().match(/^\-*(?:^0$|(?:\d+)(?:\.\d{1,})*([a-z]{2}))$/) ? true : false); + return v; + } + ctrl.$parsers.push(floatValidation); + } + } +}) + +.directive("egPrintLabelValidInt", function () { + return { + require: "ngModel", + link: function (scope, element, attr, ctrl) { + function intValidation(v) { + ctrl.$setValidity("isInteger", v.toString().match(/^\d+$/)); + return v; + } + ctrl.$parsers.push(intValidation); + } + } +}) + +.directive('egPrintTemplateOutput', ['$compile', function ($compile) { + return function (scope, element, attrs) { scope.$watch( - function(scope) { + function (scope) { return scope.$eval(attrs.content); }, - function(value) { + function (value) { // create an isolate scope and copy the print context // data into the new scope. // TODO: see also print security concerns in egHatch var result = element.html(value); var context = scope.$eval(attrs.context); var print_scope = scope.$new(true); - angular.forEach(context, function(val, key) { + angular.forEach(context, function (val, key) { print_scope[key] = val; }) $compile(element.contents())(print_scope); @@ -490,8 +726,8 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , }; }]) -.filter('cn_wrap', function() { - return function(input, w, h, wrap_type) { +.filter('cn_wrap', function () { + return function (input, w, h, wrap_type) { var names; var prefix = input[0]; var callnum = input[1]; @@ -506,11 +742,11 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , on the spine label: subclass letters, subclass numbers, cutter numbers, trailing stuff (date) */ var patt1 = /^([A-Z]{1,3})\s*(\d+(?:\.\d+)?)\s*(\.[A-Z]\d*)\s*([A-Z]\d*)?\s*(\d\d\d\d(?:-\d\d\d\d)?)?\s*(.*)$/i; var result = callnum.match(patt1); - if (result) { - callnum = result.slice(1).join('\t'); + if (result) { + callnum = result.slice(1).join('\t'); } else { callnum = callnum.split(/\s+/).join('\t'); - } + } /* If result is null, leave callnum alone. Can't parse this malformed call num */ } else { @@ -527,17 +763,17 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , /* At this point, the call number pieces are separated by tab characters. This allows * some space-containing constructs like "v. 1" to appear on one line */ - callnum = callnum.replace(/\t\t/g,'\t'); /* Squeeze out empties */ + callnum = callnum.replace(/\t\t/g, '\t'); /* Squeeze out empties */ names = callnum.split('\t'); var j = 0; var tb = []; while (j < h) { - + /* spine */ if (j < w) { var name = names.shift(); if (name) { - name = String( name ); + name = String(name); /* if the name is greater than the label width... */ if (name.length > w) { @@ -548,20 +784,20 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , if (name.match(/^\./)) sname[0] = '.' + sname[0]; for (var k = 1; k < sname.length; k++) sname[k] = '.' + sname[k]; /* and put all but the first one back into the names array */ - names = sname.slice(1).concat( names ); + names = sname.slice(1).concat(names); /* if the name fragment is still greater than the label width... */ if (sname[0].length > w) { /* then just truncate and throw the rest back into the names array */ - tb[j] = sname[0].substr(0,w); - names = [ sname[0].substr(w) ].concat( names ); + tb[j] = sname[0].substr(0, w); + names = [sname[0].substr(w)].concat(names); } else { /* otherwise we're set */ tb[j] = sname[0]; } } else { /* if we can't split on periods, then just truncate and throw the rest back into the names array */ - tb[j] = name.substr(0,w); - names = [ name.substr(w) ].concat( names ); + tb[j] = name.substr(0, w); + names = [name.substr(w)].concat(names); } } else { /* otherwise we're set */ @@ -575,8 +811,58 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , } }) -.filter('wrap', function() { - return function(input, w, wrap_type, indent) { +.filter("columnRowRange", function () { + return function (i) { + var res = []; + for (var j = 0; j < i; j++) { + res.push(j); + } + return res; + } +}) + +//Accepts $scope.preview_scope.copies and $scope.preview_scope.toolbox_settings as its parameters. +.filter("labelOutputRows", function () { + return function (copies, settings) { + var cols = [], rows = []; + for (var j = 0; j < (settings.page.start_position.row - 1) ; j++) { + cols = []; + for (var k = 0; k < settings.page.dimensions.columns; k++) { + cols.push({ c: null, index: k, cls: getPrintLabelOutputClass(k, settings), styl: getPrintLabelStyle(k, settings) }); + } + rows.push({ columns: cols }); + } + cols = []; + for (var j = 0; j < (settings.page.start_position.column - 1) ; j++) { + cols.push({ c: null, index: j, cls: getPrintLabelOutputClass(j, settings), styl: getPrintLabelStyle(j, settings) }); + } + var m = cols.length; + for (var j = 0; j < copies.length; j++) { + for (var n = 0; n < settings.page.label.set.size; n++) { + if (m < settings.page.dimensions.columns) { + cols.push({ c: copies[j], index: cols.length, cls: getPrintLabelOutputClass(m, settings), styl: getPrintLabelStyle(m, settings) }); + m += 1; + } + if (m === settings.page.dimensions.columns) { + m = 0; + rows.push({ columns: cols }); + cols = []; + n = settings.page.label.set.size; + } + } + } + cols.length > 0 ? rows.push({ columns: cols }) : false; + if (rows.length > 0) { + while ((rows[(rows.length - 1)].columns.length) < settings.page.dimensions.columns) { + rows[(rows.length - 1)].columns.push({ c: null, index: rows[(rows.length - 1)].columns.length, cls: getPrintLabelOutputClass(rows[(rows.length - 1)].columns.length, settings), styl: getPrintLabelStyle(rows[(rows.length - 1)].columns.length, settings) }); + } + } + return rows; + } +}) + +.filter('wrap', function () { + return function (input, w, wrap_type, indent) { var output; if (!w) return input; @@ -589,17 +875,17 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , if_cant_wrap_then_truncate, idx ) { - if (idx>10) { + if (idx > 10) { console.log('possible infinite recursion, aborting'); return ''; } if (String(text).length <= length) { return text; } else { - var truncated_text = String(text).substr(0,length); + var truncated_text = String(text).substr(0, length); var pivot_pos = truncated_text.lastIndexOf(' '); - var left_chunk = text.substr(0,pivot_pos).replace(/\s*$/,''); - var right_chunk = String(text).substr(pivot_pos+1); + var left_chunk = text.substr(0, pivot_pos).replace(/\s*$/, ''); + var right_chunk = String(text).substr(pivot_pos + 1); var wrapped_line; if (left_chunk.length == 0) { @@ -621,7 +907,7 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , length, false, if_cant_wrap_then_truncate, - idx+1) + idx + 1) : right_chunk ) ) @@ -631,16 +917,23 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , } } - switch(wrap_type) { + switch (wrap_type) { case 'once': - output = wrap_on_space(input,w,true,false,0); - break; + output = wrap_on_space(input, w, true, false, 0); + break; default: - output = wrap_on_space(input,w,false,false,0); - break; + output = wrap_on_space(input, w, false, false, 0); + break; } return output; } -}) +}); + +function getPrintLabelOutputClass(index, settings) { + return settings.page.column_class[index % settings.page.label.set.size]; +} +function getPrintLabelStyle(index, settings) { + return index > 0 && (index % settings.page.label.set.size === 0) ? settings.page.label.gap.size : ""; +} \ No newline at end of file diff --git a/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js b/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js old mode 100644 new mode 100755 index 20c825746e..5e2331e31c --- a/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js +++ b/Open-ILS/web/js/ui/default/staff/cat/volcopy/app.js @@ -1971,12 +1971,19 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , ).then(function(copy_ids) { if (and_exit) { $scope.dirty = false; + !$scope.completedGridDataProvider.sort ? copy_ids.reverse() : $scope.completedGridDataProvider.sort.length === 0 ? copy_ids.reverse() : false; if ($scope.defaults.print_item_labels) { + var cp_full = []; + var i = 1; + angular.forEach(copy_ids, function (copy) { + cp_full.push({ id: i, target_copy: copy }); + i++; + }); egCore.net.request( 'open-ils.actor', 'open-ils.actor.anon_cache.set_value', null, 'print-labels-these-copies', { - copies : copy_ids + copies : cp_full } ).then(function(key) { if (key) { @@ -2149,7 +2156,7 @@ function($scope , $q , $window , $routeParams , $location , $timeout , egCore , { order_by : { 'acpt' : ['label'] } }, { atomic: true } ).then(function(list) { return list.map(function(item) { - return item.label() + " (" + egCore.org.get(item.owner()).shortname() + ")"; + return item.label(); }); }); } diff --git a/Open-ILS/web/js/ui/default/staff/circ/checkin/app.js b/Open-ILS/web/js/ui/default/staff/circ/checkin/app.js old mode 100644 new mode 100755 index 6d71f6c6dd..452016a73a --- a/Open-ILS/web/js/ui/default/staff/circ/checkin/app.js +++ b/Open-ILS/web/js/ui/default/staff/circ/checkin/app.js @@ -397,12 +397,18 @@ function($scope , $q , $window , $location , $timeout , egCore , checkinSvc , eg }); } - $scope.printSpineLabels = function(items){ - var copy_ids = []; + $scope.printSpineLabels = function(items){ + var copy_ids = [], cp_full; angular.forEach(items, function(item) { if (item.acp) copy_ids.push(item.acp.id()); }); - itemSvc.print_spine_labels(copy_ids); + !$scope.gridDataProvider.sort ? copy_ids.reverse() : $scope.gridDataProvider.sort.length === 0 ? copy_ids.reverse() : false; + var i = 0; + angular.forEach(copy_ids, function (copy) { + cp_full.push({ id: i, target_copy: copy }); + i++; + }); + itemSvc.print_spine_labels(cp_full); } $scope.addCopyAlerts = function(items) { diff --git a/Open-ILS/web/js/ui/default/staff/circ/services/item.js b/Open-ILS/web/js/ui/default/staff/circ/services/item.js old mode 100644 new mode 100755 -- 2.11.0