Bugzilla – Attachment 164332 Details for
Bug 33568
Use the REST API to display items on the staff biblio detail view
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 33568: Separate holdings
Bug-33568-Separate-holdings.patch (text/plain), 93.86 KB, created by
Jonathan Druart
on 2024-04-03 07:39:08 UTC
(
hide
)
Description:
Bug 33568: Separate holdings
Filename:
MIME Type:
Creator:
Jonathan Druart
Created:
2024-04-03 07:39:08 UTC
Size:
93.86 KB
patch
obsolete
>From 511659e226956a204cfa3ffff7980901d5b000c7 Mon Sep 17 00:00:00 2001 >From: Jonathan Druart <jonathan.druart@bugs.koha-community.org> >Date: Tue, 18 Apr 2023 16:29:44 +0200 >Subject: [PATCH] Bug 33568: Separate holdings >MIME-Version: 1.0 >Content-Type: text/plain; charset=UTF-8 >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 <oleonard@myacpl.org> > >Signed-off-by: Laurence Rault <laurence.rault@biblibre.com> >Signed-off-by: Emily Lamancusa <emily.lamancusa@montgomerycountymd.gov> >Signed-off-by: Tomás Cohen Arazi <tomascohen@theke.io> >--- > 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 59f70c97d08..b5a092332a6 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 4bed0bc7005..774dab7c109 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 b0d29e87c0f..d9851e03c87 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 @@ > <div id="bibliodetails" class="toptabs"> > > <ul class="nav nav-tabs" role="tablist"> >- [% IF (SeparateHoldings) %] >+ [% IF Koha.Preference('SeparateHoldings') %] > <li role="presentation"> >- <a href="#holdings" aria-controls="holdings" role="tab" data-toggle="tab">[% Branches.GetLoggedInBranchname | html %] holdings ([% itemloop.size() || 0 | html %])</a> >+ [%# FIXME We could build the numbers from DataTable's info %] >+ <a href="#holdings" aria-controls="holdings" role="tab" data-toggle="tab">[% Branches.GetLoggedInBranchname | html %] holdings ([% items_to_display_count - ( other_holdings_count || 0 ) - ( hidden_count || 0 ) || 0 | html %])</a> > </li> > <li role="presentation"> >- <a href="#otherholdings" aria-controls="otherholdings" role="tab" data-toggle="tab">Other holdings ([% otheritemloop.size() || 0 | html %])</a> >+ <a href="#otherholdings" aria-controls="otherholdings" role="tab" data-toggle="tab">Other holdings ([% other_holdings_count || 0 | html %])</a> > </li> > [% ELSE %] > <li role="presentation"> >- <a href="#holdings" aria-controls="holdings" role="tab" data-toggle="tab">Holdings ([% itemloop.size() || 0 | html %])</a> >+ <a href="#holdings" aria-controls="holdings" role="tab" data-toggle="tab">Holdings ([% items_to_display_count || 0 | html %])</a> > </li> > [% END %] > [% IF Koha.Preference('EnableItemGroups') %] >@@ -347,321 +348,43 @@ > </span> > [% END %] > </div> >+ > <table class="items_table" id="[% tab | html %]_table"> > <thead> >- <tr> >- [% IF (StaffDetailItemSelection) %]<th id="[% tab | html %]_checkbox" data-colname="[% tab | html %]_checkbox" class="NoSort"></th>[% END %] >- [% IF Koha.Preference('LocalCoverImages') && ( tab == 'holdings' && itemloop_has_images || tab == 'otherholdings' && otheritemloop_has_images ) %] >- <th id="[% tab | html %]_cover_image" data-colname="[% tab | html %]_cover_image">Cover image</th> >- [% END %] >- [% IF ( item_level_itypes ) %]<th id="[% tab | html %]_itype" data-colname="[% tab | html %]_itype">Item type</th>[% END %] >- <th id="[% tab | html %]_holdingbranch" data-colname="[% tab | html %]_holdingbranch">Current library</th> >- <th id="[% tab | html %]_homebranch" data-colname="[% tab | html %]_homebranch">Home library</th> >- [% IF ( itemdata_ccode ) %]<th id="[% tab | html %]_ccode" data-colname="[% tab | html %]_ccode">Collection</th>[% END %] >- [% IF Koha.Preference('EnableItemGroups') %] >- <th id="[% tab | html %]_item_group" data-colname="[% tab | html %]_item_group">Item group</th> >- [% END %] >- <th id="[% tab | html %]_itemcallnumber" data-colname="[% tab | html %]_itemcallnumber">Call number</th> >- [% IF volinfo %] >- <th id="[% tab | html %]_enumchron" data-colname="[% tab | html %]_enumchron">Serial enumeration / chronology</th> >- [% END %] >- <th id="[% tab | html %]_status" data-colname="[% tab | html %]_status">Status</th> >- <th id="[% tab | html %]_lastseen" data-colname="[% tab | html %]_lastseen">Last seen</th> >- <th id="[% tab | html %]_issues" data-colname="[% tab | html %]_issues">Checkouts</th> >- <th id="[% tab | html %]_renewals" data-colname="[% tab | html %]_renewals">Renewals</th> >- <th id="[% tab | html %]_dateaccessioned" data-colname="[% tab | html %]_dateaccessioned">Date accessioned</th> >- <th id="[% tab | html %]_datelastborrowed" data-colname="[% tab | html %]_datelastborrowed">Date last borrowed</th> >- <th id="[% tab | html %]_barcode" data-colname="[% tab | html %]_barcode">Barcode</th> >- [% IF ( itemdata_uri ) %]<th id="[% tab | html %]_uri" data-colname="[% tab | html %]_uri">URL</th>[% END %] >- [% IF ( itemdata_copynumber ) %]<th id="[% tab | html %]_copynumber" data-colname="[% tab | html %]_copynumber">Copy number</th>[% END %] >- [% IF ( itemdata_stocknumber ) %]<th id="[% tab | html %]_stocknumber" data-colname="[% tab | html %]_stocknumber">Inventory number</th>[% END %] >- [% IF materials %]<th id="[% tab | html %]_materials" data-colname="[% tab | html %]_materials">Materials specified</th>[% END %] >- [% IF ( itemdata_itemnotes ) %]<th id="[% tab | html %]_itemnotes" data-colname="[% tab | html %]_itemnotes">Public notes</th>[% END %] >- [% IF ( itemdata_nonpublicnotes ) %]<th id="[% tab | html %]_itemnotes_nonpublic" data-colname="[% tab | html %]_itemnotes_nonpublic">Non-public notes</th>[% END %] >- [% IF ( hostrecords ) %]<th id="[% tab | html %]_hostrecord" data-colname="[% tab | html %]_hostrecord">Host records</th>[% END %] >- [% IF ( analyze ) %]<th id="[% tab | html %]_usedin" data-colname="[% tab | html %]_usedin">Used in</th><th></th>[% END %] >- [% IF ( ShowCourseReserves ) %]<th id="[% tab | html %]_course_reserves" data-colname="[% tab | html %]_course_reserves">Course reserves</th>[% END %] >- [% IF ( SpineLabelShowPrintOnBibDetails ) %]<th id="[% tab | html %]_spinelabel" data-colname="[% tab | html %]_spinelabel" class="NoSort">Spine label</th>[% END %] >- [% IF ( CAN_user_editcatalogue_edit_items ) %]<th id="[% tab | html %]_actions" data-colname="[% tab | html %]_actions"class="NoSort noExport"> </th>[% END %] >+ [% IF (StaffDetailItemSelection) %]<th id="[% tab | html %]_checkbox" data-colname="[% tab | html %]_checkbox" class="NoSort"></th>[% END %] >+ [% IF Koha.Preference('LocalCoverImages') %] >+ <th id="[% tab | html %]_cover_image" data-colname="[% tab | html %]_cover_image">Cover image</th> >+ [% END %] >+ [% IF ( item_level_itypes ) %]<th id="[% tab | html %]_itype" data-colname="[% tab | html %]_itype">Item type</th>[% END %] >+ <th id="[% tab | html %]_holdingbranch" data-colname="[% tab | html %]_holdingbranch">Current library</th> >+ <th id="[% tab | html %]_homebranch" data-colname="[% tab | html %]_homebranch">Home library</th> >+ <th id="[% tab | html %]_ccode" data-colname="[% tab | html %]_ccode">Collection</th> >+ [% IF Koha.Preference('EnableItemGroups') %] >+ <th id="[% tab | html %]_item_group" data-colname="[% tab | html %]_item_group">Item group</th> >+ [% END %] >+ <th id="[% tab | html %]_itemcallnumber" data-colname="[% tab | html %]_itemcallnumber">Call number</th> >+ <th id="[% tab | html %]_enumchron" data-colname="[% tab | html %]_enumchron">Serial enumeration / chronology</th> >+ <th id="[% tab | html %]_status" data-colname="[% tab | html %]_status">Status</th> >+ <th id="[% tab | html %]_lastseen" data-colname="[% tab | html %]_lastseen">Last seen</th> >+ <th id="[% tab | html %]_issues" data-colname="[% tab | html %]_issues">Checkouts</th> >+ <th id="[% tab | html %]_renewals" data-colname="[% tab | html %]_renewals">Renewals</th> >+ <th id="[% tab | html %]_dateaccessioned" data-colname="[% tab | html %]_dateaccessioned">Date accessioned</th> >+ <th id="[% tab | html %]_datelastborrowed" data-colname="[% tab | html %]_datelastborrowed">Date last borrowed</th> >+ <th id="[% tab | html %]_barcode" data-colname="[% tab | html %]_barcode">Barcode</th> >+ <th id="[% tab | html %]_uri" data-colname="[% tab | html %]_uri">URL</th> >+ <th id="[% tab | html %]_copynumber" data-colname="[% tab | html %]_copynumber">Copy number</th> >+ <th id="[% tab | html %]_stocknumber" data-colname="[% tab | html %]_stocknumber">Inventory number</th> >+ <th id="[% tab | html %]_materials" data-colname="[% tab | html %]_materials">Materials specified</th> >+ <th id="[% tab | html %]_itemnotes" data-colname="[% tab | html %]_itemnotes">Public notes</th> >+ <th id="[% tab | html %]_itemnotes_nonpublic" data-colname="[% tab | html %]_itemnotes_nonpublic">Non-public notes</th> >+ [% IF ( hostrecords ) %]<th id="[% tab | html %]_hostrecord" data-colname="[% tab | html %]_hostrecord">Host records</th>[% END %] >+ [% IF ( analyze ) %]<th id="[% tab | html %]_usedin" data-colname="[% tab | html %]_usedin">Used in</th><th></th>[% END %] >+ [% IF ( ShowCourseReserves ) %]<th id="[% tab | html %]_course_reserves" data-colname="[% tab | html %]_course_reserves">Course reserves</th>[% END %] >+ [% IF ( SpineLabelShowPrintOnBibDetails ) %]<th id="[% tab | html %]_spinelabel" data-colname="[% tab | html %]_spinelabel" class="NoSort">Spine label</th>[% END %] >+ [% IF ( CAN_user_editcatalogue_edit_items ) %]<th id="[% tab | html %]_actions" data-colname="[% tab | html %]_actions"class="NoSort noExport"> </th>[% END %] > </tr> > </thead> >- <tbody> >- [% FOREACH item IN items %] >- [% SET date_due = item.object.checkout.date_due %] >- <tr id="item_[% item.itemnumber | html %]" data-itemnumber="[% item.itemnumber | html %]" data-duedate="[% date_due | html %]"> >- [% IF (StaffDetailItemSelection) %] >- <td style="text-align:center;vertical-align:middle"> >- [% IF item.can_be_edited %] >- <input type="checkbox" value="[% item.itemnumber | html %]" name="itemnumber" /> >- [% END %] >- </td> >- [% END %] >- [% IF Koha.Preference('LocalCoverImages') && ( tab == 'holdings' && itemloop_has_images || tab == 'otherholdings' && otheritemloop_has_images ) %] >- <td class="cover"> >- <div class="bookcoverimg"> >- <div class="cover-slider"> >- [% FOREACH image IN item.object.cover_images %] >- <div class="cover-image local-coverimg"> >- <a href="/cgi-bin/koha/catalogue/image.pl?itemnumber=[% image.itemnumber | uri %]&imagenumber=[% image.imagenumber | uri %]" title="Local cover image"> >- <img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&imagenumber=[% image.imagenumber | uri %]" alt="Local cover image" data-link="/cgi-bin/koha/catalogue/imageviewer.pl?itemnumber=[% item.itemnumber | uri %]&imagenumber=[% image.imagenumber | uri %]" /> >- </a> >- </div> >- [% END %] >- </div> >- </div> >- </td> >- [% END %] >- >- [% IF ( item_level_itypes ) %] >- <td class="itype"> >- [% SET itemtype = item.itemtype %] >- [% IF !noItemTypeImages && itemtype.image_location('intranet') %] >- <img src="[% itemtype.image_location('intranet') | html %]" alt="[% itemtype.translated_description | html %]" title="[% itemtype.translated_description | html %]" /> >- [% END %] >- <span class="itypedesc itypetext">[% itemtype.translated_description | html %]</span> >- </td> >- [% END %] >- <td class="location">[% UNLESS ( singlebranchmode ) %][% Branches.GetName( item.holdingbranch ) | html %] [% END %]</td> >- <td class="homebranch"> >- <span class="homebranchdesc">[% Branches.GetName(item.homebranch) | html %]</span> >- <span class="shelvingloc"> >- [%# 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 %] >- </span> >- </td> >- [% IF ( itemdata_ccode ) %]<td>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => item.ccode ) | html %]</td>[% END %] >- [% IF Koha.Preference('EnableItemGroups') %]<td class="item_group">[% item.object.item_group.description | html %]</td>[% END %] >- <td class="itemcallnumber">[% IF ( item.itemcallnumber ) %] [% item.itemcallnumber | html %][% END %]</td> >- [% IF ( volinfo ) %] >- [% SET serial = item.serial %] >- [% IF itemdata_publisheddate #If there is at least one published date, use it for sorting %] >- <td class="enumchron" data-order="[% serial.publisheddate | html %]"> >- [% ELSE %] >- <td class="enumchron"> >- [% END %] >- [% IF ( itemdata_enumchron ) %] >- [% IF item.enumchron && serial.serialseq %] >- <span class="enum">[% item.enumchron | html %]</span> >- [% IF ( serial.serialseq && item.enumchron != serial.serialseq ) %] >- <span class="sep"> -- </span> >- <span class="serialseq">[% serial.serialseq | html %]</span> >- [% END %] >- [% ELSIF item.enumchron %] >- <span class="enum">[% item.enumchron | html %]</span> >- [% ELSIF item.serialseq %] >- <span class="serialseq">[% serial.serialseq | html %]</span> >- [% END %] >- [% IF serial.publisheddate %] >- <span class="pubdate">([% serial.publisheddate | $KohaDates %])</span> >- [% END %] >- [% END %] >- </span> >- </td> >- [% END %] >- <td class="status"> >- >- [% IF item.object.checkout %] >- [% IF item.object.checkout.onsite_checkout %] >- <div class="item_status localuse">Currently in local use >- [% ELSE %] >- <div class="item_status datedue">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 %] >- </div> >- [% ELSIF ( transfer = item.object.get_transfer ) %] >- [% IF (transfer.datesent) %] >- <div class="item_status intransit">In transit from [% Branches.GetName( transfer.frombranch ) | html %] to [% Branches.GetName( transfer.tobranch ) | html %] since [% transfer.datesent | $KohaDates %]</div> >- [% ELSE %] >- <div class="item_status transitrequested">Transit pending from [% Branches.GetName( transfer.frombranch ) | html %] to [% Branches.GetName( transfer.tobranch ) | html %] since [% transfer.daterequested | $KohaDates %]</div> >- [% END %] >- [% END %] >- >- [% IF ( item.itemlost ) %] >- [% SET itemlost_description = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.itemlost', authorised_value => item.itemlost ) %] >- [% IF itemlostloop %] >- <div class="item_status lost">[% itemlost_description | html %]</div> >- [% ELSE %] >- <div class="item_status lost">Unavailable (lost or missing)</div> >- [% END %] >- [% END %] >- >- [% IF ( item.withdrawn ) %] >- [% SET withdrawn_description = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.withdrawn', authorised_value => item.withdrawn ) %] >- [% IF withdrawn_description %] >- <div class="item_status wdn">[% withdrawn_description | html %]</div> >- [% ELSE %] >- <div class="item_status wdn">Withdrawn</div> >- [% END %] >- [% END %] >- >- [% IF ( item.damaged ) %] >- [% SET damaged_description = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.damaged', authorised_value => item.damaged ) %] >- [% IF damaged_description %] >- <div class="item_status dmg">[% damaged_description | html %]</div> >- [% ELSE %] >- <div class="item_status dmg">Damaged</div> >- [% END %] >- [% END %] >- >- [% IF ( item.notforloan || item.itemtype.notforloan ) %] >- <div class="item_status notforloan">Not for loan >- [% SET not_for_loan_description = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.notforloan', authorised_value => item.notforloan ) %] >- [% IF not_for_loan_description %] >- <span class="reason">([% not_for_loan_description | html %])</span> >- [% END %] >- </div> >- [% END %] >- >- [% SET hold = item.first_hold %] >- [% IF hold %] >- [% IF hold.waitingdate %] >- <div class="item_status waitingat">Waiting at [% Branches.GetName( hold.branchcode ) | html %][% IF ( hold.desk_id ) %], [% hold.desk.desk_name | html %][% END %] since [% hold.waitingdate | $KohaDates %].</div> >- [% IF canreservefromotherbranches AND ( hold.waitingdate OR hold.priority == 1 ) %] >- <span class="heldfor">Hold for:</span> >- [% INCLUDE 'patron-title.inc' patron=hold.borrower hide_patron_infos_if_needed=1 %] >- [% END %] >- [% ELSE %] >- <div class="item_status holdonitem">There is an item level hold on this item (priority = [% hold.priority | html %]).</div> >- [% END %] >- [% END %] >- >- [% IF Koha.Preference('UseRecalls') %] >- [% SET recall = item.object.recall %] >- [% IF recall %] >- [% IF recall.waiting_date %] >- <div class="item_status recallat">Waiting at [% Branches.GetName( recall.pickup_library_id ) | html %] since [% recall.waiting_date | $KohaDates %]</div> >- [% ELSE %] >- [% patron_link = BLOCK %]<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% recall.patron_id | uri %]">[% recall.patron.firstname | html %] [% recall.patron.surname | html %] ([% recall.patron.cardnumber | html %])</a>[% END %] >- <div class="item_status recallby">recalled by [% patron_link| $raw %] on [% recall.created_date | $KohaDates %]</div> >- [% END %] >- [% END %] >- [% END %] >- >- [% UNLESS ( item.notforloan || item.itemtype.notforloan || item.onloan || item.itemlost || item.withdrawn || item.damaged || transfer || hold || ( Koha.Preference('UseRecalls') && recall ) ) %] >- <div class="item_status available">Available</div> >- [% END %] >- >- [% IF ( item.restricted ) %] >- <div class="item_status restricted">([% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.restricted', authorised_value => item.restricted ) | html %])</div> >- [% END %] >- >- [% IF ( item.bundle_host ) %] >- <div class="item_status bundled">In bundle: [% INCLUDE 'biblio-title.inc' biblio = item.bundle_host.biblio link = 1 %]</div> >- [% END %] >- >- </td> >- <td class="datelastseen" data-order="[% item.datelastseen | html %]">[% item.datelastseen | $KohaDates with_hours => 1 %]</td> >- <td class="issues" data-order="[% item.issues || 0 | html %]">[% item.issues || 0 | html %]</td> >- <td class="renewals" data-order="[% item.renewals || 0 | html %]">[% item.renewals || 0 | html %]</td> >- <td class="dateaccessioned" data-order="[% item.dateaccessioned | html %]">[% item.dateaccessioned | $KohaDates %]</td> >- <td class="datelastborrowed" data-order="[% item.datelastborrowed | html %]">[% item.datelastborrowed | $KohaDates %]</td> >- <td><a href="/cgi-bin/koha/catalogue/moredetail.pl?itemnumber=[% item.itemnumber | uri %]&biblionumber=[% item.biblionumber | uri %]&bi=[% item.biblioitemnumber | uri %]#item[% item.itemnumber | uri %]">[% item.barcode | html %]</a></td> >- [% IF ( itemdata_uri ) %] >- [% IF item.uri.split(' \| ').size > 1 %] >- <td class="uri"> >- [% FOREACH uri IN item.uri.split(' \| ') %]<a href="[% uri | url %]">[% uri | html %]</a><br>[% END %] >- </td> >- [% ELSE %] >- <td class="uri"> >- [% IF item.uri %] >- <a href="[% item.uri | url %]">[% IF Koha.Preference('URLLinkText') %][% Koha.Preference('URLLinkText') | html %][% ELSE %]Link to resource[% END %]</a> >- [% END %] >- </td> >- [% END %] >- [% END %] >- [% IF ( itemdata_copynumber ) %] >- <td class="copynumber">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.copynumber', authorised_value => item.copynumber ) | html %]</td> >- [% END %] >- [% IF ( itemdata_stocknumber ) %] >- <td class="stocknumber">[% item.stocknumber | html %]</td> >- [% END %] >- [% IF materials %] >- <td class="materials"> [% item.materials | html %] </td> >- [% END %] >- [% IF ( itemdata_itemnotes ) %] >- <td><div class="itemnotes">[% item.object.itemnotes.replace('\n','<br />') | $raw %]</div></td> >- [% END %] >- [% IF itemdata_nonpublicnotes %] >- <td class="nonpublicnote">[% item.itemnotes_nonpublic | html %]</td> >- [% END %] >- [% IF ( hostrecords ) %] >- <td>[% IF ( item.hostbiblionumber) %]<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% item.hostbiblionumber | uri %]" >[% item.hosttitle | html %]</a>[% END %]</td> >- [% END %] >- [% IF ( analyze ) %] >- <td> >- [% IF ( item.countanalytics ) %] >- <a href="/cgi-bin/koha/catalogue/search.pl?idx=hi&q=[% item.itemnumber | uri %]">[% item.countanalytics | html %] analytics</a> >- [% END %] >- </td> >- [% END %] >- [% IF ( analyze ) %] >- <td><a href="/cgi-bin/koha/cataloguing/addbiblio.pl?hostbiblionumber=[% item.biblionumber | uri %]&hostitemnumber=[% item.itemnumber | uri %]">Create analytics</a></td> >- [% END %] >- >- [% IF ShowCourseReserves %] >- <td> >- [% IF item.course_reserves %] >- [% FOREACH r IN item.course_reserves %] >- [% IF r.course.enabled == 'yes' %] >- <p> >- <a href="/cgi-bin/koha/course_reserves/course-details.pl?course_id=[% r.course.course_id | uri %]"> >- [% r.course.course_name | html %] >- <!--[% IF r.course.course_number %] [% r.course.course_number | html %] [% END %]--> >- [% IF r.course.section %] [% r.course.section | html %] [% END %] >- [% IF r.course.term %] [% AuthorisedValues.GetByCode( 'TERM', r.course.term ) | html %] [% END %] >- </a> >- </p> >- [% END %] >- [% END %] >- [% END %] >- </td> >- [% END %] >- >- [% IF ( SpineLabelShowPrintOnBibDetails ) %] >- <td><a class="btn btn-default btn-xs print-label" href="/cgi-bin/koha/labels/spinelabel-print.pl?barcode=[% item.barcode | uri %]"><i class="fa fa-print"></i> Print label</a></td> >- [% END %] >- >- [% IF CAN_user_editcatalogue_edit_items %] >- <td class="actions"> >- [% IF item.can_be_edited %] >- [% IF Koha.Preference('LocalCoverImages') OR Koha.Preference('OPACLocalCoverImages') %] >- <div class="btn-group"> >- <a class="btn btn-default btn-xs" href="/cgi-bin/koha/cataloguing/additem.pl?op=edititem&biblionumber=[% item.biblionumber | html %]&itemnumber=[% item.itemnumber | html %]#edititem"><i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit</a><a class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></a> >- <ul class="dropdown-menu pull-right"> >- <li><a href="/cgi-bin/koha/tools/upload-cover-image.pl?itemnumber=[% item.itemnumber | uri %]&filetype=image"><i class="fa fa-upload"></i> Upload image</a></li> >- </ul> >- </div> >- [% ELSE %] >- <a class="btn btn-default btn-xs" href="/cgi-bin/koha/cataloguing/additem.pl?op=edititem&biblionumber=[% item.biblionumber | html %]&itemnumber=[% item.itemnumber | html %]#edititem"><i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit</a> >- [% END %] >- [% END %] >- [% IF bundlesEnabled %] >- <button class="btn btn-default btn-xs details-control"><i class="fa fa-folder"></i> Manage bundle ([% item.bundled | html %]|[% item.bundled_lost | html %])</button> >- [% END %] >- </td> >- [% END %] >- </tr> >- [% END %] >- </tbody> > </table> >- > [% END %][%# end of block items_table %] > > [% IF Koha.Preference('EnableItemGroups') %] >@@ -693,51 +416,13 @@ > </span> > [% END %] > >-[% IF ( count ) %] >- [% IF ( showncount ) %] >- [%# PROCESS items_table tab="holdings" items=itemloop %] >- >- [% SET tab="holdings" %] >- <table id="table_items"> >- <thead> >- [% IF (StaffDetailItemSelection) %]<th id="[% tab | html %]_checkbox" data-colname="[% tab | html %]_checkbox" class="NoSort"></th>[% END %] >- [% IF Koha.Preference('LocalCoverImages') %] >- <th id="[% tab | html %]_cover_image" data-colname="[% tab | html %]_cover_image">Cover image</th> >- [% END %] >- [% IF ( item_level_itypes ) %]<th id="[% tab | html %]_itype" data-colname="[% tab | html %]_itype">Item type</th>[% END %] >- <th id="[% tab | html %]_holdingbranch" data-colname="[% tab | html %]_holdingbranch">Current library</th> >- <th id="[% tab | html %]_homebranch" data-colname="[% tab | html %]_homebranch">Home library</th> >- <th id="[% tab | html %]_ccode" data-colname="[% tab | html %]_ccode">Collection</th> >- [% IF Koha.Preference('EnableItemGroups') %] >- <th id="[% tab | html %]_item_group" data-colname="[% tab | html %]_item_group">Item group</th> >- [% END %] >- <th id="[% tab | html %]_itemcallnumber" data-colname="[% tab | html %]_itemcallnumber">Call number</th> >- <th id="[% tab | html %]_enumchron" data-colname="[% tab | html %]_enumchron">Serial enumeration / chronology</th> >- <th id="[% tab | html %]_status" data-colname="[% tab | html %]_status">Status</th> >- <th id="[% tab | html %]_lastseen" data-colname="[% tab | html %]_lastseen">Last seen</th> >- <th id="[% tab | html %]_issues" data-colname="[% tab | html %]_issues">Checkouts</th> >- <th id="[% tab | html %]_renewals" data-colname="[% tab | html %]_renewals">Renewals</th> >- <th id="[% tab | html %]_dateaccessioned" data-colname="[% tab | html %]_dateaccessioned">Date accessioned</th> >- <th id="[% tab | html %]_datelastborrowed" data-colname="[% tab | html %]_datelastborrowed">Date last borrowed</th> >- <th id="[% tab | html %]_barcode" data-colname="[% tab | html %]_barcode">Barcode</th> >- <th id="[% tab | html %]_uri" data-colname="[% tab | html %]_uri">URL</th> >- <th id="[% tab | html %]_copynumber" data-colname="[% tab | html %]_copynumber">Copy number</th> >- <th id="[% tab | html %]_stocknumber" data-colname="[% tab | html %]_stocknumber">Inventory number</th> >- <th id="[% tab | html %]_materials" data-colname="[% tab | html %]_materials">Materials specified</th> >- <th id="[% tab | html %]_itemnotes" data-colname="[% tab | html %]_itemnotes">Public notes</th> >- <th id="[% tab | html %]_itemnotes_nonpublic" data-colname="[% tab | html %]_itemnotes_nonpublic">Non-public notes</th> >- [% IF ( hostrecords ) %]<th id="[% tab | html %]_hostrecord" data-colname="[% tab | html %]_hostrecord">Host records</th>[% END %] >- [% IF ( analyze ) %]<th id="[% tab | html %]_usedin" data-colname="[% tab | html %]_usedin">Used in</th><th></th>[% END %] >- [% IF ( ShowCourseReserves ) %]<th id="[% tab | html %]_course_reserves" data-colname="[% tab | html %]_course_reserves">Course reserves</th>[% END %] >- [% IF ( SpineLabelShowPrintOnBibDetails ) %]<th id="[% tab | html %]_spinelabel" data-colname="[% tab | html %]_spinelabel" class="NoSort">Spine label</th>[% END %] >- [% IF ( CAN_user_editcatalogue_edit_items ) %]<th id="[% tab | html %]_actions" data-colname="[% tab | html %]_actions"class="NoSort noExport"> </th>[% END %] >- </tr> >- </thead> >- </table> >- [% END %] >+[% SET hidden_count = all_items_count - items_to_display_count %] >+[% IF all_items_count %] >+ [% PROCESS items_table tab="holdings" %] > >- [% IF ( hiddencount ) %] >- <p><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblionumber | uri %]&showallitems=1">Show all items ([% hiddencount | html %] hidden)</a> >+ [% IF hidden_count %] >+ [%# FIXME We could deal with that in JS and prevent a full refresh %] >+ <p><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblionumber | uri %]&showallitems=1">Show all items ([% hidden_count | html %] hidden)</a> > [% END %] > [% ELSE %] > [% IF ( ALTERNATEHOLDINGS ) %] >@@ -757,13 +442,9 @@ > [% END %] > </div> > >-[% IF (SeparateHoldings) %] >+[% IF Koha.Preference('SeparateHoldings') %] > <div role="tabpanel" class="tab-pane" id="otherholdings"> >- [% IF (otheritemloop.size) %] >- [% PROCESS items_table tab="otherholdings" items=otheritemloop %] >- [% ELSE %] >- <span class="nootheritems">No other items.</span> >- [% END %] >+ [% PROCESS items_table tab="otherholdings" %] > </div> > [% 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 '<input type="checkbox" value="%s" name="itemnumber" />'.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 '<input type="checkbox" value="%s" name="itemnumber" />'.format(row.item_id); >+ } else { >+ return '' >+ } > } >- let node = '<div class="bookcoverimg">'; >- node += '<div class="cover-slider">'; >- row.cover_image_ids.forEach(id => { >- node += '<div class="cover-image local-coverimg">'; >- node += '<a href="/cgi-bin/koha/catalogue/image.pl?itemnumber=%s&imagenumber=%s" title="Local cover image">'.format(id, id); >- node += '<img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&imagenumber=%s" alt="Local cover image" data-link="/cgi-bin/koha/catalogue/imageviewer.pl?itemnumber=[% item.itemnumber | uri %]&imagenumber=%s" />'.format(id, id); >- node += '</a>'; >+ }, >+ [% 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 = '<div class="bookcoverimg">'; >+ node += '<div class="cover-slider">'; >+ row.cover_image_ids.forEach(id => { >+ node += '<div class="cover-image local-coverimg">'; >+ node += '<a href="/cgi-bin/koha/catalogue/image.pl?itemnumber=%s&imagenumber=%s" title="Local cover image">'.format(id, id); >+ node += '<img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&imagenumber=%s" alt="Local cover image" data-link="/cgi-bin/koha/catalogue/imageviewer.pl?itemnumber=[% item.itemnumber | uri %]&imagenumber=%s" />'.format(id, id); >+ node += '</a>'; >+ node += '</div>'; >+ }); > node += '</div>'; >- }); >- node += '</div>'; >- node += '</div>'; >- 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 >- ? '<img src="%s" alt="%s" title="%s" /> '.format(image_location, item_type_description, item_type_description) >- : ''; >- [% END %] >- node += '<span class="itypedesc itypetext">%s</span>'.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 = '<span class="homebranchdesc">%s</span>'.format(row._strings.home_library_id.str); >- nodes += '<span class="shelvingloc">' >- [%# 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 += '</div>'; >+ return node; > } >- nodes += '</span>'; >- 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 >+ ? '<img src="%s" alt="%s" title="%s" /> '.format(image_location, item_type_description, item_type_description) >+ : ''; >+ [% END %] >+ node += '<span class="itypedesc itypetext">%s</span>'.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 += '<span class="enum">%s</span>'.format(row.serial_issue_number); >- if ( serial.serialseq && row.serial_issue_number != serial.serialseq ) { >- nodes += ' <span class="sep"> -- </span>' >- nodes += ' <span class="serialseq">%s</span>'.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 = '<span class="homebranchdesc">%s</span>'.format(row._strings.home_library_id.str); >+ nodes += '<span class="shelvingloc">' >+ [%# 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 += ' <span class="enum">%s</span>'.format(row.serial_issue_number); >- } else if ( serial && serial.serialseq ) { >- nodes += '<span class="serialseq">%s</span>'.format(serial.serialseq); >+ nodes += '</span>'; >+ return nodes; > } >- if ( serial && serial.publisheddate ) { >- nodes += ' <span class="pubdate">(%s)</span>'.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 += '<span>'; >- 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 += '<span class="enum">%s</span>'.format(row.serial_issue_number); >+ if ( serial.serialseq && row.serial_issue_number != serial.serialseq ) { >+ nodes += ' <span class="sep"> -- </span>' >+ nodes += ' <span class="serialseq">%s</span>'.format(serial.serialseq); >+ } >+ } else if ( row.serial_issue_number ) { >+ nodes += ' <span class="enum">%s</span>'.format(row.serial_issue_number); >+ } else if ( serial && serial.serialseq ) { >+ nodes += '<span class="serialseq">%s</span>'.format(serial.serialseq); >+ } >+ if ( serial && serial.publisheddate ) { >+ nodes += ' <span class="pubdate">(%s)</span>'.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 += '<span>'; >+ 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 += '<span class="datedue">'; >- if ( can_edit_items_from[row.holding_library_id] ){ >+ nodes += '<span class="datedue">'; > 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 += "</span>" >+ } else if ( row.transfer ) { >+ if ( row.transfer.datesent ) { >+ nodes += '<span class="intransit">%s</span>'.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 += '<span class="transitrequested">%s</span>'.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 += "</span>" >- } else if ( row.transfer ) { >- if ( row.transfer.datesent ) { >- nodes += '<span class="intransit">%s</span>'.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 += '<span class="transitrequested">%s</span>'.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 += '<span class="lost">%s</span>'.format(lost_lib); > } >- } > >- if ( row.lost_status ) { >- let lost_lib = av_lost.get(row.lost_status.toString()) || _("Unavailable (lost or missing"); >- nodes += '<span class="lost">%s</span>'.format(lost_lib); >- } >+ if ( row.withdrawn ) { >+ let withdrawn_lib = av_withdrawn.get(row.withdrawn.toString()) || _("Withdrawn"); >+ nodes += '<span class="wdn">%s</span>'.format(withdrawn_lib); >+ } > >- if ( row.withdrawn ) { >- let withdrawn_lib = av_withdrawn.get(row.withdrawn.toString()) || _("Withdrawn"); >- nodes += '<span class="wdn">%s</span>'.format(withdrawn_lib); >- } >+ if ( row.damaged ) { >+ let damaged_lib = av_damaged.get(row.damaged.toString()) || _("Damaged"); >+ nodes += '<span class="dmg">%s</span>'.format(damaged_lib); >+ } > >- if ( row.damaged ) { >- let damaged_lib = av_damaged.get(row.damaged.toString()) || _("Damaged"); >- nodes += '<span class="dmg">%s</span>'.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 += '<span class="notforloan">%s'.format(_("Not for loan")) + ( not_for_loan_lib ? '<span class="reason"> (%s)</span>'.format(not_for_loan_lib) : '' ) + '</span>'; >+ } > >- 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 += '<span class="notforloan">%s'.format(_("Not for loan")) + ( not_for_loan_lib ? '<span class="reason"> (%s)</span>'.format(not_for_loan_lib) : '' ) + '</span>'; >- } >+ 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 += '<span class="waitingat">%s</span>'.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 += ' <span class="heldfor">%s</span>'.format(_("Hold for: %s").format(patron_to_html)); >+ } >+ [% END %] >+ } else { >+ nodes += '<span class="holdonitem">%s</span>'.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 += '<span class="waitingat">%s</span>'.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 += ' <span class="heldfor">%s</span>'.format(_("Hold for: %s").format(patron_to_html)); >+ [% IF Koha.Preference('UseRecalls') %] >+ if ( row.recall ) { >+ if ( row.recall.waiting_date ) { >+ nodes += '<span>%s</span>'.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 += '<span>%s</span>'.format(_("recalled by %s on %s").format(patron_to_html, row.recall.created_date)) > } >- [% END %] >- } else { >- nodes += '<span class="holdonitem">%s</span>'.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 += ' <span>%s</span>'.format(_("Available")) > } >- } > >- [% IF Koha.Preference('UseRecalls') %] >- if ( row.recall ) { >- if ( row.recall.waiting_date ) { >- nodes += '<span>%s</span>'.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 += '<span>%s</span>'.format(_("recalled by %s on %s").format(patron_to_html, row.recall.created_date)); >- } >+ if ( row.restricted_status ) { >+ nodes += '<span class="restricted">(%s)</span>'.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 += ' <span>%s</span>'.format(_("Available")) >+ if ( row.in_bundle ) { >+ nodes += '<span class="bundled">%s</span>'.format(_("In bundle: %s").format($biblio_to_html(row.bundle_host.biblio, { link: true }))); >+ } >+ return nodes; > } >- >- if ( row.restricted_status ) { >- nodes += '<span class="restricted">(%s)</span>'.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 += '<span class="bundled">%s</span>'.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 '<a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=%s#item%s">%s</a>'.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 += '<a href="%s">%s</a><br/>'.format(uri, uri); >- }); >- } else { >- nodes += '<a href="%s">%s</a><br/>'.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', '<br />') : ''; >- } >- }, >- { >- 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 '<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=%s>%s</a>'.format(row.biblio_id, row.biblio.title); >- } >- }, >- [% END %] >- [% IF ( analyze ) %] >- { >- data: "", >- searchable: false, // FIXME >- orderable: true, >- render: function (data, type, row, meta) { >- return ""; // FIXME Display analytic count + link >- } >- }, >- [% END %] >- [% IF ( ShowCourseReserves ) %] >- { >- data: "", >- searchable: false, // FIXME >- orderable: true, >- render: function (data, type, row, meta) { >- return ""; // FIXME Display course reserves >- } >- }, >- [% END %] >- [% IF ( SpineLabelShowPrintOnBibDetails ) %] >- { >- data: "", >- searchable: false, >- orderable: false, >- render: function (data, type, row, meta) { >- return '<a class="btn btn-default btn-xs print-label" href="/cgi-bin/koha/labels/spinelabel-print.pl?barcode=%s"><i class="fa fa-print"></i> Print label</a>'.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 += '<div class="btn-group">'; >- nodes += ' <a class="btn btn-default btn-xs" href="/cgi-bin/koha/cataloguing/additem.pl?op=edititem&biblionumber=%s&itemnumber=%s#edititem"><i class="fa fa-pencil"></i> Edit</a><a class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></a>'.format(row.biblio_id, row.item_id); >- nodes += ' <ul class="dropdown-menu pull-right">'; >- nodes += ' <li><a href="/cgi-bin/koha/tools/upload-cover-image.pl?itemnumber=%s&filetype=image"><i class="fa fa-upload"></i> Upload image</a></li>'.format(row.item_id); >- nodes += ' </ul>'; >- nodes += '</div>'; >- [% ELSE %] >- nodes += '<a class="btn btn-default btn-xs" href="/cgi-bin/koha/cataloguing/additem.pl?op=edititem&biblionumber=%s&itemnumber=%s#edititem"><i class="fa fa-pencil"></i> Edit</a>'.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 += '<button class="btn btn-default btn-xs details-control"><i class="fa fa-folder"></i> Manage bundle (%s|%s)</button>'.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 '<a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=%s#item%s">%s</a>'.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 += '<a href="%s">%s</a><br/>'.format(uri, uri); >+ }); >+ } else { >+ nodes += '<a href="%s">%s</a><br/>'.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', '<br />') : ''; >+ } >+ }, >+ { >+ 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 '<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=%s>%s</a>'.format(row.biblio_id, row.biblio.title); >+ } >+ }, >+ [% END %] >+ [% IF ( analyze ) %] >+ { >+ data: "", >+ searchable: false, // FIXME >+ orderable: true, >+ render: function (data, type, row, meta) { >+ return ""; // FIXME Display analytic count + link >+ } >+ }, >+ [% END %] >+ [% IF ( ShowCourseReserves ) %] >+ { >+ data: "", >+ searchable: false, // FIXME >+ orderable: true, >+ render: function (data, type, row, meta) { >+ return ""; // FIXME Display course reserves >+ } >+ }, >+ [% END %] >+ [% IF ( SpineLabelShowPrintOnBibDetails ) %] >+ { >+ data: "", >+ searchable: false, >+ orderable: false, >+ render: function (data, type, row, meta) { >+ return '<a class="btn btn-default btn-xs print-label" href="/cgi-bin/koha/labels/spinelabel-print.pl?barcode=%s"><i class="fa fa-print"></i> Print label</a>'.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 += '<div class="btn-group">'; >+ nodes += ' <a class="btn btn-default btn-xs" href="/cgi-bin/koha/cataloguing/additem.pl?op=edititem&biblionumber=%s&itemnumber=%s#edititem"><i class="fa-solid fa-pencil"></i> Edit</a><a class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></a>'.format(row.biblio_id, row.item_id); >+ nodes += ' <ul class="dropdown-menu pull-right">'; >+ nodes += ' <li><a href="/cgi-bin/koha/tools/upload-cover-image.pl?itemnumber=%s&filetype=image"><i class="fa fa-upload"></i> Upload image</a></li>'.format(row.item_id); >+ nodes += ' </ul>'; >+ nodes += '</div>'; >+ [% ELSE %] >+ nodes += '<a class="btn btn-default btn-xs" href="/cgi-bin/koha/cataloguing/additem.pl?op=edititem&biblionumber=%s&itemnumber=%s#edititem"><i class="fa-solid fa-pencil"></i> Edit</a>'.format(row.biblio_id, row.item_id); >+ [% END %] >+ } >+ [% IF bundlesEnabled %] >+ // FIXME How do we handle that correctly? >+ //nodes += '<button class="btn btn-default btn-xs details-control"><i class="fa fa-folder"></i> Manage bundle (%s|%s)</button>'.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; >+ } > </script> > [% CoverImagePlugins | $raw %] > [% END %] >-- >2.34.1
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 33568
:
151339
|
153791
|
164308
|
164309
|
164310
|
164311
|
164312
|
164313
|
164314
|
164315
|
164316
|
164317
|
164318
|
164319
|
164320
|
164321
|
164322
|
164323
|
164324
|
164325
|
164326
|
164327
|
164328
|
164329
|
164330
|
164331
|
164332
|
164333
|
164334
|
164335
|
164336
|
164337
|
164338
|
164339
|
164340
|
164341
|
164342
|
164343
|
164344
|
164345
|
164346
|
164347
|
164348
|
164349
|
164350
|
164351
|
164352
|
164353
|
164354
|
164355
|
164356
|
164358
|
164359
|
164360
|
164361
|
164362
|
164363
|
164364
|
164365
|
164366
|
164367
|
164368
|
164369
|
164370
|
164371
|
164372
|
164373
|
164374
|
164472
|
164480
|
164482
|
164483
|
164485
|
164528