From 4da7caa3c0edd20ba6a2a283f914356d4cf0016c Mon Sep 17 00:00:00 2001 From: ayobi Date: Wed, 2 Oct 2024 22:32:51 -0400 Subject: [PATCH 1/6] added new fields to sample summary --- microsetta_admin/server.py | 111 ++++++++++-------- .../templates/per_sample_summary.html | 61 ++++++---- 2 files changed, 102 insertions(+), 70 deletions(-) diff --git a/microsetta_admin/server.py b/microsetta_admin/server.py index c949a29..dbae28c 100644 --- a/microsetta_admin/server.py +++ b/microsetta_admin/server.py @@ -406,58 +406,75 @@ def per_sample_summary(): # 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}]) - - # 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) - - if status == 200: - if result['partial_result'] is True: - unprocessed_barcodes = result['unprocessed_barcodes'] + search_field = request.form.get('search_field') + search_value = request.form.get('text_input') + uploaded_file = request.files.get('file') + + if uploaded_file: + search_values, err = \ + upload_util.parse_request_csv_col(request, + 'file', + search_field) + 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}]) 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] - - 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()) + search_values = [search_value] if search_value else [] + + payload = {} + if search_field == 'sample_barcode': + payload['sample_barcodes'] = search_values + elif search_field == 'kit_id': + payload['kit_ids'] = search_values + elif search_field == 'email': + payload['emails'] = search_values + elif search_field == 'outbound_tracking': + payload['outbound_tracking_numbers'] = search_values + elif search_field == 'inbound_tracking': + payload['inbound_tracking_numbers'] = 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']) + 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] + + 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): diff --git a/microsetta_admin/templates/per_sample_summary.html b/microsetta_admin/templates/per_sample_summary.html index 3b06ab1..f3b466e 100644 --- a/microsetta_admin/templates/per_sample_summary.html +++ b/microsetta_admin/templates/per_sample_summary.html @@ -27,36 +27,51 @@ {% block content %}

Sample Summaries


-
Retrieve summary for a single sample
+{% if error_message %} +

+ {{ error_message |e }} +

+{% endif %}
- {% if error_message %} -

- {{ error_message |e }} -

- {% endif %} -
- - - - - -
- -
-
-
Retrieve summaries using a csv file
-
+
Retrieve summary for a sample
+ - - + + + + + + + + + - + - - + +
+ + +
+ + + +
Barcodes must be listed in column "sample_name"
(max: 1000)
The selected search field must be in column "sample_name"
(max: 1000)
+ +
From 0df4dd14d3a2b0aee8e97d31291d6d3ae09f0679 Mon Sep 17 00:00:00 2001 From: ayobi Date: Wed, 2 Oct 2024 22:37:26 -0400 Subject: [PATCH 2/6] lint --- microsetta_admin/server.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/microsetta_admin/server.py b/microsetta_admin/server.py index dbae28c..095a3d3 100644 --- a/microsetta_admin/server.py +++ b/microsetta_admin/server.py @@ -401,10 +401,6 @@ 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: search_field = request.form.get('search_field') search_value = request.form.get('text_input') From 15c020c08fb823d684a67a58659949e1b792000b Mon Sep 17 00:00:00 2001 From: ayobi Date: Mon, 21 Oct 2024 20:03:28 -0300 Subject: [PATCH 3/6] add csv handling for sample summaries --- microsetta_admin/server.py | 39 +++++++++++-------- .../templates/per_sample_summary.html | 32 ++++++++++----- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/microsetta_admin/server.py b/microsetta_admin/server.py index 095a3d3..e3439a9 100644 --- a/microsetta_admin/server.py +++ b/microsetta_admin/server.py @@ -1,3 +1,4 @@ +import csv import jwt from flask import render_template, Flask, request, session, send_file, url_for import secrets @@ -406,18 +407,15 @@ def per_sample_summary(): search_value = request.form.get('text_input') uploaded_file = request.files.get('file') + search_values = [] + if uploaded_file: - search_values, err = \ - upload_util.parse_request_csv_col(request, - 'file', - search_field) - 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}]) + 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: search_values = [search_value] if search_value else [] @@ -445,12 +443,19 @@ def per_sample_summary(): 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] + if not resource.empty: + 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] + 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', diff --git a/microsetta_admin/templates/per_sample_summary.html b/microsetta_admin/templates/per_sample_summary.html index f3b466e..6786fa5 100644 --- a/microsetta_admin/templates/per_sample_summary.html +++ b/microsetta_admin/templates/per_sample_summary.html @@ -11,6 +11,21 @@ block.innerHTML = ""; } }; + + function handleFormSubmit(event) { + var fileInput = document.getElementById('file'); + var textInput = document.getElementById('text_input'); + + if (fileInput.files.length > 0 || textInput.value.trim() !== "") { + remove_error_messages(); + return true; + } else { + alert('Please provide either a file or text input.'); + event.preventDefault(); + return false; + } + } + $(document).ready(function() { {% if resource is not none %} $('#search_results').DataTable({ @@ -34,12 +49,12 @@

Sample Summaries

