1 function display_pickup_location (state) {
3 if ( state.needs_override === true ) {
5 '<span>' + state.text + '</span> <span style="float:right;" title="' +
6 _("This pickup location is not allowed according to circulation rules") +
7 '"><i class="fa fa-exclamation-circle" aria-hidden="true"></i></span>'
11 $text = $('<span>'+state.text+'</span>');
20 * Generate a Select2 dropdown for pickup locations
22 * It expects the select object to contain several data-* attributes
23 * - data-pickup-location-source: 'biblio', 'item' or 'hold' (default)
24 * - data-patron-id: required for 'biblio' and 'item'
25 * - data-biblio-id: required for 'biblio' only
26 * - data-item-id: required for 'item' only
28 * @return {Object} The Select2 instance
31 $.fn.pickup_locations_dropdown = function () {
33 var pickup_location_source = $(this).data('pickup-location-source');
34 var patron_id = $(this).data('patron-id');
35 var biblio_id = $(this).data('biblio-id');
36 var item_id = $(this).data('item-id');
37 var hold_id = $(this).data('hold-id');
41 if ( pickup_location_source === 'biblio' ) {
42 url = '/api/v1/biblios/' + encodeURIComponent(biblio_id) + '/pickup_locations';
44 else if ( pickup_location_source === 'item' ) {
45 url = '/api/v1/items/' + encodeURIComponent(item_id) + '/pickup_locations';
48 url = '/api/v1/holds/' + encodeURIComponent(hold_id) + '/pickup_locations';
56 delay: 300, // wait 300 milliseconds before triggering the request
59 data: function (params) {
60 var search_term = (params.term === undefined) ? '' : params.term;
62 "q": JSON.stringify({"name":{"-like":'%'+search_term+'%'}}),
67 if ( pickup_location_source !== 'hold' ) {
68 query["patron_id"] = patron_id;
73 processResults: function (data) {
75 data.results.forEach( function ( pickup_location ) {
78 "id": pickup_location.library_id.escapeHtml(),
79 "text": pickup_location.name.escapeHtml(),
80 "needs_override": pickup_location.needs_override
84 return { "results": results, "pagination": { "more": data.pagination.more } };
86 transport: kohaSelect2Transport,
88 templateResult: display_pickup_location
95 /* global __ dataTablesDefaults borrowernumber SuspendHoldsIntranet */
96 $(document).ready(function() {
98 function suspend_hold(hold_id, end_date) {
101 if ( end_date !== null && end_date !== '' ) params = JSON.stringify({ "end_date": end_date });
105 url: '/api/v1/holds/'+encodeURIComponent(hold_id)+'/suspension',
106 contentType: 'application/json',
111 function resume_hold(hold_id) {
114 url: '/api/v1/holds/'+encodeURIComponent(hold_id)+'/suspension'
120 // Don't load holds table unless it is clicked on
121 $("#holds-tab").on( "click", function(){ load_holds_table() } );
123 // If the holds tab is preselected on load, we need to load the table
124 if ( $("#holds-tab").parent().hasClass('ui-state-active') ) { load_holds_table() }
126 function load_holds_table() {
127 var holds = new Array();
128 if ( ! holdsTable ) {
130 holdsTable = $("#holds-table").dataTable($.extend(true, {}, dataTablesDefaults, {
135 "data": { _: "reservedate_formatted", "sort": "reservedate" }
138 "mDataProp": function ( oObj ) {
139 title = "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber="
142 + oObj.title.escapeHtml();
144 $.each(oObj.subtitle, function( index, value ) {
145 title += " " + value.escapeHtml();
148 title += " " + oObj.part_number + " " + oObj.part_name;
150 if ( oObj.enumchron ) {
151 title += " (" + oObj.enumchron.escapeHtml() + ")";
157 title += " " + __("by _AUTHOR_").replace("_AUTHOR_", oObj.author.escapeHtml());
160 if ( oObj.itemnotes ) {
162 if ( flatpickr.formatDate( new Date(oObj.issuedate), "Y-m-d" ) == ymd ){
163 span_class = "circ-hlt";
165 title += " - <span class='" + span_class + "'>" + oObj.itemnotes.escapeHtml() + "</span>"
172 "mDataProp": function( oObj ) {
173 return oObj.itemcallnumber && oObj.itemcallnumber.escapeHtml() || "";
177 "mDataProp": function( oObj ) {
179 if ( oObj.barcode ) {
180 data += " <a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber="
187 + oObj.barcode.escapeHtml()
194 "mDataProp": function( oObj ) {
195 if( oObj.branches.length > 1 && oObj.found !== 'W' && oObj.found !== 'T' ){
196 var branchSelect='<select priority='+oObj.priority+' class="hold_location_select" data-hold-id="'+oObj.reserve_id+'" reserve_id="'+oObj.reserve_id+'" name="pick-location" data-pickup-location-source="hold">';
197 for ( var i=0; i < oObj.branches.length; i++ ){
200 if( oObj.branches[i].selected ){
202 selectedbranch = " selected='selected' ";
203 setbranch = __(" (current) ");
204 } else if ( oObj.branches[i].pickup_location == 0 ) {
210 branchSelect += '<option value="'+ oObj.branches[i].branchcode.escapeHtml() +'"'+selectedbranch+'>'+oObj.branches[i].branchname.escapeHtml()+setbranch+'</option>';
212 branchSelect +='</select>';
215 else { return oObj.branchcode.escapeHtml() || ""; }
218 { "data": { _: "expirationdate_formatted", "sort": "expirationdate" } },
220 "mDataProp": function( oObj ) {
221 if ( oObj.priority && parseInt( oObj.priority ) && parseInt( oObj.priority ) > 0 ) {
222 return oObj.priority;
230 "mDataProp": function( oObj ) {
231 return "<select name='rank-request'>"
232 +"<option value='n'>" + __("No") + "</option>"
233 +"<option value='del'>" + __("Yes") + "</option>"
235 + "<input type='hidden' name='biblionumber' value='" + oObj.biblionumber + "'>"
236 + "<input type='hidden' name='borrowernumber' value='" + borrowernumber + "'>"
237 + "<input type='hidden' name='reserve_id' value='" + oObj.reserve_id + "'>";
242 "visible": SuspendHoldsIntranet,
243 "mDataProp": function( oObj ) {
244 holds[oObj.reserve_id] = oObj; //Store holds for later use
248 } else if ( oObj.suspend == 1 ) {
249 return "<a class='hold-resume btn btn-default btn-xs' data-hold-id='" + oObj.reserve_id + "'>"
250 +"<i class='fa fa-play'></i> " + __("Resume") + "</a>";
252 return "<a class='hold-suspend btn btn-default btn-xs' data-hold-id='" + oObj.reserve_id + "' data-hold-title='"+ oObj.title +"'>"
253 +"<i class='fa fa-pause'></i> " + __("Suspend") + "</a>";
258 "mDataProp": function( oObj ) {
261 if ( oObj.suspend == 1 ) {
262 data += "<p>" + __("Hold is <strong>suspended</strong>");
263 if ( oObj.suspend_until ) {
264 data += " " + __("until %s").format(oObj.suspend_until_formatted);
269 if ( oObj.itemtype_limit ) {
270 data += __("Next available %s item").format(oObj.itemtype_limit);
273 if ( oObj.barcode ) {
275 if ( oObj.found == "W" ) {
277 if ( oObj.waiting_here ) {
278 data += __("Item is <strong>waiting here</strong>");
279 if (oObj.desk_name) {
280 data += ", " + __("at %s").format(oObj.desk_name.escapeHtml());
283 data += __("Item is <strong>waiting</strong>");
284 data += " " + __("at %s").format(oObj.waiting_at);
285 if (oObj.desk_name) {
286 data += ", " + __("at %s").format(oObj.desk_name.escapeHtml());
291 } else if ( oObj.transferred ) {
292 data += __("Item is <strong>in transit</strong> from %s since %s").format(oObj.from_branch, oObj.date_sent);
293 } else if ( oObj.not_transferred ) {
294 data += __("Item hasn't been transferred yet from %s").format(oObj.not_transferred_by);
304 "bServerSide": false,
306 "url": '/cgi-bin/koha/svc/holds',
307 "data": function ( d ) {
308 d.borrowernumber = borrowernumber;
313 $('#holds-table').on( 'draw.dt', function () {
314 $(".hold-suspend").on( "click", function() {
315 var hold_id = $(this).data('hold-id');
316 var hold_title = $(this).data('hold-title');
317 $("#suspend-modal-title").html( hold_title );
318 $("#suspend-modal-submit").data( 'hold-id', hold_id );
319 $('#suspend-modal').modal('show');
322 $(".hold-resume").on("click", function () {
323 var hold_id = $(this).data('hold-id');
326 ).success(function () {
327 holdsTable.api().ajax.reload();
328 }).error(function (jqXHR, textStatus, errorThrown) {
329 if (jqXHR.status === 404) {
330 alert(__("Unable to resume, hold not found"));
331 holdsTable.api().ajax.reload();
336 $(".hold_location_select").each(function(){ $(this).pickup_locations_dropdown(); });
338 $(".hold_location_select").on("change", function(){
339 $(this).prop("disabled",true);
340 var cur_select = $(this);
341 var res_id = $(this).attr('reserve_id');
342 $(this).after('<div id="updating_reserveno'+res_id+'" class="waiting"><img src="/intranet-tmpl/prog/img/spinner-small.gif" alt="" /><span class="waiting_msg"></span></div>');
343 var api_url = '/api/v1/holds/' + encodeURIComponent(res_id) + '/pickup_location';
347 data: JSON.stringify({ "pickup_library_id": $(this).val() }),
348 headers: { "x-koha-override": "any" },
349 success: function( data ){ holdsTable.api().ajax.reload(); },
350 error: function( jqXHR, textStatus, errorThrown) {
351 alert('There was an error:'+textStatus+" "+errorThrown);
352 cur_select.prop("disabled",false);
353 $("#updating_reserveno"+res_id).remove();
354 cur_select.val( cur_select.children('option[selected="selected"]').val() );
361 if ( $("#holds-table").length ) {
362 $("#holds-table_processing").position({
363 of: $( "#holds-table" ),
371 <div id='suspend-modal' class='modal fade' role='dialog' aria-hidden='true'>\
372 <div class='modal-dialog'>\
373 <div class='modal-content'>\
374 <form id='suspend-modal-form' class='form-inline'>\
375 <div class='modal-header'>\
376 <button type='button' class='closebtn' data-dismiss='modal' aria-hidden='true'>×</button>\
377 <h3 id='suspend-modal-label'>" + __("Suspend hold on") + " <i><span id='suspend-modal-title'></span></i></h3>\
380 <div class='modal-body'>\
381 <input type='hidden' id='suspend-modal-reserve_id' name='reserve_id' />\
383 <label for='suspend-modal-until'>" + __("Suspend until:") + "</label>\
384 <input name='suspend_until' id='suspend-modal-until' class='suspend-until' size='10' />\
386 <p><a class='btn btn-link' id='suspend-modal-clear-date' >" + __("Clear date to suspend indefinitely") + "</a></p>\
390 <div class='modal-footer'>\
391 <button id='suspend-modal-submit' class='btn btn-primary' type='submit' name='submit'>" + __("Suspend") + "</button>\
392 <a href='#' data-dismiss='modal' aria-hidden='true' class='cancel'>" + __("Cancel") + "</a>\
400 $("#suspend-modal-until").flatpickr({
401 minDate: new Date().fp_incr(1) // Require that "until date" be in the future
403 $("#suspend-modal-clear-date").on( "click", function() { $("#suspend-modal-until").val(""); } );
405 $("#suspend-modal-submit").on( "click", function( e ) {
407 var suspend_until_date = $("#suspend-modal-until").val();
408 if ( suspend_until_date !== null ) suspend_until_date = $date(suspend_until_date, {dateformat:"rfc3339"});
410 $(this).data('hold-id'),
412 ).success(function () {
413 holdsTable.api().ajax.reload();
414 }).error(function (jqXHR, textStatus, errorThrown) {
415 if (jqXHR.status === 404) {
416 alert(__("Unable to resume, hold not found"));
417 holdsTable.api().ajax.reload();
420 $("#suspend-modal-until").val(""); // clean the input
421 $('#suspend-modal').modal('hide');