Bugzilla – Attachment 78555 Details for
Bug 15219
Server-side processing and pagination on checkouts tables
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 15219: Server-side processing and pagination on checkouts tables
Bug-15219-Server-side-processing-and-pagination-on.patch (text/plain), 65.50 KB, created by
Julian Maurice
on 2018-09-11 15:19:57 UTC
(
hide
)
Description:
Bug 15219: Server-side processing and pagination on checkouts tables
Filename:
MIME Type:
Creator:
Julian Maurice
Created:
2018-09-11 15:19:57 UTC
Size:
65.50 KB
patch
obsolete
>From 053195c3f909dc457441fe3488ecc419be677a9b Mon Sep 17 00:00:00 2001 >From: Julian Maurice <julian.maurice@biblibre.com> >Date: Wed, 18 Nov 2015 15:52:14 +0100 >Subject: [PATCH] Bug 15219: Server-side processing and pagination on checkouts > tables > >Some libraries have patrons with more than 1000 checkouts. Loading all >of them at once can be very long, and sometimes can cause timeout >errors. >This patch prevent that by enabling server-side processing and >pagination on checkouts tables. >This affects patron's checkouts and patron's relatives' checkouts tables >on pages circ/circulation.pl and members/moremember.pl. > >As server-side processing can be useless and cumbersome with small >sets of data, a new system preference is introduced to control this >behaviour (server-side processing is disabled by default). > >Additionally, this patch: >- adds a switch to turn off and on row grouping (today's checkouts vs > previous checkouts) (on by default) >- adds "column settings" for relatives' checkouts tables >- factorize some code that was duplicated across the two DataTables > configurations (mDataProp) > >Test plan: >1. Find (or create) a patron that have at least 10 checkouts and where > the relatives checkouts table contain at least 10 checkouts. >2. Go to the patron's detail page and check everything works fine > in both tables (sorting, pagination, the data itself, ...) >3. Do the same on circulation page (circulation.pl) >4. Enable system preference ServerSideCheckoutsTable >5. Repeat steps 2 and 3 > >Signed-off-by: Eric Gosselin <eric.gosselin@inlibro.com> >--- > admin/columns_settings.yml | 60 +- > .../data/mysql/atomicupdate/bug_15219.sql | 2 + > installer/data/mysql/sysprefs.sql | 1 + > .../plugins/jquery.dataTables.rowGrouping.js | 10 +- > .../en/includes/checkouts-table-footer.inc | 2 +- > .../prog/en/includes/checkouts-table.inc | 1 - > .../prog/en/includes/checkouts.js.inc | 26 + > .../prog/en/includes/columns_settings.inc | 2 +- > .../prog/en/includes/strings.inc | 1 + > .../admin/preferences/circulation.pref | 6 + > .../prog/en/modules/circ/circulation.tt | 13 +- > .../prog/en/modules/members/moremember.tt | 12 +- > koha-tmpl/intranet-tmpl/prog/js/checkouts.js | 834 +++++++++--------- > svc/checkouts | 105 +-- > 14 files changed, 562 insertions(+), 513 deletions(-) > create mode 100644 installer/data/mysql/atomicupdate/bug_15219.sql > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/checkouts.js.inc > >diff --git a/admin/columns_settings.yml b/admin/columns_settings.yml >index 3e2a6723e5..5ac9f5fd1a 100644 >--- a/admin/columns_settings.yml >+++ b/admin/columns_settings.yml >@@ -231,7 +231,7 @@ modules: > moremember: > issues-table: > - >- columnname: sort_order >+ columnname: group_order > cannot_be_toggled: 1 > cannot_be_modified: 1 > is_hidden: 1 >@@ -240,11 +240,6 @@ modules: > cannot_be_toggled: 1 > cannot_be_modified: 1 > is_hidden: 1 >- - >- columnname: due_date_unformatted >- cannot_be_toggled: 1 >- cannot_be_modified: 1 >- is_hidden: 1 > - > columnname: due_date > - >@@ -279,6 +274,29 @@ modules: > columnname: export > cannot_be_toggled: 1 > cannot_be_modified: 1 >+ relatives-issues-table: >+ - >+ columnname: due_date >+ - >+ columnname: title >+ - >+ columnname: item_type >+ - >+ columnname: location >+ - >+ columnname: checkout_on >+ - >+ columnname: checkout_from >+ - >+ columnname: callno >+ - >+ columnname: charge >+ - >+ columnname: fine >+ - >+ columnname: price >+ - >+ columnname: patron > > holdshistory: > holdshistory-table: >@@ -388,7 +406,7 @@ modules: > circulation: > issues-table: > - >- columnname: sort_order >+ columnname: group_order > cannot_be_toggled: 1 > cannot_be_modified: 1 > is_hidden: 1 >@@ -397,11 +415,6 @@ modules: > cannot_be_toggled: 1 > cannot_be_modified: 1 > is_hidden: 1 >- - >- columnname: due_date_unformatted >- cannot_be_toggled: 1 >- cannot_be_modified: 1 >- is_hidden: 1 > - > columnname: due_date > - >@@ -436,6 +449,29 @@ modules: > columnname: export > cannot_be_toggled: 1 > cannot_be_modified: 1 >+ relatives-issues-table: >+ - >+ columnname: due_date >+ - >+ columnname: title >+ - >+ columnname: item_type >+ - >+ columnname: location >+ - >+ columnname: checkout_on >+ - >+ columnname: checkout_from >+ - >+ columnname: callno >+ - >+ columnname: charge >+ - >+ columnname: fine >+ - >+ columnname: price >+ - >+ columnname: patron > > returns: > checkedintable: >diff --git a/installer/data/mysql/atomicupdate/bug_15219.sql b/installer/data/mysql/atomicupdate/bug_15219.sql >new file mode 100644 >index 0000000000..a186d45abe >--- /dev/null >+++ b/installer/data/mysql/atomicupdate/bug_15219.sql >@@ -0,0 +1,2 @@ >+INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) >+VALUES ('ServerSideCheckoutsTables','0',NULL,'If enabled, use the "server-side processing" feature for checkouts tables. Can improve performance when there is a big number of checkouts to display.','YesNo'); >diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql >index 753bc57d0a..8a2064883b 100644 >--- a/installer/data/mysql/sysprefs.sql >+++ b/installer/data/mysql/sysprefs.sql >@@ -497,6 +497,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` > ('SelfCheckTimeout','120','','Define the number of seconds before the Web-based Self Checkout times out a patron','Integer'), > ('SeparateHoldings','0',NULL,'Separate current branch holdings from other holdings','YesNo'), > ('SeparateHoldingsBranch','homebranch','homebranch|holdingbranch','Branch used to separate holdings','Choice'), >+('ServerSideCheckoutsTables','0',NULL,'If enabled, use the "server-side processing" feature for checkouts tables. Can improve performance when there is a big number of checkouts per patron.','YesNo'), > ('SessionRestrictionByIP','1','Check for change in remote IP address for session security. Disable only when remote IP address changes frequently.','','YesNo'), > ('SessionStorage','mysql','mysql|Pg|tmp','Use database or a temporary file for storing session data','Choice'), > ('ShelfBrowserUsesCcode','1','0','Use the item collection code when finding items for the shelf browser.','YesNo'), >diff --git a/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.rowGrouping.js b/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.rowGrouping.js >index 126ff63357..12a88e4dba 100644 >--- a/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.rowGrouping.js >+++ b/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.rowGrouping.js >@@ -608,15 +608,15 @@ > > } > >- oTable.fnSetColumnVis(properties.iGroupingColumnIndex, !properties.bHideGroupingColumn); >+ oTable.fnSetColumnVis(properties.iGroupingColumnIndex, !properties.bHideGroupingColumn, false); > if (properties.bCustomColumnOrdering) { >- oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex, !properties.bHideGroupingOrderByColumn); >+ oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex, !properties.bHideGroupingOrderByColumn, false); > } > if (properties.iGroupingColumnIndex2 != -1) { >- oTable.fnSetColumnVis(properties.iGroupingColumnIndex2, !properties.bHideGroupingColumn2); >+ oTable.fnSetColumnVis(properties.iGroupingColumnIndex2, !properties.bHideGroupingColumn2, false); > } > if (properties.bCustomColumnOrdering2) { >- oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex2, !properties.bHideGroupingOrderByColumn2); >+ oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex2, !properties.bHideGroupingOrderByColumn2, false); > } > oTable.fnSettings().aoDrawCallback.push({ > "fn": _fnDrawCallBackWithGrouping, >@@ -687,4 +687,4 @@ > > }); > }; >-})(jQuery); >\ No newline at end of file >+})(jQuery); >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table-footer.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table-footer.inc >index b831c1e507..0da60c5930 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table-footer.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table-footer.inc >@@ -1,6 +1,6 @@ > <tfoot> > <tr> >- <td colspan="11" style="text-align: right; font-weight:bold;">Totals:</td> >+ <td colspan="10" style="text-align: right; font-weight:bold;">Totals:</td> > <td id="totaldue" style="text-align: right;">[% totaldue | html %]</td> > <td id="totalfine" style="text-align: right;">[% finetotal | html %]</td> > <td id="totalprice" style="text-align: right;">[% totalprice | html %]</td> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc >index f9265dc8ad..696ff67bd1 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts-table.inc >@@ -13,7 +13,6 @@ > <th scope="col"> </th> > <th scope="col"> </th> > <th scope="col">Due date</th> >- <th scope="col">Due date</th> > <th scope="col">Title</th> > <th scope="col">Item type</th> > <th scope="col">Collection</th> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts.js.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts.js.inc >new file mode 100644 >index 0000000000..fea263e555 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/checkouts.js.inc >@@ -0,0 +1,26 @@ >+[% USE Asset %] >+[% USE Koha %] >+[% USE raw %] >+ >+<script> >+ [% IF Koha.Preference('ServerSideCheckoutsTables') %] >+ var ServerSideCheckoutsTables = true; >+ [% ELSE %] >+ var ServerSideCheckoutsTables = false; >+ [% END %] >+ var AllowCirculate = [% (CAN_user_circulate_circulate_remaining_permissions)? 1 : 0 %]; >+ var AllowRenewalLimitOverride = [% (CAN_user_circulate_override_renewals && Koha.Preference('AllowRenewalLimitOverride'))? 1 : 0 %]; >+ >+ var MSG_DT_LOADING_RECORDS = _("Loading... you may continue scanning."); >+ >+ var borrowernumber = "[% borrowernumber | $raw %]"; >+ var relatives_borrowernumbers = new Array(); >+ [% FOREACH b IN relatives_borrowernumbers %] >+ relatives_borrowernumbers.push("[% b | $raw %]"); >+ [% END %] >+ >+ var columns_settings = [% ColumnsSettings.GetColumns( 'circ', 'circulation', 'issues-table', 'json' ) | $raw %]; >+ var relatives_columns_settings = [% ColumnsSettings.GetColumns( 'circ', 'circulation', 'relatives-issues-table', 'json' ) | $raw %]; >+</script> >+ >+[% Asset.js('js/checkouts.js') | $raw %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/columns_settings.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/columns_settings.inc >index 636cc5a562..bf1bbdec6f 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/columns_settings.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/columns_settings.inc >@@ -71,7 +71,7 @@ function KohaTable(id_selector, dt_parameters, columns_settings, add_filters) { > table.dataTable($.extend(true, {}, dataTablesDefaults, dt_parameters)); > > $(hidden_ids).each(function(index, value) { >- table.fnSetColumnVis( value, false ); >+ table.fnSetColumnVis( value, false, false ); > }); > > if ( add_filters ) { >diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc >index bd513293dd..2f03dbbe5e 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc >@@ -46,5 +46,6 @@ > var CURRENT = _(" (current) "); > var MSG_NO_ITEMTYPE = _("No itemtype"); > var MSG_CHECKOUTS_BY_ITEMTYPE = _("Number of checkouts by item type"); >+ var GROUP_TODAYS_CHECKOUTS = _("Group today's checkouts"); > //]]> > </script> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref >index c7193dfb0e..74d2e4f07e 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref >@@ -52,6 +52,12 @@ Circulation: > asc: earliest to latest > desc: latest to earliest > - due date. >+ - >+ - pref: ServerSideCheckoutsTables >+ choices: >+ yes: Enable >+ no: Do not enable >+ - server-side processing on checkouts tables. It can improve performance when there is a big number of checkouts to display. > - > - pref: SpecifyDueDate > choices: >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >index dbf3e2d37e..4fba41c019 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt >@@ -848,7 +848,6 @@ No patron matched <span class="ex">[% message | html %]</span> > <table id="relatives-issues-table"> > <thead> > <tr> >- <th scope="col">Due date (unformatted, hidden)</th> > <th scope="col">Due date</th> > <th scope="col">Title</th> > <th scope="col">Item type</th> >@@ -983,30 +982,20 @@ No patron matched <span class="ex">[% message | html %]</span> > [% INCLUDE 'timepicker.inc' %] > [% Asset.js("lib/jquery/plugins/jquery.dataTables.rowGrouping.js") | $raw %] > [% Asset.js("js/pages/circulation.js") | $raw %] >- [% Asset.js("js/checkouts.js") | $raw %] >+ [% INCLUDE 'checkouts.js.inc' %] > [% Asset.js("js/holds.js") | $raw %] > [% Asset.js("js/circ-patron-search-results.js") | $raw %] > <script type="text/javascript"> > /* Set some variable needed in circulation.js */ >- var MSG_DT_LOADING_RECORDS = _("Loading... you may continue scanning."); > var interface = "[% interface | html %]"; > var theme = "[% theme | html %]"; >- var borrowernumber = "[% patron.borrowernumber | html %]"; > var branchcode = "[% branch | html %]"; > var exports_enabled = "[% Koha.Preference('ExportCircHistory') | html %]"; >- var AllowRenewalLimitOverride = [% (CAN_user_circulate_override_renewals && Koha.Preference('AllowRenewalLimitOverride') )? 1: 0 | html %]; >- var AllowCirculate = [% (CAN_user_circulate_circulate_remaining_permissions)? 1 : 0 | html %]; > var script = "circulation"; >- var relatives_borrowernumbers = new Array(); >- [% FOREACH b IN relatives_borrowernumbers %] >- relatives_borrowernumbers.push("[% b | html %]"); >- [% END %] > > var MSG_EXPORT_SELECT_CHECKOUTS = _("You must select checkout(s) to export"); > var MSG_CONFIRM_DELETE_MESSAGE = _("Are you sure you want to delete this message? This cannot be undone."); > >- columns_settings = [% ColumnsSettings.GetColumns( 'circ', 'circulation', 'issues-table', 'json' ) | $raw %] >- > [% IF borrowernumber and patron %] > if($.cookie("holdfor") != [% patron.borrowernumber | html %]){ > $.removeCookie("holdfor", { path: '/' }); >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt >index a88a98ee88..458af27760 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt >@@ -687,7 +687,6 @@ > <table id="relatives-issues-table" style="width: 100% !Important;"> > <thead> > <tr> >- <th scope="col">Due date hidden not formatted</th> > <th scope="col">Due date</th> > <th scope="col">Title</th> > <th scope="col">Item type</th> >@@ -801,7 +800,7 @@ > [% INCLUDE 'timepicker.inc' %] > [% Asset.js("lib/jquery/plugins/jquery.dataTables.rowGrouping.js") | $raw %] > [% Asset.js("js/pages/circulation.js") | $raw %] >- [% Asset.js("js/checkouts.js") | $raw %] >+ [% INCLUDE 'checkouts.js.inc' %] > [% Asset.js("js/holds.js") | $raw %] > [% INCLUDE 'str/members-menu.inc' %] > [% Asset.js("js/members-menu.js") | $raw %] >@@ -810,22 +809,13 @@ > /* Set some variable needed in circulation.js */ > var interface = "[% interface | html %]"; > var theme = "[% theme | html %]"; >- var borrowernumber = "[% patron.borrowernumber | html %]"; > var branchcode = "[% Branches.GetLoggedInBranchcode() | html %]"; > var exports_enabled = "[% Koha.Preference('ExportCircHistory') | html %]"; >- var AllowCirculate = [% (CAN_user_circulate_circulate_remaining_permissions)? 1 : 0 | html %] >- var AllowRenewalLimitOverride = [% (CAN_user_circulate_override_renewals && Koha.Preference('AllowRenewalLimitOverride') )? 1: 0 | html %]; > var script = "moremember"; >- var relatives_borrowernumbers = new Array(); >- [% FOREACH b IN relatives_borrowernumbers %] >- relatives_borrowernumbers.push("[% b | html %]"); >- [% END %] > > var MSG_EXPORT_SELECT_CHECKOUTS = _("You must select checkout(s) to export"); > var MSG_CONFIRM_DELETE_MESSAGE = _("Are you sure you want to delete this message? This cannot be undone."); > >- columns_settings = [% ColumnsSettings.GetColumns( 'members', 'moremember', 'issues-table', 'json' ) | $raw %] >- > $(document).ready(function() { > if ( $('#clubs-tab').length ) { > $('#clubs-tab-link').on('click', function() { >diff --git a/koha-tmpl/intranet-tmpl/prog/js/checkouts.js b/koha-tmpl/intranet-tmpl/prog/js/checkouts.js >index 2525f567c7..6c36781aac 100644 >--- a/koha-tmpl/intranet-tmpl/prog/js/checkouts.js >+++ b/koha-tmpl/intranet-tmpl/prog/js/checkouts.js >@@ -1,3 +1,282 @@ >+(function($) { >+ >+var ymd = $.datepicker.formatDate('yy-mm-dd', new Date()); >+ >+function enableGrouping(datatable) { >+ datatable.rowGrouping({ >+ iGroupingColumnIndex: 1, >+ iGroupingOrderByColumnIndex: 0, >+ sGroupingColumnSortDirection: "desc" >+ }); >+} >+ >+function disableGrouping(datatable) { >+ var oSettings = datatable.fnSettings(); >+ for (f = 0; f < oSettings.aoDrawCallback.length; f++) { >+ if (oSettings.aoDrawCallback[f].sName == 'fnRowGrouping') { >+ oSettings.aoDrawCallback.splice(f, 1); >+ oSettings.aaSortingFixed = null; >+ datatable.fnDraw(); >+ break; >+ } >+ } >+} >+ >+var mRenders = { >+ groupOrder: function (oData, sType, oObj) { >+ if ( oObj.issued_today ) { >+ return "1"; >+ } else { >+ return "0"; >+ } >+ }, >+ groupName: function (oData, sType, oObj) { >+ if (oObj.issued_today) { >+ return "<strong>" + TODAYS_CHECKOUTS + "</strong>"; >+ } else { >+ return "<strong>" + PREVIOUS_CHECKOUTS + "</strong>"; >+ } >+ }, >+ dateDueFormatted: function (oData, sType, oObj) { >+ var due = oObj.date_due_formatted; >+ >+ if ( oObj.date_due_overdue ) { >+ due = "<span class='overdue'>" + due + "</span>"; >+ } >+ >+ due = "<span id='date_due_" + oObj.itemnumber + "' class='date_due'>" + due + "</span>"; >+ >+ if ( oObj.lost ) { >+ due += "<span class='lost'>" + oObj.lost.escapeHtml() + "</span>"; >+ } >+ >+ if ( oObj.damaged ) { >+ due += "<span class='dmg'>" + oObj.damaged.escapeHtml() + "</span>"; >+ } >+ >+ return due; >+ }, >+ title: function (oData, sType, oObj) { >+ var title = "<span id='title_" + oObj.itemnumber + "' class='strong'><a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber=" >+ + oObj.biblionumber >+ + "'>" >+ + oObj.title.escapeHtml(); >+ >+ $.each(oObj.subtitle, function( index, value ) { >+ title += " " + value.subfield.escapeHtml(); >+ }); >+ >+ if ( oObj.enumchron ) { >+ title += " (" + oObj.enumchron.escapeHtml() + ")"; >+ } >+ >+ title += "</a></span>"; >+ >+ if ( oObj.author ) { >+ title += " " + BY.replace( "_AUTHOR_", " " + oObj.author.escapeHtml() ); >+ } >+ >+ if ( oObj.itemnotes ) { >+ var span_class = "text-muted"; >+ if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { >+ span_class = "circ-hlt"; >+ } >+ title += " - <span class='" + span_class + " item-note-public'>" + oObj.itemnotes.escapeHtml() + "</span>"; >+ } >+ >+ if ( oObj.itemnotes_nonpublic ) { >+ var span_class = "text-danger"; >+ if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { >+ span_class = "circ-hlt"; >+ } >+ title += " - <span class='" + span_class + " item-note-nonpublic'>" + oObj.itemnotes_nonpublic.escapeHtml() + "</span>"; >+ } >+ >+ var onsite_checkout = ''; >+ if ( oObj.onsite_checkout == 1 ) { >+ onsite_checkout += " <span class='onsite_checkout'>(" + INHOUSE_USE + ")</span>"; >+ } >+ >+ title += " " >+ + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=" >+ + oObj.biblionumber >+ + "&itemnumber=" >+ + oObj.itemnumber >+ + "#" >+ + oObj.itemnumber >+ + "'>" >+ + oObj.barcode.escapeHtml() >+ + "</a>" >+ + onsite_checkout >+ >+ return title; >+ }, >+ itemtype: function (oData, sType, oObj) { >+ return oObj.itemtype_description.escapeHtml(); >+ }, >+ collection: function (oData, sType, oObj) { >+ return oObj.collection.escapeHtml(); >+ }, >+ location: function (oData, sType, oObj) { >+ return oObj.location.escapeHtml(); >+ }, >+ homebranch: function (oData, sType, oObj) { >+ return oObj.homebranch.escapeHtml(); >+ }, >+ issuedate: function (oData, sType, oObj) { >+ return oObj.issuedate_formatted; >+ }, >+ branch: function (oData, sType, oObj) { >+ return oObj.branchname.escapeHtml(); >+ }, >+ itemcallnumber: function (oData, sType, oObj) { >+ return oObj.itemcallnumber.escapeHtml(); >+ }, >+ charge: function (oData, sType, oObj) { >+ if (!oObj.charge) oObj.charge = 0; >+ return '<span style="text-align: right; display: block;">' + parseFloat(oObj.charge).toFixed(2) + '<span>'; >+ }, >+ fine: function (oData, sType, oObj) { >+ if (!oObj.fine) oObj.fine = 0; >+ return '<span style="text-align: right; display: block;">' + parseFloat(oObj.fine).toFixed(2) + '<span>'; >+ }, >+ price: function (oData, sType, oObj) { >+ if (!oObj.price) oObj.price = 0; >+ return parseFloat(oObj.price).toFixed(2); >+ }, >+ renew: function (oData, sType, oObj) { >+ var content = ""; >+ var span_style = ""; >+ var span_class = ""; >+ >+ content += "<span>"; >+ content += "<span style='padding: 0 1em;'>" + oObj.renewals_count + "</span>"; >+ >+ if ( oObj.can_renew ) { >+ // Do nothing >+ } else if ( oObj.can_renew_error == "on_reserve" ) { >+ content += "<span class='renewals-disabled-no-override'>" >+ + "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + ON_HOLD + "</a>" >+ + "</span>"; >+ >+ span_style = "display: none"; >+ span_class = "renewals-allowed"; >+ } else if ( oObj.can_renew_error == "too_many" ) { >+ content += "<span class='renewals-disabled'>" >+ + NOT_RENEWABLE >+ + "</span>"; >+ >+ span_style = "display: none"; >+ span_class = "renewals-allowed"; >+ } else if ( oObj.can_renew_error == "restriction" ) { >+ content += "<span class='renewals-disabled'>" >+ + NOT_RENEWABLE_RESTRICTION >+ + "</span>"; >+ >+ span_style = "display: none"; >+ span_class = "renewals-allowed"; >+ } else if ( oObj.can_renew_error == "overdue" ) { >+ content += "<span class='renewals-disabled'>" >+ + NOT_RENEWABLE_OVERDUE >+ + "</span>"; >+ >+ span_style = "display: none"; >+ span_class = "renewals-allowed"; >+ } else if ( oObj.can_renew_error == "too_soon" ) { >+ content += "<span class='renewals-disabled'>" >+ + NOT_RENEWABLE_TOO_SOON.format( oObj.can_renew_date ) >+ + "</span>"; >+ >+ span_style = "display: none"; >+ span_class = "renewals-allowed"; >+ } else if ( oObj.can_renew_error == "auto_too_soon" ) { >+ content += "<span class='renewals-disabled'>" >+ + NOT_RENEWABLE_AUTO_TOO_SOON >+ + "</span>"; >+ >+ span_style = "display: none"; >+ span_class = "renewals-allowed"; >+ } else if ( oObj.can_renew_error == "auto_too_late" ) { >+ content += "<span class='renewals-disabled'>" >+ + NOT_RENEWABLE_AUTO_TOO_LATE >+ + "</span>"; >+ >+ span_style = "display: none"; >+ span_class = "renewals-allowed"; >+ } else if ( oObj.can_renew_error == "auto_too_much_oweing" ) { >+ content += "<span class='renewals-disabled'>" >+ + NOT_RENEWABLE_AUTO_TOO_MUCH_OWEING >+ + "</span>"; >+ >+ span_style = "display: none"; >+ span_class = "renewals-allowed"; >+ } else if ( oObj.can_renew_error == "auto_account_expired" ) { >+ content += "<span class='renewals-disabled'>" >+ + NOT_RENEWABLE_AUTO_ACCOUNT_EXPIRED >+ + "</span>"; >+ >+ span_style = "display: none"; >+ span_class = "renewals-allowed"; >+ } else if ( oObj.can_renew_error == "auto_renew" ) { >+ content += "<span class='renewals-disabled'>" >+ + NOT_RENEWABLE_AUTO_RENEW >+ + "</span>"; >+ >+ span_style = "display: none"; >+ span_class = "renewals-allowed"; >+ } else if ( oObj.can_renew_error == "onsite_checkout" ) { >+ // Don't display something if it's an onsite checkout >+ } else { >+ content += "<span class='renewals-disabled'>" >+ + oObj.can_renew_error >+ + "</span>"; >+ >+ span_style = "display: none"; >+ span_class = "renewals-allowed"; >+ } >+ >+ var can_force_renew = ( oObj.onsite_checkout == 0 ) && ( oObj.can_renew_error != "on_reserve" ); >+ var can_renew = ( oObj.renewals_remaining > 0 && !oObj.can_renew_error ); >+ if ( can_renew || can_force_renew ) { >+ content += "<span class='" + span_class + "' style='" + span_style + "'>" >+ + "<input type='checkbox' "; >+ if ( oObj.date_due_overdue && can_renew ) { >+ content += "checked='checked' "; >+ } >+ content += "class='renew' id='renew_" + oObj.itemnumber + "' name='renew' value='" + oObj.itemnumber +"'/>" >+ + "</span>"; >+ >+ content += "<span class='renewals'>(" >+ + RENEWALS_REMAINING.format( oObj.renewals_remaining, oObj.renewals_allowed ) >+ + ")</span>"; >+ } >+ >+ content += "</span>"; >+ >+ return content; >+ }, >+ checkin: function (oData, sType, oObj) { >+ if (oObj.can_renew_error == "on_reserve") { >+ return "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + ON_HOLD + "</a>"; >+ } else { >+ return "<input type='checkbox' class='checkin' id='checkin_" + oObj.itemnumber + "' name='checkin' value='" + oObj.itemnumber +"'></input>"; >+ } >+ }, >+ export: function (oData, sType, oObj) { >+ var s = "<input type='checkbox' name='itemnumbers' value='" + oObj.itemnumber + "' style='visibility:hidden;' />"; >+ >+ s += "<input type='checkbox' class='export' id='export_" + oObj.biblionumber + "' name='biblionumbers' value='" + oObj.biblionumber + "' />"; >+ return s; >+ }, >+ patron: function (oData, sType, oObj) { >+ return "<a href='/cgi-bin/koha/members/moremember.pl?borrowernumber=" + oObj.borrowernumber + "'>" >+ + oObj.borrower.firstname.escapeHtml() >+ + " " >+ + oObj.borrower.surname.escapeHtml() >+ + " (" + oObj.borrower.cardnumber.escapeHtml() + ")</a>" >+ } >+}; >+ > $(document).ready(function() { > $.ajaxSetup ({ cache: false }); > >@@ -152,8 +431,6 @@ $(document).ready(function() { > return false; > }); > >- var ymd = $.datepicker.formatDate('yy-mm-dd', new Date()); >- > $('#issues-table').hide(); > $('#issues-table-actions').hide(); > $('#issues-table-load-immediately').change(function(){ >@@ -187,16 +464,43 @@ $(document).ready(function() { > "sProcessing": MSG_DT_LOADING_RECORDS, > }, > "bAutoWidth": false, >- "dom": 'B<"clearfix">rt', >+ "bProcessing": true, >+ "bServerSide": ServerSideCheckoutsTables, >+ "sAjaxSource": "/cgi-bin/koha/svc/checkouts", >+ "fnServerParams": function (aoData) { >+ aoData.push({ "name": "borrowernumber", "value": borrowernumber }); >+ }, >+ "fnInitComplete": function(oSettings, json) { >+ // Build a summary of checkouts grouped by itemtype >+ var checkoutsByItype = json.aaData.reduce(function (obj, row) { >+ obj[row.itemtype_description] = (obj[row.itemtype_description] || 0) + 1; >+ return obj; >+ }, {}); >+ var ul = $('<ul>'); >+ Object.keys(checkoutsByItype).sort().forEach(function (itype) { >+ var li = $('<li>') >+ .append($('<strong>').html(itype || MSG_NO_ITEMTYPE)) >+ .append(': ' + checkoutsByItype[itype]); >+ ul.append(li); >+ }) >+ $('<details>') >+ .addClass('checkouts-by-itemtype') >+ .append($('<summary>').html(MSG_CHECKOUTS_BY_ITEMTYPE)) >+ .append(ul) >+ .insertBefore(oSettings.nTableWrapper) >+ }, >+ "bPaginate": true, >+ "sPaginationType": "four_button", >+ "dom": 'B<"clearfix"><"top pager"ilp>rt', >+ "aaSorting": [], > "aoColumns": [ > { >- "mDataProp": function( oObj ) { >- return oObj.sort_order; >- } >+ "mData": "issued_today", >+ "mRender": mRenders.groupOrder > }, > { >- "mDataProp": function( oObj ) { >- if ( oObj.issued_today ) { >+ "mData": function (oObj) { >+ if (oObj.issued_today) { > return "<strong>" + TODAYS_CHECKOUTS + "</strong>"; > } else { > return "<strong>" + PREVIOUS_CHECKOUTS + "</strong>"; >@@ -204,276 +508,70 @@ $(document).ready(function() { > } > }, > { >- "mDataProp": "date_due", >- "bVisible": false, >+ "mData": "date_due", >+ "mRender": mRenders.dateDueFormatted > }, > { >- "iDataSort": 2, // Sort on hidden unformatted date due column >- "mDataProp": function( oObj ) { >- var due = oObj.date_due_formatted; >- >- if ( oObj.date_due_overdue ) { >- due = "<span class='overdue'>" + due + "</span>"; >- } >- >- due = "<span id='date_due_" + oObj.itemnumber + "' class='date_due'>" + due + "</span>"; >- >- if ( oObj.lost ) { >- due += "<span class='lost'>" + oObj.lost.escapeHtml() + "</span>"; >- } >- >- if ( oObj.damaged ) { >- due += "<span class='dmg'>" + oObj.damaged.escapeHtml() + "</span>"; >- } >- >- var patron_note = " <span class='patron_note_" + oObj.itemnumber + "'></span>"; >- due +="<br>" + patron_note; >- >- return due; >- } >+ "mData": "title", >+ "mRender": mRenders.title > }, > { >- "mDataProp": function ( oObj ) { >- title = "<span id='title_" + oObj.itemnumber + "' class='strong'><a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber=" >- + oObj.biblionumber >- + "'>" >- + oObj.title.escapeHtml(); >- >- $.each(oObj.subtitle, function( index, value ) { >- title += " " + value.subfield.escapeHtml(); >- }); >- >- if ( oObj.enumchron ) { >- title += " (" + oObj.enumchron.escapeHtml() + ")"; >- } >- >- title += "</a></span>"; >- >- if ( oObj.author ) { >- title += " " + BY.replace( "_AUTHOR_", " " + oObj.author.escapeHtml() ); >- } >- >- if ( oObj.itemnotes ) { >- var span_class = "text-muted"; >- if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { >- span_class = "circ-hlt"; >- } >- title += " - <span class='" + span_class + " item-note-public'>" + oObj.itemnotes.escapeHtml() + "</span>"; >- } >- >- if ( oObj.itemnotes_nonpublic ) { >- var span_class = "text-danger"; >- if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { >- span_class = "circ-hlt"; >- } >- title += " - <span class='" + span_class + " item-note-nonpublic'>" + oObj.itemnotes_nonpublic.escapeHtml() + "</span>"; >- } >- >- var onsite_checkout = ''; >- if ( oObj.onsite_checkout == 1 ) { >- onsite_checkout += " <span class='onsite_checkout'>(" + INHOUSE_USE + ")</span>"; >- } >- >- title += " " >- + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=" >- + oObj.biblionumber >- + "&itemnumber=" >- + oObj.itemnumber >- + "#" >- + oObj.itemnumber >- + "'>" >- + oObj.barcode.escapeHtml() >- + "</a>" >- + onsite_checkout >- >- return title; >- }, >- "sType": "anti-the" >+ "mData": "itemtype", >+ "mRender": mRenders.itemtype > }, > { >- "mDataProp": function ( oObj ) { >- return oObj.itemtype_description.escapeHtml(); >- } >+ "mData": "ccode", >+ "mRender": mRenders.collection > }, > { >- "mDataProp": function ( oObj ) { >- return oObj.collection.escapeHtml(); >- } >+ "mData": "location", >+ "mRender": mRenders.location > }, > { >- "mDataProp": function ( oObj ) { >- return oObj.location.escapeHtml(); >- } >+ "mData": "homebranch", >+ "mRender": mRenders.homebranch > }, > { >- "mDataProp": function ( oObj ) { >- return oObj.homebranch.escapeHtml(); >- } >+ "mData": "issuedate", >+ "mRender": mRenders.issuedate > }, >- { "mDataProp": "issuedate_formatted" }, > { >- "mDataProp": function ( oObj ) { >- return oObj.branchname.escapeHtml(); >- } >+ "mData": "branchcode", >+ "mRender": mRenders.branch > }, > { >- "mDataProp": function ( oObj ) { >- return oObj.itemcallnumber.escapeHtml(); >- } >+ "mData": "itemcallnumber", >+ "mRender": mRender.itemcallnumber > }, > { >- "mDataProp": function ( oObj ) { >- if ( ! oObj.charge ) oObj.charge = 0; >- return '<span style="text-align: right; display: block;">' + parseFloat(oObj.charge).toFixed(2) + '<span>'; >- } >+ "mData": "charge", >+ "mRender": mRenders.charge, >+ "bSortable": ServerSideCheckoutsTables ? false : true > }, > { >- "mDataProp": function ( oObj ) { >- if ( ! oObj.fine ) oObj.fine = 0; >- return '<span style="text-align: right; display: block;">' + parseFloat(oObj.fine).toFixed(2) + '<span>'; >- } >+ "mData": "fine", >+ "mRender": mRenders.fine, >+ "bSortable": ServerSideCheckoutsTables ? false : true > }, > { >- "mDataProp": function ( oObj ) { >- if ( ! oObj.price ) oObj.price = 0; >- return '<span style="text-align: right; display: block;">' + parseFloat(oObj.price).toFixed(2) + '<span>'; >- } >+ "mData": "replacementprice", >+ "mRender": mRenders.price, >+ "bSortable": ServerSideCheckoutsTables ? false : true > }, > { >- "bSortable": false, > "bVisible": AllowCirculate ? true : false, >- "mDataProp": function ( oObj ) { >- var content = ""; >- var span_style = ""; >- var span_class = ""; >- >- content += "<span>"; >- content += "<span style='padding: 0 1em;'>" + oObj.renewals_count + "</span>"; >- >- if ( oObj.can_renew ) { >- // Do nothing >- } else if ( oObj.can_renew_error == "on_reserve" ) { >- content += "<span class='renewals-disabled-no-override'>" >- + "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + ON_HOLD + "</a>" >- + "</span>"; >- >- span_style = "display: none"; >- span_class = "renewals-allowed"; >- } else if ( oObj.can_renew_error == "too_many" ) { >- content += "<span class='renewals-disabled'>" >- + NOT_RENEWABLE >- + "</span>"; >- >- span_style = "display: none"; >- span_class = "renewals-allowed"; >- } else if ( oObj.can_renew_error == "restriction" ) { >- content += "<span class='renewals-disabled'>" >- + NOT_RENEWABLE_RESTRICTION >- + "</span>"; >- >- span_style = "display: none"; >- span_class = "renewals-allowed"; >- } else if ( oObj.can_renew_error == "overdue" ) { >- content += "<span class='renewals-disabled'>" >- + NOT_RENEWABLE_OVERDUE >- + "</span>"; >- >- span_style = "display: none"; >- span_class = "renewals-allowed"; >- } else if ( oObj.can_renew_error == "too_soon" ) { >- content += "<span class='renewals-disabled'>" >- + NOT_RENEWABLE_TOO_SOON.format( oObj.can_renew_date ) >- + "</span>"; >- >- span_style = "display: none"; >- span_class = "renewals-allowed"; >- } else if ( oObj.can_renew_error == "auto_too_soon" ) { >- content += "<span class='renewals-disabled'>" >- + NOT_RENEWABLE_AUTO_TOO_SOON >- + "</span>"; >- >- span_style = "display: none"; >- span_class = "renewals-allowed"; >- } else if ( oObj.can_renew_error == "auto_too_late" ) { >- content += "<span class='renewals-disabled'>" >- + NOT_RENEWABLE_AUTO_TOO_LATE >- + "</span>"; >- >- span_style = "display: none"; >- span_class = "renewals-allowed"; >- } else if ( oObj.can_renew_error == "auto_too_much_oweing" ) { >- content += "<span class='renewals-disabled'>" >- + NOT_RENEWABLE_AUTO_TOO_MUCH_OWEING >- + "</span>"; >- >- span_style = "display: none"; >- span_class = "renewals-allowed"; >- } else if ( oObj.can_renew_error == "auto_account_expired" ) { >- content += "<span class='renewals-disabled'>" >- + NOT_RENEWABLE_AUTO_ACCOUNT_EXPIRED >- + "</span>"; >- >- span_style = "display: none"; >- span_class = "renewals-allowed"; >- } else if ( oObj.can_renew_error == "auto_renew" ) { >- content += "<span class='renewals-disabled'>" >- + NOT_RENEWABLE_AUTO_RENEW >- + "</span>"; >- >- span_style = "display: none"; >- span_class = "renewals-allowed"; >- } else if ( oObj.can_renew_error == "onsite_checkout" ) { >- // Don't display something if it's an onsite checkout >- } else { >- content += "<span class='renewals-disabled'>" >- + oObj.can_renew_error >- + "</span>"; >- >- span_style = "display: none"; >- span_class = "renewals-allowed"; >- } >- >- var can_force_renew = ( oObj.onsite_checkout == 0 ) && ( oObj.can_renew_error != "on_reserve" ); >- var can_renew = ( oObj.renewals_remaining > 0 && !oObj.can_renew_error ); >- if ( can_renew || can_force_renew ) { >- content += "<span class='" + span_class + "' style='" + span_style + "'>" >- + "<input type='checkbox' "; >- if ( oObj.date_due_overdue && can_renew ) { >- content += "checked='checked' "; >- } >- content += "class='renew' id='renew_" + oObj.itemnumber + "' name='renew' value='" + oObj.itemnumber +"'/>" >- + "</span>"; >- >- content += "<span class='renewals'>(" >- + RENEWALS_REMAINING.format( oObj.renewals_remaining, oObj.renewals_allowed ) >- + ")</span>"; >- } >- >- content += "</span>"; >- >- return content; >- } >+ "mRender": mRenders.renew, >+ "bSortable": false > }, > { >- "bSortable": false, > "bVisible": AllowCirculate ? true : false, >- "mDataProp": function ( oObj ) { >- if ( oObj.can_renew_error == "on_reserve" ) { >- return "<a href='/cgi-bin/koha/reserve/request.pl?biblionumber=" + oObj.biblionumber + "'>" + ON_HOLD + "</a>"; >- } else { >- return "<input type='checkbox' class='checkin' id='checkin_" + oObj.itemnumber + "' name='checkin' value='" + oObj.itemnumber +"'></input>"; >- } >- } >+ "mRender": mRenders.checkin, >+ "bSortable": false > }, > { > "bVisible": exports_enabled == 1 ? true : false, > "bSortable": false, >- "mDataProp": function ( oObj ) { >- var s = "<input type='checkbox' name='itemnumbers' value='" + oObj.itemnumber + "' style='visibility:hidden;' />"; >- >- s += "<input type='checkbox' class='export' id='export_" + oObj.biblionumber + "' name='biblionumbers' value='" + oObj.biblionumber + "' />"; >- return s; >- } >+ "mRender": mRenders.export > } > ], > "fnFooterCallback": function ( nRow, aaData, iStart, iEnd, aiDisplay ) { >@@ -488,57 +586,30 @@ $(document).ready(function() { > $("#totaldue").html(total_charge.toFixed(2)); > $("#totalfine").html(total_fine.toFixed(2)); > $("#totalprice").html(total_price.toFixed(2)); >- }, >- "bPaginate": false, >- "bProcessing": true, >- "bServerSide": false, >- "sAjaxSource": '/cgi-bin/koha/svc/checkouts', >- "fnServerData": function ( sSource, aoData, fnCallback ) { >- aoData.push( { "name": "borrowernumber", "value": borrowernumber } ); >- >- $.getJSON( sSource, aoData, function (json) { >- fnCallback(json) >- } ); >- }, >- "fnInitComplete": function(oSettings, json) { >- // Disable rowGrouping plugin after first use >- // so any sorting on the table doesn't use it >- var oSettings = issuesTable.fnSettings(); >- >- for (f = 0; f < oSettings.aoDrawCallback.length; f++) { >- if (oSettings.aoDrawCallback[f].sName == 'fnRowGrouping') { >- oSettings.aoDrawCallback.splice(f, 1); >- break; >- } >- } >- >- oSettings.aaSortingFixed = null; >- >- // Build a summary of checkouts grouped by itemtype >- var checkoutsByItype = json.aaData.reduce(function (obj, row) { >- obj[row.itemtype_description] = (obj[row.itemtype_description] || 0) + 1; >- return obj; >- }, {}); >- var ul = $('<ul>'); >- Object.keys(checkoutsByItype).sort().forEach(function (itype) { >- var li = $('<li>') >- .append($('<strong>').html(itype || MSG_NO_ITEMTYPE)) >- .append(': ' + checkoutsByItype[itype]); >- ul.append(li); >- }) >- $('<details>') >- .addClass('checkouts-by-itemtype') >- .append($('<summary>').html(MSG_CHECKOUTS_BY_ITEMTYPE)) >- .append(ul) >- .insertBefore(oSettings.nTableWrapper) >- }, >- }, columns_settings).rowGrouping( >- { >- iGroupingColumnIndex: 1, >- iGroupingOrderByColumnIndex: 0, >- sGroupingColumnSortDirection: "asc" > } >- ); >+ }, columns_settings); >+ >+ enableGrouping(issuesTable); >+ >+ var groupingSwitch = $('<input type="checkbox">') >+ .attr('id', 'issues-table-row-grouping-switch') >+ .attr('checked', 'checked') >+ .css('vertical-align', 'middle') >+ .change(function() { >+ if ($(this).is(':checked')) { >+ enableGrouping(issuesTable); >+ } else { >+ disableGrouping(issuesTable); >+ } >+ }); >+ $('<div></div>') >+ .css('float', 'left') >+ .css('padding', '0.3em 0.5em') >+ .css('line-height', '1.9em') >+ .append(groupingSwitch) >+ .append(' ') >+ .append('<label for="issues-table-row-grouping-switch">' + GROUP_TODAYS_CHECKOUTS + '</label>') >+ .appendTo('#issues-table_wrapper .top.pager'); > > if ( $("#issues-table").length ) { > $("#issues-table_processing").position({ >@@ -552,153 +623,76 @@ $(document).ready(function() { > var relativesIssuesTable; > $("#relatives-issues-tab").click( function() { > if ( ! relativesIssuesTable ) { >- relativesIssuesTable = $("#relatives-issues-table").dataTable({ >+ relativesIssuesTable = KohaTable("#relatives-issues-table", { > "bAutoWidth": false, >- "sDom": "rt", >- "aaSorting": [], >+ "sDom": 'C<"top pager"ilp>rt', >+ "aaSorting": [[4, "desc"]], >+ "bProcessing": true, >+ "bServerSide": ServerSideCheckoutsTables, >+ "sAjaxSource": "/cgi-bin/koha/svc/checkouts", >+ "fnServerParams": function (aoData) { >+ for (i in relatives_borrowernumbers) { >+ var borrowernumber = relatives_borrowernumbers[i]; >+ aoData.push({ "name": "borrowernumber", "value": borrowernumber }); >+ } >+ }, >+ "bPaginate": true, >+ "sPaginationType": "four_button", > "aoColumns": [ > { >- "mDataProp": "date_due", >- "bVisible": false, >+ "mData": "date_due", >+ "mRender": mRenders.dateDueFormatted > }, > { >- "iDataSort": 1, // Sort on hidden unformatted date due column >- "mDataProp": function( oObj ) { >- var today = new Date(); >- var due = new Date( oObj.date_due ); >- if ( today > due ) { >- return "<span class='overdue'>" + oObj.date_due_formatted + "</span>"; >- } else { >- return oObj.date_due_formatted; >- } >- } >+ "mData": "title", >+ "mRender": mRenders.title, > }, > { >- "mDataProp": function ( oObj ) { >- title = "<span class='strong'><a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber=" >- + oObj.biblionumber >- + "'>" >- + oObj.title.escapeHtml(); >- >- $.each(oObj.subtitle, function( index, value ) { >- title += " " + value.subfield.escapeHtml(); >- }); >- >- if ( oObj.enumchron ) { >- title += " (" + oObj.enumchron.escapeHtml() + ")"; >- } >- >- title += "</a></span>"; >- >- if ( oObj.author ) { >- title += " " + BY.replace( "_AUTHOR_", " " + oObj.author.escapeHtml() ); >- } >- >- if ( oObj.itemnotes ) { >- var span_class = ""; >- if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { >- span_class = "circ-hlt"; >- } >- title += " - <span class='" + span_class + "'>" + oObj.itemnotes.escapeHtml() + "</span>" >- } >- >- if ( oObj.itemnotes_nonpublic ) { >- var span_class = ""; >- if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { >- span_class = "circ-hlt"; >- } >- title += " - <span class='" + span_class + "'>" + oObj.itemnotes_nonpublic.escapeHtml() + "</span>" >- } >- >- var onsite_checkout = ''; >- if ( oObj.onsite_checkout == 1 ) { >- onsite_checkout += " <span class='onsite_checkout'>(" + INHOUSE_USE + ")</span>"; >- } >- >- title += " " >- + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=" >- + oObj.biblionumber >- + "&itemnumber=" >- + oObj.itemnumber >- + "#" >- + oObj.itemnumber >- + "'>" >- + oObj.barcode.escapeHtml() >- + "</a>" >- + onsite_checkout; >- >- return title; >- }, >- "sType": "anti-the" >+ "mData": "itemtype", >+ "mRender": mRenders.itemtype > }, > { >- "mDataProp": function ( oObj ) { >- return oObj.itemtype_description.escapeHtml(); >- } >+ "mData": "ccode", >+ "mRender": mRenders.collection > }, > { >- "mDataProp": function ( oObj ) { >- return oObj.collection.escapeHtml(); >- } >+ "mData": "location", >+ "mRender": mRenders.location > }, > { >- "mDataProp": function ( oObj ) { >- return oObj.location.escapeHtml(); >- } >+ "mData": "issuedate", >+ "mRender": mRenders.issuedate > }, >- { "mDataProp": "issuedate_formatted" }, > { >- "mDataProp": function ( oObj ) { >- return oObj.branchname.escapeHtml(); >- } >+ "mData": "branchcode", >+ "mRender": mRenders.branch > }, > { >- "mDataProp": function ( oObj ) { >- return oObj.itemcallnumber.escapeHtml(); >- } >+ "mData": "itemcallnumber", >+ "mRender": mRenders.itemcallnumber > }, > { >- "mDataProp": function ( oObj ) { >- if ( ! oObj.charge ) oObj.charge = 0; >- return parseFloat(oObj.charge).toFixed(2); >- } >+ "mData": "charge", >+ "mRender": mRenders.charge, >+ "bSortable": ServerSideCheckoutsTables ? false : true > }, > { >- "mDataProp": function ( oObj ) { >- if ( ! oObj.fine ) oObj.fine = 0; >- return parseFloat(oObj.fine).toFixed(2); >- } >+ "mData": "fine", >+ "mRender": mRenders.fine, >+ "bSortable": ServerSideCheckoutsTables ? false : true > }, > { >- "mDataProp": function ( oObj ) { >- if ( ! oObj.price ) oObj.price = 0; >- return parseFloat(oObj.price).toFixed(2); >- } >+ "mData": "replacementprice", >+ "mRender": mRenders.price, >+ "bSortable": ServerSideCheckoutsTables ? false : true > }, > { >- "mDataProp": function( oObj ) { >- return "<a href='/cgi-bin/koha/members/moremember.pl?borrowernumber=" + oObj.borrowernumber + "'>" >- + oObj.borrower.firstname.escapeHtml() >- + " " + >- oObj.borrower.surname.escapeHtml() >- + " (" + oObj.borrower.cardnumber.escapeHtml() + ")</a>" >- } >- }, >- ], >- "bPaginate": false, >- "bProcessing": true, >- "bServerSide": false, >- "sAjaxSource": '/cgi-bin/koha/svc/checkouts', >- "fnServerData": function ( sSource, aoData, fnCallback ) { >- $.each(relatives_borrowernumbers, function( index, value ) { >- aoData.push( { "name": "borrowernumber", "value": value } ); >- }); >- >- $.getJSON( sSource, aoData, function (json) { >- fnCallback(json) >- } ); >- }, >- }); >+ "mData": "borrowernumber", >+ "mRender": mRenders.patron, >+ "bSortable": ServerSideCheckoutsTables ? false : true >+ } >+ ] >+ }, relatives_columns_settings); > } > }); > >@@ -718,4 +712,6 @@ $(document).ready(function() { > } > } ).prop('checked', false); > } >- }); >+}); >+ >+})(jQuery); >diff --git a/svc/checkouts b/svc/checkouts >index 9a1b3a5648..e97fc4afc3 100755 >--- a/svc/checkouts >+++ b/svc/checkouts >@@ -27,6 +27,7 @@ use C4::Biblio qw(GetMarcBiblio GetFrameworkCode GetRecordValue ); > use C4::Circulation qw(GetIssuingCharges CanBookBeRenewed GetRenewCount GetSoonestRenewDate); > use C4::Overdues qw(GetFine); > use C4::Context; >+use C4::Utils::DataTables; > > use Koha::AuthorisedValues; > use Koha::DateUtils; >@@ -45,26 +46,33 @@ unless (haspermission($userid, { circulate => 'circulate_remaining_permissions' > exit 0; > } > >-my @sort_columns = qw/date_due title itype issuedate branchcode itemcallnumber/; >- > my @borrowernumber = $input->multi_param('borrowernumber'); >-my $offset = $input->param('iDisplayStart'); >-my $results_per_page = $input->param('iDisplayLength') || -1; >- >-my $sorting_column = $input->param('iSortCol_0') || q{}; >-$sorting_column = ( $sorting_column && $sort_columns[$sorting_column] ) ? $sort_columns[$sorting_column] : 'issuedate'; >- >-my $sorting_direction = $input->param('sSortDir_0') || q{}; >-$sorting_direction = $sorting_direction eq 'asc' ? 'asc' : 'desc'; >- >-$results_per_page = undef if ( $results_per_page == -1 ); >- >-binmode STDOUT, ":encoding(UTF-8)"; >-print $input->header( -type => 'text/plain', -charset => 'UTF-8' ); >+my $offset = $input->param('iDisplayStart'); >+my $count = $input->param('iDisplayLength'); >+ >+my %params = dt_get_params($input); >+my $orderby = dt_build_orderby(\%params); >+ >+my $todaysIssuesDefaultSortOrder = >+ C4::Context->preference('todaysIssuesDefaultSortOrder'); >+my $previousIssuesDefaultSortOrder = >+ C4::Context->preference('previousIssuesDefaultSortOrder'); >+ >+# Default sort when user hasn't clicked on a column header yet. >+# When row grouping is enabled, DataTables ask to sort on issued_today column, >+# so we need to treat this case the same as the "no sorting" case >+if (!$orderby || $orderby =~ m/ORDER BY issued_today desc\s*$/) { >+ $orderby = qq{ >+ ORDER BY >+ issued_today DESC, >+ CASE WHEN issued_today = 0 THEN date_due END $previousIssuesDefaultSortOrder, >+ CASE WHEN issued_today != 0 THEN date_due END $todaysIssuesDefaultSortOrder >+ }; >+} > > my @parameters; > my $sql = ' >- SELECT >+ SELECT SQL_CALC_FOUND_ROWS > issuedate, > date_due, > date_due < now() as date_due_overdue, >@@ -102,7 +110,7 @@ my $sql = ' > location, > items.enumchron, > >- DATEDIFF( issuedate, CURRENT_DATE() ) AS not_issued_today >+ DATEDIFF( issuedate, CURRENT_DATE() ) = 0 AS issued_today > FROM issues > LEFT JOIN items USING ( itemnumber ) > LEFT JOIN biblio USING ( biblionumber ) >@@ -110,27 +118,33 @@ my $sql = ' > LEFT JOIN borrowers USING ( borrowernumber ) > LEFT JOIN branches ON ( issues.branchcode = branches.branchcode ) > LEFT JOIN branches branches2 ON ( items.homebranch = branches2.branchcode ) >- WHERE borrowernumber >+ WHERE > '; > >+my $borrowernumber_sql = 'borrowernumber'; > if ( @borrowernumber == 1 ) { >- $sql .= '= ?'; >-} >-else { >- $sql .= ' IN (' . join( ',', ('?') x @borrowernumber ) . ') '; >+ $borrowernumber_sql .= ' = ?'; >+} else { >+ $borrowernumber_sql .= ' IN (' . join( ',', ('?') x @borrowernumber ) . ') '; > } >+$sql .= $borrowernumber_sql; > push( @parameters, @borrowernumber ); > >-$sql .= " ORDER BY $sorting_column $sorting_direction "; >+$sql .= " $orderby"; >+ >+if ($count && $count > 0) { >+ $sql .= " LIMIT ?,?"; >+ push @parameters, $offset, $count; >+} > > my $dbh = C4::Context->dbh(); > my $sth = $dbh->prepare($sql); > $sth->execute(@parameters); >+my ($iTotalDisplayRecords) = $dbh->selectrow_array('SELECT FOUND_ROWS()'); > > my $item_level_itypes = C4::Context->preference('item-level_itypes'); > >-my @checkouts_today; >-my @checkouts_previous; >+my @checkouts; > while ( my $c = $sth->fetchrow_hashref() ) { > my ($charge) = GetIssuingCharges( $c->{itemnumber}, $c->{borrowernumber} ); > my $fine = GetFine( $c->{itemnumber}, $c->{borrowernumber} ); >@@ -227,36 +241,25 @@ while ( my $c = $sth->fetchrow_hashref() ) { > firstname => $c->{firstname}, > cardnumber => $c->{cardnumber}, > }, >- issued_today => !$c->{not_issued_today}, >+ issued_today => $c->{issued_today} ? JSON::true : JSON::false, > }; > >- if ( $c->{not_issued_today} ) { >- push( @checkouts_previous, $checkout ); >- } >- else { >- push( @checkouts_today, $checkout ); >- } >+ push @checkouts, $checkout; > } > >+binmode STDOUT, ":encoding(UTF-8)"; >+print $input->header( -type => 'application/json', -charset => 'UTF-8' ); > >-@checkouts_today = sort { $a->{timestamp} cmp $b->{timestamp} } @checkouts_today; >-@checkouts_today = reverse(@checkouts_today) >- unless ( C4::Context->preference('todaysIssuesDefaultSortOrder') eq 'desc' ); >- >-@checkouts_previous = sort { $a->{date_due} cmp $b->{date_due} } @checkouts_previous; >-@checkouts_previous = reverse(@checkouts_previous) >- if ( C4::Context->preference('previousIssuesDefaultSortOrder') eq 'desc' ); >- >-my @checkouts = ( @checkouts_today, @checkouts_previous ); >- >-my $i = 1; >-map { $_->{sort_order} = $i++ } @checkouts; >- >+my $sEcho = $input->param('sEcho'); >+my ($iTotalRecords) = $dbh->selectrow_array( >+ "SELECT COUNT(*) FROM issues WHERE $borrowernumber_sql", undef, >+ @borrowernumber); > >-my $data; >-$data->{'iTotalRecords'} = scalar @checkouts; >-$data->{'iTotalDisplayRecords'} = scalar @checkouts; >-$data->{'sEcho'} = $input->param('sEcho') || undef; >-$data->{'aaData'} = \@checkouts; >+my $response = { >+ iTotalRecords => $iTotalRecords, >+ iTotalDisplayRecords => $iTotalDisplayRecords, >+ sEcho => $sEcho, >+ aaData => \@checkouts, >+}; > >-print to_json($data); >+print to_json($response); >-- >2.17.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 15219
:
45018
|
45036
|
45054
|
48107
|
50075
|
60071
|
60642
|
61158
|
61159
|
61545
|
61546
|
72905
|
72906
|
74224
|
74225
|
75911
|
75912
|
75913
|
78555
|
78556
|
78557
|
78558
|
78559
|
79195
|
79196
|
79197
|
79198
|
79199
|
92776
|
92777
|
92778
|
92779
|
92780
|
92781
|
93921