From a3fa8f04acbd75b366a637d0d11cd714614e6e64 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Tue, 18 Apr 2023 16:29:44 +0200 Subject: [PATCH] Bug 33568: Separate holdings MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This needs to be well tested! Sysprefs SeparateHoldings and SeparateHoldingsBranch As well as the "Lost items in staff interface" that can be defined at patron's category level. This patch is simply restoring the previous behaviour but I think we could do better. Signed-off-by: Owen Leonard Signed-off-by: Laurence Rault Signed-off-by: Emily Lamancusa Signed-off-by: Tomás Cohen Arazi Signed-off-by: Katrin Fischer --- Koha/REST/V1/Biblios.pm | 2 + catalogue/detail.pl | 162 +-- .../prog/en/modules/catalogue/detail.tt | 1294 +++++++---------- 3 files changed, 503 insertions(+), 955 deletions(-) diff --git a/Koha/REST/V1/Biblios.pm b/Koha/REST/V1/Biblios.pm index 59f70c97d0..b5a092332a 100644 --- a/Koha/REST/V1/Biblios.pm +++ b/Koha/REST/V1/Biblios.pm @@ -300,6 +300,8 @@ sub get_items { return try { + # FIXME We need to order_by serial.publisheddate if we have _order_by=+me.serial_issue_number + # Should we use search_ordered here? Maybe as well in Koha::REST::V1::Items::list? # FIXME Do we always need host_items => 1 or depending on a flag? # FIXME Should we prefetch => ['issue','branchtransfer']? my $items_rs = $biblio->items( { host_items => 1 } )->search( {}, { join => 'biblioitem' } ) ); diff --git a/catalogue/detail.pl b/catalogue/detail.pl index 4bed0bc700..774dab7c10 100755 --- a/catalogue/detail.pl +++ b/catalogue/detail.pl @@ -190,21 +190,18 @@ $template->param( ); my $itemtypes = { map { $_->itemtype => $_ } @{ Koha::ItemTypes->search_with_localization->as_list } }; -my $params; my $patron = Koha::Patrons->find( $borrowernumber ); -$params->{ itemlost } = 0 if $patron->category->hidelostitems && !$showallitems; +my $include_lost_items = !$patron->category->hidelostitems || $showallitems; my $items_params = { ( $invalid_marc_record ? () : ( host_items => 1 ) ), }; -my $items = $biblio->items($items_params)->search_ordered( $params, { prefetch => ['issue','current_branchtransfers'] } ); +my $all_items = $biblio->items($items_params); +my $items_to_display = $all_items->search({ $include_lost_items ? () : ( itemlost => 0 ) }); # flag indicating existence of at least one item linked via a host record my $hostrecords = $biblio->host_items->count; my $dat = &GetBiblioData($biblionumber); -$dat->{'count'} = $biblio->items($items_params)->count; -$dat->{'showncount'} = $items->count; -$dat->{'hiddencount'} = $dat->{'count'} - $dat->{'showncount'}; #is biblio a collection and are bundles enabled my $leader = $marc_record->leader(); @@ -321,138 +318,18 @@ if ( defined $dat->{'itemtype'} ) { $dat->{imageurl} = getitemtypeimagelocation( 'intranet', $itemtypes->{ $dat->{itemtype} }->imageurl ); } -my (@itemloop, @otheritemloop, %itemfields); - -my $mss = Koha::MarcSubfieldStructures->search({ frameworkcode => $fw, kohafield => 'items.itemlost', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] }); -if ( $mss->count ) { - $template->param( itemlostloop => GetAuthorisedValues( $mss->next->authorised_value ) ); -} -$mss = Koha::MarcSubfieldStructures->search({ frameworkcode => $fw, kohafield => 'items.damaged', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] }); -if ( $mss->count ) { - $template->param( itemdamagedloop => GetAuthorisedValues( $mss->next->authorised_value ) ); -} -$mss = Koha::MarcSubfieldStructures->search({ frameworkcode => $fw, kohafield => 'items.withdrawn', authorised_value => { not => undef } }); -if ( $mss->count ) { - $template->param( itemwithdrawnloop => GetAuthorisedValues( $mss->next->authorised_value) ); +if ( C4::Context->preference('SeparateHoldings') ) { + my $SeparateHoldingsBranch = C4::Context->preference('SeparateHoldingsBranch') || 'homebranch'; + my $other_holdings_count = $items_to_display->search({ $SeparateHoldingsBranch => { '!=' => C4::Context->userenv->{branch} } })->count; + $template->param( other_holdings_count => $other_holdings_count ); } - -$mss = Koha::MarcSubfieldStructures->search({ frameworkcode => $fw, kohafield => 'items.materials', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] }); -my %materials_map; -if ($mss->count) { - my $materials_authvals = GetAuthorisedValues($mss->next->authorised_value); - if ($materials_authvals) { - foreach my $value (@$materials_authvals) { - $materials_map{$value->{authorised_value}} = $value->{lib}; - } - } -} - -my $analytics_flag; -my $materials_flag; # set this if the items have anything in the materials field -my $currentbranch = C4::Context->userenv ? C4::Context->userenv->{branch} : undef; -if ($currentbranch and C4::Context->preference('SeparateHoldings')) { - $template->param(SeparateHoldings => 1); -} -my $separatebranch = C4::Context->preference('SeparateHoldingsBranch') || 'homebranch'; -my ( $itemloop_has_images, $otheritemloop_has_images ); - -while ( my $item = $items->next ) { - my $itembranchcode = $item->$separatebranch; - - my $item_info = $item->unblessed; - $item_info->{itemtype} = $itemtypes->{$item->effective_itemtype}; - - foreach (qw(ccode enumchron copynumber stocknumber itemnotes itemnotes_nonpublic uri )) { - $itemfields{$_} = 1 if $item->$_; - } - - # FIXME The following must be Koha::Item->serial - my $serial_item = Koha::Serial::Items->find($item->itemnumber); - if ( $serial_item ) { - my $serial = Koha::Serials->find($serial_item->serialid); - $item_info->{serial} = $serial if $serial; - $itemfields{publisheddate} = 1; - } - - $item_info->{object} = $item; - - # checking for holds - my $holds = $item->current_holds; - if ( my $first_hold = $holds->next ) { - $item_info->{first_hold} = $first_hold; - } - - #item has a host number if its biblio number does not match the current bib - - if ($item->biblionumber ne $biblionumber){ - $item_info->{hostbiblionumber} = $item->biblionumber; - $item_info->{hosttitle} = $item->biblio->title; - } - - - if ( $analyze ) { - # count if item is used in analytical bibliorecords - # The 'countanalytics' flag is only used in the templates if analyze is set - my $countanalytics = GetAnalyticsCount( $item->itemnumber ); - if ($countanalytics > 0){ - $analytics_flag=1; - $item_info->{countanalytics} = $countanalytics; - } - } - - if (defined($item->materials) && $item->materials =~ /\S/){ - $materials_flag = 1; - if (defined $materials_map{ $item->materials }) { - $item_info->{materials} = $materials_map{ $item->materials }; - } - } - - if ( C4::Context->preference('UseCourseReserves') ) { - $item_info->{'course_reserves'} = GetItemCourseReservesInfo( itemnumber => $item->itemnumber ); - } - - $item_info->{can_be_edited} = $patron->can_edit_items_from( $item->homebranch ); - - if ( $item->is_bundle ) { - $item_info->{bundled} = - $item->bundle_items->search( { itemlost => { '!=' => 0 } } ) - ->count; - $item_info->{bundled_lost} = - $item->bundle_items->search( { itemlost => 0 } )->count; - $item_info->{is_bundle} = 1; - } - - if ($item->in_bundle) { - $item_info->{bundle_host} = $item->bundle_host; - } - - if ($currentbranch and C4::Context->preference('SeparateHoldings')) { - if ($itembranchcode and $itembranchcode eq $currentbranch) { - push @itemloop, $item_info; - $itemloop_has_images++ if $item->cover_images->count; - } else { - push @otheritemloop, $item_info; - $otheritemloop_has_images++ if $item->cover_images->count; - } - } else { - push @itemloop, $item_info; - $itemloop_has_images++ if $item->cover_images->count; - } -} - $template->param( - itemloop_has_images => $itemloop_has_images, - otheritemloop_has_images => $otheritemloop_has_images, + count => $all_items->count, # FIXME 'count' is used in catalog-strings.inc + # But it's not a meaningful variable, we should rename it there + all_items_count => $all_items->count, + items_to_display_count => $items_to_display->count, ); -# Display only one tab if one items list is empty -if (scalar(@itemloop) == 0 || scalar(@otheritemloop) == 0) { - $template->param(SeparateHoldings => 0); - if (scalar(@itemloop) == 0) { - @itemloop = @otheritemloop; - } -} - my $some_private_shelves = Koha::Virtualshelves->get_some_shelves( { borrowernumber => $borrowernumber, @@ -476,23 +353,12 @@ $template->param( $template->param( MARCNOTES => !$invalid_marc_record ? $biblio->get_marc_notes() : undef, - itemdata_ccode => $itemfields{ccode}, - itemdata_enumchron => $itemfields{enumchron}, - itemdata_uri => $itemfields{uri}, - itemdata_copynumber => $itemfields{copynumber}, - itemdata_stocknumber => $itemfields{stocknumber}, - itemdata_publisheddate => $itemfields{publisheddate}, - volinfo => $itemfields{enumchron}, - itemdata_itemnotes => $itemfields{itemnotes}, - itemdata_nonpublicnotes => $itemfields{itemnotes_nonpublic}, z3950_search_params => C4::Search::z3950_search_args($dat), hostrecords => $hostrecords, - analytics_flag => $analytics_flag, C4::Search::enabled_staff_search_views, - materials => $materials_flag, ); -if (C4::Context->preference("AlternateHoldingsField") && $items->count == 0) { +if (C4::Context->preference("AlternateHoldingsField") && $items_to_display->count == 0) { my $fieldspec = C4::Context->preference("AlternateHoldingsField"); my $subfields = substr $fieldspec, 3; my $holdingsep = C4::Context->preference("AlternateHoldingsSeparator") || ' '; @@ -528,8 +394,6 @@ foreach ( keys %{$dat} ) { # method query not found?!?! $template->param( AmazonTld => get_amazon_tld() ) if ( C4::Context->preference("AmazonCoverImages")); $template->param( - itemloop => \@itemloop, - otheritemloop => \@otheritemloop, biblionumber => $biblionumber, ($analyze? 'analyze':'detailview') =>1, subscriptions => \@subs, @@ -634,7 +498,7 @@ if ( C4::Context->preference('UseCourseReserves') ) { $template->param( course_reserves => $course_reserves ); } -my @libraries = $biblio->items({ host_items => 1 })->get_column('homebranch'); +my @libraries = $biblio->items($items_params)->get_column('homebranch'); my %can_edit_items_from = map { $_ => $patron->can_edit_items_from($_) } @libraries; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt index b0d29e87c0..d9851e03c8 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt @@ -284,16 +284,17 @@ + - - [% IF (StaffDetailItemSelection) %][% END %] - [% IF Koha.Preference('LocalCoverImages') && ( tab == 'holdings' && itemloop_has_images || tab == 'otherholdings' && otheritemloop_has_images ) %] - - [% END %] - [% IF ( item_level_itypes ) %][% END %] - - - [% IF ( itemdata_ccode ) %][% END %] - [% IF Koha.Preference('EnableItemGroups') %] - - [% END %] - - [% IF volinfo %] - - [% END %] - - - - - - - - [% IF ( itemdata_uri ) %][% END %] - [% IF ( itemdata_copynumber ) %][% END %] - [% IF ( itemdata_stocknumber ) %][% END %] - [% IF materials %][% END %] - [% IF ( itemdata_itemnotes ) %][% END %] - [% IF ( itemdata_nonpublicnotes ) %][% END %] - [% IF ( hostrecords ) %][% END %] - [% IF ( analyze ) %][% END %] - [% IF ( ShowCourseReserves ) %][% END %] - [% IF ( SpineLabelShowPrintOnBibDetails ) %][% END %] - [% IF ( CAN_user_editcatalogue_edit_items ) %][% END %] + [% IF (StaffDetailItemSelection) %][% END %] + [% IF Koha.Preference('LocalCoverImages') %] + + [% END %] + [% IF ( item_level_itypes ) %][% END %] + + + + [% IF Koha.Preference('EnableItemGroups') %] + + [% END %] + + + + + + + + + + + + + + + + [% IF ( hostrecords ) %][% END %] + [% IF ( analyze ) %][% END %] + [% IF ( ShowCourseReserves ) %][% END %] + [% IF ( SpineLabelShowPrintOnBibDetails ) %][% END %] + [% IF ( CAN_user_editcatalogue_edit_items ) %][% END %] - - [% FOREACH item IN items %] - [% SET date_due = item.object.checkout.date_due %] - - [% IF (StaffDetailItemSelection) %] - - [% END %] - [% IF Koha.Preference('LocalCoverImages') && ( tab == 'holdings' && itemloop_has_images || tab == 'otherholdings' && otheritemloop_has_images ) %] - - [% END %] - - [% IF ( item_level_itypes ) %] - - [% END %] - - - [% IF ( itemdata_ccode ) %][% END %] - [% IF Koha.Preference('EnableItemGroups') %][% END %] - - [% IF ( volinfo ) %] - [% SET serial = item.serial %] - [% IF itemdata_publisheddate #If there is at least one published date, use it for sorting %] - - [% END %] - - - - - - - - [% IF ( itemdata_uri ) %] - [% IF item.uri.split(' \| ').size > 1 %] - - [% ELSE %] - - [% END %] - [% END %] - [% IF ( itemdata_copynumber ) %] - - [% END %] - [% IF ( itemdata_stocknumber ) %] - - [% END %] - [% IF materials %] - - [% END %] - [% IF ( itemdata_itemnotes ) %] - - [% END %] - [% IF itemdata_nonpublicnotes %] - - [% END %] - [% IF ( hostrecords ) %] - - [% END %] - [% IF ( analyze ) %] - - [% END %] - [% IF ( analyze ) %] - - [% END %] - - [% IF ShowCourseReserves %] - - [% END %] - - [% IF ( SpineLabelShowPrintOnBibDetails ) %] - - [% END %] - - [% IF CAN_user_editcatalogue_edit_items %] - - [% END %] - - [% END %] -
Cover imageItem typeCurrent libraryHome libraryCollectionItem groupCall numberSerial enumeration / chronologyStatusLast seenCheckoutsRenewalsDate accessionedDate last borrowedBarcodeURLCopy numberInventory numberMaterials specifiedPublic notesNon-public notesHost recordsUsed inCourse reservesSpine label Cover imageItem typeCurrent libraryHome libraryCollectionItem groupCall numberSerial enumeration / chronologyStatusLast seenCheckoutsRenewalsDate accessionedDate last borrowedBarcodeURLCopy numberInventory numberMaterials specifiedPublic notesNon-public notesHost recordsUsed inCourse reservesSpine label 
- [% IF item.can_be_edited %] - - [% END %] - -
-
- [% FOREACH image IN item.object.cover_images %] -
- - Local cover image - -
- [% END %] -
-
-
- [% SET itemtype = item.itemtype %] - [% IF !noItemTypeImages && itemtype.image_location('intranet') %] - [% itemtype.translated_description | html %] - [% END %] - [% itemtype.translated_description | html %] - [% UNLESS ( singlebranchmode ) %][% Branches.GetName( item.holdingbranch ) | html %] [% END %] - [% Branches.GetName(item.homebranch) | html %] - - [%# If permanent location is defined, show description or code and %] - [%# display current location in parentheses. If not, display current location. %] - [%# Note that permanent location is a code, and location may be an authval. %] - [% SET item_location = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.location ) %] - [% IF item.permanent_location %] - [% SET permloc_authval = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.permanent_location ) %] - [% permloc_authval | html %] - [% IF item_location AND item_location != permloc_authval AND item.location != item.permanent_location %] - ([% item_location | html %]) - [% END %] - [% ELSE %] - [% item_location | html %] - [% END %] - - [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => item.ccode ) | html %][% item.object.item_group.description | html %][% IF ( item.itemcallnumber ) %] [% item.itemcallnumber | html %][% END %] - [% ELSE %] - - [% END %] - [% IF ( itemdata_enumchron ) %] - [% IF item.enumchron && serial.serialseq %] - [% item.enumchron | html %] - [% IF ( serial.serialseq && item.enumchron != serial.serialseq ) %] - -- - [% serial.serialseq | html %] - [% END %] - [% ELSIF item.enumchron %] - [% item.enumchron | html %] - [% ELSIF item.serialseq %] - [% serial.serialseq | html %] - [% END %] - [% IF serial.publisheddate %] - ([% serial.publisheddate | $KohaDates %]) - [% END %] - [% END %] - - - - [% IF item.object.checkout %] - [% IF item.object.checkout.onsite_checkout %] -
Currently in local use - [% ELSE %] -
Checked out - [% END %] - [% IF item.object.checkout.onsite_checkout %] - by - [% ELSE %] - to - [% END %] - [% INCLUDE 'patron-title.inc' patron=item.object.checkout.patron hide_patron_infos_if_needed=1 %] - : due [% date_due | $KohaDates as_due_date => 1 %] -
- [% ELSIF ( transfer = item.object.get_transfer ) %] - [% IF (transfer.datesent) %] -
In transit from [% Branches.GetName( transfer.frombranch ) | html %] to [% Branches.GetName( transfer.tobranch ) | html %] since [% transfer.datesent | $KohaDates %]
- [% ELSE %] -
Transit pending from [% Branches.GetName( transfer.frombranch ) | html %] to [% Branches.GetName( transfer.tobranch ) | html %] since [% transfer.daterequested | $KohaDates %]
- [% END %] - [% END %] - - [% IF ( item.itemlost ) %] - [% SET itemlost_description = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.itemlost', authorised_value => item.itemlost ) %] - [% IF itemlostloop %] -
[% itemlost_description | html %]
- [% ELSE %] -
Unavailable (lost or missing)
- [% END %] - [% END %] - - [% IF ( item.withdrawn ) %] - [% SET withdrawn_description = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.withdrawn', authorised_value => item.withdrawn ) %] - [% IF withdrawn_description %] -
[% withdrawn_description | html %]
- [% ELSE %] -
Withdrawn
- [% END %] - [% END %] - - [% IF ( item.damaged ) %] - [% SET damaged_description = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.damaged', authorised_value => item.damaged ) %] - [% IF damaged_description %] -
[% damaged_description | html %]
- [% ELSE %] -
Damaged
- [% END %] - [% END %] - - [% IF ( item.notforloan || item.itemtype.notforloan ) %] -
Not for loan - [% SET not_for_loan_description = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.notforloan', authorised_value => item.notforloan ) %] - [% IF not_for_loan_description %] - ([% not_for_loan_description | html %]) - [% END %] -
- [% END %] - - [% SET hold = item.first_hold %] - [% IF hold %] - [% IF hold.waitingdate %] -
Waiting at [% Branches.GetName( hold.branchcode ) | html %][% IF ( hold.desk_id ) %], [% hold.desk.desk_name | html %][% END %] since [% hold.waitingdate | $KohaDates %].
- [% IF canreservefromotherbranches AND ( hold.waitingdate OR hold.priority == 1 ) %] - Hold for: - [% INCLUDE 'patron-title.inc' patron=hold.borrower hide_patron_infos_if_needed=1 %] - [% END %] - [% ELSE %] -
There is an item level hold on this item (priority = [% hold.priority | html %]).
- [% END %] - [% END %] - - [% IF Koha.Preference('UseRecalls') %] - [% SET recall = item.object.recall %] - [% IF recall %] - [% IF recall.waiting_date %] -
Waiting at [% Branches.GetName( recall.pickup_library_id ) | html %] since [% recall.waiting_date | $KohaDates %]
- [% ELSE %] - [% patron_link = BLOCK %][% recall.patron.firstname | html %] [% recall.patron.surname | html %] ([% recall.patron.cardnumber | html %])[% END %] -
recalled by [% patron_link| $raw %] on [% recall.created_date | $KohaDates %]
- [% END %] - [% END %] - [% END %] - - [% UNLESS ( item.notforloan || item.itemtype.notforloan || item.onloan || item.itemlost || item.withdrawn || item.damaged || transfer || hold || ( Koha.Preference('UseRecalls') && recall ) ) %] -
Available
- [% END %] - - [% IF ( item.restricted ) %] -
([% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.restricted', authorised_value => item.restricted ) | html %])
- [% END %] - - [% IF ( item.bundle_host ) %] -
In bundle: [% INCLUDE 'biblio-title.inc' biblio = item.bundle_host.biblio link = 1 %]
- [% END %] - -
[% item.datelastseen | $KohaDates with_hours => 1 %][% item.issues || 0 | html %][% item.renewals || 0 | html %][% item.dateaccessioned | $KohaDates %][% item.datelastborrowed | $KohaDates %][% item.barcode | html %] - [% FOREACH uri IN item.uri.split(' \| ') %][% uri | html %]
[% END %] -
- [% IF item.uri %] - [% IF Koha.Preference('URLLinkText') %][% Koha.Preference('URLLinkText') | html %][% ELSE %]Link to resource[% END %] - [% END %] - [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.copynumber', authorised_value => item.copynumber ) | html %][% item.stocknumber | html %] [% item.materials | html %]
[% item.object.itemnotes.replace('\n','
') | $raw %]
[% item.itemnotes_nonpublic | html %][% IF ( item.hostbiblionumber) %][% item.hosttitle | html %][% END %] - [% IF ( item.countanalytics ) %] - [% item.countanalytics | html %] analytics - [% END %] - Create analytics - [% IF item.course_reserves %] - [% FOREACH r IN item.course_reserves %] - [% IF r.course.enabled == 'yes' %] -

- - [% r.course.course_name | html %] - - [% IF r.course.section %] [% r.course.section | html %] [% END %] - [% IF r.course.term %] [% AuthorisedValues.GetByCode( 'TERM', r.course.term ) | html %] [% END %] - -

- [% END %] - [% END %] - [% END %] -
Print label - [% IF item.can_be_edited %] - [% IF Koha.Preference('LocalCoverImages') OR Koha.Preference('OPACLocalCoverImages') %] - - [% ELSE %] - Edit - [% END %] - [% END %] - [% IF bundlesEnabled %] - - [% END %] -
- [% END %][%# end of block items_table %] [% IF Koha.Preference('EnableItemGroups') %] @@ -693,51 +416,13 @@ [% END %] -[% IF ( count ) %] - [% IF ( showncount ) %] - [%# PROCESS items_table tab="holdings" items=itemloop %] - - [% SET tab="holdings" %] - - - [% IF (StaffDetailItemSelection) %][% END %] - [% IF Koha.Preference('LocalCoverImages') %] - - [% END %] - [% IF ( item_level_itypes ) %][% END %] - - - - [% IF Koha.Preference('EnableItemGroups') %] - - [% END %] - - - - - - - - - - - - - - - - [% IF ( hostrecords ) %][% END %] - [% IF ( analyze ) %][% END %] - [% IF ( ShowCourseReserves ) %][% END %] - [% IF ( SpineLabelShowPrintOnBibDetails ) %][% END %] - [% IF ( CAN_user_editcatalogue_edit_items ) %][% END %] - - -
Cover imageItem typeCurrent libraryHome libraryCollectionItem groupCall numberSerial enumeration / chronologyStatusLast seenCheckoutsRenewalsDate accessionedDate last borrowedBarcodeURLCopy numberInventory numberMaterials specifiedPublic notesNon-public notesHost recordsUsed inCourse reservesSpine label 
- [% END %] +[% SET hidden_count = all_items_count - items_to_display_count %] +[% IF all_items_count %] + [% PROCESS items_table tab="holdings" %] - [% IF ( hiddencount ) %] -

Show all items ([% hiddencount | html %] hidden) + [% IF hidden_count %] + [%# FIXME We could deal with that in JS and prevent a full refresh %] +

Show all items ([% hidden_count | html %] hidden) [% END %] [% ELSE %] [% IF ( ALTERNATEHOLDINGS ) %] @@ -757,13 +442,9 @@ [% END %] -[% IF (SeparateHoldings) %] +[% IF Koha.Preference('SeparateHoldings') %]

- [% IF (otheritemloop.size) %] - [% PROCESS items_table tab="otherholdings" items=otheritemloop %] - [% ELSE %] - No other items. - [% END %] + [% PROCESS items_table tab="otherholdings" %]
[% END %] @@ -2171,21 +1852,21 @@ // End bundle handling [% END %] - var table_names = [ 'holdings_table', 'otherholdings_table' ]; + var table_ids = [ 'holdings_table', 'otherholdings_table' ]; var table_settings = [ [% TablesSettings.GetTableSettings('catalogue', 'detail','holdings_table','json') | $raw %], [% TablesSettings.GetTableSettings('catalogue', 'detail','otherholdings_table','json') | $raw %] ]; - var has_images = [ "[% itemloop_has_images | html %]", "[% otheritemloop_has_images | html %]" ]; - table_names.forEach( function( table_name, index ) { - if ( !has_images[index] ) { - table_settings[index].columns.splice(1,1); - } - var dt_parameters = { - "dom": 't', - "paginate": false, - "autoWidth": false, - "bKohaColumnsUseNames": true, - "dom": 'C<"top pager"ilpfB><"#filter_c">tr<"bottom pager"ip>', - }; - var table = KohaTable( table_name, dt_parameters, table_settings[index], 'with_filters' ); + table_ids.forEach( function( table_id, index ) { + let filters = {}; + [% IF Koha.Preference('SeparateHoldings') %] + [% SET SeparateHoldingsBranch = Koha.Preference('SeparateHoldingsBranch') || 'homebranch' %]; + let branch = '[% IF SeparateHoldingsBranch == 'homebranch' %]home_library_id[% ELSE %]holding_library_id[% END %]'; + if ( table_id == 'holdings_table' ) { + filters[branch] = '[% Branches.GetLoggedInBranchcode() | html %]'; + } else { + filters[branch] = { '!=': '[% Branches.GetLoggedInBranchcode() | html %]' }; + } + [% END %] + + var table = build_table(table_id, table_settings[index], filters); [% IF bundlesEnabled %] // Add event listener for opening and closing bundle details @@ -2498,7 +2179,10 @@ [% ELSE %] const url_link_text = _("Link to resource"); [% END %] - let table_url = "/api/v1/biblios/[% biblio.biblionumber | uri %]/items?"; + [%# FIXME The X-Base-Total-Count will be the number of items of the biblios %] + [%# In case or SeparateHoldings we may need to display the number of biblios in each tab %] + [%# Do we need separate/new endpoints or do we hack the somewhere client-side? %] + let item_table_url = "/api/v1/biblios/[% biblio.biblionumber | uri %]/items?"; let embed = ["+strings,checkout,checkout.patron,transfer,first_hold,first_hold.patron,item_type"]; [% IF Koha.Preference('LocalCoverImages') %] embed.push('cover_image_ids'); @@ -2513,469 +2197,467 @@ embed.push('recall', 'recall.patron') [% END %] embed.push('in_bundle', 'bundle_host'); - let table_settings = [% TablesSettings.GetTableSettings('catalogue', 'detail','holdings_table','json') | $raw %]; - var items_table = $("#table_items").kohaTable({ - ajax: { url: table_url }, - order: [[ 0, "asc" ]], - embed, - bAutoWidth: false, - bKohaColumnsUseNames: true, // FIXME We should not need that now, do we? - columns: [ - [% IF (StaffDetailItemSelection) %] - { - data: "me.item_id", - searchable: false, - orderable: false, - render: function (data, type, row, meta) { - if ( can_edit_items_from[row.holding_library_id] ){ - return ''.format(row.item_id); - } else { - return '' - } - } - }, + + function build_table (table_id, table_settings, filters) { + [% IF hidden_count %] + filters.lost_status = "0"; [% END %] - [% IF Koha.Preference('LocalCoverImages') %] - { - data: "", - className: "cover", - searchable: false, - orderable: false, - render: function (data, type, row, meta) { - if ( !row.cover_image_ids.length > 0 ) { - return ''; + var items_table = $("#" + table_id).kohaTable({ + ajax: { url: item_table_url }, + order: [[ 0, "asc" ]], + embed, + autoWidth: false, + bKohaColumnsUseNames: true, // FIXME We should not need that now, do we? + columns: [ + [% IF (StaffDetailItemSelection) %] + { + data: "me.item_id", + searchable: false, + orderable: false, + render: function (data, type, row, meta) { + if ( can_edit_items_from[row.holding_library_id] ){ + return ''.format(row.item_id); + } else { + return '' + } } - let node = '
'; - node += '
'; - row.cover_image_ids.forEach(id => { - node += '
'; - node += ''.format(id, id); - node += 'Local cover image'.format(id, id); - node += ''; + }, + [% END %] + [% IF Koha.Preference('LocalCoverImages') %] + { + data: "", + className: "cover", + searchable: false, + orderable: false, + render: function (data, type, row, meta) { + if ( !row.cover_image_ids.length > 0 ) { + return ''; + } + let node = '
'; + node += '
'; + row.cover_image_ids.forEach(id => { + node += ''; + }); node += '
'; - }); - node += '
'; - node += '
'; - return node; - } - }, - [% END %] - [% IF ( item_level_itypes ) %] - { - data: "me.itype:biblioitem.itemtype", - className: "itype", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - let node = ''; - [% UNLESS noItemTypeImages %] - let image_location = item_type_image_locations[row.item_type_id]; - let item_type_description = row._strings.item_type_id.str; - node += image_location - ? '%s '.format(image_location, item_type_description, item_type_description) - : ''; - [% END %] - node += '%s'.format(item_type_description); - return node; - } - }, - [% END %] - { - data: "me.holding_library_id", - className: "location", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return row._strings.holding_library_id.str; - } - }, - { - data: "me.home_library_id", - className: "homebranch", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - let nodes = '%s'.format(row._strings.home_library_id.str); - nodes += '' - [%# If permanent location is defined, show description or code and - display current location in parentheses. If not, display current location. - Note that permanent location is a code, and location may be an authval. - %] - - let loc_str = row._strings.location.str; - if ( row.permanent_location && row.permanent_location != row.location ) { - let permanent_loc_str = av_loc[row.permanent_location]; - nodes += '%s (%s)'.format(permanent_loc_str, loc_str); - } else { - nodes += loc_str; + node += '
'; + return node; } - nodes += ''; - return nodes; - } - }, - { - data: "me.collection_code", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return row._strings.collection_code.str; - } - }, - [% IF Koha.Preference('EnableItemGroups') %] - { - data: "item_group_item.item_group.description", - className: "item_group", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - if ( row.item_group_item ) { - return row.item_group_item.item_group.description; - } else { - return ""; + }, + [% END %] + [% IF ( item_level_itypes ) %] + { + data: "me.itype:biblioitem.itemtype", + className: "itype", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + let node = ''; + [% UNLESS noItemTypeImages %] + let image_location = item_type_image_locations[row.item_type_id]; + let item_type_description = row._strings.item_type_id.str; + node += image_location + ? '%s '.format(image_location, item_type_description, item_type_description) + : ''; + [% END %] + node += '%s'.format(item_type_description); + return node; } - } - }, - [% END %] - { - data: "me.callnumber", - className: "itemcallnumber", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return row.callnumber; - } - - }, - { - data: "me.serial_issue_number", - className: "enumchron", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - let nodes = ""; - [%# FIXME Previously we displayed the column if at least one item of the biblio had an enumchron/serial_issue_number. Now it's only if one item of the ones displayed on the current page, how is that bad? How can it be fixed in an elegant way? Should we display the column only if biblio.serial? %] - let serial = row.serialitem ? row.serialitem.serial : null; - if ( row.serial_issue_number && serial && serial.serialseq ) { - nodes += '%s'.format(row.serial_issue_number); - if ( serial.serialseq && row.serial_issue_number != serial.serialseq ) { - nodes += ' -- ' - nodes += ' %s'.format(serial.serialseq); + }, + [% END %] + { + data: "me.holding_library_id", + className: "location", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return row._strings.holding_library_id.str; + } + }, + { + data: "me.home_library_id", + className: "homebranch", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + let nodes = '%s'.format(row._strings.home_library_id.str); + nodes += '' + [%# If permanent location is defined, show description or code and %] + [%# display current location in parentheses. If not, display current location. %] + [%# Note that permanent location is a code, and location may be an authval. %] + let loc_str = row._strings.location.str; + if ( row.permanent_location && row.permanent_location != row.location ) { + let permanent_loc_str = av_loc[row.permanent_location]; + nodes += '%s (%s)'.format(permanent_loc_str, loc_str); + } else { + nodes += loc_str; } - } else if ( row.serial_issue_number ) { - nodes += ' %s'.format(row.serial_issue_number); - } else if ( serial && serial.serialseq ) { - nodes += '%s'.format(serial.serialseq); + nodes += ''; + return nodes; } - if ( serial && serial.publisheddate ) { - nodes += ' (%s)'.format($date(serial.publisheddate)); + }, + { + data: "me.collection_code", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return row._strings.collection_code.str; } - return nodes; - } - }, - { - data: "me.lost_status", - className: "status", - searchable: false, // FIXME We are losing the ability to search on the status - orderable: false, - render: function (data, type, row, meta) { - let nodes = ""; - if ( row.checkout ) { - nodes += ''; - if ( row.checkout.onsite_checkout ) { - if ( can_edit_items_from[row.holding_library_id] ){ + }, + [% IF Koha.Preference('EnableItemGroups') %] + { + data: "item_group_item.item_group.description", + className: "item_group", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + if ( row.item_group_item ) { + return row.item_group_item.item_group.description; + } else { + return ""; + } + } + }, + [% END %] + { + data: "me.callnumber", + className: "itemcallnumber", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return row.callnumber; + } + + }, + { + data: "me.serial_issue_number", + className: "enumchron", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + let nodes = ""; + [%# FIXME Previously we displayed the column if at least one item of the biblio had an enumchron/serial_issue_number. Now it's only if one item of the ones displayed on the current page, how is that bad? How can it be fixed in an elegant way? Should we display the column only if biblio.serial? %] + let serial = row.serialitem ? row.serialitem.serial : null; + if ( row.serial_issue_number && serial && serial.serialseq ) { + nodes += '%s'.format(row.serial_issue_number); + if ( serial.serialseq && row.serial_issue_number != serial.serialseq ) { + nodes += ' -- ' + nodes += ' %s'.format(serial.serialseq); + } + } else if ( row.serial_issue_number ) { + nodes += ' %s'.format(row.serial_issue_number); + } else if ( serial && serial.serialseq ) { + nodes += '%s'.format(serial.serialseq); + } + if ( serial && serial.publisheddate ) { + nodes += ' (%s)'.format($date(serial.publisheddate)); + } + return nodes; + } + }, + { + data: "me.lost_status", + className: "status", + searchable: false, // FIXME We are losing the ability to search on the status + orderable: false, + render: function (data, type, row, meta) { + let nodes = ""; + if ( row.checkout ) { + nodes += ''; + if ( row.checkout.onsite_checkout ) { let patron_to_html = $patron_to_html(row.checkout.patron); [%# FIXME What about hide_patron_infos_if_needed?? %] nodes += _("Currently in local use by %s").format(patron_to_html); } else { - nodes += _("Currently in local use"); - } - } else { - nodes += ''; - if ( can_edit_items_from[row.holding_library_id] ){ + nodes += ''; let patron_to_html = $patron_to_html(row.checkout.patron); [%# FIXME What about hide_patron_infos_if_needed?? %] nodes += _("Checked out to %s").format(patron_to_html); + } + nodes += ': '; + nodes += _("due %s").format($date(row.checkout.due_date)); [%# FIXME Missing due date formatting here, $date do not have as_due_date option %] + nodes += "" + } else if ( row.transfer ) { + if ( row.transfer.datesent ) { + nodes += '%s'.format(_("In transit from %s to %s since %s").format(row.transfer.frombranch, row.transfer.tobranch, $date(row.transfer.datesent))); [%# FIXME display library names, not codes, do we use _strings here? %] } else { - nodes += _("Checked out"); + nodes += '%s'.format(_("Transit pending from %s to %s since %s").format(row.transfer.frombranch, row.transfer.tobranch, $date(row.transfer.daterequested))); [%# FIXME See above %] } } - nodes += ': '; - nodes += _("due %s").format($date(row.checkout.due_date)); [%# FIXME Missing due date formatting here, $date do not have as_due_date option %] - nodes += "" - } else if ( row.transfer ) { - if ( row.transfer.datesent ) { - nodes += '%s'.format(_("In transit from %s to %s since %s").format(row.transfer.frombranch, row.transfer.tobranch, $date(row.transfer.datesent))); [%# FIXME display library names, not codes, do we use _strings here? %] - } else { - nodes += '%s'.format(_("Transit pending from %s to %s since %s").format(row.transfer.frombranch, row.transfer.tobranch, $date(row.transfer.daterequested))); [%# FIXME See above %] + + if ( row.lost_status ) { + let lost_lib = av_lost.get(row.lost_status.toString()) || _("Unavailable (lost or missing"); + nodes += '%s'.format(lost_lib); } - } - if ( row.lost_status ) { - let lost_lib = av_lost.get(row.lost_status.toString()) || _("Unavailable (lost or missing"); - nodes += '%s'.format(lost_lib); - } + if ( row.withdrawn ) { + let withdrawn_lib = av_withdrawn.get(row.withdrawn.toString()) || _("Withdrawn"); + nodes += '%s'.format(withdrawn_lib); + } - if ( row.withdrawn ) { - let withdrawn_lib = av_withdrawn.get(row.withdrawn.toString()) || _("Withdrawn"); - nodes += '%s'.format(withdrawn_lib); - } + if ( row.damaged ) { + let damaged_lib = av_damaged.get(row.damaged.toString()) || _("Damaged"); + nodes += '%s'.format(damaged_lib); + } - if ( row.damaged ) { - let damaged_lib = av_damaged.get(row.damaged.toString()) || _("Damaged"); - nodes += '%s'.format(damaged_lib); - } + if ( row.not_for_loan_status || row.item_type.notforloan ) { + let not_for_loan_lib = av_not_for_loan.get(row.not_for_loan_status.toString()); + nodes += '%s'.format(_("Not for loan")) + ( not_for_loan_lib ? ' (%s)'.format(not_for_loan_lib) : '' ) + ''; + } - if ( row.not_for_loan_status || row.item_type.notforloan ) { - let not_for_loan_lib = av_not_for_loan.get(row.not_for_loan_status.toString()); - nodes += '%s'.format(_("Not for loan")) + ( not_for_loan_lib ? ' (%s)'.format(not_for_loan_lib) : '' ) + ''; - } + if ( row.first_hold ) { + if ( row.first_hold.waiting_date ) { + [%# FIXME Display library names instead of codes %] + [%# FIXME We lost the desk name, we need an additional embed %] + nodes += '%s'.format(_("Waiting at %s since %s.".format(row.first_hold.pickup_library_id, $date(row.first_hold.waiting_date)))); + [% IF Koha.Preference('canreservefromotherbranches') %] + if ( row.first_hold.waiting_date || row.first_hold.priority == 1 ) { + let patron_to_html = $patron_to_html(row.first_hold.patron); [%# FIXME What about hide_patron_infos_if_needed?? %] + nodes += ' %s'.format(_("Hold for: %s").format(patron_to_html)); + } + [% END %] + } else { + nodes += '%s'.format(_("There is an item level hold on this item (priority = %s).").format(row.first_hold.priority)); + } + } - if ( row.first_hold ) { - if ( row.first_hold.waiting_date ) { - [%# FIXME Display library names instead of codes %] - [%# FIXME We lost the desk name, we need an additional embed %] - nodes += '%s'.format(_("Waiting at %s since %s.".format(row.first_hold.pickup_library_id, $date(row.first_hold.waiting_date)))); - [% IF Koha.Preference('canreservefromotherbranches') %] - if ( row.first_hold.waiting_date || row.first_hold.priority == 1 ) { - let patron_to_html = $patron_to_html(row.first_hold.patron); [%# FIXME What about hide_patron_infos_if_needed?? %] - nodes += ' %s'.format(_("Hold for: %s").format(patron_to_html)); + [% IF Koha.Preference('UseRecalls') %] + if ( row.recall ) { + if ( row.recall.waiting_date ) { + nodes += '%s'.format(_("Waiting at %s since %s").format(row.recall.pickup_library_id, $date(row.recall.waiting_date))); # FIXME Display library names instead of codes + } else { + let patron_to_html = $patron_to_html(row.recall.patron); + nodes += '%s'.format(_("recalled by %s on %s").format(patron_to_html, row.recall.created_date)) } - [% END %] - } else { - nodes += '%s'.format(_("There is an item level hold on this item (priority = %s).").format(row.first_hold.priority)); + } + [% END %] + + if ( ! ( row.not_for_loan_status || row.item_type.notforloan || row.checked_out_date || row.lost_status || row.withdrawn || row.damaged || row.transfer || row.first_hold || row.recall ) ) { + nodes += ' %s'.format(_("Available")) } - } - [% IF Koha.Preference('UseRecalls') %] - if ( row.recall ) { - if ( row.recall.waiting_date ) { - nodes += '%s'.format(_("Waiting at %s since %s").format(row.recall.pickup_library_id, $date(row.recall.waiting_date))); # FIXME Display library names instead of codes - } else { - let patron_to_html = $patron_to_html(row.recall.patron); - nodes += '%s'.format(_("recalled by %s on %s").format(patron_to_html, row.recall.created_date)); - } + if ( row.restricted_status ) { + nodes += '(%s)'.format(av_restricted.get(row.restricted_status.toString())); } - [% END %] - if ( ! ( row.not_for_loan_status || row.item_type.notforloan || row.checked_out_date || row.lost_status || row.withdrawn || row.damaged || row.transfer || row.first_hold || row.recall ) ) { - nodes += ' %s'.format(_("Available")) + if ( row.in_bundle ) { + nodes += '%s'.format(_("In bundle: %s").format($biblio_to_html(row.bundle_host.biblio, { link: true }))); + } + return nodes; } - - if ( row.restricted_status ) { - nodes += '(%s)'.format(av_restricted.get(row.restricted_status.toString())); + }, + { + data: "me.last_seen_date", + className: "datelastseen", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return $date(row.last_seen_date); } - - if ( row.in_bundle ) { - nodes += '%s'.format(_("In bundle: %s").format($biblio_to_html(row.bundle_host.biblio, { link: true }))); + }, + { + data: "me.checkouts_count", + className: "issues", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return row.checkouts_count || 0; } - return nodes; - } - }, - { - data: "me.last_seen_date", - className: "datelastseen", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return $date(row.last_seen_date); - } - }, - { - data: "me.checkouts_count", - className: "issues", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return row.checkouts_count || 0; - } - }, - { - data: "me.renewals_count", - className: "renewals", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return row.renewals_count || 0; - } - }, - { - data: "me.acquisition_date", - className: "dateaccessioned", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return $date(row.acquisition_date); - } - }, - { - data: "me.last_checkout_date", - className: "datelastborrowed", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return $date(row.last_checkout_date); - } - }, - { - data: "me.external_id", - className: "", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return '%s'.format(row.biblio_id, row.item_id, row.external_id); - } - }, - { - data: "me.uri", - className: "uri", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - if ( !row.uri ) return ""; - - let nodes = ''; - if ( row.uri.split(' \| ').length > 1 ) { - row.uri.split(' \| ').forEach((uri, i) => { - nodes += '%s
'.format(uri, uri); - }); - } else { - nodes += '%s
'.format(row.uri, url_link_text); + }, + { + data: "me.renewals_count", + className: "renewals", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return row.renewals_count || 0; } - return nodes; - } - }, - { - data: "me.copy_number", - className: "copynumber", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return row._strings.copy_number ? row._strings.copy_number.str : row.copy_number; - } - }, - { - data: "me.inventory_number", - className: "stocknumber", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return row.inventory_number; - } - }, - { - data: "me.materials_notes", - className: "materials", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return row.materials_notes; - } - }, - { - data: "me.public_notes", - className: "itemnotes", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return row.public_notes ? row.public_notes.replaceAll('\n', '
') : ''; - } - }, - { - data: "me.internal_notes", - className: "nonpublicnote", - searchable: true, - orderable: true, - render: function (data, type, row, meta) { - return row.internal_notes; - } - }, - [% IF ( hostrecords ) %] - { - data: "biblio.biblio_id", - searchable: false, // FIXME - orderable: true, - render: function (data, type, row, meta) { - if ( row.biblio_id == [% biblio.biblionumber %] ) return ""; - return ' Print label'.format(row.external_id); - } - }, - [% END %] - [% IF CAN_user_editcatalogue_edit_items %] - { - data: function( row, type, val, meta ) { - let nodes = ''; - if ( can_edit_items_from[row.holding_library_id] ){ - [% IF Koha.Preference('LocalCoverImages') OR Koha.Preference('OPACLocalCoverImages') %] - nodes += '
'; - nodes += ' Edit'.format(row.biblio_id, row.item_id); - nodes += ' '; - nodes += '
'; - [% ELSE %] - nodes += ' Edit'.format(row.biblio_id, row.item_id); - [% END %] + }, + { + data: "me.acquisition_date", + className: "dateaccessioned", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return $date(row.acquisition_date); } - [% IF bundlesEnabled %] - // FIXME How do we handle that correctly? - //nodes += ''.format(row.bundled, row.bundled_lost); - [% END %] - - return nodes; }, - className: "actions", - searchable: false, - orderable: false - } - [% END %] - ], - initComplete: function( settings, json ){ - let table = settings.oInstance.api(); - table.columns().every(function(i){ - let is_empty = true; - let nodes = this.nodes(); - nodes.each((td, ii) => { - if ( $(td).html() !== '' ) { - is_empty = false; - return; + { + data: "me.last_checkout_date", + className: "datelastborrowed", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return $date(row.last_checkout_date); + } + }, + { + data: "me.external_id", + className: "", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return '%s'.format(row.biblio_id, row.item_id, row.external_id); + } + }, + { + data: "me.uri", + className: "uri", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + if ( !row.uri ) return ""; + + let nodes = ''; + if ( row.uri.split(' \| ').length > 1 ) { + row.uri.split(' \| ').forEach((uri, i) => { + nodes += '%s
'.format(uri, uri); + }); + } else { + nodes += '%s
'.format(row.uri, url_link_text); } - }); - if ( is_empty ) { - table.columns(i).visible(false); + return nodes; } - }); + }, + { + data: "me.copy_number", + className: "copynumber", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return row._strings.copy_number ? row._strings.copy_number.str : row.copy_number; + } + }, + { + data: "me.inventory_number", + className: "stocknumber", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return row.inventory_number; + } + }, + { + data: "me.materials_notes", + className: "materials", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return row.materials_notes; + } + }, + { + data: "me.public_notes", + className: "itemnotes", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return row.public_notes ? row.public_notes.replaceAll('\n', '
') : ''; + } + }, + { + data: "me.internal_notes", + className: "nonpublicnote", + searchable: true, + orderable: true, + render: function (data, type, row, meta) { + return row.internal_notes; + } + }, + [% IF ( hostrecords ) %] + { + data: "biblio.biblio_id", + searchable: false, // FIXME + orderable: true, + render: function (data, type, row, meta) { + if ( row.biblio_id == [% biblio.biblionumber | html %] ) return ""; + return ' Print label'.format(row.external_id); + } + }, + [% END %] + [% IF CAN_user_editcatalogue_edit_items %] + { + data: function( row, type, val, meta ) { + let nodes = ''; + if ( can_edit_items_from[row.holding_library_id] ){ + [% IF Koha.Preference('LocalCoverImages') OR Koha.Preference('OPACLocalCoverImages') %] + nodes += '
'; + nodes += ' Edit'.format(row.biblio_id, row.item_id); + nodes += ' '; + nodes += '
'; + [% ELSE %] + nodes += ' Edit'.format(row.biblio_id, row.item_id); + [% END %] + } + [% IF bundlesEnabled %] + // FIXME How do we handle that correctly? + //nodes += ''.format(row.bundled, row.bundled_lost); + [% END %] + + return nodes; + }, + className: "actions", + searchable: false, + orderable: false + } + [% END %] + ], + initComplete: function( settings, json ){ + let table = settings.oInstance.api(); + table.columns().every(function(i){ + let is_empty = true; + let nodes = this.nodes(); + nodes.each((td, ii) => { + if ( $(td).html() !== '' ) { + is_empty = false; + return; + } + }); + if ( is_empty ) { + table.columns(i).visible(false); + } + }); + }, }, - }, - table_settings, - true); + table_settings, + true, + filters, + ); + return items_table; + } [% CoverImagePlugins | $raw %] [% END %] -- 2.39.5