impl selectlist for foreign key
This commit is contained in:
parent
b56bdf8984
commit
a6edbc0f56
@ -12,14 +12,19 @@ use struct_fields::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
mod selectlist_fields;
|
mod selectlist_fields;
|
||||||
use selectlist_fields::{get_select_list, get_select_lists};
|
use selectlist_fields::{get_select_list_from_enum, get_select_list_from_model, get_select_lists};
|
||||||
|
|
||||||
mod attributes;
|
mod attributes;
|
||||||
mod model_fields;
|
mod model_fields;
|
||||||
|
|
||||||
#[proc_macro_derive(DeriveActixAdminSelectList, attributes(actix_admin))]
|
#[proc_macro_derive(DeriveActixAdminEnumSelectList, attributes(actix_admin))]
|
||||||
pub fn derive_actix_admin_select_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn derive_actix_admin_enum_select_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
get_select_list(input)
|
get_select_list_from_enum(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(DeriveActixAdminModelSelectList, attributes(actix_admin))]
|
||||||
|
pub fn derive_actix_admin_model_select_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
get_select_list_from_model(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(DeriveActixAdmin, attributes(actix_admin))]
|
#[proc_macro_derive(DeriveActixAdmin, attributes(actix_admin))]
|
||||||
@ -70,15 +75,16 @@ pub fn derive_actix_admin_view_model(input: proc_macro::TokenStream) -> proc_mac
|
|||||||
entities
|
entities
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_entity(db: &DatabaseConnection, mut model: ActixAdminModel) -> ActixAdminModel {
|
fn validate_entity(model: &mut ActixAdminModel) {
|
||||||
let mut validation_errs = Entity::validate_model(&model);
|
Entity::validate_model(model);
|
||||||
//model.errors.append(&mut validation_errs);
|
|
||||||
model.errors = validation_errs;
|
|
||||||
|
|
||||||
if !model.has_errors() {
|
let custom_errors = Entity::validate(&model);
|
||||||
|
model.custom_errors = custom_errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn create_entity(db: &DatabaseConnection, mut model: ActixAdminModel) -> ActixAdminModel {
|
||||||
let new_model = ActiveModel::from(model.clone());
|
let new_model = ActiveModel::from(model.clone());
|
||||||
let insert_operation = Entity::insert(new_model).exec(db).await;
|
let insert_operation = Entity::insert(new_model).exec(db).await;
|
||||||
}
|
|
||||||
|
|
||||||
model
|
model
|
||||||
}
|
}
|
||||||
@ -91,17 +97,12 @@ pub fn derive_actix_admin_view_model(input: proc_macro::TokenStream) -> proc_mac
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn edit_entity(db: &DatabaseConnection, id: i32, mut model: ActixAdminModel) -> ActixAdminModel {
|
async fn edit_entity(db: &DatabaseConnection, id: i32, mut model: ActixAdminModel) -> ActixAdminModel {
|
||||||
let mut validation_errs = Entity::validate_model(&model);
|
|
||||||
//model.errors.append(&mut validation_errs);
|
|
||||||
model.errors=validation_errs;
|
|
||||||
|
|
||||||
if !model.has_errors() {
|
|
||||||
let entity: Option<Model> = Entity::find_by_id(id).one(db).await.unwrap();
|
let entity: Option<Model> = Entity::find_by_id(id).one(db).await.unwrap();
|
||||||
let mut entity: ActiveModel = entity.unwrap().into();
|
let mut entity: ActiveModel = entity.unwrap().into();
|
||||||
|
|
||||||
#(#fields_for_edit_model);*;
|
#(#fields_for_edit_model);*;
|
||||||
let entity: Model = entity.update(db).await.unwrap();
|
let entity: Model = entity.update(db).await.unwrap();
|
||||||
}
|
|
||||||
model
|
model
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +153,8 @@ pub fn derive_actix_admin_model(input: proc_macro::TokenStream) -> proc_macro::T
|
|||||||
values: hashmap![
|
values: hashmap![
|
||||||
#(#fields_for_from_model),*
|
#(#fields_for_from_model),*
|
||||||
],
|
],
|
||||||
errors: HashMap::new()
|
errors: HashMap::new(),
|
||||||
|
custom_errors: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,12 +196,11 @@ pub fn derive_actix_admin_model(input: proc_macro::TokenStream) -> proc_macro::T
|
|||||||
(num_pages, model_entities)
|
(num_pages, model_entities)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_model(model: &ActixAdminModel) -> HashMap<String, String> {
|
fn validate_model(model: &mut ActixAdminModel) {
|
||||||
let mut errors = HashMap::<String, String>::new();
|
let mut errors = HashMap::<String, String>::new();
|
||||||
#(#fields_for_validate_model);*;
|
#(#fields_for_validate_model);*;
|
||||||
//let mut custom_errors = Entity.validate();
|
|
||||||
//errors.append(&mut custom_errors);
|
model.errors = errors;
|
||||||
errors
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_fields() -> Vec<ActixAdminViewModelField> {
|
fn get_fields() -> Vec<ActixAdminViewModelField> {
|
||||||
|
@ -5,13 +5,37 @@ use quote::quote;
|
|||||||
use crate::model_fields::{ ModelField };
|
use crate::model_fields::{ ModelField };
|
||||||
use proc_macro2::{Span};
|
use proc_macro2::{Span};
|
||||||
|
|
||||||
pub fn get_select_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn get_select_list_from_model(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
//let ast: DeriveInput = syn::parse(input).unwrap();
|
||||||
|
//let (_vis, _ty, _generics) = (&ast.vis, &ast.ident, &ast.generics);
|
||||||
|
|
||||||
|
let expanded = quote! {
|
||||||
|
#[async_trait]
|
||||||
|
impl ActixAdminSelectListTrait for Entity {
|
||||||
|
async fn get_key_value(db: &DatabaseConnection) -> Vec<(String, String)> {
|
||||||
|
let entities = Entity::find().order_by_asc(Column::Id).all(db).await;
|
||||||
|
let mut key_value = Vec::new();
|
||||||
|
|
||||||
|
for entity in entities.unwrap() {
|
||||||
|
key_value.push((entity.id.to_string(), entity.to_string()));
|
||||||
|
};
|
||||||
|
key_value.sort_by(|a, b| a.1.cmp(&b.1));
|
||||||
|
key_value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
proc_macro::TokenStream::from(expanded)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_select_list_from_enum(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
let ast: DeriveInput = syn::parse(input).unwrap();
|
let ast: DeriveInput = syn::parse(input).unwrap();
|
||||||
let (_vis, ty, _generics) = (&ast.vis, &ast.ident, &ast.generics);
|
let (_vis, ty, _generics) = (&ast.vis, &ast.ident, &ast.generics);
|
||||||
|
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
|
#[async_trait]
|
||||||
impl ActixAdminSelectListTrait for #ty {
|
impl ActixAdminSelectListTrait for #ty {
|
||||||
fn get_key_value() -> Vec<(String, String)> {
|
async fn get_key_value(db: &DatabaseConnection) -> Vec<(String, String)> {
|
||||||
let mut fields = Vec::new();
|
let mut fields = Vec::new();
|
||||||
for field in #ty::iter() {
|
for field in #ty::iter() {
|
||||||
fields.push((field.to_string(), field.to_string()));
|
fields.push((field.to_string(), field.to_string()));
|
||||||
@ -20,6 +44,7 @@ pub fn get_select_list(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
proc_macro::TokenStream::from(expanded)
|
proc_macro::TokenStream::from(expanded)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +56,7 @@ pub fn get_select_lists(fields: &Vec<ModelField>) -> Vec<proc_macro2::TokenStrea
|
|||||||
let ident_name = model_field.ident.to_string();
|
let ident_name = model_field.ident.to_string();
|
||||||
let select_list_ident = Ident::new(&(model_field.select_list), Span::call_site());
|
let select_list_ident = Ident::new(&(model_field.select_list), Span::call_site());
|
||||||
quote! {
|
quote! {
|
||||||
#ident_name => #select_list_ident::get_key_value()
|
#ident_name => #select_list_ident::get_key_value(db).await
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
|
@ -4,6 +4,7 @@ use std::collections::HashMap;
|
|||||||
use tera::{Tera, Result, to_value, try_get_value };
|
use tera::{Tera, Result, to_value, try_get_value };
|
||||||
use std::{ hash::BuildHasher};
|
use std::{ hash::BuildHasher};
|
||||||
use actix_session::{Session};
|
use actix_session::{Session};
|
||||||
|
use async_trait::async_trait;
|
||||||
|
|
||||||
pub mod view_model;
|
pub mod view_model;
|
||||||
pub mod model;
|
pub mod model;
|
||||||
@ -14,7 +15,7 @@ pub mod prelude {
|
|||||||
pub use crate::builder::{ ActixAdminBuilder, ActixAdminBuilderTrait};
|
pub use crate::builder::{ ActixAdminBuilder, ActixAdminBuilderTrait};
|
||||||
pub use crate::model::{ ActixAdminModel, ActixAdminModelTrait};
|
pub use crate::model::{ ActixAdminModel, ActixAdminModelTrait};
|
||||||
pub use crate::view_model::{ ActixAdminViewModel, ActixAdminViewModelTrait, ActixAdminViewModelField, ActixAdminViewModelSerializable, ActixAdminViewModelFieldType };
|
pub use crate::view_model::{ ActixAdminViewModel, ActixAdminViewModelTrait, ActixAdminViewModelField, ActixAdminViewModelSerializable, ActixAdminViewModelFieldType };
|
||||||
pub use actix_admin_macros::{ DeriveActixAdmin, DeriveActixAdminModel, DeriveActixAdminViewModel, DeriveActixAdminSelectList };
|
pub use actix_admin_macros::{ DeriveActixAdmin, DeriveActixAdminModel, DeriveActixAdminViewModel, DeriveActixAdminEnumSelectList, DeriveActixAdminModelSelectList };
|
||||||
pub use crate::{ ActixAdminAppDataTrait, ActixAdmin, ActixAdminConfiguration };
|
pub use crate::{ ActixAdminAppDataTrait, ActixAdmin, ActixAdminConfiguration };
|
||||||
pub use crate::{ hashmap, ActixAdminSelectListTrait };
|
pub use crate::{ hashmap, ActixAdminSelectListTrait };
|
||||||
}
|
}
|
||||||
@ -88,8 +89,9 @@ pub trait ActixAdminAppDataTrait {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SelectListTrait
|
// SelectListTrait
|
||||||
|
#[async_trait]
|
||||||
pub trait ActixAdminSelectListTrait {
|
pub trait ActixAdminSelectListTrait {
|
||||||
fn get_key_value() -> Vec<(String, String)>;
|
async fn get_key_value(db: &DatabaseConnection) -> Vec<(String, String)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@ pub trait ActixAdminModelTrait {
|
|||||||
search: &String
|
search: &String
|
||||||
) -> (usize, Vec<ActixAdminModel>);
|
) -> (usize, Vec<ActixAdminModel>);
|
||||||
fn get_fields() -> Vec<ActixAdminViewModelField>;
|
fn get_fields() -> Vec<ActixAdminViewModelField>;
|
||||||
fn validate_model(model: &ActixAdminModel) -> HashMap<String, String>;
|
fn validate_model(model: &mut ActixAdminModel);
|
||||||
// function to be overridable for custom error handling
|
// function to be overridable for custom error handling
|
||||||
fn validate(&self) -> HashMap<String, String> {
|
fn validate(_model: &ActixAdminModel) -> HashMap<String, String> {
|
||||||
return HashMap::new();
|
return HashMap::new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,6 +28,7 @@ pub struct ActixAdminModel {
|
|||||||
pub primary_key: Option<String>,
|
pub primary_key: Option<String>,
|
||||||
pub values: HashMap<String, String>,
|
pub values: HashMap<String, String>,
|
||||||
pub errors: HashMap<String, String>,
|
pub errors: HashMap<String, String>,
|
||||||
|
pub custom_errors: HashMap<String, String>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -37,6 +38,7 @@ impl ActixAdminModel {
|
|||||||
primary_key: None,
|
primary_key: None,
|
||||||
values: HashMap::new(),
|
values: HashMap::new(),
|
||||||
errors: HashMap::new(),
|
errors: HashMap::new(),
|
||||||
|
custom_errors: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +65,7 @@ impl ActixAdminModel {
|
|||||||
primary_key: None,
|
primary_key: None,
|
||||||
values: hashmap,
|
values: hashmap,
|
||||||
errors: HashMap::new(),
|
errors: HashMap::new(),
|
||||||
|
custom_errors: HashMap::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,8 @@ async fn create_or_edit_post<T: ActixAdminAppDataTrait, E: ActixAdminViewModelTr
|
|||||||
}
|
}
|
||||||
|
|
||||||
let db = &data.get_db();
|
let db = &data.get_db();
|
||||||
let model = ActixAdminModel::create_from_payload(payload).await.unwrap();
|
let mut model = ActixAdminModel::create_from_payload(payload).await.unwrap();
|
||||||
|
E::validate_entity(&mut model);
|
||||||
|
|
||||||
if model.has_errors() {
|
if model.has_errors() {
|
||||||
let mut ctx = Context::new();
|
let mut ctx = Context::new();
|
||||||
|
@ -21,6 +21,7 @@ pub trait ActixAdminViewModelTrait {
|
|||||||
async fn get_entity(db: &DatabaseConnection, id: i32) -> ActixAdminModel;
|
async fn get_entity(db: &DatabaseConnection, id: i32) -> ActixAdminModel;
|
||||||
async fn edit_entity(db: &DatabaseConnection, id: i32, model: ActixAdminModel) -> ActixAdminModel;
|
async fn edit_entity(db: &DatabaseConnection, id: i32, model: ActixAdminModel) -> ActixAdminModel;
|
||||||
async fn get_select_lists(db: &DatabaseConnection) -> HashMap<String, Vec<(String, String)>>;
|
async fn get_select_lists(db: &DatabaseConnection) -> HashMap<String, Vec<(String, String)>>;
|
||||||
|
fn validate_entity(model: &mut ActixAdminModel);
|
||||||
|
|
||||||
fn get_entity_name() -> String;
|
fn get_entity_name() -> String;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user