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

Allow Browse Table Contents to be downloaded #640

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -392,5 +392,6 @@
nzSpin></i>
<span>Loading…</span>
</nz-tag>
<cvc-table-downloader [vars]="this.queryRef.variables" tableName="assertions"></cvc-table-downloader>
<cvc-no-more-rows [cvcShowTag]="noMoreRows$ | ngrxPush"></cvc-no-more-rows>
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { CvcMolecularProfileTagModule } from '@app/components/molecular-profiles
import { CvcClearableInputFilterModule } from '@app/components/shared/clearable-input-filter/clearable-input-filter.module';
import { CvcNoMoreRowsModule } from '@app/components/shared/no-more-rows/no-more-rows.module';
import { CvcTableCountsModule } from '@app/components/shared/table-counts/table-counts.module';
import { CvcTableDownloaderModule } from '@app/components/shared/table-downloader/table-downloader.module';
import { CvcTagListModule } from '@app/components/shared/tag-list/tag-list.module';
import { CvcTagOverflowModule } from '@app/components/shared/tag-overflow/tag-overflow.module';
import { CvcPipesModule } from '@app/core/pipes/pipes.module';
Expand Down Expand Up @@ -61,6 +62,7 @@ import { CvcAssertionsTableComponent } from './assertions-table.component';
CvcTagListModule,
CvcTagOverflowModule,
CvcMolecularProfileTagModule,
CvcTableDownloaderModule
],
exports: [CvcAssertionsTableComponent]
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,5 +141,6 @@
nzSpin></i>
<span>Loading…</span>
</nz-tag>
<cvc-table-downloader [vars]="this.queryRef.variables" tableName="clinical_trials"></cvc-table-downloader>
<cvc-no-more-rows [cvcShowTag]="noMoreRows$ | ngrxPush"></cvc-no-more-rows>
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { NgModule } from '@angular/core';
import { CvcClearableInputFilterModule } from '@app/components/shared/clearable-input-filter/clearable-input-filter.module';
import { CvcNoMoreRowsModule } from '@app/components/shared/no-more-rows/no-more-rows.module';
import { CvcTableCountsModule } from '@app/components/shared/table-counts/table-counts.module';
import { CvcTableDownloaderModule } from '@app/components/shared/table-downloader/table-downloader.module';
import { CvcPipesModule } from '@app/core/pipes/pipes.module';
import { CvcAutoHeightCardModule } from '@app/directives/auto-height-card/auto-height-card.module';
import { CvcAutoHeightTableModule } from '@app/directives/auto-height-table/auto-height-table.module';
Expand Down Expand Up @@ -40,6 +41,7 @@ import { CvcClinicalTrialsTableComponent } from './clinical-trials-table.compone
CvcNoMoreRowsModule,
CvcTableCountsModule,
CvcTableScrollModule,
CvcTableDownloaderModule
],
exports: [CvcClinicalTrialsTableComponent]
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,5 +193,6 @@
nzSpin></i>
<span>Loading…</span>
</nz-tag>
<cvc-table-downloader [vars]="this.queryRef.variables" tableName="diseases"></cvc-table-downloader>
<cvc-no-more-rows [cvcShowTag]="noMoreRows$ | ngrxPush"></cvc-no-more-rows>
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { CvcClearableInputFilterModule } from '@app/components/shared/clearable-
import { CvcLinkTagModule } from '@app/components/shared/link-tag/link-tag.module';
import { CvcNoMoreRowsModule } from '@app/components/shared/no-more-rows/no-more-rows.module';
import { CvcTableCountsModule } from '@app/components/shared/table-counts/table-counts.module';
import { CvcTableDownloaderModule } from '@app/components/shared/table-downloader/table-downloader.module';
import { CvcPipesModule } from '@app/core/pipes/pipes.module';
import { CvcAutoHeightCardModule } from '@app/directives/auto-height-card/auto-height-card.module';
import { CvcAutoHeightTableModule } from '@app/directives/auto-height-table/auto-height-table.module';
Expand Down Expand Up @@ -43,6 +44,7 @@ import { CvcDiseasesTableComponent } from './diseases-table.component';
CvcNoMoreRowsModule,
CvcTableCountsModule,
CvcTableScrollModule,
CvcTableDownloaderModule
],
exports: [CvcDiseasesTableComponent]
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,5 +141,6 @@
nzSpin></i>
<span>Loading…</span>
</nz-tag>
<cvc-table-downloader [vars]="this.queryRef.variables" tableName="drugs"></cvc-table-downloader>
<cvc-no-more-rows [cvcShowTag]="noMoreRows$ | ngrxPush"></cvc-no-more-rows>
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { CvcTableScrollModule } from '@app/directives/table-scroll/table-scroll.
import { CvcTableCountsModule } from '@app/components/shared/table-counts/table-counts.module';
import { CvcNoMoreRowsModule } from '@app/components/shared/no-more-rows/no-more-rows.module';
import { CvcPipesModule } from '@app/core/pipes/pipes.module';
import { CvcTableDownloaderModule } from '@app/components/shared/table-downloader/table-downloader.module';

