about summary refs log tree commit diff
path: root/uploader/static
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2024-07-25 11:07:33 -0500
committerFrederick Muriuki Muriithi2024-07-25 14:34:09 -0500
commit754e8f214b940e05298cb360ed829f5c685d55a5 (patch)
tree62c2c5b601746621f0949b38937ad232f006dee2 /uploader/static
parentde9e1b9fe37928b864bea28b408de6c14d04526b (diff)
downloadgn-uploader-754e8f214b940e05298cb360ed829f5c685d55a5.tar.gz
Rename module: qc_app --> uploader
Diffstat (limited to 'uploader/static')
-rw-r--r--uploader/static/css/custom-bootstrap.css23
-rw-r--r--uploader/static/css/styles.css7
-rw-r--r--uploader/static/css/two-column-with-separator.css27
-rw-r--r--uploader/static/images/CITGLogo.pngbin0 -> 11962 bytes
-rw-r--r--uploader/static/js/select_platform.js70
-rw-r--r--uploader/static/js/upload_progress.js97
-rw-r--r--uploader/static/js/upload_samples.js132
-rw-r--r--uploader/static/js/utils.js10
8 files changed, 366 insertions, 0 deletions
diff --git a/uploader/static/css/custom-bootstrap.css b/uploader/static/css/custom-bootstrap.css
new file mode 100644
index 0000000..67f1199
--- /dev/null
+++ b/uploader/static/css/custom-bootstrap.css
@@ -0,0 +1,23 @@
+/** Customize some bootstrap selectors **/
+.btn {
+    text-transform: capitalize;
+}
+
+.navbar-inverse {
+    background-color: #336699;
+    border-color: #080808;
+    color: #FFFFFF;
+    background-image: none;
+}
+
+.navbar-inverse .navbar-nav>li>a {
+    color: #FFFFFF;
+}
+
+.navbar-nav > li > a {
+    padding: 5px;
+}
+
+.navbar {
+    min-height: 30px;
+}
diff --git a/uploader/static/css/styles.css b/uploader/static/css/styles.css
new file mode 100644
index 0000000..a88c229
--- /dev/null
+++ b/uploader/static/css/styles.css
@@ -0,0 +1,7 @@
+.heading {
+    text-transform: capitalize;
+}
+
+label {
+    text-transform: capitalize;
+}
diff --git a/uploader/static/css/two-column-with-separator.css b/uploader/static/css/two-column-with-separator.css
new file mode 100644
index 0000000..b6efd46
--- /dev/null
+++ b/uploader/static/css/two-column-with-separator.css
@@ -0,0 +1,27 @@
+.two-column-with-separator {
+    display: grid;
+    grid-template-columns: 9fr 1fr 9fr;
+}
+
+.two-col-sep-col1 {
+    grid-column: 1 / 2;
+}
+
+.two-col-sep-separator {
+    grid-column: 2 / 3;
+    text-align: center;
+    color: #FE3535;
+    font-weight: bolder;
+}
+
+.two-col-sep-col2 {
+    grid-column: 3 / 4;
+}
+
+.two-col-sep-col1, .two-col-sep-col2 {
+    border-style: solid;
+    border-color: #FE3535;
+    border-width: 1px;
+    border-radius: 2em;
+    padding: 2em 3em 2em 3em;
+}
diff --git a/uploader/static/images/CITGLogo.png b/uploader/static/images/CITGLogo.png
new file mode 100644
index 0000000..ae99fed
--- /dev/null
+++ b/uploader/static/images/CITGLogo.png
Binary files differdiff --git a/uploader/static/js/select_platform.js b/uploader/static/js/select_platform.js
new file mode 100644
index 0000000..4fdd865
--- /dev/null
+++ b/uploader/static/js/select_platform.js
@@ -0,0 +1,70 @@
+function radio_column(chip) {
+    col = document.createElement("td");
+    radio = document.createElement("input");
+    radio.setAttribute("type", "radio");
+    radio.setAttribute("name", "genechipid");
+    radio.setAttribute("value", chip["GeneChipId"]);
+    radio.setAttribute("required", "required");
+    col.appendChild(radio);
+    return col;
+}
+
+function setup_genechips(genechip_data) {
+    columns = ["GeneChipId", "GeneChipName"]
+    submit_button = document.querySelector(
+	"#select-platform-form button[type='submit']");
+    elt = document.getElementById(
+	"genechips-table").getElementsByTagName("tbody")[0];
+    remove_children(elt);
+    if((genechip_data === undefined) || genechip_data.length === 0) {
+	row = document.createElement("tr");
+	col = document.createElement("td");
+	col.setAttribute("colspan", "3");
+	text = document.createTextNode("No chips found for selected species");
+	col.appendChild(text);
+	row.appendChild(col);
+	elt.appendChild(row);
+	submit_button.setAttribute("disabled", true);
+	return false;
+    }
+
+    submit_button.removeAttribute("disabled")
+    genechip_data.forEach(chip => {
+	row = document.createElement("tr");
+	row.appendChild(radio_column(chip));
+	columns.forEach(column => {
+	    col = document.createElement("td");
+	    content = document.createTextNode(chip[column]);
+	    col.appendChild(content);
+	    row.appendChild(col);
+	});
+	elt.appendChild(row);
+    });
+}
+
+function genechips() {
+    return JSON.parse(
+	document.getElementById("select-platform-form").getAttribute(
+	    "data-genechips"));
+}
+
+function update_genechips(event) {
+    genec = genechips();
+
+    species_elt = document.getElementById("species");
+
+    if(event.target == species_elt) {
+	setup_genechips(genec[species_elt.value.toLowerCase()]);
+    }
+}
+
+function select_row_radio(row) {
+    radio = row.getElementsByTagName(
+	"td")[0].getElementsByTagName(
+	    "input")[0];
+    if(radio === undefined) {
+	return false;
+    }
+    radio.setAttribute("checked", "checked");
+    return true;
+}
diff --git a/uploader/static/js/upload_progress.js b/uploader/static/js/upload_progress.js
new file mode 100644
index 0000000..9638b36
--- /dev/null
+++ b/uploader/static/js/upload_progress.js
@@ -0,0 +1,97 @@
+function make_processing_indicator(elt) {
+    var count = 0;
+    return function() {
+	var message = "Finalising upload and saving file: "
+	if(count > 5) {
+	    count = 1;
+	}
+	for(i = 0; i < count; i++) {
+	    message = message + ".";
+	}
+	elt.innerHTML = message
+	count = count + 1
+    };
+}
+
+function make_progress_updater(file, indicator_elt) {
+    var progress_bar = indicator_elt.querySelector("#progress-bar");
+    var progress_text = indicator_elt.querySelector("#progress-text");
+    var extra_text = indicator_elt.querySelector("#progress-extra-text");
+    return function(event) {
+	if(event.loaded <= file.size) {
+	    var percent = Math.round((event.loaded / file.size) * 100);
+	    progress_bar.value = percent
+	    progress_text.innerHTML = "Uploading: " + percent + "%";
+	    extra_text.setAttribute("class", "hidden")
+	}
+
+	if(event.loaded == event.total) {
+	    progress_bar.value = 100;
+	    progress_text.innerHTML = "Uploaded: 100%";
+	    extra_text.setAttribute("class", null);
+	    intv = setInterval(make_processing_indicator(extra_text), 400);
+	    setTimeout(function() {clearTimeout(intv);}, 20000);
+	}
+    };
+}
+
+function setup_cancel_upload(request, indicator_elt) {
+    document.getElementById("btn-cancel-upload").addEventListener(
+	"click", function(event) {
+	    event.preventDefault();
+	    request.abort();
+	});
+}
+
+function setup_request(file, progress_indicator_elt) {
+    var request = new XMLHttpRequest();
+    var updater = make_progress_updater(file, progress_indicator_elt);
+    request.upload.addEventListener("progress", updater);
+    request.onload = function(event) {
+	document.location.assign(request.responseURL);
+    };
+    setup_cancel_upload(request, progress_indicator_elt)
+    return request;
+}
+
+function selected_filetype(radios) {
+    for(idx = 0; idx < radios.length; idx++) {
+	if(radios[idx].checked) {
+	    return radios[idx].value;
+	}
+    }
+}
+
+function make_data_uploader(setup_formdata) {
+    return function(event) {
+	event.preventDefault();
+
+	var pindicator = document.getElementById("upload-progress-indicator");
+
+	var form = event.target;
+	var the_file = form.querySelector("input[type='file']").files[0];
+	if(the_file === undefined) {
+	    form.querySelector("input[type='file']").parentElement.setAttribute(
+		"class", "invalid-input");
+	    error_elt = form.querySelector("#no-file-error");
+	    if(error_elt !== undefined) {
+		error_elt.setAttribute("style", "display: block;");
+	    }
+	    return false;
+	}
+	var formdata = setup_formdata(form);
+
+	document.getElementById("progress-filename").innerHTML = the_file.name;
+	var request = setup_request(the_file, pindicator);
+	request.open(form.getAttribute("method"), form.getAttribute("action"));
+	request.send(formdata);
+	return false;
+    }
+}
+
+
+function setup_upload_handlers(formid, datauploader) {
+    console.info("Setting up the upload handlers.")
+    upload_form = document.getElementById(formid);
+    upload_form.addEventListener("submit", datauploader);
+}
diff --git a/uploader/static/js/upload_samples.js b/uploader/static/js/upload_samples.js
new file mode 100644
index 0000000..aed536f
--- /dev/null
+++ b/uploader/static/js/upload_samples.js
@@ -0,0 +1,132 @@
+/*
+ * Read the file content and set the `data-preview-content` attribute on the
+ * file element
+ */
+function read_first_n_lines(event,
+			    fileelement,
+			    numlines,
+			    firstlineheading = true) {
+    var thefile = fileelement.files[0];
+    var reader = new FileReader();
+    reader.addEventListener("load", (event) => {
+	var filecontent = event.target.result.split(
+	    "\n").slice(
+		0, (numlines + (firstlineheading ? 1 : 0))).map(
+		    (line) => {return line.trim("\r");});
+	fileelement.setAttribute(
+	    "data-preview-content", JSON.stringify(filecontent));
+	display_preview(event);
+    })
+    reader.readAsText(thefile);
+}
+
+function remove_rows(preview_table) {
+    var table_body = preview_table.getElementsByTagName("tbody")[0];
+    while(table_body.children.length > 0) {
+	table_body.removeChild(table_body.children.item(0));
+    }
+}
+
+/*
+ * Display error row
+ */
+function display_error_row(preview_table, error_message) {
+    remove_rows(preview_table);
+    row = document.createElement("tr");
+    cell = document.createElement("td");
+    cell.setAttribute("colspan", 4);
+    cell.innerHTML = error_message;
+    row.appendChild(cell);
+    preview_table.getElementsByTagName("tbody")[0].appendChild(row);
+}
+
+function strip(str, chars) {
+    var end = str.length;
+    var start = 0
+    for(var j = str.length; j > 0; j--) {
+	if(!chars.includes(str[j - 1])) {
+	    break;
+	}
+	end = end - 1;
+    }
+    for(var i = 0; i < end; i++) {
+	if(!chars.includes(str[i])) {
+	    break;
+	}
+	start = start + 1;
+    }
+    return str.slice(start, end);
+}
+
+function process_preview_data(preview_data, separator, delimiter) {
+    return preview_data.map((line) => {
+	return line.split(separator).map((field) => {
+	    return strip(field, delimiter);
+	});
+    });
+}
+
+function render_preview(preview_table, preview_data) {
+    remove_rows(preview_table);
+    var table_body = preview_table.getElementsByTagName("tbody")[0];
+    preview_data.forEach((line) => {
+	var row = document.createElement("tr");
+	line.forEach((field) => {
+	    var cell = document.createElement("td");
+	    cell.innerHTML = field;
+	    row.appendChild(cell);
+	});
+	table_body.appendChild(row);
+    });
+}
+
+/*
+ * Display a preview of the data, relying on the user's selection.
+ */
+function display_preview(event) {
+    var data_preview_table = document.getElementById("tbl:samples-preview");
+    remove_rows(data_preview_table);
+
+    var separator = document.getElementById("select:separator").value;
+    if(separator === "other") {
+	separator = document.getElementById("txt:separator").value;
+    }
+    if(separator == "") {
+	display_error_row(data_preview_table, "Please provide a separator.");
+	return false;
+    }
+
+    var delimiter = document.getElementById("txt:delimiter").value;
+
+    var firstlineheading = document.getElementById("chk:heading").checked;
+
+    var fileelement = document.getElementById("file:samples");
+    var preview_data = JSON.parse(
+	fileelement.getAttribute("data-preview-content") || "[]");
+    if(preview_data.length == 0) {
+	display_error_row(
+	    data_preview_table,
+	    "No file data to preview. Check that file is provided.");
+    }
+
+    render_preview(data_preview_table, process_preview_data(
+	preview_data.slice(0 + (firstlineheading ? 1 : 0)),
+	separator,
+	delimiter));
+}
+
+document.getElementById("chk:heading").addEventListener(
+    "change", display_preview);
+document.getElementById("select:separator").addEventListener(
+    "change", display_preview);
+document.getElementById("txt:separator").addEventListener(
+    "keyup", display_preview);
+document.getElementById("txt:delimiter").addEventListener(
+    "keyup", display_preview);
+document.getElementById("file:samples").addEventListener(
+    "change", (event) => {
+	read_first_n_lines(event,
+			   document.getElementById("file:samples"),
+			   30,
+			   document.getElementById("chk:heading").checked);
+    });
diff --git a/uploader/static/js/utils.js b/uploader/static/js/utils.js
new file mode 100644
index 0000000..045dd47
--- /dev/null
+++ b/uploader/static/js/utils.js
@@ -0,0 +1,10 @@
+function remove_children(element) {
+    Array.from(element.children).forEach(child => {
+	element.removeChild(child);
+    });
+}
+
+function trigger_change_event(element) {
+    evt = new Event("change");
+    element.dispatchEvent(evt);
+}