[Fix] Fix Prediction Spinner, ensure proper pathway status is set

Fixes Spinner and status message display on pathway page

Reviewed-on: enviPath/enviPy#291
Co-authored-by: Tobias O <tobias.olenyi@envipath.com>
Co-committed-by: Tobias O <tobias.olenyi@envipath.com>
This commit is contained in:
2026-01-15 23:09:12 +13:00
committed by jebus
parent 1c2f70b3b9
commit 5f5ae76182
8 changed files with 105 additions and 32 deletions

View File

@ -21,6 +21,7 @@ document.addEventListener('alpine:init', () => {
Alpine.data('pathwayViewer', (config) => ({
status: config.status,
modified: config.modified,
modifiedDate: null,
statusUrl: config.statusUrl,
emptyDueToThreshold: config.emptyDueToThreshold === "True",
showUpdateNotice: false,
@ -39,6 +40,8 @@ document.addEventListener('alpine:init', () => {
},
init() {
this.modifiedDate = this.parseDate(this.modified);
if (this.status === 'running') {
this.startPolling();
}
@ -66,26 +69,39 @@ document.addEventListener('alpine:init', () => {
this.showEmptyDueToThresholdNotice = true;
}
if (data.modified > this.modified) {
if (!this.emptyDueToThreshold) {
this.showUpdateNotice = true;
this.updateMessage = this.getUpdateMessage(data.status);
}
const nextModifiedDate = this.parseDate(data.modified);
const modifiedChanged = this.hasNewerTimestamp(nextModifiedDate, this.modifiedDate);
const statusChanged = data.status !== this.status;
if ((modifiedChanged || statusChanged) && !this.emptyDueToThreshold) {
this.showUpdateNotice = true;
this.updateMessage = this.getUpdateMessage(data.status, modifiedChanged, statusChanged);
}
if (data.status !== 'running') {
this.status = data.status;
if (this.pollInterval) {
clearInterval(this.pollInterval);
this.pollInterval = null;
}
this.modified = data.modified;
this.modifiedDate = nextModifiedDate;
this.status = data.status;
if (data.status !== 'running' && this.pollInterval) {
clearInterval(this.pollInterval);
this.pollInterval = null;
}
} catch (err) {
console.error('Polling error:', err);
}
},
getUpdateMessage(status) {
getUpdateMessage(status, modifiedChanged, statusChanged) {
// Prefer explicit status change messaging, otherwise fall back to modified change copy
if (statusChanged) {
if (status === 'completed') {
return 'Prediction completed. Reload the page to see the updated Pathway.';
}
if (status === 'failed') {
return 'Prediction failed. Reload the page to see the latest status.';
}
}
let msg = 'Prediction ';
if (status === 'running') {
@ -99,6 +115,18 @@ document.addEventListener('alpine:init', () => {
return msg;
},
parseDate(dateString) {
// Normalize "YYYY-MM-DD HH:mm:ss" into an ISO-compatible string to avoid locale issues
if (!dateString) return null;
return new Date(dateString.replace(' ', 'T'));
},
hasNewerTimestamp(nextDate, currentDate) {
if (!nextDate) return false;
if (!currentDate) return true;
return nextDate.getTime() > currentDate.getTime();
},
reloadPage() {
location.reload();
}