dry some stuff. also lot of yelling at the compiler
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
Reference in New Issue
Block a user