create relation
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
{% extends "_layout" %}
|
||||
|
||||
{% block title -%}
|
||||
Define relation
|
||||
{%- endblock %}
|
||||
|
||||
{% block nav -%}
|
||||
<a href="/">Home</a>
|
||||
{%- endblock %}
|
||||
|
||||
{% block content -%}
|
||||
|
||||
<h1>Define new relation from "{{object.name}}"</h1>
|
||||
|
||||
<form action="/model/relation/create" method="POST">
|
||||
<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" value="1">
|
||||
<br>
|
||||
|
||||
<label for="multiple">Multiple:</label>
|
||||
<input type="checkbox" name="multiple" id="multiple" value="1"><br>
|
||||
|
||||
<label for="related">Related object:</label>
|
||||
<select name="related" id="related">
|
||||
{% for m in models %}
|
||||
<option value="{{ m.id }}">{{ m.name }}</option>
|
||||
{% endfor %}
|
||||
</select><br>
|
||||
|
||||
<input type="submit" value="Save">
|
||||
</form>
|
||||
|
||||
|
||||
{%- endblock %}
|
||||
@@ -97,6 +97,8 @@ async fn main() -> std::io::Result<()> {
|
||||
.service(routes::index)
|
||||
.service(routes::object_model_create_form)
|
||||
.service(routes::object_model_create)
|
||||
.service(routes::relation_model_create_form)
|
||||
.service(routes::relation_model_create)
|
||||
.service(routes::object_model_delete)
|
||||
.service(routes::relation_model_delete)
|
||||
.service(routes::property_model_delete)
|
||||
@@ -107,6 +109,7 @@ async fn main() -> std::io::Result<()> {
|
||||
.run().await
|
||||
}
|
||||
|
||||
|
||||
fn init_yopa() -> YopaStoreWrapper {
|
||||
let mut store = Storage::new();
|
||||
|
||||
|
||||
+99
-5
@@ -1,12 +1,15 @@
|
||||
use actix_web::{web, HttpRequest, Responder, HttpResponse};
|
||||
use crate::TERA;
|
||||
use crate::tera_ext::TeraExt;
|
||||
use yopa::{Storage, StorageError};
|
||||
use yopa::{Storage, StorageError, ID};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use yopa::model::{PropertyModel, RelationModel, ObjectModel};
|
||||
use std::ops::DerefMut;
|
||||
use actix_session::Session;
|
||||
use crate::session_ext::SessionExt;
|
||||
use std::str::FromStr;
|
||||
use std::fmt::{Debug, Display};
|
||||
use actix_web::http::header::IntoHeaderValue;
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
struct ObjectModelDisplay<'a> {
|
||||
@@ -23,12 +26,39 @@ struct RelationModelDisplay<'a> {
|
||||
properties: Vec<&'a PropertyModel>,
|
||||
}
|
||||
|
||||
fn redirect(path : impl AsRef<str>) -> actix_web::Result<impl Responder> {
|
||||
fn redirect(path : impl IntoHeaderValue) -> actix_web::Result<HttpResponse> {
|
||||
Ok(HttpResponse::SeeOther()
|
||||
.header("location", path.as_ref()) // back - to where?
|
||||
.header("location", path) // back - to where?
|
||||
.finish())
|
||||
}
|
||||
|
||||
trait ParseOrBadReq {
|
||||
fn parse_or_bad_request<T, E>(&self) -> actix_web::Result<T>
|
||||
where T: FromStr<Err=E>,
|
||||
E: Display + Debug + 'static;
|
||||
}
|
||||
|
||||
impl ParseOrBadReq for &str {
|
||||
fn parse_or_bad_request<T, E>(&self) -> actix_web::Result<T>
|
||||
where T: FromStr<Err=E>,
|
||||
E: Display + Debug + 'static
|
||||
{
|
||||
self.parse::<T>()
|
||||
.map_err(|e| actix_web::error::ErrorBadRequest(e))
|
||||
}
|
||||
}
|
||||
|
||||
impl ParseOrBadReq for String {
|
||||
fn parse_or_bad_request<T, E>(&self) -> actix_web::Result<T>
|
||||
where T: FromStr<Err=E>,
|
||||
E: Display + Debug + 'static
|
||||
{
|
||||
self.as_str()
|
||||
.parse_or_bad_request()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[get("/")]
|
||||
pub(crate) async fn index(session : Session, store : crate::YopaStoreWrapper) -> actix_web::Result<impl Responder> {
|
||||
|
||||
@@ -115,6 +145,70 @@ pub(crate) async fn object_model_create(
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/model/relation/create/{object_id}")]
|
||||
pub(crate) async fn relation_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 = rg.get_object_model(object_id.parse_or_bad_request()?)
|
||||
.ok_or_else(|| actix_web::error::ErrorNotFound("No such source object"))?;
|
||||
|
||||
let mut models: Vec<_> = rg.get_object_models().collect();
|
||||
|
||||
models.sort_by_key(|m| &m.name);
|
||||
|
||||
context.insert("models", &models);
|
||||
context.insert("object", &object);
|
||||
|
||||
TERA.build_response("relation_create", &context)
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub(crate) struct RelationModelCreate {
|
||||
pub object : ID,
|
||||
pub name : String,
|
||||
pub optional : Option<i32>,
|
||||
pub multiple : Option<i32>,
|
||||
pub related : ID,
|
||||
}
|
||||
|
||||
#[post("/model/relation/create")]
|
||||
pub(crate) async fn relation_model_create(
|
||||
form : web::Form<RelationModelCreate>,
|
||||
store : crate::YopaStoreWrapper,
|
||||
session : Session
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let mut wg = store.write().await;
|
||||
let form = form.into_inner();
|
||||
match wg.define_relation(RelationModel {
|
||||
id: Default::default(),
|
||||
object: form.object,
|
||||
name: form.name.clone(),
|
||||
optional: form.optional.unwrap_or_default() != 0,
|
||||
multiple: form.multiple.unwrap_or_default() != 0,
|
||||
related: form.related
|
||||
}) {
|
||||
Ok(_id) => {
|
||||
debug!("Relation created, redirecting to root");
|
||||
session.flash_success(format!("Relation model \"{}\" created.", form.name));
|
||||
redirect("/")
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Error creating relation model: {:?}", e);
|
||||
session.flash_error(e.to_string());
|
||||
redirect(format!("/model/relation/create/{}", form.object))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/model/object/delete/{id}")]
|
||||
pub(crate) async fn object_model_delete(
|
||||
id : web::Path<String>,
|
||||
@@ -143,7 +237,7 @@ pub(crate) async fn relation_model_delete(
|
||||
session : Session
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let mut wg = store.write().await;
|
||||
match wg.undefine_relation(id.parse().map_err(|e| actix_web::error::ErrorBadRequest(e))?) {
|
||||
match wg.undefine_relation(id.parse_or_bad_request()?) {
|
||||
Ok(rm) => {
|
||||
debug!("Relation deleted, redirecting to root");
|
||||
session.flash_success(format!("Relation model \"{}\" deleted.", rm.name));
|
||||
@@ -164,7 +258,7 @@ pub(crate) async fn property_model_delete(
|
||||
session : Session
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let mut wg = store.write().await;
|
||||
match wg.undefine_property(id.parse().map_err(|e| actix_web::error::ErrorBadRequest(e))?) {
|
||||
match wg.undefine_property(id.parse_or_bad_request()?) {
|
||||
Ok(rm) => {
|
||||
debug!("Property deleted, redirecting to root");
|
||||
session.flash_success(format!("Property \"{}\" deleted.", rm.name));
|
||||
|
||||
Reference in New Issue
Block a user