[Fix] UI Fixes (#266)

Rather than have a bunch of pull-requests that @jebus will have to merge shall we collect some of the fixes for the UI issues I found in here.

- [x] #259
- [x] #260
- [x] #261
- [x] #262
- [x] #263
- [x] #264
- [x] #265

Co-authored-by: Tobias O <tobias.olenyi@envipath.com>
Reviewed-on: enviPath/enviPy#266
Co-authored-by: Liam Brydon <lbry121@aucklanduni.ac.nz>
Co-committed-by: Liam Brydon <lbry121@aucklanduni.ac.nz>
This commit is contained in:
2025-12-15 21:28:43 +13:00
committed by jebus
parent 8adb93012a
commit 4bf20e62ef
15 changed files with 279 additions and 170 deletions

View File

@ -34,23 +34,3 @@
}
@import "./daisyui-theme.css";
/* Loading Spinner - Benzene Ring */
.benzene-spinner {
display: flex;
justify-content: center;
align-items: center;
padding: 2rem;
}
.benzene-spinner svg {
width: 48px;
height: 48px;
animation: spin 3s linear infinite;
}
@keyframes spin {
100% {
transform: rotate(360deg);
}
}

View File

@ -44,6 +44,7 @@ document.addEventListener('alpine:init', () => {
this.isLoading = true;
this.error = null;
this.$dispatch('loading-start');
try {
const url = new URL(this.endpoint, window.location.origin);
@ -74,6 +75,7 @@ document.addEventListener('alpine:init', () => {
this.error = `Unable to load ${this.endpoint}. Please try again.`;
} finally {
this.isLoading = false;
this.$dispatch('loading-end');
}
},

View File

@ -0,0 +1,88 @@
/**
* Pathway Viewer Alpine.js Component
*
* Provides reactive status management and polling for pathway predictions.
* Handles status updates, change detection, and update notices.
*/
document.addEventListener('alpine:init', () => {
/**
* Pathway Viewer Component
*
* Usage:
* <div x-data="pathwayViewer({
* status: 'running',
* modified: '2024-01-01T00:00:00Z',
* statusUrl: '/pathway/123?status=true'
* })" x-init="init()">
* ...
* </div>
*/
Alpine.data('pathwayViewer', (config) => ({
status: config.status,
modified: config.modified,
statusUrl: config.statusUrl,
showUpdateNotice: false,
updateMessage: '',
pollInterval: null,
get statusTooltip() {
const tooltips = {
'completed': 'Pathway prediction complete.',
'failed': 'Pathway prediction failed.',
'running': 'Pathway prediction running.'
};
return tooltips[this.status] || '';
},
init() {
if (this.status === 'running') {
this.startPolling();
}
},
startPolling() {
this.pollInterval = setInterval(() => this.checkStatus(), 5000);
},
async checkStatus() {
try {
const response = await fetch(this.statusUrl);
const data = await response.json();
if (data.modified > this.modified) {
this.showUpdateNotice = true;
this.updateMessage = this.getUpdateMessage(data.status);
}
if (data.status !== 'running') {
this.status = data.status;
if (this.pollInterval) {
clearInterval(this.pollInterval);
this.pollInterval = null;
}
}
} catch (err) {
console.error('Polling error:', err);
}
},
getUpdateMessage(status) {
let msg = 'Prediction ';
if (status === 'running') {
msg += 'is still running. But the Pathway was updated.';
} else if (status === 'completed') {
msg += 'is completed. Reload the page to see the updated Pathway.';
} else if (status === 'failed') {
msg += 'failed. Reload the page to see the current shape.';
}
return msg;
},
reloadPage() {
location.reload();
}
}));
});