aboutsummaryrefslogtreecommitdiff
path: root/uploader/static
diff options
context:
space:
mode:
Diffstat (limited to 'uploader/static')
-rw-r--r--uploader/static/css/styles.css212
-rw-r--r--uploader/static/js/datatables.js69
-rw-r--r--uploader/static/js/debug.js40
-rw-r--r--uploader/static/js/files.js4
-rw-r--r--uploader/static/js/misc.js6
-rw-r--r--uploader/static/js/populations.js36
-rw-r--r--uploader/static/js/pubmed.js113
-rw-r--r--uploader/static/js/species.js34
-rw-r--r--uploader/static/js/utils.js27
9 files changed, 440 insertions, 101 deletions
diff --git a/uploader/static/css/styles.css b/uploader/static/css/styles.css
index f482c1b..df50dec 100644
--- a/uploader/static/css/styles.css
+++ b/uploader/static/css/styles.css
@@ -1,161 +1,187 @@
+* {
+ box-sizing: border-box;
+}
+
body {
margin: 0.7em;
- box-sizing: border-box;
display: grid;
- grid-template-columns: 1fr 6fr;
- grid-template-rows: 5em 100%;
+ grid-template-columns: 2fr 8fr;
grid-gap: 20px;
- font-family: Georgia, Garamond, serif;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-style: normal;
+ font-size: 20px;
}
#header {
- grid-column: 1/3;
- width: 100%;
- /* background: cyan; */
- padding-top: 0.5em;
- border-radius: 0.5em;
+ /* Place it in the parent element */
+ grid-column-start: 1;
+ grid-column-end: 3;
+
+ /* Define layout for the children elements */
+ display: grid;
+ grid-template-columns: 8fr 2fr;
+ /* Content styling */
background-color: #336699;
- border-color: #080808;
color: #FFFFFF;
- background-image: none;
+ border-radius: 3px;
+ min-height: 30px;
}
-#header .header {
- font-size: 2em;
- display: inline-block;
- text-align: start;
-}
+#header #header-text {
+ /* Place it in the parent element */
+ grid-column-start: 1;
+ grid-column-end: 2;
-#header .header-nav {
- display: inline-block;
- color: #FFFFFF;
+ /* Content styling */
+ padding-left: 1em;
}
-#header .header-nav li {
- border-width: 1px;
- border-color: #FFFFFF;
- vertical-align: middle;
- margin: 0.2em;
- border-style: solid;
- border-width: 2px;
- border-radius: 0.5em;
- text-align: center;
+#header #header-nav {
+ /* Place it in the parent element */
+ grid-column-start: 2;
+ grid-column-end: 3;
}
-#header .header-nav a {
+#header #header-nav .nav li a {
+ /* Content styling */
color: #FFFFFF;
- text-decoration: none;
+ background: #4477AA;
+ border: solid 5px #336699;
+ border-radius: 5px;
+ font-size: 0.7em;
+ text-align: center;
+ padding: 1px 7px;
}
#nav-sidebar {
- grid-column: 1/2;
- /* background: #e5e5ff; */
- padding-top: 0.5em;
- border-radius: 0.5em;
- font-size: 1.2em;
+ /* Place it in the parent element */
+ grid-column-start: 1;
+ grid-column-end: 2;
}
-#main {
- grid-column: 2/3;
- width: 100%;
- /* background: gray; */
+#nav-sidebar .nav li a:hover {
border-radius: 0.5em;
}
-.pagetitle {
- padding-top: 0.5em;
- /* background: pink; */
+#nav-sidebar .nav .activemenu {
+ border-style: solid;
border-radius: 0.5em;
- /* background-color: #6699CC; */
- /* background-color: #77AADD; */
- background-color: #88BBEE;
+ border-color: #AAAAAA;
+ background-color: #EFEFEF;
}
-.pagetitle h1 {
- text-align: start;
- text-transform: capitalize;
- padding-left: 0.25em;
-}
+#main {
+ /* Place it in the parent element */
+ grid-column-start: 2;
+ grid-column-end: 3;
-.pagetitle .breadcrumb {
- background: none;
+ /* Define layout for the children elements */
+ display: grid;
+ grid-template-columns: 1fr;
+ grid-template-rows: 4em 100%;
+ grid-gap: 1em;
}
-.pagetitle .breadcrumb .active a {
- color: #333333;
+#main #pagetitle {
+ /* Place it in the parent element */
+ grid-column-start: 1;
+ grid-column-end: 3;
+
+ /* Content-styling */
+ border-radius: 3px;
+ background-color: #88BBEE;
}
-.pagetitle .breadcrumb a {
- color: #666666;
+#main #pagetitle .title {
+ font-size: 1.4em;
+ text-transform: capitalize;
+ padding-left: 0.5em;
}
-.main-content {
- font-size: 1.275em;
+@media screen and (max-width: 20in) {
+ #main #all-content {
+ /* Place it in the parent element */
+ grid-column-start: 1;
+ grid-column-end: 3;
+
+ /* Define layout for the children elements */
+ max-width: 80%;
+ }
+
+ #sidebar-content {
+ display: none;
+ }
}
-.breadcrumb {
- text-transform: capitalize;
+@media screen and (min-width: 20.1in) {
+ #main #all-content {
+ /* Place it in the parent element */
+ grid-column-start: 1;
+ grid-column-end: 3;
+
+ /* Define layout for the children elements */
+ display: grid;
+ grid-template-columns: 7fr 3fr;
+ grid-gap: 1.5em;
+ }
}
-dd {
- margin-left: 3em;
- font-size: 0.88em;
- padding-bottom: 1em;
+#main #all-content .row {
+ margin: 0 2px;
}
-input[type="submit"], .btn {
- text-transform: capitalize;
+#main #all-content #main-content {
+ background: #FFFFFF;
+ max-width: 950px;
}
-.card {
- margin-top: 0.3em;
- border-width: 1px;
- border-style: solid;
- border-radius: 0.3em;
- border-color: #AAAAAA;
- padding: 0.5em;
+#pagetitle .breadcrumb {
+ background: none;
+ text-transform: capitalize;
+ font-size: 0.75em;
}
-.activemenu {
- border-style: solid;
- border-radius: 0.5em;
- border-color: #AAAAAA;
- background-color: #EFEFEF;
+#pagetitle .breadcrumb .active a {
+ color: #333333;
}
-.danger {
- color: #A94442;
- border-color: #DCA7A7;
- background-color: #F2DEDE;
+#pagetitle .breadcrumb a {
+ color: #666666;
}
.heading {
border-bottom: solid #EEBB88;
+ text-transform: capitalize;
}
.subheading {
padding: 1em 0 0.1em 0.5em;
border-bottom: solid #88BBEE;
+ text-transform: capitalize;
+}
+
+input[type="search"] {
+ border-radius: 5px;
}
-form {
- margin-top: 0.3em;
- background: #E5E5FF;
- padding: 0.5em;
- border-radius:0.5em;
+.btn {
+ text-transform: Capitalize;
}
-form .form-control {
- background-color: #EAEAFF;
+table.dataTable thead th, table.dataTable tfoot th{
+ border-right: 1px solid white;
+ color: white;
+ background-color: #369 !important;
}
-.sidebar-content .card .card-title {
- font-size: 1.5em;
+table.dataTable tbody tr.selected td {
+ background-color: #ffee99 !important;
}
-.sidebar-content .card-text table tbody td:nth-child(1) {
- font-weight: bolder;
+.form-group {
+ margin-bottom: 2em;
+ padding-bottom: 0.2em;
+ border-bottom: solid gray 1px;
}
diff --git a/uploader/static/js/datatables.js b/uploader/static/js/datatables.js
new file mode 100644
index 0000000..82fd696
--- /dev/null
+++ b/uploader/static/js/datatables.js
@@ -0,0 +1,69 @@
+/** Handlers for events in datatables **/
+
+var addTableLength = (menuList, lengthToAdd, dataLength) => {
+ if(dataLength >= lengthToAdd) {
+ newList = structuredClone(menuList);//menuList.slice(0, menuList.length); // shallow copy
+ newList.push(lengthToAdd);
+ return newList;
+ }
+ return menuList;
+};
+
+var defaultLengthMenu = (data) => {
+ menuList = []
+ var lengths = [10, 25, 50, 100, 1000, data.length];
+ lengths.forEach((len) => {
+ menuList = addTableLength(menuList, len, data.length);
+ });
+ return menuList;
+};
+
+var buildDataTable = (tableId, data = [], columns = [], userSettings = {}) => {
+ var defaultSettings = {
+ responsive: true,
+ layout: {
+ topStart: null,
+ topEnd: null,
+ bottomStart: null,
+ bottomEnd: null,
+ },
+ select: true,
+ lengthMenu: defaultLengthMenu(data),
+ language: {
+ processing: "Processing… Please wait.",
+ loadingRecords: "Loading table data… Please wait.",
+ lengthMenu: "",
+ info: ""
+ },
+ data: data,
+ columns: columns,
+ drawCallback: (settings) => {
+ $(this[0]).find("tbody tr").each((idx, row) => {
+ var arow = $(row);
+ var checkboxOrRadio = arow.find(".chk-row-select");
+ if (checkboxOrRadio) {
+ if (arow.hasClass("selected")) {
+ checkboxOrRadio.prop("checked", true);
+ } else {
+ checkboxOrRadio.prop("checked", false);
+ }
+ }
+ });
+ }
+ }
+ var theDataTable = $(tableId).DataTable({
+ ...defaultSettings,
+ ...userSettings
+ });
+ theDataTable.on("select", (event, datatable, type, cell, originalEvent) => {
+ datatable.rows({selected: true}).nodes().each((node, index) => {
+ $(node).find(".chk-row-select").prop("checked", true)
+ });
+ });
+ theDataTable.on("deselect", (event, datatable, type, cell, originalEvent) => {
+ datatable.rows({selected: false}).nodes().each((node, index) => {
+ $(node).find(".chk-row-select").prop("checked", false)
+ });
+ });
+ return theDataTable;
+};
diff --git a/uploader/static/js/debug.js b/uploader/static/js/debug.js
new file mode 100644
index 0000000..eb01209
--- /dev/null
+++ b/uploader/static/js/debug.js
@@ -0,0 +1,40 @@
+/**
+ * The entire purpose of this function is for use to debug values inline
+ * without changing the flow of the code too much.
+ *
+ * This **MUST** be a non-arrow function to allow access to the `arguments`
+ * object.
+ *
+ * This function expects at least one argument.
+ *
+ * If more than one argument is provided, then:
+ * a) the last argument is considered the value, and will be returned
+ * b) all other arguments will be converted to string and output
+ *
+ * If only one argument is provided, it is considered the value, and will be
+ * returned.
+ *
+ * Zero arguments is an error condition.
+ **/
+function __pk__(val) {
+ /* Handle zero arguments */
+ if (arguments.length < 1) {
+ throw new Error("Invalid arguments: Expected at least one argument.");
+ }
+
+ msg = "/********** DEBUG **********/";
+ if (arguments.length > 1) {
+ msg = Array.from(
+ arguments
+ ).slice(
+ 0,
+ arguments.length - 1
+ ).map((val) => {
+ return String(val);
+ }).join("; ")
+ }
+
+ value = arguments[arguments.length - 1];
+ console.debug("/********** " + msg + " **********/", value);
+ return value;
+}
diff --git a/uploader/static/js/files.js b/uploader/static/js/files.js
index 9d6bca1..0bde6f7 100644
--- a/uploader/static/js/files.js
+++ b/uploader/static/js/files.js
@@ -84,8 +84,8 @@ var errorHandler = makeResumableHandler("error");
var markResumableDragAndDropElement = (resumable, fileinput, droparea, browsebutton) => {
if(resumable.support) {
//Hide file input element and display drag&drop UI
- add_class(fileinput, "hidden");
- remove_class(droparea, "hidden");
+ add_class(fileinput, "visually-hidden");
+ remove_class(droparea, "visually-hidden");
// Define UI elements for browse and drag&drop
resumable.assignDrop(droparea);
diff --git a/uploader/static/js/misc.js b/uploader/static/js/misc.js
deleted file mode 100644
index cf7b39e..0000000
--- a/uploader/static/js/misc.js
+++ /dev/null
@@ -1,6 +0,0 @@
-"Miscellaneous functions and event-handlers"
-
-$(".not-implemented").click((event) => {
- event.preventDefault();
- alert("This feature is not implemented yet. Please bear with us.");
-});
diff --git a/uploader/static/js/populations.js b/uploader/static/js/populations.js
new file mode 100644
index 0000000..89ededa
--- /dev/null
+++ b/uploader/static/js/populations.js
@@ -0,0 +1,36 @@
+$(() => {
+ var populationsDataTable = buildDataTable(
+ "#tbl-select-population",
+ JSON.parse(
+ $("#tbl-select-population").attr("data-populations-list")),
+ [
+ {
+ data: (apopulation) => {
+ return `<input type="radio" name="population_id"`
+ + `id="rdo_population_id_${apopulation.InbredSetId}" `
+ + `value="${apopulation.InbredSetId}" `
+ + `class="chk-row-select">`;
+ }
+ },
+ {
+ searchable: true,
+ data: (apopulation) => {
+ return `${apopulation.FullName} (${apopulation.InbredSetName})`;
+ }
+ }
+ ],
+ {
+ select: "single",
+ paging: true,
+ scrollY: 700,
+ deferRender: true,
+ scroller: true,
+ scrollCollapse: true,
+ layout: {
+ topStart: "info",
+ topEnd: "search",
+ bottomStart: "pageLength",
+ bottomEnd: false
+ }
+ });
+});
diff --git a/uploader/static/js/pubmed.js b/uploader/static/js/pubmed.js
new file mode 100644
index 0000000..9afd4c3
--- /dev/null
+++ b/uploader/static/js/pubmed.js
@@ -0,0 +1,113 @@
+var extract_details = (pubmed_id, details) => {
+ var months = {
+ "jan": "January",
+ "feb": "February",
+ "mar": "March",
+ "apr": "April",
+ "may": "May",
+ "jun": "June",
+ "jul": "July",
+ "aug": "August",
+ "sep": "September",
+ "oct": "October",
+ "nov": "November",
+ "dec": "December"
+ };
+ var _date = details[pubmed_id].pubdate.split(" ");
+ return {
+ "authors": details[pubmed_id].authors.map((authobj) => {
+ return authobj.name;
+ }),
+ "title": details[pubmed_id].title,
+ "journal": details[pubmed_id].fulljournalname,
+ "volume": details[pubmed_id].volume,
+ "pages": details[pubmed_id].pages,
+ "month": _date.length > 1 ? months[_date[1].toLowerCase()] : "jan",
+ "year": _date[0],
+ };
+};
+
+var update_publication_details = (details) => {
+ Object.entries(details).forEach((entry) => {;
+ switch(entry[0]) {
+ case "authors":
+ $("#txt-publication-authors").val(entry[1].join(", "));
+ break;
+ case "month":
+ $("#select-publication-month")
+ .children("option")
+ .each((index, child) => {
+ console.debug(entry[1].toLowerCase());
+ child.selected = child.value == entry[1].toLowerCase();
+ });
+ default:
+ $("#txt-publication-" + entry[0]).val(entry[1]);
+ break;
+ }
+ });
+};
+
+var fetch_publication_abstract = (pubmed_id, pub_details) => {
+ $.ajax("https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi",
+ {
+ "method": "GET",
+ "data": {
+ "db": "pubmed",
+ "id": pubmed_id,
+ "rettype": "abstract",
+ "retmode": "xml"
+ },
+ "success": (data, textStatus, jqXHR) => {
+ update_publication_details({
+ ...pub_details,
+ ...{
+ "abstract": Array.from(data
+ .getElementsByTagName(
+ "Abstract")[0]
+ .children)
+ .map((elt) => {return elt.textContent.trim();})
+ .join("\r\n")
+ }});
+ },
+ "error": (jqXHR, textStatus, errorThrown) => {},
+ "complete": (jqXHR, textStatus) => {},
+ "dataType": "xml"
+ });
+};
+
+var fetch_publication_details = (pubmed_id, complete_thunks) => {
+ error_display = $("#search-pubmed-id-error");
+ error_display.text("");
+ add_class(error_display, "visually-hidden");
+ $.ajax("https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi",
+ {
+ "method": "GET",
+ "data": {"db": "pubmed", "id": pubmed_id, "format": "json"},
+ "success": (data, textStatus, jqXHR) => {
+ // process and update publication details
+ hasError = (
+ Object.hasOwn(data, "error") ||
+ Object.hasOwn(data.result[pubmed_id], "error"));
+ if(hasError) {
+ error_display.text(
+ "There was an error fetching a publication with " +
+ "the given PubMed ID! The error received " +
+ "was: '" + (
+ data.error ||
+ data.result[pubmed_id].error) +
+ "'. Please check ID you provided and try " +
+ "again.");
+ remove_class(error_display, "visually-hidden");
+ } else {
+ fetch_publication_abstract(
+ pubmed_id,
+ extract_details(pubmed_id, data.result));
+ }
+ },
+ "error": (jqXHR, textStatus, errorThrown) => {},
+ "complete": () => {
+ complete_thunks.forEach((thunk) => {thunk()});
+ },
+ "dataType": "json"
+ });
+};
diff --git a/uploader/static/js/species.js b/uploader/static/js/species.js
new file mode 100644
index 0000000..d42e081
--- /dev/null
+++ b/uploader/static/js/species.js
@@ -0,0 +1,34 @@
+$(() => {
+ var speciesDataTable = buildDataTable(
+ "#tbl-select-species",
+ JSON.parse(
+ $("#tbl-select-species").attr("data-species-list")),
+ [
+ {
+ data: (aspecies) => {
+ return `<input type="radio" name="species_id"`
+ + `id="rdo_species_id_${aspecies.SpeciesId}" `
+ + `value="${aspecies.SpeciesId}" class="chk-row-select">`;
+ }
+ },
+ {
+ data: (aspecies) => {
+ return `${aspecies.FullName} (${aspecies.SpeciesName})`;
+ }
+ }
+ ],
+ {
+ select: "single",
+ paging: true,
+ scrollY: 700,
+ deferRender: true,
+ scroller: true,
+ scrollCollapse: true,
+ layout: {
+ topStart: "info",
+ topEnd: "search",
+ bottomStart: "pageLength",
+ bottomEnd: false
+ }
+ });
+});
diff --git a/uploader/static/js/utils.js b/uploader/static/js/utils.js
index 045dd47..1b31661 100644
--- a/uploader/static/js/utils.js
+++ b/uploader/static/js/utils.js
@@ -8,3 +8,30 @@ function trigger_change_event(element) {
evt = new Event("change");
element.dispatchEvent(evt);
}
+
+
+var remove_class = (element, classvalue) => {
+ new_classes = (element.attr("class") || "").split(" ").map((val) => {
+ return val.trim();
+ }).filter((val) => {
+ return ((val !== classvalue) &&
+ (val !== ""))
+ }).join(" ");
+
+ if(new_classes === "") {
+ element.removeAttr("class");
+ } else {
+ element.attr("class", new_classes);
+ }
+};
+
+
+var add_class = (element, classvalue) => {
+ remove_class(element, classvalue);
+ element.attr("class", (element.attr("class") || "") + " " + classvalue);
+};
+
+$(".not-implemented").click((event) => {
+ event.preventDefault();
+ alert("This feature is not implemented yet. Please bear with us.");
+});