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
13 changes: 13 additions & 0 deletions frontend/__tests__/unit/components/Card.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ jest.mock('react-icons/fa6', () => ({
FaXTwitter: (props: React.SVGProps<SVGSVGElement>) => (
<svg data-testid="x-twitter-icon" {...props} />
),
FaCodePullRequest: (props: React.SVGProps<SVGSVGElement>) => (
<svg data-testid="pull-request-icon" {...props} />
),
}))

jest.mock('react-icons/fa', () => ({
Expand Down Expand Up @@ -730,4 +733,14 @@ describe('Card', () => {
expect(socialLink).toHaveAttribute('aria-label', 'Social media link')
})
})
it('renders PR count badge when pullRequestCount is provided', () => {
render(<Card {...baseProps} pullRequestCount={3} />)
expect(screen.getByText('3 open PRs')).toBeInTheDocument()
expect(screen.getByTestId('pull-request-icon')).toBeInTheDocument()
})

it('does not render PR count badge when pullRequestCount is 0', () => {
render(<Card {...baseProps} pullRequestCount={0} />)
expect(screen.queryByTestId('pull-request-icon')).not.toBeInTheDocument()
})
})
13 changes: 13 additions & 0 deletions frontend/__tests__/unit/components/IssuesTable.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,19 @@ describe('<IssuesTable />', () => {
const headers = within(table).getAllByRole('columnheader')
expect(headers).toHaveLength(3)
})
it('calculates correct column count with PR count column', () => {
render(<IssuesTable issues={[]} showAssignee={true} showPullRequestCount={true} />)
const table = screen.getByRole('table')
const headers = within(table).getAllByRole('columnheader')
expect(headers).toHaveLength(5)
Comment thread
pranav-871 marked this conversation as resolved.
})

it('calculates correct column count without assignee but with PR count column', () => {
render(<IssuesTable issues={[]} showAssignee={false} showPullRequestCount={true} />)
const table = screen.getByRole('table')
const headers = within(table).getAllByRole('columnheader')
expect(headers).toHaveLength(4)
})
})

