--- /dev/null
+<div class="container-fluid" style="text-align:center">
+ <div class="alert alert-info alert-less-pad strong-text-2">
+ <span>[% l('Holds Pull List') %]</span>
+ </div>
+</div>
+
+<div class="pad-vert"></div>
+
+<div ng-if="!detail_hold_id">
+[% INCLUDE 'staff/circ/holds/t_pull_list.tt2' %]
+</div>
+
+<!-- hold details -->
+<div ng-if="detail_hold_id">
+ <div class="row">
+ <div class="col-md-2">
+ <button class="btn btn-default" ng-click="list_view()">
+ [% l('List View') %]
+ </button>
+ </div>
+ </div>
+ <div class="pad-vert"></div>
+ <eg-record-summary record='detail_hold_record'
+ record-id="detail_hold_record_id"></eg-record-summary>
+ <eg-hold-details hold-retrieved="set_hold" hold-id="detail_hold_id"></eg-hold-details>
+</div>
--- /dev/null
+<eg-grid
+ id-field="id"
+ features="-sort,-multisort"
+ items-provider="gridDataProvider"
+ persist-key="circ.holds.pull">
+
+ <eg-grid-menu-item handler="detail_view"
+ label="[% l('Detail View') %]"></eg-grid-menu-item>
+
+ <eg-grid-action handler="grid_actions.show_recent_circs"
+ label="[% l('Show Last Few Circulations') %]"></eg-grid-action>
+ <eg-grid-action divider="true"></eg-grid-action>
+ <eg-grid-action handler="grid_actions.set_copy_quality"
+ label="[% l('Set Desired Copy Quality') %]"></eg-grid-action>
+ <eg-grid-action handler="grid_actions.edit_pickup_lib"
+ label="[% l('Edit Pickup Library') %]"></eg-grid-action>
+ <eg-grid-action handler="grid_actions.edit_notify_prefs"
+ label="[% l('Edit Notification Settings') %]"></eg-grid-action>
+ <eg-grid-action handler="grid_actions.edit_dates"
+ label="[% l('Edit Hold Dates') %]"></eg-grid-action>
+ <eg-grid-action handler="grid_actions.activate"
+ label="[% l('Activate') %]"></eg-grid-action>
+ <eg-grid-action handler="grid_actions.suspend"
+ label="[% l('Suspend') %]"></eg-grid-action>
+ <eg-grid-action handler="grid_actions.set_top_of_queue"
+ label="[% l('Set Top of Queue') %]"></eg-grid-action>
+ <eg-grid-action handler="grid_actions.clear_top_of_queue"
+ label="[% l('Un-Set Top of Queue') %]"></eg-grid-action>
+ <eg-grid-action handler="grid_actions.transfer_to_marked_title"
+ label="[% l('Transfer To Marked Title') %]"></eg-grid-action>
+ <eg-grid-action handler="grid_actions.mark_damaged"
+ label="[% l('Mark Item Damaged') %]"></eg-grid-action>
+ <eg-grid-action handler="grid_actions.mark_missing"
+ label="[% l('Mark Item Missing') %]"></eg-grid-action>
+ <eg-grid-action divider="true"></eg-grid-action>
+ <eg-grid-action handler="grid_actions.retarget"
+ label="[% l('Find Another Target') %]"></eg-grid-action>
+ <eg-grid-action handler="grid_actions.cancel_hold"
+ label="[% l('Cancel Hold') %]"></eg-grid-action>
+
+ <eg-grid-field label="[% l('Hold ID') %]" path='hold.id'></eg-grid-field>
+ <eg-grid-field label="[% l('Current Copy') %]"
+ path='hold.current_copy.barcode'>
+ <a href="./cat/item/{{item.hold.current_copy().id()}}/summary" target="_self">
+ {{item.hold.current_copy().barcode()}}
+ </a>
+ </eg-grid-field>
+
+ <eg-grid-field label="[% l('Request Date') %]" path='hold.request_time'></eg-grid-field>
+ <eg-grid-field label="[% l('Hold Type') %]" path='hold.hold_type'></eg-grid-field>
+ <eg-grid-field label="[% l('Pickup Library') %]" path='hold.pickup_lib.shortname'></eg-grid-field>
+ <eg-grid-field label="[% l('Copy Location') %]" path='copy.location.name'></eg-grid-field>
+ <eg-grid-field label="[% l('Call Number') %]" path='volume.label'></eg-grid-field>
+
+ <eg-grid-field label="[% l('Title') %]" path='mvr.title'>
+ <a href="[% ctx.base_path %]/opac/record/{{item.mvr.doc_id()}}">
+ {{item.mvr.title()}}
+ </a>
+ </eg-grid-field>
+
+ <eg-grid-field label="[% l('Author') %]" path='mvr.author'></eg-grid-field>
+ <eg-grid-field label="[% l('Potential Copies') %]" path='potential_copies'></eg-grid-field>
+ <eg-grid-field label="[% l('Status') %]" path='status_string' hidden></eg-grid-field>
+
+ <eg-grid-field label="[% l('Queue Position') %]" path='queue_position' hidden></eg-grid-field>
+ <eg-grid-field path='hold.*' parent-idl-class="ahr" hidden></eg-grid-field>
+ <eg-grid-field path='copy.*' parent-idl-class="acp" hidden></eg-grid-field>
+ <eg-grid-field path='volume.*' parent-idl-class="acn" hidden></eg-grid-field>
+ <eg-grid-field path='mvr.*' parent-idl-class="mvr" hidden></eg-grid-field>
+</eg-grid>
+
+<div class="container-fluid" style="text-align:center">
+ <div class="alert alert-info alert-less-pad strong-text-2">
+ <span>[% l('Holds Shelf') %]</span>
+ </div>
+</div>
+
<div class="row">
<div class="col-md-3">
<div class="input-group">
<eg-grid-menu-item handler="clear_holds" disabled="disable_clear"
label="[% l('Clear These Holds') %]"></eg-grid-menu-item>
- <eg-grid-action handler="show_recent_circs"
+ <eg-grid-action handler="grid_actions.show_recent_circs"
label="[% l('Show Last Few Circulations') %]"></eg-grid-action>
<eg-grid-action divider="true"></eg-grid-action>
- <eg-grid-action handler="set_copy_quality"
+ <eg-grid-action handler="grid_actions.set_copy_quality"
label="[% l('Set Desired Copy Quality') %]"></eg-grid-action>
- <eg-grid-action handler="edit_pickup_lib"
+ <eg-grid-action handler="grid_actions.edit_pickup_lib"
label="[% l('Edit Pickup Library') %]"></eg-grid-action>
- <eg-grid-action handler="edit_notify_prefs"
+ <eg-grid-action handler="grid_actions.edit_notify_prefs"
label="[% l('Edit Notification Settings') %]"></eg-grid-action>
- <eg-grid-action handler="edit_dates"
+ <eg-grid-action handler="grid_actions.edit_dates"
label="[% l('Edit Hold Dates') %]"></eg-grid-action>
- <eg-grid-action handler="activate"
+ <eg-grid-action handler="grid_actions.activate"
label="[% l('Activate') %]"></eg-grid-action>
- <eg-grid-action handler="suspend"
+ <eg-grid-action handler="grid_actions.suspend"
label="[% l('Suspend') %]"></eg-grid-action>
- <eg-grid-action handler="set_top_of_queue"
+ <eg-grid-action handler="grid_actions.set_top_of_queue"
label="[% l('Set Top of Queue') %]"></eg-grid-action>
- <eg-grid-action handler="clear_top_of_queue"
+ <eg-grid-action handler="grid_actions.clear_top_of_queue"
label="[% l('Un-Set Top of Queue') %]"></eg-grid-action>
- <eg-grid-action handler="transfer_to_marked_title"
+ <eg-grid-action handler="grid_actions.transfer_to_marked_title"
label="[% l('Transfer To Marked Title') %]"></eg-grid-action>
- <eg-grid-action handler="mark_damaged"
+ <eg-grid-action handler="grid_actions.mark_damaged"
label="[% l('Mark Item Damaged') %]"></eg-grid-action>
- <eg-grid-action handler="mark_missing"
+ <eg-grid-action handler="grid_actions.mark_missing"
label="[% l('Mark Item Missing') %]"></eg-grid-action>
<eg-grid-action divider="true"></eg-grid-action>
- <eg-grid-action handler="retarget"
+ <eg-grid-action handler="grid_actions.retarget"
label="[% l('Find Another Target') %]"></eg-grid-action>
- <eg-grid-action handler="cancel_hold"
+ <eg-grid-action handler="grid_actions.cancel_hold"
label="[% l('Cancel Hold') %]"></eg-grid-action>
<eg-grid-field label="[% l('Hold ID') %]" path='hold.id'></eg-grid-field>
<eg-grid-menu-item handler="detail_view"
label="[% l('Detail View') %]"></eg-grid-menu-item>
- <eg-grid-action handler="show_recent_circs"
+ <eg-grid-action handler="grid_actions.show_recent_circs"
label="[% l('Show Last Few Circulations') %]"></eg-grid-action>
<eg-grid-action divider="true"></eg-grid-action>
- <eg-grid-action handler="set_copy_quality"
+ <eg-grid-action handler="grid_actions.set_copy_quality"
label="[% l('Set Desired Copy Quality') %]"></eg-grid-action>
- <eg-grid-action handler="edit_pickup_lib"
+ <eg-grid-action handler="grid_actions.edit_pickup_lib"
label="[% l('Edit Pickup Library') %]"></eg-grid-action>
- <eg-grid-action handler="edit_notify_prefs"
+ <eg-grid-action handler="grid_actions.edit_notify_prefs"
label="[% l('Edit Notification Settings') %]"></eg-grid-action>
- <eg-grid-action handler="edit_dates"
+ <eg-grid-action handler="grid_actions.edit_dates"
label="[% l('Edit Hold Dates') %]"></eg-grid-action>
- <eg-grid-action handler="activate"
+ <eg-grid-action handler="grid_actions.activate"
label="[% l('Activate') %]"></eg-grid-action>
- <eg-grid-action handler="suspend"
+ <eg-grid-action handler="grid_actions.suspend"
label="[% l('Suspend') %]"></eg-grid-action>
- <eg-grid-action handler="set_top_of_queue"
+ <eg-grid-action handler="grid_actions.set_top_of_queue"
label="[% l('Set Top of Queue') %]"></eg-grid-action>
- <eg-grid-action handler="clear_top_of_queue"
+ <eg-grid-action handler="grid_actions.clear_top_of_queue"
label="[% l('Un-Set Top of Queue') %]"></eg-grid-action>
- <eg-grid-action handler="transfer_to_marked_title"
+ <eg-grid-action handler="grid_actions.transfer_to_marked_title"
label="[% l('Transfer To Marked Title') %]"></eg-grid-action>
- <eg-grid-action handler="mark_damaged"
+ <eg-grid-action handler="grid_actions.mark_damaged"
label="[% l('Mark Item Damaged') %]"></eg-grid-action>
- <eg-grid-action handler="mark_missing"
+ <eg-grid-action handler="grid_actions.mark_missing"
label="[% l('Mark Item Missing') %]"></eg-grid-action>
<eg-grid-action divider="true"></eg-grid-action>
- <eg-grid-action handler="retarget"
+ <eg-grid-action handler="grid_actions.retarget"
label="[% l('Find Another Target') %]"></eg-grid-action>
- <eg-grid-action handler="cancel_hold"
+ <eg-grid-action handler="grid_actions.cancel_hold"
label="[% l('Cancel Hold') %]"></eg-grid-action>
<eg-grid-field label="[% l('Hold ID') %]" path='hold.id'></eg-grid-field>
</a>
</li>
<li>
+ <a href="./circ/holds/pull" target="_self">
+ <span class="glyphicon glyphicon-th-list"></span>
+ [% l('Pull List for Hold Requests') %]
+ </a>
+ </li>
+ <li>
<a href="./circ/renew/renew" target="_self">
<span class="glyphicon glyphicon-refresh"></span>
[% l('Renew Items') %]
resolve : resolver
});
+ $routeProvider.when('/circ/holds/pull', {
+ templateUrl: './circ/holds/t_pull',
+ controller: 'HoldsPullListCtrl',
+ resolve : resolver
+ });
+
+ $routeProvider.when('/circ/holds/pull/:hold_id', {
+ templateUrl: './circ/holds/t_pull',
+ controller: 'HoldsPullListCtrl',
+ resolve : resolver
+ });
+
$routeProvider.otherwise({redirectTo : '/circ/holds/shelf'});
})
+.factory('holdUiSvc', function() {
+ return {
+ holds : [] // cache
+ }
+})
+
.controller('HoldsShelfCtrl',
- ['$scope','$q','$routeParams','$window','$location','egCore','egHolds','egCirc','egGridDataProvider',
-function($scope , $q , $routeParams , $window , $location , egCore , egHolds , egCirc , egGridDataProvider) {
+ ['$scope','$q','$routeParams','$window','$location','egCore','egHolds','egHoldGridActions','egCirc','egGridDataProvider',
+function($scope , $q , $routeParams , $window , $location , egCore , egHolds , egHoldGridActions , egCirc , egGridDataProvider) {
$scope.detail_hold_id = $routeParams.hold_id;
var hold_ids = [];
var holds = [];
var clear_mode = false;
$scope.gridControls = {};
+ $scope.grid_actions = egHoldGridActions;
function fetch_holds(offset, count) {
var ids = hold_ids.slice(offset, offset + count);
var provider = egGridDataProvider.instance({});
$scope.gridDataProvider = provider;
+ function refresh_page() {
+ holds = [];
+ hold_ids = [];
+ provider.refresh();
+ }
+ // called after any egHoldGridActions action occurs
+ $scope.grid_actions.refresh = refresh_page;
+
provider.get = function(offset, count) {
// see if we have the requested range cached
return deferred.promise;
}
- function refresh_page() {
- holds = [];
- hold_ids = [];
- provider.refresh();
- }
-
-
// re-draw the grid when user changes the org selector
$scope.pickup_ou = egCore.org.get(egCore.auth.user().ws_ou());
$scope.$watch('pickup_ou', function(newVal, oldVal) {
$scope.show_active = function() { clear_mode = false; refresh_page() }
$scope.disable_clear = function() { return clearing || !clear_mode }
- // action handlers
- // TODO: These are copied directly from patron/holds.js.
- // Consider refactoring / consolidating.
- $scope.cancel_hold = function(items) {
- var hold_ids = items.filter(function(item) {
- return !item.hold.cancel_time();
- }).map(function(item) {return item.hold.id()});
-
- return egHolds.cancel_holds(hold_ids).then(refresh_page);
- }
-
- // jump to circ list for either 1) the targeted copy or
- // 2) the hold target copy for copy-level holds
- $scope.show_recent_circs = function(items) {
- if (items.length && (copy = items[0].copy)) {
- var url = $location.path(
- '/cat/item/' + copy.id() + '/circ_list').absUrl();
- $window.open(url, '_blank').focus();
- }
- }
-
- function generic_update(items, action) {
- if (!items.length) return $q.when();
- var hold_ids = items.map(function(item) {return item.hold.id()});
- return egHolds[action](hold_ids).then(refresh_page);
- }
-
- $scope.set_copy_quality = function(items) {
- generic_update(items, 'set_copy_quality'); }
- $scope.edit_pickup_lib = function(items) {
- generic_update(items, 'edit_pickup_lib'); }
- $scope.edit_notify_prefs = function(items) {
- generic_update(items, 'edit_notify_prefs'); }
- $scope.edit_dates = function(items) {
- generic_update(items, 'edit_dates'); }
- $scope.suspend = function(items) {
- generic_update(items, 'suspend_holds'); }
- $scope.activate = function(items) {
- generic_update(items, 'activate_holds'); }
- $scope.set_top_of_queue = function(items) {
- generic_update(items, 'set_top_of_queue'); }
- $scope.clear_top_of_queue = function(items) {
- generic_update(items, 'clear_top_of_queue'); }
- $scope.transfer_to_marked_title = function(items) {
- generic_update(items, 'transfer_to_marked_title'); }
-
- $scope.mark_damaged = function(items) {
- var copy_ids = items
- .filter(function(item) { return Boolean(item.copy) })
- .map(function(item) { return item.copy.id() });
- if (copy_ids.length)
- egCirc.mark_damaged(copy_ids).then(refresh_page);
- }
-
- $scope.mark_missing = function(items) {
- var copy_ids = items
- .filter(function(item) { return Boolean(item.copy) })
- .map(function(item) { return item.copy.id() });
- if (copy_ids.length)
- egCirc.mark_missing(copy_ids).then(refresh_page);
- }
-
- $scope.retarget = function(items) {
- var hold_ids = items.map(function(item) { return item.hold.id() });
- egHolds.retarget(hold_ids).then(refresh_page);
- }
-
-
// udpate the in-grid hold with the clear-shelf cached response info.
function handle_clear_cache_resp(resp) {
if (!angular.isArray(resp)) resp = [resp];
refresh_page();
-}]);
+}])
+
+.controller('HoldsPullListCtrl',
+ ['$scope','$q','$routeParams','$window','$location','egCore','egHolds','egCirc','egGridDataProvider','egHoldGridActions','holdUiSvc',
+function($scope , $q , $routeParams , $window , $location , egCore , egHolds , egCirc , egGridDataProvider , egHoldGridActions , holdUiSvc) {
+ $scope.detail_hold_id = $routeParams.hold_id;
+
+ var provider = egGridDataProvider.instance({});
+ $scope.gridDataProvider = provider;
+
+ $scope.grid_actions = egHoldGridActions;
+ $scope.grid_actions.refresh = function() {
+ holdUiSvc.holds = [];
+ provider.refresh();
+ }
+
+ provider.get = function(offset, count) {
+
+ if (holdUiSvc.holds[offset]) {
+ return provider.arrayNotifier(holdUiSvc.holds, offset, count);
+ }
+
+ var deferred = $q.defer();
+ var recv_index = 0;
+
+ // fetch the IDs
+ egCore.net.request(
+ 'open-ils.circ',
+ 'open-ils.circ.hold_pull_list.fleshed.stream',
+ egCore.auth.token(), count, offset
+ ).then(
+ deferred.resolve, null,
+ function(hold_data) {
+ egHolds.local_flesh(hold_data);
+ holdUiSvc.holds[offset + recv_index++] = hold_data;
+ deferred.notify(hold_data);
+ }
+ );
+
+ return deferred.promise;
+ }
+
+ $scope.detail_view = function(action, user_data, items) {
+ if (h = items[0]) {
+ $location.path('/circ/holds/pull/' + h.hold.id());
+ }
+ }
+
+ $scope.list_view = function(items) {
+ $location.path('/circ/holds/pull');
+ }
+
+ // when the detail hold is fetched (and updated), update the bib
+ // record summary display record id.
+ $scope.set_hold = function(hold_data) {
+ $scope.detail_hold_record_id = hold_data.mvr.doc_id();
+ }
+
+}])
angular.module('egPatronApp').controller('PatronHoldsCtrl',
['$scope','$q','$routeParams','egCore','egUser','patronSvc',
- 'egGridDataProvider','egHolds','$window','$location','egCirc',
+ 'egGridDataProvider','egHolds','$window','$location','egCirc','egHoldGridActions',
function($scope, $q, $routeParams, egCore, egUser, patronSvc,
- egGridDataProvider , egHolds , $window , $location , egCirc) {
+ egGridDataProvider , egHolds , $window , $location , egCirc, egHoldGridActions) {
$scope.initTab('holds', $routeParams.id);
$scope.holds_display = 'main';
$scope.detail_hold_id = $routeParams.hold_id;
+ $scope.grid_actions = egHoldGridActions;
function refresh_all() {
patronSvc.refreshPrimary();
patronSvc.hold_ids = [];
provider.refresh()
}
+ $scope.grid_actions.refresh = refresh_all;
$scope.show_main_list = function() {
// don't need a full reset_page() to swap tabs
function fetchHolds(offset, count) {
var ids = patronSvc.hold_ids.slice(offset, offset + count);
- return egHolds.fetch_holds(ids).then(
- function() { $scope.loading = false; },
- null,
- function(hold_data) { patronSvc.holds.push(hold_data) }
+ return egHolds.fetch_holds(ids).then(null, null,
+ function(hold_data) {
+ patronSvc.holds.push(hold_data);
+ return hold_data;
+ }
);
}
return deferred.promise;
}
- $scope.cancel_hold = function(items) {
- var hold_ids = items.filter(function(item) {
- return !item.hold.cancel_time();
- }).map(function(item) {return item.hold.id()});
-
- return egHolds.cancel_holds(hold_ids).then(refresh_all);
- }
-
- // jump to circ list for either 1) the targeted copy or
- // 2) the hold target copy for copy-level holds
- $scope.show_recent_circs = function(items) {
- if (items.length && (copy = items[0].copy)) {
- var url = $location.path(
- '/cat/item/' + copy.id() + '/circ_list').absUrl();
- $window.open(url, '_blank').focus();
- }
- }
-
- function generic_update(items, action) {
- if (!items.length) return $q.when();
- var hold_ids = items.map(function(item) {return item.hold.id()});
- return egHolds[action](hold_ids).then(refresh_all);
- }
-
- $scope.set_copy_quality = function(items) {
- generic_update(items, 'set_copy_quality'); }
- $scope.edit_pickup_lib = function(items) {
- generic_update(items, 'edit_pickup_lib'); }
- $scope.edit_notify_prefs = function(items) {
- generic_update(items, 'edit_notify_prefs'); }
- $scope.edit_dates = function(items) {
- generic_update(items, 'edit_dates'); }
- $scope.suspend = function(items) {
- generic_update(items, 'suspend_holds'); }
- $scope.activate = function(items) {
- generic_update(items, 'activate_holds'); }
- $scope.set_top_of_queue = function(items) {
- generic_update(items, 'set_top_of_queue'); }
- $scope.clear_top_of_queue = function(items) {
- generic_update(items, 'clear_top_of_queue'); }
- $scope.transfer_to_marked_title = function(items) {
- generic_update(items, 'transfer_to_marked_title'); }
-
- $scope.mark_damaged = function(items) {
- var copy_ids = items
- .filter(function(item) { return Boolean(item.copy) })
- .map(function(item) { return item.copy.id() });
- if (copy_ids.length)
- egCirc.mark_damaged(copy_ids).then(refresh_all);
- }
- $scope.mark_missing = function(items) {
- var copy_ids = items
- .filter(function(item) { return Boolean(item.copy) })
- .map(function(item) { return item.copy.id() });
- if (copy_ids.length)
- egCirc.mark_missing(copy_ids).then(refresh_all);
- }
-
- $scope.retarget = function(items) {
- var hold_ids = items.map(function(item) { return item.hold.id() });
- egHolds.retarget(hold_ids).then(refresh_all);
- }
-
$scope.print = function() {
var holds = [];
angular.forEach(patronSvc.holds, function(item) {
var service = {};
service.fetch_holds = function(hold_ids) {
+ var deferred = $q.defer();
- return egCore.net.request(
- 'open-ils.circ',
- 'open-ils.circ.hold.details.batch.retrieve.authoritative',
- egCore.auth.token(), hold_ids
-
- ).then(null, null, function(hold_data) {
- var hold = hold_data.hold;
- hold_data.id = hold.id();
- service.local_flesh(hold_data);
- return hold_data;
- });
+ // FIXME: large batches using .authoritative result in many
+ // stranded cstore backends on the server. Needs investigation.
+ // For now, collect holds in a series of small batches.
+ // Fetch them serially both to avoid the above problem and
+ // to maintain order.
+ var batch_size = 5;
+ var index = 0;
+
+ function one_batch() {
+ var ids = hold_ids.slice(index, index + batch_size)
+ .filter(function(id) {return Boolean(id)}) // avoid nulls
+
+ console.debug('egHolds.fetch_holds => ' + ids);
+ index += batch_size;
+
+ if (!ids.length) {
+ deferred.resolve();
+ return;
+ }
+
+ egCore.net.request(
+ 'open-ils.circ',
+ 'open-ils.circ.hold.details.batch.retrieve.authoritative',
+ egCore.auth.token(), ids
+
+ ).then(
+ one_batch, // kick off the next batch
+ null,
+ function(hold_data) {
+ var hold = hold_data.hold;
+ hold_data.id = hold.id();
+ service.local_flesh(hold_data);
+ deferred.notify(hold_data);
+ }
+ );
+ }
+
+ one_batch(); // kick it off
+ return deferred.promise;
}
var hold = hold_data.hold;
hold.pickup_lib(egCore.org.get(hold.pickup_lib()));
hold.current_shelf_lib(egCore.org.get(hold.current_shelf_lib()));
+ hold_data.id = hold.id();
// current_copy is not always fleshed in the API
if (hold.current_copy() && typeof hold.current_copy() != 'object')
return service;
}])
+/**
+ * Action handlers for the common Hold grid UI.
+ * These generally scrub the data for valid input then pass the
+ * holds / copies / etc. off to the relevant action in egHolds or egCirc.
+ *
+ * Caller must apply a reset_page function, which is called after
+ * most actionis are performed.
+ */
+.factory('egHoldGridActions',
+ ['$window','$location','egCore','egHolds','egCirc',
+function($window , $location , egCore , egHolds , egCirc) {
+
+ var service = {};
+
+ service.refresh = function() {
+ console.error('egHoldGridActions.refresh not defined!');
+ }
+
+ service.cancel_hold = function(items) {
+ var hold_ids = items.filter(function(item) {
+ return !item.hold.cancel_time();
+ }).map(function(item) {return item.hold.id()});
+
+ return egHolds.cancel_holds(hold_ids).then(service.refresh);
+ }
+
+ // jump to circ list for either 1) the targeted copy or
+ // 2) the hold target copy for copy-level holds
+ service.show_recent_circs = function(items) {
+ if (items.length && (copy = items[0].copy)) {
+ var url = $location.path(
+ '/cat/item/' + copy.id() + '/circ_list').absUrl();
+ $window.open(url, '_blank').focus();
+ }
+ }
+
+ function generic_update(items, action) {
+ if (!items.length) return $q.when();
+ var hold_ids = items.map(function(item) {return item.hold.id()});
+ return egHolds[action](hold_ids).then(service.refresh);
+ }
+
+ service.set_copy_quality = function(items) {
+ generic_update(items, 'set_copy_quality'); }
+ service.edit_pickup_lib = function(items) {
+ generic_update(items, 'edit_pickup_lib'); }
+ service.edit_notify_prefs = function(items) {
+ generic_update(items, 'edit_notify_prefs'); }
+ service.edit_dates = function(items) {
+ generic_update(items, 'edit_dates'); }
+ service.suspend = function(items) {
+ generic_update(items, 'suspend_holds'); }
+ service.activate = function(items) {
+ generic_update(items, 'activate_holds'); }
+ service.set_top_of_queue = function(items) {
+ generic_update(items, 'set_top_of_queue'); }
+ service.clear_top_of_queue = function(items) {
+ generic_update(items, 'clear_top_of_queue'); }
+ service.transfer_to_marked_title = function(items) {
+ generic_update(items, 'transfer_to_marked_title'); }
+
+ service.mark_damaged = function(items) {
+ var copy_ids = items
+ .filter(function(item) { return Boolean(item.copy) })
+ .map(function(item) { return item.copy.id() });
+ if (copy_ids.length)
+ egCirc.mark_damaged(copy_ids).then(service.refresh);
+ }
+
+ service.mark_missing = function(items) {
+ var copy_ids = items
+ .filter(function(item) { return Boolean(item.copy) })
+ .map(function(item) { return item.copy.id() });
+ if (copy_ids.length)
+ egCirc.mark_missing(copy_ids).then(service.refresh);
+ }
+
+ service.retarget = function(items) {
+ var hold_ids = items.map(function(item) { return item.hold.id() });
+ egHolds.retarget(hold_ids).then(service.refresh);
+ }
+
+ return service;
+}])
+
/**
* Hold details interface
*/