more touchups

This commit is contained in:
bkellam 2025-10-23 15:49:58 -07:00
parent 39bcb09778
commit cd54eb0b7b
3 changed files with 120 additions and 26 deletions

View file

@ -1,18 +1,21 @@
import { Suspense } from "react" import { sew } from "@/actions"
import { notFound } from "next/navigation"
import Link from "next/link"
import { ChevronLeft, ExternalLink } from "lucide-react"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge" import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Skeleton } from "@/components/ui/skeleton" import { Skeleton } from "@/components/ui/skeleton"
import { RepoJobsTable } from "../components/repoJobsTable" import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
import { SINGLE_TENANT_ORG_DOMAIN } from "@/lib/constants" import { SINGLE_TENANT_ORG_DOMAIN } from "@/lib/constants"
import { sew } from "@/actions"
import { withOptionalAuthV2 } from "@/withAuthV2"
import { ServiceErrorException } from "@/lib/serviceError" import { ServiceErrorException } from "@/lib/serviceError"
import { cn, getCodeHostInfoForRepo, isServiceError } from "@/lib/utils" import { cn, getCodeHostInfoForRepo, isServiceError } from "@/lib/utils"
import { withOptionalAuthV2 } from "@/withAuthV2"
import { ChevronLeft, ExternalLink, Info } from "lucide-react"
import Image from "next/image" import Image from "next/image"
import Link from "next/link"
import { notFound } from "next/navigation"
import { Suspense } from "react"
import { RepoJobsTable } from "../components/repoJobsTable"
import { getConfigSettings } from "@sourcebot/shared"
import { env } from "@/env.mjs"
function formatDate(date: Date | null) { function formatDate(date: Date | null) {
if (!date) return "Never" if (!date) return "Never"
@ -39,6 +42,21 @@ export default async function RepoDetailPage({ params }: { params: Promise<{ id:
webUrl: repo.webUrl ?? undefined, webUrl: repo.webUrl ?? undefined,
}); });
const configSettings = await getConfigSettings(env.CONFIG_PATH);
const nextIndexAttempt = (() => {
const latestJob = repo.jobs.length > 0 ? repo.jobs[0] : null;
if (!latestJob) {
return undefined;
}
if (latestJob.completedAt) {
return new Date(latestJob.completedAt.getTime() + configSettings.reindexIntervalMs);
}
return undefined;
})();
return ( return (
<div className="container mx-auto"> <div className="container mx-auto">
<div className="mb-6"> <div className="mb-6">
@ -78,16 +96,17 @@ export default async function RepoDetailPage({ params }: { params: Promise<{ id:
<div className="grid gap-4 md:grid-cols-3 mb-8"> <div className="grid gap-4 md:grid-cols-3 mb-8">
<Card> <Card>
<CardHeader className="pb-3"> <CardHeader className="pb-3">
<CardTitle className="text-sm font-medium">Last Indexed</CardTitle> <CardTitle className="text-sm font-medium flex items-center gap-1.5">
</CardHeader> Created
<CardContent> <Tooltip>
<div className="text-2xl font-semibold">{repo.indexedAt ? formatDate(repo.indexedAt) : "Never"}</div> <TooltipTrigger asChild>
</CardContent> <Info className="h-3.5 w-3.5 text-muted-foreground cursor-help" />
</Card> </TooltipTrigger>
<TooltipContent>
<Card> <p>When this repository was first added to Sourcebot</p>
<CardHeader className="pb-3"> </TooltipContent>
<CardTitle className="text-sm font-medium">Created</CardTitle> </Tooltip>
</CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="text-2xl font-semibold">{formatDate(repo.createdAt)}</div> <div className="text-2xl font-semibold">{formatDate(repo.createdAt)}</div>
@ -96,10 +115,39 @@ export default async function RepoDetailPage({ params }: { params: Promise<{ id:
<Card> <Card>
<CardHeader className="pb-3"> <CardHeader className="pb-3">
<CardTitle className="text-sm font-medium">Last Updated</CardTitle> <CardTitle className="text-sm font-medium flex items-center gap-1.5">
Last indexed
<Tooltip>
<TooltipTrigger asChild>
<Info className="h-3.5 w-3.5 text-muted-foreground cursor-help" />
</TooltipTrigger>
<TooltipContent>
<p>The last time this repository was successfully indexed</p>
</TooltipContent>
</Tooltip>
</CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<div className="text-2xl font-semibold">{formatDate(repo.updatedAt)}</div> <div className="text-2xl font-semibold">{repo.indexedAt ? formatDate(repo.indexedAt) : "Never"}</div>
</CardContent>
</Card>
<Card>
<CardHeader className="pb-3">
<CardTitle className="text-sm font-medium flex items-center gap-1.5">
Scheduled
<Tooltip>
<TooltipTrigger asChild>
<Info className="h-3.5 w-3.5 text-muted-foreground cursor-help" />
</TooltipTrigger>
<TooltipContent>
<p>When the next indexing job is scheduled to run</p>
</TooltipContent>
</Tooltip>
</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-semibold">{nextIndexAttempt ? formatDate(nextIndexAttempt) : "-"}</div>
</CardContent> </CardContent>
</Card> </Card>
</div> </div>
@ -127,8 +175,12 @@ const getRepoWithJobs = async (repoId: number) => sew(() =>
id: repoId, id: repoId,
}, },
include: { include: {
jobs: true, jobs: {
} orderBy: {
createdAt: 'desc'
},
}
},
}); });
if (!repo) { if (!repo) {

View file

@ -18,10 +18,13 @@ import {
useReactTable, useReactTable,
} from "@tanstack/react-table" } from "@tanstack/react-table"
import { cva } from "class-variance-authority" import { cva } from "class-variance-authority"
import { AlertCircle, ArrowUpDown } from "lucide-react" import { AlertCircle, ArrowUpDown, RefreshCwIcon } from "lucide-react"
import * as React from "react" import * as React from "react"
import { CopyIconButton } from "../../components/copyIconButton" import { CopyIconButton } from "../../components/copyIconButton"
import { useMemo } from "react" import { useMemo } from "react"
import { LightweightCodeHighlighter } from "../../components/lightweightCodeHighlighter"
import { useRouter } from "next/navigation"
import { useToast } from "@/components/hooks/use-toast"
// @see: https://v0.app/chat/repo-indexing-status-uhjdDim8OUS // @see: https://v0.app/chat/repo-indexing-status-uhjdDim8OUS
@ -107,8 +110,14 @@ export const columns: ColumnDef<RepoIndexingJob>[] = [
<TooltipTrigger> <TooltipTrigger>
<AlertCircle className="h-4 w-4 text-destructive" /> <AlertCircle className="h-4 w-4 text-destructive" />
</TooltipTrigger> </TooltipTrigger>
<TooltipContent className="max-w-sm"> <TooltipContent className="max-w-[750px] max-h-96 overflow-scroll">
<p className="text-sm">{job.errorMessage}</p> <LightweightCodeHighlighter
language="text"
lineNumbers={true}
renderWhitespace={false}
>
{job.errorMessage}
</LightweightCodeHighlighter>
</TooltipContent> </TooltipContent>
</Tooltip> </Tooltip>
</TooltipProvider> </TooltipProvider>
@ -174,6 +183,8 @@ export const RepoJobsTable = ({ data }: { data: RepoIndexingJob[] }) => {
const [sorting, setSorting] = React.useState<SortingState>([{ id: "createdAt", desc: true }]) const [sorting, setSorting] = React.useState<SortingState>([{ id: "createdAt", desc: true }])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([]) const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({}) const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({})
const router = useRouter();
const { toast } = useToast();
const table = useReactTable({ const table = useReactTable({
data, data,
@ -238,6 +249,20 @@ export const RepoJobsTable = ({ data }: { data: RepoIndexingJob[] }) => {
<SelectItem value="CLEANUP">Cleanup</SelectItem> <SelectItem value="CLEANUP">Cleanup</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
<Button
variant="outline"
className="ml-auto"
onClick={() => {
router.refresh();
toast({
description: "Page refreshed",
});
}}
>
<RefreshCwIcon className="w-3 h-3" />
Refresh
</Button>
</div> </div>
<div className="rounded-md border"> <div className="rounded-md border">

View file

@ -28,11 +28,13 @@ import {
useReactTable, useReactTable,
} from "@tanstack/react-table" } from "@tanstack/react-table"
import { cva } from "class-variance-authority" import { cva } from "class-variance-authority"
import { ArrowUpDown, ExternalLink, MoreHorizontal } from "lucide-react" import { ArrowUpDown, ExternalLink, MoreHorizontal, RefreshCwIcon } from "lucide-react"
import Image from "next/image" import Image from "next/image"
import Link from "next/link" import Link from "next/link"
import { useMemo, useState } from "react" import { useMemo, useState } from "react"
import { getBrowsePath } from "../../browse/hooks/utils" import { getBrowsePath } from "../../browse/hooks/utils"
import { useRouter } from "next/navigation"
import { useToast } from "@/components/hooks/use-toast";
// @see: https://v0.app/chat/repo-indexing-status-uhjdDim8OUS // @see: https://v0.app/chat/repo-indexing-status-uhjdDim8OUS
@ -193,6 +195,8 @@ export const ReposTable = ({ data }: { data: Repo[] }) => {
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]) const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({}) const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})
const [rowSelection, setRowSelection] = useState({}) const [rowSelection, setRowSelection] = useState({})
const router = useRouter();
const { toast } = useToast();
const { const {
numCompleted, numCompleted,
@ -256,6 +260,19 @@ export const ReposTable = ({ data }: { data: Repo[] }) => {
<SelectItem value="null">No status ({numNoJobs})</SelectItem> <SelectItem value="null">No status ({numNoJobs})</SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>
<Button
variant="outline"
className="ml-auto"
onClick={() => {
router.refresh();
toast({
description: "Page refreshed",
});
}}
>
<RefreshCwIcon className="w-3 h-3" />
Refresh
</Button>
</div> </div>
<div className="rounded-md border"> <div className="rounded-md border">
<Table> <Table>