Bugzilla – Attachment 82432 Details for
Bug 20600
Provide the ability for users to filter ILL requests
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 20600: Add filtering of ILL requests in list
Bug-20600-Add-filtering-of-ILL-requests-in-list.patch (text/plain), 20.85 KB, created by
Andrew Isherwood
on 2018-11-19 11:30:46 UTC
(
hide
)
Description:
Bug 20600: Add filtering of ILL requests in list
Filename:
MIME Type:
Creator:
Andrew Isherwood
Created:
2018-11-19 11:30:46 UTC
Size:
20.85 KB
patch
obsolete
>From 9f6c671f518e25bfe021d4c39d49676c5508bece Mon Sep 17 00:00:00 2001 >From: Andrew Isherwood <andrew.isherwood@ptfs-europe.com> >Date: Fri, 20 Apr 2018 14:25:49 +0100 >Subject: [PATCH] Bug 20600: Add filtering of ILL requests in list > >This patch adds the ability for the ILL request list in the staff >interface to be filtered by a number of criteria: > >- Status >- Date placed >- Date modified >- Pickup branch >- Borrower card number > >To test: >1) Apply patch >2) Ensure you have a reasonable range of ILL requests created >3) Navigate to the "View ILL requests" page >4) Choose one or more filtering criteria >5) Click "Search" >6) Observe the results are filtered to match the selected criteria >7) Click "Clear" >8) Observe your results are returned to their initial state >9) Repeat steps 4 -> 6 until you are happy. > >Dates supplied by the /api/v1/illrequests API route were not conforming >to the preference specified by the dateformat syspref. This patch >addresses that. > >It has been addressed as part of this bug since we are adding filtering >of requests by some date fields and, therefore, needed dates in a >predictable format. > >To test: >1) Apply the patch >2) Ensure you have at least one ILL request created >3) Make a request to the /api/v1/illrequests endpoint >4) Observe that dates supplied for "placed_formatted" & "updated_formatted" conform to your >dateformat syspref. >5) Change your date format syspref, repeat steps 3 & 4 > >Signed-off-by: Magnus Enger <magnus@libriotech.no> >Works as advertised. Nice enh! > >Signed-off-by: Owen Leonard <oleonard@myacpl.org> >--- > Koha/REST/V1/Illrequests.pm | 20 ++ > .../intranet-tmpl/prog/css/src/staff-global.scss | 5 + > .../prog/en/modules/ill/ill-requests.tt | 328 +++++++++++++++++++-- > 3 files changed, 323 insertions(+), 30 deletions(-) > >diff --git a/Koha/REST/V1/Illrequests.pm b/Koha/REST/V1/Illrequests.pm >index a3a0d61c1c..d072b6382f 100644 >--- a/Koha/REST/V1/Illrequests.pm >+++ b/Koha/REST/V1/Illrequests.pm >@@ -24,6 +24,7 @@ use Koha::Illrequestattributes; > use Koha::Libraries; > use Koha::Patrons; > use Koha::Libraries; >+use Koha::DateUtils qw( format_sqldatetime ); > > =head1 NAME > >@@ -41,6 +42,9 @@ sub list { > my $c = shift->openapi->valid_input or return; > > my $args = $c->req->params->to_hash // {}; >+ my $filter; >+ my $output = []; >+ my @format_dates = ( 'placed', 'updated' ); > > # Create a hash where all keys are embedded values > # Enables easy checking >@@ -54,6 +58,22 @@ sub list { > # Get all requests > my @requests = Koha::Illrequests->as_list; > >+ # Create new "formatted" columns for each date column >+ # that needs formatting >+ foreach(@requests) { >+ foreach my $field(@format_dates) { >+ if (defined $_->{$field}) { >+ $_->{$field . "_formatted"} = format_sqldatetime( >+ $_->{$field}, >+ undef, >+ undef, >+ 1 >+ ); >+ } >+ } >+ >+ } >+ > # Identify patrons & branches that > # we're going to need and get them > my $to_fetch = { >diff --git a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss >index dc72a32732..ba61e17474 100644 >--- a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss >+++ b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss >@@ -4002,6 +4002,11 @@ span { > } > } > >+#illfilter_dateplaced, >+#illfilter_datemodified { >+ width: 80%; >+} >+ > #requestattributes { > font-family: monospace; > line-height: 1.3em; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/ill/ill-requests.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/ill/ill-requests.tt >index 54b69d0009..8df43635eb 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/ill/ill-requests.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/ill/ill-requests.tt >@@ -10,12 +10,30 @@ > [% Asset.js("lib/jquery/plugins/jquery.checkboxes.min.js") | $raw %] > [% Asset.css("css/datatables.css") | $raw %] > [% INCLUDE 'datatables.inc' %] >-<script> >+[% INCLUDE 'calendar.inc' %] >+<script type="text/javascript"> > //<![CDATA[ > $(document).ready(function() { > > // Illview Datatable setup > >+ var table; >+ >+ // Filters that are active >+ var activeFilters = {}; >+ >+ // Date format for datepickers >+ var dateMap = { >+ dmydot: 'dd.mm.yy', >+ iso: 'yy-mm-dd', >+ metric: 'dd/mm/yy', >+ us: 'mm/dd/yy' >+ }; >+ var dateFormat = dateMap['[% Koha.Preference('dateformat') %]']; >+ $('#illfilter_dateplaced, #illfilter_datemodified').datepicker( >+ 'option', 'dateFormat', dateFormat >+ ); >+ > // Fields we don't want to display > var ignore = [ > 'accessurl', >@@ -27,7 +45,6 @@ > 'medium', > 'notesopac', > 'notesstaff', >- 'placed', > 'replied' > ]; > >@@ -46,15 +63,150 @@ > 'metadata_author', > 'metadata_title', > 'borrowername', >+ 'patron_cardnumber', > 'biblio_id', > 'library', > 'status', >+ 'placed', >+ 'placed_formatted', > 'updated', >+ 'updated_formatted', > 'illrequest_id', > 'comments', > 'action' // Action should always be last > ]; > >+ // Filterable columns >+ var filterable = { >+ status: { >+ prep: function(tableData, oData) { >+ var uniques = {}; >+ tableData.forEach(function(row) { >+ var resolvedName = getStatusName( >+ oData[0].capabilities[row.status].name >+ ); >+ uniques[resolvedName] = 1 >+ }); >+ Object.keys(uniques).sort().forEach(function(unique) { >+ $('#illfilter_status').append( >+ '<option value="' + unique + >+ '">' + unique + '</option>' >+ ); >+ }); >+ }, >+ listener: function() { >+ var me = 'status'; >+ $('#illfilter_status').change(function() { >+ var sel = $('#illfilter_status option:selected').val(); >+ if (sel && sel.length > 0) { >+ activeFilters[me] = function() { >+ table.column(6).search(sel); >+ } >+ } else { >+ if (activeFilters.hasOwnProperty(me)) { >+ delete activeFilters[me]; >+ } >+ } >+ }); >+ }, >+ clear: function() { >+ $('#illfilter_status').val(''); >+ } >+ }, >+ pickupBranch: { >+ prep: function(tableData, oData) { >+ var uniques = {}; >+ tableData.forEach(function(row) { >+ uniques[row.library.branchname] = 1 >+ }); >+ Object.keys(uniques).sort().forEach(function(unique) { >+ $('#illfilter_branchname').append( >+ '<option value="' + unique + >+ '">' + unique + '</option>' >+ ); >+ }); >+ }, >+ listener: function() { >+ var me = 'pickupBranch'; >+ $('#illfilter_branchname').change(function() { >+ var sel = $('#illfilter_branchname option:selected').val(); >+ if (sel && sel.length > 0) { >+ activeFilters[me] = function() { >+ table.column(5).search(sel); >+ } >+ } else { >+ if (activeFilters.hasOwnProperty(me)) { >+ delete activeFilters[me]; >+ } >+ } >+ }); >+ }, >+ clear: function() { >+ $('#illfilter_branchname').val(''); >+ } >+ }, >+ barcode: { >+ listener: function() { >+ var me = 'barcode'; >+ $('#illfilter_barcode').change(function() { >+ var val = $('#illfilter_barcode').val(); >+ if (val && val.length > 0) { >+ activeFilters[me] = function() { >+ table.column(3).search(val); >+ } >+ } else { >+ if (activeFilters.hasOwnProperty(me)) { >+ delete activeFilters[me]; >+ } >+ } >+ }); >+ }, >+ clear: function() { >+ $('#illfilter_barcode').val(''); >+ } >+ }, >+ dateModified: { >+ listener: function() { >+ var me = 'dateModified'; >+ $('#illfilter_datemodified').change(function() { >+ var val = $('#illfilter_datemodified').val(); >+ if (val && val.length > 0) { >+ activeFilters[me] = function() { >+ table.column(10).search(val); >+ } >+ } else { >+ if (activeFilters.hasOwnProperty(me)) { >+ delete activeFilters[me]; >+ } >+ } >+ }); >+ }, >+ clear: function() { >+ $('#illfilter_datemodified').val(''); >+ } >+ }, >+ datePlaced: { >+ listener: function() { >+ var me = 'datePlaced'; >+ $('#illfilter_dateplaced').change(function() { >+ var val = $('#illfilter_dateplaced').val(); >+ if (val && val.length > 0) { >+ activeFilters[me] = function() { >+ table.column(8).search(val); >+ } >+ } else { >+ if (activeFilters.hasOwnProperty(me)) { >+ delete activeFilters[me]; >+ } >+ } >+ }); >+ }, >+ clear: function() { >+ $('#illfilter_dateplaced').val(''); >+ } >+ } >+ }; >+ > // Remove any fields we're ignoring > var removeIgnore = function(dataObj) { > dataObj.forEach(function(thisRow) { >@@ -147,31 +299,35 @@ > var status_name = meta.settings.oInit.originalData[0].capabilities[ > row.status > ].name; >- switch( status_name ) { >- case "New request": >- return _("New request"); >- case "Requested": >- return _("Requested"); >- case "Requested from partners": >- return _("Requested from partners"); >- case "Request reverted": >- return _("Request reverted"); >- case "Queued request": >- return _("Queued request"); >- case "Cancellation requested": >- return _("Cancellation requested"); >- case "Completed": >- return _("Completed"); >- case "Delete request": >- return _("Delete request"); >- default: >- return status_name; >- } >+ return getStatusName(status_name); > } else { > return ''; > } > }; > >+ var getStatusName = function(origName) { >+ switch( origName ) { >+ case "New request": >+ return _("New request"); >+ case "Requested": >+ return _("Requested"); >+ case "Requested from partners": >+ return _("Requested from partners"); >+ case "Request reverted": >+ return _("Request reverted"); >+ case "Queued request": >+ return _("Queued request"); >+ case "Cancellation requested": >+ return _("Cancellation requested"); >+ case "Completed": >+ return _("Completed"); >+ case "Delete request": >+ return _("Delete request"); >+ default: >+ return origName; >+ } >+ }; >+ > // Render function for creating a row's action link > var createActionLink = function(data, type, row) { > return '<a class="btn btn-default btn-sm" ' + >@@ -206,6 +362,12 @@ > library: { > name: _("Library"), > func: createLibrary >+ }, >+ updated: { >+ name: _("Updated on"), >+ }, >+ patron_cardnumber: { >+ name: _("Patron barcode") > } > }; > >@@ -268,7 +430,8 @@ > // Create the base column object > var colObj = { > name: thisCol, >- className: thisCol >+ className: thisCol, >+ defaultContent: '' > }; > // We may need to process the data going in this > // column, so do it if necessary >@@ -284,27 +447,90 @@ > }); > > // Initialise the datatable >- $('#ill-requests').DataTable($.extend(true, {}, dataTablesDefaults, { >- 'aoColumnDefs': [ // Last column shouldn't be sortable or searchable >- { >+ table = $('#ill-requests').DataTable($.extend(true, {}, dataTablesDefaults, { >+ 'aoColumnDefs': [ >+ { // Last column shouldn't be sortable or searchable > 'aTargets': [ 'actions' ], > 'bSortable': false, > 'bSearchable': false > }, >+ { // Hide the two date columns we use just for sorting >+ 'aTargets': [ 'placed', 'updated' ], >+ 'bVisible': false, >+ 'bSearchable': false >+ }, >+ { // When sorting 'placed', we want to use the >+ // unformatted column >+ 'aTargets': [ 'placed_formatted'], >+ 'iDataSort': 7 >+ }, >+ { // When sorting 'updated', we want to use the >+ // unformatted column >+ 'aTargets': [ 'updated_formatted'], >+ 'iDataSort': 9 >+ } > ], >- 'aaSorting': [[ 6, 'desc' ]], // Default sort, updated descending >+ 'aaSorting': [[ 9, 'desc' ]], // Default sort, updated descending > 'processing': true, // Display a message when manipulating > 'iDisplayLength': 10, // 10 results per page > 'sPaginationType': "full_numbers", // Pagination display > 'deferRender': true, // Improve performance on big datasets > 'data': dataCopy, > 'columns': colData, >- 'originalData': data // Enable render functions to access >- // our original data >+ 'originalData': data, // Enable render functions to access >+ // our original data >+ 'initComplete': function() { >+ >+ // Prepare any filter elements that need it >+ for (var el in filterable) { >+ if (filterable.hasOwnProperty(el)) { >+ if (filterable[el].hasOwnProperty('prep')) { >+ filterable[el].prep(dataCopy, data); >+ } >+ if (filterable[el].hasOwnProperty('listener')) { >+ filterable[el].listener(); >+ } >+ } >+ } >+ >+ } > })); >+ > } > ); > >+ var clearSearch = function() { >+ table.search('').columns().search(''); >+ activeFilters = {}; >+ for (var filter in filterable) { >+ if ( >+ filterable.hasOwnProperty(filter) && >+ filterable[filter].hasOwnProperty('clear') >+ ) { >+ filterable[filter].clear(); >+ } >+ } >+ table.draw(); >+ }; >+ >+ // Apply any search filters, or clear any previous >+ // ones >+ $('#illfilter_form').submit(function(event) { >+ event.preventDefault(); >+ table.search('').columns().search(''); >+ for (var active in activeFilters) { >+ if (activeFilters.hasOwnProperty(active)) { >+ activeFilters[active](); >+ } >+ } >+ table.draw(); >+ }); >+ >+ // Clear all filters >+ $('#clear_search').click(function() { >+ clearSearch(); >+ }); >+ > }); > //]]> > </script> >@@ -326,6 +552,45 @@ > > <div id="doc3" class="yui-t2"> > <div id="bd"> >+ [% IF query_type == 'illlist' %] >+ <div id="illfilter_yui_column" class="yui-b"> >+ <form method="get" id="illfilter_form"> >+ <fieldset class="brief"> >+ <h3>Filters</h3> >+ <ol> >+ <li> >+ <label for="illfilter_status">Status:</label> >+ <select name="illfilter_status" id="illfilter_status"> >+ <option value=""></option> >+ </select> >+ </li> >+ <li> >+ <label for="illfilter_dateplaced">Date placed:</label> >+ <input type="text" name="illfilter_dateplaced" id="illfilter_dateplaced" class="datepicker"> >+ </li> >+ <li> >+ <label for="illfilter_datemodified">Updated on:</label> >+ <input type="text" name="illfilter_datemodified" id="illfilter_datemodified" class="datepicker"> >+ </li> >+ <li> >+ <label for="illfilter_branchname">Library:</label> >+ <select name="illfilter_branchname" id="illfilter_branchname"> >+ <option value=""></option> >+ </select> >+ </li> >+ <li> >+ <label for="illfilter_barcode">Patron barcode:</label> >+ <input type="text" name="illfilter_barcode" id="illfilter_barcode"> >+ </li> >+ </ol> >+ <fieldset class="action"> >+ <input type="submit" value="Search" /> >+ <input type="button" value="Clear" id="clear_search" /> >+ </fieldset> >+ </fieldset> >+ </form> >+ </div> >+ [% END %] > <div id="yui-main"> > <div id="interlibraryloans" class="yui-b"> > [% IF !backends_available || !has_branch %] >@@ -706,7 +971,10 @@ > <th>Bibliographic record ID</th> > <th>Library</th> > <th>Status</th> >- <th>Updated on</th> >+ <th class="placed"> </th> >+ <th class="placed_formatted">Date placed</th> >+ <th class="updated"> </th> >+ <th class="updated_formatted">Updated on</th> > <th>Request number</th> > <th>Comments</th> > <th class="actions"></th> >-- >2.11.0
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 20600
:
74640
|
74641
|
75202
|
75276
|
75734
|
75735
|
75753
|
75755
|
75844
|
75845
|
75848
|
75849
|
75850
|
75851
|
75852
|
75853
|
75854
|
75871
|
77691
|
77692
|
77693
|
77694
|
77695
|
77696
|
77697
|
78439
|
78440
|
78441
|
78442
|
78443
|
78444
|
78445
|
78446
|
78463
|
78464
|
78465
|
78466
|
78467
|
78468
|
78469
|
78470
|
79183
|
80468
|
81992
|
81993
|
82032
|
82033
|
82034
|
82035
|
82036
|
82037
|
82038
|
82039
|
82062
|
82170
|
82171
|
82432
|
82433
|
82434
|
82435
|
82436
|
82437
|
82438
|
82439
|
82440
|
82441
|
82442
|
83882
|
83887
|
84736
|
84737
|
84738
|
84739
|
84740
|
84741
|
84742
|
84743
|
84744
|
84745
|
84746
|
84747
|
84748
|
84749
|
85037
|
85038
|
85039
|
85040
|
85041
|
85042
|
85043
|
85044
|
85045
|
85046
|
85047
|
85048
|
85049
|
85050