Skip to content

Add slack total members count#1508

Merged
arkid15r merged 17 commits intoOWASP:mainfrom
ahmedxgouda:feature/slack-total-members-count
May 24, 2025
Merged

Add slack total members count#1508
arkid15r merged 17 commits intoOWASP:mainfrom
ahmedxgouda:feature/slack-total-members-count

Conversation

@ahmedxgouda
Copy link
Collaborator

@ahmedxgouda ahmedxgouda commented May 22, 2025

Resolves #1502

  • Appended total_members_count to the workspace model, and extended the sync logic to populate it.
  • Implemented presentation for this field (because of the reduced space for each counter, I made the feature display as cols in the large screens only).
  • Implemented tests.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 22, 2025

Summary by CodeRabbit

  • New Features
    • Added display of Slack Community statistics to the main page, showing the total number of Slack workspace members.
  • Enhancements
    • Updated statistics layout to include a fifth column for the new Slack Community metric.
    • Improved formatting and rounding of all displayed statistics for consistency.
  • Bug Fixes
    • Ensured statistics values are accurately rounded and displayed.
  • Tests
    • Added unit and end-to-end tests to verify the presence and correct rendering of the Slack Community statistic and other counters.
  • Chores
    • Updated mock data and type definitions to support the new Slack Community statistic.

Walkthrough

This change introduces a new statistic for the Slack workspace total members count, visible on the main page alongside existing counters. It adds a new field and logic to the backend to store and expose this count, updates the frontend to display it, and includes new tests and mock data to support and verify the feature.

Changes

Files / Groups Change Summary
backend/apps/slack/models/workspace.py, backend/apps/slack/migrations/... Add total_members_count field to Workspace model; migration for schema update; add get_default_workspace()
backend/apps/slack/management/commands/slack_sync_data.py Update sync command to set and save total_members_count after fetching members
backend/apps/owasp/graphql/nodes/stats.py Add slack_workspace_stats field to GraphQL StatsNode
backend/apps/owasp/graphql/queries/stats.py Expose slack_workspace_stats in stats resolver; use new round_down utility for all stats
backend/apps/common/utils.py, backend/tests/apps/common/utils_test.py Add and test round_down utility function
frontend/src/types/home.ts Add slackWorkspaceStats to statsOverview type
frontend/src/server/queries/homeQueries.ts Add slackWorkspaceStats to GraphQL query
frontend/src/app/page.tsx Add Slack Community counter to main page; update layout to 5 columns; pass raw values to counters
frontend/tests/unit/data/mockHomeData.ts, frontend/tests/e2e/data/... Add slackWorkspaceStats to mock data; update other stat values
frontend/tests/unit/pages/Home.test.tsx Add unit test for rendering new stat and formatted values
frontend/tests/e2e/pages/Home.spec.ts Add E2E test for Slack Community stat presence

Assessment against linked issues

