From c81e0e814329693315b5952acbf8fecf27714c2a Mon Sep 17 00:00:00 2001 From: Alex Weng Date: Sat, 8 Nov 2025 14:09:53 -0500 Subject: [PATCH 1/2] Added new Jenkins route --- client/src/lib/api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/lib/api.ts b/client/src/lib/api.ts index eb57f7c..6aa64b3 100644 --- a/client/src/lib/api.ts +++ b/client/src/lib/api.ts @@ -170,6 +170,7 @@ export const api = { }, 800); return () => clearInterval(timer); }, + }; // Helper to start GitHub OAuth (server redirects back after callback) @@ -204,4 +205,3 @@ function writeSecrets(repo: string, env: string, obj: Record) { // in-memory job storage for mock deploys const JOBS: Map = new Map(); - From 83e504d8e27776ab1fb85c1a478201da406146a7 Mon Sep 17 00:00:00 2001 From: Alex Weng Date: Sat, 8 Nov 2025 14:09:55 -0500 Subject: [PATCH 2/2] Add new Jenkins Route --- client/src/App.tsx | 3 ++ client/src/routes/Jenkins.tsx | 69 +++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 client/src/routes/Jenkins.tsx diff --git a/client/src/App.tsx b/client/src/App.tsx index 1d8fa6f..6fe459f 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -6,6 +6,7 @@ import SecretsPage from "./pages/SecretsPage"; import DashboardPage from "./pages/DashboardPage"; import { useRepoStore } from "./store/useRepoStore"; import { usePipelineStore } from "./store/usePipelineStore"; +import Jenkins from "./routes/Jenkins"; function NeedRepo({ children }: { children: JSX.Element }) { const { repo, branch } = useRepoStore(); @@ -25,6 +26,7 @@ export default function App() { 2 Configure 3 Secrets 4 Dashboard + 5 Jenkins
@@ -34,6 +36,7 @@ export default function App() { } /> } /> } /> + } />
diff --git a/client/src/routes/Jenkins.tsx b/client/src/routes/Jenkins.tsx new file mode 100644 index 0000000..a40c3ea --- /dev/null +++ b/client/src/routes/Jenkins.tsx @@ -0,0 +1,69 @@ +import { useState } from "react"; +import { BASE } from "../lib/api"; + +const SERVER_BASE = BASE.replace(/\/api$/, ""); + +export default function Jenkins() { + const [question, setQuestion] = useState(""); + const [answer, setAnswer] = useState(""); + const [error, setError] = useState(null); + const [loading, setLoading] = useState(false); + + async function handleAsk() { + if (!question.trim()) return; + setLoading(true); + setError(null); + setAnswer(""); + try { + const res = await fetch(`${SERVER_BASE}/jenkins/ask`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + credentials: "include", + body: JSON.stringify({ question: question.trim() }), + }); + const data = await res.json().catch(() => ({})); + if (!res.ok) throw new Error((data as any)?.error || res.statusText); + setAnswer(data?.answer ?? ""); + } catch (err: any) { + setError(err?.message ?? "Request failed"); + } finally { + setLoading(false); + } + } + + return ( +
+

Jenkins

+