Skip to content
Merged

Alex #20

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -25,6 +26,7 @@ export default function App() {
<Link to="/configure">2 Configure</Link>
<Link to="/secrets">3 Secrets</Link>
<Link to="/dashboard">4 Dashboard</Link>
<Link to="/jenkins">5 Jenkins</Link>
</nav>
</header>
<main style={{ padding: 16, maxWidth: 960, margin: "0 auto" }}>
Expand All @@ -34,6 +36,7 @@ export default function App() {
<Route path="/configure" element={<NeedRepo><ConfigurePage /></NeedRepo>} />
<Route path="/secrets" element={<NeedRepo><NeedPipeline><SecretsPage /></NeedPipeline></NeedRepo>} />
<Route path="/dashboard" element={<NeedRepo><DashboardPage /></NeedRepo>} />
<Route path="/jenkins" element={<Jenkins />} />
</Routes>
</main>
</BrowserRouter>
Expand Down
2 changes: 1 addition & 1 deletion client/src/lib/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ export const api = {
}, 800);
return () => clearInterval(timer);
},

};

// Helper to start GitHub OAuth (server redirects back after callback)
Expand Down Expand Up @@ -204,4 +205,3 @@ function writeSecrets(repo: string, env: string, obj: Record<string, string>) {

// in-memory job storage for mock deploys
const JOBS: Map<string, any> = new Map();

69 changes: 69 additions & 0 deletions client/src/routes/Jenkins.tsx
Original file line number Diff line number Diff line change
@@ -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<string | null>(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 (
<section style={{ display: "grid", gap: 12 }}>
<h1>Jenkins</h1>
<textarea
rows={4}
value={question}
onChange={(e) => setQuestion(e.target.value)}
placeholder="Ask Jenkins about jobs or status"
style={{ width: "100%", padding: 8, fontSize: 14 }}
/>
<div style={{ display: "flex", gap: 8 }}>
<button onClick={handleAsk} disabled={loading || !question.trim()}>
{loading ? "Sending..." : "Ask"}
</button>
<button
type="button"
onClick={() => {
setQuestion("");
setAnswer("");
setError(null);
}}
>
Clear
</button>
</div>
{error && <div style={{ color: "red", fontSize: 13 }}>{error}</div>}
<textarea
readOnly
value={answer}
placeholder="Jenkins response will appear here"
rows={6}
style={{ width: "100%", padding: 8, fontSize: 14, background: "#f6f6f6" }}
/>
</section>
);
}