mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 12:25:22 +00:00
fix build
This commit is contained in:
parent
5a670bfdb9
commit
2b51f96550
1 changed files with 0 additions and 208 deletions
|
|
@ -1,208 +0,0 @@
|
||||||
"use client"
|
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button"
|
|
||||||
import type { ColumnDef } from "@tanstack/react-table"
|
|
||||||
import { ArrowUpDown, Clock, Loader2, CheckCircle2, Check, ListFilter } from "lucide-react"
|
|
||||||
import Image from "next/image"
|
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"
|
|
||||||
import { cn, getRepoImageSrc } from "@/lib/utils"
|
|
||||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
|
|
||||||
import Link from "next/link"
|
|
||||||
import { getBrowsePath } from "../browse/hooks/utils"
|
|
||||||
|
|
||||||
export type RepoStatus = 'syncing' | 'indexed' | 'not-indexed';
|
|
||||||
|
|
||||||
export type RepositoryColumnInfo = {
|
|
||||||
repoId: number
|
|
||||||
repoName: string;
|
|
||||||
repoDisplayName: string
|
|
||||||
imageUrl?: string
|
|
||||||
status: RepoStatus
|
|
||||||
lastIndexed: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const statusLabels: Record<RepoStatus, string> = {
|
|
||||||
'syncing': "Syncing",
|
|
||||||
'indexed': "Indexed",
|
|
||||||
'not-indexed': "Pending",
|
|
||||||
};
|
|
||||||
|
|
||||||
const StatusIndicator = ({ status }: { status: RepoStatus }) => {
|
|
||||||
let icon = null
|
|
||||||
let description = ""
|
|
||||||
let className = ""
|
|
||||||
|
|
||||||
switch (status) {
|
|
||||||
case 'syncing':
|
|
||||||
icon = <Loader2 className="h-3.5 w-3.5 animate-spin" />
|
|
||||||
description = "Repository is currently syncing"
|
|
||||||
className = "text-blue-600 bg-blue-50 dark:bg-blue-900/20 dark:text-blue-400"
|
|
||||||
break
|
|
||||||
case 'indexed':
|
|
||||||
icon = <CheckCircle2 className="h-3.5 w-3.5" />
|
|
||||||
description = "Repository has been successfully indexed and is up to date"
|
|
||||||
className = "text-green-600 bg-green-50 dark:bg-green-900/20 dark:text-green-400"
|
|
||||||
break
|
|
||||||
case 'not-indexed':
|
|
||||||
icon = <Clock className="h-3.5 w-3.5" />
|
|
||||||
description = "Repository is pending initial sync"
|
|
||||||
className = "text-yellow-600 bg-yellow-50 dark:bg-yellow-900/20 dark:text-yellow-400"
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TooltipProvider>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<div
|
|
||||||
className={cn("flex items-center gap-1.5 text-xs font-medium px-2.5 py-0.5 rounded-full w-fit", className)}
|
|
||||||
>
|
|
||||||
{icon}
|
|
||||||
{statusLabels[status]}
|
|
||||||
</div>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
<p className="text-sm">{description}</p>
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const columns = (domain: string): ColumnDef<RepositoryColumnInfo>[] => [
|
|
||||||
{
|
|
||||||
accessorKey: "repoDisplayName",
|
|
||||||
header: 'Repository',
|
|
||||||
size: 500,
|
|
||||||
cell: ({ row: { original: { repoId, repoName, repoDisplayName, imageUrl } } }) => {
|
|
||||||
return (
|
|
||||||
<div className="flex flex-row items-center gap-3 py-2">
|
|
||||||
<div className="relative h-8 w-8 overflow-hidden rounded-md border bg-muted">
|
|
||||||
{imageUrl ? (
|
|
||||||
<Image
|
|
||||||
src={getRepoImageSrc(imageUrl, repoId, domain) || "/placeholder.svg"}
|
|
||||||
alt={`${repoDisplayName} logo`}
|
|
||||||
width={32}
|
|
||||||
height={32}
|
|
||||||
className="object-cover"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className="flex h-full w-full items-center justify-center bg-muted text-xs font-medium uppercase text-muted-foreground">
|
|
||||||
{repoDisplayName.charAt(0)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Link
|
|
||||||
className={"font-medium text-primary hover:underline cursor-pointer"}
|
|
||||||
href={getBrowsePath({
|
|
||||||
repoName: repoName,
|
|
||||||
path: '/',
|
|
||||||
pathType: 'tree',
|
|
||||||
domain
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{repoDisplayName.length > 40 ? `${repoDisplayName.slice(0, 40)}...` : repoDisplayName}
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: "status",
|
|
||||||
size: 150,
|
|
||||||
header: ({ column }) => {
|
|
||||||
const uniqueLabels = Object.values(statusLabels);
|
|
||||||
const currentFilter = column.getFilterValue() as string | undefined;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="w-[150px]">
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenuTrigger asChild>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
className={cn(
|
|
||||||
"px-0 font-medium hover:bg-transparent focus:bg-transparent active:bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0",
|
|
||||||
currentFilter ? "text-primary hover:text-primary" : "text-muted-foreground hover:text-muted-foreground"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
Status
|
|
||||||
<ListFilter className={cn(
|
|
||||||
"ml-2 h-3.5 w-3.5",
|
|
||||||
currentFilter ? "text-primary" : "text-muted-foreground"
|
|
||||||
)} />
|
|
||||||
{currentFilter && (
|
|
||||||
<div className="absolute -top-1 -right-1 w-2.5 h-2.5 rounded-full bg-primary animate-pulse" />
|
|
||||||
)}
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent align="start">
|
|
||||||
<DropdownMenuItem onClick={() => column.setFilterValue(undefined)}>
|
|
||||||
<Check className={cn("mr-2 h-4 w-4", !column.getFilterValue() ? "opacity-100" : "opacity-0")} />
|
|
||||||
All
|
|
||||||
</DropdownMenuItem>
|
|
||||||
{uniqueLabels.map((label) => (
|
|
||||||
<DropdownMenuItem key={label} onClick={() => column.setFilterValue(label)}>
|
|
||||||
<Check className={cn("mr-2 h-4 w-4", column.getFilterValue() === label ? "opacity-100" : "opacity-0")} />
|
|
||||||
{label}
|
|
||||||
</DropdownMenuItem>
|
|
||||||
))}
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
cell: ({ row }) => {
|
|
||||||
return <StatusIndicator status={row.original.status} />
|
|
||||||
},
|
|
||||||
filterFn: (row, id, value) => {
|
|
||||||
if (value === undefined) return true;
|
|
||||||
|
|
||||||
const status = row.getValue(id) as RepoStatus;
|
|
||||||
return statusLabels[status] === value;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: "lastIndexed",
|
|
||||||
size: 150,
|
|
||||||
header: ({ column }) => (
|
|
||||||
<div className="w-[150px]">
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
|
||||||
className="px-0 font-medium hover:bg-transparent focus:bg-transparent active:bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0"
|
|
||||||
>
|
|
||||||
Last Synced
|
|
||||||
<ArrowUpDown className="ml-2 h-3.5 w-3.5" />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
cell: ({ row }) => {
|
|
||||||
if (!row.original.lastIndexed) {
|
|
||||||
return <div className="text-muted-foreground">Never</div>;
|
|
||||||
}
|
|
||||||
const date = new Date(row.original.lastIndexed)
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className="font-medium">
|
|
||||||
{date.toLocaleDateString("en-US", {
|
|
||||||
month: "short",
|
|
||||||
day: "numeric",
|
|
||||||
year: "numeric",
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<div className="text-xs text-muted-foreground">
|
|
||||||
{date
|
|
||||||
.toLocaleTimeString("en-US", {
|
|
||||||
hour: "2-digit",
|
|
||||||
minute: "2-digit",
|
|
||||||
hour12: false,
|
|
||||||
})
|
|
||||||
.toLowerCase()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
Loading…
Reference in a new issue