Skip to content

feat: Teacher Classroom Management — create, enroll students, track attendance, and visualize seating in 3D#266

Open
hasnaa88 wants to merge 7 commits into
Open-TutorAi:mainfrom
hasnaa88:feature/classroom-management
Open

feat: Teacher Classroom Management — create, enroll students, track attendance, and visualize seating in 3D#266
hasnaa88 wants to merge 7 commits into
Open-TutorAi:mainfrom
hasnaa88:feature/classroom-management

Conversation

@hasnaa88

@hasnaa88 hasnaa88 commented Jun 24, 2026

Copy link
Copy Markdown

Why

Open TutorAI CE lacked any classroom management workflow for teachers.
This PR introduces the full end-to-end feature so that teachers can
organize students into classrooms, track attendance in real time, and
communicate through announcements — without relying on external tools.

Changelog

Added

  • Teacher classroom CRUD (create, edit, delete) with a 6-step wizard
  • Student enrollment via email, CSV import, permanent join code, and one-off invite codes
  • Live attendance sessions: students self check-in, teacher can override statuses manually
  • Per-student attendance history (presence %, absence %, last 10 sessions)
  • Classroom announcements stream (post and delete)
  • 3D seating chart (Three.js) with rows, U-shape, and islands layouts
  • Rate limiting on auth and enrollment endpoints (slowapi)
  • Pagination on all list endpoints (limit / offset)
  • Security headers middleware (CSP, X-Frame-Options, nosniff, Referrer-Policy)
  • Input validation bounds on all free-text and numeric schema fields
  • CSV upload limits (5 MB, 2 000 rows, .csv extension check)

Changed

  • JWT dev secret replaced with secrets.token_hex(32) (no more static string)
  • Invite code entropy increased from 48 bits to 64 bits
  • Production Vite build no longer emits sourcemaps

Summary

This PR delivers the full teacher classroom management workflow end to end:
teachers can create and manage classrooms, enroll students, run live attendance
sessions, post announcements, and visualize the class in a 3D seating chart.
Students can join classrooms with a code, self check-in during live sessions,
and read class announcements.


Teacher Dashboard & Classrooms

Teacher Dashboard
teacher-dashboard

My Classrooms
teacher-my-classrooms


Create a Classroom

A 6-step wizard guides the teacher through name, subject, course, objectives,
level, and a final review before creation.

Create Classroom — Step 1
create-classroom-step1

Create Classroom — Review
create-classroom-review


Edit & Delete a Classroom

Edit Classroom
edit-classroom

Delete Classroom
delete-classroom-dialog


Student Enrollment

Students can be added by email, imported via CSV, or enrolled with a join code.

Students Tab — empty
students-tab-empty

Students Tab — list view
students-list


3D Seating Chart

Three switchable layouts: rows, U-shape, and islands (groups of 4).
Hover to see a student's name; click to open their info card.

3D Chart — Islands
3d-chart-islands

3D Chart — Rows
3d-chart-rows

3D Chart — U-shape
3d-chart-u


Live Attendance Sessions

When the teacher starts a session, all enrolled students are marked Absent by
default. Students join from their portal and are automatically marked Present.

Attendance Tab — empty
presences-tab-empty

Start Session modal
start-session-modal

Session started confirmation
session-started-confirmation

Attendance list + Student History
attendance-with-student-history


Student Portal

Students see a Live badge on open sessions and can join with one click.

Student My Classrooms
student-my-classrooms

Student — You are present ✓
student-card-present


Test plan

  • pytest -q → 272 passed, 0 failed
  • Teacher can create / edit / delete a classroom
  • Teacher can add a student by email, import a CSV, and share a join code
  • Teacher can generate a one-off invite code with expiry and max-uses
  • Student can join a classroom with a code
  • Teacher starts a session → all students default to ABSENT
  • Student clicks "Join Session" → marked PRESENT
  • Teacher manually overrides a student's status → saved immediately
  • Teacher ends a session → students can no longer join
  • Teacher posts an announcement → enrolled students see it
  • Teacher deletes an announcement → removed immediately for all users
  • 3D seating chart renders and layout switching works without page reload
  • Clicking a student avatar opens their info card with attendance stats

