Skip to content

Study Groups#75

Open
Ananya44444 wants to merge 2 commits into
alphaonelabs:mainfrom
Ananya44444:study
Open

Study Groups#75
Ananya44444 wants to merge 2 commits into
alphaonelabs:mainfrom
Ananya44444:study

Conversation

@Ananya44444

@Ananya44444 Ananya44444 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Adds study group creation, membership, and invitation management to the Cloudflare Workers platform.

Database (migrations/0004_add_study_groups.sql, schema.sql)
Three new tables: study_groups, study_group_members, study_group_invites. Invite status uses pending | accepted | declined matching Django source. activity_id is nullable to allow standalone groups. Unique constraints on (group_id, user_id) and (group_id, invitee_id) enforced at DB level.

Backend (src/study_groups.py, src/worker.py)
Ten endpoints covering group CRUD, join/leave, invite and respond flows. Multi-table writes use env.DB.batch() for atomicity (group create + member insert, invite accept + member insert). Creator leave is blocked with a 400 matching Django behavior. Module lazy-loaded inside matched route branch only. Notifications wired for join, invite, accept, and decline events.

Frontend (public/study-groups.html, public/study-group-detail.html, public/invitations.html)
Group listing with search, create form, join/leave actions, detail view with member list and invite flow, and invitations page with accept/decline. Private group 403 shown as explicit UI message. Auth redirect and Bearer token fetch pattern matches existing pages.

Navigation (public/partials/navbar.html)
Study Groups added to desktop and mobile LEARN sections.

Tests (tests/test_study_groups_api.py)
45 tests covering auth, group lifecycle, membership rules, invitation flows, creator-leave block, duplicate invite 400, and capacity enforcement on accept.

Adds full study group support on Cloudflare Workers, covering group creation, membership, invitations, and responses.

Key changes:

  • New database tables for groups, members, and invites, with constraints and indexes to support membership, invite status, and activity linking.
  • New backend API module and router integration for group CRUD, join/leave, invite, and invitation accept/decline flows.
  • Batched DB writes for atomic operations like creator membership insertion and invite acceptance.
  • New frontend pages for browsing groups, viewing group details, and managing invitations.
  • Navbar updates to surface Study Groups in desktop and mobile navigation.
  • Added API tests covering auth, access control, membership rules, invite behavior, capacity checks, and atomic invite acceptance.

Impact:

  • Enables users to discover, create, join, manage, and respond to study group invitations.
  • Improves UX with clearer private-group access messaging and invitation management flows.

Copilot AI review requested due to automatic review settings July 5, 2026 14:17

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Ananya44444, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository: alphaonelabs/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2ff88616-e46d-47da-bd6c-4a4cb236aec3

📥 Commits

Reviewing files that changed from the base of the PR and between 1097c09 and fc37239.

📒 Files selected for processing (6)
  • public/invitations.html
  • public/study-group-detail.html
  • public/study-groups.html
  • src/study_groups.py
  • src/worker.py
  • tests/test_study_groups_api.py

Walkthrough

This PR adds a full "Study Groups" feature: new database tables, a backend Python API module for group CRUD, membership, and invitations, worker routing to dispatch to that module, tests, and new client-side HTML pages for browsing/creating groups, viewing group detail, and managing pending invitations.

Changes

Study Groups Feature

