wip edit form data
This commit is contained in:
@@ -157,6 +157,7 @@ async fn main() -> std::io::Result<()> {
|
||||
.service(routes::objects::create_form)
|
||||
.service(routes::objects::create)
|
||||
.service(routes::objects::detail)
|
||||
.service(routes::objects::update_form)
|
||||
//
|
||||
.service(static_files)
|
||||
.default_service(web::to(|| HttpResponse::NotFound().body("File or endpoint not found")))
|
||||
|
||||
+136
-10
@@ -4,7 +4,7 @@ use crate::session_ext::SessionExt;
|
||||
use crate::routes::models::object::ObjectModelForm;
|
||||
use crate::TERA;
|
||||
use crate::tera_ext::TeraExt;
|
||||
use yopa::{ID, model};
|
||||
use yopa::{ID, model, Storage, data};
|
||||
use yopa::data::Object;
|
||||
use serde::{Serialize,Deserialize};
|
||||
use yopa::insert::InsertObj;
|
||||
@@ -14,6 +14,8 @@ use serde_json::Value;
|
||||
use itertools::Itertools;
|
||||
use yopa::model::{ObjectModel, PropertyModel, RelationModel};
|
||||
use heck::TitleCase;
|
||||
use std::collections::HashMap;
|
||||
use json_dotpath::DotPaths;
|
||||
|
||||
// we only need references here, Context serializes everything to Value.
|
||||
// cloning would be a waste of cycles
|
||||
@@ -48,6 +50,17 @@ pub(crate) async fn create_form(
|
||||
|
||||
context.insert("model", model);
|
||||
|
||||
let form_data = prepare_object_create_data(&rg, model.id)?;
|
||||
|
||||
context.insert("form_data", &form_data);
|
||||
|
||||
TERA.build_response("objects/object_create", &context)
|
||||
}
|
||||
|
||||
fn prepare_object_create_data(rg : &Storage, model_id : ID) -> actix_web::Result<ObjectCreateData> {
|
||||
let model = rg.get_object_model(model_id)
|
||||
.ok_or_else(|| actix_web::error::ErrorNotFound("No such model"))?;
|
||||
|
||||
let relations : Vec<_> = rg.get_relation_models_for_object_model(model.id).collect();
|
||||
|
||||
let mut prop_object_ids : Vec<ID> = relations.iter().map(|r| r.id).collect();
|
||||
@@ -61,19 +74,15 @@ pub(crate) async fn create_form(
|
||||
related_ids.sort();
|
||||
related_ids.dedup();
|
||||
|
||||
let form_data = ObjectCreateData {
|
||||
Ok(ObjectCreateData {
|
||||
model_id: model.id,
|
||||
schema: Schema {
|
||||
obj_models: rg.get_object_models().collect(), // TODO get only the ones that matter here
|
||||
rel_models: relations,
|
||||
prop_models: rg.get_property_models_for_parents(&prop_object_ids).collect()
|
||||
prop_models: rg.get_property_models_for_parents(prop_object_ids).collect()
|
||||
},
|
||||
objects: rg.get_objects_of_type(&related_ids).collect()
|
||||
};
|
||||
|
||||
context.insert("form_data", &form_data);
|
||||
|
||||
TERA.build_response("objects/object_create", &context)
|
||||
objects: rg.get_objects_of_type(related_ids).collect()
|
||||
})
|
||||
}
|
||||
|
||||
#[post("/object/create")]
|
||||
@@ -189,7 +198,7 @@ pub(crate) async fn detail(
|
||||
let mut ids_to_get_values_for = relations.iter().map(|r| r.id).collect_vec();
|
||||
ids_to_get_values_for.push(object_id);
|
||||
let mut grouped_values = {
|
||||
rg.get_grouped_values_for_objects(&ids_to_get_values_for)
|
||||
rg.get_grouped_values_for_objects(ids_to_get_values_for)
|
||||
};
|
||||
|
||||
// object's own properties
|
||||
@@ -252,3 +261,120 @@ pub(crate) async fn detail(
|
||||
|
||||
TERA.build_response("objects/object_detail", &context)
|
||||
}
|
||||
|
||||
#[derive(Serialize,Debug,Clone)]
|
||||
struct EnrichedObject<'a> {
|
||||
id: ID,
|
||||
model: ID,
|
||||
name: String,
|
||||
values: HashMap<String /* ID but as string so serde will stop exploding */, Vec<&'a data::Value>>,
|
||||
relations: HashMap<String /* ID */, Vec<EnrichedRelation<'a>>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize,Debug,Clone)]
|
||||
struct EnrichedRelation<'a> {
|
||||
id: ID,
|
||||
object: ID,
|
||||
model: ID,
|
||||
related: ID,
|
||||
values: HashMap<String /* ID */, Vec<&'a data::Value>>,
|
||||
}
|
||||
|
||||
// FIXME relation values are now showing in the edit form!
|
||||
// TODO save handling
|
||||
|
||||
#[get("/object/update/{id}")]
|
||||
pub(crate) async fn update_form(
|
||||
id: web::Path<ID>,
|
||||
store: crate::YopaStoreWrapper,
|
||||
session: Session
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let mut context = tera::Context::new();
|
||||
session.render_flash(&mut context);
|
||||
|
||||
let rg = store.read().await;
|
||||
|
||||
let object = rg.get_object(*id)
|
||||
.ok_or_else(|| actix_web::error::ErrorNotFound("No such object"))?;
|
||||
|
||||
let model = rg.get_object_model(object.model)
|
||||
.ok_or_else(|| actix_web::error::ErrorNotFound("Object has no model"))?;
|
||||
|
||||
// maybe its useful,idk
|
||||
context.insert("model", &model);
|
||||
context.insert("object", &object);
|
||||
|
||||
let create_data = prepare_object_create_data(&rg, model.id)?;
|
||||
|
||||
let mut value_map = HashMap::new();
|
||||
let mut relation_map = HashMap::new();
|
||||
|
||||
// Some properties may have no values, so we first check what IDs to expect
|
||||
let prop_ids = create_data.schema.prop_models.iter()
|
||||
.filter(|p| p.object == model.id).map(|p| p.id).collect_vec();
|
||||
|
||||
let mut values_grouped = rg.get_values_for_object(*id)
|
||||
.into_group_map_by(|v| v.model);
|
||||
|
||||
prop_ids.into_iter().for_each(|id| {
|
||||
value_map.insert(id.to_string(), values_grouped.remove(&id).unwrap_or_default());
|
||||
});
|
||||
|
||||
{
|
||||
// Some properties may have no values, so we first check what IDs to expect
|
||||
let rel_ids = create_data.schema.rel_models.iter()
|
||||
.filter(|p| p.object == model.id).map(|p| p.id).collect_vec();
|
||||
|
||||
let relations = rg.get_relations_for_object(*id).collect_vec();
|
||||
let grouped_relations = relations.iter()
|
||||
.into_group_map_by(|relation| relation.model);
|
||||
|
||||
let mut relation_properties = rg.get_grouped_prop_models_for_parents(rel_ids.clone());
|
||||
|
||||
let mut relation_values = rg.get_grouped_values_for_objects(rel_ids.clone());
|
||||
|
||||
for (rel_model_id, relations) in grouped_relations {
|
||||
let mut instances = vec![];
|
||||
let props_for_rel = relation_properties.remove(&rel_model_id).unwrap_or_default();
|
||||
|
||||
for rel in relations {
|
||||
let mut relation_values_map = HashMap::new();
|
||||
|
||||
// values keyed by model
|
||||
let mut rel_values = relation_values.remove(&rel.id).unwrap_or_default().into_iter()
|
||||
.into_group_map_by(|relation| relation.model);
|
||||
|
||||
props_for_rel.iter().for_each(|prop_model| {
|
||||
relation_values_map.insert(prop_model.id.to_string(), rel_values.remove(&prop_model.id).unwrap_or_default());
|
||||
});
|
||||
|
||||
let enriched = EnrichedRelation {
|
||||
id: rel.id,
|
||||
object: rel.object,
|
||||
model: rel.model,
|
||||
related: rel.related,
|
||||
values: relation_values_map
|
||||
};
|
||||
|
||||
instances.push(enriched);
|
||||
}
|
||||
|
||||
relation_map.insert(rel_model_id.to_string(), instances);
|
||||
}
|
||||
}
|
||||
|
||||
let mut form = serde_json::to_value(create_data)?;
|
||||
|
||||
let object = EnrichedObject {
|
||||
id: object.id ,
|
||||
model: object.model,
|
||||
name: object.name.clone(),
|
||||
values: value_map,
|
||||
relations: relation_map
|
||||
};
|
||||
|
||||
form.dot_set("object", object);
|
||||
context.insert("form_data", &form);
|
||||
|
||||
TERA.build_response("objects/object_update", &context)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user