Skip to content

Commit

Permalink
Made online output tools available for async-watched exports
Browse files Browse the repository at this point in the history
GuilhemSempere committed Aug 27, 2024
1 parent 1209814 commit 290fc2f
Showing 4 changed files with 355 additions and 283 deletions.
229 changes: 146 additions & 83 deletions src/main/webapp/ProgressWatch.jsp
Original file line number Diff line number Diff line change
@@ -1,84 +1,147 @@
<%--
* GIGWA - Genotype Investigator for Genome Wide Analyses
* Copyright (C) 2016 - 2019, <CIRAD> <IRD>
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License, version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* See <http://www.gnu.org/licenses/agpl.html> for details about GNU General
* Public License V3.
--%>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="UTF-8" import="fr.cirad.web.controller.gigwa.GigwaRestController"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>

<head>
<script type="text/javascript" src="js/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="<c:url value="/js/common.js" />"></script>
<link rel="shortcut icon" href="images/favicon.png" type="image/x-icon" />
<link type="text/css" rel="stylesheet" href="css/bootstrap.min.css">
<link type="text/css" rel="stylesheet" href="css/main.css">
<script type="text/javascript">
var progressUrl = "<c:url value='<%=GigwaRestController.REST_PATH + GigwaRestController.BASE_URL + GigwaRestController.PROGRESS_PATH%>' />";
var abortUrl = "<c:url value='<%=GigwaRestController.REST_PATH + GigwaRestController.BASE_URL + GigwaRestController.ABORT_PROCESS_PATH%>' />";
var destinationLink = "${param.successURL}";
var fileName = destinationLink.substring(destinationLink.lastIndexOf("/") + 1);
if (fileName.startsWith("?"))
fileName = location.origin + '<c:url value='/' />' + fileName;
var processAborted = false;
function watchProgress()
{
$.ajax({
url: progressUrl<c:if test="${param.process != null}">+'?progressToken=${param.process}'</c:if>,
type: "GET",
async: false,
<c:if test="${param.token != null}">headers: { "Authorization": "Bearer ${param.token}" },</c:if>
success: function (jsonResult) {
if (jsonResult == null)
$('body').append('<center><p style="margin-top:60px;" class="bold">No such process is running at the moment.</p><p>Refresh to try again or use the link below to access resulting data in case the process has already finished:<br/><br/><a style="cursor:pointer;" href="' + destinationLink + '">' + (fileName == '?' ? destinationLink : fileName) + '</a></p></center>');
else
{
$('#progress').modal({backdrop: 'static', keyboard: false, show: true});
$('.modal-backdrop.in').css('opacity', '0.1');
displayProcessProgress(5, <c:choose><c:when test="${param.token != null}">'${param.token}'</c:when><c:otherwise>null</c:otherwise></c:choose>, '${param.process}');
$('#progress').on('hidden.bs.modal', function () {
if (processAborted)
$('body').append('<center><p style="margin-top:60px;" class="bold">Process aborted</p></center>');
else if (!$('#progress').data('error'))
$('body').append('<center><p style="margin-top:60px;" class="bold">Process has completed. Data is now <a style="cursor:pointer;" href="' + destinationLink + '">available here</a></center>');
});
}
},
error: function (xhr, ajaxOptions, thrownError) {
handleError(xhr, thrownError);
}
});
$("div.modal-backdrop").remove();
}
</script>
<title>Gigwa process watcher</title>
</head>

<body style='background-color:#f0f0f0;' onload="$('button#abortButton').css('display', ${param.abortable eq 'true'} ? 'inline' : 'none'); watchProgress();">
<div style='background-color:white; width:100%; padding:5px;'><img src="<c:url value='/images/logo.png' />" height="25"></div>
<div id='progress' style='margin-top:50px; margin-left:20%; width:60%; display:block; text-align:center; display:none;'>
<p>This process is running as a background task.</p>
<p>You may leave the main Gigwa page and either keep this one open or copy its URL to check again later.</p>
<h2 id="progressText" class="loading-message" style='margin-top:50px'>Please wait...</h2>
<button class="btn btn-danger btn-sm" id="abortButton" style="display:none;" type="button" name="abort" onclick="if (confirm('Are you sure?')) abort('${param.process}');">Abort</button>
</div>
</body>

