<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/services/circ.js"></script>
[% INCLUDE 'staff/circ/share/circ_strings.tt2' %]
<script src="[% ctx.media_prefix %]/js/ui/default/staff/circ/checkin/app.js"></script>
+<link rel="stylesheet" href="[% ctx.base_path %]/staff/css/circ.css" />
[% END %]
-<!-- checkin form -->
+<!-- alerts row -->
<div class="row pad-vert">
- <div class="col-md-4">
+ <div class="col-md-12">
+ <div class="flex-row left-anchored">
+ <div ng-if="is_backdate()" class="alert-danger pad-all-min">
+ [% l('Backdated Check In [_1]',
+ '{{checkinArgs.backdate | date:"shortDate"}}') %]
+ </div>
+ <div ng-if="modifiers.no_precat_alert" class="alert-danger pad-all-min">
+ [% l('Ignore Pre-Cataloged Items') %]
+ </div>
+ <div ng-if="modifiers.noop" class="alert-danger pad-all-min">
+ [% l('Suppress Holds and Transits') %]
+ </div>
+ <div ng-if="modifiers.void_overdues" class="alert-danger pad-all-min">
+ [% l('Amnesty Mode') %]
+ </div>
+ <div ng-if="modifiers.auto_print_holds_transits"
+ class="alert-danger pad-all-min">
+ [% l('Auto-Print Hold and Transit Slips') %]
+ </div>
+ </div>
+ </div>
+</div>
+
+<!-- checkin form -->
+<div class="row">
+ <div class="col-md-6">
<form ng-submit="checkin(checkinArgs)" role="form" class="form-inline">
<div class="input-group">
+
<label class="input-group-addon"
for="patron-checkin-barcode" >[% l('Barcode') %]</label>
- <input focus-me="focusMe" blur-me="blurMe" class="form-control"
+ <input focus-me="focusMe" blur-me="blurMe"
+ class="form-control"
ng-model="checkinArgs.copy_barcode"
placeholder="[% l('Barcode') %]"
id="patron-checkin-barcode" type="text"/>
- <!-- do we really need a button?
- <span class="input-group-btn">
- <input type="submit" class="btn btn-default" value="[% l('Submit') %]"/>
- </span>
- -->
+ <input type="submit" class="btn btn-default" value="[% l('Submit') %]"/>
</div>
</form>
</div>
- <div class="col-md-8">
+
+ <div class="col-md-6">
<div class="flex-row">
- <div class="pad-horiz" ng-if="is_backdate()">
- <div class="alert-danger pad-min">
- [% l('Backdated Check In [_1]',
- '{{checkinArgs.backdate | date:"shortDate"}}') %]
- </div>
- </div>
<div class="flex-cell"></div>
<div class="pad-horiz">[% l('Effective Date') %]</div>
<!-- date max= not yet supported -->
</div>
</div>
</div>
-
</div>
<hr/>
<span>[% l('Ignore Pre-cataloged Items') %]</span>
</a>
</li>
+ <li>
+ <a href dropdown-toggle
+ ng-click="modifiers.noop=!modifiers.noop">
+ <span ng-if="modifiers.noop"
+ class="label label-success">✓</span>
+ <span ng-if="!modifiers.noop"
+ class="label label-warning">✗</span>
+ <span>[% l('Suppress Holds and Transits') %]</span>
+ </a>
+ </li>
+ <li>
+ <a href dropdown-toggle
+ ng-click="modifiers.void_overdues=!modifiers.void_overdues">
+ <span ng-if="modifiers.void_overdues"
+ class="label label-success">✓</span>
+ <span ng-if="!modifiers.void_overdues"
+ class="label label-warning">✗</span>
+ <span>[% l('Amnesty Mode') %]</span>
+ </a>
+ </li>
+ <li>
+ <a href dropdown-toggle
+ ng-click="modifiers.auto_print_holds_transits=!modifiers.auto_print_holds_transits">
+ <span ng-if="modifiers.auto_print_holds_transits"
+ class="label label-success">✓</span>
+ <span ng-if="!modifiers.auto_print_holds_transits"
+ class="label label-warning">✗</span>
+ <span>[% l('Auto-Print Hold and Transit Slips') %]</span>
+ </a>
+ </li>
</ul>
</div><!-- btn grp -->
</div><!-- col -->
<!-- TODO: APP_JS should really be called APP_ADDONS or some such.
It just means "load these things, too, and load them last" -->
-<link rel="stylesheet" href="[% ctx.base_path %]/staff/css/circ/patron.css" />
+<link rel="stylesheet" href="[% ctx.base_path %]/staff/css/circ.css" />
<script>
angular.module('egCoreMod').run(['egStrings', function(s) {
--- /dev/null
+/** style to make a grid look like a striped table */
+#patron-summary-grid div.row {padding: 3px; border-right: 2px solid rgb(248, 248, 248);}
+#patron-summary-grid div.row:nth-child(odd) {background-color: rgb(248, 248, 248);}
+
+/* there are bootstrap tyles for error, warning, etc.,
+but the ones I'm finding aren't quite cutting it..*/
+.patron-summary-alert {color: red; font-weight:bold}
+.patron-summary-alert-small {color: red}
+.patron-summary-divider { border-top: 1px solid #CCC}
+.patron-summary-act-link {font-size: .8em;}
+
+#patron-checkout-barcode,
+#patron-checkin-barcode { width: 16em; }
+
+#patron-search-form div.form-group {
+ margin-bottom: 5px;
+}
+
+/* let search form elements fill their containers w/ slight padding */
+#patron-search-form-row {margin-left: 0px;}
+#patron-search-form div.col-md-2 { padding: 2px; }
+#patron-search-form input:not([type="checkbox"]) { width: 100%; }
+#patron-search-form .eg-org-selector,
+#patron-search-form .eg-org-selector button,
+#patron-search-form .patron-search-selector,
+ #patron-search-form .patron-search-selector button {
+ width: 100%;
+ text-align: left
+}
+
+
+#patron-payments-spreadsheet {
+ margin-top: 10px;
+ padding-top: 10px;
+ border-top: 1px solid #aaa;
+}
+
+#patron-payments-spreadsheet .flex-cell {
+ margin: 2px;
+}
+
+#patron-payments-spreadsheet .flex-cell.well {
+ min-height: 1.5em;
+ margin-bottom: 0px; /* bootstrap default is 20px */
+}
+
+[%#
+vim: ft=css
+%]
+++ /dev/null
-/** style to make a grid look like a striped table */
-#patron-summary-grid div.row {padding: 3px; border-right: 2px solid rgb(248, 248, 248);}
-#patron-summary-grid div.row:nth-child(odd) {background-color: rgb(248, 248, 248);}
-
-/* there are bootstrap tyles for error, warning, etc.,
-but the ones I'm finding aren't quite cutting it..*/
-.patron-summary-alert {color: red; font-weight:bold}
-.patron-summary-alert-small {color: red}
-.patron-summary-divider { border-top: 1px solid #CCC}
-.patron-summary-act-link {font-size: .8em;}
-
-#patron-checkout-barcode { width: 16em; }
-
-#patron-search-form div.form-group {
- margin-bottom: 5px;
-}
-
-/* let search form elements fill their containers w/ slight padding */
-#patron-search-form-row {margin-left: 0px;}
-#patron-search-form div.col-md-2 { padding: 2px; }
-#patron-search-form input:not([type="checkbox"]) { width: 100%; }
-#patron-search-form .eg-org-selector,
-#patron-search-form .eg-org-selector button,
-#patron-search-form .patron-search-selector,
- #patron-search-form .patron-search-selector button {
- width: 100%;
- text-align: left
-}
-
-
-#patron-payments-spreadsheet {
- margin-top: 10px;
- padding-top: 10px;
- border-top: 1px solid #aaa;
-}
-
-#patron-payments-spreadsheet .flex-cell {
- margin: 2px;
-}
-
-#patron-payments-spreadsheet .flex-cell.well {
- min-height: 1.5em;
- margin-bottom: 0px; /* bootstrap default is 20px */
-}
-
-[%#
-vim: ft=css
-%]
.pad-horiz {padding : 0px 10px 0px 10px; }
.pad-vert {padding : 20px 0px 10px 0px;}
-.pad-min {padding : 5px; }
+.pad-left {padding-left: 10px;}
+.pad-right {padding-right: 10px;}
+.pad-all-min {padding : 5px; }
+.pad-all {padding : 10px; }
#print-div { display: none; }
width: 8em;
}
+/* barcode inputs are everywhere. Let's have a consistent style */
+.barcode { width: 16em; }
+
/* ----------------------------------------------------------------------
* Grid
* ---------------------------------------------------------------------- */
.flex-row.padded div {
padding: 5px;
}
+.flex-row.left-anchored > div {
+ margin-right: 10px;
+}
.flex-cell {
flex: 1;
padding: 4px; /* bootstrap default is much bigger */
}
);
+ var today = new Date();
$scope.focusMe = true;
$scope.checkins = checkinSvc.checkins;
- $scope.checkinArgs = {backdate : new Date()}
+ $scope.checkinArgs = {backdate : today}
$scope.using_hatch = egCore.hatch.usingHatch();
$scope.modifiers = {};
- var today = new Date();
-
+ // ensure the backdate is not in the future
+ // note: input type=date max=foo not yet supported anywhere
$scope.$watch('checkinArgs.backdate', function(newval) {
if (newval && newval > today)
$scope.checkinArgs.backdate = today;
delete params.backdate;
}
+ if ($scope.modifiers.noop)
+ params.noop = true;
+ if ($scope.modifiers.void_overdues)
+ params.void_overdues = true;
+
var options = {
check_barcode : $scope.strict_barcode,
- no_precat_alert : $scope.modifiers.no_precat_alert
+ no_precat_alert : $scope.modifiers.no_precat_alert,
+ auto_print_holds_transits :
+ $scope.modifiers.auto_print_holds_transits
};
- egCirc.checkin(angular.copy(params), options)
+ egCirc.checkin(params, options)
.then(function(final_resp) {
final_resp.evt.index = checkinSvc.checkins.length;
final_resp.evt.copy_barcode = params.copy_barcode;
service.checkout = function(params, options) {
if (!options) options = {};
- console.debug('egCirc.checkout() : ' + js2JSON(params));
+ console.debug('egCirc.checkout() : '
+ + js2JSON(params) + ' : ' + js2JSON(options));
var promise = options.check_barcode ?
service.test_barcode(params.copy_barcode) : $q.when();
service.renew = function(params, options) {
if (!options) options = {};
- console.debug('egCirc.renew() : ' + js2JSON(params));
+ console.debug('egCirc.renew() : '
+ + js2JSON(params) + ' : ' + js2JSON(options));
var method = 'open-ils.circ.renew';
if (options.override) method += '.override';
service.checkin = function(params, options) {
if (!options) options = {};
+ console.debug('egCirc.checkin() : '
+ + js2JSON(params) + ' : ' + js2JSON(options));
+
var promise = options.check_barcode ?
service.test_barcode(params.copy_barcode) : $q.when();
}
}
+ // collect transit, address, and hold info that's not already
+ // included in responses.
+ service.collect_route_data = function(tmpl, evt, params, options) {
+ var promises = [];
+ var data = {};
+
+ if (evt.org && !tmpl.match(/hold_shelf/)) {
+ promises.push(
+ service.get_org_addr(evt.org, 'holds_address')
+ .then(function(addr) { data.address = addr })
+ );
+ }
+
+ if (evt.payload.hold) {
+ promises.push(
+ egCore.pcrud.retrieve('au',
+ evt.payload.hold.usr(), {
+ flesh : 1,
+ flesh_fields : {'au' : ['card']}
+ }
+ ).then(function(patron) {data.patron = patron})
+ );
+ }
+
+ if (!tmpl.match(/hold_shelf/)) {
+ promises.push(
+ service.find_copy_transit(evt, params, options)
+ .then(function(trans) {data.transit = transit})
+ );
+ }
+
+ return $q.all(promises).then(function() { return data });
+ }
+
service.route_dialog = function(tmpl, evt, params, options) {
- return $modal.open({
- templateUrl: tmpl,
- controller: [
- '$scope','$modalInstance','destAddr','holdUser','transit',
- function($scope , $modalInstance , destAddr , holdUser , transit) {
- $scope.today = new Date();
+ return service.collect_route_data(tmpl, evt, params, options)
+ .then(function(data) {
+
+ // All actions flow from the print data
- var print_context = {
- copy : egCore.idl.toHash(evt.payload.copy),
- title : evt.payload.record.title(),
- author : evt.payload.record.author()
- }
+ var print_context = {
+ copy : egCore.idl.toHash(evt.payload.copy),
+ title : evt.payload.record.title(),
+ author : evt.payload.record.author()
+ }
- if (transit) {
- // route_dialog includes the "route to holds shelf"
- // dialog, which has no transit
- print_context.transit = egCore.idl.toHash(transit);
- print_context.dest_address = egCore.idl.toHash(destAddr);
- print_context.dest_location =
- egCore.idl.toHash(egCore.org.get(transit.dest()));
- }
+ if (data.transit) {
+ // route_dialog includes the "route to holds shelf"
+ // dialog, which has no transit
+ print_context.transit = egCore.idl.toHash(data.transit);
+ print_context.dest_address = egCore.idl.toHash(data.address);
+ print_context.dest_location =
+ egCore.idl.toHash(egCore.org.get(data.transit.dest()));
+ }
- if (holdUser) {
- print_context.hold = egCore.idl.toHash(evt.payload.hold);
- print_context.patron = egCore.idl.toHash(holdUser);
- }
+ if (data.patron) {
+ print_context.hold = egCore.idl.toHash(evt.payload.hold);
+ print_context.patron = egCore.idl.toHash(data.patron);
+ }
- angular.forEach(print_context, function(val, key) {
- $scope[key] = val;
+ function print_transit() {
+ var template = transit ?
+ (data.patron ? 'hold_transit_slip' : 'transit_slip') :
+ 'hold_shelf_slip';
+
+ return egCore.print.print({
+ context : 'default',
+ template : template,
+ scope : print_context
});
+ }
- $scope.ok = function() {$modalInstance.close()}
+ // when auto-print is on, skip the dialog and go straight
+ // to printing.
+ if (options.auto_print_holds_transits)
+ return print_transit();
- $scope.print = function() {
- $modalInstance.close();
+ return $modal.open({
+ templateUrl: tmpl,
+ controller: [
+ '$scope','$modalInstance',
+ function($scope , $modalInstance) {
- template = transit ?
- (holdUser ? 'hold_transit_slip' : 'transit_slip') :
- 'hold_shelf_slip';
+ $scope.today = new Date();
- egCore.print.print({
- context : 'default',
- template : template,
- scope : print_context
+ // copy the print scope into the dialog scope
+ angular.forEach(print_context, function(val, key) {
+ $scope[key] = val;
});
- }
- }],
- resolve : {
- // transit destination org unit address
- destAddr : function() {
- if (!evt.org || tmpl.match(/hold_shelf/))
- return $q.when();
- return service.get_org_addr(evt.org, 'holds_address');
- },
- holdUser : function() {
- if (!evt.payload.hold) return $q.when();
- return egCore.pcrud.retrieve('au',
- evt.payload.hold.usr(), {
- flesh : 1,
- flesh_fields : {'au' : ['card']}
- }
- );
- },
- transit : function() {
- if (tmpl.match(/hold_shelf/)) return $q.when();
- return service.find_copy_transit(evt, params, options);
- }
- }
- }).result;
+ $scope.ok = function() {$modalInstance.close()}
+
+ $scope.print = function() {
+ $modalInstance.close();
+ print_transit();
+ }
+ }]
+
+ }).result;
+ });
}
// action == what action to take if the user confirms the alert