Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/components/DayPRsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { format, parseISO } from 'date-fns';
import type { CommitLog } from '../api';
import { LinkBox } from './common/linkBehavior';
import { STATUS_COLORS, TEXT_OPACITY, scrollbarSx } from '../theme';
import { minerPrPath } from '../utils';

interface DayPRsPanelProps {
date: string;
Expand Down Expand Up @@ -97,7 +98,10 @@ const DayPRsPanel: React.FC<DayPRsPanelProps> = ({ date, prs, username }) => {
{dayPRs.map((pr, idx) => {
const dotColor = prStateColor(pr);
const stateLabel = prStateLabel(pr);
const detailsHref = `/miners/pr?repo=${encodeURIComponent(pr.repository)}&number=${pr.pullRequestNumber}`;
const detailsHref = minerPrPath(
pr.repository,
pr.pullRequestNumber,
);
const timeLabel = pr.mergedAt
? format(new Date(pr.mergedAt), 'h:mm a')
: '';
Expand Down
9 changes: 6 additions & 3 deletions src/components/issues/IssueSubmissionsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import EmojiEventsIcon from '@mui/icons-material/EmojiEvents';
import { IssueSubmission } from '../../api/models/Issues';
import { STATUS_COLORS } from '../../theme';
import { formatDate } from '../../utils/format';
import { getGithubAvatarSrc } from '../../utils';
import { getGithubAvatarSrc, minerPrPath } from '../../utils';
import { LinkBox } from '../common/linkBehavior';
import {
DataTable,
Expand Down Expand Up @@ -223,7 +223,10 @@ const IssueSubmissionsTable: React.FC<IssueSubmissionsTableProps> = ({
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
{winnerSubmission && (
<LinkBox
href={`/miners/pr?repo=${encodeURIComponent(winnerSubmission.repositoryFullName)}&number=${winnerSubmission.number}`}
href={minerPrPath(
winnerSubmission.repositoryFullName,
winnerSubmission.number,
)}
linkState={linkState}
sx={{ textDecoration: 'none', display: 'block' }}
>
Expand Down Expand Up @@ -471,7 +474,7 @@ const IssueSubmissionsTable: React.FC<IssueSubmissionsTableProps> = ({
}
onRowClick={(submission) =>
navigate(
`/miners/pr?repo=${encodeURIComponent(submission.repositoryFullName)}&number=${submission.number}`,
minerPrPath(submission.repositoryFullName, submission.number),
{ state: linkState },
)
}
Expand Down
5 changes: 3 additions & 2 deletions src/components/layout/GlobalSearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import CloseIcon from '@mui/icons-material/Close';
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom';
import { useSearchResults } from '../../pages/search/searchData';
import { useLinkBehavior, linkResetSx } from '../common/linkBehavior';
import { minerPrPath, minerRepositoryPath } from '../../utils';

const QUICK_RESULT_LIMIT = 3;
const DROPDOWN_CLOSE_DELAY_MS = 150;
Expand Down Expand Up @@ -316,7 +317,7 @@ const GlobalSearchBar: React.FC = () => {
});
});
repositoryResults.forEach((repo) => {
const href = `/miners/repository?name=${encodeURIComponent(repo.fullName)}`;
const href = minerRepositoryPath(repo.fullName);
items.push({
key: `repo-${repo.fullName}`,
kind: 'repo',
Expand All @@ -327,7 +328,7 @@ const GlobalSearchBar: React.FC = () => {
});
});
prResults.forEach((pr) => {
const href = `/miners/pr?repo=${encodeURIComponent(pr.repository)}&number=${pr.pullRequestNumber}`;
const href = minerPrPath(pr.repository, pr.pullRequestNumber);
items.push({
key: `pr-${pr.repository}-${pr.pullRequestNumber}`,
kind: 'pr',
Expand Down
3 changes: 2 additions & 1 deletion src/components/miners/MinerOpenDiscoveryIssuesByRepo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
getRepositoryOwnerAvatarSrc,
getScoringWindowStartIso,
isOutsideScoringWindow,
minerPrPath,
paginateItems,
} from '../../utils';
import {
Expand Down Expand Up @@ -325,7 +326,7 @@ const MinerOpenDiscoveryIssuesByRepo: React.FC<
}
const repoForPr =
issue.solving_pr?.repo_full_name ?? issue.repo_full_name;
const prHref = `/miners/pr?repo=${encodeURIComponent(repoForPr)}&number=${prNumber}`;
const prHref = minerPrPath(repoForPr, prNumber);
return (
<a
href={prHref}
Expand Down
3 changes: 2 additions & 1 deletion src/components/miners/MinerPrScoreDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { usePullRequestDetails, type CommitLog } from '../../api';
import { STATUS_COLORS, tooltipSlotProps } from '../../theme';
import { parseNumber } from '../../utils/ExplorerUtils';
import { buildMergedPillDefs } from '../../utils/multiplierDefs';
import { minerPrPath } from '../../utils';

const tipProps = {
...tooltipSlotProps,
Expand Down Expand Up @@ -116,7 +117,7 @@ const MinerPrScoreDetail: React.FC<MinerPrScoreDetailProps> = ({
expanded,
}) => {
const prLinkProps = useLinkBehavior<HTMLAnchorElement>(
`/miners/pr?repo=${encodeURIComponent(pr.repository)}&number=${pr.pullRequestNumber}`,
minerPrPath(pr.repository, pr.pullRequestNumber),
);

const isMerged = !!pr.mergedAt;
Expand Down
3 changes: 2 additions & 1 deletion src/components/miners/MinerRepoStandingCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { MinerRepositoryEvaluation } from '../../api/models/Dashboard';
import { tooltipSlotProps } from '../../theme';
import { credibilityColor } from '../../utils/format';
import { getRepositoryOwnerAvatarSrc } from '../../utils/avatar';
import { minerRepositoryPath } from '../../utils';
import { linkResetSx, useLinkBehavior } from '../common/linkBehavior';

type ViewMode = 'prs' | 'issues';
Expand All @@ -19,7 +20,7 @@ const INACTIVE_OPACITY = 0.42;

/** Build the link to a repository's Miners tab. */
const repoMinersHref = (repositoryFullName: string): string =>
`/miners/repository?name=${encodeURIComponent(repositoryFullName)}&tab=miners`;
minerRepositoryPath(repositoryFullName, { tab: 'miners' });

/* ── Eligibility marker — dot + word, echoes leaderboard MinerCard ─── */
const EligibilityLabel: React.FC<{ eligible: boolean }> = ({ eligible }) => (
Expand Down
8 changes: 6 additions & 2 deletions src/components/prs/PRDetailsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ import theme, {
TEXT_OPACITY,
tooltipSlotProps,
} from '../../theme';
import { getRepositoryOwnerAvatarSrc, parseNumber } from '../../utils';
import {
getRepositoryOwnerAvatarSrc,
minerRepositoryPath,
parseNumber,
} from '../../utils';
import { buildMultiplierGrid } from '../../utils/multiplierDefs';
import PRTimeDecayChart from './PRTimeDecayChart';

Expand All @@ -38,7 +42,7 @@ const PRDetailsCard: React.FC<PRDetailsCardProps> = ({
usePullRequestDetails(repository, pullRequestNumber);

const repoLinkProps = useLinkBehavior<HTMLAnchorElement>(
`/miners/repository?name=${encodeURIComponent(repository)}`,
minerRepositoryPath(repository),
{ state: { backLabel: `Back to PR #${pullRequestNumber}` } },
);
if (isDetailsLoading) {
Expand Down
3 changes: 2 additions & 1 deletion src/components/prs/PRHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
formatDate,
formatUsdEstimate,
getRepositoryOwnerAvatarSrc,
minerRepositoryPath,
} from '../../utils';
import { type PullRequestDetails } from '../../api/models/Dashboard';
import { STATUS_COLORS } from '../../theme';
Expand All @@ -25,7 +26,7 @@ const PRHeader: React.FC<PRHeaderProps> = ({
}) => {
const [owner] = repository.split('/');
const repoLinkProps = useLinkBehavior<HTMLAnchorElement>(
`/miners/repository?name=${encodeURIComponent(repository)}`,
minerRepositoryPath(repository),
{ state: { backLabel: `Back to PR #${pullRequestNumber}` } },
);
const authorLinkProps = useLinkBehavior<HTMLAnchorElement>(
Expand Down
14 changes: 9 additions & 5 deletions src/components/repositories/RepositoryPRsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ import {
useWatchlist,
} from '../../hooks/useWatchlist';
import theme, { TEXT_OPACITY, scrollbarSx } from '../../theme';
import { filterPrs, getPrStatusCounts, type PrStatusFilter } from '../../utils';
import {
filterPrs,
getPrStatusCounts,
minerPrPath,
type PrStatusFilter,
} from '../../utils';
import { getRepositoryOwnerAvatarSrc } from '../../utils/avatar';
import { formatDate } from '../../utils/format';
import FilterButton from '../FilterButton';
Expand Down Expand Up @@ -188,10 +193,9 @@ const RepositoryPRsTable: React.FC<RepositoryPRsTableProps> = ({

const handleRowClick = useCallback(
(pr: CommitLog) => {
navigate(
`/miners/pr?repo=${encodeURIComponent(pr.repository)}&number=${pr.pullRequestNumber}`,
{ state: { backLabel: `Back to ${repositoryFullName}` } },
);
navigate(minerPrPath(pr.repository, pr.pullRequestNumber), {
state: { backLabel: `Back to ${repositoryFullName}` },
});
},
[navigate, repositoryFullName],
);
Expand Down
7 changes: 4 additions & 3 deletions src/pages/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
getGithubAvatarSrc,
getGithubUserAvatarSrcById,
getPrStatusLabel,
minerPrPath,
parseNumber,
} from '../utils';
import useDashboardData from './dashboard/useDashboardData';
Expand Down Expand Up @@ -266,9 +267,7 @@ const buildActivityRows = (prs: CommitLog[]): LandingActivityRow[] =>
title: pr.pullRequestTitle || `PR #${pr.pullRequestNumber}`,
repository: pr.repository,
author: pr.author || shortIdentity(pr.hotkey || 'unknown'),
href: `/miners/pr?repo=${encodeURIComponent(pr.repository)}&number=${
pr.pullRequestNumber
}`,
href: minerPrPath(pr.repository, pr.pullRequestNumber),
dateLabel: timestamp.dateLabel,
timeLabel: timestamp.timeLabel,
tone:
Expand Down Expand Up @@ -1723,6 +1722,8 @@ const TopActiveReposPanel: React.FC<{
return (
<LinkBox
key={`${row.repository}-${index}`}
// TODO: this route does not exist — should be minerRepositoryPath(row.repository) (/miners/repository?name=...).
// Left as-is to keep this PR a no-op extraction; fix in a follow-up.
href={`/repositories/details?repo=${encodeURIComponent(row.repository)}`}
linkState={{ backLabel: 'Back to Home' }}
sx={(theme) => ({
Expand Down
7 changes: 3 additions & 4 deletions src/pages/RepositoriesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { type CommitLog } from '../api/models/Dashboard';
import { getRepositoryOwnerAvatarSrc } from '../utils/avatar';
import { buildRepoDiscoveryRollupFromMiners } from '../utils/ExplorerUtils';
import { isMergedPr } from '../utils/prStatus';
import { minerPrPath, minerRepositoryPath } from '../utils';

const FONTS = { mono: '"JetBrains Mono", monospace' } as const;

Expand Down Expand Up @@ -129,10 +130,8 @@ const cardSx = (theme: Theme) => ({

// ── Page ────────────────────────────────────────────────────────────────────
const REPO_LINK_STATE = { backLabel: 'Back to Repositories' } as const;
const getRepoHref = (name: string) =>
`/miners/repository?name=${encodeURIComponent(name)}`;
const getPrHref = (name: string, number: number) =>
`/miners/pr?repo=${encodeURIComponent(name)}&number=${number}`;
const getRepoHref = (name: string) => minerRepositoryPath(name);
const getPrHref = (name: string, number: number) => minerPrPath(name, number);

const RepositoriesPage: React.FC = () => {
const registerRepoLink = useLinkBehavior<HTMLAnchorElement>(
Expand Down
6 changes: 3 additions & 3 deletions src/pages/WatchlistPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ import { filterPrs, type PrStatusFilter } from '../utils/prTable';
import { getIssueStatusMeta } from '../utils/issueStatus';
import { formatDate, formatTokenAmount, formatWeight } from '../utils/format';
import { getRepositoryOwnerAvatarSrc } from '../utils/avatar';
import { minerPrPath, minerRepositoryPath } from '../utils';
import theme, {
CHART_COLORS,
LABEL_COLORS,
Expand Down Expand Up @@ -1149,8 +1150,7 @@ const repoHeaderStack = (
</Box>
);

const getRepoHref = (repo: Repository) =>
`/miners/repository?name=${encodeURIComponent(repo.fullName)}`;
const getRepoHref = (repo: Repository) => minerRepositoryPath(repo.fullName);

const repoColumns: DataTableColumn<WatchedRepoStats, RepoSortKey>[] = [
{
Expand Down Expand Up @@ -3038,7 +3038,7 @@ const PRsViewModeToggle: React.FC<{
};

const getPrHref = (pr: CommitLog) =>
`/miners/pr?repo=${encodeURIComponent(pr.repository)}&number=${pr.pullRequestNumber}`;
minerPrPath(pr.repository, pr.pullRequestNumber);

const PRCard: React.FC<{
pr: CommitLog;
Expand Down
11 changes: 3 additions & 8 deletions src/pages/dashboard/views/DashboardFeaturedWork.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
sectionContainerSx,
sectionTitleSx,
} from './featuredWorkStyles';
import { minerPrPath, minerRepositoryPath } from '../../../utils';

interface DashboardFeaturedWorkProps {
items: FeaturedWorkRepo[];
Expand All @@ -24,12 +25,6 @@ const FEATURED_WORK_TITLE = 'Featured Work';
const MAX_COLUMNS_SM = 2;
const MAX_COLUMNS_LG = 3;

const buildPrDetailUrl = (repo: string, prNumber: number): string =>
`/miners/pr?repo=${encodeURIComponent(repo)}&number=${encodeURIComponent(String(prNumber))}`;

const buildRepoDetailUrl = (repo: string): string =>
`/miners/repository?name=${encodeURIComponent(repo)}`;

const computeGridColumns = (
itemCount: number,
): { xs: string; sm: string; lg: string } => ({
Expand All @@ -48,14 +43,14 @@ const DashboardFeaturedWorkSection: React.FC<DashboardFeaturedWorkProps> = ({

const navigateToRepo: NavigateToRepoFn = useCallback(
(repoName: string): void => {
navigate(buildRepoDetailUrl(repoName));
navigate(minerRepositoryPath(repoName));
},
[navigate],
);

const navigateToPr: NavigateToPrFn = useCallback(
(repoName: string, pr: FeaturedWorkPr): void => {
navigate(buildPrDetailUrl(repoName, pr.prNumber));
navigate(minerPrPath(repoName, pr.prNumber));
},
[navigate],
);
Expand Down
3 changes: 3 additions & 0 deletions src/pages/dashboard/views/LiveCommitLog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ const CommitLogItem: React.FC<{

const content = (
<LinkBox
// TODO: convert to minerPrPath(entry.repository, entry.pullRequestNumber).
// Left inline here to preserve current byte-level URL (repository is not encoded
// today, so swapping in the helper would change the URL string); fix in a follow-up.
href={`/miners/pr?repo=${entry.repository}&number=${entry.pullRequestNumber}`}
linkState={{ backLabel: 'Back to Dashboard' }}
ref={innerRef}
Expand Down
5 changes: 3 additions & 2 deletions src/pages/search/SearchPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import MinerTab from './MinerTab';
import PullRequestsTab from './PullRequestsTab';
import RepositoryTab from './RepositoryTab';
import { MIN_SEARCH_QUERY_LENGTH, useSearchResults } from './searchData';
import { minerPrPath, minerRepositoryPath } from '../../utils';

const ROWS_PER_PAGE_OPTIONS = [10, 25, 50];
const SEARCH_TABS = ['miners', 'repositories', 'prs', 'issues'] as const;
Expand Down Expand Up @@ -169,10 +170,10 @@ const SearchPage: React.FC = () => {
`/miners/details?githubId=${encodeURIComponent(miner.githubId)}`;

const getRepositoryHref = (repo: { fullName: string }) =>
`/miners/repository?name=${encodeURIComponent(repo.fullName)}`;
minerRepositoryPath(repo.fullName);

const getPrHref = (pr: { repository: string; pullRequestNumber: number }) =>
`/miners/pr?repo=${encodeURIComponent(pr.repository)}&number=${pr.pullRequestNumber}`;
minerPrPath(pr.repository, pr.pullRequestNumber);

const getIssueHref = (issue: { id: number }) =>
`/bounties/details?id=${issue.id}`;
Expand Down
1 change: 1 addition & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export * from './multiplierDefs';
export * from './watchlistSort';
export * from './avatar';
export * from './githubRepoUrl';
export * from './paths';
13 changes: 13 additions & 0 deletions src/utils/paths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const minerPrPath = (
repository: string,
pullRequestNumber: number | string,
): string =>
`/miners/pr?repo=${encodeURIComponent(repository)}&number=${pullRequestNumber}`;

export const minerRepositoryPath = (
repositoryFullName: string,
options?: { tab?: string },
): string => {
const base = `/miners/repository?name=${encodeURIComponent(repositoryFullName)}`;
return options?.tab ? `${base}&tab=${options.tab}` : base;
};
Loading