<%--
* GIGWA - Genotype Investigator for Genome Wide Analyses
* Copyright (C) 2016 - 2019, <CIRAD> <IRD>
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License, version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* See <http://www.gnu.org/licenses/agpl.html> for details about GNU General
* Public License V3.
--%>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="UTF-8" import="fr.cirad.web.controller.gigwa.GigwaRestController"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<jsp:useBean id="appConfig" class="fr.cirad.tools.AppConfig" />

<html>

<head>
<script type="text/javascript" src="js/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="<c:url value="/js/common.js" />"></script>
<link rel="shortcut icon" href="images/favicon.png" type="image/x-icon" />
<link type="text/css" rel="stylesheet" href="css/bootstrap.min.css">
<link type="text/css" rel="stylesheet" href="css/main.css">
<script type="text/javascript">
var progressUrl = "<c:url value='<%=GigwaRestController.REST_PATH + GigwaRestController.BASE_URL + GigwaRestController.PROGRESS_PATH%>' />";
var abortUrl = "<c:url value='<%=GigwaRestController.REST_PATH + GigwaRestController.BASE_URL + GigwaRestController.ABORT_PROCESS_PATH%>' />";
var downloadURL = "${param.successURL}";
var fileName = downloadURL.substring(downloadURL.lastIndexOf("/") + 1);
if (fileName.startsWith("?"))
fileName = location.origin + '<c:url value='/' />' + fileName;
var processAborted = false;
<c:if test="${param.exportFormat != null}">
var galaxyPushURL = '<c:url value="<%=GigwaRestController.REST_PATH + GigwaRestController.BASE_URL + GigwaRestController.GALAXY_HISTORY_PUSH%>" />';
var onlineOutputTools = null;
var igvDataLoadPort, igvGenomeListUrl;
<c:set var="igvDataLoadPort" value="<%= appConfig.get(\"igvDataLoadPort\") %>"></c:set>
<c:set var="igvGenomeListUrl" value="<%= appConfig.get(\"igvGenomeListUrl\") %>"></c:set>
<c:if test='${!fn:startsWith(igvDataLoadPort, "??") && !empty igvDataLoadPort && !fn:startsWith(igvGenomeListUrl, "??") && !empty igvGenomeListUrl}'>
igvDataLoadPort = ${igvDataLoadPort};
igvGenomeListUrl = '<c:url value="<%=GigwaRestController.REST_PATH + GigwaRestController.BASE_URL + GigwaRestController.IGV_GENOME_LIST_URL %>" />';
</c:if>
$.ajax({
url: '<c:url value="<%=GigwaRestController.REST_PATH + GigwaRestController.BASE_URL + GigwaRestController.ONLINE_OUTPUT_TOOLS_URL%>" />',
async: true,
type: "GET",
contentType: "application/json;charset=utf-8",
success: function(labelsAndURLs) {
onlineOutputTools = labelsAndURLs;
onlineOutputTools["Custom tool"] = {"url" : "", "formats" : ""};
},
error: function(xhr, thrownError) {
handleError(xhr, thrownError);
}
});
</c:if>
function watchProgress()
{
$.ajax({
url: progressUrl<c:if test="${param.process != null}">+'?progressToken=${param.process}'</c:if>,
type: "GET",
async: false,
<c:if test="${param.token != null}">headers: { "Authorization": "Bearer ${param.token}" },</c:if>
success: function (jsonResult) {
if (jsonResult == null) {
$('body').append('<center id="defaultMsg"><p style="margin-top:60px;" class="bold">No such process is running at the moment.</p><p>Refresh to try again or use the link below to access resulting data in case the process has already finished:<br/><br/><a style="cursor:pointer;" href="' + downloadURL + '">' + (fileName == '?' ? downloadURL : fileName) + '</a></p></center>');
<c:if test="${param.exportFormat != null}">
$.ajax({
type: 'HEAD',
url: downloadURL,
success: function(data, textStatus, jqXHR) {
if (jqXHR.status >= 200 && jqXHR.status < 300) {
successFunction();
$("#defaultMsg").remove();
}
}
});
</c:if>
}
else
{
$('#progress').modal({backdrop: 'static', keyboard: false, show: true});
$('.modal-backdrop.in').css('opacity', '0.1');
displayProcessProgress(5, <c:choose><c:when test="${param.token != null}">'${param.token}'</c:when><c:otherwise>null</c:otherwise></c:choose>, '${param.process}'<c:if test="${param.exportFormat != null}">, successFunction</c:if>);
$('#progress').on('hidden.bs.modal', function () {
if (processAborted)
$('body').append('<center><p style="margin-top:60px;" class="bold">Process aborted</p></center>');
<c:if test="${param.exportFormat == null}">
else if (!$('#progress').data('error'))
$('body').append('<center><p style="margin-top:60px;" class="bold">Process has completed. Data is now <a style="cursor:pointer;" href="' + downloadURL + '">available here</a></center>');
</c:if>
$('#progress').off('hidden.bs.modal');
});
}
},
error: function (xhr, ajaxOptions, thrownError) {
handleError(xhr, thrownError);
}
});
$("div.modal-backdrop").remove();
}
<c:if test="${param.exportFormat != null}">
function successFunction() {
let fileExtensions = "${param.exportFormatExtensions}".split(";");
<c:if test="${param.exportedTsvMetadata eq true}">
fileExtensions.push("tsv");
</c:if>
showServerExportBox(fileExtensions);
}
</c:if>
</script>
<title>Gigwa process watcher</title>
</head>
<body style='background-color:#f0f0f0;' onload="$('button#abort').css('display', ${param.abortable eq 'true'} ? 'inline' : 'none'); watchProgress();">
<c:if test="${param.exportFormat != null}">
<input type="hidden" id="exportFormat" value="${param.exportFormat}" />
<input type="hidden" id="module" value="${param.module}" />
<input type="hidden" id="galaxyInstanceURL" value="${param.galaxyInstanceUrl}" />
<input type="hidden" id="exportedIndividualCount" value="${param.exportedIndividualCount}" />
<input type="hidden" id="count" value="${param.exportedVariantCount}" />
</c:if>
<div style='background-color:white; width:100%; padding:5px;'><img src="<c:url value='/images/logo.png' />" height="25"></div>
<div id='progress' style='margin-top:50px; margin-left:20%; width:60%; display:block; text-align:center; display:none;'>
<p>This process is running as a background task.</p>
<p>You may leave the main Gigwa page and either keep this one open or copy its URL to check again later.</p>
<h2 id="progressText" class="loading-message" style='margin-top:100px'>Please wait...</h2>
<button class="btn btn-danger btn-sm" id="abort" style="display:none;" type="button" name="abort" onclick="if (confirm('Are you sure?')) abort('${param.process}');">Abort</button>
</div>
<div id="serverExportBox" class="panel" style="position:absolute; margin:0; top:50px; left:calc(50% - 250px); width:400px;"></div>
</body>
</html>
11 changes: 8 additions & 3 deletions src/main/webapp/index.jsp
Original file line number Diff line number Diff line change
@@ -333,7 +333,7 @@ https://doi.org/10.1093/gigascience/giz051</pre>
<h3 class="loading-message"><span id="progressText" class="loading-message">Please wait...</span><span id="ddlWarning" style="display:none;"><br/><br/>Output file is being generated and will not be valid before this message disappears</span></h3>
<br/>
<button style="display:inline; margin-right:10px;" class="btn btn-danger btn-sm" type="button" name="abort" id='abort' onclick="abort($(this).attr('rel')); $('a#exportBoxToggleButton').removeClass('active');">Abort</button>
<button style="display:inline; margin-left:10px;" id="asyncProgressButton" class="btn btn-info btn-sm" type="button" onclick="window.open('ProgressWatch.jsp?process=export_' + token + '&abortable=true&successURL=' + escape(downloadURL));" title="This will open a separate page allowing to watch export progress at any time. Leaving the current page will not abort the export process.">Open async progress watch page</button>
<button style="display:inline; margin-left:10px;" id="asyncProgressButton" class="btn btn-info btn-sm" type="button" onclick="window.open('ProgressWatch.jsp?process=export_' + token + '&abortable=true&successURL=' + escape(downloadURL) + '&module=' + getModuleName() + '&exportFormat=' + $('#exportFormat').val() + '&galaxyInstanceUrl=' + $('#galaxyInstanceURL').val() + '&exportedVariantCount=' + count + '&exportedIndividualCount=' + exportedIndividualCount + '&exportFormatExtensions=' + $('#exportFormat option:selected').data('ext') + '&exportedTsvMetadata=' + ($('#exportPanel input#exportedIndividualMetadataCheckBox').is(':checked') && 'FLAPJACK' != $('#exportFormat').val() && 'DARWIN' != $('#exportFormat').val()));" title="This will open a separate page allowing to watch export progress at any time. Leaving the current page will not abort the export process.">Open async progress watch page</button>
</div>
</div>
</div>
@@ -784,7 +784,7 @@ https://doi.org/10.1093/gigascience/giz051</pre>
});
$.ajax({
url: '<c:url value="<%=GigwaRestController.REST_PATH + GigwaRestController.BASE_URL + GigwaRestController.ONLINE_OUTPUT_TOOLS_URL%>" />?module=' + referenceset,
url: '<c:url value="<%=GigwaRestController.REST_PATH + GigwaRestController.BASE_URL + GigwaRestController.ONLINE_OUTPUT_TOOLS_URL%>" />',
async: false,
type: "GET",
contentType: "application/json;charset=utf-8",
@@ -1961,7 +1961,12 @@ https://doi.org/10.1093/gigascience/giz051</pre>
$("div#exportPanel").hide();
$("a#exportBoxToggleButton").removeClass("active");
}
displayProcessProgress(2, "export_" + token, null, showServerExportBox);
displayProcessProgress(2, "export_" + token, null, function() {
let fileExtensions = $("#exportFormat option:selected").data('ext').split(";");
if ($('#exportPanel input#exportedIndividualMetadataCheckBox').is(':checked') && "FLAPJACK" != $('#exportFormat').val() && "DARWIN" != $('#exportFormat').val() /* these two already have their own metadata file format*/)
fileExtensions.push("tsv");
showServerExportBox(fileExtensions);
});
}
function postDataToIFrame(frameName, url, params)
201 changes: 201 additions & 0 deletions src/main/webapp/js/common.js
Original file line number Diff line number Diff line change
@@ -307,4 +307,205 @@ function grabNcbiTaxon(inputObj)
$(inputObj).attr('species', genus + " " + species);

