| Line 0
          
      
      
        Link Here | 
            
              |  |  | 1 | [% USE raw %] | 
            
              | 2 | [% USE To %] | 
            
              | 3 | [% USE Asset %] | 
            
              | 4 | [% USE Koha %] | 
            
              | 5 | [% USE Branches %] | 
            
              | 6 | [% USE Categories %] | 
            
              | 7 | [% SET footerjs = 1 %] | 
            
              | 8 | [% INCLUDE 'doc-head-open.inc' %] | 
            
              | 9 | [% SET libraries = Branches.all %] | 
            
              | 10 | [% SET categories = Categories.all.unblessed %] | 
            
              | 11 | <title>Patron search › Koha</title> | 
            
              | 12 | [% INCLUDE 'doc-head-close.inc' %] | 
            
              | 13 | <style> .modal-body .close { display: none; } </style> | 
            
              | 14 | </head> | 
            
              | 15 |  | 
            
              | 16 | <body id="common_patron_search" class="common"> | 
            
              | 17 | <div id="patron_search" class="yui-t7"> | 
            
              | 18 |     <div class="container-fluid"> | 
            
              | 19 |  | 
            
              | 20 |         <form id="searchform"> | 
            
              | 21 |             <fieldset class="brief"> | 
            
              | 22 |                 <h3>Search for patron</h3> | 
            
              | 23 |                 <ol> | 
            
              | 24 |                     <li> | 
            
              | 25 |                         <label for="searchmember_filter">Search:</label> | 
            
              | 26 |                         <input type="text" id="searchmember_filter" value="[% searchmember | html %]" class="focus" /> | 
            
              | 27 |                     </li> | 
            
              | 28 |  | 
            
              | 29 |                     [% FOR column IN columns %] | 
            
              | 30 |                         [% SWITCH column %] | 
            
              | 31 |                         [% CASE 'branch' %] | 
            
              | 32 |                             <li> | 
            
              | 33 |                                 <label for="branchcode_filter">Library:</label> | 
            
              | 34 |                                 <select id="branchcode_filter"> | 
            
              | 35 |                                     [% SET libraries = Branches.all( only_from_group => 1 ) %] | 
            
              | 36 |                                     [% IF libraries.size != 1 %] | 
            
              | 37 |                                         <option value="">Any</option> | 
            
              | 38 |                                     [% END %] | 
            
              | 39 |                                     [% FOREACH l IN libraries %] | 
            
              | 40 |                                         <option value="[% l.branchcode | html %]">[% l.branchname | html %]</option> | 
            
              | 41 |                                     [% END %] | 
            
              | 42 |                                 </select> | 
            
              | 43 |                             </li> | 
            
              | 44 |                         [% CASE 'category' %] | 
            
              | 45 |                             <li> | 
            
              | 46 |                                 <label for="categorycode_filter">Category:</label> | 
            
              | 47 |                                 <select id="categorycode_filter"> | 
            
              | 48 |                                     <option value="">Any</option> | 
            
              | 49 |                                     [% FOREACH category IN categories %] | 
            
              | 50 |                                         <option value="[% category.categorycode | html %]">[% category.description | html %]</option> | 
            
              | 51 |                                     [% END %] | 
            
              | 52 |                                 </select> | 
            
              | 53 |                             </li> | 
            
              | 54 |                         [% END %] | 
            
              | 55 |                     [% END %] | 
            
              | 56 |                 </ol> | 
            
              | 57 |                 <fieldset class="action"> | 
            
              | 58 |                     <input type="submit" value="Search" /> | 
            
              | 59 |                 </fieldset> | 
            
              | 60 |             </fieldset> | 
            
              | 61 |         </form> | 
            
              | 62 |  | 
            
              | 63 |         [% IF patrons_with_acq_perm_only %] | 
            
              | 64 |             <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> | 
            
              | 65 |         [% END %] | 
            
              | 66 |  | 
            
              | 67 |         [% IF patrons_with_suggestion_perm_only %] | 
            
              | 68 |             <div class="hint">Only staff with superlibrarian or suggestions_manage permissions are returned in the search results</div> | 
            
              | 69 |         [% END %] | 
            
              | 70 |  | 
            
              | 71 |         <div class="browse"> | 
            
              | 72 |             Browse by last name: | 
            
              | 73 |             [% FOREACH letter IN alphabet.split(' ') %] | 
            
              | 74 |                 <a href="#" class="filterByLetter">[% letter | html %]</a> | 
            
              | 75 |             [% END %] | 
            
              | 76 |         </div> | 
            
              | 77 |  | 
            
              | 78 |         <div id="info" class="dialog message"></div> | 
            
              | 79 |         <div id="error" class="dialog alert"></div> | 
            
              | 80 |  | 
            
              | 81 |         <input type="hidden" id="firstletter_filter" value="" /> | 
            
              | 82 |         <div id="searchresults"> | 
            
              | 83 |             <table id="memberresultst"> | 
            
              | 84 |                 <thead> | 
            
              | 85 |                     <tr> | 
            
              | 86 |                         [% FOR column IN columns %] | 
            
              | 87 |                             [% SWITCH column %] | 
            
              | 88 |                                 [% CASE 'cardnumber' %]<th>Card</th> | 
            
              | 89 |                                 [% CASE 'dateofbirth' %]<th>Date of birth</th> | 
            
              | 90 |                                 [% CASE 'address' %]<th>Address</th> | 
            
              | 91 |                                 [% CASE 'name' %]<th>Name</th> | 
            
              | 92 |                                 [% CASE 'branch' %]<th data-filter="libraries">Library</th> | 
            
              | 93 |                                 [% CASE 'category' %]<th data-filter="categories">Category</th> | 
            
              | 94 |                                 [% CASE 'dateexpiry' %]<th>Expires on</td> | 
            
              | 95 |                                 [% CASE 'borrowernotes' %]<th>Notes</th> | 
            
              | 96 |                                 [% CASE 'action' %]<th> </th> | 
            
              | 97 |                             [% END %] | 
            
              | 98 |                         [% END %] | 
            
              | 99 |                     </tr> | 
            
              | 100 |                   </thead> | 
            
              | 101 |                 <tbody></tbody> | 
            
              | 102 |             </table> | 
            
              | 103 |         </div> | 
            
              | 104 |  | 
            
              | 105 | <div id="closewindow"><a href="#" class="btn btn-default btn-default close">Close</a></div> | 
            
              | 106 |  | 
            
              | 107 | <!-- Patron preview modal --> | 
            
              | 108 | <div class="modal" id="patronPreview" tabindex="-1" role="dialog" aria-labelledby="patronPreviewLabel"> | 
            
              | 109 |     <div class="modal-dialog" role="document"> | 
            
              | 110 |         <div class="modal-content"> | 
            
              | 111 |             <div class="modal-header"> | 
            
              | 112 |                 <button type="button" class="closebtn" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> | 
            
              | 113 |                 <h4 class="modal-title" id="patronPreviewLabel"></h4> | 
            
              | 114 |             </div> | 
            
              | 115 |             <div class="modal-body"> | 
            
              | 116 |                 <div id="loading"> | 
            
              | 117 |                     <img src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif" alt="" /> Loading | 
            
              | 118 |                 </div> | 
            
              | 119 |             </div> | 
            
              | 120 |             <div class="modal-footer"> | 
            
              | 121 |                 <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> | 
            
              | 122 |             </div> | 
            
              | 123 |         </div> | 
            
              | 124 |     </div> | 
            
              | 125 | </div> | 
            
              | 126 |  | 
            
              | 127 | </div> | 
            
              | 128 | </div> | 
            
              | 129 |  | 
            
              | 130 | [% MACRO jsinclude BLOCK %] | 
            
              | 131 |     <script> | 
            
              | 132 |         let categories = [% To.json(categories) | $raw %]; | 
            
              | 133 |         let categories_map = categories.reduce((map, c) => { | 
            
              | 134 |             map[c.categorycode] = c; | 
            
              | 135 |             return map; | 
            
              | 136 |         }, {}); | 
            
              | 137 |         let libraries  = [% To.json(libraries) | $raw %]; | 
            
              | 138 |         let libraries_map = libraries.reduce((map, l) => { | 
            
              | 139 |             map[l.branchcode] = l; | 
            
              | 140 |             return map; | 
            
              | 141 |         }, {}); | 
            
              | 142 |     </script> | 
            
              | 143 |     [% INCLUDE 'datatables.inc' %] | 
            
              | 144 |     [% INCLUDE 'js-date-format.inc' %] | 
            
              | 145 |     [% INCLUDE 'js-patron-get-age.inc' %] | 
            
              | 146 |     [% INCLUDE 'js-patron-format.inc' %] | 
            
              | 147 |     [% INCLUDE 'js-patron-format-address.inc' %] | 
            
              | 148 |  | 
            
              | 149 |     <script> | 
            
              | 150 |         var search = 0; | 
            
              | 151 |         let patrons_table; | 
            
              | 152 |         $(document).ready(function(){ | 
            
              | 153 |             $("#info").hide(); | 
            
              | 154 |             $("#error").hide(); | 
            
              | 155 |  | 
            
              | 156 |             $("#searchresults").hide(); | 
            
              | 157 |  | 
            
              | 158 |             let additional_filters = { | 
            
              | 159 |                 surname: function(){ | 
            
              | 160 |                     let start_with = $("#firstletter_filter").val() | 
            
              | 161 |                     if (!start_with) return ""; | 
            
              | 162 |                     return { "like": start_with + "%" } | 
            
              | 163 |                 } | 
            
              | 164 |             }; | 
            
              | 165 |             patrons_table = $("#memberresultst").kohaTable({ | 
            
              | 166 |                 "ajax": { | 
            
              | 167 |                     "url": '/api/v1/patrons' | 
            
              | 168 |                 }, | 
            
              | 169 |                 "order": [[ 1, "asc" ]], | 
            
              | 170 |                 "iDeferLoading": 0, | 
            
              | 171 |                 "columns": [ | 
            
              | 172 |                     [% FOR column IN columns %] | 
            
              | 173 |                         [% SWITCH column %] | 
            
              | 174 |                             [% CASE 'cardnumber' %] | 
            
              | 175 |                             { | 
            
              | 176 |                                 "data": "cardnumber", | 
            
              | 177 |                                 "searchable": true, | 
            
              | 178 |                                 "orderable": true | 
            
              | 179 |                             } | 
            
              | 180 |                             [% CASE 'dateofbirth' %] | 
            
              | 181 |                             { | 
            
              | 182 |                                 "data": "date_of_birth", | 
            
              | 183 |                                 "searchable": true, | 
            
              | 184 |                                 "orderable": true, | 
            
              | 185 |                                 "render": function( data, type, row, meta ) { | 
            
              | 186 |                                     return data ? escape_str($date(data) + " (" + _("%s years").format($get_age(data)) + ")") : ""; | 
            
              | 187 |                                 } | 
            
              | 188 |                             } | 
            
              | 189 |                             [% CASE 'address' %] | 
            
              | 190 |                             { | 
            
              | 191 |                                 "data": "me.street_number:me.address:me.address2:me.city:me.state:me.postal_code:me.country", | 
            
              | 192 |                                 "searchable": true, | 
            
              | 193 |                                 "orderable": true, | 
            
              | 194 |                                 "render": function( data, type, row, meta ) { | 
            
              | 195 |                                     return escape_str($format_address(row) + " ") + escape_str(libraries_map[row.library_id].branchname); | 
            
              | 196 |                                 } | 
            
              | 197 |                             } | 
            
              | 198 |                             [% CASE 'name' %] | 
            
              | 199 |                             { | 
            
              | 200 |                                 "data": "me.firstname:me.surname", | 
            
              | 201 |                                 "searchable": true, | 
            
              | 202 |                                 "orderable": true, | 
            
              | 203 |                                 "render": function( data, type, row, meta ) { | 
            
              | 204 |                                     return $patron_to_html(row, { invert_name: 1 }); | 
            
              | 205 |                                 } | 
            
              | 206 |                             } | 
            
              | 207 |                             [% CASE 'branch' %] | 
            
              | 208 |                             { | 
            
              | 209 |                                 "data": "library_id", | 
            
              | 210 |                                 "searchable": true, | 
            
              | 211 |                                 "orderable": true, | 
            
              | 212 |                                 "render": function( data, type, row, meta ) { | 
            
              | 213 |                                     return escape_str(libraries_map[data].branchname); | 
            
              | 214 |                                 } | 
            
              | 215 |                             } | 
            
              | 216 |                             [% CASE 'category' %] | 
            
              | 217 |                             { | 
            
              | 218 |                                 "data": "category_id", | 
            
              | 219 |                                 "searchable": true, | 
            
              | 220 |                                 "orderable": true, | 
            
              | 221 |                                 "render": function( data, type, row, meta ) { | 
            
              | 222 |                                     return escape_str(categories_map[data].description); | 
            
              | 223 |                                 } | 
            
              | 224 |                             } | 
            
              | 225 |                             [% CASE 'dateexpiry' %] | 
            
              | 226 |                             { | 
            
              | 227 |                                 "data": "expiry_date", | 
            
              | 228 |                                 "searchable": true, | 
            
              | 229 |                                 "orderable": true, | 
            
              | 230 |                                 "render": function( data, type, row, meta ) { | 
            
              | 231 |                                     return data ? escape_str($date(data)) : ""; | 
            
              | 232 |                                 } | 
            
              | 233 |                             } | 
            
              | 234 |                             [% CASE 'borrowernotes' %] | 
            
              | 235 |                             { | 
            
              | 236 |                                 "data": "staff_notes", | 
            
              | 237 |                                 "searchable": true, | 
            
              | 238 |                                 "orderable": true, | 
            
              | 239 |                                 [%# We don't escape here, we allow html tag in staff notes %] | 
            
              | 240 |                             } | 
            
              | 241 |                             [% CASE 'action' %] | 
            
              | 242 |                             { | 
            
              | 243 |                                 "data": function( row, type, val, meta ) { | 
            
              | 244 |  | 
            
              | 245 |                                     let patron_id = encodeURIComponent(row.patron_id); | 
            
              | 246 |                                     [% IF selection_type == 'select' %] | 
            
              | 247 |                                         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)+'\' />'; | 
            
              | 248 |                                     [% ELSE %] | 
            
              | 249 |                                         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 + '" />'; | 
            
              | 250 |                                     [% END %] | 
            
              | 251 |                                 }, | 
            
              | 252 |                                 "searchable": false, | 
            
              | 253 |                                 "orderable": false | 
            
              | 254 |                             } | 
            
              | 255 |                         [% END %] | 
            
              | 256 |                         [% UNLESS loop.last %],[% END %] | 
            
              | 257 |                     [% END %] | 
            
              | 258 |                 ], | 
            
              | 259 |                 'bAutoWidth': false, | 
            
              | 260 |                 'sPaginationType': 'full_numbers', | 
            
              | 261 |                 "iDisplayLength": [% Koha.Preference('PatronsPerPage') | html %], | 
            
              | 262 |             }, null, 1, additional_filters); | 
            
              | 263 |  | 
            
              | 264 |             $("#searchform").on('submit', filter); | 
            
              | 265 |             $(".filterByLetter").on("click",function(e){ | 
            
              | 266 |                 e.preventDefault(); | 
            
              | 267 |                 filterByFirstLetterSurname($(this).text()); | 
            
              | 268 |             }); | 
            
              | 269 |             $("body").on("click",".add_user",function(e){ | 
            
              | 270 |                 e.preventDefault(); | 
            
              | 271 |                 var borrowernumber = $(this).data("borrowernumber"); | 
            
              | 272 |                 var firstname = $(this).data("firstname"); | 
            
              | 273 |                 var surname = $(this).data("surname"); | 
            
              | 274 |                 add_user( borrowernumber, firstname + " " + surname ); | 
            
              | 275 |             }); | 
            
              | 276 |  | 
            
              | 277 |             $("body").on("click",".select_user",function(e){ | 
            
              | 278 |                 e.preventDefault(); | 
            
              | 279 |                 var borrowernumber = $(this).data("borrowernumber"); | 
            
              | 280 |                 var borrower_data = $("#borrower_data"+borrowernumber).val(); | 
            
              | 281 |                 select_user( borrowernumber, JSON.parse(borrower_data) ); | 
            
              | 282 |             }); | 
            
              | 283 |  | 
            
              | 284 |             $("body").on("click",".patron_preview", function( e ){ | 
            
              | 285 |                 e.preventDefault(); | 
            
              | 286 |                 var borrowernumber = $(this).data("borrowernumber"); | 
            
              | 287 |                 var page = "/cgi-bin/koha/members/moremember.pl?print=brief&borrowernumber=" + borrowernumber; | 
            
              | 288 |                 $("#patronPreview .modal-body").load( page + " div.container-fluid" ); | 
            
              | 289 |                 $('#patronPreview').modal({show:true}); | 
            
              | 290 |             }); | 
            
              | 291 |  | 
            
              | 292 |             $("#patronPreview").on('hidden.bs.modal', function (e) { | 
            
              | 293 |                 $("#patronPreview .modal-body").html("<img src=\"[% interface | html %]/[% theme | html %]/img/spinner-small.gif\" alt=\"\" /> Loading"); | 
            
              | 294 |             }); | 
            
              | 295 |  | 
            
              | 296 |         }); | 
            
              | 297 |  | 
            
              | 298 |         function filter() { | 
            
              | 299 |             search = 1; | 
            
              | 300 |             $("#firstletter_filter").val(''); | 
            
              | 301 |             $("#searchresults").show(); | 
            
              | 302 |  | 
            
              | 303 |             let table_dt = patrons_table.DataTable(); | 
            
              | 304 |             [% FOR c IN columns %] | 
            
              | 305 |                 [% SWITCH c %] | 
            
              | 306 |                 [% CASE 'branch' %] | 
            
              | 307 |                     let library_id = $("#branchcode_filter").val(); | 
            
              | 308 |                     patrons_table.find('thead tr:eq(1) th[data-filter="libraries"] select').val(library_id); | 
            
              | 309 |                     table_dt.column([% loop.count - 1 %]).search(library_id); | 
            
              | 310 |                 [% CASE 'category' %] | 
            
              | 311 |                     let category_id = $("#categorycode_filter").val(); | 
            
              | 312 |                     patrons_table.find('thead tr:eq(1) th[data-filter="categories"] select').val(category_id); | 
            
              | 313 |                     table_dt.column([% loop.count - 1 %]).search(category_id); | 
            
              | 314 |                 [% END %] | 
            
              | 315 |             [% END %] | 
            
              | 316 |             table_dt.search($("#searchmember_filter").val()); | 
            
              | 317 |             table_dt.draw(); | 
            
              | 318 |             return false; | 
            
              | 319 |         } | 
            
              | 320 |  | 
            
              | 321 |         // User has clicked on a letter | 
            
              | 322 |         function filterByFirstLetterSurname(letter) { | 
            
              | 323 |             $("#firstletter_filter").val(letter); | 
            
              | 324 |             search = 1; | 
            
              | 325 |             $("#searchresults").show(); | 
            
              | 326 |             patrons_table.fnDraw(); | 
            
              | 327 |         } | 
            
              | 328 |  | 
            
              | 329 |         // modify parent window owner element | 
            
              | 330 |         [% IF selection_type == 'add' %] | 
            
              | 331 |             function add_user(borrowernumber, borrowername) { | 
            
              | 332 |                 var p = window.opener; | 
            
              | 333 |                 // In one place (serials/routing.tt), the page is reload on every add | 
            
              | 334 |                 // We have to wait for the page to be there | 
            
              | 335 |                 function wait_for_opener () { | 
            
              | 336 |                     if ( ! $(opener.document).find('body').size() ) { | 
            
              | 337 |                         setTimeout(wait_for_opener, 500); | 
            
              | 338 |                     } else { | 
            
              | 339 |                         [%# Note that add_user could sent data instead of borrowername too %] | 
            
              | 340 |                         $("#info").hide(); | 
            
              | 341 |                         $("#error").hide(); | 
            
              | 342 |                         if ( p.add_user(borrowernumber, borrowername) < 0 ) { | 
            
              | 343 |                             $("#error").html(_("Patron '%s' is already in the list.").format(borrowername)); | 
            
              | 344 |                             $("#error").show(); | 
            
              | 345 |                         } else { | 
            
              | 346 |                             $("#info").html(_("Patron '%s' added.").format(borrowername)); | 
            
              | 347 |                             $("#info").show(); | 
            
              | 348 |                         } | 
            
              | 349 |                     } | 
            
              | 350 |                 } | 
            
              | 351 |                 wait_for_opener(); | 
            
              | 352 |             } | 
            
              | 353 |         [% ELSIF selection_type == 'select' %] | 
            
              | 354 |             function select_user(borrowernumber, data) { | 
            
              | 355 |                 var p = window.opener; | 
            
              | 356 |                 [%  IF callback %] | 
            
              | 357 |                     p.[% callback | html %](borrowernumber, data); | 
            
              | 358 |                 [%  ELSE %] | 
            
              | 359 |                     p.select_user(borrowernumber, data); | 
            
              | 360 |                 [%  END %] | 
            
              | 361 |                 window.close(); | 
            
              | 362 |             } | 
            
              | 363 |         [% END %] | 
            
              | 364 |     </script> | 
            
              | 365 | [% END %] | 
            
              | 366 |  | 
            
              | 367 | [% SET popup_window = 1 %] | 
            
              | 368 | [% INCLUDE 'intranet-bottom.inc' %] |