Skip to content

Commit e2fcce7

Browse files
authored
Merge pull request #20 from oslabs-beta/alex
Alex
2 parents 8660a3b + 83e504d commit e2fcce7

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

client/src/App.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import SecretsPage from "./pages/SecretsPage";
66
import DashboardPage from "./pages/DashboardPage";
77
import { useRepoStore } from "./store/useRepoStore";
88
import { usePipelineStore } from "./store/usePipelineStore";
9+
import Jenkins from "./routes/Jenkins";
910

1011
function NeedRepo({ children }: { children: JSX.Element }) {
1112
const { repo, branch } = useRepoStore();
@@ -30,6 +31,7 @@ export default function App() {
3031
<Link to="/configure">2 Configure</Link>
3132
<Link to="/secrets">3 Secrets</Link>
3233
<Link to="/dashboard">4 Dashboard</Link>
34+
<Link to="/jenkins">5 Jenkins</Link>
3335
</nav>
3436
</header>
3537
<main style={{ padding: 16, maxWidth: 960, margin: "0 auto" }}>
@@ -39,6 +41,7 @@ export default function App() {
3941
<Route path="/configure" element={<NeedRepo><ConfigurePage /></NeedRepo>} />
4042
<Route path="/secrets" element={<NeedRepo><NeedPipeline><SecretsPage /></NeedPipeline></NeedRepo>} />
4143
<Route path="/dashboard" element={<NeedRepo><DashboardPage /></NeedRepo>} />
44+
<Route path="/jenkins" element={<Jenkins />} />
4245
</Routes>
4346
</main>
4447
</BrowserRouter>

client/src/lib/api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ async startDeploy({
219219
}, 600);
220220
return () => clearInterval(timer);
221221
},
222+
222223
};
223224

224225
// Helper to start GitHub OAuth (server redirects back after callback)

client/src/routes/Jenkins.tsx

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { useState } from "react";
2+
import { BASE } from "../lib/api";
3+
4+
const SERVER_BASE = BASE.replace(/\/api$/, "");
5+
6+
export default function Jenkins() {
7+
const [question, setQuestion] = useState("");
8+
const [answer, setAnswer] = useState("");
9+
const [error, setError] = useState<string | null>(null);
10+
const [loading, setLoading] = useState(false);
11+
12+
async function handleAsk() {
13+
if (!question.trim()) return;
14+
setLoading(true);
15+
setError(null);
16+
setAnswer("");
17+
try {
18+
const res = await fetch(`${SERVER_BASE}/jenkins/ask`, {
19+
method: "POST",
20+
headers: { "Content-Type": "application/json" },
21+
credentials: "include",
22+
body: JSON.stringify({ question: question.trim() }),
23+
});
24+
const data = await res.json().catch(() => ({}));
25+
if (!res.ok) throw new Error((data as any)?.error || res.statusText);
26+
setAnswer(data?.answer ?? "");
27+
} catch (err: any) {
28+
setError(err?.message ?? "Request failed");
29+
} finally {
30+
setLoading(false);
31+
}
32+
}
33+
34+
return (
35+
<section style={{ display: "grid", gap: 12 }}>
36+
<h1>Jenkins</h1>
37+
<textarea
38+
rows={4}
39+
value={question}
40+
onChange={(e) => setQuestion(e.target.value)}
41+
placeholder="Ask Jenkins about jobs or status"
42+
style={{ width: "100%", padding: 8, fontSize: 14 }}
43+
/>
44+
<div style={{ display: "flex", gap: 8 }}>
45+
<button onClick={handleAsk} disabled={loading || !question.trim()}>
46+
{loading ? "Sending..." : "Ask"}
47+
</button>
48+
<button
49+
type="button"
50+
onClick={() => {
51+
setQuestion("");
52+
setAnswer("");
53+
setError(null);
54+
}}
55+
>
56+
Clear
57+
</button>
58+
</div>
59+
{error && <div style={{ color: "red", fontSize: 13 }}>{error}</div>}
60+
<textarea
61+
readOnly
62+
value={answer}
63+
placeholder="Jenkins response will appear here"
64+
rows={6}
65+
style={{ width: "100%", padding: 8, fontSize: 14, background: "#f6f6f6" }}
66+
/>
67+
</section>
68+
);
69+
}

0 commit comments

Comments
 (0)