edit form save almost working

This commit is contained in:
2021-02-20 18:11:03 +01:00
parent 6561da7e99
commit bc8b04f331
17 changed files with 469 additions and 81 deletions
+8 -7
View File
@@ -159,6 +159,7 @@ async fn main() -> std::io::Result<()> {
.service(routes::objects::create)
.service(routes::objects::detail)
.service(routes::objects::update_form)
.service(routes::objects::update)
//
.service(static_files)
.default_service(web::to(|| HttpResponse::NotFound().body("File or endpoint not found")))
@@ -241,35 +242,35 @@ fn init_yopa() -> YopaStoreWrapper {
}).unwrap();
let book1 = store.insert_object(InsertObj {
model_id: id_book,
model: id_book,
name: "Book 1".to_string(),
values: vec![],
relations: vec![]
}).unwrap();
store.insert_object(InsertObj {
model_id: id_book,
model: id_book,
name: "Book 2".to_string(),
values: vec![],
relations: vec![]
}).unwrap();
store.insert_object(InsertObj {
model_id: id_recipe,
model: id_recipe,
name: "Recipe1".to_string(),
values: vec![
InsertValue {
model_id: val_descr,
model: val_descr,
value: TypedValue::String("Bla bla bla".into())
}
],
relations: vec![
InsertRel {
model_id: rel_book_id,
related_id: book1,
model: rel_book_id,
related: book1,
values: vec![
InsertValue {
model_id: page,
model: page,
value: TypedValue::Integer(15)
}
]
+1 -1
View File
@@ -102,7 +102,7 @@ pub(crate) async fn update(
let form = form.into_inner();
let id = model_id.into_inner();
match wg.update_object(ObjectModel {
match wg.update_object_model(ObjectModel {
id,
name: form.name.clone(),
}) {
+1 -1
View File
@@ -244,7 +244,7 @@ pub(crate) async fn update(
}
};
match wg.update_property(PropertyModel {
match wg.update_property_model(PropertyModel {
id,
object: Default::default(), // dummy
name: form.name.clone(),
+1 -1
View File
@@ -174,7 +174,7 @@ pub(crate) async fn update(
let form = form.into_inner();
let id = model_id.into_inner();
match wg.update_relation(RelationModel {
match wg.update_relation_model(RelationModel {
id,
object: Default::default(), // dummy
name: form.name.clone(),
+103 -11
View File
@@ -4,10 +4,10 @@ use crate::session_ext::SessionExt;
use crate::routes::models::object::ObjectModelForm;
use crate::TERA;
use crate::tera_ext::TeraExt;
use yopa::{ID, model, Storage, data};
use yopa::{ID, model, Storage, data, TypedValue};
use yopa::data::Object;
use serde::{Serialize,Deserialize};
use yopa::insert::InsertObj;
use yopa::insert::{InsertObj, InsertValue};
use crate::utils::redirect;
use actix_web::web::Json;
use serde_json::Value;
@@ -16,6 +16,7 @@ use yopa::model::{ObjectModel, PropertyModel, RelationModel};
use heck::TitleCase;
use std::collections::HashMap;
use json_dotpath::DotPaths;
use yopa::update::UpdateObj;
// we only need references here, Context serializes everything to Value.
// cloning would be a waste of cycles
@@ -102,7 +103,7 @@ pub(crate) async fn create(
let form = form.into_inner();
let name = form.name.clone();
let model_name = wg.get_model_name(form.model_id).to_owned().to_title_case();
let model_name = wg.get_model_name(form.model).to_owned().to_title_case();
match wg.insert_object(form) {
Ok(_id) => {
@@ -174,11 +175,13 @@ struct RelationInstanceView<'a> {
#[get("/object/detail/{id}")]
pub(crate) async fn detail(
id: web::Path<ID>,
store: crate::YopaStoreWrapper
store: crate::YopaStoreWrapper,
session: Session
) -> actix_web::Result<impl Responder> {
let object_id = *id;
let mut context = tera::Context::new();
session.render_flash(&mut context);
let rg = store.read().await;
@@ -192,14 +195,15 @@ pub(crate) async fn detail(
context.insert("model", model);
context.insert("kind", &rg.get_model_name(object.model));
let relations = rg.get_relations_for_object(object_id).collect_vec();
let mut relations = rg.get_relations_for_object(object_id).collect_vec();
let reci_relations = rg.get_reciprocal_relations_for_object(object_id).collect_vec();
// values by parent ID
let mut ids_to_get_values_for = relations.iter().map(|r| r.id).collect_vec();
ids_to_get_values_for.extend(reci_relations.iter().map(|r| r.id));
ids_to_get_values_for.push(object_id);
let mut grouped_values = {
rg.get_grouped_values_for_objects(ids_to_get_values_for)
};
let mut grouped_values = rg.get_grouped_values_for_objects(ids_to_get_values_for);
// object's own properties
{
@@ -214,6 +218,9 @@ pub(crate) async fn detail(
values
})
}
view_object_properties.sort_by_key(|p| &p.model.name);
context.insert("properties", &view_object_properties);
}
@@ -244,21 +251,77 @@ pub(crate) async fn detail(
})
}
view_rel_properties.sort_by_key(|p| &p.model.name);
instances.push(RelationInstanceView {
related: related_obj,
properties: view_rel_properties
})
}
instances.sort_by_key(|r| &r.related.name);
relation_views.push(RelationView {
model: rg.get_relation_model(model_id).unwrap(),
related_name: rg.get_model_name(model_id),
instances
})
}
relation_views.sort_by_key(|r| &r.model.name);
context.insert("relations", &relation_views);
}
// near-copypasta for reciprocal
{
let grouped_relations = reci_relations.iter()
.into_group_map_by(|relation| relation.model);
let mut relation_views = vec![];
for (model_id, relations) in grouped_relations {
let mut instances = vec![];
for rel in relations {
let related_obj = match rg.get_object(rel.object) {
None => continue,
Some(obj) => obj
};
let mut rel_values_by_model = grouped_values
.remove(&rel.id).unwrap_or_default().into_iter()
.into_group_map_by(|value| value.model);
let mut view_rel_properties = vec![];
for (prop_model_id, values) in rel_values_by_model {
view_rel_properties.push(PropertyView {
model: rg.get_property_model(prop_model_id).unwrap(),
values
})
}
view_rel_properties.sort_by_key(|p| &p.model.name);
instances.push(RelationInstanceView {
related: related_obj,
properties: view_rel_properties
})
}
instances.sort_by_key(|r| &r.related.name);
relation_views.push(RelationView {
model: rg.get_relation_model(model_id).unwrap(),
related_name: rg.get_model_name(model_id),
instances
})
}
relation_views.sort_by_key(|r| &r.model.reciprocal_name);
context.insert("reciprocal_relations", &relation_views);
}
TERA.build_response("objects/object_detail", &context)
}
@@ -280,9 +343,6 @@ struct EnrichedRelation<'a> {
values: HashMap<String /* ID */, Vec<&'a data::Value>>,
}
// FIXME relation values are not showing in the edit form!
// TODO save handling
#[get("/object/update/{id}")]
pub(crate) async fn update_form(
id: web::Path<ID>,
@@ -382,3 +442,35 @@ pub(crate) async fn update_form(
TERA.build_response("objects/object_update", &context)
}
#[post("/object/update/{id}")]
pub(crate) async fn update(
id: web::Path<ID>,
form: web::Json<UpdateObj>,
store: crate::YopaStoreWrapper,
session: Session,
) -> actix_web::Result<HttpResponse> {
warn!("{:?}", form);
let mut wg = store.write().await;
let form = form.into_inner();
let name = form.name.clone();
let object = wg.get_object(form.id)
.ok_or_else(|| actix_web::error::ErrorNotFound("No such object"))?;
let model_name = wg.get_model_name(object.model).to_owned().to_title_case();
match wg.update_object(form) {
Ok(_id) => {
debug!("Object created, redirecting to root");
session.flash_success(format!("{} \"{}\" updated.", model_name, name));
Ok(HttpResponse::Ok().finish())
}
Err(e) => {
warn!("Error updating model: {}", e);
Ok(HttpResponse::BadRequest().body(e.to_string()))
}
}
}