Line 0
Link Here
|
|
|
1 |
[% USE Koha %] |
2 |
[% USE Branches %] |
3 |
[% USE raw %] |
4 |
[% USE To %] |
5 |
|
6 |
[% BLOCK patron_search_filters_simple %] |
7 |
<form id="patron_search_form"> |
8 |
<div class="hint">Enter patron card number or partial name:</div> |
9 |
<input type="text" size="40" id="search_patron_filter" class="focus" autocomplete="off" /> |
10 |
<input type="submit" value="Search" /> |
11 |
</form> |
12 |
[% END %] |
13 |
|
14 |
[% BLOCK patron_search_filters %] |
15 |
<form id="patron_search_form"> |
16 |
<fieldset class="brief"> |
17 |
<h3>Search for patron</h3> |
18 |
<ol> |
19 |
<li> |
20 |
<label for="search_patron_filter">Search:</label> |
21 |
<div class="hint">Enter patron card number or partial name:</div> |
22 |
<input type="text" id="search_patron_filter" value="[% search_filter | html %]" class="focus" /> |
23 |
</li> |
24 |
|
25 |
[% FOR column IN columns %] |
26 |
[% SWITCH column %] |
27 |
[% CASE 'branch' %] |
28 |
<li> |
29 |
<label for="branchcode_filter">Library:</label> |
30 |
<select id="branchcode_filter"> |
31 |
[% SET libraries = Branches.all( only_from_group => 1 ) %] |
32 |
[% IF libraries.size != 1 %] |
33 |
<option value="">Any</option> |
34 |
[% END %] |
35 |
[% FOREACH l IN libraries %] |
36 |
<option value="[% l.branchcode | html %]">[% l.branchname | html %]</option> |
37 |
[% END %] |
38 |
</select> |
39 |
</li> |
40 |
[% CASE 'category' %] |
41 |
<li> |
42 |
<label for="categorycode_filter">Category:</label> |
43 |
<select id="categorycode_filter"> |
44 |
<option value="">Any</option> |
45 |
[% FOREACH category IN categories %] |
46 |
<option value="[% category.categorycode | html %]">[% category.description | html %]</option> |
47 |
[% END %] |
48 |
</select> |
49 |
</li> |
50 |
[% END %] |
51 |
[% END %] |
52 |
</ol> |
53 |
<fieldset class="action"> |
54 |
<input type="submit" value="Search" /> |
55 |
</fieldset> |
56 |
</fieldset> |
57 |
</form> |
58 |
[% END %] |
59 |
|
60 |
[% BLOCK patron_search_table %] |
61 |
|
62 |
[% IF filter == 'suggestions_managers' %] |
63 |
<div class="hint">Only staff with superlibrarian or suggestions_manage permissions are returned in the search results</div> |
64 |
[% ELSIF filter == 'orders_managers' %] |
65 |
<div class="hint">Only staff with superlibrarian or acquisitions permissions (or order_manage permission if granular permissions are enabled) are returned in the search results</div> |
66 |
[% ELSIF filter == 'funds_owners' OR filter == 'funds_users' %] |
67 |
<div class="hint">Only staff with superlibrarian or acquisitions permissions (or budget_modify permission if granular permissions are enabled) are returned in the search results</div> |
68 |
[% END %] |
69 |
|
70 |
<div class="browse"> |
71 |
Browse by last name: |
72 |
[% SET alphabet = Koha.Preference('alphabet').split(' ') %] |
73 |
[% UNLESS alphabet.size %] |
74 |
[% alphabet = ['A' .. 'Z'] %] |
75 |
[% END %] |
76 |
[% FOREACH letter IN alphabet %] |
77 |
<a href="#" class="filterByLetter">[% letter | html %]</a> |
78 |
[% END %] |
79 |
</div> |
80 |
|
81 |
<div id="[% table_id %]_search_results" style="display:none;"> |
82 |
|
83 |
<div id="info" class="dialog message" style="display: none;"></div> |
84 |
<div id="error" class="dialog alert" style="dispay: none;"></div> |
85 |
|
86 |
|
87 |
<input type="hidden" id="firstletter_filter" value="" /> |
88 |
[% IF open_on_row_click %] |
89 |
<table id="[% table_id %]" class="selections-table"> |
90 |
[% ELSE %] |
91 |
<table id="[% table_id %]"> |
92 |
[% END %] |
93 |
<thead> |
94 |
<tr> |
95 |
[% FOR column IN columns %] |
96 |
[% SWITCH column %] |
97 |
[% CASE 'cardnumber' %]<th>Card</th> |
98 |
[% CASE 'dateofbirth' %]<th>Date of birth</th> |
99 |
[% CASE 'name' %]<th>Name</th> |
100 |
[% CASE 'name-address' %]<th>Name</th> |
101 |
[% CASE 'address' %]<th>Address</th> |
102 |
[% CASE 'address-library' %]<th>Address</th> |
103 |
[% CASE 'branch' %]<th data-filter="libraries">Library</th> |
104 |
[% CASE 'category' %]<th data-filter="categories">Category</th> |
105 |
[% CASE 'dateexpiry' %]<th>Expires on</td> |
106 |
[% CASE 'borrowernotes' %]<th>Notes</th> |
107 |
[% CASE 'phone' %]<th>Phone</th> |
108 |
[% CASE 'action' %]<th> </th> |
109 |
[% END %] |
110 |
[% END %] |
111 |
</tr> |
112 |
</thead> |
113 |
<tbody></tbody> |
114 |
</table> |
115 |
</div> |
116 |
|
117 |
<!-- Patron preview modal --> |
118 |
<div class="modal" id="patronPreview" tabindex="-1" role="dialog" aria-labelledby="patronPreviewLabel"> |
119 |
<div class="modal-dialog" role="document"> |
120 |
<div class="modal-content"> |
121 |
<div class="modal-header"> |
122 |
<button type="button" class="closebtn" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> |
123 |
<h4 class="modal-title" id="patronPreviewLabel"></h4> |
124 |
</div> |
125 |
<div class="modal-body"> |
126 |
<div id="loading"> |
127 |
<img src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif" alt="" /> Loading |
128 |
</div> |
129 |
</div> |
130 |
<div class="modal-footer"> |
131 |
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button> |
132 |
</div> |
133 |
</div> |
134 |
</div> |
135 |
</div> |
136 |
|
137 |
[% END %] |
138 |
|
139 |
[% BLOCK patron_search_js %] |
140 |
|
141 |
[% IF redirect_if_one_result && !redirect_url %] |
142 |
<script>console.log("Wrong call of patron_searh_js - missing redirect_url");</script> |
143 |
[% END %] |
144 |
<script> |
145 |
let categories = [% To.json(categories) | $raw %]; |
146 |
let categories_map = categories.reduce((map, c) => { |
147 |
map[c.categorycode] = c; |
148 |
return map; |
149 |
}, {}); |
150 |
let libraries = [% To.json(libraries) | $raw %]; |
151 |
let libraries_map = libraries.reduce((map, l) => { |
152 |
map[l.branchcode] = l; |
153 |
return map; |
154 |
}, {}); |
155 |
|
156 |
[% IF Koha.Preference('ExtendedPatronAttributes') %] |
157 |
let extended_attribute_types = [% To.json(attribute_type_codes || []) | $raw %]; |
158 |
[% END %] |
159 |
|
160 |
</script> |
161 |
|
162 |
[% INCLUDE 'datatables.inc' %] |
163 |
[% INCLUDE 'js-date-format.inc' %] |
164 |
[% INCLUDE 'js-patron-get-age.inc' %] |
165 |
[% INCLUDE 'js-patron-format.inc' %] |
166 |
[% INCLUDE 'js-patron-format-address.inc' %] |
167 |
|
168 |
<script> |
169 |
var first_draw = 0; |
170 |
let patrons_table; |
171 |
|
172 |
$(document).ready(function(){ |
173 |
|
174 |
|
175 |
$("#info").hide(); |
176 |
$("#error").hide(); |
177 |
|
178 |
let additional_filters = { |
179 |
surname: function(){ |
180 |
let start_with = $("#firstletter_filter").val() |
181 |
if (!start_with) return ""; |
182 |
return { "like": start_with + "%" } |
183 |
}, |
184 |
"-and": function(){ |
185 |
let filter = $("#searchmember_filter").val(); |
186 |
if (!filter) return ""; |
187 |
[% SET search_fields = Koha.Preference('DefaultPatronSearchFields') || 'surname,firstname,othernames,cardnumber,userid' %] |
188 |
return [ |
189 |
[% FOR search_field IN search_fields.split(',') %] |
190 |
{"me.[% search_field %]":{"like":"%"+filter+"%"}}, |
191 |
[% END %] |
192 |
[% IF Koha.Preference('ExtendedPatronAttributes') %] |
193 |
{ |
194 |
"extended_attributes.value": { "like": "%" + filter + "%" }, |
195 |
"extended_attributes.code": extended_attribute_types |
196 |
} |
197 |
[% END %] |
198 |
]; |
199 |
} |
200 |
}; |
201 |
[% UNLESS default_sort_column %] |
202 |
[% default_sort_column = "name" %] |
203 |
[% END %] |
204 |
[% SET order_column_index = 0 %] |
205 |
patrons_table = $("#[% table_id %]").kohaTable({ |
206 |
"ajax": { |
207 |
[% SWITCH filter %] |
208 |
[% CASE 'suggestions_managers' %] |
209 |
"url": '/api/v1/suggestions/managers', |
210 |
[% CASE 'baskets_managers' %] |
211 |
"url": '/api/v1/acquisitions/baskets/managers', |
212 |
[% CASE 'funds_owners' %] |
213 |
"url": '/api/v1/acquisitions/funds/owners', |
214 |
[% CASE 'funds_users' %] |
215 |
"url": '/api/v1/acquisitions/funds/users', |
216 |
[% CASE %] |
217 |
"url": '/api/v1/patrons', |
218 |
[% END %] |
219 |
"dataSrc": function ( json ) { |
220 |
[% IF redirect_if_one_result %] |
221 |
// redirect if there is only 1 result. |
222 |
if ( first_draw && json.recordsFiltered == 1 ) { |
223 |
document.location.href = '[% redirect_url %]&borrowernumber=' + json.data[0].patron_id; |
224 |
return false; |
225 |
} |
226 |
first_draw = 0; |
227 |
[% END %] |
228 |
return json.data; |
229 |
} |
230 |
}, |
231 |
embed: ['extended_attributes'], |
232 |
"drawCallback": function( settings ) { |
233 |
var api = this.api(); |
234 |
var data = api.data(); |
235 |
if ( data.length == 0 ) return; |
236 |
|
237 |
[% IF open_on_row_click %] |
238 |
$.each($(this).find("tbody tr"), function(index, tr) { |
239 |
let url = "[% on_click_url %]&borrowernumber=" + data[index].patron_id; |
240 |
$(tr).off('click').on('click', function() { |
241 |
document.location.href = url; |
242 |
}).addClass('clickable'); |
243 |
$(tr).find("a.patron_name").attr('href', url); |
244 |
}); |
245 |
[% ELSE %] |
246 |
$.each($(this).find("tbody tr"), function(index, tr) { |
247 |
$(tr).find("a.patron_name").addClass("patron_preview"); |
248 |
}); |
249 |
[% END %] |
250 |
}, |
251 |
"iDeferLoading": 0, |
252 |
"columns": [ |
253 |
[% FOR column IN columns %] |
254 |
[% IF default_sort_column == column %] |
255 |
[% order_column_index = loop.count - 1%] |
256 |
[% END %] |
257 |
[% SWITCH column %] |
258 |
[% CASE 'cardnumber' %] |
259 |
{ |
260 |
"data": "cardnumber", |
261 |
"searchable": true, |
262 |
"orderable": true |
263 |
} |
264 |
[% CASE 'dateofbirth' %] |
265 |
{ |
266 |
"data": "date_of_birth", |
267 |
"searchable": true, |
268 |
"orderable": true, |
269 |
"render": function( data, type, row, meta ) { |
270 |
return data ? escape_str($date(data) + " (" + _("%s years").format($get_age(data)) + ")") : ""; |
271 |
} |
272 |
} |
273 |
[% CASE 'address' %] |
274 |
{ |
275 |
"data": "me.street_number:me.address:me.address2:me.city:me.state:me.postal_code:me.country", |
276 |
"searchable": true, |
277 |
"orderable": true, |
278 |
"render": function( data, type, row, meta ) { |
279 |
let r = '<div class="address"><ul>'; |
280 |
r += $format_address(row, { no_line_break: 1 }); |
281 |
r += '</div></ul>'; |
282 |
return r; |
283 |
} |
284 |
} |
285 |
[% CASE 'address-library' %] |
286 |
{ |
287 |
"data": "me.street_number:me.address:me.address2:me.city:me.state:me.postal_code:me.country", |
288 |
"searchable": true, |
289 |
"orderable": true, |
290 |
"render": function( data, type, row, meta ) { |
291 |
let r = '<div class="address"><ul>'; |
292 |
r += $format_address(row, { no_line_break: 1 }); |
293 |
r += '</div></ul>'; |
294 |
r += " " + escape_str(libraries_map[row.library_id].branchname); |
295 |
return r; |
296 |
} |
297 |
} |
298 |
[% CASE 'name-address' %] |
299 |
{ |
300 |
"data": "me.firstname:me.surname:me.othernames:me.street_number:me.address:me.address2:me.city:me.state:me.postal_code:me.country", |
301 |
"searchable": true, |
302 |
"orderable": true, |
303 |
"render": function( data, type, row, meta ) { |
304 |
let patron_id = encodeURIComponent(row.patron_id); |
305 |
let r = ''; |
306 |
[% IF ! open_on_row_click %] |
307 |
r += "<a href=\"/cgi-bin/koha/members/moremember.pl?borrowernumber=" + patron_id + "\" class=\"patron_name\" data-borrowernumber=\"" + patron_id + "\" style=\"white-space:nowrap\">" + $patron_to_html(row, { invert_name: 1 }) + "</a>"; |
308 |
[% ELSE %] |
309 |
r += $patron_to_html(row, { invert_name: 1 }); |
310 |
[% END %] |
311 |
r += '<br/>'; |
312 |
r += '<div class="address"><ul>'; |
313 |
r += $format_address(row, { no_line_break: 1 }); |
314 |
|
315 |
if ( row.email ) { |
316 |
r += "<li>" + _("Email: ") + "<a href='mailto:" + encodeURIComponent(row.email) + "'>" + escape_str(row.email) + "</a></li>"; |
317 |
} |
318 |
r += '</ul></div>' |
319 |
|
320 |
return r; |
321 |
} |
322 |
} |
323 |
[% CASE 'name' %] |
324 |
{ |
325 |
"data": "me.firstname:me.surname:me.othernames", |
326 |
"searchable": true, |
327 |
"orderable": true, |
328 |
"render": function( data, type, row, meta ) { |
329 |
let patron_id = encodeURIComponent(row.patron_id); |
330 |
return "<a href=\"/cgi-bin/koha/members/moremember.pl?borrowernumber=" + patron_id + "\" class=\"patron_name\" data-borrowernumber=\"" + patron_id + "\" style=\"white-space:nowrap\">" + $patron_to_html(row, { invert_name: 1 }) + "</a>"; |
331 |
} |
332 |
} |
333 |
[% CASE 'branch' %] |
334 |
{ |
335 |
"data": "library_id", |
336 |
"searchable": true, |
337 |
"orderable": true, |
338 |
"render": function( data, type, row, meta ) { |
339 |
return escape_str(libraries_map[data].branchname); |
340 |
} |
341 |
} |
342 |
[% CASE 'category' %] |
343 |
{ |
344 |
"data": "category_id", |
345 |
"searchable": true, |
346 |
"orderable": true, |
347 |
"render": function( data, type, row, meta ) { |
348 |
return escape_str(categories_map[data].description); |
349 |
} |
350 |
} |
351 |
[% CASE 'dateexpiry' %] |
352 |
{ |
353 |
"data": "expiry_date", |
354 |
"searchable": true, |
355 |
"orderable": true, |
356 |
"render": function( data, type, row, meta ) { |
357 |
return data ? escape_str($date(data)) : ""; |
358 |
} |
359 |
} |
360 |
[% CASE 'borrowernotes' %] |
361 |
{ |
362 |
"data": "staff_notes", |
363 |
"searchable": true, |
364 |
"orderable": true, |
365 |
[%# We don't escape here, we allow html tag in staff notes %] |
366 |
} |
367 |
[% CASE 'phone' %] |
368 |
{ |
369 |
"data": "phone", |
370 |
"searchable": true, |
371 |
"orderable": true, |
372 |
"render": function( data, type, row, meta ) { |
373 |
return escape_str(data); |
374 |
} |
375 |
} |
376 |
[% CASE 'action' %] |
377 |
{ |
378 |
"data": function( row, type, val, meta ) { |
379 |
|
380 |
let patron_id = encodeURIComponent(row.patron_id); |
381 |
[% IF selection_type == 'select' %] |
382 |
return '<a href="#" class="btn btn-default btn-xs select_user" data-borrowernumber="' + patron_id + '">Select</a><input type="hidden" id="borrower_data' + patron_id + '" name="borrower_data'+ patron_id + '" value=\''+JSON.stringify(row)+'\' />'; |
383 |
[% ELSE %] |
384 |
return '<a href="#" class="btn btn-default btn-xs add_user" data-borrowernumber="' + patron_id + '" data-firstname="' + encodeURIComponent(row.firstname) + '" data-surname="' + encodeURIComponent(row.surname) + '">Add</a><input type="hidden" id="borrower_data' + patron_id + '" name="borrower_data'+ patron_id + '" />'; |
385 |
[% END %] |
386 |
}, |
387 |
"searchable": false, |
388 |
"orderable": false |
389 |
} |
390 |
[% END %] |
391 |
[% UNLESS loop.last %],[% END %] |
392 |
[% END %] |
393 |
], |
394 |
"order": [[ [% order_column_index %], "asc" ]], |
395 |
'bAutoWidth': false, |
396 |
'sPaginationType': 'full_numbers', |
397 |
"iDisplayLength": [% Koha.Preference('PatronsPerPage') | html %], |
398 |
}, typeof table_settings !== 'undefined' ? table_settings : null, 1, additional_filters); |
399 |
|
400 |
$("#patron_search_form").on('submit', filter); |
401 |
$(".filterByLetter").on("click",function(e){ |
402 |
e.preventDefault(); |
403 |
filterByFirstLetterSurname($(this).text()); |
404 |
}); |
405 |
$("body").on("click",".add_user",function(e){ |
406 |
e.preventDefault(); |
407 |
var borrowernumber = $(this).data("borrowernumber"); |
408 |
var firstname = $(this).data("firstname"); |
409 |
var surname = $(this).data("surname"); |
410 |
add_user( borrowernumber, firstname + " " + surname ); |
411 |
}); |
412 |
|
413 |
$("body").on("click",".select_user",function(e){ |
414 |
e.preventDefault(); |
415 |
var borrowernumber = $(this).data("borrowernumber"); |
416 |
var borrower_data = $("#borrower_data"+borrowernumber).val(); |
417 |
select_user( borrowernumber, JSON.parse(borrower_data) ); |
418 |
}); |
419 |
|
420 |
$("body").on("click",".patron_preview", function( e ){ |
421 |
e.preventDefault(); |
422 |
var borrowernumber = $(this).data("borrowernumber"); |
423 |
var page = "/cgi-bin/koha/members/moremember.pl?print=brief&borrowernumber=" + borrowernumber; |
424 |
$("#patronPreview .modal-body").load( page + " div.container-fluid" ); |
425 |
$('#patronPreview').modal({show:true}); |
426 |
}); |
427 |
|
428 |
$("#patronPreview").on('hidden.bs.modal', function (e) { |
429 |
$("#patronPreview .modal-body").html("<img src=\"[% interface | html %]/[% theme | html %]/img/spinner-small.gif\" alt=\"\" /> Loading"); |
430 |
}); |
431 |
|
432 |
}); |
433 |
|
434 |
function filter() { |
435 |
$("#firstletter_filter").val(''); |
436 |
$("#[% table_id %]_search_results").show(); |
437 |
|
438 |
let table_dt = patrons_table.DataTable(); |
439 |
[% FOR c IN columns %] |
440 |
[% SWITCH c %] |
441 |
[% CASE 'branch' %] |
442 |
library_id = $("#branchcode_filter").val() || ""; |
443 |
patrons_table.find('thead tr:eq(1) th[data-filter="libraries"] select').val(library_id); |
444 |
if (library_id) |
445 |
table_dt.column([% loop.count - 1 %]).search('^'+library_id+'$'); |
446 |
[% CASE 'category' %] |
447 |
let category_id = $("#categorycode_filter").val() || ""; |
448 |
patrons_table.find('thead tr:eq(1) th[data-filter="categories"] select').val(category_id); |
449 |
if (category_id) |
450 |
table_dt.column([% loop.count - 1 %]).search('^'+category_id+'$'); |
451 |
[% END %] |
452 |
[% END %] |
453 |
table_dt.search(""); |
454 |
first_draw = 1; // Only redirect if we are coming from here |
455 |
table_dt.draw(); |
456 |
return false; |
457 |
} |
458 |
|
459 |
// User has clicked on a letter |
460 |
function filterByFirstLetterSurname(letter) { |
461 |
$("#firstletter_filter").val(letter); |
462 |
$("#[% table_id %]_search_results").show(); |
463 |
patrons_table.DataTable().draw(); |
464 |
} |
465 |
|
466 |
// modify parent window owner element |
467 |
[% IF selection_type == 'add' %] |
468 |
function add_user(borrowernumber, borrowername) { |
469 |
var p = window.opener; |
470 |
// In one place (serials/routing.tt), the page is reload on every add |
471 |
// We have to wait for the page to be there |
472 |
function wait_for_opener () { |
473 |
if ( ! $(opener.document).find('body').size() ) { |
474 |
setTimeout(wait_for_opener, 500); |
475 |
} else { |
476 |
[%# Note that add_user could sent data instead of borrowername too %] |
477 |
$("#info").hide(); |
478 |
$("#error").hide(); |
479 |
if ( p.add_user(borrowernumber, borrowername) < 0 ) { |
480 |
$("#error").html(_("Patron '%s' is already in the list.").format(borrowername)); |
481 |
$("#error").show(); |
482 |
} else { |
483 |
$("#info").html(_("Patron '%s' added.").format(borrowername)); |
484 |
$("#info").show(); |
485 |
} |
486 |
} |
487 |
} |
488 |
wait_for_opener(); |
489 |
} |
490 |
[% ELSIF selection_type == 'select' %] |
491 |
function select_user(borrowernumber, data) { |
492 |
var p = window.opener; |
493 |
[% IF callback %] |
494 |
p.[% callback | html %](borrowernumber, data); |
495 |
[% ELSE %] |
496 |
p.select_user(borrowernumber, data); |
497 |
[% END %] |
498 |
window.close(); |
499 |
} |
500 |
[% END %] |
501 |
</script> |
502 |
[% END %] |