forked from enviPath/enviPy
All html files now prettier formatted and fixes for incompatible blocks applied Co-authored-by: Tim Lorsbach <tim@lorsba.ch> Reviewed-on: enviPath/enviPy#193 Co-authored-by: Tobias O <tobias.olenyi@envipath.com> Co-committed-by: Tobias O <tobias.olenyi@envipath.com>
571 lines
20 KiB
HTML
571 lines
20 KiB
HTML
{% extends "framework.html" %}
|
|
{% load static %}
|
|
{% block content %}
|
|
<script src="https://d3js.org/d3.v7.min.js"></script>
|
|
<style>
|
|
#vizdiv {
|
|
width: 100%;
|
|
height: 600px;
|
|
background: white;
|
|
}
|
|
|
|
#pwsvg {
|
|
width: 100%;
|
|
height: 100%;
|
|
color: red;
|
|
}
|
|
|
|
.link {
|
|
stroke: #999;
|
|
stroke-opacity: 0.6;
|
|
}
|
|
|
|
.link_no_arrow {
|
|
stroke: #999;
|
|
stroke-opacity: 0.6;
|
|
}
|
|
|
|
.node image {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.node circle {
|
|
fill: lightblue;
|
|
stroke: steelblue;
|
|
stroke-width: 1.5px;
|
|
}
|
|
|
|
.inside_app_domain {
|
|
fill: green;
|
|
stroke: green;
|
|
stroke-width: 1.5px;
|
|
}
|
|
|
|
.outside_app_domain {
|
|
fill: red;
|
|
stroke: red;
|
|
stroke-width: 1.5px;
|
|
}
|
|
|
|
.passes_app_domain {
|
|
stroke: green;
|
|
stroke-width: 1.5px;
|
|
stroke-opacity: 0.6;
|
|
}
|
|
|
|
.fails_app_domain {
|
|
stroke: red;
|
|
stroke-width: 1.5px;
|
|
stroke-opacity: 0.6;
|
|
}
|
|
|
|
.highlighted {
|
|
stroke: red;
|
|
stroke-width: 3px;
|
|
}
|
|
|
|
.tooltip {
|
|
position: absolute;
|
|
background: lightgrey;
|
|
padding: 5px;
|
|
border-radius: 5px;
|
|
visibility: hidden;
|
|
opacity: 1;
|
|
}
|
|
</style>
|
|
<script src="{% static 'js/pw.js' %}"></script>
|
|
|
|
{% block action_modals %}
|
|
{% include "modals/objects/add_pathway_node_modal.html" %}
|
|
{% include "modals/objects/add_pathway_edge_modal.html" %}
|
|
{% include "modals/objects/download_pathway_csv_modal.html" %}
|
|
{% include "modals/objects/download_pathway_image_modal.html" %}
|
|
{% include "modals/objects/identify_missing_rules_modal.html" %}
|
|
{% include "modals/objects/generic_copy_object_modal.html" %}
|
|
{% include "modals/objects/edit_pathway_modal.html" %}
|
|
{% include "modals/objects/generic_set_aliases_modal.html" %}
|
|
{% include "modals/objects/generic_set_scenario_modal.html" %}
|
|
{% include "modals/objects/delete_pathway_node_modal.html" %}
|
|
{% include "modals/objects/delete_pathway_edge_modal.html" %}
|
|
{% include "modals/objects/generic_delete_modal.html" %}
|
|
{% endblock action_modals %}
|
|
|
|
<p></p>
|
|
<div id="pwcontent">
|
|
<div class="panel-group" id="pwAccordion">
|
|
<div class="panel panel-default">
|
|
<div
|
|
class="panel-heading"
|
|
id="headingPanel"
|
|
style="font-size:2rem;height: 46px"
|
|
>
|
|
{{ pathway.name|safe }}
|
|
</div>
|
|
</div>
|
|
<div
|
|
class="panel panel-default panel-heading list-group-item"
|
|
style="background-color:silver"
|
|
>
|
|
<h4 class="panel-title">
|
|
<a
|
|
id="vizLink"
|
|
data-toggle="collapse"
|
|
data-parent="#pwAccordion"
|
|
href="#viz"
|
|
>
|
|
Graphical Representation
|
|
</a>
|
|
</h4>
|
|
</div>
|
|
<div id="viz" class="panel-collapse in collapse">
|
|
<nav role="navigation" class="navbar navbar-default" style="margin: 0;">
|
|
<div class="navbar-header"></div>
|
|
<div id="editbarCollapse" class="navbar-collapse collapse">
|
|
<ul class="nav navbar-nav">
|
|
<li class="dropdown requiresWritePerm">
|
|
<a
|
|
href="#"
|
|
class="dropdown-toggle"
|
|
data-toggle="dropdown"
|
|
role="button"
|
|
aria-haspopup="true"
|
|
aria-expanded="false"
|
|
>
|
|
<span class="glyphicon glyphicon-edit"></span>
|
|
Edit
|
|
<span class="caret"></span
|
|
></a>
|
|
<ul id="editingList" class="dropdown-menu">
|
|
{% block actions %}
|
|
{% include "actions/objects/pathway.html" %}
|
|
{% endblock %}
|
|
</ul>
|
|
</li>
|
|
{% if pathway.setting.model.app_domain %}
|
|
<li class="dropdown">
|
|
<a
|
|
href="#"
|
|
class="dropdown-toggle"
|
|
data-toggle="dropdown"
|
|
role="button"
|
|
aria-haspopup="true"
|
|
aria-expanded="false"
|
|
>
|
|
<span class="glyphicon glyphicon-eye-open"></span>
|
|
View
|
|
<span class="caret"></span
|
|
></a>
|
|
<ul id="editingList" class="dropdown-menu">
|
|
<li>
|
|
<a class="button" id="app-domain-toggle-button">
|
|
<i
|
|
id="app-domain-toggle-button"
|
|
class="glyphicon glyphicon-eye-open"
|
|
></i>
|
|
App Domain View</a
|
|
>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
{% endif %}
|
|
</ul>
|
|
|
|
<ul class="nav navbar-nav navbar-right">
|
|
<li>
|
|
<a
|
|
role="button"
|
|
data-toggle="modal"
|
|
onclick="goFullscreen('vizdiv')"
|
|
>
|
|
<span class="glyphicon glyphicon-fullscreen"></span>
|
|
Fullscreen
|
|
</a>
|
|
</li>
|
|
<li>
|
|
{% if pathway.completed %}
|
|
<button
|
|
type="button"
|
|
class="btn btn-default navbar-btn"
|
|
data-toggle="popover"
|
|
id="status"
|
|
data-original-title=""
|
|
title=""
|
|
data-content="Pathway prediction complete."
|
|
>
|
|
<span class="glyphicon glyphicon-ok"></span>
|
|
</button>
|
|
{% elif pathway.failed %}
|
|
<button
|
|
type="button"
|
|
class="btn btn-default navbar-btn"
|
|
data-toggle="popover"
|
|
id="status"
|
|
data-original-title=""
|
|
title=""
|
|
data-content="Pathway prediction failed."
|
|
>
|
|
<span class="glyphicon glyphicon-remove"></span>
|
|
</button>
|
|
{% else %}
|
|
<button
|
|
type="button"
|
|
class="btn btn-default navbar-btn"
|
|
data-toggle="popover"
|
|
id="status"
|
|
data-original-title=""
|
|
title=""
|
|
data-content="Pathway prediction running."
|
|
>
|
|
<img height="20" src="{% static '/images/wait.gif' %}" />
|
|
</button>
|
|
{% endif %}
|
|
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
<div id="vizdiv">
|
|
<svg id="pwsvg">
|
|
<defs>
|
|
<marker
|
|
id="arrow"
|
|
viewBox="0 0 10 10"
|
|
refX="43"
|
|
refY="5"
|
|
markerWidth="6"
|
|
markerHeight="6"
|
|
orient="auto-start-reverse"
|
|
markerUnits="userSpaceOnUse"
|
|
>
|
|
<path d="M 0 0 L 10 5 L 0 10 z" fill="#999" />
|
|
</marker>
|
|
<marker
|
|
id="arrow_passes_app_domain"
|
|
viewBox="0 0 10 10"
|
|
refX="43"
|
|
refY="5"
|
|
markerWidth="6"
|
|
markerHeight="6"
|
|
orient="auto-start-reverse"
|
|
markerUnits="userSpaceOnUse"
|
|
>
|
|
<path d="M 0 0 L 10 5 L 0 10 z" fill="green" />
|
|
</marker>
|
|
<marker
|
|
id="arrow_fails_app_domain"
|
|
viewBox="0 0 10 10"
|
|
refX="43"
|
|
refY="5"
|
|
markerWidth="6"
|
|
markerHeight="6"
|
|
orient="auto-start-reverse"
|
|
markerUnits="userSpaceOnUse"
|
|
>
|
|
<path d="M 0 0 L 10 5 L 0 10 z" fill="red" />
|
|
</marker>
|
|
</defs>
|
|
<g id="zoomable"></g>
|
|
</svg>
|
|
<div id="tooltip" class="tooltip"></div>
|
|
</div>
|
|
</div>
|
|
<!-- Description -->
|
|
<div
|
|
class="panel panel-default panel-heading list-group-item"
|
|
style="background-color:silver"
|
|
>
|
|
<h4 class="panel-title">
|
|
<a
|
|
id="DescriptionLink"
|
|
data-toggle="collapse"
|
|
data-parent="#pathwayAccordion"
|
|
href="#Description"
|
|
>Description</a
|
|
>
|
|
</h4>
|
|
</div>
|
|
<div id="Description" class="panel-collapse in collapse">
|
|
<div class="panel-body list-group-item" id="DescriptionContent">
|
|
{{ pathway.description | safe }}
|
|
</div>
|
|
</div>
|
|
|
|
{% if pathway.aliases %}
|
|
<!-- Aliases -->
|
|
<div
|
|
class="panel panel-default panel-heading list-group-item"
|
|
style="background-color:silver"
|
|
>
|
|
<h4 class="panel-title">
|
|
<a
|
|
id="pathway-aliases-link"
|
|
data-toggle="collapse"
|
|
data-parent="#pathway-detail"
|
|
href="#pathway-aliases"
|
|
>Aliases</a
|
|
>
|
|
</h4>
|
|
</div>
|
|
<div id="pathway-aliases" class="panel-collapse in collapse">
|
|
<div class="panel-body list-group-item">
|
|
{% for alias in pathway.aliases %}
|
|
<a class="list-group-item">{{ alias }}</a>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if pathway.scenarios.all %}
|
|
<div
|
|
class="panel panel-default panel-heading list-group-item"
|
|
style="background-color:silver"
|
|
>
|
|
<h4 class="panel-title">
|
|
<a
|
|
id="pathway-scenario-link"
|
|
data-toggle="collapse"
|
|
data-parent="#pathway-detail"
|
|
href="#pathway-scenario"
|
|
>Scenarios</a
|
|
>
|
|
</h4>
|
|
</div>
|
|
<div id="pathway-scenario" class="panel-collapse in collapse">
|
|
<div class="panel-body list-group-item">
|
|
{% for s in pathway.scenarios.all %}
|
|
<a class="list-group-item" href="{{ s.url }}"
|
|
>{{ s.name|safe }} <i>({{ s.package.name|safe }})</i></a
|
|
>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if pathway.setting %}
|
|
<div
|
|
class="panel panel-default panel-heading list-group-item"
|
|
style="background-color:silver"
|
|
>
|
|
<h4 class="panel-title">
|
|
<a
|
|
id="pathwaySettingLink"
|
|
data-toggle="collapse"
|
|
data-parent="#pathwayAccordion"
|
|
href="#pathwaySetting"
|
|
>Setting</a
|
|
>
|
|
</h4>
|
|
</div>
|
|
<div id="pathwaySetting" class="panel-collapse collapse">
|
|
<div class="panel-body list-group-item" id="pathwaySettingContent">
|
|
<table class="table-bordered table-hover table">
|
|
<tr style="background-color: rgba(0, 0, 0, 0.08);">
|
|
<th scope="col" width="20%">Parameter</th>
|
|
<th scope="col" width="80%">Value</th>
|
|
</tr>
|
|
<tbody>
|
|
{% if pathway.setting.model %}
|
|
<tr>
|
|
<td width="20%">Model</td>
|
|
<td width="80%">
|
|
<table
|
|
width="100%"
|
|
class="table-bordered table-hover table"
|
|
>
|
|
<tbody>
|
|
<tr>
|
|
<td colspan="2">
|
|
<li class="list-group-item">
|
|
<a href="{{ pathway.setting.model.url }}">
|
|
{{ pathway.setting.model.name|safe }}
|
|
</a>
|
|
</li>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th width="20%">Model Parameter</th>
|
|
<th width="80%">Parameter Value</th>
|
|
</tr>
|
|
<tr>
|
|
<td width="20%">Threshold</td>
|
|
<td width="80%">
|
|
{{ pathway.setting.model_threshold }}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
{% endif %}
|
|
{% if pathway.setting.rule_packages.all %}
|
|
<tr>
|
|
<td width="20%">Rule Packages</td>
|
|
<td width="80%">
|
|
<table
|
|
width="100%"
|
|
class="table-bordered table-hover table"
|
|
>
|
|
<tbody>
|
|
<tr>
|
|
<td colspan="2">
|
|
{% for p in pathway.setting.rule_packages.all %}
|
|
<li class="list-group-item">
|
|
<a href="{{ p.url }}"> {{ p.name|safe }} </a>
|
|
</li>
|
|
{% endfor %}
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
{% endif %}
|
|
<tr>
|
|
<td>
|
|
<p>Max Nodes</p>
|
|
</td>
|
|
<td>
|
|
<p>{{ pathway.setting.max_nodes }}</p>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td>
|
|
<p>Max Depth</p>
|
|
</td>
|
|
<td>
|
|
<p>{{ pathway.setting.max_depth }}</p>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{# prettier-ignore-start #}
|
|
<script>
|
|
// Global switch for app domain view
|
|
var appDomainViewEnabled = false;
|
|
|
|
function goFullscreen(id) {
|
|
var element = document.getElementById(id);
|
|
if (element.mozRequestFullScreen) {
|
|
element.mozRequestFullScreen();
|
|
} else if (element.webkitRequestFullScreen) {
|
|
element.webkitRequestFullScreen();
|
|
}
|
|
}
|
|
|
|
function transformReferences(text) {
|
|
return text.replace(/\[\s*(http[^\]|]+)\s*\|\s*([^\]]+)\s*\]/g, '<a target="parent" href="$1">$2</a>');
|
|
}
|
|
|
|
pathway = {{ pathway.d3_json | safe }};
|
|
|
|
$(function () {
|
|
|
|
$('#status').popover({
|
|
trigger: 'manual',
|
|
placement: 'bottom',
|
|
html: true
|
|
});
|
|
|
|
// If prediction is still running, regularly check status
|
|
if (pathway.status === 'running') {
|
|
let last_modified = pathway.modified;
|
|
|
|
let pollInterval = setInterval(async () => {
|
|
try {
|
|
const response = await fetch("{{ pathway.url }}?status=true", {});
|
|
const data = await response.json();
|
|
|
|
if (data.modified > last_modified) {
|
|
var msg = 'Prediction '
|
|
var btn = '<button type="button" onclick="location.reload()" class="btn btn-primary" id="reloadBtn">Reload page</button>'
|
|
|
|
if (data.status === "running") {
|
|
msg += 'is still running. But the Pathway was updated.<br>' + btn;
|
|
|
|
} else if (data.status === "completed") {
|
|
msg += 'is completed. Reload the page to see the updated Pathway.<br>' + btn;
|
|
} else if (data.status === "failed") {
|
|
msg += 'failed. Reload the page to see the current shape<br>' + btn;
|
|
}
|
|
|
|
$('#status').attr(
|
|
'data-content', msg
|
|
).popover('show');
|
|
}
|
|
|
|
if (data.status === "completed" || data.status === "failed") {
|
|
$('#status img').remove();
|
|
if (data.status === "completed") {
|
|
$('#status').append('<span class="glyphicon glyphicon-ok"></span>')
|
|
} else {
|
|
$('#status').append('<span class="glyphicon glyphicon-remove"></span>')
|
|
}
|
|
clearInterval(pollInterval);
|
|
}
|
|
|
|
} catch (err) {
|
|
console.error("Polling error:", err);
|
|
}
|
|
}, 5000);
|
|
}
|
|
|
|
draw(pathway, 'vizdiv');
|
|
// TODO fix somewhere else...
|
|
var newDesc = transformReferences($('#DescriptionContent')[0].innerText);
|
|
$('#DescriptionContent').html(newDesc);
|
|
|
|
|
|
$('#app-domain-toggle-button').on('click', function () {
|
|
// glyphicon glyphicon-eye-close
|
|
// glyphicon glyphicon-eye-open
|
|
appDomainViewEnabled = !appDomainViewEnabled;
|
|
|
|
if (appDomainViewEnabled) {
|
|
$('#app-domain-toggle-button > i').removeClass('glyphicon-eye-open');
|
|
$('#app-domain-toggle-button > i').addClass('glyphicon-eye-close');
|
|
nodes.forEach((x) => {
|
|
if(x.app_domain) {
|
|
if (x.app_domain.inside_app_domain) {
|
|
d3.select(x.el).select("circle").classed("inside_app_domain", true);
|
|
} else {
|
|
d3.select(x.el).select("circle").classed("outside_app_domain", true);
|
|
}
|
|
}
|
|
});
|
|
links.forEach((x) => {
|
|
if(x.app_domain) {
|
|
if (x.app_domain.passes_app_domain) {
|
|
d3.select(x.el).attr("marker-end", d => d.target.pseudo ? "" : "url(#arrow_passes_app_domain)");
|
|
d3.select(x.el).classed("passes_app_domain", true);
|
|
} else {
|
|
d3.select(x.el).attr("marker-end", d => d.target.pseudo ? "" : "url(#arrow_fails_app_domain)");
|
|
d3.select(x.el).classed("fails_app_domain", true);
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
$('#app-domain-toggle-button > i').removeClass('glyphicon-eye-close');
|
|
$('#app-domain-toggle-button > i').addClass('glyphicon-eye-open');
|
|
nodes.forEach((x) => {
|
|
d3.select(x.el).select("circle").classed("inside_app_domain", false);
|
|
d3.select(x.el).select("circle").classed("outside_app_domain", false);
|
|
});
|
|
links.forEach((x) => {
|
|
d3.select(x.el).attr("marker-end", d => d.target.pseudo ? "" : "url(#arrow)");
|
|
d3.select(x.el).classed("passes_app_domain", false);
|
|
d3.select(x.el).classed("fails_app_domain", false);
|
|
});
|
|
}
|
|
})
|
|
|
|
});
|
|
|
|
</script>
|
|
{# prettier-ignore-end #}
|
|
{% endblock content %}
|