forked from enviPath/enviPy
[Feature] Async Prediction Status Poll (#93)
Fixed #81 Co-authored-by: Tim Lorsbach <tim@lorsba.ch> Reviewed-on: enviPath/enviPy#93
This commit is contained in:
@ -1358,14 +1358,17 @@ class Pathway(EnviPathModel, AliasMixin, ScenarioMixin):
|
|||||||
return self.kv.get('mode', 'build') == 'predicted'
|
return self.kv.get('mode', 'build') == 'predicted'
|
||||||
|
|
||||||
# Status
|
# Status
|
||||||
|
def status(self):
|
||||||
|
return self.kv.get('status', 'completed')
|
||||||
|
|
||||||
def completed(self):
|
def completed(self):
|
||||||
return self.kv.get('status', 'completed') == 'completed'
|
return self.status() == 'completed'
|
||||||
|
|
||||||
def running(self):
|
def running(self):
|
||||||
return self.kv.get('status', 'completed') == 'running'
|
return self.status() == 'running'
|
||||||
|
|
||||||
def failed(self):
|
def failed(self):
|
||||||
return self.kv.get('status', 'completed') == 'failed'
|
return self.status() == 'failed'
|
||||||
|
|
||||||
def d3_json(self):
|
def d3_json(self):
|
||||||
# Ideally it would be something like this but
|
# Ideally it would be something like this but
|
||||||
@ -1472,7 +1475,8 @@ class Pathway(EnviPathModel, AliasMixin, ScenarioMixin):
|
|||||||
"upToDate": True,
|
"upToDate": True,
|
||||||
"links": adjusted_links,
|
"links": adjusted_links,
|
||||||
"nodes": nodes,
|
"nodes": nodes,
|
||||||
"modified": self.modified.strftime('%Y-%m-%d %H:%M:%S')
|
"modified": self.modified.strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
|
"status": self.status(),
|
||||||
}
|
}
|
||||||
|
|
||||||
return json.dumps(res)
|
return json.dumps(res)
|
||||||
|
|||||||
@ -1438,6 +1438,12 @@ def package_pathway(request, package_uuid, pathway_uuid):
|
|||||||
if request.GET.get("last_modified", False):
|
if request.GET.get("last_modified", False):
|
||||||
return JsonResponse({'modified': current_pathway.modified.strftime('%Y-%m-%d %H:%M:%S')})
|
return JsonResponse({'modified': current_pathway.modified.strftime('%Y-%m-%d %H:%M:%S')})
|
||||||
|
|
||||||
|
if request.GET.get('status', False):
|
||||||
|
return JsonResponse({
|
||||||
|
'status': current_pathway.status(),
|
||||||
|
'modified': current_pathway.modified.strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
|
})
|
||||||
|
|
||||||
if request.GET.get("download", False) == "true":
|
if request.GET.get("download", False) == "true":
|
||||||
filename = f"{current_pathway.name.replace(' ', '_')}_{current_pathway.uuid}.csv"
|
filename = f"{current_pathway.name.replace(' ', '_')}_{current_pathway.uuid}.csv"
|
||||||
csv_pw = current_pathway.to_csv()
|
csv_pw = current_pathway.to_csv()
|
||||||
|
|||||||
@ -149,19 +149,19 @@
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
{% if pathway.completed %}
|
{% if pathway.completed %}
|
||||||
<button type="button" class="btn btn-default navbar-btn" data-toggle="tooltip"
|
<button type="button" class="btn btn-default navbar-btn" data-toggle="popover"
|
||||||
id="status" data-original-title="" title=""
|
id="status" data-original-title="" title=""
|
||||||
data-content="Pathway prediction complete.">
|
data-content="Pathway prediction complete.">
|
||||||
<span class="glyphicon glyphicon-ok"></span>
|
<span class="glyphicon glyphicon-ok"></span>
|
||||||
</button>
|
</button>
|
||||||
{% elif pathway.failed %}
|
{% elif pathway.failed %}
|
||||||
<button type="button" class="btn btn-default navbar-btn" data-toggle="tooltip"
|
<button type="button" class="btn btn-default navbar-btn" data-toggle="popover"
|
||||||
id="status" data-original-title="" title=""
|
id="status" data-original-title="" title=""
|
||||||
data-content="Pathway prediction failed.">
|
data-content="Pathway prediction failed.">
|
||||||
<span class="glyphicon glyphicon-remove"></span>
|
<span class="glyphicon glyphicon-remove"></span>
|
||||||
</button>
|
</button>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button type="button" class="btn btn-default navbar-btn" data-toggle="tooltip"
|
<button type="button" class="btn btn-default navbar-btn" data-toggle="popover"
|
||||||
id="status" data-original-title="" title=""
|
id="status" data-original-title="" title=""
|
||||||
data-content="Pathway prediction running.">
|
data-content="Pathway prediction running.">
|
||||||
<img height="20" src="{% static '/images/wait.gif' %}">
|
<img height="20" src="{% static '/images/wait.gif' %}">
|
||||||
@ -317,7 +317,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
// Globla switch for app domain view
|
// Global switch for app domain view
|
||||||
var appDomainViewEnabled = false;
|
var appDomainViewEnabled = false;
|
||||||
|
|
||||||
function goFullscreen(id) {
|
function goFullscreen(id) {
|
||||||
@ -336,6 +336,56 @@
|
|||||||
pathway = {{ pathway.d3_json | safe }};
|
pathway = {{ pathway.d3_json | safe }};
|
||||||
|
|
||||||
$(function () {
|
$(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');
|
draw(pathway, 'vizdiv');
|
||||||
// TODO fix somewhere else...
|
// TODO fix somewhere else...
|
||||||
var newDesc = transformReferences($('#DescriptionContent')[0].innerText);
|
var newDesc = transformReferences($('#DescriptionContent')[0].innerText);
|
||||||
|
|||||||
Reference in New Issue
Block a user