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

Import gff ui #16

Merged
merged 12 commits into from
Nov 17, 2017
Merged

Import gff ui #16

merged 12 commits into from
Nov 17, 2017

Conversation

yaoyuyang
Copy link
Member

Add UI for import gff as genome in the database. Feature includes upload form validation and importing status and link to the uploaded genome after importing is finished.

@yaoyuyang yaoyuyang requested a review from myw November 13, 2017 17:16
@yaoyuyang
Copy link
Member Author

@aruginkgo keep you in the loop. I added the import gff UI here if you want to learn how I added them since I remember at one point you were working on something similar.

Copy link
Contributor

@myw myw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great!
My comments point out some ideas for improvement, some consistency/style points, and some minor errors.

.gitignore Outdated
@@ -64,4 +64,6 @@ test.db*
ncbi/

# compiled static files
static/
src/edge/static/edge/assets
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these lines do not need to be added here. Asset compilation has changed; all compiled assets that should be ignored now go in src/edge/static/edge/assets, the compiled assets are ignored in the other .gitignore file, src/.gitignore (I know, this is confusing; i didn't set this up, I just tried not to break it and keep the boundaries consistent.

these three lines should be removed; my original line should not be added back, however. that was just something i forgot to remove from when i was trying something different.
also, feel free to remove src/edge/static/edge/edge.css in your local tree you won't need it.

var model = $parse(attrs.fileModel);
var modelSetter = model.assign;

element.bind('change', function(){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spaces after closing paren for anon funcs, as above; please make it consistent throughout with whatever the existing convention is

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just use a regular ng-model for this? is it because ngModel doesn't allow you to actually assign to sub-attributes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to get the file in the controller's scope so I can process them easily. I learned this from here. https://www.uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs/
Not sure if this is the best way to do but it works fine.

$scope.add_genome_error = undefined;
$scope.addGenome = function(){
var file = $scope.gffFile;
$scope.add_genome_error = undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should use camelCase here for consistency; pretty much all JS has now moved to this convention.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right! Fixed. i_have_too_much_love_for_snake_case. Ruby was my first love and it has a profound impact on my coding style.

$scope.add_genome_pending = undefined;
$scope.add_genome_result = undefined;
if (!file) {
$scope.add_genome_error = {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can do this with a single object literal: $scope.addGenomeError = { message: 'Need to choose GFF file' }; also, prefer single quotes for consistency

@@ -0,0 +1,10 @@
<header>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well done. This is much cleaner!

response = HttpResponse(content_type='text/plain')
response['Content-Disposition'] = "attachment; filename=\"g%s.gff\"" % genome_id
io.to_gff_file(response)
return response


def genome_import(request):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should stick some REST validation around this, making sure it only gets called on POSTs, etc; you can do this with the @require_POST() decorator or a class-based view that only implements the post method.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good thoughts! It's actually @require_http_methods(["POST"]) https://docs.djangoproject.com/en/1.11/topics/http/decorators/

response = HttpResponse(content_type='text/plain')
response['Content-Disposition'] = "attachment; filename=\"g%s.gff\"" % genome_id
io.to_gff_file(response)
return response


def genome_import(request):
import tempfile
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unless you have a great reason for doing otherwise, it's less confusing IMO to put all imports at the top of a file.

"id": g.id,
"name": g.name,
})
build_genome_blastdb.delay(g.id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should return the task id in the API, so that if someone wants to check on the status, they can

def genome_import(request):
import tempfile
res = {
"imported_genomes": [],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currently, if your code throws any errors in this, you'll just return a 500 status; that might be fine, but there may be some errors you want to catch and report in your API instead, in an 'error' field.

build_genome_blastdb.delay(g.id)
return HttpResponse(json.dumps(res), content_type='application/json')


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there tests for other views like this? Might make sense to add one if there are; shouldn't be so bad; i'd just mock up the task and import_gff, and make sure that both are called as expected based on the number of genomes that are submitted.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should add a test for sure.

@yaoyuyang
Copy link
Member Author

@myw could you take another look? I've resolved most of your comments! Thank you for the detailed review. Learned quite a few things!

Copy link
Contributor

@myw myw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some HTML cleanup and a better way to write the GFF file.

$scope.getBaseURL = function() { return '/edge/'; }
$scope.addGenome = function(){
var file = $scope.gffFile;
$scope.addGenomeStatus = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice. I like this approach

}
$scope.addGenomeStatus.pending = true;
var fd = new FormData();
var gff_name = $scope.genome.name;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still wrong convention

</div>
<div class="form-group">
<label for="gff_file">GFF File (GFF3 format):</label><br/>
<input type="file" file-model="gffFile" id='gff_file'/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

html attributes should use double quotes; also, Ids typically come first


<div class="form-group">
<label for="genome_name">Genome Name:</label>
<input id="genome_name", name=name, type="text" ng-model="genome.name" required />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attributes should not have commas between them, and "name" should have quotes around it.

<label for="gff_file">GFF File (GFF3 format):</label><br/>
<input type="file" file-model="gffFile" id='gff_file'/>
</div>
<button class="btn btn-primary", type="submit", ng-disabled="userForm.$invalid", ng-click="addGenome()">Import</button>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no commas between attributes

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. Fixed. I misread your previous comments, literally oblivated not


<div class="well" ng-show="addGenomeStatus.results">
<span class="text-success" ng-repeat='genome in addGenomeStatus.results.imported_genomes'>
Success: Added in Edge as <a ng-href="#/genomes/{{ genome.id }}">Genome {{ genome.id }}: {{ genome.name }}</a></span>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

span tag alignment is still weird here

response = HttpResponse(content_type='text/plain')
response['Content-Disposition'] = "attachment; filename=\"g%s.gff\"" % genome_id
io.to_gff_file(response)
return response


@require_http_methods(["POST"])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by convention, we stick with single quotes for non-docstrings, unless you need them for brevity when expressing string literals that contain single quotes, e.g. "I like to 'eat' foods"

}
for name in request.FILES:
with tempfile.NamedTemporaryFile(mode='rw+b', delete=False) as gff:
gff.write(request.FILES.get(name).read())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using .read() can cause OOM errors for large files. Since GFFs can be large, I suggest doing the django-recommended best-practice and using UploadedFile.chunks. See the docs for an example.

res = {
'imported_genomes': [],
}
for name in request.FILES:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is more a matter of taste, but I find it much easier to read code with period line breaks in it to separate "paragraphs" or "thoughts". In here, to increase legibility, I'd stick extra lines after the dict literal, and before the return, and around each individual "component" of the for loop: the gff writing/deletion, the BLASTdb task creation, and the call to JsonResponse.

@yaoyuyang
Copy link
Member Author

@myw can you take another look? Much appreciated!

Copy link
Contributor

@myw myw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just the commas;
commas betweet html attributes are not valid html


<div class="form-group">
<label for="genomeName">Genome Name:</label>
<input id="genomeName", name="name", type="text", ng-model="genome.name" required />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No commas in html attributes

@yaoyuyang
Copy link
Member Author

@myw fixed. Another look? Thanks!

@myw
Copy link
Contributor

myw commented Nov 17, 2017

All good. Ready for merge! Re: the commas; no worries. I figured that is exactly what happened as I saw that you added more.

@yaoyuyang
Copy link
Member Author

Surprisingly, the commas did not cause any problems in html rendering in chrome even though it's clearly not the w3 standard. Maybe chrome is just forgiving about these errors.

@yaoyuyang
Copy link
Member Author

Thanks for the thorough review @myw!

@yaoyuyang yaoyuyang merged commit b27c315 into master Nov 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants