diff --git a/frontend/app/components/panel/manage-genotype.hbs b/frontend/app/components/panel/manage-genotype.hbs
index 46f8419b..fd220d77 100644
--- a/frontend/app/components/panel/manage-genotype.hbs
+++ b/frontend/app/components/panel/manage-genotype.hbs
@@ -345,12 +345,20 @@
{{#if this.vcfExportText.length}}
-
+
{{/tab.pane}}
{{/let}}
{{/let}}
diff --git a/frontend/app/components/panel/manage-genotype.js b/frontend/app/components/panel/manage-genotype.js
index 9a52594f..5c4f4db9 100644
--- a/frontend/app/components/panel/manage-genotype.js
+++ b/frontend/app/components/panel/manage-genotype.js
@@ -21,6 +21,7 @@ import NamesFilters from '../../utils/data/names-filters';
import { toPromiseProxy, toArrayPromiseProxy, addObjectArrays, arrayClear } from '../../utils/ember-devel';
import { thenOrNow, contentOf, pollCondition, promiseThrottle } from '../../utils/common/promises';
import { responseTextParseHtml } from '../../utils/domElements';
+import { fileDownloadBlob, fileDownloadAsCSV, text2Gzip } from '../../utils/dom/file-download';
import { clipboard_writeText } from '../../utils/common/html';
import { arrayChoose } from '../../utils/common/arrays';
import { intervalSize } from '../../utils/interval-calcs';
@@ -183,6 +184,7 @@ function featureHasSamplesLoaded(feature) {
* .replaceResults default: false
* .showResultText default: false
+ * .compressVCF default : true
* .showConfigureLookup default: false
* .showSampleFilters default : false
@@ -475,6 +477,9 @@ export default class PanelManageGenotypeComponent extends Component {
if (userSettings.showResultText === undefined) {
userSettings.showResultText = false;
}
+ if (userSettings.compressVCF === undefined) {
+ userSettings.compressVCF = true;
+ }
if (userSettings.showConfigureLookup === undefined) {
userSettings.showConfigureLookup = true;
}
@@ -3155,6 +3160,11 @@ export default class PanelManageGenotypeComponent extends Component {
//----------------------------------------------------------------------------
+ /**
+ * @return a file base name for VCF Download of displayed data of this.lookupBlock.
+ * The base name does not include the extension, because either
+ * '.vcf.txt' or '.vcf.gz' may be used
+ */
@computed(
'lookupDatasetId', 'lookupScope', 'vcfGenotypeLookupDomain',
'vcfGenotypeSamplesSelected', 'requestFormat')
@@ -3168,8 +3178,7 @@ export default class PanelManageGenotypeComponent extends Component {
'_' + scope +
'_' + domainText +
'_' + this.requestFormat +
- '_' + samplesLength +
- '.vcf' ;
+ '_' + samplesLength;
return fileName;
}
@@ -3954,6 +3963,27 @@ export default class PanelManageGenotypeComponent extends Component {
return combinedP;
}
+ /** Export as a user file download a VCF file constructed from .headerTextP,
+ * .vcfGenotypeText via combineHeader()
+ *
+ * The exported MIME Type used is 'text/csv' because
+ * 'text/tsv'is would be interpreted as Vcard, refn
+ * https://github.com/samtools/hts-specs/issues/407
+ * https://developer.mozilla.org/en-US/docs/Web/HTTP/MIME_types/Common_types
+ */
+ vcfExportTextToFile() {
+ this.vcfExportTextP.then(combined => {
+ const data = combined.join('\n');
+ if (this.args.userSettings.compressVCF) {
+ const blobP = text2Gzip(data, 'application/gzip');
+ blobP.then(blob =>
+ fileDownloadBlob(this.vcfExportFileName + '.vcf.gz', blob, 'application/gzip'));
+ } else {
+ fileDownloadAsCSV(this.vcfExportFileName + '.vcf.txt', data, 'text/plain');
+ }
+ });
+ }
+
combineHeader(headerText, vcfGenotypeText) {
/** remove trailing \n, so that split does not create a trailing empty line. */
headerText = headerText.trim().split('\n');
diff --git a/frontend/app/utils/dom/file-download.js b/frontend/app/utils/dom/file-download.js
index 991ef582..3380b24c 100644
--- a/frontend/app/utils/dom/file-download.js
+++ b/frontend/app/utils/dom/file-download.js
@@ -1,22 +1,28 @@
//------------------------------------------------------------------------------
/* global Blob */
+/* global removeEventListener */
+/* global document */
+/* global URL */
+/* global CompressionStream */
+/* global Response */
//------------------------------------------------------------------------------
-export {fileDownloadAsCSV}
-/** Trigger a download of a CSV / TSV file containing the given CSV / TSV string
+export {fileDownloadBlob, fileDownloadAsCSV}
+/** Trigger a download of a file containing the given data blob.
*
- * Based on a post on discuss.emberjs.com by skaterdav85, May 2018 :
+ * fileDownloadBlob() and fileDownloadAsCSV() are partly based on a post on discuss.emberjs.com by skaterdav85, May 2018 :
* https://discuss.emberjs.com/t/whats-the-best-strategy-for-letting-users-download-ember-data-returns-as-csvs/14767/2
+ *
+ * @param filename string
+ * @param blob
*/
-function fileDownloadAsCSV(filename, contents) {
+function fileDownloadBlob(filename, blob) {
const { document, URL, removeEventListener } = window;
const anchor = document.createElement('a');
anchor.download = filename;
- const url = anchor.href = URL.createObjectURL(new Blob([contents], {
- type: 'text/csv'
- }));
+ const url = anchor.href = URL.createObjectURL(blob);
//----------------------------------------------------------------------------
@@ -31,6 +37,16 @@ function fileDownloadAsCSV(filename, contents) {
anchor.click();
URL.revokeObjectURL(url);
anchor.remove();
+
+}
+/** Trigger a download of a CSV / TSV file containing the given CSV / TSV string
+ *
+ * @param filename string
+ * @param type default is 'text/csv'
+ */
+function fileDownloadAsCSV(filename, contents, type = 'text/csv') {
+ const blob = new Blob([contents], { type });
+ fileDownloadBlob(filename, blob);
}
//------------------------------------------------------------------------------
@@ -64,3 +80,18 @@ function exportAsCSVFile(fileName, data, keyArray, columnHeaders, quoteIfNeeded)
}
//------------------------------------------------------------------------------
+
+export { text2Gzip }
+/** Compress the given string, and return content for a .gz file download
+ * @return promise yielding a blob, of gzip data
+ */
+function text2Gzip(contents, type = 'text/csv') {
+ const
+ stream = new CompressionStream("gzip"),
+ blob = new Blob([contents], { type }),
+ compressedStream = blob.stream().pipeThrough(stream),
+ promise = new Response(compressedStream).blob();
+
+ return promise;
+
+}