From 9ff87b7e2071512a720efe4bcc9a6f522881a75c Mon Sep 17 00:00:00 2001 From: null Date: Wed, 20 May 2026 03:09:22 -0500 Subject: [PATCH] fix (ui): tables --- backend/app/api/forgejo_issues.py | 10 +- frontend/src/app/git-projects/issues/page.tsx | 1 + .../src/components/git/ForgejoIssuesTable.tsx | 112 ++++++++---------- 3 files changed, 57 insertions(+), 66 deletions(-) diff --git a/backend/app/api/forgejo_issues.py b/backend/app/api/forgejo_issues.py index cce7d5b..bd592b9 100644 --- a/backend/app/api/forgejo_issues.py +++ b/backend/app/api/forgejo_issues.py @@ -43,7 +43,10 @@ async def list_issues( ) -> ForgejoIssueListResponse: """List cached issues with optional filters.""" # Build query with filters - statement = select(ForgejoIssue).where(ForgejoIssue.organization_id == ctx.organization.id) + statement = select(ForgejoIssue).where( + ForgejoIssue.organization_id == ctx.organization.id, + ForgejoIssue.is_pull_request.is_(False), + ) if repository_id: try: @@ -75,7 +78,10 @@ async def list_issues( ) # Count total - total_statement = select(func.count()).select_from(ForgejoIssue).where(ForgejoIssue.organization_id == ctx.organization.id) + total_statement = select(func.count()).select_from(ForgejoIssue).where( + ForgejoIssue.organization_id == ctx.organization.id, + ForgejoIssue.is_pull_request.is_(False), + ) if repository_id: try: repo_uuid = UUID(repository_id) diff --git a/frontend/src/app/git-projects/issues/page.tsx b/frontend/src/app/git-projects/issues/page.tsx index 63afd15..881e9d3 100644 --- a/frontend/src/app/git-projects/issues/page.tsx +++ b/frontend/src/app/git-projects/issues/page.tsx @@ -260,6 +260,7 @@ export default function GitIssuesPage() { diff --git a/frontend/src/components/git/ForgejoIssuesTable.tsx b/frontend/src/components/git/ForgejoIssuesTable.tsx index 5b33a68..96c2357 100644 --- a/frontend/src/components/git/ForgejoIssuesTable.tsx +++ b/frontend/src/components/git/ForgejoIssuesTable.tsx @@ -1,19 +1,18 @@ "use client"; -import { useCallback, useMemo, useState } from "react"; +import { useMemo } from "react"; import { type ColumnDef, getCoreRowModel, useReactTable, } from "@tanstack/react-table"; -import { CircleDot, ExternalLink, XCircle } from "lucide-react"; +import { CircleDot, ExternalLink } from "lucide-react"; -import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { DataTable } from "@/components/tables/DataTable"; -import { CloseForgejoIssueDialog } from "@/components/git/CloseForgejoIssueDialog"; import type { ForgejoIssue, ForgejoIssueLabel } from "@/lib/api-forgejo"; +import type { ForgejoRepository } from "@/lib/api-forgejo"; /** Normalize a Forgejo label color to a valid 6-char hex string or null. */ function normalizeLabelColor(raw: string | null | undefined): string | null { @@ -54,29 +53,42 @@ function LabelChip({ label }: { label: ForgejoIssueLabel }) { export type ForgejoIssuesTableProps = { issues: ForgejoIssue[]; + repositories: ForgejoRepository[]; isLoading?: boolean; onRefresh: () => void; }; export function ForgejoIssuesTable({ issues, + repositories, isLoading = false, - onRefresh, + onRefresh: _onRefresh, }: ForgejoIssuesTableProps) { - const [closeIssueDialogOpen, setCloseIssueDialogOpen] = useState(false); - const [issueToClose, setIssueToClose] = useState(null); - - const handleCloseClick = useCallback((issue: ForgejoIssue) => { - setIssueToClose(issue); - setCloseIssueDialogOpen(true); - }, []); - - const handleCloseSuccess = () => { - onRefresh(); - }; + const repositoryNameById = useMemo(() => { + const map = new Map(); + for (const repository of repositories) { + map.set( + repository.id, + repository.display_name || `${repository.owner}/${repository.repo}`, + ); + } + return map; + }, [repositories]); const columns: ColumnDef[] = useMemo( () => [ + { + id: "repository", + header: "Repository", + cell: ({ row }) => { + const fallback = row.original.repository_id; + return ( + + {repositoryNameById.get(row.original.repository_id) ?? fallback} + + ); + }, + }, { accessorKey: "forgejo_issue_number", header: "#", @@ -104,20 +116,6 @@ export function ForgejoIssuesTable({ ), }, - { - accessorKey: "body_preview", - header: "Description", - cell: ({ row }) => { - const body = row.original.body_preview; - if (!body) return null; - const truncated = body.length > 120 ? body.slice(0, 120) + "…" : body; - return ( -
- {truncated} -
- ); - }, - }, { accessorKey: "state", header: "State", @@ -153,13 +151,24 @@ export function ForgejoIssuesTable({ }, }, { - accessorKey: "author", - header: "Author", - cell: ({ row }) => ( - - {row.original.author || "Unknown"} - - ), + id: "assignee", + header: "Assignee", + cell: ({ row }) => { + const assignee = row.original.assignees?.[0]; + const login = + assignee && + typeof assignee === "object" && + "login" in assignee && + typeof assignee.login === "string" + ? assignee.login + : null; + + return ( + + {login || "Unassigned"} + + ); + }, }, { accessorKey: "forgejo_updated_at", @@ -180,27 +189,8 @@ export function ForgejoIssuesTable({ } }, }, - { - id: "actions", - header: "Actions", - cell: ({ row }) => { - const issue = row.original; - if (issue.state !== "open" || issue.is_pull_request) return null; - return ( - - ); - }, - }, ], - [handleCloseClick], + [repositoryNameById], ); const table = useReactTable({ data: issues, @@ -215,7 +205,7 @@ export function ForgejoIssuesTable({ table={table} isLoading={isLoading} loadingLabel="Loading Git Project issues…" - tableClassName="min-w-[960px] w-full text-left text-sm" + tableClassName="min-w-[980px] w-full text-left text-sm" emptyState={{ icon: , title: "No Git Project issues found", @@ -224,12 +214,6 @@ export function ForgejoIssuesTable({ }} /> - ); }