forked from enviPath/enviPy
[Feature] Threshold Warning + Cosmetics (#277)
Co-authored-by: Tim Lorsbach <tim@lorsba.ch> Reviewed-on: enviPath/enviPy#277
This commit is contained in:
@ -216,59 +216,62 @@
|
||||
x-data="pathwayViewer({
|
||||
status: '{{ pathway.status }}',
|
||||
modified: '{{ pathway.modified|date:"Y-m-d H:i:s" }}',
|
||||
statusUrl: '{{ pathway.url }}?status=true'
|
||||
statusUrl: '{{ pathway.url }}?status=true',
|
||||
emptyDueToThreshold: '{{ pathway.empty_due_to_threshold }}'
|
||||
})"
|
||||
x-init="init()"
|
||||
>
|
||||
<!-- Status Display -->
|
||||
<div class="tooltip tooltip-left absolute top-4 right-4 z-10">
|
||||
<div class="tooltip-content" x-text="statusTooltip"></div>
|
||||
<div id="status" class="flex items-center">
|
||||
<!-- Completed icon -->
|
||||
<template x-if="status === 'completed'">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-check"
|
||||
{% if pathway.predicted %}
|
||||
<!-- Status Display -->
|
||||
<div class="tooltip tooltip-left absolute top-4 right-4 z-10">
|
||||
<div class="tooltip-content" x-text="statusTooltip"></div>
|
||||
<div id="status" class="flex items-center">
|
||||
<!-- Completed icon -->
|
||||
<template x-if="status === 'completed'">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-check"
|
||||
>
|
||||
<path d="M20 6 9 17l-5-5" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<!-- Failed icon -->
|
||||
<template x-if="status === 'failed'">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-x"
|
||||
>
|
||||
<path d="M18 6 6 18" />
|
||||
<path d="M6 6l12 12" />
|
||||
</svg>
|
||||
</template>
|
||||
<!-- Loading spinner -->
|
||||
<div
|
||||
x-show="status === 'running'"
|
||||
style="width: 20px; height: 20px;"
|
||||
>
|
||||
<path d="M20 6 9 17l-5-5" />
|
||||
</svg>
|
||||
</template>
|
||||
<!-- Failed icon -->
|
||||
<template x-if="status === 'failed'">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-x"
|
||||
>
|
||||
<path d="M18 6 6 18" />
|
||||
<path d="M6 6l12 12" />
|
||||
</svg>
|
||||
</template>
|
||||
<!-- Loading spinner -->
|
||||
<div
|
||||
x-show="status === 'running'"
|
||||
style="width: 20px; height: 20px;"
|
||||
>
|
||||
{% include "components/loading-spinner.html" %}
|
||||
{% include "components/loading-spinner.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
<!-- Update Notice -->
|
||||
<div
|
||||
x-show="showUpdateNotice"
|
||||
@ -280,6 +283,15 @@
|
||||
Reload page
|
||||
</button>
|
||||
</div>
|
||||
<!-- Empty due to Threshold notice -->
|
||||
<div
|
||||
x-show="showEmptyDueToThresholdNotice"
|
||||
x-cloak
|
||||
class="alert alert-info absolute right-4 bottom-4 left-4 z-10"
|
||||
>
|
||||
<span x-html="emptyDueToThresholdMessage"></span>
|
||||
</div>
|
||||
|
||||
<svg id="pwsvg">
|
||||
<defs>
|
||||
<marker
|
||||
@ -455,95 +467,110 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{# prettier-ignore-start #}
|
||||
{# FIXME: This is a hack to get the pathway data into the JavaScript code. #}
|
||||
{{ pathway.d3_json|json_script:"pathway" }}
|
||||
|
||||
<script>
|
||||
// Global switch for app domain view
|
||||
var appDomainViewEnabled = false;
|
||||
<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 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>');
|
||||
}
|
||||
function transformReferences(text) {
|
||||
return text.replace(
|
||||
/\[\s*(http[^\]|]+)\s*\|\s*([^\]]+)\s*\]/g,
|
||||
'<a target="parent" href="$1">$2</a>',
|
||||
);
|
||||
}
|
||||
|
||||
var pathway = JSON.parse(document.getElementById("pathway").textContent);
|
||||
|
||||
var pathway = {{ pathway.d3_json | safe }};
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
draw(pathway, "vizdiv");
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
draw(pathway, 'vizdiv');
|
||||
// Transform references in description
|
||||
const descContent = document.getElementById("DescriptionContent");
|
||||
if (descContent) {
|
||||
const newDesc = transformReferences(descContent.innerText);
|
||||
descContent.innerHTML = newDesc;
|
||||
}
|
||||
|
||||
// Transform references in description
|
||||
const descContent = document.getElementById('DescriptionContent');
|
||||
if (descContent) {
|
||||
const newDesc = transformReferences(descContent.innerText);
|
||||
descContent.innerHTML = newDesc;
|
||||
}
|
||||
// App domain toggle
|
||||
const appDomainBtn = document.getElementById("app-domain-toggle-button");
|
||||
if (appDomainBtn) {
|
||||
appDomainBtn.addEventListener("click", function () {
|
||||
appDomainViewEnabled = !appDomainViewEnabled;
|
||||
const icon = document.getElementById("app-domain-icon");
|
||||
|
||||
// App domain toggle
|
||||
const appDomainBtn = document.getElementById('app-domain-toggle-button');
|
||||
if (appDomainBtn) {
|
||||
appDomainBtn.addEventListener('click', function() {
|
||||
appDomainViewEnabled = !appDomainViewEnabled;
|
||||
const icon = document.getElementById('app-domain-icon');
|
||||
if (appDomainViewEnabled) {
|
||||
// Change to eye-off icon
|
||||
icon.innerHTML =
|
||||
'<path d="M9.88 9.88a3 3 0 1 0 4.24 4.24"/><path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/><path d="M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61"/><line x1="2" x2="22" y1="2" y2="22"/>';
|
||||
|
||||
if (appDomainViewEnabled) {
|
||||
// Change to eye-off icon
|
||||
icon.innerHTML = '<path d="M9.88 9.88a3 3 0 1 0 4.24 4.24"/><path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/><path d="M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61"/><line x1="2" x2="22" y1="2" y2="22"/>';
|
||||
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 {
|
||||
// Change back to eye icon
|
||||
icon.innerHTML =
|
||||
'<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/>';
|
||||
|
||||
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 {
|
||||
// Change back to eye icon
|
||||
icon.innerHTML = '<path d="M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z"/><circle cx="12" cy="12" r="3"/>';
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Show actions button if there are actions
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
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 #}
|
||||
// Show actions button if there are actions
|
||||
const actionsButton = document.getElementById("actionsButton");
|
||||
const actionsList = actionsButton?.querySelector("ul");
|
||||
if (actionsList && actionsList.children.length > 0) {
|
||||
actionsButton?.classList.remove("hidden");
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock content %}
|
||||
|
||||
Reference in New Issue
Block a user