derive html input type based on field type
This commit is contained in:
parent
80df5a2719
commit
a0fe692046
@ -2,29 +2,20 @@ use proc_macro;
|
|||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
mod struct_fields;
|
mod struct_fields;
|
||||||
use struct_fields::{
|
use struct_fields::{
|
||||||
get_fields_for_tokenstream,
|
get_actix_admin_fields, get_actix_admin_fields_html_input,
|
||||||
get_fields_for_edit_model,
|
get_actix_admin_fields_is_option_list, get_actix_admin_fields_searchable,
|
||||||
get_fields_for_from_model,
|
get_actix_admin_fields_select_list, get_actix_admin_fields_type_path_string,
|
||||||
get_actix_admin_fields_html_input,
|
get_field_for_primary_key, get_fields_for_create_model, get_fields_for_edit_model,
|
||||||
get_fields_for_create_model,
|
get_fields_for_from_model, get_fields_for_tokenstream, get_fields_for_validate_model,
|
||||||
get_actix_admin_fields,
|
|
||||||
get_field_for_primary_key,
|
|
||||||
get_primary_key_field_name,
|
get_primary_key_field_name,
|
||||||
get_actix_admin_fields_select_list,
|
|
||||||
get_actix_admin_fields_is_option_list,
|
|
||||||
get_fields_for_validate_model,
|
|
||||||
get_actix_admin_fields_searchable
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mod selectlist_fields;
|
mod selectlist_fields;
|
||||||
use selectlist_fields::{
|
use selectlist_fields::{get_select_list, get_select_lists};
|
||||||
get_select_list,
|
|
||||||
get_select_lists
|
|
||||||
};
|
|
||||||
|
|
||||||
mod model_fields;
|
|
||||||
mod attributes;
|
mod attributes;
|
||||||
|
mod model_fields;
|
||||||
|
|
||||||
#[proc_macro_derive(DeriveActixAdminSelectList, attributes(actix_admin))]
|
#[proc_macro_derive(DeriveActixAdminSelectList, attributes(actix_admin))]
|
||||||
pub fn derive_actix_admin_select_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn derive_actix_admin_select_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
@ -46,6 +37,7 @@ pub fn derive_crud_fns(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
|||||||
let field_for_primary_key = get_field_for_primary_key(&fields);
|
let field_for_primary_key = get_field_for_primary_key(&fields);
|
||||||
let fields_for_validate_model = get_fields_for_validate_model(&fields);
|
let fields_for_validate_model = get_fields_for_validate_model(&fields);
|
||||||
let fields_searchable = get_actix_admin_fields_searchable(&fields);
|
let fields_searchable = get_actix_admin_fields_searchable(&fields);
|
||||||
|
let fields_type_path = get_actix_admin_fields_type_path_string(&fields);
|
||||||
|
|
||||||
let select_lists = get_select_lists(&fields);
|
let select_lists = get_select_lists(&fields);
|
||||||
|
|
||||||
@ -120,7 +112,6 @@ pub fn derive_crud_fns(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
|||||||
// TODO: separate primary key from other keys
|
// TODO: separate primary key from other keys
|
||||||
let entity = Entity::find_by_id(id).one(db).await.unwrap().unwrap();
|
let entity = Entity::find_by_id(id).one(db).await.unwrap().unwrap();
|
||||||
let model = ActixAdminModel::from(entity);
|
let model = ActixAdminModel::from(entity);
|
||||||
|
|
||||||
model
|
model
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,10 +125,8 @@ pub fn derive_crud_fns(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
|||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,12 +176,9 @@ pub fn derive_crud_fns(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
|||||||
(num_pages, model_entities)
|
(num_pages, model_entities)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn validate_model(model: &ActixAdminModel) -> HashMap<String, String> {
|
fn validate_model(model: &ActixAdminModel) -> HashMap<String, String> {
|
||||||
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();
|
//let mut custom_errors = Entity.validate();
|
||||||
//errors.append(&mut custom_errors);
|
//errors.append(&mut custom_errors);
|
||||||
errors
|
errors
|
||||||
@ -205,7 +191,7 @@ pub fn derive_crud_fns(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
|||||||
#(#field_names),*
|
#(#field_names),*
|
||||||
).split(",")
|
).split(",")
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let html_input_types = stringify!(
|
let html_input_types = stringify!(
|
||||||
#(#field_html_input_type),*
|
#(#field_html_input_type),*
|
||||||
).split(",")
|
).split(",")
|
||||||
@ -220,14 +206,19 @@ pub fn derive_crud_fns(input: proc_macro::TokenStream) -> proc_macro::TokenStrea
|
|||||||
#(#is_option_list),*
|
#(#is_option_list),*
|
||||||
];
|
];
|
||||||
|
|
||||||
for (field_name, html_input_type, select_list, is_option_list) in izip!(&field_names, &html_input_types, &field_select_lists, is_option_lists) {
|
let fields_type_paths = [
|
||||||
vec.push(ActixAdminViewModelField {
|
#(#fields_type_path),*
|
||||||
field_name: field_name.replace('"', "").replace(' ', "").to_string(),
|
];
|
||||||
html_input_type: html_input_type.replace('"', "").replace(' ', "").to_string(),
|
|
||||||
select_list: select_list.replace('"', "").replace(' ', "").to_string(),
|
for (field_name, html_input_type, select_list, is_option_list, fields_type_path) in izip!(&field_names, &html_input_types, &field_select_lists, is_option_lists, fields_type_paths) {
|
||||||
is_option: is_option_list
|
vec.push(ActixAdminViewModelField {
|
||||||
});
|
field_name: field_name.replace('"', "").replace(' ', "").to_string(),
|
||||||
}
|
html_input_type: html_input_type.replace('"', "").replace(' ', "").to_string(),
|
||||||
|
select_list: select_list.replace('"', "").replace(' ', "").to_string(),
|
||||||
|
is_option: is_option_list,
|
||||||
|
field_type: ActixAdminViewModelFieldType::from(fields_type_path)
|
||||||
|
});
|
||||||
|
}
|
||||||
vec
|
vec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,4 +28,21 @@ impl ModelField {
|
|||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_type_path_string(&self) -> String {
|
||||||
|
let type_path_string: String;
|
||||||
|
if self.is_option() {
|
||||||
|
match &self.inner_type.clone().unwrap() {
|
||||||
|
Type::Path(type_path) => type_path_string = type_path.clone().into_token_stream().to_string(),
|
||||||
|
_ => panic!("not a type path")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match &self.ty {
|
||||||
|
Type::Path(type_path) => type_path_string = type_path.clone().into_token_stream().to_string(),
|
||||||
|
_ => panic!("not a type path")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type_path_string
|
||||||
|
}
|
||||||
}
|
}
|
@ -43,9 +43,9 @@ pub fn filter_fields(fields: &Fields) -> Vec<ModelField> {
|
|||||||
(LitStr::from(attr_field)).value()
|
(LitStr::from(attr_field)).value()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
let html_input_type = actix_admin_attr.map_or("text".to_string(), |attr| {
|
let html_input_type = actix_admin_attr.map_or("".to_string(), |attr| {
|
||||||
attr.html_input_type
|
attr.html_input_type
|
||||||
.map_or("text".to_string(), |attr_field| {
|
.map_or("".to_string(), |attr_field| {
|
||||||
(LitStr::from(attr_field)).value()
|
(LitStr::from(attr_field)).value()
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
@ -140,6 +140,20 @@ pub fn get_actix_admin_fields_is_option_list(fields: &Vec<ModelField>) -> Vec<To
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_actix_admin_fields_type_path_string(fields: &Vec<ModelField>) -> Vec<TokenStream> {
|
||||||
|
fields
|
||||||
|
.iter()
|
||||||
|
.filter(|model_field| !model_field.primary_key)
|
||||||
|
.map(|model_field| {
|
||||||
|
let type_path_string = model_field.get_type_path_string();
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#type_path_string
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_actix_admin_fields_html_input(fields: &Vec<ModelField>) -> Vec<TokenStream> {
|
pub fn get_actix_admin_fields_html_input(fields: &Vec<ModelField>) -> Vec<TokenStream> {
|
||||||
fields
|
fields
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use sea_orm::DatabaseConnection;
|
use sea_orm::DatabaseConnection;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use tera::{Tera};
|
use tera::{Tera, Result, Value, to_value, try_get_value };
|
||||||
|
use std::{ hash::BuildHasher};
|
||||||
|
|
||||||
pub mod view_model;
|
pub mod view_model;
|
||||||
pub mod model;
|
pub mod model;
|
||||||
@ -11,7 +12,7 @@ pub mod builder;
|
|||||||
pub mod prelude {
|
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};
|
pub use crate::view_model::{ ActixAdminViewModel, ActixAdminViewModelTrait, ActixAdminViewModelField, ActixAdminViewModelFieldType };
|
||||||
pub use actix_admin_macros::{ DeriveActixAdminModel, DeriveActixAdminSelectList };
|
pub use actix_admin_macros::{ DeriveActixAdminModel, DeriveActixAdminSelectList };
|
||||||
pub use crate::{ ActixAdminAppDataTrait, ActixAdmin };
|
pub use crate::{ ActixAdminAppDataTrait, ActixAdmin };
|
||||||
pub use crate::{ hashmap, ActixAdminSelectListTrait };
|
pub use crate::{ hashmap, ActixAdminSelectListTrait };
|
||||||
@ -30,10 +31,43 @@ macro_rules! hashmap {
|
|||||||
|
|
||||||
// globals
|
// globals
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref TERA: Tera =
|
static ref TERA: Tera = {
|
||||||
Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap();
|
let mut tera = Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap();
|
||||||
|
tera.register_filter("get_html_input_type", get_html_input_type);
|
||||||
|
tera.register_filter("get_html_input_class", get_html_input_class);
|
||||||
|
tera
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_html_input_class<S: BuildHasher>(value: &tera::Value, _: &HashMap<String, tera::Value, S>) -> Result<tera::Value> {
|
||||||
|
let field = try_get_value!("get_html_input_class", "value", ActixAdminViewModelField, value);
|
||||||
|
let html_input_type = match field.field_type {
|
||||||
|
ActixAdminViewModelFieldType::Checkbox => "checkbox",
|
||||||
|
_ => "input"
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(to_value(html_input_type).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_html_input_type<S: BuildHasher>(value: &tera::Value, _: &HashMap<String, tera::Value, S>) -> Result<tera::Value> {
|
||||||
|
let field = try_get_value!("get_html_input_type", "value", ActixAdminViewModelField, value);
|
||||||
|
|
||||||
|
// TODO: convert to option
|
||||||
|
if field.html_input_type != "" {
|
||||||
|
return Ok(to_value(field.html_input_type).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
let html_input_type = match field.field_type {
|
||||||
|
ActixAdminViewModelFieldType::Text => "text",
|
||||||
|
ActixAdminViewModelFieldType::DateTime => "datetime-local",
|
||||||
|
ActixAdminViewModelFieldType::Checkbox => "checkbox",
|
||||||
|
_ => "text"
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(to_value(html_input_type).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// AppDataTrait
|
// AppDataTrait
|
||||||
pub trait ActixAdminAppDataTrait {
|
pub trait ActixAdminAppDataTrait {
|
||||||
fn get_db(&self) -> &DatabaseConnection;
|
fn get_db(&self) -> &DatabaseConnection;
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use sea_orm::DatabaseConnection;
|
use sea_orm::DatabaseConnection;
|
||||||
use serde::{Serialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use crate::ActixAdminModel;
|
use crate::ActixAdminModel;
|
||||||
|
use std::convert::From;
|
||||||
|
|
||||||
#[async_trait(?Send)]
|
#[async_trait(?Send)]
|
||||||
pub trait ActixAdminViewModelTrait {
|
pub trait ActixAdminViewModelTrait {
|
||||||
@ -34,10 +35,37 @@ pub struct ActixAdminViewModel {
|
|||||||
pub fields: Vec<ActixAdminViewModelField>,
|
pub fields: Vec<ActixAdminViewModelField>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub enum ActixAdminViewModelFieldType {
|
||||||
|
Number,
|
||||||
|
Text,
|
||||||
|
TextArea,
|
||||||
|
Checkbox,
|
||||||
|
Date,
|
||||||
|
Time,
|
||||||
|
DateTime,
|
||||||
|
SelectList
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for ActixAdminViewModelFieldType {
|
||||||
|
fn from(input: &str) -> ActixAdminViewModelFieldType {
|
||||||
|
match input {
|
||||||
|
"i32" => ActixAdminViewModelFieldType::Number,
|
||||||
|
"i64" => ActixAdminViewModelFieldType::Number,
|
||||||
|
"usize" => ActixAdminViewModelFieldType::Number,
|
||||||
|
"String" => ActixAdminViewModelFieldType::Text,
|
||||||
|
"bool" => ActixAdminViewModelFieldType::Checkbox,
|
||||||
|
"DateTimeWithTimeZone" => ActixAdminViewModelFieldType::DateTime,
|
||||||
|
_ => ActixAdminViewModelFieldType::Text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct ActixAdminViewModelField {
|
pub struct ActixAdminViewModelField {
|
||||||
pub field_name: String,
|
pub field_name: String,
|
||||||
pub html_input_type: String,
|
pub html_input_type: String,
|
||||||
pub select_list: String,
|
pub select_list: String,
|
||||||
pub is_option: bool
|
pub is_option: bool,
|
||||||
|
pub field_type: ActixAdminViewModelFieldType
|
||||||
}
|
}
|
@ -13,27 +13,50 @@
|
|||||||
<title>Actix Admin</title>
|
<title>Actix Admin</title>
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css" integrity="sha512-1sCRPdkRXhBV2PBLUdRb4tMg1w2YPf37qatUFeS7zlBy7jJI8Lf4VHwWfZZfpXtYSLy85pkm9GaYVYMfw5BC1A==" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.2/css/all.min.css"
|
||||||
|
integrity="sha512-1sCRPdkRXhBV2PBLUdRb4tMg1w2YPf37qatUFeS7zlBy7jJI8Lf4VHwWfZZfpXtYSLy85pkm9GaYVYMfw5BC1A=="
|
||||||
|
crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||||
<script src="https://unpkg.com/htmx.org@1.7.0"></script>
|
<script src="https://unpkg.com/htmx.org@1.7.0"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function checkAll(bx) {
|
function checkAll(bx) {
|
||||||
var cbs = document.getElementsByTagName('input');
|
var cbs = document.getElementsByTagName('input');
|
||||||
for(var i=0; i < cbs.length; i++) {
|
for (var i = 0; i < cbs.length; i++) {
|
||||||
if(cbs[i].type == 'checkbox') {
|
if (cbs[i].type == 'checkbox') {
|
||||||
cbs[i].checked = bx.checked;
|
cbs[i].checked = bx.checked;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
// Get all "navbar-burger" elements
|
||||||
|
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
|
||||||
|
|
||||||
|
// Add a click event on each of them
|
||||||
|
$navbarBurgers.forEach(el => {
|
||||||
|
el.addEventListener('click', () => {
|
||||||
|
|
||||||
|
// Get the target from the "data-target" attribute
|
||||||
|
const target = el.dataset.target;
|
||||||
|
const $target = document.getElementById(target);
|
||||||
|
|
||||||
|
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
|
||||||
|
el.classList.toggle('is-active');
|
||||||
|
$target.classList.toggle('is-active');
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
{% include "header.html" %}
|
{% include "header.html" %}
|
||||||
<div class="container is-fluid">
|
<div class="container is-fluid">
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<form method="post">
|
<form method="post">
|
||||||
{% for model_field in view_model.fields -%}
|
{% for model_field in view_model.fields -%}
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="{{ model_field.field_name }}">
|
<label class="{{ model_field | get_html_input_type }}" for="{{ model_field.field_name }}">
|
||||||
{{ model_field.field_name | split(pat="_") | join(sep=" ") | title }}
|
{{ model_field.field_name | split(pat="_") | join(sep=" ") | title }}
|
||||||
</label>
|
</label>
|
||||||
{% if model_field.select_list != "" %}
|
{% if model_field.select_list != "" %}
|
||||||
@ -26,8 +26,8 @@
|
|||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<input class="input {% if model.errors | get(key=model_field.field_name,default="" ) !="" %}is-danger{% endif %}"
|
<input class="{{ model_field | get_html_input_class }} {% if model.errors | get(key=model_field.field_name,default="" ) !="" %}is-danger{% endif %}"
|
||||||
type="{{ model_field.html_input_type }}"
|
type="{{ model_field | get_html_input_type }}"
|
||||||
value="{{ model.values | get(key=model_field.field_name, default="") | split(pat=" _") | join(sep=" " ) | title }}"
|
value="{{ model.values | get(key=model_field.field_name, default="") | split(pat=" _") | join(sep=" " ) | title }}"
|
||||||
name="{{ model_field.field_name }}"
|
name="{{ model_field.field_name }}"
|
||||||
placeholder="{{ model_field.field_name }}"
|
placeholder="{{ model_field.field_name }}"
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path
|
|
||||||
d="M10.72,19.9a8,8,0,0,1-6.5-9.79A7.77,7.77,0,0,1,10.4,4.16a8,8,0,0,1,9.49,6.52A1.54,1.54,0,0,0,21.38,12h.13a1.37,1.37,0,0,0,1.38-1.54,11,11,0,1,0-12.7,12.39A1.54,1.54,0,0,0,12,21.34h0A1.47,1.47,0,0,0,10.72,19.9Z">
|
|
||||||
<animateTransform attributeName="transform" type="rotate" dur="0.75s" values="0 12 12;360 12 12"
|
|
||||||
repeatCount="indefinite" />
|
|
||||||
</path>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 480 B |
BIN
database.db-wal
BIN
database.db-wal
Binary file not shown.
@ -11,10 +11,11 @@ pub struct Model {
|
|||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub comment: String,
|
pub comment: String,
|
||||||
#[sea_orm(column_type = "Text")]
|
#[sea_orm(column_type = "Text")]
|
||||||
|
#[actix_admin(html_input_type = "email")]
|
||||||
pub user: String,
|
pub user: String,
|
||||||
#[sea_orm(column_type = "DateTime")]
|
#[sea_orm(column_type = "DateTime")]
|
||||||
#[actix_admin(html_input_type = "datetime-local")]
|
pub insert_date: DateTimeWithTimeZone,
|
||||||
pub insert_date: DateTimeWithTimeZone
|
pub is_visible: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
@ -44,6 +44,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::Comment).string().not_null())
|
||||||
.col(ColumnDef::new(comment::Column::User).string().not_null())
|
.col(ColumnDef::new(comment::Column::User).string().not_null())
|
||||||
.col(ColumnDef::new(comment::Column::InsertDate).date_time().not_null())
|
.col(ColumnDef::new(comment::Column::InsertDate).date_time().not_null())
|
||||||
|
.col(ColumnDef::new(comment::Column::IsVisible).boolean().not_null())
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
create_table(db, &stmt).await
|
create_table(db, &stmt).await
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
use sea_orm::entity::prelude::*;
|
use sea_orm::entity::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use actix_admin::prelude::*;
|
use actix_admin::prelude::*;
|
||||||
use std::str::FromStr;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize, DeriveActixAdminModel)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Deserialize, Serialize, DeriveActixAdminModel)]
|
||||||
#[sea_orm(table_name = "post")]
|
#[sea_orm(table_name = "post")]
|
||||||
|
Loading…
Reference in New Issue
Block a user