@NgModule({
declarations: [CvcDrugsTableComponent],
Expand All @@ -43,6 +44,7 @@ import { CvcPipesModule } from '@app/core/pipes/pipes.module';
CvcNoMoreRowsModule,
CvcTableCountsModule,
CvcTableScrollModule,
CvcTableDownloaderModule
],
exports: [CvcDrugsTableComponent]
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,5 +489,6 @@
nzSpin></i>
<span>Loading…</span>
</nz-tag>
<cvc-table-downloader [vars]="this.queryRef.variables" tableName="evidence"></cvc-table-downloader>
<cvc-no-more-rows [cvcShowTag]="noMoreRows$ | ngrxPush"></cvc-no-more-rows>
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export class CvcEvidenceTableComponent implements OnInit {
first: this.initialPageSize,
organizationId: this.organizationId,
phenotypeId: this.phenotypeId,
rating: this.evidenceRatingInput ? this.evidenceRatingInput : undefined,
evidenceRating: this.evidenceRatingInput ? this.evidenceRatingInput : undefined,
sourceId: this.sourceId,
status: this.status,
userId: this.userId,
Expand Down Expand Up @@ -258,7 +258,7 @@ export class CvcEvidenceTableComponent implements OnInit {
variantOrigin: this.variantOriginInput
? this.variantOriginInput
: undefined,
rating: this.evidenceRatingInput ? this.evidenceRatingInput : undefined,
evidenceRating: this.evidenceRatingInput ? this.evidenceRatingInput : undefined,
molecularProfileName: this.molecularProfileNameInput ? this.molecularProfileNameInput : undefined,
})
.then(() => this.scrollIndex$.next(0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { CvcMolecularProfileTagModule } from '@app/components/molecular-profiles
import { CvcClearableInputFilterModule } from '@app/components/shared/clearable-input-filter/clearable-input-filter.module';
import { CvcNoMoreRowsModule } from '@app/components/shared/no-more-rows/no-more-rows.module';
import { CvcTableCountsModule } from '@app/components/shared/table-counts/table-counts.module';
import { CvcTableDownloaderModule } from '@app/components/shared/table-downloader/table-downloader.module';
import { CvcTagListModule } from '@app/components/shared/tag-list/tag-list.module';
import { CvcTagOverflowModule } from '@app/components/shared/tag-overflow/tag-overflow.module';
import { CvcPipesModule } from '@app/core/pipes/pipes.module';
Expand Down Expand Up @@ -63,6 +64,7 @@ import { CvcEvidenceTableComponent } from './evidence-table.component';
CvcTagListModule,
CvcTagOverflowModule,
CvcMolecularProfileTagModule,
CvcTableDownloaderModule
],
exports: [CvcEvidenceTableComponent]
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ query EvidenceBrowse(
$evidenceDirection: EvidenceDirection
$clinicalSignificance: EvidenceClinicalSignificance
$evidenceType: EvidenceType
$rating: Int
$evidenceRating: Int
$variantOrigin: VariantOrigin
$variantId: Int
$molecularProfileId: Int
Expand Down Expand Up @@ -40,7 +40,7 @@ query EvidenceBrowse(
evidenceDirection: $evidenceDirection
clinicalSignificance: $clinicalSignificance
evidenceType: $evidenceType
evidenceRating: $rating
evidenceRating: $evidenceRating
variantOrigin: $variantOrigin
variantId: $variantId
molecularProfileId: $molecularProfileId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,5 +173,6 @@
nzSpin></i>
<span>Loading…</span>
</nz-tag>
<cvc-table-downloader [vars]="this.queryRef.variables" tableName="genes"></cvc-table-downloader>
<cvc-no-more-rows [cvcShowTag]="noMoreRows$ | ngrxPush"></cvc-no-more-rows>
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { CvcClearableInputFilterModule } from '@app/components/shared/clearable-
import { CvcNoMoreRowsModule } from '@app/components/shared/no-more-rows/no-more-rows.module';
import { CvcPlainTagOverflowModule } from '@app/components/shared/plain-tag-overflow/plain-tag-overflow.module';
import { CvcTableCountsModule } from '@app/components/shared/table-counts/table-counts.module';
import { CvcTableDownloaderModule } from '@app/components/shared/table-downloader/table-downloader.module';
import { CvcTagOverflowModule } from '@app/components/shared/tag-overflow/tag-overflow.module';
import { CvcPipesModule } from '@app/core/pipes/pipes.module';
import { CvcAutoHeightCardModule } from '@app/directives/auto-height-card/auto-height-card.module';
Expand Down Expand Up @@ -50,6 +51,7 @@ import { CvcGenesTableComponent } from './genes-table.component';
CvcTableCountsModule,
CvcTableScrollModule,
CvcTagOverflowModule,
CvcTableDownloaderModule
],
exports: [CvcGenesTableComponent]
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,5 +200,6 @@
nzSpin></i>
<span>Loading…</span>
</nz-tag>
<cvc-table-downloader [vars]="this.queryRef.variables" tableName="molecular_profiles"></cvc-table-downloader>
<cvc-no-more-rows [cvcShowTag]="noMoreRows$ | ngrxPush"></cvc-no-more-rows>
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { CvcClearableInputFilterModule } from '@app/components/shared/clearable-
import { CvcNoMoreRowsModule } from '@app/components/shared/no-more-rows/no-more-rows.module';
import { CvcPlainTagOverflowModule } from '@app/components/shared/plain-tag-overflow/plain-tag-overflow.module';
import { CvcTableCountsModule } from '@app/components/shared/table-counts/table-counts.module';
import { CvcTableDownloaderModule } from '@app/components/shared/table-downloader/table-downloader.module';
import { CvcTagOverflowModule } from '@app/components/shared/tag-overflow/tag-overflow.module';
import { CvcVariantTagModule } from '@app/components/variants/variant-tag/variant-tag.module';
import { CvcPipesModule } from '@app/core/pipes/pipes.module';
Expand Down Expand Up @@ -46,7 +47,8 @@ import { CvcMolecularProfilesTableComponent } from './molecular-profile-table.co
CvcTableScrollModule,
CvcTagOverflowModule,
CvcMolecularProfileTagModule,
CvcPlainTagOverflowModule
CvcPlainTagOverflowModule,
CvcTableDownloaderModule
],
exports: [CvcMolecularProfilesTableComponent]
})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<button nz-button
nzSize="small"
(click)="this.downloadTable()"
[disabled]="this.downloading | async">
<span *ngIf="!(this.downloading | async)"nz-icon nzType="download" nzTheme="outline"></span>
<span *ngIf="this.downloading | async" nz-icon nzType="sync" [nzSpin]="true"></span>
Download Table
</button>
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { Component, Output, EventEmitter, OnDestroy, Input } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Query } from "apollo-angular";
import { EmptyObject } from "apollo-angular/types";
import { BehaviorSubject } from "rxjs";

