Skip to content

Commit a91a6fd

Browse files
authored
Merge pull request #2064 from antgonza/fix-1959
fix #1959
2 parents f3c1216 + 4b19b45 commit a91a6fd

File tree

9 files changed

+136
-84
lines changed

9 files changed

+136
-84
lines changed

qiita_pet/handlers/api_proxy/prep_template.py

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,8 @@ def prep_template_summary_get_req(prep_id, user_id):
299299
Format {'status': status,
300300
'message': message,
301301
'num_samples': value,
302-
'category': [(val1, count1), (val2, count2), ...], ...}
302+
'category': [(val1, count1), (val2, count2), ...],
303+
'editable': bool}
303304
"""
304305
exists = _check_prep_template_exists(int(prep_id))
305306
if exists['status'] != 'success':
@@ -309,17 +310,21 @@ def prep_template_summary_get_req(prep_id, user_id):
309310
access_error = check_access(prep.study_id, user_id)
310311
if access_error:
311312
return access_error
313+
314+
editable = Study(prep.study_id).can_edit(User(user_id))
312315
df = prep.to_dataframe()
313316
out = {'num_samples': df.shape[0],
314-
'summary': {},
317+
'summary': [],
315318
'status': 'success',
316-
'message': ''}
319+
'message': '',
320+
'editable': editable}
317321

318-
cols = list(df.columns)
322+
cols = sorted(list(df.columns))
319323
for column in cols:
320324
counts = df[column].value_counts()
321-
out['summary'][str(column)] = [(str(key), counts[key])
322-
for key in natsorted(counts.index)]
325+
out['summary'].append(
326+
(str(column), [(str(key), counts[key])
327+
for key in natsorted(counts.index)]))
323328
return out
324329

325330

@@ -417,10 +422,11 @@ def prep_template_patch_req(user_id, req_op, req_path, req_value=None,
417422
418423
Returns
419424
-------
420-
dict of {str, str}
425+
dict of {str, str, str}
421426
A dictionary with the following keys:
422427
- status: str, whether if the request is successful or not
423428
- message: str, if the request is unsuccessful, a human readable error
429+
- row_id: str, the row_id that we tried to delete
424430
"""
425431
req_path = [v for v in req_path.split('/') if v]
426432
if req_op == 'replace':
@@ -458,13 +464,15 @@ def prep_template_patch_req(user_id, req_op, req_path, req_value=None,
458464

459465
return {'status': status, 'message': msg}
460466
elif req_op == 'remove':
461-
# The structure of the path should be /prep_id/{columns|samples}/name
462-
if len(req_path) != 3:
467+
# The structure of the path should be:
468+
# /prep_id/row_id/{columns|samples}/name
469+
if len(req_path) != 4:
463470
return {'status': 'error',
464471
'message': 'Incorrect path parameter'}
465472
prep_id = int(req_path[0])
466-
attribute = req_path[1]
467-
attr_id = req_path[2]
473+
row_id = req_path[1]
474+
attribute = req_path[2]
475+
attr_id = req_path[3]
468476

469477
# Check if the user actually has access to the study
470478
pt = PrepTemplate(prep_id)
@@ -478,12 +486,13 @@ def prep_template_patch_req(user_id, req_op, req_path, req_value=None,
478486
# Store the job id attaching it to the sample template id
479487
r_client.set(PREP_TEMPLATE_KEY_FORMAT % prep_id,
480488
dumps({'job_id': job_id, 'is_qiita_job': False}))
481-
return {'status': 'success', 'message': ''}
489+
return {'status': 'success', 'message': '', 'row_id': row_id}
482490
else:
483491
return {'status': 'error',
484492
'message': 'Operation "%s" not supported. '
485493
'Current supported operations: replace, remove'
486-
% req_op}
494+
% req_op,
495+
'row_id': '0'}
487496

488497

489498
def prep_template_samples_get_req(prep_id, user_id):

qiita_pet/handlers/api_proxy/sample_template.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -521,13 +521,15 @@ def sample_template_patch_request(user_id, req_op, req_path, req_value=None,
521521
if req_op == 'remove':
522522
req_path = [v for v in req_path.split('/') if v]
523523

524-
if len(req_path) != 3:
524+
# format: study_id/row_id/column|sample/attribute_id
525+
if len(req_path) != 4:
525526
return {'status': 'error',
526527
'message': 'Incorrect path parameter'}
527528

528529
st_id = req_path[0]
529-
attribute = req_path[1]
530-
attr_id = req_path[2]
530+
row_id = req_path[1]
531+
attribute = req_path[2]
532+
attr_id = req_path[3]
531533

532534
# Check if the user actually has access to the template
533535
st = SampleTemplate(st_id)
@@ -542,9 +544,10 @@ def sample_template_patch_request(user_id, req_op, req_path, req_value=None,
542544
r_client.set(SAMPLE_TEMPLATE_KEY_FORMAT % st_id,
543545
dumps({'job_id': job_id}))
544546

545-
return {'status': 'success', 'message': ''}
547+
return {'status': 'success', 'message': '', 'row_id': row_id}
546548

547549
else:
548550
return {'status': 'error',
549551
'message': 'Operation "%s" not supported. '
550-
'Current supported operations: remove' % req_op}
552+
'Current supported operations: remove' % req_op,
553+
'row_id': 0}

qiita_pet/handlers/api_proxy/tests/test_prep_template.py

Lines changed: 45 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -206,40 +206,9 @@ def test_prep_template_graph_get_req_no_exists(self):
206206

207207
def test_prep_template_summary_get_req(self):
208208
obs = prep_template_summary_get_req(1, 'test@foo.bar')
209-
exp = {'summary': {
210-
'experiment_center': [('ANL', 27)],
211-
'center_name': [('ANL', 27)],
212-
'run_center': [('ANL', 27)],
213-
'run_prefix': [('s_G1_L001_sequences', 27)],
214-
'primer': [('GTGCCAGCMGCCGCGGTAA', 27)],
215-
'target_gene': [('16S rRNA', 27)],
216-
'sequencing_meth': [('Sequencing by synthesis', 27)],
217-
'run_date': [('8/1/12', 27)],
218-
'platform': [('Illumina', 27)],
219-
'pcr_primers': [('FWD:GTGCCAGCMGCCGCGGTAA; '
220-
'REV:GGACTACHVGGGTWTCTAAT', 27)],
221-
'library_construction_protocol': [(
222-
'This analysis was done as in Caporaso et al 2011 Genome '
223-
'research. The PCR primers (F515/R806) were developed against '
224-
'the V4 region of the 16S rRNA (both bacteria and archaea), '
225-
'which we determined would yield optimal community clustering '
226-
'with reads of this length using a procedure similar to that '
227-
'of ref. 15. [For reference, this primer pair amplifies the '
228-
'region 533_786 in the Escherichia coli strain 83972 sequence '
229-
'(greengenes accession no. prokMSA_id:470367).] The reverse '
230-
'PCR primer is barcoded with a 12-base error-correcting Golay '
231-
'code to facilitate multiplexing of up to 1,500 samples per '
232-
'lane, and both PCR primers contain sequencer adapter '
233-
'regions.', 27)],
234-
'experiment_design_description': [(
235-
'micro biome of soil and rhizosphere of cannabis plants from '
236-
'CA', 27)],
237-
'study_center': [('CCME', 27)],
238-
'center_project_name': [],
239-
'sample_center': [('ANL', 27)],
240-
'samp_size': [('.25,g', 27)],
241-
'qiita_prep_id': [('1', 27)],
242-
'barcode': [
209+
exp = {
210+
'status': 'success', 'message': '',
211+
'summary': [('barcode', [
243212
('AACTCCTGTGGA', 1), ('ACCTCAGTCAAG', 1), ('ACGCACATACAA', 1),
244213
('AGCAGGCACGAA', 1), ('AGCGCTCACATC', 1), ('ATATCGCGATGA', 1),
245214
('ATGGCCTGACTA', 1), ('CATACACGCACC', 1), ('CCACCCAGTAAC', 1),
@@ -248,15 +217,44 @@ def test_prep_template_summary_get_req(self):
248217
('CGTAGAGCTCTC', 1), ('CGTGCACAATTG', 1), ('GATAGCACTCGT', 1),
249218
('GCGGACTATTCA', 1), ('GTCCGCAAGTTA', 1), ('TAATGGTCGTAG', 1),
250219
('TAGCGCGAACTT', 1), ('TCGACCAAACAC', 1), ('TGAGTGGTCTGT', 1),
251-
('TGCTACAGACGT', 1), ('TGGTTATGGCAC', 1), ('TTGCACCGTCGA', 1)],
252-
'emp_status': [('EMP', 27)],
253-
'illumina_technology': [('MiSeq', 27)],
254-
'experiment_title': [('Cannabis Soil Microbiome', 27)],
255-
'target_subfragment': [('V4', 27)],
256-
'instrument_model': [('Illumina MiSeq', 27)]},
257-
'num_samples': 27,
258-
'status': 'success',
259-
'message': ''}
220+
('TGCTACAGACGT', 1), ('TGGTTATGGCAC', 1), ('TTGCACCGTCGA', 1)
221+
]), ('center_name', [('ANL', 27)]), ('center_project_name', []),
222+
('emp_status', [('EMP', 27)]),
223+
('experiment_center', [('ANL', 27)]),
224+
('experiment_design_description', [
225+
('micro biome of soil and rhizosphere of cannabis plants '
226+
'from CA', 27)]),
227+
('experiment_title', [('Cannabis Soil Microbiome', 27)]),
228+
('illumina_technology', [('MiSeq', 27)]),
229+
('instrument_model', [('Illumina MiSeq', 27)]),
230+
('library_construction_protocol', [
231+
('This analysis was done as in Caporaso et al 2011 Genome '
232+
'research. The PCR primers (F515/R806) were developed '
233+
'against the V4 region of the 16S rRNA (both bacteria '
234+
'and archaea), which we determined would yield optimal '
235+
'community clustering with reads of this length using a '
236+
'procedure similar to that of ref. 15. [For reference, '
237+
'this primer pair amplifies the region 533_786 in the '
238+
'Escherichia coli strain 83972 sequence (greengenes '
239+
'accession no. prokMSA_id:470367).] The reverse PCR '
240+
'primer is barcoded with a 12-base error-correcting '
241+
'Golay code to facilitate multiplexing of up to 1,500 '
242+
'samples per lane, and both PCR primers contain '
243+
'sequencer adapter regions.', 27)]),
244+
('pcr_primers', [(
245+
'FWD:GTGCCAGCMGCCGCGGTAA; REV:GGACTACHVGGGTWTCTAAT', 27)]),
246+
('platform', [('Illumina', 27)]),
247+
('primer', [('GTGCCAGCMGCCGCGGTAA', 27)]),
248+
('qiita_prep_id', [('1', 27)]), ('run_center', [('ANL', 27)]),
249+
('run_date', [('8/1/12', 27)]),
250+
('run_prefix', [('s_G1_L001_sequences', 27)]),
251+
('samp_size', [('.25,g', 27)]),
252+
('sample_center', [('ANL', 27)]),
253+
('sequencing_meth', [('Sequencing by synthesis', 27)]),
254+
('study_center', [('CCME', 27)]),
255+
('target_gene', [('16S rRNA', 27)]),
256+
('target_subfragment', [('V4', 27)])],
257+
'editable': True, 'num_samples': 27}
260258
self.assertEqual(obs, exp)
261259

262260
def test_prep_template_summary_get_req_no_access(self):
@@ -476,8 +474,8 @@ def test_prep_template_patch_req(self):
476474
# Delete a prep template column
477475
obs = prep_template_patch_req(
478476
'test@foo.bar', 'remove',
479-
'/%s/columns/target_subfragment/' % pt.id)
480-
exp = {'status': 'success', 'message': ''}
477+
'/%s/10/columns/target_subfragment/' % pt.id)
478+
exp = {'status': 'success', 'message': '', 'row_id': '10'}
481479
self.assertEqual(obs, exp)
482480
self._wait_for_parallel_job('prep_template_%s' % pt.id)
483481
self.assertNotIn('target_subfragment', pt.categories())
@@ -489,7 +487,8 @@ def test_prep_template_patch_req(self):
489487
'Cancer Genomics')
490488
exp = {'status': 'error',
491489
'message': 'Operation "add" not supported. '
492-
'Current supported operations: replace, remove'}
490+
'Current supported operations: replace, remove',
491+
'row_id': '0'}
493492
self.assertEqual(obs, exp)
494493
# Incorrect path parameter
495494
obs = prep_template_patch_req(

qiita_pet/handlers/api_proxy/tests/test_sample_template.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -525,28 +525,28 @@ def test_sample_template_meta_cats_get_req_no_template(self):
525525
def test_sample_template_patch_request(self):
526526
# Wrong operation operation
527527
obs = sample_template_patch_request(
528-
"test@foo.bar", "add", "/1/columns/season_environment/")
528+
"test@foo.bar", "add", "/1/10/columns/season_environment/")
529529
exp = {'status': 'error',
530530
'message': 'Operation "add" not supported. '
531-
'Current supported operations: remove'}
531+
'Current supported operations: remove',
532+
'row_id': 0}
532533
self.assertEqual(obs, exp)
533534
# Wrong path parameter
534535
obs = sample_template_patch_request(
535-
"test@foo.bar", "remove", "/columns/season_environment/")
536+
"test@foo.bar", "remove", "10/columns/season_environment/")
536537
exp = {'status': 'error',
537538
'message': 'Incorrect path parameter'}
538539
self.assertEqual(obs, exp)
539540
# No access
540541
obs = sample_template_patch_request(
541-
"demo@microbio.me", "remove", "/1/columns/season_environment/")
542+
"demo@microbio.me", "remove", "/1/10/columns/season_environment/")
542543
exp = {'status': 'error',
543544
'message': 'User does not have access to study'}
544545
self.assertEqual(obs, exp)
545546
# Success
546547
obs = sample_template_patch_request(
547-
"test@foo.bar", "remove", "/1/columns/season_environment/")
548-
exp = {'status': 'success',
549-
'message': ''}
548+
"test@foo.bar", "remove", "/1/10/columns/season_environment/")
549+
exp = {'status': 'success', 'message': '', 'row_id': '10'}
550550
self.assertEqual(obs, exp)
551551

