add object delete button

master
Ondřej Hruška 4 years ago
parent 58c44afa30
commit 82c1bcf0fd
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 3
      yopa-web/resources/templates/objects/index.html.tera
  2. 1
      yopa-web/resources/templates/objects/object_detail.html.tera
  3. 1
      yopa-web/src/main.rs
  4. 2
      yopa-web/src/routes/models/object.rs
  5. 25
      yopa-web/src/routes/objects.rs
  6. 56
      yopa/src/lib.rs

@ -20,7 +20,8 @@ Objects
<ul> <ul>
{% for object in table.objects %} {% for object in table.objects %}
<li><a href="/object/detail/{{object.id}}">{{object.name}}</a> (<a href="/object/update/{{object.id}}">Edit</a>) <li><a href="/object/detail/{{object.id}}">{{object.name}}</a> (<a href="/object/update/{{object.id}}">Edit</a>,
<a href="/object/delete/{{object.id}}" onclick="return confirm('Delete object?')">Delete</a>)
{% endfor %} {% endfor %}
</ul> </ul>

@ -7,6 +7,7 @@
{% block nav -%} {% block nav -%}
<a href="/">Home</a> <a href="/">Home</a>
<a href="/object/update/{{object.id}}">Edit</a> <a href="/object/update/{{object.id}}">Edit</a>
<a href="/object/delete/{{object.id}}" onclick="return confirm('Delete object?')">Delete</a>
{%- endblock %} {%- endblock %}
{% block content -%} {% block content -%}

@ -160,6 +160,7 @@ async fn main() -> std::io::Result<()> {
.service(routes::objects::detail) .service(routes::objects::detail)
.service(routes::objects::update_form) .service(routes::objects::update_form)
.service(routes::objects::update) .service(routes::objects::update)
.service(routes::objects::delete)
// //
.service(static_files) .service(static_files)
.default_service(web::to(|| HttpResponse::NotFound().body("File or endpoint not found"))) .default_service(web::to(|| HttpResponse::NotFound().body("File or endpoint not found")))

@ -137,7 +137,7 @@ pub(crate) async fn delete(
Err(e) => { Err(e) => {
warn!("Error deleting object model: {}", e); warn!("Error deleting object model: {}", e);
session.flash_error(e.to_string()); session.flash_error(e.to_string());
redirect("/") // back? redirect("/models") // back?
} }
} }
} }

@ -436,8 +436,8 @@ pub(crate) async fn update_form(
relations: relation_map relations: relation_map
}; };
let _ = form.dot_remove("model_id"); form.dot_remove("model_id").unwrap();
form.dot_set("object", object); form.dot_set("object", object).unwrap();
context.insert("form_data", &form); context.insert("form_data", &form);
TERA.build_response("objects/object_update", &context) 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<ID>,
store: crate::YopaStoreWrapper,
session: Session,
) -> actix_web::Result<impl Responder> {
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?
}
}
}

@ -2,7 +2,7 @@
#[macro_use] extern crate log; #[macro_use] extern crate log;
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap};
use itertools::Itertools; use itertools::Itertools;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -18,7 +18,7 @@ use crate::model::{PropertyModel, RelationModel};
pub use data::{TypedValue}; pub use data::{TypedValue};
pub use model::{DataType}; pub use model::{DataType};
use crate::data::{Object, Value}; use crate::data::{Object};
use crate::update::{UpdateObj, UpsertValue}; use crate::update::{UpdateObj, UpsertValue};
pub mod model; pub mod model;
@ -138,7 +138,7 @@ impl Storage {
// Ensure the default type is compatible // Ensure the default type is compatible
prop.default = match prop.default.clone().cast_to(prop.data_type) { prop.default = match prop.default.clone().cast_to(prop.data_type) {
Ok(v) => v, 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)); debug!("Define property model \"{}\" of {}", prop.name, self.describe_model(prop.object));
@ -155,19 +155,24 @@ impl Storage {
// Remove relation templates // Remove relation templates
let removed_relation_ids = map_drain_filter(&mut self.rel_models, |_k, v| v.object == id || v.related == id) let removed_relation_ids = map_drain_filter(&mut self.rel_models, |_k, v| v.object == id || v.related == id)
.keys(); .keys();
debug!("Undefined {} relation models", removed_relation_ids.len());
// Remove related property templates // 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)) let removed_prop_ids = map_drain_filter(&mut self.prop_models, |_k, v| v.object == id || removed_relation_ids.contains(&v.object))
.keys(); .keys();
debug!("Undefined {} property models", removed_prop_ids.len());
// Remove objects // 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 // 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 // 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. // 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); debug!("Undefine relation model \"{}\"", t.name);
// Remove relations // 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 // Remove related property templates
let removed_prop_tpl_ids = map_drain_filter(&mut self.prop_models, |_k, v| v.object == id).keys(); 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. // 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) { return if let Some(t) = self.prop_models.remove(&id) {
debug!("Undefine property model \"{}\"", t.name); debug!("Undefine property model \"{}\"", t.name);
// Remove relations // Remove values
let _ = map_drain_filter(&mut self.values, |_k, v| v.model == id); let removed_values = map_drain_filter(&mut self.values, |_k, v| v.model == id);
debug!("Deleted {} values", removed_values.len());
Ok(t) Ok(t)
} else { } else {
Err(StorageError::NotExist(format!("property model {}", id).into())) Err(StorageError::NotExist(format!("property model {}", id).into()))
@ -337,10 +346,12 @@ impl Storage {
self.objects.insert(object_id, object); self.objects.insert(object_id, object);
debug!("Add {} new object relations", relations_to_insert.len());
for rel in relations_to_insert { for rel in relations_to_insert {
self.relations.insert(rel.id, rel); self.relations.insert(rel.id, rel);
} }
debug!("Add {} new values", values_to_insert.len());
for value in values_to_insert { for value in values_to_insert {
self.values.insert(value.id, value); self.values.insert(value.id, value);
} }
@ -561,18 +572,22 @@ impl Storage {
let obj_mut = self.objects.get_mut(&updated_object_id).unwrap(); let obj_mut = self.objects.get_mut(&updated_object_id).unwrap();
obj_mut.name = updobj.name; obj_mut.name = updobj.name;
debug!("Add {} new object relations", relations_to_insert.len());
for rel in relations_to_insert { for rel in relations_to_insert {
self.relations.insert(rel.id, rel); self.relations.insert(rel.id, rel);
} }
debug!("Add {} new values", values_to_insert.len());
for value in values_to_insert { for value in values_to_insert {
self.values.insert(value.id, value); self.values.insert(value.id, value);
} }
debug!("Deleted {} values", value_ids_to_delete.len());
for id in value_ids_to_delete { for id in value_ids_to_delete {
self.values.remove(&id); self.values.remove(&id);
} }
debug!("Deleted {} object relations", relations_to_delete.len());
for id in relations_to_delete { for id in relations_to_delete {
self.relations.remove(&id); self.relations.remove(&id);
} }
@ -650,10 +665,29 @@ impl Storage {
// Ensure the default type is compatible // Ensure the default type is compatible
prop.default = match prop.default.clone().cast_to(prop.data_type) { prop.default = match prop.default.clone().cast_to(prop.data_type) {
Ok(v) => v, 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); self.prop_models.insert(prop.id, prop);
Ok(()) Ok(())
} }
/// Delete an object and associated data
pub fn delete_object(&mut self, id: ID) -> Result<data::Object, StorageError> {
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()))
};
}
} }

Loading…
Cancel
Save