View | Details | Raw Unified | Return to bug 33568
Collapse All | Expand All

(-)a/Koha/REST/V1/Biblios.pm (+2 lines)
Lines 300-305 sub get_items { Link Here
300
300
301
    return try {
301
    return try {
302
302
303
        # FIXME We need to order_by serial.publisheddate if we have _order_by=+me.serial_issue_number
304
        #       Should we use search_ordered here? Maybe as well in Koha::REST::V1::Items::list?
303
        # FIXME Do we always need host_items => 1 or depending on a flag?
305
        # FIXME Do we always need host_items => 1 or depending on a flag?
304
        # FIXME Should we prefetch => ['issue','branchtransfer']?
306
        # FIXME Should we prefetch => ['issue','branchtransfer']?
305
        my $items_rs = $biblio->items( { host_items => 1 } )->search( {}, { join => 'biblioitem' } ) );
307
        my $items_rs = $biblio->items( { host_items => 1 } )->search( {}, { join => 'biblioitem' } ) );
(-)a/catalogue/detail.pl (-149 / +13 lines)
Lines 190-210 $template->param( Link Here
190
);
190
);
191
191
192
my $itemtypes = { map { $_->itemtype => $_ } @{ Koha::ItemTypes->search_with_localization->as_list } };
192
my $itemtypes = { map { $_->itemtype => $_ } @{ Koha::ItemTypes->search_with_localization->as_list } };
193
my $params;
194
my $patron = Koha::Patrons->find( $borrowernumber );
193
my $patron = Koha::Patrons->find( $borrowernumber );
195
$params->{ itemlost } = 0 if $patron->category->hidelostitems && !$showallitems;
194
my $include_lost_items = !$patron->category->hidelostitems || $showallitems;
196
my $items_params = {
195
my $items_params = {
197
    ( $invalid_marc_record ? () : ( host_items => 1 ) ),
196
    ( $invalid_marc_record ? () : ( host_items => 1 ) ),
198
};
197
};
199
my $items = $biblio->items($items_params)->search_ordered( $params, { prefetch => ['issue','current_branchtransfers'] } );
198
my $all_items = $biblio->items($items_params);
199
my $items_to_display = $all_items->search({ $include_lost_items ? () : ( itemlost => 0 ) });
200
200
201
# flag indicating existence of at least one item linked via a host record
201
# flag indicating existence of at least one item linked via a host record
202
my $hostrecords = $biblio->host_items->count;
202
my $hostrecords = $biblio->host_items->count;
203
203
204
my $dat = &GetBiblioData($biblionumber);
204
my $dat = &GetBiblioData($biblionumber);
205
$dat->{'count'} = $biblio->items($items_params)->count;
206
$dat->{'showncount'} = $items->count;
207
$dat->{'hiddencount'} = $dat->{'count'} - $dat->{'showncount'};
208
205
209
#is biblio a collection and are bundles enabled
206
#is biblio a collection and are bundles enabled
210
my $leader = $marc_record->leader();
207
my $leader = $marc_record->leader();
Lines 321-458 if ( defined $dat->{'itemtype'} ) { Link Here
321
    $dat->{imageurl} = getitemtypeimagelocation( 'intranet', $itemtypes->{ $dat->{itemtype} }->imageurl );
318
    $dat->{imageurl} = getitemtypeimagelocation( 'intranet', $itemtypes->{ $dat->{itemtype} }->imageurl );
322
}
319
}
323
320
324
my (@itemloop, @otheritemloop, %itemfields);
321
if ( C4::Context->preference('SeparateHoldings') ) {
325
322
    my $SeparateHoldingsBranch = C4::Context->preference('SeparateHoldingsBranch') || 'homebranch';
326
my $mss = Koha::MarcSubfieldStructures->search({ frameworkcode => $fw, kohafield => 'items.itemlost', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] });
323
    my $other_holdings_count = $items_to_display->search({ $SeparateHoldingsBranch => { '!=' => C4::Context->userenv->{branch} } })->count;
