use actix_session::Session; use actix_web::{Responder, web}; use serde::{Serialize, Deserialize}; use yopa::ID; use yopa::model::{PropertyModel, RelationModel}; use crate::session_ext::SessionExt; use crate::TERA; use crate::tera_ext::TeraExt; use crate::utils::{ParseOrBadReq, redirect}; #[derive(Serialize, Debug)] pub(crate) struct RelationModelDisplay<'a> { pub(crate) model: &'a RelationModel, pub(crate) related_name: &'a str, pub(crate) properties: Vec<&'a PropertyModel>, } #[get("/model/relation/create/{object_id}")] pub(crate) async fn create_form( object_id: web::Path, store: crate::YopaStoreWrapper, session: Session, ) -> actix_web::Result { let mut context = tera::Context::new(); session.render_flash(&mut context); let rg = store.read().await; debug!("ID = {}", object_id); let object = rg.get_object_model(object_id.parse_or_bad_request()?) .ok_or_else(|| actix_web::error::ErrorNotFound("No such source object"))?; let mut models: Vec<_> = rg.get_object_models().collect(); models.sort_by_key(|m| &m.name); context.insert("models", &models); context.insert("object", &object); TERA.build_response("relation_create", &context) } #[derive(Deserialize)] pub(crate) struct RelationModelCreateForm { pub object: ID, pub name: String, pub reciprocal_name: String, #[serde(default)] pub optional: bool, #[serde(default)] pub multiple: bool, pub related: ID, } #[post("/model/relation/create")] pub(crate) async fn 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_relation(RelationModel { id: Default::default(), object: form.object, name: form.name.clone(), reciprocal_name: form.reciprocal_name.clone(), optional: form.optional, multiple: form.multiple, related: form.related, }) { Ok(_id) => { debug!("Relation created, redirecting to root"); session.flash_success(format!("Relation model \"{}\" created.", form.name)); redirect("/") } Err(e) => { warn!("Error creating relation model: {:?}", e); session.flash_error(e.to_string()); redirect(format!("/model/relation/create/{}", form.object)) } } } #[derive(Serialize, Debug)] pub(crate) struct ObjectOrRelationModelDisplay { pub(crate) id: ID, pub(crate) describe: String, } #[get("/model/relation/delete/{id}")] pub(crate) async fn delete( id: web::Path, store: crate::YopaStoreWrapper, session: Session, ) -> actix_web::Result { let mut wg = store.write().await; match wg.undefine_relation(id.parse_or_bad_request()?) { 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? } } } #[derive(Serialize,Deserialize)] pub(crate) struct RelationModelEditForm { pub name: String, pub reciprocal_name: String, #[serde(default)] pub optional: bool, #[serde(default)] pub multiple: bool, } #[get("/model/relation/update/{model_id}")] pub(crate) async fn update_form( model_id: web::Path, store: crate::YopaStoreWrapper, session: Session, ) -> actix_web::Result { let mut context = tera::Context::new(); session.render_flash(&mut context); let rg = store.read().await; let model = rg.get_relation_model(*model_id) .ok_or_else(|| actix_web::error::ErrorNotFound("No such model"))?; // Re-fill old values if let Ok(Some(form)) = session.take::("old") { let mut model = model.clone(); model.name = form.name; model.optional = form.optional; // TODO try if regular bools cant be used model.multiple = form.multiple; context.insert("model", &model); } else { context.insert("model", model); } TERA.build_response("relation_update", &context) } #[post("/model/relation/update/{model_id}")] pub(crate) async fn update( model_id: web::Path, form: web::Form, store: crate::YopaStoreWrapper, session: Session, ) -> actix_web::Result { let mut wg = store.write().await; let form = form.into_inner(); let id = model_id.into_inner(); match wg.update_relation(RelationModel { id, object: Default::default(), // dummy name: form.name.clone(), reciprocal_name: form.reciprocal_name.to_string(), optional: form.optional, multiple: form.multiple, related: Default::default() // dummy }) { Ok(_id) => { debug!("Relation updated, redirecting to root"); session.flash_success(format!("Relation model \"{}\" updated.", form.name)); redirect("/") } Err(e) => { warn!("Error updating model: {:?}", e); session.flash_error(e.to_string()); session.set("old", form); redirect(format!("/model/relation/update/{}", id)) } } }