diff --git a/ccw/src/templates/dashboard-js/components/version-check.js b/ccw/src/templates/dashboard-js/components/version-check.js index 0ddba25f..59b16696 100644 --- a/ccw/src/templates/dashboard-js/components/version-check.js +++ b/ccw/src/templates/dashboard-js/components/version-check.js @@ -55,26 +55,74 @@ function toggleAutoUpdate() { async function checkForUpdatesNow() { const btn = document.getElementById('checkUpdateNow'); if (btn) { - // Add loading animation - btn.classList.add('animate-spin'); + // Add loading state - change button color and animate icon + btn.classList.add('checking'); btn.disabled = true; } + // Show checking notification + console.log('[Version Check] Starting update check...'); + if (typeof addGlobalNotification === 'function') { + addGlobalNotification('info', 'Checking for updates...', 'Please wait', 'version-check'); + } else { + console.warn('[Version Check] addGlobalNotification is not available'); + } + // Force check regardless of toggle state const originalState = autoUpdateEnabled; autoUpdateEnabled = true; try { - await checkForUpdates(); - addGlobalNotification('success', 'Update check complete', 'Checked for latest version', 'version-check'); + const res = await fetch('/api/version-check'); + + if (!res.ok) { + throw new Error('Failed to fetch version information'); + } + + const data = await res.json(); + versionCheckData = data; + console.log('[Version Check] Result:', data); + + if (data.hasUpdate) { + // New version available + console.log('[Version Check] Update available:', data.latestVersion); + showUpdateBanner(data); + if (typeof addGlobalNotification === 'function') { + addGlobalNotification( + 'success', + 'Update Available!', + `New version ${data.latestVersion} is available (current: ${data.currentVersion})`, + 'version-check' + ); + } + } else { + // Already up to date + console.log('[Version Check] Already up to date:', data.currentVersion); + if (typeof addGlobalNotification === 'function') { + addGlobalNotification( + 'success', + 'You\'re up to date!', + `Current version ${data.currentVersion} is the latest`, + 'version-check' + ); + } + } } catch (err) { - addGlobalNotification('error', 'Update check failed', err.message, 'version-check'); + console.error('[Version Check] Error:', err); + if (typeof addGlobalNotification === 'function') { + addGlobalNotification( + 'error', + 'Update check failed', + err.message || 'Unable to check for updates', + 'version-check' + ); + } } finally { // Restore original state autoUpdateEnabled = originalState; if (btn) { - btn.classList.remove('animate-spin'); + btn.classList.remove('checking'); btn.disabled = false; } } diff --git a/ccw/src/templates/dashboard.html b/ccw/src/templates/dashboard.html index 6f36dca7..08c70779 100644 --- a/ccw/src/templates/dashboard.html +++ b/ccw/src/templates/dashboard.html @@ -234,6 +234,51 @@ animation: spin 1s linear infinite; } + /* Custom Tooltip (bottom position) */ + .tooltip-bottom { + position: relative; + } + .tooltip-bottom:hover::after { + content: attr(data-tooltip); + position: absolute; + top: calc(100% + 8px); + left: 50%; + transform: translateX(-50%); + padding: 6px 10px; + background-color: hsl(var(--foreground)); + color: hsl(var(--background)); + font-size: 12px; + white-space: nowrap; + border-radius: 4px; + z-index: 1000; + pointer-events: none; + } + .tooltip-bottom:hover::before { + content: ""; + position: absolute; + top: calc(100% + 2px); + left: 50%; + transform: translateX(-50%); + border: 6px solid transparent; + border-bottom-color: hsl(var(--foreground)); + z-index: 1001; + pointer-events: none; + } + + /* Check Update Button Loading State */ + #checkUpdateNow.checking { + background-color: hsl(var(--primary)); + color: hsl(var(--primary-foreground)); + pointer-events: none; + } + #checkUpdateNow.checking .check-icon-default { + display: none; + } + #checkUpdateNow.checking .check-icon-loading { + display: block; + animation: spin 1s linear infinite; + } + /* Auto-Update Toggle Switch */ .auto-update-switch { position: relative; @@ -345,15 +390,20 @@