Skip to content
Merged
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
25 changes: 12 additions & 13 deletions backend/apps/github/api/internal/nodes/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@

import strawberry
import strawberry_django
from django.db.models import Exists, OuterRef
from django.db.models import Prefetch

from apps.github.api.internal.nodes.pull_request import PullRequestNode
from apps.github.api.internal.nodes.user import UserNode
from apps.github.models.issue import Issue
from apps.github.models.pull_request import PullRequest

MERGED_PULL_REQUESTS_PREFETCH = Prefetch(
"pull_requests",
queryset=PullRequest.objects.filter(
merged_at__isnull=False,
state="closed",
),
to_attr="merged_pull_requests",
)


@strawberry_django.type(
Issue,
Expand Down Expand Up @@ -47,20 +56,10 @@ def labels(self, root: Issue) -> list[str]:
"""Resolve label names for the issue."""
return [label.name for label in root.labels.all()]

@strawberry_django.field(
annotate={
"is_merged": Exists(
PullRequest.objects.filter(
merged_at__isnull=False,
related_issues=OuterRef("pk"),
state="closed",
)
)
}
)
@strawberry_django.field(prefetch_related=[MERGED_PULL_REQUESTS_PREFETCH])
def is_merged(self, root: Issue) -> bool:
"""Return True if this issue has at least one merged pull request."""
return root.is_merged
return bool(getattr(root, "merged_pull_requests", None))

@strawberry_django.field(prefetch_related=["participant_interests__user"])
def interested_users(self, root: Issue) -> list[UserNode]:
Expand Down
12 changes: 9 additions & 3 deletions backend/apps/mentorship/api/internal/nodes/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import strawberry

from apps.common.utils import normalize_limit
from apps.github.api.internal.nodes.issue import IssueNode
from apps.github.api.internal.nodes.issue import MERGED_PULL_REQUESTS_PREFETCH, IssueNode
from apps.github.api.internal.nodes.pull_request import PullRequestNode
from apps.github.api.internal.nodes.user import UserNode
from apps.github.models import Label
Expand Down Expand Up @@ -86,7 +86,9 @@ def issues(
return []

queryset = self.issues.select_related("repository", "author").prefetch_related(
"assignees", "labels"
"assignees",
"labels",
MERGED_PULL_REQUESTS_PREFETCH,
)

if label and label != "all":
Expand Down Expand Up @@ -120,7 +122,11 @@ def issue_by_number(self, number: int) -> IssueNode | None:
"""Return a single issue by its GitHub number within this module's linked issues."""
return (
self.issues.select_related("repository", "author")
.prefetch_related("assignees", "labels")
.prefetch_related(
"assignees",
"labels",
MERGED_PULL_REQUESTS_PREFETCH,
)
.filter(number=number)
.first()
)
Expand Down
5 changes: 3 additions & 2 deletions backend/apps/mentorship/api/internal/queries/mentorship.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from django.db.models import Prefetch

from apps.common.utils import normalize_limit
from apps.github.api.internal.nodes.issue import IssueNode
from apps.github.api.internal.nodes.issue import MERGED_PULL_REQUESTS_PREFETCH, IssueNode
from apps.github.models import Label
from apps.github.models.user import User as GithubUser
from apps.mentorship.api.internal.nodes.mentee import MenteeNode
Expand Down Expand Up @@ -119,11 +119,12 @@ def get_mentee_module_issues(
module.issues.filter(assignees=github_user)
.only("id", "number", "title", "state", "created_at", "url")
.prefetch_related(
Prefetch("labels", queryset=Label.objects.only("id", "name")),
Prefetch(
"assignees",
queryset=GithubUser.objects.only("id", "login", "name", "avatar_url"),
),
Prefetch("labels", queryset=Label.objects.only("id", "name")),
MERGED_PULL_REQUESTS_PREFETCH,
)
.order_by("-created_at")
)
Expand Down
5 changes: 3 additions & 2 deletions frontend/__tests__/unit/components/IssuesTable.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ describe('<IssuesTable />', () => {

it('renders Merged status badge when isMerged is true', () => {
render(<IssuesTable issues={[mockIssues[2]]} />)
const mergedBadges = screen.getAllByText('Merged')
expect(mergedBadges.length).toBeGreaterThan(0)
// Merged issues display with "Closed" text (purple badge)
const closedBadges = screen.getAllByText('Closed')
expect(closedBadges.length).toBeGreaterThan(0)
})

it('defaults to Closed status for unknown states', () => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/__tests__/unit/pages/IssuesPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ describe('IssuesPage', () => {
})

describe.each([
{ state: 'closed', isMerged: true, expectedText: 'Merged' },
{ state: 'closed', isMerged: true, expectedText: 'Closed' },
{ state: 'closed', isMerged: false, expectedText: 'Closed' },
])('issue states', ({ state, isMerged, expectedText }) => {
it(`renders ${expectedText} issues correctly`, () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ describe('ModuleIssueDetailsPage', () => {

describe('issue states', () => {
it.each([
{ state: 'closed', isMerged: true, expectedText: 'Merged' },
{ state: 'closed', isMerged: true, expectedText: 'Closed' },
{ state: 'closed', isMerged: false, expectedText: 'Closed' },
{ state: 'open', isMerged: false, expectedText: 'Open' },
])('renders issue state as "$expectedText"', ({ state, isMerged, expectedText }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ const ModuleIssueDetailsPage = () => {
issueStatusLabel = 'Open'
} else if (issue.isMerged) {
issueStatusClass = 'bg-[#8657E5] text-white'
issueStatusLabel = 'Merged'
issueStatusLabel = 'Closed'
} else {
issueStatusClass = 'bg-[#DA3633] text-white'
issueStatusLabel = 'Closed'
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/IssuesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const IssuesTable: React.FC<IssuesTableProps> = ({
const getStatusBadge = (state: string, isMerged?: boolean) => {
const statusMap: Record<string, { text: string; class: string }> = {
open: { text: 'Open', class: 'bg-[#238636]' },
merged: { text: 'Merged', class: 'bg-[#8657E5]' },
merged: { text: 'Closed', class: 'bg-[#8657E5]' },
closed: { text: 'Closed', class: 'bg-[#DA3633]' },
}

Expand Down