diff --git a/static/js/workers.js b/static/js/workers.js index 1d9287b..462b0b0 100644 --- a/static/js/workers.js +++ b/static/js/workers.js @@ -4,9 +4,7 @@ let workerData = null; let refreshTimer; let pageLoadTime = Date.now(); -let currentProgress = 0; -const PROGRESS_MAX = 60; // 60 seconds for a complete cycle -let lastUpdateTime = Date.now(); +let lastManualRefreshTime = 0; let filterState = { currentFilter: 'all', searchTerm: '' @@ -19,189 +17,114 @@ let serverTimeOffset = 0; let serverStartTime = null; // New variable to track custom refresh timing -let lastManualRefreshTime = 0; const MIN_REFRESH_INTERVAL = 10000; // Minimum 10 seconds between refreshes +// Hashrate Normalization Utilities +// Helper function to normalize hashrate to TH/s for consistent graphing +function normalizeHashrate(value, unit) { + if (!value || isNaN(value)) return 0; + + unit = (unit || 'th/s').toLowerCase(); + if (unit.includes('ph/s')) { + return value * 1000; // Convert PH/s to TH/s + } else if (unit.includes('eh/s')) { + return value * 1000000; // Convert EH/s to TH/s + } else if (unit.includes('gh/s')) { + return value / 1000; // Convert GH/s to TH/s + } else if (unit.includes('mh/s')) { + return value / 1000000; // Convert MH/s to TH/s + } else if (unit.includes('kh/s')) { + return value / 1000000000; // Convert KH/s to TH/s + } else if (unit.includes('h/s') && !unit.includes('th/s') && !unit.includes('ph/s') && + !unit.includes('eh/s') && !unit.includes('gh/s') && !unit.includes('mh/s') && + !unit.includes('kh/s')) { + return value / 1000000000000; // Convert H/s to TH/s + } else { + // Assume TH/s if unit is not recognized + return value; + } +} + +// Helper function to format hashrate values for display +function formatHashrateForDisplay(value, unit) { + if (isNaN(value) || value === null || value === undefined) return "N/A"; + + // Always normalize to TH/s first if unit is provided + let normalizedValue = unit ? normalizeHashrate(value, unit) : value; + + // Select appropriate unit based on magnitude + if (normalizedValue >= 1000000) { // EH/s range + return (normalizedValue / 1000000).toFixed(2) + ' EH/s'; + } else if (normalizedValue >= 1000) { // PH/s range + return (normalizedValue / 1000).toFixed(2) + ' PH/s'; + } else if (normalizedValue >= 1) { // TH/s range + return normalizedValue.toFixed(2) + ' TH/s'; + } else if (normalizedValue >= 0.001) { // GH/s range + return (normalizedValue * 1000).toFixed(2) + ' GH/s'; + } else { // MH/s range or smaller + return (normalizedValue * 1000000).toFixed(2) + ' MH/s'; + } +} + // Initialize the page -$(document).ready(function() { +$(document).ready(function () { + console.log("Worker page initializing..."); + // Set up initial UI initializePage(); - + // Get server time for uptime calculation updateServerTime(); - - // Set up refresh synchronization with main dashboard - setupRefreshSync(); - + + // Define global refresh function for BitcoinMinuteRefresh + window.manualRefresh = fetchWorkerData; + + // Wait before initializing BitcoinMinuteRefresh to ensure DOM is ready + setTimeout(function () { + // Initialize BitcoinMinuteRefresh with our refresh function + if (typeof BitcoinMinuteRefresh !== 'undefined' && BitcoinMinuteRefresh.initialize) { + BitcoinMinuteRefresh.initialize(window.manualRefresh); + console.log("BitcoinMinuteRefresh initialized with refresh function"); + } else { + console.warn("BitcoinMinuteRefresh not available"); + } + }, 500); + // Fetch worker data immediately on page load fetchWorkerData(); - - // Set up refresh timer - setInterval(updateProgressBar, 1000); - - // Set up uptime timer - synced with main dashboard - setInterval(updateUptime, 1000); - - // Start server time polling - same as main dashboard - setInterval(updateServerTime, 30000); - - // Auto-refresh worker data - aligned with main dashboard if possible - setInterval(function() { - // Check if it's been at least PROGRESS_MAX seconds since last update - const timeSinceLastUpdate = Date.now() - lastUpdateTime; - if (timeSinceLastUpdate >= PROGRESS_MAX * 1000) { - // Check if there was a recent manual refresh - const timeSinceManualRefresh = Date.now() - lastManualRefreshTime; - if (timeSinceManualRefresh >= MIN_REFRESH_INTERVAL) { - console.log("Auto-refresh triggered after time interval"); - fetchWorkerData(); - } - } - }, 10000); // Check every 10 seconds to align better with main dashboard - + // Set up filter button click handlers - $('.filter-button').click(function() { + $('.filter-button').click(function () { $('.filter-button').removeClass('active'); $(this).addClass('active'); filterState.currentFilter = $(this).data('filter'); filterWorkers(); }); - + // Set up search input handler - $('#worker-search').on('input', function() { + $('#worker-search').on('input', function () { filterState.searchTerm = $(this).val().toLowerCase(); filterWorkers(); }); }); -// Set up refresh synchronization with main dashboard -function setupRefreshSync() { - // Listen for storage events (triggered by main dashboard) - window.addEventListener('storage', function(event) { - // Check if this is our dashboard refresh event - if (event.key === 'dashboardRefreshEvent') { - console.log("Detected dashboard refresh event"); - - // Prevent too frequent refreshes - const now = Date.now(); - const timeSinceLastRefresh = now - lastUpdateTime; - - if (timeSinceLastRefresh >= MIN_REFRESH_INTERVAL) { - console.log("Syncing refresh with main dashboard"); - // Reset progress bar and immediately fetch - resetProgressBar(); - // Refresh the worker data - fetchWorkerData(); - } else { - console.log("Skipping too-frequent refresh", timeSinceLastRefresh); - // Just reset the progress bar to match main dashboard - resetProgressBar(); - } - } - }); - - // On page load, check if we should align with main dashboard timing - try { - const lastDashboardRefresh = localStorage.getItem('dashboardRefreshTime'); - if (lastDashboardRefresh) { - const lastRefreshTime = parseInt(lastDashboardRefresh); - const timeSinceLastDashboardRefresh = Date.now() - lastRefreshTime; - - // If main dashboard refreshed recently, adjust our timer - if (timeSinceLastDashboardRefresh < PROGRESS_MAX * 1000) { - console.log("Adjusting timer to align with main dashboard"); - currentProgress = Math.floor(timeSinceLastDashboardRefresh / 1000); - updateProgressBar(currentProgress); - - // Calculate when next update will happen (roughly 60 seconds from last dashboard refresh) - const timeUntilNextRefresh = (PROGRESS_MAX * 1000) - timeSinceLastDashboardRefresh; - - // Schedule a one-time check near the expected refresh time - if (timeUntilNextRefresh > 0) { - console.log(`Scheduling coordinated refresh in ${Math.floor(timeUntilNextRefresh/1000)} seconds`); - setTimeout(function() { - // Check if a refresh happened in the last few seconds via localStorage event - const newLastRefresh = parseInt(localStorage.getItem('dashboardRefreshTime') || '0'); - const secondsSinceLastRefresh = (Date.now() - newLastRefresh) / 1000; - - // If dashboard hasn't refreshed in the last 5 seconds, do our own refresh - if (secondsSinceLastRefresh > 5) { - console.log("Coordinated refresh time reached, fetching data"); - fetchWorkerData(); - } else { - console.log("Dashboard already refreshed recently, skipping coordinated refresh"); - } - }, timeUntilNextRefresh); - } - } - } - } catch (e) { - console.error("Error reading dashboard refresh time:", e); - } - - // Check for dashboard refresh periodically - setInterval(function() { - try { - const lastDashboardRefresh = parseInt(localStorage.getItem('dashboardRefreshTime') || '0'); - const now = Date.now(); - const timeSinceLastRefresh = (now - lastUpdateTime) / 1000; - const timeSinceDashboardRefresh = (now - lastDashboardRefresh) / 1000; - - // If dashboard refreshed more recently than we did and we haven't refreshed in at least 10 seconds - if (lastDashboardRefresh > lastUpdateTime && timeSinceLastRefresh > 10) { - console.log("Catching up with dashboard refresh"); - resetProgressBar(); - fetchWorkerData(); - } - } catch (e) { - console.error("Error in periodic dashboard check:", e); - } - }, 5000); // Check every 5 seconds -} - -// Server time update via polling - same as main.js -function updateServerTime() { - $.ajax({ - url: "/api/time", - method: "GET", - timeout: 5000, - success: function(data) { - serverTimeOffset = new Date(data.server_timestamp).getTime() - Date.now(); - serverStartTime = new Date(data.server_start_time).getTime(); - }, - error: function(jqXHR, textStatus, errorThrown) { - console.error("Error fetching server time:", textStatus, errorThrown); - } - }); -} - -// Update uptime display - synced with main dashboard -function updateUptime() { - if (serverStartTime) { - const currentServerTime = Date.now() + serverTimeOffset; - const diff = currentServerTime - serverStartTime; - const hours = Math.floor(diff / (1000 * 60 * 60)); - const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); - const seconds = Math.floor((diff % (1000 * 60)) / 1000); - $("#uptimeTimer").html("Uptime: " + hours + "h " + minutes + "m " + seconds + "s"); - } -} - // Initialize page elements function initializePage() { + console.log("Initializing page elements..."); + // Initialize mini chart for total hashrate if the element exists if (document.getElementById('total-hashrate-chart')) { initializeMiniChart(); } - + // Show loading state $('#worker-grid').html('
Loading worker data...
'); - + // Add retry button (hidden by default) if (!$('#retry-button').length) { $('body').append(''); - - $('#retry-button').on('click', function() { + + $('#retry-button').on('click', function () { $(this).text('Retrying...').prop('disabled', true); fetchWorkerData(true); setTimeout(() => { @@ -211,45 +134,109 @@ function initializePage() { } } +// Server time update via polling - enhanced to use shared storage +function updateServerTime() { + console.log("Updating server time..."); + + // First try to get stored values + try { + const storedOffset = localStorage.getItem('serverTimeOffset'); + const storedStartTime = localStorage.getItem('serverStartTime'); + + if (storedOffset && storedStartTime) { + serverTimeOffset = parseFloat(storedOffset); + serverStartTime = parseFloat(storedStartTime); + console.log("Using stored server time offset:", serverTimeOffset, "ms"); + + // Only update BitcoinMinuteRefresh if it's initialized + if (typeof BitcoinMinuteRefresh !== 'undefined' && BitcoinMinuteRefresh.updateServerTime) { + BitcoinMinuteRefresh.updateServerTime(serverTimeOffset, serverStartTime); + } + return; // Don't fetch if we have valid values + } + } catch (e) { + console.error("Error reading stored server time:", e); + } + + // Fetch from API if needed + $.ajax({ + url: "/api/time", + method: "GET", + timeout: 5000, + success: function (data) { + // Calculate the offset between server time and local time + serverTimeOffset = new Date(data.server_timestamp).getTime() - Date.now(); + serverStartTime = new Date(data.server_start_time).getTime(); + + // Store in localStorage for cross-page sharing + localStorage.setItem('serverTimeOffset', serverTimeOffset.toString()); + localStorage.setItem('serverStartTime', serverStartTime.toString()); + + // Only update BitcoinMinuteRefresh if it's initialized + if (typeof BitcoinMinuteRefresh !== 'undefined' && BitcoinMinuteRefresh.updateServerTime) { + BitcoinMinuteRefresh.updateServerTime(serverTimeOffset, serverStartTime); + } + + console.log("Server time synchronized. Offset:", serverTimeOffset, "ms"); + }, + error: function (jqXHR, textStatus, errorThrown) { + console.error("Error fetching server time:", textStatus, errorThrown); + } + }); +} + // Fetch worker data from API function fetchWorkerData(forceRefresh = false) { + console.log("Fetching worker data..."); + // Track this as a manual refresh for throttling purposes lastManualRefreshTime = Date.now(); - + $('#worker-grid').addClass('loading-fade'); - - // Update progress bar to show data is being fetched - resetProgressBar(); - + // Choose API URL based on whether we're forcing a refresh const apiUrl = `/api/workers${forceRefresh ? '?force=true' : ''}`; - + $.ajax({ url: apiUrl, method: 'GET', dataType: 'json', timeout: 15000, // 15 second timeout - success: function(data) { + success: function (data) { + if (!data || !data.workers || data.workers.length === 0) { + console.warn("No workers found in data response"); + $('#worker-grid').html(` +
+

