From d7d8ba886a9212b103bfb2727346bab0cb5907b0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 27 Sep 2025 23:03:48 +0000 Subject: [PATCH 1/2] Initial plan From f87f9fd480132c548b483ac2486f2708c3250475 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 27 Sep 2025 23:13:02 +0000 Subject: [PATCH 2/2] Add table sorting functionality to Pull Requests table Co-authored-by: ChrisTimperley <523560+ChrisTimperley@users.noreply.github.com> --- .../src/components/PullRequestsSection.tsx | 127 ++++++++++++++++-- 1 file changed, 117 insertions(+), 10 deletions(-) diff --git a/frontend/src/components/PullRequestsSection.tsx b/frontend/src/components/PullRequestsSection.tsx index 10740fc..2742ef0 100644 --- a/frontend/src/components/PullRequestsSection.tsx +++ b/frontend/src/components/PullRequestsSection.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState, useMemo } from 'react'; import { Card, CardContent, @@ -12,6 +12,7 @@ import { TableBody, Link, Chip, + TableSortLabel, } from '@mui/material'; import { Settings } from '@mui/icons-material'; import { PullRequest, Issue } from '../types'; @@ -34,6 +35,48 @@ export const PullRequestsSection: React.FC = ({ owner, repo, }) => { + const [sortBy, setSortBy] = useState('created_at'); + const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc'); + + // Sort pull requests based on current sort criteria + const sortedPullRequests = useMemo(() => { + return [...pullRequests].sort((a, b) => { + let aValue: any = a[sortBy]; + let bValue: any = b[sortBy]; + + // Handle special sorting cases for different data types + if (sortBy === 'created_at' || sortBy === 'closed_at' || sortBy === 'merged_at') { + aValue = aValue ? new Date(aValue).getTime() : 0; + bValue = bValue ? new Date(bValue).getTime() : 0; + } else if (sortBy === 'comments' || sortBy === 'additions' || sortBy === 'deletions') { + aValue = aValue ?? 0; + bValue = bValue ?? 0; + } else if (sortBy === 'reviewers') { + aValue = aValue?.length ?? 0; + bValue = bValue?.length ?? 0; + } else if (sortBy === 'linked_issues') { + aValue = aValue?.length ?? 0; + bValue = bValue?.length ?? 0; + } + + if (aValue < bValue) { + return sortDirection === 'asc' ? -1 : 1; + } + if (aValue > bValue) { + return sortDirection === 'asc' ? 1 : -1; + } + return 0; + }); + }, [pullRequests, sortBy, sortDirection]); + + const handleSort = (column: keyof PullRequest) => { + if (sortBy === column) { + setSortDirection(sortDirection === 'asc' ? 'desc' : 'asc'); + } else { + setSortBy(column); + setSortDirection('asc'); + } + }; return ( @@ -61,19 +104,83 @@ export const PullRequestsSection: React.FC = ({ - PR # - Title - Status - Author - Reviewer - Comments - Linked Issue - CI + + handleSort('number')} + > + PR # + + + + handleSort('title')} + > + Title + + + + handleSort('status')} + > + Status + + + + handleSort('author')} + > + Author + + + + handleSort('reviewers')} + > + Reviewer + + + + handleSort('comments')} + > + Comments + + + + handleSort('linked_issues')} + > + Linked Issue + + + + handleSort('ci_status')} + > + CI + + Lines Changed - {pullRequests.map((pr) => { + {sortedPullRequests.map((pr) => { // Use comments directly from PR data, or fallback to deriving from linked issues let comments = pr.comments ?? 0; let linkedIssueElement = ;