Skip to content

Conversation

@Rajgupta36
Copy link
Contributor

Proposed change


Resolves #2239

Tasks

  • created issues list page
  • created seperate issue page
  • created command to link pr with related issue.
  • created graphql queries and mutationg related to issue,task and pr

Rajgupta36 and others added 30 commits August 6, 2025 19:17
* fix ui bugs

* update format

* fix test cases

* fix test cases

* update UI

* update UI

* update line clamp property

* fix test case

* Update styling

---------

Co-authored-by: Kate Golovanova <[email protected]>
Co-authored-by: Arkadii Yakovets <[email protected]>
* Update docker-compose/local.yaml

* UI/ux mentorship program update (OWASP#2244)

* fix ui bugs

* update format

* fix test cases

* fix test cases

* update UI

* update UI

* update line clamp property

* fix test case

* Update styling

---------

Co-authored-by: Kate Golovanova <[email protected]>
Co-authored-by: Arkadii Yakovets <[email protected]>

* fix params and remove refresh params

* update direct cache

* fix test cases

* better exception caching

* update logic

Update docker-compose/local.yaml

UI/ux mentorship program update (OWASP#2244)

* fix ui bugs

* update format

* fix test cases

* fix test cases

* update UI

* update UI

* update line clamp property

* fix test case

* Update styling

---------

Co-authored-by: Kate Golovanova <[email protected]>
Co-authored-by: Arkadii Yakovets <[email protected]>

* Update apollo cache logic on updating programs and modules

* restore files

* fix test cases

* fix test cases

* update button to link

* fix type

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
Co-authored-by: Kate Golovanova <[email protected]>
Co-authored-by: Arkadii Yakovets <[email protected]>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 8, 2025

Summary by CodeRabbit

  • New Features

    • Module Issues: new listing with label filters and detailed issue view (assignees, labels, related PRs, interested users).
    • Assign/unassign contributors to issues directly from the module issue page.
    • Program and module cards improved with tooltips and multi-line descriptions.
  • Admin Enhancements

    • Admin UI shows issue level, related issues autocomplete, comment management, and interest tracking.
  • Refactor/Style

    • Consistent title-casing, simplified navigation, updated buttons, and streamlined responsive grids.
  • Chores

    • New sync/update commands for issues, levels, comments, and PR links.
    • Updated local development volumes and env loading.

Walkthrough

Adds mentorship issues management: backend models/migrations for Issue comments, Issue.level, PullRequest.related_issues; admin configs; sync/management commands; GraphQL nodes/mutations for issues, assignees, interests; Makefile targets. Frontend adds issues list/detail pages, queries/mutations, UI tweaks, and test updates. Docker Compose volume names changed; dotenv loaded in manage.py.

Changes

Cohort / File(s) Summary
Makefiles
backend/Makefile, backend/apps/github/Makefile, backend/apps/mentorship/Makefile
Include mentorship Makefile; add target to update PR links; add mentorship sync targets (module issues, issue levels, comments).
GitHub backend: models & migrations
backend/apps/github/migrations/0037_issue_level_comment.py, .../migrations/0038_pullrequest_related_issues.py, backend/apps/github/models/__init__.py, .../models/issue.py, .../models/comment.py, .../models/pull_request.py
Add Issue.level FK; new Comment model and GenericRelation on Issue; PullRequest.related_issues M2M; export models; latest_comment property.
GitHub backend: admin
backend/apps/github/admin/__init__.py, .../admin/comment.py, .../admin/issue.py, .../admin/pull_request.py
Register CommentAdmin; show Issue.level; enable PR.related_issues autocomplete.
GitHub backend: API & sync
backend/apps/github/api/internal/nodes/issue.py, backend/apps/github/common.py, backend/apps/github/management/commands/github_update_pull_requests.py
Extend IssueNode (fields, resolvers for assignees/labels/interested_users/pull_requests); add sync_issue_comments; add command to link PRs to issues via closing keywords.
Mentorship backend: models & managers
backend/apps/mentorship/migrations/0005_remove_task_level_module_issues_and_more.py, .../models/module.py, .../models/task.py, .../models/issue_user_interest.py, .../models/__init__.py, .../models/managers/module.py, .../models/managers/__init__.py
Add Module.issues M2M; remove Task.level, relax Task.assigned_at; introduce IssueUserInterest model; add PublishedModuleManager and exports.
Mentorship backend: admin
backend/apps/mentorship/admin/__init__.py, .../admin/issue_user_interest.py, .../admin/module.py, .../admin/task.py
Register IssueUserInterestAdmin; ModuleAdmin autocomplete issues; TaskAdmin ordering by assigned_at desc.
Mentorship backend: GraphQL
backend/apps/mentorship/api/internal/mutations/module.py, .../api/internal/nodes/module.py
Add mutations to assign/unassign issue to user; ModuleNode fields for issues, issue lookup, interested users, task deadlines/assigned_at.
Mentorship backend: management commands
backend/apps/mentorship/management/commands/sync_module_issues.py, .../sync_issue_levels.py, .../mentorship_update_comments.py
Commands to link issues to modules and create tasks, sync Issue.levels from labels, and update comments/interests across modules.
Mentorship backend: utils
backend/apps/mentorship/utils.py
Add normalize_name utility.
Backend infra
backend/manage.py, docker-compose/local.yaml
Load dotenv (called twice); rename volumes to -mentorship variants across services.
Frontend: new mentorship issue pages
frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/issues/page.tsx, .../issues/[issueId]/page.tsx
Add module issues list with label filter; add single issue page with details, PRs, interested users, and assign/unassign actions.
Frontend: mentorship pages updates
frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx, .../programs/[programKey]/page.tsx, .../programs/page.tsx, .../my/mentorship/page.tsx, .../my/mentorship/programs/[programKey]/page.tsx, .../modules/[moduleKey]/edit/page.tsx, .../programs/[programKey]/edit/page.tsx, .../modules/create/page.tsx
Use titleCaseWord; adjust grids; remove refresh query param flows; cache update on create; navigation updates.
Frontend: components
frontend/src/components/ProgramCard.tsx, .../SingleModuleCard.tsx, .../ModuleCard.tsx, .../CardDetailsPage.tsx, .../ActionButton.tsx, .../ModuleForm.tsx, .../ProgramForm.tsx
Tooltip title and clamped description; admin dropdown now admin-only and simplified; ModuleCard uses Link; add “View Issues” button in details; color/style changes for buttons.
Frontend: GraphQL client additions
frontend/src/server/queries/issueQueries.ts, .../queries/moduleQueries.ts, .../mutations/moduleMutations.ts, .../mutations/programsMutations.ts
Add queries for module issues and issue view; add assign/unassign mutations; expand mutation return selections (ids, experienceLevels, admins).
Frontend: types
frontend/src/types/issue.ts, .../types/pullRequest.ts
Add Issue.pullRequests and PullRequest.id.
Frontend tests
frontend/__tests__/unit/components/ProgramCard.test.tsx, .../SingleModuleCard.test.tsx, .../pages/CreateModule.test.tsx, .../pages/EditModule.test.tsx, .../pages/ProgramDetails*.test.tsx
Update expectations for Tooltip, description clamping, admin/menu changes, capitalization, and navigation without refresh flag.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested labels

backend, frontend, backend-tests, frontend-tests, makefile

Suggested reviewers

  • arkid15r
  • kasya

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning This pull request includes extensive backend migrations, new comment synchronization functions, multiple management commands, Makefile and Docker Compose updates, and broader GraphQL node and admin changes that exceed the scope of the linked UI/UX issue page requirements. These unrelated changes introduce risk and make the review harder to scope against the original issue. Please split unrelated backend migrations, syncing commands, and infrastructure modifications into separate pull requests so this PR can focus solely on the UI/UX issue pages feature.
Title Check ❓ Inconclusive The title “UI/ux issue page” is related to the feature but is too vague and generic to convey the specific scope of changes, such as adding both an issues list and a detailed single-issue view. It does not clearly summarize the primary change or match the conventions of a concise, descriptive PR title. A more focused title would help teammates quickly understand the main purpose of this pull request. Consider renaming the pull request to something like “Add issues list and single issue UI pages” to clearly reflect the primary UI enhancements implemented.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues Check ✅ Passed The pull request implements all of the linked issue’s requirements by providing the issues list and single issue pages with filtering, clickable rows, truncated descriptions, assignee linking, labels, interested user management, GitHub PR linking via a new management command, and the necessary GraphQL queries and mutations.
Description Check ✅ Passed The description outlines the implemented changes—issues list page, separate issue page, command for linking PRs to issues, and related GraphQL operations—and correctly references the linked issue #2239, keeping the content on-topic and relevant to the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 92.68% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/components/SingleModuleCard.tsx (1)

70-85: Link construction must not reference window at render time

Rendering this component on the server will throw because window doesn’t exist there. Switch to a relative href or derive the base path via usePathname() so the module page remains navigable in SSR.

Apply this diff:

-          <Link
-            href={`${window.location.pathname}/modules/${module.key}`}
+          <Link
+            href={`./modules/${module.key}`}
🧹 Nitpick comments (4)
backend/apps/mentorship/admin/task.py (1)

28-29: Consider explicit NULL ordering for better UX.

The descending sort by assigned_at is a good default. However, since assigned_at is nullable (per the model changes in this PR), database-specific NULL ordering behavior may affect the list view. In PostgreSQL, ORDER BY field DESC defaults to NULLS FIRST, meaning tasks with NULL assigned_at (unassigned or pending tasks) will appear at the top of the list, potentially obscuring recently assigned tasks.

If you want recently assigned tasks to appear first and NULL values last, consider using Django's F expressions:

from django.db.models import F

ordering = [F("assigned_at").desc(nulls_last=True)]

This ensures a consistent and predictable order regardless of the database backend.

frontend/__tests__/unit/components/SingleModuleCard.test.tsx (1)

165-171: Update expectation to match valid href

Once the component stops using window, the link should render as ./modules/test-module (no double slash). Please align the assertion so the test reflects the corrected href.

frontend/src/components/ProgramCard.tsx (1)

17-22: Consider reusing the existing date formatter utility.

A formatDate utility already exists at frontend/src/utils/dateFormatter.ts that handles both Unix timestamps and ISO strings. The local implementation duplicates this logic.

Apply this diff to use the shared utility:

+import { formatDate } from 'utils/dateFormatter'
 import { faEye } from '@fortawesome/free-regular-svg-icons'
 import { faEdit } from '@fortawesome/free-solid-svg-icons'
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
 import { Tooltip } from '@heroui/tooltip'
 import type React from 'react'
 import { Program } from 'types/mentorship'
 import ActionButton from 'components/ActionButton'
 
 interface ProgramCardProps {
   program: Program
   onEdit?: (key: string) => void
   onView: (key: string) => void
   accessLevel: 'admin' | 'user'
 }
 
 const ProgramCard: React.FC<ProgramCardProps> = ({ program, onEdit, onView, accessLevel }) => {
-  const formatDate = (d: string) =>
-    new Date(d).toLocaleDateString('en-US', {
-      month: 'short',
-      day: 'numeric',
-      year: 'numeric',
-    })
-
   const roleClass = {
backend/apps/github/api/internal/nodes/issue.py (1)

55-58: Consider optimizing the database query.

The resolver may trigger N+1 queries since it doesn't use select_related("user"). For better performance, especially when resolving multiple issues, consider applying query optimization.

Apply this diff to optimize the query:

 @strawberry.field
 def interested_users(self) -> list[UserNode]:
     """Return all users who have expressed interest in this issue."""
-    return [interest.user for interest in IssueUserInterest.objects.filter(issue=self)]
+    interests = IssueUserInterest.objects.filter(issue=self).select_related("user")
+    return [interest.user for interest in interests]
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e49e117 and c0b09ae.

⛔ Files ignored due to path filters (2)
  • frontend/src/types/__generated__/moduleMutations.generated.ts is excluded by !**/__generated__/**
  • frontend/src/types/__generated__/programsMutations.generated.ts is excluded by !**/__generated__/**
📒 Files selected for processing (64)
  • backend/Makefile (1 hunks)
  • backend/apps/github/Makefile (1 hunks)
  • backend/apps/github/admin/__init__.py (1 hunks)
  • backend/apps/github/admin/comment.py (1 hunks)
  • backend/apps/github/admin/issue.py (1 hunks)
  • backend/apps/github/admin/pull_request.py (1 hunks)
  • backend/apps/github/api/internal/nodes/issue.py (2 hunks)
  • backend/apps/github/common.py (2 hunks)
  • backend/apps/github/management/commands/github_update_pull_requests.py (1 hunks)
  • backend/apps/github/migrations/0037_issue_level_comment.py (1 hunks)
  • backend/apps/github/migrations/0038_pullrequest_related_issues.py (1 hunks)
  • backend/apps/github/models/__init__.py (1 hunks)
  • backend/apps/github/models/comment.py (1 hunks)
  • backend/apps/github/models/issue.py (3 hunks)
  • backend/apps/github/models/pull_request.py (1 hunks)
  • backend/apps/mentorship/Makefile (1 hunks)
  • backend/apps/mentorship/admin/__init__.py (1 hunks)
  • backend/apps/mentorship/admin/issue_user_interest.py (1 hunks)
  • backend/apps/mentorship/admin/module.py (1 hunks)
  • backend/apps/mentorship/admin/task.py (1 hunks)
  • backend/apps/mentorship/api/internal/mutations/module.py (3 hunks)
  • backend/apps/mentorship/api/internal/nodes/module.py (2 hunks)
  • backend/apps/mentorship/management/commands/mentorship_update_comments.py (1 hunks)
  • backend/apps/mentorship/management/commands/sync_issue_levels.py (1 hunks)
  • backend/apps/mentorship/management/commands/sync_module_issues.py (1 hunks)
  • backend/apps/mentorship/migrations/0005_remove_task_level_module_issues_and_more.py (1 hunks)
  • backend/apps/mentorship/models/__init__.py (1 hunks)
  • backend/apps/mentorship/models/issue_user_interest.py (1 hunks)
  • backend/apps/mentorship/models/managers/__init__.py (1 hunks)
  • backend/apps/mentorship/models/managers/module.py (1 hunks)
  • backend/apps/mentorship/models/module.py (2 hunks)
  • backend/apps/mentorship/models/task.py (1 hunks)
  • backend/apps/mentorship/utils.py (1 hunks)
  • backend/manage.py (1 hunks)
  • docker-compose/local.yaml (5 hunks)
  • frontend/__tests__/unit/components/ProgramCard.test.tsx (2 hunks)
  • frontend/__tests__/unit/components/SingleModuleCard.test.tsx (4 hunks)
  • frontend/__tests__/unit/pages/CreateModule.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/EditModule.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/ProgramDetails.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/ProgramDetailsMentorship.test.tsx (1 hunks)
  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx (2 hunks)
  • frontend/src/app/mentorship/programs/[programKey]/page.tsx (2 hunks)
  • frontend/src/app/mentorship/programs/page.tsx (1 hunks)
  • frontend/src/app/my/mentorship/page.tsx (1 hunks)
  • frontend/src/app/my/mentorship/programs/[programKey]/edit/page.tsx (1 hunks)
  • frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/edit/page.tsx (1 hunks)
  • frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/issues/[issueId]/page.tsx (1 hunks)
  • frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/issues/page.tsx (1 hunks)
  • frontend/src/app/my/mentorship/programs/[programKey]/modules/create/page.tsx (3 hunks)
  • frontend/src/app/my/mentorship/programs/[programKey]/page.tsx (4 hunks)
  • frontend/src/components/ActionButton.tsx (1 hunks)
  • frontend/src/components/CardDetailsPage.tsx (1 hunks)
  • frontend/src/components/ModuleCard.tsx (2 hunks)
  • frontend/src/components/ModuleForm.tsx (1 hunks)
  • frontend/src/components/ProgramCard.tsx (3 hunks)
  • frontend/src/components/ProgramForm.tsx (1 hunks)
  • frontend/src/components/SingleModuleCard.tsx (1 hunks)
  • frontend/src/server/mutations/moduleMutations.ts (2 hunks)
  • frontend/src/server/mutations/programsMutations.ts (3 hunks)
  • frontend/src/server/queries/issueQueries.ts (1 hunks)
  • frontend/src/server/queries/moduleQueries.ts (1 hunks)
  • frontend/src/types/issue.ts (2 hunks)
  • frontend/src/types/pullRequest.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2025-09-17T02:42:41.928Z
Learnt from: Rajgupta36
PR: OWASP/Nest#2288
File: frontend/src/components/ActionButton.tsx:0-0
Timestamp: 2025-09-17T02:42:41.928Z
Learning: In frontend/src/components/ActionButton.tsx, the user Rajgupta36 intentionally changed text-blue-600 to text-[#1D7BD7] to align the text color with the border color (#1D7BD7) for visual consistency, prioritizing design alignment over theme tokens.

Applied to files:

  • frontend/src/components/ActionButton.tsx
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
PR: OWASP/Nest#2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS is actively used in frontend/src/app/my/mentorship/programs/[programKey]/edit/page.tsx for program editing functionality and cannot be removed. It serves a different purpose than GET_PROGRAM_ADMIN_DETAILS, providing comprehensive program information needed for editing.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/page.tsx
  • frontend/src/app/my/mentorship/programs/[programKey]/edit/page.tsx
  • frontend/src/app/my/mentorship/programs/[programKey]/page.tsx
  • frontend/src/app/my/mentorship/programs/[programKey]/modules/create/page.tsx
  • frontend/src/server/mutations/programsMutations.ts
📚 Learning: 2025-09-29T06:02:35.566Z
Learnt from: rudransh-shrivastava
PR: OWASP/Nest#2178
File: frontend/src/components/SingleModuleCard.tsx:54-54
Timestamp: 2025-09-29T06:02:35.566Z
Learning: In the Module type from types/mentorship.ts, the experienceLevel field is required (experienceLevel: ExperienceLevelEnum), not optional, so null/undefined checks are not needed when accessing this field.

Applied to files:

  • frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx
📚 Learning: 2025-07-13T07:31:06.511Z
Learnt from: Rajgupta36
PR: OWASP/Nest#1717
File: frontend/src/components/ModuleCard.tsx:53-55
Timestamp: 2025-07-13T07:31:06.511Z
Learning: In Next.js 13+ app router, useRouter from 'next/navigation' does not provide asPath or query properties. Use useParams to extract route parameters and usePathname to get the current pathname instead.

Applied to files:

  • frontend/src/app/my/mentorship/programs/[programKey]/page.tsx
  • frontend/src/app/my/mentorship/programs/[programKey]/modules/create/page.tsx
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
PR: OWASP/Nest#2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS and GET_PROGRAM_ADMIN_DETAILS are two separate queries serving different purposes: GET_PROGRAM_DETAILS fetches comprehensive program information while GET_PROGRAM_ADMIN_DETAILS fetches only admin-related details. These queries cannot be removed or merged as they serve different use cases in the application.

Applied to files:

  • frontend/src/server/mutations/programsMutations.ts
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
PR: OWASP/Nest#2155
File: frontend/src/server/queries/programsQueries.ts:81-81
Timestamp: 2025-08-31T13:47:15.861Z
Learning: In frontend/src/server/queries/programsQueries.ts, GET_PROGRAM_DETAILS and GET_PROGRAM_ADMIN_DETAILS are two separate queries serving different purposes: GET_PROGRAM_DETAILS fetches comprehensive program information while GET_PROGRAM_ADMIN_DETAILS fetches only admin-related details.

Applied to files:

  • frontend/src/server/mutations/programsMutations.ts
🧬 Code graph analysis (33)
backend/apps/mentorship/models/managers/__init__.py (1)
backend/apps/mentorship/models/managers/module.py (1)
  • PublishedModuleManager (8-13)
backend/apps/mentorship/admin/__init__.py (1)
backend/apps/mentorship/models/issue_user_interest.py (1)
  • IssueUserInterest (6-31)
frontend/src/app/mentorship/programs/[programKey]/page.tsx (1)
frontend/src/utils/capitalize.ts (1)
  • titleCaseWord (1-4)
frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx (1)
frontend/src/utils/capitalize.ts (1)
  • titleCaseWord (1-4)
backend/apps/mentorship/models/issue_user_interest.py (3)
backend/apps/github/models/issue.py (1)
  • Meta (24-30)
backend/apps/github/api/internal/queries/user.py (1)
  • user (40-53)
backend/apps/mentorship/api/internal/nodes/mentor.py (2)
  • login (23-25)
  • name (18-20)
backend/apps/mentorship/api/internal/mutations/module.py (5)
backend/apps/mentorship/models/issue_user_interest.py (1)
  • IssueUserInterest (6-31)
backend/apps/nest/api/internal/permissions.py (1)
  • IsAuthenticated (10-21)
backend/apps/mentorship/api/internal/nodes/module.py (2)
  • ModuleNode (17-94)
  • issues (43-49)
backend/apps/mentorship/models/module.py (1)
  • Module (17-104)
backend/apps/mentorship/models/mentor.py (1)
  • Mentor (11-40)
backend/apps/mentorship/admin/issue_user_interest.py (1)
backend/apps/mentorship/models/issue_user_interest.py (1)
  • IssueUserInterest (6-31)
backend/apps/github/admin/comment.py (1)
backend/apps/github/models/comment.py (1)
  • Comment (11-81)
backend/apps/mentorship/api/internal/nodes/module.py (3)
backend/apps/github/api/internal/nodes/issue.py (2)
  • IssueNode (23-63)
  • interested_users (56-58)
backend/apps/mentorship/models/issue_user_interest.py (1)
  • IssueUserInterest (6-31)
backend/apps/mentorship/models/task.py (1)
  • Task (10-80)
backend/apps/github/management/commands/github_update_pull_requests.py (1)
backend/apps/github/models/pull_request.py (2)
  • PullRequest (11-152)
  • bulk_save (114-116)
backend/apps/mentorship/models/module.py (2)
backend/apps/mentorship/models/managers/module.py (1)
  • PublishedModuleManager (8-13)
backend/apps/mentorship/api/internal/nodes/module.py (1)
  • issues (43-49)
frontend/__tests__/unit/components/SingleModuleCard.test.tsx (1)
frontend/src/wrappers/testUtil.tsx (1)
  • render (14-14)
backend/apps/mentorship/management/commands/sync_module_issues.py (4)
backend/apps/github/models/issue.py (2)
  • Issue (18-233)
  • save (186-195)
backend/apps/mentorship/models/task.py (2)
  • Task (10-80)
  • Status (19-25)
backend/apps/mentorship/utils.py (1)
  • normalize_name (4-6)
backend/apps/github/models/repository.py (1)
  • path (154-156)
frontend/src/types/issue.ts (1)
frontend/src/types/pullRequest.ts (1)
  • PullRequest (3-11)
backend/apps/mentorship/utils.py (1)
backend/apps/mentorship/api/internal/nodes/mentor.py (1)
  • name (18-20)
backend/apps/mentorship/management/commands/sync_issue_levels.py (4)
backend/apps/github/models/issue.py (1)
  • Issue (18-233)
backend/apps/github/models/label.py (1)
  • Label (9-77)
backend/apps/mentorship/models/task_level.py (1)
  • TaskLevel (8-61)
backend/apps/mentorship/utils.py (1)
  • normalize_name (4-6)
frontend/src/components/ProgramCard.tsx (1)
frontend/src/utils/dateFormatter.ts (1)
  • formatDate (1-20)
frontend/src/app/my/mentorship/programs/[programKey]/page.tsx (5)
frontend/src/types/mentorship.ts (2)
  • Program (22-37)
  • Module (52-64)
frontend/src/server/mutations/programsMutations.ts (1)
  • UPDATE_PROGRAM_STATUS_MUTATION (49-57)
frontend/src/server/queries/programsQueries.ts (1)
  • GET_PROGRAM_AND_MODULES (44-81)
frontend/src/utils/capitalize.ts (1)
  • titleCaseWord (1-4)
frontend/src/utils/dateFormatter.ts (1)
  • formatDate (1-20)
backend/apps/mentorship/models/__init__.py (1)
backend/apps/mentorship/models/issue_user_interest.py (1)
  • IssueUserInterest (6-31)
backend/apps/mentorship/migrations/0005_remove_task_level_module_issues_and_more.py (1)
backend/apps/github/migrations/0037_issue_level_comment.py (1)
  • Migration (7-74)
backend/apps/github/admin/__init__.py (1)
backend/apps/github/admin/comment.py (1)
  • CommentAdmin (8-18)
backend/apps/github/models/__init__.py (2)
backend/apps/github/models/comment.py (1)
  • Comment (11-81)
backend/apps/github/models/issue.py (1)
  • Issue (18-233)
frontend/src/app/my/mentorship/programs/[programKey]/modules/create/page.tsx (3)
frontend/src/server/queries/programsQueries.ts (1)
  • GET_PROGRAM_AND_MODULES (44-81)
frontend/src/types/mentorship.ts (1)
  • Module (52-64)
frontend/src/app/global-error.tsx (1)
  • handleAppError (66-86)
frontend/src/components/ModuleCard.tsx (1)
frontend/src/components/TruncatedText.tsx (1)
  • TruncatedText (3-45)
backend/apps/mentorship/models/managers/module.py (1)
backend/apps/mentorship/models/program.py (1)
  • ProgramStatus (25-28)
backend/apps/github/api/internal/nodes/issue.py (4)
backend/apps/github/api/internal/nodes/pull_request.py (1)
  • PullRequestNode (17-42)
frontend/src/types/issue.ts (1)
  • Issue (4-21)
backend/apps/mentorship/models/issue_user_interest.py (1)
  • IssueUserInterest (6-31)
backend/apps/mentorship/api/internal/nodes/module.py (1)
  • interested_users (62-72)
frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/issues/page.tsx (5)
frontend/src/server/queries/moduleQueries.ts (1)
  • GET_MODULE_ISSUES (79-120)
frontend/src/app/global-error.tsx (2)
  • handleAppError (66-86)
  • ErrorDisplay (28-51)
backend/apps/mentorship/api/internal/nodes/module.py (1)
  • issues (43-49)
backend/apps/github/api/internal/nodes/issue.py (2)
  • labels (51-53)
  • assignees (46-48)
frontend/src/components/TruncatedText.tsx (1)
  • TruncatedText (3-45)
backend/apps/github/migrations/0037_issue_level_comment.py (1)
backend/apps/mentorship/migrations/0005_remove_task_level_module_issues_and_more.py (1)
  • Migration (7-79)
backend/apps/github/common.py (5)
backend/apps/github/models/comment.py (3)
  • Comment (11-81)
  • update_data (59-81)
  • bulk_save (54-56)
backend/apps/github/models/issue.py (4)
  • Issue (18-233)
  • update_data (209-233)
  • save (186-195)
  • bulk_save (198-200)
backend/apps/github/models/repository.py (2)
  • path (154-156)
  • update_data (307-349)
backend/apps/github/models/user.py (3)
  • User (19-159)
  • update_data (130-159)
  • bulk_save (110-112)
backend/apps/common/models.py (1)
  • bulk_save (19-34)
backend/apps/github/models/comment.py (3)
backend/apps/common/models.py (2)
  • BulkSaveModel (10-34)
  • TimestampedModel (37-46)
backend/apps/common/utils.py (1)
  • truncate (181-193)
backend/apps/github/models/issue.py (5)
  • Meta (24-30)
  • from_github (107-146)
  • bulk_save (198-200)
  • update_data (209-233)
  • save (186-195)
backend/apps/github/models/issue.py (1)
backend/apps/github/models/generic_issue_model.py (1)
  • GenericIssueModel (10-77)
backend/apps/mentorship/management/commands/mentorship_update_comments.py (5)
backend/apps/common/utils.py (1)
  • truncate (181-193)
backend/apps/github/common.py (1)
  • sync_issue_comments (237-292)
backend/apps/github/models/issue.py (1)
  • Issue (18-233)
backend/apps/mentorship/models/issue_user_interest.py (1)
  • IssueUserInterest (6-31)
backend/apps/mentorship/models/module.py (1)
  • Module (17-104)
frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/issues/[issueId]/page.tsx (3)
frontend/src/server/queries/issueQueries.ts (3)
  • GET_MODULE_ISSUE_VIEW (3-53)
  • ASSIGN_ISSUE_TO_USER (55-71)
  • UNASSIGN_ISSUE_FROM_USER (73-89)
frontend/src/app/global-error.tsx (1)
  • ErrorDisplay (28-51)
frontend/src/components/TruncatedText.tsx (1)
  • TruncatedText (3-45)
🪛 checkmake (0.2.2)
backend/apps/mentorship/Makefile

[warning] 1-1: Missing required phony target "all"

(minphony)


[warning] 1-1: Missing required phony target "clean"

(minphony)


[warning] 1-1: Missing required phony target "test"

(minphony)

🔇 Additional comments (36)
backend/manage.py (1)

14-14: LGTM!

Loading dotenv inside the main guard is the correct approach for Django's manage.py.

frontend/src/app/my/mentorship/programs/[programKey]/modules/[moduleKey]/edit/page.tsx (1)

120-120: LGTM! Verify parent page refresh behavior.

The navigation change is consistent with the test updates and correctly uses the programKey parameter. Ensure the parent program page properly refreshes its data when navigated to after module updates.

frontend/__tests__/unit/pages/EditModule.test.tsx (1)

117-117: LGTM! Consistent with implementation changes.

The test expectation correctly reflects the implementation change in the module edit page.

frontend/src/app/my/mentorship/programs/[programKey]/modules/create/page.tsx (2)

8-8: LGTM!

The new imports support the cache update functionality added to the mutation.

Also applies to: 10-10, 12-12


132-132: Verify navigation behavior if cache update fails.

The removal of the ?refresh query parameter is appropriate when cache updates work correctly. However, if the cache update fails (see previous comment), the user won't see the new module on the destination page.

Test this scenario:

  1. Create a module when the GET_PROGRAM_AND_MODULES query hasn't been executed yet (cache is empty)
  2. Verify that the new module appears on the program page after navigation
  3. If it doesn't appear, consider keeping a lightweight refresh mechanism as a fallback
frontend/src/components/ProgramCard.tsx (2)

30-30: LGTM: Clean fallback and consistent line-clamping.

The description handling with a simple fallback and consistent line-clamp-6 styling provides a stable layout regardless of content length.

Also applies to: 65-69


33-35: LGTM: Responsive sizing and improved layout structure.

The responsive card sizing and restructured flex containers provide better visual hierarchy and separation between content and actions.

Also applies to: 72-72

frontend/__tests__/unit/components/ProgramCard.test.tsx (2)

27-33: LGTM: Simple and effective Tooltip mock.

The mock implementation correctly wraps children and provides the title attribute for testing, which is sufficient for unit testing the Tooltip integration.


201-211: LGTM: Correct verification of line-clamp styling.

The test properly verifies that short descriptions render with the line-clamp-6 class, ensuring consistent styling across all description lengths.

backend/apps/mentorship/admin/module.py (1)

16-16: LGTM!

The autocomplete configuration for the issues field follows Django admin best practices and will improve UX when linking issues to modules.

frontend/src/app/my/mentorship/page.tsx (1)

132-132: LGTM!

The grid layout simplification improves consistency by using a unified gap and removes the 4-column breakpoint, creating a more predictable responsive behavior across viewport sizes.

backend/apps/mentorship/models/managers/module.py (1)

8-13: LGTM!

The PublishedModuleManager correctly implements a custom Django manager to filter modules by published program status. The implementation follows Django manager patterns and uses proper field lookups.

backend/apps/github/api/internal/nodes/issue.py (4)

16-18: LGTM!

The addition of number and summary fields to the GraphQL node exposes useful issue metadata to clients.


45-48: LGTM!

The assignees resolver correctly returns a list of UserNode instances from the ManyToMany relationship.


50-53: LGTM!

The labels resolver efficiently extracts label names using values_list with flat=True.


60-63: LGTM!

The pull_requests resolver correctly uses select_related to optimize the query and avoid N+1 issues when fetching related author and repository data.

backend/apps/mentorship/admin/__init__.py (1)

3-3: LGTM!

The import correctly exposes the IssueUserInterest admin, following the established pattern for admin module exposure in this package.

backend/Makefile (1)

3-3: LGTM!

The inclusion of the mentorship Makefile follows the established pattern and enables mentorship-specific make targets at the top level.

frontend/src/types/pullRequest.ts (1)

4-4: LGTM!

Adding the id field as a required string property is essential for stable cross-referencing with issues and enables proper PR tracking in UI components.

frontend/src/server/mutations/moduleMutations.ts (1)

17-17: LGTM!

Adding the id field to the mentors selection in both mutations is necessary for proper mentor identification and tracking when creating or updating modules. The change is applied consistently across both UPDATE_MODULE and CREATE_MODULE operations.

Also applies to: 40-40

frontend/__tests__/unit/pages/ProgramDetails.test.tsx (1)

70-70: LGTM!

Test expectation correctly updated to match the title-cased proficiency levels now rendered in the UI.

frontend/__tests__/unit/pages/ProgramDetailsMentorship.test.tsx (1)

70-70: LGTM!

Test expectation correctly updated to match the title-cased proficiency levels now rendered in the UI.

backend/apps/github/admin/comment.py (1)

8-21: LGTM!

The admin configuration correctly exposes Comment model fields for list display, filtering, and search. The use of nest_created_at and nest_updated_at fields (inherited from TimestampedModel) and the search path author__login are appropriate.

backend/apps/github/models/__init__.py (1)

3-4: LGTM!

The public API expansion to include Comment and Issue follows the existing export pattern and aligns with the new models introduced in this PR.

backend/apps/mentorship/models/managers/__init__.py (1)

1-1: LGTM!

The re-export of PublishedModuleManager follows standard package organization patterns and makes the manager accessible at the package level.

backend/apps/github/admin/issue.py (1)

22-22: LGTM!

Adding level to the list display provides useful visibility for issue categorization in the admin interface. The field is properly defined on the Issue model via the recent migration.

backend/apps/github/admin/pull_request.py (1)

17-17: LGTM!

Adding related_issues to autocomplete fields provides better UX when linking pull requests to issues in the admin interface. The field is properly defined via the recent migration.

backend/apps/github/Makefile (1)

21-23: LGTM!

The new github-update-pull-requests target follows the established pattern of other GitHub management commands in this Makefile and provides a convenient interface for linking pull requests to issues.

frontend/src/app/mentorship/programs/[programKey]/page.tsx (1)

9-9: LGTM: Consistent capitalization with new utility.

The replacement of lodash's upperFirst with titleCaseWord applies proper title casing ("BEGINNER""Beginner"), whereas upperFirst would only uppercase the first character without lowercasing the rest. This is appropriate for displaying enum values in a user-friendly format.

Also applies to: 73-73, 79-79

frontend/src/app/mentorship/programs/[programKey]/modules/[moduleKey]/page.tsx (1)

9-9: LGTM: Consistent capitalization applied.

Consistent with the program details page, the module's experience level now uses titleCaseWord for proper title casing.

Also applies to: 52-52

backend/apps/mentorship/models/__init__.py (1)

1-1: LGTM: Standard public model export.

The public export of IssueUserInterest follows Django conventions, enabling clean imports (from mentorship.models import IssueUserInterest) throughout the codebase.

frontend/src/types/issue.ts (1)

1-1: LGTM: Type definition matches backend schema.

The optional pullRequests field correctly reflects the new Many-to-Many relationship between issues and pull requests introduced in the backend. The optional typing is appropriate since not all issues will have related PRs.

Also applies to: 13-13

backend/apps/mentorship/utils.py (1)

4-6: LGTM: Robust normalization utility.

The use of casefold() instead of lower() is a good choice for case-insensitive normalization, as it handles Unicode characters more aggressively (e.g., German ß becomes ss). The implementation gracefully handles None inputs.

backend/apps/github/admin/__init__.py (1)

3-3: LGTM: Standard admin export.

The public export of CommentAdmin follows the established pattern for Django admin module organization.

backend/apps/github/models/pull_request.py (1)

64-69: LGTM: Well-defined Many-to-Many relationship.

The related_issues field correctly establishes a Many-to-Many relationship between pull requests and issues with appropriate configuration:

  • blank=True allows PRs without linked issues
  • related_name="pull_requests" provides the reverse accessor from Issue
  • Aligns with migration 0038 and frontend type definitions
frontend/src/app/mentorship/programs/page.tsx (1)

53-53: LGTM: Simplified and consistent grid layout.

The grid layout changes create more uniform spacing with gap-6 and streamline the responsive behavior by removing the 4-column layout on very large screens. This aligns with similar layout standardizations across other mentorship pages in this PR.

Comment on lines +70 to +73
relevant_issues = Issue.objects.filter(
repository_id__in=module_repos, state=Issue.State.OPEN
).distinct()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Restrict comment sync to module-linked issues

This query pulls every open issue from the module’s repositories, including ones that aren’t tagged for the module. That creates interest records for unrelated work and burns unnecessary GitHub API quota. Use the curated module.issues relation (populated by the sync command) so we only touch issues intentionally linked to the module.

-        relevant_issues = Issue.objects.filter(
-            repository_id__in=module_repos, state=Issue.State.OPEN
-        ).distinct()
+        relevant_issues = module.issues.filter(state=Issue.State.OPEN).distinct()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
relevant_issues = Issue.objects.filter(
repository_id__in=module_repos, state=Issue.State.OPEN
).distinct()
relevant_issues = module.issues.filter(state=Issue.State.OPEN).distinct()
🤖 Prompt for AI Agents
In backend/apps/mentorship/management/commands/mentorship_update_comments.py
around lines 70 to 73, the current query fetches every open issue in the module
repositories (repository_id__in=module_repos) which pulls unrelated issues;
replace that with the curated relation to only process module-linked issues: use
module.issues.filter(state=Issue.State.OPEN).distinct() (or the equivalent
manager access) so only intentionally linked issues are synchronized; ensure
`module` is the same object in scope and drop the repository_id filter.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Oct 8, 2025

Quality Gate Failed Quality Gate failed

Failed conditions
D Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@Rajgupta36 Rajgupta36 closed this Oct 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants