add option for html input type on column
This commit is contained in:
parent
96b069042e
commit
2b653510b2
@ -6,10 +6,12 @@ pub mod derive_attr {
|
||||
Eq,
|
||||
PartialEq,
|
||||
FromAttributes,
|
||||
Default
|
||||
Default,
|
||||
Clone
|
||||
)]
|
||||
pub struct ActixAdmin {
|
||||
pub primary_key: Option<()>
|
||||
pub primary_key: Option<()>,
|
||||
pub html_input_type: Option<syn::LitStr>
|
||||
//pub inner_type: Option<syn::Type>,
|
||||
|
||||
// Anything that implements `syn::parse::Parse` is supported.
|
||||
|
@ -2,17 +2,17 @@ use proc_macro;
|
||||
use quote::quote;
|
||||
|
||||
mod struct_fields;
|
||||
use struct_fields::{ get_fields_for_tokenstream, get_fields_for_edit_model, get_fields_for_from_model, get_fields_for_create_model, get_field_names, get_field_for_primary_key, get_primary_key_field_name};
|
||||
use struct_fields::{ get_fields_for_tokenstream, get_fields_for_edit_model, get_fields_for_from_model, get_actix_admin_fields_html_input, get_fields_for_create_model, get_actix_admin_fields, get_field_for_primary_key, get_primary_key_field_name};
|
||||
|
||||
mod model_fields;
|
||||
|
||||
mod attributes;
|
||||
|
||||
#[proc_macro_derive(DeriveActixAdminModel, attributes(actix_admin))]
|
||||
pub fn derive_crud_fns(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let fields = get_fields_for_tokenstream(input);
|
||||
|
||||
let names_const_fields_str = get_field_names(&fields);
|
||||
let field_names = get_actix_admin_fields(&fields);
|
||||
let field_html_input_type = get_actix_admin_fields_html_input(&fields);
|
||||
let name_primary_field_str = get_primary_key_field_name(&fields);
|
||||
let fields_for_create_model = get_fields_for_create_model(&fields);
|
||||
let fields_for_edit_model = get_fields_for_edit_model(&fields);
|
||||
@ -21,6 +21,7 @@ pub fn derive_crud_fns(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
||||
|
||||
let expanded = quote! {
|
||||
use std::convert::From;
|
||||
use std::iter::zip;
|
||||
use async_trait::async_trait;
|
||||
use actix_web::{web, HttpResponse, HttpRequest, Error};
|
||||
use actix_admin::prelude::*;
|
||||
@ -135,21 +136,32 @@ pub fn derive_crud_fns(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
||||
(num_pages, model_entities)
|
||||
}
|
||||
|
||||
fn get_fields() -> Vec<(String, ActixAdminField)> {
|
||||
fn get_fields() -> Vec<(String, String)> {
|
||||
let mut vec = Vec::new();
|
||||
let field_names = stringify!(
|
||||
#(#names_const_fields_str),*
|
||||
#(#field_names),*
|
||||
).split(",")
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
.for_each( |field_name|
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let html_input_types = stringify!(
|
||||
#(#field_html_input_type),*
|
||||
).split(",")
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut names_and_input_type = zip(field_names, html_input_types);
|
||||
|
||||
names_and_input_type
|
||||
.for_each( |field_name_and_type_tuple|
|
||||
vec.push((
|
||||
field_name
|
||||
field_name_and_type_tuple.0
|
||||
.replace('"', "")
|
||||
.replace(' ', "")
|
||||
.to_string(),
|
||||
// TODO: match correct ActixAdminField Value
|
||||
ActixAdminField::Text
|
||||
field_name_and_type_tuple.1
|
||||
.replace('"', "")
|
||||
.replace(' ', "")
|
||||
.to_string()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -8,7 +8,8 @@ pub struct ModelField {
|
||||
pub ty: Type,
|
||||
// struct field is option<>
|
||||
pub inner_type: Option<Type>,
|
||||
pub primary_key: bool
|
||||
pub primary_key: bool,
|
||||
pub html_input_type: String
|
||||
}
|
||||
|
||||
impl ModelField {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use proc_macro2::{Span, Ident, TokenStream};
|
||||
use syn::{
|
||||
Fields, DeriveInput
|
||||
Fields, DeriveInput, LitStr
|
||||
};
|
||||
use quote::quote;
|
||||
use crate::attributes::derive_attr;
|
||||
@ -30,14 +30,18 @@ pub fn filter_fields(fields: &Fields) -> Vec<ModelField> {
|
||||
let field_ident = field.ident.as_ref().unwrap().clone();
|
||||
let inner_type = extract_type_from_option(&field.ty);
|
||||
let field_ty = field.ty.to_owned();
|
||||
let is_primary_key = actix_admin_attr.map_or(false, |attr| attr.primary_key.is_some());
|
||||
let is_primary_key = actix_admin_attr.clone().map_or(false, |attr| attr.primary_key.is_some());
|
||||
let html_input_type = actix_admin_attr.map_or("text".to_string(), |attr| attr.html_input_type.map_or("text".to_string(),
|
||||
|attr_field| (LitStr::from(attr_field)).value()
|
||||
));
|
||||
|
||||
let model_field = ModelField {
|
||||
visibility: field_vis,
|
||||
ident: field_ident,
|
||||
ty: field_ty,
|
||||
inner_type: inner_type,
|
||||
primary_key: is_primary_key
|
||||
primary_key: is_primary_key,
|
||||
html_input_type: html_input_type
|
||||
};
|
||||
|
||||
Some(model_field)
|
||||
@ -92,12 +96,13 @@ fn extract_type_from_option(ty: &syn::Type) -> Option<syn::Type> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_field_names(fields: &Vec<ModelField>) -> Vec<TokenStream> {
|
||||
pub fn get_actix_admin_fields(fields: &Vec<ModelField>) -> Vec<TokenStream> {
|
||||
fields
|
||||
.iter()
|
||||
.filter(|model_field| !model_field.primary_key)
|
||||
.map(|model_field| {
|
||||
let ident_name = model_field.ident.to_string();
|
||||
|
||||
quote! {
|
||||
#ident_name
|
||||
}
|
||||
@ -105,6 +110,20 @@ pub fn get_field_names(fields: &Vec<ModelField>) -> Vec<TokenStream> {
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
pub fn get_actix_admin_fields_html_input(fields: &Vec<ModelField>) -> Vec<TokenStream> {
|
||||
fields
|
||||
.iter()
|
||||
.filter(|model_field| !model_field.primary_key)
|
||||
.map(|model_field| {
|
||||
let html_input_type = model_field.html_input_type.to_string();
|
||||
|
||||
quote! {
|
||||
#html_input_type
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
pub fn get_field_for_primary_key(fields: &Vec<ModelField>) -> TokenStream {
|
||||
let primary_key_model_field = fields
|
||||
.iter()
|
||||
|
@ -1,8 +1,8 @@
|
||||
use lazy_static::lazy_static;
|
||||
use sea_orm::DatabaseConnection;
|
||||
use serde::{Serialize};
|
||||
use std::collections::HashMap;
|
||||
use tera::{Tera};
|
||||
use serde::{Serialize};
|
||||
|
||||
pub mod view_model;
|
||||
pub mod model;
|
||||
@ -16,7 +16,6 @@ pub mod prelude {
|
||||
pub use actix_admin_macros::{ DeriveActixAdminModel };
|
||||
pub use crate::{ ActixAdminAppDataTrait, ActixAdmin};
|
||||
pub use crate::{ hashmap };
|
||||
pub use crate::{ ActixAdminField };
|
||||
}
|
||||
|
||||
use crate::prelude::*;
|
||||
@ -36,12 +35,6 @@ lazy_static! {
|
||||
Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap();
|
||||
}
|
||||
|
||||
// Fields
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub enum ActixAdminField {
|
||||
Text,
|
||||
}
|
||||
|
||||
// AppDataTrait
|
||||
pub trait ActixAdminAppDataTrait {
|
||||
fn get_db(&self) -> &DatabaseConnection;
|
||||
|
@ -3,8 +3,6 @@ use sea_orm::DatabaseConnection;
|
||||
use serde::{Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::ActixAdminField;
|
||||
|
||||
#[async_trait]
|
||||
pub trait ActixAdminModelTrait {
|
||||
async fn list_model(
|
||||
@ -12,7 +10,7 @@ pub trait ActixAdminModelTrait {
|
||||
page: usize,
|
||||
posts_per_page: usize,
|
||||
) -> (usize, Vec<ActixAdminModel>);
|
||||
fn get_fields() -> Vec<(String, ActixAdminField)>;
|
||||
fn get_fields() -> Vec<(String, String)>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
|
@ -3,7 +3,6 @@ use sea_orm::DatabaseConnection;
|
||||
use serde::{Serialize};
|
||||
|
||||
use crate::ActixAdminModel;
|
||||
use crate::ActixAdminField;
|
||||
|
||||
#[async_trait(?Send)]
|
||||
pub trait ActixAdminViewModelTrait {
|
||||
@ -26,5 +25,5 @@ pub trait ActixAdminViewModelTrait {
|
||||
pub struct ActixAdminViewModel {
|
||||
pub entity_name: String,
|
||||
pub primary_key: String,
|
||||
pub fields: Vec<(String, ActixAdminField)>,
|
||||
pub fields: Vec<(String, String)>,
|
||||
}
|
@ -4,9 +4,10 @@
|
||||
<form method="post">
|
||||
<div class="grid">
|
||||
{% for model_field in view_model.fields -%}
|
||||
<input type="text" name="{{ model_field[0] }}" placeholder="{{ model_field[0] }}" aria-label="{{ model_field[0] }}"><!-- required="" -->
|
||||
<input type="{{ model_field[1] }}" name="{{ model_field[0] }}" placeholder="{{ model_field[0] }}" aria-label="{{ model_field[0] }}"><!-- required="" -->
|
||||
{%- endfor %}
|
||||
<button type="submit">Save</button>
|
||||
<button onclick="history.back()">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock content %}
|
@ -7,6 +7,7 @@
|
||||
<input type="text" value="{{ value }}" name="{{ key }}" placeholder="{{ key }}" aria-label="{{ key }}"><!-- required="" -->
|
||||
{%- endfor %}
|
||||
<button type="submit">Save</button>
|
||||
<button onclick="history.back()">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock content %}
|
BIN
database.db-wal
BIN
database.db-wal
Binary file not shown.
@ -12,6 +12,9 @@ pub struct Model {
|
||||
pub comment: String,
|
||||
#[sea_orm(column_type = "Text")]
|
||||
pub user: String,
|
||||
#[sea_orm(column_type = "DateTime")]
|
||||
#[actix_admin(html_input_type = "datetime-local")]
|
||||
pub insert_date: DateTimeWithTimeZone
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
|
@ -43,6 +43,7 @@ pub async fn create_post_table(db: &DbConn) -> Result<ExecResult, DbErr> {
|
||||
)
|
||||
.col(ColumnDef::new(comment::Column::Comment).string().not_null())
|
||||
.col(ColumnDef::new(comment::Column::User).string().not_null())
|
||||
.col(ColumnDef::new(comment::Column::InsertDate).date_time().not_null())
|
||||
.to_owned();
|
||||
|
||||
create_table(db, &stmt).await
|
||||
|
Loading…
Reference in New Issue
Block a user