Bug 41646: Fix HTML display for self-checkin

This change moves the wrapper so that the web page display correctly

Test plan:
0. Apply the patch
1. Enable the SelfCheckInModule system preference
2. Go to http://localhost:8080/cgi-bin/koha/sci/sci-main.pl
3. Note that there isn't a lot of whitespace between
the word "koha" and "Self check-in"
4. Celebrate

Signed-off-by: David Nind <david@davidnind.com>
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
This commit is contained in:
David Cook 2026-01-16 04:25:37 +00:00 committed by Wainui Witika-Park
parent 1dbc309e9f
commit 773eaebf83
No known key found for this signature in database
GPG Key ID: 2D0A6AB5DAF1B78D
2 changed files with 270 additions and 270 deletions

View File

@ -5,45 +5,43 @@
[% SET OpacLangSelectorMode = Koha.Preference('OpacLangSelectorMode') %]
[% SET OpacHeader = AdditionalContents.get( location => "opacheader", lang => lang, library => logged_in_user.branchcode || default_branch, blocktitle => 0 ) %]
<div id="wrapper">
<header id="header-region" class="noprint">
<nav class="navbar navbar-expand">
<h1 id="logo">
<a class="navbar-brand" href="/cgi-bin/koha/sci/sci-main.pl">
[% IF ( LibraryNameTitle ) %]
[% LibraryNameTitle | html %]
[% ELSE %]
Koha online
[% END %]
</a>
</h1>
<header id="header-region" class="noprint">
<nav class="navbar navbar-expand">
<h1 id="logo">
<a class="navbar-brand" href="/cgi-bin/koha/sci/sci-main.pl">
[% IF ( LibraryNameTitle ) %]
[% LibraryNameTitle | html %]
[% ELSE %]
Koha online
[% END %]
</a>
</h1>
<ul class="navbar-nav ml-auto">
[% IF ( Koha.Preference( 'opaclanguagesdisplay' ) ) %]
<li class="nav-item"> [% INCLUDE 'langmenu.inc' %] </li>
[% END # / IF opaclanguagedisplay %]
<ul class="navbar-nav ml-auto">
[% IF ( Koha.Preference( 'opaclanguagesdisplay' ) ) %]
<li class="nav-item"> [% INCLUDE 'langmenu.inc' %] </li>
[% END # / IF opaclanguagedisplay %]
<li class="nav-item">
<ul class="navbar-nav">
<li class="nav-item">
<a href="/cgi-bin/koha/sci/sci-main.pl" class="nav-link helpModal-trigger" role="button" data-bs-toggle="modal"><i class="fa fa-info-circle fa-icon-black" aria-hidden="true"></i> Help</a>
</li>
</ul>
</li>
<li class="nav-item">
<a id="sci_logout" href="/cgi-bin/koha/sci/sci-main.pl?logout.x=1" class="nav-link logout"> <i class="fa-solid fa-right-from-bracket" aria-hidden="true"></i> Log out </a>
</li>
</ul>
</nav>
<!-- /navbar -->
[% IF ( OpacHeader ) %]
<div class="container-fluid">
<div class="row">
<div class="col"> [% PROCESS koha_news_block news => OpacHeader %] </div>
</div>
</div>
[% END # /IF opacheader %]
</header>
<li class="nav-item">
<ul class="navbar-nav">
<li class="nav-item">
<a href="/cgi-bin/koha/sci/sci-main.pl" class="nav-link helpModal-trigger" role="button" data-bs-toggle="modal"><i class="fa fa-info-circle fa-icon-black" aria-hidden="true"></i> Help</a>
</li>
</ul>
</li>
<li class="nav-item">
<a id="sci_logout" href="/cgi-bin/koha/sci/sci-main.pl?logout.x=1" class="nav-link logout"> <i class="fa-solid fa-right-from-bracket" aria-hidden="true"></i> Log out </a>
</li>
</ul>
</nav>
<!-- /navbar -->
</div>
[% IF ( OpacHeader ) %]
<div class="container-fluid">
<div class="row">
<div class="col"> [% PROCESS koha_news_block news => OpacHeader %] </div>
</div>
</div>
[% END # /IF opacheader %]
</header>
<!-- /navbar -->

View File

@ -74,271 +74,273 @@
[% Asset.js('js/i18n.js') | $raw %]
</head>
<body id="sci_main" class="sci">
[% INCLUDE 'masthead-sci.inc' %]
<div id="wrapper">
[% INCLUDE 'masthead-sci.inc' %]
<main class="main">
<div class="container-fluid">
<div class="row">
<div class="col order-first order-md-first order-lg-2">
<div id="masthead">
<h1>[% LibraryName | html %] Self check-in</h1>
<main class="main">
<div class="container-fluid">
<div class="row">
<div class="col order-first order-md-first order-lg-2">
<div id="masthead">
<h1>[% LibraryName | html %] Self check-in</h1>
</div>
[% IF ( nopermission ) %]
[%# This is what is displayed if user doesn't have permission %]
<div class="alert alert-warning">
<h2>Access denied</h2>
<p>Sorry, this self check-in station has lost authentication. Please contact the administrator to resolve this problem.</p>
</div>
[% ELSIF ( different_ip ) %]
[%# This is what is displayed if user doesn't have permission %]
<div class="alert alert-warning">
<h2>Session lost</h2>
<p>You are accessing self check-in from a different IP address! Please log in again.</p>
</div>
[% ELSIF ( checkins ) %]
[%# We have results from a check-in attempt %]
<div id="checkins" class="sci_results_list">
[% IF ( success && success.size > 0 || errors && errors.size > 0 ) %]
<table id="sci_bcheckins_table" class="table table-bordered table-striped dataTable no-footer">
<caption><h2>Results</h2></caption>
<thead>
<th>Barcode</th>
<th>Status</th>
</thead>
<tbody>
[% FOREACH success_line IN success %]
<tr>
<td>[% success_line.barcode | html %]</td>
<td>Checked in</td>
</tr>
[% END %]
[% FOREACH error IN errors %]
<tr>
<td>[% error.barcode | html %]</td>
<td>Not checked in [% PROCESS error_message messages=error.messages %]</td>
</tr>
[% END %]
</tbody>
</table>
<div>
<a href="/cgi-bin/koha/sci/sci-main.pl" id="sci_finish_button" class="btn btn-primary" role="button"><i class="fa fa-check" aria-hidden="true"></i> Finish</a>
</div>
[% ELSE %]
<div class="alert alert-warning">
<p>Your request included no check-ins.</p>
</div>
[% END %]
</div>
[% ELSE %]
[%# Prompt for barcodes %]
<div id="new_checkins" class="sci_entry">
<form id="scan_form" name="scan_form" method="post" action="/cgi-bin/koha/sci/sci-main.pl">
[% INCLUDE 'csrf-token.inc' %]
<legend class="sr-only">Scan</legend>
<div class="row">
<div class="col-auto">
<label for="barcode_input">Scan the item or enter its barcode:</label>
</div>
<div class="col-4">
<input id="barcode_input" name="barcode_input" size="20" type="text" class="focus form-control" autocomplete="off" />
</div>
<div class="col-auto">
<button id="sci_append_button" type="submit" class="btn btn-primary"> Submit </button>
</div>
</div>
<!-- /.row -->
<div class="row">
<div class="col">
<div class="sci_input_append">
<table id="sci_barcodes_table" class="table table-bordered table-striped dataTable no-footer" style="display: none;">
<caption class="sr-only">Barcodes</caption>
<thead>
<th class="barcodes_column">Barcode</th>
</thead>
<tbody> </tbody>
</table>
<!-- /#sci_barcodes_table -->
</div>
<!-- .sci_input_append -->
<input type="hidden" name="op" value="cud-check_in" />
<div id="button_bar">
<button id="sci_checkin_button" type="submit" class="btn btn-primary" style="display: none;"> <i class="fa fa-check-square" aria-hidden="true"></i> <span>Check in</span> </button>
<a href="/cgi-bin/koha/sci/sci-main.pl" class="btn btn-danger" role="button" style="display: none;" id="sci_refresh_button"> <i class="fa fa-times" aria-hidden="true"></i> <span>Cancel</span> </a>
</div>
<!-- /#button_bar -->
</div>
<!-- /.col -->
</div>
<!-- /.row -->
</form>
<!-- /#scan_form -->
</div>
<!-- / #new_checkins -->
[% END # /IF ( nopermission ) %]
[% IF ( SelfCheckInMainUserBlock ) %]
<div id="scimainuserblock"> [% PROCESS koha_news_block news => SelfCheckInMainUserBlock %] </div>
[% END %]
</div>
[% IF ( nopermission ) %]
[%# This is what is displayed if user doesn't have permission %]
<div class="alert alert-warning">
<h2>Access denied</h2>
<p>Sorry, this self check-in station has lost authentication. Please contact the administrator to resolve this problem.</p>
</div>
[% ELSIF ( different_ip ) %]
[%# This is what is displayed if user doesn't have permission %]
<div class="alert alert-warning">
<h2>Session lost</h2>
<p>You are accessing self check-in from a different IP address! Please log in again.</p>
</div>
[% ELSIF ( checkins ) %]
[%# We have results from a check-in attempt %]
<div id="checkins" class="sci_results_list">
[% IF ( success && success.size > 0 || errors && errors.size > 0 ) %]
<table id="sci_bcheckins_table" class="table table-bordered table-striped dataTable no-footer">
<caption><h2>Results</h2></caption>
<thead>
<th>Barcode</th>
<th>Status</th>
</thead>
<tbody>
[% FOREACH success_line IN success %]
<tr>
<td>[% success_line.barcode | html %]</td>
<td>Checked in</td>
</tr>
[% END %]
[% FOREACH error IN errors %]
<tr>
<td>[% error.barcode | html %]</td>
<td>Not checked in [% PROCESS error_message messages=error.messages %]</td>
</tr>
[% END %]
</tbody>
</table>
<div>
<a href="/cgi-bin/koha/sci/sci-main.pl" id="sci_finish_button" class="btn btn-primary" role="button"><i class="fa fa-check" aria-hidden="true"></i> Finish</a>
</div>
[% ELSE %]
<div class="alert alert-warning">
<p>Your request included no check-ins.</p>
</div>
[% END %]
</div>
[% ELSE %]
[%# Prompt for barcodes %]
<div id="new_checkins" class="sci_entry">
<form id="scan_form" name="scan_form" method="post" action="/cgi-bin/koha/sci/sci-main.pl">
[% INCLUDE 'csrf-token.inc' %]
<legend class="sr-only">Scan</legend>
<div class="row">
<div class="col-auto">
<label for="barcode_input">Scan the item or enter its barcode:</label>
</div>
<div class="col-4">
<input id="barcode_input" name="barcode_input" size="20" type="text" class="focus form-control" autocomplete="off" />
</div>
<div class="col-auto">
<button id="sci_append_button" type="submit" class="btn btn-primary"> Submit </button>
</div>
</div>
<!-- /.row -->
<div class="row">
<div class="col">
<div class="sci_input_append">
<table id="sci_barcodes_table" class="table table-bordered table-striped dataTable no-footer" style="display: none;">
<caption class="sr-only">Barcodes</caption>
<thead>
<th class="barcodes_column">Barcode</th>
</thead>
<tbody> </tbody>
</table>
<!-- /#sci_barcodes_table -->
</div>
<!-- .sci_input_append -->
<input type="hidden" name="op" value="cud-check_in" />
<div id="button_bar">
<button id="sci_checkin_button" type="submit" class="btn btn-primary" style="display: none;"> <i class="fa fa-check-square" aria-hidden="true"></i> <span>Check in</span> </button>
<a href="/cgi-bin/koha/sci/sci-main.pl" class="btn btn-danger" role="button" style="display: none;" id="sci_refresh_button"> <i class="fa fa-times" aria-hidden="true"></i> <span>Cancel</span> </a>
</div>
<!-- /#button_bar -->
</div>
<!-- /.col -->
</div>
<!-- /.row -->
</form>
<!-- /#scan_form -->
</div>
<!-- / #new_checkins -->
[% END # /IF ( nopermission ) %]
[% IF ( SelfCheckInMainUserBlock ) %]
<div id="scimainuserblock"> [% PROCESS koha_news_block news => SelfCheckInMainUserBlock %] </div>
[% END %]
<!-- / #masthead -->
</div>
<!-- / #masthead -->
<!-- / .row -->
</div>
<!-- / .row -->
</div>
<!-- / .container-fluid -->
</main>
<!-- / .main -->
<!-- / .container-fluid -->
</main>
<!-- / .main -->
[%# Help modal %]
<div id="helpModal" class="modal" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title" id="helpModalLabel">Self check-in help</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<!-- /.modal-header -->
<div class="modal-body">
<ul>
<li>Scan each item or enter its barcode. A list with the entered barcodes will be displayed.</li>
<li>Click the 'Check in' button to confirm.</li>
<li>The operation results will be displayed for each entered barcode.</li>
<li>The 'Finish' button is presented to start over.</li>
<li>At any step, clicking the 'Cancel' button will erase the scanned barcodes and start over.</li>
</ul>
</div>
<!-- /.modal-body -->
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">Close</button>
[%# Help modal %]
<div id="helpModal" class="modal" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title" id="helpModalLabel">Self check-in help</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<!-- /.modal-header -->
<div class="modal-body">
<ul>
<li>Scan each item or enter its barcode. A list with the entered barcodes will be displayed.</li>
<li>Click the 'Check in' button to confirm.</li>
<li>The operation results will be displayed for each entered barcode.</li>
<li>The 'Finish' button is presented to start over.</li>
<li>At any step, clicking the 'Cancel' button will erase the scanned barcodes and start over.</li>
</ul>
</div>
<!-- /.modal-body -->
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">Close</button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-content -->
<!-- /.modal-dialog -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /#helpModal -->
<!-- /#helpModal -->
</body>
</body>
[% INCLUDE 'opac-bottom.inc' %]
[% BLOCK jsinclude %]
<script>
function mungeHistory() {
// prevent back button from allowing form resubmission
if (history && history.pushState) {
history.replaceState(null, document.title, window.location.href);
[% INCLUDE 'opac-bottom.inc' %]
[% BLOCK jsinclude %]
<script>
function mungeHistory() {
// prevent back button from allowing form resubmission
if (history && history.pushState) {
history.replaceState(null, document.title, window.location.href);
}
}
}
function dofocus() {
$(".focus:last").select();
}
function dofocus() {
$(".focus:last").select();
}
var barcodes = [];
var barcodes = [];
$( window ).on( "load", function() {
$( window ).on( "load", function() {
dofocus();
});
$( window ).on( "unload", function() {
mungeHistory();
});
$(document).ready(function() {
// Barcodes scanning table initially hidden
$("#sci_barcodes_table").hide();
// Control the 'append' button behaviour
$("#sci_append_button").on('click', function(e) {
// Make sure the form is not submitted by the button
e.preventDefault();
var barcode = $('#barcode_input').val().trim(); // Trim whitespace from input
if (barcode !== "") {
// Properly escape the barcode value by using .text() for display
var barcodeHtml = $('<tr style="font-size: initial;"><td></td></tr>');
barcodeHtml.find('td').text(barcode).append(
$('<input>').attr({
type: 'hidden',
name: 'barcode',
value: barcode
})
);
$('#sci_barcodes_table tbody').append(barcodeHtml);
// Make sure the table is now displayed
$("#sci_barcodes_table").show();
$('#sci_checkin_button').show();
$('#sci_refresh_button').show();
// Add barcode to the array
barcodes.push(barcode);
}
// Clear the input and reset the focus
$('#barcode_input').val('');
dofocus();
});
$( window ).on( "unload", function() {
mungeHistory();
$(".helpModal-trigger").on("click", function(e) {
e.preventDefault();
$("#helpModal").modal("show");
});
$(document).ready(function() {
// Barcodes scanning table initially hidden
$("#sci_barcodes_table").hide();
// Control the 'append' button behaviour
$("#sci_append_button").on('click', function(e) {
// Make sure the form is not submitted by the button
e.preventDefault();
var barcode = $('#barcode_input').val().trim(); // Trim whitespace from input
if (barcode !== "") {
// Properly escape the barcode value by using .text() for display
var barcodeHtml = $('<tr style="font-size: initial;"><td></td></tr>');
barcodeHtml.find('td').text(barcode).append(
$('<input>').attr({
type: 'hidden',
name: 'barcode',
value: barcode
})
);
$('#sci_barcodes_table tbody').append(barcodeHtml);
// Make sure the table is now displayed
$("#sci_barcodes_table").show();
$('#sci_checkin_button').show();
$('#sci_refresh_button').show();
// Add barcode to the array
barcodes.push(barcode);
}
// Clear the input and reset the focus
$('#barcode_input').val('');
// Set focus at the beginning
dofocus();
});
$(".helpModal-trigger").on("click", function(e) {
e.preventDefault();
$("#helpModal").modal("show");
});
// Set focus at the beginning
dofocus();
});
var idleTime = 0;
$(document).ready(function () {
//Increment the idle time counter every second
var idleInterval = setInterval(timerIncrement, 1000);
var idleTime = 0;
$(document).ready(function () {
//Increment the idle time counter every second
var idleInterval = setInterval(timerIncrement, 1000);
//Zero the idle timer on mouse movement.
$(this).mousemove(function (e) {
idleTime = 0;
//Zero the idle timer on mouse movement.
$(this).mousemove(function (e) {
idleTime = 0;
});
$(this).keypress(function (e) {
idleTime = 0;
});
});
$(this).keypress(function (e) {
idleTime = 0;
});
});
function timerIncrement() {
if ( $("#sci_finish_button").is(":visible") || $("#sci_refresh_button").is(":visible") ) {
idleTime = idleTime + 1;
idleTimeout = [% refresh_timeout | html %];
if (idleTime >= idleTimeout ) {
location.href = '/cgi-bin/koha/sci/sci-main.pl';
function timerIncrement() {
if ( $("#sci_finish_button").is(":visible") || $("#sci_refresh_button").is(":visible") ) {
idleTime = idleTime + 1;
idleTimeout = [% refresh_timeout | html %];
if (idleTime >= idleTimeout ) {
location.href = '/cgi-bin/koha/sci/sci-main.pl';
}
}
}
}
function checkBarcodeInput() {
var inputField = document.getElementById("barcode_input");
var button = document.getElementById("sci_append_button");
function checkBarcodeInput() {
var inputField = document.getElementById("barcode_input");
var button = document.getElementById("sci_append_button");
if (inputField.value.trim() === "") {
button.disabled = true;
} else {
button.disabled = false;
if (inputField.value.trim() === "") {
button.disabled = true;
} else {
button.disabled = false;
}
}
}
checkBarcodeInput();
checkBarcodeInput();
document.getElementById("barcode_input").addEventListener("input", checkBarcodeInput);
document.getElementById("barcode_input").addEventListener("input", checkBarcodeInput);
document.getElementById("sci_append_button").addEventListener("click", function() {
setTimeout(checkBarcodeInput, 10);
});
</script>
[% IF ( Koha.Preference('SelfCheckInUserJS') ) %]
<script>
[% Koha.Preference('SelfCheckInUserJS') | $raw %]
document.getElementById("sci_append_button").addEventListener("click", function() {
setTimeout(checkBarcodeInput, 10);
});
</script>
[% IF ( Koha.Preference('SelfCheckInUserJS') ) %]
<script>
[% Koha.Preference('SelfCheckInUserJS') | $raw %]
</script>
[% END %]
[% END %]
[% END %]
</div>