Bug 33568: Course reserves
[koha.git] / koha-tmpl / intranet-tmpl / prog / en / modules / catalogue / detail.tt
1 [% USE raw %]
2 [% USE Asset %]
3 [% USE To %]
4 [% USE Koha %]
5 [% USE KohaDates %]
6 [% USE KohaPlugins %]
7 [% USE AuthorisedValues %]
8 [% USE Branches %]
9 [% USE Biblio %]
10 [% USE Frameworks %]
11 [% USE Price %]
12 [% USE TablesSettings %]
13 [% PROCESS 'i18n.inc' %]
14 [% SET CoverImagePlugins = KohaPlugins.get_plugins_intranet_cover_images %]
15
16 [% IF Koha.Preference('AmazonAssocTag') %]
17     [% AmazonAssocTag = '?tag=' _ Koha.Preference('AmazonAssocTag') %]
18 [% ELSE %]
19     [% AmazonAssocTag = '' %]
20 [% END %]
21
22 [% SET plugins_intranet_catalog_biblio_tabs = KohaPlugins.get_plugins_intranet_catalog_biblio_tab({ biblio => biblio, biblio_id => biblionumber }) %]
23
24 [% SET footerjs = 1 %]
25 [% INCLUDE 'doc-head-open.inc' %]
26 <title>[% FILTER collapse %]
27     [% IF ( unknownbiblionumber ) %]
28         [% t("Unknown record") | html %]
29     [% ELSE %]
30         [% title_in_title = INCLUDE 'biblio-title-head.inc' %]
31         [% tx("Details for {title}", { title = title_in_title }) | html %]
32     [% END %] &rsaquo;
33     [% t("Catalog") | html %] &rsaquo;
34     [% t("Koha") | html %]
35 [% END %]</title>
36 [% Asset.css("lib/Chocolat/css/chocolat.css") | $raw %]
37 [% INCLUDE 'doc-head-close.inc' %]
38 </head>
39
40 <body id="catalog_detail" class="catalog">
41
42 [% WRAPPER 'header.inc' %]
43     [% INCLUDE 'cat-search.inc' %]
44 [% END %]
45
46 [% WRAPPER 'sub-header.inc' %]
47     [% WRAPPER breadcrumbs %]
48         [% WRAPPER breadcrumb_item %]
49             <a href="/cgi-bin/koha/catalogue/search.pl">Catalog</a>
50         [% END %]
51
52         [% IF ( unknownbiblionumber ) %]
53             [% WRAPPER breadcrumb_item bc_active= 1 %]
54                 <span>Unknown record</span>
55             [% END %]
56         [% ELSE %]
57             [% WRAPPER breadcrumb_item %]
58                 [% INCLUDE 'biblio-title.inc' link = 1 %]
59             [% END %]
60             [% WRAPPER breadcrumb_item bc_active= 1 %]
61                 <span>Details</span>
62             [% END %]
63         [% END %]
64     [% END #/ WRAPPER breadcrumbs %]
65 [% END #/ WRAPPER sub-header.inc %]
66
67 <div class="main container-fluid">
68     <div class="row">
69         <div class="col-sm-10 col-sm-push-2">
70             <main>
71                 [% INCLUDE 'messages.inc' %]
72                 <div class="row">
73
74 [% IF ( unknownbiblionumber ) %]
75   <div class="dialog message">The record you requested does not exist ([% biblionumber | html %]).</div>
76 [% ELSE %]
77
78 [% IntranetCoce    = Koha.Preference('IntranetCoce') %]
79 [% CoceProviders   = Koha.Preference('CoceProviders') %]
80 [% CoceHost        = Koha.Preference('CoceHost') %]
81 [% SyndeticsCovers = Koha.Preference('SyndeticsEnabled') && Koha.Preference('SyndeticsCoverImages') %]
82
83 [% INCLUDE 'cat-toolbar.inc' %]
84     [% IF ( ocoins ) %]
85         <!-- COinS / OpenURL -->
86         <span class="Z3988" title="[% ocoins | html %]"></span>
87     [% END %]
88
89     [% IF ( CoverImagePlugins || AmazonCoverImages  || LocalCoverImages || IntranetCoce || ( SyndeticsCovers ) || (Koha.Preference('CustomCoverImages') && Koha.Preference('CustomCoverImagesURL')) ) %]
90         <div id="catalogue_detail_biblio" class="col-xs-9">
91     [% ELSE %]
92         <div id="catalogue_detail_biblio" class="col-xs-12">
93     [% END %]
94         [% IF decoding_error || analytics_error %]
95             <div class="page-section bg-danger">
96                <h1>Errors found</h1>
97                [% IF decoding_error %]
98                    <h2>Encoding errors</h2>
99                    <p class="biberror">There is at least one encoding error with this bibliographic record, the view may be degraded.</p>
100                    <pre class="error">[% decoding_error | html %]</pre>
101                [% END %]
102                [% IF analytics_error %]
103                    <h2>Analytics errors</h2>
104                    <p class="analytics_error">There was an error searching for analytic records, please see the logs for details.</p>
105                [% END %]
106             </div>
107         [% END %]
108
109         <div class="page-section">
110
111         [% XSLTBloc | $raw %]
112
113         [% IF shelves.count %]
114             <span class="results_summary"><span class="label">Lists that include this title: </span>
115             [% FOREACH s IN shelves %]
116                 <a href="/cgi-bin/koha/virtualshelves/shelves.pl?op=view&amp;shelfnumber=[% s.shelfnumber | uri %]">[% s.shelfname | html %]</a>
117                 [% IF ( loop.last ) %][% ELSE %]|[% END %]
118             [% END %]
119             </span>
120         [% END %]
121         [% IF ( TagsEnabled &&  TagsShowOnDetail &&  TagLoop ) %]
122                 <span class="results_summary"><span class="label">Tags:</span>
123                     [% FOREACH TagLoo IN TagLoop %]
124                         [% IF ( CAN_user_tools_moderate_tags ) %]
125                         <a href="/cgi-bin/koha/tags/list.pl?tag=[% TagLoo.term |uri %]">[% TagLoo.term | html %]</a>
126                         [% ELSE %]
127                         [% TagLoo.term | html %]
128                         [% END %]
129                         <span class="weight">([% TagLoo.weight_total | html %])</span>[% IF ( loop.last ) %][% ELSE %], [% END %]
130                     [% END %]
131                     </span>
132         [% END %]
133         <span id="catalogue_detail_marc_preview" class="results_summary"><span class="label">MARC preview:</span> <a href="/cgi-bin/koha/catalogue/showmarc.pl?id=[% biblionumber | uri %]&amp;viewas=html" title="MARC" class="previewMARC">Show</a></span>
134         <span id="catalogue_detail_framework" class="results_summary">
135             <span class="label">MARC framework:</span>
136             <span class="frameworkcode">[% Frameworks.GetName(biblio.frameworkcode) | html %]</span>
137         </span>
138         [% IF !item_level_itypes ||  Koha.Preference("BiblioItemtypeInfo") %]
139            <span class="results_summary itemtype"><span class="label">Itemtype:</span>
140           [% IF ( !noItemTypeImages && imageurl ) %]
141               <img src="[% imageurl | html %]" alt="" />
142           [% END %]
143           [% IF ( description ) %]
144               <span class="itypetext">[% description | html %]</span>
145           [% ELSE %]
146               <span class="itypetext">[% itemtype | html %]</span>
147           [% END %]
148           </span>
149         [% END %]
150
151         [% IF ( Koha.Preference('SearchEngine') == 'Elasticsearch' ) %]
152             <span id="catalogue_detail_elastic_record" class="results_summary"><span class="label">Elasticsearch record:</span> <a href="/cgi-bin/koha/catalogue/showelastic.pl?id=[% biblionumber | uri %]" title="Elasticsearch record" class="previewElastic">Show</a></span>
153         [% END %]
154
155         [% IF ( holdcount ) %]
156             <span class="results_summary">
157                 <span class="label">Holds:</span>
158                 <span class="number_box">
159                     [% IF CAN_user_reserveforothers_place_holds %]
160                         <a href="/cgi-bin/koha/reserve/request.pl?biblionumber=[% biblionumber | uri %]">[% holdcount | html %]</a>
161                     [% ELSE %]
162                         <span>[% holdcount | html %]</span>
163                     [% END %]
164                 </span>
165             </span>
166         [% END %]
167
168         [% IF illrequests.count %]
169             <span class="results_summary">
170                 <span class="label">ILL requests:</span>
171                 [% IF CAN_user_ill %]
172                     [% FOREACH ill IN illrequests %]
173                         <a href="/cgi-bin/koha/ill/ill-requests.pl?method=illview&illrequest_id=[% ill.illrequest_id | uri %]">Request [% ill.illrequest_id | html %]</a>[% IF ! loop.last %], [% END %]
174                     [% END %]
175                 [% ELSE %]
176                     [% FOREACH ill IN illrequests %]
177                         <span>Request [% ill.illrequest_id | html %]</span>[% IF ! loop.last %], [% END %]
178                     [% END %]
179                 [% END %]
180             </span>
181         [% END %]
182
183         [% IF ( article_requests_count = biblio.article_requests.filter_by_current.count ) %]
184             <span class="results_summary">
185                 <span class="label">Article requests:</span>
186                 <span class="number_box">
187                     <a href="/cgi-bin/koha/circ/request-article.pl?biblionumber=[% biblionumber | uri %]">[% article_requests_count | html %]</a>
188                 </span>
189             </span>
190         [% END %]
191
192         [% IF course_reserves %]
193             <span class="results_summary"><span class="label">Courses that have reserved this title: </span>
194             [% FOREACH c IN course_reserves %]
195                 <a href="/cgi-bin/koha/course_reserves/course-details.pl?course_id=[% c.course_id | uri %]">[% c.course.course_name | html %]</a>
196                 [% IF ( loop.last ) %][% ELSE %]|[% END %]
197             [% END %]
198             </span>
199         [% END %]
200         </div> [%# .page-section %]
201
202         [% IF ( CoverImagePlugins || AmazonCoverImages  || LocalCoverImages || IntranetCoce || ( SyndeticsCovers ) || (Koha.Preference('CustomCoverImages') && Koha.Preference('CustomCoverImagesURL')) ) %]
203         </div>
204             <div class="col-xs-3 bookcoverimg">
205                 <div id="biblio-cover-slider" class="cover-slider" data-isbn="[% normalized_isbn | html %]">
206                     [% IF ( LocalCoverImages ) %]
207                         [% IF localimages.count %]
208                             [% FOREACH image IN localimages %]
209                                 <div class="cover-image local-coverimg">
210                                     <a href="/cgi-bin/koha/catalogue/image.pl?imagenumber=[% image.imagenumber | uri %]" title="Local cover image">
211                                         <img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&amp;imagenumber=[% image.imagenumber | uri %]" alt="Local cover image" data-link="/cgi-bin/koha/catalogue/imageviewer.pl?biblionumber=[% biblionumber | uri %]&amp;imagenumber=[% image.imagenumber | uri %]" />
212                                     </a>
213                                     <div class="hint">Local cover image</div>
214                                 </div>
215                             [% END %]
216                         [% END %]
217                     [% END %]
218
219                     [% IF ( AmazonCoverImages && normalized_isbn) %]
220                         <div class="cover-image" id="amazon-bookcoverimg">
221                             <a href="https://images-na.ssl-images-amazon.com/images/P/[% normalized_isbn | uri %].01.LZZZZZZZ.jpg" title="Amazon cover image">
222                                 <img src="https://images-na.ssl-images-amazon.com/images/P/[% normalized_isbn | uri %].01.MZZZZZZZ.jpg" alt="Amazon cover image" data-link="http://www.amazon[% AmazonTld | uri %]/gp/reader/[% normalized_isbn | uri %][% AmazonAssocTag | uri %]#reader-link"/>
223                             </a>
224                             <div class="hint">Image from Amazon.com</div>
225                         </div>
226                     [% END %]
227
228                     [% IF ( IntranetCoce && CoceProviders && normalized_isbn ) %]
229                         [% coce_id = normalized_ean || normalized_isbn %]
230                         <div class="cover-image coce-coverimg">
231                             [% IF ( coce_id ) %]
232                                 <a title="Image from Coce" class="[% coce_id | html %]" id="coce-thumbnail-preview"></a>
233                             [% ELSE %]
234                                 <span class="no-image">No cover image available</span>
235                             [% END %]
236                             <div class="hint">Image from Coce</div>
237                         </div>
238                     [% END %]
239
240                     [% IF ( SyndeticsCovers ) %]
241                         [% IF ( content_identifier_exists ) %]
242                         <div class="cover-image" id="syndetics-bookcoverimg">
243                             <a href="https://secure.syndetics.com/index.aspx?isbn=[% normalized_isbn | url %]/LC.GIF&amp;client=[% Koha.Preference('SyndeticsClientCode') | url %]&amp;type=xw10&amp;upc=[% normalized_upc | url %]&amp;oclc=[% normalized_oclc | url %]" title="Syndetics cover image">
244                                 <img src="https://secure.syndetics.com/index.aspx?isbn=[% normalized_isbn | url %]/[% Koha.Preference('SyndeticsCoverImageSize') | url %].GIF&amp;client=[% Koha.Preference('SyndeticsClientCode') | url %]&amp;type=xw10&amp;upc=[% normalized_upc | url %]&amp;oclc=[% normalized_oclc | url %]" alt="" class="thumbnail" />
245                             </a>
246                             <div class="hint">Image from Syndetics</div>
247                         </div>
248                             [% ELSE %]
249                                 <span class="no-image">No cover image available</span>
250                             [% END %]
251                     [% END %]
252
253                     [% IF Koha.Preference('CustomCoverImages') && Koha.Preference('CustomCoverImagesURL') %]
254                         [% SET custom_cover_image_url = biblio.custom_cover_image_url %]
255                         [% IF custom_cover_image_url %]
256                             <div class="cover-image" id="custom-coverimg">
257                                 <a class="custom_cover_image" href="[% custom_cover_image_url | url %]" title="Custom cover image">
258                                     <img id="custom-img" alt="Custom cover image" src="[% custom_cover_image_url | url %]" />
259                                 </a>
260                                 <div class="hint">Custom cover image</div>
261                             </div>
262                         [% END %]
263                     [% END %]
264                 </div> <!-- /.cover-slider -->
265             </div> <!-- /.bookcoverimg.col-xs-3 -->
266         [% ELSE %]
267         </div> <!-- /.col-xs-* -->
268         [% END # /IF ( AmazonCoverImages, etc ) %]
269 </div>
270
271 <div id="bibliodetails" class="toptabs">
272
273 <ul class="nav nav-tabs" role="tablist">
274     [% IF Koha.Preference('SeparateHoldings') %]
275         <li role="presentation">
276             [%# FIXME We could build the numbers from DataTable's info %]
277             <a href="#holdings" aria-controls="holdings" role="tab" data-toggle="tab">[% Branches.GetLoggedInBranchname | html %] holdings ([% items_to_display_count - ( other_holdings_count || 0 ) - ( hidden_count || 0 ) || 0 | html %])</a>
278         </li>
279         <li role="presentation">
280             <a href="#otherholdings"  aria-controls="otherholdings" role="tab" data-toggle="tab">Other holdings ([% other_holdings_count || 0 | html %])</a>
281         </li>
282     [% ELSE %]
283         <li role="presentation">
284             <a href="#holdings" aria-controls="holdings" role="tab" data-toggle="tab">Holdings ([% items_to_display_count || 0 | html %])</a>
285         </li>
286     [% END %]
287     [% IF Koha.Preference('EnableItemGroups') %]
288         <li role="presentation">
289             <a href="#item_groups" aria-controls="item_groups" role="tab" data-toggle="tab">Item groups</a>
290         </li>
291     [% END %]
292 [% IF ( MARCNOTES || notes ) %]<li role="presentation"><a href="#description" aria-controls="description" role="tab" data-toggle="tab">Descriptions ([% ( MARCNOTES.size || 1 ) | html %])</a></li>[% END %]
293 [% IF ComponentParts && ComponentParts.size %]<li id="components_tab" role="presentation"><a href="#components"  aria-controls="components" role="tab" data-toggle="tab">Components ([% ComponentParts.size | html %])</a></li>[% END %]
294 [% IF ( subscriptionsnumber ) %]<li role="presentation"><a href="#subscriptions"  aria-controls="subscriptions" role="tab" data-toggle="tab">Subscriptions</a></li>[% END %]
295 [% IF Koha.Preference('AcquisitionDetails') %]<li role="presentation"><a href="#acq_details"  aria-controls="acq_details" role="tab" data-toggle="tab">Acquisition details</a></li>[% END %]
296 [% IF suggestions.count %]<li role="presentation"><a href="#suggestion_details"  aria-controls="suggestion_details" role="tab" data-toggle="tab">Suggestion details</a></li>[% END %]
297 [% IF ( FRBRizeEditions ) %][% IF ( XISBNS ) %]<li role="presentation"><a href="#editions"  aria-controls="editions" role="tab" data-toggle="tab">Editions</a></li>[% END %][% END %]
298 [% IF ( ( Koha.Preference('CatalogConcerns') || Koha.Preference('OpacCatalogConcerns') ) && CAN_user_editcatalogue_edit_catalogue ) %]<li role="presentation"><a href="#concerns" aria-controls="concerns" role="tab" data-toggle="tab">Concerns ([% biblio.tickets.count | html %])</a></li>[% END %]
299 [% IF ( LocalCoverImages ) %]
300     <li role="presentation">
301         <a href="#images"  aria-controls="images" role="tab" data-toggle="tab">Images ([% localimages.count || 0 | html %])</a>
302     </li>
303 [% END %]
304 [% IF HTML5MediaEnabled && HTML5MediaSets.size %]
305     <li id="media_tab" role="presentation"><a href="#html5media"  aria-controls="html5media" role="tab" data-toggle="tab">Play media</a></li>
306 [% END %]
307 [% IF ( Koha.Preference('NovelistSelectStaffEnabled') && Koha.Preference('NovelistSelectStaffProfile') && Koha.Preference('NovelistSelectStaffView') == 'tab' ) %]
308     <li class="NovelistSelect" style="display:none;" role="presentation"><a href="#NovelistSelect"  aria-controls="NovelistSelect" role="tab" data-toggle="tab">NoveList Select</a></li>
309 [% END %]
310 [% FOREACH plugins_intranet_catalog_biblio_tab IN plugins_intranet_catalog_biblio_tabs %]
311     <li role="presentation"><a href="#[% plugins_intranet_catalog_biblio_tab.id | uri %]"  aria-controls="[% plugins_intranet_catalog_biblio_tab.id | uri %]" role="tab" data-toggle="tab">[% plugins_intranet_catalog_biblio_tab.title | html %]</a></li>
312 [% END %]
313 </ul>
314
315 <div class="tab-content">
316 [% items_table_block_iter = 0 %]
317 [% BLOCK items_table %]
318     [% items_table_block_iter = items_table_block_iter + 1 %]
319     <div class="[% tab | html %]_table_table_controls">
320         [% IF (StaffDetailItemSelection) %]
321             | <a href="#" class="SelectAll" data-tab="[% tab | html %]"><i class="fa fa-check"></i> Select all</a> |
322             <a href="#" class="ClearAll" data-tab="[% tab | html %]"><i class="fa fa-times"></i> Clear all</a>
323             <span class="itemselection_actions">
324               | Actions:
325               [% IF CAN_user_tools_items_batchdel %]
326                 <a class="itemselection_action_delete"><i class="fa fa-trash-can"></i> Delete selected items</a>
327               [% END %]
328               [% IF CAN_user_tools_items_batchmod %]
329                 <a class="itemselection_action_modify"><i class="fa-solid fa-pencil" aria-hidden="true"></i> Modify selected items</a>
330               [% END %]
331               [% IF CAN_user_editcatalogue_manage_item_groups && biblio.item_groups.count %]
332                 <a class="itemselection_action_item_group_set" href="#"><i class="fa fa-book"></i> Add/move to item group</a>
333                 <a class="itemselection_action_item_group_unset" href="#"><i class="fa fa-unlink"></i> Remove from item group</a>
334               [% END %]
335             </span>
336         [% END %]
337     </div>
338
339     <table class="items_table" id="[% tab | html %]_table">
340         <thead>
341             [% IF (StaffDetailItemSelection) %]<th id="[% tab | html %]_checkbox" data-colname="[% tab | html %]_checkbox" class="NoSort"></th>[% END %]
342             [% IF Koha.Preference('LocalCoverImages') %]
343                 <th id="[% tab | html %]_cover_image" data-colname="[% tab | html %]_cover_image">Cover image</th>
344             [% END %]
345             [% IF ( item_level_itypes ) %]<th id="[% tab | html %]_itype" data-colname="[% tab | html %]_itype">Item type</th>[% END %]
346             <th id="[% tab | html %]_holdingbranch" data-colname="[% tab | html %]_holdingbranch">Current library</th>
347             <th id="[% tab | html %]_homebranch" data-colname="[% tab | html %]_homebranch">Home library</th>
348             <th id="[% tab | html %]_ccode" data-colname="[% tab | html %]_ccode">Collection</th>
349             [% IF Koha.Preference('EnableItemGroups') %]
350                 <th id="[% tab | html %]_item_group" data-colname="[% tab | html %]_item_group">Item group</th>
351             [% END %]
352             <th id="[% tab | html %]_itemcallnumber" data-colname="[% tab | html %]_itemcallnumber">Call number</th>
353             <th id="[% tab | html %]_enumchron" data-colname="[% tab | html %]_enumchron">Serial enumeration / chronology</th>
354             <th id="[% tab | html %]_status" data-colname="[% tab | html %]_status">Status</th>
355             <th id="[% tab | html %]_lastseen" data-colname="[% tab | html %]_lastseen">Last seen</th>
356             <th id="[% tab | html %]_issues" data-colname="[% tab | html %]_issues">Checkouts</th>
357             <th id="[% tab | html %]_renewals" data-colname="[% tab | html %]_renewals">Renewals</th>
358             <th id="[% tab | html %]_dateaccessioned" data-colname="[% tab | html %]_dateaccessioned">Date accessioned</th>
359             <th id="[% tab | html %]_datelastborrowed" data-colname="[% tab | html %]_datelastborrowed">Date last borrowed</th>
360             <th id="[% tab | html %]_barcode" data-colname="[% tab | html %]_barcode">Barcode</th>
361             <th id="[% tab | html %]_uri" data-colname="[% tab | html %]_uri">URL</th>
362             <th id="[% tab | html %]_copynumber" data-colname="[% tab | html %]_copynumber">Copy number</th>
363             <th id="[% tab | html %]_stocknumber" data-colname="[% tab | html %]_stocknumber">Inventory number</th>
364             <th id="[% tab | html %]_materials" data-colname="[% tab | html %]_materials">Materials specified</th>
365             <th id="[% tab | html %]_itemnotes" data-colname="[% tab | html %]_itemnotes">Public notes</th>
366             <th id="[% tab | html %]_itemnotes_nonpublic" data-colname="[% tab | html %]_itemnotes_nonpublic">Non-public notes</th>
367             [% IF ( hostrecords ) %]<th id="[% tab | html %]_hostrecord" data-colname="[% tab | html %]_hostrecord">Host records</th>[% END %]
368             [% IF ( analyze ) %]<th id="[% tab | html %]_usedin" data-colname="[% tab | html %]_usedin">Used in</th><th></th>[% END %]
369             [% IF Koha.Preference('UseCourseReserves') %]<th id="[% tab | html %]_course_reserves" data-colname="[% tab | html %]_course_reserves">Course reserves</th>[% END %]
370             [% IF ( SpineLabelShowPrintOnBibDetails ) %]<th id="[% tab | html %]_spinelabel" data-colname="[% tab | html %]_spinelabel" class="NoSort">Spine label</th>[% END %]
371             [% IF ( CAN_user_editcatalogue_edit_items ) %]<th id="[% tab | html %]_actions" data-colname="[% tab | html %]_actions"class="NoSort noExport">&nbsp;</th>[% END %]
372             </tr>
373         </thead>
374     </table>
375 [% END %][%# end of block items_table %]
376
377 [% IF Koha.Preference('EnableItemGroups') %]
378     <div role="tabpanel" class="tab-pane" id="item_groups">
379         [% IF CAN_user_editcatalogue_manage_item_groups %]
380             <div class="item_groups_table_table_controls">
381                 <a href="#" class="item-group-create btn btn-default btn-xs"><i class="fa fa-plus"></i> New item group</a>
382             </div>
383         [% END %]
384         <table class="items-group-table" id="items-group-table">
385             <thead>
386                 <tr>
387                     <th>Display order</th>
388                     <th>Description</th>
389                     <th class="NoSort">&nbsp;</th>
390                 </tr>
391             </thead>
392         </table>
393     </div>
394 [% END %]
395
396
397 <div role="tabpanel" class="tab-pane" id="holdings">
398
399 [% IF ( Koha.Preference('NovelistSelectStaffEnabled') && Koha.Preference('NovelistSelectStaffProfile') && Koha.Preference('NovelistSelectStaffView') == 'above' ) %]
400     <span class="results_summary NovelistSelect" style="display:none;">
401         <span class="label">Novelist Select: </span>
402         <div data-novelist-novelistselect=[% normalized_isbn | html %]></div>
403     </span>
404 [% END %]
405
406 [% SET hidden_count = all_items_count - items_to_display_count %]
407 [% IF all_items_count %]
408     [% PROCESS items_table tab="holdings" %]
409
410     [% IF hidden_count %]
411         [%# FIXME We could deal with that in JS and prevent a full refresh %]
412         <p><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% biblionumber | uri %]&amp;showallitems=1">Show all items ([% hidden_count | html %] hidden)</a>
413     [% END %]
414 [% ELSE %]
415     [% IF ( ALTERNATEHOLDINGS ) %]
416     [% FOREACH ALTERNATEHOLDING IN ALTERNATEHOLDINGS %]
417         <div id="alternateholdings"><span class="holdings_label">Holdings:</span> [% ALTERNATEHOLDING.holding | html %]</div>
418     [% END %]
419     [% ELSE %]
420     <div id="noitems">No physical items for this record</div>
421     [% END %]
422 [% END %]
423
424 [% IF ( Koha.Preference('NovelistSelectStaffEnabled') && Koha.Preference('NovelistSelectStaffProfile') && Koha.Preference('NovelistSelectStaffView') == 'below' ) %]
425     <span class="results_summary NovelistSelect" style="display:none;">
426         <span class="label">Novelist Select: </span>
427         <div data-novelist-novelistselect=[% normalized_isbn | html %]></div>
428     </span>
429 [% END %]
430     </div>
431
432 [% IF Koha.Preference('SeparateHoldings') %]
433     <div role="tabpanel" class="tab-pane" id="otherholdings">
434         [% PROCESS items_table tab="otherholdings" %]
435     </div>
436 [% END %]
437
438 [% IF ( MARCNOTES ) %]
439
440 <div role="tabpanel" class="tab-pane" id="description">
441 <div class="content_set">
442
443     [% FOREACH MARCNOTE IN MARCNOTES %]
444         <p class="marcnote marcnote-[% MARCNOTE.tag | html %]" id="marcnote-[% MARCNOTE.tag | html %]-[% loop.count | html %]">
445             [% IF MARCNOTE.marcnote.match('^https?://\S+$') %]
446                 <a href="[% MARCNOTE.marcnote | url %]">[% MARCNOTE.marcnote | html %]</a>
447             [% ELSE %]
448                 [% MARCNOTE.marcnote | html | html_line_break %]
449             [% END %]
450         </p>
451 [% END %]
452 </div>
453 </div>
454
455 [% END %]
456
457 [% IF ComponentParts && ComponentParts.size %]
458 <div role="tabpanel" class="tab-pane" id="components">
459     <div class="content_set">
460         <table>
461             [% FOR PART IN ComponentParts %]
462             <tr>
463                 <td>
464                     [% PART | $raw %]
465                 </td>
466             </tr>
467             [% END %]
468         </table>
469         [% IF ComponentParts.size == Koha.Preference('MaxComponentRecords')%]
470         <p>Only [% ComponentParts.size | html %] results are shown: <a href="/cgi-bin/koha/catalogue/search.pl?q=[% ComponentPartsQuery | url %]"/>show all component parts</a></p>
471         [% END %]
472     </div> <!-- /.content_set -->
473 </div> <!-- /#components -->
474
475 [% END %]
476
477 [% IF ( subscriptionsnumber ) %]
478 <div role="tabpanel" class="tab-pane" id="subscriptions">
479 <div id="catalogue_detail_subscriptions">
480     <h2>This is a serial subscription</h2>
481     <p> (There are [% subscriptionsnumber | html %] subscriptions associated with this title).</p> 
482     [% FOREACH subscription IN subscriptions %]
483             [% IF subscription.branchcode %]
484                 <h3>At library: [% Branches.GetName(subscription.branchcode) || subscription.branchcode | html %]</h3>
485             [% END %]
486             [% IF ( subscription.closed ) %]<p>This subscription is closed.</p>[% END %]
487             [% IF ( subscription.location ) %]<p class="subscription_location">Location: [% AuthorisedValues.GetDescriptionByKohaField( kohafield => 'items.location', authorised_value => subscription.location ) | html %]</p>[% END %]
488             [% IF ( subscription.callnumber ) %]<p>Callnumber: [% subscription.callnumber | html %] </p>[% END %]
489             [% IF ( subscription.subscriptionnotes ) %]<p>[% subscription.subscriptionnotes | html | html_line_break %] </p>[% END %]
490             [% IF ( subscription.missinglist ) %]<p>Missing issues: [% subscription.missinglist | html %] </p>[% END %]
491             [% IF ( subscription.librariannote ) %]<p>([% subscription.librariannote | html %])</p>[% END %]
492             [% IF ( subscription.latestserials ) %]
493             <p> The [% subscription.staffdisplaycount | html %] latest issues related to this subscription:</p>
494             <table>
495                 <tr>
496                     <th>Issue #</th>
497                     <th>Date arrived</th>
498                     <th>Date published</th>
499                     <th>Date published (text)</th>
500                     <th>Status</th>
501                     <th>Note</th>
502                 </tr>
503             [% FOREACH latestserial IN subscription.latestserials %]
504                 <tr>
505                     <td>[% latestserial.serialseq | html %]</td>
506                     <td data-order="[% latestserial.planneddate | html %]">[% latestserial.planneddate | $KohaDates %]</td>
507                     <td data-order="[% latestserial.publisheddate | html %]">[% latestserial.publisheddate | $KohaDates %]</td>
508                     <td>[% latestserial.publisheddatetext | html %]</td>
509                     <td>
510                         [% INCLUDE 'serial-status.inc' serial = latestserial %]
511                     </td>
512                     <td>[% latestserial.notes | html %]</td>
513                 </tr>
514             [% END %]
515             </table>
516             [% END %]
517             [% IF ( CAN_user_serials ) %]
518                 <p>
519                     <a class="btn btn-link" href="/cgi-bin/koha/serials/subscription-detail.pl?subscriptionid=[% subscription.subscriptionid | uri %]"><i class="fa fa-list" aria-hidden="true"></i> Subscription details</a>
520                 </p>
521             [% END %]
522     [% END %]
523 </div>
524 </div>
525 [% END %]
526
527 [% IF Koha.Preference('AcquisitionDetails') %]
528 <div role="tabpanel" class="tab-pane" id="acq_details">
529   [% IF orders.count %]
530     <table id="orders">
531       <thead>
532         <tr>
533           <th>Vendor</th>
534           <th>Invoice</th>
535           <th>Basket group</th>
536           <th>Basket</th>
537           <th>Order number</th>
538           <th>Creation date</th>
539           <th>Receive date</th>
540           <th>Status</th>
541           <th>Quantity</th>
542           <th title="Estimated cost tax incl. while pending, actual cost tax incl. once received">Price</th>
543           <th>Internal note</th>
544           <th>Subscription</th>
545           <th>Subscription call number</th>
546         </tr>
547       </thead>
548       <tbody>
549       [% FOR order IN orders %]
550         [% SET basket = order.basket %]
551         [% SET vendor = basket.bookseller %]
552           <tr>
553             <td>
554                 <a href="/cgi-bin/koha/acqui/supplier.pl?booksellerid=[% vendor.id | uri %]" title="Vendor detail page">[% vendor.name | html %]</a>
555             </td>
556             <td>
557             [% IF order.invoiceid %]
558                 [% IF CAN_user_acquisition %]
559                     <div><a href="/cgi-bin/koha/acqui/invoice.pl?invoiceid=[% order.invoiceid | uri %]"
560                        title="Invoice detail page">
561                        [% order.invoice.invoicenumber | html %]</a></div>
562                 [% ELSE %]
563                     <div>[% order.invoice.invoicenumber | html %]</div>
564                 [% END %]
565
566                 [% IF ( Koha.Preference('EDIFACT') && CAN_user_acquisition_edi_manage && order.invoice.message_id ) %]
567                     <div><a href="/cgi-bin/koha/acqui/edimsg.pl?id=[% order.invoice.message_id | uri %]" title="EDI INVOICE message">EDI message</a></div>
568                 [% END %]
569             [% END %]
570             </td>
571             <td>
572             [% IF basket.basketgroupid %]
573                 [% SET basket_group = basket.basket_group %]
574                 [% IF CAN_user_acquisition_group_manage %]
575                     <a href="/cgi-bin/koha/acqui/basketgroup.pl?op=add&booksellerid=[% vendor.id | uri %]&basketgroupid=[% basket_group.id | uri %]">[% basket_group.name | html%] ([% basket_group.id | html %])</a>
576                 [% ELSE %]
577                     [% basket_group.name | html %] ([% basket_group.id | html %])
578                 [% END %]
579             [% END %]
580             </td>
581             <td>[% IF CAN_user_acquisition_order_manage %]
582                 <a href="/cgi-bin/koha/acqui/basket.pl?basketno=[% basket.basketno | uri %]">[% basket.basketname | html %] ([% basket.basketno | html %])</a>
583             [% ELSE %]
584                 [% basket.basketname | html %] ([% basket.basketno | html %])
585             [% END %]</td>
586             <td>[% order.ordernumber | html %]</td>
587             <td data-order="[% basket.creationdate | uri %]">[% basket.creationdate | $KohaDates%]</td>
588             <td data-order="[% order.datereceived | uri %]">[% order.datereceived | $KohaDates%]</td>
589             <td>
590               [% SWITCH order.orderstatus %]
591                 [% CASE 'new' %]<span>New</span>
592                 [% CASE 'ordered' %]<span>Ordered</span>
593                 [% CASE 'partial' %]<span>Partial</span>
594                 [% CASE 'complete' %]<span>Complete</span>
595                 [% CASE 'cancelled' %]<span>Cancelled</span>
596               [% END %]
597             </td>
598             <td>[% order.quantity | html %]</td>
599             <td>[% IF ( order.orderstatus == "complete" ) %][% order.unitprice_tax_included | $Price %][% ELSE %][% order.ecost_tax_included | $Price %][% END %]
600             <td>[% order.order_internalnote | html %]</td>
601             <td>
602                 [% IF order.subscriptionid %]
603                     <a href="/cgi-bin/koha/serials/subscription-detail.pl?subscriptionid=[% order.subscriptionid | uri %]">[% order.subscriptionid | html %]</a>
604                 [% END %]
605             </td>
606             <td>
607                 [% IF order.subscriptionid %]
608                     [% order.subscription.callnumber | html %]
609                 [% END %]
610             </td>
611           </tr>
612       [% END %]
613       </tbody>
614     </table>
615   [% ELSE %]
616     <span class="noorder">There is no order for this bibliographic record.</span>
617   [% END %]
618 </div>
619 [% END %]
620
621 [% IF suggestions.count %]
622     <div role="tabpanel" class="tab-pane" id="suggestion_details">
623         [% IF nb_archived_suggestions > 0 %]
624             <p>[% tnpx('pluralization', 'There is one archived suggestion.', 'There are {count} archived suggestions.', nb_archived_suggestions, { count = nb_archived_suggestions }) | $raw  %]
625         [% END %]
626         <table id="suggestions" class="sorted">
627             <thead>
628                 <tr>
629                     <th class="NoSort">&nbsp;</th>
630                     <th class="anti-the">Suggestion</th>
631                     <th>Suggested by - on</th>
632                     <th>Managed by - on</th>
633                     <th>Last modification by - on</th>
634                     <th>Library</th>
635                     <th>Fund</th>
636                     <th>Status</th>
637                 </tr>
638             </thead>
639             <tbody>
640             [% FOREACH suggestion IN suggestions %]
641                 <tr>
642                     <td>[% suggestion.suggestionid | html %]</td>
643                     <td>
644                         <a href="/cgi-bin/koha/suggestion/suggestion.pl?suggestionid=[% suggestion.suggestionid | uri %]&amp;op=show" title="suggestion" >
645                             [% suggestion.title | html %][% IF ( suggestion.author ) %], by [% suggestion.author | html %][% END %]</a>
646                         <br />
647                         [% IF ( suggestion.copyrightdate ) %]&copy; [% suggestion.copyrightdate | html %] [% END %]
648                         [% IF ( suggestion.volumedesc ) %]; Volume:<em>[% suggestion.volumedesc | html %]</em> [% END %]
649                         [% IF ( suggestion.isbn ) %]; ISBN:<em>[% suggestion.isbn | html %]</em> [% END %][% IF ( suggestion.publishercode ) %]; Published by [% suggestion.publishercode | html %] [% END %][% IF ( suggestion.publicationyear ) %] in <em>[% suggestion.publicationyear | html %]</em> [% END %][% IF ( suggestion.place ) %] in <em>[% suggestion.place | html %]</em> [% END %][% IF ( suggestion.collectiontitle ) %]; [% suggestion.collectiontitle | html %] [% END %][% IF ( suggestion.itemtype ) %]; [% AuthorisedValues.GetByCode( 'SUGGEST_FORMAT', suggestion.itemtype, 0 ) | html %] [% END %]<br />[% IF ( suggestion.note ) %]<div class="suggestion_note"><i class="fa fa-comment"></i> [% suggestion.note | html %]</div>[% END %]
650                     </td>
651                     <td>
652                         <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% suggestion.suggestedby | uri %]">[% INCLUDE 'patron-title.inc' patron => suggestion.suggester %]</a>
653                         [% IF suggestion.suggesteddate %] - [% suggestion.suggesteddate | $KohaDates %][% END %]
654                     </td>
655                     <td>
656                         <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% suggestion.managedby | uri %]">[% INCLUDE 'patron-title.inc' patron => suggestion.manager %]</a>
657                         [% IF suggestion.manageddate %] - [% suggestion.manageddate | $KohaDates %][% END %]
658                     </td>
659                     <td>
660                         <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% suggestion.lastmodificationby | uri %]">[% INCLUDE 'patron-title.inc' patron => suggestion.last_modifier %]</a>
661                         [% IF suggestion.lastmodificationdate %] - [% suggestion.lastmodificationdate | $KohaDates %][% END %]
662                     </td>
663                     <td>
664                         [% Branches.GetName( suggestion.branchcode ) | html %]
665                     </td>
666                     <td>
667                         [% suggestion.fund.budget_name | html %]
668                     </td>
669                     <td>
670                         [% IF    suggestion.STATUS == 'ASKED'     %]<span>Pending</span>
671                         [% ELSIF suggestion.STATUS == 'ACCEPTED'  %]<span>Accepted</span>
672                         [% ELSIF suggestion.STATUS == 'ORDERED'   %]<span>Ordered</span>
673                         [% ELSIF suggestion.STATUS == 'REJECTED'  %]<span>Rejected</span>
674                         [% ELSIF suggestion.STATUS == 'CHECKED'   %]<span>Checked</span>
675                         [% ELSIF suggestion.STATUS == 'AVAILABLE' %]<span>Available</span>
676                         [% ELSIF AuthorisedValues.GetByCode( 'SUGGEST_STATUS', suggestion.STATUS ) %]
677                             [% AuthorisedValues.GetByCode( 'SUGGEST_STATUS', suggestion.STATUS ) | html %]
678                         [% ELSE %]<span>Status unknown</span>
679                         [% END %]
680                         [% IF suggestion.reason %]
681                             <br />([% suggestion.reason | html %])
682                         [% END %]
683                     </td>
684                 </tr>
685                 [% END %]
686             </tbody>
687         </table>
688     </div>
689 [% END %]
690
691 [% IF ( FRBRizeEditions ) %][% IF ( XISBNS ) %]
692 <div role="tabpanel" class="tab-pane" id="editions"><h4>Editions</h4>
693 <table>
694 [% FOREACH XISBN IN XISBNS %]<tr>[% IF ( AmazonCoverImages ) %]<td><a href="http://www.amazon.com/gp/reader/[% XISBN.normalized_isbn | uri %][% AmazonAssocTag | uri %]#reader-link"><img src="https://images-na.ssl-images-amazon.com/images/P/[% XISBN.normalized_isbn | html %].01._AA75_PU_PU-5_.jpg" /></a></td>[% END %]
695 [% IF ( !item_level_itypes || Koha.Preference('BiblioItemtypeInfo') ) %]<td>[% IF ( noItemTypeImages ) %]<span class="itypetext">[% XISBN.description | html %]</span>[% ELSE %]<img src="[% XISBN.imageurl | html %]" alt="[% XISBN.description | html %]" title="[% XISBN.description | html %]">[% END %]</td>[% END %]
696 <td><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% XISBN.biblionumber | uri %]">[% XISBN.title | html %]</a> <span>by</span> [% XISBN.author | html %] &copy;[% XISBN.copyrightdate | html %]
697   [% IF ( XISBN.publishercode ) %]
698 [% XISBN.publishercode | html %] [% IF ( XISBN.place ) %]([% XISBN.place | html %])[% END %] [% IF ( XISBN.publicationyear ) %], [% XISBN.publicationyear | html %][% END %] [% IF ( XISBN.editionstatement ) %][% XISBN.editionstatement | html %][% END %] [% IF ( XISBN.editionresponsibility ) %][% XISBN.editionresponsibility | html %][% END %]
699     [% END %]
700                 [% IF ( XISBN.pages ) %] [% END %][% XISBN.pages | html %] [% IF ( XISBN.illus ) %][% XISBN.illus | html %][% END %]
701                 [% IF ( XISBN.size ) %], [% END %][% XISBN.size | html %]
702 </td>
703
704 [% END %]
705 </table></div>[% END %]
706 [% END %]
707
708 [% IF ( ( Koha.Preference('CatalogConcerns') || Koha.Preference('OpacCatalogConcerns') ) && CAN_user_editcatalogue_edit_catalogue ) %]
709 <div role="tabpanel" class="tab-pane" id="concerns">
710     <fieldset class="action" style="cursor:pointer;">
711         <a id="hideResolved"><i class="fa fa-minus-square"></i> Hide resolved</a>
712         | <a id="showAll"><i class="fa fa-bars"></i> Show all</a>
713     </fieldset>
714
715     <table id="table_concerns" width="100%">
716         <thead>
717             <tr>
718                 <th>Reported</th>
719                 <th>Details</th>
720                 <th>Status</th>
721                 <th data-class-name="actions noExport">Actions</th>
722             </tr>
723         </thead>
724     </table>
725 </div>
726 [% END %]
727
728 [% IF ( LocalCoverImages ) %]
729     <div role="tabpanel" class="tab-pane" id="images">
730         [% IF localimages.count %]
731             <p>Click on an image to view it in the image viewer</p>
732             <ul class="thumbnails">
733                 [% FOREACH image IN localimages %]
734                     [% IF image %]
735                         <li id="imagenumber-[% image.imagenumber | html %]" class="thumbnail">
736                             <a href="/cgi-bin/koha/catalogue/imageviewer.pl?biblionumber=[% biblionumber | uri %]&amp;imagenumber=[% image.imagenumber | uri %]">
737                                 <img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&amp;imagenumber=[% image.imagenumber | uri %]" />
738                             </a>
739                             [% IF CAN_user_tools_upload_local_cover_images %]
740                                 <a href="#" class="remove"><i class="fa fa-trash-can"></i> Delete image</a>
741                             [% END %]
742                         </li>
743                     [% END %]
744                 [% END %]
745             </ul>
746         [% ELSE # - No image passed JavaScript takes care %]
747             <span class="noimagesuploaded">No images have been uploaded for this bibliographic record yet.</span>
748         [% END %]
749         [% IF ( CAN_user_tools_upload_local_cover_images ) %]
750             <p>Upload an image file: <a class="btn btn-default btn-xs" href="/cgi-bin/koha/tools/upload-cover-image.pl?biblionumber=[% biblionumber | uri %]&amp;filetype=image"><i class="fa fa-upload" aria-hidden="true"></i> Upload</a>
751             </p>
752         [% END %]
753     </div>
754 [% END %]
755
756 [% IF ( HTML5MediaEnabled ) %]
757 <div role="tabpanel" class="tab-pane" id="html5media">
758           [% FOREACH HTML5MediaSet IN HTML5MediaSets %]
759             <p>
760                 [% IF HTML5MediaSet.is_youtube %]
761                     <iframe id="player" width="640" height="360" src="[% HTML5MediaSet.srcblock | url %]"></iframe>
762                 [% ELSE %]
763                   <[% HTML5MediaParent | html %] controls preload=none>
764                     <[% HTML5MediaSet.child | html %] src="[% HTML5MediaSet.srcblock | url %]"[% HTML5MediaSet.typeblock | html %] />
765                     [[% HTML5MediaParent | html %] tag not supported by your browser.]
766                   </[% HTML5MediaParent | html %]>
767                 [% END %]
768             </p>
769           [% END %]
770 </div>
771 [% END %]
772
773
774 [% IF ( Koha.Preference('NovelistSelectStaffEnabled') && Koha.Preference('NovelistSelectStaffProfile') && Koha.Preference('NovelistSelectStaffView') == 'tab' ) %]
775     <div role="tabpanel" class="tab-pane" id="NovelistSelect" class="novelistSelect">
776         <div data-novelist-novelistselect=[% normalized_isbn | html %]></div>
777     </div>
778 [% END %]
779
780 [% FOREACH plugins_intranet_catalog_biblio_tab IN plugins_intranet_catalog_biblio_tabs %]
781     <div role="tabpanel" class="tab-pane" id="[% plugins_intranet_catalog_biblio_tab.id | html %]">
782         [% plugins_intranet_catalog_biblio_tab.content | $raw %]
783     </div>
784 [% END %]
785
786 </div><!-- /tab-content -->
787 </div><!-- /bibliodetails -->
788
789 <div id="export" style="margin-top: 1em;">
790 <form method="get" action="/cgi-bin/koha/catalogue/export.pl">
791 <table>  <tr>
792       <th>Save record</th>   </tr>
793     <tr><td> Select download format:    <select name="format">
794         <option value="mods">MODS (XML)</option>
795         <option data-toggle="modal" data-target="#exportModal_">Dublin Core</option>
796         <option value="marcxml">MARCXML</option>
797         <option value="marc8">MARC (non-Unicode/MARC-8)</option>
798         <option value="utf8">MARC (Unicode/UTF-8)</option>    </select>
799         <input type="submit" name="save" class="btn btn-primary" value="Download record" /></td>
800   </tr>
801   <tr><td>
802     <input type="hidden" name="op" value="export" /><input type="hidden" name="bib" value="[% biblionumber | html %]" />
803   </td></tr>
804 </table>
805 </form>
806 </div>
807
808 <div id="marcPreview" class="modal" tabindex="-1" role="dialog" aria-labelledby="marcPreviewLabel" aria-hidden="true">
809     <div class="modal-dialog modal-lg">
810     <div class="modal-content">
811     <div class="modal-header">
812         <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
813         <h3 id="marcPreviewLabel">MARC preview</h3>
814     </div>
815     <div class="modal-body">
816         <div id="loading"> <img src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif" alt="" /> Loading </div>
817     </div>
818     <div class="modal-footer">
819         <button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
820     </div>
821     </div>
822     </div>
823 </div>
824
825 <div id="elasticPreview" class="modal" tabindex="-1" role="dialog" aria-labelledby="elasticPreviewLabel" aria-hidden="true">
826     <div class="modal-dialog modal-lg">
827     <div class="modal-content">
828     <div class="modal-header">
829         <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
830         <h3 id="elasticPreviewLabel">Elasticsearch record</h3>
831     </div>
832     <div class="modal-body">
833         <div id="loading"> <img src="[% interface | html %]/[% theme | html %]/img/spinner-small.gif" alt="" /> Loading </div>
834     </div>
835     <div class="modal-footer">
836         <button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
837     </div>
838     </div>
839     </div>
840 </div>
841
842             </main>
843         </div> <!-- /.col-sm-10.col-sm-push-2 -->
844
845         <div class="col-sm-2 col-sm-pull-10">
846             <aside>
847                 [% INCLUDE 'biblio-view-menu.inc' %]
848             </aside>
849         </div> <!-- /.col-sm-2.col-sm-pull-10 -->
850      </div> <!-- /.row -->
851
852 [% END %]
853
854 <div class="modal fade" id="modal-item-group-create" tabindex="-1" role="dialog" aria-labelledby="modal-item-group-create-label">
855     <div class="modal-dialog">
856         <div class="modal-content">
857             <div class="modal-header">
858                 <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
859                 <h3 id="modal-item-group-create-label"><i class="fa fa-plus"></i> Create a new item group</h3>
860             </div>
861             <form method="get" id="modal-item-group-create-form" class="validated">
862                 <div class="modal-body">
863                     <fieldset>
864                         <p>
865                             <label for="item_group_description" class="required">Name: </label>
866                             <input name="description" id="modal-item-group-create-form-description" type="text" size="30" required="required" class="required" />
867                             <span class="required">Required</span>
868                         </p>
869                         <p>
870                             <label for="item_group_display_order" class="required">Display order: </label>
871                             <input name="display_order" id="modal-item-group-create-form-display_order" value="0" size="5" required="required" class="required" />
872                             <span class="required">Required</span>
873                             <br/>
874                             <span class="hint">Numbers only, item groups will be displayed in counting order</span>
875                         </p>
876                     </fieldset>
877                 </div>
878                 <div class="modal-footer">
879                     <button id="modal-item-group-create-submit" class="btn btn-default"><i class="fa fa-plus"></i> Submit</button>
880                     <button class="btn btn-link" data-dismiss="modal" aria-hidden="true">Cancel</button>
881                 </div>
882             </form>
883         </div>
884     </div>
885 </div>
886
887 <div class="modal fade" id="modal-item-group-edit" tabindex="-1" role="dialog" aria-labelledby="modal-item-group-edit-label">
888     <div class="modal-dialog">
889         <div class="modal-content">
890             <div class="modal-header">
891                 <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
892                 <h3 id="modal-item-group-edit-label"><i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit item group</h3>
893             </div>
894             <form method="get" id="modal-item-group-edit-form" class="validated">
895                 <div class="modal-body">
896                     <fieldset>
897                         <p>
898                             <label for="item_group_description" class="required">Name: </label>
899                             <input name="description" id="modal-item-group-edit-form-description" type="text" size="30" required="required" class="required" />
900                             <span class="required">Required</span>
901                         </p>
902                         <p>
903                             <label for="item_group_display_order" class="required">Sort order: </label>
904                             <input name="display_order" id="modal-item-group-edit-form-display_order" size="5" />
905                             <span class="hint">Numbers only, item groups will be displayed in counting order</span>
906                         </p>
907                     </fieldset>
908                 </div>
909                 <div class="modal-footer">
910                     <button id="modal-item-group-edit-submit" class="btn btn-default"><i class="fa-solid fa-pencil" aria-hidden="true"></i> Submit</button>
911                     <button class="btn btn-link" data-dismiss="modal" aria-hidden="true">Cancel</button>
912                 </div>
913             </form>
914         </div>
915     </div>
916 </div>
917
918 <div class="modal fade" id="modal-item-group-delete" tabindex="-1" role="dialog" aria-labelledby="modal-item-group-delete-label">
919     <div class="modal-dialog">
920         <div class="modal-content">
921             <div class="modal-header">
922                 <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
923                 <h3 id="modal-item-group-delete-label"><i class='fa fa-trash-can'></i> Delete item group</h3>
924             </div>
925             <div class="modal-body">
926                 Are you sure you want to delete this item group?
927             </div>
928             <div class="modal-footer">
929                 <button id="modal-item-group-delete-submit" class="btn btn-danger"><i class='fa fa-trash-can'></i> Delete</button>
930                 <button class="btn btn-link" data-dismiss="modal" aria-hidden="true">Cancel</button>
931             </div>
932         </div>
933     </div>
934 </div>
935
936 <div class="modal fade" id="modal-item-group-set" tabindex="-1" role="dialog" aria-labelledby="modal-item-group-set-label">
937     <div class="modal-dialog">
938         <div class="modal-content">
939             <div class="modal-header">
940                 <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
941                 <h3 id="modal-item-group-set-label"><i class='fa fa-book'></i> Set item group for items</h3>
942             </div>
943             <form method="get" id="modal-item-group-set-form" class="validated">
944                 <div class="modal-body">
945                     <fieldset>
946                         <p>
947                             <label for="item_group" class="required">Item group: </label>
948                             <select name="item_group" id="item-group-add-form-select">
949                                 [% FOREACH ig IN biblio.item_groups.search({}, {order_by => 'display_order'}) %]
950                                     <option value="[% ig.id | html %]">[% ig.description | html %]</option>
951                                 [% END %]
952                             </select>
953                             <span class="required">Required</span>
954                         </p>
955                     </fieldset>
956                 </div>
957                 <div class="modal-footer">
958                     <button id="modal-item-group-set-submit" class="btn btn-default"><i class='fa fa-book'></i> Set item group</button>
959                     <button class="btn btn-link" data-dismiss="modal" aria-hidden="true">Cancel</button>
960                 </div>
961             </form>
962         </div>
963     </div>
964 </div>
965
966 <div class="modal fade" id="modal-item-group-unset" tabindex="-1" role="dialog" aria-labelledby="modal-item-group-unset-label">
967     <div class="modal-dialog">
968         <div class="modal-content">
969             <div class="modal-header">
970                 <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
971                 <h3 id="modal-item-group-unset-label"><i class='fa fa-unlink'></i> Remove item from item group</h3>
972             </div>
973             <div class="modal-body">
974                 Are you sure you want to remove these item(s) from their item group(s)?
975             </div>
976             <div class="modal-footer">
977                 <button id="modal-item-group-unset-submit" class="btn btn-danger"><i class='fa fa-unlink'></i> Remove</button>
978                 <button class="btn btn-link" data-dismiss="modal" aria-hidden="true">Cancel</button>
979             </div>
980         </div>
981     </div>
982 </div>
983
984     [% IF bundlesEnabled %]
985     <div class="modal" id="addToBundleModal" tabindex="-1" role="dialog" aria-labelledby="addToBundleLabel">
986         <form method="get" id="addToBundleForm" action="">
987             <div class="modal-dialog" role="document">
988                 <div class="modal-content">
989                     <div class="modal-header">
990                         <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
991                         <h3 id="addToBundleLabel">Add to bundle</h3>
992                     </div>
993                     <div class="modal-body">
994                         <div id="addResult"></div>
995                         <fieldset class="rows">
996                             <ol>
997                                 <li>
998                                     <label class="required" for="external_id">Item barcode: </label>
999                                     <input type="text" id="external_id" name="external_id" required="required">
1000                                     <span class="required">Required</span>
1001                                 </li>
1002                             </ol>
1003                         </fieldset>
1004                     </div>
1005                     <div class="modal-footer">
1006                         <button type="submit" class="btn btn-default">Submit</button>
1007                         <button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
1008                     </div>
1009                 </div>
1010             </div>
1011         </form>
1012     </div>
1013
1014     <div class="modal" id="removeFromBundleModal" tabindex="-1" role="dialog" aria-labelledby="removeFromBundleLabel">
1015         <form method="get" id="removeFromBundleForm" action="">
1016             <div class="modal-dialog" role="document">
1017                 <div class="modal-content">
1018                     <div class="modal-header">
1019                         <button type="button" class="closebtn" data-dismiss="modal" aria-hidden="true">×</button>
1020                         <h3 id="removeFromBundleLabel">Remove from bundle</h3>
1021                     </div>
1022                     <div class="modal-body">
1023                         <div id="removeResult"></div>
1024                         <fieldset class="rows">
1025                             <ol>
1026                                 <li>
1027                                     <label class="required" for="external_id">Item barcode: </label>
1028                                     <input type="text" id="rm_external_id" name="external_id" required="required">
1029                                     <span class="required">Required</span>
1030                                 </li>
1031                             </ol>
1032                         </fieldset>
1033                     </div>
1034                     <div class="modal-footer">
1035                         <button type="submit" class="btn btn-default">Submit</button>
1036                         <button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
1037                     </div>
1038                 </div>
1039             </div>
1040         </form>
1041     </div>
1042     [% END %]
1043
1044     [% IF ( Koha.Preference('CatalogConcerns') ) %]
1045     [% INCLUDE 'modals/add_catalog_concern.inc' %]
1046     [% END %]
1047
1048     [% IF ( ( Koha.Preference('CatalogConcerns') || Koha.Preference('OpacCatalogConcerns') ) && CAN_user_editcatalogue_edit_catalogue ) %]
1049     [% INCLUDE 'modals/display_ticket.inc' %]
1050     [% END %]
1051
1052 [% MACRO jsinclude BLOCK %]
1053     [% INCLUDE 'catalog-strings.inc' %]
1054     [% INCLUDE 'calendar.inc' %]
1055     [% INCLUDE 'select2.inc' %]
1056     [% INCLUDE 'js-date-format.inc' %]
1057     [% Asset.js("js/catalog.js") | $raw %]
1058     [% Asset.js("js/recalls.js") | $raw %]
1059     [% Asset.js("js/coce.js") | $raw %]
1060     [% Asset.js("lib/Chocolat/js/chocolat.js") | $raw %]
1061     [% IF ( Koha.Preference('CatalogConcerns') ) %]
1062         <script>
1063             /* Set a variable needed by add_catalog_concern.js */
1064             var logged_in_user_borrowernumber = "[% logged_in_user.borrowernumber | html %]";
1065         </script>
1066         [% Asset.js("js/modals/add_catalog_concern.js") | $raw %]
1067      [% END %]
1068      [% IF ( ( Koha.Preference('CatalogConcerns') || Koha.Preference('OpacCatalogConcerns') ) && CAN_user_editcatalogue_edit_catalogue ) %]
1069          <script>
1070             $(document).ready(function() {
1071                 var table_settings = [% TablesSettings.GetTableSettings( 'cataloguing', 'concerns', 'table_concerns', 'json' ) | $raw %];
1072
1073                 var filtered = false;
1074                 let additional_filters = {
1075                     resolved_date: function(){
1076                         if ( filtered ) {
1077                             return { "=": null };
1078                         } else {
1079                             return;
1080                         }
1081                     },
1082                     biblio_id: [% biblionumber | uri %]
1083                 };
1084
1085                 var tickets_url = '/api/v1/tickets';
1086                 var tickets = $("#table_concerns").kohaTable({
1087                     "ajax": {
1088                         "url": tickets_url
1089                     },
1090                     "embed": [
1091                         "reporter",
1092                         "resolver",
1093                         "updates+count",
1094                     ],
1095                     'emptyTable': '<div class="dialog message">' + _("Congratulations, there are no catalog concerns.") + '</div>',
1096                     "columnDefs": [ {
1097                         "targets": [0,1,2],
1098                         "render": function (data, type, row, meta) {
1099                             if ( type == 'display' ) {
1100                                 if ( data != null ) {
1101                                     return data.escapeHtml();
1102                                 }
1103                                 else {
1104                                     return "";
1105                                 }
1106                             }
1107                             return data;
1108                         }
1109                     } ],
1110                     "columns": [
1111                         {
1112                             "data": "reported_date:reporter.firstname",
1113                             "render": function(data, type, row, meta) {
1114                                 let reported = '<span class="date clearfix">' + $datetime(row.reported_date) + '</span>';
1115                                 reported += '<span class="reporter clearfix">' + $patron_to_html(row.reporter, {
1116                                     display_cardnumber: false,
1117                                     url: true
1118                                 }) + '</span>';
1119                                 return reported;
1120                             },
1121                             "searchable": true,
1122                             "orderable": true
1123                         },
1124                         {
1125                             "data": "title:body",
1126                             "render": function(data, type, row, meta) {
1127                                 let resolved = ( row.resolved_date ) ? true : false;
1128                                 let result = '<a role="button" href="#" data-toggle="modal" data-target="#ticketDetailsModal" data-concern="' + encodeURIComponent(row.ticket_id) + '" data-resolved="' + resolved + '">' + row.title + '</a>';
1129                                 if (row.updates_count) {
1130                                     result += '<span class="pull-right"><a role="button" href="#" data-toggle="modal" data-target="#ticketDetailsModal" data-concern="' + encodeURIComponent(row.ticket_id) + '"><i class="fa fa-comment" aria-hidden="true"></i> ' + row.updates_count + '</a></span>';
1131                                 }
1132                                 result += '<div id="detail_' + row.ticket_id + '" class="hidden">' + row.body + '</div>';
1133                                 return result;
1134                             },
1135                             "searchable": true,
1136                             "orderable": true
1137                         },
1138                         {
1139                             "data": "resolved_date",
1140                             "render": function(data, type, row, meta) {
1141                                 let result = '';
1142                                 if (row.resolved_date) {
1143                                     result += _("Resolved by:") + ' <span>' + $patron_to_html(row.resolver, {
1144                                         display_cardnumber: false,
1145                                         url: true
1146                                     }) + '</span>';
1147                                     result += '<span class="clearfix">' + $datetime(row.resolved_date) + '</span>';
1148                                 } else {
1149                                     result += _("Open");
1150                                 }
1151                                 return result;
1152                             },
1153                             "searchable": true,
1154                             "orderable": true
1155                         },
1156                         {
1157                             "data": function(row, type, val, meta) {
1158                                 let resolved = ( row.resolved_date ) ? true : false;
1159                                 let result = '<a class="btn btn-default btn-xs" role="button" href="#" data-toggle="modal" data-target="#ticketDetailsModal" data-concern="' + encodeURIComponent(row.ticket_id) + '" data-resolved="' + resolved + '"><i class="fa-solid fa-eye" aria-hidden="true"></i> ' + _("Details") + '</a>';
1160                                 return result;
1161                             },
1162                             "searchable": false,
1163                             "orderable": false
1164                         },
1165                     ]
1166                 }, table_settings, 0, additional_filters);
1167
1168                 $('#hideResolved').on("click", function() {
1169                     filtered = true;
1170                     tickets.DataTable().draw();
1171                 });
1172
1173                 $('#showAll').on("click", function() {
1174                     filtered = false;
1175                     tickets.DataTable().draw();
1176                 });
1177             });
1178         </script>
1179         [% Asset.js("js/modals/display_ticket.js") | $raw %]
1180     [% END %]
1181     <script>
1182         var interface = "[% interface | html %]";
1183         var theme = "[% theme | html %]";
1184         // http://www.oreillynet.com/pub/a/javascript/2003/10/21/amazonhacks.html
1185         function verify_cover_images() {
1186             // Loop over each container in the template which contains covers
1187             $(".cover-slider").each(function(){
1188                 var lightbox_descriptions = [];
1189                 var first_shown = 0;
1190                 $(this).find(".cover-image").each( function( index ){
1191                 var div = $(this);
1192                 // Find the image in the container
1193                 var img = div.find("img")[0];
1194                 if( $(img).length > 0 ){
1195                     var description = "";
1196                         // All slides start hidden. If this is the first one, show it.
1197                         if( first_shown == 0 ){
1198                             div.show();
1199                             first_shown = 1;
1200                         }
1201                         // Check if Amazon image is present
1202                         if ( div.attr("id") == "amazon-bookcoverimg"  ) {
1203                             w = img.width;
1204                             h = img.height;
1205                             if ((w == 1) || (h == 1)) {
1206                                 // Amazon returned single-pixel placeholder
1207                                 // Remove the container
1208                                 div.remove();
1209                             } else {
1210                                 lightbox_descriptions.push(_("Amazon cover image (<a href='%s'>see the original image</a>)").format($(img).data('link')));
1211                             }
1212                         } else if( div.attr("id") == "custom-coverimg" ){
1213                             if ( (img.complete != null) && (!img.complete) || img.naturalHeight == 0 ) {
1214                                 // No image was loaded via the CustomCoverImages system preference
1215                                 // Remove the container
1216                                 div.remove();
1217                             } else {
1218                                 lightbox_descriptions.push( _("Custom cover image") );
1219                             }
1220                         } else if ( div.attr("id") == "syndetics-bookcoverimg" ){
1221                                 lightbox_descriptions.push(_("Syndetics cover image (<a href='%s'>see the original image</a>)").format($(img).data('link')));
1222                         }
1223                         else if( div.hasClass("coce-coverimg" ) ){
1224                             // Identify which service's image is being loaded by Coce
1225                             var coce_description;
1226                             if( $(img).attr("src").indexOf('amazon.com') >= 0 ){
1227                                 coce_description = _("Coce image from Amazon.com");
1228                             } else if( $(img).attr("src").indexOf('google.com') >= 0 ){
1229                                 coce_description = _("Coce image from Google Books");
1230                             } else if( $(img).attr("src").indexOf('openlibrary.org') >= 0 ){
1231                                 coce_description = _("Coce image from Open Library");
1232                             }
1233                             div.find(".hint").html(coce_description);
1234                             lightbox_descriptions.push(coce_description);
1235                         } else if ( div.attr("class") == "cover-image local-coverimg" ) {
1236                             lightbox_descriptions.push(_("Local cover image (<a href='%s'>edit</a>)").format($(img).data('link')));
1237                         } else {
1238                             lightbox_descriptions.push(_("Cover image source unknown"));
1239                         }
1240                     }
1241                 });
1242
1243                 // Lightbox for cover images
1244                 Chocolat(this.querySelectorAll('.cover-image a'), {
1245                     description: function(){
1246                         return lightbox_descriptions[this.settings.currentImageIndex];
1247                     }
1248                 });
1249
1250             });
1251
1252             $(".cover-slider").each(function(){
1253                 var coverSlide = this;
1254                 var coverImages = $(this).find(".cover-image");
1255                 if( coverImages.length > 1 ){
1256                     coverImages.each(function( index ){
1257                         // If more that one image is present, add a navigation link
1258                         // for activating the slide
1259                         var covernav = $("<a href=\"#\" data-num=\"" + index + "\" class=\"cover-nav\"></a>");
1260                         if( index == 0 ){
1261                             // Set the first navigation link as active
1262                             $(covernav).addClass("nav-active");
1263                         }
1264                         $(covernav).html("<i class=\"fa fa-circle\"></i>");
1265                         $(coverSlide).append( covernav );
1266                     });
1267                 }
1268
1269                 if( $(coverSlide).attr('id') == 'biblio-cover-slider' // Hide if not visible, but only for the biblio images. Images for items are only local cover images
1270                     && $(coverSlide).find(".cover-image:visible").length < 1 ){
1271                     $(coverSlide).remove();
1272                 } else {
1273                     $(coverSlide).addClass("cover-slides");
1274                     var img = $(coverSlide).find(".cover-image:visible").find("img")[0];
1275                     if( $(img).length > 0 && img.complete && img.naturalHeight > 0 ){
1276                         $(".cover-slides").css({"background-image":"none"});
1277                     }
1278                 }
1279             });
1280
1281             $("#editions img").each(function(i){
1282                 if ( this.src.indexOf('amazon.com') >= 0 ) {
1283                     w = this.width;
1284                     h = this.height;
1285                     if ((w == 1) || (h == 1)) {
1286                         this.src = 'https://images-na.ssl-images-amazon.com/images/G/01/x-site/icons/no-img-sm.gif';
1287                     } else if ( (this.complete != null) && (!this.complete) || this.naturalHeight == 0 ) {
1288                         this.src = 'https://images-na.ssl-images-amazon.com/images/G/01/x-site/icons/no-img-sm.gif';
1289                     }
1290                 }
1291             });
1292         }
1293
1294         function removeLocalImage(imagenumber) {
1295             var thumbnail = $("#imagenumber-" + imagenumber );
1296             var copy = thumbnail.html();
1297             thumbnail.find("img").css("opacity", ".2");
1298             thumbnail.find("a.remove").html("<img style='display:inline-block' src='" + interface + "/" + theme + "/img/spinner-small.gif' alt='' />");
1299             const client = APIClient.cover_image;
1300             client.cover_images.delete(imagenumber).then(
1301                 success => {
1302                     if ( success.deleted == 1 ) {
1303                         thumbnail.remove();
1304                     } else {
1305                         thumbnail.html( copy );
1306                         alert(_("An error occurred on deleting this image"));
1307                     }
1308                     if ( $('ul.thumbnails > li').length == 0 ) {
1309                         showNoImageMessage();
1310                     }
1311                 },
1312                 error => {
1313                     thumbnail.html( copy );
1314                     alert(_("An error occurred on deleting this image"));
1315                     console.warn("Something wrong happened: %s".format(error));
1316                 }
1317             );
1318         }
1319
1320         function showNoImageMessage() {
1321             var no_images_msg = _("No images have been uploaded for this bibliographic record yet.");
1322             no_images_msg = '<p>' + no_images_msg + '</p>';
1323             [% IF ( CAN_user_tools_upload_local_cover_images ) %]
1324                 var please_upload = _("Upload an image file: %sUpload%s").format("<a class='btn btn-default btn-xs' href='/cgi-bin/koha/tools/upload-cover-image.pl?biblionumber=" + biblionumber + "&amp;filetype=image'><i class='fa fa-upload' aria-hidden='true'></i> ","</a>");
1325                 no_images_msg += "<p id='upload_image'>" + please_upload + '</p>';
1326             [% END %]
1327             $('#images').html(no_images_msg);
1328         }
1329
1330         [% IF StaffDetailItemSelection %]
1331             function itemSelectionBuildDeleteLink(div) {
1332                 var itemnumbers = new Array();
1333                 $("input[name='itemnumber'][type='checkbox']:checked", div).each(function() {
1334                     itemnumbers.push($(this).val());
1335                 });
1336                 if (itemnumbers.length > 0) {
1337                     var url = '/cgi-bin/koha/tools/batchMod.pl?op=show&del=1';
1338                     url += '&itemnumber=' + itemnumbers.join('&itemnumber=');
1339                     url += '&biblionumber=[% biblionumber | uri %]';
1340                     url += '&src=CATALOGUING';
1341                     $('a.itemselection_action_delete').attr('href', url);
1342                 } else {
1343                     return false;
1344                 }
1345                 return true
1346             }
1347
1348             function itemSelectionBuildModifyLink(div) {
1349                 var itemnumbers = new Array();
1350                 $("input[name='itemnumber'][type='checkbox']:checked", div).each(function() {
1351                     itemnumbers.push($(this).val());
1352                 });
1353                 if (itemnumbers.length > 0) {
1354                     var url = '/cgi-bin/koha/tools/batchMod.pl?op=show';
1355                     url += '&itemnumber=' + itemnumbers.join('&itemnumber=');
1356                     url += '&biblionumber=[% biblionumber | uri %]';
1357                     url += '&src=CATALOGUING';
1358                     $('a.itemselection_action_modify').attr('href', url);
1359                 } else {
1360                     return false;
1361                 }
1362                 return true;
1363             }
1364
1365             function itemSelectionBuildActionLinks(tab) {
1366                 var div = $("#" + tab);
1367                 var delete_link_ok = itemSelectionBuildDeleteLink(div);
1368                 var modify_link_ok = itemSelectionBuildModifyLink(div);
1369                 if (modify_link_ok || delete_link_ok) {
1370                     $('.itemselection_actions', div).show();
1371                 } else {
1372                     $('.itemselection_actions', div).hide();
1373                 }
1374             }
1375
1376             $(document).ready(function() {
1377                 $('table.items_table').each(function() {
1378                     var div = $(this).parent().attr("id");
1379                     itemSelectionBuildActionLinks(div);
1380                 });
1381
1382                 $("input[name='itemnumber'][type='checkbox']").change(function() {
1383                     var div = $(this).parents('table').parent().parent().attr("id");
1384                     itemSelectionBuildActionLinks(div);
1385                 });
1386
1387                 $(".SelectAll").on("click",function(e){
1388                     e.preventDefault();
1389                     var tab = $(this).data("tab");
1390                     $("input[name='itemnumber'][type='checkbox']", $("#"+tab)).prop('checked', true);
1391                     itemSelectionBuildActionLinks(tab);
1392                 });
1393
1394                 $(".ClearAll").on("click",function(e){
1395                     e.preventDefault();
1396                     var tab = $(this).data("tab");
1397                     $("input[name='itemnumber'][type='checkbox']", $("#"+tab)).prop('checked', false);
1398                     itemSelectionBuildActionLinks(tab);
1399                 });
1400             });
1401         [% END %]
1402
1403         $(document).ready(function() {
1404             // Pick details tab to display by default
1405             [% IF count == 0 %]
1406                 [% IF ( Koha.Preference('HTML5MediaEnabled') == 'staff' or Koha.Preference('HTML5MediaEnabled') == 'both' ) && HTML5MediaSets.size %]
1407                     $(".nav-tabs a[href='#html5media']").tab("show");
1408                 [% ELSIF ComponentParts && ComponentParts.size %]
1409                     $(".nav-tabs a[href='#components']").tab("show");
1410                 [% ELSE %]
1411                     $(".nav-tabs a[href='#holdings']").tab("show");
1412                 [% END %]
1413             [% ELSE %]
1414                 $(".nav-tabs a[href='#holdings']").tab("show");
1415             [% END %]
1416             $('#search-form').focus();
1417             $('.thumbnails > li > .remove').click(function() {
1418                 var result = confirm(_("Are you sure you want to delete this cover image?"));
1419
1420                 if ( result == true ) {
1421                     var imagenumber = $(this).parent().attr('id').split('-')[1];
1422                     removeLocalImage(imagenumber);
1423                 }
1424
1425                 return false;
1426             });
1427             [% IF ( IntranetCoce && CoceProviders ) %]
1428                 KOHA.coce.getURL('[% CoceHost | html %]', '[% CoceProviders | html %]');
1429             [% END %]
1430
1431             $("body").on("click",".previewMARC", function(e){
1432                 e.preventDefault();
1433                 var page = $(this).attr("href");
1434                 $("#marcPreview .modal-body").load(page + " table");
1435                 $('#marcPreview').modal({show:true});
1436
1437             });
1438
1439            [% IF ( Koha.Preference('SearchEngine') == 'Elasticsearch' ) %]
1440             $("body").on("click",".previewElastic", function(e){
1441                 e.preventDefault();
1442                 var pageElastic = $(this).attr("href");
1443                 $("#elasticPreview .modal-body").load(pageElastic, function( response, status, xhr ) {
1444                     if( status == 'error' ){
1445                         $("#elasticPreview .modal-body").html("<h1>"+_("An error has occurred!")+"</h1><h2><em>"+_("Error 404")+"</em></h2><ul><li>"+_("An internal link in the staff interface is broken and the page does not exist")+"</li></ul><h3>"+_("What's next?")+"</h3><ul style='margin-bottom: 1em; padding-bottom: 1em; border-bottom: 1px solid #CCC;'><li>"+_("Use top menu bar to navigate to another part of Koha.")+"</li><li>"+_("To report a broken link or any other issue, please contact the Koha administrator.")+" <a href='mailto:[% Koha.Preference("KohaAdminEmailAddress") | uri %]'>"+_("Send email")+"</a></li></ul>");
1446                     }
1447                 });
1448                 $('#elasticPreview').modal({show:true});
1449             });
1450            [% END %]
1451
1452             [% IF ( Koha.Preference('NovelistSelectStaffEnabled') && Koha.Preference('NovelistSelectStaffProfile') && ( normalized_isbn || normalized_upc ) ) %]
1453                 novSelect.loadContentForQuery({
1454                     ClientIdentifier : '[% IF normalized_isbn %][% normalized_isbn | html %][% ELSE %][% normalized_upc | html %][% END %]',
1455                     ISBN : '[% IF normalized_isbn %][% normalized_isbn | html %][% ELSE %][% normalized_upc | html %][% END %]',
1456                     version : '2.1'
1457                 },
1458                 '[% Koha.Preference('NovelistSelectStaffProfile') | html %]',
1459                 '[% Koha.Preference('NovelistSelectPassword') | html %]',
1460                 function(d){
1461                     if ( d.length > 0 ){ //If no content
1462                         $(".NovelistSelect").show();
1463                     }
1464                  });
1465              [% END %]
1466              $(".print-label").on("click", function(e){
1467                 e.preventDefault();
1468                 link = $(this).attr("href");
1469                 openWindow(link,"Print spine label",400,400);
1470              });
1471              $(".cover-slider").on("click",".cover-nav", function(e){
1472                  e.preventDefault();
1473                 var cover_slider = $(this).parent();
1474                 // Adding click handler for cover image navigation links
1475                 var num = $(this).data("num");
1476                 $(cover_slider).find(".cover-nav").removeClass("nav-active");
1477                 $(this).addClass("nav-active");
1478                 $(cover_slider).find(".cover-image").hide();
1479                 $(cover_slider).find(".cover-image").eq( num ).show();
1480              });
1481         });
1482
1483
1484         [% IF ( IntranetCoce && CoceProviders ) %]
1485             let counter_wait = 0;
1486             function wait_for_images(cb){
1487
1488                 var loaded = 1;
1489                 counter_wait++;
1490
1491                 if ( loaded ) {
1492                     loaded = KOHA.coce.done;
1493                 }
1494
1495                 if (!loaded && counter_wait < 50) {// Do not wait more than 5 seconds
1496                     window.setTimeout(function(){wait_for_images(cb);}, 100);
1497                 } else {
1498                     if (counter_wait >= 50 ) {
1499                         console.log("Could not retrieve the images")
1500                     }
1501                     cb();
1502                 }
1503             }
1504
1505             $(window).load(function() {
1506                 wait_for_images(verify_cover_images);
1507             });
1508         [% ELSE %]
1509             $(window).load(function() {
1510                 verify_cover_images();
1511             });
1512         [% END %]
1513     </script>
1514     [% IF ( Koha.Preference('NovelistSelectStaffEnabled') && Koha.Preference('NovelistSelectStaffProfile') && ( normalized_isbn || normalized_upc ) ) %]
1515         <script src="https://imageserver.ebscohost.com/novelistselect/ns2init.js"></script>
1516     [% END %]
1517     [% INCLUDE 'datatables.inc' %]
1518     [% Asset.js("lib/jquery/plugins/jquery.dataTables.columnFilter.js") | $raw %]
1519     [% INCLUDE 'columns_settings.inc' %]
1520     [% INCLUDE 'js-date-format.inc' %]
1521     [% INCLUDE 'js-patron-format.inc' %]
1522     [% INCLUDE 'js-biblio-format.inc' %]
1523     [% Asset.js("js/browser.js") | $raw %]
1524     [% Asset.js("js/table_filters.js") | $raw %]
1525     [% Asset.js("js/place_booking_modal.js") | $raw %]
1526     <script>
1527         var browser;
1528         browser = KOHA.browser('[% searchid | html %]', parseInt(biblionumber, 10));
1529         browser.show();
1530
1531         [% IF bundlesEnabled %]
1532         var bundle_settings = [% TablesSettings.GetTableSettings('catalogue', 'detail','bundle_tables','json') | $raw %];
1533         var bundle_lost_value = [% Koha.Preference('BundleLostValue') | html %];
1534         [% END %]
1535         $(document).ready(function() {
1536
1537             [% IF bundlesEnabled %] // Bundle handling
1538             function createChild ( row, itemnumber, duedate ) {
1539
1540                 // Toolbar
1541                 var bundle_toolbar = $('<div id="toolbar" class="btn-toolbar"></div>');
1542                 bundle_toolbar.append('<a class="btn btn-default" data-toggle="modal" data-target="#addToBundleModal" data-item="' + itemnumber + '"><i class="fa fa-plus"></i> ' + _("Add to bundle") + '</a>');
1543                 bundle_toolbar.append('<a class="btn btn-default" data-toggle="modal" data-target="#removeFromBundleModal" data-item="' + itemnumber + '"><i class="fa fa-minus"></i> ' + _("Remove from bundle") + '</a>');
1544
1545                 // Disable management if there's a duedate
1546                 if(duedate) {
1547                     bundle_toolbar.children('.btn').addClass("disabled");
1548                     bundle_toolbar.attr("title", _("This bundle is checked out, it cannot be modified"));
1549                 }
1550
1551                 // This is the table we'll convert into a DataTable
1552                 var bundles_table = $('<table class="display tbundle" data-itemnumber="'+itemnumber+'" id="bundle_table_'+itemnumber+'" width="100%"/>');
1553
1554                 // Display it the child row
1555                 row.child( bundle_toolbar.add(bundles_table), 'bundle' ).show();
1556
1557                 // Initialise as a DataTable
1558                 var bundle_table_url = "/api/v1/items/" + itemnumber + "/bundled_items?";
1559                 var bundle_table = bundles_table.kohaTable({
1560                     "ajax": {
1561                         "url": bundle_table_url
1562                     },
1563                     "embed": [
1564                         "biblio",
1565                         "return_claim.patron"
1566                     ],
1567                     "order": [[ 1, "asc" ]],
1568                     "columnDefs": [ {
1569                         "targets": [0,1,2,3],
1570                         "render": function (data, type, row, meta) {
1571                             if ( data && type == 'display' ) {
1572                                 return data.escapeHtml();
1573                             }
1574                             return data;
1575                         }
1576                     } ],
1577                     "columns": [
1578                         {
1579                             "data": "biblio.title:biblio.subtitle:biblio.medium",
1580                             "title": _("Title"),
1581                             "searchable": true,
1582                             "orderable": true,
1583                             "render": function(data, type, row, meta) {
1584                                 return $biblio_to_html(row.biblio, { link: 1 });
1585                             }
1586                         },
1587                         {
1588                             "data": "biblio.author",
1589                             "title": _("Author"),
1590                             "searchable": true,
1591                             "orderable": true,
1592                         },
1593                         {
1594                             "data": "callnumber",
1595                             "title": _("Callnumber"),
1596                             "searchable": true,
1597                             "orderable": true,
1598                         },
1599                         {
1600                             "data": "external_id",
1601                             "title": _("Barcode"),
1602                             "searchable": true,
1603                             "orderable": true,
1604                         },
1605                         {
1606                             "data": "lost_status:last_seen_date:return_claim.patron",
1607                             "title": _("Status"),
1608                             "searchable": false,
1609                             "orderable": false,
1610                             "render": function(data, type, row, meta) {
1611                                 if ( row.lost_status == bundle_lost_value ) {
1612                                     let out = '<span class="lost">' + _("Last seen") + ': ' + $date(row.last_seen_date) + '</span>';
1613                                     if ( row.return_claim ) {
1614                                         out = out + '<span class="claims_return">' + _("Claims returned by") + ': ' + $patron_to_html( row.return_claim.patron, { display_cardnumber: false, url: true } ) + '</span>';
1615                                     }
1616                                     return out;
1617                                 }
1618                                 else if ( row.lost_status !== 0 ) {
1619                                     return '<span class="lost">' + _("Lost") + ': ' + row.lost_status + '</span>';
1620                                 }
1621                                 return '<span class="available">' + _("Present") + '</span>';
1622                             }
1623                         },
1624                         {
1625                             "data": function( row, type, val, meta ) {
1626                                 var result;
1627                                 if (duedate) {
1628                                     result = '<button class="btn btn-default btn-xs remove disabled" role="button" data-itemnumber="'+row.item_id+'" title="%s"><i class="fa fa-minus" aria-hidden="true"></i> %s</button>\n'.format(_("This bundle is checked out, it cannot be modified"), _("Remove"));
1629                                 } else {
1630                                     result = '<button class="btn btn-default btn-xs remove" role="button" data-itemnumber="'+row.item_id+'"><i class="fa fa-minus" aria-hidden="true"></i> '+_("Remove")+'</button>\n';
1631                                 }
1632                                 return result;
1633                             },
1634                             "title": _("Actions"),
1635                             "searchable": false,
1636                             "orderable": false,
1637                             "class": "noExport"
1638                         }
1639                     ]
1640                 }, bundle_settings, 1);
1641                 $(".tbundle").on("click", ".remove:not(.disabled)", function(){
1642                     var bundle_table = $(this).closest('table');
1643                     var host_itemnumber = bundle_table.data('itemnumber');
1644                     var component_itemnumber = $(this).data('itemnumber');
1645                     var unlink_item_url = "/api/v1/items/" + host_itemnumber + "/bundled_items/" + component_itemnumber;
1646                     $.ajax({
1647                         type: "DELETE",
1648                         url: unlink_item_url,
1649                         success: function(){
1650                             bundle_table.DataTable({ 'retrieve': true }).draw(false);
1651                         }
1652                     });
1653                 });
1654
1655                 return;
1656             }
1657
1658             var bundle_changed;
1659             var bundle_form_active;
1660             $("#addToBundleModal").on("shown.bs.modal", function(e){
1661                 var button = $(e.relatedTarget);
1662                 var item_id = button.data('item');
1663                 $("#addResult").replaceWith('<div id="addResult"></div>');
1664                 $("#addToBundleForm").attr('action', '/api/v1/items/' + item_id + '/bundled_items');
1665                 $("#external_id").focus();
1666                 bundle_changed = 0;
1667                 bundle_form_active = item_id;
1668             });
1669
1670             function addToBundle (url, data) {
1671                   /* Send the data using post with external_id */
1672                   var posting = $.post({
1673                       url: url,
1674                       data: JSON.stringify(data),
1675                       contentType: "application/json; charset=utf-8",
1676                       dataType: "json"
1677                   });
1678
1679                   const barcode = data.external_id;
1680
1681                   /* Report the results */
1682                   posting.done(function(data) {
1683                       $('#addResult').replaceWith('<div id="addResult" class="alert alert-success">'+_("Success: Added '%s'").format(barcode)+'</div>');
1684                       $('#external_id').val('').focus();
1685                       bundle_changed = 1;
1686                   });
1687                   posting.fail(function(data) {
1688                       if ( data.status === 409 ) {
1689                           var response = data.responseJSON;
1690                           if ( response.error_code === 'already_bundled' ) {
1691                               $('#addResult').replaceWith('<div id="addResult" class="alert alert-warning">'+_("Warning: Item '%s' already attached").format(barcode)+'</div>');
1692                           } else if (response.error_code === 'bundle_checkout_out') {
1693                               $('#addResult').replaceWith('<div id="addResult" class="alert alert-danger">'+_("Failure: Bundle is currently checked out")+'</div>');
1694                           } else if (response.error_code === 'checked_out') {
1695                               const button = $('<button type="button">')
1696                                 .addClass('btn btn-xs')
1697                                 .text(_("Check in and add to bundle"))
1698                                 .on('click', function () {
1699                                     addToBundle(url, { external_id: barcode, force_checkin: true });
1700                                 });
1701                               $('#addResult')
1702                                 .empty()
1703                                 .attr('class', 'alert alert-warning')
1704                                 .append(__x('Warning: Item {barcode} is checked out', { barcode }))
1705                                 .append(' ', button);
1706                           } else if (response.error_code === 'failed_checkin') {
1707                               $('#addResult')
1708                                 .empty()
1709                                 .attr('class', 'alert alert-danger')
1710                                 .append(__x('Failure: Item {barcode} cannot be checked in', { barcode }))
1711                           } else if (response.error_code === 'reserved') {
1712                               const button = $('<button type="button">')
1713                                 .addClass('btn btn-xs')
1714                                 .text(_("Ignore holds and add to bundle"))
1715                                 .on('click', function () {
1716                                     addToBundle(url, { external_id: barcode, ignore_holds: true });
1717                                 });
1718                               $('#addResult')
1719                                 .empty()
1720                                 .attr('class', 'alert alert-warning')
1721                                 .append(__x('Warning: Item {barcode} is on hold', { barcode }))
1722                                 .append(' ', button);
1723                           } else {
1724                               $('#addResult').replaceWith('<div id="addResult" class="alert alert-danger">'+_("Failure: Item '%s' belongs to another bundle").format(barcode)+'</div>');
1725                           }
1726                       } else if ( data.status === 404 ) {
1727                           $('#addResult').replaceWith('<div id="addResult" class="alert alert-danger">'+_("Failure: Item '%s' not found").format(barcode)+'</div>');
1728                       } else if ( data.status === 400 ) {
1729                           var response = data.responseJSON;
1730                           if ( response.error_code === "failed_nesting" ) {
1731                               $('#addResult').replaceWith('<div id="addResult" class="alert alert-danger">'+_("Failure: Item '%s' is a bundle and bundles cannot be nested").format(barcode)+'</div>');
1732                           } else {
1733                               $('#addResult').replaceWith('<div id="addResult" class="alert alert-danger">'+_("Failure: Check the logs for details.")+'</div>');
1734                           }
1735                       } else {
1736                           $('#addResult').replaceWith('<div id="addResult" class="alert alert-danger">'+_("Failure: Check the logs for details.")+'</div>');
1737                       }
1738                       $('#external_id').val('').focus();
1739                   });
1740             }
1741
1742             $("#addToBundleForm").submit(function(event) {
1743                   /* stop form from submitting normally */
1744                   event.preventDefault();
1745
1746                   const url = this.action;
1747                   const data = { external_id: this.elements.external_id.value };
1748
1749                   addToBundle(url, data);
1750             });
1751
1752             $("#addToBundleModal").on("hidden.bs.modal", function(e){
1753                 if ( bundle_changed ) {
1754                     $('#bundle_table_'+bundle_form_active).DataTable({ 'retrieve': true }).ajax.reload();
1755                 }
1756                 bundle_form_active = 0;
1757                 bundle_changed = 0;
1758             });
1759
1760             $("#removeFromBundleModal").on("shown.bs.modal", function(e){
1761                 var button = $(e.relatedTarget);
1762                 var item_id = button.data('item');
1763                 $("#removeResult").replaceWith('<div id="removeResult"></div>');
1764                 $("#removeFromBundleForm").attr('action', '/api/v1/items/' + item_id + '/bundled_items/');
1765                 $("#rm_external_id").focus();
1766                 bundle_changed = 0;
1767                 bundle_form_active = item_id;
1768             });
1769
1770             $("#removeFromBundleForm").submit(function(event) {
1771
1772                 /* stop form from submitting normally */
1773                 event.preventDefault();
1774
1775                 /* get the action attribute from the <form action=""> element */
1776                 var $form = $(this),
1777                 url = $form.attr('action');
1778
1779                 var barcode = $('#rm_external_id').val();
1780
1781                 /* Fetch itemnumber using rm_external_id */
1782                 var itemReq = $.get('/api/v1/items', { q: JSON.stringify({
1783                     external_id: barcode
1784                 }) }, null, "json");
1785
1786                 var itemnumber;
1787                 itemReq.done(function(data) {
1788                     if (data.length === 1) {
1789                         itemnumber = data[0].item_id;
1790
1791                         /* Remove link using fetch itemnumber */
1792                         var deleteReq = $.ajax( url + itemnumber, {
1793                             type : 'DELETE'
1794                         });
1795
1796                         /* Report the results */
1797                         deleteReq.done(function(data) {
1798                             var barcode = $('#rm_external_id').val();
1799                             $('#removeResult').replaceWith('<div id="removeResult" class="alert alert-success">'+_("Success: Removed '%s'").format(barcode)+'</div>');
1800                             $('#rm_external_id').val('').focus();
1801                             bundle_changed = 1;
1802                         });
1803                         deleteReq.fail(function(data) {
1804                             var barcode = $('#rm_external_id').val();
1805                             if ( data.status === 409 ) {
1806                                 var response = data.responseJSON;
1807                                 if (response.error_code === 'bundle_checkout_out') {
1808                                     $('#removeResult').replaceWith('<div id="removeResult" class="alert alert-danger">'+_("Failure: Bundle is currently checked out")+'</div>');
1809                                 } else if ( response.key === "PRIMARY" ) {
1810                                     $('#removeResult').replaceWith('<div id="removeResult" class="alert alert-warning">'+_("Warning: Item '%s' already attached").format(barcode)+'</div>');
1811                                 } else {
1812                                     $('#removeResult').replaceWith('<div id="removeResult" class="alert alert-danger">'+_("Failure: Item '%s' belongs to another bundle").format(barcode)+'</div>');
1813                                 }
1814                             } else if ( data.status === 404 ) {
1815                                 $('#addResult').replaceWith('<div id="addResult" class="alert alert-danger">'+_("Failure: Item '%s' not found").format(barcode)+'</div>');
1816                             } else {
1817                                 $('#removeResult').replaceWith('<div id="removeResult" class="alert alert-danger">'+_("Failure: Check the logs for details")+'</div>');
1818                             }
1819                             $('#rm_external_id').val('').focus();
1820                         });
1821                     } else {
1822                         $('#removeResult').replaceWith('<div id="removeResult" class="alert alert-danger">'+_("Failed: Barcode matched more than one item '%s'").format(barcode)+'</div>');
1823                     }
1824                 });
1825                 itemReq.fail(function(data) {
1826                      $('#removeResult').replaceWith('<div id="removeResult" class="alert alert-danger">'+_("Failed: Item not found '%s'").format(barcode)+'</div>');
1827                     $('#rm_external_id').val('').focus();
1828
1829                 });
1830             });
1831
1832             $("#removeFromBundleModal").on("hidden.bs.modal", function(e){
1833                 if ( bundle_changed ) {
1834                     $('#bundle_table_'+bundle_form_active).DataTable({ 'retrieve': true }).ajax.reload();
1835                 }
1836                 bundle_form_active = 0;
1837                 bundle_changed = 0;
1838             });
1839             // End bundle handling
1840             [% END %]
1841
1842             var table_ids = [ 'holdings_table', 'otherholdings_table' ];
1843             var table_settings = [ [% TablesSettings.GetTableSettings('catalogue', 'detail','holdings_table','json') | $raw %], [% TablesSettings.GetTableSettings('catalogue', 'detail','otherholdings_table','json')  | $raw %] ];
1844             table_ids.forEach( function( table_id, index ) {
1845                 let filters = {};
1846                 [% IF Koha.Preference('SeparateHoldings') %]
1847                     [% SET SeparateHoldingsBranch = Koha.Preference('SeparateHoldingsBranch') || 'homebranch' %];
1848                     let branch = '[% IF SeparateHoldingsBranch == 'homebranch' %]home_library_id[% ELSE %]holding_library_id[% END %]';
1849                     if ( table_id == 'holdings_table' ) {
1850                         filters[branch] = '[% Branches.GetLoggedInBranchcode() | html %]';
1851                     } else {
1852                         filters[branch] = { '!=': '[% Branches.GetLoggedInBranchcode() | html  %]' };
1853                     }
1854                 [% END %]
1855
1856                 var table = build_table(table_id, table_settings[index], filters);
1857
1858                 [% IF bundlesEnabled %]
1859                 // Add event listener for opening and closing bundle details
1860                 $('#' + table_name + ' tbody').on('click', 'button.details-control', function () {
1861                     var button = $(this);
1862                     var tr = button.closest('tr');
1863                     var dTable = button.closest('table').DataTable({ 'retrieve': true });
1864
1865                     var itemnumber = tr.data('itemnumber');
1866                     var duedate = tr.data('duedate');
1867                     var row = dTable.row( tr );
1868
1869                     if ( row.child.isShown() ) {
1870                         // This row is already open - close it
1871                         row.child.hide();
1872                         tr.removeClass('shown');
1873                         button.removeClass('active');
1874                     }
1875                     else {
1876                         // Open this row
1877                         createChild(row, itemnumber, duedate);
1878                         tr.addClass('shown');
1879                         button.addClass('active');
1880                     }
1881                 } );
1882                 [% END %]
1883             });
1884
1885             [% IF Koha.Preference('AcquisitionDetails') %]
1886                 var table_settings = [% TablesSettings.GetTableSettings('catalogue', 'detail', 'acquisitiondetails-table', 'json') | $raw %];
1887                 var acquisitiondetails_table = KohaTable("orders", {
1888                     "dom": 'C<"top pager"ilpfB><"#filter_c">tr<"bottom pager"ip>',
1889                     "paginate": false,
1890                     "autoWidth": false,
1891                     "order": [[ 4, "desc" ]],
1892                 }, table_settings);
1893             [% END %]
1894
1895             [% IF suggestions.count %]
1896                 $(".sorted").dataTable($.extend(true, {}, dataTablesDefaults, {
1897                     "columnDefs": [
1898                         { "orderable": false, "searchable":  false, "targets": [ 'NoSort' ] },
1899                         { "type": "anti-the", "targets":  [ "anti-the" ] }
1900                     ],
1901                     "pagingType": "full"
1902                 }));
1903             [% END %]
1904
1905         });
1906
1907         [% IF found1 && Koha.Preference('RetainCatalogSearchTerms') %]
1908             $(document).ready(function() {
1909                 var search_index = localStorage.getItem("cat_search_pulldown_selection");
1910                 var search_value = localStorage.getItem("searchbox_value");
1911                 if ( search_index ){ $('#cat-search-block select.advsearch').val(search_index)};
1912                 if ( search_value ){ $('#cat-search-block #search-form').val(search_value)};
1913             });
1914         [% END %]
1915
1916         [% IF Koha.Preference('EnableItemGroups') %]
1917             // Load item groups table
1918             var itemGroupsTable = $("#items-group-table").kohaTable({
1919                 autoWidth: false,
1920                 dom: '<"top pager"ilp>t<"bottom pager"ip>r',
1921                 columns: [
1922                     {
1923                         data: "display_order",
1924                         title: _("Display order"),
1925                         searchable: true,
1926                         orderable: true,
1927                     },
1928                     {
1929                         data: "description",
1930                         title: _("Description"),
1931                         searchable: true,
1932                         orderable: true,
1933                     },
1934                     {
1935                         data: function( oObj ) {
1936                             [% IF CAN_user_editcatalogue_manage_item_groups %]
1937                                 return `<button class='item-group-edit btn btn-default btn-xs' data-item-group-id='${oObj.item_group_id}'>
1938                                     <i class="fa-solid fa-pencil" aria-hidden="true"></i> ${_("Edit")}
1939                                 </button>`
1940                                 + '&nbsp'
1941                                 + `<button class='item-group-delete btn btn-default btn-xs' data-item-group-id='${oObj.item_group_id}'>
1942                                     <i class='fa fa-trash-can'></i> ${('Delete')}
1943                                 </button>`;
1944                             [% ELSE %]
1945                                 return "";
1946                             [% END %]
1947                         },
1948                         searchable: false,
1949                         orderable: false,
1950                     },
1951                 ],
1952                 paginate: false,
1953                 ajax: { url: `/api/v1/biblios/${biblionumber}/item_groups?_per_page=-1` },
1954             });
1955
1956             // Create new item groups
1957             $('.item-group-create').on('click', function(){
1958                 $('#modal-item-group-create-form-description').val("");
1959                 $('#modal-item-group-create-submit').removeAttr('disabled');
1960                 $('#modal-item-group-create').modal('show');
1961             });
1962
1963             $("#modal-item-group-create-form").validate({
1964                 submitHandler: function(form) {
1965                     $.ajax({
1966                         url: `/api/v1/biblios/${biblionumber}/item_groups`,
1967                         headers: { "x-koha-embed": "items" },
1968                         success: function(item_groups){
1969                             $('#modal-item-group-create-submit').attr('disabled', 'disabled');
1970
1971                             var settings = {
1972                               "url": `/api/v1/biblios/${biblionumber}/item_groups`,
1973                               "method": "POST",
1974                               "headers": {
1975                                 "Content-Type": "application/json"
1976                               },
1977                               "data": JSON.stringify(
1978                                   {
1979                                       "description": $("#modal-item-group-create-form-description").val(),
1980                                       "display_order": $("#modal-item-group-create-form-display_order").val(),
1981                                   }
1982                               ),
1983                             };
1984
1985                             $.ajax(settings)
1986                             .done(function (response) {
1987                                 $('#item-group-add-form-select').append($('<option>', {
1988                                     value: response.item_group_id,
1989                                     text: response.description
1990                                 }));
1991
1992                                 $('#modal-item-group-create').modal('hide');
1993                                 if ( item_groups.length == 0 ) {
1994                                     // This bib has no previous item groups, reload the page
1995                                     window.location.replace(`/cgi-bin/koha/catalogue/detail.pl?biblionumber=${biblionumber}`);
1996                                 } else {
1997                                     // Has other item groups, just reload the table
1998                                     itemGroupsTable.api().ajax.reload();
1999                                 }
2000                             })
2001                             .fail(function(err) {
2002                                 var message = err.responseJSON.error;
2003                                 alert(message);
2004                             });
2005                         }
2006                     });
2007                 }
2008             });
2009
2010             $('#modal-item-group-create').on('shown.bs.modal', function () {
2011                 $('#modal-item-group-create-form-description').focus();
2012             })
2013
2014             // Edit existing item groups
2015             $('body').on( 'click', '.item-group-edit', function(){
2016                 const item_group_id = $(this).data('item-group-id');
2017                 const url = `/api/v1/biblios/${biblionumber}/item_groups/${item_group_id}`;
2018                 $.get( url, function( data ) {
2019                     $('#modal-item-group-edit-form-description').val( data.description );
2020                     $('#modal-item-group-edit-form-display_order').val( data.display_order );
2021                     $('#modal-item-group-edit-submit').data('item-group-id', item_group_id );
2022                     $('#modal-item-group-edit-submit').removeAttr('disabled');
2023                     $('#modal-item-group-edit').modal('show');
2024                 });
2025             });
2026
2027             $("#modal-item-group-edit-form").validate({
2028                 submitHandler: function(form) {
2029                     $('#modal-item-group-edit-submit').attr('disabled', 'disabled');
2030
2031                     const item_group_id = $('#modal-item-group-edit-submit').data('item-group-id');
2032                     const url = `/api/v1/biblios/${biblionumber}/item_groups/${item_group_id}`;
2033
2034                     var settings = {
2035                       "url": url,
2036                       "method": "PUT",
2037                       "headers": {
2038                         "Content-Type": "application/json"
2039                       },
2040                       "data": JSON.stringify(
2041                           {
2042                               "description": $("#modal-item-group-edit-form-description").val(),
2043                               "display_order": $("#modal-item-group-edit-form-display_order").val(),
2044                           }
2045                       ),
2046                     };
2047
2048                     $.ajax(settings)
2049                     .done(function (response) {
2050                         $('#modal-item-group-edit').modal('hide');
2051                         itemGroupsTable.api().ajax.reload();
2052                     })
2053                     .fail(function(err) {
2054                         var message = err.responseJSON.error;
2055                         alert(message);
2056                     });
2057                 }
2058             });
2059
2060             $('#modal-item-group-edit').on('shown.bs.modal', function () {
2061                 $('#modal-item-group-edit-form-description').focus();
2062             })
2063
2064             // Delete existing item groups
2065             $('body').on( 'click', '.item-group-delete', function(){
2066                 const item_group_id = $(this).data('item-group-id');
2067                 $('#modal-item-group-delete-submit').data('item-group-id', item_group_id );
2068                 $('#modal-item-group-delete-submit').removeAttr('disabled');
2069                 $('#modal-item-group-delete').modal('show');
2070             });
2071             $("#modal-item-group-delete-submit").on('click', function(){
2072                 $('#modal-item-group-delete-submit').attr('disabled', 'disabled');
2073                 const item_group_id = $("#modal-item-group-delete-submit").data('item-group-id');
2074
2075                 $.ajax({
2076                     url: `/api/v1/biblios/${biblionumber}/item_groups/${item_group_id}`,
2077                     headers: { "x-koha-embed": "items" },
2078                     success: function(item_group_data){
2079                         $.ajax({
2080                           "url": `/api/v1/biblios/${biblionumber}/item_groups/${item_group_id}`,
2081                           "method": "DELETE",
2082                         })
2083                         .done(function (response) {
2084                             $('#modal-item-group-delete').modal('hide');
2085                             $(`#item-group-add-form-select option[value='${item_group_id}']`).remove();
2086                             if ( item_group_data.items === null ) {
2087                                 // No items for this item group, we can just refresh the table
2088                                 itemGroupsTable.api().ajax.reload();
2089                             } else {
2090                                 // This item group had items attached to it, we need to reload the page
2091                                 window.location.replace(`/cgi-bin/koha/catalogue/detail.pl?biblionumber=${biblionumber}`);
2092                             }
2093                         })
2094                         .fail(function(err) {
2095                             var message = err.responseJSON.error;
2096                             alert(message);
2097                         });
2098                     }
2099                 });
2100             });
2101
2102             // Add item(s) to a item group
2103             $('.itemselection_action_item_group_set').on('click', function(){
2104                 $('#modal-item-group-set').modal('show');
2105             });
2106
2107             $("#modal-item-group-set-form").validate({
2108                 submitHandler: function(form) {
2109                     $('#modal-item-group-set-submit').attr('disabled', 'disabled');
2110
2111                     const item_group_id = $('#item-group-add-form-select').val();
2112
2113                     let itemnumbers = new Array();
2114                     $("input[name='itemnumber'][type='checkbox']:checked").each(function() {
2115                         const itemnumber = $(this).val();
2116                         itemnumbers.push( itemnumber );
2117                     });
2118                     if (itemnumbers.length > 0) {
2119                         let url = '/cgi-bin/koha/catalogue/detail.pl?op=set_item_group';
2120                         url += '&itemnumber=' + itemnumbers.join('&itemnumber=');
2121                         url += '&biblionumber=[% biblionumber | uri %]';
2122                         url += `&item_group_id=${item_group_id}`;
2123
2124                         window.location.replace(url);
2125                     }
2126
2127                     $('#modal-item-group-set').modal('hide');
2128                 }
2129             });
2130
2131             // Remove item(s) from an item group
2132             $('.itemselection_action_item_group_unset').on('click', function(){
2133                 $('#modal-item-group-unset').modal('show');
2134             });
2135
2136             $("#modal-item-group-unset-submit").on('click', function(){
2137                 $('#modal-item-group-unset-submit').attr('disabled', 'disabled');
2138
2139                 let itemnumbers = new Array();
2140                 $("input[name='itemnumber'][type='checkbox']:checked").each(function() {
2141                     const itemnumber = $(this).val();
2142                     itemnumbers.push( itemnumber );
2143                 });
2144                 if (itemnumbers.length > 0) {
2145                     let url = '/cgi-bin/koha/catalogue/detail.pl?op=unset_item_group';
2146                     url += '&itemnumber=' + itemnumbers.join('&itemnumber=');
2147                     url += '&biblionumber=[% biblionumber | uri %]';
2148
2149                     window.location.replace(url);
2150                 }
2151
2152                 $('#modal-item-group-unset').modal('hide');
2153
2154             });
2155         [% END %]
2156         const can_edit_items_from = [% To.json(can_edit_items_from || {}) | $raw %];
2157         const item_type_image_locations = [% To.json(item_type_image_locations) | $raw %];
2158         const av_loc = new Map([% To.json(AuthorisedValues.Get('LOC')) | $raw %].map( av => [av.authorised_value, av.lib]));
2159         const av_lost = new Map([% To.json(AuthorisedValues.GetDescriptionsByKohaField({ kohafield => 'items.itemlost' })) | $raw %].map( av => [av.authorised_value, av.lib]));
2160         const av_withdrawn = new Map([% To.json(AuthorisedValues.GetDescriptionsByKohaField({ kohafield => 'items.withdrawn' })) | $raw %].map( av => [av.authorised_value, av.lib]));
2161         const av_damaged = new Map([% To.json(AuthorisedValues.GetDescriptionsByKohaField({ kohafield => 'items.damaged' })) | $raw %].map( av => [av.authorised_value, av.lib]));
2162         const av_not_for_loan= new Map([% To.json(AuthorisedValues.GetDescriptionsByKohaField({ kohafield => 'items.notforloan' })) | $raw %].map( av => [av.authorised_value, av.lib]));
2163         const av_restricted = new Map([% To.json(AuthorisedValues.GetDescriptionsByKohaField({ kohafield => 'items.restricted' })) | $raw %].map( av => [av.authorised_value, av.lib]));
2164         [% IF Koha.Preference('UseCourseReserves') %]
2165             const av_courses_term = new Map([% To.json(AuthorisedValues.Get('TERM')) | $raw %].map( av => [av.authorised_value, av.lib]));
2166         [% END %]
2167         [% IF Koha.Preference('URLLinkText') %]
2168             const url_link_text = "[% Koha.Preference('URLLinkText') | html %]";
2169         [% ELSE %]
2170             const url_link_text = _("Link to resource");
2171         [% END %]
2172         [%# FIXME The X-Base-Total-Count will be the number of items of the biblios %]
2173         [%# In case or SeparateHoldings we may need to display the number of biblios in each tab %]
2174         [%# Do we need separate/new endpoints or do we hack the somewhere client-side? %]
2175         let item_table_url = "/api/v1/biblios/[% biblio.biblionumber | uri %]/items?";
2176         let embed = ["+strings,checkout,checkout.patron,transfer,first_hold,first_hold.patron,item_type"];
2177         [% IF Koha.Preference('LocalCoverImages') %]
2178             embed.push('cover_image_ids');
2179         [% END %]
2180         [% IF Koha.Preference('EnableItemGroups') %]
2181             embed.push('item_group_item.item_group.description');
2182         [% END %]
2183         [% IF biblio.serial %]
2184             embed.push('serialitem.serial');
2185         [% END %]
2186         [% IF Koha.Preference('UseRecalls') %]
2187             embed.push('recall', 'recall.patron')
2188         [% END %]
2189         embed.push('in_bundle', 'bundle_host');
2190         [% IF Koha.Preference('UseCourseReserves') %]
2191             embed.push('course_item.course_reserves.course');
2192         [% END %]
2193
2194         function build_table (table_id, table_settings, filters) {
2195             [% IF hidden_count %]
2196                 filters.lost_status = "0";
2197             [% END %]
2198             var items_table = $("#" + table_id).kohaTable({
2199                 ajax: { url: item_table_url },
2200                 order: [[ 0, "asc" ]],
2201                 embed,
2202                 autoWidth: false,
2203                 bKohaColumnsUseNames: true, // FIXME We should not need that now, do we?
2204                 columns: [
2205                 [% IF (StaffDetailItemSelection) %]
2206                 {
2207                     data: "me.item_id",
2208                     searchable: false,
2209                     orderable: false,
2210                     render: function (data, type, row, meta) {
2211                         if ( can_edit_items_from[row.holding_library_id] ){
2212                             return '<input type="checkbox" value="%s" name="itemnumber" />'.format(row.item_id);
2213                         } else {
2214                             return ''
2215                         }
2216                     }
2217                 },
2218                 [% END %]
2219                 [% IF Koha.Preference('LocalCoverImages') %]
2220                 {
2221                     data: "",
2222                     className: "cover",
2223                     searchable: false,
2224                     orderable: false,
2225                     render: function (data, type, row, meta) {
2226                         if ( !row.cover_image_ids.length > 0 ) {
2227                             return '';
2228                         }
2229                         let node = '<div class="bookcoverimg">';
2230                         node += '<div class="cover-slider">';
2231                         row.cover_image_ids.forEach(id => {
2232                             node += '<div class="cover-image local-coverimg">';
2233                             node += '<a href="/cgi-bin/koha/catalogue/image.pl?itemnumber=%s&amp;imagenumber=%s" title="Local cover image">'.format(id, id);
2234                             node += '<img src="/cgi-bin/koha/catalogue/image.pl?thumbnail=1&amp;imagenumber=%s" alt="Local cover image" data-link="/cgi-bin/koha/catalogue/imageviewer.pl?itemnumber=[% item.itemnumber | uri %]&amp;imagenumber=%s" />'.format(id, id);
2235                             node += '</a>';
2236                             node += '</div>';
2237                         });
2238                         node += '</div>';
2239                         node += '</div>';
2240                         return node;
2241                     }
2242                 },
2243                 [% END %]
2244                 [% IF ( item_level_itypes ) %]
2245                 {
2246                     data: "me.itype:biblioitem.itemtype",
2247                     className: "itype",
2248                     searchable: true,
2249                     orderable: true,
2250                     render: function (data, type, row, meta) {
2251                         let node = '';
2252                         [% UNLESS noItemTypeImages %]
2253                             let image_location = item_type_image_locations[row.item_type_id];
2254                             let item_type_description = row._strings.item_type_id.str;
2255                             node += image_location
2256                                 ? '<img src="%s" alt="%s" title="%s" /> '.format(image_location, item_type_description, item_type_description)
2257                                 : '';
2258                         [% END %]
2259                         node += '<span class="itypedesc itypetext">%s</span>'.format(item_type_description);
2260                         return node;
2261                     }
2262                 },
2263                 [% END %]
2264                 {
2265                     data: "me.holding_library_id",
2266                     className: "location",
2267                     searchable: true,
2268                     orderable: true,
2269                     render: function (data, type, row, meta) {
2270                         return row._strings.holding_library_id.str;
2271                     }
2272                 },
2273                 {
2274                     data: "me.home_library_id",
2275                     className: "homebranch",
2276                     searchable: true,
2277                     orderable: true,
2278                     render: function (data, type, row, meta) {
2279                         let nodes = '<span class="homebranchdesc">%s</span>'.format(row._strings.home_library_id.str);
2280                         nodes += '<span class="shelvingloc">'
2281                         [%# If permanent location is defined, show description or code and             %]
2282                         [%# display current location in parentheses. If not, display current location. %]
2283                         [%# Note that permanent location is a code, and location may be an authval.    %]
2284                         let loc_str = row._strings.location.str;
2285                         if ( row.permanent_location && row.permanent_location != row.location ) {
2286                             let permanent_loc_str = av_loc[row.permanent_location];
2287                             nodes += '%s (%s)'.format(permanent_loc_str, loc_str);
2288                         } else {
2289                             nodes += loc_str;
2290                         }
2291                         nodes += '</span>';
2292                         return nodes;
2293                     }
2294                 },
2295                 {
2296                     data: "me.collection_code",
2297                     searchable: true,
2298                     orderable: true,
2299                     render: function (data, type, row, meta) {
2300                         return row._strings.collection_code.str;
2301                     }
2302                 },
2303                 [% IF Koha.Preference('EnableItemGroups') %]
2304                 {
2305                     data: "item_group_item.item_group.description",
2306                     className: "item_group",
2307                     searchable: true,
2308                     orderable: true,
2309                     render: function (data, type, row, meta) {
2310                         if ( row.item_group_item ) {
2311                             return row.item_group_item.item_group.description;
2312                         } else {
2313                             return "";
2314                         }
2315                     }
2316                 },
2317                 [% END %]
2318                 {
2319                     data: "me.callnumber",
2320                     className: "itemcallnumber",
2321                     searchable: true,
2322                     orderable: true,
2323                     render: function (data, type, row, meta) {
2324                         return row.callnumber;
2325                     }
2326
2327                 },
2328                 {
2329                     data: "me.serial_issue_number",
2330                     className: "enumchron",
2331                     searchable: true,
2332                     orderable: true,
2333                     render: function (data, type, row, meta) {
2334                         let nodes = "";
2335                         [%# FIXME Previously we displayed the column if at least one item of the biblio had an enumchron/serial_issue_number. Now it's only if one item of the ones displayed on the current page, how is that bad? How can it be fixed in an elegant way? Should we display the column only if biblio.serial? %]
2336                         let serial = row.serialitem ? row.serialitem.serial : null;
2337                         if ( row.serial_issue_number && serial && serial.serialseq ) {
2338                             nodes += '<span class="enum">%s</span>'.format(row.serial_issue_number);
2339                             if ( serial.serialseq && row.serial_issue_number != serial.serialseq ) {
2340                                 nodes += ' <span class="sep"> -- </span>'
2341                                 nodes += ' <span class="serialseq">%s</span>'.format(serial.serialseq);
2342                             }
2343                         } else if ( row.serial_issue_number ) {
2344                             nodes += ' <span class="enum">%s</span>'.format(row.serial_issue_number);
2345                         } else if ( serial && serial.serialseq ) {
2346                             nodes += '<span class="serialseq">%s</span>'.format(serial.serialseq);
2347                         }
2348                         if ( serial && serial.publisheddate ) {
2349                             nodes += ' <span class="pubdate">(%s)</span>'.format($date(serial.publisheddate));
2350                         }
2351                         return nodes;
2352                     }
2353                 },
2354                 {
2355                     data: "me.lost_status",
2356                     className: "status",
2357                     searchable: false, // FIXME We are losing the ability to search on the status
2358                     orderable: false,
2359                     render: function (data, type, row, meta) {
2360                         let nodes = "";
2361                         if ( row.checkout ) {
2362                             nodes += '<span>';
2363                             if ( row.checkout.onsite_checkout ) {
2364                                 let patron_to_html = $patron_to_html(row.checkout.patron); [%# FIXME What about hide_patron_infos_if_needed?? %]
2365                                 nodes += _("Currently in local use by %s").format(patron_to_html);
2366                             } else {
2367                                 nodes += '<span class="datedue">';
2368                                 let patron_to_html = $patron_to_html(row.checkout.patron); [%# FIXME What about hide_patron_infos_if_needed?? %]
2369                                 nodes += _("Checked out to %s").format(patron_to_html);
2370                             }
2371                             nodes += ': ';
2372                             nodes += _("due %s").format($date(row.checkout.due_date)); [%# FIXME Missing due date formatting here, $date do not have as_due_date option %]
2373                             nodes += "</span>"
2374                         } else if ( row.transfer ) {
2375                             if ( row.transfer.datesent ) {
2376                                 nodes += '<span class="intransit">%s</span>'.format(_("In transit from %s to %s since %s").format(row.transfer.frombranch, row.transfer.tobranch, $date(row.transfer.datesent))); [%# FIXME display library names, not codes, do we use _strings here? %]
2377                             } else {
2378                                 nodes += '<span class="transitrequested">%s</span>'.format(_("Transit pending from %s to %s since %s").format(row.transfer.frombranch, row.transfer.tobranch, $date(row.transfer.daterequested))); [%# FIXME See above %]
2379                             }
2380                         }
2381
2382                         if ( row.lost_status ) {
2383                             let lost_lib = av_lost.get(row.lost_status.toString()) || _("Unavailable (lost or missing");
2384                             nodes += '<span class="lost">%s</span>'.format(lost_lib);
2385                         }
2386
2387                         if ( row.withdrawn ) {
2388                             let withdrawn_lib = av_withdrawn.get(row.withdrawn.toString()) || _("Withdrawn");
2389                             nodes += '<span class="wdn">%s</span>'.format(withdrawn_lib);
2390                         }
2391
2392                         if ( row.damaged ) {
2393                             let damaged_lib = av_damaged.get(row.damaged.toString()) || _("Damaged");
2394                             nodes += '<span class="dmg">%s</span>'.format(damaged_lib);
2395                         }
2396
2397                         if ( row.not_for_loan_status || row.item_type.notforloan ) {
2398                             let not_for_loan_lib = av_not_for_loan.get(row.not_for_loan_status.toString());
2399                             nodes += '<span class="notforloan">%s'.format(_("Not for loan")) + ( not_for_loan_lib ? '<span class="reason"> (%s)</span>'.format(not_for_loan_lib) : '' ) + '</span>';
2400                         }
2401
2402                         if ( row.first_hold ) {
2403                             if ( row.first_hold.waiting_date ) {
2404                                 [%# FIXME Display library names instead of codes %]
2405                                 [%# FIXME We lost the desk name, we need an additional embed %]
2406                                 nodes += '<span class="waitingat">%s</span>'.format(_("Waiting at %s since %s.".format(row.first_hold.pickup_library_id, $date(row.first_hold.waiting_date))));
2407                                 [% IF Koha.Preference('canreservefromotherbranches') %]
2408                                     if ( row.first_hold.waiting_date || row.first_hold.priority == 1 ) {
2409                                         let patron_to_html = $patron_to_html(row.first_hold.patron); [%# FIXME What about hide_patron_infos_if_needed?? %]
2410                                         nodes += ' <span class="heldfor">%s</span>'.format(_("Hold for: %s").format(patron_to_html));
2411                                     }
2412                                 [% END %]
2413                             } else {
2414                                 nodes += '<span class="holdonitem">%s</span>'.format(_("There is an item level hold on this item (priority = %s).").format(row.first_hold.priority));
2415                             }
2416                         }
2417
2418                         [% IF Koha.Preference('UseRecalls') %]
2419                             if ( row.recall ) {
2420                                 if ( row.recall.waiting_date ) {
2421                                     nodes += '<span>%s</span>'.format(_("Waiting at %s since %s").format(row.recall.pickup_library_id, $date(row.recall.waiting_date))); # FIXME Display library names instead of codes
2422                                 } else {
2423                                     let patron_to_html = $patron_to_html(row.recall.patron);
2424                                     nodes += '<span>%s</span>'.format(_("recalled by %s on %s").format(patron_to_html, row.recall.created_date))
2425                                 }
2426                             }
2427                         [% END %]
2428
2429                         if ( ! ( row.not_for_loan_status || row.item_type.notforloan || row.checked_out_date || row.lost_status || row.withdrawn || row.damaged || row.transfer || row.first_hold || row.recall ) ) {
2430                             nodes += ' <span>%s</span>'.format(_("Available"))
2431                         }
2432
2433                         if ( row.restricted_status ) {
2434                             nodes += '<span class="restricted">(%s)</span>'.format(av_restricted.get(row.restricted_status.toString()));
2435                         }
2436
2437                         if ( row.in_bundle ) {
2438                             nodes += '<span class="bundled">%s</span>'.format(_("In bundle: %s").format($biblio_to_html(row.bundle_host.biblio, { link: true })));
2439                         }
2440                         return nodes;
2441                     }
2442                 },
2443                 {
2444                     data: "me.last_seen_date",
2445                     className: "datelastseen",
2446                     searchable: true,
2447                     orderable: true,
2448                     render: function (data, type, row, meta) {
2449                         return $date(row.last_seen_date);
2450                     }
2451                 },
2452                 {
2453                     data: "me.checkouts_count",
2454                     className: "issues",
2455                     searchable: true,
2456                     orderable: true,
2457                     render: function (data, type, row, meta) {
2458                         return row.checkouts_count || 0;
2459                     }
2460                 },
2461                 {
2462                     data: "me.renewals_count",
2463                     className: "renewals",
2464                     searchable: true,
2465                     orderable: true,
2466                     render: function (data, type, row, meta) {
2467                         return row.renewals_count || 0;
2468                     }
2469                 },
2470                 {
2471                     data: "me.acquisition_date",
2472                     className: "dateaccessioned",
2473                     searchable: true,
2474                     orderable: true,
2475                     render: function (data, type, row, meta) {
2476                         return $date(row.acquisition_date);
2477                     }
2478                 },
2479                 {
2480                     data: "me.last_checkout_date",
2481                     className: "datelastborrowed",
2482                     searchable: true,
2483                     orderable: true,
2484                     render: function (data, type, row, meta) {
2485                         return $date(row.last_checkout_date);
2486                     }
2487                 },
2488                 {
2489                     data: "me.external_id",
2490                     className: "",
2491                     searchable: true,
2492                     orderable: true,
2493                     render: function (data, type, row, meta) {
2494                         return '<a href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=%s#item%s">%s</a>'.format(row.biblio_id, row.item_id, row.external_id);
2495                     }
2496                 },
2497                 {
2498                     data: "me.uri",
2499                     className: "uri",
2500                     searchable: true,
2501                     orderable: true,
2502                     render: function (data, type, row, meta) {
2503                         if ( !row.uri ) return "";
2504
2505                         let nodes = '';
2506                         if ( row.uri.split(' \| ').length > 1 ) {
2507                             row.uri.split(' \| ').forEach((uri, i) => {
2508                                 nodes += '<a href="%s">%s</a><br/>'.format(uri, uri);
2509                             });
2510                         } else {
2511                             nodes += '<a href="%s">%s</a><br/>'.format(row.uri, url_link_text);
2512                         }
2513                         return nodes;
2514                     }
2515                 },
2516                 {
2517                     data: "me.copy_number",
2518                     className: "copynumber",
2519                     searchable: true,
2520                     orderable: true,
2521                     render: function (data, type, row, meta) {
2522                         return row._strings.copy_number ? row._strings.copy_number.str : row.copy_number;
2523                     }
2524                 },
2525                 {
2526                     data: "me.inventory_number",
2527                     className: "stocknumber",
2528                     searchable: true,
2529                     orderable: true,
2530                     render: function (data, type, row, meta) {
2531                         return row.inventory_number;
2532                     }
2533                 },
2534                 {
2535                     data: "me.materials_notes",
2536                     className: "materials",
2537                     searchable: true,
2538                     orderable: true,
2539                     render: function (data, type, row, meta) {
2540                         return row.materials_notes;
2541                     }
2542                 },
2543                 {
2544                     data: "me.public_notes",
2545                     className: "itemnotes",
2546                     searchable: true,
2547                     orderable: true,
2548                     render: function (data, type, row, meta) {
2549                         return row.public_notes ? row.public_notes.replaceAll('\n', '<br />') : '';
2550                     }
2551                 },
2552                 {
2553                     data: "me.internal_notes",
2554                     className: "nonpublicnote",
2555                     searchable: true,
2556                     orderable: true,
2557                     render: function (data, type, row, meta) {
2558                         return row.internal_notes;
2559                     }
2560                 },
2561                 [% IF ( hostrecords ) %]
2562                 {
2563                     data: "biblio.biblio_id",
2564                     searchable: false, // FIXME
2565                     orderable: true,
2566                     render: function (data, type, row, meta) {
2567                         if ( row.biblio_id == [% biblio.biblionumber | html %] ) return "";
2568                         return '<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=%s>%s</a>'.format(row.biblio_id, row.biblio.title);
2569                     }
2570                 },
2571                 [% END %]
2572                 [% IF ( analyze ) %]
2573                 {
2574                     data: "",
2575                     searchable: false, // FIXME
2576                     orderable: true,
2577                     render: function (data, type, row, meta) {
2578                         return ""; // FIXME Display analytic count + link
2579                     }
2580                 },
2581                 [% END %]
2582                 [% IF Koha.Preference('UseCourseReserves') %]
2583                 {
2584                     data: "course_item.course_reserves.course.course_name",
2585                     searchable: true,
2586                     orderable: true,
2587                     render: function (data, type, row, meta) {
2588                         let nodes = '';
2589                         if (!row.course_item) return nodes;
2590                         row.course_item.course_reserves.forEach((cr, i) => {
2591                             let c = cr.course;
2592                             if ( c.enabled != 'yes' ) return;
2593                             nodes += '<p>';
2594                             nodes += '<a href="/cgi-bin/koha/course_reserves/course-details.pl?course_id=%s">'.format(c.course_id);
2595                             nodes += c.course_name;
2596                             if ( c.section ) {
2597                                 nodes += ' ' + c.section;
2598                             }
2599                             if ( c.term ) {
2600                                 nodes += ' ' + av_courses_term.get(c.term.toString());
2601                             }
2602                             nodes += '</p>';
2603                         });
2604                         return nodes;
2605                     }
2606                 },
2607                 [% END %]
2608                 [% IF ( SpineLabelShowPrintOnBibDetails ) %]
2609                 {
2610                     data: "",
2611                     searchable: false,
2612                     orderable: false,
2613                     render: function (data, type, row, meta) {
2614                         return '<a class="btn btn-default btn-xs print-label" href="/cgi-bin/koha/labels/spinelabel-print.pl?barcode=%s"><i class="fa fa-print"></i> Print label</a>'.format(row.external_id);
2615                     }
2616                 },
2617                 [% END %]
2618                 [% IF CAN_user_editcatalogue_edit_items %]
2619                 {
2620                     data: function( row, type, val, meta ) {
2621                         let nodes = '';
2622                         if ( can_edit_items_from[row.holding_library_id] ){
2623                             [% IF Koha.Preference('LocalCoverImages') OR Koha.Preference('OPACLocalCoverImages') %]
2624                                 nodes += '<div class="btn-group">';
2625                                 nodes += ' <a class="btn btn-default btn-xs" href="/cgi-bin/koha/cataloguing/additem.pl?op=edititem&biblionumber=%s&itemnumber=%s#edititem"><i class="fa-solid fa-pencil"></i> Edit</a><a class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></a>'.format(row.biblio_id, row.item_id);
2626                                 nodes += ' <ul class="dropdown-menu pull-right">';
2627                                 nodes += '  <li><a href="/cgi-bin/koha/tools/upload-cover-image.pl?itemnumber=%s&amp;filetype=image"><i class="fa fa-upload"></i> Upload image</a></li>'.format(row.item_id);
2628                                 nodes += ' </ul>';
2629                                 nodes += '</div>';
2630                             [% ELSE %]
2631                                 nodes += '<a class="btn btn-default btn-xs" href="/cgi-bin/koha/cataloguing/additem.pl?op=edititem&biblionumber=%s&itemnumber=%s#edititem"><i class="fa-solid fa-pencil"></i> Edit</a>'.format(row.biblio_id, row.item_id);
2632                             [% END %]
2633                         }
2634                         [% IF bundlesEnabled %]
2635                             // FIXME How do we handle that correctly?
2636                             //nodes += '<button class="btn btn-default btn-xs details-control"><i class="fa fa-folder"></i> Manage bundle (%s|%s)</button>'.format(row.bundled, row.bundled_lost);
2637                         [% END %]
2638
2639                         return nodes;
2640                     },
2641                     className: "actions",
2642                     searchable: false,
2643                     orderable: false
2644                 }
2645                 [% END %]
2646                 ],
2647                 initComplete: function( settings, json ){
2648                     let table = settings.oInstance.api();
2649                     table.columns().every(function(i){
2650                         let is_empty = true;
2651                         let nodes = this.nodes();
2652                         nodes.each((td, ii) => {
2653                             if ( $(td).html() !== '' ) {
2654                                 is_empty = false;
2655                                 return;
2656                             }
2657                         });
2658                         if ( is_empty ) {
2659                             table.columns(i).visible(false);
2660                         }
2661                     });
2662                 },
2663             },
2664             table_settings,
2665             true,
2666             filters,
2667             );
2668             return items_table;
2669         }
2670     </script>
2671     [% CoverImagePlugins | $raw %]
2672 [% END %]
2673 [% INCLUDE 'intranet-bottom.inc' %]