diff --git a/backend/src/controller/classroom/courses.rs b/backend/src/controller/classroom/courses.rs new file mode 100644 index 0000000..ed1016d --- /dev/null +++ b/backend/src/controller/classroom/courses.rs @@ -0,0 +1,27 @@ +use rocket::{http::Status, serde::json::Json}; +use serde::Deserialize; + +use crate::json_result::JsonResult; +use crate::online_classroom::course_disenroll::disenroll; + +#[derive(Debug, Deserialize)] +pub struct DisenrollData { + pub course_id: i32, + pub user_id: i32, +} + +#[options("/classroom/disenroll")] +pub fn disenroll_user_options() -> Status { + Status::Ok +} + +#[post("/classroom/disenroll", format = "json", data = "")] +pub async fn disenroll_user(data: Json) -> Json> { + match disenroll(data.course_id, data.user_id).await { + Ok(_) => JsonResult::ok(()), + Err(err) => { + log::error!("Error disenrolling user: {}", err); + JsonResult::err(err) + } + } +} diff --git a/backend/src/controller/classroom/mod.rs b/backend/src/controller/classroom/mod.rs index 2548112..9a8b1b9 100644 --- a/backend/src/controller/classroom/mod.rs +++ b/backend/src/controller/classroom/mod.rs @@ -10,6 +10,11 @@ use crate::{ }; use rocket::{http::Status, serde::json::Json}; +mod courses; + +pub use courses::disenroll_user_options; +pub use courses::disenroll_user; + #[options("/classroom/user")] pub fn create_user_options() -> Status { Status::Ok diff --git a/backend/src/main.rs b/backend/src/main.rs index e9660c6..27e1c4f 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -143,6 +143,8 @@ async fn rocket() -> _ { controller::classroom::create_user_options, controller::classroom::create_user, controller::classroom::get_courses, + controller::classroom::disenroll_user_options, + controller::classroom::disenroll_user, controller::classroom::register_course_contr_options, controller::classroom::register_course_contr, controller::classroom::get_expiration_date, diff --git a/backend/src/online_classroom/course_disenroll.rs b/backend/src/online_classroom/course_disenroll.rs index e69de29..01274c9 100644 --- a/backend/src/online_classroom/course_disenroll.rs +++ b/backend/src/online_classroom/course_disenroll.rs @@ -0,0 +1,9 @@ +use super::session::classroom_get_redirect; + +pub async fn disenroll(course_id: i32, user_id: i32) -> Result<(), String> { + classroom_get_redirect(format!( + "/main/admin/user_information.php?action=unsubscribe&course_id={}&user_id={}", + course_id, user_id + )) + .await +} diff --git a/backend/src/online_classroom/mod.rs b/backend/src/online_classroom/mod.rs index a0dc826..65820b7 100644 --- a/backend/src/online_classroom/mod.rs +++ b/backend/src/online_classroom/mod.rs @@ -4,6 +4,7 @@ use crate::json_result::JsonResult; use self::session::ensure_session; +pub mod course_disenroll; pub mod create_user; pub mod get_courses; pub mod get_expiration_date; @@ -11,7 +12,6 @@ pub mod register_course; mod session; pub mod update_expiration_date; pub mod user; -pub mod course_disenroll; /// Tries to connect to the online classroom, and gets a session cookie /// if neccesary. diff --git a/backend/src/online_classroom/session.rs b/backend/src/online_classroom/session.rs index 62daa97..ef4878f 100644 --- a/backend/src/online_classroom/session.rs +++ b/backend/src/online_classroom/session.rs @@ -58,6 +58,42 @@ pub async fn classroom_post_redirect( } } +/// Make a get request & expect an http 302 redirect +pub async fn classroom_get_redirect(url: String) -> Result<(), String> { + let classroom_url = std::env::var("CLASSROOM_URL").expect("CLASSROOM_URL env var is not set!"); + + ensure_session().await?; + + // Get the stored client + let jar = SESSION_COOKIE.read().unwrap().jar.clone(); + + let uri = format!("{}{}", classroom_url, url); + + // Do the request + let response = Request::get(uri) + .cookie_jar(jar) + .body("") + .or_else(|err| Err(format!("Error creating request: {:?}", err)))? + .send(); + + let mut response = match response { + Ok(r) => r, + Err(err) => return Err(format!("Error sending request: {:?}", err)), + }; + + if response.status() == isahc::http::StatusCode::FOUND { + return Ok(()); + } + + match response.text() { + Ok(t) => { + log_html(&t); + Err(format!("Expected HTTP 302, got other code.")) + } + Err(err) => Err(format!("Error getting text from response: {:?}", err)), + } +} + /// Makes a request to the online classroom, and returns the html string pub async fn request(url: String) -> Result { let classroom_url = std::env::var("CLASSROOM_URL").expect("CLASSROOM_URL env var is not set!"); diff --git a/frontend/src/OnlineClassroom/ClassroomUserInfo/Courses.tsx b/frontend/src/OnlineClassroom/ClassroomUserInfo/Courses.tsx index 11e23d8..ff4246c 100644 --- a/frontend/src/OnlineClassroom/ClassroomUserInfo/Courses.tsx +++ b/frontend/src/OnlineClassroom/ClassroomUserInfo/Courses.tsx @@ -7,8 +7,8 @@ import { OutlinedCard } from "../../components/OutlinedCard"; import { XIcon } from "../../icons/XIcon"; import { QuestionIcon } from "../../icons/QuestionIcon"; -export function CoursesList(props: {userid: number, updateSignal: number, courses: Array, setCourses: (c: Array) => void}) { - const {error, setError, status, setStatus} = useLoading(); +export function CoursesList(props: { userid: number, updateSignal: number, courses: Array, setCourses: (c: Array) => void }) { + const { error, setError, status, setStatus } = useLoading(); const loadCourses = async() => { setStatus(LoadingStatus.Loading); @@ -58,7 +58,7 @@ export function CoursesList(props: {userid: number, updateSignal: number, course - {(c) => } + {(c) => } @@ -79,7 +79,34 @@ export function CoursesList(props: {userid: number, updateSignal: number, course ); } -function Course(props: {course: ClassroomCourse}) { +function Course(props: { + course: ClassroomCourse, + user_id: number, + onDelete: () => void, +}) { + const { error, setError, status, setStatus } = useLoading(); + + const disenroll = () => { + console.log(`in the process of disenroll... ${props.course.course_id}`); + setStatus(LoadingStatus.Loading); + setError(""); + + backend.post("/api/classroom/disenroll", { + course_id: props.course.course_id, + user_id: props.user_id, + }) + .then(() => { + setStatus(LoadingStatus.Ok); + props.onDelete(); + }) + .catch((err) => { + alert("Error desmatriculando. Ver consola"); + console.log(err); + // setError(err); + setStatus(LoadingStatus.Error); + }); + }; + return (
diff --git a/frontend/src/components/NavRail.tsx b/frontend/src/components/NavRail.tsx index c0d674c..e928f04 100644 --- a/frontend/src/components/NavRail.tsx +++ b/frontend/src/components/NavRail.tsx @@ -1,5 +1,5 @@ import { HomeIcon } from "../icons/HomeIcon"; -import {createSignal, Show, type JSX, For} from "solid-js"; +import { createSignal, Show, type JSX, For } from "solid-js"; import { DocxIcon } from "../icons/DocxIcon"; import { ScanIcon } from "../icons/ScanIcon"; import { KeyIcon } from "../icons/KeyIcon"; @@ -18,7 +18,7 @@ export function NavRail() { } /> } /> } /> - } /> + } />
@@ -54,7 +54,7 @@ function NavRailButton(props: { function ColorSelector() { const [showSelector, setShowSelector] = createSignal(false); - const colors: Array<{name: string, color: string}> = [ + const colors: Array<{ name: string, color: string }> = [ { name: "Verde", color: "green", @@ -96,7 +96,7 @@ function ColorSelector() {
- Colores + Colores @@ -111,7 +111,7 @@ function ColorSelector() { - {({name, color}) => } + {({ name, color }) => } @@ -121,7 +121,7 @@ function ColorSelector() { ); } -function ColorButton(props: {name: string, color: string}) { +function ColorButton(props: { name: string, color: string }) { const select = () => { applyColors(props.color); }; @@ -130,12 +130,12 @@ function ColorButton(props: {name: string, color: string}) {