@Component({
selector: 'cvc-table-downloader',
templateUrl: './table-downloader.component.html',
styleUrls: ['./table-downloader.component.less'],
})
export class CvcTableDownloaderComponent<V extends EmptyObject> {

@Input() tableName?: string
@Input() vars?: V

downloading = new BehaviorSubject<boolean>(false)

constructor(private http: HttpClient) {}

downloadTable() {
if(this.vars) {
let payload = {
variables: this.vars
}
this.downloading.next(true);
this.http.post(`/api/download_table/${this.tableName}`, payload, {responseType: 'blob', observe: 'response'}).subscribe((resp: any) => {
const a = document.createElement("a");
document.body.append(a);
a.style.display = 'none';
const blob = new Blob([resp.body], {type: 'text/csv'});
const url = window.URL.createObjectURL(blob);
a.href = url;
a.download = `${this.tableName}-${new Date().toLocaleString().split(',')[0]}.tsv`
a.click();
this.downloading.next(false);
setTimeout(() => { window.URL.revokeObjectURL(url); }, 400)
})
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NzButtonModule } from 'ng-zorro-antd/button';
import { NzIconModule } from 'ng-zorro-antd/icon';
import { CvcTableDownloaderComponent } from './table-downloader.component';

@NgModule({
declarations: [CvcTableDownloaderComponent],
imports: [
CommonModule,
NzButtonModule,
NzIconModule
],
exports: [CvcTableDownloaderComponent]
})
export class CvcTableDownloaderModule { }
Original file line number Diff line number Diff line change
Expand Up @@ -202,5 +202,6 @@
nzSpin></i>
<span>Loading…</span>
</nz-tag>
<cvc-table-downloader [vars]="this.queryRef.variables" tableName="sources"></cvc-table-downloader>
<cvc-no-more-rows [cvcShowTag]="noMoreRows$ | ngrxPush"></cvc-no-more-rows>
</ng-template>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { CvcClearableInputFilterModule } from '@app/components/shared/clearable-
import { CvcNoMoreRowsModule } from '@app/components/shared/no-more-rows/no-more-rows.module';
import { CvcPlainTagOverflowModule } from '@app/components/shared/plain-tag-overflow/plain-tag-overflow.module';
import { CvcTableCountsModule } from '@app/components/shared/table-counts/table-counts.module';
import { CvcTableDownloaderModule } from '@app/components/shared/table-downloader/table-downloader.module';
import { CvcPipesModule } from '@app/core/pipes/pipes.module';
import { CvcAutoHeightCardModule } from '@app/directives/auto-height-card/auto-height-card.module';
import { CvcAutoHeightTableModule } from '@app/directives/auto-height-table/auto-height-table.module';
Expand Down Expand Up @@ -46,6 +47,7 @@ import { CvcSourcesTableComponent } from './sources-table.component';
CvcSourceTagModule,
CvcTableCountsModule,
CvcTableScrollModule,
CvcTableDownloaderModule
],
exports: [CvcSourcesTableComponent]
})
Expand Down
22 changes: 22 additions & 0 deletions server/app/controllers/concerns/with_graphql_variables.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module WithGraphqlVariables
extend ActiveSupport::Concern
# Handle variables in form data, JSON body, or a blank value
def prepare_variables(variables_param)
case variables_param
when String
if variables_param.present?
JSON.parse(variables_param) || {}
else
{}
end
when Hash
variables_param
when ActionController::Parameters
variables_param.to_unsafe_hash # GraphQL-Ruby will validate name and type of incoming variables.
when nil
{}
else
raise ArgumentError, "Unexpected parameter: #{variables_param}"
end
end
end
22 changes: 1 addition & 21 deletions server/app/controllers/graphql_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class GraphqlController < ApplicationController
include WithGraphqlVariables
# If accessing from outside this domain, nullify the session
# This allows for outside API access while preventing CSRF attacks,
# but you'll have to authenticate your user separately
Expand All @@ -23,27 +24,6 @@ def execute
end