hasnaa88 added 5 commits May 6, 2026 15:19
- app.css : reorganisation, suppression doublons, design system complet
- UserMessage : bulle dégradé bleu/cyan avec shimmer hover
- ResponseMessage : bulle AI avec accent bar et animations
- Chat : glassmorphism navbar, input floating, loading motivant
- MessageInput : amélioration zone de saisie
- Sidebar, RightBar, ConfirmDialog : améliorations visuelles
…ments, 3D seating chart)

Builds out the full teacher classroom workflow end to end:
- Classroom CRUD with student enrollment via manual add, CSV import,
  a persistent join code, and ad-hoc invite codes
- Live attendance: sessions default students to absent, students self
  check in via /join, teachers can end a session to stop check-ins
- Classroom announcements (stream) so teachers can post updates that
  enrolled students see on their dashboard
- A Three.js 3D seating chart; clicking a student's avatar opens their
  info with live presence/absence percentages
- Shared teacher dashboard shell (sidebar + navbar) reused from the
  student UI, plus a student-facing "My Classrooms" + join flow
…shots to docs

- Add rate limiting (slowapi) on login, signup, invite redeem, and session join
- Add pagination (limit/offset) to classroom and student list endpoints
- Add security headers middleware (CSP, X-Frame-Options, nosniff, Referrer-Policy)
- Reject CSV imports larger than 5 MB or exceeding 2 000 rows
- Replace hardcoded JWT dev secret with a random token (secrets.token_hex)
- Guard against CORS wildcard + allow_credentials combination in production
- Add max_length/ge field bounds to all free-text and numeric schema fields
- Increase invite code entropy from 48 bits (hex[:12]) to 64 bits (hex[:16])
- Disable sourcemaps in production Vite build
- Update teacher classroom management user guide with annotated screenshots
…nouncements, 3D seating chart, security fixes, and docs
@hasnaa88 hasnaa88 requested a review from pr-elhajji as a code owner June 24, 2026 21:18
@TarekAi TarekAi self-requested a review June 24, 2026 22:58

@TarekAi TarekAi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thank you @hasnaa88 for this contribution, we really appreciate your effort. Before we start reviewing your work, could you please resolve the merge conflicts ?

@Oumaima-elkhoummassi

Copy link
Copy Markdown

Hi @hasnaa88
Documentation Review – Great effort on the comprehensive documentation! However, there are some issues to fix:

