Bugzilla – Attachment 130705 Details for
Bug 30093
Rewrite the patron search when placing a hold with the REST API route
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 30093: Make patron search from request.pl use the REST API
Bug-30093-Make-patron-search-from-requestpl-use-th.patch (text/plain), 64.08 KB, created by
Jonathan Druart
on 2022-02-17 10:09:21 UTC
(
hide
)
Description:
Bug 30093: Make patron search from request.pl use the REST API
Filename:
MIME Type:
Creator:
Jonathan Druart
Created:
2022-02-17 10:09:21 UTC
Size:
64.08 KB
patch
obsolete
>From 28b737a13d8ed321b3e548cb7b958ba7f19fb8b3 Mon Sep 17 00:00:00 2001 >From: Jonathan Druart <jonathan.druart@bugs.koha-community.org> >Date: Wed, 9 Feb 2022 16:29:23 +0100 >Subject: [PATCH] Bug 30093: Make patron search from request.pl use the REST > API > >In this patch we want to reuse what has been done in the previous bug >report to search patrons using the REST API route. >The code is mainly in members/search.tt, for all the patron searches >that "add" or "select" a patron (popup windows). >The patron search for holds is a bit different, we don't want to open a >popup window. >We are moving to code to an include file (patron-search.tt) to make it >reusable easily. > >Note that we are improving how the patron's addresses are displayed, and >provide a JS equivalent to the TT includes files. > >Test plan: >Search for patrons from the "Place a hold on" view. >You should see the same view as behaviour, with more filters. >--- > .../en/includes/js-patron-format-address.inc | 110 +++- > .../prog/en/includes/patron-search.inc | 502 ++++++++++++++++++ > .../prog/en/modules/members/search.tt | 394 +------------- > .../prog/en/modules/reserve/request.tt | 128 ++--- > .../modules/reserve/tables/members_results.tt | 32 -- > members/search.pl | 1 - > reserve/request.pl | 10 +- > 7 files changed, 660 insertions(+), 517 deletions(-) > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/patron-search.inc > delete mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/reserve/tables/members_results.tt > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/js-patron-format-address.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/js-patron-format-address.inc >index 935a1f36c48..60923ec5240 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/js-patron-format-address.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/js-patron-format-address.inc >@@ -1,20 +1,112 @@ > <!-- js-patron-format-address.inc --> >+[% USE raw %] >+[% USE To %] >+[% USE AuthorisedValues %] > <script> > (function() { > >- window.$format_address = function(data, options) { >+ const roadtypes = [% To.json(AuthorisedValues.Get('ROADTYPE')) | $raw %]; >+ let roadtypes_map = roadtypes.reduce((map, r) => { >+ map[r.street_type] = r; >+ return map; >+ }, {}); >+ >+ function member_display_address_style_us(data, line_break) { >+ let address = ""; >+ if ( data.address || data.address2 ) { >+ if ( data.address ) { >+ let roadtype_desc = ''; >+ if ( data.street_type ) { >+ roadtype_desc = roadtypes_map[data.street_type] ? roadtypes_map[data.street_type].street_type : data.street_type; >+ } >+ address += '<li class="patronaddress1">' + escape_str(data.streetnumber) + ' ' + escape_str(data.address) + ' ' + escape_str(roadtype_desc) + '</li>'; >+ } >+ } >+ if ( data.address2 ) { >+ address += '<li class="patronaddress2">' + escape_str(data.address2) + '</li>' >+ } >+ if ( data.city || data.postal_code || data.state || data.country ) { >+ address += '<li class="patroncity">' + escape_str(data.city); >+ if ( data.state ) { >+ if ( data.city ) { >+ address += ', '; >+ } >+ address += escape_str(data.city); >+ } >+ if ( data.postal_code ) { >+ address += " " + escape_str(data.postal_code); >+ } >+ if ( data.country ) { >+ if ( data.postal_code || data.state || data.city ) { >+ address += ', '; >+ } >+ address += escape_str(data.country) >+ } >+ address += '</li>' >+ } > >- let address = ''; >- address += (data.street_number ? data.street_number + ' ' : '' ); >- address += (data.address ? data.address + ' ' : '' ); >- address += (data.address2 ? data.address2 + ' ' : '' ); >- address += (data.city ? data.city + ' ' : '' ); >- address += (data.state ? data.state + ' ' : '' ); >- address += (data.postal_code ? data.postal_code + ' ' : '' ); >- address += (data.country ? data.country + ' ' : '' ); > return address; > } > >+ function member_display_address_style_de(data, line_break) { >+ let address = ""; >+ if ( data.address || data.address2 ) { >+ if ( data.address ) { >+ let roadtype_desc = ''; >+ if ( data.street_type ) { >+ roadtype_desc = roadtypes_map[data.street_type] ? roadtypes_map[data.street_type].street_type : data.street_type; >+ } >+ address += '<li class="patronaddress1">' + escape_str(data.address) + ' ' + escape_str(roadtype_desc) + escape_str(data.street_number) + '</li>'; >+ } >+ } >+ if ( data.address2 ) { >+ address += '<li class="patronaddress2">' + escape_str(data.address2) + '</li>' >+ } >+ if ( data.city || data.postal_code || data.state || data.country ) { >+ address += '<li class="patroncity">'; >+ address += escape_str(data.postal_code) + ' ' + escape_str(data.city); >+ address += data.state ? line_break + escape_str(data.state) : ''; >+ address += data.country ? line_break + escape_str(data.country) : ''; >+ address += '</li>' >+ } >+ >+ return address; >+ } >+ >+ function member_display_address_style_fr(data, line_break) { >+ let address = ""; >+ if ( data.address || data.address2 ) { >+ if ( data.address ) { >+ let roadtype_desc = ''; >+ if ( data.street_type ) { >+ roadtype_desc = roadtypes_map[data.street_type] ? roadtypes_map[data.street_type].street_type : data.street_type; >+ } >+ address += '<li class="patronaddress1">' + escape_str(data.street_number) + ' ' + escape_str(roadtype_desc) + escape_str(data.address) + '</li>'; >+ } >+ } >+ if ( data.address2 ) { >+ address += '<li class="patronaddress2">' + escape_str(data.address2) + '</li>' >+ } >+ if ( data.city || data.postal_code || data.state || data.country ) { >+ address += '<li class="patroncity">'; >+ address += escape_str(data.postal_code) + ' ' + escape_str(data.city); >+ address += data.state ? line_break + escape_str(data.state) : ''; >+ address += data.country ? line_break + escape_str(data.country) : ''; >+ address += '</li>' >+ } >+ >+ return address; >+ } >+ >+ window.$format_address = function(data, options) { >+ let line_break = options && options.no_line_break ? ' ' : '<br/>'; >+ [%~ IF Koha.Preference( 'AddressFormat' ) ~%] >+ return member_display_address_style_[% Koha.Preference( 'AddressFormat' ) %](data, line_break); >+ [%~ ELSE ~%] >+ return member_display_address_style_us(data, line_break); >+ [%~ END ~%] >+ } >+ > })(); > </script> > <!-- / js-patron-format-address.inc --> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/patron-search.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/patron-search.inc >new file mode 100644 >index 00000000000..10ec3081ecb >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/patron-search.inc >@@ -0,0 +1,502 @@ >+[% USE Koha %] >+[% USE Branches %] >+[% USE raw %] >+[% USE To %] >+ >+[% BLOCK patron_search_filters_simple %] >+ <form id="patron_search_form"> >+ <div class="hint">Enter patron card number or partial name:</div> >+ <input type="text" size="40" id="search_patron_filter" class="focus" autocomplete="off" /> >+ <input type="submit" value="Search" /> >+ </form> >+[% END %] >+ >+[% BLOCK patron_search_filters %] >+ <form id="patron_search_form"> >+ <fieldset class="brief"> >+ <h3>Search for patron</h3> >+ <ol> >+ <li> >+ <label for="search_patron_filter">Search:</label> >+ <div class="hint">Enter patron card number or partial name:</div> >+ <input type="text" id="search_patron_filter" value="[% search_filter | html %]" class="focus" /> >+ </li> >+ >+ [% FOR column IN columns %] >+ [% SWITCH column %] >+ [% CASE 'branch' %] >+ <li> >+ <label for="branchcode_filter">Library:</label> >+ <select id="branchcode_filter"> >+ [% SET libraries = Branches.all( only_from_group => 1 ) %] >+ [% IF libraries.size != 1 %] >+ <option value="">Any</option> >+ [% END %] >+ [% FOREACH l IN libraries %] >+ <option value="[% l.branchcode | html %]">[% l.branchname | html %]</option> >+ [% END %] >+ </select> >+ </li> >+ [% CASE 'category' %] >+ <li> >+ <label for="categorycode_filter">Category:</label> >+ <select id="categorycode_filter"> >+ <option value="">Any</option> >+ [% FOREACH category IN categories %] >+ <option value="[% category.categorycode | html %]">[% category.description | html %]</option> >+ [% END %] >+ </select> >+ </li> >+ [% END %] >+ [% END %] >+ </ol> >+ <fieldset class="action"> >+ <input type="submit" value="Search" /> >+ </fieldset> >+ </fieldset> >+ </form> >+[% END %] >+ >+[% BLOCK patron_search_table %] >+ >+ [% IF filter == 'suggestions_managers' %] >+ <div class="hint">Only staff with superlibrarian or suggestions_manage permissions are returned in the search results</div> >+ [% ELSIF filter == 'orders_managers' %] >+ <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> >+ [% ELSIF filter == 'funds_owners' OR filter == 'funds_users' %] >+ <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> >+ [% END %] >+ >+ <div class="browse"> >+ Browse by last name: >+ [% SET alphabet = Koha.Preference('alphabet').split(' ') %] >+ [% UNLESS alphabet.size %] >+ [% alphabet = ['A' .. 'Z'] %] >+ [% END %] >+ [% FOREACH letter IN alphabet %] >+ <a href="#" class="filterByLetter">[% letter | html %]</a> >+ [% END %] >+ </div> >+ >+ <div id="[% table_id %]_search_results" style="display:none;"> >+ >+ <div id="info" class="dialog message" style="display: none;"></div> >+ <div id="error" class="dialog alert" style="dispay: none;"></div> >+ >+ >+ <input type="hidden" id="firstletter_filter" value="" /> >+ [% IF open_on_row_click %] >+ <table id="[% table_id %]" class="selections-table"> >+ [% ELSE %] >+ <table id="[% table_id %]"> >+ [% END %] >+ <thead> >+ <tr> >+ [% FOR column IN columns %] >+ [% SWITCH column %] >+ [% CASE 'cardnumber' %]<th>Card</th> >+ [% CASE 'dateofbirth' %]<th>Date of birth</th> >+ [% CASE 'name' %]<th>Name</th> >+ [% CASE 'name-address' %]<th>Name</th> >+ [% CASE 'address' %]<th>Address</th> >+ [% CASE 'address-library' %]<th>Address</th> >+ [% CASE 'branch' %]<th data-filter="libraries">Library</th> >+ [% CASE 'category' %]<th data-filter="categories">Category</th> >+ [% CASE 'dateexpiry' %]<th>Expires on</td> >+ [% CASE 'borrowernotes' %]<th>Notes</th> >+ [% CASE 'phone' %]<th>Phone</th> >+ [% CASE 'action' %]<th> </th> >+ [% END %] >+ [% END %] >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ >+<!-- Patron preview modal --> >+<div class="modal" id="patronPreview" tabindex="-1" role="dialog" aria-labelledby="patronPreviewLabel"> >+ <div class="modal-dialog" role="document"> >+ <div class="modal-content"> >+ <div class="modal-header"> >+ <button type="button" class="closebtn" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> >+ <h4 class="modal-title" id="patronPreviewLabel"></h4> >+ </div> >+ <div class="modal-body"> >+ <div id="loading"> >+ <img src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif" alt="" /> Loading >+ </div> >+ </div> >+ <div class="modal-footer"> >+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> >+ </div> >+ </div> >+ </div> >+</div> >+ >+[% END %] >+ >+[% BLOCK patron_search_js %] >+ >+ [% IF redirect_if_one_result && !redirect_url %] >+ <script>console.log("Wrong call of patron_searh_js - missing redirect_url");</script> >+ [% END %] >+ <script> >+ let categories = [% To.json(categories) | $raw %]; >+ let categories_map = categories.reduce((map, c) => { >+ map[c.categorycode] = c; >+ return map; >+ }, {}); >+ let libraries = [% To.json(libraries) | $raw %]; >+ let libraries_map = libraries.reduce((map, l) => { >+ map[l.branchcode] = l; >+ return map; >+ }, {}); >+ >+ [% IF Koha.Preference('ExtendedPatronAttributes') %] >+ let extended_attribute_types = [% To.json(attribute_type_codes || []) | $raw %]; >+ [% END %] >+ >+ </script> >+ >+ [% INCLUDE 'datatables.inc' %] >+ [% INCLUDE 'js-date-format.inc' %] >+ [% INCLUDE 'js-patron-get-age.inc' %] >+ [% INCLUDE 'js-patron-format.inc' %] >+ [% INCLUDE 'js-patron-format-address.inc' %] >+ >+ <script> >+ var first_draw = 0; >+ let patrons_table; >+ >+ $(document).ready(function(){ >+ >+ >+ $("#info").hide(); >+ $("#error").hide(); >+ >+ let additional_filters = { >+ surname: function(){ >+ let start_with = $("#firstletter_filter").val() >+ if (!start_with) return ""; >+ return { "like": start_with + "%" } >+ }, >+ "-and": function(){ >+ let filter = $("#searchmember_filter").val(); >+ if (!filter) return ""; >+ [% SET search_fields = Koha.Preference('DefaultPatronSearchFields') || 'surname,firstname,othernames,cardnumber,userid' %] >+ return [ >+ [% FOR search_field IN search_fields.split(',') %] >+ {"me.[% search_field %]":{"like":"%"+filter+"%"}}, >+ [% END %] >+ [% IF Koha.Preference('ExtendedPatronAttributes') %] >+ { >+ "extended_attributes.value": { "like": "%" + filter + "%" }, >+ "extended_attributes.code": extended_attribute_types >+ } >+ [% END %] >+ ]; >+ } >+ }; >+ [% UNLESS default_sort_column %] >+ [% default_sort_column = "name" %] >+ [% END %] >+ [% SET order_column_index = 0 %] >+ patrons_table = $("#[% table_id %]").kohaTable({ >+ "ajax": { >+ [% SWITCH filter %] >+ [% CASE 'suggestions_managers' %] >+ "url": '/api/v1/suggestions/managers', >+ [% CASE 'baskets_managers' %] >+ "url": '/api/v1/acquisitions/baskets/managers', >+ [% CASE 'funds_owners' %] >+ "url": '/api/v1/acquisitions/funds/owners', >+ [% CASE 'funds_users' %] >+ "url": '/api/v1/acquisitions/funds/users', >+ [% CASE %] >+ "url": '/api/v1/patrons', >+ [% END %] >+ "dataSrc": function ( json ) { >+ [% IF redirect_if_one_result %] >+ // redirect if there is only 1 result. >+ if ( first_draw && json.recordsFiltered == 1 ) { >+ document.location.href = '[% redirect_url %]&borrowernumber=' + json.data[0].patron_id; >+ return false; >+ } >+ first_draw = 0; >+ [% END %] >+ return json.data; >+ } >+ }, >+ embed: ['extended_attributes'], >+ "drawCallback": function( settings ) { >+ var api = this.api(); >+ var data = api.data(); >+ if ( data.length == 0 ) return; >+ >+ [% IF open_on_row_click %] >+ $.each($(this).find("tbody tr"), function(index, tr) { >+ let url = "[% on_click_url %]&borrowernumber=" + data[index].patron_id; >+ $(tr).off('click').on('click', function() { >+ document.location.href = url; >+ }).addClass('clickable'); >+ $(tr).find("a.patron_name").attr('href', url); >+ }); >+ [% ELSE %] >+ $.each($(this).find("tbody tr"), function(index, tr) { >+ $(tr).find("a.patron_name").addClass("patron_preview"); >+ }); >+ [% END %] >+ }, >+ "iDeferLoading": 0, >+ "columns": [ >+ [% FOR column IN columns %] >+ [% IF default_sort_column == column %] >+ [% order_column_index = loop.count - 1%] >+ [% END %] >+ [% SWITCH column %] >+ [% CASE 'cardnumber' %] >+ { >+ "data": "cardnumber", >+ "searchable": true, >+ "orderable": true >+ } >+ [% CASE 'dateofbirth' %] >+ { >+ "data": "date_of_birth", >+ "searchable": true, >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return data ? escape_str($date(data) + " (" + _("%s years").format($get_age(data)) + ")") : ""; >+ } >+ } >+ [% CASE 'address' %] >+ { >+ "data": "me.street_number:me.address:me.address2:me.city:me.state:me.postal_code:me.country", >+ "searchable": true, >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ let r = '<div class="address"><ul>'; >+ r += $format_address(row, { no_line_break: 1 }); >+ r += '</div></ul>'; >+ return r; >+ } >+ } >+ [% CASE 'address-library' %] >+ { >+ "data": "me.street_number:me.address:me.address2:me.city:me.state:me.postal_code:me.country", >+ "searchable": true, >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ let r = '<div class="address"><ul>'; >+ r += $format_address(row, { no_line_break: 1 }); >+ r += '</div></ul>'; >+ r += " " + escape_str(libraries_map[row.library_id].branchname); >+ return r; >+ } >+ } >+ [% CASE 'name-address' %] >+ { >+ "data": "me.firstname:me.surname:me.othernames:me.street_number:me.address:me.address2:me.city:me.state:me.postal_code:me.country", >+ "searchable": true, >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ let patron_id = encodeURIComponent(row.patron_id); >+ let r = ''; >+ [% IF ! open_on_row_click %] >+ 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>"; >+ [% ELSE %] >+ r += $patron_to_html(row, { invert_name: 1 }); >+ [% END %] >+ r += '<br/>'; >+ r += '<div class="address"><ul>'; >+ r += $format_address(row, { no_line_break: 1 }); >+ >+ if ( row.email ) { >+ r += "<li>" + _("Email: ") + "<a href='mailto:" + encodeURIComponent(row.email) + "'>" + escape_str(row.email) + "</a></li>"; >+ } >+ r += '</ul></div>' >+ >+ return r; >+ } >+ } >+ [% CASE 'name' %] >+ { >+ "data": "me.firstname:me.surname:me.othernames", >+ "searchable": true, >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ let patron_id = encodeURIComponent(row.patron_id); >+ 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>"; >+ } >+ } >+ [% CASE 'branch' %] >+ { >+ "data": "library_id", >+ "searchable": true, >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return escape_str(libraries_map[data].branchname); >+ } >+ } >+ [% CASE 'category' %] >+ { >+ "data": "category_id", >+ "searchable": true, >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return escape_str(categories_map[data].description); >+ } >+ } >+ [% CASE 'dateexpiry' %] >+ { >+ "data": "expiry_date", >+ "searchable": true, >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return data ? escape_str($date(data)) : ""; >+ } >+ } >+ [% CASE 'borrowernotes' %] >+ { >+ "data": "staff_notes", >+ "searchable": true, >+ "orderable": true, >+ [%# We don't escape here, we allow html tag in staff notes %] >+ } >+ [% CASE 'phone' %] >+ { >+ "data": "phone", >+ "searchable": true, >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return escape_str(data); >+ } >+ } >+ [% CASE 'action' %] >+ { >+ "data": function( row, type, val, meta ) { >+ >+ let patron_id = encodeURIComponent(row.patron_id); >+ [% IF selection_type == 'select' %] >+ 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)+'\' />'; >+ [% ELSE %] >+ 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 + '" />'; >+ [% END %] >+ }, >+ "searchable": false, >+ "orderable": false >+ } >+ [% END %] >+ [% UNLESS loop.last %],[% END %] >+ [% END %] >+ ], >+ "order": [[ [% order_column_index %], "asc" ]], >+ 'bAutoWidth': false, >+ 'sPaginationType': 'full_numbers', >+ "iDisplayLength": [% Koha.Preference('PatronsPerPage') | html %], >+ }, typeof table_settings !== 'undefined' ? table_settings : null, 1, additional_filters); >+ >+ $("#patron_search_form").on('submit', filter); >+ $(".filterByLetter").on("click",function(e){ >+ e.preventDefault(); >+ filterByFirstLetterSurname($(this).text()); >+ }); >+ $("body").on("click",".add_user",function(e){ >+ e.preventDefault(); >+ var borrowernumber = $(this).data("borrowernumber"); >+ var firstname = $(this).data("firstname"); >+ var surname = $(this).data("surname"); >+ add_user( borrowernumber, firstname + " " + surname ); >+ }); >+ >+ $("body").on("click",".select_user",function(e){ >+ e.preventDefault(); >+ var borrowernumber = $(this).data("borrowernumber"); >+ var borrower_data = $("#borrower_data"+borrowernumber).val(); >+ select_user( borrowernumber, JSON.parse(borrower_data) ); >+ }); >+ >+ $("body").on("click",".patron_preview", function( e ){ >+ e.preventDefault(); >+ var borrowernumber = $(this).data("borrowernumber"); >+ var page = "/cgi-bin/koha/members/moremember.pl?print=brief&borrowernumber=" + borrowernumber; >+ $("#patronPreview .modal-body").load( page + " div.container-fluid" ); >+ $('#patronPreview').modal({show:true}); >+ }); >+ >+ $("#patronPreview").on('hidden.bs.modal', function (e) { >+ $("#patronPreview .modal-body").html("<img src=\"[% interface | html %]/[% theme | html %]/img/spinner-small.gif\" alt=\"\" /> Loading"); >+ }); >+ >+ }); >+ >+ function filter() { >+ $("#firstletter_filter").val(''); >+ $("#[% table_id %]_search_results").show(); >+ >+ let table_dt = patrons_table.DataTable(); >+ [% FOR c IN columns %] >+ [% SWITCH c %] >+ [% CASE 'branch' %] >+ library_id = $("#branchcode_filter").val() || ""; >+ patrons_table.find('thead tr:eq(1) th[data-filter="libraries"] select').val(library_id); >+ if (library_id) >+ table_dt.column([% loop.count - 1 %]).search('^'+library_id+'$'); >+ [% CASE 'category' %] >+ let category_id = $("#categorycode_filter").val() || ""; >+ patrons_table.find('thead tr:eq(1) th[data-filter="categories"] select').val(category_id); >+ if (category_id) >+ table_dt.column([% loop.count - 1 %]).search('^'+category_id+'$'); >+ [% END %] >+ [% END %] >+ table_dt.search(""); >+ first_draw = 1; // Only redirect if we are coming from here >+ table_dt.draw(); >+ return false; >+ } >+ >+ // User has clicked on a letter >+ function filterByFirstLetterSurname(letter) { >+ $("#firstletter_filter").val(letter); >+ $("#[% table_id %]_search_results").show(); >+ patrons_table.DataTable().draw(); >+ } >+ >+ // modify parent window owner element >+ [% IF selection_type == 'add' %] >+ function add_user(borrowernumber, borrowername) { >+ var p = window.opener; >+ // In one place (serials/routing.tt), the page is reload on every add >+ // We have to wait for the page to be there >+ function wait_for_opener () { >+ if ( ! $(opener.document).find('body').size() ) { >+ setTimeout(wait_for_opener, 500); >+ } else { >+ [%# Note that add_user could sent data instead of borrowername too %] >+ $("#info").hide(); >+ $("#error").hide(); >+ if ( p.add_user(borrowernumber, borrowername) < 0 ) { >+ $("#error").html(_("Patron '%s' is already in the list.").format(borrowername)); >+ $("#error").show(); >+ } else { >+ $("#info").html(_("Patron '%s' added.").format(borrowername)); >+ $("#info").show(); >+ } >+ } >+ } >+ wait_for_opener(); >+ } >+ [% ELSIF selection_type == 'select' %] >+ function select_user(borrowernumber, data) { >+ var p = window.opener; >+ [% IF callback %] >+ p.[% callback | html %](borrowernumber, data); >+ [% ELSE %] >+ p.select_user(borrowernumber, data); >+ [% END %] >+ window.close(); >+ } >+ [% END %] >+ </script> >+[% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/search.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/search.tt >index ab2ac6ca684..620a9d73db6 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/search.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/search.tt >@@ -1,5 +1,4 @@ > [% USE raw %] >-[% USE To %] > [% USE Asset %] > [% USE Koha %] > [% USE Branches %] >@@ -8,400 +7,37 @@ > [% INCLUDE 'doc-head-open.inc' %] > [% SET libraries = Branches.all %] > [% SET categories = Categories.all.unblessed %] >+[% PROCESS 'patron-search.inc' %] > <title>Patron search › Koha</title> > [% INCLUDE 'doc-head-close.inc' %] >-<style> .modal-body .close { display: none; } </style> >+<style> .modal-body .close { display: none; } </style>[%# FIXME This is not great, we should make members/memberentrygen.tt use a modal as well and we won't need that here %] > </head> > > <body id="common_patron_search" class="common"> > <div id="patron_search" class="yui-t7"> > <div class="container-fluid"> > >- <form id="searchform"> >- <fieldset class="brief"> >- <h3>Search for patron</h3> >- <ol> >- <li> >- <label for="searchmember_filter">Search:</label> >- <input type="text" id="searchmember_filter" value="[% searchmember | html %]" class="focus" /> >- </li> >- >- [% FOR column IN columns %] >- [% SWITCH column %] >- [% CASE 'branch' %] >- <li> >- <label for="branchcode_filter">Library:</label> >- <select id="branchcode_filter"> >- [% SET libraries = Branches.all( only_from_group => 1 ) %] >- [% IF libraries.size != 1 %] >- <option value="">Any</option> >- [% END %] >- [% FOREACH l IN libraries %] >- <option value="[% l.branchcode | html %]">[% l.branchname | html %]</option> >- [% END %] >- </select> >- </li> >- [% CASE 'category' %] >- <li> >- <label for="categorycode_filter">Category:</label> >- <select id="categorycode_filter"> >- <option value="">Any</option> >- [% FOREACH category IN categories %] >- <option value="[% category.categorycode | html %]">[% category.description | html %]</option> >- [% END %] >- </select> >- </li> >- [% END %] >- [% END %] >- </ol> >- <fieldset class="action"> >- <input type="submit" value="Search" /> >- </fieldset> >- </fieldset> >+ [% PROCESS patron_search_filters categories => categories, libraries => libraries, columns => columns, search_filter => searchmember %] > </form> > >- [% IF filter == 'suggestions_managers' %] >- <div class="hint">Only staff with superlibrarian or suggestions_manage permissions are returned in the search results</div> >- [% ELSIF filter == 'orders_managers' %] >- <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> >- [% ELSIF filter == 'funds_owners' OR filter == 'funds_users' %] >- <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> >- [% END %] >- >- <div class="browse"> >- Browse by last name: >- [% FOREACH letter IN alphabet.split(' ') %] >- <a href="#" class="filterByLetter">[% letter | html %]</a> >- [% END %] >- </div> >- >- <div id="info" class="dialog message" style="display: none;"></div> >- <div id="error" class="dialog alert" style="dispay: none;"></div> >+ [% PROCESS patron_search_table table_id => 'memberresultst' columns => columns %] > >- <input type="hidden" id="firstletter_filter" value="" /> >- <div id="searchresults" style="display:none;"> >- <table id="memberresultst"> >- <thead> >- <tr> >- [% FOR column IN columns %] >- [% SWITCH column %] >- [% CASE 'cardnumber' %]<th>Card</th> >- [% CASE 'dateofbirth' %]<th>Date of birth</th> >- [% CASE 'address' %]<th>Address</th> >- [% CASE 'name' %]<th>Name</th> >- [% CASE 'branch' %]<th data-filter="libraries">Library</th> >- [% CASE 'category' %]<th data-filter="categories">Category</th> >- [% CASE 'dateexpiry' %]<th>Expires on</td> >- [% CASE 'borrowernotes' %]<th>Notes</th> >- [% CASE 'action' %]<th> </th> >- [% END %] >- [% END %] >- </tr> >- </thead> >- <tbody></tbody> >- </table> >- </div> >+ <div id="closewindow"><a href="#" class="btn btn-default btn-default close">Close</a></div> > >-<div id="closewindow"><a href="#" class="btn btn-default btn-default close">Close</a></div> >- >-<!-- Patron preview modal --> >-<div class="modal" id="patronPreview" tabindex="-1" role="dialog" aria-labelledby="patronPreviewLabel"> >- <div class="modal-dialog" role="document"> >- <div class="modal-content"> >- <div class="modal-header"> >- <button type="button" class="closebtn" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> >- <h4 class="modal-title" id="patronPreviewLabel"></h4> >- </div> >- <div class="modal-body"> >- <div id="loading"> >- <img src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif" alt="" /> Loading >- </div> >- </div> >- <div class="modal-footer"> >- <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> >- </div> >- </div> > </div> > </div> > >-</div> >-</div> >- > [% MACRO jsinclude BLOCK %] >- <script> >- let categories = [% To.json(categories) | $raw %]; >- let categories_map = categories.reduce((map, c) => { >- map[c.categorycode] = c; >- return map; >- }, {}); >- let libraries = [% To.json(libraries) | $raw %]; >- let libraries_map = libraries.reduce((map, l) => { >- map[l.branchcode] = l; >- return map; >- }, {}); >- >- [% IF Koha.Preference('ExtendedPatronAttributes') %] >- let extended_attribute_types = [% To.json(attribute_type_codes || []) | $raw %]; >- [% END %] >- </script> >- [% INCLUDE 'datatables.inc' %] >- [% INCLUDE 'js-date-format.inc' %] >- [% INCLUDE 'js-patron-get-age.inc' %] >- [% INCLUDE 'js-patron-format.inc' %] >- [% INCLUDE 'js-patron-format-address.inc' %] >- >- <script> >- var search = 0; >- let patrons_table; >- $(document).ready(function(){ >- $("#info").hide(); >- $("#error").hide(); >- >- $("#searchresults").hide(); >- >- let additional_filters = { >- surname: function(){ >- let start_with = $("#firstletter_filter").val() >- if (!start_with) return ""; >- return { "like": start_with + "%" } >- }, >- "-and": function(){ >- let filter = $("#searchmember_filter").val(); >- if (!filter) return ""; >- [% SET search_fields = Koha.Preference('DefaultPatronSearchFields') || 'surname,firstname,othernames,cardnumber,userid' %] >- return [ >- [% FOR search_field IN search_fields.split(',') %] >- {"me.[% search_field %]":{"like":"%"+filter+"%"}}, >- [% END %] >- [% IF Koha.Preference('ExtendedPatronAttributes') %] >- { >- "extended_attributes.value": { "like": "%" + filter + "%" }, >- "extended_attributes.code": extended_attribute_types >- } >- [% END %] >- ]; >- }, >- }; >- [% SET default_sort_column = "name" %] >- [% SET order_column_index = 0 %] >- patrons_table = $("#memberresultst").kohaTable({ >- "ajax": { >- [% SWITCH filter %] >- [% CASE 'suggestions_managers' %] >- "url": '/api/v1/suggestions/managers' >- [% CASE 'baskets_managers' %] >- "url": '/api/v1/acquisitions/baskets/managers' >- [% CASE 'funds_owners' %] >- "url": '/api/v1/acquisitions/funds/owners' >- [% CASE 'funds_users' %] >- "url": '/api/v1/acquisitions/funds/users' >- [% CASE %] >- "url": '/api/v1/patrons' >- [% END %] >- }, >- embed: ['extended_attributes'], >- "iDeferLoading": 0, >- "columns": [ >- [% FOR column IN columns %] >- [% IF default_sort_column == column %] >- [% order_column_index = loop.count - 1%] >- [% END %] >- [% SWITCH column %] >- [% CASE 'cardnumber' %] >- { >- "data": "cardnumber", >- "searchable": true, >- "orderable": true >- } >- [% CASE 'dateofbirth' %] >- { >- "data": "date_of_birth", >- "searchable": true, >- "orderable": true, >- "render": function( data, type, row, meta ) { >- return data ? escape_str($date(data) + " (" + _("%s years").format($get_age(data)) + ")") : ""; >- } >- } >- [% CASE 'address' %] >- { >- "data": "me.street_number:me.address:me.address2:me.city:me.state:me.postal_code:me.country", >- "searchable": true, >- "orderable": true, >- "render": function( data, type, row, meta ) { >- return escape_str($format_address(row) + " ") + escape_str(libraries_map[row.library_id].branchname); >- } >- } >- [% CASE 'name' %] >- { >- "data": "me.firstname:me.surname:othernames", >- "searchable": true, >- "orderable": true, >- "render": function( data, type, row, meta ) { >- let patron_id = encodeURIComponent(row.patron_id); >- return "<a href=\"/cgi-bin/koha/members/moremember.pl?borrowernumber=" + patron_id + "\" class=\"patron_preview\" data-borrowernumber=\"" + patron_id + "\" style=\"white-space:nowrap\">" + $patron_to_html(row, { invert_name: 1 }) + "</a>"; >- } >- } >- [% CASE 'branch' %] >- { >- "data": "library_id", >- "searchable": true, >- "orderable": true, >- "render": function( data, type, row, meta ) { >- return escape_str(libraries_map[data].branchname); >- } >- } >- [% CASE 'category' %] >- { >- "data": "category_id", >- "searchable": true, >- "orderable": true, >- "render": function( data, type, row, meta ) { >- return escape_str(categories_map[data].description); >- } >- } >- [% CASE 'dateexpiry' %] >- { >- "data": "expiry_date", >- "searchable": true, >- "orderable": true, >- "render": function( data, type, row, meta ) { >- return data ? escape_str($date(data)) : ""; >- } >- } >- [% CASE 'borrowernotes' %] >- { >- "data": "staff_notes", >- "searchable": true, >- "orderable": true, >- [%# We don't escape here, we allow html tag in staff notes %] >- } >- [% CASE 'action' %] >- { >- "data": function( row, type, val, meta ) { >- >- let patron_id = encodeURIComponent(row.patron_id); >- [% IF selection_type == 'select' %] >- 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)+'\' />'; >- [% ELSE %] >- 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 + '" />'; >- [% END %] >- }, >- "searchable": false, >- "orderable": false >- } >- [% END %] >- [% UNLESS loop.last %],[% END %] >- [% END %] >- ], >- "order": [[ [% order_column_index %], "asc" ]], >- 'bAutoWidth': false, >- 'sPaginationType': 'full_numbers', >- "iDisplayLength": [% Koha.Preference('PatronsPerPage') | html %], >- }, null, 1, additional_filters); >- >- $("#searchform").on('submit', filter); >- $(".filterByLetter").on("click",function(e){ >- e.preventDefault(); >- filterByFirstLetterSurname($(this).text()); >- }); >- $("body").on("click",".add_user",function(e){ >- e.preventDefault(); >- var borrowernumber = $(this).data("borrowernumber"); >- var firstname = $(this).data("firstname"); >- var surname = $(this).data("surname"); >- add_user( borrowernumber, firstname + " " + surname ); >- }); >- >- $("body").on("click",".select_user",function(e){ >- e.preventDefault(); >- var borrowernumber = $(this).data("borrowernumber"); >- var borrower_data = $("#borrower_data"+borrowernumber).val(); >- select_user( borrowernumber, JSON.parse(borrower_data) ); >- }); >- >- $("body").on("click",".patron_preview", function( e ){ >- e.preventDefault(); >- var borrowernumber = $(this).data("borrowernumber"); >- var page = "/cgi-bin/koha/members/moremember.pl?print=brief&borrowernumber=" + borrowernumber; >- $("#patronPreview .modal-body").load( page + " div.container-fluid" ); >- $('#patronPreview').modal({show:true}); >- }); >- >- $("#patronPreview").on('hidden.bs.modal', function (e) { >- $("#patronPreview .modal-body").html("<img src=\"[% interface | html %]/[% theme | html %]/img/spinner-small.gif\" alt=\"\" /> Loading"); >- }); >- >- }); >- >- function filter() { >- search = 1; >- $("#firstletter_filter").val(''); >- $("#searchresults").show(); >- >- let table_dt = patrons_table.DataTable(); >- [% FOR c IN columns %] >- [% SWITCH c %] >- [% CASE 'branch' %] >- let library_id = $("#branchcode_filter").val(); >- patrons_table.find('thead tr:eq(1) th[data-filter="libraries"] select').val(library_id); >- if (library_id) >- table_dt.column([% loop.count - 1 %]).search('^'+library_id+'$'); >- [% CASE 'category' %] >- let category_id = $("#categorycode_filter").val(); >- patrons_table.find('thead tr:eq(1) th[data-filter="categories"] select').val(category_id); >- if (category_id) >- table_dt.column([% loop.count - 1 %]).search('^'+category_id+'$'); >- [% END %] >- [% END %] >- table_dt.search(""); >- table_dt.draw(); >- return false; >- } >- >- // User has clicked on a letter >- function filterByFirstLetterSurname(letter) { >- $("#firstletter_filter").val(letter); >- search = 1; >- $("#searchresults").show(); >- patrons_table.fnDraw(); >- } >- >- // modify parent window owner element >- [% IF selection_type == 'add' %] >- function add_user(borrowernumber, borrowername) { >- var p = window.opener; >- // In one place (serials/routing.tt), the page is reload on every add >- // We have to wait for the page to be there >- function wait_for_opener () { >- if ( ! $(opener.document).find('body').size() ) { >- setTimeout(wait_for_opener, 500); >- } else { >- [%# Note that add_user could sent data instead of borrowername too %] >- $("#info").hide(); >- $("#error").hide(); >- if ( p.add_user(borrowernumber, borrowername) < 0 ) { >- $("#error").html(_("Patron '%s' is already in the list.").format(borrowername)); >- $("#error").show(); >- } else { >- $("#info").html(_("Patron '%s' added.").format(borrowername)); >- $("#info").show(); >- } >- } >- } >- wait_for_opener(); >- } >- [% ELSIF selection_type == 'select' %] >- function select_user(borrowernumber, data) { >- var p = window.opener; >- [% IF callback %] >- p.[% callback | html %](borrowernumber, data); >- [% ELSE %] >- p.select_user(borrowernumber, data); >- [% END %] >- window.close(); >- } >- [% END %] >- </script> >+ [% PROCESS patron_search_js >+ table_id => 'memberresultst', >+ categories => categories, >+ libraries => libraries, >+ extended_attribute_types => extended_attribute_types, >+ columns => columns, >+ filter => filter, >+ selection_type => selection_type, >+ callback => callback >+ %] > [% END %] > > [% SET popup_window = 1 %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >index cee579cc3b6..1a40ef665f8 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt >@@ -14,6 +14,10 @@ > [% PROCESS 'i18n.inc' %] > [% SET footerjs = 1 %] > [% INCLUDE 'doc-head-open.inc' %] >+[% SET libraries = Branches.all %] >+[% SET categories = Categories.all.unblessed %] >+[% SET columns = ['name', 'cardnumber', 'dateofbirth', 'category', 'branch', 'address', 'phone'] %] >+[% PROCESS "patron-search.inc" %] > [% UNLESS ( multi_hold ) %] > <title>Place a hold on [% INCLUDE 'biblio-title-head.inc' %] › Holds › Circulation › Koha</title> > [% ELSE %] >@@ -163,30 +167,9 @@ > [% END %] > </ul> > <div id="holds_patronsearch_pane"> >- <form id="holds_patronsearch" method="get"> >- <div class="hint">Enter patron card number or partial name:</div> >- <input type="text" size="40" id="patron" class="focus" autocomplete="off" /> >- <input type="submit" value="Search" /> >- [% FOREACH biblionumber IN biblionumbers %] >- <input type="hidden" name="biblionumber" value="[% biblionumber | html %]"/> >- [% END %] >- </form> <!-- /#holds_patronsearch --> >- >- <table id="table_borrowers" class="selections-table" style="display: none;"> >- <thead> >- <tr> >- <th>Name</th> >- <th>Address</th> >- <th>Card number</th> >- <th>Date of birth</th> >- <th>Category</th> >- <th>Library</th> >- <th>Primary phone</th> >- </tr> >- </thead> >- <tbody></tbody> >- </table> >+ [% PROCESS patron_search_filters_simple %] > >+ [% PROCESS patron_search_table table_id => 'table_borrowers', open_on_row_click => 1 %] > </div> > [% IF clubcount %] > <div id="holds_clubsearch_pane"> >@@ -1187,7 +1170,6 @@ > } > > var MSG_CANCEL_SELECTED = _("Cancel selected (%s)"); >- columns_settings_borrowers_table = [% TablesSettings.GetColumns( 'circ', 'circulation', 'table_borrowers', 'json' ) | $raw %]; > $.fn.select2.defaults.set("width", "100%" ); > $.fn.select2.defaults.set("dropdownAutoWidth", true ); > >@@ -1569,79 +1551,35 @@ > } > return false; > }); >+ }); >+ </script> > >- [% FOREACH biblionumber IN biblionumbers %] >- [% SET url_biblio_params = url_biblio_params _ "&biblionumber=" _ biblionumber %] >- [% END %] >- [% IF multi_hold %] >- [% SET url_biblio_params = url_biblio_params _ "&multi_hold=1" %] >- [% END %] >- search = 0; >- dtMemberResults = KohaTable("table_borrowers", { >- 'bServerSide': true, >- 'sAjaxSource': "/cgi-bin/koha/svc/members/search", >- 'fnServerData': function(sSource, aoData, fnCallback) { >- if ( ! search ) { >- return; >- } >- aoData.push({ >- 'name': 'searchmember', >- 'value': $("#patron").val() >- },{ >- 'name': 'template_path', >- 'value': 'reserve/tables/members_results.tt', >- }); >- $.ajax({ >- 'dataType': 'json', >- 'type': 'POST', >- 'url': sSource, >- 'data': aoData, >- 'success': function(json){ >- // redirect if there is only 1 result. >- if ( json.iTotalDisplayRecords == 1 ) { >- var borrowernumber = json.aaData[0].borrowernumber; >- document.location.href = '/cgi-bin/koha/reserve/request.pl?borrowernumber=' + borrowernumber + "[% url_biblio_params %]" >- return false; >- } >- fnCallback(json); >- } >- }); >- }, >- 'fnDrawCallback': function (oSettings) { >- var data = this.fnGetData(); >- $.each($(this).find("tbody tr"), function(index, tr) { >- let url = '/cgi-bin/koha/reserve/request.pl?borrowernumber=' + data[index].borrowernumber + "[% url_biblio_params %]" >- $(tr).off('click').on('click', function() { >- document.location.href = url; >- }).addClass('clickable'); >- $(tr).find("a.patron_preview").attr('href', url); >- }); >- }, >- 'aoColumns':[ >- { 'mDataProp': 'dt_name' }, >- { 'mDataProp': 'dt_address' }, >- { 'mDataProp': 'dt_cardnumber' }, >- { 'mDataProp': 'dt_dateofbirth' }, >- { 'mDataProp': 'dt_category' }, >- { 'mDataProp': 'dt_branch' }, >- { 'mDataProp': 'dt_phone' }, >- ], >- 'bFilter': false, >- 'bAutoWidth': false, >- 'sPaginationType': 'full_numbers', >- "bProcessing": true >- }, columns_settings_borrowers_table ); >- $("#table_borrowers_wrapper").hide(); >- >- function filter() { >- search = 1; >- $("#table_borrowers").show(); >- $("#table_borrowers_wrapper").show(); >- dtMemberResults.fnDraw(); >- return false; >- } >- $("#holds_patronsearch").on("submit", filter); > >+ <script> >+ $(document).ready(function() { >+ table_settings = [% TablesSettings.GetColumns( 'circ', 'circulation', 'table_borrowers', 'json' ) | $raw %]; >+ }); >+ </script> >+ >+ [% SET url_biblio_params = "biblionumber=" _ biblionumbers.join("&biblionumber=") %] >+ [% IF multi_hold %] >+ [% SET url_biblio_params = url_biblio_params _ "&multi_hold=1" %] >+ [% END %] >+ >+ [% PROCESS patron_search_js >+ table_id => 'table_borrowers', >+ categories => categories, >+ libraries => libraries, >+ extended_attribute_types => attribute_type_codes, >+ columns => columns, >+ open_on_row_click => 1, >+ on_click_url => '/cgi-bin/koha/reserve/request.pl?' _ url_biblio_params, >+ redirect_if_one_result => 1, >+ redirect_url => '/cgi-bin/koha/reserve/request.pl?' _ url_biblio_params >+ %] >+ <script> >+ $(document).ready(function() { >+ $("#holds_patronsearch").on("submit", filter); > }); > </script> > [% END %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/tables/members_results.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/tables/members_results.tt >deleted file mode 100644 >index 15370307a58..00000000000 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/tables/members_results.tt >+++ /dev/null >@@ -1,32 +0,0 @@ >-[% USE raw %] >-[% USE I18N %] >-[% USE To %] >-[% USE Price %] >-[% PROCESS 'member-display-address-style.inc' %] >-{ >- "sEcho": [% sEcho | html %], >- "iTotalRecords": [% iTotalRecords | html %], >- "iTotalDisplayRecords": [% iTotalDisplayRecords | html %], >- "aaData": [ >- [% FOREACH data IN aaData %] >- { >- "dt_name": >- "<a href=\"/cgi-bin/koha/members/moremember.pl?borrowernumber=[% data.borrowernumber | html %]\" class=\"patron_preview\" data-borrowernumber=\"[% data.borrowernumber | html %]\" style='white-space:nowrap' title=\"[% I18N.t("View") | html %]\">[% INCLUDE 'patron-title.inc' borrowernumber = data.borrowernumber category_type = data.category_type firstname = data.firstname surname = data.surname othernames = data.othernames invert_name = 1 | $To %]</a><br />", >- "dt_address": >- "[%~ INCLUDE 'display-address-style' patron=data no_line_break=1 | $To ~%]", >- "dt_cardnumber": >- "[% data.cardnumber | html | $To %]", >- "dt_dateofbirth": >- "[% INCLUDE 'patron-age.inc' patron = data %]", >- "dt_category": >- "[% data.category_description | html | $To %] <span class=\"patron_category_type\">([% data.category_type | html | $To %])</span>", >- "dt_branch": >- "[% data.branchname | html | $To %]", >- "dt_phone": >- "[% data.phone| html | $To %]", >- "borrowernumber": >- "[% data.borrowernumber | html %]" >- }[% UNLESS loop.last %],[% END %] >- [% END %] >- ] >-} >diff --git a/members/search.pl b/members/search.pl >index b53773ad007..c3d80a2e4fb 100755 >--- a/members/search.pl >+++ b/members/search.pl >@@ -46,7 +46,6 @@ $template->param( > columns => \@columns, > filter => $filter, > selection_type => $selection_type, >- alphabet => ( C4::Context->preference('alphabet') || join ' ', 'A' .. 'Z' ), > attribute_type_codes => ( C4::Context->preference('ExtendedPatronAttributes') > ? [ Koha::Patron::Attribute::Types->search( { staff_searchable => 1 } )->get_column('code') ] > : [] ), >diff --git a/reserve/request.pl b/reserve/request.pl >index 433923980cc..8af97c234a1 100755 >--- a/reserve/request.pl >+++ b/reserve/request.pl >@@ -39,7 +39,6 @@ use C4::Koha qw( getitemtypeimagelocation ); > use C4::Serials qw( CountSubscriptionFromBiblionumber ); > use C4::Circulation qw( GetTransfers _GetCircControlBranch GetBranchItemRule ); > use Koha::DateUtils qw( dt_from_string output_pref ); >-use C4::Utils::DataTables::Members; > use C4::Search qw( enabled_staff_search_views ); > > use Koha::Biblios; >@@ -51,6 +50,7 @@ use Koha::Items; > use Koha::ItemTypes; > use Koha::Libraries; > use Koha::Patrons; >+use Koha::Patron::Attribute::Types; > use Koha::Clubs; > use Koha::BackgroundJob::BatchCancelHold; > >@@ -686,6 +686,14 @@ if ( ( $findborrower && $borrowernumber_hold || $findclub && $club_hold ) > } > $template->param( biblionumbers => \@biblionumbers ); > >+$template->param( >+ attribute_type_codes => ( C4::Context->preference('ExtendedPatronAttributes') >+ ? [ Koha::Patron::Attribute::Types->search( { staff_searchable => 1 } )->get_column('code') ] >+ : [] >+ ), >+); >+ >+ > # pass the userenv branch if no pickup location selected > $template->param( pickup => $pickup || C4::Context->userenv->{branch} ); > >-- >2.25.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 30093
:
130605
|
130606
|
130627
|
130628
|
130705
|
130944
|
130945
|
130946
|
131830
|
131831
|
131832
|
132537
|
132538
|
132540
|
132541
|
132542
|
132647
|
132648
|
132653
|
132654
|
132655
|
132699
|
132700
|
132701
|
132702
|
132724
|
132725
|
132726
|
132727
|
132728