about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--wqflask/wqflask/oauth2/data.py18
-rw-r--r--wqflask/wqflask/static/new/javascript/auth/search.js167
-rw-r--r--wqflask/wqflask/static/new/javascript/auth/search_genotypes.js183
-rw-r--r--wqflask/wqflask/static/new/javascript/auth/search_mrna.js96
-rw-r--r--wqflask/wqflask/templates/oauth2/data-list-genotype.html2
-rw-r--r--wqflask/wqflask/templates/oauth2/data-list-mrna.html8
6 files changed, 299 insertions, 175 deletions
diff --git a/wqflask/wqflask/oauth2/data.py b/wqflask/wqflask/oauth2/data.py
index 6804dafa..2b4dfc75 100644
--- a/wqflask/wqflask/oauth2/data.py
+++ b/wqflask/wqflask/oauth2/data.py
@@ -22,7 +22,6 @@ def __render_template__(templatepath, **kwargs):
 def __search_mrna__(query, template, **kwargs):
     species_name = kwargs["species_name"]
     search_uri = urljoin(app.config["GN_SERVER_URL"], "oauth2/data/search")
-    print(f"SEARCHING FOR mrna")
     datasets = oauth2_get(
         "oauth2/data/search",
         json = {
@@ -96,6 +95,23 @@ def json_search_genotypes() -> Response:
             __handle_error__,
             lambda datasets: jsonify(datasets))
 
+@data.route("/mrna/search", methods=["POST"])
+def json_search_mrna() -> Response:
+    def __handle_error__(err):
+        error = process_error(err)
+        return jsonify(error), error["status_code"]
+
+    return oauth2_get(
+        "oauth2/data/search",
+        json = {
+            "query": request.json["query"],
+            "dataset_type": "mrna",
+            "species_name": request.json["species_name"],
+            "selected": __selected_datasets__()
+        }).either(
+            __handle_error__,
+            lambda datasets: jsonify(datasets))
+
 @data.route("/<string:species_name>/<string:dataset_type>/list",
             methods=["GET", "POST"])
 def list_data_by_species_and_dataset(
diff --git a/wqflask/wqflask/static/new/javascript/auth/search.js b/wqflask/wqflask/static/new/javascript/auth/search.js
new file mode 100644
index 00000000..5226000d
--- /dev/null
+++ b/wqflask/wqflask/static/new/javascript/auth/search.js
@@ -0,0 +1,167 @@
+class InvalidCSSIDSelector extends Error {
+    constructor(message) {
+	super(message);
+	this.name = "InvalidCSSIDSelector";
+    }
+}
+
+class InvalidDataAttributeName extends Error {
+    constructor(message) {
+	super(message);
+	this.name = "InvalidDataAttributeName";
+    }
+}
+
+/**
+ * CSSIDSelector: A CSS ID Selector
+ * @param {String} A CSS selector of the form '#...'
+ */
+class CSSIDSelector {
+    constructor(selector) {
+	if(!selector.startsWith("#")) {
+	    throw new InvalidCSSIDSelector(
+		"Expected the CSS selector to begin with a `#` character.");
+	}
+	let id_str = selector.slice(1, selector.length);
+	if(document.getElementById(id_str) == null) {
+	    throw new InvalidCSSIDSelector(
+		"Element with ID '" + id_str + "' does not exist.");
+	}
+	this.selector = selector;
+    }
+}
+
+/**
+ * TableDataSource: A type to represent a table's data source
+ * @param {String} A CSS selector for an ID
+ * @param {String} A `data-*` attribute name
+ */
+class TableDataSource {
+    constructor(table_id, data_attribute_name, checkbox_creation_function) {
+	this.table_id = new CSSIDSelector(table_id);
+	let data = document.querySelector(
+	    table_id).getAttribute(data_attribute_name);
+	if(data == null) {
+	    throw new InvalidDataAttributeName(
+		"data-* attribute '" + data_attribute_name + "' does not exist " +
+		    "for table with ID '" + table_id.slice(1, table_id.length) +
+		    "'.");
+	} else {
+	    this.data_attribute_name = data_attribute_name;
+	}
+	this.checkbox_creation_function = checkbox_creation_function;
+    }
+}
+
+/**
+ * Render the table
+ * @param {String} The selector for the table's ID
+ * @param {String} The name of the data-* attribute holding the table's data
+ * @param {Function} The function to call to generate the appropriate checkbox
+ */
+function render_table(table_data_source) {
+    table_id = table_data_source.table_id.selector;
+    data_attr_name = table_data_source.data_attribute_name;
+    $(table_id + " tbody tr").remove();
+    table_data = JSON.parse($(table_id).attr(data_attr_name));
+    if(table_data.length < 1) {
+	row = $("<tr>")
+	cell = $('<td colspan="100%" align="center">');
+	cell.append(
+	    $('<span class="glyphicon glyphicon-info-sign text-info">'));
+	cell.append("&nbsp;");
+	cell.append("No genotype datasets remaining.");
+	row.append(cell);
+	$(table_id + " tbody").append(row);
+    }
+    table_data.forEach(function(dataset) {
+	row = $("<tr>")
+	row.append(table_data_source.checkbox_creation_function(dataset));
+	row.append(table_cell(dataset.InbredSetName));
+	row.append(table_cell(dataset.dataset_name));
+	row.append(table_cell(dataset.dataset_fullname));
+	row.append(table_cell(dataset.dataset_shortname));
+	$(table_id + " tbody").append(row);
+    });
+}
+
+function remove_from_table_data(dataset, table_data_source) {
+    let table_id = table_data_source.table_id.selector;
+    let data_attr_name = table_data_source.data_attribute_name;
+    without_dataset = JSON.parse($(table_id).attr(data_attr_name)).filter(
+	function(dst) {
+	    return !(dst.SpeciesId == dataset.SpeciesId &&
+		     dst.InbredSetId == dataset.InbredSetId &&
+		     dst.GenoFreezeId == dataset.GenoFreezeId);
+	});
+    $(table_id).attr(data_attr_name, JSON.stringify(without_dataset));
+}
+
+function add_to_table_data(dataset, table_data_source) {
+    let table_id = table_data_source.table_id.selector;
+    let data_attr_name = table_data_source.data_attribute_name;
+    table_data = JSON.parse($(table_id).attr(data_attr_name));
+    if(!in_array(dataset, table_data)) {
+	table_data.push(dataset);
+    }
+    $(table_id).attr(data_attr_name, JSON.stringify(Array.from(table_data)));
+}
+
+/**
+ * Switch the dataset from search table to selection table and vice versa
+ * @param {Object} A genotype dataset
+ * @param {TableDataSource} The table to switch the dataset from
+ * @param {TableDataSource} The table to switch the dataset to
+ */
+function select_deselect_dataset(dataset, source, destination) {
+    dest_selector = destination.table_id.selector
+    dest_data = JSON.parse(
+	$(dest_selector).attr(destination.data_attribute_name));
+    add_to_table_data(dataset, destination); // Add to destination table
+    remove_from_table_data(dataset, source); // Remove from source table
+    /***** BEGIN: Re-render tables *****/
+    render_table(destination);
+    render_table(source);
+    /***** END: Re-render tables *****/
+}
+
+function debounce(func, delay=500) {
+    var timeout;
+    return function search(event) {
+	clearTimeout(timeout);
+	timeout = setTimeout(func, delay);
+    };
+}
+
+/**
+ * Build a checkbox: For internal use only
+ * @param {Genotype Dataset object} A genotype dataset object
+ * @param {String} A string to initialise the checkbox
+ */
+function __build_checkbox__(dataset, checkbox_str) {
+    cell = $("<td>");
+    check = $(checkbox_str);
+    check.val(JSON.stringify(dataset));
+    cell.append(check);
+    return cell;
+}
+
+function link_checkbox(dataset) {
+    return __build_checkbox__(
+	dataset,
+	'<input type="checkbox" class="checkbox checkbox-selected" ' +
+	    'name="selected" checked="checked">');
+}
+
+function search_checkbox(dataset) {
+    return __build_checkbox__(
+	dataset,
+	'<input type="checkbox" class="checkbox checkbox-search" ' +
+	    'name="search_datasets">');
+}
+
+function table_cell(value) {
+    cell = $("<td>");
+    cell.html(value);
+    return cell;
+}
diff --git a/wqflask/wqflask/static/new/javascript/auth/search_genotypes.js b/wqflask/wqflask/static/new/javascript/auth/search_genotypes.js
index 8d821f44..40f88121 100644
--- a/wqflask/wqflask/static/new/javascript/auth/search_genotypes.js
+++ b/wqflask/wqflask/static/new/javascript/auth/search_genotypes.js
@@ -1,66 +1,8 @@
 /**
- * Build a checkbox: For internal use only
- * @param {Genotype Dataset object} A genotype dataset object
- * @param {String} A string to initialise the checkbox
+ * Check whether `dataset` is in array of `datasets`.
+ * @param {GenotypeDataset} A genotype dataset.
+ * @param {Array} An array of genotype datasets.
  */
-function __build_checkbox__(dataset, checkbox_str) {
-    cell = $("<td>");
-    check = $(checkbox_str);
-    check.val(JSON.stringify(dataset));
-    cell.append(check);
-    return cell;
-}
-
-function link_checkbox(dataset) {
-    return __build_checkbox__(
-	dataset,
-	'<input type="checkbox" class="checkbox checkbox-selected" ' +
-	    'name="selected" checked="checked">');
-}
-
-function search_checkbox(dataset) {
-    return __build_checkbox__(
-	dataset,
-	'<input type="checkbox" class="checkbox checkbox-search" ' +
-	    'name="search_datasets">');
-}
-
-function table_cell(value) {
-    cell = $("<td>");
-    cell.html(value);
-    return cell;
-}
-
-/**
- * Render the table
- * @param {String} The selector for the table's ID
- * @param {String} The name of the data-* attribute holding the table's data
- * @param {Function} The function to call to generate the appropriate checkbox
- */
-function render_table(table_id, data_attr_name, checkbox_function) {
-    $(table_id + " tbody tr").remove();
-    table_data = JSON.parse($(table_id).attr(data_attr_name));
-    if(table_data.length < 1) {
-	row = $("<tr>")
-	cell = $('<td colspan="100%" align="center">');
-	cell.append(
-	    $('<span class="glyphicon glyphicon-info-sign text-info">'));
-	cell.append("&nbsp;");
-	cell.append("No genotype datasets remaining.");
-	row.append(cell);
-	$(table_id + " tbody").append(row);
-    }
-    table_data.forEach(function(dataset) {
-	row = $("<tr>")
-	row.append(checkbox_function(dataset));
-	row.append(table_cell(dataset.InbredSetName));
-	row.append(table_cell(dataset.dataset_name));
-	row.append(table_cell(dataset.dataset_fullname));
-	row.append(table_cell(dataset.dataset_shortname));
-	$(table_id + " tbody").append(row);
-    });
-}
-
 function in_array(dataset, datasets) {
     found = datasets.filter(function(dst) {
 	return (dst.SpeciesId == dataset.SpeciesId &&
@@ -70,28 +12,6 @@ function in_array(dataset, datasets) {
     return found.length > 0;
 }
 
-function remove_from_table_data(dataset, table_data_source) {
-    let table_id = table_data_source.table_id.selector;
-    let data_attr_name = table_data_source.data_attribute_name;
-    without_dataset = JSON.parse($(table_id).attr(data_attr_name)).filter(
-	function(dst) {
-	    return !(dst.SpeciesId == dataset.SpeciesId &&
-		     dst.InbredSetId == dataset.InbredSetId &&
-		     dst.GenoFreezeId == dataset.GenoFreezeId);
-	});
-    $(table_id).attr(data_attr_name, JSON.stringify(without_dataset));
-}
-
-function add_to_table_data(dataset, table_data_source) {
-    let table_id = table_data_source.table_id.selector;
-    let data_attr_name = table_data_source.data_attribute_name;
-    table_data = JSON.parse($(table_id).attr(data_attr_name));
-    if(!in_array(dataset, table_data)) {
-	table_data.push(dataset);
-    }
-    $(table_id).attr(data_attr_name, JSON.stringify(Array.from(table_data)));
-}
-
 function toggle_link_button() {
     num_groups = $("#frm-link-genotypes select option").length - 1;
     num_selected = JSON.parse(
@@ -103,96 +23,14 @@ function toggle_link_button() {
     }
 }
 
-class InvalidCSSIDSelector extends Error {
-    constructor(message) {
-	super(message);
-	this.name = "InvalidCSSIDSelector";
-    }
-}
-
-class InvalidDataAttributeName extends Error {
-    constructor(message) {
-	super(message);
-	this.name = "InvalidDataAttributeName";
-    }
-}
-
-/**
- * CSSIDSelector: A CSS ID Selector
- * @param {String} A CSS selector of the form '#...'
- */
-class CSSIDSelector {
-    constructor(selector) {
-	if(!selector.startsWith("#")) {
-	    throw new InvalidCSSIDSelector(
-		"Expected the CSS selector to begin with a `#` character.");
-	}
-	let id_str = selector.slice(1, selector.length);
-	if(document.getElementById(id_str) == null) {
-	    throw new InvalidCSSIDSelector(
-		"Element with ID '" + id_str + "' does not exist.");
-	}
-	this.selector = selector;
-    }
-}
-
-/**
- * TableDataSource: A type to represent a table's data source
- * @param {String} A CSS selector for an ID
- * @param {String} A `data-*` attribute name
- */
-class TableDataSource {
-    constructor(table_id, data_attribute_name) {
-	this.table_id = new CSSIDSelector(table_id);
-	let data = document.querySelector(
-	    table_id).getAttribute(data_attribute_name);
-	if(data == null) {
-	    throw new InvalidDataAttributeName(
-		"data-* attribute '" + data_attribute_name + "' does not exist " +
-		    "for table with ID '" + table_id.slice(1, table_id.length) +
-		    "'.");
-	} else {
-	    this.data_attribute_name = data_attribute_name;
-	}
-    }
-}
-
-/**
- * Switch the dataset from search table to selection table and vice versa
- * @param {Object} A genotype dataset
- * @param {TableDataSource} The table to switch the dataset from
- * @param {TableDataSource} The table to switch the dataset to
- */
-function select_deselect_dataset(dataset, source, destination) {
-    dest_selector = destination.table_id.selector
-    dest_data = JSON.parse(
-	$(dest_selector).attr(destination.data_attribute_name));
-    add_to_table_data(dataset, destination); // Add to destination table
-    remove_from_table_data(dataset, source); // Remove from source table
-    /***** BEGIN: Re-render tables *****/
-    // The `render_table` could be modified to use the checkbox creator function
-    // from the `TableDataSource` object, once that is modified to have that.
-    render_table(
-	"#tbl-link-genotypes", "data-selected-datasets", link_checkbox);
-    render_table("#tbl-genotypes", "data-datasets", search_checkbox);
-    toggle_link_button();
-    /***** END: Re-render tables *****/
-}
-
-function debounce(func, delay=500) {
-    var timeout;
-    return function search(event) {
-	clearTimeout(timeout);
-	timeout = setTimeout(func, delay);
-    };
-}
-
 function search_genotypes() {
     query = document.getElementById("txt-query").value;
     selected = JSON.parse(document.getElementById(
 	"tbl-link-genotypes").getAttribute("data-selected-datasets"));
     species_name = document.getElementById("txt-species-name").value
     search_endpoint = "/oauth2/data/genotype/search"
+    search_table = new TableDataSource(
+	"#tbl-genotypes", "data-datasets", search_checkbox);
     $.ajax(
 	search_endpoint,
 	{
@@ -213,22 +51,23 @@ function search_genotypes() {
 			data.error_description);
 		document.getElementById("tbl-genotypes").setAttribute(
 		    "data-datasets", JSON.stringify([]));
-		render_table("#tbl-genotypes", "data-datasets", search_checkbox);
+		render_table(search_table);
 	    },
 	    "success": function(data, textStatus, jqXHR) {
 		document.getElementById("search-error").setAttribute(
 		    "style", "display: none;");
 		document.getElementById("tbl-genotypes").setAttribute(
 		    "data-datasets", JSON.stringify(data));
-		render_table("#tbl-genotypes", "data-datasets", search_checkbox);
+		render_table(search_table);
 	    }
 	});
 }
 
 $(document).ready(function() {
-    let search_table = new TableDataSource("#tbl-genotypes", "data-datasets");
+    let search_table = new TableDataSource(
+	"#tbl-genotypes", "data-datasets", search_checkbox);
     let link_table = new TableDataSource(
-	"#tbl-link-genotypes", "data-selected-datasets");
+	"#tbl-link-genotypes", "data-selected-datasets", link_checkbox);
 
     $("#frm-search-traits").submit(function(event) {
 	event.preventDefault();
@@ -241,6 +80,7 @@ $(document).ready(function() {
         if(this.checked) {
 	    select_deselect_dataset(
 		JSON.parse(this.value), search_table, link_table);
+	    toggle_link_button();
         }
     });
 
@@ -248,6 +88,7 @@ $(document).ready(function() {
 	if(!this.checked) {
 	    select_deselect_dataset(
 		JSON.parse(this.value), link_table, search_table);
+	    toggle_link_button();
 	}
     });
 });
diff --git a/wqflask/wqflask/static/new/javascript/auth/search_mrna.js b/wqflask/wqflask/static/new/javascript/auth/search_mrna.js
new file mode 100644
index 00000000..e754ae76
--- /dev/null
+++ b/wqflask/wqflask/static/new/javascript/auth/search_mrna.js
@@ -0,0 +1,96 @@
+/**
+ * Check whether `dataset` is in array of `datasets`.
+ * @param {mRNADataset} A mrna dataset.
+ * @param {Array} An array of mrna datasets.
+ */
+function in_array(dataset, datasets) {
+    found = datasets.filter(function(dst) {
+	return (dst.SpeciesId == dataset.SpeciesId &&
+		dst.InbredSetId == dataset.InbredSetId &&
+		dst.ProbeFreezeId == dataset.ProbeFreezeId &&
+		dst.ProbeSetFreezeId == dataset.ProbeSetFreezeId);
+    });
+    return found.length > 0;
+}
+
+function toggle_link_button() {
+    num_groups = $("#frm-link select option").length - 1;
+    num_selected = JSON.parse(
+	$("#tbl-link").attr("data-datasets")).length;
+    if(num_groups > 0 && num_selected > 0) {
+	$("#frm-link input[type='submit']").prop("disabled", false);
+    } else {
+	$("#frm-link input[type='submit']").prop("disabled", true);
+    }
+}
+
+function search_mrna() {
+    query = document.getElementById("txt-query").value;
+    selected = JSON.parse(document.getElementById(
+	"tbl-link").getAttribute("data-datasets"));
+    species_name = document.getElementById("txt-species-name").value
+    search_endpoint = "/oauth2/data/mrna/search"
+    search_table = new TableDataSource(
+	"#tbl-search", "data-datasets", search_checkbox);
+    $.ajax(
+	search_endpoint,
+	{
+	    "method": "POST",
+	    "contentType": "application/json; charset=utf-8",
+	    "dataType": "json",
+	    "data": JSON.stringify({
+		"query": query,
+		"selected": selected,
+		"dataset_type": "mrna",
+		"species_name": species_name}),
+	    "error": function(jqXHR, textStatus, errorThrown) {
+		error_data = jqXHR.responseJSON
+		console.debug("ERROR_DATA:", error_data);
+		elt = document.getElementById("search-error").setAttribute(
+		    "style", "display: block;");
+		document.getElementById("search-error-text").innerHTML = (
+		    error_data.error + " (" + error_data.status_code + "): " +
+			error_data.error_description);
+		document.getElementById("tbl-search").setAttribute(
+		    "data-datasets", JSON.stringify([]));
+		render_table(search_table);
+	    },
+	    "success": function(data, textStatus, jqXHR) {
+		document.getElementById("search-error").setAttribute(
+		    "style", "display: none;");
+		document.getElementById("tbl-search").setAttribute(
+		    "data-datasets", JSON.stringify(data));
+		render_table(search_table);
+	    }
+	});
+}
+
+$(document).ready(function() {
+    let search_table = new TableDataSource(
+	"#tbl-search", "data-datasets", search_checkbox);
+    let link_table = new TableDataSource(
+	"#tbl-link", "data-datasets", link_checkbox);
+
+    $("#frm-search").submit(function(event) {
+	event.preventDefault();
+	return false;
+    });
+
+    $("#txt-query").keyup(debounce(search_mrna));
+
+    $("#tbl-search").on("change", ".checkbox-search", function(event) {
+        if(this.checked) {
+	    select_deselect_dataset(
+		JSON.parse(this.value), search_table, link_table);
+	    toggle_link_button();
+        }
+    });
+
+    $("#tbl-link").on("change", ".checkbox-selected", function(event) {
+	if(!this.checked) {
+	    select_deselect_dataset(
+		JSON.parse(this.value), link_table, search_table);
+	    toggle_link_button();
+	}
+    });
+});
diff --git a/wqflask/wqflask/templates/oauth2/data-list-genotype.html b/wqflask/wqflask/templates/oauth2/data-list-genotype.html
index 30ee0d27..c780a583 100644
--- a/wqflask/wqflask/templates/oauth2/data-list-genotype.html
+++ b/wqflask/wqflask/templates/oauth2/data-list-genotype.html
@@ -159,6 +159,8 @@
 {%endblock%}
 
 {%block js%}
+<script src="/static/new/javascript/auth/search.js"
+	language="javascript" type="text/javascript"></script>
 <script src="/static/new/javascript/auth/search_genotypes.js"
 	language="javascript" type="text/javascript"></script>
 {%endblock%}
diff --git a/wqflask/wqflask/templates/oauth2/data-list-mrna.html b/wqflask/wqflask/templates/oauth2/data-list-mrna.html
index 1c22f65c..0e163235 100644
--- a/wqflask/wqflask/templates/oauth2/data-list-mrna.html
+++ b/wqflask/wqflask/templates/oauth2/data-list-mrna.html
@@ -23,7 +23,7 @@
   </div>
 
   <div class="row">
-    <form id="frm-link-mrna" method="POST"
+    <form id="frm-link" method="POST"
 	  action="{{url_for('oauth2.data.link_mrna_data')}}">
       <legend>Link mRNA Assay Datasets to Group</legend>
 
@@ -41,9 +41,9 @@
       </div>
 
       <div class="form-group">
-      <table id="tbl-link-mrna"
+      <table id="tbl-link"
 	     class="table-hover table-striped cell-border dataTable no-footer"
-	     data-selected-datasets='{{selected_datasets | list | tojson}}'>
+	     data-datasets='{{selected_datasets | list | tojson}}'>
 	<thead>
 	  <tr>
 	    <th>Deselect</th>
@@ -161,6 +161,8 @@
 {%endblock%}
 
 {%block js%}
+<script src="/static/new/javascript/auth/search.js"
+	language="javascript" type="text/javascript"></script>
 <script src="/static/new/javascript/auth/search_mrna.js"
 	language="javascript" type="text/javascript"></script>
 {%endblock%}