From 82c1bcf0fd4bc4224d14515584f63f5c957fab33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sat, 20 Feb 2021 18:49:29 +0100 Subject: [PATCH] add object delete button --- .../templates/objects/index.html.tera | 3 +- .../templates/objects/object_detail.html.tera | 1 + yopa-web/src/main.rs | 1 + yopa-web/src/routes/models/object.rs | 2 +- yopa-web/src/routes/objects.rs | 25 ++++++++- yopa/src/lib.rs | 56 +++++++++++++++---- 6 files changed, 73 insertions(+), 15 deletions(-) diff --git a/yopa-web/resources/templates/objects/index.html.tera b/yopa-web/resources/templates/objects/index.html.tera index 92254bd..76f3f25 100644 --- a/yopa-web/resources/templates/objects/index.html.tera +++ b/yopa-web/resources/templates/objects/index.html.tera @@ -20,7 +20,8 @@ Objects diff --git a/yopa-web/resources/templates/objects/object_detail.html.tera b/yopa-web/resources/templates/objects/object_detail.html.tera index cda230c..33df7b6 100644 --- a/yopa-web/resources/templates/objects/object_detail.html.tera +++ b/yopa-web/resources/templates/objects/object_detail.html.tera @@ -7,6 +7,7 @@ {% block nav -%} Home Edit +Delete {%- endblock %} {% block content -%} diff --git a/yopa-web/src/main.rs b/yopa-web/src/main.rs index 7d65687..1e3665d 100644 --- a/yopa-web/src/main.rs +++ b/yopa-web/src/main.rs @@ -160,6 +160,7 @@ async fn main() -> std::io::Result<()> { .service(routes::objects::detail) .service(routes::objects::update_form) .service(routes::objects::update) + .service(routes::objects::delete) // .service(static_files) .default_service(web::to(|| HttpResponse::NotFound().body("File or endpoint not found"))) diff --git a/yopa-web/src/routes/models/object.rs b/yopa-web/src/routes/models/object.rs index 30f4d9d..c1d0052 100644 --- a/yopa-web/src/routes/models/object.rs +++ b/yopa-web/src/routes/models/object.rs @@ -137,7 +137,7 @@ pub(crate) async fn delete( Err(e) => { warn!("Error deleting object model: {}", e); session.flash_error(e.to_string()); - redirect("/") // back? + redirect("/models") // back? } } } diff --git a/yopa-web/src/routes/objects.rs b/yopa-web/src/routes/objects.rs index 0b7cfa5..fa86043 100644 --- a/yopa-web/src/routes/objects.rs +++ b/yopa-web/src/routes/objects.rs @@ -436,8 +436,8 @@ pub(crate) async fn update_form( relations: relation_map }; - let _ = form.dot_remove("model_id"); - form.dot_set("object", object); + form.dot_remove("model_id").unwrap(); + form.dot_set("object", object).unwrap(); context.insert("form_data", &form); TERA.build_response("objects/object_update", &context) @@ -474,3 +474,24 @@ pub(crate) async fn update( } } } + +#[get("/object/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.delete_object(*id) { + Ok(obj) => { + debug!("Object deleted, redirecting to root"); + session.flash_success(format!("Object \"{}\" deleted.", obj.name)); + redirect("/") + } + Err(e) => { + warn!("Error deleting object: {}", e); + session.flash_error(e.to_string()); + redirect("/") // back? + } + } +} diff --git a/yopa/src/lib.rs b/yopa/src/lib.rs index 9dd1e50..3ece77d 100644 --- a/yopa/src/lib.rs +++ b/yopa/src/lib.rs @@ -2,7 +2,7 @@ #[macro_use] extern crate log; use std::borrow::Cow; -use std::collections::{HashMap, HashSet}; +use std::collections::{HashMap}; use itertools::Itertools; use serde::{Deserialize, Serialize}; @@ -18,7 +18,7 @@ use crate::model::{PropertyModel, RelationModel}; pub use data::{TypedValue}; pub use model::{DataType}; -use crate::data::{Object, Value}; +use crate::data::{Object}; use crate::update::{UpdateObj, UpsertValue}; pub mod model; @@ -138,7 +138,7 @@ impl Storage { // Ensure the default type is compatible prop.default = match prop.default.clone().cast_to(prop.data_type) { Ok(v) => v, - Err(d) => return Err(StorageError::NotExist(format!("default value {:?} has invalid type", prop.default).into())) + Err(_) => return Err(StorageError::NotExist(format!("default value {:?} has invalid type", prop.default).into())) }; debug!("Define property model \"{}\" of {}", prop.name, self.describe_model(prop.object)); @@ -155,19 +155,24 @@ impl Storage { // Remove relation templates let removed_relation_ids = map_drain_filter(&mut self.rel_models, |_k, v| v.object == id || v.related == id) .keys(); + debug!("Undefined {} relation models", removed_relation_ids.len()); // Remove related property templates let removed_prop_ids = map_drain_filter(&mut self.prop_models, |_k, v| v.object == id || removed_relation_ids.contains(&v.object)) .keys(); + debug!("Undefined {} property models", removed_prop_ids.len()); // Remove objects - let _ = map_drain_filter(&mut self.objects, |_k, v| v.model == id); + let removed_objects = map_drain_filter(&mut self.objects, |_k, v| v.model == id); + debug!("Deleted {} objects", removed_objects.len()); // Remove property values - let _ = map_drain_filter(&mut self.values, |_k, v| removed_prop_ids.contains(&v.model)); + let removed_values = map_drain_filter(&mut self.values, |_k, v| removed_prop_ids.contains(&v.model)); + debug!("Deleted {} object or relation values", removed_values.len()); // Remove relations - let _ = map_drain_filter(&mut self.relations, |_k, v| removed_relation_ids.contains(&v.model)); + let removed_relations = map_drain_filter(&mut self.relations, |_k, v| removed_relation_ids.contains(&v.model)); + debug!("Deleted {} object relations", removed_relations.len()); // Related object remain untouched, so there can be a problem with orphans. This is up to the application to deal with. @@ -183,12 +188,15 @@ impl Storage { debug!("Undefine relation model \"{}\"", t.name); // Remove relations - let _ = map_drain_filter(&mut self.relations, |_k, v| v.model == id).keys(); + let removed = map_drain_filter(&mut self.relations, |_k, v| v.model == id); + debug!("Deleted {} object relations", removed.len()); // Remove related property templates let removed_prop_tpl_ids = map_drain_filter(&mut self.prop_models, |_k, v| v.object == id).keys(); + debug!("Undefined {} relation property models", removed_prop_tpl_ids.len()); - let _ = map_drain_filter(&mut self.values, |_k, v| removed_prop_tpl_ids.contains(&v.model)); + let removed_values = map_drain_filter(&mut self.values, |_k, v| removed_prop_tpl_ids.contains(&v.model)); + debug!("Deleted {} relation values", removed_values.len()); // Related object remain untouched, so there can be a problem with orphans. This is up to the application to deal with. @@ -203,8 +211,9 @@ impl Storage { return if let Some(t) = self.prop_models.remove(&id) { debug!("Undefine property model \"{}\"", t.name); - // Remove relations - let _ = map_drain_filter(&mut self.values, |_k, v| v.model == id); + // Remove values + let removed_values = map_drain_filter(&mut self.values, |_k, v| v.model == id); + debug!("Deleted {} values", removed_values.len()); Ok(t) } else { Err(StorageError::NotExist(format!("property model {}", id).into())) @@ -337,10 +346,12 @@ impl Storage { self.objects.insert(object_id, object); + debug!("Add {} new object relations", relations_to_insert.len()); for rel in relations_to_insert { self.relations.insert(rel.id, rel); } + debug!("Add {} new values", values_to_insert.len()); for value in values_to_insert { self.values.insert(value.id, value); } @@ -561,18 +572,22 @@ impl Storage { let obj_mut = self.objects.get_mut(&updated_object_id).unwrap(); obj_mut.name = updobj.name; + debug!("Add {} new object relations", relations_to_insert.len()); for rel in relations_to_insert { self.relations.insert(rel.id, rel); } + debug!("Add {} new values", values_to_insert.len()); for value in values_to_insert { self.values.insert(value.id, value); } + debug!("Deleted {} values", value_ids_to_delete.len()); for id in value_ids_to_delete { self.values.remove(&id); } + debug!("Deleted {} object relations", relations_to_delete.len()); for id in relations_to_delete { self.relations.remove(&id); } @@ -650,10 +665,29 @@ impl Storage { // Ensure the default type is compatible prop.default = match prop.default.clone().cast_to(prop.data_type) { Ok(v) => v, - Err(d) => return Err(StorageError::NotExist(format!("default value {:?} has invalid type", prop.default).into())) + Err(_) => return Err(StorageError::NotExist(format!("default value {:?} has invalid type", prop.default).into())) }; self.prop_models.insert(prop.id, prop); Ok(()) } + + /// Delete an object and associated data + pub fn delete_object(&mut self, id: ID) -> Result { + return if let Some(t) = self.objects.remove(&id) { + debug!("Delete object \"{}\"", t.name); + // Remove relation templates + let removed_relation_ids = map_drain_filter(&mut self.relations, |_k, v| v.object == id || v.related == id) + .keys(); + debug!("Deleted {} object relations", removed_relation_ids.len()); + + // Remove values + let removed_values = map_drain_filter(&mut self.values, |_k, v| removed_relation_ids.contains(&v.object) || v.object == id); + debug!("Deleted {} object values", removed_values.len()); + + Ok(t) + } else { + Err(StorageError::NotExist(format!("object {}", id).into())) + }; + } }