552552
# This is needed so the clean up works - this is a distributed system

qiita_pet/handlers/study_handlers/prep_template.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,26 @@ class PrepTemplateSummaryAJAX(BaseHandler):
4444
@authenticated
4545
def get(self):
4646
prep_id = to_int(self.get_argument('prep_id'))
47+
4748
res = prep_template_summary_get_req(prep_id, self.current_user.id)
49+
4850
self.render('study_ajax/prep_summary_table.html', pid=prep_id,
49-
stats=res['summary'])
51+
stats=res['summary'], editable=res['editable'])
5052

5153

5254
class PrepTemplateAJAX(BaseHandler):
5355
@authenticated
5456
def get(self):
5557
"""Send formatted summary page of prep template"""
5658
prep_id = to_int(self.get_argument('prep_id'))
59+
row_id = self.get_argument('row_id', '0')
5760

5861
res = prep_template_ajax_get_req(self.current_user.id, prep_id)
5962
res['prep_id'] = prep_id
63+
res['row_id'] = row_id
6064
# Escape the message just in case javascript breaking characters in it
6165
res['alert_message'] = url_escape(res['alert_message'])
66+
6267
self.render('study_ajax/prep_summary.html', **res)
6368

6469

qiita_pet/handlers/study_handlers/sample_template.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ class SampleTemplateAJAX(BaseHandler):
7474
def get(self):
7575
"""Send formatted summary page of sample template"""
7676
study_id = self.get_argument('study_id')
77+
row_id = self.get_argument('row_id', '0')
78+
7779
files = [f for _, f in get_files_from_uploads_folders(study_id)
7880
if f.endswith(('txt', 'tsv'))]
7981
data_types = sorted(data_types_get_req()['data_types'])
@@ -95,6 +97,7 @@ def get(self):
9597
stats['files'] = files
9698
stats['study_id'] = study_id
9799
stats['data_types'] = data_types
100+
stats['row_id'] = row_id
98101
# URL encode in case message has javascript-breaking characters in it
99102
stats['alert_message'] = url_escape(stats['alert_message'])
100103
self.render('study_ajax/sample_summary.html', **stats)

