Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Organization FE/BE implementation #1295

Merged
merged 21 commits into from
Apr 11, 2025

Conversation

Dishant1804
Copy link
Collaborator

@Dishant1804 Dishant1804 commented Apr 6, 2025

Resolves #1231

  • add organization list page (a card with a basic information like name, members count, logo, etc)
  • add organization details page (details, stats, repositories, issues, releases, top contributors -- our regular pages components)
  • update the main page search bar to show related results for organizations
2025-04-07.13-29-22.mp4

Copy link
Contributor

coderabbitai bot commented Apr 6, 2025

Summary by CodeRabbit

  • New Features

    • Introduced comprehensive organization support—including new GraphQL queries, indexing, and dedicated details pages—to enrich organization data and search functionalities.
  • Refactor

    • Updated navigation and routing by renaming endpoints from “users” to “members” while adjusting UI texts and search placeholders accordingly.
  • Tests

    • Added extensive unit and end-to-end tests focused on organization features and updated navigation to ensure a smooth user experience.

Walkthrough

This pull request implements a full-stack solution to support organizations. On the backend, it adds new GraphQL nodes, queries, and an Algolia index for organizations, along with expanded indexing mixins and additional query filter capabilities using an organization parameter. On the frontend, new pages and components for displaying organization lists and details have been created, updates have been made to the search bar indexing, and navigation paths have been adjusted from "users" to "members." Numerous tests have been added and updated to ensure the new functionality performs as expected.

Changes

File(s) Change Summary
backend/apps/core/utils/index.py
backend/apps/github/graphql/nodes/organization.py
backend/apps/github/graphql/queries/organization.py
backend/apps/github/index/organization.py
backend/apps/github/models/mixins/organization.py
backend/tests/apps/github/{graphql/nodes,models/mixins}/organization_test.py
Added organization-specific indexing logic, GraphQL nodes, queries, and mixin properties to enable organization data handling and Algolia indexing.
backend/apps/github/graphql/queries/{issue.py, pull_request.py, release.py, repository.py, repository_contributor.py} Extended existing GraphQL queries by adding an optional organization filter to enable organization-specific data retrieval.
frontend/src/app/organizations/[organizationKey]/page.tsx
frontend/src/app/organizations/page.tsx
frontend/__tests__/{e2e/pages/OrganizationDetails.spec.ts,unit/data/mockOrganizationData.ts,unit/pages/Organization*.tsx}
frontend/src/server/queries/organizationQueries.ts
frontend/src/types/{organization.ts,search.ts}
Introduced new organization details and list pages, added a GraphQL query (GET_ORGANIZATION_DATA), and created a new organization type to support organization-related frontend functionality.
Multiple backend and frontend files (e.g., backend/apps/common/management/commands/generate_sitemap.py, backend/apps/slack/*, various frontend test files, and component imports) Updated URL paths and navigation from “users” to “members” to reflect the new routing structure and updated terminology.
frontend/src/components/{CardDetailsPage.tsx, MultiSearch.tsx, UserCard.tsx}
frontend/src/types/card.ts
frontend/src/utils/constants.ts
frontend/src/app/{chapters,page,committees,page,projects/contribute/page,projects/page}.tsx
frontend/src/components/{ContributorAvatar.tsx,ItemCardList.tsx,LeadersList.tsx,RecentReleases.tsx,TopContributors.tsx}
frontend/__tests__/{unit/pages/*,e2e/components/Header.spec.ts}
Updated UI components and test cases: added support for organization type, integrated new icons and properties (e.g., followers_count), modified search placeholder texts, and refined routing and navigation logic within components.

Assessment against linked issues

Objective (from [#1231]) Addressed Explanation
Implement organizations (full-stack support with Algolia indexing and GraphQL on BE/FE, organization list and details pages, updated search)

Suggested labels

backend

Suggested reviewers

  • kasya

Tip

⚡💬 Agentic Chat (Pro Plan, General Availability)
  • We're introducing multi-step agentic chat in review comments and issue comments, within and outside of PR's. This feature enhances review and issue discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments and add commits to existing pull requests.
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Dishant1804 Dishant1804 changed the title OrganizationsPage and OrganizationDetailsPage FE/BE implementation Organization FE/BE implementation Apr 6, 2025
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: 6

🧹 Nitpick comments (13)
frontend/__tests__/unit/pages/OrganizationDetails.test.tsx (2)

48-60: Consider being more specific with loading spinner expectations

The test verifies that loading spinners exist but doesn't assert the exact count. While using toBeGreaterThan(0) provides some flexibility, consider asserting a specific count if the UI should consistently show a fixed number of spinners.

- expect(loadingSpinner.length).toBeGreaterThan(0)
+ expect(loadingSpinner.length).toBe(expectedNumberOfSpinners)

31-46: Consider adding tests for navigation functionality

The navigateMock is set up but not tested. Consider adding a test that verifies navigation occurs correctly when relevant elements are clicked.

test('navigates when organization name is clicked', async () => {
  render(<OrganizationDetailsPage />)
  
  await waitFor(() => {
    expect(screen.getByText('Test Organization')).toBeInTheDocument()
  })
  
  // Assuming there's a clickable element with the organization name
  fireEvent.click(screen.getByText('Test Organization'))
  
  expect(navigateMock).toHaveBeenCalledWith('/expected/path')
})
frontend/src/components/UserCard.tsx (1)

42-47: Consider adding accessibility attributes to the members icon

While the implementation correctly shows the members count when available, consider enhancing accessibility by adding descriptive attributes to the icon.

- <FontAwesomeIcon icon={faUsers} className="mr-1 h-4 w-4" />
+ <FontAwesomeIcon 
+   icon={faUsers} 
+   className="mr-1 h-4 w-4" 
+   aria-label="Members count" 
+   title="Number of members" 
+ />
backend/tests/apps/github/graphql/nodes/organization_test.py (1)

47-82: Consider enhancing type assertions for GraphQL fields

The tests verify field existence and types, but some assertions use string comparisons which are fragile.

- assert str(top_contributors_field.type) == "[RepositoryContributorNode]"
+ from apps.github.graphql.nodes.repository import RepositoryContributorNode
+ assert isinstance(top_contributors_field.type, List)
+ assert top_contributors_field.type.of_type == RepositoryContributorNode

- assert str(url_field.type) == "String"
+ from graphene import String
+ assert url_field.type == String
frontend/src/pages/Organization.tsx (1)

51-67: Layout implementation looks good but has a minor issue.

The SearchPageLayout is properly configured with all necessary props. The responsive grid layout for organization cards is well-structured.

However, there's a minor improvement suggested by the static analysis tool:

-        {organizations && organizations.map(renderOrganizationCard)}
+        {organizations?.map(renderOrganizationCard)}

Using optional chaining is more concise and equally safe for this use case.

🧰 Tools
🪛 Biome (1.9.4)

[error] 64-64: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

frontend/src/pages/OrganizationDetails.tsx (1)

26-39: Use optional chaining for more concise code.

The conditional check can be simplified using optional chaining for better readability.

  useEffect(() => {
-    if (data && data.organization) {
+    if (data?.organization) {
      setOrganization(data.organization)
      setIsLoading(false)
    }
    if (graphQLRequestError) {
      toaster.create({
        description: 'Unable to complete the requested operation.',
        title: 'GraphQL Request Failed',
        type: 'error',
      })
      setIsLoading(false)
+     setOrganization(null) // Explicitly set to null for consistency
    }
  }, [data, graphQLRequestError, organizationKey])
🧰 Tools
🪛 Biome (1.9.4)

[error] 27-27: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

backend/apps/github/index/organization.py (1)

49-53: Consider adding organizational synonyms

The method is defined but doesn't add any organization-specific synonyms yet. Consider adding common synonym pairs for organizational terms (e.g., "org", "organization", "company", "foundation").

 @staticmethod
 def update_synonyms():
     """Update synonyms for the organizations index."""
-    OrganizationIndex.reindex_synonyms("github", "organizations")
+    synonyms = [
+        {"objectID": "org_synonyms", "type": "synonym", 
+         "synonyms": ["org", "organization", "company", "foundation"]},
+        {"objectID": "inc_synonyms", "type": "synonym",
+         "synonyms": ["inc", "incorporated", "corporation", "corp"]}
+    ]
+    OrganizationIndex.reindex_synonyms("github", "organizations", synonyms)
frontend/__tests__/unit/data/mockOrganizationData.ts (1)

43-45: Consider handling potential line breaks in descriptions

The multi-line description format used here is good for readability. Ensure that your components properly handle potential line breaks or HTML formatting in real descriptions.

backend/apps/github/graphql/nodes/organization.py (2)

58-60: Consider removing unnecessary resolver.

This resolver simply returns the property value without any transformation or additional logic. Consider removing it as GraphQL can automatically resolve field values from object properties.

-    def resolve_url(self, info):
-        """Resolve organization URL."""
-        return self.url

110-138: Consider adding caching for top contributors.

Computing top contributors across all repositories can be expensive for large organizations. Consider adding caching or batching this operation, especially if it's called frequently.

frontend/__tests__/e2e/pages/OrganizationDetails.spec.ts (2)

6-11: Add test cases for error states and empty data.

All current tests are positive tests checking if elements are visible. Consider adding tests for error states (e.g., organization not found) and empty data scenarios (e.g., no repositories, issues, or contributors).


4-14: Consider using more specific route mocking.

The test mocks all GraphQL requests with the same response. If your component makes different GraphQL queries that require different responses, consider more specific route mocking that matches specific queries.

// Example of more specific route mocking
await page.route('**/graphql/', async (route) => {
  const body = JSON.parse(route.request().postData() || '{}');
  if (body.query.includes('organization')) {
    await route.fulfill({
      status: 200,
      json: { data: mockOrganizationDetailsData },
    });
  } else {
    // Handle other queries
    await route.continue();
  }
});
backend/apps/github/models/mixins/organization.py (1)

39-43: Handle potential None value explicitly.

While the ternary operator handles the None case for created_at, it would be clearer to use a more explicit check.

    @property
    def idx_created_at(self):
        """Return created at for indexing."""
-       return self.created_at.timestamp() if self.created_at else None
+       if self.created_at is None:
+           return None
+       return self.created_at.timestamp()
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc269c4 and 558f59a.

