From 82275fa2db63b7d2358897aad72b845a73cb8bda Mon Sep 17 00:00:00 2001 From: Kyle M Hall Date: Tue, 4 Feb 2014 12:42:55 -0500 Subject: [PATCH] Bug 11703 - Convert checkouts table to ajax datatable When a patron has many checked out items, circulation.pl can take a very long time to load ( on the order of minutes in some cases ). This is primarily due to the processing of the previous checkouts list. If we convert to this table to a datatable that fetches its data via ajax, we can make circulation.pl far more responsive. The same should be done with relative's checkouts as well. Test Plan: 1) Apply this patch 2) Observe that the checkouts and relatives' checkouts tables are now loaded asynchronously 3) Observe and verify the renew and return actions are now ajax based and function in a manner equivilent to how they used to. This bug had quite a few followups, so I squashed all of them into one change so that code is easier to follow. Original commit messages are below: Bug 11703 - Use the ajax datatables on patron details page Bug 11703 - Convert holds tables to ajax datatables Bug 11703 [QA Followup 1] - Center bProcessing message over table Bug 11703 [QA Followup 2] - Remove icons from checkout and clear buttons Bug 11703 [QA Followup 3] - Remove references to UseTablesortForCirc Bug 11703 [QA Followup 4] - Add back in Today's checkouts/Previous checkouts rows Bug 11703 [QA Followup 5] Bug 11703 [QA Followup 6] - Move strings to an include file for translation purposes Bug 11703 [QA Followup 7] - Fix issues spotted by koha-qa.pl Bug 11703 [QA Followup 8] - Speed up api/checkouts.pl as much as possible Bug 11703 [QA Followup 9] - Move scripts from api directory to svc directory Bug 11703 [QA Followup 10] - Fix errors caused by rebase Bug 11703 [QA Followup 11] - Prevent multiple fetchs from ajax source Bug 11703 [QA Followup 12] - Fix problem detected by koha-qa.pl Bug 11703 [QA Followup 13] - Removed uneccessary data from renewal box during renewal Bug 11703 [QA Followup 14] - Fix table column span Signed-off-by: Dobrica Pavlinusic Signed-off-by: Katrin Fischer Passes all tests and QA script. Test plan on bug report: http://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=11703#c98 Signed-off-by: Jonathan Druart Signed-off-by: Christopher Brannon --- Koha/Schema/Result/Issue.pm | 32 +- Koha/Schema/Result/Reserve.pm | 24 +- circ/circulation.pl | 218 +----- installer/data/mysql/sysprefs.sql | 1 - .../plugins/jquery.dataTables.rowGrouping.js | 690 ++++++++++++++++++ .../prog/en/css/staff-global.css | 2 +- .../en/includes/checkouts-table-footer.inc | 2 +- .../prog/en/includes/strings.inc | 30 + .../intranet-tmpl/prog/en/js/checkouts.js | 435 +++++++++++ koha-tmpl/intranet-tmpl/prog/en/js/holds.js | 133 ++++ .../prog/en/js/pages/circulation.js | 73 +- .../admin/preferences/circulation.pref | 6 - .../prog/en/modules/circ/circulation.tt | 562 +++----------- .../prog/en/modules/members/moremember.tt | 404 ++++------ members/moremember.pl | 209 +----- svc/checkin.pl | 75 ++ svc/checkouts.pl | 167 +++++ svc/holds.pl | 143 ++++ svc/renew.pl | 69 ++ 19 files changed, 2073 insertions(+), 1202 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.rowGrouping.js create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc create mode 100644 koha-tmpl/intranet-tmpl/prog/en/js/checkouts.js create mode 100644 koha-tmpl/intranet-tmpl/prog/en/js/holds.js create mode 100755 svc/checkin.pl create mode 100755 svc/checkouts.pl create mode 100755 svc/holds.pl create mode 100755 svc/renew.pl diff --git a/Koha/Schema/Result/Issue.pm b/Koha/Schema/Result/Issue.pm index 282c802f12..e1838b6f03 100644 --- a/Koha/Schema/Result/Issue.pm +++ b/Koha/Schema/Result/Issue.pm @@ -184,10 +184,34 @@ __PACKAGE__->belongs_to( # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZEh31EKBmURMKxDxI+H3EA __PACKAGE__->belongs_to( - "borrower", - "Koha::Schema::Result::Borrower", - { borrowernumber => "borrowernumber" }, - { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, + "borrower", + "Koha::Schema::Result::Borrower", + { borrowernumber => "borrowernumber" }, + { join_type => "LEFT", on_delete => "CASCADE", on_update => "CASCADE" }, +); + +__PACKAGE__->belongs_to( + "item", + "Koha::Schema::Result::Item", + { itemnumber => "itemnumber" }, + { + is_deferrable => 1, + join_type => "LEFT", + on_delete => "CASCADE", + on_update => "CASCADE", + }, +); + +__PACKAGE__->belongs_to( + "branch", + "Koha::Schema::Result::Branch", + { branchcode => "branchcode" }, + { + is_deferrable => 1, + join_type => "LEFT", + on_delete => "CASCADE", + on_update => "CASCADE", + }, ); 1; diff --git a/Koha/Schema/Result/Reserve.pm b/Koha/Schema/Result/Reserve.pm index 527651d506..184a854e09 100644 --- a/Koha/Schema/Result/Reserve.pm +++ b/Koha/Schema/Result/Reserve.pm @@ -288,6 +288,28 @@ __PACKAGE__->belongs_to( # Created by DBIx::Class::Schema::Loader v0.07025 @ 2013-10-14 20:56:21 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ig/fobzvZf1OgAHZFtkyyQ +__PACKAGE__->belongs_to( + "item", + "Koha::Schema::Result::Item", + { itemnumber => "itemnumber" }, + { + is_deferrable => 1, + join_type => "LEFT", + on_delete => "CASCADE", + on_update => "CASCADE", + }, +); + +__PACKAGE__->belongs_to( + "biblio", + "Koha::Schema::Result::Biblio", + { biblionumber => "biblionumber" }, + { + is_deferrable => 1, + join_type => "LEFT", + on_delete => "CASCADE", + on_update => "CASCADE", + }, +); -# You can replace this text with custom content, and it will be preserved on regeneration 1; diff --git a/circ/circulation.pl b/circ/circulation.pl index 91851d2df3..81737ee8e1 100755 --- a/circ/circulation.pl +++ b/circ/circulation.pl @@ -42,6 +42,7 @@ use CGI::Session; use C4::Members::Attributes qw(GetBorrowerAttributes); use Koha::Borrower::Debarments qw(GetDebarments IsDebarred); use Koha::DateUtils; +use Koha::Database; use Date::Calc qw( Today @@ -96,14 +97,6 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user ( my $branches = GetBranches(); -my @failedrenews = $query->param('failedrenew'); # expected to be itemnumbers -our %renew_failed = (); -for (@failedrenews) { $renew_failed{$_} = 1; } - -my @failedreturns = $query->param('failedreturn'); -our %return_failed = (); -for (@failedreturns) { $return_failed{$_} = 1; } - my $findborrower = $query->param('findborrower') || q{}; $findborrower =~ s|,| |g; my $borrowernumber = $query->param('borrowernumber'); @@ -121,10 +114,6 @@ if (C4::Context->preference("DisplayClearScreenButton")) { $template->param(DisplayClearScreenButton => 1); } -if (C4::Context->preference("UseTablesortForCirc")) { - $template->param(UseTablesortForCirc => 1); -} - my $barcode = $query->param('barcode') || q{}; $barcode =~ s/^\s*|\s*$//g; # remove leading/trailing whitespace @@ -360,9 +349,8 @@ if ($barcode) { } } - # FIXME If the issue is confirmed, we launch another time GetMemberIssuesAndFines, now display the issue count after issue - my ( $od, $issue, $fines ) = GetMemberIssuesAndFines( $borrowernumber ); - $template->param( issuecount => $issue ); + my ( $od, $issue, $fines ) = GetMemberIssuesAndFines($borrowernumber); + $template->param( issuecount => $issue ); } # reload the borrower info for the sake of reseting the flags..... @@ -374,194 +362,13 @@ if ($borrowernumber) { # BUILD HTML # show all reserves of this borrower, and the position of the reservation .... if ($borrowernumber) { + $template->param( + holds_count => Koha::Database->new()->schema()->resultset('Reserve') + ->count( { borrowernumber => $borrowernumber } ) ); - # new op dev - # now we show the status of the borrower's reservations - my @borrowerreserv = GetReservesFromBorrowernumber($borrowernumber ); - my @reservloop; - my @WaitingReserveLoop; - - foreach my $num_res (@borrowerreserv) { - my %getreserv; - my %getWaitingReserveInfo; - my $getiteminfo = GetBiblioFromItemNumber( $num_res->{'itemnumber'} ); - my $itemtypeinfo = getitemtypeinfo( (C4::Context->preference('item-level_itypes')) ? $getiteminfo->{'itype'} : $getiteminfo->{'itemtype'} ); - my ( $transfertwhen, $transfertfrom, $transfertto ) = - GetTransfers( $num_res->{'itemnumber'} ); - - $getreserv{waiting} = 0; - $getreserv{transfered} = 0; - $getreserv{nottransfered} = 0; - - $getreserv{reservedate} = format_date( $num_res->{'reservedate'} ); - $getreserv{reserve_id} = $num_res->{'reserve_id'}; - $getreserv{title} = $getiteminfo->{'title'}; - $getreserv{subtitle} = GetRecordValue('subtitle', GetMarcBiblio($getiteminfo->{biblionumber}), GetFrameworkCode($getiteminfo->{biblionumber})); - $getreserv{itemtype} = $itemtypeinfo->{'description'}; - $getreserv{author} = $getiteminfo->{'author'}; - $getreserv{barcodereserv} = $getiteminfo->{'barcode'}; - $getreserv{itemcallnumber} = $getiteminfo->{'itemcallnumber'}; - $getreserv{biblionumber} = $getiteminfo->{'biblionumber'}; - $getreserv{waitingat} = GetBranchName( $num_res->{'branchcode'} ); - $getreserv{suspend} = $num_res->{'suspend'}; - $getreserv{suspend_until} = $num_res->{'suspend_until'}; - # check if we have a waiting status for reservations - if ( $num_res->{'found'} && $num_res->{'found'} eq 'W' ) { - $getreserv{color} = 'reserved'; - $getreserv{waiting} = 1; -# genarate information displaying only waiting reserves - $getWaitingReserveInfo{title} = $getiteminfo->{'title'}; - $getWaitingReserveInfo{biblionumber} = $getiteminfo->{'biblionumber'}; - $getWaitingReserveInfo{itemtype} = $itemtypeinfo->{'description'}; - $getWaitingReserveInfo{author} = $getiteminfo->{'author'}; - $getWaitingReserveInfo{itemcallnumber} = $getiteminfo->{'itemcallnumber'}; - $getWaitingReserveInfo{reservedate} = format_date( $num_res->{'reservedate'} ); - $getWaitingReserveInfo{waitingat} = GetBranchName( $num_res->{'branchcode'} ); - $getWaitingReserveInfo{waitinghere} = 1 if $num_res->{'branchcode'} eq $branch; - } - # check transfers with the itemnumber foud in th reservation loop - if ($transfertwhen) { - $getreserv{color} = 'transfered'; - $getreserv{transfered} = 1; - $getreserv{datesent} = format_date($transfertwhen); - $getreserv{frombranch} = GetBranchName($transfertfrom); - } elsif ($getiteminfo->{'holdingbranch'} ne $num_res->{'branchcode'}) { - $getreserv{nottransfered} = 1; - $getreserv{nottransferedby} = GetBranchName( $getiteminfo->{'holdingbranch'} ); - } - -# if we don't have a reserv on item, we put the biblio infos and the waiting position - if ( $getiteminfo->{'title'} eq '' ) { - my $getbibinfo = GetBiblioData( $num_res->{'biblionumber'} ); - - $getreserv{color} = 'inwait'; - $getreserv{title} = $getbibinfo->{'title'}; - $getreserv{subtitle} = GetRecordValue('subtitle', GetMarcBiblio($num_res->{biblionumber}), GetFrameworkCode($num_res->{biblionumber})); - $getreserv{nottransfered} = 0; - $getreserv{itemtype} = $itemtypeinfo->{'description'}; - $getreserv{author} = $getbibinfo->{'author'}; - $getreserv{biblionumber} = $num_res->{'biblionumber'}; - } - $getreserv{waitingposition} = $num_res->{'priority'}; - $getreserv{expirationdate} = $num_res->{'expirationdate'}; - push( @reservloop, \%getreserv ); - -# if we have a reserve waiting, initiate waitingreserveloop - if ($getreserv{waiting} == 1) { - push (@WaitingReserveLoop, \%getWaitingReserveInfo) - } - - } - - # return result to the template - $template->param( - countreserv => scalar @reservloop, - reservloop => \@reservloop , - WaitingReserveLoop => \@WaitingReserveLoop, - ); $template->param( adultborrower => 1 ) if ( $borrower->{'category_type'} eq 'A' ); } -# make the issued books table. -my $todaysissues = ''; -my $previssues = ''; -our @todaysissues = (); -our @previousissues = (); -our @relissues = (); -our @relprevissues = (); -my $displayrelissues; - -our $totalprice = 0; - -sub build_issue_data { - my $issueslist = shift; - my $relatives = shift; - - # split in 2 arrays for today & previous - foreach my $it ( @$issueslist ) { - my $itemtypeinfo = getitemtypeinfo( (C4::Context->preference('item-level_itypes')) ? $it->{'itype'} : $it->{'itemtype'} ); - - # set itemtype per item-level_itype syspref - FIXME this is an ugly hack - $it->{'itemtype'} = ( C4::Context->preference( 'item-level_itypes' ) ) ? $it->{'itype'} : $it->{'itemtype'}; - - ($it->{'charge'}, $it->{'itemtype_charge'}) = GetIssuingCharges( - $it->{'itemnumber'}, $it->{'borrowernumber'} - ); - $it->{'charge'} = sprintf("%.2f", $it->{'charge'}) if defined $it->{'charge'}; - my ($can_renew, $can_renew_error) = CanBookBeRenewed( - $it->{'borrowernumber'},$it->{'itemnumber'} - ); - $it->{"renew_error_${can_renew_error}"} = 1 if defined $can_renew_error; - my $restype = C4::Reserves::GetReserveStatus( $it->{'itemnumber'} ); - $it->{'can_renew'} = $can_renew; - $it->{'can_confirm'} = !$can_renew && !$restype; - $it->{'renew_error'} = ( $restype eq "Waiting" or $restype eq "Reserved" ) ? 1 : 0; - $it->{'checkoutdate'} = C4::Dates->new($it->{'issuedate'},'iso')->output('syspref'); - $it->{'issuingbranchname'} = GetBranchName($it->{'branchcode'}); - - $totalprice += $it->{'replacementprice'} || 0; - $it->{'itemtype'} = $itemtypeinfo->{'description'}; - $it->{'itemtype_image'} = $itemtypeinfo->{'imageurl'}; - $it->{'dd_sort'} = $it->{'date_due'}; - $it->{'dd'} = output_pref($it->{'date_due'}); - $it->{'displaydate_sort'} = $it->{'issuedate'}; - $it->{'displaydate'} = output_pref($it->{'issuedate'}); - #$it->{'od'} = ( $it->{'date_due'} lt $todaysdate ) ? 1 : 0 ; - $it->{'od'} = $it->{'overdue'}; - $it->{'subtitle'} = GetRecordValue('subtitle', GetMarcBiblio($it->{biblionumber}), GetFrameworkCode($it->{biblionumber})); - $it->{'renew_failed'} = $renew_failed{$it->{'itemnumber'}}; - $it->{'return_failed'} = $return_failed{$it->{'barcode'}}; - - if ( ( $it->{'issuedate'} && $it->{'issuedate'} gt $todaysdate ) - || ( $it->{'lastreneweddate'} && $it->{'lastreneweddate'} gt $todaysdate ) ) { - (!$relatives) ? push @todaysissues, $it : push @relissues, $it; - } else { - (!$relatives) ? push @previousissues, $it : push @relprevissues, $it; - } - ($it->{'renewcount'},$it->{'renewsallowed'},$it->{'renewsleft'}) = C4::Circulation::GetRenewCount($it->{'borrowernumber'},$it->{'itemnumber'}); #Add renewal count to item data display - - $it->{'soonestrenewdate'} = output_pref( - C4::Circulation::GetSoonestRenewDate( - $it->{borrowernumber}, $it->{itemnumber} - ) - ); - } -} - -if ($borrower) { - - # Getting borrower relatives - my @relborrowernumbers = GetMemberRelatives($borrower->{'borrowernumber'}); - #push @borrowernumbers, $borrower->{'borrowernumber'}; - - # get each issue of the borrower & separate them in todayissues & previous issues - my $issueslist = GetPendingIssues($borrower->{'borrowernumber'}); - my $relissueslist = []; - if ( @relborrowernumbers ) { - $relissueslist = GetPendingIssues(@relborrowernumbers); - } - - build_issue_data($issueslist, 0); - build_issue_data($relissueslist, 1); - - $displayrelissues = scalar($relissueslist); - - if ( C4::Context->preference( "todaysIssuesDefaultSortOrder" ) eq 'asc' ) { - @todaysissues = sort { $a->{'timestamp'} cmp $b->{'timestamp'} } @todaysissues; - } - else { - @todaysissues = sort { $b->{'timestamp'} cmp $a->{'timestamp'} } @todaysissues; - } - - if ( C4::Context->preference( "previousIssuesDefaultSortOrder" ) eq 'asc' ){ - @previousissues = sort { $a->{'date_due'} cmp $b->{'date_due'} } @previousissues; - } - else { - @previousissues = sort { $b->{'date_due'} cmp $a->{'date_due'} } @previousissues; - } -} - - my @values; my %labels; my $CGIselectborrower; @@ -694,6 +501,11 @@ if (C4::Context->preference('ExtendedPatronAttributes')) { ); } +my @relatives = GetMemberRelatives( $borrower->{'borrowernumber'} ); +my $relatives_issues_count = + Koha::Database->new()->schema()->resultset('Issue') + ->count( { borrowernumber => \@relatives } ); + $template->param( lib_messages_loop => $lib_messages_loop, bor_messages_loop => $bor_messages_loop, @@ -731,13 +543,7 @@ $template->param( duedatespec => $duedatespec, message => $message, CGIselectborrower => $CGIselectborrower, - totalprice => sprintf('%.2f', $totalprice), totaldue => sprintf('%.2f', $total), - todayissues => \@todaysissues, - previssues => \@previousissues, - relissues => \@relissues, - relprevissues => \@relprevissues, - displayrelissues => $displayrelissues, inprocess => $inprocess, is_child => ($borrowernumber && $borrower->{'category_type'} eq 'C'), circview => 1, @@ -748,6 +554,8 @@ $template->param( SuspendHoldsIntranet => C4::Context->preference('SuspendHoldsIntranet'), AutoResumeSuspendedHolds => C4::Context->preference('AutoResumeSuspendedHolds'), RoutingSerials => C4::Context->preference('RoutingSerials'), + relatives_issues_count => $relatives_issues_count, + relatives_borrowernumbers => \@relatives, ); # save stickyduedate to session diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index d41ef74be1..ed427eaee9 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -428,7 +428,6 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('UseICU','0','1','Tell Koha if ICU indexing is in use for Zebra or not.','YesNo'), ('UseKohaPlugins','0','','Enable or disable the ability to use Koha Plugins.','YesNo'), ('UseQueryParser','0',NULL,'If enabled, try to use QueryParser for queries.','YesNo'), -('UseTablesortForCirc','0','','If on, use the JQuery tablesort function on the list of current borrower checkouts on the circulation page. Note that the use of this function may slow down circ for patrons with may checkouts.','YesNo'), ('UseTransportCostMatrix','0','','Use Transport Cost Matrix when filling holds','YesNo'), ('viewISBD','1','','Allow display of ISBD view of bibiographic records','YesNo'), ('viewLabeledMARC','0','','Allow display of labeled MARC view of bibiographic records','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 new file mode 100644 index 0000000000..126ff63357 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.rowGrouping.js @@ -0,0 +1,690 @@ +/* +* File: jquery.dataTables.grouping.js +* Version: 1.2.9. +* Author: Jovan Popovic +* +* Copyright 2013 Jovan Popovic, all rights reserved. +* +* This source file is free software, under either the GPL v2 license or a +* BSD style license, as supplied with this software. +* +* This source file is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. +* Parameters: +* @iGroupingColumnIndex Integer Index of the column that will be used for grouping - default 0 +* @sGroupingColumnSortDirection Enumeration Sort direction of the group +* @iGroupingOrderByColumnIndex Integer Index of the column that will be used for ordering groups +* @sGroupingClass String Class that will be associated to the group row. Default - "group" +* @sGroupItemClass String Class that will be associated to the group row of group items. Default - "group-item" +* @bSetGroupingClassOnTR Boolean If set class will be set to the TR instead of the TD withing the grouping TR +* @bHideGroupingColumn Boolean Hide column used for grouping once results are grouped. Default - true +* @bHideGroupingOrderByColumn Boolean Hide column used for ordering groups once results are grouped. Default - true +* @sGroupBy Enumeration Type of grouping that should be applied. Values "name"(default), "letter", "year" +* @sGroupLabelPrefix String Prefix that will be added to each group cell +* @bExpandableGrouping Boolean Attach expand/collapse handlers to the grouping rows +* @bExpandSingleGroup Boolean Use accordon grouping +* @iExpandGroupOffset Integer Number of pixels to set scroll position above the currently selected group. If -1 scroll will be alligned to the table +* General settings +* @sDateFormat: "dd/MM/yyyy" String Date format used for grouping +* @sEmptyGroupLabel String Lable that will be placed as group if grouping cells are empty. Default "-" + +* Parameters used in the second level grouping +* @iGroupingColumnIndex2 Integer Index of the secondary column that will be used for grouping - default 0 +* @sGroupingColumnSortDirection2 Enumeration Sort direction of the secondary group +* @iGroupingOrderByColumnIndex2 Integer Index of the column that will be used for ordering secondary groups +* @sGroupingClass2 String Class that will be associated to the secondary group row. Default "subgroup" +* @sGroupItemClass2 String Class that will be associated to the secondary group row of group items. Default "subgroup-item" +* @bHideGroupingColumn2 Boolean Hide column used for secondary grouping once results are grouped. Default - true, +* @bHideGroupingOrderByColumn2 Boolean Hide column used for ordering secondary groups once results are grouped. Default - true, +* @sGroupBy2 Enumeration Type of grouping that should be applied to secondary column. Values "name"(default), "letter", "year", +* @sGroupLabelPrefix2 String Prefix that will be added to each secondary group cell +* @fnOnGrouped Function Function that is called when grouping is finished. Function has no parameters. +*/ +(function ($) { + + "use strict"; + + $.fn.rowGrouping = function (options) { + + function _fnOnGrouped() { + + } + + function _fnOnGroupCreated(oGroup, sGroup, iLevel) { + /// + ///Function called when a new grouping row is created(it should be overriden in properties) + /// + } + + function _fnOnGroupCompleted(oGroup, sGroup, iLevel) { + /// + ///Function called when a new grouping row is created(it should be overriden in properties) + /// + } + + function _getMonthName(iMonth) { + var asMonths = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; + return asMonths[iMonth - 1]; + } + + var defaults = { + + iGroupingColumnIndex: 0, + sGroupingColumnSortDirection: "", + iGroupingOrderByColumnIndex: -1, + sGroupingClass: "group", + sGroupItemClass: "group-item", + bHideGroupingColumn: true, + bHideGroupingOrderByColumn: true, + sGroupBy: "name", + sGroupLabelPrefix: "", + fnGroupLabelFormat: function (label) { return label; }, + bExpandableGrouping: false, + bExpandSingleGroup: false, + iExpandGroupOffset: 100, + asExpandedGroups: null, + + sDateFormat: "dd/MM/yyyy", + sEmptyGroupLabel: "-", + bSetGroupingClassOnTR: false, + + iGroupingColumnIndex2: -1, + sGroupingColumnSortDirection2: "", + iGroupingOrderByColumnIndex2: -1, + sGroupingClass2: "subgroup", + sGroupItemClass2: "subgroup-item", + bHideGroupingColumn2: true, + bHideGroupingOrderByColumn2: true, + sGroupBy2: "name", + sGroupLabelPrefix2: "", + fnGroupLabelFormat2: function (label) { return label; }, + bExpandableGrouping2: false, + + fnOnGrouped: _fnOnGrouped, + + fnOnGroupCreated: _fnOnGroupCreated, + fnOnGroupCompleted: _fnOnGroupCompleted, + + oHideEffect: null, // { method: "hide", duration: "fast", easing: "linear" }, + oShowEffect: null,//{ method: "show", duration: "slow", easing: "linear" } + + bUseFilteringForGrouping: false // This is still work in progress option + }; + return this.each(function (index, elem) { + + var oTable = $(elem).dataTable(); + + var aoGroups = new Array(); + $(this).dataTableExt.aoGroups = aoGroups; + + function fnCreateGroupRow(sGroupCleaned, sGroup, iColspan) { + var nGroup = document.createElement('tr'); + var nCell = document.createElement('td'); + nGroup.id = "group-id-" + oTable.attr("id") + "_" + sGroupCleaned; + + var oGroup = { id: nGroup.id, key: sGroupCleaned, text: sGroup, level: 0, groupItemClass: ".group-item-" + sGroupCleaned, dataGroup: sGroupCleaned, aoSubgroups: new Array() }; + + + + if (properties.bSetGroupingClassOnTR) { + nGroup.className = properties.sGroupingClass + " " + sGroupCleaned; + } else { + nCell.className = properties.sGroupingClass + " " + sGroupCleaned; + } + + nCell.colSpan = iColspan; + nCell.innerHTML = properties.sGroupLabelPrefix + properties.fnGroupLabelFormat(sGroup == "" ? properties.sEmptyGroupLabel : sGroup, oGroup ); + if (properties.bExpandableGrouping) { + + if (!_fnIsGroupCollapsed(sGroupCleaned)) { + nCell.className += " expanded-group"; + oGroup.state = "expanded"; + } else { + nCell.className += " collapsed-group"; + oGroup.state = "collapsed"; + } + nCell.className += " group-item-expander"; + $(nCell).attr('data-group', oGroup.dataGroup); //Fix provided by mssskhalsa (Issue 5) + $(nCell).attr("data-group-level", oGroup.level); + $(nCell).click(_fnOnGroupClick); + } + nGroup.appendChild(nCell); + aoGroups[sGroupCleaned] = oGroup; + oGroup.nGroup = nGroup; + properties.fnOnGroupCreated(oGroup, sGroupCleaned, 1); + return oGroup; + } + + function _fnCreateGroup2Row(sGroup2, sGroupLabel, iColspan, oParentGroup) { + + var nGroup2 = document.createElement('tr'); + nGroup2.id = oParentGroup.id + "_" + sGroup2; + var nCell2 = document.createElement('td'); + var dataGroup = oParentGroup.dataGroup + '_' + sGroup2; + + var oGroup = { id: nGroup2.id, key: sGroup2, text: sGroupLabel, level: oParentGroup.level + 1, groupItemClass: ".group-item-" + dataGroup, + dataGroup: dataGroup, aoSubgroups: new Array() + }; + + if (properties.bSetGroupingClassOnTR) { + nGroup2.className = properties.sGroupingClass2 + " " + sGroup2; + } else { + nCell2.className = properties.sGroupingClass2 + " " + sGroup2; + } + + nCell2.colSpan = iColspan; + nCell2.innerHTML = properties.sGroupLabelPrefix2 + properties.fnGroupLabelFormat2(sGroupLabel == "" ? properties.sEmptyGroupLabel : sGroupLabel, oGroup); + + if (properties.bExpandableGrouping) { + + nGroup2.className += " group-item-" + oParentGroup.dataGroup; + } + + + if (properties.bExpandableGrouping && properties.bExpandableGrouping2) { + + if (!_fnIsGroupCollapsed(oGroup.dataGroup)) { + nCell2.className += " expanded-group"; + oGroup.state = "expanded"; + } else { + nCell2.className += " collapsed-group"; + oGroup.state = "collapsed"; + } + nCell2.className += " group-item-expander"; + $(nCell2).attr('data-group', oGroup.dataGroup); + $(nCell2).attr("data-group-level", oGroup.level); + $(nCell2).click(_fnOnGroupClick); + } + + nGroup2.appendChild(nCell2); + + oParentGroup.aoSubgroups[oGroup.dataGroup] = oGroup; + aoGroups[oGroup.dataGroup] = oGroup; + oGroup.nGroup = nGroup2; + properties.fnOnGroupCreated(oGroup, sGroup2, 2); + return oGroup; + } + + function _fnIsGroupCollapsed(sGroup) { + if (aoGroups[sGroup] != null) + return (aoGroups[sGroup].state == "collapsed"); + else + if (sGroup.indexOf("_") > -1) + true; + else + if(bInitialGrouping && (asExpandedGroups==null || asExpandedGroups.length == 0)) + return false;// initially if asExpandedGroups is empty - no one is collapsed + else + return ($.inArray(sGroup, asExpandedGroups) == -1); //the last chance check asExpandedGroups + } + + function _fnGetYear(x) { + if(x.length< (iYearIndex+iYearLength) ) + return x; + else + return x.substr(iYearIndex, iYearLength); + } + function _fnGetGroupByName(x) { + return x; + } + + function _fnGetGroupByLetter(x) { + return x.substr(0, 1); + } + + function _fnGetGroupByYear(x) { + return _fnGetYear(x); + //return Date.parseExact(x, properties.sDateFormat).getFullYear();//slooooow + } + + function _fnGetGroupByYearMonth(x) { + //var date = Date.parseExact(x, "dd/MM/yyyy"); + //return date.getFullYear() + " / " + date.getMonthName(); + //return x.substr(iYearIndex, iYearLength) + '/' + x.substr(iMonthIndex, iMonthLength); + return x.substr(iYearIndex, iYearLength) + ' ' + _getMonthName(x.substr(iMonthIndex, iMonthLength)); + } + + function _fnGetCleanedGroup(sGroup) { + + if (sGroup === "") return "-"; + return sGroup.toLowerCase().replace(/[^a-zA-Z0-9\u0080-\uFFFF]+/g, "-"); //fix for unicode characters (Issue 23) + //return sGroup.toLowerCase().replace(/\W+/g, "-"); //Fix provided by bmathews (Issue 7) + } + + function _rowGroupingRowFilter(oSettings, aData, iDataIndex) { + ///Used to expand/collapse groups with DataTables filtering + if (oSettings.nTable.id !== oTable[0].id) return true; + var sColData = aData[properties.iGroupingColumnIndex]; + if (typeof sColData === "undefined") + sColData = aData[oSettings.aoColumns[properties.iGroupingColumnIndex].mDataProp]; + if (_fnIsGroupCollapsed(_fnGetCleanedGroup(sColData))) { + if (oTable.fnIsOpen(oTable.fnGetNodes(iDataIndex))) + { + if (properties.fnOnRowClosed != null) { + properties.fnOnRowClosed(this); // $(this.cells[0].children[0]).attr('src', '../../Images/details.png'); + } + oTable.fnClose(oTable.fnGetNodes(iDataIndex)); + } + return false; + }; + return true; + } //end of function _rowGroupingRowFilter + + + function fnExpandGroup(sGroup) { + ///Expand group if expanadable grouping is used + + aoGroups[sGroup].state = "expanded"; + + $("td[data-group^='" + sGroup + "']").removeClass("collapsed-group"); + $("td[data-group^='" + sGroup + "']").addClass("expanded-group"); + + + if(properties.bUseFilteringForGrouping) + { + oTable.fnDraw(); + return;//Because rows are expanded with _rowGroupingRowFilter function + } + + if (jQuery.inArray(sGroup, asExpandedGroups)==-1) + asExpandedGroups.push(sGroup); + + if (properties.oHideEffect != null) + $(".group-item-" + sGroup, oTable) + [properties.oShowEffect.method](properties.oShowEffect.duration, + properties.oShowEffect.easing, + function () { }); + else + $(".group-item-" + sGroup, oTable).show(); + + + } //end of function fnExpandGroup + + function fnCollapseGroup(sGroup) { + ///Collapse group if expanadable grouping is used + + aoGroups[sGroup].state = "collapsed"; + $("td[data-group^='" + sGroup + "']").removeClass("expanded-group"); + $("td[data-group^='" + sGroup + "']").addClass("collapsed-group"); + + if(properties.bUseFilteringForGrouping) + { + oTable.fnDraw(); + return;//Because rows are expanded with _rowGroupingRowFilter function + } + //var index = $.inArray(sGroup, asExpandedGroups); + //asExpandedGroups.splice(index, 1); + + $('.group-item-' + sGroup).each(function () { + //Issue 24 - Patch provided by Bob Graham + if (oTable.fnIsOpen(this)) { + if (properties.fnOnRowClosed != null) { + properties.fnOnRowClosed(this); // $(this.cells[0].children[0]).attr('src', '../../Images/details.png'); + } + oTable.fnClose(this); + } + }); + + if (properties.oHideEffect != null) + $(".group-item-" + sGroup, oTable) + [properties.oHideEffect.method](properties.oHideEffect.duration, + properties.oHideEffect.easing, + function () { }); + else + $(".group-item-" + sGroup, oTable).hide(); + + } //end of function fnCollapseGroup + + function _fnOnGroupClick(e) { + /// + ///Function that is called when user click on the group cell in order to + ///expand of collapse group + /// + + //var sGroup = $(this).attr("rel"); + var sGroup = $(this).attr("data-group"); + var iGroupLevel = $(this).attr("data-group-level"); + + var bIsExpanded = !_fnIsGroupCollapsed(sGroup); + if (properties.bExpandSingleGroup) { + if (!bIsExpanded) { + var sCurrentGroup = $("td.expanded-group").attr("data-group"); + fnCollapseGroup(sCurrentGroup); + fnExpandGroup(sGroup); + + if (properties.iExpandGroupOffset != -1) { + var position = $("#group-id-" + oTable.attr("id") + "_" + sGroup).offset().top - properties.iExpandGroupOffset; + window.scroll(0, position); + } else { + var position = oTable.offset().top; + window.scroll(0, position); + } + } + } else { + if (bIsExpanded) { + fnCollapseGroup(sGroup); + } else { + fnExpandGroup(sGroup); + } + } + e.preventDefault(); + + }; //end function _fnOnGroupClick + + + function _fnDrawCallBackWithGrouping (oSettings) { + + if (oTable.fnSettings().oFeatures.bServerSide) + bInitialGrouping = true; + var bUseSecondaryGrouping = false; + + if (properties.iGroupingColumnIndex2 != -1) + bUseSecondaryGrouping = true; + + //-----Start grouping + + if (oSettings.aiDisplayMaster.length == 0) { //aiDisplay + return; + } + + var nTrs = $('tbody tr', oTable); + var iColspan = 0; //nTrs[0].getElementsByTagName('td').length; + for (var iColIndex = 0; iColIndex < oSettings.aoColumns.length; iColIndex++) { + if (oSettings.aoColumns[iColIndex].bVisible) + iColspan += 1; + } + var sLastGroup = null; + var sLastGroup2 = null; + if (oSettings.aiDisplay.length > 0) { + for (var i = 0; i < nTrs.length; i++) { + + + var iDisplayIndex = oSettings._iDisplayStart + i; + if (oTable.fnSettings().oFeatures.bServerSide) + iDisplayIndex = i; + var sGroupData = ""; + var sGroup = null; + var sGroupData2 = ""; + var sGroup2 = null; + + //Issue 31 - Start fix provided by Fabien Taysse +// sGroupData = oSettings.aoData[oSettings.aiDisplay[iDisplayIndex]]._aData[properties.iGroupingColumnIndex]; +// if (sGroupData == undefined) +// sGroupData = oSettings.aoData[oSettings.aiDisplay[iDisplayIndex]]._aData[oSettings.aoColumns[properties.iGroupingColumnIndex].mDataProp]; + sGroupData = this.fnGetData(nTrs[i], properties.iGroupingColumnIndex); + //Issue 31 - End fix provided by Fabien Taysse + + var sGroup = sGroupData; + if (properties.sGroupBy != "year") + sGroup = fnGetGroup(sGroupData); + + if (bUseSecondaryGrouping) { + sGroupData2 = oSettings.aoData[oSettings.aiDisplay[iDisplayIndex]]._aData[properties.iGroupingColumnIndex2]; + if (sGroupData2 == undefined) + sGroupData2 = oSettings.aoData[oSettings.aiDisplay[iDisplayIndex]]._aData[oSettings.aoColumns[properties.iGroupingColumnIndex2].mDataProp]; + if (properties.sGroupBy2 != "year") + sGroup2 = fnGetGroup(sGroupData2); + } + + + if (sLastGroup == null || _fnGetCleanedGroup(sGroup) != _fnGetCleanedGroup(sLastGroup)) { // new group encountered (or first of group) + var sGroupCleaned = _fnGetCleanedGroup(sGroup); + + if(sLastGroup != null) + { + properties.fnOnGroupCompleted(aoGroups[_fnGetCleanedGroup(sLastGroup)]); + } + /* + if (properties.bExpandableGrouping && bInitialGrouping) { + if (properties.bExpandSingleGroup) { + if (asExpandedGroups.length == 0) + asExpandedGroups.push(sGroupCleaned); + } else { + asExpandedGroups.push(sGroupCleaned); + } + } + */ + if(properties.bAddAllGroupsAsExpanded && jQuery.inArray(sGroupCleaned,asExpandedGroups) == -1) + asExpandedGroups.push(sGroupCleaned); + + var oGroup = fnCreateGroupRow(sGroupCleaned, sGroup, iColspan); + var nGroup = oGroup.nGroup; + + if(nTrs[i].parentNode!=null) + nTrs[i].parentNode.insertBefore(nGroup, nTrs[i]); + else + $(nTrs[i]).before(nGroup); + + sLastGroup = sGroup; + sLastGroup2 = null; //to reset second level grouping + + + + + + } // end if (sLastGroup == null || sGroup != sLastGroup) + + $(nTrs[i]).attr("data-group", aoGroups[sGroupCleaned].dataGroup); + + $(nTrs[i]).addClass(properties.sGroupItemClass); + $(nTrs[i]).addClass("group-item-" + sGroupCleaned); + if (properties.bExpandableGrouping) { + if (_fnIsGroupCollapsed(sGroupCleaned) && !properties.bUseFilteringForGrouping) { + $(nTrs[i]).hide(); + } + } + + + if (bUseSecondaryGrouping) { + + if (sLastGroup2 == null || _fnGetCleanedGroup(sGroup2) != _fnGetCleanedGroup(sLastGroup2)) { + var sGroup2Id = _fnGetCleanedGroup(sGroup) + '-' + _fnGetCleanedGroup(sGroup2); + var oGroup2 = _fnCreateGroup2Row(sGroup2Id, sGroup2, iColspan, aoGroups[sGroupCleaned]) + var nGroup2 = oGroup2.nGroup; + nTrs[i].parentNode.insertBefore(nGroup2, nTrs[i]); + + sLastGroup2 = sGroup2; + } + + $(nTrs[i]).attr("data-group", oGroup2.dataGroup) + .addClass(properties.sGroupItemClass2) + .addClass("group-item-" + oGroup2.dataGroup); + } //end if (bUseSecondaryGrouping) + + + + } // end for (var i = 0; i < nTrs.length; i++) + }; // if (oSettings.aiDisplay.length > 0) + + if(sLastGroup != null) + { + properties.fnOnGroupCompleted(aoGroups[_fnGetCleanedGroup(sLastGroup)]); + } + + + //-----End grouping + properties.fnOnGrouped(aoGroups); + + bInitialGrouping = false; + + }; // end of _fnDrawCallBackWithGrouping = function (oSettings) + + + //var oTable = this; + var iYearIndex = 6; + var iYearLength = 4; + var asExpandedGroups = new Array(); + var bInitialGrouping = true; + + var properties = $.extend(defaults, options); + + if (properties.iGroupingOrderByColumnIndex == -1) { + properties.bCustomColumnOrdering = false; + properties.iGroupingOrderByColumnIndex = properties.iGroupingColumnIndex; + } else { + properties.bCustomColumnOrdering = true; + } + + if (properties.sGroupingColumnSortDirection == "") { + if (properties.sGroupBy == "year") + properties.sGroupingColumnSortDirection = "desc"; + else + properties.sGroupingColumnSortDirection = "asc"; + } + + + if (properties.iGroupingOrderByColumnIndex2 == -1) { + properties.bCustomColumnOrdering2 = false; + properties.iGroupingOrderByColumnIndex2 = properties.iGroupingColumnIndex2; + } else { + properties.bCustomColumnOrdering2 = true; + } + + if (properties.sGroupingColumnSortDirection2 == "") { + if (properties.sGroupBy2 == "year") + properties.sGroupingColumnSortDirection2 = "desc"; + else + properties.sGroupingColumnSortDirection2 = "asc"; + } + + + + iYearIndex = properties.sDateFormat.toLowerCase().indexOf('yy'); + iYearLength = properties.sDateFormat.toLowerCase().lastIndexOf('y') - properties.sDateFormat.toLowerCase().indexOf('y') + 1; + + var iMonthIndex = properties.sDateFormat.toLowerCase().indexOf('mm'); + var iMonthLength = properties.sDateFormat.toLowerCase().lastIndexOf('m') - properties.sDateFormat.toLowerCase().indexOf('m') + 1; + + var fnGetGroup = _fnGetGroupByName; + switch (properties.sGroupBy) { + case "letter": fnGetGroup = _fnGetGroupByLetter; + break; + case "year": fnGetGroup = _fnGetGroupByYear; + break; + case "month": fnGetGroup = _fnGetGroupByYearMonth; + break; + default: fnGetGroup = _fnGetGroupByName; + break; + } + + + if (properties.asExpandedGroups != null) { + if (properties.asExpandedGroups == "NONE") { + properties.asExpandedGroups = []; + asExpandedGroups = properties.asExpandedGroups; + bInitialGrouping = false; + } else if (properties.asExpandedGroups == "ALL") { + properties.bAddAllGroupsAsExpanded = true; + } else if (properties.asExpandedGroups.constructor == String) { + var currentGroup = properties.asExpandedGroups; + properties.asExpandedGroups = new Array(); + properties.asExpandedGroups.push(_fnGetCleanedGroup(currentGroup)); + asExpandedGroups = properties.asExpandedGroups; + bInitialGrouping = false; + } else if (properties.asExpandedGroups.constructor == Array) { + for (var i = 0; i < properties.asExpandedGroups.length; i++) { + asExpandedGroups.push(_fnGetCleanedGroup(properties.asExpandedGroups[i])); + if (properties.bExpandSingleGroup) + break; + } + bInitialGrouping = false; + } + }else{ + properties.asExpandedGroups = new Array(); + properties.bAddAllGroupsAsExpanded = true; + } + if(properties.bExpandSingleGroup){ + var nTrs = $('tbody tr', oTable); + var sGroupData = oTable.fnGetData(nTrs[0], properties.iGroupingColumnIndex); + + var sGroup = sGroupData; + if (properties.sGroupBy != "year") + sGroup = fnGetGroup(sGroupData); + + var sGroupCleaned = _fnGetCleanedGroup(sGroup); + properties.asExpandedGroups = new Array(); + properties.asExpandedGroups.push(sGroupCleaned); + + } + + oTable.fnSetColumnVis(properties.iGroupingColumnIndex, !properties.bHideGroupingColumn); + if (properties.bCustomColumnOrdering) { + oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex, !properties.bHideGroupingOrderByColumn); + } + if (properties.iGroupingColumnIndex2 != -1) { + oTable.fnSetColumnVis(properties.iGroupingColumnIndex2, !properties.bHideGroupingColumn2); + } + if (properties.bCustomColumnOrdering2) { + oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex2, !properties.bHideGroupingOrderByColumn2); + } + oTable.fnSettings().aoDrawCallback.push({ + "fn": _fnDrawCallBackWithGrouping, + "sName": "fnRowGrouping" + }); + + var aaSortingFixed = new Array(); + aaSortingFixed.push([properties.iGroupingOrderByColumnIndex, properties.sGroupingColumnSortDirection]); + if (properties.iGroupingColumnIndex2 != -1) { + aaSortingFixed.push([properties.iGroupingOrderByColumnIndex2, properties.sGroupingColumnSortDirection2]); + } // end of if (properties.iGroupingColumnIndex2 != -1) + + oTable.fnSettings().aaSortingFixed = aaSortingFixed; + //Old way + //oTable.fnSettings().aaSortingFixed = [[properties.iGroupingOrderByColumnIndex, properties.sGroupingColumnSortDirection]]; + + switch (properties.sGroupBy) { + case "name": + break; + + + case "letter": + + /* Create an array with the values of all the input boxes in a column */ + oTable.fnSettings().aoColumns[properties.iGroupingOrderByColumnIndex].sSortDataType = "rg-letter"; + $.fn.dataTableExt.afnSortData['rg-letter'] = function (oSettings, iColumn) { + var aData = []; + $('td:eq(' + iColumn + ')', oSettings.oApi._fnGetTrNodes(oSettings)).each(function () { + aData.push(_fnGetGroupByLetter(this.innerHTML)); + }); + return aData; + } + + + break; + + + case "year": + /* Create an array with the values of all the input boxes in a column */ + oTable.fnSettings().aoColumns[properties.iGroupingOrderByColumnIndex].sSortDataType = "rg-date"; + $.fn.dataTableExt.afnSortData['rg-date'] = function (oSettings, iColumn) { + var aData = []; + var nTrs = oSettings.oApi._fnGetTrNodes(oSettings); + for(i = 0; i< nTrs.length; i++) + { + aData.push(_fnGetYear( oTable.fnGetData( nTrs[i], iColumn) )); + } + +/* + $('td:eq(' + iColumn + ')', oSettings.oApi._fnGetTrNodes(oSettings)).each(function () { + aData.push(_fnGetYear(this.innerHTML)); + }); +*/ + return aData; + } + break; + default: + break; + + } // end of switch (properties.sGroupBy) + + if(properties.bUseFilteringForGrouping) + $.fn.dataTableExt.afnFiltering.push(_rowGroupingRowFilter); + + oTable.fnDraw(); + + + + }); + }; +})(jQuery); \ No newline at end of file diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css index 20b1207e56..f7678f0804 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css @@ -274,7 +274,7 @@ tr.even td, tr.even.highlight td { border-right : 1px solid #BCBCBC; } -td.od { +.overdue td.od { color : #cc0000; font-weight : bold; } 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 90c4cb2e77..99342016c9 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 @@ - Totals: + Totals: [% totaldue %] [% totalprice %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc new file mode 100644 index 0000000000..e22810ae8b --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc @@ -0,0 +1,30 @@ + diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/checkouts.js b/koha-tmpl/intranet-tmpl/prog/en/js/checkouts.js new file mode 100644 index 0000000000..268eefe777 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/js/checkouts.js @@ -0,0 +1,435 @@ +$(document).ready(function() { + // Handle the select all/none links for checkouts table columns + $("#CheckAllRenewals").on("click",function(){ + $("#UncheckAllCheckins").click(); + $(".renew:visible").attr("checked", "checked" ); + return false; + }); + $("#UncheckAllRenewals").on("click",function(){ + $(".renew:visible").removeAttr("checked"); + return false; + }); + + $("#CheckAllCheckins").on("click",function(){ + $("#UncheckAllRenewals").click(); + $(".checkin:visible").attr("checked", "checked" ); + return false; + }); + $("#UncheckAllCheckins").on("click",function(){ + $(".checkin:visible").removeAttr("checked"); + return false; + }); + + // Don't allow both return and renew checkboxes to be checked + $(document).on("change", '.renew', function(){ + if ( $(this).is(":checked") ) { + $( "#checkin_" + $(this).val() ).removeAttr("checked"); + } + }); + $(document).on("change", '.checkin', function(){ + if ( $(this).is(":checked") ) { + $( "#renew_" + $(this).val() ).removeAttr("checked"); + } + }); + + // Clicking the table cell checks the checkbox inside it + $(document).on("click", 'td', function(e){ + if(e.target.tagName.toLowerCase() == 'td'){ + $(this).find("input:checkbox:visible").each( function() { + $(this).click(); + }); + } + }); + + // Handle renewals and returns + $("#RenewCheckinChecked").on("click",function(){ + $(".checkin:checked:visible").each(function() { + itemnumber = $(this).val(); + + $(this).replaceWith(""); + + params = { + itemnumber: itemnumber, + borrowernumber: borrowernumber, + branchcode: branchcode, + exempt_fine: $("#exemptfine").is(':checked') + }; + + $.post( "/cgi-bin/koha/svc/checkin.pl", params, function( data ) { + id = "#checkin_" + data.itemnumber; + + content = ""; + if ( data.returned ) { + content = CIRCULATION_RETURNED; + } else { + content = CIRCULATION_NOT_RETURNED; + } + + $(id).replaceWith( content ); + }, "json") + }); + + $(".renew:checked:visible").each(function() { + var override_limit = $("#override_limit").is(':checked') ? 1 : 0; + + var itemnumber = $(this).val(); + + $(this).parent().parent().replaceWith(""); + + var params = { + itemnumber: itemnumber, + borrowernumber: borrowernumber, + branchcode: branchcode, + override_limit: override_limit, + date_due: $("#newduedate").val() + }; + + $.post( "/cgi-bin/koha/svc/renew.pl", params, function( data ) { + var id = "#renew_" + data.itemnumber; + + var content = ""; + if ( data.renew_okay ) { + content = CIRCULATION_RENEWED_DUE + " " + data.date_due; + } else { + content = CIRCULATION_RENEW_FAILED + " "; + if ( data.error == "no_checkout" ) { + content += NOT_CHECKED_OUT; + } else if ( data.error == "too_many" ) { + content += TOO_MANY_RENEWALS; + } else if ( data.error == "on_reserve" ) { + content += ON_RESERVE; + } else if ( data.error ) { + content += data.error; + } else { + content += REASON_UNKNOWN; + } + } + + $(id).replaceWith( content ); + }, "json") + }); + + // Prevent form submit + return false; + }); + + $("#RenewAll").on("click",function(){ + $("#CheckAllRenewals").click(); + $("#UncheckAllCheckins").click(); + $("#RenewCheckinChecked").click(); + + // Prevent form submit + return false; + }); + + var ymd = $.datepicker.formatDate('yy-mm-dd', new Date()); + + var issuesTable; + var drawn = 0; + issuesTable = $("#issues-table").dataTable({ + "sDom": "<'row-fluid'<'span6'><'span6'>r>t<'row-fluid'>t", + "aaSorting": [[ 0, "desc" ]], + "aoColumns": [ + { + "mDataProp": function( oObj ) { + if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { + return "" + TODAYS_CHECKOUTS + ""; + } else { + return "" + PREVIOUS_CHECKOUTS + ""; + } + } + }, + { + "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; + + $.each(oObj.subtitle, function( index, value ) { + title += " " + value.subfield; + }); + + title += ""; + + if ( oObj.author ) { + title += " " + BY + " " + oObj.author; + } + + if ( oObj.itemnotes ) { + var span_class = ""; + if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { + span_class = "circ-hlt"; + } + title += " - " + oObj.itemnotes + "" + } + + title += " " + + "" + + oObj.barcode + + ""; + + return title; + } + }, + { "mDataProp": "itemtype" }, + { "mDataProp": "issuedate" }, + { "mDataProp": "branchname" }, + { "mDataProp": "itemcallnumber" }, + { + "bSortable": false, + "mDataProp": function ( oObj ) { + return parseFloat(oObj.charge).toFixed(2); + } + }, + { + "bSortable": false, + "mDataProp": "price" }, + { + "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 { + content += "" + + oObj.can_renew_error + + ""; + + span_style = "display: none"; + span_class = "renewals-allowed"; + } + + content += "" + + "" + + ""; + + if ( oObj.renewals_remaining ) { + content += "(" + + oObj.renewals_remaining + + " " + OF + " " + + oObj.renewals_allowed + " " + + RENEWALS_REMAINING + ")"; + } + + 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); + }, + "bPaginate": false, + "bProcessing": true, + "bServerSide": false, + "sAjaxSource": '/cgi-bin/koha/svc/checkouts.pl', + "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( + { + iGroupingOrderByColumnIndex: 0, + sGroupingColumnSortDirection: "desc" + } + ); + + if ( $("#issues-table").length ) { + $("#issues-table_processing").position({ + of: $( "#issues-table" ), + collision: "none" + }); + } + + // Don't load relatives' issues table unless it is clicked on + var relativesIssuesTable; + $("#relatives-issues-tab").click( function() { + if ( ! relativesIssuesTable ) { + relativesIssuesTable = $("#relatives-issues-table").dataTable({ + "sDom": "<'row-fluid'<'span6'><'span6'>r>t<'row-fluid'>t", + "aaSorting": [], + "aoColumns": [ + { + "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; + + $.each(oObj.subtitle, function( index, value ) { + title += " " + value.subfield; + }); + + title += ""; + + if ( oObj.author ) { + title += " " + BY + " " + oObj.author; + } + + if ( oObj.itemnotes ) { + var span_class = ""; + if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { + span_class = "circ-hlt"; + } + title += " - " + oObj.itemnotes + "" + } + + title += " " + + "" + + oObj.barcode + + ""; + + return title; + } + }, + { "mDataProp": "itemtype" }, + { "mDataProp": "issuedate" }, + { "mDataProp": "branchname" }, + { "mDataProp": "itemcallnumber" }, + { "mDataProp": "charge" }, + { "mDataProp": "price" }, + { + "mDataProp": function( oObj ) { + return "" + + oObj.borrower.firstname + " " + oObj.borrower.surname + " (" + oObj.borrower.cardnumber + ")" + } + }, + ], + "bPaginate": false, + "bProcessing": true, + "bServerSide": true, + "sAjaxSource": '/cgi-bin/koha/svc/checkouts.pl', + "fnServerData": function ( sSource, aoData, fnCallback ) { + $.each(relatives_borrowernumbers, function( index, value ) { + aoData.push( { "name": "borrowernumber", "value": value } ); + }); + + $.getJSON( sSource, aoData, function (json) { + fnCallback(json) + } ); + }, + }); + } + }); + + if ( $("#relatives-issues-table").length ) { + $("#relatives-issues-table_processing").position({ + of: $( "#relatives-issues-table" ), + collision: "none" + }); + } + + if ( AllowRenewalLimitOverride ) { + $( '#override_limit' ).click( function () { + if ( this.checked ) { + $( '.renewals-allowed' ).show(); $( '.renewals-disabled' ).hide(); + } else { + $( '.renewals-allowed' ).hide(); $( '.renewals-disabled' ).show(); + } + } ).attr( 'checked', false ); + } + }); diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/holds.js b/koha-tmpl/intranet-tmpl/prog/en/js/holds.js new file mode 100644 index 0000000000..76dfee55fc --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/js/holds.js @@ -0,0 +1,133 @@ +$(document).ready(function() { + // Don't load holds table unless it is clicked on + var holdsTable; + $("#holds-tab").click( function() { + if ( ! holdsTable ) { + holdsTable = $("#holds-table").dataTable({ + "sDom": "<'row-fluid'<'span6'><'span6'>r>t<'row-fluid'>t", + "aoColumns": [ + { + "mDataProp": "reservedate_formatted" + }, + { + "mDataProp": function ( oObj ) { + title = "" + + oObj.title; + + $.each(oObj.subtitle, function( index, value ) { + title += " " + value.subfield; + }); + + title += ""; + + if ( oObj.author ) { + title += " " + BY + " " + oObj.author; + } + + if ( oObj.itemnotes ) { + var span_class = ""; + if ( $.datepicker.formatDate('yy-mm-dd', new Date(oObj.issuedate) ) == ymd ) { + span_class = "circ-hlt"; + } + title += " - " + oObj.itemnotes + "" + } + + title += " " + + "" + + oObj.barcode + + ""; + + return title; + } + }, + { + "mDataProp": function( oObj ) { + return oObj.itemcallnumber || ""; + } + }, + { + "mDataProp": function( oObj ) { + var data = ""; + + if ( oObj.suspend == 1 ) { + data += "

" + HOLD_IS + " " + SUSPENDED + " "; + if ( oObj.suspend_until ) { + data += " " + UNTIL + " " + oObj.suspend_until_formatted; + } + data += "

"; + } + + if ( oObj.barcode ) { + data += ""; + if ( oObj.found == "W" ) { + data += ITEM_IS + " " + WAITING + " "; + + if ( ! oObj.waiting_here ) { + data += " " + AT + " " + oObj.waiting_at; + } + } else if ( oObj.transferred ) { + data += ITEM_IS + " " + IN_TRANSIT + " " + FROM + oObj.from_branch; + } else if ( oObj.not_transferred ) { + data += NOT_TRANSFERRED_YET + " " + oObj.not_transferred_by; + } data += ""; + + data += " " + oObj.barcode + ""; + } + + return data; + } + }, + { "mDataProp": "expirationdate_formatted" }, + { + "mDataProp": function( oObj ) { + if ( oObj.priority && parseInt( oObj.priority ) && parseInt( oObj.priority ) > 0 ) { + return oObj.priority; + } else { + return ""; + } + } + }, + { + "mDataProp": function( oObj ) { + return "" + + "" + + "" + + ""; + } + } + ], + "bPaginate": false, + "bProcessing": true, + "bServerSide": true, + "sAjaxSource": '/cgi-bin/koha/svc/holds.pl', + "fnServerData": function ( sSource, aoData, fnCallback ) { + aoData.push( { "name": "borrowernumber", "value": borrowernumber } ); + + $.getJSON( sSource, aoData, function (json) { + fnCallback(json) + } ); + }, + }); + + if ( $("#holds-table").length ) { + $("#holds-table_processing").position({ + of: $( "#holds-table" ), + collision: "none" + }); + } + } + }); + +}); diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/pages/circulation.js b/koha-tmpl/intranet-tmpl/prog/en/js/pages/circulation.js index fe307bf22f..489403f10a 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/js/pages/circulation.js +++ b/koha-tmpl/intranet-tmpl/prog/en/js/pages/circulation.js @@ -1,57 +1,22 @@ $(document).ready(function() { - $('#patronlists').tabs(); - var allcheckboxes = $(".checkboxed"); - $("#renew_all").on("click",function(){ - allcheckboxes.checkCheckboxes(":input[name*=items]"); - allcheckboxes.unCheckCheckboxes(":input[name*=barcodes]"); - }); - $("#CheckAllitems").on("click",function(){ - allcheckboxes.checkCheckboxes(":input[name*=items]"); - allcheckboxes.unCheckCheckboxes(":input[name*=barcodes]"); return false; - }); - $("#CheckNoitems").on("click",function(){ - allcheckboxes.unCheckCheckboxes(":input[name*=items]"); return false; - }); - $("#CheckAllreturns").on("click",function(){ - allcheckboxes.checkCheckboxes(":input[name*=barcodes]"); - allcheckboxes.unCheckCheckboxes(":input[name*=items]"); return false; - }); - $("#CheckNoreturns" ).on("click",function(){ - allcheckboxes.unCheckCheckboxes(":input[name*=barcodes]"); return false; - }); - - $("#CheckAllexports").on("click",function(){ - allcheckboxes.checkCheckboxes(":input[name*=biblionumbers]"); + $("#CheckAllExports").on("click",function(){ + $(".export:visible").attr("checked", "checked" ); return false; }); - $("#CheckNoexports").on("click",function(){ - allcheckboxes.unCheckCheckboxes(":input[name*=biblionumbers]"); + $("#UncheckAllExports").on("click",function(){ + $(".export:visible").removeAttr("checked"); return false; }); - $("#relrenew_all").on("click",function(){ - allcheckboxes.checkCheckboxes(":input[name*=items]"); - allcheckboxes.unCheckCheckboxes(":input[name*=barcodes]"); - }); - $("#relCheckAllitems").on("click",function(){ - allcheckboxes.checkCheckboxes(":input[name*=items]"); - allcheckboxes.unCheckCheckboxes(":input[name*=barcodes]"); return false; - }); - $("#relCheckNoitems").on("click",function(){ - allcheckboxes.unCheckCheckboxes(":input[name*=items]"); return false; - }); - $("#relCheckAllreturns").on("click",function(){ - allcheckboxes.checkCheckboxes(":input[name*=barcodes]"); - allcheckboxes.unCheckCheckboxes(":input[name*=items]"); return false; - }); - $("#relCheckNoreturns").on("click",function(){ - allcheckboxes.unCheckCheckboxes(":input[name*=barcodes]"); return false; - }); + $('#patronlists').tabs(); + $("#messages ul").after(""+MSG_ADD_MESSAGE+""); + $("#borrower_messages .cancel").on("click",function(){ $("#add_message_form").hide(); $("#addmessage").show(); }); + $("#addmessage").on("click",function(){ $(this).hide(); $("#add_message_form").show(); @@ -76,14 +41,7 @@ $(document).ready(function() { export_checkouts(export_format); return false; }); - // Clicking the table cell checks the checkbox inside it - $("td").on("click",function(e){ - if(e.target.tagName.toLowerCase() == 'td'){ - $(this).find("input:checkbox:visible").each( function() { - $(this).click(); - }); - } - }); + }); function export_checkouts(format) { @@ -107,13 +65,9 @@ function export_checkouts(format) { } else if (format == 'iso2709') { $("#dont_export_item").val(1); } - document.issues.action="/cgi-bin/koha/tools/export.pl"; + document.getElementById("export_format").value = format; document.issues.submit(); - - /* Reset form action to its initial value */ - document.issues.action="/cgi-bin/koha/reserve/renewscript.pl"; - } function validate1(date) { @@ -124,10 +78,3 @@ function validate1(date) { return false; } } - -// prevent adjacent checkboxes from being checked simultaneously -function radioCheckBox(box){ - box.parents("td").siblings().find("input:checkbox.radio").each(function(){ - $(this).removeAttr("checked"); - }); - } 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 5a768a6682..55d8a7852e 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 @@ -39,12 +39,6 @@ Circulation: asc: earliest to latest desc: latest to earliest - due date. - - - - pref: UseTablesortForCirc - choices: - yes: "Enable" - no: "Don't enable" - - "the sorting of current patron checkouts on the circulation screen.
NOTE: Enabling this function may slow down circulation time for patrons with many checkouts." - - pref: soundon 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 75e05b390d..9951030b3a 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/circulation.tt @@ -13,90 +13,46 @@ [% INCLUDE 'doc-head-close.inc' %] [% INCLUDE 'calendar.inc' %] -[% IF ( UseTablesortForCirc ) %] -[% INCLUDE 'datatables.inc' %][% END %] + + +[% INCLUDE 'datatables.inc' %] +[% INCLUDE 'strings.inc' %] [% INCLUDE 'timepicker.inc' %] + + + @@ -527,7 +483,7 @@ No patron matched [% message %] [% ELSE %] [% END %] - + [% IF ( SpecifyDueDate ) %]
Specify due date [% INCLUDE 'date-format.inc' %]:
@@ -539,7 +495,7 @@ No patron matched [% message %] [% ELSE %] [% END %] - +
[% END %] @@ -698,399 +654,111 @@ No patron matched [% message %]
- - -
-[% IF ( issuecount ) %] -
- - - - - - - - - - - - - - - - - [% IF ( exports_enabled ) %] - [% END %] - -[% IF ( todayissues ) %] -[% INCLUDE 'checkouts-table-footer.inc' %] - - - [% FOREACH todayissue IN todayissues %] - [% IF ( loop.odd ) %] - - [% ELSE %] - - [% END %] - [% IF ( todayissue.od ) %] - - - - [% IF ( todayissue.multiple_borrowers ) %][% END %] - - - - - [% IF ( todayissue.renew_failed ) %] - - [% ELSE %] - - [% END %] - [% IF ( todayissue.return_failed ) %] - - [% ELSE %] - [% IF ( todayissue.renew_error_on_reserve ) %] - - [% ELSE %] - - [% END %] - [% END %] - [% IF ( exports_enabled ) %] - - [% END %] - - [% END %] - [% END %] - -[% IF ( previssues ) %] - [% UNLESS ( todayissues ) %] - [% INCLUDE 'checkouts-table-footer.inc' %] - - [% END %] - [% IF ( UseTablesortForCirc ) %][% IF ( exports_enabled ) %][% END %][% ELSE %][% IF ( exports_enabled ) %][% END %] - [% FOREACH previssue IN previssues %] - [% IF ( loop.odd ) %] - - [% ELSE %] - + [% IF relatives_issues_count %] +
  • Relatives' checkouts
  • [% END %] - [% IF ( previssue.od ) %] - - - - [% IF ( previssue.multiple_borrowers ) %][% END %] - - - - - [% IF ( previssue.renew_failed ) %] - - [% ELSE %] - - [% END %] - [% IF ( previssue.return_failed ) %] - +
  • + [% IF ( holds_count ) %] + [% holds_count %] Hold(s) [% ELSE %] - [% IF ( previssue.renew_error_on_reserve ) %] -
  • - [% ELSE %] - - [% END %] - [% END %] - [% IF ( exports_enabled ) %] - - [% END %] - - [% END %] -[% END %] - -
    Due dateTitleItem typeChecked out onChecked out fromCall noChargePriceRenew

    select all | none

    Check in

    select all | none

    Export

    select all | none

    [% ELSE %][% END %] - [% todayissue.dd %] + - [% IF ( todayissue.itemlost ) %] - [% AuthorisedValues.GetByCode( 'LOST', todayissue.itemlost ) %] - [% END %] - [% IF ( todayissue.damaged ) %] - [% AuthorisedValues.GetByCode( 'DAMAGED', todayissue.damaged ) %] - [% END %] - [% todayissue.title |html %][% FOREACH subtitl IN todayissue.subtitle %] [% subtitl.subfield %][% END %][% IF ( todayissue.author ) %], by [% todayissue.author %][% END %][% IF ( todayissue.itemnotes ) %]- [% todayissue.itemnotes %][% END %] [% todayissue.barcode %][% UNLESS ( noItemTypeImages ) %] [% IF ( todayissue.itemtype_image ) %][% END %][% END %][% todayissue.itemtype %][% todayissue.checkoutdate %][% todayissue.firstname %] [% todayissue.surname %][% todayissue.issuingbranchname %][% todayissue.itemcallnumber %][% todayissue.charge %][% todayissue.replacementprice %]Renewal failed[% IF ( todayissue.renewals ) %][% todayissue.renewals %][% ELSE %]0[% END %] - [% IF ( todayissue.can_renew ) %] - - [% IF ( todayissue.od ) %] - - [% ELSE %] - - [% END %] - [% IF todayissue.renewsallowed && todayissue.renewsleft %] - ([% todayissue.renewsleft %] of [% todayissue.renewsallowed %] renewals remaining) - [% END %] - [% ELSE %] - [% IF ( todayissue.can_confirm ) %] - [% IF todayissue.renewsallowed && todayissue.renewsleft && !todayissue.renew_error_too_soon %] - ([% todayissue.renewsleft %] of [% todayissue.renewsallowed %] renewals remaining) - [% END %] - - [% END %] - [% IF ( todayissue.renew_error_on_reserve ) %] - On hold - [% ELSIF ( todayissue.renew_error_too_many ) %] - Not renewable - [% ELSIF ( todayissue.renew_error_too_soon ) %] - No renewal before [% todayissue.soonestrenewdate %] - ([% todayissue.renewsleft %] of [% todayissue.renewsallowed %] renewals remaining) - [% END %] - [% IF ( todayissue.can_confirm ) %] - - [% END %] - [% END %] - Checkin failedOn hold - - - - - - -
    Previous checkouts
    [% ELSE %][% END %]Previous checkouts
    [% ELSE %][% END %] - [% previssue.dd %] - [% IF ( previssue.itemlost ) %] - [% AuthorisedValues.GetByCode( 'LOST', previssue.itemlost ) %] - [% END %] - [% IF ( previssue.damaged ) %] - [% AuthorisedValues.GetByCode( 'DAMAGED', previssue.damaged ) %] - [% END %] - [% previssue.title |html %][% FOREACH subtitl IN previssue.subtitle %] [% subtitl.subfield %][% END %][% IF ( previssue.author ) %], by [% previssue.author %][% END %] [% IF ( previssue.itemnotes ) %]- [% previssue.itemnotes %][% END %] [% previssue.barcode %] - [% previssue.itemtype %] - [% previssue.displaydate %][% previssue.firstname %] [% previssue.surname %][% previssue.issuingbranchname %][% previssue.itemcallnumber %][% previssue.charge %][% previssue.replacementprice %]Renewal failed[% IF ( previssue.renewals ) %][% previssue.renewals %][% ELSE %]0[% END %] - [% IF ( previssue.can_renew ) %] - - [% IF ( previssue.od ) %] - - [% ELSE %] - - [% END %] - [% IF previssue.renewsallowed && previssue.renewsleft %] - ([% previssue.renewsleft %] of [% previssue.renewsallowed %] renewals remaining) - [% END %] - [% ELSE %] - [% IF ( previssue.can_confirm ) %] - [% IF previssue.renewsallowed && previssue.renewsleft && !previssue.renew_error_too_soon %] - ([% previssue.renewsleft %] of [% previssue.renewsallowed %] renewals remaining) - [% END %] - - [% END %] - [% IF ( previssue.renew_error_on_reserve ) %] - On Hold - [% ELSIF ( previssue.renew_error_too_many ) %] - Not renewable - [% ELSIF ( previssue.renew_error_too_soon ) %] - No renewal before [% previssue.soonestrenewdate %] - ([% previssue.renewsleft %] of [% previssue.renewsallowed %] renewals remaining) - [% END %] - [% IF ( previssue.can_confirm ) %] - - [% END %] - [% END %] - Check-in failedOn hold - - - - - - -
    - [% IF ( issuecount ) %] -
    - [% IF ( CAN_user_circulate_override_renewals ) %] - [% IF ( AllowRenewalLimitOverride ) %] - - - [% END %] - [% END %] - - -
    - [% IF ( exports_enabled ) %] -
    - - - - - - - - -
    + 0 Holds [% END %] - [% END %] -
    -[% ELSE %] -

    Patron has nothing checked out.

    -[% END %] - -
    - + -[% IF ( displayrelissues ) %] -
    - - - - - - - - - - - - - - -[% IF ( relissues ) %] - - [% FOREACH relissue IN relissues %] - [% IF ( loop.odd ) %] - - [% ELSE %] - - [% END %] - [% IF ( relissue.overdue ) %] +
  • [% debarments.size %] Restrictions
  • + - [% IF ( relissue.itemlost ) %] - [% AuthorisedValues.GetByCode( 'LOST', relissue.itemlost ) %] - [% END %] - [% IF ( relissue.damaged ) %] - [% AuthorisedValues.GetByCode( 'DAMAGED', relissue.damaged ) %] + +
    + [% IF ( issuecount ) %] +
    Due dateTitleItem typeChecked out onChecked out fromCall noChargePricePatron
    [% ELSE %][% END %] - [% relissue.dd %]
    + + + + + + + + + + + + + + + + + + [% INCLUDE 'checkouts-table-footer.inc' %] +
     Due dateDue dateTitleItem typeChecked out onChecked out fromCall noChargePriceRenew

    select all | none

    Check in

    select all | none

    Export

    select all | none

    + +
    + [% IF ( CAN_user_circulate_override_renewals ) %] + [% IF ( AllowRenewalLimitOverride ) %] + + + [% END %] [% END %] - - [% relissue.title |html %][% FOREACH subtitl IN relissue.subtitle %] [% subtitl.subfield %][% END %][% IF ( relissue.author ) %], by [% relissue.author %][% END %][% IF ( relissue.itemnotes ) %]- [% relissue.itemnotes %][% END %] [% relissue.barcode %] - [% UNLESS ( noItemTypeImages ) %] [% IF ( relissue.itemtype_image ) %][% END %][% END %][% relissue.itemtype %] - [% relissue.displaydate %] - [% relissue.issuingbranchname %] - [% relissue.itemcallnumber %] - [% relissue.charge %] - [% relissue.replacementprice %][% relissue.firstname %] [% relissue.surname %] ([% relissue.cardnumber %]) - - [% END %] - [% END %] -[% IF ( relprevissues ) %] - [% IF ( UseTablesortForCirc ) %]Previous checkouts[% ELSE %]Previous checkouts[% END %] - [% FOREACH relprevissue IN relprevissues %] - [% IF ( loop.odd ) %] - + + +
    [% ELSE %] - +

    Patron has nothing checked out.

    [% END %] - [% IF ( relprevissue.overdue ) %][% ELSE %][% END %] - [% relprevissue.dd %] - - [% relprevissue.title |html %][% FOREACH subtitl IN relprevissue.subtitle %] [% subtitl.subfield %][% END %][% IF ( relprevissue.author ) %], by [% relprevissue.author %][% END %] [% IF ( relprevissue.itemnotes ) %]- [% relprevissue.itemnotes %][% END %] [% relprevissue.barcode %] - [% UNLESS noItemTypeImages %][% IF relprevissue.itemtype_image %][% END %][% END %][% relprevissue.itemtype %] - [% relprevissue.displaydate %] - [% relprevissue.issuingbranchname %] - [% relprevissue.itemcallnumber %] - [% IF ( relprevissue.multiple_borrowers ) %][% relprevissue.firstname %] [% relprevissue.surname %][% END %] - [% relprevissue.charge %] - [% relprevissue.replacementprice %] - [% relprevissue.firstname %] [% relprevissue.surname %] ([% relprevissue.cardnumber %]) - - - [% END %] -[% END %] - - -
    -[% END %] + +[% IF ( relatives_issues_count ) %] +
    + + + + + + + + + + + + + + +
    Due dateTitleItem typeChecked out onChecked out fromCall noChargePricePatron
    +
    +[% END %] [% INCLUDE borrower_debarments.inc %]
    -[% IF ( reservloop ) %] +[% IF ( holds_count ) %]
    - - - - - - - - - - - - - - [% FOREACH reservloo IN reservloop %] - - - - - - - - - - - [% END %] -
    Hold dateTitleCall numberBarcodeExpirationPriorityDelete? 
    [% reservloo.reservedate %][% reservloo.title |html %][% FOREACH subtitl IN reservloo.subtitle %] [% subtitl.subfield %][% END %][% IF ( reservloo.author ) %], by [% reservloo.author %][% END %][% reservloo.itemcallnumber %][% IF ( reservloo.barcodereserv ) %]Item [% reservloo.barcodereserv %] - [% END %][% IF ( reservloo.waiting ) %] waiting at [% reservloo.waitingat %] - [% END %] - [% IF ( reservloo.transfered ) %] in transit from - [% reservloo.frombranch %] since [% reservloo.datesent %] - [% END %] - [% IF ( reservloo.nottransfered ) %] hasn't been transferred yet from [% reservloo.nottransferedby %] - [% END %][% reservloo.expirationdate | $KohaDates %] - [% IF ( reservloo.waitingposition ) %] [% reservloo.waitingposition %] [% END %] - - - - - [% IF ( reservloo.suspend ) %]Suspended [% IF ( reservloo.suspend_until ) %] until [% reservloo.suspend_until | $KohaDates %][% END %][% END %]
    -
    + + + + + + + + + + + + + +
    Hold dateTitleCall numberBarcodeExpirationPriorityDelete?
    + +
    + +
    [% IF SuspendHoldsIntranet %] 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 345c728d49..3c9b678f84 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/moremember.tt @@ -9,13 +9,29 @@ [% INCLUDE 'doc-head-close.inc' %] [% INCLUDE 'calendar.inc' %] - + [% INCLUDE 'datatables.inc' %] - +[% INCLUDE 'strings.inc' %] + [% INCLUDE 'timepicker.inc' %] + + +