Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Update frontend/src/pages/Dashboard.jsx
Browse files- frontend/src/pages/Dashboard.jsx +71 -29
frontend/src/pages/Dashboard.jsx
CHANGED
|
@@ -54,6 +54,7 @@ export const Dashboard = () => {
|
|
| 54 |
const dashboardPollRef = useRef(null);
|
| 55 |
const activeScanRef = useRef(null);
|
| 56 |
const completedScanIdRef = useRef(null);
|
|
|
|
| 57 |
|
| 58 |
const markScanAsCompleted = useCallback((id) => {
|
| 59 |
completedScanIdRef.current = id;
|
|
@@ -90,10 +91,13 @@ export const Dashboard = () => {
|
|
| 90 |
}
|
| 91 |
}, []);
|
| 92 |
|
| 93 |
-
const startLogPolling = useCallback((scan) => {
|
| 94 |
stopLogPolling();
|
| 95 |
activeScanRef.current = scan;
|
| 96 |
persistActiveScan(scan);
|
|
|
|
|
|
|
|
|
|
| 97 |
let consecutiveErrors = 0;
|
| 98 |
const MAX_ERRORS = 20; // tolerate up to 20 failures (covers token refresh + brief outages)
|
| 99 |
|
|
@@ -136,7 +140,10 @@ export const Dashboard = () => {
|
|
| 136 |
setActiveScan(null);
|
| 137 |
activeScanRef.current = null;
|
| 138 |
persistActiveScan(null); // clear localStorage
|
| 139 |
-
|
|
|
|
|
|
|
|
|
|
| 140 |
fetchDashboard();
|
| 141 |
}
|
| 142 |
} catch (err) {
|
|
@@ -182,6 +189,7 @@ export const Dashboard = () => {
|
|
| 182 |
});
|
| 183 |
|
| 184 |
if (runningScans.length > 0) {
|
|
|
|
| 185 |
// If we are ALREADY tracking an active scan that is still in progress, STICK WITH IT!
|
| 186 |
const currentStillRunning = activeScanRef.current
|
| 187 |
? runningScans.find(s => s.id === activeScanRef.current.id)
|
|
@@ -197,10 +205,11 @@ export const Dashboard = () => {
|
|
| 197 |
setActiveScan(nextScan);
|
| 198 |
activeScanRef.current = nextScan;
|
| 199 |
setLiveLogs([]);
|
| 200 |
-
startLogPolling(nextScan);
|
| 201 |
}
|
| 202 |
} else {
|
| 203 |
// No active scans remaining
|
|
|
|
| 204 |
if (activeScanRef.current) {
|
| 205 |
setActiveScan(null);
|
| 206 |
activeScanRef.current = null;
|
|
@@ -226,7 +235,7 @@ export const Dashboard = () => {
|
|
| 226 |
if (storedScan && storedScan.id) {
|
| 227 |
setActiveScan(storedScan);
|
| 228 |
activeScanRef.current = storedScan;
|
| 229 |
-
startLogPolling(storedScan);
|
| 230 |
}
|
| 231 |
} catch (_) {
|
| 232 |
localStorage.removeItem(ACTIVE_SCAN_KEY);
|
|
@@ -486,7 +495,13 @@ export const Dashboard = () => {
|
|
| 486 |
const scanData = recentScans.find(s => s.id === completedScanId);
|
| 487 |
const isFailed = scanData?.status === 'failed';
|
| 488 |
const isTerminated = scanData?.status === 'terminated';
|
| 489 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 490 |
if (isTerminated) {
|
| 491 |
return (
|
| 492 |
<div className="w-full bg-red-50 border border-red-200 rounded-xl p-md flex items-center justify-between shadow-sm">
|
|
@@ -497,14 +512,23 @@ export const Dashboard = () => {
|
|
| 497 |
<p className="font-body-sm text-body-sm text-red-700">Sorry, due to some problemes we terminate your scanning and also show that scanner is terminated.</p>
|
| 498 |
</div>
|
| 499 |
</div>
|
| 500 |
-
<
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
|
| 504 |
-
|
| 505 |
-
|
| 506 |
-
|
| 507 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 508 |
</div>
|
| 509 |
);
|
| 510 |
}
|
|
@@ -519,14 +543,23 @@ export const Dashboard = () => {
|
|
| 519 |
<p className="font-body-sm text-body-sm text-red-700">The scanner encountered a critical error. View logs for details.</p>
|
| 520 |
</div>
|
| 521 |
</div>
|
| 522 |
-
<
|
| 523 |
-
|
| 524 |
-
|
| 525 |
-
|
| 526 |
-
|
| 527 |
-
|
| 528 |
-
|
| 529 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 530 |
</div>
|
| 531 |
);
|
| 532 |
}
|
|
@@ -540,14 +573,23 @@ export const Dashboard = () => {
|
|
| 540 |
<p className="font-body-sm text-body-sm text-green-700">Vulnerability analysis finished. View the full report below.</p>
|
| 541 |
</div>
|
| 542 |
</div>
|
| 543 |
-
<
|
| 544 |
-
|
| 545 |
-
|
| 546 |
-
|
| 547 |
-
|
| 548 |
-
|
| 549 |
-
|
| 550 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 551 |
</div>
|
| 552 |
);
|
| 553 |
})()
|
|
|
|
| 54 |
const dashboardPollRef = useRef(null);
|
| 55 |
const activeScanRef = useRef(null);
|
| 56 |
const completedScanIdRef = useRef(null);
|
| 57 |
+
const liveScanIdsRef = useRef(new Set());
|
| 58 |
|
| 59 |
const markScanAsCompleted = useCallback((id) => {
|
| 60 |
completedScanIdRef.current = id;
|
|
|
|
| 91 |
}
|
| 92 |
}, []);
|
| 93 |
|
| 94 |
+
const startLogPolling = useCallback((scan, isLive = true) => {
|
| 95 |
stopLogPolling();
|
| 96 |
activeScanRef.current = scan;
|
| 97 |
persistActiveScan(scan);
|
| 98 |
+
if (isLive && scan?.id) {
|
| 99 |
+
liveScanIdsRef.current.add(scan.id);
|
| 100 |
+
}
|
| 101 |
let consecutiveErrors = 0;
|
| 102 |
const MAX_ERRORS = 20; // tolerate up to 20 failures (covers token refresh + brief outages)
|
| 103 |
|
|
|
|
| 140 |
setActiveScan(null);
|
| 141 |
activeScanRef.current = null;
|
| 142 |
persistActiveScan(null); // clear localStorage
|
| 143 |
+
if (liveScanIdsRef.current.has(currentScan.id)) {
|
| 144 |
+
markScanAsCompleted(currentScan.id);
|
| 145 |
+
liveScanIdsRef.current.delete(currentScan.id);
|
| 146 |
+
}
|
| 147 |
fetchDashboard();
|
| 148 |
}
|
| 149 |
} catch (err) {
|
|
|
|
| 189 |
});
|
| 190 |
|
| 191 |
if (runningScans.length > 0) {
|
| 192 |
+
runningScans.forEach(s => liveScanIdsRef.current.add(s.id));
|
| 193 |
// If we are ALREADY tracking an active scan that is still in progress, STICK WITH IT!
|
| 194 |
const currentStillRunning = activeScanRef.current
|
| 195 |
? runningScans.find(s => s.id === activeScanRef.current.id)
|
|
|
|
| 205 |
setActiveScan(nextScan);
|
| 206 |
activeScanRef.current = nextScan;
|
| 207 |
setLiveLogs([]);
|
| 208 |
+
startLogPolling(nextScan, true);
|
| 209 |
}
|
| 210 |
} else {
|
| 211 |
// No active scans remaining
|
| 212 |
+
localStorage.removeItem(ACTIVE_SCAN_KEY);
|
| 213 |
if (activeScanRef.current) {
|
| 214 |
setActiveScan(null);
|
| 215 |
activeScanRef.current = null;
|
|
|
|
| 235 |
if (storedScan && storedScan.id) {
|
| 236 |
setActiveScan(storedScan);
|
| 237 |
activeScanRef.current = storedScan;
|
| 238 |
+
startLogPolling(storedScan, false); // isLive = false, prevent stale error banner
|
| 239 |
}
|
| 240 |
} catch (_) {
|
| 241 |
localStorage.removeItem(ACTIVE_SCAN_KEY);
|
|
|
|
| 495 |
const scanData = recentScans.find(s => s.id === completedScanId);
|
| 496 |
const isFailed = scanData?.status === 'failed';
|
| 497 |
const isTerminated = scanData?.status === 'terminated';
|
| 498 |
+
|
| 499 |
+
const handleDismiss = () => {
|
| 500 |
+
setCompletedScanId(null);
|
| 501 |
+
completedScanIdRef.current = null;
|
| 502 |
+
localStorage.removeItem(ACTIVE_SCAN_KEY);
|
| 503 |
+
};
|
| 504 |
+
|
| 505 |
if (isTerminated) {
|
| 506 |
return (
|
| 507 |
<div className="w-full bg-red-50 border border-red-200 rounded-xl p-md flex items-center justify-between shadow-sm">
|
|
|
|
| 512 |
<p className="font-body-sm text-body-sm text-red-700">Sorry, due to some problemes we terminate your scanning and also show that scanner is terminated.</p>
|
| 513 |
</div>
|
| 514 |
</div>
|
| 515 |
+
<div className="flex items-center gap-sm">
|
| 516 |
+
<Link
|
| 517 |
+
to={`/scans/results?id=${completedScanId}`}
|
| 518 |
+
className="bg-red-600 hover:bg-red-700 text-white font-label-md text-label-md px-lg py-sm rounded-lg flex items-center gap-sm transition-colors font-bold border-0"
|
| 519 |
+
style={{ textDecoration: 'none' }}
|
| 520 |
+
>
|
| 521 |
+
<span className="material-symbols-outlined text-[18px]">open_in_new</span>
|
| 522 |
+
View Details
|
| 523 |
+
</Link>
|
| 524 |
+
<button
|
| 525 |
+
onClick={handleDismiss}
|
| 526 |
+
className="p-sm text-red-600 hover:bg-red-100 rounded-lg transition-colors border-0 bg-transparent cursor-pointer flex items-center justify-center"
|
| 527 |
+
title="Dismiss notification"
|
| 528 |
+
>
|
| 529 |
+
<span className="material-symbols-outlined text-[20px]">close</span>
|
| 530 |
+
</button>
|
| 531 |
+
</div>
|
| 532 |
</div>
|
| 533 |
);
|
| 534 |
}
|
|
|
|
| 543 |
<p className="font-body-sm text-body-sm text-red-700">The scanner encountered a critical error. View logs for details.</p>
|
| 544 |
</div>
|
| 545 |
</div>
|
| 546 |
+
<div className="flex items-center gap-sm">
|
| 547 |
+
<Link
|
| 548 |
+
to={`/scans/results?id=${completedScanId}`}
|
| 549 |
+
className="bg-red-600 hover:bg-red-700 text-white font-label-md text-label-md px-lg py-sm rounded-lg flex items-center gap-sm transition-colors font-bold border-0"
|
| 550 |
+
style={{ textDecoration: 'none' }}
|
| 551 |
+
>
|
| 552 |
+
<span className="material-symbols-outlined text-[18px]">open_in_new</span>
|
| 553 |
+
View Details
|
| 554 |
+
</Link>
|
| 555 |
+
<button
|
| 556 |
+
onClick={handleDismiss}
|
| 557 |
+
className="p-sm text-red-600 hover:bg-red-100 rounded-lg transition-colors border-0 bg-transparent cursor-pointer flex items-center justify-center"
|
| 558 |
+
title="Dismiss notification"
|
| 559 |
+
>
|
| 560 |
+
<span className="material-symbols-outlined text-[20px]">close</span>
|
| 561 |
+
</button>
|
| 562 |
+
</div>
|
| 563 |
</div>
|
| 564 |
);
|
| 565 |
}
|
|
|
|
| 573 |
<p className="font-body-sm text-body-sm text-green-700">Vulnerability analysis finished. View the full report below.</p>
|
| 574 |
</div>
|
| 575 |
</div>
|
| 576 |
+
<div className="flex items-center gap-sm">
|
| 577 |
+
<Link
|
| 578 |
+
to={`/scans/results?id=${completedScanId}`}
|
| 579 |
+
className="bg-green-600 hover:bg-green-700 text-white font-label-md text-label-md px-lg py-sm rounded-lg flex items-center gap-sm transition-colors font-bold border-0"
|
| 580 |
+
style={{ textDecoration: 'none' }}
|
| 581 |
+
>
|
| 582 |
+
<span className="material-symbols-outlined text-[18px]">open_in_new</span>
|
| 583 |
+
View Full Report
|
| 584 |
+
</Link>
|
| 585 |
+
<button
|
| 586 |
+
onClick={handleDismiss}
|
| 587 |
+
className="p-sm text-green-600 hover:bg-green-100 rounded-lg transition-colors border-0 bg-transparent cursor-pointer flex items-center justify-center"
|
| 588 |
+
title="Dismiss notification"
|
| 589 |
+
>
|
| 590 |
+
<span className="material-symbols-outlined text-[20px]">close</span>
|
| 591 |
+
</button>
|
| 592 |
+
</div>
|
| 593 |
</div>
|
| 594 |
);
|
| 595 |
})()
|