Skip to content

Conversation

@ishanBahuguna
Copy link
Contributor

Proposed change

Resolves #2624

Backend:

  1. Updated the Project model to support Slack channel URLs using EntityChannel.
  2. Implemented a new resolver to fetch Slack channel links from the backend.
  3. Added test cases for the updated model and resolver functionality.

Frontend:

  1. Updated the GraphQL query to fetch Slack channel data for Project pages.
  2. Displayed proper badges on specific projects
  3. Added test cases to validate the correct retrieval and rendering of Slack channel.

While working on the issue I found that the Chapter page is already displaying the slack channels on frontend

Checklist

  • I read and followed the contributing guidelines
  • I ran make check-test locally and all tests passed
  • I used AI for code, documentation, or tests in this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 11, 2025

Summary by CodeRabbit

  • New Features

    • Projects now show social links on their detail pages (project-type details include platform-specific URLs).
    • Project data now exposes a socialUrls field so UI can render connected channel links.
  • Tests

    • Added tests ensuring social links are exposed and rendered for projects.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Adds GenericRelation fields to Project and Chapter models, exposes a new social_urls GraphQL field on ProjectNode, updates frontend to fetch and render social links for projects, and adds corresponding backend and frontend tests.

Changes

Cohort / File(s) Summary
Backend — GraphQL node
backend/apps/owasp/api/internal/nodes/project.py
Added social_urls(self) -> list[str] on ProjectNode that collects active social_channels and returns Slack app redirect URLs when slack_channel_id is present.
Backend — Models
backend/apps/owasp/models/project.py, backend/apps/owasp/models/chapter.py
Added GenericRelation fields: social_channels on Project and channels on Chapter, and imported EntityChannel to support the relations.
Backend — Tests
backend/tests/apps/owasp/api/internal/nodes/project_test.py, backend/tests/apps/owasp/models/project_test.py
Added tests to assert presence and configuration of the social_urls GraphQL field and social_channels GenericRelation on Project.
Frontend — Pages / Components
frontend/src/app/projects/[projectKey]/page.tsx, frontend/src/components/CardDetailsPage.tsx
Pass project.socialUrls as socialLinks to DetailsCard; expand SocialLinks rendering to include type 'project'.
Frontend — Queries & Types
frontend/src/server/queries/projectQueries.ts, frontend/src/types/project.ts
Included socialUrls in the GET_PROJECT_DATA GraphQL query and added optional socialUrls?: string[] to the Project type.
Frontend — Tests
frontend/__tests__/unit/components/CardDetailsPage.test.tsx
Added test asserting SocialLinks render for project type when socialLinks are provided (expecting 3 links in the test).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to GenericRelation parameters (content_type_field, object_id_field, related_query_name) and migrations implications.
  • Review social_urls resolver for potential N+1 queries and ensure active-channel filtering is correct.
  • Confirm GraphQL schema generation and frontend types/queries align (naming and optionality).
  • Validate updated frontend conditional rendering and corresponding unit test expectations.

Suggested reviewers

  • arkid15r
  • kasya

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding related Slack channels to chapters and projects, matching the core feature implementation across backend and frontend.
Description check ✅ Passed The description is related to the changeset, covering backend model/resolver updates and frontend GraphQL/UI changes, though somewhat incomplete regarding Chapter implementation details.
Linked Issues check ✅ Passed The PR addresses issue #2624 by adding Slack channel relationships to both Project and Chapter models with GraphQL resolvers, frontend UI updates, and test coverage for both backend and frontend.
Out of Scope Changes check ✅ Passed All code changes are directly aligned with issue #2624 objectives: backend model relations, GraphQL resolvers, frontend UI rendering, and comprehensive test coverage for both layers.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent 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 c430247 and 537018e.

📒 Files selected for processing (2)
  • backend/apps/owasp/api/internal/nodes/project.py (1 hunks)
  • frontend/__tests__/unit/components/CardDetailsPage.test.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • frontend/tests/unit/components/CardDetailsPage.test.tsx
  • backend/apps/owasp/api/internal/nodes/project.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Run pre-commit checks
  • GitHub Check: Run spell check
  • GitHub Check: Run frontend checks
  • GitHub Check: CodeQL (python)
  • GitHub Check: CodeQL (javascript-typescript)
  • GitHub Check: labeler

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: 0

🧹 Nitpick comments (5)
frontend/src/components/CardDetailsPage.tsx (1)

120-148: Extending SocialLinks to project type is aligned and guarded

The condition now including type === 'project' reuses the existing SocialLinks rendering path for chapters/committees and is still safely guarded by socialLinks truthiness, with SocialLinks itself no-op’ing on an empty array. This is a straightforward and correct extension of the existing behavior.

If you touch this area again, consider replacing the repeated type === ... checks with an ['chapter', 'committee', 'project'].includes(type) style predicate for slightly clearer intent.

backend/tests/apps/owasp/models/project_test.py (1)