$(inputObj).val(taxonName);
}

function showServerExportBox(exportFormatExtensions)
{
$("div#exportPanel").hide();
$("a#exportBoxToggleButton").removeClass("active");
if (processAborted || downloadURL == null)
return;

var fileName = downloadURL.substring(downloadURL.lastIndexOf("/") + 1);
$('#serverExportBox').html('<button type="button" class="close" data-dismiss="modal" aria-hidden="true" style="float:right;" onclick="$(\'#serverExportBox\').hide();">x&nbsp;</button></button>&nbsp;Export file will be available at this URL for 48h:<br/><a id="exportOutputUrl" download href="' + downloadURL + '">' + fileName + '</a> ').show();
var exportedFormat = $('#exportFormat').val().toUpperCase();
if ("VCF" == exportedFormat)
addIgvExportIfRunning();
else if ("FLAPJACK" == exportedFormat)
addFjBytesExport();

var archivedDataFiles = new Array();
for (var key in exportFormatExtensions)
archivedDataFiles[exportFormatExtensions[key]] = location.origin + downloadURL.replace(new RegExp(/\.[^.]*$/), '.' + exportFormatExtensions[key]);

var galaxyInstanceUrl = $("#galaxyInstanceURL").val().trim();
if (galaxyInstanceUrl.startsWith("http")) {
var fileURLs = "";
for (key in archivedDataFiles)
fileURLs += (fileURLs == "" ? "" : " ,") + "'" + archivedDataFiles[key] + "'";
$('#serverExportBox').append('<br/><br/>&nbsp;<input type="button" value="Send exported data to Galaxy" onclick="sendToGalaxy([' + fileURLs + ']);" />&nbsp;');
}

if (onlineOutputTools != null)
for (var toolName in onlineOutputTools) {
var toolConfig = getOutputToolConfig(toolName);
if (toolConfig['url'] != null && toolConfig['url'].trim() != "" && (toolConfig['formats'] == null || toolConfig['formats'].trim() == "" || toolConfig['formats'].toUpperCase().split(",").includes($('#exportFormat').val().toUpperCase()))) {

var formatsForThisButton = "", urlForThisButton = toolConfig['url'];
var matchResult = urlForThisButton.match(/{([^}]+)}/g);
if (matchResult != null) {
var placeHolders = matchResult.map(res => res.replace(/{|}/g , ''));
phLoop: for (var i in placeHolders) {
var phFormats = placeHolders[i].split("\|");
for (var j in phFormats) {
for (var key in archivedDataFiles) {
if (key == phFormats[j]) {
formatsForThisButton += (formatsForThisButton == "" ? "" : ", ") + key;
urlForThisButton = urlForThisButton.replace("\{" + placeHolders[i] + "\}", archivedDataFiles[key]);
continue phLoop;
}
}
}
console.log("unused param: " + placeHolders[i]);
urlForThisButton = urlForThisButton.replace("\{" + placeHolders[i] + "\}", "");
}
}

if (urlForThisButton == toolConfig['url'] && urlForThisButton.indexOf("*") != -1) {
urlForThisButton = urlForThisButton.replace("\*", Object.values(archivedDataFiles).join(","));
formatsForThisButton = Object.keys(archivedDataFiles).join(", ");
}

if (formatsForThisButton != "")
$('#serverExportBox').append('<br/><br/>&nbsp;<input type="button" value="Send ' + formatsForThisButton + ' file(s) to ' + toolName + '" onclick="window.open(\'' + urlForThisButton + '\');" />&nbsp;')
}
}
}