{% endif %}
Retrieve summary for a sample
-
+ - + - - + - + + From 8a1d7c3d597ca5c6b566c12295e0a280b9251c32 Mon Sep 17 00:00:00 2001 From: ayobi Date: Mon, 28 Oct 2024 17:03:58 -0300 Subject: [PATCH 4/6] changes based on feedback --- microsetta_admin/server.py | 25 +++++++------- .../templates/per_sample_summary.html | 34 ++++++++++--------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/microsetta_admin/server.py b/microsetta_admin/server.py index e3439a9..f1530d4 100644 --- a/microsetta_admin/server.py +++ b/microsetta_admin/server.py @@ -404,8 +404,8 @@ def per_sample_summary(): **build_login_variables()) else: search_field = request.form.get('search_field') - search_value = request.form.get('text_input') - uploaded_file = request.files.get('file') + search_value = request.form.get('single_search') + uploaded_file = request.files.get('upload_list') search_values = [] @@ -420,16 +420,7 @@ def per_sample_summary(): search_values = [search_value] if search_value else [] payload = {} - if search_field == 'sample_barcode': - payload['sample_barcodes'] = search_values - elif search_field == 'kit_id': - payload['kit_ids'] = search_values - elif search_field == 'email': - payload['emails'] = search_values - elif search_field == 'outbound_tracking': - payload['outbound_tracking_numbers'] = search_values - elif search_field == 'inbound_tracking': - payload['inbound_tracking_numbers'] = search_values + payload[search_field] = search_values # perform the main query. status, result = APIRequest.post('/api/admin/account_barcode_summary?' @@ -447,7 +438,15 @@ def per_sample_summary(): order = ['sampleid', 'project', 'account-email', 'source-type', 'site-sampled', 'sample-date', 'sample-time', 'sample-status', 'sample-received', - 'ffq-taken', 'ffq-complete', 'vioscreen_username'] + '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: diff --git a/microsetta_admin/templates/per_sample_summary.html b/microsetta_admin/templates/per_sample_summary.html index 6786fa5..214281d 100644 --- a/microsetta_admin/templates/per_sample_summary.html +++ b/microsetta_admin/templates/per_sample_summary.html @@ -13,16 +13,20 @@ }; function handleFormSubmit(event) { - var fileInput = document.getElementById('file'); - var textInput = document.getElementById('text_input'); + var fileInput = document.getElementById('upload_list'); + var textInput = document.getElementById('single_search'); - if (fileInput.files.length > 0 || textInput.value.trim() !== "") { - remove_error_messages(); - return true; - } else { - alert('Please provide either a file or text input.'); + if (fileInput.files.length > 0 && textInput.value.trim() !== "") { + alert("Please provide either a text input or a file, not both."); + event.preventDefault(); + return false; + } else if (fileInput.files.length === 0 && textInput.value.trim() === "") { + alert("Please provide either a text input or a file."); event.preventDefault(); return false; + } else { + remove_error_messages(); + return true; } } @@ -55,22 +59,22 @@
Retrieve summary for a sample
@@ -79,8 +83,6 @@
Retrieve summary for a sample
- -
- @@ -48,20 +63,19 @@
Retrieve summary for a sample
- -
- +
+
- +
- +
The selected search field must be in column "sample_name"
(max: 1000)
From d4b815fe43896fc746d96b6cc00efc407d15ff28 Mon Sep 17 00:00:00 2001 From: ayobi Date: Mon, 28 Oct 2024 20:54:17 -0300 Subject: [PATCH 5/6] update naming --- microsetta_admin/templates/per_sample_summary.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/microsetta_admin/templates/per_sample_summary.html b/microsetta_admin/templates/per_sample_summary.html index 214281d..3ff3ab6 100644 --- a/microsetta_admin/templates/per_sample_summary.html +++ b/microsetta_admin/templates/per_sample_summary.html @@ -13,14 +13,14 @@ }; function handleFormSubmit(event) { - var fileInput = document.getElementById('upload_list'); - var textInput = document.getElementById('single_search'); + var uploadList = document.getElementById('upload_list'); + var singleSearch = document.getElementById('single_search'); - if (fileInput.files.length > 0 && textInput.value.trim() !== "") { + 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 (fileInput.files.length === 0 && textInput.value.trim() === "") { + } else if (uploadList.files.length === 0 && singleSearch.value.trim() === "") { alert("Please provide either a text input or a file."); event.preventDefault(); return false; From d23cd5cf5cf85dd9fd3af98a66dc3cdc72d67869 Mon Sep 17 00:00:00 2001 From: Cassidy Symons <83246693+cassidysymons@users.noreply.github.com> Date: Mon, 28 Oct 2024 17:18:05 -0700 Subject: [PATCH 6/6] Apply suggestions from code review --- microsetta_admin/templates/per_sample_summary.html | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/microsetta_admin/templates/per_sample_summary.html b/microsetta_admin/templates/per_sample_summary.html index 3ff3ab6..be90368 100644 --- a/microsetta_admin/templates/per_sample_summary.html +++ b/microsetta_admin/templates/per_sample_summary.html @@ -56,7 +56,7 @@
Retrieve summary for a sample
- + - + - -
+
 
- + + Single Value Search:
-- OR --
- + + Upload List:
+