describe('Default Props', () => {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/app/contribute/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const ContributePage = () => {
labels={issue.labels}
projectLink={issue.projectUrl}
projectName={issue.projectName}
pullRequestCount={issue.pullRequests?.length}
summary={issue.summary ?? ''}
title={issue.title}
url={issue.url}
Expand Down
12 changes: 11 additions & 1 deletion frontend/src/components/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Tooltip } from '@heroui/tooltip'
import Link from 'next/link'
import { FaCalendar } from 'react-icons/fa6'
import { FaCalendar, FaCodePullRequest } from 'react-icons/fa6'
import { IconWrapper } from 'wrappers/IconWrapper'
import type { CardProps } from 'types/card'
import { ICONS } from 'utils/data'
Expand All @@ -20,6 +20,7 @@ const Card = ({
level,
projectLink,
projectName,
pullRequestCount,
social,
summary,
timeline,
Expand Down Expand Up @@ -137,6 +138,15 @@ const Card = ({
<LabelList entityKey={`${cardKey}-labels`} labels={labels} maxVisible={5} />
</div>
)}
{/* PR Count Badge */}
{!!pullRequestCount && (
<div className="flex items-center">
<span className="inline-flex items-center gap-1 rounded-full bg-blue-100 px-2 py-0.5 text-xs font-medium text-blue-700 dark:bg-blue-900/30 dark:text-blue-300">
<FaCodePullRequest className="h-3 w-3" />
{pullRequestCount} open PR{pullRequestCount === 1 ? '' : 's'}
</span>
</div>
)}
{/* Contributors section */}
<div className="flex flex-wrap items-center gap-2">
{topContributors?.map((contributor, index) => (
Expand Down
26 changes: 26 additions & 0 deletions frontend/src/components/IssuesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Image from 'next/image'
import { useRouter } from 'next/navigation'
import type React from 'react'

import { FaCodePullRequest } from 'react-icons/fa6'
import { LabelList } from 'components/LabelList'

export type IssueRow = {
Expand All @@ -17,12 +18,14 @@ export type IssueRow = {
assignees?: Array<{ avatarUrl: string; login: string; name: string }>
url?: string
deadline?: string | null
pullRequestCount?: number
}

interface IssuesTableProps {
issues: IssueRow[]
showAssignee?: boolean
showDeadline?: boolean
showPullRequestCount?: boolean
onIssueClick?: (issueNumber: number) => void
issueUrl?: (issueNumber: number) => string
maxVisibleLabels?: number
Expand All @@ -35,6 +38,7 @@ const IssuesTable: React.FC<IssuesTableProps> = ({
issues,
showAssignee = true,
showDeadline = false,
showPullRequestCount = false,
onIssueClick,
issueUrl,
maxVisibleLabels = MAX_VISIBLE_LABELS,
Expand Down Expand Up @@ -73,6 +77,7 @@ const IssuesTable: React.FC<IssuesTableProps> = ({
let count = 3 // Title, Status, Labels
if (showAssignee) count++
if (showDeadline) count++
if (showPullRequestCount) count++
return count
}

Expand Down Expand Up @@ -145,6 +150,14 @@ const IssuesTable: React.FC<IssuesTableProps> = ({
Deadline
</th>
)}
{showPullRequestCount && (
Comment thread
pranav-871 marked this conversation as resolved.
<th
scope="col"
className="px-6 py-3 text-center text-xs font-medium tracking-wider text-gray-500 uppercase dark:text-gray-400"
>
Open PRs
</th>
)}
</tr>
</thead>
<tbody className="divide-y divide-gray-200 bg-white dark:divide-gray-700 dark:bg-[#1f2327]">
Expand Down Expand Up @@ -191,6 +204,19 @@ const IssuesTable: React.FC<IssuesTableProps> = ({
className="gap-1 lg:gap-2"
/>
</td>
{/* PR Count */}
{showPullRequestCount && (
<td className="block pb-3 text-center lg:table-cell lg:px-6 lg:py-4">
{issue.pullRequestCount !== undefined && issue.pullRequestCount > 0 ? (
<span className="inline-flex items-center gap-1 rounded-full bg-blue-100 px-2 py-0.5 text-xs font-medium text-blue-700 dark:bg-blue-900/30 dark:text-blue-300">
<FaCodePullRequest className="h-3 w-3" />
{issue.pullRequestCount}
</span>
) : (
<span className="text-xs text-gray-400">—</span>
)}
</td>
)}
Comment thread
pranav-871 marked this conversation as resolved.

{/* Assignee */}
{showAssignee && (
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/components/MenteeIssues.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type React from 'react'
import { useState } from 'react'
import { FaBug, FaCheckCircle, FaClock } from 'react-icons/fa'
import { FaCodePullRequest } from 'react-icons/fa6'
import { IconWrapper } from 'wrappers/IconWrapper'
import type { Issue } from 'types/issue'
import { formatDate } from 'utils/dateFormatter'
Expand Down Expand Up @@ -81,10 +82,17 @@ const MenteeIssues: React.FC<MenteeIssuesProps> = ({ openIssues, closedIssues, m
</div>
)}

<div className="flex items-center space-x-4 text-sm text-gray-500">
<div className="flex flex-wrap items-center gap-2 text-sm text-gray-500">
<span>#{issue.number}</span>
<span>Created: {formatDate(issue.createdAt)}</span>
{issue.updatedAt && <span>Updated: {formatDate(issue.updatedAt)}</span>}
{!!issue.pullRequests?.length && (
<span className="inline-flex items-center gap-1 rounded-full bg-blue-100 px-2 py-0.5 text-xs font-medium text-blue-700 dark:bg-blue-900/30 dark:text-blue-300">
<FaCodePullRequest className="h-3 w-3" />
{issue.pullRequests.length} open PR
{issue.pullRequests.length === 1 ? '' : 's'}
</span>
)}
</div>
</div>

Expand Down
1 change: 1 addition & 0 deletions frontend/src/types/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export type CardProps = {
level?: Level
projectLink?: string
projectName?: string
pullRequestCount?: number
social?: { title: string; icon: IconType; url: string }[]
summary: string
title: string
Expand Down