function getOutputToolConfig(toolName)
{
var storedToolConfig = localStorage.getItem("outputTool_" + toolName);
return storedToolConfig != null ? JSON.parse(storedToolConfig) : onlineOutputTools[toolName];
}

function addIgvExportIfRunning() {
if (igvDataLoadPort == null)
return;

var igvGenomeOptions = null;
$.ajax({
type:"GET",
url:"http://127.0.0.1:" + igvDataLoadPort,
success:function(jsonResult) {
if ("ERROR Unknown command: /" == jsonResult)
{
if (igvGenomeOptions == null)
{
var genomeList = $.ajax({
async:false,
type:"GET",
url:igvGenomeListUrl,
crossDomain : true,
error:function(xhr, ajaxOptions, thrownError) {}
});

igvGenomeOptions = "<option>&nbsp;</option>";
if (genomeList.responseText != null)
{
var genomeLines = genomeList.responseText.split("\n");
for (var i=0; i<genomeLines.length; i++)
if (i > 0 || !genomeLines[i].startsWith("<")) // skip header
{
var genomeFields = genomeLines[i].split("\t");
if (genomeFields.length == 3)
igvGenomeOptions += "<option value='" + genomeFields[2] + "'>" + genomeFields[0] + "</option>";
}
}
$('div#serverExportBox').append("<br/><br/><center><table><tr><th valign='middle'>View in IGV within genomic/structural context&nbsp;</th></tr><tr><td align='center'><select id='igvGenome' style='min-width:175px;'>" + igvGenomeOptions + "</select><br/>(you may select a genome to switch to)</td><td valign='top'>&nbsp;<input type='button' value='Send' onclick='sendToIGV();'/></td></tr></table></center>");
}
}
},
error:function(xhr, ajaxOptions, thrownError) {
//handleError(xhr, ajaxOptions, thrownError);
console.log("Unable to find IGV instance");
}
});
}