No workers found. Try refreshing the page.

+
+ `); + return; + } + workerData = data; - lastUpdateTime = Date.now(); - + + // Notify BitcoinMinuteRefresh that we've refreshed the data + if (typeof BitcoinMinuteRefresh !== 'undefined' && BitcoinMinuteRefresh.notifyRefresh) { + BitcoinMinuteRefresh.notifyRefresh(); + } + // Update UI with new data updateWorkerGrid(); updateSummaryStats(); updateMiniChart(); updateLastUpdated(); - + // Hide retry button $('#retry-button').hide(); - + // Reset connection retry count connectionRetryCount = 0; - + console.log("Worker data updated successfully"); }, - error: function(xhr, status, error) { + error: function (xhr, status, error) { console.error("Error fetching worker data:", error); - + // Show error in worker grid $('#worker-grid').html(`
@@ -257,39 +244,40 @@ function fetchWorkerData(forceRefresh = false) {

Error loading worker data: ${error || 'Unknown error'}

`); - + // Show retry button $('#retry-button').show(); - + // Implement exponential backoff for automatic retry connectionRetryCount++; const delay = Math.min(30000, 1000 * Math.pow(1.5, Math.min(5, connectionRetryCount))); - console.log(`Will retry in ${delay/1000} seconds (attempt ${connectionRetryCount})`); - + console.log(`Will retry in ${delay / 1000} seconds (attempt ${connectionRetryCount})`); + setTimeout(() => { fetchWorkerData(true); // Force refresh on retry }, delay); }, - complete: function() { + complete: function () { $('#worker-grid').removeClass('loading-fade'); } }); } // Update the worker grid with data -// UPDATED FUNCTION function updateWorkerGrid() { + console.log("Updating worker grid..."); + if (!workerData || !workerData.workers) { console.error("No worker data available"); return; } - + const workerGrid = $('#worker-grid'); workerGrid.empty(); - + // Apply current filters before rendering const filteredWorkers = filterWorkersData(workerData.workers); - + if (filteredWorkers.length === 0) { workerGrid.html(`
@@ -299,82 +287,66 @@ function updateWorkerGrid() { `); return; } - - // Calculate total unpaid earnings (from the dashboard) - const totalUnpaidEarnings = workerData.total_earnings || 0; - - // Sum up hashrates of online workers to calculate share percentages - const totalHashrate = workerData.workers - .filter(w => w.status === 'online') - .reduce((sum, w) => sum + parseFloat(w.hashrate_3hr || 0), 0); - - // Calculate share percentage for each worker - const onlineWorkers = workerData.workers.filter(w => w.status === 'online'); - const offlineWorkers = workerData.workers.filter(w => w.status === 'offline'); - - // Allocate 95% to online workers, 5% to offline workers - const onlinePool = totalUnpaidEarnings * 0.95; - const offlinePool = totalUnpaidEarnings * 0.05; - + // Generate worker cards filteredWorkers.forEach(worker => { - // Calculate earnings share based on hashrate proportion - let earningsDisplay = worker.earnings; - - // Explicitly recalculate earnings share for display consistency - if (worker.status === 'online' && totalHashrate > 0) { - const hashrateShare = parseFloat(worker.hashrate_3hr || 0) / totalHashrate; - earningsDisplay = (onlinePool * hashrateShare).toFixed(8); - } else if (worker.status === 'offline' && offlineWorkers.length > 0) { - earningsDisplay = (offlinePool / offlineWorkers.length).toFixed(8); - } - // Create worker card const card = $('
'); - + // Add class based on status if (worker.status === 'online') { card.addClass('worker-card-online'); } else { card.addClass('worker-card-offline'); } - + // Add worker type badge card.append(`
${worker.type}
`); - + // Add worker name card.append(`
${worker.name}
`); - + // Add status badge if (worker.status === 'online') { card.append('
ONLINE
'); } else { card.append('
OFFLINE
'); } - - // Add hashrate bar + + // Add hashrate bar with normalized values for consistent display const maxHashrate = 200; // TH/s - adjust based on your fleet - const hashratePercent = Math.min(100, (worker.hashrate_3hr / maxHashrate) * 100); + const normalizedHashrate = normalizeHashrate( + worker.hashrate_3hr, + worker.hashrate_3hr_unit || 'th/s' + ); + const hashratePercent = Math.min(100, (normalizedHashrate / maxHashrate) * 100); + + // Format hashrate for display with appropriate unit + const formattedHashrate = formatHashrateForDisplay( + worker.hashrate_3hr, + worker.hashrate_3hr_unit || 'th/s' + ); + card.append(`
Hashrate (3hr):
-
${worker.hashrate_3hr} ${worker.hashrate_3hr_unit}
+
${formattedHashrate}
`); - - // Add additional stats - NOTE: Using recalculated earnings + + // Add additional stats card.append(`
Last Share:
-
${worker.last_share.split(' ')[1]}
+
${typeof worker.last_share === 'string' ? worker.last_share.split(' ')[1] || worker.last_share : 'N/A'}
Earnings:
-
${earningsDisplay}
+
${worker.earnings.toFixed(8)}
Accept Rate:
@@ -386,35 +358,22 @@ function updateWorkerGrid() {
`); - + // Add card to grid workerGrid.append(card); }); - - // Verify the sum of displayed earnings equals the total - console.log(`Total unpaid earnings: ${totalUnpaidEarnings} BTC`); - console.log(`Sum of worker displayed earnings: ${ - filteredWorkers.reduce((sum, w) => { - if (w.status === 'online' && totalHashrate > 0) { - const hashrateShare = parseFloat(w.hashrate_3hr || 0) / totalHashrate; - return sum + parseFloat((onlinePool * hashrateShare).toFixed(8)); - } else if (w.status === 'offline' && offlineWorkers.length > 0) { - return sum + parseFloat((offlinePool / offlineWorkers.length).toFixed(8)); - } - return sum; - }, 0) - } BTC`); } // Filter worker data based on current filter state function filterWorkersData(workers) { if (!workers) return []; - + return workers.filter(worker => { - const workerName = worker.name.toLowerCase(); + // Default to empty string if name is undefined + const workerName = (worker.name || '').toLowerCase(); const isOnline = worker.status === 'online'; - const workerType = worker.type.toLowerCase(); - + const workerType = (worker.type || '').toLowerCase(); + // Check if worker matches filter let matchesFilter = false; if (filterState.currentFilter === 'all') { @@ -428,10 +387,10 @@ function filterWorkersData(workers) { } else if (filterState.currentFilter === 'fpga' && workerType === 'fpga') { matchesFilter = true; } - + // Check if worker matches search term - const matchesSearch = workerName.includes(filterState.searchTerm); - + const matchesSearch = filterState.searchTerm === '' || workerName.includes(filterState.searchTerm); + return matchesFilter && matchesSearch; }); } @@ -439,35 +398,37 @@ function filterWorkersData(workers) { // Apply filter to rendered worker cards function filterWorkers() { if (!workerData || !workerData.workers) return; - + // Re-render the worker grid with current filters updateWorkerGrid(); } -// Modified updateSummaryStats function for workers.js +// Modified updateSummaryStats function with normalized hashrate display function updateSummaryStats() { if (!workerData) return; - + // Update worker counts $('#workers-count').text(workerData.workers_total || 0); $('#workers-online').text(workerData.workers_online || 0); $('#workers-offline').text(workerData.workers_offline || 0); - + // Update worker ring percentage - const onlinePercent = workerData.workers_total > 0 ? + const onlinePercent = workerData.workers_total > 0 ? workerData.workers_online / workerData.workers_total : 0; $('.worker-ring').css('--online-percent', onlinePercent); - - // IMPORTANT: Update total hashrate using EXACT format matching main dashboard - // This ensures the displayed value matches exactly what's on the main page + + // Display normalized hashrate with appropriate unit if (workerData.total_hashrate !== undefined) { - // Format with exactly 1 decimal place - matches main dashboard format - const formattedHashrate = Number(workerData.total_hashrate).toFixed(1); - $('#total-hashrate').text(`${formattedHashrate} ${workerData.hashrate_unit || 'TH/s'}`); + // Format with proper unit conversion + const formattedHashrate = formatHashrateForDisplay( + workerData.total_hashrate, + workerData.hashrate_unit || 'TH/s' + ); + $('#total-hashrate').text(formattedHashrate); } else { - $('#total-hashrate').text(`0.0 ${workerData.hashrate_unit || 'TH/s'}`); + $('#total-hashrate').text(`0.0 TH/s`); } - + // Update other summary stats $('#total-earnings').text(`${(workerData.total_earnings || 0).toFixed(8)} BTC`); $('#daily-sats').text(`${numberWithCommas(workerData.daily_sats || 0)} sats`); @@ -476,12 +437,18 @@ function updateSummaryStats() { // Initialize mini chart function initializeMiniChart() { - const ctx = document.getElementById('total-hashrate-chart').getContext('2d'); - + console.log("Initializing mini chart..."); + + const ctx = document.getElementById('total-hashrate-chart'); + if (!ctx) { + console.error("Mini chart canvas not found"); + return; + } + // Generate some sample data to start const labels = Array(24).fill('').map((_, i) => i); - const data = [750, 760, 755, 770, 780, 775, 760, 765, 770, 775, 780, 790, 785, 775, 770, 765, 780, 785, 775, 770, 775, 780, 775, 774.8]; - + const data = Array(24).fill(0).map(() => Math.random() * 100 + 700); + miniChart = new Chart(ctx, { type: 'line', data: { @@ -501,7 +468,7 @@ function initializeMiniChart() { maintainAspectRatio: false, scales: { x: { display: false }, - y: { + y: { display: false, min: Math.min(...data) * 0.9, max: Math.max(...data) * 1.1 @@ -521,113 +488,49 @@ function initializeMiniChart() { }); } -// Update mini chart with real data +// Update mini chart with real data and normalization function updateMiniChart() { - if (!miniChart || !workerData || !workerData.hashrate_history) return; - + if (!miniChart || !workerData || !workerData.hashrate_history) { + console.log("Skipping mini chart update - missing data"); + return; + } + // Extract hashrate data from history const historyData = workerData.hashrate_history; - if (!historyData || historyData.length === 0) return; - - // Get the values for the chart - const values = historyData.map(item => parseFloat(item.value) || 0); + if (!historyData || historyData.length === 0) { + console.log("No hashrate history data available"); + return; + } + + // Get the normalized values for the chart + const values = historyData.map(item => { + const val = parseFloat(item.value) || 0; + const unit = item.unit || workerData.hashrate_unit || 'th/s'; + return normalizeHashrate(val, unit); + }); const labels = historyData.map(item => item.time); - + // Update chart data miniChart.data.labels = labels; miniChart.data.datasets[0].data = values; - + // Update y-axis range - const min = Math.min(...values); - const max = Math.max(...values); + const min = Math.min(...values.filter(v => v > 0)) || 0; + const max = Math.max(...values) || 1; miniChart.options.scales.y.min = min * 0.9; miniChart.options.scales.y.max = max * 1.1; - + // Update the chart miniChart.update('none'); } -// Update progress bar -function updateProgressBar() { - if (currentProgress < PROGRESS_MAX) { - currentProgress++; - const progressPercent = (currentProgress / PROGRESS_MAX) * 100; - $("#bitcoin-progress-inner").css("width", progressPercent + "%"); - - // Add glowing effect when close to completion - if (progressPercent > 80) { - $("#bitcoin-progress-inner").addClass("glow-effect"); - } else { - $("#bitcoin-progress-inner").removeClass("glow-effect"); - } - - // Update remaining seconds text - let remainingSeconds = PROGRESS_MAX - currentProgress; - if (remainingSeconds <= 0) { - $("#progress-text").text("Waiting for update..."); - $("#bitcoin-progress-inner").addClass("waiting-for-update"); - } else { - $("#progress-text").text(remainingSeconds + "s to next update"); - $("#bitcoin-progress-inner").removeClass("waiting-for-update"); - } - - // Check for main dashboard refresh near the end to ensure sync - if (currentProgress >= 55) { // When we're getting close to refresh time - try { - const lastDashboardRefresh = parseInt(localStorage.getItem('dashboardRefreshTime') || '0'); - const secondsSinceDashboardRefresh = (Date.now() - lastDashboardRefresh) / 1000; - - // If main dashboard just refreshed (within last 5 seconds) - if (secondsSinceDashboardRefresh <= 5) { - console.log("Detected recent dashboard refresh, syncing now"); - resetProgressBar(); - fetchWorkerData(); - return; - } - } catch (e) { - console.error("Error checking dashboard refresh status:", e); - } - } - } else { - // Reset progress bar if it's time to refresh - // But first check if the main dashboard refreshed recently - try { - const lastDashboardRefresh = parseInt(localStorage.getItem('dashboardRefreshTime') || '0'); - const secondsSinceDashboardRefresh = (Date.now() - lastDashboardRefresh) / 1000; - - // If dashboard refreshed in the last 10 seconds, wait for it instead of refreshing ourselves - if (secondsSinceDashboardRefresh < 10) { - console.log("Waiting for dashboard refresh event instead of refreshing independently"); - return; - } - } catch (e) { - console.error("Error checking dashboard refresh status:", e); - } - - // If main dashboard hasn't refreshed recently, do our own refresh - if (Date.now() - lastUpdateTime > PROGRESS_MAX * 1000) { - console.log("Progress bar expired, fetching data"); - fetchWorkerData(); - } - } -} - -// Reset progress bar -function resetProgressBar() { - currentProgress = 0; - $("#bitcoin-progress-inner").css("width", "0%"); - $("#bitcoin-progress-inner").removeClass("glow-effect"); - $("#bitcoin-progress-inner").removeClass("waiting-for-update"); - $("#progress-text").text(PROGRESS_MAX + "s to next update"); -} - // Update the last updated timestamp function updateLastUpdated() { if (!workerData || !workerData.timestamp) return; - + try { const timestamp = new Date(workerData.timestamp); - $("#lastUpdated").html("Last Updated: " + + $("#lastUpdated").html("Last Updated: " + timestamp.toLocaleString() + ""); } catch (e) { console.error("Error formatting timestamp:", e); @@ -638,4 +541,4 @@ function updateLastUpdated() { function numberWithCommas(x) { if (x == null) return "N/A"; return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); -} \ No newline at end of file +}