277 lines
5.6 KiB
Python
277 lines
5.6 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from typing import List, Optional, Dict
|
|
|
|
from pydantic import BaseModel, EmailStr, Field
|
|
from pydantic.config import ConfigDict
|
|
|
|
from app.models import ModuleType, ProgressStatus, QuestionType
|
|
|
|
|
|
class TokenPair(BaseModel):
|
|
access_token: str
|
|
refresh_token: str
|
|
token_type: str = "bearer"
|
|
|
|
|
|
class TokenRefresh(BaseModel):
|
|
refresh_token: str
|
|
|
|
|
|
class UserCreate(BaseModel):
|
|
email: EmailStr
|
|
password: str = Field(min_length=6)
|
|
|
|
|
|
class UserOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
email: EmailStr
|
|
role: str
|
|
is_active: bool
|
|
picture_url: Optional[str] = None
|
|
|
|
|
|
class AdminUserOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
email: EmailStr
|
|
role: str
|
|
is_active: bool
|
|
oauth_provider: Optional[str] = None
|
|
oauth_subject: Optional[str] = None
|
|
picture_url: Optional[str] = None
|
|
created_at: datetime
|
|
|
|
|
|
class AdminUserUpdate(BaseModel):
|
|
role: Optional[str] = None
|
|
is_active: Optional[bool] = None
|
|
|
|
|
|
class CourseCreate(BaseModel):
|
|
title: str
|
|
description: Optional[str] = None
|
|
is_published: bool = False
|
|
|
|
|
|
class CourseUpdate(BaseModel):
|
|
title: Optional[str] = None
|
|
description: Optional[str] = None
|
|
is_published: Optional[bool] = None
|
|
|
|
|
|
class AdminCourseCreate(CourseCreate):
|
|
group_ids: List[int] = []
|
|
|
|
|
|
class AdminCourseUpdate(CourseUpdate):
|
|
group_ids: Optional[List[int]] = None
|
|
|
|
|
|
class CourseOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
title: str
|
|
description: Optional[str] = None
|
|
is_published: bool
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
|
|
class AdminCourseOut(CourseOut):
|
|
group_ids: List[int] = []
|
|
|
|
|
|
class ModuleCreate(BaseModel):
|
|
order_index: int
|
|
type: ModuleType
|
|
title: str
|
|
content_text: Optional[str] = None
|
|
pass_score: Optional[int] = 80
|
|
upload_id: Optional[int] = None
|
|
|
|
|
|
class ModuleUpdate(BaseModel):
|
|
order_index: Optional[int] = None
|
|
type: Optional[ModuleType] = None
|
|
title: Optional[str] = None
|
|
content_text: Optional[str] = None
|
|
pass_score: Optional[int] = None
|
|
upload_id: Optional[int] = None
|
|
|
|
|
|
class QuizChoiceCreate(BaseModel):
|
|
text: str
|
|
is_correct: bool = False
|
|
|
|
|
|
class QuizChoiceOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
text: str
|
|
is_correct: bool
|
|
|
|
|
|
class QuizChoicePublic(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
text: str
|
|
|
|
|
|
class QuizQuestionCreate(BaseModel):
|
|
prompt: str
|
|
question_type: QuestionType = QuestionType.mcq
|
|
choices: List[QuizChoiceCreate]
|
|
|
|
|
|
class QuizQuestionUpdate(BaseModel):
|
|
prompt: Optional[str] = None
|
|
question_type: Optional[QuestionType] = None
|
|
choices: Optional[List[QuizChoiceCreate]] = None
|
|
|
|
|
|
class QuizQuestionOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
prompt: str
|
|
question_type: QuestionType
|
|
choices: List[QuizChoiceOut]
|
|
|
|
|
|
class QuizQuestionPublic(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
prompt: str
|
|
question_type: QuestionType
|
|
choices: List[QuizChoicePublic]
|
|
|
|
|
|
class ModuleOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
course_id: int
|
|
order_index: int
|
|
type: ModuleType
|
|
title: str
|
|
content_text: Optional[str] = None
|
|
pass_score: Optional[int] = None
|
|
upload_id: Optional[int] = None
|
|
created_at: datetime
|
|
questions: List[QuizQuestionOut] = []
|
|
|
|
|
|
class ModuleProgressOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
module_id: int
|
|
status: ProgressStatus
|
|
completed_at: Optional[datetime] = None
|
|
score: Optional[float] = None
|
|
|
|
|
|
class ModuleWithProgress(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
order_index: int
|
|
type: ModuleType
|
|
title: str
|
|
content_text: Optional[str] = None
|
|
pass_score: Optional[int] = None
|
|
upload_id: Optional[int] = None
|
|
status: ProgressStatus
|
|
completed_at: Optional[datetime] = None
|
|
score: Optional[float] = None
|
|
questions: List[QuizQuestionPublic] = []
|
|
|
|
|
|
class CourseWithModules(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
title: str
|
|
description: Optional[str] = None
|
|
is_published: bool
|
|
modules: List[ModuleWithProgress]
|
|
|
|
|
|
class QuizSubmit(BaseModel):
|
|
answers: Dict[int, int]
|
|
|
|
|
|
class QuizResult(BaseModel):
|
|
score: float
|
|
passed: bool
|
|
|
|
|
|
class EnrollOut(BaseModel):
|
|
course_id: int
|
|
enrolled_at: datetime
|
|
|
|
|
|
class ProgressCourse(BaseModel):
|
|
course_id: int
|
|
title: str
|
|
percent: float
|
|
status: str
|
|
final_exam_score: Optional[float] = None
|
|
final_exam_passed: Optional[bool] = None
|
|
completed_at: Optional[datetime] = None
|
|
|
|
|
|
class ProgressOut(BaseModel):
|
|
courses: List[ProgressCourse]
|
|
|
|
|
|
class GroupCreate(BaseModel):
|
|
name: str
|
|
|
|
|
|
class GroupUpdate(BaseModel):
|
|
name: Optional[str] = None
|
|
|
|
|
|
class GroupOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
name: str
|
|
created_at: datetime
|
|
|
|
|
|
class GroupMemberAdd(BaseModel):
|
|
user_id: Optional[int] = None
|
|
email: Optional[EmailStr] = None
|
|
|
|
|
|
class UploadOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
filename: str
|
|
content_type: str
|
|
size_bytes: int
|
|
created_at: datetime
|
|
|
|
|
|
class AchievementOut(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
id: int
|
|
code: str
|
|
name: str
|
|
description: Optional[str] = None
|
|
earned_at: Optional[datetime] = None
|
|
earned: bool = False
|
|
|