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

(-)a/admin/transfer_limits.pl (+42 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# copyright 2020 ByWater Solutions
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
22
use CGI qw ( -utf8 );
23
use C4::Auth;
24
use C4::Context;
25
use C4::Output;
26
use C4::Koha;
27
use C4::Circulation
28
  qw{ IsBranchTransferAllowed DeleteBranchTransferLimits CreateBranchTransferLimit };
29
30
my $input = new CGI;
31
32
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
33
    {
34
        template_name => "admin/transfer_limits.tt",
35
        query         => $input,
36
        type          => "intranet",
37
        flagsrequired => { parameters => 'manage_transfers' },
38
        debug         => 1,
39
    }
40
);
41
42
output_html_with_http_headers $input, $cookie, $template->output;
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branch_transfer_limits.tt (-1 / +8 lines)
Lines 28-34 Link Here
28
    </form>
28
    </form>
29
29
30
<p class="help">Check the boxes for the libraries you allow your items to be transferred to.</p>
30
<p class="help">Check the boxes for the libraries you allow your items to be transferred to.</p>
31
<fieldset>[% IF ( limitType == 'ccode' ) %]<strong>For all collection codes: </strong>[% ELSE %]<strong>For all item types: </strong>[% END %]<a id="CheckAll" href="#"><i class="fa fa-check"></i> Select all</a> | <a id="UncheckAll" href="#"><i class="fa fa-remove"></i> Clear all</a></fieldset>
31
<fieldset>
32
    [% IF ( limitType == 'ccode' ) %]<strong>For all collection codes: </strong>[% ELSE %]<strong>For all item types: </strong>[% END %]
33
    <a id="CheckAll" href="#"><i class="fa fa-check"></i> Select all</a>
34
    |
35
    <a id="UncheckAll" href="#"><i class="fa fa-remove"></i> Clear all</a>
36
    |
37
    <a href="/cgi-bin/koha/admin/transfer_limits.pl">Switch to advanced editor</a>
38
</fieldset>
32
39
33
40
34
  <div id="transferlimit_tabs" class="toptabs">
41
  <div id="transferlimit_tabs" class="toptabs">
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/transfer_limits.tt (-1 / +437 lines)
Line 0 Link Here
0
- 
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 code:</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
    [% Asset.js("lib/jquery/plugins/jquery.checkboxes.min.js") | $raw %]
125
    <script>
126
        const branchTransferLimitsType = "[% BranchTransferLimitsType | html %]";
127
        const val_type = branchTransferLimitsType == "itemtype" ? "item_type" : "collection_code";
128
        const branches = [% To.json(branches) | $raw %];
129
130
        $('#loading_limits').hide();
131
        $('.spinner').hide();
