From f49cf32238caae5c2ed1b3aad2b1558ddb667c2d Mon Sep 17 00:00:00 2001 From: Owen Leonard Date: Tue, 26 Apr 2022 11:29:13 +0000 Subject: [PATCH] Bug 30623: Copy permissions from one user to another This patch adds controls to the patron "Set permissions" page allowing the user to copy a set of permissions from one patron to another. The patch also makes a minor correction to global staff interface CSS to correct the appearance of non-primary split buttons. To test, apply the patch and rebuild the staff interface CSS. You may want to clear your browser cache. - Locate a patron in the staff client and choose More -> Set permissions. You might want to start with a staff patron who has multiple permissions enabled. - You should see two new buttons in the toolbar immediately above the list of permissions: "Copy settings," a split button with a secondary option to choose "Forget copied settings"; and "Paste settings" which should be disabled by default. - Clicking the "Copy settings" button should trigger the copy icon to cycle/fade from the copy icon to the check-mark icon and back to the copy icon. I thought this interaction needed some visual feedback since it doesn't otherwise trigger visible action. - Clicking the "Copy settings" button should also enable the "Paste settings" button. - Locate another patron, preferable one with permissions visibly different from your first choice. - On their "Set permissions" page, click the "Paste settings" button. The list of permissions should expand all settings and all the checkboxes should now match your original choice. - At this stage you could find another patron and paste the same permissions again. - Click "Copy settings -> Forget copied settings." The "Paste settings" button should become disabled. - Using the browser console to check the contents of Local Storage should confirm that the "copiedPermissions" entry has been removed. Signed-off-by: Lucas Gass Signed-off-by: Marcel de Rooy Signed-off-by: Katrin Fischer --- .../prog/en/modules/members/member-flags.tt | 62 ++++++++++++++++++- .../intranet-tmpl/prog/js/staff-global.js | 18 ++++++ 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-flags.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-flags.tt index 68a5796969..b94958b7ab 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-flags.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/member-flags.tt @@ -40,6 +40,7 @@ [% INCLUDE 'members-toolbar.inc' %] +
[% INCLUDE 'csrf-token.inc' %] @@ -58,12 +59,22 @@ Clear all + +
+ + + +
+ + Paste settings
Filter:
-
+
[% FOREACH loo IN loop %] [% IF ( loo.expand ) %]
@@ -272,8 +283,57 @@ } } }); + + if( copied = getCopiedPermissions() ){ + $("#pastePermissions").removeClass("disabled"); + } + + /* write to the clipboard now */ + $("#copyPermissions").on("click", function(e){ + e.preventDefault(); + let flags = new Object(); + $("#flag_form input:checkbox").each(function(){ + flags[ $(this).attr('id') ] = $(this).prop("checked"); + }); + formText = JSON.stringify( flags ); + localStorage.setItem("copiedPermissions", formText ); + toggleBtnIcon( $(this), "fa-copy", "fa-check" ); + $("#pastePermissions").removeClass("disabled"); + }); + + $("#pastePermissions").on("click", function(e){ + e.preventDefault(); + $(".toggleall_on").click(); + let copiedPermissions = getCopiedPermissions(); + + let checkBox; + let checked; + for( const permission in copiedPermissions ){ + checkBox = `${permission}`; + checked = `${copiedPermissions[permission]}` == "true" ? true : false; + $("#" + checkBox).prop("checked", checked ); + } + }); + + $("#clearCopied").on("click", function(e){ + e.preventDefault(); + localStorage.removeItem("copiedPermissions"); + $("#pastePermissions").addClass("disabled"); + }); }); + function getCopiedPermissions(){ + const copied = localStorage.getItem("copiedPermissions"); + let copiedPermissions; + try { + copiedPermissions = JSON.parse( copied ); + return copiedPermissions; + } catch ( ex ){ + console.error("Bad parse: ", ex.message ); + return false; + } + } + function setLibrarian(){ $('input[name="flag"]').each(function() { if($(this).attr('id') != "flag-0" && !$(this).hasClass('superlib') ){ diff --git a/koha-tmpl/intranet-tmpl/prog/js/staff-global.js b/koha-tmpl/intranet-tmpl/prog/js/staff-global.js index e424f2870b..71db55ae88 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/staff-global.js +++ b/koha-tmpl/intranet-tmpl/prog/js/staff-global.js @@ -340,6 +340,7 @@ function logOut() { localStorage.removeItem("bibs_selected"); localStorage.removeItem("patron_search_selections"); localStorage.removeItem("item_search_selections"); + localStorage.removeItem("copiedPermissions"); } function openHelp() { @@ -787,3 +788,20 @@ function selectBsTabByHash(tabs_container_id) { $("#" + tabs_container_id + " a:first").tab("show"); } } + +/** + * Fades out a Font Awesome icon, fades in a replacement, and back + * @param {object} element - jQuery object representing the icon's container + * @param {string} start - The icon which will be temporarily replaced + * @param {string} replacement - The icon which will be the temporary replacement + */ +function toggleBtnIcon( element, start, replacement ){ + let icon = element.find( "." + start ); + icon.fadeOut( 1000, function(){ + $(this).removeClass( start ).addClass( replacement ).fadeIn( 1000, function(){ + $(this).fadeOut( 1000, function(){ + $(this).removeClass( replacement ).addClass( start ).fadeIn( 1000 ); + }); + }); + }); +} -- 2.39.5