Missing steps in the user guide (features exist in the code/API but aren't shown):

  • Manually overriding a student's presence status (PATCH /api/presences/{id})
  • Creating a one-off/expiring invite code (POST /api/classrooms/{id}/invites) -
    the guide only covers the permanent join code
  • Deleting an announcement (DELETE /api/announcements/{id})

Language: a few French words appear in the user guide ("Présences tab", "Démarrer une séance") and the entire class-diagram.md file is in French — could you switch these to English to match the project's documentation rule?

.Rhistory appears to be an unrelated local file (R language) - please
remove it from the PR.

Reminder: could you add a "Why" section and a changelog entry to the PR
description ?

Please address the missing guide sections and the language fix before approval.

@TarekAi

TarekAi commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Can we use the existing 3D classroom for the students organization ?

@hasnaa88

Copy link
Copy Markdown
Author

Hi Mr. @TarekAi
Partially — the 3D scene can be the visual layer, but drag-and-drop seat assignment is not yet implemented.

The current component already renders students on desks in 3D and detects clicks on avatars. What's missing is the ability to drag a student from one seat to another and save that arrangement.

It's doable as a next step on top of what's already there.

@Eziane

Eziane commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Salam @hasnaa88
Thanks for the contribution!
Please resolve the merge conflicts so we can review it

@Eziane

Eziane commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Salam @hasnaa88
Went through the backend side of this in detail (checked out the branch locally),

1. The new Alembic migrations aren't actually run anywhere
alembic/versions/*.py, data/database.py

This PR adds 4 real migration files (create classrooms table, add objectives to class_sessions, add ended_at to class_sessions, etc.) — genuine ALTER TABLE/add_column changes meant for an existing database. But the app still starts up via data/database.py::init_database(), which just calls Base.metadata.create_all() — and nothing in the Dockerfile, devops scripts, or CI ever runs alembic upgrade head. create_all() only creates tables that don't exist yet; it won't add a new column to a table that's already there. So a brand-new database is fine, but deploying this onto an existing production database won't pick up the new columns, and the app will error the first time it touches them. Either wire alembic upgrade head into the deploy step, or drop the migration files and keep relying on create_all() — just needs to be one or the other.

2. Self-check-in is rate-limited by IP, which will misfire for a whole classroom
gateway/http/routers/sessions.py line 128 (POST /api/sessions/{session_id}/join, @limiter.limit("20/minute"))

The limiter's key is get_remote_address (slowapi default) — capped per IP, not per student. Live attendance check-in is exactly the scenario where a whole class checks in within a minute or two, often from the same school network/NAT — meaning they'd share one IP. Past the 20th check-in from that IP in a minute, the rest get blocked. Worth keying this one off current_user.id instead (it's an authenticated endpoint anyway), or raising the ceiling well above a typical class size.

Also noticed (not blocking): ownership checks use built-in PermissionError here instead of the project's common.exceptions.AuthorizationError used elsewhere — just a consistency nit.

Heads-up, not this PR's fault: #274 will conflict hard with this one if both land — both add teacher classroom-management backend code, and both independently created gateway/http/rate_limit.py from scratch with completely different, incompatible implementations. Someone needs to pick one before both can merge.

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 introduces an end-to-end “Teacher Classroom Management” feature spanning UI (SvelteKit), API (FastAPI), database models/migrations (SQLAlchemy/Alembic), and tests (Vitest/Cypress/Pytest), enabling teachers to manage classrooms, enroll students, run attendance sessions, and post announcements.

Changes:

  • Adds classroom CRUD UI (wizard + dashboard), student enrollment flows (invite codes, CSV import), and attendance + announcements UIs.
  • Implements corresponding API routes/services/repositories, new domain models, and Alembic migrations.
  • Adds rate limiting + security headers middleware, and expands unit/integration/e2e test coverage.

Reviewed changes

Copilot reviewed 113 out of 160 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
ui/vitest.config.js Adjusts Vitest config to define Vite globals and force browser resolution conditions.
ui/vite.config.ts Updates Vite build sourcemap behavior (intended prod change).
ui/src/tests/teacherShell.test.ts Adds unit tests for teacher shell navbar/redirect behavior.
ui/src/tests/studentInfoModal.test.ts Adds tests for student info modal + history loading/error cases.
ui/src/tests/studentClassrooms.test.ts Adds tests for student classrooms page behaviors (live session/join/invite).
ui/src/tests/studentAvatar.test.ts Adds tests for avatar photo/initials fallback logic.
ui/src/tests/editClassroom.test.ts Adds tests for edit-classroom page prefill/save/error handling.
ui/src/tests/createClassroom.test.ts Adds tests for create-classroom wizard navigation/validation/submit.
ui/src/tests/classroomSeatingChart.test.ts Adds tests for seating chart empty/WebGL-unavailable/layout controls.
ui/src/tests/classroomsApi.test.ts Adds MSW-based tests for classrooms + sessions API clients.
ui/src/tests/classrooms.test.ts Adds tests for “My Classrooms” dashboard UI and filtering/navigation.
ui/src/tests/announcementsFeed.test.ts Adds tests for announcements list/post/delete/error states.
ui/src/routes/teacher/+layout.svelte Introduces teacher route layout shell wrapper.
ui/src/routes/classrooms/new/+page.svelte Adds 6-step classroom creation wizard page.
ui/src/routes/classrooms/+page.svelte Adds “My Classrooms” list page with search + empty/loading states.
ui/src/routes/classrooms/+layout.svelte Wraps classrooms routes with teacher shell layout.
ui/src/lib/types/classroom.ts Adds TS types for classrooms, enrollment, sessions, attendance, announcements.
ui/src/lib/components/wizard/StepSubject.svelte Wizard step: name/description/subject inputs.
ui/src/lib/components/wizard/StepReview.svelte Wizard step: review table + submit + inline errors.
ui/src/lib/components/wizard/StepObjectives.svelte Wizard step: objectives input.
ui/src/lib/components/wizard/StepLevel.svelte Wizard step: level selection.
ui/src/lib/components/wizard/StepDetails.svelte Wizard step: duration/language inputs.
ui/src/lib/components/wizard/StepCourse.svelte Wizard step: course name input.
ui/src/lib/components/teacher/TeacherShell.svelte Adds shared teacher chrome + auth guard around teacher/classrooms routes.
ui/src/lib/components/StudentInfoModal.svelte Adds modal showing student details and attendance history panel.
ui/src/lib/components/StudentAvatar.svelte Adds avatar component with deterministic color + photo fallback.
ui/src/lib/components/student/pages/Dashboard.svelte Replaces placeholder join-course logic with real invite redemption.
ui/src/lib/components/student/elements/Sidebar.svelte Adds forced role + href support; maps /classrooms/* to nav highlighting.
ui/src/lib/components/student/elements/RightBar.svelte Refactors progress card UI structure.
ui/src/lib/components/StartSessionModal.svelte Adds start-session modal with success state and error handling.
ui/src/lib/components/icons/StopCircle.svelte Adds stop-circle icon for ending sessions.
ui/src/lib/components/DeleteClassroomModal.svelte Adds delete confirmation modal with consequences list.
ui/src/lib/components/CreateStudentModal.svelte Adds UI to create a student account and enroll into classroom.
ui/src/lib/components/ClassroomCard.svelte Adds classroom card UI with options menu + delete integration.
ui/src/lib/components/chat/Messages/UserMessage.svelte Updates user message styling.
ui/src/lib/components/chat/Messages/ResponseMessage.svelte Tweaks SVG stroke color in response message UI.
ui/src/lib/components/chat/MessageInput.svelte Minor whitespace change.
ui/src/lib/components/attendance/StudentHistoryPanel.svelte Adds student attendance history visualization panel.
ui/src/lib/components/attendance/SessionList.svelte Adds session list UI with end/delete controls.
ui/src/lib/components/attendance/SessionDetail.svelte Adds session detail table of presences + student selection.
ui/src/lib/components/attendance/PresenceStatusBadge.svelte Adds status badge component for presence state.
ui/src/lib/components/attendance/AttendanceKPICards.svelte Adds attendance KPI cards component.
ui/src/lib/components/attendance/AttendanceDonut.svelte Adds donut chart component for attendance breakdown.
ui/src/lib/components/AnnouncementsFeed.svelte Adds announcement stream UI (list/post/delete, permission-gated).
ui/src/lib/apis/sessions/index.ts Adds sessions/attendance API client.
ui/src/lib/apis/errors.ts Adds shared API error types (Forbidden/NotFound).
ui/src/lib/apis/classrooms/index.ts Adds classrooms API client incl. students/import/invites/enrolled list.
ui/src/lib/apis/announcements/index.ts Adds announcements API client.
ui/src/app.css Minor whitespace change.
ui/package.json Adds MSW + Vitest coverage dependency ordering updates.
ui/cypress/e2e/classrooms.cy.ts Adds Cypress e2e coverage for classroom workflows + access control.
tests/test_classrooms_import_invites.py Adds integration tests for CSV import, invites, join code persistence, rate limiting.
tests/test_auth.py Adds integration test for signin rate limiting.
tests/test_announcements.py Adds unit + integration coverage for announcements service and endpoints.
tests/fixtures/sample_students.csv Adds sample CSV fixture for student import scenarios.
tests/conftest.py Adds autouse fixture to reset rate limiter between tests.
requirements.txt Adds slowapi + pytest-mock dependency.
requirements-ci.txt Adds slowapi + pytest-mock to CI dependencies.
pytest.ini Introduces unit/integration markers.
pyproject.toml Adds pytest-mock to project dependencies list.
Makefile Adds feature-specific test targets for classrooms UI/API and e2e runs.
learning/sessions/schemas.py Adds Pydantic schemas for sessions/presences/stats/history.
learning/classrooms/schemas.py Adds classroom/enrollment/invite Pydantic schemas and validation bounds.
learning/classrooms/repository.py Adds classroom repository operations incl. invites and enrollment queries.
learning/attendance/repository.py Adds attendance repository for sessions/presences operations.
learning/attendance/init.py Declares attendance domain boundary.
learning/announcements/service.py Adds announcements service with access checks and CRUD logic.
learning/announcements/schemas.py Adds Pydantic schemas for announcements.
learning/announcements/repository.py Adds announcements repository CRUD.
learning/announcements/init.py Declares announcements domain boundary.
gateway/http/routers/sessions.py Adds attendance/session routes incl. join rate limiting.
gateway/http/routers/auth.py Adds rate limiting to auth endpoints + role allowlist for self-signup.
gateway/http/routers/announcements.py Adds announcements routes for classroom stream.
gateway/http/rate_limit.py Introduces shared SlowAPI limiter module.
gateway/http/app.py Registers new routers, adds security headers middleware, adds rate limit handler.
docs/teacher_space/teacher-classroom-management-user-guide.md Adds user guide documentation for the feature.
docs/teacher_space/sequence-diagram.md Adds mermaid sequence diagrams for core flows.
docs/teacher_space/class-diagram.md Adds mermaid class diagram for new domain entities.
data/models/user.py Adds relationships for classrooms/enrollments/presences.
data/models/session.py Adds ClassSession SQLAlchemy model.
data/models/presence.py Adds Presence SQLAlchemy model + PresenceStatus enum.
data/models/invite.py Adds Invite SQLAlchemy model.
data/models/enrollment.py Adds Enrollment SQLAlchemy model.
data/models/classroom.py Adds Classroom SQLAlchemy model + relationships.
data/models/announcement.py Adds Announcement SQLAlchemy model.
data/models/init.py Exports new models/enums.
config/settings.py Replaces dev JWT secret behavior and adds CORS+credentials safety guard.
alembic/versions/d020e02dee83_add_ended_at_to_class_sessions.py Adds ended_at column migration for class_sessions.
alembic/versions/96394a73af7d_add_objectives_to_class_sessions.py Adds objectives column migration for class_sessions.
alembic/versions/3aabdff2eab4_teacher_classroom_management.py Adds initial migrations for classrooms/enrollments/sessions/presences tables.
alembic/versions/25d47d6be6ea_add_invite_is_primary_and_announcements.py Adds invite primary flag + announcements table migration.
alembic/script.py.mako Adds Alembic revision template.
alembic/README Adds Alembic readme stub.
alembic/env.py Adds Alembic env configuration wiring Base metadata.
alembic.ini Adds Alembic configuration.
accounts/users/service.py Adjusts create_user role handling for optional role input.
.gitignore Adds .Rhistory ignore.
Files not reviewed (1)
  • ui/package-lock.json: Generated file

fill="none"
stroke={arc.color}
stroke-width={STROKE}
stroke-dasharray="{arc.length} {CIRCUMFERENCE - arc.length}"
Comment on lines +21 to +32
const isDarkMode = derived(theme, ($theme) => {
return (
$theme === 'dark' ||
($theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches)
);
});

let currentIsDarkMode = false;
isDarkMode.subscribe((value) => {
currentIsDarkMode = value;
document.documentElement.classList.toggle('dark', value);
});
Comment on lines +68 to +73
if (pathname.startsWith('/classrooms')) {
pageFromUrl = 'classrooms';
} else {
const pathSegments = pathname.split('/');
if (pathSegments.length >= 3) {
pageFromUrl = pathSegments[2]; // student/dashboard -> "dashboard"
Comment on lines +105 to +108
<span class="progress-badge">
{courseCompletion < 50 ? "In Progress" : "Almost Done"}
</span>
</div>
Comment on lines +125 to +129
<p class="text-center text-sm text-gray-500 dark:text-gray-400 mt-3">
{courseCompletion < 50
? "Keep going 💪"
: "You're doing great 🚀"}
</p>
Comment thread ui/vite.config.ts
Comment on lines 37 to 39
build: {
sourcemap: true
sourcemap: process.env.NODE_ENV !== 'production'
},
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.

5 participants