mirror of
				https://github.com/StefBuwalda/dashboard_test.git
				synced 2025-10-31 03:39:58 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			104 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
| <!DOCTYPE html>
 | |
| <html lang="en" data-bs-theme="dark">
 | |
| 
 | |
| <head>
 | |
|     <meta name="viewport" content="width=device-width, initial-scale=1" charset=" UTF-8">
 | |
|     <title>Dashboard</title>
 | |
|     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet"
 | |
|         integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
 | |
|     <link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
 | |
|     <style>
 | |
|         /* Prevent Bootstrap's default 0.6s width tween that causes lag */
 | |
|         .progress-bar {
 | |
|             transition: none !important;
 | |
|         }
 | |
|     </style>
 | |
| </head>
 | |
| 
 | |
| <body class="m-2 bg-light-subtle pt-3">
 | |
|     <div class="progress fixed-top mt-1" style="height: auto;">
 | |
|         <div id="progressBar" class="progress-bar rounded-pill" role="progressbar" style="width: 100%; margin: 0 auto;">
 | |
|             <h5 class="m-0">5s</h5>
 | |
|         </div>
 | |
|     </div>
 | |
|     <div id="main_body" class="d-flex flex-wrap justify-content-center"></div>
 | |
| </body>
 | |
| 
 | |
| <script>
 | |
|     const main_body = document.getElementById("main_body");
 | |
|     const url = '/api/status';
 | |
| 
 | |
|     const interval = 5000; // 5 seconds between requests
 | |
|     const progressBar = document.getElementById('progressBar');
 | |
| 
 | |
|     function fetchData() {
 | |
|         fetch(url, { cache: 'no-store' })
 | |
|             .then(response => response.json())
 | |
|             .then(data => {
 | |
|                 console.log(data)
 | |
|                 updateWebpage(data)
 | |
|             })
 | |
|             .catch(error => console.error("Error fetching data", error))
 | |
|             .finally(() => {
 | |
|                 // Animate progress bar over 'interval' before next fetch
 | |
|                 animateProgress(interval, () => {
 | |
|                     fetchData(); // next fetch after animation
 | |
|                 });
 | |
|             });
 | |
|     }
 | |
| 
 | |
|     function animateProgress(duration, callback) {
 | |
|         const start = performance.now();
 | |
| 
 | |
|         function frame(now) {
 | |
|             const elapsed = now - start;
 | |
|             const ratio = Math.min(elapsed / duration, 1);
 | |
| 
 | |
|             progressBar.style.width = 100 * (1 - ratio) + "%";
 | |
|             progressBar.innerHTML = "<h5 class='m-0'>" + (interval * (1 - ratio) / 1000).toFixed(1) + "s</h5>";
 | |
| 
 | |
|             if (ratio < 1) {
 | |
|                 requestAnimationFrame(frame);
 | |
|             } else {
 | |
|                 callback();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // reset bar and start animation
 | |
|         progressBar.style.width = '100%';
 | |
|         progressBar.textContent = '100%';
 | |
|         requestAnimationFrame(frame);
 | |
|     }
 | |
| 
 | |
|     function updateWebpage(services) {
 | |
|         main_body.innerHTML = ''; // Clear webpage
 | |
| 
 | |
|         // Build all service divs as a single string
 | |
|         main_body.innerHTML = services.map(s => `
 | |
|         <a href="${s.url}" class="d-block text-body text-decoration-none m-2 border border-3 ${s.ping ? 'border-success' : 'border-danger'}" style="width: 175px">
 | |
|             <div class="bg-body-tertiary d-flex flex-column align-items-center">
 | |
|                 <div class="bg-dark w-100">
 | |
|                     <h4 class="text-center text-truncate m-0 p-1">${s.label}</h4>
 | |
|                 </div>
 | |
|                 <div class="position-relative ratio ratio-1x1">
 | |
|                     <div class="d-flex justify-content-center align-items-center">
 | |
|                         <img src="static/icons/${s.service_id - 1}.svg" class="img-fluid w-75">
 | |
|                     </div>
 | |
|                     <div>
 | |
|                         ${s.public_access ? `` : `<img src='static/lock.svg' class='img-fluid position-absolute bottom-0 end-0 w-25'>`}
 | |
|                         <div class="position-absolute bottom-0 text-body bg-dark bg-opacity-75 px-1 rounded">${s.ping ? s.ping + "ms" : ""}</div>
 | |
|                     </div>
 | |
|                 </div>
 | |
|             </div>
 | |
|         </a>
 | |
|     `).join(''); // join into a single string
 | |
|     }
 | |
| 
 | |
|     fetchData(); // start the loop
 | |
| </script>
 | |
| 
 | |
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"
 | |
|     integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI"
 | |
|     crossorigin="anonymous"></script>
 | |
| 
 | |
| </html> |