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()))
+ };
+ }
}