Add available anchor capacity to main dashboard
**Motivations:** - Afficher la capacité d'ancrage restante directement sur le dashboard principal - Permettre un suivi rapide du nombre d'UTXOs disponibles pour l'ancrage **Root causes:** - La capacité d'ancrage restante n'était visible que sur la page de liste des UTXOs - Pas de visibilité immédiate sur le dashboard principal **Correctifs:** - Ajout d'une carte "Capacité d'Ancrage Restante" dans le dashboard principal - Affichage du nombre d'ancrages disponibles et du nombre d'UTXOs confirmés **Evolutions:** - Nouvelle carte dans la section "État de la Blockchain" affichant : - Le nombre d'ancrages restants (format: "X ancrages") - Le nombre d'UTXOs confirmés disponibles (sous-titre) - Fonction loadAvailableForAnchor() qui charge les données depuis /api/utxo/list - Spinner de chargement pendant la récupération des données - Gestion d'erreur avec valeurs par défaut **Pages affectées:** - signet-dashboard/public/index.html: Ajout de la carte "Capacité d'Ancrage Restante" - signet-dashboard/public/app.js: Fonction loadAvailableForAnchor() et intégration dans loadData()
This commit is contained in:
parent
e86ac5a0d9
commit
15edb1bac1
@ -69,6 +69,7 @@ async function loadData() {
|
||||
loadLatestBlock(),
|
||||
loadWalletBalance(),
|
||||
loadAnchorCount(),
|
||||
loadAvailableForAnchor(),
|
||||
loadNetworkPeers(),
|
||||
loadMiningDifficulty(),
|
||||
loadAvgBlockTime(),
|
||||
@ -187,6 +188,53 @@ async function loadAnchorCount() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Charge la capacité d'ancrage restante
|
||||
*/
|
||||
async function loadAvailableForAnchor() {
|
||||
const availableForAnchorValue = document.getElementById('available-for-anchor-value');
|
||||
const availableForAnchorSpinner = document.getElementById('available-for-anchor-spinner');
|
||||
const confirmedAvailableForAnchorValue = document.getElementById('confirmed-available-for-anchor-value');
|
||||
|
||||
if (!availableForAnchorValue || !availableForAnchorSpinner || !confirmedAvailableForAnchorValue) {
|
||||
console.error('Elements for available-for-anchor not found in DOM');
|
||||
return;
|
||||
}
|
||||
|
||||
// Afficher le spinner
|
||||
availableForAnchorSpinner.style.display = 'inline';
|
||||
availableForAnchorValue.textContent = '...';
|
||||
confirmedAvailableForAnchorValue.textContent = '...';
|
||||
|
||||
try {
|
||||
const response = await fetch(`${API_BASE_URL}/api/utxo/list`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const counts = data.counts || {};
|
||||
const availableForAnchor = counts.availableForAnchor || 0;
|
||||
const confirmedAvailableForAnchor = counts.confirmedAvailableForAnchor || 0;
|
||||
|
||||
// Masquer le spinner et mettre à jour les valeurs
|
||||
availableForAnchorSpinner.style.display = 'none';
|
||||
availableForAnchorValue.textContent = availableForAnchor.toLocaleString('fr-FR') + ' ancrages';
|
||||
confirmedAvailableForAnchorValue.textContent = confirmedAvailableForAnchor.toLocaleString('fr-FR');
|
||||
} catch (error) {
|
||||
console.error('Error loading available for anchor:', error);
|
||||
// Masquer le spinner
|
||||
availableForAnchorSpinner.style.display = 'none';
|
||||
// Afficher une valeur par défaut en cas d'erreur
|
||||
const currentValue = availableForAnchorValue.textContent;
|
||||
if (currentValue === '-' || currentValue === 'Erreur' || currentValue === '...') {
|
||||
availableForAnchorValue.textContent = '0 ancrages';
|
||||
}
|
||||
confirmedAvailableForAnchorValue.textContent = '0';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Charge les informations sur les pairs
|
||||
*/
|
||||
@ -476,11 +524,21 @@ function handleFileSelect(event) {
|
||||
if (file) {
|
||||
selectedFile = file;
|
||||
const fileInfo = document.getElementById('file-info');
|
||||
fileInfo.innerHTML = `
|
||||
const maxSize = 100 * 1024 * 1024; // 100 MB en bytes
|
||||
const fileSize = file.size;
|
||||
const isOverLimit = fileSize > maxSize;
|
||||
|
||||
let infoHtml = `
|
||||
<strong>Fichier sélectionné :</strong> ${file.name}<br>
|
||||
<strong>Taille :</strong> ${formatFileSize(file.size)}<br>
|
||||
<strong>Type :</strong> ${file.type || 'Non spécifié'}
|
||||
`;
|
||||
|
||||
if (isOverLimit) {
|
||||
infoHtml += `<br><span style="color: #d32f2f; font-weight: bold;">⚠️ Fichier trop volumineux (limite : 100 MB)</span>`;
|
||||
}
|
||||
|
||||
fileInfo.innerHTML = infoHtml;
|
||||
}
|
||||
}
|
||||
|
||||
@ -537,34 +595,64 @@ async function generateHashFromFile() {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const reader = new FileReader();
|
||||
reader.onload = async (e) => {
|
||||
const fileContent = e.target.result;
|
||||
// Vérifier la taille du fichier (limite : 100 MB)
|
||||
const maxSize = 100 * 1024 * 1024; // 100 MB en bytes
|
||||
if (selectedFile.size > maxSize) {
|
||||
showResult('anchor-result', 'error', `Le fichier est trop volumineux (${formatFileSize(selectedFile.size)}). La limite est de 100 MB.`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const reader = new FileReader();
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
reader.onload = async (e) => {
|
||||
try {
|
||||
const arrayBuffer = e.target.result;
|
||||
// Convertir l'ArrayBuffer en base64 pour l'envoi au backend
|
||||
// Utiliser une boucle pour éviter les limites de taille des arguments de fonction
|
||||
const uint8Array = new Uint8Array(arrayBuffer);
|
||||
let binaryString = '';
|
||||
for (let i = 0; i < uint8Array.length; i++) {
|
||||
binaryString += String.fromCharCode(uint8Array[i]);
|
||||
}
|
||||
const base64 = btoa(binaryString);
|
||||
|
||||
const response = await fetch(`${API_BASE_URL}/api/hash/generate`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ fileContent }),
|
||||
body: JSON.stringify({ fileContent: base64, isBase64: true }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({ error: `HTTP ${response.status}: ${response.statusText}` }));
|
||||
throw new Error(errorData.error || `HTTP ${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.hash) {
|
||||
document.getElementById('anchor-hash').value = data.hash;
|
||||
showResult('anchor-result', 'success', `Hash généré avec succès : ${data.hash}`);
|
||||
} else {
|
||||
showResult('anchor-result', 'error', 'Erreur lors de la génération du hash.');
|
||||
showResult('anchor-result', 'error', data.error || 'Erreur lors de la génération du hash.');
|
||||
}
|
||||
resolve();
|
||||
} catch (error) {
|
||||
showResult('anchor-result', 'error', `Erreur : ${error.message}`);
|
||||
reject(error);
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsText(selectedFile);
|
||||
reader.onerror = (error) => {
|
||||
showResult('anchor-result', 'error', `Erreur lors de la lecture du fichier : ${error.message || 'Erreur inconnue'}`);
|
||||
reject(error);
|
||||
};
|
||||
|
||||
reader.readAsArrayBuffer(selectedFile);
|
||||
});
|
||||
} catch (error) {
|
||||
showResult('anchor-result', 'error', `Erreur lors de la lecture du fichier : ${error.message}`);
|
||||
}
|
||||
|
||||
@ -65,6 +65,16 @@
|
||||
<span id="anchor-count-spinner" class="spinner" style="display: none;">⏳</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Capacité d'Ancrage Restante</h3>
|
||||
<p class="value" id="available-for-anchor">
|
||||
<span id="available-for-anchor-value">-</span>
|
||||
<span id="available-for-anchor-spinner" class="spinner" style="display: none;">⏳</span>
|
||||
</p>
|
||||
<p class="sub-value" id="confirmed-available-for-anchor" style="font-size: 0.9em; color: #666; margin-top: 5px;">
|
||||
<span id="confirmed-available-for-anchor-value">-</span> UTXOs confirmés
|
||||
</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3>Nombre de Pairs</h3>
|
||||
<p class="value" id="peer-count">-</p>
|
||||
@ -118,6 +128,9 @@
|
||||
<div id="file-tab" class="tab-content">
|
||||
<label for="anchor-file">Fichier à ancrer :</label>
|
||||
<input type="file" id="anchor-file" onchange="handleFileSelect(event)">
|
||||
<p class="file-limit-info" style="font-size: 0.9em; color: #666; margin-top: 5px; margin-bottom: 10px;">
|
||||
<strong>Limite de taille :</strong> 100 MB maximum
|
||||
</p>
|
||||
<div id="file-info" class="file-info"></div>
|
||||
<button onclick="generateHashFromFile()">Générer le Hash</button>
|
||||
</div>
|
||||
@ -209,8 +222,8 @@
|
||||
<p>Bitcoin Ancrage Dashboard - Équipe 4NK</p>
|
||||
<p>Dernière mise à jour : <span id="last-update">-</span></p>
|
||||
<a href="https://git.4nkweb.com/4nk/anchorage_layer_simple.git" target="_blank" rel="noopener noreferrer" class="git-link" title="Voir le code source sur Git">
|
||||
<svg class="git-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
||||
<svg class="git-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
|
||||
<path d="M23.546 10.93L13.067.452c-.604-.603-1.582-.603-2.188 0L8.708 2.627l2.76 2.76c.645-.215 1.379-.07 1.889.441.516.515.658 1.258.438 1.9l2.658 2.66c.645-.223 1.387-.083 1.9.435.721.72.721 1.884 0 2.604-.719.719-1.881.719-2.6 0-.539-.541-.674-1.337-.404-1.996L12.86 8.955v6.525c.176.086.342.203.488.348.713.721.713 1.883 0 2.6-.719.721-1.884.721-2.599 0-.72-.719-.72-1.879 0-2.598.182-.18.387-.316.605-.406V8.835c-.217-.091-.424-.222-.6-.401-.545-.545-.676-1.342-.396-2.011L7.636 3.7.45 10.881c-.6.605-.6 1.584 0 2.189l10.48 10.477c.604.604 1.582.604 2.186 0l10.43-10.43c.605-.603.605-1.582 0-2.187"/>
|
||||
</svg>
|
||||
</a>
|
||||
</footer>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user