From 23878d2a508cbc9b3fe711cec3da3af934ad4f4b Mon Sep 17 00:00:00 2001
From: Jake Deery
Date: Mon, 1 Dec 2025 14:45:40 +0000
Subject: [PATCH] Bug 14962: On Display code for Intranet scripts & templates
This patch makes the necessary changes to the Intranet to make sure
effective locations, collection codes, and branches are correctly
displayed.
Please see the test files commit for instructions on how to test this
bundle of patches.
---
basket/basket.pl | 19 +-
catalogue/itemsearch.pl | 7 +
catalogue/moredetail.pl | 16 +
catalogue/search.pl | 6 +
cataloguing/additem.pl | 4 +
circ/overdue.pl | 65 ++--
circ/pendingreserves.pl | 30 +-
circ/returns.pl | 2 +
circ/view_holdsqueue.pl | 23 ++
display/display-home.pl | 52 +++
.../prog/en/includes/action-logs.inc | 10 +
.../prog/en/includes/cat-toolbar.inc | 70 ++++
.../catalogue/itemsearch_item.csv.inc | 2 +-
.../catalogue/itemsearch_item.json.inc | 11 +-
.../prog/en/includes/display-search.inc | 35 ++
.../intranet-tmpl/prog/en/includes/header.inc | 3 +
.../tables/items/catalogue_detail.inc | 47 ++-
.../prog/en/includes/permissions.inc | 21 ++
.../prog/en/includes/waiting_holds.inc | 2 +-
.../prog/en/modules/admin/library_groups.tt | 24 +-
.../admin/preferences/circulation.pref | 7 +
.../en/modules/admin/preferences/logs.pref | 6 +
.../prog/en/modules/basket/basket.tt | 8 +-
.../prog/en/modules/catalogue/detail.tt | 324 ++++++++++++++++++
.../prog/en/modules/catalogue/moredetail.tt | 17 +-
.../prog/en/modules/catalogue/results.tt | 15 +-
.../prog/en/modules/cataloguing/additem.tt | 5 +
.../prog/en/modules/circ/article-requests.tt | 12 +-
.../prog/en/modules/circ/branchtransfers.tt | 2 +-
.../prog/en/modules/circ/on-site_checkouts.tt | 2 +-
.../prog/en/modules/circ/overdue.tt | 4 +-
.../prog/en/modules/circ/pendingbookings.tt | 4 +-
.../prog/en/modules/circ/pendingreserves.tt | 24 +-
.../prog/en/modules/circ/returns.tt | 9 +-
.../prog/en/modules/circ/view_holdsqueue.tt | 33 +-
.../prog/en/modules/display/display-home.tt | 36 ++
.../prog/en/modules/intranet-main.tt | 6 +
.../en/modules/recalls/recalls_to_pull.tt | 4 +-
.../prog/en/modules/reports/itemslost.tt | 4 +-
.../prog/en/modules/tags/list.tt | 4 +-
.../prog/en/modules/tools/viewlog.tt | 2 +-
.../prog/en/modules/virtualshelves/shelves.tt | 6 +-
recalls/recalls_to_pull.pl | 2 +-
43 files changed, 907 insertions(+), 78 deletions(-)
create mode 100755 display/display-home.pl
create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/display-search.inc
create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/display/display-home.tt
diff --git a/basket/basket.pl b/basket/basket.pl
index 49d98371f4c..1ff5c4d7937 100755
--- a/basket/basket.pl
+++ b/basket/basket.pl
@@ -17,6 +17,7 @@
use Modern::Perl;
use CGI qw ( -utf8 );
+use C4::Context;
use C4::Koha;
use C4::Biblio qw(
GetMarcSeries
@@ -29,6 +30,7 @@ use C4::Output qw( output_html_with_http_headers );
use Koha::AuthorisedValues;
use Koha::Biblios;
use Koha::CsvProfiles;
+use Koha::Items;
my $query = CGI->new;
@@ -87,7 +89,15 @@ foreach my $biblionumber (@bibs) {
$num++;
$dat->{biblionumber} = $biblionumber;
- $dat->{ITEM_RESULTS} = $biblio->items->search_ordered;
+ my $items = $biblio->items->search_ordered;
+
+ # Add effective_location for display module support
+ if ( C4::Context->preference('UseDisplayModule') ) {
+ foreach my $item ( $items->as_list ) {
+ $item->{effective_location} = $item->effective_location;
+ }
+ }
+ $dat->{ITEM_RESULTS} = $items;
$dat->{MARCNOTES} = $marcnotesarray;
$dat->{MARCSUBJCTS} = $marcsubjctsarray;
$dat->{MARCAUTHORS} = $marcauthorsarray;
@@ -107,9 +117,10 @@ my $resultsarray = \@results;
# my $itemsarray=\@items;
$template->param(
- BIBLIO_RESULTS => $resultsarray,
- csv_profiles => Koha::CsvProfiles->search( { type => 'marc', used_for => 'export_records' } ),
- bib_list => $bib_list,
+ BIBLIO_RESULTS => $resultsarray,
+ csv_profiles => Koha::CsvProfiles->search( { type => 'marc', used_for => 'export_records' } ),
+ bib_list => $bib_list,
+ UseDisplayModule => C4::Context->preference('UseDisplayModule'),
);
output_html_with_http_headers $query, $cookie, $template->output;
diff --git a/catalogue/itemsearch.pl b/catalogue/itemsearch.pl
index ae8dd8241d6..6ac30c47d71 100755
--- a/catalogue/itemsearch.pl
+++ b/catalogue/itemsearch.pl
@@ -30,6 +30,7 @@ use C4::Koha qw( GetAuthorisedValues );
use Koha::AuthorisedValues;
use Koha::Biblios;
use Koha::Item::Search::Field qw(GetItemSearchFields);
+use Koha::Items;
use Koha::ItemTypes;
use Koha::Libraries;
@@ -292,6 +293,12 @@ if ( defined $format and $format ne 'shareable' ) {
$item->{biblioitem} = $biblio->biblioitem->unblessed;
my $checkout = Koha::Checkouts->find( { itemnumber => $item->{itemnumber} } );
$item->{checkout} = $checkout;
+
+ # Add effective_location for display module support
+ if ( C4::Context->preference('UseDisplayModule') ) {
+ my $item_obj = Koha::Items->find( $item->{itemnumber} );
+ $item->{effective_location} = $item_obj ? $item_obj->effective_location : $item->{location};
+ }
}
}
diff --git a/catalogue/moredetail.pl b/catalogue/moredetail.pl
index cdd6c09be08..f5a13d204f9 100755
--- a/catalogue/moredetail.pl
+++ b/catalogue/moredetail.pl
@@ -161,6 +161,7 @@ foreach my $item (@items) {
$item_info->{itype} = $itemtypes->{ $item->itype }->{'translated_description'}
if exists $itemtypes->{ $item->itype };
$item_info->{effective_itemtype} = $itemtypes->{ $item->effective_itemtype };
+ $item_info->{effective_location} = $item->effective_location;
$item_info->{'ccode'} = $ccodes->{ $item->ccode } if $ccodes && $item->ccode && exists $ccodes->{ $item->ccode };
if ( defined $item->copynumber ) {
$item_info->{'displaycopy'} = 1;
@@ -256,6 +257,21 @@ foreach my $item (@items) {
$item_info->{nomod} = !$patron->can_edit_items_from( $item->homebranch );
+ my @displays;
+ my @display_items = Koha::DisplayItems->search(
+ { itemnumber => $item->itemnumber },
+ {
+ order_by => { '-desc' => 'date_added' },
+ }
+ )->as_list;
+
+ foreach my $display_item (@display_items) {
+ push @displays, $display_item->display;
+ }
+
+ $item_info->{displays} = \@displays
+ unless $#displays < 0;
+
push @item_data, $item_info;
}
diff --git a/catalogue/search.pl b/catalogue/search.pl
index b723855d066..df8d317aff9 100755
--- a/catalogue/search.pl
+++ b/catalogue/search.pl
@@ -684,6 +684,12 @@ if ($hits) {
sort_by => \@sort_by
}
);
+use Data::Dumper; $Data::Dumper::Maxdepth = 2;
+print STDERR "##### " . __LINE__ . " #######################################################\n";
+foreach my $result (@newresults) {
+ print STDERR Dumper($result->{available_items_loop});
+}
+print STDERR "##### " . __LINE__ . " #######################################################\n";
$template->param( hits_to_paginate => $hits_to_paginate );
$template->param( SEARCH_RESULTS => \@newresults );
diff --git a/cataloguing/additem.pl b/cataloguing/additem.pl
index 5c3e2005124..86e2a7486bb 100755
--- a/cataloguing/additem.pl
+++ b/cataloguing/additem.pl
@@ -698,6 +698,10 @@ my @items;
for my $item ( $biblio->items->as_list, $biblio->host_items->as_list ) {
my $i = $item->columns_to_str;
$i->{nomod} = 1 unless $patron->can_edit_items_from( $item->homebranch );
+
+ # Add effective_location for display module support
+ $i->{effective_location} = $item->effective_location;
+
push @items, $i;
}
diff --git a/circ/overdue.pl b/circ/overdue.pl
index 2d58dd27ee4..badb4934b24 100755
--- a/circ/overdue.pl
+++ b/circ/overdue.pl
@@ -28,6 +28,7 @@ use Koha::DateUtils qw( dt_from_string );
use Koha::Patron::Attribute::Types;
use DateTime;
use DateTime::Format::MySQL;
+use Koha::Items;
my $input = CGI->new;
my $showall = $input->param('showall');
@@ -349,36 +350,40 @@ if ($noreport) {
}
push @overduedata, {
- patron => Koha::Patrons->find( $data->{borrowernumber} ),
- duedate => $data->{date_due},
- borrowernumber => $data->{borrowernumber},
- cardnumber => $data->{cardnumber},
- borrowertitle => $data->{borrowertitle},
- surname => $data->{surname},
- firstname => $data->{firstname},
- streetnumber => $data->{streetnumber},
- streettype => $data->{streettype},
- address => $data->{address},
- address2 => $data->{address2},
- city => $data->{city},
- zipcode => $data->{zipcode},
- country => $data->{country},
- phone => $data->{phone},
- email => $data->{email},
- branchcode => $data->{branchcode},
- barcode => $data->{barcode},
- datelastborrowed => $data->{datelastborrowed},
- itemnum => $data->{itemnumber},
- issuedate => $data->{issuedate},
- biblionumber => $data->{biblionumber},
- title => $data->{title},
- subtitle => $data->{subtitle},
- part_number => $data->{part_number},
- part_name => $data->{part_name},
- author => $data->{author},
- homebranchcode => $data->{homebranch},
- holdingbranchcode => $data->{holdingbranch},
- location => $data->{location},
+ patron => Koha::Patrons->find( $data->{borrowernumber} ),
+ duedate => $data->{date_due},
+ borrowernumber => $data->{borrowernumber},
+ cardnumber => $data->{cardnumber},
+ borrowertitle => $data->{borrowertitle},
+ surname => $data->{surname},
+ firstname => $data->{firstname},
+ streetnumber => $data->{streetnumber},
+ streettype => $data->{streettype},
+ address => $data->{address},
+ address2 => $data->{address2},
+ city => $data->{city},
+ zipcode => $data->{zipcode},
+ country => $data->{country},
+ phone => $data->{phone},
+ email => $data->{email},
+ branchcode => $data->{branchcode},
+ barcode => $data->{barcode},
+ datelastborrowed => $data->{datelastborrowed},
+ itemnum => $data->{itemnumber},
+ issuedate => $data->{issuedate},
+ biblionumber => $data->{biblionumber},
+ title => $data->{title},
+ subtitle => $data->{subtitle},
+ part_number => $data->{part_number},
+ part_name => $data->{part_name},
+ author => $data->{author},
+ homebranchcode => $data->{homebranch},
+ holdingbranchcode => $data->{holdingbranch},
+ location => $data->{location},
+ effective_location => do {
+ my $item = Koha::Items->find( $data->{itemnumber} );
+ $item ? $item->effective_location : '';
+ },
itemcallnumber => $data->{itemcallnumber},
replacementprice => $data->{replacementprice},
itemnotes_nonpublic => $data->{itemnotes_nonpublic},
diff --git a/circ/pendingreserves.pl b/circ/pendingreserves.pl
index 140b7b0bd11..879a2108d13 100755
--- a/circ/pendingreserves.pl
+++ b/circ/pendingreserves.pl
@@ -276,13 +276,14 @@ foreach my $bibnum (@biblionumbers) {
# get available values for each biblio
my $fields = {
- collections => 'ccode',
- locations => 'location',
- callnumbers => 'itemcallnumber',
- enumchrons => 'enumchron',
- copynumbers => 'copynumber',
- barcodes => 'barcode',
- holdingbranches => 'holdingbranch'
+ collections => 'ccode',
+ locations => 'location',
+ effective_locations => 'effective_location',
+ callnumbers => 'itemcallnumber',
+ enumchrons => 'enumchron',
+ copynumbers => 'copynumber',
+ barcodes => 'barcode',
+ holdingbranches => 'holdingbranch'
};
while ( my ( $key, $field ) = each %$fields ) {
@@ -316,6 +317,21 @@ foreach my $bibnum (@biblionumbers) {
$hold_info->{hold} = $res_info;
$hold_info->{item_group} = $res_info->item_group;
+ my @displays;
+ my @display_items = Koha::DisplayItems->search(
+ { itemnumber => $hold_info->{item}->itemnumber },
+ {
+ order_by => { '-desc' => 'date_added' },
+ }
+ )->as_list;
+
+ foreach my $display_item (@display_items) {
+ push @displays, $display_item->display;
+ }
+
+ $hold_info->{displays} = \@displays
+ unless $#displays < 0;
+
push @holds_info, $hold_info;
}
diff --git a/circ/returns.pl b/circ/returns.pl
index 35c3367ea4b..752ca3a72dc 100755
--- a/circ/returns.pl
+++ b/circ/returns.pl
@@ -758,6 +758,8 @@ foreach my $code ( keys %$messages ) {
;
} elsif ( $code eq 'InBundle' ) {
$template->param( InBundle => $messages->{InBundle} );
+ } elsif ( $code eq 'RemovedFromDisplay' ) {
+ $template->param( RemovedFromDisplay => $messages->{RemovedFromDisplay} );
} elsif ( $code eq 'UpdateLastSeenError' ) {
$err{UpdateLastSeenError} = $messages->{UpdateLastSeenError};
} else {
diff --git a/circ/view_holdsqueue.pl b/circ/view_holdsqueue.pl
index 460c5d6ba90..9c56df5e430 100755
--- a/circ/view_holdsqueue.pl
+++ b/circ/view_holdsqueue.pl
@@ -59,6 +59,28 @@ if ($run_report) {
}
);
+ my @itemsdisplays;
+ for my $item ($items->as_list) {
+ my $itemsdisplay;
+
+ my @displays;
+ my @display_items = Koha::DisplayItems->search(
+ { itemnumber => $item->itemnumber },
+ {
+ order_by => { '-desc' => 'date_added' },
+ }
+ )->as_list;
+
+ foreach my $display_item (@display_items) {
+ push @displays, $display_item->display;
+
+ $itemsdisplay->{itemnumber} = $item->itemnumber;
+ $itemsdisplay->{displays} = \@displays;
+
+ push @itemsdisplays, $itemsdisplay;
+ }
+ }
+
$template->param(
branchlimit => $branchlimit,
itemtypeslimit => $itemtypeslimit,
@@ -66,6 +88,7 @@ if ($run_report) {
locationslimit => $locationslimit,
total => $items->count,
itemsloop => $items,
+ itemsdisplays => \@itemsdisplays,
run_report => $run_report,
);
}
diff --git a/display/display-home.pl b/display/display-home.pl
new file mode 100755
index 00000000000..f571f548b18
--- /dev/null
+++ b/display/display-home.pl
@@ -0,0 +1,52 @@
+#!/usr/bin/perl
+
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see .
+
+use Modern::Perl;
+
+use CGI qw ( -utf8 );
+use C4::Auth qw( get_template_and_user );
+use C4::Output qw( output_html_with_http_headers );
+
+use Koha::Database::Columns;
+
+my $query = CGI->new;
+my ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user(
+ {
+ template_name => 'display/display-home.tt',
+ query => $query,
+ type => 'intranet',
+ flagsrequired => { displays => '*' },
+ }
+);
+
+my $columns = Koha::Database::Columns::columns;
+$template->param(
+ db_columns => {
+ map {
+ my $table = $_;
+ map { ( $table . '.' . $_ => $columns->{$table}->{$_} ) }
+ keys %{ $columns->{$table} }
+ } qw( biblio biblioitems items )
+ },
+ api_mappings => {
+ items => Koha::Item->to_api_mapping,
+ biblioitems => Koha::Biblioitem->to_api_mapping,
+ biblio => Koha::Biblio->to_api_mapping,
+ },
+);
+
+output_html_with_http_headers $query, $cookie, $template->output;
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/action-logs.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/action-logs.inc
index b863662511d..b164177973e 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/action-logs.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/action-logs.inc
@@ -22,6 +22,8 @@
Circulation [% UNLESS Koha.Preference('IssueLog') %] [% END %]
[% CASE 'CLAIMS' %]
Claims [% UNLESS Koha.Preference('ClaimsLog') %] [% END %]
+ [% CASE 'DISPLAYS' %]
+ Displays [% UNLESS Koha.Preference('DisplayItemsLog') %] [% END %]
[% CASE 'FINES' %]
Fines [% UNLESS Koha.Preference('FinesLog') %] [% END %]
[% CASE 'SYSTEMPREFERENCE' %]
@@ -153,6 +155,14 @@
Modify cardnumber
[% CASE 'RESET 2FA' %]
Reset 2FA
+ [% CASE 'ENABLE' %]
+ Enable
+ [% CASE 'DISABLE' %]
+ Disable
+ [% CASE 'ADD_ITEM' %]
+ Add item
+ [% CASE 'REMOVE_ITEM' %]
+ Remove item
[% CASE %]
[% action | html %]
[% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc
index 7b4ac6920fb..fe55e4adc68 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc
@@ -303,11 +303,81 @@
[% END %]
[% END %]
+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %]
+
+ Add to display
+
+
+ [% END %]
+
[% FOREACH p IN plugins %]
[% p.intranet_catalog_biblio_enhancements_toolbar_button | $raw %]
[% END %]
+
+[% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %]
+
+[% END %]
+
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.csv.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.csv.inc
index 5d859d8c5b8..c184daaa275 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.csv.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.csv.inc
@@ -12,7 +12,7 @@
"[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => item.ccode ) | replace('"', '""') | $raw %]" [%- delimiter | $raw -%] "[% item.barcode | replace('"', '""') | $raw %]" [%- delimiter | $raw -%]
"[% item.itemnumber | replace('"', '""') | $raw %]" [%- delimiter | $raw -%] "[% item.enumchron | replace('"', '""') | $raw %]" [%- delimiter | $raw -%] "[% item.itemcallnumber | replace('"', '""') | $raw %]" [%- delimiter | $raw -%]
"[% Branches.GetName(item.homebranch) | replace('"', '""') | $raw %]" [%- delimiter | $raw -%] "[% Branches.GetName(item.holdingbranch) | replace('"', '""') | $raw %]" [%- delimiter | $raw -%]
-"[% AuthorisedValues.GetDescriptionByKohaField(frameworkcode => biblio.frameworkcode, kohafield => 'items.location', authorised_value => item.location) | replace('"', '""') | $raw %]" [%- delimiter | $raw -%]
+"[% AuthorisedValues.GetDescriptionByKohaField(frameworkcode => biblio.frameworkcode, kohafield => 'items.location', authorised_value => item.effective_location) | replace('"', '""') | $raw %]" [%- delimiter | $raw -%]
"[% ItemTypes.GetDescription(item.itype) | replace('"', '""') | $raw %]" [%- delimiter | $raw -%] "[% item.stocknumber | replace('"', '""') | $raw %]" [%- delimiter | $raw -%]
"[% AuthorisedValues.GetDescriptionByKohaField(frameworkcode => biblio.frameworkcode, kohafield => 'items.notforloan', authorised_value => item.notforloan) | replace('"', '""') | $raw %]" [%- delimiter | $raw -%]
"[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.itemlost', authorised_value => item.itemlost ) || "" | replace('"', '""') | $raw %]" [%- delimiter | $raw -%]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.json.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.json.inc
index 2367c59f1b2..ec69e8f0149 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.json.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/catalogue/itemsearch_item.json.inc
@@ -20,7 +20,16 @@
[% item.barcode | html | $To %]
[%~ END %]",
"[% item.itemnumber | html %]", "[% item.enumchron | html | $To %]", "[% item.itemcallnumber | html | $To %]", "[% Branches.GetName(item.homebranch) | html %]", "[% Branches.GetName(item.holdingbranch) | html %]",
-"[% AuthorisedValues.GetDescriptionByKohaField( frameworkcode => biblio.frameworkcode, kohafield => 'items.location', authorised_value => item.location) | html %]", "[% ItemTypes.GetDescription(item.itype) | html %]",
+[% IF Koha.Preference('UseDisplayModule') && item.effective_location %]
+ [% SET effective_loc = item.effective_location %]
+ [% IF effective_loc.match('^DISPLAY:') %]
+ "[% effective_loc | html %]", "[% ItemTypes.GetDescription(item.itype) | html %]",
+ [% ELSE %]
+ "[% AuthorisedValues.GetDescriptionByKohaField( frameworkcode => biblio.frameworkcode, kohafield => 'items.location', authorised_value => effective_loc) | html %]", "[% ItemTypes.GetDescription(item.itype) | html %]",
+ [% END %]
+[% ELSE %]
+ "[% AuthorisedValues.GetDescriptionByKohaField( frameworkcode => biblio.frameworkcode, kohafield => 'items.location', authorised_value => item.location) | html %]", "[% ItemTypes.GetDescription(item.itype) | html %]",
+[% END %]
"[% item.stocknumber | html | $To %]", "[% AuthorisedValues.GetDescriptionByKohaField( frameworkcode => biblio.frameworkcode, kohafield => 'items.notforloan', authorised_value => item.notforloan) | html %]",
"[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.itemlost', authorised_value => item.itemlost ) || "" | html %]",
"[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.withdrawn', authorised_value => item.withdrawn ) || "" | html %]",
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/display-search.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/display-search.inc
new file mode 100644
index 00000000000..dfd9014b355
--- /dev/null
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/display-search.inc
@@ -0,0 +1,35 @@
+[% USE raw %]
+[% USE Koha %]
+[% PROCESS 'html_helpers.inc' %]
+
+[% WRAPPER tabs id="header_search" %]
+ [% WRAPPER tab_panels %]
+ [% IF ( CAN_user_circulate_circulate_remaining_permissions ) %]
+ [% INCLUDE 'patron-search-box.inc' bs_tab_active= 1 %]
+ [% INCLUDE 'checkin-search-box.inc' %]
+ [% INCLUDE 'renew-search-box.inc' %]
+ [% END %]
+ [% IF ( CAN_user_catalogue ) %]
+ [% INCLUDE 'catalogue-search-box.inc' %]
+ [% END %]
+ [% END # /tab_panels %]
+ [% WRAPPER tabs_nav %]
+ [% IF ( CAN_user_circulate_circulate_remaining_permissions ) %]
+ [% WRAPPER tab_item tabname="circ_search" bt_active= 1 %]
+
Check out
+ [% END %]
+ [% WRAPPER tab_item tabname= "checkin_search" %]
+
Check in
+ [% END %]
+ [% WRAPPER tab_item tabname= "renew_search" %]
+
Renew
+ [% END %]
+ [% END %]
+ [% IF ( CAN_user_catalogue ) %]
+ [% WRAPPER tab_item tabname= "catalog_search" %]
+
Search catalog
+ [% END %]
+ [% END %]
+ [% END # /tabs_nav %]
+[% END # /WRAPPER tabs %]
+
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/header.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/header.inc
index 0634fd3492b..64844460790 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/header.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/header.inc
@@ -70,6 +70,9 @@
[% IF Koha.Preference('PreservationModule') && CAN_user_preservation %]
Preservation
[% END %]
+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %]
+
Displays
+ [% END %]
[% IF ( CAN_user_reports ) %]
Reports
[% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers/tables/items/catalogue_detail.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers/tables/items/catalogue_detail.inc
index d74198bdaf0..c2a4cb4a50a 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers/tables/items/catalogue_detail.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers/tables/items/catalogue_detail.inc
@@ -425,22 +425,42 @@
}
},
{
+ [% IF Koha.Preference('UseDisplayModule') %]
+ data: "me.effective_location",
+ searchable: false,
+ orderable: false,
+ [% ELSE %]
data: "me.location",
datatype: "coded_value:location",
searchable: true,
orderable: true,
+ [% END %]
render: function (data, type, row, meta) {
let nodes = '
';
- [%# If permanent location is defined, show description or code and %]
- [%# display current location in parentheses. If not, display current location. %]
- [%# Note that permanent location is a code, and location may be an authval. %]
+ [% IF Koha.Preference('UseDisplayModule') %]
+ // Use effective_location directly - API handles all logic
+ let loc_str = av_loc.get(row.effective_location) || row.effective_location;
+
+ // Style display items differently (those starting with "DISPLAY:")
+ if (row.effective_location && row.effective_location.startsWith && row.effective_location.startsWith('DISPLAY:')) {
+ nodes += '%s '.format(escape_str(loc_str));
+ } else if ( row.permanent_location && row.permanent_location != row.location ) {
+ let permanent_loc_str = av_loc.get(row.permanent_location);
+ nodes += '%s (%s)'.format(escape_str(permanent_loc_str), escape_str(loc_str));
+ } else {
+ nodes += escape_str(loc_str);
+ }
+ [% ELSE %]
+ [%# Standard location logic when Display module is disabled %]
let loc_str = row._strings.location ? row._strings.location.str : row.location;
+
if ( row.permanent_location && row.permanent_location != row.location ) {
let permanent_loc_str = av_loc.get(row.permanent_location);
nodes += '%s (%s)'.format(escape_str(permanent_loc_str), escape_str(loc_str));
} else {
nodes += escape_str(loc_str);
}
+ [% END %]
nodes += ' ';
return nodes;
}
@@ -601,6 +621,27 @@
}
}
[% END %]
+
+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %]
+ $.ajax({
+ url: '/api/v1/displays',
+ async: false,
+ method: 'GET',
+ headers: { 'x-koha-embed': 'display_items' },
+ success: displays => {
+ displays.forEach(display => {
+ display.display_items.forEach(display_item => {
+ if (display_item.itemnumber === row.item_id)
+ nodes += '
%s '.format(_("DISPLAY: %s")).format('
%s ').format(display.display_id, display.display_name);
+ });
+ });
+ },
+ error: error => {
+ console.error(error);
+ }
+ });
+ [% END %]
+
if ( status == 'available' ) {
nodes += '
%s '.format(_("Available"))
}
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/permissions.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/permissions.inc
index 9aae9efba09..08ea5d49a51 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/permissions.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/permissions.inc
@@ -51,6 +51,9 @@
[%- CASE 'coursereserves' -%]
Course reserves
([% name | html %])
+ [%- CASE 'displays' -%]
+
Display module
+
([% name | html %])
[%- CASE 'plugins' -%]
Koha plugins
([% name | html %])
@@ -511,6 +514,24 @@
[%- CASE 'manage_courses' -%]
Add, edit and delete courses
([% name | html %])
+ [%- CASE 'add_display' -%]
+
Add displays
+
([% name | html %])
+ [%- CASE 'edit_display' -%]
+
Edit displays
+
([% name | html %])
+ [%- CASE 'delete_display' -%]
+
Delete displays
+
([% name | html %])
+ [%- CASE 'add_items_to_display' -%]
+
Add items to displays
+
([% name | html %])
+ [%- CASE 'add_items_to_display_from_any_libraries' -%]
+
Add items to displays from any libraries
+
([% name | html %])
+ [%- CASE 'remove_items_from_display' -%]
+
Remove items from displays
+
([% name | html %])
[%- CASE 'configure' -%]
Configure plugins
([% name | html %])
diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/waiting_holds.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/waiting_holds.inc
index 2ba57981f4f..4df1eff7fbb 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/includes/waiting_holds.inc
+++ b/koha-tmpl/intranet-tmpl/prog/en/includes/waiting_holds.inc
@@ -83,7 +83,7 @@
[% Branches.GetName( reserveloo.item.homebranch ) | html %]
[% Branches.GetName( reserveloo.item.holdingbranch ) | html %][% IF (reserveloo.desk_id ) %], [% reserveloo.desk.desk_name | html %][% END %]
-
[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => reserveloo.item.location) | html %]
+
[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => reserveloo.item.effective_location ) | html %]
[% reserveloo.item.itemcallnumber | html %]
[% reserveloo.item.copynumber | html %]
[% reserveloo.item.enumchron | html %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/library_groups.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/library_groups.tt
index 059b66b9b04..d935408a52d 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/library_groups.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/library_groups.tt
@@ -152,6 +152,12 @@
Is local float group
+
+
+
+ Is display group
+
+
@@ -235,6 +241,12 @@
Is local float group
+
+
+
+ Is display group
+
+
@@ -331,7 +343,8 @@
var ft_search_groups_staff = $(this).data("groupFt_search_groups_staff");
var ft_local_hold_group = $(this).data("groupFt_local_hold_group");
var ft_local_float_group = $(this).data("groupFt_local_float_group");
- edit_group(id, parent_id, title, description, ft_hide_patron_info, ft_search_groups_opac, ft_search_groups_staff, ft_local_hold_group, ft_limit_item_editing, ft_local_float_group);
+ var ft_display_group = $(this).data("groupFt_display_group");
+ edit_group(id, parent_id, title, description, ft_hide_patron_info, ft_search_groups_opac, ft_search_groups_staff, ft_local_hold_group, ft_limit_item_editing, ft_local_float_group, ft_display_group);
});
$(".delete-group").on("click", function (e) {
@@ -368,6 +381,7 @@
$("#add-group-modal-ft_search_groups_staff").prop("checked", false);
$("#add-group-modal-ft_local_hold_group").prop("checked", false);
$("#add-group-modal-ft_local_float_group").prop("checked", false);
+ $("#add-group-modal-ft_display_group").prop("checked", false);
if (parent_id) {
$("#root-group-features-add").hide();
} else {
@@ -376,7 +390,7 @@
$("#add-group-modal").modal("show");
}
- function edit_group(id, parent_id, title, description, ft_hide_patron_info, ft_search_groups_opac, ft_search_groups_staff, ft_local_hold_group, ft_limit_item_editing, ft_local_float_group) {
+ function edit_group(id, parent_id, title, description, ft_hide_patron_info, ft_search_groups_opac, ft_search_groups_staff, ft_local_hold_group, ft_limit_item_editing, ft_local_float_group, ft_display_group) {
$("#edit-group-modal-id").val(id);
$("#edit-group-modal-title").val(title);
$("#edit-group-modal-description").val(description);
@@ -387,6 +401,7 @@
$("#edit-group-modal-ft_search_groups_staff").prop("checked", false);
$("#edit-group-modal-ft_local_hold_group").prop("checked", false);
$("#edit-group-modal-ft_local_float_group").prop("checked", false);
+ $("#edit-group-modal-ft_display_group").prop("checked", false);
$("#root-group-features-edit").hide();
} else {
$("#edit-group-modal-ft_hide_patron_info").prop("checked", ft_hide_patron_info ? true : false);
@@ -395,6 +410,7 @@
$("#edit-group-modal-ft_search_groups_staff").prop("checked", ft_search_groups_staff ? true : false);
$("#edit-group-modal-ft_local_hold_group").prop("checked", ft_local_hold_group ? true : false);
$("#edit-group-modal-ft_local_float_group").prop("checked", ft_local_float_group ? true : false);
+ $("#edit-group-modal-ft_display_group").prop("checked", ft_display_group ? true : false);
$("#root-group-features-edit").show();
}
@@ -455,6 +471,9 @@
[% IF group.ft_local_float_group %]
Is local float group
[% END %]
+ [% IF group.ft_display_group %]
+ Is display group
+ [% END %]
[% END %]
@@ -486,6 +505,7 @@
data-group-ft_local_hold_group="[% group.ft_local_hold_group | html %]"
data-group-ft_limit_item_editing="[% group.ft_limit_item_editing | html %]"
data-group-ft_local_float_group="[% group.ft_local_float_group | html %]"
+ data-group-ft_display_group="[% group.ft_display_group | html %]"
>
Edit
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
index 82070552d6c..fa57525ba54 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref
@@ -1342,6 +1342,13 @@ Circulation:
1: Use
0: "Don't use"
- "course reserves."
+ Display module:
+ -
+ - pref: UseDisplayModule
+ choices:
+ 1: Use
+ 0: "Don't use"
+ - "the display module for managing item displays."
Batch checkout:
-
- pref: BatchCheckouts
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/logs.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/logs.pref
index 58679b4ab32..08cd86ef81f 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/logs.pref
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/logs.pref
@@ -84,6 +84,12 @@ Logging:
1: Log
0: "Don't log"
- information from cron jobs.
+ -
+ - pref: DisplayItemsLog
+ choices:
+ 1: Log
+ 0: "Don't log"
+ - when displays are created, edited, deleted, or when items are added to or removed from displays.
-
- pref: ReportsLog
choices:
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt
index e032a57227d..100e2b64f53 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt
@@ -243,7 +243,9 @@
[% FOREACH ITEM_RESULT IN BIBLIO_RESULT.ITEM_RESULTS %]
[% Branches.GetName(ITEM_RESULT.holdingbranch) | html %]
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ITEM_RESULT.location ) | html %]
+
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ITEM_RESULT.effective_location ) | html %]
+
[% IF ( ITEM_RESULT.itemcallnumber ) %]
([% ITEM_RESULT.itemcallnumber | html %])
[% END %]
@@ -337,7 +339,9 @@
[% ITEM_RESULT.itemcallnumber | html %]
[% Branches.GetName(ITEM_RESULT.holdingbranch) | html %]
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ITEM_RESULT.location ) | html %]
+
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ITEM_RESULT.effective_location ) | html %]
+
[% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt
index 061b5d39a11..d7630e23690 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt
@@ -2368,7 +2368,331 @@
$(".delete-comment").on("click", function(){
return confirm( _("Are you sure you want to delete this comment?") );
});
+
+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %]
+ // Display functionality
+ let availableDisplays = [];
+ let displayItemsTable = null;
+ let selectedDisplayItems = [];
+
+ // Load displays on page load
+ $(document).ready(function() {
+ // Load available displays for dropdown
+ $.ajax({
+ url: '/api/v1/displays',
+ method: 'GET',
+ headers: { 'x-koha-embed': 'display_items' },
+ success: function(displays) {
+ availableDisplays = displays.filter(display => display.enabled);
+ updateDisplayDropdown();
+ updateDisplaySelect();
+ },
+ error: function() {
+ $('#display-dropdown').html('
Failed to load displays ');
+ }
+ });
+ });
+
+ function updateDisplayDropdown() {
+ const dropdown = $('#display-dropdown');
+ if (availableDisplays.length === 0) {
+ dropdown.html('No active displays available ');
+ return;
+ }
+
+ let html = '';
+ availableDisplays.forEach(display => {
+ html += `${display.display_name} `;
+ });
+ dropdown.html(html);
+ }
+
+ function updateDisplaySelect() {
+ // Update display select
+ const displaySelect = $('#display-select');
+ let selectHtml = 'Select a display ';
+ availableDisplays.forEach(display => {
+ selectHtml += `${display.display_name} `;
+ });
+ displaySelect.html(selectHtml);
+ }
+
+ function initializeDisplayItemsTable() {
+ if (displayItemsTable && displayItemsTable.DataTable) {
+ displayItemsTable.DataTable().destroy();
+ displayItemsTable = null;
+ }
+
+ selectedDisplayItems = [];
+
+ // Use the same API endpoint and embed options as the main items table
+ let item_table_url = "/api/v1/biblios/[% biblionumber | uri %]/items?";
+ let embed = ["+strings,_status,home_library,holding_library"];
+
+ displayItemsTable = $("#display-items-table").kohaTable({
+ ajax: { url: item_table_url },
+ embed: embed,
+ order: [[1, 'asc']], // Sort by barcode
+ autoWidth: false,
+ paging: false,
+ searching: true,
+ info: false,
+ columns: [
+ {
+ data: "me.item_id",
+ searchable: false,
+ orderable: false,
+ render: function (data, type, row, meta) {
+ return ` `;
+ }
+ },
+ {
+ data: "me.external_id",
+ searchable: true,
+ orderable: true,
+ render: function (data, type, row, meta) {
+ return escape_str(row.external_id || 'No barcode');
+ }
+ },
+ {
+ data: "me.holding_library_id",
+ searchable: true,
+ orderable: true,
+ render: function (data, type, row, meta) {
+ return escape_str(row._strings.holding_library_id ? row._strings.holding_library_id.str : row.holding_library_id);
+ }
+ },
+ {
+ data: "me.home_library_id",
+ searchable: true,
+ orderable: true,
+ render: function (data, type, row, meta) {
+ return escape_str(row._strings.home_library_id ? row._strings.home_library_id.str : row.home_library_id);
+ }
+ },
+ {
+ [% IF Koha.Preference('UseDisplayModule') %]
+ data: "me.effective_location",
+ searchable: false,
+ orderable: false,
+ [% ELSE %]
+ data: "me.location",
+ searchable: true,
+ orderable: true,
+ [% END %]
+ render: function (data, type, row, meta) {
+ [% IF Koha.Preference('UseDisplayModule') %]
+ // Get the display name for effective location
+ let effective_loc_str = av_loc.get(row.effective_location) || row.effective_location;
+ return escape_str(effective_loc_str || '');
+ [% ELSE %]
+ let loc_str = row._strings.location ? row._strings.location.str : row.location;
+ return escape_str(loc_str || '');
+ [% END %]
+ }
+ },
+ {
+ data: "me.collection_code",
+ searchable: true,
+ orderable: true,
+ render: function (data, type, row, meta) {
+ return escape_str(row._strings.collection_code ? row._strings.collection_code.str : row.collection_code);
+ }
+ },
+ {
+ data: "me.callnumber",
+ searchable: true,
+ orderable: true,
+ render: function (data, type, row, meta) {
+ return escape_str(row.callnumber || '');
+ }
+ },
+ {
+ data: "",
+ searchable: false,
+ orderable: false,
+ render: function (data, type, row, meta) {
+ let status = '';
+ if (row._status && row._status.length > 0) {
+ status = row._status.map(s => s.replace(/_/g, ' ')).join(', ');
+ } else {
+ status = 'Available';
+ }
+ return escape_str(status);
+ }
+ }
+ ],
+ [% IF Koha.Preference('UseDisplayModule') %]
+ rowCallback: function(row, data) {
+ // Hide items that are already on displays (effective_location starts with "DISPLAY:")
+ if (data.effective_location && data.effective_location.startsWith && data.effective_location.startsWith('DISPLAY:')) {
+ $(row).hide();
+ return;
+ }
+ $(row).show();
+ },
+ [% END %]
+ drawCallback: function(settings) {
+ // Handle individual checkbox changes
+ $('.display-item-checkbox').off('change').on('change', function() {
+ const itemId = parseInt($(this).val());
+ if ($(this).is(':checked')) {
+ if (!selectedDisplayItems.includes(itemId)) {
+ selectedDisplayItems.push(itemId);
+ }
+ } else {
+ selectedDisplayItems = selectedDisplayItems.filter(id => id !== itemId);
+ }
+ updateSelectAllState();
+ });
+
+ // Handle select all checkbox
+ $('#select-all-display-items').off('change').on('change', function() {
+ const isChecked = $(this).is(':checked');
+ $('.display-item-checkbox').prop('checked', isChecked);
+
+ if (isChecked) {
+ selectedDisplayItems = [];
+ $('.display-item-checkbox').each(function() {
+ selectedDisplayItems.push(parseInt($(this).val()));
+ });
+ } else {
+ selectedDisplayItems = [];
+ }
+ });
+ }
+ });
+ }
+
+ function updateSelectAllState() {
+ const totalCheckboxes = $('.display-item-checkbox').length;
+ const checkedCheckboxes = $('.display-item-checkbox:checked').length;
+
+ if (checkedCheckboxes === 0) {
+ $('#select-all-display-items').prop('indeterminate', false).prop('checked', false);
+ } else if (checkedCheckboxes === totalCheckboxes) {
+ $('#select-all-display-items').prop('indeterminate', false).prop('checked', true);
+ } else {
+ $('#select-all-display-items').prop('indeterminate', true);
+ }
+ }
+
+ function openDisplayModal(displayId = null) {
+ if (displayId) {
+ $('#display-select').val(displayId);
+ }
+ // Initialize the DataTable when the modal is opened
+ initializeDisplayItemsTable();
+ $('#addToDisplayModal').modal('show');
+ }
+
+ // Clear date button functionality
+ $('#clear-date').on('click', function() {
+ $('#date-remove').val('');
+ });
+
+ // Form submission
+ $('#addToDisplayForm').on('submit', function(e) {
+ e.preventDefault();
+
+ const displayId = $('#display-select').val();
+ const removeDate = $('#date-remove').val();
+
+ if (!displayId) {
+ alert('Please select a display');
+ return;
+ }
+
+ if (selectedDisplayItems.length === 0) {
+ alert('Please select at least one item');
+ return;
+ }
+
+ $('#add-to-display-btn').prop('disabled', true).text('Adding...');
+
+ // Add each item to the display
+ let promises = selectedDisplayItems.map(itemId => {
+ const data = {
+ display_id: parseInt(displayId),
+ itemnumber: parseInt(itemId),
+ biblionumber: [% biblionumber | html %],
+ date_added: new Date().toISOString().split('T')[0]
+ };
+ if (removeDate) {
+ data.date_remove = removeDate;
+ }
+
+ return $.ajax({
+ url: '/api/v1/display/items',
+ method: 'POST',
+ contentType: 'application/json',
+ data: JSON.stringify(data)
+ });
+ });
+
+ Promise.all(promises).then(() => {
+ alert(`Successfully added ${selectedDisplayItems.length} item(s) to display`);
+ $('#addToDisplayModal').modal('hide');
+ $('#addToDisplayForm')[0].reset();
+ selectedDisplayItems = [];
+
+ // Safely refresh modal table
+ try {
+ if (displayItemsTable && displayItemsTable.DataTable) {
+ displayItemsTable.DataTable().draw();
+ }
+ } catch (e) {
+ // Modal table refresh failed - not critical
+ }
+
+ // Safely refresh the main items table to show updated locations
+ try {
+ if (typeof build_items_table === 'function') {
+ $('.items_table').each(function() {
+ let table_id = $(this).attr('id').replace('_table', '');
+ build_items_table(table_id, false, { destroy: true });
+ });
+ }
+ } catch (e) {
+ // Main table refresh failed - reload page as fallback
+ window.location.reload();
+ }
+ }).catch((error) => {
+ console.error('Error adding items to display:', error);
+ alert('Failed to add some items to display. Please try again.');
+ }).finally(() => {
+ $('#add-to-display-btn').prop('disabled', false).text('Add to display');
+ });
+ });
+
+ // Clean up when modal is hidden
+ $('#addToDisplayModal').on('hidden.bs.modal', function() {
+ if (displayItemsTable && displayItemsTable.DataTable) {
+ displayItemsTable.DataTable().destroy();
+ displayItemsTable = null;
+ }
+ selectedDisplayItems = [];
+ $('#addToDisplayForm')[0].reset();
+ });
+ [% END %]
[% CoverImagePlugins | $raw %]
[% END # /jsinclude %]
+
+[% BLOCK cssinclude %]
+
+[% END %]
[% INCLUDE 'intranet-bottom.inc' %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt
index 16ec134a580..02be24ed8cd 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/moredetail.tt
@@ -187,10 +187,23 @@
[% IF ( ITEM_DAT.displaycopy ) %]
Copy number: [% ITEM_DAT.copyvol | html %]
[% END %]
- [% IF ( ITEM_DAT.location ) %]
+ [% IF ( ITEM_DAT.effective_location ) %]
Shelving location:
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ITEM_DAT.location ) | html %]
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ITEM_DAT.effective_location ) | html %]
+
+ [% END %]
+ [% IF ( ITEM_DAT.displays ) %]
+
+ [% IF ITEM_DAT.displays.size > 1 %]
+ In displays:
+ [% ELSE %]
+ In display:
+ [% END %]
+ [% FOR display IN ITEM_DAT.displays %]
+ [% display.display_name | html %]
+ [% UNLESS loop.last %], [% END %]
+ [% END %]
[% END %]
[% IF ( ITEM_DAT.replacementprice ) %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/results.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/results.tt
index c04479af867..3aee76aeb36 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/results.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/results.tt
@@ -826,8 +826,8 @@
[% IF ( items_loo.branchname ) %]
[% items_loo.branchname | html %]
[% END %]
- [% IF ( items_loo.location ) %]
- [% items_loo.location | html %]
+ [% IF ( items_loo.effective_location ) %]
+ [% items_loo.effective_location | html %]
[% END %]
[% IF ( items_loo.collectioncode ) %]
[% items_loo.collectioncode | html %]
@@ -855,6 +855,17 @@
[% IF ( items_loo.notforloan ) %]
[% items_loo.notforloan | html %]
[% END %]
+ [% IF ( items_loo.displays ) %]
+ [% IF items_loo.displays.size > 1 %]
+ In displays:
+ [% ELSE %]
+ In display:
+ [% END %]
+ [% FOR display IN items_loo.displays %]
+ [% display.display_name | html %]
+ [% UNLESS loop.last %], [% END %]
+ [% END %]
+ [% END %]
[% items_loo.count | html %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/additem.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/additem.tt
index 76758d3deb6..fa5479f5519 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/additem.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/cataloguing/additem.tt
@@ -5,6 +5,7 @@
[% USE KohaDates %]
[% USE Price %]
[% USE Item %]
+[% USE AuthorisedValues %]
[% USE TablesSettings %]
[% PROCESS 'i18n.inc' %]
[% INCLUDE 'doc-head-open.inc' %]
@@ -213,6 +214,10 @@
[% item.$attribute | $Price %]
[% ELSIF item.$attribute && attribute == 'itemcallnumber' %]
[% item.$attribute | html %]
+ [% ELSIF attribute == 'location' %]
+
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.effective_location ) | html %]
+
[% ELSE %]
[% item.$attribute | html %]
[% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/article-requests.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/article-requests.tt
index cfb47daa5c4..6c5e89c3427 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/article-requests.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/article-requests.tt
@@ -273,8 +273,8 @@
[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => ar.item.ccode ) | html %]
[% ItemTypes.GetDescription( ar.item.effective_itemtype ) | html %]
- [% IF ar.item.location %]
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ar.item.location ) | html %]
+ [% IF ar.item.effective_location %]
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ar.item.effective_location ) | html %]
[% END %]
[% ar.item.itemcallnumber | html %]
@@ -380,8 +380,8 @@
[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => ar.item.ccode ) | html %]
[% ItemTypes.GetDescription( ar.item.effective_itemtype ) | html %]
- [% IF ar.item.location %]
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ar.item.location ) | html %]
+ [% IF ar.item.effective_location %]
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ar.item.effective_location ) | html %]
[% END %]
[% ar.item.itemcallnumber | html %]
@@ -484,8 +484,8 @@
[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => ar.item.ccode ) | html %]
[% ItemTypes.GetDescription( ar.item.effective_itemtype ) | html %]
- [% IF ar.item.location %]
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ar.item.location ) | html %]
+ [% IF ar.item.effective_location %]
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ar.item.effective_location ) | html %]
[% END %]
[% ar.item.itemcallnumber | html %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/branchtransfers.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/branchtransfers.tt
index 56dd9901695..dae810712d0 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/branchtransfers.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/branchtransfers.tt
@@ -273,7 +273,7 @@
>[% trsfitemloo.item.barcode | html %]
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => trsfitemloo.item.location ) | html %]
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => trsfitemloo.item.effective_location ) | html %]
[% trsfitemloo.item.itemcallnumber | html %]
[% ItemTypes.GetDescription( trsfitemloo.item.effective_itemtype ) | html %]
[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => trsfitemloo.item.ccode ) | html %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/on-site_checkouts.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/on-site_checkouts.tt
index bb315fd622f..14b5b7fe7c7 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/on-site_checkouts.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/on-site_checkouts.tt
@@ -63,7 +63,7 @@
[% item.barcode | html %]
[% Branches.GetName(item.branchcode) | html %]
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.location ) | html %]
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => (item.effective_location || item.location) ) | html %]
[% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/overdue.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/overdue.tt
index 1bc2b58b50d..196394d57a5 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/overdue.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/overdue.tt
@@ -144,7 +144,9 @@
>
[% Branches.GetName( overdueloo.homebranchcode ) | html %]
[% Branches.GetName( overdueloo.holdingbranchcode ) | html %]
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => overdueloo.location ) | html %]
+
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => overdueloo.effective_location ) | html %]
+
[% overdueloo.datelastborrowed | $KohaDates %]
Earliest hold date
Hold notes
Pickup location
+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %]
+ Displays
+ [% END %]
Action
@@ -184,8 +187,8 @@
- [% FOREACH loc IN hold_info.locations %]
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => loc ) | html %]
+ [% FOREACH effective_location IN hold_info.effective_locations %]
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => effective_location ) | html %]
[% END %]
@@ -199,6 +202,23 @@
[% hold.reservedate | $KohaDates %] in [% Branches.GetName ( hold.branchcode ) | html %]
[% hold.reservenotes | html %]
[% Branches.GetName ( hold.branchcode ) | html %]
+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %]
+
+ [% IF ( hold_info.displays ) %]
+ [% IF hold_info.displays.size > 1 %]
+ In displays:
+ [% ELSE %]
+ In display:
+ [% END %]
+ [% FOR display IN hold_info.displays %]
+ [% display.display_name | html %]
+ [% UNLESS loop.last %], [% END %]
+ [% END %]
+ [% ELSE %]
+ Not in any displays
+ [% END %]
+
+ [% END %]
- [% checkin.item_location | html %]
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => checkin.item.effective_location ) | html %]
[% checkin.item.itemcallnumber | html %]
[% checkin.item.dateaccessioned | $KohaDates %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/view_holdsqueue.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/view_holdsqueue.tt
index facdba84331..cc1164d4efc 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/view_holdsqueue.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/view_holdsqueue.tt
@@ -121,6 +121,9 @@
Patron category
Send to
Date
+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %]
+ Displays
+ [% END %]
Notes
@@ -204,6 +207,13 @@
+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %]
+
+
+
+
+
+ [% END %]
@@ -240,7 +250,9 @@
[% Branches.GetName( itemsloo.holdingbranch ) | html %]
[% Branches.GetName( itemsloo.item.homebranch ) | html %]
[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => itemsloo.item.ccode ) | html %]
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => itemsloo.item.location ) | html %]
+
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => itemsloo.item.effective_location ) | html %]
+
[% ItemTypes.GetDescription( itemsloo.item.effective_itemtype ) | html %]
[% itemsloo.item.itemcallnumber | html %]
[% itemsloo.item.copynumber | html %]
@@ -287,6 +299,25 @@
[% itemsloo.patron.category.description | html %] ([% itemsloo.patron.categorycode | html %])
[% Branches.GetName( itemsloo.pickbranch ) | html %]
[% itemsloo.reservedate | $KohaDates %]
+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %]
+
+ [% FOREACH itemsdisplay IN itemsdisplays %]
+ [% IF (itemsloo.itemnumber == itemsdisplay.itemnumber) %]
+ [% IF itemsdisplay.displays.size > 1 %]
+ In displays:
+ [% ELSE %]
+ In display:
+ [% END %]
+ [% FOREACH display IN itemsdisplay.displays %]
+ [% display.display_name | html %]
+ [% UNLESS loop.last %], [% END %]
+ [% END %]
+ [% ELSE %]
+ Item not in display
+ [% END %]
+ [% END %]
+
+ [% END %]
[% itemsloo.notes | html %]
[% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/display/display-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/display/display-home.tt
new file mode 100644
index 00000000000..1c5fe28c516
--- /dev/null
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/display/display-home.tt
@@ -0,0 +1,36 @@
+[% USE raw %]
+[% USE To %]
+[% USE Asset %]
+[% USE Koha %]
+[% USE KohaDates %]
+[% USE TablesSettings %]
+[% USE AuthorisedValues %]
+[% SET footerjs = 1 %]
+[% PROCESS 'i18n.inc' %]
+[% INCLUDE 'doc-head-open.inc' %]
+ Displays › Koha
+[% INCLUDE 'doc-head-close.inc' %]
+
+
+
+[% WRAPPER 'header.inc' %]
+ [% INCLUDE 'display-search.inc' %]
+[% END %]
+
+
+
+[% MACRO jsinclude BLOCK %]
+ [% INCLUDE 'calendar.inc' %]
+ [% INCLUDE 'datatables.inc' %]
+ [% INCLUDE 'js-date-format.inc' %]
+ [% INCLUDE 'js-biblio-format.inc' %]
+
+ [% Asset.js("js/vue/dist/display.js") | $raw %]
+[% END %]
+[% INCLUDE 'intranet-bottom.inc' %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt
index fe5e0597aaa..b79d835b9d1 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt
@@ -167,6 +167,12 @@
[% END %]
+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %]
+
+ Displays
+
+ [% END %]
+
[% IF ( CAN_user_tools || CAN_user_clubs ) %]
Tools
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/recalls/recalls_to_pull.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/recalls/recalls_to_pull.tt
index dba569bc1df..35bb025bae0 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/recalls/recalls_to_pull.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/recalls/recalls_to_pull.tt
@@ -111,8 +111,8 @@
- [% FOREACH loc IN recall.locations %]
- [% AuthorisedValues.GetByCode('LOC', loc) | html %]
+ [% FOREACH location IN recall.locations %]
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => location ) | html %]
[% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/itemslost.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/itemslost.tt
index 8f87e2161bf..8f9497ebdbd 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/itemslost.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/itemslost.tt
@@ -126,7 +126,9 @@
[% ItemTypes.GetDescription(item.effective_itemtype) | html %]
[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => item.ccode ) | html %]
[% Branches.GetName(item.holdingbranch) | html %]
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.location ) | html %]
+
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.effective_location ) | html %]
+
[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.notforloan', authorised_value => item.notforloan ) | html %] [% item.itemnotes | $raw %]
[% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tags/list.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tags/list.tt
index 60d1bc4e330..fb9929ae06e 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tags/list.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tags/list.tt
@@ -96,7 +96,9 @@
>[% FOREACH item IN title.items %]
[% Branches.GetName(item.holdingbranch) | html %]
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.location ) | html %]
+
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.effective_location ) | html %]
+
[% IF ( item.itemcallnumber ) %]
([% item.itemcallnumber | html %])
[% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt
index 6e434a5c67f..d64e4f62e24 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/viewlog.tt
@@ -123,7 +123,7 @@
[% ELSE %]
All
[% END %]
- [% FOREACH modx IN [ 'AUTH' 'CATALOGUING' 'AUTHORITIES' 'MEMBERS' 'ACQUISITIONS' 'SERIAL' 'HOLDS' 'ILL' 'CIRCULATION' 'CLAIMS' 'FINES' 'SYSTEMPREFERENCE' 'CRONJOBS', 'REPORTS', 'SEARCHENGINE', 'NOTICES', 'NEWS', 'RECALLS', 'SUGGESTION', 'TRANSFERS' ] %]
+ [% FOREACH modx IN [ 'AUTH' 'CATALOGUING' 'AUTHORITIES' 'MEMBERS' 'ACQUISITIONS' 'SERIAL' 'HOLDS' 'ILL' 'CIRCULATION' 'CLAIMS' 'DISPLAYS' 'FINES' 'SYSTEMPREFERENCE' 'CRONJOBS', 'REPORTS', 'SEARCHENGINE', 'NOTICES', 'NEWS', 'RECALLS', 'SUGGESTION', 'TRANSFERS' ] %]
[% IF modules.grep(modx).size %]
[% PROCESS translate_log_module module=modx %]
[% Branches.GetName(item.holdingbranch) | html %]
- [% IF ( item.location ) %]
- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.location ) | html %]
+ [% IF ( item.effective_location ) %]
+
+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.effective_location ) | html %]
+
[% END %]
[% IF ( item.itemcallnumber ) %]
[[% item.itemcallnumber | html %] ]
diff --git a/recalls/recalls_to_pull.pl b/recalls/recalls_to_pull.pl
index 0f91a775d1b..026c511657a 100755
--- a/recalls/recalls_to_pull.pl
+++ b/recalls/recalls_to_pull.pl
@@ -98,7 +98,7 @@ if ( $op eq 'list' ) {
push( @copynumbers, $item->copynumber ) if ( $item->copynumber );
push( @enumchrons, $item->enumchron ) if ( $item->enumchron );
push( @itemtypes, $item->effective_itemtype ) if ( $item->effective_itemtype );
- push( @locations, $item->location ) if ( $item->location );
+ push( @locations, $item->effective_location ) if ( $item->effective_location );
push( @libraries, $item->holdingbranch ) if ( $item->holdingbranch );
}
}
--
2.50.1 (Apple Git-155)