Bug 27936: Clarify AllowItemsOnHoldCheckoutSIP syspref help text
[koha.git] / koha-tmpl / intranet-tmpl / prog / en / modules / admin / transfer_limits.tt
1 [% USE raw %]
2 [% USE To %]
3 [% USE Asset %]
4 [% USE Branches %]
5 [% USE Koha %]
6 [% USE ItemTypes %]
7 [% USE AuthorisedValues %]
8 [% SET footerjs = 1 %]
9 [% INCLUDE 'doc-head-open.inc' %]
10 <title>Koha &rsaquo; Administration &rsaquo; Library checkin and transfer policy</title>
11 [% INCLUDE 'doc-head-close.inc' %]
12 <style>td { text-align: center; } .sorted { min-width: 50%; }</style>
13 </head>
14
15 [% SET BranchTransferLimitsType = Koha.Preference('BranchTransferLimitsType') %]
16 [% SET branches = Branches.all %]
17
18 <body id="admin_branch_transfer_limits" class="admin">
19 [% INCLUDE 'header.inc' %]
20 [% INCLUDE 'prefs-admin-search.inc' %]
21
22 <div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> &rsaquo; Set library checkin and transfer policy</div>
23
24 <div class="main container-fluid">
25     <div class="row">
26         <div class="col-sm-10 col-sm-push-2">
27             <main>
28                 <h1>Checkin and transfer policy</h1>
29
30                 <p>
31                     [% IF BranchTransferLimitsType == "itemtype" %]
32                         <label for="value_selector">Select an item type:</label>
33                         <select id="value_selector">
34                             <option value="" selected></option>
35                             [% SET itemtypes = ItemTypes.Get %]
36                             [%  FOREACH i IN itemtypes %]
37                                 <option value="[% i.itemtype | html %]">[% i.description | html %]</option>
38                             [% END %]
39                         </select>
40                     [% ELSE #BranchTransferLimitsType == "ccode" %]
41                         <label for="value_selector">Select a collection:</label>
42                         <select id="value_selector">
43                             <option value="" selected></option>
44                             [% SET ccodes = AuthorisedValues.Get('CCODE') %]
45                             [%  FOREACH c IN ccodes %]
46                                 <option value="[% c.authorised_value | html %]">[% c.lib | html %]</option>
47                             [% END %]
48                         </select>
49                     [% END %]
50
51                     <span id="loading_limits">
52                         <i class="fa fa-spinner fa-pulse fa-fw"></i>
53                         <span>Loading...</span>
54                     </span>
55                 </p>
56
57                 <p class="help">Check the boxes for the libraries you allow your items to be transferred to.</p>
58                 <fieldset>
59                     <a id="check-all" class="limit-action" href="#"><i class="fa fa-check"></i> Check all</a>
60                     |
61                     <a id="uncheck-all" class="limit-action" href="#"><i class="fa fa-remove"></i> Uncheck all</a>
62                     |
63                     <a href="/cgi-bin/koha/admin/branch_transfer_limits.pl">Switch to basic editor</a>
64                 </fieldset>
65
66                 <table id="transfer_limits" class="table table-striped table-bordered table-hover table-condensed">
67
68                     <thead>
69                         <tr>
70                             <td>&nbsp;</td>
71                             <td>&nbsp;</td>
72                             [% FOREACH to IN branches %]
73                                 <td>
74                                     <p><a class="btn btn-default btn-xs check-all-col limit-action" data-to="[% to.branchcode | html %]" href="#"><i class="fa fa-check"></i> Check</a></p>
75                                     <p><a class="btn btn-default btn-xs uncheck-all-col limit-action" data-to="[% to.branchcode | html %]" href="#"><i class="fa fa-remove"></i> Uncheck</a></p>
76                                 </td>
77                             [% END %]
78                         </tr>
79
80                         <tr>
81                             <td>&nbsp;</td>
82                             <th>From / To</th>
83                             [% FOREACH b IN branches %]
84                                 <th style="word-break: break-all !important" title="[% b.branchname | html %]">[% b.branchname | html %]</th>
85                             [% END %]
86                         </tr>
87                     </thead>
88
89                     <tbody>
90                         [% FOREACH from IN branches %]
91                             <tr>
92                                 <td>
93                                     <p><a class="btn btn-default btn-xs check-all-row limit-action" data-from="[% from.branchcode | html %]" href="#"><i class="fa fa-check"></i> Check</a></p>
94                                     <p><a class="btn btn-default btn-xs uncheck-all-row limit-action" data-from="[% from.branchcode | html %]" href="#"><i class="fa fa-remove"></i> Uncheck</a></p>
95                                 </td>
96                                 <th>[% from.branchname | html %]</th>
97                                 [% FOREACH to IN branches %]
98                                     <td class="checkbox-cell">
99                                         [% IF to.branchcode == from.branchcode %]
100                                             &nbsp;
101                                         [% ELSE %]
102                                             <input class="limit-checkboxes from-[% from.branchcode | html %] to-[% to.branchcode | html %]" id="limit-[% from.branchcode | html %]-[% to.branchcode | html %]" type="checkbox" title="From: [%  from.branchname | html %], To: [%  to.branchname | html %]" checked/>
103                                             <i id="spinner-limit-[% from.branchcode | html %]-[% to.branchcode | html %]" class="spinner fa fa-spinner fa-pulse fa-fw"></i>
104                                         [% END %]
105                                     </td>
106                                 [% END %]
107                             </tr>
108                         [% END %]
109                     </tbody>
110                 </table>
111             </main>
112         </div> <!-- /.col-sm-10.col-sm-push-2 -->
113
114         <div class="col-sm-2 col-sm-pull-10">
115             <aside>
116                 [% INCLUDE 'admin-menu.inc' %]
117             </aside>
118         </div> <!-- /.col-sm-2.col-sm-pull-10 -->
119     </div> <!-- /.row -->
120
121 [% MACRO jsinclude BLOCK %]
122     [% Asset.js("js/admin-menu.js") | $raw %]
123     [% INCLUDE 'datatables.inc' %]
124     <script>
125         const branchTransferLimitsType = "[% BranchTransferLimitsType | html %]";
126         const val_type = branchTransferLimitsType == "itemtype" ? "item_type" : "collection_code";
127         const branches = [% To.json(branches) | $raw %];
128
129         $('#loading_limits').hide();
130         $('.spinner').hide();
131
132         $(document).ready(function() {
133             $("#check-all").click(function() {
134                 const val = $('#value_selector').val();
135
136                 $('.limit-action').addClass('disabled');
137                 $('#value_selector').prop('disabled',true);
138
139                 let checkboxes = [];
140                 $(".limit-checkboxes").each(function() {
141                     const checkbox = $(this);
142                     if (checkbox.data('limit_id')) {
143                         checkboxes.push(checkbox);
144                         checkbox.hide();
145                         $(`#spinner-${checkbox.attr('id')}`).show();
146                     }
147                 });
148
149                 del_limits( checkboxes, val );
150                 return false;
151             });
152
153
154             $("#uncheck-all").click(function() {
155                 const val = $('#value_selector').val();
156
157                 $('.limit-action').addClass('disabled');
158                 $('#value_selector').prop('disabled',true);
159
160                 let checkboxes = [];
161                 $(".limit-checkboxes").each(function() {
162                     const checkbox = $(this);
163                     if (!checkbox.data('limit_id')) {
164                         checkboxes.push(checkbox);
165                         checkbox.hide();
166                         $(`#spinner-${checkbox.attr('id')}`).show();
167                     }
168                 });
169
170                 add_limits( checkboxes, val );
171                 return false;
172             });
173
174             $('.check-all-col').click(function() {
175                 let checkboxes = [];
176                 const to = $(this).data('to');
177                 const val = $('#value_selector').val();
178
179                 $('.limit-action').addClass('disabled');
180                 $('#value_selector').prop('disabled',true);
181
182                 $(`.to-${to}`).each(function() {
183                     const checkbox = $(this);
184                     if (checkbox.data('limit_id')) {
185                         checkboxes.push(checkbox);
186                         checkbox.hide();
187                         $(`#spinner-${checkbox.attr('id')}`).show();
188                     }
189                 });
190
191                 del_limits( checkboxes, val, to );
192                 return false;
193             });
194
195             $('.uncheck-all-col').click(function() {
196                 let checkboxes = [];
197                 const to = $(this).data('to');
198                 const val = $('#value_selector').val();
199
200                 $('.limit-action').addClass('disabled');
201                 $('#value_selector').prop('disabled',true);
202
203                 $(`.to-${to}`).each(function() {
204                     const checkbox = $(this);
205                     if (!checkbox.data('limit_id')) {
206                         checkbox.hide();
207                         $(`#spinner-${checkbox.attr('id')}`).show();
208                     }
209                 });
210
211                 add_limits( checkboxes, val, to );
212                 return false;
213             });
214
215             $('.check-all-row').click(function() {
216                 let checkboxes = [];
217                 const from = $(this).data('from');
218                 const val = $('#value_selector').val();
219
220                 $('.limit-action').addClass('disabled');
221                 $('#value_selector').prop('disabled',true);
222
223                 $(`.from-${from}`).each(function() {
224                     const checkbox = $(this);
225                     if (checkbox.data('limit_id')) {
226                         checkboxes.push(checkbox);
227                         checkbox.hide();
228                         $(`#spinner-${checkbox.attr('id')}`).show();
229                     }
230                 });
231
232                 del_limits( checkboxes, val, null, from );
233                 return false;
234             });
235
236
237             $('.uncheck-all-row').click(function() {
238                 let checkboxes = [];
239                 const from = $(this).data('from');
240                 const val = $('#value_selector').val();
241
242                 $('.limit-action').addClass('disabled');
243                 $('#value_selector').prop('disabled',true);
244
245                 $(`.from-${from}`).each(function() {
246                     const checkbox = $(this);
247                     if (!checkbox.data('limit_id')) {
248                         checkbox.hide();
249                         $(`#spinner-${checkbox.attr('id')}`).show();
250                     }
251                 });
252
253                 add_limits( checkboxes, val, null, from );
254                 return false;
255             });
256
257             $(".checkbox-cell").click(function(e) {
258                 var checkbox = $(this).find(".limit-checkboxes").get(0);
259                 if (checkbox && !checkbox.disabled) {
260                     if (e.target != checkbox) {
261                         checkbox.checked = !checkbox.checked;
262                         $(checkbox).change();
263                     }
264                 }
265             });
266
267             $("#value_selector").on('change', function() {
268                 const val = $('#value_selector').val();
269                 window.history.replaceState(null, "", `/cgi-bin/koha/admin/transfer_limits.pl?code=${val}`);
270                 updateTransferLimitsTable();
271             });
272
273             $(".limit-checkboxes").on('change', function() {
274                 const checkbox = $(this);
275                 const id = checkbox.attr('id');
276
277                 checkbox.hide();
278                 $(`#spinner-${id}`).show();
279
280                 const limit_id = checkbox.data('limit_id');
281
282                 if (limit_id) { // limit id exists, so limit needs to be deleted
283                     delLimit(checkbox);
284                 } else { // limit does not exist, needs to be created
285                     addLimit(checkbox);
286                 }
287             });
288
289             updateTransferLimitsTable();
290
291             const queryString = window.location.search;
292             const urlParams = new URLSearchParams(queryString);
293             const code = urlParams.get('code');
294             if ( code ) {
295                 $('#value_selector').val(code);
296                 updateTransferLimitsTable();
297             }
298         });
299
300         function delLimit(checkbox) {
301             const id = checkbox.attr('id');
302             const limit_id = checkbox.data('limit_id');
303
304             return $.ajax({
305                 url: `/api/v1/transfer_limits/${limit_id}`,
306                 type: 'DELETE',
307                 success: function(result) {
308                     checkbox.data('limit_id', null);
309                     checkbox.attr('checked', true);
310                     $(`#spinner-${id}`).hide();
311                     checkbox.show();
312                 },
313                 error: function(xhr, status, error) {
314                     var errorMessage = xhr.status + ': ' + xhr.statusText
315                     alert('Error - ' + errorMessage);
316                 }
317             });
318         }
319
320         function addLimit(checkbox) {
321             const id = checkbox.attr('id');
322             const parts = id.split('-');
323             const from = parts[1];
324             const to = parts[2];
325
326             const val = $('#value_selector').val();
327
328             let data = {
329                 to_library_id: to,
330                 from_library_id: from,
331             };
332             data[val_type] = val;
333             return $.ajax({
334                 url: `/api/v1/transfer_limits`,
335                 type: 'POST',
336                 data: JSON.stringify(data),
337                 dataType: 'json',
338                 success: function(result) {
339                     checkbox.data('limit_id', result.limit_id);
340                     checkbox.attr('checked', false);
341                     $(`#spinner-${id}`).hide();
342                     checkbox.show();
343                 },
344                 error: function(xhr, status, error) {
345                     var errorMessage = xhr.status + ': ' + xhr.statusText
346                     alert('Error - ' + errorMessage);
347                 }
348             });
349         }
350
351         function add_limits( checkboxes, val, to, from ){
352             let data = {};
353             data[val_type] = val;
354             if (to) data["to_library_id"] = to;
355             if (from) data["from_library_id"] = from;
356
357             return $.ajax({
358                 url: `/api/v1/transfer_limits/batch`,
359                 type: 'POST',
360                 data: JSON.stringify(data),
361                 dataType: 'json',
362                 success: function(result) {
363                     for ( i = 0; i < result.length; i++ ) {
364                         const r = result[i];
365                         let checkbox = $(`#limit-${r.from_library_id}-${r.to_library_id}`);
366                         const id = checkbox.attr('id');
367                         checkbox.data('limit_id', r.limit_id);
368                         checkbox.attr('checked', false);
369                         $(`#spinner-${id}`).hide();
370                         checkbox.show();
371                     }
372                 },
373                 complete: function() {
374                     $('.limit-action').removeClass('disabled');
375                     $('#value_selector').prop('disabled',false);
376                 },
377                 error: function(xhr, status, error) {
378                     var errorMessage = xhr.status + ': ' + xhr.statusText
379                     alert('Error - ' + errorMessage);
380                 }
381             });
382         }
383
384         function del_limits( checkboxes, val, to, from ){
385             let data = {};
386             data[val_type] = val;
387             if (to) data["to_library_id"] = to;
388             if (from) data["from_library_id"] = from;
389
390             return $.ajax({
391                 url: `/api/v1/transfer_limits/batch`,
392                 type: 'DELETE',
393                 data: JSON.stringify(data),
394                 dataType: 'json',
395                 success: function(result) {
396                     for ( i = 0; i < checkboxes.length; i++ ) {
397                         const checkbox = checkboxes[i];
398                         const id = checkbox.attr('id');
399                         checkbox.data('limit_id', '');
400                         checkbox.attr('checked', true);
401                         $(`#spinner-${id}`).hide();
402                         checkbox.show();
403                     }
404                 },
405                 complete: function() {
406                     $('.limit-action').removeClass('disabled');
407                     $('#value_selector').prop('disabled',false);
408                 },
409                 error: function(xhr, status, error) {
410                     var errorMessage = xhr.status + ': ' + xhr.statusText
411                     alert('Error - ' + errorMessage);
412                 }
413             });
414         }
415
416         function updateTransferLimitsTable() {
417             const val = $('#value_selector').val();
418             const url = `/api/v1/transfer_limits?_per_page=-1&q={"${val_type}": "${val}"}`;
419
420             if ( val ) {
421                 $('#transfer_limits').show();
422             } else {
423                 $('#transfer_limits').hide();
424             }
425
426             $(".limit-checkboxes").attr("disabled", true);
427             $(".limit-checkboxes").attr("checked", false);
428
429             if (val) {
430                 $('#loading_limits').show();
431
432                 $.ajax({
433                     dataType: "json",
434                     url: url,
435                     success: function(data) {
436                         $(".limit-checkboxes").attr("disabled", false);
437                         $(".limit-checkboxes").attr("checked", true);
438                         $(".limit-checkboxes").data('limit_id', null);
439
440                         for (var i = 0; i < data.length; i++) {
441                             let limit = data[i];
442                             let checkbox = $(`#limit-${limit.from_library_id}-${limit.to_library_id}`);
443                             checkbox.attr('checked', false);
444                             checkbox.data('limit_id', limit.limit_id);
445                         }
446                     },
447                     complete: function() {
448                         $('#loading_limits').hide();
449                     },
450                     error: function(xhr, status, error) {
451                         var errorMessage = xhr.status + ': ' + xhr.statusText
452                         alert('Error - ' + errorMessage);
453                     }
454                 });
455             }
456         }
457     </script>
458 [% END %]
459 [% INCLUDE 'intranet-bottom.inc' %]