Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sample summary report expansion #106

Merged
merged 6 commits into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 65 additions & 48 deletions microsetta_admin/server.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import csv
import jwt
from flask import render_template, Flask, request, session, send_file, url_for
import secrets
Expand Down Expand Up @@ -401,63 +402,79 @@ def per_sample_summary():
projects=projects,
error_message=result,
**build_login_variables())

# if we are here then the user is querying using barcodes and we
# simply need to set up the query below to perform.
sample_barcodes = [sample_barcode, ]
else:
# assume POST, since there are only two methods defined in route.
# if we are here, it is because the user is querying using an uploaded
# file containing sample names.
sample_barcodes, err = upload_util.parse_request_csv_col(request,
'file',
'sample_name')
if err is not None:
# there was an error. abort early.
return render_template('per_sample_summary.html',
resource=None,
projects=projects,
**build_login_variables(),
search_error=[{'error': err}])
search_field = request.form.get('search_field')
search_value = request.form.get('single_search')
uploaded_file = request.files.get('upload_list')

# perform the main query.
payload = {'sample_barcodes': sample_barcodes}
status, result = APIRequest.post('/api/admin/account_barcode_summary?stri'
'p_sampleid=%s' % str(strip_sampleid),
json=payload)
search_values = []

if status == 200:
if result['partial_result'] is True:
unprocessed_barcodes = result['unprocessed_barcodes']
if uploaded_file:
file_content = io.TextIOWrapper(uploaded_file,
encoding='utf-8-sig')
csv_reader = csv.reader(file_content)

for row in csv_reader:
search_values.extend(row)
else:
unprocessed_barcodes = None
resource = pd.DataFrame(result['samples'])
order = ['sampleid', 'project', 'account-email',
'source-type', 'site-sampled', 'sample-date',
'sample-time', 'sample-status', 'sample-received',
'ffq-taken', 'ffq-complete', 'vioscreen_username']
order.extend(sorted(set(resource.columns) - set(order)))
resource = resource[order]
search_values = [search_value] if search_value else []

if unprocessed_barcodes:
return render_template('per_sample_summary.html',
resource=resource,
projects=projects,
error_message="Too many barcodes. S"
"erver processed only"
" the first 1000.",
**build_login_variables())
payload = {}
payload[search_field] = search_values

# perform the main query.
status, result = APIRequest.post('/api/admin/account_barcode_summary?'
'strip_sampleid=%s' %
str(strip_sampleid),
json=payload)

if status == 200:
if result['partial_result'] is True:
unprocessed_barcodes = result['unprocessed_barcodes']
else:
unprocessed_barcodes = None
resource = pd.DataFrame(result['samples'])
if not resource.empty:
order = ['sampleid', 'project', 'account-email',
cassidysymons marked this conversation as resolved.
Show resolved Hide resolved
'source-type', 'site-sampled', 'sample-date',
'sample-time', 'sample-status', 'sample-received',
'first-scan-status', 'first-scan-timestamp',
'latest-scan-status', 'latest-scan-timestamp',
'sample-has-inconsistencies', 'sample-is-valid',
'no-associated-source', 'no-collection-info',
'no-registered-account', 'received-unknown-validity',
'ffq-taken', 'ffq-complete', 'vioscreen_username',
'kit-id', 'outbound-tracking',
'inbound-tracking'
]
order.extend(sorted(set(resource.columns) - set(order)))
resource = resource[order]
else:
return render_template('per_sample_summary.html',
resource=resource,
projects=projects,
error_message="No sample found",
**build_login_variables())

if unprocessed_barcodes:
return render_template('per_sample_summary.html',
resource=resource,
projects=projects,
error_message="Too many barcodes. S"
"erver processed only"
" the first 1000.",
**build_login_variables())
else:
return render_template('per_sample_summary.html',
resource=resource,
projects=projects,
**build_login_variables())
else:
return render_template('per_sample_summary.html',
resource=resource,
resource=None,
projects=projects,
error_message=result,
**build_login_variables())
else:
return render_template('per_sample_summary.html',
resource=None,
projects=projects,
error_message=result,
**build_login_variables())


def _get_by_sample_barcode(sample_barcodes, strip_sampleid, projects):
Expand Down
79 changes: 55 additions & 24 deletions microsetta_admin/templates/per_sample_summary.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,25 @@
block.innerHTML = "";
}
};

