dry some stuff. also lot of yelling at the compiler

This commit is contained in:
2021-02-23 00:14:09 +01:00
parent e810724cd1
commit 3997381748
12 changed files with 350 additions and 127 deletions
+31 -29
View File
@@ -41,7 +41,7 @@ pub(crate) struct ObjectModelForm {
pub name: String,
#[serde(default)]
// #[serde(with="serde_with::rust::default_on_error")] // This is because "" can be selected
#[serde(with="my_string_empty_as_none")]
#[serde(with = "my_string_empty_as_none")]
pub name_property: Option<ID>,
}
@@ -56,7 +56,7 @@ pub(crate) async fn create(
match wg.define_object(ObjectModel {
id: Default::default(),
name: form.name.clone(),
name_property: form.name_property
name_property: form.name_property,
}) {
Ok(_id) => {
wg.persist().err_to_500()?;
@@ -96,10 +96,13 @@ pub(crate) async fn update_form(
context.insert("model", &model);
} else {
context.insert("model", model);
context.insert("old", &ObjectModelForm {
name: model.name.to_string(),
name_property: model.name_property
});
context.insert(
"old",
&ObjectModelForm {
name: model.name.to_string(),
name_property: model.name_property,
},
);
}
let properties = rg.get_property_models_for_parent(*model_id).collect_vec();
@@ -162,30 +165,29 @@ pub(crate) async fn delete(
}
}
pub mod my_string_empty_as_none {
use serde::{Deserializer, Serializer, Serialize};
use std::str::FromStr;
use std::fmt::{Display, Write};
use std::marker::PhantomData;
use serde::de::{Visitor, Error};
use serde::de::{Error, Visitor};
use serde::{Deserializer, Serialize, Serializer};
use std::fmt;
use std::fmt::Display;
use std::marker::PhantomData;
use std::str::FromStr;
use yopa::ID;
// FIXME largely copied from serde_with
/// Deserialize an `Option<T>` from a string using `FromStr`
pub fn deserialize<'de, D, S>(deserializer: D) -> Result<Option<S>, D::Error>
where
D: Deserializer<'de>,
S: FromStr,
S::Err: Display,
where
D: Deserializer<'de>,
S: FromStr,
S::Err: Display,
{
struct OptionStringEmptyNone<S>(PhantomData<S>);
impl<'de, S> Visitor<'de> for OptionStringEmptyNone<S>
where
S: FromStr,
S::Err: Display,
where
S: FromStr,
S::Err: Display,
{
type Value = Option<S>;
@@ -194,8 +196,8 @@ pub mod my_string_empty_as_none {
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
where
E: Error,
{
match value {
"" => Ok(None),
@@ -204,8 +206,8 @@ pub mod my_string_empty_as_none {
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: Error,
where
E: Error,
{
match &*value {
"" => Ok(None),
@@ -215,16 +217,16 @@ pub mod my_string_empty_as_none {
// TODO remove?
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: Error,
where
E: Error,
{
self.visit_str(&v.to_string())
}
// handles the `null` case
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: Error,
where
E: Error,
{
Ok(None)
}
@@ -235,8 +237,8 @@ pub mod my_string_empty_as_none {
/// Serialize a string from `Option<T>` using `AsRef<str>` or using the empty string if `None`.
pub fn serialize<S>(option: &Option<ID>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
where
S: Serializer,
{
option.serialize(serializer)
+52 -40
View File
@@ -1,23 +1,24 @@
use std::borrow::{Borrow, Cow};
use std::borrow::Cow;
use std::collections::HashMap;
use actix_session::Session;
use actix_web::{HttpResponse, Responder, web};
use actix_web::{web, HttpResponse, Responder};
use heck::TitleCase;
use itertools::Itertools;
use json_dotpath::DotPaths;
use serde::Serialize;
use yopa::{data, ID, model, Storage};
use yopa::data::Object;
use yopa::{data, model, Storage, ID};
use yopa::insert::InsertObj;
use yopa::model::{ObjectModel, PropertyModel, RelationModel};
use yopa::update::UpdateObj;
use crate::session_ext::SessionExt;
use crate::TERA;
use crate::tera_ext::TeraExt;
use crate::utils::{redirect, StorageErrorIntoResponseError};
use crate::TERA;
use yopa::helpers::GroupByModel;
// we only need references here, Context serializes everything to Value.
// cloning would be a waste of cycles
@@ -97,13 +98,14 @@ fn prepare_object_create_data(rg: &Storage, model_id: ID) -> actix_web::Result<O
.get_property_models_for_parents(prop_object_ids)
.collect(),
},
objects: rg.get_objects_of_types(related_ids).map(|o| {
ObjectDisplay {
objects: rg
.get_objects_of_types(related_ids)
.map(|o| ObjectDisplay {
id: o.id,
model: o.model,
name: rg.get_object_name(o),
}
}).collect(),
})
.collect(),
})
}
@@ -162,13 +164,16 @@ pub(crate) async fn list_inner(
.sorted_by_key(|m| &m.name)
.map(|model| {
let objects = objects_by_model.remove(&model.id).unwrap_or_default();
let mut objects = objects.into_iter().map(|o| {
ObjectDisplay {
id: o.id,
model: o.model,
name: rg.get_object_name(o), // TODO optimize
}
}).collect_vec();
let mut objects = objects
.into_iter()
.map(|o| {
ObjectDisplay {
id: o.id,
model: o.model,
name: rg.get_object_name(o), // TODO optimize
}
})
.collect_vec();
objects.sort_by(|a, b| a.name.cmp(&b.name));
ModelWithObjects { model, objects }
@@ -223,11 +228,14 @@ pub(crate) async fn detail(
.get_object_model(object.model)
.ok_or_else(|| actix_web::error::ErrorNotFound("No such model"))?;
context.insert("object", &ObjectDisplay {
id: object_id,
model: object.model,
name: rg.get_object_name(object),
});
context.insert(
"object",
&ObjectDisplay {
id: object_id,
model: object.model,
name: rg.get_object_name(object),
},
);
context.insert("model", model);
context.insert("kind", &rg.get_model_name(object.model));
@@ -248,8 +256,7 @@ pub(crate) async fn detail(
let object_values_by_model = grouped_values
.remove(&object_id)
.unwrap_or_default()
.into_iter()
.into_group_map_by(|value| value.model);
.group_by_model();
let mut view_object_properties = vec![];
for (prop_model_id, values) in object_values_by_model {
@@ -268,7 +275,7 @@ pub(crate) async fn detail(
{
let grouped_relations = relations
.iter()
.into_group_map_by(|relation| relation.model);
.group_by_model();
let mut relation_views = vec![];
for (model_id, relations) in grouped_relations {
@@ -283,8 +290,7 @@ pub(crate) async fn detail(
let rel_values_by_model = grouped_values
.remove(&rel.id)
.unwrap_or_default()
.into_iter()
.into_group_map_by(|value| value.model);
.group_by_model();
let mut view_rel_properties = vec![];
for (prop_model_id, values) in rel_values_by_model {
@@ -327,7 +333,7 @@ pub(crate) async fn detail(
{
let grouped_relations = reci_relations
.iter()
.into_group_map_by(|relation| relation.model);
.group_by_model();
let mut relation_views = vec![];
for (model_id, relations) in grouped_relations {
@@ -342,8 +348,7 @@ pub(crate) async fn detail(
let rel_values_by_model = grouped_values
.remove(&rel.id)
.unwrap_or_default()
.into_iter()
.into_group_map_by(|value| value.model);
.group_by_model();
let mut view_rel_properties = vec![];
for (prop_model_id, values) in rel_values_by_model {
@@ -428,11 +433,14 @@ pub(crate) async fn update_form(
// maybe its useful,idk
context.insert("model", &model);
context.insert("object", &ObjectDisplay {
id: object.id,
model: object.model,
name: rg.get_object_name(object),
});
context.insert(
"object",
&ObjectDisplay {
id: object.id,
model: object.model,
name: rg.get_object_name(object),
},
);
let create_data = prepare_object_create_data(&rg, model.id)?;
@@ -448,7 +456,8 @@ pub(crate) async fn update_form(
.map(|p| p.id)
.collect_vec();
let mut values_grouped = rg.get_values_for_object(*id).into_group_map_by(|v| v.model);
let mut values_grouped = rg.get_values_for_object(*id)
.group_by_model();
prop_ids.into_iter().for_each(|id| {
value_map.insert(
@@ -472,7 +481,7 @@ pub(crate) async fn update_form(
let mut relations_grouped_by_model = relations
.iter()
.into_group_map_by(|relation| relation.model);
.group_by_model();
let mut property_models_grouped_by_parent =
rg.get_grouped_prop_models_for_parents(relation_model_ids.clone());
@@ -497,8 +506,7 @@ pub(crate) async fn update_form(
let mut rel_values = relation_values_grouped_by_instance
.remove(&rel.id)
.unwrap_or_default()
.into_iter()
.into_group_map_by(|relation| relation.model);
.group_by_model();
prop_models_for_relation.iter().for_each(|prop_model| {
relation_values_map.insert(
@@ -525,7 +533,7 @@ pub(crate) async fn update_form(
let object = EnrichedObject {
id: object.id,
model: object.model,
name: rg.get_object_name_by_id(object.id),
name: rg.get_object_name(object),
values: value_map,
relations: relation_map,
};
@@ -558,7 +566,11 @@ pub(crate) async fn update(
Ok(_id) => {
wg.persist().err_to_500()?;
debug!("Object created, redirecting to root");
session.flash_success(format!("{} \"{}\" updated.", model_name, wg.get_object_name_by_id(id)));
session.flash_success(format!(
"{} \"{}\" updated.",
model_name,
wg.get_object_name_by_id(id)
));
Ok(HttpResponse::Ok().finish())
}
Err(e) => {