Layer / File(s) Summary
Database schema
schema.sql, src/worker.py
Adds study_groups, study_group_members, study_group_invites tables with foreign keys and indexes, mirrored in the worker's DDL initializer.
Backend core: list/create/detail/delete
src/study_groups.py
Adds shared helpers (auth, notifications, DB batch, user lookup) and endpoints to list, create, view details of, and delete study groups.
Backend membership: join/leave/invite/respond
src/study_groups.py
Adds join/leave with capacity checks, invite creation, invitation listing/response (accept/decline) with atomic DB updates, public activity-group listing, and the route dispatcher.
Worker routing wiring
src/worker.py
Dispatches study-groups/invitations/activity-group routes to the new module, dynamically loading and caching it.
Backend tests
tests/test_study_groups_api.py
Adds async tests covering auth, CRUD, visibility, join/leave, invite, and accept/decline scenarios.
Study groups listing page
public/study-groups.html
Adds browsing/searching public groups, "My Groups" management, create-group form, join/leave actions, and invitations badge.
Group detail page
public/study-group-detail.html
Adds group detail view with role-based leave/delete/invite actions.
Invitations page and navbar links
public/invitations.html, public/partials/navbar.html
Adds a pending-invitations page with accept/decline actions, plus navbar links to the new study-groups page.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant StudyGroupsHTML as study-groups.html
  participant Worker
  participant StudyGroupsAPI
  participant DB

  User->>StudyGroupsHTML: Create group form submit
  StudyGroupsHTML->>Worker: POST /api/study-groups
  Worker->>StudyGroupsAPI: handle(request, env, path, method)
  StudyGroupsAPI->>DB: batch insert group + creator membership
  DB-->>StudyGroupsAPI: inserted group id
  StudyGroupsAPI-->>StudyGroupsHTML: group details
  StudyGroupsHTML-->>User: reload group list
Loading
sequenceDiagram
  participant Inviter
  participant DetailPage as study-group-detail.html
  participant StudyGroupsAPI
  participant DB
  participant Invitee
  participant InvitationsPage as invitations.html

  Inviter->>DetailPage: Click "Invite"
  DetailPage->>StudyGroupsAPI: POST /invite {username}
  StudyGroupsAPI->>DB: insert pending invite
  StudyGroupsAPI-->>Invitee: notification
  Invitee->>InvitationsPage: View pending invitations
  InvitationsPage->>StudyGroupsAPI: GET /api/invitations
  Invitee->>InvitationsPage: Accept/Decline
  InvitationsPage->>StudyGroupsAPI: POST /respond {action}
  StudyGroupsAPI->>DB: batch update membership + invite status
  StudyGroupsAPI-->>Inviter: notification of response
Loading

Related Issues: Not specified in the provided data.

Related PRs: Not specified in the provided data.

Suggested labels: feature, backend, frontend, database

Suggested reviewers: Consider assigning someone familiar with the worker routing/module-loading pattern and someone comfortable reviewing SQLite schema/foreign-key constraints, since those areas carry the highest logical density in this change.

🐇 A new study nook, doors thrown wide,
Groups now gather side by side,
Invites hop in, accepted with glee,
Tables and routes align beautifully —
Hop along, reviewer, and see! 🌱

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is related to the new feature, but it is too generic to clearly convey the main change. Use a more descriptive title, such as adding study group creation, membership, and invitations.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@public/invitations.html`:
- Around line 87-104: The fade-out in respond() is ineffective because render()
in invitations.html rebuilds the list before the animation runs, detaching the
passed article node. Update respond() so the optimistic removal and render()
happen without trying to animate a stale DOM node, and remove the
article.classList.add('opacity-50')/article.remove() path or move the animation
to the live element before render() replaces it. Also drop the redundant
loadInvites() call on the success path since the local invites state is already
updated by the optimistic splice.
- Around line 55-73: The dynamic invite list in render() updates without
notifying assistive tech, so screen reader users miss accept/decline removals.
Add a polite live region to the `#invite-list` container in the invitations
template so updates are announced when render() replaces its contents, keeping
the existing list rendering logic unchanged.

In `@public/study-group-detail.html`:
- Around line 33-34: The invite controls in study-group-detail.html need
accessibility fixes: the `#invite-username` field should have an explicit
accessible label instead of relying on placeholder text, and the `#invite-btn`
should declare its button type. Update the invite markup around `#invite-username`
and `#invite-btn` to add a proper label association (or equivalent accessible
labeling) and set the button’s type explicitly so the control semantics are
clear.

