@@ -17,15 +17,13 @@ import { SINGLE_TENANT_ORG_DOMAIN } from "@/lib/constants"
1717import { cn , getCodeHostCommitUrl , getCodeHostIcon , getCodeHostInfoForRepo , getRepoImageSrc } from "@/lib/utils"
1818import {
1919 type ColumnDef ,
20- type SortingState ,
2120 type VisibilityState ,
2221 flexRender ,
2322 getCoreRowModel ,
24- getSortedRowModel ,
2523 useReactTable ,
2624} from "@tanstack/react-table"
2725import { cva } from "class-variance-authority"
28- import { ArrowUpDown , ExternalLink , Loader2 , MoreHorizontal , RefreshCwIcon } from "lucide-react"
26+ import { ArrowDown , ArrowUp , ArrowUpDown , ExternalLink , Loader2 , MoreHorizontal , RefreshCwIcon } from "lucide-react"
2927import Image from "next/image"
3028import Link from "next/link"
3129import { useEffect , useRef , useState } from "react"
@@ -82,15 +80,29 @@ const getStatusBadge = (status: Repo["latestJobStatus"]) => {
8280 return < Badge className = { statusBadgeVariants ( { status } ) } > { labels [ status ] } </ Badge >
8381}
8482
85- export const columns : ColumnDef < Repo > [ ] = [
83+ interface ColumnsContext {
84+ onSortChange : ( sortBy : string ) => void ;
85+ currentSortBy ?: string ;
86+ currentSortOrder : string ;
87+ }
88+
89+ export const getColumns = ( context : ColumnsContext ) : ColumnDef < Repo > [ ] => [
8690 {
8791 accessorKey : "displayName" ,
8892 size : 400 ,
89- header : ( { column } ) => {
93+ header : ( ) => {
94+ const isActive = context . currentSortBy === 'displayName' ;
95+ const Icon = isActive
96+ ? ( context . currentSortOrder === 'asc' ? ArrowUp : ArrowDown )
97+ : ArrowUpDown ;
98+
9099 return (
91- < Button variant = "ghost" onClick = { ( ) => column . toggleSorting ( column . getIsSorted ( ) === "asc" ) } >
100+ < Button
101+ variant = "ghost"
102+ onClick = { ( ) => context . onSortChange ( 'displayName' ) }
103+ >
92104 Repository
93- < ArrowUpDown className = "ml-2 h-4 w-4" />
105+ < Icon className = "ml-2 h-4 w-4" />
94106 </ Button >
95107 )
96108 } ,
@@ -157,14 +169,19 @@ export const columns: ColumnDef<Repo>[] = [
157169 {
158170 accessorKey : "indexedAt" ,
159171 size : 200 ,
160- header : ( { column } ) => {
172+ header : ( ) => {
173+ const isActive = context . currentSortBy === 'indexedAt' ;
174+ const Icon = isActive
175+ ? ( context . currentSortOrder === 'asc' ? ArrowUp : ArrowDown )
176+ : ArrowUpDown ;
177+
161178 return (
162179 < Button
163180 variant = "ghost"
164- onClick = { ( ) => column . toggleSorting ( column . getIsSorted ( ) === "asc" ) }
181+ onClick = { ( ) => context . onSortChange ( 'indexedAt' ) }
165182 >
166183 Last synced
167- < ArrowUpDown className = "ml-2 h-4 w-4" />
184+ < Icon className = "ml-2 h-4 w-4" />
168185 </ Button >
169186 )
170187 } ,
@@ -276,6 +293,15 @@ interface ReposTableProps {
276293 totalCount : number ;
277294 initialSearch : string ;
278295 initialStatus : string ;
296+ initialSortBy ?: string ;
297+ initialSortOrder : string ;
298+ stats : {
299+ numCompleted : number
300+ numFailed : number
301+ numPending : number
302+ numInProgress : number
303+ numNoJobs : number
304+ }
279305}
280306
281307export const ReposTable = ( {
@@ -285,8 +311,10 @@ export const ReposTable = ({
285311 totalCount,
286312 initialSearch,
287313 initialStatus,
314+ initialSortBy,
315+ initialSortOrder,
316+ stats,
288317} : ReposTableProps ) => {
289- const [ sorting , setSorting ] = useState < SortingState > ( [ ] )
290318 const [ columnVisibility , setColumnVisibility ] = useState < VisibilityState > ( { } )
291319 const [ rowSelection , setRowSelection ] = useState ( { } )
292320 const [ searchValue , setSearchValue ] = useState ( initialSearch )
@@ -336,20 +364,40 @@ export const ReposTable = ({
336364 router . replace ( `${ pathname } ?${ params . toString ( ) } ` ) ;
337365 } ;
338366
367+ const handleSortChange = ( sortBy : string ) => {
368+ const params = new URLSearchParams ( searchParams . toString ( ) ) ;
369+
370+ // Toggle sort order if clicking the same column
371+ if ( initialSortBy === sortBy ) {
372+ const newOrder = initialSortOrder === 'asc' ? 'desc' : 'asc' ;
373+ params . set ( 'sortOrder' , newOrder ) ;
374+ } else {
375+ // Default to ascending when changing columns
376+ params . set ( 'sortBy' , sortBy ) ;
377+ params . set ( 'sortOrder' , 'asc' ) ;
378+ }
379+
380+ params . set ( 'page' , '1' ) ; // Reset to page 1 on sort change
381+ router . replace ( `${ pathname } ?${ params . toString ( ) } ` ) ;
382+ } ;
383+
339384 const totalPages = Math . ceil ( totalCount / pageSize ) ;
340385
386+ const columns = getColumns ( {
387+ onSortChange : handleSortChange ,
388+ currentSortBy : initialSortBy ,
389+ currentSortOrder : initialSortOrder ,
390+ } ) ;
391+
341392 const table = useReactTable ( {
342393 data,
343394 columns,
344- onSortingChange : setSorting ,
345395 getCoreRowModel : getCoreRowModel ( ) ,
346- getSortedRowModel : getSortedRowModel ( ) ,
347396 onColumnVisibilityChange : setColumnVisibility ,
348397 onRowSelectionChange : setRowSelection ,
349398 columnResizeMode : 'onChange' ,
350399 enableColumnResizing : false ,
351400 state : {
352- sorting,
353401 columnVisibility,
354402 rowSelection,
355403 } ,
@@ -381,11 +429,11 @@ export const ReposTable = ({
381429 </ SelectTrigger >
382430 < SelectContent >
383431 < SelectItem value = "all" > Filter by status</ SelectItem >
384- < SelectItem value = "COMPLETED" > Completed</ SelectItem >
385- < SelectItem value = "IN_PROGRESS" > In progress</ SelectItem >
386- < SelectItem value = "PENDING" > Pending</ SelectItem >
387- < SelectItem value = "FAILED" > Failed</ SelectItem >
388- < SelectItem value = "null " > No status</ SelectItem >
432+ < SelectItem value = "COMPLETED" > Completed ( { stats . numCompleted } ) </ SelectItem >
433+ < SelectItem value = "IN_PROGRESS" > In progress ( { stats . numInProgress } ) </ SelectItem >
434+ < SelectItem value = "PENDING" > Pending ( { stats . numPending } ) </ SelectItem >
435+ < SelectItem value = "FAILED" > Failed ( { stats . numFailed } ) </ SelectItem >
436+ < SelectItem value = "none " > No status ( { stats . numNoJobs } ) </ SelectItem >
389437 </ SelectContent >
390438 </ Select >
391439 < Button
0 commit comments