function addFjBytesExport() {
$('div#serverExportBox').append("<br/><br/><center><input type='button' value='View in Flapjack-Bytes' onclick='sendToFjBytes();'/>" + (exportedIndividualCount * count > 500000000 ? "<div class='text-red margin-top'>WARNING: Exported dataset potentially contains more than 500 million genotypes.<br/>A standard workstation's web-browser may be unable to load it in with Flapjack-Bytes </div>" : "") + "</center>");
}

function sendToGalaxy(archivedDataFiles) {
var galaxyInstanceUrl = $("#galaxyInstanceURL").val().trim(), apiKey = sessionStorage.getItem("galaxyApiKey::" + galaxyInstanceUrl);
if (apiKey == null)
apiKey = prompt("Enter the API key tied to your account on\n" + galaxyInstanceUrl);
if (apiKey != null && apiKey.trim() != "") {
sessionStorage.setItem("galaxyApiKey::" + galaxyInstanceUrl, apiKey);
$('#progressText').html("Pushing files to " + galaxyInstanceUrl + " ...");
$('#asyncProgressButton').hide();
$('button#abort').hide();
$('#progress').modal({
backdrop: 'static',
keyboard: false,
show: true
});
setTimeout(function() {
var n = 0, responseMsg = null;
for (var fileUrl in archivedDataFiles)
$.ajax({
async: false,
url: galaxyPushURL + "?galaxyUrl=" + galaxyInstanceUrl + "&galaxyApiKey=" + apiKey + "&fileUrl=" + archivedDataFiles[fileUrl],
type: "GET",
success: function(respString) {
responseMsg = respString;
n++;
},
error: function(xhr, ajaxOptions, thrownError) {
$('#progress').modal('hide');

if (xhr.status == 403) {
console.log("Removing invalid Galaxy API key: " + apiKey);
sessionStorage.removeItem("galaxyApiKey::" + galaxyInstanceUrl);
}

if (thrownError == "" && xhr.getAllResponseHeaders() == '')
alert("Error accessing resource: " + genomeURL);
else
handleError(xhr, thrownError);
}
});
if (n > 0)
if (confirm(n + " file(s) " + responseMsg + "\nOpen a window pointing to that Galaxy instance?"))
window.open(galaxyInstanceUrl);
$('#progress').modal('hide');
}, 1);
}
}