📒 Files selected for processing (27)
  • backend/apps/core/utils/index.py (1 hunks)
  • backend/apps/github/graphql/nodes/organization.py (1 hunks)
  • backend/apps/github/graphql/queries/__init__.py (2 hunks)
  • backend/apps/github/graphql/queries/organization.py (1 hunks)
  • backend/apps/github/index/__init__.py (1 hunks)
  • backend/apps/github/index/organization.py (1 hunks)
  • backend/apps/github/models/mixins/organization.py (1 hunks)
  • backend/tests/apps/github/graphql/nodes/organization_test.py (1 hunks)
  • backend/tests/apps/github/models/mixins/organization_test.py (1 hunks)
  • frontend/__tests__/e2e/pages/Organization.spec.ts (1 hunks)
  • frontend/__tests__/e2e/pages/OrganizationDetails.spec.ts (1 hunks)
  • frontend/__tests__/unit/data/mockOrganizationData.ts (1 hunks)
  • frontend/__tests__/unit/pages/Organization.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/OrganizationDetails.test.tsx (1 hunks)
  • frontend/src/App.tsx (2 hunks)
  • frontend/src/api/queries/organizationQueries.ts (1 hunks)
  • frontend/src/components/CardDetailsPage.tsx (3 hunks)
  • frontend/src/components/MultiSearch.tsx (7 hunks)
  • frontend/src/components/UserCard.tsx (2 hunks)
  • frontend/src/pages/Home.tsx (1 hunks)
  • frontend/src/pages/Organization.tsx (1 hunks)
  • frontend/src/pages/OrganizationDetails.tsx (1 hunks)
  • frontend/src/pages/index.ts (2 hunks)
  • frontend/src/types/card.ts (1 hunks)
  • frontend/src/types/organization.ts (1 hunks)
  • frontend/src/types/search.ts (2 hunks)
  • frontend/src/utils/constants.ts (1 hunks)
🧰 Additional context used
🧬 Code Definitions (14)
backend/apps/github/index/__init__.py (1)
backend/apps/github/index/organization.py (1)
  • OrganizationIndex (8-61)
frontend/__tests__/e2e/pages/Organization.spec.ts (1)
frontend/__tests__/unit/data/mockOrganizationData.ts (1)
  • mockOrganizationData (1-35)
frontend/src/App.tsx (1)
frontend/src/pages/index.ts (2)
  • OrganizationPage (28-28)
  • OrganizationDetailsPage (27-27)
frontend/__tests__/unit/pages/OrganizationDetails.test.tsx (2)
frontend/__tests__/unit/data/mockOrganizationData.ts (1)
  • mockOrganizationDetailsData (37-146)
frontend/src/pages/index.ts (1)
  • OrganizationDetailsPage (27-27)
backend/apps/github/graphql/queries/__init__.py (1)
backend/apps/github/graphql/queries/organization.py (1)
  • OrganizationQuery (10-41)
backend/tests/apps/github/graphql/nodes/organization_test.py (1)
backend/apps/github/graphql/nodes/organization.py (2)
  • OrganizationNode (32-138)
  • OrganizationStatsNode (22-29)
backend/tests/apps/github/models/mixins/organization_test.py (1)
backend/apps/github/models/mixins/organization.py (3)
  • is_indexable (8-10)
  • idx_description (45-47)
  • idx_collaborators_count (18-37)
frontend/src/components/UserCard.tsx (1)
frontend/src/types/card.ts (1)
  • UserCardProps (54-63)
frontend/src/pages/OrganizationDetails.tsx (2)
frontend/src/pages/index.ts (1)
  • OrganizationDetailsPage (27-27)
frontend/src/api/queries/organizationQueries.ts (1)
  • GET_ORGANIZATION_DATA (3-63)
frontend/__tests__/unit/pages/Organization.test.tsx (1)
frontend/__tests__/unit/data/mockOrganizationData.ts (1)
  • mockOrganizationData (1-35)
backend/apps/github/graphql/queries/organization.py (1)
backend/apps/github/graphql/nodes/organization.py (1)
  • OrganizationNode (32-138)
frontend/src/types/search.ts (1)
frontend/src/types/organization.ts (1)
  • OrganizationTypeAlgolia (1-16)
frontend/src/components/MultiSearch.tsx (1)
frontend/src/types/organization.ts (1)
  • OrganizationTypeAlgolia (1-16)
frontend/__tests__/e2e/pages/OrganizationDetails.spec.ts (1)
frontend/__tests__/unit/data/mockOrganizationData.ts (1)
  • mockOrganizationDetailsData (37-146)
🪛 Biome (1.9.4)
frontend/src/pages/Organization.tsx

[error] 64-64: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

frontend/src/pages/OrganizationDetails.tsx

[error] 27-27: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
🔇 Additional comments (56)
frontend/src/utils/constants.ts (1)

12-12: Navigation link addition looks good!

The addition of the "Organizations" link to the "Community" submenu is well-placed and follows the established pattern for navigation items. This properly integrates the new organization pages into the application's navigation structure.

frontend/__tests__/e2e/pages/Organization.spec.ts (1)

1-30: Well-structured organization page test suite.

The test suite is well-organized with appropriate setup and assertions. It correctly mocks the API response for organization data and includes tests for both rendering and navigation functionality.

frontend/src/pages/Home.tsx (1)

140-140: Good addition of 'organizations' to the search indexes.

Adding 'organizations' to the MultiSearchBar indexes enables users to search for organizations from the main page, which is one of the key objectives of this PR. The indexes are properly ordered alphabetically.

frontend/src/App.tsx (2)

8-9: Properly imported the new organization page components.

The new organization components are correctly imported and maintain the alphabetical ordering convention.


54-55: Correctly added routes for organization pages.

The routes follow the application's established pattern - a list route at /organizations and a details route at /organization/:organizationKey with a parameter for the specific organization.

backend/apps/core/utils/index.py (1)

118-130: Appropriate addition of organization attributes for indexing.

The new case for "organizations" in the get_params_for_index function includes all the essential attributes needed for search functionality. The attributes are comprehensive and will allow for effective organization searching and display.

frontend/__tests__/unit/pages/OrganizationDetails.test.tsx (3)

1-46: Good test setup with comprehensive mocks!

The test file is well-structured with properly mocked dependencies. Good use of before/after hooks, and clear separation of testing concerns.


62-80: Well-structured test with comprehensive assertions

This test effectively verifies all the key organizational details are rendered correctly when data is available.


82-134: Tests cover all component sections thoroughly

The tests for organization stats, issues, releases, contributors, and error handling are well-organized and complete. This comprehensive coverage ensures the component behaves correctly across various scenarios.

frontend/src/components/UserCard.tsx (2)

2-2: Good icon import for the new members functionality

The additional FontAwesome icon import is appropriate for the new feature.


6-15: Props signature update looks good

The component signature has been properly updated to include the new members property.

frontend/src/types/search.ts (2)

3-3: Good import for the new organization type

The import for OrganizationTypeAlgolia is appropriate and follows the existing pattern.


15-22: Well-structured union type update for search suggestions

The OrganizationTypeAlgolia[] has been properly added to the union type, enabling organization search functionality.

backend/tests/apps/github/graphql/nodes/organization_test.py (2)

1-46: Good test structure for OrganizationNode

The tests are well-organized with clear descriptions and assertions to verify the inheritance hierarchy and field configuration.


84-96: Good test for OrganizationStatsNode

The test effectively verifies that the OrganizationStatsNode has all the expected fields.

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

1-16: Interface definition looks good.

The OrganizationTypeAlgolia interface is well-structured with appropriate types and optional fields. This provides good type safety for organization data from Algolia search.

One note: the timestamp fields (created_at and updated_at) are defined as numbers, implying Unix timestamps. This is fine, but make sure any component displaying these values handles the conversion to readable dates consistently.

backend/apps/github/graphql/queries/__init__.py (1)

4-4: GraphQL organization query integration looks good.

The OrganizationQuery class is properly imported and added to the GithubQuery inheritance list, extending the GraphQL schema with organization query capabilities. The alphabetical ordering of both imports and class inheritance is maintained, which is good practice.

Also applies to: 14-14

frontend/src/pages/Organization.tsx (2)

1-7: Imports look good.

All necessary imports are present for the component's functionality, including hooks, types, and UI components.


8-24: Component setup and hook usage looks good.

The component properly uses the useSearchPage hook with appropriate type parameters and configuration for organization data. The navigation hook is also correctly initialized.

frontend/__tests__/unit/pages/Organization.test.tsx (4)

1-24: Test setup and mocks look good.

The component imports and mocks are properly set up, including mocks for external dependencies like fetchAlgoliaData and useNavigate. The pagination component mock is also well-implemented to simulate page navigation.


25-36: Test lifecycle hooks are properly implemented.

The beforeEach and afterEach hooks correctly set up the test environment and clean up after each test, which is a good practice.


37-45: Basic rendering test looks good.

The test correctly verifies that organization names appear in the rendered component after data is loaded.


47-62: Pagination test is well-implemented.

The test properly mocks window.scrollTo and verifies it's called with the expected parameters when changing pages. This ensures that the page scrolls to the top after navigation.

frontend/src/components/CardDetailsPage.tsx (3)

78-79: LGTM! Statistics section now supports organizations.

The conditional rendering logic has been appropriately extended to display statistics for organizations alongside users, projects, repositories, and committees.


124-127: LGTM! Recent Issues and Releases sections now support organizations.

The conditional rendering has been properly updated to display the grid containing Recent Issues and Recent Releases for organizations, consistent with how it's handled for projects, repositories, and users.


142-147: LGTM! Repositories section now supports organizations.

The code appropriately extends the Repositories section to be displayed for organizations when they have repositories, which is a logical addition since organizations are collections of repositories.

backend/apps/github/graphql/queries/organization.py (1)

1-42: LGTM! Well-structured GraphQL query implementation for organizations.

The OrganizationQuery class is well-designed with appropriate fields for fetching a single organization by login and a list of organizations with filtering options. The resolver method includes proper error handling.

frontend/src/pages/OrganizationDetails.tsx (4)

45-53: LGTM! Appropriate error handling when organization is not found.

The component correctly displays a user-friendly error message when the organization doesn't exist, which provides a good user experience.


55-76: LGTM! Well-structured organization details.

The organization details array is well-organized with appropriate fields including GitHub profile link, join date, followers count, and location with a fallback for missing data.


78-105: LGTM! Comprehensive statistics with appropriate icons.

The statistics are well-structured with appropriate icons that visually represent each metric, and the pluralization handling for repositories is correctly implemented.


107-119: LGTM! Proper usage of DetailsCard component.

The component correctly passes all necessary props to the DetailsCard component, ensuring consistent display of organization information.

