aboutsummaryrefslogtreecommitdiff
path: root/gn2/wqflask
diff options
context:
space:
mode:
authorAlexander Kabui2024-09-06 11:17:34 +0300
committerGitHub2024-09-06 11:17:34 +0300
commita221d82a16428012a577924279af262a9c9f67a4 (patch)
tree15dce78331b9b9cd775bcf73f0be204095f598aa /gn2/wqflask
parentfdf14becd8913d0e53cfad45bc4045a77e718769 (diff)
parent8b45ac5e26a1dd266b0de9bb442afe50169739c6 (diff)
downloadgenenetwork2-a221d82a16428012a577924279af262a9c9f67a4.tar.gz
Merge pull request #863 from genenetwork/chores/merge-gnqa-systems
Chores/merge gnqa systems
Diffstat (limited to 'gn2/wqflask')
-rw-r--r--gn2/wqflask/requests.py10
-rw-r--r--gn2/wqflask/templates/base.html3
-rw-r--r--gn2/wqflask/templates/gnqa.html145
-rw-r--r--gn2/wqflask/templates/gnqa_answer.html277
-rw-r--r--gn2/wqflask/templates/gnqa_search_history.html106
-rw-r--r--gn2/wqflask/views.py123
6 files changed, 404 insertions, 260 deletions
diff --git a/gn2/wqflask/requests.py b/gn2/wqflask/requests.py
index 43c8001f..182201a5 100644
--- a/gn2/wqflask/requests.py
+++ b/gn2/wqflask/requests.py
@@ -14,3 +14,13 @@ def get(url, params=None, **kwargs) -> Either:
def post(url, data=None, json=None, **kwargs) -> Either:
"""Wrap requests post method with Either monad"""
return __wrap_response__(requests.post(url, data=data, json=json, **kwargs))
+
+
+def put(url, data=None, json=None, **kwargs) -> Either:
+ """Wrap requests put method with Either monad"""
+ return __wrap_response__(requests.put(url, data=data, json=json, **kwargs))
+
+
+def delete(url, **kwargs) -> Either:
+ """Wrap requests delete method with Either monad"""
+ return __wrap_response__(requests.delete(url, **kwargs))
diff --git a/gn2/wqflask/templates/base.html b/gn2/wqflask/templates/base.html
index eb4e9e91..6c545646 100644
--- a/gn2/wqflask/templates/base.html
+++ b/gn2/wqflask/templates/base.html
@@ -183,11 +183,10 @@
</div>
<!-- todo fix text overlap for this;;responsiveness-->
- <!-- this functionality is currently use;ga.genenetwork.org/gnqna
<span style="padding: 5px;margin-left: 65px;" id="gnqna_home">
<a href="/gnqna">GNQA Search</a>
</span>
- -->
+
<span style="padding: 5px;margin-left: 65px;" >
<a style="text-decoration: none" target="_blank" href="/search-syntax">
<i style="text-align: center;color:#336699;;" class="fa fa-question-circle fa-2x" title="see more search hints" aria-hidden="true"></i>
diff --git a/gn2/wqflask/templates/gnqa.html b/gn2/wqflask/templates/gnqa.html
index 1268ef39..158b0b4e 100644
--- a/gn2/wqflask/templates/gnqa.html
+++ b/gn2/wqflask/templates/gnqa.html
@@ -1,9 +1,7 @@
{% extends "base.html" %}
{% block title %}GNQA{% endblock %}
-
{% block css %}
-<style>
-
+ <style>
.htmx-indicator{
display:none;
opacity: 0;
@@ -82,79 +80,78 @@
background-color: #ccf;
}
-</style>
+ </style>
{% endblock %}
-
{% block search %}{% endblock %}
-{% block content %} <!-- Start of body -->
-<section class="container-fluid">
- <header class="row">
- <h1 class="col-sm-12 text-center search-header">
- AI Search
- <small>
- <sup>
- <button class="search-hist-btn" hx-get="/gnqna/hist/" hx-target="#swap" hx-swap="innerHTML" >
- [Search History]
- </button>
- </sup>
- </small>
- </h1>
- </header>
- <form class="row form-horizontal" id="gnqna_search_home"
- action="/gnqna" method="POST">
- <!--- init gnqa codebase here -->
- <div class="form-group form-group-lg col col-xs-12 col-sm-6 col-sm-offset-3">
- <button class="btn btn-default btn-sm col-xs-1 col-sm-1 col-sm-offset-3"
- hx-post="/gnqna"
- hx-target="#swap"
- hx-swap="innerHTML"
- hx-indicator="#indicator">
- <i class="fa fa-search fa-3x" aria-hidden="true" title="Search"></i>
- <img id="indicator" class="htmx-indicator" src="/static/gif/loader.gif"/>
- </button>
- <input
- class="text-left input-lg col-sm-5"
- id="gnqna_search_home_input"
- type="text" autocomplete="on"
- required
- placeholder="Ask More Questions or Topics (E.g Genes)"
- value=''
- name="querygnqa"
- hx-post="/gnqna"
- hx-target="#swap"
- hx-swap="innerHTML"
- hx-indicator="#indicator"
- />
- </div>
- </form>
- <article id="swap" class="row">
- <div class="row gnqa-copy">
- <p class="col-sm-10 col-sm-offset-1 col-md-offset-3 col-md-6">
- Welcome to the GeneNetwork Question and Answer (GNQA)system. We utilize a large language model and 3000 scientific publications to make GNQA a subject matter expert in three areas: <b><a href="/">GeneNetwork.org </a></b>, <b>genomics/genetics with regards to diabetes</b> and <b>genomics/genetics with regards to agin.</b>.
- </p>
- <p class="col-sm-11 col-md-offset-3 col-md-6">At the moment when you ask GNQA something it will attempt to return a sensible answer with <q>real</q> references. To this end we aim to reduce hallucinations and provide a knowledge launchpad for a researcher to enhance their knowledge on the relevant subject matter.</p>
- <p class="col-sm-11 col-md-offset-3 col-md-6">
- GNQA is not a finished product as we are working diligently to improve it daily.
- </p>
- <p class="col-sm-11 col-md-offset-3 col-md-6"><b>Thanks for using GNQA!</b> </p>
-
- </div>
- </article>
-</section>
-
-{% endblock %}
-
-{% block js %}
-<script src="{{ url_for('js', filename='jquery/jquery.min.js') }}" type="text/javascript"></script>
-
-<script language="javascript" type="text/javascript" src="{{ url_for('js', filename='jquery-ui/jquery-ui.min.js') }}"></script>
-
-<script language="javascript" type="text/javascript" src="{{ url_for('js', filename='htmx.min.js') }}"></script>
-
-<script type="text/javascript">
+{% block content %}
+ <!-- Start of body -->
+ <section class="container-fluid">
+ <header class="row">
+ <h1 class="col-sm-12 text-center search-header">
+ AI Search
+ <small>
+ <sup>
+ <button class="search-hist-btn"
+ hx-get="/gnqna/records"
+ hx-target="#swap"
+ hx-swap="innerHTML">[Search History]</button>
+ </sup>
+ </small>
+ </h1>
+ </header>
+ <form class="row form-horizontal"
+ id="gnqna_search_home"
+ action="/gnqna"
+ method="post">
+ <!--- init gnqa codebase here -->
+ <div class="form-group form-group-lg col col-xs-12 col-sm-6 col-sm-offset-3">
+ <button class="btn btn-default btn-sm col-xs-1 col-sm-1 col-sm-offset-3"
+ hx-post="/gnqna"
+ hx-target="#swap"
+ hx-swap="innerHTML"
+ hx-indicator="#indicator">
+ <i class="fa fa-search fa-3x" aria-hidden="true" title="Search"></i>
+ <img id="indicator" class="htmx-indicator" src="/static/gif/loader.gif" />
+ </button>
+ <input class="text-left input-lg col-sm-5"
+ id="gnqna_search_home_input"
+ type="text"
+ autocomplete="on"
+ required
+ placeholder="Ask More Questions or Topics (E.g Genes)"
+ value=''
+ name="querygnqa" />
+ </div>
+ </form>
+ <article id="swap" class="row">
+ <div class="row gnqa-copy">
+ <div class="col-sm-10 col-sm-offset-1 col-md-offset-3 col-md-6">
+ <p>
+ Welcome to the GeneNetwork Question and Answer (GNQA)system. We utilize a large language model and 3000 scientific publications to make GNQA a subject matter expert in three areas: <b><a href="/">GeneNetwork.org</a></b>, <b>genomics/genetics with regards to diabetes</b> and <b>genomics/genetics with regards to agin.</b>.
+ </p>
+ <p>
+ At the moment when you ask GNQA something it will attempt to return a sensible answer with <q>real</q> references. To this end we aim to reduce hallucinations and provide a knowledge launchpad for a researcher to enhance their knowledge on the relevant subject matter.
+ </p>
+ <p>GNQA is not a finished product as we are working diligently to improve it daily.</p>
+ <p>
+ <b>Thanks for using GNQA!</b>
+ </p>
+ <div></div>
+ </article>
+ </section>
+ {% endblock %}
+ {% block js %}
+ <script src="{{ url_for('js', filename='jquery/jquery.min.js') }}"
+ type="text/javascript"></script>
+ <script language="javascript"
+ type="text/javascript"
+ src="{{ url_for('js', filename='jquery-ui/jquery-ui.min.js') }}"></script>
+ <script language="javascript"
+ type="text/javascript"
+ src="{{ url_for('js', filename='htmx.min.js') }}"></script>
+ <script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
$('footer').hide()
});
-</script>
-{% endblock %}
-
+ </script>
+ {% endblock %}
diff --git a/gn2/wqflask/templates/gnqa_answer.html b/gn2/wqflask/templates/gnqa_answer.html
index 0ddcfde7..7a637b20 100644
--- a/gn2/wqflask/templates/gnqa_answer.html
+++ b/gn2/wqflask/templates/gnqa_answer.html
@@ -1,112 +1,191 @@
-
<section class="container-fluid answers gnqa-copy">
<div class="row container gnqa-answer" style="margin-bottom: 1em">
- <p class="row lead">
- <mark style="font-family: 'Linux Libertine','Georgia','Times','Source Serif Pro',serif;"><b><i>{{ query }}</i></b></mark><br/>
- {{ answer }}
- </p>
- <div class="rating row" data-doc-id="{{query}}">
- <button class="btn" id="upvote" data-toggle="tooltip" data-placement="top" title="Vote Up"><i class="fa fa-thumbs-up fa-sm fa-1x" aria-hidden="true"></i></button>
- <button class="btn" id="downvote" data-toggle="tooltip" data-placement="top" title="Vote Down"><i class="fa fa-thumbs-down fa-sm fa-1x" aria-hidden="true"></i></button>
- <sub id="rate" class="text-info">
- </sub>
- </div>
+ <p class="row lead">
+ <mark style="font-family: 'Linux Libertine','Georgia','Times','Source Serif Pro',serif"><b><i>{{ query }}</i></b></mark>
+ <br />
+ {{ answer|safe }}
+ </p>
+ <div class="rating row" data-doc-id="{{ query }}">
+ <button class="btn"
+ id="upvote"
+ data-toggle="tooltip"
+ data-placement="top"
+ title="Vote Up">
+ <i class="fa fa-thumbs-up fa-sm fa-1x" aria-hidden="true"></i>
+ </button>
+ <button class="btn"
+ id="downvote"
+ data-toggle="tooltip"
+ data-placement="top"
+ title="Vote Down">
+ <i class="fa fa-thumbs-down fa-sm fa-1x" aria-hidden="true"></i>
+ </button>
+ <sub id="rate" class="text-info">
+ </sub>
+ </div>
</div>
<div class="row container">
- <details open>
- <summary><h3 style="font-family: 'Linux Libertine','Georgia','Times','Source Serif Pro',serif;">References</h3></summary>
- {% if references %}
- <ul class="list-unstyled">
- {% for reference in references %}
- <li>
- <div class="panel-group" role="tablist" aria-multiselectable="true" style="margin-bottom:0;">
- <div class="panel panel-default">
- {% if loop.first %}
- <div class="panel-heading active" role="tab" id="heading{{ reference.doc_id }}">
- <h4 class="panel-title" style="font-family: 'Linux Libertine','Georgia','Times','Source Serif Pro',serif;">
-
- <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse{{ reference.doc_id }}" aria-expanded="true" aria-controls="collapse{{reference.doc_id}}">
- {{ reference.bibInfo }}
- </a>
- </h4>
- </div>
- <div id="collapse{{reference.doc_id}}" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="heading{{reference.doc_id}}">
- <div class="panel-body">
- <p class="node-references">{{ reference.comboTxt }}</p>
- <div>
- {% if reference.pubmed %}
- <details open>
- <summary>See PubMed Info</summary>
- <div style="font-family: 'Linux Libertine','Georgia','Times','Source Serif Pro',serif;margin-top:1.4em">
- <h3><b>{{ reference.pubmed[0].get('title') }}:</b></h3>
- <p><b>Authors:</b><span class="text-muted">{{ reference.pubmed[0].get('authors') }}</span></p>
- <p><b>PMID: <span class="text-info">{{ reference.pubmed[0].get('pub_id') }}</span></b></p>
- <p><b>Abstract: </b></p>
- <p>{{ reference.pubmed[0].get('abstract')|safe }}</p>
- <p><a href="{{reference.pubmed[0].get('source')}}" target="_blank">See full Article on Pubmed</a></p>
- </div>
- </details>
- {% endif %}
- </div>
- </div>
- {% else %}
- <div class="panel-heading" role="tab" id="heading{{reference.doc_id}}">
- <h4 class="panel-title" style="font-family: 'Linux Libertine','Georgia','Times','Source Serif Pro',serif;">
-
- <a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion" href="#collapse{{reference.doc_id}}" aria-expanded="false" aria-controls="collapse{{reference.doc_id}}">
- {{ reference.bibInfo }}
- </a>
- </h4>
- </div>
- <div id="collapse{{reference.doc_id}}" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading{{reference.doc_id}}">
- <div class="panel-body">
- <p class="node-references">{{reference.comboTxt}}</p>
- <div>
- {% if reference.pubmed %}
- <details >
- <summary>See PubMed Info</summary>
- <div style="font-family: 'Linux Libertine','Georgia','Times','Source Serif Pro',serif;margin-top:1.4em">
- <h3><b>{{ reference.pubmed[0].get('title') }}:</b></h3>
- <p><b>Authors:</b><span class="text-muted">{{ reference.pubmed[0].get('authors') }}</span></p>
- <p><b>PMID: <span class="text-info">{{ reference.pubmed[0].get('pub_id') }}</span></b></p>
- <p><b>Abstract: </b></p>
- <p>{{ reference.pubmed[0].get('abstract')|safe }}</p>
- <p><a href="{{reference.pubmed[0].get('source')}}" target="_blank" style="float:left;">See full Article on Pubmed</a></p>
- </div>
- </details>
- {% endif %}
- </div>
- </div>
- </div>
- {% endif %}
- </div>
- </div>
- </li>
- {% endfor %}
- </ul>
- {% else %}
- <p><i>No references available.</i></p>
- {% endif %}
- </details>
- </div>
+ <details open>
+ <summary>
+ <h3 style="font-family: 'Linux Libertine','Georgia','Times','Source Serif Pro',serif">References</h3>
+ </summary>
+ {% if references %}
+ <ul class="list-unstyled">
+ {% for reference in references %}
+ <li>
+ <div class="panel-group"
+ role="tablist"
+ aria-multiselectable="true"
+ style="margin-bottom:0">
+ <div class="panel panel-default">
+ {% if loop.first %}
+ <div class="panel-heading active"
+ role="tab"
+ id="heading{{ reference.doc_id }}">
+ <h4 class="panel-title"
+ style="font-family: 'Linux Libertine','Georgia','Times','Source Serif Pro',serif">
+ <a class="collapsed"
+ role="button"
+ data-toggle="collapse"
+ data-parent="#accordion"
+ href="#collapse{{ reference.doc_id }}"
+ aria-expanded="true"
+ aria-controls="collapse{{ reference.doc_id }}">
+ {{ reference.bibInfo }}
+ </a>
+ </h4>
+ </div>
+ <div id="collapse{{ reference.doc_id }}"
+ class="panel-collapse collapse in"
+ role="tabpanel"
+ aria-labelledby="heading{{ reference.doc_id }}">
+ <div class="panel-body">
+ <p class="node-references">{{ reference.comboTxt|safe }}</p>
+ <div>
+ {% if reference.pubmed %}
+ <details open>
+ <summary>See PubMed Info</summary>
+ <div style="font-family: 'Linux Libertine','Georgia','Times','Source Serif Pro',serif;
+ margin-top:1.4em">
+ <h3>
+ <b>{{ reference.pubmed[0].get("title") }}:</b>
+ </h3>
+ <p>
+ <b>Authors:</b><span class="text-muted">{{ reference.pubmed[0].get("authors") }}</span>
+ </p>
+ <p>
+ <b>PMID: <span class="text-info">{{ reference.pubmed[0].get("pub_id") }}</span></b>
+ </p>
+ <p>
+ <b>Abstract: </b>
+ </p>
+ <p>{{ reference.pubmed[0].get("abstract") |safe }}</p>
+ <p>
+ <a href="{{ reference.pubmed[0].get("source") }}" target="_blank">See full Article on Pubmed</a>
+ </p>
+ </div>
+ </details>
+ {% endif %}
+ </div>
+ </div>
+ {% else %}
+ <div class="panel-heading" role="tab" id="heading{{ reference.doc_id }}">
+ <h4 class="panel-title"
+ style="font-family: 'Linux Libertine','Georgia','Times','Source Serif Pro',serif">
+ <a class="collapsed"
+ role="button"
+ data-toggle="collapse"
+ data-parent="#accordion"
+ href="#collapse{{ reference.doc_id }}"
+ aria-expanded="false"
+ aria-controls="collapse{{ reference.doc_id }}">
+ {{ reference.bibInfo }}
+ </a>
+ </h4>
+ </div>
+ <div id="collapse{{ reference.doc_id }}"
+ class="panel-collapse collapse"
+ role="tabpanel"
+ aria-labelledby="heading{{ reference.doc_id }}">
+ <div class="panel-body">
+ <p class="node-references">{{ reference.comboTxt|safe }}</p>
+ <div>
+ {% if reference.pubmed %}
+ <details>
+ <summary>See PubMed Info</summary>
+ <div style="font-family: 'Linux Libertine','Georgia','Times','Source Serif Pro',serif;
+ margin-top:1.4em">
+ <h3>
+ <b>{{ reference.pubmed[0].get("title") }}:</b>
+ </h3>
+ <p>
+ <b>Authors:</b><span class="text-muted">{{ reference.pubmed[0].get("authors") }}</span>
+ </p>
+ <p>
+ <b>PMID: <span class="text-info">{{ reference.pubmed[0].get("pub_id") }}</span></b>
+ </p>
+ <p>
+ <b>Abstract: </b>
+ </p>
+ <p>{{ reference.pubmed[0].get("abstract") |safe }}</p>
+ <p>
+ <a href="{{ reference.pubmed[0].get("source") }}"
+ target="_blank"
+ style="float:left">See full Article on Pubmed</a>
+ </p>
+ </div>
+ </details>
+ {% endif %}
+ </div>
+ </div>
+ </div>
+ {% endif %}
+ </div>
+ </div>
+ </li>
+ {% endfor %}
+ </ul>
+ {% else %}
+ <p>
+ <i>No references available.</i>
+ </p>
+ {% endif %}
+ </details>
+ </div>
+ </div>
</section>
{% block js %}
-
-<script>
+ <script>
+ function updateRatingHandler(target, responseObj, args){
+ let {status, response} = responseObj.xhr
+ if (status == 200 && args == "upvote"){
+ htmx.toggleClass(htmx.find('#upvote'), 'btn-success');
+ htmx.removeClass(htmx.find("#downvote"), "btn-danger");
+ }
+ else if(status == 200 && args == "downvote") {
+ htmx.toggleClass(htmx.find('#downvote'), 'btn-danger');
+ htmx.removeClass(htmx.find("#upvote"), "btn-success");
+ }
+ else {
+ alert(`Error occurred with status ${status} and Error ${response}` )
+}}
var query = {{ query|tojson }};
var answer = {{ answer|tojson }}
var {task_id} = {{ task_id|tojson }}
- htmx.on("#upvote", "click", function(evt){
+htmx.on("#upvote", "click", function(evt){
vote_count = htmx.find(".btn-success") ? 0 : 1
- htmx.ajax("POST", `/gnqna/rating/${task_id}/${vote_count}`, {target: "#rate", swap:"innerHTML",values: {'query': query, 'answer': answer}}).then(()=>{
- htmx.toggleClass(htmx.find('#upvote'), 'btn-success');
- htmx.removeClass(htmx.find("#downvote"), "btn-danger");
-})});
+ htmx.ajax("POST",
+ `/gnqna/rating/${task_id}/${vote_count}`,
+ {target: "#rate",
+ handler: (target,obj)=> updateRatingHandler(target, obj, "upvote"),
+ swap:"innerHTML",
+ values: {'query': query, 'answer': answer}})});
htmx.on("#downvote", "click", function(evt){
vote_count = htmx.find(".btn-danger") ? 0 : -1
- htmx.ajax("POST", `/gnqna/rating/${task_id}/${vote_count}`, {target: "#rate", swap:"innerHTML",values: {'query': query, 'answer': answer}}).then(()=>{
- htmx.toggleClass(htmx.find('#downvote'), 'btn-danger');
- htmx.removeClass(htmx.find("#upvote"), "btn-success")
- })});
-</script>
+ htmx.ajax("POST", `/gnqna/rating/${task_id}/${vote_count}`,
+ {target: "#rate",
+ handler: (target, obj)=> updateRatingHandler(target,obj, "downvote"),
+ swap:"innerHTML",
+ values: {'query': query, 'answer': answer}})});
+ </script>
{% endblock %}
diff --git a/gn2/wqflask/templates/gnqa_search_history.html b/gn2/wqflask/templates/gnqa_search_history.html
index 2c07b8c0..8d54ad80 100644
--- a/gn2/wqflask/templates/gnqa_search_history.html
+++ b/gn2/wqflask/templates/gnqa_search_history.html
@@ -1,42 +1,66 @@
-<section class="container-fluid gnqa-copy">
- <header class="row">
-
- <div class="panel panel default col-sm-6 col-sm-offset-3">
- <div class="panel panel-default">
- <div class="panel-heading">
- <div>
- <h4 class="text-primary">You search History </h4>
- </div>
- </div>
- </div>
+<section class="container-fluid gnqa-copy" id="search-hist">
+ <header class="row">
+ <div class="panel panel default col-sm-6 col-sm-offset-3">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <div>
+ <h4 class="text-secondary"
+ style="font-family: 'Linux Libertine','Georgia','Times','Source Serif Pro',serif;
+ font-size:2.3rem">Your AI search History</h4>
+ </div>
+ </div>
+ </div>
+ </div>
+ </header>
+ <div class="container row">
+ <div>
+ <div class="col-sm-6 col-sm-offset-3" style="margin-bottom:10px">
+ <button type="button" class="btn btn-danger" id="delete-btn">Delete Selected</button>
+ </div>
+ <div>
+ <div class="panel panel-default col-sm-6 col-sm-offset-3 ">
+ <div>
+ <ul class="list-group list-group-flush" style="overflow-y:scroll">
+ {% for item in prev_queries %}
+ <li class="row list-group-item">
+ <input name=""
+ type="checkbox"
+ value="{{ item['task_id'] }}"
+ class="col-sm-1"
+ style="height: 20px;
+ width: 20px">
+ <div class="col-sm-10">
+ <button hx-get="/gnqna/record?query={{ item['query'] }}&search_task_id={{ item['task_id'] }}"
+ hx-target="#swap"
+ hx-swap="innerHTML"
+ hx-trigger="click"
+ data-bs-toggle="tooltip"
+ data-bs-placement="left"
+ title="/gnqna/record?query={{ item['query'] }}&search_task_id={{ item['task_id'] }}"
+ style="background:transparent;
+ border:none;
+ cursor:pointer">
+ <p class="text-info">{{ item["query"] }}</p>
+ </button>
+ </div>
+ </li>
+ {% endfor %}
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
</div>
- </header>
- <div class="container row">
- <div class="panel panel-default col-sm-6 col-sm-offset-3 ">
- {% for record in prev_queries %}
- <div class="panel-body">
- <div class="row">
- <input name="" type="checkbox" value="" class="col-sm-1">
- <div class="col-sm-10">
- {% for id,val in record.items() %}
- <button
- hx-get="/gnqna/hist/search/{{id}}"
- hx-target="#swap"
- hx-swap="innerHTML"
- hx-trigger= "click"
- data-bs-toggle="tooltip"
- data-bs-placement="left"
- title="/gnqna/hist/search?{{id}}"
- style="background:transparent;border:none;cursor:pointer"
- >
- <b class="text-info">{{val}} </b>
- </button>
- {% endfor %}
- </div>
- </div>
- </div>
- {% endfor %}
- </div>
- </div>
- </div>
- </section>
+</section>
+<script>
+ htmx.on("#delete-btn", "click", function(evt){
+ htmx.ajax("DELETE","/gnqna/records", {target: "#search-hist", swap :"none",
+ handler: (target,obj) =>{
+ htmx.ajax("GET", "gnqna/records", {
+ target: "#search-hist",
+ swap: "innerHTML"
+ })
+ },
+ values: Array.from(htmx.findAll("input[type=checkbox]:checked"), e => e.value)})
+ })
+</script>
diff --git a/gn2/wqflask/views.py b/gn2/wqflask/views.py
index 7e8cd901..7699c303 100644
--- a/gn2/wqflask/views.py
+++ b/gn2/wqflask/views.py
@@ -261,35 +261,22 @@ def gsearchtable():
return flask.jsonify(current_page)
-"""@app.route("/gnqna", methods=["POST", "GET"]) ;;feature currently disabled
-;;use ga.genenetwork.org
+@app.route("/gnqna", methods=["POST", "GET"])
@require_oauth2
-"""
-
-
def gnqna():
-
if request.method == "POST":
try:
- def __error__(resp):
- return resp.json()
-
def error_page(resp):
return render_template("gnqa_errors.html",
**{"status_code": resp.status_code, **resp.json()})
def __success__(resp):
return render_template("gnqa_answer.html", **{"gn_server_url": GN3_LOCAL_URL, **(resp.json())})
- """
- disable gn-auth currently not stable
- if not user_logged_in():
- return error_page("Please Login/Register to Genenetwork to access this Service")
- """
token = session_info()["user"]["token"].either(
lambda err: err, lambda tok: tok["access_token"])
- return monad_requests.post(
+ return monad_requests.put(
urljoin(GN3_LOCAL_URL,
- "/api/llm/gnqna"),
+ "/api/llm/search"),
json=dict(request.form),
headers={
"Authorization": f"Bearer {token}"
@@ -299,15 +286,8 @@ def gnqna():
).either(
error_page, __success__)
except Exception as error:
- return flask.jsonify({"error": str(error)})
- prev_queries = (monad_requests.get(
- urljoin(GN3_LOCAL_URL,
- "/api/llm/get_hist_names")
- ).then(
- lambda resp: resp
- ).either(lambda x: [], lambda x: x.json()["prev_queries"]))
-
- return render_template("gnqa.html", prev_queries=prev_queries)
+ return flask.jsonify({"error": str(error)}), 500
+ return render_template("gnqa.html")
@app.route("/editor/edit", methods=["GET"])
@@ -343,34 +323,89 @@ def commit_gn_doc():
return render_template("gn_editor_results_page.html", **data)
-@app.route("/gnqna/hist/", methods=["GET"])
+@app.route("/gnqna/records", methods=["GET"])
@require_oauth2
-def get_hist_titles():
+def get_gnqa_records():
+ """Call the Api endpoint for fetching all gnqa records"""
+ def _error_(resp):
+ return render_template("gnqa_errors.html",
+ **{"status_code": resp.status_code,
+ **resp.json()})
+
+ def _success_(resp):
+ response = resp.json()
+ return render_template("gnqa_search_history.html",
+ prev_queries=response)
token = session_info()["user"]["token"].either(
lambda err: err, lambda tok: tok["access_token"])
- response = monad_requests.get(urljoin(GN3_LOCAL_URL,
- "/api/llm/hist/titles"),
- headers={
- "Authorization": f"Bearer {token}"
- }
- ).then(lambda resp: resp).either(
- lambda x: x.json(), lambda x: x.json())
- return render_template("gnqa_search_history.html", **response)
+ response_url = "/api/llm/search/records"
+ return (monad_requests.get(urljoin(GN3_LOCAL_URL, response_url),
+ headers={
+ "Authorization": f"Bearer {token}"
+ }
+ ).then(lambda resp: resp).either(
+ _error_, _success_))
-@app.route("/gnqna/hist/search/<search_term>", methods=["GET"])
+@app.route("/gnqna/record", methods=["GET"])
@require_oauth2
-def fetch_hist_records(search_term):
+def get_gnqa_record_by_task_id():
+ """Get specific record using task"""
+ def _error_(resp):
+ return render_template("gnqa_errors.html",
+ **{"status_code": resp.status_code,
+ **resp.json()})
+
+ def _success_(resp):
+ response = resp.json()
+ return render_template("gnqa_answer.html", **response)
token = session_info()["user"]["token"].either(
lambda err: err, lambda tok: tok["access_token"])
- response = monad_requests.get(urljoin(GN3_LOCAL_URL,
- f"/api/llm/history/{search_term}"),
+ response_url = f"api/llm/search/record/{request.args.get('search_task_id')}"
+ return (monad_requests.get(urljoin(GN3_LOCAL_URL, response_url),
+ headers={
+ "Authorization": f"Bearer {token}"
+ }).then(lambda resp: resp).either(
+ _error_, _success_))
+
+
+@app.route("/gnqna/records", methods=["DELETE"])
+@require_oauth2
+def delete_gnqa_records():
+ """Call the Api endpoint for fetching all gnqa records"""
+ def _error_(resp):
+ return render_template("gnqa_errors.html",
+ **{"status_code": resp.status_code,
+ **resp.json()})
+
+ token = session_info()["user"]["token"].either(
+ lambda err: err, lambda tok: tok["access_token"])
+ return (monad_requests.delete(urljoin(GN3_LOCAL_URL,
+ "/api/llm/search/records"),
+ json=dict(request.form),
headers={
- "Authorization": f"Bearer {token}"
- }
- ).then(lambda resp: resp).either(
- lambda x: x.json(), lambda x: x.json())
- return render_template("gnqa_answer.html", **response)
+ "Authorization": f"Bearer {token}"})
+ .then(lambda resp: resp).either(
+ _error_, lambda x: x.json()))
+
+
+@app.route("/gnqna/record", methods=["DELETE"])
+@require_oauth2
+def delete_gnqa_record_by_task_id():
+ """Get specific record using task"""
+ def _error_(resp):
+ return render_template("gnqa_errors.html",
+ **{"status_code": resp.status_code,
+ **resp.json()})
+
+ token = session_info()["user"]["token"].either(
+ lambda err: err, lambda tok: tok["access_token"])
+ response_url = f"api/llm/search/record/{request.args.get('search_task_id')}"
+ return (monad_requests.get(urljoin(GN3_LOCAL_URL, response_url),
+ headers={
+ "Authorization": f"Bearer {token}"}).then(lambda resp: resp)
+ .either(
+ _error_, lambda x: x.json()))
@app.route("/gnqna/rating/<task_id>/<int(signed=True):weight>",