Study Groups#75
Conversation
|
Warning Review limit reached
Next review available in: 42 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Repository: alphaonelabs/coderabbit/.coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (6)
WalkthroughThis 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. ChangesStudy Groups Feature
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
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
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, 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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
⛔ Files ignored due to path filters (1)
migrations/0011_add_study_groups.sqlis excluded by!**/migrations/**
📒 Files selected for processing (8)
public/invitations.htmlpublic/partials/navbar.htmlpublic/study-group-detail.htmlpublic/study-groups.htmlschema.sqlsrc/study_groups.pysrc/worker.pytests/test_study_groups_api.py
|
please update this to use the activity object as type study group |
|
@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? |
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 usespending | accepted | declinedmatching Django source.activity_idis 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:
Impact: