From c386096ff1bc807f0ffb46cac26e3285de760c38 Mon Sep 17 00:00:00 2001 From: Luke Sikina <lucas.skina@gmail.com> Date: Thu, 15 Feb 2024 14:28:19 -0500 Subject: [PATCH 1/2] [ALS-5832] - Break out the upload of (geno|pheno)typic data into separate requests - Update UI to send separate requests - Fix confirmation modal state --- .../requestSearch/requestSearchResult.hbs | 12 ++++++- .../requestSearch/requestSearchResult.js | 33 +++++++++++++++---- .../requestSearch/verifySendModal.hbs | 10 ++++-- .../requestSearch/verifySendModal.js | 3 +- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.hbs b/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.hbs index 5df7b18..f5ad914 100644 --- a/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.hbs +++ b/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.hbs @@ -57,7 +57,17 @@ {{/if}} </div> <div class="col-md-4 request-result-header"> - <button id="upload-data-button" class="super-rounded" {{#if disableUpload}}disabled="disabled"{{/if}}> + <div style="width: 100%;"> + <div> + <input type="checkbox" id="pheno_check" name="pheno_check" {{#if sendPhenoData}}checked{{/if}}> + <label for="pheno_check"><i class="fa-solid fa-notes-medical"></i> Phenotypic Data</label> + </div> + <div> + <input type="checkbox" id="geno_check" name="geno_check" {{#if sendGenoData}}checked{{/if}}> + <label for="geno_check"><i class="fa-solid fa-dna"></i> Annotated variant data for selected genes</label> + </div> + </div> + <button id="upload-data-button" class="super-rounded"> <h3 class="fa-solid fa-arrow-up-from-bracket request-result-icon"></h3> Send patient level data </button> diff --git a/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.js b/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.js index 29d19c5..b5c8167 100644 --- a/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.js +++ b/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.js @@ -26,7 +26,8 @@ define([ display: "", }, requesterEmail: "Unknown", - disableUpload: "true", + sendGenoData: false, + sendPhenoData: false, }, }); var requestSearchResultView = BB.View.extend({ @@ -41,6 +42,8 @@ define([ this.uploadData = this.uploadData.bind(this); this.openVerifySend = this.openVerifySend.bind(this); this.onDownloadClick = this.onDownloadClick.bind(this); + this.toggleGeno = this.toggleGeno.bind(this); + this.togglePheno = this.togglePheno.bind(this); this.model.set("s3Directory", opts.queryResult.id); this.model.set("queryStartDate", opts.queryResult.date); this.model.set("queryId", opts.queryResult.uuid); @@ -57,12 +60,20 @@ define([ "click #data-store-help-button": "openDataStoreHelp", "click #upload-data-button": "openVerifySend", "click #refresh-status-btn": "fetchQueryStatus", + "click #pheno_check": "togglePheno", + "click #geno_check": "toggleGeno", "input #query-approved": "approveQueryForUpload", "change #site-select": "setSite" }, reset: function () { this.model.clear().set(this.model.defaults); }, + togglePheno() { + this.model.set('sendPhenoData', !this.model.get('sendPhenoData')) + }, + toggleGeno() { + this.model.set('sendGenoData', !this.model.get('sendGenoData')) + }, fetchQueryStatus() { var queryID = this.model.get("commonAreaID"); if (!queryID) { @@ -109,11 +120,9 @@ define([ this.model.set("phenotypicStatus", response.phenotypic); this.model.set("phenotypicStatusIcon", statusIconMapping[response.phenotypic]); - // Enable upload if neither geno/pheno are Uploaded or Uploading - this.model.set("disableUpload", (response.phenotypic + response.genomic).includes("Upload")); this.render(); }, - uploadData() { + uploadData(dataType) { var query = this.model.get("queryData").query; query.picSureId = this.model.get("commonAreaID"); if (!query.picSureId) { @@ -123,7 +132,7 @@ define([ var site = this.model.get("selectedSite"); var populateQueryStatus = this.populateQueryStatus; $.ajax({ - url: window.location.origin + "/picsure/proxy/uploader/upload/" + site, + url: window.location.origin + "/picsure/proxy/uploader/upload/" + site + "?dataType=" + dataType, headers: { Authorization: "Bearer " + JSON.parse(sessionStorage.getItem("session")).token, }, @@ -199,15 +208,25 @@ define([ $(".close").click(); $("#data-request-btn").focus(); }; - const onSend = this.uploadData; + const upload = this.uploadData; const data = { datasetUUID: this.model.get("queryId"), commonAreaID: this.model.get("commonAreaID"), site: this.model.get("site"), + sendPhenoData: this.model.get('sendPhenoData'), + sendGenoData: this.model.get('sendGenoData'), + }; + const onSend = function () { + if (data.sendGenoData) { + upload("Genomic"); + } + if (data.sendPhenoData) { + upload("Phenotypic"); + } }; modal.displayModal( - new confirmUpload({ onClose, onSend }), + new confirmUpload({ onClose, onSend }, data), "", onClose, { width: "19%" } diff --git a/ui/src/main/webapp/picsureui/requestSearch/verifySendModal.hbs b/ui/src/main/webapp/picsureui/requestSearch/verifySendModal.hbs index c9eb7b5..c8faf2d 100644 --- a/ui/src/main/webapp/picsureui/requestSearch/verifySendModal.hbs +++ b/ui/src/main/webapp/picsureui/requestSearch/verifySendModal.hbs @@ -1,8 +1,12 @@ <div id="upload-data-confirmation"> <div class="row"> - <div class="col-md-12" style="margin-bottom: 5px; text-align: center;"> - Are you sure you want to send {{datasetUUID}} - to {{site}} in folder {{commonAreaID}} for use in Service Workbench? + <div class="col-md-12" style="margin-bottom: 5px;"> + Are you sure you want to send to {{site}} in folder {{commonAreaID}} for use in Service Workbench? + The following data will be sent: + <ul> + {{#if sendPhenoData}}<li><i class="fa-solid fa-notes-medical"></i> Phenotypic Data</li>{{/if}} + {{#if sendGenoData}}<li><i class="fa-solid fa-dna"></i> Variant data for selected genes</li>{{/if}} + </ul> </div> </div> <div class="row"> diff --git a/ui/src/main/webapp/picsureui/requestSearch/verifySendModal.js b/ui/src/main/webapp/picsureui/requestSearch/verifySendModal.js index 24fdd42..57753be 100644 --- a/ui/src/main/webapp/picsureui/requestSearch/verifySendModal.js +++ b/ui/src/main/webapp/picsureui/requestSearch/verifySendModal.js @@ -6,9 +6,10 @@ define([ template, modal ){ return BB.View.extend({ - initialize : function(handlers){ + initialize : function(handlers, state){ this.template = HBS.compile(template); this.handlers = handlers; + Object.assign(this, state); }, events: { "click #verify-send-modal-cancel-btn": "onClose", From 5f342f04017d41f6faa076857e83b1dd1efb8dfa Mon Sep 17 00:00:00 2001 From: Luke Sikina <lucas.skina@gmail.com> Date: Wed, 21 Feb 2024 11:25:59 -0500 Subject: [PATCH 2/2] [ALS-5832] Add a few modals to data requests tab --- .../requestSearch/alertUploadTime.hbs | 23 ++++++++++ .../requestSearch/alertUploadTime.js | 32 +++++++++++++ .../picsureui/requestSearch/dataTypesHelp.hbs | 14 ++++++ .../picsureui/requestSearch/dataTypesHelp.js | 24 ++++++++++ .../requestSearch/requestSearchResult.hbs | 12 ++--- .../requestSearch/requestSearchResult.js | 45 +++++++++++++++++-- .../requestSearch/verifySendModal.hbs | 32 ++++++------- 7 files changed, 154 insertions(+), 28 deletions(-) create mode 100644 ui/src/main/webapp/picsureui/requestSearch/alertUploadTime.hbs create mode 100644 ui/src/main/webapp/picsureui/requestSearch/alertUploadTime.js create mode 100644 ui/src/main/webapp/picsureui/requestSearch/dataTypesHelp.hbs create mode 100644 ui/src/main/webapp/picsureui/requestSearch/dataTypesHelp.js diff --git a/ui/src/main/webapp/picsureui/requestSearch/alertUploadTime.hbs b/ui/src/main/webapp/picsureui/requestSearch/alertUploadTime.hbs new file mode 100644 index 0000000..c71fb81 --- /dev/null +++ b/ui/src/main/webapp/picsureui/requestSearch/alertUploadTime.hbs @@ -0,0 +1,23 @@ +<div id="upload-data-alert"> + <div class="row"> + <div class="col-md-12" style="margin-bottom: 5px;"> + <p>Sending data from PIC-SURE to Service Workbench can take several minutes.</p> + <p>To update the status of your data upload, click the refresh button <i class="fa-solid fa-arrows-rotate"></i></p> + </div> + </div> + <div class="row"> + <section id="buttons" style="display: flex; flex-direction: column; align-items: center;"> + <button + id="upload-data-alert-ok-btn" class="btn btn-outline tabable" + tabindex="1" type="button" style="width: 100px;" + > + Ok, Got it! + </button> + <div> + <input type="checkbox" id="upload-data-alert-no-remind"> + <label for="upload-data-alert-no-remind">Don't show this again.</label> + </div> + </section> + </div> + +</div> \ No newline at end of file diff --git a/ui/src/main/webapp/picsureui/requestSearch/alertUploadTime.js b/ui/src/main/webapp/picsureui/requestSearch/alertUploadTime.js new file mode 100644 index 0000000..eafd7a0 --- /dev/null +++ b/ui/src/main/webapp/picsureui/requestSearch/alertUploadTime.js @@ -0,0 +1,32 @@ +define([ + "jquery", "backbone", "handlebars", "underscore", + "text!requestSearch/alertUploadTime.hbs", "common/modal" +], function( + $, BB, HBS, _, + template, modal +){ + return BB.View.extend({ + initialize : function(handlers){ + this.template = HBS.compile(template); + this.handlers = handlers; + }, + events: { + "click #upload-data-alert-cancel-btn": "onClose", + "click #upload-data-alert-ok-btn": "onClose", + "click #upload-data-alert-no-remind": "dontRemindMe", + }, + onClose: function() { + this.handlers.onClose(this); + }, + render: function(){ + this.$el.html(this.template(this)); + $(".modal-header").css("display", "none"); + $(".modal-footer").css("display", "none"); + $(".modal-dialog").css("margin-top", "20%"); + modal.createTabIndex(); // always do this at end + }, + dontRemindMe: function() { + localStorage.setItem("disable-upload-reminder", true); + } + }); +}); \ No newline at end of file diff --git a/ui/src/main/webapp/picsureui/requestSearch/dataTypesHelp.hbs b/ui/src/main/webapp/picsureui/requestSearch/dataTypesHelp.hbs new file mode 100644 index 0000000..76a421b --- /dev/null +++ b/ui/src/main/webapp/picsureui/requestSearch/dataTypesHelp.hbs @@ -0,0 +1,14 @@ +<div id="data-types-help"> + <ul> + <li> + <b>Phenotypic Data: </b>Clinical data, electronic health record information + </li> + <li> + <b>Annotated variant data for selected genes: </b>The annotated variant data is sourced from the combined, + annotated VCF and represents the patient cohort selected by the applied genomic and clinical filters. The + original sample VCFs have been annotated using the Ensembl Variant Effect Predictor (VEP) to provide + additional annotations and determine the effects of each variant. Modifier variants have been removed. + To learn more visit the <a href="https://pic-sure.gitbook.io/genomic-information-commons/pic-sure-features/variant-explorer">User Guide</a>. + </li> + </ul> +</div> \ No newline at end of file diff --git a/ui/src/main/webapp/picsureui/requestSearch/dataTypesHelp.js b/ui/src/main/webapp/picsureui/requestSearch/dataTypesHelp.js new file mode 100644 index 0000000..b43a8eb --- /dev/null +++ b/ui/src/main/webapp/picsureui/requestSearch/dataTypesHelp.js @@ -0,0 +1,24 @@ +define([ + "jquery", "backbone", "handlebars", "underscore", + "text!requestSearch/dataTypesHelp.hbs", "common/modal" +], function( + $, BB, HBS, _, + template, modal +){ + return BB.View.extend({ + initialize : function(handlers){ + this.template = HBS.compile(template); + this.handlers = handlers; + }, + events: { + "click #data-types-help-close-btn": "onClose", + }, + onClose: function() { + this.handlers.onClose(this); + }, + render: function(){ + this.$el.html(this.template(this)); + modal.createTabIndex(); // always do this at end + } + }); +}); \ No newline at end of file diff --git a/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.hbs b/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.hbs index f5ad914..c46950c 100644 --- a/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.hbs +++ b/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.hbs @@ -36,7 +36,8 @@ <i id="data-store-help-button" class="fa-regular fa-circle-question" style="margin-left: 5px;"></i> </div> <div class="col-md-4 request-result-header"> - <h4 style="display: inline;">Send Data to SWB</h4> + <h4 style="display: inline;">Select & Send Data</h4> + <i id="data-types-help-button" class="fa-regular fa-circle-question" style="margin-left: 5px;"></i> </div> <div class="col-md-4 request-result-header"> <h4 style="display: inline;">Status</h4> @@ -60,16 +61,15 @@ <div style="width: 100%;"> <div> <input type="checkbox" id="pheno_check" name="pheno_check" {{#if sendPhenoData}}checked{{/if}}> - <label for="pheno_check"><i class="fa-solid fa-notes-medical"></i> Phenotypic Data</label> + <label style="font-weight: normal;" for="pheno_check">Phenotypic data</label> </div> <div> <input type="checkbox" id="geno_check" name="geno_check" {{#if sendGenoData}}checked{{/if}}> - <label for="geno_check"><i class="fa-solid fa-dna"></i> Annotated variant data for selected genes</label> + <label style="font-weight: normal;" for="geno_check">Annotated variant data for selected genes</label> </div> </div> - <button id="upload-data-button" class="super-rounded"> - <h3 class="fa-solid fa-arrow-up-from-bracket request-result-icon"></h3> - Send patient level data + <button id="upload-data-button" class="btn btn-outline success super-rounded"> + Send Data </button> </div> <div class="col-md-4 request-result-header"> diff --git a/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.js b/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.js index b5c8167..34dbbf2 100644 --- a/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.js +++ b/ui/src/main/webapp/picsureui/requestSearch/requestSearchResult.js @@ -1,14 +1,18 @@ define([ "backbone", "handlebars", "text!requestSearch/requestSearchResult.hbs", - "common/modal", "dataset/dataset-view", "requestSearch/dataStoreLocationHelp", "requestSearch/verifySendModal" + "common/modal", "dataset/dataset-view", "requestSearch/dataStoreLocationHelp", "requestSearch/verifySendModal", + "requestSearch/alertUploadTime", "requestSearch/dataTypesHelp", ], function ( BB, HBS, requestSearchResultTemplate, - modal, viewDataset, viewHelp, confirmUpload + modal, viewDataset, viewHelp, confirmUpload, + alertUploadTime, dataTypesHelp ) { var statusIconMapping = { 'Uploaded': 'fa-circle-check', + 'Querying': 'fa-magnifying-glass', + 'Queued': 'fa-hourglass', 'Unsent': 'fa-circle-xmark', 'Unknown': 'fa-circle-question', 'Error': 'fa-circle-xmark', @@ -42,6 +46,7 @@ define([ this.uploadData = this.uploadData.bind(this); this.openVerifySend = this.openVerifySend.bind(this); this.onDownloadClick = this.onDownloadClick.bind(this); + this.displayAlertThenPopulateStatus = this.displayAlertThenPopulateStatus.bind(this); this.toggleGeno = this.toggleGeno.bind(this); this.togglePheno = this.togglePheno.bind(this); this.model.set("s3Directory", opts.queryResult.id); @@ -58,6 +63,7 @@ define([ "click .request-result-data-button": "onDownloadClick", "click #data-request-btn": "openDataRequestModal", "click #data-store-help-button": "openDataStoreHelp", + "click #data-types-help-button": "openDataTypesHelp", "click #upload-data-button": "openVerifySend", "click #refresh-status-btn": "fetchQueryStatus", "click #pheno_check": "togglePheno", @@ -112,6 +118,24 @@ define([ this.model.set("homeSite", { site: response.homeSite, display: response.homeDisplay }); this.render(); }, + displayAlertThenPopulateStatus(response) { + if (localStorage.getItem("disable-upload-reminder") === 'true') { + this.populateQueryStatus(response); + } else { + const populateQueryStatus = this.populateQueryStatus; + const onClose = (view) => { + $(".close").click(); + $("#data-request-btn").focus(); + populateQueryStatus(response); + }; + modal.displayModal( + new alertUploadTime({ onClose }), + "", + onClose, + { width: "19%" } + ); + } + }, populateQueryStatus(response) { this.model.set("approved", response.approved); this.model.set("site", response.site); @@ -130,7 +154,7 @@ define([ query.picSureId = this.model.get("queryId"); } var site = this.model.get("selectedSite"); - var populateQueryStatus = this.populateQueryStatus; + var displayAlertThenPopulateStatus = this.displayAlertThenPopulateStatus; $.ajax({ url: window.location.origin + "/picsure/proxy/uploader/upload/" + site + "?dataType=" + dataType, headers: { @@ -139,7 +163,7 @@ define([ data: JSON.stringify(query), contentType: "application/json", type: "POST", - success: populateQueryStatus, + success: displayAlertThenPopulateStatus, dataType: "json", }); }, @@ -203,6 +227,19 @@ define([ { width: "50%" } ); }, + openDataTypesHelp: function(){ + const onClose = (view) => { + $(".close").click(); + $("#data-request-btn").focus(); + }; + + modal.displayModal( + new dataTypesHelp({ onClose }), + "Data Types", + onClose, + { width: "50%" } + ); + }, openVerifySend: function(){ const onClose = (view) => { $(".close").click(); diff --git a/ui/src/main/webapp/picsureui/requestSearch/verifySendModal.hbs b/ui/src/main/webapp/picsureui/requestSearch/verifySendModal.hbs index c8faf2d..dde8f7a 100644 --- a/ui/src/main/webapp/picsureui/requestSearch/verifySendModal.hbs +++ b/ui/src/main/webapp/picsureui/requestSearch/verifySendModal.hbs @@ -1,32 +1,28 @@ <div id="upload-data-confirmation"> <div class="row"> <div class="col-md-12" style="margin-bottom: 5px;"> - Are you sure you want to send to {{site}} in folder {{commonAreaID}} for use in Service Workbench? - The following data will be sent: + Are you sure you want to send: <ul> {{#if sendPhenoData}}<li><i class="fa-solid fa-notes-medical"></i> Phenotypic Data</li>{{/if}} {{#if sendGenoData}}<li><i class="fa-solid fa-dna"></i> Variant data for selected genes</li>{{/if}} </ul> + to {{site}} GIC Service Workbench? </div> </div> <div class="row"> - <section id="buttons" class="row"> - <div class="col-md-6"> - <button + <section id="buttons" style="display: flex; justify-content: space-around;"> + <button id="verify-send-modal-cancel-btn" class="btn btn-outline secondary tabable" - tabindex="0" type="button" style="width: 100px;" - > - Cancel - </button> - </div> - <div class="col-md-6"> - <button - id="verify-send-modal-send-btn" class="btn btn-outline action tabable" - tabindex="1" type="button" style="width: 100px;" - > - Send - </button> - </div> + tabindex="0" type="button" style="width: 80px;" + > + Cancel + </button> + <button + id="verify-send-modal-send-btn" class="btn btn-outline success tabable" + tabindex="1" type="button" style="width: 80px;" + > + Send + </button> </section> </div>