132
133
        $(document).ready(function() {
134
            $("#check-all").click(function() {
135
                const val = $('#value_selector').val();
136
137
                $('.limit-action').addClass('disabled');
138
                $('#value_selector').prop('disabled',true);
139
140
                let checkboxes = [];
141
                $(".limit-checkboxes").each(function() {
142
                    const checkbox = $(this);
143
                    if (checkbox.data('limit_id')) {
144
                        checkboxes.push(checkbox);
145
                        checkbox.hide();
146
                        $(`#spinner-${checkbox.attr('id')}`).show();
147
                    }
148
                });
149
150
                del_limits( checkboxes, val );
151
                return false;
152
            });
153
154
155
            $("#uncheck-all").click(function() {
156
                const val = $('#value_selector').val();
157
158
                $('.limit-action').addClass('disabled');
159
                $('#value_selector').prop('disabled',true);
160
161
                let checkboxes = [];
162
                $(".limit-checkboxes").each(function() {
163
                    const checkbox = $(this);
164
                    if (!checkbox.data('limit_id')) {
165
                        checkboxes.push(checkbox);
166
                        checkbox.hide();
167
                        $(`#spinner-${checkbox.attr('id')}`).show();
168
                    }
169
                });
170
171
                add_limits( checkboxes, val );
172
                return false;
173
            });
174
175
            $('.check-all-col').click(function() {
176
                let checkboxes = [];
177
                const to = $(this).data('to');
178
                const val = $('#value_selector').val();
179
180
                $('.limit-action').addClass('disabled');
181
                $('#value_selector').prop('disabled',true);
182
183
                $(`.to-${to}`).each(function() {
184
                    const checkbox = $(this);
185
                    if (checkbox.data('limit_id')) {
186
                        checkboxes.push(checkbox);
187
                        checkbox.hide();
188
                        $(`#spinner-${checkbox.attr('id')}`).show();
189
                    }
190
                });
191
192
                del_limits( checkboxes, val, to );
193
                return false;
194
            });
195
196
            $('.uncheck-all-col').click(function() {
197
                let checkboxes = [];
198
                const to = $(this).data('to');
199
                const val = $('#value_selector').val();
200
201
                $('.limit-action').addClass('disabled');
202
                $('#value_selector').prop('disabled',true);
203
204
                $(`.to-${to}`).each(function() {
205
                    const checkbox = $(this);
206
                    if (!checkbox.data('limit_id')) {
207
                        checkbox.hide();
208
                        $(`#spinner-${checkbox.attr('id')}`).show();
209
                    }
210
                });
211
212
                add_limits( checkboxes, val, to );
213
                return false;
214
            });
215
216
            $('.check-all-row').click(function() {
217
                let checkboxes = [];
218
                const from = $(this).data('from');
219
                const val = $('#value_selector').val();
220
221
                $('.limit-action').addClass('disabled');
222
                $('#value_selector').prop('disabled',true);
223
224
                $(`.from-${from}`).each(function() {
225
                    const checkbox = $(this);
226
                    if (checkbox.data('limit_id')) {
227
                        checkboxes.push(checkbox);
228
                        checkbox.hide();
229
                        $(`#spinner-${checkbox.attr('id')}`).show();
230
                    }
231
                });
232
233
                del_limits( checkboxes, val, null, from );
234
                return false;
235
            });
236
237
238
            $('.uncheck-all-row').click(function() {
239
                let checkboxes = [];
240
                const from = $(this).data('from');
241
                const val = $('#value_selector').val();
242
243
                $('.limit-action').addClass('disabled');
244
                $('#value_selector').prop('disabled',true);
245
246
                $(`.from-${from}`).each(function() {
247
                    const checkbox = $(this);
248
                    if (!checkbox.data('limit_id')) {
249
                        checkbox.hide();
250
                        $(`#spinner-${checkbox.attr('id')}`).show();
251
                    }
252
                });
253
254
                add_limits( checkboxes, val, null, from );
255
                return false;
256
            });
257
258
            $(".checkbox-cell").click(function(e) {
259
                var checkbox = $(this).find(".limit-checkboxes").get(0);
260
                if (checkbox && !checkbox.disabled) {
261
                    if (e.target != checkbox) {
262
                        checkbox.checked = !checkbox.checked;
263
                        $(checkbox).change();
264
                    }
265
                }
266
            });
267
268
            $("#value_selector").on('change', function() {
269
                updateTransferLimitsTable();
270
            });
271
272
            $(".limit-checkboxes").on('change', function() {
273
                const checkbox = $(this);
274
                const id = checkbox.attr('id');
275
276
                checkbox.hide();
277
                $(`#spinner-${id}`).show();
278
279
                const limit_id = checkbox.data('limit_id');
280
281
                if (limit_id) { // limit id exists, so limit needs to be deleted
282
                    delLimit(checkbox);
283
                } else { // limit does not exist, needs to be created
284
                    addLimit(checkbox);
285
                }
286
            });
287
288
            updateTransferLimitsTable();
289
        });
290
291
        function delLimit(checkbox) {
292
            const id = checkbox.attr('id');
293
            const limit_id = checkbox.data('limit_id');
294
295
            return $.ajax({
296
                url: `/api/v1/transfer_limits/${limit_id}`,
297
                type: 'DELETE',
298
                success: function(result) {
299
                    checkbox.data('limit_id', null);
300
                    checkbox.attr('checked', true);
301
                    $(`#spinner-${id}`).hide();
302
                    checkbox.show();
303
                },
304
                error: function(xhr, status, error) {
305
                    var errorMessage = xhr.status + ': ' + xhr.statusText
306
                    alert('Error - ' + errorMessage);
307
                }
308
            });
309
        }
