From 642dad84dcf6608eef8b234a63a77303659e2173 Mon Sep 17 00:00:00 2001 From: Dave Lawrence Date: Thu, 19 Sep 2024 10:39:44 +0930 Subject: [PATCH] issue #1171 - generate download --- analysis/grid_export.py | 8 ++ analysis/views/views_grid.py | 2 + library/django_utils/jqgrid_view.py | 2 +- snpdb/models/models.py | 2 +- snpdb/templates/snpdb/data/view_vcf.html | 111 +++++++++--------- snpdb/views/views.py | 21 ++-- .../default_static/js/generated_graphs.js | 6 +- 7 files changed, 80 insertions(+), 72 deletions(-) diff --git a/analysis/grid_export.py b/analysis/grid_export.py index ea505c848..251baede5 100644 --- a/analysis/grid_export.py +++ b/analysis/grid_export.py @@ -92,6 +92,14 @@ def _grid_export_vcf(genome_build, colmodels, items, sample_ids, sample_names_by pseudo_buffer = StashFile() vcf_writer = Writer(pseudo_buffer, vcf_reader) + # Need to pass escapechar + vcf_writer.writer = csv.writer( + pseudo_buffer, + delimiter="\t", + lineterminator="\n", + quoting=csv.QUOTE_NONE, + escapechar="\\", + ) def iter_row_writer(): for obj in items: diff --git a/analysis/views/views_grid.py b/analysis/views/views_grid.py index 1f5f4cb53..186119081 100644 --- a/analysis/views/views_grid.py +++ b/analysis/views/views_grid.py @@ -119,6 +119,8 @@ def cohort_grid_export(request, cohort_id, export_type): params_hash = get_grid_downloadable_file_params_hash(cohort_id, export_type) task = export_cohort_to_downloadable_file.si(cohort_id, export_type) cgf = CachedGeneratedFile.get_or_create_and_launch("export_cohort_to_downloadable_file", params_hash, task) + if cgf.exception: + raise ValueError(cgf.exception) return redirect(cgf) diff --git a/library/django_utils/jqgrid_view.py b/library/django_utils/jqgrid_view.py index 4f8093eda..c03c05ad8 100644 --- a/library/django_utils/jqgrid_view.py +++ b/library/django_utils/jqgrid_view.py @@ -136,7 +136,7 @@ def grid_export_csv(colmodels, items) -> Iterator[str]: pseudo_buffer = StashFile() header, labels = colmodel_header_labels(colmodels, label_overrides=label_overrides) # Don't use dictwriter as some sample names may be the same - writer = csv.writer(pseudo_buffer, dialect='excel') + writer = csv.writer(pseudo_buffer, dialect='excel', escapechar='\\', quoting=csv.QUOTE_NONE) writer.writerow(header) def iter_row_writer(): diff --git a/snpdb/models/models.py b/snpdb/models/models.py index fa52c088a..40633c746 100644 --- a/snpdb/models/models.py +++ b/snpdb/models/models.py @@ -57,7 +57,7 @@ class CachedGeneratedFile(models.Model): generator = models.TextField() params_hash = models.TextField() # sha256 of params task_id = models.CharField(max_length=36, null=True) - task_status = models.TextField(null=True) # TODO: what's the actual size? + task_status = models.TextField(null=True) generate_start = models.DateTimeField(null=True) generate_end = models.DateTimeField(null=True) diff --git a/snpdb/templates/snpdb/data/view_vcf.html b/snpdb/templates/snpdb/data/view_vcf.html index a946f187b..7cea6fd25 100644 --- a/snpdb/templates/snpdb/data/view_vcf.html +++ b/snpdb/templates/snpdb/data/view_vcf.html @@ -283,42 +283,67 @@ }); }); - function pollAndDownloadFile(selector, fileType) { - const spinnerId = 'spinner-' + fileType; - function downloadFile(data) { - /* - $("#" + spinnerId).replaceWith(' Error retrieving download...'); - - -
Annotated VCF -
+ class AnnotatedFileDownload { + constructor(selector, pollUrl, fileType) { + this.selector = $(selector); + this.pollUrl = pollUrl; + this.fileType = fileType; + this.ucFileType = this.fileType.toUpperCase() + } + setGenerateDownloadLink() { + // console.log("setGenerateDownloadLink"); + const that = this; + const generateLink = $(`
Annotated ${this.ucFileType}
`); + generateLink.click(function(event) { + event.preventDefault(); + that.setPolling(true); + }); + this.selector.empty(); + this.selector.append(generateLink); + console.log("/setGenerateDownloadLink"); + } - */ - window.location.href = data.url; + setDownloadLink(url) { + // console.log("setDownloadLink"); + this.selector.html(`
Annotated ${this.ucFileType}
`); } - let failureFunc = function(data) { - console.log("Fail!"); - $("#" + spinnerId).replaceWith(' Error retrieving download...'); + setError() { + // console.log("setError"); + this.selector.html(' Error retrieving download...'); } - $(selector).replaceWith(` Preparing download...`); - let pollUrl = Urls.cohort_grid_export({{ vcf.cohort.pk }}, fileType); - poll_cached_generated_file(pollUrl, downloadFile, failureFunc); + setPolling(download) { + // console.log("setPolling"); + let that = this; + function downloadFile(data) { + that.setDownloadLink(data.url); + if (download) { + window.location.href = data.url; + } + } + $(this.selector).html(` Preparing download...`); + poll_cached_generated_file(this.pollUrl, downloadFile, this.setError) + } } - $("#generate-vcf-download").click(function(event) { - event.preventDefault(); - pollAndDownloadFile(this, "vcf"); - }); - - - $("#generate-csv-download").click(function(event) { - event.preventDefault(); - pollAndDownloadFile(this, "csv"); - }); - + {% for file_type, cgf in annotated_download_files.items %} + var pollUrl = Urls.cohort_grid_export({{ vcf.cohort.pk }}, "{{ file_type }}"); + var afdSelector = $("div#generate-{{ file_type }}-download"); + var afd = new AnnotatedFileDownload(afdSelector, pollUrl, "{{ file_type }}"); + {% if cgf %} + {% if cgf.exception %} + afd.setError() + {% elif cgf.status == "SUCCESS" %} + afd.setDownloadLink("{{ cgf.get_media_url }}"); + {% else %} + afd.setPolling(false); + {% endif %} + {% else %} + afd.setGenerateDownloadLink(); + {% endif %} + {% endfor %} }); @@ -351,38 +376,16 @@

VCF: {{ vcf.name }}

{% csrf_token %} {% crispy vcf_form form_helper.horizontal %} - {% if can_download_vcf %} + {% if annotated_download_files or vcf.uploadedvcf.uploaded_file.exists %}
{% if vcf.uploadedvcf.uploaded_file.exists %}
Original VCF
({{ vcf.uploadedvcf.uploaded_file.size|filesizeformat }})
{% endif %} - {% if can_download_annotated_vcf %} -
- {% if annotated_vcf_url %} - -
Annotated VCF -
- {% else %} - -
Annotated VCF -
- {% endif %} -
-
- {% if annotated_csv_url %} - -
Annotated CSV -
- {% else %} - -
Annotated CSV -
- {% endif %} - -
- {% endif %} + {% for file_type in annotated_download_files %} +
+ {% endfor %}
{% endif %} diff --git a/snpdb/views/views.py b/snpdb/views/views.py index 17ca3581d..cea99ed80 100644 --- a/snpdb/views/views.py +++ b/snpdb/views/views.py @@ -282,21 +282,18 @@ def view_vcf(request, vcf_id): except UploadedVCF.DoesNotExist: can_view_upload_pipeline = False - can_download_annotated_vcf = False - annotated_vcf_url = None - annotated_csv_url = None + annotated_download_files = {} if vcf.import_status == ImportStatus.SUCCESS and cohort_id: try: AnalysisTemplate.get_template_from_setting("ANALYSIS_TEMPLATES_AUTO_COHORT_EXPORT") - can_download_annotated_vcf = True params_hash_vcf = get_grid_downloadable_file_params_hash(cohort_id, "vcf") - if cgf_vcf := CachedGeneratedFile.objects.filter(generator="export_cohort_to_downloadable_file", - params_hash=params_hash_vcf).first(): - annotated_vcf_url = cgf_vcf.get_media_url() + cgf_vcf = CachedGeneratedFile.objects.filter(generator="export_cohort_to_downloadable_file", + params_hash=params_hash_vcf).first() params_hash_csv = get_grid_downloadable_file_params_hash(cohort_id, "csv") - if cgf_csv := CachedGeneratedFile.objects.filter(generator="export_cohort_to_downloadable_file", - params_hash=params_hash_csv).first(): - annotated_csv_url = cgf_csv.get_media_url() + cgf_csv = CachedGeneratedFile.objects.filter(generator="export_cohort_to_downloadable_file", + params_hash=params_hash_csv).first() + + annotated_download_files = {"vcf": cgf_vcf, "csv": cgf_csv} except ValueError: pass @@ -311,10 +308,8 @@ def view_vcf(request, vcf_id): 'patient_form': PatientForm(user=request.user), # blank 'has_write_permission': has_write_permission, 'can_download_vcf': (not settings.VCF_DOWNLOAD_ADMIN_ONLY) or request.user.is_superuser, - 'can_download_annotated_vcf': can_download_annotated_vcf, 'can_view_upload_pipeline': can_view_upload_pipeline, - 'annotated_vcf_url': annotated_vcf_url, - 'annotated_csv_url': annotated_csv_url, + 'annotated_download_files': annotated_download_files, "variant_zygosity_count_collections": variant_zygosity_count_collections, } return render(request, 'snpdb/data/view_vcf.html', context) diff --git a/variantgrid/static_files/default_static/js/generated_graphs.js b/variantgrid/static_files/default_static/js/generated_graphs.js index 631126666..9fd5542d4 100644 --- a/variantgrid/static_files/default_static/js/generated_graphs.js +++ b/variantgrid/static_files/default_static/js/generated_graphs.js @@ -48,7 +48,7 @@ function poll_graph_status(graph_selector, poll_url, delete_url) { function poll_cached_generated_file(poll_url, success_func, failure_func) { - $.getJSON(poll_url, function(data) { + $.getJSON(poll_url, function (data) { if (data.status == "SUCCESS") { success_func(data); } else if (data.status == 'FAILURE') { @@ -59,5 +59,5 @@ function poll_cached_generated_file(poll_url, success_func, failure_func) { }; window.setTimeout(retry_func, freq); } - }); -} \ No newline at end of file + }).fail(failure_func); +}