5 angular.module('egPatronApp').controller('PatronHoldsCtrl',
7 ['$scope','$q','$routeParams','egCore','egUser','patronSvc',
8 'egGridDataProvider','egHolds','$window','$location','egCirc','egHoldGridActions',
9 function($scope, $q, $routeParams, egCore, egUser, patronSvc,
10 egGridDataProvider , egHolds , $window , $location , egCirc, egHoldGridActions) {
12 $scope.initTab('holds', $routeParams.id);
13 $scope.holds_display = 'main';
14 $scope.detail_hold_id = $routeParams.hold_id;
15 $scope.gridControls = {};
16 $scope.grid_actions = egHoldGridActions;
18 function refresh_all() {
19 patronSvc.refreshPrimary();
21 patronSvc.hold_ids = [];
24 $scope.grid_actions.refresh = refresh_all;
26 $scope.show_main_list = function() {
27 // don't need a full reset_page() to swap tabs
28 $scope.holds_display = 'main';
30 patronSvc.hold_ids = [];
34 $scope.show_alt_list = function() {
35 // don't need a full reset_page() to swap tabs
36 $scope.holds_display = 'alt';
38 patronSvc.hold_ids = [];
42 $scope.hide_cancel_hold = function(action) {
43 return $scope.holds_display == 'alt';
46 $scope.hide_uncancel_hold = function(action) {
47 return !$scope.hide_cancel_hold();
50 var provider = egGridDataProvider.instance({});
51 $scope.gridDataProvider = provider;
53 function fetchHolds(offset, count) {
54 // TODO: LP#1697954 Fetch all holds on grid render to support
55 // client-side sorting. Migrate to server-side sorting to avoid
56 // the need for fetching all items.
58 // we're going to just fetch all the holds up front
59 //var ids = patronSvc.hold_ids.slice(offset, offset + count);
60 return egHolds.fetch_holds(patronSvc.hold_ids).then(null, null,
62 console.log('fetchHolds, hold_data',hold_data);
63 egCirc.flesh_copy_circ_library(hold_data.copy);
64 patronSvc.holds.push(hold_data);
70 /*provider.get = function(offset, count) {
72 // see if we have the requested range cached
73 if (patronSvc.holds[offset]) {
74 return provider.arrayNotifier(patronSvc.holds, offset, count);
77 // see if we have the holds IDs for this range already loaded
78 if (patronSvc.hold_ids[offset]) {
79 return fetchHolds(offset, count);
82 var deferred = $q.defer();
83 patronSvc.hold_ids = [];
85 var method = 'open-ils.circ.holds.id_list.retrieve.authoritative';
86 if ($scope.holds_display == 'alt')
87 method = 'open-ils.circ.holds.canceled.id_list.retrieve.authoritative';
91 'open-ils.circ', method,
92 egCore.auth.token(), $scope.patron_id
94 ).then(function(hold_ids) {
96 if (!hold_ids.length || hold_ids.length < offset + 1)
102 $scope.gridDataProvider.grid.totalCount = hold_ids.length;
104 patronSvc.hold_ids = hold_ids;
105 fetchHolds(offset, count)
106 .then(deferred.resolve, null, function (data) {
108 if (current >= offset && current < count) {
109 deferred.notify(data);
116 return deferred.promise;
118 provider.get = function(offset, count) {
119 console.log('get, this', this);
120 console.log('$scope', $scope);
122 // see if we have the requested range cached
123 if (patronSvc.holds[offset]) {
124 return provider.arrayNotifier(patronSvc.holds, offset, count);
128 patronSvc.holds = [];
131 fulfillment_time : null,
132 'h.usr': $scope.patron_id
134 if ($scope.holds_display == 'alt') {
135 restrictions['cancel_time'] = { not : null };
137 console.log('restrictions',restrictions);
139 var order_by = [{ shelf_expire_time : null }];
141 // NOTE: Server sorting is currently disabled entirely by the
142 // first clause in this 'if'. This is perfectly fine because
143 // clientsort always runs inside the arrayNotifier implementation
144 // in the egGrid code. However, in order to retain the memory
145 // of sorting constraints placed on us by the current server-side
146 // code, an initial "cannot sort these" array and test is added
147 // here. An alternate implementation might be to map fields to
148 // query positions, thus allowing positional ORDER BY clauses.
149 // With as many fields as the wide hold object has, this is
150 // non-trivial at the moment.
151 if (false && provider.sort && provider.sort.length) {
152 // A list of fields we can't sort on the server side. That's ok, because
153 // the grid is marked clientsort, so it always re-sorts in the browser.
155 'relative_queue_position',
156 'default_estimated_wait',
157 'min_estimated_wait',
161 'notification_count',
162 'last_notification_time',
164 'copy_location_order_position',
167 'usr_alias_or_display_name',
169 'usr_alias_or_first_given_name'
173 angular.forEach(provider.sort, function (c) {
174 if (!angular.isObject(c)) {
175 if (c.match(/^hold\./)) {
176 var i = c.replace('hold.','');
177 if (cannot_sort.includes(i)) return;
183 var i = Object.keys(c)[0];
184 var direction = c[i];
185 if (i.match(/^hold\./)) {
186 i = i.replace('hold.','');
187 if (cannot_sort.includes(i)) return;
189 ob[i] = {dir:direction};
196 // egProgressDialog.open({max : 1, value : 0});
198 return egHolds.fetch_wide_holds(
202 return provider.arrayNotifier(patronSvc.holds, offset, count);
205 function(hold_data) {
207 hold_count = hold_data;
209 // egProgressDialog.update({max:hold_count});
211 // egProgressDialog.increment();
212 var new_item = { id : hold_data.id, hold : hold_data };
213 new_item.status_string =
214 egCore.strings['HOLD_STATUS_' + hold_data.hold_status]
215 || hold_data.hold_status;
217 patronSvc.holds.push(new_item);
220 )/*.finally(egProgressDialog.close)*/;
223 $scope.print = function() {
225 angular.forEach(patronSvc.holds, function(item) {
227 hold : egCore.idl.toHash(item.hold),
228 copy : egCore.idl.toHash(item.copy),
229 volume : egCore.idl.toHash(item.volume),
230 title : item.mvr.title(),
231 author : item.mvr.author()
237 template : 'holds_for_patron',
238 scope : {patron : egCore.idl.toHash(patronSvc.current), holds : holds}
242 $scope.detail_view = function(action, user_data, items) {
244 $location.path('/circ/patron/' +
245 $scope.patron_id + '/holds/' + h.id);
249 $scope.list_view = function(items) {
250 $location.path('/circ/patron/' + $scope.patron_id + '/holds');
253 $scope.place_hold = function() {
255 egCore.hatch.setLoginSessionItem(
256 'eg.circ.patron_hold_target', patronSvc.current.card().barcode());
258 $window.location.href = '/eg2/staff/catalog';
261 // when the detail hold is fetched (and updated), update the bib
262 // record summary display record id.
263 $scope.set_hold = function(hold_data) {
264 $scope.detail_hold_record_id = hold_data.bre_id;
270 .controller('PatronHoldsCreateCtrl',
271 ['$scope','$routeParams','$location','egCore','egWorkLog','patronSvc','$cookies',
272 function($scope , $routeParams , $location , egCore , egWorkLog , patronSvc , $cookies) {
274 // set preferred and search library cookies
275 egCore.hatch.getItem('eg.search.pref_lib').then(function(lib) {
276 $cookies.put('eg_pref_lib', lib, {path: '/'});
278 egCore.hatch.getItem('eg.search.search_lib').then(function(lib) {
279 $cookies.put('eg_search_lib', lib, {path: '/'});
283 opac_hold_placed : function(hold) {
284 patronSvc.fetchUserStats(); // update hold counts
286 egCore.strings.EG_WORK_LOG_REQUESTED_HOLD,{
287 'action' : 'requested_hold',
288 'patron_id' : patronSvc.current.id(),
295 $scope.initTab('holds', $routeParams.id).then(function(isAlert) {
297 // not guarenteed to have a barcode until init fetches the user
298 $scope.handlers.patron_barcode = patronSvc.current.card().barcode();
302 $location.absUrl().replace(/\/staff\/.*/, '/opac/advanced');
304 $scope.handle_page = function(url) {