function handleFormSubmit(event) {
var uploadList = document.getElementById('upload_list');
var singleSearch = document.getElementById('single_search');

if (uploadList.files.length > 0 && singleSearch.value.trim() !== "") {
alert("Please provide either a text input or a file, not both.");
event.preventDefault();
return false;
} else if (uploadList.files.length === 0 && singleSearch.value.trim() === "") {
alert("Please provide either a text input or a file.");
event.preventDefault();
return false;
} else {
remove_error_messages();
return true;
}
}

$(document).ready(function() {
{% if resource is not none %}
$('#search_results').DataTable({
Expand All @@ -27,36 +46,48 @@
{% block content %}
<h3>Sample Summaries</h3>
<hr class="dashed">
<h5>Retrieve summary for a single sample</h5>
{% if error_message %}
<p style="color:red">
{{ error_message |e }}
</p>
{% endif %}
<div style="height: 400px; width: 400px">
{% if error_message %}
<p style="color:red">
{{ error_message |e }}
</p>
{% endif %}
<form name="search_form" id="search_form" method="GET">
<table width=100% border=0>
<tr>
<td colspan=3 style="text-align:left;padding:4px"> <input type="text" name="sample_barcode" placeholder="Enter barcode here" id="sample_barcode" {% if info %} value="{{info.barcode}}"{% endif %}> </td>
<td colspan=1 style="text-align:right;padding:4px"> <input type="submit" value="Retrieve"> </td>
</tr>
</table>
<script> document.search_form.sample_barcode.focus() </script>
</form>
<hr class="dashed">
<h5>Retrieve summaries using a csv file</h5>
<form name="upload_csv" id="search_csv" method="POST" enctype="multipart/form-data" onsubmit="return remove_error_messages()">
<h5>Retrieve summary for a sample</h5>
<form name="search_form" id="search_form" method="POST" enctype="multipart/form-data" onsubmit="return handleFormSubmit(event)">
<table width=100% border=0>
<tr>
<td colspan=3 style="text-align:left;padding:4px"><input type=file name=file></td>
<td colspan=1 style="text-align:right;padding:4px"><input type=submit value=Upload></td>
<td colspan=3 style="text-align:left;padding:4px">
cassidysymons marked this conversation as resolved.
Show resolved Hide resolved
<label for="search_field">Select search field:</label>
<select id="search_field" name="search_field">
<option value="sample_barcodes">Barcode</option>
<option value="kit_ids">Kit ID</option>
<option value="emails">Email</option>
<option value="outbound_tracking_numbers">Outbound Tracking Number</option>
<option value="inbound_tracking_numbers">Inbound Tracking Number</option>
</select>
</td>
</tr>
<tr>
cassidysymons marked this conversation as resolved.
Show resolved Hide resolved
<td colspan=3 style="text-align:left;padding:4px">
cassidysymons marked this conversation as resolved.
Show resolved Hide resolved
<input type="text" name="single_search" placeholder="Enter value here" id="single_search">
cassidysymons marked this conversation as resolved.
Show resolved Hide resolved
</td>
</tr>
<tr>
cassidysymons marked this conversation as resolved.
Show resolved Hide resolved
<td colspan=3 style="text-align:left;padding:4px">
cassidysymons marked this conversation as resolved.
Show resolved Hide resolved
<input type="file" name="upload_list" id="upload_list">
cassidysymons marked this conversation as resolved.
Show resolved Hide resolved
</td>
</tr>
<tr>
<td colspan=3 style="text-align:right;padding:4px">
cassidysymons marked this conversation as resolved.
Show resolved Hide resolved
<input type="submit" value="Retrieve">
</td>
</tr>
<tr><td colspan=4></td></tr>
<tr><td colspan=4 style="text-align:center;padding:4px"><i>Barcodes must be listed in column "sample_name"<br>(max: 1000)</i> </td></tr>
<tr><td colspan=4></td></tr>
<tr>
<td colspan=3> <label for="strip_sampleid"> Check to remove sample IDs from summary</label> </td>
<td colspan=1 style="text-align:center;padding:4px"> <input type="checkbox" id="strip_sampleid" name="strip_sampleid"> </td>
<td colspan=3><label for="strip_sampleid">Check to remove sample IDs from summary</label></td>
<td colspan=1 style="text-align:center;padding:4px">
<input type="checkbox" id="strip_sampleid" name="strip_sampleid">
</td>
</tr>
</table>
</form>
Expand Down
Loading