Bug 28867: Use Bootstrap button menu and modal for adding patrons to lists
This patch reworks the controls for adding patrons to a list from the patron search results page. The <select> is converted to a Bootstrap dropdown menu, and the list creation form is moved into a Bootstrap modal. To test, apply the patch and rebuild the staff interface CSS (https://wiki.koha-community.org/wiki/Working_with_SCSS_in_the_OPAC_and_staff_client). - In the staff interface, perform a patron search that will return multiple results. - In the toolbar at the top of the search results you should see two disabled Bootstrap-styled buttons: "Add to patron list" and "Merge selected patrons." - The "Select all" and "Clear all" links should work to enable and disable the toolbar buttons. - "Clear all" and then check the checkbox next to one of the results. The "Add to patron list" button should be enabled. - Check a second checkbox. The "Merge selected patrons" button should be enabled. - Test the "Add to patron list" button. It should trigger a dropdown menu listing existing patrons lists and a "New list" link. - Test adding to an exising patron list. It should trigger a message at the top of the page which shows a link to that list. - Test adding to a new list. It should trigger a Bootstrap modal where you can enter the name of the new list. - Submitting the list title form should close the modal and trigger the display of the message showing how many patrons were added to your new list. The link to the new list should be correct. - Test the "Merge selected patrons" button. It should send the selected patrons to the patron merge screen. Signed-off-by: David Nind <david@davidnind.com> Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de> Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
This commit is contained in:
parent
d0ab4f292d
commit
f64cc6b472
2 changed files with 138 additions and 115 deletions
|
@ -2070,22 +2070,24 @@ li {
|
|||
}
|
||||
|
||||
#searchresults {
|
||||
ul {
|
||||
li {
|
||||
clear: left;
|
||||
font-size: 90%;
|
||||
list-style: url("../img/item-bullet.svg");
|
||||
padding: .2em 0;
|
||||
td {
|
||||
ul {
|
||||
li {
|
||||
clear: left;
|
||||
font-size: 90%;
|
||||
list-style: url("../img/item-bullet.svg");
|
||||
padding: .2em 0;
|
||||
|
||||
&.result_itype_image {
|
||||
list-style: none;
|
||||
list-style-type: none;
|
||||
}
|
||||
&.result_itype_image {
|
||||
list-style: none;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
img {
|
||||
float: left;
|
||||
margin: 3px 5px 3px -5px;
|
||||
max-width: 25px;
|
||||
img {
|
||||
float: left;
|
||||
margin: 3px 5px 3px -5px;
|
||||
max-width: 25px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
<main>
|
||||
|
||||
[% IF CAN_user_tools_manage_patron_lists %]
|
||||
<div id="patron_list_dialog" class="dialog alert">
|
||||
<div id="patron_list_dialog" class="dialog message">
|
||||
Added <span class="patrons-length"></span> patrons to <a></a>.
|
||||
</div>
|
||||
[% END %]
|
||||
|
@ -72,38 +72,32 @@
|
|||
[% IF CAN_user_tools_manage_patron_lists || CAN_user_borrowers_edit_borrowers %]
|
||||
<div class="searchheader fh-fixedHeader" id="searchheader">
|
||||
<div>
|
||||
<a href="#" id="select_all"><i class="fa fa-check"></i> Select all</a>
|
||||
<a href="#" class="btn btn-link" 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>
|
||||
<a href="#" class="btn btn-link" id="clear_all"><i class="fa fa-remove"></i> Clear all</a>
|
||||
[% IF CAN_user_tools_manage_patron_lists %]
|
||||
|
|
||||
<span>
|
||||
<label for="add_to_patron_list">Add selected patrons to:</label>
|
||||
<select id="add_to_patron_list" name="add_to_patron_list">
|
||||
<option value=""></option>
|
||||
[% IF patron_lists %]
|
||||
<optgroup label="Patron lists:">
|
||||
[% FOREACH pl IN patron_lists %]
|
||||
<option value="[% pl.patron_list_id | html %]">[% pl.name | html %]</option>
|
||||
[% END %]
|
||||
</optgroup>
|
||||
[% END %]
|
||||
|
||||
<option value="new">[ New list ]</option>
|
||||
</select>
|
||||
|
||||
<input type="text" id="new_patron_list" name="new_patron_list" id="new_patron_list" />
|
||||
|
||||
<input id="add_to_patron_list_submit" type="submit" class="submit" value="Save">
|
||||
</span>
|
||||
[% END %]
|
||||
|
||||
[% IF CAN_user_tools_manage_patron_lists && CAN_user_borrowers_edit_borrowers %]
|
||||
|
|
||||
[% IF CAN_user_tools_manage_patron_lists %]
|
||||
<div id="patronlist-dropdown" class="btn-group">
|
||||
<button id="patronlist-menu" type="button" class="btn btn-sm btn-default dropdown-toggle patron-edits disabled" disabled="disabled" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Add to patron list <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
[% IF patron_lists %]
|
||||
[% FOREACH pl IN patron_lists %]
|
||||
<li><a href="#" class="patron-list-add" data-listid="[% pl.patron_list_id | html %]">[% pl.name | html %]</a></li>
|
||||
[% END %]
|
||||
[% END %]
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a href="#" class="patron-list-add" data-listid="new">New list</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
[% END %]
|
||||
|
||||
[% IF CAN_user_borrowers_edit_borrowers %]
|
||||
<button id="merge-patrons" type="submit">Merge selected patrons</button>
|
||||
<button id="merge-patrons" class="btn btn-sm btn-default disabled" disabled="disabled" type="submit"><i class="fa fa-compress" aria-hidden="true"></i> Merge selected patrons</button>
|
||||
[% END %]
|
||||
</div>
|
||||
</div>
|
||||
|
@ -210,6 +204,32 @@
|
|||
</div> <!-- /.col-sm-2.col-sm-pull-10 -->
|
||||
</div> <!-- /.row -->
|
||||
|
||||
<!-- New Patron List Modal -->
|
||||
<div class="modal" id="new-patron-list" tabindex="-1" role="dialog" aria-labelledby="new-patron-listLabel">
|
||||
<div class="modal-dialog" 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="new-patron-listLabel">Add patrons to a new patron list</h4>
|
||||
</div>
|
||||
<form id="new-patron-list_form">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="new_patron_list" class="required">Patron list name: </label>
|
||||
<input class="form-control required" type="text" name="new_patron_list" id="new_patron_list" required="required" />
|
||||
<input type="hidden" name="add_to_patron_list" id="add_to_patron_list" />
|
||||
<span class="required">Required</span>
|
||||
</div>
|
||||
</div> <!-- /.modal-body -->
|
||||
<div class="modal-footer">
|
||||
<button type="submit" id="add_to_patron_list_submit" class="btn btn-default approve">Submit</button>
|
||||
<button type="button" class="btn btn-default deny" data-dismiss="modal">Cancel</button>
|
||||
</div> <!-- /.modal-footer -->
|
||||
</form> <!-- /#new-patron-list_form -->
|
||||
</div> <!-- /.modal-content -->
|
||||
</div> <!-- /.modal-dialog -->
|
||||
</div> <!-- /#new-patron-list -->
|
||||
|
||||
[% MACRO jsinclude BLOCK %]
|
||||
[% INCLUDE 'datatables.inc' %]
|
||||
[% INCLUDE 'columns_settings.inc' %]
|
||||
|
@ -229,101 +249,70 @@
|
|||
$('#merge-patrons').prop('disabled', true);
|
||||
$('#memberresultst').on('change', 'input.selection', function() {
|
||||
if ( $('.selection:checked').length > 1 ) {
|
||||
$('#merge-patrons').prop('disabled', false);
|
||||
/* More than one checkbox has been checked */
|
||||
$('#merge-patrons').prop('disabled', false).removeClass("disabled");
|
||||
$("#patronlist-menu").removeClass("disabled").prop("disabled", false);
|
||||
} else if ( $('.selection:checked').length == 1 ) {
|
||||
/* At least one checkbox has been checked */
|
||||
$('#merge-patrons').prop('disabled', true).addClass("disabled");
|
||||
$("#patronlist-menu").removeClass("disabled").prop("disabled", false);
|
||||
} else {
|
||||
$('#merge-patrons').prop('disabled', true);
|
||||
/* No checkbox has been checked */
|
||||
$('#merge-patrons').prop('disabled', true).addClass("disabled");
|
||||
$("#patronlist-menu").addClass("disabled").prop("disabled", true);
|
||||
}
|
||||
});
|
||||
|
||||
$('#merge-patrons').on('click', function() {
|
||||
var merge_patrons_url = 'merge-patrons.pl?' + $('.selection:checked')
|
||||
.map(function() {
|
||||
return "id=" + $(this).val()
|
||||
}).get().join('&');
|
||||
|
||||
window.location.href = merge_patrons_url;
|
||||
});
|
||||
|
||||
$('#add_to_patron_list_submit').prop('disabled', true);
|
||||
$('#new_patron_list').hide();
|
||||
|
||||
$('#add_to_patron_list').change(function() {
|
||||
var value = $('#add_to_patron_list').val();
|
||||
if ( value == 'new' ) {
|
||||
$('#new_patron_list').val('')
|
||||
$('#new_patron_list').show();
|
||||
$('#new_patron_list').focus();
|
||||
} else if ( value ) {
|
||||
$('#new_patron_list').hide();
|
||||
$('#add_to_patron_list_submit').prop('disabled', false);
|
||||
} else {
|
||||
$('#new_patron_list').hide();
|
||||
$('#add_to_patron_list_submit').prop('disabled', true);
|
||||
}
|
||||
});
|
||||
|
||||
$('#new_patron_list').on('input', function() {
|
||||
if ( $('#new_patron_list').val() ) {
|
||||
$('#add_to_patron_list_submit').prop('disabled', false);
|
||||
} else {
|
||||
$('#add_to_patron_list_submit').prop('disabled', true);
|
||||
}
|
||||
});
|
||||
|
||||
$("#add_to_patron_list_submit").on('click', function(e){
|
||||
if ( $('#add_to_patron_list').val() == 'new' ) {
|
||||
if ( $('#new_patron_list').val() ) {
|
||||
$("#add_to_patron_list option").each(function() {
|
||||
if ( $(this).text() == $('#new_patron_list').val() ) {
|
||||
alert( _("You already have a list with that name!") );
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
alert( _("You must give your new patron list a name!") );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$("#patronlist-dropdown").on("click", ".patron-list-add", function(e){
|
||||
e.preventDefault();
|
||||
|
||||
if ( $("#memberresultst input:checkbox:checked").length == 0 ) {
|
||||
alert( _("You have not selected any patrons to add to a list!") );
|
||||
$(".btn-group").removeClass("open"); /* Close button menu */
|
||||
return false;
|
||||
}
|
||||
|
||||
var borrowernumbers = [];
|
||||
$("#memberresultst").find("input:checkbox:checked").each(function(){
|
||||
borrowernumbers.push($(this).val());
|
||||
});
|
||||
var data = {
|
||||
add_to_patron_list: $("#add_to_patron_list").val(),
|
||||
new_patron_list: $("#new_patron_list").val(),
|
||||
borrowernumbers: borrowernumbers
|
||||
};
|
||||
$.ajax({
|
||||
data: data,
|
||||
type: 'POST',
|
||||
url: '/cgi-bin/koha/svc/members/add_to_list',
|
||||
success: function(data) {
|
||||
$("#patron_list_dialog").show();
|
||||
$("#patron_list_dialog > span.patrons-length").html(data.patrons_added_to_list);
|
||||
$("#patron_list_dialog > a").attr("href", "/cgi-bin/koha/patron_lists/list.pl?patron_list_id=" + data.patron_list.patron_list_id);
|
||||
$("#patron_list_dialog > a").html(data.patron_list.name);
|
||||
if ( $('#add_to_patron_list').val() == 'new' ) {
|
||||
var new_patron_list_added = $("<option>", {
|
||||
value: data.patron_list.patron_list_id,
|
||||
text: data.patron_list.name
|
||||
});
|
||||
$("#add_to_patron_list optgroup").append(new_patron_list_added);
|
||||
$("#add_to_patron_list").val(data.patron_list.patron_list_id);
|
||||
$("#new_patron_list").val('');
|
||||
$('#add_to_patron_list').change();
|
||||
var listid = $(this).data("listid");
|
||||
$("#add_to_patron_list").val( listid );
|
||||
if( listid == "new" ){
|
||||
/* #add_to_patron_list value "new" in the modal form will tell API to create a new list */
|
||||
$("#new-patron-list").modal("show");
|
||||
} else {
|
||||
/* Ajax submit the patrons to list */
|
||||
|
||||
patronListAdd();
|
||||
}
|
||||
})
|
||||
|
||||
/* Submit selected patrons to a list via AJAX */
|
||||
$("#new-patron-list_form").on('submit', function(e){
|
||||
e.preventDefault();
|
||||
/* Upon submitting modal patron list add form... */
|
||||
if ( $('#new_patron_list').val() ) {
|
||||
$(".patron-list-add").each(function() {
|
||||
/* Check each list name in the menu of patron lists */
|
||||
/* If submitted list name matches... */
|
||||
if ( $(this).text() == $('#new_patron_list').val() ) {
|
||||
alert( _("You already have a list with that name!") );
|
||||
return false;
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert("an error occurred");
|
||||
}
|
||||
});
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
alert( _("You must give your new patron list a name!") );
|
||||
return false;
|
||||
}
|
||||
$("#new-patron-list").modal("hide");
|
||||
patronListAdd();
|
||||
});
|
||||
|
||||
$(".filterByLetter").on("click",function(e){
|
||||
e.preventDefault();
|
||||
filterByFirstLetterSurname( $(this).text(), true );
|
||||
|
@ -510,6 +499,38 @@
|
|||
|
||||
});
|
||||
|
||||
function patronListAdd(){
|
||||
var borrowernumbers = [];
|
||||
$("#memberresultst").find("input:checkbox:checked").each(function(){
|
||||
borrowernumbers.push($(this).val());
|
||||
});
|
||||
var data = {
|
||||
add_to_patron_list: $("#add_to_patron_list").val(),
|
||||
new_patron_list: $("#new_patron_list").val(),
|
||||
borrowernumbers: borrowernumbers
|
||||
};
|
||||
$.ajax({
|
||||
data: data,
|
||||
type: 'POST',
|
||||
url: '/cgi-bin/koha/svc/members/add_to_list',
|
||||
success: function(data) {
|
||||
$("#patron_list_dialog").show();
|
||||
$("#patron_list_dialog > span.patrons-length").html(data.patrons_added_to_list);
|
||||
$("#patron_list_dialog > a").attr("href", "/cgi-bin/koha/patron_lists/list.pl?patron_list_id=" + data.patron_list.patron_list_id);
|
||||
$("#patron_list_dialog > a").html(data.patron_list.name);
|
||||
|
||||
if ( $('#add_to_patron_list').val() == 'new' ) {
|
||||
/* Add a new entry to the menu */
|
||||
$("#patronlist-dropdown .divider").before('<li><a class="patron-list-add" href="#" data-listid="' + data.patron_list.patron_list_id + '">' + data.patron_list.name + '</li>');
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
alert("an error occurred");
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function getSearchByLocation( setstate ){
|
||||
/* Check to see if the URL contains a search parameter */
|
||||
if( location.search != ""){
|
||||
|
|
Loading…
Reference in a new issue