@ -22,6 +22,20 @@ pub(crate) async fn create_form(
let rg = store . read ( ) . await ;
// Re-fill old values
if let Ok ( Some ( form ) ) = session . take ::< PropertyModelCreateForm > ( "old" ) {
context . insert ( "old" , & form ) ;
} else {
context . insert ( "old" , & PropertyModelCreateForm {
object : Default ::default ( ) ,
name : "" . to_string ( ) ,
optional : false ,
multiple : false ,
data_type : DataType ::String ,
default : "" . to_string ( )
} ) ;
}
debug ! ( "ID = {}" , object_id ) ;
let object = {
@ -46,8 +60,8 @@ pub(crate) async fn create_form(
TERA . build_response ( "property_create" , & context )
}
#[ derive(Deserialize) ]
pub ( crate ) struct PropertyModelCreate {
#[ derive(Serialize, Deserialize) ]
pub ( crate ) struct PropertyModelCreateForm {
pub object : ID ,
pub name : String ,
#[ serde(default) ]
@ -60,80 +74,76 @@ pub(crate) struct PropertyModelCreate {
pub default : String ,
}
#[ post( " /model/property/create " ) ]
pub ( crate ) async fn 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 ;
let multiple = form . multiple ;
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 {
fn parse_default ( data_type : DataType , default : String ) -> Result < TypedValue , String > {
Ok ( match data_type {
DataType ::String = > {
if form . default . is_empty ( ) & & optional {
None
} else {
Some ( TypedValue ::String ( form . default . into ( ) ) )
}
TypedValue ::String ( default . into ( ) )
}
DataType ::Integer = > {
if form . default . is_empty ( ) {
if optional {
None
} else {
Some ( TypedValue ::Integer ( 0 ) )
}
if default . is_empty ( ) {
TypedValue ::Integer ( 0 )
} else {
// TODO better error reporting
Some ( TypedValue ::Integer ( form . default . parse ( )
TypedValue ::Integer ( default . parse ( )
. map_err ( | _ | {
actix_web ::error ::ErrorBadRequest ( format! ( "Error parsing \"{}\" as integer" , form . default ) )
} ) ? ) )
format! ( "Error parsing \"{}\" as integer" , default )
} ) ? )
}
}
DataType ::Decimal = > {
if form . default . is_empty ( ) {
if optional {
None
} else {
Some ( TypedValue ::Decimal ( 0.0 ) )
}
if default . is_empty ( ) {
TypedValue ::Decimal ( 0.0 )
} else {
// TODO better error reporting
Some ( TypedValue ::Decimal ( form . default . parse ( )
TypedValue ::Decimal ( default . parse ( )
. map_err ( | _ | {
actix_web ::error ::ErrorBadRequest ( format! ( "Error parsing \"{}\" as decimal" , form . default ) )
} ) ? ) )
format! ( "Error parsing \"{}\" as decimal" , default )
} ) ? )
}
}
DataType ::Boolean = > {
if form . default . is_empty ( ) {
if optional {
None
if default . is_empty ( ) {
TypedValue ::Boolean ( false )
} else {
Some ( TypedValue ::Boolean ( false ) )
}
} else {
Some ( TypedValue ::String ( form . default . clone ( ) . into ( ) )
TypedValue ::String ( default . clone ( ) . into ( ) )
. cast_to ( DataType ::Boolean ) . map_err ( | _ | {
actix_web ::error ::ErrorBadRequest ( format! ( "Error parsing \"{}\" as boolean" , form . default ) )
} ) ? )
format! ( "Error parsing \"{}\" as boolean" , default )
} ) ?
}
}
} )
}
} ,
#[ post( " /model/property/create " ) ]
pub ( crate ) async fn create (
form : web ::Form < PropertyModelCreateForm > ,
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 ;
let multiple = form . multiple ;
let default = match parse_default ( form . data_type , form . default . clone ( ) ) {
Ok ( def ) = > def ,
Err ( msg ) = > {
warn ! ( "{}" , msg ) ;
session . flash_error ( msg ) ;
session . set ( "old" , & form ) ;
return redirect ( format! ( "/model/property/create/{}" , form . object ) ) ;
}
} ;
match wg . define_property ( PropertyModel {
id : Default ::default ( ) ,
object : form . object ,
name : form . name . clone ( ) ,
optional ,
multiple ,
data_type : form . data_type ,
default ,
} ) {
Ok ( _id ) = > {
debug ! ( "Property created, redirecting to root" ) ;
@ -141,8 +151,9 @@ pub(crate) async fn create(
redirect ( "/" )
}
Err ( e ) = > {
warn ! ( "Error creating property model: {:? }" , e ) ;
warn ! ( "Error creating property model: {}" , e ) ;
session . flash_error ( e . to_string ( ) ) ;
session . set ( "old" , & form ) ;
redirect ( format! ( "/model/property/create/{}" , form . object ) )
}
}
@ -162,9 +173,96 @@ pub(crate) async fn delete(
redirect ( "/" )
}
Err ( e ) = > {
warn ! ( "Error deleting property: {:? }" , e ) ;
warn ! ( "Error deleting property: {}" , e ) ;
session . flash_error ( e . to_string ( ) ) ;
redirect ( "/" ) // back?
}
}
}
#[ derive(Serialize, Deserialize) ]
pub ( crate ) struct PropertyModelEditForm {
pub name : String ,
#[ 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
pub default : String ,
}
#[ get( " /model/property/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_property_model ( * model_id )
. ok_or_else ( | | actix_web ::error ::ErrorNotFound ( "No such model" ) ) ? ;
// Re-fill old values
if let Ok ( Some ( form ) ) = session . take ::< PropertyModelEditForm > ( "old" ) {
let mut model = model . clone ( ) ;
model . name = form . name ;
model . data_type = form . data_type ;
model . default = TypedValue ::String ( form . default . into ( ) ) ;
model . optional = form . optional ;
model . multiple = form . multiple ;
context . insert ( "model" , & model ) ;
} else {
context . insert ( "model" , model ) ;
}
TERA . build_response ( "property_update" , & context )
}
#[ post( " /model/property/update/{model_id} " ) ]
pub ( crate ) async fn update (
model_id : web ::Path < ID > ,
form : web ::Form < PropertyModelEditForm > ,
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 ( ) ;
let default = match parse_default ( form . data_type , form . default . clone ( ) ) {
Ok ( def ) = > def ,
Err ( msg ) = > {
warn ! ( "{}" , msg ) ;
session . flash_error ( msg ) ;
session . set ( "old" , form ) ;
return redirect ( format! ( "/model/property/update/{}" , id ) ) ;
}
} ;
match wg . update_property ( PropertyModel {
id ,
object : Default ::default ( ) , // dummy
name : form . name . clone ( ) ,
optional : form . optional ,
multiple : form . multiple ,
data_type : form . data_type ,
default ,
} ) {
Ok ( _id ) = > {
debug ! ( "Relation updated, redirecting to root" ) ;
session . flash_success ( format! ( "Property \"{}\" 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 ) )
}
}
}