function sendToFjBytes() {
let url = "fjbytes.html?m=" + location.origin + $("a#exportOutputUrl").attr("href").replace(new RegExp(/\.[^.]*$/), '.map') +
"&g=" + location.origin + $("a#exportOutputUrl").attr("href").replace(new RegExp(/\.[^.]*$/), '.genotype') +
"&p=" + location.origin + $("a#exportOutputUrl").attr("href").replace(new RegExp(/\.[^.]*$/), '.phenotype') +
"&id=" + getModuleName();

if ($("#fjBytesPanel").length == 0) {
location.href = url;
return;
}

$("#fjBytesPanel").modal({
opacity: 80,
overlayCss: {
backgroundColor: "#111111"
}
});

$('#fjBytesPanelHeader').html('<center>This is a functionality under development and might not be totally stable. Check <a href="https://github.com/cropgeeks/flapjack-bytes" target="_blank">https://github.com/cropgeeks/flapjack-bytes</a> for information about Flapjack-Bytes.&nbsp;&nbsp;&nbsp;<a href="' + url + '" onclick="$(\'#fjBytesPanel\').modal(\'hide\');" target="_blank">Open in separate window</a></center>');
$("#fjBytesFrame").attr('src', url);
}

function sendToIGV(genomeID)
{
var genomeID = $("select#igvGenome").val();
$.ajax({
type:"GET",
url:"http://127.0.0.1:" + igvDataLoadPort + "/load?" + (genomeID != "" ? "genome=" + genomeID + "&" : "") + "file=" + location.origin + $("a#exportOutputUrl").attr("href").replace(new RegExp(/\.[^.]*$/), '.vcf'),
success:function(tsvResult) {
alert("Variant list was sent to IGV!");
},
error:function(xhr, ajaxOptions, thrownError) {
handleError(xhr, ajaxOptions, thrownError);
}
});
}
197 changes: 0 additions & 197 deletions src/main/webapp/js/main.js
Original file line number Diff line number Diff line change
@@ -22,85 +22,6 @@ var igvGenomeOptions = null;
var filtersToColumns = new Array();


function addIgvExportIfRunning() {
if (igvDataLoadPort == null)
return;

var igvGenomeOptions = null;
$.ajax({
type:"GET",
url:"http://127.0.0.1:" + igvDataLoadPort,
success:function(jsonResult) {
if ("ERROR Unknown command: /" == jsonResult)
{
if (igvGenomeOptions == null)
{
var genomeList = $.ajax({
async:false,
type:"GET",
url:igvGenomeListUrl,
crossDomain : true,
error:function(xhr, ajaxOptions, thrownError) {}
});

igvGenomeOptions = "<option>&nbsp;</option>";
if (genomeList.responseText != null)
{
var genomeLines = genomeList.responseText.split("\n");
for (var i=0; i<genomeLines.length; i++)
if (i > 0 || !genomeLines[i].startsWith("<")) // skip header
{
var genomeFields = genomeLines[i].split("\t");
if (genomeFields.length == 3)
igvGenomeOptions += "<option value='" + genomeFields[2] + "'>" + genomeFields[0] + "</option>";
}
}
$('div#serverExportBox').append("<br/><br/><center><table><tr><th valign='middle'>View in IGV within genomic/structural context&nbsp;</th></tr><tr><td align='center'><select id='igvGenome' style='min-width:175px;'>" + igvGenomeOptions + "</select><br/>(you may select a genome to switch to)</td><td valign='top'>&nbsp;<input type='button' value='Send' onclick='sendToIGV();'/></td></tr></table></center>");
}
}
},
error:function(xhr, ajaxOptions, thrownError) {
//handleError(xhr, ajaxOptions, thrownError);
console.log("Unable to find IGV instance");
}
});
}

