headless_lms_server/controllers/course_material/
course_modules.rs1use headless_lms_models::{course_instances, user_course_exercise_service_variables};
2use models::{course_modules, library::custom_view_exercises::CustomViewExerciseSubmissions};
3use utoipa::OpenApi;
4
5use crate::{domain::authorization::skip_authorize, prelude::*};
6
7#[derive(OpenApi)]
8#[openapi(paths(
9 get_course_module_id_by_chapter_id,
10 get_default_course_module_id_by_course_id,
11 get_user_course_module_exercises_by_exercise_type
12))]
13pub(crate) struct CourseMaterialCourseModulesApiDoc;
14
15#[utoipa::path(
21 get,
22 path = "/chapter/{chapter_id}",
23 operation_id = "getCourseMaterialModuleIdByChapterId",
24 tag = "course-material-course-modules",
25 params(
26 ("chapter_id" = Uuid, Path, description = "Chapter id")
27 ),
28 responses(
29 (status = 200, description = "Course module id", body = Uuid)
30 )
31)]
32#[instrument(skip(pool))]
33async fn get_course_module_id_by_chapter_id(
34 chapter_id: web::Path<Uuid>,
35 pool: web::Data<PgPool>,
36 user: AuthUser,
37) -> ControllerResult<web::Json<Uuid>> {
38 let mut conn = pool.acquire().await?;
39 let module_id = course_modules::get_course_module_id_by_chapter(&mut conn, *chapter_id).await?;
40 let token = skip_authorize();
41 token.authorized_ok(web::Json(module_id))
42}
43
44#[utoipa::path(
50 get,
51 path = "/course/{course_id}",
52 operation_id = "getCourseMaterialDefaultModuleIdByCourseId",
53 tag = "course-material-course-modules",
54 params(
55 ("course_id" = Uuid, Path, description = "Course id")
56 ),
57 responses(
58 (status = 200, description = "Default course module id", body = Uuid)
59 )
60)]
61#[instrument(skip(pool))]
62async fn get_default_course_module_id_by_course_id(
63 course_id: web::Path<Uuid>,
64 pool: web::Data<PgPool>,
65 user: AuthUser,
66) -> ControllerResult<web::Json<Uuid>> {
67 let mut conn = pool.acquire().await?;
68 let module = course_modules::get_default_by_course_id(&mut conn, *course_id).await?;
69 let module_id = module.id;
70 let token = skip_authorize();
71 token.authorized_ok(web::Json(module_id))
72}
73
74#[utoipa::path(
80 get,
81 path = "/{course_module_id}/exercise-tasks/{exercise_type}/{course_instance_id}",
82 operation_id = "getCourseMaterialExerciseTasksByModuleAndType",
83 tag = "course-material-course-modules",
84 params(
85 ("course_module_id" = Uuid, Path, description = "Course module id"),
86 ("exercise_type" = String, Path, description = "Exercise type"),
87 ("course_instance_id" = Uuid, Path, description = "Course instance id")
88 ),
89 responses(
90 (
91 status = 200,
92 description = "Exercise tasks, exercises, and user variables",
93 body = CustomViewExerciseSubmissions
94 )
95 )
96)]
97#[instrument(skip(pool))]
98async fn get_user_course_module_exercises_by_exercise_type(
99 path: web::Path<(Uuid, String, Uuid)>,
100 pool: web::Data<PgPool>,
101 user: AuthUser,
102) -> ControllerResult<web::Json<CustomViewExerciseSubmissions>> {
103 let mut conn = pool.acquire().await?;
104 let (course_module_id, exercise_type, course_instance_id) = path.into_inner();
105 let course_id = course_instances::get_course_instance(&mut conn, course_instance_id)
106 .await?
107 .course_id;
108 let exercise_tasks = models::exercise_task_submissions::get_user_custom_view_exercise_tasks_by_module_and_exercise_type(
109 &mut conn,
110 &exercise_type,
111 course_module_id,
112 user.id,
113 course_id)
114 .await?;
115
116 let exercises = models::exercises::get_exercises_by_module_containing_exercise_type(
117 &mut conn,
118 &exercise_type,
119 course_module_id,
120 )
121 .await?;
122 let user_variables =
123 user_course_exercise_service_variables::get_all_user_variables_for_user_and_course_and_exercise_type(&mut conn, user.id, course_id, &exercise_type).await?;
124 let token = skip_authorize();
125 let res = CustomViewExerciseSubmissions {
126 exercise_tasks,
127 exercises,
128 user_variables,
129 };
130
131 token.authorized_ok(web::Json(res))
132}
133
134pub fn _add_routes(cfg: &mut ServiceConfig) {
142 cfg.route(
143 "/chapter/{chapter_id}",
144 web::get().to(get_course_module_id_by_chapter_id),
145 )
146 .route(
147 "/course/{course_id}",
148 web::get().to(get_default_course_module_id_by_course_id),
149 )
150 .route(
151 "/{course_module_id}/exercise-tasks/{exercise_type}/{course_instance_id}",
152 web::get().to(get_user_course_module_exercises_by_exercise_type),
153 );
154}