Skip to content

feat: Add waiting room DO and courses flows across learner and host journeys#49

Open
Lakshya-2440 wants to merge 3 commits into
alphaonelabs:mainfrom
Lakshya-2440:feat/waitingroom-courses-clean
Open

feat: Add waiting room DO and courses flows across learner and host journeys#49
Lakshya-2440 wants to merge 3 commits into
alphaonelabs:mainfrom
Lakshya-2440:feat/waitingroom-courses-clean

Conversation

@Lakshya-2440

@Lakshya-2440 Lakshya-2440 commented Apr 20, 2026

Copy link
Copy Markdown

This PR establishes the core discovery-to-course flow for Alpha One Labs by connecting the Waiting Room, Courses, and Teaching journeys end to end. It introduces dedicated pages for room detail, course listing, and teach-course creation, and adds backend support so creators can fulfill demand from waiting rooms into actual courses.

What’s Implemented
Waiting Room + Course Conversion Flow
Added waiting room detail experience and clickable room cards.
Added support for marking a waiting room as fulfilled with linked course metadata.
Exposed room-level fetch APIs for detail rendering and creator actions.

Courses Experience
Added dedicated Courses listing page and scripts.
Added Teach Course flow for instructors/hosts.
Integrated navigation updates so users can move smoothly across dashboard, waiting room, and courses.

Host Management Controls
Added host-side delete actions for:
Entire course/activity
Individual sessions within a course
Added corresponding backend endpoints with authorization checks and ownership validation.

Impact / Review Focus
Waiting room fulfill lifecycle and creator-only authorization.
Correctness of delete flows (activity/session) and data cleanup.

Demo
https://drive.google.com/file/d/1vQNKKGjwZYwT8LtRwKQEpbIl13ui2Djn/view?usp=sharing

Overview

This PR delivers an end-to-end “Waiting Room → Courses → Teaching” flow. Learners can create and join waiting rooms (learning requests), while instructors/hosts can fulfill those requests by creating courses from the waiting room data. It also adds creator/host-protected deletion flows and ties course/session visibility to enrollment/role state.

Key Additions

Frontend – Waiting Rooms

  • Waiting room listing (public/waitingroom.html, public/waitingroom.js): shows open/fulfilled rooms, join/leave controls, room creation modal, and periodic polling for updates.
  • Waiting room detail (public/waitingroom-detail.html, public/waitingroom-detail.js): displays room metadata and participant list, supports join/leave, and exposes creator-only actions (teach/fulfill and delete). Includes client-side error handling and refresh behavior.

Frontend – Courses & Teaching

  • Courses listing (public/courses.html, public/courses.js): authenticated user’s course cards with expandable session sections that lazy-load sessions; supports URL-based highlighting (?highlight=) and locks session content for non-enrolled/non-host viewers.
  • Course/Activity detail (public/course.html): activity details driven by id query param, fetches GET /api/activities/:actId, renders sessions (locked vs host controls), and provides host actions to delete sessions or delete the entire course/activity.
  • Teach Course from waiting room (public/teach-course.html, public/teach-course.js): fetches the waiting-room payload, blocks publishing unless the user is the waiting-room creator and the room isn’t fulfilled, creates the course + sessions, then marks the waiting room as fulfilled and redirects to the new course with highlighting.

Shared Auth/UX Utilities

  • Auth helpers (public/js/auth.js): adds token/user extraction (getUserFromToken), storage clearing/migration, Authorization header building, safe HTML escaping, and reusable user menu wiring.

Backend – Durable Object + Protected Deletion

  • WaitingRoomDO (src/worker.py, wired via wrangler.toml): Durable Object handling all /api/waitingroom* operations (list/get/create/join/leave/delete and fulfill), returning explicit status codes for auth/validation/not-found/permission failures.
  • Host-only deletion endpoints (src/worker.py):
    • POST /api/activities/delete: verifies host ownership via activities.host_id and cascades deletes across session_attendance, sessions, enrollments, activity_tags, then activities.
    • POST /api/sessions/delete: verifies host ownership by joining sessions to activities.host_id, then cascades delete across session_attendance and sessions.
  • Routing updates: dispatch forwards /api/waitingroom* requests to the global Durable Object instance and routes the new deletion endpoints to their handlers.

