From 0afeb3a9ee4786d503a280d695e20e771aa68561 Mon Sep 17 00:00:00 2001 From: Owen Leonard <oleonard@myacpl.org> Date: Fri, 3 May 2019 13:56:02 +0000 Subject: [PATCH] Bug 22844: Simplify the process of selecting database columns for system preferences This patch introduces a new way for users to select database columns for system preferences like BorrowerMandatoryField, which currently require hand-typing of database names. This new system uses a JSON file containing label:column pairs for database columns which are relevant to preferences which reference borrower table columns. My intention was to have user-friendly values as the labels, but embedding English strings in JSON would make them untranslatable. The following preferences are affected: - BorrowerMandatoryField - BorrowerUnwantedField - PatronSelfModificationBorrowerUnwantedField - PatronSelfRegistrationBorrowerMandatoryField - PatronSelfRegistrationBorrowerUnwantedField To test, apply the patch and regenerate the staff client CSS. restart_all to make sure the updated .pref file is used. - Go to Administration -> System preferences, and search for "PatronSelf" - The input fields for PatronSelfModificationBorrowerUnwantedField, PatronSelfRegistrationBorrowerMandatoryField, and PatronSelfRegistrationBorrowerUnwantedField should appear as "locked" (read-only) inputs. - Clicking the input field should trigger a modal window with checkboxes for each available column from the borrowers table. - Test that the "select all" and "clear all" links work correctly. - Test that the "cancel" link closes the modal without saving your selections. - Test that the "Save" button closes the modal, copies your selections to the form field, and triggers the preference-saving function (this eliminates the need to click a save button again after closing the modal). - Test this process by making modifications to all three different preferences, confirming that the right data is preselected each time the modal is shown and the right data is saved to the right field each time. --- admin/preferences.pl | 6 +++ koha-tmpl/intranet-tmpl/prog/css/preferences.css | 26 ++++++++- .../intranet-tmpl/prog/css/src/staff-global.scss | 5 ++ .../prog/en/modules/admin/preferences.tt | 29 +++++++++- .../en/modules/admin/preferences/borrowers.json | 53 +++++++++++++++++++ .../prog/en/modules/admin/preferences/opac.pref | 12 ++--- .../prog/en/modules/admin/preferences/patrons.pref | 7 +-- .../intranet-tmpl/prog/js/pages/preferences.js | 61 +++++++++++++++++++++- 8 files changed, 187 insertions(+), 12 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/borrowers.json diff --git a/admin/preferences.pl b/admin/preferences.pl index 92c5bbe..2862e69 100755 --- a/admin/preferences.pl +++ b/admin/preferences.pl @@ -64,6 +64,12 @@ sub _get_chunk { if( $options{'syntax'} ){ $chunk->{'syntax'} = $options{'syntax'}; } + + if( $options{'type'} && $options{'type'} eq 'modalselect' ){ + $chunk->{'source'} = $options{'source'}; + $chunk->{'type'} = 'modalselect'; + } + if ( $options{'class'} && $options{'class'} eq 'password' ) { $chunk->{'input_type'} = 'password'; } elsif ( $options{'class'} && $options{'class'} eq 'date' ) { diff --git a/koha-tmpl/intranet-tmpl/prog/css/preferences.css b/koha-tmpl/intranet-tmpl/prog/css/preferences.css index 7ecce1b..0b27e49 100644 --- a/koha-tmpl/intranet-tmpl/prog/css/preferences.css +++ b/koha-tmpl/intranet-tmpl/prog/css/preferences.css @@ -1,4 +1,8 @@ -.preference-url, .preference-multi, .preference-long, .preference-file { +.preference-url, +.preference-multi, +.preference-long, +.preference-file, +.preference-modalselect { width: 20em; } @@ -10,6 +14,14 @@ width: 5em; } +input[type="text"].modalselect { + cursor: pointer; +} + +input[type="text"].modalselect:hover { + background-color: #FFC; +} + textarea.preference { width: 35em; height: 20em; @@ -134,4 +146,16 @@ span.overridden { border: 1px solid #EEE; margin: 1em 1em 1em 0; resize: vertical; +} + +#prefModal label { + display: block; + font-weight: bold; + line-height: 1.5em; +} + +.dbcolumn { + font-weight: normal; + font-family: monospace; + color: #666; } \ No newline at end of file diff --git a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss index c0f13ae..fefd7dd 100644 --- a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss +++ b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss @@ -4285,6 +4285,11 @@ span { margin: .5em 0; } +.columns-2 { + columns: 2 auto; + column-gap: 2.5em; +} + .columns-3 { columns: 3 auto; column-gap: 2.5em; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences.tt index 764f164..c9ef8e7 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences.tt @@ -92,6 +92,8 @@ </option> [% END %] </select> + [% ELSIF ( CHUNK.type_modalselect ) %] + <input type="text" name="pref_[% CHUNK.name | html %]" id="pref_[% CHUNK.name | html %]" class="modalselect preference preference-[% CHUNK.type | html %]" data-source="[% CHUNK.source | html %]" readonly="readonly" value="[% CHUNK.value | html %]"/> [% ELSIF ( CHUNK.type_multiple ) %] <select name="pref_[% CHUNK.name | html %]" id="pref_[% CHUNK.name | html %]" class="preference preference-[% CHUNK.class or "choice" | html %]" multiple="multiple"> [% FOREACH CHOICE IN CHUNK.CHOICES %][% IF ( CHOICE.selected ) %]<option value="[% CHOICE.value | html %]" selected="selected">[% ELSE %]<option value="[% CHOICE.value | html %]">[% END %][% CHOICE.text | html %]</option>[% END %] @@ -163,6 +165,31 @@ </div> <!-- /.col-sm-2.col-sm-pull-10 --> </div> <!-- /.row --> +<!-- Modal --> +<div class="modal" id="prefModal" tabindex="-1" role="dialog" aria-labelledby="prefModalLabel"> + <div class="modal-dialog modal-wide" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="closebtn" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="prefModalLabel">Modal title</h4> + </div> + <div class="modal-body"> + <p> + <a href="#" id="select_all"><i class="fa fa-check"></i> Select all</a> + | + <a href="#" id="clear_all"><i class="fa fa-remove"></i> Clear all</a> + </p> + <form action="#" id="prefModalForm"> + </form> + </div> + <div class="modal-footer"> + <button id="saveModalPrefs" data-target="" type="button" class="btn btn-default">Save</button> + <button type="button" class="btn btn-link cancel" data-dismiss="modal">Cancel</button> + </div> + </div> + </div> +</div> + [% MACRO jsinclude BLOCK %] [% INCLUDE 'datatables.inc' %] [% Asset.js("lib/hc-sticky.js") | $raw %] @@ -174,6 +201,7 @@ [% Asset.js( "lib/codemirror/yaml.min.js" ) | $raw %] <script> var Sticky; + var themelang = "[% themelang | html %]"; $(document).ready(function(){ [% UNLESS ( searchfield ) %] Sticky = $("#toolbar"); @@ -193,7 +221,6 @@ e.preventDefault(); window.location.reload(true); }); - }); // This is here because of its dependence on template variables, everything else should go in js/pages/preferences.js - jpw var to_highlight = "[% searchfield |replace("'", "\'") |replace('"', '\"') |replace('\n', '\\n') |replace('\r', '\\r') | html %]"; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/borrowers.json b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/borrowers.json new file mode 100644 index 0000000..fc1482f --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/borrowers.json @@ -0,0 +1,53 @@ +{ + "cardnumber": "cardnumber", + "surname": "surname", + "firstname": "firstname", + "title": "title", + "othernames": "othernames", + "initials": "initials", + "streetnumber": "streetnumber", + "streettype": "streettype", + "address": "address", + "address2": "address2", + "city": "city", + "state": "state", + "zipcode": "zipcode", + "country": "country", + "email": "email", + "phone": "phone", + "mobile": "mobile", + "fax": "fax", + "emailpro": "emailpro", + "phonepro": "phonepro", + "B_streetnumber": "B_streetnumber", + "B_streettype": "B_streettype", + "B_address": "B_address", + "B_address2": "B_address2", + "B_city": "B_city", + "B_state": "B_state", + "B_zipcode": "B_zipcode", + "B_country": "B_country", + "B_email": "B_email", + "B_phone": "B_phone", + "dateofbirth": "dateofbirth", + "branchcode": "branchcode", + "categorycode": "categorycode", + "contactname": "contactname", + "contactfirstname": "contactfirstname", + "borrowernotes": "borrowernotes", + "sex": "sex", + "password": "password", + "userid": "userid", + "opacnote": "opacnote", + "contactnote": "contactnote", + "altcontactfirstname": "altcontactfirstname", + "altcontactsurname": "altcontactsurname", + "altcontactaddress1": "altcontactaddress1", + "altcontactaddress2": "altcontactaddress2", + "altcontactaddress3": "altcontactaddress3", + "altcontactstate": "altcontactstate", + "altcontactzipcode": "altcontactzipcode", + "altcontactcountry": "altcontactcountry", + "altcontactphone": "altcontactphone", + "smsalertnumber": "smsalertnumber" +} \ No newline at end of file diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref index 8300553..6ae7027 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref @@ -793,18 +793,18 @@ OPAC: - - "The following <a href='http://schema.koha-community.org/__VERSION__/tables/borrowers.html' target='blank'>database columns</a> must be filled in on the patron entry screen:" - pref: PatronSelfRegistrationBorrowerMandatoryField - class: multi - - (separate columns with |) + type: modalselect + source: borrowers - - "The following <a href='http://schema.koha-community.org/__VERSION__/tables/borrowers.html' target='blank'>database columns</a> will not appear on the patron self-registration screen:" - pref: PatronSelfRegistrationBorrowerUnwantedField - class: multi - - (separate columns with |) + type: modalselect + source: borrowers - - "The following <a href='http://schema.koha-community.org/__VERSION__/tables/borrowers.html' target='blank'>database columns</a> will not appear on the patron self-modification screen:" - pref: PatronSelfModificationBorrowerUnwantedField - class: multi - - (separate columns with |) + type: modalselect + source: borrowers - - "Display the following additional instructions for patrons who self register via the OPAC ( HTML is allowed ):" - pref: PatronSelfRegistrationAdditionalInstructions diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref index 9007da9..2920c2c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref @@ -39,13 +39,14 @@ Patrons: - - "The following <a href='http://schema.koha-community.org/__VERSION__/tables/borrowers.html' target='blank'>database columns</a> must be filled in on the patron entry screen:" - pref: BorrowerMandatoryField - class: multi - - (separate columns with |) + type: modalselect + source: borrowers - "<strong>NOTE:</strong> If autoMemberNum is enabled, the system preference BorrowerMandatoryField must not contain the field cardnumber." - - "The following <a href='http://schema.koha-community.org/__VERSION__/tables/borrowers.html' target='blank'>database columns</a> will not appear on the patron entry screen:" - pref: BorrowerUnwantedField - class: multi + type: modalselect + source: borrowers - (separate columns with |) - - "Guarantors can be the following of those they guarantee:" diff --git a/koha-tmpl/intranet-tmpl/prog/js/pages/preferences.js b/koha-tmpl/intranet-tmpl/prog/js/pages/preferences.js index d5db030..9d9599a 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/pages/preferences.js +++ b/koha-tmpl/intranet-tmpl/prog/js/pages/preferences.js @@ -1,4 +1,4 @@ -/* global KOHA MSG_MADE_CHANGES CodeMirror MSG_CLICK_TO_EXPAND MSG_CLICK_TO_COLLAPSE to_highlight search_jumped humanMsg MSG_NOTHING_TO_SAVE MSG_MODIFIED MSG_SAVING MSG_SAVED_PREFERENCE dataTablesDefaults */ +/* global KOHA MSG_MADE_CHANGES CodeMirror MSG_CLICK_TO_EXPAND MSG_CLICK_TO_COLLAPSE to_highlight search_jumped humanMsg MSG_NOTHING_TO_SAVE MSG_MODIFIED MSG_SAVING MSG_SAVED_PREFERENCE dataTablesDefaults themelang */ // We can assume 'KOHA' exists, as we depend on KOHA.AJAX KOHA.Preferences = { @@ -205,4 +205,63 @@ $( document ).ready( function () { email: true }); }); + + + $(".modalselect").on("click", function(){ + var datasource = $(this).data("source"); + var pref_name = this.id.replace(/pref_/, ''); + var pref_value = this.value; + var prefs = pref_value.split("|"); + + $.getJSON( themelang + "/modules/admin/preferences/" + datasource + ".json", function( data ){ + var items = []; + var checked = ""; + $.each( data, function( key, val ){ + if( prefs.indexOf( val ) >= 0 ){ + checked = ' checked="checked" '; + } else { + checked = ""; + } + items.push('<label><input class="dbcolumn_selection" type="checkbox" id="' + key + '"' + checked + ' name="pref" value="' + val + '" /> ' + key + '</label>'); + }); + $("<div/>", { + "class": "columns-2", + html: items.join("") + }).appendTo("#prefModalForm"); + }); + $("#saveModalPrefs").data("target", this.id ); + $("#prefModalLabel").text( pref_name ); + $("#prefModal").modal("show"); + }); + + $("#saveModalPrefs").on("click", function(){ + var formfieldid = $("#" + $(this).data("target") ); + var prefs = []; + $("#prefModal input[type='checkbox']").each(function(){ + if( $(this).prop("checked") ){ + prefs.push( this.value ); + } + }); + + formfieldid.val( prefs.join("|") ) + .addClass("modified"); + mark_modified.call( formfieldid ); + KOHA.Preferences.Save( formfieldid.closest("form") ); + $("#prefModal").modal("hide"); + }); + + $("#prefModal").on("hide.bs.modal", function(){ + $("#prefModalLabel,#prefModalForm").html(""); + $("#saveModalPrefs").data("target", "" ); + }); + + $("#select_all").on("click",function(e){ + e.preventDefault(); + $(".dbcolumn_selection").prop("checked", true); + }); + $("#clear_all").on("click",function(e){ + e.preventDefault(); + $(".dbcolumn_selection").prop("checked", false); + }); + } ); -- 2.1.4