Skip to content

Commit

Permalink
Merge pull request #102 from ayobi/vocab_samples_issues
Browse files Browse the repository at this point in the history
vocab for sample issues
  • Loading branch information
cassidysymons authored Jul 30, 2024
2 parents a709df5 + 27491cf commit c43e8fa
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 36 deletions.
62 changes: 40 additions & 22 deletions microsetta_admin/server.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import jwt
from flask import render_template, Flask, request, session, send_file
from flask import render_template, Flask, request, session, send_file, url_for
import secrets
from datetime import datetime
import io
Expand Down Expand Up @@ -582,10 +582,10 @@ def _check_sample_status(extended_barcode_info):
# GET to view the page,
# POST to update info for a barcode -AND (possibly)-
# email end user about the change in sample status,
def _scan_get(sample_barcode, update_error):
def _scan_get(sample_barcode, update_error, observations):
# If there is no sample_barcode in the GET
# they still need to enter one in the box, so show empty page
if sample_barcode is None:
if sample_barcode is None and observations is None:
return render_template('scan.html', **build_login_variables())

# Assuming there is a sample barcode, grab that sample's information
Expand Down Expand Up @@ -629,7 +629,8 @@ def _scan_get(sample_barcode, update_error):
update_error=update_error,
received_type_dropdown=RECEIVED_TYPE_DROPDOWN,
source=result['source'],
events=events
events=events,
observations=observations
)
elif status == 401:
# If we fail due to unauthorized, need the user to log in again
Expand All @@ -655,7 +656,8 @@ def _scan_post_update_info(sample_barcode,
issue_type,
template,
received_type,
recorded_type):
recorded_type,
observations):

