use crate::db::errors::DatabaseError; use actix_web::{delete, get, post, put, web, HttpResponse, Responder}; use serde::{Deserialize, Serialize}; use std::borrow::Borrow; use std::convert::TryFrom; use crate::db::models::{Periods, Schedule}; use crate::db::schedules::*; use crate::db::tag::get_tag; use crate::handlers::errors::HandlerError; use crate::return_models::ReturnSchedule; use crate::types::EmgauwaUid; use crate::utils::vec_has_error; #[derive(Debug, Serialize, Deserialize)] pub struct RequestSchedule { name: String, periods: Periods, tags: Vec<String>, } #[get("/api/v1/schedules")] pub async fn index() -> impl Responder { let schedules = get_schedules(); let return_schedules: Vec<ReturnSchedule> = schedules.iter().map(ReturnSchedule::from).collect(); HttpResponse::Ok().json(return_schedules) } #[get("/api/v1/schedules/tag/{tag}")] pub async fn tagged(path: web::Path<(String,)>) -> impl Responder { let (tag,) = path.into_inner(); let tag_db = get_tag(&tag); if tag_db.is_err() { return HttpResponse::from(tag_db.unwrap_err()); } let tag_db = tag_db.unwrap(); let schedules = get_schedules_by_tag(&tag_db); let return_schedules: Vec<ReturnSchedule> = schedules.iter().map(ReturnSchedule::from).collect(); HttpResponse::Ok().json(return_schedules) } #[get("/api/v1/schedules/{schedule_id}")] pub async fn show(path: web::Path<(String,)>) -> impl Responder { let (schedule_uid,) = path.into_inner(); let emgauwa_uid = EmgauwaUid::try_from(schedule_uid.as_str()).or(Err(HandlerError::BadUid)); match emgauwa_uid { Ok(uid) => { let schedule = get_schedule_by_uid(uid); match schedule { Ok(ok) => HttpResponse::Ok().json(ReturnSchedule::from(ok)), Err(err) => HttpResponse::from(err), } } Err(err) => HttpResponse::from(err), } } #[post("/api/v1/schedules")] pub async fn add(data: web::Json<RequestSchedule>) -> impl Responder { let new_schedule = create_schedule(&data.name, &data.periods); if new_schedule.is_err() { return HttpResponse::from(new_schedule.unwrap_err()); } let new_schedule = new_schedule.unwrap(); let result = set_schedule_tags(&new_schedule, data.tags.as_slice()); if result.is_err() { return HttpResponse::from(result.unwrap_err()); } HttpResponse::Created().json(ReturnSchedule::from(new_schedule)) } #[post("/api/v1/schedules/list")] pub async fn add_list(data: web::Json<Vec<RequestSchedule>>) -> impl Responder { let result: Vec<Result<Schedule, DatabaseError>> = data .as_slice() .iter() .map(|request_schedule| { let new_schedule = create_schedule(&request_schedule.name, &request_schedule.periods)?; set_schedule_tags(&new_schedule, request_schedule.tags.as_slice())?; Ok(new_schedule) }) .collect(); match vec_has_error(&result) { true => HttpResponse::from( result .into_iter() .find(|r| r.is_err()) .unwrap() .unwrap_err(), ), false => { let return_schedules: Vec<ReturnSchedule> = result .iter() .map(|s| ReturnSchedule::from(s.as_ref().unwrap())) .collect(); HttpResponse::Created().json(return_schedules) } } } #[put("/api/v1/schedules/{schedule_id}")] pub async fn update( path: web::Path<(String,)>, data: web::Json<RequestSchedule>, ) -> impl Responder { let (schedule_uid,) = path.into_inner(); let emgauwa_uid = EmgauwaUid::try_from(schedule_uid.as_str()).or(Err(HandlerError::BadUid)); if emgauwa_uid.is_err() { return HttpResponse::from(emgauwa_uid.unwrap_err()); } let emgauwa_uid = emgauwa_uid.unwrap(); let schedule = get_schedule_by_uid(emgauwa_uid); if schedule.is_err() { return HttpResponse::from(schedule.unwrap_err()); } let schedule = schedule.unwrap(); let schedule = update_schedule(&schedule, data.name.as_str(), data.periods.borrow()); if schedule.is_err() { return HttpResponse::from(schedule.unwrap_err()); } let schedule = schedule.unwrap(); let result = set_schedule_tags(&schedule, data.tags.as_slice()); if result.is_err() { return HttpResponse::from(result.unwrap_err()); } HttpResponse::Ok().json(ReturnSchedule::from(schedule)) } #[delete("/api/v1/schedules/{schedule_id}")] pub async fn delete(path: web::Path<(String,)>) -> impl Responder { let (schedule_uid,) = path.into_inner(); let emgauwa_uid = EmgauwaUid::try_from(schedule_uid.as_str()).or(Err(HandlerError::BadUid)); match emgauwa_uid { Ok(uid) => match uid { EmgauwaUid::Off => HttpResponse::from(HandlerError::ProtectedSchedule), EmgauwaUid::On => HttpResponse::from(HandlerError::ProtectedSchedule), EmgauwaUid::Any(_) => match delete_schedule_by_uid(uid) { Ok(_) => HttpResponse::Ok().json("schedule got deleted"), Err(err) => HttpResponse::from(err), }, }, Err(err) => HttpResponse::from(err), } }