This commit is contained in:
Ross
2025-11-11 11:12:36 +00:00
parent 9ebcd24938
commit 9a9ce11ccb
4 changed files with 620 additions and 622 deletions
@@ -238,8 +238,8 @@
{% csrf_token %}
<a href="/anatomy/examination/create" id="add_examination" class="add-popup"
onclick="return showAddPopup(this);"><img src="{% static 'img/icon-addlink.svg' %}"></a>
<a href="/anatomy/body_part/create" id="add_body_part" class="add-popup"
onclick="return showAddPopup(this);"><img src="{% static 'img/icon-addlink.svg' %}"></a>
<a href="/anatomy/body_part/create" id="add_body_part" class="add-popup"
onclick="return showAddPopup(this);"><img src="{% static 'img/icon-addlink.svg' %}"></a>
{{ form|crispy }}
<div id="drop-container" class="drop-target">Drop image here
+230 -230
View File
@@ -5,109 +5,109 @@
{% block js %}
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
<script type="text/javascript">
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) {
console.log(id)
$(id + "_to").append('<option value=' + newID + ' title=' + newRepr + ' >' + newRepr + '</option>')
win.close();
}
<script type="text/javascript">
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) {
console.log(id)
$(id + "_to").append('<option value=' + newID + ' title=' + newRepr + ' >' + newRepr + '</option>')
win.close();
}
document.addEventListener('drop', function (e) { e.preventDefault(); }, false);
document.addEventListener('drop', function (e) { e.preventDefault(); }, false);
function add_input_form() {
var form_idx = $('#id_images-TOTAL_FORMS').val();
$('#image_form_set').append($('#empty_form').html().replace(/__prefix__/g, form_idx));
$('#id_images-TOTAL_FORMS').val(parseInt(form_idx) + 1);
}
function add_input_form() {
var form_idx = $('#id_images-TOTAL_FORMS').val();
$('#image_form_set').append($('#empty_form').html().replace(/__prefix__/g, form_idx));
$('#id_images-TOTAL_FORMS').val(parseInt(form_idx) + 1);
}
function add_answers_input_form() {
var form_idx = $('#id_answers-TOTAL_FORMS').val();
$('#answer_form_set').append($('#answer_empty_form').html().replace(/__prefix__/g, form_idx));
$('#id_answers-TOTAL_FORMS').val(parseInt(form_idx) + 1);
}
function add_answers_input_form() {
var form_idx = $('#id_answers-TOTAL_FORMS').val();
$('#answer_form_set').append($('#answer_empty_form').html().replace(/__prefix__/g, form_idx));
$('#id_answers-TOTAL_FORMS').val(parseInt(form_idx) + 1);
}
$(document).ready(function () {
$("#add_examination").appendTo($("label[for='id_examination']"));
$(document).ready(function () {
$("#add_examination").appendTo($("label[for='id_examination']"));
dropContainer = document.getElementById("drop-container");
dropContainer = document.getElementById("drop-container");
dropContainer.ondragover = function (evt) {
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragover = function (evt) {
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragenter = function (evt) {
console.log("ENTER")
console.log(evt)
$(evt.target).addClass("drop-target-active")
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragenter = function (evt) {
console.log("ENTER")
console.log(evt)
$(evt.target).addClass("drop-target-active")
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragleave = function (evt) {
console.log("ENTER")
console.log(evt)
$(evt.target).removeClass("drop-target-active")
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragleave = function (evt) {
console.log("ENTER")
console.log(evt)
$(evt.target).removeClass("drop-target-active")
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondrop = function (evt) {
$(evt.target).removeClass("drop-target-active");
dropContainer.ondrop = function (evt) {
$(evt.target).removeClass("drop-target-active");
if (evt.dataTransfer.files.length < 1) {
toastr.warning(`Drop failed :( try again?`);
} else {
toastr.info(`Adding ${evt.dataTransfer.files.length} files.`);
}
if (evt.dataTransfer.files.length < 1) {
toastr.warning(`Drop failed :( try again?`);
} else {
toastr.info(`Adding ${evt.dataTransfer.files.length} files.`);
}
// Get all input elements
inputs = $("#long-form input[type=file][id^=id_images-]");
inputs = $("#long-form input[type=file][id^=id_images-]");
//fileInput = document.getElementById("id_images-0-image");
// Make sure we have enough input targets
input_diff = (evt.dataTransfer.files.length - inputs.length)
input_diff = (evt.dataTransfer.files.length - inputs.length)
if (input_diff > 0) {
for (let j = 0; j < input_diff; j++) {
add_input_form()
}
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 = $("#long-form input[type=file][id^=id_images-]");
}
inputs = $("#long-form input[type=file][id^=id_images-]");
}
// Loop through each dropped file and try to assign to an
// input element
[...evt.dataTransfer.files].forEach((f) => {
let dT = new DataTransfer();
dT.clearData();
dT.items.add(f);
for (let i = 0; i < inputs.length; i++) {
el = inputs.get(i)
[...evt.dataTransfer.files].forEach((f) => {
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;
if (el.files.length == 0) {
el.files = dT.files;
//ocr(el)
return false
return false
}
}
}
})
})
// // If you want to use some of the dropped files
// const dT = new DataTransfer();
@@ -115,31 +115,31 @@
// dT.items.add(evt.dataTransfer.files[3]);
// fileInput.files = dT.files;
loadDicomViewerAndFileImages();
loadDicomViewerAndFileImages();
evt.preventDefault();
evt.stopPropagation();
};
evt.preventDefault();
evt.stopPropagation();
};
$('#add_more_images').click(() => { add_input_form() });
$('#add_more_answers').click(() => { add_answers_input_form() });
$('#add_more_images').click(() => { add_input_form() });
$('#add_more_answers').click(() => { add_answers_input_form() });
$("input[type=file]").on('change', function () {
$(this).removeClass("image-ident-warning");
$(this).removeClass("image-ident-ok");
console.log("input change1");
console.log("input change", this);
$("input[type=file]").on('change', function () {
$(this).removeClass("image-ident-warning");
$(this).removeClass("image-ident-ok");
console.log("input change1");
console.log("input change", this);
//ocr(this);
//LoadDicomViewer();
});
});
sortable('.sortable');
sortable('.sortable')[0].addEventListener('sortupdate', function(e) {
sortable('.sortable');
sortable('.sortable')[0].addEventListener('sortupdate', function(e) {
/*
This event is triggered when the user stops sorting and the DOM position has not yet changed.
@@ -153,15 +153,15 @@
*/
//updateImagePositions();
$(".temp-thumb").remove()
loadDicomViewer();
$(".temp-thumb").remove()
loadDicomViewer();
});
});
});
function ocr(input) {
function ocr(input) {
// Tesseract.recognize(f, "eng",{ logger: m => console.log(m) }
// ).then(({ data: { text } }) => {
// console.log(text);
@@ -171,186 +171,186 @@
// }
// })
console.log('{% static "worker.min.js" %}');
console.log('{{ STATIC_URL }}/tesseract-core.wasm.js %}');
console.log('{% static "worker.min.js" %}');
console.log('{{ STATIC_URL }}/tesseract-core.wasm.js %}');
const worker = Tesseract.createWorker({
workerPath: '{% static "worker.min.js" %}',
langPath: '{% static "" %}',
const worker = Tesseract.createWorker({
workerPath: '{% static "worker.min.js" %}',
langPath: '{% static "" %}',
//langPath: '{{ STATIC_URL }}',
corePath: '{% static "tesseract-core.wasm.js" %}',
});
corePath: '{% static "tesseract-core.wasm.js" %}',
});
const url = URL.createObjectURL(input.files[0]);
let img = new Image;
img.src = url;
const url = URL.createObjectURL(input.files[0]);
let img = new Image;
img.src = url;
img.onload = function () {
img.onload = function () {
width = img.width;
width = img.width;
// const rectangle = { left: 0, top: 0, width: width, height: 10 }
(async () => {
await worker.load();
await worker.loadLanguage('eng');
await worker.initialize('eng');
(async () => {
await worker.load();
await worker.loadLanguage('eng');
await worker.initialize('eng');
// const { data: { text } } = await worker.recognize(input.files[0], { rectangle });
const { data: { text } } = await worker.recognize(input.files[0]);
const { data: { text } } = await worker.recognize(input.files[0]);
//console.log(text);
l = text.toLowerCase();
$(`img[data-input-id='${input.id}'`).removeClass("image-ident-loading");
console.log(l);
if (l.includes("accesion") || l.includes("number") || l.search(/(ref|rk9|rh8|ra9|rbz)\d+/g) > -1) {
$(input).addClass("image-ident-warning");
$(`img[data-input-id='${input.id}'`).addClass("image-ident-warning");
} else {
$(input).addClass("image-ident-ok");
l = text.toLowerCase();
$(`img[data-input-id='${input.id}'`).removeClass("image-ident-loading");
console.log(l);
if (l.includes("accesion") || l.includes("number") || l.search(/(ref|rk9|rh8|ra9|rbz)\d+/g) > -1) {
$(input).addClass("image-ident-warning");
$(`img[data-input-id='${input.id}'`).addClass("image-ident-warning");
} else {
$(input).addClass("image-ident-ok");
}
}
await worker.terminate();
})();
await worker.terminate();
})();
}
}
}
async function loadDicomViewerAndFileImages(callback) {
$("#single-dicom-viewer").empty()
async function loadDicomViewerAndFileImages(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);
});
}
const reader = (file) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.onload = () => resolve(fileReader);
fileReader.readAsDataURL(file);
});
}
const readFile = (file, el) => {
reader(file).then(reader => {
var image = new Image();
image.height = 100;
image.title = file.name;
image.src = reader.result;
image.className = "temp-thumb";
console.log("read" ,el);
$(el).parent().parent().prepend(image);
const readFile = (file, el) => {
reader(file).then(reader => {
var image = new Image();
image.height = 100;
image.title = file.name;
image.src = reader.result;
image.className = "temp-thumb";
console.log("read" ,el);
$(el).parent().parent().prepend(image);
//images.push(reader.result);
loadViewer(images);
});
loadViewer(images);
});
}
file_set = $("#image_form_set input[type=file]");
file_set.each(async (n, el) => {
console.log(el);
if (el.files.length > 0) {
filename = el.files[0].name;
await readFile(el.files[0], el);
}
})
console.log("images from files", images);
}
file_set = $("#image_form_set input[type=file]");
file_set.each(async (n, el) => {
console.log(el);
if (el.files.length > 0) {
filename = el.files[0].name;
await readFile(el.files[0], el);
}
})
console.log("images from files", images);
}
function loadViewer(images) {
function loadViewer(images) {
//dicomViewer.loadCornerstone($("#single-dicom-viewer"), null, images, annotations);
file_set = $("#image_form_set input[type=file]");
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++;
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 img");
if (n == image_set.length) {
const event = new CustomEvent('loadDicomViewer', { "detail": image_set });
image_set = $("#image_form_set img");
if (n == image_set.length) {
const event = new CustomEvent('loadDicomViewer', { "detail": image_set });
window.dispatchEvent(event);
sortable('.sortable');
window.dispatchEvent(event);
sortable('.sortable');
//sortable('.sortable')[0].addEventListener('sortstop', function(e) {
updateImagePositions();
updateImagePositions();
}
}
}
function updateImagePositions() {
console.log("UP pos");
function updateImagePositions() {
console.log("UP pos");
file_set = $("#image_form_set ul");
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)
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);
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);
if (file_element.files.length > 0) {
file_name = file_element.files[0].name
$(ul).find("input[type=text]").val(file_name);
}
if (file_element.files.length > 0 || $(ul).find(":contains('Currently:')")) {
n++;
$(ul).find("input[type=number]").val(n);
}
}
if (file_element.files.length > 0 || $(ul).find(":contains('Currently:')")) {
n++;
$(ul).find("input[type=number]").val(n);
}
}
</script>
}
</script>
{{ form.media }}
{{ form.media }}
{% endblock %}
{% block content %}
<h2>Series Form</h2>
This form will create a image set that can be associated with a long question. If the question has already been created it can be linked below.
<form action="" method="post" enctype="multipart/form-data" id="long-form">
{% csrf_token %}
<a href="/generic/examination/create" id="add_examination" class="add-popup"
onclick="return showAddPopup(this);"><img src="{% static 'img/icon-addlink.svg' %}"></a>
<table>
{{ form.as_table }}
</table>
<h2>Series Form</h2>
This form will create a image set that can be associated with a long question. If the question has already been created it can be linked below.
<form action="" method="post" enctype="multipart/form-data" id="long-form">
{% csrf_token %}
<a href="/generic/examination/create" id="add_examination" class="add-popup"
onclick="return showAddPopup(this);"><img src="{% static 'img/icon-addlink.svg' %}"></a>
<table>
{{ form.as_table }}
</table>
<h3>Images:</h3>
<input type="button" value="Add More Images" id="add_more_images">
<div id="drop-container" class="">Drop images here (or use the buttons below). Dropping images here will overwrite existing images in the series. When drag and dropping make sure to drag the first image or the order will not be maintained. Note: dicom images are often not exported in order (although their order can be automatically detected once uploaded)
<div id="single-dicom-viewer" class="dicom-viewer" data-images="" data-annotations=''></div>
<div id="drop-filenames"></div>
</div>
<div id="image_form_set" class="sortable">
{% for form in image_formset %}
<ul class="no-error image-formset">
{{form.non_field_errors}}
{{form.errors}}
{{ form.as_ul }}
<h3>Images:</h3>
<input type="button" value="Add More Images" id="add_more_images">
<div id="drop-container" class="">Drop images here (or use the buttons below). Dropping images here will overwrite existing images in the series. When drag and dropping make sure to drag the first image or the order will not be maintained. Note: dicom images are often not exported in order (although their order can be automatically detected once uploaded)
<div id="single-dicom-viewer" class="dicom-viewer" data-images="" data-annotations=''></div>
<div id="drop-filenames"></div>
</div>
<div id="image_form_set" class="sortable">
{% for form in image_formset %}
<ul class="no-error image-formset">
{{form.non_field_errors}}
{{form.errors}}
{{ form.as_ul }}
</ul>
{% endfor %}
</div>
{{ image_formset.management_form }}
<input type="submit" class="submit-button" value="Submit" name="submit">
</form>
<div id="empty_form" style="display:none">
<ul class='no_error image-formset'>
{{ image_formset.empty_form.as_ul }}
</ul>
{% endfor %}
</div>
{{ image_formset.management_form }}
<input type="submit" class="submit-button" value="Submit" name="submit">
</form>
<div id="empty_form" style="display:none">
<ul class='no_error image-formset'>
{{ image_formset.empty_form.as_ul }}
</ul>
</div>
<div id="images">
<div id="images">
</div>
</div>
{% endblock %}
+218 -219
View File
@@ -5,14 +5,14 @@
{% block js %}
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
<script type="text/javascript">
let csrf_token = "{{csrf_token}}";
let hash_url = "{% url 'rapids:rapid_question_by_hash' %}";
<script type="text/javascript">
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 load_viewer = false;
let load_viewer = false;
// async function listAllFilesAndDirs(dirHandle, files_only) {
// const files = [];
@@ -41,80 +41,80 @@
// }
document.addEventListener('drop', function (e) {
e.preventDefault();
}, false);
document.addEventListener('drop', function (e) {
e.preventDefault();
}, false);
function add_answers_input_form() {
var form_idx = $('#id_answers-TOTAL_FORMS').val();
$('#answer_form_set').append($('#answer_empty_form').html().replace(/__prefix__/g, form_idx));
$(`#id_answers-${form_idx}-status`).val(2);
$('#id_answers-TOTAL_FORMS').val(parseInt(form_idx) + 1);
}
function add_answers_input_form() {
var form_idx = $('#id_answers-TOTAL_FORMS').val();
$('#answer_form_set').append($('#answer_empty_form').html().replace(/__prefix__/g, form_idx));
$(`#id_answers-${form_idx}-status`).val(2);
$('#id_answers-TOTAL_FORMS').val(parseInt(form_idx) + 1);
}
$(document).ready(function () {
$("#add_abnormality").appendTo($("#abnormality-label"));
$("#add_examination").appendTo($("#examination-label"));
$("#add_region").appendTo($("#region-label"));
$(document).ready(function () {
$("#add_abnormality").appendTo($("#abnormality-label"));
$("#add_examination").appendTo($("#examination-label"));
$("#add_region").appendTo($("#region-label"));
dropContainer = document.getElementById("drop-container");
dropContainer = document.getElementById("drop-container");
dropContainer.ondragover = function (evt) {
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragover = function (evt) {
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragenter = function (evt) {
console.log("ENTER")
console.log(evt)
$(evt.target).addClass("drop-target-active")
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragenter = function (evt) {
console.log("ENTER")
console.log(evt)
$(evt.target).addClass("drop-target-active")
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragleave = function (evt) {
console.log("ENTER")
console.log(evt)
$(evt.target).removeClass("drop-target-active")
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragleave = function (evt) {
console.log("ENTER")
console.log(evt)
$(evt.target).removeClass("drop-target-active")
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondrop = function (evt) {
$(evt.target).removeClass("drop-target-active");
dropContainer.ondrop = function (evt) {
$(evt.target).removeClass("drop-target-active");
file_drop_number = evt.dataTransfer.files.length;
file_drop_number = evt.dataTransfer.files.length;
if (file_drop_number < 1) {
toastr.warning(`Drop failed (no files), try again.`);
} else {
toastr.info(`Loading ${file_drop_number} dropped image(s).`);
}
if (file_drop_number < 1) {
toastr.warning(`Drop failed (no files), try again.`);
} else {
toastr.info(`Loading ${file_drop_number} dropped image(s).`);
}
// Get all input elements
inputs = extendInputs("rapid-form", file_drop_number);
inputs = extendInputs("rapid-form", file_drop_number);
console.log("drop inputs", inputs, evt);
console.log("drop inputs", inputs, evt);
// Loop through each dropped file and try to assign to an
// input element
[...evt.dataTransfer.files].forEach((f) => {
feedback = false;
if (evt.target.id == "feedback-drop-target") {
feedback = true;
}
addFile(f, feedback)
})
[...evt.dataTransfer.files].forEach((f) => {
feedback = false;
if (evt.target.id == "feedback-drop-target") {
feedback = true;
}
addFile(f, feedback)
})
evt.preventDefault();
evt.stopPropagation();
};
evt.preventDefault();
evt.stopPropagation();
};
// $('#directory-picker-button').click(() => {
@@ -170,71 +170,71 @@
$('#add_more_images').click(() => {
add_input_form()
});
$('#add_more_answers').click(() => {
add_answers_input_form()
});
$('#add_more_images').click(() => {
add_input_form()
});
$('#add_more_answers').click(() => {
add_answers_input_form()
});
$("input[type=file]").on('change', input_change);
$("input[type=file]").on('change', input_change);
$("#rapid-form").on("submit", (evt) => {
submit = true;
if (!$normal) {
if ($('#id_answers-TOTAL_FORMS').val() == "0") {
$("#rapid-form").on("submit", (evt) => {
submit = true;
if (!$normal) {
if ($('#id_answers-TOTAL_FORMS').val() == "0") {
submit = false;
add_answers_input_form();
toastr.error(`Question that are not normal require an answer`);
evt.preventDefault();
}
}
if (!$("#id_examination_to option").length) {
submit = false;
add_answers_input_form();
toastr.error(`Question that are not normal require an answer`);
toastr.error("Please add examination type")
evt.preventDefault();
}
}
if (submit) {
toastr.info(`Submiting question... please wait`, '', {
"closeButton": false,
"debug": false,
"newestOnTop": false,
"progressBar": true,
"positionClass": "toast-top-full-width",
"preventDuplicates": false,
"onclick": null,
"showDuration": "300",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
});
}
})
});
function extractDicomDetails(byteArray) {
if (!$("#id_examination_to option").length) {
submit = false;
toastr.error("Please add examination type")
evt.preventDefault();
}
if (submit) {
toastr.info(`Submiting question... please wait`, '', {
"closeButton": false,
"debug": false,
"newestOnTop": false,
"progressBar": true,
"positionClass": "toast-top-full-width",
"preventDuplicates": false,
"onclick": null,
"showDuration": "300",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
});
}
})
});
function extractDicomDetails(byteArray) {
if (!$("#id_examination_to option").length) {
// 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 {
try {
// parse byteArray into a DataSet object using the parseDicom library
var dataSet = dicomParser.parseDicom(byteArray);
var dataSet = dicomParser.parseDicom(byteArray);
// dataSet contains the parsed elements. Each element is available via a property
// in the dataSet.elements object. The property name is based on the elements group
@@ -244,157 +244,156 @@
// To access the data for an element, we need to know its type and its tag.
// We will get the sopInstanceUid from the file which is a string and
// has the tag (0020,000D)
var study_description = dataSet.string('x00081030').toLowerCase();
console.log("STUDY", study_description);
var study_description = dataSet.string('x00081030').toLowerCase();
console.log("STUDY", study_description);
// try to match with a study description (if not already selected)
if ($(`#id_examination_to option`).length < 1) {
option = $(`#id_examination_from option[title*='${study_description}' i]`);
if ($(`#id_examination_to option`).length < 1) {
option = $(`#id_examination_from option[title*='${study_description}' i]`);
if (option.length) {
option.appendTo($("#id_examination_to"));
toastr.success(`Examination set to ${option.attr('title')} from dicom data`);
} else {
toastr.warning(
`Unable to set examination ${study_description} from dicom data (it needs creating)`);
if (option.length) {
option.appendTo($("#id_examination_to"));
toastr.success(`Examination set to ${option.attr('title')} from dicom data`);
} else {
toastr.warning(
`Unable to set examination ${study_description} from dicom data (it needs creating)`);
}
}
} catch (err) {
console.log(err);
}
}
} catch (err) {
console.log(err);
}
}
}
</script>
<script type="text/hyperscript">
init
set global $normal to false
if (#id_normal_0.checked )
Fade(.abnormal-fields) then
set global $normal to true then
</script>
<script type="text/hyperscript">
init
set global $normal to false
if (#id_normal_0.checked )
Fade(.abnormal-fields) then
set global $normal to true then
remove @required from <#answer_form_set textarea/> then
remove @required from <#answer_empty_form textarea.required/>
end
end
remove @required from <#answer_empty_form textarea.required/>
end
end
def Fade(elt)
def Fade(elt)
if elt's style's opacity != "0"
transition element elt opacity to 0 over 350ms
transition element elt transform to "translateY(0.25rem)" over 350ms
hide elt
transition element elt opacity to 0 over 350ms
transition element elt transform to "translateY(0.25rem)" over 350ms
hide elt
else
show elt
transition element elt opacity to 1 over 350ms
transition element elt transform to "translateY(0rem)" over 350ms
transition element elt opacity to 1 over 350ms
transition element elt transform to "translateY(0rem)" over 350ms
end
end
on change from #id_normal_0
if (#id_normal_0.checked )
Fade(.abnormal-fields) then
set global $normal to true then
end
on change from #id_normal_0
if (#id_normal_0.checked )
Fade(.abnormal-fields) then
set global $normal to true then
remove @required from <#answer_form_set textarea/> then
remove @required from <#answer_empty_form textarea.required/>
end
on change from #id_normal_1
if (#id_normal_1.checked )
Fade(.abnormal-fields) then
set global $normal to false then
remove @required from <#answer_empty_form textarea.required/>
end
on change from #id_normal_1
if (#id_normal_1.checked )
Fade(.abnormal-fields) then
set global $normal to false then
add @required to <#answer_form_set textarea/> then
add @required to <#answer_empty_form textarea.required/>
end
add @required to <#answer_empty_form textarea.required/>
end
</script>
</script>
{{ form.media }}
{{ form.media }}
{% endblock %}
{% block content %}
{% if object %}
{% include "rapids/question_link_header.html" %}
{% endif %}
<h2>Submit Rapid</h2>
<p>
<h3>Instructions</h3>
Abnormality, Region and Laterality are used to categorise within the system (they are not used for marking). String
answers that match those added below will be used for automatic marking. Multiple images can be added to a question.
If
the feedback image box is checked they will not be displayed when taking the question.
</p>
{% if object %}
{% include "rapids/question_link_header.html" %}
{% endif %}
<h2>Submit Rapid</h2>
<p>
<h3>Instructions</h3>
Abnormality, Region and Laterality are used to categorise within the system (they are not used for marking). String
answers that match those added below will be used for automatic marking. Multiple images can be added to a question.
If
the feedback image box is checked they will not be displayed when taking the question.
</p>
<!-- <div>
To monitor a directory select it here.<br />
<button id="directory-picker-button">Pick a directory</button>
<span id="directory-picker-display">No directory monitored</span>
</div> -->
<form action="" method="post" enctype="multipart/form-data" id="rapid-form">
<form action="" method="post" enctype="multipart/form-data" id="rapid-form">
{% comment %} {% csrf_token %} {% endcomment %}
<a href="/rapids/abnormality/create" id="add_abnormality" class="add-popup"
onclick="return showAddPopup(this);"><img src="{% static 'img/icon-addlink.svg' %}"></a>
<a href="/rapids/examination/create" id="add_examination" class="add-popup"
onclick="return showAddPopup(this);"><img src="{% static 'img/icon-addlink.svg' %}"></a>
<a href="/rapids/region/create" id="add_region" class="add-popup" onclick="return showAddPopup(this);"><img
<a href="/rapids/abnormality/create" id="add_abnormality" class="add-popup"
onclick="return showAddPopup(this);"><img src="{% static 'img/icon-addlink.svg' %}"></a>
<a href="/rapids/examination/create" id="add_examination" class="add-popup"
onclick="return showAddPopup(this);"><img src="{% static 'img/icon-addlink.svg' %}"></a>
<a href="/rapids/region/create" id="add_region" class="add-popup" onclick="return showAddPopup(this);"><img
src="{% static 'img/icon-addlink.svg' %}"></a>
{% crispy form form.helper %}
{% crispy form form.helper %}
<div class="abnormal-fields">
<h3>Answers:</h3>
<input type="button" value="Add More Answers" id="add_more_answers">
<div id="answer_form_set">
{% for form in answer_formset %}
<ul class="no-error answer-formset">
{{form.non_field_errors}}
{{form.errors}}
{{ form.as_ul }}
</ul>
{% endfor %}
</div>
{{ answer_formset.management_form }}
</div>
<h3>Images:</h3>
<div id="drop-container" class="drop-target">Drop images here (or use the buttons below)<div
<div class="abnormal-fields">
<h3>Answers:</h3>
<input type="button" value="Add More Answers" id="add_more_answers">
<div id="answer_form_set">
{% for form in answer_formset %}
<ul class="no-error answer-formset">
{{form.non_field_errors}}
{{form.errors}}
{{ form.as_ul }}
</ul>
{% endfor %}
</div>
{{ answer_formset.management_form }}
</div>
<h3>Images:</h3>
<div id="drop-container" class="drop-target">Drop images here (or use the buttons below)<div
id="feedback-drop-target">Feedback image?<br />drop those here</div>
<div id="drop-filenames"></div>
</div>
<input type="button" value="Add More Images" id="add_more_images">
<div id="image_form_set">
{% for form in image_formset %}
<ul class="no-error image-formset">
{{form.non_field_errors}}
{{form.errors}}
{{ form.as_ul }}
<div id="drop-filenames"></div>
</div>
<input type="button" value="Add More Images" id="add_more_images">
<div id="image_form_set">
{% for form in image_formset %}
<ul class="no-error image-formset">
{{form.non_field_errors}}
{{form.errors}}
{{ form.as_ul }}
</ul>
{% endfor %}
</div>
{{ image_formset.management_form }}
<input type="submit" class="submit-button" value="Submit" name="submit">
</form>
<div id="empty_form" style="display:none">
<ul class='no_error image-formset'>
{{ image_formset.empty_form.as_ul }}
</ul>
</div>
<div id="answer_empty_form" style="display:none">
<ul class='no_error answer-formset'>
{{ answer_formset.empty_form.as_ul }}
</ul>
{% endfor %}
</div>
{{ image_formset.management_form }}
<input type="submit" class="submit-button" value="Submit" name="submit">
</form>
<div id="empty_form" style="display:none">
<ul class='no_error image-formset'>
{{ image_formset.empty_form.as_ul }}
</ul>
</div>
<div id="answer_empty_form" style="display:none">
<ul class='no_error answer-formset'>
{{ answer_formset.empty_form.as_ul }}
</ul>
</div>
<div id="single-dicom-viewer" class="rapid-dicom-viewer" data-images="" data-annotations='' style="display:none"></div>
<div id="single-dicom-viewer" class="rapid-dicom-viewer" data-images="" data-annotations='' style="display:none"></div>
{% endblock %}
{% block css %}
<style>
.add-popup {
float: left;
}
</style>
<style>
.add-popup {
float: left;
}
</style>
{% endblock css %}
+170 -171
View File
@@ -5,14 +5,14 @@
{% block js %}
<!--<script type="text/javascript" src="/admin/jsi18n/"></script>-->
<script type="text/javascript">
let csrf_token = "{{csrf_token}}";
let hash_url = "{% url 'shorts:question_by_hash' %}";
<script type="text/javascript">
let csrf_token = "{{csrf_token}}";
let hash_url = "{% url 'shorts:question_by_hash' %}";
//let monitor_directory_handler = false;
//let monitor_interval_id = false;
// set to hold the files that are still being processed
let load_viewer = false;
let load_viewer = false;
// async function listAllFilesAndDirs(dirHandle, files_only) {
// const files = [];
@@ -41,78 +41,78 @@
// }
document.addEventListener('drop', function (e) {
e.preventDefault();
}, false);
document.addEventListener('drop', function (e) {
e.preventDefault();
}, false);
function add_answers_input_form() {
var form_idx = $('#id_answers-TOTAL_FORMS').val();
$('#answer_form_set').append($('#answer_empty_form').html().replace(/__prefix__/g, form_idx));
$(`#id_answers-${form_idx}-status`).val(2);
$('#id_answers-TOTAL_FORMS').val(parseInt(form_idx) + 1);
}
function add_answers_input_form() {
var form_idx = $('#id_answers-TOTAL_FORMS').val();
$('#answer_form_set').append($('#answer_empty_form').html().replace(/__prefix__/g, form_idx));
$(`#id_answers-${form_idx}-status`).val(2);
$('#id_answers-TOTAL_FORMS').val(parseInt(form_idx) + 1);
}
$(document).ready(function () {
$("#add_examination").appendTo($("#examination-label"));
$(document).ready(function () {
$("#add_examination").appendTo($("#examination-label"));
dropContainer = document.getElementById("drop-container");
dropContainer = document.getElementById("drop-container");
dropContainer.ondragover = function (evt) {
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragover = function (evt) {
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragenter = function (evt) {
console.log("ENTER")
console.log(evt)
$(evt.target).addClass("drop-target-active")
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragenter = function (evt) {
console.log("ENTER")
console.log(evt)
$(evt.target).addClass("drop-target-active")
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragleave = function (evt) {
console.log("ENTER")
console.log(evt)
$(evt.target).removeClass("drop-target-active")
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondragleave = function (evt) {
console.log("ENTER")
console.log(evt)
$(evt.target).removeClass("drop-target-active")
evt.preventDefault();
evt.stopPropagation();
};
dropContainer.ondrop = function (evt) {
$(evt.target).removeClass("drop-target-active");
dropContainer.ondrop = function (evt) {
$(evt.target).removeClass("drop-target-active");
file_drop_number = evt.dataTransfer.files.length;
file_drop_number = evt.dataTransfer.files.length;
if (file_drop_number < 1) {
toastr.warning(`Drop failed (no files), try again.`);
} else {
toastr.info(`Loading ${file_drop_number} dropped image(s).`);
}
if (file_drop_number < 1) {
toastr.warning(`Drop failed (no files), try again.`);
} else {
toastr.info(`Loading ${file_drop_number} dropped image(s).`);
}
// Get all input elements
inputs = extendInputs("rapid-form", file_drop_number);
inputs = extendInputs("rapid-form", file_drop_number);
console.log("drop inputs", inputs, evt);
console.log("drop inputs", inputs, evt);
// Loop through each dropped file and try to assign to an
// input element
[...evt.dataTransfer.files].forEach((f) => {
feedback = false;
if (evt.target.id == "feedback-drop-target") {
feedback = true;
}
addFile(f, feedback)
})
[...evt.dataTransfer.files].forEach((f) => {
feedback = false;
if (evt.target.id == "feedback-drop-target") {
feedback = true;
}
addFile(f, feedback)
})
evt.preventDefault();
evt.stopPropagation();
};
evt.preventDefault();
evt.stopPropagation();
};
// $('#directory-picker-button').click(() => {
@@ -168,71 +168,71 @@
$('#add_more_images').click(() => {
add_input_form()
});
$('#add_more_answers').click(() => {
add_answers_input_form()
});
$('#add_more_images').click(() => {
add_input_form()
});
$('#add_more_answers').click(() => {
add_answers_input_form()
});
$("input[type=file]").on('change', input_change);
$("input[type=file]").on('change', input_change);
$("#rapid-form").on("submit", (evt) => {
submit = true;
if (!$normal) {
if ($('#id_answers-TOTAL_FORMS').val() == "0") {
$("#rapid-form").on("submit", (evt) => {
submit = true;
if (!$normal) {
if ($('#id_answers-TOTAL_FORMS').val() == "0") {
submit = false;
add_answers_input_form();
toastr.error(`Question that are not normal require an answer`);
evt.preventDefault();
}
}
if (!$("#id_examination_to option").length) {
submit = false;
add_answers_input_form();
toastr.error(`Question that are not normal require an answer`);
toastr.error("Please add examination type")
evt.preventDefault();
}
}
if (submit) {
toastr.info(`Submiting question... please wait`, '', {
"closeButton": false,
"debug": false,
"newestOnTop": false,
"progressBar": true,
"positionClass": "toast-top-full-width",
"preventDuplicates": false,
"onclick": null,
"showDuration": "300",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
});
}
})
});
function extractDicomDetails(byteArray) {
if (!$("#id_examination_to option").length) {
submit = false;
toastr.error("Please add examination type")
evt.preventDefault();
}
if (submit) {
toastr.info(`Submiting question... please wait`, '', {
"closeButton": false,
"debug": false,
"newestOnTop": false,
"progressBar": true,
"positionClass": "toast-top-full-width",
"preventDuplicates": false,
"onclick": null,
"showDuration": "300",
"hideDuration": "1000",
"timeOut": "5000",
"extendedTimeOut": "1000",
"showEasing": "swing",
"hideEasing": "linear",
"showMethod": "fadeIn",
"hideMethod": "fadeOut"
});
}
})
});
function extractDicomDetails(byteArray) {
if (!$("#id_examination_to option").length) {
// 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 {
try {
// parse byteArray into a DataSet object using the parseDicom library
var dataSet = dicomParser.parseDicom(byteArray);
var dataSet = dicomParser.parseDicom(byteArray);
// dataSet contains the parsed elements. Each element is available via a property
// in the dataSet.elements object. The property name is based on the elements group
@@ -242,98 +242,97 @@
// To access the data for an element, we need to know its type and its tag.
// We will get the sopInstanceUid from the file which is a string and
// has the tag (0020,000D)
var study_description = dataSet.string('x00081030').toLowerCase();
console.log("STUDY", study_description);
var study_description = dataSet.string('x00081030').toLowerCase();
console.log("STUDY", study_description);
// try to match with a study description (if not already selected)
if ($(`#id_examination_to option`).length < 1) {
option = $(`#id_examination_from option[title*='${study_description}' i]`);
if ($(`#id_examination_to option`).length < 1) {
option = $(`#id_examination_from option[title*='${study_description}' i]`);
if (option.length) {
option.appendTo($("#id_examination_to"));
toastr.success(`Examination set to ${option.attr('title')} from dicom data`);
} else {
toastr.warning(
`Unable to set examination ${study_description} from dicom data (it needs creating)`);
if (option.length) {
option.appendTo($("#id_examination_to"));
toastr.success(`Examination set to ${option.attr('title')} from dicom data`);
} else {
toastr.warning(
`Unable to set examination ${study_description} from dicom data (it needs creating)`);
}
}
} catch (err) {
console.log(err);
}
}
} catch (err) {
console.log(err);
}
}
}
</script>
</script>
{{ form.media }}
{{ form.media }}
{% endblock %}
{% block content %}
{% if object %}
{% include "shorts/question_link_header.html" %}
{% endif %}
<h2>Submit Shorts Question</h2>
<h3>Instructions</h3>
<p>
Use this form to create a new short style question/case. Multiple images can be added to a question.
If the feedback image box is checked they will not be displayed when taking the question.
</p>
<p>Once you have created the question with this form you can add relevant findings.
</p>
{% if object %}
{% include "shorts/question_link_header.html" %}
{% endif %}
<h2>Submit Shorts Question</h2>
<h3>Instructions</h3>
<p>
Use this form to create a new short style question/case. Multiple images can be added to a question.
If the feedback image box is checked they will not be displayed when taking the question.
</p>
<p>Once you have created the question with this form you can add relevant findings.
</p>
<!-- <div>
To monitor a directory select it here.<br />
<button id="directory-picker-button">Pick a directory</button>
<span id="directory-picker-display">No directory monitored</span>
</div> -->
<form action="" method="post" enctype="multipart/form-data" id="rapid-form">
<form action="" method="post" enctype="multipart/form-data" id="rapid-form">
{% comment %} {% csrf_token %} {% endcomment %}
<a href="/rapids/examination/create" id="add_examination" class="add-popup"
onclick="return showAddPopup(this);"><img src="{% static 'img/icon-addlink.svg' %}"></a>
<a href="/rapids/examination/create" id="add_examination" class="add-popup"
onclick="return showAddPopup(this);"><img src="{% static 'img/icon-addlink.svg' %}"></a>
{% crispy form form.helper %}
{% crispy form form.helper %}
<h3>Images:</h3>
<div id="drop-container" class="drop-target">Drop images here (or use the buttons below)<div
<h3>Images:</h3>
<div id="drop-container" class="drop-target">Drop images here (or use the buttons below)<div
id="feedback-drop-target">Feedback image?<br />drop those here</div>
<div id="drop-filenames"></div>
</div>
<input type="button" value="Add More Images" id="add_more_images">
<div id="image_form_set">
{% for form in image_formset %}
<ul class="no-error image-formset">
{{form.non_field_errors}}
{{form.errors}}
{{ form.as_ul }}
<div id="drop-filenames"></div>
</div>
<input type="button" value="Add More Images" id="add_more_images">
<div id="image_form_set">
{% for form in image_formset %}
<ul class="no-error image-formset">
{{form.non_field_errors}}
{{form.errors}}
{{ form.as_ul }}
</ul>
{% endfor %}
</div>
{{ image_formset.management_form }}
<input type="submit" class="submit-button" value="Submit" name="submit">
</form>
<div id="empty_form" style="display:none">
<ul class='no_error image-formset'>
{{ image_formset.empty_form.as_ul }}
</ul>
</div>
<div id="answer_empty_form" style="display:none">
<ul class='no_error answer-formset'>
{{ answer_formset.empty_form.as_ul }}
</ul>
{% endfor %}
</div>
{{ image_formset.management_form }}
<input type="submit" class="submit-button" value="Submit" name="submit">
</form>
<div id="empty_form" style="display:none">
<ul class='no_error image-formset'>
{{ image_formset.empty_form.as_ul }}
</ul>
</div>
<div id="answer_empty_form" style="display:none">
<ul class='no_error answer-formset'>
{{ answer_formset.empty_form.as_ul }}
</ul>
</div>
<div id="single-dicom-viewer" class="rapid-dicom-viewer" data-images="" data-annotations='' style="display:none"></div>
<div id="single-dicom-viewer" class="rapid-dicom-viewer" data-images="" data-annotations='' style="display:none"></div>
{% endblock %}
{% block css %}
<style>
.add-popup {
float: left;
}
</style>
<style>
.add-popup {
float: left;
}
</style>
{% endblock css %}