feat: add feedback management endpoints and update group controller with feedback services
This commit is contained in:
parent
96b07323cc
commit
73642874c0
4 changed files with 117 additions and 1 deletions
|
@ -3,6 +3,7 @@ use actix_web::web::{self, ServiceConfig};
|
||||||
// TODO: Refactor to use re-exports instead of making module public
|
// TODO: Refactor to use re-exports instead of making module public
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod class;
|
pub mod class;
|
||||||
|
pub mod feedback;
|
||||||
pub mod group;
|
pub mod group;
|
||||||
pub mod project;
|
pub mod project;
|
||||||
pub mod template;
|
pub mod template;
|
||||||
|
@ -15,6 +16,7 @@ pub fn register_controllers(cfg: &mut ServiceConfig) {
|
||||||
.service(web::scope("/class").configure(class::setup))
|
.service(web::scope("/class").configure(class::setup))
|
||||||
.service(web::scope("/template").configure(template::setup))
|
.service(web::scope("/template").configure(template::setup))
|
||||||
.service(web::scope("/auth").configure(auth::setup))
|
.service(web::scope("/auth").configure(auth::setup))
|
||||||
|
.service(web::scope("/feedback").configure(feedback::setup))
|
||||||
.service(
|
.service(
|
||||||
web::resource("/ok").to(|| async { actix_web::HttpResponse::Ok().body("available") }),
|
web::resource("/ok").to(|| async { actix_web::HttpResponse::Ok().body("available") }),
|
||||||
);
|
);
|
||||||
|
|
59
crates/backend/src/controller/feedback.rs
Normal file
59
crates/backend/src/controller/feedback.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use actix_web::{HttpResponse, Responder, delete, get, post, web::ServiceConfig};
|
||||||
|
|
||||||
|
use crate::error::{ApiError, MessageResponse};
|
||||||
|
|
||||||
|
pub fn setup(cfg: &mut ServiceConfig) {
|
||||||
|
cfg.service(get_feedback_form)
|
||||||
|
.service(submit_feedback)
|
||||||
|
.service(get_feedback_status)
|
||||||
|
.service(reset_feedback);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[utoipa::path(get, path = "/api/v1/feedback/{token}", tag = "feedback")]
|
||||||
|
#[get("/feedback/{token}")]
|
||||||
|
pub async fn get_feedback_form() -> Result<impl Responder, ApiError> {
|
||||||
|
// TODO: Implement feedback form retrieval
|
||||||
|
// 1. Validate token exists and is not completed
|
||||||
|
// 2. Get project template and group information
|
||||||
|
// 3. Return form structure
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok().json("{}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[utoipa::path(post, path = "/api/v1/feedback/{token}", tag = "feedback")]
|
||||||
|
#[post("/feedback/{token}")]
|
||||||
|
pub async fn submit_feedback() -> Result<impl Responder, ApiError> {
|
||||||
|
// TODO: Implement feedback submission
|
||||||
|
// 1. Validate token and ensure not already completed
|
||||||
|
// 2. Store feedback responses
|
||||||
|
// 3. Mark as completed with timestamp
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok().json(MessageResponse {
|
||||||
|
message: "Feedback submitted successfully".to_string(),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[utoipa::path(get, path = "/api/v1/feedback/{token}/status", tag = "feedback")]
|
||||||
|
#[get("/feedback/{token}/status")]
|
||||||
|
pub async fn get_feedback_status() -> Result<impl Responder, ApiError> {
|
||||||
|
// TODO: Implement status checking
|
||||||
|
// 1. Get completion status for this token
|
||||||
|
// 2. Check if all group members completed feedback
|
||||||
|
// 3. Calculate final grade if group grade exists
|
||||||
|
// 4. Get anonymized feedback received
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok().json("{}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[utoipa::path(delete, path = "/api/v1/feedback/{token}/reset", tag = "feedback")]
|
||||||
|
#[delete("/feedback/{token}/reset")]
|
||||||
|
pub async fn reset_feedback() -> Result<impl Responder, ApiError> {
|
||||||
|
// TODO: Implement feedback reset
|
||||||
|
// 1. Verify teacher authorization
|
||||||
|
// 2. Reset completion status and clear responses
|
||||||
|
// 3. Optionally regenerate token
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok().json(MessageResponse {
|
||||||
|
message: "Feedback reset successfully".to_string(),
|
||||||
|
}))
|
||||||
|
}
|
|
@ -5,7 +5,11 @@ pub fn setup(cfg: &mut actix_web::web::ServiceConfig) {
|
||||||
.service(get_groups_for_project)
|
.service(get_groups_for_project)
|
||||||
.service(create_group)
|
.service(create_group)
|
||||||
.service(update_group)
|
.service(update_group)
|
||||||
.service(delete_group);
|
.service(delete_group)
|
||||||
|
.service(generate_group_feedback_tokens)
|
||||||
|
.service(get_group_feedback_tokens)
|
||||||
|
.service(set_group_grade)
|
||||||
|
.service(set_individual_grades);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
|
@ -88,3 +92,47 @@ async fn update_group() -> impl Responder {
|
||||||
async fn delete_group() -> impl Responder {
|
async fn delete_group() -> impl Responder {
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[utoipa::path(
|
||||||
|
post,
|
||||||
|
path = "/api/v1/group/{id}/generate-feedback-tokens",
|
||||||
|
tag = "groups"
|
||||||
|
)]
|
||||||
|
#[post("/{id}/generate-feedback-tokens")]
|
||||||
|
async fn generate_group_feedback_tokens() -> impl Responder {
|
||||||
|
// TODO: Generate feedback tokens for all students in this group
|
||||||
|
// 1. Get all UserGroupProject entries for this group
|
||||||
|
// 2. Generate UUID tokens for each student
|
||||||
|
// 3. Update database with tokens
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
|
#[utoipa::path(get, path = "/api/v1/group/{id}/feedback-tokens", tag = "groups")]
|
||||||
|
#[get("/{id}/feedback-tokens")]
|
||||||
|
async fn get_group_feedback_tokens() -> impl Responder {
|
||||||
|
// TODO: Get all feedback tokens for students in this group
|
||||||
|
// 1. List all tokens with completion status
|
||||||
|
// 2. Include student information for teacher view
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
|
#[utoipa::path(post, path = "/api/v1/group/{id}/grade", tag = "groups")]
|
||||||
|
#[post("/{id}/grade")]
|
||||||
|
async fn set_group_grade() -> impl Responder {
|
||||||
|
// TODO: Set the group grade (same grade for all students)
|
||||||
|
// 1. Validate teacher authorization
|
||||||
|
// 2. Store group grade for all students in group
|
||||||
|
// 3. Apply same grade to all UserGroupProject entries
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
|
#[utoipa::path(post, path = "/api/v1/group/{id}/individual-grades", tag = "groups")]
|
||||||
|
#[post("/{id}/individual-grades")]
|
||||||
|
async fn set_individual_grades() -> impl Responder {
|
||||||
|
// TODO: Set individual grades for each student in group
|
||||||
|
// 1. Validate teacher authorization
|
||||||
|
// 2. Accept array of student_id -> grade mappings
|
||||||
|
// 3. Store individual grades in UserGroupProject entries
|
||||||
|
// 4. Calculate final grades with peer feedback if available
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
|
@ -64,6 +64,9 @@ impl MigrationTrait for Migration {
|
||||||
.col(uuid(UserGroupProject::UserId))
|
.col(uuid(UserGroupProject::UserId))
|
||||||
.col(uuid(UserGroupProject::GroupId))
|
.col(uuid(UserGroupProject::GroupId))
|
||||||
.col(uuid(UserGroupProject::ProjectId))
|
.col(uuid(UserGroupProject::ProjectId))
|
||||||
|
.col(uuid_uniq(UserGroupProject::FeedbackId).null())
|
||||||
|
.col(boolean(UserGroupProject::FeedbackCompleted).default(false))
|
||||||
|
.col(date_time(UserGroupProject::FeedbackCompletedAt).null())
|
||||||
.primary_key(
|
.primary_key(
|
||||||
Index::create()
|
Index::create()
|
||||||
.col(UserGroupProject::UserId)
|
.col(UserGroupProject::UserId)
|
||||||
|
@ -173,6 +176,10 @@ enum UserGroupProject {
|
||||||
UserId,
|
UserId,
|
||||||
GroupId,
|
GroupId,
|
||||||
ProjectId,
|
ProjectId,
|
||||||
|
// Feedback
|
||||||
|
FeedbackId,
|
||||||
|
FeedbackCompleted,
|
||||||
|
FeedbackCompletedAt,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(DeriveIden)]
|
#[derive(DeriveIden)]
|
||||||
|
|
Loading…
Add table
Reference in a new issue