Bugzilla – Attachment 112330 Details for
Bug 26633
Add advanced editor for transfer limits
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 26633: Add advanced editor for transfer limits
Bug-26633-Add-advanced-editor-for-transfer-limits.patch (text/plain), 22.56 KB, created by
Lisette Scheer
on 2020-10-23 23:31:32 UTC
(
hide
)
Description:
Bug 26633: Add advanced editor for transfer limits
Filename:
MIME Type:
Creator:
Lisette Scheer
Created:
2020-10-23 23:31:32 UTC
Size:
22.56 KB
patch
obsolete
>From 8eaac6839934b3661d62c0370575493c513aa683 Mon Sep 17 00:00:00 2001 >From: Kyle M Hall <kyle@bywatersolutions.com> >Date: Thu, 8 Oct 2020 11:15:44 -0400 >Subject: [PATCH] Bug 26633: Add advanced editor for transfer limits > >The current transfer limits editor works great for Koha instances with >small numbers of branches. However, for consortiums with dozens or even >hundreds of libraries, the editor does not work well or effectively. > >We should provide an "advanced" editor displays all to/from library >combinations in a grid and allows them to be edited in a manner somewhat >similar to the transport cost matrix editor. > >Test Plan: >1) Apply this patch >2) Browse to the transfer limits editor >3) Click the new "Switch to advanced editor" link >4) Select a collection code/item type to edit limits for >5) Test the "Check all" function >6) Test the "Uncheck all" function >7) Test the "Check" column function >8) Test the "Uncheck" column function >9) Test the "Check" row function >10) Test the "Uncheck" row function >11) Test individual checkboxes/table cells > >Signed-off-by: Lisette Scheer <lisettes@latahlibrary.org> > >Signed-off-by: Lisette Scheer <lisettes@latahlibrary.org> > >Signed-off-by: Lisette Scheer <lisettes@latahlibrary.org> > >Signed-off-by: Lisette Scheer <lisettes@latahlibrary.org> >--- > admin/transfer_limits.pl | 42 ++ > .../en/modules/admin/branch_transfer_limits.tt | 9 +- > .../prog/en/modules/admin/transfer_limits.tt | 437 +++++++++++++++++++++ > 3 files changed, 487 insertions(+), 1 deletion(-) > create mode 100755 admin/transfer_limits.pl > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/admin/transfer_limits.tt > >diff --git a/admin/transfer_limits.pl b/admin/transfer_limits.pl >new file mode 100755 >index 0000000000..98801efa63 >--- /dev/null >+++ b/admin/transfer_limits.pl >@@ -0,0 +1,42 @@ >+#!/usr/bin/perl >+ >+# copyright 2020 ByWater Solutions >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use CGI qw ( -utf8 ); >+use C4::Auth; >+use C4::Context; >+use C4::Output; >+use C4::Koha; >+use C4::Circulation >+ qw{ IsBranchTransferAllowed DeleteBranchTransferLimits CreateBranchTransferLimit }; >+ >+my $input = new CGI; >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { >+ template_name => "admin/transfer_limits.tt", >+ query => $input, >+ type => "intranet", >+ flagsrequired => { parameters => 'manage_transfers' }, >+ debug => 1, >+ } >+); >+ >+output_html_with_http_headers $input, $cookie, $template->output; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branch_transfer_limits.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branch_transfer_limits.tt >index 9dd039171b..4b6cb4947c 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branch_transfer_limits.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branch_transfer_limits.tt >@@ -28,7 +28,14 @@ > </form> > > <p class="help">Check the boxes for the libraries you allow your items to be transferred to.</p> >-<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> >+<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> >+ | >+ <a href="/cgi-bin/koha/admin/transfer_limits.pl">Switch to advanced editor</a> >+</fieldset> > > > <div id="transferlimit_tabs" class="toptabs"> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/transfer_limits.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/transfer_limits.tt >new file mode 100644 >index 0000000000..117863348f >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/transfer_limits.tt >@@ -0,0 +1,437 @@ >+[% USE raw %] >+[% USE To %] >+[% USE Asset %] >+[% USE Branches %] >+[% USE Koha %] >+[% USE ItemTypes %] >+[% USE AuthorisedValues %] >+[% SET footerjs = 1 %] >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Administration › Library checkin and transfer policy</title> >+[% INCLUDE 'doc-head-close.inc' %] >+<style>td { text-align: center; } .sorted { min-width: 50%; }</style> >+</head> >+ >+[% SET BranchTransferLimitsType = Koha.Preference('BranchTransferLimitsType') %] >+[% SET branches = Branches.all %] >+ >+<body id="admin_branch_transfer_limits" class="admin"> >+[% INCLUDE 'header.inc' %] >+[% INCLUDE 'prefs-admin-search.inc' %] >+ >+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> › Set library checkin and transfer policy</div> >+ >+<div class="main container-fluid"> >+ <div class="row"> >+ <div class="col-sm-10 col-sm-push-2"> >+ <main> >+ <h1>Checkin and transfer policy</h1> >+ >+ <p> >+ [% IF BranchTransferLimitsType == "itemtype" %] >+ <label for="value_selector">Select an item type:</label> >+ <select id="value_selector"> >+ <option value="" selected></option> >+ [% SET itemtypes = ItemTypes.Get %] >+ [% FOREACH i IN itemtypes %] >+ <option value="[% i.itemtype | html %]">[% i.description | html %]</option> >+ [% END %] >+ </select> >+ [% ELSE #BranchTransferLimitsType == "ccode" %] >+ <label for="value_selector">Select a collection code:</label> >+ <select id="value_selector"> >+ <option value="" selected></option> >+ [% SET ccodes = AuthorisedValues.Get('CCODE') %] >+ [% FOREACH c IN ccodes %] >+ <option value="[% c.authorised_value | html %]">[% c.lib | html %]</option> >+ [% END %] >+ </select> >+ [% END %] >+ >+ <span id="loading_limits"> >+ <i class="fa fa-spinner fa-pulse fa-fw"></i> >+ <span>Loading...</span> >+ </span> >+ </p> >+ >+ <p class="help">Check the boxes for the libraries you allow your items to be transferred to.</p> >+ <fieldset> >+ <a id="check-all" class="limit-action" href="#"><i class="fa fa-check"></i> Check all</a> >+ | >+ <a id="uncheck-all" class="limit-action" href="#"><i class="fa fa-remove"></i> Uncheck all</a> >+ | >+ <a href="/cgi-bin/koha/admin/branch_transfer_limits.pl">Switch to basic editor</a> >+ </fieldset> >+ >+ <table id="transfer_limits" class="table table-striped table-bordered table-hover table-condensed"> >+ >+ <thead> >+ <tr> >+ <td> </td> >+ <td> </td> >+ [% FOREACH to IN branches %] >+ <td> >+ <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> >+ <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> >+ </td> >+ [% END %] >+ </tr> >+ >+ <tr> >+ <td> </td> >+ <th>From / To</th> >+ [% FOREACH b IN branches %] >+ <th style="word-break: break-all !important" title="[% b.branchname | html %]">[% b.branchname | html %]</th> >+ [% END %] >+ </tr> >+ </thead> >+ >+ <tbody> >+ [% FOREACH from IN branches %] >+ <tr> >+ <td> >+ <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> >+ <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> >+ </td> >+ <th>[% from.branchname | html %]</th> >+ [% FOREACH to IN branches %] >+ <td class="checkbox-cell"> >+ [% IF to.branchcode == from.branchcode %] >+ >+ [% ELSE %] >+ <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/> >+ <i id="spinner-limit-[% from.branchcode | html %]-[% to.branchcode | html %]" class="spinner fa fa-spinner fa-pulse fa-fw"></i> >+ [% END %] >+ </td> >+ [% END %] >+ </tr> >+ [% END %] >+ </tbody> >+ </table> >+ </main> >+ </div> <!-- /.col-sm-10.col-sm-push-2 --> >+ >+ <div class="col-sm-2 col-sm-pull-10"> >+ <aside> >+ [% INCLUDE 'admin-menu.inc' %] >+ </aside> >+ </div> <!-- /.col-sm-2.col-sm-pull-10 --> >+ </div> <!-- /.row --> >+ >+[% MACRO jsinclude BLOCK %] >+ [% Asset.js("js/admin-menu.js") | $raw %] >+ [% INCLUDE 'datatables.inc' %] >+ [% Asset.js("lib/jquery/plugins/jquery.checkboxes.min.js") | $raw %] >+ <script> >+ const branchTransferLimitsType = "[% BranchTransferLimitsType | html %]"; >+ const val_type = branchTransferLimitsType == "itemtype" ? "item_type" : "collection_code"; >+ const branches = [% To.json(branches) | $raw %]; >+ >+ $('#loading_limits').hide(); >+ $('.spinner').hide(); >+ >+ $(document).ready(function() { >+ $("#check-all").click(function() { >+ const val = $('#value_selector').val(); >+ >+ $('.limit-action').addClass('disabled'); >+ $('#value_selector').prop('disabled',true); >+ >+ let checkboxes = []; >+ $(".limit-checkboxes").each(function() { >+ const checkbox = $(this); >+ if (checkbox.data('limit_id')) { >+ checkboxes.push(checkbox); >+ checkbox.hide(); >+ $(`#spinner-${checkbox.attr('id')}`).show(); >+ } >+ }); >+ >+ del_limits( checkboxes, val ); >+ return false; >+ }); >+ >+ >+ $("#uncheck-all").click(function() { >+ const val = $('#value_selector').val(); >+ >+ $('.limit-action').addClass('disabled'); >+ $('#value_selector').prop('disabled',true); >+ >+ let checkboxes = []; >+ $(".limit-checkboxes").each(function() { >+ const checkbox = $(this); >+ if (!checkbox.data('limit_id')) { >+ checkboxes.push(checkbox); >+ checkbox.hide(); >+ $(`#spinner-${checkbox.attr('id')}`).show(); >+ } >+ }); >+ >+ add_limits( checkboxes, val ); >+ return false; >+ }); >+ >+ $('.check-all-col').click(function() { >+ let checkboxes = []; >+ const to = $(this).data('to'); >+ const val = $('#value_selector').val(); >+ >+ $('.limit-action').addClass('disabled'); >+ $('#value_selector').prop('disabled',true); >+ >+ $(`.to-${to}`).each(function() { >+ const checkbox = $(this); >+ if (checkbox.data('limit_id')) { >+ checkboxes.push(checkbox); >+ checkbox.hide(); >+ $(`#spinner-${checkbox.attr('id')}`).show(); >+ } >+ }); >+ >+ del_limits( checkboxes, val, to ); >+ return false; >+ }); >+ >+ $('.uncheck-all-col').click(function() { >+ let checkboxes = []; >+ const to = $(this).data('to'); >+ const val = $('#value_selector').val(); >+ >+ $('.limit-action').addClass('disabled'); >+ $('#value_selector').prop('disabled',true); >+ >+ $(`.to-${to}`).each(function() { >+ const checkbox = $(this); >+ if (!checkbox.data('limit_id')) { >+ checkbox.hide(); >+ $(`#spinner-${checkbox.attr('id')}`).show(); >+ } >+ }); >+ >+ add_limits( checkboxes, val, to ); >+ return false; >+ }); >+ >+ $('.check-all-row').click(function() { >+ let checkboxes = []; >+ const from = $(this).data('from'); >+ const val = $('#value_selector').val(); >+ >+ $('.limit-action').addClass('disabled'); >+ $('#value_selector').prop('disabled',true); >+ >+ $(`.from-${from}`).each(function() { >+ const checkbox = $(this); >+ if (checkbox.data('limit_id')) { >+ checkboxes.push(checkbox); >+ checkbox.hide(); >+ $(`#spinner-${checkbox.attr('id')}`).show(); >+ } >+ }); >+ >+ del_limits( checkboxes, val, null, from ); >+ return false; >+ }); >+ >+ >+ $('.uncheck-all-row').click(function() { >+ let checkboxes = []; >+ const from = $(this).data('from'); >+ const val = $('#value_selector').val(); >+ >+ $('.limit-action').addClass('disabled'); >+ $('#value_selector').prop('disabled',true); >+ >+ $(`.from-${from}`).each(function() { >+ const checkbox = $(this); >+ if (!checkbox.data('limit_id')) { >+ checkbox.hide(); >+ $(`#spinner-${checkbox.attr('id')}`).show(); >+ } >+ }); >+ >+ add_limits( checkboxes, val, null, from ); >+ return false; >+ }); >+ >+ $(".checkbox-cell").click(function(e) { >+ var checkbox = $(this).find(".limit-checkboxes").get(0); >+ if (checkbox && !checkbox.disabled) { >+ if (e.target != checkbox) { >+ checkbox.checked = !checkbox.checked; >+ $(checkbox).change(); >+ } >+ } >+ }); >+ >+ $("#value_selector").on('change', function() { >+ updateTransferLimitsTable(); >+ }); >+ >+ $(".limit-checkboxes").on('change', function() { >+ const checkbox = $(this); >+ const id = checkbox.attr('id'); >+ >+ checkbox.hide(); >+ $(`#spinner-${id}`).show(); >+ >+ const limit_id = checkbox.data('limit_id'); >+ >+ if (limit_id) { // limit id exists, so limit needs to be deleted >+ delLimit(checkbox); >+ } else { // limit does not exist, needs to be created >+ addLimit(checkbox); >+ } >+ }); >+ >+ updateTransferLimitsTable(); >+ }); >+ >+ function delLimit(checkbox) { >+ const id = checkbox.attr('id'); >+ const limit_id = checkbox.data('limit_id'); >+ >+ return $.ajax({ >+ url: `/api/v1/transfer_limits/${limit_id}`, >+ type: 'DELETE', >+ success: function(result) { >+ checkbox.data('limit_id', null); >+ checkbox.attr('checked', true); >+ $(`#spinner-${id}`).hide(); >+ checkbox.show(); >+ }, >+ error: function(xhr, status, error) { >+ var errorMessage = xhr.status + ': ' + xhr.statusText >+ alert('Error - ' + errorMessage); >+ } >+ }); >+ } >+ >+ function addLimit(checkbox) { >+ const id = checkbox.attr('id'); >+ const parts = id.split('-'); >+ const from = parts[1]; >+ const to = parts[2]; >+ >+ const val = $('#value_selector').val(); >+ >+ let data = { >+ to_library_id: to, >+ from_library_id: from, >+ }; >+ data[val_type] = val; >+ return $.ajax({ >+ url: `/api/v1/transfer_limits`, >+ type: 'POST', >+ data: JSON.stringify(data), >+ dataType: 'json', >+ success: function(result) { >+ checkbox.data('limit_id', result.limit_id); >+ checkbox.attr('checked', false); >+ $(`#spinner-${id}`).hide(); >+ checkbox.show(); >+ }, >+ error: function(xhr, status, error) { >+ var errorMessage = xhr.status + ': ' + xhr.statusText >+ alert('Error - ' + errorMessage); >+ } >+ }); >+ } >+ >+ function add_limits( checkboxes, val, to, from ){ >+ let data = {}; >+ data[val_type] = val; >+ if (to) data["to_library_id"] = to; >+ if (from) data["from_library_id"] = from; >+ >+ return $.ajax({ >+ url: `/api/v1/transfer_limits/batch`, >+ type: 'POST', >+ data: JSON.stringify(data), >+ dataType: 'json', >+ success: function(result) { >+ for ( i = 0; i < result.length; i++ ) { >+ const r = result[i]; >+ let checkbox = $(`#limit-${r.from_library_id}-${r.to_library_id}`); >+ const id = checkbox.attr('id'); >+ checkbox.data('limit_id', r.limit_id); >+ checkbox.attr('checked', false); >+ $(`#spinner-${id}`).hide(); >+ checkbox.show(); >+ $('.limit-action').removeClass('disabled'); >+ $('#value_selector').prop('disabled',false); >+ } >+ }, >+ error: function(xhr, status, error) { >+ var errorMessage = xhr.status + ': ' + xhr.statusText >+ alert('Error - ' + errorMessage); >+ } >+ }); >+ } >+ >+ function del_limits( checkboxes, val, to, from ){ >+ let data = {}; >+ data[val_type] = val; >+ if (to) data["to_library_id"] = to; >+ if (from) data["from_library_id"] = from; >+ >+ return $.ajax({ >+ url: `/api/v1/transfer_limits/batch`, >+ type: 'DELETE', >+ data: JSON.stringify(data), >+ dataType: 'json', >+ success: function(result) { >+ for ( i = 0; i < checkboxes.length; i++ ) { >+ const checkbox = checkboxes[i]; >+ const id = checkbox.attr('id'); >+ checkbox.data('limit_id', ''); >+ checkbox.attr('checked', true); >+ $(`#spinner-${id}`).hide(); >+ checkbox.show(); >+ $('.limit-action').removeClass('disabled'); >+ $('#value_selector').prop('disabled',false); >+ } >+ }, >+ error: function(xhr, status, error) { >+ var errorMessage = xhr.status + ': ' + xhr.statusText >+ alert('Error - ' + errorMessage); >+ } >+ }); >+ } >+ >+ function updateTransferLimitsTable() { >+ const val = $('#value_selector').val(); >+ const url = `/api/v1/transfer_limits?_per_page=-1&q={"${val_type}": "${val}"}`; >+ >+ if ( val ) { >+ $('#transfer_limits').show(); >+ } else { >+ $('#transfer_limits').hide(); >+ } >+ >+ $(".limit-checkboxes").attr("disabled", true); >+ $(".limit-checkboxes").attr("checked", false); >+ >+ if (val) { >+ $('#loading_limits').show(); >+ >+ $.getJSON(url, function(data) { >+ $(".limit-checkboxes").attr("disabled", false); >+ $(".limit-checkboxes").attr("checked", true); >+ $(".limit-checkboxes").data('limit_id', null); >+ >+ for (var i = 0; i < data.length; i++) { >+ let limit = data[i]; >+ let checkbox = $(`#limit-${limit.from_library_id}-${limit.to_library_id}`); >+ checkbox.attr('checked', false); >+ checkbox.data('limit_id', limit.limit_id); >+ } >+ >+ $('#loading_limits').hide(); >+ }); >+ } >+ } >+ </script> >+[% END %] >+[% INCLUDE 'intranet-bottom.inc' %] >-- >2.11.0
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 26633
:
111380
|
111381
|
112327
|
112328
|
112330
|
112437
|
112438
|
112587
|
112778
|
112779
|
112780
|
112781
|
112782
|
112923
|
112924
|
112925
|
112926
|
112927
|
112928
|
112929
|
113053
|
113265
|
113266
|
113267
|
113268
|
113269
|
113270
|
113271
|
113272
|
113273
|
113274
|
113275
|
113676
|
113677
|
113961
|
116612
|
116613
|
116952
|
116953
|
116954
|
116955
|
116956
|
116957
|
116958
|
116959
|
116960
|
116961
|
116962
|
116963
|
116964