function addFjBytesExport() {
$('div#serverExportBox').append("<br/><br/><center><input type='button' value='View in Flapjack-Bytes' onclick='sendToFjBytes();'/>" + (exportedIndividualCount * count > 500000000 ? "<div class='text-red margin-top'>WARNING: Exported dataset potentially contains more than 500 million genotypes.<br/>A standard workstation's web-browser may be unable to load it in with Flapjack-Bytes </div>" : "") + "</center>");
}

function sendToFjBytes() {
$("#fjBytesPanel").modal({
opacity: 80,
overlayCss: {
backgroundColor: "#111111"
}
});

let url = "fjbytes.html?m=" + location.origin + $("a#exportOutputUrl").attr("href").replace(new RegExp(/\.[^.]*$/), '.map') +
"&g=" + location.origin + $("a#exportOutputUrl").attr("href").replace(new RegExp(/\.[^.]*$/), '.genotype') +
"&p=" + location.origin + $("a#exportOutputUrl").attr("href").replace(new RegExp(/\.[^.]*$/), '.phenotype') +
"&id=" + getModuleName();
$('#fjBytesPanelHeader').html('<center>This is a functionality under development and might not be totally stable. Check <a href="https://github.com/cropgeeks/flapjack-bytes" target="_blank">https://github.com/cropgeeks/flapjack-bytes</a> for information about Flapjack-Bytes.&nbsp;&nbsp;&nbsp;<a href="' + url + '" onclick="$(\'#fjBytesPanel\').modal(\'hide\');" target="_blank">Open in separate window</a></center>');
$("#fjBytesFrame").attr('src', url);
}

function sendToIGV(genomeID)
{
var genomeID = $("select#igvGenome").val();
$.ajax({
type:"GET",
url:"http://127.0.0.1:" + igvDataLoadPort + "/load?" + (genomeID != "" ? "genome=" + genomeID + "&" : "") + "file=" + location.origin + $("a#exportOutputUrl").attr("href").replace(new RegExp(/\.[^.]*$/), '.vcf'),
success:function(tsvResult) {
alert("Variant list was sent to IGV!");
},
error:function(xhr, ajaxOptions, thrownError) {
handleError(xhr, ajaxOptions, thrownError);
}
});
}

function getSelectedTypes() {
var variantTypes = $('#variantTypes').val();
if (variantTypes === null || variantTypes.length === variantTypesCount)
@@ -1136,59 +1057,6 @@ function checkGroupOverlap(groupNumber) {
});
}

function sendToGalaxy(archivedDataFiles) {
var galaxyInstanceUrl = $("#galaxyInstanceURL").val().trim(), apiKey = sessionStorage.getItem("galaxyApiKey::" + galaxyInstanceUrl);
if (apiKey == null)
apiKey = prompt("Enter the API key tied to your account on\n" + galaxyInstanceUrl);
if (apiKey != null && apiKey.trim() != "") {
sessionStorage.setItem("galaxyApiKey::" + galaxyInstanceUrl, apiKey);
$('#progressText').html("Pushing files to " + galaxyInstanceUrl + " ...");
$('#asyncProgressButton').hide();
$('button#abort').hide();
$('#progress').modal({
backdrop: 'static',
keyboard: false,
show: true
});
setTimeout(function() {
var n = 0, responseMsg = null;
for (var fileUrl in archivedDataFiles)
$.ajax({
async: false,
url: galaxyPushURL + "?galaxyUrl=" + galaxyInstanceUrl + "&galaxyApiKey=" + apiKey + "&fileUrl=" + archivedDataFiles[fileUrl],
type: "GET",
success: function(respString) {
responseMsg = respString;
n++;
},
error: function(xhr, ajaxOptions, thrownError) {
$('#progress').modal('hide');

if (xhr.status == 403) {
console.log("Removing invalid Galaxy API key: " + apiKey);
sessionStorage.removeItem("galaxyApiKey::" + galaxyInstanceUrl);
}

if (thrownError == "" && xhr.getAllResponseHeaders() == '')
alert("Error accessing resource: " + genomeURL);
else
handleError(xhr, thrownError);
}
});
if (n > 0)
if (confirm(n + " file(s) " + responseMsg + "\nOpen a window pointing to that Galaxy instance?"))
window.open(galaxyInstanceUrl);
$('#progress').modal('hide');
}, 1);
}
}

function getOutputToolConfig(toolName)
{
var storedToolConfig = localStorage.getItem("outputTool_" + toolName);
return storedToolConfig != null ? JSON.parse(storedToolConfig) : onlineOutputTools[toolName];
}

