Bugzilla – Attachment 190226 Details for
Bug 14962
Temp Shelving Location
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 14962: On Display code for Intranet scripts & templates
Bug-14962-On-Display-code-for-Intranet-scripts--te.patch (text/plain), 99.43 KB, created by
Jake Deery
on 2025-12-05 14:51:42 UTC
(
hide
)
Description:
Bug 14962: On Display code for Intranet scripts & templates
Filename:
MIME Type:
Creator:
Jake Deery
Created:
2025-12-05 14:51:42 UTC
Size:
99.43 KB
patch
obsolete
>From 23878d2a508cbc9b3fe711cec3da3af934ad4f4b Mon Sep 17 00:00:00 2001 >From: Jake Deery <jake.deery@openfifth.co.uk> >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 <http://www.gnu.org/licenses>. >+ >+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 @@ > <span>Circulation</span>[% UNLESS Koha.Preference('IssueLog') %]<i class="log-disabled fa-solid fa-triangle-exclamation" title="Log not enabled" data-log="IssueLog"></i>[% END %] > [% CASE 'CLAIMS' %] > <span>Claims</span>[% UNLESS Koha.Preference('ClaimsLog') %]<i class="log-disabled fa-solid fa-triangle-exclamation" title="Log not enabled" data-log="ClaimsLog"></i>[% END %] >+ [% CASE 'DISPLAYS' %] >+ <span>Displays</span>[% UNLESS Koha.Preference('DisplayItemsLog') %]<i class="log-disabled fa-solid fa-triangle-exclamation" title="Log not enabled" data-log="DisplayItemsLog"></i>[% END %] > [% CASE 'FINES' %] > <span>Fines</span>[% UNLESS Koha.Preference('FinesLog') %]<i class="log-disabled fa-solid fa-triangle-exclamation" title="Log not enabled" data-log="FinesLog"></i>[% END %] > [% CASE 'SYSTEMPREFERENCE' %] >@@ -153,6 +155,14 @@ > <span>Modify cardnumber</span> > [% CASE 'RESET 2FA' %] > <span>Reset 2FA</span> >+ [% CASE 'ENABLE' %] >+ <span>Enable</span> >+ [% CASE 'DISABLE' %] >+ <span>Disable</span> >+ [% CASE 'ADD_ITEM' %] >+ <span>Add item</span> >+ [% CASE 'REMOVE_ITEM' %] >+ <span>Remove item</span> > [% 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 %] >+ <div class="btn-group"> >+ <button type="button" class="btn btn-default dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false"><i class="fa fa-tv"></i> Add to display</button> >+ <ul class="dropdown-menu" id="display-dropdown"> >+ <li class="text-center"><i class="fa fa-spinner fa-spin"></i> Loading displays...</li> >+ </ul> >+ </div> >+ [% END %] >+ > [% FOREACH p IN plugins %] > [% p.intranet_catalog_biblio_enhancements_toolbar_button | $raw %] > [% END %] > </div> > >+<!-- Modal for Add to Display --> >+[% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %] >+ <div class="modal fade" id="addToDisplayModal" tabindex="-1" role="dialog" aria-labelledby="addToDisplayModalLabel" aria-hidden="true"> >+ <div class="modal-dialog modal-lg"> >+ <div class="modal-content"> >+ <div class="modal-header"> >+ <h4 class="modal-title" id="addToDisplayModalLabel">Add items to display</h4> >+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> >+ </div> >+ <form id="addToDisplayForm"> >+ <div class="modal-body"> >+ <div class="row"> >+ <div class="col-md-6"> >+ <label for="display-select" class="form-label">Select display:</label> >+ <select id="display-select" class="form-select" required> >+ <option value="">Loading displays...</option> >+ </select> >+ </div> >+ <div class="col-md-6"> >+ <label for="date-remove" class="form-label">Remove date (optional):</label> >+ <div class="input-group"> >+ <input type="date" id="date-remove" class="form-control" /> >+ <button class="btn btn-outline-secondary" type="button" id="clear-date" title="Clear date"> >+ <i class="fa fa-times"></i> >+ </button> >+ </div> >+ </div> >+ </div> >+ <div class="row mt-3"> >+ <div class="col-12"> >+ <label class="form-label">Select items to add:</label> >+ <div class="table-responsive"> >+ <table id="display-items-table" class="table table-striped"> >+ <thead> >+ <tr> >+ <th><input type="checkbox" id="select-all-display-items" /></th> >+ <th>Barcode</th> >+ <th>Current library</th> >+ <th>Home library</th> >+ <th>Location</th> >+ <th>Collection</th> >+ <th>Call number</th> >+ <th>Status</th> >+ </tr> >+ </thead> >+ <tbody> </tbody> >+ </table> >+ </div> >+ </div> >+ </div> >+ </div> >+ <div class="modal-footer"> >+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> >+ <button type="submit" class="btn btn-primary" id="add-to-display-btn">Add to display</button> >+ </div> >+ </form> >+ </div> >+ </div> >+ </div> >+[% END %] >+ > <!--Modal for Dublin Core--> > <div class="modal" id="exportModal_" tabindex="-1" role="dialog" aria-labelledby="exportLabelexportModal_" aria-hidden="true"> > <div class="modal-dialog"> >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 @@ > <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% biblio.biblionumber | uri %]#item[% item.itemnumber | uri %]" title="Go to item details">[% item.barcode | html | $To %]</a> > [%~ 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' %] >+<!-- display-search.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 %] >+ <i class="fa fa-fw fa-upload" aria-hidden="true"></i> <span class="tab-title">Check out</span> >+ [% END %] >+ [% WRAPPER tab_item tabname= "checkin_search" %] >+ <i class="fa fa-fw fa-download" aria-hidden="true"></i> <span class="tab-title">Check in</span> >+ [% END %] >+ [% WRAPPER tab_item tabname= "renew_search" %] >+ <i class="fa fa-fw fa-retweet" aria-hidden="true"></i> <span class="tab-title">Renew</span> >+ [% END %] >+ [% END %] >+ [% IF ( CAN_user_catalogue ) %] >+ [% WRAPPER tab_item tabname= "catalog_search" %] >+ <i class="fa fa-fw fa-search" aria-hidden="true"></i> <span class="tab-title">Search catalog</span> >+ [% END %] >+ [% END %] >+ [% END # /tabs_nav %] >+[% END # /WRAPPER tabs %] >+<!-- /display-search.inc --> >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 %] > <li><a class="dropdown-item" href="/cgi-bin/koha/preservation/home.pl">Preservation</a></li> > [% END %] >+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %] >+ <li><a class="dropdown-item" href="/cgi-bin/koha/display/display-home.pl">Displays</a></li> >+ [% END %] > [% IF ( CAN_user_reports ) %] > <li><a class="dropdown-item" href="/cgi-bin/koha/reports/reports-home.pl">Reports</a></li> > [% 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 = '<span class="shelvingloc">'; >- [%# If permanent location is defined, show description or code and %] >- [%# display current location in parentheses. If not, display current location. %] >- [%# Note that permanent location is a code, and location may be an authval. %] >+ [% 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 += '<span class="display-location" title="Item is currently on display">%s</span>'.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 += '</span>'; > 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 += '<span class="holding_status on_display">%s</span>'.format(_("DISPLAY: %s")).format('<a href="/cgi-bin/koha/display/displays/%s">%s</a>').format(display.display_id, display.display_name); >+ }); >+ }); >+ }, >+ error: error => { >+ console.error(error); >+ } >+ }); >+ [% END %] >+ > if ( status == 'available' ) { > nodes += ' <span>%s</span>'.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' -%] > <span class="main_permission coursereserves_permission">Course reserves</span> > <span class="permissioncode">([% name | html %])</span> >+ [%- CASE 'displays' -%] >+ <span class="main_permission displays_permission">Display module</span> >+ <span class="permissioncode">([% name | html %])</span> > [%- CASE 'plugins' -%] > <span class="main_permission plugins_permission">Koha plugins</span> > <span class="permissioncode">([% name | html %])</span> >@@ -511,6 +514,24 @@ > [%- CASE 'manage_courses' -%] > <span class="sub_permission manage_courses_subpermission"> Add, edit and delete courses </span> > <span class="permissioncode">([% name | html %])</span> >+ [%- CASE 'add_display' -%] >+ <span class="sub_permission add_display_subpermission"> Add displays </span> >+ <span class="permissioncode">([% name | html %])</span> >+ [%- CASE 'edit_display' -%] >+ <span class="sub_permission edit_display_subpermission"> Edit displays </span> >+ <span class="permissioncode">([% name | html %])</span> >+ [%- CASE 'delete_display' -%] >+ <span class="sub_permission delete_display_subpermission"> Delete displays </span> >+ <span class="permissioncode">([% name | html %])</span> >+ [%- CASE 'add_items_to_display' -%] >+ <span class="sub_permission add_items_to_display_subpermission"> Add items to displays </span> >+ <span class="permissioncode">([% name | html %])</span> >+ [%- CASE 'add_items_to_display_from_any_libraries' -%] >+ <span class="sub_permission add_items_to_display_from_any_libraries_subpermission"> Add items to displays from any libraries </span> >+ <span class="permissioncode">([% name | html %])</span> >+ [%- CASE 'remove_items_from_display' -%] >+ <span class="sub_permission remove_items_from_display_subpermission"> Remove items from displays </span> >+ <span class="permissioncode">([% name | html %])</span> > [%- CASE 'configure' -%] > <span class="sub_permission configure_subpermission"> Configure plugins </span> > <span class="permissioncode">([% name | html %])</span> >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 @@ > </td> > <td>[% Branches.GetName( reserveloo.item.homebranch ) | html %]</td> > <td>[% Branches.GetName( reserveloo.item.holdingbranch ) | html %][% IF (reserveloo.desk_id ) %], [% reserveloo.desk.desk_name | html %][% END %]</td> >- <td>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => reserveloo.item.location) | html %]</td> >+ <td>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => reserveloo.item.effective_location ) | html %]</td> > <td>[% reserveloo.item.itemcallnumber | html %]</td> > <td>[% reserveloo.item.copynumber | html %]</td> > <td>[% reserveloo.item.enumchron | html %]</td> >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 > </label> > </p> >+ <p> >+ <label> >+ <input type="checkbox" name="ft_display_group" id="add-group-modal-ft_display_group" value="1" /> >+ Is display group >+ </label> >+ </p> > </div> > </div> > </div> >@@ -235,6 +241,12 @@ > Is local float group > </label> > </p> >+ <p> >+ <label> >+ <input type="checkbox" id="edit-group-modal-ft_display_group" name="ft_display_group" value="1" /> >+ Is display group >+ </label> >+ </p> > </div> > </div> > </div> >@@ -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 %] > <li>Is local float group</li> > [% END %] >+ [% IF group.ft_display_group %] >+ <li>Is display group</li> >+ [% END %] > </ul> > [% END %] > </td> >@@ -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 %]" > > > <i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit > </a> >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 %] > <p> > [% Branches.GetName(ITEM_RESULT.holdingbranch) | html %] >- <span class="shelvingloc"> [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ITEM_RESULT.location ) | html %] </span> >+ <span class="shelvingloc"> >+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ITEM_RESULT.effective_location ) | html %] >+ </span> > [% IF ( ITEM_RESULT.itemcallnumber ) %] > ([% ITEM_RESULT.itemcallnumber | html %]) > [% END %] >@@ -337,7 +339,9 @@ > <span class="callnumber">[% ITEM_RESULT.itemcallnumber | html %]</span> > </strong> > [% Branches.GetName(ITEM_RESULT.holdingbranch) | html %] >- <span class="shelvingloc"> [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ITEM_RESULT.location ) | html %] </span> >+ <span class="shelvingloc"> >+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ITEM_RESULT.effective_location ) | html %] >+ </span> > </span> > </div> > [% 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('<li class="text-center text-muted">Failed to load displays</li>'); >+ } >+ }); >+ }); >+ >+ function updateDisplayDropdown() { >+ const dropdown = $('#display-dropdown'); >+ if (availableDisplays.length === 0) { >+ dropdown.html('<li class="dropdown-item text-muted">No active displays available</li>'); >+ return; >+ } >+ >+ let html = ''; >+ availableDisplays.forEach(display => { >+ html += `<li><a class="dropdown-item" href="#" data-display-id="${display.display_id}" onclick="openDisplayModal(${display.display_id})">${display.display_name}</a></li>`; >+ }); >+ dropdown.html(html); >+ } >+ >+ function updateDisplaySelect() { >+ // Update display select >+ const displaySelect = $('#display-select'); >+ let selectHtml = '<option value="">Select a display</option>'; >+ availableDisplays.forEach(display => { >+ selectHtml += `<option value="${display.display_id}">${display.display_name}</option>`; >+ }); >+ 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 `<input type="checkbox" class="display-item-checkbox" value="${row.item_id}" data-item-id="${row.item_id}">`; >+ } >+ }, >+ { >+ 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 %] > </script> > [% CoverImagePlugins | $raw %] > [% END # /jsinclude %] >+ >+[% BLOCK cssinclude %] >+ <style> >+ .display-location { >+ font-weight: bold; >+ color: #d9534f; >+ } >+ .display-location::before { >+ content: "ðº "; >+ font-size: 0.8em; >+ } >+ .original-location { >+ font-size: 0.9em; >+ font-style: italic; >+ } >+ </style> >+[% 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 ) %] > <li class="copynumber"><span class="label">Copy number:</span> [% ITEM_DAT.copyvol | html %] </li> > [% END %] >- [% IF ( ITEM_DAT.location ) %] >+ [% IF ( ITEM_DAT.effective_location ) %] > <li class="location"> > <span class="label">Shelving location:</span> >- [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ITEM_DAT.location ) | html %] >+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ITEM_DAT.effective_location ) | html %] >+ </li> >+ [% END %] >+ [% IF ( ITEM_DAT.displays ) %] >+ <li class="displays" class="nowrap"> >+ [% IF ITEM_DAT.displays.size > 1 %] >+ <span class="label">In displays:</span> >+ [% ELSE %] >+ <span class="label">In display:</span> >+ [% END %] >+ [% FOR display IN ITEM_DAT.displays %] >+ <a href="/cgi-bin/koha/display/displays/[% display.display_id | url %]">[% display.display_name | html %]</a> >+ [% UNLESS loop.last %], [% END %] >+ [% END %] > </li> > [% 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 ) %] >- <span class="shelvingloc">[% items_loo.location | html %]</span> >+ [% IF ( items_loo.effective_location ) %] >+ <span class="shelvingloc">[% items_loo.effective_location | html %]</span> > [% END %] > [% IF ( items_loo.collectioncode ) %] > <span class="ccode">[% items_loo.collectioncode | html %]</span> >@@ -855,6 +855,17 @@ > [% IF ( items_loo.notforloan ) %] > [% items_loo.notforloan | html %] > [% END %] >+ [% IF ( items_loo.displays ) %] >+ [% IF items_loo.displays.size > 1 %] >+ <span>In displays:</span> >+ [% ELSE %] >+ <span>In display:</span> >+ [% END %] >+ [% FOR display IN items_loo.displays %] >+ <a href="/cgi-bin/koha/display/displays/[% display.display_id | url %]">[% display.display_name | html %]</a> >+ [% UNLESS loop.last %], [% END %] >+ [% END %] >+ [% END %] > <span class="item_count">[% items_loo.count | html %]</span> > </div> > <!-- /.result_item_details --> >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 @@ > <td class="[% can_mod | html %]" data-order="[% item.$attribute | html %]">[% item.$attribute | $Price %]</td> > [% ELSIF item.$attribute && attribute == 'itemcallnumber' %] > <td class="[% can_mod | html %]" data-order="[% item.cn_sort | html %]">[% item.$attribute | html %]</td> >+ [% ELSIF attribute == 'location' %] >+ <td class="[% can_mod | html %]"> >+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.effective_location ) | html %] >+ </td> > [% ELSE %] > <td class="[% can_mod | html %]">[% item.$attribute | html %]</td> > [% 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 @@ > <td class="ar-collection">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => ar.item.ccode ) | html %]</td> > <td class="ar-itemtype">[% ItemTypes.GetDescription( ar.item.effective_itemtype ) | html %]</td> > <td class="ar-callnumber"> >- [% IF ar.item.location %] >- <em>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ar.item.location ) | html %]</em> >+ [% IF ar.item.effective_location %] >+ <em>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ar.item.effective_location ) | html %]</em> > [% END %] > > [% ar.item.itemcallnumber | html %] >@@ -380,8 +380,8 @@ > <td class="ar-collection">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => ar.item.ccode ) | html %]</td> > <td class="ar-itemtype">[% ItemTypes.GetDescription( ar.item.effective_itemtype ) | html %]</td> > <td class="ar-callnumber"> >- [% IF ar.item.location %] >- <em>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ar.item.location ) | html %]</em> >+ [% IF ar.item.effective_location %] >+ <em>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ar.item.effective_location ) | html %]</em> > [% END %] > > [% ar.item.itemcallnumber | html %] >@@ -484,8 +484,8 @@ > <td class="ar-collection">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => ar.item.ccode ) | html %]</td> > <td class="ar-itemtype">[% ItemTypes.GetDescription( ar.item.effective_itemtype ) | html %]</td> > <td class="ar-callnumber"> >- [% IF ar.item.location %] >- <em>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ar.item.location ) | html %]</em> >+ [% IF ar.item.effective_location %] >+ <em>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => ar.item.effective_location ) | html %]</em> > [% 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 %]</a > ></td > > >- <td class="tf-location"><span class="shelvingloc">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => trsfitemloo.item.location ) | html %]</span></td> >+ <td class="tf-location"><span class="shelvingloc">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => trsfitemloo.item.effective_location ) | html %]</span></td> > <td class="tf-itemcallnumber">[% trsfitemloo.item.itemcallnumber | html %]</td> > <td class="tf-itemtype">[% ItemTypes.GetDescription( trsfitemloo.item.effective_itemtype ) | html %]</td> > <td class="tf-ccode">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => trsfitemloo.item.ccode ) | html %]</td> >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 @@ > <a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% item.biblionumber | uri %]&itemnumber=[% item.itemnumber | uri %]#item[% item.itemnumber | uri %]">[% item.barcode | html %]</a> > </td> > <td>[% Branches.GetName(item.branchcode) | html %]</td> >- <td>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.location ) | html %]</td> >+ <td>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => (item.effective_location || item.location) ) | html %]</td> > </tr> > [% END %] > </tbody> >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 @@ > > > <td>[% Branches.GetName( overdueloo.homebranchcode ) | html %]</td> > <td>[% Branches.GetName( overdueloo.holdingbranchcode ) | html %]</td> >- <td>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => overdueloo.location ) | html %]</td> >+ <td> >+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => overdueloo.effective_location ) | html %] >+ </td> > <td data-order="[% overdueloo.datelastborrowed | html %]">[% overdueloo.datelastborrowed | $KohaDates %]</td> > <td > ><a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=[% overdueloo.biblionumber | uri %]&itemnumber=[% overdueloo.itemnum | uri %]#item[% overdueloo.itemnum | uri %]" >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingbookings.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingbookings.tt >index 2fceb2ae90e..932653c1168 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingbookings.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingbookings.tt >@@ -235,7 +235,7 @@ > } > }, > { >- "data": "item.location", >+ "data": "item.effective_location", > "title": _("Location"), > "searchable": false, > "orderable": false, >@@ -244,7 +244,7 @@ > if ( row.item.checked_out_date ) { > return _("On loan, due: ") + $date(row.item.checked_out_date); > } else { >- return row.item._strings.location.str; >+ return row.item._strings.effective_location.str; > } > } else { > return null; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingreserves.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingreserves.tt >index 2b74dbe86c7..95c8f39dddd 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingreserves.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/pendingreserves.tt >@@ -83,6 +83,9 @@ > <th>Earliest hold date</th> > <th>Hold notes</th> > <th class="string-sort">Pickup location</th> >+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %] >+ <th class="no-sort">Displays</th> >+ [% END %] > <th class="no-sort">Action</th> > </tr> > </thead> >@@ -184,8 +187,8 @@ > </td> > <td> > <ul> >- [% FOREACH loc IN hold_info.locations %] >- <li>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => loc ) | html %]</li> >+ [% FOREACH effective_location IN hold_info.effective_locations %] >+ <li>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => effective_location ) | html %]</li> > [% END %] > </ul> > </td> >@@ -199,6 +202,23 @@ > <td data-order="[% hold.reservedate | html %]"> [% hold.reservedate | $KohaDates %] in [% Branches.GetName ( hold.branchcode ) | html %] </td> > <td>[% hold.reservenotes | html %]</td> > <td> [% Branches.GetName ( hold.branchcode ) | html %] </td> >+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %] >+ <td> >+ [% IF ( hold_info.displays ) %] >+ [% IF hold_info.displays.size > 1 %] >+ <span>In displays:</span> >+ [% ELSE %] >+ <span>In display:</span> >+ [% END %] >+ [% FOR display IN hold_info.displays %] >+ <a href="/cgi-bin/koha/display/displays/[% display.display_id | url %]">[% display.display_name | html %]</a> >+ [% UNLESS loop.last %], [% END %] >+ [% END %] >+ [% ELSE %] >+ <em>Not in any displays</em> >+ [% END %] >+ </td> >+ [% END %] > <td> > <form name="cancelReserve" action="/cgi-bin/koha/circ/pendingreserves.pl" method="post"> > [% INCLUDE 'csrf-token.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt >index eb71cb8dbc7..098b01e1e84 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt >@@ -267,6 +267,13 @@ > </div> > [% END %] > >+ [% IF RemovedFromDisplay %] >+ <div id="removed_from_display" class="alert alert-info"> >+ <h3>Item removed from display</h3> >+ <p>This item has been removed from the display: <strong>[% RemovedFromDisplay.display_name | html %]</strong></p> >+ </div> >+ [% END %] >+ > [% IF ( errmsgloop ) %] > <div class="alert alert-warning audio-alert-warning"> > <h3>Check in message</h3> >@@ -1383,7 +1390,7 @@ > [%- END -%] > </td> > <td class="ci-shelvinglocation"> >- <span class="shelvingloc">[% checkin.item_location | html %]</span> >+ <span class="shelvingloc"> [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => checkin.item.effective_location ) | html %] </span> > </td> > <td class="ci-callnumber"> [% checkin.item.itemcallnumber | html %] </td> > <td class="ci-dateaccessioned"> [% checkin.item.dateaccessioned | $KohaDates %] </td> >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 @@ > <th class="hq-patroncategory">Patron category</th> > <th class="hq-sendto">Send to</th> > <th class="hq-date">Date</th> >+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %] >+ <th class="hq-displays">Displays</th> >+ [% END %] > <th class="hq-notes">Notes</th> > </tr> > <tr> >@@ -204,6 +207,13 @@ > <input type="text" placeholder="Date" /> > </span> > </td> >+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %] >+ <td class="hq-displays"> >+ <span class="filter_column filter_text"> >+ <input type="text" placeholder="Displays" /> >+ </span> >+ </td> >+ [% END %] > <td class="hq-notes"> > <span class="filter_column filter_text"> > <input type="text" placeholder="Notes" /> >@@ -240,7 +250,9 @@ > <td class="hq-holdingbranch">[% Branches.GetName( itemsloo.holdingbranch ) | html %]</td> > <td class="hq-homebranch">[% Branches.GetName( itemsloo.item.homebranch ) | html %]</td> > <td class="hq-collection">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => itemsloo.item.ccode ) | html %]</td> >- <td class="hq-location">[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => itemsloo.item.location ) | html %]</td> >+ <td class="hq-location"> >+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => itemsloo.item.effective_location ) | html %] >+ </td> > <td class="hq-itemtype">[% ItemTypes.GetDescription( itemsloo.item.effective_itemtype ) | html %]</td> > <td class="hq-callnumber"><span class="itemcallnumber">[% itemsloo.item.itemcallnumber | html %]</span></td> > <td class="hq-copynumber">[% itemsloo.item.copynumber | html %]</td> >@@ -287,6 +299,25 @@ > <td class="hq-patroncategory">[% itemsloo.patron.category.description | html %] ([% itemsloo.patron.categorycode | html %])</td> > <td class="hq-sendto">[% Branches.GetName( itemsloo.pickbranch ) | html %]</td> > <td class="hq-date" data-order="[% itemsloo.reservedate | html %]">[% itemsloo.reservedate | $KohaDates %]</td> >+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %] >+ <td> >+ [% FOREACH itemsdisplay IN itemsdisplays %] >+ [% IF (itemsloo.itemnumber == itemsdisplay.itemnumber) %] >+ [% IF itemsdisplay.displays.size > 1 %] >+ <span>In displays:</span> >+ [% ELSE %] >+ <span>In display:</span> >+ [% END %] >+ [% FOREACH display IN itemsdisplay.displays %] >+ <a href="/cgi-bin/koha/display/displays/[% display.display_id | url %]">[% display.display_name | html %]</a> >+ [% UNLESS loop.last %], [% END %] >+ [% END %] >+ [% ELSE %] >+ <span><em>Item not in display</em></span> >+ [% END %] >+ [% END %] >+ </td> >+ [% END %] > <td class="hq-notes">[% itemsloo.notes | html %]</td> > </tr> > [% 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' %] >+<title> Displays › Koha </title> >+[% INCLUDE 'doc-head-close.inc' %] >+</head> >+ >+<body id="display_home" class="display"> >+[% WRAPPER 'header.inc' %] >+ [% INCLUDE 'display-search.inc' %] >+[% END %] >+ >+<div id="display"></div> >+ >+[% MACRO jsinclude BLOCK %] >+ [% INCLUDE 'calendar.inc' %] >+ [% INCLUDE 'datatables.inc' %] >+ [% INCLUDE 'js-date-format.inc' %] >+ [% INCLUDE 'js-biblio-format.inc' %] >+ <script> >+ const authorised_value_categories = [% To.json(AuthorisedValues.GetCategories()) | $raw %].map(c => c.category); >+ const db_columns = [% To.json(db_columns) | $raw %]; >+ const api_mappings = [% To.json(api_mappings) | $raw %]; >+ >+ const csrf_token = "[% Koha.GenerateCSRF | $raw %]"; >+ </script> >+ [% 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 @@ > </li> > [% END %] > >+ [% IF Koha.Preference('UseDisplayModule') && CAN_user_displays %] >+ <li> >+ <a class="icon_general icon_display" href="/cgi-bin/koha/display/display-home.pl"><i class="fa-solid fa-fw fa-image-portrait"></i>Displays</a> >+ </li> >+ [% END %] >+ > [% IF ( CAN_user_tools || CAN_user_clubs ) %] > <li> > <a class="icon_general icon_tools" href="/cgi-bin/koha/tools/tools-home.pl"><i class="fa fa-fw fa-wrench"></i>Tools</a> >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 @@ > </td> > <td class="recall-locations"> > <ul> >- [% FOREACH loc IN recall.locations %] >- <li>[% AuthorisedValues.GetByCode('LOC', loc) | html %]</li> >+ [% FOREACH location IN recall.locations %] >+ <li>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => location ) | html %]</li> > [% END %] > </ul> > </td> >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 @@ > <td>[% ItemTypes.GetDescription(item.effective_itemtype) | html %]</td> > <td>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.ccode', authorised_value => item.ccode ) | html %]</td> > <td>[% Branches.GetName(item.holdingbranch) | html %]</td> >- <td>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.location ) | html %]</td> >+ <td> >+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.effective_location ) | html %] >+ </td> > <td>[% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.notforloan', authorised_value => item.notforloan ) | html %] </td><td>[% item.itemnotes | $raw %]</td> > </tr> > [% 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 %] > <li> > [% Branches.GetName(item.holdingbranch) | html %] >- <span class="shelvingloc"> [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.location ) | html %] </span> >+ <span class="shelvingloc"> >+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.effective_location ) | html %] >+ </span> > [% 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 %] > <label for="moduleALL" class="viewlog"><input type="checkbox" id="moduleALL" name="modules" value="" /> All</label> > [% 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 %] > <label for="module[% modx | html %]" class="viewlog" > ><input type="checkbox" id="module[% modx | html %]" name="modules" value="[% modx | html %]" checked="checked" /> [% PROCESS translate_log_module module=modx %]</label >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/shelves.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/shelves.tt >index f002d0abf31..ca057f0d3ec 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/shelves.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/shelves.tt >@@ -388,8 +388,10 @@ > [% FOREACH item IN itemsloo.ITEM_RESULTS %] > <li> > [% Branches.GetName(item.holdingbranch) | html %] >- [% IF ( item.location ) %] >- <span class="shelvingloc"> [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.location ) | html %] </span> >+ [% IF ( item.effective_location ) %] >+ <span class="shelvingloc"> >+ [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => item.effective_location ) | html %] >+ </span> > [% END %] > [% IF ( item.itemcallnumber ) %] > [<a href="/cgi-bin/koha/catalogue/search.pl?idx=callnum&q=%22[% item.itemcallnumber | uri %]%22">[% item.itemcallnumber | html %]</a>] >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)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 14962
:
190216
|
190217
|
190218
|
190219
|
190220
|
190221
|
190222
|
190223
|
190224
|
190225
| 190226 |
190227
|
190228
|
190229
|
190230
|
190231
|
190232