diff options
author | Frederick Muriuki Muriithi | 2023-04-17 14:18:56 +0300 |
---|---|---|
committer | Frederick Muriuki Muriithi | 2023-04-17 14:18:56 +0300 |
commit | c21016add8fb6b66e4413f8cacba256d4dbf2404 (patch) | |
tree | 7162bff8f7e82e2b9ebac67c90a3f5f0ca22423f | |
parent | 2c517dc9b463f63ffef3c17bd56265b168755c6b (diff) | |
download | genenetwork2-c21016add8fb6b66e4413f8cacba256d4dbf2404.tar.gz |
oauth2: Build code to do search
At this point, the code fails with a 404, despite the appropriate
endpoint existing. Will need further debugging.
-rw-r--r-- | wqflask/wqflask/oauth2/data.py | 44 | ||||
-rw-r--r-- | wqflask/wqflask/static/new/javascript/auth/search.js | 29 | ||||
-rw-r--r-- | wqflask/wqflask/static/new/javascript/auth/search_phenotypes.js | 114 | ||||
-rw-r--r-- | wqflask/wqflask/templates/oauth2/data-list-phenotype.html | 160 |
4 files changed, 177 insertions, 170 deletions
diff --git a/wqflask/wqflask/oauth2/data.py b/wqflask/wqflask/oauth2/data.py index 2b4dfc75..c3d426cf 100644 --- a/wqflask/wqflask/oauth2/data.py +++ b/wqflask/wqflask/oauth2/data.py @@ -1,11 +1,16 @@ """Handle linking data to groups.""" +import sys import json +import uuid +from datetime import datetime from urllib.parse import urljoin +from redis import Redis from flask import ( flash, request, jsonify, url_for, redirect, Response, Blueprint, render_template, current_app as app) +from jobs import jobs from .request_utils import process_error from .client import oauth2_get, oauth2_post @@ -59,24 +64,31 @@ def __search_genotypes__(query, template, **kwargs): return __render_template__(template, search_uri=search_uri, **datasets, **kwargs) def __search_phenotypes__(query, template, **kwargs): + page = int(request.args.get("page", 1)) per_page = int(request.args.get("per_page", 500)) - species_name = kwargs["species_name"] - search_uri = (f"search/?type=phenotype&per_page={per_page}&query=" - f"species:{species_name}") + ( - f" AND ({query})" if bool(query) else "") - traits = oauth2_get(search_uri).either( - lambda err: {"traits_error": process_error(err)}, - lambda trts: {"traits": tuple({ - "index": idx, **trait - } for idx, trait in enumerate(trts, start=1))}) - selected_traits = request.form.getlist("selected_traits") - - return __render_template__( - template, **traits, per_page=per_page, query=query, - selected_traits=selected_traits, - search_endpoint=urljoin(app.config["GN_SERVER_URL"], "search/"), - **kwargs) + def __search_error__(error): + raise Exception(error) + def __search_success__(search_results): + job_id = uuid.UUID(search_results["job_id"]) + return __render_template__( + template, traits=[], per_page=per_page, query=query, + selected_traits=selected_traits, search_results=search_results, + search_endpoint=urljoin( + app.config["GN_SERVER_URL"], "oauth2/data/search"), + results_endpoint=urljoin( + app.config["GN_SERVER_URL"], + f"oauth2/data/search/phenotype/{job_id}"), + **kwargs) + return oauth2_get("oauth2/data/search", json={ + "dataset_type": "phenotype", + "species_name": kwargs["species_name"], + "per_page": per_page, + "page": page, + "gn3_server_uri": app.config["GN_SERVER_URL"] + }).either( + lambda err: __search_error__(process_error(err)), + __search_success__) @data.route("/genotype/search", methods=["POST"]) def json_search_genotypes() -> Response: diff --git a/wqflask/wqflask/static/new/javascript/auth/search.js b/wqflask/wqflask/static/new/javascript/auth/search.js index 5226000d..cd86a9df 100644 --- a/wqflask/wqflask/static/new/javascript/auth/search.js +++ b/wqflask/wqflask/static/new/javascript/auth/search.js @@ -134,30 +134,31 @@ function debounce(func, delay=500) { } /** - * Build a checkbox: For internal use only - * @param {Genotype Dataset object} A genotype dataset object - * @param {String} A string to initialise the checkbox + * Build a checkbox + * @param {Dataset Object} A JSON.stringify-able object + * @param {String} The name to assign the checkbox */ -function __build_checkbox__(dataset, checkbox_str) { +function build_checkbox(data_object, checkbox_name, checkbox_aux_classes="") { cell = $("<td>"); - check = $(checkbox_str); - check.val(JSON.stringify(dataset)); + check = $( + '<input type="checkbox" class="checkbox" ' + + 'name="' + checkbox_name + '" checked="checked">'); + check.val(JSON.stringify(data_object)); + auxilliary_classes = checkbox_aux_class.trim(); + if(Boolean(auxilliary_classes)) { + check.attr("class", + check.attr("class") + " " + auxilliary_classes.trim()); + } cell.append(check); return cell; } function link_checkbox(dataset) { - return __build_checkbox__( - dataset, - '<input type="checkbox" class="checkbox checkbox-selected" ' + - 'name="selected" checked="checked">'); + return build_checkbox(dataset, "selected", "checkbox-selected"); } function search_checkbox(dataset) { - return __build_checkbox__( - dataset, - '<input type="checkbox" class="checkbox checkbox-search" ' + - 'name="search_datasets">'); + return build_checkbox(dataset, "search_datasets", "checkbox-search"); } function table_cell(value) { diff --git a/wqflask/wqflask/static/new/javascript/auth/search_phenotypes.js b/wqflask/wqflask/static/new/javascript/auth/search_phenotypes.js new file mode 100644 index 00000000..b172ffd1 --- /dev/null +++ b/wqflask/wqflask/static/new/javascript/auth/search_phenotypes.js @@ -0,0 +1,114 @@ +/** + * Global variables: Bad idea - figure out how to pass them down a call stack. + */ +search_table = new TableDataSource( + "#tbl-phenotypes", "data-traits", + function(trait) {build_checkbox(trait, "search_traits")}); +link_table = new TableDataSource( + "#tbl-link-phenotypes", "data-traits", + function(trait) {build_checkbox(trait, "selected")}); + +/** + * Toggle the state for the "Link Traits" button + */ +function toggle_link_button() { + num_groups = $("#frm-link-phenotypes select option").length - 1; + num_selected = JSON.parse( + $("#tbl-link-phenotypes").attr("data-datasets")).length; + if(num_groups > 0 && num_selected > 0) { + $("#frm-link-phenotypes input[type='submit']").prop("disabled", false); + } else { + $("#frm-link-phenotypes input[type='submit']").prop("disabled", true); + } +} + +/** + * Default error function: print out debug messages + */ +function default_error_fn(jqXHR, textStatus, errorThrown) { + console.debug("XHR:", jqXHR); + console.debug("STATUS:", textStatus); + console.debug("ERROR:", errorThrown); +} + +function display_search_results(data, textStatus, jqXHR) { + $("#tbl-phenotypes").attr( + "data-traits", JSON.stringify(data.search_results)); + render_table(search_table); +} + +/** + * Fetch the search results + * @param {UUID}: The job id to fetch data for + */ +function fetch_search_results(job_id, success, error=default_error_fn) { + endpoint = $("#frm-search-traits").attr("data-search-results-endpoint"); + $.ajax( + endpoint, + { + "method": "GET", + "contentType": "application/json; charset=utf-8", + "dataType": "json", + "error": error, + "success": success + } + ); +} + +function search_phenotypes() { + query = document.getElementById("txt-query").value; + selected = JSON.parse(document.getElementById( + "tbl-link-phenotypes").getAttribute("data-traitss")); + species_name = document.getElementById("txt-species-name").value + per_page = document.getElementById("txt-per-page").value + search_table = new TableDataSource( + "#tbl-phenotypes", "data-traits", search_checkbox); + $.ajax( + "/oauth2/data/search", + { + "method": "GET", + "contentType": "application/json; charset=utf-8", + "dataType": "json", + "data": JSON.stringify({ + "query": query, + "species_name": species_name, + "dataset_type": "phenotype", + "per_page": per_page + }), + "error": default_error_fn, + "success": (data, textStatus, jqXHR) => { + fetch_search_results(data.job_id); + } + }); +} + +$(document).ready(function() { + $("#frm-search-traits").submit(event => { + event.preventDefault(); + return false; + }); + + $("#txt-query").keyup(debounce(search_phenotypes)); + + $("#tbl-phenotypes").on("change", ".checkbox-selected", function(event) { + if(this.checked) { + select_deselect(JSON.parse(this.value), search_table, link_table); + toggle_link_button(); + } + }); + + $("#tbl-link-phenotypes").on("change", ".checkbox-search", function(event) { + if(!this.checked) { + select_deselect(JSON.parse(this.value), search_table, link_table); + toggle_link_button(); + } + }); + + setTimeout( + function() { + fetch_search_results( + $("#tbl-phenotypes").attr("data-initial-job-id"), + display_search_results) + }, + 500); +}); diff --git a/wqflask/wqflask/templates/oauth2/data-list-phenotype.html b/wqflask/wqflask/templates/oauth2/data-list-phenotype.html index 53c6ce8c..e6998d28 100644 --- a/wqflask/wqflask/templates/oauth2/data-list-phenotype.html +++ b/wqflask/wqflask/templates/oauth2/data-list-phenotype.html @@ -40,7 +40,9 @@ </select> </div> - <table id="tbl-link-phenotypes" class="table-hover table-striped cell-border"> + <table id="tbl-link-phenotypes" + class="table-hover table-striped cell-border dataTable no-footer" + data-traits="[]"> <tbody> <tr> <td colspan="100%" align="center" style="text-align: center;"> @@ -53,12 +55,14 @@ </tr> </table> - {%if groups | length > 0%} - <input type="submit" value="Link Selected" class="btn btn-primary" /> - {%else%} - <input type="submit" value="No group to link to" class="btn btn-warning" - disabled="disabled" /> - {%endif%} + <div class="form-group text-center"> + <input type="submit" value="Link Selected" + class="btn btn-primary" + style="border-top: 0.3em;" + {%if groups | length <= 0 or traits | length <= 0%} + disabled="disabled" + {%endif%} /> + </div> </form> </div> @@ -66,7 +70,8 @@ <span id="search-messages" class="alert-danger" style="display:none"></span> <form id="frm-search-traits" action="#" - method="POST"> + method="POST" + data-search-results-endpoint="{{results_endpoint}}"> {%if dataset_type == "mrna"%} <legend>mRNA: Search</legend> {%else%} @@ -84,17 +89,19 @@ <div class="form-group"> <label for="txt-query">Search</label> <div class="input-group"> - <span class="input-group-addon">species:{{species_name}} AND (</span> + <span class="input-group-addon">species:{{species_name}} AND </span> <input type="text" id="txt-query" name="query" class="form-control" value="{{query}}"/> - <span class="input-group-addon">)</span> </div> </div> </form> </div> <div class="row"> - <table id="tbl-phenotypes" class="table-hover table-striped cell-border"> + <table id="tbl-phenotypes" + class="table-hover table-striped cell-border dataTable no-footer" + data-traits="[]" + data-initial-job-id={{search_results.job_id}}> <tbody> <tr> <td colspan="100%" align="center"> @@ -110,134 +117,7 @@ {%block js%} <script language="javascript" type="text/javascript" - src="/js/DataTables/js/jquery.dataTables.min.js"></script> - -<script language="javascript" type="text/javascript" - src="/js/DataTablesExtensions/plugins/sorting/natural.js"></script> - -<script language="javascript" type="text/javascript" - src="/js/DataTablesExtensions/colReorder/js/dataTables.colReorder.js"> -</script> - -<script language="javascript" type="text/javascript" - src="/js/DataTablesExtensions/colResize/dataTables.colResize.js"> -</script> - + src="/static/new/javascript/auth/search.js"></script> <script language="javascript" type="text/javascript" - src="/static/new/javascript/create_datatable.js"></script> - -<script language="javascript" type="text/javascript"> - function init_table(table_id, traits) { - create_table( - tableId=table_id, tableData=traits, - columnDefs=[ - {"data": null, "render": function(data) { - return ( - '<input type="checkbox" ' + - (table_id == 'tbltbl-phenotypes' ? - 'name="pheno_traits" ': 'name="selected_traits" ') + - 'class="checkbox" value="' + - data.name + ':' + data.dataset + - '" />'); - }}, - {"title": "Index", "data": "index"}, - {"title": "Dataset", "data": "dataset_fullname"}, - {"title": "Group", "data": "group"}, - {"title": "Record", "data": null, "render": function(data) { - return ( - '<a target="_blank" href="/show_trait?trait_id=' + - data.name + '&dataset=' + data.dataset + - '">' + data.name + "</a>"); - }}, - {"title": "Description", "data": "description"}, - {"title": "Authors", "data": "authors"}, - {"title": "Year", "data": null, render: function(data) { - return ( - '<a target="_blank" href="' + data.pubmed_link + - '" >' + data.year + '</a>'); - }}, - {"title": "LRS", "data": null, "render": function(data) { - return data.lrs ? data.lrs.toFixed(4) : "N/A"; - }}, - {"title": "Peak Location", "data": null, "render": function(data) { - return 'Chr' + data.geno_chr + ': ' + data.geno_mb; - }}, - {"title": "Additive Effects", "data": null, "render": function(data) { - return data.additive ? data.additive.toFixed(4) : "N/A"; - }}], - customSettings = { - "scrollY": "40vh", - "language": { - "emptyTable": "No traits to display!", - "info": "Showing _START_ to _END_ of _TOTAL_ entries", - "infoEmpty": "No entries to show", - "loadingRecords": "Loading entries ..." - } - }); - } - - function add_index(item, index) { - return {"index": index, ...item}; - } - - function do_search() { - /*vent.preventDefault();*/ - user_query = $("#txt-query").val(); - dataset_type = $("#txt-dataset-type").val(); - per_page = $("#txt-per-page").val(); - species = $("#txt-species").val(); - query = "species:" + species; - if (user_query.length > 2) { - query = query + " AND (" + user_query + ")"; - } - $("#search-messages").html(""); - $("#search-messages").attr("style", "display:none;"); - $.ajax( - "{{search_endpoint}}", - { - "method": "GET", - "data": { - "type": dataset_type, - "per_page": per_page, - "query": query - }, - "error": function(jqXHR, textStatus, errorThrown) { - msg_elt = $("#search-messages") - console.debug(jqXHR) - $("#search-messages").html( - "<strong>" + textStatus + "</strong>: Search for '" + - user_query + "' failed! Try a different search."); - $("#search-messages").attr("style", "display: block;"); - }, - "success": function (data, textStatus, jqXHR) { - init_table("tbl-phenotypes", data.map(add_index)); - } - }); - } - - function debounced_search() { - var timeout; - return function search(event) { - clearTimeout(timeout); - timeout = setTimeout(do_search, 500); - }; - } - - function sanitised_table_data(data) { - if(data && data.length > 0) { - return data - } - return null - } - - $(document).ready(function() { - $("#frm-search-traits").submit(function(event) { - event.preventDefault(); - return false; - }); - $("#txt-query").keyup(debounced_search()) - init_table("tbl-phenotypes", {{traits | list | tojson}}); - init_table("tbl-link-phenotypes", {{selected_traits | list | tojson}}); - }); -</script> + src="/static/new/javascript/auth/search_phenotypes.js"></script> {%endblock%} |