frontend/src/api/queries/organizationQueries.ts (1)

3-63: LGTM! Comprehensive GraphQL query for organization data.

The query is well-structured and retrieves all necessary data for displaying detailed organization information, including basic details, statistics, repositories, issues, releases, and top contributors.

backend/tests/apps/github/models/mixins/organization_test.py (5)

5-5: Good practice defining a constant for test values

Using a named constant EXPECTED_CONTRIBUTOR_COUNT instead of hardcoding the value directly in the test improves readability and maintainability.


19-30: LGTM - Comprehensive test for is_indexable property

The test correctly covers all possible combinations of name and login attributes, ensuring the organization is only indexable when both are present.


32-38: LGTM - Good test coverage for idx_description property

Both test cases (with value and empty) ensure the idx_description property correctly handles all scenarios.


40-63: Well-structured test for idx_collaborators_count with proper mocking

This test effectively uses mocking to verify both paths in the idx_collaborators_count implementation:

  1. When no repositories exist (returning collaborators_count)
  2. When repositories exist (returning count of distinct contributors)

The assertions verify both the return values and that the correct filter arguments were used.


11-11:

❓ Verification inconclusive

Verify the removal of the "idx_company" test case

I notice that the parameterized test now only includes the "idx_name" attribute test case, removing what appears to have been an "idx_company" test. Make sure this removal was intentional and that you're not losing test coverage.


🏁 Script executed:

#!/bin/bash
# Check if the organization model still has an idx_company property
rg -A 2 -B 2 "def idx_company" backend/apps/github/models/mixins/organization.py

Length of output: 82


Action Required: Confirm Intentional Removal of "idx_company" Test Case

After running a search for any occurrences of idx_company in the Organization model, no definitions (e.g., a def idx_company) were found. This suggests that the removal of the idx_company test case was likely intentional. However, please manually verify that there is indeed no dependent functionality or business logic requiring the idx_company attribute to avoid any unintended loss of test coverage.

  • Verification Points:
    • Confirm that the removal of the idx_company test case aligns with the overall refactoring strategy.
    • Double-check any related documentation or recent changes that might reference the idx_company attribute.
backend/apps/github/index/organization.py (6)

7-10: LGTM - Organization index class properly registered

The @register(Organization) decorator correctly associates this index class with the Organization model.


11-11: Consistent index naming

The index name "organizations" follows the naming convention used throughout the codebase for other entity types.


13-23: LGTM - Comprehensive field selection for organization indexing

The fields include all relevant organization properties needed for search and display in the UI, including metrics like followers and collaborators counts that will help with ranking results.


25-45: Well-configured search settings with appropriate ranking strategy

The search configuration:

  1. Sets a reasonable minimum proximity value
  2. Prioritizes organizations with more followers, contributors, and recent creation
  3. Uses standard Algolia ranking criteria
  4. Makes organization names and logins searchable in any order

This will provide relevant search results that prioritize popular and active organizations.


47-47: LGTM - Properly configured indexability criteria

Setting should_index = "is_indexable" correctly uses the property tested in organization_test.py to determine which organizations should be indexed.


54-61: LGTM - Simple entity retrieval method

The get_entities method correctly retrieves all Organization objects for indexing.

frontend/__tests__/unit/data/mockOrganizationData.ts (2)

1-35: LGTM - Well-structured mock organization list data

The mock organization data provides realistic test values for all required fields and includes multiple organizations with different characteristics. This is excellent for testing the organizations list view.


37-146: LGTM - Comprehensive mock data for organization details

The mock data for organization details is thorough and includes:

  1. Basic organization information
  2. Statistics summary
  3. Repository listings with metrics
  4. Issue listings with authors
  5. Release information with linked repositories
  6. Top contributors with contribution counts

This mock data covers all the components needed for the organization details page.

frontend/src/components/MultiSearch.tsx (7)

8-8: LGTM - Appropriate icon selection for organizations

Adding the faBuilding icon is a good choice to represent organizations in the UI.


18-18: LGTM - Type import for organization data

Adding the OrganizationTypeAlgolia type import ensures proper type checking for organization search results.


53-57: LGTM - Updated hits type to include organizations

The type definition for hits has been properly updated to include OrganizationTypeAlgolia[].


89-96: LGTM - Updated function signature to support organization type

The handleSuggestionClick function signature has been appropriately updated to include OrganizationTypeAlgolia in the union type.


108-110: LGTM - Added navigation case for organizations

The switch statement case for organizations correctly navigates to the organization detail page using the login as the identifier.


131-136: LGTM - Updated type cast in key handler

The type cast in the key down handler has been properly updated to include OrganizationTypeAlgolia.


216-217: LGTM - Added icon mapping for organizations

The getIconForIndex function now correctly returns the faBuilding icon for organization search results.

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

4-4: Import looks good!

The addition of OrganizationIndex import aligns with the PR objective of implementing organization-related features. This will make the organization indexing functionality available to the GitHub app.

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

61-61: Good addition of the members property.

Adding this optional property to the UserCardProps interface allows the component to display organization member counts, which aligns well with the new organization pages being implemented.

frontend/src/pages/index.ts (2)

11-12: Imports for new organization pages look good.

These imports correctly bring in the new Organization and OrganizationDetails pages, aligning with the PR objective.


27-28: Proper export of new pages.

The organization pages are correctly exported, making them available to the routing system and other parts of the application.

@Dishant1804 Dishant1804 marked this pull request as draft April 6, 2025 21:12
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: 1

🧹 Nitpick comments (3)
backend/apps/github/graphql/nodes/organization.py (1)

91-96: Paging or limiting repository results.
Currently, the code retrieves the top 10 repositories according to stars in resolve_repositories, which is good. However, consider whether further pagination or filtering is necessary for organizations with more than 10 noteworthy repositories.

frontend/src/app/organization/page.tsx (1)

64-66: Use optional chaining for safer access to organizations.

Consider using optional chaining to safely access the organizations array.