310
311
        function addLimit(checkbox) {
312
            const id = checkbox.attr('id');
313
            const parts = id.split('-');
314
            const from = parts[1];
315
            const to = parts[2];
316
317
            const val = $('#value_selector').val();
318
319
            let data = {
320
                to_library_id: to,
321
                from_library_id: from,
322
            };
323
            data[val_type] = val;
324
            return $.ajax({
325
                url: `/api/v1/transfer_limits`,
326
                type: 'POST',
327
                data: JSON.stringify(data),
328
                dataType: 'json',
329
                success: function(result) {
330
                    checkbox.data('limit_id', result.limit_id);
331
                    checkbox.attr('checked', false);
332
                    $(`#spinner-${id}`).hide();
333
                    checkbox.show();
334
                },
335
                error: function(xhr, status, error) {
336
                    var errorMessage = xhr.status + ': ' + xhr.statusText
337
                    alert('Error - ' + errorMessage);
338
                }
339
            });
340
        }
341
342
        function add_limits( checkboxes, val, to, from ){
343
            let data = {};
344
            data[val_type] = val;
345
            if (to) data["to_library_id"] = to;
346
            if (from) data["from_library_id"] = from;
347
348
            return $.ajax({
349
                url: `/api/v1/transfer_limits/batch`,
350
                type: 'POST',
351
                data: JSON.stringify(data),
352
                dataType: 'json',
353
                success: function(result) {
354
                    for ( i = 0; i < result.length; i++ ) {
355
                        const r = result[i];
356
                        let checkbox = $(`#limit-${r.from_library_id}-${r.to_library_id}`);
357
                        const id = checkbox.attr('id');
358
                        checkbox.data('limit_id', r.limit_id);
359
                        checkbox.attr('checked', false);
360
                        $(`#spinner-${id}`).hide();
361
                        checkbox.show();
362
                        $('.limit-action').removeClass('disabled');
363
                        $('#value_selector').prop('disabled',false);
364
                    }
365
                },
366
                error: function(xhr, status, error) {
367
                    var errorMessage = xhr.status + ': ' + xhr.statusText
368
                    alert('Error - ' + errorMessage);
369
                }
370
            });
371
        }
372
373
        function del_limits( checkboxes, val, to, from ){
374
            let data = {};
375
            data[val_type] = val;
376
            if (to) data["to_library_id"] = to;
377
            if (from) data["from_library_id"] = from;
378
379
            return $.ajax({
380
                url: `/api/v1/transfer_limits/batch`,
381
                type: 'DELETE',
382
                data: JSON.stringify(data),
383
                dataType: 'json',
384
                success: function(result) {
385
                    for ( i = 0; i < checkboxes.length; i++ ) {
386
                        const checkbox = checkboxes[i];
387
                        const id = checkbox.attr('id');
388
                        checkbox.data('limit_id', '');
389
                        checkbox.attr('checked', true);
390
                        $(`#spinner-${id}`).hide();
391
                        checkbox.show();
392
                        $('.limit-action').removeClass('disabled');
393
                        $('#value_selector').prop('disabled',false);
394
                    }
395
                },
396
                error: function(xhr, status, error) {
397
                    var errorMessage = xhr.status + ': ' + xhr.statusText
398
                    alert('Error - ' + errorMessage);
399
                }
400
            });
401
        }
402
403
        function updateTransferLimitsTable() {
404
            const val = $('#value_selector').val();
405
            const url = `/api/v1/transfer_limits?_per_page=-1&q={"${val_type}": "${val}"}`;
406
407
            if ( val ) {
408
                $('#transfer_limits').show();
409
            } else {
410
                $('#transfer_limits').hide();
411
            }
412
413
            $(".limit-checkboxes").attr("disabled", true);
414
            $(".limit-checkboxes").attr("checked", false);
415
416
            if (val) {
417
                $('#loading_limits').show();
418
419
                $.getJSON(url, function(data) {
420
                    $(".limit-checkboxes").attr("disabled", false);
421
                    $(".limit-checkboxes").attr("checked", true);
422
                    $(".limit-checkboxes").data('limit_id', null);
423
424
                    for (var i = 0; i < data.length; i++) {
425
                        let limit = data[i];
426
                        let checkbox = $(`#limit-${limit.from_library_id}-${limit.to_library_id}`);
427
                        checkbox.attr('checked', false);
428
                        checkbox.data('limit_id', limit.limit_id);
429
                    }
430
431
                    $('#loading_limits').hide();
432
                });
433
            }
434
        }
435
    </script>
436
[% END %]
437
[% INCLUDE 'intranet-bottom.inc' %]

Return to bug 26633