4-9: Good coverage of social_channels GenericRelation

The new test_social_channels_ accurately verifies the presence and configuration of the social_channels GenericRelation on Project, including model type and content-type/object-id field names, which should catch regressions in the relation wiring.

You might rename the test to something like test_social_channels_field_configuration (dropping the trailing underscore) to better reflect its purpose and match existing naming style.

Also applies to: 136-143

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

675-695: New test for project social links covers the added behavior

The renders social links for project type when socialLinks are provided test accurately asserts that the Social Links heading appears and that three links are rendered for a project with three URLs, mirroring the existing chapter/committee tests and giving good regression coverage.

Because you assert on getAllByRole('link'), this test may become brittle if additional unrelated links are added to the card; using a more specific container or test id around the Social Links section could make it more resilient.

backend/apps/owasp/api/internal/nodes/project.py (1)

114-127: social_urls resolver is functionally correct for Slack channels

The resolver walks active social_channels, filters for Slack entries with a non-empty slack_channel_id, and returns well-formed app_redirect URLs, which matches the requirement to expose related Slack channels; given it’s used for a single-project query, the simple loop is acceptable from a performance standpoint.

If there’s a chance of duplicate EntityChannel records pointing to the same Slack channel, you may want to de-duplicate urls (e.g., via a set) or enforce uniqueness at the DB layer to avoid repeated badges in the UI.

backend/apps/owasp/models/chapter.py (1)

71-77: Consider aligning field naming with Project model for consistency.

The implementation is correct, but there's a naming inconsistency: Project uses social_channels while Chapter uses channels. Since both serve the same purpose (linking to EntityChannel for social/Slack channels), consistent naming would improve code maintainability and reduce cognitive load when working across both models.

If you agree, consider renaming to match:

