</script>
[% END %]
+
+<!-- TODO: CSS, header image, other styling...-->
+
+<!-- header bar : main banner image and scan box -->
<div class="row" ng-if="!is_login_page()">
<div class="col-md-12">
<div class="row">
<div>[% l('Welcome, [_1]', '{{patron().first_given_name()}}') %]</div>
</div>
<div class="row">
- <!-- TODO: header image stuff -->
<div class="col-md-5"></div>
<div class="col-md-2">
<input
</div>
</div>
+<!-- dynamic content pane (left) and navigation pane (right) -->
<div class="row">
- <div class="col-md-8">
+ <div class="{{dyn_content_class()}}">
<div ng-view></div>
</div>
<div class="col-md-4" ng-if="!is_login_page()">
<fieldset>
<legend>[% l('Items Checked Out') %]</legend>
- <div>[% l('Total items this session: [_1]',
- '{{counts("session_circ")}}') %]</div>
- <div>[% l('Total items on account: [_1]',
- '{{counts("total_circ")}}') %]</div>
- <div><button class="btn btn-success">
+ <div>[% l('Total items this session: [_1]', '{{counts("session_circ")}}') %]</div>
+ <div>[% l('Total items on account: [_1]', '{{counts("total_circ")}}') %]</div>
+ <div><button class="btn btn-success" ng-click="show_pane('items')">
[% l('View Items Out') %]</button></div>
</fieldset>
<fieldset>
<legend>[% l('Holds') %]</legend>
- <div>[% l('You have [_1] item(s) ready for pickup',
- '{{counts("hold_ready")}}') %]</div>
- <div>[% l('You have [_1] total holds',
- '{{counts("total_hold")}}') %]</div>
- <div><button class="btn btn-success">
+ <div>[% l('You have [_1] item(s) ready for pickup', '{{counts("hold_ready")}}') %]</div>
+ <div>[% l('You have [_1] total holds', '{{counts("total_hold")}}') %]</div>
+ <div><button class="btn btn-success" ng-click="show_pane('holds')">
[% l('View Holds') %]</button></div>
</fieldset>
<fieldset>
<legend>[% l('Fines') %]</legend>
- <div><button class="btn btn-success">
+ <div><button class="btn btn-success" ng-click="show_pane('fines')">
[% l('View Details') %]</button>
</div>
</fieldset>
-<div class="container">
- <div class="row">
- <div class="col-md-3"></div>
- <div class="col-md-6">
- <fieldset>
- <legend>[% l('Please log in with your username or library barcode.') %]</legend>
+<div class="row">
+ <div class="col-md-3"></div>
+ <div class="col-md-6">
+ <fieldset>
+ <legend>[% l('Please log in with your username or library barcode.') %]</legend>
- <form ng-submit="login(args)" name="sc-login-form"
- autocomplete="off" class="form-horizontal" role="form">
- <div class="form-group">
- <label class="col-md-4 control-label" for="login-username">[% l('Username or Barcode') %]</label>
- <div class="col-md-8">
- <input type="text" id="login-username" class="form-control"
- focus-me="focus_username" select-me="focus_username"
- placeholder="Username" ng-model="args.username"/>
- </div>
+ <form ng-submit="login(args)" name="sc-login-form"
+ autocomplete="off" class="form-horizontal" role="form">
+ <div class="form-group">
+ <label class="col-md-4 control-label" for="login-username">[% l('Username or Barcode') %]</label>
+ <div class="col-md-8">
+ <input type="text" id="login-username" class="form-control"
+ focus-me="focus_username" select-me="focus_username"
+ placeholder="Username" ng-model="args.username"/>
</div>
+ </div>
- <div class="form-group">
- <label class="col-md-4 control-label" for="login-password">[% l('Password') %]</label>
- <div class="col-md-8">
- <input type="password" id="login-password" class="form-control"
- placeholder="Password" ng-model="args.password"/>
- </div>
+ <div class="form-group" ng-if="password_required">
+ <label class="col-md-4 control-label" for="login-password">[% l('Password') %]</label>
+ <div class="col-md-8">
+ <input type="password" id="login-password" class="form-control"
+ placeholder="Password" ng-model="args.password"/>
</div>
+ </div>
- <div class="form-group">
- <div class="col-md-offset-4 col-md-2">
- <button type="submit" class="btn btn-default">[% l('Log in') %]</button>
- </div>
- <div class="col-md-2">
- <span ng-show="login_failed" class="label label-warning">[% l('Login Failed') %]</span>
- </div>
+ <div class="form-group">
+ <div class="col-md-offset-4 col-md-2">
+ <button type="submit" class="btn btn-default">[% l('Log in') %]</button>
</div>
+ <div class="col-md-2">
+ <span ng-show="login_failed" class="label label-warning">[% l('Login Failed') %]</span>
+ </div>
+ </div>
- </form>
- </fieldset>
- </div>
- <div class="col-md-3"></div>
- </div>
+ </form>
+ </fieldset>
+ </div>
+ <div class="col-md-3"></div>
</div>
* Self-Checkout App
*/
+/*
+ * TODO: add support auth.js for forcing a re-login when navigating
+ * away from the selfcheck UI. Consider sessionStorage item
+ * that restricts access.
+ */
+
angular.module('egSelfCheckApp',
['ngRoute', 'ui.bootstrap', 'egCoreMod', 'egUiMod', 'ngToast'])
resolve : resolver
});
+ $routeProvider.when('/circ/selfcheck/items', {
+ templateUrl: './circ/selfcheck/t_items',
+ controller: 'ItemsCtrl',
+ resolve : resolver
+ });
+
$routeProvider.otherwise({redirectTo : '/circ/selfcheck/login'});
})
};
+ // called with each path load
+ service.new_path_init = function() {
+ if (!service.patron)
+ return service.logout_patron();
+ service.reset_login_timer();
+ }
+
service.show_timeout_warning = function() {
- // TODO: force logout after warning timeout
egConfirmDialog.open(
egCore.strings.CONFIRM_TIMEOUT_TITLE,
egCore.strings.CONFIRM_TIMEOUT_LOGOUT
);
+ // If the patron choses no action from the above dialog,
+ // force a logout after the configured amount of time.
service.login_warning_timer = $timeout(
service.logout_patron, service.login_timeout_warning
);
});
}
+ /*
+ * Returns true if the username string looks like a barcode.
+ */
+ service.username_is_barcode = function(username) {
+ var regstr =
+ egCore.env.aous['circ.selfcheck.patron_password_required'];
+ if (regstr) {
+ var reg = new RegExp(regstr);
+ return reg && username.match(reg);
+ }
+ return false;
+ }
+
+ /*
+ * Test password if required, then fetch the user data.
+ */
service.login_patron = function(username, password) {
- // TODO: test barcode regex
- var barcode = null;
+ var barcode;
+ if (service.username_is_barcode(username)) {
+ barcode = username;
+ username = null;
+ }
- if (true) { // TODO: test password required
+ if (egCore.env.aous['circ.selfcheck.patron_password_required']) {
return egCore.auth.verify({
username : username,
barcode : barcode,
}
}
+ /*
+ * Return to the login page via full page load to clear
+ * stored user data.
+ */
service.logout_patron = function() {
- // force a page reload to clear all cached data.
$window.location.href = $location.absUrl().replace(
/\/selfcheck\/.*/, '/selfcheck/login');
}
+ /*
+ * Returns a notify-stream of open circ blobs.
+ * Resets total circ count to match the server.
+ */
+ service.get_items_out = function() {
+ service.total_circ_count = 0;
+ return egCore.net.request(
+ 'open-ils.circ',
+ 'open-ils.circ.actor.user.checked_out',
+ egCore.auth.token(), service.patron.id()
+ ).then(null, null, function(circ_blob) {
+ service.total_circ_count++;
+ return circ_blob;
+ });
+ }
+
return service;
}])
return $location.path() == '/circ/selfcheck/login';
}
+ $scope.dyn_content_class = function() {
+ return $scope.is_login_page() ? 'col-md-12' : 'col-md-8';
+ }
+
$scope.scanbox = {
text : '',
focus : false,
$scope.patron = function() { return scSvc.patron }
+ $scope.show_pane = function(name) {
+ if (name && name.match(/(login|checkout|items|holds|fines)$/)) {
+ console.log('navigating to pane ' + name);
+ $location.path('/circ/selfcheck/' + name);
+ }
+ }
+
}])
['$scope','$q','$location','egCore','scSvc',
function($scope, $q, $location , egCore, scSvc) {
+ $scope.focus_username = true;
+ $scope.password_required =
+ egCore.env.aous['circ.selfcheck.patron_password_required'];
+
$scope.login = function(args) {
$scope.login_failed = false;
if (!args.username) return;
+ if ($scope.password_required && !args.password) return;
scSvc.login_patron(args.username, args.password).then(
function() {
.controller('CheckoutCtrl',
['$scope','$q','$location','egCore','scSvc',
function($scope, $q, $location , egCore, scSvc) {
+ scSvc.new_path_init();
+ $scope.scanbox.focus = true;
- if (!scSvc.patron) {
- $location.path('/circ/selfcheck/login');
- return;
- }
+}])
- scSvc.reset_login_timer();
+.controller('ItemsCtrl',
+ ['$scope','$q','$location','egCore','scSvc',
+function($scope, $q, $location , egCore, scSvc) {
+ scSvc.new_path_init();
$scope.scanbox.focus = true;
+ $scope.circs = [];
+
+ scSvc.get_items_out().then(null, null,
+ function(circ_blob) { $scope.circs.push(circ_blob) });
}])