-        {organizations && organizations.map(renderOrganizationCard)}
+        {organizations?.map(renderOrganizationCard)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 65-65: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

frontend/src/app/organization/[organizationKey]/page.tsx (1)

27-43: Consider using optional chaining in the useEffect dependency check.

The conditional check for data could be simplified using optional chaining.

-    if (data && data.organization) {
+    if (data?.organization) {

Also, good error handling with appropriate toast notifications and loading state management.

🧰 Tools
🪛 Biome (1.9.4)

[error] 28-28: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 558f59a and 08320f1.

📒 Files selected for processing (14)
  • backend/apps/github/graphql/nodes/organization.py (1 hunks)
  • frontend/__tests__/e2e/pages/Organization.spec.ts (1 hunks)
  • frontend/__tests__/e2e/pages/OrganizationDetails.spec.ts (1 hunks)
  • frontend/__tests__/unit/pages/Organization.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/OrganizationDetails.test.tsx (1 hunks)
  • frontend/src/app/organization/[organizationKey]/page.tsx (1 hunks)
  • frontend/src/app/organization/page.tsx (1 hunks)
  • frontend/src/app/page.tsx (1 hunks)
  • frontend/src/components/CardDetailsPage.tsx (3 hunks)
  • frontend/src/components/MultiSearch.tsx (7 hunks)
  • frontend/src/components/UserCard.tsx (2 hunks)
  • frontend/src/server/queries/organizationQueries.ts (1 hunks)
  • frontend/src/types/card.ts (1 hunks)
  • frontend/src/utils/constants.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
  • frontend/src/utils/constants.ts
  • frontend/src/types/card.ts
  • frontend/src/components/UserCard.tsx
  • frontend/tests/e2e/pages/Organization.spec.ts
  • frontend/src/components/CardDetailsPage.tsx
  • frontend/tests/unit/pages/Organization.test.tsx
  • frontend/tests/unit/pages/OrganizationDetails.test.tsx
  • frontend/tests/e2e/pages/OrganizationDetails.spec.ts
🧰 Additional context used
🧬 Code Definitions (4)
frontend/src/app/organization/[organizationKey]/page.tsx (3)
frontend/src/server/queries/organizationQueries.ts (1)
  • GET_ORGANIZATION_DATA (3-63)
frontend/src/wrappers/ErrorWrapper.tsx (1)
  • ErrorDisplay (26-49)
frontend/src/utils/dateFormatter.ts (1)
  • formatDate (1-16)
frontend/src/app/organization/page.tsx (2)
frontend/src/hooks/useSearchPage.ts (1)
  • useSearchPage (30-135)
frontend/src/types/organization.ts (1)
  • OrganizationTypeAlgolia (1-16)
frontend/src/components/MultiSearch.tsx (4)
frontend/src/types/organization.ts (1)
  • OrganizationTypeAlgolia (1-16)
frontend/src/types/chapter.ts (1)
  • ChapterTypeAlgolia (9-24)
frontend/src/types/project.ts (1)
  • ProjectTypeAlgolia (25-46)
frontend/src/types/event.ts (1)
  • EventType (1-10)
backend/apps/github/graphql/nodes/organization.py (7)
backend/apps/common/graphql/nodes.py (1)
  • BaseNode (6-10)
backend/apps/github/graphql/nodes/issue.py (1)
  • IssueNode (7-19)
backend/apps/github/graphql/nodes/release.py (1)
  • ReleaseNode (11-39)
backend/apps/github/graphql/nodes/repository_contributor.py (1)
  • RepositoryContributorNode (6-14)
backend/apps/github/models/organization.py (1)
  • Organization (12-88)
backend/apps/github/models/repository.py (1)
  • Repository (22-332)
backend/apps/github/models/repository_contributor.py (1)
  • RepositoryContributor (12-104)
🪛 Biome (1.9.4)
frontend/src/app/organization/[organizationKey]/page.tsx

[error] 28-28: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

frontend/src/app/organization/page.tsx

[error] 65-65: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (18)
backend/apps/github/graphql/nodes/organization.py (3)

6-16: Consider verifying permissions for private organizations.
While this GraphQL node effectively exposes organization data, verify whether any authorization checks or visibility rules are required to ensure that private or restricted organizations are not unintentionally exposed.


62-90: Great use of the Django aggregation functions for organization stats.
This implementation is a significant performance improvement over iterating Python-side for large data sets and aligns well with past review suggestions.


115-143: Efficient top contributors retrieval.
Good job leveraging the TOP_CONTRIBUTORS_LIMIT to cap the query size, preventing excessive data loads for organizations with large contributor bases.

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

145-145: Confirm “organizations” index availability.
Including 'organizations' in the search indexes is appropriate for the new organization feature. Ensure that this Algolia index is actually available and properly configured, or the search might fail.

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

1-2: No immediate concerns with the GraphQL query definition.
All fields mesh well with the back-end schema, and the use of the $login variable is straightforward.

frontend/src/app/organization/page.tsx (3)

9-69: Good implementation of the OrganizationPage component.

The component structure follows best practices by separating concerns and reusing existing components. The useSearchPage hook is appropriately configured for organizations, and the router navigation is implemented correctly.

🧰 Tools
🪛 Biome (1.9.4)

[error] 65-65: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


26-50: Well-structured card rendering logic.

The renderOrganizationCard function is well-organized and handles navigation properly. The component encapsulation is clean, with a clear separation between navigation logic and presentation.


52-68: Good use of SearchPageLayout for consistent UX.

Using the SearchPageLayout component ensures consistent search experience across the application. The responsive grid layout with appropriate breakpoints is also well implemented.

🧰 Tools
🪛 Biome (1.9.4)

[error] 65-65: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

frontend/src/app/organization/[organizationKey]/page.tsx (4)

19-25: Well-structured component initialization.

Good use of React hooks for state management and GraphQL query setup. The component correctly extracts the organizationKey from URL parameters and sets up the appropriate initial states.


45-57: Good user experience handling for loading and error states.

The component properly handles loading states with a spinner and displays a user-friendly error message when an organization isn't found. This ensures a good user experience even in edge cases.


59-109: Well-structured organization data formatting.

The arrays for organization details and stats are well-structured and properly handle optional fields with fallbacks (e.g., organization.location || 'Not provided'). The pluralization for repositories is a nice touch for better UI text.


111-123: Clean rendering of DetailsCard with appropriate props.

The component correctly passes all necessary data to the DetailsCard component, ensuring a consistent display of organization information. Setting the type to "organization" is important for the DetailsCard to render appropriately.

frontend/src/components/MultiSearch.tsx (6)

7-8: Good integration of organization search functionality.

The import of the necessary icon and type for organizations is well implemented, maintaining consistency with the existing code structure.

Also applies to: 17-18


54-56: Well-integrated type update for hits array.

Adding OrganizationTypeAlgolia to the hit types ensures proper type safety when handling organization search results.


88-96: Properly expanded function signature for suggestion handling.

The updated function signature correctly includes OrganizationTypeAlgolia as a potential suggestion type, maintaining type safety.


108-113: Good implementation of organization navigation with type safety.

The new case for organizations includes a proper type guard to safely access the login property. This ensures type safety and prevents potential runtime errors.


133-140: Consistent update to Enter key handler typecasting.

The typecasting in the keydown handler has been properly updated to include OrganizationTypeAlgolia, ensuring consistency with the handleSuggestionClick function.


219-220: Well-implemented icon selection for organizations.

Adding the building icon for organizations in the getIconForIndex function provides a clear visual indication of organization results in the search dropdown.

@Dishant1804 Dishant1804 marked this pull request as ready for review April 7, 2025 05:59
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 (3)
frontend/src/app/organization/page.tsx (3)

26-50: Consider key placement and null handling for organization properties.

The component key is provided in the UserCard instead of the root element of the mapped item. Also, some fields might benefit from improved null handling.

  return (
+     <div key={organization.objectID}>
      <UserCard
        button={SubmitButton}
-       key={organization.objectID}
        avatar={organization.avatar_url}
-       name={organization.name}
+       name={organization.name || organization.login}
        company={organization.company || ''}
        email={organization.email || ''}
        location={organization.location || `@${organization.login}`}
        members={organization.collaborators_count}
        className="h-64 w-80 bg-white p-6 text-left shadow-lg transition-transform duration-500 hover:scale-105 hover:shadow-xl dark:bg-gray-800 dark:shadow-gray-900/30"
      />
+     </div>
    )

52-68: Consider using optional chaining for improved code readability.

The code works as is, but could be improved by using optional chaining.

-        {organizations && organizations.map(renderOrganizationCard)}
+        {organizations?.map(renderOrganizationCard)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 65-65: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


64-66: Consider adding a loading state and error handling for better UX.

While the component passes isLoaded to the SearchPageLayout, there isn't explicit handling of loading states or errors in the grid display itself.

      <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
-        {organizations && organizations.map(renderOrganizationCard)}
+        {!isLoaded ? (
+          <div className="col-span-full text-center">Loading organizations...</div>
+        ) : organizations?.length === 0 ? (
+          <div className="col-span-full text-center">No organizations found</div>
+        ) : (
+          organizations.map(renderOrganizationCard)
+        )}
      </div>
🧰 Tools
🪛 Biome (1.9.4)

[error] 65-65: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1501068 and 56b6ac3.

📒 Files selected for processing (1)
  • frontend/src/app/organization/page.tsx (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
frontend/src/app/organization/page.tsx

[error] 65-65: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
  • GitHub Check: CodeQL (python)
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (3)
frontend/src/app/organization/page.tsx (3)

1-8: Well-structured imports with good organization.

The component properly uses 'use client' directive for Next.js client components, and has organized imports logically by grouping hooks, types, and UI components.


9-23: Good use of the custom hook for search functionality.

The component effectively leverages the useSearchPage hook with appropriate type parameters and configuration for the organization search. The clear destructuring of returned values makes the code readable.


71-72: Export is properly defined.

The component is correctly exported as the default export.

@github-actions github-actions bot added nestbot and removed backend labels Apr 9, 2025
Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

Let's start from:

  • add recent PRs for org details page (extend pull_request graphql endpoint w/ organization filter)
  • move issue resolver logic to existing recent issues endpoint (extend w/ filtering by org)
  • move release resolver logic to existing recent releases endpoint (extend w/ filtering by org)
  • move repositories resolver logic to existing repository endpoint (create a new one w/ filtering by org)
  • move top contributors resolver logic to existing repository contributor endpoint (extend w/ filtering by org)

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

♻️ Duplicate comments (2)
backend/tests/apps/github/graphql/nodes/organization_test.py (1)

1-97: Good test structure for OrganizationNode and OrganizationStatsNode.

The tests verify the structure, inheritance, and field configurations of both GraphQL nodes, which is essential for ensuring the schema is correctly defined.

Add tests for resolver methods

The current tests verify field types but don't test the actual resolver methods functionality. Consider adding tests that check if the resolvers return the expected data.

def test_resolve_url_returns_correct_value(self):
    """Test if resolve_url returns the correct URL."""
    mock_organization = MagicMock()
    mock_organization.url = "https://github.com/test-org"
    
    node = OrganizationNode(mock_organization)
    result = node.resolve_url(None)
    
    assert result == "https://github.com/test-org"
backend/apps/github/graphql/nodes/organization.py (1)

58-86: Optimized stats resolution with aggregation.

The resolve_stats method efficiently calculates organization statistics using Django's aggregation functions, which is a performant approach for handling large datasets.

🧹 Nitpick comments (4)
frontend/src/app/community/members/page.tsx (1)

27-27: URL path correctly updated from 'users' to 'members'.

The navigation path update aligns with the new URL structure for accessing member profiles.

Consider renaming the component from UsersPage to MembersPage and updating other UI text references (like "OWASP Users" in pageTitle and "Search for OWASP users..." in the search placeholder) to maintain terminology consistency with the new URL path.

frontend/__tests__/e2e/pages/Organizations.spec.ts (1)

1-38: Well-structured e2e tests for the new Organization page.

The tests properly mock the API response, set up authentication, and verify both rendering and navigation functionality of the new Organizations page.

The navigation test on line 34-37 could be more specific with its assertion. Consider checking for a more specific URL pattern:

- expect(await page.url()).toContain('organizations')
+ expect(await page.url()).toMatch(/\/organizations\/[^\/]+$/)

This would ensure navigation leads to a specific organization detail page, not just any URL containing "organizations".

frontend/src/app/organizations/[organizationKey]/page.tsx (1)

27-43: Use optional chaining for more concise data access.

Consider using optional chaining for safer and more concise data access.

  useEffect(() => {
-    if (data && data.organization) {
+    if (data?.organization) {
      setOrganization(data.organization)
      setIsLoading(false)
    }
    if (graphQLRequestError) {
      addToast({
        description: 'Unable to complete the requested operation.',
        title: 'GraphQL Request Failed',
        timeout: 3000,
        shouldShowTimeoutProgress: true,
        color: 'danger',
        variant: 'solid',
      })
      setIsLoading(false)
    }
  }, [data, graphQLRequestError, organizationKey])
🧰 Tools
🪛 Biome (1.9.4)

[error] 28-28: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

backend/apps/github/graphql/nodes/organization.py (1)

87-142: Optimize repeated repository queries in resolver methods.

Multiple resolver methods (resolve_repositories, resolve_issues, resolve_releases, and resolve_top_contributors) all perform separate queries to fetch repositories for the organization.

Consider caching the repository query in a single method or property to reduce database hits:

+ def get_repositories(self):
+     """Get repositories for the organization with caching."""
+     if not hasattr(self, '_repositories'):
+         self._repositories = Repository.objects.filter(organization=self)
+     return self._repositories

  def resolve_repositories(self, info):
      """Resolve repositories for the organization."""
-     return Repository.objects.filter(organization=self).order_by("-stars_count")[
+     return self.get_repositories().order_by("-stars_count")[
          :RECENT_REPOSITORIES_LIMIT
      ]

  def resolve_issues(self, info):
      """Resolve issues for the organization."""
-     repositories = Repository.objects.filter(organization=self)
+     repositories = self.get_repositories()
      return (
          Issue.objects.filter(repository__in=repositories)
          .select_related("repository", "author")
          .order_by("-created_at")[:RECENT_ISSUES_LIMIT]
      )

  def resolve_releases(self, info):
      """Resolve releases for the organization."""
-     repositories = Repository.objects.filter(organization=self)
+     repositories = self.get_repositories()
      return (
          Release.objects.filter(repository__in=repositories)
          .select_related("repository", "author")
          .order_by("-published_at")[:RECENT_RELEASES_LIMIT]
      )

  def resolve_top_contributors(self, info):
      """Resolve top contributors for the organization."""
      top_contributors = (
-         RepositoryContributor.objects.filter(repository__in=self.repository_set.all())
+         RepositoryContributor.objects.filter(repository__in=self.get_repositories())
          .values(
              "user__id",
              "user__login",
              "user__name",
              "user__avatar_url",
          )
          .annotate(total_contributions=models.Sum("contributions_count"))
          .order_by("-total_contributions")[:TOP_CONTRIBUTORS_LIMIT]
      )

This optimization will reduce the number of database queries needed for fetching the same set of repositories multiple times.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 56b6ac3 and 786354c.

📒 Files selected for processing (32)
  • backend/apps/common/management/commands/generate_sitemap.py (2 hunks)
  • backend/apps/github/graphql/nodes/organization.py (1 hunks)
  • backend/apps/slack/commands/community.py (1 hunks)
  • backend/apps/slack/common/handlers/users.py (1 hunks)
  • backend/tests/apps/github/graphql/nodes/organization_test.py (1 hunks)
  • backend/tests/apps/slack/commands/community_test.py (2 hunks)
  • frontend/__tests__/e2e/pages/About.spec.ts (1 hunks)
  • frontend/__tests__/e2e/pages/OrganizationDetails.spec.ts (1 hunks)
  • frontend/__tests__/e2e/pages/Organizations.spec.ts (1 hunks)
  • frontend/__tests__/e2e/pages/UserDetails.spec.ts (1 hunks)
  • frontend/__tests__/e2e/pages/Users.spec.tsx (3 hunks)
  • frontend/__tests__/unit/data/mockAboutData.ts (1 hunks)
  • frontend/__tests__/unit/pages/About.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/Organization.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/OrganizationDetails.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/ProjectDetails.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/RepositoryDetails.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/UserDetails.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/Users.test.tsx (2 hunks)
  • frontend/src/app/about/page.tsx (1 hunks)
  • frontend/src/app/community/members/page.tsx (1 hunks)
  • frontend/src/app/organizations/[organizationKey]/page.tsx (1 hunks)
  • frontend/src/app/organizations/page.tsx (1 hunks)
  • frontend/src/components/ContributorAvatar.tsx (1 hunks)
  • frontend/src/components/ItemCardList.tsx (1 hunks)
  • frontend/src/components/LeadersList.tsx (1 hunks)
  • frontend/src/components/MultiSearch.tsx (7 hunks)
  • frontend/src/components/RecentReleases.tsx (1 hunks)
  • frontend/src/components/TopContributors.tsx (1 hunks)
  • frontend/src/components/UserCard.tsx (2 hunks)
  • frontend/src/types/card.ts (1 hunks)
  • frontend/src/utils/constants.ts (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • backend/apps/slack/common/handlers/users.py
  • backend/apps/slack/commands/community.py
  • frontend/tests/unit/pages/UserDetails.test.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
  • frontend/src/types/card.ts
  • frontend/tests/unit/pages/Organization.test.tsx
  • frontend/tests/unit/pages/OrganizationDetails.test.tsx
  • frontend/src/components/UserCard.tsx
  • frontend/src/utils/constants.ts
  • frontend/src/components/MultiSearch.tsx
  • frontend/tests/e2e/pages/OrganizationDetails.spec.ts
🧰 Additional context used
🧬 Code Graph Analysis (8)
backend/apps/common/management/commands/generate_sitemap.py (1)
frontend/src/types/user.ts (1)
  • user (3-17)
frontend/src/app/community/members/page.tsx (1)
frontend/src/types/user.ts (1)
  • user (3-17)
frontend/__tests__/e2e/pages/Organizations.spec.ts (1)
frontend/__tests__/unit/data/mockOrganizationData.ts (1)
  • mockOrganizationData (1-35)
backend/tests/apps/github/graphql/nodes/organization_test.py (6)
backend/apps/common/graphql/nodes.py (1)
  • BaseNode (6-10)
backend/apps/github/graphql/nodes/issue.py (1)
  • IssueNode (7-19)
backend/apps/github/graphql/nodes/organization.py (2)
  • OrganizationNode (32-141)
  • OrganizationStatsNode (22-29)
backend/apps/github/graphql/nodes/release.py (1)
  • ReleaseNode (11-39)
backend/apps/github/graphql/nodes/repository.py (1)
  • RepositoryNode (15-81)
backend/apps/github/models/organization.py (1)
  • Organization (12-88)
frontend/src/components/ContributorAvatar.tsx (1)
frontend/src/types/link.ts (1)
  • Link (1-6)
frontend/src/app/organizations/[organizationKey]/page.tsx (3)
frontend/src/server/queries/organizationQueries.ts (1)
  • GET_ORGANIZATION_DATA (3-63)
frontend/src/wrappers/ErrorWrapper.tsx (1)
  • ErrorDisplay (26-49)
frontend/src/utils/dateFormatter.ts (1)
  • formatDate (1-16)
frontend/src/app/organizations/page.tsx (2)
frontend/src/hooks/useSearchPage.ts (1)
  • useSearchPage (30-135)
frontend/src/types/organization.ts (1)
  • OrganizationTypeAlgolia (1-16)
backend/apps/github/graphql/nodes/organization.py (7)
backend/apps/common/graphql/nodes.py (1)
  • BaseNode (6-10)
backend/apps/github/graphql/nodes/issue.py (1)
  • IssueNode (7-19)
backend/apps/github/graphql/nodes/release.py (1)
  • ReleaseNode (11-39)
backend/apps/github/graphql/nodes/repository_contributor.py (1)
  • RepositoryContributorNode (6-14)
backend/apps/github/models/organization.py (1)
  • Organization (12-88)
backend/apps/github/models/repository.py (1)
  • Repository (22-332)
backend/apps/github/models/repository_contributor.py (1)
  • RepositoryContributor (12-104)
🪛 Biome (1.9.4)
frontend/src/app/organizations/[organizationKey]/page.tsx

[error] 28-28: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

frontend/src/app/organizations/page.tsx

[error] 65-65: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run backend tests
🔇 Additional comments (33)
backend/tests/apps/slack/commands/community_test.py (2)

45-46: URL path updated to use "members" instead of "users".

The URL has been updated to reflect the new routing structure from "users" to "members", which is consistent with the PR objectives of enhancing organization-related features.


62-62: Assertion updated to match new URL pattern.

This assertion has been correctly updated to check for the new URL pattern, maintaining test integrity while reflecting the path change from "users" to "members".

backend/apps/common/management/commands/generate_sitemap.py (2)

27-27: Static route path updated from "users" to "members".

The sitemap static route has been correctly updated to use the new path structure while maintaining the same change frequency and priority values.


152-157: Individual user paths updated to use "members" instead of "users".

The dynamic path generation for individual user pages has been correctly updated to use the new URL structure. The change is consistent with updates in other files and properly utilizes the user's login property.

frontend/__tests__/e2e/pages/About.spec.ts (1)

85-85: URL path correctly updated from 'users' to 'members'.

This change aligns with the updated URL structure for accessing member profiles throughout the application.

frontend/__tests__/e2e/pages/UserDetails.spec.ts (1)

20-20: URL path correctly updated from 'users' to 'members'.

This change ensures the test navigates to the correct URL path, consistent with the updated routing structure.

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

51-51: URL path correctly updated from 'users' to 'members'.

This change ensures contributors' profile links point to the correct URL path, consistent with the updated routing structure.

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

43-43: Path update aligns with application-wide change from "users" to "members".

This change is part of a consistent update across the application to standardize the URL structure, changing user paths from /community/users/ to /community/members/. This modification supports the organization implementation by ensuring consistent navigation patterns throughout the application.

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

34-34: Path update aligns with application-wide change from "users" to "members".

This change is consistent with the URL structure standardization seen across the application, updating author profile links from /community/users/ to /community/members/. This ensures navigation consistency as part of the organization implementation.

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

409-409: Test data URL updated to match new member path structure.

The test data has been correctly updated to reflect the new URL structure, ensuring test cases remain valid with the application-wide change from /community/users/ to /community/members/.

frontend/src/app/about/page.tsx (1)

175-176: Profile link in onclick handler updated to use "members" path.

The profile navigation has been consistently updated from /community/users/${username} to /community/members/${username} to align with the standardized URL structure throughout the application.

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

25-25: URL path updated to align with new member-centric routing structure.

The change from "users" to "members" in the URL path is consistent with other changes in the codebase related to the organization implementation.

frontend/__tests__/e2e/pages/Users.spec.tsx (1)

23-23:

❓ Verification inconclusive

URL paths updated correctly to the new member-centric routing structure.

The URL changes from /community/users to /community/members are consistent with other changes in this PR.

Verify if the test file name and message text should also be updated for consistency:

  1. The test file is still named Users.spec.tsx but tests /members routes
  2. Line 39 still checks for "No Users Found" text - verify if the actual UI text has been updated

Also applies to: 38-39, 55-55


🏁 Script executed:

#!/bin/bash
# Check if the UI text has been updated to "No Members Found"
rg -i "No Members Found" --type=tsx --type=ts

Length of output: 75


Verify UI Text and File Naming Consistency

The URL path changes to /community/members are correctly applied, but please verify the following manually:

  • The test file is still named Users.spec.tsx even though the tested route is now /members.
  • The test still checks for "No Users Found" text (e.g., on line 39) – confirm if the UI has been updated to "No Members Found".

The above script is intended to check for any occurrences of "No Members Found" in .tsx files. If no output is found, please manually verify if this discrepancy is intentional or if the test text and/or file name require updating.


🏁 Script executed:

#!/bin/bash
# Re-run the search using a custom tsx file type so that .tsx files are included
rg --type-add 'tsx:*.tsx' --type tsx -i "No Members Found" .

Length of output: 184


Manual Verification Needed for UI Consistency

The URL changes to /community/members are correct, but there are two potential inconsistencies that need manual verification:

  • The test file is still named Users.spec.tsx even though it now tests member-related routes.
  • The test still checks for "No Users Found" text (likely on or around line 39). Please verify if the UI text has been updated to "No Members Found" or if the test text should remain unchanged.

Please verify these points to ensure consistency across the codebase.

frontend/__tests__/unit/data/mockAboutData.ts (1)

29-29: Mock data URLs updated correctly to match the new routing structure.

The changes consistently update all user URLs from /community/users/{username} to /community/members/{username} in the mock data, which aligns with the other changes in this PR.

Also applies to: 35-35, 41-41

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

43-43: Navigation path updated to align with new member-centric routing structure.

The change from "users" to "members" in the onClick navigation handler is consistent with the other routing changes across the codebase related to the organization implementation.

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

135-135: URL path updated correctly.

The updated path reflects the change from "users" to "members" in the URL routing structure, which is consistent with the organizational path changes mentioned in the PR objectives. This ensures tests pass after the URL structure update.

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

133-133: URL path updated correctly.

The path has been updated from /community/users/contributor1 to /community/members/contributor1, aligning with the consistent URL structure changes throughout the application.

frontend/__tests__/unit/pages/Users.test.tsx (2)

6-6: Path update correctly migrates from 'users' to 'members'.

The import path has been updated to reflect the new routing structure, which aligns with the organization-related changes mentioned in the PR objectives.


133-133: Test assertion properly updated for new URL structure.

The navigation test has been correctly updated to verify routing to the new path structure (/community/members/user_1 instead of /community/users/user_1), maintaining consistency with the import path changes.

frontend/src/app/organizations/page.tsx (5)

1-8: LGTM: Component imports and client directive look good.

The necessary imports are properly configured for the organization page component. The 'use client' directive is correctly placed at the top of the file to indicate client-side rendering.


9-23: Well-implemented search hook integration.

The component properly utilizes the useSearchPage hook with appropriate parameters for organization search. The implementation correctly handles pagination, search queries, and loading states.


26-50: Organization card rendering is well-structured.

The renderOrganizationCard function provides a clean implementation for displaying organization information. The navigation to organization details pages is correctly implemented using the router.


52-68: Consider adding null check for organizations array.

The code is generally well-structured, but there's a potential issue when mapping over the organizations array.

-        {organizations && organizations.map(renderOrganizationCard)}
+        {organizations?.map(renderOrganizationCard)}

This change would use the optional chaining operator to safely access the map method, preventing errors if organizations is null.

🧰 Tools
🪛 Biome (1.9.4)

[error] 65-65: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


71-71: Properly exported component.

The component is correctly exported as the default export.

frontend/src/app/organizations/[organizationKey]/page.tsx (6)

1-18: LGTM: Imports and client directive properly set up.

All necessary imports are correctly included for data fetching, UI components, and utilities. The 'use client' directive is appropriately placed at the top of the file.


19-26: Well-implemented query setup for organization data.

The component correctly sets up the GraphQL query with the organization key from URL parameters. The local state is properly initialized for organization data and loading status.


45-57: Well-handled loading and error states.

The component properly displays a loading spinner while data is being fetched and an appropriate error message if the organization is not found. This provides a good user experience during data loading and error scenarios.


59-81: Well-structured organization details formatting.

The organization details are well-organized into a structured array for rendering. The use of the formatDate utility function for date formatting is appropriate, and the optional rendering for location is handled correctly.


82-110: Comprehensive statistics display with appropriate icons.

The statistics are well-organized with appropriate icons and units. The implementation handles pluralization properly with the pluralizedName property where needed.


111-126: Clean implementation of the details card rendering.

The DetailsCard component is properly used with all necessary props passed correctly. The type is set to "organization" which allows the component to render organization-specific sections.

backend/apps/github/graphql/nodes/organization.py (3)

1-21: LGTM: Clear imports and constants.

The imports are organized well, and the constants for limiting results (RECENT_ISSUES_LIMIT, RECENT_RELEASES_LIMIT, RECENT_REPOSITORIES_LIMIT) are defined with appropriate values.


22-30: Well-defined organization stats node.

The OrganizationStatsNode class properly defines the fields needed for organization statistics. The use of GraphQL scalar types is appropriate for each field.


32-57: Well-structured organization node with comprehensive fields.

The OrganizationNode class correctly extends BaseNode and includes all necessary fields for organization data. The Meta class properly specifies the model and fields to expose through GraphQL.

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

♻️ Duplicate comments (1)
frontend/src/server/queries/organizationQueries.ts (1)

3-71: Consider adding pagination or cursors for top contributors.
You limit the number of pull requests, releases, organization repositories, and issues, but there's no limit or pagination mechanism for topContributors. For large organizations, returning all contributors in one shot may degrade performance and slow down the UI.

🧹 Nitpick comments (4)
frontend/__tests__/unit/data/mockOrganizationData.ts (1)

1-35: Enhance test coverage with edge cases.
These datasets provide typical scenarios. Consider adding edge cases, e.g., an organization with no repositories, zero contributors, or missing fields, to verify the behavior under exceptional conditions.

Also applies to: 37-164

backend/apps/github/graphql/queries/repository.py (1)

41-56: Consider adding error handling for non-existent organizations

The resolver method correctly filters repositories by organization login and orders them by popularity (stars count). However, unlike resolve_repository, there's no error handling if the organization doesn't exist.

def resolve_organization_repositories(root, info, organization, limit):
    """Resolve repositories for an organization.

    Args:
        root (Any): The root query object.
        info (ResolveInfo): The GraphQL execution context.
        organization (str): The login of the organization.
        limit (int): Maximum number of repositories to return.

    Returns:
        QuerySet: Queryset containing the repositories for the organization.

    """
+   # Check if organization exists first
+   from apps.github.models.organization import Organization
+   try:
+       org = Organization.objects.get(login=organization)
+   except Organization.DoesNotExist:
+       return []
+
    return Repository.objects.filter(organization__login=organization).order_by(
        "-stars_count"
    )[:limit]
backend/apps/github/graphql/queries/repository_contributor.py (2)

35-107: Consider refactoring to reduce code duplication in node construction.

There's duplication in the node construction logic between the organization-filtered and non-organization-filtered paths. Consider extracting this into a helper function to improve maintainability.

+def _create_contributor_node(contributor_data, with_project=True):
+    """Create a contributor node from query data.
+    
+    Args:
+        contributor_data (dict): Dictionary with contributor data.
+        with_project (bool): Whether to include project data.
+        
+    Returns:
+        RepositoryContributorNode: The constructed node.
+    """
+    node = RepositoryContributorNode(
+        avatar_url=contributor_data["user__avatar_url"],
+        contributions_count=contributor_data.get("total_contributions", 
+            contributor_data.get("contributions_count")),
+        login=contributor_data["user__login"],
+        name=contributor_data["user__name"],
+    )
+    
+    if with_project and "project_name" in contributor_data:
+        node.project_name = contributor_data["project_name"]
+        node.project_url = contributor_data["project_url"]
+    
+    return node

def resolve_top_contributors(root, info, limit, organization=None):
    # ... existing code ...
    
    if organization:
        # ... existing organization query code ...
        
-        return [
-            RepositoryContributorNode(
-                avatar_url=trc["user__avatar_url"],
-                contributions_count=trc["total_contributions"],
-                login=trc["user__login"],
-                name=trc["user__name"],
-            )
-            for trc in top_contributors
-        ]
+        return [_create_contributor_node(trc, with_project=False) for trc in top_contributors]
    
    # ... existing non-organization query code ...
    
-    return [
-        RepositoryContributorNode(
-            avatar_url=trc["user__avatar_url"],
-            contributions_count=trc["contributions_count"],
-            login=trc["user__login"],
-            name=trc["user__name"],
-            project_name=trc["project_name"],
-            project_url=trc["project_url"],
-        )
-        for trc in top_contributors
-    ]
+    return [_create_contributor_node(trc) for trc in top_contributors]

41-51:

❓ Verification inconclusive

Consider adding pagination for better performance with large organizations.

For large organizations with many contributors, the aggregation might be expensive. Consider implementing pagination instead of just using a limit, to allow clients to fetch results in batches.

Run the following script to check if there are organizations with a large number of contributors:


🏁 Script executed:

#!/bin/bash
# Check if there are any organizations with a high number of contributors

echo "Checking for large organizations with many contributors..."

# Count contributors per organization
python -c "
import django
django.setup()
from apps.github.models.repository_contributor import RepositoryContributor
from django.db.models import Count

# Get organizations with more than 50 contributors
large_orgs = RepositoryContributor.objects.values('repository__organization__login').annotate(
    contributor_count=Count('user', distinct=True)
).filter(contributor_count__gt=50).order_by('-contributor_count')

if large_orgs:
    print('Found organizations with many contributors:')
    for org in large_orgs:
        print(f'- {org[\"repository__organization__login\"]}: {org[\"contributor_count\"]} contributors')
else:
    print('No organizations with more than 50 contributors found.')
"

Length of output: 978


Revisit Pagination for Scalability in Contributor Aggregation

It looks like the verification script couldn’t run due to a missing Django dependency, so we couldn’t conclusively determine if many organizations indeed require pagination. However, if production data reveals organizations with a high number of contributors, the current aggregation logic (lines 41–51 in backend/apps/github/graphql/queries/repository_contributor.py) may suffer performance issues. Please verify manually in a properly configured Django environment if large contributor counts occur, and if so, consider updating the logic to use pagination for more efficient data retrieval.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 786354c and 700e81f.

📒 Files selected for processing (15)
  • backend/apps/github/graphql/nodes/organization.py (1 hunks)
  • backend/apps/github/graphql/queries/issue.py (2 hunks)
  • backend/apps/github/graphql/queries/pull_request.py (2 hunks)
  • backend/apps/github/graphql/queries/release.py (3 hunks)
  • backend/apps/github/graphql/queries/repository.py (2 hunks)
  • backend/apps/github/graphql/queries/repository_contributor.py (2 hunks)
  • backend/tests/apps/github/graphql/nodes/organization_test.py (1 hunks)
  • frontend/__tests__/e2e/pages/OrganizationDetails.spec.ts (1 hunks)
  • frontend/__tests__/unit/data/mockOrganizationData.ts (1 hunks)
  • frontend/__tests__/unit/pages/OrganizationDetails.test.tsx (1 hunks)
  • frontend/src/app/organizations/[organizationKey]/page.tsx (1 hunks)
  • frontend/src/components/CardDetailsPage.tsx (3 hunks)
  • frontend/src/components/LeadersList.tsx (1 hunks)
  • frontend/src/components/RecentReleases.tsx (1 hunks)
  • frontend/src/server/queries/organizationQueries.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • frontend/tests/unit/pages/OrganizationDetails.test.tsx
  • frontend/src/components/LeadersList.tsx
  • frontend/src/components/RecentReleases.tsx
  • frontend/src/components/CardDetailsPage.tsx
  • backend/tests/apps/github/graphql/nodes/organization_test.py
  • frontend/tests/e2e/pages/OrganizationDetails.spec.ts
🧰 Additional context used
🧬 Code Graph Analysis (5)
backend/apps/github/graphql/queries/repository.py (2)
backend/apps/github/graphql/nodes/repository.py (1)
  • RepositoryNode (15-81)
backend/apps/github/models/repository.py (1)
  • Repository (22-332)
backend/apps/github/graphql/queries/repository_contributor.py (3)
backend/apps/github/graphql/nodes/repository_contributor.py (1)
  • RepositoryContributorNode (6-14)
backend/apps/github/models/repository_contributor.py (1)
  • RepositoryContributor (12-104)
backend/apps/github/models/managers/repository_contributor.py (4)
  • by_humans (12-16)
  • by_humans (36-38)
  • to_community_repositories (18-20)
  • to_community_repositories (40-42)
backend/apps/github/graphql/nodes/organization.py (4)
backend/apps/common/graphql/nodes.py (1)
  • BaseNode (6-10)
backend/apps/github/models/organization.py (1)
  • Organization (12-88)
backend/apps/github/models/repository.py (1)
  • Repository (22-332)
backend/apps/github/models/repository_contributor.py (1)
  • RepositoryContributor (12-104)
backend/apps/github/graphql/queries/pull_request.py (1)
backend/apps/github/models/pull_request.py (1)
  • PullRequest (11-125)
backend/apps/github/graphql/queries/issue.py (2)
backend/apps/owasp/graphql/nodes/project.py (1)
  • resolve_recent_issues (56-58)
frontend/src/types/user.ts (1)
  • Issue (24-31)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run backend tests
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (24)
backend/apps/github/graphql/nodes/organization.py (5)

1-20: Comprehensive definition of stats fields and clean imports.
All fields in OrganizationStatsNode are clearly defined and the aggregator approach for stats is structurally consistent. No immediate issues are identified in these lines.


22-27: Approach to defining organization node fields looks good.
The OrganizationNode sets up a clear GraphQL schema, with stats and url accessible. This is in keeping with Graphene conventions.


28-42: Confirm exposure of email and other sensitive fields.
Including fields like email in a public GraphQL schema can be a potential privacy concern. Ensure that the endpoint is appropriately protected or that these fields are safe to expose publicly.

Would you like to review how these fields are accessed or implement any access restrictions or masking?


44-71: Efficient stats calculation matches recommended aggregator usage.
This resolves the prior review comment regarding improved database queries. The aggregate sums for stars, forks, and issues, along with distinct user count, are optimal for large data sets.


73-75:

❓ Verification inconclusive

Verify underlying url property on the Organization model.
resolve_url returns self.url, but the Organization model snippet does not explicitly list a url field or property. Ensure this is defined or inherited from a parent model so that it does not raise errors at runtime.


🏁 Script executed:

#!/bin/bash
# Verify that the Organization model has a `url` property or
# at least a fallback to a related field.
rg --multiline --context 5 --case-sensitive 'class Organization' 

Length of output: 6718


Action: Confirm that the Organization model provides a valid url attribute

The resolve_url method in backend/apps/github/graphql/nodes/organization.py returns self.url. However, our search in the Organization model (i.e. backend/apps/github/models/organization.py) does not show an explicit definition for a url property. Please verify that one of the inherited base classes (such as GenericUserModel, NodeModel, or OrganizationIndexMixin) supplies this attribute. If none of those or a fallback mechanism provides it, then an explicit definition should be added to the Organization model to prevent runtime errors.

backend/apps/github/graphql/queries/repository.py (1)

18-22: Looks good: Added new GraphQL field for organization repositories

The new field organization_repositories has been correctly defined to retrieve a list of repositories for a specific organization with a sensible default limit of 12.

backend/apps/github/graphql/queries/issue.py (5)

19-19: Looks good: Added organization parameter to recent_issues

The organization parameter has been correctly defined as an optional string parameter.


22-22: Looks good: Updated resolver method signature

The resolver method signature has been properly updated to include the new organization parameter.


31-31: Looks good: Updated method documentation

Documentation has been properly updated to describe the new organization parameter.


39-39: Good optimization: Added repository to select_related

Adding repository to the select_related call is a good optimization to reduce database queries when filtering by organization.


47-49: Looks good: Implemented organization filter

The filter correctly filters issues by the organization's login when the parameter is provided.

backend/apps/github/graphql/queries/release.py (4)

19-19: Looks good: Added organization parameter to recent_releases

The organization parameter has been correctly defined as an optional string parameter.


22-22: Looks good: Updated resolver method signature

The resolver method signature has been properly updated to include the new organization parameter.


31-31: Looks good: Updated method documentation

Documentation has been properly updated to describe the new organization parameter.


48-52: Looks good: Implemented organization filter

The filter correctly filters releases by the organization's login when the parameter is provided. The code formatting with proper indentation makes it consistent with the existing login filter above.

backend/apps/github/graphql/queries/pull_request.py (5)

19-19: Looks good: Added organization parameter to recent_pull_requests

The organization parameter has been correctly defined as an optional string parameter.


22-24: Looks good: Updated resolver method signature

The resolver method signature has been properly updated to include the new organization parameter.


33-33: Looks good: Updated method documentation

Documentation has been properly updated to describe the new organization parameter.


41-41: Good optimization: Added repository to select_related

Adding repository to the select_related call is a good optimization to reduce database queries when filtering by organization.


49-51: Looks good: Implemented organization filter

The filter correctly filters pull requests by the organization's login when the parameter is provided.

backend/apps/github/graphql/queries/repository_contributor.py (4)

4-4: Good addition of the Sum import for the new aggregation logic.

The addition of the Sum import is necessary and properly used for aggregating the total contributions in the organization filter path.


16-20: GraphQL field definition correctly extended with optional organization parameter.

The addition of the optional organization parameter to the top_contributors field is well-implemented:

  • Made it non-required with required=False to maintain backward compatibility
  • Kept the existing limit parameter functionality
  • Parameter naming is clear and follows the API's conventions

22-34: Method signature and documentation properly updated.

The resolver method signature has been correctly updated to include the new optional organization parameter, and the documentation has been updated to reflect this change. This is good practice for maintaining code readability and API documentation.


63-95: Good separation of concerns for organization and non-organization queries.

The code clearly separates the organization-specific logic from the original query path, making it easier to understand and maintain. The comment at line 63 helps clarify the purpose of this section.

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

♻️ Duplicate comments (1)
frontend/src/server/queries/organizationQueries.ts (1)

3-72: GraphQL query structure looks good, but consider implementing pagination

The query is well-structured and fetches comprehensive organization data including basic information, statistics, contributors, repositories, and activity (PRs, issues, releases). The use of limit parameters for recent activities is a good start.

However, this query still lacks proper pagination mechanisms for repositories, issues, and releases. While you're using limit parameters, there are no pagination cursors or offsets to load additional data beyond the initial set.

Consider enhancing this query by:

  1. Adding cursor-based pagination arguments (using the GraphQL after pattern)
  2. Implementing separate queries for different sections that can be loaded on demand
  3. Including total counts for paginated collections
export const GET_ORGANIZATION_DATA = gql`
  query GetOrganization($login: String!) {
    organization(login: $login) {
      # Basic info remains the same
    }
    topContributors(organization: $login) {
      # This section remains the same
    }
-   recentPullRequests(limit: 5, organization: $login) {
+   recentPullRequests(limit: 5, organization: $login, after: $pullRequestCursor) {
      title
      createdAt
      url
      author {
        login
        avatarUrl
      }
+     pageInfo {
+       hasNextPage
+       endCursor
+     }
    }
    # Apply similar pattern to other paginated sections
  }
`

+ export const GET_ORGANIZATION_REPOSITORIES = gql`
+   query GetOrganizationRepositories($login: String!, $limit: Int, $cursor: String) {
+     organizationRepositories(organization: $login, limit: $limit, after: $cursor) {
+       nodes {
+         name
+         url
+         contributorsCount
+         forksCount
+         openIssuesCount
+         starsCount
+         key
+       }
+       pageInfo {
+         hasNextPage
+         endCursor
+       }
+     }
+   }
+ `
🧹 Nitpick comments (2)
frontend/src/server/queries/organizationQueries.ts (2)

52-60: Consider adding more repository metadata

The repository data fetched is missing some potentially useful fields that could enhance the UI display and user experience.

Consider adding these additional fields:

  • description: Provides context about the repository's purpose
  • primaryLanguage: Shows the main technology used
  • visibility: Whether the repo is public or private
  • updatedAt: Last updated timestamp
organizationRepositories(organization: $login, limit: 12) {
  name
  url
  contributorsCount
  forksCount
  openIssuesCount
  starsCount
  key
+ description
+ primaryLanguage {
+   name
+   color
+ }
+ visibility
+ updatedAt
}

18-24: Consider expanding organization statistics

The current stats are good, but consider adding more metrics that would be valuable for organization overview.

stats {
  totalRepositories
  totalContributors
  totalStars
  totalForks
  totalIssues
+ totalPullRequests
+ totalCommits
+ avgTimeToMerge
+ topLanguages {
+   name
+   color
+   percentage
+ }
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 700e81f and 145a771.

📒 Files selected for processing (2)
  • backend/apps/github/graphql/queries/repository_contributor.py (2 hunks)
  • frontend/src/server/queries/organizationQueries.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/apps/github/graphql/queries/repository_contributor.py
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
  • GitHub Check: CodeQL (python)
  • GitHub Check: CodeQL (javascript-typescript)

@Dishant1804 Dishant1804 requested a review from arkid15r April 9, 2025 19:33
@Dishant1804
Copy link
Collaborator Author

Let's start from:

  • add recent PRs for org details page (extend pull_request graphql endpoint w/ organization filter)
  • move issue resolver logic to existing recent issues endpoint (extend w/ filtering by org)
  • move release resolver logic to existing recent releases endpoint (extend w/ filtering by org)
  • move repositories resolver logic to existing repository endpoint (create a new one w/ filtering by org)
  • move top contributors resolver logic to existing repository contributor endpoint (extend w/ filtering by org)

Hey @arkid15r these changes are implemented and ready for review :)

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 (4)
backend/apps/github/graphql/queries/organization.py (1)

30-33: Consider adding logging for non-existent organizations.

While the error handling is appropriate, adding a log when an organization is not found would make it easier to track these lookup failures in production.

 try:
     return Organization.objects.get(login=login)
 except Organization.DoesNotExist:
+    # Consider logging this failure with logger.debug or logger.info
     return None
frontend/src/app/organizations/page.tsx (3)

64-66: Improve code safety with optional chaining

Replace the logical AND operator with optional chaining for a more concise and idiomatic approach.

-        {organizations && organizations.map(renderOrganizationCard)}
+        {organizations?.map(renderOrganizationCard)}
🧰 Tools
🪛 Biome (1.9.4)

[error] 65-65: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


45-46: Revisit location fallback logic

Using @${organization.login} as a fallback for location seems unintuitive since location typically represents a physical place. Consider separating the login information or using a more descriptive fallback.

-        location={organization.location || `@${organization.login}`}
+        location={organization.location || ''}
+        username={organization.login}

Note: This assumes the UserCard component supports a username prop. If not, you might need to update that component as well.


47-47: Extract Tailwind classes to a reusable constant

The long string of Tailwind classes reduces readability. Consider extracting this into a constant at the top of the component for better maintainability.

const OrganizationPage = () => {
+  const cardClassName = "h-64 w-80 bg-white p-6 text-left shadow-lg transition-transform duration-500 hover:scale-105 hover:shadow-xl dark:bg-gray-800 dark:shadow-gray-900/30"
  const {
    // ...

Then update the component:

-        className="h-64 w-80 bg-white p-6 text-left shadow-lg transition-transform duration-500 hover:scale-105 hover:shadow-xl dark:bg-gray-800 dark:shadow-gray-900/30"
+        className={cardClassName}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 145a771 and 252fe57.

📒 Files selected for processing (22)
  • backend/apps/github/graphql/queries/issue.py (3 hunks)
  • backend/apps/github/graphql/queries/organization.py (1 hunks)
  • backend/apps/github/graphql/queries/pull_request.py (3 hunks)
  • backend/apps/github/graphql/queries/release.py (3 hunks)
  • backend/apps/github/graphql/queries/repository.py (2 hunks)
  • backend/apps/github/graphql/queries/repository_contributor.py (1 hunks)
  • frontend/__tests__/unit/pages/Chapters.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/Committees.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/Contribute.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/Projects.test.tsx (1 hunks)
  • frontend/__tests__/unit/pages/Users.test.tsx (3 hunks)
  • frontend/src/app/chapters/page.tsx (1 hunks)
  • frontend/src/app/committees/page.tsx (1 hunks)
  • frontend/src/app/community/members/page.tsx (2 hunks)
  • frontend/src/app/organizations/[organizationKey]/page.tsx (1 hunks)
  • frontend/src/app/organizations/page.tsx (1 hunks)
  • frontend/src/app/projects/contribute/page.tsx (1 hunks)
  • frontend/src/app/projects/page.tsx (1 hunks)
  • frontend/src/components/RecentReleases.tsx (3 hunks)
  • frontend/src/server/queries/organizationQueries.ts (1 hunks)
  • frontend/src/types/card.ts (1 hunks)
  • frontend/src/types/organization.ts (1 hunks)
✅ Files skipped from review due to trivial changes (5)
  • frontend/src/app/chapters/page.tsx
  • frontend/src/app/projects/contribute/page.tsx
  • frontend/src/app/committees/page.tsx
  • frontend/src/app/projects/page.tsx
  • frontend/tests/unit/pages/Contribute.test.tsx
🚧 Files skipped from review as they are similar to previous changes (11)
  • frontend/src/types/card.ts
  • frontend/src/components/RecentReleases.tsx
  • backend/apps/github/graphql/queries/release.py
  • frontend/src/app/community/members/page.tsx
  • backend/apps/github/graphql/queries/pull_request.py
  • frontend/src/server/queries/organizationQueries.ts
  • frontend/src/types/organization.ts
  • frontend/tests/unit/pages/Users.test.tsx
  • frontend/src/app/organizations/[organizationKey]/page.tsx
  • backend/apps/github/graphql/queries/repository_contributor.py
  • backend/apps/github/graphql/queries/repository.py
🧰 Additional context used
🧬 Code Graph Analysis (2)
backend/apps/github/graphql/queries/organization.py (3)
backend/apps/common/graphql/queries.py (1)
  • BaseQuery (6-7)
backend/apps/github/graphql/nodes/organization.py (1)
  • OrganizationNode (22-75)
backend/apps/github/models/organization.py (1)
  • Organization (12-88)
backend/apps/github/graphql/queries/issue.py (1)
backend/apps/owasp/graphql/nodes/project.py (1)
  • resolve_recent_issues (56-58)
🪛 Biome (1.9.4)
frontend/src/app/organizations/page.tsx

[error] 65-65: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (10)
frontend/__tests__/unit/pages/Committees.test.tsx (1)

74-75: Placeholder text update aligns with UI standardization.

This change correctly updates the test to match the new placeholder text in the Committees search bar, which is part of a broader effort to standardize placeholder texts across the application by removing specific references to "OWASP".

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

112-112: Placeholder text updated to be more generic.

The search placeholder has been updated from "Search for OWASP chapters..." to "Search for chapters...", which aligns with the broader updates in this PR to make search functionality more general and consistent across the application.

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

82-82: Placeholder text updated to be more generic.

The search placeholder has been changed from "Search for OWASP projects..." to "Search for projects...", following the same pattern of generalizing search placeholders across the application. This is consistent with the other similar changes for chapters and matches the implementation of organization search functionality.

backend/apps/github/graphql/queries/organization.py (1)

1-34: Implementation looks good with clear organization query support.

This new file provides a well-structured implementation of GraphQL queries for GitHub organizations. The code follows project conventions with clear docstrings and appropriate error handling. The resolve_organization method efficiently handles the lookup of an organization by its login and gracefully handles the case where the organization doesn't exist.

backend/apps/github/graphql/queries/issue.py (4)

19-19: LGTM: Organization parameter properly added to GraphQL query.

The addition of the organization parameter to filter issues by an organization's login is well-implemented.


22-22: Method signature correctly updated with organization parameter.

The resolver method signature has been properly updated to include the new optional organization parameter with a default value of None.


31-31: Docstring properly updated with organization parameter description.

Documentation has been updated to include the new parameter, maintaining code quality standards.


43-54: Filtering logic implemented well with performance considerations.

The implementation efficiently filters issues by organization using appropriate select_related to optimize queries. The select_related for repository__organization is correctly placed inside the organization conditional block, minimizing unnecessary joins when not filtering by organization.

frontend/src/app/organizations/page.tsx (2)

38-48: Reusing UserCard for organizations may require review

The component reuses UserCard for displaying organizations, which might not be semantically accurate. Consider either:

  1. Renaming UserCard to a more generic name like ProfileCard throughout the application to accommodate both users and organizations
  2. Creating a dedicated OrganizationCard component if organizations require different fields or behaviors

While this works functionally, it might cause confusion for future developers. Please verify that all UserCard props are appropriate for organizations.


9-69: LGTM - Well-structured component

The OrganizationPage component is well-structured and correctly implements the organization listing functionality as described in the PR objectives. Good job using:

  • The useSearchPage hook for search and pagination
  • Proper component composition
  • Clean separation of rendering logic
  • Responsive grid layout
🧰 Tools
🪛 Biome (1.9.4)

[error] 65-65: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

@arkid15r arkid15r enabled auto-merge April 11, 2025 02:26
arkid15r
arkid15r previously approved these changes Apr 11, 2025
Copy link
Collaborator

@arkid15r arkid15r left a comment

Choose a reason for hiding this comment

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

LGTM, great work!

Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
5.6% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

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

🔭 Outside diff range comments (1)
frontend/__tests__/e2e/components/Header.spec.ts (1)

44-60: 🛠️ Refactor suggestion

Add test for the Organizations link in desktop view.

I notice that you've added an assertion for the 'Organizations' link in the mobile view tests, but there isn't a corresponding assertion in the desktop view tests. For complete test coverage, you should add a test for the Organizations link in the desktop dropdown as well.

// Assert dropdown options appear
await expect(navbar.getByRole('link', { name: 'Chapters' })).toBeVisible()
await expect(navbar.getByRole('link', { name: 'Members' })).toBeVisible()
+await expect(navbar.getByRole('link', { name: 'Organizations' })).toBeVisible()
await expect(navbar.getByRole('link', { name: 'Snapshots' })).toBeVisible()
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 14fd710 and ca55079.

📒 Files selected for processing (2)
  • frontend/__tests__/e2e/components/Header.spec.ts (2 hunks)
  • frontend/__tests__/e2e/pages/Users.spec.ts (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
  • GitHub Check: Run frontend unit tests
🔇 Additional comments (1)
frontend/__tests__/e2e/components/Header.spec.ts (1)

58-58: LGTM - Navigation updates for members and organizations.

The Header component tests have been properly updated to reflect the navigation changes. You've successfully added assertions for the new 'Members' link in both desktop and mobile views, as well as the 'Organizations' link in mobile view.

Also applies to: 109-112

@@ -20,7 +20,7 @@ test.describe('Users Page', () => {
path: '/',
},
])
await page.goto('/community/users')
await page.goto('/community/members')
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Update file name to reflect the new "members" terminology.

The test file is correctly updated to use the new path /community/members instead of /community/users, but the file itself is still named Users.spec.ts. For consistency across the codebase, consider renaming this file to Members.spec.ts.

Additionally, the test descriptions and assertions still use "Users" terminology (e.g., 'Users Page', 'No Users Found') while testing "members" routes.

-test.describe('Users Page', () => {
+test.describe('Members Page', () => {

And:

-await expect(page.getByText('No Users Found')).toBeVisible()
+await expect(page.getByText('No Members Found')).toBeVisible()

This would ensure full terminology consistency across both routes and user-facing messages.

Also applies to: 38-38, 55-55

@arkid15r arkid15r added this pull request to the merge queue Apr 11, 2025
Merged via the queue into OWASP:main with commit dd1f55c Apr 11, 2025
21 of 22 checks passed
Rajgupta36 pushed a commit to Rajgupta36/Nest-n that referenced this pull request Apr 11, 2025
* OragnizationPage and OrganizationDetailsPage fe/be

* checks and lint

* removed unused field

* migrated organization to nextjs components

* checks and lint

* adding member check for reliability

* improved usercard

* Update code

* using resolvers with filtering

* code rabbit suggestions

* Update code

* What conflict?

* Update tests

* Update code

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
Rajgupta36 pushed a commit to Rajgupta36/Nest-n that referenced this pull request Apr 11, 2025
* OragnizationPage and OrganizationDetailsPage fe/be

* checks and lint

* removed unused field

* migrated organization to nextjs components

* checks and lint

* adding member check for reliability

* improved usercard

* Update code

* using resolvers with filtering

* code rabbit suggestions

* Update code

* What conflict?

* Update tests

* Update code

---------

Co-authored-by: Arkadii Yakovets <[email protected]>
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.

Implement organizations
2 participants