327
if ( $mss->count ) {
324
    $template->param( other_holdings_count => $other_holdings_count );
328
    $template->param( itemlostloop => GetAuthorisedValues( $mss->next->authorised_value ) );
329
}
330
$mss = Koha::MarcSubfieldStructures->search({ frameworkcode => $fw, kohafield => 'items.damaged', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] });
331
if ( $mss->count ) {
332
    $template->param( itemdamagedloop => GetAuthorisedValues( $mss->next->authorised_value ) );
333
}
334
$mss = Koha::MarcSubfieldStructures->search({ frameworkcode => $fw, kohafield => 'items.withdrawn', authorised_value => { not => undef } });
335
if ( $mss->count ) {
336
    $template->param( itemwithdrawnloop => GetAuthorisedValues( $mss->next->authorised_value) );
337
}
325
}
338
339
$mss = Koha::MarcSubfieldStructures->search({ frameworkcode => $fw, kohafield => 'items.materials', authorised_value => [ -and => {'!=' => undef }, {'!=' => ''}] });
340
my %materials_map;
341
if ($mss->count) {
342
    my $materials_authvals = GetAuthorisedValues($mss->next->authorised_value);
343
    if ($materials_authvals) {
344
        foreach my $value (@$materials_authvals) {
345
            $materials_map{$value->{authorised_value}} = $value->{lib};
346
        }
347
    }
348
}
349
350
my $analytics_flag;
351
my $materials_flag; # set this if the items have anything in the materials field
352
my $currentbranch = C4::Context->userenv ? C4::Context->userenv->{branch} : undef;
353
if ($currentbranch and C4::Context->preference('SeparateHoldings')) {
354
    $template->param(SeparateHoldings => 1);
355
}
356
my $separatebranch = C4::Context->preference('SeparateHoldingsBranch') || 'homebranch';
357
my ( $itemloop_has_images, $otheritemloop_has_images );
358
359
while ( my $item = $items->next ) {
360
    my $itembranchcode = $item->$separatebranch;
361
362
    my $item_info = $item->unblessed;
363
    $item_info->{itemtype} = $itemtypes->{$item->effective_itemtype};
364
365
    foreach (qw(ccode enumchron copynumber stocknumber itemnotes itemnotes_nonpublic uri )) {
366
        $itemfields{$_} = 1 if $item->$_;
367
    }
368
369
    # FIXME The following must be Koha::Item->serial
370
    my $serial_item = Koha::Serial::Items->find($item->itemnumber);
371
    if ( $serial_item ) {
372
        my $serial = Koha::Serials->find($serial_item->serialid);
373
        $item_info->{serial} = $serial if $serial;
374
        $itemfields{publisheddate} = 1;
375
    }
376
377
    $item_info->{object} = $item;
378
379
    # checking for holds
380
    my $holds = $item->current_holds;
381
    if ( my $first_hold = $holds->next ) {
382
        $item_info->{first_hold} = $first_hold;
383
    }
384
385
    #item has a host number if its biblio number does not match the current bib
386
387
    if ($item->biblionumber ne $biblionumber){
388
        $item_info->{hostbiblionumber} = $item->biblionumber;
389
        $item_info->{hosttitle} = $item->biblio->title;
390
    }
391
392
393
    if ( $analyze ) {
394
        # count if item is used in analytical bibliorecords
395
        # The 'countanalytics' flag is only used in the templates if analyze is set
396
        my $countanalytics = GetAnalyticsCount( $item->itemnumber );
397
        if ($countanalytics > 0){
398
            $analytics_flag=1;
399
            $item_info->{countanalytics} = $countanalytics;
400
        }
401
    }
402
403
    if (defined($item->materials) && $item->materials =~ /\S/){
404
        $materials_flag = 1;
405
        if (defined $materials_map{ $item->materials }) {
406
            $item_info->{materials} = $materials_map{ $item->materials };
407
        }
408
    }
409
410
    if ( C4::Context->preference('UseCourseReserves') ) {
411
        $item_info->{'course_reserves'} = GetItemCourseReservesInfo( itemnumber => $item->itemnumber );
412
    }
413
414
    $item_info->{can_be_edited} = $patron->can_edit_items_from( $item->homebranch );
415
416
    if ( $item->is_bundle ) {
417
        $item_info->{bundled} =
418
          $item->bundle_items->search( { itemlost => { '!=' => 0 } } )
419
          ->count;
420
        $item_info->{bundled_lost} =
421
          $item->bundle_items->search( { itemlost => 0 } )->count;
422
        $item_info->{is_bundle} = 1;
423
    }
424
425
    if ($item->in_bundle) {
426
        $item_info->{bundle_host} = $item->bundle_host;
427
    }
428
429
    if ($currentbranch and C4::Context->preference('SeparateHoldings')) {
430
        if ($itembranchcode and $itembranchcode eq $currentbranch) {
431
            push @itemloop, $item_info;
432
            $itemloop_has_images++ if $item->cover_images->count;
433
        } else {
434
            push @otheritemloop, $item_info;
435
            $otheritemloop_has_images++ if $item->cover_images->count;
436
        }
437
    } else {
438
        push @itemloop, $item_info;
439
        $itemloop_has_images++ if $item->cover_images->count;
440
    }
441
}
442
443
$template->param(
326
$template->param(
444
    itemloop_has_images      => $itemloop_has_images,
327
    count => $all_items->count, # FIXME 'count' is used in catalog-strings.inc
445
    otheritemloop_has_images => $otheritemloop_has_images,
328
                                # But it's not a meaningful variable, we should rename it there
329
    all_items_count => $all_items->count,
330
    items_to_display_count => $items_to_display->count,
446
);
331
);
447
332
448
# Display only one tab if one items list is empty
449
if (scalar(@itemloop) == 0 || scalar(@otheritemloop) == 0) {
450
    $template->param(SeparateHoldings => 0);
451
    if (scalar(@itemloop) == 0) {
452
        @itemloop = @otheritemloop;
453
    }
454
}
455
456
my $some_private_shelves = Koha::Virtualshelves->get_some_shelves(
333
my $some_private_shelves = Koha::Virtualshelves->get_some_shelves(
457
    {
334
    {
458
        borrowernumber => $borrowernumber,
335
        borrowernumber => $borrowernumber,
Lines 476-498 $template->param( Link Here
476
353
477
$template->param(
354
$template->param(
478
    MARCNOTES               => !$invalid_marc_record ? $biblio->get_marc_notes() : undef,
355
    MARCNOTES               => !$invalid_marc_record ? $biblio->get_marc_notes() : undef,
479
    itemdata_ccode          => $itemfields{ccode},
480
    itemdata_enumchron      => $itemfields{enumchron},
481
    itemdata_uri            => $itemfields{uri},
482
    itemdata_copynumber     => $itemfields{copynumber},
483
    itemdata_stocknumber    => $itemfields{stocknumber},
484
    itemdata_publisheddate  => $itemfields{publisheddate},
485
    volinfo                 => $itemfields{enumchron},
486
    itemdata_itemnotes      => $itemfields{itemnotes},
487
    itemdata_nonpublicnotes => $itemfields{itemnotes_nonpublic},
488
    z3950_search_params     => C4::Search::z3950_search_args($dat),
356
    z3950_search_params     => C4::Search::z3950_search_args($dat),
489
    hostrecords             => $hostrecords,
357
    hostrecords             => $hostrecords,
490
    analytics_flag          => $analytics_flag,
491
    C4::Search::enabled_staff_search_views,
358
    C4::Search::enabled_staff_search_views,
492
    materials => $materials_flag,
493
);
359
);
494
360
495
if (C4::Context->preference("AlternateHoldingsField") && $items->count == 0) {
361
if (C4::Context->preference("AlternateHoldingsField") && $items_to_display->count == 0) {
496
    my $fieldspec = C4::Context->preference("AlternateHoldingsField");
362
    my $fieldspec = C4::Context->preference("AlternateHoldingsField");
497
    my $subfields = substr $fieldspec, 3;
363
    my $subfields = substr $fieldspec, 3;
498
    my $holdingsep = C4::Context->preference("AlternateHoldingsSeparator") || ' ';
364
    my $holdingsep = C4::Context->preference("AlternateHoldingsSeparator") || ' ';
Lines 528-535 foreach ( keys %{$dat} ) { Link Here
528
# method query not found?!?!
394
# method query not found?!?!
529
$template->param( AmazonTld => get_amazon_tld() ) if ( C4::Context->preference("AmazonCoverImages"));
395
$template->param( AmazonTld => get_amazon_tld() ) if ( C4::Context->preference("AmazonCoverImages"));
530
$template->param(
396
$template->param(
531
    itemloop        => \@itemloop,
532
    otheritemloop   => \@otheritemloop,
533
    biblionumber        => $biblionumber,
397
    biblionumber        => $biblionumber,
534
    ($analyze? 'analyze':'detailview') =>1,
398
    ($analyze? 'analyze':'detailview') =>1,
535
    subscriptions       => \@subs,
399
    subscriptions       => \@subs,
Lines 634-640 if ( C4::Context->preference('UseCourseReserves') ) { Link Here
634
    $template->param( course_reserves => $course_reserves );
498
    $template->param( course_reserves => $course_reserves );
635
}
499
}
636
500
637
my @libraries = $biblio->items({ host_items => 1 })->get_column('homebranch');
501
my @libraries = $biblio->items($items_params)->get_column('homebranch');
638
my %can_edit_items_from = map {
502
my %can_edit_items_from = map {
639
    $_ => $patron->can_edit_items_from($_)
503
    $_ => $patron->can_edit_items_from($_)
640
} @libraries;
504
} @libraries;
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt (-807 / +488 lines)
Lines 284-299 Link Here
284
<div id="bibliodetails" class="toptabs">
284
<div id="bibliodetails" class="toptabs">
285
285
286
<ul class="nav nav-tabs" role="tablist">
286
<ul class="nav nav-tabs" role="tablist">
287
    [% IF (SeparateHoldings) %]
287
    [% IF Koha.Preference('SeparateHoldings') %]
288
        <li role="presentation">
288
        <li role="presentation">
289
            <a href="#holdings" aria-controls="holdings" role="tab" data-toggle="tab">[% Branches.GetLoggedInBranchname | html %] holdings ([% itemloop.size() || 0 | html %])</a>
289
            [%# FIXME We could build the numbers from DataTable's info %]
290
            <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>
290
        </li>
291
        </li>
291
        <li role="presentation">
292
        <li role="presentation">
292
            <a href="#otherholdings"  aria-controls="otherholdings" role="tab" data-toggle="tab">Other holdings ([% otheritemloop.size() || 0 | html %])</a>
293
            <a href="#otherholdings"  aria-controls="otherholdings" role="tab" data-toggle="tab">Other holdings ([% other_holdings_count || 0 | html %])</a>
293
        </li>
294
        </li>
294
    [% ELSE %]
295
    [% ELSE %]
295
        <li role="presentation">
296
        <li role="presentation">
296
            <a href="#holdings" aria-controls="holdings" role="tab" data-toggle="tab">Holdings ([% itemloop.size() || 0 | html %])</a>
297
            <a href="#holdings" aria-controls="holdings" role="tab" data-toggle="tab">Holdings ([% items_to_display_count || 0 | html %])</a>
297
        </li>
298
        </li>
298
    [% END %]
299
    [% END %]
299
    [% IF Koha.Preference('EnableItemGroups') %]
300
    [% IF Koha.Preference('EnableItemGroups') %]
Lines 347-667 Link Here
347
            </span>
348
            </span>
348
        [% END %]
349
        [% END %]
349
    </div>
350
    </div>
351
350
    <table class="items_table" id="[% tab | html %]_table">
352
    <table class="items_table" id="[% tab | html %]_table">
351
        <thead>
353
        <thead>
352
            <tr>
354
            [% IF (StaffDetailItemSelection) %]<th id="[% tab | html %]_checkbox" data-colname="[% tab | html %]_checkbox" class="NoSort"></th>[% END %]
353
                [% IF (StaffDetailItemSelection) %]<th id="[% tab | html %]_checkbox" data-colname="[% tab | html %]_checkbox" class="NoSort"></th>[% END %]
355
            [% IF Koha.Preference('LocalCoverImages') %]
354
                [% IF Koha.Preference('LocalCoverImages') && ( tab == 'holdings' && itemloop_has_images || tab == 'otherholdings' && otheritemloop_has_images ) %]
356
                <th id="[% tab | html %]_cover_image" data-colname="[% tab | html %]_cover_image">Cover image</th>
355
                    <th id="[% tab | html %]_cover_image" data-colname="[% tab | html %]_cover_image">Cover image</th>
357
            [% END %]
356
                [% END %]
358
            [% IF ( item_level_itypes ) %]<th id="[% tab | html %]_itype" data-colname="[% tab | html %]_itype">Item type</th>[% END %]
357
                [% IF ( item_level_itypes ) %]<th id="[% tab | html %]_itype" data-colname="[% tab | html %]_itype">Item type</th>[% END %]
359
            <th id="[% tab | html %]_holdingbranch" data-colname="[% tab | html %]_holdingbranch">Current library</th>
358
                <th id="[% tab | html %]_holdingbranch" data-colname="[% tab | html %]_holdingbranch">Current library</th>
360
            <th id="[% tab | html %]_homebranch" data-colname="[% tab | html %]_homebranch">Home library</th>
359
                <th id="[% tab | html %]_homebranch" data-colname="[% tab | html %]_homebranch">Home library</th>
361
            <th id="[% tab | html %]_ccode" data-colname="[% tab | html %]_ccode">Collection</th>
360
                [% IF ( itemdata_ccode ) %]<th id="[% tab | html %]_ccode" data-colname="[% tab | html %]_ccode">Collection</th>[% END %]
362
            [% IF Koha.Preference('EnableItemGroups') %]
361
                [% IF Koha.Preference('EnableItemGroups') %]
363
                <th id="[% tab | html %]_item_group" data-colname="[% tab | html %]_item_group">Item group</th>
362
                    <th id="[% tab | html %]_item_group" data-colname="[% tab | html %]_item_group">Item group</th>
364
            [% END %]
363
                [% END %]
365
            <th id="[% tab | html %]_itemcallnumber" data-colname="[% tab | html %]_itemcallnumber">Call number</th>
364
                <th id="[% tab | html %]_itemcallnumber" data-colname="[% tab | html %]_itemcallnumber">Call number</th>
366
            <th id="[% tab | html %]_enumchron" data-colname="[% tab | html %]_enumchron">Serial enumeration / chronology</th>
365
                [% IF volinfo %]
367
            <th id="[% tab | html %]_status" data-colname="[% tab | html %]_status">Status</th>
366
                    <th id="[% tab | html %]_enumchron" data-colname="[% tab | html %]_enumchron">Serial enumeration / chronology</th>
368
            <th id="[% tab | html %]_lastseen" data-colname="[% tab | html %]_lastseen">Last seen</th>
367
                [% END %]
369
            <th id="[% tab | html %]_issues" data-colname="[% tab | html %]_issues">Checkouts</th>
368
                <th id="[% tab | html %]_status" data-colname="[% tab | html %]_status">Status</th>
370
            <th id="[% tab | html %]_renewals" data-colname="[% tab | html %]_renewals">Renewals</th>
369
                <th id="[% tab | html %]_lastseen" data-colname="[% tab | html %]_lastseen">Last seen</th>
371
            <th id="[% tab | html %]_dateaccessioned" data-colname="[% tab | html %]_dateaccessioned">Date accessioned</th>
370
                <th id="[% tab | html %]_issues" data-colname="[% tab | html %]_issues">Checkouts</th>
372
            <th id="[% tab | html %]_datelastborrowed" data-colname="[% tab | html %]_datelastborrowed">Date last borrowed</th>
371
                <th id="[% tab | html %]_renewals" data-colname="[% tab | html %]_renewals">Renewals</th>
373
            <th id="[% tab | html %]_barcode" data-colname="[% tab | html %]_barcode">Barcode</th>
372
                <th id="[% tab | html %]_dateaccessioned" data-colname="[% tab | html %]_dateaccessioned">Date accessioned</th>
374
            <th id="[% tab | html %]_uri" data-colname="[% tab | html %]_uri">URL</th>
373
                <th id="[% tab | html %]_datelastborrowed" data-colname="[% tab | html %]_datelastborrowed">Date last borrowed</th>
375
            <th id="[% tab | html %]_copynumber" data-colname="[% tab | html %]_copynumber">Copy number</th>
374
                <th id="[% tab | html %]_barcode" data-colname="[% tab | html %]_barcode">Barcode</th>
376
            <th id="[% tab | html %]_stocknumber" data-colname="[% tab | html %]_stocknumber">Inventory number</th>
375
                [% IF ( itemdata_uri ) %]<th id="[% tab | html %]_uri" data-colname="[% tab | html %]_uri">URL</th>[% END %]
377
            <th id="[% tab | html %]_materials" data-colname="[% tab | html %]_materials">Materials specified</th>
376
                [% IF ( itemdata_copynumber ) %]<th id="[% tab | html %]_copynumber" data-colname="[% tab | html %]_copynumber">Copy number</th>[% END %]
378
            <th id="[% tab | html %]_itemnotes" data-colname="[% tab | html %]_itemnotes">Public notes</th>
377
                [% IF ( itemdata_stocknumber ) %]<th id="[% tab | html %]_stocknumber" data-colname="[% tab | html %]_stocknumber">Inventory number</th>[% END %]
379
            <th id="[% tab | html %]_itemnotes_nonpublic" data-colname="[% tab | html %]_itemnotes_nonpublic">Non-public notes</th>
378
                [% IF materials %]<th id="[% tab | html %]_materials" data-colname="[% tab | html %]_materials">Materials specified</th>[% END %]
380
            [% IF ( hostrecords ) %]<th id="[% tab | html %]_hostrecord" data-colname="[% tab | html %]_hostrecord">Host records</th>[% END %]
379
                [% IF ( itemdata_itemnotes ) %]<th id="[% tab | html %]_itemnotes" data-colname="[% tab | html %]_itemnotes">Public notes</th>[% END %]
381
            [% IF ( analyze ) %]<th id="[% tab | html %]_usedin" data-colname="[% tab | html %]_usedin">Used in</th><th></th>[% END %]
380
                [% IF ( itemdata_nonpublicnotes ) %]<th id="[% tab | html %]_itemnotes_nonpublic" data-colname="[% tab | html %]_itemnotes_nonpublic">Non-public notes</th>[% END %]
382
            [% IF ( ShowCourseReserves ) %]<th id="[% tab | html %]_course_reserves" data-colname="[% tab | html %]_course_reserves">Course reserves</th>[% END %]
381
                [% IF ( hostrecords ) %]<th id="[% tab | html %]_hostrecord" data-colname="[% tab | html %]_hostrecord">Host records</th>[% END %]
383
            [% IF ( SpineLabelShowPrintOnBibDetails ) %]<th id="[% tab | html %]_spinelabel" data-colname="[% tab | html %]_spinelabel" class="NoSort">Spine label</th>[% END %]
382
                [% IF ( analyze ) %]<th id="[% tab | html %]_usedin" data-colname="[% tab | html %]_usedin">Used in</th><th></th>[% END %]
384
            [% IF ( CAN_user_editcatalogue_edit_items ) %]<th id="[% tab | html %]_actions" data-colname="[% tab | html %]_actions"class="NoSort noExport">&nbsp;</th>[% END %]
383
                [% IF ( ShowCourseReserves ) %]<th id="[% tab | html %]_course_reserves" data-colname="[% tab | html %]_course_reserves">Course reserves</th>[% END %]
384
                [% IF ( SpineLabelShowPrintOnBibDetails ) %]<th id="[% tab | html %]_spinelabel" data-colname="[% tab | html %]_spinelabel" class="NoSort">Spine label</th>[% END %]
385
                [% IF ( CAN_user_editcatalogue_edit_items ) %]<th id="[% tab | html %]_actions" data-colname="[% tab | html %]_actions"class="NoSort noExport">&nbsp;</th>[% END %]
386
            </tr>
385
            </tr>
387
        </thead>
386
        </thead>
388
        <tbody>
389
            [% FOREACH item IN items %]
390
                [% SET date_due = item.object.checkout.date_due %]
391
                <tr id="item_[% item.itemnumber | html %]" data-itemnumber="[% item.itemnumber | html %]" data-duedate="[% date_due | html %]">
392
                [% IF (StaffDetailItemSelection) %]
393
                    <td style="text-align:center;vertical-align:middle">
394
                        [% IF item.can_be_edited %]
395
                            <input type="checkbox" value="[% item.itemnumber | html %]" name="itemnumber" />
396
                        [% END %]
397
                    </td>
398
                [% END %]
399
                    [% IF Koha.Preference('LocalCoverImages') && ( tab == 'holdings' && itemloop_has_images || tab == 'otherholdings' && otheritemloop_has_images ) %]
400
                        <td class="cover">
401
                            <div class="bookcoverimg">
402
                                <div class="cover-slider">
403
                                    [% FOREACH image IN item.object.cover_images %]
404
                                        <div class="cover-image local-coverimg">
405
                                            <a href="/cgi-bin/koha/catalogue/image.pl?itemnumber=[% image.itemnumber | uri %]&amp;imagenumber=[% image.imagenumber | uri %]" title="Local cover image">
406
                                                <img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&amp;imagenumber=[% image.imagenumber | uri %]" alt="Local cover image" data-link="/cgi-bin/koha/catalogue/imageviewer.pl?itemnumber=[% item.itemnumber | uri %]&amp;imagenumber=[% image.imagenumber | uri %]" />
407
                                            </a>
408
                                        </div>
409
                                    [% END %]
410
                                </div>
411
                            </div>
412
                        </td>
413
                    [% END %]
414
415
                    [% IF ( item_level_itypes ) %]
416
                        <td class="itype">
417
                            [% SET itemtype = item.itemtype %]
418
                            [% IF !noItemTypeImages && itemtype.image_location('intranet') %]
419
                                <img src="[% itemtype.image_location('intranet') | html %]" alt="[% itemtype.translated_description | html %]" title="[% itemtype.translated_description | html %]" />
420
                            [% END %]
421
                            <span class="itypedesc itypetext">[% itemtype.translated_description | html %]</span>
422
                        </td>
423
                    [% END %]
424
                    <td class="location">[% UNLESS ( singlebranchmode ) %][% Branches.GetName( item.holdingbranch ) | html %] [% END %]</td>
425
                    <td class="homebranch">
426
                        <span class="homebranchdesc">[% Branches.GetName(item.homebranch) | html %]</span>
427
                        <span class="shelvingloc">
428
                        [%# If permanent location is defined, show description or code and             %]
429
                        [%# display current location in parentheses. If not, display current location. %]
430
                        [%# Note that permanent location is a code, and location may be an authval.    %]
431
                            [% SET item_location = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.location ) %]
432
                            [% IF item.permanent_location %]
433
                                [% SET permloc_authval = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.permanent_location ) %]
434
                                [% permloc_authval | html %]
435
                                [% IF item_location AND item_location != permloc_authval AND item.location != item.permanent_location %]
436
                                    ([% item_location | html %])
437
                                [% END %]
438
                            [% ELSE %]
439
                                [% item_location | html %]
440
                            [% END %]
441
                        </span>
442
                    </td>
443
                    [% IF ( itemdata_ccode ) %]<td>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => item.ccode ) | html %]</td>[% END %]
444
                    [% IF Koha.Preference('EnableItemGroups') %]<td class="item_group">[% item.object.item_group.description | html %]</td>[% END %]
445
                    <td class="itemcallnumber">[% IF ( item.itemcallnumber ) %] [% item.itemcallnumber | html %][% END %]</td>
446
                    [% IF ( volinfo ) %]
447
                        [% SET serial = item.serial %]
448
                        [% IF itemdata_publisheddate #If there is at least one published date, use it for sorting %]
449
                            <td class="enumchron" data-order="[% serial.publisheddate | html %]">
450
                        [% ELSE %]
451
                            <td class="enumchron">
452
                        [% END %]
453
                            [% IF ( itemdata_enumchron ) %]
454
                                [% IF item.enumchron && serial.serialseq %]
455
                                    <span class="enum">[% item.enumchron | html %]</span>
456
                                    [% IF ( serial.serialseq && item.enumchron != serial.serialseq ) %]
457
                                        <span class="sep"> -- </span>
458
                                        <span class="serialseq">[% serial.serialseq | html %]</span>
459
                                    [% END %]
460
                                [% ELSIF item.enumchron %]
461
                                    <span class="enum">[% item.enumchron | html %]</span>
462
                                [% ELSIF item.serialseq %]
463
                                    <span class="serialseq">[% serial.serialseq | html %]</span>
464
                                [% END %]
465
                                [% IF serial.publisheddate %]
466
                                    <span class="pubdate">([% serial.publisheddate | $KohaDates %])</span>
467
                                [% END %]
468
                            [% END %]
469
                            </span>
470
                        </td>
471
                    [% END %]
472
                    <td class="status">
473
474
                        [% IF item.object.checkout %]
475
                          [% IF item.object.checkout.onsite_checkout %]
476
                            <div class="item_status localuse">Currently in local use
477
                          [% ELSE %]
478
                            <div class="item_status datedue">Checked out
479
                          [% END %]
480
                              [% IF item.object.checkout.onsite_checkout %]
481
                                by
482
                              [% ELSE %]
483
                                to
484
                              [% END %]
485
                              [% INCLUDE 'patron-title.inc' patron=item.object.checkout.patron hide_patron_infos_if_needed=1 %]
486
                            : due [% date_due | $KohaDates as_due_date => 1 %]
487
                            </div>
488
                        [% ELSIF ( transfer = item.object.get_transfer ) %]
489
                            [% IF (transfer.datesent) %]
490
                                <div class="item_status intransit">In transit from [% Branches.GetName( transfer.frombranch ) | html %] to [% Branches.GetName( transfer.tobranch ) | html %] since [% transfer.datesent | $KohaDates %]</div>
491
                            [% ELSE %]
492
                                <div class="item_status transitrequested">Transit pending from [% Branches.GetName( transfer.frombranch ) | html %] to [% Branches.GetName( transfer.tobranch ) | html %] since [% transfer.daterequested | $KohaDates %]</div>
493
                            [% END %]
494
                        [% END %]
495
496
                        [% IF ( item.itemlost ) %]
497
                            [% SET itemlost_description = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.itemlost', authorised_value => item.itemlost ) %]
498
                            [% IF itemlostloop %]
499
                                <div class="item_status lost">[% itemlost_description | html %]</div>
500
                            [% ELSE %]
501
                                <div class="item_status lost">Unavailable (lost or missing)</div>
502
                            [% END %]
503
                        [% END %]
504
505
                        [% IF ( item.withdrawn ) %]
506
                            [% SET withdrawn_description = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.withdrawn', authorised_value => item.withdrawn ) %]
507
                            [% IF withdrawn_description %]
508
                                <div class="item_status wdn">[% withdrawn_description | html %]</div>
509
                            [% ELSE %]
510
                                <div class="item_status wdn">Withdrawn</div>
511
                            [% END %]
512
                        [% END %]
513
514
                        [% IF ( item.damaged ) %]
515
                            [% SET damaged_description = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.damaged', authorised_value => item.damaged ) %]
516
                            [% IF damaged_description %]
517
                                <div class="item_status dmg">[% damaged_description | html %]</div>
518
                            [% ELSE %]
519
                                <div class="item_status dmg">Damaged</div>
520
                            [% END %]
521
                        [% END %]
522
523
                        [% IF ( item.notforloan || item.itemtype.notforloan ) %]
524
                            <div class="item_status notforloan">Not for loan
525
                            [% SET not_for_loan_description = AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.notforloan', authorised_value => item.notforloan ) %]
526
                            [% IF not_for_loan_description %]
527
                                <span class="reason">([% not_for_loan_description | html %])</span>
528
                            [% END %]
529
                            </div>
530
                        [% END %]
531
532
                        [% SET hold = item.first_hold %]
533
                        [% IF hold %]
534
                            [% IF hold.waitingdate %]
535
                                <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>
536
                                [% IF canreservefromotherbranches AND ( hold.waitingdate OR hold.priority == 1 ) %]
537
                                    <span class="heldfor">Hold for:</span>
538
                                    [% INCLUDE 'patron-title.inc' patron=hold.borrower hide_patron_infos_if_needed=1 %]
539
                                [% END %]
540
                            [% ELSE %]
541
                                <div class="item_status holdonitem">There is an item level hold on this item (priority = [% hold.priority | html %]).</div>
542
                            [% END %]
543
                        [% END %]
544
545
                        [% IF Koha.Preference('UseRecalls') %]
546
                            [% SET recall = item.object.recall %]
547
                            [% IF recall %]
548
                                [% IF recall.waiting_date %]
549
                                    <div class="item_status recallat">Waiting at [% Branches.GetName( recall.pickup_library_id ) | html %] since [% recall.waiting_date | $KohaDates %]</div>
550
                                [% ELSE %]
551
                                    [% 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 %]
552
                                    <div class="item_status recallby">recalled by [% patron_link| $raw %] on [% recall.created_date | $KohaDates %]</div>
553
                                [% END %]
554
                            [% END %]
555
                        [% END %]
556
557
                        [% UNLESS ( item.notforloan || item.itemtype.notforloan || item.onloan || item.itemlost || item.withdrawn || item.damaged || transfer || hold || ( Koha.Preference('UseRecalls') && recall ) ) %]
558
                            <div class="item_status available">Available</div>
559
                        [% END %]
560
561
                        [% IF ( item.restricted ) %]
562
                            <div class="item_status restricted">([% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.restricted', authorised_value => item.restricted ) | html %])</div>
563
                        [% END %]
564
565
                        [% IF ( item.bundle_host ) %]
566
                            <div class="item_status bundled">In bundle: [% INCLUDE 'biblio-title.inc' biblio = item.bundle_host.biblio link = 1 %]</div>
567
                        [% END %]
568
569
                    </td>
570
                    <td class="datelastseen" data-order="[% item.datelastseen | html %]">[% item.datelastseen | $KohaDates with_hours => 1 %]</td>
571
                    <td class="issues" data-order="[% item.issues || 0 | html %]">[% item.issues || 0 | html %]</td>
572
                    <td class="renewals" data-order="[% item.renewals || 0 | html %]">[% item.renewals || 0 | html %]</td>
573
                    <td class="dateaccessioned" data-order="[% item.dateaccessioned | html %]">[% item.dateaccessioned | $KohaDates %]</td>
574
                    <td class="datelastborrowed" data-order="[% item.datelastborrowed | html %]">[% item.datelastborrowed | $KohaDates %]</td>
575
                    <td><a href="/cgi-bin/koha/catalogue/moredetail.pl?itemnumber=[% item.itemnumber | uri %]&amp;biblionumber=[% item.biblionumber | uri %]&amp;bi=[% item.biblioitemnumber | uri %]#item[% item.itemnumber | uri %]">[% item.barcode | html %]</a></td>
576
                    [% IF ( itemdata_uri ) %]
577
                        [% IF item.uri.split(' \| ').size > 1 %]
578
                            <td class="uri">
579
                                [% FOREACH uri IN item.uri.split(' \| ') %]<a href="[% uri | url %]">[% uri | html %]</a><br>[% END %]
580
                            </td>
581
                        [% ELSE %]
582
                            <td class="uri">
583
                                [% IF item.uri %]
584
                                    <a href="[% item.uri | url %]">[% IF Koha.Preference('URLLinkText') %][% Koha.Preference('URLLinkText') | html %][% ELSE %]Link to resource[% END %]</a>
585
                                [% END %]
586
                            </td>
587
                        [% END %]
588
                    [% END %]
589
                    [% IF ( itemdata_copynumber ) %]
590
                        <td class="copynumber">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.copynumber', authorised_value => item.copynumber ) | html %]</td>
591
                    [% END %]
592
                    [% IF ( itemdata_stocknumber ) %]
593
                        <td class="stocknumber">[% item.stocknumber | html %]</td>
594
                    [% END %]
595
                    [% IF materials %]
596
                        <td class="materials"> [% item.materials | html %] </td>
597
                    [% END %]
598
                    [% IF ( itemdata_itemnotes ) %]
599
                        <td><div class="itemnotes">[% item.object.itemnotes.replace('\n','<br />') | $raw %]</div></td>
600
                    [% END %]
601
                    [% IF itemdata_nonpublicnotes %]
602
                        <td class="nonpublicnote">[% item.itemnotes_nonpublic | html %]</td>
603
                    [% END %]
604
                    [% IF ( hostrecords ) %]
605
                        <td>[% IF ( item.hostbiblionumber) %]<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% item.hostbiblionumber | uri %]" >[% item.hosttitle | html %]</a>[% END %]</td>
606
                    [% END %]
607
                    [% IF ( analyze ) %]
608
                        <td>
609
                            [% IF ( item.countanalytics ) %]
610
                                <a href="/cgi-bin/koha/catalogue/search.pl?idx=hi&amp;q=[% item.itemnumber | uri %]">[% item.countanalytics | html %] analytics</a>
611
                            [% END %]
612
                        </td>
613
                    [% END %]
614
                    [% IF ( analyze ) %]
615
                        <td><a href="/cgi-bin/koha/cataloguing/addbiblio.pl?hostbiblionumber=[% item.biblionumber | uri %]&amp;hostitemnumber=[% item.itemnumber | uri %]">Create analytics</a></td>
616
                    [% END %]
617
618
                [% IF ShowCourseReserves %]
619
                    <td>
620
                        [% IF item.course_reserves %]
621
                            [% FOREACH r IN item.course_reserves %]
622
                                [% IF r.course.enabled == 'yes' %]
623
                                    <p>
624
                                      <a href="/cgi-bin/koha/course_reserves/course-details.pl?course_id=[% r.course.course_id | uri %]">
625
                                         [% r.course.course_name | html %]
626
                                         <!--[% IF r.course.course_number %] [% r.course.course_number | html %] [% END %]-->
627
                                         [% IF r.course.section %] [% r.course.section | html %] [% END %]
628
                                         [% IF r.course.term %] [% AuthorisedValues.GetByCode( 'TERM', r.course.term ) | html %] [% END %]
629
                                      </a>
630
                                   </p>
631
                               [% END %]
632
                           [% END %]
633
                       [% END %]
634
                    </td>
635
                [% END %]
636
637
                [% IF ( SpineLabelShowPrintOnBibDetails ) %]
638
                    <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>
639
                [% END %]
640
641
                [% IF CAN_user_editcatalogue_edit_items %]
642
                    <td class="actions">
643
                        [% IF item.can_be_edited %]
644
                            [% IF Koha.Preference('LocalCoverImages') OR Koha.Preference('OPACLocalCoverImages') %]
645
                                <div class="btn-group">
646
                                    <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>
647
                                    <ul class="dropdown-menu pull-right">
648
                                        <li><a href="/cgi-bin/koha/tools/upload-cover-image.pl?itemnumber=[% item.itemnumber | uri %]&amp;filetype=image"><i class="fa fa-upload"></i> Upload image</a></li>
649
                                    </ul>
650
                                </div>
651
                            [% ELSE %]
652
                                <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>
653
                            [% END %]
654
                        [% END %]
655
                        [% IF bundlesEnabled %]
656
                            <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>
657
                        [% END %]
658
                    </td>
659
                [% END %]
660
                </tr>
661
            [% END %]
662
        </tbody>
663
    </table>
387
    </table>
664
665
[% END %][%# end of block items_table %]
388
[% END %][%# end of block items_table %]
666
389
667
[% IF Koha.Preference('EnableItemGroups') %]
390
[% IF Koha.Preference('EnableItemGroups') %]
Lines 693-743 Link Here
693
    </span>
416
    </span>
694
[% END %]
417
[% END %]
695
418
696
[% IF ( count ) %]
419
[% SET hidden_count = all_items_count - items_to_display_count %]
697
    [% IF ( showncount ) %]
420
[% IF all_items_count %]
698
        [%# PROCESS items_table tab="holdings" items=itemloop %]
421
    [% PROCESS items_table tab="holdings" %]
699
700
        [% SET tab="holdings" %]
701
        <table id="table_items">
702
            <thead>
703
                [% IF (StaffDetailItemSelection) %]<th id="[% tab | html %]_checkbox" data-colname="[% tab | html %]_checkbox" class="NoSort"></th>[% END %]
704
                [% IF Koha.Preference('LocalCoverImages') %]
705
                    <th id="[% tab | html %]_cover_image" data-colname="[% tab | html %]_cover_image">Cover image</th>
706
                [% END %]
707
                [% IF ( item_level_itypes ) %]<th id="[% tab | html %]_itype" data-colname="[% tab | html %]_itype">Item type</th>[% END %]
708
                <th id="[% tab | html %]_holdingbranch" data-colname="[% tab | html %]_holdingbranch">Current library</th>
709
                <th id="[% tab | html %]_homebranch" data-colname="[% tab | html %]_homebranch">Home library</th>
710
                <th id="[% tab | html %]_ccode" data-colname="[% tab | html %]_ccode">Collection</th>
711
                [% IF Koha.Preference('EnableItemGroups') %]
712
                    <th id="[% tab | html %]_item_group" data-colname="[% tab | html %]_item_group">Item group</th>
713
                [% END %]
714
                <th id="[% tab | html %]_itemcallnumber" data-colname="[% tab | html %]_itemcallnumber">Call number</th>
715
                <th id="[% tab | html %]_enumchron" data-colname="[% tab | html %]_enumchron">Serial enumeration / chronology</th>
716
                <th id="[% tab | html %]_status" data-colname="[% tab | html %]_status">Status</th>
717
                <th id="[% tab | html %]_lastseen" data-colname="[% tab | html %]_lastseen">Last seen</th>
718
                <th id="[% tab | html %]_issues" data-colname="[% tab | html %]_issues">Checkouts</th>
719
                <th id="[% tab | html %]_renewals" data-colname="[% tab | html %]_renewals">Renewals</th>
720
                <th id="[% tab | html %]_dateaccessioned" data-colname="[% tab | html %]_dateaccessioned">Date accessioned</th>
721
                <th id="[% tab | html %]_datelastborrowed" data-colname="[% tab | html %]_datelastborrowed">Date last borrowed</th>
722
                <th id="[% tab | html %]_barcode" data-colname="[% tab | html %]_barcode">Barcode</th>
723
                <th id="[% tab | html %]_uri" data-colname="[% tab | html %]_uri">URL</th>
724
                <th id="[% tab | html %]_copynumber" data-colname="[% tab | html %]_copynumber">Copy number</th>
725
                <th id="[% tab | html %]_stocknumber" data-colname="[% tab | html %]_stocknumber">Inventory number</th>
726
                <th id="[% tab | html %]_materials" data-colname="[% tab | html %]_materials">Materials specified</th>
727
                <th id="[% tab | html %]_itemnotes" data-colname="[% tab | html %]_itemnotes">Public notes</th>
728
                <th id="[% tab | html %]_itemnotes_nonpublic" data-colname="[% tab | html %]_itemnotes_nonpublic">Non-public notes</th>
729
                [% IF ( hostrecords ) %]<th id="[% tab | html %]_hostrecord" data-colname="[% tab | html %]_hostrecord">Host records</th>[% END %]
730
                [% IF ( analyze ) %]<th id="[% tab | html %]_usedin" data-colname="[% tab | html %]_usedin">Used in</th><th></th>[% END %]
731
                [% IF ( ShowCourseReserves ) %]<th id="[% tab | html %]_course_reserves" data-colname="[% tab | html %]_course_reserves">Course reserves</th>[% END %]
732
                [% IF ( SpineLabelShowPrintOnBibDetails ) %]<th id="[% tab | html %]_spinelabel" data-colname="[% tab | html %]_spinelabel" class="NoSort">Spine label</th>[% END %]
733
                [% IF ( CAN_user_editcatalogue_edit_items ) %]<th id="[% tab | html %]_actions" data-colname="[% tab | html %]_actions"class="NoSort noExport">&nbsp;</th>[% END %]
734
                </tr>
735
            </thead>
736
        </table>
737
    [% END %]
738
422
739
    [% IF ( hiddencount ) %]
423
    [% IF hidden_count %]
740
       <p><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblionumber | uri %]&amp;showallitems=1">Show all items ([% hiddencount | html %] hidden)</a>
424
        [%# FIXME We could deal with that in JS and prevent a full refresh %]
425
        <p><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblionumber | uri %]&amp;showallitems=1">Show all items ([% hidden_count | html %] hidden)</a>
741
    [% END %]
426
    [% END %]
742
[% ELSE %]
427
[% ELSE %]
743
    [% IF ( ALTERNATEHOLDINGS ) %]
428
    [% IF ( ALTERNATEHOLDINGS ) %]
Lines 757-769 Link Here
757
[% END %]
442
[% END %]
758
    </div>
443
    </div>
759
444
760
[% IF (SeparateHoldings) %]
445
[% IF Koha.Preference('SeparateHoldings') %]
761
    <div role="tabpanel" class="tab-pane" id="otherholdings">
446
    <div role="tabpanel" class="tab-pane" id="otherholdings">
762
        [% IF (otheritemloop.size) %]
447
        [% PROCESS items_table tab="otherholdings" %]
763
            [% PROCESS items_table tab="otherholdings" items=otheritemloop %]
764
        [% ELSE %]
765
            <span class="nootheritems">No other items.</span>
766
        [% END %]
767
    </div>
448
    </div>
768
[% END %]
449
[% END %]
769
450
Lines 2171-2191 Link Here
2171
            // End bundle handling
1852
            // End bundle handling
2172
            [% END %]
1853
            [% END %]
2173
1854
2174
            var table_names = [ 'holdings_table', 'otherholdings_table' ];
1855
            var table_ids = [ 'holdings_table', 'otherholdings_table' ];
2175
            var table_settings = [ [% TablesSettings.GetTableSettings('catalogue', 'detail','holdings_table','json') | $raw %], [% TablesSettings.GetTableSettings('catalogue', 'detail','otherholdings_table','json')  | $raw %] ];
1856
            var table_settings = [ [% TablesSettings.GetTableSettings('catalogue', 'detail','holdings_table','json') | $raw %], [% TablesSettings.GetTableSettings('catalogue', 'detail','otherholdings_table','json')  | $raw %] ];
2176
            var has_images = [ "[% itemloop_has_images | html %]", "[% otheritemloop_has_images | html %]" ];
1857
            table_ids.forEach( function( table_id, index ) {
2177
            table_names.forEach( function( table_name, index ) {
1858
                let filters = {};
2178
                if ( !has_images[index] ) {
1859
                [% IF Koha.Preference('SeparateHoldings') %]
2179
                    table_settings[index].columns.splice(1,1);
1860
                    [% SET SeparateHoldingsBranch = Koha.Preference('SeparateHoldingsBranch') || 'homebranch' %];
2180
                }
1861
                    let branch = '[% IF SeparateHoldingsBranch == 'homebranch' %]home_library_id[% ELSE %]holding_library_id[% END %]';
2181
                var dt_parameters = {
1862
                    if ( table_id == 'holdings_table' ) {
2182
                    "dom": 't',
1863
                        filters[branch] = '[% Branches.GetLoggedInBranchcode() | html %]';
2183
                    "paginate": false,
1864
                    } else {
2184
                    "autoWidth": false,
1865
                        filters[branch] = { '!=': '[% Branches.GetLoggedInBranchcode() | html  %]' };
2185
                    "bKohaColumnsUseNames": true,
1866
                    }
2186
                    "dom": 'C<"top pager"ilpfB><"#filter_c">tr<"bottom pager"ip>',
1867
                [% END %]
2187
                };
1868
2188
                var table = KohaTable( table_name, dt_parameters, table_settings[index], 'with_filters' );
1869
                var table = build_table(table_id, table_settings[index], filters);
2189
1870
2190
                [% IF bundlesEnabled %]
1871
                [% IF bundlesEnabled %]
2191
                // Add event listener for opening and closing bundle details
1872
                // Add event listener for opening and closing bundle details
Lines 2498-2504 Link Here
2498
        [% ELSE %]
2179
        [% ELSE %]
2499
            const url_link_text = _("Link to resource");
2180
            const url_link_text = _("Link to resource");
2500
        [% END %]
2181
        [% END %]
2501
        let table_url = "/api/v1/biblios/[% biblio.biblionumber | uri %]/items?";
2182
        [%# FIXME The X-Base-Total-Count will be the number of items of the biblios %]
2183
        [%# In case or SeparateHoldings we may need to display the number of biblios in each tab %]
2184
        [%# Do we need separate/new endpoints or do we hack the somewhere client-side? %]
2185
        let item_table_url = "/api/v1/biblios/[% biblio.biblionumber | uri %]/items?";
2502
        let embed = ["+strings,checkout,checkout.patron,transfer,first_hold,first_hold.patron,item_type"];
2186
        let embed = ["+strings,checkout,checkout.patron,transfer,first_hold,first_hold.patron,item_type"];
2503
        [% IF Koha.Preference('LocalCoverImages') %]
2187
        [% IF Koha.Preference('LocalCoverImages') %]
2504
            embed.push('cover_image_ids');
2188
            embed.push('cover_image_ids');
Lines 2513-2981 Link Here
2513
            embed.push('recall', 'recall.patron')
2197
            embed.push('recall', 'recall.patron')
2514
        [% END %]
2198
        [% END %]
2515
        embed.push('in_bundle', 'bundle_host');
2199
        embed.push('in_bundle', 'bundle_host');
2516
        let table_settings = [% TablesSettings.GetTableSettings('catalogue', 'detail','holdings_table','json') | $raw %];
2200
2517
        var items_table = $("#table_items").kohaTable({
2201
        function build_table (table_id, table_settings, filters) {
2518
            ajax: { url: table_url },
2202
            [% IF hidden_count %]
2519
            order: [[ 0, "asc" ]],
2203
                filters.lost_status = "0";
2520
            embed,
2521
            bAutoWidth: false,
2522
            bKohaColumnsUseNames: true, // FIXME We should not need that now, do we?
2523
            columns: [
2524
            [% IF (StaffDetailItemSelection) %]
2525
            {
2526
                data: "me.item_id",
2527
                searchable: false,
2528
                orderable: false,
2529
                render: function (data, type, row, meta) {
2530
                    if ( can_edit_items_from[row.holding_library_id] ){
2531
                        return '<input type="checkbox" value="%s" name="itemnumber" />'.format(row.item_id);
2532
                    } else {
2533
                        return ''
2534
                    }
2535
                }
2536
            },
2537
            [% END %]
2204
            [% END %]
2538
            [% IF Koha.Preference('LocalCoverImages') %]
2205
            var items_table = $("#" + table_id).kohaTable({
2539
            {
2206
                ajax: { url: item_table_url },
2540
                data: "",
2207
                order: [[ 0, "asc" ]],
2541
                className: "cover",
2208
                embed,
2542
                searchable: false,
2209
                autoWidth: false,
2543
                orderable: false,
2210
                bKohaColumnsUseNames: true, // FIXME We should not need that now, do we?
2544
                render: function (data, type, row, meta) {
2211
                columns: [
2545
                    if ( !row.cover_image_ids.length > 0 ) {
2212
                [% IF (StaffDetailItemSelection) %]
2546
                        return '';
2213
                {
2214
                    data: "me.item_id",
2215
                    searchable: false,
2216
                    orderable: false,
2217
                    render: function (data, type, row, meta) {
2218
                        if ( can_edit_items_from[row.holding_library_id] ){
2219
                            return '<input type="checkbox" value="%s" name="itemnumber" />'.format(row.item_id);
2220
                        } else {
2221
                            return ''
2222
                        }
2547
                    }
2223
                    }
2548
                    let node = '<div class="bookcoverimg">';
2224
                },
2549
                    node += '<div class="cover-slider">';
2225
                [% END %]
2550
                    row.cover_image_ids.forEach(id => {
2226
                [% IF Koha.Preference('LocalCoverImages') %]
2551
                        node += '<div class="cover-image local-coverimg">';
2227
                {
2552
                        node += '<a href="/cgi-bin/koha/catalogue/image.pl?itemnumber=%s&amp;imagenumber=%s" title="Local cover image">'.format(id, id);
2228
                    data: "",
2553
                        node += '<img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&amp;imagenumber=%s" alt="Local cover image" data-link="/cgi-bin/koha/catalogue/imageviewer.pl?itemnumber=[% item.itemnumber | uri %]&amp;imagenumber=%s" />'.format(id, id);
2229
                    className: "cover",
2554
                        node += '</a>';
2230
                    searchable: false,
2231
                    orderable: false,
2232
                    render: function (data, type, row, meta) {
2233
                        if ( !row.cover_image_ids.length > 0 ) {
2234
                            return '';
2235
                        }
2236
                        let node = '<div class="bookcoverimg">';
2237
                        node += '<div class="cover-slider">';
2238
                        row.cover_image_ids.forEach(id => {
2239
                            node += '<div class="cover-image local-coverimg">';
2240
                            node += '<a href="/cgi-bin/koha/catalogue/image.pl?itemnumber=%s&amp;imagenumber=%s" title="Local cover image">'.format(id, id);
2241
                            node += '<img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&amp;imagenumber=%s" alt="Local cover image" data-link="/cgi-bin/koha/catalogue/imageviewer.pl?itemnumber=[% item.itemnumber | uri %]&amp;imagenumber=%s" />'.format(id, id);
2242
                            node += '</a>';
2243
                            node += '</div>';
2244
                        });
2555
                        node += '</div>';
2245
                        node += '</div>';
2556
                    });
2246
                        node += '</div>';
2557
                    node += '</div>';
2247
                        return node;
2558
                    node += '</div>';
2559
                    return node;
2560
                }
2561
            },
2562
            [% END %]
2563
            [% IF ( item_level_itypes ) %]
2564
            {
2565
                data: "me.itype:biblioitem.itemtype",
2566
                className: "itype",
2567
                searchable: true,
2568
                orderable: true,
2569
                render: function (data, type, row, meta) {
2570
                    let node = '';
2571
                    [% UNLESS noItemTypeImages %]
2572
                        let image_location = item_type_image_locations[row.item_type_id];
2573
                        let item_type_description = row._strings.item_type_id.str;
2574
                        node += image_location
2575
                            ? '<img src="%s" alt="%s" title="%s" /> '.format(image_location, item_type_description, item_type_description)
2576
                            : '';
2577
                    [% END %]
2578
                    node += '<span class="itypedesc itypetext">%s</span>'.format(item_type_description);
2579
                    return node;
2580
                }
2581
            },
2582
            [% END %]
2583
            {
2584
                data: "me.holding_library_id",
2585
                className: "location",
2586
                searchable: true,
2587
                orderable: true,
2588
                render: function (data, type, row, meta) {
2589
                    return row._strings.holding_library_id.str;
2590
                }
2591
            },
2592
            {
2593
                data: "me.home_library_id",
2594
                className: "homebranch",
2595
                searchable: true,
2596
                orderable: true,
2597
                render: function (data, type, row, meta) {
2598
                    let nodes = '<span class="homebranchdesc">%s</span>'.format(row._strings.home_library_id.str);
2599
                    nodes += '<span class="shelvingloc">'
2600
                    [%# If permanent location is defined, show description or code and
2601
                        display current location in parentheses. If not, display current location.
2602
                        Note that permanent location is a code, and location may be an authval.
2603
                    %]
2604
2605
                    let loc_str = row._strings.location.str;
2606
                    if ( row.permanent_location && row.permanent_location != row.location ) {
2607
                        let permanent_loc_str = av_loc[row.permanent_location];
2608
                        nodes += '%s (%s)'.format(permanent_loc_str, loc_str);
2609
                    } else {
2610
                        nodes += loc_str;
2611
                    }
2248
                    }
2612
                    nodes += '</span>';
2249
                },
2613
                    return nodes;
2250
                [% END %]
2614
                }
2251
                [% IF ( item_level_itypes ) %]
2615
            },
2252
                {
2616
            {
2253
                    data: "me.itype:biblioitem.itemtype",
2617
                data: "me.collection_code",
2254
                    className: "itype",
2618
                searchable: true,
2255
                    searchable: true,
2619
                orderable: true,
2256
                    orderable: true,
2620
                render: function (data, type, row, meta) {
2257
                    render: function (data, type, row, meta) {
2621
                    return row._strings.collection_code.str;
2258
                        let node = '';
2622
                }
2259
                        [% UNLESS noItemTypeImages %]
2623
            },
2260
                            let image_location = item_type_image_locations[row.item_type_id];
2624
            [% IF Koha.Preference('EnableItemGroups') %]
2261
                            let item_type_description = row._strings.item_type_id.str;
2625
            {
2262
                            node += image_location
2626
                data: "item_group_item.item_group.description",
2263
                                ? '<img src="%s" alt="%s" title="%s" /> '.format(image_location, item_type_description, item_type_description)
2627
                className: "item_group",
2264
                                : '';
2628
                searchable: true,
2265
                        [% END %]
2629
                orderable: true,
2266
                        node += '<span class="itypedesc itypetext">%s</span>'.format(item_type_description);
2630
                render: function (data, type, row, meta) {
2267
                        return node;
2631
                    if ( row.item_group_item ) {
2632
                        return row.item_group_item.item_group.description;
2633
                    } else {
2634
                        return "";
2635
                    }
2268
                    }
2636
                }
2269
                },
2637
            },
2270
                [% END %]
2638
            [% END %]
2271
                {
2639
            {
2272
                    data: "me.holding_library_id",
2640
                data: "me.callnumber",
2273
                    className: "location",
2641
                className: "itemcallnumber",
2274
                    searchable: true,
2642
                searchable: true,
2275
                    orderable: true,
2643
                orderable: true,
2276
                    render: function (data, type, row, meta) {
2644
                render: function (data, type, row, meta) {
2277
                        return row._strings.holding_library_id.str;
2645
                    return row.callnumber;
2278
                    }
2646
                }
2279
                },
2647
2280
                {
2648
            },
2281
                    data: "me.home_library_id",
2649
            {
2282
                    className: "homebranch",
2650
                data: "me.serial_issue_number",
2283
                    searchable: true,
2651
                className: "enumchron",
2284
                    orderable: true,
2652
                searchable: true,
2285
                    render: function (data, type, row, meta) {
2653
                orderable: true,
2286
                        let nodes = '<span class="homebranchdesc">%s</span>'.format(row._strings.home_library_id.str);
2654
                render: function (data, type, row, meta) {
2287
                        nodes += '<span class="shelvingloc">'
2655
                    let nodes = "";
2288
                        [%# If permanent location is defined, show description or code and             %]
2656
                    [%# 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? %]
2289
                        [%# display current location in parentheses. If not, display current location. %]
2657
                    let serial = row.serialitem ? row.serialitem.serial : null;
2290
                        [%# Note that permanent location is a code, and location may be an authval.    %]
2658
                    if ( row.serial_issue_number && serial && serial.serialseq ) {
2291
                        let loc_str = row._strings.location.str;
2659
                        nodes += '<span class="enum">%s</span>'.format(row.serial_issue_number);
2292
                        if ( row.permanent_location && row.permanent_location != row.location ) {
2660
                        if ( serial.serialseq && row.serial_issue_number != serial.serialseq ) {
2293
                            let permanent_loc_str = av_loc[row.permanent_location];
2661
                            nodes += ' <span class="sep"> -- </span>'
2294
                            nodes += '%s (%s)'.format(permanent_loc_str, loc_str);
2662
                            nodes += ' <span class="serialseq">%s</span>'.format(serial.serialseq);
2295
                        } else {
2296
                            nodes += loc_str;
2663
                        }
2297
                        }
2664
                    } else if ( row.serial_issue_number ) {
2298
                        nodes += '</span>';
2665
                        nodes += ' <span class="enum">%s</span>'.format(row.serial_issue_number);
2299
                        return nodes;
2666
                    } else if ( serial && serial.serialseq ) {
2667
                        nodes += '<span class="serialseq">%s</span>'.format(serial.serialseq);
2668
                    }
2300
                    }
2669
                    if ( serial && serial.publisheddate ) {
2301
                },
2670
                        nodes += ' <span class="pubdate">(%s)</span>'.format($date(serial.publisheddate));
2302
                {
2303
                    data: "me.collection_code",
2304
                    searchable: true,
2305
                    orderable: true,
2306
                    render: function (data, type, row, meta) {
2307
                        return row._strings.collection_code.str;
2671
                    }
2308
                    }
2672
                    return nodes;
2309
                },
2673
                }
2310
                [% IF Koha.Preference('EnableItemGroups') %]
2674
            },
2311
                {
2675
            {
2312
                    data: "item_group_item.item_group.description",
2676
                data: "me.lost_status",
2313
                    className: "item_group",
2677
                className: "status",
2314
                    searchable: true,
2678
                searchable: false, // FIXME We are losing the ability to search on the status
2315
                    orderable: true,
2679
                orderable: false,
2316
                    render: function (data, type, row, meta) {
2680
                render: function (data, type, row, meta) {
2317
                        if ( row.item_group_item ) {
2681
                    let nodes = "";
2318
                            return row.item_group_item.item_group.description;
2682
                    if ( row.checkout ) {
2319
                        } else {
2683
                        nodes += '<span>';
2320
                            return "";
2684
                        if ( row.checkout.onsite_checkout ) {
2321
                        }
2685
                            if ( can_edit_items_from[row.holding_library_id] ){
2322
                    }
2323
                },
2324
                [% END %]
2325
                {
2326
                    data: "me.callnumber",
2327
                    className: "itemcallnumber",
2328
                    searchable: true,
2329
                    orderable: true,
2330
                    render: function (data, type, row, meta) {
2331
                        return row.callnumber;
2332
                    }
2333
2334
                },
2335
                {
2336
                    data: "me.serial_issue_number",
2337
                    className: "enumchron",
2338
                    searchable: true,
2339
                    orderable: true,
2340
                    render: function (data, type, row, meta) {
2341
                        let nodes = "";
2342
                        [%# 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? %]
2343
                        let serial = row.serialitem ? row.serialitem.serial : null;
2344
                        if ( row.serial_issue_number && serial && serial.serialseq ) {
2345
                            nodes += '<span class="enum">%s</span>'.format(row.serial_issue_number);
2346
                            if ( serial.serialseq && row.serial_issue_number != serial.serialseq ) {
2347
                                nodes += ' <span class="sep"> -- </span>'
2348
                                nodes += ' <span class="serialseq">%s</span>'.format(serial.serialseq);
2349
                            }
2350
                        } else if ( row.serial_issue_number ) {
2351
                            nodes += ' <span class="enum">%s</span>'.format(row.serial_issue_number);
2352
                        } else if ( serial && serial.serialseq ) {
2353
                            nodes += '<span class="serialseq">%s</span>'.format(serial.serialseq);
2354
                        }
2355
                        if ( serial && serial.publisheddate ) {
2356
                            nodes += ' <span class="pubdate">(%s)</span>'.format($date(serial.publisheddate));
2357
                        }
2358
                        return nodes;
2359
                    }
2360
                },
2361
                {
2362
                    data: "me.lost_status",
2363
                    className: "status",
2364
                    searchable: false, // FIXME We are losing the ability to search on the status
2365
                    orderable: false,
2366
                    render: function (data, type, row, meta) {
2367
                        let nodes = "";
2368
                        if ( row.checkout ) {
2369
                            nodes += '<span>';
2370
                            if ( row.checkout.onsite_checkout ) {
2686
                                let patron_to_html = $patron_to_html(row.checkout.patron); [%# FIXME What about hide_patron_infos_if_needed?? %]
2371
                                let patron_to_html = $patron_to_html(row.checkout.patron); [%# FIXME What about hide_patron_infos_if_needed?? %]
2687
                                nodes += _("Currently in local use by %s").format(patron_to_html);
2372
                                nodes += _("Currently in local use by %s").format(patron_to_html);
2688
                            } else {
2373
                            } else {
2689
                                nodes += _("Currently in local use");
2374
                                nodes += '<span class="datedue">';
2690
                            }
2691
                        } else {
2692
                            nodes += '<span class="datedue">';
2693
                            if ( can_edit_items_from[row.holding_library_id] ){
2694
                                let patron_to_html = $patron_to_html(row.checkout.patron); [%# FIXME What about hide_patron_infos_if_needed?? %]
2375
                                let patron_to_html = $patron_to_html(row.checkout.patron); [%# FIXME What about hide_patron_infos_if_needed?? %]
2695
                                nodes += _("Checked out to %s").format(patron_to_html);
2376
                                nodes += _("Checked out to %s").format(patron_to_html);
2377
                            }
2378
                            nodes += ': ';
2379
                            nodes += _("due %s").format($date(row.checkout.due_date)); [%# FIXME Missing due date formatting here, $date do not have as_due_date option %]
2380
                            nodes += "</span>"
2381
                        } else if ( row.transfer ) {
2382
                            if ( row.transfer.datesent ) {
2383
                                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? %]
2696
                            } else {
2384
                            } else {
2697
                                nodes += _("Checked out");
2385
                                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 %]
2698
                            }
2386
                            }
2699
                        }
2387
                        }
2700
                        nodes += ': ';
2388
2701
                        nodes += _("due %s").format($date(row.checkout.due_date)); [%# FIXME Missing due date formatting here, $date do not have as_due_date option %]
2389
                        if ( row.lost_status ) {
2702
                        nodes += "</span>"
2390
                            let lost_lib = av_lost.get(row.lost_status.toString()) || _("Unavailable (lost or missing");
2703
                    } else if ( row.transfer ) {
2391
                            nodes += '<span class="lost">%s</span>'.format(lost_lib);
2704
                        if ( row.transfer.datesent ) {
2705
                            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? %]
2706
                        } else {
2707
                            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 %]
2708
                        }
2392
                        }
2709
                    }
2710
2393
2711
                    if ( row.lost_status ) {
2394
                        if ( row.withdrawn ) {
2712
                        let lost_lib = av_lost.get(row.lost_status.toString()) || _("Unavailable (lost or missing");
2395
                            let withdrawn_lib = av_withdrawn.get(row.withdrawn.toString()) || _("Withdrawn");
2713
                        nodes += '<span class="lost">%s</span>'.format(lost_lib);
2396
                            nodes += '<span class="wdn">%s</span>'.format(withdrawn_lib);
2714
                    }
2397
                        }
2715
2398
2716
                    if ( row.withdrawn ) {
2399
                        if ( row.damaged ) {
2717
                        let withdrawn_lib = av_withdrawn.get(row.withdrawn.toString()) || _("Withdrawn");
2400
                            let damaged_lib = av_damaged.get(row.damaged.toString()) || _("Damaged");
2718
                        nodes += '<span class="wdn">%s</span>'.format(withdrawn_lib);
2401
                            nodes += '<span class="dmg">%s</span>'.format(damaged_lib);
2719
                    }
2402
                        }
2720
2403
2721
                    if ( row.damaged ) {
2404
                        if ( row.not_for_loan_status || row.item_type.notforloan ) {
2722
                        let damaged_lib = av_damaged.get(row.damaged.toString()) || _("Damaged");
2405
                            let not_for_loan_lib = av_not_for_loan.get(row.not_for_loan_status.toString());
2723
                        nodes += '<span class="dmg">%s</span>'.format(damaged_lib);
2406
                            nodes += '<span class="notforloan">%s'.format(_("Not for loan")) + ( not_for_loan_lib ? '<span class="reason"> (%s)</span>'.format(not_for_loan_lib) : '' ) + '</span>';
2724
                    }
2407
                        }
2725
2408
2726
                    if ( row.not_for_loan_status || row.item_type.notforloan ) {
2409
                        if ( row.first_hold ) {
2727
                        let not_for_loan_lib = av_not_for_loan.get(row.not_for_loan_status.toString());
2410
                            if ( row.first_hold.waiting_date ) {
2728
                        nodes += '<span class="notforloan">%s'.format(_("Not for loan")) + ( not_for_loan_lib ? '<span class="reason"> (%s)</span>'.format(not_for_loan_lib) : '' ) + '</span>';
2411
                                [%# FIXME Display library names instead of codes %]
2729
                    }
2412
                                [%# FIXME We lost the desk name, we need an additional embed %]
2413
                                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))));
2414
                                [% IF Koha.Preference('canreservefromotherbranches') %]
2415
                                    if ( row.first_hold.waiting_date || row.first_hold.priority == 1 ) {
2416
                                        let patron_to_html = $patron_to_html(row.first_hold.patron); [%# FIXME What about hide_patron_infos_if_needed?? %]
2417
                                        nodes += ' <span class="heldfor">%s</span>'.format(_("Hold for: %s").format(patron_to_html));
2418
                                    }
2419
                                [% END %]
2420
                            } else {
2421
                                nodes += '<span class="holdonitem">%s</span>'.format(_("There is an item level hold on this item (priority = %s).").format(row.first_hold.priority));
2422
                            }
2423
                        }
2730
2424
2731
                    if ( row.first_hold ) {
2425
                        [% IF Koha.Preference('UseRecalls') %]
2732
                        if ( row.first_hold.waiting_date ) {
2426
                            if ( row.recall ) {
2733
                            [%# FIXME Display library names instead of codes %]
2427
                                if ( row.recall.waiting_date ) {
2734
                            [%# FIXME We lost the desk name, we need an additional embed %]
2428
                                    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
2735
                            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))));
2429
                                } else {
2736
                            [% IF Koha.Preference('canreservefromotherbranches') %]
2430
                                    let patron_to_html = $patron_to_html(row.recall.patron);
2737
                                if ( row.first_hold.waiting_date || row.first_hold.priority == 1 ) {
2431
                                    nodes += '<span>%s</span>'.format(_("recalled by %s on %s").format(patron_to_html, row.recall.created_date))
2738
                                    let patron_to_html = $patron_to_html(row.first_hold.patron); [%# FIXME What about hide_patron_infos_if_needed?? %]
2739
                                    nodes += ' <span class="heldfor">%s</span>'.format(_("Hold for: %s").format(patron_to_html));
2740
                                }
2432
                                }
2741
                            [% END %]
2433
                            }
2742
                        } else {
2434
                        [% END %]
2743
                            nodes += '<span class="holdonitem">%s</span>'.format(_("There is an item level hold on this item (priority = %s).").format(row.first_hold.priority));
2435
2436
                        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 ) ) {
2437
                            nodes += ' <span>%s</span>'.format(_("Available"))
2744
                        }
2438
                        }
2745
                    }
2746
2439
2747
                    [% IF Koha.Preference('UseRecalls') %]
2440
                        if ( row.restricted_status ) {
2748
                        if ( row.recall ) {
2441
                            nodes += '<span class="restricted">(%s)</span>'.format(av_restricted.get(row.restricted_status.toString()));
2749
                            if ( row.recall.waiting_date ) {
2750
                                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
2751
                            } else {
2752
                                let patron_to_html = $patron_to_html(row.recall.patron);
2753
                                nodes += '<span>%s</span>'.format(_("recalled by %s on %s").format(patron_to_html, row.recall.created_date));
2754
                            }
2755
                        }
2442
                        }
2756
                    [% END %]
2757
2443
2758
                    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 ) ) {
2444
                        if ( row.in_bundle ) {
2759
                        nodes += ' <span>%s</span>'.format(_("Available"))
2445
                            nodes += '<span class="bundled">%s</span>'.format(_("In bundle: %s").format($biblio_to_html(row.bundle_host.biblio, { link: true })));
2446
                        }
2447
                        return nodes;
2760
                    }
2448
                    }
2761
2449
                },
2762
                    if ( row.restricted_status ) {
2450
                {
2763
                        nodes += '<span class="restricted">(%s)</span>'.format(av_restricted.get(row.restricted_status.toString()));
2451
                    data: "me.last_seen_date",
2452
                    className: "datelastseen",
2453
                    searchable: true,
2454
                    orderable: true,
2455
                    render: function (data, type, row, meta) {
2456
                        return $date(row.last_seen_date);
2764
                    }
2457
                    }
2765
2458
                },
2766
                    if ( row.in_bundle ) {
2459
                {
2767
                        nodes += '<span class="bundled">%s</span>'.format(_("In bundle: %s").format($biblio_to_html(row.bundle_host.biblio, { link: true })));
2460
                    data: "me.checkouts_count",
2461
                    className: "issues",
2462
                    searchable: true,
2463
                    orderable: true,
2464
                    render: function (data, type, row, meta) {
2465
                        return row.checkouts_count || 0;
2768
                    }
2466
                    }
2769
                    return nodes;
2467
                },
2770
                }
2468
                {
2771
            },
2469
                    data: "me.renewals_count",
2772
            {
2470
                    className: "renewals",
2773
                data: "me.last_seen_date",
2471
                    searchable: true,
2774
                className: "datelastseen",
2472
                    orderable: true,
2775
                searchable: true,
2473
                    render: function (data, type, row, meta) {
2776
                orderable: true,
2474
                        return row.renewals_count || 0;
2777
                render: function (data, type, row, meta) {
2778
                    return $date(row.last_seen_date);
2779
                }
2780
            },
2781
            {
2782
                data: "me.checkouts_count",
2783
                className: "issues",
2784
                searchable: true,
2785
                orderable: true,
2786
                render: function (data, type, row, meta) {
2787
                    return row.checkouts_count || 0;
2788
                }
2789
            },
2790
            {
2791
                data: "me.renewals_count",
2792
                className: "renewals",
2793
                searchable: true,
2794
                orderable: true,
2795
                render: function (data, type, row, meta) {
2796
                    return row.renewals_count || 0;
2797
                }
2798
            },
2799
            {
2800
                data: "me.acquisition_date",
2801
                className: "dateaccessioned",
2802
                searchable: true,
2803
                orderable: true,
2804
                render: function (data, type, row, meta) {
2805
                    return $date(row.acquisition_date);
2806
                }
2807
            },
2808
            {
2809
                data: "me.last_checkout_date",
2810
                className: "datelastborrowed",
2811
                searchable: true,
2812
                orderable: true,
2813
                render: function (data, type, row, meta) {
2814
                    return $date(row.last_checkout_date);
2815
                }
2816
            },
2817
            {
2818
                data: "me.external_id",
2819
                className: "",
2820
                searchable: true,
2821
                orderable: true,
2822
                render: function (data, type, row, meta) {
2823
                    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);
2824
                }
2825
            },
2826
            {
2827
                data: "me.uri",
2828
                className: "uri",
2829
                searchable: true,
2830
                orderable: true,
2831
                render: function (data, type, row, meta) {
2832
                    if ( !row.uri ) return "";
2833
2834
                    let nodes = '';
2835
                    if ( row.uri.split(' \| ').length > 1 ) {
2836
                        row.uri.split(' \| ').forEach((uri, i) => {
2837
                            nodes += '<a href="%s">%s</a><br/>'.format(uri, uri);
2838
                        });
2839
                    } else {
2840
                        nodes += '<a href="%s">%s</a><br/>'.format(row.uri, url_link_text);
2841
                    }
2475
                    }
2842
                    return nodes;
2476
                },
2843
                }
2477
                {
2844
            },
2478
                    data: "me.acquisition_date",
2845
            {
2479
                    className: "dateaccessioned",
2846
                data: "me.copy_number",
2480
                    searchable: true,
2847
                className: "copynumber",
2481
                    orderable: true,
2848
                searchable: true,
2482
                    render: function (data, type, row, meta) {
2849
                orderable: true,
2483
                        return $date(row.acquisition_date);
2850
                render: function (data, type, row, meta) {
2851
                    return row._strings.copy_number ? row._strings.copy_number.str : row.copy_number;
2852
                }
2853
            },
2854
            {
2855
                data: "me.inventory_number",
2856
                className: "stocknumber",
2857
                searchable: true,
2858
                orderable: true,
2859
                render: function (data, type, row, meta) {
2860
                    return row.inventory_number;
2861
                }
2862
            },
2863
            {
2864
                data: "me.materials_notes",
2865
                className: "materials",
2866
                searchable: true,
2867
                orderable: true,
2868
                render: function (data, type, row, meta) {
2869
                    return row.materials_notes;
2870
                }
2871
            },
2872
            {
2873
                data: "me.public_notes",
2874
                className: "itemnotes",
2875
                searchable: true,
2876
                orderable: true,
2877
                render: function (data, type, row, meta) {
2878
                    return row.public_notes ? row.public_notes.replaceAll('\n', '<br />') : '';
2879
                }
2880
            },
2881
            {
2882
                data: "me.internal_notes",
2883
                className: "nonpublicnote",
2884
                searchable: true,
2885
                orderable: true,
2886
                render: function (data, type, row, meta) {
2887
                    return row.internal_notes;
2888
                }
2889
            },
2890
            [% IF ( hostrecords ) %]
2891
            {
2892
                data: "biblio.biblio_id",
2893
                searchable: false, // FIXME
2894
                orderable: true,
2895
                render: function (data, type, row, meta) {
2896
                    if ( row.biblio_id == [% biblio.biblionumber %] ) return "";
2897
                    return '<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=%s>%s</a>'.format(row.biblio_id, row.biblio.title);
2898
                }
2899
            },
2900
            [% END %]
2901
            [% IF ( analyze ) %]
2902
            {
2903
                data: "",
2904
                searchable: false, // FIXME
2905
                orderable: true,
2906
                render: function (data, type, row, meta) {
2907
                    return ""; // FIXME Display analytic count + link
2908
                }
2909
            },
2910
            [% END %]
2911
            [% IF ( ShowCourseReserves ) %]
2912
            {
2913
                data: "",
2914
                searchable: false, // FIXME
2915
                orderable: true,
2916
                render: function (data, type, row, meta) {
2917
                    return ""; // FIXME Display course reserves
2918
                }
2919
            },
2920
            [% END %]
2921
            [% IF ( SpineLabelShowPrintOnBibDetails ) %]
2922
            {
2923
                data: "",
2924
                searchable: false,
2925
                orderable: false,
2926
                render: function (data, type, row, meta) {
2927
                    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);
2928
                }
2929
            },
2930
            [% END %]
2931
            [% IF CAN_user_editcatalogue_edit_items %]
2932
            {
2933
                data: function( row, type, val, meta ) {
2934
                    let nodes = '';
2935
                    if ( can_edit_items_from[row.holding_library_id] ){
2936
                        [% IF Koha.Preference('LocalCoverImages') OR Koha.Preference('OPACLocalCoverImages') %]
2937
                            nodes += '<div class="btn-group">';
2938
                            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);
2939
                            nodes += ' <ul class="dropdown-menu pull-right">';
2940
                            nodes += '  <li><a href="/cgi-bin/koha/tools/upload-cover-image.pl?itemnumber=%s&amp;filetype=image"><i class="fa fa-upload"></i> Upload image</a></li>'.format(row.item_id);
2941
                            nodes += ' </ul>';
2942
                            nodes += '</div>';
2943
                        [% ELSE %]
2944
                            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);
2945
                        [% END %]
2946
                    }
2484
                    }
2947
                    [% IF bundlesEnabled %]
2948
                        // FIXME How do we handle that correctly?
2949
                        //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);
2950
                    [% END %]
2951
2952
                    return nodes;
2953
                },
2485
                },
2954
                className: "actions",
2486
                {
2955
                searchable: false,
2487
                    data: "me.last_checkout_date",
2956
                orderable: false
2488
                    className: "datelastborrowed",
2957
            }
2489
                    searchable: true,
2958
            [% END %]
2490
                    orderable: true,
2959
            ],
2491
                    render: function (data, type, row, meta) {
2960
            initComplete: function( settings, json ){
2492
                        return $date(row.last_checkout_date);
2961
                let table = settings.oInstance.api();
2493
                    }
2962
                table.columns().every(function(i){
2494
                },
2963
                    let is_empty = true;
2495
                {
2964
                    let nodes = this.nodes();
2496
                    data: "me.external_id",
2965
                    nodes.each((td, ii) => {
2497
                    className: "",
2966
                        if ( $(td).html() !== '' ) {
2498
                    searchable: true,
2967
                            is_empty = false;
2499
                    orderable: true,
2968
                            return;
2500
                    render: function (data, type, row, meta) {
2501
                        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);
2502
                    }
2503
                },
2504
                {
2505
                    data: "me.uri",
2506
                    className: "uri",
2507
                    searchable: true,
2508
                    orderable: true,
2509
                    render: function (data, type, row, meta) {
2510
                        if ( !row.uri ) return "";
2511
2512
                        let nodes = '';
2513
                        if ( row.uri.split(' \| ').length > 1 ) {
2514
                            row.uri.split(' \| ').forEach((uri, i) => {
2515
                                nodes += '<a href="%s">%s</a><br/>'.format(uri, uri);
2516
                            });
2517
                        } else {
2518
                            nodes += '<a href="%s">%s</a><br/>'.format(row.uri, url_link_text);
2969
                        }
2519
                        }
2970
                    });
2520
                        return nodes;
2971
                    if ( is_empty ) {
2972
                        table.columns(i).visible(false);
2973
                    }
2521
                    }
2974
                });
2522
                },
2523
                {
2524
                    data: "me.copy_number",
2525
                    className: "copynumber",
2526
                    searchable: true,
2527
                    orderable: true,
2528
                    render: function (data, type, row, meta) {
2529
                        return row._strings.copy_number ? row._strings.copy_number.str : row.copy_number;
2530
                    }
2531
                },
2532
                {
2533
                    data: "me.inventory_number",
2534
                    className: "stocknumber",
2535
                    searchable: true,
2536
                    orderable: true,
2537
                    render: function (data, type, row, meta) {
2538
                        return row.inventory_number;
2539
                    }
2540
                },
2541
                {
2542
                    data: "me.materials_notes",
2543
                    className: "materials",
2544
                    searchable: true,
2545
                    orderable: true,
2546
                    render: function (data, type, row, meta) {
2547
                        return row.materials_notes;
2548
                    }
2549
                },
2550
                {
2551
                    data: "me.public_notes",
2552
                    className: "itemnotes",
2553
                    searchable: true,
2554
                    orderable: true,
2555
                    render: function (data, type, row, meta) {
2556
                        return row.public_notes ? row.public_notes.replaceAll('\n', '<br />') : '';
2557
                    }
2558
                },
2559
                {
2560
                    data: "me.internal_notes",
2561
                    className: "nonpublicnote",
2562
                    searchable: true,
2563
                    orderable: true,
2564
                    render: function (data, type, row, meta) {
2565
                        return row.internal_notes;
2566
                    }
2567
                },
2568
                [% IF ( hostrecords ) %]
2569
                {
2570
                    data: "biblio.biblio_id",
2571
                    searchable: false, // FIXME
2572
                    orderable: true,
2573
                    render: function (data, type, row, meta) {
2574
                        if ( row.biblio_id == [% biblio.biblionumber | html %] ) return "";
2575
                        return '<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=%s>%s</a>'.format(row.biblio_id, row.biblio.title);
2576
                    }
2577
                },
2578
                [% END %]
2579
                [% IF ( analyze ) %]
2580
                {
2581
                    data: "",
2582
                    searchable: false, // FIXME
2583
                    orderable: true,
2584
                    render: function (data, type, row, meta) {
2585
                        return ""; // FIXME Display analytic count + link
2586
                    }
2587
                },
2588
                [% END %]
2589
                [% IF ( ShowCourseReserves ) %]
2590
                {
2591
                    data: "",
2592
                    searchable: false, // FIXME
2593
                    orderable: true,
2594
                    render: function (data, type, row, meta) {
2595
                        return ""; // FIXME Display course reserves
2596
                    }
2597
                },
2598
                [% END %]
2599
                [% IF ( SpineLabelShowPrintOnBibDetails ) %]
2600
                {
2601
                    data: "",
2602
                    searchable: false,
2603
                    orderable: false,
2604
                    render: function (data, type, row, meta) {
2605
                        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);
2606
                    }
2607
                },
2608
                [% END %]
2609
                [% IF CAN_user_editcatalogue_edit_items %]
2610
                {
2611
                    data: function( row, type, val, meta ) {
2612
                        let nodes = '';
2613
                        if ( can_edit_items_from[row.holding_library_id] ){
2614
                            [% IF Koha.Preference('LocalCoverImages') OR Koha.Preference('OPACLocalCoverImages') %]
2615
                                nodes += '<div class="btn-group">';
2616
                                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);
2617
                                nodes += ' <ul class="dropdown-menu pull-right">';
2618
                                nodes += '  <li><a href="/cgi-bin/koha/tools/upload-cover-image.pl?itemnumber=%s&amp;filetype=image"><i class="fa fa-upload"></i> Upload image</a></li>'.format(row.item_id);
2619
                                nodes += ' </ul>';
2620
                                nodes += '</div>';
2621
                            [% ELSE %]
2622
                                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);
2623
                            [% END %]
2624
                        }
2625
                        [% IF bundlesEnabled %]
2626
                            // FIXME How do we handle that correctly?
2627
                            //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);
2628
                        [% END %]
2629
2630
                        return nodes;
2631
                    },
2632
                    className: "actions",
2633
                    searchable: false,
2634
                    orderable: false
2635
                }
2636
                [% END %]
2637
                ],
2638
                initComplete: function( settings, json ){
2639
                    let table = settings.oInstance.api();
2640
                    table.columns().every(function(i){
2641
                        let is_empty = true;
2642
                        let nodes = this.nodes();
2643
                        nodes.each((td, ii) => {
2644
                            if ( $(td).html() !== '' ) {
2645
                                is_empty = false;
2646
                                return;
2647
                            }
2648
                        });
2649
                        if ( is_empty ) {
2650
                            table.columns(i).visible(false);
2651
                        }
2652
                    });
2653
                },
2975
            },
2654
            },
2976
        },
2655
            table_settings,
2977
        table_settings,
2656
            true,
2978
        true);
2657
            filters,
2658
            );
2659
            return items_table;
2660
        }
2979
    </script>
2661
    </script>
2980
    [% CoverImagePlugins | $raw %]
2662
    [% CoverImagePlugins | $raw %]
2981
[% END %]
2663
[% END %]
2982
- 

Return to bug 33568