create property
This commit is contained in:
+1
-1
@@ -8,7 +8,7 @@ build = "build.rs"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
yopa = { path = "../yopa" }
|
||||
yopa = { path = "../yopa", features = [] }
|
||||
serde = "1"
|
||||
serde_json = "1"
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ Define object
|
||||
|
||||
<h1>Define new object model</h1>
|
||||
|
||||
{# TODO implement value restoration on error #}
|
||||
|
||||
<form action="/model/object/create" method="POST">
|
||||
<label for="name">Name:</label>
|
||||
<input type="text" id="name" name="name"><br>
|
||||
|
||||
@@ -10,20 +10,23 @@ Define property
|
||||
|
||||
{% block content -%}
|
||||
|
||||
<h1>Add new property to model "{{model.name}}"</h1>
|
||||
{# The parent can be either object or relation model #}
|
||||
<h1>Add new property to {{object.describe}}</h1>
|
||||
|
||||
{# TODO implement value restoration on error #}
|
||||
|
||||
<form action="/model/property/create" method="POST">
|
||||
<input type="hidden" name="object" value="{{object}}">
|
||||
<input type="hidden" name="object" value="{{object.id}}">
|
||||
|
||||
<label for="name">Name:</label>
|
||||
<input type="text" id="name" name="name"><br>
|
||||
|
||||
<label for="optional">Optional:</label>
|
||||
<input type="checkbox" name="optional" id="optional">
|
||||
<input type="checkbox" name="optional" id="optional" value="1">
|
||||
<br>
|
||||
|
||||
<label for="multiple">Multiple:</label>
|
||||
<input type="checkbox" name="multiple" id="multiple"><br>
|
||||
<input type="checkbox" name="multiple" id="multiple" value="1"><br>
|
||||
|
||||
<label for="data_type">Type:</label>
|
||||
<select name="data_type" id="data_type">
|
||||
|
||||
@@ -12,6 +12,8 @@ Define relation
|
||||
|
||||
<h1>Define new relation from "{{object.name}}"</h1>
|
||||
|
||||
{# TODO implement value restoration on error #}
|
||||
|
||||
<form action="/model/relation/create" method="POST">
|
||||
<input type="hidden" name="object" value="{{object.id}}">
|
||||
|
||||
|
||||
@@ -99,6 +99,8 @@ async fn main() -> std::io::Result<()> {
|
||||
.service(routes::object_model_create)
|
||||
.service(routes::relation_model_create_form)
|
||||
.service(routes::relation_model_create)
|
||||
.service(routes::property_model_create_form)
|
||||
.service(routes::property_model_create)
|
||||
.service(routes::object_model_delete)
|
||||
.service(routes::relation_model_delete)
|
||||
.service(routes::property_model_delete)
|
||||
|
||||
+146
-2
@@ -1,7 +1,7 @@
|
||||
use actix_web::{web, HttpRequest, Responder, HttpResponse};
|
||||
use crate::TERA;
|
||||
use crate::tera_ext::TeraExt;
|
||||
use yopa::{Storage, StorageError, ID};
|
||||
use yopa::{Storage, StorageError, ID, DataType, TypedValue};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yopa::model::{PropertyModel, RelationModel, ObjectModel};
|
||||
use std::ops::DerefMut;
|
||||
@@ -44,7 +44,10 @@ impl ParseOrBadReq for &str {
|
||||
E: Display + Debug + 'static
|
||||
{
|
||||
self.parse::<T>()
|
||||
.map_err(|e| actix_web::error::ErrorBadRequest(e))
|
||||
.map_err(|e| {
|
||||
error!("Parse error for \"{}\"", self);
|
||||
actix_web::error::ErrorBadRequest(e)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,6 +212,147 @@ pub(crate) async fn relation_model_create(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
struct ObjectOrRelationModelDisplay {
|
||||
id : ID,
|
||||
describe : String,
|
||||
}
|
||||
|
||||
#[get("/model/property/create/{object_id}")]
|
||||
pub(crate) async fn property_model_create_form(
|
||||
object_id : web::Path<String>,
|
||||
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;
|
||||
|
||||
debug!("ID = {}", object_id);
|
||||
|
||||
let object = {
|
||||
let id = object_id.parse_or_bad_request()?;
|
||||
debug!("Create property for ID={}", id);
|
||||
if let Some(om) = rg.get_object_model(id) {
|
||||
ObjectOrRelationModelDisplay {
|
||||
id: om.id,
|
||||
describe: format!("object model \"{}\"", om.name),
|
||||
}
|
||||
} else if let Some(rm) = rg.get_relation_model(id) {
|
||||
ObjectOrRelationModelDisplay {
|
||||
id: rm.id,
|
||||
describe: format!("relation model \"{}\"", rm.name),
|
||||
}
|
||||
} else {
|
||||
return Err(actix_web::error::ErrorNotFound("No such source object"));
|
||||
}
|
||||
};
|
||||
|
||||
context.insert("object", &object);
|
||||
TERA.build_response("property_create", &context)
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub(crate) struct PropertyModelCreate {
|
||||
pub object : ID,
|
||||
pub name : String,
|
||||
pub optional : Option<i32>,
|
||||
pub multiple : Option<i32>,
|
||||
pub data_type : DataType,
|
||||
/// Default value to be parsed to the data type
|
||||
/// May be unused if empty and optional
|
||||
pub default : String,
|
||||
}
|
||||
|
||||
#[post("/model/property/create")]
|
||||
pub(crate) async fn property_model_create(
|
||||
form : web::Form<PropertyModelCreate>,
|
||||
store : crate::YopaStoreWrapper,
|
||||
session : Session
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let mut wg = store.write().await;
|
||||
let form = form.into_inner();
|
||||
|
||||
let optional = form.optional.unwrap_or_default() != 0;
|
||||
let multiple = form.multiple.unwrap_or_default() != 0;
|
||||
|
||||
match wg.define_property(PropertyModel {
|
||||
id: Default::default(),
|
||||
object: form.object,
|
||||
name: form.name.clone(),
|
||||
optional,
|
||||
multiple,
|
||||
data_type: form.data_type,
|
||||
default: {
|
||||
match form.data_type {
|
||||
DataType::String => {
|
||||
if form.default.is_empty() && optional {
|
||||
None
|
||||
} else {
|
||||
Some(TypedValue::String(form.default.into()))
|
||||
}
|
||||
}
|
||||
DataType::Integer => {
|
||||
if form.default.is_empty() {
|
||||
if optional {
|
||||
None
|
||||
} else {
|
||||
Some(TypedValue::Integer(0))
|
||||
}
|
||||
} else {
|
||||
// TODO better error reporting
|
||||
Some(TypedValue::Integer(form.default.parse()
|
||||
.map_err(|_| {
|
||||
actix_web::error::ErrorBadRequest(format!("Error parsing \"{}\" as integer", form.default))
|
||||
})?))
|
||||
}
|
||||
}
|
||||
DataType::Decimal => {
|
||||
if form.default.is_empty() {
|
||||
if optional {
|
||||
None
|
||||
} else {
|
||||
Some(TypedValue::Decimal(0.0))
|
||||
}
|
||||
} else {
|
||||
// TODO better error reporting
|
||||
Some(TypedValue::Decimal(form.default.parse()
|
||||
.map_err(|_| {
|
||||
actix_web::error::ErrorBadRequest(format!("Error parsing \"{}\" as decimal", form.default))
|
||||
})?))
|
||||
}
|
||||
}
|
||||
DataType::Boolean => {
|
||||
if form.default.is_empty() {
|
||||
if optional {
|
||||
None
|
||||
} else {
|
||||
Some(TypedValue::Boolean(false))
|
||||
}
|
||||
} else {
|
||||
Some(TypedValue::String(form.default.clone().into())
|
||||
.cast_to(DataType::Boolean).map_err(|_| {
|
||||
actix_web::error::ErrorBadRequest(format!("Error parsing \"{}\" as boolean", form.default))
|
||||
})?)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}) {
|
||||
Ok(_id) => {
|
||||
debug!("Property created, redirecting to root");
|
||||
session.flash_success(format!("Property model \"{}\" created.", form.name));
|
||||
redirect("/")
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Error creating property model: {:?}", e);
|
||||
session.flash_error(e.to_string());
|
||||
redirect(format!("/model/property/create/{}", form.object))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/model/object/delete/{id}")]
|
||||
pub(crate) async fn object_model_delete(
|
||||
id : web::Path<String>,
|
||||
|
||||
Reference in New Issue
Block a user