|
|
@ -1,5 +1,4 @@ |
|
|
|
use std::borrow::Cow; |
|
|
|
use std::borrow::Cow; |
|
|
|
use std::collections::HashMap; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use actix_session::Session; |
|
|
|
use actix_session::Session; |
|
|
|
use actix_web::{web, HttpResponse, Responder}; |
|
|
|
use actix_web::{web, HttpResponse, Responder}; |
|
|
@ -7,6 +6,7 @@ use heck::TitleCase; |
|
|
|
use itertools::Itertools; |
|
|
|
use itertools::Itertools; |
|
|
|
use json_dotpath::DotPaths; |
|
|
|
use json_dotpath::DotPaths; |
|
|
|
use serde::Serialize; |
|
|
|
use serde::Serialize; |
|
|
|
|
|
|
|
use indexmap::IndexMap; |
|
|
|
|
|
|
|
|
|
|
|
use yopa::{data, model, Storage, ID}; |
|
|
|
use yopa::{data, model, Storage, ID}; |
|
|
|
|
|
|
|
|
|
|
@ -37,11 +37,18 @@ pub struct ObjectDisplay<'a> { |
|
|
|
pub name: Cow<'a, str>, |
|
|
|
pub name: Cow<'a, str>, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Serialize)] |
|
|
|
|
|
|
|
pub struct ObjectCreate<'a> { |
|
|
|
|
|
|
|
pub id: ID, |
|
|
|
|
|
|
|
pub model: ID, |
|
|
|
|
|
|
|
pub name: Cow<'a, str>, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Debug, Clone)] |
|
|
|
#[derive(Serialize, Debug, Clone)] |
|
|
|
pub struct ObjectCreateData<'a> { |
|
|
|
pub struct ObjectCreateData<'a> { |
|
|
|
pub model_id: ID, |
|
|
|
pub model_id: ID, |
|
|
|
pub schema: Schema<'a>, |
|
|
|
pub schema: Schema<'a>, |
|
|
|
pub objects: Vec<ObjectDisplay<'a>>, |
|
|
|
pub objects: Vec<ObjectCreate<'a>>, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[get("/object/create/{model_id}")] |
|
|
|
#[get("/object/create/{model_id}")] |
|
|
@ -96,11 +103,12 @@ fn prepare_object_create_data(rg: &Storage, model_id: ID) -> actix_web::Result<O |
|
|
|
rel_models: relations, |
|
|
|
rel_models: relations, |
|
|
|
prop_models: rg |
|
|
|
prop_models: rg |
|
|
|
.get_property_models_for_parents(prop_object_ids) |
|
|
|
.get_property_models_for_parents(prop_object_ids) |
|
|
|
|
|
|
|
.sorted_by(PropertyModel::order_refs) |
|
|
|
.collect(), |
|
|
|
.collect(), |
|
|
|
}, |
|
|
|
}, |
|
|
|
objects: rg |
|
|
|
objects: rg |
|
|
|
.get_objects_of_types(related_ids) |
|
|
|
.get_objects_of_types(related_ids) |
|
|
|
.map(|o| ObjectDisplay { |
|
|
|
.map(|o| ObjectCreate { |
|
|
|
id: o.id, |
|
|
|
id: o.id, |
|
|
|
model: o.model, |
|
|
|
model: o.model, |
|
|
|
name: rg.get_object_name(o), |
|
|
|
name: rg.get_object_name(o), |
|
|
@ -115,8 +123,6 @@ pub(crate) async fn create( |
|
|
|
store: crate::YopaStoreWrapper, |
|
|
|
store: crate::YopaStoreWrapper, |
|
|
|
session: Session, |
|
|
|
session: Session, |
|
|
|
) -> actix_web::Result<impl Responder> { |
|
|
|
) -> actix_web::Result<impl Responder> { |
|
|
|
warn!("{:?}", form); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut wg = store.write().await; |
|
|
|
let mut wg = store.write().await; |
|
|
|
let form = form.into_inner(); |
|
|
|
let form = form.into_inner(); |
|
|
|
|
|
|
|
|
|
|
@ -161,7 +167,7 @@ pub(crate) async fn list_inner( |
|
|
|
|
|
|
|
|
|
|
|
let models: Vec<_> = rg |
|
|
|
let models: Vec<_> = rg |
|
|
|
.get_object_models() |
|
|
|
.get_object_models() |
|
|
|
.sorted_by_key(|m| &m.name) |
|
|
|
.sorted_by(ObjectModel::order_refs) |
|
|
|
.map(|model| { |
|
|
|
.map(|model| { |
|
|
|
let objects = objects_by_model.remove(&model.id).unwrap_or_default(); |
|
|
|
let objects = objects_by_model.remove(&model.id).unwrap_or_default(); |
|
|
|
let mut objects = objects |
|
|
|
let mut objects = objects |
|
|
@ -239,7 +245,9 @@ pub(crate) async fn detail( |
|
|
|
context.insert("model", model); |
|
|
|
context.insert("model", model); |
|
|
|
context.insert("kind", &rg.get_model_name(object.model)); |
|
|
|
context.insert("kind", &rg.get_model_name(object.model)); |
|
|
|
|
|
|
|
|
|
|
|
let relations = rg.get_relations_for_object(object_id).collect_vec(); |
|
|
|
let relations = rg |
|
|
|
|
|
|
|
.get_relations_for_object(object_id) |
|
|
|
|
|
|
|
.collect_vec(); |
|
|
|
let reci_relations = rg |
|
|
|
let reci_relations = rg |
|
|
|
.get_reciprocal_relations_for_object(object_id) |
|
|
|
.get_reciprocal_relations_for_object(object_id) |
|
|
|
.collect_vec(); |
|
|
|
.collect_vec(); |
|
|
@ -266,7 +274,7 @@ pub(crate) async fn detail( |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
view_object_properties.sort_by_key(|p| &p.model.name); |
|
|
|
view_object_properties.sort_by(|a, b| PropertyModel::order(a.model, b.model)); |
|
|
|
|
|
|
|
|
|
|
|
context.insert("properties", &view_object_properties); |
|
|
|
context.insert("properties", &view_object_properties); |
|
|
|
} |
|
|
|
} |
|
|
@ -300,7 +308,7 @@ pub(crate) async fn detail( |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
view_rel_properties.sort_by_key(|p| &p.model.name); |
|
|
|
view_rel_properties.sort_by(|a, b| PropertyModel::order(a.model, b.model)); |
|
|
|
|
|
|
|
|
|
|
|
let related_name = rg.get_object_name(related_obj); |
|
|
|
let related_name = rg.get_object_name(related_obj); |
|
|
|
|
|
|
|
|
|
|
@ -324,7 +332,7 @@ pub(crate) async fn detail( |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
relation_views.sort_by_key(|r| &r.model.name); |
|
|
|
relation_views.sort_by(|a, b| RelationModel::order_refs(&a.model, &b.model)); |
|
|
|
|
|
|
|
|
|
|
|
context.insert("relations", &relation_views); |
|
|
|
context.insert("relations", &relation_views); |
|
|
|
} |
|
|
|
} |
|
|
@ -358,7 +366,7 @@ pub(crate) async fn detail( |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
view_rel_properties.sort_by_key(|p| &p.model.name); |
|
|
|
view_rel_properties.sort_by(|a, b| PropertyModel::order(a.model, b.model)); |
|
|
|
|
|
|
|
|
|
|
|
let related_name = rg.get_object_name(related_obj); |
|
|
|
let related_name = rg.get_object_name(related_obj); |
|
|
|
|
|
|
|
|
|
|
@ -383,7 +391,7 @@ pub(crate) async fn detail( |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
relation_views.sort_by_key(|r| &r.model.reciprocal_name); |
|
|
|
relation_views.sort_by(|a, b| RelationModel::reciprocal_order_refs(&a.model, &b.model)); |
|
|
|
|
|
|
|
|
|
|
|
context.insert("reciprocal_relations", &relation_views); |
|
|
|
context.insert("reciprocal_relations", &relation_views); |
|
|
|
} |
|
|
|
} |
|
|
@ -396,11 +404,11 @@ struct EnrichedObject<'a> { |
|
|
|
id: ID, |
|
|
|
id: ID, |
|
|
|
model: ID, |
|
|
|
model: ID, |
|
|
|
name: Cow<'a, str>, |
|
|
|
name: Cow<'a, str>, |
|
|
|
values: HashMap< |
|
|
|
values: IndexMap< |
|
|
|
String, /* ID but as string so serde will stop exploding */ |
|
|
|
String, /* ID but as string so serde will stop exploding */ |
|
|
|
Vec<&'a data::Value>, |
|
|
|
Vec<&'a data::Value>, |
|
|
|
>, |
|
|
|
>, |
|
|
|
relations: HashMap<String /* ID */, Vec<EnrichedRelation<'a>>>, |
|
|
|
relations: IndexMap<String /* ID */, Vec<EnrichedRelation<'a>>>, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Debug, Clone)] |
|
|
|
#[derive(Serialize, Debug, Clone)] |
|
|
@ -409,7 +417,7 @@ struct EnrichedRelation<'a> { |
|
|
|
object: ID, |
|
|
|
object: ID, |
|
|
|
model: ID, |
|
|
|
model: ID, |
|
|
|
related: ID, |
|
|
|
related: ID, |
|
|
|
values: HashMap<String /* ID */, Vec<&'a data::Value>>, |
|
|
|
values: IndexMap<String /* ID */, Vec<&'a data::Value>>, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#[get("/object/update/{id}")] |
|
|
|
#[get("/object/update/{id}")] |
|
|
@ -444,8 +452,8 @@ pub(crate) async fn update_form( |
|
|
|
|
|
|
|
|
|
|
|
let create_data = prepare_object_create_data(&rg, model.id)?; |
|
|
|
let create_data = prepare_object_create_data(&rg, model.id)?; |
|
|
|
|
|
|
|
|
|
|
|
let mut value_map = HashMap::new(); |
|
|
|
let mut value_map = IndexMap::new(); |
|
|
|
let mut relation_map = HashMap::new(); |
|
|
|
let mut relation_map = IndexMap::new(); |
|
|
|
|
|
|
|
|
|
|
|
// Some properties may have no values, so we first check what IDs to expect
|
|
|
|
// Some properties may have no values, so we first check what IDs to expect
|
|
|
|
let prop_ids = create_data |
|
|
|
let prop_ids = create_data |
|
|
@ -453,6 +461,7 @@ pub(crate) async fn update_form( |
|
|
|
.prop_models |
|
|
|
.prop_models |
|
|
|
.iter() |
|
|
|
.iter() |
|
|
|
.filter(|p| p.object == model.id) |
|
|
|
.filter(|p| p.object == model.id) |
|
|
|
|
|
|
|
.sorted_by(PropertyModel::order_refs2) |
|
|
|
.map(|p| p.id) |
|
|
|
.map(|p| p.id) |
|
|
|
.collect_vec(); |
|
|
|
.collect_vec(); |
|
|
|
|
|
|
|
|
|
|
@ -500,7 +509,7 @@ pub(crate) async fn update_form( |
|
|
|
.unwrap_or_default(); |
|
|
|
.unwrap_or_default(); |
|
|
|
|
|
|
|
|
|
|
|
for rel in relations { |
|
|
|
for rel in relations { |
|
|
|
let mut relation_values_map = HashMap::new(); |
|
|
|
let mut relation_values_map = IndexMap::new(); |
|
|
|
|
|
|
|
|
|
|
|
// values keyed by model
|
|
|
|
// values keyed by model
|
|
|
|
let mut rel_values = relation_values_grouped_by_instance |
|
|
|
let mut rel_values = relation_values_grouped_by_instance |
|
|
|