relation edit
This commit is contained in:
@@ -5,5 +5,5 @@
|
||||
{%- endif -%}
|
||||
{%- if prop.optional %}, OPTIONAL{% endif %}
|
||||
{%- if prop.multiple %}, MULTIPLE{% endif %}
|
||||
<a href="/model/property/delete/{{prop.id}}">Delete property</a>
|
||||
<a href="/model/property/delete/{{prop.id}}" onclick="return confirm('Delete property?')">Delete property</a>
|
||||
{% endmacro input %}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<li>
|
||||
<b title="{{model.id}}">{{model.name}}</b><br>
|
||||
|
||||
<a href="/model/object/delete/{{model.id}}">Delete model</a> ·
|
||||
<a href="/model/object/delete/{{model.id}}" onclick="return confirm('Delete model?')">Delete model</a> ·
|
||||
<a href="/model/object/update/{{model.id}}">Edit model</a> ·
|
||||
<a href="/model/relation/create/{{model.id}}">New relation</a> ·
|
||||
<a href="/model/property/create/{{model.id}}">New property</a>
|
||||
@@ -50,7 +50,8 @@
|
||||
{%- if rel.model.multiple %}, MULTIPLE{% endif %}
|
||||
<br>
|
||||
|
||||
<a href="/model/relation/delete/{{rel.model.id}}">Delete relation</a> ·
|
||||
<a href="/model/relation/update/{{rel.model.id}}">Edit relation</a> ·
|
||||
<a href="/model/relation/delete/{{rel.model.id}}" onclick="return confirm('Delete relation?')">Delete relation</a> ·
|
||||
<a href="/model/property/create/{{rel.model.id}}">New property</a>
|
||||
<br>
|
||||
|
||||
|
||||
@@ -12,11 +12,9 @@ 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" autocomplete="off"><br>
|
||||
<input type="text" id="name" name="name" value="{{old.name}}" autocomplete="off"><br>
|
||||
|
||||
<input type="submit" value="Save">
|
||||
</form>
|
||||
|
||||
@@ -22,11 +22,11 @@ Define property
|
||||
<input type="text" id="name" name="name" autocomplete="off"><br>
|
||||
|
||||
<label for="optional">Optional:</label>
|
||||
<input type="checkbox" name="optional" id="optional" value="1" autocomplete="off">
|
||||
<input type="checkbox" name="optional" id="optional" value="true" autocomplete="off">
|
||||
<br>
|
||||
|
||||
<label for="multiple">Multiple:</label>
|
||||
<input type="checkbox" name="multiple" id="multiple" value="1" autocomplete="off"><br>
|
||||
<input type="checkbox" name="multiple" id="multiple" value="true" autocomplete="off"><br>
|
||||
|
||||
<label for="data_type">Type:</label>
|
||||
<select name="data_type" id="data_type" autocomplete="off">
|
||||
|
||||
@@ -24,11 +24,11 @@ Define relation
|
||||
<input type="text" id="reciprocal_name" name="reciprocal_name" autocomplete="off"><br>
|
||||
|
||||
<label for="optional">Optional:</label>
|
||||
<input type="checkbox" name="optional" id="optional" value="1" autocomplete="off">
|
||||
<input type="checkbox" name="optional" id="optional" value="true" autocomplete="off">
|
||||
<br>
|
||||
|
||||
<label for="multiple">Multiple:</label>
|
||||
<input type="checkbox" name="multiple" id="multiple" value="1" autocomplete="off"><br>
|
||||
<input type="checkbox" name="multiple" id="multiple" value="true" autocomplete="off"><br>
|
||||
|
||||
<label for="related">Related object:</label>
|
||||
<select name="related" id="related" autocomplete="off">
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
{% extends "_layout" %}
|
||||
|
||||
{% block title -%}
|
||||
Edit relation
|
||||
{%- endblock %}
|
||||
|
||||
{% block nav -%}
|
||||
<a href="/">Home</a>
|
||||
{%- endblock %}
|
||||
|
||||
{% block content -%}
|
||||
|
||||
<h1>Edit relation model "{{model.name}}"</h1>
|
||||
|
||||
<form action="/model/relation/update/{{model.id}}" method="POST">
|
||||
<label for="name">Name:</label>
|
||||
<input type="text" id="name" name="name" value="{{model.name}}" autocomplete="off"><br>
|
||||
|
||||
<label for="reciprocal_name">Reciprocal name:</label>
|
||||
<input type="text" id="reciprocal_name" name="reciprocal_name" value="{{model.reciprocal_name}}" autocomplete="off"><br>
|
||||
|
||||
<label for="optional">Optional:</label>
|
||||
<input type="checkbox" name="optional" id="optional" value="true" {{opt(checked=model.optional)}} autocomplete="off">
|
||||
<br>
|
||||
|
||||
<label for="multiple">Multiple:</label>
|
||||
<input type="checkbox" name="multiple" id="multiple" value="true" {{opt(checked=model.multiple)}} autocomplete="off"><br>
|
||||
|
||||
<p>The related object cannot be changed. Create a new relation if needed.</p>
|
||||
|
||||
<input type="submit" value="Save">
|
||||
</form>
|
||||
|
||||
|
||||
{%- endblock %}
|
||||
@@ -56,6 +56,21 @@ pub(crate) static TERA: Lazy<Tera> = Lazy::new(|| {
|
||||
Err(tera::Error::msg("Expected nonenmpty object"))
|
||||
});
|
||||
|
||||
tera.register_function("opt", |args: &HashMap<String, Value>| -> tera::Result<Value> {
|
||||
if args.len() != 1 {
|
||||
return Err("Expected 1 argument".into());
|
||||
}
|
||||
match args.iter().nth(0) {
|
||||
Some((name, &Value::Bool(true))) => {
|
||||
Ok(Value::String(name.clone()))
|
||||
},
|
||||
Some((_, &Value::Bool(false))) => {
|
||||
Ok(Value::Null)
|
||||
},
|
||||
_ => Err("Expected bool argument".into()),
|
||||
}
|
||||
});
|
||||
|
||||
// TODO need to inject HttpRequest::url_for() into tera context, but it then can't be accessed by the functions.
|
||||
// tera.register_function("url_for", |args: HashMap<String, Value>| -> tera::Result<Value> {
|
||||
// match args.get("name") {
|
||||
@@ -110,6 +125,8 @@ async fn main() -> std::io::Result<()> {
|
||||
//
|
||||
.service(routes::relation_model::create_form)
|
||||
.service(routes::relation_model::create)
|
||||
.service(routes::relation_model::update_form)
|
||||
.service(routes::relation_model::update)
|
||||
.service(routes::relation_model::delete)
|
||||
//
|
||||
.service(routes::property_model::create_form)
|
||||
|
||||
@@ -25,10 +25,17 @@ pub(crate) async fn create_form(session: Session) -> actix_web::Result<impl Resp
|
||||
let mut context = tera::Context::new();
|
||||
session.render_flash(&mut context);
|
||||
|
||||
// Re-fill old values
|
||||
if let Ok(Some(form)) = session.take::<ObjectModelForm>("old") {
|
||||
context.insert("old", &form);
|
||||
} else {
|
||||
context.insert("old", &ObjectModelForm::default());
|
||||
}
|
||||
|
||||
TERA.build_response("model_create", &context)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct ObjectModelForm {
|
||||
pub name: String,
|
||||
}
|
||||
@@ -53,6 +60,7 @@ pub(crate) async fn create(
|
||||
Err(e) => {
|
||||
warn!("Error creating model: {:?}", e);
|
||||
session.flash_error(e.to_string());
|
||||
session.set("old", form);
|
||||
redirect("/model/object/create")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +50,10 @@ pub(crate) async fn create_form(
|
||||
pub(crate) struct PropertyModelCreate {
|
||||
pub object: ID,
|
||||
pub name: String,
|
||||
pub optional: Option<i32>,
|
||||
pub multiple: Option<i32>,
|
||||
#[serde(default)]
|
||||
pub optional: bool,
|
||||
#[serde(default)]
|
||||
pub multiple: bool,
|
||||
pub data_type: DataType,
|
||||
/// Default value to be parsed to the data type
|
||||
/// May be unused if empty and optional
|
||||
@@ -67,8 +69,8 @@ pub(crate) async fn create(
|
||||
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;
|
||||
let optional = form.optional;
|
||||
let multiple = form.multiple;
|
||||
|
||||
match wg.define_property(PropertyModel {
|
||||
id: Default::default(),
|
||||
|
||||
@@ -44,18 +44,20 @@ pub(crate) async fn create_form(
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub(crate) struct RelationModelCreate {
|
||||
pub(crate) struct RelationModelCreateForm {
|
||||
pub object: ID,
|
||||
pub name: String,
|
||||
pub reciprocal_name: String,
|
||||
pub optional: Option<i32>,
|
||||
pub multiple: Option<i32>,
|
||||
#[serde(default)]
|
||||
pub optional: bool,
|
||||
#[serde(default)]
|
||||
pub multiple: bool,
|
||||
pub related: ID,
|
||||
}
|
||||
|
||||
#[post("/model/relation/create")]
|
||||
pub(crate) async fn create(
|
||||
form: web::Form<RelationModelCreate>,
|
||||
form: web::Form<RelationModelCreateForm>,
|
||||
store: crate::YopaStoreWrapper,
|
||||
session: Session,
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
@@ -66,8 +68,8 @@ pub(crate) async fn create(
|
||||
object: form.object,
|
||||
name: form.name.clone(),
|
||||
reciprocal_name: form.reciprocal_name.clone(),
|
||||
optional: form.optional.unwrap_or_default() != 0,
|
||||
multiple: form.multiple.unwrap_or_default() != 0,
|
||||
optional: form.optional,
|
||||
multiple: form.multiple,
|
||||
related: form.related,
|
||||
}) {
|
||||
Ok(_id) => {
|
||||
@@ -109,3 +111,74 @@ pub(crate) async fn delete(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize,Deserialize)]
|
||||
pub(crate) struct RelationModelEditForm {
|
||||
pub name: String,
|
||||
pub reciprocal_name: String,
|
||||
#[serde(default)]
|
||||
pub optional: bool,
|
||||
#[serde(default)]
|
||||
pub multiple: bool,
|
||||
}
|
||||
|
||||
#[get("/model/relation/update/{model_id}")]
|
||||
pub(crate) async fn update_form(
|
||||
model_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 model = rg.get_relation_model(*model_id)
|
||||
.ok_or_else(|| actix_web::error::ErrorNotFound("No such model"))?;
|
||||
|
||||
// Re-fill old values
|
||||
if let Ok(Some(form)) = session.take::<RelationModelEditForm>("old") {
|
||||
let mut model = model.clone();
|
||||
model.name = form.name;
|
||||
model.optional = form.optional; // TODO try if regular bools cant be used
|
||||
model.multiple = form.multiple;
|
||||
context.insert("model", &model);
|
||||
} else {
|
||||
context.insert("model", model);
|
||||
}
|
||||
|
||||
TERA.build_response("relation_update", &context)
|
||||
}
|
||||
|
||||
#[post("/model/relation/update/{model_id}")]
|
||||
pub(crate) async fn update(
|
||||
model_id: web::Path<ID>,
|
||||
form: web::Form<RelationModelEditForm>,
|
||||
store: crate::YopaStoreWrapper,
|
||||
session: Session,
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let mut wg = store.write().await;
|
||||
let form = form.into_inner();
|
||||
|
||||
let id = model_id.into_inner();
|
||||
match wg.update_relation(RelationModel {
|
||||
id,
|
||||
object: Default::default(), // dummy
|
||||
name: form.name.clone(),
|
||||
reciprocal_name: form.reciprocal_name.to_string(),
|
||||
optional: form.optional,
|
||||
multiple: form.multiple,
|
||||
related: Default::default() // dummy
|
||||
}) {
|
||||
Ok(_id) => {
|
||||
debug!("Relation updated, redirecting to root");
|
||||
session.flash_success(format!("Relation model \"{}\" updated.", form.name));
|
||||
redirect("/")
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Error updating model: {:?}", e);
|
||||
session.flash_error(e.to_string());
|
||||
session.set("old", form);
|
||||
redirect(format!("/model/relation/update/{}", id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user