-    # related channels from EntityChannel
-    channels = GenericRelation(
+    # related channels from EntityChannel
+    social_channels = GenericRelation(
         EntityChannel,
         content_type_field="entity_type",
         object_id_field="entity_id",
-        related_query_name="chapter",
+        related_query_name="chapter",
     )

Note: If you choose to rename, ensure any existing usages of chapter.channels (e.g., in API resolvers or templates) are updated accordingly.

📜 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 bfef4da and c430247.

⛔ Files ignored due to path filters (2)
  • frontend/src/types/__generated__/graphql.ts is excluded by !**/__generated__/**
  • frontend/src/types/__generated__/projectQueries.generated.ts is excluded by !**/__generated__/**
📒 Files selected for processing (10)
  • backend/apps/owasp/api/internal/nodes/project.py (1 hunks)
  • backend/apps/owasp/models/chapter.py (2 hunks)
  • backend/apps/owasp/models/project.py (2 hunks)
  • backend/tests/apps/owasp/api/internal/nodes/project_test.py (2 hunks)
  • backend/tests/apps/owasp/models/project_test.py (2 hunks)
  • frontend/__tests__/unit/components/CardDetailsPage.test.tsx (1 hunks)
  • frontend/src/app/projects/[projectKey]/page.tsx (1 hunks)
  • frontend/src/components/CardDetailsPage.tsx (1 hunks)
  • frontend/src/server/queries/projectQueries.ts (1 hunks)
  • frontend/src/types/project.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-07-12T17:36:57.255Z
Learnt from: Rajgupta36
Repo: OWASP/Nest PR: 1717
File: frontend/__tests__/unit/pages/createProgram.test.tsx:70-86
Timestamp: 2025-07-12T17:36:57.255Z
Learning: When testing React page components that use mocked form components, validation logic should be tested at the form component level, not the page level. Page-level tests should focus on authentication, role checking, submission handling, and navigation logic.

Applied to files:

  • frontend/__tests__/unit/components/CardDetailsPage.test.tsx
📚 Learning: 2025-06-20T16:12:59.256Z
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 1633
File: frontend/src/components/HealthMetrics.tsx:30-30
Timestamp: 2025-06-20T16:12:59.256Z
Learning: In the DetailsCard component (frontend/src/components/CardDetailsPage.tsx), there's a length check before rendering HealthMetrics: `healthMetricsData.length > 0`. This ensures that when HealthMetrics is rendered, the data array has at least one element, making accessing data[0] safe within the HealthMetrics component.

Applied to files:

  • frontend/src/components/CardDetailsPage.tsx
📚 Learning: 2025-06-20T16:12:59.256Z
Learnt from: ahmedxgouda
Repo: OWASP/Nest PR: 1633
File: frontend/src/components/HealthMetrics.tsx:30-30
Timestamp: 2025-06-20T16:12:59.256Z
Learning: In the DetailsCard component (frontend/src/components/CardDetailsPage.tsx), there's a safety check that ensures HealthMetrics component is only rendered when healthMetricsData exists and has at least one element: `healthMetricsData && healthMetricsData.length > 0`. This makes accessing data[0] safe within the HealthMetrics component.

Applied to files:

  • frontend/src/components/CardDetailsPage.tsx
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 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/server/queries/projectQueries.ts
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 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/queries/projectQueries.ts
📚 Learning: 2025-08-31T13:47:15.861Z
Learnt from: rudransh-shrivastava
Repo: OWASP/Nest PR: 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/queries/projectQueries.ts
📚 Learning: 2025-09-10T03:14:06.506Z
Learnt from: arkid15r
Repo: OWASP/Nest PR: 1995
File: backend/apps/github/models/issue.py:61-65
Timestamp: 2025-09-10T03:14:06.506Z
Learning: When refactoring from ManyToManyField to GenericForeignKey + GenericRelation in Django, all standard relationship operations (.all(), .add(), .select_related(), .order_by()) continue to work unchanged. GenericRelation automatically handles setting content_type and object_id when using .add().

Applied to files:

  • backend/apps/owasp/models/project.py
🧬 Code graph analysis (4)
backend/apps/owasp/models/chapter.py (1)
backend/apps/owasp/models/entity_channel.py (1)
  • EntityChannel (8-66)
frontend/src/app/projects/[projectKey]/page.tsx (1)
backend/apps/github/models/repository.py (1)
  • project (162-164)
backend/tests/apps/owasp/models/project_test.py (1)
backend/apps/owasp/models/entity_channel.py (1)
  • EntityChannel (8-66)
backend/apps/owasp/models/project.py (1)
backend/apps/owasp/models/entity_channel.py (1)
  • EntityChannel (8-66)
🔇 Additional comments (7)
frontend/src/app/projects/[projectKey]/page.tsx (1)

91-111: Propagating socialUrls into DetailsCard looks correct

Passing socialLinks={project.socialUrls} cleanly wires the new GraphQL field into the shared details component, and the downstream component already guards rendering on presence/length of the array, so this should be safe even when the field is null/undefined or empty.

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

18-48: socialUrls type addition is consistent with usage

Adding socialUrls?: string[] to Project matches the GraphQL selection and DetailsCard props, and keeping it optional preserves backward compatibility with callers that don’t request this field.

frontend/src/server/queries/projectQueries.ts (1)

3-128: GraphQL query now correctly fetches socialUrls

Including socialUrls in GET_PROJECT_DATA keeps the client query in sync with the new ProjectNode field and the Project type, enabling the project page to render social links without affecting other queries like GET_PROJECT_METADATA.

backend/tests/apps/owasp/api/internal/nodes/project_test.py (1)

16-41: ProjectNode test suite correctly extended for social_urls

Adding "social_urls" to expected_field_names and the dedicated test_resolve_social_urls that checks the type as list[str] keeps the public API contract of ProjectNode well-specified and ensures the new field can’t silently change or disappear.

Also applies to: 108-111

backend/apps/owasp/models/project.py (2)

22-22: LGTM!

The import is correctly placed alongside other model imports.


130-136: LGTM!

The GenericRelation setup is correct and follows Django conventions. The field configuration properly maps to EntityChannel's entity_type and entity_id fields, and the related_query_name="project" enables efficient reverse lookups. Based on learnings, this pattern supports all standard relationship operations.

backend/apps/owasp/models/chapter.py (1)

17-17: LGTM!

The import is correctly placed with other model imports.

@ahmedxgouda ahmedxgouda self-assigned this Dec 11, 2025
@ishanBahuguna
Copy link
Contributor Author

@ahmedxgouda should I keep working on this ? As you have assigned this to yourself

@arkid15r
Copy link
Collaborator

@ahmedxgouda should I keep working on this ? As you have assigned this to yourself

@ishanBahuguna yes. Ahmed is an assignee for the code review.

@sonarqubecloud
Copy link

Copy link
Collaborator

@ahmedxgouda ahmedxgouda left a comment

Choose a reason for hiding this comment

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

Thanks for working in this. You didn't update the chapter graphql resolvers with the new EntityChannel field data. Also, please look into the bellow comments.

Comment on lines +123 to +126
for ec in self.social_channels.filter(is_active=True):
channel = ec.channel
if (
ec.platform == "slack"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
for ec in self.social_channels.filter(is_active=True):
channel = ec.channel
if (
ec.platform == "slack"
for entity_channel in self.social_channels.filter(is_active=True):
channel = entity_channel.channel
if (
entity_channel.platform == "slack"

)

# related channels from EntityChannel
social_channels = GenericRelation(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why this named social_channels and it is named in Chapter model: channels?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ahmedxgouda I forget to remove it from chapter page.

I'm am a bit confused regarding updating the chapter graphql resolver , the chapter page already shows the related communication channel on frontend . So do I still need to update the resolver?

Copy link
Collaborator

Choose a reason for hiding this comment

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

It seems we will migrate to using EntityChannel field instead of urls JSON field. At least that what I understood from the issue description. Maybe @arkid15r could confirm that.

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.

Add related Slack channels to Chapter and Project pages

3 participants