diff --git a/anatomy/static/js/anatomy.js b/anatomy/static/js/anatomy.js
index ede0d47d..0493c7c2 100644
--- a/anatomy/static/js/anatomy.js
+++ b/anatomy/static/js/anatomy.js
@@ -579,4 +579,5 @@ function delete_multiple(url, csrf_token) {
}
}
-window.delete_multiple = delete_multiple
\ No newline at end of file
+window.delete_multiple = delete_multiple
+
diff --git a/anatomy/static/js/upload_form_helpers.js b/anatomy/static/js/upload_form_helpers.js
new file mode 100644
index 00000000..8fff2006
--- /dev/null
+++ b/anatomy/static/js/upload_form_helpers.js
@@ -0,0 +1,373 @@
+ let active_file_inputs = new Set();
+
+ 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);
+ }
+
+ async function blobToBase64(blob) {
+ return new Promise((resolve, _) => {
+ const reader = new FileReader();
+ reader.onloadend = () => resolve(reader.result);
+ reader.readAsDataURL(blob);
+ });
+ }
+
+ function extendInputs(form_id, n) {
+ // Makes sure we have n inputs available
+ // returns available inputs
+ inputs = getUnusedInputs($(`#${form_id} 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($(`#${form_id} input[type=file][id^=id_images-]`));
+ }
+ return inputs;
+ }
+
+ function getCurrentFormFiles(form_id) {
+ inputs = $(`#${form_id} 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 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 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;
+ }
+ }
+
+ }
+
+
+ function ocr2(url, input) {
+ console.log("OCR", 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");
+
+ }
+ })
+
+ }
+
+ function input_change(evt) {
+ file = evt.target.files[0];
+ $(evt.target).removeClass("image-ident-warning");
+ $(evt.target).removeClass("image-ident-ok");
+
+ el = evt.target;
+
+ readFileAndProcess2(el);
+
+ }
+
+ 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('')
+ win.close();
+ }
+
+
+ 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);
+
+
+
+
+ $(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();
+
+ base = await blobToBase64(el.files[0]);
+ imageId = "base64://" + base.split(",")[1];
+ imageId2 = base;
+ const element = $(``).get(0)
+ $(el).parent().parent().prepend(element);
+
+
+ ocr2(url, el);
+ checkHash(hash, el);
+
+ if ($("#drop-filenames").length > 0) {
+ $("#drop-filenames").append(
+ `${n}: ${el.files[0].name}
`
+ )
+ }
+ } else {
+ imageId = `wadouri:${url}`;
+ imageId2 = imageId
+
+ const element = $(`