Impact

  • Learner UX: users can request content via waiting rooms, join/leave rooms, and see course availability once fulfilled; session details are gated until enrollment/host access.
  • Instructor/Host UX: instructors can create courses directly from waiting-room demand with pre-filled metadata, manage lifecycle, and delete courses/sessions with server-side authorization and cascading cleanup.
  • Reliability/Security: creator-only and host-only actions are enforced server-side (token + ownership validation), with structured deletion order to prevent orphaned dependent records.

@coderabbitai

coderabbitai Bot commented Apr 20, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This pull request adds waiting-room listing and detail workflows, course creation and browsing pages, an activity detail view, shared browser authentication utilities, a Durable Object backend, and authenticated deletion APIs for activities and sessions.

Changes

Waiting room workflows

Layer / File(s) Summary
Waiting room persistence and routing
src/worker.py, wrangler.toml
Adds Durable Object storage and /api/waitingroom/* handling, with binding and migration registration.
Waiting room listing interface
public/waitingroom.*
Adds room creation, rendering, participant actions, polling, modal controls, notifications, and responsive styling.
Waiting room details and teaching handoff
public/waitingroom-detail.*, public/teach-course.*
Adds room detail actions and an authenticated course-drafting flow that creates course/session records and fulfills a room.

Course management views

Layer / File(s) Summary
Course listing and session expansion
public/courses.*
Lists courses, lazy-loads sessions, applies access-based locking, escapes rendered content, and supports highlighting.
Activity detail and participation states
public/course.html
Renders activity metadata, sessions, enrollment states, join behavior, and host controls.

Shared authentication

Layer / File(s) Summary
Authentication and navigation utilities
public/js/auth.js
Adds storage migration, token parsing, authorization headers, HTML escaping, logout cleanup, and user-menu wiring.

Activity deletion controls

Layer / File(s) Summary
Activity and session deletion APIs
src/worker.py
Adds authenticated ownership checks and dependent-row cleanup for activity and session deletion.

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

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.81% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main additions: waiting room DO support and new courses/host flows.
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: 20

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@public/course.html`:
- Line 119: The esc function only escapes &, <, > which is unsafe for values
interpolated into quoted HTML attributes (see its use in building the delete
button onclick with deleteSession('\'+ esc(s.id) +\'')). Update esc to also
escape both single-quote (') and double-quote (") characters (e.g., to &#39; and
&quot;) so attribute contexts are safe, and align its behavior with the existing
escapeHtml used in courses.js / waitingroom.js so a future shared escape helper
can be introduced; change the esc implementation and verify uses like
deleteSession( ... esc(s.id) ...) and any other attribute or JS-embedded
interpolations still work with the hardened escaping.
- Around line 144-168: deleteCourse and deleteSession are async functions
invoked from inline onclick handlers, so thrown errors become unhandled promise
rejections and give no user feedback; wrap the fetch/response logic in each
function in a try/catch (same pattern used in joinActivity) and on error surface
the message to the user (e.g., alert(err.message || 'Failed to delete
course/session')) instead of throwing, while preserving the existing redirects
and successful-path behavior; update both deleteCourse() and
deleteSession(sessionId) accordingly.

In `@public/courses.html`:
- Around line 50-53: The search input inside the .nav-search div lacks an
accessible label; update the <input> with a programmatic label by either
wrapping it in a <label> element or adding an appropriate aria-label (e.g.,
aria-label="Search courses" or aria-label describing purpose) so screen readers
can identify it — target the input element within the .nav-search container to
apply this change.

In `@public/courses.js`:
- Around line 1-22: The three functions readAuthValue, clearAuth, and
authHeaders are duplicated across courses.js, waitingroom.js,
waitingroom-detail.js and inlined in course.html; extract them into a single new
public/auth.js that defines these functions once and exposes them globally
(e.g., attach to window or export for module use), include public/auth.js before
the other page scripts, then remove the duplicate implementations from
courses.js, waitingroom.js, waitingroom-detail.js and the inline script in
course.html so all callers use the shared readAuthValue, clearAuth, and
authHeaders implementations.
- Around line 119-127: The code dereferences DOM nodes grid
(document.getElementById('courses')) and empty
(document.getElementById('empty')) without checking they exist, causing a
TypeError if either is missing; update the init logic around fetchCourses/const
grid/const empty to guard against null: verify empty and grid are non-null
before accessing style or innerHTML (e.g., return or skip the DOM updates when
one is missing), and ensure the behavior of the early-return branch (when
courses.length === 0) handles the missing elements consistently so no property
is accessed on a null reference.
- Around line 81-97: In renderSessions, time and sub are being collapsed into
one expression so sub (location/description or locked message) is never shown
when time exists; update renderSessions so you render time and sub as separate
lines: compute title, time and sub as you already do, then in the template
output a session-title, a session-time line that uses escapeHtml(time) only when
time is truthy, and a separate session-sub line that uses escapeHtml(sub) (or
the locked message) so sub is shown even when time exists; ensure you use
escapeHtml for both time and sub and preserve the locked behavior.

In `@public/teach-course.html`:
- Around line 137-145: Replace the non-interactive <span class="linkish"
aria-disabled="true"> used for "+ Add Another Session Time" with a real
interactive element: change it to a <button type="button"> (or <button
type="button" disabled> if not yet implemented) so it is focusable,
keyboard-operable, and announced to assistive tech; ensure any existing click
handler in teach-course.js is bound to this button (refer to the ".linkish"
selector/handler and update it to target the new button). Also change the inputs
with id="subject" and id="tags" from type="text" to type="hidden" (or remove
display:none CSS in favor of type="hidden") so they are semantically correct and
avoid HTMLHint label warnings.

In `@public/teach-course.js`:
- Line 299: The call to fulfillRoom is using the DOM element textContent
('nav-uname') as the actor; instead use the authoritative profile data (e.g.
profile.username or the hoisted currentUser variable) instead of reading the
navbar. Update the await fulfillRoom(...) invocation to pass profile.username
(or currentUser if you move it out of the try-block started at line ~221) as the
actor argument while keeping waitingRoomId, course.id, and course.title || title
unchanged.
- Around line 136-192: The toolbar handler uses errEl
(document.getElementById('err-msg')) without validating it, so calls to
errEl.textContent can throw; update wireDescriptionToolbar to guard errEl the
same as toolbar and textarea (e.g., if (!toolbar || !textarea || !errEl) return)
or otherwise provide a safe fallback for errEl before adding the click listener
so that both uses of errEl.textContent (the initial clear in the click handler
and the 'help' branch) are safe; modify the function wiring
(wireDescriptionToolbar) to reference the validated errEl when invoking
replaceSelection/lineifySelection actions.
- Around line 271-307: The submit handler can create duplicate courses on retry
because createCourse is called unconditionally; update the handler (the function
that calls createCourse, createSession and fulfillRoom) to stash the created
course id and a session flag in local variables (e.g., courseId, sessionCreated)
and skip calling createCourse/createSession when those values exist (use
courseId to avoid re-creating the course and sessionCreated to avoid re-creating
the session), persist courseId to sessionStorage/localStorage so a page reload
still prevents duplicate creation, and on failure attempt a best-effort cleanup
by calling DELETE /api/activities/:id using the stored courseId before
re-enabling the submit button; reference createCourse, createSession,
fulfillRoom, waitingRoomId, btn and the submit handler in your changes.

In `@public/waitingroom-detail.js`:
- Around line 1-27: The auth helper functions (readAuthValue, writeAuthValue,
clearAuth, authHeaders) and related fetchRoom logic are duplicated across
multiple files; extract them into a single shared module (e.g.,
public/js/auth.js) that exports these functions and import/include that module
from public/waitingroom-detail.js (and the other files) via a <script
type="module"> or shared include; update waitingroom-detail.js to remove the
local definitions and instead call the imported
readAuthValue/writeAuthValue/clearAuth/authHeaders (and fetchRoom if
applicable), keeping exported function names unchanged so callers don’t need to
change.

In `@public/waitingroom.html`:
- Around line 27-34: The search input element (placeholder "What do you want to
learn?") is missing an accessible label and all icon buttons (elements with
class "icon-btn") lack explicit button types; add aria-label="Search" to that
input and add type="button" to each <button class="icon-btn"> (including the
cart button with the .cart-badge span) so intent is explicit and screen readers
can access the input.
- Around line 60-62: The initial HTML seeds for the room counter and username
are hard-coded causing a flash; change the default content of the elements with
id "room-count" and "nav-uname" in waitingroom.html from "8" and "lakshya" to
sensible placeholders (e.g., "0" for `#room-count` and "..." for `#nav-uname`) so
the first paint matches eventual JS-updated values (consistent with courses.html
/ teach-course.html); update the text nodes in the elements with id="room-count"
and id="nav-uname" accordingly.

In `@public/waitingroom.js`:
- Around line 330-346: The polling code uses setInterval(refreshRooms, 3000) and
only clears it on beforeunload and only guards re-entrancy with isRefreshing;
update this by (1) also listening for pagehide to clear the refreshInterval (add
a handler alongside window.addEventListener('beforeunload', ...)), and (2) make
the visibilitychange handler debounce against an in-flight or very-recent
refresh by checking isRefreshing before calling refreshRooms and/or scheduling a
short setTimeout (e.g., next tick/100ms) if isRefreshing is true so rapid
visibility flicker doesn't spur multiple calls; reference the functions/vars
refreshRooms, isRefreshing, refreshInterval and the events
visibilitychange/pagehide when locating the changes.
- Around line 143-198: The isCreator check uses username equality only; change
it to prefer comparing room.creatorId to currentParticipantId
(String(room.creatorId) === String(currentParticipantId)) and only fall back to
the existing username comparison (String(room.creator || '').toLowerCase() ===
String(currentUser).toLowerCase()) so the Delete button rendering (uses
isCreator) matches server-side creatorId logic and still works for
legacy/name-only rooms.
- Around line 143-155: The renderRooms function currently assumes DOM nodes
exist and will throw if document.getElementById returns null; update renderRooms
to guard accesses to grid, roomCount, youLabel and tabCount (e.g., if (!grid)
return; or only set textContent/innerHTML when the element is non-null) before
dereferencing .textContent or .innerHTML; likewise, add null checks before
setting nav-uname and nav-avatar in the code that updates the navigation (check
document.getElementById('nav-uname') and document.getElementById('nav-avatar')
exist before assigning .textContent or .src) so missing elements no longer crash
the page.

In `@src/worker.py`:
- Around line 82-99: The path-matching is too loose: the regex in m_room (used
when method == "GET") can accidentally match reserved sub-paths like
create/join/leave/delete/fulfill and the code uses
path.endswith('/api/waitingrooms') which can match unintended URLs; update the
m_room regex in the GET branch (the re.fullmatch call that assigns m_room) to
exclude those reserved words (e.g., use a negative lookahead for
create|join|leave|delete|fulfill) and replace any uses of
path.endswith('/api/waitingrooms') (and other similar endswith checks) with
exact equality checks (path == '/api/waitingrooms') so matching is unambiguous
and safe.
- Around line 186-198: The delete and fulfill handlers allow anonymous
deletes/fulfillments when a room lacks creator_id because the current checks
skip both branches if actor or creator are empty; fix by explicitly requiring an
authenticated actor and refusing when identity values are empty: in the delete
handler (variables: creator_id, actor, creator, normalized_actor,
normalized_creator, id_matches, name_matches) add an early check that auth_user
(or actor) must be present and non-empty and return 403 if missing, and treat
empty creator (legacy room with missing creator name) as not-authorized rather
than permitting deletion; apply the identical explicit
authentication-and-non-empty-identity check to the fulfill handler (the same
variable names and matching logic around name_matches) so anonymous callers
cannot operate on rooms without creatorId.
- Around line 43-234: The WaitingRoomDO handlers never run because there's no
durable object binding or dispatcher route: add a DO binding (e.g., WAITING_ROOM
= { class_name = "WaitingRoomDO" }) in wrangler.toml and update the _dispatch
function to detect /api/waitingroom* paths and forward them to the WaitingRoomDO
stub (create/get the stub and call fetch/handle as other DO routes do); also
move imports for urlparse and js to the top of the file per PEP8 (no late
imports) and add type annotations: change WaitingRoomDO.__init__(self, state,
env) to return -> None and annotate _normalize_participants(raw) with
appropriate parameter and return types (e.g., raw: Any -> List[Dict[str,str]])
to satisfy ANN204/ANN202.
- Around line 1409-1427: The deletion sequence uses multiple
env.DB.prepare(...).run() calls which are separate D1 transactions and can leave
partial state; replace with a single atomic batch by building the statements
(using env.DB.prepare(...) bound with act_id and user["id"]) and executing them
via env.DB.batch(to_js(stmts)) to ensure atomic cascade deletion; additionally,
after successful deletion invoke your waiting-room invalidation (either call the
Durable Object endpoint to clear courseId/courseTitle or emit an event so the
waiting room DO removes stale linked-course fields) so the waiting room does not
show links to deleted activities; keep the existing capture_exception(...) error
handling around the batch call to log failures.
🪄 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: cbaa49bf-36d5-4e73-8bd5-7b698f111dae

📥 Commits

Reviewing files that changed from the base of the PR and between 101794d and c994f61.

📒 Files selected for processing (10)
  • public/course.html
  • public/courses.html
  • public/courses.js
  • public/teach-course.html
  • public/teach-course.js
  • public/waitingroom-detail.html
  • public/waitingroom-detail.js
  • public/waitingroom.html
  • public/waitingroom.js
  • src/worker.py

Comment thread public/course.html Outdated
Comment thread public/course.html
Comment thread public/courses.html
Comment thread public/courses.js Outdated
Comment thread public/courses.js
Comment thread public/waitingroom.js
Comment thread src/worker.py Outdated
Comment thread src/worker.py Outdated
Comment thread src/worker.py Outdated
Comment thread src/worker.py
Introduces courses and waiting-room detail pages, teach-course flow wiring, and worker API support for room fulfillment plus host-managed course/session deletion.
@Lakshya-2440
Lakshya-2440 force-pushed the feat/waitingroom-courses-clean branch from c994f61 to 9b05d86 Compare April 20, 2026 23:04
@A1L13N
A1L13N requested a review from Copilot April 21, 2026 03:46

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.

Pull request overview

This PR connects the “Waiting Room” demand signal to course creation and adds host management delete controls, enabling an end-to-end learner discovery → host fulfillment → course/session management flow.

Changes:

  • Add a Waiting Room Durable Object with endpoints to create/list/get/join/leave/delete/fulfill rooms.
  • Introduce new frontend pages/scripts for waiting room list/detail, course listing, and “teach course from waiting room”.
  • Add backend delete endpoints for activities and sessions and wire corresponding UI controls.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
src/worker.py Adds WaitingRoomDO plus new /api/activities/delete and /api/sessions/delete endpoints.
public/waitingroom.js Implements waiting room listing UI, join/leave/delete actions, and polling refresh.
public/waitingroom.html Adds Waiting Rooms landing page markup and modal for creating requests.
public/waitingroom-detail.js Implements waiting room detail rendering and actions (join/leave/teach/delete).
public/waitingroom-detail.html Adds Waiting Room detail page markup/styles.
public/teach-course.js Implements course creation from a waiting room + fulfillment call.
public/teach-course.html Adds “teach course” form UI for fulfilling a waiting room.
public/courses.js Implements authenticated course listing and session expansion.
public/courses.html Adds Courses listing page markup and styling.
public/course.html Adds course detail page UI with host-side delete controls for course/sessions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/worker.py
Comment thread src/worker.py
Comment thread public/waitingroom.html Outdated
Comment thread public/teach-course.html Outdated
Comment thread src/worker.py Outdated
Comment thread public/course.html Outdated
Comment thread src/worker.py Outdated
Comment thread src/worker.py Outdated
Comment thread src/worker.py Outdated
Comment thread src/worker.py
@A1L13N

A1L13N commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

@Lakshya-2440 please take a look

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

🤖 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/course.html`:
- Around line 148-150: Update the delete confirmation in deleteCourse and the
associated delete button label to use “activity” instead of “course,” preserving
the existing warning that all sessions are deleted and the action cannot be
undone.
- Line 118: Update the user initialization around
JSON.parse(readAuthValue('edu_user')) to catch malformed stored JSON instead of
allowing page initialization to throw. When parsing fails, clear both the
invalid edu_user value and its associated auth entry, then continue with a null
user so the activity page can load.

In `@public/courses.html`:
- Around line 54-60: Add descriptive aria-label attributes to each icon-only
button in the nav-icons container, naming the actions represented by 💬, 🛒, 🔔,
🌐, and 🌙. Keep the existing button types, icons, and cart-badge markup
unchanged.

In `@public/courses.js`:
- Around line 92-95: Update the session-loading handler in public/courses.js to
listen for the details toggle event rather than only
button[data-action="toggle"] clicks. In the toggle handler, detect when the
details element opens and invoke fetchCourseWithSessions using its
data-course-id, preserving the existing loading and already-loaded behavior for
both native summary clicks and programmatic details.open changes.

In `@public/waitingroom.css`:
- Line 10: Remove the quotes from the Inter font-family name in every
declaration in waitingroom.css, including all eight occurrences, while
preserving the existing fallback fonts and ordering.

In `@public/waitingroom.html`:
- Around line 108-111: Update the newsletter controls in the newsletter form:
add an aria-label to the email input and an aria-label plus type="button" to the
submit button. Keep the existing placeholder and button content unchanged.

In `@src/worker.py`:
- Around line 3274-3285: Update the delete flow in api_delete_session to execute
the session_attendance and sessions DELETE statements together through
env.DB.batch, following the existing batching pattern used by
api_delete_activity. Preserve the current parameter bindings, exception capture
via capture_exception, error response, and success response.
🪄 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: 9a5d3c16-9e9b-4994-a1ec-f7270d5caa7e

📥 Commits

Reviewing files that changed from the base of the PR and between c994f61 and 07a1e24.

📒 Files selected for processing (13)
  • public/course.html
  • public/courses.html
  • public/courses.js
  • public/js/auth.js
  • public/teach-course.html
  • public/teach-course.js
  • public/waitingroom-detail.html
  • public/waitingroom-detail.js
  • public/waitingroom.css
  • public/waitingroom.html
  • public/waitingroom.js
  • src/worker.py
  • wrangler.toml

Comment thread public/course.html
Comment thread public/course.html
Comment thread public/courses.html
Comment thread public/courses.js
Comment thread public/waitingroom.css
Comment thread public/waitingroom.html
Comment thread src/worker.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants