diff --git a/src/components/miners/MinerOpenDiscoveryIssuesByRepo.tsx b/src/components/miners/MinerOpenDiscoveryIssuesByRepo.tsx index 7951ddbc..99d2ac28 100644 --- a/src/components/miners/MinerOpenDiscoveryIssuesByRepo.tsx +++ b/src/components/miners/MinerOpenDiscoveryIssuesByRepo.tsx @@ -18,9 +18,11 @@ import type { MinerIssue } from '../../api/models/Dashboard'; import { getRepositoryOwnerAvatarSrc, getScoringWindowStartIso, + isIssueStatusFilter, isOutsideScoringWindow, minerPrPath, paginateItems, + type IssueStatusFilter, } from '../../utils'; import { DataTable, @@ -32,19 +34,11 @@ import TablePagination from '../common/TablePagination'; import { tooltipSlotProps } from '../../theme'; import { useDataTableParams } from '../../hooks/useDataTableParams'; -type IssueStatusFilter = 'all' | 'open' | 'solved' | 'closed'; type IssueSortField = 'number' | 'repository' | 'date'; type SortDir = 'asc' | 'desc'; const PAGE_SIZE = 20; -const ISSUE_STATUS_FILTERS: readonly IssueStatusFilter[] = [ - 'all', - 'open', - 'solved', - 'closed', -]; - const DEFAULT_SORT_DIR: Record = { number: 'desc', repository: 'asc', @@ -57,11 +51,6 @@ const isSolvedIssue = (i: MinerIssue) => const isClosedIssue = (i: MinerIssue) => i.state === 'CLOSED' && !i.solving_pr?.merged_at; -const isIssueStatusFilter = ( - value: string | null, -): value is IssueStatusFilter => - value !== null && (ISSUE_STATUS_FILTERS as readonly string[]).includes(value); - const filterIssues = ( issues: MinerIssue[], { diff --git a/src/components/miners/MinerPRsTable.tsx b/src/components/miners/MinerPRsTable.tsx index 983a7df8..4ead4a67 100644 --- a/src/components/miners/MinerPRsTable.tsx +++ b/src/components/miners/MinerPRsTable.tsx @@ -30,6 +30,7 @@ import { getRepositoryOwnerAvatarSrc, getPrStatusCounts, isOutsideScoringWindow, + isPrStatusFilter, type PrStatusFilter, } from '../../utils'; import { @@ -65,13 +66,6 @@ type PrSortField = | 'watch'; type SortDir = 'asc' | 'desc'; -const PR_STATUS_FILTERS: readonly PrStatusFilter[] = [ - 'all', - 'open', - 'merged', - 'closed', -]; - // Direction applied when a user first clicks a column header — string // columns feel natural ascending, numeric/date columns descending. const DEFAULT_SORT_DIR: Record = { @@ -105,9 +99,6 @@ const getScoreTooltip = (pr: CommitLog): string | null => { return parts.join(' · '); }; -const isPrStatusFilter = (value: string | null): value is PrStatusFilter => - value !== null && (PR_STATUS_FILTERS as readonly string[]).includes(value); - // Stable per-PR key — shared by the DataTable row key and the expanded-row // tracking set so the two never drift. const prRowKey = (pr: CommitLog): string => diff --git a/src/components/repositories/RepositoryPRsTable.tsx b/src/components/repositories/RepositoryPRsTable.tsx index 4a04c02b..60f729ee 100644 --- a/src/components/repositories/RepositoryPRsTable.tsx +++ b/src/components/repositories/RepositoryPRsTable.tsx @@ -33,6 +33,7 @@ import theme, { TEXT_OPACITY, scrollbarSx } from '../../theme'; import { filterPrs, getPrStatusCounts, + isPrStatusFilter, minerPrPath, type PrStatusFilter, } from '../../utils'; @@ -69,9 +70,6 @@ interface RepositoryPRsTableProps { state?: 'open' | 'closed' | 'merged' | 'all'; } -const isPrStatusFilter = (v: unknown): v is PrStatusFilter => - v === 'all' || v === 'open' || v === 'merged' || v === 'closed'; - const PR_PAGE_SIZE = 20; const RepositoryPRsTable: React.FC = ({ diff --git a/src/pages/WatchlistPage.tsx b/src/pages/WatchlistPage.tsx index 245f6231..aa903ef7 100644 --- a/src/pages/WatchlistPage.tsx +++ b/src/pages/WatchlistPage.tsx @@ -102,9 +102,11 @@ import { usePrSourceFilter } from '../hooks/usePrSourceFilter'; import { isMergedPr, isClosedUnmergedPr, + isPrStatusFilter, getPrStatusCounts, + type PrStatusFilter, } from '../utils/prStatus'; -import { filterPrs, type PrStatusFilter } from '../utils/prTable'; +import { filterPrs } from '../utils/prTable'; import { getIssueStatusMeta } from '../utils/issueStatus'; import { formatDate, formatTokenAmount, formatWeight } from '../utils/format'; import { getRepositoryOwnerAvatarSrc } from '../utils/avatar'; @@ -1030,9 +1032,6 @@ type WatchedRepoStats = Repository & { discoveryContributors: Set; }; -const isPrStatusFilterStored = (v: unknown): v is PrStatusFilter => - v === 'all' || v === 'open' || v === 'merged' || v === 'closed'; - type RepoSortKey = | 'name' | 'weight' @@ -3238,7 +3237,7 @@ const PRsList: React.FC<{ itemKeys: string[] }> = ({ itemKeys }) => { const [statusFilter, setStatusFilter] = useSessionStoredState( 'watchlist:prs:statusFilter', 'all', - isPrStatusFilterStored, + isPrStatusFilter, ); const [viewMode, setViewMode] = useWatchlistViewMode(); const [page, setPage] = useState(0); diff --git a/src/utils/issueStatus.ts b/src/utils/issueStatus.ts index 9dcd274a..af72c51f 100644 --- a/src/utils/issueStatus.ts +++ b/src/utils/issueStatus.ts @@ -1,6 +1,21 @@ import { alpha } from '@mui/material/styles'; import { STATUS_COLORS } from '../theme'; +export type IssueStatusFilter = 'all' | 'open' | 'solved' | 'closed'; + +export const ISSUE_STATUS_FILTERS: readonly IssueStatusFilter[] = [ + 'all', + 'open', + 'solved', + 'closed', +]; + +export const isIssueStatusFilter = ( + value: unknown, +): value is IssueStatusFilter => + typeof value === 'string' && + (ISSUE_STATUS_FILTERS as readonly string[]).includes(value); + interface IssueStatusMeta { bgColor: string; borderColor: string; diff --git a/src/utils/prStatus.ts b/src/utils/prStatus.ts index ac927563..362054ba 100644 --- a/src/utils/prStatus.ts +++ b/src/utils/prStatus.ts @@ -3,6 +3,19 @@ interface PrStatusLike { prState?: string | null; } +export type PrStatusFilter = 'all' | 'open' | 'merged' | 'closed'; + +export const PR_STATUS_FILTERS: readonly PrStatusFilter[] = [ + 'all', + 'open', + 'merged', + 'closed', +]; + +export const isPrStatusFilter = (value: unknown): value is PrStatusFilter => + typeof value === 'string' && + (PR_STATUS_FILTERS as readonly string[]).includes(value); + export const isOpenPr = (pr: PrStatusLike): boolean => pr.prState === 'OPEN' || (!pr.prState && !pr.mergedAt); diff --git a/src/utils/prTable.ts b/src/utils/prTable.ts index 1b82afba..3a0ecbbf 100644 --- a/src/utils/prTable.ts +++ b/src/utils/prTable.ts @@ -1,5 +1,10 @@ import { type CommitLog } from '../api'; -import { isClosedUnmergedPr, isMergedPr, isOpenPr } from './prStatus'; +import { + isClosedUnmergedPr, + isMergedPr, + isOpenPr, + type PrStatusFilter, +} from './prStatus'; /** Substring match against merged timestamp (ISO, locale date/time, year). */ const mergedAtMatchesSearch = ( @@ -16,8 +21,6 @@ const mergedAtMatchesSearch = ( return false; }; -export type PrStatusFilter = 'all' | 'open' | 'merged' | 'closed'; - interface FilterPrsOptions { author?: string | null; includeNumber?: boolean;