qiita_pet/templates/study_ajax/prep_summary.html

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,18 +181,18 @@
181181
* prep information
182182
*
183183
*/
184-
function delete_prep_column(prep_id, column_name) {
184+
function delete_prep_column(prep_id, column_name, row_id) {
185185
if(confirm("Are you sure you want to delete '" + column_name + "' information?")) {
186186
$.ajax({
187187
url: '{% raw qiita_config.portal_dir %}/prep_template/',
188188
type: 'PATCH',
189-
data: {'op': 'remove', 'path': '/' + prep_id + '/columns/' + column_name},
189+
data: {'op': 'remove', 'path': '/' + prep_id + '/' + row_id + '/columns/' + column_name},
190190
success: function(data) {
191191
if(data.status == 'error') {
192192
bootstrapAlert(data.message, "danger");
193193
}
194194
else {
195-
populate_main_div('/study/description/prep_template/', { prep_id: prep_id, study_id: {{study_id}} });
195+
populate_main_div('/study/description/prep_template/', { prep_id: prep_id, study_id: {{study_id}}, row_id: row_id });
196196
}
197197
}
198198
});
@@ -329,6 +329,22 @@
329329
}
330330
}
331331

332+
/*
333+
* Autoscroll prep info list
334+
*
335+
* This is a helper function so we can scroll once the prep table is ready
336+
*/
337+
function autoscroll_prep_list() {
338+
// taken from: http://stackoverflow.com/a/2906009
339+
if ({{row_id}} > 1) {
340+
var container = $("html, body"), scrollTo = $("#row_{{row_id}}");
341+
342+
container.animate({
343+
scrollTop: scrollTo.offset().top - container.offset().top + container.scrollTop()
344+
});
345+
}
346+
}
347+
332348
$(document).ready(function () {
333349
if("{{investigation_type}}" !== "None") {
334350
// The prep information already has an investigation type
@@ -402,6 +418,8 @@
402418
{% else %}
403419
$('#alert-message').alert('close');
404420
{% end %}
421+
422+
405423
});
406424
</script>
407425

qiita_pet/templates/study_ajax/prep_summary_table.html

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1+
<script type="text/javascript">
2+
$(document).ready(function () {
3+
autoscroll_prep_list();
4+
});
5+
</script>
6+
7+
18
{% from future.utils import viewitems %}
29
<div class="panel panel-default">
310
<div class="panel-heading">
411
Information summary
512
</div>
613
<div id="summary-table-div">
714
<table class="table">
8-
{% for category, summary in viewitems(stats) %}
9-
<tr>
15+
{% for i, (category, summary) in enumerate(stats, -1) %}
16+
<tr id="row_{{i}}">
1017
<td>
11-
<a class="btn btn-danger" onclick="delete_prep_column({{pid}}, '{{category}}');"><span class="glyphicon glyphicon-trash"></span></a>
18+
<a class="btn btn-danger" onclick="delete_prep_column({{pid}}, '{{category}}', {{i}});"><span class="glyphicon glyphicon-trash"></span></a>
1219
</td>
1320
{% if len(summary) == 1 %}
1421
<td colspan="2">

0 commit comments

Comments
 (0)