Objective Addressed Explanation
Add total_members_count field to SlackWorkspace model (#1502)
Update Slack sync command to fetch and store total members count (#1502)
Add new main page stat counter for Slack members, styled and positioned with others (#1502)
Ensure value updates during sync and frontend reflects latest count (#1502)
Write tests for sync logic and verify new counter appears in UI (#1502)

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.

✨ Finishing Touches
  • 📝 Generate Docstrings

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

❤️ Share
🪧 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @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.

@github-actions github-actions bot added docs Improvements or additions to documentation frontend nestbot frontend-tests and removed docs Improvements or additions to documentation labels May 22, 2025
@ahmedxgouda
Copy link
Collaborator Author

What? How did the rebase happen?

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

🧹 Nitpick comments (3)
backend/apps/slack/models/workspace.py (1)

19-19: Consider adding a docstring to the new field

The total_members_count field looks good and uses an appropriate type (PositiveIntegerField) with a sensible default value. Consider adding a docstring to document its purpose and update behavior, similar to other fields in this model.

-    total_members_count = models.PositiveIntegerField(default=0)
+    total_members_count = models.PositiveIntegerField(
+        verbose_name="Total Members Count",
+        default=0,
+        help_text="The total number of members in the Slack workspace",
+    )
backend/apps/slack/management/commands/slack_sync_data.py (1)

105-107: Consider optimizing database writes during sync.

The implementation correctly updates the workspace's total members count during the pagination loop. However, calling workspace.save() after every batch might lead to excessive database writes when processing large workspaces with many member batches.

Consider saving the workspace only once after all batches are processed, unless there's a specific requirement to have real-time updates during sync:

-                    # Set workspace total members count
-                    workspace.total_members_count = total_members
-                    workspace.save()
+                    # Update workspace total members count in memory
+                    workspace.total_members_count = total_members

Then add after line 110 (after the pagination loop):

# Save the final total members count
workspace.save()
backend/apps/owasp/graphql/nodes/stats.py (1)

10-10: Note field reordering.

The order of field declarations has changed, moving active_projects_stats to the second position. While this has no functional impact (GraphQL doesn't rely on field definition order), it's worth noting in case there was a specific organizational intent.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 9c92bc4 and 8cc068f.

📒 Files selected for processing (12)
  • backend/apps/owasp/graphql/nodes/stats.py (1 hunks)
  • backend/apps/owasp/graphql/queries/stats.py (2 hunks)
  • backend/apps/slack/management/commands/slack_sync_data.py (1 hunks)
  • backend/apps/slack/migrations/0010_workspace_total_members_count.py (1 hunks)
  • backend/apps/slack/models/workspace.py (1 hunks)
  • frontend/__tests__/e2e/data/mockHomeData.ts (1 hunks)
  • frontend/__tests__/e2e/pages/Home.spec.ts (2 hunks)
  • frontend/__tests__/unit/data/mockHomeData.ts (1 hunks)
  • frontend/__tests__/unit/pages/Home.test.tsx (2 hunks)
  • frontend/src/app/page.tsx (2 hunks)
  • frontend/src/server/queries/homeQueries.ts (1 hunks)
  • frontend/src/types/home.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
frontend/src/app/page.tsx (1)
frontend/src/components/AnimatedCounter.tsx (1)
  • AnimatedCounter (10-35)
frontend/__tests__/e2e/pages/Home.spec.ts (1)
frontend/__tests__/e2e/data/mockHomeData.ts (1)
  • mockHomeData (1-286)
🪛 GitHub Actions: Run CI/CD
backend/apps/owasp/graphql/queries/stats.py

[error] 13-13: CSpell: Unknown word 'MINROUNDED' found.


[error] 33-33: CSpell: Unknown word 'MINROUNDED' found.

🔇 Additional comments (14)
frontend/src/types/home.ts (1)

41-41: LGTM! Type definition for Slack member count

The addition of the workspaceStats field to the statsOverview type is correctly implemented as a number type, following the naming pattern of other stats fields.

frontend/__tests__/e2e/data/mockHomeData.ts (1)

245-245: LGTM! Mock data for Slack member count

The mock value for workspaceStats is appropriately added to support testing of the new Slack members count feature.

backend/apps/slack/migrations/0010_workspace_total_members_count.py (1)

1-17: LGTM! Migration for adding Slack members count field

The migration is properly structured with the correct dependency and field definition. It follows Django migration best practices by focusing on a single, well-defined change.

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

83-83: LGTM! Added workspaceStats field to GraphQL query.

The addition of workspaceStats to the statsOverview selection set aligns with the PR objective to add Slack total members count. This change will enable the frontend to fetch the Slack workspace member count data from the backend.

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

120-124: LGTM! Updated mock data with new workspaceStats field.

The mock data has been properly updated with the new workspaceStats field to support testing the Slack members count feature. The values for other statistics have also been adjusted to more realistic figures.

backend/apps/owasp/graphql/nodes/stats.py (1)

13-13: LGTM! Added workspace_stats field to StatsNode.

The addition of the workspace_stats field to the StatsNode GraphQL object type correctly exposes the Slack workspace member count through the API. The integer type is appropriate for this numeric statistic.

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

115-132: Added Slack Members statistics to counter data.

The code adds a new statistic "Slack Members" to the existing stats display, which aligns with the PR objective to track Slack membership counts.


359-359: Grid layout adjusted to accommodate new statistics.

The layout has been appropriately changed from md:grid-cols-4 to lg:grid-cols-5 to fit the new Slack Members counter.


364-364: Simplified AnimatedCounter implementation.

The code now passes raw numeric values directly to the AnimatedCounter component instead of using parseInt, which is cleaner and more efficient.

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

5-5: Added millify import for number formatting.

The millify library is correctly imported for number formatting in the test.

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

3-3: Added millify import for E2E tests.

The millify library is correctly imported for formatting numbers in the E2E test.

backend/apps/owasp/graphql/queries/stats.py (3)

3-4: Added required imports for new functionality.

The imports for floor from math module and Workspace model are necessary for the new functionality.

Also applies to: 11-12


21-36: Good refactoring with general_round_down method.

The new static method centralizes the rounding logic, which improves code maintainability and consistency.

🧰 Tools
🪛 GitHub Actions: Run CI/CD

[error] 33-33: CSpell: Unknown word 'MINROUNDED' found.


61-65: Consistent use of the new rounding method.

All statistics are now consistently rounded using the new general_round_down method, which improves code maintainability.

Comment on lines 261 to 282
test('renders stats correctly', async () => {
render(<Home />)

const headers = [
'Active Projects',
'Local Chapters',
'Contributors',
'Countries',
'Slack Members',
]
const stats = mockGraphQLData.statsOverview

await waitFor(() => {
headers.map((header) => expect(screen.getByText(header)).toBeInTheDocument())
// Wait for 2 seconds
setTimeout(() => {
Object.values(stats).forEach((value) =>
expect(screen.getByText(`${millify(value)}+`)).toBeInTheDocument()
)
}, 2000)
})
})
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

Test implementation for stats needs improvement.

While the test correctly verifies the presence of all statistics including the new "Slack Members" stat, the setTimeout approach can lead to flaky tests.

Replace the setTimeout with a proper waitFor implementation:

-      // Wait for 2 seconds
-      setTimeout(() => {
-        Object.values(stats).forEach((value) =>
-          expect(screen.getByText(`${millify(value)}+`)).toBeInTheDocument()
-        )
-      }, 2000)
+      // Wait for all stats to be rendered
+      await Promise.all(
+        Object.values(stats).map(async (value) => {
+          await waitFor(() => {
+            expect(screen.getByText(`${millify(value)}+`)).toBeInTheDocument()
+          })
+        })
+      )

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In frontend/__tests__/unit/pages/Home.test.tsx around lines 261 to 282, the test
uses setTimeout inside waitFor to delay assertions, which can cause flaky tests.
Remove the setTimeout and instead use waitFor to directly wait for the expected
elements with the stats values to appear. This means inside waitFor, assert that
each stat value with millify formatting plus '+' is present in the document
without any manual delay.

@ahmedxgouda ahmedxgouda force-pushed the feature/slack-total-members-count branch from 8cc068f to 7e2c036 Compare May 22, 2025 18:00
@ahmedxgouda ahmedxgouda marked this pull request as ready for review May 23, 2025 07:06
@sonarqubecloud
Copy link

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 (2)
backend/apps/common/utils.py (1)

104-115: Function implementation looks good, but consider adding input validation.

The round_down function is well-implemented with clear documentation and correct mathematical logic. However, consider adding input validation to handle edge cases.

Consider adding input validation to handle edge cases:

 def round_down(value: int, base: int) -> int:
     """Round down the stats to the nearest base.

     Args:
         value: The value to round down.
         base: The base to round down to.

     Returns:
         int: The rounded down value.

+    Raises:
+        ValueError: If base is zero or negative.
     """
+    if base <= 0:
+        raise ValueError("Base must be a positive integer")
     return value - (value % base)
backend/tests/apps/common/utils_test.py (1)

84-101: Comprehensive test coverage with excellent parametrization.

The test cases are well-designed and cover various rounding scenarios effectively. All mathematical calculations are correct and the parametrized approach ensures good coverage.

Consider adding edge case tests to complement the existing coverage:

+    @pytest.mark.parametrize(
+        ("value", "base", "expected_exception"),
+        [
+            (100, 0, ValueError),
+            (100, -1, ValueError),
+        ],
+    )
+    def test_round_down_edge_cases(self, value, base, expected_exception):
+        with pytest.raises(expected_exception):
+            round_down(value, base)
+
+    def test_round_down_negative_value(self):
+        # Test behavior with negative values
+        assert round_down(-15, 10) == -20
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 4f15c09 and 34d3314.

📒 Files selected for processing (13)
  • backend/apps/common/utils.py (1 hunks)
  • backend/apps/owasp/graphql/nodes/stats.py (1 hunks)
  • backend/apps/owasp/graphql/queries/stats.py (2 hunks)
  • backend/apps/slack/management/commands/slack_sync_data.py (1 hunks)
  • backend/apps/slack/models/workspace.py (1 hunks)
  • backend/tests/apps/common/utils_test.py (2 hunks)
  • frontend/__tests__/e2e/data/mockHomeData.ts (1 hunks)
  • frontend/__tests__/e2e/pages/Home.spec.ts (1 hunks)
  • frontend/__tests__/unit/data/mockHomeData.ts (1 hunks)
  • frontend/__tests__/unit/pages/Home.test.tsx (2 hunks)
  • frontend/src/app/page.tsx (2 hunks)
  • frontend/src/server/queries/homeQueries.ts (1 hunks)
  • frontend/src/types/home.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (11)
  • frontend/src/server/queries/homeQueries.ts
  • frontend/src/types/home.ts
  • frontend/tests/unit/data/mockHomeData.ts
  • backend/apps/slack/management/commands/slack_sync_data.py
  • backend/apps/owasp/graphql/queries/stats.py
  • frontend/tests/e2e/data/mockHomeData.ts
  • frontend/tests/e2e/pages/Home.spec.ts
  • backend/apps/slack/models/workspace.py
  • frontend/tests/unit/pages/Home.test.tsx
  • backend/apps/owasp/graphql/nodes/stats.py
  • frontend/src/app/page.tsx
🧰 Additional context used
🧬 Code Graph Analysis (1)
backend/tests/apps/common/utils_test.py (1)
backend/apps/common/utils.py (1)
  • round_down (104-115)
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Run frontend unit tests
  • GitHub Check: Run frontend e2e tests
  • GitHub Check: Run backend tests
  • GitHub Check: CodeQL (javascript-typescript)
🔇 Additional comments (1)
backend/tests/apps/common/utils_test.py (1)

13-13: Import addition looks good.

The import for round_down is correctly added to the test file.

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

await waitFor(() => {
headers.forEach((header) => expect(screen.getByText(header)).toBeInTheDocument())
// Wait for 2 seconds
setTimeout(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This doesn't look right but I'm not sure how to make that better 🤷‍♂️

@arkid15r arkid15r added this pull request to the merge queue May 24, 2025
Merged via the queue into OWASP:main with commit 017fbaa May 24, 2025
23 checks passed
ahmedxgouda added a commit to ahmedxgouda/Nest that referenced this pull request May 24, 2025
* Add total_members_count field to Workspace model and update Slack sync command

* Update pnpm-lock.yaml

* Update member details page title

* Update member details page layout

* Update CONTRIBUTING.md

* Update CONTRIBUTING.md formatting

* Add workspace stats to the stats node and query

* Update frontend

* Refactore conterData

* Update frontend tests

* Fix spelling

* Apply make-check

* Update frontend tests

* Use forEach instead of map

* Apply coderabbitai suggestion

* Update code

---------

Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
github-merge-queue bot pushed a commit that referenced this pull request May 25, 2025
* Add body to the milestone node

* Add progress to the milestone node

* Update frontend

* Update backend tests

* Add slack total members count (#1508)

* Add total_members_count field to Workspace model and update Slack sync command

* Update pnpm-lock.yaml

* Update member details page title

* Update member details page layout

* Update CONTRIBUTING.md

* Update CONTRIBUTING.md formatting

* Add workspace stats to the stats node and query

* Update frontend

* Refactore conterData

* Update frontend tests

* Fix spelling

* Apply make-check

* Update frontend tests

* Use forEach instead of map

* Apply coderabbitai suggestion

* Update code

---------

Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>

* Update Frontend tests

* Apply coderabbitai suggestion

* Update frontend mock data

* Refactor frontend

* Apply suggestions

* Revert docker change

* Add tooltip

* Update frontend

* Fix bug

* Update progress icon location and color

* Fix tests

---------

Co-authored-by: Arkadii Yakovets <arkadii.yakovets@owasp.org>
Co-authored-by: Kate Golovanova <kate@kgthreads.com>
@ahmedxgouda ahmedxgouda deleted the feature/slack-total-members-count branch June 15, 2025 07:36
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.

Display Slack Workspace Total Members Count on Main Page

2 participants

Comments