";
-}
-
-function makeAccordionPanel(accordionId, panelName, panelContent, collapsed, id) {
- if(panelContent == "" || panelContent == "no description") {
- return "";
- }
- if(collapsed == true) {
- collapsed = "in";
+ // Handle both ID selectors and DOM elements
+ let element;
+ if (typeof attachOb === 'string') {
+ element = attachOb.startsWith('#')
+ ? document.querySelector(attachOb)
+ : document.getElementById(attachOb);
} else {
- collapsed = "";
- }
- var panelId = typeof id === "undefined" ? cleanIdName(panelName) : id;
- return "
";
-}
-
-function fillPRCurve(modelUri, onclick){
- if (modelUri == '') {
- return;
+ element = attachOb;
}
- // clear div
- $('#plotDiv').empty();
-
- // for the time being add animation
- makeLoadingGif('#plotDiv');
-
- $.getJSON(modelUri + "?prcurve", function (result) {
- // remove loading gif
- $('#plotDiv').empty();
-
- // check if model is in a proper state
- if(result.hasOwnProperty('error')){
- var content = '
';
- $('#plotDiv').append(content);
- return
- }
-
- var chartPanel = '
';
- $('#plotDiv').append(chartPanel);
-
- // Labels
- var x = ['Recall'];
- var y = ['Precision'];
- var thres = ['threshold'];
-
- // Compare function for the given array
- function compare(a, b) {
- if (a.threshold < b.threshold)
- return -1;
- else if (a.threshold > b.threshold)
- return 1;
- else
- return 0;
- }
-
- // gets the index for a certain value
- function getIndexForValue(data, val, val_name) {
- for(var idx in data) {
- if(data[idx][val_name] == val) {
- return idx;
- }
- }
- return -1;
- }
-
- var data = result.prdata;
- var dataLength = Object.keys(data).length;
- data.sort(compare);
-
- // collect data in 3 individual arrays
- for (var idx in data) {
- var d = data[idx];
- x.push(d.recall);
- y.push(d.precision);
- thres.push(d.threshold);
- }
-
- // generate the actual chart with values collected above
- var chart = c3.generate({
- bindto: '#chart',
- data: {
- onclick: function (d, e) {
- var idx = d.index;
- var thresh = data[dataLength-idx-1].threshold;
-
- onclick(thresh)
-
- },
- x: 'Recall',
- y: 'Precision',
- columns: [
- x,
- y,
- //thres
- ]
- },
- size: {
- height: 400, // TODO: Make variable to current modal width
- width: 480
- },
- axis: {
- x: {
- max: 1,
- min: 0,
- label: 'Recall',
- padding: 0,
- tick: {
- fit: true,
- values: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
- }
- },
- y: {
- max: 1,
- min: 0,
- label: 'Precision',
- padding: 0,
- tick: {
- fit: true,
- values: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
- }
- }
- },
- point: {
- r: 4
- },
- tooltip: {
- format: {
- title: function (recall) {
- idx = getIndexForValue(data, recall, "recall");
- if(idx != -1) {
- return "Threshold: " + data[idx].threshold;
- }
- return "";
- },
- value: function (precision, ratio, id) {
- return undefined;
- }
- }
- },
- zoom: {
- enabled: true
- }
- });
-
- });
+ if (element) {
+ element.innerHTML = spinnerHtml;
+ }
}
+// Keep old function name for backwards compatibility
+function makeLoadingGif(attachOb) {
+ showLoadingSpinner(attachOb);
+}
+
+// FIXME: marked for removal
+// function cleanIdName(idName) {
+// return idName.replace(/[ \-()]/g, "")
+// }
+
+// FIXME: marked for removal
+// function makeAccordionHead(accordionId, accordionTitle, reviewStatus) {
+// return "
"
+// + "
"
+// + "
"
+// + accordionTitle + reviewStatus
+// + "
"
+// + "
";
+// }
+
+// FIXME: marked for removal
+// function makeAccordionPanel(accordionId, panelName, panelContent, collapsed, id) {
+// if(panelContent == "" || panelContent == "no description") {
+// return "";
+// }
+// if(collapsed == true) {
+// collapsed = "in";
+// } else {
+// collapsed = "";
+// }
+// var panelId = typeof id === "undefined" ? cleanIdName(panelName) : id;
+// return "
"
+// + "
"
+// + "
"
+// + panelContent
+// + "
"
+// + "
";
+// }
+
+// FIXME: marked for removal
+// async function fillPRCurve(modelUri, onclick){
+// if (modelUri == '') {
+// return;
+// }
+
+// // clear div
+// const plotDiv = document.getElementById('plotDiv');
+// plotDiv.innerHTML = '';
+
+// // for the time being add animation
+// makeLoadingGif('#plotDiv');
+
+// try {
+// const response = await fetch(modelUri + "?prcurve");
+// const result = await response.json();
+
+// // remove loading gif
+// plotDiv.innerHTML = '';
+
+// // check if model is in a proper state
+// if(result.hasOwnProperty('error')){
+// var content = '
'+result.error+' \nYou can check the model
here.
';
+// plotDiv.innerHTML += content;
+// return
+// }
+
+// var chartPanel = '
';
+// plotDiv.innerHTML += chartPanel;
+
+// // Labels
+// var x = ['Recall'];
+// var y = ['Precision'];
+// var thres = ['threshold'];
+
+// // Compare function for the given array
+// function compare(a, b) {
+// if (a.threshold < b.threshold)
+// return -1;
+// else if (a.threshold > b.threshold)
+// return 1;
+// else
+// return 0;
+// }
+
+// // gets the index for a certain value
+// function getIndexForValue(data, val, val_name) {
+// for(var idx in data) {
+// if(data[idx][val_name] == val) {
+// return idx;
+// }
+// }
+// return -1;
+// }
+
+// var data = result.prdata;
+// var dataLength = Object.keys(data).length;
+// data.sort(compare);
+
+// // collect data in 3 individual arrays
+// for (var idx in data) {
+// var d = data[idx];
+// x.push(d.recall);
+// y.push(d.precision);
+// thres.push(d.threshold);
+// }
+
+// // generate the actual chart with values collected above
+// var chart = c3.generate({
+// bindto: '#chart',
+// data: {
+// onclick: function (d, e) {
+// var idx = d.index;
+// var thresh = data[dataLength-idx-1].threshold;
+
+// onclick(thresh)
+
+// },
+// x: 'Recall',
+// y: 'Precision',
+// columns: [
+// x,
+// y,
+// //thres
+// ]
+// },
+// size: {
+// height: 400, // TODO: Make variable to current modal width
+// width: 480
+// },
+// axis: {
+// x: {
+// max: 1,
+// min: 0,
+// label: 'Recall',
+// padding: 0,
+// tick: {
+// fit: true,
+// values: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
+// }
+// },
+// y: {
+// max: 1,
+// min: 0,
+// label: 'Precision',
+// padding: 0,
+// tick: {
+// fit: true,
+// values: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
+// }
+// }
+// },
+// point: {
+// r: 4
+// },
+// tooltip: {
+// format: {
+// title: function (recall) {
+// idx = getIndexForValue(data, recall, "recall");
+// if(idx != -1) {
+// return "Threshold: " + data[idx].threshold;
+// }
+// return "";
+// },
+// value: function (precision, ratio, id) {
+// return undefined;
+// }
+// }
+// },
+// zoom: {
+// enabled: true
+// }
+// });
+
+// } catch (error) {
+// console.error('Error loading PR curve:', error);
+// const plotDiv = document.getElementById('plotDiv');
+// plotDiv.innerHTML = '
Error loading PR curve data.
';
+// }
+// }
+
function handleAssessmentResponse(depict_url, data) {
var inside_app_domain = "
This compound is " + (data["assessment"]["inside_app_domain"] ? "inside" : "outside") + " the Applicability Domain derived from the chemical (PCA) space constructed using the training data." + "";
@@ -782,6 +845,6 @@ function handleAssessmentResponse(depict_url, data) {
res = tpl + transformations;
- $("#appDomainAssessmentResultTable").append(res);
+ document.getElementById('appDomainAssessmentResultTable').innerHTML += res;
}
diff --git a/static/js/pw.js b/static/js/pw.js
index 907f28e0..8c7c49ba 100644
--- a/static/js/pw.js
+++ b/static/js/pw.js
@@ -1,15 +1,22 @@
console.log("loaded pw.js")
function predictFromNode(url) {
- $.post("", {node: url})
- .done(function (data) {
- console.log("Success:", data);
- window.location.href = data.success;
- })
- .fail(function (xhr, status, error) {
- console.error("Error:", xhr.status, xhr.responseText);
- // show user-friendly message or log error
- });
+ fetch("", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded",
+ "X-CSRFToken": document.querySelector('[name=csrfmiddlewaretoken]')?.value || ''
+ },
+ body: new URLSearchParams({node: url})
+ })
+ .then(response => response.json())
+ .then(data => {
+ console.log("Success:", data);
+ window.location.href = data.success;
+ })
+ .catch(error => {
+ console.error("Error:", error);
+ });
}
// data = {{ pathway.d3_json | safe }};
@@ -103,6 +110,9 @@ function draw(pathway, elem) {
}
function dragstarted(event, d) {
+ // Prevent zoom pan when dragging nodes
+ event.sourceEvent.stopPropagation();
+
if (!event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
@@ -117,6 +127,9 @@ function draw(pathway, elem) {
}
function dragged(event, d) {
+ // Prevent zoom pan when dragging nodes
+ event.sourceEvent.stopPropagation();
+
d.fx = event.x;
d.fy = event.y;
@@ -127,6 +140,9 @@ function draw(pathway, elem) {
}
function dragended(event, d) {
+ // Prevent zoom pan when dragging nodes
+ event.sourceEvent.stopPropagation();
+
if (!event.active) simulation.alphaTarget(0);
// Mark that dragging has ended
@@ -192,52 +208,153 @@ function draw(pathway, elem) {
d3.select(t).select("circle").classed("highlighted", !d3.select(t).select("circle").classed("highlighted"));
}
- // Wait one second before showing popup
+ // Wait before showing popup (ms)
var popupWaitBeforeShow = 1000;
- // Keep Popup at least for one second
- var popushowAtLeast = 1000;
- function pop_show_e(element) {
- var e = element;
- setTimeout(function () {
- if ($(e).is(':hover')) { // if element is still hovered
- $(e).popover("show");
+ // Custom popover element
+ let popoverTimeout = null;
- // workaround to set fixed positions
- pop = $(e).attr("aria-describedby")
- h = $('#' + pop).height();
- $('#' + pop).attr("style", `position: fixed; top: ${clientY - (h / 2.0)}px; left: ${clientX + 10}px; margin: 0px; max-width: 1000px; display: block;`)
- setTimeout(function () {
- var close = setInterval(function () {
- if (!$(".popover:hover").length // mouse outside popover
- && !$(e).is(':hover')) { // mouse outside element
- $(e).popover('hide');
- clearInterval(close);
- }
- }, 100);
- }, popushowAtLeast);
+ function createPopover() {
+ const popover = document.createElement('div');
+ popover.id = 'custom-popover';
+ popover.className = 'fixed z-50';
+ popover.style.cssText = `
+ background: #ffffff;
+ border: 1px solid #d1d5db;
+ box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
+ max-width: 320px;
+ padding: 0.75rem;
+ border-radius: 0.5rem;
+ opacity: 0;
+ visibility: hidden;
+ transition: opacity 150ms ease-in-out, visibility 150ms ease-in-out;
+ pointer-events: auto;
+ `;
+ popover.setAttribute('role', 'tooltip');
+ popover.innerHTML = `
+
+
+ `;
+
+ // Add styles for content images
+ const style = document.createElement('style');
+ style.textContent = `
+ #custom-popover img {
+ max-width: 100%;
+ height: auto;
+ display: block;
+ margin: 0.5rem 0;
}
- }, popupWaitBeforeShow);
+ #custom-popover a {
+ color: #2563eb;
+ text-decoration: none;
+ }
+ #custom-popover a:hover {
+ text-decoration: underline;
+ }
+ `;
+ if (!document.getElementById('popover-styles')) {
+ style.id = 'popover-styles';
+ document.head.appendChild(style);
+ }
+
+ // Keep popover open when hovering over it
+ popover.addEventListener('mouseenter', () => {
+ if (popoverTimeout) {
+ clearTimeout(popoverTimeout);
+ popoverTimeout = null;
+ }
+ });
+
+ popover.addEventListener('mouseleave', () => {
+ hidePopover();
+ });
+
+ document.body.appendChild(popover);
+ return popover;
+ }
+
+ function getPopover() {
+ return document.getElementById('custom-popover') || createPopover();
+ }
+
+ function showPopover(element, title, content) {
+ const popover = getPopover();
+ popover.querySelector('.popover-title').textContent = title;
+ popover.querySelector('.popover-content').innerHTML = content;
+
+ // Make visible to measure
+ popover.style.visibility = 'hidden';
+ popover.style.opacity = '0';
+ popover.style.display = 'block';
+
+ // Smart positioning - avoid viewport overflow
+ const padding = 10;
+ const popoverRect = popover.getBoundingClientRect();
+ const viewportWidth = window.innerWidth;
+ const viewportHeight = window.innerHeight;
+
+ let left = clientX + 15;
+ let top = clientY - (popoverRect.height / 2);
+
+ // Prevent right overflow
+ if (left + popoverRect.width > viewportWidth - padding) {
+ left = clientX - popoverRect.width - 15;
+ }
+
+ // Prevent bottom overflow
+ if (top + popoverRect.height > viewportHeight - padding) {
+ top = viewportHeight - popoverRect.height - padding;
+ }
+
+ // Prevent top overflow
+ if (top < padding) {
+ top = padding;
+ }
+
+ popover.style.top = `${top}px`;
+ popover.style.left = `${left}px`;
+ popover.style.visibility = 'visible';
+ popover.style.opacity = '1';
+
+ currentElement = element;
+ }
+
+ function hidePopover() {
+ const popover = getPopover();
+ popover.style.opacity = '0';
+ popover.style.visibility = 'hidden';
+ currentElement = null;
}
function pop_add(objects, title, contentFunction) {
- objects.attr("id", "pop")
- .attr("data-container", "body")
- .attr("data-toggle", "popover")
- .attr("data-placement", "right")
- .attr("title", title);
+ objects.each(function (d) {
+ const element = this;
- objects.each(function (d, i) {
- options = {trigger: "manual", html: true, animation: false};
- this_ = this;
- var p = $(this).popover(options).on("mouseenter", function () {
- pop_show_e(this);
+ element.addEventListener('mouseenter', () => {
+ if (popoverTimeout) clearTimeout(popoverTimeout);
+
+ popoverTimeout = setTimeout(() => {
+ if (element.matches(':hover')) {
+ const content = contentFunction(d);
+ showPopover(element, title, content);
+ }
+ }, popupWaitBeforeShow);
});
- p.on("show.bs.popover", function (e) {
- // this is to dynamically ajdust the content and bounds of the popup
- p.attr('data-content', contentFunction(d));
- p.data("bs.popover").setContent();
- p.data("bs.popover").tip().css({"max-width": "1000px"});
+
+ element.addEventListener('mouseleave', () => {
+ if (popoverTimeout) {
+ clearTimeout(popoverTimeout);
+ popoverTimeout = null;
+ }
+
+ // Delay hide to allow moving to popover
+ setTimeout(() => {
+ const popover = getPopover();
+ if (!popover.matches(':hover') && !element.matches(':hover')) {
+ hidePopover();
+ }
+ }, 100);
});
});
}
@@ -255,7 +372,7 @@ function draw(pathway, elem) {
}
}
- popupContent += "

"
+ popupContent += "

"
if (n.scenarios.length > 0) {
popupContent += '
Half-lives and related scenarios:'
for (var s of n.scenarios) {
@@ -265,7 +382,7 @@ function draw(pathway, elem) {
var isLeaf = pathway.links.filter(obj => obj.source.id === n.id).length === 0;
if (pathway.isIncremental && isLeaf) {
- popupContent += '
Predict from here';
+ popupContent += '
Predict from here';
}
return popupContent;
@@ -285,7 +402,7 @@ function draw(pathway, elem) {
popupContent += adcontent;
}
- popupContent += "

"
+ popupContent += "

"
if (e.reaction_probability) {
popupContent += '
Probability:' + e.reaction_probability.toFixed(3) + '
';
}
@@ -308,6 +425,23 @@ function draw(pathway, elem) {
});
const zoomable = d3.select("#zoomable");
+ const svg = d3.select("#pwsvg");
+ const container = d3.select("#vizdiv");
+
+ // Set explicit SVG dimensions for proper zoom behavior
+ svg.attr("width", width)
+ .attr("height", height);
+
+ // Add background rectangle FIRST to enable pan/zoom on empty space
+ // This must be inserted before zoomable group so it's behind everything
+ svg.insert("rect", "#zoomable")
+ .attr("x", 0)
+ .attr("y", 0)
+ .attr("width", width)
+ .attr("height", height)
+ .attr("fill", "transparent")
+ .attr("pointer-events", "all")
+ .style("cursor", "grab");
// Zoom Funktion aktivieren
const zoom = d3.zoom()
@@ -316,7 +450,12 @@ function draw(pathway, elem) {
zoomable.attr("transform", event.transform);
});
- d3.select("svg").call(zoom);
+ // Apply zoom to the SVG element - this enables wheel zoom
+ svg.call(zoom);
+
+ // Also apply zoom to container to catch events that might not reach SVG
+ // This ensures drag-to-pan works even when clicking on empty space
+ container.call(zoom);
nodes = pathway['nodes'];
links = pathway['links'];
diff --git a/templates/actions/collections/compound.html b/templates/actions/collections/compound.html
index 417f30a8..9133ba9a 100644
--- a/templates/actions/collections/compound.html
+++ b/templates/actions/collections/compound.html
@@ -1,6 +1,9 @@
{% if meta.can_edit %}
-
+
New Compound
diff --git a/templates/actions/collections/compound_structure.html b/templates/actions/collections/compound_structure.html
index 3867a865..48ef3681 100644
--- a/templates/actions/collections/compound_structure.html
+++ b/templates/actions/collections/compound_structure.html
@@ -2,8 +2,7 @@
New Compound Structure
diff --git a/templates/actions/collections/edge.html b/templates/actions/collections/edge.html
index efdccf98..13e24f9a 100644
--- a/templates/actions/collections/edge.html
+++ b/templates/actions/collections/edge.html
@@ -1,6 +1,9 @@
{% if meta.can_edit %}
-
+
New Edge
diff --git a/templates/actions/collections/group.html b/templates/actions/collections/group.html
index 7146febc..40f7e0ef 100644
--- a/templates/actions/collections/group.html
+++ b/templates/actions/collections/group.html
@@ -1,5 +1,8 @@
-
+
New Group
diff --git a/templates/actions/collections/model.html b/templates/actions/collections/model.html
index 48be3ea9..65e630c9 100644
--- a/templates/actions/collections/model.html
+++ b/templates/actions/collections/model.html
@@ -1,6 +1,9 @@
{% if meta.can_edit and meta.enabled_features.MODEL_BUILDING %}
-
+
New Model
diff --git a/templates/actions/collections/node.html b/templates/actions/collections/node.html
index 4835e16f..eb10ff73 100644
--- a/templates/actions/collections/node.html
+++ b/templates/actions/collections/node.html
@@ -1,6 +1,9 @@
{% if meta.can_edit %}
-
+
New Node
diff --git a/templates/actions/collections/package.html b/templates/actions/collections/package.html
index edb3577b..3621b4bf 100644
--- a/templates/actions/collections/package.html
+++ b/templates/actions/collections/package.html
@@ -1,18 +1,23 @@
-
+
New Package
-
+
Import Package from JSON
Import Package from legacy
JSON
-
+
New Reaction
diff --git a/templates/actions/collections/rule.html b/templates/actions/collections/rule.html
index a3dcbbcd..6a560deb 100644
--- a/templates/actions/collections/rule.html
+++ b/templates/actions/collections/rule.html
@@ -1,6 +1,9 @@
{% if meta.can_edit %}
-
+
New Rule
diff --git a/templates/actions/collections/scenario.html b/templates/actions/collections/scenario.html
index 92521924..ec203126 100644
--- a/templates/actions/collections/scenario.html
+++ b/templates/actions/collections/scenario.html
@@ -1,6 +1,9 @@
{% if meta.can_edit %}
-
+
New Scenario
diff --git a/templates/actions/collections/setting.html b/templates/actions/collections/setting.html
index 4d7eb345..2499cfb0 100644
--- a/templates/actions/collections/setting.html
+++ b/templates/actions/collections/setting.html
@@ -1,6 +1,9 @@
{% if meta.can_edit %}
-
+
New Setting
diff --git a/templates/actions/objects/compound.html b/templates/actions/objects/compound.html
index ff34041b..d463309f 100644
--- a/templates/actions/objects/compound.html
+++ b/templates/actions/objects/compound.html
@@ -1,42 +1,59 @@
{% if meta.can_edit %}
-
+
Edit Compound
-
+
Set Aliases
-
+
Add Structure
-
+
Set Scenarios
Set External Reference
{% endif %}
-
+
Copy
{% if meta.can_edit %}
-
+
Delete Compound
diff --git a/templates/actions/objects/compound_structure.html b/templates/actions/objects/compound_structure.html
index cfe3a57b..d214cd05 100644
--- a/templates/actions/objects/compound_structure.html
+++ b/templates/actions/objects/compound_structure.html
@@ -2,33 +2,40 @@
Edit Compound Structure
-
+
Set Aliases
-
+
Set Scenarios
Set External Reference
-
+
Delete Compound Structure
diff --git a/templates/actions/objects/edge.html b/templates/actions/objects/edge.html
index c36d7dd2..99f831d7 100644
--- a/templates/actions/objects/edge.html
+++ b/templates/actions/objects/edge.html
@@ -1,16 +1,25 @@
{% if meta.can_edit %}
-
+
Set Aliases
-
+
Set Scenarios
-
+
Delete Edge
diff --git a/templates/actions/objects/group.html b/templates/actions/objects/group.html
index fdeeb76b..974722c3 100644
--- a/templates/actions/objects/group.html
+++ b/templates/actions/objects/group.html
@@ -1,11 +1,17 @@
{% if meta.can_edit %}
-
+
Add/Remove Member
-
+
Delete Group
diff --git a/templates/actions/objects/model.html b/templates/actions/objects/model.html
index b84d7f67..5f58feda 100644
--- a/templates/actions/objects/model.html
+++ b/templates/actions/objects/model.html
@@ -1,21 +1,33 @@
{% if meta.can_edit %}
-
+
Edit Model
-
+
Evaluate Model
-
+
Retrain Model
-
+
Delete Model
diff --git a/templates/actions/objects/node.html b/templates/actions/objects/node.html
index 787132eb..cbf5bbe5 100644
--- a/templates/actions/objects/node.html
+++ b/templates/actions/objects/node.html
@@ -1,21 +1,33 @@
{% if meta.can_edit %}
-
+
Edit Node
-
+
Set Aliases
-
+
Set Scenarios
-
+
Delete Node
diff --git a/templates/actions/objects/package.html b/templates/actions/objects/package.html
index fb489d37..2ad3483d 100644
--- a/templates/actions/objects/package.html
+++ b/templates/actions/objects/package.html
@@ -1,35 +1,49 @@
{% if meta.can_edit %}
-
+
Edit Package
Edit Permissions
-
+
Publish Package
-
+
Export Package as JSON
-
+
License
-
+
Delete Package
diff --git a/templates/actions/objects/pathway.html b/templates/actions/objects/pathway.html
index 760557b9..4b2e898e 100644
--- a/templates/actions/objects/pathway.html
+++ b/templates/actions/objects/pathway.html
@@ -1,26 +1,34 @@
{% if meta.can_edit %}
-
+
Add Compound
-
+
Add Reaction
{% endif %}
-
+
Copy
Download Pathway as CSV
@@ -28,8 +36,7 @@
Download Pathway as Image
@@ -38,8 +45,7 @@
Identify Missing
Rules
-
+
Edit Pathway
-
+
Set Scenarios
-
+
Set Aliases
- {#
#}
- {# #}
- {# Calculate Compound Properties#}
- {# #}
Delete Compound
@@ -78,14 +88,16 @@
Delete Reaction
-
+
Delete Pathway
diff --git a/templates/actions/objects/reaction.html b/templates/actions/objects/reaction.html
index 1bf3d953..c21c77dc 100644
--- a/templates/actions/objects/reaction.html
+++ b/templates/actions/objects/reaction.html
@@ -1,37 +1,51 @@
{% if meta.can_edit %}
-
+
Edit Reaction
-
+
Set Aliases
-
+
Set Scenarios
Set External Reference
{% endif %}
-
+
Copy
{% if meta.can_edit %}
-
+
Delete Reaction
diff --git a/templates/actions/objects/rule.html b/templates/actions/objects/rule.html
index 4c9e0282..850bc264 100644
--- a/templates/actions/objects/rule.html
+++ b/templates/actions/objects/rule.html
@@ -1,28 +1,43 @@
{% if meta.can_edit %}
-
+
Edit Rule
-
+
Set Aliases
-
+
Set Scenarios
{% endif %}
-
+
Copy
{% if meta.can_edit %}
-
+
Delete Rule
diff --git a/templates/actions/objects/scenario.html b/templates/actions/objects/scenario.html
index 33e9f999..532ef6b1 100644
--- a/templates/actions/objects/scenario.html
+++ b/templates/actions/objects/scenario.html
@@ -2,8 +2,7 @@
Add Additional Information
@@ -11,14 +10,16 @@
Set Additional Information
-
+
Delete Scenario
diff --git a/templates/actions/objects/user.html b/templates/actions/objects/user.html
index 9404c57c..b386436e 100644
--- a/templates/actions/objects/user.html
+++ b/templates/actions/objects/user.html
@@ -1,19 +1,24 @@
{% if meta.can_edit %}
-
+
Update
-
+
Update Password
New Prediction Setting
@@ -23,7 +28,10 @@
{# Manage API Token#}
{# #}
-
+
Delete Account
diff --git a/templates/collections/joblog.html b/templates/collections/joblog.html
index a14c3564..2a469a62 100644
--- a/templates/collections/joblog.html
+++ b/templates/collections/joblog.html
@@ -1,49 +1,33 @@
-{% extends "framework.html" %}
+{% extends "framework_modern.html" %}
{% load static %}
{% load envipytags %}
{% block content %}
-
-
-
- Jobs
-
-
-
Job Logs Desc
+
+
+
+
+
User Prediction Jobs
+
Job Logs Desc
+
-
-
-
-
-
- {% if meta.user.is_superuser %}
- | User |
- {% endif %}
- ID |
- Name |
- Status |
- Queued |
- Done |
- Result |
-
+
+
+
+
Recent Jobs
+
+
+
+
+
+ | ID |
+ Name |
+ Status |
+ Queued |
+ Done |
+ Result |
+
+
{% for job in jobs %}
@@ -58,7 +42,11 @@
| {{ job.created }} |
{{ job.done_at }} |
{% if job.task_result and job.task_result|is_url == True %}
- Result |
+
+ Result
+ |
{% elif job.task_result %}
{{ job.task_result|slice:"40" }}... |
{% else %}
@@ -70,19 +58,31 @@
-
-
-
+
+ {% if objects %}
+
+
+ {% endif %}
{% endblock content %}
diff --git a/templates/collections/objects_list.html b/templates/collections/objects_list.html
index bd214465..e574d862 100644
--- a/templates/collections/objects_list.html
+++ b/templates/collections/objects_list.html
@@ -1,28 +1,32 @@
-{% extends "framework.html" %}
+{% extends "framework_modern.html" %}
{% load static %}
{% block content %}
- {% if object_type != 'package' %}
-
-
-
-
- Error:
- Getting objects failed!
-
-
+ {# Serialize objects data for Alpine pagination #}
+ {# prettier-ignore-start #}
+ {# FIXME: This is a hack to get the objects data into the JavaScript code. #}
+
+ {# prettier-ignore-end #}
+ {% if object_type != 'package' %}
+
{% endif %}
@@ -56,423 +60,474 @@
{% endif %}
{% endblock action_modals %}
-
-
-
- {% if object_type == 'package' %}
- Packages
- {% elif object_type == 'compound' %}
- Compounds
- {% elif object_type == 'structure' %}
- Compound structures
- {% elif object_type == 'rule' %}
- Rules
- {% elif object_type == 'reaction' %}
- Reactions
- {% elif object_type == 'pathway' %}
- Pathways
- {% elif object_type == 'node' %}
- Nodes
- {% elif object_type == 'edge' %}
- Edges
- {% elif object_type == 'scenario' %}
- Scenarios
- {% elif object_type == 'model' %}
- Model
- {% elif object_type == 'setting' %}
- Settings
- {% elif object_type == 'user' %}
- Users
- {% elif object_type == 'group' %}
- Groups
- {% endif %}
-