use actix_web::{web, HttpRequest, Responder, HttpResponse}; use crate::TERA; use crate::tera_ext::TeraExt; use yopa::{Storage, StorageError}; use serde::{Deserialize, Serialize}; use yopa::model::{PropertyModel, RelationModel, ObjectModel}; use std::ops::DerefMut; use actix_session::Session; use crate::session_ext::SessionExt; #[derive(Serialize, Debug)] struct ObjectModelDisplay<'a> { id : yopa::ID, name : &'a str, properties: Vec<&'a PropertyModel>, relations: Vec>, } #[derive(Serialize, Debug)] struct RelationModelDisplay<'a> { model : &'a RelationModel, related_name : &'a str, properties: Vec<&'a PropertyModel>, } fn redirect(path : impl AsRef) -> actix_web::Result { Ok(HttpResponse::SeeOther() .header("location", path.as_ref()) // back - to where? .finish()) } #[get("/")] pub(crate) async fn index(session : Session, store : crate::YopaStoreWrapper) -> actix_web::Result { let rg = store.read().await; let models_iter = rg.get_object_models(); // object and relation props let mut model_props = rg.get_grouped_prop_models(); let mut model_relations = rg.get_grouped_relation_models(); let mut models = vec![]; for om in models_iter { let mut oprops = model_props.remove(&om.id).unwrap_or_default(); let mut relations = model_relations.remove(&om.id).unwrap_or_default(); let rel_displays = relations.into_iter().map(|rm| { let mut rprops = model_props.remove(&rm.id).unwrap_or_default(); rprops.sort_by_key(|m| &m.name); RelationModelDisplay { model: rm, related_name: rg.get_model_name(rm.related), properties: rprops } }).collect::>(); oprops.sort_by_key(|m| &m.name); models.push(ObjectModelDisplay { id: om.id, name: &om.name, properties: oprops, relations: rel_displays, }) } models.sort_by_key(|m| m.name); let mut ctx = tera::Context::new(); ctx.insert("models", &models); session.render_flash(&mut ctx); TERA.build_response("index", &ctx) } #[get("/model/object/create")] pub(crate) async fn object_model_create_form(session : Session) -> actix_web::Result { let mut context = tera::Context::new(); session.render_flash(&mut context); TERA.build_response("model_create", &context) } #[derive(Deserialize)] pub(crate) struct ObjectModelCreate { pub name : String, } #[post("/model/object/create")] pub(crate) async fn object_model_create( form : web::Form, store : crate::YopaStoreWrapper, session : Session ) -> actix_web::Result { let mut wg = store.write().await; let form = form.into_inner(); match wg.define_object(ObjectModel { id: Default::default(), name: form.name.clone() }) { Ok(_id) => { debug!("Object created, redirecting to root"); session.flash_success(format!("Object model \"{}\" created.", form.name)); redirect("/") } Err(e) => { warn!("Error creating model: {:?}", e); session.flash_error(e.to_string()); redirect("/model/object/create") } } } #[get("/model/object/delete/{id}")] pub(crate) async fn object_model_delete( id : web::Path, store : crate::YopaStoreWrapper, session : Session ) -> actix_web::Result { let mut wg = store.write().await; match wg.undefine_object(id.parse().map_err(|e| actix_web::error::ErrorBadRequest(e))?) { Ok(om) => { debug!("Object model deleted, redirecting to root"); session.flash_success(format!("Object model \"{}\" deleted.", om.name)); redirect("/") } Err(e) => { warn!("Error deleting object model: {:?}", e); session.flash_error(e.to_string()); redirect("/") // back? } } } #[get("/model/relation/delete/{id}")] pub(crate) async fn relation_model_delete( id : web::Path, store : crate::YopaStoreWrapper, session : Session ) -> actix_web::Result { let mut wg = store.write().await; match wg.undefine_relation(id.parse().map_err(|e| actix_web::error::ErrorBadRequest(e))?) { Ok(rm) => { debug!("Relation deleted, redirecting to root"); session.flash_success(format!("Relation model \"{}\" deleted.", rm.name)); redirect("/") } Err(e) => { warn!("Error deleting relation model: {:?}", e); session.flash_error(e.to_string()); redirect("/") // back? } } } #[get("/model/property/delete/{id}")] pub(crate) async fn property_model_delete( id : web::Path, store : crate::YopaStoreWrapper, session : Session ) -> actix_web::Result { let mut wg = store.write().await; match wg.undefine_property(id.parse().map_err(|e| actix_web::error::ErrorBadRequest(e))?) { Ok(rm) => { debug!("Property deleted, redirecting to root"); session.flash_success(format!("Property \"{}\" deleted.", rm.name)); redirect("/") } Err(e) => { warn!("Error deleting property: {:?}", e); session.flash_error(e.to_string()); redirect("/") // back? } } }