###
# Bugfix Part 1 for duplicate emails being sent. Theory is that client is
Expand All @@ -673,26 +675,26 @@ def _scan_post_update_info(sample_barcode,
if result['latest_scan']:
latest_status = result['latest_scan']['sample_status']
###

# Do the actual update
status, response = APIRequest.post(
'/api/admin/scan/%s' % sample_barcode,
json={
"sample_status": sample_status,
"technician_notes": technician_notes
"technician_notes": technician_notes,
"observations": observations
}
)

# if the update failed, keep track of the error so it can be displayed
if status != 201:
update_error = response
return _scan_get(sample_barcode, update_error)
return _scan_get(sample_barcode, update_error, observations)
else:
update_error = None

# If we're not supposed to send an email, go back to GET
if action != "send_email":
return _scan_get(sample_barcode, update_error)
return _scan_get(sample_barcode, update_error, observations)

###
# Bugfix Part 2 for duplicate emails being sent.
Expand All @@ -702,15 +704,15 @@ def _scan_post_update_info(sample_barcode,
update_error = "Ignoring Send Email, sample_status would " \
"not have been updated (Displayed page was out of " \
"sync)"
return _scan_get(sample_barcode, update_error)
return _scan_get(sample_barcode, update_error, observations)
###

# This is what we'll hit if there are no email templates to send for
# the new sample status (or if we screw up javascript side :D )
if template is None:
update_error = "Cannot Send Email: No Issue Type Specified " \
"(or no issue types available)"
return _scan_get(sample_barcode, update_error)
return _scan_get(sample_barcode, update_error, observations)

# Otherwise, send out an email to the end user
status, response = APIRequest.post(
Expand All @@ -733,7 +735,13 @@ def _scan_post_update_info(sample_barcode,
else:
update_error = None

return _scan_get(sample_barcode, update_error)
return _scan_get(sample_barcode, update_error, observations)


def get_observations(sample_barcode):
status, result = APIRequest.get('/api/admin/scan/observations/%s'
% sample_barcode)
return result


@app.route('/scan', methods=['GET', 'POST'])
Expand All @@ -745,7 +753,14 @@ def scan():
# form parameters
if request.method == 'GET':
sample_barcode = request.args.get('sample_barcode')
return _scan_get(sample_barcode, None)
update_error = None

if sample_barcode is not None:
observations = get_observations(sample_barcode)
else:
observations = None

return _scan_get(sample_barcode, update_error, observations)

# If its a post, make the changes, then refresh the page
if request.method == 'POST':
Expand All @@ -763,15 +778,18 @@ def scan():
template = request.form.get('template')
received_type = request.form.get('received_type')
recorded_type = request.form.get('recorded_type')

return _scan_post_update_info(sample_barcode,
technician_notes,
sample_status,
action,
issue_type,
template,
received_type,
recorded_type)
observations = request.form.getlist('observation_id')

_scan_post_update_info(sample_barcode,
technician_notes,
sample_status,
action,
issue_type,
template,
received_type,
recorded_type,
observations)
return redirect(url_for('scan', sample_barcode=sample_barcode))


@app.route('/metadata_pulldown', methods=['GET', 'POST'])
Expand Down
41 changes: 33 additions & 8 deletions microsetta_admin/templates/scan.html
Original file line number Diff line number Diff line change
Expand Up @@ -247,16 +247,25 @@ <h4>Scan History</h4>
<th class="bordered">Scan Timestamp</th>
<th class="bordered">Sample Status</th>
<th class="bordered">Technician Notes</th>
<th class="bordered">Observations</th>
</tr>
</thead>
<tbody>
{% for scan in scans_info %}
<tr>
<td class="bordered">{{ format_timestamp(scan['scan_timestamp']) }}</td>
<td class="bordered">{{ scan['sample_status'] }}</td>
<td class="bordered">{{ scan['technician_notes'] }}</td>
</tr>
{% endfor %}
{% for scan in scans_info %}
<tr>
<td class="bordered">{{ format_timestamp(scan['scan_timestamp']) }}</td>
<td class="bordered">{{ scan['sample_status'] }}</td>
<td class="bordered">{{ scan['technician_notes'] }}</td>
<td class="bordered">
{% for observation in scan['observations'] %}
{% if observation['category'] %}
{{ observation['category'] }}: {{ observation['observation'] }}{% if not loop.last %}, {% endif %}
{% else %}
{{ observation['observation'] }}
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
Expand Down Expand Up @@ -305,6 +314,22 @@ <h4>Scan History</h4>
</td>
</tr>
<!-- End collapsible email template fields -->
{% if observations %}
<tr>
<td>Observations:</td>
<td>
{% set categories = observations|map(attribute='category')|unique %}
{% for category in categories %}
<b>{{ category }}</b><br>
{% for observation in observations if observation['category'] == category %}
<input type="checkbox" id="{{ observation['observation_id'] }}" name="observation_id" value="{{ observation['observation_id'] }}">
<label for="{{ observation['observation_id'] }}">{{ observation['observation'] }}</label><br>
{% endfor %}
{% endfor %}
</td>
</tr>
{% endif %}

<tr>
<td>Technician Notes: </td>
<td>
Expand Down Expand Up @@ -353,4 +378,4 @@ <h4>Event Log</h4>
</table>
{% endif %}
</div>
{% endblock %}
{% endblock %}
57 changes: 51 additions & 6 deletions microsetta_admin/tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,22 @@ def test_scan_specific_no_warnings(self):
"account": {'id': 'd8592c74-9694-2135-e040-8a80115d6401'}
}

resp2 = {
"barcode_info": {"barcode": "000004216"},
"projects_info": [],
"scans_info": [],
"latest_scan": None,
"sample": {'site': 'baz'},
"source": {'name': 'a source a name',
'source_type': 'human',
'source_data': {'description': None}},
"account": {'id': 'd8592c74-9694-2135-e040-8a80115d6401'}
}

api_get_1 = DummyResponse(200, resp1)
api_get_2 = DummyResponse(200, [])
self.mock_get.side_effect = [api_get_1, api_get_2]
api_get_2 = DummyResponse(200, resp2)
api_get_3 = DummyResponse(200, [])
self.mock_get.side_effect = [api_get_1, api_get_2, api_get_3]

response = self.app.get('/scan?sample_barcode=000004216',
follow_redirects=True)
Expand All @@ -232,9 +245,27 @@ def test_scan_specific_no_collection_info_warning(self):
'source_data': {'description': None}},
}

resp2 = {
"barcode_info": {"barcode": "000004216"},
"projects_info": [{
"project": "American Gut Project",
"is_microsetta": True,
"bank_samples": False,
"plating_start_date": None
}],
"scans_info": [],
"latest_scan": None,
"sample": {'datetime_collected': None},
"account": {'id': "ThizIzNotReal"},
"source": {'name': 'a source a name',
'source_type': 'human',
'source_data': {'description': None}},
}

api_get_1 = DummyResponse(200, resp1)
api_get_2 = DummyResponse(200, [])
self.mock_get.side_effect = [api_get_1, api_get_2]
api_get_2 = DummyResponse(200, resp2)
api_get_3 = DummyResponse(200, [])
self.mock_get.side_effect = [api_get_1, api_get_2, api_get_3]

response = self.app.get('/scan?sample_barcode=000004216',
follow_redirects=True)
Expand All @@ -257,9 +288,23 @@ def test_scan_specific_no_associated_source_warning(self):
"account": {"id": "foo"},
"source": None}

resp2 = {"barcode_info": {"barcode": "000004216"},
"projects_info": [{
"project": "American Gut Project",
"is_microsetta": True,
"bank_samples": False,
"plating_start_date": None
}],
"scans_info": [],
"latest_scan": None,
"sample": None,
"account": {"id": "foo"},
"source": None}

api_get_1 = DummyResponse(200, resp1)
api_get_2 = DummyResponse(200, [])
self.mock_get.side_effect = [api_get_1, api_get_2]
api_get_2 = DummyResponse(200, resp2)
api_get_3 = DummyResponse(200, [])
self.mock_get.side_effect = [api_get_1, api_get_2, api_get_3]

response = self.app.get('/scan?sample_barcode=000004216',
follow_redirects=True)
Expand Down

0 comments on commit c43e8fa

Please sign in to comment.