mirror of
https://github.com/Retropex/custom-ocean.xyz-dashboard.git
synced 2025-05-12 19:20:45 +02:00
Delete templates directory
This commit is contained in:
parent
d374bc3ba1
commit
4845f42fa4
@ -1,73 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}Ocean.xyz Pool Mining Dashboard{% endblock %}</title>
|
||||
|
||||
<!-- Common fonts -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=VT323&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Font Awesome -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Common CSS -->
|
||||
<link rel="stylesheet" href="/static/css/common.css">
|
||||
|
||||
<!-- Page-specific CSS -->
|
||||
{% block css %}{% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<!-- Connection status indicator -->
|
||||
<div id="connectionStatus"></div>
|
||||
|
||||
<!-- Top right link -->
|
||||
<a href="https://x.com/DJObleezy" id="topRightLink" target="_blank" rel="noopener noreferrer">Made by @DJO₿leezy</a>
|
||||
|
||||
<h1 class="text-center">
|
||||
<a href="/" style="text-decoration:none; color:inherit;">
|
||||
{% block header %}Ocean.xyz Pool Mining Dashboard v 0.3{% endblock %}
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
{% block last_updated %}
|
||||
<p class="text-center" id="lastUpdated" style="color: #f7931a"><strong>Last Updated:</strong> {{ current_time }}<span id="terminal-cursor"></span></p>
|
||||
{% endblock %}
|
||||
|
||||
{% block navigation %}
|
||||
<div class="navigation-links">
|
||||
<a href="/dashboard" class="nav-link {% block dashboard_active %}{% endblock %}">Dashboard</a>
|
||||
<a href="/workers" class="nav-link {% block workers_active %}{% endblock %}">Workers</a>
|
||||
<a href="/blocks" class="nav-link {% block blocks_active %}{% endblock %}">Blocks</a>
|
||||
<a href="/notifications" class="nav-link {% block notifications_active %}{% endblock %}">
|
||||
Notifications
|
||||
<span id="nav-unread-badge" class="nav-badge"></span>
|
||||
</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<!-- Main content area -->
|
||||
{% block content %}{% endblock %}
|
||||
|
||||
<!-- Hidden Congrats Message -->
|
||||
{% block congrats_message %}
|
||||
<div id="congratsMessage" style="display:none; position: fixed; top: 20px; left: 50%; transform: translateX(-50%); z-index: 1000; background: #f7931a; color: #000; padding: 10px; border-radius: 5px; box-shadow: 0 0 15px rgba(247, 147, 26, 0.7);"></div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<!-- External JavaScript libraries -->
|
||||
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-annotation@1.1.0"></script>
|
||||
|
||||
<!-- Page-specific JavaScript -->
|
||||
{% block javascript %}{% endblock %}
|
||||
|
||||
<!-- Bitcoin Progress Bar -->
|
||||
<script src="/static/js/BitcoinProgressBar.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -1,94 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Blocks - Ocean.xyz Mining Dashboard{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
<link rel="stylesheet" href="/static/css/blocks.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block header %}Blockchain Monitor{% endblock %}
|
||||
|
||||
{% block blocks_active %}active{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<!-- Latest block stats -->
|
||||
<div class="row mb-2 equal-height">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">Latest Block Stats</div>
|
||||
<div class="card-body">
|
||||
<div class="latest-block-stats">
|
||||
<div class="stat-item">
|
||||
<strong>Block Height:</strong>
|
||||
<span id="latest-height" class="metric-value white">Loading...</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<strong>Time:</strong>
|
||||
<span id="latest-time" class="metric-value blue">Loading...</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<strong>Transactions:</strong>
|
||||
<span id="latest-tx-count" class="metric-value white">Loading...</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<strong>Size:</strong>
|
||||
<span id="latest-size" class="metric-value white">Loading...</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<strong>Difficulty:</strong>
|
||||
<span id="latest-difficulty" class="metric-value yellow">Loading...</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<strong>Mining Pool:</strong>
|
||||
<span id="latest-pool" class="metric-value green">Loading...</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<strong>Avg Fee Rate:</strong>
|
||||
<span id="latest-fee-rate" class="metric-value yellow">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Blocks grid -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">Recent Bitcoin Blocks</div>
|
||||
<div class="card-body">
|
||||
<div class="blocks-container">
|
||||
<div id="blocks-grid" class="blocks-grid">
|
||||
<!-- Blocks will be generated here via JavaScript -->
|
||||
<div class="loader">
|
||||
<span class="loader-text">Connecting to mempool.space API<span class="terminal-cursor"></span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Block details modal -->
|
||||
<div id="block-modal" class="block-modal">
|
||||
<div class="block-modal-content">
|
||||
<div class="block-modal-header">
|
||||
<span class="block-modal-title">Block Details</span>
|
||||
<span class="block-modal-close">×</span>
|
||||
</div>
|
||||
<div class="block-modal-body">
|
||||
<div id="block-details">
|
||||
<!-- Block details will be displayed here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
<script src="/static/js/blocks.js"></script>
|
||||
<script src="/static/js/block-animation.js"></script>
|
||||
{% endblock %}
|
@ -1,713 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Ocean.xyz Pool Miner - Initializing...</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=VT323&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/static/css/boot.css">
|
||||
<style>
|
||||
/* Added styles for configuration form */
|
||||
#config-form {
|
||||
display: none;
|
||||
margin-top: 20px;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
border: 1px solid #f7931a;
|
||||
padding: 15px;
|
||||
max-width: 600px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
box-shadow: 0 0 10px rgba(247, 147, 26, 0.5);
|
||||
}
|
||||
|
||||
.config-title {
|
||||
color: #f7931a;
|
||||
font-size: 22px;
|
||||
text-align: center;
|
||||
margin-bottom: 15px;
|
||||
text-shadow: 0 0 8px rgba(247, 147, 26, 0.8);
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
color: #f7931a;
|
||||
}
|
||||
|
||||
.form-group input {
|
||||
width: 100%;
|
||||
background-color: #111;
|
||||
border: 1px solid #f7931a;
|
||||
padding: 8px;
|
||||
color: white;
|
||||
font-family: 'VT323', monospace;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.form-group input:focus {
|
||||
outline: none;
|
||||
box-shadow: 0 0 5px #f7931a;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #f7931a;
|
||||
border: none;
|
||||
color: black;
|
||||
padding: 8px 15px;
|
||||
font-family: 'VT323', monospace;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
min-width: 120px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background-color: #ffa642;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: #333;
|
||||
color: #f7931a;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
/* Make skip button more mobile-friendly */
|
||||
#skip-button {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
z-index: 1000;
|
||||
padding: 12px 20px;
|
||||
font-size: 18px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
#skip-button {
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
padding: 15px 25px;
|
||||
font-size: 20px; /* Larger font size for better tap targets */
|
||||
border-radius: 10px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tooltip styles */
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
.tooltip .tooltip-text {
|
||||
visibility: hidden;
|
||||
width: 200px;
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border: 1px solid #f7931a;
|
||||
padding: 5px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 125%;
|
||||
left: 50%;
|
||||
margin-left: -100px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tooltip:hover .tooltip-text {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Form success/error message */
|
||||
#form-message {
|
||||
margin-top: 10px;
|
||||
padding: 8px;
|
||||
text-align: center;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message-success {
|
||||
background-color: rgba(50, 205, 50, 0.2);
|
||||
border: 1px solid #32CD32;
|
||||
color: #32CD32;
|
||||
}
|
||||
|
||||
.message-error {
|
||||
background-color: rgba(255, 0, 0, 0.2);
|
||||
border: 1px solid #ff0000;
|
||||
color: #ff0000;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<button id="skip-button">SKIP</button>
|
||||
<div id="debug-info"></div>
|
||||
<div id="loading-message">Loading mining data...</div>
|
||||
<div id="bitcoin-logo">
|
||||
██████╗ ████████╗ ██████╗ ██████╗ ███████╗
|
||||
██╔══██╗╚══██╔══╝██╔════╝ ██╔═══██╗██╔════╝
|
||||
██████╔╝ ██║ ██║ ██║ ██║███████╗
|
||||
██╔══██╗ ██║ ██║ ██║ ██║╚════██║
|
||||
██████╔╝ ██║ ╚██████╗ ╚██████╔╝███████║
|
||||
╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝
|
||||
v.21
|
||||
</div>
|
||||
<div id="terminal">
|
||||
<div id="terminal-content">
|
||||
<span id="output"></span><span class="cursor"></span>
|
||||
<span id="prompt-container">
|
||||
<span id="prompt-text">
|
||||
Initialize mining dashboard? [Y/N]:
|
||||
<span class="prompt-cursor"></span>
|
||||
<input type="text" id="user-input" maxlength="1" autocomplete="off" spellcheck="false" autofocus style="font-size: 16px; font-weight: bold;">
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Configuration Form -->
|
||||
<div id="config-form">
|
||||
<div class="config-title">MINING CONFIGURATION</div>
|
||||
<div class="form-group">
|
||||
<label for="wallet-address">
|
||||
Bitcoin Wallet Address
|
||||
<span class="tooltip">
|
||||
?
|
||||
<span class="tooltip-text">Your Ocean.xyz pool mining address</span>
|
||||
</span>
|
||||
</label>
|
||||
<input type="text" id="wallet-address" placeholder="bc1..." value="">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="power-cost">
|
||||
Power Cost ($/kWh)
|
||||
<span class="tooltip">
|
||||
?
|
||||
<span class="tooltip-text">Your electricity cost per kilowatt-hour</span>
|
||||
</span>
|
||||
</label>
|
||||
<input type="number" id="power-cost" step="0.01" min="0" placeholder="0.12" value="">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="power-usage">
|
||||
Power Usage (Watts)
|
||||
<span class="tooltip">
|
||||
?
|
||||
<span class="tooltip-text">Total power consumption of your mining equipment</span>
|
||||
</span>
|
||||
</label>
|
||||
<input type="number" id="power-usage" step="1" min="0" placeholder="3450" value="">
|
||||
</div>
|
||||
<div id="form-message"></div>
|
||||
<div class="form-actions">
|
||||
<button class="btn btn-secondary" id="use-defaults">Use Defaults</button>
|
||||
<button class="btn" id="save-config">Save & Continue</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Debug logging
|
||||
function updateDebug(message) {
|
||||
document.getElementById('debug-info').textContent = message;
|
||||
console.log(message);
|
||||
}
|
||||
|
||||
// Format numbers with commas
|
||||
function numberWithCommas(x) {
|
||||
if (x == null) return "N/A";
|
||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||
}
|
||||
|
||||
// Global variables
|
||||
let bootMessages = [];
|
||||
let dashboardData = null;
|
||||
let outputElement = document.getElementById('output');
|
||||
const bitcoinLogo = document.getElementById('bitcoin-logo');
|
||||
const skipButton = document.getElementById('skip-button');
|
||||
const loadingMessage = document.getElementById('loading-message');
|
||||
const promptContainer = document.getElementById('prompt-container');
|
||||
const userInput = document.getElementById('user-input');
|
||||
const configForm = document.getElementById('config-form');
|
||||
let messageIndex = 0;
|
||||
let timeoutId = null;
|
||||
let waitingForUserInput = false;
|
||||
let bootComplete = false;
|
||||
let configLoaded = false;
|
||||
let currentConfig = {
|
||||
wallet: "yourwallethere",
|
||||
power_cost: 0.0,
|
||||
power_usage: 0.0
|
||||
};
|
||||
|
||||
// Replace the current loadConfig function with this improved version
|
||||
function loadConfig() {
|
||||
// Always make a fresh request to get the latest config
|
||||
fetch('/api/config?nocache=' + new Date().getTime()) // Add cache-busting parameter
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to load configuration: ' + response.statusText);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
console.log("Loaded configuration:", data);
|
||||
currentConfig = data;
|
||||
|
||||
// After loading, always update the form fields with the latest values
|
||||
document.getElementById('wallet-address').value = currentConfig.wallet || "";
|
||||
document.getElementById('power-cost').value = currentConfig.power_cost || "";
|
||||
document.getElementById('power-usage').value = currentConfig.power_usage || "";
|
||||
configLoaded = true;
|
||||
})
|
||||
.catch(err => {
|
||||
console.error("Error loading config:", err);
|
||||
// Use default values if loading fails
|
||||
currentConfig = {
|
||||
wallet: "yourwallethere",
|
||||
power_cost: 0.0,
|
||||
power_usage: 0.0
|
||||
};
|
||||
|
||||
// Still update the form with default values
|
||||
document.getElementById('wallet-address').value = currentConfig.wallet || "";
|
||||
document.getElementById('power-cost').value = currentConfig.power_cost || "";
|
||||
document.getElementById('power-usage').value = currentConfig.power_usage || "";
|
||||
});
|
||||
}
|
||||
|
||||
// Also update the save button event handler to reload the config after saving
|
||||
document.getElementById('save-config').addEventListener('click', function () {
|
||||
const messageElement = document.getElementById('form-message');
|
||||
messageElement.style.display = 'block';
|
||||
|
||||
saveConfig()
|
||||
.then(data => {
|
||||
console.log("Configuration saved:", data);
|
||||
messageElement.textContent = "Configuration saved successfully!";
|
||||
messageElement.className = "message-success";
|
||||
|
||||
// Update currentConfig with the saved values
|
||||
currentConfig = data.config || data;
|
||||
|
||||
setTimeout(redirectToDashboard, 1000);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error saving configuration:", error);
|
||||
messageElement.textContent = "Error saving configuration. Please try again.";
|
||||
messageElement.className = "message-error";
|
||||
});
|
||||
});
|
||||
|
||||
// Save configuration
|
||||
function saveConfig() {
|
||||
const wallet = document.getElementById('wallet-address').value.trim();
|
||||
const powerCost = parseFloat(document.getElementById('power-cost').value) || 0;
|
||||
const powerUsage = parseFloat(document.getElementById('power-usage').value) || 0;
|
||||
|
||||
const updatedConfig = {
|
||||
wallet: wallet || currentConfig.wallet,
|
||||
power_cost: powerCost,
|
||||
power_usage: powerUsage
|
||||
};
|
||||
|
||||
return fetch('/api/config', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(updatedConfig)
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to save configuration');
|
||||
}
|
||||
return response.json();
|
||||
});
|
||||
}
|
||||
|
||||
// Safety timeout: redirect after 60 seconds if boot not complete
|
||||
window.addEventListener('load', function () {
|
||||
setTimeout(function () {
|
||||
if (!bootComplete && !waitingForUserInput) {
|
||||
console.warn("Safety timeout reached - redirecting to dashboard");
|
||||
redirectToDashboard();
|
||||
}
|
||||
}, 60000);
|
||||
});
|
||||
|
||||
// Configuration form event listeners
|
||||
document.getElementById('save-config').addEventListener('click', function () {
|
||||
const messageElement = document.getElementById('form-message');
|
||||
messageElement.style.display = 'block';
|
||||
|
||||
saveConfig()
|
||||
.then(data => {
|
||||
console.log("Configuration saved:", data);
|
||||
messageElement.textContent = "Configuration saved successfully!";
|
||||
messageElement.className = "message-success";
|
||||
setTimeout(redirectToDashboard, 1000);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error("Error saving configuration:", error);
|
||||
messageElement.textContent = "Error saving configuration. Please try again.";
|
||||
messageElement.className = "message-error";
|
||||
});
|
||||
});
|
||||
|
||||
// Replace the current Use Defaults button event listener with this fixed version
|
||||
document.getElementById('use-defaults').addEventListener('click', function () {
|
||||
console.log("Use Defaults button clicked");
|
||||
|
||||
// Always use the hardcoded default values, not the currentConfig
|
||||
const defaultWallet = "yourwallethere";
|
||||
const defaultPowerCost = 0.0;
|
||||
const defaultPowerUsage = 0.0;
|
||||
|
||||
console.log("Setting to default values");
|
||||
|
||||
// Apply the hardcoded default values to the form fields
|
||||
document.getElementById('wallet-address').value = defaultWallet;
|
||||
document.getElementById('power-cost').value = defaultPowerCost;
|
||||
document.getElementById('power-usage').value = defaultPowerUsage;
|
||||
|
||||
// Show visual feedback that the button was clicked
|
||||
const btn = document.getElementById('use-defaults');
|
||||
const originalText = btn.textContent;
|
||||
btn.textContent = "Defaults Applied";
|
||||
btn.style.backgroundColor = "#32CD32";
|
||||
|
||||
// Reset the button after a short delay
|
||||
setTimeout(function () {
|
||||
btn.textContent = originalText;
|
||||
btn.style.backgroundColor = "";
|
||||
}, 1500);
|
||||
});
|
||||
|
||||
// Redirect to dashboard
|
||||
function redirectToDashboard() {
|
||||
updateDebug("Boot sequence complete, redirecting...");
|
||||
const baseUrl = window.location.origin;
|
||||
window.location.href = baseUrl + "/dashboard";
|
||||
}
|
||||
|
||||
// Fade in Bitcoin logo
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
setTimeout(function () {
|
||||
bitcoinLogo.style.visibility = 'visible';
|
||||
setTimeout(function () {
|
||||
bitcoinLogo.style.opacity = '1';
|
||||
}, 100);
|
||||
}, 500);
|
||||
|
||||
// Load configuration
|
||||
loadConfig();
|
||||
});
|
||||
|
||||
// Post-confirmation messages with retro typing effect
|
||||
function showPostConfirmationMessages(response) {
|
||||
try {
|
||||
outputElement = document.getElementById('output');
|
||||
if (!outputElement) {
|
||||
setTimeout(redirectToDashboard, 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
// Configuration form will be shown after boot sequence
|
||||
if (response.toUpperCase() === 'Y') {
|
||||
const yesMessages = [
|
||||
{ text: "INITIALIZING DASHBOARD...\n", html: true, delay: 400 },
|
||||
{ text: "Connecting to real-time data feeds...", speed: 20, delay: 300 },
|
||||
{ text: "<span class='green'>CONNECTED</span>\n", html: true, delay: 400 },
|
||||
{ text: "Loading blockchain validators...", speed: 15, delay: 300 },
|
||||
{ text: "<span class='green'>COMPLETE</span>\n", html: true, delay: 400 },
|
||||
{ text: "Starting TX fee calculation module...", speed: 15, delay: 400 },
|
||||
{ text: "<span class='green'>ACTIVE</span>\n", html: true, delay: 400 },
|
||||
{ text: "Verifying BTC-USD exchange rates...", speed: 15, delay: 200 },
|
||||
{ text: "<span class='green'>CURRENT RATE CONFIRMED</span>\n", html: true, delay: 300 },
|
||||
{ text: "Calibrating hashrate telemetry...", speed: 15, delay: 200 },
|
||||
{ text: "<span class='green'>CALIBRATED</span>\n", html: true, delay: 200 },
|
||||
{ text: "Loading mining configuration...", speed: 15, delay: 200 },
|
||||
{ text: "<span class='green'>LOADED</span>\n", html: true, delay: 300 },
|
||||
{ text: "Preparing configuration interface...", speed: 15, delay: 800 },
|
||||
{ text: "<span class='green'>READY</span>\n", html: true, delay: 500 },
|
||||
{ text: "\nPlease configure your mining setup or use the default values:\n", html: true, delay: 800, showConfigForm: true }
|
||||
];
|
||||
|
||||
let msgIndex = 0;
|
||||
function processNextMessage() {
|
||||
if (msgIndex >= yesMessages.length) {
|
||||
return;
|
||||
}
|
||||
const currentMessage = yesMessages[msgIndex];
|
||||
|
||||
if (currentMessage.showConfigForm) {
|
||||
msgIndex++;
|
||||
// Show configuration form
|
||||
document.getElementById('config-form').style.display = 'block';
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentMessage.html) {
|
||||
outputElement.innerHTML += currentMessage.text;
|
||||
msgIndex++;
|
||||
setTimeout(processNextMessage, currentMessage.delay || 300);
|
||||
} else {
|
||||
let charIndex = 0;
|
||||
function typeCharacter() {
|
||||
if (charIndex < currentMessage.text.length) {
|
||||
outputElement.innerHTML += currentMessage.text.charAt(charIndex);
|
||||
charIndex++;
|
||||
setTimeout(typeCharacter, currentMessage.speed || 20);
|
||||
} else {
|
||||
msgIndex++;
|
||||
setTimeout(processNextMessage, currentMessage.delay || 300);
|
||||
}
|
||||
}
|
||||
typeCharacter();
|
||||
}
|
||||
}
|
||||
setTimeout(processNextMessage, 500);
|
||||
} else {
|
||||
// If user selects 'N', just redirect to dashboard
|
||||
outputElement.innerHTML += "N\n\nDASHBOARD INITIALIZATION ABORTED.\n";
|
||||
outputElement.innerHTML += "\nUsing default configuration values.\n";
|
||||
setTimeout(redirectToDashboard, 2000);
|
||||
}
|
||||
} catch (err) {
|
||||
setTimeout(redirectToDashboard, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Y/N prompt input
|
||||
userInput.addEventListener('keydown', function (e) {
|
||||
if (waitingForUserInput && e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
const response = userInput.value.toUpperCase();
|
||||
|
||||
if (response === 'Y' || response === 'N') {
|
||||
promptContainer.style.display = 'none';
|
||||
waitingForUserInput = false;
|
||||
outputElement.innerHTML += response + "\n";
|
||||
userInput.value = '';
|
||||
showPostConfirmationMessages(response);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Show the prompt
|
||||
function showUserPrompt() {
|
||||
promptContainer.style.display = 'inline';
|
||||
waitingForUserInput = true;
|
||||
document.querySelector('.cursor').style.display = 'none';
|
||||
userInput.focus();
|
||||
}
|
||||
|
||||
// Disable truncation so all text is visible
|
||||
function manageTerminalContent() { }
|
||||
|
||||
// Retro typing effect for boot messages
|
||||
function typeBootMessages() {
|
||||
try {
|
||||
if (!outputElement) {
|
||||
outputElement = document.getElementById('output');
|
||||
if (!outputElement) {
|
||||
skipButton.click();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (messageIndex >= bootMessages.length) { return; }
|
||||
const currentMessage = bootMessages[messageIndex];
|
||||
|
||||
if (currentMessage.showPrompt) {
|
||||
messageIndex++;
|
||||
showUserPrompt();
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentMessage.html) {
|
||||
outputElement.innerHTML += currentMessage.text;
|
||||
messageIndex++;
|
||||
timeoutId = setTimeout(typeBootMessages, currentMessage.delay || 300);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!currentMessage.typingIndex) { currentMessage.typingIndex = 0; }
|
||||
if (currentMessage.typingIndex < currentMessage.text.length) {
|
||||
outputElement.innerHTML += currentMessage.text.charAt(currentMessage.typingIndex);
|
||||
currentMessage.typingIndex++;
|
||||
timeoutId = setTimeout(typeBootMessages, currentMessage.speed || 15);
|
||||
} else {
|
||||
messageIndex++;
|
||||
timeoutId = setTimeout(typeBootMessages, currentMessage.delay || 300);
|
||||
}
|
||||
} catch (err) {
|
||||
messageIndex++;
|
||||
timeoutId = setTimeout(typeBootMessages, 500);
|
||||
}
|
||||
}
|
||||
|
||||
// Skip button: reveal configuration form only
|
||||
skipButton.addEventListener('click', function () {
|
||||
clearTimeout(timeoutId);
|
||||
// Optionally, clear boot messages or hide elements related to boot sequence
|
||||
outputElement.innerHTML = "";
|
||||
// Hide any loading or prompt messages
|
||||
loadingMessage.style.display = 'none';
|
||||
promptContainer.style.display = 'none';
|
||||
// Show the configuration form
|
||||
configForm.style.display = 'block';
|
||||
});
|
||||
|
||||
// Start the typing animation (hides loading message)
|
||||
function startTyping() {
|
||||
loadingMessage.style.display = 'none';
|
||||
setTimeout(typeBootMessages, 150);
|
||||
}
|
||||
|
||||
// Fallback messages (used immediately)
|
||||
function setupFallbackMessages() {
|
||||
bootMessages = [
|
||||
{ text: "BITCOIN OS - MINING SYSTEM - v21.000.000\n", speed: 25, delay: 300 },
|
||||
{ text: "Copyright (c) 2009-2025 Satoshi Nakamoto\n", speed: 20, delay: 250 },
|
||||
{ text: "All rights reserved.\n\n", speed: 25, delay: 300 },
|
||||
{ text: "INITIALIZING SYSTEM...\n", speed: 25, delay: 300 },
|
||||
{ text: "HARDWARE: ", speed: 25, delay: 100 },
|
||||
{ text: "<span class='green'>OK</span>\n", html: true, delay: 300 },
|
||||
{ text: "NETWORK: ", speed: 25, delay: 100 },
|
||||
{ text: "<span class='green'>OK</span>\n", html: true, delay: 300 },
|
||||
{ text: "BLOCKCHAIN: ", speed: 25, delay: 100 },
|
||||
{ text: "<span class='green'>SYNCHRONIZED</span>\n", html: true, delay: 300 },
|
||||
{ text: "MINING RIG: ", speed: 25, delay: 100 },
|
||||
{ text: "<span class='green'>ONLINE</span>\n", html: true, delay: 300 },
|
||||
{ text: "\nSystem ready. ", speed: 25, delay: 400 },
|
||||
{ showPrompt: true, delay: 0 }
|
||||
];
|
||||
startTyping();
|
||||
}
|
||||
|
||||
// Initialize with fallback, then try live data
|
||||
setupFallbackMessages();
|
||||
updateDebug("Fetching dashboard data...");
|
||||
fetch('/api/metrics')
|
||||
.then(response => {
|
||||
if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); }
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
dashboardData = data;
|
||||
clearTimeout(timeoutId);
|
||||
messageIndex = 0;
|
||||
outputElement = document.getElementById('output');
|
||||
outputElement.innerHTML = "";
|
||||
bootMessages = [
|
||||
{ text: "BITCOIN OS - MINING CONTROL SYSTEM - v21.000.000\n", speed: 25, delay: 300 },
|
||||
{ text: "Copyright (c) 2009-2025 Satoshi Nakamoto & The Bitcoin Core Developers\n", speed: 20, delay: 250 },
|
||||
{ text: "All rights reserved.\n\n", speed: 25, delay: 300 },
|
||||
{ text: "INITIALIZING SHA-256 MINING SUBSYSTEMS...\n", speed: 25, delay: 400 },
|
||||
{ text: "ASIC CLUSTER STATUS: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='green'>ONLINE</span>\n", html: true, delay: 300 },
|
||||
{ text: "CHIP TEMPERATURE: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='green'>62°C - WITHIN OPTIMAL RANGE</span>\n", html: true, delay: 300 },
|
||||
{ text: "COOLING SYSTEMS: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='green'>OPERATIONAL</span>\n", html: true, delay: 300 },
|
||||
{ text: "POWER SUPPLY HEALTH: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='green'>98.7% - NOMINAL</span>\n", html: true, delay: 300 },
|
||||
{ text: "\nCONNECTING TO BITCOIN NETWORK...\n", speed: 20, delay: 400 },
|
||||
{ text: "BLOCKCHAIN SYNC STATUS: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='green'>SYNCHRONIZED</span>\n", html: true, delay: 300 },
|
||||
{ text: "DIFFICULTY ADJUSTMENT: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='yellow'>CALCULATED</span>\n", html: true, delay: 300 },
|
||||
{ text: "MEMPOOL MONITORING: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='green'>ACTIVE</span>\n", html: true, delay: 300 },
|
||||
{ text: "\nESTABLISHING POOL CONNECTION...\n", speed: 20, delay: 300 },
|
||||
{ text: "CONNECTING TO OCEAN.XYZ...\n", speed: 20, delay: 300 },
|
||||
{ text: "STRATUM PROTOCOL v2: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='green'>INITIALIZED</span>\n", html: true, delay: 300 },
|
||||
{ text: "POOL HASHRATE: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='green'>VERIFIED</span>\n", html: true, delay: 300 },
|
||||
{ text: "WORKER AUTHENTICATION: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='green'>SUCCESSFUL</span>\n", html: true, delay: 300 },
|
||||
{ text: "\nINITIALIZING METRICS COLLECTORS...\n", speed: 20, delay: 300 },
|
||||
{ text: "HASHRATE MONITOR: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='green'>ACTIVE</span>\n", html: true, delay: 300 },
|
||||
{ text: "EARNINGS CALCULATOR: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='green'>CALIBRATED</span>\n", html: true, delay: 300 },
|
||||
{ text: "POWER USAGE TRACKING: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='green'>ENABLED</span>\n", html: true, delay: 300 },
|
||||
{ text: "PAYOUT THRESHOLD MONITOR: ", speed: 15, delay: 100 },
|
||||
{ text: "<span class='green'>ACTIVE</span>\n", html: true, delay: 300 },
|
||||
{ text: "\nCURRENT NETWORK METRICS DETECTED\n", speed: 20, delay: 300 },
|
||||
{ text: "BTC PRICE: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='yellow'>$" + numberWithCommas((data.btc_price || 0).toFixed(2)) + "</span>\n", html: true, delay: 300 },
|
||||
{ text: "NETWORK DIFFICULTY: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='white'>" + numberWithCommas(Math.round(data.difficulty || 0)) + "</span>\n", html: true, delay: 300 },
|
||||
{ text: "NETWORK HASHRATE: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='white'>" + (data.network_hashrate ? numberWithCommas(Math.round(data.network_hashrate)) : "N/A") + " EH/s</span>\n", html: true, delay: 300 },
|
||||
{ text: "BLOCK HEIGHT: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='white'>" + numberWithCommas(data.block_number || "N/A") + "</span>\n", html: true, delay: 300 },
|
||||
{ text: "\nMINER PERFORMANCE DATA\n", speed: 20, delay: 300 },
|
||||
{ text: "CURRENT HASHRATE: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='yellow'>" + (data.hashrate_60sec || "N/A") + " " + (data.hashrate_60sec_unit || "TH/s") + "</span>\n", html: true, delay: 300 },
|
||||
{ text: "24HR AVG HASHRATE: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='yellow'>" + (data.hashrate_24hr || "N/A") + " " + (data.hashrate_24hr_unit || "TH/s") + "</span>\n", html: true, delay: 300 },
|
||||
{ text: "ACTIVE WORKERS: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='yellow'>" + (data.workers_hashing || "0") + "</span>\n", html: true, delay: 300 },
|
||||
{ text: "\nFINANCIAL CALCULATIONS\n", speed: 20, delay: 300 },
|
||||
{ text: "DAILY MINING REVENUE: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='green'>$" + numberWithCommas((data.daily_revenue || 0).toFixed(2)) + "</span>\n", html: true, delay: 300 },
|
||||
{ text: "DAILY POWER COST: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='red'>$" + numberWithCommas((data.daily_power_cost || 0).toFixed(2)) + "</span>\n", html: true, delay: 300 },
|
||||
{ text: "DAILY PROFIT: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='green'>$" + numberWithCommas((data.daily_profit_usd || 0).toFixed(2)) + "</span>\n", html: true, delay: 300 },
|
||||
{ text: "PROJECTED MONTHLY PROFIT: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='green'>$" + numberWithCommas((data.monthly_profit_usd || 0).toFixed(2)) + "</span>\n", html: true, delay: 300 },
|
||||
{ text: "DAILY SATOSHI YIELD: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='yellow'>" + numberWithCommas(data.daily_mined_sats || 0) + " sats</span>\n", html: true, delay: 300 },
|
||||
{ text: "UNPAID EARNINGS: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='green'>" + (data.unpaid_earnings || "0") + " BTC</span>\n", html: true, delay: 300 },
|
||||
{ text: "ESTIMATED TIME TO PAYOUT: ", speed: 20, delay: 100 },
|
||||
{ text: "<span class='yellow'>" + (data.est_time_to_payout || "Unknown") + "</span>\n", html: true, delay: 300 },
|
||||
{ text: "\n", speed: 25, delay: 100 },
|
||||
{ text: "<span class='green'>ALL MINING PROCESSES OPERATIONAL</span>\n", html: true, delay: 400 },
|
||||
{ text: "\nInitialize mining dashboard? ", speed: 25, delay: 400 },
|
||||
{ showPrompt: true, delay: 0 }
|
||||
];
|
||||
startTyping();
|
||||
})
|
||||
.catch(error => {
|
||||
updateDebug(`Error fetching dashboard data: ${error.message}`);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,363 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Ocean.xyz Pool Mining Dashboard v 0.3{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
<link rel="stylesheet" href="/static/css/dashboard.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block dashboard_active %}active{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Graph Container -->
|
||||
<div id="graphContainer" class="mb-2">
|
||||
<canvas id="trendGraph" style="width: 100%; height: 100%; position: relative; z-index: 2;"></canvas>
|
||||
</div>
|
||||
|
||||
<!-- Miner Status -->
|
||||
<div class="row mb-2 equal-height">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">Miner Status</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<strong>Status:</strong>
|
||||
<span id="miner_status" class="metric-value">
|
||||
{% if metrics and metrics.workers_hashing and metrics.workers_hashing > 0 %}
|
||||
<span class="status-green">ONLINE</span> <span class="online-dot"></span>
|
||||
{% else %}
|
||||
<span class="status-red">OFFLINE</span> <span class="offline-dot"></span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Workers Hashing:</strong>
|
||||
<span id="workers_hashing" class="metric-value">{{ metrics.workers_hashing or 0 }}</span>
|
||||
<span id="indicator_workers_hashing"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Last Share:</strong>
|
||||
<span id="last_share" class="metric-value">{{ metrics.total_last_share or "N/A" }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pool Hashrates and Bitcoin Network Stats -->
|
||||
<div class="row equal-height">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">Pool Hashrates</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<strong>Pool Total Hashrate:</strong>
|
||||
<span id="pool_total_hashrate" class="metric-value white">
|
||||
{% if metrics and metrics.pool_total_hashrate and metrics.pool_total_hashrate_unit %}
|
||||
{{ metrics.pool_total_hashrate }} {{ metrics.pool_total_hashrate_unit[:-2]|upper ~ metrics.pool_total_hashrate_unit[-2:] }}
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_pool_total_hashrate"></span>
|
||||
</p>
|
||||
<hr>
|
||||
<p>
|
||||
<strong>24hr Avg Hashrate:</strong>
|
||||
<span id="hashrate_24hr" class="metric-value white">
|
||||
{% if metrics and metrics.hashrate_24hr %}
|
||||
{{ metrics.hashrate_24hr }}
|
||||
{% if metrics.hashrate_24hr_unit %}
|
||||
{{ metrics.hashrate_24hr_unit[:-2]|upper ~ metrics.hashrate_24hr_unit[-2:] }}
|
||||
{% else %}
|
||||
TH/s
|
||||
{% endif %}
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_hashrate_24hr"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>3hr Avg Hashrate:</strong>
|
||||
<span id="hashrate_3hr" class="metric-value white">
|
||||
{% if metrics and metrics.hashrate_3hr %}
|
||||
{{ metrics.hashrate_3hr }}
|
||||
{% if metrics.hashrate_3hr_unit %}
|
||||
{{ metrics.hashrate_3hr_unit[:-2]|upper ~ metrics.hashrate_3hr_unit[-2:] }}
|
||||
{% else %}
|
||||
TH/s
|
||||
{% endif %}
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_hashrate_3hr"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>10min Avg Hashrate:</strong>
|
||||
<span id="hashrate_10min" class="metric-value white">
|
||||
{% if metrics and metrics.hashrate_10min %}
|
||||
{{ metrics.hashrate_10min }}
|
||||
{% if metrics.hashrate_10min_unit %}
|
||||
{{ metrics.hashrate_10min_unit[:-2]|upper ~ metrics.hashrate_10min_unit[-2:] }}
|
||||
{% else %}
|
||||
TH/s
|
||||
{% endif %}
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_hashrate_10min"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>60sec Avg Hashrate:</strong>
|
||||
<span id="hashrate_60sec" class="metric-value white">
|
||||
{% if metrics and metrics.hashrate_60sec %}
|
||||
{{ metrics.hashrate_60sec }}
|
||||
{% if metrics.hashrate_60sec_unit %}
|
||||
{{ metrics.hashrate_60sec_unit[:-2]|upper ~ metrics.hashrate_60sec_unit[-2:] }}
|
||||
{% else %}
|
||||
TH/s
|
||||
{% endif %}
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_hashrate_60sec"></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">Bitcoin Network Stats</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<strong>Block Number:</strong>
|
||||
<span id="block_number" class="metric-value white">
|
||||
{% if metrics and metrics.block_number %}
|
||||
{{ metrics.block_number|commafy }}
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_block_number"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>BTC Price:</strong>
|
||||
<span id="btc_price" class="metric-value yellow">
|
||||
{% if metrics and metrics.btc_price %}
|
||||
${{ "%.2f"|format(metrics.btc_price) }}
|
||||
{% else %}
|
||||
$0.00
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_btc_price"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Network Hashrate:</strong>
|
||||
<span id="network_hashrate" class="metric-value white">
|
||||
{% if metrics and metrics.network_hashrate %}
|
||||
{{ metrics.network_hashrate|round|commafy }} EH/s
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_network_hashrate"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Difficulty:</strong>
|
||||
<span id="difficulty" class="metric-value white">
|
||||
{% if metrics and metrics.difficulty %}
|
||||
{{ metrics.difficulty|round|commafy }}
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_difficulty"></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Satoshi and USD Metrics -->
|
||||
<div class="row equal-height">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">Satoshi Metrics</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<strong>Daily Mined (Net):</strong>
|
||||
<span id="daily_mined_sats" class="metric-value yellow">
|
||||
{% if metrics and metrics.daily_mined_sats %}
|
||||
{{ metrics.daily_mined_sats|commafy }} sats
|
||||
{% else %}
|
||||
0 sats
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_daily_mined_sats"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Monthly Mined (Net):</strong>
|
||||
<span id="monthly_mined_sats" class="metric-value yellow">
|
||||
{% if metrics and metrics.monthly_mined_sats %}
|
||||
{{ metrics.monthly_mined_sats|commafy }} sats
|
||||
{% else %}
|
||||
0 sats
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_monthly_mined_sats"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Est. Earnings/Day:</strong>
|
||||
<span id="estimated_earnings_per_day_sats" class="metric-value yellow">
|
||||
{% if metrics and metrics.estimated_earnings_per_day_sats %}
|
||||
{{ metrics.estimated_earnings_per_day_sats|commafy }} sats
|
||||
{% else %}
|
||||
0 sats
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_estimated_earnings_per_day_sats"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Est. Earnings/Block:</strong>
|
||||
<span id="estimated_earnings_next_block_sats" class="metric-value yellow">
|
||||
{% if metrics and metrics.estimated_earnings_next_block_sats %}
|
||||
{{ metrics.estimated_earnings_next_block_sats|commafy }} sats
|
||||
{% else %}
|
||||
0 sats
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_estimated_earnings_next_block_sats"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Est. Rewards in Window:</strong>
|
||||
<span id="estimated_rewards_in_window_sats" class="metric-value yellow">
|
||||
{% if metrics and metrics.estimated_rewards_in_window_sats %}
|
||||
{{ metrics.estimated_rewards_in_window_sats|commafy }} sats
|
||||
{% else %}
|
||||
0 sats
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_estimated_rewards_in_window_sats"></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">USD Metrics</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<strong>Daily Revenue:</strong>
|
||||
<span id="daily_revenue" class="metric-value green">
|
||||
{% if metrics and metrics.daily_revenue is defined and metrics.daily_revenue is not none %}
|
||||
${{ "%.2f"|format(metrics.daily_revenue) }}
|
||||
{% else %}
|
||||
$0.00
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_daily_revenue"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Daily Power Cost:</strong>
|
||||
<span id="daily_power_cost" class="metric-value red">
|
||||
{% if metrics and metrics.daily_power_cost is defined and metrics.daily_power_cost is not none %}
|
||||
${{ "%.2f"|format(metrics.daily_power_cost) }}
|
||||
{% else %}
|
||||
$0.00
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_daily_power_cost"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Daily Profit (USD):</strong>
|
||||
<span id="daily_profit_usd" class="metric-value green">
|
||||
{% if metrics and metrics.daily_profit_usd is defined and metrics.daily_profit_usd is not none %}
|
||||
${{ "%.2f"|format(metrics.daily_profit_usd) }}
|
||||
{% else %}
|
||||
$0.00
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_daily_profit_usd"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Monthly Profit (USD):</strong>
|
||||
<span id="monthly_profit_usd" class="metric-value green">
|
||||
{% if metrics and metrics.monthly_profit_usd is defined and metrics.monthly_profit_usd is not none %}
|
||||
${{ "%.2f"|format(metrics.monthly_profit_usd) }}
|
||||
{% else %}
|
||||
$0.00
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_monthly_profit_usd"></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Payout & Misc -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card" id="payoutMiscCard">
|
||||
<div class="card-header">Payout & Misc</div>
|
||||
<div class="card-body">
|
||||
<p>
|
||||
<strong>Unpaid Earnings:</strong>
|
||||
<span id="unpaid_earnings" class="metric-value green">
|
||||
{% if metrics and metrics.unpaid_earnings %}
|
||||
{{ metrics.unpaid_earnings }} BTC
|
||||
{% else %}
|
||||
0 BTC
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_unpaid_earnings"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Last Block:</strong>
|
||||
<span id="last_block_height" class="metric-value white">
|
||||
{{ metrics.last_block_height if metrics and metrics.last_block_height else "N/A" }}
|
||||
</span>
|
||||
—
|
||||
<span id="last_block_time" class="metric-value blue">
|
||||
{{ metrics.last_block_time if metrics and metrics.last_block_time else "N/A" }}
|
||||
</span>
|
||||
—
|
||||
<span class="green">
|
||||
{% if metrics and metrics.last_block_earnings %}
|
||||
+{{ metrics.last_block_earnings|int|commafy }} sats
|
||||
{% else %}
|
||||
+0 sats
|
||||
{% endif %}
|
||||
</span>
|
||||
<span id="indicator_last_block"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Est. Time to Payout:</strong>
|
||||
<span id="est_time_to_payout" class="metric-value yellow">
|
||||
{{ metrics.est_time_to_payout if metrics and metrics.est_time_to_payout else "N/A" }}
|
||||
</span>
|
||||
<span id="indicator_est_time_to_payout"></span>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Blocks Found:</strong>
|
||||
<span id="blocks_found" class="metric-value white">
|
||||
{{ metrics.blocks_found if metrics and metrics.blocks_found else "0" }}
|
||||
</span>
|
||||
<span id="indicator_blocks_found"></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
<!-- External JavaScript file with our application logic -->
|
||||
<script src="/static/js/main.js"></script>
|
||||
{% endblock %}
|
@ -1,22 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Error - Mining Dashboard</title>
|
||||
<!-- Include both Orbitron and VT323 fonts -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=VT323&display=swap" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/static/css/error.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="error-container">
|
||||
<h1>ERROR</h1>
|
||||
<div class="error-code">CODE: SYS_EXCEPTION_0x45</div>
|
||||
<p>{{ message }}<span class="terminal-cursor"></span></p>
|
||||
<a href="/" class="btn btn-primary">Return to Dashboard</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,94 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Notifications - Ocean.xyz Mining Dashboard{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
<link rel="stylesheet" href="/static/css/notifications.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block header %}Notification Center{% endblock %}
|
||||
|
||||
{% block notifications_active %}active{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Notification Controls -->
|
||||
<div class="row mb-2">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">Notification Controls</div>
|
||||
<div class="card-body">
|
||||
<div class="notification-controls">
|
||||
<div class="filter-buttons">
|
||||
<button class="filter-button active" data-filter="all">All</button>
|
||||
<button class="filter-button" data-filter="hashrate">Hashrate</button>
|
||||
<button class="filter-button" data-filter="block">Blocks</button>
|
||||
<button class="filter-button" data-filter="worker">Workers</button>
|
||||
<button class="filter-button" data-filter="earnings">Earnings</button>
|
||||
<button class="filter-button" data-filter="system">System</button>
|
||||
</div>
|
||||
<div class="notification-actions">
|
||||
<button id="mark-all-read" class="action-button">Mark All as Read</button>
|
||||
<button id="clear-read" class="action-button">Clear Read Notifications</button>
|
||||
<button id="clear-all" class="action-button danger">Clear All</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notifications List -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<span>Notifications</span>
|
||||
<span id="unread-badge" class="unread-badge">0</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="notifications-container">
|
||||
<!-- Notifications will be populated here by JavaScript -->
|
||||
<div class="loading-message">Loading notifications<span class="terminal-cursor"></span></div>
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
<div class="pagination-controls">
|
||||
<button id="load-more" class="load-more-button">Load More</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Empty State Template (hidden) -->
|
||||
<div id="empty-template" style="display:none;">
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-bell-slash"></i>
|
||||
<p>No notifications to display</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notification Template (hidden) -->
|
||||
<div id="notification-template" style="display:none;">
|
||||
<div class="notification-item" data-id="">
|
||||
<div class="notification-icon">
|
||||
<i class="fas"></i>
|
||||
</div>
|
||||
<div class="notification-content">
|
||||
<div class="notification-message"></div>
|
||||
<div class="notification-meta">
|
||||
<span class="notification-time"></span>
|
||||
<span class="notification-category"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="notification-actions">
|
||||
<button class="mark-read-button"><i class="fas fa-check"></i></button>
|
||||
<button class="delete-button"><i class="fas fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
<script src="/static/js/notifications.js"></script>
|
||||
{% endblock %}
|
@ -1,109 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Workers Overview - Ocean.xyz Pool Mining Dashboard{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
<link rel="stylesheet" href="/static/css/workers.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block header %}Workers Overview{% endblock %}
|
||||
|
||||
{% block workers_active %}active{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Summary statistics -->
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-header">Miner Summary</div>
|
||||
<div class="card-body">
|
||||
<div class="summary-stats">
|
||||
<div class="summary-stat">
|
||||
<div class="worker-ring" style="--online-percent: {{ workers_online / workers_total if workers_total > 0 else 0 }}">
|
||||
<div class="worker-ring-inner">
|
||||
<span id="workers-count">{{ workers_total }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="summary-stat-label">Workers</div>
|
||||
<div>
|
||||
<span class="green-glow" id="workers-online">{{ workers_online }}</span> /
|
||||
<span class="red-glow" id="workers-offline">{{ workers_offline }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="summary-stat">
|
||||
<div class="summary-stat-value white-glow" id="total-hashrate">
|
||||
{% if total_hashrate is defined %}
|
||||
{{ "%.1f"|format(total_hashrate) }} {{ hashrate_unit }}
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="summary-stat-label">Total Hashrate</div>
|
||||
<div class="mini-chart">
|
||||
<canvas id="total-hashrate-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="summary-stat">
|
||||
<div class="summary-stat-value green-glow" id="total-earnings">
|
||||
{% if total_earnings is defined %}
|
||||
{{ "%.8f"|format(total_earnings) }} BTC
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="summary-stat-label">Unpaid Earnings</div>
|
||||
</div>
|
||||
|
||||
<div class="summary-stat">
|
||||
<div class="summary-stat-value yellow-glow" id="daily-sats">
|
||||
{% if daily_sats is defined %}
|
||||
{{ daily_sats|commafy }} sats
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="summary-stat-label">Daily Sats</div>
|
||||
</div>
|
||||
|
||||
<div class="summary-stat">
|
||||
<div class="summary-stat-value white-glow" id="avg-acceptance-rate">
|
||||
{% if avg_acceptance_rate is defined %}
|
||||
{{ "%.2f"|format(avg_acceptance_rate) }}%
|
||||
{% else %}
|
||||
N/A
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="summary-stat-label">Acceptance Rate</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Controls bar -->
|
||||
<div class="controls-bar">
|
||||
<input type="text" class="search-box" id="worker-search" placeholder="Search workers...">
|
||||
<div class="filter-buttons">
|
||||
<button class="filter-button active" data-filter="all">All Workers</button>
|
||||
<button class="filter-button" data-filter="online">Online</button>
|
||||
<button class="filter-button" data-filter="offline">Offline</button>
|
||||
<button class="filter-button" data-filter="asic">ASIC</button>
|
||||
<button class="filter-button" data-filter="bitaxe">Bitaxe</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Workers grid -->
|
||||
<div class="worker-grid" id="worker-grid">
|
||||
<!-- Worker cards will be generated here via JavaScript -->
|
||||
<div id="loader" class="text-center p-5" style="display:none;">
|
||||
<i class="fas fa-spinner fa-spin"></i> Loading worker data...
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
<script src="/static/js/workers.js"></script>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue
Block a user