From f5168c27bfa645a75d43f7f04fea34e425eae119 Mon Sep 17 00:00:00 2001 From: Kobe Date: Mon, 23 Jun 2025 19:06:08 +0200 Subject: [PATCH] Update instances.html --- templates/main/instances.html | 115 ++++++++++++++++++++++++++++++---- 1 file changed, 104 insertions(+), 11 deletions(-) diff --git a/templates/main/instances.html b/templates/main/instances.html index 61ec53b..5120841 100644 --- a/templates/main/instances.html +++ b/templates/main/instances.html @@ -40,6 +40,15 @@ background-color: #d1ecf1 !important; border-color: #bee5eb !important; } + + .badge.bg-orange { + background-color: #fd7e14 !important; + color: white !important; + } + + .badge.bg-orange:hover { + background-color: #e55a00 !important; + } {% endblock %} @@ -742,15 +751,13 @@ document.addEventListener('DOMContentLoaded', function() { } // Wait a short moment to ensure the table is rendered - setTimeout(() => { - // Check statuses on page load + setTimeout(async () => { + // First fetch latest version information + await fetchLatestVersion(); + + // Then check statuses and fetch company names checkAllInstanceStatuses(); - - // Fetch company names for all instances fetchCompanyNames(); - - // Fetch latest version information - fetchLatestVersion(); }, 100); // Set up periodic status checks (every 30 seconds) @@ -936,6 +943,49 @@ async function fetchInstanceStats(instanceUrl, instanceId, jwtToken) { } } +// Function to compare semantic versions and determine update type +function compareSemanticVersions(currentVersion, latestVersion) { + try { + // Parse versions into parts (handle cases like "1.0" or "1.0.0") + const parseVersion = (version) => { + const parts = version.split('.').map(part => { + const num = parseInt(part, 10); + return isNaN(num) ? 0 : num; + }); + // Ensure we have at least 3 parts (major.minor.patch) + while (parts.length < 3) { + parts.push(0); + } + return parts.slice(0, 3); // Only take first 3 parts + }; + + const current = parseVersion(currentVersion); + const latest = parseVersion(latestVersion); + + // Compare major version + if (current[0] < latest[0]) { + return 'major'; + } + + // Compare minor version + if (current[1] < latest[1]) { + return 'minor'; + } + + // Compare patch version + if (current[2] < latest[2]) { + return 'patch'; + } + + // If we get here, current version is newer or equal + return 'up_to_date'; + + } catch (error) { + console.error('Error comparing semantic versions:', error); + return 'unknown'; + } +} + // Function to fetch version information for an instance async function fetchVersionInfo(instanceUrl, instanceId) { const row = document.querySelector(`[data-instance-id="${instanceId}"]`).closest('tr'); @@ -984,7 +1034,23 @@ async function fetchVersionInfo(instanceUrl, instanceId) { if (appVersion !== 'unknown') { // Get the latest version for comparison const latestVersionBadge = document.getElementById('latestVersionBadge'); - const latestVersion = latestVersionBadge ? latestVersionBadge.textContent.replace('Loading...', '').trim() : null; + let latestVersion = latestVersionBadge ? latestVersionBadge.textContent.replace('Loading...', '').trim() : null; + + // If latest version is not available yet, wait a bit and try again + if (!latestVersion || latestVersion === '') { + // Show loading state while waiting for latest version + versionCell.innerHTML = ` + + ${appVersion.length > 8 ? appVersion.substring(0, 8) : appVersion} + `; + + // Wait a bit and retry the comparison + setTimeout(() => { + fetchVersionInfo(instanceUrl, instanceId); + }, 2000); + return; + } // Determine if this instance is up to date let badgeClass = 'bg-secondary'; @@ -992,13 +1058,40 @@ async function fetchVersionInfo(instanceUrl, instanceId) { let tooltipText = `App Version: ${appVersion}
Git Commit: ${gitCommit}
Deployed: ${deployedAt}`; if (latestVersion && appVersion === latestVersion) { + // Exact match - green badgeClass = 'bg-success'; statusIcon = 'fas fa-check-circle'; tooltipText += '
✅ Up to date'; } else if (latestVersion && appVersion !== latestVersion) { - badgeClass = 'bg-danger'; - statusIcon = 'fas fa-exclamation-triangle'; - tooltipText += `
⚠️ Outdated (Latest: ${latestVersion})`; + // Compare semantic versions + const versionComparison = compareSemanticVersions(appVersion, latestVersion); + + switch (versionComparison) { + case 'patch': + // Only patch version different - yellow + badgeClass = 'bg-warning'; + statusIcon = 'fas fa-exclamation-triangle'; + tooltipText += `
🟡 Patch update available (Latest: ${latestVersion})`; + break; + case 'minor': + // Minor version different - orange + badgeClass = 'bg-orange'; + statusIcon = 'fas fa-exclamation-triangle'; + tooltipText += `
🟠 Minor update available (Latest: ${latestVersion})`; + break; + case 'major': + // Major version different - red + badgeClass = 'bg-danger'; + statusIcon = 'fas fa-exclamation-triangle'; + tooltipText += `
🔴 Major update available (Latest: ${latestVersion})`; + break; + default: + // Unknown format or comparison failed - red + badgeClass = 'bg-danger'; + statusIcon = 'fas fa-exclamation-triangle'; + tooltipText += `
🔴 Outdated (Latest: ${latestVersion})`; + break; + } } versionCell.innerHTML = `