8.3 KiB
8.3 KiB
Test Templates System - Implementation Summary
Overview
This document describes the implementation of a comprehensive Test Template System for OpenCCB, allowing instructors to create and reuse test/quiz templates based on:
- Course Level:
beginner,beginner_1,beginner_2,intermediate,advanced, etc. - Course Type:
intensiveorregular - Assessment Type:
CA,MWT,MOT,FOT,FWT
Database Changes
New Enums
-- Course levels
CREATE TYPE course_level AS ENUM (
'beginner', 'beginner_1', 'beginner_2',
'intermediate', 'intermediate_1', 'intermediate_2',
'advanced', 'advanced_1', 'advanced_2'
);
-- Course types
CREATE TYPE course_type AS ENUM ('intensive', 'regular');
-- Test types (assessment types)
CREATE TYPE test_type AS ENUM ('CA', 'MWT', 'MOT', 'FOT', 'FWT');
New Tables
test_templates
Main table for storing test templates with metadata:
id: UUID primary keyorganization_id: Multi-tenancy supportname,description: Template identificationlevel,course_type,test_type: Classification enumsduration_minutes,passing_score,total_points: Configurationinstructions: General test instructionstemplate_data: JSONB with complete test structuretags: Text array for categorizationusage_count: Tracks template popularityis_active: Soft delete support
test_template_sections
Optional sections within a test (e.g., "Reading", "Grammar", "Listening"):
template_id: Foreign key totest_templatessection_order: Ordering within templatepoints,instructions: Section-specific configsection_data: JSONB for advanced configuration
test_template_questions
Individual questions for each template:
template_id,section_id: Foreign keysquestion_order: Orderingquestion_type: "multiple-choice", "true-false", "short-answer", "essay", "matching", "ordering"question_text,options,correct_answer,explanation: Question contentpoints,metadata: Scoring and additional data
Database Functions
get_test_templates_by_filters(): Filter templates by level, type, test type, and searchincrement_template_usage(): Track template usage statistics
Course Model Updates
Added optional fields to courses table:
level: Course level enumcourse_type: Course type enum
Backend Implementation
Models (shared/common/src/models.rs)
New Rust structs:
CourseLevel,CourseType,TestType: Enum typesTestTemplate,TestTemplateSection,TestTemplateQuestion: Main modelsCreateTestTemplatePayload,UpdateTestTemplatePayload: Request/Response DTOsTestTemplateWithQuestions: Composite response type
API Handlers (services/cms-service/src/handlers_test_templates.rs)
RESTful endpoints:
| Method | Endpoint | Description |
|---|---|---|
| GET | /test-templates |
List templates with filters |
| POST | /test-templates |
Create new template |
| GET | /test-templates/{id} |
Get template with questions |
| PUT | /test-templates/{id} |
Update template |
| DELETE | /test-templates/{id} |
Delete template |
| POST | /test-templates/{id}/questions |
Add question |
| DELETE | /test-templates/{id}/questions/{qid} |
Delete question |
| POST | /test-templates/{id}/sections |
Add section |
| DELETE | /test-templates/{id}/sections/{sid} |
Delete section |
| POST | /test-templates/{id}/apply |
Apply template to lesson |
Routes (services/cms-service/src/main.rs)
All routes are protected and require organization context.
Frontend Implementation
TypeScript Types (web/studio/src/lib/api.ts)
type CourseLevel = 'beginner' | 'beginner_1' | ... | 'advanced_2';
type CourseType = 'intensive' | 'regular';
type TestType = 'CA' | 'MWT' | 'MOT' | 'FOT' | 'FWT';
type QuestionType = 'multiple-choice' | 'true-false' | ...;
interface TestTemplate { ... }
interface TestTemplateSection { ... }
interface TestTemplateQuestion { ... }
interface CreateTestTemplatePayload { ... }
API Functions (cmsApi object)
listTestTemplates(filters)getTestTemplate(templateId)createTestTemplate(payload)updateTestTemplate(templateId, payload)deleteTestTemplate(templateId)createTemplateQuestion(templateId, payload)deleteTemplateQuestion(templateId, questionId)createTemplateSection(templateId, payload)deleteTemplateSection(templateId, sectionId)applyTemplateToLesson(templateId, lessonId, gradingCategoryId)
UI Components
TestTemplateManager (web/studio/src/components/TestTemplates/TestTemplateManager.tsx)
Main management interface with:
- Grid view of templates
- Search functionality
- Advanced filters (level, course type, test type)
- Template cards showing:
- Name, description
- Level, type badges with color coding
- Duration, passing score, total points
- Tags
- Usage statistics
- Action buttons (view, edit, delete, apply)
TestTemplateForm (web/studio/src/components/TestTemplates/TestTemplateForm.tsx)
Modal form for creating/editing templates with:
- Basic info (name, description)
- Classification (level, course type, test type)
- Configuration (duration, passing score, total points)
- Instructions
- Tag management
Page (web/studio/src/app/test-templates/page.tsx)
Dedicated page at /test-templates route.
Usage Examples
Creating a Template via API
curl -X POST http://localhost:3001/test-templates \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "X-Organization-Id: YOUR_ORG_ID" \
-H "Content-Type: application/json" \
-d '{
"name": "Final Exam - Beginner 1",
"description": "Comprehensive final exam for beginner level",
"level": "beginner_1",
"course_type": "regular",
"test_type": "FWT",
"duration_minutes": 90,
"passing_score": 70,
"total_points": 100,
"instructions": "Answer all questions. You have 90 minutes.",
"tags": ["final", "beginner", "written"]
}'
Filtering Templates
# Get all FOT templates for beginner intensive courses
curl "http://localhost:3001/test-templates?level=beginner_1&course_type=intensive&test_type=FOT" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Applying Template to a Lesson
curl -X POST http://localhost:3001/test-templates/TEMPLATE_ID/apply \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "X-Organization-Id: YOUR_ORG_ID" \
-H "Content-Type: application/json" \
-d '{
"lesson_id": "LESSON_ID",
"grading_category_id": "CATEGORY_ID"
}'
Migration
Run the migration to set up the database schema:
cd services/cms-service
sqlx migrate run --source migrations
The migration file is: 20260316000000_test_templates.sql
Future Enhancements
- Template Cloning: Allow duplicating existing templates
- Question Bank: Centralized repository of questions that can be mixed and matched
- Template Sharing: Share templates across organizations
- Analytics: Track template effectiveness and student performance
- AI Generation: Auto-generate templates based on course content
- Version Control: Track template revisions
- Bulk Operations: Apply templates to multiple lessons at once
- Preview Mode: Preview template before applying
File Structure
openccb/
├── shared/common/src/models.rs # Rust models
├── services/cms-service/
│ ├── migrations/20260316000000_test_templates.sql
│ ├── src/handlers_test_templates.rs # API handlers
│ └── src/main.rs # Routes
└── web/studio/
├── src/lib/api.ts # TypeScript types & API functions
├── src/components/TestTemplates/
│ ├── TestTemplateManager.tsx
│ ├── TestTemplateForm.tsx
│ └── index.ts
└── src/app/test-templates/
└── page.tsx
Testing
Backend Tests
cargo test -p common
cargo test -p cms-service
Frontend Type Check
cd web/studio
npm run type-check
Notes
- All templates are organization-scoped for multi-tenancy
- Soft delete via
is_activeflag preserves historical data - Usage count helps identify popular templates
- JSONB fields provide flexibility for evolving question types
- The system integrates with existing grading categories via
tipo_notacatalog