In `@public/study-groups.html`:
- Around line 94-110: The error-handling paths in the study groups flows are
assuming every non-ok response is valid JSON, which can throw before the user
sees the real error. Update the `apiFetch` call sites in `create-form`, `join`,
and `leave` so that after an `!res.ok` branch they safely handle non-JSON bodies
(for example by checking the response content type or falling back to
`res.text()`), and only call `res.json()` when parsing is safe. Keep the fix
localized around the existing `apiFetch` usage and the submit/join/leave
handlers so failed responses still surface a usable message.
- Around line 67-68: The search and activity filter inputs are missing
accessible names because they rely only on placeholders. Update the markup for
the `#search` and `#activity-filter` fields in the study groups template to use
proper <label> elements (or equivalent accessible labeling tied to each input),
matching the approach used by the create-form fields. Keep the existing inputs
and ensure each field has a unique, descriptive label that screen readers can
announce.
- Around line 216-232: The join/leave click handlers in the study-groups page
are treating any non-null apiFetch response as success, so failures from the
backend are hidden. Update the handlers around the group-grid and my-groups
listeners to check res.ok before calling loadGroups(), and surface an error
state/message when join or leave returns a non-2xx response. Keep the behavior
localized to the existing event handlers and apiFetch flow so the UI only
refreshes after a confirmed success.

In `@src/study_groups.py`:
- Around line 394-409: The invite creation logic in the study group flow is
treating any UNIQUE conflict as a duplicate pending invite, but the unique
constraint on the study_group_invites row means an existing declined or older
invite should be reused instead. Update the invite handling in the study_groups
invite path to detect the conflict and refresh the existing row back to pending,
while also updating inviter_id and updated_at, rather than returning the
“pending invite already exists” error. Keep the existing helper-based error
handling around the invite creation code, but adjust the conflict branch so
re-inviting the same user/group pair succeeds by reusing the existing invite
record.

In `@src/worker.py`:
- Around line 2804-2808: The fallback loader in worker.py relies on
importlib.util but only importlib is imported, so this can still fail with
AttributeError if util was not loaded elsewhere. Update the import section so
importlib.util is explicitly imported, then keep using the existing
spec_from_file_location/module_from_spec flow in the fallback block around
study_groups loading.

In `@tests/test_study_groups_api.py`:
- Around line 123-141: The duplicate-join assertion in
test_join_public_group_success_and_join_twice_conflict is too permissive because
it accepts both 400 and 409. Update the second request assertion to the single
status code actually returned by the join flow in worker._dispatch for an
already-member case, so the test verifies the exact API contract instead of
allowing regressions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: alphaonelabs/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d5bf1849-3527-496b-b419-804fd365f3a0

📥 Commits

Reviewing files that changed from the base of the PR and between 997b01e and 1097c09.

⛔ Files ignored due to path filters (1)
  • migrations/0011_add_study_groups.sql is excluded by !**/migrations/**
📒 Files selected for processing (8)
  • public/invitations.html
  • public/partials/navbar.html
  • public/study-group-detail.html
  • public/study-groups.html
  • schema.sql
  • src/study_groups.py
  • src/worker.py
  • tests/test_study_groups_api.py

Comment thread public/invitations.html
Comment thread public/invitations.html
Comment thread public/study-group-detail.html Outdated
Comment thread public/study-groups.html Outdated
Comment thread public/study-groups.html
Comment thread public/study-groups.html
Comment thread src/study_groups.py
Comment thread src/worker.py
Comment thread tests/test_study_groups_api.py Outdated
@A1L13N

A1L13N commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

please update this to use the activity object as type study group

@A1L13N A1L13N left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

please update

@Ananya44444

Copy link
Copy Markdown
Contributor Author

@A1L13N This means _create_group will insert its own activities row (type=study_group, host_id=creator, title=name) directly, rather than accepting a pre-existing activity_id from the client right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants