diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index d721fb3..c735851 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -82,7 +82,7 @@ fn load_or_generate_key(path: &std::path::Path) -> Result<[u8; 32], Box rusqlite::Result { }) } +#[allow(dead_code)] const SELECT_ALL_COLS: &str = "SELECT id, tracker_id, artifact_id, artifact_title, artifact_data, \ status, analyst_report, developer_report, worktree_path, branch_name, \ detected_at, processed_at FROM processed_tickets"; @@ -91,6 +92,7 @@ impl ProcessedTicket { Ok(count > 0) } + #[allow(dead_code)] pub fn list_by_tracker(conn: &Connection, tracker_id: &str) -> Result> { let sql = format!( "{} WHERE tracker_id = ?1 ORDER BY detected_at DESC", @@ -115,6 +117,7 @@ impl ProcessedTicket { rows.collect() } + #[allow(dead_code)] pub fn get_by_id(conn: &Connection, id: &str) -> Result { let sql = format!("{} WHERE id = ?1", SELECT_ALL_COLS); conn.query_row(&sql, params![id], from_row) diff --git a/src-tauri/src/services/tuleap_client.rs b/src-tauri/src/services/tuleap_client.rs index b8d3f39..358001f 100644 --- a/src-tauri/src/services/tuleap_client.rs +++ b/src-tauri/src/services/tuleap_client.rs @@ -31,6 +31,7 @@ impl TuleapClient { } } + #[allow(dead_code)] pub async fn test_connection(&self) -> Result<(), String> { let url = format!("{}/api/projects?limit=1", self.base_url); let resp = self diff --git a/src/components/projects/ProjectDashboard.tsx b/src/components/projects/ProjectDashboard.tsx index 4646cbe..8e0b089 100644 --- a/src/components/projects/ProjectDashboard.tsx +++ b/src/components/projects/ProjectDashboard.tsx @@ -1,17 +1,30 @@ import { useEffect, useState } from "react"; import { useParams, Link, useNavigate } from "react-router-dom"; -import { getProject, deleteProject } from "../../lib/api"; -import type { Project } from "../../lib/types"; +import { getProject, deleteProject, listTrackers, listProcessedTickets } from "../../lib/api"; +import type { Project, WatchedTracker, ProcessedTicket } from "../../lib/types"; +import TrackerList from "../trackers/TrackerList"; export default function ProjectDashboard() { const { projectId } = useParams(); const navigate = useNavigate(); const [project, setProject] = useState(null); + const [trackers, setTrackers] = useState([]); + const [tickets, setTickets] = useState([]); + + async function loadData() { + if (!projectId) return; + const [proj, trks, tkts] = await Promise.all([ + getProject(projectId), + listTrackers(projectId), + listProcessedTickets(projectId), + ]); + setProject(proj); + setTrackers(trks); + setTickets(tkts); + } useEffect(() => { - if (projectId) { - getProject(projectId).then(setProject); - } + loadData(); }, [projectId]); async function handleDelete() { @@ -23,10 +36,25 @@ export default function ProjectDashboard() { navigate("/"); } + function statusBadgeClass(status: string): string { + switch (status) { + case "Pending": + return "bg-yellow-100 text-yellow-700"; + case "Done": + return "bg-green-100 text-green-700"; + case "Error": + return "bg-red-100 text-red-700"; + default: + return "bg-blue-100 text-blue-700"; + } + } + if (!project) { return
Loading...
; } + const recentTickets = tickets.slice(-10).reverse(); + return (
@@ -68,8 +96,37 @@ export default function ProjectDashboard() {
-
- Tracker surveillance and ticket processing will be available in the next update. +
+

Watched Trackers

+ +
+ +
+

Recent Tickets

+ {recentTickets.length === 0 ? ( +
No tickets processed yet.
+ ) : ( +
+ {recentTickets.map((ticket) => ( +
+
+
+ #{ticket.artifact_id} + {ticket.artifact_title} +
+
+ + {ticket.status} + +
+ ))} +
+ )}
);