From a117275efe3189794015611eab9d8d37ec16300f Mon Sep 17 00:00:00 2001 From: wisecolt Date: Mon, 2 Feb 2026 19:03:41 +0000 Subject: [PATCH] feat(ui): metrikleri odaklanma ve gezinme durumunda yenile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Metriklerin güncel kalması için pencere odaklanıldığında ve sayfa gezinildiğinde verilerin yeniden yüklenmesi eklendi. Backend deployment servisinde tip tanımları güncellendi. --- backend/src/routes/deployments.ts | 4 +++ backend/src/routes/jobs.ts | 4 +++ backend/src/services/deploymentService.ts | 2 +- frontend/src/pages/HomePage.tsx | 32 ++++++++++++++++++++--- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/backend/src/routes/deployments.ts b/backend/src/routes/deployments.ts index fb3ad21..71bed75 100644 --- a/backend/src/routes/deployments.ts +++ b/backend/src/routes/deployments.ts @@ -88,6 +88,10 @@ router.get("/env-examples", async (req, res) => { router.get("/metrics/summary", async (req, res) => { authMiddleware(req, res, async () => { + const deploymentCount = await DeploymentProject.countDocuments(); + if (deploymentCount === 0) { + await deploymentService.bootstrapFromFilesystem(); + } const since = new Date(); since.setDate(since.getDate() - 7); diff --git a/backend/src/routes/jobs.ts b/backend/src/routes/jobs.ts index baf00ef..0ee452c 100644 --- a/backend/src/routes/jobs.ts +++ b/backend/src/routes/jobs.ts @@ -30,6 +30,10 @@ router.get("/", async (_req, res) => { }); router.get("/metrics/summary", async (_req, res) => { + const jobCount = await Job.countDocuments(); + if (jobCount === 0) { + await jobService.bootstrapFromFilesystem(); + } const since = new Date(); since.setDate(since.getDate() - 7); diff --git a/backend/src/services/deploymentService.ts b/backend/src/services/deploymentService.ts index 5cecb14..ccf875a 100644 --- a/backend/src/services/deploymentService.ts +++ b/backend/src/services/deploymentService.ts @@ -385,7 +385,7 @@ class DeploymentService { this.io.except(`deployment:${deploymentId}`).emit("deployment:log", { deploymentId, line }); } - private emitRun(deploymentId: string, run: DeploymentRun) { + private emitRun(deploymentId: string, run: DeploymentRunDocument) { if (!this.io) return; this.io.to(`deployment:${deploymentId}`).emit("deployment:run", { deploymentId, diff --git a/frontend/src/pages/HomePage.tsx b/frontend/src/pages/HomePage.tsx index 7ee4eac..4013489 100644 --- a/frontend/src/pages/HomePage.tsx +++ b/frontend/src/pages/HomePage.tsx @@ -1,5 +1,5 @@ -import { useEffect, useMemo, useState } from "react"; -import { useNavigate } from "react-router-dom"; +import { useCallback, useEffect, useMemo, useState } from "react"; +import { useLocation, useNavigate } from "react-router-dom"; import { Line, LineChart, @@ -18,6 +18,7 @@ import { JobStatusBadge } from "../components/JobStatusBadge"; import { RepoIcon } from "../components/RepoIcon"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faClockRotateLeft, faListCheck, faFlaskVial, faRocket } from "@fortawesome/free-solid-svg-icons"; +import { useAuth } from "../providers/auth-provider"; function formatDuration(ms?: number) { if (!ms || Number.isNaN(ms)) return "-"; @@ -41,9 +42,14 @@ export function HomePage() { const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const { jobStreams } = useLiveData(); + const { token } = useAuth(); const navigate = useNavigate(); + const location = useLocation(); - useEffect(() => { + const loadMetrics = useCallback(() => { + if (!token) return; + setLoading(true); + setError(null); Promise.allSettled([fetchJobMetrics(), fetchDeploymentMetrics()]) .then(([jobResult, deployResult]) => { if (jobResult.status === "fulfilled") { @@ -65,7 +71,25 @@ export function HomePage() { } }) .finally(() => setLoading(false)); - }, []); + }, [token]); + + useEffect(() => { + loadMetrics(); + }, [loadMetrics, location.key]); + + useEffect(() => { + const handleFocus = () => { + if (document.visibilityState === "visible") { + loadMetrics(); + } + }; + window.addEventListener("focus", handleFocus); + document.addEventListener("visibilitychange", handleFocus); + return () => { + window.removeEventListener("focus", handleFocus); + document.removeEventListener("visibilitychange", handleFocus); + }; + }, [loadMetrics]); const chartData = useMemo(() => { if (!metrics) {