Bugzilla – Attachment 29472 Details for
Bug 11703
Convert checkouts table to ajax datatable
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 11703 - Convert checkouts table to ajax datatable
Bug-11703---Convert-checkouts-table-to-ajax-datata.patch (text/plain), 169.87 KB, created by
Kyle M Hall (khall)
on 2014-07-03 13:35:55 UTC
(
hide
)
Description:
Bug 11703 - Convert checkouts table to ajax datatable
Filename:
MIME Type:
Creator:
Kyle M Hall (khall)
Created:
2014-07-03 13:35:55 UTC
Size:
169.87 KB
patch
obsolete
>From db4a8e17223a7f9c504314321a79c0d4371da3b2 Mon Sep 17 00:00:00 2001 >From: Kyle M Hall <kyle@bywatersolutions.com> >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 <dpavlin@rot13.org> >Signed-off-by: Katrin Fischer <Katrin.Fischer.83@web.de> >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 <jonathan.druart@biblibre.com> > >Signed-off-by: Christopher Brannon <cbrannon@cdalibrary.org> >--- > 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 ++++++++++++++++++++ > .../intranet-tmpl/prog/en/css/staff-global.css | 2 +- > .../prog/en/includes/checkouts-table-footer.inc | 2 +- > .../intranet-tmpl/prog/en/includes/strings.inc | 30 + > koha-tmpl/intranet-tmpl/prog/en/js/checkouts.js | 435 ++++++++++++ > koha-tmpl/intranet-tmpl/prog/en/js/holds.js | 133 ++++ > .../intranet-tmpl/prog/en/js/pages/circulation.js | 73 +-- > .../en/modules/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 282c802..e1838b6 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 527651d..184a854 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 91851d2..81737ee 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 d41ef74..ed427ea 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 0000000..126ff63 >--- /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) { >+ ///<summary> >+ ///Function called when a new grouping row is created(it should be overriden in properties) >+ ///</summary> >+ } >+ >+ function _fnOnGroupCompleted(oGroup, sGroup, iLevel) { >+ ///<summary> >+ ///Function called when a new grouping row is created(it should be overriden in properties) >+ ///</summary> >+ } >+ >+ 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) { >+ ///<summary>Used to expand/collapse groups with DataTables filtering</summary> >+ 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) { >+ ///<summary>Expand group if expanadable grouping is used</summary> >+ >+ 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) { >+ ///<summary>Collapse group if expanadable grouping is used</summary> >+ >+ 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) { >+ ///<summary> >+ ///Function that is called when user click on the group cell in order to >+ ///expand of collapse group >+ ///</summary> >+ >+ //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 20b1207..f7678f0 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 90c4cb2..9934201 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="6" style="text-align: right; font-weight:bold;">Totals:</td> >+ <td colspan="8" style="text-align: right; font-weight:bold;">Totals:</td> > <td>[% totaldue %]</td> > <td>[% totalprice %]</td> > <td colspan="3"><div class="date-select"> >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 0000000..e22810a >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/strings.inc >@@ -0,0 +1,30 @@ >+<script type="text/javascript"> >+//<![CDATA[ >+ var CIRCULATION_RETURNED = _("Returned"); >+ var CIRCULATION_NOT_RETURNED = _("Unable to return"); >+ var CIRCULATION_RENEWED_DUE = _("Renewed, due:"); >+ var CIRCULATION_RENEW_FAILED = _("Renew failed:") >+ var NOT_CHECKED_OUT = _("not checked out"); >+ var TOO_MANY_RENEWALS = _("too many renewals"); >+ var ON_RESERVE = _("on reserve"); >+ var REASON_UNKNOWN = _("reason unkown"); >+ var TODAYS_CHECKOUTS = _("Today's checkouts"); >+ var PREVIOUS_CHECKOUTS = _("Previous checkouts"); >+ var BY = _("by"); >+ var ON_HOLD = _("On hold"); >+ var NOT_RENEWABLE = _("Not renewable"); >+ var OF = _("of"); >+ var RENEWALS_REMAINING = _("renewals remaining"); >+ var HOLD_IS = _("Hold is"); >+ var SUSPENDED = _("suspended"); >+ var UNTIL = _("until"); >+ var ITEM_IS = _("Item is"); >+ var WAITING = _("waiting"); >+ var AT = _("at"); >+ var IN_TRANSIT = _("in transit"); >+ var FROM = _("from"); >+ var NOT_TRANSFERRED_YET = _("Item hasn't been transferred yet from"); >+ var NO = _("No"); >+ var YES = _("Yes"); >+//]]> >+</script> >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 0000000..268eefe >--- /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("<img id='checkin_" + itemnumber + "' src='" + interface + "/" + theme + "/img/loading-small.gif' />"); >+ >+ 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("<img id='renew_" + itemnumber + "' src='" + interface + "/" + theme + "/img/loading-small.gif' />"); >+ >+ 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 "<strong>" + TODAYS_CHECKOUTS + "</strong>"; >+ } else { >+ return "<strong>" + PREVIOUS_CHECKOUTS + "</strong>"; >+ } >+ } >+ }, >+ { >+ "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 "<span class='overdue'>" + oObj.date_due_formatted + "</span>"; >+ } else { >+ return oObj.date_due_formatted; >+ } >+ } >+ }, >+ { >+ "mDataProp": function ( oObj ) { >+ title = "<a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber=" >+ + oObj.biblionumber >+ + "'>" >+ + oObj.title; >+ >+ $.each(oObj.subtitle, function( index, value ) { >+ title += " " + value.subfield; >+ }); >+ >+ title += "</a>"; >+ >+ 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 += " - <span class='" + span_class + "'>" + oObj.itemnotes + "</span>" >+ } >+ >+ title += " " >+ + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=" >+ + oObj.biblionumber >+ + "&itemnumber=" >+ + oObj.itemnumber >+ + "#" >+ + oObj.itemnumber >+ + "'>" >+ + oObj.barcode >+ + "</a>"; >+ >+ 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 += "<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'>" >+ + "<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 { >+ content += "<span class='renewals-disabled'>" >+ + oObj.can_renew_error >+ + "</span>"; >+ >+ span_style = "display: none"; >+ span_class = "renewals-allowed"; >+ } >+ >+ content += "<span class='" + span_class + "' style='" + span_style + "'>" >+ + "<input type='checkbox' class='renew' id='renew_" + oObj.itemnumber + "' name='renew' value='" + oObj.itemnumber +"'/>" >+ + "</span>"; >+ >+ if ( oObj.renewals_remaining ) { >+ content += "<span class='renewals'>(" >+ + oObj.renewals_remaining >+ + " " + OF + " " >+ + oObj.renewals_allowed + " " >+ + RENEWALS_REMAINING + ")</span>"; >+ } >+ >+ content += "</span>"; >+ >+ >+ return content; >+ } >+ }, >+ { >+ "bSortable": 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>"; >+ } >+ } >+ }, >+ { >+ "bVisible": exports_enabled ? true : false, >+ "bSortable": false, >+ "mDataProp": function ( oObj ) { >+ return "<input type='checkbox' class='export' id='export_" + oObj.biblionumber + "' name='biblionumbers' value='" + oObj.biblionumber + "' />"; >+ } >+ } >+ ], >+ "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 "<span class='overdue'>" + oObj.date_due_formatted + "</span>"; >+ } else { >+ return oObj.date_due_formatted; >+ } >+ } >+ }, >+ { >+ "mDataProp": function ( oObj ) { >+ title = "<a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber=" >+ + oObj.biblionumber >+ + "'>" >+ + oObj.title; >+ >+ $.each(oObj.subtitle, function( index, value ) { >+ title += " " + value.subfield; >+ }); >+ >+ title += "</a>"; >+ >+ 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 += " - <span class='" + span_class + "'>" + oObj.itemnotes + "</span>" >+ } >+ >+ title += " " >+ + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=" >+ + oObj.biblionumber >+ + "&itemnumber=" >+ + oObj.itemnumber >+ + "#" >+ + oObj.itemnumber >+ + "'>" >+ + oObj.barcode >+ + "</a>"; >+ >+ return title; >+ } >+ }, >+ { "mDataProp": "itemtype" }, >+ { "mDataProp": "issuedate" }, >+ { "mDataProp": "branchname" }, >+ { "mDataProp": "itemcallnumber" }, >+ { "mDataProp": "charge" }, >+ { "mDataProp": "price" }, >+ { >+ "mDataProp": function( oObj ) { >+ return "<a href='/cgi-bin/koha/members/moremember.pl?borrowernumber=" + oObj.borrowernumber + "'>" >+ + oObj.borrower.firstname + " " + oObj.borrower.surname + " (" + oObj.borrower.cardnumber + ")</a>" >+ } >+ }, >+ ], >+ "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 0000000..76dfee5 >--- /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 = "<a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber=" >+ + oObj.biblionumber >+ + "'>" >+ + oObj.title; >+ >+ $.each(oObj.subtitle, function( index, value ) { >+ title += " " + value.subfield; >+ }); >+ >+ title += "</a>"; >+ >+ 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 += " - <span class='" + span_class + "'>" + oObj.itemnotes + "</span>" >+ } >+ >+ title += " " >+ + "<a href='/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=" >+ + oObj.biblionumber >+ + "&itemnumber=" >+ + oObj.itemnumber >+ + "#" >+ + oObj.itemnumber >+ + "'>" >+ + oObj.barcode >+ + "</a>"; >+ >+ return title; >+ } >+ }, >+ { >+ "mDataProp": function( oObj ) { >+ return oObj.itemcallnumber || ""; >+ } >+ }, >+ { >+ "mDataProp": function( oObj ) { >+ var data = ""; >+ >+ if ( oObj.suspend == 1 ) { >+ data += "<p>" + HOLD_IS + " <strong> " + SUSPENDED + " </strong>"; >+ if ( oObj.suspend_until ) { >+ data += " " + UNTIL + " " + oObj.suspend_until_formatted; >+ } >+ data += "</p>"; >+ } >+ >+ if ( oObj.barcode ) { >+ data += "<em>"; >+ if ( oObj.found == "W" ) { >+ data += ITEM_IS + " <strong> " + WAITING + " </strong>"; >+ >+ if ( ! oObj.waiting_here ) { >+ data += " " + AT + " " + oObj.waiting_at; >+ } >+ } else if ( oObj.transferred ) { >+ data += ITEM_IS + " <strong> " + IN_TRANSIT + " </strong> " + FROM + oObj.from_branch; >+ } else if ( oObj.not_transferred ) { >+ data += NOT_TRANSFERRED_YET + " " + oObj.not_transferred_by; >+ } data += "</em>"; >+ >+ data += " <a href='/cgi-bin/koha/catalogue/detail.pl?biblionumber=" >+ + oObj.biblionumber + "'>" + oObj.barcode + "</a>"; >+ } >+ >+ 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 "<select name='rank-request'>" >+ + "<option value='n'>" + NO + "</option>" >+ + "<option value='del'>" + YES + "</option>" >+ + "</select>" >+ + "<input type='hidden' name='biblionumber' value='" + oObj.biblionumber + "'>" >+ + "<input type='hidden' name='borrowernumber' value='" + borrowernumber + "'>" >+ + "<input type='hidden' name='reserve_id' value='" + oObj.reserve_id + "'>"; >+ } >+ } >+ ], >+ "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 fe307bf..489403f 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("<a href=\"#\" id=\"addmessage\">"+MSG_ADD_MESSAGE+"</a>"); >+ > $("#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 5a768a6..55d8a78 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 >@@ -40,12 +40,6 @@ Circulation: > 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. <br/>NOTE: Enabling this function may slow down circulation time for patrons with many checkouts." >- - > - pref: soundon > choices: > yes: "Enable" >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 75e05b3..9951030 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 @@ > </title> > [% INCLUDE 'doc-head-close.inc' %] > [% INCLUDE 'calendar.inc' %] >-[% IF ( UseTablesortForCirc ) %]<link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" /> >-[% INCLUDE 'datatables.inc' %][% END %] >+ >+<link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" /> >+[% INCLUDE 'datatables.inc' %] > <script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.checkboxes.min.js"></script> >+[% INCLUDE 'strings.inc' %] > <script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery-ui-timepicker-addon.min.js"></script> > [% INCLUDE 'timepicker.inc' %] >+<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.dataTables.rowGrouping.js"></script> > <script type="text/javascript" src="[% themelang %]/js/pages/circulation.js"></script> >+<script type="text/javascript" src="[% themelang %]/js/checkouts.js"></script> >+<script type="text/javascript" src="[% themelang %]/js/holds.js"></script> > <script type="text/javascript"> > //<![CDATA[ >+/* Set some variable needed in circulation.js */ >+var interface = "[% interface %]"; >+var theme = "[% theme %]"; >+var borrowernumber = "[% borrowernumber %]"; >+var branchcode = "[% branch %]"; >+var exports_enabled = "[% exports_enabled %]"; >+var AllowRenewalLimitOverride = [% CAN_user_circulate_override_renewals && AllowRenewalLimitOverride %]; >+var relatives_borrowernumbers = new Array(); >+[% FOREACH b IN relatives_borrowernumbers %] >+ relatives_borrowernumbers.push("[% b %]"); >+[% END %] >+ > var MSG_ADD_MESSAGE = _("Add a new message"); > var MSG_EXPORT_SELECT_CHECKOUTS = _("You must select checkout(s) to export"); > [% IF ( borrowernumber ) %]if($.cookie("holdfor") != [% borrowernumber %]){ $.cookie("holdfor",null, { path: "/", expires: 0 }); }[% ELSE %]$.cookie("holdfor",null, { path: "/", expires: 0 });[% END %] > [% UNLESS ( borrowernumber ) %][% UNLESS ( CGIselectborrower ) %]window.onload=function(){ $('#findborrower').focus(); };[% END %][% END %] >- $(document).ready(function() { >- $('#issues-form').preventDoubleFormSubmit(); >- $('#patronlists').tabs([% IF ( UseTablesortForCirc ) %]{ >- // Correct table sizing for tables hidden in tabs >- // http://www.datatables.net/examples/api/tabs_and_scrolling.html >- "show": function(event, ui) { >- var oTable = $('div.dataTables_wrapper>table', ui.panel).dataTable(); >- if ( oTable.length > 0 ) { >- oTable.fnAdjustColumnSizing(); >- } >- } >- }[% END %]); >- [% IF ( UseTablesortForCirc ) %] >- $("#issuest").dataTable($.extend(true, {}, dataTablesDefaults, { >- "sDom": 't', >- "aaSorting": [], >- "aoColumnDefs": [ >- { "aTargets": [ -1, -2[% IF ( exports_enabled ) %], -3[% END %] ], "bSortable": false, "bSearchable": false }, >- { "sType": "anti-the", "aTargets" : [ "anti-the" ] }, >- { "sType": "title-string", "aTargets" : [ "title-string" ] } >- ], >- "bPaginate": false >- })); >- >- $("#relissuest").dataTable($.extend(true, {}, dataTablesDefaults, { >- "sDom": 't', >- "aaSorting": [], >- "aoColumnDefs": [ >- { "sType": "anti-the", "aTargets" : [ "anti-the" ] }, >- { "sType": "title-string", "aTargets" : [ "title-string" ] }, >- { "sType": "html", "aTargets" : [ "html-content" ] } >- ], >- "bPaginate": false >- })); >- >- $("#issuest").on("sort",function() { >- $("#previous").hide(); // Don't want to see "previous checkouts" header sorted with other rows >- }); >- $("#relissuest").on("sort",function() { >- $("#relprevious").hide(); // Don't want to see "previous checkouts" header sorted with other rows >- }); >- [% END %] >- [% 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 ); >- [% END %][% IF !( CircAutoPrintQuickSlip == 'clear' ) %] >+ >+$(document).ready(function() { >+ [% IF !( CircAutoPrintQuickSlip == 'clear' ) %] > // listen submit to trigger qslip on empty checkout > $('#mainform').bind('submit',function() { >- if ($('#barcode').val() == '') { >- return printx_window( '[% CircAutoPrintQuickSlip %]' ); } >- });[% END %] >- >- [% IF ( CAN_user_circulate_override_renewals ) %] >- [% 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 ); >- [% END %] >- [% END %] >- [% IF AutoResumeSuspendedHolds %] >- $("#suspend_until").datepicker("option", "minDate", 1); // require that hold suspended until date is after today >+ if ($('#barcode').val() == '') { >+ return printx_window( '[% CircAutoPrintQuickSlip %]' ); >+ } >+ }); > [% END %] >- }); >+}); > //]]> > </script> > </head> >@@ -527,7 +483,7 @@ No patron matched <span class="ex">[% message %]</span> > [% ELSE %] > <input type="text" name="barcode" id="barcode" class="barcode focus" size="14" /> > [% END %] >- <input type="submit" value="Check Out" /> >+ <button type="submit" class="btn">Check out</button> > > [% IF ( SpecifyDueDate ) %]<div class="date-select"> > <div class="hint">Specify due date [% INCLUDE 'date-format.inc' %]: </div> >@@ -539,7 +495,7 @@ No patron matched <span class="ex">[% message %]</span> > [% ELSE %] > <input type="checkbox" id="stickyduedate" onclick="this.form.barcode.focus();" name="stickyduedate" /> > [% END %] >- <input type="button" class="action" id="cleardate" value="Clear" name="cleardate" onclick="this.checked = false; this.form.duedatespec.value = ''; this.form.stickyduedate.checked = false; this.form.barcode.focus(); return false;" /> >+ <button class="btn btn-small action" id="cleardate" name="cleardate" onclick="this.checked = false; this.form.duedatespec.value = ''; this.form.stickyduedate.checked = false; this.form.barcode.focus(); return false;" >Clear</button> > </div>[% END %] > <input type="hidden" name="borrowernumber" id="borrowernumber" value="[% borrowernumber %]" /> > <input type="hidden" name="branch" value="[% branch %]" /> >@@ -698,399 +654,111 @@ No patron matched <span class="ex">[% message %]</span> > <div class="yui-g"><div id="patronlists" class="toptabs"> > > <ul> >-<li> [% IF ( issuecount ) %] >+ <li> >+ [% IF ( issuecount ) %] > <a href="#checkouts">[% issuecount %] Checkout(s)</a> >- [% ELSE %] >+ [% ELSE %] > <a href="#checkouts">0 Checkouts</a> >- [% END %]</li> >-[% IF ( displayrelissues ) %] >-<li><a href="#relissues">Relatives' checkouts</a></li> >-[% END %] >-<li>[% IF ( countreserv ) %] >- <a href="#reserves">[% countreserv %] Hold(s)</a> >- [% ELSE %] >- <a href="#reserves">0 Holds</a> >- [% END %]</li> >- <li><a id="debarments-tab-link" href="#reldebarments">[% debarments.size %] Restrictions</a></li> >- >-</ul> >- >-<!-- SUMMARY : TODAY & PREVIOUS ISSUES --> >-<div id="checkouts"> >-[% IF ( issuecount ) %] >- <form id="issues-form" name="issues" action="/cgi-bin/koha/reserve/renewscript.pl" method="post" class="checkboxed"> >- <input type="hidden" value="circ" name="destination" /> >- <input type="hidden" name="cardnumber" value="[% cardnumber %]" /> >- <input type="hidden" name="borrowernumber" value="[% borrowernumber %]" /> >- <input type="hidden" name="branch" value="[% branch %]" /> >- <table id="issuest"> >- <thead><tr> >- <th scope="col" class="title-string">Due date</th> >- <th scope="col" class="anti-the">Title</th> >- <th scope="col">Item type</th> >- <th scope="col" class="title-string">Checked out on</th> >- <th scope="col">Checked out from</th> >- <th scope="col">Call no</th> >- <th scope="col">Charge</th> >- <th scope="col">Price</th> >- <th scope="col">Renew <p class="column-tool"><a href="#" id="CheckAllitems">select all</a> | <a href="#" id="CheckNoitems">none</a></p></th> >- <th scope="col">Check in <p class="column-tool"><a href="#" id="CheckAllreturns">select all</a> | <a href="#" id="CheckNoreturns">none</a></p></th> >- [% IF ( exports_enabled ) %] >- <th scope="col">Export <p class="column-tool"><a href="#" id="CheckAllexports">select all</a> | <a href="#" id="CheckNoexports">none</a></p></th> > [% END %] >- </tr></thead> >-[% IF ( todayissues ) %] >-[% INCLUDE 'checkouts-table-footer.inc' %] >- <tbody> >- >- [% FOREACH todayissue IN todayissues %] >- [% IF ( loop.odd ) %] >- <tr> >- [% ELSE %] >- <tr class="highlight"> >- [% END %] >- [% IF ( todayissue.od ) %]<td class="od">[% ELSE %]<td>[% END %] >- <span title="[% todayissue.dd_sort %]">[% todayissue.dd %]</span> >+ </li> > >- [% IF ( todayissue.itemlost ) %] >- <span class="lost">[% AuthorisedValues.GetByCode( 'LOST', todayissue.itemlost ) %]</span> >- [% END %] >- [% IF ( todayissue.damaged ) %] >- <span class="dmg">[% AuthorisedValues.GetByCode( 'DAMAGED', todayissue.damaged ) %]</span> >- [% END %] >- </td> >- <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% todayissue.biblionumber %]&type=intra"><strong>[% todayissue.title |html %][% FOREACH subtitl IN todayissue.subtitle %] [% subtitl.subfield %][% END %]</strong></a>[% IF ( todayissue.author ) %], by [% todayissue.author %][% END %][% IF ( todayissue.itemnotes ) %]- <span class="circ-hlt">[% todayissue.itemnotes %]</span>[% END %] <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% todayissue.biblionumber %]&itemnumber=[% todayissue.itemnumber %]#item[% todayissue.itemnumber %]">[% todayissue.barcode %]</a></td> >- <td>[% UNLESS ( noItemTypeImages ) %] [% IF ( todayissue.itemtype_image ) %]<img src="[% todayissue.itemtype_image %]" alt="" />[% END %][% END %][% todayissue.itemtype %]</td> >- <td><span title="[% todayissue.displaydate_sort %]">[% todayissue.checkoutdate %]</span></td> >- [% IF ( todayissue.multiple_borrowers ) %]<td>[% todayissue.firstname %] [% todayissue.surname %]</td>[% END %] >- <td>[% todayissue.issuingbranchname %]</td> >- <td>[% todayissue.itemcallnumber %]</td> >- <td>[% todayissue.charge %]</td> >- <td>[% todayissue.replacementprice %]</td> >- [% IF ( todayissue.renew_failed ) %] >- <td class="problem">Renewal failed</td> >- [% ELSE %] >- <td><span style="padding: 0 1em;">[% IF ( todayissue.renewals ) %][% todayissue.renewals %][% ELSE %]0[% END %]</span> >- [% IF ( todayissue.can_renew ) %] >- <input type="checkbox" name="all_items[]" value="[% todayissue.itemnumber %]" checked="checked" style="display: none;" /> >- [% IF ( todayissue.od ) %] >- <input type="checkbox" class="radio" name="items[]" value="[% todayissue.itemnumber %]" checked="checked" /> >- [% ELSE %] >- <input type="checkbox" class="radio" name="items[]" value="[% todayissue.itemnumber %]" /> >- [% END %] >- [% IF todayissue.renewsallowed && todayissue.renewsleft %] >- <span class="renewals">([% todayissue.renewsleft %] of [% todayissue.renewsallowed %] renewals remaining)</span> >- [% END %] >- [% ELSE %] >- [% IF ( todayissue.can_confirm ) %]<span class="renewals-allowed" style="display: none"> >- <input type="checkbox" name="all_items[]" value="[% todayissue.itemnumber %]" checked="checked" style="display: none;" /> >- [% IF ( todayissue.od ) %] >- <input type="checkbox" class="radio" name="items[]" value="[% todayissue.itemnumber %]" checked="checked" /> >- [% ELSE %] >- <input type="checkbox" class="radio" name="items[]" value="[% todayissue.itemnumber %]" /> >- [% END %] >- </span> >- [% IF todayissue.renewsallowed && todayissue.renewsleft && !todayissue.renew_error_too_soon %] >- <span class="renewals">([% todayissue.renewsleft %] of [% todayissue.renewsallowed %] renewals remaining)</span> >- [% END %] >- <span class="renewals-disabled"> >- [% END %] >- [% IF ( todayissue.renew_error_on_reserve ) %] >- <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% todayissue.biblionumber %]">On hold</a> >- [% ELSIF ( todayissue.renew_error_too_many ) %] >- Not renewable >- [% ELSIF ( todayissue.renew_error_too_soon ) %] >- No renewal before [% todayissue.soonestrenewdate %] >- <span class="renewals">([% todayissue.renewsleft %] of [% todayissue.renewsallowed %] renewals remaining)</span> >- [% END %] >- [% IF ( todayissue.can_confirm ) %] >- </span> >- [% END %] >- [% END %] >- </td> >- [% END %] >- [% IF ( todayissue.return_failed ) %] >- <td class="problem">Checkin failed</td> >- [% ELSE %] >- [% IF ( todayissue.renew_error_on_reserve ) %] >- <td><a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% todayissue.biblionumber %]">On hold</a> >- <input type="checkbox" name="all_barcodes[]" value="[% todayissue.barcode %]" checked="checked" style="display: none;" /> >- </td> >- [% ELSE %] >- <td><input type="checkbox" class="radio" name="barcodes[]" value="[% todayissue.barcode %]" /> >- <input type="checkbox" name="all_barcodes[]" value="[% todayissue.barcode %]" checked="checked" style="display: none;" /> >- </td> >- [% END %] >- [% END %] >- [% IF ( exports_enabled ) %] >- <td style="text-align:center;"> >- <input type="checkbox" id="export_[% todayissue.biblionumber %]" name="biblionumbers" value="[% todayissue.biblionumber %]" /> >- <input type="checkbox" name="itemnumbers" value="[% todayissue.itemnumber %]" style="visibility:hidden;" /> >- </td> >- [% END %] >- </tr> >- [% END %] <!-- /loop todayissues --> >- <!-- /if todayissues -->[% END %] >- >-[% IF ( previssues ) %] >- [% UNLESS ( todayissues ) %] >- [% INCLUDE 'checkouts-table-footer.inc' %] >- <tbody> >- [% END %] >- [% IF ( UseTablesortForCirc ) %]<tr id="previous"><th><span title="">Previous checkouts</span></th><th></th><th></th><th><span title=""></span></th><th></th><th></th><th></th><th></th><th></th><th></th>[% IF ( exports_enabled ) %]<th></th>[% END %]</tr>[% ELSE %]<tr id="previous">[% IF ( exports_enabled ) %]<th colspan="11">[% ELSE %]<th colspan="10">[% END %]Previous checkouts</th></tr>[% END %] >- [% FOREACH previssue IN previssues %] >- [% IF ( loop.odd ) %] >- <tr> >- [% ELSE %] >- <tr class="highlight"> >+ [% IF relatives_issues_count %] >+ <li><a id="relatives-issues-tab" href="#relatives-issues">Relatives' checkouts</a></li> > [% END %] >- [% IF ( previssue.od ) %]<td class="od">[% ELSE %]<td>[% END %] >- <span title="[% previssue.dd_sort %]">[% previssue.dd %]</span> > >- [% IF ( previssue.itemlost ) %] >- <span class="lost">[% AuthorisedValues.GetByCode( 'LOST', previssue.itemlost ) %]</span> >- [% END %] >- [% IF ( previssue.damaged ) %] >- <span class="dmg">[% AuthorisedValues.GetByCode( 'DAMAGED', previssue.damaged ) %]</span> >- [% END %] >- </td> >- <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% previssue.biblionumber %]&type=intra"><strong>[% previssue.title |html %][% FOREACH subtitl IN previssue.subtitle %] [% subtitl.subfield %][% END %]</strong></a>[% IF ( previssue.author ) %], by [% previssue.author %][% END %] [% IF ( previssue.itemnotes ) %]- [% previssue.itemnotes %][% END %] <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% previssue.biblionumber %]&itemnumber=[% previssue.itemnumber %]#item[% previssue.itemnumber %]">[% previssue.barcode %]</a></td> >- <td> >- [% previssue.itemtype %] >- </td> >- <td><span title="[% previssue.displaydate_sort %]">[% previssue.displaydate %]</span></td> >- [% IF ( previssue.multiple_borrowers ) %]<td>[% previssue.firstname %] [% previssue.surname %]</td>[% END %] >- <td>[% previssue.issuingbranchname %]</td> >- <td>[% previssue.itemcallnumber %]</td> >- <td>[% previssue.charge %]</td> >- <td>[% previssue.replacementprice %]</td> >- [% IF ( previssue.renew_failed ) %] >- <td class="problem">Renewal failed</td> >- [% ELSE %] >- <td><span style="padding: 0 1em;">[% IF ( previssue.renewals ) %][% previssue.renewals %][% ELSE %]0[% END %]</span> >- [% IF ( previssue.can_renew ) %] >- <input type="checkbox" name="all_items[]" value="[% previssue.itemnumber %]" checked="checked" style="display: none;" /> >- [% IF ( previssue.od ) %] >- <input type="checkbox" class="radio" name="items[]" value="[% previssue.itemnumber %]" checked="checked" /> >- [% ELSE %] >- <input type="checkbox" class="radio" name="items[]" value="[% previssue.itemnumber %]" /> >- [% END %] >- [% IF previssue.renewsallowed && previssue.renewsleft %] >- <span class="renewals">([% previssue.renewsleft %] of [% previssue.renewsallowed %] renewals remaining)</span> >- [% END %] >- [% ELSE %] >- [% IF ( previssue.can_confirm ) %]<span class="renewals-allowed" style="display: none"> >- <input type="checkbox" name="all_items[]" value="[% previssue.itemnumber %]" checked="checked" style="display: none;" /> >- [% IF ( previssue.od ) %] >- <input type="checkbox" class="radio" name="items[]" value="[% previssue.itemnumber %]" checked="checked" /> >- [% ELSE %] >- <input type="checkbox" class="radio" name="items[]" value="[% previssue.itemnumber %]" /> >- [% END %] >- </span> >- [% IF previssue.renewsallowed && previssue.renewsleft && !previssue.renew_error_too_soon %] >- <span class="renewals">([% previssue.renewsleft %] of [% previssue.renewsallowed %] renewals remaining)</span> >- [% END %] >- <span class="renewals-disabled"> >- [% END %] >- [% IF ( previssue.renew_error_on_reserve ) %] >- <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% previssue.biblionumber %]">On Hold</a> >- [% ELSIF ( previssue.renew_error_too_many ) %] >- Not renewable >- [% ELSIF ( previssue.renew_error_too_soon ) %] >- No renewal before [% previssue.soonestrenewdate %] >- <span class="renewals">([% previssue.renewsleft %] of [% previssue.renewsallowed %] renewals remaining)</span> >- [% END %] >- [% IF ( previssue.can_confirm ) %] >- </span> >- [% END %] >- [% END %] >- </td> >- [% END %] >- [% IF ( previssue.return_failed ) %] >- <td class="problem">Check-in failed</td> >+ <li> >+ [% IF ( holds_count ) %] >+ <a href="#reserves" id="holds-tab">[% holds_count %] Hold(s)</a> > [% ELSE %] >- [% IF ( previssue.renew_error_on_reserve ) %] >- <td><a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% previssue.biblionumber %]">On hold</a> >- <input type="checkbox" name="all_barcodes[]" value="[% previssue.barcode %]" checked="checked" style="display: none;" /> >- </td> >- [% ELSE %] >- <td><input type="checkbox" class="radio" name="barcodes[]" value="[% previssue.barcode %]" /> >- <input type="checkbox" name="all_barcodes[]" value="[% previssue.barcode %]" checked="checked" style="display: none;" /> >- </td> >- [% END %] >- [% END %] >- [% IF ( exports_enabled ) %] >- <td style="text-align:center;"> >- <input type="checkbox" id="export_[% previssue.biblionumber %]" name="biblionumbers" value="[% previssue.biblionumber %]" /> >- <input type="checkbox" name="itemnumbers" value="[% previssue.itemnumber %]" style="visibility:hidden;" /> >- </td> >- [% END %] >- </tr> >- <!-- /loop previssues -->[% END %] >-<!--/if previssues -->[% END %] >- </tbody> >- </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 %] >- <input type="submit" name="renew_checked" value="Renew or Return checked items" /> >- <input type="submit" id="renew_all" name="renew_all" value="Renew all" /> >- </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> >- [% 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" /> >- <input type="button" id="export_submit" value="Export" /> >- </fieldset> >+ <a href="#reserves" id="holds-tab">0 Holds</a> > [% END %] >- [% END %] >- </form> >-[% ELSE %] >-<p>Patron has nothing checked out.</p> >-[% END %] >- >-</div> >- >+ </li> > >-[% IF ( displayrelissues ) %] >-<div id="relissues"> >- <table id="relissuest"> >- <thead> >- <tr> >- <th scope="col" class="title-string">Due date</th> >- <th scope="col" class="anti-the">Title</th> >- <th scope="col">Item type</th> >- <th scope="col" class="title-string">Checked out on</th> >- <th scope="col">Checked out from</th> >- <th scope="col">Call no</th> >- <th scope="col">Charge</th> >- <th scope="col">Price</th> >- <th scope="col" class="html-content">Patron</th> >- </tr> >- </thead> >-[% IF ( relissues ) %] <tbody> >- >- [% FOREACH relissue IN relissues %] >- [% IF ( loop.odd ) %] >- <tr> >- [% ELSE %] >- <tr class="highlight"> >- [% END %] >- [% IF ( relissue.overdue ) %]<td class="od">[% ELSE %]<td>[% END %] >- <span title="[% relissue.dd_sort %]">[% relissue.dd %]</span></td> >+ <li><a id="debarments-tab-link" href="#reldebarments">[% debarments.size %] Restrictions</a></li> >+</ul> > >- [% IF ( relissue.itemlost ) %] >- <span class="lost">[% AuthorisedValues.GetByCode( 'LOST', relissue.itemlost ) %]</span> >- [% END %] >- [% IF ( relissue.damaged ) %] >- <span class="dmg">[% AuthorisedValues.GetByCode( 'DAMAGED', relissue.damaged ) %]</span> >+<!-- SUMMARY : TODAY & PREVIOUS ISSUES --> >+<div id="checkouts"> >+ [% IF ( issuecount ) %] >+ <table id="issues-table"> >+ <thead> >+ <tr> >+ <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">Checked out on</th> >+ <th scope="col">Checked out from</th> >+ <th scope="col">Call no</th> >+ <th scope="col">Charge</th> >+ <th scope="col">Price</th> >+ <th scope="col">Renew <p class="column-tool"><a href="#" id="CheckAllRenewals">select all</a> | <a href="#" id="UncheckAllRenewals">none</a></p></th> >+ <th scope="col">Check in <p class="column-tool"><a href="#" id="CheckAllCheckins">select all</a> | <a href="#" id="UncheckAllCheckins">none</a></p></th> >+ <th scope="col">Export <p class="column-tool"><a href="#" id="CheckAllExports">select all</a> | <a href="#" id="UncheckAllExports">none</a></p></th> >+ </tr> >+ </thead> >+ [% INCLUDE 'checkouts-table-footer.inc' %] >+ </table> >+ >+ <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 %] >- </td> >- <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% relissue.biblionumber %]&type=intra"><strong>[% relissue.title |html %][% FOREACH subtitl IN relissue.subtitle %] [% subtitl.subfield %][% END %]</strong></a>[% IF ( relissue.author ) %], by [% relissue.author %][% END %][% IF ( relissue.itemnotes ) %]- <span class="circ-hlt">[% relissue.itemnotes %]</span>[% END %] <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% relissue.biblionumber %]&itemnumber=[% relissue.itemnumber %]#item[% relissue.itemnumber %]">[% relissue.barcode %]</a></td> >- <td>[% UNLESS ( noItemTypeImages ) %] [% IF ( relissue.itemtype_image ) %]<img src="[% relissue.itemtype_image %]" alt="" />[% END %][% END %][% relissue.itemtype %]</td> >- <td><span title="[% relissue.displaydate_sort %]">[% relissue.displaydate %]</span></td> >- <td>[% relissue.issuingbranchname %]</td> >- <td>[% relissue.itemcallnumber %]</td> >- <td>[% relissue.charge %]</td> >- <td>[% relissue.replacementprice %]</td><td><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% relissue.borrowernumber %]">[% relissue.firstname %] [% relissue.surname %] ([% relissue.cardnumber %])</a></td> >- </tr> >- [% END %] <!-- /loop relissues --> >- <!-- /if relissues -->[% END %] >-[% IF ( relprevissues ) %] >- [% IF ( UseTablesortForCirc ) %]<tr id="relprevious"><th><span title="">Previous checkouts</span></th><th></th><th></th><th><span title=""></span></th><th></th><th></th><th></th><th></th><th></th></tr>[% ELSE %]<tr id="relprevious"><th colspan="9">Previous checkouts</th></tr>[% END %] >- [% FOREACH relprevissue IN relprevissues %] >- [% IF ( loop.odd ) %] >- <tr> >+ <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> > [% ELSE %] >- <tr class="highlight"> >+ <p>Patron has nothing checked out.</p> > [% END %] >- [% IF ( relprevissue.overdue ) %]<td class="od">[% ELSE %]<td>[% END %] >- <span title="[% relprevissue.dd_sort %]">[% relprevissue.dd %]</span> >- </td> >- <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% relprevissue.biblionumber %]&type=intra"><strong>[% relprevissue.title |html %][% FOREACH subtitl IN relprevissue.subtitle %] [% subtitl.subfield %][% END %]</strong></a>[% IF ( relprevissue.author ) %], by [% relprevissue.author %][% END %] [% IF ( relprevissue.itemnotes ) %]- [% relprevissue.itemnotes %][% END %] <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% relprevissue.biblionumber %]&itemnumber=[% relprevissue.itemnumber %]#item[% relprevissue.itemnumber %]">[% relprevissue.barcode %]</a></td> >- <td>[% UNLESS noItemTypeImages %][% IF relprevissue.itemtype_image %]<img src="[% relprevissue.itemtype_image %]" alt="" />[% END %][% END %][% relprevissue.itemtype %]</td> >- <td><span title="[% relprevissue.displaydate_sort %]">[% relprevissue.displaydate %]</span></td> >- <td>[% relprevissue.issuingbranchname %]</td> >- <td>[% relprevissue.itemcallnumber %]</td> >- [% IF ( relprevissue.multiple_borrowers ) %]<td>[% relprevissue.firstname %] [% relprevissue.surname %]</td>[% END %] >- <td>[% relprevissue.charge %]</td> >- <td>[% relprevissue.replacementprice %]</td> >- <td><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% relprevissue.borrowernumber %]">[% relprevissue.firstname %] [% relprevissue.surname %] ([% relprevissue.cardnumber %])</a></td> >- >- </tr> >- <!-- /loop relprevissue -->[% END %] >-<!--/if relprevissues -->[% END %] >- </tbody> >- </table> >- > </div> >-[% END %]<!-- end displayrelissues --> >+ >+[% IF ( relatives_issues_count ) %] >+ <div id="relatives-issues"> >+ <table id="relatives-issues-table"> >+ <thead> >+ <tr> >+ <th scope="col">Due date</th> >+ <th scope="col">Title</th> >+ <th scope="col">Item type</th> >+ <th scope="col">Checked out on</th> >+ <th scope="col">Checked out from</th> >+ <th scope="col">Call no</th> >+ <th scope="col">Charge</th> >+ <th scope="col">Price</th> >+ <th scope="col">Patron</th> >+ </tr> >+ </thead> >+ </table> >+ </div> >+[% END %] > > [% INCLUDE borrower_debarments.inc %] > > <div id="reserves"> >-[% IF ( reservloop ) %] >+[% IF ( holds_count ) %] > <form action="/cgi-bin/koha/reserve/modrequest.pl" method="post"> >- <input type="hidden" name="from" value="circ" /> >- <table id="holdst"> >- <thead><tr> >- <th>Hold date</th> >- <th>Title</th> >- <th>Call number</th> >- <th>Barcode</th> >- <th>Expiration</th> >- <th>Priority</th> >- <th>Delete?</th> >- <th> </th> >- </tr></thead> >- <tbody> >- [% FOREACH reservloo IN reservloop %] >- <tr class="[% reservloo.color %]"> >- <td>[% reservloo.reservedate %]</td> >- <td><a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% reservloo.biblionumber %]"><strong>[% reservloo.title |html %][% FOREACH subtitl IN reservloo.subtitle %] [% subtitl.subfield %][% END %]</strong></a>[% IF ( reservloo.author ) %], by [% reservloo.author %][% END %]</td> >- <td>[% reservloo.itemcallnumber %]</td> >- <td><em>[% IF ( reservloo.barcodereserv ) %]Item [% reservloo.barcodereserv %] >- [% END %][% IF ( reservloo.waiting ) %] <strong>waiting at [% reservloo.waitingat %]</strong> >- [% END %] >- [% IF ( reservloo.transfered ) %] <strong>in transit</strong> from >- [% reservloo.frombranch %] since [% reservloo.datesent %] >- [% END %] >- [% IF ( reservloo.nottransfered ) %] hasn't been transferred yet from [% reservloo.nottransferedby %]</i> >- [% END %]</em></td> >- <td>[% reservloo.expirationdate | $KohaDates %]</td> >- <td> >- [% IF ( reservloo.waitingposition ) %]<b> [% reservloo.waitingposition %] </b>[% END %] >- </td> >- <td><select name="rank-request"> >- <option value="n">No</option> >- <option value="del">Yes</option> >- </select> >- <input type="hidden" name="biblionumber" value="[% reservloo.biblionumber %]" /> >- <input type="hidden" name="borrowernumber" value="[% borrowernumber %]" /> >- <input type="hidden" name="reserve_id" value="[% reservloo.reserve_id %]" /> >- </td> >- <td>[% IF ( reservloo.suspend ) %]Suspended [% IF ( reservloo.suspend_until ) %] until [% reservloo.suspend_until | $KohaDates %][% END %][% END %]</td> >- </tr> >- [% END %]</tbody> >- </table> >- <fieldset class="action"><input type="submit" class="cancel" name="submit" value="Cancel marked holds" /></fieldset> >+ <input type="hidden" name="from" value="circ" /> >+ <table id="holds-table" style="width: 100% !Important;"> >+ <thead> >+ <tr> >+ <th>Hold date</th> >+ <th>Title</th> >+ <th>Call number</th> >+ <th>Barcode</th> >+ <th>Expiration</th> >+ <th>Priority</th> >+ <th>Delete?</th> >+ </tr> >+ </thead> >+ </table> >+ >+ <fieldset class="action"> >+ <input type="submit" class="cancel" name="submit" value="Cancel marked holds" /> >+ </fieldset> > </form> > > [% 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 345c728..3c9b678 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 @@ > </title> > [% INCLUDE 'doc-head-close.inc' %] > [% INCLUDE 'calendar.inc' %] >-<link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" /> >+<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/en/css/datatables.css" /> > [% INCLUDE 'datatables.inc' %] >-<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.checkboxes.min.js"></script> >+[% INCLUDE 'strings.inc' %] >+<script type="text/javascript" src="[% themelang %]/lib/jquery/plugins/jquery.checkboxes.min.js"></script> > <script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery-ui-timepicker-addon.min.js"></script> > [% INCLUDE 'timepicker.inc' %] >+<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.dataTables.rowGrouping.js"></script> >+<script type="text/javascript" src="[% themelang %]/js/checkouts.js"></script> >+<script type="text/javascript" src="[% themelang %]/js/holds.js"></script> > <script type="text/JavaScript"> > //<![CDATA[ >+/* Set some variable needed in circulation.js */ >+var interface = "[% interface %]"; >+var theme = "[% theme %]"; >+var borrowernumber = "[% borrowernumber %]"; >+var branchcode = "[% branch %]"; >+var exports_enabled = "[% exports_enabled %]"; >+var AllowRenewalLimitOverride = [% CAN_user_circulate_override_renewals && AllowRenewalLimitOverride %]; >+var relatives_borrowernumbers = new Array(); >+[% FOREACH b IN relatives_borrowernumbers %] >+ relatives_borrowernumbers.push("[% b %]"); >+[% END %] >+ > $(document).ready(function() { > $('#finesholdsissues').tabs({ > // Correct table sizing for tables hidden in tabs >@@ -27,23 +43,6 @@ $(document).ready(function() { > } > } > } ); >- $("#issuest").dataTable($.extend(true, {}, dataTablesDefaults, { >- "sDom": 't', >- "aoColumnDefs": [ >- { "aTargets": [ -1,-2 ], "bSortable": false, "bSearchable": false } >- ], >- "aoColumns": [ >- { "sType": "title-string" },{ "sType": "anti-the" },null,{ "sType": "title-string" },null,null,null,null,null,null >- ], >- "bPaginate": false >- })); >- $("#relissuest").dataTable($.extend(true, {}, dataTablesDefaults, { >- "sDom": 't', >- "aoColumns": [ >- { "sType": "title-string" },{ "sType": "anti-the" },null,{ "sType": "title-string" },null,null,null,null,null >- ], >- "bPaginate": false >- })); > $("#holdst").dataTable($.extend(true, {}, dataTablesDefaults, { > "sDom": 't', > "aoColumnDefs": [ >@@ -66,42 +65,7 @@ $(document).ready(function() { > } > return confirm(_("Are you sure you want to replace the current patron image? This cannot be undone.")); > });[% END %] >- $("#renew_all" ).click(function(){ $(".checkboxed").checkCheckboxes(":input[name*=items]" ); $(".checkboxed").unCheckCheckboxes(":input[name*=barcodes]"); }); >- $("#CheckAllitems" ).click(function(){ $(".checkboxed").checkCheckboxes(":input[name*=items]" ); $(".checkboxed").unCheckCheckboxes(":input[name*=barcodes]"); return false; }); >- $("#CheckNoitems" ).click(function(){ $(".checkboxed").unCheckCheckboxes(":input[name*=items]"); return false; }); >- $("#CheckAllreturns").click(function(){ $(".checkboxed").checkCheckboxes(":input[name*=barcodes]"); $(".checkboxed").unCheckCheckboxes(":input[name*=items]"); return false; }); >- $("#CheckNoreturns" ).click(function(){ $(".checkboxed").unCheckCheckboxes(":input[name*=barcodes]"); return false; }); >- >- $("#relrenew_all" ).click(function(){ $(".checkboxed").checkCheckboxes(":input[name*=items]" ); $(".checkboxed").unCheckCheckboxes(":input[name*=barcodes]"); }); >- $("#relCheckAllitems" ).click(function(){ $(".checkboxed").checkCheckboxes(":input[name*=items]" ); $(".checkboxed").unCheckCheckboxes(":input[name*=barcodes]"); return false; }); >- $("#relCheckNoitems" ).click(function(){ $(".checkboxed").unCheckCheckboxes(":input[name*=items]"); return false; }); >- $("#relCheckAllreturns").click(function(){ $(".checkboxed").checkCheckboxes(":input[name*=barcodes]"); $(".checkboxed").unCheckCheckboxes(":input[name*=items]"); return false; }); >- $("#relCheckNoreturns" ).click(function(){ $(".checkboxed").unCheckCheckboxes(":input[name*=barcodes]"); return false; }); >- >- >- [% IF ( CAN_user_circulate_override_renewals ) %] >- [% 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 ); >- [% END %] >- [% END %] >- $("td").click(function(e){ >- if(e.target.tagName.toLowerCase() == 'td'){ >- $(this).find("input:checkbox").each( function() { >- $(this).attr('checked', !$(this).attr('checked')); >- if($(this).attr('checked')){ >- $(this).parent().siblings().find("input:checkbox").each(function(){ >- if($(this).attr('checked')){ $(this).removeAttr('checked'); } >- }); >- } >- }); >- } >- }); >+ > $("#suspend_until").datepicker({ minDate: 1 }); // require that hold suspended until date is after today > $("#newduedate").datetimepicker({ > minDate: 1, // require that renewal date is after today >@@ -424,190 +388,102 @@ function validate1(date) { > > <div id="finesholdsissues" class="toptabs"> > <ul> >- <li><a href="#checkedout">[% issueloop.size %] Checkout(s)</a></li> >- [% IF relissueloop.size %] >- <li><a href="#relissues">Relatives' Checkouts</a></li> >- [% END %] >+ <li><a href="#checkouts">[% issueloop.size %] Checkout(s)</a></li> >+ [% IF relatives_issues_count %] >+ <li><a href="#relatives-issues" id="relatives-issues-tab">Relatives' checkouts</a></li> >+ [% END %] > <li><a href="#finesandcharges">Fines & Charges</a></li> >- <li>[% IF ( countreserv ) %] >- <a href="#onhold">[% countreserv %] Hold(s)</a> [% ELSE %] >- <a href="#onhold">0 Holds</a> >- [% END %]</li> >+ <li> >+ [% IF ( holds_count ) %] >+ <a href="#reserves" id="holds-tab">[% holds_count %] Hold(s)</a> >+ [% ELSE %] >+ <a href="#reserves" id="holds-tab">0 Holds</a> >+ [% END %] >+ </li> > <li><a id="debarments-tab-link" href="#reldebarments">[% debarments.size %] Restrictions</a></li> > </ul> > >- <form action="/cgi-bin/koha/reserve/renewscript.pl" method="post" class="checkboxed"> >- <input type="hidden" name="borrowernumber" value="[% borrowernumber %]" /> >- <input type="hidden" name="branch" value="[% branch %]" /> >-<div id="checkedout"> >- [% IF ( issueloop ) %] >- <table id="issuest"> >- <thead> >- <tr> >- <th scope="col">Due date</th> >- <th scope="col">Title</th> >- <th scope="col">Item type</th> >- <th scope="col">Checked out on</th> >- <th scope="col">Checked out from</th> >- <th scope="col">Call no.</th> >- <th scope="col">Charge</th> >- <th scope="col">Price</th> >- <th scope="col">Renew <p class="column-tool"><a href="#" id="CheckAllitems">select all</a> | <a href="#" id="CheckNoitems">none</a></p></th> >- <th scope="col">Check in <p class="column-tool"><a href="#" id="CheckAllreturns">select all</a> | <a href="#" id="CheckNoreturns">none</a></p></th> >- </tr></thead> >- [% INCLUDE 'checkouts-table-footer.inc' %] >- <tbody> >- [% FOREACH issueloo IN issueloop %] >- >- [% IF ( issueloo.overdue ) %] >- <tr class="problem"> >- [% ELSE %] >- <tr> >- [% END %] >- [% IF ( issueloo.red ) %] >- <td class="od"> >- [% ELSE %] >- <td> >- [% END %] >- <span title="[% issueloo.date_due %]">[% issueloo.date_due | $KohaDates %]</span> >- [% IF ( issueloo.itemlost ) %] >- <span class="lost">[% issueloo.itemlost %]</span> >+ <div id="checkouts"> >+ [% IF ( issuecount ) %] >+ <form name="issues" action="/cgi-bin/koha/tools/export.pl" method="post" class="checkboxed"> >+ <table id="issues-table" style="width: 100% !Important;"> >+ <thead> >+ <tr> >+ <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">Checked out on</th> >+ <th scope="col">Checked out from</th> >+ <th scope="col">Call no</th> >+ <th scope="col">Charge</th> >+ <th scope="col">Price</th> >+ <th scope="col">Renew <p class="column-tool"><a href="#" id="CheckAllRenewals">select all</a> | <a href="#" id="UncheckAllRenewals">none</a></p></th> >+ <th scope="col">Check in <p class="column-tool"><a href="#" id="CheckAllCheckins">select all</a> | <a href="#" id="UncheckAllCheckins">none</a></p></th> >+ <th scope="col">Export <p class="column-tool"><a href="#" id="CheckAllExports">select all</a> | <a href="#" id="UncheckAllExports">none</a></p></th> >+ </tr> >+ </thead> >+ [% INCLUDE 'checkouts-table-footer.inc' %] >+ </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> >+ [% 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 %] >- [% IF ( issueloo.damaged ) %] >- <span class="dmg">[% issueloo.itemdamaged %]</span> >- [% END %] >-</td> >- <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% issueloo.biblionumber %]"><strong>[% issueloo.title |html %][% FOREACH subtitl IN issueloo.subtitle %] [% subtitl.subfield %][% END %]</strong></a>[% IF ( issueloo.author ) %], by [% issueloo.author %][% END %] [% IF ( issueloo.publishercode ) %]; [% issueloo.publishercode %] [% END %] [% IF ( issueloo.publicationyear ) %], [% issueloo.publicationyear %][% END %] <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% issueloo.biblionumber %]&itemnumber=[% issueloo.itemnumber %]#item[% issueloo.itemnumber %]">[% issueloo.barcode %]</a></td> >-<td>[% UNLESS ( noItemTypeImages ) %] [% IF ( issueloo.itemtype_image ) %]<img src="[% issueloo.itemtype_image %]" alt="" />[% END %][% END %][% issueloo.itemtype_description %]</td> >- <td><span title="[% issueloo.issuedate %]">[% issueloo.issuedate | $KohaDates%]</span></td> >- <td>[% issueloo.issuingbranchname %]</td> >- <td>[% issueloo.itemcallnumber %]</td> >- <td>[% issueloo.charge %]</td> >- <td>[% issueloo.replacementprice %]</td> >- [% IF ( issueloo.renew_failed ) %] >- <td class="problem">Renewal Failed</td> >- [% ELSE %] >- <td><span style="padding: 0 1em;">[% IF ( issueloo.renewals ) %][% issueloo.renewals %][% ELSE %]0[% END %]</span> >- [% IF ( issueloo.norenew ) %] >- [% IF ( issueloo.can_confirm ) %]<span class="renewals-allowed" style="display: none"> >- <input type="checkbox" name="all_items[]" value="[% issueloo.itemnumber %]" checked="checked" style="display: none;" /> >- [% IF ( issueloo.od ) %] >- <input type="checkbox" name="items[]" value="[% issueloo.itemnumber %]" checked="checked" /> >- [% ELSE %] >- <input type="checkbox" name="items[]" value="[% issueloo.itemnumber %]" /> >- [% END %] >- </span> >- [% IF issueloo.renewsallowed && issueloo.renewsleft && !issueloo.norenew_reason_too_soon %] >- <span class="renewals">([% issueloo.renewsleft %] of [% issueloo.renewsallowed %] renewals remaining)</span> >- [% END %] >- <span class="renewals-disabled"> >- [% END %] >- [% IF ( issueloo.norenew_reason_on_reserve ) %] >- <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% issueloo.biblionumber %]">On Hold</a> >- [% ELSIF ( issueloo.norenew_reason_too_many ) %] >- Not renewable >- [% ELSIF ( issueloo.norenew_reason_too_soon ) %] >- No renewal before [% issueloo.soonestrenewdate %] >- <span class="renewals">([% issueloo.renewsleft %] of [% issueloo.renewsallowed %] renewals remaining)</span> > [% END %] >- [% IF ( issueloo.can_confirm ) %] >- </span> >- [% END %] >- [% ELSE %] >- <input type="checkbox" name="all_items[]" value="[% issueloo.itemnumber %]" checked="checked" style="display: none;" /> >- [% IF ( issueloo.red ) %] >- <input type="checkbox" name="items[]" value="[% issueloo.itemnumber %]" checked="checked" onclick="uncheck_sibling(this);" /> >- [% ELSE %] >- <input type="checkbox" name="items[]" value="[% issueloo.itemnumber %]" onclick="uncheck_sibling(this);" /> >- [% END %] >- [% IF issueloo.renewsallowed && issueloo.renewsleft %] >- <span class="renewals">([% issueloo.renewsleft %] of [% issueloo.renewsallowed %] renewals remaining)</span> >- [% END %] >- [% END %] >- </td> >- [% END %] >- [% IF ( issueloo.return_failed ) %] >- <td class="problem">Check-in failed</td> >- [% ELSE %] >- [% IF ( issueloo.norenew_reason_on_reserve ) %] >- <td><a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% issueloo.biblionumber %]">On hold</a></td> >+ </form> > [% ELSE %] >- <td><input type="checkbox" name="barcodes[]" value="[% issueloo.barcode %]" onclick="uncheck_sibling(this);" /> >- <input type="checkbox" name="all_barcodes[]" value="[% issueloo.barcode %]" checked="checked" style="display: none;" /> >- </td> >- [% END %] >- [% END %] >- </tr> >- [% END %] >- </tbody> >- </table> >- <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" /> >+ <p>Patron has nothing checked out.</p> > [% END %] >- [% END %] >- <input type="submit" name="renew_checked" value="Renew or return checked items" /> >- <input type="submit" id="renew_all" name="renew_all" value="Renew all" /> >- </fieldset> >- [% ELSE %]<p>Patron has nothing checked out.</p> >-[% END %] >-</div> >- >+ </div> > >-[% IF relissueloop %] >-<div id="relissues"> >- <table id="relissuest"> >- <thead> >- <tr> >- <th scope="col">Due date</th> >- <th scope="col">Title</th> >- <th scope="col">Item type</th> >- <th scope="col">Checked out on</th> >- <th scope="col">Checked out from</th> >- <th scope="col">Call no.</th> >- <th scope="col">Charge</th> >- <th scope="col">Price</th> >- <th scope="col">Patron</th> >- </tr> >- </thead> >- <tbody> >- [% FOREACH relissueloo IN relissueloop %] >- >- [% IF ( relissueloo.overdue ) %] >- <tr class="problem"> >- [% ELSE %] >- <tr> >- [% END %] >- [% IF ( relissueloo.red ) %] >- <td class="od"> >- [% ELSE %] >- <td> >- [% END %] >- <span title="[% relissueloo.date_due %]">[% relissueloo.date_due | $KohaDates %]</span> >- [% IF ( relissueloo.itemlost ) %] >- <span class="lost">[% relissueloo.itemlost %]</span> >- [% END %] >- [% IF ( relissueloo.damaged ) %] >- <span class="dmg">[% relissueloo.itemdamaged %]</span> >- [% END %] >-</td> >- <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% relissueloo.biblionumber %]"><strong>[% relissueloo.title |html %][% FOREACH subtitl IN relissueloo.subtitle %] [% subtitl.subfield %][% END %]</strong></a>[% IF relissueloo.author %], by [% relissueloo.author %][% END %] [% IF relissueloo.publishercode %]; [% relissueloo.publishercode %] [% END %] [% IF relissueloo.publicationyear %], [% relissueloo.publicationyear %][% END %] <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% relissueloo.biblionumber %]&itemnumber=[% relissueloo.itemnumber %]#item[% relissueloo.itemnumber %]">[% relissueloo.barcode %]</a></td> >-<td>[% UNLESS ( noItemTypeImages ) %] [% IF ( relissueloo.itemtype_image ) %]<img src="[% relissueloo.itemtype_image %]" alt="" />[% END %][% END %][% relissueloo.itemtype_description %]</td> >- <td><span title="[% relissueloo.issuedate %]">[% relissueloo.issuedate | $KohaDates %]</span></td> >- <td>[% relissueloo.issuingbranchname %]</td> >- <td>[% relissueloo.itemcallnumber %]</td> >- <td>[% relissueloo.charge %]</td> >- <td>[% relissueloo.replacementprice %]</td> >- <td><a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% relissueloo.borrowernumber %]">[% relissueloo.firstname %] [% relissueloo.surname %] ([% relissueloo.cardnumber %])</a></td> >- </tr> >- [% END %] >- </tbody> >- </table> >+[% IF ( relatives_issues_count ) %] >+ <div id="relatives-issues"> >+ <table id="relatives-issues-table" style="width: 100% !Important;"> >+ <thead> >+ <tr> >+ <th scope="col">Due date</th> >+ <th scope="col">Title</th> >+ <th scope="col">Item type</th> >+ <th scope="col">Checked out on</th> >+ <th scope="col">Checked out from</th> >+ <th scope="col">Call no</th> >+ <th scope="col">Charge</th> >+ <th scope="col">Price</th> >+ <th scope="col">Patron</th> >+ </tr> >+ </thead> >+ </table> > </div> > [% END %] >- </form> > > <div id="finesandcharges"> > [% IF ( totaldue_raw ) %] >@@ -619,59 +495,27 @@ function validate1(date) { > > [% INCLUDE borrower_debarments.inc %] > >-<div id="onhold"> >-[% IF ( reservloop ) %] >-<form action="/cgi-bin/koha/reserve/modrequest.pl" method="post"> >- <input type="hidden" name="from" value="borrower" /> >- <table id="holdst"> >- <thead><tr> >- <th>Hold date</th> >- <th>Title</th> >- <th>Call number</th> >- <th>Barcode</th> >- <th>Expiration</th> >- <th>Priority</th> >- <th>Delete?</th> >- <th> </th> >- </tr></thead> >- <tbody>[% FOREACH reservloo IN reservloop %] >- <tr class="[% reservloo.color %]"> >- <td><span title="[% reservloo.reservedate %]">[% reservloo.reservedate | $KohaDates %]</span></td> >- <td> >- <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% reservloo.biblionumber %]">[% reservloo.title |html %][% FOREACH subtitl IN reservloo.subtitle %] [% subtitl.subfield %][% END %]</a>[% IF ( reservloo.author ) %], by [% reservloo.author %][% END %] >- </td> >- <td>[% reservloo.itemcallnumber %]</td> >- <td>[% IF ( reservloo.waiting ) %] >- <em>Item is <strong>waiting</strong></em> >- [% END %] >- [% IF ( reservloo.transfered ) %] >- <em>Item <strong>in transit</strong> from >- [% reservloo.frombranch %] since [% reservloo.datesent %] </em> >- [% END %] >+<div id="reserves"> >+[% IF ( holds_count ) %] >+ <form action="/cgi-bin/koha/reserve/modrequest.pl" method="post"> >+ <input type="hidden" name="from" value="circ" /> >+ <table id="holds-table" style="width: 100% !Important;"> >+ <thead> >+ <tr> >+ <th>Hold date</th> >+ <th>Title</th> >+ <th>Call number</th> >+ <th>Barcode</th> >+ <th>Expiration</th> >+ <th>Priority</th> >+ <th>Delete?</th> >+ </tr> >+ </thead> >+ </table> > >- [% IF ( reservloo.nottransfered ) %] >- <em>Item hasn't been transferred yet from [% reservloo.nottransferedby %]</em> >- [% END %] >- [% IF ( reservloo.barcodereserv ) %] >- <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% reservloo.biblionumber %]">[% reservloo.barcodereserv %]</a> >- [% END %] >- </td> >- <td>[% reservloo.expirationdate | $KohaDates %]</td> >- <td>[% IF ( reservloo.waitingposition ) %]<strong>[% reservloo.waitingposition %]</strong>[% END %]</td> >- <td><select name="rank-request"> >- <option value="n">No</option> >- <option value="del">Yes</option> >- </select> >- <input type="hidden" name="biblionumber" value="[% reservloo.biblionumber %]" /> >- <input type="hidden" name="borrowernumber" value="[% borrowernumber %]" /> >- <input type="hidden" name="reserve_id" value="[% reservloo.reserve_id %]" /> >- </td> >- <td>[% IF ( reservloo.suspend ) %]Suspended [% IF ( reservloo.suspend_until ) %] until [% reservloo.suspend_until | $KohaDates %][% END %][% END %]</td> >- </tr> >- [% END %]</tbody> >- </table> >- >- <fieldset class="action"><input type="submit" class="cancel" name="submit" value="Cancel marked holds" /></fieldset> >+ <fieldset class="action"> >+ <input type="submit" class="cancel" name="submit" value="Cancel marked holds" /> >+ </fieldset> > </form> > > [% IF SuspendHoldsIntranet %] >diff --git a/members/moremember.pl b/members/moremember.pl >index 92d79e5..72e97b1 100755 >--- a/members/moremember.pl >+++ b/members/moremember.pl >@@ -2,6 +2,7 @@ > > # Copyright 2000-2002 Katipo Communications > # Copyright 2010 BibLibre >+# Copyright 2014 ByWater Solutions > # > # This file is part of Koha. > # >@@ -56,6 +57,7 @@ use Koha::Borrower::Debarments qw(GetDebarments IsDebarred); > #use Data::Dumper; > use DateTime; > use Koha::DateUtils; >+use Koha::Database; > > use vars qw($debug); > >@@ -68,14 +70,6 @@ my $dbh = C4::Context->dbh; > my $input = CGI->new; > $debug or $debug = $input->param('debug') || 0; > my $print = $input->param('print'); >-my $override_limit = $input->param("override_limit") || 0; >-my @failedrenews = $input->param('failedrenew'); >-my @failedreturns = $input->param('failedreturn'); >-my $error = $input->param('error'); >-my %renew_failed; >-for my $renew (@failedrenews) { $renew_failed{$renew} = 1; } >-my %return_failed; >-for my $failedret (@failedreturns) { $return_failed{$failedret} = 1; } > > my $template_name; > my $quickslip = 0; >@@ -115,8 +109,10 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( > ); > my $borrowernumber = $input->param('borrowernumber'); > >-#start the page and read in includes >-my $data = GetMember( 'borrowernumber' => $borrowernumber ); >+my ( $od, $issue, $fines ) = GetMemberIssuesAndFines($borrowernumber); >+$template->param( issuecount => $issue ); >+ >+my $data = GetMember( 'borrowernumber' => $borrowernumber ); > > if ( not defined $data ) { > $template->param (unknowuser => 1); >@@ -126,8 +122,6 @@ if ( not defined $data ) { > > my $category_type = $data->{'category_type'}; > >-### $category_type >- > $debug and printf STDERR "dates (enrolled,expiry,birthdate) raw: (%s, %s, %s)\n", map {$data->{$_}} qw(dateenrolled dateexpiry dateofbirth); > foreach (qw(dateenrolled dateexpiry dateofbirth)) { > my $userdate = $data->{$_}; >@@ -251,14 +245,11 @@ if ( C4::Context->preference('OPACPrivacy') ) { > $template->param( "privacy".$data->{'privacy'} => 1); > } > >-# current issues >-# >-my @borrowernumbers = GetMemberRelatives($borrowernumber); >-my $issue = GetPendingIssues($borrowernumber); >-my $relissue = []; >-if ( @borrowernumbers ) { >- $relissue = GetPendingIssues(@borrowernumbers); >-} >+my @relatives = GetMemberRelatives($borrowernumber); >+my $relatives_issues_count = >+ Koha::Database->new()->schema()->resultset('Issue') >+ ->count( { borrowernumber => \@relatives } ); >+ > my $roadtype = C4::Koha::GetAuthorisedValueByCode( 'ROADTYPE', $data->{streettype} ); > my $today = DateTime->now( time_zone => C4::Context->tz); > $today->truncate(to => 'day'); >@@ -266,85 +257,13 @@ my @borrowers_with_issues; > my $overdues_exist = 0; > my $totalprice = 0; > >-my @issuedata = build_issue_data($issue); >-my @relissuedata = build_issue_data($relissue); >- >- > ### ############################################################################### > # BUILD HTML > # show all reserves of this borrower, and the position of the reservation .... > if ($borrowernumber) { >- >- # new op dev >- # now we show the status of the borrower's reservations >- my @borrowerreserv = GetReservesFromBorrowernumber($borrowernumber ); >- my @reservloop; >- foreach my $num_res (@borrowerreserv) { >- my %getreserv; >- my $getiteminfo = GetBiblioFromItemNumber( $num_res->{'itemnumber'} ); >- my $itemtypeinfo = getitemtypeinfo( $getiteminfo->{'itemtype'} ); >- my ( $transfertwhen, $transfertfrom, $transfertto ) = >- GetTransfers( $num_res->{'itemnumber'} ); >- >- foreach (qw(waiting transfered nottransfered)) { >- $getreserv{$_} = 0; >- } >- $getreserv{reservedate} = $num_res->{'reservedate'}; >- foreach (qw(biblionumber title author itemcallnumber )) { >- $getreserv{$_} = $getiteminfo->{$_}; >- } >- $getreserv{barcodereserv} = $getiteminfo->{'barcode'}; >- $getreserv{itemtype} = $itemtypeinfo->{'description'}; >- >- # check if we have a waitin status for reservations >- if ( defined $num_res->{found} and $num_res->{'found'} eq 'W' ) { >- $getreserv{color} = 'reserved'; >- $getreserv{waiting} = 1; >- } >- >- # check transfers with the itemnumber foud in th reservation loop >- if ($transfertwhen) { >- $getreserv{color} = 'transfered'; >- $getreserv{transfered} = 1; >- $getreserv{datesent} = C4::Dates->new($transfertwhen, 'iso')->output('syspref') or die "Cannot get new($transfertwhen, 'iso') from C4::Dates"; >- $getreserv{frombranch} = GetBranchName($transfertfrom); >- } >- >- if ( ( $getiteminfo->{'holdingbranch'} ne $num_res->{'branchcode'} ) >- and not $transfertwhen ) >- { >- $getreserv{nottransfered} = 1; >- $getreserv{nottransferedby} = >- GetBranchName( $getiteminfo->{'holdingbranch'} ); >- } >- $getreserv{title} = $getiteminfo->{'title'}; >- $getreserv{subtitle} = GetRecordValue('subtitle', GetMarcBiblio($getiteminfo->{biblionumber}), GetFrameworkCode($getiteminfo->{biblionumber})); >- >-# 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'} ); >- my $getbibtype = getitemtypeinfo( $getbibinfo->{'itemtype'} ); >- $getreserv{color} = 'inwait'; >- $getreserv{title} = $getbibinfo->{'title'}; >- $getreserv{subtitle} = GetRecordValue('subtitle', GetMarcBiblio($num_res->{biblionumber}), GetFrameworkCode($num_res->{biblionumber})); >- $getreserv{nottransfered} = 0; >- $getreserv{itemtype} = $getbibtype->{'description'}; >- $getreserv{author} = $getbibinfo->{'author'}; >- $getreserv{biblionumber} = $num_res->{'biblionumber'}; >- } >- $getreserv{waitingposition} = $num_res->{'priority'}; >- $getreserv{suspend} = $num_res->{'suspend'}; >- $getreserv{suspend_until} = $num_res->{'suspend_until'}; >- $getreserv{expirationdate} = $num_res->{'expirationdate'}; >- $getreserv{reserve_id} = $num_res->{'reserve_id'}; >- >- push( @reservloop, \%getreserv ); >- } >- >- # return result to the template >- $template->param( reservloop => \@reservloop, >- countreserv => scalar @reservloop, >- ); >+ $template->param( >+ holds_count => Koha::Database->new()->schema()->resultset('Reserve') >+ ->count( { borrowernumber => $borrowernumber } ) ); > } > > # current alert subscriptions >@@ -435,13 +354,9 @@ $template->param( > totalprice => sprintf("%.2f", $totalprice), > totaldue => sprintf("%.2f", $total), > totaldue_raw => $total, >- issueloop => @issuedata, >- relissueloop => @relissuedata, > overdues_exist => $overdues_exist, >- error => $error, > StaffMember => ($category_type eq 'S'), > is_child => ($category_type eq 'C'), >-# reserveloop => \@reservedata, > samebranch => $samebranch, > quickslip => $quickslip, > activeBorrowerRelationship => (C4::Context->preference('borrowerRelationship') ne ''), >@@ -450,100 +365,8 @@ $template->param( > RoutingSerials => C4::Context->preference('RoutingSerials'), > debarments => GetDebarments({ borrowernumber => $borrowernumber }), > PatronsPerPage => C4::Context->preference("PatronsPerPage") || 20, >+ relatives_issues_count => $relatives_issues_count, >+ relatives_borrowernumbers => \@relatives, > ); >-$template->param( $error => 1 ) if $error; > > output_html_with_http_headers $input, $cookie, $template->output; >- >-sub build_issue_data { >- my $issues = shift; >- >- my $localissue; >- >- foreach my $issue ( @{$issues} ) { >- >- # Getting borrower details >- my $memberdetails = GetMemberDetails( $issue->{borrowernumber} ); >- $issue->{borrowername} = >- $memberdetails->{firstname} . ' ' . $memberdetails->{surname}; >- $issue->{cardnumber} = $memberdetails->{cardnumber}; >- my $issuedate; >- if ($issue->{issuedate} ) { >- $issuedate = $issue->{issuedate}->clone(); >- } >- $issue->{subtitle} = GetRecordValue('subtitle', GetMarcBiblio($issue->{biblionumber}), GetFrameworkCode($issue->{biblionumber})); >- $issue->{issuingbranchname} = GetBranchName($issue->{branchcode}); >- my %row = %{$issue}; >- $totalprice += $issue->{replacementprice}; >- >- # item lost, damaged loops >- if ( $row{'itemlost'} ) { >- my $fw = GetFrameworkCode( $issue->{biblionumber} ); >- my $category = GetAuthValCode( 'items.itemlost', $fw ); >- my $lostdbh = C4::Context->dbh; >- my $sth = $lostdbh->prepare( >-"select lib from authorised_values where category=? and authorised_value =? " >- ); >- $sth->execute( $category, $row{'itemlost'} ); >- my $loststat = $sth->fetchrow; >- if ($loststat) { >- $row{'itemlost'} = $loststat; >- } >- } >- if ( $row{'damaged'} ) { >- my $fw = GetFrameworkCode( $issue->{biblionumber} ); >- my $category = GetAuthValCode( 'items.damaged', $fw ); >- my $damageddbh = C4::Context->dbh; >- my $sth = $damageddbh->prepare( >-"select lib from authorised_values where category=? and authorised_value =? " >- ); >- $sth->execute( $category, $row{'damaged'} ); >- my $damagedstat = $sth->fetchrow; >- if ($damagedstat) { >- $row{'itemdamaged'} = $damagedstat; >- } >- } >- >- # end lost, damaged >- if ( $issue->{overdue} ) { >- $overdues_exist = 1; >- $row{red} = 1; >- } >- if ($issuedate) { >- $issuedate->truncate( to => 'day' ); >- if ( DateTime->compare( $issuedate, $today ) == 0 ) { >- $row{today} = 1; >- } >- } >- >- #find the charge for an item >- my ( $charge, $itemtype ) = >- GetIssuingCharges( $issue->{itemnumber}, $borrowernumber ); >- >- my $itemtypeinfo = getitemtypeinfo($itemtype); >- $row{'itemtype_description'} = $itemtypeinfo->{description}; >- $row{'itemtype_image'} = $itemtypeinfo->{imageurl}; >- >- $row{'charge'} = sprintf( "%.2f", $charge ); >- >- my ( $renewokay, $renewerror ) = >- CanBookBeRenewed( $borrowernumber, $issue->{itemnumber}, >- $override_limit ); >- $row{'norenew'} = !$renewokay; >- $row{'can_confirm'} = ( !$renewokay && $renewerror ne 'on_reserve' ); >- $row{"norenew_reason_$renewerror"} = 1 if $renewerror; >- $row{renew_failed} = $renew_failed{ $issue->{itemnumber} }; >- $row{return_failed} = $return_failed{ $issue->{barcode} }; >- ($row{'renewcount'},$row{'renewsallowed'},$row{'renewsleft'}) = C4::Circulation::GetRenewCount($issue->{'borrowernumber'},$issue->{'itemnumber'}); #Add renewal count to item data display >- >- $row{'soonestrenewdate'} = output_pref( >- C4::Circulation::GetSoonestRenewDate( >- $issue->{borrowernumber}, >- $issue->{itemnumber} >- ) >- ); >- >- push( @{$localissue}, \%row ); >- } >- return $localissue; >-} >diff --git a/svc/checkin.pl b/svc/checkin.pl >new file mode 100755 >index 0000000..a303e52 >--- /dev/null >+++ b/svc/checkin.pl >@@ -0,0 +1,75 @@ >+#!/usr/bin/perl >+ >+# Copyright 2014 ByWater Solutions >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 3 of the License, or (at your option) any later >+# version. >+# >+# Koha 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. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+use CGI; >+use JSON qw(to_json); >+ >+use C4::Circulation; >+use C4::Items qw(GetBarcodeFromItemnumber); >+use C4::Context; >+use C4::Auth qw(check_cookie_auth); >+ >+use Koha::DateUtils qw(output_pref_due); >+ >+my $input = new CGI; >+ >+my ( $auth_status, $sessionID ) = >+ check_cookie_auth( $input->cookie('CGISESSID'), >+ { circulate => 'circulate_remaining_permissions' } ); >+ >+if ( $auth_status ne "ok" ) { >+ exit 0; >+} >+ >+binmode STDOUT, ":encoding(UTF-8)"; >+print $input->header( -type => 'text/plain', -charset => 'UTF-8' ); >+ >+my $itemnumber = $input->param('itemnumber'); >+my $borrowernumber = $input->param('borrowernumber'); >+my $override_limit = $input->param('override_limit'); >+my $exempt_fine = $input->param('exempt_fine'); >+my $branchcode = $input->param('branchcode') >+ || C4::Context->userenv->{'branch'}; >+ >+my $barcode = GetBarcodeFromItemnumber($itemnumber); >+ >+my $data; >+$data->{itemnumber} = $itemnumber; >+$data->{borrowernumber} = $borrowernumber; >+$data->{branchcode} = $branchcode; >+ >+if ( C4::Context->preference("InProcessingToShelvingCart") ) { >+ my $item = GetItem($itemnumber); >+ if ( $item->{'location'} eq 'PROC' ) { >+ $item->{'location'} = 'CART'; >+ ModItem( $item, $item->{'biblionumber'}, $item->{'itemnumber'} ); >+ } >+} >+ >+if ( C4::Context->preference("ReturnToShelvingCart") ) { >+ my $item = GetItem($itemnumber); >+ $item->{'location'} = 'CART'; >+ ModItem( $item, $item->{'biblionumber'}, $item->{'itemnumber'} ); >+} >+ >+( $data->{returned} ) = AddReturn( $barcode, $branchcode, $exempt_fine ); >+ >+print to_json($data); >diff --git a/svc/checkouts.pl b/svc/checkouts.pl >new file mode 100755 >index 0000000..ab59fb4 >--- /dev/null >+++ b/svc/checkouts.pl >@@ -0,0 +1,167 @@ >+#!/usr/bin/perl >+ >+# This software is placed under the gnu General Public License, v2 (http://www.gnu.org/licenses/gpl.html) >+ >+# Copyright 2014 ByWater Solutions >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 3 of the License, or (at your option) any later >+# version. >+# >+# Koha 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. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use strict; >+use warnings; >+ >+use CGI; >+use JSON qw(to_json); >+ >+use C4::Auth qw(check_cookie_auth); >+use C4::Biblio qw(GetMarcBiblio GetFrameworkCode GetRecordValue ); >+use C4::Circulation qw(GetIssuingCharges CanBookBeRenewed GetRenewCount); >+use C4::Context; >+ >+use Koha::DateUtils; >+ >+my $input = new CGI; >+ >+my ( $auth_status, $sessionID ) = >+ check_cookie_auth( $input->cookie('CGISESSID'), >+ { circulate => 'circulate_remaining_permissions' } ); >+ >+if ( $auth_status ne "ok" ) { >+ exit 0; >+} >+ >+my @sort_columns = qw/date_due title itype issuedate branchcode itemcallnumber/; >+ >+my @borrowernumber = $input->param('borrowernumber'); >+my $offset = $input->param('iDisplayStart'); >+my $results_per_page = $input->param('iDisplayLength') || -1; >+my $sorting_column = $sort_columns[ $input->param('iSortCol_0') ] >+ || 'issuedate'; >+my $sorting_direction = $input->param('sSortDir_0') 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 @parameters; >+my $sql = ' >+ SELECT >+ issuedate, >+ date_due, >+ >+ biblionumber, >+ biblio.title, >+ author, >+ >+ itemnumber, >+ barcode, >+ itemnotes, >+ itemcallnumber, >+ replacementprice, >+ >+ issues.branchcode, >+ branchname, >+ >+ itype, >+ itemtype, >+ >+ borrowernumber, >+ surname, >+ firstname, >+ cardnumber >+ FROM issues >+ LEFT JOIN items USING ( itemnumber ) >+ LEFT JOIN biblio USING ( biblionumber ) >+ LEFT JOIN biblioitems USING ( biblionumber ) >+ LEFT JOIN borrowers USING ( borrowernumber ) >+ LEFT JOIN branches ON ( issues.branchcode = branches.branchcode ) >+ WHERE borrowernumber >+'; >+ >+if ( @borrowernumber == 1 ) { >+ $sql .= '= ?'; >+} >+else { >+ $sql = ' IN (' . join( ',', ('?') x @borrowernumber ) . ') '; >+} >+push( @parameters, @borrowernumber ); >+ >+$sql .= " ORDER BY $sorting_column $sorting_direction "; >+ >+my $dbh = C4::Context->dbh(); >+my $sth = $dbh->prepare($sql); >+$sth->execute( @parameters ); >+ >+my $item_level_itypes = C4::Context->preference('item-level_itypes'); >+ >+my @checkouts; >+while ( my $c = $sth->fetchrow_hashref() ) { >+ my ($charge) = GetIssuingCharges( $c->{itemnumber}, $c->{borrowernumber} ); >+ >+ my ( $can_renew, $can_renew_error ) = >+ CanBookBeRenewed( $c->{borrowernumber}, $c->{itemnumber} ); >+ >+ my ( $renewals_count, $renewals_allowed, $renewals_remaining ) = >+ GetRenewCount( $c->{borrowernumber}, $c->{itemnumber} ); >+ push( >+ @checkouts, >+ { >+ DT_RowId => $c->{itemnumber} . '-' . $c->{borrowernumber}, >+ title => $c->{title}, >+ author => $c->{author}, >+ barcode => $c->{barcode}, >+ itemtype => $item_level_itypes ? $c->{itype} : $c->{itemtype}, >+ itemnotes => $c->{itemnotes}, >+ branchcode => $c->{branchcode}, >+ branchname => $c->{branchname}, >+ itemcallnumber => $c->{itemcallnumber} || q{}, >+ charge => $charge, >+ price => $c->{replacementprice} || q{}, >+ can_renew => $can_renew, >+ can_renew_error => $can_renew_error, >+ itemnumber => $c->{itemnumber}, >+ borrowernumber => $c->{borrowernumber}, >+ biblionumber => $c->{biblionumber}, >+ issuedate => $c->{issuedate}, >+ date_due => $c->{date_due}, >+ renewals_count => $renewals_count, >+ renewals_allowed => $renewals_allowed, >+ renewals_remaining => $renewals_remaining, >+ issuedate_formatted => >+ output_pref( dt_from_string( $c->{issuedate} ) ), >+ date_due_formatted => >+ output_pref_due( dt_from_string( $c->{date_due} ) ), >+ subtitle => GetRecordValue( >+ 'subtitle', >+ GetMarcBiblio( $c->{biblionumber} ), >+ GetFrameworkCode( $c->{biblionumber} ) >+ ), >+ borrower => { >+ surname => $c->{surname}, >+ firstname => $c->{firstname}, >+ cardnumber => $c->{cardnumber}, >+ } >+ } >+ ); >+} >+ >+my $data; >+$data->{'iTotalRecords'} = scalar @checkouts; #FIXME >+$data->{'iTotalDisplayRecords'} = scalar @checkouts; >+$data->{'sEcho'} = $input->param('sEcho') || undef; >+$data->{'aaData'} = \@checkouts; >+ >+print to_json($data); >diff --git a/svc/holds.pl b/svc/holds.pl >new file mode 100755 >index 0000000..9fbdb5f >--- /dev/null >+++ b/svc/holds.pl >@@ -0,0 +1,143 @@ >+#!/usr/bin/perl >+ >+# This software is placed under the gnu General Public License, v2 (http://www.gnu.org/licenses/gpl.html) >+ >+# Copyright 2014 ByWater Solutions >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 3 of the License, or (at your option) any later >+# version. >+# >+# Koha 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. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+use CGI; >+use JSON qw(to_json); >+ >+use C4::Auth qw(check_cookie_auth); >+use C4::Biblio qw(GetMarcBiblio GetFrameworkCode GetRecordValue ); >+use C4::Branch qw(GetBranchName); >+use C4::Charset; >+use C4::Circulation qw(GetTransfers); >+use C4::Context; >+ >+use Koha::Database; >+use Koha::DateUtils; >+ >+my $input = new CGI; >+ >+my ( $auth_status, $sessionID ) = >+ check_cookie_auth( $input->cookie('CGISESSID'), >+ { circulate => 'circulate_remaining_permissions' } ); >+ >+if ( $auth_status ne "ok" ) { >+ exit 0; >+} >+ >+my $branch = C4::Context->userenv->{'branch'}; >+ >+my $schema = Koha::Database->new()->schema(); >+ >+my @sort_columns = >+ qw/reservedate title itemcallnumber barcode expirationdate priority/; >+ >+my $borrowernumber = $input->param('borrowernumber'); >+my $offset = $input->param('iDisplayStart'); >+my $results_per_page = $input->param('iDisplayLength'); >+my $sorting_direction = $input->param('sSortDir_0') || 'desc'; >+my $sorting_column = $sort_columns[ $input->param('iSortCol_0') ] >+ || 'reservedate'; >+ >+binmode STDOUT, ":encoding(UTF-8)"; >+print $input->header( -type => 'text/plain', -charset => 'UTF-8' ); >+ >+my $holds_rs = $schema->resultset('Reserve')->search( >+ { borrowernumber => $borrowernumber }, >+ { >+ prefetch => { 'item' => 'biblio' }, >+ order_by => { "-$sorting_direction" => $sorting_column } >+ } >+); >+ >+my $borrower; >+my @holds; >+while ( my $h = $holds_rs->next() ) { >+ my $item = $h->item(); >+ >+ my $biblionumber = $h->biblio()->biblionumber(); >+ >+ my $hold = { >+ DT_RowId => $h->reserve_id(), >+ biblionumber => $biblionumber, >+ title => $h->biblio()->title(), >+ author => $h->biblio()->author(), >+ reserve_id => $h->reserve_id(), >+ reservedate => $h->reservedate(), >+ expirationdate => $h->expirationdate(), >+ suspend => $h->suspend(), >+ suspend_until => $h->suspend_until(), >+ found => $h->found(), >+ waiting => $h->found() eq 'W', >+ waiting_at => $h->branchcode()->branchname(), >+ waiting_here => $h->branchcode()->branchcode() eq $branch, >+ priority => $h->priority(), >+ subtitle => GetRecordValue( >+ 'subtitle', GetMarcBiblio($biblionumber), >+ GetFrameworkCode($biblionumber) >+ ), >+ reservedate_formatted => $h->reservedate() >+ ? output_pref_due( dt_from_string( $h->reservedate() ) ) >+ : q{}, >+ suspend_until_formatted => $h->suspend_until() >+ ? output_pref_due( dt_from_string( $h->suspend_until() ) ) >+ : q{}, >+ expirationdate_formatted => $h->expirationdate() >+ ? output_pref_due( dt_from_string( $h->expirationdate() ) ) >+ : q{}, >+ }; >+ >+ $hold->{transfered} = 0; >+ $hold->{not_transfered} = 0; >+ >+ if ($item) { >+ $hold->{itemnumber} = $item->itemnumber(); >+ $hold->{barcode} = $item->barcode(); >+ $hold->{itemtype} = $item->effective_itemtype(); >+ $hold->{itemcallnumber} = $item->itemcallnumber() || q{}; >+ >+ my ( $transferred_when, $transferred_from, $transferred_to ) = >+ GetTransfers( $item->itemnumber() ); >+ if ($transferred_when) { >+ $hold->{color} = 'transferred'; >+ $hold->{transferred} = 1; >+ $hold->{date_sent} = format_date($transferred_when); >+ $hold->{from_branch} = GetBranchName($transferred_from); >+ } >+ elsif ( $item->holdingbranch()->branchcode() ne >+ $h->branchcode()->branchcode() ) >+ { >+ $hold->{not_transferred} = 1; >+ $hold->{not_transferred_by} = $h->branchcode()->branchname(); >+ } >+ } >+ >+ push( @holds, $hold ); >+} >+ >+my $data; >+$data->{'iTotalRecords'} = scalar @holds; >+$data->{'iTotalDisplayRecords'} = scalar @holds; >+$data->{'sEcho'} = $input->param('sEcho') || undef; >+$data->{'aaData'} = \@holds; >+ >+print to_json($data); >diff --git a/svc/renew.pl b/svc/renew.pl >new file mode 100755 >index 0000000..add9e9f >--- /dev/null >+++ b/svc/renew.pl >@@ -0,0 +1,69 @@ >+#!/usr/bin/perl >+ >+# Copyright 2014 ByWater Solutions >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 3 of the License, or (at your option) any later >+# version. >+# >+# Koha 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. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use Modern::Perl; >+ >+use CGI; >+use JSON qw(to_json); >+ >+use C4::Circulation; >+use C4::Context; >+use C4::Auth qw(check_cookie_auth); >+ >+use Koha::DateUtils qw(output_pref_due dt_from_string); >+ >+my $input = new CGI; >+ >+my ( $auth_status, $sessionID ) = >+ check_cookie_auth( $input->cookie('CGISESSID'), >+ { circulate => 'circulate_remaining_permissions' } ); >+ >+if ( $auth_status ne "ok" ) { >+ exit 0; >+} >+ >+binmode STDOUT, ":encoding(UTF-8)"; >+print $input->header( -type => 'text/plain', -charset => 'UTF-8' ); >+ >+my $itemnumber = $input->param('itemnumber'); >+my $borrowernumber = $input->param('borrowernumber'); >+my $override_limit = $input->param('override_limit'); >+my $branchcode = $input->param('branchcode') >+ || C4::Context->userenv->{'branch'}; >+my $date_due; >+if ( $input->param('date_due') ) { >+ $date_due = dt_from_string( $input->param('date_due') ); >+ $date_due->set_hour(23); >+ $date_due->set_minute(59); >+} >+ >+my $data; >+$data->{itemnumber} = $itemnumber; >+$data->{borrowernumber} = $borrowernumber; >+$data->{branchcode} = $branchcode; >+ >+( $data->{renew_okay}, $data->{error} ) = >+ CanBookBeRenewed( $borrowernumber, $itemnumber, $override_limit ); >+ >+if ( $data->{renew_okay} ) { >+ $date_due = AddRenewal( $borrowernumber, $itemnumber, $branchcode, $date_due ); >+ $data->{date_due} = output_pref_due( $date_due ); >+} >+ >+print to_json($data); >-- >1.7.2.5
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 11703
:
25105
|
25110
|
25111
|
25213
|
25217
|
25218
|
25220
|
25221
|
25261
|
25262
|
25263
|
25264
|
25271
|
25272
|
25289
|
25290
|
25292
|
25390
|
25391
|
25986
|
25987
|
25988
|
25989
|
25990
|
25991
|
25992
|
25993
|
25994
|
25995
|
25996
|
25997
|
25998
|
25999
|
26081
|
26085
|
26115
|
26131
|
26158
|
26160
|
26241
|
26986
|
26990
|
26991
|
27102
|
27241
|
27338
|
27339
|
27340
|
27341
|
27342
|
27349
|
27350
|
27353
|
27354
|
27356
|
27548
|
27610
|
27717
|
27718
|
27745
|
27746
|
27750
|
27751
|
28025
|
28026
|
28027
|
28028
|
28029
|
29195
|
29196
|
29197
|
29198
|
29199
|
29279
|
29280
|
29281
|
29282
|
29283
|
29284
|
29419
|
29420
|
29432
|
29433
|
29434
|
29438
|
29439
|
29440
|
29444
|
29445
|
29446
|
29447
|
29448
|
29449
|
29450
|
29451
|
29452
|
29453
|
29454
|
29472
|
29473
|
29474
|
29475
|
29476
|
29477
|
29478
|
29479
|
29480
|
29493
|
30228