From 2a6bafe47243a7dc17f045077084b6c453cfad35 Mon Sep 17 00:00:00 2001 From: wivern Date: Fri, 22 Dec 2023 17:28:31 +0300 Subject: [PATCH 1/9] ATL-29 API Support for R Shiny Apps --- .../cohort-definition-manager.html | 16 ++++++++ .../cohort-definition-manager.js | 38 +++++++++++++++++++ js/pages/cohort-definitions/const.js | 2 + 3 files changed, 56 insertions(+) diff --git a/js/pages/cohort-definitions/cohort-definition-manager.html b/js/pages/cohort-definitions/cohort-definition-manager.html index 2665a0ca7..1159c6382 100644 --- a/js/pages/cohort-definitions/cohort-definition-manager.html +++ b/js/pages/cohort-definitions/cohort-definition-manager.html @@ -790,6 +790,22 @@

+ +
+ + +
+ diff --git a/js/pages/cohort-definitions/cohort-definition-manager.js b/js/pages/cohort-definitions/cohort-definition-manager.js index 99f13fdc5..ad0aae7fc 100644 --- a/js/pages/cohort-definitions/cohort-definition-manager.js +++ b/js/pages/cohort-definitions/cohort-definition-manager.js @@ -213,6 +213,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html', this.reportCohortDefinitionId = ko.observable(); this.reportSourceKey = ko.observable(); this.reportReportName = ko.observable(); + this.loading = ko.observable(false); this.loadingReport = ko.observable(false); this.reportTriggerRun = ko.observable(false); this.tabMode = sharedState.CohortDefinition.mode; @@ -849,6 +850,19 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html', } + this.shinyOptions = [ + { + action: this.downloadShinyApp, + title: 'components.shiny.button.menu.download', + defaultTitle: 'Download' + }, + { + action: this.publishShinyApp, + title: 'components.shiny.button.menu.publish', + defaultTitle: 'Publish' + } + ]; + PermissionService.decorateComponent(this, { entityTypeGetter: () => entityType.COHORT_DEFINITION, entityIdGetter: () => this.currentCohortDefinition().id(), @@ -1181,6 +1195,30 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html', } } + downloadShinyApp(source) { + FileService.loadZip( + config.api.url + constants.paths.downloadShiny(this.currentCohortDefinition().id(), source.sourceKey), + this.currentCohortDefinition().name() + "_cohortCounts_shinyApp.zip" + ) + .catch((e) => console.error("error when downloading: " + e)) + .finally(() => this.loading(false)); + } + + async publishShinyApp(source) { + this.loading = true; + try { + await httpService.doGet(config.api.url + constants.paths.publishShiny(this.currentCohortDefinition().id(), source.sourceKey)); + alert("Cohort is published"); + } catch (e) { + console.error('An error has occurred when publishing', e); + if (e.status === 403) { + alert('Permission denied'); + } else { + alert('Unexpected error occurred when publishing'); + } + } + } + onRouterParamsChanged(params) { let { cohortDefinitionId, conceptSetId, selectedSourceId, mode = 'definition', sourceKey, sampleId, version } = params; this.cohortDefinitionIdOnRoute(cohortDefinitionId) diff --git a/js/pages/cohort-definitions/const.js b/js/pages/cohort-definitions/const.js index 5c4a0c798..705df598f 100644 --- a/js/pages/cohort-definitions/const.js +++ b/js/pages/cohort-definitions/const.js @@ -45,6 +45,8 @@ define( const paths = { details: id => `/cohortdefinition/${id}`, + downloadShiny: (id, sourceKey) => `shiny/download/cohort/${id}/${sourceKey}`, + publishShiny: (id, sourceKey) => `shiny/publish/cohort/${id}/${sourceKey}`, }; const getPeriodTypeFilter = (chosenPeriods) => ({ From e403440ba82e43c68cfaa53b721c1d3f07cc7ae3 Mon Sep 17 00:00:00 2001 From: fedor_glushchenko Date: Mon, 27 May 2024 10:47:38 +0300 Subject: [PATCH 2/9] ATL-46: Download shiny name changed --- js/pages/cohort-definitions/cohort-definition-manager.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/pages/cohort-definitions/cohort-definition-manager.js b/js/pages/cohort-definitions/cohort-definition-manager.js index ad0aae7fc..28192929d 100644 --- a/js/pages/cohort-definitions/cohort-definition-manager.js +++ b/js/pages/cohort-definitions/cohort-definition-manager.js @@ -1196,9 +1196,11 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html', } downloadShinyApp(source) { + let date = Date.now() + let formattedDate = (moment(date)).format('YYYY_MM_DD') FileService.loadZip( config.api.url + constants.paths.downloadShiny(this.currentCohortDefinition().id(), source.sourceKey), - this.currentCohortDefinition().name() + "_cohortCounts_shinyApp.zip" + this.sourceName + "_" + formattedDate + "_" + this.currentCohortDefinition().name() + ".zip" ) .catch((e) => console.error("error when downloading: " + e)) .finally(() => this.loading(false)); From 2e910e67faa76619200ebea953781e5b265b53cb Mon Sep 17 00:00:00 2001 From: fedor_glushchenko Date: Thu, 30 May 2024 14:41:11 +0300 Subject: [PATCH 3/9] ATL-46: fixed name --- js/pages/cohort-definitions/cohort-definition-manager.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/pages/cohort-definitions/cohort-definition-manager.js b/js/pages/cohort-definitions/cohort-definition-manager.js index 28192929d..abf7ed415 100644 --- a/js/pages/cohort-definitions/cohort-definition-manager.js +++ b/js/pages/cohort-definitions/cohort-definition-manager.js @@ -6,6 +6,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html', 'services/ConceptSet', 'services/Permission', 'services/Tags', + 'moment', 'components/conceptset/utils', 'utils/DatatableUtils', 'components/cohortbuilder/CohortExpression', @@ -70,6 +71,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html', conceptSetService, PermissionService, TagsService, + moment, conceptSetUitls, datatableUtils, CohortExpression, @@ -1200,7 +1202,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html', let formattedDate = (moment(date)).format('YYYY_MM_DD') FileService.loadZip( config.api.url + constants.paths.downloadShiny(this.currentCohortDefinition().id(), source.sourceKey), - this.sourceName + "_" + formattedDate + "_" + this.currentCohortDefinition().name() + ".zip" + source.sourceKey + "_" + formattedDate + "_" + this.currentCohortDefinition().name() + ".zip" ) .catch((e) => console.error("error when downloading: " + e)) .finally(() => this.loading(false)); From d0c2bf017aa7d9f350c3db5139cc84b157befbe1 Mon Sep 17 00:00:00 2001 From: oleg-odysseus Date: Tue, 28 May 2024 18:15:19 +0200 Subject: [PATCH 4/9] [ATL-48] Introduced a new button for downloading and publishing the Incidence Rates Shiny App --- .../iranalysis/components/results.html | 16 ++++++ .../iranalysis/components/results.js | 49 ++++++++++++++++++- js/pages/incidence-rates/const.js | 2 + 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/js/pages/incidence-rates/components/iranalysis/components/results.html b/js/pages/incidence-rates/components/iranalysis/components/results.html index 665fb77a4..d46459530 100644 --- a/js/pages/incidence-rates/components/iranalysis/components/results.html +++ b/js/pages/incidence-rates/components/iranalysis/components/results.html @@ -150,6 +150,22 @@

+ +
+ + +
+ diff --git a/js/pages/incidence-rates/components/iranalysis/components/results.js b/js/pages/incidence-rates/components/iranalysis/components/results.js index e77519f9f..41da92b5a 100644 --- a/js/pages/incidence-rates/components/iranalysis/components/results.js +++ b/js/pages/incidence-rates/components/iranalysis/components/results.js @@ -2,6 +2,10 @@ define([ 'knockout', 'jquery', 'text!./results.html', + 'appConfig', + 'services/file', + 'services/http', + 'moment', 'utils/AutoBind', 'services/IRAnalysis', 'pages/incidence-rates/const', @@ -19,6 +23,10 @@ define([ ko, $, view, + config, + FileService, + httpService, + moment, AutoBind, IRAnalysisService, constants, @@ -27,7 +35,7 @@ define([ authApi, Component, commonUtils, - sharedState + sharedState, ) { class IRAnalysisResultsViewer extends AutoBind(Component) { @@ -49,6 +57,7 @@ define([ this.cancelExecution = params.cancelExecution; this.stoppingSources = params.stoppingSources; this.criticalCount = params.criticalCount; + this.config = config; this.dirtyFlag = params.dirtyFlag; this.analysisCohorts = params.analysisCohorts; @@ -149,6 +158,44 @@ define([ className: 'generation-buttons-column', render: () => `` }]; + this.shinyOptions = [ + { + action: this.downloadShinyApp, + title: 'components.shiny.button.menu.download', + defaultTitle: 'Download' + }, + { + action: this.publishShinyApp, + title: 'components.shiny.button.menu.publish', + defaultTitle: 'Publish' + } + ]; + } + + downloadShinyApp(source) { + let date = Date.now(); + let formattedDate = (moment(date)).format('YYYY_MM_DD'); + FileService.loadZip( + config.api.url + constants.apiPaths.downloadShiny(source.info().executionInfo.id.analysisId, source.source.sourceKey), + source.source.sourceName + "_" + formattedDate + "_incidenceRates_shinyApp.zip" + ) + .catch((e) => console.error("error when downloading: " + e)) + .finally(() => this.loading(false)); + } + + async publishShinyApp(source) { + this.loading = true; + try { + await httpService.doGet(config.api.url + constants.apiPaths.publishShiny(source.info().executionInfo.id.analysisId, source.source.sourceKey)); + alert("Incidence Rate report is published"); + } catch (e) { + console.error('An error has occurred when publishing', e); + if (e.status === 403) { + alert('Permission denied'); + } else { + alert('Unexpected error occurred when publishing'); + } + } } reportDisabledReason(source) { diff --git a/js/pages/incidence-rates/const.js b/js/pages/incidence-rates/const.js index 9fa79dca0..4042fa023 100644 --- a/js/pages/incidence-rates/const.js +++ b/js/pages/incidence-rates/const.js @@ -4,6 +4,8 @@ define( root: '/iranalysis/', analysis: id => `/iranalysis${typeof id !== 'undefined' ? `/${id}` : ''}`, createAnalysis: () => '/iranalysis/0', + downloadShiny: (id, sourceKey) => `shiny/download/incidence/${id}/${sourceKey}`, + publishShiny: (id, sourceKey) => `shiny/publish/incidence/${id}/${sourceKey}`, }; const status = { From bba8fd7aa6a0a6b8529e5d687a73e02d204ba10a Mon Sep 17 00:00:00 2001 From: fedor_glushchenko Date: Thu, 6 Jun 2024 17:27:44 +0300 Subject: [PATCH 5/9] ATL-46: Name changes --- js/pages/cohort-definitions/cohort-definition-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/pages/cohort-definitions/cohort-definition-manager.js b/js/pages/cohort-definitions/cohort-definition-manager.js index abf7ed415..3809948aa 100644 --- a/js/pages/cohort-definitions/cohort-definition-manager.js +++ b/js/pages/cohort-definitions/cohort-definition-manager.js @@ -1202,7 +1202,7 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html', let formattedDate = (moment(date)).format('YYYY_MM_DD') FileService.loadZip( config.api.url + constants.paths.downloadShiny(this.currentCohortDefinition().id(), source.sourceKey), - source.sourceKey + "_" + formattedDate + "_" + this.currentCohortDefinition().name() + ".zip" + "Cohort_" + this.currentCohortDefinition().id() + "_" + source.sourceKey + ".zip" ) .catch((e) => console.error("error when downloading: " + e)) .finally(() => this.loading(false)); From 09e284ec09794113224405d7c00db34131437d3b Mon Sep 17 00:00:00 2001 From: oleg-odysseus Date: Tue, 4 Jun 2024 16:57:19 +0200 Subject: [PATCH 6/9] [ATL-49] Introduced a button for Shiny App publishing for Cohort Characterizations --- .../analysis-execution-list.html | 17 ++++++ .../analysis-execution-list.js | 54 +++++++++++++++++++ .../analysisExecution/shiny-const.js | 11 ++++ 3 files changed, 82 insertions(+) create mode 100644 js/components/analysisExecution/shiny-const.js diff --git a/js/components/analysisExecution/analysis-execution-list.html b/js/components/analysisExecution/analysis-execution-list.html index 8fcddaac4..5a617341d 100644 --- a/js/components/analysisExecution/analysis-execution-list.html +++ b/js/components/analysisExecution/analysis-execution-list.html @@ -100,6 +100,23 @@

)', {submissions: submissions().length})"> + +
+ + +
+
    diff --git a/js/components/analysisExecution/analysis-execution-list.js b/js/components/analysisExecution/analysis-execution-list.js index 4e3f3546b..1caa7aacc 100644 --- a/js/components/analysisExecution/analysis-execution-list.js +++ b/js/components/analysisExecution/analysis-execution-list.js @@ -8,8 +8,11 @@ define([ 'services/Source', 'services/JobDetailsService', 'services/file', + 'services/http', + 'moment', 'lodash', 'const', + 'components/analysisExecution/shiny-const', 'text!./analysis-execution-list.html', 'less!./analysis-execution-list.less', 'components/modal-exit-message', @@ -23,8 +26,11 @@ define([ SourceService, JobDetailsService, FileService, + httpService, + moment, lodash, consts, + shinyConsts, view ) { class AnalysisExecutionList extends Component { @@ -89,6 +95,7 @@ define([ this.executionResultModes = consts.executionResultModes; this.isExecutionDesignShown = ko.observable(false); this.executionDesign = ko.observable(null); + this.config = config; this.sourcesColumn = [{ render: (s, p, d) => { @@ -147,6 +154,53 @@ define([ ); this.isViewGenerationsPermitted && this.startPolling(); + this.shinyOptions = [ + { + action: this.downloadShinyApp, + title: 'components.shiny.button.menu.download', + defaultTitle: 'Download' + }, + { + action: this.publishShinyApp, + title: 'components.shiny.button.menu.publish', + defaultTitle: 'Publish' + } + ]; + } + + downloadShinyApp = (source) => { + let submission = this.findLatestSubmission(source.sourceKey); + let submissionId; + if (submission) { + submissionId = submission.id; + } + let currentAnalysisId=this.analysisId(); + FileService.loadZip( + config.api.url + shinyConsts.apiPaths.downloadShiny(submissionId, source.sourceKey), + "Characterization_" + currentAnalysisId + "_gv" + submissionId + "_" + source.sourceKey + ".zip" + ) + .catch((e) => console.error("error when downloading: " + e)) + .finally(() => this.loading(false)); + } + + publishShinyApp = async (source) => { + this.loading = true; + let submission = this.findLatestSubmission(source.sourceKey); + let submissionId; + if (submission) { + submissionId = submission.id; + } + try { + await httpService.doGet(config.api.url + shinyConsts.apiPaths.publishShiny(submissionId, source.sourceKey)); + alert("Cohort Characterization report is published"); + } catch (e) { + console.error('An error has occurred when publishing', e); + if (e.status === 403) { + alert('Permission denied'); + } else { + alert('Unexpected error occurred when publishing'); + } + } } startPolling() { diff --git a/js/components/analysisExecution/shiny-const.js b/js/components/analysisExecution/shiny-const.js new file mode 100644 index 000000000..e2de82b08 --- /dev/null +++ b/js/components/analysisExecution/shiny-const.js @@ -0,0 +1,11 @@ +define( + (require, exports) => { + const apiPaths = { + downloadShiny: (id, sourceKey) => `shiny/download/cohort_characterization/${id}/${sourceKey}`, + publishShiny: (id, sourceKey) => `shiny/publish/cohort_characterization/${id}/${sourceKey}`, + }; + return { + apiPaths + }; + } +); \ No newline at end of file From 8865dfab9d87848fae2cb7f7138e1779d9e802a5 Mon Sep 17 00:00:00 2001 From: oleg-odysseus Date: Tue, 18 Jun 2024 14:34:42 +0200 Subject: [PATCH 7/9] [ATL-48][ATL-29] Fixed names of published downloadable shiny apps --- js/pages/cohort-definitions/cohort-definition-manager.js | 2 -- .../components/iranalysis/components/results.js | 9 ++++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/js/pages/cohort-definitions/cohort-definition-manager.js b/js/pages/cohort-definitions/cohort-definition-manager.js index 3809948aa..87ada1531 100644 --- a/js/pages/cohort-definitions/cohort-definition-manager.js +++ b/js/pages/cohort-definitions/cohort-definition-manager.js @@ -1198,8 +1198,6 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html', } downloadShinyApp(source) { - let date = Date.now() - let formattedDate = (moment(date)).format('YYYY_MM_DD') FileService.loadZip( config.api.url + constants.paths.downloadShiny(this.currentCohortDefinition().id(), source.sourceKey), "Cohort_" + this.currentCohortDefinition().id() + "_" + source.sourceKey + ".zip" diff --git a/js/pages/incidence-rates/components/iranalysis/components/results.js b/js/pages/incidence-rates/components/iranalysis/components/results.js index 41da92b5a..eb9434916 100644 --- a/js/pages/incidence-rates/components/iranalysis/components/results.js +++ b/js/pages/incidence-rates/components/iranalysis/components/results.js @@ -173,14 +173,13 @@ define([ } downloadShinyApp(source) { - let date = Date.now(); - let formattedDate = (moment(date)).format('YYYY_MM_DD'); + let analysisId = source.info().executionInfo.id.analysisId; FileService.loadZip( - config.api.url + constants.apiPaths.downloadShiny(source.info().executionInfo.id.analysisId, source.source.sourceKey), - source.source.sourceName + "_" + formattedDate + "_incidenceRates_shinyApp.zip" + config.api.url + constants.apiPaths.downloadShiny(analysisId, source.source.sourceKey), + "Incidence_" + analysisId + "_" + source.source.sourceKey + ".zip" ) .catch((e) => console.error("error when downloading: " + e)) - .finally(() => this.loading(false)); + .finally(() => this.isLoading(false)); } async publishShinyApp(source) { From b5f2581b1a1808cde0125e332819c816e737da64 Mon Sep 17 00:00:00 2001 From: oleg-odysseus Date: Tue, 25 Jun 2024 23:48:51 +0200 Subject: [PATCH 8/9] [ATL-50] Introduced Cohort Pathway Shiny app download and publishing --- .../analysis-execution-list.js | 29 +++++++++++++++---- .../analysisExecution/shiny-const.js | 6 ++-- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/js/components/analysisExecution/analysis-execution-list.js b/js/components/analysisExecution/analysis-execution-list.js index 1caa7aacc..4a2f0c819 100644 --- a/js/components/analysisExecution/analysis-execution-list.js +++ b/js/components/analysisExecution/analysis-execution-list.js @@ -174,10 +174,19 @@ define([ if (submission) { submissionId = submission.id; } - let currentAnalysisId=this.analysisId(); + let currentAnalysisId = this.analysisId(); + let resultsPathPrefix = this.resultsPathPrefix; + let apiPath = (resultsPathPrefix && resultsPathPrefix.includes('characterizations')) + ? shinyConsts.apiPaths.downloadShinyCC(submissionId, source.sourceKey) + : shinyConsts.apiPaths.downloadShinyPW(submissionId, source.sourceKey); + + let filePrefix = (resultsPathPrefix && resultsPathPrefix.includes('characterizations')) + ? "Characterization_" + : "Pathway_"; + FileService.loadZip( - config.api.url + shinyConsts.apiPaths.downloadShiny(submissionId, source.sourceKey), - "Characterization_" + currentAnalysisId + "_gv" + submissionId + "_" + source.sourceKey + ".zip" + config.api.url + apiPath, + filePrefix + currentAnalysisId + "_gv" + submissionId + "_" + source.sourceKey + ".zip" ) .catch((e) => console.error("error when downloading: " + e)) .finally(() => this.loading(false)); @@ -190,9 +199,19 @@ define([ if (submission) { submissionId = submission.id; } + + let resultsPathPrefix = this.resultsPathPrefix; + let apiPath = (resultsPathPrefix && resultsPathPrefix.includes('characterizations')) + ? shinyConsts.apiPaths.publishShinyCC(submissionId, source.sourceKey) + : shinyConsts.apiPaths.publishShinyPW(submissionId, source.sourceKey); + + let alertPrefix = (resultsPathPrefix && resultsPathPrefix.includes('characterizations')) + ? "Characterization" + : "Pathway"; + try { - await httpService.doGet(config.api.url + shinyConsts.apiPaths.publishShiny(submissionId, source.sourceKey)); - alert("Cohort Characterization report is published"); + await httpService.doGet(config.api.url + apiPath); + alert("Cohort " + alertPrefix + " report is published"); } catch (e) { console.error('An error has occurred when publishing', e); if (e.status === 403) { diff --git a/js/components/analysisExecution/shiny-const.js b/js/components/analysisExecution/shiny-const.js index e2de82b08..ad17b50cc 100644 --- a/js/components/analysisExecution/shiny-const.js +++ b/js/components/analysisExecution/shiny-const.js @@ -1,8 +1,10 @@ define( (require, exports) => { const apiPaths = { - downloadShiny: (id, sourceKey) => `shiny/download/cohort_characterization/${id}/${sourceKey}`, - publishShiny: (id, sourceKey) => `shiny/publish/cohort_characterization/${id}/${sourceKey}`, + downloadShinyCC: (id, sourceKey) => `shiny/download/cohort_characterization/${id}/${sourceKey}`, + publishShinyCC: (id, sourceKey) => `shiny/publish/cohort_characterization/${id}/${sourceKey}`, + downloadShinyPW: (id, sourceKey) => `shiny/download/cohort_pathway/${id}/${sourceKey}`, + publishShinyPW: (id, sourceKey) => `shiny/publish/cohort_pathway/${id}/${sourceKey}`, }; return { apiPaths From b9edf97931e46cb18d56c033b271d0e1eb0eb0a1 Mon Sep 17 00:00:00 2001 From: oleg-odysseus Date: Fri, 30 Aug 2024 12:08:53 +0200 Subject: [PATCH 9/9] Added new operation loadZipNoRename to FileService which takes the downloaded filename from Content-Disposition header, used this operation in all shiny apps downloads --- .../analysis-execution-list.js | 11 +--- .../cohort-definition-manager.js | 5 +- .../iranalysis/components/results.js | 5 +- js/services/file.js | 64 ++++++++++++++----- 4 files changed, 54 insertions(+), 31 deletions(-) diff --git a/js/components/analysisExecution/analysis-execution-list.js b/js/components/analysisExecution/analysis-execution-list.js index 4a2f0c819..135007634 100644 --- a/js/components/analysisExecution/analysis-execution-list.js +++ b/js/components/analysisExecution/analysis-execution-list.js @@ -174,19 +174,14 @@ define([ if (submission) { submissionId = submission.id; } - let currentAnalysisId = this.analysisId(); + let resultsPathPrefix = this.resultsPathPrefix; let apiPath = (resultsPathPrefix && resultsPathPrefix.includes('characterizations')) ? shinyConsts.apiPaths.downloadShinyCC(submissionId, source.sourceKey) : shinyConsts.apiPaths.downloadShinyPW(submissionId, source.sourceKey); - let filePrefix = (resultsPathPrefix && resultsPathPrefix.includes('characterizations')) - ? "Characterization_" - : "Pathway_"; - - FileService.loadZip( - config.api.url + apiPath, - filePrefix + currentAnalysisId + "_gv" + submissionId + "_" + source.sourceKey + ".zip" + FileService.loadZipNoRename( + config.api.url + apiPath ) .catch((e) => console.error("error when downloading: " + e)) .finally(() => this.loading(false)); diff --git a/js/pages/cohort-definitions/cohort-definition-manager.js b/js/pages/cohort-definitions/cohort-definition-manager.js index 87ada1531..ca96a2500 100644 --- a/js/pages/cohort-definitions/cohort-definition-manager.js +++ b/js/pages/cohort-definitions/cohort-definition-manager.js @@ -1198,9 +1198,8 @@ define(['jquery', 'knockout', 'text!./cohort-definition-manager.html', } downloadShinyApp(source) { - FileService.loadZip( - config.api.url + constants.paths.downloadShiny(this.currentCohortDefinition().id(), source.sourceKey), - "Cohort_" + this.currentCohortDefinition().id() + "_" + source.sourceKey + ".zip" + FileService.loadZipNoRename( + config.api.url + constants.paths.downloadShiny(this.currentCohortDefinition().id(), source.sourceKey) ) .catch((e) => console.error("error when downloading: " + e)) .finally(() => this.loading(false)); diff --git a/js/pages/incidence-rates/components/iranalysis/components/results.js b/js/pages/incidence-rates/components/iranalysis/components/results.js index eb9434916..f030033a9 100644 --- a/js/pages/incidence-rates/components/iranalysis/components/results.js +++ b/js/pages/incidence-rates/components/iranalysis/components/results.js @@ -174,9 +174,8 @@ define([ downloadShinyApp(source) { let analysisId = source.info().executionInfo.id.analysisId; - FileService.loadZip( - config.api.url + constants.apiPaths.downloadShiny(analysisId, source.source.sourceKey), - "Incidence_" + analysisId + "_" + source.source.sourceKey + ".zip" + FileService.loadZipNoRename( + config.api.url + constants.apiPaths.downloadShiny(analysisId, source.source.sourceKey) ) .catch((e) => console.error("error when downloading: " + e)) .finally(() => this.isLoading(false)); diff --git a/js/services/file.js b/js/services/file.js index ce18e6624..5981c209a 100644 --- a/js/services/file.js +++ b/js/services/file.js @@ -7,33 +7,63 @@ define( authApi, ) => { class FileService { - // jQuery won't allow to set responseType other than 'text' + // Helper function to simplify setting up and making the XMLHttpRequest + _makeRequest(url, method, params, callback) { + const xhr = new XMLHttpRequest(); + xhr.open(method, url, true); + xhr.setRequestHeader("Authorization", authApi.getAuthorizationHeader()); + xhr.setRequestHeader("Content-type", "application/json"); + xhr.setRequestHeader("Action-Location", location); + xhr.onreadystatechange = () => { + if (xhr.readyState === 4) { + callback(xhr); + } + }; + xhr.onerror = () => reject({ + status: xhr.status, + statusText: xhr.statusText + }); + xhr.responseType = "arraybuffer"; + xhr.send(JSON.stringify(params)); + } + loadZip(url, filename, method = 'GET', params = {}) { - const promise = new Promise((resolve, reject) => { - const xhr = new XMLHttpRequest(); - xhr.open(method, url, true); - xhr.setRequestHeader("Authorization", authApi.getAuthorizationHeader()); - xhr.setRequestHeader("Content-type", "application/json"); - xhr.setRequestHeader("Action-Location", location); - xhr.onreadystatechange = function() { - if (xhr.readyState === 4 && xhr.status === 200) { + return new Promise((resolve, reject) => { + this._makeRequest(url, method, params, (xhr) => { + if (xhr.status === 200) { resolve(); const blob = new Blob([xhr.response], { type: "octet/stream" }); saveAs(blob, filename); - } else if (xhr.readyState === 4) { - reject({status: xhr.status, statusText: xhr.statusText}); + } else { + reject({ status: xhr.status, statusText: xhr.statusText }); } - } - xhr.onerror = reject; - xhr.responseType = "arraybuffer"; - xhr.send(JSON.stringify(params)); + }); }); + } - return promise; + loadZipNoRename(url, method = 'GET', params = {}) { + return new Promise((resolve, reject) => { + this._makeRequest(url, method, params, (xhr) => { + if (xhr.status === 200) { + const filename = xhr.getResponseHeader('Content-Disposition') + .split('filename=')[1] + .split(';')[0] + .replace(/\"/g, ''); // Clean up filename string + const blob = new Blob([xhr.response], { type: "octet/stream" }); + saveAs(blob, filename); + resolve(); + } else { + reject({ + status: xhr.status, + statusText: xhr.statusText + }); + } + }); + }); } saveAsJson(data) { - const blob = new Blob([JSON.stringify(data)], {type: "text/json;charset=utf-8"}); + const blob = new Blob([JSON.stringify(data)], { type: "text/json;charset=utf-8" }); saveAs(blob, 'data.json'); } }