.
This commit is contained in:
@@ -6,11 +6,12 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
let normal = false;
|
||||
let csrf_token = "{{csrf_token}}";
|
||||
let hash_url = "{% url 'rapids:rapid_question_by_hash' %}";
|
||||
//let monitor_directory_handler = false;
|
||||
//let monitor_interval_id = false;
|
||||
|
||||
// set to hold the files that are still being processed
|
||||
let active_file_inputs = new Set();
|
||||
let load_viewer = false;
|
||||
|
||||
// async function listAllFilesAndDirs(dirHandle, files_only) {
|
||||
@@ -39,84 +40,13 @@
|
||||
// return files;
|
||||
// }
|
||||
|
||||
function showEditPopup(url) {
|
||||
var win = window.open(url, "Edit",
|
||||
'height=500,width=800,resizable=yes,scrollbars=yes');
|
||||
return false;
|
||||
}
|
||||
|
||||
function showAddPopup(triggeringLink) {
|
||||
var name = triggeringLink.id.replace(/^add_/, '');
|
||||
href = triggeringLink.href;
|
||||
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
|
||||
win.focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
function closePopup(win, newID, newRepr, id) {
|
||||
$(id + "_to").append('<option value=' + newID + ' title=' + newRepr + ' >' + newRepr + '</option>')
|
||||
win.close();
|
||||
}
|
||||
|
||||
document.addEventListener('drop', function (e) {
|
||||
e.preventDefault();
|
||||
}, false);
|
||||
|
||||
function getUnusedInputs(inputs) {
|
||||
new_inputs = [];
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
input = inputs.get(i);
|
||||
|
||||
if (!input.value) {
|
||||
new_inputs.push(input);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $(new_inputs);
|
||||
|
||||
}
|
||||
|
||||
function getCurrentFiles() {
|
||||
inputs = $("#rapid-form input[type=file]");
|
||||
|
||||
let files = new Set();
|
||||
for (let j = 0; j < inputs.length; j++) {
|
||||
i = inputs.get(j);
|
||||
if (i.files.length > 0) {
|
||||
files.add(i.files[0]);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
function extendInputs(n) {
|
||||
// Makes sure we have n inputs available
|
||||
// returns available inputs
|
||||
inputs = getUnusedInputs($("#rapid-form input[type=file][id^=id_images-]"));
|
||||
//fileInput = document.getElementById("id_images-0-image");
|
||||
|
||||
|
||||
// Make sure we have enough input targets
|
||||
input_diff = (n - inputs.length)
|
||||
|
||||
if (input_diff > 0) {
|
||||
for (let j = 0; j < input_diff; j++) {
|
||||
add_input_form()
|
||||
}
|
||||
|
||||
// Need to make sure we include the new ones...
|
||||
inputs = getUnusedInputs($("#rapid-form input[type=file][id^=id_images-]"));
|
||||
}
|
||||
return inputs;
|
||||
}
|
||||
|
||||
function add_input_form() {
|
||||
var form_idx = $('#id_images-TOTAL_FORMS').val();
|
||||
$('#image_form_set').append($($('#empty_form').html().replace(/__prefix__/g, form_idx)).on("change",
|
||||
input_change));
|
||||
$('#id_images-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
||||
}
|
||||
|
||||
function add_answers_input_form() {
|
||||
var form_idx = $('#id_answers-TOTAL_FORMS').val();
|
||||
@@ -125,62 +55,6 @@
|
||||
$('#id_answers-TOTAL_FORMS').val(parseInt(form_idx) + 1);
|
||||
}
|
||||
|
||||
function input_change(evt) {
|
||||
file = evt.target.files[0];
|
||||
$(evt.target).removeClass("image-ident-warning");
|
||||
$(evt.target).removeClass("image-ident-ok");
|
||||
|
||||
|
||||
|
||||
el = evt.target;
|
||||
|
||||
|
||||
//readFileAndProcess();
|
||||
readFileAndProcess2(el);
|
||||
|
||||
// Check if we have selected a examination type
|
||||
if (!$("#id_examination_to option").length) {
|
||||
|
||||
// Yes we do read the file twice (here and where loading it in the viewer)
|
||||
var reader = new FileReader();
|
||||
reader.onload = function (file) {
|
||||
var arrayBuffer = reader.result;
|
||||
// Here we have the file data as an ArrayBuffer. dicomParser requires as input a
|
||||
// Uint8Array so we create that here
|
||||
var byteArray = new Uint8Array(arrayBuffer);
|
||||
extractDicomStudyDescription(byteArray)
|
||||
}
|
||||
reader.readAsArrayBuffer(file);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function addFile(f, feedback) {
|
||||
let dT = new DataTransfer();
|
||||
dT.clearData();
|
||||
dT.items.add(f);
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
el = inputs.get(i);
|
||||
|
||||
if (el.files.length == 0) {
|
||||
el.files = dT.files;
|
||||
//ocr(el)
|
||||
|
||||
if (feedback) {
|
||||
arr = el.name.split("-");
|
||||
arr.splice(2, 1, "feedback_image");
|
||||
feedback_el_name = arr.join("-");
|
||||
|
||||
$(`[name=${feedback_el_name}]`).prop("checked", true);
|
||||
}
|
||||
|
||||
$(el).change();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
$(document).ready(function () {
|
||||
@@ -223,7 +97,7 @@
|
||||
}
|
||||
|
||||
// Get all input elements
|
||||
inputs = extendInputs(file_drop_number);
|
||||
inputs = extendInputs("rapid-form", file_drop_number);
|
||||
|
||||
console.log("drop inputs", inputs, evt);
|
||||
|
||||
@@ -250,7 +124,7 @@
|
||||
// listAllFilesAndDirs(monitor_directory_handler).then(async function (
|
||||
// items) {
|
||||
// files_to_add = new Set();
|
||||
// current_files = getCurrentFiles();
|
||||
// current_files = getCurrentFormFiles();
|
||||
// current_files_tuple = new Set()
|
||||
// for (let elem of current_files) {
|
||||
// current_files_tuple.add(
|
||||
@@ -368,321 +242,83 @@
|
||||
|
||||
});
|
||||
|
||||
function ocr2(url, input) {
|
||||
console.log("OCR", url, input)
|
||||
Tesseract.recognize(
|
||||
url,
|
||||
'eng',
|
||||
{ logger: m => console.log(m) }
|
||||
).then(({ data: { text } }) => {
|
||||
l = text.toLowerCase();
|
||||
uploading_el = $(`img[data-input-id='${input.id}'], div[data-input-id='${input.id}']`)
|
||||
uploading_el.removeClass("image-ident-loading");
|
||||
console.log("found text", l);
|
||||
if (l.includes("accesion") || l.includes("number") || l.search(
|
||||
/(ref|rk9|rh8|ra9|rbz)\d+/g) > -1) {
|
||||
console.log("Match found ", input);
|
||||
$(input).addClass("image-ident-warning");
|
||||
uploading_el.addClass("image-ident-warning");
|
||||
} else {
|
||||
$(input).addClass("image-ident-ok");
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
async function blobToBase64(blob) {
|
||||
return new Promise((resolve, _) => {
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => resolve(reader.result);
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
}
|
||||
// async function readFileAndProcess(callback) {
|
||||
// //$("#single-dicom-viewer").empty()
|
||||
// //images = []
|
||||
// //Function that returns a promise to read the file
|
||||
// const reader = (file) => {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// const fileReader = new FileReader();
|
||||
// fileReader.onload = () => resolve(fileReader);
|
||||
// fileReader.readAsDataURL(file);
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// // Add file to the process list
|
||||
// active_file_inputs.add(el)
|
||||
// const readFile = (file, el) => {
|
||||
// reader(file).then(reader => {
|
||||
// console.log("12345", reader)
|
||||
// $(el).parent().parent().find(".temp-thumb").remove();
|
||||
//
|
||||
// if (reader.result.startsWith("data:application/octet-stream;base64")) {
|
||||
// const element = $(`<div class='temp-thumb' src=${reader.result}></div>`).get(0)
|
||||
// $(el).parent().parent().prepend(element);
|
||||
// const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add(
|
||||
// file
|
||||
// );
|
||||
// cornerstone.enable(element);
|
||||
// cornerstone.loadAndCacheImage(imageId).then(function (image) {
|
||||
// cornerstone.displayImage(element, image);
|
||||
// cornerstone.resize(element)
|
||||
//
|
||||
// });
|
||||
//
|
||||
// } else {
|
||||
// var image = new Image();
|
||||
// image.title = file.name;
|
||||
// image.src = reader.result;
|
||||
// image.className = "temp-thumb";
|
||||
// $(el).parent().parent().prepend(image);
|
||||
// //images.push(reader.result);
|
||||
// }
|
||||
//
|
||||
// active_file_inputs.delete(el)
|
||||
// console.log("active", active_file_inputs)
|
||||
// // Only load once all queued files have been processed
|
||||
// if (active_file_inputs.size < 1) {
|
||||
// loadViewer();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// file_set = $("#image_form_set input[type=file]");
|
||||
//
|
||||
// file_set.each(async (n, el) => {
|
||||
// if (el.files.length > 0) {
|
||||
// filename = el.files[0].name;
|
||||
// // Probably no need to await here anymore
|
||||
// await readFile(el.files[0], el);
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
async function readFileAndProcess2(el) {
|
||||
|
||||
//file_set = $("#image_form_set input[type=file]");
|
||||
|
||||
//file_set.each(async (n, el) => {
|
||||
|
||||
if (el.files.length > 0) {
|
||||
filename = el.files[0].name;
|
||||
// Probably no need to await here anymore
|
||||
//await readFile(el.files[0], el);
|
||||
// const viewLoadChecker = setInterval(function () {
|
||||
// if (load_viewer) {
|
||||
// load_viewer = false;
|
||||
// loadViewer();
|
||||
// }
|
||||
// }, 2000);
|
||||
|
||||
|
||||
|
||||
|
||||
console.log(el.files[0])
|
||||
function extractDicomDetails(byteArray) {
|
||||
if (!$("#id_examination_to option").length) {
|
||||
|
||||
$(el).parent().parent().find(".temp-thumb").remove();
|
||||
|
||||
let url = URL.createObjectURL(el.files[0])
|
||||
|
||||
n = el.id.split("-")[1];
|
||||
$(`#drop-filenames span[data-input-id='${el.id}']`).remove();
|
||||
|
||||
let extra_class = " image-ident-loading";
|
||||
if ($(el).hasClass("image-ident-warning")) {
|
||||
extra_class = " image-ident-warning";
|
||||
} else if ($(el).hasClass("image-ident-ok")) {
|
||||
extra_class = " image-ident-ok";
|
||||
}
|
||||
|
||||
//let extra_class = "";
|
||||
let imageId;
|
||||
if (el.files[0].type.startsWith("image")) {
|
||||
|
||||
let hash = CryptoJS.MD5(el.files[0]).toString();
|
||||
console.log("HASH", hash)
|
||||
|
||||
base = await blobToBase64(el.files[0]);
|
||||
imageId = "base64://" + base.split(",")[1];
|
||||
imageId2 = base;
|
||||
const element = $(`<img class='temp-thumb' src=${imageId}></div>`).get(0)
|
||||
$(el).parent().parent().prepend(element);
|
||||
|
||||
|
||||
ocr2(url, el);
|
||||
checkHash(hash, el);
|
||||
|
||||
$("#drop-filenames").append(
|
||||
`<span data-input-id='${el.id}'><span>${n}: ${el.files[0].name}</span><img class='uploading${extra_class}' data-input-id='${el.id}' src=${url}></span>`
|
||||
)
|
||||
} else {
|
||||
imageId = `wadouri:${url}`;
|
||||
imageId2 = imageId
|
||||
|
||||
console.log(imageId)
|
||||
const element = $(`<div class='temp-thumb' src=${imageId2}></div>`).get(0)
|
||||
$(el).parent().parent().prepend(element);
|
||||
cornerstone.enable(element);
|
||||
cornerstone.loadAndCacheImage(imageId).then(function (image) {
|
||||
cornerstone.displayImage(element, image);
|
||||
cornerstone.resize(element)
|
||||
|
||||
|
||||
let pixel_data = image.getPixelData().toString()
|
||||
console.log(element, "pixel data", pixel_data)
|
||||
|
||||
let hash = CryptoJS.MD5(pixel_data).toString();
|
||||
console.log(element, "HASH", hash)
|
||||
checkHash(hash, el);
|
||||
|
||||
});
|
||||
|
||||
$("#drop-filenames").append(
|
||||
`<span data-input-id='${el.id}'><span>${n}: ${el.files[0].name}</span><div class='uploading${extra_class}' data-input-id='${el.id}' src=${url}></div></span>`
|
||||
)
|
||||
|
||||
const element2 = $(`#drop-filenames div[data-input-id='${el.id}']`).get(0);
|
||||
cornerstone.enable(element2);
|
||||
cornerstone.loadAndCacheImage(imageId).then(function (image) {
|
||||
cornerstone.displayImage(element2, image);
|
||||
|
||||
$(element2).addClass("temp-thumb-large");
|
||||
cornerstone.resize(element2)
|
||||
setTimeout(function () {
|
||||
ocr2($(element2).find("canvas").get(0).toDataURL(), el);
|
||||
$(element2).removeClass("temp-thumb-large");
|
||||
cornerstone.resize(element2)
|
||||
}, 500);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
active_file_inputs.delete(el)
|
||||
console.log("active", active_file_inputs)
|
||||
// Only load once all queued files have been processed
|
||||
if (active_file_inputs.size < 1) {
|
||||
load_viewer = true;
|
||||
//loadViewer();
|
||||
}
|
||||
}
|
||||
//})
|
||||
}
|
||||
|
||||
async function readFileAndProcess(callback) {
|
||||
//$("#single-dicom-viewer").empty()
|
||||
//images = []
|
||||
//Function that returns a promise to read the file
|
||||
const reader = (file) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onload = () => resolve(fileReader);
|
||||
fileReader.readAsDataURL(file);
|
||||
});
|
||||
}
|
||||
|
||||
// Add file to the process list
|
||||
active_file_inputs.add(el)
|
||||
const readFile = (file, el) => {
|
||||
reader(file).then(reader => {
|
||||
console.log("12345", reader)
|
||||
$(el).parent().parent().find(".temp-thumb").remove();
|
||||
|
||||
if (reader.result.startsWith("data:application/octet-stream;base64")) {
|
||||
const element = $(`<div class='temp-thumb' src=${reader.result}></div>`).get(0)
|
||||
$(el).parent().parent().prepend(element);
|
||||
const imageId = cornerstoneWADOImageLoader.wadouri.fileManager.add(
|
||||
file
|
||||
);
|
||||
cornerstone.enable(element);
|
||||
cornerstone.loadAndCacheImage(imageId).then(function (image) {
|
||||
cornerstone.displayImage(element, image);
|
||||
cornerstone.resize(element)
|
||||
|
||||
});
|
||||
|
||||
} else {
|
||||
var image = new Image();
|
||||
image.title = file.name;
|
||||
image.src = reader.result;
|
||||
image.className = "temp-thumb";
|
||||
$(el).parent().parent().prepend(image);
|
||||
//images.push(reader.result);
|
||||
}
|
||||
|
||||
active_file_inputs.delete(el)
|
||||
console.log("active", active_file_inputs)
|
||||
// Only load once all queued files have been processed
|
||||
if (active_file_inputs.size < 1) {
|
||||
loadViewer();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
file_set = $("#image_form_set input[type=file]");
|
||||
|
||||
file_set.each(async (n, el) => {
|
||||
if (el.files.length > 0) {
|
||||
filename = el.files[0].name;
|
||||
// Probably no need to await here anymore
|
||||
await readFile(el.files[0], el);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const viewLoadChecker = setInterval(function () {
|
||||
if (load_viewer) {
|
||||
load_viewer = false;
|
||||
loadViewer();
|
||||
}
|
||||
}, 2000);
|
||||
|
||||
function loadViewer() {
|
||||
console.log("LOAD VIEWER")
|
||||
// temp fix before starting viewer collapsed
|
||||
$("#single-dicom-viewer").show()
|
||||
//file_set = $("#image_form_set input[type=file]");
|
||||
|
||||
//n = 0;
|
||||
//for (let i = 0; i < file_set.length; i++) {
|
||||
// el = file_set.get(i)
|
||||
// if (el.files.length > 0) {
|
||||
// n++;
|
||||
// }
|
||||
//}
|
||||
|
||||
image_set = $("#image_form_set .temp-thumb").get()//.map(function() { return $(this).attr("src")}).get();
|
||||
console.log(image_set);
|
||||
//console.log()
|
||||
//if (n == image_set.length) {
|
||||
const event = new CustomEvent('loadDicomViewer', {
|
||||
"detail": image_set
|
||||
});
|
||||
|
||||
window.dispatchEvent(event);
|
||||
sortable('.sortable');
|
||||
//sortable('.sortable')[0].addEventListener('sortstop', function(e) {
|
||||
updateImagePositions();
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
function updateImagePositions() {
|
||||
console.log("UP pos");
|
||||
|
||||
file_set = $("#image_form_set ul");
|
||||
|
||||
n = 0;
|
||||
for (let i = 0; i < file_set.length; i++) {
|
||||
ul = file_set.get(i);
|
||||
console.log(ul)
|
||||
|
||||
file_element = $(ul).find("input[type=file]").get(0);
|
||||
|
||||
// If a (new) file is being uploaded we save it's name prior to it being hashed
|
||||
if (file_element.files.length > 0) {
|
||||
file_name = file_element.files[0].name
|
||||
//$(ul).find("input[type=text]").val(file_name);
|
||||
$(ul).find("input[name*='filename']").val(file_name);
|
||||
}
|
||||
|
||||
if (file_element.files.length > 0 || $(ul).find(":contains('Currently:')")) {
|
||||
n++;
|
||||
$(ul).find("input[type=number]").val(n);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function checkHash(hash, input) {
|
||||
$.ajax({
|
||||
url: "{% url 'rapids:rapid_question_by_hash' %}",
|
||||
data: {
|
||||
csrfmiddlewaretoken: '{{ csrf_token }}',
|
||||
hash: hash
|
||||
},
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
})
|
||||
// $.ajax().done(), $.ajax().fail(), $ajax().always() are upto you. Add/change accordingly
|
||||
.done(function (data) {
|
||||
console.log(data);
|
||||
|
||||
if (data.status == "success") {
|
||||
console.log("success");
|
||||
console.log(data.id)
|
||||
if (data.id) {
|
||||
//toastr.info(`id ${data.id}`)
|
||||
uploading_el = $(`img[data-input-id='${input.id}'], div[data-input-id='${input.id}']`)
|
||||
$(input).addClass("image-duplicate");
|
||||
uploading_el.addClass("image-duplicate");
|
||||
|
||||
toastr.warning(`Image (${input.files[0].name}) already exists.<br /><a href='${data.url}'>Click to view</a><br /><button type="button" class="btn clear">Dismiss</button>`, "Duplicate image", {
|
||||
"closeButton": false,
|
||||
"debug": false,
|
||||
"newestOnTop": false,
|
||||
"progressBar": false,
|
||||
"positionClass": "toast-top-full-width",
|
||||
"preventDuplicates": false,
|
||||
"onclick": null,
|
||||
"showDuration": "0",
|
||||
"hideDuration": "0",
|
||||
"timeOut": 0,
|
||||
"extendedTimeOut": 0,
|
||||
"showEasing": "swing",
|
||||
"hideEasing": "linear",
|
||||
"showMethod": "fadeIn",
|
||||
"hideMethod": "fadeOut",
|
||||
"tapToDismiss": false
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
.always(function () {
|
||||
console.log('[Done]');
|
||||
})
|
||||
}
|
||||
|
||||
function extractDicomStudyDescription(byteArray) {
|
||||
// We need to setup a try/catch block because parseDicom will throw an exception
|
||||
// if you attempt to parse a non dicom part 10 file (or one that is corrupted)
|
||||
try {
|
||||
@@ -717,6 +353,7 @@
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user