@@ -, +, @@ no changes should be noted to some number of seconds. --- installer/data/mysql/sysprefs.sql | 2 + installer/data/mysql/updatedatabase.pl | 12 + koha-tmpl/intranet-tmpl/prog/en/js/checkouts.js | 417 +++++++++++--------- .../prog/en/modules/admin/preferences/patrons.pref | 8 + .../prog/en/modules/circ/circulation.tt | 13 +- .../prog/en/modules/members/moremember.tt | 67 ++-- 6 files changed, 300 insertions(+), 219 deletions(-) --- a/installer/data/mysql/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -82,6 +82,8 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('CatalogModuleRelink','0',NULL,'If OFF the linker will never replace the authids that are set in the cataloging module.','YesNo'), ('CataloguingLog','1',NULL,'If ON, log edit/create/delete actions on bibliographic data. WARNING: this feature is very resource consuming.','YesNo'), ('checkdigit','none','none|katipo','If ON, enable checks on patron cardnumber: none or \"Katipo\" style checks','Choice'), +('CheckoutsTableSecondsToLoadCirculation', '0', NULL, 'Number of seconds to delay the loading of the checkouts table for circulation.', 'Integer'), +('CheckoutsTableSecondsToLoadPatronDetails', '0', NULL, 'Number of seconds to delay the loading of the checkouts table for patron details.', 'Integer'), ('CircAutocompl','1',NULL,'If ON, autocompletion is enabled for the Circulation input','YesNo'), ('CircAutoPrintQuickSlip','qslip',NULL,'Choose what should happen when an empty barcode field is submitted in circulation: Display a print quick slip window, Display a print slip window or Clear the screen.','Choice'), ('CircControl','ItemHomeLibrary','PickupLibrary|PatronLibrary|ItemHomeLibrary','Specify the agency that controls the circulation and fines policy','Choice'), --- a/installer/data/mysql/updatedatabase.pl +++ a/installer/data/mysql/updatedatabase.pl @@ -8570,6 +8570,18 @@ if ( CheckVersion($DBversion) ) { SetVersion($DBversion); } +$DBversion = "3.17.00.XXX"; +if ( CheckVersion($DBversion) ) { + $dbh->do(q{ + INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES + ('CheckoutsTableSecondsToLoadCirculation', '0', NULL, 'Number of seconds to delay the loading of the checkouts table for circulation.', 'Integer'), + ('CheckoutsTableSecondsToLoadPatronDetails', '0', NULL, 'Number of seconds to delay the loading of the checkouts table for patron details.', 'Integer'); + }); + + print "Upgrade to $DBversion done (Bug 12550 - Add ability to delay loading of patron's checkouts in circulation and patron details)\n"; + SetVersion($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) --- a/koha-tmpl/intranet-tmpl/prog/en/js/checkouts.js +++ a/koha-tmpl/intranet-tmpl/prog/en/js/checkouts.js @@ -126,219 +126,254 @@ $(document).ready(function() { var ymd = $.datepicker.formatDate('yy-mm-dd', new Date()); - var issuesTable; - var drawn = 0; - issuesTable = $("#issues-table").dataTable({ - "oLanguage": { - "sEmptyTable" : MSG_DT_LOADING_RECORDS, - }, - "bAutoWidth": false, - "sDom": "<'row-fluid'<'span6'><'span6'>r>t<'row-fluid'>t", - "aoColumns": [ - { - "mDataProp": function( oObj ) { - if ( oObj.issued_today ) { - return "" + TODAYS_CHECKOUTS + ""; - } else { - return "" + PREVIOUS_CHECKOUTS + ""; - } - } - }, - { - "mDataProp": "date_due", - "bVisible": false, + // Don't bother loading table if there are no checkouts to show + if ( issues_count ) { + var issuesTable; + + if ( checkouts_table_seconds_to_load ) { + $('#issues-table').hide(); + $('#issues-table-actions').hide(); + $('#issues-table-load-now-button').click(function(){ + LoadIssuesTableNow(); + return false; + }); + var loadIssuesTableInterval = setInterval(function(){ CountdownIssuesTableLoading(); }, 1000); + } else { + $('#issues-table-loading-message').hide(); + LoadIssuesTable(); + } + } + + function CountdownIssuesTableLoading(){ + if ( checkouts_table_seconds_to_load ) { + $('#issues-table-loading-count').text( checkouts_table_seconds_to_load ); + checkouts_table_seconds_to_load--; + } else { + LoadIssuesTableNow(); + } + } + + function LoadIssuesTableNow() { + clearInterval(loadIssuesTableInterval); + $('#issues-table-loading-message').hide(); + $('#issues-table').show(); + $('#issues-table-actions').show(); + LoadIssuesTable(); + } + + function LoadIssuesTable() { + issuesTable = $("#issues-table").dataTable({ + "oLanguage": { + "sEmptyTable" : MSG_DT_LOADING_RECORDS, }, - { - "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 "" + oObj.date_due_formatted + ""; - } else { - return oObj.date_due_formatted; + "bAutoWidth": false, + "sDom": "<'row-fluid'<'span6'><'span6'>r>t<'row-fluid'>t", + "aoColumns": [ + { + "mDataProp": function( oObj ) { + if ( oObj.issued_today ) { + return "" + TODAYS_CHECKOUTS + ""; + } else { + return "" + PREVIOUS_CHECKOUTS + ""; + } } - } - }, - { - "mDataProp": function ( oObj ) { - title = "" - + oObj.title; - - $.each(oObj.subtitle, function( index, value ) { - title += " " + value.subfield; - }); + }, + { + "mDataProp": "date_due", + "bVisible": false, + }, + { + "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 "" + oObj.date_due_formatted + ""; + } else { + return oObj.date_due_formatted; + } + } + }, + { + "mDataProp": function ( oObj ) { + title = "" + + oObj.title; - title += ""; + $.each(oObj.subtitle, function( index, value ) { + title += " " + value.subfield; + }); - if ( oObj.author ) { - title += " " + BY.replace( "_AUTHOR_", " " + oObj.author ); - } + title += ""; - if ( oObj.itemnotes ) { - var span_class = ""; - if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { - span_class = "circ-hlt"; + if ( oObj.author ) { + title += " " + BY.replace( "_AUTHOR_", " " + oObj.author ); } - title += " - " + oObj.itemnotes + "" - } - title += " " - + "" - + oObj.barcode - + ""; - - return title; - } - }, - { "mDataProp": "itemtype" }, - { "mDataProp": "issuedate_formatted" }, - { "mDataProp": "branchname" }, - { "mDataProp": "itemcallnumber" }, - { - "mDataProp": function ( oObj ) { - if ( ! oObj.charge ) oObj.charge = 0; - return parseFloat(oObj.charge).toFixed(2); - } - }, - { - "mDataProp": function ( oObj ) { - if ( ! oObj.price ) oObj.price = 0; - return parseFloat(oObj.price).toFixed(2); - } - }, - { - "bSortable": false, - "mDataProp": function ( oObj ) { - var content = ""; - var span_style = ""; - var span_class = ""; - - content += ""; - content += "" + oObj.renewals_count + ""; - - if ( oObj.can_renew ) { - // Do nothing - } else if ( oObj.can_renew_error == "on_reserve" ) { - content += "" - + "" + ON_HOLD + "" - + ""; - - span_style = "display: none"; - span_class = "renewals-allowed"; - } else if ( oObj.can_renew_error == "too_many" ) { - content += "" - + NOT_RENEWABLE - + ""; - - span_style = "display: none"; - span_class = "renewals-allowed"; - } else if ( oObj.can_renew_error == "too_soon" ) { - content += "" - + NOT_RENEWABLE_TOO_SOON.format( oObj.can_renew_date ) - + ""; - - span_style = "display: none"; - span_class = "renewals-allowed"; - } else { - content += "" - + oObj.can_renew_error - + ""; + if ( oObj.itemnotes ) { + var span_class = ""; + if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { + span_class = "circ-hlt"; + } + title += " - " + oObj.itemnotes + "" + } - span_style = "display: none"; - span_class = "renewals-allowed"; + title += " " + + "" + + oObj.barcode + + ""; + + return title; + } + }, + { "mDataProp": "itemtype" }, + { "mDataProp": "issuedate_formatted" }, + { "mDataProp": "branchname" }, + { "mDataProp": "itemcallnumber" }, + { + "mDataProp": function ( oObj ) { + if ( ! oObj.charge ) oObj.charge = 0; + return parseFloat(oObj.charge).toFixed(2); + } + }, + { + "mDataProp": function ( oObj ) { + if ( ! oObj.price ) oObj.price = 0; + return parseFloat(oObj.price).toFixed(2); } + }, + { + "bSortable": false, + "mDataProp": function ( oObj ) { + var content = ""; + var span_style = ""; + var span_class = ""; - content += "" - + "" - + ""; + content += ""; + content += "" + oObj.renewals_count + ""; + + if ( oObj.can_renew ) { + // Do nothing + } else if ( oObj.can_renew_error == "on_reserve" ) { + content += "" + + "" + ON_HOLD + "" + + ""; + + span_style = "display: none"; + span_class = "renewals-allowed"; + } else if ( oObj.can_renew_error == "too_many" ) { + content += "" + + NOT_RENEWABLE + + ""; + + span_style = "display: none"; + span_class = "renewals-allowed"; + } else if ( oObj.can_renew_error == "too_soon" ) { + content += "" + + NOT_RENEWABLE_TOO_SOON.format( oObj.can_renew_date ) + + ""; + + span_style = "display: none"; + span_class = "renewals-allowed"; + } else { + content += "" + + oObj.can_renew_error + + ""; + + span_style = "display: none"; + span_class = "renewals-allowed"; + } - if ( oObj.renewals_remaining ) { - content += "(" - + RENEWALS_REMAINING.format( oObj.renewals_remaining, oObj.renewals_allowed ) - + ")"; - } + content += "" + + "" + + ""; - content += ""; + if ( oObj.renewals_remaining ) { + content += "(" + + RENEWALS_REMAINING.format( oObj.renewals_remaining, oObj.renewals_allowed ) + + ")"; + } + + content += ""; - return content; + return content; + } + }, + { + "bSortable": false, + "mDataProp": function ( oObj ) { + if ( oObj.can_renew_error == "on_reserve" ) { + return "" + ON_HOLD + ""; + } else { + return ""; + } + } + }, + { + "bVisible": exports_enabled ? true : false, + "bSortable": false, + "mDataProp": function ( oObj ) { + return ""; + } + } + ], + "fnFooterCallback": function ( nRow, aaData, iStart, iEnd, aiDisplay ) { + var total_charge = 0; + var total_price = 0; + for ( var i=0; i < aaData.length; i++ ) { + total_charge += aaData[i]['charge'] * 1; + total_price += aaData[i]['price'] * 1; } + var nCells = nRow.getElementsByTagName('td'); + nCells[1].innerHTML = total_charge.toFixed(2); + nCells[2].innerHTML = total_price.toFixed(2); }, - { - "bSortable": false, - "mDataProp": function ( oObj ) { - if ( oObj.can_renew_error == "on_reserve" ) { - return "" + ON_HOLD + ""; - } else { - return ""; + "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) { + // 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; }, + }).rowGrouping( { - "bVisible": exports_enabled ? true : false, - "bSortable": false, - "mDataProp": function ( oObj ) { - return ""; - } - } - ], - "fnFooterCallback": function ( nRow, aaData, iStart, iEnd, aiDisplay ) { - var total_charge = 0; - var total_price = 0; - for ( var i=0; i < aaData.length; i++ ) { - total_charge += aaData[i]['charge'] * 1; - total_price += aaData[i]['price'] * 1; - } - var nCells = nRow.getElementsByTagName('td'); - nCells[1].innerHTML = total_charge.toFixed(2); - nCells[2].innerHTML = 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) { - // 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; - } + iGroupingOrderByColumnIndex: 0, + sGroupingColumnSortDirection: "desc" } + ); - oSettings.aaSortingFixed = null; - }, - }).rowGrouping( - { - iGroupingOrderByColumnIndex: 0, - sGroupingColumnSortDirection: "desc" + if ( $("#issues-table").length ) { + $("#issues-table_processing").position({ + of: $( "#issues-table" ), + collision: "none" + }); } - ); - - if ( $("#issues-table").length ) { - $("#issues-table_processing").position({ - of: $( "#issues-table" ), - collision: "none" - }); } // Don't load relatives' issues table unless it is clicked on --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref @@ -138,3 +138,11 @@ Patrons: - pref: CardnumberLength - "characters long. The length can be a single number to specify an exact length, a range separated by a comma (i.e., 'Min,Max'), or a maximum with no minimum (i.e., ',Max')." - "If 'cardnumber' is included in the BorrowerMandatoryField list, the minimum length, if not specified here, defaults to one." + - + - Wait + - pref: CheckoutsTableSecondsToLoadCirculation + class: integer + - seconds before loading the patron's checkouts table when checking out items to a patron and + - pref: CheckoutsTableSecondsToLoadPatronDetails + class: integer + - seconds when viewing a patron's details. --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -1,3 +1,4 @@ +[% USE Koha %] [% USE Branches %] [% USE KohaDates %] [% IF ( export_remove_fields OR export_with_csv_profile ) %] @@ -33,6 +34,9 @@ var borrowernumber = "[% borrowernumber %]"; var branchcode = "[% branch %]"; var exports_enabled = "[% exports_enabled %]"; var AllowRenewalLimitOverride = [% CAN_user_circulate_override_renewals && AllowRenewalLimitOverride %]; +var issues_count = [% issuecount %]; +[%- SET CheckoutsTableSecondsToLoad = Koha.Preference('CheckoutsTableSecondsToLoadCirculation') -%] +var checkouts_table_seconds_to_load = [% CheckoutsTableSecondsToLoad ? CheckoutsTableSecondsToLoad - 1 : 0 %]; var relatives_borrowernumbers = new Array(); [% FOREACH b IN relatives_borrowernumbers %] relatives_borrowernumbers.push("[% b %]"); @@ -680,6 +684,13 @@ No patron matched [% message %]
[% IF ( issuecount ) %] +
+

+ Load now + Loading in [% Koha.Preference('CheckoutsTableSecondsToLoadCirculation') %] seconds... +

+
+ @@ -701,7 +712,7 @@ No patron matched [% message %] [% INCLUDE 'checkouts-table-footer.inc' %]
-
+
[% IF ( CAN_user_circulate_override_renewals ) %] [% IF ( AllowRenewalLimitOverride ) %] --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt @@ -1,3 +1,4 @@ +[% USE Koha %] [% USE KohaDates %] [% INCLUDE 'doc-head-open.inc' %] Koha › Patrons › @@ -27,6 +28,9 @@ var borrowernumber = "[% borrowernumber %]"; var branchcode = "[% branch %]"; var exports_enabled = "[% exports_enabled %]"; var AllowRenewalLimitOverride = [% CAN_user_circulate_override_renewals && AllowRenewalLimitOverride %]; +var issues_count = [% issuecount %]; +[%- SET CheckoutsTableSecondsToLoad = Koha.Preference('CheckoutsTableSecondsToLoadPatronDetails') -%] +var checkouts_table_seconds_to_load = [% CheckoutsTableSecondsToLoad ? CheckoutsTableSecondsToLoad - 1 : 0 %]; var relatives_borrowernumbers = new Array(); [% FOREACH b IN relatives_borrowernumbers %] relatives_borrowernumbers.push("[% b %]"); @@ -408,6 +412,13 @@ function validate1(date) { <div id="checkouts"> [% IF ( issuecount ) %] + <div id="issues-table-loading-message"> + <p> + <a id="issues-table-load-now-button" href="#" class="btn"><i class="icon-download"></i> Load now</a> + Loading in <span id="issues-table-loading-count">[% Koha.Preference('CheckoutsTableSecondsToLoadPatronDetails') %]</span> seconds... + </p> + </div> + <form name="issues" action="/cgi-bin/koha/tools/export.pl" method="post" class="checkboxed"> <table id="issues-table" style="width: 100% !Important;"> <thead> @@ -431,36 +442,38 @@ function validate1(date) { </table> [% IF ( issuecount ) %] - <fieldset class="action"> - [% IF ( CAN_user_circulate_override_renewals ) %] - [% IF ( AllowRenewalLimitOverride ) %] - <label for="override_limit">Override renewal limit:</label> - <input type="checkbox" name="override_limit" id="override_limit" value="1" /> - [% END %] - [% END %] - <button class="btn" id="RenewCheckinChecked"><i class="icon-check"></i> Renew or return checked items</button> - <button class="btn" id="RenewAll"><i class="icon-book"></i> Renew all</button> - </fieldset> - - [% IF ( exports_enabled ) %] - <fieldset> - <label for="export_formats"><b>Export checkouts using format:</b></label> - <select name="export_formats" id="export_formats"> - <option value="iso2709_995">ISO2709 with items</option> - <option value="iso2709">ISO2709 without items</option> - [% IF ( export_with_csv_profile ) %] - <option value="csv">CSV</option> + <div id="issues-table-actions"> + <fieldset class="action"> + [% IF ( CAN_user_circulate_override_renewals ) %] + [% IF ( AllowRenewalLimitOverride ) %] + <label for="override_limit">Override renewal limit:</label> + <input type="checkbox" name="override_limit" id="override_limit" value="1" /> [% END %] - </select> - - <label for="export_remove_fields">Don't export fields:</label> <input type="text" id="export_remove_fields" name="export_remove_fields" value="[% export_remove_fields %]" title="Use for iso2709 exports" /> - <input type="hidden" name="op" value="export" /> - <input type="hidden" id="export_format" name="format" value="iso2709" /> - <input type="hidden" id="dont_export_item" name="dont_export_item" value="0" /> - <input type="hidden" id="record_type" name="record_type" value="bibs" /> - <button class="btn btn-small" id="export_submit"><i class="icon-download-alt"></i> Export</button> + [% END %] + <button class="btn" id="RenewCheckinChecked"><i class="icon-check"></i> Renew or return checked items</button> + <button class="btn" id="RenewAll"><i class="icon-book"></i> Renew all</button> </fieldset> - [% END %] + + [% IF ( exports_enabled ) %] + <fieldset> + <label for="export_formats"><b>Export checkouts using format:</b></label> + <select name="export_formats" id="export_formats"> + <option value="iso2709_995">ISO2709 with items</option> + <option value="iso2709">ISO2709 without items</option> + [% IF ( export_with_csv_profile ) %] + <option value="csv">CSV</option> + [% END %] + </select> + + <label for="export_remove_fields">Don't export fields:</label> <input type="text" id="export_remove_fields" name="export_remove_fields" value="[% export_remove_fields %]" title="Use for iso2709 exports" /> + <input type="hidden" name="op" value="export" /> + <input type="hidden" id="export_format" name="format" value="iso2709" /> + <input type="hidden" id="dont_export_item" name="dont_export_item" value="0" /> + <input type="hidden" id="record_type" name="record_type" value="bibs" /> + <button class="btn btn-small" id="export_submit"><i class="icon-download-alt"></i> Export</button> + </fieldset> + [% END %] + </div> [% END %] </form> [% ELSE %] --