Bugzilla – Attachment 150719 Details for
Bug 22440
Improve ILL page performance by moving to server side filtering
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 22440: New ILL requests table
Bug-22440-New-ILL-requests-table.patch (text/plain), 66.52 KB, created by
Martin Renvoize
on 2023-05-05 11:04:55 UTC
(
hide
)
Description:
Bug 22440: New ILL requests table
Filename:
MIME Type:
Creator:
Martin Renvoize
Created:
2023-05-05 11:04:55 UTC
Size:
66.52 KB
patch
obsolete
>From 3d2952745e3283a9227380f6006ae5a02b5cd173 Mon Sep 17 00:00:00 2001 >From: Pedro Amorim <pedro.amorim@ptfs-europe.com> >Date: Thu, 30 Mar 2023 12:07:17 +0200 >Subject: [PATCH] Bug 22440: New ILL requests table >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >Content-Transfer-Encoding: 8bit > >Use kohaTable requesting the REST api instead of the old KohaTable > >Co-authored-by: Tomás Cohen Arazi <tomascohen@theke.io> >Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com> >--- > Koha/Illrequest.pm | 14 +- > Koha/Illrequestattributes.pm | 16 + > Koha/Schema/Result/Illrequest.pm | 2 +- > admin/columns_settings.yml | 17 +- > api/v1/swagger/definitions/ill_request.yaml | 2 +- > api/v1/swagger/paths/illrequests.yaml | 2 +- > .../en/includes/ill-list-table-strings.inc | 18 +- > .../prog/en/includes/ill-list-table.inc | 27 +- > .../prog/en/includes/js-biblio-format.inc | 57 +- > .../prog/en/modules/ill/ill-requests.tt | 113 ++- > .../prog/en/modules/members/ill-requests.tt | 2 + > koha-tmpl/intranet-tmpl/prog/js/datatables.js | 40 +- > .../intranet-tmpl/prog/js/ill-list-table.js | 905 ++++++++---------- > 13 files changed, 594 insertions(+), 621 deletions(-) > >diff --git a/Koha/Illrequest.pm b/Koha/Illrequest.pm >index 227484d95c..8c58e7f7e7 100644 >--- a/Koha/Illrequest.pm >+++ b/Koha/Illrequest.pm >@@ -24,6 +24,7 @@ use Try::Tiny qw( catch try ); > use DateTime; > > use C4::Letters; >+use Mojo::Util qw(deprecated); > > use Koha::Cache::Memory::Lite; > use Koha::Database; >@@ -177,6 +178,7 @@ sub statusalias { > =cut > > sub illrequestattributes { >+ deprecated 'illrequestattributes is DEPRECATED in favor of extended_attributes'; > my ( $self ) = @_; > return Koha::Illrequestattributes->_new_from_dbic( > scalar $self->_result->illrequestattributes >@@ -247,20 +249,20 @@ sub library { > return Koha::Library->_new_from_dbic( scalar $self->_result->library ); > } > >-=head3 ill_extended_attributes >+=head3 extended_attributes > >- my $ill_extended_attributes = $request->ill_extended_attributes; >+ my $extended_attributes = $request->extended_attributes; > > Returns the linked I<Koha::Illrequestattributes> resultset object. > > =cut > >-sub ill_extended_attributes { >+sub extended_attributes { > my ( $self ) = @_; > >- return Koha::Illrequestattributes->_new_from_dbic( >- scalar $self->_result->ill_extended_attributes >- ); >+ my $rs = $self->_result->extended_attributes; >+ # We call search to use the filters in Koha::Illrequestattributes->search >+ return Koha::Illrequestattributes->_new_from_dbic($rs)->search; > } > > =head3 status_alias >diff --git a/Koha/Illrequestattributes.pm b/Koha/Illrequestattributes.pm >index 947ef0db22..fbf3409366 100644 >--- a/Koha/Illrequestattributes.pm >+++ b/Koha/Illrequestattributes.pm >@@ -32,6 +32,22 @@ Koha::Illrequestattributes - Koha Illrequestattributes Object class > > =head2 Class Methods > >+=cut >+ >+=head3 search >+ >+my $attributes = Koha::Illrequestattributes->search( $params ); >+ >+=cut >+ >+sub search { >+ my ( $self, $params, $attributes ) = @_; >+ >+ unless ( exists $attributes->{order_by} ) { $attributes->{order_by} = ['me.type', 'value'] } >+ >+ return $self->SUPER::search( $params, $attributes ); >+} >+ > =head3 type > > =cut >diff --git a/Koha/Schema/Result/Illrequest.pm b/Koha/Schema/Result/Illrequest.pm >index 51dabbec12..5f1b0230dd 100644 >--- a/Koha/Schema/Result/Illrequest.pm >+++ b/Koha/Schema/Result/Illrequest.pm >@@ -342,7 +342,7 @@ __PACKAGE__->has_many( > ); > > __PACKAGE__->has_many( >- "ill_extended_attributes", >+ "extended_attributes", > "Koha::Schema::Result::Illrequestattribute", > { "foreign.illrequest_id" => "self.illrequest_id" }, > { cascade_copy => 0, cascade_delete => 0 }, >diff --git a/admin/columns_settings.yml b/admin/columns_settings.yml >index 12091f3154..cdff0ea0bb 100644 >--- a/admin/columns_settings.yml >+++ b/admin/columns_settings.yml >@@ -824,7 +824,7 @@ modules: > ill-requests: > columns: > - >- columnname: illrequest_id >+ columnname: ill_request_id > - > columnname: metadata_author > - >@@ -851,27 +851,12 @@ modules: > columnname: library_branchname > - > columnname: status >- - >- columnname: placed >- cannot_be_toggled: 1 >- cannot_be_modified: 1 >- is_hidden: 1 > - > columnname: placed_formatted >- - >- columnname: updated >- cannot_be_toggled: 1 >- cannot_be_modified: 1 >- is_hidden: 1 > - > columnname: updated_formatted > - > columnname: replied >- - >- columnname: completed >- cannot_be_toggled: 1 >- cannot_be_modified: 1 >- is_hidden: 1 > - > columnname: completed_formatted > - >diff --git a/api/v1/swagger/definitions/ill_request.yaml b/api/v1/swagger/definitions/ill_request.yaml >index 6178944755..7c668bdfb5 100644 >--- a/api/v1/swagger/definitions/ill_request.yaml >+++ b/api/v1/swagger/definitions/ill_request.yaml >@@ -108,7 +108,7 @@ properties: > - integer > - "null" > description: The linked comment objects count (x-koha-embed) >- ill_extended_attributes: >+ extended_attributes: > type: > - array > - "null" >diff --git a/api/v1/swagger/paths/illrequests.yaml b/api/v1/swagger/paths/illrequests.yaml >index bcee3d85a5..5e0d016998 100644 >--- a/api/v1/swagger/paths/illrequests.yaml >+++ b/api/v1/swagger/paths/illrequests.yaml >@@ -27,7 +27,7 @@ > - biblio > - comments > - comments+count >- - ill_extended_attributes >+ - extended_attributes > - library > - id_prefix > - patron >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/ill-list-table-strings.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/ill-list-table-strings.inc >index 7734384155..f4327f40eb 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/ill-list-table-strings.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/ill-list-table-strings.inc >@@ -1,21 +1,7 @@ > <!-- ill-list-table-strings.inc --> > <script> >- var ill_borrower_details = _("View patron details"); >- var ill_biblio_details = _("View bibliographic record"); >- var ill_statuses = { >- new: _("New request"), >- req: _("Requested"), >- genreq: _("Requested from partners"), >- rev: _("Reverted"), >- que: _("Queued request"), >- canc: _("Cancellation requested"), >- comp: _("Completed"), >- del: _("Delete request") >- }; > var ill_manage = _("Manage request"); >- var ill_columns = { >- biblio_id: _("Bibliographic record ID"), >- updated: _("Updated on") >- }; >+ var ill_manage_select_backend_first = _("Select a backend first"); >+ var ill_all_statuses = _("All statuses"); > </script> > <!-- / ill-list-table-strings.inc --> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/ill-list-table.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/ill-list-table.inc >index 755e6e550b..c0d75cc27b 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/ill-list-table.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/ill-list-table.inc >@@ -1,30 +1,23 @@ >-[% IF prefilters.length > 0 %] >-<table id="ill-requests" data-prefilters="[% prefilters | html %]"> >-[% ELSE %] > <table id="ill-requests"> >-[% END %] > <thead> >- <tr id="illview-header"> >+ <tr id="ill_requests_header"> > <th scope="col">Request ID</th> >- <th scope="col">Author</th> >- <th scope="col">Title</th> >- <th scope="col">Article title</th> >- <th scope="col">Issue</th> >- <th scope="col">Volume</th> >- <th scope="col">Year</th> >- <th scope="col">Pages</th> >- <th scope="col">Request type</th> >+ <th scope="col" data-datatype="related-object" data-related="extended_attributes" data-related-key="type" data-related-value="author" data-related-search-on="value">Author</th> >+ <th scope="col" data-datatype="related-object" data-related="extended_attributes" data-related-key="type" data-related-value="title" data-related-search-on="value">Title</th> >+ <th scope="col" data-datatype="related-object" data-related="extended_attributes" data-related-key="type" data-related-value="article_title" data-related-search-on="value">Article title</th> >+ <th scope="col" data-datatype="related-object" data-related="extended_attributes" data-related-key="type" data-related-value="issue" data-related-search-on="value">Issue</th> >+ <th scope="col" data-datatype="related-object" data-related="extended_attributes" data-related-key="type" data-related-value="volume" data-related-search-on="value">Volume</th> >+ <th scope="col" data-datatype="related-object" data-related="extended_attributes" data-related-key="type" data-related-value="year" data-related-search-on="value">Year</th> >+ <th scope="col" data-datatype="related-object" data-related="extended_attributes" data-related-key="type" data-related-value="pages" data-related-search-on="value">Pages</th> >+ <th scope="col" data-datatype="related-object" data-related="extended_attributes" data-related-key="type" data-related-value="type" data-related-search-on="value">Request type</th> > <th scope="col">Order ID</th> > <th scope="col">Patron</th> > <th scope="col">Bibliographic record ID</th> > <th scope="col">Library</th> > <th scope="col">Status</th> >- <th scope="col" class="placed"> </th> > <th scope="col" class="placed_formatted">Placed on</th> >- <th scope="col" class="updated"> </th> > <th scope="col" class="updated_formatted">Updated on</th> > <th scope="col">Replied</th> >- <th scope="col" class="completed"> </th> > <th scope="col" class="completed_formatted">Completed on</th> > <th scope="col">Access URL</th> > <th scope="col">Cost</th> >@@ -38,4 +31,4 @@ > </thead> > <tbody id="illview-body"> > </tbody> >-</table> >+</table> >\ No newline at end of file >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/js-biblio-format.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/js-biblio-format.inc >index f953337856..c06002600f 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/js-biblio-format.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/js-biblio-format.inc >@@ -13,17 +13,24 @@ > return ''; // empty string for no biblio > } > >- var title = '<span class="biblio-title">'; >- if (biblio.title != null && biblio.title != '') { >- title += escape_str(biblio.title); >- } else { >- title += __("No title"); >+ var title = ''; >+ >+ if ( config && config.biblio_id_only ) { >+ title = escape_str(biblio.biblio_id); > } >- title += '</span>'; >+ else { >+ title = '<span class="biblio-title">'; >+ if (biblio.title != null && biblio.title != '') { >+ title += escape_str(biblio.title); >+ } else { >+ title += __("No title"); >+ } >+ title += '</span>'; > >- // add subtitle >- if (biblio.subtitle != null && biblio.subtitle != '') { >- title += ' <span class="biblio-subtitle">' + escape_str(biblio.subtitle) + '</span>'; >+ // add subtitle >+ if (biblio.subtitle != null && biblio.subtitle != '') { >+ title += ' <span class="biblio-subtitle">' + escape_str(biblio.subtitle) + '</span>'; >+ } > } > > // set title as link >@@ -39,23 +46,25 @@ > } > } > >- // add medium >- if (biblio.medium != null && biblio.medium != '') { >- title += ' <span class="biblio-medium">' + escape_str(biblio.medium) + '</span>'; >- } >- >- // add part numbers/names >- let part_numbers = (typeof biblio.part_number === 'string') ? biblio.part_number.split("|") : []; >- let part_names = (typeof biblio.part_name === 'string') ? biblio.part_name.split("|") : []; >- let i = 0; >- while (part_numbers[i] || part_names[i]) { >- if (part_numbers[i]) { >- title += ' <span class="part-number">' + escape_str(part_numbers[i]) + '</span>'; >+ if ( !config || !config.biblio_id_only ) { >+ // add medium >+ if (biblio.medium != null && biblio.medium != '') { >+ title += ' <span class="biblio-medium">' + escape_str(biblio.medium) + '</span>'; > } >- if (part_names[i]) { >- title += ' <span class="part-name">' + escape_str(part_names[i]) + '</span>'; >+ >+ // add part numbers/names >+ let part_numbers = (typeof biblio.part_number === 'string') ? biblio.part_number.split("|") : []; >+ let part_names = (typeof biblio.part_name === 'string') ? biblio.part_name.split("|") : []; >+ let i = 0; >+ while (part_numbers[i] || part_names[i]) { >+ if (part_numbers[i]) { >+ title += ' <span class="part-number">' + escape_str(part_numbers[i]) + '</span>'; >+ } >+ if (part_names[i]) { >+ title += ' <span class="part-name">' + escape_str(part_names[i]) + '</span>'; >+ } >+ i++; > } >- i++; > } > > return title; >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 23c6c33f12..261fa61096 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 >@@ -68,10 +68,15 @@ > <label for="illfilter_keyword">Keyword:</label> > <input type="text" name="illfilter_keyword" id="illfilter_keyword" /> > </li> >+ <li> >+ <label for="illfilter_backend">Backend:</label> >+ <select name="illfilter_backend" id="illfilter_backend"> >+ <option value="">All backends</option> >+ </select> >+ </li> > <li> > <label for="illfilter_status">Status:</label> > <select name="illfilter_status" id="illfilter_status"> >- <option value=""></option> > </select> > </li> > <li> >@@ -93,7 +98,8 @@ > <li> > <label for="illfilter_branchname">Library:</label> > <select name="illfilter_branchname" id="illfilter_branchname"> >- <option value=""></option> >+ <option value="">All libraries</option> >+ [% PROCESS options_for_libraries libraries => Branches.all( selected => userbranch, only_from_group => 1 ) %] > </select> > </li> > <li> >@@ -150,7 +156,7 @@ > [% IF !whole.stage || whole.stage == 'form' %] > <h1 id="ill-issue-title">Issue requested item to [% INCLUDE 'patron-title.inc' patron = request.patron %]</h1> > [% IF !request.biblio_id || request.biblio_id.length == 0 %] >- <div class="alert">This item cannot be checked out out as there is no bibliographic record associated with it</div> >+ <div class="alert">This item cannot be issued as it has no biblio record associated with it</div> > [% END %] > [% IF whole.value.errors.itemcount %] > <div class="alert">The bibliographic record for this request has multiple items, it should only have one. Please fix this then try again.</div> >@@ -599,15 +605,16 @@ > <span class="fa fa-eye"></span> > Display supplier metadata > </a> >- [% IF Koha.Preference('IllLog') %] >- <a title="ILL request log" id="ill-request-display-log" class="btn btn-default pull-right" href="#"> >- <span class="fa fa-calendar"></span> >- ILL request log >- </a> >- [% END %] >+ <a title="ILL request log" id="ill-request-display-log" class="btn btn-default pull-right" href="#"> >+ <span class="fa fa-calendar"></span> >+ ILL request log >+ </a> > </div> >- <div class="page-section"> >- <h3>Request details</h3> >+ <div class="ill-view-panel panel panel-default"> >+ <div class="panel-heading"> >+ <h3>Request details</h3> >+ </div> >+ <div class="panel-body"> > <h4>Details from library</h4> > <div class="rows"> > <ol> >@@ -618,7 +625,7 @@ > <li class="borrowernumber"> > <span class="label borrowernumber">Patron:</span> > [% borrowerlink = "/cgi-bin/koha/members/moremember.pl" _ "?borrowernumber=" _ request.patron.borrowernumber %] >- <a href="[% borrowerlink | url %]" title="View patron details"> >+ <a href="[% borrowerlink | url %]" title="View borrower details"> > [% request.patron.firstname _ " " _ request.patron.surname _ " [" _ request.patron.cardnumber _ "]" | html %] > </a> > </li> >@@ -664,7 +671,7 @@ > [% IF request.price_paid %][% request.price_paid | $Price %][% ELSE %]<span>N/A</span>[% END %] > </li> > <li class="req_id"> >- <span class="label req_id">Request ID:</span> >+ <span class="label req_id">Request number:</span> > [% request.id_prefix _ request.illrequest_id | html %] > </li> > <li class="notesstaff"> >@@ -672,7 +679,7 @@ > <p>[% request.notesstaff | html %]</p> > </li> > <li class="notesopac"> >- <span class="label notes_opac">OPAC notes:</span> >+ <span class="label notes_opac">Notes:</span> > <p>[% request.notesopac | html %]</p> > </li> > </ol> >@@ -688,6 +695,7 @@ > [% END %] > </ol> > </div> >+ </div> > </div> > > <div id="dataPreview" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="dataPreviewLabel" aria-hidden="true"> >@@ -738,40 +746,44 @@ > </div> > </div> > >- <div class="page-section"> >- <h3>[% request.illcomments.count | html %] comments</h3> >- [% IF request.illcomments.count && request.illcomments.count > 0 %] >- [% FOREACH comment IN request.illcomments %] >- <div class="rows comment_[% comment.patron.categorycode | html %]"> >- <h5>Comment by: >- <a href="[% borrowerlink | url %]" title="View patron details"> >- [% comment.patron.firstname _ " " _ comment.patron.surname _ " [" _ comment.patron.cardnumber _ "]" | html %]</a> >- [% comment.timestamp | $KohaDates with_hours => 1 %]</h5> >- <p>[% comment.comment | html %]</p> >- </div> >+ <div class="ill-view-panel panel panel-default"> >+ <div class="panel-heading"> >+ <h3>[% request.illcomments.count | html %] comments</h3> >+ </div> >+ <div class="panel-body"> >+ [% IF request.illcomments.count && request.illcomments.count > 0 %] >+ [% FOREACH comment IN request.illcomments %] >+ <div class="rows comment_[% comment.patron.categorycode | html %]"> >+ <h5>Comment by: >+ <a href="[% borrowerlink | url %]" title="View borrower details"> >+ [% comment.patron.firstname _ " " _ comment.patron.surname _ " [" _ comment.patron.cardnumber _ "]" | html %]</a> >+ [% comment.timestamp | $KohaDates with_hours => 1 %]</h5> >+ <p>[% comment.comment | html %]</p> >+ </div> >+ [% END %] > [% END %] >- [% END %] >- <div class="rows"> >- <h3><a id="toggle_addcomment" href="#">Add comment</a></h3> >- <div id="addcomment" class="content_hidden"> >- <form class="validated" method="post" action="/cgi-bin/koha/ill/ill-requests.pl"> >- <input type="hidden" value="save_comment" name="method"> >- <input type="hidden" value="[% csrf_token | html %]" name="csrf_token"> >- <input type="hidden" value="[% request.illrequest_id | html %]" name="illrequest_id"> >- <fieldset class="rows"> >- <ol> >- <li> >- <label class="required" for="comment">Comment: </label> >- <textarea class="required" required="required" cols="80" rows="10" id="comment" name="comment"></textarea> >- <span class="required">Required</span> >- </li> >- </ol> >- </fieldset> >- <fieldset class="action"> >- <input type="submit" class="btn btn-primary" value="Submit" /> >- </fieldset> >- </form> >- </div> >+ <div class="rows"> >+ <h3><a id="toggle_addcomment" href="#">Add comment</a></h3> >+ <div id="addcomment" class="content_hidden"> >+ <form class="validated" method="post" action="/cgi-bin/koha/ill/ill-requests.pl"> >+ <input type="hidden" value="save_comment" name="method"> >+ <input type="hidden" value="[% csrf_token | html %]" name="csrf_token"> >+ <input type="hidden" value="[% request.illrequest_id | html %]" name="illrequest_id"> >+ <fieldset class="rows"> >+ <ol> >+ <li> >+ <label class="required" for="comment">Comment: </label> >+ <textarea class="required" required="required" cols="80" rows="10" id="comment" name="comment"></textarea> >+ <span class="required">Required</span> >+ </li> >+ </ol> >+ </fieldset> >+ <fieldset class="action"> >+ <input type="submit" class="btn btn-primary" value="Submit" /> >+ </fieldset> >+ </form> >+ </div> >+ </div> > </div> > </div> > >@@ -780,12 +792,12 @@ > <h1>View ILL requests</h1> > <div id="results" class="page-section"> > <h2>Details for all requests</h2> >- [% INCLUDE 'ill-list-table.inc' %] >+ [% INCLUDE 'ill-list-table.inc' %] > </div> <!-- /#results --> > [% ELSIF query_type == 'availability' %] > <!-- availability --> > <h1>Availability</h1> >- <div id="results" class="page-section"> >+ <div id="results"> > <h3>Displaying availability results</h3> > <form method="POST" action="/cgi-bin/koha/ill/ill-requests.pl"> > [% FOREACH key IN whole.keys %] >@@ -830,6 +842,8 @@ > > [% MACRO jsinclude BLOCK %] > [% INCLUDE 'datatables.inc' %] >+ [% INCLUDE 'js-biblio-format.inc' %] >+ [% INCLUDE 'js-patron-format.inc' %] > [% INCLUDE 'columns_settings.inc' %] > [% INCLUDE 'calendar.inc' %] > [% INCLUDE 'select2.inc' %] >@@ -871,6 +885,7 @@ > [% IF query_type == 'generic_confirm' && Koha.Preference('ILLCheckAvailability') %] > [% Asset.js("js/ill-availability-partner.js") | $raw %] > [% END %] >+ > [% END %] > > [% TRY %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/ill-requests.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/ill-requests.tt >index d3465cfaa2..4b7c30fb9e 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/ill-requests.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/ill-requests.tt >@@ -56,6 +56,8 @@ > [% Asset.js("js/members-menu.js") | $raw %] > [% INCLUDE 'datatables.inc' %] > [% INCLUDE 'columns_settings.inc' %] >+ [% INCLUDE 'js-biblio-format.inc' %] >+ [% INCLUDE 'js-patron-format.inc' %] > [% INCLUDE 'calendar.inc' %] > <script> > var prefilters = '[% prefilters | html %]'; >diff --git a/koha-tmpl/intranet-tmpl/prog/js/datatables.js b/koha-tmpl/intranet-tmpl/prog/js/datatables.js >index bcf308c56c..d6f840680f 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/datatables.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/datatables.js >@@ -560,9 +560,43 @@ function _dt_default_ajax (params){ > // escape SQL LIKE special characters % > value = value.replace(/(\%|\\)/g, "\\$1"); > } >- part[!attr.includes('.')?'me.'+attr:attr] = criteria === 'exact' >- ? value >- : {like: (['contains', 'ends_with'].indexOf(criteria) !== -1?'%':'') + value + (['contains', 'starts_with'].indexOf(criteria) !== -1?'%':'')}; >+ >+ let built_value; >+ if ( col.datatype !== undefined ) { >+ if ( col.datatype == 'date' ) { >+ let rfc3339 = $date_to_rfc3339(value); >+ if ( rfc3339 != 'Invalid Date' ) { >+ built_value = rfc3339; >+ } >+ } >+ else if (col.datatype == 'related-object') { >+ let query_term = value; >+ >+ if (criteria != 'exact') { >+ query_term = { like: (['contains', 'ends_with'].indexOf(criteria) !== -1 ? '%' : '') + value + (['contains', 'starts_with'].indexOf(criteria) !== -1 ? '%' : '') }; >+ } >+ >+ part = { >+ [col.related + '.' + col.relatedKey]: col.relatedValue, >+ [col.related + '.' + col.relatedSearchOn]: query_term >+ }; >+ } else { >+ console.log("datatype %s not supported yet".format(col.datatype)); >+ } >+ } >+ >+ if (col.datatype != 'related-object') { >+ let value_part; >+ if ( criteria === 'exact' ) { >+ value_part = built_value ? [value, built_value] : value >+ } else { >+ let like = {like: (['contains', 'ends_with'].indexOf(criteria) !== -1?'%':'') + value + (['contains', 'starts_with'].indexOf(criteria) !== -1?'%':'')}; >+ value_part = built_value ? [like, built_value] : like; >+ } >+ >+ part[!attr.includes('.')?'me.'+attr:attr] = value_part; >+ } >+ > parts.push(part); > } > return parts; >diff --git a/koha-tmpl/intranet-tmpl/prog/js/ill-list-table.js b/koha-tmpl/intranet-tmpl/prog/js/ill-list-table.js >index d6e92cc517..9b914cf728 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/ill-list-table.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/ill-list-table.js >@@ -1,322 +1,4 @@ > $(document).ready(function() { >- >- // Illview Datatable setup >- >- var table; >- >- // Filters that are active >- var activeFilters = {}; >- >- // Get any prefilters >- var prefilters = $('table#ill-requests').data('prefilters'); >- >- // Fields we need to expand (flatten) >- var expand = [ >- 'metadata', >- 'patron', >- 'library' >- ]; >- >- // Expanded fields >- // This is auto populated >- var expanded = {}; >- >- // Filterable columns >- var filterable = { >- status: { >- prep: function(tableData, oData) { >- var uniques = {}; >- tableData.forEach(function(row) { >- var resolvedName; >- if (row.status_alias) { >- resolvedName = row.status_alias.lib; >- } else { >- resolvedName = getStatusName( >- row.capabilities[row.status].name, >- row >- ); >- } >- 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.api().column(13).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.api().column(12).search(sel); >- } >- } else { >- if (activeFilters.hasOwnProperty(me)) { >- delete activeFilters[me]; >- } >- } >- }); >- }, >- clear: function() { >- $('#illfilter_branchname').val(''); >- } >- }, >- patron: { >- listener: function() { >- var me = 'patron'; >- $('#illfilter_patron').change(function() { >- var val = $('#illfilter_patron').val(); >- if (val && val.length > 0) { >- activeFilters[me] = function() { >- table.api().column(10).search(val); >- } >- } else { >- if (activeFilters.hasOwnProperty(me)) { >- delete activeFilters[me]; >- } >- } >- }); >- }, >- clear: function() { >- $('#illfilter_patron').val(''); >- } >- }, >- keyword: { >- listener: function () { >- var me = 'keyword'; >- $('#illfilter_keyword').change(function () { >- var val = $('#illfilter_keyword').val(); >- if (val && val.length > 0) { >- activeFilters[me] = function () { >- table.api().search(val); >- } >- } else { >- if (activeFilters.hasOwnProperty(me)) { >- delete activeFilters[me]; >- } >- } >- }); >- }, >- clear: function () { >- $('#illfilter_keyword').val(''); >- } >- }, >- dateModified: { >- clear: function() { >- $('#illfilter_datemodified_start, #illfilter_datemodified_end').val(''); >- } >- }, >- datePlaced: { >- clear: function() { >- $('#illfilter_dateplaced_start, #illfilter_dateplaced_end').val(''); >- } >- } >- }; //END Filterable columns >- >- // Expand any fields we're expanding >- var expandExpand = function(row) { >- expand.forEach(function(thisExpand) { >- if (row.hasOwnProperty(thisExpand)) { >- if (!expanded.hasOwnProperty(thisExpand)) { >- expanded[thisExpand] = []; >- } >- var expandObj = row[thisExpand]; >- Object.keys(expandObj).forEach( >- function(thisExpandCol) { >- var expColName = thisExpand + '_' + thisExpandCol.replace(/\s/g,'_'); >- // Keep a list of fields that have been expanded >- // so we can create toggle links for them >- if (expanded[thisExpand].indexOf(expColName) == -1) { >- expanded[thisExpand].push(expColName); >- } >- expandObj[expColName] = >- expandObj[thisExpandCol]; >- delete expandObj[thisExpandCol]; >- } >- ); >- $.extend(true, row, expandObj); >- delete row[thisExpand]; >- } >- }); >- }; >- //END Expand >- >- // Strip the expand prefix if it exists, we do this for display >- var stripPrefix = function(value) { >- expand.forEach(function(thisExpand) { >- var regex = new RegExp(thisExpand + '_', 'g'); >- value = value.replace(regex, ''); >- }); >- return value; >- }; >- >- // Our 'render' function for borrowerlink >- var createPatronLink = function(data, type, row) { >- var patronLink = '<a title="' + ill_borrower_details + '" ' + >- 'href="/cgi-bin/koha/members/moremember.pl?' + >- 'borrowernumber='+row.borrowernumber+'">'; >- if ( row.patron_firstname ) { >- patronLink = patronLink + row.patron_firstname + ' '; >- } >- patronLink = patronLink + row.patron_surname + >- ' (' + row.patron_cardnumber + ')' + '</a>'; >- return patronLink; >- }; >- >- // Our 'render' function for biblio_id >- var createBiblioLink = function(data, type, row) { >- return (row.biblio_id) ? >- '<a title="' + ill_biblio_details + '" ' + >- 'href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=' + >- row.biblio_id + '">' + >- row.biblio_id + >- '</a>' : ''; >- }; >- >- // Our 'render' function for title >- var createTitle = function(data, type, row) { >- return ( >- row.hasOwnProperty('metadata_container_title') && >- row.metadata_container_title >- ) ? row.metadata_container_title : row.metadata_title; >- }; >- >- // Render function for request ID >- var createRequestId = function(data, type, row) { >- return row.id_prefix + row.illrequest_id; >- }; >- >- // Render function for type >- var createType = function(data, type, row) { >- if (!row.hasOwnProperty('metadata_Type') || !row.metadata_Type) { >- if (row.hasOwnProperty('medium') && row.medium) { >- row.metadata_Type = row.medium; >- } else { >- row.metadata_Type = null; >- } >- } >- return row.metadata_Type; >- }; >- >- // Render function for request status >- var createStatus = function(data, type, row, meta) { >- if (row.status_alias) { >- return row.status_alias.lib >- ? row.status_alias.lib >- : row.status_alias.authorised_value; >- } else { >- var status_name = row.capabilities[row.status].name; >- return getStatusName(status_name, row); >- } >- }; >- >- var getStatusName = function(origName, row) { >- switch( origName ) { >- case "New request": >- return ill_statuses.new; >- case "Requested": >- return ill_statuses.req; >- case "Requested from partners": >- var statStr = ill_statuses.genreq; >- if ( >- row.hasOwnProperty('requested_partners') && >- row.requested_partners && >- row.requested_partners.length > 0 >- ) { >- statStr += ' (' + row.requested_partners + ')'; >- } >- return statStr; >- case "Request reverted": >- return ill_statuses.rev; >- case "Queued request": >- return ill_statuses.que; >- case "Cancellation requested": >- return ill_statuses.canc; >- case "Completed": >- return ill_statuses.comp; >- case "Delete request": >- return ill_statuses.del; >- 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" ' + >- 'href="/cgi-bin/koha/ill/ill-requests.pl?' + >- 'method=illview&illrequest_id=' + >- row.illrequest_id + >- '">' + ill_manage + '</a>'; >- }; >- >- // Columns that require special treatment >- var specialCols = { >- action: { >- func: createActionLink, >- skipSanitize: true >- }, >- illrequest_id: { >- func: createRequestId >- }, >- status: { >- func: createStatus >- }, >- biblio_id: { >- name: ill_columns.biblio_id, >- func: createBiblioLink, >- skipSanitize: true >- }, >- metadata_title: { >- func: createTitle >- }, >- metadata_Type: { >- func: createType >- }, >- updated: { >- name: ill_columns.updated >- }, >- patron: { >- skipSanitize: true, >- func: createPatronLink >- } >- }; >- > // Display the modal containing request supplier metadata > $('#ill-request-display-log').on('click', function(e) { > e.preventDefault(); >@@ -360,200 +42,449 @@ $(document).ready(function() { > $('#dataPreview').modal({show:true}); > }); > >- // Allow us to chain Datatable render helpers together, so we >- // can use our custom functions and render.text(), which >- // provides us with data sanitization >- $.fn.dataTable.render.multi = function(renderArray) { >- return function(d, type, row, meta) { >- for(var r = 0; r < renderArray.length; r++) { >- var toCall = renderArray[r].hasOwnProperty('display') ? >- renderArray[r].display : >- renderArray[r]; >- d = toCall(d, type, row, meta); >- } >- return d; >+ function display_extended_attribute(row, type) { >+ var arr = $.grep(row.extended_attributes, ( x => x.type === type )); >+ if (arr.length > 0) { >+ return escape_str(arr[0].value); > } >+ >+ return ''; > } > >- // Get our data from the API and process it prior to passing >- // it to datatables >- var filterParam = prefilters ? '&' + prefilters : ''; >- // Only fire the request if we're on an appropriate page >- if ( >- ( >- // ILL list requests page >- window.location.href.match(/ill\/ill-requests\.pl/) && >- window.location.search.length == 0 >- ) || >- // Patron profile page >- window.location.href.match(/members\/ill-requests\.pl/) >- ) { >- var ajax = $.ajax( >- '/api/v1/illrequests?embed=metadata,patron,capabilities,library,status_alias,comments,requested_partners' >- + filterParam >- ).done(function() { >- var data = JSON.parse(ajax.responseText); >- // Make a copy, we'll be removing columns next and need >- // to be able to refer to data that has been removed >- var dataCopy = $.extend(true, [], data); >- // Expand columns that need it and create an array >- // of all column names >- $.each(dataCopy, function(k, row) { >- expandExpand(row); >+ // At the moment, the only prefilter possible is borrowernumber >+ // see ill/ill-requests.pl and members/ill-requests.pl >+ let additional_prefilters = []; >+ if(prefilters){ >+ let prefilters_array = prefilters.split("&"); >+ prefilters_array.forEach((prefilter) => { >+ let prefilter_split = prefilter.split("="); >+ additional_prefilters.push( { >+ "key": prefilter_split[0], >+ "value": prefilter_split[1] >+ } ); >+ > }); >+ } > >- // Assemble an array of column definitions for passing >- // to datatables >- var colData = []; >- var columns = table_settings['columns']; >- columns.forEach(function(thisCol) { >- var colName = thisCol.columnname; >- // Create the base column object >- var colObj = $.extend({}, thisCol); >- colObj.name = colName; >- colObj.className = colName; >- colObj.defaultContent = ''; >- >- // We may need to process the data going in this >- // column, so do it if necessary >- if ( >- specialCols.hasOwnProperty(colName) && >- specialCols[colName].hasOwnProperty('func') >- ) { >- var renderArray = [ >- specialCols[colName].func >- ]; >- if (!specialCols[colName].skipSanitize) { >- renderArray.push( >- $.fn.dataTable.render.text() >- ); >+ let additional_filters = { >+ "me.backend": function(){ >+ let backend = $("#illfilter_backend").val(); >+ if (!backend) return ""; >+ return { "=": backend } >+ }, >+ "me.branchcode": function(){ >+ let branchcode = $("#illfilter_branchname").val(); >+ if (!branchcode) return ""; >+ return { "=": branchcode } >+ }, >+ "me.borrowernumber": function(){ >+ let borrowernumber_pre_filter = additional_prefilters.find(e => e.key === 'borrowernumber'); >+ if ( additional_prefilters.length == 0 || typeof borrowernumber_pre_filter === undefined) return ""; >+ return { "=": borrowernumber_pre_filter["value"] } >+ }, >+ "-or": function(){ >+ let patron = $("#illfilter_patron").val(); >+ let status = $("#illfilter_status").val(); >+ let filters = []; >+ let patron_sub_or = []; >+ let status_sub_or = []; >+ let subquery_and = []; >+ >+ if (!patron && !status) return ""; >+ >+ if(patron){ >+ const patron_search_fields = "me.borrowernumber,patron.cardnumber,patron.firstname,patron.surname"; >+ patron_search_fields.split(',').forEach(function(attr){ >+ let operator = "="; >+ let patron_data = patron; >+ if ( attr != "me.borrowernumber" && attr != "patron.cardnumber") { >+ operator = "like"; >+ patron_data = "%" + patron + "%"; > } >+ patron_sub_or.push({ >+ [attr]:{[operator]: patron_data } >+ }); >+ }); >+ subquery_and.push(patron_sub_or); >+ } > >- colObj.render = $.fn.dataTable.render.multi( >- renderArray >- ); >- } else { >- colObj.data = colName; >- colObj.render = $.fn.dataTable.render.text() >- } >- // Make sure properties that aren't present in the API >- // response are populated with null to avoid Datatables >- // choking on their absence >- dataCopy.forEach(function(thisData) { >- if (!thisData.hasOwnProperty(colName)) { >- thisData[colName] = null; >- } >+ if(status){ >+ const status_search_fields = "me.status,me.status_av"; >+ status_search_fields.split(',').forEach(function(attr){ >+ status_sub_or.push({ >+ [attr]:{"=": status } >+ }); >+ }); >+ subquery_and.push(status_sub_or); >+ } >+ >+ filters.push({"-and": subquery_and}); >+ >+ return filters; >+ }, >+ "me.placed": function(){ >+ if ( additional_prefilters.length != 0 && !additional_prefilters.find(e => e.key === 'placed')) return ""; >+ let placed_start = $('#illfilter_dateplaced_start').get(0)._flatpickr.selectedDates[0]; >+ let placed_end = $('#illfilter_dateplaced_end').get(0)._flatpickr.selectedDates[0]; >+ if (!placed_start && !placed_end) return ""; >+ return { >+ ...(placed_start && {">=": placed_start}), >+ ...(placed_end && {"<=": placed_end}) >+ } >+ }, >+ "me.updated": function(){ >+ if ( additional_prefilters.length != 0 && !additional_prefilters.find(e => e.key === 'updated')) return ""; >+ let updated_start = $('#illfilter_datemodified_start').get(0)._flatpickr.selectedDates[0]; >+ let updated_end = $('#illfilter_datemodified_end').get(0)._flatpickr.selectedDates[0]; >+ if (!updated_start && !updated_end) return ""; >+ // set selected datetime hours and minutes to the end of the day >+ // to grab any request updated during that day >+ let updated_end_value = new Date(updated_end); >+ updated_end_value.setHours(updated_end_value.getHours()+23); >+ updated_end_value.setMinutes(updated_end_value.getMinutes()+59); >+ return { >+ ...(updated_start && {">=": updated_start}), >+ ...(updated_end && {"<=": updated_end_value}) >+ } >+ }, >+ "-and": function(){ >+ let keyword = $("#illfilter_keyword").val(); >+ if (!keyword) return ""; >+ >+ let filters = []; >+ let subquery_and = []; >+ >+ const search_fields = "me.illrequest_id,me.borrowernumber,me.biblio_id,me.due_date,me.branchcode,library.name,me.status,me.status_alias,me.placed,me.replied,me.updated,me.completed,me.medium,me.accessurl,me.cost,me.price_paid,me.notesopac,me.notesstaff,me.orderid,me.backend,patron.firstname,patron.surname"; >+ let sub_or = []; >+ search_fields.split(',').forEach(function(attr){ >+ sub_or.push({ >+ [attr]:{"like":"%" + keyword + "%"} > }); >- colData.push(colObj); > }); >+ subquery_and.push(sub_or); >+ filters.push({"-and": subquery_and}); >+ >+ const extended_attributes = "title,type,author,article_title,pages,issue,volume,year"; >+ let extended_sub_or = []; >+ subquery_and = []; >+ extended_sub_or.push({ >+ "extended_attributes.type": extended_attributes.split(','), >+ "extended_attributes.value":{"like":"%" + keyword + "%"} >+ }); >+ subquery_and.push(extended_sub_or); > >- // Initialise the datatable >- table = KohaTable("ill-requests", { >- 'aoColumnDefs': [ >- { // Last column shouldn't be sortable or searchable >- 'aTargets': [ 'actions' ], >- 'bSortable': false, >- 'bSearchable': false >- }, >- { // When sorting 'placed', we want to use the >- // unformatted column >- 'aTargets': [ 'placed_formatted'], >- 'iDataSort': 14 >- }, >- { // When sorting 'updated', we want to use the >- // unformatted column >- 'aTargets': [ 'updated_formatted'], >- 'iDataSort': 16 >- }, >- { // When sorting 'completed', we want to use the >- // unformatted column >- 'aTargets': [ 'completed_formatted'], >- 'iDataSort': 19 >- } >- ], >- 'aaSorting': [[ 16, 'desc' ]], // Default sort, updated descending >- 'processing': true, // Display a message when manipulating >- 'sPaginationType': "full_numbers", // Pagination display >- 'deferRender': true, // Improve performance on big datasets >- 'data': dataCopy, >- "dom": '<"top pager"<"table_entries"ilp><"table_controls"B>>tr<"bottom pager"ip>', >- 'columns': colData, >- '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(); >- } >- } >- } >+ filters.push({"-and": subquery_and}); >+ return filters; >+ } >+ }; > >+ var ill_requests_table = $("#ill-requests").kohaTable({ >+ "ajax": { >+ "url": '/api/v1/ill_requests' >+ }, >+ "embed": [ >+ '+strings', >+ 'biblio', >+ 'comments+count', >+ 'extended_attributes', >+ 'library', >+ 'id_prefix', >+ 'patron' >+ ], >+ "stateSave": true, // remember state on page reload >+ "columns": [ >+ { >+ "data": "ill_request_id", >+ "searchable": true, >+ "orderable": true, >+ "render": function( data, type, row, meta ) { >+ return '<a href="/cgi-bin/koha/ill/ill-requests.pl?' + >+ 'method=illview&illrequest_id=' + >+ encodeURIComponent(data) + >+ '">' + escape_str(row.id_prefix) + escape_str(data) + '</a>'; >+ } >+ }, >+ { >+ "data": "", // author >+ "orderable": false, >+ "render": function(data, type, row, meta) { >+ return display_extended_attribute(row, 'author'); >+ } >+ }, >+ { >+ "data": "", // title >+ "orderable": false, >+ "render": function(data, type, row, meta) { >+ return display_extended_attribute(row, 'title'); >+ } >+ }, >+ { >+ "data": "", // article_title >+ "orderable": false, >+ "render": function(data, type, row, meta) { >+ return display_extended_attribute(row, 'article_title'); >+ } >+ }, >+ { >+ "data": "", // issue >+ "orderable": false, >+ "render": function(data, type, row, meta) { >+ return display_extended_attribute(row, 'issue'); >+ } >+ }, >+ { >+ "data": "", // volume >+ "orderable": false, >+ "render": function(data, type, row, meta) { >+ return display_extended_attribute(row, 'volume'); >+ } >+ }, >+ { >+ "data": "", // year >+ "orderable": false, >+ "render": function(data, type, row, meta) { >+ return display_extended_attribute(row, 'year'); >+ } >+ }, >+ { >+ "data": "", // pages >+ "orderable": false, >+ "render": function(data, type, row, meta) { >+ return display_extended_attribute(row, 'pages'); >+ } >+ }, >+ { >+ "data": "", // type >+ "orderable": false, >+ "render": function(data, type, row, meta) { >+ return display_extended_attribute(row, 'type'); >+ } >+ }, >+ { >+ "data": "ill_backend_request_id", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ return escape_str(data); > } >- }, table_settings); >- >- // Custom date range filtering >- $.fn.dataTable.ext.search.push(function(settings, data, dataIndex) { >- var placedStart = $('#illfilter_dateplaced_start').get(0)._flatpickr.selectedDates[0]; >- var placedEnd = $('#illfilter_dateplaced_end').get(0)._flatpickr.selectedDates[0]; >- var modifiedStart = $('#illfilter_datemodified_start').get(0)._flatpickr.selectedDates[0]; >- var modifiedEnd = $('#illfilter_datemodified_end').get(0)._flatpickr.selectedDates[0]; >- var rowPlaced = data[14] ? new Date(data[14]) : null; >- var rowModified = data[16] ? new Date(data[16]) : null; >- var placedPassed = true; >- var modifiedPassed = true; >- if (placedStart && rowPlaced && rowPlaced < placedStart) { >- placedPassed = false >- }; >- if (placedEnd && rowPlaced && rowPlaced > placedEnd) { >- placedPassed = false; >+ }, >+ { >+ "data": "patron.firstname:patron.surname:patron.cardnumber", >+ "render": function(data, type, row, meta) { >+ return (row.patron) ? $patron_to_html( row.patron, { display_cardnumber: true, url: true } ) : ''; } }, >+ { >+ "data": "biblio_id", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ if ( data === null ) { >+ return ""; >+ } >+ return $biblio_to_html(row.biblio, { biblio_id_only: 1, link: 1 }); > } >- if (modifiedStart && rowModified && rowModified < modifiedStart) { >- modifiedPassed = false >- }; >- if (modifiedEnd && rowModified && rowModified > modifiedEnd) { >- modifiedPassed = false; >+ }, >+ { >+ "data": "library.name", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ return escape_str(data); > } >+ }, >+ { >+ "data": "status", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ let status_label = row._strings.status_av ? >+ row._strings.status_av.str ? >+ row._strings.status_av.str : >+ row._strings.status_av.code : >+ row._strings.status.str >+ return escape_str(status_label); >+ } >+ }, >+ { >+ "data": "requested_date", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ return $date(data); >+ } >+ }, >+ { >+ "data": "timestamp", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ return $date(data); >+ } >+ }, >+ { >+ "data": "replied_date", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ return $date(data); >+ } >+ }, >+ { >+ "data": "completed_date", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ return $date(data); >+ } >+ }, >+ { >+ "data": "access_url", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ return escape_str(data); >+ } >+ }, >+ { >+ "data": "cost", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ return escape_str(data); >+ } >+ }, >+ { >+ "data": "paid_price", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ return escape_str(data); >+ } >+ }, >+ { >+ "data": "comments_count", >+ "orderable": true, >+ "searchable": false, >+ "render": function(data, type, row, meta) { >+ return escape_str(data); >+ } >+ }, >+ { >+ "data": "opac_notes", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ return escape_str(data); >+ } >+ }, >+ { >+ "data": "staff_notes", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ return escape_str(data); >+ } >+ }, >+ { >+ "data": "ill_backend_id", >+ "orderable": true, >+ "render": function(data, type, row, meta) { >+ return escape_str(data); >+ } >+ }, >+ { >+ "data": "ill_request_id", >+ "orderable": false, >+ "searchable": false, >+ "render": function( data, type, row, meta ) { >+ return '<a class="btn btn-default btn-sm" ' + >+ 'href="/cgi-bin/koha/ill/ill-requests.pl?' + >+ 'method=illview&illrequest_id=' + >+ encodeURIComponent(data) + >+ '">' + ill_manage + '</a>'; >+ } >+ } >+ ] >+ }, table_settings, null, additional_filters); > >- return placedPassed && modifiedPassed; >+ $("#illfilter_form").on('submit', filter); > >- }); >+ function redrawTable() { >+ let table_dt = ill_requests_table.DataTable(); >+ table_dt.draw(); >+ } > >+ function filter() { >+ redrawTable(); >+ return false; >+ } >+ >+ function clearSearch() { >+ let filters = [ >+ "illfilter_backend", >+ "illfilter_branchname", >+ "illfilter_patron", >+ "illfilter_keyword", >+ ]; >+ filters.forEach((filter) => { >+ $("#"+filter).val(""); > }); >- } //END if window.location.search.length == 0 > >- var clearSearch = function() { >- table.api().search('').columns().search(''); >- activeFilters = {}; >- for (var filter in filterable) { >- if ( >- filterable.hasOwnProperty(filter) && >- filterable[filter].hasOwnProperty('clear') >- ) { >- filterable[filter].clear(); >+ //Clear flatpickr date filters >+ $('#illfilter_form > fieldset > ol > li:nth-child(4) > span > a').click(); >+ $('#illfilter_form > fieldset > ol > li:nth-child(5) > span > a').click(); >+ $('#illfilter_form > fieldset > ol > li:nth-child(6) > span > a').click(); >+ $('#illfilter_form > fieldset > ol > li:nth-child(7) > span > a').click(); >+ >+ disableStatusFilter(); >+ >+ redrawTable(); >+ } >+ >+ function populateStatusFilter(backend) { >+ $.ajax({ >+ type: "GET", >+ url: "/api/v1/ill_backends/"+backend+"/statuses", >+ success: function(statuses){ >+ $('#illfilter_status').append( >+ '<option value="">'+ill_all_statuses+'</option>' >+ ); >+ statuses.sort((a, b) => a.str.localeCompare(b.str)).forEach(function(status) { >+ $('#illfilter_status').append( >+ '<option value="' + status.code + >+ '">' + status.str + '</option>' >+ ); >+ }); > } >- } >- table.api().draw(); >- }; >+ }); >+ } > >- // Apply any search filters, or clear any previous >- // ones >- $('#illfilter_form').submit(function(event) { >- event.preventDefault(); >- table.api().search('').columns().search(''); >- for (var active in activeFilters) { >- if (activeFilters.hasOwnProperty(active)) { >- activeFilters[active](); >+ function populateBackendFilter() { >+ $.ajax({ >+ type: "GET", >+ url: "/api/v1/ill_backends", >+ success: function(backends){ >+ backends.sort((a, b) => a.ill_backend_id.localeCompare(b.ill_backend_id)).forEach(function(backend) { >+ $('#illfilter_backend').append( >+ '<option value="' + backend.ill_backend_id + >+ '">' + backend.ill_backend_id + '</option>' >+ ); >+ }); > } >+ }); >+ } >+ >+ function disableStatusFilter() { >+ $('#illfilter_status').children().remove(); >+ $("#illfilter_status").attr('title', ill_manage_select_backend_first); >+ $('#illfilter_status').prop("disabled", true); >+ } >+ >+ function enableStatusFilter() { >+ $('#illfilter_status').children().remove(); >+ $("#illfilter_status").attr('title', ''); >+ $('#illfilter_status').prop("disabled", false); >+ } >+ >+ $('#illfilter_backend').change(function() { >+ var selected_backend = $('#illfilter_backend option:selected').val(); >+ if (selected_backend && selected_backend.length > 0) { >+ populateStatusFilter(selected_backend); >+ enableStatusFilter(); >+ } else { >+ disableStatusFilter(); > } >- table.api().draw(); > }); > >+ disableStatusFilter(); >+ populateBackendFilter(); >+ > // Clear all filters > $('#clear_search').click(function() { > clearSearch(); >-- >2.40.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 22440
:
150715
|
150716
|
150717
|
150718
| 150719 |
150720
|
150721
|
150722
|
150723
|
150788
|
150789