[Classroom] Disenroll user from a course
This commit is contained in:
parent
54c61b8b2a
commit
b4616e0ba5
27
backend/src/controller/classroom/courses.rs
Normal file
27
backend/src/controller/classroom/courses.rs
Normal file
@ -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 = "<data>")]
|
||||||
|
pub async fn disenroll_user(data: Json<DisenrollData>) -> Json<JsonResult<()>> {
|
||||||
|
match disenroll(data.course_id, data.user_id).await {
|
||||||
|
Ok(_) => JsonResult::ok(()),
|
||||||
|
Err(err) => {
|
||||||
|
log::error!("Error disenrolling user: {}", err);
|
||||||
|
JsonResult::err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,11 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use rocket::{http::Status, serde::json::Json};
|
use rocket::{http::Status, serde::json::Json};
|
||||||
|
|
||||||
|
mod courses;
|
||||||
|
|
||||||
|
pub use courses::disenroll_user_options;
|
||||||
|
pub use courses::disenroll_user;
|
||||||
|
|
||||||
#[options("/classroom/user")]
|
#[options("/classroom/user")]
|
||||||
pub fn create_user_options() -> Status {
|
pub fn create_user_options() -> Status {
|
||||||
Status::Ok
|
Status::Ok
|
||||||
|
@ -143,6 +143,8 @@ async fn rocket() -> _ {
|
|||||||
controller::classroom::create_user_options,
|
controller::classroom::create_user_options,
|
||||||
controller::classroom::create_user,
|
controller::classroom::create_user,
|
||||||
controller::classroom::get_courses,
|
controller::classroom::get_courses,
|
||||||
|
controller::classroom::disenroll_user_options,
|
||||||
|
controller::classroom::disenroll_user,
|
||||||
controller::classroom::register_course_contr_options,
|
controller::classroom::register_course_contr_options,
|
||||||
controller::classroom::register_course_contr,
|
controller::classroom::register_course_contr,
|
||||||
controller::classroom::get_expiration_date,
|
controller::classroom::get_expiration_date,
|
||||||
|
@ -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
|
||||||
|
}
|
@ -4,6 +4,7 @@ use crate::json_result::JsonResult;
|
|||||||
|
|
||||||
use self::session::ensure_session;
|
use self::session::ensure_session;
|
||||||
|
|
||||||
|
pub mod course_disenroll;
|
||||||
pub mod create_user;
|
pub mod create_user;
|
||||||
pub mod get_courses;
|
pub mod get_courses;
|
||||||
pub mod get_expiration_date;
|
pub mod get_expiration_date;
|
||||||
@ -11,7 +12,6 @@ pub mod register_course;
|
|||||||
mod session;
|
mod session;
|
||||||
pub mod update_expiration_date;
|
pub mod update_expiration_date;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
pub mod course_disenroll;
|
|
||||||
|
|
||||||
/// Tries to connect to the online classroom, and gets a session cookie
|
/// Tries to connect to the online classroom, and gets a session cookie
|
||||||
/// if neccesary.
|
/// if neccesary.
|
||||||
|
@ -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
|
/// Makes a request to the online classroom, and returns the html string
|
||||||
pub async fn request(url: String) -> Result<String, String> {
|
pub async fn request(url: String) -> Result<String, String> {
|
||||||
let classroom_url = std::env::var("CLASSROOM_URL").expect("CLASSROOM_URL env var is not set!");
|
let classroom_url = std::env::var("CLASSROOM_URL").expect("CLASSROOM_URL env var is not set!");
|
||||||
|
@ -7,8 +7,8 @@ import { OutlinedCard } from "../../components/OutlinedCard";
|
|||||||
import { XIcon } from "../../icons/XIcon";
|
import { XIcon } from "../../icons/XIcon";
|
||||||
import { QuestionIcon } from "../../icons/QuestionIcon";
|
import { QuestionIcon } from "../../icons/QuestionIcon";
|
||||||
|
|
||||||
export function CoursesList(props: {userid: number, updateSignal: number, courses: Array<ClassroomCourse>, setCourses: (c: Array<ClassroomCourse>) => void}) {
|
export function CoursesList(props: { userid: number, updateSignal: number, courses: Array<ClassroomCourse>, setCourses: (c: Array<ClassroomCourse>) => void }) {
|
||||||
const {error, setError, status, setStatus} = useLoading();
|
const { error, setError, status, setStatus } = useLoading();
|
||||||
|
|
||||||
const loadCourses = async() => {
|
const loadCourses = async() => {
|
||||||
setStatus(LoadingStatus.Loading);
|
setStatus(LoadingStatus.Loading);
|
||||||
@ -58,7 +58,7 @@ export function CoursesList(props: {userid: number, updateSignal: number, course
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<For each={props.courses}>
|
<For each={props.courses}>
|
||||||
{(c) => <Course course={c} />}
|
{(c) => <Course course={c} user_id={props.userid} onDelete={loadCourses} />}
|
||||||
</For>
|
</For>
|
||||||
|
|
||||||
<Show when={error() !== ""}>
|
<Show when={error() !== ""}>
|
||||||
@ -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 (
|
return (
|
||||||
<div
|
<div
|
||||||
class="px-4 py-3 transition-colors
|
class="px-4 py-3 transition-colors
|
||||||
@ -89,7 +116,8 @@ function Course(props: {course: ClassroomCourse}) {
|
|||||||
<p>{props.course.name}</p>
|
<p>{props.course.name}</p>
|
||||||
<button
|
<button
|
||||||
class="disabled:opacity-50 disabled:cursor-not-allowed"
|
class="disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
disabled
|
onclick={disenroll}
|
||||||
|
disabled={status() === LoadingStatus.Loading}
|
||||||
>
|
>
|
||||||
<XIcon fill="var(--c-error)" />
|
<XIcon fill="var(--c-error)" />
|
||||||
</button>
|
</button>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { HomeIcon } from "../icons/HomeIcon";
|
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 { DocxIcon } from "../icons/DocxIcon";
|
||||||
import { ScanIcon } from "../icons/ScanIcon";
|
import { ScanIcon } from "../icons/ScanIcon";
|
||||||
import { KeyIcon } from "../icons/KeyIcon";
|
import { KeyIcon } from "../icons/KeyIcon";
|
||||||
@ -18,7 +18,7 @@ export function NavRail() {
|
|||||||
<NavRailButton path="/certs" name="Certs" icon={<DocxIcon />} />
|
<NavRailButton path="/certs" name="Certs" icon={<DocxIcon />} />
|
||||||
<NavRailButton path="/accesos" name="Accesos" icon={<KeyIcon />} />
|
<NavRailButton path="/accesos" name="Accesos" icon={<KeyIcon />} />
|
||||||
<NavRailButton path="/escaneo" name="Escaneo" icon={<ScanIcon />} />
|
<NavRailButton path="/escaneo" name="Escaneo" icon={<ScanIcon />} />
|
||||||
<NavRailButton path="/reportes" name="Reportes" icon={<ChartScatterIcon />} />
|
<NavRailButton path="/reportes" name="Reportes" icon={<ChartScatterIcon fill="var(--c-on-surface-variant)" />} />
|
||||||
<ColorSelector />
|
<ColorSelector />
|
||||||
</div>
|
</div>
|
||||||
<div id="color-selector" />
|
<div id="color-selector" />
|
||||||
@ -54,7 +54,7 @@ function NavRailButton(props: {
|
|||||||
|
|
||||||
function ColorSelector() {
|
function ColorSelector() {
|
||||||
const [showSelector, setShowSelector] = createSignal(false);
|
const [showSelector, setShowSelector] = createSignal(false);
|
||||||
const colors: Array<{name: string, color: string}> = [
|
const colors: Array<{ name: string, color: string }> = [
|
||||||
{
|
{
|
||||||
name: "Verde",
|
name: "Verde",
|
||||||
color: "green",
|
color: "green",
|
||||||
@ -111,7 +111,7 @@ function ColorSelector() {
|
|||||||
<For
|
<For
|
||||||
each={colors}
|
each={colors}
|
||||||
>
|
>
|
||||||
{({name, color}) => <ColorButton name={name} color={color} />}
|
{({ name, color }) => <ColorButton name={name} color={color} />}
|
||||||
</For>
|
</For>
|
||||||
</div>
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
@ -121,7 +121,7 @@ function ColorSelector() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ColorButton(props: {name: string, color: string}) {
|
function ColorButton(props: { name: string, color: string }) {
|
||||||
const select = () => {
|
const select = () => {
|
||||||
applyColors(props.color);
|
applyColors(props.color);
|
||||||
};
|
};
|
||||||
@ -130,12 +130,12 @@ function ColorButton(props: {name: string, color: string}) {
|
|||||||
<button
|
<button
|
||||||
class="text-center bg-c-outline rounded pt-2
|
class="text-center bg-c-outline rounded pt-2
|
||||||
border border-c-transparent hover:border-c-outline transition-colors"
|
border border-c-transparent hover:border-c-outline transition-colors"
|
||||||
style={{"background-color": `var(--c-${props.color}-surface-variant)`}}
|
style={{ "background-color": `var(--c-${props.color}-surface-variant)` }}
|
||||||
onclick={select}
|
onclick={select}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="inline-block w-8 h-8 rounded-full"
|
class="inline-block w-8 h-8 rounded-full"
|
||||||
style={{"background-color": `var(--c-${props.color}-primary)`}}
|
style={{ "background-color": `var(--c-${props.color}-primary)` }}
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
{props.name}
|
{props.name}
|
||||||
|
Loading…
Reference in New Issue
Block a user