Koha/koha-tmpl/intranet-tmpl/prog/js/patron-webcam.js
David Cook 1b9a4d9754 Bug 35344: Warn on patron image upload if missing cardnumber
This change displays a warning message instead of the patron image
upload feature in the patron record when the patron is missing the
cardnumber.

Without this change, the staff user can try to upload a patron image
but it will silently fail. This change warns the staff user of the
cardnumber requirement for patron image upload.

Test plan:
0. Apply the patch
1. Enable the "patronimages" system preference
2. Go to http://localhost:8081/cgi-bin/koha/members/moremember.pl?borrowernumber=51
3. Click "Add" over the patron image placeholder
4. Note the "Upload photo" button and the ability to take a patron photo if your
device has a camera
5. Remove "cardnumber" from BorrowerMandatoryField
6. Go to http://localhost:8081/cgi-bin/koha/circ/circulation.pl?borrowernumber=51
7. Edit the patron to remove the cardnumber
8. Click "Add" over the patron image placeholder
9. Note that no patron image upload features appear. Instead, only
a warning appears stating that the patron needs a cardnumber before
the patron image upload can be performed

Signed-off-by: David Nind <david@davidnind.com>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
(cherry picked from commit 855b8bc66e)
Signed-off-by: Fridolin Somers <fridolin.somers@biblibre.com>
(cherry picked from commit 0a8908bddb)
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
2023-12-14 21:19:31 +00:00

198 lines
6 KiB
JavaScript

/* global __ */
/* exported startup */
/* Adapted from Mozilla's article "Taking still photos with WebRTC"
* https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Taking_still_photos
*/
var width = 480; // We will scale the photo width to this
var height = 0; // This will be computed based on the input stream
// |streaming| indicates whether or not we're currently streaming
// video from the camera. Obviously, we start at false.
var streaming = false;
// The various HTML elements we need to configure or control. These
// will be set by the startup() function.
var video = null;
var canvas = null;
var photo = null;
var takebutton = null;
var retakebutton = null;
var downloadbutton = null;
var savebutton = null;
var output = null;
var camera = null;
var uploadfiletext = null;
/**
* Initiate the camera and add some click handlers
*/
function startup() {
video = document.getElementById('viewfinder');
canvas = document.getElementById('canvas');
photo = document.getElementById('photo');
takebutton = document.getElementById('takebutton');
retakebutton = document.getElementById('retakebutton');
downloadbutton = document.getElementById('downloadbutton');
savebutton = document.getElementById('savebutton');
output = document.getElementById("output");
camera = document.getElementById("camera");
uploadfiletext = document.getElementById("uploadfiletext");
if ( ! video ){
//If there is no video element, don't try to start up camera
return;
}
try {
navigator.mediaDevices.getUserMedia({
video: true,
audio: false
})
.then(function (stream) {
video.srcObject = stream;
video.play();
})
.catch(function (err) {
$("#capture-patron-image").hide();
$("#camera-error").css("display", "flex");
$("#camera-error-message").text( showMediaErrors( err ) );
});
} catch(err) {
$("#capture-patron-image").hide();
$("#camera-error").css("display", "flex");
$("#camera-error-message").text( showMediaErrors( err ) );
}
video.addEventListener('canplay', function () {
if (!streaming) {
height = video.videoHeight / (video.videoWidth / width);
// Firefox currently has a bug where the height can't be read from
// the video, so we will make assumptions if this happens.
if (isNaN(height)) {
height = width / (4 / 3);
}
video.setAttribute('width', width);
video.setAttribute('height', height);
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
photo.setAttribute('width', width);
photo.setAttribute('height', height);
streaming = true;
}
}, false);
takebutton.addEventListener('click', function (ev) {
takepicture();
ev.preventDefault();
}, false);
retakebutton.addEventListener('click', function (ev) {
ev.preventDefault();
retakephoto();
}, false);
clearphoto();
}
function showMediaErrors( err ){
// Example error: "NotAllowedError: Permission denied"
var errorcode = err.toString().split(":");
var output;
switch ( errorcode[0] ) {
case "NotFoundError":
case "DevicesNotFoundError":
output = __("No camera detected.");
break;
case "NotReadableError":
case "TrackStartError":
output = __("Could not access camera.");
break;
case "NotAllowedError":
case "PermissionDeniedError":
output = __("Access to camera denied.");
break;
case "TypeError":
output = __("This feature is available only in secure contexts (HTTPS).");
break;
default:
output = __("An unknown error occurred: ") + err;
break;
}
return output;
}
/**
* Clear anything passed to the canvas element and the corresponding image.
*/
function clearphoto() {
var context = canvas.getContext('2d');
context.fillStyle = "#AAA";
context.fillRect(0, 0, canvas.width, canvas.height);
var data = canvas.toDataURL('image/jpeg', 1.0);
photo.setAttribute('src', data);
}
/**
* Reset the interface to hide download and save buttons.
* Redisplay camera "shutter" button.
*/
function retakephoto(){
downloadbutton.href= "";
downloadbutton.style.display = "none";
takebutton.style.display = "inline-block";
retakebutton.style.display = "none";
savebutton.style.display = "none";
output.style.display = "none";
photo.src = "";
camera.style.display = "block";
uploadfiletext.value = "";
}
/**
* Capture the data from the user's camera and write it to the canvas element.
* The canvas data is converted to a data-url, and that URL set as the src
* attribute of an image.
* Display two controls for the captured photo: Download (to save to the
* user's computer) and Upload (save to the patron's record in Koha).
*/
function takepicture() {
var context = canvas.getContext('2d');
var cardnumber = document.getElementById("cardnumber").value;
camera.style.display = "none";
downloadbutton.style.display = '';
output.style.display = "block";
takebutton.style.display = "none";
retakebutton.style.display = "inline-block";
savebutton.style.display = "inline-block";
if (width && height) {
canvas.width = width;
canvas.height = height;
context.drawImage(video, 0, 0, width, height);
var data = canvas.toDataURL('image/jpeg', 1.0);
photo.setAttribute('src', data);
if( cardnumber !== '' ){
// Download a file which the patrons card number as its name
downloadbutton.download = cardnumber + ".jpg";
} else {
downloadbutton.download = "patron-photo.jpg";
}
downloadbutton.href = data;
uploadfiletext.value = data;
} else {
clearphoto();
}
}