private

# Handle variables in form data, JSON body, or a blank value
def prepare_variables(variables_param)
case variables_param
when String
if variables_param.present?
JSON.parse(variables_param) || {}
else
{}
end
when Hash
variables_param
when ActionController::Parameters
variables_param.to_unsafe_hash # GraphQL-Ruby will validate name and type of incoming variables.
when nil
{}
else
raise ArgumentError, "Unexpected parameter: #{variables_param}"
end
end

def handle_error_in_development(e)
logger.error e.message
logger.error e.backtrace.join("\n")
Expand Down
49 changes: 49 additions & 0 deletions server/app/controllers/table_download_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
require 'csv'

class TableDownloadController < ApplicationController
include WithGraphqlVariables

@@table_resolvers = {
genes: Resolvers::BrowseGenes,
evidence: Resolvers::TopLevelEvidenceItems,
drugs: Resolvers::TopLevelDrugs,
sources: Resolvers::BrowseSources,
diseases: Resolvers::BrowseDiseases,
molecular_profiles: Resolvers::BrowseMolecularProfiles,
clinical_trials: Resolvers::TopLevelClinicalTrials,
assertions: Resolvers::TopLevelAssertions
}

def download
if res = @@table_resolvers[params[:table_name].to_sym]
stream_table(resolver: res)
else
head :bad_request
end
end

private
def stream_table(resolver: )

variables = prepare_variables(params[:variables])
variables.delete('sortBy')
variables.transform_keys! { |k| GraphQL::Schema::Member::BuildType.underscore(k) }

headers.delete("Content-Length")
headers["Cache-Control"] = "no-cache"
headers["Content-Type"] = "text/csv"
headers["Content-Disposition"] = "attachment; filename=\"#{params[:action]}-#{Date.today}.tsv\""
headers["X-Accel-Buffering"] = "no"

response.status = 200


self.response_body = Enumerator.new do |collection|
collection << CSV.generate_line(resolver.table_headers, col_sep: "\t")

resolver.new(filters: variables).results.find_each do |result|
collection << CSV.generate_line( resolver.to_row(object: result), col_sep: "\t")
end
end
end
end
Loading