function applyOutputToolConfig(t) {
if ($("input#outputToolURL").val().trim() == "") {
localStorage.removeItem("outputTool_" + $("#onlineOutputTools").val());
@@ -1216,71 +1084,6 @@ function checkIfOuputToolConfigChanged() {
$("#applyOutputToolConfig").prop('disabled', changed ? false : 'disabled');
}

function showServerExportBox()
{
$("div#exportPanel").hide();
$("a#exportBoxToggleButton").removeClass("active");
if (processAborted || downloadURL == null)
return;

var fileName = downloadURL.substring(downloadURL.lastIndexOf("/") + 1);
$('#serverExportBox').html('<button type="button" class="close" data-dismiss="modal" aria-hidden="true" style="float:right;" onclick="$(\'#serverExportBox\').hide();">x&nbsp;</button></button>&nbsp;Export file will be available at this URL for 48h:<br/><a id="exportOutputUrl" download href="' + downloadURL + '">' + fileName + '</a> ').show();
var exportedFormat = $('#exportFormat').val().toUpperCase();
if ("VCF" == exportedFormat)
addIgvExportIfRunning();
else if ("FLAPJACK" == exportedFormat)
addFjBytesExport();

var archivedDataFiles = new Array(), exportFormatExtensions = $("#exportFormat option:selected").data('ext').split(";");
if ($('#exportPanel input#exportedIndividualMetadataCheckBox').is(':checked') && "FLAPJACK" != exportedFormat && "DARWIN" != exportedFormat /* these two already have their own metadata file format*/)
exportFormatExtensions.push("tsv");
for (var key in exportFormatExtensions)
archivedDataFiles[exportFormatExtensions[key]] = location.origin + downloadURL.replace(new RegExp(/\.[^.]*$/), '.' + exportFormatExtensions[key]);

var galaxyInstanceUrl = $("#galaxyInstanceURL").val().trim();
if (galaxyInstanceUrl.startsWith("http")) {
var fileURLs = "";
for (key in archivedDataFiles)
fileURLs += (fileURLs == "" ? "" : " ,") + "'" + archivedDataFiles[key] + "'";
$('#serverExportBox').append('<br/><br/>&nbsp;<input type="button" value="Send exported data to Galaxy" onclick="sendToGalaxy([' + fileURLs + ']);" />&nbsp;');
}

if (onlineOutputTools != null)
for (var toolName in onlineOutputTools) {
var toolConfig = getOutputToolConfig(toolName);
if (toolConfig['url'] != null && toolConfig['url'].trim() != "" && (toolConfig['formats'] == null || toolConfig['formats'].trim() == "" || toolConfig['formats'].toUpperCase().split(",").includes($('#exportFormat').val().toUpperCase()))) {

var formatsForThisButton = "", urlForThisButton = toolConfig['url'];
var matchResult = urlForThisButton.match(/{([^}]+)}/g);
if (matchResult != null) {
var placeHolders = matchResult.map(res => res.replace(/{|}/g , ''));
phLoop: for (var i in placeHolders) {
var phFormats = placeHolders[i].split("\|");
for (var j in phFormats) {
for (var key in archivedDataFiles) {
if (key == phFormats[j]) {
formatsForThisButton += (formatsForThisButton == "" ? "" : ", ") + key;
urlForThisButton = urlForThisButton.replace("\{" + placeHolders[i] + "\}", archivedDataFiles[key]);
continue phLoop;
}
}
}
console.log("unused param: " + placeHolders[i]);
urlForThisButton = urlForThisButton.replace("\{" + placeHolders[i] + "\}", "");
}
}

if (urlForThisButton == toolConfig['url'] && urlForThisButton.indexOf("*") != -1) {
urlForThisButton = urlForThisButton.replace("\*", Object.values(archivedDataFiles).join(","));
formatsForThisButton = Object.keys(archivedDataFiles).join(", ");
}

if (formatsForThisButton != "")
$('#serverExportBox').append('<br/><br/>&nbsp;<input type="button" value="Send ' + formatsForThisButton + ' file(s) to ' + toolName + '" onclick="window.open(\'' + urlForThisButton + '\');" />&nbsp;')
}
}
}

function resetFilters() {
$('#genomeBrowserPanel').fadeOut();
$('#variantDetailPanel').fadeOut();

0 comments on commit 290fc2f

Please sign in to comment.